fritzing-app-0.9.2b/000077500000000000000000000000001250202676700143055ustar00rootroot00000000000000fritzing-app-0.9.2b/.gitignore000066400000000000000000000016061250202676700163000ustar00rootroot00000000000000.qmake.stash # QtCreator folders and files # ##################### phoenix.pro.user /phoenix-build-* *.user *.user* # FritzingTools folder ##################### #/tools # visual studio folders and files # ##################### *.sdf *.opensdf *.sln *.vcxproj *.vcxproj.* Makefile* # no longer keep boost library in the source # /src/lib/boost* # Compiled source # ################### *.pyc *.com *.class *.dll *.exe *.o *.so *.suo *.pdb # Temporary files # ############### *.py~ *.xml~ # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods #*.7z #*.dmg #*.gz #*.iso #*.jar #*.rar #*.tar #*.zip # Logs and databases # ###################### #*.log #*.sql #*.sqlite # OS generated files # ###################### .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db .bash_history saved_state fritzing-app-0.9.2b/.gitmodules000066400000000000000000000001301250202676700164540ustar00rootroot00000000000000[submodule "parts"] path = parts url = https://github.com/fritzing/fritzing-parts.git fritzing-app-0.9.2b/Fritzing.1000066400000000000000000000012561250202676700161670ustar00rootroot00000000000000.TH FRITZING 1 "October 03, 2010" "Fritzing" .SH NAME fritzing \- from prototype to product .SH SYNOPSIS .B fritzing .SH DESCRIPTION .PP Fritzing is an open-source initiative to support designers, artists, researchers and hobbyists to work creatively with interactive electronics. We are creating a software and website in the spirit of Processing and Arduino, developing a tool that allows users to document their prototypes, share them with others, teach electronics in a classroom, and to create a pcb layout for professional manufacturing. .SH AUTHOR This manual page was written by Enrique Hernández Bello , for the Debian project (and may be used by others). fritzing-app-0.9.2b/Fritzing.sh000066400000000000000000000005261250202676700164400ustar00rootroot00000000000000#!/bin/sh appname="Fritzing" # dirname=`dirname "${0}"` # new dirname procedure from Volker Kuhlmann # use -f to make the readlink path absolute dirname="$(dirname -- "$(readlink -f -- "${0}")" )" if [ "$dirname" = "." ]; then dirname="$PWD/$dirname" fi LD_LIBRARY_PATH="${dirname}/lib" export LD_LIBRARY_PATH "$dirname/lib/$appname" $* fritzing-app-0.9.2b/FritzingInfo.plist000066400000000000000000000074561250202676700200060ustar00rootroot00000000000000 NSPrincipalClass NSApplication CFBundleExecutable Fritzing CFBundleGetInfoString Fritzing 0.9.2 CFBundleShortVersionString 0.9.2 CFBundleVersion bda4e CFBundleIconFile fritzing_icon.icns CFBundleIdentifier org.fritzing.Fritzing CFBundlePackageType APPL CFBundleSignature FRtz CFBundleDocumentTypes CFBundleTypeExtensions fz CFBundleTypeName Fritzing sketch CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions fzz CFBundleTypeName Fritzing shareable sketch CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions fzb CFBundleTypeName Fritzing bin CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions fzp CFBundleTypeName Fritzing part CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions fzm CFBundleTypeName Fritzing module CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions fzpz CFBundleTypeName Fritzing bundled part CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML fritzing-app-0.9.2b/LICENSE.CC-BY-SA000066400000000000000000000503421250202676700164130ustar00rootroot00000000000000License Creative Commons Attribution-ShareAlike 3.0 Unported http://creativecommons.org/licenses/by-sa/3.0/legalcode THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 1. Definitions "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License. "Creative Commons Compatible License" means a license that is listed at http://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; to Distribute and Publicly Perform the Work including as incorporated in Collections; and, to Distribute and Publicly Perform Adaptations. For the avoidance of doubt: Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested. You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. 5. Representations, Warranties and Disclaimer UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. Termination This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 8. Miscellaneous Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. Creative Commons Notice Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of the License. Creative Commons may be contacted at http://creativecommons.org/.fritzing-app-0.9.2b/LICENSE.GPL2000066400000000000000000000452721250202676700160270ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE The Qt GUI Toolkit is Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). Contact: Qt Software Information (qt-info@nokia.com) You may use, distribute and copy the Qt GUI Toolkit under the terms of GNU General Public License version 2, which is displayed below. ------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin 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. 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 St, 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. ------------------------------------------------------------------------- In addition, as a special exception, Trolltech gives permission to link the code of its release of Qt with the OpenSSL project's "OpenSSL" library (or modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must comply with the GNU General Public License version 2 or the GNU General Public License version 3 in all respects for all of the code used other than the "OpenSSL" code. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version of this file. fritzing-app-0.9.2b/LICENSE.GPL3000066400000000000000000001067001250202676700160220ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE The Qt GUI Toolkit is Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). Contact: Qt Software Information (qt-info@nokia.com) You may use, distribute and copy the Qt GUI Toolkit under the terms of GNU General Public License version 3, which is displayed below. ------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ------------------------------------------------------------------------- In addition, as a special exception, Trolltech gives permission to link the code of its release of Qt with the OpenSSL project's "OpenSSL" library (or modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must comply with the GNU General Public License version 2 or the GNU General Public License version 3 in all respects for all of the code used other than the "OpenSSL" code. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version of this file. fritzing-app-0.9.2b/bins/000077500000000000000000000000001250202676700152405ustar00rootroot00000000000000fritzing-app-0.9.2b/bins/contribParts.fzb000066400000000000000000000053631250202676700204240ustar00rootroot00000000000000 Contributed Parts fritzing-app-0.9.2b/bins/core.fzb000066400000000000000000001233771250202676700167100ustar00rootroot00000000000000 Core Parts > > > fritzing-app-0.9.2b/bins/more/000077500000000000000000000000001250202676700162025ustar00rootroot00000000000000fritzing-app-0.9.2b/bins/more/ADIcon-mono.png000066400000000000000000000005611250202676700207550ustar00rootroot00000000000000PNG  IHDR;0tEXtSoftwareAdobe ImageReadyqe<IDATx @bm"(c#/%#t[ǠnvsXhJ{\5uVuž#OG;5\K)Ij !zQ 0=%I26MJ[TeIm-qo}s!rD Tv1|cctUaD:aQg CH)5da0e+֟z:` q IENDB`fritzing-app-0.9.2b/bins/more/ADIcon.png000066400000000000000000000006071250202676700200100ustar00rootroot00000000000000PNG  IHDR;0tEXtSoftwareAdobe ImageReadyqe<)IDATx1E`NjZ؂ZZ ѩi쁖ɛDTr89p<1¾AYNaUUv<4V(8:paex,Ӈu]f?b O$Iiz[u42GPl˲m[vmF@~}sa?OuKihuϧgK"=eYhz<38 gŻ_ 7Ms#aGQ8%@;o #CL+_uݿK[dIENDB`fritzing-app-0.9.2b/bins/more/AnalogDevices.fzb000066400000000000000000000053351250202676700214170ustar00rootroot00000000000000 Analog Devices fritzing-app-0.9.2b/bins/more/Atlas Scientific.fzb000066400000000000000000000036641250202676700220230ustar00rootroot00000000000000 Atlas Scientific fritzing-app-0.9.2b/bins/more/Seeed-Studio-Icon-mono.png000066400000000000000000000014461250202676700230430ustar00rootroot00000000000000PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<IDATxW1@ yA|(/o: r""}ޅ}/pHcZXH.YrȵǧiffL yk44;cePC#PќV/@6Ş@'Ҭ#x-g@gӨEL>ۈ=6jpe"wHbܣNȑhP]SLA>tLbB_+D>x@^&ae"sH)|eMfREȪuʀKTǵQ*P+&FF9V\ˇ)q8C w:hl)y/:q'!:fF,e "+DW9ކG#j A,aDnO5H@ymU< Ñj\,j>N%n2G.!E h7 'G9%)8E=̃{'.T]' Ac ^?ó=Zqa8|TlDגp"ϙ'D*Pὁ<ǓA~pB>a;J"E 87wOZ(;3ni2 {l}/Wz` MօIENDB`fritzing-app-0.9.2b/bins/more/Seeed-Studio-Icon.png000066400000000000000000000020461250202676700220720ustar00rootroot00000000000000PNG  IHDR tEXtSoftwareAdobe ImageReadyqe<IDATxڴVmHQn1PE$`?V_Ԑ2a)h, 4hHr fʠE ;z}wW/r99{oo0Jũ/bGZCbGplOzzeuQ>*qN  DPAo8 @Rpn,DjI \m8_rҏ0\cӁ%>}$"5 (,e یD\mDD+K )qjp"Fjz@ƼP H 誹I#8Iw shUXG]n !u=zac!0gxa%3? H@7UVJ0R}!?**ـ{A)|j )[`Լǜ.Zd QI"(P@t0]ޑA?1 jbG5* a4cJh #"A]-!u' dtHp=H8K#E=n8\˼#eb}=^=0HO с8݊]1=bKδ L5!?Q3rLNPlwkO]﴿^-Fkl06kt5(Ê= Ё&G.s1+5k3Jo ڛ)SUC\eh'!:J@R+ź(DLA|m11t_x1)׀H(2" ex{O1 mDՒk74a[Z,;u?DzӶgo_%T5=ƧZed4'ă{_N!%$ӦQ9F@h:5&Ї36U7ho!IENDB`fritzing-app-0.9.2b/bins/more/arduino.fzb000066400000000000000000000212271250202676700203520ustar00rootroot00000000000000 Arduino fritzing-app-0.9.2b/bins/more/atlas-scientific-mono.png000066400000000000000000000027771250202676700231150ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp ;sIDATxVZAA,L9PA,"guYF,mD/4*x D >ma};>7vٙv;Nr&~3Q2~$CC`! SAX.ײXT+2d>pdN N)J-Ą# 5E"šH?TjBVc8ncZ=q\j0Lj ̍z'%;G$=*& tF8F:`@ߧlE_'aDZ^yt:N' ?F#4,rb=+<j= 'IT*t] ձXhcf3M'˱nbrD&annМx6!J!ˁ8gO;W*QT^"\fFNP( 4B"$䢵3=/1HZlȨF/RB?)zX(&Z[B q|>ngM'XmRLw*^̎Fczl,S/+z,_h&k!I!@<ț=}3M[%7e;hIENDB`fritzing-app-0.9.2b/bins/more/atlas-scientific.png000066400000000000000000000427451250202676700221460ustar00rootroot00000000000000PNG  IHDRl} pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-8XiTXtXML:com.adobe.xmp Adobe Photoshop CC (Windows) 2013-09-18T18:10:30-04:00 2013-09-19T10:35-04:00 2013-09-19T10:35-04:00 image/png 3 sRGB IEC61966-2.1 xmp.iid:fa04d466-5cfc-ea48-b9ef-6108b3358b60 xmp.did:fa04d466-5cfc-ea48-b9ef-6108b3358b60 xmp.did:fa04d466-5cfc-ea48-b9ef-6108b3358b60 created xmp.iid:fa04d466-5cfc-ea48-b9ef-6108b3358b60 2013-09-18T18:10:30-04:00 Adobe Photoshop CC (Windows) 1 720000/10000 720000/10000 2 1 30 31 A cHRMz%u0`:o_FIDATx_HSq?wJ+2BZQA*A%꡿/CPA)^VR2W2M9ldݛ~;99B0d!b7iAf,6f H'/l@jzV*)`c)"8RA9XlZY #Yjbh"(3.=[qr͚Cd6$%%bt~Nb𹿝/1@NR&el]E>w?`hO1syw>z#Qȥ%tzpw4$J̓3Ajh`'D\֬ %L*I.p`<jÝYo.cp(&7d>7ٶؔ+Ă(&sٚFl ;mKzbB6);ɩZk{,nZG @yIH1"M ybUc?o!')ÉiuY5.L 6,{#/IENDB`fritzing-app-0.9.2b/bins/more/intel-mono.png000066400000000000000000000011271250202676700207720ustar00rootroot00000000000000PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<IDATxVq0 @7 NP30d6 $N@ atz*&$W;]bcK/O2A[ohX=^Vş@2grC>t,=3yFNP=gx (9HmMk AR R`l+1hx N~MiG S=rzi1{l.X]ͦsE;lI㋼cX*d/!XXք`sP@T2RNU%f_fXexu< TCf,!X46& AR%uLd_ Q)=\VJnz4CvZ+B,ڍ0?A Zyʜ.G vJ\} F%1vu+I8>itC";VfֈUؗ*zs Intel fritzing-app-0.9.2b/bins/more/intel.png000066400000000000000000000014071250202676700200250ustar00rootroot00000000000000PNG  IHDR tEXtSoftwareAdobe ImageReadyqe<IDATxOHTQ1J"Sk3B3\ -f00h)E-AD&&Ƣ 1~q},D $7( Q: >1?27Brʃİ .Xs%%ܚJ%$ I Lilypad fritzing-app-0.9.2b/bins/more/parallax.fzb000066400000000000000000000067541250202676700205250ustar00rootroot00000000000000 Parallax fritzing-app-0.9.2b/bins/more/picaxe.fzb000066400000000000000000000447451250202676700201740ustar00rootroot00000000000000 Picaxe fritzing-app-0.9.2b/bins/more/seeed_fritzing_parts.fzb000066400000000000000000000056131250202676700231240ustar00rootroot00000000000000 Seeed Studio fritzing-app-0.9.2b/bins/more/snootlab.fzb000066400000000000000000000031111250202676700205220ustar00rootroot00000000000000 Snootlab fritzing-app-0.9.2b/bins/more/sparkfun-analogic-mono.png000066400000000000000000000010071250202676700232600ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxVn0>5/hq{y$l=0(J40eFHG[(nZC.ضcKN7B9), cYv=de,w]P~PBdqy|j<0T:p17л걆}] À ->Qht= xqsn4}!M5Adt!WBEla0Ɛʅٺ;Yos޻ PJa^06bʢf3ia4ɻ. pzڧ\e GNŧI'eʶBRzZ1x\Gf?u\vM׀.Ǘd=/KNw˧#P;Isu *ŷ`*IENDB`fritzing-app-0.9.2b/bins/more/sparkfun-analogic.fzb000066400000000000000000000146471250202676700223250ustar00rootroot00000000000000 SparkFun-AnalogIC fritzing-app-0.9.2b/bins/more/sparkfun-analogic.png000066400000000000000000000011331250202676700223120ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxVNA  !` B&P hGE1m,B ܑ}, 7=;,,N3Lt4' S# ?v67ɻ(jR*˲3u"EuzZ-6Bl:OY\$ַ]WB!8Lmo)DEsb;|ˣF>ї܍]EC]2񳘍-mZ=V|]˒4܎ٱr ..`?0scۋE"- S1m]UA=z0* ꎚ3(ͿLhz@JnK4xMk’ !oM jt%9Vub6"dYPE6@&UUKѦXpszhy*1> ]x02nXat~4on3͂rrEIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-connectors-mono.png000066400000000000000000000013021250202676700236560ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<dIDATxW@cp a¡@*$$WSU.@D}Q @QС!tE8άx.i5|f'؆FqJK 0ʓl6- vu77 $zdُpXCpF*mKz=r|ҫ 9t:+/L&s"OӖ.JGu6TJ7g+4;\׮{?_ ܡvȶv.MgkA$_0ネ$;.ְݸO1r uh;xYsB"2~M4 s҄ٴyOB+;=t2 i9WdI&Oy=Ÿl8sY u]{* SparkFun-Connectors fritzing-app-0.9.2b/bins/more/sparkfun-connectors.png000066400000000000000000000013261250202676700227160ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<xIDATxWQb&`#^R[MJsAPPD,类ܮﭹ cyy G[PTbk l6],wV5l6OH\.d2ץR{n&^x<& Ef_ jEZaj>~T*u 7^oz]R-lƓ$IRidY]Hq8vx SparkFun-DigitalIC fritzing-app-0.9.2b/bins/more/sparkfun-digitalic.png000066400000000000000000000007271250202676700224760ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<yIDATxb`zzz05p3PxAcDXZ:ga,np+3AƮ~%:}`8{v7#32|*L wZL7iiIC] )zb Q2l`do1##3bRO$%lJ XWrׯw`cIY}.FbXJ.iZr'8<ʷX-ffdQOѱ5股vA|]X ӧ3ܽ{цؾ>gϞ$WRR ޾}ZPh)L  OL#.1eĀBrFcp1[ IENDB`fritzing-app-0.9.2b/bins/more/sparkfun-discretesemi-mono.png000066400000000000000000000004161250202676700241660ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxb``Q0#.j }hpý^&ςK'`l)i)03R=&Ki?߿~M988Qyfct)cG`:0g~뷯`Ç$.-%}bQ0 F(F 83% SparkFun-DiscreteSemi fritzing-app-0.9.2b/bins/more/sparkfun-discretesemi.png000066400000000000000000000005071250202676700232210ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxb``Q@$`%Ql!% @lPPg1l@'%ǂKBTN@TNĖRabcвq%ҿ13TZ$_? ' #kGv @bc{zz#K|v3SȠ0\Aɷ\+eW+ w~3||$N}8@oA(` #`'\E SparkFun-Electromechanical fritzing-app-0.9.2b/bins/more/sparkfun-electromechanical.png000066400000000000000000000016001250202676700241760ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<"IDATxWKa~1SΊnB`]4E&n"v'4. W9tDʹSc9yyz%esH#M#D"*1LӨ |rrh8Ah4)f:y^" !ߎQ__{|B!`0&&q&􋋋)AE Q NGhnnfixx8v(#4^zk3>B&`Ly!:A֜kDy^C.,xss~}:WGᢈiDW{mYte⺖K!/d*\\Ɗx:璉i%wvv~P ,La14 1{ s 2&}w000 2:W[[^%_-:T7:Eڨ5bӒcuu am#}ee%:u0EJr$<IK{{{Fp8XhT*&nG?vwwvuucߏ)gJ1WI"9@% Ab\5L(4IJ*/b*-ţmj?4 ffHgffpx_OXM<9uIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-etc-mono.png000066400000000000000000000002151250202676700222560ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe</IDATxС 0 (yu;鉡VJrn?K``; m $IENDB`fritzing-app-0.9.2b/bins/more/sparkfun-etc.fzb000066400000000000000000000224171250202676700213150ustar00rootroot00000000000000 SparkFun-Etc. fritzing-app-0.9.2b/bins/more/sparkfun-etc.png000066400000000000000000000002111250202676700213040ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<+IDATx!1 B!"鲭ҧbl{}YIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-poweric-mono.png000066400000000000000000000006201250202676700231530ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<2IDATxb`tȜ3g*<>,tLOO?b K-)f= (W<[̄,bm A&b(>~_ ''g?=g}IŤ?~0L2ŀ\(?{n-f1@QԲ?b4K K|;M;89hb1<]ÎbNx8SOb`~ j ?5}lbbMMM'D@)h-BFjuHc(0DdIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-poweric.fzb000066400000000000000000000242131250202676700222060ustar00rootroot00000000000000 SparkFun-PowerIC fritzing-app-0.9.2b/bins/more/sparkfun-poweric.png000066400000000000000000000006401250202676700222070ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<BIDATxb`tȜg+dyV3;ZXY%`AY11R`%2 Ff&@lb, H𭀺~Λ;DGŤ2|uӀ\(-UX|MY4Pxⁱϟ?4ׯj ´۷p;1ϟ4op5///M,"|A-''։ѣG/;)**B*YSO└0H5>JAl...0M->AiX "=kQ'b)))Fjot)M 흔S˧IENDB`fritzing-app-0.9.2b/bins/more/sparkfun-rf-mono.png000066400000000000000000000015621250202676700221200ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxڴWq@ "W\` +@\#R L*Hij,M9Kn-: Lby}(۞o obؙ@?͒ '\8eJpEX ktN,e32ʷ)}|N^/[Уn$ HH4h\0 ]ɔG_4/dހ? b3z|>ȉ4zrVA{(>cFzQrMLG@ SparkFun-RF fritzing-app-0.9.2b/bins/more/sparkfun-rf.png000066400000000000000000000016751250202676700211570ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<_IDATxڴWkAJ$ [=oK7ӣ$'#MO)ۋ i!AI"H n!EZIJ0&^&Ng7ځlߛ91öm>U[k`q wa"-!ap .܄ƀ9sܧL HYg$``()[: d̂\?pՒ @@?G )"@nh$tg!#>8RL2ДF9ȕƛ.:]?Vmfǚ!ءC&acZd!.Ek,\alݰJɟ  YpI/G\"H'pm]XXbHd(|^G=[GI2LEjN~'3֤t:գ#n.)RLNNz^Sұ Oe03d:tXzn{ӁtB.:s"!<=u"(,NY>M,J#QJ|k= E,q׫r7a9Ud~+c}oJ, Fl6gepir΋5^["u_0=L4ܞ\*|MOXG7,]~)R_=x{YeNƭk/=]MՖ:cϦ뛹Gn.즧xs/m(nx љ=S{_K.戳|ee|+oӏ^?lzzX_>6HXzw?0& h[adMjcOpPz=HbobIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-sensors-mono.png000066400000000000000000000012701250202676700232010ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<ZIDATxTKoQf$HZ0Ʈߨ_`uJŝ ]X ! fx\PS$K{'s{ %L8m?~Lrɘ'N*+OIOEIt^d'ÁNhhDOMq%2`6ݑĤwG f#05xR,̼ۗ#BVw!IRZv;?h4(KM%_ c> G ۅ^ɥ3N$;6AV}L&p\rܧ\.CUU ׃=REvY*h QGɼ^/J$ĉ4|>~? pK'8Nۚ wX|l^jwg@='2)z0FeS-k d*g_dۘk)]+c-ΑVZVͽב6ޏ^KL$0 So}u8d&Gqm;GXDkhLKmE XYOzTNţ( eP१Of.FK X A qIENDB`fritzing-app-0.9.2b/bins/more/sparkfun-sensors.fzb000066400000000000000000000350741250202676700222410ustar00rootroot00000000000000 SparkFun-Sensors fritzing-app-0.9.2b/bins/more/sparkfun-sensors.png000066400000000000000000000012571250202676700222400ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<QIDATxU=La~J4Ɔ41AM l& [7:фZvL] izXI8c$;9KQN&$}}|> 0`ࡡuCP &)2+Hohv߆=F|>_mk6dbz䣣mXwvCt"p@BQۃEs$tl)U嚙,k ι9x<Sx}8JzfPe"lQb*x6zp@$z@ vmWF?4˪C'ehMNjwI mnB99edamc}1f[ M%53FZɄ6ihH/:&+R*i|Uӫ $.B. ZŷD:I>;lƻuQodߺzEQccK&(N'Хz4>~\hMMA* quU[ӝӫ 4 ӟ#Yg$9Jz\ǀ͆ςؗˍ=2O€^$IENDB`fritzing-app-0.9.2b/bins/more/sparkfun.fzb000066400000000000000000000365151250202676700205500ustar00rootroot00000000000000 SparkFun fritzing-app-0.9.2b/control000066400000000000000000000017661250202676700157220ustar00rootroot00000000000000Source: fritzing Section: electronics Priority: optional Maintainer: Brendan Howell Build-Depends: libqt4-assistant, libqt4-dbus, libqt4-help, libqt4-network, libqt4-opengl, libqt4-script, libqt4-scripttools, libqt4-sql, libqt4-svg, libqt4-webkit, libqt4-xmlpatterns, libqt4-xml, libqtcore4, libqtgui4, libstdc++6, libc6 Standards-Version: 3.8.3 Homepage: http://fritzing.org Package: fritzing Architecture: any Depends: libqt4-dbus, libqt4-help, libqt4-network, libqt4-opengl, libqt4-sql, libqt4-svg, libqt4-webkit, libqt4-xmlpatterns, libqt4-xml, libqtcore4, libqtgui4 Description: Easy-to-use, electronic design software. Fritzing is an open source project designed to help one transition from a prototype to a finished project. Aimed at users who want to produce or document circuits and experiments, one starts by building a physical prototype, then recreating it with Fritzing’s graphical editor. From there one can generate a schematic, PCB artwork, and PCB production files. fritzing-app-0.9.2b/fritzing.appdata.xml000066400000000000000000000033651250202676700203030ustar00rootroot00000000000000 fritzing.desktop CC-BY-SA-3.0 GPL-3.0+ Fritzing Electronic Design Tool

Fritzing is an open-source electronic design tool focusing on makers, hobbyists, and everyone else interested in getting creative with interactive electronics. Document your electronic sketches, learn from example projects, produce your own PCBs, and share with the community. Fritzing differs from other tools through:

  • a real-world breadboard view that is hands-on and easy to understand
  • a visual component library including the Arduino, Raspberry Pi, SparkFun parts and many more
  • an intuitive user interface, with seamless switching between breadboard, schematic and pcb design

The lively community on fritzing.org exchanges projects and tips, and there is also a PCB service "Fritzing Fab" that produces user designs.

http://fritzing.org/static/img/fritzing-preview-bb.png http://fritzing.org/static/img/fritzing-preview-schem.png http://fritzing.org/static/img/fritzing-preview-pcb.png http://fritzing.org/static/img/fritzing-preview-welcome.png http://www.fritzing.org info_at_fritzing.org
fritzing-app-0.9.2b/fritzing.desktop000066400000000000000000000003341250202676700175340ustar00rootroot00000000000000[Desktop Entry] Name=Fritzing GenericName=Fritzing Comment=Electronic Design Automation software Exec=Fritzing Icon=fritzing Terminal=false Type=Application Categories=Development;IDE;Electronics; X-SuSE-translate=false fritzing-app-0.9.2b/fritzing.rc000066400000000000000000000032221250202676700164660ustar00rootroot00000000000000IDI_ICON1 ICON DISCARDABLE "resources/images/fritzing_icon.ico" #include #define VER_FILEVERSION 0,9,2,0 #define VER_FILEVERSION_STR "0.9.2b\0" #define VER_PRODUCTVERSION 0,9,2,0 #define VER_PRODUCTVERSION_STR "0.9.2b\0" #define VER_COMPANYNAME_STR "Fritzing" #define VER_FILEDESCRIPTION_STR "Fritzing" #define VER_INTERNALNAME_STR "Fritzing" #define VER_LEGALCOPYRIGHT_STR "Copyright 2007-2014 Fritzing" #define VER_LEGALTRADEMARKS1_STR "All Rights Reserved" #define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR #define VER_ORIGINALFILENAME_STR "Fritzing.exe" #define VER_PRODUCTNAME_STR "Fritzing" #define VER_COMPANYDOMAIN_STR "fritzing.org" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_PRODUCTVERSION BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_PRODUCTVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1252 END ENDfritzing-app-0.9.2b/help/000077500000000000000000000000001250202676700152355ustar00rootroot00000000000000fritzing-app-0.9.2b/help/images/000077500000000000000000000000001250202676700165025ustar00rootroot00000000000000fritzing-app-0.9.2b/help/images/assoc1.PNG000066400000000000000000000442521250202676700202500ustar00rootroot00000000000000PNG  IHDR]dlasRGBgAMA a pHYsodH?IDATx^w]Em?tޜ^5!  5@ !-t*"bhtbC ,ۿ޵]k̙9IƵ¼ggy;KÄ`[sg\E"Tp>vϑσeHAwҥŋooyb"#mre/)jDD2e 2A LZԣ D2A7nn D D"(Q"FЍZN(]]dvre @Qˉ2e2A̎ZNr DA7j9Q tQ"vQˉZN(t#F-'@.@.2;j9Qˉ2e nݨD2 d`ԨQɰa2=GNF&EЍ .DM-jjk go[bŊuTדtem[hq\ec=裭 Ѽ QiAw8䓭Z2:f5AsIn'0KyTKtUWۭdoVM7!WOw6ky6tO&x`kgy&[Ұ'M}c=̘1ΑGM^xM^X'[o57|3]r=}7v>`g?k}uAQP CTronk@w}=m{fH~ݙ3gf0U~ӟ&W_}u~ɟvMUswvȜC;2gNҿN>U8S;vw\'xbp6hV{(@Zh?4.h<#G ҠBfmoϠ9ll{U`=[.gܣ0@xm<[A*t!N(;]w]Kկ\9Yv]wm㏷C{ 1ҷ[D-ЯܫK/%ÇwN;wk/97"oرcӃg . jV:T@\2 VЫN o[D,lDL\yA҆v„ ɘ1cPcĉ~d`H] ȘF~I'MW˗fwN0A'?IpI^et{3FYWt]nUO54ݣ:%X ;qQgE]`<݃Y(!H>˵^kEͮn}Q$&De$+`BDG*{?:(7)@7/˰7N; f064n^]B~DM>Y4YT >Z~SaΜ9-&I#!;b^u. ~_[@7VjsB{Yi% ߿GgY+&'xʳ~]LJ!RӍ.NbEc njDž Afփ.ǏfȆn6df^։CHpRQM\Bǰuڼ..Rݒ?UtyH uHczB.ZMwҥmLAUI$dJƄ~Sjj?CLYᡇԮfrJ'{z'|24/K/4{キ%z"/ W!Te5/o1xChX ëA~oP~8z&#Xdž\FG}3t 1N[mUe{a E7AWM@1MUON)V#2!TQMj".\UYif: m]Ja&p ^=$̆;U#H,)S\j݀'E5Uۣ9SWUut\&2?|+m=U:j[-@[JH%d'jDҺn]&d[y; " 4qp@PnRtAn3%_Z՘T$D𪄚O/bNmllTnShHC_<$D:#*}l yzl-Uh ]좧(YBL!?ͯutHuW/ \8w^duKHз,!0*etr{!|#f‰;nH$G,[kWT7AbA6]5v.oH/2/c`3?S#xit El3VvQ9P(}N_U#SNfFI>-]evI&!<ۨOTů~nVjL] .&b-9~=x]p*<BntaˬBn*jrD(C=i1W9n=PDWvQ9YvTlw4SIs9rdiA_I|LY9DiÜ!\I^ 4ڱ6X#dfʤ5fo4X"IjR@^oM& rvV:^(x/c%] Ƈ6Q]YB@ Uv\?_f\5zqAgֱ^*N"?ɺU-Jm*r1gYR.t^+R~)Qxɰ[uV 4"Ʀ~<J_Ew(YާEBԆ9ҋg~?|r p|;;!饀w}yZ.U-$Pv6j-t\NeB't;vw>(,̼-wܑ x\*fvwTxyG,󼇹!pxY\I3k?x6N!n:nvL|^Q4Ѕ(#`ex{ rY+i \IsV+4c3ܼK =3|K,Iqx\nҵ{y@}4z!hrϘ1gѢEcPu. euA*\ ʤV^ms(0eҌl\eL=]&y^rAeҌي͇j.Ϛ)v!u&9W7Kp,n0_fɩ)yUDr37}.\7V%~֬YV ]b+SҌQ]M qEp |\e8_L4/\,̼vX6 pq^vp8e2 _YԜ_N`~ t"4d.asR`A m&*WJn^Mp%:x{<+4^rC/+p/KؖI{p%sVJ/2@W|暌43Q>\I]ȍ蚀׀x{ y׀x{ y׀+ixmaSk2E~o]xKܺH?,o5:iw՘>nw' ^e_)n'O[IOXCv-F'1HxoPB$A6LJ;NLƤ1W!oi+hO!hLii~g9D-pܦ,hMiCs}`>f,dHez۱I}&d'D6|/2|H, '4fXaAs“uTҘYd)&y&M1.SB+BZSf:in4dz ݓc ټh^m*49Y o1 /vQs ^L zR&뛎 I)k6;g,[mbM5$կ&;^9+i6UlMctm]!6[#J̒beOG-nu!>p6h>g\N yec`ٴ[6\k o6m\޼c`[˷I5`.5ѬO|LxԿ?O S^"B61{ !Z^L 75Ѻp4NWs^-4Kt/H4g;gJs';Pn}S,ϡp5ƂʡO?`?Zp78 X5ۢ ^"L '2hn~jjR۠i94.[px$sO&''g&#ٱiKɜ _Ncy}?򑏴^T{ T8wpc M1eIpFta +^j_\>.YLETG#r>[#1Ӓ(lL8jjbS.F|f}|Cmh.sWoöYdRt<5}|d$ *?޻k. f]Z^ӱ6WnNع\6]oㅠ 6`cH_Ǟwa"qib/tYp8\Tc/ H^rtl9&&/D:qDe+quz LKMO?ǖI[ɤB}g:h)wK_t4n,Zhx#5>b_[ 3ZC"2QET_@3 U7҇T""OLMP`9ܓDIgN>T`ج4϶g.3E*MI>stx~J34OUE {6j+Ŝ5W(m!qrHp3QOKMGT t+}s2~(bKMk&!,M\hjB+db3O mxugvme҃}f!ǙƊm!ۋMI NLg !9.ޱ^+f!8yzf>>inۚf-de!6'Oo.lIecqIgc'̀)؄97 {oYЄB#r4 Y;nsQ҄Ol!6!,֠!;02!;^E3+"i6h[Լp56dO򸅠yR3Ma5lo(l6Хd>rQ28\bB6%xXh!9grq|`Z92:bH2@/E G؅40o Mfga"36[;«9{;PcHl 3) 6ѵ&yNicb/$tK6\ߩ͝447 v"Da9i&, wJrfXc5g@wOdf( VVUxhLB*6J-;XB1qDoQmN!bҝ .<ɅhV&Xht@ւ@h,0_eص፮m:4ӬfMu Y3[oK!5qm,1eAsFf]kOFR,4wG\=$VwWrUgNUЕ4Vb6Nk}hP1ٵMWۤOskYIOZmhbBSm"2{Bsp 4l,6 Fn Cm[9"4o! zN &uՈMXU/{f6Ox)vmסIy,|@ %ƶYoxm/ۘww 8dqZQ{o]Hw{]쮡Na"m>+'dc,h7 }&waDkxy!{MLtN0 gHjWe.M#+bnGŐ1 8yi|lf};Ms Z]֮ԉyaᝧfuXsT>nLhZ&< K#1 )N3C!ikSXh-: Cxg`ّnC m45lr{(]B,*N]"/뤓kYxB*&8լ>YxjQ!I0K!69؈I*G#Z" Ǭs 6 -$ᛡkj/  @.)f1%J /ed^h3bMtYD54#QJ4OqA@x .SQ"0L+{eݐE Ϫ77y᧘dy&w?r_r5$Exۖ{mz#- ~*GAH}-ءA+`P1d]X 8"/ľRJbvF9޺Q!жR,N&vYwEAsQ.NaYL=٪OAqv?u|W%oNZCK>T!ȇ>w]??,[o&|W ̕k3 :AX9ZcMEyMr6\Y'GQ]n~*\ _YPe(8dgI. 9MYO;O1iͮI;6]yAv9^"'V0plF&{f38x+9\daKnCbj YX>>Юb2Vp8,k"n4&_W\n17yKDuly3p2LKjdkj7-o]7Ic@L/fXK$Ȗ i{mќNx rn(1aFZ$͎R30YQaa"za%T4=`ia7Q"u[y?2rD\5pٖ^O։~lC*1̭.d 1Ѯ:.\ɑa h.kؤJi}HZ"^H4)p[e1."5V@"I.canh(Rn^$Uӵ.L pH5+[,޵ju"bVysdYmxh[Vɼ4S4ߖVD>@7-YviG2ux;<\c꒩b ݣJ0a q&'"MjG|ckZ Y2xXڣ†2)}d)W3Ϻ(Ry YΙ㎷бG ǥa*TPUl3&d]t,BsjL3w94c;.SOߌ15z.=ChVPڬ\"Igu,Gfw$3UTrя}4FrDQBR1jȨռ,r ܐ? tWY r7H/7oS0䜋& զoEǁ!MHgQ%^xaonvRu,c\s4KixGmQ m| 9쳏fTnSBJ6Y\'=D8(4OSXzur!숍nYaNk,f!+BGqD½h"Z.;ilp8lLq>k)?xl9 6! k֠ !#B΃؟kv϶Ҝ|{:N."ʫ$NZ?Ae8 \ib͟?:f'貨N3 kmmh1Ӆx1tN)_iSO=;ОsTֵV>{D:ꨣvu)s|uN! &B;蠃:… 4tς'.K78c廍CpۮBd6`B[;U=ua.|+\sO͍z'C=tAjD!zΞ-Jلk!7YM^>裍;2?k\>3z37Ϝ)6>sNEoK)%vyg+= X.v}s|s,lTYp;ąۭ9pBCl@U9-*-lfm_|fXdI{}JsmRұ_8L"t}駭$ZAonEF6ՙj] 'm{ pAstg ^pMm{^@lAڣqb]l)<%Y $}T! TfYM^.oxww%hf޲ҌrqᇷY!/s}AsMB|AS./r3r1}lF`^, Ќ\g,k& h"+hƿIH{pi_җ.}o"d}׬Uӕn$ D|`5ޜtf\a-xs oNC \=c iyT \NS6|ǛSN9ZFx|TG~k\Jx320  p;4oV ^D>.{V ^,Bݬ+%ꫯni{ .% pQ~wx>Gȑ#[rd]%,7xnƻ9zMF-,H\7/xcƛpC4^ibW\+I7 6@b+N;;046\dL x1ImfL|*`.S;e]V*09>iUW]U*_5O.|K%(S6XP~4ۀ9X*͗^zi{ǥj9g\d 9TÕ#22!$DUam!mܹABDpC4޼tdy/ hY]mo:p}E^pmo:&*%t|H/A&9m a|>OulNWt{ yp^o5\Ier}WnV^mվ9Pܶ :4!SՌqӾ0J%D$dea &S05u]]q\&/| ]W*D袋JYg|<h!}U[iƋ(h!GP>s=4\G}e*^|(7ЕwEPXT MT}p]M>XTY鳵B3h.Ge/9o+4S (JmWeV탵8_E=֋!gh*[Qo'>Ҟ;!Lf͊WיJ$M3ќDeZ39$H<(S6~))X6/B|L.&l`Nh;CʤYPZBPL޲ifmCi Ik[]{xKݼҒ_/4@1@GGcD,vZu<*Iޥ24\!"wI8&7//).iee>GTPN4Tz*ij&L(M6q߾Pt(k3tt]AOi$$3Щ>w \4B-Bs@WqtuzL5 |s 5Z:Z,J?4cǶi+P_AW $ =#hBmХPX&aI{EL<Ȋކp٦۠˷Mz56/b۸ >`[Q&ݑJ:n.i:T僌G C{]\Axxn^[63j^[un@nӍn5BAwS*jf"zA=-FMu~/-zA@A7/|k_tꜪ4 yᤓNr!Bێ4yXPyA//:7kU7/PC}0We^uμOMlMK[:0{m$1R@O}O<6a8s*Y/wgt|*zCc(:U_KE)XOAظAe>?O~|+e&o:L:2"&q^ ۑ6fSFU4GUG4P(ZҽW_T6̝ lm4ю2~fjs^BoMq3gN7Jׂ j"TgE8`1V]TR5'F O6.Sz\pa MB0F@[!-_zSQV?U`1)ZMZ"#;LsuJ3M*\:BCֶ|[iSpe5E9tWd޾U3x*c\e.[_EVt`#-4Pa0e=#Jocn*oUQP;h@=zt43^Hݼd˜$E. ѨtQO]fAkU 8qi(|Ƭg9&K߬4dmbQfqY*0)wQ`վewG;U 7kG=f1Fӆx2'Ixfb\МB"Qck#W+iBEr6GM2f :T<'}p2j/woᆮ\/.{+n06+v|3ێ[5&tS٧eI VZT/DŽ6] 87L* (8E `47*aYs׍~^+6Ute9*p1j&ȰIq{+ӦMK.%Kҋ{@FYc-Q6T8Z7Sw5(DdptTc`CWU4Dl!'$Gwշr`}5 C0LEӀo\*RĻ^P7Z2eU-8 %mQvY7!xFiFlU/R6$U=鉿얖-}sZ}'"Uǜ΁ގ<"g䡫602/P>SRd@-u0}6=&&;Y^򽇭uF]^CX1蠫 ];sρ3l /S]N}<)wݹʜC^C1&Eb+UVN/<`Zq)n}{E)˱;"q٘AX/:)tz{ȠS.nK %GU&e_zj=o<9GVeBzwU9a(4NwV]EfeCJYPuDZ>_Ӏ, 8Ԫ2$J03.^وr: \`>ʖIHjTtmWcfZeԅ}t|F?샅A*io[s )4ag#&EWXPu-Ɋ=<܂~뭷f#7Wt8W pkbrbboTnX{jshg h gRdtm[D: 9PL+ +u1HY"meo(R9^RIJA&y'X\i#AW:פz•NApcwQE, tіB­2rA.&^g6b> 6:+83}d U#>TgYhW5«k# 2իuc77o<:7@@7P(MQ$8}Tx_1֘kbqc')(]۲~/ tٱmzVAD-KC=PLߘp56)N#7*Gw߿]e  ؐ,fޥҥK+/yAt:sNo(nK7m(ILË@ Ƕ1݋L0ѯA<蠃$øQ.qTFAݽ S#x+@qA(17B|b7h\MEKC~L$ wvk 2.j5SK]O"~'LCyE OX$KT)M7irYPxMA)!^L~`8Bm3 "U1fU7Aoվ*>)Iz Z;:wѱ~F=t{: !+  F & yVY@BÖO{ў+ k ml)OhM 6`\zc߷q{l=Dpr a`R4RPy[[d 0-2te @e n9sT DЍ(Q(A˕/|(rerrV'޲GnC_ǟpBX\gnˀt< J&o鎷X*Qq/Tw˷9n3yˆߋ2W ARg"6U^%(R0jq!TbQ%K1 JZ0k [U5a; .E'n)m{ݼ; w w8QZy̟p{|s0\)>'3A&Ϝp{hbK\ȃ!99j.Utg_8Wq ^t}I 9@~^xE}\o̎F2eDya׸+.(QL2]~3Qˍ(QRZK`x!izmQO(mIu( vtsF2e_e _,IENDB`fritzing-app-0.9.2b/help/images/bus1.png000066400000000000000000002637431250202676700201010ustar00rootroot00000000000000PNG  IHDRF~;sRGBgAMA a pHYsodIDATx^E;tx*b@ *,,,9.%眖%.9眃IuNS=3;3[)uu랩WUS{&ԧj5hz,RRRRRRRRa͚kqPҐQM1;Gz4-z_~BoYW7)YrƤ|cRNS&$WNNcVGì{'26 _l3l5 8ѷ)56[~i64h,c2Ѱ;wԫWgKrrM} Zݷl6[/ݧc&)Rd{>}P2Ļ 8.ߺh wd%ɻ`?vt Z;NYM~R'MM _eZҿk޼~ڬYO>?H-M4iҀ+ >Օ:&Lu2B3-A5ݥZCT yũԥjA7Γofּ6Pl4_5E̾X̾UG*7ؠ 1׼x ?UT*l?>R[M/3øM8TV|͢4U xK QZ/ }]_-[ҿ(&BW𝏂/PhPѡM6._;/V/ 4T0P0ZQ! cF4 m+UwZ6eӦMդ5\DAC58iݾ 'ԣҏ)u)~3iY??i_0D~Fm4-#Pq]\Īex?9̙~.sصb ` 1 I-06lpP ۠? ɛ43bnGG*cG- <y諄qtzЗ?VU/ab3 평ψn@jA {lc0)Nu>'15Չ.Ow2p +~1㩎^9_5fa8':~~^k_^婎Q;xGlgwDuv/gxG`GDuȚv``TGH@Y~4`gHuة:C?jÚ}cҨvh,jѱ)ƦrjRόK96+qJh\zEY)HGXj*b>V{x р9"9~F5z12ֲ01 lXpQVܠSTqI|WD4bB[F~~1֠|"xѬ/2͆YNDh#\1`PA؎.f`Ilu4:6~;e =vQt7z:z ?82#'HO:3*uy縣oN'ATqq]\Xje0V{*1׿j[W<2t10#?~ &N8iҤjbREA AY/?5Pt9>VXINw,4@z23$?3Syu}dc?Ƃ^f# 9w$s:i!ݻ~74Ţt\*MW p`#(FxE:u"`?btғƿW k~{`~V=U\YcP~muDub;dy s%cTdz̃3ibGTGxGNX;Rɒ%: jYfZ O_Gc$n>ԢBrzUZmHCBwо=ZdJS)}Is&Y5 `'NRP9n*{*WuqC U}4tgV_10֡qYe,B&.izN X1c̙3g[РBT E/K>ݧ`3Ueyfe# eh5>_ d#}D0As)(췝-S[|n|MÂ`ayc+6GluTWtQݯ4I:k+a N3zR~vqֲRO{?1~}#&^7Q[7_ݺ6׷iMmhtg\=qM5=C\'tu9׌kG;P6ֶٖ66iMq]\}Q=KPwߘXx}^WiLE]}S-wG? }#A}g…)Gx9gy-&>x8m396f*Re{ymi>|^eѕW{Nc,6>B6OF@c#\}ϥqW)ˮ!8G 1s?4R˜^n⁍cbUo6bvfS ه7ͯO}W|H wGr1%[ ң۹&ٙ٦_<{CmI-#|J=19g/3+=ߖyw bp*M |꘭_0 `9ܯPTkܖV"ꜵIfBRVG:>Y`ZeNpv#IN婎 Ac :Cc)X~;ю=aIOxӝQHWD D,8@ZZ>gqlZ{w0N?gMZ #?nL8'ǿ2ON.2O(Ĝ2_.bK_-b_-bkacφWQ%5[[ZآW-|W3'fԗғ_R.Ko_3~c⃯-nj&8&\o^o|IfagdfNҽc*j,R>'QSz#FG3z Q wS=*"ݛ;W]VNpY47%f)_ydpi»!|k w^'vS׮Qk:Vצru,~Ok_'+o#khNv|Ü&T,IHT't|+Nt>'ird=fMx',j8']LF;me |b> Nocy ӝa|a!_0E lvJ*4U "zLdi" q-~pcJ>6cSJ>6䣳J?:#ZCY/>ŇVКZnoWbeKt`3+ZP!qI%PR.{H7\!zi_N 1s~֣u =_,:tdSxnncʵlYfck9f?W)ׯ+oT}ޜ~JcJyb^; `sݷrx6m ݹ|ʟ*l ozCfx7R׹ <0 4&og,-+k2LvTx)wK/|e$`ֻA`>wQ<(-lsZD]3Fvx1a+&BaS.]:t]lp^kpuꔢ]Jp:52Xu9 j#T܍+6qƕ)Tn{갆ԃ{.q}*TQVܙn9id:s5ڧ/Jk1P6y/*M;.SSUyiB~%߫&N^+`r,%WTGH: HgגqW٪TghDKTձy5{xmvη#Mw)Xlv[ULĮ]}YDW6oDs$C ff d,:t@TfIλ٫Vc'V&xG:dN6?nHKSc_}j«OM|iYr+\rŗ+xjM֕*E2{=$S? 4\ Y(WךTIJǕ-ݣ} C~oyu7}>9+[hQ?q/G^W 0 ]Onxjc0).r,RR"y#] 3lЦlY/[87|*~xf)STC[ SL^#ҚH v ꆫs*&SlZ3]#]fJSe; KVu:+#tP]ъN1)~YFrNA:7)S<6c^OڥNCiZC=u]鶩@*۩sZv @۬ۓe8R}Mbh.\U/.=^S8y$WZm [NVRw-z6 wz:Ӡ6)آk_ Qum\w8uWiFݐvUt!HB3$(0EHS&S3U%)MX%%X_V@:f|ͫ n [.uf;3#c;Zgz(kNx?,!ݴi3[~5_FUV_E\?5SN:uڌw}굴sTtӯ'5mun4um~`c o0 +0 3*0 *nzJfPr%|Prϯ$jjUm;ת'.J.~wK.xJUfTzqZTzqRWE!]啾bCvMdHwpĪ![z^BH玍p!]^Ӂ64CjH{9eنgg^!b3B:B2\HR zP?M9Sµ[ɛxhឭ7(.j\j9^tf1tTxU\$O|8^ "N똮FRɖ!:0Bw׹a5BtGV H{C:JgtnRRmxC)pLt: oS]䉉񜋬\OWqN/72Ɓ ּ(!e{j~<U7sUhbp)umSݳ853\.Soǫ{AvrW漚v^yǫe~k{J"6)W!W} fWfg+l9a@::Ů3l\OB|Fѯ>",җݎ|XMBXx n3ZTRx_=VeNW^3wثC|7@ zv tڵ_={3O$?qyU>qVl5qPS|ցR:OkTӤ܏4yuUyM-lmYen!n?!p:5هYT[yWGhxը>{HR=WnoRfKӲqG{e}vj|gYxEj#b汱)[ 4TϩJg.8Sc]=ۮ0$B,(XXpN1żu*&'uMVcS`>"(wtGwP65].q:lsHԈ .|x#0s9#x'a:fN\'Ӛ8 T$+-Ye֬ʿ>-sVt'& JǢ%(1_ -v|N;V ВGSXt*XBax N%f̜8ph]֣?*{gPop[侀6P XJJCҮv6iNW6nxyY,r㰤Q}zwM+[";ll総ڍ;n޾v3M `&i JxMKGIL\A4/SP= }k^&"Dgy6\S \e j4++ 9P˻aUf#7Үm*5MU$,8U uT{f^'ϰ'I᫰q JpdO9xV7e>ߠ#|ϳbq)52(nRI.UoJF.Pc ꔰKLLQ&)yꨨSR^Ү9k.ShNm%p(9AiHܹAm%+PjxPWarjj% OE% ӰK[w %W]𗲥dGoC\Hܗ*d"E(K̥Du{[95] AFv^y̌c%Lh%%ʯ*u*atv u<֤ݯJ׌Jxg\,pvѤ:2BR\fƠ6AƪU.[lyXueUkQW^zzknXn#oba&|svaqV_| ;=e̞)NUL}pRL?6kԉYNWOLGn,FPuhƘC6fYVM3[wxliZu2 (W+ռcGl7[,EM󕮝ZO%[|GR`+b /KeOB3 }@aD섒RX)cmMyz24"^ j82цj\d;ق`tQ`r؂`U"XJ9`|`͢r#X&a jL'0V ^I>,8DOjߤZR ˂ &9j,CR'ґ9h < $aT3 9MWJwB%@uxZ#L5<8>xVyzG*NHAXW5KzϱcTG:,Qꫯ>.@r*X^놡r\@yA-/Kwyrʽn]_ ?~?x/UkGV}?=`̧ fKJ0[HrAu4^izWCφX>'<<;v:*u(X e޽eZ]͊uvH^Q}a +tv(>hT+C >բ_.װs_JR%<,TElGEZiVY J ,,_AUc'WeeWT0m뉍_k̨FN3D`^*/ _DO]>mJfV1=\ P+ mU{AR, Q'ݯl5P lWr_)yuVӃa[&Wg 7ڱ=|5<;>K}XB;CW,fױu,#1-2K~ ѱ>u>}U֯_km[u(l1]Æ\)0/8|b/|-`g[5xnDE:}N9"TěTgքQ:M>ͽݯ}GK*;;=3._'ccYլ*FXh v2,:yщ8a@4:4dtCg| !#CW\n=HRzmÕEH5fɸ.<#3FZ/ؽ4EKc#y xWCf|ܼe`~OD?8x""bqg!. S4p! >](`|y1 Oco9<̙#%ߞ%/sf>dm}a_s ũN_5[آdC%lEꓘXGTq5Dfw v!Yz$)|~;2ѿ~ ֜ s[I _SDuXڋ]%[F 7:  h 1'Gu HO2؎\0A,4~<)i a=,&az i-a0ؠj?p7&0Y} ,YV8񷆏NN[%WJѯxg:>Y%3TUDe K:wSn“YBdz%[L Q|# k삝lV/Y!ޯA2,ݎP H;*^Lc22O%5Ӽ0=o ou-mԓc20f"ٴȬAGc`X,~}+Вd`LJ&wL9z bn஡y]̌oy j7F2Y~ kiPl[R; :4V) ˸:cl2:T|,:coÐsg1w~rY{*y)O7}1b W/H|ưLd^<`HM\P_4~օMt bcEHQo;'S'{X 4hAL=i`. sHLJJ_sjDF<ڢrR ),kQF{UbLt60 cc5sha;Jbb(H%A@EKRNXLmO?DK2[sα3@:CS{7K/y#.L9d4C_zh#cSxØI~70O?^5B2Jc-b2]BLFƃ3wܼ.օ[l0 ËrQa*ꃏ=~~ oJ?Yl|fiT2:$P ToG u\ҝh`ieIYU 8>6}kwΌ4dc `X; MX d!$mutZb5iG70H!/݅?vml+Ȱ/[|]pT6p阩sB Rq/@{:so g(fӤ ҟ\@<5|>ˌA /Yňد#^fG2ikɿ$9`ψ@[i G I` r,>%C{wSиkQ% :/~y6Mqi5 1ўG< ~X<Q/7y!0ًemRRRRRRRRax5Tgt StUV ?P~J H H H H H H H ~ HwϲJ H H H H H H H ~t| ?*5 5 5 5 5 5 5 5>31 ӌ%M4X/h72K>5W0R \N׆sa2놭$K.ax+#WM1▲[JTOWLv֚?] 5]NDwrwt0/%Jt6ߐnHE=F] QOV:Q> =JdYK7uԀԀԀԀ@hwIUvѭtxa&Krۣ>q뾣v.ϑGLaJ?=ԇ̎a7į\Yr)q+*S 㪬[PtChU i 7"O=)7GRRj@j@j@j@j 4pኘ u4nk&uzRWڗp9{=^rA1{5a4;0#J=Tm޷nSG&Ae^߂#4҉f}Fo|d-s4ekRRRRRW'a(WG !݁M V ^aq|y'9ʚnrnND%zgZ`Gfwdhzym_w=ap/w vOͱ{i)/5 5 5 5 5%xՃt:;O^:C;tIQ3Tt15Ǩc<{ 6!䳝smGͮe_K:)W}!\9_ͭ1(F;e2YWtdJrM/6lذdff۷O#FHj#?eHwZ[v7*۵?{7gV~NYQq'F-͉Zv]ڻՕæ֝S!5ݸqC+ܲeˊ+mU-"ßFFFǙ@uH7h Uđ2eпN5k5 ңOdF4ݗὄ͆I7|wG~(5VcBe++ó١t"TNvY)Rj#q*J]\EljVׂ֜#5鲲5w| :tH.xbHn޼ׯ_Ձh2aH"t&n1Xx t޻TۭwJF`,vFФDniSO/2j1nL7.+Wʴ1%{n%i NnY7kXcQv$+6zwW,:U|*^J6do'/)d- zGZ}jاa';Ġd 3-kZYqevmwڤ:)ew>}^.yruٶQ ոޚt[{uc-ȽRNj.;;p.]̧[&l0GVIrq{`Ԣn!fsSҘҪGF٣2waܲe6 bLJ`4HQdIts%{lVV]%K6hRri:5?[I:hm`2jLU)^=f1mi靖,=i{|T*9KQ+ >(C%k(MaY$3uGܳGݢ*D-U\ݦmD3="-p֤ګhApPtpv0nժU`8 DX̥[z5=^r=NgSgyMϤ3; %LuKmO챉oMK8LT@;V79?[ݙt=!}dXŸxUxmڷ~6.ެUrSrPTd׿(OgKys4Jԭ ź_ q,L Zn׆YoT!\Ei*m-ru~G@avS؉0RN_֜I 5S/5t{d۴i.]ʮC3,"^ẅ́}'w$yb]R\*^&o߂ܲ#oHz%pCoji>DJ#lҼ(C:ܐܐHU Ց|XCuB,)zHЇ_iqj)trѝ2sͤӶi(KKLwv%OK٩(v*VzMŹ}*xqk9hg}S$̮fѾS7='ݸ: e+WP]Oj9jySo58E/U(/CYZeH,RRa xc ;ϥ5R 38phx0*E +JVg>!KYne=Bl͚~JSO15GPe2>6xņ蝱>6nNNMrBթgHwafvߩ^5nhZc 4qT1[d,_#;r5Uy:b_~^{[D*r!➒chT>fj;o%%D_H H D|,BjW6PB]2y&.38W+̛2YI7|GicRB ]D߈Ԁ@ R+%.mymFpI)ɱPtwZٙtr !Jio֭[dF+͆I7T~ݑ!%=i?NH H |ϥta;Yҿ-DYara \ݑʑH>ԀԀtE?UdВUj@j@j 4@_J'9@j j4 Xnxf?)(5 5 5`K;J\ވԀP^:׵kbm2ȐCEPbvD(b ,&.|rl #.CrP\f</.n:0N2fqCP|P_fx;#_k]}y~&{7|s+W\e ߼yy@/5}K'N|",B&.F8yGRJ6I+ IPY(GZ?b~y$Oެ@iHsT!cD:tL$&I 9η֨շOWxes\:Ey@j\:D:^ED"]Z$IHG12<"BGem5gxWҀxFX[&^xQ6io߾eīQi!fWsא'O%K_^\>++kÆ /FOqy8:.]*.QT!.'*:)v_,nY}(*˃ /xgc+/o`<$rA@@_lR,&B_b.O$uO ?N7H#")➄r>o9%+Hh# T'X0?0/\/Xϛ7O\=A,u03Z\O z S۷2fqCP|P_fx;#_k]}y~& KÊ8 FtMs vPi4`'˅uJH+3m߾}S~WzHFʈW*xEyc TLpLA쎂b]*<$5&7Z#Dr+,%;#uP'xd%#dx Mq+N%ޤ XA )ꚓGmR# CƭUm>uƻ^eNjj8W5Mou;.WstqMW6%v 6ExӞttDuJ'Np3HH'.Hyk2z Xuأ= ٣ns +΢˃h;=y˦hd/ȭ@{y{MѥY uPgpƑ3ZF7nMj<2b9A@xb{@:^DCf$gJk <:CKX#~cnSOB:% {&ߓF fDAd\F֫L^4&c칸ٝӁY4WQ8^ *H "cbt#6YY^fK߇QҥK  Q QD:JΥs\:D:k- ~xx3 e} ňN%eNu&:G osFA:f `HGT'Nds\:^2/]%5V:F#5˝ʹ\PbxuY,/ZQE*'Oc>s#ridJPUL \}0H~՛3jS)[f`Jp]PROmRW ϛT7ݯ{.z. uzHPXܯ($IǫtJ+lڴIkbv_Hywgq8LFz#"9aF@mN8/z&γrf=`xu+T:KT` =q(*xq[Q>*P@3ѥX=KY.[k)O&W<J_\hr̜P ^~oA_M_foϾg? 2|p/+nСDu5,E/z!!<"b@\>ҧC!#Bm/"β׈w3Ɲ;(½51AV: xTcN$ɹtr.'EΥt9C!m^I]b1 M%zZ0ɎQD:QJΥs\:OD:tQ^1EXa`x^:i$IH'aH'.RFJOЀ+O"Et$I3@GDh';)5^W/+u `WJΥs\:I+]B><7b[|;w"D:tD>)$҅rגz F:xC d,p\"0/]t͚5gee]V\~{-Z$.?%Kc& </.p'C}peyye|yueMG$WaRޠ@h!y]WڥG:|a,h,v333 C,##T!.`ŅG\0pBqyjqy@Rqyqy/n,> kM3֕ݗ7I_oGndpVAJE:8b)T'"$!#dx'E:^Ͽo+C1XWf.Ө>o/6^o?~t37޽Υߠ<:U&\:JΥs\:OD:t@n|O7Iwx9f_(kDh w葎y]N"(%tJ'tttr+w~|;+nuk߸ygY"DxXxdxpoo;nȑdCH'8PI+I+ȇE"D: X7z_W28Mư7oO!#ÃSHxZt(tpJǫ@%N"D:OD:t.׋GTKxdxp0ҁ߼ҥKGX <6*#htÆ "/^3l❑/}\U9*^H7n8v@"@%tJ't"tN\u%h4 2o޼O?"y<\4Gg=ċMH;swtW\tŋ.\x'Oܹ{֬Y"P!Z.rJNZ餕N"N"nyϹ_wD<En}YDRr իWN #;x V,YdŊk/^mhѢիWgffYF\~… #.j*ܯʕ+q˗/]T\8E\ˀ-eBA}ye|yueMG7|sy|w_ebݼz&Ԕ+sdQN h>g\vSLWS.3 {+gf fdX (0aopa$ޱc-׭ߴbjGaLt7/6mG]G:YVfdHנո ]fΈT+ܬ4Gv;C:tByt3L<]ϟpy,۲u WY|*<K9WlM>H2E$-5u֯_/苁]y6n܈mx: Mŵ{%Ť^ŧN_JPpVn4Y686a+W.YFi&_s{B$a2K3](&^ P@ԙ3g`&W|e;~Cvò\?` O]ҡ?! 4ddn aGT?f@d#cV ȑ#\Z5={+1t୚5k.UTۧOTנ~}{"]?;~>fyͯ\߬/iwJSU[*u{R߫{ʿ}h?l ڸڍֳ%o 5mߖpjْGvߥ5~}La}v_6{?[<^uqyz`|T-.Z0<KS nC\:%p.Dg5z#x8/ÕB:[Ltt͛7gE5 kMj2C:tH u O_qx0da#/V|ז|hK;Um?n5[۔/ve[헩Pɖk8.ҕ-x^z0$KW|w<ϿW^6_*oxS\7d SL'"N#CVLsnzGK']B Bk H9r95+ܭsX=AV< #o խ[W^\v}pP#1M=#DdY_w0CW_}eRlYEޡ{%1啗I!+eYH!_cqεH *[ >GU/=Q4*gVW5z5w s^W˗/ottm9Yrê!F+18 Uōt3OCY?$#݋/װz]$t~C8gV^x>oJ.m&3yB: vҬ?tV>3+K/Ӧʇ$o4t3Ϙɳ00e2-^)7\/Af/^ZOnxx.aҁJ*evJdA/TA#fl٢XK QYDjo @!9LB:d';vX/'1~k/i,gYf",4m6jzoQ~Ľ=pLj#mZA: l`1魷rQ0Cސ`u A: uT@Ap Ͻ*TҡT0N#]yɒC]"y.hp Ey6Ao|+=w[LRZc逘!Ҭ?<ҩ/J#oHu {}!.Az t[DG`3 uZf 2bZ'1Fm#FCq, ӧk!O`G ˿RNիc`&y>0Ͱjժ铘`J!R6#0  Tsf@ }^:3c893S>A:H*tx5j`xj/K5 ~2Cg/C:ȣCyTzxO=} KnnE5E>~ tqfZ`\n/NP.x!쁏B:x[vOw # vM|"8uL2y鲳W5!ݱ 33p܃ ~?ĐN}td/ Oq&"oqt" C:Ayt  ʓN5^O!,9w皵bnLq 1\i?% _9#Hw-؀t4#6ll+deMX`HWq_-*D:'H)(4/^kVު7tٚBHܼft^x-#0ۊB Pwͥa+gΜb+Vd3zgLbO\|g-T m=(Z 07l_%ZtoL_koWz4vW>C4ѧؽaO:v&dq:o`786a+W.YFi&:jTo3+Cj 1aP( qٳQtұ^c;$ a*4ftYȐK}X mr ohS:'a$֥UG:(gSE;\y@i@".Ps[ODNt.7N@H4b9̗cVHX;w.t1u ΆGb+ kFܕk6l޼eek7Xș6rn3fnjlRM/qʻגրD:^_ CEx0ioV:It!y^9t,!e+ϟnk}g!YY /y׼e7%oGj@ΥAuKH=mVQv{՗R h H*̱tH&C.YW_`6-Ͼn\o.Ԁa0MJ Bt|n߾+Qt`@z3sv\8[zi7䋉[26%M|~d/)b6J}k4?Rep"d!iPf J."O2͂rt9?H AG:> 3\stl=on+anP|zH'>4ڒ,4Yf欶s!bZۛHf} xnC|3yo8Z_ۡ؍{-|-HeZ\yvs̵SH[ӧ0%>O`~n9}OG,;xrm q% -muֵI+(ד\kѾ5@M ,ڡ_= 'ִ, b]s;|+23&W&"AMAS3kt K^mZTȕ_gXu䛏&"ث@৴;ZZsQ`"h˿fSl:yN<4HE!\A: Ͽ핁κO,Yy4=[˃on#b&(Ԉ၂wF,j%.DT>ɛsՁSf8$Dh|qs} MDhAg -s=l"K H* V/۱c\p!; ӨtD1DK|嗘'a- tg $Ю ՕnH{|Sgœv֝㗯cBa0EL0^-~.UO 'gEks)n((גHE787w8ywmt~ٺ} brܩ<$a.Wh`Bg+O]1{u?V1>f>+BLgO O~! tL~l3;)ҾD{e'#oAѭsή]v VdH`Y/Bc>Ř]LzӋw&c=tݻukۦ59`СGfJѣM6HRtԇq>|#XilXA0O]f(F)_IN0f0l(ʍ_l2ȹ֝DuL?Ȁu`SvgF47d2ww fo/̧]HJW8?|v3B.]ä+L/:=?l6X M!28&ЈK@,x9a|2{-l"9x6DL8vaQt`Q0yXfdh$ϟ/ǀaob ^M2gN[ I(рP|$@2Wx!+zk!qB-E<K19t7fkš`7 f͚6ag @B~o?B 8מvۊm1ccGk|0] N[h>u id0! f̷ F0<6}çS.aDC`km d,DH%hvᷨD(y?>EjtR9^F:8U5qH׶!b Ng ;ii _f W ֭=} 麬ww;bޚǺ-'䝇tJ+GwH$+ڥ;aRIF O+@ 稂:A+pO\!`94x`OJg(tD6 2@]yj?y=/"E0D: C+%4el۸3fCrsқ wBG 'J)ddxD$βR5b9 /+DYJWF ~;"~I7^]߁fJu#Sv3z؊Fo?|߯_-if@&sTlCpU0+@5bqu/؀0`2\HAS+FzH kyWBЂaB+Rub"2h;w0 [A^5 j@r𥊨NDH>KuuQE|";E] +,XS]=cW&YW$rPDđMI=T"Ay&0K_ƍ8 h V: ?PB:HD||XWA:tӴ%Q3b &zV>bphjVXEG uNoq;\d2y穮>~F F&y7x_l;T`hϿ6m”B¼dk,޲d<זr[?ZG bcc5HWn]3kB9Q|"{mK*"+cLkϦ͵Cg}pCM'fhW&vC8V0F ;nh^y>U{"ϒs H+~$bT:V4nTSxM7nK2G:lXu&CDu{n#$>+.]/6x ݴLl<Ճt>\|9#{0IHԎ\y鐾W_uDvuV۵6_=o4Cu|"ݎWIA˷_Ր0+KvHrPPG,<|HnE@&!K-2ώgk;qur\4vVު7tٚBHLgnrF0%ȮG[ի6*`8̙39tQ/ϕHD:%}q_!6|"g7# #+\G(g27nʞc{GC{"faVLܼtE<;)4􋐩Q^Hj dHAzӎcforUifn|"/@v55@HҺvp 0x = s g,n7"{={%O4L{0ry:,s;g>둎Z5ytFB:ȯjQs# FiW*Ν8ktwdltKP)xHYWuR#棾6as4uo_lxc\`bH5(XTS;- {cgNHTj? %V=~ :\ND lf%V  :u*q XM΂;m@ k@}(RC <~ ;ėY|D / |K&5ɡ(2,Fa(?uH kz? ts餁.ry( zNH@odӔtgϞ].k׮E㮈W~sKLH's."[I}_!8ySהJۯ^3 xEJ0$i*=PWM5QuK1D:IH^<0ɃtȋTRҟa5\X@KTyp*֊`M!oC_ZA;%(P۽o<)됆> 4HczZ_ĬJ9TG#mAQE| tzz 5%@۴iSXUΟ?BǏ#&Zm%.jnC]w=0;a]1._t S@B:, ؓJ1آ,Uؙ /8^5e%o95{^iH{'?D:8cԈF2Eúim)e|1`Ɂ>ASب C5y阛ՓYML&{d_j!tʱca̰F,yx ݶ\"۲e B{#F`eeX o +LA!>w%#,XP]TrQE&j;D *jvZ*ODMxv2Y^}ꝋ|SkJ$"a9D֟TQѥA:a" + yX]-@2,,֒kt7}l"`sP2c!f AH9 -~CFuZ# ŋ Xpɒ%v.\l2T; "Yb #84@HfE` AL0\Zr<Ѐ{(a3T)T,T @`0afeGeS{of8`RFkv|fOv{dኅno:Z]2y`S57‡ L oh$͛' ,sjW^|ʱc':={oܴuժuIs| J ҁ켐f͚P[E7^bի'C.o7USWTx1|"*x3W^sw EGpJVipSRvxa3X@B&f1yTsOc4 Kaqš3%Yp wz"} atN2cʷ ]~{;u&k7 Y܆W7W,Ӈ|I◳&C:5gM .:|t߾vݶm׆ [رK"]'Rk71̌d9H XǑy~y4ٵ!NB ) :p8q! 9rl؃L_~h"CDv( vmY?xN"lPj 4@HWZ5c+]5P" K!^P;%l0rk0ήINʤFSWn -R86l{δZj aEl.` ;4堄vU"]dRa >2"^9 R{`+*4wQ(eWo2Qx< Nhb+"F"]KRQB:`1a/!J"R /Yo #Dq&35~wݻ?h|&"mK~ϴV.H]i()H"@U.w\D26`zYO +1C^XX<6eǔJ6Ffyu"7ȵ 4HFͨ)oDj l5:SVH/=}>m7&8eK9;vb z! }*<7gaՋJd|pC`Ht{H' v> m;pN#s\>pJdWG|a; ʎI D1CWxdaXX֭[`U+TAa!O7jyO?z~^yK?j=]Sh_/s VHGILPC2[CU`{VwztnV>rڔrjn|Ar0ν6K뇼İ!E1H,w#ˁwal;q{D i 0_m0gHŒT7< $fCB#Y|ݴu)qf=q V"R?)V9Q3z HGT't-7oִi./߂tG9n呎N"C9R !{ocݔ56.]oWĮy4&ugJ{i]9o Ȋ\˧ 2b [߹D‚5咬Ӥ[7"GfIpuF D ;#)Ɂo =Mƞ rr$"Fn6$e)C`tidCD a`p@)yS6?ͷ1ґnݦmv0{㕫WWAm'!Bb߾ / y>GJ0]*Qٹ  r,p,M߬pP7J JZr d3F:fV:X"0\EuhlIu焨N5 Rݨ{vw§|#T9Fc|R2!Bx_H jȚEBڣ` $ńB?vM,Be}C!o$@FߟVlnW1=HN`.֝<6?-緝tF:?ya۱tvSih>̢;zU+MMsg?@MZuY\fH7}i1Z}3D: |tK o hTeR N"]!m@\hp&e&/oՌv#1H0RWHMmwMYSD +ȸWYGv PDK:s1m#8Zol7sט {"e?lr3BP)o< # F??Hy@zˡaC]ݫœy P#ݶP~Jƭ'Gܩӧ}%1QMVƏ6̨30qEeI-k&tN vKoD#b'iPzhhqݿ.=p>DAH R&Z<̄=gV^݆9E0@Ь@6eΣTY [ VS!i2!"ĺ`ooq:a$9|*ݠeyםSzX {Vh;H $Ik~D]Ez' A].qb?läݱG7{ssԕ5y$O,,5D^uf}EdFAQHLmNz-ζϷXC4T9[_餕. H%nѢE ;z("X2<"x#eNX=ؤ^.8a HuKٝtN^SJ@;o(X0Qd,1` g4#XW9u^YX:tx4 /6k4uζiM: u¯YWe${%.N[0tv4Wp0 X]P2c?6);0kNqS@$rQAlmLA@7Kbâ$+ 2ж+տvIGʕ.Qc6A1S/Oҝ|ڇlzki9Jlf'>zXL^hjiA"]KRB:uI Y+~ÿc8Gz'[O HUҵ31IN}j՘g]`l}5 P, \L ]2;%_o_LLv/Л1~_Oj빘 #İ}s})|| &.N[0C:FuJV:\ 0|@ `6~+ɨ'הAܻw6I҆pR-8)=tiBi_y袐ۧD0 e"K1<ⷝ^^|* pl2l?j#< }gdzUJ sM'2HtF"]dRaP't9lô9g y AdH<;)4ˈ*.>69az(>UaQ+ta8@.I D֭ ".Ǒ8]+_> Vr\,*WnT$҅F4uvގAxڧ\X4 x7"5 5L?sF#`]Kozy%c)>Ddĸ<{' ŏ[H>BqxE$lð„6#..g1ݻiiionܸy˗\pܵkm6lؒvǎ]))/^_&_~*c,h*t0ԑNZrJqo:qwXN#q,m.]p'Ag7+.a&•KmK@Ҁ5-^^z$B`w}GMut4ͲOQ`J|Fx%i[eٲelbC"]J H5rh,Du!+%G/G~S,NĂKoWn]8X[ĵ .'3 "k@V:5;sG\}N| Lw"Dtæm".#wC:^*N"]r+ghBMn)y_A=yt~(-N6tʒax{*ƨBJHҀD:{>P:^j vgAN#5,ڡ_= l[џٰytK rP b\'Ŋ}:'l 17I %dRA!]JeZjwY`)E"3ϢOF"#)F|q Ϳ>DDxo&[8ҥ6y<&b*xg .ݎ\ (H%D$I+]Y [D{5\Vyv=]]B"_վclؔC&ŌlZ QQ OE&\~DXp-v a%R%N*jr1A7JpXꤕFGi .T)7Ըom\-0l94HWׄ'<Ñss uM۩3fG;a)CvJ&cd~0lW>ZxktDt^chqz^~ՅJYMUJoS&)DWji҂{,wS.kp^޷kGj G4XȐWrj@::t.JlU,iz &BteG/@fql7ۧ$_=9j>{gm'pBqg8!:wZsl9}/^;5"Dek7R]Ȑc=/K;I̧CHNmm7X_G:Yu +Tr@+Iuaqc:tQj8 +'~wƍ۩OJ=&hv! C8#"]c7tsHcy¤R`8`|j!]قԀԀO B::t5p+]I-z @T ꚖI_dFA3A?mAT̯_86fot&:PsLwjF4&\ g Ҍ:>c4t:>}Ӗ] a@r$x~A,|9"&'OB~}iE(#JJBRbbzt?(G5H6>@xmJcæ=řI`8 C\=v͸{^?y3ɆgSo.'LLAeڃ$#=ƫ!O )ǟ-6Ќ)ww25NyGRaHCI+?&:eUs&O Oq0P36Hw_\N2Jf0859x:>f`DzE:~Jm`]T,-#JcqԬ V?<0pk;9~[~eߺ~.\˅[E5g/;wb_\L~:T{d%"\KIobϪ#H?s8& sxnÊ KdSWnC}*!vJ:tqHbR t[wEO&-!C.KEqHí@5 N"g` t9aksҁoV9oǶ:bBUM٢Z".;?'\?3܈o呎KD `WqV-љ)[GiNՋ2q\  <`9/eҡ'q%#V@zv.{$J@&8F"]Nپ@j@{%tJk8^Ի66®LGtM[ؙS_fk'mN|ưO14 Vm\@ ?HY ?K_ RN%2l?o5""C}7.ZT}1}9]G.ǨN*䥼ۛEvb{{M98~f:6 3_վQ0"\pSSjg qP >W"]KRր]IHHAu<wu4ݵ&:9s!ʚvCM(ҽ++>d.羻#N,6)doWKƮ\؃a5!c7*>Px3-&=YtMEvϐ.op˶!=!Ѽ5z]g..tHrBU0_ӼT=x8Cu^o##(T 6i Vl[Tq.S-X:dޒo7߱=vP!ݱcvr.]pD=v7k^^M$nɗ]:f6 =H('mTtq_y~hpE6u܃+Y a:Y4\ ZX=ۆ9ś[,tZp\ c!q %#Z;Ap=\17`/dLZtc!.=eĔٚe[li `aOJ"]KRրD:9.2X-JowKؠ@1m00 5FKN q/dt8,a,\Ѧ  5Y, / "!+zVTwn_@i+ {Xą]=dsc }@65_tb[H×ݠ9Kٚg$.cl_j 5 N"D:mcy/<8%1a B =S ҕ4 װMЈ>a?|8q] q!AnN ՟ ;ƐذUO6떿̢ ںBRV#*Jg=FHW0'R:nJ3uҥ%҅p+$5l tܯ ,(QD4ڢys[?FX:^x -l?+:E#vL|4v&b5Lt,`tH}~n:U#ϬtW4z0&`I.\m!]/SO Jk`ċ!z\HEnvta8.I [$E>6L]ji_U_ 3'jҴ?ujet8lhEfx>xUTÕ逘g^)jHj Uo ҡ@`Aʂ!`a" 1@C$!H7 fz+$=JȇلJΣ4sʞc$)1`[B="],5`Q޲8m39ٌbzbe:x',biҏ~$ +# fHG ]YDAƾWt;eRagܯ t6Ihy8yi[/rڕJ!F`U-0k`#]]-?{7m>ZYOajδI ;#vb-̻"AA& H `Gd'pQdݲ6'YF ݯH'/Zi%:ƹH23ßH ?~x'ݸMFY{?N̓0ҫvSK1{n(0Yρ_e_ԥ9E(+Q>BuPr"kN"]KRրH!I VgMjoDD8!FY ``)G $wG{Au0\a?*0<>_|xX U/̴pb2B_-.d 6 Y,E !5qݠ?q-Y\KP. /O%kv&`z\a &HlKl ħ&]r sC Xlp_dK!f1aԵ6n,}&kN؍ݽ{7--}ݍ7^v .:|t߾vݶm׆ [ر+%5EeJ"42[ 9%ܣ`!]O? V[7"tAaa [H;oCWLC f(KHh kwK`0óK@5q>DlUB[ GwK䰮CN^a^/[xGS#D3;$&@~;r2;?Ԧ|H7a|X c劙p€WS<{*ҷΝ'$A?UԭʤRLlémZmTr=#~HDm(b#,a6te'M +/K22eFh8eu͆MoTxCܩAkРVwY Q`9NGX#` Hx;Dt&0tXaH#X5U\-ݼhqXw-} 9m̍C6R n6ۨD]im!2X qsWa jmK'Hm<;ľT~giV1D۰ysXXº)tsDw5 t/H':N:^x֨N:MsDp@WE+Rt+̣GJ,ώ?AH_G ċ}kmg3|)!Cj 4 t"o.^|%RioёD^`"]a#[tZQD! X ѯ/ۨpKϫ~(O) H;t ,"$I 6҅~,opgI ^$҅hFFE5q֭˨N:^ktD'D~PX`J|_>ȫK k@"Ƞ(ŜҀHgsSˈ ]fff:uIHH\͐mmԢBC"ݻbq"=:؎<]j 4 KmxR*&ɘP[Śo<{VHTyLL@,xoDڵk3H'..6@4.Σv .W`jЌ*Rj .BBd!LґHEog57ҽ.8~?C ժUW/VL57t"m2P06qa^4U 7ͻ\,'( "*TSJI1ewZTORasd4d;TFŢHn-p\n…5k$ 4"B6q!o:id #SEkmnA(52 D%t߫udo1yH bS\nJBs$%)Uխ9L9ǥ.Q̩tqT{cN$HWF :$E5dbs$_9R,z`@SLչ=ǎ8C: ǃC:ST3V:(Ne8$9ڥcNAl'5T$ڭիWՑNt0ԑNk:88T~g.=*ϮK ynn:C_uJ9tu% B:Lxb)t}.!پto5<fՑN"9iN ťnC̳BZԈٓ3tw|s/^uF6qݻiiionܸy˗\pܵkm6lؒvǎ]))/*k*ML1)W,Nv7m:WґM3JB5x] `NtzzV:g([骿.̅&5tqa+x(|ð7~x'{g3|d&/{&(Ua#8TN"]Nپ@j.ҁ JT/>rdI}RLqUɿmMERQWc^^:ta8.I [mQ%ŰO6Q]wnWKZB0:KH D$q&R-**YNsO ~fh B:tEw`EwP- b%4KPj XHErdDۆH^\ w'.ZahґJ5_YkD;^ـ?< r n#h!Mz@vg VSZ ~,djF褐1ZvR !ݠ]:RjB3:ʫH D"Nt:@: U>x~'nPzӼ[JY,Hg?:S׏y{:w9&GںhD ka4hXM{3֎fUro6_> |(r.]čRA@nʕ |-_|ժU_t5kоP+"ov{cE"ѯfo;?ުl q jHm@Suш M :{nZZ۷7n^z+.\:t}wڻmۮ dgݱcWJjŋ10PJSXCNp*٬ԀԀb]aeeeˢE@]+!Qc#Gƪm2CcڪA?\7qM4&~.3 h 8%=_DB)#5p {ǫDp ÿ?JE%Ð\ OYnC?ܠ9R ~QTQ0<[t^I$҅?B]z}f1v yGVxlŃ9@H>,+_xN*w1$dQ"reG +]O"ݱPK Dl!Aa"t\Ú7 ̬oٛl?5h/:ktQ0<[tJkq05V}jv6* eHx$+ڹG35hVϽ[͑t9쎅R^j 4(լYSZ2αvpd2bRE@r,Nѳg5p/W䔡~^Z` 5$I+]Xlj Z+81"A]+ jP7+:s&T'tNҀ-Xf̥\:uJ \ SYO|ڗFsn:,gHu"h]pJ QDCG \X!xd I}rj{5-^3#e;RA\N"] t!ʙLt>C6\=4z&jZn5k{튼|ZU$EР+*5< #:5^*N"]Blv6<lUOȇG W] 5jPctC]0K.ͭŧǏ'9S:wKh&.xlYj r5` @u(H,Q vZozO>;;{ƍhNw rJL=>m%O3k- #j6X #(џkz\]Jo#݈n6O>[t57< ּs&"wЕ=BǏ3+D:x.ĩA9@4)PW̖4MoÒY p`yzm)^4OɈpaY1"ZQH^\ KQlٳ?)5mؠ$TlO ҢrARZHWK-vJ7hN 1Fu9O3؁`MUj؃HPtQMD_u{ZUtÓZ&thұ]v ݰ/!ȷ$+wFu֍7ϟp̹ӧϜ8qzϞkwؕrE oAiqh߉vjJR!A[h`ƌCSR,9rM`b' ?Mtvr R?)V HKi+\teq67VLW& DG/kIAzumUI÷Ƶ6 呝N<<Ν_*S&MQMNJ€|B&ފ5ɏat6F.*TL]1藃 f͚+Wߴmᒕlr*v␀ndb*WS9喬\se ^^!w}G`E%Q= "]*Uh"\:8^JG:JrJL,˗/_j0/]N,u(_OSłmCʂ:q"ݻ* wb^Wekjل&H޽{7--m5qcs|n޼9fH>YQ B({LV.\`7lܶ{=6n]jݥ˗qP& ]RLM,r}{Qŏڕ_8b%TwAQϻ-o| 3cT T#ݒ%K X/^l2AaٕGVX%)ր'B8:Y^VäMG~`jc =_<҅ábQc_Q mx6*c5QVmQysZP[f6te[rM/+,,$N]VP}UIY,T_a5ط}}=~r{!i&-vdBEV"].kGO~å_lM[Y_.!|;zCx?;VCM2ɈW[ʹt T v<36s0.-gzz]pCja҂T\;s&)e$SQ%@FSkg䶼ߔ׶N4J)nTUYض@:C`\FmȱgΜp·^عk7AgoS|J {杆I~oß8(}RSxQ x~t4N^hUygT-#ծ]^exD;=xWFdڬ$D"ѯ9؇`_:_yc?=ϡ{fG "U5@+4{ؘJ ,Bv%\E ɸVYenUs$QAIгt< `ڵkׯ_?GŶұkPX ][R{A5jן*c=.mLx=GӐ;+|eT'.YD>a(x_.1@fcl9ϫ""2#sqd^ᚧ㈂jw$-?购Y# 3H1M)~ ]H12Up\Hjt HIM;v؎]{?HH2@U_%'EtQh/ktݺvEDQٰaî]r23@+3iL9 f"4&!Ŧe!K蓘GTmebTsd\:FHwիאGMtBg۵Y2=qB:? 20Ϟ iqcTg`H,  ZIU= 4AB:yЌ".Ix;QqV@n 0ѡTÞa;3@cyA-_.^[HGTtuQV:?H !f29зYEET=#۲@ ՙ!q .:|t߾vݶm׆ [r*p !j@p!.5n"8h*rO$~v9Wa`%#I'z+s c `_*8@0{j*WNatA׀]Nkc:is wd˛0ҩ# ۂ8A]=ީsXJZ}ٸUKWm޴5};L7ZLZT=["H QD:@'XHiIy}F\`}EHBʄBt.svYLܽS3kkѬޘa :c|J{̓'J D$"kuVn@0mu#߲7 ̬ar/#X#bm ݈{}ݛw' OŠ|;4Hţ55P't~ Y"r^)بаϐ侶á3 p`G^Bm:ǛHwE }S/JSX4NC++kժUhxWQa#XV:L؏qvVx7~8ԉW HT# hgO}}JFo;KĆMhb޽{7-- +r8ɼtB,[.5@HWn]C[l ,K, C̮ŋ8Q"BR4Σ ǹ^n3X?ytv9`uKJoGUP]nBw?tZ3KJc@.р8PG:/+K'jb.Dv{Ԧ)v3`yc3 L/ 88b `Xܢ[rꞨs.oSj׀-\x @u2<) 0_$uuĸA"ݻ( w͑;~R|ՕxpDu&80t KNq9VV`J׍Mp9%M.TgsrX.oYjt;/kzUZBN?cduĉԍ+t=:9PlQ`F]4-*mާv%U/ Ƴ}w'.v/4I{!#tk=I+qHPoRQrׯMV:K)&58 k25 u]nBxz֊%N 9"tHݖD (p ~]J15Pp|^u~")XC{plؾz*,SU}uZ7f#ފYvUNٱGxWҿN:TUUu۷=;wھ 7Y~˖\`I]Wĥ=t\u4RNR)S繵2eʬY?U@h޵_7g(U AuG.qLPq?9b؋`i~6z{1c@{iwe@@ӿNt~!|tD4 D Ν;={󃳯[p!?a^ @7m4᷾g PW=3B"-EMOtZXPH͓HG2@~; c+J,P& *ocɣ@m>rl[xr ٷ0ƦL{M+XH7^!̽=/"-܂t"eI(Y)xm ~R<@BC{ZG*cnHwJ$,w tt ZEfUh =@^ΛqE:LKy^57BkۖoI^k@}nƩXܨew&n yrĢ8_O:z `|W_5~߳eT H76ІQaaL"/9,K'.?&YDq!VG:В){<YMU_ \*骋3y.{H'u^:~%ұ#8b= \Fc *e IA{1SC&6k֙GY{@kåɉS@= P @8HE:,֦MAFNPyFr5tՏEYhy>ڴ_hE:~ìeH'YDtn:'6Wævřr,{Hwk"H׾}{C*Aϡ;7teqyPtrt'.K fZ!^39^5hK9ҙ^(旇tn-Jߖ-[ 5{aCK?9p@ӧ﫿]ybP ~H'#EL2'4ȱt&,Pc5Lsl3A9Lt:3z#+bd9?84iKgD:Iu+*ky`.<'mܭK?4yJ޺ *$ trkeLH͇ D1<`gtt#9xuz1ָ{Uߓ[^N5ʣD: +0X !Xt 5ؚucQt 2̮~ݪs4zⰵ5XtĒ]Ήt.-֥ !xh)(ݖHN^:8OK7aKY&]*`ְnjkk#J?9.,@8 4(ܙMa^E%Ū4BSVN`ӧ+vk3gD>0 U]"k?7UݴӊˣY?.^|%|! uzС8p`߾wٹsnظi͚+W^lK._rP;vQ!ݫKijfG0nν 6 D f̘1_9M6N|[Za#]scvoAjj귎 { M|^/B@:H/4igvnhy`C#bωmoq/] V>_daɝ E;d@PDb,.\P]Fݫ<#XKgܰǐBQG:^g\W:\Dw,?D^{d; 8YZb#]Jל]/Dhv,"w-Ry<]rB1pVg;DC Žd@4PG:^E5c,NR~|&M4uTeYn'L0}tֻfEy]:R#;z1y.e!DNsE ךߗκ:'"@H:tطo{vܵ}6nZfʕ-[`˗T9hǎ%nl͖`~E ωe˖-Z?|C3g.PN/Ι35pVQ 8Nt؝,2sm,K׷ ! uJ+դHww:!pq_9^ QNOX\αtkaD_g2Tj8#f9(-%"{z*P$ t:"]{_,8&pm:xŗr:UBnDlyOؚA*tQgxW"]z v#ω˛vIK׫33roK3GNǞ6'_ H"]uhYbH-; s[ꠦn)]K<dwZ7ptlM6bPܹsϳgϞ?~puuu .DqKjyÑsN ,6HIs*> `RHg[3|tQ_HW0, Xy/}PHtतUʚ lPSm˵m_'=|eIʴ0ТZҁW]kږYdv1z,@ E:8 u9w{xp3 +,g(ZB'#viwWEMtuR|-RQaΔU$UE>8[:Xfnҙ+3T_=H׾}{HD:"|3 {rso '҉ Ɉtip \jBls%=pz9XOŸ89\p.F*Csy ~Hkސ^{$wY"D, Y͒"eO3rH)ޱp6"] ixb$^^z(]qA 0j ҥ㞦l*+jfG6K^-2LbWEW~e5kިW5WuH!:JrXNmzDz֔k*ԲKg3=M*,B_@uD!]#?׈fS "=@㏇Wp ||Ȅй7tKc.z`^[[17ZFY"4KOLEFfDbA:8[?Hu172H 'f/ 鰅W8HkP3U> D:_6fBP_#TMl`.;lSX"b3+tk$j@H:tطo{vܵ}6nZfʕ-[`˗T9hǎ6֎HCLIEL-T@MNRYf-RNx̙3G|[ӧϛ7jGB#VDqKLވnkή{Q) t)}9r*;wR4{+/ukuzD ]C43@{t -]un鳝4,H wgPN8ꔼtD:IJs`i灹NWCuiq<)@+žU(/ҁtKw'=gc|K׷w. |ۘ (BrG:L]TDHפkeS#]ňҥX O+žU( }ňtqFXR.Pk.$ҷ1*P 鲯K2RvU HWﱧ5ytETB:+k~ɃwHx#&I̹ENE>ΗP"TGTGy~@l==߱=0ҵ~kSн/NƇvn_=ߋOXq̣: WuֽusT7xߴ08PQǦ.?TtBҍ?qϾ+ 3Ꮈ/n`,zVDhW ẗa&=c?="4;6+1F/yۑ _k>މU?\//]ڶ = 3fӗ{h|ؘq3 vgIDATxov{@C 36w=?q=2yknGQ]do3-}lcU!!mp̨w>Z⾸]T8Zhf9נܙI4lSιza|^AS  C_kusWnE>~#Oo|f&}ӧ{Z>0ekg}~->zMz/,`ޮ}>yd~Lgm : &<{m:|{?ʆ3py _Io=VJ{ֈH;X'H&}R*_5'Y}[~cC /;Nuv g}( ?Fx>] w<^,Xիf.( T(MX܇{d-f?]3x >7ݏ S(Ioz֣=/?JXA#kF ) Wt^Аcpkq CkD[ .G)ˉt,B/ELHM T9"x.>6ګ  sȝ@B/U0HjG_t諯H G 6 *e^'Sb<Dl{Jà7!»爢VocUs+sF:ܻ;ip>pB|w0k`E}~jċ vX1[ 閽UvOy)Zkv~zw箲(z. .K~j%Ql"y*Tsta;KwO"bqu઄sJkhVH<$9+z7pz&k80AL\8 $WƓ`/x'̊8}ֿȬ? Vq-[4j* Tyq@-\n/ ?koiCLzŰ? ^CLC8vFrH0%4-{AÊF7 O<,wK@'^xArtPL9رt^Q/tâa? pj _n9凗WP_&*WuA΁m8?z,l lzԴ$ ))_^2-l3W;$hR%r8"ϥȵT^!n'Q^Os&|Nn] fCĦQæJ4g@5h2Oud'[ =" ,i(fv~]yדu}@S^v&[*iM+\SH=ny\!HM/]4jJ"]ojԽy6Ô0I x,YA_yz]4(d3wM/,3 \ȓ!VЉ77EpRAvtYA !鰽) pGlɚ?^=ܴu_ӨhKtD^6+#,5/ᬓWPstuhsJ. Z0pČ)A:m ,I -Q$06˚I@M>MTiͻ?2=vTpN3L8N;KZ9"Ĉی\Ϙ XDtIwfB1ʡ$M0ar4it#fsG:jh]xL1Leu]Ιclj;뇎" /NO6Xrva *r<(Y̿Sׇ=qk&S0lCUUU΃1@9)CPG"}HVNgL1ВTh>⡪?K8¿͙3gr5kּy͗wޑ` t̙0J\@.lx#kU-=XRu?blY6u[Ùv;(hW+SލO2 ?-y=]x*GE,qԊ#h Y~u3sbXLD Ba9۞At%C~:H׬wkNiY@+pˠQ,Sti,XTpU;2@R-5stф`JtN# |lk4q5vP(goH4Nl|..6T5b7 g_r { \;%GӘ H/Z|Ὺ w$ Zq"hjE i`-b#K%gC¡2(24<T<*pr`s+tHf^׌tcOܿJSw}qw.6/c  _J 䤄fPW6[9\PW6GnHW5{/Myy麉78szd(m}>c]H$u ~uBV#>zHgݻs#vO[qժ˗d[/1sv4G {vdݜ}L#uy)Kb.xfjH'Ck5P\S[pyYN_`Lf|0l\n4cϑ*xy^; &t83q[S($x=Jc/}h@ܷ#d|UMYmKַv%^5sg-?pe3V1 .۹r=q׽!oJEa@ :u*DP+!]/Wk;pmp62*i D}[gᮃ_`xm߁+6,?ܳЬ,Sv }n{?Ic!5<}VqL]͢>iY$ QJ~r=p=S|z2TaƆa*7`r q+^o$SY/mXnpwTbt7ߊٱސA m۶k׮=w^eoDx,mQ)@ B X.8$RvzDyN5q3j~gǞ}Uc;?9Tw7O=ڽSnݧ%*?g '?'h@3Z= H%,9jtWVnjI=2_bbJYQ 7 w,OnF@HK#etEͳţ.T fjH_m8M=0mB 2#Êt]VY\x^ɮ~8++耗N 톍NշuUG,]<5c)6(K'oi{T;t桲i8t7ބK5x4ZtF.^ EnOMt|ݐ?G]^+k"HW<}'8&sCbWvuܺ#Cͷ W*'v,X%`􊭚H 3}10 SFq>g(U,},2$Hws 銧gMJ"] #݈bIcb2XS`óp@D@!CwtG_@!\ާ;2*7x\| :1쨹W4~;;MkЊ~V_C 83O1NX b!iE~Z1C_"['Q]j*HK4}HתlꤗnyVx͙3gr5kּy͗wޡTtn 4c9g lr518/&iI9Cڇ>s{ݝ{1N 53kҁ}X_-ݸc7NYg`fC[ Ho12 @??U8gq0lݶMҳYQwTHr9ЉL0c "H]:z~, tt8x&" jw7 Hy`_[{m+Otc;8-&+*t="(γG:'fK}Z `.s2;=ѫ @gB#֤Qe6}0Y`0 |Á0 'M3ko,[+a,:s쭊>94}SOoR਎~FO_7-Zeʁ9I_W* k\HUTv*ר&] sKX&7TRK110䅰DSBP d%g7?( 銪geG"]Pp|K?p +wbYg3$r \7!4P Pd Uˁu[0nYbؾ؄ ga4(?_`P̨5˭+6yY8]"xxִ ?81>0O" _W3LUI¯"«ak7f\9Y|7RXo.[Hb(W!wX;b\o=W|a޽9'DYQH]%ІAù@jp.o1f-.&+`wgX|E:CGŚjX{9ep%Gx[#phjÍtdzE./MsE]q/kVmSY~U&D:,`juW`w +Jupsw4%bn?\2`,vKS#`yGv|J9sXCǭ|+/U3w`~=nO(U_˔@( % Qp1q\%데4X$%%|h Y=銪geG"]Pt|tP `:kx|\3x$O?|'zOo qL,3-1zB¢5bnE8@c:-j$G}>cԑ |,,=UR?ȨUV @I_{!͚!%nj ;JCz nXTkctV{ FX-#/ų2;fl@+>5-*tyAnJнe`0{njWc{{a[V'{n+˱|.KiL\cӈvg@`vP7;L`ISߺ@X@"er;^Aۧxb1lm bYEv0xp|3æ143:9 gN  *Rl0j:8B0 ^bcmh cx@UTPK̷Wl H!c::ҁ_\HvB銧gMJ"]^+T:{6ڌ-ͷF v XſZu;Cׂ.mC >aQS/`t An/p>`TF)Di㴰AN:`Ugt;0D؁H' ?1(ۼXY z<8mWݓuy3`TJ)BOIH ͺuY2F* bU>n2(RWfDYQH]%_"MHͷ"?AŁyߜ->cNpa clZpIcxXLpLzq~1/kE`El숩j4xN5HD9n l"XY+ pVTOXan1u>kƊ-tf "R;qd]S4 OYϖSD:l>ܳ_q 'OϚAٳg/VNuuusU6_ z(/D Ѩ[zE4Wc n0.$Ya`^^V9@h< /,)sh d V%@FXb̟'c#l}jb8Ԩ@>#Fzɓ/{] (;햏#J ƂvY1qU901%!Qy-FC0%`<=z;]B:ayx+`B~.-x{c#E(.]dMw ]?y!ߔHW=qhj8?rkhT o_t91a?SMP$,. d_z֑,s?tCљ)1)Wtf5- @:~^ty銹ͻ>VM/1(?#F:t~!n tG pMt dKAsoqbҭOU?>W'WW'iKN2]sI]R||X'o>JC_sB#ҩ+ D lIKW ozdi%3o͟aҾّO:ջ/ &@8vz wwt571Uore7?]ٟ_v+K~kig;؋^lÅi*3UKse֝U.w~y 2Nh,-A*?^j:C˒ wS޶UʢvtSL3^#x=sN{0=yѴqqoePK54.i‚a~]3p}bWE!9C@.Hwɥ|oNtN(pVlA,2H=Hq.VvhtP]{*=M=SN G g(Oq[^:5RiݪUHaLj]+ pg넙]x(]w߳ /hv_p"'.0h)/ÕA"o ˃Wx|X^kxnqV[n]Ez~=iFOLMHڋ9hg ^9s=ՅtAT(5(l{e^,^ఊ ߨ.D&M> K/=Kt { 1X hߛ"'5ڗi7Q ~R Wt󟙏_Ⲳ$;{XJ{ttO97)H^agZ_ve^"ѻ[g"ҁ Q~Hq a/T!(ߜlfӟdygAe/R!؛h]!9/=S>,x=ecS^:uYf{ȇ%ʃTV`opRT#kNSY)HWVRҲ0͟QyOK[H#94T:=ҁfZr8ioVt1:e"/zǯ磮(K'zqڴ9`t? @D: A{`otoժt#ӟ7#Q$1~%-3͏cPf1Q *:l"n:w]t ri#ƖR5M3t9HNUثAx 3#/ٹPca3 Lg$IK\ki~L\Riz@M;g%CiN"fRR:y"Yx颌t~"4H7'MKj_CG&a. v6!9zMsE:'/;k*tVPWߦC:;3[솉@0LTK5s,]=3nQ`Xj[ec-<\NtJJL.819zڑpܣZi#iI"]zkđ[D*<^5 /]Fp<ʤ1^Х?&Yv8G/cROw-^ڠd4k[2#čQP>t^:Lt3sCڌ^kj=Q%\viܖ2%,Kt^^IIk~}u]r%]yv\u1g]zt9 -FW%W,'J$1H&'QʹSbGL biY TP`(5Makz %3< -? ҃0=p!jVW|҉uupDA6|0`KgZ{ 7 Щ$_9r >. FTʩ θ*]{뵴k,W_mtW^yUW]etor -ץ7|W\aF:܍7hIy+Y۵kܑd) 7 #h"X"p%ҁpSK{<u,rxX) W,W4$Ǎ${. B^0He`} ? ]很`Sc3?5>P jm0V{p&++;+R#ڰKh K w {.@_jXg`/QK#RHagKK \kg# &2&aWT*k.0x@*W"Õ(tK"=BaY"=zHЅtiÙ7B%YO&~3~I|bS b9#a{^h?jdG5<fi<|D:g|^:Ds-b /zUs#(hR<5 BȓHt2 F^y_9)Y)p_IԏI't?vKUy\?ts2OW'?>e֓^Y *D:H[1T 4tt D:"]jɡ@>*@+.(@#D\:B^K C".fEb0dւ .tcgyeڬLjq^L .S\٫$(KSfT1Q~ώni_8)ۣ0(+{TYbBRu@zaxrxysRϜbs0nKk@ڷoW*aw6m7RÆ~1cŋa ǖ,Yn"$(z D/Xcg챫nذۛ=q QYTY= Im/T w=zPd$ -8{]Z TܙQxbG]CvЇx/yWH!F=¹j<\jYL޲Ʀ,1àשV0L/]{, Pt;W2t饣N*@`ڴTeT D_".C K߿襋~R*@/]FOhL/]~{ez襣9៣?(*襣^EA"пURSH7X:N CܣDX#*PT k߾]e˖-Z?|2} *\ġcS&r"&Lv; 2kQ, dA;IP.C/aAs*u(tD:"}<(Nt9W^x{t)*+qt2Q*g$ OWz&tD:p2 P{N*+ zKT stKl1ΒWtZ^Âa^G 8YXxuЇELv2Q*g<"W?[1M:Naa4iw&NE[a6aucQLaT LkZ#qap]:q!X~01(|r;c(ł g&֬Yc0#e#O8="Fџ PPM#PO_ W^$e{ s]:G0 ",襣N*C/VnD;{iD]2cWǕoRIZXɓTHo>lO?ϲesm۶ =G xw1.;KG/tO˦Qt bᣗg1\#U璆dTFt [۰a:%7޽{Au9YDlaz)Wvq,^Q>N4}XogMljG;a8D@vt@7d2 ΣYȯ,Ŕ!ڧ)ک!S+aDαKWe!z+tD:zeo) ^ι!m<x]gJS"N.1])m}p"vF-eDխH$,5Au/S"!t{sz4ڤE^x uKe iR.QS_'WMJ/s P9KӗU; -t_K'p;sx81E 饓 * >K wnY}"ݙHDX7-!Cߣ5GdKxe=eĿ2a )9Mt.!D@dZ#kYH%TGSA B#<#֩gT 8!^:tD:*xQԾ0a1RsϲzƎA@|H'"i˖--Z(HGtfh1:f=@Y= _="c5ucQG)n'0SƁ6TUV/Ą64346°8k$ƣ&1,bkݺɉԪU.~<.]5KNTȂtwqҁX:tp(&@.EcG/M=D1vP1JۣǃPcSǓ' =qƀʢCLHnhA3CcS/ Vn7IЍGMb@:᥻znF_jNG ّNR8=# 2*R΍tiQ楆uW^AatYx*U=҉kFo'ҹ]#8=8G|'w[p _].kwH*wNPtn-t{ #>SLtN|W簈I3 H#tD:^xNUxHW]>_ dAn W~%tD:"T R!j9ЛptݩvŬ@vTG#tDh"r_C"sϺY[o%ҹQ#fwHW؝:kW 8!͛oIuX{8Y-^l͢EQǶu"jnb Yw*P dAoY T ]ph!]=-[S) nG̙ (+n&# SLpc{,e>0[~~) ZLhhhLT |INZt_S,rꇧ$*Ȑ[@:L{ TdU=c4裏ЃnݺU eyWmm- DS3Ftu׮]b~+ޥH=QD7(o[V.֡eł#J1TYJ#6$HxTVV&2אՔ *eTwDKÁ{ >T hb9L%"Bo Ү# 8@HIGRr `r.%8hԷ)cӵk:ͤsN\k:*;Jyӹ»zEMu4]2uP'qXt}Eu)cC@Ť@: aI#̄ל8!ĿQUUՁݣ=eY̗pX~(fe0c]Æ CdTRÿڟ {}BF:YuN H)y[kӰ Ik&${ 4g@:cMuTD:o(D:+/Ӿ-/ɮEiNV~>t{"ڮ];u<{kt2 كޔ /{1|xpF=Z s>َ?EtDJ(*xuւts )_e@:9ZɁdd f Ɋt˩t9q!*|: ]IeU:^)$9{ϝp ]tqDvٛS?塮bաs>k0nXQχBGo#ґ"@O>* ˗.<3{uRcm1F:ΈzU ݤT.)G:K{6mt 7C0aap ;㯸#F8 \JSS?C]ǻvo>`M;QχB?޶uGhEixڷoߩSX^ p2JeVAی>›A.g-l\ %Jrqe[x!hvi충),00s)+k2y^أXրt:#Is@:_N=Գ>[ncƌq@w7nZv=u t8-W] 7銜"^}tZ«W^yAuyA:|rÝxFz!5,H-kkV 38'gXݢF3pF=Z VXt[hD3MO E]v+FtXBavTxȂt]wNaL>#خm.U־J {z >`/QχB%K/\duD"gW_ ݽދj~ESԭtDl_w+mi1a~BW ; ˊtr̢p@:aZno/^6aʕ8-๹s J8y!@-Jݨ@ "K.nd޼EPy+^P`3gy{j"]3Sīux/*@)tQ7~xtrartXj.3f̚6ȏNY[;cʷtg"/^btt:^E@ dAk HG:AMrs^{ŋ`de+08ȯ/|2@,/J"&avKt g?e|r,qRD/8eo[**Ċtب.轫?S f,oA ieUT DD%W}#&*@Dt,WH P*@~Q( ;V`"el&sf/݇LT P*OtY *&*@D:QF".d P*U"]D:` D:^EU)>T S"(sQ#ҽDTHŠ*cT P8*@enT " w}E%oӦMv3^cT "T_<" P*@~Q(63Q*@@< Ef1 xD:dT G[=-[S9V|6XHZ1 в](o[RҪC9˒$2S*@+gC\L-; Kt{emm4$u;T[[(}&TΤOiN~=β*۪eG:*(UͷzV PnyN4NP]6ZHT S<#]y۲rFz\36]Z&2rspӭZ3LF<%fSSn YV;Uʎtv(P5?UVdVjoP'KtT tJ84M3tK`.Psfїۛ91͎IT+=F 2dT-$GSږN:4Meqm3FHnQALJ,x|^Ţxim t5VU^}jiOVԶeRV|:ڳ;h#u$2?~<oAxl`T Px*/%:]0WD$I`D:݊܁JQm. Lg2涴MgYk&iRMK/Yby$P.۪i#2#HQj&O>C5 p 9ᄖMp^^mUtDxYj*@>#I_A zOLcJz5N9%FW,F9H0.w2)K^ye Ϝ&MOBKAj{cCI{ \N03R_xDLY OWp=K$YvH P*@⩀HCHύJn3Ȟ?M&s.c6:ؚEMUۖ1A s3MbyHg9iW?P/״j "˦tuLT P*OF:AH(+x2vZK7,/s{NOPGOOYDI#ZvӪe-c4?h[_5IH[V|`1vS>b.Èt)cUlTVI~+ױt`fpҙn-T S.kRO3!Kɗd %IOU5$%'p3Y4UsA?:*y/nxJjzDr:'Oi%;„t *cvZڷzyKmw0uҤIU=^f tnKúoAx,eT Px*@+,6<"&*@DbY"Q#-fT Px*@+,6vm7B#DU$}51 P*@銭g}DH P*@H:xVH'uJ^LT P*OtӳEnĉ9T T *iʱ5N|FmJ*JZvD7c9^F91 7jr;kݴCcrV HS=RS*@!~W-o C\V^3$>[WȎX"@S=Y҆uZuL c5\Hꤋ!N7}; * D>Vw&¸ۡƠC:OM&Rkϖ*Atr ۼyݺt|T P*0zV!w9zWNąo2vYڷu9]iLڏr?fND]HwZ84((ޟEsf27: Uj:eqژ1Z^)tٚE"kO k'D:Iui/aT Px* .KgݧKKoC!W1zIveA^GѹuClP޳t4˨e8lv~(H fNҟQBW fp\IJY /7 I f3Q*@@<t 1K'bvY^CZe-Ҵ!m~զyUI]Qw3b^&|rN.L7)̀czmbbkY0ť[pmKN4S2x"Cx#771b~)L9-/V^ &$e dlT Sܐ.5E˘ը <] ?]QyK7rn-1="Inzqâ$qNTCPL m&Z5pV۴,p{w<#YxNXU%zKhlf}941$f=̘kP^ 2֝ ojJYb!@nHw3KMpHj>)c>84-:I)/RzT䥫cT Px*@S<efbDZ OU'XlUJ"p!Y ?} `&T S"]7EBS@ ݍ7Tt3T Bby#*@ :,]ҢEO?g=RS*@ "],EBS@tl'әT Bby#*ڵk'uJH7 P*@.^) NRMeT Px*@ 卨@ `9 :"]<_,5T@M"],EBSHIAuJHWDTHZQ0^:wH7 P*@.^) SMfT Px*@ 卨@ sH'b;"&w *@D0{Yދ lJ(.tuStQG/]qc`E"],EBS@t,N_xk@)pwvq?{h./~w[ju-/?}g yoӥ?q`DкXވ @u6mJ*`HW H* ;gǽ{>tXA?lyI׸D:~]믯<}ey/*D:Yo֭[[Ns .< W:cW_}cNR-sTHZQ0 y `@EGtLLEX%j{j/-iX/1ώsOܲe˷~ oƿ3"XN(;2ϣtUey/*D:"])p$ʤF0Dhw)ZySXqfkiEf팷Ǿ0){%nѿ 3ceʥS_%>tRZǏ=}H%|IN~9D`O?xC >&v'3.1Hg<..7a*@S퀙[ h>' HKAUda p Yf+cw"Rf5Sg HI8ر};wڵ &k3O>YW Um۱}Kaڌv.Otcn D0{Yދ HW 2rsEKM&iζ ɜ@.A&ngO[ InQ;נbt]tZF:_~9g[n>ÏDlqqW\q+{G#ճT}"(O 卨@ \vj 0+,Uz'\:*p*0 \f8H'JLd|ji)Wٺ]UYp*.:].::\ԍCa+?,>L>}{gɰwu=\n۠K&.[θϛtʟ{sD0{Yދ HWX \ی0S20Hdq^{\dtI,mK'FԉTq5]7~EӅboCHtU"h|6/Y@:D GճT'$DкXވ &w2uFIc3L@DtF:tLjV ]ԑK/܈˗ÅAG}e]?#N+``L/bȊt9*O 彨@h 8 P*P\ Bby#*21J/4T D\"],) ןZX<*@WHZQ0xMDT@]t.^T Uo'w M tn{SS+ ì|xŻT ZzCT_\^'.T  ۧ27*G M7݄"qT P*@@ӟ4ruiӦM-Z(7oIaa}–Kآ.SiR*MLSbjrTi?'}du7Hd)iI^x{;)>e_̜]>%}whYb%& Z*jM剂_toܯ_;uc'?`0tc:tZg& x-ܚHvtG"^THHwaF$%>g->ݜ_5d- ~@~`M]vDu׷|ۿ3ڄ=4R;J(xFWVSZǪ~NGҢ|MCP{_fƏ$oX Y4EKRr_^X N1;qꊜղV's7 y5וyNivݣ>Av%c2W])V X>D5ن`WD UXHp 707 8 e6` gTWz^0yq#kVB6v[Z}_32Lgȸᚃrٕq @(dq @/d DƁ(d2q 〛IGƁ@Ɓ@ƁOFe2*@aW=3xr OFe2*@aW=3xr OFe2*@aW=?hhh BI>dPEY{[ogckkk xge(Ɂހ[xgBIg 2 \qA/ժU2PQq$~_$nMo?1cdPY<BSO-;eJr'mWe~͛7/}׷o+q}K.$*WR7{_}Ug>}/J_]tQI\wuwgcc?Slr72| bo~ׯ|+xSyI,P.0j H!+NpU'|:]nٲ%?|yH:c7T /EuT?W|sgϞ61F_׊Ţy=~T\ 0n0uwߍ?O".D rGmKMJJEӤ2sN'vb0PTׯӟjb6s=c^`pW[t @C5vg(`<ַ2 e7Ӽ5D>{?鿂yc=oU*sfu2@a֬YSW_}[nw#t] wy9]wejvO<@hzvbPXd9?Oٯi*jsgߟuYbF5JZ9н_~j;X$v@d۾G 6W6AVSМk ߲<=^=OkU/}I)"jfz .\7lDPm&MB m`< Չ/>U-o&P!$P* 8TX.7X7^C!^K=B=R萪C6"=ĦƕW^CC655Eʰa7tP) 5kD,y\@z HI\ * zHkS(XKnקŔr@tD2cBQG13E392-9'|xkN:I -LڱFZP( 0WXN2 ~5gsN=eO|饗J@c>裃 >bŊxv4 iC!/-}^B"L_ƕ <s; ~' ղwP$B.]⳹Qam%aBw+z\6nܨ_|ԩo_~; E>#GjO;~_'[C4A] e?q@Fsܹ#9~~롇eb$G>zv@O?|d O7ÌTK8&UK\qOB?\}Pd1.o”)S<"uX/}Ӄ ă ;m:RZ1^ 9BsHȠcqZr/8ѣGۉW_׿Ha@($f (g;fj?(wyQ|?̖x}iMAиBhj (@N$/sA^n&x h[Hc]s'X@cO1vb=՗E%KU=wMKVL-S$g<4x>xnppעE\̒d0TG:hH \4"_w}U~3+M_IA  \bn^>FO뼰_b9b<5]H*&WonjVNB|X)| A=ͬ@;sybjm[ZZdĈ;A\MwWf'i&"14̧e>줠@|g(-GyD/ hvo\!t4ՑWtV\glD &nF(-=.1iMeRu.go\eI|_M oXvtѶ/|%o-.,{_3я~FܫYj>Pn/g{cmIzG¥^g;.pfl4c }/t".ZGŸ>l)$ד'O]D3'LHeꠠP="Ch: ĉLvjh/nl&Eս@-YDl(̙3!LUk& jA@'L^n2|T ^aTkfvA[osBA:u]? jh{2Ct(;QXSx~EXK6yGq90,2Ha;OfT/RB{-==^DȖFłMu-{fKO|$IT?Dsye I1Q\BN! "Ӵ?%Ad.'f@W-ɐ̺rq`޻s<% t7pSĘ.F7rQ*l~]OA)_}i2`k. @>^:+x3NzO@Ijl t (+ .D2L:Ir^SHsM3̙Cef|a60[Ci&%|*0A^h![ا54Pp+<8AA/TllVQ "ҰK/_VF4#_FeR}n{i܈s,4~0Us:T8Њ1=2\etKL!14p؂ߔ~%CfB&Цdג ='}(X9cc>B(dҕq @/d DƁ(d2q 〛IGƁ] +q,@aW=wqL>Z$lu.f@g2PE%{]$OLıZ8$,]B8`r^Bq@Ŀ0F^(828ss@ :m:ח\4@aRE&--@ $D=@(D(AQ%( CtZ&D8< Et0d rx4  D&%'јjB $& ;tBW@x$$u4F2`lb28O"A=dP!ZD"f@rD}رd2 P$6A@f¼yl "8Et䙚Q~3A3vPJE  phzؘ$L4ʡ?]@{Ʉ $n1 )''hu( T游Toק0Lr$YO(k&O ! JH dbX忤LXd%%p|4U",X<c%SJ'8֙fJ`D[iF"_Y$!+@&ɏ"v.$B>'hC6O\)7 (B7O\״]*pJMy8h@]

SJ#DDo=uxp pFĞ.\g^D,Ϫ N .t +OpnqYTA= \@R#DPdP&* O\"(2ؗlH9ػPrˎXs` 8pCI gOsNqlkLX1IUzPKmBqgb"w@74U9uۉMFq4QA -p/ah(*q5U3@'L@_xߎРhbAA sл}z^(ZX;j!š|qX1?jQKqcWbQk̘1 ]1~B봪yŖb+-J lMd s>\y啮`áڧ͸pQدgbȠ0@Nn2 z,-r I 8۴20!vq! <2Vo<-G`\ąOpaV~C5ڪ,-O@$ 6hPhDŗjkXQёo(կm} ݢB{4ow]l\su` 7n-jhрW,ƴ\S_ܛ"6$[ Ds\/U5&F/Vd(n,溑]`ϞcPTR, TݐgfBα;Eۈzgo@acwF@Y5[7bIIsm&ŦDFͨ9ųdU}BUG3mf`mh7ޣ}[Zw,oTD吥/7Yr׆|՞hpE1#7hIF#22&KV+KbnT-y&M1^ eJ%-"6ʍi*":(O A {f&(25ōx|b^Kל= ,7(`EYٚBǤseDhYa0ڪ;],ܾ(+zלܘ詨F"`y1)nh2=# #\ (ٳ0LJs`tSl ?-'dVIu"JWKh|TA~rjȷhg̛@]C)rY-.]Axh =QTZm~D} Ä-ߪQx>t-=*Q+L'xFcT"~lh1[? ZOD!qx_}=` 5m X4gxAo*rN Qk|5W'(4v1 ų<_v+( - BǻUW[:< s77+Z=Z 6EXdEm,n`F/MExƖS!58 Ip5(uJK q%#?7ߎF-Grky$4ᘰɽW]g+N^4NƫoxC ؔ 'J_haD"2i#H:`I2(iN4yơ0'&Y0 c,H^HTO " s9 6(5wE Z iN2O$dH[!ahiX<ǻ1QZG9{FG%B(Lr1&%"KoO@1Rd",zM:qMa_㥣 (֩-J)%A /7S0|52-M7ML)ǖHR)4.lK+=DlDS;OS$J@,ͩjQShِDS`c~~. < s{ "@&VB\kx4=ߘ'%V*&pCrvqrmYI5771/n_)f2JK'OS=W.S`bGp?^:~G_?=3imJۿp_7G1 4Kn1z .pQquU5f76.jXyDzy]jW1!;Ryᙝ {ar,%&'n v~"~<*#qMjǡ I]s1 iQ?<,*f\BNZ ΊA]a-C{%(4}%#SyɽW]n *L %>_8IH[`ǟ Fɓ}ɀ`1̴'5gzN =&nnOn^ԑU6Aޔ8d@Sr[I$KQ*ʒ -Ii¤Dj;X`4xIwtNQbJ3< =|tDWk"s@>k%h}[=b{Ҡ=[,RakKs#W|v$! {J}ƚ|nrJ,F P}0"0ښ/k>(pYyUQ:./PGGQ–ȥQWڲ?Q!,Z 5:c,WQF¢y c=d8*\T}.jB~2iEN8QX :g7 &SQ7&F0G5܈cNAFp!Z_XGySrU @*&(wy"c!PzWL̏2DV&Ԋz2wQ,iҎNTPb6k5EXc DYp]]$Vdk`PN' Zє 9?XDtg!0p>#-WX(xqvJj ZS`>ًÄ̈K 2_$m/ ;ImGV6(?EC Ƀe˖W^y*!i{5Șװ-p:v8{zppcɒ%"I{.>9 cO=GsfP8㎓!;X=nn CƂšm.I'DiF8e2$~ǠPkQ R J7΋a{,իW˃~Aa-":(7mPPv鴨m.RXe[]gf8c6a&5u?7Uߵ}⹉+/1^ K.':Z]T:Hv\tE $GtWϕirnFDLw)>PR}2(9/]Gu)XG}LFl, ^ʕ+ex S8~/;g]FЫpÈ]GU nBCgWҠr:NjΝ;Wx ͤ-XLEiSO `,-_&`M6G(IV7VvPn衇*Ο?&#_#@}Uow}~0倬"N5G)Pod\84ɉ&O~,iӦ׿6[b"#T=8W.lx͇ &F~lV"U:iRx׹:@m\[Ǡ XeS( t!BIh2.P!L QD"2.0!r."MqݓdGqh"N\pWp-)! YA mn"'.Z E$2@"NyA>+Ž(o#]8oJ9dmPz732wqbF ""Gpc>>DD( VoKn:ϢÏB —-c,]dPU˅ pa}ɘIdgf3]""(2_6'7ƭG~:Ü0˕BE(4KAX|i.8@ADboNO8S%S#[z 7Q0p(;>6ۈޡǩ/Z EG5^ĀJlDq } Dؙs"yHX#7J!b>C6A`j4"ƺ/Z? ;7' Gؕ|8s3R~]h|$N\ !\X|I@Lf`##hBmt@R}ɠ@k<[lFPyʹ婔rوɊECmZEdIjb`5 fѝd#c|[ȈȨ-CIϜV8b,'C9Ķ8s=7DFtā3jq9=)lǰ?"#B_6~`lZ'StWmv"# j!cr#2]!} 9CD'"¶m 9}α+>S1kVX7n夶b{[k[9ЋZ!裏A6y/RZ~S ?#O-6.hR A((" 'apLv Ȉ} T0]vD9Bէ .;$y@*@B$͹ܼyB.=dRy0Hd !V""p`As {owɂ%uו٣0zpl?nȸϘ _#@&adO):f5#`\9[nxuDPmoz\\&#o*dD@jN?XuhDPB E#x \tttaR_{f=(Aτ?J"BBID\A\M|!3umxuvNi&IX7Q/OL*!g-I6.+W]uUb28ޙƳM_JLreodظK?&&.{7CJLl\@QwD@Mm~'=MA{,ǿeIDP)SJ;>.Bc5(!6.zJ%AaBɞc5 lub=dcׇ JM7a5(}`"Z9y`듟\f'"T<AQQ\DJ'"T<AjժX̿'"(2* >DWCt555kmw~lPP3m>h~˧Xm|tO:#|2l>o.BcٴiS?"Ә`٤fH\26sOIA P4B~LJ] J<)aL ؏@|kyR$O22n׾w**o (v`9T!𞈀c|+FOdd 3 ((/Z= O'^|0;IŮc +jU ]4ds@ertQ!L,D%O@=\7HJL?,XP0e|2uAr@u2̉M5Wh6q!9(ӗ8q/9Rj<.W5Ma41Gh˞q @?r 6(r(&(><1 8bĈT:th9d㼉Y%!c٩pNJ6)4K22&Nq*JIb2leZSf[k<ԾrA'e!M@_%<Ծrȸ;S!#n'(X(W LLP6l)QDS,BYhLWB m h 쬠@LL#$Q!!)( eU!P=\D(LB8"֍IӐƅ!C-饞hr`&ϚJ|7V8>?!p L2ȍd0@R(yHh/JB"WM%JU_ P \|kh[cR}A$q]͕BYS@Vj!a::ɸ})(di XM0㟨 }&(-zk_dk2LpD`_5O}`>PM4(W2@ݷWlP09Aɦqh^mG_8ᬳðy03v7nh`,ddĖB@'Q^q aB'jCBF`RH[qDk'KZK)u(tϷ-=s钏ϣ#8B32-fTE2r!B}-(<e?VXz~y;Wؠ@Zfp%M>Ǐ FfXH,MM7'%6q L8K \1WЉF@ Eѣ5圣ʠЉ3!gرq| WW==KZdr-z '2k~i ^պ=h3Ndbug,z mݠFo= h݀kֽ_cg_Ƭ GGycM'kӪ2J^X45Q.=Ƞ=g7kyuZ=XTs *:kDVKZ XemNS.@{<;Afw۞ u%tiH' \18>IsALЍVLԥa#_M3wu `R1Ruwd112i` J1%"Xº(0.ЌU)`)G: /9 &y$I^2)%Tbv.[7k3qWENK+Scfn8GwLTU&L50-7)zrV)ĊF@N̖~VsC9y>30aԠG)ճ29C=T->V?,j:&Ɔ>]bFI`)%"$p]7B&ZӯL2X$ic& -:p|Y4 VQ[qE+DDsSۛAC0xQiexʘyt JSi`&V2|lnRvP`DKbG 31|(Fz6b;q.=uĈfHIdWsSW &P5vLu .ssgp6#d?aDqiQe&@v3dC 0:}_} ҵx_Jۍ]]]rFSD:L)*PW_HtUi4b_CF;AQ!%Ƚx9?fȜ .dw$ΨV I]p#:(Կfz)('WQc fh]Gp𤚱\Ι I})ˊXRU-J}tNS"olj25㏋E5DУMG.P-K"˜eӉf4YCiYyDně/Re\j<}Q j=C\ĕ=k̇_=?- %?gʧAxΣ7SkthTӫ pJ<1|I8_ R3~L8`~ohF;lu]HfQz cCU~uۧ2\Jv;숴6t?J @ F zvź^On_A@ӆ"RudVÁV-Av,[mckݸ}禌"۾L>۱5/OdhkW\B=fA'vF3w2 G=iE|&[tdŁDx2(|wDz1PC8zJ/tx7p$ (@"5״f8zGh:$>)FYHbַ*zLY9Ma(٨R ԺOu5pbPTǔ]a$ے4xB\vE9CqcSh@Ŝ"t;G ̲xjmÙ>%{}c璇dU TKGz}ny/\wB#~\d&V22(HSW/v%bJ SZ\{G\B,Fp6s.) Y .nbKm0ӳg3(YDYbK=8,Y$TK <iy$čLFԃBJ9O!O2!(h¶AD_?soI*Q wV"χHf:|W ~[zesEgGau%/;s7S<9BK"E)o>)ٳ2`_xO e3q@0ꫯ? .d3GFu=;NO8]S̲މ9PUU}ׇӾ<X82wM(Pи!  T;oeN]j a\O~ϟ?X3\~x wAo)[W)^lf,8opM7/~Myv|s%)9V9!z8…J\(;@͛řLTW7|3$gZC&|'.(a} ߁6=z@}шP PK(fd8ke_^* tw8_@kD(\|%s$ {nƁPMOrg8Ɂ.~A=)Κe8PQ ^:8q(wPlʚeu8{9p ^*3-}p!ňFqSMĻe}f8=KJB%@aG';%@Ɓ q`G3U^qE9E(Thh?0"!<ܽ 7f?דylV Hv!YIENDB`fritzing-app-0.9.2b/help/images/highlight2.png000066400000000000000000000400101250202676700212340ustar00rootroot00000000000000PNG  IHDR^˦sRGBgAMA a pHYsod?IDATx^gűxkMJ "#!DZrVI`1s9L2`oߨuK9=잕Ґ!C⊒nK@%`S￟|aZuM U]@ 'Nb/_y/_yv饗?7kŋOi駟ךΚ5+|0VkEy#89zk?;SOϫ*c?s`v/k> 5K䏏?_>BOtT@Kx뭷.2n#_abmfmr-3Rut{j8蠃=uTl25m=\ /0ZA6bc]J2o<韵O>uǣ7h*jw!n7_1joo7򷩁`:(6`Kw@O6!9*.\hp7ʗ*/fv4a}1_>#Zv )zW0qy|u]W^{7ߘ]w]85e naCCp> H^/pd>#*J! &bK.) y7` |&l^e'fCvRTX! #~$<{LE 4t]pOʭ{5h 5nWKHRgaI*F8(bz 9ƛ*d\` pu1~p!⻯|O?%ORJ&ġ0.Rݢ#b뭷^QC 0db.#<2a~nN`V<3ߗ@>4^!Cl> H z w\['}*P1{M]N Bsi⧟~"Fkka6e{յLfH~Oi&M Uېkyp–%:T<;6Rɧ;_}n@fiuszr;|cBN>dN *1Ee Zr- |xdHLwz +ѤaÆ]N vWy4.8ݎ|9bo`j!aHO_r 7Q&-(Z%t+5Tv$H I.0#ZհBR!I@C=tΆ|4C،!=~%?πDFhCZG`X(GEm^` @@#_CM؁kw{13B|=P;w܄qf|TRnfW-ġ0Jn4Cڼ Pt0gP9iiIT <XsI3Yjiܸqh8cvmSIPmlǍIauX85HfHBÐbamVGHsVʴa4K˾;lKS@yusm 5P@̆ N]wՎ3s2}Ae [؁ נ[n'fgTaJetmuT©og!tǁEaԀPܝ S@2Zr;R79XB ύnѲ[ Hys*ֻl8o`V,|*{ KlWC')H$D/j&h<PzwwMbHE`I}Q7#ȡFjٜ)Rȵ_K\${Qn^Btym#Cx|d5i'빭Uj&F|ת$;Xu SbRU_ʭvNȰĘC"5?Uo^)I©9f 8G4C~CB|Z9vNk$\;0v4L3;w˅` >&kxM\N}ǽ/IG@2>m׺H d@) Q\~x uO^m#V=}l6ՓN:)$_&2}qȎ}-qoP:9!! -N8v2䑴8wYXI{7`/@K2(Tjqǫʅ=3r_NjZ[Dv=ї=(%`$A^ [EP&NTRCcJ ((TRJj(u@)0 VCV(bC>\I '(% wܑZ'lq|ؾ_W ԲI)n.L7+(HZI |xKJ`Ț#͌|?5 @sHaL4:t43o!Q{i7WJ@@ӧrq&ĈE o~Qq qJ^jhUK5_<.|cz{oyZ o٤u'z^G> W=ad1縗Ny iZMdc7VK 7m?@i|?ѿpa01I u_ Ϲָ0hO u&%@?i&}T(JEC<1(R*iMWѢFLل^m0>T4>opZ*v>|X8y;;ИK I'<`z WN}p_e -} ڣ 0qօ|0ݘ 1A(`$J/H!50>~TӦeD/ d6ƫL̮xفfof`|A ;4s(C#x@w~DSkv>ʺ jxj?b6h<vpv^8M/@I0Ϯm7̣ۛgS։/AI 9X$*6>%Tv!I/ P0Ln p޳BW*;`$ie>R!mN{1=uc*A쐂 gYTnq/V5>#[P&Z<5$zy׵SC%nOnaw+Q4 jC1jNuIj;OK x^^Qf:͚Mf//VN Wz(Fu2;#V 0odvª6J3UKJuP<5L=Ue//Zvyazsg)>Z,R#jEO*洇9[_OZ_(dPήC,)G y # 6c };*=uv=(Vv v"|J; PI4K<3O'Ây&Zԇ ^T Ӓ]4]/$^U``:Ƞ@%ثO19g:e)0à 0X94Ǘ U+)df< YGU28UiQmq%y6Co5>aua*fVn8һֳZ[RUݲ_%8ڴN~i_cV6{e=`Ԗ|BmG* 4 c_'F546ӥdPx_j-wv kPzVA<.n2-"'UwBLدMhE4(2p\m_>h&dRn: cDGf6ZcX{ q *b:=ϑ-[LoIcV:ﬣ L/ ]JviGATƭVߣjJFx߅͖ M`~cZ2ny `YlQl6ͮMJ&c[#i,'0<幰nApSmueP&%bmevpv7nF!FcJrڄ-^/;_o}MFl^cPHn@ֳ"FJط{MD BzоZo>f; E͆f^~ݛݯN-YZ@FO Cf Jg" I9(46֕F &:_4lVogkH[EQ`eVqI5j.C ?:-~u@,0GhkX+XB[o>\#Q* ʖvZbj0pCsPRJ8i^+T[ C a!@uv&diat꺩2B*?QPW ;Se|>Q`(JeH#r E559rhgGͲ2}hdYJZ/e> 5u21ۇ+mְaPjl0 [u2l2PD&C?)8,י` QRk2(3ϝq$_**2'U&{^HZ({/[75ßLکEC~ve6wX[bexT:.<~+-(M G`NfsU//̽p ;9u Zv'eԱ%^.#8UeQhGBڐzT NJݣ2I'Sv5ݝm&G꘼{Q (Eunei9+}9n(*z?׎ 75 w+)ԓ69!%o,eA] ?Ѡ@ɺ N4`k+[LIRf 4-DX`xai}u1ֺcVBB{%_~;9 3x`&ԩSC=QGG'.SѡWρt|d>PDJ Mړ1:k "JY%\h`xJ6$@ROsD:0-0m XAx:``hmrl= '0pUT*2؀Zr~=RD֏1(9pjXxM SLK ?B!zδc[䜶ӪZ0;F74`$WϠማ;k~Dg5W`0Z0H#:]UdrIe@-5<'!2(QwErIe2f=o` v"9/҈99ˍrO] gQe՝PjgqD"fF0֩)ErRC޽y5P/駟ejU2j?QsSk03YFmxp ~=n ե)]]}|t17јFv"x#tFeqV젹VcC#9 KK Tgvkuiu3(" ` WuE,q) ɿvI[z2;c;x2E }>( u7QX2(E%2؞`E1yϨ{txΣh" [#0Zz+N?td0Һdj $PA'T.[9s7>y萇s;mibU2֘w9}7KLpCb/yεK Jؤ`s[ocۡ0WšSAa/ؾ /&c)B% !a = )Bb3djBlBCBzMDmr[6Lyk/;l[4"%]n~Ϣ|~bel]j5kµ^{뭷 ;̙3'"B:쀽G5o]x/a҄?F?r'/x;3W,: Q| xA؁^?9B3a|}{p<'|`$/%9Ƿt bVcгg>L`ԨQz0ŗ_~`[ ?Cd5dl[taI\处r&'/t/k>xm%[F='>g?v0`׷H慺 #+,md^b)^KNg[(O/ BTrrĜtPy!IXzyȎt`Qyw ptl"Zk-6&Y|>j={O>x6^v @ jPFX 4>$vXx-ݼ$6s{ϊyqT^~X:a4iP:05cT^^b00ubYen83(Py-b0,Òm.4 R x?Hbo{p+A>ÿsoa$fq'ۣel E8\j< b8<>j9s&q`|>l;@xTZ5$Y Qʪ Hж0j!i>^0ֲ8z!W_&ZH L #`h jxH4H q20Tv`E,[=XF@> # m5?K r7,;؁ɝwYv((QxJ dgmIT/<6RwHɼ$B^v y!F2/yK:!ɼxrmjj6`} $Q uys!:Bx!_1:BxA'zuv!`Py8k ,wcSw}קO,)V!ἐ3$ݧ`uz!Pv煆`SÞ{f@9쳽Ԑ.;[J`j,k 0Tς5͆^h5?lB W]+%PJK`_f;u% Ywq41K~/;6ʆLRVZ ]CBdݿ(v0`@!06x<06tB`5.R :`ϡꫯx;ӡMUW]%wCqI'{] UYFc;AqwǓg3obW9c*esk\x2'N,Yg%}R`DO+ߓZ ۡ'ar;H~"#wo V70E<Ő!C=BO6rBrᇋ/238C~|j B`d$Cqw N;٪_}-"U<믿^袋. ; qKͳۡW_}dZQ E2cOUdw-Dtbr>޳fSbqM7 6;} /  OdF%="-j{Gn!%|l`q]=ہzjKRA8$: UnN)S['B 9cVKV;."y@9-$.-MYSTKa.OCMM1"B(4UhY`2'C;z\!4a`ҘVP؛y$3d#lj q..jWl`Ԗh_ 6;*lb1I(wQIŸo_0lc {cOGyX]ALAČP؁e.Fi(Y(P# %ſ؊n0:wdy4±Gȼacj6kur!P`@6@6McRA(ihBHc&IO5j(~5,fq{# ]v Ԁ+R% "g›"!&l7YĽH*g;1{(bb%M /.ޜ}9{`/Y0:_rBcOE [v&L-$3(*( ,I9amQ!IM 5O7ǯf&K( o|6n ؃yfی¾ m[@ @´1)B$)\#(ֿx=$ 0B6e*H0_nC )ӌp$?XUFf!ȅ[źf#/Ú!599p/^ؽz/:Ji@XE,*MrȞz)1 a˘k;ǒvY,H5Nɍjbn=9aʦC RQmr]heEYX8B>#&#YfUC T] Lxfd=IroL;KJ W?F|8ܗ5I fࠄh8q1d/ ,ֆ$@V;`KjUfe!A'L<'#@*=X3^I#'N ,t2QlOC \̗lAžcˆJ4N ܀::f"Ofv-V#<2\x3ٳ^nf'4nR0?EQ-a^ UmÈcq. hAbnαb=2^Z=Itvb!uyouS1] sK>,8y$7%JSQ!_WX&X11Ac[eā8b> ]~Kƕ?6Ȃ̠PfQRޜe 0]`g0-qyD s<L@GJs^F#D T$D3yNs`㬒1B4g C=b>!Ԇ B4 3 eI>+u4h(|G8d2.a1%`ܛF M<%R @I 줔&V-@!(1X$PRÊ6(DueQG}Yg]@fYK O=kF{U;O:QO0"]Ȁ ǘkn{ֶ޻]o7PcWȼ.*8p=aDu>/ Օs$ :e2H N $]0]xXj07U:U^RJ`r &A Yxg'-% ,QvB!FH쳔 )e@ w/4fwtARʇXF Zj~]ws).2j9kVS;]"J $f̜@UrJ h ,B3D@SI`5`w-5L*uM%L)n'e3 ̆o;t;K X.z -9fEq\Ҕu;9QeFCwԞČPp7[ ifmFfIENDB`fritzing-app-0.9.2b/help/images/highlight3.png000066400000000000000000000405421250202676700212470ustar00rootroot00000000000000PNG  IHDR]սsRGBgAMA a pHYsod@IDATx^w &@Ɋ sxU@żeY]0`10igzY✇g=U5-}o69P\FFmO΁96@ F9@ N9B9rq 8sǁz2gs 9.q(=_9.d8@r\P{΁r\qq!C9:uӹs֭[LM69.0*os9{O5553n-Z3DžjwNS|ޘ1~xWM΁j?񏤸@yܸq|MB5J:)?>#oԻwo9-/Bb z=C^y9.Tsjrsą?0bhD.ŧΝ7߬]YyWkЮ!zb_|1;+z/+VD? ?7U.^_A~=Gt8gyfժUEtح[Gs=f'|>3 /@ȵ^ @?O ƞ4DR) HmH84#:\vN?t׳ .~BWc=VqHdw}Wu(ڥzp_5[fMhaÆaF衇P|_~W_BCR\W]uɷ .`/D_ l&рB<{Gۓ={vAXM&z:9CXP٥:1cFDxl T̴}D76KhH rɷ:kSo zgq ?̙cno,;~}Ϯ\R p^|駟ֿ._+S=T.Ұ,~K.D覛n"FWCswaU}w6ȭW=yAd.3a [W939gq){hUsLYe˖ٵ:v+ޠp<8`MA˨^P$LXn ߼qkD+T7 nF Aw}՗=zTAAY! =9[okNd>?]w?.{h3nqaǍ?3!- Y7AD a@>zTC!"=01E]!,awwҥk,.S~L, JBR ->;bRFx7P&8jX5-G3'.r)JB:jHx"i jR7,gl67]vMaC0~8^!WO?&T"b|￯F QqK9k Y牠a‘G8E3e> P.ӏ裏ną)Shh85ue#˸*gg8qJՒȜW=l:ce\!h4hYDuiz0qq8\CBN:$T[ yϰ|\h_R9dWW3.xjZT@K%KG?۫W/87ԗ~ [|Ն PHRh .xtIGpy%LMmL0[^jхg .@O\8>2[ 5Հ \`s=5}JTp 3'q2A՗\OZԒˀJ/hإd*&iowRƎCApE zј1cTM fVX?BMMgႋ`+YOӖ/lQ*| 'y(X%4άcI"P^,qΐԤX@C=t3w|=@5X> p]FO{ABR{W.(@MP?`Lqj[OM՘ZeJiV pLhdg!@C\P ۵CoQV z\Ş3ePcB'z\RMi:k ~yNgd(fW9e(&rXVʌ)f2*%[CrX];ްɟVH W\qEpAVSLE޶'HP'5񺔬fZUd TQqAضw9|""r ȡ H&\x\YLgCw\̃fjf&hd@jK}؍;#q˜)ai^%90MBY\K`!r\h:Yr\ћoI.KH6Z 9h(Hz'hBq䒑'f BsUN޾Ys tHh@0T/|=zn^}A 9.hp !-b \Ņ|u|1>r#r+>~[Ӂ}7><ç&=z鄗 OM6NY 79dp ?k[զByė=/HG8Ujn&o[ ؈8 Ʀ& "tdTdf@QrT)2\PSS6_ab&. (k1bmG$K_V>8LΊj̖?Բ!u[ 󂟧o5=)<ƒ@(3$K=ܠ?ϐ0/HfsFIX)+zSvT cϜg~O-172'G#ܲ>`2(J>Rp4'O2jRh/BdmOh[ުP!PPbGJ"Y_vvmx|Pg1+BoH ,JlJ&X E4T>PQPPd@|@A DP9PO "@&LPB$W(g*thSPHrGeuQϋ6wkC;L44Z-, k2jAᗅ,겨L2L7Mk>T0S, 444x%-8 An  虽d Oh((23J?4TLh0q!j2 AMms}qمoB\!%(lY(^2m=NbȈR"cǀb9s "bEX AAqcN2"&%phN3 ;[..A9n)AAsCuV@F˨4?7p(24Θ}X_}~iĥ¿KWh<v'v, ^PAƘ%wh`g搬&10KJ:8s Eh >)(G.P8&&СNԍ 2nP;kȈ)EƸҐb:ʤTȈ)PWpKCwUh)P:]Qh؀ AtTLs}iEm=^^"4()hd ="4رq'(Lrc"4ȈNI2r Dh!3aFinkBD0bPF/, |@a^d$0%2lGӬ Q[ NPتTc/ɦ-!`j;AaRiɘX;Oyud7 tBhhpB"b n@|`KGCG9CMA,l-$GC,l )-P˽/<WCbr-ɳGI|wA9Mh_1$-tAԖpR|F`8HpAbS¶bpA@j&cb1&3/;A7l2] NPhULoiz. 9*Z޲nG]Z4ʽo(tQuͬi ]&1dp)efmX H9MH Pm)TF bB(d;u^Ő뜽1жDҍm g#NsֹzۉdVaDŽCˤocÞuldص ^\n*A}BM:Y`eF(hhBlQc&4+rN\En#K?LC V {o,hO(K"lX-1O @M.)(EFc} ws]"\WKR}GtrMJ8"s%p֛NӓX.{8N.LC=* i 8m3}n#t.؛ 6J 6 ʖtZgd4k5+&4芸h]>nB[Ob~AiqTd+q+MK}dL+}s#Je?1 fJx"bNՄ vd5;J@6҂LJnaNEOҍA)Ew&Ղ rDtg<}|Τ0R:Ň )Ϋ̖ƞ]T!>uT&:$x"6 H[dݞ sr$!Rsl)) N0g^CsEϫ*pWŎ[YB,W錕7Y7q0xsguc Hհǜ \\Abڐj>9(x! Kު0J? Ng #>cV}x<2q^>? ɱ@`6RΤ|,b]KJuMlMjn_\%1S\gWSd)d% 1[7KzIxb/FQH%HKR{]q ORid )@ 2āȐ9 !Izx'gs]\uyM>RNgqH:zQJT12QjX1BQW1~7%H aPL\^ vu[N!c/:pP֛ 1S~>{BI$A9?;B bJn_Oz!*NA^f.ZkT&tW@}'ڠ} xW!tީR2AS KׁIj .P͋2R¹Mp9;~ZP˝ |{2b`DEk TV^(,_N-RW~λ3(ypa̘1fW1H;yG@\ Q;k * -JK}7EP``{TJ*PFo׵8@2%"nF׽gǐP€In%(\ k4y;ѭEdƀy=x8tQrަ;EZ (|]VXay'Vj0qgy.a?ulQIbU T~E{1ӌu DO}ǭVܸb+dh {"cGō^%H(q8}dPa!:P47 笢}bǍ{HYG4& ɽ hQI eYI#Ky'- }Pxw󛠜W/X'bMRgَ/E1f ^ǶAAq3 (602.N>+'_1 A\@7:֥Dn˱GyDAEfv5\^YX67oqv2Bƽ tYtd2ef$ݬ 7&aIEtZ( o")&Nh.x:)zO>$+l-XJ]T~exR!${x[%ˮ2n3$CSWBKuDz+uW v 8mL눔SՔ {Yd|b5JnxCa,(/xšZ ƔLT"6~ƅj6NCB ; wٵjTd`!b@ HE%]Аm.jSrjx-C/I6%2WW@!vBCD8&xetPFyhPũ]6 Id ۏtEz!' ‡~.B/^^{߮1> as<0K `ˑh Mc\t b2La.P@(W ht߯B[txqACJ?q\r"&&~FqDPxW[nZmڴ/4L0C07 xU`/py{l5 [ET߰2y{m﹮x ulGl2V[.zC4(BC@iW> RZqDB<4Px{-CC";Ȉ`r\A !dMLq9e{ؖªUlP`(A!K't ,Ycyù^Dž׍NOdߖSt:}JæOUѿSLp-hEk]t!wX[X[j_rr.gLݵ0ug=k>{rig6a@Çs6"\zCdYf]nLO}@Fs2ppo^C#^2䒕W|{۳r:DtD(N2uwC#^5×|o{4v1Sں1 2B7f8C# i.`>" L-k-*Z۱o=%.`̲ݖEvPũCJSQKӧ(Lɭ١fIB X׀C Lhᩧr¢EMܲбkٮ}:ߘn[y^5V۷nNVbk ۏ;0!2nX~CcmUm2AL'=3ZsGqIgȸ[um?'c̐1pohI'N>Ow\sоCʈ#X'v踃 DGƒ>h݀3rCc|A ;dnA(EC<@fj XFLX}4X2lɈ_)}w{e׿+&.\s5j'~Ӎ) `=0{s=54~AcZr))!d!>|xSO=5t/q7 P"Sw:9Ln\p!2LO:sg={>S躇LQכCֆqeHƈ#((9駟j9 `!(^z) Dr1ǘ+x!"QJI6g]veQ`jWihEF!47* >(aD }@A $BgB(* "(\r%&((2* "(p POċ~cǎj r OP!C:XKB PPdviA!L3b$a`2\ ]tь[o5}9(Z }AT̸M@U_ m5˖-KMwZBV(!64,_|qj2/_믿'>dVUj2+ۋY`A^}թXt?h)Vz 3m)(zZbfHο>c 2Spi Ķ!D bAAQbCCQbǂj9Q?߶m%!(\2lh9Q뮻.}Pl!+5ls)>q P!h5A'(44xB* Ș6mZ5P0boW_i~\P@֟>-!<}NI+2> I>='j3{d#iEVjIJanswZ TQ24pfyN;%>cT SV ɰ}VBZHd>m n-C2z衤Q}UWeH92!ܹtI~%)qA 0vX 6bx/M{)NX^ G Ln7< 22a* ]&)ѣGCD75Zƒ82PrTݟ smg'ᣏ>jBCYOb2@΁ KL\4I{,h#$qq_gΜIMI}>V΁͂p1s0[niݻgB;\{΄ r6lX&d ]CI:&#ѩSLҥKru /΄D$Å2mezzb- ꄒl\f /O= WhfBIX4mW.)ĭ2LHI Dž46wq;渀>w[Q iX# f1?_aGur~7ܔ~75a B TgW"8wz#y睦#xےL?+*&#&#Gl~f=](=ܣ=7Ϊ =e\105o.9眣%1wL0Q|Ù7o'42L?k6f$ ".ҩ~LȈL )hG&"eU^G :߼ c^Ǐτ!~f>]>)2 =[)$eBFN/pOo$J %=Uo_~ =e.Ђ4k1q]W?5).5dS NI&-\rD":PKSg":Q|ǼӧO=pWH=KVdtMz+3f-#uQ^zIEVE}"o=k55kh24^ bH~f߬YxfU9<hR71; VvP5'*N@(DN<"e{^ LQg~AO>DG;S ՝*" р"ecDr-=`y4'ͻ !Gk׮f4d3{60mF3OtMဆ ¢ \]L\rנ8i5`EPLl:MIVW:.\c%**&P.#~4j6|6<*y 22+#R6箻209cEΝ3!NXi bB.2ƪȊ pG 2C3*Qh1t: Ko"|?"&ޖڵkI!.50+Xו `0d `JqQ+asRAJ:choԻRy*޵ٳgd Zʈ:x`. x-,BczCOh.tzo;/%6o<J=/SvHĸ@lKPJ ,_vs{ 42S\k2|tc9k0Ba6>o:OtXu Yuh!&MSPl*f4Pd0 NQ-7¢DA&RUXU?#vАՁ>dQ)qA YrX,EB yWZQ t F{V_QD8whzA[ ȥ1Mki:ffˤ[TVԦxDi2C/).|gWzypD % 47'O&JH4DYzL4)+!yu{!U&\/K0Vug>͔L'BlXvIIVE|ۄmPEM  .0lBh2ՃipGրR؃CY(yfExъ0x(ˀb֕Ӑ憊/2~5hVv=vrS<\s^y1L%HfJlg2Eau8#ī,@muuuMLK Is(WȽzI[%قLynGq2+ĻH2qAF*=5par?՘ i3!+*z MLwVWEb!3c_uh*JaJ X$S57O -51hkg6&.(xx 8qD@ƺieh':,iq9g.Ԓ3ȃ$u;f#8M2\V-l4_CMU]QGVaT_i ՠЬP;uBƸ. x$aԨW\8г#q(Կl_x(8?WٵiO@ʆ2xe}T369= PLwjc FAuCW0˧'Q pA~+VàZAW /JkYb<8[LFX1A% u6 '̡\6F2 )Y̮/kм\^uYRטfu?=#^FV<*q nlsN pN#wU f"mD[=Ȗ6"@;X\ {~1"?L>5?|Oԑtl+!+-E&dЉ]ͼhb&8ҡAႭe L@.^{#ٶUkӪ W1KDSNAjmL 4t]$m-{0..+g/T{e^Lkjw Vw%8r,i_fXCHIId|#oE '3 :Qbމ>-Lzh S+k1ir;x:IR[1^xAqRJ`v%YM=ՌxctW'hF&%x3H /2 QyILӤ7PN<+J MӠFǩa hfEaOVva!BB  ֎^Aq!I `<^9U6SI _d{Ҍq* -NDJ`ƞ(S6w-3G0,LlhhLSQ|UQ R%&ɐ+,O?4ghI_e9@ELD5ۏdu*>΍ot2a]' ,\Y)f@d1lrTBV⦠ XlX"ӾBm8 D0}.XAU.+O  S$PlӮ9xC**Yif{lpJ&s @&q!6ج8f%|292@ 1$fŁ6+q9 pcGtQNv6c55t/+TO̳:&LH`9ihnjkn{?ߏ{(ny1ef[ӈ-%@E9Pϙ;W\LpAuuՊ2m 8<@ l dVV#@![\P4}9\jUA@)/i΁Jp`.,],* t5+Ϝ%6(T44䁆RI5GT .8~W]sONs΁M*G7 AsqpxrT.lr UŁjy7Xsq`.2}$2w4}=rsl؀ |Xh.uћ+yhи<"732IENDB`fritzing-app-0.9.2b/help/images/pin1.png000066400000000000000000002551171250202676700200720ustar00rootroot00000000000000PNG  IHDRF~;sRGBgAMA a pHYsodIDATx^EsϽ dlTP@2*PAJRVD$1K%d"I2& "=oWN3ӓW=-^3UQ;sF{4F^ٛ\lj-` l[ -p}J7T)}sÒoΌjwÕߋ(Qbܸq/Er) {mU>}k1WV)uLgH9bҋW)x3M a|< mP(mkG,8hwY2]fj'{}:M2"?#)o-uoSF 3nӤb{?sĉ_|ży^%_LiZ*%9k厹|7-44BUӵ/ͰJtrpSRhZ4i SO0a^%>l޽{գGݻ?ݺuڵZꢥξɗ:R%évJjkJmlR\#Ӯ1)|\UV-}i %5"<CRT] -QJyD}͂^Ql/|;#~G~Rcp}|GR}P^*J~<0=%yIjj}^$SڽȻ}OmWیߟ3.oB\VJ;,OjuaCOZs'~,]ȑ# \pcá 6 g7B%bZ;e20-3f [rGrdKf͚5{9 WQ%d n@GG'!OE=I{z<Ûd=US=I~$#G>R#'~6O:Jwv TB Č~X THEg^lzG)oHPS?V'Lu* ϩ"\sjP7/(9P/NtUΠIRS_iPg)9PuR&ZjuT~?-;KOUASt;NvR3bg'QGiuH\Aw&.rM-1S̘rl֔/gM9>kʩYSNϞ|v䯴9ۤ7=ş~pnd %|rL1ڕ֗HVl(VK#=)a(1 {>I8ep94D9'ڣ6 4|/w,.L͵(-)P"Y3|%IO>UO+e?ʏ^ŋѭV1b T3sRC~E "BZ`… -ZZ 'cP %hHtPf%PIK!q(fYe`"B[%I#-P?)?K$@ϗܾH^)h!0>s2̮&QF_x2Q_bgvuP8C`;<$ؑ7VbYTV9ґ,*عW’"gxTGdrTU5џj0N3PŬ:̊bGxt;vrAS}2ruRT'k_~X|HD 4B:hu%F-mO\Z)GDŽ [DB&xԆ5{^աi0aG& r°0g' =7aW^M{?k8).& EQ؎i%0 |>~>ml/?ZXTo HpOCPm1\Sɒ[U~JMޮțS4yJ7}&v+\1q@вe>裏?x)B,wN@4sjLhWXrJkUj{ UҠ(,I Ɠ O~wu"QA#Q9d0D@Z&hH)tH$")whvʜ"W-O[ v j!N  uj堺rՅt~JSoݯs^K;ea\gݖ@h:U`R:WAYh0N*vhu2lB;]'qu!%*2\5U~)?Y SB5o{/=wo Ű~;:߱a}O {RlϝֶO00DJY95N wLێ ~=w{^;^p**ҡst餐#vz+n~hS?d~ʹ͜,zwWw?8=ۥTIwD0 $&Z$ɜjz[;W3 kJA@ PTQ*U/:DPJ/dAu̟RYsFteDpN\ȃv a߹;5ITGZ ER;H*uIl쵺0.I M#jLufN&y5{`eⅆC,z䢥Qwj9kYƒ+ NXؑNu䁅Vvm wГ)8‚ ܯ%]}DZ8nм6c3¶oH/>bCqm;^ڌ8㔇B\ E(y޻9탞ݦ~÷ HRnUoi{)v%荬YwNͺۧd^Xfנ9xAʜ9P?b?-`!|f`5**CSOG6\Ob藇 |ԃRǙd?@u:$@?y!| RyPe8<pg a|I##}( Ezt4NaW4ak*!]؃snPAt-NUdD>bYvj,aY3ke9`VRag9 !rB7!HWV-WSӨ-JSw!X[6{< uUKQNj6ms[u;c?C?mǕm\n GxcvtSS{?S?V#Eޛ@JNHG_u}m>tϒS%S__slG>2o_u,rͦ$s0(8r{#34h4fQNtJD,R݁gv3>Y0!r2~Buظg p|TڳH3ST,ؠ` ;:*ێzmZxkJZ3:_?_n)/k~z³5}1ߕXk|#z5C.DtV/wTTC*v:!ݒ(L?3nVu0;Pn]TrJ.}pLu)~%_mH,DչtZTgdu4YC T'_P |h:9YS&3 sݙdUlv >$'9`Twa --EɣQwСS/)/tp=ϙG4;4zsՄt kķN߭o_o\z^yk]g;sޙ靹;<$qd睹QmwnA s7]}g;r?ƥwܴMAk 4tPOpSnrK+~{+hc5ÀC ׌Ϻs|ѻ^hww4 `RU9rs$e}#s,:FIZ<4ǿh@a+`C3 3y &UJ 6%ce5Eφw=PI c J&}8⎌;F| e< vHu2z/@ƛ%#$i?$X?wC !CvȨ;`Ӯ S{oj:jgza?'?0-cX+\J싽ZMޤ瀉ڱ(%TE5QTU:dsg8 e/1c}9OMzȨ޴ikc 7~O߰7;_U?.ܯa ]Z_ sмQd90Ͱtau bCxU%d/ݯIV&4pQwRSwQ YsDKAQ ububyej֬HFEQ!n_@OM&H cIQ#"[PxٷUxfŷkU|VjVW.vuʬ[fC[Vve^,vzeQzeW-Neu/Sa~ תn-Q/jPпk3um䦼7J4|=Uy煣M~k|=]wmiItV`$n| s95D/ğ#!'5\S@{}D-־%KeM R\_ॅ Z CHgvE׻edt{眥~Ӑn6uo^c˰$<<,vuB !ilu13KЩ\v"y 9kb)JopP3یtFg/ *CH$l2ӧ^]ypbFSi~V\Vz/~ oiP~[mCd}.2TpS_۠-E->^ԛv܍/Inbi0!)En?FퟻlYϑf߫>UkB^W9N"_[:z =Gz&ƍ%-*qO;sAq05jh܃;$%pmB&ԓ(MԢUu(ڞW^|>dw^'x~Au3X{jڵ@?MX9UG:uȝt6h #@^jГM"iQ[x!IG8Ue"7 (_n6xgpsrG{ͯ4QK7q\fvڴM%҇tDP/ZTP}-kAmn7ŸM/WȠ|ZsEoHLS.5jڞo^e9r=7n"aj@tϑN t3S{'aU$rijxWUtAS5QPHipLTMNTgĠթ#:a-;9K Q촵t˚َ(|.0w ЄHo?3[߾b1@".P>-[q+цIT!?pHCl/x9}[Wy*Y;oTu]U4QiTe]*]e7oZP}pr~zo-VtO T]{WwU]qWՏ 慠oXUnXuAuNj{wW2M)v2Y<ᥛ[zЙt!f)zuEG=e۶eD@ 1O\∽fq>t7 | U EaZ:0z3|gAu ҉tNɌ( 9CოHE!Ηnyv`ֽ8ӂ)D;! $9MHw'ҩIzfҸT #]WE#BZ8tGI g.A\yʹ} mH*OX;Ni5ZiZ (QqD%`W k}cVp${Bn*HgP0`Ȁ/vd,]ν ^Gm?dOCG6tب:wцm%/5{}qם׸u?PwY:k᚛ܤ&5?mRs oGpGkmѶ ZH5ZpYe?P@-cOWH'ݯjB;f+,y$]S_]8yv<-z>NH狍Б@E'5g@nte4:eF:8X<U:-LCMH["8p+݇tRԨPh=1(K?=txS>q؀ xc| kۺu2'Wr<9^53`Av/")(;kP=+M #'22ڍV"fɇEdQp JW P.TmN(Ų^&R8;%iG)̤BcZ U|=LQNҝ߬T(Vg:qmjx$΍&՜&n:v ,NT3/.ݯvZ\VxNFKÜ:D7?iW="n D:B+)]>N Ӵ8ݸQF׃҉ZRG؞O;Jϝ+ ዋЂ`!E#5nV-UZ}'0ԀDxir4N>+ 1NnPĄN2gX# P| ro̓*t>ǫnWߐ/my[k㕂4X+ǫ+IQ ^NhO_ 8FUU*V2hc-S?uU2TW=Ev RR K+&do9Lsur vWv59#w#6J*=HgGur0zb|\1[HhcOV]B*vIOk^+Vr"yK-W4꥗n1Æg`2l_Hۘ6vƽm}G]a_OmiA k\fwtiKeOmE'Vu}bM'7tO7cxlgva^mmoDZߍ{m['tbS'?nVjG]c[ѻ93._*4{cC><# KMVUxOl?w9!.הkkT6%a"+M4!J/Uxm8ZZ@Dl& +TjE0MV'%(3銜m2D ib. }{%+MN:A1.bX@6$MqڢE˨7dp]q—`cD@Ӣ#!H.a,b~m%w | _EDLI KDN/(`aYZ`F!BZzܯ@π}_8&SˠMha/I y)@5qRIUʋj#9- iv:1 P%gTW @.)$Ws &Wrqu_ ܲlNAlD힠p*yUf33ovKDf.ru@׉,ZɅLn3pX ,MF&MyCn_A۔gb[z}V~9_:K^6rZ8ǰM֬R/.+NktZק'};misN>iwqπ v+A흷}qvտvu|:oxZlwdȳޘgù>|<yo~@lvfvδ}xvn񜳋ֶS_8_Ο{oy_~覊;vhӸ,F+>>զǿWߵ-Oߛ}T?5:ruc1h+{\h@SPrLtNUذDRX1U,/KJЀ6l"x8$D-aX%B@rA0GQn`D%b F" ;t!I}#Svr`4moH̦fyC73fjXhe0˂L=հI͋ Us9}DLWN )~%IS'T-x WC bgwPJF,U5<9O d;C~iEEJ+-}; @w(O s9 sHH3[csUԬ~ oUT`QgDЅB:qu C&:K.wޒTT3GXrFv4Thg釕TGXt+k:RPs2'NXWHg5RDx+%J3.I. 㽂R{I`k;1̠I2`ͫ;N/D2n#|ˬrrT=I ]haJ*+C"ڜv;|FI /-(x%9IRvf73Yhr_FHh/U>g9S:Z!BFJTjpiM 9Hd:,:Tr:9 qPtJea4SGwO֩P\1Du"T"T֍VGs *ԹE:U:tGBgJUϚ" P3afD3br ^ҽHD?iԈgA*A"K&Y۠{KDK  s~Mr9ÎTU.M,9$g 5 3`.FѯeϧI]+P gckթrad\+LN>R@u+AB4Yc~iUzL xg!H;RҢrbu = SQ+NLL1 3hLsºB:z~ H4C)aan qiUf)I Rz*I$Su2)hB mfפ4HJDSɌPLe/)IAHU`MrmfuGƥG@of 0~ol_]1z Z*T+sɇ=YU[/Z]䔰x~U`->!Q'WZa 0PK;qNA&~YJZUGXkp9)ՙ%`1 W2Ψ9 jɧ#}gl˧W"\#vw\ [-` ~utrB'7Ϩ5`YSvQ .1WAGU8]_#CmsQuQW |Ȩjkfl@ ;#g W[l[-p *f>i-hQ{z'̪ɘhKݡ Z]C:}V~6 9-` l[ , 9JH7ydhuҍ?- KW` RJ̉-Hf G:%tY¦8[-TzNl@Z IIK3# UIe@[i+ H'[ -hVJGl&#]p@EJ[i"8,{s<'[ &s}:y;w\VZuC6BBtҁ\KL\n+ NfxR,C!ӤyQJ-'[ &MO>|a5D:P]@x##̑P,zzwHTky%,r\:}QS{N"-=^9bqXTL_a_E67ʇD+ܻwƍeC߯^";+V8sl@:P5M4)>cNN_I7]K$LF9i 8t1`4BEsilXȲxMo&KSU:%{Иㆃ?@k_;cq!T*S(Oyv*n[ & ۼyX:lEP[9=W8^5tҎ RyWd@evpMz^9pPOUkHz=#ѩj=/Z:h:QNFʩ\_,]V354w/$*Gsgc0tm跋f'-Ȏm3"nqCT=,c&kY'wd,Zhx-J_F:oTEckcskxc1:[̠Ȧ cb,TlYV%ъU];o\R,bfB:8^Auk SaPݖ-[p@: pKuV(ܕR*ݦ#L/!!Q)%Hw1XaPҝpHh9[?C֝218%}v %QR9x*Ω5+ ݲlp[KUmjIO A j\3:tp<#z эIݼ'hJqF!;l@tt'Nt%#<_:Khkʱ#Wipz\fvfTeKYZtl_bVrb'mf+Ԇg2AjߺvOIOYB3 v{ZuGp-K䎌o(N{iT8e|OJS7=9=8o&KSU:|sb 1m4ЦNRsNCI믿a'.7]'H3<|wGơLgUd.-T ZrxkTJ?Q2IrSqou4GzwdiF:o; F:oɥh(G$ n'.$c\/B*vb\5U$T3<| bXȲ(8~iXՌt)@vnAKt ;X2G~I@ ͈ܞԻ#K0yc1ykO.-G AZt$k` R`cUD:!a\=ҹrF[-2yۛril[ vS ca2SjMN.JlC~U '%=?)_IIW^_W&,~5j1Ž3"gx钴f<M5,6t26r#Ǘ>>l@B`_IjҩTRt7 7iP钴f<@# yLXcU PMM2#"HR K,L0%|lt~ÿ37-\9^sttttiL˖HJsUVU'1 l@+G9Vc?~bnjts7pCZڶm+.gn-[ T Kt kv_*r@?'?~ HGgqKb\onj G0OJܑKu;ޫK~(eӳ2U* .̆*Q4 ' ,Vv}^T~ SZtAoJDjYP8Oͼa\KW7iyTPqܺ4˧!YKヶO\{MY߲~;zl+9JurQ/'h1?O㆗V,yCH{AҩGJ*tAxM7ǫkT,ћ!Xۣ#]6}~Q~u]~DsT/w+tMJ/A- qSTl:u g Yꍡ6u Qoߺ4g.db9&A[vWe'n0{yknq!jQ O@@R!2&F7>b wU-祻tu].\ t=X{>Ξm6;Y 8 ΌPUA.PtCZ2J'am0Qs9pf ]&sF:(`U47lv/Nsi.M}|3 TSLT~曠.Hd`/$ROJܑ*<+jS7NVW]%r"5O|Dn$p(ݶY02ݔ<A9K1 B"6mmTj[?1@|5KS2$}Q 4ULuYlav u]:sj^THcx,]))6w K-E +Fjq0 ҒNOy9Z_pYQo^cY"O:عcKDr}~ *VhYuOu;Fw4:|:I~nJ}.4ӯ2*|$gz/VUm.[k~/3gd&+HҌ3Jtttf 0Ɨbs%U!KnOz q'VLcr- I X=.h +74>HMq&- 1 Citk@:J'PoY&%pV6PRHM Mb ra)j7RJ8C'RO #]\N-pR}Au40GX:KώWvaxDm$@Z@E:x]@SJ#mvVҰ[f XZ@x͜9x%#qttttttܛiWH8p9#^95(rl"׳J+-{ H#:m4"1ұJ*]PpoN 86qGL-A3"V WF:F:F:F:vFH`Sl" V ;ŏSW5rpir)( 4^la|BAa#_|!6ґP+######A6]\Wv/ۤ;<$# ăƋ;H'H@ Q#C_cx, <.UEt㖝K mq?SX [*oXH9IcU:V邂K$ .+,!OL :ez}l]]V-7vGH=xZJuC:^<*td&Yda2A@۫NHo'6Q  1fQ2:Χ>5J3T?cFQlSH])EPϏG{nZjmVRHGFn{PHcx,]^#^LĿK Q_t8ѶJ >J B1K:d'Hu2)sCm??!]H!^l3ϕ-[4hGMTIGQ####Gpx"e~ 7zV`.0vG*u=0O@O..5r4QlJ⿒J-UoPtV훃یt͛c9s,Yd՛6mZj{t 7$#ҡJ"*xe+;^U:VT @LQg~tB:5mZ+jMބSMQ3Aqj>.M\`쎀 ~1M j k=j:FF}WۓĢĵܦw q0ZvqV?D9/Rܘ U}sb۩t8CV#U:t$1ұJ*tұJJ(SgM۪V_ܣ!<˃Y}s1:BHw2iV'Oj;$nQczS"ȡ$_fihIf̉DYȎtVk;.䮻 7|S utttttt#O\rB:5mZfR+<ȃY}s1:BHw"in [wCfd В4Z*YzTEcbdGB:W{;t-͝;TGB######H|y pִ28)\=##m.ua\f t2fikgTN0W= [U/W_R8HWr̍^E/v\NJtF:t<,;|0abcgM۪[O~Rqp.uG Ԛ֢Ls-Q9BHw4viF dm1Cv͠5I)@ҨP_JSVoѢ:%!MS/z GբtVK;H~ pґPH*tұJ**7?q'YӶyFǓ_=iՀjͧ3 X<_"#Ãzm_9B:(qoH[oIcccccc龾gM@;Ǔ!2j*lQo] ^RsY^ xe+;^ʎׄ5s}}q pִjQIpd+0kj/Tf\4t]e{&<2<8WËMHwEa285p4-0 ߿?5^Q @~[`cU:VXcs?:"Φֿ}NIb<,<2HHHHHHHR7M $ρn/#;^ʎWv5qkEX H*! t\%`cccccK SlY HGD P<QڜuvsαJ*tұJ*t!v=}-{8GVrHdꫯҗPC@UB:8?]vmhDF:vxe+;^C9{Z[ HG0?kmڴi/}R N\a\؆OJz~R0?|%RxV藾i*| 5ja|B#Ych\hsX:mV7|HK`zHOzkiߟat)t]4־ c p- (_~٢$O("s*< N2B?oX##=N 0#V,'49B:8t[rxGpxGpxDBH ՟ V|V㴝ɺY& WkHG0As;t| _atAYMq7·r!t*~7'V -'4asH:tەw߱J*tұJPF:*2:N@N?+qKCFt#GA7?+F_ڹs'#tұJǓ$ژ0:C:Jut~c` Da|B#D: t 9Ο?*tұJ*t 0հArq$EW G:aDJ89:|x0]U\n=H*}AѸ9JoQ#;^ʎWv51V`-.|•l#:},n~VXcU:VXKN[ -{S NfcU:VXcU&n\Y H5 ").1.mn[G]ZPۯ .xe+;^2-fΜW ŋ)1 [ 9,cC؃t"\ּxb}Gr ېCIIO : Vݗ0 tNj/]pϝϿKH L V?᠒E*tұJ*]tӧO']՟駫|ݹs_>sĉ8ӝV8.UP#9,c9uWF:|q; dKnBO8A#esP]+?]?uCٖ-ۡ1%p+St_ҥKXcU:VXK(H?_#pܹs͟8p.Po%9,c95 "@%F:xנrlBuŒR0%GέLW ڵk$5 dWB:tHHHHg@jSc1#Ģ_ S UZZ\ߞ?~x@+ #cv師t` Dtk: #U:Ą'1ILx$}` mHcccccc lZ ҵm0G.}` mxIcccccc lZiӦst#SuDxhC\8[ ,ڴi#:VXc.(/%Z ?~钨妲jH'&?3EIdt5`,]֭%ҭ^cCS؆làD#IlI/rSIjH'U:V2;^nW\+'IHn6[ ,5^UVZ!1111ұnmu+nXq &%vVtE4v~ӧtT-ŋSXMN.JlC~U '%=?)x%{>?/O<}v˶H`SnY=W5.-9̲ƾVgd "@=#T@kٲ%!tұJ*t٩tsȉ/O9}v]VH74/rBٱ%8#d*K ?J`'x.$, WrttDuttttttvH?|$9wgt&+pD{t/P꒧fyK jjڵ+4b5UhPk%[% W"UW{7hE-8s78I[jGr+Y 9#^y2 xx'8uW߀._9jx- ~s9ճ>[ (ALjHDFDk%f@:qY'BPE] a4ˊFWALKZQ !]fͬU-ZXc.(p+Gg}w/^駟ҩg#hhY35-*UWpke f3K_r,k16KsSE00 A]w]NR####;^jxdo… Ps~ ~"^5ʙ~RóD:YbGY>*46Is!-Ksh[HH ˔Hk޼:F:F:F:F:F:F:K⹫W~[ (G\u;[:"N3"Ġ: v+53ެ5@tUQ;l3!/-TsH'#'O:WK._.\RX6߼&p4wY:RMY>5R !j b[ܬZT߈cxD`a;/L3M ut6kQ#C>p:Kcs,I90[ ,`@: \@U:VXcU:Jk8ķ H':Iutttttt {q3lV%%Ψ1‘!粲/v0NC~|>/wl@X 鰎VGBt|Γ a $IF:P9<#8<#8<"XFX 8IU:VXcU:O.-*ґPgTtDuttttttC\ [- Hcx> |>0!0(`rvzr!l!]+-lBtұJ _lİz2v@7s㾙e?f0~Q/Vtߓ1pp}s}36ڄ0q'H+ EZ"X:vdŒU63##2ҥUw7 Μ9sue?Jᮔx,tA'?~bt)0ro-XիW*#}31YTKQH4 [ڴiCT hn˴xbJ-Ymj'eo)ot\!7uA2gq}X  6!qLyCqvVtEU/ah^UD<-l<_ _ܝ2b(HWإrFF_?Tz@-]KF#]TCƸt$ԱJcqW x#ݬ.@ vi(%O?W`uYdC}e.tnYJfC Sz#{(S#[ z0 LLID#g3lWe9aH+Vc5:^Z`#Kq(Wry˱ 2|t(Í }TjB:]@\, ڶm HHHH',3C))u*TIY1y H\ e ۫t#lXAgct~ -4>ׂ`sV݉IkHgf#1Dg`  :SD:uձJ*]n%> 9(a5krFru9Va)IFc\ p-f A5kִk׎.xW.pɱ_ܑN0g*)Ityt''ׯ?!}x􏰑!_Ʃ utt7'E̾f5Emg9)./qFPJW-W(̭;ո@S !t> _*xOTH,@Hg9F ubW^L`L`aMr ]<^-ܥpRVwׂ(|%D>-No\!5NC_iNWg*1螺F:UթP KCXݕW,FԱtO k;hm79@;+ =T-$ 2Z|c9$^]1_!4U Up\{fhVB:ꢄtk֬Ic&&&7?OJ y] Lҹ;^Lc~NQg`8F:8a#;Q HGT >.'d`o8ROJ R^u#M3^A<\;^e0#Z?Tbk߾o`ƑhҰA:}TFr:kKt8S\EHGVe,t!N]WG\[zuv$119ChO|$8҅1`ȫKzGNxG0| tvT&<H׶m[Iuttt`eMLes30E`LuaˈUViFR####SlRP,##]—@$H uZnHgfwR|Ii8(o,>ztU͙H.kժXcU:VXs$t29 ݅WSZoQ!&(A#;su]0pf,G$k=D%? YfC_7~-.y? (7W ]˖-%1ұJxJaK@0҅Al䲀B_-Z PgD:uթ JZ&V!_t+ska[%ҁ$1ұJ*t<.`#gCwvW[=5oޜ.\[ B A˗í pZuBݖig)Cr ېCIIO ;^#&r@X%5mTR\"^i,xLx> L)3%Kd DhHKcc+;^ʎWvlIJ{THHHHHHHXy_ptc=ft^ǎנÓ$&R-m*] /| l7ptM4!+# _gpW-UJbVasr@ X=I P@ `#8<"ƿ@ 0ҥ@WͷpcF:[SnI|0=tnBH t$ԹRHLS\؆OJz~RR[` @H3"|~UܕrW:ŸhR􅜇-paW:C :2<R[` KXWHtnU:F:F2pRO #R!!QWxWx =32ƘbRN[Xd_8I'c(-BE:KHU;*vk[3(@a2"]A^R^gGMb.\6uZuN,&\w;52UWdvEr0uat _ 񎝗}Fnhrgp \.BUPȚ/m۽_;Sg:|#tApQ0ɆZ |.,inT H#||_IoЀtݺ[҆ ٓHgb;g#Ol'8,@$PF@" P ߉kT[ sAM3֮¾! &Q|~,2ngON!CvJPu+nw衣'N>]p.|~ xQ<0SNUů;C(6&30ұx CgAtxlux RJB:٧ҾA2\E( r"N!S+21'*9:( zO]MQfo;t]O?9 +7qw.T[8}osիS- tѴ0S_RO+/ctiܯD*6^HB2~a:&3'f)% 8 o: !$&N?}i ;}}醭:S`}ya7 \ErPu:rK_[߮\?8USaVgV_ɂtUVըQզ\]!\ Y m6 k &Jǫx x5kr#_Lk 9+ǫB a(XGxct`~o/8݅lYփj>xÝ-9 fFYݾks@ҥKAw`9?Ȉw>9sxVΜ9#U:F:Xܕ0dP⌍0,W y.d x'Ոtjx/tPe K'1G4|kTґjp.wK'zG}l:5BLbbN(4(7F xʕW҅Y+Bxu// $ $'y:$#;^cL/v8+O!MN.JlC~U '%=?)xfȤ$7Ԩ.ۡx!aahfH@laNV'H_,t0K%-cɊ%+7;^ŸhR H7|0ZїvyxF&X Z3yt5Ba&a$aFV]WzjU=zDtDWKg^HB '%Dw2ұY%=% +#wT9}3GpDH/G/\ikh!"4w\Zr ېCIIO #]v|fo:z='[-H 0ҥ[ J0H[-`aF"]֭a  kFt~1E,-%w7-(W\jnmVdIٜ]6Φeʔ̵jJaí1ҥm7nptM6% N uvcpŋ/U JŸŊcK]nDk ?~$tQ| QAg}G*V_˃sI[.uߴ7HGTgt9Ew\ضmԦMK#@9w>X7A ^reX'۩I7|3L, 6#z+g5O/_\kq=` 4GpWWv*TaK6mڴvfZ0`/Q&Ի{ҥKַ~נW^9k,ӧO+V@EY.m;xt{B]@xtHώ3Y`gׯU}ݨQ̕;={8O=yX""hX*hH2_޽{Vc]vA^:ȑ#8gϞgr-H׎1_43eʔ}qڿ;v:t Gc˖-#;|0 :=W~we ӦMџw}7 "]HwdΧ~Ɵ۷.dj)33_`7n, ;:u?Q[o*f̘o/e;v,X7nJR СSAJ<_Hn:oZ $# @:(vH@K1d (5I>vo-йBC裏J8:{F@=zG==..BhѢ>-*\޽A~:]2P/QFT $'.jUHОo߾$[n̙#??8 ~#pAv /.X f͚ iҤS6A\#G4k׏>X?9٭[73nё6l=V$Żayӧo޼ߖgϞ/_;/]tر:uม: p%8qU@#ķ 8BO07x ZFn?s":c7̃>E!4uT(4 2.\?᛻poݺ$x@_s$\#`[gͷKIbcǎe˖&U\#̉'L$C`B/ WȏWzɍt֯\"IuTx2tŸ֭۴o߁t>9^g 0*:t/^(KBS;u):Gӧ[cp}-8 / 2788W@4D H.]S/姃3g@ßPנ@A9tD|9`^|͛gZDX.Ft~N uFC#MlRۨQ(=S2/ߐea4>DH b!ɊByoA K@^z GA9X:t |Wa 9Tg8r1f GE~`%Z 6x8E]hix!\! 3ᾠ!Ȯ ݣqrfC׎?uKJQ5"|{q$ҵ1k0*Q. DڦMXp#茁\8#Й,KP]#F(ܐ؃b6͌hpD;z/CSХ")?$jߢZ5F M U2#p q qTFbp^CCHGRdОefs DJ! @u$DoiVEk>#kH}0[-\"Q 뮻.CT\HޗxPb4y4YrY8gc XZG6600t3H+' >ÿ/#(y 1‡Kbx N%S}HE! as"J#t3!ש F9(Y 2# H7y|CqM˖3yؙqQl#]|UZ`C7v2h~AHj¤z?Gb.17yLZ0 "P $ah Ġ+@ 2C-1I]]8Y1*F#n@ܝ1 ӛ[hD] Zpɒ%j \ Ap'|-\f*vBC(Ak"f(bIQP0!!2`NzdY'xp ( ashEþ|0;M q .JF[r jGp" o;F$!?=A?:|aRtZ=IB#.T:#Fu1 -ࣧG$u2eXE 'a" I 9PMv "45'c?Qd a8@@PSs"D*BND \x1 D~b&Bej՜@A ?>"?Zleh!UY EP P L C !z45-1x|fP ¶T b]1 x|愑TBHֽ@C̀0Q0(a# @N( "'1ĵ0MeO>$ )TX@UIjA\g\ HGbgȀ6j4EV~>V3THagEn]?MTtOW$F: ͛o5w/WEaF1o& ,yc̊Ůnʀ ځ Dg/ySKhWef"V$$d1Jũ@ P˃U!S劊K\ h ~=7W4K[<3[`[` x[KУ#W.Y,  \zeo @ `2?,I/Pnq|ͼ,CTBAcӧ- nYB@9gPe-gP0JB@?9O -~fCM1'>@( 69\fBK"`HR3D}/bqANspp 0L/ܐn`Vn7E#d-~x40HTհ=^cR$ 51Lt= [.^[ $ Ƨ%[ZR#W0 FO+o9 lBIhZTR?b['Z  Dw{[gj^l@ zynV%g~u},Z%oZ'K0 u MBʼ>Ahٝoh!0$QbLziS5Y? teE\?-YP֌ba{]+<ޚ X\O?4( o`=!7xB-&bylۃA1@ dcKc=SxnbrDhP&^3 C 0@p#8S%:+Qr;'F0:$HRGΙF:)U:^ʎ`_ޜJFDݵzrE*[$xҢT_:.EE YQ98!t"%d=uOEOX! Oh'.JE@3d\vTȆD@_l/3V`^2EE2%srZUiwZ`fr^5K ^* EO ?MA,vZKdi~(C@ E=k+ZIA~ +ָ4 lX sZr-$TƀH+P^`윦7 dO7R"h (S5x&lX$h 9&B0&B?SoCF08).a hBF:} GdۓH Co] G/^.٫|y8R\2bDH2ixNEsԜŴ1|OTV䑀qI68Bu-^Gj#Eި֋|UbKV*_$Z/f YP 9jU0 jRE]3Wg|a>EMo!NuU o-#9-Z(DUD5q8+ l#-T+Fݰᑇ!*q# >S"3B:|J؇?׮]+͂8Kl{20>tIga4,l D%JaFuI XB}JwKJJv*]Q*漳R骅=+ TT^+aTgVr *]){.X<(AH*]Y*8ۥJW{nӦM+؋"H0 W|57C3E<Sį_dF3( )*`Dk{a Q(r]HH'8qrw[a(>,2h5Z.T:P5Ji26 <toKyXX,v >T *[Av[4NKw>tXb:U_t|˪>mVJL18Va,yjB<-^, cD찒h-|VuV'"^*X*KZ'0=!+!e"U\ 1PnDFvTBhUxYb|*I}!2zJ+I1WP/+BeƈWĩtbrl=3hQEī8  X#Ė #S[x}89!Kor0ccXƫ jF:#t2UwFI و _o\@g:/ʋr+kܩU(EDEtIAa62HC2":v$"\t N3,b6u2K3\4+ 4rPn/f#tAa*LΥN#Vq@BЍi~ch1 $Cl~cam$=cò@8C:o.E~W<}F:UHŢHꋜB:Cwj;^e0#]\Y)I*6I KHtƏvJ9T#hY.* O6#@Ѩ<Z~ |jU FI #x(H1IJcPDusUɛ.sp=㷊10?u<:F 4ȱt7֠ɐA.Q P9GDt`UұJ$f@uHitPDiX =8$ځk$j6MqK͉nBC91 (S9'K5qĜ KjPh;>[OZhg̲Sj(߲@+{A@"Ʊ\ax."PҚ8u1ӐnV;z c$%!#a|vH) '5>X"J-QCJ6'iN 8@: y:eZ,xcCx:¶m kʬepkHc>T k87bzsğW6#P#20qt`&< e^Ta״#w"9P+7׃9\fs2Aux@(A}fo# ~Ub*lu3b]bjU* R#]!ODO@Jt,T:rX@\`\ҽދE6Ot8h:u5 ^'h(gqA-qD ]a9]7lCׅQFnt(c ۲e |7W=w\D8;<5s! XHS*Wƍqe@:%hЊ`,\rK.·D`mn0`C x70)`E͂_{A! _=JV+)֚fЃќaX\NpH[o ,L) DwhsYP}Zw$b2Bm[@(0;36_[o%pP}]fPJ(% .ҖDF8!xQwEj|tQ Ǒc;QQ-HS,gIL\N,|-<[=]&"b@raW!sD >6!d[ 3x Q&E""-\9<\ !e轰cΆ@7PX/Z2"z>4 &8ua$+^,T"b5ҦԣXW'ѺyD+ g2T)/eߴ1HP A+)ppӁn8CFd.=:FtAh\fJ[ HGB]tz&](k.ꘟna hBA1Y [0GҥQ %P8-|4z6ЫA[ j@T^rb2UF@BZ5Zhgh BkQqՒUz=YR,.wQ@dC1tP5E@mB63dB?_`n8iL cLxt@"P j%j˼1NpU2\\\k#j-2k/-% {[h8\2JiF%XH_љxy U"'.) |sQ^ (? +f_n1fe )荣 yO|B);|ʄ]h$7 wH:UX1F̐Aoψ2-sЕ;Bv`D`Ds,9}gۆR> NR uvƑ,XʀcѠ@^wc(UET֭UZjHWMA:m5&A`9Omes<sZ1t{)nln}jR~F|B\ntـC ka,4oaKm?s'aX/Oב9\HȂ_H9$ 祈;@:@J3#!a:j1*gK 40r?ZjGZ#:<m'MfHP ?`AeeEDO;!=C!l"?J.[e6+BN@6$d<8RꜹiӦ0OAW@Cb2F #}^sV-!id>fb`-e#"j!р9P(E1Vz!(6FX!Q -+SNo͓[Sq+OrsE>_x{1D[o `[!!Q]*#]P*A2HH a]*ak"h>܀j C BLuCjZ2rt:3Ly:i$fB8DhS=0ҙ `.0hׄXw\59@rS%I`&k6kb;hZR|ysNtp’AuSˡo(A6/:|Rg{\`+!)eL8ew}'EqXVPT:,WJbJ)@11: ڦjJZc"^_VL P2BsD6hsW- YNyUg@⮋eg[IH?Z~KGQ&Cz1g^geҲLA}F:l-$Yt@:#~#~3͑aE BR{?w'M:ga3a7z8k  Z@vPs&tY<_~u4Iu+A|%}VP kdX .WIuj9aBo#` 0|EG]Ermx*:6 wÐPhz#0(Fp?-N g)AY朘5┐42310Zb7^hٲo~vf&pbhTТ@ +;x? ) ZEeh^ ZXu"D5bԣ|:4_,(PJPZ ~@ C8a -Q+ "a^.HKn97 asb[ވ+n Sb;Ҁ3fΤ̛?t|qanybtֈ&a,Ёz5&ac Z5똀P 7C2gD3 7@_7.WH= t4v<`krX:hr^603fHxO`SO=aHdE\.Qx(<1pk׮*J.T#@-sQ38#D؍Q+M,Uro{f͛A:j= .0}0p0űgHcbaLr vLk靖Hg`ι/!.[vA*fq CFx٫ #zȣ ~FyZb0b2Uo͚ݍOWp_~i;n6f_߲l>iXAdØѠ. tקhH'.H+ĚqX Aj"t4T6HMf+i F#a=֧j!ZV(48Ӥɓgϙ3Alժ_߾p&H;zأ{w ؾqa]yWF5E?G;ZXzu.\PX{u}rPh]gB6g#];?-z t* bF:%YT03zBchpà;價"0 W1+CfcG Pi+T(wkr+-eC+G C++LaFd$)f3%9᥂C ;v`Nx%n@g}Aݪ74M_}͑C?kݱ}-_-##]*|/)iHU+ꬑfa0mQfG']c.U:́ S.LyR(aEh-fugnAB$f~>^Jc L`PfHav'L0#|H7pC m[4xKAm ѣpBoj#i|Cľ={jTtۍM~kLHw##]JBT*Y TY8^iD]l)0 ڷ~C7c 0 T:,Ɋ'KyÆ j;HX+lX7Ç+w+fUj+S e7AǯX+c.K=p_7ހ2Ym{nnvH-ϡG:|a=v^s+㩆S{I+ $%aM$&n!ygX sCǏ@3t[lA$@:H5t J~XB:ƪ΃tpvh׎ [H1%u}I`"#t`\]s!=tsΝұJVp7H>Cnjr I]HGR#&O^x1rBTS+aI%"۷oG9HXkDE:pEǫmVsY>LDK Z>rĈSnσ&N2drΚ=%0aܰ!_K_;@x51wF:FdieC_| &X:V:+43u.tr <kfHHoڴ Sa $r3IK&0!nY xwk.p1;eMY^o7B,ӘaCoeJ-?.[nn¥+ҪM G:!tݰD*ܣ8zՠNa5{O$<[,@[b1P.` 1=v"nVTA8@VZEHc\tWyJ,7F:Bv͚(]Nha, 9dV C2+=)0Jcd D!!Q]ގ>h9mձ5I۷FKx5l',c˓q*T@6Es=XS}yEӇ2  EXҩS7I_wkS0 &+C{_(/54.@Nm(/1,&'10&BE:P]U:U+((X`1oYR#]H&1ҹRD:B(3YHSAu*wZMc1@tb t^sa͛X:Lz-&2yPV O !Hg~X,DEȡC> H;MWR?޾* 1^f~iP_ڕ+?] 8uȗ޷Ν{7o EcA0Hq4TnW!Rn^cPQلG9<"ԯdȑkו2b{GdFi24Ii74VW% v R00(}YOS1 ^Y Ȼ˃}C܏,$1S=A:A:P]*! 9RX1mv54/zYxT-2ͤtƽ{\Fhʗ/0$ZHΞ.p'ίSLHp .!˩w%͜9ӥP׫Gzk{Wc68,'?Ch*#]:|l-I kt֨Qci8^1c |ގ3|w/ F)pFh UfH ڭ1~„StqozDZ!]aLt17ydsT*0|30%if ^!!< H7wܨG[)tP̣9czvРAڵiHt^@ZC#K8{7FD{钴[feTC:Ht.\ &2~!;^W{Rx}woɞϷjBѾm[ NH~e $E:uqVooŸ=t~3dnxf9OjMutIڭr#$ӽ{UVm޼ysO߉GMO4=j Owo54ur-[Zs%eH~e $MRzu)@YlԩaSow}31;L ",0Ɨ{(xŤ7xM+͟0e2Yxq]߷HcKnHK7R8ҥK-!iD?~Wh$|C-6mDRfe-H*7-/ $ҹX?o/*T @M>|#S[:Gap˗>Hʌ񵩊tNku]={U˕+ףGOT|7?\j t^@ZC#WKVhO:s̹s֬YE5zK:̟?ǰ!CԪU++.*ҭ[7^d)ޢ-Z۷Ov߹sF/\i`Knt*aW߉+=Oi5jM[lITE 6k׮|xCؤIcaop::>|#]$eWA:|3" =-Z4_aT!yEuc—0?0nM^O"Ht]^}*T>}Bvce *aj.;6,f^G$#_Oo?|ʕ._…KO:r˃wpν7zi.^nci)_I!]Iڹr@Hn:rxE+Bhuyt^Qn>8L;i쌉O?Ĉ=z<`<$Ȟ1cF޽öX\.tֹmN&TR%\0 |r,9|cHI~t'LدǏ_r傂PΜ.. 9܊pCƃ'1?v;*\i*qovݸa͟-rR@{X㕱Pw - VVWH':WJ|y\(%{ҁJs+ӈ#,;  ;8vV|L[nݻw/C)a۷$}R!5r:]S1ƍ qnĉsf}o?_&ԈzQ]qܿIj+_"Q]Hg؀6KrH@߿d7-0X9c0ɓA5A!ލ3&`b%ѫQnJ޽X"kS`܎;V\)}D%;-Yڵ_!# 5^nƥa*@*`QdIw+$ňD:,vtQ, -a ]l@JN1ټy ."^B]¼WAiܞܙ63;rs^nƫa*8mKPJAya'2,-1RsSPP 6gۇsN<+W"Η7nN:d2#]4C1My0 ܯ:ENdxmh&9%QRAd.X1.TyVWXXhibֺ'"D??x嗡FɘQ-.e1ݑn gzZ`7_ !{2.bF:¶Vt๐qH^0_Ĝ#b@zӧO\t^zi׮]i'aW_}QP& : ƻLAK92EhĹt\`==?%B]cꦺH ׆t8Vba7`wK \4iÍduMdp2ҹy"blƎ#yݻ;tc@}{OOsvĵ_-y j(q^ [# JdQ/m%6Ja5* RvmHbn]aaWT,c)SB v9!;ފMdH&E|کCHt{ܐ`N;z"ԥUR ]<:x)~t 8Qow[!wߕz{t >ApU tJt B] zX"W=zx7HÍ{91%I3 ?y"B:կhZ4a?}"0T#TV"3\dUB/ >)ta)ǽ;14#]ox2>x}Cmc|vqÇyX8^W+}@;u [m,J{ =,}.Zڡ*pR'Jj`6/]>}.\LΝLre˖rlǵFXúu놃Psb$,f1҅t)TF}-AT3"9Νfm0_O?M7ۤI]Gĺ| Be-.7'4TF}&!d\ OnH] rfDA t_M5jXnB&WG&Y*;'_BҹףZjϟasE)gPw7wy_ qN\fՒOߦg\?yْ0 s9Yܘ3Fˠ@P&O[oUH*F0ҹljo'9U{u8,jH.qJ(2x# D:Q&u_D5+Ju:ܴ˜VoMb\3œ來w0Y%tLY94o7g"^Afȉ D3L>ZG;ߚg~u/I}SmysN[D |2a;N85$b@fF:0m#mI3͌Ĝ-ҥX:|c1 Łs̓ԫWR9o%\ U@;o#G`j)p$^Y{ٮKˊL̜9SPVm9jϼoĐ;Kq3Eta(;w%QNFtAHt%.|u',Zja0@kF7kf2>G ;;3b겳2o.{! `O=O:XZ+jIvۿ?fk0t>ȑ%|z{ʔJ(c/^}-ax_dIy|̘8t b\r._f նFvF46tQ-6HGc_ؒ%K{k<v8\BP{' -!qa~~>nʕ؀G=v옙p#]9}Sڵ+O>ٯ_?T|#tb&/cۃo׺tSM4A65bAp׻m6P.\… XQא 7c P]=̦d J Gϟ;wgfų;wٺumǑhaF+_1.zz4#]L5ct#G¯ PjK !ynʬYL䁴3f }GLd̬vf nQ!e A[lxEYwW ] x Kc J @:0:2Bd}Q /y2e _{uxx "&1ҥIgϷ`ɷfG'(fi#^Ŭr52Kh#?F>Lf'"up}lBTg+"h;m|MعsgՠtBC*J5j4mڴ͛|AD?;/x֭FjH==cX._QuGd zuJ\kvgdUE޵\XZ4,· WFAbyReZtܘ,H!RDn2#Լ"3y͞ݻnْm۾!!ݔ)Sp,h2;v 1Ƥ Ʀ:FttC 0dtaw!Ru,]vjOڨdŲro5ntt,]*GP9x^3NP@,#UԒU%fNYp>!]F!ivd!!50jHƪ]{Atim\~EHu3!A`zPri'Fe w*!gdw.j%j,[Xr Wg1%籃%DAWčKRH޵$C| 4Jf_*Bd۵ ڵic( 2.3ҥCO&HGta}G"D5kF`yVtN@s}9LXZٰK-ɍȆE.]ILhzFY8Na^ f)mݤhĥqÇ ~ؐSOJ9b##Ν{7o ]x/ɡ ~>}CFiȐH7$~SU1܅t/W|/^ ǎ8t_ݻ7me.]2Wit\T#;r\$*UR _cǎշo_Yh ba50}pzjqAaJ {StvWGեS'_ΝG&,1G0B_x…?tngwܳuێ 0ElX >HGIB(}E£:"O+aɇ} :uowrU?-7{rYH \. 5]Hx5,"`YTPx@QDBXE- a]<~էYS+NfOW}=ԩz#Koo}ȏQf ࠼nq/Y?G}tڴi+zl d SosyiQ'ZPIB +5^<c˸ ?wQoW_}mW_~ySO=&r:BN Nmѝ.H7|qMzaα;z-#v,>ڹwso:jSv(q7|>+%tAFN<<'Hv;.RkY T"] ZhdCfA`㷞n}fնn$jGn9V¼y.ұ18{kgMOoHܫt,hRUkul;(UPk[o'!ݧ[[}.M:jY/8&N57̆`6Ӣ#?c"ҝWtgy"HZp`&)H׾Hw&AR׳&T ts&L>g!/onͱ{lH\HD./[H=xwX񚴦#um *vi￟Xmmm3d.ߎ1yW?sby~:6Dq]m& M}]y\CoGΜ4L3w/5 {yJD:rᅊtͽ?{#8k6H7z:굃ME:# kp z___?x֍:r=uNuqj>87 a3ݴ:&{"&fY㱝Fߦ=m&ۄjtl$հ\sl;j^z"Hj<чr*rwi;p`"][f c+i G@|;4 :w6 /@5={6t2%.X1:6}ٿU!6kAVucVfgyvqdžuVOTgQǦ.t.pN#t\/SEd tguֵ^J1կΜ9M/_#l:|#oel:ml,>Mxg}W?twt̘1grFysjs!`ّ[nmfH[jxse%KELSS˯#VFs9=L[ .zjڋmUqVpŊ⧋/bDwvmqmBcPݛo~P2p1ܘ1r $^p衇5>sU\!5\$`{Wh`"]~I:_qfUstՃ}FrF>jD;t'xB t"nir-7KۋΉwo[Zƀ]R$aVK 9)P%dG9)_W1NsMtl E\n-]zAEul2>uycZz~qfjƤItÁtyf GOW N$[ԓrąշV՞p68EsnY[Nn \&Z'x"ل."L2|͙pϖ~ai!?!UGuoq C<2BGjNn("%)SiQˎ>(CdLmW&_O:Ou9G/ˋ= 8p9s"]Pa8ΖrS g? >c__{S7o"^G}sQHӰ[V Ү=5 4+w^P5@bEݨ<6pj].+)k 12~tswy'F옎1lu̮Sv8{9Gжj+Z b\?矟NM|s_hA[,srRLƴVR@\tEGQWƪ%}#A90q{=>lqd҇j 3T2'_O:{=jrPzzڸ}D`yX»։{Ͽ%*dwx׼^s9?~knw5z_y'ja1~mpQ {H$"xCul I:tFL*i:c"C]wE*@+ ږR"e5W=jp"<∈/~XƏ[cf8Zv3J GrCw0gLбD1]VⴓNH-#:ɬž&miWcj@OC&n'I\5}{tw`i;qio]qu>3H{"ɱ5CuTHMsX fҥcF,7~.]}-|S꫿AxWLvw2qNݧx-!mg Duq鑙A ĂEq8Z}k_cbTw9ސ2-BիwuWNMH;..TkD=PG{$IdLꪫHۊhGİvw-b#N2:yكOp_ 7x ZzY ;*B-X8{ٲ (Uq3 !Ӌ>̻!0:.ޕxφ/K0r.V"&85C=8R'Wt21θ"+Adsg%z7Ο9ΨKj~7^:Fn * *|xU.H0W_OSR%~1s"Oa{?r!V%Ȋ%?ʘpcwn5qZOif]n;n#~޼y:@7|3_;S`{8ۀ9H.CI{}]6|G2Fh$AgtA &3)K/$~5yr6 *HwM7:s=oD40ː w+ Lb0f:t7s0kKgw#! s&Hq脥UPq5$!:eMt _tYz,97dKzlZ++!Gq…җ,^mV}uuQ3.H'=phg‘ɁJ0``Ndz9o7Jw5"=fy2tK>5Ov3B ꓋, F*2 Kʀ%$H˄ .P9@Sy-A:ul1 LoH3H7U~{qO\^Ct0lV>}Hidr׸@"\dT~ (6DE3 G} q C|3֞|ɼ Ar EbqYy ]pIJb9g\+ ~\r%tלlQ_lfCfϙSGS_]-d]+~zՙd*=iT UD]}\ġU81K{Qf }ӄ م1"{醡Wt5dkD@Ϳe$L+|ζHzD䝌0kX{\z^=j ħko,GЎ(;,BuD`%XB>n|L7o): ^G:E>K 'q)Aĩk! /HGXbjg?C42+׷YNS8 n2UeLO@+.13]F.(l0hF[xF5}W+&@rMɁt4 !.w؁[E:o-.rv.0WBqW/aY _t-_Ov6Ԍ׺)UO!~„s7Is寙i/ }WtġS<c53teT?Jn'H]mamOM9ԼC4# )yȴ9` i^A:5S2d lGftkc2m} pjC )A8 h qVzx}@ '+60k*H tJuzo#qsTH\u2#&ڤ?GXr%v毙QHd6sJ:u* y3d/ŵ3a=d$yW%#IVih!:DPyZ[:D.ӑ &Cš$:gڐ9Iqr{'Hklv.%h²{MJ"\%]D+ÁtPݸqnrIzDyEۀNYiY)Fhb#mbz1t<PaZDLL rՊ3I.bD,&I$u׺5Oلu:AЍB!(C[ZBPD(|bLRD:& A1H]:f͚"-$3NZS$1ȔG޷3ftp[-7X";OH_H@P;bbWGŌ+nY`1q&)0)푮=j*G#C8Ûe8M\z鈟 áV`@4)P dƶ1ư,:QdO"Ω7}c BHx9Cajǐ$}>=C9|K?,blj=AHX ->4doeɎBui`4-t !$K ]0L $aI =?<9`-CuPxκH׶8&%m?*0qx(Y Fxh[e :͠a9tF0ZNtyFJ B#$oQ 7 l!ELdP<08 }s)at~v:#PJ7>c,<Ǵ<6uvtQձ1(TYبkxK糴%TG?QifuledP:6uؖl .߹Ϧ@51vj6R3)&RLѸ(!Mu IL1)&>apR[ ՉA0(h!5-):wذK6$9Ν+w J^mǔ]t nn3nM:qN<KaycRO[t-7[aL2H1Tt9 1Tk#U< : DH1;)e.%l$6C _lZ1/zV/38ss];}O9mhAUgˎ:; aV=r7 `5J :l1ڦح|;v=?aE@]A ;׈A2BA72{`I"9Y('k.Le:P'ĝֵ涅uq9:sØn g/:ak1f xJ }O;i!QWc˷TZ8ߴCO0K,ckMU'϶-j:4]6LŁ9掙h ?o9]j@;gl18|te_WA.HuTB(P`#0E ]@3:t5>zq#a's΅'& tGYb6>~քMztN9CHsaW{fOt'vcO^fƓƙf'n<o׊݃W2o:gqS;3xGPMhl[cՍCx_1890T ƌM=L4d)# \vg|Ta_fM6O;~gn;ŰtL-},cpf&uN941ch83x6㶚δ0nw1op´ýZs[8symomZ8ylS̲5[u=n6q3̱(1yL7{aA8حuo}-F8HW+bFy(0bv_gC-HG-/zuH 1F`S b ZdF΅Wt19vJi,#:ovl;- 2 ؚ7)a ;Bs dt/ nu΄z18kg˞78}!fMu Nڠǰ'fE+5gw8r͞zaE:c] u|\bc |JvݣtS{\̙AMcí6yBL7iRdŒa~y=c2<ޮ./*D:19>bPZ#Ru [G$esJ&> b-K׿@9_/IcgIe`YhcSm!j 8a^Ơ+$bfM(*X3ٸ'%ė)mCuUB'}֓Nܨ4fHe!Zf](6ic`"y'P]l5$NޝƜ4t[ h"]!jm*G g۶vc.nQx(Y?te.[JD a grOճ&@ {=-m!@ a"|޾cŽ[,?k\X{@%o$'( Ęf:K Լ )sp^Rͩ&\~cX/B+N &agMe^Xgw}8݋0x&̧{.{؛bY洹@$ ]6%c3]&P{ Ɖ$ ȱ0gcn A/H~$'}?#0z=[:ݴsa>%0|̈́vY ^0Ơp*)A> PشpM%yxXw1(&;bKc/1i24G:pݥ^߻VP3RjU 42bY5R;6Eć>906򗖐x_f@F9ơ]X],\WvjH+Yn>"ayX8؈kSKxX9[&l1kVHD䓁tI@@<i?IYLP#)^4Lac KUB|e0aF5 ]f=<{^!ήܗX|ć0DZH&?6&B(n 6Ld:9.vBwĂ F]Yxٲe3Fd.&] 6~5H&KJ8TG7bdAF&M㭖HWZ Q͑,'W^mL sͷ\ CCC3fHdY"bsYȨM4dIdxacYwYreb50Qy:L5e>=5rqm5NvysR;ju TfnxQv`m!Tg'ք]ZZPd :]H7y{xٲn-ox^ڟ;5[P3RjU 4oI!xT]2^Hm`}֬ÁD&;3fD*dE1|>É"5gϞw'Tc ̜9jĚ#-L3?/ҒA"-  rˈ2-PA.t x,aH7y_P7pCy_:HWZ Q9H'#F\)# W ?o8BUj$n=X#7sj/S1N>A"cœ[aĚ J/䒌)xpjRQ\ |/n5^"toLL=kvAKd&ք.2¦k׮%C%ȨHq=?&JH-[t#縂V]pKλ+()*Pt-56sg|~iTۂ,:$^1lT3)$՘FkI`ʚ/dfsu]/2? 3n)[n@il{k.XCDZ @)+VS },%Uo& O5^$ĉ qB ]QLɧ( {Ayٽ7^Hxh;8&D=a%$\;A%3Һ ]K}g$ p¯6%i'j?˷?(ĐTZYG|Z |E܆-zGxŸbx}ʫ0*r-t2ڬ6;#=;Xp뭷XZ!xGH5\Asט+;0ť X'Hˀߞ&2 $ *CID:[s3N YԤ‰HgqqR̸,řtY@L\kDD#>?NjS2Id4sF&ϡᗿ"|+1* Ԣ@-^yW55 ϋ#㩍KYťٳJ pqHM W(m:If9vt ROը,AX:^($&3 a\&Y̮&ebp- d YJ^Kt?G8|ZӨD_{v8ڦ5y_)q /+HwC=Dlϑp^x8v "H'U@El#ԫ:jC0r+FS|i|I$ 'uZkbI@ $~rSSm˙dgA&a0_)s MEjB<1U.Q(F|Oa;Mٮ2alLN-C|l.ū/^z)$q:Jȁ8/sR$8/HVaN5B񚤉pRjt4 /|_5 [#2N91R'ͩ=XQ 7m錇7i:H,m* H5xMС 3Ke<:F6&r.&3g 9ši-a\93ea~4s@B$2F1up ,S{ Ł xi!v́OYq(bB[N0d湎,/nj@wQw$6FHedV;ωm@^'K arZFHj< |s{uYrx;9aHCvAȣ#Ju梣 Nħ6""ȚgٹDY,W/߭+6d˙ߟ8ް5z ϖX`8rZˎ^ ҺClaR, eײhm s%";eFV @$A1pi8MR0~Č{ g'a\ ב.]`1p%9^LYBE Bi3#+_{eEH c60/%0$! A $($XV& kr5)3i$J&xA^b Nw%dkYtD `rZ_phR؃<69 K sc&.SMၾK"z=ߚ]`.yvWy姺~&> . 󙮴hѢgJW1@/qv d! Z%nAB7X-p9#V(R xMhVRxMK]BL&Q" AL(N5[N 3{b-j-Qt"eZ `bMF-BF_,p¯Lĥ(;01' L7k" +1)U3jU h e/@8vc"X #җ6A)+rqiԂ*Hc\$:wFxjgNG68sU^&VaM\Ļ)̐C= $::8HHk$=eWt\8X9GPme`.yȉt_K֥k>pDOF/O R~zhܼyvYC,>H.Uxlę"xvm9 N&_մ=*PGt ,Ǫ@ 2^:E:>fG)ַ#\Z W6í( j) 4ʎ(ZAP@Hi?2>IEj0M%PCWo"]GP=*R TtlV~u(yj4TC]22)t-5jcT&*P%1xfg|j?buVJj0M%PCWo"]GP=*R TtQHߔ(ҵԘQ"]VqDqDqdq$Ѿ~*)5qS-""] #6ͽmZjLƨMT@NNNtoQ| E&zjUPSSSS("*ҵԘQ""""""iQTb+HHHHHHWL[ (HHHHHH* ^E:E:E:E:E:EfU@PSSSSS3ﵨ@PSSSSS3HU@(tttttt~EPZX~fVt^|ba/OGvj0M%PCWoJץU@h=CWUO<]eڵ/#R@II)Ϗ.4RG{_* 4D,h?='CZ~ )n/|&ռ@y@:Ѝgpٸ*7d?nN>,҉3kIEN*"[GcRv\w?{o]u[_W5Т ) Ffã> i&^:΢#*!ZwvlAut#0]k`KS]d`۞}ךWa^?U@HT@NK٣zpʊt:67xlV,V,.;t}\s䭆w vo7x'齖ZTU QA:P^a9&g?ۣ$%"c.#䩩TR >toDs3g+ӧOn+W"]qjm*G*Nzе Cbu.A:-\/_~73wKgD:@P^5 ~'BugumFDŽ[t@Y to?mR`8HoZsDMrѿ˒A\5sЛ"Etm;M% H7BE>kXE: jUx-|5ni(ҵ] B:qԩNtVؑ/#|YH[osHCD* @ nHjI_ߒUL zv:6̚p8<40+C{ ǹC d@8=z(-Z((gy3(j}Q+W9%Vܟps'WVQ򓜭YɈgCO Eo`\Q#݊~{ 3j*Z\+7ڻ|q;-GyIɭRzj ;*ҥk |yԠNжHoΨ" \E,. ERݽk3^s2< 02Z*PPx^p'WVSZXOo[?tvehjpzސ3ԟw*!ɬW>!!X ϕIA:kzﮀ0@Po*1{wE~цqG hb'[+iY0],n|,{)tP].0wOU?~rVteeV -"$9Hg 휁t$4$;R&x>%0i, {L:TJ=Ffo2j'_B* ӅD ''KH(p,G\hu/s: p5@ A'OSЇKm*͡Y72m|,zHw衇Gl7dK?yiߓzH_  s a)M{?,3SKW# xp.2[&\_ J%V =3)l}4g, \PNKNJ]bqDoWbs(iux cuc%\;q\sqwPlal@Rr ۩kЏxײ(7;A6H [Gvl^!;`3o2^:R]Y[p!Uk@ssu|¸uQvc,8sy.P#؉ѝ[04L Yd$zעQਘzcˑ.:Rh<(4t&ͤt%&ڣmP6c G'/"P9䐜H'<7ue˖)58t'F_] xvŏwr 5" sCEć FmOe{y<%ΒV#E|i5"]ܚo\NsG&Ⱦ^,ex&Mnp t F:F̱1o?ҿ(yewygŃ>;u9~KҁtduYެٿ^ &!L &X2%^%\M'JNC)gxg]8; ̚>ļ҄>Z'8B~ $F;¹֠Sv:0WW0R .J$]XzDi%`qx;f"a(6Y P#1womwIZhKJ{I.Y5+KlA,[>`A:J|b-̙|t F>w}7֯U!HyN]NFD_^/tiH7}tvյ҅!! ^ .2`= GDn|*[s9%m#^GDzmg ]"$`]&eὌJxOsE)}Õ-b-xt睴 Tr9דElr:K]zvbХ<ɚ'\&K] /.ʌWV;蠃,s=vT9ҁ}+W"]WǛo+/. "/@:ީ)Ԉ(/=̳ܽtiHv۱ ;a4KW:sf^JRʻj v dy, e `.‡zHHᇿEK}o]D^<SSQg{ɧׯE. 9͝KJ 8 @ֵ8GJ[f+S<@F:ڵktFzן{u~uQ7"bݺu/jD~'*ҥ!яg( @;,ՕE:]$gE{~oc=ШuQ>~_.P##>ER'/"]"y[k` @yQ"ݠ #-áuf/~j39ȊtsUKU@h},Y+ ~\b쌘~TU\=Dhe.ǁU\*8_+imiK[ ҉Ζs-* T@N@hK\/P]toƾkuw}Mx_* @1Pk\; G:Ku.Z* @1Pӱ_hK >cn͚5KU@PTb*HזùvJȅtBut|zkUU@(Q@N~U-(t⨣HU@PTb*HזùvJȅtBu.ҽEPTU (د  ]weґEPTU (ҵpR ^KGQ+[۬ @DE:UTJ{K* @1Pk\; TtojQTU@(t:m@.xec -* ET@UKcMة;-:MjyWa`ߨQ+*͆F>ʹe j*mVTUztʣ7Vo % cO `ShmE#睰 $ X\ըBG.WU \دUӃb2U\5cR So\'Hh"5ǫ^_iQTU@(MF!8[DwB/kbTvy}Ӏ3 C@H=vLT.<ǝBʎxZ ul/u-WU =mE򯎹i{__ 6J{M* @1/y.Q/>eL>dC!1?DL *΍)Wx ⹡h2Kg0L,O\/aA0I J4+i^ Ӻ{lʩb?2|'%\]+QIlo6Z];"W ѣG?fj^V* Vgi쫤qpdp5ü ̲J女'2Q)l1`Yv5F!K)WEy(%'sY_x\bVw2fDCohk~ҮK+Xg<ҽEPTU Q5XEb>ժ* T@ C |?W%e`(?,[oIJi!]CW68tí@HU@PTb*Ps觉014N_vkă;?SHאKTpoU"cZTU@P@mH@809<xE<64N+'\5 i`?ymp7AfFshGg Tt?ע *PLF:|]FM\eG5C>uPNQ )c_1ņM-?FR3lEVt]n  z(Fen_wu/^yb>Ǵժ* ? .(Ґ.^'N L*g1n8eg5g{iPװJ{T* @1 Dt-){@ #^ 6dk橗.W͹VCaa)%K yѢ *PLF:Υe8lV5R')jUKJ0Hu|;Nrͥ lƹe7\6g\H'`^EPTU Ԇt}0_P&^')=k"&%[Ĥ %9'_НuJժ* T@Ȟ=ZԮBW:6hnI}+%޺jI꒘W+rzVWXo?i# Kl-nme"@gu;gIDDu1JT֞1*xyv&vw'~/2!/6kG>҉.~-* T*sF8wSqGT<Йu b'ҕZOe8t@dm#VG:mjgrܭa =kbbrf1fz }Y:^:PX&[=pՒu,Օ ~^^Ӣ *PLB:h)2V8~gD,+te=4*-µ]ˉ?9›<1$0,Li;H.=6W's.\(HGQSZUTUҕbN$ƂUU tk֬cѣGQW8(Sm*  ( 㒿uaLXެy[Jt׹g@ث{}z6of 6tM=+VyӧO?o߱۳=~{^%{D`A_) ݥ^XsO>H1^ɣ"]FP WHk0ojQK 97=1bH0"'-ӆzf.W@x%ռ6Dݝ瞐4'Nn}?x;|yFnÏ?ts k7qyFKTJZjƨR@!dEzpON+.a!]hSN;!o/ &"@<ҕqŝa5cwuW\h{_+}|wa;nWNϧH.QýGyEzjGh)@:vHթ] IȠXKG+I ݿdQ_O++_.ya8xKS$H9Bތ{fmΝGyE1@(tx(԰z @09cg3l ҥ\gIm^:'[( ]wەb'՝zDE_,)-#x  +4=""]xE.AtAՎ*R H'/"]AH@[I1=䲑.JK!!%؂| iC kҝ$Cx2+=6,TήFvډ܈{/ZF!Jħ>7ɒ<@_ڵk;7y< "]K U^ X4& ~ƀanY&#Q,tjt`0H+HCAG213<rx-'Ms W_}ye/Y{ﶠwCH< "]FP N~#a>جcW^#~+;餓©[ so5+rWkaX K8ҽG )}áS{zz zGy䑟91b&+m{$.QWvTR t$XUJرc̎ /2[Iu#JVĺuaj;ulm曮[`F`FZjƨU+w=\NNPTq̴c&#˼: HXBa+U=ꁪ@K)aSr0t֚@*[ưŧLۡcڦcƍg>sWX &}Tzr eFZjTƨR@NNPT"]FP 4Eozv h5U@9 (5e֓R[5H V@^#QZJ*vkL} *P8.^yऍQTxkeW L\p/m* U@NqA(6{}{ߣ^g* ZnD ƑN* xUJPFH r-'x"hQTU@PTU@h)N8ᄛo}l)LxNnŊPiWQjRM+krOPM*_RWʾi/h䅽e_RTqC%pg{͏5^)*n*Km_"W*u){q[[mqJ}&ŵ_:ށ-n}%rc^Zs+}K_r7=zӧ\3ϴHg$_Y_읯=9ҋ8<蠃>C9P,aNY^[9rdKZ\UE.%)\k)\wp'D G_5+}统f 짹 %.7mo_DNd7r7Xi\\{)vrҮKc*~5x'>7w~0JE7F'eZ{թ3ɓ>l(Onڞ)^щ5:n_!5݄Tj ~ɓG&L7ˠ[Y\j"#z8$:BT䁘viT┥!?E({ eKu_2>#TUS)鸯Tg*u9@=1㾺DG륶Ꜿ{>Vw˕w5Z ,E.3RryjTy~#g CJu؝i+A8@nu'Sx _ҥKFZ].C*~nQ޲ ZJ?ljҹ ZǧU<֧W뒩.unR]xG gk Z_]䖨5-{3*TժS<9 p g͚5jٲewx8.&^HhV7(xx" d>-~#HbUn}SD{q[>ſDM^ڀB(mD~ꩧ :sɍxkw3-* * -؆邏N:?K,4#IENDB`fritzing-app-0.9.2b/help/images/pin3.PNG000066400000000000000000000447471250202676700177410ustar00rootroot00000000000000PNG  IHDR[σsRGBgAMA a pHYsodI|IDATx^i\E#" yIB @BB= H !5VAEd_e`UYUAP`qy3/f}/T[]]ݺN@[ԩS:ubŊD-[~4csl(nח' @(@۸6@@09j j l#F&@@0vHc T+l#F&@@09j j l#F&@@0vHc T+l#F&@@09j j l#F&@@0vHce1bD2tLȑ#zQE`,,bc_;7v!裏gr'l% 6*8oKϟ]Gl#zd]_qkF[ߒ=ù"F`e`?- pV^F m]hQc]{5йկ~w]_p:(㚊`6muVt]fM0/N>dVM {n%իW'0祗^JTeKsW{;dӟnxc[K.$Нx]j7dȐnH^xd ,H{nKB/r?O~{*onz;~'Z-h!c][[xr)9 ea 8CZm=Xo]tQp- rqtAM>!ol@}6{)W?я͞=;h"=Xh42eJ7nSKQE&n馶+>_U7Jxua}c Hzc9kqp`u};NoiӦ%l!@+۠-Bp2v…msl׿>>?OZsN@uȧF (^{w뭷z衶}ٖv~abT kC߽ fJ]\5\"/w}w-8;y߿ɜmޛ)im1`{\`0N;݄cdʕ+~?馛6۫GFҥKI\~-G>|x*(k{^[=~Mfe#ƞgєl/EApk: 8Ta q.qS߹u]wZ9I-v]viSO5C[ ҷ[FUey 69;c` >- w: GNLN2*ZR@XX$.Z(®:+8oqUWoHbq%FC[ӆB!t6x1NY*V ͼyL jcM*f+%+ϺҶ`2wz)yMRY؁: .%9U:8$8mvsOy2v|Eh of PnU`k`/FmTD "K`{'gY[eE[&fz+ҟl? 67[Bt5d`K'O`kߘ2dg;qTTu}?EF|䥃-Z[jq6]^-9sڰĚnGy$2!U->$l >l[6%Uq$T%6xz5A3yF>}z+j/Q-1ҮM::ÌYL)U1*P&dc$!U`-j&Mj 9?-@l^[E]jAd |@m/䫨j~,[=|j>Fo!IOIU-4AJYP]es!3><@S8[eR0'{7$LVTeE}Fu3& Ad<`8Ϯk/" s5i ddiS5h![Me"w޹ɼ^[=#dPY. $}k J =BS|/H??GGY+&筫hY[eSlUY-!YcXTFu&Au梡[w}cY@+RȌlBk5ؒ>v FM6٤db^ŖHoD҆ g:zful3LOӦ"`˻Dȍ[Kt\Zxi+Vh p JOzO25(S"Uʚ >hv3SSO=I^AF駟_'. lʟUHP;&ABE5٩uY@'xg& AhwxH~>|W֟6CBxQo{_/'?|T՘2 /"*9fE7Ƞƶlٲ](<Bnst`kWBnjb:D!%aC9]1K)nPFDQW6 Q9wHS dYs7XbJ$BN-֬YCj~`6j9QiBM8Twa&L` :(uj`Kq;!=N0z/ )¡)!9)0JN\sMi2nRT,2i !'m,Th&EfdˤL:K Oeȵz{̺0g43e|uץ2qDQZ [2ifMYmY0'xb VljVK^"BA-6ܹsi-C<1wb!@8F+ҩ6B hQ-RU=Ǵ!͔R6 f(26 J[.׻nj ^6>Uь6J]eK֭5hЧWNS (:oi`KNKQ"ͅݩo\64[S$)QXtLT*KE>(6̑^=]zurU h|;;ݐ!饰g}yZ-U$(v5j-lZ=|6'l-vw',ȼ-޽ޛ pZ*XvwpyGG,Y!vhpYZI3k?p6N7՚nΕ`6L|^0B  Z9欀M4gn9+bJfnm^&f\Yx=Lmh&_S$+tm^^G+ j\$GnmiҥK]ҡZ ˤkyK UChI3YPu-^ˤ*C7ʤzM .'ˤYyp]@]5S&o} 39D/r=X!3`;qdɼz^c຀nUٳg[-u\@}LϻJ3r19x]&r,éb8p]@] frÄˤڐΊ^>u-ЫҳҎm/຀RUWELC!+ $.̘HFe+yi``\tP%J ymBiU*Y[@+iZIsu-7)>_*VstRQ'd'D6|.&2|H,d㥗W'5o+b}͵F="nOi[#͓׷M23/:s2)`/)"4al45?}Ɖ3>?T`ygl]A6ZA3VciͧLo6g\I21iCmR6OsFuFg&CM)#RA*?>w&Ƅ׶^im[TUk 7%Sտ|欤qO69g,[mbMNN.|~c͛.Κ4Blb n´Bli#Ʊ[#J̒beWG-&nu!@6h>gZNyeIm[6\kH iFK|3IxԿY |$ȹ pm bmJN*뱱jTuAhZiVVŐ&Nˮӛ p(ټ|UB2@;4kB;[cpm!Vd{vx`Լ]ZI}DV >m$|i ^vh=/ټ#d(@"KM.Zswhy;M5]NMh烇Ԛ}7-pqX3|[nk[$}7WZIo8 Yuq4Wѡ *CfO˲ F(lol6aOH}}C@\b{ń#h@.>CrkV8fz7.Ǐ،u`K,l0؄7B >4N>b 7L[oi3)@hC6e/oOI3R߅MchZ UvIߑ~3Om$k ^]mxΎMPC3kqB@&g#%Y?`Srǥ@fSKp Bs gn/KcIbN>,_8Z,زlG}Eld4Sޅ/93 X'dLKMO;džm0li%uY|s=F3EYqtXa72 {g) e(oֳ׿6GU/g8.@&e'P_ r4{(-p6Ne b$Կ$q&M$>Sr;#$k&YiFk9.>xŽ27q,3GE[ٽl7J‰*ba9D`}Mc.BB3l;EDw`Bv|4'p+2i6f'n3]R 3*)͒bE{B FUX.͟4FZhlgNSBޅz;)"©\}a6,=?k5ZOhko[uQ|(=;iߤ!-2! ;Cp%-4G0-Զ1*& 3\fjj:lq8f6oYH.>@P_~r1g ͆$} X-ܠBeV/l\ ZtT 1XP;nz/0641̹N 76爋,c_!4`+ifĚ̱ zl㳂CAe pqdo铝ƥ{hŤov'yyz&Ƃ73Oo,Ms8x!Ω%WVj#놶U5]XM!M)N'w,b\&s `Ϯ7_ғ&k3>ܲLc@ԇ64uiY7L iLbN..rO+64Ti>Tl]fJ)`QYY6hFCo\84yo vs Hn/%;m8rh[ڧ4 Ә49s;ܠ1å@KsMfb-[֮8T85m`Vqv5FmLkXSy%L6;0?! ֦6Ih6h?c[s ac6 yd>w`+Ni|EɌ^`+x憘#+pyNi&3J3ќü4IO!Mf9ͰEQ+-HefOvN6Vg3Q\FCDcSg^ڧ6> O}^M\>>8jXFV:z  ΁8j&3Bߒ ,VxUHo*ؔtDí<J|^IUIkg~7>e `݀D[&l[ ՎciW}]p%)Js:.䘓Q6f偰_@[T-ń4O߸fWTf#n;KOϬ +`jݡ0>mJeΥY߆"2ŧ6Y4kv[9 @Nl*m@Y9YцjWa F3lB SoR<1M29E,R<t'me%K.9&yߦ6##x8 GnwV;mCy{]&ΜO٤yL/̀'9i'AHmU|  \mp@qX $U?6Vf]o鿻lFE3TLHO!6[=A'M̍i$c ْddC з̓pl2H9փlb-[i7o]''p;^Ͼnɺ{j9hKw8HwCSXK}PRtl6}ufiXD}leLA;xMӼ^rP;5 l9Vi9en][1ͮ:.d\45lUx*fZk}ZA{"#km'#NZ eb`Kk8yivTtB4;ͦ1-&n]41܌Ci9cV4ٖE&d2/*jH&ئŢ,iil pdy8ٙ SeqYNze hI Qfc,D#gqlY~V^%4,gF*8K36}֏2к\`XMم2]^ #2fsZɀK!2j,Nd2/{ΪHD!.M8 CqwNs^BKQٌ$jҖ'sկfG *:RM %o/BW΀XHeEX[l Xt{mS0DξsG M6<bzޣmJp:swk,4ҔhQ !*2auF Çls% l>slK9F{f+ӶQcu4Zml6YZ\U!$0/r^w\|'3l1&]&}% R8HupjhNEC_jodPmqpQ%,N-ӧU56I s[r6.I[4016WiHiF(g\3Ff[yؼ|.`Ɠcγfk[`Gbߡy:؞5SlOS| QwH2L86Z>a_9䤤66&1D>IճZ𘦵?e:H!m ޹n=5KIѬ8u?᳠>zE9>jP)NBj*M6p,&Y)򦼪Y%: 49+SKK3f,}!NcxCim'w%Z4sZ4K3 bJ)2Wڧ1׎nwi J95FREv͒֯8}e-7R|-`-2ߞdSO=5yw -Z47xvj`}"4&Q:.OEK0/wM/e]4;XL ,BvڢZГtg$\{o'.;݆m2AyaZ*5k$|ώɨfO,f!+UJ)z\QνcovrGXiNoj8hAқwBJ5C3mh{M tP[o>ܲ!,dnS, ~a2y7! <}}ym 9㦙nGMeIp87|#h4,vT6xlUm1Ťv]BG-v/Mx} %^΋r"-@)Qxiy[ [6I-r+=Wy \`cڤmjw88qlu_qkެwOl>2xyŊ67dCD~GXvmr 2\9A;dJh|g8Z%OO?tܨw=` 2ʎ%sΜ9v"&FY4w&24KDp֋B-TJ>sY hY [imf\1?ڔ%mk*ܸnl\B2R2-@m6>3^#c U>MSXKpw784оKInFR=3w}[j(Æ k[-`L+ N`gݠ/." h^E[c' u`Zf\R&qm4X8;P5d 6H ٠ɣ<<% he˖%W\q f@(8,H@.}j:Xreo|H3&~Cɀ6ju0M( 8J]@KQ6&Bp 9Me$#eCrcJ#$vN  M4F `bΙ4 Y'l7Ȑo3O^wu ؘuC70pBi)F-8xj}$Zh`K/E}Fhex iiַgaڏ ht6WuPV4>C=4>]ӫ5Țbw \ZI p1;&V'C~{'6~xІ;w\c RTL|-ɸ hTҥKf֜8y^q͕myOz.GFK_ac;DX5Rm㚀 LAά@\enNCIs(V@C hYz{l! 7/{@+)psʆhxs)C5(o ؚVR5܌pC4Z}Kp39+І.0=+І.}nVup]@{545Z}\IW^y-T";O` h.!)ݤyۀhC5ܙ3s֙ 6[xXL Un^&ZI1q 7/ІhҔ擯| 1WF  py]uU駟^shqInI02i; 8B˥c^~La C Z _}ե| 7XqB2ea I7L p[nT/첄: &qi.'je)ɂ1j~d@Fb%d/˦Ɵ @z~m,e 7˷>-BGwp|H /z m6-BGw<3,tc|H;#t Cp:>׾MIr-t pm7<@m棏>:hZI=!fZ%^VS Emː!CB&V.!- 5ؘI?Ahfܡllw:JT&sw>;n.CVC /vi 3EQpC|{2iOXLY鳵;B3h{ %|M7ufZI-a'YgDM}PEбBJܮp;n^ .o~PE$oM3 AEi߇*L7|"ҁ/ʔ h_Jg7(fxڎC2iVe.v4SlY۬PZv*8ԝM}'4;HM,y"O wx@Ra}ި<']wx>Ȩ$?qBMh__uSr] f_e>S@N0Tz&| qƕNMLٳ}XFte󴍝e"fTlˎm`2gRv.(cVغ]3^lI$Z5[lIuS}i`룙1hf[nN \j`kɵVu ѵ959~_h GnN(H.NZGj>zB3V`K]K;[hj`]O:͔Smm: |ۤ Wwkkk`k*<X %cQWt`dbA=0KD-ꢛ"ͤ"VgfcmQF8#~lYFPOQfmmJFP@&zsπ3#PgTY7#8'tӌ *͝vrj^7ΌZPf-s8s1#<-4qvZӆu>`A|qkvN8E=Jiymô ^zKxUw= z$4!+j$poBqq9/9}]5kVM?OZ֪^CWzϟ_)o(GnV+liC ;=cn)RI=EM2nFPO⫯)S*e&o^,:AL:2+wqk^ ۆ6&SU4?U4PY=iҤq曕ߕz!6۬&QNOLSu̫^w}w²;}ީt-Y͋/ƙow6*8~Ь1}Pj^0rUguV`|hӟ4a!ByJeajgU̓J,80Q f긫,*Z<{[hZAA3- \0I]h˕,l~m9&r 2y5:&bѤ;6QK"_{:t=Wp4#8Ql89U;,4dm˷UF>ՍVQ#$P[d흓JwJO1 Z՜ASeg*t!=," yW?BQ?޶D9&m|x)Fwu ȑ#+Bꦅ< 3fƔ%)P{Ffr|22ґZM@83^>1_f~)&nR:^|WUQ5L[vsQuA;ߪPV}tLcCh4mMg-kr~G-,Y.,256{oFS.׻hyd :cCU90̓a'K"kO}oyRlphal J& XP>bGe\J7E}Z4Әn KcB{. fRm@&\ʫ.'Eә:Njg:?IM[߸ܰ(BIW:䷗_~9yx-*c+lJuA}nH̤;Q:OgG/S?4~Ot;!v]HD)"4^:#!U(f,ٯ~8\g\ #6YXhQ*`Ɩ( Geß +isw}ӢӲr/cM7(E]dBf̘Lu)o-}Mݜ5ks; e-N)cČvL 90 Զ8պ$& Ȃ!:SOm"YwP]4Q)t.of6AP8z@In$םT:6T#>TuGl ݤ:0cI7֡Qu[ J C~vCe;])1&@BTۂb \2[e `J%u1C+1Pi6͍˚Nft[b-ˑk}IU3͑݋QWZu Zi>}zeߗ/_^m 42jB_XxqGB jI"!‚#"bо81>ⶫ껬1dM')rO4^p"^Uj҆Gؕ)j]l*ÖYN'J4bksL!iŞđNdJ]nY .tMZ}Unj΁ގ k<"'䡫6/2/0>2JJg#d+Lřh_v zY987lUzk޼y]\DF貁Ƨf;wu)s z} [hyNj-TS:h<5 ť㛋`D~lm -$ðSED; P,@iFp>,xi&!? 0-<14G5k,?lԝ\LxU>`j2Dg)b+]d`K bI/||~> SQӫԡhe9S֨rXVj_lF oj,tu,[5sjJhr#@C4w 3O)}-ժJWvݑZA/Hz7c"OLuN.:vrGtNؔ>df'Sj 8\q?F'd;7 -* Զ˶sgpw~5''T-Zno۽md蕬K/lp MـzĪT]Tϖc6j&֪ l,~S[)R˘b˫Ў Y.B`NڳBe#J V 7 Zo@Z ([Z%]Q=vZ]e'Dh}bRR^=)j;мBH \&mw4t*>녙d*-gaE;<  8H`*xЈ+:(h"t/3G8t/:M6VPye^` 0."&0T(eHilx}[w$|ߘ@XyxEii̧0;@t\kÔs ]l.髦DYGĽK9/ߺDX̼]DQ~ -%lJ߹Iǥ`tH&1 4`a-hi `az|'.( `K1[E*e(vl^' a[qW-/m7o\QNDqV~K!*q=kwuU{l'^ M20K.)%,-Nt<<2]trt M20//z(م0,l]A{l7VdQ ";  Ljm6=ua׎ci I t' vlkjde @@3] `$Ru,GWn䚋8t;2ȝqGfnZPIENDB`fritzing-app-0.9.2b/help/images/schematic1.png000066400000000000000000001231761250202676700212430ustar00rootroot00000000000000PNG  IHDR=*sRGBgAMA a pHYsodIDATx^ ՙݎYF3:lot=qØddeq\AP1" (j[A{}_#DcL&?篧O~~yo\]]]us~s*||{o>m1ͽwS7sVQqofwvu?=':bDk-_=,סm}|l16.GٷNܐ[- ۟8M_ 5m:n۶udz<&ɱHnwت[FMWx\;10b݂+9np]t;se)gqv?>\wIN8,wg'ϤuO| =cp7;oI?\D 1@ t3*s/)݌YSf\&rpT7Ntvl&9pZ|k-F۫ßñ;X1@ Yt;KISwG7%=Fm&41@ 1@ =g)&č{T 1c{7z]֭-믿Kkk֬qyի]V{\U{W]Vo~jVriW^qYmʕȶb 7X[Cf׵zxK˗; h\[^.yf_;2QY)4ugu{ꩧܕW^f͚wy.ْ?ٳg-|| /p@3g ܹsyE]6|'M-7[ɿmM{)GK s=7ng}v|̤͜93ngqFGv駻iӦO:5nvZܦLN=Ԇv)O>9n'Ov?OI'To?݉'&MN8q;cu&N9z;݄ (nGu;#vGm;,nzh9䐸7.nt;v<pq~Po￿m̘1n6j(l ۾m}q{w6rHFᚵÇN7~d?ddN0&n~[QZ,1$|| ?nSXXc C^{sO{wn~ܾ 添mf 77ҤI_MV'.<>@הӮK͞K;\x><ʉSsxdi;cmG"c4NJ böpB_ZK.el4{]ɿncqr¿R.-_>B"sN]-RI|j/גgCNmd^Yl/"alh{춗P%˝o w2fCg3Yi>މϗ$eXxy_oRX'& Ƌ!'ڴs<˅;+p0d{Aeu[[su<C.r3>kC|g})^'3^E wZfۗ$e[ھ#>VBKJ¬wXRf,~'KB O+5Ifś zҔd}K'Onba"/R#&ǣܦv} 9C{d$<y^4+6| \ZZ2f/+[%y1qr\K/%8OFZ00&{QW$?믿i\nF+M+ܖp;[g '/<䋂|q/uLdE}p|K?-ķ݂]ˢvVE️wqdVEE`tMo[nI[xq9%Koz+ے8> p%<P yu("۾l$,It'KF›1_f}YIR0YGv3jX&ʴ)O]K֌L{aֽ{xV01hv"'_؊HD˗&Z2R"e>R!e4}>԰2y`FAyL7 % ^a e;ki)^};V";^gHKJfF-e?"F(i6Rd<9rI%KDוwdo˲,kSgr.q$_$>d߅H|3R"g)H0J#m6`*ݰJoQ%c[V%͂i펲aY_6oْq#ȭYr)eO[>uw]]enwrŝw;sv#7ܼ~4I$˲VR+WOkwu_w!}kmiϧo3 OlZ켗iNY|)=ydxcqOrwr$V#4$9ZI2CJ?9`aӆ[,@''1m4ԳN5M~{d%/*R!"R=-r`ZY.H> o x!0uEoAX^cJFuXQms8Z`ʏO:9S/O|]HaWwwu7Ans_)V\ԞGm[yTƱP4ITDnݩ_J%hϋE8л~>-g=]?chva ݽ7pv2]z܂vɒk;t;䢁_ btSȬU7̼N%"%faA?ڷx s'\T!3lW-7͐8߳ߴb6ZI(TrXg k)sSOuΛаLѹ w' w?>׆$u V՟ GLK' ('jL4(3`:)5[q^Ѳ21OJr8"N8RLQpZ>3+_7uhqFة.s;f]ze_75Os_#<}ufţH؈edx99GmF8x1x_'ݑgU=e#Yq'- B-M,{L"2Ҕv}~Fi# M/:ih4붯lqd0O^/h;,C;Jن= rӤyQVA)7 9M-%d7"j/1M+x{'SYN`*|3y?7ܜ.kkpqodzn3ngFK4pwIMJe~Kn.w{DRseg7wUKV Εk9JKRs$_yeq}y ^}rԏ3EǸ3jg㇉8ϭjf 9Lh;7s_0Qy-c{Ϟ趓fE:m,EO;=h/:ާ?Zun2mQdsZN_j_pxV"xXcxkGE;jz(cQsqnN-IAIUX/ G 5>e$OFېo 5Ld#d^^ۖ9mF(<-3Z6mƑG)g_vgn0n卿H.;t;cq?zQwSkCqX2JE]ٍ.Ϥm,6LrM]߿뮑:tUfT{MgF(W߿̛b?W[d{ a $7HLJ.KOJ>ltULt\R@1FTop\Lny/Nޱ[8w0z`h@/g߿v!Z7SǾ7"%"igQHW:GͨI 7::ҹQwMB|v"e/.wәU ҎD~IUkv>3ΠΈ$KRQNUo~]e5QB|y\gKmTe0vv|ɜ,/f;0z@wnbػ0|C,D *Xp◣}ߝ7 $T8ˤ4UyvEUw|$Ց Te>DlaM g @W9zOg}Z6dzHu677O]9˸cۣݬxV>ªwbp_ꦈHFBَGˉ^z,7Az)>0c.RI`VJ_|\bHᗅhϸZs&Ύgkڱ*R53ߙ kf6,t"mf$H/m .:AwQxA&^䥴Hg R!:Z=O9u&A?†Evnu:'XrpV4FL/RQGƘ `k8Kƹ.5QNs5\@/̲Hr-ӽLv=%Q]*rQE:]Ew4\g/yuiӷPǺٱ4x5qj7 . &pĵ)]W&Vјq{+RBVtQn6L^U/b-Z@qD`8on;w\:)ǵk6}N0=|,ص77ʍUy ΁6fSĸ!WcAeqÛ./Nez+Sofs993V{FQn2 7%"95D~Xty_Og笟Hȳ8,ېaM2wFmi%m G;3%w^yf;ULHG[l*ጁ|e77i>Msc%Mt6>w_q+ &l;ajsrR<\#E;zv^\{m5́8Źgj#uXb)I:{ q.8w[xoug8.V WA0.9.UM :+Os_2Χ^ UwظTPu@._rR\4(3nflcq80w\ 5ie,#hi5nkk}sUA-thɉaRK6bɰ_@jqCDb`'e\ZRRjv^P_X]}^u ҔZ.XD_b/5{m aԗ]4-8I7&Gr DծT}FG 2QQinnTr2Q/;;[@Y q\gyQ,HF!} lYẂiO{8o}Vhg^֐q`}? Y&xg7^/CCU3ξ!.ըK7ՆGHt/7RPoqȊept }raru賢lr/ YF 9Wi#<)qE(IiOn{?Nf<}[.psf5ލ>w}ϻQl~|Q GqGֈ2rMq lu8[/UvXM@ß^EF[MnWe6Ţ&տR^nHQ/"̨ z9j8ls)#oÂt[ȳC͝uvWKG 1??_$hđ$7Q:luD_8{l4[_E꾇썿FJw~`e#ę(^K<Q:]Xߜ5])dY9,Sry.O&ȷ+ϒqʳ^Y*ee܊/i#!Gn;8wtlw_wGƾ{(˼ODpSmKYO- a' f\>;," AyDCmqt¯6V?K`q,ܜڔɩǓc4Woꬁ́ɉN8W)%aCHi,ۍ!f"3`yy'9ILg<~EOMδӭ +m@a뙧 _燰k=JZNahsgC*.9J8NF;JVF'dg)"΍H5Jdc][3Y碬׭<F٨Rcw-޷wg[7;}o=17ܞ;nqFK.raђuK6#lL,5Ϸ wsDYΝN.ddhvQN-}5wPcg0v(~&@?srj^\Ƌd9.^)Sc'Ll6ҙ\/\SmMٓyI$G-wt׉iufM-[M-24̆)j\wLum$hYSng]eF^{%,CI$꾶3%5ܭl͂.9agwFGg!3̍] o }q\#GwEYq˳d$3mL""^E63iyyOqRL"WSѸIM:' ' If qKƸ~,0Y$9"{IXϴ,f(8M2,Lٳg?y=5fe_bd k;vHw;6u=2]' &܄?XI^Y/#',/&l~ғpc9&]x@?I8ݶ$lV-HQ6t"CU&~*ِ͂Vy^J68u[Bѭ+Y,Cws|qQwwrXpB/"]"b"ga=p&;/iz]?˴e}V6RVngukޭ6Hr>[XFS%3I)bPx&d4KJ̪:묨I|5|=|}y#˝qH'340iӦ^o~dKp2fwmJլ~$,|pX, 3,q(Œ=`9rlD1q+B#QD 492&BN;͵jwIhZ5{O9'OHR&Y"Lܩ&ݳfOXccBbEb')gi_Zlllll[RF@^ 8nܸhαNn Ym:+U<ئ3%CEJ6ELݭ,r;S~ys`ZMdM~󵎒u^CYLc7M* jx[xW~uYP7ivs\8p(iuaiDZYDXAx2,/3z5bfDD^B9JP$LfMKI&p .d$^kEJl4)A&N &N6힑0~R{CWl/)>_Klll0e^ejmf_,W_a洌!#m ҍNgea n'g"Es/;W$"7x#B6i>)'D"4lNy>2IN| s*/l s2CQ(>l4ŏ6<]YΝ"么vX.k׮MVeLfX'o5gPuSYQnF חnnKnf7 /57T", Yd %`LAIP CI e젃eBOkkD>Zެe>3n/a1j֬Mu䩥.sVxK|H$:ũυ_d[(K\첏/aLs(sdCn`9ds ,SW5q(eYE"'lsڍbɛBiL L{l' O oonk&apapRܬtX~RӲHr(">{%ًa/I1 cYݑgp;2m]4lswŨ9!>^'(8>/fےg,w;X8eY bb U$^WkݮwFRXfH*}ydgyvD >#&#<#Yq{ί-;כ{_NYmNWgc|역mϤhjܾ8~fMy7 yӝm Y$~7!'X&#1@ 1cgZt -T%;[=^[0mu# 3ZnNn[nɉFc2;{mCs6v^ER78MuKϛ3'܆3bl_%|wNu[cѕi1g2z6܏zLyv߄b ڍѣd P[{׺]_$ Bdfȫ3>#k&! mh]ޟ-ُ#gGsGF]#?vlnGcUa^bh헿#nDz}{k^ kF^qmMޓ8x<s9bh~?ǣ~d`#b ~+o7<"j\.|>:鱌f}n _ϮWjFu{mc|%7yV_Z=|䘂=N*Joj4,^IoXM,}`I 1@ t'*o8u6Iw' O,s/,ڌy]>ǫ8*Gw6nk/d{jkON+rY4phq6mGñOp6z/E҆_l?}π1@ 1PV T:̛b ܈h%. b b`@3L8`@ 1p#. b b`@O8ڟ @Uq>>₸ b J T&OUh0 b b1PI33οYgG1@ 1@ PʤY5ęb b 'Tp%wsg@c01@ 1нpԉi_>Š8F 1@ t'*9.wƙigOYj?`n\ gbwc Ssu?g$ߴ 8B0bK`q.Uw/Hdž^ TFھ8tls{1%2V/o߶ sW8xf\wq5ތĹ_gĹ"3tA ⌐p\8.!*;R@9nq/Ӟ]RXr\I`qpi ۈ|@'c2&Yf9m-YNovݶ۞wzgJUjmsq79|ꉸjGIm6(YѯN\?⌈tRDX75bA(Y5mNu'7˷ZWl;=*'kד}щ7wK3ئ)jW8 1^=#1jb2)[okb;Ɲa96 ೯g>N72\qlym3b3Ćm%^;#'LPJ???GNsls{/{yͯSOns<֥Hu&zj9c5wCuK^vWsv |r&M JDjDU˸jOWvZ=r6ѶvWĤĽ/a(&}EvƝHmد>_yޓg<U-?d5"|lq,5eiҲ_yjF6erׅU˸lnTO)jXWlX&e+׶C_tF]A߈W//m2Ly8+m5%שVo~ܴ߷ޜltDzE| 8eÆsM69'9 nri^o3>$qHl_|^}O[r1yM+H> SH)'KmP a2Ix/,&8Iʵ~(> }I&Q46׷?~VWpaƬ~ܴ'&=8'%֭,=MmsbZ$䌣D?rT>ӄY7.J|C %990-ŭXyŏ,/2ЕH@'ˆZoS?=Yce r8jFIFĹe\!>f¸ EiXJR>쳓ۑq7fd?Tlゑ/_#m}SF.s5휳ZM$۰bڹ0g3 "n@GgCin6s@_~m٤H'een~)Wܤe߲fO{YߏfۂJEPz6)lx=mp\f}Gm2j qMx\d8N\*?;-ډ߆~բֶ]>G~0m~ưr9mW|kq{.ˊVl"еqFH!$|q6b us@_z8?U/w#>?rO꫾?^>^]|G4?^^oKVxM%QaZbX."K%hر DnLnq8Np7?8G76eRrmow1/NqU܌o&_D?YWz[Yşs+繦~ 3٦M-ۓ?OvZ an@eg9ԛ?^xy[z۪n,/ou[7ly*E^[w&눷vDϧ?m>վ'^Ӊ2e;&ZƕgvKOتq8q  >3ZĽ/B1|^8Mg~z4[9߷:aiz?u5WM}g[7gTq;5kVǶq$ͼ8aQ?F)O̺qQ3b/R?Og`8yaq%qy݈zbƶ![1ЍhpT y6s@z)Zs{q^Vmq.퟿gBgg!RŹ(|IZs{q%q3΃ mF g6.jl#E ke*Ӳ s/TRzy[ mWdqFD:)"L1K}g׳yYWǡd^,~ f1@ @11P92G s: @pA2p8:/o{믿1=Zx )=g#<^|E) 7´׃뮻hO=-8D8x^/嶗f50m@&@ 56~8uqCmg=?y 5diBmlg?YqֳCmlc8!9ُAYhq1MI_Ze֗:⬏?YqCg=C98Kq\<;aj$}Eq8!6vg8g_qg;n[ܐqDmg=?YqCg=C9CeAYls8y"zlc8!zs83>ZNƕ8!6vg8PO~8 q ;2v!g8!v~!S9Pdsg!v!g8!v~!Q̨@cT!v!g8!v~!S)ΰC\g=CYqCg=C9C}3 C;qsE g=;qC ̨k%j28!6vg8g8`cbّqD g=;qC g&@αClg=CYqCg=C9CCifm}1Fg;SYqֳCmg;?YqN P9Pdv+g8!6vg8g3g}peips-7"z~lc8!zsFSn q,;2v!g8!v~!!ξD PAFFg!v!g8!v~!Fƙ́ųCLg=CYqCg=C9GY"͈>!v!g8!v~!#4D}QϜtUV9eF(C g=;qC g}q.lg8"zvl8"9J5$L>ȸ93g;WYqֳCmg;?YqNp8Δj-M)հdg?YqֳCmg;?Yq!>|YgQՅY8x"6~g8!v~!F4jgG)g8!6vg8gsXߌ8 q.lg8"zvl8"9ęR }euPacK8!6vg8g?ƙgI35΅xg}zq֟q~֬YS瓬M/֭]~k2￈sgg)ӠTChjώR ;S2zg;2v~!S<3>Xv'g8!6vg8gj56j!z~lc8!zs8''@5ΔjRّq3E g=;qC LY`d;qE g=;qC 6J5UChdg8ۙ"zlc8!zsL>!v!g8!v~!8:&7;/lc86~818#ΈrnΨlc8!6~8gFXb!v!g8!v~!!\pA]Ex F`T)YcT ;ƏQ5lUqCsg<#`#\,;2vq&Op'l?qCq\,;γyvrJ%nJldl8!|:i"Ҟ|IJ5(TCR|ЭsNeh]?l뻈8g9s4/Ј>8ˎgg>srmY]8ۏUj~vg?YqNg?ΝgYlsg;ϲyذa~w,2 ~\!@mqC,q\,;γ,qԧ>TgqJm7ޏ8ێ3l8!-J56o޼zy~ꩧq.)q+yn̙6~xJ5 ظ9Xv^YgĹS\/5ζ8!6~B%ze54sgv򏌳>go=泥s竌84+k!<0Ng[Emg?Yq/qfTlNPqwt_U.y9 /&s~Vi}qCmg=?9C 6I>26rsCj/:y$g2|ͳ,l;!6~Bn+g?7Yl88[mU,8wFg9 l;"6~!W]u IYpdcvZwgӧ9slo򗿜Fv8ϲ\8!z~s8_}.l>8.mm<{sf?ƃ/KYe3\tAmCqCSO"k,mdGƹ8vi\}]_⬏GnԳ~8!6~Bu]Wo?)>g}!űC,Yfɓ'رc'Nlx]ڗl8!-J5__o"ш>((lY8dFB  ζ8!z~s8p .l2g}q.lg8qֳTN!6!7x#L8;/lc'g'VXAƹ22dmqCon)n"FYpdc8Y%eZџIl8!|7!`ƹXv'g8QacGg8gŋ]V\IƹL)w^ƮReqg?26~!K,qzW^A瞩7}72i]L2gGƎg8E. v[CCFF8y"zlc8!zs8/]ԅmժUd8LGlG6~ܢTC. ~{CCFƹXvd<8"zvdm8!zs qyw۲e˜c8Y"zlc8!zs8y.l*L@7"g8!v~!!wu 6J5eGq3Dg;q3D3va -T8v%g8!6vg8tsOCCFƹXv'g8!6vg8gkq.qc8:?ƏlqCSO"!`#\,;Γ!gGƎg8g<¶zj2dU`T Lvq#l8!-J5?__!`#\,;2vd g=;26vdg=C9CEöf2fqw^Ǝg?Əg?Yq|Ѕ qb!vd g=;26vdg=C9C~a68c!v!g8!v~!B?_ _G)cgqֳCmg;?YqFK@j56~56~8!z~s8?#.ldFsg;O2zg;2v~!"~)xG6ĹXv'g8!6vg8gc=oP\`}+΋8Qa8QaG8gj<.l>8q$g8ّq#l8"-/{'ڵk8q. |VgqֳCmg;?Yq'|҅ qbّqD g=;qC SO9ߤ. P(űC,g=CYqCg=C9CCiLj>8qD g=;qC O;g}!ŲC<g=CYqCg=C9CEyzC8qD g=;qC qȨ4?7ߤƙQ5zf FПqcg?qC__Nd3fC1)lGYqֳ#lcGq3D[jxqa>((v!g8!v~!!= 6ĹXv'g8!6vg8g?&8q.lg8"zvl8"dKэg}Em9q@?nC,j0>>8rsg=?Yώg;?Yqn!ӟC=To>[f  GWj>8O~dmg?26~dmg=?Ĺ8uY CgĹD!㬿x zvdm8!zs8 PVZox[l\4Q8ؑqCm8qC+1c4K"Έ3cS<%㬿x zvdm8!zsR YXyE!lcL8!6vg8#ΥfOg}TƎR ?ƏR ?J5lg=?qFqgqCmg?qCgq.5tb9J5YώR ;J5g=Cq.U(w^J5l8!6~dm8!z~38q.5:IλN2gGƎg8#ΥJg}%lcGq#lGqCSOptʛCm9ƏgGƎg8#d)(5~r8!6vg8SQ4qw^J5l(հCm(հTqCgęs1ЉLruqO<,Yn&w=իW8/dm8!z3\Eq++K/3f}kn 7tJznvp_~9%!ζ#lGqCR/̈"6veŋ?@s=ݛoYjm&䈳-g?qCR/ʈ"6veW\1@7|s뮻]v}XjEqqqEmg=?q.8;/lcW8?2e{dq/2AxRiql8!z~3\qw^Ʈ q 'DZ$_s5 |ᇗOg{%"68s8ѣ1cmҥM9?9ZoMC|(]✷oH6;"΃xJ5}5q1Eq[qd@k%wO~qF{.~r܇8!^g}:i"6`}s='M8bR ?qCR/ȈRac˥mgSjFs gOYqFK #΋88$)2/"XCe8x"z~3\qw^ƮkU,"XCe8x"z~QW^qov<=2+ԙ­=n믿_~e3g_|W|yk6s^2݊g}ֽ=oLҭns'vò|ڵnWf'xSk&[Nxtڴfu|ceܸqnM6/ Y7J=~ny48m47c 7o޼x&:Z6~}Y_+1b 7lذt˖-g{s}Wϑ//IhyA~:~O<[r%^9O?gdɒצ߆-qfgŽR ?ɸo;؄ ̙33E0KyPtbH:'Ne Fհ]FհTƏR =?J5RJ5&@a8:}1]ggċ.(E}8/\AkX qkqCgĹԌg}qfmL!͋b݌C38vm~w]/;dwg?qC7R>J5l섟d/~s<_á qկ~Տ?n sg[Emg?YqFK@qw^_[Re*H[O2r" 7heCm}qCmg=?q."8;?A(rW?'>tS~-8.l8!z~3\qw^/2ɓ ]́<-=Ї>TO}Snv%q]qCgĹԋ5əe/]ven֬Y ds=7̣Hq~衇38ײGm}qCmg=?q.8;/Snؕ1}o.;c<{\|l8!ΈsmYyg2ӟt]/8QCndMv=-g?qCSę PEq˝eطzk3? 2F/7wg?qCR/ƈqCmg?qCgJ5(Kvu;nZվT"ζCmg?YqFKqw^26vedR"ζCmg?YqFg2Υ@sZg#  qCgĹTi"dm8!6~l8!Έ3Lƹ(:8/g;8"z~3\4qw^26vdmg?26~8#Έ3Rc q˒q_<g=;26vdg=C9E PFF]oK.u}}}nNI^jH>2KƎlGƏ8#Υ ?(l8!6~8gjH9:q[Zqd?J5g=;J5l(հC q\,;2v!g8!v~!8Ś@8!6vg8!Βu&62Ų#l8"zvl8"ΈsFjq@?Əm9qCgęRRcR Lv!6~8#ΥJg}%lcGqCmg?YqN(~H:j,38ۘ25z~56v8!z3LƙRRcrY@g;q3D)(U8;/6vj!6~jQa8!Έ3Lƹ ?q7qCgĹTi"dm8!6~l8!Έ3Lƹ(3kJ8QlcGg8#ΥJg}%lcGq#lGqCgęs1@Y/l;nl8!ΈsDYy8ؑqCmg?qCS9esLlc(6~8!zv8Ql8"Έ3gJ5J/W|q_<g=;qC R 2#Ҥ'lGgGv~!"~qg}8냌ΰTq3Dg;q3D3y3g}q.l8"zvl8">RaK8!6vg8gȑ#g) 62Ų#l8"zvl8"936ĹXv'g8!6vg8+V#F08 q.l8"zvl8"9({L"6vl818!z~s8>!8냍sg;O2zg;2v~!!{ q\,;q3Dg;q3DSO"5{ yɒ%jPQ4ӟ(հCm(հTqC3y=˳(8냍s8yq3D8ؑqC RP%8 q.l8"zvl8"Pg}!ŲC<g=CYqCg=CĹ8/_܅,΋/ƙgj /Tzq_<g=;qC  qmqbّqD g=;qC 3ψ>b!v!g8!v~!Cì36ĹXv'g8!6vg8g}'-BsL(8!6~l86~"~9qWg_&@#8ّq#l8"md8냍RbّqD g=;qC R}{dofJ5(`8c /ZLq^bݤI܁F: wi;ӽ=gigqCg=Cq.Lq+Y2g̘j+WTZ}ck)‚8g?jmg=?98Yg2`TXvg3 .PKSwzg[!6~8g/ψ>b!vez &N.7gΜlK_ v⽈-g?qCggYlsg;2x7n{ReXSOmg1kY'l?qCgĹ 25΋8ؕQ|}_W}Ntm>X$X^l8!ΈsdYyg2ĹA=#OUkI)l8!)N"aTCljqvF;|#⼎ cq_qCR/dqsx܎twcYJ5l8!6~LFdYyg^sֳR)XTX'8#Υ^g}EmzQxxyw-*6^qg?qCR/ʈ"6v"wܧ?i馛6 A'vmV%-g?qC,'^zɭ]cZ{ ֬YV\ 7emVrjܖ-[nOg}s__j.6~jQGTqCm䧶Prj6IqNWD~?o"Όs1Ug۵qCSę P q)O~y|K3't[o2E,hΜ9 SO8q]26~8#Υ^g}S̺d(E('[7,9odyoϰ,GRa8!z~s,2Yls|Y"@C2v[oq oNdV?mmz#ζ8!6~8zA&(8 FmƎ뮿z'l9,^/v#Glfܦ׆v-g?qCgyMJX8gw+>,38N"6~8s8gR }QQ,;2vgueo#GݭړL{!l8!ΈsfJ5qv(%-r?ݶn> 6ɐowΝg${-g?qC)(8;/lcW8 m-g?qCgęRcY+znjeq_xq~!8#ΥJg}%lcGq#l8!z~38q.5̜q_<g=;26vdg=Cq.U8;/g;26~g?26~8#dK2xgqCmg?YqFK&2KƎl8!6~"Lv3`53Q8QlcGg8gń,e@g?Əg?Yq(@'8q#8ّq#l8"99o3g;'xժUN."yDe#KƎlGƏ8g/ψ>Ҿ4 6dm8!zvdm8!z3\jqw^26vdmg?26~dmg=?Ĺ q3g}q.lIYqֳ#lcGq3Dg255jO~dmg?26~dmg=?9EǏ6d|r'Y民qbّq$g8ّq#l8"Έ3g2Υ@֏8/lc8!z3\4qsqTqTƏR ?YqN;R.eag}Emg?qCmg=?ę3.}IDI7O~l8!6~8#Έs1Љ/yI8QlcGg8+VwߝQ5:(j;/6vdmg?26~dmg=?q.5ۈ8;/lc8!6~l8!Έ3zޒr8O~l8!6~C\×l0>ؘXvd Pv'lo8ie `lJ58QacGg8#ΥJ4jQa8q#l8!99:qb!vd g=;26vdg=C9E~{&+V8fߤ\q\,;q3Dg;q3Dsf<#`Ce8y"zlc8!zs8xggYlsg;OYqֳCmg;?Yq&́ GWj 9*⬿x zvl8"ΈsĨKƎQ5lg?FհcT ?YqFg2Υg Lv!6~8#ΥJg}%lcGqCmg?YqFg2Υ@YSjYώg;jg=Cq.U8;/g;26~g?26~8#dK2xgqCmg?YqFK&2KƎl8!6~"We=lv P(ŲCCRkTqŲC<{TgumY]Qgg[Emg=?9EĹK-2΋8JY}-ɓݎ;8wTV6q_qCSyCtBqq~7N;TQFe_ؖ%y?qcqCS#@AQo8iy/,,A{Ҽ.8")q_K#ζc8!z~s8s1uqk6F>بq.g;2NKjk/@@#ζc8!z~s8y䑈3A%?Y1wܺ4Mrs`(z4!ζc8!z~s83J9:qbّq,#,(Y|ICǶqcqCsgYlsg;n?Ps2O_6gEm"z~QϬk֬qW_}սpSʕ+4G}]tEnѢEn d跩St$Z?u|#ivbذaƍgN'N{(S&z<-_ܽ+S{ի'<gww6m߆J8/'3k׮OjM1=r]bܔ#_<$s0qD &3gf`R Ғ3lzq6Wo0lk/n|_zq6KNKa[{mE&KoE8wzN%LC1g]\sk~Az~6h#7mڴ N[ԗqrK,1meD^\PZ5ζs6~jQRN8+Eqq'>8GZ)"95[fر=#"6~8s8 .ĹҥK㟌|>'y(C3aE2l߈l8!)✜%gFjNx 2[o>7/~orˡSo+"wԧ>U?ַ{8wi<_- ζ!l8!)✜qXօR [)8(R~|l]e,8ێ1l8!)6JQ59P|hcqhqs`gjl2#6~8/g} '@Qd3<3h9|pR uLsb8}8#Έ R i.'Cn#gE-/㲗CmqCqngJ5G]q.[#dT =;/l8!)(jW(հNf?ԗG8!6vq1Dq'@>|cT }elc8!z~lc8!zs8 ʒfJ5lgCYqֳCmg;?YqNpY\sgQl۫,5?ի{fO8Qa8!)N"월l0s>DR O26~*yt l=qCq'@AŽ8"6~gGv~!܆8DqbQa8"zvl8"Έsdq~!g8!v~!"(ag}5+@mL)հCg=;qC q'@I%K\__>sҁWZ"e#KƎĺ6~h8!)✜%gYl8q$g8ّq#l8")✜qXV-6~g8!v~!" Pg}!ΝcGq3Dg;q3DSĹ("Дj胍Rb!v!g8!v~!"&@AƨųCLg=CYqCg=Cq.u4jqcT ?ƏQ5lUqCg9R0W_@۱#8ّq#l8")jjFs8y"zlc8!zs83>RacMqCg;q3DSę P8wg;kYqֳCmg;?YqNg&@=v5g8!6vg8eʕnĈ P%ҔjRa8!zvl8")'@37ꃍeGq3Dg;q3DSOgYlsg;OYqֳCmg;?YqFKØR }Emqc?&@C6YdFƹXv'g=CYώg;?YqF83s`1ui'_GYqCg=Cq.U(w^26vj!6~jQa8!)cgęsb$㬿x zvdm8!zs8y䑈sq#l8q#l8!)<~xq&ܥțrdYώg;?YqFKD2KƎlGƏ8#Έ ά28!6~l8!)(jt26ֈz~6vj!zs83>Tq3Dg;q3DSę P8wlg8"zvl8")N2rH7bĈz[dsgvO:U\DڕFTCyg;jmg?jmqCq'@AlK_3g޺6wܞr8bqCmg=?9E PDCy&4Fm<g2rJ6ydy\^ Lƹb O9^!l;!z~3\ꉘR }Emʺ90,~K!l?J5lg?YqNpT>К]gSjm8#ζgߋ8ێ=l8!)N8+υ qEmg=?2zv8Ql8")((lY8Mw}K_r3fpB/Hr6 ζCmg?YqNf0>Uxviϻ'|ge$9-==y<g[Fmg?Yq#F9PO~b]jU+=˗/w< ܔ/:N:$7uTw:挖`뭷vm]׏sWz^z%sOy$Z`yWৈ?8⩧8[oǷ!oUŒs8 Dc YW_}nؑ\<>l„ n̙"V"s܄qQ}r?cwtxms_Qj2^{ ~sի믿?%?z ~ ~rAYw_kfmmȻp,qlk?CaT ETw.ĹZM{O/կ64{dR [ߥTƏR ?J5(H)'@qg}Q\<;a*?`dҼ8^y*84n{キAMUy84l8!z~s8~ PBqnj6F(۝/|N|Q^gm>蠃(泄~8ێ%l8!)N8+R _g?KMsEbd~g}zJ8.l8!z~s8 B;8_tE8,wM{;v,Lƹb 9S ζ 8s8 <'L26~mIc 6`T tg8̄PyT!ldmg?YqNpt[f' l?qCgquTH!J8K>)7}t'EF.]>7dRiZL Dmg?YqN(j,K8"6~esX[w.#Ȁ&:l=qCqn6 8مq1Em-rDw~tb-g?qCSę PuM8X#6~~]NK9Metv}=)̾#ζCmg?YqNg?ʊ+mr Fjˎ<->kx-^8n={7{Zg{Qlg8"z~s8 Pg}`8qD g=;qC gĹqw^N!zlc8!z38Gućc8!zvl8")|qnM6q2^{A>ZI'gWqCg;q3DSy ,g}Q\,;J5<g=CYqCg=C9E=PĹK dqq~֬Y3h._cm[!z~s8)Tc=dAFFg!vd g=;26vdg=CĹ qy^xsgvO:U\D>?"6vdmg?26~dmg=?q.Ug}Emg?qCmg=?9YJ5|#fpƔQ5l(C(հTq3DSyAoc=(8;/g;26~g?26~Q8+O5lKƏgGƎg8P9Pl\,;2v!g8!v~!"mw\CgYlsg;OYqֳCmg;?Yq84# cΰC\g=CYqCg=CĹ qy[ǹqw^Ǝmg?n@?YqFǹ/yn,rnԟg;qCmg=?98K/ 6jeGΓR =CYώR ;J5g=CĹ qyF8qD g=;qC gęR J5J"KW]⬿x zvl8"-ynv4|#62Ų#l8"zvl8"ΈsFFw^Ǝmg?n@?YqFgJ5Jv+\8ّq#l8"9Y5|`TXvd<g=CYqCg=Cq.5H"6vj!6~jQa8!Έ3LF1PdE"㬿x zvdm8!zs q^bE\o) M2KƎlGƏ8#Υfg}Emg?qCmg=?qF ̠[*`]7pҬTC@(հTq3D3O|5(jˎ'g8!6vg8#Υf+)w^ƎR ?ƏR ?J5lg=?qF)(5,!㬿x zvdm8!zsNq%j胍RbّqD g=;qC q>&ld8:/̈>Ze)հq@?YqֳCmg;?YqNc߾83>8ˎ'g8!6vg8Y8 q.l8"zvl8"Έs7Q(j!6~aǨ6~"ƍTK#M ΋8!6~l8!z~s8p3\j&>m?!6vl8!z~3\ qw^26vl8!6~Lܥz,r;ˑq֟g;qCmg=?qFRc/ E/˨gǨ6va8"ΈsDRacGq#lGqCgęs1Ptq_<g=;26vdg=Cq.U8;/g;26~g?26~8#dKv2E/K˗ 'ߍ5vav"YEu}KƎg8#Υ^8;/g^8w}+WTR/\j?Mldm8!z~s83>b!6 GgWfvs[o iv=/ucyvLg?YqFKd!KƮ̌dk{a` {f̘,X.wGO|qnp;8ێ)l8!Δj 8F˖q2eJ40\28dK+z߭TCƎg;?YqFK qw^26veez)w.cǎI1kdm8!z~38q.5qK4/zkPG^26vdg=Cq.MYy8ؕq^j{;Y6_{?˗dm8!z~3\qw^Ʈ q={v]?89["ζCmg?YqFKp#΋8ؕ!rbNJ6_g#ζCmg?YqFKx#΋8ؕ![lE]eع7|3-?6l3| 6,A^(kl8!)(j78X3_7oQ ';4>яDv9sfO8bqCmg=?(pŊk:pkf'l2w-g}~+Of/co92߹6(u?E19ɹN -z?_{5'\zdxI\ -r?W^yޖ&2n8&w߽3g;ꫯ^?yLk0Ƀ[{&Lg(}-W a裏cnj}{+p/R}r>9__7,כ~&<"9%A>S^7)7C)vWO^F)b]Cm"O?tz-_; ym[, |8Wee,O"_tRw;`s1QĔ׋/n8 ^~-oҎzgJ5l}R ?J5l(TK#+_J]#w_fs=V2}&l뻈l8!ΈsbYyEfnw9縳>;n>S*q;2yYFIjg[~8"6~8z!FWe\qGK\r8Kt~_˒=\sM{Ydm}qCmg=?q.B8;/ַEFT!8( 6J69Kbx\uUZgQ#ζ8!6~!2W8FrT nCmUTx㍹9\8K?c]:L NPxwf(1Zl뻈l8!)N"4 1l'@y'wx9+>\8>uqg>9Ox,eիW#, #ζ8!z~s,8 q.]ڔۿ ݜ9Pꫯn_r}vک+g[Fmg?YqQfg}!ŲK^ gmo7[nd4fol("ζ8!6~8z1TCyg;mq~ ğg^/ېNUz:@l8!ΈseYyg2ًs=?x7l0}mNJ7lٲRf#ζCmg?YqFK8#΋88gi/8qCmg=?qFq.5ʔòj>q_xq~!8s PYh.dmL9qCg;q3DRRacGlGg?YqTqT(t@2gGƎg8dVʴGYIENDB`fritzing-app-0.9.2b/help/images/schematic2.png000066400000000000000000002276341250202676700212500ustar00rootroot00000000000000PNG  IHDR[sRGBgAMA a pHYsodIDATx^G6 393sf8$ܝ,\;!hp@͐g|ZzݽZVb=\W]]UOUhJ!qAԱjۥ?ԗZvEfmQQ6]EB[@7] !i4n\2sԱpc4444r:y$8pnJVŋӼyh֬Y4c >}:M:LB'OcHcǍRnR>RÖ@@ʩSh׮]|ryߟ?s1`````HRHٶm-XƏ/矧'O?ed*}wd[=zDn_MNÇdqzS.ݚ?~A%A#pB;v,7oD Ѥ%KHK. K˖-#9ڋ[h @JϗsҜ9shR43sL A6m\+ͤIȜސ&L`$;qɄ9Ui4fFiȑ21naÆСCe2d }dݻ7Ջz)S={ԭ[7v*S.]ds2uI_;wdj߾Lڵm۶#ڴiC*nݚԪU+2-[ZhAVy)5k֌RӦMSӰQ5@͍35]?~iV6N{i0`4iBzjܸ1!5jH 6$=5hЀT~}BW^X[.S:u(88># tspZ:q`ŊrJ)|nWu; )y)7cL04("aN T`T2 HX ;a @ B3Ё f` D&Ё:Ё*)a |D7|YވCJj\1j.|*0AuӍ U":Px7@+ 2Li>Ǒ|. (p` nABJ6(ƍa7dp^PV` `մfZv-[֯_ozڍ7(`8!ˡck>8z0 3B)d8q+9:7BDD( aFL H8:P p%Tҁ8K ŵP DO8ZxتW9Ssh5xhE?7XPGKqfJ4`A=Xq0ߑ@ApRrzIl",3 @o poذ6nH6miͲ}XK@aNxP)?'|::Q@B OV"3FVCuC +pPbE@8:wB9tPVb3PIyu Jb =I8o%fqzw_CDW5wjN]ǜEJ~ahXR)3HpW送A{f*V@n/9n nY`-@p&(.[8w۷o;vΝ;ݻ='sІSB_&ݜtP0$ D t.$8f.BY/C 3йaC(pca:BA G8~fdN.Fw]|w4Gyn\ZͳN:t~*AD VfP !Y#3̙nWp /WN3`itv:Pm[GkrԡUoԢoԤeoԠkкܵhHףjњR-h&@L:ػw/۷/}-|9BGcǎJ& h:Dz2( "t a:JbTcalXq/\ ;nE$шnV;#t6::W 芣A6";dc\͓>W,t:=D /`̲H 28uIbmVɂz 8[qjA{rT*Ҷ+,h i-EZf[ !Xx-Rj, Ǐ'N?H*!o Fd(P℘9f`E(N`B:2t ; 1VHJ$beF& FAJPH\&k5)n[+*7fќ+C p1"@'Aq,p[т,D+b,,D/}*ig5YѲюw;ҭ HH7D:GTRVZU 980MС 4L h2TN);iGoir޲4i{ ,3J鲔NlHei^>Zڅ~-1 Q ,̣?Kss4]3JcRJӰJBBu#쀃:lJ|>_EJ0ׂDN-?tL]93nf~:d4e{R}mf1hLS}w,Y2z5.}zqMaP ҿèQ>EXMz h$-8/L3y)ؓLϠ^S`4 ƶ)J5v2st9AkG,s=rPi_.D"Ћ9PXeL)a̦͠N  ϙp }]nO8fB8 fkNެ@k^-O_*C{jwտdIlY' +3uQie&l58O>MgΜ[m .nh'I`uXU]h̙й à*CSާ7 akGQ4rMHGbn1)iIA6!V)T|r978SZokMSz"Z3hX7IΕ&f3QTXl}fw5Oa,8!a>48ҕ6MG 1 CO{m5C38m74bF9Up_Ċ?>,jd l6t EEH[*+=-$+\|fg>@ͼ{6{UgiUܒ붼TabuP̪ywZ ;@Ej+MS˧˕}+b%uY93$8s4hS)wA R a((ф B΋C ǗN aҔCSX7ZpJu0Cx-Ysx-Mmi}}ozznT6'NhѢV4 > )?,Euv|*gaB/ڵ㩅bXPKqm7q\V pP0TU5V曣1kl ;Tfq.fzU dE&P^&[{B74p7Ѧ6BtH̢ D6QkCcL޳d7TFօc:օ)RAM~ur y\|l9/ɩaJk!.ч"h^3 X~BƷ| rQoؚI= D}J Z#D J9Qt/ h$ B8 *4qVfd)E ^H76)ێ P6uy-TPuѣiBprSv=Ө6hstj))ogJ.L}/ 9gά@+7%=85EnBw*XX@&9 RA!@TwA*l`IJ bHNJ!ˊ ;J #8X;Ek4SLAPF&D;fZE q ;fH63HpWAH*ҙ"(A9T 6XIߟZNy\.Bs<'T H"Aw!P`<]PD]ڍҙsơBSj , 5f1 UC+Yl%I`VL1RTn $缄1|B0T 87 哴zݩc!clB߬kӪ1rnB@ј!Q`^A D$GKE(IZ  w~`hJ9J1 @1Qƻ9- '!3K?r/xqIHa͠X6̂@~& ,%iߊW{?p+ѬC<6uע4X94mowR Kp`.\]S0A I!dapvdQSF)¶˨҄$8&2m|!2{T:J!QݻF qTBX2 [vh'93 GLC C)X:xX bBbC0^ Rr ݸ+WmӀ@Z5㨹#o񖯉 wtbaJcכYfo::å4^&H'0. abZ_RKU{J:ڔa>NveVFh<7!тB'I <R "@iH+Da hbe+1A$y-!ZBfg~^pDo5UF/ NEu8(@F ?76 mڕuj%RQ_FM~ 5|U< A*>+$tgt(YwH_7íp T0V7> ʉ K8u',>uK(u >X?FtgX+Γ)c B!t8ډLX1 :ira@{Rl,S%6 *AS4'D[xlr3s? v`Y*Vm,57b+vv:9nݩ R-oškf ֺ'zEf"'۶1 YJ,'RFCH\WHLk/dU[79+$TMҞ BA׌Pny%4ҬqMY0}?R j~LuCi_jB{NpSFU&ac+꿹uL{vCua_̣^&;"+d;p2 U!|8ABZxZ?:(u}Y!6xTW9^*~S*[AQHX8􈌺+e!%VD d>C|ifD duʂȏ ȍK:&B!i}VQu~ l *nA;6Uu_]AouE 0d{V4tu eQVEU#^26Ё;XbʉA0Utݮ ZPuHdM=mC"jmMhH~R,:L8pمmV7Amv9=ReGfٿ9Y;= ,~,o~V :"7UsdЃ Wksk*M;>>|rfAV!:QC6# w%#3ЕJ/d 9݃X, PaQ!P^uF spA fAvx~`Cfv|)a:Zd:T lPuqQ;v̇:Ն 7$ltjdž|#! d|[%XU{oYmoN<Ѐ+u:UkEۊO1@ M¨-9n]Aѭ^2sEpC^L pۡ~,I>f'I $R,hZq6 '$ Pa^o=o%7od^v:+_wcz׊1C0f@57٘xqlaMH`6?$܊Tf/V fرN p4\4uq"yVOWENJ} ȧ~p Yq t"n," 9sGLZ͓@ƒb$[pVJV2S]HPT\z$!g%XUoVaTxVaRJnXC_g+pP{uW7xu{!ou뇹~cT%661cS6:$K驄rH֩JI`VpG,Q'3M*z +\ѾZ @>P: P?Au (0q!@p֠Vun;Y/%[V;WJĠ Av5BHqn֝Lh+cgnf9kFb[?nꦯny`r}TڜJ%~eJUiJ2a :a]'*ʤ! pК'PAdP&.)3Me(:iɏ#ʤM'6XilfriDz;7])$hʼn[nb p0A?~N<LLLLLIDdc44444D4` 0q1`````HH&_c44444<4`P_80 0 0 0 0 $ 8#N<LLLLLC7EN۩P.0:}D*RF~ȣ~;}~XoU֗>m׺ږ㠏(vۮ|>f5'G ۙ x\h>3}Gs8rYbр#8c6PP|n8mvܖwGCc(oJ+gvYGQ Mmc`xxC_~֩5f3w89w޷xx"р p8("+$9ܔXqpPL80pޮ^Ac2_Gx7j85VZ1VEo[M MwЅ1@Y5>nhG},L߿8þ?zvCc'4l\ ҍ{?:$  ʄ6G"|/hk?Z|PB}.$4rnR6}jF1.)r1FVu:O~KSW7q}H7!nq82ȐMO XӄNfzߟ:^7nS.6yx"Ӏ%8@ n"PlϵGq htnѡ >M?Оa/oFi8xh^D]\gI"Ȑ7ӻH-5-tAjDԑ!Vm3DwDC/\6} ss4 i g/61s>8y@,tשHi^qthϦ_}~/@}ԲDdtMD @pij]xd\Ƽڍʘn-u!l7#GGwD9 cc4`@Q䴉 p0P")o%zڍԞmPeg kC홿xlwDJ+ݨI |}Cc"@"c#Uﴹz6bniՊ>#̙;LpmX2 0 Ă$8 spiMyhf6h#\\P<]kq'[rf```x2i|'B`LLLLO& X)S_>/c44444<4o80 0 0 0 0 $   pǀiiiii Yh:0@Ѐ#8ضm7q>&!Nǀi;1 0 Ċ?w#sy2 0 0 x[ppQ *߂߂X;9Ӗw11hcf &OLVK܍s܃Uf+g~K>g̴; *فy xIJf["9#ƕy2σ3>`A|`gd-I, wN. t*Vl:ugڜLW{9H5}q1ȃۊ?"80_ti*4.c'8Ŧ b.*4Jf[BǺvb\byAx%O?DX*lszcrjXA㶜v!w7ҶHWjWkڨ3RS4i>POtEqZ:FĢk\T}V#݌]@}cpPFoz}0 CTߑzyUh?8@p!8$VA{ qR<;Pbޥ,;v* 3L}1N UD (%.)(ފ6hs;+iݸkWe[Qi̅u. _VV7eq1j\}ߖ<zH}Sc+?`b93eOhDYߒRZ>SKZxfvi'z?M^xihGےZtʟڦ]Km/ҷD{a1B"up`kC%`H=WmS4VMzK⪯ Z7mmrJ2o:V,8zчumn1i}EYOv{n/sð46{?Mq z6/aiO_ w@y+Hۧs9?ylꦮ{Au=U~Yoj9 YOx~\t}W[ϢHnz<‶b뛟.u Ve5`"ҕ -Ol~VcG|+sM[X 6tjGЩ l7u}XW8gGulch{z#I}}yC۹<..ȴNַY36cσx2XUqUyVM ))Mh !yWcٞM%r+N89 !C ADLftŽv<%^׀]~X[Ҿ }w%MBɒ5auk^nױݺ# f𸤣S˞il<.np 5s\:cnDw%th萑g15NiLKSӠCߨϮss/opP+ H:@*") BDrЙF7d$:63:h k0l/֌AױպC|.׸@_r˜h>m!l_HH_cp\@Ν;dAgq#JwS#q5Zl˔2lϭ7Z,/]h/ҷBc@) d͚Q)$N'p>XC0? ]BOQ($F+5)~4<,n$Isi>P\}7Ӽ;:5ӭ}n|6V} ֱGPc$<Xї˽ƘC;ݤҖthqhiĉNnݺe |alF<@:5M}Q0܍r HxnScػ~[ϪHnzz'x1UDRck5Oڸ/ܔBhU~н+8Zց>-Sw:|wyo5VYW^[u6}KjݖeaI7qBy)3Q1Onրx(8v??O?b G,LW{e $b3x\j:cI!Dr5N.ƀ7p|d澪%b3b\y\  9z*'c8tWDY猠xb(A$/_b xJf["9#ƕ uԍcݎ1sOyx̘@8PʈB"߀H0 OVcX?C:.(hW_~IHjߎ1G>{ťm|/ho>Kޯ>Gť}1hW;_<&cK+p7łm]-6E?͝KSL|;ԇ@بE$!@ sf`sIysiM}I9y,Vp X;ArO/n6 7ys7t<9H2΁0݆b؀dpFbAq'|~08&^ AwhA(Psl>,Vp98w,3'˴k@yƌ,UP!Xiʋ/074픇c+pl'x\DLo@sB<&L'<x)N~:˔ 0կs)&~|om|{ v AYtNT*_8^@(0C{m9u>Q[}ʕv ܬ(+X Z܄lfpn-yLݚ228~Y u$VHtXнL*ۨ ܯ' %+xۚrOgp 'i9p18`p18pRgp-/i}2+$:oj 8m>\p` ycpX>As  53?Ԡn]Zrk=ɜTgH9p 8m*ׯ]cR"EO=5WVZ(08`pDx Fρcfg?OE5cOSV,7# Xgpp;"9psM0sC<\]e͒կ_ $58k ΁ns8^bAs>3:y2+]ZTR-\Hmr9`A,@:s c`bw܃x9}qlG*Ip4 ըZ/ZA 1"s+8mYp׀Ah?`|, +{8 89[ gĉԢiSڰ~tIݼIzVt9`0`?I@s ppͱXc+!sAÇ%7B$@,V`!YbOrdsL;o͛6ۺ׍4(poݺEOF0ǏKsFe_"x\0uYObslzy;2A>O޽{qi/Wƥm۷e r<ԅox)T^߸q#.m@}/SRdzK/&H4+VclW\ql8UBq Ƴ{.[}rdǎQ%³iSsW%zøs̓@nd>>k21tXʈV `[%hn>QFX %&Ūdؐ!_Jj~6jV&o]:w&R{YZPDŽ18H,pCpAln9Getw۷D ~sp}18`py#g Ύ&2(ݻS cL֠nݘh}p[Hʗ;c~{(1³`F*8ﱇe %o\ؗ,V1w=En"[Eۨ-CGO^H>u87H:[ 7Xc# ={o ƏOsCp`΁B%xi i+w R~g|r8:϶xݾyEx{ۏ4:7>#8#n(g!V`΁IDŽ%΁9+dn<[7V!m}^%Br#+$s܌<9`„ *2#wδvD>Lۼ  㬑 1a9H,S 7U+7u:9Ab΁Xyq֤s'9^38H2:3(P tz 2/$EX]O>aSF6eP+$:E "#O?6u'zȑlСt%BŋE :s$r[W<.XA8o0+<9bӧSҥ,fva|ԦUHVfVx7 | oKVmV:ud=|8k p0i$R 87s2FCEƁVN޼jJkhȠAWgN6ؿ6od}:|}7ԶMap!VH\0ʜnty;{t񭏥x08`pD#xWp0yd@'"gp8s`|yhݼyS'W)k,4I9f+/H׫GS'ݳd߾}kݚ|,t4~gVp0\Xͥ˗˿[4m*~wڕ^ɚU!0ӟh޽Ɗ?k&2(Yu2Ttt% ңG_֍htPr7څ)Kuᦫ"4WO։mΝgϜi(`<#_}+YD #pewfVAA 3jWsAUz=`p1P 7Lx+ sqzٿKٞ{իMW\6`͔7ka+,Fo݊C JW}]MQ-D *op!Z'8 9ҧz.]LǏA+,)RW_jЈAgO?9ܯLzZ5j@;*E`eρ˾92e ) f6c#yHؽs(`A(XՏԽ{6_oGvU3>[(P<_.u?~]n\xf%5+X hDeJ$p?B]NlG fԿazݺQw{%ơX]f_vup;e%G* ʗKy5nLcG#=USǎ4hW߃v~uzΜ1i`^bDaj9N|dY#n:@pBXcP ۴{ 4vFx6q8#ū}|;Eq%Ʀ]BuޭdIFKPP99sx"sNLۈ4X Aogߤz߸A9|``JЮ n}7ycw[7bZ)U0?͘{W,7<8A݊ M셵 J:C)nuF/`%? ̕#TR:lqԅ9gOC﷚eV:5k8z= PPƌ^Md|cMԪTOp8&mL)(lXߵX`}ls'h+@I p8 eG96I%ӟw G[LJPF<|`?/ZXnL+8K'A.CzȬ8 `J zcA,=A5)w~ժaB|z2B!΁.V77txӦM#$.^ hR f/EH^g>Y.Z|Y$D]jc< `7C,jƯLF͍=$d^7P8[ơ*F:o (e`ziF?q 0X9KZp0]u 19 poG0J m=~9،@ݥ3Adoʋ]:1 y*9`p~B7x<s֐aR8>ib˜CÔ+/JŅыB{G4uEKTXW"#G|B ޑ9xYZ~ WL~"z!߭vH( lED*Ϝoc:ƞ2D tnFb~}tw9_J;nqsPT)՞ϖwrU'YlA/pK "XZ/s p΃ɟY8_*Ν/mLad855MrDl٢7P??tm`؀ƚR9Xҗ]^g Ί^WAkG?ԇ6`تa]>ժ\͚!뇢#Z7nHP<>G١>;i-24^)ukQ J[7m |'=8P9XU(VDk`C/H `|Fڽ' L lF%l wlXSƏ SR;3 e̸TDÆ Ϊ1#tC`+PmÂ5!|._¿NV,7rGVJukh9OjтzXXsfr`ו|Cd+CZ@EDF 8Jܥoٰ^;!JAjVLAI f Ţ ppiR@O88og<}i`Sl /z7b8X( aӭ ׬ Aʭ-wEfݼIMpS$u=_G< !SAE8${~F5V ;7\?Q  go6Ν1Mz[,K/нwͱ];QCɼߤ1%*ppduf긢%/@Rȓ T@`phO0^`).9B^ӊMǏ J`M"B7x)dp@=~<|5 8=6~pSu#rg}UW%BP^6xj 7s;8P eDHN {6`W)9@a?4v4})%>YAPANtf@q{XuCSn$=8PO8f@pٜb   :  yJ^f,@4ͦd CԅMß~{"!/6M7_+B? ponƃpf|#^8_Ҿ-a_9qo+pHp1mZnƈ6 {pEɳ)cd wl{-@kO5Y3RD e+BSA]-bؒ#T63"<"ʡS5 ;FJ0 @z;p/=P M9i q_NBׂ:۷h& Bqղ4Q8 D('ʓ`9"$ 18x288ϛkluX:8bx #(n RʈH ڿ_:.p:IuɀXqY4޵-`anT,҅:!*FpGa 3G"cרI pH,I{ As @tCB#IOi{ ,``J%EX:`!  g#Tƫ΁.w`4W38xAq^*L@q*$B 矗aݎP "8_5Ї=R'AE^5YyR9/1Qޜz-MɗAkB us 1_>խ?o,l/SFQ!b]+8@~0?J&$8pS7Uƺ1i…218H|΁M  )PLPC"a}@r JP7PeU"|7¬N N:Vlʥ!iOZ!Aŋ pu$A4 MYWHs (+ @@)""5-\:rhFGKS'Ok׬q< _Y|DhPnfݣ!D Owyt/u$Xaϫ'9pZ8 2'8p7{s@-s/V P@nc5z]kVI E* 9Bݻ spWF}7IJp9R!ӧDZ|  puepq*CU"2pTGP05ԕ aEUTt!͛ ?A}z,_-[& Ȃ4'{gpfܲa}/Bfy9PI݌҅"U0}u&n "O4`Tjein0k4  bwk~HZpR WXa$08`pL A!As#n {iĠ241|.NyCKhځ #LT NQa$ ;5+OKɛ౰w_%uXD#xu֭Enj23| Ι@oTaȟ= XǤ98ظqcXbp;hppZ񅲕 s/?#´BNr:;l nnO! Z\A-u >p!?AWte#hz0){NzDBH 9qlڴIt0 C9׮Ҍɓ´w&] B]] XL%Ú%r^.tp7:2dX<_˵p:ai iX}?f2{jCQnٲ6ol$38fh}C7v &hmW>c`~EDrU˖ܤ܉Z pǦMp΅ \&^})l3Ҿ3k{Dv|dYc D[+Z%lTبZ(nǪED4S08H^ph3 9ڤ @W'fap``a@eKiX;>0I#Bӥhz NDTy\x'hMLl3&+tT.)9 =18pF}@s:[)$g.^Uyut~?>~޹\zΜ:,`YRnbj¦AʒCAXbEž C^F^uVk -pQ$p)J@YDHT9C(8+CT5+K΅7ژ=m o]r &(9<>$6ػQI  %8XEie f]G܌M҂cǎ<rAD4&0UtC [mȪ]a:X8 4j;_*9tP7C/e79O=PJlR'4PPT+$?LR>(,uǜԧV r"^bbm7+|_WHdp08:`p&tlՂ))o(o8P71vh@x̰!]+,[@*Yf §' 0_冐Cܙ6/lZ?`py085* CH3 ,!b(яITp_%PH ˗\J91Dp; 0kuRl۬Vx%uƘs$X>M`C yswXdظ08c${'H*?LzXclD>8ֹ&Ѕ^fnp=b(Pnl܎|I N Bwq:L={Ĝg+`J(ALI)o܁rXuFN/U8 +W߲a}(pKzkB!&>O^oޤΝ#=YbH 99FS99%R kV}wI`}f)^ DdEgzјQ$z*$xzJKsx:388o Tz*9r6]# n. =!dpH̙1]< L*\pC\sN͚ơ>aܸty-]j{^˗-3 _hu[}CQԝќ|ow28VWb:4[ɑ]KT\ڿݺy3]G[5e-7F9Sq<)V8 ГsBG>F9n*g2׏5m=Ѷ:0V媏V@?kT('m@B]4On>GjCqL (.ܹcF_u_*ͧ~b9z(q y,fTz;hǣmqxi[TLIus0BXwzrծ}zS^>k t<ׄ .V!hn߾-ٝvcqu;VnK>\ P̝=;e A??'mۿ( _Mr#LVX<&jU 9jNtRl)YyDeRA%X|"O9}IbYv98>pH#;ZBxʕQv^_oW]Y+C* au ԮQCF{eY!{ԡ g!><[6@W?l7Hnǎ xUʠK"Y~rT[ t.;HSQl8LjT*GӅx~/Xu ]H I4pШV =}qMِ!~˗hux9,t2۵&_҂O"+gBs_%H3?vB~Ů2,OF(p"6/x SvVn67y8Xʃ l/>F 7};Սyʗ)#\`o{qrT9oSH2h΁ٟhbD~2A75Q ʇӽww#"x 3lHO<Q!3#@pR҂83dFY_VB>s 38&ظ˄, U04otKpCqA󠱠ѣf %۠D 28غi1!+ͭK;nn<^88xp0A&CƩHb@uuձ.G[v@nWp0b0نnp9E,v@ viN  8X#Ǎ >pcƳ QV.|';v |t 3MVaf oh\K¢DL ֯YEy4wѾOJ0CBjܸL{EO8~i kVm7=7b\{Yj/KG[ !(OW Z gې~}Y3cYxN7sMɔT܂9(L?ؿJ2XIP>wmX!@b:8a2\")t_ YЧ[_ 5 =of}B<H4_۴7^U{(,/;{MZpP_8cnauVԢ |Eo٘z>; X*_,w1ڮY|:* .~/38hբq(´K-89ci9P:a9Pª9ᒗqx @Z[J[6][O>"BG)6.[@%N/ʥ.R=ͽ:apβxȁtsd&5XJft t؞F ` `.? Ǐ&p }d(߸!y]^gpߘ{ շp>+9Y+ Ҥ<PY9IBys%|⢴iӼ'8#Vz酰\O8-9(J H6A*NL*WVV40ɪ2(B9&ZEX`89_JKXC}skVBVς^$/͛6J7\р-QlLɒ~ @z{NUhVb /VQ(@l,@c;;JMQ$`¨rQmâ N;:U*>Ϟ6UƖ0}5EEI i+80s0FB%y$ii2b[ E D\KNՆn8p<#lg@䃳|:C8kZq9@8]RRB@N4pԢYt7n*o`c…2~{[΁.6gߌG(k/,PS ysQ >ҡ94uBGRHq{#AK'D:P}1yԇ"Ojp8DUvΐaQ@0o>[0tлYAl)S,c-t[Og!w J}S`n Nb},ge{UZf-8@zk+f "J以KHgstppO8.<ȷ{vHN~s=Pf8C0۰fu:p<0z#sqRIbU(%g_ڊT Ģ:2V:641SHţf4 Ѕr0y(@9{262bPH]))Gtb"=`΁3hJ>)6/[H (MHnA/=q|J+I+'R{|#E>?iE $3=t .;09ѣ}_%onsD~39~&29!f+8=AIZp 08H|A "R ĚƬgp t&E}2gP3b08518ߏ:wɜqx5R!tsAB<&LzHFAh+R9`pKZAa  N4 Ădp=+:4GtN'{ bAWNu&-8h&|aΦl 4&f=9`?~i'r :@`p99pXgsbAWNu&%17o+eVl^X͝;pD}Ϝh1 8-Z9`΁Fœ8H,39+:s լs:s:fK9L=;A&nce˖a9pڰ\rfOϛKD(^?+|tM?zv~_Fr4f4?w.C6VHL^׉^zϜ6Fc*?w6۷#涋slP4܌JC" Z" 08p9V`5ڳLy*vyb085Y `ݶkkcrAЊq֤ uXV  ~~}+Xwѝ;w6hߎ1jdbB9sˍMlT݊T`~YW^$~U+*eJQ^=kvf׳S~=Ŕ1G?{ݻsؐ!9GIpl)r 7Aݺ| ~tpлKgZ<M5oͪAOΞǏѬS(׫/|sgL tS`08q[W|hy+CZ6͛Ф+)sX!{#܎ʗM6( qsȑlXRz D jF6ZrÉ%APղ4߇r|/t} AOx>3f/~!9A;Hjp -]Jo3"9X5[/klVBiJKjݸ!5W٩MB)M9k$H |Xr뺴oKnjCSVF9N t`p=`p@`2]~]*Z+$W2E ~t]0{on f|Z~A]&;믺5V t2RFuנ$=8P ^VI93C؀ PBT܃:9cAF1sA")$Z}}rkpPVtk JD?^۲@ 08xG_O? [TPWB3 ypp=C_)غ%Lc A:b :\l X[E:#yH\t #;J2>RBPn]c/KJHCцnu38`pPɬ Vč7i :@V&K?nݸACM7䥡KprCY: 7]SjSW-[mk3 jP08`p4M/*!E:þɓ| ˗p^kXP,Y qA'h֯~Upa5dpV2ҢA=G7&TppA6eLPSF3c͓[*^{h=}x quSs>5+*N?2o4+mpأA4lukm%3i G <N͚! OJ#㮨/^H>DpD$ypso.[,>jU@*tt{Dz:( 䞝;h4sdZ4w9xrqZ~38`pn- 8ʥi14@%߳;M4._ ws`'V[5ߦlfDpSO-YrEQHp$b"yϗuA@.(,^zAXd|nX`CUXV6/Ґр?VGo!pVU=mޔ/`྽2?Ƒ6 ynuTK @Ϝ:)͕;iߢdŊsebpXAb9V}\RpC`؇>MΠsвa}2LTzUߥ܎ upsn , <38ߐ2:/,+/*A3i% `IY08H z-KN8@Up>aPGp#JuJ  ];ep5A%8غiMP׮I$8X!;,,+pȈ 紡=XShx}`q \,=F)Bˆ5iڄ)%"Kb?Cy(HZ3(X! lfDHe(1,*H5,4x ރˀ@prBœ:#ՋÙA0+V1LqWǁ(?"Gǎ;{!(j; ()M^.?ssV4x9{`?y(πaˆz}|(08jR 4~k9N/u08`pĀ/'/~&2 DKC~38`p?le08gpG`?mDUH" K+L a@8Gs`8AQBߩ6H8)+Y^09^%9ks ˣ֩:;nͨ_)޾k n4єcpy‹C Ϣ|ݣSG[ M~:~Oc2P@ܖ 0.8r@:@4f":u82~LP(6?͚:ݽzvMn18`p08pAgxE<^'^EE;&e?|H-ụoP]xQX<{v9U@ePPgpĜ;pVU't͛7sZ3Xu;wdWvUŋ1nzU7]mD!-^N}'Gv'gʺ߿O *~wcئ7sdWE3ny~4u-&<-mBc`mG[7nܠ/o~)vѾ]BYpm+\p\ ٶ͛e~;0 ,+' k :ܶ ͞>-,1= Y2t >kUq&cל J@ ~$ {۱,7Rhm>7fxoX_xqcȓ+>dIV5x~1モd=nRY3]͸Ac!^F|5QrhS4<)myMsE0Kt{w?~wK>Nj@glJ`\9YīŜ$6h[>3+$FPKǘ+==.]>Fj>tb *Vo{=W^ŋB(JI@ *y ~^t= a1@w3 #m 8o@BDB|`ܰpʰB3 08jn ݔheIZԶyjݤLnnڈP=k Ϫ/bx8apBS,oȽ*V@Q{LbWnbkִlٿ5*n6[ʥK쳤ܜ=p#mٰ^?؃xG4tCT d-7WV 7{7{ wN]::fM"Uݪ ώ^nʈA?WժYtRㆸ< Zh8yPv ?;6G򋠛23T ;aSF9ћY5+K۷l|_> #Dl:uӯQ::8UY LngDž!?Kp`:dL7J__d W-3g5H\a{1u[^$35&0pP8["F|-bV-38TX3lHL̻ զEpAxS ucs8nXhn @~4Y]nE?aYd`xñ1c+>N*/Jp_X%I =P6et% 8IRݥF?jbz%rD XG'/,N uﮝD~W$8D<*v N'~3]{pPJ%k \Q<q훨7}v>| / @ *Wqa)Vǖ , ;`΁gvpܠx"8J]۶+PR08@QkU L}z>u@nqb"tR 8~q{2릌( &ugs\Zf~2 xffpлR솃Gopt>c8N1ITp;릌A \/X_ٲFK(9:,VB/AQNR9ٟV^>w`eOᰝ{ 39~7hef N-A`dV:Jdp)}u1Fa*V x{iŘݻn@D1h,sMt4MZpвeKI%9H|]= ĚƬ ccҜ:<5aK0Vx<5xB37"rNjp N4 boo7o~=$>zw&J8?wN=b;u nyҏGt=8qCA 38Vb` ++p4m,.!mߓ&zuU SF 8E8 8d? NN hS3Q ` G04I; LaW(`ڡe 0518`p~ AwhӯXA94B -]B:>H@XgB' PV寧ĉ'ʌ \A= Awр=;w~[dh<Ҿ-}vf@ܙ3кqCۮƊDAPz08B/A9+gS:.m :08J3Agp8Cx18`pZ:t ge~29d  :HA,YY >v(mnJcVXA[6ol9=l ؠΦn/`͛gW<Xv)g ze]5ثh Xgx B#?bEl֮ܰYν{HG4cm.lmA₃1_wܹ]-RL3="*6E JX/26ɍ┊`Xҗ]v k/Kv^4wpo/ǬsU/H,Y0T {"9JZpмy0~?~0y ij`gflq jU}I:  y nD'NkAj㠀y&S=Љr;NArpskD]">{4õQ#(NjyavأyA4㷬8x=ӒV<_C^ ]Ǎ[;@wvS7tt7:_ ҅ )*  Xkur[4"$U:.#5A…o='7]ܙ=`p ɮX9PmCP|ׯ]5 חA?#pHea? /Ԛ:̭G_ۊtV󯃃jJ#,XجY3 Tbpd AlfMblZB@w,]8ȷp@7&x1Akkn8s\pc-o7(,B`N/vUʔ"DX7s#<,DqDŽ}򤱣L}VuCq zu ]; Ll H62nTxQci+eWyrSZGPp0ݖap-`P'QX.~&,A$Ds9p4F ۄ2Ab_ϚI?ƯK'?(k>i 8#DAMZ2_:8<Τs]Bab 觮\Mj+ػ'Ƃ }uVhZ=NʬhpK@@ /Ƀԥ}[  ^TqjѠ4Կie'_҃<9X`ܻK0p`V=8ҷS +yfHf)nr|u`^~2 x  frx|upF/H}۴n̻aj߱>aeZΜĞ:8=ts?~-,g +(~=K40t']@,p:jRԺqCۭ+]p!fb/ke|y087?uDSoELtΥ8 v& ˀ|s6栾D!" 4mTTbpdyFgNE$SU G€D8tupp_,F,hxQs<^%VF9^6-_fjNZ!rc/t5o|'B{вa}:*bobib(W5^n89p>Л4iB:@'\qȃ,H v(#"\sw`qRO)$~*`p qЃ=9Y+8$S'N؂\M+BAmCB"1`ƘAD_)"Ō .9{xDB_:,%hC+  :~+_lTv8v0}zRث Dp(vNØTH/ƍ=`΁350+!P s܈ @q`|BF^=bb1!m=9x;cР8q?|*VFx3UNcFIM-R1tD n5UB]#1ڹHjp._H+.I?wV.H )Bj~ ʥ O.P@99vS99p,aN %Knܐ{ ..!ȼ[P:81SFlabZbp5jdpA`p<ؙsgp+A;D߾uҤhPaވr('ìlYՑ ݻ|fs/%JFeZKPyYepN VClp6lh0i!39N49HLA @ 8-f h$08]9ՙb 08pZ, 8H,38`p r308pZ, 8H,38`p r3iA @  N4 ĂLjpt08pZ, 8H,38`p rA*`Ϟ=lȦ=18`pഡ=+:ԫW9P9pZ, 8H,38`p r3)=@%  N4 ĂLZpPn0p{n+X 64 0vjYq%t}PQ 8 9ffO>~0n0,ߦ6>>~< (ɘQ-J2{zc51c98'3BPĦӰ2Xs DžqK 9`!/EE$?(<2A6]#E%olTwnߦFjˏA|_:085YM{vG\_:8ϩAjaqsgp@38QZ%ݻw-ٕ mq@{;ЛY_4]vM`^&/<'CJ# [iU漠y~4u- `rCD[>r_|PD[DT?pEMY;O۷l6ޣyf%OIP7}jQR99skK$pХ}[ʋiMôqaPNںqC wm6&"uKp`%bbn^WPՕJ7!V'`Ι>r=(<@H9j,./'Xw| .2剹3O8r\9@)KЦukn@M+Aoр=Ц7ĦСes9QE MXЕSppkq$ݏH6g2^:?5zp 8 Xا. &DwW9xWCRkq, o׮^l~"  'ȇ*VcrTF$M\/ < p`uD_BED(b""o4t8xǂx=tp:p\↎!5SrAes%/D9Ҏ]^ppsJCpԻmk"Kpqo~@tpv_7IJtwhyƘ R dpw״wC*6 R>pHy)d^$ wуpУSG.+|>ds08p%8__:ҘC >`!̘Pw ge850Kf ;  /WD L;0Xn!`p?Zs~hAۺ.AKTm7I(8/2!1;cZ:k5u -]V(,&?Tccs\Wf@01XAfpEp`)Tʁ W%p`JCJ)9 bG73seg{D {HdL9}q!:݂l*1ptߊ,["l~ffp<^nK]Esئ׮z0^ I3x c@eoV {6edSF+9Dn!ha4|3i4p);nM:$)&)C?wVKa~Ӌ=GLInZ/ҚdU~gp 8hp 1vhGޑ}I͵3SU}w Xɹ3uㆮ#=h4 %  klq ?rcA.b m }wdU'X&PiFEM"O\G+.3M̩9h[&uj|FX̓cن]ݸE`Ghc9W>cލGh{mz1sgLeKKɏ=׃qKv2ѪeK-^zgMFV peAj@wqUg,f5;D2VID;˖.?ܹ].tprbq?+.Jorؘ z=$^\ F =,>cԦuk k矕9߇RoƠ /\#SƏ5֑09__=q@}ߠ_4x@ds Q<@n\2Td0fpз[WygqG+žE]?_EZ-6/̾hh/(pP$O.šRiP޲_j]vѣϟy&=/%"28fllɬࠁ'  X ԍK0[ljm4 l308`p`E[7mtnۄ#t8]r9S3nۼIDp0I'k,k,f曾94Vs%\cG={4}Щò^x$pϟ']͂ йmւ ,V>iZAXdq͈qj#3;Ast'۫T7h@XfтJ/N0l@c%›ٲ֍~:!Rv4kʬ X2_ʘU7CXoe fpʨC7f ^&,R=qH  J`s ֶol<Ƿf YS'$UЪuVJ Ow18`pz286𒮐kV#fs=р>y yZ53DIpD-]y<|9 ,8@)2zepy>CA%Oy%rȦ֗:U*9!`C)ᄼ `Э=Xp0Uٞߗb#HP+K@ŗf6B{up\6Yi4sB3:)nFc?mNpḞ+U0Rq@;c*eJ.:-ts _A91*`Ό:4mLu@X'8~kH0'[Wptpu *+6:@2:& ԷMXE?`RX<-EȘ{c FsMiԐA> MW" '0!28`p륞-p $Zլ6- ޽O&!XٜB6Gܖgp-/^?>~N?&q:08r-EKlDkgpbX1 => MSv18B<bMD Ě_R08Ȩ5oQ0k6)vQE+fpFA:08J3AgDVHt}XX!ؐ^0OFN 5vX 1U?ss 99Ȩ ! 2j18`p p%QEw | jrXbZz;[!hQvQap hXQX lJ6 R}^N@608[+ă18CdpFbXЕS ؔMu98 u'}Zf! xaʈ׮]:SMg玨;mx Ncs32B#SΗR hQf3H.\Κ֭%mބ cCs9s؃7GSyZlVaofp- ,]8?9}cc= qaF @ fAңG$ؽōRmԱn\?wލ۷߭÷c /Y2%Estǵ+WQreuFTbyٛYAɺ֥}[ںq5N~HٍO?e<۸v6h|4I޸q#.m|C4e?3O۞\18`΁kʬ7DX9S'Mp؀r~&uV-B@2 ȼZ6w=~Ƃ?tm ŋJz3tE4o=:LDgsdݪAZذ{ NmX+0S`D G(0߀t0G g^tQ>?>NsKpfr֗]-=KKkC؟x ыGhoY38Xhq͓nPn mׁ8z7'M$% 3^qY(b牍DŽ9"}zQlI$=~ ھ]bT8BGSsn55q,խ-4Z*P:Q"2Ƭcp :Z`e-6"Y+9`p|x5 }|iˆa 7E:8Ԍɓ;(߸~]u)NmZa~.1wJ&`< Ꮥ}B"ajsAO99l~Qd?Ḁ:08`pBđJ:ʄ^@WXC}Aղ U!xXFŜ^%? Uzs1bCyI6B"s `kCwʉ,o `&̘` @G9`΁-8qHQ:|(2:^iN]̂$.8vW|[`8jȠt`' (y@W;%IoBZY HzRXb!I Jȫ MB=&#*weia"ss` */sBBH 4lPVP ΋/Xo ĚƬgp t:  |exK4M%<^Y!KPyYu%/1ttg {K 99Ŝ %5@ 8-, h$08]9 bapFbXЕS fӳXu6XgSF6e]ZA?ssY09N49`A,ʩN09.m08pPcXЕSI 5j$Tbs N4 Ădp08d3lv:Lb/qXЕUptssD9`΁=ss r39:@`pidpݷXwsPshK=8W.]Es#h2}g&>x !=| ,O"i)4np;c̪d"3|nxo7q8{y1a:a=inHyB~*4c$ᇴ'߻Q$ M0R/T^+p]:P|9+=t0l= ZwϞ>eG XժQ}6lv)v jQO<Kpq9ظv妤6fjәS(Nj[Է7n`i8#VY1Uʔ4ۯB kVJ%g~&_z aFޥ9ߤ/d5{͚P7 sφi?n?zڻw/ϟ&LCyU>ݺu]g_ĥqiwW,dk=vUEr>X؄ O6o% Sk2ƍG?&*nvc;!Wu;VD/v. $Aq&Mc-M9Tp@DSG4e=z$Aa4uDSԢoYz@ʋ_ y۷h&hqZ9y⣈@кZWC}G,Yu_F@ljϚ=k̜;6 LZl%ByLɒ7w\9r~vwY+7Q 7bc^:jaXogyZ>ҾmLiuXv 2spKp0ԡ vnoҘ4TWD hW\q-VvΜ.}pq1q3}5 C`a2%%$,f7PNE2䣹_{YVT(^TnX9)Ee&\_Vy08K;єGǎ>r@OztANtB?f9P8+dVpPXL A5~/Z6Ym,tFUh^Cy ٟV>M6kƔ"f:88v/8;bU,QɑhzADRHL%P˥( qKnZTD&(BJ &Xm:U*ǏM Qaի,YzX99J3A(ܭc{OT_1ڪRk³k.=%uU+}<08H08H\pDA).B8GiT)Eb=-(7(W̻j@718`p:R?4UTۺ܂UGzfv$s6t4i"E 9p?07:~O{w4衃 pm;n Z\XR&e08pK+A3;A 8@:o/^\vd?  V18p~xx5 @D++ա> (pܶt=m*:q8'%e];#hH]۷y3چbhװǾ)|-p"= d^38!]z%c}*:l.-|n&ڷX;&=.B4ק[*/cb\ 2@in=`39hZ\ņ[66UضysmA ŵWhTHAa.d24n:N{0 ZS}2p\p0Wu =$: ~6Rx5  ܹ}} Jp (+6$ ?Q c]1DhD fT0SY_ /mФժA+.! zaZAFЙ K۷l&X- kߪA&/S'ܷW(اL3LsgN7M<I V@6/?Oe 0?d&-rq{_0{VLEHf/A4|~Z{Ocpsr24QY>IB fp0__ Μ:IϓAX͚@x`K΍ef?A|/Z!3 yqepDc¼p`Ԧit"ƻ naaXX)^@[ORbBH? ~7h18!n 9HR]OΟ??Mk21A-"r ҝ;w͛O?{Yۺp8^z5.moߖm·oX[Hcȕ#>.ڄ~~<7CѨ۶ kE]n]gOv77AA rJ\Vtk,\~ ENu]/V1^׼_[[o;m5M0_x;h^xYcWR%q&cϚ0p9p1ăVpM'>(i]t\,ɟ'KXշN3ذ._(>xjV,O7@T,Vf6QF}>VXn-NW}ׯF7Q{gώ=bA'wvs\ҁ?ٳ~!)p0`p A`ȑUۨ:8-iT0rcZ9 mۤHѣ-76?lnjn[z>r@e8pH`(:ty*»K3|6^ḏ+A<ݬq@i49p s#{fZ*)N v[F7oocx D ~=@s 㵎 9hX޷C:>p6>v-{76{!~?3j>u38H 08H\p~j͓[^A)JkT|m ux'HpA^6rfK!Ì5sE(9(]" *%-8hٲ%!)gʬhoڸ̛4ud?we:8,jl`3&OJ#bgB@%vx=W\6́їEsώ>d|W  t3k͘6U+/D^7R~9pMP "D]@3Ɔ'ȧgs?tm.8BR6uѱƳfkZ2y\9A@ -1s)0Of<&L[t ŽVyOW^^M՟(<@򃥧؊rƍnlX'M`ڈM^  jS$?x087p^(.[֬nV4<%b/('| PJ\r8vߣ֪ xՍ= .ZOsH`3XH$p^wCņM߶yںq_*f3S~lҽZpтKOnlL8ais߄T}f:U*6wbpDhQ(—7p+t̙qo+,cU #~?jըXjU \1n`p{1%+Aa'<͖tpp)*]߳{8V x(3ݼqC7mx f]F݊TAQvA| x X; W(^b]=u^{WWuW?Է{2bd'i%#su &4n+p pMU5/WtÄ.@:`]w; Q[p=ױ?VYdJ6g.UsƏiK̳CUk yq7zo]]hpi$+tmG w썽OE sg1=2<h*8J-BdɪN벂M$A&Aj?|.-z*1heAEVXO>[}{SS p~lQpnkv( _ζu፴?㔓 Z@g3F{ߠ}d cL>W t>$pPE}SsX1ɠ wclXt9̝Nhy~8- CӦ#͛'pPޡA56~>r,SS"/,⠪=ÿG\16-+ 7IB6""eVHJK@ .8`/h}_p^ <]7mɝBH%2 Kuy7~}hcIž'E+lXCVm"e$/8s/ʐذyb $+^/+$OVE)@AV{Ay{}-__xaaaJS[WӴsCMҬ" @pЯ_?$5Gp@#AS fxl# 9slBWHAdUYe'u2+x0 ,^Ȱeyn 8Tu-ŀ88ȻU~&jmR-8N%ppYv߉CtXs88Hh.p&,ޗA μ BroA%p@E^NJ麫LdIvJ*n:䕡 9P- eA: h`n;ƌ>LfɪN@ V@@C4pO$Ir*.>3-p!;yAso \'Gfx\ܱb[buЀA (8G77E)(Z_>+w98gʔY)Mf&%{r7|cZ#@Ayij8C*:gשwiK'G9Tf͚zAb)O8HRk'ٱJ)kTڌ8Pju/aϜ1yK\/bs9p`vIhÕY?x}ڷ}WOtH}KǍ)pP jxEOҽ~uJiV{[zꚌ`ų3&čdǎ%zq֭q%%DodƌfyM3r7Ʊf+Stl :['zSE湇Zw}g> "Cj16cbN8jkך&3.ٙw?n?:gdv]?RS? -\n(Жr\_i]vء{t>I{M5%pp tqF6^~ٞgsw_? w 291lȕvu9I968pƎLEcN9h@b)a fZP=>f؄^k.߿G}̀/ccmzQagT6x(91z:7f0Rnk'B|W{ٽ.{5CKɓI ʈ6i=ux ScE-~N9ГKJ18&Ǵ TDEcFb`ڷ< Xc QX&|/Ҁ%A*b|.\hڷoo&NbQ֪Z~9A,z_! CIԋj/pެ>bs~`;C2 VzWE%w;kVi{KmL;$ ZVq#5*1~<Op;)<eef"ܿ=iN9蒲rÁAQ`'M??kh4P̟n rslB\n#:ާ,ǬSGGqؑJ!q'u}l_Tw5`+a7\7+xC A Jyr [ bABS&m|dH'.tѹmvQh|eD.^lsbpٲBA\'tB8 dQyI6mh*k׿Yӕ+sofyAtMQa+f>\'aX:(f8{kr9ä6r^^hkw3z0[ _6K|3|ok*૯6Y:Eeoe6GQ:#Ks`Py/2E (9^(8p\=芊E&bxv\׌k͙O1g:o_ESm][8|uS計NYCӧY֐ 3k q7V6r3H^G~Ȝt/͌깧!ΧtAΖq)Tʁz08kF@kH"AiҖ QR0 xok/8vp6X2Y}0?@DM^;<`~CCLkF1vw/p/| PΟ7DC(P E)1?B*?_2yak/8` qęyҾ y=;3GzpŵD*)wmaI #w9&)09YT4d?!f K6<E~y}J>beo;n.`XpJf)pP/"kɹ2|(jצAG+Yo`L}wa &+/8ŀ~}J)LHsE {@MoF*8@fIRyqnC!:'}N?~~6)$‡"i+D9$z [cgX,Ys:Vs/rǖ= Jg#:,$V ,R`: "BPؘ.@x"x, l BS+̆\:!/>lд"p p;8^+I(8`S#1?th&>Ҍ 2e*h{ 0DM:th3w5$"Tu$:x)<>D%9\x2  9hCc sP}ӂ جx烅&vssQǡ\+$AJ2Z!0+8h4ϑAn6v9lY=w~"Hj 5,bYJ{Mp)({ ! ۂBuQ6ކ+pЌAڅ}ѵҌ_Kpƴp+́* /IDAT B{Vũr^xrW5Dep0'ݠ2pUR }KVsFi|nJb[ƍ1i HLb!jΦ^Io!HL$^EȜwUvQdNc9ȢH2l𕥃Lo sn+La.~/\r mNfٳf3N9ڐIz-,s 0x^ӭ|*`i)2ʛ-x=}/|;L8q܍/МZEjx/ |YKI8 x^ue6 yAoפ6b/s@!)wnv'[ ׍0~[,M> ܳ#yiYsc;E88>/+*s8 m\:&xMĹg"At!tTi;L1}, 2 miۻ4y}C2$*Cb*oih.X[DlNف5FfH$S!ג!NkjlMJKfl|b֨oeIn3gLpuL9 Ȱ;S~6&zrPݙGtD@!ѣ悘bJ5z'N%SUC\[ɴFhT[^ ljm2Cb4fJ)S @m;v(3c9APB]W reEqksBW=ˮ;h~6٣9b(1ߧ/߅ӮhJ)#:d|l-SfQ󓻾I2]X@ nJ"^̑g]цM=rdcv ȳ!|f@ q/%Ar{mWQ戴lqڵkͪ@+^tMEDq{[s͚5<;s7: 컯=>z06)2{B3N˶7^y6};zH}ͽm{;͡m[/wҹ^ݺoW jw 2V"sZN+Wik2>2~g|'l8`=~dVl[@ߒ_ws@w 2f~oY7n\$rJcu䓽Y4^ @.qvo+^TTqX#Gٙ;~xIIk rJ]|5$_<_@fW^ҿXhubxo}f |!. 'n@NC7wAvZFsT1fqs}Arn;!zז[чyg<dŊ:(Ts/=R]vءO=}&=kA%Cv8$y)vۙVmUIIж6+L.ڄg狌3JzJP>9pCFKs@淎쟩+ZF+xH#9O, ,kQkC7R|LT"u>mҤ[Zli&lJS ;8K95S)]V5]Mk9 쌊|YKsAicEв<2dm=sGIc9@ǭIٲu9VrIfH-3콧UzqqJDrH" aXd) '2.=x4XaBAVヲ}/M`:d׷oUge?1v 9&e?)A={gV>k;kO!7x88HѾHpqU8]z>Fb>%ʸ۫K 0~^<8W/_.ץ: Μ>\Xrw\i,`HU\j(AukRdQ:Y8Y'/)&Τa`_KY5zArO~ԼpAlR6¥oi38_?U-+eBM;iڋ9syͅ9Md8N}a{!_D>/IPαR_wAK/1VN}\^p^ا ^xp{ϑAyAɗ=׎sd*lY ౮oz6E3QrMS[ vU q$ !Wdf5>x \S,f!Z|l]E'7;u8L_|l„>򂃨"O}:$|Q>A/tJ6_[!<^c9Cq%Yk 82.7/GUOB^JYEaa 9qΩ޺:D88XHd &H2A8L|]2a-6Jy8#0ip*ckh+p pPA- tO > 0euA/aI@v88zmm켹ohIWX҂n>/ x-IIlry&8xglJG򓁞u\> 4+pp`g#6>(y:χ W DZ|'p p-pE|K1mjpa`8 Js2VHuK@Z[iB cqBg3bLb8gODLf̞5Ӝӳ=Zڈ4 ZW@ـ}5ne2aGG/j#v:" 49 1DTρ|b3#s@N֑G8K6!׽\7s6S4z!C@ـj/'_E+ć{ìmi9Kج x8[V*9(R9NpfltӌV@[7v,HAe_ʷsïb*_cF > 2+ȬE\#s@3N9نS;'iR}2áI`d gڒu^J#7y hpFO(QˆOTH9L]qK/͛9Ȼe>s@̈́pd*y-<,[CSR<9| Y88-ak%9Gt dUI׉9hl$ qzPj *rqR^%AԴ{ wL = 8~Pg^{Os%o!p駑WAq1EQ>0{n͆3fʋ}N?՞''c$7`1'<ތjsqz:s]#p p-t-9J[Es\CkךN>=Ḿr1M9p0D$E+%>Mp q l拠[Aw…}f)*P}QfAnج|EY8 ϭ1X>}aHF$8b<qv1>[ukm~Okxtb?/ OyGNn#B6+d RˬÑLˊԞ1Y7d9s 09sP %ԧA:pegg5G'o_?^?Y!&.@́044^@tHLZ^48xkb>fu`Z2V/g{ڑ Ibk//L%g K8#|F>9H#KvVZ8>=z[;ngYn4"kZ2+x~%ǽZ :Sbk?%[r`MJ t@Iц< $:b8f(g~2W}U\$|զXB%%Wʮy;eipa\NCflfsY8ڥۏ?&$b?,>tPʹS| OrMka]rIicv~-ɡ~V;`Cm~0?P%9`\픇-;o-ͼ@P.\sDvؿ]GrPi-L&{280 8ac:*W2z TcjAԉHrWpS\\qB@gc.MжٵA[Ŭ'KvnF{5_&ƍۨhld-hnVaFXXáI5m㈫(Rn|!p pEn^S$88W0ާ0?X.:Et<`*:c=uV]2˗^}dz3wN;nO ߽wt';n\:`3~8;~y-->;gygK{=ǃ3fX?`hS$8GzӸ2\_s88SB ʬycPL>NvH 8e5fןiKL Wi>}L34{ﱇ9-T6ǣfLOVV r$# B?D1m78GjdLD8?G]}MZ& N^^jC_f4LjYާ5Mɓ7p*=Y! 7δ{q:øQכ[e`R#8x.:][U}b22la$YHoi:h{e 6/85?f˖Y@vE%@<2|7  5îMi\_WhW5uS5E×.Q&ɆH:bzt3 =|ʱG[&/=;IGiK^h+x ]S>f_s q)Pkg͝n-|aGv41̰W(׸ܧ8@U8aQkf"8HtpW'fAk| ,KMt]S0+ol`|uhO0 Yk+0i޳ d|%-Û^u]r0I2~Y!$7pJg QaÜ?ЃoapC9Ds8sζ\Y_ ?_q08 '(?>yr &s 8`cD,K|{|/ J5EpPd)ab}]ZY~ρA48hzYS Xl|is[fŁM.eb&Qbap溢 $RY?h($ZV~`WbahgqFİρ{$G2|V q8F.y ܼy| qO@vKOf ɐ6&|8xXcŁ_Cӧ ZS)FJTQKTۿYFhB8pev?;l!1_T##~R-l띯wi.H W\f벳cX>l82BcsP}ʯd;8FK&j`Pp|ܿuko[zZ`@{lwɓY3K5N`6K<>}g/%F(!6$p0 H 7% iݻJ7-9 ɑP9t,"g|gA[eF ;88`=mh"?O`s-e&Oo^xi3sA-2s@t|4][ IkL$3Kl ,At%! lW~RA?l + N ;8`1_4zM>A&׏꼳,`0 mYk8 W]G壥5rHJS$=Z8bmn#p pPLWs8d^Vmp@r}dž/ | INs'4=N&p,?>J!AV{]<y +K-98HЛ#8p1J_fj=yp;!A:YJKm~ cUsd^Vmvͪ(pCMA~Z88 8e.GA9\P888bh #"88(jOӏAy)m9p gV=h nQ=3w-86Kz[HŸaRݒЦȃLk׮-4.WTkjK]_~ [3uE'PTia\OsMmw>!d=ѳGBE5ld\Ae|v8Cb}8e))Nͅ梹ˀAgiSQAXP>B+p opz2.p p`i&ͤmZAW\ ů6AK/Ȭ B*8*c5>wqv5U9*3xРsC 2&_{shsN^Zg+4 Z񓞉q?]~L|OVrV$p p piF4 >p,mU[iV}7pC83zo{N@@@ Ql0yQmk+88H$B4+TSIзAe,Z]-߽p:;%޼>O1vlj`jժ_xvٙZO5kdlGk(vÆ c2YPccP'ɸԮZ3OCUw5 x(AAQWB8qcgblQyv|P1ydo޼قZ͘By5=rd8`3 & O5Oq?]~gޙj/r%kvفTBMɬ BeLfqIN4^#p' lQX܈*-Bjr / 2RъRgì_'@UU[4͉9sWݎ͉M~O@@&2PF́$xa ~5IR2+Ȭ$#{Af%+ E+B1b9ȼ)GI ʧ?B)i[t1b)s x0 zdVYA@w3/AW b|dVYAf7# >rRtPLPo 7|:ڦ5rH`5#@A%[5b9sPlihN>9ρ|e@>9`a|K>YI'߾@y|evkJf?ׯt,XoL<🨞A9s @AO@p@A?T-МA ȶ2+$ ("7CR7̬ - 9'@́TdVH PI} $H~888YAfzd@IZp}* 5Ś$rHρ|VT9ρ|ρ884mik #'EYAfeʧ?dV"Ȭ[Pi("a>(Ĵ2ST{9$!QA@(4Rd[D|sPC_9ρ|s(GNn#-S>@>>rRDx09s %4f{7?Pw7mYyOfdV 9ρR-]s9`M3Ɯ~fBX,2)p p p p9ȲF@ e |7o6_uo)o_}m_t;9(_Y>mGwR|]5{ >IY7nh~ǚϸ_gKygUwV : XfOctMW\i֭[W7l`/_^իWۣLk׮5|IMydI >'Ͻjժb d|e4ȶ{@"ɷ/5 x4{ # EV52+ȬPCfLeV5j+,&9)A2ӟTnӜ|J@GNn#p p ps hӟF@@@ Q!:}F@ qcpB' E+ dVPD9F%AR$%Az88NS@ IFA""Tk_dVɬ B(–POZ(iZȝk"pMlPZ2+Ȭr7 2+ȬA@>P;8ho߾ʐ >Gf|62+ȬPLb ~ ,Db(ۈ9sPL'@́ 2+$^9s໩Ń"ɷ8a}f)*M?`kNpZ ϟ2~]3SDeH,Zߚ͛|6-m)lv@߼ E+ dVYGNFflV88U*2+Ȭ++EYAAۗQ 2+$1b|K9(R%@́吘hs RT[1b49s):s r)1ER~9s $9svs)1EQ>9HBʘvs)B6_PFDʬ "+ 2+-Sɬ A@WN@HyJӗAyE>9HV>9(J#$n9ρ|sfc)|sP,%#@> 9HR0]́jUR-9~5RIENDB`fritzing-app-0.9.2b/help/images/schematic3.png000066400000000000000000000633601250202676700212430ustar00rootroot00000000000000PNG  IHDRoԂsRGBgAMA a pHYsodfIDATx^UEyqּz;3kc *J3( * 9H%IIJ &h}4u UԮ{?%=>Usw<-R$߻wOTPN<|'^r!5tOF Q*krOѴ~=-tÇ;b3NU˖JQDјzV W/_u^(_>PyhZ]!Cn@F?j$i`MV.]stIchHݽcQ__XNRۆ خcc`zf+`do'ܱ]̞>M xSX&eㆱOVEn]Ĉ!9ݻ[[003~\Dƍ:ժh" ;kW%IZ (k/ٔ=vl"}>Շw`xs~ 6 I(Թ^^UzϏnNes=ѼY ʶqq]qm7){wq2: =NUu HrpJY1HM=J>H2hJ\ϧ w$Xh eAcN㴔Rt[xuhx]tHb H J8VH@eQFu'h,@` 4 0tN mQ~$ ~pMTU$i&Haɔ25xU5ظVgM+Lk}٤ Nr>dK D:nܟMtHbWiPgN"Ѷ`gFJ}%AkeA 쪀~-MI(hb}̘ /A0שNI ,8-RXܾ}5@9 /͹ P6DB=oY1#S٪4qև/Ք|xu}tHRt@ipٵDZ eY'Q\ϥj(ݞ:q“]x< ӞT׀fW9W9 ~׫p`xtHB{xLIip6FzuLzTW,Y,Gw`6BS~[0Sz`$`,Y0_ W\7 Xvm-޳gN;Fsdp0j~N[r$H?09^?k[=E'F ߐ% /Uy.ЧDg~~_.Ut ûڅ rʞOׁj ~7J'*e0Dq)U^.ؙAroδ̶F*e0~:xL,H}9It9 ~WFm[?00&)`Pt ğCP4CC( 1 ;{Ʊ& {  C$A.kW9`k`0y&$Q `\YGN/? bO$FP)^pwP5DB>2h5CvZu'=V{S~s = C$1>ҀLNF9JNi-$9Gw:`1h~ߺ]OCOW.W+I;gEi٢rڠZ5|0;Bm1/U ~cؠҲzt.dMExNUu H뵎KSi-U NY*' Μ4q<?a:}K9, 09^3FF{`_]KZ*+ ۝,FsfLtpZIR$#ʕ˾"g߻w1#z2`0u2| ?0, :xAFXnX;9-頲x}XA W*/ :NŋcUViNХ&~6`s^n Ƽ/gJ%йd\ . ~: 0NId3>J^tЁϡͿT:s֨ ~WEWޞ ~:`XN'nw`yDCY~K'e 'H&6}}pZJJ%K]漆20Nvǎ v- ܓt0N}{ p^آys'0>&! ?s0 z5_d2&=i0#>9`sA0lbpⳕRwkWk,_S 0h⩟VAˀee-WܿS]#۞ӪvqCzv:msaWҹu+i`mٸ ʦT^!#`жtJˊ>Lgx3\**]0, (:p+׮^8ӮA5 W-[*`P[7}X% +BY}{q mxrTFߞK/u8:lR&jCTA=AF F.iuJLI A~~}P?^ l] ; huwnRh7K_ *ȡCfC6qZu&ut =퉡^ l ~:`XkWO,:4 L 33 n^0k׮j r ?ǫ] d0ka!`k4X Q v|LI-} 0hKyAuO{L"ء;-(seA[]HYZtI8ehrcD`,] az۽{V}F+K)^u ~KW_Q a`6[(.Q&{ImtܸN^>:aNKAsShO>.*O-omݬPA@B~ ~7vNg0a`w" uWg ~m`Og`i ^-Țp# Fa#Q86e09^>?0 d0jP|`9Q /0& ~:`0m6#ڦ!`9@èl ٜ Z´@`#!OG ñ H9^hV0שN 2F5 XL#hp1RLd09T` s Q /0D`a4v2x^n' ? o:U)@èTt` .&Q ?Ǜj}t`00d0(@w ~:`0N :ǵ 6aM6`0`2C0t` .a8x]0r DpP_/}#y#;x*\HSHEzu7й;^v ꍻdrLZGEcs7Acߞ=rJpk ƿxv0nc0m8T,&6:44X|p`6wkc0w#L3F4 d۷o,0Y` Jgh aO[l_[ qѰZ d0H:w2= 3g"kݰ^+dx;ϖ.. CCBO9^O&?S̞>M-7`0 m2䄋XhH$I'uݮ``T`+@]L;((]2dq)zZ2` GfL0p Ayޗ3˜m" ȸ0aiO6JٵNKѨޫMlVS-24b)h" `ĝO*ҥK>x翶Nw̛W:?GMxR]:_¹sD7P*;;y q ߶커SNw۷f&A3OBA铪N syXpR RG[6}+U(dC<'%[=ߟuH5-\F[hKKzҶaTC$"LsѦUUʕQ[`EOnۼYT(ZDَ `U$XEU$T{~d@[Юt н|\VF6ӾBw` c"^`W&uDW@w^PI/C7|wmʍC Ş];ŻU&5lw-B0@۵ڹ3>Mİ>K:ؾW?u-ڰɓIN 0F ;g8^3Tҿw/AC,z]ge/ d0Xg0xIWW.իWfYx5P ZZT%cI]/V0X0˄娬Y*u^d0d0s 2DBPӼet лmw6P`ܼySv~ٯت\P@) ϕ))~ص˵``[,E<0~r"r@cK{9}ZuyWk Z  . ;ǀ FpAߙ٤>G# ƑCb;`^нYy ndv(x:)τ~`_7`@-q$OݰvX<-p@&(:׾z2A-̜knSPPqǵs(l0|Z~ca')7jLǵϝ5SаJ0{ NdΉ]s:vϽ{;!  oY5ֶ/78^0hA&~hgK|oOW+=h(E 61qx2pHuܫsh$3A֭[ 1be۶`04I|!cG}|͍ pzD0 Ɖ'… SKOѿ(zU}.z!`g'y `8#FwF#!7ZjUJ)}C^AK?{vhX@C? ٵ A AB21$Oa a6APѽcXBvj`h5*RTg͘i] U3E>Zm#-:`03K7==]` [0=g>tRk6b-Ϳ ~pAm!CC$T͛5`04!C$Ns3R[ٵ3` AͶ?BQ&V`pP`KC}2@ܽsG+h0Zݾ79#n۬3 h@Z5C9|8 d0؜FN`0[X\<_` ixR*`RrRl¡Ayy_k -Brd0^rE 8P.Xa4 >uR|c: #bŒNe-k<2 _rұȇ-'Nƍ':ذa2yr#}hjp0rk׮C "ܾt@`(H'tp gtQ wʗ˨3Na.Q.I%Ƞ,M} ~TEu@y:6`$fJAK(`9ԩWؗu(Võ.8iq I=(Q(#T^cx_& 7عc`TT`ω`(ujmVC9P䙳tJ)hE:#}:Fe0֨GV??0;tPGuh;*}s*-[#?0;tT9ZqGxic%XO F® աQѴ~=%X|Y`s#p$#:6c3cڄSE٠3nq(%ؼO FmX}XaB #ʣsRװ~9| * ;,"/;Y $ 6_^gC` îsdT߿Y#q`0Tw;su>cG ͓uv;]<ǒ!A~}w !#=#&h_'tʚt6dџkL؀AFI#'gr~ 1f0m&&щxI:e3͝ .&mٵ3|iRS&`y ]۵qK$,_g`;`th\ܻwO[`Q =]ڏB&Mt c) 62";µV0Тc?N `*0߿"U&y۳GzurMx\&21e8 h_ z ʪGN(*V0X0\.[PplH k8@%Ž49$`[}g42닩Zbv#<rulNw:{;J:ZhC$XE ɜ9{v,vR\v|9`F ۷Ebi[…lE dK5U$C|DK=i+0Ȗo{Qie_N ~ﯚ`bp>!^pAH, ztQJSvÇ8Ÿe0>|ePv:΋?09D4󦋞h d0jVv=pQ} (H^dnLG1᥾TgUR1/j5ZHu_- \tZT6{|i2A #Ֆ0]:KT#,w`$9`\|YЄÜ_@9WFreݻw9F`n}5{Z $`8bj>ٟIVHH̘. нwsl :P9йٕ 0hќmy7YDH3 ^[jm`2I2Xغ[GpH3u9 `2Y۷l֯M ^='.0Ā/ǥb~NdѪZ{áI}O.~nW{&#FƨφJ!f-7޻|vurLcsb~#`j?}ӵ ~:`$)`ұ+[dڶ[6Bé2+w|6>Mfj#`ju ~:`$)`fT2@xt OC ׮] "y\\dQ|لuσzz 0xj6u?I }zt81yXp*K6mt`[oJߋ秃<ëvI4PHai v:#C,"Y*10_AvZ/ 0x9"^`# ceR0 *t΀ 2f tf0Ϣ]Ev\pk0x׀:?00ڼT5tt^,gev =V.WZj3 ?0x9"^`#o? ݰ^HD{i9gZ1? ^=.tH21u4P$9D\,yUޥvѳm ^=i0dZ-{vm93l P9mEpag _`|?00:\(uC`ʥKYf2d/-h" ~:`$ `ߥ4h֮VEE˧ZicF t9# w:-o^ `l{ zګIT' J憵k9'Jxᙊ <x4TB;-[ m«u@FD$eJfEDfmm4Y,];}`Бtt 2(B[S'ٻ{7KA+60o/`$`lP0~5l0L,ał !L40L{\#qiǬS:EJsĭ[<* 0h5fcoMH=} Z7p0[20,J:9իs}'/-svXhZ-._`x֪׾8`p$HheWˑC^i)-׺ 0Ȇݻ9a3 9^#d0, ZjؑÞ_gv*iE /\Tn؀AʖK{RjΟaA0Ի~z?0, s8hB΀Z-RXg}1Sa?e75 3 a& #AǨ?]4~awp!kTvq ͫ }⎗ ~!,-\?0,0;(ͯh[0Sw: ~:`0B9#n-O[`8/Ag`s:}t`0F5!~Fh`a4l ~6 `/ 2F5 `POG b#fd09^4d ~:`0`2 @ 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0XE_7 b#fd0;b4^d0` aT` &?0FN :!_0 d0j ~F`a4l ~6 `/ 2F5 `P` 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0XE_7 b#fd0;b4^d0` aT` &?0FN :!_0 d0j ~F`a4l ~6 `/ 2F5 `P` 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0:V\pA|mX4w;rQѻ{7ѣSاW.bc-?O~bS0, `۷oA> 3~bO'skWNwyۨnKIJE EE S=Jz'8{.z :è㏌@1hPy_ZGEJEfMĈ!bq>=ݘHV-[*Z6~S:RL,A)s@`Np:/>/F}6T?v4R]7qcųKh ٻ*\(yf$l`0F5H.|ظ~?CX0df/}!*( X䄍9Ge0FFhѨX,M{֠{<ѳv[7}p{o:c/w_dq [SMO˗}Rީ}:/7x(Ocǎ%}tR]:"Xݻgwֱ cx|_Aŋ|AY 粆f/EՇewl\?6r6ύTڠ>x>wx1pArȑtrJ'P?& q۫d˨aC=Ѿ۱C؂'Ee=6tVImC$"It- HdU,c%ҟ0w;s Ś+ʈ۷~%-^#%nK N#, kr]4ozx+li\N6dVPNSe*ܱxWt:SG#^,ᚙS(!9 aT}[h5߮<ݶyvt0)!tg0af0_P W &[O39ۚ{iIc(oM` m f76`^*Aʕˡ93+B`0RB\: ;C5";`ha ƀqΝXʏP`A ao%w`JnVe?%`c `W\˗-?\ʚݽ[7|P5ХS'A:S>'&UlpϝSn(W.JKv-0 … ѣGcPI{bId0hB%4QK 0$ע 'Qwe0 Fʼn'D֭N-[xrrTOy`D9tH`KPnWZnTvJZޗ@0 =wwtRNh `<8YCco~?SႨ}Jm&$g_:AB(@ K5[`u떘0sA }t X`Ni :d0 f0h'&99L x &^.2wލA ̃ Xн7/+E>ރ-0 Ư_A 1D0hbre~+SRO{JR` #Tl4,f@l!5Y tS~^P@?wL6lNK%ܺw9`vmڈ<.1DI%p{WA̜J 06]c?x0  AKS͝+?S|:d4qbl}Ĭ*wߺ'7oXr8`DOLt䩒ro ۷d.(9ѵg0bQ&y#A^P/C=$=PTh׶-CF[A !=˖ƌ7Caƽ{DfM((Ξ9XqFȢwj;b&xJaTH")x1vpVDG)#y(o C1c4Ca`\o6>I Ꙇu^ (`g0|TwO`9R֨.̘uߋR'`-RX){AC#,H砠aAYpA(HNV?񏄿`HgKrzjXAGӄ M߳x<ǵ2p# i;K0hN>O,&N: tzS` ;v3g;u]:wgSLѧOF1~-.V,_.&N İіF[4 E!R;v8!:|χ~% ?S|{UP~wn-b t 0ĸgѢEgΝbubb"|_;6ߢz -]*?_`y[ܿO|YAG믾m5sĐAAY׮^0 Sq2۷ocvuT#  zwOg2 gZtXL/vBY:?ZFoS'O++/+it%F*?l@ȶtd;#9Ǝ:$Tg̟=KkhOX0J:r! C$9ɀ{+FV-|WnVe g RN``D?<tJ4A+IuٳkgAsPTM{ t ` NC$,)ઞߡ`?zD˄:uHa4+  nj`[[RvG6Zm־{N`/پ`0Y0FFo*m7֢`\pA˞]ڶֶh0;tts0pm띦VG2~Z-to6.`0whX(&y{U)^,? 7oMSsVpAz`0whp;Îv۟8f0T9l0dfvR :mp_}@ H8# KMGq,=:uT堳Wl`0ЁF5I[c%A( 0nܸ!~Gَ.4E#pp_ސ8yהkW#O(о%¯DBcFs3xmW:G#>9W++* S'W]А&d0P^ Dt\h?gpwk~E֤۷1"h`(`D}{& {wJ]gĪeKۋVM 1dP{Oc'9u(xN=Mu㺯OFmv327ۤN!-ߣSi3NV.7Y1q(Q nWjE憒`0tAŏ#+D]?70vD!c+K\>`hwn΁2vt'"y ͆0ɓW.hJNg* e`Ȃ{' 2jn!yYl%Q`>%};AmfׇPSOhTBć2@~ۦ)]Jf)DAN~N_tcF  xǎ  խþk_Ja[1qSG` `и[ {.`} .^]˵.{I0A5}_8_$ws+،_Aq=w;3H4~;{Bzv;t-[D\| Iu:l@=E7{;~C$yCyYCV~U$n/iX5 Da_e0ﷳDytAAϭxk:|sbˎӦBǍ:AC~A`˰$`,?/P`LX"I!' fN6}!P"bA0?jC`z&UO,ڡ^ꁮjgB \ܯo`]0ţLwzl$# pvhZz ruN:TtS瞾]ڶk[dÎ T.[,Α,l`y]I` TA#2~qٲUZ_w 0jV~q`ŒŁ|]AゆfO A#:?gב #>TO ;4 H!:4?zD8%p-ÔƲE Zp+SRܸ~]-:1#GAv=mE{ƔI`j6 ֭*M0R0hN,xWT>˛2MD2 +.vb|:[tz}{v8c_g `4&tAvt``_|p?pu5N ВرI :v䰲-ډNy,d?0#X#LC5<cx~ѩ4pmۼ~mkem#;YcbCrZJKN ,W-7 `g+`ԭQ]L3:3vhAs܁XSF+%TzN)~qd-0%}6o5 ;A~K5Pd|A>{a)K.d[ݻ:`ҵ=4'Zn޹g΁a3hMŽCA l8H?wNy5w_Osc1|Nøh0ҠEG,:,:m# :iS Z΀/IYe-FrFP'}󌌌~!Y{00(e)[yӥ,W(ZD*+UFk_}E/F-a}.d<5 ]Jz/r!L`<_)֫&ʶ:yҳ]΂mNmGKU)ݦ ~:`$)`l\4/b/fѰC"8~rГoqٵ1靖mN*}/Q5{U$. 6`S*z`$)`О셟#"gY\WH &|nd'?jPt`s:x]tHBz~ ~v4IPqp 8.<ԮWnV3WhNJb!3] p /?# cYLKV ąr)88ԠAeΘ2Wqc]']T,N~W$j d09^{ sFFzum7Mǹ˲5'r*AXiI̮R gN'4`\rYԮZՏGTC)(0y>L|G09Aqѽc{Aہ7_vՓbeB9cUQ~{36A#2t(tCJőC|hΆS*%Q0;o B zw?ks j;INgw!{?$u9<:J]i(S\li$mfQ`>iY˖u~S`s*{-`$ `o)ިSrHƩ'Gt!iظ~]耱AѽE"`TDI.^t.ᑸØ9u&ќK"sG+PtD?x0Ʃh./Sa=Lx k7B_ # Q ~UM՞*ZH{t`x՞̎) &L F 12ݾQ{9 ~:`0:rwQxhT+O  *~F8`a4l ~6 `/ 2F5 `POG b#fd09^4d ~:`0`2 @ 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0XE_7 b#fd0;b4^d0` aT` &?0FN :!_0 d0j ~F`a4l ~6 `/ 2F5 `P` 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0XE_7 b#fd0;b4^d0` aT` &?0FN :!_0 d0j ~F`a4l ~6 `/ 2F5 `P` 0F6mG{s Q /0p7t` .nN߫; d0:_ ~m`00d0 OG b#fd09^4d ~:`0`2 @U$u` .6:2lF#MSE 2F5  l`a49 |4PC0@èl*?0F6xmӐ 0` aT` 6V a4l 6Mq ~:`0`2Gp OG 4@CCuF  @_`t` .6:2lFMC6 s Q /0AV\rYn?{`ѫ[fkukjz5_}^]K4{ت׫8zjrqaqŦ`0YF57o4 ӺYѡUsnvObHńџs d'`>u*;+O=TBeb#lޟK;d@`#`,UnOW'عc̼mDOq8sT,׫b$Cӧ77G`S0ja/`~wiZ_F̌D[fׂ.i,r{ؑMĔm"q);m$`.8d02 ˕_LP  7[j1'  td0j`d`ă:ƚ+\o9?B > *F2}L6nݺshǨφ򲅋$۷IcCs1lH@ üiz'DҐ}ݵ]q޽ FJ ?4UGCAX|UAu5~Ȕ]:|IENDB`fritzing-app-0.9.2b/help/images/start.png000066400000000000000000003307401250202676700203540ustar00rootroot00000000000000PNG  IHDRYLsRGBgAMA a pHYsodIDATx^|u$4@pww/-hww+PܝJ[{mI<ݝ9!>^|JЎPc{YΛ7on̙3g$LzeJOZF󐩒LI 2ydK2II2&ƍ;v1cF=jԨI2bĈÇ6lСCd $l&k>}ݻMz&mҭ[6b?M:٤M:ؤ$mm&IZ'I$i$-$"/A+lA[c۷qh: :1 ܟbI^ƚ5kִiƍ7lذAׯW^ݺu$ITqxG l;&!Ips d7/,f#Ȍxp95#{`Fq JV?k}qWMBB "T$tcM݇$Η2^-L)6Į[[Bo(p#^G(35cO's@փpD4oě|Mh#_bJan;nwOOIԕTMK'@(Yw!UgE)G]A 3^"4>$$""It,!aRo腢/ ATtVe,:ԧE]zt}I8&q;r‘͛7q>@P/$Qknݺ5S{_ZkK%Ӽ{%Yҹ-p OhM!64륱[{:Ϳtutmˋ=qxi\ʕ+/^IK0 a@ߢ$Yl%6Y+Ŷ?T$(QS"R&L@mGA)<%2= r$lN 2(@~ _5(@?{}P$V$Q@F =zH)MI$M$iB3WɉIxEԵBE x = sP:j$ (, R҈AAM7B5@ ]k((ee j4(A((~ѓA~9DAi@wAqwA4(Y՚, YNJg6ѡA*vM|Mk? 3Q&b0Gx~ &@(C2 @(h@& J}W!^r(4 >oqKh?Z7fJq'aƽ™ئh+L3-yw f\0f_M}6bgV$ػw/L LVs Z $$-[l+VBV ,{`WD2(1 ƨ9CJY4+[8BdT̜ T-+e"|(S"„(SlK+ʶDdP$P$Vٜ(sF(RgԨ#54dc, 0CGe +.(x sPE욢Р @%m7nڴi˖-[mMKh,hOyflN]$ n!dA6q2s)[5ȩɟ T6iHu`"6R*R)QAQ"XlB.2@R"0I~YD|#yʢ W@A t&`Z"[:O| K2C-xAg1p Q<ÐES+z 4Ȅ5 24B΅>kA}7QRAM7Qٲu\"'cmPĨmbРmPQЌn  THQOc&.= T+aTȷXˍۊ(=hBEr!A  ڵkwJٓRGҥKXQ+hO%/_iP''Dy6h.N41k#oL5qM?i8M1?{OŒw'EޞykRI#0]4'8?iĹ#M'qMh("N&O_ɮb6ҷ޲u䭵8oyk$䩱Pjطֲ-Hr@۷ܹl;R6HJ$Q&Fθ9"ORmSP%Y2[= IJ}$)BRH#ѡT:$%U749Q$3'UbH!ox 45S{:kBO:7G'c|)0CT,$ 1'2`$Q $gQO1P>PD)d#{-> Zܠ)r gSxMT4p!,'eYq0NN![ufA(S<(;+Bq qhuFͤ22#!d=t2\2"0 ={VT==suN> k',j0)̗_~9FmsxXđaGE8td3G>WG1Mms I޷F95tydĥFF刈S#pdž=:}/ZRW Q]#(( =TւEpU9, eO(j$s:ˆAhЅ2.Wġmи8 ELY4rUӠ$ T<|eXuSTM^b4Nٿ5CmA1b`Vdj&4h!TPTF!;󋊌2"Ń< TdU 3 9 #QxGM@DN > *SaUîlY@wLt?T $HK),yhOa&D2n!UPR{Z20zKc7QF4vΞCtMTA!]pt&JlSH jK&*Wݠ<l"  j#(A"\.'[#yQ9yM `!E e4Ed%Dd7H%gz|T rII!Fx6Rs#{Mt6w'Lzw:лӡNG":p2p ;\JWw.Mwci6 xi@Nj:Կ;XGu<`DFt>$odd|s/Rn6Ut}k+1rǕ;v8퐄5?bGP@Ҟ=_FP\iP4h" STMT'Ϫk Rs.r3ߔ皩KQ4:L+^ܳƁPd_2TfYv)F2TZQF/Jd΢.E mؼe,/-ZuUGǮRJ˩ i{&l7$r+%/،I !_ih.o]|KZ"ΒwʽTr.u#QիCGרvt1-P<JW:ywʻd%m(M+XV+/r`w^ %1VAr7+,GR2jw_!^I~UW~E,`k;ztpK lޒE=XdG+ 1 EV!X?VZLr@]:RU0::_%+z ʸ(p\`I q\>tm&`R&$fΎ#LC[n]?,&4A0TYRlbE5kuD%:c٘G5X )(>)UF?j 0+ǵXZ3~Yyj6;lyG,h6q!y⪉cc'v0уE ;qLnp mJ˛wUӌd7Q0 :,/ 4?1gB & < g[UxNNm AZS۠*AAiɣ4SŨo ŏ<9"Eoȿ/EDQ\\Fy$~y s&\sq@e9WXc}PA>ۃ}v s0pt$4ۨq(tX4v 4۾l_fmkH6Xse`ΥZkA@/ y% 99/Pqa XKۇ.~ȷE:!e Nfs lu?H(x^x6{UAM"%=\tPpͪHBB9Ӭէt@A9mB7ۙXo;E"jQØh&J byө& gwzqhE3)Q8jJZiz d&ZB;Tа4W89%4Fc(e zsE--ng]7Hq UC'u 4D04ao5<Q0-U:7EAQlP輠A1\ l&ңCL7Q+RduM0h$))d4RW^'Ϫ6PP8w= T8zgp%=#;W<&*lā2 F?B(pQ, *:2*MhjfrAA bT"4HɁ}Dm0OLhWW@]eچs'̖^kMp.;B,bqxų4ZQժ)HKLÃ6+Њb!Z )J%/Ө_PsIyBB9͊1-ID#anK,)IZJFNL͔ JXi`09P$6 CZšGkLYˢҿ,zY KLIFVKM71CɏjbLc(8V՝s2gkyGD(-'XcKVI^VX1 -b才֒'I%z |U7;Pp,A $bE <. N>1 EVl& dW~0L4& tm 7Qi#PɄ畕ˍhz-\sBY:Br%۠>R~QaյѷAyt 1ѫg44۷<7`%+U޻o?HӀ(luEA4Ӓg}謘% .(UpqKJ\Q갂 n+% )[p8\.?MZKt8~Qwge|Xwme|W.-ҾG y5DDA N,4b>.=/[+w r\ް^E((7_pmTH O)8ȊIPxnƒt1,NmN,i`3[LaJB`$!\o]JCɱƄ6RiTh5B+ Z`l鱫RH SR**囱v)jclݺdDIb)qj,mH,DB$zTAP(($t ȻP36l-X,e#דּ!8)H0gϢcCDL:I#!lNsg V:9`VAK)Ҽmֶ>q^t>y'$!u>9m39Õ:mZ̊bu9lYt3K0L SzZ< "y |D1:(UJEQLs ۠)uӠ(D]KhP3E0SxRMҠ jκMaAJD> 3 *#*#MCΆW, Q Tу= P͚zԻO18Vu 8aZlE*?H N!:ZL;2tbZbU:;}Q%BU YQ)du57T \5hKvW W#`5'M#UXkM_T]=pG7W P9dmՕCWV]^9tiF{2 =N^_=uz,6x=am d!ΫQJhQJ)B+ v_Eq*(EHޣֹD6yqP2I{)j&j?&2n VL D b`TjhCD2"L*XE*g &YQPw%)JJ`b DR+ R)J& I(h _tKWۀ1M6YbdT.NєքĶm dJ(\ljm$T([mnYjU n@shs$2G:\Ơ(0ZDA z;UgM7SiY 4ΩhqM\AJDz N'+g9Ϲ** * ?΢f&ꐊӸa7`h}TʋTTVF5ȣr:.P@HEd%_Tv « h0 8&,i)!CGa:lb6|̊kVuc9"J12Z15k6 щs-nU |C- ÷5*QݍmZnӲnvYqD2&GlӁf0}4|w÷6ҨF74,~՘W>4cB "3($qV n+cϐo}Těz^"rCC[ XA+S?NX}DB 0R$Y"hj (2J(A js /XE)*GP0 )d:I"#'`;X3L hE6q3T.2!UeicDYB+(Hydf/f6 l}6#ΤgKHjDV &X5-r[ 36J+ HjZS,Kځe/)揚3g 'QC@*9О%9.Hڢ?.ω*(PPx_ bw}4^B/Pf>fy E6&#m2<7QlJ)Ӡ(rɈaP4-avRG)PP':2aPPDE,2첊A+Qm W)RˈajCB_TQ~"jNAQ~P6,.\ ۸ikT >H`[4M#FQi5zML3vbZns=M7?UsZaپ\pmZ]ߦ]Pgo:;9ԩkR8NٙNw}6a&̟Ե.P:׹uw6mlWӖnͭ3JQ\D /Ywہn+ۼ+z^99FE)(`7TLppA[.P:q[^<% nf }9IN lƾĴ1IIa}ble&' 6O[5ePi<@Ez@ag>[1D$V_6%TFbɈRV/P4h7J~ ˤ֠6155SI* ͓2j&XK8qyCNI]l]Ŗҿ  $)2ִe# A6B6auM2eGJ CQH csMNb^jjM&nj>9KT0vvҘx<*+RlDmRV`P+Hp((j+hf&7ӯ]MT՝7+Lzq Vo :k6S]^q+*nrG&*hP]o]dH:YABxm M{)4Yw~r&J7 Fl:!DG짠AP*"P E5R z8 o1SgG2&j2Mcr=~*M&Li0i0kLs ͻ"ʼ0I?E5rRxem@)K)bDr`?u@|s _'**̋ #M9*H((jLnРw2yMM)TnFe:tkj((z5 {*Dk*-a/nPMl:jc߬> =AzAaX&*hP$XR*nAm!1ʑ:핝- B!T_Q: ]wBF2 AA% 0R-K)2NMeʔV>=qZ9?:>zy>/k|> 4(a h6j B3hIdž05Y`zr͟N>|jZ3w>LmWӧ 4A3c/WAJv{++^/U,_ZT~úC' CKT]2|=%Kj˅eSaʟ֟-K("IbP{Iq}VN$yR)9yx*V2"Aw&L\ bFqSːVK h :NZgiNPCҀ#Gt#9w<,Vo 8&AT(7<1E1 BA< 2mk,_iО%De۠ ̌x8,6hiT۾$%]"凞ѧYt^FA7Qr&,iPou#PP\kAnX\ ?lMj inHaP1NgB(KeT96e ٳ_T z$A.!(<(rJvn0&-#AjGAqu6~){}YǛe[㵊5_V祂Uu JB4(lQ 2ڲ셅PaD,@>d# lS%rHDdS=97ClV԰'@tL$4$~Z / -AJ'dLgd:QOKhPtt8g\EjA#^mMY &PԐ@ w x$/^x^!P0M4C#u;pu-:/suTY?457QE4MOH#4S&e4&ceTa/R+&*MLLrbU{NX؅DA{c$jiyNeԡP?1A/9zP dzr.x?iDA42&ad  "Ht B&0YPK-0c[U=^EVR\cWXGY &[\@-;U۱r֩NmTnyն*7c⃟ތ@ I~AB2BdLyj/lyN9a]4^*@;lwjwM2)5e l=PGw qp"nJm%}/~ N2> IEljˤKkr&ߚ Bv)}@|S)C{ 8jc>*P*2hԺ(v5yMg2 :tpǞ%`A7Q 0\-^A{ qp'=*7Jě:悛f&TT#t ""(^FT^5"BA2Lw)z ΧAq4/T|N{ R4H#;g-APd!R!FDiΙg('2v96C dLaPG_lD'CF"ݠSADAJ,$44B$B;~?(=A ډvŐ XM5w>3_+})8 g 8ަxw%H 4Z딛(T$L'cmP? =9Y+tAWu f%//S[¡{ Er'ӤAgQPԖ(~kK2dB tUѪFFgNX2u1M.<(<&4bkAF}愽@*˞6j ԤAQH[:4(,2JFBx lFQsry_?CVdñjTA!^'bX;a#/\vDwPAttё\'Cr"75@`- "YȶNB+B`,)}mtqSh?q>8Oz.@pjBM1A%Zb?6qpP#@W >j $zm>iM+ fH>4&jEAv5/w!4&*NQPNMC qDujP  w}gP]qQvWfÅOo t}7QOS4H_SY WP<]2*G˨"Q gQ $P0,Jta!4b1&ꚧ(|ԧAE^2){Q08Md^'bBDG|x8*2)!D턩ک]1Gt'{]: 4nA8',l2].Nsp#Y u P$. ) M P4ׄ B{"QHʣg>7 )}v(x7$PBAQ``D4uQ3py&aО~\:fObA%t cP3êSuS{)dJ"n0-4ܿ0(Ӡs Bר򄧁^NɊ 4Hf=,4:!7AuĠAeNq#(H6J3P3y(R>(H(B\@ Lao! 2.dwyDawRn&gڦbI.l*D6vyN.@1H/ (Pz1vMSN R7B nH1Dr)d<&*t# 4 ߔN # b U\7Uo\3A\KVdGGdPeT2J&}F N(E)ʲyaTQ"΢"\2̓iPMTB 4I$6"rY$T\5NJ#h Mw| '0F )dM={hC00h k #أ\ Hδ%t ͵:ͅ`9tGFZ&{l8 %--W8Wˇ>Hg znhzoi͝5%;ugzM] o` Xk57+ " zA(8uTBB˷~3j` Gs*{{s(D} w-okp?i]ݞE-$Ϊ8Co`آWپ/N]?7C jwawNީ;uk5` XGO 5kPH"OoiNXW%Ҫ=QEH:v\}.'萨sf$W9mJ>Ɗ}ZW5hl/]qkeI;jⵜ/4i_uI>IxR˴E렿w~9,okԊj~:YiXƋ ٌs5t ̓jAߚBIj܇:? MmCi6*k5` X̢?I3g  Sl<{,wS;+ ׊%I3v`oϚLZ}GJܧwge(FkK8k69vegiN`MCcul UL[K۶Â&$}lt5j]Wc1=xgˊgB^}9^{IGIuCXk5` 2ABQ8Pƽv5,ky7۹XyK[Dm>=Ƃ֖Puǒ%*S/ FMZ۳` i=?gs we9ߎƙH^S~֗.ЍYk5` Ң~P h(x3;ZZDZu _8]6]ko:GI~κk*ã!qMm\y̓&ikqJߔKWga_(yiVi5` Xk h\$Hq<2O`}cKCc Xk5` OC(8&^B~595 X:0Xk5` X)4ӳ(H4qo~54paxIn_k5` Xk ( Ĝ9sVk5` Xk5` ~ :}t J(W` Xk5` X  @ۿ'k5` Xk5HE Qp QKz9*Y- R=?9ρ>ӧB={/ CGIXW5<{40 2&Ulgs?;c̿4[vA,k5  N:U [5:?EܗTK-ʷ(ߢtv` 45p!I^@AOɓ;lg~6?_nw,@&J>/nR[Rۯ\h 0 wķ(WxM5)NHu_k|e% **HA #U.DKx+ qρs+Iy& ~ & d† ́xZ iQZNmS.^.Uxk5` "})G +"QرY3[n{h@A {6#r3͝iLsg:uOdD:+ }"K\t_\ҧmZvqsvq50[v²w,I@7n ܹ-O:xz4OXMET@Aa/ް+;+;+|WQ4XP!5I`_)g׎k]wklj4EԔ5@><u`9 [kD"3D0!ڽ{h,P>&)Ip6#Iffffffff~Iy%FAY5kLР& "]RN`n,k%A,͏_}-AbD[!5Lu}NM5NXfj`۶mrapqRwޱ/ %C'N9gV<ǼǼyOg& ^`a 20? (tr &?h& ѠQP]ыqE,~+bw/߽\+Uӷq` 45$רf MFADqqɝNtr;(4cB0/D7Qq>,k5 x#V83Xf'? O 7Q0òaVX d w#AhahaE4`FduҾ+((((((((((|L ͗H41$$~ϐ5I4@(L4h2 r }}_rߗGh  hѣӡ}Lw!L&e2VAdQp?<2##<2##<2 yRJS@9|լt]={օs(HA+bqE,=>X_%\k:[V!kת ZjiЅ%o` xGM4)nˣ{#; ddddedbdbdbdr2s(#T8$H484HQX4pu׻96(H G{ıG{ıG rx-VxVAy{DÇ7B/y+k;1e((8= ʱ~ Ȉc$GzCAQX5ಃ\#TOOBk` JF?M ! 7nUpZJt~vCLyHذndzmop܌5)4XA }_rߗ<ȣ<(zu0@A]BABfL( ҼQd4`d +H@Q|l   𴃨P@w ÛYmɎ$MєΊv6lSdҌn0PZ#-Q1K#k ]jeQ"5AD)m 횭LLLLLLlQZ)P'G(+H-&eGY%7H$f6cf)8MBA-\2ܺ)R )H 5ԀVAAQ|l   Ur"( ]@+(bD^bl6L.XU)P098PS'3k) ()QU r]A+u3j}0.^MΑa4(E"6ېh4A! jP0ԁNvM7y!d+hatύY:VA((%QFAFAFAFAF&F&F&F&g)>7O^v+dgϞ}qGI4S dHpHS ŭZicD-BA"LA> IMQ] (D=XWDADADADADo$&??=uuAA9 b|!s"iP˒QLB/mjZ(!1jlL6!(){3)*Ȥx1 r~q   Xs! ˯O=|{w޿y΅9~ҕYgGA":8zdbqd:k k@  rژ#S Tjc7駟<Ν7nܾzƥKWO C4;|iր*Q.1hhhhhh5-}lg~!|7o_r…g\8~GΝ`  r_5xy(\h:w[=S/au`R  `X@3K̓)PFA~zUʬ¬¬¬X~G'TDA2k55 5 d Jzd~y(H4Xj5{e3p'/5D;cq_K+(u 亂>_Kz\/zyeB+XX=Ub^+((((,2e`gҸ<+([9V??9sgcS4`/k h@"(#632 2 2 2 2 2 2 2 GL >=k x*H8~xFAFAFAFAFAFAFAFAFAFA k5`iVAFArߗ徯Gs0zYw58Rt}x5j4wӿVA@t__~Uȅw9ծ^7}tC/]}Aw… =wށG۷oΝ|ݺu6lKcǎmڴ BV^=sllԠ5Tv S:5V;>}ٔ)SVX1w\ɸqM&4UϞ53[qM߸A\>b[҃|B_wJ?YUϟpSǏz۞ +/\7дm~ \ZX>¡+Μ;'Z ĭllPg΢Ρ +g`Q ;p@L# [KFH8l5bx?8Ϗ ~Q}h0O<|YO y/cQ:e wU~|wZ2 +|6oիCAy…[r?N(>ݻw59Ppʕ[lqAtH?eʴ-[^iP=ߧϝ+O-Zhԩj֬Y(un^۷ѥ˭}FE^ͻ@QWjӪ$0$`ݙ37}'Vra߃aQfNrA'O /۷_j7ضmƍ&$$6\`Ç X6">Dza ٳ}tɑ[.& w_+z,W\>g00V9_j"3-BO`+lw1+wy{ΝbҾWٚ5s5kL=.޼ VmLZQbg' F '1M 1rLLLL"SF}ndǷ˖}4v9sR~Ѣ0֏~~D|}/ep tT` M0Uaʃ=q68P=9s[:/X8c? 7p@D] s77_ڵ?%br҄趭̟8 =͓ǚ3xq9cΝ#߬&Ppun`? ШsnMLpISx8 6lvėgȤQ0(ķH 3vMYSBAXac5<عٹٹٹ1=FWAg:|ժk޽ir !*(A6km^>A޼G7n4~!M(B >x"3G޽#OQAA}!{ IA jb+̀KEA3N{ ӟ{ K7+e ):w-.\ϞBӧf3ŋ1۷Q" QPF>X?N秽? >~ŋp o"LjUp_ݿ/X-1jbnC( Ba$ -SWlw֭[Cb,_# AnVn[Q!&௿H d$QQPimgȼǼǼǼǼǼ gfiذ_&No[}t+(N_iuǎ_upe;5jᇀo>B-_) :ְ5IAo խ`?N}G3h0{ygoӲ]._VEMO֮S(w;{GF? k~.]{uxoAFPp՗.],V")C/V&og NZm; b󽇏%*L=w)As(B 4_L7=+uc /w,7à xȶmtPM+D0K-[ᙉ(8o<^ڵx| bh=PqTXn3ƅk׬CBALm;?C{=?W,|`\B1??fȀ-VnqҪ> \JK\ f|Y:2bJ 9bz n)mSƟlVX/Zpզ}#,^C-tԗD˗l f͚5((Yf$4*(^F;/e$$;iӅ-54[o>0?\]Hk Ш^<0FxǷ7t߱c%. Gs3Q\@A|.NƾM(xs۹5 &L)z b~>2 jVAoߦ{ H!': D݈إ.2wn(;1ĺy= P !3o $̞={*U <**h UArG;^( ?{y&3|3 .\HĵoǎcW8#(8@;:"1F a<섴 `B#. ]ݻv5?{(՚"LwN!r Pich"jQ#Dt#VN\nPlj&N6hv DIM|xJ}RN<  0 ׯ۷cCl+=KN}sw?3w O{O-tFus(0U% HWXAn`11c ͺ);zMn֒.b`(O?AAk(d뎫׮"˩/NXpW+W&F lڎHQF$l~uᙳ&/OEq+WQgp`V!{d UP-I_5bߟM.lra0f0n1w 4!QRob͒ }*BnX))'H$Ma|,m54?V0&&P^j^jiK]ٕ_RJ(A8 Z}+W;~88 kʼegEk M(yw_~l/~;HW`B6 >b!E34@~!F,OZЕ+W/ǎ[jղe@:vڅ608eݾ} ޼y L#(5=z$nwR?=Oziy.ݣ`LuZV7wr*w>}"*WRd%JTRo~Xh(L0꫟}0/gΜ Xb3*TBB4CclBVDXuk/ ܲN 6lp|/^C(﫯Ǜ6mZh@njK#(8~xϢ  1im=f1s{b5,`*,Pl_&(} .RHя?$K*THX(G#@ |J*c@mڴYhƍᲈ/3[F }|| 6 ~'vxUk&.0&ӧOBBºu4p#(HK, -Z\%K]Vfmk׮}믿q̳ ;;nl;k12 D1 *Qad~6lg{̓\<ȕ_ap ̑#'`v6 >Ν?i! "8%K\;AK.=k,8"o>$$ +V Ap%Ky† L(x[̯6xdРA9r:t(f`S5)Po?*(%7{w;ԩS;tש[_M! kho߾iӦM2x3,ߴlͯhqjsk;̖Wv &F{4biYWD `q;L|hVhVxy"c`"Ej5+ި}i&Pp@@B^z_ӋXUXhw3"oXXcƌ !PǪ(AaWN; "*4PЬwh6&qqqF4 o_?;c;7b|xwl7cb׬|ͽ91,'Pw˗/ϝ'7 a哏nAtEQΏ?5 'n[1t1WݰtO]pº%Q b&AO lgs?^g ro@AЬm]o, (o^xg%Ap 0!6 rxb^3 VA 8;wn0fĈ P,(XAAA:8`ܪEs,l(Y .&AUF9sGǶ_g(~q^#߽}YFAZhO qt |GX[`?., 2dܹuo\|t8mli*'$ 2 ZSU30000P~~󐟇^x_D t(- b"i0o޼V Ov"ϯW^`CD4C\݋-e^Pp<0y늄\ 6 n#GtvW/g=vE4~o7UY@rP. 6_k! rpj  z*H>5Y<塸$ׁ:\@ީ}E.T¿~EAf )f _U9(lgo$O(+W.TN 2T#b%bswPѣm۶ 4UV͚5V,UT[.h[r8p٫xh8x6<~|y auJ&lٲ#A'`' a ,;vL((L@6;d Rmoa߶4÷(ߢ|-ߒ]CAtӑ_"`L=+A84X1 h8? H@#a Pرcն ([,(+)JVF *[qu@BAXq-X\>X"3hLc&hJpͫq0~28ڭlūhgD1P{ ~fo]vr޿h ;-ZmזZ*ĸ(n3hWX 16W]`q(&b`<& "GE=~n]tYQPX@hպ705k) Zz`o6(xVI E$@_0a-I}n4p q $ ~jQ XdbCBAPv6d9?TVξ}WoӷQo B, D5)TPPSƏdիVO:%fʮ~J <|H́X ˂ϭ+Rˤeezg(~!0  2 2 2 2 2 2 2 2 2 2 :L4KM*hs|`09Ǐ6S!Ֆ 0 ~ɧX(>k(B|#ՐgNe`&r XfJ*{ ' 'BBA̠P};wI5Q#+G j$t; *XQyc~w[7o]xʕ+m<;`ձP1" 5taDHfͪU K0`$iW:Ե =k ߗDCF*蚃(, p9YC =Ͼۏ:JTZڀgdŗ], †UPV&{…+|wsΝw(X9vPpjXt@A8o a1?~ Aؠ*$$$$$$VAe> :t{x a0 "}(^;1aJsg&# R>}P9<*:u:(h$VsN:|}Wmݺ, "MD1v"qS:<{6. P8aME[;r}{" p&&&&&&Nc6Ĵ1g$(ꫯƛFdEPGbt-3Ҟ?ڵkaC9>6zh!L@$;`!r{L9z(O{HuD_]_Qyp̃O>r swnڻOgϞ`yD7} nܸPpa-Q}>[w+wJ# t*U]嗋 GPhQ|l   `'@hQY}_zihQQ0*Qh  XXXk D G¿czꄂE{ԌV, |?&)(+bL/ 8ەwh(H~B8b! 3`F,DGPP\(>>8spaAB S{U4tz~rݝUvșl5klԨ YŲe>8~s͈f߶ukVA#YO-\FK&\>8M 6q AAAA/^d [ylD8,<s'T 2Q, ,X/%ݡ NE6wPPM7x_iMΘ_7.NhdNo\i{saY@v!?###aAA;vx= P$DY*VA.\fu3g B0d`Uc BVA   OX7jL>A6ۀ* _S#(ץ^7sb$w ?H{gbt$D[<#gΜqJ̃>SnhL)͐<~ CQ)U7СC/LvWÇ=yRžGnj9mBȋdB@x%.1e帬r\Vqu.+4~]A ">@0A@2 j:§Ԑ)V)*_y FT;f2o`LsV\~vbSՍQ%v6GJE{K(0Q;jZ=FZݙgƺ H5yJ#kܹQU!-ZAAT1?nQX>rz7pcۈ Pӵ뙄sܾ"NZH[A \aCӊIuKz`dΌH(*H$,(8i?IF@ȩ6Pޡ`;w`K.HӸqc,^8Jw @"T * "OŊZ<;>k֬@A$1@|2    r GL+UCȱ0-Z.RĠ=Qsirb1V`͸⇍\<0jqE}-_c{\BKXo>zL5rɀ%ȅ,h0̆*0 p;+~SDu Nr0/[Sg=\zUTTT޽:uBY} ^zҥJv3 q6/O/h[7Ii2 .ZhO_FAFAFAFAFAFAFAFAFAO a壪d2x%y0rQ_uѿg1Uԫn1ӛ/m,钸g8&l3¹+Ϙ|44_teB˹ZLټ˴Ε'Ӹ(* ナGA8bCxdS.XH{۶l6~<[1?Q?@Ď;`}5k-,2 z*/5?؋'֬9ujӚU(b2 .^49FA~q   s x4C%% ʧXNCj& ;nBCc Q/W,X48u֍M)0[(6Qs @'!PP!ಃkxSGW;ܕ 4 KXPQ׃A)Zd%'OۖPH)hЛ(% \UFAi!Vn"^5-V\b!9|*$$$$$$VA5*(`G{v]k}̵c)C@ O @A ӝ(l2j׮]cdddddddddt6L&.<7L VAm&9!&rI<c<c<c:ktXb:QaϛU ;ujYIiO?&+lru 2 0 0 0 0 0 UFӯU;H %3#½v 6AUR>>|$HO+D'(luȐ A} Wb\UqU10uV*Y% _bޛVA!k5`BA ?NQp$7n`7XXX 0 ?2LAA|9i(LȴKvڛ7o(;(;(;(;(;cE2efVxbHSP:$1Q/Eȭ[/ ώ~KNi<ݿ4Hf 6l`daaaaaa$ҚA!W߀8oT:m mS37Jrm U8Y>#5()j^e,#ʾ٫O7zUlOyRidW~a ,J{aS{|n`KdeH9,yWIRUWXjժHC[kdΡ]\$|.X*nb "O(%s `Acǎ=z|~9I& DUrTwn0K߂~4b~K /6ckZFd[:2"a,eSae-c*(XHMsSMX"4`sD`y)XFHt.DЇT/ nQ|c<c<c< dxǏ#Ea||}A7-Eܳgϙ3gN8aʡ_m(XQR1|LǢ ՜ .QLXT{芖aGU(pKtWFWx.e|ǔityH카(kwapEӒkB/ɱ($Y}}h͡h+*7.>G믿{{ GoNQp[lݺݻld`````` f P5Ν*(wY(X`\LoWdJ2s;ma-9)[FxxT'KtUKdK1eVڊ*Y2 0eL;(Z` CL ʙ`qg}_5fKO( L?_oF_~ $ | MIb& $پ}; r\VqY9.+eoC~;dηCF ЅLd"{+ʿ)$!gU|6UpE92 ^?tϿӊPnGp4A(S0 ry ^1222j2 ٯ_?C w0`1Ppݘ?pYdCE6] -Ч~ow-\ȯT/_a;[FUzux9+ {>edKU,CJ>Y[U,}PB ժU3FѦDs Ym}ƐlkB X2(Y$|D" 7 1wIr}veQveQveQveQvx:Az`?!p# aD ߅ LGA&~h0zXΦ4H9J -?⣨e>ظId"E-9(Z;ʔ䆉Ty%s#+6Fs.Rmas}8}J(Ѵi@?I /zRP~!̊.YuMPUp]p3U5?_Qp9{(M3qH1D૯bdddddddd̐(-fɒ%'A0"/]d: I~'OxM,ZaPo_~wH*d=&4QrMhLQ|Ax,x,x, Cfݡ^y"=<̜9PpҤIQI /^V;\?]NW=gn0H(ɰZAZ:iѹrn]`r# (XZR"VH([(߿p~*T+[y\G˘r)ܨrG7~!eb#[={*5i&fDyԩ\qL@kKV5>|eM(u)jL*׭[oPHb Ͱ 6CV|4j 3Ú-Fn(r@(ǁ ͰUIIIIII<6񬂰‰8@W&6lC8dZbq;V ޷n5}-||}ӛ{t\ut4عrЗIFLF60ڹgxtr#:-WpE|ѢE,2edW*Y!bA!95~JONҖ~(?芐:s;@4*Tp_V3( A˂|擿nٳgL<T?gΜYfѠN!6&v8e,w >?)Q "ΛBLF0 򛏭<c<c<c*HE P  ɚ5k\ }xejĺ6'۝.k~ Pؖ5cThn[2 cTx`-ZUWHE`>!_U7݋=7⫃+-P ?4H}4k֬dɒٳ46hPjԨM!6&vyQBAT]YpQ mHD_CBSi3`?uKlU 4p-3Bh!6sE6 ;ˤ&D}qRu˸=ˈR,cʢleteTi,cm5byexYL]Aa& iٛN7ʢ/֫+HW*$hD:;w4pwH,ZV-/-< ȱ. 3?[B |bӒ|ld`````` h$& SX*}CVq͙3(X58 :VZΝ;a„;tlג {Y2c=7% c85+̘*Ϗ\tuT|mXupd-cDϪ ya`ele˰QUQHQ#hSηz)}膐l)4< |ѳ (Pt1rr 4vA@}E53MT'Q|l   0*(b ,H%e~`ΝHDJhBٵk/{\wc?>,~GVO\r]pQHREs[e_U፱C"ZFVDV-1}^]Z 3gjsPu]@B`A| f,2Ț2t~LlsYQL$EZ0sڤ+Z(͞?gZBLLY0ּS,7{eb`C#"ORS ] d<# (j<"`Q%l9  FP̀$""H]=m~S;֟ofSX"˾]ydB+Rį_@__h-T$_ejLD yede ͟]6>ٻ>!PpjpE1uk +:?fU|aޡct* M6ry 6o$hPeˆM!L HCxu"$7#8ԩ]K EQmY6{đN4k|BЫ 16Fn4~3ArnQP.,C(e帬r\ckqy.1υvI491spSua9t< (ADsiPeB۔1`FB3; o](?p@``0 2aE (W.4([GVxn|k/bTw5~;~ٝS!IX YIŬ{idH:'@ RŬ ɶ(0l*j'I6lځE1GM;x NOص6?V$ ((v1ϝ;G@#FA~XXXXЀ)(~yD4 Qx*Օ+yfDfruM6飧`α͋Lj̆NJɏ8[¾  (R$/ȯ( Y? XbGű{e^UQ)ᴆ>[gnR%a[ckXguJ{CZ(?fE`Y,ϊ|]pz(Zn:b V6;+ 6+CV|Ԭޡ'CG˅_>P9[*,k׮KB( Yz5XLas Ջiic6???pĄic/ PWM RLGu,1t,ĶmP "(cl^PDLۆWZ0ؒǨu#*P Ha)O@uJi1ֲQ(>Q2<ҢSoVWuPײeKC@!t AL@ ͯ mDE>GACC 1r+cZ&|3N݋9*Pnꓺ a ֒$F5HmvˆG[kjApX\AB&@TUX`-*hLtd4]nq  ˕lTw߳e;hQFA/"U(j?x_߹{;.^>|KWf͞p۔LF0 2 2 2 2 2 2 2 2 f`\l>,Plɒ% LnW?_{7ۣj߮P|Cicԓo"u6@ + (?8kUXFut՗2@/VQ *;hVI%%_tQbd]AM3S(OQXK11y3 8_̶m&/T $4 Sn/EՀw%K_fV2%edidANї'W}aGPh!߮rϟf\宒?O+σ:r3p>:joUP>bhɉu~ 8mS(MwS3\QQQQQQQQQ0C  "^Zl:Gv>`Sz%ׯ_/ 61%V!)vj_iʶ7 u_W2e]sdi3KYgOf_cl[0] N~PUIH0΁l ʹ]D?ʕ+y ;2 0 0 0 0 0 (f<Qtx56gh[ݪZZ=z|UN)Kщ+h/8(H?|mtU@gVܲ`Q"Sp_+nj/"qQ/NfQQU^W2eH ˈUziQ0ȷ` N=zGOreiۧa./w1cFH֑/`4 q rY9.+e帬r\VKs]K{"Ji9W؛X202 ~e|/ b]~e,CJZ -m\.A.`9aCuC% Ȕ.]M?N$j_hDᶉ,dČVAFAݻ1Fr&#f3-/X|o_A Y%=D.YVAS@tWb26PP(xM;dQ8=:g$D| /amNȄw1&b7`n (ʜ9QPb> ^MZ.` Tk"&$Jw(HM޹7(ŇS]f %v #gZb$AAAea 2X`ؙoFAx =рZg@:[DѣGuzRwrEYX@J ,XI1uA/% ~).t:JA?sf d P …`_մ)IsYFAFAXFA.((,:f.5_&k =jn$0ݙo/ɞ={Se cϙ5SPp֭ l&w1 ݻF$1g "{k@FAFAFAFAFA @р)(e˖ܾ}۳(d:׌րZ@A< 亂i+Bgc3LW/5\xzc_$ct"k֬s.Ŕs.eTӹ.:s. @HZ74Dm9T5 H}LSu]3j"XHM4 P0""իWk + V' ɑt$z}?~< ^jtkԛ5@i!k@;tXp$A 9 M2 x+eN   ZYect<ؘL(Mdʨ :@FA @;cQ|>}lR 0H5iltp Qɏf8Ll\4ys95ew(Q̛4Y (hCy\k1EתU77|X«X: #%WQ+ԑP'k5uY9)ӐmQЛȔQiD( ܿya& Go𡽩m+3+eQFAmDژ6[¦VS˖ݻwG " 汄W62޽u,x  %U(YXvAHlJ& H#lis"(& ^@q5 "Cׄ.kŁ@&T(n2ry/ԛ l([7yFFꠠ Q! &7I64r FdT纂wEo *ά)qLvB6o<&SL|\\Ōz-6؉ҫW/ EDtAN!tꗘGy+ȗqSF۵%gl]c9&%Bx+F7R %P(R}&:jZ7gPμNa(^mV:(8}t}֭[H3DZPMK-Ϛ5 #)wV~޹jQpȑ/I?~ 36m4Mb˫^j7Qٳ_~'O~|7o_r…g\8~4t%e=HQ0`TF8SFA~ݸI(X&e 5Yfʕ ʗ/` zSԩS7In߾;ȥ\^ݻFݻwY/~32eZӟΏQ0`TF8SFA~&J(_Qٌ'@$ +UƍmVx8K 0[.N-oժqVpfe)^EA~lR{ X FXMG *x\+: +L(ps%gËqj9I*gZ O]U3 211SNь2™2 2 2 diAkpp˗OSЌ&ؕ̂\W/)/l1XQ( FX`گڗϐDE?; B̥yoATh3H(ؼyslڴI"?CrQ9'^2@[֯=]S&Nܻck'(|9j:+6kPBҘ-ԫYtbm٨vʗ-+B `QjXYD۾kF1e7PƤ@,>y ai=Q0#VvMkOJ(3gN4" KP.b޼y{n 6ϝ;׭[7pjZlp ܳG9zǏc,{ QpƽBA56lΝ;/Ç?x 6[GZzq5jTVjժ=='OBFQڷm!D&c$L;vh5Tl&нK8 *ޤIyok׆IKŊLNۤ~_-c5kVcٲe+\0Tb0bjް&,%# Zr B>(0W kݤH&&c *'z޽oݺ ~h;(##Nb*xD#w͗LnLnV4ne~QQwPpQq=z( ʕ+^2s%Sׯ'00"NDቚ[ :t8m.\cʕ+񑖣K̙3 X8 ?aB{5 ӧtR.`ʕ ZVqC'8fHnZ΋1iTa}:j\Li|0&?4Y oyԨQ<}4`5ի%-[Dq$̀pN^b+xJѡ=`#-29Z nFX T8Ps:^ AQ>  鄂-Z_ar 9d17m vQC(n: p @яvI`|||D+f<ת^N*˔ <2K"Xm! k֭a ѣ(H&f1b{n\*/Y%\SV(jK,ݷoob|Ap[ɍq/^ddd{/~_Jл(%YZC0g-g=78QK<}nrQXuhPZѦA^2}\A*ƭD#"">xUVЧFA8%oߞO AXg?tO89r  |6T<4V8B Waޙ3gd,Va @d:,Z Ǎ{Lݙy#(45|mV 9t%T?ACĄ`6U`?G sh,P_+ =.c7H8`H"Sgedaqp1xۤ J 6h&묮$kT h$:#54iXgA4%Y3k@3ZDLڈ?4 qHC<6ݹXy[(ͫfddTl1wgGSh2 PKOWVpT$ɫ4w"e@& &l׈cja@AVA~F9R#GQPD jbUP w8Cqɀ@VpDAq݊rl-`k2 }.2pFS17QQQQK_7{ɦ)I!_qt^RLk(弨)wQ8%?cQQye_覻cq QP^fp0BDA#j0#*f(>QЛ Q n!;e4}C6cddddLqƩ6#_afhͮU`,<,"j' Ci6&9-}>%ē+* >Vr(2  (/X Rhf5ѻPIw54 DBAb?9O;NJ^>49 (et_= z : >ilLy h5#kbt4 FP]ɇ~C&xh zYTCbpՌ 20 2 $2"@QgBO?Lz>}:RE56He N{7kꫯR Lٲe ]+`(h*"d U ][ z3 r]A.g@+BF:fls+347VPXVAQ[Q:莿肏 Gk134#GZrDAAO(Қ+Q$L8CD;v.,G{/2ICRK/ S-WXH3ήGA/_5d~`~&w}"ֶlR^ (g=8g}[n߸qh|tm9v( QBSЩp\)S[ݲe͛7J|௿'O~|tKg;os.̚=NJ' ܾ}wޡߣ[ܻw$wnD]>*C֡﯒Q<=9;PAE郇 , 6,Ill,ɓ1O Icbbh-(V-Zh޼y؄Ο?V@ رN32\:;t*J5kiޝU(v7G?|o^tw˳Ǐ:t}V鷃9U߽F:[FA#J~鿿2N9XA 2B1Gk1^Kv"u+m yZH`,\PZlS5bĩ Ĭ:(h!ޡSWP2,Y^jPpʕ|ͳg~'Oܹ{7o]~/_=y4n{ rNwsr4)y{rFAFbT ; =5$PČzE>c4X:+o` tj7Pcc-XCkZ[:U Jk;w|x5u(hzw$0aUQ09p?~DfL$He"ux3FA~|J_(e9vd{M%7QFA^cj~&UtPSg`Ly{I;\I9$FnTD3 2p1 .&$QY~6i%J5b䥶lRxnZơ*T)c>`dtԌQPFcRN-ܶmPhG4ll"K6rtVA+%YӓϺ\o !B *j(r3(* 2Nɔ)SOk1^Mh-vU ' d,QA0xΝwy'9ks˽{H{n<7"edʨa*`JYIO (81y1Ԑ8!8uQP r`Ch:6pd`;f!Խ+[c AV^M!K,v?,^XB  Z݊=(C3mPA 亂\WK)zY*X';sL bY*& zyޕ^CQE_5K N^z)(3}͚5|ӦMimDDqJ (CWZ 4=]TD wGAFA5;/":" b䪀/).eMoϤZ3Ũ6UIOQl?ټM\ jBETNQ&e 5Yfʕ ʗ/`f}׬plio4qXuDIG~(ŏTܽE O:|4ic*a0 ecp)(XLht!yE5pݿunԲ 1"($]Hyĩ3 2yS { fC X+TPR,QD%ƻY,ddX"/@QTx !)~yF̮FAFtp _ >S\Za t͛7l={TT 2mڴbŊ+W.44Q>{ 8q"6Yl;VAرc;vU?66N&&&!;shd@6mBp&Rt1ccƍas˖-zRL:=t=Zhk4hP:uH8"vZ˱W6Ôݯ_?hޝ:Q  2 2 2 2 2 2 fv3x{~i4 VR`Խ: `]vAWԤI+F Gd4%:RZ5@ }tʕ+k׮Yfu3th}qЃu=t >/^3t7n<}uo";vk5W4\u矛{0 .]BS 4`Mpt(9]AFAFAFAFAFAFA(ٛ1 2 e1v?@aC#Thc" Fلl5Ν; dڵ4E. >Q`Q۴iCg@3g"{>;<0TJcPPE/a޽Et{>|m;w,J0RQu,a)5 }*(YUq)pTO:  2 2 2 2 2 2 fv3xiS(j )DEa wP0gΜCRDҮ03uԡCBtAG[ma]A9= NnQۂ a&A XH5CcsBAE0aŊqtMw #(  =vWԩ.Y*/[aٳ) $ rS6M_ou9mAfh 3g /Е=cYdh,Y>ٳ >}=ɎeȐ! %dbL /\oFA"VM&t Q׉1cC  ;$KSİi2;1eɲUKDA# '¡"HǏ`F KAAU0 <&AY: 0hU͐~ ?fFAFA=R`4px'5(^BA@m[lDo6YsE(0\C.\(\1Ya mŊgϞD FNnݺC}!'PTFުݹs'TAߗ6̩1F nٰa5B(yheahM3p%+.Y8CCׯ/+_]NpDb`͚589@nJ1  ޽{wޱ/˽{(`㾃 uHAfhD7uQuD*Z6`+ީ9Vc9Vc9VP;adL(2 (AAtD bH A۶m+7o4vH 8E&|hAR6sw(RѠ( AB~uC f|JKW("eD0% Q}G@( kԨ?A࿷h"Z>aX3>Tdd` !ld [hGQ> k@QQ0 K8(HC1yȀP.ꠓ"{_51l"&Z \g$"*ݛ"SPyՀQ X 9ë6+#4IȈȧrookq+J!X|"Inc 2AHiQCCQqng3kw„&#tYgƪAPct5u5>;kԢV x07tgLt.pi_F۶mˈgmZl| iGD4ܡ 2 2Ȉ@( w/G]+ 7 f+xUW1B b*Q$ƪ h%+ [/MdnjU#n!//#@ {UR$1MbUJF- {TU:x[5 '@IT-ւcaNp8 3~g@M`;چq !q9{|˺K #!Q0FuĊ $uEAvEwMW 4 r hFNDPX Nt (q<>1p(P]1lQЫ v]S l DA Q!ZoQ(XrLpÁPxR2ank NA8 __ԐkVS!(ggO=?mf  tfkjgdIZEic{,x VAiUVAZiUxs!  2_WaIT^]YQq- }ըQ}B)(Kq+P ^'Ȭ}K=E/~ r0U/Ͼ"  Xlg|^#6Ȇ8DE!b;e1$)Wxˌ(Hsq4Dž//q5h15 w7o0:@A/; Q0(Vf>Jbvb/^3>U6# jk M$ @fc0@oɇ(Nj(wG$ FAnF!o߾XE5jT^ 5a„ÇWb3p_VЫۑPu~dՈ'w!jUd:R\fyGA&껃(CG'l.M7E 0(hAa5hw&՜SaNJ.K )rL-V&OevoH$ 3RI\r\^ (ĸ7j Z 2# 2|LTܿWnk4C8yĐCdҸEʍئ" iYZ)`%DAnܿnjmਠ 4㋜(ݷɯR}\jk45X4KJ 2D.ݟֈjgQAtЛ.oXF@њՖVA*r`d*(ȱ+ȱ+r 8q!(𔜕9++uL?o>=P9(h‰2wݲ/ mVy>)/ǎ;$"I}Q:uUUU gYY8P$Zx#p6\䀋"xل9L0 TDA`XP};t46~:DA, Q q) C=AX0" s#=m F?a yc}̙ZF/aj ;2<ꮁ` *+𸂀=Aza|#r\ sHAJDOM3J{(-TTB!QSaa ؟< > !lhDAq1AH`D_|QA4U<(J1uD3)5P~DA[.())ޢ A{?Hb 2?8 R8b+ƽ8DE!qsc  AVxl+Ѵ&45DA ')H ȅM%. Q0h((ZXLiPp#qf,T e3]7mT}WԽ=ިQУ…./Y: QZsQPEhPPAhH"% rQ((T ~jf;m̍Z!=z~{v؋lC^J\`7V}ˍk޾z5׶pm_eM׼~߬U}/i@1}"  *H )Q0 ĺD@ gK2@AU[o:5΋ԪUYW<#o} }d}u*KB,vEDA Q(H$ Q((t́8Ӈfk;j_\y//0oK@ڞ muA|AZ ޼=P C6CE*^^ 捊"Y1 1D,ͮtOQ/(,r궿!g' z E,(0ȳ;;R(J:gOC(A;n}:bJLAiKsŊ& s#?yϵzN G4o׮]QXQQT`JRզMT؆;`Ν;lK.nIs.* NzZ:畫r̗K.A I&y{DA Q(H &qEgqCmԸc˜(s$ Y&}cF[=q9 ꤈iآ(ݘ!kWDiбs Pn'HSQVA3 k֬VP7n܈1 ѩ(:ofr/>ر> By` erĈSl֬ټym۶(r8 k!V|Ǝ+˱i\8}z/n`&P[+^P-_zx뛖D@㈂BQ4K# DA`P(>092ЈMQA- v!T1?7Q(ZS= &MP}0 ־YJ!۱yby#f/_4a(8{k$OEnݺ9@A".5k֨(s=6&Nc… CB#p%4iR׮]z)>vQplWFX>{oV=H[2 A`4۳& DA`PP11巘JC^SWe(_H%6Jau55*I*d :h:B P 'GꦊhW^~$210[DxX;,V_*2L>^z͟?_e3(`\XA}e@! bmq(8Q[(fiDA Q(H &q%heV(,VƔ P 3V0 'ZKSf4C`-*f0@"~%\|Ű "0(TעE ̮$>bР`3 #NW͛7A s KƁNЦE0!2c^-{Vem/U@MlzY+WPpDh›gM$ D`r ,b)//%DM #nfA1 ߝhP7[:g2 h0 Z UQPUD1׋0WYYC1s/EI4a r :t(BEC"a\8iD|PBYZ(Q!1O^2$d\TB҉OŤ&#gb5I8Ǝ/^?mL:&T@A#)Sθȸ|p 믿U y;ܴi2b̙icvb8eaZyPРdAt飈ф7oϚ( 1omayAA}ܢ`V$ബe*@$ /:u\wu< ú ֮][|_Zj{2ؠB8bءoi(o_B$. NgN" z E,-(h$flajH (3h ǗǗj<{,gΜ9uz߼y7l4dpUUJri(k+Ο0 w9V*D@> 8eJ,x<]q¹ oޞ5Qc9Vc9V0cZ+DAoQܹo?ٲkډeOk DH &JPsK١`̊6j-؅؈Cl |JYQ(H$ Â`2+DAQ駞3z'(EA /o\<@)Wy@ VUK2җ΃2pb5o_m1QMYT(H$ DT(H UW]%1( AAĎMa*D󀂋-DE/QP "Pp I\9<VAl DA Q(%۰ E9J Ds:NvPc1V45a„b1V0/(X:edifu nN-:+ =e% z8P!f=" 󗊄PJJJPc&Qb!DA Q(H$ z6,++DAoQ00 m P 6S30ic-„FD3,PJ$y@(Q! f8 E p0á 2q ;֎UP_=^{5D@(2)[ (L6Z>}tba !Qb!DAgy) (`8PZI$ z:vDH刖Do |H-Z呀yHoO۶m[np=z8qIoUq8PTz!@A:R (hcy:ظwP\DBpDu6[oըat#?Iޝylԩ">"aW&M-B_~EZ~Ђ"~b??e]&bQE6|!b/ > ʂi0֥K7xDRXN r r r`8 [I$ zN>~ѣ>[شi˺u 1{u`?,`Bl[\$ "c xY/f͚ISڵk? ]~*a DA Q !+'E$  aS }$S0 : F!o߾XE5j{N q 0 {(6[3޳?`(H !@A<9 ރ540S[T>yle@& Aa: k߾(`QP@A QQ$ɍrE"V{%(ތc=@:y*S *H y JihIvT] Q0(OHa$ TiAsUM aVAʤUj b[߽NZ$ fXܩ:eL' AaUP8b(: /() X6h|KDAZ $ MLxtM?YATuT%*0*$K{zO/,QT.oX (A ΢A1LV3z~ $ DEǪ: bP> Lmb+O3! Z1 zWXAO &8&!PP}Ty rt(O#la )a$ LA@B%-{. ])&AŠ;΄# f:'E$  f=[qu(K`ޫ#f+J ]t6R|tZ4ɦnnhڙgr6$XA sr*tCQgzx{l!DA D9(g L:%Dt”3ڐ:,H$ # S+@$ D`#hZL):F?mEh\@NP RQ(9`D1P~$1!خzT eHQ(H$ kDA`pP1 3)dD@yM6؈ "@A[3 S*DA Q(H 6-t눂Dࠠ8ZԠv Q,(^>[B2*@$ DA`AVO(H  J LFtf*(DA Q(H 6-t눂D࣠((DUP!TS:l DA,xnٲ(-]:3# R' 9Vc9Vc9V0? ACA.$ R 40֋my-1Ǘ^zEK pƐX.T 8P(H$ DA(P(H ʡ' 3bF/2[orf @HT!@{ ÔE*++]6D}b{p{A0g  r0Aԥ 0c\A=8@=pj5۠N@AIDA$ @  rQ"ph^zk^M462PTAAADA7'mg=KZ8*1IDATB sQ K7(r4Lb61n3c 0 \< r r nLT@QH$ F*U?U0 *8sT> jf* nݺsƍÛnҥ|Diշ.ZN@V x-\KQFR iܹDAvd tF%vj+ : 1CAaN̪T HB͚5ӡ g5qra%5$ 4y ǗQ={*@)@XAXA4+xΪ ,SמB®.*\Z8VyS&QY'GQ*- 7QDaA J =x{$;No.Ov_K(pQFܓyPp|>X{BU,pi.0 Lc9t(rIYU`ӦM b Q(H$  o;uo9? C\Z zBDA #A|0A+ ADA Q(c̉DAn'|mP>!@&MH Q(ރgH*x9˩3:߫ C >̉aD LΔL2F;gQPLР9s0 3"1{fSE~w93:W4]]{} NlUGo̺=滄,N(csOKK |;~}|cRݛ-cFP诨V={NiawbŊqƕͦUE𨠣={yi$ }_}pi;~ęo:߫ E}\c4UVkMuw֧cGIۧl~ձNr9g|9{.VѣG?lF & ˖-M(G (- n[4nB0d(QB=_z(xwNs?WPT|nHWqyݯft]Q)m괖E->v}"v*.-N÷WOQPpK9(PVZu\'#իW3fL:jԨܣVZ,DAqM|yx - sc=p7WlHbCk5kJ7Z|KY{K|ϖ(S&(z|Ti&/ Sʈr.\ORl>w% X{PqƂ1s Q3r9'sssLE,@ eb NqZ&T.km5@S$#*UʖcJMR*x"AB >=G^:$ @ݺc=LP. L(haHř3g]Œ(HjZ6y\ѮƗLxC,t% JecW1GY( 9yrԷ_:~jCQqIn "^k\Q[i&.xcuazEjQ1oOdQq21!ZḚ(e46)+4c k@W(O;10a0 .^x e nژ`h=iE1# 111ÇQ( ( a!ʼg* 滪/GN~36í*4b[Vu9j{e6c~ܹ,D͠Utmj(<m-Z2h&Z3M*Ķڦ3yFRVkk9hMJU^piA^x- S7[i_݈8- ^uU?ϯkR3ߚ>1[_'~`^ ͆Vt(ثW/]L,\!CҕIp¸104FƍtKyS˲VM,DA/(بQ#i]cI=x{ ɳ>qRu/?jCQ?xnb[bҗnp d+&Y[Z|%pKے̙t/ ӯ'7VcXbNsiZҼY`"-čcS/U_%" a[4Бa 鬂`_j߰L}uC/gz+.~衇Fn//{7oapт#̈²7s+?5m島/_80ls % dqd@Fr}Q:K/Գg{?tv뮻zLm_}\iyut" x8MРHaL3 @L2ʹ1gMq Q(*+k/H D9Vc!S'|w9ˡo>nVt}ǵ~ҢWu3fAg3CA Mo6lO(xU-zk~r]_cB(A~:e$E] /]`&Qp͹*{ng͚ű$ӿKL_;~9x۽_?q}Q,0 w=枣 48 :xwy'&A.t׭7,nӣyݛY5&A8"2Vt3kV 0b[n;wԩS3?d҄ kz NB% B:VO,9sԩS[UU;}@Aa!(H {ZX3+=|;ܳQнT.*\ZN<)޹^~eaw ZzuP>yyIG6m`㩩Uy3.oQwQ,+ݴ1s袋2[2Ծ-n-Zի}E<жN֎qlQ

w93IA|kj'f۷o?aLW̳U(H|.(x5{ΖV~1]kw射P.-\`DA'D(۷/0cFlbY1#Qb D(#_:Te˖_~8Éw'ATC 7~Og֖L7cbFEսO+ؿ_l~}:z`)Iι8VP¤?e‚ʛUA@Ahh^|ogydz\ Q0O(/٣XL(@Q>`?`] 9w܉[Vy(Ţt(4.+ho'x}ED|aϭicK7ѣպ:uNKhs$rI(6[,զ)u :G =pW :t ûiڴi󌂠A3gΤ(Di#%E.``V΄(H  ‚QT);Q 0-|abu1-aXɘ6m BGQ}lS M ?KAݞ3 [ KL" hWȑ#'N2={ܹs+ZDô1E(X!WX7a)A {fPFb6jsoܰaè-.kWyc`$!"CKXAtz }'|+X^=s61 v0?f͜Y;4Kn7]ƍG3ļ4ꢄ(L"p VVV~D@ fL$ ;h [n۶m|6dm=dJև`/@AMӡ 01=Z![j< WQEat5ZMQFj@d > n*Ա(ĊLx[ '̀ PP$i,l[fT S(*6FjXwƺ VTTft4){l?@.&w|oJ]=|#怱NqԄ? lK[yC5v/`|!،cƌqc><#$XkGeŇk'ƄUH}p .z2ٗЈʭ۶B@ fL$ k~A3fZzuT/^mD `yy4h'3Xk|:/5]_r%Oxoo`0!bO>_?Q0 ԲZW4?gFDRlٲÇc4c" ȗn Qw0` /B@ NmQTbjr:vn>fǮ^Ǥ2s$ |s٬ٲguTAAFAm(6s"@;boY][ahtqƷJ1z_׿.?((4$"brױcat|8y}|S˲VM,D ~ҝ&q)++k}ըQcPݻ(V0(D91K< 0Nu'& ڇC9Ndċ,s(g b5`l3 &b\*`Oܣ`(([9M~#D Lp"D0@k 1.5Q0(cǎիW/VQ}݅!j]]qrf s( ZÜ`u,،:ݻ'DM7- hȉS-JVPgvS:O:)[l) 7A≝(vĶJ2q{rUiӄQ, /^/υ P:ƌydě~=pB|h?v TԣG]]4#Q _J^44E㍻[kLʂ {FIP{h207^dr |huM`MQpժU^# Q0(x P*T Q0r.lAkQ(wbT 8U(5EusGޢ. ɗ 1a- |F 1O; bT Q`S"m۶4 Q0(Gy 1/aCFvѣd ioZylH 28^b(wD<$&*@ ^ 6,JvڥS|fj={6e *ژ _!-0FГp d m?p6 $ nLQ! Ey1XD@+ӡ*Iy˖-jNQA mB}`믿ޓ`6\Ƒ+-Um!"  m( zӥM{K^7_mZO|۵9mj PL ĴdcAzVAxDA;mB@ "IlnЀfXz͛uTJc w9c3n7K&Ǹ2m_{umM^^|v5D=&JV"%,rUke*MOH( PF-!T  .YRb, bu(1 0 /pT _ NT;|Ȼ^֬g=}wADA% "P.]tvr!8dN,؅um["2)R/ڼxф'-T h 7oެ XQQ!lϗ:3"ށLl&/S*nf~* o~РAxZ/|WQ0(!P0]@pMyժUj<`aZU^rr.T K_Q0KAf/|U֭v~fT  t66D0U)FM3b>k6 D`@3DA$3Q*@)@XtL*`O`Wΐ(lLK}*@3DA{k!Q($P* u QpR.T D\7lXv-4[S ʨj(Scudh=9CADA']UB |@X!~ p80 ml<NN 0'@S; #O@QH7+VXԓK4({"A'O=wd2mEl6f6+h 1K8-#+Á+t\(xt7>Q`C~y;(9a%[f|Y&|D- H30lT,H30rӦVnNQЄLDbP &+++*|}q '  WS& 9s*oǜ 4 C̃D뷛"ְt _ރ.lqi?YB5#vn) l:PĦZKIWјPH'*l#ۼ4SE pZ2YjzeS3,g(K1~Cs .h`*@(`4恵J}tM`~PAZ.gT q0ƂQ0~9I0D IF C4gќ9% KKqҰ$9LIC%|3mvl H͠T X ^O5j׮݈#>9s,ZhNtkmVWX;) N히}JG'̸b!a(Oy,Ui*h~l4ٶ4c $#B l$gϞ:uG;|g;wcnM[|7l4dpUUJ4hYZj_*IVpXK-QDANJxIVA@ݠ`lȊZZz?FBҵjP⩙ @tTp/rªh'Q#&ʊcN6XmʙԃTQ3H| TZZC59VAP~s 8(|lUv'*p2<%1_D7oߣEڷo_5t>N>ݻwDE {xŢpžZZ`>nvCpB0v]~_QEAn~+|/DUVYDݻw7}n tvœʹ@N,(Lx΢./Q0QoQPҠ(,@(,Y uҥ{^KGpA@t 7<>$ nZ *z].//qWP `ۖZIT xFV] ļ|"pW_?^tLjp;uD:Hܿxe%^^k// Q0}b6 DP`C8qɓA>Fyl(.7._]ˢ^]X(Tx H,..(wtOy;X`V! ɍ P**`DAp 'K$:vؑ#Ǫ>\?+?C>߬Y3AH^:*^8ϗ ]ưB|RW]Xm۶Ftu{# Ǿ.>*`DAewN!_b2{~sM[-/߼yF4= GTF3}8򒋦DAhZ(!-1G@a*`Uu̙'O?~c{`۶yUk,Y}Qi$  8 #E4s#@sbr&*c /ļ;& fk`~*@V  ={ԩӂ>[شi˺u,^|ÆM* Ξ=iӦ}G_l"2aXjݺu0➄ݻ7ӋWeee0ݶmWZ_>ãO{.h׮.3\lBb^V+// s\´fT xM4 à_(RLSKzlDڰ},F<6@w0-jlڴiɒ%wر/%Zz饗0Fvk.3\lx}譮6l//`PPAG*@QbQXyI` 8vXg,NvH3,{GQԂy fyt-Z^z+ÏS"͟?_۷] tvE Bm @ .6\rvox;Jc M盡hD9R*Up֬Y?@AݻF"܌R 2 `QquPbfo3jl߾XjභeLt]T嵁 &h\lPT0o7,C:* p6V~g P*I"@ƍK QicQ*`ߣw)O kL\owW*H T \([]F$ ׍Q*@sDw<*@ܠ`Æ M(Ht]T P*Px ÅÇ0$iv޿@{|G=6leݺ*{3D׳gnzDAR+|AID(?`k׬O {AO5pb])f8;/»Ÿ+ֺn¨*DOz^Xս/^N7(ػ.]z IxyQ 6h@ QȪP һnZ 8¸ԟSF˫7gW/ƗQf@@98eto~#F0$~u|b/VoW]vK̋(Lㆥ whKWR7 8xH ģ{D6+V,[D,6%!n˨CC*Yz5Q9S4P(L_^t 襗ּ:5]Eկ~3V0(دuݺiPkDA=~BrjDTwx;v`9(:Yf-y1V0/Vqy ФI&DAb 8F3f*( DAQQ*@@+@$ t+عs~ s_ӯUVFqM`؊(?gm KnP4{nHr->O P*@"Q( v-/ƌXAAz ti Ikmb[]x_FT PW(kA.1tE\Y}AґMc~3؎'X1,&3 8xic 4 *诃(H3tH:uPov0Z`a+>oaClyw -t &U0n,n mZ$73cx0wygϾvMP{QahELAv'HQ0t(Pp ҵ^ 1/QֿA:f]"[dq'^DBx\T ( CBp`:u컀+عs|H[nS`F&AyT P*@)@ # ^uU]wP]`Bspx31C{3v!h)3CWcyŁ( Ѯ zW_vf+@ (C$xcrb3ļ`^g^y`}tVRt}Je]Q\sZH%G1<)!{Hl*If̘p2yW&A%*+[6oV# +C3ļQY,F6ydyӗĊ.ļY7ͅ^4u74=^(22t^iق `[,yK*ʘUfe2[: #+/\Y)ʮ*~ sL(ãmxt>7?7L_^DP ,@.<6V0/ 73J\a\6nޱu]{-Yg9̄c&lQp̙*5kVt)_bْ%bٴi1}xK[EOc4YB }^ ʥ/>bcQ={u+8~ ,6XE6&z-[ڵ/#G=W`Ss4NL6F '(K֭DZE!'1`9E1 .T P*@ F| v"R\F3p s 4P-_80%(yAt7q{myڸ 6x̰VA^% 'c0p$QQAaA((h0 ֭BHQ jK$~μ%#x5 VQ*$DވLQ(H8]jN¨'INQAZ#iiR*@@!)@$ g6SH) G/Q`!u x.T P*aD~9"YT|hկtM:8SE։2$ñJ[ Tw'K|XA ϔ P*CASF0a LP\VD 3$3P*.Q4(VAhI#1iR*@Q0t(8v<9Ms3kkմxdDAIӄQkXcZ6C _*֛{`ii@nQp\T DfK8MQPd5qT RqR TRb(ZD³t\qT$Q*nP v\ϘT x1ļ-7>䠃\V3JcUb0S% JU08ID7T P*@ 1 6B׺IZM\RHW= $ COaT7aGAak^j+>>puCa69K$6[pl2_hvj *1O(/ "dSxC2z\Tj^ۡ`nS$ iQ\|yvВ,`]!TQTfQZIrT{ܠ Ol ^˖.kPxŊ=z@`bӠ%:"~ e,.\ cu^6ݻQpv^tG`Q,lʗ(bL_Ւ80 *>u(XMIPcHŴ:3T {c1əT #b~e۷oGbժ͉`ȸL|޽W^Ah|6yY]KFe\P+I4V}O[J!)S$H(qƟaC#.QP}w "4!*:_<?~I BO% z*e}S*@K`P E*Aܣ6$zQ\*@(@$ FcSR 6i J Y*T P 'fk@p J$ E@_%Jۡ`nS$ 3Q*Tu1K5' `PpƍgPi0(ߑ[ nFV}u!/QQ(g1 gUx!M_^D`!x_`߾7o[x  ̙3(( F$EykW(@ t@l|eg1= +q&JxMW0q9 QR@Esd˖k'|<}]{MQiӦ F -]*֯_v>2̱0B1<:kIQE$ B@СO=5fOip  >xk.xq.[+1$vjngQ: A80qDc%`lrS\Vzjg+^T PP(hlnV7顎ФIQmdqӺN. vrVeI6|ke͢uc{TX2ɺ/m9<Y<3 1L f~*b^roLٕ(>:vQ03(XX,fK3CP:ԽlUe~*t(ةcGD@(c7md:ܹs D=rE`\YYbޫ8.g; Σf8NN{g^^^D&1кu[S⑥1_`9$54ؤ[)ƺ5|"+`^1 )WT^r KkjzKSc*~,ˤp l֬AQ0"!FbҥXV,[ C3ļQY/g1=6 Ϋ C̛W0|q VA&.1.&KcHhChmO7 K!ޞ]9c 1ӢFQB:7QR9k׮-PP QȪRJWIw5 r+O>mcp Iܣ0 n Z(Ҫ8Tj!6C^LW޳pA. `r`VAZ,g|4k4HbQebO jg0>CDKk|:SK*I 7QG < *@ J:pQio2a(`ݞZT * 8xH|LKDA|P*@@ F aaT G`<,PlƸ!{T P*yQC󅧻Sc,++U!wȮCELh~*qB5){yQQ= XA Vnڄ˕!Yxty@gye|:C'.qE$ Lw'B UР`DB%rE  FeC`{̚lٲ,7Q6ydyӗ / =6nPq-*\x+Vڜ:/: ̠>eFE  gT 2 NPp߾}5jHFoqRlfϞ]vܶmꊊeK2&N,WG!ph1.geBv}/Dw+ܫKT f3 (o|yASQ0432:-ՠ -p;g! ]΅ P  7QZ=6&S*@DA Q@BQp ]˸tT P*$DA`1MDA`: l T DA QAW(ؼysJQle!vxNT P*]#;4iad&=aQQw#Kj[IY[ҸqndiZDPZW-u'pFQP r/WĬt;vJ5ojPtw0 U#6zǎW^ |erʼnul!L߻B/Q ![ !񷜮@g[@ 5=`ݿzd DAg xs((hc QГ1d…=|]=zHQ-N3,Z.0k# ߲%je[Ϊ@;WV!5ąfQ'oQQ(h޼]Ұavw kX侐Lm(i\mvfBeqQQ^ ^`f$ zE01_YYWtҾ}^%>}(]Т~b \-.Q.߲m_ d <-:=W 2g:*m_(L1m ,m{uQa@ Ǫ0iƖem,ZKrEICq"J;q`U߀Y;8ř<BG}TҠ/((h(Wꫯ&N(P+_ &(]W[h wYH uaqvټh_ [Ao9a/#য়~Joѣ`kʼn tu[( ʒ8q͌ %: k(N*]Qi% 3CF?hH`T"7n_.W^3fyMaw,츂> 8p`ɓ&M >܅T]Ύ2h{ z-ȷlqw*0Ҳ*Чf rB!ZhZ`Z4Y =N fxuTgtlf@m Ӱ=h0ŘБopT`q+7lh&GQo7Yt(ʴ+/*AN߰W^bh<6( uTÆ@z/yI aVA3LI닢r˺N j*ꥆԐOODDAMx6Kc8Lca,b k8LqL[z^C+)=>[(h^&@1M]5 fӋkSFM.Ʈ@Vf͆ /0lܸ'M(`Y P*@ \ Q[ƳY u1SM/A*&E((%OFPдLi`ו@NkE9z0ݹCY~l\= Κ5{֨Q#1$(e2eU; <=*@(DDAm63fJZUMYxpzrMsO KWf횑3~1iPGf"s|A4^Kb9A4&AټΝ 4ش^`ƍ% i,Ď ω P*@*@$ zx6K3G8H_drFMXA9?gl{ ť J7Ku, {fecO UY)C )`iiiF@M(Dt_,z@-;x]]Qhߑmjw3b K aHH$ ڄ7oh &y{Tg($#jUz 6 0$  ,%cyW^vyuEN -.P;ecTRCO& joC oΞ={O=z#ܽuM[|7l4dpUUJ}rMG-R x3g|衇a4; 2|`z lSy\(-\6-tGKl_C+ȸyHyT0 1Dlo3! )G^w^euyBW/{.Er.N߅;xפ;(SCx8l!5tpyNH#ŁN: MnQ6}9%K(S(@<$ :AAͤO>Uuc㻆hQbQꖢ-KPȬ%dM*R /tDA(:NLƝ0 @H_i9VPCJӊ4SM2Sh8*HhjX Q'A {`쁱`2y,``;|rPPAQF@Wtï12#12lx&" P}Xb>/*vKV > " dT (} J Q=A1?/bDA`0A" z`( $ DA Q(H$ `F:vΈy¥@@4dȐoٳN>~ѣ>[شi˺u,^|ÆMKWUUu>3fsƈq\A C!~?|__yZi  EA3g֯_G UVA1`L0&gl!Q( יq% ˾/gɺh/!(H  EDAP" DA xF< % W:H |DcKKK16!!lxE" HimQ4 $ EnYzb!S&L Q0:p3 ) 9sS>ȡCo߹y *׬YbeEKu3icd-IoIzK[2W̤gf" F++s  È$!8᪃͛֬]_^z鲕 .1` |GAU(H$ g3,xgQ(HL|%\Cɓ'8pԩSZPGapϞ;wl;>۶mǖ-**L0AU({w7" H$6ʗ/ (SС`yy9hpsp6}1 ~?Ccg Q(HtO$æ 1DAC!~?9Ai%3eq!9P*`0_@H_~;vBI'O' OYtMM+.!?dCAtѾ1KPv2`u[ 'Z7)`rp`0 VA$ zr9Q)GVA 7QNÞ%{Yg%|݄ukժuj֬y7BM3ROj!`qK[y^H$ zr-y zLB8PqɏL|ȇ|ȇ|7l߰VF5o޼}aѢE@ZM%O]zS%q Қ-K̈QHLJZ,8R\/cDA't59\(hқB'lf?0;_;pGM6SLySp dilݪt?'D7ZS;p1 Z匝* JIK5,hAtÄ.QPҠ(gi &a\A?BcqJVJDСCǏ:@ӦM5 ִxd)<x#;4QZKĔQZz HuV>xq ̆b{1=0M*HbczZDjc4bP((Us}D&gԦ& DA췱~m!z7,oݰ9Y`ٳΝ_B "jo)h'MgS쇱8"IƤPwT6ܘR|;gv:` 7էTaƖ1 ח Z[a ,k[(| xz4_g5L3 $ c ~ٙfguy +:p0 Ot/:`gҫ YIQQj7 $X8A}%M`VA5FB P/9ZEDAN,DQz^./*hx_Tfū\DvB?E: 3.9 + Lt+/a|71P 5cSrfHw3Tg|Q=DDTc(IZPP_bL(Xa $QDL>i"Hn$7ɍy8#5d 1:8 LcRf4A0V*JLlUВnyv;| 읳w9{읇wywt}с3"_-DA7k6ږE0Q% MhfFvb؉!?d 2O`Af/)#x1Q*@T @@ QM9hbޓkҽUP} bk;!,H_$Ҳe&L+ɸEu*@T dZȄ:!CbsedeN']B$ zr)zAQSQDƒb 5T P*@r&͕S رcbPg(|Q:f3\IQ7L WF XuP ƈ$m'%%%| fXN.ģIȏT P*@pZ`9y?~bС!R1M$@ (f% Z}3 J$ s k/\Wl%kԄ .>)Ґ!CΞ AN*@[xh`1]<_*@(>|\AFX7F'N"bc٭&  lԨZ ~D~;2*@nt+:vGȨ8 kժ%h(U="(&Q,S?~wpIټyv}|FCHYUPʈW};w޶m*@ ԭQ*@2*e˶ +?۹1 ֬Y)SL6 4Hq' ()1[Vf۷ؽ{盷l߲u+v!*mY75uKmjE ࣏>ڧO9sdDAzgϾ?ʅ P*`_|)PPGȨƍ׮]cbڵ 숋lD*̸0I Fe mڶy]{ +=`JB+,*`q".DA&ݺu[hQFp V˱Q*@2*fUl۶1 ""K@~ vލ ((/уQCƍ  HgΈp߾} WBVN$!fպM6a գT dT|y9D 8J! :50dT6m޺m@M0ïСC؅ cX:GSau>!1(PP`YbE\ g;va1]zT P ,]rѢe8CAt 'DÁicƌ7>b[3@Ȃ#Gpsa2AAAc8AE 1/^pO,BT Pt[iS3B& QYU`+/c`f&ZidA߭Gm'Hxt4uի`u1 T P*@rʕƎ+;$VԠ¸D,1P&x$pژBZ:/5< , #C̫b 7QQPy x?ʧ pb$T P*@r2֬((8(hM fEMY^#GВ! HypyaU#5m jyXIxf{S*@T[,Ƴ8dKcZ {xRFsQǸ_1Q*@T 8U(HjDA_c\[0Q*@T 8U(h۹htsAGy>M_2Q*@T 8U(cɁR34( P*@TDA7=K$ zrM>PyT P*@£QГs@ ! =] |D_0Q*@T 8U(I9 \AϙT P*@*@BDAO.E7(ؤIYyXQ.)Ϸm`}ʕ+ +׮]e, P*@@d zuN[Hq2WQԥ>U:9Q(bqy½{֨QǸ}V_}}_-,8m~u}yтoxs%sk~:pS:s'U>u$ 6^ CQ=wCQz}ѳ庢O^m6Рf?:ys >bl%Y%|>}D S*@DAh$ R=<@aD5lYnqbzFdh %%`/NY(φ(㇇6N%e#}ZKXGl.?P-j(شiSPaÆ%RiiiڵMٛ,+]Yݺi/taޠ/~<[8&^{m]wWyƽַ{#|[4p7?tf[WΝ;ǴUz{'F8^4buҖ?_[wݺu1۶;qvGîCfbea6l.XG3PCkQ>tIި˗^pԑ#G;vU, P*@@)@L y,is$BĴ1Zj!b>,RYor(fHt :) [lٱc-ZQX>]؈]~#BD JB+*3}}|٣sFM*C ^?஺uW/>I=A Vo)*O]v]E?߶l23fK~'SCn߾T%v}ͷgc.__0;;sDZ`HDK':VٳUZ?`J P*@@4 DcTsMAA1 ZcnqK` CQ I ӸJ˴V P]GywQ(GPW9dwku<[7lG <7 Faw0 ekA,/ ZRK|͞ݸ48zサ5ka|}=zy\/ڵO1J>.־F/+eu9- #wOz{,~F?# |ޏl|A7~勦)Q9 pu`Lǁb;2O8(w;vY P#6cv5(#ݷ%P*@(T]b$Kc>])ԆUPs7MA  4XuX;JXAn[1( baxS,)~+ˏ׳Kλኵ LP0ԫ}_u_\ mOhA_PPU}5-XFrKN_7c0>SŬ喥7};kl;ފ<郏 :m& P,3.U#Qm?(=+~˷~}<Ռ?y]6,}rH/A9P7DDX:  5 Y Ċ3(PoKT P*P ]X]<" P?T,D1I }߫uO[zlc7WO؅ ((\~L h0# JГ뮻n7vncڼ[my~:,ᆉW]9 ͛7#VK:5w? hWoț{/35cJV/ٺ=7ԁqէVR}rrI''! pȳsߡyGt'<N+%CSm< P*@@*@bD !kVAk_6k@!㦝8q"- i]V>!VAР_VA`!5VA(4zj5`k/1'~Eb:pn?ty eE goLj}lڴi|j,gŧN} ÷|OϨ>Iէ>>aiէ>xvTê]6ä v*(7i7|%tD'UlYs3 G=zncT DQ0glρ*!xE۽!(Q|]qW&d@װ!u>&裏jFXBjt~((SH6tɷF̼_-zӽ:1g"g^93s̩>={ŀ3W>1 C3̪3jόݟht@UO>1]1g&XYK_a}ȉ E1bq{0y6HX)5 b !D7R(Pꢢۗśyml'M>WY9Q(^޳h1cϛ?cCMڻϻ.`ט1㉂PM\AAQP LWGաG;=>kX?5ݝ- Y^G D,Y2rpJOϪ;jޭ;ws٠=~s&Aa /DV'!#VrJ X pL__fMt %ŐB1hqx s~j}޶Ҥ4>gY=Q($N~]O|tVAPOe@ Ua~?@fUVmOŀ@A`>>tҥKi"ȷ }lƌ駟ڨ- p YX8  f6.j<4=?Jۡ&VrjO䈕j"3^DOXe34cEJ,ݩ%۩iaV0`}D kb@*Dġ*8w\Ɂ@AaiޢU:[ְ4(F`;}{ sWyꝋ/6Eg}G BO4U46 Ԟ p >1o[kBծUU[s 0s Mqܘtfvկ޺FEۺ5چZt 9cG`' 7nI zmyEը l(-VuSS 4fKYMQ -Y(@$ F u6GВ! Hťicʹ# @HMYM0[>}}Opӣ"1h-9uVWu@ Skjծ)U&k L+cCT\}+cXX]] +}& ׯU XXbj 3S)0]ZfbE+[ g%˽pS`Z%o4DWlam%[klyN͘x^F(dK(@,$X( , QPN>֨Q`PD0 7`rV77|L4(8t~h631g:+ޘt^'>Ya4K@;GUfkע@Ug g翎//]t_}ܰa*-a> o sR)0+FvcQ;1Q<1u8&qx(TRFVKHа *'tM_O@[5JR$jO(HQ@i`lUܘ,P0*@?fP+Wna= }.Xi*7ciR|iR:h<]E?`o1ǟթA5[rV|A?TRوφW}6곡U;ޫQR} ;Dc}w}Ta.,߆"O~s# iN *5 +vT+h~4lOwj:) Z J̊5>M wvZ|$!|" l hP]`4 ~8LWXʆkw|g?-H`lVWfLQU;GƖ?=a >ҧH#8&#eqcDM[ 2ezE ;w,B;(6( DbQ;m`*@QS(謯̣@V  Ǥ+(C"a:f~j"Fc:7cxDtڹ߁T횄Ya6<Xl@`U!Hnvv^x1fqܘO')a0;WB/X2QPFu8eb`bQ!8(iP*@A|9^*  ٍU1-AT}^#tfGOB^0@#XbbVWہ~UhOVWVWu=KWmӕs UIY C@9(;v c'"@'&/q> c y}ΉH/r] &QQ% reX`F P*@@DP0kN¥@hP$hi~CGp.7 D?~|圿S_ET}v[޿j{m}KaX 'P_!3ABXG'fG KW"￟8`0!!@ZŠ@A~(RA T P*@" gT 2 1NXE}PL>z(8d Wrɓ'xbϐͳT-?a T]ձpoW.ƲbT@ncz,ʄ39rnHr  ? VbDf$]Kpfl!~I<}4!r"}W;v"QVqΝ.(xL"V{h_fl3P*@ \R({ȴ`?x@ɘW/pX,O|ϯwEj]n0+VPOkYal-~_f;hl@(&8&bd c)=Ea0%<]-Z ˖-tR+3l0p DmM p P#NJB*>b#vaem@An*Qf P*@@ c*@% Fϟcǎ3`+`޵g?Q, {=&65_P suUð [_<W6t] ł~g͚G?CKm1à'°)v}'gφJ`B}_}Ua΁j C{$LXAuDD0!`B lQ*@BN:kE&*@4p;0b|\KA}ܡt3 T `K`s3fA=fo|+_}pP0yuY6cƌZ~U95ZcV{^?=K,mV>APn7Npn2e &M( 2bLȑ#aCghiС؈AF0%?VDilڴ%\bUmI럴bA4^Y`B\T P*@"@tP; 8Fb pS`hP0 F61PZ {9Xi8paB(uY(>͗/Tjdgz[ȧ2mC^cP`ðCH^%r H~ѣG~b,Vոq`!D6d B15\.&劊{]éT DG`6m c P(7n `$ 0' &L kw^|DDlFȀlȌCp G!(J)J`˹s~ x[ eduY x͛7ޡpib+q@s\/T P*""$MvVj>E=nJ"le⃚cX"E8DiUMinq3f6:% >V0DZ65 s9kT Pp)5Dc&[ r]V:''|6*bUɚfЕ4u DT P*L 3R"YAdZ9mچxR(NYExKԄb1VH"|Ylg3AQ#T P*@))bIaIxmrV$ yRS|qK|}df4RNh}REdQ&ڜZfԞCF%wp*fT P*@4ۘP7 ".w_1¾+[OTS,[/+ӸŬD fO!YNdkzf`VxYf=K)el5|Ў2N P*@+)<{&*@pSxnaP}6&]s%-\ X۫R0bV%5h5+{ԪNAi9E ]V@B&U3txKg79psP*@) Dz8pf&*@n5##-O P*@@ D-.~ 1Q*p;q > % ) |~exT P*@))4vy PLT P*@N AT} gT P*@p gT 2 x5m@N< P*@+@ -BT a bR&*@T Pg D++sTBPZ˘T P*@*@$P*BsT P*@*@$P*Vl+P*@T 8S(H T(HT P*@@j`vlkݤx54קTZP::GQ*@T @(8i8  HK KD2emk Tm DS`~+ P*@W <5./oٲeǎ;t)k֬yy>+rqYzfOd<$\*3還7a kX})T(HT P*@* ^tեKoJ:w\Nj켛rPxZI?ф=vתn<502:)Hۛ4m׺)36-;ʐ\qxpD% , Eij:_~|-Q*@0 kժ}vUV?ο?jfT (xJI2 .ψzO \]Az 8%PP#8$ep`*P0%`8bNP$"*  T oTj|7*4h`-򬟙Vo7v,떳vɥ\p}__XAuliƍ~_ـ'coQt|FIU?ee~RQPN'F@O15ld/UC  ϳT PM ( EIeѝKFp=bSY,(i:Ѽ+^Li4nIlڒg풵e#V&6uE_w3g|7&ֱΞp6xNjǕ߿.O??qB'(M K:UP"e*(Gl_s+(B *(_xWAmҽnޠo!^A[̪mw8P]h&:%ʪ^O2+mVyOKՇF.O4g!T l HIܹGAy; *lIB wbU8 dFuCA?W{m/YUU;|ѣG;V=` :t߳g~3݃PwJ]G?]P'abIg`F&RiiiڵP9(asb; zڄbx/da 3T;;jL-PͩkMIkRlE82Y;d ?Ri,ǑXuTKZoyZmJS,YN?4949S,bߦ(gj2ɐ}c^T JзJ 0WbVzW)X}2ϖ4&PP噿sT=n4Ln|RΝ1(R׮] >sL.ڢE D&X?S|׭[F4U뮫S剂$*@{?Ƅi{ѩټy=H&QbwwRObDI~~⍽P IWCk+!L"ƾ/$(ċS5ɥq$d/Z];5+J IK`hOBl&z*h!Q[AIfVU7G袥$ס)`<7+h`T Ut(4Gk<<j# &L4&s1{ '\qIԎD<8sЍW6T\F ܬ%YfﰞC(tܦ%icLE3UB-oZyPІiBקTU_}$osO>LLk& sTҊ%섚!HˠǷ ƳI s(eG%pFZށ+&_ ދU3 Gآ}n*M)VKh4虴+J5imܢMYLP0 w{T nv TTY19N?V0QSJH[(h2Iմ1RG?O3fÆ Y$|'n)# >uoC<:nٲ+gϮg<*LNTNy P;VAO0aѢE@9 ߷tK M+5JBt z` 0Q0DXэ8I&/e~Ě:Ǥ/)VA4VASFK,,PPV#縷jҒ)qWI`pJ& Zt%;#)S*S?JW3>O\A4~:e< -I>SH*& L&y!xE1;v@f;L>H]OsT*/"AAgDE1L%|D۴i3e (:0}Uީx80U0aRK1I~p]%d–>a'6'^ڠGUP629X.uL]r T+%퐉TzE:SڬU*a|crTV_(}|ϗ P*pŏw߅nʕ+VXnHظ~zX{9dXk ֳNTZ_(8 P(`AaⓉ$M6Mp؜kQV4E`5al]:S0~l3yUΜ=,[lҥKPȆeZRyZiYS Ud}YbXn9 }֬Y3}Vs6#bc˙(ʇ{dS~?B`0H@B8bիW_pA,۟~t{w{Dp_ྐR Q*10 .IP ƛ勍S*@?0S?'D0xqq1v!raҥDAS>l_] U(HT ]?Lr]pˏ.~mȆ̴ ڤ(Ry 1 PSQt+p+D?`lT P*@@p 0EA;(߿>B$ R*@T | T ~}q7oJЀ5jO(eϞ=rd=m aT P*@ P9.T P 'MԪU+TDT P*@yT_sdСhA`LCJwjr}vA$S`?g[Di_DB0FZפ~_銝{] 9rpͫm3}|$JoJ=%jZ4R\~Ηշ>g\'Q(B%ʫѫ/ȳ6…P/Y)`0ovFv.p`Ϟ=US7p1ӧϫ;=iz05+uhH+-aXHM,Sۯ0ݺ<ZE}l`/շda _+N\|qfjGmǔ܋ER X>WS9W~AXߚU$YԻPT{0t7B+_`}Ƚd.XQ(ʗ[;Z\@Q.գNm'wdMeSaX6I{XfGI$N'(^P@^_7wyxF=ԋg2t4/qめ8–P/wgCl>*ͥ$1(+_*_+ѺGfS}.(|:䭷'/'(h-Au>w$!$5QP($ܠu)]/_ u((qu;4v ΗeWV;@h2 4fե <"d{ 4 0 8$WŅA SnPP% [)~O,X ¼د_ѠtaU o aPt2tD :۠C;3 f2>< ޿$ӡ0(AzkjϪo0(M4a7ŕ(KSmi0h(h1ݯm+ÙbUg iT{x.ϪUf cG4i棒+ hP13 f JO 󠃻2cCF p;T˿P۶m3e\2fc舕9sUin>-͍6MTtaW[] ʗtAOil/WiP~}e6h]1CGmHK%a[f>#& Z叭I`S՝DU$n*~ ۰neAK{aJSs,r|N\~4-L!R][ಷ8);P۟.5R{RRݕпoO% (Tnv^nwOF4@St&*@T P*@Y"T P*@T P*@T P*@T P*@T P*@T P*@T P*@T P*@T P*@T P*@T P*@T P*@@n4!JIENDB`fritzing-app-0.9.2b/help/images/tools1.png000066400000000000000000000505151250202676700204370ustar00rootroot00000000000000PNG  IHDR\sRGBgAMA a pHYsodPIDATx^ ՙZ+'Ifdf&fz-5MjVO'}ct'^ݝ(^"6J"x!<%\T$]v=OSuuvoUU?lԧ>GG|3gmb&BI-̣R EGT G5[n …  .8q }l{OِpJmzj{Ķ~6mڃ=w~{wԩSLǶɶ;Ӏڭ&vmPX즛nk7x 7c~dۄ \xm\s\?޶zܸqW6ֶ+ .l̘1߳ 5Զњ9*!qĉ%II#dIeY<#(*JIUѡ @hPa" J*P*nII3I(C mF 04*# O7i) 7 C ;ZPAS'|ꩧf&bri qhO<J&`B4  ,B< tP :BBN бcpp% ‡P4tѠЀ Ph.h5 PWAա*Hc<BJ4$KԎ `fҷϚ5g}ζb) Q%RRB%a4 W B Nw pPAl t 8PD0Bx@z> &DP\^!k@kA  0IEH턺 /.C./k8tsp`Μ9{ϟ5l+!1kor$!3 042p! >B`Ac!Cp;p ҝ!+xj hH5(4e5h2ʀ"82 2sAA>HJ@ . !^g QW 0m-ZxK/aSR``!BPAM\A !~ 2^P>>} B(AP80 鐺w: 2k@50\AРf2ȼL1Ѡc!B5(k[7mWՏ7`?" B"|$ rҝ_~yɒ%K]6 ; &@%h\5 !^5(L"%Ș>: B 8Pㅨ܁>XG@ŚBEpR&;sePsǘ)5ˠ#\Eb' PE # Dp\FT7.wlm#294 M /8 j Nw EQЛ )8aC4Ӑ^ gvܒS 1p!fJ\ޕP$zL3zCK?pO#|mۿ_?vl`( dp5d@{.`KI =Ͻ"aB7S0 Aw0 qԌ#rx!B>^qP}@O x _X6 5ټcAmsAAJBѠ*T߰0H.6w+qwS[zO/qa2 *(8 B Xi F?<4j6(VoY#@vX'4' '}1_(ev=~ƋQq 2`?" Bf,&\0؃G.=6a @=k%P weğl`Yj=RAټu@'lGCЈ KN'DP"xR_MQkAAw/ kggϟ؃80Yᥧoxԃ! ,^K5yB-3fU; aLoNhB&YŤ&e.Q7G 0`'bn.,Kcā΂`54 ф~WBbEb1e޳42M\@ ,_(/G! wHkVBxR8o!=h,g@!8\ GI. l|nD4Jg%0yh!?u*%LQM(:P]kDAp@V&ʳLQ+rǁ΂ජCq4OU ۖI=I Ƃh62Ys!1*qbJO1…¦{~+_ߡs ؏uߒD9QM L;1(7);g:~,EoR&NXu KfbnCi{})[xIMЗ'J+xb< sbBq0$`CAhH|Jh JN=&h=D>0 MJ [u7ϚAC>`?" BֽxI2ېaZ +GeZ(#eYV.&(n蜢A`ӍsxA=?B袃ЩDq jSc3'M '}AzZ>F2OXƠx)[3&=+e׶ v_7؏qP],!e!js#WZFc3V(Aqd6 ƨ `AZ}`xlA ~ .[3hCK OU& JJ e<BPˠ!5Sqcuwq?~E@z8R;+4`zDJ@ROBex8E=oȣOC$ `)&}`8)~ḄƃLyyFY܎Cp&2ͪ5Dy . PB>`<@tk ԣJD)w%==횡\?bߏG7>чbm~E4pYਞDo|QVSy*i7yAtrA5JjԠ8!.CԂǙn >\c^c; Ea]DFx ~2.CA5vG'7/й5HiXpfCz!q@)jA=pTosW7VBz2q(iw+Qس>BsӘ>_{Q(`wOkWČw,Z^6$!PS4^)oC %Y'J} q1NՉ1ۍ딣ĉЮ H43OX)KvY:h,| A\B_|cp(aQ P"eH3Őy(Gmc;lڮ:M([ v׶k[nb[f]{#6ifA~{M3#[Ͱ('0O|O~uA,k'IdF85m7+uc{{4*@:@t: C@*|7кEeΩHF%A͢R4  iTb*A  T,*H@*(`%&RTuHz=кu̜S ꒋ@+@(T.b`* ((ڿ T6B:Z ЂPS! B tBGW? O  lT С 8|`S=*@ShLܿV6"?xbv %9irri$=K|޶&Bʱx|.Fb#LNo!!=zK*Z.du@sLh)5TPh|tڸ骫SlG[%ԛli!֩wՁB.}H VE9pFm6# v kWpsRH1ÑIhT"Xc>Z/3P)ֈCñVAWcG0؂RGǯj1~YOlVtnsR ^d8NÊhWzђ-= B[cAC7}S@ܒ 2:U:[pUnv IDy r숩-xP(#KV v1d_kQS)*V_(\TÇQT 4YlHî58- Pl Wڹs{C>|_eGA޻w/:].P|N?bm),* q @ rP`%*P-(@( 4( ׯPP`*PBm8X36/Z|:cP*@A s_&X  ,Zk-By )WOOqر7tӄ  9BA L( FQxknVwv{ ΌBʐMRgqWL:'x.\ۋ9BA|s:Px=~ ¿]6OU ԄL z @az P@~r<?L4&AJPLw{e|MP[pm.T@[՜A% )PB<jPHWHCU^RwoN o6`;+P"0[CN'eAA \hM(TA*NR[SO=%\ CQBVXA~%٤d( =(.:P(ull5T`J8!P`ՁBc󿱱fT @A `P.>{|kP)iWeDK@G/ 2PAEʅ¬{]ՉRҞ[nD/,TY--(OضE zC1pÍrݻ?,T*.Vj5}_)ZPvW';o̘1GkPY2T\-(Odɒm+ zS5AKB-,(mժU>(o=y”Mn8z;N+n~89g!96pJNQCϷΚa b/@C§D6?*S%թgNٴԞ!\7tt8щNLΰvS:D^*W4IGT*.f_I{1z ݲ}¤Y~g^깵c[ԏBZL015$Є)Pkz֔>{3kהjv l C0;THv2@o\OG3k@F|DX;.7vXwb c!(j@ac3P̻dg=շaN;>h./[&N;֍MV{g*iYGSNSԶɺ~ šbv[eA8_R(wЉ V4h{Fm˂[`h[w&3j\ћ !Peɡl۰a VAG? W, o=Au[OYr!`p1B79[[:pw;qP{ж- ie3/?E HyGaAafBšb&_dNJ¶'BGw؁r7** U˷@5+S.n}^{īon4i%@ePq9R|R^m*BZqoǠfPL)u~Nټ*˷}%?w4>(Cw+Mu1RE9DK@G/SPK|P*ԠD( O4* ,7B'7J\Jzb7\+w`TtJ Tқ3 T dPɲRY nk(QϴLO>d MLOݠ36ǚ:^L!)L̈́$ (rJ>MwwM7݄BANヂ;f{`28:E+)qwرcz!|DSПr~p饗bڨQZ  x2w<`ﴆ(Fݽr(~&K@߰=x>(<B᪫7n}P9rŶ,\xS :.^fI{  &w&B^HxU;AL4^~W\q'!P1bDB;zϗmCs")h  pdtcXP+}P"\tEUp`(XfA43d 8@ ΂ BÇ,ܹń8OA ͔!@!1pa@š0yqhvδP@Q{r=  Æ kYOC:ZVVzzk|E@惂aСCY Pf*i4.."lYT 4_  p Ҡ1E*@)PȦ,Ϣ-ѣ &&,z -Z6W  P OZZ ,PpShjf@z0$AD ҫɐT С \07B4@R*#?>(͓&4Q*P: EA!q6Q\93)0 X^ǖ(<1s{rYs["$&Ĕb3hx (\p }@(XA^}mӆM[n{qP@s_o;kLhؓC彔!" z%'gH;VݸnM}on֎,]-1]Q+?wP *H^^Gɱ ydq P"Uk_u_;xU" /̿Z_BWn;:)Fv1޶uᗬ-#cK+pbH?;Ą"%kR䠀ޱ^) g{[mz/ض~뮺{QuVsˍ]vz}[ZDv9ՀuJХ1E2rV oiMR&QCd(, |s ??9?xQ^J6eq/iPt/Pdwj};Z;p&琉{!(L+>oZIȂ{isL P6<!/((ȭ=rh(\uMJ(.:UV@pPr}1oTp5Bp: _k!(PB@q5hE%yu3=VG 䦀 B+L T[шeKߵ)XFM@ Q*P}b0 X2=qRz 9T@ )@(AP* 2woC Pr0rR(@(T.*P a1q/:֊Qw"3g'Rh^|Xc.g M0q1HR9P?ؑQ;ﻏ=B/ AdUJ/lw"h]RS[SB@ %0@VP(ZaOZLB*٥E+@(0-bR VSSPh cv@  E+@)@(X1ThfT Z˜]*PB 3~*b  -Va.(ZBh?h10f PŒ BUKVPHPx/z3*fVtO?Ҏ{?\/0WY߶wtڢ PhDzTYBh?<*7#歝 EB(SxY2Care.L(T#SA!3E|6&_~ Ʀ}Ph^WdB 2sPP( z7i{+( _s з9 . ץ ;k .CdmSvQGEf" 4;?|:C ˥6$auNw V{\ ePNWld "ôBKy ` n|?q&b<t;Zݽ v~o@aT=2P /(\h(8ۆ~yA!< ^{NT1 U 3ԨA(m /M{ sN .V\K=|Pӊ`y?T#V)gp׿'S,y>hs A`Q7)B_Oz UvK(9WnBsa\)9mh(Xkt+lPB.D# V!s?1bNB-Yi2C!ȅFZ>)I.8hWՂ4F(`K(BU[6  9r/Hd=MP[> …vhL$R6QQ( 2PhbP[ \EC|. X *@( P*SQ( hJ @#N4M`A:\BOL *@ h)MU T |td,Tm ڦ*Y*B>:2*6  mS,GB! hJ BT% BQQ(M J>O{,>=S~zz΂$Z CA>/ztA"1ڜxn9sg6'vPD&3<򼜒Kf$O!Q.Z _W+7eih/^s|m?_>p vP kL",_܅-[:er1D˘).p[Zb Jy[rqWgOd0M8{W_W'_:ߏC_1]bnj?zJn-]jկl_NNΫiP)zkEoi 4n=zG}&^pf=0lK<8# QX82 e5zS e-RwA[dSfS~-[,xO-,YaK?AW!Hv:bM(x5V{}æ-[o1I8crV5ԨKIA!@x(7k}:Yڮ{@8m7jq8U5 jcRU >69%=kF;M>/bZ'uWok?}|&My  iMf͙j6nۺm׮ٳ{W׮OC 99Xriz^XbB~x>uA_{Q+e۸Hg$H)6Z7TzL9qSY_LgԵkn p烏:t( *]]&([[8@?}['NzגRtC)]" Om2uf H( B!@Wsw=++C!uoߺu //x_'.gMBFziܚmظIpرǏ9 SUQ.w L. J 2{=̝7ow?AW?XB(ɳG%jv쀏(9rd߾} i]M7pb.0BgHsOAAS1 Q#4pFg)?fFv{r\$}lQ@pG?n"c8?n>|d~jΌYoٶѣ $yTL'cNkBaރ%'  BAsR0Vr)Aqp>oJdVL)%\a ?/FiCٓ,h1' ұ]8gZo4 ?ß)-՗ Xr)nEXr˘iB2B*  ]=]B!wI!hm֮? BksOrWP]RFHZ[B돹+@(.)#@P趭7/=@\ۜZOB> BW1 HSPO/mUR Ӌ@+@(}T>bh*  m_, OB> BW1 HSPOCo۾cE|&T _Юк2XB!hyc=hT _Ю D@!ߦبRPȳ6-.B}8u<"Pȳ6-.B]8 /Ӓ>X{R2F(%s@A$r}0KhD}NzKhڽgkݽT@Wcbqt' B5Fz8n?#)Z`(;/?[nw8z . R!} (8ވ( 7qp $]7;SPiM--5 V{\ @W|ra; u]:SaoABeE6i5w` {?! L$0D(APPH\};3+۽)83 qCp`tLgAC(5ܸ KH>w1 :8= *>i PȆhT?Ps NX2j?"pom)I7h rPKV:mZ9OݷmaQF0dȐ_,}6}WOR5S2֎ej!rp9|7jYj*( ( {p?`s7wu9_׾--)_MsEجUiSs8"#72ڲ̈́$°aÄ yA5~Z7ݯG:nhmC . 8D"6*BI^uJhO!X@MV q@\ L( ߏVƆv1w= gqmn&HR@PY(S(L g) ( m *S( #GgP(.W¡ \ e) ( BYt@  QFBTD pBṳ@]  K.P u S !~Pb3i*PB]r10hr8 >Oa,ShB\0 \ ڥuRh,SV PL TQBoeB/h,͞MT;m\m6Z׷Oߣ*` 4ǟĿPAS 4 9wܠqs )1( o>1ʠqmSH|JΏEXi(}q+pM͹ZmdwA؞ljJrWtVT\eJ~|)T 6{,ڙw[]?񯜥m}uu$&?4^Vzj5)DVDt@2:WH̚3OnBkNCːC ǎ[_!xOU9o*guVP(+ҴrWA*guF(Xw=b Б Ӗq @?<kfP(mف(PiμRm `k|H~j69[ ? CfA=@Ϟ'5krB,g5Ȕ}yVՇ_!0:s;:YZ(g{.5BG5 Uڬܿ k$a(dHGLC]oB 1קv9=f<n*|E-2v.q R .gS o EY  VGZmZG٫]~5Y `گF]y\i-P((ҫH#FP&.1btr `hAS,O!/-ILP뵢REAAjZ O=*CA t?_5A&B}!"pE \( 3(Ȟ$4o?hzgih=EaBZ(JBTq=+juf}ԀN\pO!CA pT(HMD}ء %uޘhTk%i{G9GS YUoG)duiPpE%;&AO_QMYI>b%BN3Zcܬ7his7u',u^ݒo7 +K,PhwGEBL3NDRƞB\ *{K.* i<(mB$:P[5%Ol7 ;tW=;I4M(KgQ;5'*!Yw.\(SHI/u ja:1rٙP&BW4j{>cpO \פ%{HHx#("'j@P6l8 )GR:]XhBAB]>*9N CPq(̛`C!oE4,r2eCAPq(eղPT BaȐ!BYT, pBYt@  nB*ax*P̀@OjfT CAB!}0$(Wbp 0BjfT CA@(* ( Bԩ@zZ1$f WX(\p;p> @P.pNf@JpPHY FJWX( Pz53T Bz t-|:eö;NXH*PhnQYGzN>d]pJ~j[>5>Ą Q*P1D@7$C4*@ U MJ8X'T =rgTr  f PL TNBrU QrHY S(W N@]r,Q+W+'YqE#BW1r*и8'4*@*@/<H%O!1=T P7'd>T PgPH@;+`@AHOe ((+P̈́ \Y=m ,9oI:T@(aPV@y Æ .  Xx*@( P*S@Aa,<YϤ^zF@(PlL(uGTCF(_,iQ*Q …p(@Ե!^1ހa><pHbFQvITd T(L]1Q*p I1I&cL̼ԦZz2_}_T󈪉B2AJߺr9հ T \) EsN&Xu.(L(d[z(\0I4ܜo\pA]TK̥DRP珊6 #DqAH㝆Т,(.΂ 2,:ۘ rA9B 1΂%KtT T˗[>|ӟhT P( o#ˢIENDB`fritzing-app-0.9.2b/help/parts_editor_help.html000066400000000000000000000411161250202676700216350ustar00rootroot00000000000000 Parts Editor Help


We have decided to release the new Parts Editor in two phases. The first phase, included in release 0.7.9, is already easier to use  and more powerful than the old Parts Editor, but you still have to do a lot of preliminary work using an SVG editor like Inkscape, Illustrator, or CorelDRAW. In the next phase we hope to eliminate much of the need to use these programs.

How to start

The new approach is very different from that of the old Parts Editor, and explaining that difference is the purpose of this document. The first big change is that you cannot create a new part from scratch--you must begin with a part that already exists. So the best thing to do is to find a part that is pretty close to what you eventually want. If your part is really different from anything else, then just to try to match the number of connectors. For example, if your part needs 39 pins, then start with a generic IC part, change it to a SIP (single inline package) and give it 39 pins. Though finding a part to begin with may seem like a burden, it will save you effort as you go through the process.

You can open the new parts editor by right-clicking a part in a sketch and choosing the 'Edit' option; choosing 'Edit' from the Part menu; right clicking a part in the Parts Bin and choosing the 'Edit' option; or using the Parts Bin drop down menu.

Six views

The new Parts Editor no longer tries to display everything in a single view.  Instead, it works like the sketch window which has multiple tabs with only one tab visible at a time.  In the new Parts Editor there are six tabs: Breadboard view, Schematic view, PCB view, Icon view, Metadata view, and Connectors view. As you might expect, the first four views are for the part images; the Metadata view is where you enter the part's title, author, and other properties; and the Connectors view is for editing connector metadata, and for adding or removing connectors. For the latter, you just type in the number of connectors you want.

Loading new images


To load the SVGs for your part, switch to the appropriate view, and use File > Load image for view. As before, you can load SVGs in all views and gEDA .fp files and KICAD .mod files in PCB view only. To create an SVG for any view, you must use an external SVG editor (Inkscape, Illustrator, CorelDRAW, or a text editor) to layout the elements that will be used as connectors. The SVG example below uses <circle> elements for connectors.

Loading PNG or JPG images directly is possible, but since these become SVG images with only a single element, there is no way to place individual connectors. We also  discourage the use of PNG and JPG because these are raster-based rather than vector-based, so they don't look good when scaled. If you still prefer to use PNG or JPG, we recommend that for now you open them in an external SVG editor and add connector elements there (see below for more about 'connector elements'). Save the result as an SVG, and use that in the Parts Editor.  In phase 2 you will be able to add connector elements directly in the Parts Editor.

Since you have already begun with a part, it may be that you will only have to load a single image for a particular view--you do not have to replace all the images in the original part.

It is still necessary to prepare SVGs for PCB view by grouping elements in layers: copper0, silkscreen, copper1, etc. (Layering will be handled in the phase 2 parts editor.) The best way to understand the layers is to open up one of the core pcb svg files, For example have a look at the file crystal_hc49U.svg. Silkscreen layer has four while lines, the two copper layers share a pair of circles as connector elements.

<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="tiny" height="0.20306in" version="1.2" viewBox="0 0 46684 20306" width="0.46684in" xmlns="http://www.w3.org/2000/svg">

<desc>Fritzing footprint SVG</desc>
<g id="silkscreen">
<line stroke="white" stroke-width="1000" x1="1000" x2="45684" y1="1000" y2="1000"/>
<line stroke="white" stroke-width="1000" x1="45684" x2="45684" y1="1000" y2="19306"/>
<line stroke="white" stroke-width="1000" x1="45684" x2="1000" y1="19306" y2="19306"/>
<line stroke="white" stroke-width="1000" x1="1000" x2="1000" y1="19306" y2="1000"/>
</g>
<g id="copper1"><g id="copper0">
<circle cx="13736" cy="10153" fill="none" id="connector0pin" r="2750" stroke="rgb(255, 191, 0)" stroke-width="2000"/>
<circle cx="32948" cy="10153" fill="none" id="connector1pin" r="2750" stroke="rgb(255, 191, 0)" stroke-width="2000"/>
</g></g>
</svg>

Sometimes you will want to reuse the breadboard image as your icon image. There is a shortcut for this under File > Reuse breadboard image. You can also find the options: File > Reuse schematic image, and File > Reuse PCB image.

For certain parts--like a breadboard--there is only one view image. For technical reasons, you have to tell the Parts Editor this is what you want.  Use View > Make only this view visible from the current view (one of Breadboard, Schematic, or PCB) to make the part invisible in the other two views.

Undo, save, show in folder

The next big difference from the old Parts Editor is that undo is always available, even after loading view images. Furthermore, you can save your changes at any point and keep working--the new Parts Editor is less like a dialog and more like a full document window.

If you start with a core part (i.e. a part from the Fritzing distro), saving from the Parts Editor is disabled. You must use Save as new part, because you cannot change a core part. Save as new part creates a new part in your local storage area (explained below) and this part is added to the "My Parts" Bin--it is a copy of the original part (plus whatever changes you have already made so far using the Parts Editor). If you are editing a custom part that was in a sketch, the part will be updated whenever you save. If you want the new part to display in the My Parts Bin the next time you run Fritzing, remember to save the bin (use the drop down menu at the upper left of the bin). If you start editing from a part in the My Parts Bin you have a choice between Save (which will overwrite the part), and Save As New Part (which will create a new part and add it to the My Parts Bin). If you copy a part into My Parts Bin from some other bin, then probably Save will be disabled.

On Windows the local storage folder is something like C:\Users\[username]\AppData\Roaming\Fritzing\parts\user\, and SVGs are stored in C:\Users\[username]\AppData\Roaming\Fritzing\parts\svg\user\. On Linux and Mac this would be ~/.config/Fritzing/parts/user/ and ~/.config/Fritzing/parts/svg/user/.

To find the SVG image for the current view on the desktop, choose File > Show in Folder. On Mac and Windows this will open a folder on your desktop with the SVG file selected. Under Linux you get the folder but no file selection (if anyone has advice about how to get selection to work, we would be grateful).

Associating a connector with its SVG counterpart


The next task will be to associate each connector with its counterpart in the SVG for each view. This is handled very differently from before. For an example, I am going to use images from a part created by Shunichi Yamamoto (who graciously gave us permission to include them in this tutorial, and who also helped beta test the new Parts Editor). 

The new part will have 39 pins, so we begin with a Generic IC part and drag it into an empty sketch. There we use the Inspector to change it a to SIP and give it 39 pins. Then we open that in the new Parts Editor with a right-click. 

starting up

Next we load the new breadboard image using File > Load image for view.  In the Tools widget at the upper right, you see a list of connectors. Choose one to make it the current or active connector. If it has already been associated with an SVG element, that element will display a marquee highlight. Since we are just starting out, we will choose pin1 which is not currently associated with any SVG element.

pin1

To create the actual association click the "Select graphic" button over in the Connectors widget. This basically puts you in a "mode" that lasts until the next time you mouse down. If you want to escape the mode, click anywhere outside the part or use the escape key. You can only make the association when you are in this mode (this keeps you from accidentally associating a connector to a graphic when you didn't intend to).

In the mode, move your mouse over the SVG. As you do so, different SVG elements will highlight. It is often the case that any given mouse location can refer to multiple SVG elements (or groups of elements). Use the shift-key plus the mouse wheel to highlight other elements above or beneath the currently highlighted one (in the z-order)--the mouse wheel without the shift key will pan or zoom as usual (depending on your preferences setting for wheel events). If you are already on the bottom layer then the next wheel "downward" will make the element flash white; a similar white flash will occur if you are already at the top layer and wheel "upward". In other words, the flash signifies you can't move any further in the z-order in that direction.

Here are three highlights from the same mouse position, using the mouse wheel + shift:

highlight1
highlight2
highlight3

The first highlight is the one we want so we mouse down when the wheel gets us back to that small rectangle. Now the element has a marquee to show that it is the current pin, and you also see the terminal point as a crosshair which defaults to the center. The terminal point is the place where a wire attaches to the connector.

assoc1

After associating pin2 and pin3 we have:

pin3

Adjusting terminal points

In PCB and Breadboard view the terminal point is usually the center of the connector so you don't have to do any thing else.  But in schematic view the terminal point is usually near the end of the connector. So let's go to schematic view.  We start with the original SVG image. Note how the connectors are already showing their anchor points. Pin3 is the current connector.

schematic

Now we load the new schematic image and start associating pins.

schematic2

Here is what the Connectors widget looks like with pin3 as the current connector:

tools1

Notice that since we have selected graphics for three of the connectors, those connectors are checked in the connector list.

You can use the buttons or spinners to adjust the terminal point. Here is a close up after hitting the W button, and clicking the X spinner twice (look at the pin marked 'AN2'):

schematic3

You can also drag the terminal point directly by mousing down on it when its SVG element is highlighted.

Setting internal connections


An internal connection is when a two or more connectors in a part are already connected, for example the GND connectors on the Arduino UNO. You can specify and edit internal connections by clicking on the "Set internal connections" checkbox in the Connectors widget--it's beneath the connectors list (you can see it in the image of the Connectors widget, above). Since we are talking about the Arduino UNO, here is what it looks like when Set internal connections is checked:

bus1

The green lines represent the internal connections. To remove an internal connection, right-click the line and choose "Remove internal connection". To add a new connection, just drag a line out from one connector to another.

Known limitations

The following feature are due in phase two:
  • adding holes
  • mixing THT and SMD connectors--for now you must start with an SMD part to create a new SMD part, and start with a through-hole part to create a new through-hole part.
  • control over SVG element layering
  • direct manipulation of SVG elements
  • setting up parts with bendable legs.

Bye for now

That's pretty much the phase one story. We hope you like what you've seen. Stay tuned for phase two.


fritzing-app-0.9.2b/parts/000077500000000000000000000000001250202676700154365ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/000077500000000000000000000000001250202676700150525ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/contrib/000077500000000000000000000000001250202676700165125ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/contrib/placeholder.txt000066400000000000000000000000001250202676700215230ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/core/000077500000000000000000000000001250202676700160025ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/core/placeholder.txt000066400000000000000000000000001250202676700210130ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/obsolete/000077500000000000000000000000001250202676700166665ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/obsolete/placeholder.txt000066400000000000000000000000001250202676700216770ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/user/000077500000000000000000000000001250202676700160305ustar00rootroot00000000000000fritzing-app-0.9.2b/pdb/user/placeholder.txt000066400000000000000000000000001250202676700210410ustar00rootroot00000000000000fritzing-app-0.9.2b/phoenix.pro000066400000000000000000000136771250202676700165170ustar00rootroot00000000000000# /******************************************************************* # # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Fritzing 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 Fritzing. If not, see . # # ******************************************************************** # # $Revision: 6960 $: # $Author: irascibl@gmail.com $: # $Date: 2013-04-10 12:15:14 +0200 (Mi, 10. Apr 2013) $ # #********************************************************************/ # Fritzing requires two Qt-provided plugins in order to run correctly, # however the QTPLUGIN syntax only seems to work if Qt is built statically, # so QTPLUGIN is included here only for information purposes: # # QTPLUGIN += qjpeg qsqlite CONFIG += debug_and_release win32 { # release build using msvc 2010 needs to use Multi-threaded (/MT) for the code generation/runtime library option # release build using msvc 2010 needs to add msvcrt.lib;%(IgnoreSpecificDefaultLibraries) to the linker/no default libraries option CONFIG -= embed_manifest_exe INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib DEFINES += _CRT_SECURE_NO_DEPRECATE DEFINES += _WINDOWS RELEASE_SCRIPT = $$(RELEASE_SCRIPT) # environment variable set from release script message("target arch: $${QMAKE_TARGET.arch}") contains(QMAKE_TARGET.arch, x86_64) { RELDIR = ../release64 DEBDIR = ../debug64 DEFINES += WIN64 } !contains(QMAKE_TARGET.arch, x86_64) { RELDIR = ../release32 DEBDIR = ../debug32 } Release:DESTDIR = $${RELDIR} Release:OBJECTS_DIR = $${RELDIR} Release:MOC_DIR = $${RELDIR} Release:RCC_DIR = $${RELDIR} Release:UI_DIR = $${RELDIR} Debug:DESTDIR = $${DEBDIR} Debug:OBJECTS_DIR = $${DEBDIR} Debug:MOC_DIR = $${DEBDIR} Debug:RCC_DIR = $${DEBDIR} Debug:UI_DIR = $${DEBDIR} } macx { RELDIR = ../release64 DEBDIR = ../debug64 Release:DESTDIR = $${RELDIR} Release:OBJECTS_DIR = $${RELDIR} Release:MOC_DIR = $${RELDIR} Release:RCC_DIR = $${RELDIR} Release:UI_DIR = $${RELDIR} Debug:DESTDIR = $${DEBDIR} Debug:OBJECTS_DIR = $${DEBDIR} Debug:MOC_DIR = $${DEBDIR} Debug:RCC_DIR = $${DEBDIR} Debug:UI_DIR = $${DEBDIR} CONFIG += x86_64 # x86 ppc QMAKE_INFO_PLIST = FritzingInfo.plist #DEFINES += QT_NO_DEBUG # uncomment this for xcode LIBS += -lz LIBS += /usr/lib/libz.dylib LIBS += /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation LIBS += /System/Library/Frameworks/Carbon.framework/Carbon LIBS += /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit } unix { !macx { # unix is defined on mac HARDWARE_PLATFORM = $$system(uname -m) contains( HARDWARE_PLATFORM, x86_64 ) { DEFINES += LINUX_64 } else { DEFINES += LINUX_32 } LIBS += -lz } isEmpty(PREFIX) { PREFIX = /usr } BINDIR = $$PREFIX/bin DATADIR = $$PREFIX/share PKGDATADIR = $$DATADIR/fritzing DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\" target.path =$$BINDIR desktop.path = $$DATADIR/applications desktop.files += fritzing.desktop manpage.path = $$DATADIR/man/man1 manpage.files += Fritzing.1 icon.path = $$DATADIR/icons icon.extra = install -D -m 0644 $$PWD/resources/images/fritzing_icon.png $(INSTALL_ROOT)$$DATADIR/icons/fritzing.png parts.path = $$PKGDATADIR parts.files += parts pdb.path = $$PKGDATADIR pdb.files += pdb help.path = $$PKGDATADIR help.files += help sketches.path = $$PKGDATADIR sketches.files += sketches bins.path = $$PKGDATADIR bins.files += bins translations.path = $$PKGDATADIR/translations translations.extra = find $$PWD/translations -name "*.qm" -size +128c -exec cp -pr {} $(INSTALL_ROOT)$$PKGDATADIR/translations \\; syntax.path = $$PKGDATADIR/translations/syntax syntax.files += translations/syntax/*.xml INSTALLS += target desktop manpage icon parts sketches bins translations syntax pdb help } ICON = resources/images/fritzing_icon.icns QT += core gui svg xml network sql # opengl greaterThan(QT_MAJOR_VERSION, 4) { QT += widgets printsupport concurrent serialport } else { include($$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf) } RC_FILE = fritzing.rc RESOURCES += phoenixresources.qrc include(pri/kitchensink.pri) include(pri/mainwindow.pri) include(pri/partsbinpalette.pri) include(pri/partseditor.pri) include(pri/referencemodel.pri) include(pri/svg.pri) include(pri/help.pri) include(pri/version.pri) include(pri/eagle.pri) include(pri/utils.pri) include(pri/dock.pri) include(pri/items.pri) include(pri/autoroute.pri) include(pri/dialogs.pri) include(pri/connectors.pri) include(pri/infoview.pri) include(pri/model.pri) include(pri/sketch.pri) include(pri/translations.pri) include(pri/program.pri) include(pri/qtsysteminfo.pri) !contains(DEFINES, QUAZIP_INSTALLED) { include(pri/quazip.pri) } contains(DEFINES, QUAZIP_INSTALLED) { INCLUDEPATH += /usr/include/quazip /usr/include/minizip LIBS += -lquazip -lminizip } TARGET = Fritzing TEMPLATE = app fritzing-app-0.9.2b/phoenixresources.qrc000066400000000000000000000606611250202676700204320ustar00rootroot00000000000000 resources/zoomfactors.txt resources/ratsnestcolors.xml resources/properties.xml resources/vias.xml resources/images/splash/fhp_logo_small.png resources/images/splash/splash_progressbar.png resources/images/splash/fab_logo_bar.png resources/images/splash/fab_slice1.png resources/images/splash/fab_slice2.png resources/images/splash/fab_slice3.png resources/images/splash/fab_slice4.png resources/images/splash/fab_slice5.png resources/images/splash/fab_slice6.png resources/images/splash/splash_screen_start.png resources/images/splash/april1st.png resources/images/splash/splash.xml resources/images/AboutBoxLogoShield.png resources/images/aboutbox_CC.png resources/images/aboutbox_FHP.png resources/images/aboutbox_scrollfade.png resources/images/watermark_fritzing_outline.svg resources/images/welcome_kit.png resources/images/pcbs_2013.png resources/images/dot.png resources/images/fritzing_icon.png resources/images/fritzing_logo_background.png resources/images/breadboard_icon.png resources/images/schematic_icon.png resources/images/pcb_icon.png resources/images/icon_icon.png resources/images/remove_prop_enter.png resources/images/remove_prop_leave.png resources/images/helpImageBreadboard.png resources/images/helpImageSchematic.png resources/images/helpImagePCB.png resources/images/splitterHandle.png resources/images/part_lock.svg resources/images/part_sticky.svg resources/images/cursor/spot_face_cutter.bmp resources/images/cursor/spot_face_cutter_mask.bmp resources/images/cursor/curve.bmp resources/images/cursor/curve_mask.bmp resources/images/cursor/bendpoint.bmp resources/images/cursor/bendpoint_mask.bmp resources/images/cursor/bendleg.bmp resources/images/cursor/bendleg_mask.bmp resources/images/cursor/new_bendpoint.bmp resources/images/cursor/new_bendpoint_mask.bmp resources/images/cursor/magic_wand.bmp resources/images/cursor/magic_wand_mask.bmp resources/images/cursor/make_wire.bmp resources/images/cursor/make_wire_mask.bmp resources/images/cursor/part_move.bmp resources/images/cursor/part_move_mask.bmp resources/images/cursor/rubberband_move.bmp resources/images/cursor/rubberband_move_mask.bmp resources/images/cursor/rotate.bmp resources/images/cursor/rotate_mask.bmp resources/images/cursor/scale.bmp resources/images/cursor/scale_mask.bmp resources/images/icons/Toolbar_Icon_Order.png resources/images/icons/check.png resources/images/icons/nocheck.png resources/images/icons/TabWidgetCodeInactive_icon.png resources/images/icons/TabWidgetCodeActive_icon.png resources/images/icons/TabWidgetCodeHover_icon.png resources/images/icons/TabWidgetSchematicActive_icon.png resources/images/icons/TabWidgetSchematicInactive_icon.png resources/images/icons/TabWidgetSchematicHover_icon.png resources/images/icons/TabWidgetBreadboardActive_icon.png resources/images/icons/TabWidgetBreadboardInactive_icon.png resources/images/icons/TabWidgetBreadboardHover_icon.png resources/images/icons/TabWidgetWelcomeActive_icon.png resources/images/icons/TabWidgetWelcomeInactive_icon.png resources/images/icons/TabWidgetWelcomeHover_icon.png resources/images/icons/TabWidgetPcbActive_icon.png resources/images/icons/TabWidgetPcbInactive_icon.png resources/images/icons/TabWidgetPcbHover_icon.png resources/images/icons/toolbarExport_gbr_icon.png resources/images/icons/toolbarExport_gbx_icon.png resources/images/icons/toolbarExport_jpeg_icon.png resources/images/icons/toolbarExport_pdf_icon.png resources/images/icons/toolbarExport_png_icon.png resources/images/icons/toolbarExport_ps_icon.png resources/images/icons/toolbarOrderEnabled_icon.png resources/images/icons/toolbarOrderDisabled_icon.png resources/images/icons/toolbarOrderPressed_icon.png resources/images/icons/toolbarAutorouteEnabled_icon.png resources/images/icons/toolbarAutorouteDisabled_icon.png resources/images/icons/toolbarAutoroutePressed_icon.png resources/images/icons/toolbarActiveLayerEnabled_icon.png resources/images/icons/toolbarActiveLayerDisabled_icon.png resources/images/icons/toolbarActiveLayerPressed_icon.png resources/images/icons/toolbarActiveLayerBEnabled_icon.png resources/images/icons/toolbarActiveLayerBDisabled_icon.png resources/images/icons/toolbarActiveLayerBPressed_icon.png resources/images/icons/toolbarActiveLayerTEnabled_icon.png resources/images/icons/toolbarActiveLayerTDisabled_icon.png resources/images/icons/toolbarActiveLayerTPressed_icon.png resources/images/icons/toolbarViewFromBEnabled_icon.png resources/images/icons/toolbarViewFromBDisabled_icon.png resources/images/icons/toolbarViewFromBPressed_icon.png resources/images/icons/toolbarViewFromTEnabled_icon.png resources/images/icons/toolbarViewFromTDisabled_icon.png resources/images/icons/toolbarViewFromTPressed_icon.png resources/images/icons/toolbarDiyEnabled_icon.png resources/images/icons/toolbarDiyDisabled_icon.png resources/images/icons/toolbarDiyPressed_icon.png resources/images/icons/toolbarNotesEnabled_icon.png resources/images/icons/toolbarNotesDisabled_icon.png resources/images/icons/toolbarNotesPressed_icon.png resources/images/icons/toolbarRotateEnabled_icon.png resources/images/icons/toolbarRotateDisabled_icon.png resources/images/icons/toolbarRotatePressed_icon.png resources/images/icons/toolbarFlipEnabled_icon.png resources/images/icons/toolbarFlipDisabled_icon.png resources/images/icons/toolbarFlipPressed_icon.png resources/images/icons/toolbar_separator.png resources/images/icons/dockWidgetEmpty_icon.png resources/images/icons/dockWidgetCloseNormal_icon.png resources/images/icons/dockWidgetCloseHover_icon.png resources/images/icons/dockWidgetClosePressed_icon.png resources/images/icons/dockWidgetFloatNormal_icon.png resources/images/icons/dockWidgetFloatHover_icon.png resources/images/icons/dockWidgetFloatPressed_icon.png resources/images/icons/dockWidgetCollapseNormal_icon.png resources/images/icons/dockWidgetCollapseHover_icon.png resources/images/icons/dockWidgetCollapsePressed_icon.png resources/images/icons/noteResizeGrip.png resources/images/icons/combobox-arrow.png resources/images/icons/segmentedSwitcherXActiveDimmed.png resources/images/icons/segmentedSwitcherXActiveFocus.png resources/images/icons/segmentedSwitcherXActiveFocusHover.png resources/images/icons/segmentedSwitcherXInactiveDimmed.png resources/images/icons/segmentedSwitcherXInactiveFocus.png resources/images/icons/segmentedSwitcherXInactiveFocusHover.png resources/images/icons/WS-new-icon.png resources/images/icons/WS-open-icon.png resources/images/icons/WS-fzz-icon.png resources/images/icons/WS-blogLogo.png resources/images/icons/WS-galleryLogo.png resources/images/icons/WS-shopLogo.png resources/images/icons/WS-fabLogo.png resources/images/icons/arrowButtonUp.png resources/images/icons/arrowButtonDown.png resources/images/icons/arrowButtonLeft.png resources/images/icons/arrowButtonRight.png resources/images/icons/toolbarShareBG_icon.png resources/images/icons/toolbarSharePressed_icon.png resources/images/icons/toolbarShareDisabled_icon.png resources/images/icons/toolbarShareEnabled_icon.png resources/images/icons/zoomSliderMinus.png resources/images/icons/zoomSliderMinusPressed.png resources/images/icons/zoomSliderPlus.png resources/images/icons/zoomSliderPlusPressed.png resources/images/icons/searchField.png resources/images/icons/noicon.png resources/images/icons/parts_plural_v3_plur.png resources/images/icons/parts_plural_v3_sing.png resources/images/icons/asterisk.png resources/images/icons/partsBinCombinedMenu_icon.png resources/images/icons/partsBinCombinedMenuPressed_icon.png resources/images/icons/partsBinCombinedMenuHover_icon.png resources/images/icons/noArrow_icon.png resources/images/icons/partsEditorZoomInVerButton.png resources/images/icons/partsEditorZoomOutVerButton.png resources/images/icons/partsEditorZoomInHorButton.png resources/images/icons/partsEditorZoomOutHorButton.png resources/images/icons/fabquote_button_hover.png resources/images/icons/fabquote_button_press.png resources/images/icons/fabquote_button_release.png resources/parts/core/wire.fzp resources/parts/core/cmRuler.fzp resources/parts/core/note.fzp resources/parts/core/rectangle_pcb.fzp resources/parts/core/rectangle_pcb_two_layers.fzp resources/parts/core/ellipse_pcb.fzp resources/parts/core/ellipse_pcb_two_layers.fzp resources/parts/core/roundrect_pcb.fzp resources/parts/core/roundrect_pcb_two_layers.fzp resources/parts/core/logotext.fzp resources/parts/core/logoimage.fzp resources/parts/core/silkscreen0logoimage.fzp resources/parts/core/breadboardlogoimage.fzp resources/parts/core/copper1logoimage.fzp resources/parts/core/copper0logoimage.fzp resources/parts/core/schematiclogoimage.fzp resources/parts/core/newlogoimage.fzp resources/parts/core/newsilkscreen0logoimage.fzp resources/parts/core/newbreadboardlogoimage.fzp resources/parts/core/newcopper1logoimage.fzp resources/parts/core/newcopper0logoimage.fzp resources/parts/core/newschematiclogoimage.fzp resources/parts/core/copper1logotext.fzp resources/parts/core/copper0logotext.fzp resources/parts/core/silkscreen0logotext.fzp resources/parts/core/schematiclogotext.fzp resources/parts/core/breadboardlogotext.fzp resources/parts/core/boardlogoimage.fzp resources/parts/core/boardlogoimage_one_layer.fzp resources/parts/core/ground.fzp resources/parts/core/netlabel.fzp resources/parts/core/netlabel_left.fzp resources/parts/core/via.fzp resources/parts/core/pad.fzp resources/parts/core/pad0.fzp resources/parts/core/blocker.fzp resources/parts/core/blocker0.fzp resources/parts/core/dcpower.fzp resources/parts/core/power.fzp resources/parts/core/power_label.fzp resources/parts/core/jumper.fzp resources/parts/core/groundplane.fzp resources/parts/core/hole.fzp resources/parts/core/30.20PerfboardModuleID.fzp resources/parts/core/30.20StripboardModuleID.fzp resources/parts/core/30.20Stripboard2ModuleID.fzp resources/parts/core/schematic_frame.fzp resources/parts/svg/core/icon/iconPerfboard.svg resources/parts/svg/core/icon/iconStripboard.svg resources/parts/svg/core/icon/wireicon.svg resources/parts/svg/core/icon/rulericon.svg resources/parts/svg/core/icon/rectangle_pcb.svg resources/parts/svg/core/icon/silkscreen_logo.svg resources/parts/svg/core/icon/silkscreen_text.svg resources/parts/svg/core/icon/copper0_text.svg resources/parts/svg/core/icon/copper0_logo.svg resources/parts/svg/core/icon/copper1_text.svg resources/parts/svg/core/icon/copper1_logo.svg resources/parts/svg/core/icon/schematic_text.svg resources/parts/svg/core/icon/schematic_logo.svg resources/parts/svg/core/icon/breadboard_text.svg resources/parts/svg/core/icon/breadboard_logo.svg resources/parts/svg/core/icon/jumpericon.svg resources/parts/svg/core/icon/hole.svg resources/parts/svg/core/icon/via.svg resources/parts/svg/core/icon/pad.svg resources/parts/svg/core/icon/blocker.svg resources/parts/svg/core/icon/schematic_frame_icon.svg resources/parts/svg/core/icon/groundplane.svg resources/parts/svg/core/icon/note.svg resources/parts/svg/core/breadboard/ruler.svg resources/parts/svg/core/breadboard/wire.svg resources/parts/svg/core/breadboard/30.20perfboard.svg resources/parts/svg/core/breadboard/breadboardlogo.svg resources/parts/svg/core/pcb/rectangle_pcb.svg resources/parts/svg/core/pcb/ellipse_pcb.svg resources/parts/svg/core/pcb/roundrect_pcb.svg resources/parts/svg/core/pcb/logo.svg resources/parts/svg/core/pcb/copper1logo.svg resources/parts/svg/core/pcb/jumper.svg resources/parts/svg/core/pcb/hole.svg resources/parts/svg/core/pcb/groundplane.svg resources/parts/svg/core/pcb/via.svg resources/parts/svg/core/pcb/pad.svg resources/parts/svg/core/pcb/pad0.svg resources/parts/svg/core/schematic/netlabel.svg resources/parts/svg/core/schematic/frame.svg resources/parts/svg/core/schematic/schematiclogo.svg resources/parts/svg/obsolete/schematic/0.3.schem.netlabel.svg resources/parts/svg/obsolete/schematic/0.3.schem.frame.svg resources/styles/fritzing.qss resources/styles/partseditor.qss resources/styles/newpartseditor.qss resources/styles/programwindow.qss resources/styles/linux-fritzing.qss resources/styles/linux-kde-oxygen-fritzing.qss resources/styles/linux-gnome-fritzing.qss resources/styles/win-fritzing.qss resources/styles/mac-fritzing.qss resources/styles/updatedialog.css resources/fonts/DroidSans.ttf resources/fonts/DroidSansMono.ttf resources/fonts/DroidSans-Bold.ttf resources/fonts/NOTICE resources/fonts/OCRA.ttf resources/bins/my_parts.fzb resources/bins/search.fzb resources/bins/temp.fzb resources/bins/order.xml resources/bins/pe.fzb resources/bins/icons/Arduino.png resources/bins/icons/Arduino-mono.png resources/bins/icons/Core.png resources/bins/icons/Core-mono.png resources/bins/icons/Custom1.png resources/bins/icons/Custom1-mono.png resources/bins/icons/Mine.png resources/bins/icons/Mine-mono.png resources/bins/icons/PICAXE.png resources/bins/icons/PICAXE-mono.png resources/bins/icons/Search.png resources/bins/icons/Lilypad.png resources/bins/icons/Lilypad-mono.png resources/bins/icons/Snootlab.png resources/bins/icons/Snootlab-mono.png resources/bins/icons/SparkFun.png resources/bins/icons/SparkFun-mono.png resources/bins/icons/Contrib.png resources/bins/icons/Contrib-mono.png resources/bins/icons/Parallax.png resources/bins/icons/Parallax-mono.png resources/bins/icons/Pololu.png resources/bins/icons/Pololu-mono.png resources/bins/icons/Temp.png resources/bins/icons/Temp-mono.png resources/templates/jumper_copper0LayerTemplate.txt resources/templates/jumper_jumperwiresLayerTemplate.txt resources/templates/bom.html resources/templates/bom_row.html resources/templates/perfboard_boardLayerTemplate.txt resources/templates/perfboard_connectorTemplate.txt resources/templates/perfboard_connectorFzpTemplate.txt resources/templates/perfboard_fzpTemplate.txt resources/templates/generic_sip_connectorFzpTemplate.txt resources/templates/generic_sip_fzpTemplate.txt resources/templates/generic_dip_fzpTemplate.txt resources/templates/mystery_part_sipFzpTemplate.txt resources/templates/mystery_part_dipFzpTemplate.txt resources/templates/generic_female_pin_header_fzpTemplate.txt resources/templates/screw_terminal_fzpTemplate.txt resources/templates/jumper_pcb_svg_template.txt resources/templates/jumper_pcb_svg_2nd_template.txt resources/templates/generic_female_pin_header_schem_template.txt resources/templates/generic_male_pin_header_schem_template.txt resources/templates/generic_female_10thin_pin_header_schem_template.txt resources/templates/generic_male_10thin_pin_header_schem_template.txt resources/templates/generic_female_10thin_double_pin_header_schem_template.txt resources/templates/generic_male_10thin_double_pin_header_schem_template.txt resources/templates/generic_female_pin_header_bread_template.txt resources/templates/generic_female_pin_header_bread_2nd_template.txt resources/templates/generic_rounded_female_pin_header_bread_template.txt resources/templates/generic_rounded_female_pin_header_bread_2nd_template.txt resources/templates/generic_male_pin_header_bread_template.txt resources/templates/generic_male_pin_header_bread_2nd_template.txt resources/templates/generic_sip_bread_template.txt resources/templates/schematic_frame_template.txt resources/templates/0.3.schem.schematic_frame_template.txt resources/templates/screw_terminal_bread_template.txt resources/templates/stripboards.xml resources/images/icons/zoomSlider.png resources/images/icons/zoomSliderHover.png resources/images/icons/checkhover.png resources/images/icons/checkactive.png resources/images/icons/smalToolarrow-inactive.png resources/images/icons/smalToolarrow-normal.png resources/images/icons/smalToolarrow-pressed.png resources/images/icons/spinArrowButtonUpNormal.png resources/images/icons/spinArrowButtonUpPressed.png resources/images/icons/spinArrowButtonDownNormal.png resources/images/icons/spinArrowButtonDownPressed.png resources/images/icons/TabScrollArrowButtonUpNormal.png resources/images/icons/TabScrollArrowButtonUpPressed.png resources/images/icons/TabScrollArrowButtonDownNormal.png resources/images/icons/TabScrollArrowButtonDownPressed.png resources/images/icons/TabScrollArrowButtonLeftNormal.png resources/images/icons/TabScrollArrowButtonLeftPressed.png resources/images/icons/TabScrollArrowButtonRightNormal.png resources/images/icons/TabScrollArrowButtonRightPressed.png resources/images/icons/toolbarNewCodeDisabled_icon.png resources/images/icons/toolbarNewCodeEnabled_icon.png resources/images/icons/toolbarNewCodePressed_icon.png resources/images/icons/toolbarMonitorCodeDisabled_icon.png resources/images/icons/toolbarMonitorCodeEnabled_icon.png resources/images/icons/toolbarMonitorCodePressed_icon.png resources/images/icons/toolbarOpenCodeDisabled_icon.png resources/images/icons/toolbarOpenCodeEnabled_icon.png resources/images/icons/toolbarOpenCodePressed_icon.png resources/images/icons/toolbarProgramCodeDisabled_icon.png resources/images/icons/toolbarProgramCodeEnabled_icon.png resources/images/icons/toolbarProgramCodePressed_icon.png resources/images/icons/toolbarSaveCodeDisabled_icon.png resources/images/icons/toolbarSaveCodeEnabled_icon.png resources/images/icons/toolbarSaveCodePressed_icon.png fritzing-app-0.9.2b/pri/000077500000000000000000000000001250202676700150775ustar00rootroot00000000000000fritzing-app-0.9.2b/pri/autoroute.pri000066400000000000000000000035171250202676700176500ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2948 $: # $Author: cohen@irascible.com $: # $Date: 2009-05-15 17:05:14 +0200 (Fri, 15 May 2009) $ # ********************************************************************/ HEADERS += \ src/autoroute/autorouter.h \ src/autoroute/cmrouter/cmrouter.h \ src/autoroute/autorouteprogressdialog.h \ src/autoroute/autoroutersettingsdialog.h \ src/autoroute/panelizer.h \ src/autoroute/cmrouter/tile.h \ src/autoroute/cmrouter/tileutils.h \ src/autoroute/mazerouter/mazerouter.h \ src/autoroute/zoomcontrols.h \ src/autoroute/drc.h \ SOURCES += \ src/autoroute/autorouter.cpp \ src/autoroute/cmrouter/cmrouter.cpp \ src/autoroute/autorouteprogressdialog.cpp \ src/autoroute/autoroutersettingsdialog.cpp \ src/autoroute/panelizer.cpp \ src/autoroute/cmrouter/tile.cpp \ src/autoroute/cmrouter/DBcell.cpp \ src/autoroute/cmrouter/search.cpp \ src/autoroute/cmrouter/search2.cpp \ src/autoroute/mazerouter/mazerouter.cpp \ src/autoroute/zoomcontrols.cpp \ src/autoroute/drc.cpp \ fritzing-app-0.9.2b/pri/connectors.pri000066400000000000000000000030711250202676700177710ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2948 $: # $Author: cohen@irascible.com $: # $Date: 2009-05-15 17:05:14 +0200 (Fri, 15 May 2009) $ # ********************************************************************/ HEADERS += \ src/connectors/bus.h \ src/connectors/busshared.h \ src/connectors/connector.h \ src/connectors/connectoritem.h \ src/connectors/nonconnectoritem.h \ src/connectors/connectorshared.h \ src/connectors/ercdata.h \ src/connectors/svgidlayer.h SOURCES += \ src/connectors/bus.cpp \ src/connectors/busshared.cpp \ src/connectors/connector.cpp \ src/connectors/connectoritem.cpp \ src/connectors/nonconnectoritem.cpp \ src/connectors/connectorshared.cpp \ src/connectors/ercdata.cpp \ src/connectors/svgidlayer.cpp fritzing-app-0.9.2b/pri/dialogs.pri000066400000000000000000000030231250202676700172330ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2740 $: # $Author: cohen@irascible.com $: # $Date: 2009-03-28 07:54:52 +0100 (Sat, 28 Mar 2009) $ # ********************************************************************/ HEADERS += src/dialogs/prefsdialog.h \ src/dialogs/pinlabeldialog.h \ src/dialogs/groundfillseeddialog.h \ src/dialogs/quotedialog.h \ src/dialogs/recoverydialog.h \ src/dialogs/setcolordialog.h \ src/dialogs/translatorlistmodel.h SOURCES += src/dialogs/prefsdialog.cpp \ src/dialogs/pinlabeldialog.cpp \ src/dialogs/groundfillseeddialog.cpp \ src/dialogs/quotedialog.cpp \ src/dialogs/recoverydialog.cpp \ src/dialogs/setcolordialog.cpp \ src/dialogs/translatorlistmodel.cpp fritzing-app-0.9.2b/pri/dock.pri000066400000000000000000000022001250202676700165250ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 6373 $: # $Author: cohen@irascible.com $: # $Date: 2012-09-06 08:39:51 +0200 (Do, 06. Sep 2012) $ # ********************************************************************/ HEADERS += \ src/dock/layerpalette.h \ SOURCES += \ src/dock/layerpalette.cpp \ fritzing-app-0.9.2b/pri/eagle.pri000066400000000000000000000021741250202676700166740ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 5721 $: # $Author: cohen@irascible.com $: # $Date: 2012-01-03 16:53:58 +0100 (Di, 03. Jan 2012) $ # ********************************************************************/ HEADERS += src/eagle/fritzing2eagle.h SOURCES += src/eagle/fritzing2eagle.cpp fritzing-app-0.9.2b/pri/help.pri000066400000000000000000000023711250202676700165460ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 5721 $: # $Author: cohen@irascible.com $: # $Date: 2012-01-03 16:53:58 +0100 (Di, 03. Jan 2012) $ # ********************************************************************/ HEADERS += src/help/aboutbox.h \ src/help/firsttimehelpdialog.h \ src/help/tipsandtricks.h SOURCES += src/help/aboutbox.cpp \ src/help/firsttimehelpdialog.cpp \ src/help/tipsandtricks.cpp fritzing-app-0.9.2b/pri/infoview.pri000066400000000000000000000021761250202676700174470ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2740 $: # $Author: cohen@irascible.com $: # $Date: 2009-03-28 07:54:52 +0100 (Sat, 28 Mar 2009) $ # ********************************************************************/ HEADERS += src/infoview/htmlinfoview.h SOURCES += src/infoview/htmlinfoview.cpp fritzing-app-0.9.2b/pri/items.pri000066400000000000000000000060631250202676700167410ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2846 $: # $Author: cohen@irascible.com $: # $Date: 2009-04-21 16:23:36 +0200 (Tue, 21 Apr 2009) $ # ********************************************************************/ HEADERS += \ src/items/breadboard.h \ src/items/capacitor.h \ src/items/clipablewire.h \ src/items/dip.h \ src/items/groundplane.h \ src/items/hole.h \ src/items/itembase.h \ src/items/jumperitem.h \ src/items/layerkinpaletteitem.h \ src/items/led.h \ src/items/logoitem.h \ src/items/moduleidnames.h \ src/items/mysterypart.h \ src/items/note.h \ src/items/pad.h \ src/items/paletteitem.h \ src/items/paletteitembase.h \ src/items/partfactory.h \ src/items/partlabel.h \ src/items/perfboard.h \ src/items/pinheader.h \ src/items/propertydef.h \ src/items/resistor.h \ src/items/resizableboard.h \ src/items/ruler.h \ src/items/schematicframe.h \ src/items/schematicsubpart.h \ src/items/screwterminal.h \ src/items/stripboard.h \ src/items/symbolpaletteitem.h \ src/items/tracewire.h \ src/items/via.h \ src/items/virtualwire.h \ src/items/wire.h \ SOURCES += \ src/items/breadboard.cpp \ src/items/capacitor.cpp \ src/items/clipablewire.cpp \ src/items/dip.cpp \ src/items/groundplane.cpp \ src/items/hole.cpp \ src/items/itembase.cpp \ src/items/jumperitem.cpp \ src/items/layerkinpaletteitem.cpp \ src/items/led.cpp \ src/items/logoitem.cpp \ src/items/moduleidnames.cpp \ src/items/mysterypart.cpp \ src/items/note.cpp \ src/items/pad.cpp \ src/items/paletteitem.cpp \ src/items/paletteitembase.cpp \ src/items/partfactory.cpp \ src/items/partlabel.cpp \ src/items/perfboard.cpp \ src/items/pinheader.cpp \ src/items/propertydef.cpp \ src/items/resistor.cpp \ src/items/resizableboard.cpp \ src/items/ruler.cpp \ src/items/schematicframe.cpp \ src/items/schematicsubpart.cpp \ src/items/screwterminal.cpp \ src/items/stripboard.cpp \ src/items/symbolpaletteitem.cpp \ src/items/tracewire.cpp \ src/items/via.cpp \ src/items/virtualwire.cpp \ src/items/wire.cpp \ fritzing-app-0.9.2b/pri/kitchensink.pri000066400000000000000000000034231250202676700201270ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 6409 $: # $Author: cohen@irascible.com $: # $Date: 2012-09-13 05:05:28 +0200 (Do, 13. Sep 2012) $ # ********************************************************************/ HEADERS += \ src/commands.h \ src/debugdialog.h \ src/fapplication.h \ src/fsplashscreen.h \ src/fsvgrenderer.h \ src/installedfonts.h \ src/itemdrag.h \ src/layerattributes.h \ src/processeventblocker.h \ src/routingstatus.h \ src/sketchtoolbutton.h \ src/viewgeometry.h \ src/viewlayer.h \ src/waitpushundostack.h SOURCES += \ src/commands.cpp \ src/debugdialog.cpp \ src/fapplication.cpp \ src/fsplashscreen.cpp \ src/fsvgrenderer.cpp \ src/itemdrag.cpp \ src/layerattributes.cpp \ src/main.cpp \ src/processeventblocker.cpp \ src/sketchtoolbutton.cpp \ src/viewgeometry.cpp \ src/viewlayer.cpp \ src/waitpushundostack.cpp fritzing-app-0.9.2b/pri/mainwindow.pri000066400000000000000000000027741250202676700200010ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 6370 $: # $Author: cohen@irascible.com $: # $Date: 2012-09-05 17:51:33 +0200 (Wed, 05 Sep 2012) $ # ********************************************************************/ HEADERS += \ src/mainwindow/fdockwidget.h \ src/mainwindow/fritzingwindow.h \ src/mainwindow/mainwindow.h \ src/mainwindow/sketchareawidget.h \ SOURCES += \ src/mainwindow/fdockwidget.cpp \ src/mainwindow/fritzingwindow.cpp \ src/mainwindow/mainwindow.cpp \ src/mainwindow/mainwindow_export.cpp \ src/mainwindow/mainwindow_menu.cpp \ src/mainwindow/mainwindow_dock.cpp \ src/mainwindow/sketchareawidget.cpp \ fritzing-app-0.9.2b/pri/model.pri000066400000000000000000000025751250202676700167240ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 3727 $: # $Author: cohen@irascible.com $: # $Date: 2009-11-14 12:36:34 +0100 (Sat, 14 Nov 2009) $ # ********************************************************************/ HEADERS += \ src/model/modelbase.h \ src/model/modelpart.h \ src/model/modelpartshared.h \ src/model/palettemodel.h \ src/model/sketchmodel.h SOURCES += \ src/model/modelbase.cpp \ src/model/modelpart.cpp \ src/model/modelpartshared.cpp \ src/model/palettemodel.cpp \ src/model/sketchmodel.cpp fritzing-app-0.9.2b/pri/partsbinpalette.pri000066400000000000000000000041461250202676700210210ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 PARTIC,asMainWindowULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with Fritzing. If not, see . # ******************************************************************** # $Revision: 6486 $: # $Author: irascibl@gmail.com $: # $Date: 2012-09-27 10:12:47 +0200 (Do, 27. Sep 2012) $ # ********************************************************************/ HEADERS += \ src/partsbinpalette/partsbinpalettewidget.h \ src/partsbinpalette/partsbinview.h \ src/partsbinpalette/partsbinlistview.h \ src/partsbinpalette/partsbiniconview.h \ src/partsbinpalette/graphicsflowlayout.h \ src/partsbinpalette/svgiconwidget.h \ src/partsbinpalette/partsbincommands.h \ src/partsbinpalette/searchlineedit.h \ src/partsbinpalette/binmanager/binmanager.h \ src/partsbinpalette/binmanager/stacktabbar.h \ src/partsbinpalette/binmanager/stacktabwidget.h SOURCES += \ src/partsbinpalette/partsbinpalettewidget.cpp \ src/partsbinpalette/partsbinview.cpp \ src/partsbinpalette/partsbinlistview.cpp \ src/partsbinpalette/partsbiniconview.cpp \ src/partsbinpalette/graphicsflowlayout.cpp \ src/partsbinpalette/svgiconwidget.cpp \ src/partsbinpalette/partsbincommands.cpp \ src/partsbinpalette/searchlineedit.cpp \ src/partsbinpalette/binmanager/binmanager.cpp \ src/partsbinpalette/binmanager/stacktabbar.cpp \ src/partsbinpalette/binmanager/stacktabwidget.cpp fritzing-app-0.9.2b/pri/partseditor.pri000066400000000000000000000100311250202676700201460ustar00rootroot00000000000000# /******************************************************************* # # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Fritzing 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 Fritzing. If not, see . # # ******************************************************************** # # $Revision: 6448 $: # $Author: cohen@irascible.com $: # $Date: 2012-09-17 23:36:33 +0200 (Mo, 17. Sep 2012) $ # #********************************************************************/ HEADERS += \ # src/partseditor/editabledatewidget.h \ # src/partseditor/abstractconnectorinfowidget.h \ # src/partseditor/mismatchingconnectorwidget.h \ # src/partseditor/partseditorconnectoritem.h \ # src/partseditor/singleconnectorinfowidget.h \ # src/partseditor/partconnectorswidget.h \ # src/partseditor/connectorsinfowidget.h \ # src/partseditor/editablelinewidget.h \ # src/partseditor/editabletextwidget.h \ # src/partseditor/abstracteditablelabelwidget.h \ # src/partseditor/partseditormainwindow.h \ # src/partseditor/editablelabel.h \ # src/partseditor/partspecificationswidget.h \ # src/partseditor/addremovelistwidget.h \ # src/partseditor/partseditorpaletteitem.h \ # src/partseditor/addremoveconnectorbutton.h \ # src/partseditor/connectorinforemovebutton.h \ # src/partseditor/partseditorconnectorspaletteitem.h \ # src/partseditor/partseditorconnectorsconnectoritem.h \ # src/partseditor/partseditorlayerkinpaletteitem.h \ # src/partseditor/partseditorconnectorslayerkinpaletteitem.h \ # src/partseditor/partseditorview.h \ # src/partseditor/partseditorviewswidget.h \ # src/partseditor/fixfontsdialog.h \ \ src/partseditor/pemainwindow.h \ src/partseditor/pemetadataview.h \ src/partseditor/pecommands.h \ src/partseditor/peconnectorsview.h \ src/partseditor/pesvgview.h \ src/partseditor/petoolview.h \ src/partseditor/peutils.h \ src/partseditor/pegraphicsitem.h \ src/partseditor/kicadmoduledialog.h \ src/partseditor/hashpopulatewidget.h \ src/partseditor/baseremovebutton.h \ SOURCES += \ # src/partseditor/editabledatewidget.cpp \ # src/partseditor/abstractconnectorinfowidget.cpp \ # src/partseditor/mismatchingconnectorwidget.cpp \ # src/partseditor/partseditorconnectoritem.cpp \ # src/partseditor/singleconnectorinfowidget.cpp \ # src/partseditor/partconnectorswidget.cpp \ # src/partseditor/connectorsinfowidget.cpp \ # src/partseditor/editablelinewidget.cpp \ # src/partseditor/editabletextwidget.cpp \ # src/partseditor/abstracteditablelabelwidget.cpp \ # src/partseditor/partseditormainwindow.cpp \ # src/partseditor/editablelabel.cpp \ # src/partseditor/partspecificationswidget.cpp \ # src/partseditor/addremovelistwidget.cpp \ # src/partseditor/partseditorpaletteitem.cpp \ # src/partseditor/partseditorconnectorspaletteitem.cpp \ # src/partseditor/partseditorconnectorsconnectoritem.cpp \ # src/partseditor/partseditorview.cpp \ # src/partseditor/partseditorviewswidget.cpp \ # src/partseditor/fixfontsdialog.cpp \ \ src/partseditor/pemainwindow.cpp \ src/partseditor/pemetadataview.cpp \ src/partseditor/pecommands.cpp \ src/partseditor/peconnectorsview.cpp \ src/partseditor/pesvgview.cpp \ src/partseditor/petoolview.cpp \ src/partseditor/peutils.cpp \ src/partseditor/pegraphicsitem.cpp \ src/partseditor/kicadmoduledialog.cpp \ src/partseditor/hashpopulatewidget.cpp \ fritzing-app-0.9.2b/pri/program.pri000066400000000000000000000037111250202676700172640ustar00rootroot00000000000000# /******************************************************************* # # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Fritzing 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 Fritzing. If not, see . # # ******************************************************************** # # $Revision: 3854 $: # $Author: cohen@irascible.com $: # $Date: 2009-12-10 17:42:28 +0100 (Thu, 10 Dec 2009) $ # #********************************************************************/ HEADERS += \ src/program/highlighter.h \ src/program/programtab.h \ src/program/programwindow.h \ src/program/syntaxer.h \ src/program/trienode.h \ src/program/console.h \ src/program/consolewindow.h \ src/program/consolesettings.h \ src/program/platform.h \ src/program/platformarduino.h \ src/program/platformpicaxe.h \ src/program/platformlaunchpad.h SOURCES += \ src/program/highlighter.cpp \ src/program/programtab.cpp \ src/program/programwindow.cpp \ src/program/syntaxer.cpp \ src/program/trienode.cpp \ src/program/console.cpp \ src/program/consolewindow.cpp \ src/program/consolesettings.cpp \ src/program/platform.cpp \ src/program/platformarduino.cpp \ src/program/platformpicaxe.cpp \ src/program/platformlaunchpad.cpp FORMS += \ src/program/consolewindow.ui \ src/program/consolesettings.ui fritzing-app-0.9.2b/pri/qtsysteminfo.pri000066400000000000000000000001401250202676700203530ustar00rootroot00000000000000SOURCES += src/lib/qtsysteminfo/QtSystemInfo.cpp HEADERS += src/lib/qtsysteminfo/QtSystemInfo.h fritzing-app-0.9.2b/pri/quazip.pri000066400000000000000000000027441250202676700171330ustar00rootroot00000000000000# /******************************************************************* # # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Fritzing 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 Fritzing. If not, see . # # ******************************************************************** # # $Revision: 5721 $: # $Author: cohen@irascible.com $: # $Date: 2012-01-03 16:53:58 +0100 (Di, 03. Jan 2012) $ # #********************************************************************/ HEADERS += \ src/lib/quazip/crypt.h \ src/lib/quazip/ioapi.h \ src/lib/quazip/quazip.h \ src/lib/quazip/quazipfile.h \ src/lib/quazip/quazipfileinfo.h \ src/lib/quazip/quazipnewinfo.h \ src/lib/quazip/unzip.h \ src/lib/quazip/zip.h SOURCES += \ src/lib/quazip/ioapi.c \ src/lib/quazip/quazip.cpp \ src/lib/quazip/quazipfile.cpp \ src/lib/quazip/quazipnewinfo.cpp \ src/lib/quazip/unzip.c \ src/lib/quazip/zip.c fritzing-app-0.9.2b/pri/referencemodel.pri000066400000000000000000000023371250202676700205770ustar00rootroot00000000000000# /******************************************************************* # # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Fritzing 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 Fritzing. If not, see . # # ******************************************************************** # # $Revision: 6309 $: # $Author: cohen@irascible.com $: # $Date: 2012-08-17 11:16:43 +0200 (Fr, 17. Aug 2012) $ # #********************************************************************/ HEADERS += \ src/referencemodel/sqlitereferencemodel.h \ src/referencemodel/referencemodel.h \ SOURCES += \ src/referencemodel/sqlitereferencemodel.cpp \ fritzing-app-0.9.2b/pri/sketch.pri000066400000000000000000000032431250202676700170760ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 3727 $: # $Author: cohen@irascible.com $: # $Date: 2009-11-14 12:36:34 +0100 (Sat, 14 Nov 2009) $ # ********************************************************************/ HEADERS += \ src/sketch/fgraphicsscene.h \ src/sketch/breadboardsketchwidget.h \ src/sketch/infographicsview.h \ src/sketch/pcbsketchwidget.h \ src/sketch/schematicsketchwidget.h \ src/sketch/sketchwidget.h \ src/sketch/welcomeview.h \ src/sketch/zoomablegraphicsview.h \ SOURCES += \ src/sketch/fgraphicsscene.cpp \ src/sketch/breadboardsketchwidget.cpp \ src/sketch/infographicsview.cpp \ src/sketch/pcbsketchwidget.cpp \ src/sketch/schematicsketchwidget.cpp \ src/sketch/sketchwidget.cpp \ src/sketch/welcomeview.cpp \ src/sketch/zoomablegraphicsview.cpp \ fritzing-app-0.9.2b/pri/svg.pri000066400000000000000000000041711250202676700164150ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 5721 $: # $Author: cohen@irascible.com $: # $Date: 2012-01-03 16:53:58 +0100 (Di, 03. Jan 2012) $ # ********************************************************************/ HEADERS += src/svg/svgfilesplitter.h \ src/svg/svgpathparser.h \ src/svg/svgpathgrammar_p.h \ src/svg/svgpathlexer.h \ src/svg/svgpathrunner.h \ src/svg/svg2gerber.h \ src/svg/svgflattener.h \ src/svg/gerbergenerator.h \ src/svg/groundplanegenerator.h \ src/svg/x2svg.h \ src/svg/kicad2svg.h \ src/svg/kicadmodule2svg.h \ src/svg/kicadschematic2svg.h \ src/svg/gedaelement2svg.h \ src/svg/gedaelementparser.h \ src/svg/gedaelementgrammar_p.h \ src/svg/gedaelementlexer.h SOURCES += src/svg/svgfilesplitter.cpp \ src/svg/svgpathparser.cpp \ src/svg/svgpathgrammar.cpp \ src/svg/svgpathlexer.cpp \ src/svg/svgpathrunner.cpp \ src/svg/svg2gerber.cpp \ src/svg/svgflattener.cpp \ src/svg/gerbergenerator.cpp \ src/svg/groundplanegenerator.cpp \ src/svg/x2svg.cpp \ src/svg/kicad2svg.cpp \ src/svg/kicadmodule2svg.cpp \ src/svg/kicadschematic2svg.cpp \ src/svg/gedaelement2svg.cpp \ src/svg/gedaelementparser.cpp \ src/svg/gedaelementgrammar.cpp \ src/svg/gedaelementlexer.cpp fritzing-app-0.9.2b/pri/translations.pri000066400000000000000000000043361250202676700203420ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 2846 $: # $Author: cohen@irascible.com $: # $Date: 2009-04-21 16:23:36 +0200 (Tue, 21 Apr 2009) $ # ********************************************************************/ TRANSLATIONS += translations/fritzing_de.ts \ translations/fritzing_ar.ts \ translations/fritzing_bg.ts \ translations/fritzing_bn.ts \ translations/fritzing_cs.ts \ translations/fritzing_da.ts \ translations/fritzing_el.ts \ translations/fritzing_en.ts \ translations/fritzing_es.ts \ translations/fritzing_et.ts \ translations/fritzing_fa.ts \ translations/fritzing_fr.ts \ translations/fritzing_gl.ts \ translations/fritzing_hi.ts \ translations/fritzing_hu.ts \ translations/fritzing_id.ts \ translations/fritzing_it.ts \ translations/fritzing_ja.ts \ translations/fritzing_ko.ts \ translations/fritzing_mk.ts \ translations/fritzing_mr.ts \ translations/fritzing_nl.ts \ translations/fritzing_pl.ts \ translations/fritzing_pt_br.ts \ translations/fritzing_pt_pt.ts \ translations/fritzing_ro.ts \ translations/fritzing_ru.ts \ translations/fritzing_sk.ts \ translations/fritzing_sl.ts \ translations/fritzing_sr.ts \ translations/fritzing_sv.ts \ translations/fritzing_th.ts \ translations/fritzing_tr.ts \ translations/fritzing_uk.ts \ translations/fritzing_ur.ts \ translations/fritzing_zh_cn.ts \ translations/fritzing_zh_tw.ts \ fritzing-app-0.9.2b/pri/utils.pri000066400000000000000000000062121250202676700167540ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 6796 $: # $Author: irascibl@gmail.com $: # $Date: 2013-01-12 07:45:08 +0100 (Sa, 12. Jan 2013) $ # ********************************************************************/ # assume boost libraries are installed under linux win32|macx { # boost_1_54_0 is buggy BOOSTS = 43 44 45 46 47 48 49 50 51 52 53 55 56 57 LATESTBOOST = 0 for(boost, BOOSTS) { exists(../src/lib/boost_1_$${boost}_0) { LATESTBOOST = $$boost } } contains(LATESTBOOST, 0) { message("Please download the boost library--you can find it at http://www.boost.org/") message("Note that boost 1.54 has a bug in a function that Fritzing uses, so download some other version") error("Copy the boost library to .../src/lib/, so that you have .../src/lib/boost_1_xx_0") } message(using boost from src/lib/boost_1_$${LATESTBOOST}_0) INCLUDEPATH += src/lib/boost_1_$${LATESTBOOST}_0 } HEADERS += \ src/utils/abstractstatesbutton.h \ src/utils/autoclosemessagebox.h \ src/utils/bendpointaction.h \ src/utils/bezier.h \ src/utils/bezierdisplay.h \ src/utils/boundedregexpvalidator.h \ src/utils/bundler.h \ src/utils/clickablelabel.h \ src/utils/cursormaster.h \ src/utils/expandinglabel.h \ src/utils/familypropertycombobox.h \ src/utils/fileprogressdialog.h \ src/utils/flineedit.h \ src/utils/fmessagebox.h \ src/utils/focusoutcombobox.h \ src/utils/fsizegrip.h \ src/utils/lockmanager.h \ src/utils/misc.h \ src/utils/resizehandle.h \ src/utils/folderutils.h \ src/utils/graphicsutils.h \ src/utils/graphutils.h \ src/utils/ratsnestcolors.h \ src/utils/schematicrectconstants.h \ src/utils/s2s.h \ src/utils/textutils.h \ src/utils/zoomslider.h SOURCES += \ src/utils/autoclosemessagebox.cpp \ src/utils/bendpointaction.cpp \ src/utils/bezier.cpp \ src/utils/bezierdisplay.cpp \ src/utils/clickablelabel.cpp \ src/utils/cursormaster.cpp \ src/utils/expandinglabel.cpp \ src/utils/fileprogressdialog.cpp \ src/utils/flineedit.cpp \ src/utils/fmessagebox.cpp \ src/utils/focusoutcombobox.cpp \ src/utils/fsizegrip.cpp \ src/utils/lockmanager.cpp \ src/utils/misc.cpp \ src/utils/resizehandle.cpp \ src/utils/folderutils.cpp \ src/utils/graphicsutils.cpp \ src/utils/graphutils.cpp \ src/utils/ratsnestcolors.cpp \ src/utils/schematicrectconstants.cpp \ src/utils/s2s.cpp \ src/utils/textutils.cpp \ src/utils/zoomslider.cpp fritzing-app-0.9.2b/pri/version.pri000066400000000000000000000023761250202676700173100ustar00rootroot00000000000000# /******************************************************************* # Part of the Fritzing project - http://fritzing.org # Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de # Fritzing is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # Fritzing 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 Fritzing. If not, see . # ******************************************************************** # $Revision: 5721 $: # $Author: cohen@irascible.com $: # $Date: 2012-01-03 16:53:58 +0100 (Di, 03. Jan 2012) $ # ********************************************************************/ HEADERS += \ src/version/updatedialog.h \ src/version/version.h \ src/version/versionchecker.h SOURCES += \ src/version/updatedialog.cpp \ src/version/version.cpp \ src/version/versionchecker.cpp fritzing-app-0.9.2b/readme.md000066400000000000000000000066701250202676700160750ustar00rootroot00000000000000# Fritzing The Fritzing application is an Electronic Design Automation software with a low entry barrier, suited for the needs of makers and hobbyists. It offers a unique real-life "breadboard" view, and a parts library with many commonly used high-level components. Fritzing makes it very easy to communicate about circuits, as well as to turn them into PCB layouts ready for production. It is particularly popular among Arduino and Raspberry Pi users, and is widely used in education and creative tinkering. * For more information on Fritzing and its related activities, visit [http://fritzing.org](http://fritzing.org). There you can also [download](http://fritzing.org/download) the latest releases for all platforms and get help on getting started. * To report a problem or suggest improvements, use the [issue tracker](https://github.com/fritzing/fritzing-app/issues) or the [user forums](http://fritzing.org/forum) * If you would like to help with the development, please take a look at the [developer instructions](https://github.com/fritzing/fritzing-app/wiki). This includes information about how to compile and run the Fritzing app in a few steps. # Folder Structure * **bins** - Part bins (.fzb, aka part libraries) are collections of parts, most importantly the "core" parts bin, and vendor-specific collections. * **help** - End-user documentation included with the app. This should really be moved back to the website. * **parts** - All the part definitions, including meta data (.fzp) and graphics (.svg), as well as some utility tools. They are kept in a separate repository at [https://github.com/fritzing/fritzing-parts](http://github.com/fritzing/fritzing-parts) and only linked from here. * **pri** - Submodule definitions for Qt * **resources** - Binaries and definitions that are supposed to not be touched by users, such as fonts, images, special parts, etc. * **sketches** - Example circuits/sketches shipped with the application * **src** - Application logic! * **tools** - Utility tools for making releases, converting parts, etc. * **translations** - Language translations # Credits The Fritzing app is maintained by the Friends-of-Fritzing e.V., a non-profit foundation based in Berlin, Germany. The project has grown out of a state-funded research project at the [Interaction Design Lab](http://idl.fh-potsdam.de) at [Potsdam University of Applied Sciences](http://fh-potsdam.de). The core team consists of Prof. Reto Wettach, André Knörig, Jonathan Cohen, and Stefan Hermann. Many [fantastic people](http://fritzing.org/about/people/) have contributed to it over the years. The Fritzing app is written on top of the [Qt cross-platform framework](http://qt-project.org). # Licensing The source code of Fritzing is licensed under GNU GPL v3, the documentation and part designs under Creative Commons Attribution-ShareALike 3.0 Unported. The full text of these licenses are shipped with this download. This means that you can create your own variation of Fritzing, as long as you credit us and also publish it under GPL. Similarly, you may re-publish our documentation, as long as you credit us, and publish it under the same license. You may publish circuits and diagrams that you create with Fritzing and that use our graphics, again as long as you credit us, and publish your works under the same license. A credit can be as simple as "this image was created with Fritzing." Look up [our FAQs](http://fritzing.org/faq/) for more details on licensing. fritzing-app-0.9.2b/resources/000077500000000000000000000000001250202676700163175ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/bins/000077500000000000000000000000001250202676700172525ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/bins/icons/000077500000000000000000000000001250202676700203655ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/bins/icons/Arduino-mono.png000066400000000000000000000010301250202676700234340ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxm@ Iw؀tA@e6hA:A T  W֘PTd%ߝ}A۶KB慽7/~R+x /od`,8Y29Fzr$pؓ{ lrx}p#Dm%IGts3 :M(Ēt)n$AlvAxΥ{FY8.*;KlWGcak(IoQ|ORN6]*Bf*U3go\lw$j1BvPTjl7@LDP&ܱQ\o7U̮:ժ@6,bS) ({Sfݹx &:xɦ?/LT1zU2og_^\`pWIENDB`fritzing-app-0.9.2b/resources/bins/icons/Arduino.png000066400000000000000000000010261250202676700224730ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxM0v H7 AW^H'2ap?OLlw;_î낿h^ G3RD(ֈUpΙ|2ti`¶&\8w+n7Dj:iA' UGɎߜ;U ;"7̚5ÇֺLzrHMZxetp=1xPyVԘ 6>]lщ$6s2G'8[5b~n`Њ=37|YheDIJ&WU%ol+{Fh+s& >)W)>·ãj&Rٮ S]V$8Q$ƍ:lwO=jf1F>Wň,EJ`7K{]`C`YYI :Gw}23XmrbIKISd1qDQhodeYG~ö IENDB`fritzing-app-0.9.2b/resources/bins/icons/Contrib.png000066400000000000000000000007511250202676700224760ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxV;R0578t$'( 87% 70fY+3TͼV+k?J͘G8nocJ6/?8/o(kԂFzݞdwlGl 6逆J lͤ_dS/F6yElO[#|-ti?Gl8(rY\mUdRE#y(2ph9*;Jj(R*"'8QtX~LYF?СOði&iDh:H^Aiȇ q;lĵrIK Pl]RK|xB˔W/߼NǰFu7S/_|@ׁ61$DMg1c23{HIENDB`fritzing-app-0.9.2b/resources/bins/icons/Core-mono.png000066400000000000000000000006121250202676700227300ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<,IDATxS 0 :BG`N@ e#t<>)JrNZmK tܓ00rp:?U.k *7✣ bڑ)B1&K1tc_DHDx81U0QaM#0A:<~cpF5S,ISol |%t+#6 _Ui>"0{I8,d|/aׇc]ԓFGgXO̿.p8p`rmhIENDB`fritzing-app-0.9.2b/resources/bins/icons/Core.png000066400000000000000000000005411250202676700217630ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATx 08@G`2nlmJ^Ζß%/]]LQEY&V:=LإsucI')_[&o W>pX1 |ʹlilqV쩱~L 5n&#IMk)mswlfӇ7#Vb-wz/Ҡ -S${//#j(M%6d&fDWb_G([p68IENDB`fritzing-app-0.9.2b/resources/bins/icons/Custom1-mono.png000066400000000000000000000666331250202676700234120ustar00rootroot00000000000000PNG  IHDRl}sBIT|d pHYs B4tEXtSoftwareMacromedia Fireworks 8hxprVWxOhP4 0E 7uA  D<Ѿtz[F5Gmk/o720LaI >m[uf2%yţ7Wq޿;˻zmsSiVST?1/8's؎k^C{פ>>>3hO1'q=ߵQNoM%?`*~7ԧ𯒳MdcsX"o[lu9 -s}w2SgkXo`!m^,g`p rEU*+tP#ÝTV_kn+:q?{Mc7j9.HmkBF)3mkTSx][sƒFrؒ[/ڧB(b]e@IVeow(Qa%=__վv6~0Zo֨5;-kvvv±[?헆9;Gxv{.ӿYoor͍TYQWzX9Od{{Va)є_aD8;Ci{:3c{ҝNfwv Kj{~.}nuNo2mYv}v=n`/WsM64:^shPӅ:4:k lf e]ـWtÞMb]30{1V?Bgb`،3Qx^ 5fzite c3x{wC@taP M3(gT .zdL0Yh4- MAŎNв$:66 #iD88.+}rGKo,v^qiqv`=q[Fl%,R.=*?K[w O@kxc^"4*FeШ A2hԂ< , &pz.EC44/!{VT'-ݔei2Br|ΐwM`rL.IpP 4wui {~A\8Z8Zhj0|h.>v#þQlAhtEHg Cj1(\ e0 #|a_6RERkq(aV,BY*| *S&( `>醯9oƋñfĖ⩱[=Q.`ڕ z<*YdiC 2Լ,"^*nwSޔ m4׽~r*< v,Qba9;qM3 њ(2N#P~VVk1Vu ]*ܧoL}$qôiV="#N;+?+*/YbZ!m9 Eb4ƁYCzqpkzS.KcԸŌv/}UdgG3%`zzy0CL w}i$I&+9q18O `#b1NN*pზ;0& -N DN -'y8իfr Ml6)CQh1H-A8l0}y%]=Ya3f4tvZIdNQʀ!T-LH Ɇb' $Ǹrosvr=h ?"cjHJn|22fG= ߰x o߄`hy<#Ken?Y~g-iP*J(>L7 s,)7SCgK[<ײO d)VuU'HHfr<8n cIiS&K_V ,x|M8L,΅ImAtϥ>{LU'KGS@1ۻ|{m,L&ցҨa;%C|75N)fZ"9&#F5U)$a& Ns N&7lĤfXboWҌ6=ljZ'6jH+ D*?s8yvd'նC~AyU26xRжVLx 6bA 5#=ZpNKp<\N%?dvE4+h0j)lN&*K1=fCK KrG&xv8N9M /B_ Ef7W'O*_7]B'DR0GtBCِѲ)c_jYxaZܓ+-Rϓ/Nr0&$r? E)NUZ*^"؅"r[ dOG}$`kԒ+#G\r!2f9 >IZtO5LbjC+C|dG%uI=22<->4h1G&QIԭ%ZE/(.= $*?1W2њVHpnW; 숣# ń٪eYC<2U$:;JD" ꇫrW} l;ZnG}3bo̝&=՞dcփ#Ћ! դdjҪ".!2 2~l&-Vi=jvC.`tk59yLN^-2rZ #4t+~Ĥ|T&٨Y&|C5ηl&1ָVf۔N_>yKHc!bKUzKsYxp 4_;1TuM{;[♙0/F˂) .vMْ˰qHFN{یmCK<:q&H" -*Pئ H8+O)t} [Mm6nM=UKC5yaMQ!_R(q F~ z_|?]qUĞCpJy)"p^]Ïoe4ih*+|>'6gö&a3&`~A uP>{~D)+ <]xNS1s}*h+4QH[:3k±sҎ0Y\: UYa#'! ['ȏ 'ܹ™-].LU::Ly>;cx/TM:4"UW"Z4P"[9瓼#q'jx(KȎ};BO>5l~I`[ttla(G8(;pvx?԰kfֽfhW ]3t5C95C#M{P3t5C }ڸ f皝kvy/dOSQ5gל]sl^rj2OZst5G}8q9Zwu]5;|Y ;ws ;וw5C ]3}`VyX+jfзn ]W ]3two[bٹf皝:;߶ʻŰs]yWsv5gOξmw蚣k}*pt§Hzp=^(;3 4g׳0ٚ(%ή^<9vFـ1=CȘh[A1*mϸ_0>vԷ} i_;ykt)׽O%a,J]g|E_TO]OT|8vW| +0t0!k5C }Z~2SebY'c$9$ 틞H^Yf {[cb1o2ǹQmw`Y?Nm'ӿ|H6/B)НwWÝM/gԉ#z4$OUd-6tyQɭOvQ~p|1|ΌBޱɒ[h)Ӗ*ZodQpNlÒ~#!V"%WS<޸-M\`dBZȜޏѪnr2A([#V_אF?p#8~_/8odX ~{|P)x8h%G$Ir i)T>>="Rs>X$~?HE vqj uY=O%;HxGz%,rNw*T'"3g+sޚ,-{"O]iw֬1HJWKG1Ʈ/{,ֲIvI.g|&5 䱌Z˙61V)JT-E;jݼ &]eIWLc:mrz-kfmiÄ&.ks}]uzЫ^v'uvF: Ǻ#yy.W[ߏō`)Gcal<T|3b5#&b(ͮ{I oISZ)PvH fPO'0>Z ÍBoá_|$&N0oj:o`{B lS3ףEt=_(ͷ2ˆQG[*D~U$|vQI>\|Q%I`Ե\"2qg5U`OA6׃lWг}zҮ,7 lܟ+p/d1&4˻^Cn/tF>K5_՟ݗ8?Ǖ039K-[O ϗQiWQ0A"6z o]sưOCjLNm:UttiCM{6_Qy/եmOF7Y{ЦvnϮǚݍ!qRgCm22C.lԡYc`31{D3o hxuY)Ysu:gvXslpܾ?0Q)cwp=>S v;i5|9wsqr#lѓ6H1H7z /(k|荍MѡƁˌUg~LMl5=<oBžr9mvG`綝=ܶaa͞CtMୃ3  ΃WiE-@ώ}O39Jnu`q9_5gUh>Ml47ts(?:t[xY ^Vkqy f!!tv = [xW}koj;p|إƬ<&EL4)׳@ { $qɁ2Q-{-7MVi`Jh\N÷8Ͱ}ZF3:`D;t+ܥ?|A:D8~D ꂑmkBSx]N0Æ WM- 2*5X|DZ=fLc(F? hҶ BLrGpodgd/e>f 9]WA\\Lf[xilϣTs1H QlHاEt(SAZ_Y X mkBTWx흍8 FSHI!)$FRHnw HYx3ꇤsaaaaxIǏ'U{o_ھgW9 o'GW {>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O- 92b?Tlk%?_21B sY5>:>c=1Ow y^- ڶ,XzusM#גU]>H_yYv!ۉ_mi Rus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, l gX #vQg Bٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'-(W? źvƔOʙRv[K?[A}?-wmՑ}g\=c}M ggg DŽ-B^k_g?F? v0||؎=ǧHPgs/hؑI t~{n^}ZyD5XWvO)"c0vY Z|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8gʱL{? 0 0 _k3>z_\S |<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu l+6v<ï k7]/lc[`On}򚄫 G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ 1Gg{+ҏlw<=}GݽFƨ^)zIpG K֜{{e G12ۭqiumf>.}~a? 0 0 [u+7Svq֭y΅ ?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo 9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3 _[_*mtcmC>qSL=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^U O7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU? 0 0 0 0 0 0 0.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwx b)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-tĒyNAgC \NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`% Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=o G<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy czA;w9zszWHVax3 %mkBTx흍) q ĉ8D^>׻gI@XjjgiЃ`0 `0 ?ϟ|:seQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/ D:3D&򈼹e^Hyi#/OGzϪ߯_~ :sMe#M3Y#=2 QЙ[\s=E8}E>GȩT ڲTg-}VfoSVwzV}./>~!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-k dW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ: `0 :8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV U?)V>ғ)x|Yҁgi\yi^cUo*= !TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x )/OS yUo2e)Ve3'wgGg=J^`0  ľu kU,Ksؑ5nY,bXw{ w&3QהNQev ]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fzt|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz `0 *\?W8GY:Dgcg< 2+'W6qn؟{ru"wU쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP ~n%hUG4(_sn|W}Tg&x^c,Fѭ+ <#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3 `0Q[ veO\k^8֔v<Zbz\Opbn$~}oz3ј mK vU]^iNWA#x딫jt q :E= z%օq)CcYEqyRG-+u (K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_Eб Vq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7 `0]kIu+eL]ւoA^;=GR?v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{ ?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0 leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR( VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l? `0 `0 `{~i`oLy>uoi\qK|}7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;y`$jwymkBT6x횉m0]HI!)$FR?6c>>~sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/rˆ_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{G}?v✽3X~j{zTAO^ʰ>?sy|G)PoP jրDCnZ+Fz}W @ _*mkBTx}+(H,"H$"#X$,QԈZs>U{ ..T}6ڳ-F`p]k߅~b  О$wݓٱ|sCoA+q3lOx@(0a+? T,_7s\Ϙ^Bl1)C+k(FyN"8dPC_9>O0&l4Im+nwGrŰ)/tihf ѸX>E)<,6s45zb?J\<OM%O#(76:= ӋYAƒH Ls6MXBcX&ǘJte. 3.je(??Lj=%wZizFTx$kP8Em jAOހ>~؆B9 ֤8UKCvjbL Cy ;mj P. DkwUE€3ܨ8xUJs\ɟ+;}sFQ(KIXݛƨ 1 +KdX];Jģcx$D׷X`i @l̏rnm$^9΄zBGϞQ=nfkDe; <a>,⢞jk0B[p($Ǡp4 nq`XƓ vϵ.xHnorJ5Hu뇗 f a[Z:>36[g RL؍?( &w.7C#~B{] UW 71jk~ecGrD.=K@WDZM0倐0\xvqNZ ># BE )&yA}t?B Ym(WIpɱ |2+\2 )l8tl@Z.Be񅋍RSƃm>dIl'N adĢG3%#)?$s _5=YBR#-k"qGP-e"f%֩-ϓ378M9ϊ,_*n;HEBƱcl~ ˝[/sagIE2,z1t:kLș壋G){7ond{@rP>kwk׽ #kXfyEAB9uM4P=_lgW؇N#_nGpp ,ZUu6ȓVӰ0EK7*|]{75F\ԶzQz! uH>upT٣o3P)[^6` -d&*=%fY<^ط`_6|h3ء>2 Pq7ώ ,NsjF=B` 큳CiU)R鐏@LҮǧmb<2FHRqùFXi䎲OmGA}:*u f:@ʫRH.66jcGOpO- 6HKJU:Jǃv,3DZEƮqq7p?ȌK%ȧ$;?Qr6pP7`a^=R_)m>D3#£ _' Iɭu͋C-Rne㯄ssL<ȭ/R)|Lt_1Lk=rr 4/gEr~PnB[\g[{gYvRW' {Fem1{ wL;7&$xc0 n&u@5sCCձm8Heft x{q(aтa?Q%l4ςxmWI׆GC1kQ3iJh,KRO`ʲ4)%b6B8\pe;u)ko)#WSncRx{[sXv195_0Kՙ7>Tp5ٴl3S"؝LX睫[5m Q="u}pϘ*xbՉ#iM+@Z! Ϯ~jYݬ$?5mtu] %@݅:4h8ۃtu3; ΑO1A/r R*5i&j#Y2:$Z(ad@>'z L뇶6Z8|`6"X1_z' F-я?X^ A:?1;h/KVB' vOnFS ƤQ{=kh7MwXQp\v͓O/. N3HKRlK"q^Wh1wt h@3e6N|I;y?8t[[! $,ήLe"z%IކAkRl!3u8ځy?_W)AbCO!rza5Sn֗#<43y6"R߃CQ&>[# BHǽ{vekOTlq(UH͵h ݔ8,@tՂL{p/*L"d_y k,4 G̖bD>,.ok"D;|7[.DCA#ilϟI֬Dq]+eE _-- ڰc^Lq1~CCC9gNH8BkhJ#Z-`VoMa 9r$պZ-hkh ?C$ ^tď9d(8P݅]ڶw[wl;dn׆oKd Hބ(DInI M_(5)6H/Y1 QRk,nXHʉ?>df&6^EJmt{CCc`0ʅv5x<\9Yc}106"״!֏9dl:' 1H"z'7QqɌ#KR./CVgQȬ\ `?d1yuM6Ƶ8ZX]8^pwQE &1frRKi$GݜЕh3'{;;~FK37ku<pdʎ+C RMzƏ7)nҀ lEGyl:̑IoBS%|ЕsTulebA}Aʹ10A{KʘӺtjdLI=r PRg_LbR Şl?␔)![Fo wi&k^CV(t@pW2{hxHGRn͉eCbxԉ6GQd27\ثdS=\Ff*0ۣOP5(rZߙxQZ>~GAeN-jY7Ҿn;n?ӹ"Px}/NW:݊&׾:x" ꭥу;R펔 c䛅љElmG§a= h¨BG_uYnZ쫭FYs U"zM&:Gnu.DX5Xn;}ԫ%XO?~2&Frjj8 yA*W I9/ub)Zl: s 85J>~iI3Yԕ;:#hELם[ROd^GA˩f~Y!En0~/A Km>^WYq"<цF*c:xw|͞w%ehRgd9̕v3v Dgh>>?3hYDkgC(ʹƒԕSԜ| 2Q94(?OGQ34 fccPopTYaW(>@tX4`LGٞpɄaŰl\[9c26U M6f,'C4i?W~psϠ?kAKrŵk@I|>^xs?\`,D̒5W^w DMXf_8<%|8_왉pP1Wlm߃f?4:́_Ԕv M;k:p_sj؎qw]$F}y ,b'N=o0, ~M YR46+!}@~ujctCP.Y(x׎z?70WXFܣo3z0c8RGg0 TU򄽻w"/4֏CQ`[{Ocn]+{{ N!33+5]qpj' r9FDȬ)~: 9Gmx2-?sraG"yvUpa;Ră A\& ?#n 0eed~oq嶭!!DzP^H)>oȑ.ļԶ=Hy7S-M ?8ycߧq|#5"2Б lm#UeΤVbM͘jAc7Z ]> 4gb s 2WRsKg6 's8qzTT[R[w)I95xWj #!nN+zPڔ KgTE,?{^RDݥ=Ru^zîc&D'i74SJߔ&HUG[crͦ<׿~4}څh;lpAZ%XZ;tQ?yk1+Ƴu6[ Dc4Ɯ*dB#!}e>samhG3c^8u9󼵕⸈߂UyB;f "Yi=D =4&|C3g]~WgjhSIXU"1A5Fr4{AljwTt6</N \Rta| i>T.Wo>>xϯY{緷m,J{gg}v~)]s!?wXGFl!7U|Cnfﳅ:.@mq%臔Ru?.:aBֺE#Gg'yXDuSWNJD)21ѵVagWPqȒ s?¶@g")s\T{f3go^w:^"{d#!φt},nyWFKv„X4|VB~,˘_&fjp/WԍwaO H 3I`u1ͤ+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_Wݚw)6IDATH=n G7g,;=yDvw P1Ϙ4!~<ćE+&(F:1nK$<sY0"c>R#bEa7 CD! #b E0dEpjczYk-I`=sqMVm[:I#7\kkJbTk=Y- Ng/,BR7{cDIRJ؝C1Yҍ;Qz+q}g8 ?"k> B vz$Z]IENDB`fritzing-app-0.9.2b/resources/bins/icons/Custom1.png000066400000000000000000000005401250202676700224250ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxb``P 0hO~n'c& b"hBꘈ0da O"&jmb vt- @Y>.@.H-S=k=>R9׸,ny?$ @K-^@iB!ZH] 袨$נ"kP<- bBBT ҷF(>p}+-IENDB`fritzing-app-0.9.2b/resources/bins/icons/Lilypad-mono.png000066400000000000000000000024561250202676700234460ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp IDATxW0 $ MM @#\[$mկ#!B; a-9q) x1÷d{Чd]׵ !4bk2,M ji8 Kmڷƨmwտ́,hJsQ)ހ7E`ێc5Uqψot@9h4KagAiA3뱆{*m =De յz6Qsb:>s(F2 fǂy2FuuF:c${:4"j[S@R=-yG%+ 7sкgөDu@Ǒ&if5myX6?>jW<ƹ˚0!:ns5n탷{1з2~Z=ǿӫ[)~DR0IENDB`fritzing-app-0.9.2b/resources/bins/icons/Lilypad.png000066400000000000000000000006301250202676700224700ustar00rootroot00000000000000PNG  IHDRDz5tEXtSoftwareAdobe ImageReadyqe<TPLTE]|hto:aîq;bϽ˄UwpzHmưg.X:dHtRNSIDATxڔG0 P%7|{@}㱭Q)yȻ%W%mVʮIENDB`fritzing-app-0.9.2b/resources/bins/icons/Mine-mono.png000066400000000000000000000005601250202676700227320ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxSm @ 28 @P0 @p0 4\~җ4z}z qvRa]X吻xBׁou4*xBr)Іۋh! 6L<ϵ|ڃDaU)LGչ.ĉ/'ؔ(?`7;œS|Æohvįb}G*~{Ka>N\k-U b'$7 ݡ/|'wN_Vi0 _ kǦ?IENDB`fritzing-app-0.9.2b/resources/bins/icons/Mine.png000066400000000000000000000005331250202676700217640ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATxT 0D@Gpn lu d_9kw{P BXMD)C"ۍcm)0 HtFq/bƻ/# Xǧ_I K-LłP +! ġhi! N5!\Z H=b-%dAABJ,YVJ @8@3u A " @Z Д1{bPZ!WsU>(@Z@TlSPӇـ]ao1@_tIENDB`fritzing-app-0.9.2b/resources/bins/icons/PICAXE.png000066400000000000000000000007271250202676700220520ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<dIDATxb?@&)k %3nb~E ~kha O҃Pm1rIԖxB% P&ȵ@@Az@dqiOA8ga)W :-M i'҅@ )e #@ G9qmZ@e,$Bu)E&1ҠA,>4_H =jXic&1U;ce4U,@c P0@KHAN8wRJCVC7j.`@>cx@hB 蕪bjPU4 E=hf[ `h4/,g IENDB`fritzing-app-0.9.2b/resources/bins/icons/Parallax-mono.png000066400000000000000000000005551250202676700236120ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATx 0`j|AG`!#nI7 ߤ&}hVI/&>8&ȖUP$8_>Ny=kp[aD9.eQ](ro}c-T>yF̄P+"spm$h }dUCtHBѕ>*F [s**"n9#[ DnkPvbv "_aIhC"camS-rO' Kx`n;IENDB`fritzing-app-0.9.2b/resources/bins/icons/Parallax.png000066400000000000000000000005601250202676700226400ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATx 0`jyE6@0D7@koRZZĤ/y!MѦ0!D6E̲" Zzs䚄+\8FQz¥, EnoŞʧ?#(pjQrđWB{j\(FZaqNEe0X!gd ȅcMXrJNBKC311 zHE7mQ!a<mqIp~ 0 m%nIENDB`fritzing-app-0.9.2b/resources/bins/icons/Pololu-mono.png000066400000000000000000000010231250202676700233070ustar00rootroot00000000000000PNG  IHDRDz5tEXtSoftwareAdobe ImageReadyqe<PLTE$$$###000///<<<ʢ222hhhjjjbbb񧧧GGG,,,---%%%ppp```===iiiEEE@@@JJJ'''&&&(((Po/tRNSZ8IDATxԒKW@ gJ *CEy(oP3ɰ9,Xa|ܤ|5ca8VhA$ */B%++ڃW-UcJi,Ɗ9dwTvnSo]FM C=2噍3':z#W*.T^ZXsMyؤ|lkF'įyeIENDB`fritzing-app-0.9.2b/resources/bins/icons/Pololu.png000066400000000000000000000010121250202676700223370ustar00rootroot00000000000000PNG  IHDRDz5tEXtSoftwareAdobe ImageReadyqe<PLTE#3aj\e!^b$դԟN[ &6/<Ye3A 1"4?P]  Ql>tRNSq6IDATxE1 P3efffՑliv>9y$g5zئ#5.K ujSDt@ê-, SNkENP;ڕ>ּ\@3RWc6܏YAP]$s)oAvDÝ$IENDB`fritzing-app-0.9.2b/resources/bins/icons/Search.png000066400000000000000000000007301250202676700223000ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<eIDATxM0wADA!N@6 H '^(RAA٠L~KG9Z dgߝum.1FBcm\nM#2R\SQM`5!s\ Ws^]siYBbz?+ *!0;|Z3gN{š9ck<}}?]ujF:%ˀsT-y+FEq9>w_x(5.OEoVWeJ5psu5?@[z.jg;4߁ /!IENDB`fritzing-app-0.9.2b/resources/bins/icons/Snootlab-mono.png000066400000000000000000000010001250202676700236110ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxVM@M"Hq;L퀤`]HhgEJ{fq4sLk ׋׉tM[{V}LސL ْ슬ԄdSVtN, ʣ 4Pn^js:|.uǺ΅l3*B EN&Đm JFjSiB=CJW:$0e^&j:EIY GGYJP[B ޸6;Nqoq38Ӌ#QMoZn nYJ G8w GF~UyPrS"Z9+]!Y$'bN%TRsWہ_ 0RgIENDB`fritzing-app-0.9.2b/resources/bins/icons/Snootlab.png000066400000000000000000000010271250202676700226540ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxb`B %.MƖRX4PH}x@ dib@ĎB*/,,RX|$ ph@@CAj~,,[Og@p # =ą@7hBjr>Rx G r(c*Xc=--3 jT"jK.,5 rPblZ O-"3O Р,a(NUuZVZ F5x>RI!L!4C RZhbxXGD([0b)#e ٹ?x7@-ڏT&/e!0D&$Q4PyXClOPDmu { drIENDB`fritzing-app-0.9.2b/resources/bins/icons/SparkFun-mono.png000066400000000000000000000006271250202676700235770ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe<$IDATxb?@&#br58) gg$5qA-l|$@\@ jlnGP}J?1??ObbƷ@ vFrJ.AQbh(A9hhPԇ@(Qd1z(h({.PL\z@X)hi._e#b+ *YhZA59u0%OZX@x!%RRR,ej&&"O3;1;PV6G-&4 _YljIENDB`fritzing-app-0.9.2b/resources/bins/icons/SparkFun.png000066400000000000000000000006001250202676700226200ustar00rootroot00000000000000PNG  IHDRl} pHYs  tEXtSoftwareAdobe ImageReadyqe< IDATxb`0񝙖2 B}P 끸Ix2 FQ fIENDB`fritzing-app-0.9.2b/resources/bins/icons/Temp-mono.png000066400000000000000000000005301250202676700227440ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATx 0+a6 P A@'0nhG8BG=rMj#{KJ 9'_k 0974os$2iM᭡XZ"o41XNz rbPLEcufX!:f)3![s ;,EŒ;ۇp2KjG #y5NJ"R#FE:+vGg#;ڱ θ= $ |\VIENDB`fritzing-app-0.9.2b/resources/bins/icons/Temp.png000066400000000000000000000005221250202676700217770ustar00rootroot00000000000000PNG  IHDRl}tEXtSoftwareAdobe ImageReadyqe<IDATx 0_6pFpG t6P'@'(N`7P' #y_]KEQK"کt*~QHdNbM:PX My Parts fritzing-app-0.9.2b/resources/bins/order.xml000066400000000000000000000013141250202676700211060ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/bins/pe.fzb000066400000000000000000000073521250202676700203700ustar00rootroot00000000000000 Parts Editor Parts fritzing-app-0.9.2b/resources/bins/search.fzb000066400000000000000000000002401250202676700212160ustar00rootroot00000000000000 Search fritzing-app-0.9.2b/resources/bins/temp.fzb000066400000000000000000000002341250202676700207210ustar00rootroot00000000000000 Temp fritzing-app-0.9.2b/resources/fonts/000077500000000000000000000000001250202676700174505ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/fonts/DroidSans-Bold.ttf000066400000000000000000005650701250202676700227500ustar00rootroot000000000000000GDEF&?4GPOS?TGSUBlt LTSH[[ OS/2`cmapԢKcvt KRQ\fpgms#Sgasp?( glyfA f "hdmxt8Hhead9d<6hhea *t$hmtxHUlocaS_maxp nameh0postP'!?prepeq֊Zbx_<2S =  m  y y/ZT33f @ [(1ASC m ^ Ju+-hb ?R!R=\?hXR?=HuNh?h\hNh9hhVhLh7hHh?HuR?hXhXhXf3#w{dwB9HND w w 1^d)jP1N 3BJLVfff)jqqqffybP/Psb P7hhXJuhhRh\hhjd/RhX=dm\hX/;L =qHu\9T . . ZB333333`w{{{{*B6/D w w w w whm wsVVVVVVVfffffqqqqJfffffhXfPP3V3V3Vwfwfwfwff/f{f{f{f{f{fwjwjwjwjqBq!qBqjBqB9qHqHqxHqHyHDDD wf wf wfwmf y yq yS1^b1^b1^b1^]d)P/d)P/d)P/jsPP17P17P17h3V`V wf1^buqT 3Hu H^J3#+9{P1 wBND?R wmNd)\m76f3Nf Nf3Nff ffyff%)-fwfw{)+w1^B69)3#+ {9^DDN wwd)\mNH=Vff3Nff//PZfb D{{JffbqqqP#TjsjsjsPRRRJR?%?!{5{bu ?!RRu w9fh#hRhB?)7f : ; Z C;9 )hXd%qLhXhXhXhXX))hq^^N) T-;-+Uh%TTq)3N3V^rXy))Hw;f\{DfbwH))D)3m wfjj wf^wFfbwfbwwfhu))-/'/7^3NRhZw fwfd)//ZZ )/m{m{DDB9 bm{ ?B3V3V`V{lf7f7f9^3Nh9h9DD wf wf wfHJPPPm{''/ b \f\/fNJ N=`w%f)/X5N;3V3V3V33V3V3V3V3V3V3V3V{f{f{f{f{{f{f{fBqoBq wf wf wf b wf wf wfHw;fHw;fHw;fHw;fHw;f\\\\\PPPf- -11111 V.     -  &&&&&'$0 0   ----&&&&& & &&&&&&"'    ' ' '$$$------  $    (" 0$$( &( ( &$.&&*.'&.      ,*"&+. "2(&(,. $. .&.&- +# #(*-  $+0&$&   '& +&&&&&&&&&       (((((--&                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ~ # O_?M   " & 0 3 : < D  !!!!"!&!.!^"""""""+"H"`"e%  #P`>M   & 0 2 9 < D  !!!!"!&!.!["""""""+"H"`"d%aI1vhcb]gD Xz} Bvt %"iOS`xlhijkopqrstu45]^   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a rdeixpk vj0-s12gw'*).l|!cn,B/(m}b  3:45y KRqNOPzSQL~ # O_?M   " & 0 3 : < D  !!!!"!&!.!^"""""""+"H"`"e%  #P`>M   & 0 2 9 < D  !!!!"!&!.!["""""""+"H"`"d%aI1vhcb]gD Xz} Bvt %"iOS`xlhijkopqrstu45]^@EYXUTSRQPONMLKJIHGFEDCBA@?>=<;:9876510/.-,('&%$#"! ,E#F` &`&#HH-,E#F#a &a&#HH-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y &QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,(#p(>(#p(E: -, E%EadPQXED!!Y-,I#D-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+)#D)z-,Ee,#DE+#D-,KRXED!!Y-,KQXED!!Y-,%# `#-,%# a#-,%-,F#F`F# F`ab# # pE` PXaFY`h:-, E%FRKQ[X%F ha%%?#!8!Y-, E%FPX%F ha%%?#!8!Y-,CC -,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,KSX%Id#Ei@ab aj#D#!# 9/Y-,KSX %Idi &%Id#ab aj#D&#D#D& 9# 9//Y-,E#E`#E`#E`#vhb -,H+-, ETX@D E@aD!!Y-,E0/E#Ea``iD-,KQX/#p#B!!Y-,KQX %EiSXD!!Y!!Y-,EC`c`iD-,/ED-,E# E`D-,E#E`D-,K#QX34 34YDD-,CX&EXdf`d `f X!@YaY#XeY)#D#)!!!!!Y-,CTXKS#KQZX8!!Y!!!!Y-,CX%Ed `f X!@Ya#XeY)#D%% XY%% F%#B<%%%% F%`#B< XY%%)) EeD%%)%% XY%%CH%%%%`CH!Y!!!!!!!-,% F%#B%%EH!!!!-,% %%CH!!!-,E# E P X#e#Y#h @PX!@Y#XeY`D-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,!KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-, #KSKQZX#8!!Y-,%ISX @8!Y-,F#F`#Fa#  Fab@@pE`h:-, #Id#SX<!Y-,KRX}zY-,KKTB-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY@cTX@C`BYYYYY-,Eh#KQX# E d@PX|Yh`YD-,%%#>#> #eB #B#?#? #eB#B-,zE#-@3 P07GW/@P0%5UeWfF@? F33U3U0@`_ 030@`F趴 F@ F/?З/?OόgFt&n6nUg fffee dd'^7^&]\Z[Z&Z6Z3UU3U/ WW+WWV"V2VVUT@!T F SSFO7OFN7N[k{ FH FGF@1F F3UU3UUGU0oTS++KRK P[%S@QZUZ[XYBK2SX`YKdSX@YKSXBYssss+++++++++ssssss+sss^sst+++s++ssssss++++ssssst+s+ss+s++s+s++++sss+++++ssssssssss+^ Nu^{18L+ff6?/!ww6? ^}TLyJx71%U****L ?gb]r :  Y t F $YKz!`B0GvNp&qg3z Y r ! >>??+?C?Z?s?@@@@@AA'A>AUAkAAAAAABBB)BRZqȿc #=V !8Qiƒœ |Öî(@YqĊĢ/ASi(DžzNɲ-ʖD˧Y̞͐ͤ͸1Jd~Ηΰ%>WpωϢϻ0H_vЍФ*C\uюѲ1H`wҎҧ &@Z~ӢӺ,D[sԋԢԹ/D\tՌգջ.E[qygع ك1aڑ +@  p@  H?2/3/+]33/310!!7!!IhyJhu]@B/?wfxi ` ?//]q3]]]]2]]]]]]]10#!4>32#".3Z0@%#?00?#%@0/A((A/-@**@B/@ _ ?33/]3/^]]9/10#!#))))-@P!   ` ` p  H      T 0 @ [?O   /3?399//]]]]]]]]]33]2233]22/]]33/3/]9293/]]92393/3/10!!####5!7#5!333337#/MNLJ/!MMNN/Ljjiib%3<C@F&.@#@@?@@:0 44+4{444)OE==$=t===@? H-*AA&9.@@@@&%@H%%# &@&P&&&&&:P`@/]33/]333/]]33/+9]]333333/+]3]]2]9/]]]323]]3210#5.'&'&&'.54>753&&'4.'665%5ifBpbY+*cjm4 [[-9j_WdeA>'_^. +;84967K`>  &>#L^rHK{[9 (+)#J\rR$ </?0? "-A1 H?@ H: H5 H@$ H H( H H#8.Y""V  !!@#!!).C +=&3"!?/??/99//883]3]10++++++++32654#"#".54>32#32654#"#".54>32;-21/`2-)V[UW,(UZVX-+p-21/`2-)V[UW,(TZVX-}|{}lv??vllu>>uHJ}|{}lv??vllu>>uR-9I@A'G():::HG#$-&DDDH67;K(( @" HK.G 67??''3-$#G3??3?99/39/3/+3]9///]]]]9]9]10!!'#".54>7.54>32667!%32674.#"66aPtxËL%Da<&5 =mZVi<-Lg;#5=)6F+ 9M-73#.R$JqN$HjENqJ$1}]2w^Z=d@  ??210#>54'3d$JqNEjH$NqJ$1|Z^w]?V#@@1?2/]/]]]10%'%7)u!㜉'm)hy9w)hpX @  /3322/222210!5!3!!#ondq? V@A/? < L y   *  &6F/?O @ H /+/]3]2]]]]]]10%#>7!'/36z|{8=}5=V@ ?/]]105!=u9&@/? `//]]]1074>32#".u0@%#?00?#%@0/A((A/-@**@D(@ ?//833/8210]]!D!J?)!@n#n tt??/10#"&&54663232654&#")7y|=7x~~>JVjh[[h5I.۱ffgf@~\1%@n `??/]]33/310!!4>7'31 NIOP! wN'!/@!n#@P`   ?2?39/]33310!!5>54&#"'>32!'+XAjL*YKOP-bvXiv?54.##532>54&#"'>321UsCEٓvZ-dda+VrD%Sbhf\zIai0SG;*ctLl~EoLy[=`xC'($ :Q0-I3!9L+NX#4'/Y= 8@ n u ??39/32/29/]]332210#!!5!3!54>7#=m# -//i 1>B<- *^/V(b@#%&&&&"$! H!{!]!m!!!n*@ Ht %s"t ?3?9/]/+9/]]]+933]3102#".'32654&#"'!!66V^xDJՊ7lcY$#\cd-;94{7 U:plwF  #oylq BL+);M@/" ( !  7/n =7nP`2u*t%u??9/]3/]29/]10]]]4>32&&#"3>32#".2>54&#"L;eّ230&U+f+ 9L_;_i8C|nlO)C1Y[.L63KmiпyE Cxf$?->vowEM?`Bk{$:H%3eQ27'-@ s??9/3]/]2]103!!`H!':N@j  %  #JJn00nP@@n######((nP` 66EE4EDEdEEEE-v;v??9/]]]]99/]]3/]]]]3/]]]]99]]10]]]]2#".54>7.54>32654.''">54.5[zH(F`8:oV4Hmv~A,Lf:1V?%I|v3L2ih#7F#,H3!9)+9 8+*:,XYBkWDL_vI[h86d[Kx`JIYlAWY,(C0cQ*C903=H8&8#*=/%&1>(#8&?);G@* "('  7n=/n 2u*t%u??9/]]/29/]10]]]#".'532>7##".54>32%"32>54.;eْ230%U,f+ 8L`;_i8C|nlP)D1Z[.L63KFiѾxE Cye$>.>vowFM?aBj|$:H%3eQ2us'0@)))/)?) `#/?/]32]]1074>32#".4>32#".u0@%#?00?#%@00@%#?00?#%@0/A((A/-@**@g/A((A/-A))A?s k@P < L y   *  """"/"?"  `  &6F/?O @ H /+?/]3]/]]]3]]]]10%#>74>32#".'/3/0@%#?00?#%@06z|{8=}5/A((A/-A))AX`@A4Ddt5E&/O:J) 0@/]q33]]/]2]]9=/33/210]]%5H}X2@ II @/]]3/]]/32105!5!XH'{X`@A;Kk{ 5E&/O:J) 0@/]q33]]/]3]]9=/33/310]]5X}H=Ju';8@2((' H= -7M?3?9/9/3/10]54>7>54&#"'>324>32#".+D0*:$MOEUf+emp6fr=7S7*5 0A%#?00?#%A0J3SKG&!438%9J:*-#1^V?cUO,!1,/ 3232>54.#"32>7#"$&54>3232>77&&#"-\^&C8) 2>K,SX.>tg-`YN #4"LmQFʄ8vuq3^債h6f⁞ l>L?*=' 6;R3_[#//$9iYg}E  ]**6 6\{EȊHfՑK"*1g|ßq=epc'Gc=2Ri3@ &6Fv@?H )9IyH `p@_?2?3]9//83]]]3/8]3]933999910+]+]!!!!.'de{^  ]\D`@Rcd#54&##32>54.#ЌG:S67_G)Fv6:N0ir=S35V@'Wg>lR7 -OxVdm:s*?*TI4J-)C0w#B@+e  !!Z!j!! g%%%`%%[f$_ _??]]]]210]]"3267#"&&546$32&&%Y]0+Y`Yi0^bg;NZmddREsu}A(% lo70':# &@ Zg?Zd__??]10#!!24.##326#ec1]Wr^\zt8H F@*g  Zd _L; _ _??9/]]]]]]22210!!!!!!!J W@:g  \d _oL;_??9/]]]]]]]2]]210!!!!!!Fw''D@('' %\)`)p))[ f('_+"_"_??9/]]]]29/10!#"&&546$32&&#"3267!D:vNZdu]gD^ft>+\eB[(5  ai2(".GqlH 1 G@+ Ze  Zd _L; ?2?39/]]]]]2]]210!!!!!!!65w=B ;@#  @ H0  Z _ _?2?2/]3323]+]10!!57'5!gRRRNR9R4@# Zeo '_/]?]2/10]"&'32>5!Ab"%Q0.O;!6IR  1R>~w8 r@N9y  I Y  9IYy di  E U  Zd $ ?3?399]2]]3/8]]33310]]]]!!!!7!t6zNX-`V@m)@/?Zd_??]]103!!6J H @Y HG6'I; ) H] eX 6 F   '  ^ d  ?2?33/3]]22]933+]2210]]]]]]++!#!!3!!4>767# <P{\V%NLFX^JBJL$T[@, H9I +I H^e  H @H6 F   $  F  @ H ^ d  ?22?33+]22]]++]+]22]]+10!!#!!3&'.5!w >RMLA9PLJ CC>w'(@[g)/)?)[ f(#__??]10#"&&54663232>54.#"OOOO (S~WYQ''Q~XWS(ݩllkksDDssDDm=@&Z ?_Zd__??9/]2]10]32654&####!!2=wO:٠Gͅ@humh`P?uw/W@8&6&[g1/1?1[f0;K[)  +_!_ /??9/83]]]]99]]10!""#"&&54663232>54.#"'OwQir OOO (S~WYQ''Q~XWS(wѬ,mJlkksDDssDD ~@P  ZD   Z d gL;` _  ?3?9/]]]]]]]92]3/8]39/]9]]310]]]32654&##!! !Tpx~O (CW0oX&G8-gdhXyKz_G54.'.54>32.#"CyjT0bee23I-#?Y7.reDAxj5ecd5d-NJG$NS7W>K~[2bo<,, +")9")?74Dedbk8&  SE%924!(Se);>@' o 0 @  Z@_??2/]3/2/]]]]]10!!!!! 0@  ZeZ d_ ?2?]10]]#".5!3265 EԏϋH5 ?^?uNrĐRMziQsI"X@+   `po@   ?2?3]/83]]3/8]3]93310]]!!!>79899JP``!!`_Pj6&@m 5)595I5f%v%'%%i$y$($ $&6Fk{ H dt6FV%k{9IY* dt@> H-V%%%%Y$$$$  -556`6p6666688@&5$ { , < L    -?23]]3?3]]]]]33/83]]3/8]3]9333]]3]]3310]+]]]]]]]]]]]]+]]]]]]]]]!!.'!!>7!>7!    1        16DJF;;EJD81=LTPEDMRG7 3 7GRMDEPTL= |@8    `p o @  ?3?399]]/83]33]]]3/8]3]933333]10!!!!!cV N^)+q@  0  ?@dtZ0@ H?3?9/3+3/]92/8]]]]33/8]3]]]10]]!!!VNDDP\Z/1 t@1iH  @ ` p  P O f@HO __?2?23/]33]+]]]]3/]33]+]10!!5!!!k}s"@??/]210!!#3s B(@ ?//833/8310]]!!!J3 @ ??3/2103#5!!3qT=7@+   ?3//23/39=/3310]]]]3#EDJNH//3/10!5!NRLP! *@E _o_/]2/]/33/]]10.'5!"_\LV+.0SXQ"QQLVu.a@>    @ .FU0O0000&G0  Q:N)N??2?3]9//]]]229/]10]]]!'##".5467754&#"'663232>5); !BNa@DtU0PHHEcTpe=T3D7*H5-A*+W[ TEB*#/6/A(F;9S6w08@ .GW2&FT1+M  M?2?3??2210]]2#".'##!3>"32654&Vf99hX8WD331 6GZ03G,,I6[UUsJ؎ْJ(3{!M!''#<-%JqK!Q~U,fs<@&   !!/!O!o!GV M M??]]3/]310]]".54>32&&#"3267qxIKvVKXBz7oddkWJ%FGMBٗ:*&%-# f=08@  %HU2.GV1+M  M?2?2??2210]]".54>323&'&&5!#'#72>754.#"Vf99iX6ZH9 1; 6GY76L/.N;`Z[J؎ٓJ-;#'("M!f"=,%KpK!Q~U,fDs)e@A  %%% HW++0+FV*9I(P|ON ??9/]]]]]]2]]]9/]10]]"!.".54>32!32>7dQk0H xʒQJro}CV%C_=3[VT,(QZhrz3V?$RFבܓJCz@gG& ! )HJ@,  H/FNM ???32/]3/32]]3/9/10+#!#5754>32&&#"3Ϩ4`U\~,HD.<1yyRRkT# M7.54>7&&54>3232654&##"32654&#"=6jj6 *8QY0Lrr9*FY/)!$6"Xg8lh21* \0N9bg>4#nDEH@?I\3"I*Ud7%%LuQ_k9+QrH=Z@( *3 4-(&rZc4/$XJ?* 5f[dd[Zjj6@!FU0 F TM ?2??22]10]!!4&#"!!36632jKN;P011`S`4yy0^Y*]'.,WM/dl/@0` FTS??3/]22]]104>32#".!!-=""<--<""=->1+9##9+*:##:^'E@,  FU))0)`))S### 'M?]?3/]]]22/210]"&'532>5!4>32#".f0f"6"-!1'W6-=""<--<""=- 'A3)Me:k+9##9+*:##:n  H@6 H0$ F T H ??399]+?23/8]]]33399]++10]]7!!!!pXlw1`TRJ @0`FT??]]10!!!1s*q@4  Fy8& #F"U,_, F T+@ H'M # ?22??322+32]9/]]]]]]]210]]!!4&#"!33>323>32!4&#"`HM:M.)CPZ.s+DR[.HMm\yy0^Y^+>(OU+>('yyjs;@$EFU0 F TM  ?2??22]10]]!!4&#"!33>32jIP

(/dlfds 6@!  G W!_!GV MM??]10]]]]32654&#"#".54>32^ji^^ki]GwoLGxoL1ؔMM،ؓLLws08@ .GW2& F T1 M +M?2???22210]]".'#!33>32"32654&7WD4+6GZ7Wf8:i3G,,I6[UU(3#7;J"<-J؎ٓJ%JqK!Q~U,f=s08@  !&F#U2GV1$" M,M?2?2??2210]]%2>754.#"".54>3237!!46767#Z7K./M:`Z[Wf89iX8ZI8 6GZ%JqK%Q~U,J؎ٓK-;#9 !"=,Hs@@! HFFTEU ?3]??2]]3/+]102.#"!33>  ;cG'-8EWsCmO^+F1bs7c@ !!' HFW9909.@ H.F V8.+N( H($N H ?3+?3+992+]]+310]]#".'532>54.'.54>32&&#"@vh7^TN(*]\W%):% .YKIkE"7*L=GrR,LXX,"%!%/"!APgGNuN'..$.,&!'=Nh/L\  H@4 HO_oF _ o  NM??332/]33/2]3/]+310+%267#".5#5773!!f-Q*+KI~\5X@"UlfA>d^;@#J FU0F T  ?3?2]/]210]]!'##".5!32>5!{)ER\0R`41IP

7!3>7!V   Z/q  zPu  u+?OY,gwwh,ZO@}^'moc=FI@1 \icbqp' X^ @[   iZ9I( FVf'7  @ H  /   @ Hi Z 9 I *   @ HfT6F$  ?3?399]]]]]]+]]]]]]+/83]32]]3/8+]3]9]]]]]]]]]33]10]]]]!!!!ZZ};#PjP^@.8 7  ) 9     @, H  p  &6@ ?2?33]]3/83]]]]]]3/]]3/8+]3]]]]]93]]]3]]10!3>7!#"&'532>77N PF>֡4L@#0D1# ^4v/8:9u /B)87m^ |@IYiH   @ H   @ HFVf@H@ HNN?2?2/+]3]+]+]]3/+9/33]+]10!!5!5!!mVFʹQ(N@2 ( H% H!0''oI!"??9/]]]9/]32210++4>'4>3".5}>aB!&c(A-sz-A(c&oR+D0>JiC  6+ջ# n^+6  CjJ;/@ 0@p?//]103#!(Rس H@) H %(%$o$$$I$$$??9/]]]9/332210++#5>5&675&'4.'523"&c(@-zr-@(c& Ba>}-JjC  6++^n #++6  CiJ0D+RaX'}$\@,(H %  @ H&   H @ H ?_@H/+]33/++]3/10+]+].#"5663232>7#".%9/*><93N39F0&90*><9e39Fh !,67  -m u^i@J[/?wfxi` /?/]3]]]]]]2]]]]]]]]10_]3!#".54>323^0@%#?00?#%@0^1%/A((A/-A))A)c)@ %%%%++++n@ H**?*!u(v  /]3]/3]+]]29/32105.54>753.#"3267\h88i[&LG?V587B\;rL23|E KljˈK    (SW%RB&@j $$*$ 'Wn!k{:   @`c @w  Gst?2]]?]29/]32/]]]3/]399//]]]]3]]]]]210]2&&#"!!!!5>55#5354>nP]Gu?CKN,5*C/?o0"#M_ۏ7Q:(*:R:qd.\ "6@_54.#"+f36`/},c68c+}53D'(F55F('D36c,*g68b-}}{}[j'E33E'(E33Eb@ O@<  @ n  @  @ H ?3?99//]]3]+3232/]33]2]292/8]3]933/8]3]9310!3#3#!5#535#53!59<\Zݲ/$@0@p?/99///]32103#3#j)CV@51E11&120B00$0:J))@ H  H$@V H$H'D HRMM(MM!!:'XoXXXX@ HDD'DD00?$HRHRHR 05, ?2?299//3333/]3/]3/+]23/]99+99+10++]]]]]]4>7&&54>32&&#"#"&'532>54.'.7>54.'y%0?F:k[fURDNQJ4Q8GuS.E8>?>renF'Z\Y'8J--QBLxR+qv 4[F %,K?2(vKAkL)/% 3.0*''DSe>d{%(iJJwT.)&# *'&* @Qf[?a3 $, 631$,%%@ #/]]32/2/104>32#".%4>32#"&%33&&33%&43''3>2HH$?]?]99//]]/]]99//]]310]]"3267#".54>32&4>32#".732>54.#"aj`k999vMkk64iiSDJq}6ahha66ahha6`ޥ``ޥ`򔃇D|jg{D,":ha66ahhb55bhޥ``ޥ``/.@ H  H H@D H .00000000@ H%O _  @H .((??2?39//+]3+]22]10]++++'#".54>774&#"'663232>55(qD2Q: +QwKZ;6(b4B>[DeB!&/ & 3$n:@7T9F="&$'7 $R^\ [@2 / _      ?322322333]]2233/]33310%R55=wwwwX?@ /3/10%#!5!#l=VdD 4H@W ?@ `  ??'J55     p     ::.DD ?]?]9///]]93/]]99//]]329910###!232654.##4>32#".732>54.#"MB/B9/ `6ahha66ahha6`ޥ``ޥ`^npR9B#. ha66ahhb55bhޥ``ޥ``?/10!5! \'@ )#?104>32#".732>54.#"\6^~HH]66]HH~^6*9 9**9 9*qG~^77^~GH~]55]~H8**8 9++9X D@(   @ H/+]3322//33223310]!5!3!!#5!onq/JR@3 H H   / _ Ee ?2?3/]33]]2+10+!57>54&#"'6632!y.=%0((W5{AmBmM+6T54&#"'6632QY3J1LABIJE&@0p\4@$ 23/T9e>g>jM,Ed *7B$y##(265&'&2&(/>!7!L0/*V *6>?:LQQ"18;82j^9@"B F U0FT M ??2??32]210]32>5!#'##"&'!!KQ:N01+ #iK6Z1yy0^YUU.,*+%T$Jq5@ H   /2?9//]9/+10####".54>3!=U_m32#".u0@%#?00?#%@0/A((A/-A))AK@0( H??//9/]9]/]3/33310+#"&'532654&'73HwW-H%'%+J\N:-9Z>! #%9= "/=\JH7@$/_p ??3/]33/3]10#4>7'%3HNm-J=>4 =9Y H @5 H H H!!!!!!!!@ HO _  ??/]+]10++++#".54>3232654&#"-TvJEuU/-SwKDsV0L7><77<>7\W]11]WW]00]WdeeddccT^^ ]@4     /_   ?322322333]]2/_]322310'7'7^55#;w\\w9;w\\w9.'&{<*@`p`]5]5]55?55.'&{t0@pD`]5]]]5]]5?5Z''<u @P0]]5]55?55By^';C@) 2((' H @P` -7M/3?9/]/9/3/10]3267#".54>7>55#".54>32+D0*:$NNETg+fmp6fr=8S7)5 )0@%#?00?#%@0^J3SKF&!438%9J;)-"1]U?cUP,!1,0;V/A((A/-A))A3s&$CR&#%+5+53s&$vR@ &V%+5+53s&$KNR@ &*%+5+53`&$RNR@ &)%+5+53V&$jLR@ &&5%+55+553 &$PLX @4.34!%+55?3/559@%FF Zp g@.H_ _  L ;    __?2?29/]]]]]]2//3]+229/]332399]]]]10]!!!!!!!!!!#3X[\a\`Nw&&z ,$ %+5s&(CR &%+5+5s&(v\R@  &M %+5+5 s&(KR@  &%+5+5V&(jR@ & *%+55+55*s&,CR &%+5+5Bs&,vR@  &` %+5+5,s&,K@R@  &%+5+56V&,j>R& *%+55+55/#g@BZg!?!X;Z'd _oL;__??9/]]]]]]]322]2]]]103!2#!#%4.##3#326/ce1]WrRd\^Tzt8`&1RR&* %+5+5ws&2CTR(&-4 %+5+5ws&2vR@ (&I(/ %+5+5ws&2KR(&/; %+5+5w`&2RR@ +&,: %+5+5wV&2jR7&(F %+55+55m  n@D V%5Y  * :  V%5Y*: @ H_/]+]/10]]]]]]]]]]]]]7'՗-1-ӕ-+ј-՘w$/2@(%[g1/1?1[ f0'+ +??99]9910#"''7&5466327&#"4'32>OHRa]O[AFP^] /EaWS(+9"P0YQ'ݩl=u^d(k!o`cݸs+DstD s&8C=R&$ %+5+5 s&8vR@ &_ %+5+5 s&8KR&+ %+5+5 V&8jR@ '&6 %+55+55s&<vZR@  &R %+5+5mH@,Zg?_ Zd` `   ??99//22]]10]##!!3232654&##m3u6|u9Tyxjsh^OByizlg+Co< H H@7 HF11GHF**9E  GWEE8F9TD 4M?9O?3]??99]]99]]]10+++#"&'532654.'.54>54&#"!4>32+?K?+5R91L5b<ELP"PX)JI>)dalkJusH@aL:0*"(3&AM\<"=>**1"$@?E(5N>45>(?Nahsmj4+SzV!&DC/&Ǵ4; %+5+5V!&Dvm@ /&/6 %+5+5V &DK@ /&$6B %+5+5V&DR@ 2&$3A %+5+5V&Dj@ >&+/M %+55+55V&DP@ 4&%9/ %+55+55Vu4CL@^   G'F55 *H HHH/%WNONoN;G VM59'I'(''PGGG|GGG,(DDO (N>N,N/?2??]3?]9/]]]3]]22]2]]9/329910]]]]"&'#".5467754&#"'6632632!326732>5"!.E+Tb{RD{]6PHHEcTpm~o|CV%C_=^X(QZhe=T3D7*H5Rk/Hei6M3+W[ TEB*#/6Cz@gG&+- /A(F;9S6rz3V?$fs&Fzh@ P((  %+]5fD!&HC*&/6%+5+5fD!&Hvs@ *&l*1%+5+5fD!&HK@ *& 1=%+5+5fD&Hj@ 9& *H%+55+55!&C& %+5+5!&vE@ &Z %+5+5!&K& %+5+5&j&"%+55+55JH#'7v@Q $  (GW99/9_9990GV88!--N55N_K/?]]]]3?]9/]]2]]]]]10]]]]&&'77#".54>327&&''4.#"326"N*`I9dHlG$HvoLAua` eBe1K3l]1L5j\0"E&jEyܘODzzC?1X8h/VB'?hJ)j&QR3&- %+5+5fd!&RC &%, %+5+5fd!&Rvf@  &O ' %+5+5fd!&RK &'3 %+5+5fd&RR#&$2 %+5+5fd&Rj/& > %+55+55X+`@7""=M} +- '?_  H//+]/]]/]]]9/]3]2105!4>32#".4>32#".X&32&&23&&32&&23&d*:##:*(:%%:*:$$:*(9%%9fd#,@S''w''#'3''&,< % '$$8$H$$GW._.7GGV-@% H& H&*!!8!H!!M**7*G**M?]?]99++]]]9910]]]]]]]]]]]]]]#"&''7&&54>327&#"4'326dGw9h09DEOGx>s31>?F: (9i]%i^1ؔM^ZoJۏؓLO`bHхVA@1Nd!&XC& ' %+5+5d!&Xv@ &P" %+5+5d!&XK)&". %+5+5d&Xj/*&9 %+55+55P!&\v=@ &c& %+5+5w$58@  3G W7+FT60M%M?2?2??2210]]>32#".'#!!"32654&7HY7Vf98fW7ZG613G,,I6[UU#<-J؎ٓJ&2 4;yB#%N%JqK!Q~U,P&\j@ .&= %+55+553&$M`R@ &%+5+5V&DM@ 1& /0 %+5+53}&$NLR@ &!%+5+5V+&DN @ 4&/9/ %+5+53&$Q= ++%+5V u&DQm CC%+5ws&&v3R@ $&$+ %+5+5f!&Fv@  & ' %+5+5ws&&KR@$&@+^+7 %+]5+5f!&FK@ &0'@'`'p'6'3 %+]5+5wf&&OR@ 3&r$. %+5+5f&FO)@ /&Q * %+5+5ws&&LR@ )&d/$ %+5+5f!&FL@ %&E+  %+5+5#s&'LTR&#%+5+5f&G8;@ 6\<<%+5?5/#f'8q@G  #.F:6GV9! 3   #(?2?]2?9/]]]3]]2?]329/10]]".54>323&'&&55!5!5!3##'#72>754.#"Vf99iX6ZH9 ;1; 6GYC4G,,I7[UUF̆΋F,<#((#Q$3ǡT"=,"DfEJrM(&(M#R@ & %+5+5fD&HM'@ ,& *+%+5+5}&(NR@ & %+5+5fD+&HN@ /&4*%+5+5I&(O!5& %+5+5fD&HO!@ 9&*4%+5+5&(Q!!!%+5f(Ds&HQ9??%%%+5s&(LR& %+5+5fD!&HL@ /&5*%+5+5w's&*KR@ (&V/; %+5+5=!&JK"@^&`ePe@eeq%%+]]]5+5w'}&*NR@ -&G2( %+5+5=+&JNc&`hִh^%%+]5+5w'f&*OR@ 7&Z(2 %+5+5=&JOm&^h%%+5+5w;'&*9 R(. %+5=!&J:7@ c&d^%%+5+5s&+KR &%+5+5j&KKJ@ &%1 %+5+5f@:ZeZ d    P  _L   ?3?399//]33]]]22322]]32210#!!!#535!!5!5!͹ʸ65w-j$m@G"" FU&&0&& F T%    PM  ?3??]29/]]3]]]232]910]!!4&#"!#535!!!36632jKN;P0Ϝ1;1`S`4Pyy1^Y/ǡ*]'[WM/dk`&,R@R@ &%+5+5&R&%+5+5B&,MUR@ & %+5+5n&M@ &%+5+5!}&,N>R& %+5+5+&N &%+5+5B&,Q%+5j&LQ` --%+5Bf&,OPR& %+5+5^ @0`FT??]]10!!!1^BR &,-@e!!o!O!!]]]]4)&LMJ@'UAAAA0A A]]]]]449Rs&-KR@&' %+]5+5!&7K@& ' %+]]5+5;&.9\ %+5;&N9` %+5^@)9  *H@7 H0$ F T H   ?3?399+]23/]]]33399]++10]]]7!!!!Flw15fR^(['.,s&/vR@ &%+5+5&Ovg@&@| %+]]5+5;&/9-ڴ %+5x;&O9 %+5&/8/  %+5?5&O8@  \%+5?5&/Op%+5&OO8@ 0t%+]5 9@"/ ?    Zd ??932]]103'7!7!Eq6u)oXĞX ?@* 0 P ` F T  ??9]]32]107!'7!FuGq1+ph+p-s&1vR@ &G %+5+5j!&Qv@ &T" %+5+5;&19´ %+5;js&Q9u! %+5s&1LR&# %+5+5j!&QL3 && %+5+5d'Q@ U)_))]]4Ry'@9% I!! H!^"e)))@)P)vG$F@ H^d(#@ H )!   '_/]??3]]333+3+]22]]]]]]+]229/10]"&'32>7#!!3&'.5!Ab"%Q0*P@,;=DzR  (C3NMLA9PMJ CC>Joi3js*L@/E ))@ F%U,,0,,FT+M ?2???22]/]]10]]"&'532>54&#"!33>320f"5","NK

(/dlMe:w&2MR*&() %+5+5fd&RM)"& ! %+5+5w}&2NR-&2( %+5+5fd+&RN%&*  %+5+5ws&2S-R@ (&v(? %+55+55fu!&RSq@  &\ 7 %+55+55w+q@HZ(( g---?-_- [ f,g_L;g_)_(%__??2?2?]9/]]]]]]]]229/210!!#"&&546632!!!!!"3267&&-a5OO6b-EWS((S~W >>H&&&&WDDD,G VC(88O9I(P==|===!)55M/M!N?2??]9/]]]]]?]2]]2/]]]9/]]]29910]]]]"&'#".54>326632!32>732654&#"%"!.RwHBqoLGxjBBmo|CVx3[WT,(QZh^ji^^ki])E3 0HKPNMM،ؓLOMNNCz ! E:Y=3V?$ s&5v}R&& %+5+5V!&Uv@ &`"%+5+5; &59% %+5q;Hs&U9)!%+5 s&5L!R$&* %+5+5S!&UL &&%+5+5^s&6vNR@ :&:A%+5+5b!&Vv @ 8&b8?%+5+5^s&6KR@ :&AM%+5+5b!&VK@ 8&?K%+5+5^&6zNB:%+5bs&Vz@8%+5^s&6LR@ ?& E:%+5+5]!&VL@ =&C8%+5+5);;&79%+5/;L&W9  %+5);s&7LR@  &%+5+5/(&W8 z%+5);m@Do0@  Z@  ??29/3]2/]32/]9/]]]]]9/]]]]10!!#53!!!3#Tb/L!@  H@ H##O#_#o###F @/HI_ o  N PMM??39/]322/]3/2]+22]3/]+33]10+%267#".55#535#5773!!3#f-Q*+KI~\5X@"UlƽfƔA> `&8RR&* %+5+5d&XR1@ &- %+5+5 &8MR& %+5+5d&XMD@ & %+5+5 }&8NR&" %+5+5d+&XN/ &% %+5+5 &8PR@ &" %+55+55d&XP1@  &% %+55+55 s&8SR@ &g/ %+55+55!&XS@ &o2 %+55+55 &8Q~--%+5d^&XQ //%+5js&:KdR7&>J6%+5+5s!&ZK4&;G2%+5+5s&<KR &%+5+5P!&\K@ &&2 %+5+5V&<jR@ & '%+55+551s&=v9R@  &_ %+5+57m!&]v@  &i %+5+51f&=OR@ & %+5+57m&]O@ & %+5+51s&=LR& %+5+57!&]L@& %+]5+55@" HpFTM ??]]]3/10+"!4>32&&=;14`T]~,HD-M<\kT# )i@D H0  ((?&F@`)N&" ???32/]]]]]32/]9/]9/10+]]#"&'532>5#5754>32&&#"3#'Wc0f"6"-#4`T]~,HD.<1yMe: 'A3qRRkT# M32.'5>7!4&#"366ig+$A\75\E(H^  ]60/*VL\_#6**7++&2-IJ#:W8X=!!=Wa!KYY7;>5) 043 494-33-+33V -<P\@&++  G =@&&&.F, QQ= WW@RG=GG=,U^O^^0^4G0.Q)ZaBTaL0LLLL @ P BL LB:%%"N)7N/??2?3]9///]]9//]]]9////]3]3229/]]]10]]]5>7!'##".5467754&#"'663232>5#".54>324&#"3260/*VL]^#; !BNa@DtU0PHHEcTpe=T3D7*H5{'E\67\A$$A\75\E(6**600*6043 494'-A*+W[ TEB*#/6/A(F;9S68Y>!!=Y77X=!!=W8-33--44s&vR&e%+5+5V!&v@ M&uMT %%+5+5ws&vR@ 0&I07 %+5+5fd!&vf@ -&O-4%+5+5^;&69:@%+5b;s&V98>%+5!6@!) _ o  _/]22/]3]]/33/]310&&'#5>7!!3n46h3?A<d74\UXX/0C,$A3"+K|Y20X}M+2 1(@ @H/]]/+104>32#".-=""<--<""=-+9##9+*:##:TJ@ H  H H@ HH_@1HO o   H_o@H@ H_/]+]]+]+]]/]]+]+10++++#".54>324&#"326J'E\67\A$$A\75\E(6**600*68Y>!!=Y77X=!!=W8-33--44 8@'** :   ?? //]/]10]]]3267#".54>73-# ? J2:\A#1B%FN*(  "=T3+H?8BmH@0opH _ o   G_/]3]3/]]3/]3/]]310"#>3232673#".% (AX5)NMK$$ )BW4(PLKB56PtL% '!46OtM%!'!!N@3 H H@H `!_o_/]22/]3]/]2/33/+3/3++105>7!35>7!0/*- *6?>;0/*- *6>?:LQQ"18;82LQQ"18;82/! S @8 H,<L| _  _o _  /]3/]/33/]3]]]]+10>7!#  R5MQP!DR #{@W<L* _o## ###  "@H@ H"/""/]3/++]3/3]2/]3/3/]]33/]]104632#"&%4632#"&'>7!#G:9JJ9:G#G<9JJ954.#"JkOOOO (S~WYQ''Q~XWS(fllkksDDssDDB,.@ &FvH @HHW g  9  48 `p?@H@H   g 4  @ ;  ?3?3]]3/8]]3]++]3/8]3]]9]3310]]++].'!!!RqP__!!`_PJ01R U@5g  ? _  f _L; _ _??9/]]]]]]]22/]22/10!!!!!ZRJsdw=Hw21@Ze ?  Zd_??3]10!!!!!84Lm3N'h@D   (H@ H   `p?2?2]2]2/3]+]]2/]]+93]10355!!"&'&'67>3!NZzC &+G61,("  =);7<\3 .;@]....^;    t  ]%g====_=o=@===/=5]f< /`;`- ?22?22]]]]]]9/_]]_]_]_]33]_]_]221032>54.##5#".54>335!32###"33 MrL&!EjH%n\9Bӑ11ӉB9[n$HjE"&LrM 0UtC5!D=֘//ֆ="'JlF>kN,#ׂˌJLHʂ!XsCBrX7+@z   $$j$z$$L$;$($$$ )[!!--@Hk-{---/-?-_- fvC4'[  , !$ # ?32?]2/]]]]]]]3]]+]2/]2]]]]]]]10]]"!!.54>32!!>54&>fLsHvR-TT-TvJw|Mh?Xm),}gWWg|-(nX6V&,j>R& *%+55+55V&<jR@ & '%+55+55f!&~TF@ N&/DJ3%+5+5N!&T@ B&n8>+%+5+5j!&TD@ #&B %+5+5!&T&%+5+5&U% 2%+555fqC@  ? G33*s*T**@A I* **EEEEElEZEEH IE/EEGVDoD09$ M ???M?2]?2??]]]+]]]]]+]]]]]2210]]%2>754.#"".54>32366733267#".'#Z7K./M:`Z[[j:;ob7YH9 ! & ')4RA09I]&OyT Q~U,J׍ٓK*?*#S!bwD".  '@0"=.;s@I!  9F_o,GW==0=333#FT<2M:333)MM??9/]9?29/]]3/]2]10]]]]]2#"&'!4>"32654.##532>54&gGW`4@wg[9Mc'E47:9pm)G^6H66N4b1bb 8^]ls= 4{s7;eN |p?V57N/a_N^@3G)9 H X    G @' Hp   & 6    @   ??333323/83]]]]]]]3/8+]93]3]]3]]]]]9/]10%!4>7!3>7!# %u= >>~4*y?R)ll] S_f2fd.@g@?" , (H44*/G  WB_B9G*VA4 444 >M%N H ?3+?9]33]2/9/]]9310]]].54>32&&#"#".54>4.'326)K9"=o`Aqgb3lTO%2 ?^>IunL8a.@'$OA+2H.ajGUc9JsN()-7$47<#^ȃ?=unjsLn5YJ< 1RvQ0S="Ns7@x # ;,{4++++W999_94H!!!!!!!!!! *FV8O}H /N,& NF%5?3]]]?39/]]]]92]3/]]]]]]]]2/]]9/]]]10]]]#"32>7#".54>75&&54>32&&#"3 v;]B9j`S H͂}:'Ge=liI}^6nh_(VBV.K4r{ID, #*/UzK>ZA( dPoF 1 'B7f3k@$ 2  ##%  *  H@ H5p5*G V4 /*!5# N!?2292]3/+]/2]3/9]10]]!>54.'.54>7#!5!&16) "@4]f7Rf485ywH& #B]:RoD%-[YR#'SNE  Hqe^߶p©|i,JZ5 4AOjs<@%EFU0 F TM  ????22]10]]4&#"!33>329KP:O0)CPZ0s||0^Y^*>(Efb+!n@G  GW#_#G V"N}$I>OO??9/_]+_]_]_]]]]2]210]]]]#"&&546632267!"!&&b8{Ê~>8z?f\uZidZ\ mm))lk^=@  Hp@I0pFT ??/]]+]10+3267#".5@5-Q*,KI~\5^A>"Ul^!4@2 '444%4--- H/- -- -)--@ H6@6`666666/643  @5--$???9333/83]3]]3/+]9]33]]]+]10]]]3'.#"5>323267#".'&&'#!)0:%2 ',,\aE ('&# )01;XA/\%  !\5@# 0\V@O,  5! !9 3I-3%]x^>?;MfH@:  F%21%1%9999:: ??*??H4F  & && 4@! H44JpJ*GVI'P*/?$$9JN?229/992]3/+9///99]]]/2]]]10]]]]4>75&&54>7##5!#"33#"!>54.'.f)Kh?ir"FnK@7/*! AIf<7\E#B]:RoD&16) "@4]f7Dr]G ~g7UB1 ?_@+B-{{BP1 4AO.-[YR#'SNE  FkfdsRd^d@A  HFO0@F0@N ???22]3]]]]]q9/]/2/10+%267#".5!!#57!##A1;? GrO+6  &O|VBuf31yXs-M@5 )GW/_///// FV.M$M?2??]2]10]]]#"&'#!4>32%"32>54.X;obH3GsjI0F/%c40F,,F/ؓM+"+.'_-הMM$MxU++&Q~YYQ%fs-i@%& $$$H@ H/p///GV.$.//((. M?3339]]3/+3/]/]]2]]]104>32&&#"!>54.'.fKvVKXBz7od$B^:RoD&16) "@4]f7?*&%EW56DR0._\V%*WSH Lsf`)S@8  $!G++0++++++G V*%MM??2]]]2310]]]#".54>3!!!32>54&'#"uDÀtJS݋!%A1+2N76M195+Cb?iLHӋڋ@'YhxHvT.+NmC{K$R)^w@E H  0@`UK.F/?Op@ HNM ??2/+]]]/]]]]]3/]3]10+3267#".5!57!s@4-Q*+KI~\5yA>"Ulf^H@0 )9 FW!!!!FT  M??3]]]]10]]]".5!32>54.'!uo-2\b3N4 3 CQo`*\jB|z}CC{{HJfw 5@c- ''4'HEu%,I%%%y%$%%%H/W77777DI_77HV6N* $N4??32?3]]+]]]9/_]_]]]]+9]3]]2310]]4.#">.54>74>32'@.3:?fG'pQ!=U3'=*%AW3:fTkyA]pNBuY3Oa54'!!.5!JlG"-#)%Xwx˒R#=cI+S`܌E&A֚3WyN(;wH^=g@B%%%H$I$$$$$$z$$$0H9W?0?@?`?HV>3$+M ?322?3]9/]_]]]]_]+]9910".'##".54>7!32>5!32>54'!?bK5 6Jb?ll6 *%A<+D/*8!!8*/C,%+55+55fd!&RT#@ *&A & %+5+5!&T3@ *&/ &%+5+5wH!&T)@ H&L>D9%+5+5V&(jR@ & *%+55+55)#t@L*:H Z_o@/ Z %$__`???29/]3/99//]]]]]29+]10]"&'32>554&#!!!!!!25h..Y%/$FP/hq; =5YG^5f]s&av\R@ &M %+5+5w$m@I ""Z"j""!g&&&`&&[f%_oL; _ _??9/]]]]]]]2]]]]2910]"!!3267#"&&546$32&&%K|]: ' Yi0^bg;NZmddR1\V(% lo70':^6B,6V&,j>R& *%+55+559R-P*7@ / H @E H^)$ H $$)+Z )))) ) 1Zg9_987_ +_)_+_ ??]?9/]3/]99//]]23]++]]2]+10]]]32#!##"&'532>7>7!32>54.##lȃ?Aґy !:Z\*J 4,$ %)/T8Y?"%Da=?Bvalu>^M`g5 DrV2%H0N8:J*V#g@A Zu Zg%%_%%% Z d$#_; _ ?3?39/]]]]322]9/]3210]]]#!!!!!!3232>54.##VAґyL65mǃ?T8Z?!%Da<@lu>w=Bv0N8:J*)]@:Z  _ o @  /   Zg _ _ ?3?29/q3/99//]]]]]210]!4&#!!!!!!2}FP/hq;YG^5f]s&vR@  & %+5+5&6#R'&,"%+5+5V u@N\yD5 Ze ?  Zd _//3?3]9/]]]_]_]]_]_]q]]q10!!!!!!!|{66VL3$mW@:Zg?_o@HZ d_4_ _ ??9/]]]]2+]91032#!!!32>54.##lȃ?AҒyJT8Y?!$Da=?Bvalu>H0N8:J*%a VS@- \ Z \ _ _??22/33/3/]99//]33]3/103667!3!!!! q9k[J4GW1r%VLTV^jm(9ݹ@# H%  H  *  H *@C H%5     ]9     0P@  }} ?33?3399//]]33333/833/82]]]3/8]33/839/3]]322]]10]+]+]+]+!!!!!!>?!@=?@<<B^9[@8#)\Z g;0f:i"""""`##e#:#J###/,`5`?3?39/]]]]]]923/9910#"&'32654.##532>54&#"'>32X3[}K\c4JՌW+iml/9j]vhpW#vseL4o[r|B`IxX9  9YwI`t@)&$ pg5K21F-KYA6%;*6a@, H9 I   +  I H^ e  H@H6F$ F@ H^d  ?22?33+]22]]++]+]22]]+10!3!!46767#!RrL>CC JLGJ9ALM&6R&" %+5+5 g@C ) H  d o v d E U &    Zd ?2?3923]]]]]]3/8]]33310]+]!!!!!@6J=<Bn@  H @6 H^ H @Ze!!__ ??]?/]9/]]]3]++]2]+10]!!!#"&'532>7>7! !:Z\*J 4,$ %)J^M`g5 DrV2%0+w2nm3w&);7!g@# !!dt# #P#@" "5 _?2?9]3/3/83]3/8]]]293310]]#"&'32>7!3>7X+Z{x3u31u53G2" H   is= /?$++$ %*)y\3s;V C@*\ ZO_@H @ Zd _/?2?3]3/+]3/10%3!!!!!66`Lm6@!  Ze?oZ _ ??39/]210]!!#".5!3267!:jda2]e65TdJZ65" 3a\\jk%% f@CZ     p T d  Ze P ` /  Zd _ ?33?2]]]9/_]]_]]_]]]10!!!!!!6"68JLVo@`\Z     p T d  Z;K[@H4Td Z d _  ?33/?22_]]]]]]3/+]9/_]]_]]_]]]3/10!!3!!!!!6t68@`L#`@? ZZg?_o@H_ 4    _ _??9/]]]]3/+]9/210]]#!!!3232>54.###Aґylȃ?T8Y?!$Da=?lu>Bv0N8:J*5k@H ZoZe!!@H!?!o!!!! Zd _ 4    _?3?39/]]]]2]]+9/]10]]#!!3232>54.##!!mAҒy6lȃ?T8Y?!$Da=?G5lu>Bv0N8:J*ymX@> Zg?_o Zd_ 4    _??9/]]]]2]10]]#!!3232>54.##mAҒy6lȃ?T8Y?!$Da=?lu>Bv0N8:J*H$g@F Zj [ g&&?&&&f%_oL;__??9/]]]]]]]2]2910]"'6632#".'3267!5!.XRbdUN:hb^0iY&/Rt8'07e賩l %(V\1.d@?[ %[g0/00 Z d/ _L; **_   _?]???]9/]]]]]]2]9/310#".'!!!!>3232>54.#"J瞑ۘU 6Z֋Jr#IoLNoH""GoMLpJ#ݩl\ÉܛTksDDssDDH|@' ZZ eo@%gL;`_  ?3?9/]]]]]]]33/83]29/]93]10]]!.54$!!!#"33,YG-z`iejt1>`ZJ1VdapVuDfj%';b@> % !-G W==7GV<2N(M#  H  H ?3++]3]?9/32]210]]]]46676673>32#"&&2>54.#"f?ؙfq"1qrj+GiH& 6La;\h8KsuI*E2(A.+M>, 1Tς )Qh<1 >zz׏HZFrTClK)&6;OuG^ (i  @: H%!GG W****%6FT)I8P%%%$OO??9/]]]9]2]3/9]10+]#!!24&##32>4##326jpo;_C%4p}]tAXX&?-ۼTT9Z)AT3H{Y2^EpB;"5f8f^.@ HFTN??3/+]10!!fk^^o^@ H &6f@0H Ue  IF@" H`/ I N  N ?22/3?3/]]]3/+]3/]9/]]]]93]]+]3+10%#!!!3>7!3WM:N^7U=( ٤opU}fDsH^@U@  @ OO  F     y ` V & 6  @ H@`/ @  ?33?339933333/833/83]]]3/8+]33/839/]_]]_]_]]]]]33]2210]]]]!!!!!!n<uu;?77FNs7@Y&*6*%)5)$(4(; 9 !%77'I2FW999_9 'V86O777}7H777-N$N??9/]]]]92]]3/99]10]]]]]]]2654&#"'>32#"&'532>54&##5^l$QRP%Z-an}JTwGr_2WA%>ÅE NZd49cH*f2C66  #IpMew &E~_8#" 1$DA^e@ H HI  H U@ HFHT@ H  H?22+?33+]22+]2210++!!46767!n;^N#r8AH*r5>A^?&6q&%+5+5^ >@%  0 FFT ??]33/]833310]]!!!!?Pu1^7^L^P@0 H6FIt3& FU N???/]9/]_]]]]10+!!##"'532>7!L9[bjD2,)#! yd L^ @O: 5   HU""""0""HT!@H HH H ?222++]?33++]32]]]293310]]]]]]!!#.'!!>7!"ٺ   qSiu7 6ofT^#6o_HG]j4o^ ?@'FU 0  F T NI ?2?39/]]2]210!!!!!l2^R3^fdsRZ^+@FU  FTN?3?]]10!!!Z^y^wsSfsF/^^@+vF 0  @ HN??23/]+]3/]]]]]]9/]10!!!5^yP^\f$/@s  + u f  H     9 *   %GW1111p1_1101GV0(** N'++N  ??32]?32]?]]]]]9/_]_]]_]]]]]33]_]_]2210_]]]]!.54>7!4.'>ԐJGՎՒLEד#B`=<`B$#B^;=^A"d \uuƓ]  ]uxǓY DtW8  :XrCCrW7 d 8Wt X^[o'^ B@+I F  0 @ ` p FT /?2?3]3/3/10%3!!!!!11^y{b^C@+ F U0FV O  ??39/]2]]2103267!!#".5@5KB1!KU_6Q[2^\H?( %-ZZ^ o@FI@6IfW= I FU P FT N?2?33]9/_]_]+_]]]]+]+]10!!!!!!!1X1X1^yyo^@ F  I  @II f W =   I    FI  PFT  N/?22?33]3/]]3/9/_]_]+_]]]]+]+]10%3!!!!!!!+1X1X1^yy)^L@0F_  FWo O NO ??9//]9/]2]10]]32#!!54&##32>4p} XX&?-^PQ]2yA:"6^ Y@: FP FU_o0F TO O ?3?39/2]]9/]]10]]32#!!4&##32>!!ч4p}J1%XXuy&?-2Q]2^A:"6^d^ @@) FW0F TO O ??9/2]]10]]32#!!4&##3264p} 1bXXL`Q]2^A:AJs!@ H H@G H  H H GW##/#O#o#O O   } H  NN??9/]]]]]/]]3]]++2910+++"&'53267!5!&#"'>32cDBQ\qi ?t0VJV^2fJC %".x&7ڤߒGjs&d@@  FO  !GW(/(O(_( F T' NI$M M????9/]]2]9/]310]]]]#".'#!!3>3232654&#"jDra}Q1Q}cjIcT`^TT`^T1ؔM:w{3^Rms;L؋^w@<   FUOo0FV@P O ??39/2/83]]]]2]99]]]]]10]]!!.54>3!!#33#"J!+L8 >p^w\J"2!:Qg?TX-bGN%0fD&Hj@ 9& *H%+55+55j4t@J F0U66066'!FT5!P'M******** ***M???99//]]]3322/2222]910"&'532>54&#"!#535!!!366320f"5","OJ;P0Ϝ1;1`S`4'W 'A3nn1^Y/ǡ*]'[WM/dkMe:f!&v@ &S %+5+5fs  H@ H H ""/"O"o"H@&HGV!O}HN N??9/]]]]]++2]]3/]3910+++".54>32&&#"!!3267qxIKvVKXBz7]dh b]WJDBٗ:'#$z}˃}-#%$bsVL&j&"%+55+55M^(@] %I%F}Vf$4` FW*/*O**** H$$O%N M%O???9/]/]]99//]]]]]2]]10]]]]!##"'532>7!32#4&##3269[bjD2,)#! 4q|XXuyL`yd LPQ]2`A:A^o@HF   FW/O_@H FT OO ?3?39/]]322]+]9/]]32]10]]32#!!!!!!4&##326?4q|I1=1%XXuyL`Q]23^RA:Aj$p@G FU&&0&& F  T% PM   ?3?99//]]]3322/2222]910!!4&#"!#535!!!36632jKN;P0Ϝ1;1`S`4Pyy1^Y/ǡ*]'[WM/dk!&v@  &= %+5+5P?&\6$&) %+5+5o^ z@ I   I @=I   I v U e  FU 0 ` FT N?3?3/]9/]_]]+_]_]++_]_]103!!!!!11^yo+4@ ^  p Zd_??/]?]]3/10!!!!!g 6R@I_@' H  0 P p FTN??3/]3/+]10!!!!!@^1js&:CR7&6%+5+5s!&ZvP@ 4&d4;2%+5+5jV&:jdRF&7U6%+55+55s&ZjC&4R2%+55+55s&<CR &%+5+5P!&\CY&$+ %+5+5R?/105!R\R?/105!R\R?/105!R\1N&@  /]//3210!5!5!5!NRR1 E@2/)9I v 3 C %     ?/3]]]]]2]]10'>73%'.46z|{8=|5 C@1/ y < L   *  &6F ?/3]2]]]]]10#>7'/37y}z8<|5? V@A/? y < L   *  &6F/?O @ H /+/]3]2]]]]]]10%#>7!'/36z|{8=}5 A@//)9Iv3C%  ?/3]]]]2]]10#.'7=4.'5|<8z}y7u x@Z)9I3Cv% )9I v 3 C   %   ?32/]3]]]]2]/3]]]]2]]10>73!%>73!(.4'.46z|{8=|56z|{8=|5u x@Z<Ly * &6F y < L   *  &6F ?32/3]2]]]]/]3]2]]]]]10#>7!#>7!'/3'/37y}z8<|57y}z8<|5? @_o 0y<L * &6FOo y < L   *  &6FO_o @ H /+32/]]3]2]]]]/]]3]2]]]]]]]10%#>7!#>7!'/3'/36z|{8=}56z|{8=}5{ <@'  0  0  /?22]]/]3210%!5!%77777LB_{V@:  0p 0  /22?22]/]322210%%!5'75!%%oK78L//L87K/-yxb)G@-`p/O_  `p0H/+]/]]]]]104>32#".b,Mi=;iN--Ni;=iM,VxL##LxVUxM$$Mxub9';j@8(2222222======`=O=0== `@ H-7#/3322/+]]]]]]]]]]3/]9/1074>32#".%4>32#".%4>32#".u0@%#?00?#%@0G0A%#?00?#%A0H0@%#?00?#%@0/A((A/-@**@-/A((A/-@**@-/A((A/-@**@? "-AL`@ U H: H^ HZ@ HP H?@ H5 H1 H H@+ H H H#8.VY @GPPW)......b?bHMBWERJ\+ =&3???3222?/]]9///]8]8]3]3]10++++++++++++#32654#"#".54>3232654#"#".54>3232654#"#".54>32+p-21/`2-)V[UW,(TZVX-;-12/a1-)V\TW,(TZVX-x-21/`2-)V[UW,(UZVX-J}|{}lv??vllu>>un}|{}lv??vllu>>u}|{}lv??vllu>>u BR^b+@?322]22310R5=wwR^b+@?322]22310'7b5#;w\\w9u&H*@11111`1O1/111]]]]]]]]]]w?//833/8210#+Jf:@%/O  0 ` p   ?3??2/]2]]104&#"#33663232#4"Ǣ "aDL@0Q<T32/#Z@4 n t?Oo t ??99//]]32/]3/3222910!!!#53!!!!ϕFRB,@k **+* * n'# k {   %!@`c @.!""%& &_"&&/&_&&"&"&(t?2]?99//]]32322/]]]3/]3399//]3332210]]]]]2&&#"!!!!!!5>7#535#5354>nP]Gu?CK>>*3(@.?o0"#M_qs0G4% &6I3ssqd.3y@] (&&$H/+/O/"/ / /-@' H5]%.P+**(++__??9/?9/33/2/]]23/+399//]]32/2]1032654&####!!2267#".5#57733#>wPk:٠3mͅ@+G$)vEDoO+X )humh`P?ur!Oa>lg/!BZ5@W&)4*33 !27n!(  *!!  ())/)) ) )3t/t?3?399//]3232/]3/322]]299]10]]]]]"!!!!3267#"'#53&&5465#53>32&&ij:rO<9^+vt[xfPbExɍ  }v"  {‡G*(#?#A& H, H H@ H  H H@3)CC@ H1>8);$$$5.! /??]?]/2+99//883310++++++##".54>3232654&#"".54>32&&#"3267+-TvJEuU/-SwKDsV0L7><66<>7dJ|Y12Z{I5j.7(L"E>=B8^'"aJW]11]WW]00]Wdeeddcc8,XYbW(kZZd)+5a@< ,,),,,I!!7?772'V'''HP&P33 /RP  ?3/?9/]3/2/]33]2]22/]10%2673#".5556674>324&#"66o3@)TbT`3&]31[*/[ZM{V.5fb )? %*KBcfai73dd  _V(-TxKc{f2)D1AJL?*-9¹+ H'@( H! H H.$4;  H^@ H;/;?; @C H  ^  ;K[ 7)1oFV4DT ?33]3/]/]?3]3/]22+]9/+]2+22210++++!!#!!3&'&&5!5!#".54>3232654&#"+J V-TwJEtU/-SwJDtU1K7><77<>7KK@<DF<@}JW^11^WW]00]Wdeeddcc ҹ @H9IYH6FV@gHH d0@P"""""@H"@ H @ H?333/+3333233/]++]]]2229///]]]]229]10++]+]+##5!###33#4>7#}4?<"^/## 7vfH"/>@"#1///?///) ?2?399//]]]3/]332210".54>32!32>7.#"yƆE,Lfv?qŽQ@MX.Jt^M"H$Sn;M]53WI<#^nc~\<Oу," 32&&#"66322>7&&#"b!Eisx^&6V|iiT c[GLN&QWm.8aN9N5-I:) .iѹQFuQ=e=)sy)+/^P_44)DYab+HP9@N&6Fv )9Iy @H@ H?o@ H_ ?3?99/+3]]++]2]93]3]10]]7!!.'!9^i    4:2 2:5 7H*@[e @ [d_/3?]10!!! 7})7 h@AdU1(  P ` p     ` _??9=/3/2]23]]3/]3/9/]]]]3]1055!!!)? H7Bo Xd?//105!Xd%N@ %(' H H/2++/9//3/39/993310]]]##5!3Elq{7#/>@ +$@ H( H( H@3 H'+7+G+(:8:H:&262F2)#9#I#2#:@@@@`@+@ H0&2# ?_5  /32/]392/+]9]]]]10++++]]#"&'#".54>326632267&&#""32>54.7.TtGX?;OFvV/.TvIR>;[GtT.-Q(&P2.!0PWQ&U/. !/C{]7VZM]0X}MFz[5P^PZ1X}BEDC&10%AH&20$LG@.% * |fW 0@ o  //]9/]]]]3210]]"#"&'532654>32&&3<6dV8a*#R);37dVmV#SHAd\,IEd\+(X]B'aa6@3333P3`3 303@3]]].5Xd@<        I I @  /]]233/]3]2/33/322/39910]]'7#5!7!5!3!!X;Pu\PT۪V٪X= g@D4 D d t     :J) 0@5 E  &  /?O/2/]3]]3/]3]]9=/33/32210]]35!5XH}X= g@D;Kk{    :J) 0@5E&/ ? O  /2/]3]]3/]3]]9=/33/33210]]35! 5XH}H>JXP N@    ? o @ H /3?39=/3/+]]9=/33310#3P=r=r!fg)&IL @////333P3]]]]]]55)&IO@/P]]]]]]5h3?J@1 H H      _  _/]3/]]3/]]/]]10++#".'!32>739sl12L5,I6"?P^42]S9H),G5^6@#  FU0` 'M?]?]]2/10]"&'532>5!f0f"6"-!1'W 'A3)Me:^ N@8<L* _G  O  _o _  /]3/]/]33]/]3]]]10>7!#^ R5MQP!DQ^; J@4<L* _G  O  `  /]3/]/]3]3/]3]]]10>7!#^ R5VMQP!ERN! N@8H  _  3C% O _ o  _/]3/]/]33]]]/]3]10!56673 R5MQP!DR)5 U H@1 H H H@H !!!/!_!!!! ??]//+10++++32654&#"#".54>32%-12..21-)U\TW,(TZVX-}|{{}lv??vllu>>u J \@<5E/_ 6F 2B@H ??39/332/+29/]33]22]10]##5!533!5467}} ᗗAͤ*]1 +-*T9" H@# H F   $$$/$_$$$$ @* H 5 E U & gwbr ?3?9/]]]]/+]9/33]3310++2#"&'532654&#"'!!66CtV1G27366322654&#"*R|RL_5J˂CF}dH YJt;><9%1  /mDrS/0ZQom'3AR5+/G?6D'7);J9@%/_?2?/]]9/10!5!TMJ)-5'4B@ % H H H@ H@@88..(( @U H H #@.DDD/D_DDDD8##( 2I222;;G;;;G++H55?]?]9/]]]]99/]3/]3/99++]]]]10++++2#".54>7.54>32654&''">54&ApT0'4"?11Z~MTW-+:.#1Vr7:9;<@9 05u+-4&  *9U8%>2()4B*9bG(&E`9*B4(+5>%8T9n-99-*;;/)2 !/+9$4A@*1666/6_6666( @H+% ??9//+3]210#"&'532>7##".54>32%"32>54.*lJ13SlA %0=&<`D$.VzLN]35B8;/-3`V$AY5$%HhBCpR.4fGA7A&6*T #'+/37;?CGS_ox@Y4, 8WQzpotgdd~kpQQQQokkoQ]O_D($ ]PK`KKKA=1 *BF>&2oygppz`zoTHHpooaoo@% Hoo`ZNNx`/`?`o```, 95!/^]3333/33339/]333/33/+]]3/339/333/3/3/3/3/33333/]3/33333/]39///]333/33333/3/3/310!#%5!#533!5353!5!!5!5!#3#35!#35!35!#35#3#3"&54672'2654&#"32##32654&##32654&#532653#"T/0momImmmm0oowoooommH??HEBBmp--83m^{B.$)0;J1%&4 %1}h_=0oo/mmmmmmoo;mmJoooo/yhhg^^ff^^gCS1D D:QYb" "+% *f$2r^dT#/P@(##$ *0*@***O$$$ ##0---''/3/33/3/]3//3/3/33/]3/]3/310 54676654.#"663232654&#"TV!LcM1[Q+ZWR"RD~8?>'REJGFDGGDFGVW/,>:LYEkJ'#".:/1DA5yP;>II>@II!&7L@@0x%+]]]55)`) OY@59GMQ`QFC1H$M+ >NM++p++++6NH6M??99//]]32//]3/]3210.#"#".54654&#"'66323265<&'.54>323 )9I)2;"N~:]qZ! 1H;[Zg(?-~D/beLU\/89-WD+]]38]w?5i+* "4^X?G 8*XXHzW1W׀ @"""" "0""   ?@5  ) Y    Z0&Ff ` ???39]]/]2/]]]]]93/8]3]]]]]]]10>7>32&&#"!!T1233>M1+F" %AJIBPTByl+&:'  $ {Z/3^ :@R222H1I111111*1z111!H 0<<0<@<`55!326?bK5 6Jb?ll6#$7l,U^*8!!8*^T7N00N7F|a]f]a|†F[`^]!@]<<]@!u&0vT@ &l% %+5+5!&Pv@ +&_+2 !%+5+53&$[H@ &'!%+55+55Vu&D[@ >'9/ %+55+55r&2R\:@CKKPKKK@KK %M_MOM]]]+]]]]]55?55XN@ H  H H@ HH_@ H @HP`@HH/+]]+]+]]/+]+10++++#".54>324&#"326N'E\68[A$$A[85\E(6**600*68Y>!!=X87X=!!=W8-33--44yh+#5?@ H# H###O_/]99///+2/+]104>7#".>7!#y FoPIE%-%?B4&Z07="D9+ J%%-"4CLRP""MPP$)&I'IL/H@2MMMM0MMII`IPIII`0]]]]5]]]]]55]]]]]])&I'IO/F@1999909955`5P555`0]]]]5]]]]]5]]]]]]w1D@'[([`p3[ f2-_#_??33]]3/3301#"&&546632665!32>54.#"OOOQ++-2HaA> (S~WYQ''Q~XWS(ݩllkjacTiNsDDssDDf ,R@  G'G@ H.!G V-*M$M??33+]3/3301]]]#".54>32>5!32654&#"dGwoLGxkB&8%-/Q|^:^ji^^ki]1ؔMM،ؓLEE 4J]6KnS5!>5!{)ER\0R`41IP

32RP K6*"(C (.3NcG 3% " oR%} //014>32#".-<#"<--<"#<-+:"":+*9##9s&(CR &%+5+5s&ChR&$ %+5+5fD!&HC*&/6%+5+5!&C& %+5+5wK+**@B H**@ H@Z5= === G\gM5\ fL>> @==B:_++0`%*%%` ?3323?332239/9/]]93/+33/+]301"'>32#"&'#"&&546632.#"3267!32>54.81,lLSV(ӐJGoJInGJӉ(VTKl+28=dG&*S}T-L"6BdT}S)&Gc (bwHKKHw!b( ;vuyF'tEFyuv;^$@a$"#z##i#;#K#[##$$$$G!"( ("" ""# F&G*### #!$""$?2223]3?3399]]]/9/9]]]]9]3333]]01]]]]]]!!3>7!3>5! !u@  d9 3I-3%]x텍^9{1:;;l>?;M}#<@Z%Z #_/`_ ?/32/]/3229/0132#!!5!5!!32>54.##5mǃ?Aґy5'T8Z?!$Da=@dBvalu>d0N8:J*'C@$F!F NOOO ??39/]2/3229/0132#!!5!5!!4&##32>34p} 1):YX&?.yˣQ]2yA:"6-f@: $#/,[Zd.$'_# _,L; _ ?32??9/]]]]]32?3222/32299//01!3267#".'#!!3>32&&#"!3[TYi0^bg;Y 6kmddRPK|\: &wTi<(% \ÆۜU70':-U}Qs)_@4&6G &&+ FNNH  '&&#N?29??9/]32?29/222/99//3]2]01"$'#!!3>32&&#"!!32671 S~]2^VJV0t?X\i!7K.QBD3^Ri-&snEa=."%  @: I<)  2%  @6 H H( H  ^F  `   ?22??39/]322//9/]]]93]+3+]3]]]99}3]]]]99901!#!#!!3'.'X;={  wwDdZR[Z"!Z]R^ G@   9       j I Y ;   *   &FVf4%      @Q H% 5    HXJ(8I P  @ P `   ?33?39/]3223//9/]93]]]+]]3]]+]]]]]3]]]]]]]qq9}3]]]]]]]]qqq901#!#!!!3'.'%/2oLZZ^uC ALMLNB " @U ] G D&XY;*$ !"  "!  5 $      Z^  d# `_P`  ?333???3/399//]32322/]9/]93322/]}3]]]]93]]]9]]]]]]]01!!!#!#!!!!3'.'p{,-6yCDwww<Rcd#75!!.'!!)@Pb=53^RDjj {'&6$?$7()/dn@DGZM0M0?` jjfT\p@gff[[$\?M`;NNN D`0:`/''[ZZW` ggaj` ?333/23?3/329/]9/33/32/3/93399//2012&&#"#"32>32.#"#".54>32654.##532>54&#"'>7.'53>-8 ./Y&NyS+3[}K\c4J֌CS,7H2RHB!BG "(,Vdo9XW++f9j]whpW#vsdK'OWa78953b632&&#"#"32>32.#"#".54>32654&##5^l$QRP%Z6sE0-*3b6;IX7-7 .&M 4YB%r_2WA%>ÅE~_8 $0(  ,PqFN}Y0C>DAmDuw)5@%[g+$[ f*/+?+_$$__??9/]2201#"&&5466322>7!"!.OOOOpMtQ/ j 1RtNIpR3  2Opݩllkkh4aZZa4/ZRRZ/fds!C@(  GW#G V"_#OMM??9/]2201]]]]#".54>32267!"!&&dGwoLGxoLW^ {^VV^ _1ؔMM،ؓLL%ttttqppqT <@!  ) _?3??32/3/9933301]]]"!!>7>32&&,#99    =RlKB_50G.s-LFE'&IHK)bi8 fv@ H9@@HW&Fg  GWF M??32?3/3/9333301]]]]]]]]]]+]]]!3667>32&&#"!?\6MiHU%("^A~33wA@OxQ)  #Ts&vR!&8/%+55+55!&v&5,%+55+55w 'F@p4444Y4i4y4K4944*4 4))))w)f)E)U)6)%)))F6--(5<<)(([5[ fG45-FF(=@M<94(#__???3?3293/39/3/33/93301]]]]]]]]]]]]]]]]]]]]#"&&54663232>54.#"!3>7!#"&'532>77XEEEE^GuWYuGFuXWvH M OF>ա5K@#0D1"ݩllkksDDssDD4v/8:9u /B)8fs >@o,,,i,y,X,),!!!!!e!u!V!G!&!  >%% -44!I Y i   G -GV?,-58M41>&,  MM???3?3?32/39/2/]]33/9301]]]]]]]]]]]]]]]]]32654&#"#".54>32!3>7!#"&'532>77^ji^^ki]GwoLGxoL M OF>ա5K@#0D1"1ؔMM،ؓLL4v/8:9u /B)8w1:i@>8 2*^ $ /[g<[f;8:5J55552_E'6''''$*_ ?32]]]?3]]3932233301#"'.54>766326632>54&'#"&'CюG5pҊCCԐD42DҊD?`A?+(?A_>wB+-Ayݘ{9:s{zB,,Bz_yS**Sy_(&%%&(f=_@(; 3+I % .GW? GV>8@ H83;M+(@ H(%N ?3+3?32+932233301#"&'.54>7663266326654.'#"&'=sh E36D bt@=sj A/+A ewB"5%3313KF"4#(97E@1yY5:;6XyzX/##/Xz>kV='+-'=hS<&8/"wIbx@fs/s?shhnccssVWKW' &P&&&;;;WWE\gz1\fynvih#vvWS]bLL?WOWWWWWW#'',`&& #@;6_?3322?3332233/]q3/323/299/933/]33/]333/]2/]10"'6632#"&'#"&&546632.#"32>732>54.#".#"#54>3235>54.5463281,X,%-%NGNT />bwNKKNw!b>/ ;vuyG!9M,,M9!Gyuv;A3;1]k6&-&3VA'V 5:ZfRIdz@.u/u?ujjpeuuVWKKW455/55555   P  @JH E =WW*G=W|GV{pxkj xxWS_JKK?WOWOWWWWWWW 4/N5 8 % NEB?2222?3332233/]q3/323/99/933/+]q33/]q33/3/2/]10".54>32.#"326732>54.#"'6632#"&'#".#"#54>3235>54.54632\xCJfM,%-%NGNTGߗڃ7 'S[aX)N92$)Xa[S' 7ڤߒGB.)4;2>W<#&-&3V@'V 4:YwBHV@`'&&;Z::D\RSSTNOOQPMKLLPTUJ/JJJU UU9<<9UgX1\fWJUUVNRPLT#::#6'',`&&#<99?6_?33223?33239/222239///]3/]933333339/93/33/301"'6632#"&'#"&&546632.#"3267!32>54.#'##'##'581,XbwNKKNw!b>/ ;vuyF+#1Fyuv;oYggggY$2-@J"9"+"" "I* H #""!$$$$$$$$$r$d$S$4$D$"$$$$3.//0*++-,)'((,01&/&&&11=114&112*.,(0##XIn#[#*#:#J## # #""?223?3399]_]]]_]+]22223/3299//]]993/]933333333]]3]]]]]]]]]]]]qq3]3399]]]]]]]]]01!!3>7!3>5! !#'##'##'5u@  d9 3I-3%]x텍#R8127117P^9{1:;;l>?;M}XffffXw 9@Z   "[f!_   _ ?32?3/2]29/01&&546$32&&#"3267!_NZmddRPY]0+Y`ABlo70':Esu}Afs?@$F [ k O +  GVM M ?32?32]]]29/01.54>32&&#"3267!u>KvVKXBz7odudKg/KΌ:*&% hy @E ? 0         /33/33/3/33/3/9939939999/33/33/]322/]32/93901%'%7%7%LG㴁FGJ{J;{Z}9IĤ{{@  //3/01#"&5463!6632#608349708569+3G88=-1=69H !@    /23/3/3/]102>32#&&#"##5Nwp:-cQ5 +.5=G[tJ&-%6k]1;4X8@"s d E U   0 /3/]9/]]]]/014632.TNGN%-%,=qU3IY:5 V'@VX4@@ H  h   /3/]9/]]]+015>54.546322Vp>,%-%NGNT3V@'V 5:Y)';Ocw|@;iuuAM%aUU99-}x~M(<73>73#.'5.'5>7''>7.'7.'7B  #a   #a &UWW'*][W%Z'UWV'*][W%#OTV(E%ONIbJ"PTV(E%ONIb('%C343b)'$C442b1'UWV'*][W%&UWW'*][W%!  #a   #a E)'%D342b#)'%D342bB#OTU(F%ONIbI"PTU(F%ONIbV1@UdtCS&6  y j [ J 9 *   [1 ^  33@ H'&&^d2  _1',! ?332?3/?323/3+]2]2223/310]]]]]]]]]]]]]]]]]]!3!!!!46767#!#".'!32>7RrNN9sl12L5,H7"L>CC JLGTL9ALMP^42]S9H),G5o?-@osdBR#3l|$IK<. H -#"".   /HT. N-##(?23/2?3/?32]229/33/]310_]]_]]+_]]]]]]]]]]]!!!!46767!#".'!32>7n+݉; 9sl12L5,H6#^N#r8AH*r5>A^P^42]S9H),G5/m#^@7Z 8 X ,   %?%O%Zd$#___??99//32322]]]]]9/103#32#!#535!32>54.##lȃ?AҒy6T8Y?!$Da=?Bvalu>!H0N8:J*dP@-F FTPOO_oO??99//]322229/0135!!!32#!#4&##3261;4p} /XXL`5?Q]2oA:Am"@UZ$$?$_$$$  Zd#$0% _ "_ ??9/]]33222/]]3]3/322/]]]3]3/9939910]'##!!23227'7654&##m.G3Xs-c9Gͅ@=  9R)wO:peW"}p ?uRou5Zmhws#9@N3%52!3 EU547GW;4f44,3<333* F T:$M! 344/M ?2/322/3???9922222/]3]]3/99]39910]]]]".'#!33>32'"3227'7654&7WD4+6GZ7Wf8G>V\4z3G,,I6X=U(3#7;J"<-J؎K{p%JqK!Q~U,oXMm/ >@"  Z d _ _??9/32]229/]01!!!!#53?ʉTd^ G@*/  F /?T N#  ??9/]32]229/]01!!!!#53=ω^^'->@ '\/ Zd."__  _??9//322/29/01"!!!6632#".'32>54.\8FAw1BuW3Zk7XLE#?~IBoO-%@S[^oAhȁS  9eSYX6  L^(>@ H*!FT)M$$ M M/32??9/2/29/01%#"&'32>54.#"!!!6632LOeA~A5993XA& ChH)>"G ePD׋C #LwTDqP,^IV@` 6 f v   % Yi(  ]Y6)  \     _?33?3/339333/]]3/]33333/39/]]]332210]]]]]]]!!!!!#!!>?!@=70ը?@<<BLo^@Q9* 6%@VvHyyH6' / I_@ H N  ?33?3/339333/+]]3/]33333/39/]]]]]33]22]]10]]]]]]!!3!#!!!n<uu;?77F^&KC0 %+55Ns&BIA'%+55VV@.\& Z d   _ ?33?39333223]]3/333/301!!#!!7!uմt6zNX- L`V@mo^a@;  t e F  HT  I       N??3/?393/]]3/3332201]]]]]!!!!3!Hto;7^%@=++!- K< %Z @b u` dL; |XI]O=@#HSc1A   ?2?3?399//93333]]+]]]q3]]]+]]]]]]]]q/3/3]]]]9/]]322]23]]]]]01]]]]]]]]]]!!#'!!73!†t6|X-`V@b)m^@}j]I  } i ] K   DH      5 T  | m [ < L +     ra3CS! /?  ?2?399//]]]]9333]]]]]]]]33]]]]]]]]/9/]]3]]q22]]]]q23]]]]]]3/3]]]]]]]10!737!!#'!T};}T^{< dy@f  v g &     Z/?  L = +    _%5E   ?3?39/9]3233]3/3/3]]]]]29/]222]3]]]]]]]3]0135!3#7!!!#6zNX-tʉ/m`V1@V)   vUD6'F?H IT  P ??9/32?39333+]222/]223]]]]]]]3]3/3]]1035!!!37!!!#1;pXlwϜsTRB@!u  Z   _?2?39333/223]/3/3301!7!!!!{{NX-u@m`VR^ @@#F5 H    N?2?393/]22]]]33/301!!!!!o;u^7yV?Y@6 Z\` Z d_ L ;      _??3/?39/]]]]]2]]210!!!!!!!!+65 Lw=o^\@9 FI` FT NI   ?2??3/9/]]2]]]]210!!!!!!!l2^R3^Z R@3 Zd Z`_ L ;     ?3?39/]]]]]/]]]2210!!!!!!!Z6{Lw=^ F@+F0 F T NI  ?3?39/]]2]210!!!!!!l^R3^H/J@((Z))-\ g1?1,Z-d0'$_)+_.,)_/32?3?9/32]99//2106632#".'32>54.#"!!!!K8CuW3Zk7XMD$?IBoO-%@S[^+ K&84# AhȁS  9eSYX6 L ^)B@$"FHW+o+FT*M%%N M/?3?9/]99//210%#"&'32>54.##!!!!6632OeA~A6993XA& ChH&ePD׋C #LwTDqP,y^IwDT@16PP;%%5M&MM^;;;)E9EE^ gV.Z fUH`@@ H@@&)_% P3_`?33/22?329/+]2/]9/]]]2/9333013267#"'#"&&546632&&#"3267.54>324&#">{(:C9%?*//2|32&&#"3267.546324&#"66'46M-G8+hHpF=ƈ985DM&7!mP   Nm^51..15?@s0uTdE&6? ZjzI:)  Z,  0   _ ?3?9/32333/]]32/]9/2]]]]]]]]]]2]]]]]]]]]]10!!!!!!5!VND)+DP\Z)Z^  @^ H% 5    zkJ)9 D%5 FN ??39/332/]3/]]39/]]]2]]]]]]]]2]]+]01!!!!5!!3>7!mP   Nm^51..15?V{_@2    \     ?3/3?393]]3]]3/333/3/3/39333301!!#!!!`ծcV N^ L)+ o^@m &68)& )  I y j 8 X  tUeF7 N ?3?3/3933]]]]]]3]]]]/3/3]]33/3/3]]93]]]3]]33]01!!!!#!ZZ;#Pj)VG@*Z? o ?  \ ZP_  _ ?2/2?32/]/]/]q01!!!!!!!!5+NTL/o^P@4 FO_?O_ I0NN ?3/2?32/]]q//01#!!!!!#5\X1F^lyymV?@#ZZ/\ __?3/?39/32/]]]2/01!!!#".5!3267!+:jda2]e65TdJZ6 L5" 3a\\jk%%{ou^KF@ H?  I @ H O N ?2?3/9/32/+]2/+013267!!!!#".5@5KB1!KU_6Q[2^\H?( %-ZZm`@5 v"2Ze5 &  Z _  ?3?93/2/23333/]]29/]]3201#".5!33667!!#X1/]e65Rd*Y361Y,3a\\jkH J5 {b^j@=0)FU!v 5 &  F@O  ?3?9/3/2/23333/]]]]]29/]3201#".5!333667!!#-(Q[21@5 }"C"1C%}Z-ZZ\H? !*@Z Zd_ ??39/32201!>32!4&#"!6:jda2]e6TdIZ" 2b\jk$&q^1@FU F TO   ?2?9/]32201!4&#"!!>32V@5KB1!KU_6Q[2H?( ^D%-ZZ`5@`@:<[////B`B;1[%O$4D^1_;$$ 6_*_ ?32?9/32/]]3/]32]]]2/10%2>7#".'#".5467333>32!"!4.?Nu#*hge ?Q{S)  %)dH'4]-FsV3"N 093'\$C`=;h*"% ݚRo߲G\e6-V~QP}W.#s.7q@G3H  W992 F%+++++u+P+`+D+5+'++$ P2'N/O??329/32/]]]]]]]]q]22]2/10>32!3267#".'".546733%"!.NUdo}CV%C_=eW(QZh>rX MzT- ,4Rk/Hqq9Cz@gG&,, =}6U<-X 6%)rz3V?$V8C@O \ ?[2222E`E"$"4"D"""^>4[(O4_'>>>>>>9_-`  ?3/3?9/qr32/33/]32]]2]]]2/9/10%2>7!.'#".5467333>32!"!4.?Yl "RcwHvN ?Q{S)  %)dH'4]-FsV3"N"18-'bm׀$C`=;h*"% ݚRo߲G\e6-V~QP}W.o#s/8@QI 4H  W::3 F  %,,,,,u,P,`,D,5,',,% P(33N0O??33/329/32/]]]]]]]]q]22]2/9/10>32!3267!.'".546733%"!.NUdo}CV%C_=eW=PQc<MzT- ,4Rk/Hqq9Cz@gG&,, $Oyg6U<-X 6%)rz3V?$B,9&6NR& %+5+5?&6&%+5+5\-I@&  '\/ Zd. ` "_?3/32?39/322/223/301]"!!7!32#".'32>54.#U+6zNX 9vZ6Zk7XLE#?HBoO-%@S[^ @P6\‚S  9eSYX6  ^)W@1%&%f%%#$$H+0+%"FT*"%M#  M?3/32?39/322/22]3/310]]]%#"&'32>54.#"!!!OeA~A6993XA& ChH/201uXK_JD׋C #LwTDqP, ^ HV9#@  H  @C H^ H """""@"""Z[_%0%%_"__?3/?32?/]]29/]]]3]++]2]+10!!!!#"&'532>7>7!M !:Z\*J 4,$ %)J L^M`g5 DrV2%ow^[@8It3&HFNM N?3/?32?/]]9/]_]]]10%!!!##"'532>7!L+މ9[bjD2,)#! yd LX@4ZeZd_L; _?3/32?39/]]]]]]]2/2201%#"&'32>5!!!!!K~dG ?FN.AdD#65ZݠY  4_S= o^f@A*JJ(FU0FTM NI?2?9/]]3/322/2]210]]]]]!!#".'32>7!!l2Kk&C>; 6w41P:"^RƂA  FmN3^Vbr@H[ Z@` Z d_ L ;     _  ?3/3?39/]]]]]2]]]3/]3210!!!!!!!!N65 Lw=o^]@9 FH 0` FT NI ?2?3/39/]]2]q]2210!!!!!!!l2+݊^R3^mV:@Z\eZ_ _?3/?39/32/201!!!3#".5!3267!:jda2]e65TdJZ6V+" 3a\\jk%%{ob^W@7F I U0FVO_oN ?2?3/9/]32]]2103267!!!35#".5@5KB1!KU_6Q[2^\H?( op%-ZZV!@G!6!!!'! H @? HI; )][! _##  ^ d"  _  ?3/323?333222]]9332210]]]++]]]!#!!3!!!!4>767# <PM{\V%NLFX^TLBJL$T[o#^$@Y#:# #5     #HH&&&&&0&`&HT%@H H#H@ H N?33/33++]?33++]32]]]]2293310]]]]]]%!!!#.'!!>7!+މ"ٺ   qSiu7 6ofT^#6o_HG]j4B,3&$6LR@ &!%+5+5VE?&D6@ 4&59/ %+5+53V&$jLR@ &&5%+55+55V&Dj@ >&+/M %+55+55Vul7&(6R& %+5+5fL?&H6@ /&4*%+5+5 +P@&[g-`----'[`p@H'_ !__ ?32?9//+]3/]210">32#"&&55!.2>7!Xl *ggYVH4^-FtU3l"N"28 6,l髮ho!H\e6#,V~QP}W-fDs)=@"GW++0+$$HV*P O$N% ?32?9/3/]]210%267!2#".55!.#"5>FQk{0H xʒQJro}C%C_=3[VT,(QZhqz3V?#FבܓICzAfG& ! V&jR;&,J%+55+55fD&j@ 9&*H%+55+559V&jNR@ !&0 %+55+55&j@ !&0%+55+55^V&jRI&״:X0 %+55+55N&jG&8V'%+55+559$A@ $$ Z &`$$`?33?329/2/3/3/39/310!!#"&'32>54.##9mhs>EٓvZ-dda+VrD%SbhZ\fCo\`xC'($ :Q0-I39^#I@&## G %O##M?33?329/2/3/3/39/310]]!5!#"'32>54.##nj|k0Eٓ-dda+VrD!PghZ \]cMP$ )G]38dK,&MR@ & %+5+5&M@ &%+5+5V&jR@ '&6 %+55+55&ju@ #&2%+55+55wV&2jR7&(F %+55+55fd&Rj/& > %+55+55w)U@7%[g+/+?+$[ f*H_$$d$K$9$&$$$$__??9/]]]]]]]2]210#"&&5466322>7!"!.OOOOpMtQ/ j 1RtNIpR3  2Opݩllkkh4aZZa4/ZRRZ/fds!o@L  GW#_#G V"HO{&69(M6M?]]?]]9/]]]]2]210]]]]#".54>32267!"!&&dGwoLGxoLW^ {^VV^ _1ؔMM،ؓLL%ttttqppqwV&~jR9&*H %+55+55fd&j@ 1&"@ %+55+55HV&jR4&Ǵ%C %+55+55J&jv1&"@%+55+55&MFR@ $& "#%+5+5P&\M@ !&  %+5+5V&j;R@ 1&"@%+55+55P&\j@ .& = %+55+55s&SR@ "&k"9%+55+55P!&\S=@ &e6 %+55+55mV&jPR@ '&6 %+55+55{b&j)@ '& 6 %+55+55V -@ \Zd __?3/?3/]013!!!!F+RLo^ 2@ H IFT MN?3/?3/+013!!!!>^y5V&j%R/& >%+55+55&j@ +& : %+55+55/& <5^& <5q&;H%+]5 ^&[ %+]5@!$    sf@ Hz i Z 9 I +    z[k:J+ veTE$4    + `poI_  ?3?39/33]22]]3/]3]3/]3/3]/93]]]]]]3]]]]]33]]]]]]]3+]]3/3]3]3/]]10!!#5!!!3}mV Nj)jN X^@    @ H @ H    f E U 4 %    H H   % E U  Y *J / N | ?3?39/]]3322]/3/3/3/393]]]]3]]]33++]]3]]]]]]]]]3/+]33/+]310]]]]#53!!3#!!5ZZ-PJ=j\3@e?_Zf__ ??9/]2104>33!!".#"33\?ȉl5y҉A?=aD$!?Y8TavB1J>u**J:8N0f=G\h#2I@' Z22\4**Zf3/_%_ _??9/3/32]9/39014>33!3265!#".'#".#"3265\?ȉl5ELNE1@vg2cWE*vpo8?=aD$+<$HZa}H1BAfq-ib.$4?J>u=2Q>5K0?=f/@F@%+H55F B>GVA;M +0MM&&?22?2?9/9/33301".54>323&'&&5!32655!#".''2>754.#"VuC9iX6ZH9 1JNNE.?ug=_L=LX[$6L/.N;`Z[J؎ٓJ-;#'("M!fiKFfqib.!4$2%%KpK!Q~U,N;I@&\)) Z2\e=12""21,`7"`##27_??39/392/3/39/33/013265!#"&54.##532>54&#"'>320UtC :/OE1@wg%Tb\{Ibi0SG;)ctMl}EoLy[=%E5fq-ib.-O:!!9L+NX#4'/YN3s7E@$IF00 #F%U966 6O$77 M+ N ?32?9/39/33/9/33/102654&#"'>3232655!#".54.##5_l$PRP%Z-an}IUwGq_r{IONE-?ugfxC%Ea;2C66  #IpMew pa9Afqib.%IoI5M2V!/A@"%&&Z \ \ % `&+` _?3/?9?32/2/2/3/301!!!4.##532>54&#"'>320UtC+%Tb\{Ibi0SG;)ctMl}EoLy[=L-O:!!9L+NX#4'/YNos+J@)I%F #I!! !!** *O++ N%""% N ?32?3/9/9/33//]3/2012654&#"'>32!!!4&##5_l$PRP%Z-an}IUwGq_2WA%ׅ2C66  #IpMew &gFNID1b@8 ++20 "^0Z00000"\3"_0#&_"_?332?9//99//]]]9]9]103265!#".5!#"&'532>7>7!DMNE2@wgdzC !:Z\*J 4,$ %)JwHCfq-ib.+_k=^M`g5 DrV2%^(X@3I'F5' '''F**N' MM?332?//]]99//]]]]1032655!#".5##"'532>7!LINOE-?ugexC9[bjD2,)#! yJCfqib.+_ld LmV@2Z\eZd_L;_???39/9/]]]]]29/3103265!#".'!!!!!EONE2@wgdyC65}KFfq-ib.+_j=^C@&F F UFN IM?2??9/]]3/29/310!!32655!#".'5!!l2HMOE-?ugdyC^RHCfqib.+_kV3^w*C@$** )[g,[ f+_*_/$_??39/]23/39/01!#"$&546$32.#"32>'!?ﯣ_cck"O[h:hd0+\eXrC5{nai32.#"32>5!=2RzlђNOیqM\EOT(TnA:^DD^:]NnO,JՌەL1%  3\LHwW0%=M()%:@ \ ZA__??9/2/]]/]103265!#".5!!!ENOE1@wgdyC}KFfq-ib.+_j?/^7@ F UbF NM??2//]]/]10!32655!#".'!5IONE-?ugeyC^KFfqib.+_kX9]@5'' ;4Z/\//:&!_*4`K:'* _ ?32?39/]]]q92]2/222/2/104>32&&#"33#"32>7#".54>75.HrW{l4Ldtv#Wpiw]j9:xsi+W욌֒J4c\K}[3`Oa6$7%6AQK-F12K5ga $&)@t`IwY9  9XxNs7M@+_+94I!!FO77|777 ,/N+& N?32?329/]]9/23/2/]2/10#"32>7#".54>75&&54>32&&#"3 v8Y>=obS H͂}:'Ge=liI}^6nh_(QCW.K4r{ID, #*/UzK>ZA( dPoF ( 'B7&//%+55s^&J&&%+55R3&$g@ '!%+5+5VRu&Dg@ 4',/9 %+5+53&$fR@&&&%+]5+5V&Df@3&>@>/ %+]5+53&$wR@ &2%+55+55V&Dw@ /&7J %+55+553&$xR#&o2"%+55+55&Dx;&J: %+55+553J&$yR@ /&d7%+55+55V&Dy@ G&O/ %+55+553b&$zR@ 5&=5%+55+55V&Dz@ M&"UM %+55+55R3s&$'KNRg"@1'&,6%*%+5+5+5+5VR &D&Kg"@I'/&,DN %$6B %+5+5+5+53&${R@ (&-#%+55+55V&D{@ @&BE; %+55+553&$|R@ 3&8.%+55+55V&D|@ K&/PF %+55+553X&$}R@ @&E;%+55+55V&D}@ X&6]S %+55+553b&$~R@ '&,"%+55+55V&D~@ ?&/D: %+55+55R3}&$'NLRg"@2'&-7%!%+5+5+5+5VR+&D'gN "@H&4'/MC %,/9 %+5+5+5+5R&(g' %+5+5fRDs&Hg@ /'*4%+5+5&(fR@ & %+5+5fD&Hf@ .&(9*%+5+5`&(RR@ &%+5+5fD&H&R!R"@I&-& JX%.<%+5+5+5+5&(wR@  &'%+55+55f&Hw@ *&2E%+55+55&(xR&}'%+55+55D&Hx6&xE5%+55+55J&(yR@ $&r, %+55+55f&Hy@ B&mJ*%+55+55b&(zR@ *&2*%+55+55fD&Hz@ H& PH%+55+55R s&('KRg&@ &' &@ !+%%+5+5+5+5fTD!&H&Kg"@D'*&?I% 1=%+5+5+5+5B&,fR@ & %+5+5o6&f@ &%+5+5BR&,g' %+5+5R&Lg'" %+5+5wR&2g@ -'(2 %+5+5fRds&Rg%' * %+5+5w&2fbR@ ,&7( %+5+5fd&Rf@ $&"/  %+5+5w&2wXR@ (&0C %+55+55f&Rw@  &(; %+55+55b&2xVR4&bC3 %+55+55d&Rx,&j;+ %+55+55wJ&2yXR@ @&WH( %+55+55f&Ry@ 8&_@  %+55+55wb&2zTRF&NF %+55+55fd&Rz>&F> %+55+55wRs&2'gKR&@ <&-'@ CO %(2 %+5+5+5+5fRd!&R'gK(@ 4&%';G % * %+5+5+5+5ws&_vR2&Դ29 %+5+5f!&`vf-4 %+55ws&_CTR2&$7> %+5+5f!&`C29 %+55w&_ffR6&A2 %+5+5f&`f1&u<- %+5+5w`&_RR5&6D %+5+5f&`R1&a1? %+5+5wR&_g7'2< %+5+5fR&`g2'd-7 %+5+5R &8g^@ '" %+5+5Rd^&Xg@  '% %+5+5 &8f1R@ &' %+5+5d&Xf@ &* %+5+5s&avR#&z#*%+5+55!&bv7&h(/ !%+5+5s&aC=R#&ɴ(/%+5+55!&bC-4 !%+55&af1R'&+2#%+5+55&bf-&*7( !%+5+5`&aRR&&'5%+5+55&bR1,&,: !%+5+5R&ag^('#-%+5+5R5&bg-'(2 !%+5+5R&<g@ ' %+5+5P^&\g c) %+55&<fR@  & %+5+5P&\fu@ #& . %+5+5`&<RR@  & %+5+5P&\R@ "&#1 %+5+5f&B:9%+55!>@# /?@H/22/3/+]3/993/9901.'5!!.'5!F;>?6* -*/0:?>6* -*/038;81"QQL38;81"QQL-9 J@(@ O _  @H    @/22/3/9333/+]9901#&&'#5>7!'>73#3l46j3886;697Y$" -{;"T00T"EIK""KIE+07!7!#&&'#7#.'53/886<6873j65k3X><7 !$EIK""KIE"T00T"047!70+-,a@4@ H @o''&  & /329/322/3/9333/]9/+3201#'>54&#"56632#&&'#5>7!!B; #/ %+' 1 ^qȢ3l46j3886;697`;D =t  H)"T00T"EIK""KIE10b@3-,""& & %&@H  ",&/322/3+22/]/3/3/3/993393310".#"#>3232>73#&&'#5>7!7$KHC(+ q2F.%MHBq2F>t56w;>?;0<!12XA&!1XB&I00I?BF"E;1 ?@"     @/2/]/2/]993/016673#%#".'332>77@2794\UYY.sX*I7$*l3774NK|Y20X}MWS,?(1 !=@! @!!//]2/3/2/]9901#.'53%32>73#".'872@$7J*+J8".YXV\44773l*3(?,*@+M}X02Y|K1.e@:@ H @.#$$.#.)@)/]29/22/3/9/9/+]3201#'>54#"5663232>73#".'1&k #;* 4Vd$7J*+J8".YXV\4- )n  )hC(?,*@+M}X02Y|K13[@2$)$)/ !!.// ....$)!@ H! //2+2/3/]/3/3/3/99331032>73#".'%".#"#663232>73$7J*+J8".YXV\4$KHCq b\%MHBq2F"1  1%CnN*,OmA1 dy!1Q;  "@ /3/32/3]014&'3#"&'5326NF&A1#A]92J ? #-4mB8?H+3T="  ()/@ H M/22//01".'532>5!31,6","''U  'A3TMe:)@ H M/22//01".'532>5!31,6","''U  'A3V}Me:J4 4>BM \hNv g .?*mM h   4 1 ,O {  (3 [ 8) \a \ TDigitized data copyright 2007, Google Corporation.Droid SansBoldAscender - Droid Sans BoldVersion 1.00DroidSans-BoldDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.Licensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0Digitized data copyright 2007, Google Corporation.Droid SansBoldAscender - Droid Sans BoldVersion 1.00 build 112DroidSans-BoldDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.http://www.ascendercorp.com/http://www.ascendercorp.com/typedesigners.htmlLicensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0ff  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.nulluni00AD overscoreperiodcenteredAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatdcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdot Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek IdotaccentIJij Jcircumflex jcircumflex Kcommaaccent kcommaaccent kgreenlandicLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflex Tcommaaccent tcommaaccentTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccentmacrontonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonos afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061 afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109 afii10110 afii10193 afii10050 afii10098WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave afii00208 underscoredbl quotereversedminutesecond exclamdbl nsuperior afii08941pesetaEuro afii61248 afii61289 afii61352 estimated oneeighth threeeighths fiveeighths seveneighthsDeltauniFB01uniFB02 cyrillicbrevedotlessjcaroncommaaccent commaaccentcommaaccentrotate zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperioruni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni1F4Duni02F3 dasiaoxiauniFB03uniFB04OhornohornUhornuhornuni0300uni0301uni0303hookdotbelowuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0483uni0484uni0485uni0486uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABuni030Fcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCcyrillicbighookLC  ,latnkernLZZ 2 "  >$ ~`!6#h'L(h(h(n(h())0)6(h(h)H)V(n)))***L+++.$.$+0f2 "4544$$$$67D7D7D7D7D~88889(h(h(h(h(h(h)H(n>b>b>b>b>l>z>z>z>z>z)H>>>>>@$ 2(h 2(h@B(h "(n(n(n "(nA(h(h(hB(h(h$B$ )6C(h(h(h~)H)H~)H)H(n(n(nD(nEEJ ````)#h*J''OR 2(h(nRSS SNSSTTUUWZZ[[\|__`abbfffgFgxgh8kk(hlkldljlll(hmBmmmmn n"n n4nRnn)Hno)H)HoTp6q,t~tuu|vZw,wxhz{}~PZ F\f>萢d^ؓZ^ĕJܕ@BDE)G)JLNPRTVXZ\^`oRp)qRr)sRt)-{{{^&*24789:<$&,02468:fmq_al~IKMOQSUWY[]_acegikmoqs7qrvc &*24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqs,79;<$&8:qEGoqs;) ) )&*24@)`)fm) )_l~IKMOQSUWY[]_K$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs9= = )")$9:<@)`)68:C_i= =(Xr!#%')+-/13oqs9) )&*24fm) )_l~IKMOQSUWY[]_9) )&*24fm) )_l~IKMOQSUWY[]_c &*24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqsK$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs533$&;<=q8:;=?C_i(Xr!#%')+-/13oqsK$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs 7$&q R R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJ_fimqy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt#$C_i(Xr!#%')+-/13R R")$&*24DFGHJPQRSTUVX !#CDJ_fimy{~R R(XY_`jlr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnf f$&*24DFGHJPQRSTUVX] !#@CDJ_fimy{~f f(XY_`jlr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjln) )&*24FGHRTfmy~) )_`jl~  68:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`R R")$&*246DFGHJPQRSTUVX[\]q  !"#9@CDJ_fimy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt9) )&*24fm) )_l~IKMOQSUWY[]_ = == =&f fYZ\79f fmprt) )J) ) ) )) )[]@f fDJDf fY"$&(*,.024R RWR RR RIR R6) )R) )`j  JLNPRTVXZ\^`= =I= =2R`j  JLNPRTVXZ\^`qx)qrx DD"&*-^24789:<=;IWYZ\^$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrst DD"&*24789:<=;IWYZ\$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrst DD"&*-^24789:<=;WYZ\^$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrstf f DD"&*-^24789:<=;WYZ\^$&,0246789:;;=;?;fmq^f f  _alm~IKMOQSUWY[]_acegikmopqrst9) )&24=fm=) )_l~IKMOQSUWY[]_7) )&24=fm=) )_l~IKMOQSUWY[]_ $C_i(Xr!#%')+-/13V $,-679:;<=@` "$&68:;=?C_iq(Xr!#%')+-/13EGoqsB$0=D;=?CD_i(XYr!"#$%&'()*+,-./01234.R R = )")$&*-02467'9):@=DFGHIJPQRSTUVXYZ[\]`=q  !"#$'&'679@CDJ_fimq'y{~'R R(XY_`jlmr~'''''  '!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt   o oI[]@ a= ="FGHIJRTWy~= =  `j  68:<>@BDJLNPRTVXZ\^`= =I= =d &*-24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqs9 "@ EIRKLMNOW)YRZf[R\R])`\{HH)R){f{\qH R #%='=)=9f@ -f:) )&*-R24fm) )_l~IKMOQSUWY[]_8 "@EIfKLMNOW=YfZf[R\f`\{HHRR{{{{Hq\ { =#%)')))9f@ B) )0679:;<Y\ "#$&689:q) )mopqrstR R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJ_fimqy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprtf f "@ERKRL=M=NROR`R )=RRRRRR R R = )\")$&*-02467'@=DFGHIJPQRSTUVX[\]`=q  !"#$'&'9@CDJ_fimq'y{~'R R(XY_`jlmr~'''''  '!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt) )&*2468FGHRTYZ\ ",02479fmy~) )_`ajlm~  68:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`acegikmprt3R `j  JLNPRTVXZ\^` b)fi)mqrsux)fms _dglpqrtwx$m_bfisvyz{}~qrxy}~)O &*24789:<$&,02468:fmqrsux _aIKMOQSUWY[]_acegikmoqs79;<$&8:glpqrtwxoqsq &*24789:<m}$&,02468:_bfimsvyz{~) _aIKMOQSUWY[]_acegikmoqsR R")$&*24DFGHJPQRSTUVX !#CDJbfmqrsuxy)R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnfms)F$,79:;<=$&68:;=?C_bgilpqrtx(X!#%')+-/13EGoqsfms)*) )&*24fms)) )_IKMOQSUWY[]_ ")$&*24789:<DFGHJPQRSTUVX !#$&,02468:CDJfmqrsux (XY_`a!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnoqsfm)F$,79:;<=$&68:;=?C_gilpqrtwx(X!#%')+-/13EGoqs633$&;<=q8:;=?C_bditx(X!#%')+-/13oqs)) )&*24fms)) )_IKMOQSUWY[]_R R")$&*2467DFGHJPQRSTUVXYZ[\]m}q  !"#$&79@CDJ_bfimqsvyz{}~=R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt-m_bfimsvyz{|}~) _bgiqrtwxfmsy|}~ _biqrx,) )&*24fms) )_IKMOQSUWY[]_R R = )\")$&*-02467'@=DFGHIJPQRSTUVX[\]`=m}q  !"#$'&'9@CDJ_bfimsvyz{|}~)R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt)y~y|}) = =I)= = = =y= =yz}~)R Ry}~)R R ) )y~) ) = =I}== == =I= ==~)[]@~)[]@)R RI}))R R[]@R RIyz~)R R[]@y}~)8) )&-=24=) )_l~IKMOQSUWY[]_=  mv|} R R\&*24789:<$&,02468:\\=\R R_ajklmr}~q\ \  \ \\IKMOQSUWY[]_acegikmoqs) )) )l}~m}7) )&*24 )_l~IKMOQSUWY[]_4  v|} 1  v|} m}m) )&*24))) )_jlm}~)  ))IKMOQSUWY[]_gR Rq)\\RqR Rjkr})))))\  \)\ &*24789:<$&,02468:=))))) _al|}~)) ))))IKMOQSUWY[]_acegikmoqs*|} !79;<$&8:voqsR R\\\=\R Rjklmr}~q\ \  \ \\B))))))f)lr|}~)) ))))1= =))))= =l}~))))))&) )) )| L) )&*24=)))) )_l}~))))))IKMOQSUWY[]_V$,79:;<=$&68:;=?C(Xrv!#%')+-/13EGoqsE= =33$&;<=q8:;=?C= =(Xr  !#%')+-/13oqsB) ) )&*24@)`)) )_l}~IKMOQSUWY[]_RR R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJqq)RR R(XY_`jklmr}~q    qq!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprtc= =)qq== =jkr}q    qq*rv.) )=))) )l|}~) ))0)))))f)r|}) ))>=))))=))f)r)|})))))))) )))) q |    | #vv m}!m}$= == =m}){}  ) )) )j}  = == =m}!) )) )j}  "[]@m= == =j  0R RIR Rjm  $= =I= =j  []@}j}  )))f)})))=)f)})))qm}= =q= =m} j  ==!m}m}) )) )j  j  R R\&*24789:<$&,02468:\\=\R R_ajklmr}~q\ \  \ \\IKMOQSUWY[]_acegikmoqs7qr$,)7R9R:f;)<R=)FGHJRTW)Y)Z\))))R)))$R&R6f78R:R;)=)?)C_iqRy~)))RR==R=)R)fffR(X`jrv==R)R)RR=R=======  R)!#%')+-/1368:<>@BDE)G)JLNPRTVXZ\^`oRqRsRE=IfK=L=M=N=O=WfYfZf[)\f])pfrftfE=IfK=L=M=N=O=WfYfZR[)\f]pfrftf   $')) ,, ./ 257>DFHKNN!PR"UW%Y^(mm.}}/06@EKW]clmpqrsvwxyz{}~  !$&',,0022446;==?@CDJJVVZbddfilmo|~ )  *((+XX,``-bb.jj/lr0tt7v|8~?NWYgwxyz~ !!##%%''))++--//11336688::<<>>@@BBDEGGIVXXZZ\\^^`accffhhjjllnt latnfritzing-app-0.9.2b/resources/fonts/DroidSans.ttf000066400000000000000000005631341250202676700220710ustar00rootroot000000000000000GDEF&= GPOS=@GSUBlt< LTSHɛ OS/2˕`cmapԢVxcvt 9~>Lh fpgms#^gasp= glyfž?qhdmxBheado<6hhea S t$hmtx.'loca)Ljmaxp* nameXV0postP'?prep!e Ys_<3S = Zbm d Zz/Z933f @ [(1ASC@ m J '7+3h{fmhRh=hRhf?R%hbhh`hRhhhqhZhjhj%%?hfhfhfh%m}y9}R+H}}'h'`7PRmm3B)J?^qqHq%%+qq1Z!# R=h3hf'hhDh{hhy3dDRhfRdm{hf1=q%#?BT?,hD}9999>R@y/}}}}}h}7?^?^?^?^?^?^^qHqHqHqHqoqqqqqhfs  ?^?^?^}q}q}q}qyqy/q9Hq9Hq9Hq9Hq9Hq}%%}%%}%%}%%=0RDRR%+HffF}q}q}q}Hq11`1r'hZ'hZ'hZ'hZ'!'!'!7 7PRRPRRPRRLh?^^}s'hZu!m{%BTJ%9PR}R?R}BN'7#h`#hN@7qZq oZqq#qq qqq1qqq9}'hR@+HHu39\HZ}}'#h`H=;?^u3`)HqD^qq) q#m)7y?#Hq3qZ 37 RRRJff?f?{{o Zf7NRNR jh`hDh?hw%NfS3Oqb) Jhfd%whfhfhfhfmo}% ;%/1!Uh%TTf R+?^Bs3VV}q/HF19Hq}o%'/d ) ^9#h}q d}Xq?}q}Pq}o}qhu))//3#\HD J+/D)\D}q}q')77=#)HHHw=3w=3RJ-jqHR?^?^^9HqqHfqHf\HD\H}q}q}q;7   H3/3/#`#qqNFPNP/}q)\o\Z^?^?^?^??^?^?^?^?^?^?^?^9Hq9Hq9Hq9Hq9'H9Hq9Hq9HqRbR}q}q}q}3}q}q}q}q}q}q}q}q/////7 7 7 qjjdsssd1( +    &"  "&   *. . * .  ( '    ' &&&&&& """"" "& . .... &&&     ..          $ ...."""*(****   ...... &&0 &"*$&-  &""" &"& . . -(0&""0$  .* .    &+   *" &+  . &" &" $.  .&&*   &&"""000 '&&&&&&&&&&&&  """"""""""""..&&&                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ~ # O_?M   " & 0 3 : < D  !!!!"!&!.!^"""""""+"H"`"e%  #P`>M   & 0 2 9 < D  !!!!"!&!.!["""""""+"H"`"d%aI1vhcb]gD Xz} Bvt %"iOS`xlhijkopqrstu45]^   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a rdeixpk vj0-s12gw'*).l|!cn,B/(m}b  3:45y KRqNOPzSQL~ # O_?M   " & 0 3 : < D  !!!!"!&!.!^"""""""+"H"`"e%  #P`>M   & 0 2 9 < D  !!!!"!&!.!["""""""+"H"`"d%aI1vhcb]gD Xz} Bvt %"iOS`xlhijkopqrstu45]^@EYXUTSRQPONMLKJIHGFEDCBA@?>=<;:9876510/.-,('&%$#"! ,E#F` &`&#HH-,E#F#a &a&#HH-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y &QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,(#p(>(#p(E: -, E%EadPQXED!!Y-,I#D-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+)#D)z-,Ee,#DE+#D-,KRXED!!Y-,KQXED!!Y-,%# `#-,%# a#-,%-,F#F`F# F`ab# # pE` PXaFY`h:-, E%FRKQ[X%F ha%%?#!8!Y-, E%FPX%F ha%%?#!8!Y-,CC -,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,KSX%Id#Ei@ab aj#D#!# 9/Y-,KSX %Idi &%Id#ab aj#D&#D#D& 9# 9//Y-,E#E`#E`#E`#vhb -,H+-, ETX@D E@aD!!Y-,E0/E#Ea``iD-,KQX/#p#B!!Y-,KQX %EiSXD!!Y!!Y-,EC`c`iD-,/ED-,E# E`D-,E#E`D-,K#QX34 34YDD-,CX&EXdf`d `f X!@YaY#XeY)#D#)!!!!!Y-,CTXKS#KQZX8!!Y!!!!Y-,CX%Ed `f X!@Ya#XeY)#D%% XY%% F%#B<%%%% F%`#B< XY%%)) EeD%%)%% XY%%CH%%%%`CH!Y!!!!!!!-,% F%#B%%EH!!!!-,% %%CH!!!-,E# E P X#e#Y#h @PX!@Y#XeY`D-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,!KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-, #KSKQZX#8!!Y-,%ISX @8!Y-,F#F`#Fa#  Fab@@pE`h:-, #Id#SX<!Y-,KRX}zY-,KKTB-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY@cTX@C`BYYYYY-,Eh#KQX# E d@PX|Yh`YD-,%%#>#> #eB #B#?#? #eB#B-,zE#-@ `@+ F3UU0U0o0`@8F/?O_o@FQ_+s@ F+|@ F/?O@ F/@|P|t t0ttt oooouooKo nnnnKnU?gg/g?gg@fPfff?eeedd@Od Fa_+`_G_P"[[T[[I[;[ZZkZKZ;Z3UU3U?WW/WVFV FTF@mT FRP+?POP_PHHHeHVH:HGGG;G3UU3UUGU+oTS++KRKP[%S@QZUZ[XYBK2SX`YKdSX@YKSXBYss^stu++++++++_sssssssssss+++++_sst+++_ssssssssss++++_s^stsst++++_sssstssssststt_s+st+s+_sstt_s+_sstt_ss++sts+st+ss++s+++sss+^ NuJU}qq}}winfoxG:x Zy mmm{Too****o)q)M|D[?e?g = y j 4  t 9 I+|"f8M;Ypik_9w"9'euHH j!!t!"]"#J#$$5$=% %#%~%& &&&'+'e''(*(z((()m)))))* *r******++++D++++,,,6,--4-K-c-|--.x...../////00070N0e0~11$1;1Q1h112 2222223Y3q33333444/4F4^4u4444445i55555566&6=6S6j666666777;77788,8C8Z8q8888899,9C9V9i9999::&:>:Q:t:;;%;;;O;b;y;;<>%>8>L>d>|>>>>>>??*?=?Q?h?z?@;@S@i@@@@@@AA&A9ALAcAzAAAAABBB2BHB{BCDDDDDEEENEEEEFNF{FGG2GGGHHAHHHII(I0I8IjIIIIJ=JEJMJJJJJK)K1KyKKLL LMM)MBMXMnMMMN#NOOPPnPQ Q^QfQR0RrSSSnST7TTUUV.VWW2WKWaWwWWX(X?XXXXXYrYZ/ZFZ]ZZ[[ [[[\\\]][]]]]]]]]^g^o^w^^_;__`=``aeaabebbcecmcd`ddde@eeeff$f,fkfsffg2grghhshiiijSjkjjkLkTk\kuk}klTlllmmTmmmmmmnn(n@n[nvnnnooDorop*ppquqr]s*s2s:smsssttptuvvwAwx~xxyyAypyzzbzz{{-{||}}`}}~~-~p~~~V['ۃNZb $;RfzGt|ۈ>cω.F^u)eڌK@ӎk\ pЕ8Rl,BȗFJ3HVޝ >aD$aϣ3Ѥ&rاD.ЩWkά%hϯ6Og/LlĶwqAɸ'/7Ndʺ(B[t»,ûݻ(08Qi˼.G_%7Pf翚f¢(û(ĄO&ƇljǝDZ '@ZsȍȦ7Piɂɛɴ)@Wnʅʝʳ3Lfˣ "9Qh̘̲1Km͑ͨͿ6Me}Δά4J`xύϥϽ0FZНKѺ/z)Ӓӿ +@  p@  H?2/3/+]33/310!!7!!IhyJh:@ H@  H ?//+3/2]10+#34>32#".Py3"./""/."&5!!5&%5""57@# / o  ?33/3/]]]9/10#!#J)s)-)r)3@X!   P P  H   ?O   /3?399//]332233]22/]33/3/]9293/92393/3/10!!#!#!5!!5!3!3!!!?RTRNA+RR%TT#@}TTHPPH{-6?@34/))/!!p/<753&&'4.'662]T2f`T !W`e/YV*1[OdCB8JX[.+F3][(B1YSFrT7 !BUnJCoS5 *)ZBSkH!7-&b$9/&qYf3 ';?]<>@3<><>(2#(AA  0?>%7!-????/]]99//881032#"#".54>3232#"#".54>32#GPPG$JsOIpL&#IqNKqM'GPPG#JsOJpK&#IqNKqL'՞,JHlv??vllu>>uJIHlv??vllu>>uJm}!S@M'JI,IH G6AGB B6B6B;54.#"2>7%4>7.54>32>73#'#".!4$;V8/B*Vd:bTH }4P7#B`}(MoG<-2^XS[02Tm<`+" )5A'1`l|Nis="AAC%#>@F)$=,Y(6!?HU86[A$NzdV*$MWc9KwS++SwK@m]O$73#.R$JqN%GjENqJ$1}]2w^Z=@ ??]210#>54'3$KqNEjH$NqK$1|Z^w]Rw$@?2/]/^]]10%'%7++wo`f`Fof )@   ` ?32/]]22]10!5!3!!#}}{?y 8@ +  @ H_ //]]+32]]]10%#>7j'/36z|{8=}5RBy@ @//]105!RѨ5@ 4Ddt H//+]]]]1074>32#"."./""/."o&5!!5&%5""5@ ?/382/8310#!Jb'&@o))o  #ss??/]]10#"&&54663232>54.#"3qvs93o~wt:BkMMlEElMMkBݱfffe貖KJᗖJJ5@!@n~ @ ??/^]]]3/3]10!#4>7'3ǰ`+baY"y{+`#<@ #o%%"o! " s"t?2?39/]3/3]3/310!!5>54.#"'>32!p^KvS,"?V5_Ef(\jvA`l;5]K}QL;Z? M54.##532>54.#"'>32.StGAʊmUW]\W)5bYQ~U,$B\8kJ\&]n}Fln8`IxX9 `t@"-.2(JlCDa?(Jf=4R9C6}6)6a? N@, Vn  w_ t??39/322/]3]]9/]33332/]210##!533!4>7#?հ]{  eHH0d8{uf"11.*N@&o,,'$$(h#Y###@ Hs't$s ?3?9//+]3/]]333]3102#".'532>54&#"'!!66!cHDŀ3c[R!!Ybc*O|V.??9Z7' i7lir~C $ %NvQ 9]q +?7@ 1n "AA;o 6u,s's??9//]2]2104>32&&#"3>32#".2>54.#"q5\ƅ./+#X+ZdC* 9L_;_l;>tfdJn#####  h88Y8(888H88C&CVCCC-s;s??9/]]]]]99/]3/]]]]2/]]99102#".54>7.54>32>54.''">54&5TqB(F`8:oW5Cyfnu=-Lh:1V?%Cr DhHFkH$'If?~j}#>W30U?$~,XXClWEL_vI\h86e\Kx`JIZmBWX,5Y?##A\84TH@<Tje9R@34BT6ejj)=5@9o??/n   4u*s%u??9//]3]210#".'532>7##".54>32"32>54.5\ƅ..,#X+f+ 8L`;_l;?sfeJ%.;rjrDNG(TWFoN*/K`0CkBf'>@)))) 4Ddt@  H#/?/+]]32]1074>32#".4>32#"."./""/.""./""/."o&5!!5&%5""5'5!!5'%4""4?f a@/"""" d t P D ;  /   +  @H_ /?/]]+32]3/]]]]]]]10%#>74>32#".j'/3"./""/."6z|{8=}5'5!!5'%4""4fN@0@@o0 Pp?/^]]]q33/]]29=/33/]]10%5d!ff\@= @ {hB9/o/]]3/^]]q/]]]]]]]]3]2105!5!fdTffN@0@@o0 Pp?/^]]]q33/]]39=/33/]]105f dBlfX%%';>@!2(('F F=/= -7Q?3/2/^]9/]9/3/1054>7>54.#"'66324>32#".'B20D+9U8SF?Qa]h86P64B&"./""/."%9\PM*)CEO50O94"*;3`WCiZT/-C?B,&5!!5&%5""5mJWho@?X`'''FF'N1 j@j;@NN, [d@6S@EI/3?99//^]^]322/]]q9///]]10#".'##".54>3232>54.#"32>7#"$&546$3232>77&&#"%9La:-I4!6GY5MwR+;ob-ZRE"+.F/V{ZO=wod+V؂fv7jeU7N2M*Je?>}qaH)2A#%B18eVezD`5D(=hNݘOoR&,fEeՅw-SsE :^x@$FFII@ H/@_ H?2?9/9+/83^]3/8+]q39=/99]]99]]3310!!#3.'ߢg;Dj4 Z$*[pg1111$Zd0 #`y $`"`??9/^]]92]]]9/]]q210!2#!32>54&##!2>54.#ÃB'JmEEyZ4A{oTrF XwI !K|\'Wg>lR7 -OxVdm:J;Y;xh(He=8^C%}#L@@H ` p  @ H %%[f$!_ _?3?3]3/+]]9/+]10"3267#"&&546632&&k{C;vvYN'NUa;LWlON?'QډۖN#ln,* . &@ [gZd``??]10#!!24.##3 `_B~uɢ ^\ՊC$ B@&g  Zd _O _ _??9/^]q229/]10!!!!!!! =< p@@8 H  / Zd _?o@H@H_??9/++^]q2^]3/+]]q9/10!#!!!!}+7@++ )Zg--[ f,+_$_$_??9/]29/10!#"&&546$32.#"32>7!7pvKV_ oXH$SX].zB7x,I>73 ii,*Qډ؜V  =@# Ze   Zd _ ?2?39/^]2]]]210!#!#3!3պfVhRd W@& + { T + ; K   Z@ H  ?2?2/^]+]22_]]]]q10!!57'5!df))ff)h)H{s/@`p/Z    _/?/^]3/]]]10"&'532>533L"N-%K=&;i{ 2XD^ie1 d@- f   /Zd  H@ H ?3?399++2]]]3/8^]33/839]310!##373=yr%3#@Zd_??]]31033!Ǻ=/@69 H9Z@ H H eO  @ H&  Z d H  H ?22+2?33+322]+^]]]993+3+2]+210]]!##!3!#46767##EAJI?9XJw4=GIQ@)(Ze'   Z dH  H ?22+?3+322]]]]2]210!###33&'.531MLA9LLJ CC> }q'4@ [g)))p)/)_)[ f(#__??]]]]10#"&&54663232>54.#"qQ훣LLQ4krrk22jrrl4ݩllkk뫉ۙQQۉڗQQ3F@,[(8Hg@Zd`0@` ??9/]2^]]]]10###!232>54&##37~Ϙj~54.#"q1_]+Zyg3)LLQ4krrk22jrrl4݃ⵄ&^54.##d 1Qh7Z~Q%)SW\W]>q\#EgEHd@h3B@'Y##Zg555`5?5*Z f4*'_$ ` ?3?3992]]]3]10#"&'532654.'.54>32&&#"EsoA"W`f2Iz]YU)@tawJCAXzFsT[\/aj7#"xp6PC?%#ShTX_2-#+q`9SC;!$L`~^@2  O  0 Z@Wgw@  H_??2/+]3/^]]2/]]]]]q10!#!5!!q^_/@ZeoZ d_ ?2?]]]10#".5332>7BɈąDYR(LrĐRMzH6bQ l@ `p@ H/@ H H @  H ?3?33++?3/83+]3/8+]39=/33103#3667'*.Ja[JJa*߶HH@HHH@/H%D%%$%D%T%%% p@ H,o,, ,0,,@ H H %% H% H%?33++3?333++/83^]]]3/8+]q39=///]^]q3+3+3+3+3+3+103>73#&&'&'#3>7)   ~  8pi^&&Zcg1rJ3l/7437/p6\.cb[&%blo1` @  7  8p@ H   /  @(' ?2?399]]/822/83^]3/8+]q39=/3]33]3/8310!##33`ZLN[{/L7s@  @ H@@/OZwO6?3?9]/^]]]92/8]]]33/8]]]]]3+]103#3TBB/R 8@ g  ? O f __?9?92/2^]22/10!!5!5!!TM:ۑ9&@??/]210!!#39k1!?///8338310# J3$@`p ??]2103#5!!3jϕ)%?/3/103#)f%d!NH//3/10!5!NR! @ _/]/10#.'53x#RM?+.0SXQ"QQL^^#2T@)G#U44o40H @ H H V3P*R$P??3?9/22/++^]2210!'##".5467754.#"'6632%2>55%!BN`?EtU07Q4SB@Jdfa0/=hL+ZzI a-A*'Q{TECZ70"(8)Yb&MuOc 9Q3\V?/8-HW11@ I%GT0*P  P?2?3??22+102#".'##33>"32654&^m<32.#"3267ReJLfN268<:Q66{?Ֆۉ>"  %q04@&GU22.H V1+P P?3?3??]2210%##".54>323&'&&53#%2>754.#"T;M`<]n<32!32>7"!4.`nHBxecn;L3WQL'(MQW`r 9XJ҇֕NGnq ۜDqP,p@N`?OG/ OP ???^]32/^]3/]322/]9/]]]10###5754>32&&#"3-U|N;c'/I((:&?KD`kT# 0SAh%^?R^@ 2SG7/`7p777/7/'HYG@M H  0@`````@'@ H'2 7&&5467.54>3232654.##"32654&#"&/_],!)8]Q$A͋kj5'BW/*6@E+G12ba%O@;aH7ZA#L?)\lcdgidcjJq#mEL^5  (!/Pm=Xa4*PqG<[B* R5=Y*?Q`3Yb4 %@.sl.:! ,M`spow{tx2@GU` G TP ?2??322]10!4&#"#33>32\ipQnC ER\0Â4f`2+?*3u%@  GTS??3/22]10!#34632#"&d=-'?,-=J)<6 +:98u!.@# #G  T"S P??3/2/22]10"&'532>534632#"&B0?6#.#"Hm=-'?,-= 'A3M{W/_<6 +:98^@ D@ H/ G T @ H H ??399++?2^]3/8+]333931073##3V%om7i%RZ6d@ GT??]10!#3d^,e@?# G   g w  G,U... .P..GT-#P( ?22??32232^]]]]9/]]]]210!4&#"#4&#"#33>323>32diIfAciMh? BOY.x&IW`2Â/[XÂ4f`J+?*X^/D-3^0@GU` G TP  ?2??32]10!4&#"#33>32\ipQnC ER\0Â4f`J+?*3q-^0@HW!@!!!!H V PP??^]]10#".54>3232654&#"-C}ogGC|ogG'ՑLLՉӑKKӈ?^06@.HW22& G T1 P +P?2???3222]10".'##33>32"32654&;`M; :M`<^m<754.#"".54>32373#46767#5LiAAlQf]n<H;?hK)9GX^3_QJ+P=%Z?^5H@-%GW7?7_777,G V6&)P," P?2?992]2]]]310#"&'532>54.'.54>32&&#"?:m`m;LTY,A[95\HHsP+7dVaH?AGfb8^FHqP*-PxQ(#");$212#4./7#".5#5773!!-*# (04>jM,Ni?  Ne}QNabJ0@GU`G T P??3?3]210!'##".5332>53u ER\0[\/joQnC+?).bi=4e`:Jm@ H H H@ HP/O@ G  ??39]/8^]]]3/8++9=/3+3+10!33>73w  ǼJ!hl``lh!cJ/ù/@ H/ H' @ H  H  H@ HT''@ H[  H'  '-.H.@ H...1 1011@-  'fv?33]3?3]33/83^]]3/8++39=///+]+]3+3+3+3+3+3+10!.'&'##33>733>73   翃  Ĭ   h-24:>?:2j%J-ig[Wa_!k"\_XWhm/H#J @ 6 9k{W:JdtX5E   6@H@Hk{W:J  0        ; K (    ??/]]]]]]]^]]q]]]++]]]q9=///]]]]]]]]]q3]33]]]]q10]]33##u3fL J"d"H@ H$$$$P$$/$O$@ "#P?2?333/83^]]]3/8++9=/331033>73#"&'532>77  ǼNAVtP4L@#0F4%9J(XXR#Va^!c'QZ1 ,@)R5J l@  H@ H ? _   HH?@ HO HO?2+?2+/]+33+]]3/+3+]310!!5!5!!5 }D='@@% '#  #_)??9/]]9/]332/210.54ᒑ4>7-A(M_6}}6_M(A-wssw0=# !GnNNgVVgMNnG! #=0i{ zj-@0@p@??/^]]q103#閖3)@@% $$$# ??9/]]9/]332/2104675&&54.'53"5>5wssw-A(M_6!A`>}6_M(A-;jz {iL0=# !GnN4H-VgNnG! #=0fJZ#<@ %%   @H  ? O o  /]3/+2/]]10.#"563232>7#".%7-)<;8d27C/%7/(<;8c27C !,l  !,l ^A@ H0@ H /^]//+3/2]10+3##".54>32y3#..##..#H&5!!5&%4""4%Z@%F %'@'H 0 @  s!s@ H??99//+33/^]]29/3210$#5.54>753.#"3267vnLWb45aVH.58<;Q6 KljˈK !  %D#(u@ o# H@0 H**!@ H)!u /"""""""""ts??9/]323/+3]3/++399//^]32102&&#"!!!!5>55#534>jBB8K0RY@+ )DaCՉDW_2{#7@#. !p99 $@1 H8  ) 3   ? o  /]]]2/]93]23/+]2]3/]9/]210467'766327'#"&''7&&732>54.#"#b/l<7&&54>32&&#"#"&'532>54.'.7>54.'-:KU7dVaH8AGcf9_FHqN*)4EL;l`l;LTY+E]73^LIsP)?eH#)!AlR/&)3S@-&rT=bD%( ';9.,/ANa>4UD1&mNGoM(! '3--1>NdY%?:7 $.8"&@;9-:3 j 5@! @P 0  /]]32/^]]104632#"&%4632#"&38('::'(8w8(#:&(8s6015522560 &522dD%AUj@C"""&L444WB& /`p-G;Q-?/99//]^]/]q99//3/10"32>7#".54>32&&4>32#".732>54.#"{=^@!=_C69815<#fe36id?;>4a6ahha66ahha6meꅅeeꅅe,SxKNxR+  BzgexC!ha66ahhb55bheeꅅeeDB-N@/-///O///$ `  .-'?99/]2/]]2210'#".5467754&#"'663232>55'/8#+H4c=80Z*03u<}w3D)2*":+R# 3M3flH9d$jz:9+3-,A,1Rs `@ P`   @! H    /3/39=/93333/]]+299//]310%R5uu6tt)NNNNf9@$yVK8 ?/]]]]]]]]]10#!5RBydD:N@}R  E---P;/`p&@4J&??99//]^]q3392/]q99//]^]q929++]10]32654&#####324>32#".732>54.#"H[OSYF-9C5*! _騞6ahha66ahha6meꅅeeꅅeHEJ;0K9( nW%G8`}ha66ahhb55bheeꅅee//3/10!5! {V'C@, ))0@ o #?3/^]]]q/]]104>32#".732>54.#"{2UsAAsV22VsAAsU2{4F((F55F((F4AsV22VsAArU11UrA'E44E'(G55Gf :@!  ` ?32//]]333223]10!5!3!!#5!}}}{1Jm@@ O   @ H@H ??9/+3/+]210!57>54&#"'6632!m9H(B63]-N6RUC;"A@2&^0A!?[92VU[79h0a@<2_222@ H''@ H/_&#, ?3?39/^]9/+3/+]3/9/910#"&'532654&##532654.#"'>32NQEXX(S~VF{9?5bXk`bb\T#/;a3E=DL,EiF#NjjN73#//*?MQ#yLQQ"QXSJ7@" G U `pGTP  ?3???2]21032>53#'##"&'#3djoRnC 0gHj#4e`:ST.*&(#U*6qf7@!0@P    /2?/]]9/^]10####".54>3!fxy=U_m32#"."./""/."&5!!5&%4""4#9@ @ H //9/+9/]33310#"&'532654.'73-1GP.?%Zy9":+all+1# s):?J4@!O@ H 0 ??/]]33/+]103#4>7'3&^J<<8(I`B.@ H!! ?]+10#".54>3232654&#")MmD?jN+)LmD>kN,:KVUKKUVKmSY//YSSX..XSwyywxssTs V@/    @     /3/399=//3333/]]299//3]10'7'7tt6huu5eN\\NbeN\\Nb?&{'J<0@?@@]5]]5]]]55?55,&{'5t3(@@p@]]5]]5]5?5&u'<?<@'8p8P88333d3P303 33L]]]]]]]]5]]55?55DwD^';D@2(('F == F@H ''-7Q/3?2/9/+^]9/3/103267#".54>7>55#".54>32P'A20D+9U7TE@Ra]g85Q64B&#..##..#%:[QL*)CEO50O93#*:3`XDhZT/-C>C+/&5!!5&%4""4s&$CR&%+5+5s&$vR@ !&l%+5+5s&$KR&%+5+55&$RR@ &,%+5+5+&$j!R@ &)%+55+55&$P}1@ P@ %+55]]]]]]]55V@* Z$4T  g@  __ _ O    _?3/?99//^]q2/8329///]]]]}32310!!!#!!!!!!#V%˺=ul;<}&&z O*$ %+5s&(CR &´ %+5+5s&(v?R@ &J %+5+5s&(KR & %+5+5+&(jR@ & %+55+55>ds&,CR & %+5+5Rs&,vxR@ &j %+5+5s&,KR@  & %+5+5@w+&,j R@ & %+55+55/]@:[g! !Zd _?o@H``??9/+^]q3222/2]9/103!2#!#%4.##!!3 /_`B~uP %\^`ՊC$5&1RR@  & !/ %+5+5}qs&2CTR(&.( %+5+5}qs&2vR@ 4&X(. %+5+5}qs&2KR@ (&0( %+5+5}q5&2R}R0&1? %+5+5}q+&2jR@ 1&(< %+55+55-{ H@HH H H HH@0H@  P   Pp ?^]q2323/]3333]10++++++++7'i=Bh?fg?i>gf=g}q&1\@:)*'[ g333p3/3_3[f2)*-"_  -_ ?3?399]]]]9910#"''7&5466327&&#"'32>\[^Q훽NZa[L^BP.0C0rGrl4jX/rErk2c޷lGNd*k*&N QڊTQs&8C=R& %+5+5s&8vR@ $&H %+5+5s&8KyR&  %+5+5+&8j}R@ !&, %+55+557s&<v1R@ &c %+5+53<@![g Zd``    ??99//22]]10###33232>54&##37~Ϙ~54.'.54>54.#"#4>32+?K?+'F98X=!8eUa5AHL%8Q4+H8?U5)>H>)!W~Q'#"-@($;8:#(DCF*6O?6:C,*>)0SANhU%&Lt^!&DC3&93 "%+5+5^!&Dv5@ ?&39 "%+5+5^!&DK@ 3&3;3 "%+5+5^&DR@ ;&)7#"&'#".732>55"!4.^7Q4SB@Jd+3gal9`1UNJ%'KOU1>"L_tJG{Z4aO=hL+ZzI n 7T3ECZ70"(8U]U]Gnq rs6U;'Q{R\V&MuOc 9QcDqP,qo^&FzB /&  %+5q!&HC(&.(%+5+5q!&HvR@ 4&v(.%+5+5q!&HK@ (&0(%+5+5q&Hj@ 1&(<%+55+55g!&CU& %+5+5B!&v0@ &t %+5+5U!&K@ & %+5+5%&j@  &%+55+55o-#'9t@F(H# """ W;@;;;;2H V: #!!-P07P??99//]]339^]]9///9210#".54>327&&''7&&'774.#"326-C}ohG?vif+xZJ(U/FAz;JCoO,"FnKMmF!!GmL=ܘOBww~A;<vQr7{ H,quAݰ8kR2.XUL}Z1&QR@ !&"0 %+5+5q-!&RC &״& %+5+5q-!&RvP@ ,&N & %+5+5q-!&RK &( %+5+5q-&RR(&)7 %+5+5q-&Rj)& 4 %+55+55f+`@0-"Vf(8@( H'  `?3/^]3/]q/3+3]]3/]105!4>32#".4>32#".f)*  *))*  *)#/ /#!//#/ /#!//s/$-\@;'(%H  W/@////H V.('+"P +P??99^]]9910#"''7&&54>327&&#"4'326/C}o}bDP?FC|o?q1DP>EK-D'rH-'ՑL5mJHՉӑKlIIцT3џc{!&XC&! %+5+5!&Xv`@ '&W! %+5+5!&XK@ &# %+5+5&Xj$&/ %+55+55 !&\v@ /&g#)%+5+5? 18@/H W33' GT2,P!P?3?3??2222]10>32#".'##3%"32654&d:M`<^m<>%+5/q'8U@1-G& "&U::6H V9'%O" 3P (P?3?]3?9/32?]29/22210%##".54>323&'&&55!5!533##%2>754.#"T;M`<]n<32\ipQnC{ ER\04f`Չ+?*\5&,RR@ &#%+5+5r&R@  & %+5+5=|&,M"R@ & %+5+5*o&M@ &%+5+50@&,NR@ & %+5+58&N@  &%+5+5RBd&,Q %+5DB&LQ%@ o%%%%+]5Rd7&,OPR@ & %+5+5dJ@ GT??]10!#3dJR{)&,-8@O@H@H!!!P!!!@H+]]]]]++]]5&LM.@ 555_5@5 555@H+]]]]]]]]55H{ds&-KR@ & %+5+5W!&7K@ & %+5+5;&.9s %+5;&N9!Ĵ %+5JI@ D@ H/GT ?2?3992^]3/8+]339310!#373#m3oQhJ5##33&'&&533M"N-%K=&7d{ 2XDMLA9uAA8}4 ^ie1^(:@" G$U**`**GT)P P????32]9/10"&'532>54&#"#33>320?6#.#ipQnC ER\0"Hm 'A3m4f`J+?*M{W/}q&2MR@ *&() %+5+5q-o&RM@ "& ! %+5+5}q@&2NR@ -&2( %+5+5q-&RN%&* %+5+5}qs&2SR@ 4&C(< %+55+55q-!&RSF@ ,&E 4 %+55+55}*[@6Z'' g,,[ f+_O__$__????9/^]q]29/29/]10!!#"&&546632!!!!!"3267&& +[0LLbT>Vrl44kr4Z&&Y lk<QڊۙQXq^*6?d@;?H111 7H%WAAA@A+H V@P?+????.<4P .P?332?3329/^]]]]q29/]29910"&'#".54>326632!32>732654&#"4.#"`A?ƀgGC|oy?r pmmpLՉӑKojipGnq ;bDqP,s&5vTR)&# %+5+5!&Uv@ #&@%+5+5;&59w# %+5`;^&U9%+5s&5LR"&( %+5+5r !&ULp&"%+5+5hs&6v;R@ @&p4:%+5+5Z?!&Vv@ B&]6<%+5+5hs&6KR@ 4&"<4%+5+5Z?!&VK@ 6&>6%+5+5h&6z5:4%+5Z?^&Vz <6%+5hs&6LR@ 9&?4%+5+5Z?!&VL@ ;&A6%+5+5;&79ش%+5!;F&W9]$%+5s&7LR@  &%+5+5!&W8o a$$%+5s@L_ 0@ ZP w1  ` _?2?9/32/^]]]33/]]922/]9]]]q10!5!!!!#!5^_'ٻ3ߤ!b!F%j @7 H'/'?'#G"O OP ??3329/32/^]33]222]3/+33]10%2>7#".55#535#5773!!!!-*# (04>jM,Ni?  NeQNab5&8R`R &!/ %+5+5&XR@ #&$2 %+5+5&8MR& %+5+5o&XM!@ & %+5+5@&8N}R@ &" %+5+5&XN @  &% %+5+5&8P{R@ &" %+55+55&XP @  &% %+55+55s&8SR@ $&6, %+55+55!&XSP@ '&H/ %+55+55B&8Q  % %+5BJ&XQ !!%+5s&:K;R@ +&3+%+5+5!&ZK@ 0&80.%+5+57s&<KR@  & %+5+5 !&\K@ #&+#%+5+57+&<jR@ & %+55+55Rs&=v9R@ &^ %+5+5R5!&]v@ &` %+5+5R7&=O)R@ & %+5+5R5&]O@ & %+5+5Rs&=LR@ & %+5+5R5!&]L@ & %+5+5%@  GT P??]3/1034>32&&#"-U|N;c&/H((:'kT# 0SAN+J@*0-)G 0@`)) #P P??9/32/^]3/3/32/2]10#"&'532>5#5754>32&&#"3-U{N =9(;&-U|N;c&/H((:'D?kT#  0SAKDkT# 0SA#1>@^))**0118    V#f##Yi2o 7 G W  8HX @ H@@@/@@@@ @1 _# H <55<`1 1#<11<#) ?3/9////]]]]]333+/83^]3/8+]q39=/3]]3]]3/]99]99]3/]q3/33/]10#!#&&54>32.'>73#4&#"326P<3Ӝ3: ;R21T># 0/*?MQ#y?21?31 2?F`#y`F3O87O_}.6;<6.=A@AGB4<<43;<^ 1@T`@#UAA/AAA[K K K 7G1Ub?b>H(@: H( H((VaXPP ` p  PP^@FPFFF'$P+8R+2P/]??3?9/23/]9/3/]2/++]2299//3/]10>73#'##".5467754.#"'6632%2>55#".54>324&#"3260/*?MR#xR%!BN`?EtU07Q4SB@Jdfa0/=hL+ZzI a#=T12R;!!;R20T>#u?12?981?=A@AGB\-A*'Q{TECZ70"(8)Yb&MuOc 9Q3\V3Q88O33O87O45<<55<<Vs&v%R &H%+5+5^D!&vu@ ]&qQW%+5+5}qs&vR@ >&X28%+5+5s/!&vP@ :&L.4 %+5+5h;&69ڴ4:%+5Z;?^&V96<%+5!%@_/]32/9=/3310#&&'#5>73y3l46j3yDC;;CE"a77a"LQQ""QQL!%@  _/]32/9=/3310#.'536673EC;;CDy3j64l3yLQP##PQL"a88a"Zo@ _/]/10!!?o!{/@   _/]]2/]10#".'332>7{,MmGImI'l0C,$A3"=eJ)'If?+2 1(u @ 0  /]]/104632#"&=-'?,-=s<6 +:98m1@@-?O_0  ?O__/]^]/]]10#".54>324&#"3261#=T12R; ;R20T>#u?12?981?3Q88O33O87O45<<55<<B^@   ///103267#"&54>734"-@dd/8-+qhZ*K@48@#/  @H@ H /]23/++3/^]]10".#"#>3232673(OLF -0h!5J.*QLE-.i!5J#+#5>73#%>73#//*?MQ#ek0/*?MQ#dLQQ"QXSLQQ"QXS! '@ H@  _  /]/]32+10>73# !-4lMQP!NWV   )f@$$$$$$@ H$$ @' H H  '`/^]]]329//32+3/+3/+]q10>73#'4632#"&%4632#"& 08= R8)#:&)88(#:&(8KOQ$ MPQ%60 &522560 &522&$T0"""%+]5?5H^3@ 4Ddt H//+]]]104>32#"."./""/."&5!!5&%4""4M'(T.H@%g]]4++5?5P&+{T1H@%eo/]]]4++5?5`',Tf@0 @/%p`P@? @H@ H++]]]]]]]]]]5+]]]]]]5?5&2RTG@0-..p.P. ...$.. %PPg777]]]]44+]]]]]]]5?5T'<TKH H@% ?/]]]]]]]5++]+5?5&vZT5@#5 66666%PPg???]]]]4+]]]5?5w&U@$@$ $:%+]]555$%C@ @H/Oo@HZd_??+]3/+_]]10!#ú%hX@ [`p@' H/_o@ H [ H _??3+/+]3/+]9=/3310%!53!&&h»^*.}}1J[ a(R=+}q+S@4"[g----?-o-[f,`'__ ??9/^]]]]]99//10!!%#"&&54663232>54.#"Q훣LLQ4krrk22jrrl49Ellkk뫉ۙQQۉڗQQRd,. _@/@H@ H@ H  @" /O_ H  ?2?3+/8]]2/839=/33+++]10!#&&'#3.*aKK[`/01R c@> ? O o 0 p O  _ _ _??9/^]/]]3/]]]]q2/99//]]10!!!!!5ZRJsdN }q21@Ze o  Zd_?2?]]]10!#!#!{33N Z@ [ H @&H  / o  [/? _ _??9=/3/]32^]3/+99//+10355!!!Nn}Xgf%77<h!.;@P"gZ;!z([g=/======_=0===5[f<";`./`!!!!??99//3232^]]]]]]qq9/]]]33]2210332###5#".54>3332>54.+"33I~<4Txe//exT5=~…J][.)SW99WT(.[]˴^f={nR00Rn{=fę^S;iXNh<32!!5>54.rj2#Q_b@oP.Q욛Q.PnAb_Q#2j)DudA0o^^oǨ0AduD@w+&,j R@ & %+55+557+&<jR@ & %+55+55q!&~T@ J&>D/%+5+5Z\!&T@ F&m:@-%+5+5!&TD@ %&b %+5+5w!&T"&"%+5+5=&U,B%+555q^=8@8G/(??HV>" P8/,P3?3222?3?]22210%2>754.#"".54>32366733267#".'#5LiAAlQf]n<=qdp1 !  2"%A"&?2$ ;M`/bhek7͗HԌՐISU#R!hy~7]<3 '@0"=.u=Y@49H3/333,G W? ?0?"GT>2P333"'PP??29/^]9?2]99//]9102#"&'#4>"32>54.##532>54.w`vC?xm` Jc@@HP/OH@   @ @   ??33?3/83/8^]39=/333/8]^]]+10%#4>733>73`" %` Ǽ>~4*y?>(]ZPR]Z!Lo-2DQ@.F8.3H$WF@FFFF=H.VE$B 88 BP)P ?3?9/993^]]29/9910.54>32.#"#".54>4.'3268]C%3\}JDq`Q#J IQ[3*<'=A)1l~XC=unjzSQEoYI:bgBoQ-Z\^9Y@7#-W;;;;?;_;;4F##GV:P9y9999 1P( P??9/]]93/]]]29/910#"32>7#".54>75.54>32&&#"3)F`73\QG;mql5&?R,+F3:iV5ZRM(?KGls'Hd=[^3E*")1VuC>X>) +>P2FmJ& "&MM-@'qoj39@.F 555 H))V4.P?22/2/]]23/3105!#>54.'.54667#~L( -TxKG_:"++"0[MY\.\l+/(`/{vͳo0Yl@#.;H*-XRK HHC%"Blfl^1@GU` G TP  ????32]104&#"#33>32\ipQnC ER\04f`J+?*Gq+'[@:%GW)))))@))$G V(P$$$$$$$PP??9/^]]]]2^]]]]q210#"&&5466322>7!"!4p~vt83o~vu:+IhE#!DhJGfD#3  mm))lkJߕߕKE͉wH5@#0   `pGTP??^]3/]1032>7#".5Z?H-*$ )04>jM,Hab  NeJ!.h@*") ) )P4D 0`000.@.)PP??9/3?/83^]]3/]]]99=//339310#'.#"566323267#".'.'#5 +=+"2B#JiO?H.&&7%';/%  53)C1 *Y]669 (@.!^aWMOJ?@& G U `pGT P  ?3??33?22]221032>53#'##"&'#3djoRnC 0gHj#4e`:ST.*&(#U*6J;@ GW ?2?3/82^]]q9=/331033>53# ZrB%\uJ!cg\`qojF~@N2;;*AF8--$ F H?H_HHHHH$VG<28P9*IYi8$O9??9/9]]922]]]/^]9/393/310#"#>54.'&&54>75&&54>7##5!#"3#QW--TxKG_:"++"0[M/Nf7er-Ok>"'!U.>7IsG FrQw1UqAN`;".;H*-XRK HHC%""ǵMcC uHfI1&NuN5Q7q-^RJX@8 G/ G/@HT PP???22+]3]3/]3/9/]10%267#"&5!##57!#P/J0qqm݉'/  PJPNF7-^'9@!%HW))@)) GT(P"P?3??22^]]]10#"&'##4>32"32654&-?uhK6AxiawC;6K{}'ՑL--+.'a.ӑKK31qoo^1Q@6''F   3?3_3333HV2(-Q7 (8H $??9]]2]]]23/10#>54.'.54>32.#"-I~aG_:"++"0[MMb7IjN268<:PrI"`yN/.;H*-XRK HHC%"AvI"  9pqJ)6@!$!HW++++++H V*%PP??2]22210#".54>3!!32>54&'#"->zuk}DM΀%A0!GnMLmG!OK;_Z+oPF˅ڊ>)]l|6Ui;7bNY,cfJ:@$   W+;GPP??2/]]]^]210!32>7#".5!57f->$*($ '.5@uY4׆J;R3 MhsJP=J)@GW`GT P??3]10".5332654.'3\d) BfF PmXVc6G}ut==rwKq%^%5^@<1%G&HW7 777o777@777GV6+P 1P$??32?3^]]]]qq9/]3210.54>746324.#">fmK 8N-%?-3Xt@Zf7VhO6I+1%H{Y3C՗S}7`3hr}Goa0^PzِJ&%be35WA;k%N(@hxg w  v7@H4@ H**?*O**%%%%@)'( P#P???9]]?3/833/]^]3/+]3/8]+39=/]]33]3]10233267#".'#&&#"566-I:1{s&4%.9(C_G3ƠG5$>N>\=J &B3 &FfAj>OY  q'L@/G&GW)0)@))))))!GT( &P???32?3^]]9/3210>54.'3#.53VN_4WmoL6ZxBs 7332>5332>54.'3#"&'#Z`2/ /6K-.D,cQ-K6/ /2`Zk RyQHIRbe4)Hb92΁4ebRIHQy˒RW[[Ww&j@ &2*%+55+55=&j'&޴2%+55+55q-!&RT@ ,&= & %+5+5=!&T@ *&$%+5+5q!&T!@ H&`<<@ H=554&#!#!5!!!2/FD' @3!i{^Z]e55_ 3WEst#o1^Yie1s&av3R@ &> %+5+5}&_@@H#p###@$ H##(([f'_ $_  _?3?39/^]2]3/+]]99//+10"!!3267#"&&546632&&_xM t@vqYN'NUa;LWlON?'AzoɊH#ln,* .h6Rd,@w+&,j R@ & %+55+55H{s-*5%+Z @SHZ#######P#####/[g777@ H65_%%%%+_#`+`???9/^]3/+]99//^]]]^]38]+2210#!!#"&'532>7667!3232654.##<~†!"5OnN#J: 0>* '+m~7ww.[]Xap=qQgo; ?bu69:BqFa< !S@2Z ###### Z d"!_   ` ?3?39/^]322]q9/3210#!!#3!33232654.## <~†Hm~7ww.[]Xap=VhBqFa<s@MZUotZ0@Pgw^?O_ _?3?9/2/]]]]]3/]22/]]]^]10!2#4&#!#!5!!#Z]e5i{^1^Yst#s&vR@ &" %+5+5i&6#R@ '& ,"%+5+5 c@AZHG: Ze o  Zd _/33/?3]]]9/]]+]]]]10!!#!3!3Z]$3K@._[g_ Zd_   _`??9/^]2^]9/]10#!!!3232654.##3<~†~7N.[]ap=7!3!! dq/VMA0e.=FM''UijLȷK(@Nf v 7 G W  G  Ziy8HXWgw  p  @& H  @@ ?33?33933/8333^]]]]]]3/8+]q3339/]]]]33]]]23]]10333###%  !<<<H9h@?'[!0!!0[ g;;p?O_: `!x!!!!/,`5`?3?39/^]]]93/]]]9///910#"&'532654&##532>54.#"'>323[}KW^2C͉nU+`cc.Ϻ\a2%D_:nK\&btGmq9`IxX9  9YwH`t@"-$ 'He=6S:C6}6)6ak@ Z e 0 Zd H @# H  &  H H ) ?22^]++?3]++322]]]2210333#46767##ɮլ1>CC JLJ9ALMFi&6R&" %+5+5 ^@!   /   V  @ H Zd ?2?39923+]]]]]3/8^]338310!##335<Bb@;HZPZe!!!! _` ??3?3/^]9/^]]]38]+210!#!#"&'532>7667!!"5OnN#J: 0>* '+qQgo; ?bu69:/0+}q2n33}&7!o@!`p@ H### @ "@ H _ ?2?39+]]3/833]3/8+]393310#"&'532>733>7T&Spo3Z%%Y45RB8  7]{H5V??  !hs`;q ;@!Z Z   Zd _?3/2?3]]]3/10%3#!3!3H@Zep/ Z` p  @ H _ ??39/3/+]]]]210!##".5332673sb]e5i{ZpV,.1_YGst((3 `@BVZgw Ze   P p  Zd _?2?33^]]q9/]]q]10!!3!3!33q@KV  Z  g w   ZZe PpZd  _?3/22?33^]]q2/9/]]q]10%3#!3!3!33R@3 Z[g/?__  _ `??9/^]3/^]q9/]210#!!5!3232654.##<~†7N-\]ap=BqFa<I@+[Ze Zd_  `?3?39/^]2^]9/]10#!33232654.##33<~†~7N.[]ap=BqFa<VJ3H@.[g_@H@ H Zd_  `??9/^]2++^]]10#!33232654.##3<~†~7N.[]ap=BqFa<;D$Q@/ [  g&&&&%_x__?3?39/^]]]3/]99//210"'6632#".'532!5!.^?NOlRR:aVN'NYq Gs'. *,mm#oz@.^@<[  %[g00?0o00000@H Z d/*_ _   _???9/^]?2+]q9/]310#"&&'!#3!>3232>54.#"O喗PV UۑO1glmf00elmg1ݩldVZk뫉ۙQQۉڗQQ@ @$ HZ e? @ HK@ H@&[@Hf`` ?3?9/3^]+]3/8+]3+]q]]932+]q10#.5463!##"33B}7cK,uJsO)'NwQ\>a]J\>aDBiJ(^^Du!#';I@,-H W===@==7HV<2P(P#  H Q?+?9/32^]]]]21046676673>32#".2>54.#"u1hq}f!2{}u,>dH) >Tk@ce2E|hk{B4&#!32>{k8aG)/eq9Sg;8]C&ml>\?5hu$=[?CtV0J@k\H*E M@$< J/@PGTP??]]]3/]10!#! Z\PJ)7Jy@F /? @9     GF U0/FO P?2?22?3/]]]]2/99//]]8]]310#!#3>7!3!#7NVAcC"$:Q4}_P$gSq^HJ@ F     H@$ H0p @  ?33?33933/8333^]]]q3/8^]++3339/]]]]33231033###3XCDX5--5DR^9_@:F99 4G!W;;;;o; ;) V:8P999999/P&P??9/^]]]92]]]99//9102>54&#"'>32#"&'532>54&##5q=dH'slGK?(MRZ5Vi:3F+,R?&5lqm:LWa37`F)'@-MM&" &JmF2M;) ,BZ>CuV1#"*E3^[;J Q@ HFU   H @ H F T   ?33?332++]2+103##Z  JdjJ;&6%& %+5+5J A@#   GT  ?3?393322]3/8]333103##3aKJ-JJL@1FT GU/ PO???3/^]9/]]]q10!#!#"&'532667!@_V17YE3TiuoJ ^@?FU""@"P""FT!;K[ )4DT& ?333]]?33]]32^]]]210!##.'#3>73  9;6P 1;>JG"C<21;A!;J [@GU 0 @ P  @#H G T P/ ?2?39/^]]]2+]q210!3#!#d!߶J9Jq-^RJ-@GU  ` p GTP?2?]10!#!#!ddJ?^Sqo^F)^JX@<  p _ G`pP??2/]3/]]2/^]]q]]]q10!#!5!^5P J\q#")t@K' F I   #HW+ +++++o+@+++HV*&P'P  ??32?32?^]]]]]qq9/]]+332210#.54>734&'66!qLGwrLGy X}P%9Z U}}ȑV $ V~}ǏU < =g^#J[J D@+GG   ` p GT  P??2?3]]3/^]10#!3!33}JPPJ1@ G U`GTP  ?2?9/3]21032>73##".5P-PLM*,PU^:NzR+Jf,0 /TsDFJ f@CG  t g  GU   o @  / GT P ?33?2^]]]]qq9/_]]_]]10%!3!3!3hJPJw@N Gtg GG @/GT  P??22?33^]]qq]2/]9/_]]_]]10#!3!3!33}JPPP)J\@>GWP`?G     P `  P P P ??9/]/^]3/]q2]]10!2#!!5!4.#!!2>H/eq9!A`@7]D&M|X/1B()BPJ a@@G p G UG TP P ?3?39/]2^]]]q9/^]1032#!3#332>54.#d/eqb춶8]C&!A`@M|X/JJ)B01B(J @@)GW pG T P P ??9/]2^]q10!2#!3!2>54.#d/eq98]C&!A`@M|X/J)B01B(7B^&^@> H"W(((@(/@ HX' P/QQ??9/^]]]+q2]]29/10"&'532>7!5!&&#"'>32BY|66RItR0# ;<85@HN&fMQ%(T\   >۝ԊC^&r@KH O !HW((/(((G((/( G T'$P P,   P???9/^]]]]?2]]]q9/]q310#".'!#3!>3232654&#"@xjbuFﶶ HvcbyD)~~'ՑLB|J9tx>Kӈ#JS@GUo@F@HVPP ?2?9/2+3/83^]293103#.54>3!##33#"#-TA(8dS%AZ6kh 0LlGNyQ*T0F.f_q&Hj@ 1&(<%+55+551S@2 G-U33`33#"GT2!O#P)) ))P????]39/322222]910"&'532>54&#"##5353!!3>320?6#.#ipQnC{ ER\0"Hm 'A3D4f`Չ+?*M{W/ !&v@ &E %+5+5qo^"O@1 $$$@$HV#P/Q Q??9/^]]]2]]29/10".54>32.#"!!3267ReJLfN268<:# Q66{?Ֆۉ>"  %Z?^VuL%&j@  &%+55+55uMJ*k@E F%G $  GW,,/,?,_,,,,+$P% PO%P ???9/]3/]99//]]]]21032#!##"&'532667!4.##32>.eqb@_V17YE3+!A`@8]C&M|X/iuo1B()BuJ!S@0GG W###?##GT"PP?2?39/]322]]]]9/3210!332#!!#4.##32>d϶/eqb1!Aa?7]D&J9=M|X/J1B()B!S@2h G!U##`## G T" OP  ?2??]39/322222]9]10!4&#"##5353!!3>32\ipQnC{ ER\04f`Չ+?*\!&v@ & %+5+5 &\6@ (& -#%+5+5J Y@=GvJZ GU  ` p G T P  ?3??3]9/]]]]]10%!3!#!3d}JD@,Z  Zd_ ??3/]]]3/]]103!#ú-- 0@G GT O??3/]3/]10!#!3 Z?J?s&:CR+&1+%+5+5!&ZCL0&60.%+5+5s&:vR@ 7&d+1%+5+5!&Zv@ <&i06.%+5+5+&:j9R4&+?%+55+55&Zj9&0D.%+55+557s&<CrR & %+5+5 !&\CK#&)#%+5+5Ry@  H?/3/+105!R\ѨRy@  H?/3/+105!R\ѨRy@  H?/3/+105!R\Ѩ1N*@  /]/]/33/310!5!5!5!NRR1P %@__o  ?//]3]10'>73%'.46z|{8=|5P %@_ _o?/]/3]10#>7B'/37y}z8<|5?y 5@ H _oH?/+33/]+10%#>7j'/36z|{8=}5R +@__o ?/3/]3]10#.'74.'5|<8z}y7 b@H_o_o P`p_o ?32/]33/]/3/]3]]]10'>73!'>73'.4'.46z|{8=|56z|{8=|5 b@H_oP`p_o _o ?22/33/]/]3/]3]]]10#>7!#>7B'/3H'/37y}z8<|57y}z8<|5? ~@Q 0@`pP`p_ _o@ H ?22/+33/]/]]3/]3]_]]]10%#>7!#>7j'/3H'/36z|{8=}56z|{8=}5{h |@R o  0 @   w j T E &   6 /?222222/]]233]]]]]]]3/33]]]10%#53%h77777K_{}@q @P  zdU6F  P   /222222?222222/^]q333/222233]]]]]]]q23/332]]]q10%%#553%%1L78L//L87L/y"xmF@$/_o_ o  @  H/]]/+]]]]104>32#".$?V21V@%%@V12V?$Gd??dGFd??d'9@v;$;;;;;;;d;t;K;4; ;fv($2222222r2f2K202 222 Td -7#/3322/^]]]/^]]_]]]]]]]]]]q9/]]]]]]]]]]q1074>32#".%4>32#".%4>32#"&"./""/."%"./""/."%#./""/6Io&5!!5&%5""5%&5!!5&%5""5%&5!!5&%5"Bf ';?I]@\@TJ2#(>0<@<<0(@(><((<>EJ_?_O_____  0GYCO?>%7!-?????/]]9///]]]1032#"#".54>3232#"#".54>32#32#"#".54>32GPPG$JsOIpL&#IqNKqM'GPPG#JsOJpK&#IqNKqL'՞,GQQG#JsOJpK&#IqNJrL'JHlv??vllu>>uJIHlv??vllu>>uJIHlv??vllu>>uJ Rs<@ H?//9=/33/]]+210R5uu)NNRs?@( ??//9=/33/]3]/]]10'7uu5eN\\Nbb' /11]]h@ ??/82/8310#h՝+JjA@` @ H  ??32/+2]]]104&#"#33632??-A*i @QD4WAXeP`v@H   0Z `_?o@H _ ??99//+^]32/^]3/]322]3/]99//10!!##53!!!!$ܳ'D#0@ o+'###@> H22)%@ H%u&&)u* *o&***?*O***&*&*ts??299//]]]3232/+33]3/+399//33322102&&#"!!!!!!5>55#535#5354>jBB8K0RY@+ )DaCW_2*5y@1on$@H@, H777@ H+#n$|6u+s"""$5s%$u ???99//322+]3/++]99//32210%2>7#".5#57733####3232>54&##;$#P?5X@$Ak44|̘/{:][.9 "FjHRMӉVLN[M9mg GqQ?J9(6@K H;;,## o."c(((:#`$$,`--_$$$$$--/-_---$-$-7t3_?3?399//]]32323/]332233]3/+39910"!!!!3267#".'#53&45465#53>32&&Ev^CA"K;;[sXXraOP3w'4c[  ) Iy.}ʐN+1++H@ 9F@JpFFFFFF1"J@111 1111B,=6' ????/^]q]q9////8]]833310##".54>3232>54.#"".54>32&&#"3267 ՝+n-PpD?nQ/,PqD>nR/3&<+*<%%<*+<&EyZ45\}H3d !U"g_3Z##cJSW--WSSW--WS3V>##>V34U=!!=U&RZ_R&k tvkw{-:U@2.p#@H##<5(n 06v((0vu  ?3/?9/3322/]329/+10%2>73#".5556674>324#">o 9.d&FiF:jQ0.a14_-@hK6W=!5\|G$7cf ) 6N3w2R;SZ0%Tc y;lS1*OoEch&0Q;!!2E*j!Nby+7;@rZ99,"0@"" 2::/:::g=o===@=  Z d3232654&#"5!v)MmD?kM,)MmD>kN,BHQQGGQQHcMLA9LLJ CC> SY//YSSX..XSqssqrmm%P @] o0@P ğ""/"?""@H"@H H @ H?333/333+323+3/]++]]2229///]]]]]]2210##5!###33#4>7#h @{ell%"I'/ ## NvfH"/;@!#J1/JN+/;///)N N??9/]9//]2210".54>32!32>7.#"yƆE,Lfv?qŽQ@MX.Jt^M"H$Sn;M]53WI<#^nc~\<Oу," 326454&#"5>322>7.#"; AemjS"2Qsb[-DCACKO%}c*5^QC5% );I*>fO:%-FjԼRBnL32>32267&&#""32>54.1+MmB]AFNS+AnO-+NoCU>DOW0BmM+{?l41kE(@,,A|?k73lD'@-.@?rW4is0O8,RuHAsV1kp0N8-RuWa^Z3D&$B2jWa]\3D'&C1#7@#%%   ??/]3]]2]]]102&&#"#"&'532>54>"K=$3B'2Y|J$K>#3E*/Wy 'AT-^V) %@T0'^V(f{%#GK@.AII.  @)1C   @H ;.C?33/+]323/]3]210.#"563232>7#"..#"563232>7#".%7-)<;8d27C/%7/(<;8c27C/%7-)<;8d27C/%7/(<;8a27C !,l  !,l   ,m  -l f@   @O    @{hB9  / o/]]33/^]]q3223233/]]]]]]]]3]299//883}310#5!!5!3!!!'^>yIi{;9f R@2 @ @o0 Pp?/^]]]q33/]]29=/33/]3]210%5 5!d!dfqf R@2  @ @o0 Pp?/^]]]q33/]]39=/33/]3]21055!fdBjfXm? ]@6   @ P  /  /?99=//33/]]]]99333310#3 ?L 1&IL$@P/@//]]]]]]]55&IO"@P!@!!]]]]]]]5?@) 0p 0  @ H/3/+]3/^]3/]]]q10#".'332>71]dgX)2L5,I6"NvQ)'PwP9I)+H5dJ#@ G  T P??2/]10"&'532>53B0?6#.#"Hm 'A3M{W/y @ ? ?/3]10>73# ).`MQP!NVV o;u @  //2/310>73#o ,6bVLTS!MWV!}! @  ?/2/310#5>73 -7bLTS!NVV!%9 *@ O@ H ??/+]1032654&#"#".54>32GQNNNNQG#JsOJpK&#IqNlu>>ullt< J F@*  _@ H   /  ??9/^]32/+]9/33210##5!533!5467}y}  oC*c1 %*(;7f$J@!"" &O&&&@ H @H !??9//++]39/333102#"&'532654&#"'!!66B=kO-?y,<=;U__Y %'%C!9m#DeA LXMU+{%9-8@  !/O///@ H) $??39/3/2+]910#".54>7366322654&#"*NoD@nR/E~n-O`@ cJ6Z@$DTMG'?--=fAoP--XSnm'm@O`;+1%Hi\VRZ)7,I5/Jd8@O@ H??/]+]9/810!5!@b5J{d19q%4Dw@"8!B =2!!,FOFFF@ H&@'H =2K2[2k22225====)5??9]9]99/++]99//9102#"&54>7.54>32654.''">54&R4^F*'4">0*Mi?*8.#+H_bJHJK'7!AB8? -, A7T8%>2(-7E*9]B$s*E8++5>%8S7h;FF;0' "M76*$ #,67!9{%5;@"1 7O777@ H),&! ??9/3/+]9210#"&'532>7##".54>32%"32>54.{!Z@6Sl@ $0=&<`D$)KlCArT0DVJL&?-*>B`[} 5Wr=$%GfABoQ-/a^XLX)3$H;$T #'+/37;?CGS_ox@Y4, 8WQzpotgdd~kpQQQQokkoQ]O_D($ ]PK`KKKA=1 *BF>&2oygppz`zoTHHpooaoo@% Hoo`ZNNx`/`?`o```, 95!/^]3333/33339/]333/33/+]]3/339/333/3/3/3/3/33333/]3/33333/]39///]333/33333/3/3/310!#%5!#533!5353!5!!5!5!#3#35!#35!35!#35#3#3"&54672'2654&#"32##32654&##32654&#532653#"T/0momImmmm0oowoooommH??HEBBmp--83m^{B.$)0;J1%&4 %1}h_=0oo/mmmmmmoo;mmJoooo/yhhg^^ff^^gCS1D D:QYb" "+% *f$2r^dT#/P@(##$ *0*@***O$$$ ##0---''/3/33/3/]3//3/3/33/]3/]3/310 54676654.#"663232654&#"TV!LcM1[Q+ZWR"RD~8?>'REJGFDGGDFGVW/,>:LYEkJ'#".:/1DA5yP;>II>@IIU!&7LP + Ou@GM C>;GCC;GOQQ?Q3G "P)>OONN))0)@)P))N)N8PH8P??99//^]32/]]]3/]39/999910.#"#".54>54&#"'6632324&'.54>323j 9M[0LV.j<@ăoV" 6%%d62E, 0N:C'QYhuKlt=XH8iR3:s7_}E(]YK-! 2D(#V]a-*J620>KxQCpR.TߋH"@$$$@ H"!!@!!!!@D!!   H } k Z O + ;  ZwO! ???99/^]]]2/]]]]]]+qq93/8]]]]]3+]10>7>32&&#"#3=?</5@)#+  # (2662BK,(=' *#Un</`J<@Gg//G,,,,,,7H>>T>d>>>>@>0>>"H0@P@H--'P 2'P?22?229/9/+^]]]_]]q3/]9/_]]]]]910"&54>7!57!##"&'#32>55332>54.') +&ĵj (6K-.D,bR-K6$9}~{8JP8{~}9W[[W6vyz:bN!)Hb9!Nb:zyv6/u&0vyT@ '&K %+5+5!&Pv@ :&z-3+%+5+5&$[ %+55^^&D[ =3 "%+55&2R\@?-5 H!@55 %P@]]]]]]55++55?55s7:@(?O_0  0@P/^]/]]10#".54>324&#"3267#=T12R; ;R20T>#t@12?981@3Q88O33O87O45<<55<<h B@ 0@@ H+      ?O_/]99///]]2/+3]910>73#%467#"& 08>Rxz<9%2/:EKOQ$ MPQ%xNsL.%'F&I'ILD8@&9p9@9/999KpK@KK]]]]]]5]]]]]55&I'IOD6@%9p9@9/999=p=@==]]]]]]5]]]]]5}% 4K@, [+[ g666p6/6_6![f50_ &_??99]]]]3/9910#"&&546632>532>54.#" (?Z?+-Q훣LL爛Q)14krrk22jrrl432>5332654&#"-C}ogGC|od?.4-?V9 $'ՑLLՉӑKGD 7K]3Jx^CA^N$Q@2[#Z&p&&&_&&&Zd% $_??33/3]]]3/]]q33/10>53#".5332>74> 2U[BɈąDYR(2Nd8GiJrĐRMzH6bQy'T@3J!!G'')))))o)) )0)G T(&& P??3?33/3^]]]q3/323/10!'##".5332>53>53u ER\0[\/joQnC4> 2U[+?).bi=4e`:{2Ne8GmH! @ _/]/10#.'53y#QM@+.0SXQ#PQLH! @  _  /]/10>73#H0.+?MR"yLQP#QXSF8@#/  @H@ H /]23/++3/^]]10".#"#>3232673B(OLG-0h!5J.)QME-.h!5I#+#5>54.#"56632y-<" q%<*$242)':)o! l[1}  //104632#"&1>-+?'-><77<+7s&(CR &´ %+5+5s&CBR& %+5+5q!&HC(&.(%+5+5;!&C & %+5+5}^Eq@H9Z%666666A[ gGGGG GPGpGGG.[fF773)_&&" H<3_?322+?33329/^]q9/]]]32910"'6632#"&'##"&&546632&&#"3267332>54.h<^*L;Qw}@?ƈoIKnƁ?@}wQ;L)_733>53#&&5w& w ZrA%\uw  JVW3:AE  !cg\gT 5 !@ Z  @ 'H   H @@ H [g##0#P#`####P#!_ _O` ??99//^]]]]32/]]]q9/++]_q+39/221032#!!5!3!!32654.## ~7<~†<y.[]NBqWap=`@Fa<m'!@ G  @G H GW###p####P P@ H0P ?/]]99//^]q+]32/]q99//+]32210!!2#!#5353!!2>54.#/eq9+7^C&!A`@לM|X/)B01B(-X@/[""**/!Zd.+_'_"!!! _?3??9/^]3322?323}/9///3210"!!3267#"&&'!#3!>32&&m_xM t@uqYN'NVa:RVclON?'AzoɊH#dV\,* .q^)d@9 HO   '+ GT*Q P   /  #Q&?2??9/^]]3322?323}/399//]3210".'!#3!>32.#"!!3267TaO U^N268<;# R65|:{J9r4"  %/ @Iw   p@H@@ _ H  ??339/9+2/83^]]]+]3/8]q39/3]9=/339999]]]]q]q10!###3##'!'.'9;z#5 VJ0LCA%%ACI- ZJ @89Yy+   @ H   H   H@ HP @ P   ?33?9/92/83]]]]3/++389/39=/]33+]+]9999^]]]]]]]10]]#####3.'``q#% %#JJyU`^""_`T) @w @]+{/p"0"P"""" Z d!_  H  ?3?3339/9+3222]3/]839=///^]]]]]83333999999]]10!###!#3!3##'!'.'祁;y#5VVhJ0LCA%%ACI-J@1w  )Iiy     G@ H H @/ ?   T H@, H!!!`!p!!O!! P ?333?39/9322^]]]]]3/++8399//]8339=/]33+]+]2999999]]]]]]10#####!#3!3.'T``鶶Tp#% %#JJ9yT`_""_`Tj#&@"Y% H&@, H% $$Z&     @; H(((((@(P(p((?(#a$ O &_?22?229/^]q332/3^]]]]q3/+]]q39///]39=/333++]]10]3>75!#.####"!{6T|_IaV7z{&6O==O6&{JoUb:狋8bV;H_9H9_H?Z J#&@ v% H&@ H # $$F% & @H   H@? H((((`(((O(# &PR$&$6$$$ O_?22?9/^]33]222/3]]]q3/++q39///+]339=/33]]++]103>75!#.####"! {,BgSShC,{{$0D55F0%z T=eM1 dii1Lg=P6H+ +H6-(+@Y ))Z * H+@3 H*+   (p@4 H----@-/- Zd, +_ !a)    ?2?39/^]3322222]]]]3/+]q39/]]39///^]33++9=/33]]10!667!#3!5!#.####"!3{){JaU7{{&6O=32.#"#".54>32>54.##532>54.#"'667.'53>32&&#"GZ4$=/AaSQ2+B1# 6M51GJ\FhO 1flYQ&9gX\a2%D_:nK\;g762y3a6;CK*/ "00.R~U+3[}KW^2C )$  )H`76S:C6}0KA?:"a8$F8# w)8! ?\vEJwX9  9YwH`t@sRRp@q@ Hhhbl lXFl__R3l3lR_CMGWrrrrr0rr&FC@ HCQPRRRRRbHhR@H@ H^l[P b4+P>HP!??3?33/++39/^]]9=//+^]]]]9=/////]933/33/10+2&&#"#"32>32.#"#".54>32>54&##532>54&#"'667.'53>/ !..-7Y?#3F+,R?&5lqKY/":,2c]S!BG "(, Udo9Xp@"Vn7dL,a=dH'slGK?9kA10,y3b6:CKR w&31EX52M;) ,B[=DtV1&#   .GV)/YF*+E3^['@-MM&"";72"a8$F8#huq}q)O@2%[g++++?+o+$[ f*`O$$$$$$__??9/^]q2]]]]210#"&&5466322>7!"!.qQ훣LL駱Qjk9:kmil=d;iݪllkkGzz†GCuuCq-^!O@3HW#@####H V"P/PP??9/^]]]2]]210#".54>32267!"!&&-C}ogGC|ogG# > 'ՑLLՉӑKKԲDZ@)   /O_ @ `  ?33?3?/83^]]q3/]9=/]q3310"#3667>32&&$5*$'.*=LgK#D5-%HgBa[ONaqb+  Rm@ H H H@ H!!!!P!!/!O!@ O?2??33/83^]]]3/+]9=/+33++1033>7>32&&#"#  V5CX<" &/:J!jna_lg!@^uBPXs&vR&1%+55+55!&vP &4 %+55+55} Z'J@ [8J//7)(@#((@@@@@/@?@@@ 67777@4 H77LLLL/LOLLLLL[ fK8/JJ(DP=6(#__???3?933^]q3/+]899//]]]q3/89=/3310#"&&54663232>54.#"%33>73#"&'532>77LݑGGᙐݕL#/agg`..`gha/C  ǼN@VtP4L@#0F4%9ݪllkk뫉ۙQQۉڗQQ(XXS"Va^!c'QZ1 ,@)qN^&R\o / %+55}1?R@30[gAAAA0AA [f@ 85;_(%_ ?332?3322^]]]]_]]10#"&'.54>766326632>54.'#"&'I|J7;H LJEEǁ H;7J{ʼnJ-WSC51ERW--WRF15CSW-ݕ}?66?}{?13=}tb0&(.btsb2))0aq7T,HW99H9@$ H HV8 2/5P)&#P ?3322?3322^]]]++10#"&'.54>7663266326654&'#"&'9k_ <8:;]n=9lb;:7= [m732>54.#".#"#54632356654.54632?<^*L;Qw}@?ƈgEGgƁ?@}wQ;L)_32.#"326732654&#"'>32#".#"#5463235654.54632Qm++jP_J?mT@<4?)++piIs)19B)ip++)@5   4    >۝Չ?$+$.4#le$*$MsL)3  &&F}^ S@b#GZ3DDDDDD+O[ +gUUUU UPUpUUU<[+fTEEA7_04  ?40J# H#A_&?32+2?33/]339/3329/^]q99//9/]]]32910#'##'##'5"'6632#"&'##"&&546632&&#"3267332>54.R"21#12"P<^*L;Qw}@?ƈoIKnƁ?@}wQ;L)_733>53#&&5R"21#11#P& w ZrA%\uw  gggg\JVW3:AE  !cg\gT 5 }#T@Z@H ` p  @ H %%[f$!_ _??3?3]3/+]]9/+^]10"32>7##"&&546632&&k{C;vv-(%LWlON?'QډۖN bln,* .qo^>@%G@H !_!!!HV QQ ?3??3]]9/+10.54>32.#"3267##JLfN268<;>h#?Ֆۉ>"  Zhy %@g               O@   `p@M H 0       @ H/3/+39////]]]3/q3/q3/93/9]3/2/+]39////]]333310^]]]]%'%7%7%LG㴁FGJ{J;{Z}9IĤ{B  H@ H   /2/2/3/^]33/3++10#"&54>3!6632#,08( %-08*+9,338% -1269)B@ @ H @ /]3/3/+^]3/]102>32#54&#"##5Nwp:m|:.*eyUf$+$el#4.$+$5 @ ?O?O_/]/]29104632&&D;/2%97'>737.'.'57>7'>7'.'7.'7  #a ;  #a #&UWW'*][W%h'UWV'*][W%"PTV(E%ONI#OTV(E%ONI+)'$C342j('%C442#'UWV'*][W%&UWW'*][W%  #a ;  #a )'%D342)'%D342"PTU(F%ONI#OTU(F%ONIh1@H0&&&& &0&&&& Ze333 303 Z d2&@ H,!H@& H& _H H ) ?33^]++?33]++??3/+]322]]]22339/39/]]]q3/10!46767##3333##".'332>7d1׮Ïڦ1]dgX*2L5+I7"8ALMF>CDJLhMwP)'OwP9H),G5%@:4    H F U'''''''' 'P'`'p'@% HFT&@ H   `?22?33??3/+]322+]_]]22+339/39/^]3/10!#333##".'332>7 {zG1]dgX*2L5+I7"jJdP}NvQ)'PwP9I),H5/3!R@,Z  [g#!_ _` ??99//^]]32/9/39/221032#!#5353!!32654.##~7<~†;Š.[]NBqWap=`@Fa<!a@;GW#o####GT"PP@$HP??99//^]q+32322]9/10!!!2#!#5353!2>54.#d/eq97^C&!A`@!M|X/)B01B(3"@O [(8Hg$$@$$ Z d#" `0 @  "` ??9/]999/]39/]9932^]]]]99//39929910'###!23267'76654&##3/K6nj]|j~32'"3267'7654&;`M< ;M`<^n-HԌDN .^^)ek7Lj/ @/@ H?Z  @& H _ / ? O  ?  _ ??9/^]q32/+]^]32]3/+]q9/]10!!!##53P} J n@ 0p GH@! H O O_@H P??9/^]+]32/++]32]3/]9/103#53!!!!\Z&f@A "[(((((@( Zd' _` / ?  ?   _??9/^]q?32/]]]9/10^]"#!!6632#".'53 4.%<G-WRv1ND=?HwC{ \O  y~@ J#\@9 "")" H%%%_%%%GT$ Q PQ???9/^]329/]q9/10]"&'532654&#"#!!6632)Kj.+jBvu>\Z;fL@o % 5J>۝Ո@@W@H H @H H  Z Wgw@ HZt@' H 0`p @  _?22?3393?3/8333^]]_]]]q3/+]q33/+8329/_]]]]3323^]++]++10!##3333#!  ð<<<J@l'7)9& 6 ' 7 '7'7'7@H H @H H  F @ HFH@ H@ H0  @  `?22?3393?3/8333^]]_]+]]qq3/++33/+8329/_]]]]]3323]++]++10]]]]]]]!##3333#CDXXOŮ--5e}HB&HHB %+55DBR^&HB)!%+55@Y@H H*@H H*0@Z Z d @ H H   _ ??3/?399++2]3/^]323/^]]8393]+]+]+]+10%3###3735l=yr%3+J@j@H H*@H H*FvmU+;K  G T  P ?2??3933223/]33^]]]]]]32]+]+]+]+1033###3aKfKJ_}-J@]HP`"2B@ H Z4TW  d/   0@   ?2?399//]99]]]3/^]83339/]]3]22]210+]]+!###3733wwAdbce#J@ H H@W H &/? GT  0@`  ?3?399//933^]q3/]833329/]]]3]22+10++'#3733##mm}P}{J{F I'/@@f@P Z d/_  H@ H ?2?399++9/32]]]3/^]833/833229/]9]310!###53533#73=yr`{3@ GH@5 HT  5  O ???9/32399]3/^]]833329/++q29310353!!373###{%om^ui%RZDW@3 Z 0@   _?2?399]3/^]8333/9/]29310!##!5!73D=yr%3)J g@@ G ` @  P ?3?393]]3/]833]3/9/^]q223103##!5!`LJ-c@?Zt Z @ Z d_    _??3?39/^]2]_]]23/]q10%3##!#3!3gVhJy@RG  G  $0@PGT P/  P?2?39/^]]]?2]_]]q3/]3/]210!!#3!33#߶!J9P}H ]@; Z@    0@`Zd _ _?2?9/^]3/2^]q]q9/210!#!#3!!!gVhJ h@!G G T  @ HP/ ?2?39/^]]]+]q3/9/2210!#!#3!!!;߶!J9ǚ'_@:  Z!!%[)o)$Z%d(`/??%#_&!%_ ?3?3?9/^]q]9/29/10^]6632#".'53 4.#"#!#!I.VRv1NC=?~IwC|kK3{\O  y~@  uJ$w@N ##Gw H &&&O&_&&&&GT% Q PQ?3?3?9/^]]]q9/]]]q29/10]"&'532654&#"#!#!632Kj.+jBvu>d:?fL@o % 5PJ' >۝Ո@}>Rz@PN2I[  5 5 ?[gTTTOT_TTTT+[fSD`N:: :`:p::::&_!20__?3/29?39/]99^]99//]9103267#"'#"&&546632.#"327&54>324.#">o'AU-6Q%FO&2|32&&#"3267&&54>323267 *9H8=>ALE9(bGuz?73Fq  ǼqN.d^OO^d.17@@ HZ w @ H  @8O_ _ ?3?9/9323/^]]]]]]]q83/]]]839///+]]329=/+]103!!#!5!53TB'ٻ&B=X3J@GH@  HPO0@O??33^]2?3/83]]]]]]3/++839/]]329=/10#!5!33>73!Fs  Ǽq cJ.d^OO^d.1@GH           0 HZ  @ H 0 H @@ H @('   _??3?399]]/8333]+]_]]3/^]33+]q/+]q832+]q9=/3_]]10%3###33wZLN[{/L#J9@%Y V  H= )    F @qHjzEUeuJZ@H;K' 4D(; H@I H`euJZ ;K( P  ?3??399/]]]]]]]]]]3/+3+]99//]]]]]]+]]]]]]]]]]]]+9=/32]]]+]10]]333###e3fg}L`@ ZZ@DH/O @P`Z   / _ o  0 @ P  @ H  _ _ ??2?32/+]3/^]2/]^]]]3/+]q3/10%!33#!!5!!q^_)mJ GGH@3 H/O` G`p@H P  P??2?32/+]3/]2/]^]3/++3/10#!!5!!!33m5}P1c@  ZZ@,H/O_Zd_ _???39/3^]3/+3/]210]%###".5332>731:ica1]e5i{-Z^f8V" 1^YGst Ja@  + GG @%H_G TP P??39/3?]3/+]3/210^]!#".5332>733#H,PU^:NzR+-PLM*0 /TsDf+P}p@. Zep/ Z`p@ H _??39/3/22//+]]]]29/^]3210]#".533336673##P!]e5i{ 8vDBw91^YGstX "JV% Jk@B P   $  ZU` ZT 0 @    _??39/3/22/]]29/^]]3210^]10#".533336673##/NzR+}/[32Y2}j/TsDf-0##3P@6 Z e/_o Zd_ ??39/]32]]10^]36632#4&#"#Ǻsb]e5h{-Z_e8--1^Y/su 9J?@" HGU` G TP  ?2?9/32]]10+!4#"#3>32\-PLM*,PU^:NzR+,+J/ /SsDZ=+6d@>2[ g888) """1 [p7 `1O++++%+%+%_,_??399//^]]q32]223/]]210>32!3267#".'"&546733"!4.f [ݍֈ>%?tp[*[i|L\  g[nA%V9[kEz†G,  auz*B>#aA~xuC3^,5@+1H'W7777770H @P@(H6P0+ +    "-P"Q'?2?99//^]]]]32+]q22/]2]]]210".'&&5467333>32!32>7"!4.5kK 11LtZcn;L3WQL'(MQW`r 9YFǁor'?:"/1lu>Gnq ۜDqP,=.9r@FZ"5[ g;;;, %%%4 [p"""":" `4O..?..(.(.(`/_???3399//^]]q32]223/]]29/10>32!3267#.'"&546733"!4.f [ݍֈ>%?tp[%NXd:ĊM g[nA%V9[kEz†G,  smuz*B>#aA~xuC3^-6@0G 2H-$W8888881%H   @ P  @+H 7 %P1++(.P(Q-??33?99//^]]]]32+]q22/]2]]]29/10%#.'&&5467333>32!32>7"!4.BLTc8 11LtZcn;L3WQL'r 9Y5 #uToor'?:"/1lu>Gnq DqP,Rd,i&6R@ & %+5+5&6@ &%+5+5%g@?![  @ H ''@' Zd&_`/ _  @H  ??39/+]33?323]9/+839/10"#3332#".'53 4.FA\(5VRv1NC=?HwC|o<XU엪O  yv: J#r@G "#### H%%_%o%%%%%%!!GT$!Q "Q ?3??39/^]3323]q9/9/q8310]#"&'532654.#"#33+^xE?oWLi/,iCvu#JrN U)j@ДՈ@%j`- PJ V#s@FHZP!""Z# %%%%%%%!_` _????/^]]229/39/^]]]38]+210!!#"&'532>7667!3# !!5OnN#J: 0>* '+Ï٥qQgo; ?bu69:fJX@8F`p4 GU  P OP????/^]]229/39/]]]10!!#"&'532667!3#@_V17YE3Tz{iuoP}K@+ Ze Zd_ _?2??39/^]2]]]29/10".'53265!#3!31ND=?HgR  VhݪO ;Ji@ GU 0@P@(HGTP/Q?2??39/^]]]2+]q29/10"&'532>5!#3!3Li/,iB;[=߶!?o %-aiJ9Ո@R@2 Z @ Z d_    _??3?39/^]2]2229/310%3##!#3!3٦gVhJv@O G  $0@PGT P/  P?2?39/^]]]?2]_]]q]2229/310!!#3!33#߶!{zJ9P}Y@!ZZep/Z` p  @ H _ _ ?3??9/3/+]]]]22/10%#".5332>73##:ica1]e5i{-Z^f8" 1^YGst J'J@@%GGU` G TP P ?3?9/3?]22/10#".5332>73##3H,PU^:NzR+-PLM*0 /TsDf+69@, H H   H9Z! !!! @ H&  Z d _ @ H  H ?33+3??3+22]+^]]2222]+9/3993+3+10]]!##!3!3##4>767##EÐ٦AJI?9Xw=ABGIJ$@Z "##F$!  &&&0&@&P&&&FT%";K[ + P4DT%?2]]?33/]]3?2^]]]]]2229/393310!#.'#3>733#o  ٷ{z9;6P 1;>JG"C<21;A!P}Rd,i&$6!R@ &%+5+5^&D6@ 8&%=3 "%+5+5+&$j!R@ &)%+55+55^&Dj@ <&/3G "%+55+55V^D^i&(6R@ & %+5+5q&H6@ -&2(%+5+5q)I@/$[g++++++@ H%[f*%_/_ __ ?3?9/]2+]210"5>32#"&&55!.2>7!y[*Zi}LTQ薙ׇ>@sC[mB&U),  l髮hkFzGfA~xuDf^'C@)"HW))?)#HV(#PP Q?3?9/]2]]2102#".55!&&#"5>267!nIBxfcn;3WPL'(LQW`s 9X^J҇֕NGnq  %DqP,q+&jFR3&Ӵ*>%+55+55f&j1&(<%+55+55+&jR@ && %+55+55&j&&%+55+55H+&jRC&:N %+55+55DR&jUC&ٴ:N)!%+55+55H r@-[[ @H  [g""p ? O _  _@ Hx` ?3?9/^]]]33+2/]]]9///+10#"&'532654&##5!5!sGC͉nU+`cc.Ϻ{=;5df`t@"-$ ѦuJ$d@>J J$$@H!$$! GW&o&&0&& @ H $!P" H"P ?3?9/+332/+^]]]9///+10#"&'532>54.##5!5!_}IGss:N[f6GwV07cTmAulnI$".W}NV}R'}횅&MR& %+5+5;o&M9& %+5+5+&jR!&, %+55+55;&j%& %+55+55}q+&2jR@ 1&(< %+55+55q-&Rj)& 4 %+55+55}q~q-^}q+&~jR@ 3&*> %+55+55q-&j@ +&"6 %+55+55;D+&jR.&%9 %+55+557B&j80&ʴ';"%+55+55&M'R$&"#%+5+5 o&\M@ %&#$%+5+5+&jR+&"6%+55+55 &\j@ ,&#7%+55+55s&SfR@ .&Q"6%+55+55 !&\S@ /&Z#7%+55+55+&jTR@ &* %+55+55&j@ "&- %+55+55 d@ @5H / O o  @HZZd _ _???2/^]]]+]3/+_]]q10!3##ð J N@2 0  p  GGT P P???2/^]]]]]]3/]103!!3#\ZJ}+&jR@ '&2%+55+55P&j@ '&2 %+55+55/m& <5m J&  <5m&;#H%++5#mJ&[P%+]5`@'FVI Y 69  0? @ p@' H/_ ('   ?3?39/99]]32^]3/+]q833/83/833/8399//]]9=/33]]]]10##!5!33!LNL{^/#J@ 6   9k{W:JdtX5E     6  @H @Hk { W : J  0 9k{X5E O +[k ?3?39/^]]3322/]]]]]]q]]q/]]]++]]]q9=///]]]]]]]]]q33333]]]q99//]10!33!!##!hJJ{f1L@@)Z e[f_?Oo_ ??9/]]]2104>333!".#"337Ϙ~<][.WqBhJ=p_33332>5#"32>5;-[^r+?Rg?Aזzga,H3][-~C[8PQf:aM&?.gr<hpi9P2CkM%>M)qZ2C\@9,8GP...GUEoEEEEE@EE/EAHVD3>P% ,3P ?332??39/^]]]9/]2910%2653#".'##".54>323&'&&53!2>754.#"ob/\[AgQ=D[yQ]n<jN-.^_)ek7ND?@V [ [+%  ++ 3Z6eAAAAAAA A0Ap?O@%`444x0_;`?3?9/^]]]]3/]93/]]]]9///9104.##532>54.#"'>3232653#".)5e]\a2%D_:nK\&btGmq93[}KW^22O7ob8fYWl<MmF!'Hd>6S:C6}6)6aOJwX9  9YwHJhAw-ib./dP^;@#G F16111'G U====0='@)H_'''<6P  &#P,P??39/^]]]3/93/]+]]]q9///91032653#".54&##532>54&#"'>32R1P;i`/_`\d5a=dH'slGK?(MRZ5Vi:3F+2S<"L'I8!5ib.+T{O^['@-MM&" &JmF2M;) )>RN1@T[' " " Zp....Z//333333 303p?O20'`  x   `._??39/^]]]]9?3/]]]]]q3/2/]99//910!#4.##532>54.#"'>323#8g]\a2%D_:nK\&btGmq93[}KW^2CdA 'Hd>6S:C6}6)6aOJwX9  9YwHP^-@ F"G))-G *0*@*`**@H**////@-H_.+"PO_ P)P??39/^]]]]9?3/]+]3/+]2/99//910!4&##532>54&#"'>323#a=dH'slGK?(MRZ5Vi:3F+,R?&+^e'@-MM&" &JmF2M;) ,B[=}1@eZHH1ZP$Z'e3O3o33333 33%%_!`, ?32?9//]]]99//^]]]]3+]+]q2]10!#"&'532>7667!32653#".5 !!5OnN#J: 0>* '+cnob8fYWh:qQgo; ?bu69:сww-ib.,`lJ(\@9F(G$ GU****  P O#?32?9//]99//]]]]]]10!#"&'532667!32653#".5@_V17YE3T1P;i`/_`\f6iuo=AbA 5ib..bi-\@7ZZ e Zd__???39/^]3/2]]]]9/]21032653#".5!#3!3bonc8fYXh:fww-ib.,`l-VhJl@GG GU!! !@!P!!!!!!GT P/ P???39/^]]]3/2]]q9/210!332653#".55!#d!1P;j_/_`[f6߶J9=AbA 5ib..binJ}R*G@)** )[@ Hg,,p,[ f+*_$_$_??39/]]2/+9/10!#"&&546$32.#"32>5!;BޜV_ oXH$SX].zB6pul])V[ii,*Qډ؜VBwdq{^(@Z(( 'G@ HW**$****@*P****H V)(P@H +"P"P??39/^]]]]+]_]]q2/+9/10!#".54>32&&#"32>5!{9xˈDLۏoM><[ae4)V^QtJ#JDȉGOӄӔP%'):mb]p>-PpDe@/Z eOZ@Wgw@ H__??9/2/+]3/^]]2/]]]]1032653#".5!5!!qbonb8fYXi:^_ww-ib.,`l)oJm@J GU0@`G`p PP?2?9//]3/]]2/^]]q]]]q105!!32653#".5)51P;i_/_`\f6AbA 5ib..bi5o 9][4@.H/ ';; [/f:4`x#`&*` ?3?39/^]]]9]2/99//+9104>32&&#"33#"3267#".54>75.;smH{iZ&\Kg9_D&,WWÿ]e5lSSÃB1_WJxT-`Oa6)6}6C:S6>dH'!CeC1+&%7#".54>75.54>32&&#"3)F`73aWML%+5+5q-&RR(&)7 %+5+5}%&_g\8'5;%+5+5q&`g0'-3 %+5+5&8g/@ ' %+5+5J&Xg'! %+5+5&8fR@ &- %+5+5&Xf@ !&0 %+5+5Ns&avR1&%+%+5+5y!&bv`(. !%+55Ns&aC=R%&+%%+5+5y!&bC.( !%+55N&afRY:%%+55y&bfV=( !%+55N5&aR`R-&G.<%+5+5y&bRN1? !%+55N&ag/('H%+%+5+5y&bg+'E(. !%+5+57&<g ' %+5+5 J&\g2#)%+557&<fqR@ & %+5+5 &\fJ@ )&8#%+5+575&<RR@ & %+5+5 &\R@ +&,:%+5+5q&BҴ:9 #%+5! -@@P?O_/]32/]]9/10#.'53#.'53d#QM?*/0d#RM?*/0SXQ#PQLSXQ#PQLjR@1 @/?O/_  _/]3]29//]99=//]]3310#&&'#56673'>73#d3l46j3e3u00t3N!-j7e"T00T";EE;-.4!3232673o3t00t3d3j65k3d$GE@(*]0A*%JE>(*\0A;EE;"T00T"Z"*20Q;!"+10Q;!s 2@ /   _/]322//3]29/10>73#%#"&'332>7^ -j7eo+MnFl0D,$A3!,.5!7d8j- +MnFl0D,$A3!,g<!5.,7'#'6654&#"5632+MnFl0D,$A3!+".V 8A9,' :dc7'".#"#>3232673+MnFl0D,$A3!/$GE@(*]0A*%JE>(*\0AE 4 Z fNo g .8*f 4 h    *  ,D p  ( F 8 \L \ TDigitized data copyright 2007, Google Corporation.Droid SansRegularAscender - Droid SansVersion 1.00DroidSansDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.Licensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0Digitized data copyright 2007, Google Corporation.Droid SansRegularAscender - Droid SansVersion 1.00 build 112DroidSansDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.http://www.ascendercorp.com/http://www.ascendercorp.com/typedesigners.htmlLicensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0ff  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.nulluni00AD overscoreperiodcenteredAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatdcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdot Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek IdotaccentIJij Jcircumflex jcircumflex Kcommaaccent kcommaaccent kgreenlandicLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflex Tcommaaccent tcommaaccentTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccentmacrontonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonos afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061 afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109 afii10110 afii10193 afii10050 afii10098WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave afii00208 underscoredbl quotereversedminutesecond exclamdbl nsuperior afii08941pesetaEuro afii61248 afii61289 afii61352 estimated oneeighth threeeighths fiveeighths seveneighthsDeltauniFB01uniFB02 cyrillicbrevedotlessjcaroncommaaccent commaaccentcommaaccentrotate zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperioruni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni1F4Duni02F3 dasiaoxiauniFB03uniFB04OhornohornUhornuhornuni0300uni0301uni0303hookdotbelowuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0483uni0484uni0485uni0486uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABuni030Fcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCcyrillicbighookLC  ,latnkern:LZZ 2 "  >$ ~`!6#h'L(h(h(n(h())0)6(h(h)H)V(n)))***L+++.$.$+0f2 "4544$$$$67D7D7D7D7D~88889(h(h(h(h(h(h)H(n>b>b>b>b>l>z>z>z>z>z)H>>>>>@$ 2(h 2(h@B(h "(n(n(n "(nA(h(h(hBR(h(h$BX$ )6A(h(h(h~)H)H~)H)H(n(n(nCB(nDLDLA````)#h*H''M8PN 2(h(nQQJQXQRR&RST(UXXYZ Z]^__`d@de e~eefpj*j0(hjJj*jjjjk(hkzkkll6lDlZlDlllll)Hm,m>)H)Hmnnodrs4sJstudv*vxVy||}JX$~v ڏ 2t,(^ $J(n"h(n(n(n*48>&)))#h*ڡ 2 2t$ (yy􀒔$(~$( $($($ 0ڙ(~(^v*ڙ(ڙڙ^v*$(^ ڙڙڙv*$$sJv*ڙڙڙsJyytt$($($($$($($($( ^^ڙ$((ڙ$($($($(ڙ 2 2 2 2 2 2 2 2 2 2 2 2(h(h(h(h(h(h(h(h$$~)H~)H~)H~)H~)H~)H~)H``#h*#h*#h*$,)7R9R:f;)<R=)FGHJRTW)Y)Z\)\))))R)))))$R&R6f78R9):R;)=)?)C_iqRy~))))RR==R=)R))fffR)(X`jm)rv=)))=R)R)R)R)=R===)=)=)==  ))R)!#%')+-/1368:<>@BDE)G)JLNPRTVXZ\^`oRp)qRr)sRt)-{{{^&*24789:<$&,02468:fmq_al~IKMOQSUWY[]_acegikmoqs7qrvc &*24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqs,79;<$&8:qEGoqs;) ) )&*24@)`)fm) )_l~IKMOQSUWY[]_K$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs9= = )")$9:<@)`)68:C_i= =(Xr!#%')+-/13oqs9) )&*24fm) )_l~IKMOQSUWY[]_9) )&*24fm) )_l~IKMOQSUWY[]_c &*24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqsK$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs533$&;<=q8:;=?C_i(Xr!#%')+-/13oqsK$,79:;<=$&68:;=?C_iq(Xr!#%')+-/13EGoqs 7$&q R R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJ_fimqy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt#$C_i(Xr!#%')+-/13R R")$&*24DFGHJPQRSTUVX !#CDJ_fimy{~R R(XY_`jlr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnf f$&*24DFGHJPQRSTUVX] !#@CDJ_fimy{~f f(XY_`jlr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjln) )&*24FGHRTfmy~) )_`jl~  68:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`R R")$&*246DFGHJPQRSTUVX[\]q  !"#9@CDJ_fimy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt9) )&*24fm) )_l~IKMOQSUWY[]_ = == =&f fYZ\79f fmprt) )J) ) ) )) )[]@f fDJDf fY"$&(*,.024R RWR RR RIR R6) )R) )`j  JLNPRTVXZ\^`= =I= =2R`j  JLNPRTVXZ\^`qx)qrx DD"&*-^24789:<=;IWYZ\^$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrst DD"&*24789:<=;IWYZ\$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrst DD"&*-^24789:<=;WYZ\^$&,0246789:;;=;?;fmq^ _alm~IKMOQSUWY[]_acegikmopqrstf f DD"&*-^24789:<=;WYZ\^$&,0246789:;;=;?;fmq^f f  _alm~IKMOQSUWY[]_acegikmopqrst9) )&24=fm=) )_l~IKMOQSUWY[]_7) )&24=fm=) )_l~IKMOQSUWY[]_ $C_i(Xr!#%')+-/13V $,-679:;<=@` "$&68:;=?C_iq(Xr!#%')+-/13EGoqsB$0=D;=?CD_i(XYr!"#$%&'()*+,-./01234.R R = )")$&*-02467'9):@=DFGHIJPQRSTUVXYZ[\]`=q  !"#$'&'679@CDJ_fimq'y{~'R R(XY_`jlmr~'''''  '!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt   o oI[]@ a= ="FGHIJRTWy~= =  `j  68:<>@BDJLNPRTVXZ\^`= =I= =d &*-24789:<$&,02468:fmq _al~IKMOQSUWY[]_acegikmoqsf f "@ERKRL=M=NROR`R )=RRRRRR -f:) )&*-R24fm) )_l~IKMOQSUWY[]_B) )0679:;<Y\ "#$&689:q) )mopqrstR R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJ_fimqy{~R R(XY_`jlmr~  !"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprtR R = )\")$&*-02467'@=DFGHIJPQRSTUVX[\]`=q  !"#$'&'9@CDJ_fimq'y{~'R R(XY_`jlmr~'''''  '!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt) )&*2468FGHRTYZ\ ",02479fmy~) )_`ajlm~  68:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`acegikmprt3R `j  JLNPRTVXZ\^` b)fi)mqrsux)fms _dglpqrtwx$m_bfisvyz{}~qrxy}~)O &*24789:<$&,02468:fmqrsux _aIKMOQSUWY[]_acegikmoqs79;<$&8:glpqrtwxoqsq &*24789:<m}$&,02468:_bfimsvyz{~) _aIKMOQSUWY[]_acegikmoqsR R")$&*24DFGHJPQRSTUVX !#CDJbfmqrsuxy)R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnfms)F$,79:;<=$&68:;=?C_bgilpqrtx(X!#%')+-/13EGoqsfms)*) )&*24fms)) )_IKMOQSUWY[]_ ")$&*24789:<DFGHJPQRSTUVX !#$&,02468:CDJfmqrsux (XY_`a!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnoqsfm)F$,79:;<=$&68:;=?C_gilpqrtwx(X!#%')+-/13EGoqs633$&;<=q8:;=?C_bditx(X!#%')+-/13oqs)) )&*24fms)) )_IKMOQSUWY[]_R R")$&*2467DFGHJPQRSTUVXYZ[\]m}q  !"#$&79@CDJ_bfimqsvyz{}~=R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt-m_bfimsvyz{|}~) _bgiqrtwxfmsy|}~ _biqrx,) )&*24fms) )_IKMOQSUWY[]_R R = )\")$&*-02467'@=DFGHIJPQRSTUVX[\]`=m}q  !"#$'&'9@CDJ_bfimsvyz{|}~)R R(XY_`!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprt)y~y|}) = =I)= = = =y= =yz}~)R Ry}~)R R ) )y~) ) = =I}== == =I= ==~)[]@~)[]@)R RI}))R R[]@R RIyz~)R R[]@y}~)8) )&-=24=) )_l~IKMOQSUWY[]_=  mv|} R R\&*24789:<$&,02468:\\=\R R_ajklmr}~q\ \  \ \\IKMOQSUWY[]_acegikmoqs) )) )l}~m}7) )&*24 )_l~IKMOQSUWY[]_4  v|} 1  v|} m}m) )&*24))) )_jlm}~)  ))IKMOQSUWY[]_gR Rq)\\RqR Rjkr})))))\  \)\ &*24789:<$&,02468:=))))) _al|}~)) ))))IKMOQSUWY[]_acegikmoqs*|} !79;<$&8:voqsR R\\\=\R Rjklmr}~q\ \  \ \\B))))))f)lr|}~)) ))))1= =))))= =l}~))))))&) )) )| L) )&*24=)))) )_l}~))))))IKMOQSUWY[]_V$,79:;<=$&68:;=?C(Xrv!#%')+-/13EGoqsE= =33$&;<=q8:;=?C= =(Xr  !#%')+-/13oqsB) ) )&*24@)`)) )_l}~IKMOQSUWY[]_RR R")$&*2467DFGHJPQRSTUVXYZ[\]q  !"#$&79@CDJqq)RR R(XY_`jklmr}~q    qq!"#$%&'()*+,-./0123468:<>@BDIJKLMNOPQRSTUVWXYZ[\]^_`bdfhjlnprtc= =)qq== =jkr}q    qq*rv.) )=))) )l|}~) ))0)))))f)r|}) ))>=))))=))f)r)|})))))))) )))) q |    | #vv m}!m}$= == =m}){}  ) )) )j}  = == =m}!) )) )j}  "[]@m= == =j  0R RIR Rjm  $= =I= =j  []@}j}  )))f)})))=)f)})))qm}= =q= =m} j  ==!m}m}) )) )j  j  R R\&*24789:<$&,02468:\\=\R R_ajklmr}~q\ \  \ \\IKMOQSUWY[]_acegikmoqs7qr$,)7R9R:f;)<R=)FGHJRTW)Y)Z\))))R)))$R&R6f78R:R;)=)?)C_iqRy~)))RR==R=)R)fffR(X`jrv==R)R)RR=R=======  R)!#%')+-/1368:<>@BDE)G)JLNPRTVXZ\^`oRqRsRE=IfK=L=M=N=O=WfYfZf[)\f])pfrftfE=IfK=L=M=N=O=WfYfZR[)\f]pfrftf   $')) ,, ./ 257>DFHKNN!PR"UW%Y^(mm.}}/06@EKW]clmpqrsvwxyz{}~  !$&',,0022446;==?@CDJJVVZbddfilmo|~ )  *((+XX,``-bb.jj/lr0tt7v|8~?NWYgwxyz~ !!##%%''))++--//11336688::<<>>@@BBDEGGIVXXZZ\\^^`accffhhjjllnt latnfritzing-app-0.9.2b/resources/fonts/DroidSansMono.ttf000066400000000000000000003445201250202676700227160ustar00rootroot00000000000000`OS/2˕h`cmap}V6cvt DMrfpgms#gaspD glyf"head%=6hhea [$$hmtx[locaBmaxpwH name{'8postP(?prepAڂ~?@n_< TS =#s m#R/Zc33f  @ [(1ASC@ m J -=')=!uqTTf}!5!f!of\sR`RwNJ+\VBo!!!!!!TTTTTP}}}}!-ssssssRR!!!OufufufufHTsTsTs9fff}}}}}}!R!fffd!-PsF9+!e|z!DfT!qoTf!59J!yyR==sjJ+PZsZB!qTf5y=`Db9#!ssyRJ`}m+q{s#jR#!R{N=wR`JR yJJF}119%P9o197 q\!-BBTs}Rb=b{ \{u9PTs?R?RFPTsRXR^))/=;;+jTsfy!R!R5`qs!!-TTTsTsTsDRRR+#`q5`5`11#+'Py{uq)!!!!U!!!!!!!!YLTsTsTsJJTsTsTsTsTsTsTsTs}}}}}}}!R!R!R#999#*~ #?M   " & 0 3 : < D  !!!!"!&!.!^"""""""+"H"`"e%  #>M   & 0 2 9 < D  !!!!"!&!.!["""""""+"H"`"d%aI1vhcb]gDXz Bvt %"iOSVbrhijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu45]^   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a rdeixpk vj0-s12gw'*).l|!cn,B/(m}  3:f45y KRqNOPzSQL@EYXUTSRQPONMLKJIHGFEDCBA@?>=<;:9876510/.-,('&%$#"! ,E#F` &`&#HH-,E#F#a &a&#HH-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y &QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,(#p(>(#p(E: -, E%EadPQXED!!Y-,I#D-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+)#D)z-,Ee,#DE+#D-,KRXED!!Y-,KQXED!!Y-,%# `#-,%# a#-,%-,F#F`F# F`ab# # pE` PXaFY`h:-, E%FRKQ[X%F ha%%?#!8!Y-, E%FPX%F ha%%?#!8!Y-,CC -,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,KSX%Id#Ei@ab aj#D#!# 9/Y-,KSX %Idi &%Id#ab aj#D&#D#D& 9# 9//Y-,E#E`#E`#E`#vhb -,H+-, ETX@D E@aD!!Y-,E0/E#Ea``iD-,KQX/#p#B!!Y-,KQX %EiSXD!!Y!!Y-,EC`c`iD-,/ED-,E# E`D-,E#E`D-,K#QX34 34YDD-,CX&EXdf`d `f X!@YaY#XeY)#D#)!!!!!Y-,CTXKS#KQZX8!!Y!!!!Y-,CX%Ed `f X!@Ya#XeY)#D%% XY%% F%#B<%%%% F%`#B< XY%%)) EeD%%)%% XY%%CH%%%%`CH!Y!!!!!!!-,% F%#B%%EH!!!!-,% %%CH!!!-,E# E P X#e#Y#h @PX!@Y#XeY`D-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,!KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-,CTXH+!!!!Y-,CTXI+!!!Y-, #KSKQZX#8!!Y-,%ISX @8!Y-,F#F`#Fa#  Fab@@pE`h:-, #Id#SX<!Y-,KRX}zY-,KKTB-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY@cTX@C`BYYYYY-,Eh#KQX# E d@PX|Yh`YD-,%%#>#> #eB #B#?#? #eB#B-,zE#-@o/o3@3U3U3U@h F pU3/@FSJpМ@8 F 8 0@SGŽ@vutPsPoHnGUa`e`d_y?OFO_o[[[Z9ZZ3UU3UQP@ FIF`H;G3UU3UUGU@oTS++KRK P[%S@QZUZ[XYBK2SX`YKdSX@YKSXBYssst+++++++_ss++_s+sss+++_ss+ss+ssssss++++++++++s_ss+s++ssssss+ssss++++++s+ss+s++++s+s+++++s++ QuJs}wUinfoxH/NyL' JxyZmmsexT9zo((((Zl'Bo-JiMUg4z K a 7 o 3 n  B UOeG6o-O,z]M_1hW`bW{:  ^ !)!>!!"("""#=#_###$D$s$$%3%K%b%y%%%&:&L&d&{&&&&&' 'Z'q'''''(7(((()))]))***6*T*l**++2+H+`+w+++,5,K,b,x,,,- ------.A.Y.q.....////>h>>>>>? ?#?W???@.@@A AIAnAAABB8BQBhBBBBBBCoCwCCCCCDoDwDDDDDENEVE^EEF_FFFGG(G>GTGmGH+HHI9IIJAJlJtJKKkKLL^LMMGMMN*NO3OOOPPP.PGPPQQQ#Q[[\\q\]]]]]]^(^0^^^__E__`4`s`a3aab b bybbbbccpcxcccdd:dRdiddddddee&eZԮ] iձ>dx ôڴ !;Tm׵(AYr߶+BXoз4Lmи+AZrֹ+KbuѺ,BXoʻ&9Pg}׼~þgؿOMG '@` p?2/3/]33/]310!!7!!IhyJh 4@ /??]]9/]9/329910#32#"54y3qD.@O 0?22/]/]]]10#!# ))))-@s    @P      ?O? O    ?3?399//]]33223322/]/]]9//////]9999999103!#!##53#5!3!33!!@RTRNARR%TT#@}TTHPPH"'@$$##  $pH&X&x&&n@H@P) n  s&#  _o/?_$s H/+33/32/]3/]3392/]3/]+2]9/33322210]]]]]]]]]]]%#5"'53&&546753&'654ĩBǡQoF\@ E> ZDqNV #+Ϲ" H @ H H H H@! H H Hg****!@H@Hh&&&&!@.H!-h g($ ????/]]+]99//+]+]33]10++++++++"&54632'254#"#"&54632'254#"#'#w/J8v=%-@'& $@0H@$4$$GHO;G 0yG@ H/)H@ HFFV7@7 H!PX X&8'X')'('& O,Q ???9/]9]]]]]9+]]]/+3/3/+]99//]]_]]+]]+93910673#'#"&5467&546326654&#"32ZG!5}كdccQWcˆ]yݦֻfAOwJJ\YQv{i@ ?/]10#))' '@ ??/]3/333103#?Da) '@p ??/3333/]10#3@s wwH$@     ?2/39/]10%'%7++wo`f`Fo3 @  ?32/]3210!5!3!!#}}{?@)p@ H//]9/+]]10#79L#Cy @ 0?/]3/]105!Ѩ-@0 ?9/]102#"54f-@ ??3/33/210#sJ9 6@ oo @ Hs s??/+^]]10"!2%2#"d+n}=; +@ n  ??99/^]3/310!#47'3'Raz+Fy{+-U@o@H@ H  st?2?39/]22+]+]3/]10!!56654&#"'632!-q^|lfv}~qwԳw"_@: o _ o$sh s s ?3?39/]9/]]3]9/]3/910]!"'53 !#532654&#"'632ibr\/O`!}fwy}ƥ=f V@ H n @H@ H@ Ht  ??9/9332/+3+9/]+332210+##!533!4#fհ\{ $6eHH0dfNR@1 @ H o  s st ??39/3/]3/3333]9/+10753 !"'!!632#"PYZ7'kf;`:&9]3!O@@ Hn  #o@Hu  ss??39/]2/+]2]9/+10&#"3632#"!24&#"326G_ _hΪQ4Z hݰ;G@0yGW'(t??2/]2]9/3]10]]!!5!N31)|@  &nn n  +!nH@" H9Yiy* #s#s??9]]]+]/+]]99//999910#"&5%&54632654&#"!2654&'5鲸f~nj}cl~Ϻߡ7gejjeZ}yuZJ3!N@ H o#n  @H u us??39/2/+]]29/+10532##"&5432!"32654&#"Cc `i2󑜣gޮf-@ 0` ??9/]32102#"542#"54fffD@.) 0` /??/]9/]2/]102#"54#67m3}>&f3a@=gwhxv@? /]]33/]]]]]29333/29]10]]%53e5fà3@@' pO_oP/]]]3/]]]3/]32105!5!eTf3_@  ɷ& 6 F  @H        Hy X   H H HG Z`p  @`w&6Vf  ?2?39]]]/8]]]3/8/]299]10+]++]]]]]+]]]]]]+]!##373>yr%3.@@HZP`p_??/]+1033!{q\@ @% H'  H:   ) @M H5& H(    @P Y  ?22]2.3?33/]2]]210]]+]]]]]+]]]+]]]+]]]!##333#4#XJwf!Ds @NHE U e 4  %  HJZj;*  IYF V  ?22]?3]3/]2210]]]]+]]]]+!###3353DBL/e T{ $@ [[/_ _??/]10 ! '2# hyx",/F 8@"[ Z`  `??9/]/]2]10#! !'3265!#jƫ9TTb{U@0 H [l| H[ /  _ _?33/3?/]2/3+]9910+%&'# ! 2# ^Uy\$('y@",/ s@K+ H)   H)    F [@H Z` ` ?3?9/9/]2+99]3/8310]]+]]+]]#! #'32654&##ue夫\aiq\|?8@Z!Z  `_??99/]3/]3/10753 54&'&&54$32&# # ^е@ۃ1VhpMIˢNNf|GXfd<@$ZcP_??2/]_]_]_]]]/10!#!5!!û^_}P'@ Z Z _?2?/]]10# 3! P3'L\}! @g H) @; H&hHX*  GW%@ H?3?39]+/3]]]3/3]]]9=/3]3]10]]]]+]]]]+]]3#367')/>Jaϑc@T)9''&6) 9 (&6Hh)9@!HTEw@ Hx H    i y [ J  g & 6 F  $4d  ('K [   ?3?39/99]3/3]3/]3]9=///]]3]]3]]]]]]]3+]]]]]3+]]]]]3]]+]]]3]]10]]]]]]]]]]]]]363#&'#367= ?F( !˪X".X56JDoil'5 @$    @ H&  H  ) @< H& H )      ?2?39/33/33/]22/39]+]+]+]+10!##33ZKNZ{/L!@$ H&6hxZH)9' H@JHYH{PZcP4?3?9/3]3//]_]_]_]]]9/]]]2+]]2+10+]]]]]]]]+3#3d}/fd D@(&) __?2?2/3/33/]3/310]]]]!!5!5!!d-3@  ??/]]3/]310!!!!Z1@ ??3/33/310#sJ!14p@H ??/]33/+]10!!5!!!Zϕo%^3@ H/]33/23/229=/+33103#of%d!H//3/10!5!+!@ _/]3/310#&'53+yjVXَ{^!B@& !G#HR PN??2?39//^]3]2210!'##"&5%754#"'6323265%M?Ļ˴ĤȓaKLER`knD:@"HGPP ???2?2/]229]10%##33632#"3 !"T %ksQ;%^+@  HQ Q ?3?3/]]2/10&# !27# !2%>vi"#9cj>=#&/:@#GH P P??2?2?/]]2210%##"323&53#54&# !26qt #+ -!)ZbH^G@,HH    PPQ?3?9/^]/]q2q210!!27#"32%!! HPï=LK+ 7#1ZF@( GNP ??3?332/]3/]323/9/10!#!5%54632&#"!{=с{)hg{X?n!`#dshff^$,6@/4$ 'F_8 0?O_+F@ H"%R.)O".Q "2N?2??9/29/99/+]3/]3/]293/10#"'332!"&547&547&&54632254#"#"! 54&fAվ7d`YfV@EdJqU8MT:/kpP%e ƮX=-<@&$4G G P?2??2/^]2]10]!# #3363 wͶ gr2o333@ G V N N S???29/]322102#"54%5!!5%yj?+k`Xr:9sr{E{{V9@ G P NS???3/]9/]329102#"5453265%5!#"kkj u\ZΤrssr)'re9{Av@ )9@>HFV  +; H` G `   ??3993?/]223/]+33/39910]]]]+]]73##3 V)%RZ6+ -@G] O  NN??29/]]33210%5!!5%`Xz{{{\s^ k@EveV7GG z  G   "G@P P ?22??3299/]2]]9/]]]]]]]210!4&#"##"#3363236325>WO}TH C2LtÒrJ3-^6@!G G  P ?2??2/^]2]10!# #3363 wͶ grJo3sX^ "@H HP P??/]10"32' ! b670Η`\D^>@&HG PP ???2?2/^]22q10%##33632#"3 !"T ns!+6d)/^<@%GHP P??2??2/]]210373#47##"3254&# !26y qs)+ -)Zb#^1@ G/ Q ???39/]]23/]10&#"#336632#1{eLv1-Jwf^<@"F!F P `  PP?3?399/]3/3/10753 54&'&&54632&#"#"byƫJ`k*:JrUp' RdJ F@ Hp @ HNN?2?2/]]3/3+]2/3+10!!5!5!!+y}Db@?  p _@      /  ??9/]]]9/]]]]29/]93210$4!5 5%pJRpQKNMKQ) )@ O??/]103#`@>  P O  /  ??9/]]]9/]]3]]9/]93210475&54&'5! 5665qRIq;) )LQLLQJ3Z/@   p ?  /]]]323/]105632327#"'&#"cdGlwcdFlJl?8yl?8^ %@    ?/9/9/329910"54323#fy3H%N@F 0  H@HP Q?3/3?3/3/+]]29/]3210&# !27#5$%53碜>vizN'89bk=;EJwVR@1 o  u/_ s t?2?39/]32/]3299//3210&#"!!!!5655#534632'By!ٵyHىN1ՉD'^@ %@ H O _ o  )@ H"?Oo/]3/+]]]3/+]10'76327'#"''7&542654&#"/berrccCCacrva`AxdecbDD`erx_`BD`_vrdefdN}@ H H@<Hfv t   g n g    @0@ ?3?99//]]]332329/]]]33229]2/399//3/]]]399//10]+++33!!!#!5!5!533dZ.Ҳ-!@O??99///]32103#3#'2}@+ (/-H**I F4G//I& F&&@ H&&3(- -( N N?3?39333/+]33/]23/]999910]]]&54632&#"#"'53254&'&&54654&'Э8xcwVprq+PxHCt6N=>qXPAR9P>ThaLmYo00Ik?J 7@$p  Oo/]323/3/]102#"54!2#"54``````fggffggf ,o@F)#/? . +&!$!o `!p!!!!!! ??99//]]]]33/99//]310 ! 2#"#"&54632&#"32fCAkrܿ~=nSy^hjXWU..Um2>6G@% /0  ??2?39//]33/]]2210'#"5467754#"'63 32655!hު}p)#rxhi}vtg 3n:D?4KZn[s G@*  `  @0`   ?322/]3]]210%5uu5uu)NNNN3,@ H?2/3/+]10#!53y #+@^"$'""``"""" - $$+o "`p ??9///]]]]]]3]3/99//]]]9332910 ! 2#"###3 %3254&##fCAv^EoHTYEhjXWU..UPu`}J;?//10!5! +V @   H H@ H@! H 0  @  H?+]/]]10+]+]+]+]2#"&5462654&#"fOrsNOqp˻pNQrsPNp3 )@    ?32?/]332210!5!3!!#5!}}}{\oM@3O_ `p H  ?2?3+9/]2/22/]3/10!576654#"'632!oo=oQSNuvFkfve9sLVgxhBVN@O O_`po  H H?3+?3+9/]]]]]9/]3/3/]9/3/]910#"'53254##53254#"'632Tn]HF{aGZBom='t2|A}hoFV]m^+!@ _/]3/210673#^PpyJ=@ GG@H P  ?3??2?/+]22]21032653#'##"'#3jڔ `NjJ:XW6B7M`@%H"2  @ H Q/2?9/3/+9/]]+]10#### 63!7yy=U]3y3H^"@0` /9/]102#"54f^!C @! H0 H   _  //993/3/]993310++53254'73!"!/[x9"l\J's%o !@   ?9?9/33/103#47'J )!FIE,3X 0@    0 ??/]3/]]10"&54632'254#"dws G@*? @     ?322/]]2]210'7'7uu5itt6eN\\NbeN\\Nb'{&<9Y<@'P@]]]]]5]]]]]55?55'{&tZaD@-   P@]]]]5]]5]]]]]]5?5'u&5<NY8@$&&&&&&!!!!!!]]]]]5]]]]55?55w^![@7!@P# #G Q0 ?]]/]39/]9/]]]]9/]2310"5432327#"&54676655'YvT>kwAH%wTate]qZjãlWkZ!s&$CR&%+5+5!s&$vfR@ &f%+5+5!s&$KR@ &%+5+5!5&$RR&%+5+5!+&$jR&%+55+55!&$P}4@P@ %+55]]]]]]]55@T H7 ZO_ _ _ h    __/3?299//]]/329///]q323]]99+10!!!#!!!!!3#s`Rh#Jwj;<&&zP (" %+5#s&(CR & %+5+5#s&(v?R@ &' %+5+5#s&(K#R@  &  %+5+5#+&(jR@ &%+55+55s&,CR & %+5+5s&,vwR@ &x %+5+5s&,KR@  & %+5+5+&,jR@ &%+55+55{ I@,[ Z_h/ ``??9/]]32/]329103#53! !!!3 !V=ar|` C4D5&1RR@ &%+5+5T{s&2CR&%+5+5T{s&2vZR@ &Y%+5+5T{s&2KR&%+5+5T{5&2RR@ &%+5+5T{+&2jR@ &%+55+55-{ \H@ HH H H  HH@ H/]/]]10++++++++7'i=Bh?ff?i>gf=gP!`@8 H H [  #[/_ _ ?3?399/]329910++%'7&!27#"&# 3245\yu|\}slPzPJNŸ`iNɼxD^V",}Ps&8CR&%+5+5}Ps&8vLR@ &L%+5+5}Ps&8KR@ &%+5+5}P+&8jR@ &%+55+55!s&<vLR@ &M %+5+5F >@$[ Z ``??99///]22]10#33 !'3265!#jƫ=T*r@K F GO _     G&,G P)P???39/]9///]]]]]]10]%53254&'&&547654#"#!2#"ߏ[b{dمT1:z^ȷ1VQf=NzWujjZNouJ>!'HFV  +; H` F `    ?3?3993/]223/]+33/39910]]]]+]]73##3 VR}Js&/veR &H %+5+5+&OvN@ &A %+5+5;&/9' %+5+5;+&O9 'ݴ %+5+5&/8 %+55R&O8sf %+55&/O %+557&OOf8Y %+]55HD }@6  y *v%  Z@ H  _??99//9/+]33/29/10]]]]}!'73%!}Iƻ+N{N}}X}F+@i f     H@< H o    G@]O N   N??99//929/]]3/]322/]210++}]]'7%5!7!5%NäM`XP\yz_ly{{Ds&1vbR@ &c%+5+5-!&Qvo@ &o%+5+5;D&19'ϴ%+5+5;-^&Q9'%+5+5Ds&1LR&%+5+5-!&QL @ & %+5+5j7@G G/ P??3??2/32/]210#6# #33663 2~<(`㶔 *gnJrJNZo3{DbH@6HEUe4% _ ?33?33/3/]22229/10]]]]++##3353#"'5325)B Ȼ^>MQ^-^<@#G  GP P???2?3/]2]9/10!#3363 !"'5325# V gQ46=JomrT{&2MR@ &%+5+5sXo&RM@ & %+5+5T{@&2NR&%+5+5sX&RN@ & %+5+5T{s&2SPR@ &N%+55+55sX!&RSR@ &R %+55+55I@)Z Z_h _ ___????9/]/299//]210!!# !2!!!!!%&# !203.RHrg:I5F < X!9^$)l@) )G@Pp%F@ H +"G@HP))' P P?3322?3229//+]+29/]29910%#"32632!327#"&%2#"#"XYTIl`^{W䨪ZNO{} 3 +qLIv!1s&5vR&ݴ %+5+5#!&Uv\@ &-%+5+5;&59' %+5+5;#^&U9&@'_?%+]]]]5+5s&5LR& %+5+5#!&UL &ݴ%+5+5?s&6v`R@ &&` #%+5+5!&Vv^@ &&^ #%+5+5?s&6KR@  && %+5+5!&VK@  && %+5+5?&6z ,%+5^&Vz ,%+55?s&6LR@ $&( %+5+5!&VL @ $& ( %+5+5f;d&79 'ߴ %+5+5;o&W9@ '% %+5+5fds&7LR@  &%+5+5&W81Q %+55fdY@3  Z     c  P  ` _?2?9/32/]_]_]_]]]39/2/9/10!5!!!!#!5^_&ڻ3ߤ!bop@CG  /?N  N P?3?33329/32]2/9/]]333/]922910%# 5#535!5%3!!!!32z MiJ3] X^1ۉ}P5&8RR@ &%+5+5-&XR@ &%+5+5}P&8MR&%+5+5-o&XM@ &%+5+5}P@&8NR&%+5+5-&XN@ &%+5+5}P&8PR@ &%+55+55-&XP&%+55+55}Ps&8SLR@ &K%+55+55-!&XSP@ &O%+55+55}9P&8Q%+559dJ&XQ5@%+]]55s&:KR@ & %+5+5!&ZK& %+5+5!s&<KR@  & %+5+5Ry!&\K@ & %+5+5!+&<jR@  &%+55+55fds&=v9R@ &: %+5+5!&]vN@ &O %+5+5fd7&=OR@ & %+5+5&]O@ & %+5+5fds&=LR@ & %+5+5!&]L @ &  %+5+5d .@GO_ P ??3]9/]10&#"#4632)izw\}`wNR@*! o   ! u s s?3?39/329/]33/299//99//10#"'53265#5754632&#"33F;8\?™ad/OA\?D?fqKD%fq!s&$&P}vHRR@0(`(P(@((DP@ &)%%+55+5]]]]]]]55?]]]]5&D&Pv^H@1@@@@`@@@""""&@<%+%!%+%+55+5+]]]55]]]]]]5s&vR@ &%+5+5-!&vq@ :&p47 %+5+5Ps&v9R@ (&5"% %+5+5sX!&vP@ *&Q$'%+5+5;?&69@ "' #%+5+5;^&V9"' #%+5+5!+@  _/]293/329/3310#&'#567673yU~Nx"%%;82&OOC!+@   _/]293/329/3310#&''53673"##;xRzYy&LLC6;FoA@p@ H@ H/+]3/+]3/]10!!F?o9 L@ `p@ H   _/]23/]3/+]10# 3327 mOh L1}J@4[B& Oo/]3]]]]]]]]]102#"54fkkjrssrH   @ H@ H H H@*H H  H /@ H_/]+]++]+10+]+]+]+]"&54632"32654&bfyyfeg1?p2??tcctv_bwH<5q<55<9/8@"-=M0 H O_ /]/3/3/]9910+]#"&547332/ISw~Bqm^l}q`3@    /]323/3/]10#323273#"'&#"fh:gf"Pi9dd(R88r98!C@* @P O _ o   _/]323/]3/]2210673#%673#^PpdjWWpev! @  _/]3/3/3107673# c=mkrPS+ W@9  O o   /]329//3/]99//]310673#'2#"54!2#"542)]zRa8)`aa`lf16gffggf!&$TED%+]5?5H^"@0` /9/]102#"54f^#&(T!@     %+]]]5?5eF&+T!@     %+]]]5?5&,T Ŵ %+]5?5|{&2T%+5?5&<T4 4 %+5?5z&vT%+5?5&UZ %+555!$q%/9@@HZPH@ H_??/++]q+10!#/D չ @HHH) @ HG& H @THW G %    ` HX H *    /Oo[)9IH _?99?3]+]]/]]3]]]]+/]3]]]]+9=/33]]10+]]]]+]]]]]+]+%!53!&»_3%4}}1n #(fd=F+T{ a@@t/?{ 0X  [W[/`h _ _??9/]]/]]]99//]]]]10 ! '2# !!heyx",/,.! @H  HH )     @HG &   H   @DHWG%HXH* /H H ?2?3]++/]2]]]]+/3]]]]+9=/33]]10+]]]]+]]]]]+]+!#&'#3?-+ǍȆ`q\0D1o\ G@)/? 0   _h _ _??9/]/3/q2/99//]]10!!!!!5eQs<T{2F%@Z Z_?2?/]10!#!#!FF3H @W7 &   7&8)   _ _?9?9=/39/]333]29/310]]]]]]]]]355!!!n}Xgf%fd7!<'@Y& ) )& Z'   r @ P ` 4   HZ/?o)#@$ H#Z'` P  ``p?2/]32?3/]32/+]+9/_]]_]_]]]332210]]]]332###5#"543332654&+"33//! ˴>6SջѬ5;9u@NZIrP`4D Z/?oZ  w` ??339/3]2/]]9/_]]_]_]+]3210####"&333332653嬊B!ZJw@N HO_  H@PX[ W[/_ _?32?/]3]2]9/]]3+]]]2+10%!5!&32!!5$! -  +8\S褓 E+&,jR@ &%+55+55!+&<jR@  &%+55+55y!&~T.&&* %+5+5!&T`@ (&] $%+5+5-!&TP@ &O%+5+5!&T@ &* %+5+5;&U!% %+555555y^%=@"G '!H #P P??2?3322/]]222103673327#"'##"3254&# !26^ &3T4?( lUg-]o )*ZbP&Q@.* !HG( G  P P$P??3?9/9/]23/9/]910]#"'#46323 4&##532654&# }غu燚%^Fr=0?4ҷyP+~vRyJk@%HD T t   H 0@ H/? @ H ??33+?33/]3+3/]3+9/]93310%#433673ne7G$H?)>hiF"O@1+  F!H$HP P?3?9/]]29/9910]]&54632&#"#"$5%3 4-IJVTi%'˅mjI@?gdt,d^^Q@/  !GGPyPP ?3?39/]]9/]3/]29/910# !27#"&5475&54632&#"!HĪا?VKK BLHo+@W *  &  + HF  H{mI;-ykI;- P?2?99]]]]]]]]]]]/]3]2+3/3]10]]!#654&'&&5%#!FtŦ嫗yygBx׉v'eob9A# -^1@G G P ????2/]2]10# #3363 wͶ frJoG9 O@2 ;(H  '7GO  /  PP??9/]]]/]]2]_]210"32!#"!32d3+n|n;mJ &@G  o P??3]9/]10327# bpe]J XJ=!U@3 $! H/?H  PP ??39]?/]+333]]99333103'&&#"5632327#"&'&'#=5"VI80A>FF%A2ARWE$S;hH )o PWz-J:@# GG P  ?3??2?/]2]21032653#'##"'#3V a̭K:XW6=JJ t@F  H 5 E U $  )9  c s   DtG @ H ?2?3/8+2]9=/]3]]]]310]]]]]+3363#=n JEro+,@_)F"$_$$F  .H{mI;-Hy k I ; -  #O/,,,%"P#??29/]999]]]]]+]]]]]]/]]9///]]]99310#"#654&'$4675&5467##5!#"3LyycJזh>Eٷw[i8 dod5ADZ* ;r3 qhsX^RJy@5K [ k : (   G TE6'G @ P ` @H    P  P?3??22999//+]33]]]]]3]]]]10%#"!##57!#324Umފ&Z.PJPN};^5@H @H GPP ???22/]22+10%##32#"'32654&# TרqpFa0dto)^g@B FH{mI;,ykI;,Q ??399]]]]]]]]]]]]/]]2310#654&'$!2&# yT7>rfoc<;GZ;9H#BJ 2@HH  P P??2/]]2910!#"!#"3265+;;ǨJ>п j9JS@ G  @H= /   @ H_ PP ?3?29]2+9/]]]+]3]10!327# !579%kTT†J#XsJP;J3 F @H G GP ?2?/]3+103!2654'3# ??>JJ^\@:VfGI F IP/?P P??32?3/9/]]]9/33]]210$7!2$#" >xaD 1:ZΆ!^}&o+N@\&IY& )FV )  H @+ H  P  P ?3?3?39?399993/]3/33/+3/+399933]]]]]]]]}103327#"&'#&#"5632}7_.P@,$B4fG۴DT"5LQn7P3rYZy|> mPi@V f G  I FF@+HF@P/?P  ???32?3/]]]2+9/3]]210$43#&3-??'Ӭs&'ZZuJ@VG6@cHW6FV f G  II?!YH9HX9II0@P/ P?2?3229//]]3]]+3]]]]9/]]93]]+3]]]10332653323!"'## åhCKO?iiߵ2 2Jo~2΂2ز(.&j@ & %+55+55;&j& %+55+55sX!&RTH@ &H %+5+5;!&T'@ & %+5+5Zu!&T3@ (&1 $%+5+5#+&(jR@ &%+55+55}@IH Z  F V 7 /?  Z _@_ _ ??2?39/]99//]]]]]3/]2/+]210%532554###!5!!!2#"DCIνX#o/s&avmR@  &: %+5+5D@'@H [  _h__ ?3?39/]/]299//+10!!!27# !2&#"LuŒf6ܣNN:;iZVN?6,+&,jR@ &%+55+55- @X HxWg H x   H Z`G" _`_ a?3??9//]99//]]23+]]+]]2+10#"'532667!3 ##3 4&##wp8( $#5)'Ϧ- Fa^ xBC@% ZZ@ H_ h `?2?39/]32/+29/3210!!#3!332#'3 4&##%¥>')- Vhܠ xi@;H Z  F V 7  Z _ _0@  ?3?9/]29/]]]3/]22/+]10!2#4###!5!!κI#s&vR@ &B %+5+5i&6R@ &%+5+5F C@*Z Z Z _/33/?3/]9/]10!!#!3!3Fv{I!$o 3@[ Z_ _ `??9//]22103!!! #%! 4&##+R<^ܠ yq%/a @ H  H  H @ H[Z  @% H    Z _  _?3/322?/3/99//]+]+]10+]+]+#!#36!3!#űq Pk'Xjk#(@Lg w   6 F V  F V 7    Zhx 9IYg  g@ g@2hh   @ P    ?33?339933/8]3]3/83]/83]3/82]9/]]33]]]]]23]]10333###u]Vs<<</#Q@.[!! [%  `h ` ` ?3?39/]]9/]39/3/9]10!"'53 !#532654&#"'6!2cvɌv]O`}gzy}ƥFb@@H5EH:J )  i&  ?22?33/]22]]2]210]+]+333#4##BլpJFFi&6R&%+5+5 @`% *'  Z`p)  )@`?2?399/8]]]2]2/83]/]23]10]]!##336<BFo@! @H | Z j - = M   @ H HZ@ HZ_ ` ??3?/9/+]10++]]]]]+!#!#"'532!FuGB98fn~/iq\0F+T{2FnF3&fd7@    H@YHIY8) FV7&O_oe6%  _?2?39]]]3/]3]]]]]]3/3]]]]]]99=//++33]10#"'53267337TLx~hJU]ny6  '8b-gz?ms5; :@" Z Z _?3/2?3/]]3/10%3#!3!3 }F/@Z Z _??39/3/]210!## 33273FgnۻVZsGтePyV \@@eV7G{Z Z? Z0@P _?2?33/]]]9/]]]]10!!33333V#=@Ye V 7 G {  Z  Z?Z/o  _?3/22?33/]]]]3/]9/]]]]10%3#!33333 u ;@! Z[ _ _ `??9/3/9/]210!!5!3 !'3 4&##FD#^bRD z`m S@5I  0p? Z 0_ `?2?39/3/]2]9/]]10333 #'3 4&##3`/JNR/^ܠ yVJF <@ [ Z@H_ `??9/3/+]2]10333 #'3 4&##Rƪ^ܠ yDLJ@+ [ /  _h_ _?3?39/]3/]3]29/]10'63 !"'53 !5!&&#"M0YԒŃqٜV{k;:bn@+/O_@H @ H 7Zf@ H_h __ ????9/]3/+]]2+9/+]310##3332#"26&#"qj_`il^]V]"qs;eh9 q@   H Z   H[@H` ` ?3?9/23/+]3/83+]299+10]]#$!!## 33b}tʤ\b6J\^D;#>@%H @H !HPP?2?9/22/]2+2103632#"4>! #"!s tܺ>h% _#CAҪh? j9wlTJ [ @1 HF FGPx PP??9/]]]9/]23/910+]#!! !2654#!254&#L5%r>F#ߕJ@HT>\H#J.@GoP??99//]]10!#!˶PJ!hJ t@ ( H@5 H P     F GO _ o  GN  P?3/322?/]3/99//]]33++10]]#!#3!3!#hVP$}+P$H^HJ@iyK[)9 fvDT&6 V f  7 G   G   hx H H@Pgw H  H @   ?33?3399333/83+]3/83+]3/8]3+]3/83+]9/]]33]]]]]22]10]]]]]]]]]]33###3^mo5--5^ W@3 F F"`p!P  x  PP ?3?39/]]]93/]33/9/9102654#"'632#"'53 54!#5?ɖOWHL9 AϗEV-J H @P H  H H iyfviF f  F    ?33?33/]22]]]2]]210]]]]]++]++3##L  JdjJ-&6%@&p$ %+]]]5+5J @NX HveFV5&X H   G@H ?2?39/+]2222/310]]+]]]]]]]]]]]+]3##36ݴJ-JJ@ H @oHTd2B$ H )x9Ii     H ) 9    0@HGP O ??3?/]9/+]]]3]]+]]]]3]]]3]+10]]]]]]+]+!#!#"'532!%>o$/ sZJ@HGH@7H H\l|:J)I@0HScs5E& I  @ P p    ?333?333/]2]]]+]]]2]]]+]9=/3+]3+]10]]!##&'#367673Z Շ<00 dU&yJpM '"-J ?@&G  G  Px ?2?39/]]]/]2]210!3#!#V!߶J9JsX^R-J)@G GP?2?/]]10!#!#!VJD^S%^FyRJ<@%G P??29/]3/]2/]10!#!5!RooPRyJ\J ]@;VfGI  IIP / ?  P P??32?32?/]]]9/33]]2210#$%3$51ϝ#Z2*$-  )s<~!y`jJ[J 8@ GGo   G P?3/2?3/]]3/10#!3!33}JPP%J/@ GG P ?2?9/22/]]2103273##"&5NͫȠJfs}RJ Z@?FVfI 7I? 8I0@PP ?33?2/]]]]]9/]10%33!333+JPmJm@IIFVfI 7I?8  I 0 @ P   P   ?33?3/22/]]]]]]9/]3/10%333#!333vVP}JP+J C@) GI P P  P??9/]/]9/]2103 !!!5!3254&#J\vZRqZJc@BI Y i  I`p7I88  I7 P P?3?39/]/]]]2]]9/]]]103 !!33254&##3\ޡv¢JZRJDJ>@ F G@H P P??9/]/+]2]10! !!3!254&#\9vJZR%^i69  H@1 HH Q/xQ Q?3?39/]]]3/]3]29/10++]]753 !5!!"'63 !"_l> )>\=9;{^f@!II @ H 8I@ HPx PP ????9/]]]/+]2+9/]310##33!2! %2654&#"#LSg]\jh]]J9ŗs J o@$H)   G  Ww@ 7G PP ?2?9/9/]]3/]83]]299]]]+10!#&5463!#!%!"39#̭CfH&Hj@ &! %+55+55-"b@: G$ G  P!PO   ??99//]323?/]32]9/9105325#"##5353!!363 !"6=좓{ jQ-DՉo#!&vh@  &6 %+5+5%^]@:69     HQ/x Q Q ?3?39/]]]/]2]29/10]]]]&# !!!27# !2%>p]# #9Ú>=$$^V3L3&j&%+55+55VMJy@N  Hz   H H HG`I PPO P??3?9//]]99//]23++33+10]+]3 !###"'5326!3254&#3\Ѻ!4\`>)1-#7v&k T~ZRjJV@8I I8I@ H PP ?2?9/]32?/+]29/3]210!33 !#!#3254&# +3\բo7vJ9=JZR-!&vZ@ & %+5+5Ry&\6 @ &  %+5+5-J D@+G G G  P  ?3?33//]]9/]10%!3!#!3V!}J#>@@H ZH@ H_??3//++]+103!#s--#-@Go GO??3//]]10!#!3߶!?J?s&:CR&%+5+5!&ZC&%+5+5s&:vRR@  &R%+5+5!&Zvh@  &h%+5+5+&:jR@ & $%+55+55&Zj& $%+55+55!s&<CR & %+5+5Ry!&\C& %+5+5y@ ?/]3/105!\Ѩy?/3/105!Ѩy?/3/105!Ѩ1<@% & )/]]]]/]]]]/3210!5!!5!  ^ *@&o?9/]]10'636{>& 8@() 0p ?9/]]10#77yA$ C@1) 0p /?/]]9/]]10%#77yG$ (@&o?9/]]10#'7(<|5 J@2&/ &    ?329/]]3/]]10'63!'636{>&{6{>& \@A )  /   )@Pp  ?329/]]]]3/]]10#7!#7)7yA$7yA$   ]@@ )  ?  )@Pp  /?/]]329/]]]]3/]]10%#7!#77yGq3}G$$ /@   ??229/]332210%#53%87778L_7@   ?22?229/33322210%%#553%%K77L//L77K/y"x{R *@P`_o@ /]]]102#"&5fmo|N_@=4%4%4 %     ?33229/]]]]3/]]]3/]]]1072#"54!2#"54!2#"54 #/9E@vC3338-'""o"""""=88G :$@*5p0 ??399//]]33222/]3/3]99//]]]3]]10"&532'2654&#"'"&532'2654&#""&532'2654&#"r~q?*/:;/+ F)r}q?*/:;/+Ps}p?),<9T5#f} dF3}`j'j@ ") Z  @/_%_ _??99//]3232/333223/329310!!!!!27# #53'7#5332&#"BI(zA^'ۿOzx>:; &x\J#+" H @ H H Hf****!@EH@Hi&&&&!- P  f($  ?33???/]]2]99//++33]10++++&#"327#"&54632#"&54632'254#" RDgIJlcQ'!k!!k% JBl!j@>n  pp?? "# v vu?3/?9/33229///]]]]3/32103!"&5556746323264#"urVkHyn~g53Ly(yQk&*@$$++ @(Ht V f 7 G 0H{Yi8H'$ @o*@H*, @1!K[@ H(V(f(v((a'D T  H ?33+]3]]?3+]399//]/22+99//]2210]]]+]]]+]]]]!###3353"&532'2654&#"5! C1rrx?00?@00u/d\Zysqrmnqptuk@?   z  ?333/33392/]3]]]]99//]222210##5!###33#47#/ { ell%/VWxJvRwH<@ / ?  www H ?3+?9//]322210!327#"532'&#"w{Gaۗ3,y|{){D1Qwu'{&@VgT@7  d T D  P@]]]]]5]]]]]5]]]]555?555 'u&@jgL@1(((((((!!!!!!]]5]]]]]5]]]]]555?555'=&@jgP@4"""""""]]]5]]]]]5]]]]]555?555'?&@jgP@4 k [ K 4 $  ]]5]]]]]]5]]]]]555?555yR9@F !HN PP ?3?9/22/]29/1076&#"563 ! 432&&#"32 BLŻ^(T>{Ui2J ȵ H H@D H& H)  HH X *    _o @6HG W %    P` _H[)9I?3]]]+?99/]3]]]+3/]3]]]+9=/3]3]10]]]+]]]]+]++73!&'!Jw;"-+qEoȆX1@Z Z@ H_?2?/+]]10!#!^J z@R7 &   7&8)  @ H_ _?9?9=/39/+33329/310]]]]]]]]]55!!!JGMs+r 3@ ?3/]105!.@ //]9//2/33/39/3310##5!3d( iF'_ H@2 H H H #)&   ?/]323/3992/]910++++#"&54632632#"&#"32732654&#"bvwwltvqRmAPPChVkAPT@gmծլBkOQemNOg)@  ?3?39/]3210&#"#"'5325!28:N7<8JX׮'b{3%#H@) %$" ?  P/]]33/]3223/]32105632327#"'&#"5632327#"'&#"bbJmvadIpscdGlwcdFlm@7yl?7l?8yl?83n@A     pO_o  P/]]]323/]]]323/]3299//393910#5!!5!3!!!'=yJi{;93 e@?gwhxv  @? /]]33/]]]]]29333/3229]10]]%5 5!3e5efà3 c@>hxgwy   @? /]]33/]]]]]39333/3329]10]]55!6e}VV=f=ݖ}P D@    /3?39=/3333/]329=/333/3310#3 P;L>L 11+"R@+ G $GS O!P  ?3?3?3329/]/3/3229/9210###5754632&#"32#"54#3Ùad/O@\@!j?+kŷ?KD`%erhr:9srJ1B@" GGOP ?3?3?32?/3/329/910###5754632&#"3#3Ùad/O@\@{?KD`%erh -@  _/]23/3/]10!"&'3327ì Tw”fUVJ/@G  PN ??3/]9/]91053265%5!#"u\ZΤ7're9{A @  ?3/3/107673# T=`ktN_;@  /]3/3/10673#>`CcVR!@  _/]3/3/10#54673?[IbY99 "@ 0 ??/3/]10"&5!2%2#"d+ќ97FD% V@4_ hx H    ??9/]93329/]332+]23/]310##5!533#547TyT((Vb RZI:PD\@9 @H O_p   ??39/39/]]3/]99//+3331053254#"'!!632#"Pfi4I>#=v|D'}nm998@0   ?2?9/]2/3/]92103632#"&54#"326-4 =p͓Jb]KDSmn\G~zc> IaYMDUH};b~ͺcW8P{^7%9EKQW]aeimquy}@.bze}z}L]?E %!_!o!!!%*7O _ % %`%%@dH@7P77 %77% FUUvrn]Fkg_Lthp`xlh`ll`hLG)99&~~ H`%%%&o&&&4-<B--XSXzLScG/33/3399//33/]333/]]9/33/]39/+39339///333/2222/33339///]+]]33/]3333333/3993310#".54>3232##!##"&'532655#32654&#"%!#335!#55353#35!#3#3#3#3#35!32654&#'32654&##4N66O33O66N4XX%#WK HXE+ ''^l58933985/oo0mmoo9oooommmmmmIu;&*73%!%/X@##@X67Y?##?Y75B(6&AH4MPLR),SSJKSSK0o/mom-oohi;mmz" P)9N@&))*q2P2`222****7-))--/3/33/3/3/3/33/]3/3/]]3/310 54>7>54&#"663232>54.#"fe##5##HFAB7f-52 &+ A2)  )2AVW+"!"!9>G.|!)5*($%36;$7A:/ "/ 8!&7L o %+5  + O]@7FCC;GMQQQ3F>OONN"N)))N)N)8NH8N??99//]32/]]3/]329/10.#"#".54>54&#"'6632324&'.54>323j 9M[0LV.j<@ăoV" 6%%d62E, 0N:C'QYhuKlt=XH8iR3:s7_}E(]YK-! 2D(#V]a-*J620>KxQCpR.Tߋ H @F H& 6   YT )  ZcP ;;'@ H??9+]]]33/]_]_]_]]]2]]9]]2]]++10>7>32&&#"#3dKNI.6@)"+ ! ># /:B?8K,(=' /<Sn</J @_@<V8f8G88I77!I B,I@P/771' P <1P?222?229//]]3/]9/]]9910".54>7#57!##"&'#4.'!32>55332>{OnE ## EnO^o o ## #4$$6#O?$4#DrCtnrBJPBrntCrDW[[W>rpvCCvpr>[R&)Hb9˂&Rq\u&0vdT@ &d %+5+5\s!&Pv@ '&~!$%+5+5!&$[@ '%+55+55^&D[@ 1',"%+55+55 '2\-@+`3P3@3 3333%+]]]]]55?55HM@H/H @H pH/+]+/+]+10#".54>324&#"326H#>T12R; ;R20T>$u?21?972?3Q88O33O87O45<<55<<-h0@@@  HO_/]99///+2/]10467#"&>73#-xz<9$2.;D5 08>RNsL.%'F%KOQ$ MPQ%B)'4c@7)'')& 6(  P  R( &/ N ?33?32?3322/]3333/]9/33333910!######5754>326632&&#"!!3547&&#")ˣͤdd(MpH1W"&f?4[%)E%&7$o!-#5#55A>RjT#  4W@hfsN4W@B)'4a@6,))&6( PR( &/ N?32?33?3322/]3333/]9/33339910#####5754>3266323#&&#"3!3547&&#"Hͤdd(MpH1W"&f?0.&7$-#5#55A>RjT#  4W@hfsN4W@T 43@[+[6![ /  0_&_??32/]2210#"&&546632>7332>54.#"{@ȇɁ<<ˎ|B  !1D.**$O\]N##N\]P$ݩllkZV4?I(4cWJ[鉉ۙQQۉڗQQs +5@J&H-!H  )P$P??32/]3301#".54>32>533 4&#"XJogNIoaB&+*9K1&*ם6'ՑLLՉӑKBA8HW0Er[CBc}&6@[`p%Z(Z & _??33/3/]2]10>53#".5332>5/7 0RyW-cslc.6YACV14Ma6EiKfrEA~z3WV+0ZR'WJ!!!H!@#H!G&)G  &  P??2?33/3/3/]222++]01!'##".5332>53>53 2U\+?).bi=4e`:{2Ne8FnH+!C+!vR!.@ /]9/3/3/9/3301#'>54.#"56632!-<" q%;*$242)':)o! l[}  //014632#"&=-,?'-=<77<+7#s&(CR & %+5+5Fs&CR&%+5+5H!&HC&Դ %+5+5-!&C & %+5+5R{<u@   @ H ::'>.---@" H--3/'';;8* .. 0_*::8_"?32223?32/29//]2/+]39/93/+]310%32>5#"'6632#".'#"&&532&#"3273'80C*NB7)/"X0"N^!6.+*.5!^O#0X"/)8BM+D09%+Ye %% e%fgY+J*z@.  &!""""I_I ,*@ HI& ""O?33?3393/3/+]]q33]9/]3/]]3399]10!33>733>53#&&'ᠣ" Vm?O-BqXT jJ\U38AC!`g`!hT8>u!A@!Z [#!__` ??99//32/9/3220132#!!5!3!!32654.##^7<~†+wh.[]JNBqWap=`@Fa<X'!C@"G F# PPP ??3/39/2/9/3229/01!!2#!#5353!32>54.#/eqN+7]D&!A`@לM|X/)B01B(b-V@0"@ H*/!_!! +_*' _?32???329/32/29///]+3201"!!3267#"&&'##33>32&&DrU7 )-U}RBt9;@I,xx> LpT32.#"!!3267UrF KrS"D@9/243{ \$@]=Hs0/n:{J9r4   \T(% @  @@ H H    ` _ ?33?9/322/3/9/]93+]q9}3+]q3]910##3###!'&&'p s7'%3<VJVDniKK\=J @l G  G I    H   uFVf7% HP@ H R   ?33???9/+322/]/9/]]93]]]]]]]9}3+]]]910#####.'#3ch## "" JJ\Z]VW]["b@   w  YiVf  x  Zj2) `P@ H`  ?333?39/323+]322/22/]]]]/]9/]]]]]]]93]]]9}]9]]3]]]]01##!#3!3###3'&&'/'}-( &VVlJVJTaKK[{ J@z IfTI4DjYE3   d    PP P  ?333//?39/323322//]/]qq9/]33}/]9/]]]]]]]]]q]]210#######3!3.'#l::'\ JJ9ǐV`^##^`V#&S@,$ JZ(% (&#'a$ &_?22?9/332/33/333/39/]]329011>75!#.####"!q1LrVYqJ/qq"1F66F1"q%Ub:狋8bV;H_9H9_H?` J#&u@D$f  IzYK'&#'%   R$ &P?22?9/33233/3/]333/]39/]]]]]]]32]9013>75!#.####"! w*BdPPdB,wv$/B33B0$wT=eM1 dii1Lf>P6H+ +H6-\(+s@@)   *[+Z (/ 0 "`) + ?222?9/22333/]2/]33//]3/9/]32910!667##3!5!#.####"!`8 ɦ:AS4 77 .&'- 8BQl(Vዋ8aW;I_8H8_I?Z{ J(+@[)I       u h   *HI+H`  (I* I""P) +  ?222?39/3/2/]22/]3]3/]/]3/9/]]]]]]q3]]2910!667##3!5!#.####"!sI բ =N3 II )! !) L)}T2C J9^ii1Mg>P5G, ,G5-uF'v@DbGQQMYYl9[gg,[rrxNMMMCDD"22Z"Z]@VVNC>abl2a33QGDb'` _?2/3322?3339/922/2/3/3/33/]32/3/23/93301"32>32.#"#".54>32>54.##532>54.#"'667.'53>32&&#"G[4$=/AaTQ2V^ 5N51GJ\FhP1fkYQ&8hY\a2&D_97aVO&\;f762y3b6:CK*/ !10.S}U+3[}KX_1B )$ )H`732.#"#".54>32>54&##532>54&#"'667.'53>}.\*;bE&2G+/S=$7yJY/%@06mfZ$HN $+."\lw<_zE#UnQ}U-y;oV5yOS?>vF/0-y6e8=GSRuK> .D\;2N;) +B\>CuV1&#   +EW-3ZC(+E3^[ #B6MM&""983#`8"F9$9uPT{)+@%[+$[ `$$__??9//2201#"&&5466322>7!"!.{@ȇɁ<<ˎǃ@W{O'g(P{XUzQ**OxݩllkkGzz†GCuuCsX^+@H H PPP??9//2201#".54>32 ! !XJogNIogN e#'ՑLLՉӑKKdDF?!O@/7&8  0P` a ??3??32/3/]993]3]]92/01"#3667>32&&#5*$= -* 7>32&&#"#R f5AS<, ( J?FJC9]ge%@]uC(A.?!s&vR&m1%+55+55R!&v$&8$%+55+55F'Ho@DHHH HH/(7AA')))((( (6 6677 H/ID=6(#_???3?33//]]]9/]3/]]]3/99+]10#"&&54663232>54.#"%33>73#"&'532677j8m]]m89m^]l8y .#$. -#$. d j)>X>%0/1?ݶcbee貉ۙQQۉڗQQ8=?>@<aNxS+ WcP^>@dX>h>9>I>(>%>-I666XhxIY X,I,8,,,,I-fvI %>:P3,PP???3?99/]]/]]]]]9/]]]]3/]3]]99]]]01#".54>32324&#"%33>73#"&'532677s&Gf@=dH'(Ie<9dI+{;9u<9td j)>X>%001?'݂44ݨہ33ۨ΃8=?>@<aNxS+ WcT{)?^@5% ;+50[A [/;O8_8885_+@(P(((%_ ?32/]2?32/]2/]9933333301#"&'.54>766326632>54.'#"&'{0acJ6:Gg^,,^gG:6Jca0/K6C30E7M00M7F04D5J/ݒ~>55>~}>12;~le-%'-dnnc0(&.esX!6X@/$ 5*/,H8"H5_222/QP'''$*Q ?322/]?32/]2/]9933333301#"&'.54>76632663264&'#"&'X6bV <6:;Qc85aT :9*Qd9׿ 8309 c` 9037 'u\6,,6\ts[6( $[sG&&GJ#*(GR{='f@k56?6O6_666660<(F" F"" "P5#"'6632#".'#"&&532&#"32>7Pr^&+7vg6jp}Jwz<8$2.;D}$Z30C*NB7)/"X0"N^!6.+*.5!^O#0X"/)8BM+D0-)(ˁ$*$-5#ke$*$MsL-%&F9BYe !! e%fgY .Xs;Qb@)////@ H//)I! 7dFIXR]]UU==H @- HI X`VU``HCL<==HHHU.,,Q2/&!Q?3322?3332232/]3/323/9/2/+]2/2/3//3992/+]10"&'#".54>32&#"32>732654&#"'6632#".#"#5463235654.54632>[ XIDf_.("#(/^eDJ:23#^-FmK'3Z~iPn`.+7vh>llwJxyt$2.;D# #<כۉ>>۝Չ?$+$.4lq$*$MsL)3&&FR{ J@dH; ;;;HHHHHHHH5  !L   A5II8F<<>_8;;8   8HHF_+&0?33223?3222332239//]]933333339/]]q3/]2/10#'##'##'532>5#"'6632#".'#"&&532&#"3273R#11#11#O'80C*NB7)/"X0"N^!6.+*.5!^O#0X"/)8BM+D09%gggg+Ye %% e%fgY+ 8@//#0I888&8F8V888@fH8000000)0I0Y0i040)(8 )I  *: P  I#04   )?3?3322293?3/]]933333339/]]99]]q33+]q33]01#'##'##'533>733>53#&&'R#12"21#P:ᠣ" Vm?O-BqXT jgggg\J\U38AC!`g`!hT8>#4@Z! %[!_  _/?2?32/]3/39/01"32>7##"&&546632&&k{C;vv-(%LWlON?'QډۖN bln,* .%^5@G !HQ Q?2?32?/]3/39/01".54>32&&#"3267#qđSTzZB>:O1^W5U"?Ֆۉ>"#ic0h^o @K ?O_ 0 @ P         @H @ H/33/+33/3/33/8+3/9939939999/33/33/]322/]32/93901%'%7%7%BG㴁FGJ{J;{Z}9IĤ{@  //3/301#!#"&54>3!6632+9?,08( &.08*P9),338% -12@  /23/3/]/102>32#54&#"##5Nwp:m|:.*eyUf$+$el#4.$+$5#@@ H  /]/9/+014632&&D;/2%9FI!JCAEH%F>>FI!JCAEH%F>H?GJ  IAAEI#JC5M> "?LK> "?JO>"#?NO>"#?N9O> "?NO> "?NNA #BMNA"#BM)b +6?JU>@+$ 6JD5/ !%U>OOO:/]22//22/01%#66736673#.'5&&'5667''667&&'7.'7 -Od -T d59:@>9L.u8?A<6o,?784F/q3@)m7Hw5=%$ GP2;&$! J/w6Wr#0u6?>: T d -R gi4;$&#G7;J'J5o-?:5/H5o/?:6/Hh1\@21'&& 3@  1',! _?3/?3?3322/]229/3/2210!46767##3333##".'332>7׮B٦a0]dgW*3K5,I6#9ALMF>CC JLhMwP)'OwP9H),G5%H@` H%5 H H* :   %FF F '@F %   P?3/?3?3322/^]229/3/2210]]]]]++]++!#333##".'332>7^ : {{%0]dgW*3K5,I6#jJdP}NvQ)'PwP9I)+H5/F!A@![#Z !__` ??99//32/3229/0132#!#5353!!32654.##7<~†N.[]NBqWap=`@Fa<=D!I@'F#GPO/P??99//]32/3229/]01!!!2#!#5353!2>54.#/eq98]C&!A`@!M|X/)B01B(F#l@;[% Z ` #` ??9/32/33/99399/]22/3]3/9939901'###!23267'76654&##F3R:hj},b9~<$ ;^mv<; =sfU N 9mgL"y]D^#9x@C2!3 547H;433* G   $P 2!3 3544/P ?22/32/99399???3/^]22222/3q3/9939901".'##33>32'"3267'7654&=bO= _Tkkt DDOmC DoT"jlo\+: "7+6#=-HԌEN .^_)ek7Lhd 1@Z  _ _ ??9/32/329/01!!!##53dP}J 1@  G O P??9/32/329/01!#53!!!!#q&8@"[( Z _  _??9//32/]2/01"#!!6632#".'53 4.%<H-WRv1ND< ?HwC{ \O  y~@ XJ)5@H%+FQ P Q/??9//]2/01".'532>54&#"#!!6632)A7104=&FnM( S# "N*}ДRL   0ci/J>۝և?r@@ /?iB   _??33/?339333/3/33]]]]22/]32/9/]332210!###3333#1`HAw<<<Jb@5 I I    P/33?333/9333/22/]]]3]29/3322310!##3333#àZJJt--5e}B/&2, %+55B^&/)%+55x@Mu6V Z`p W @ %   (U6$ ?3/3?393/]]]]]2]3/]]]]3/]22]]]10%3###33+76˦<BJM@, F  G   P ?3/3?393/^]22/]22/310!#333#ݴ-J_} Z@I & `p@`      ?2?99//93299?993/8]]]33/3/]9/]]33222201!###3733wwBdbceJ@K I  {`G`   ?0?3?99//]]9399399/]2/8]]]33/39/]]32210'#3733##}6}J8 ';w@J Z `pHX@`_  ?2?39/]932333/8]]]33/3]/]322999/10!###53533#73>yr`{3;z@IveVE G  H`Yv   O ??9/32?393]3]3/8]+33/3/]3229/99]]]]10353!!373###;{ V^uߘ%RZ_@. H Z  X  _?2?3933]]]3/833/83/9/299+q01!##!5!73hudN+J \@6(8 gVGG  P ?3?393/8/9/]2]]]223]3/83]]013##!5!`LJ-N@/ Z    Z_  ?3/3?39//]]2/^]q201%3##!#3!3 VhJU@5G F   O o  G P  P?3/3?39//^]2/]]]q201!!#3!33#F𶠰J9P} K@/ Z?O@H  Z_ ?2?39//^]q2/]+]210!#!#3!!!aVhJ ;@" GO  G P ?2?39//^]2/]201!#!#3!!#ǷFJ9ǚj$D@&"@ H&!0""! _#!_ ??3?9//]+9/2/106632#"&'532654&#"#!#!1b[+3^T6U+&I/sdgp3a\O  J)N@,I` I%%%+IQ PQ/22?3?9//]]9/]3/210"&'532>54.#"#!#!66329<\(*R82F,/L9-F0N]40Wy /bkkf1-PJ'9ݥׅ<TASk@=3OOL[8 888#""B[ U+[/G`p====&_O30_ _ ?332222?/]/]3/3/2/39/q9333103267#"&'#"&&546632&&#"3267.54>324.#">{6G'7#;D E>)U;~ĆFE2]&8="Q|T*.X~P%8&)PsJJsP* , , 80.js%  ,4_^ D㞝݋?6uV|<7vVY-4`TO!e|ss^P@9H4CWH 9Y9H999$##HCNNCCR,H NP>>>>>@ H>>1$'P# 1PHJP?322?329/+]q/]]2/2/39/]]q]9333106654.#""&'#".54>32&&#"3227.54>323267!+9B ,>?RA|9&S/oGCv9O -8*QuK$'MsL "4$0TrAAnR.0@%'59?4[M@-k3T: zh%LхԗS  8lgai8'PZg=^Y+'VcFwcO B&&v$ %+55B%^&F75"%+55fd J@, ZcP_ _?3/?2/]_]_]_]]]/01!#!5!!3#û^_yRJ 6@ G GPP P?3/?2/]/10!!5!!3# oo}!<RyJc@>7G&H) G{cP ??3933/]_]]_]]]9/]2]]]2]]10#33>73H  HJ Z]VV]Z o!ʹ@$ H&6hxZH)9' H@THY H{P Z    c  P   _ ?3?9/32333/]_]_]_]]]32/9/]]]2+]]2+01+]]]]]]]]+3!!#!5!53d}&ڻ'=X3RyJ@ v  @G H y HGcPO ??39/332/]_]_]_]]]3/39/]2+]]2+]]01!!#!5!33>73 H  HcJ Z]VV]Z o5@GWH h x    @ H  &  @@ H&  H  )   H )   _?3/3?39333/33]+3/3]+/3]+3/3]+933]3]01%3###333GZKNZ{/L`J@$ H   H H@ HI  H  F@3H   FP   ?3?3/93333/3/333/]33/3933301]+]]+]+_]+]+]+]333###w"#u-P3fg}L9@0Z Z _ _  ?3/2?32///]01%!33#!#5!#J?@$ G F@ G P P?3/2?3//]]/]01#!#5!#!33y}P=@"Z  Z_  _?3/?39/32/]2/]01%3###"&5332673 QT2R=MT?&G9W:JA@%GF/G  P P?3/?39/32/]/]]201!#".53326733#F'NRZ3RX/idNI% /TsDfXV-+P}FQ@& ZZ   _    ??39/333/32/22/]29/3210!###"&533336673FAm5!2R= 3q?V$ 'G9W:X $%J_@7I@Pp G GP  ?3/]33??39/333/3/]29/]3201333673##5#".5Nid}hi5e7}/RX/JfXV-F%3/TsDF+@ Z Z_ ??39/32/]20136632#4&#"#n_ĻduVk--/tt((95J;@$G G   P   ?2?9/32/^]2]01!4&#"#3>32idZT,W\e9RX/XV:9+J/ /SsDZ{-8T@/4[:#&g&w&&3[("`3"(( _._??329/32/3]22]]22/012!32>7#".'&&5467333>"!4.}]$`$KxZ/OGA!!AL\<~v< f !0WeZz†G  ]rz*B>#a[A~xuCX^,5^@81H((7 fvI0H/ @HP0 "-P'"Q(?22?9/32/+3]22]]22/01".'&&5467333>32!32>7"!4.lK 02KuZcn;L3WPM'(MQW`s 8XFǁor'?:"/1lu=Gnq ۜDqP,{0;g@97[=&)g)w))"6[,%"`6%++ _1_??33/329/32/3]22]]22/9/012!32>7#.'&&5467333>"!4.}]$`$KxZ/OGA!;CN1ZV. f !0WeZz†G  }orz*B>#a[A~xuCX^-6q@BF2H8"%f%v%%%I1H)/!@HP1!(( Q.P??33/329/32/+3]22]]22/9/102!32>7#.'&&5467333>"!4.cn;L3WPM'BNTc9 02KuVs 8X^Gnq  "uToor'?:"/1lu=DqP,,i&6R@ & %+5+5&6@ &%+5+5X%X@1  7 g w ![' Z a _?3/32?39/32/]3/223/301]]]"#3332#".'53 4.9R#5җSRw1ND<?~IvEs}<XQ휪O  w8 XJ"U@0"!!""H$ 6FF  N!Q ?3/32?39/32/]3/2]23/3]801#"&'532654.#"#33jdOJfLi/,iB4aUSKb=ϕՈ@%jb.LJ#K@* """""[Z_"a_?3/?32?/3/9/]9901%3####"&'532>7667!Ð٦ !"5OnN#J; 0@* !'+AqQgo; ?bu69:J?@! IGGPO P?3/??/3/9/9901%3##!#"&'532667!{{@_V17YE3}iuoFN@. ZZ  0_/ _/22??39/^]]/]q3/2201".'53265!#3!3X-G=68n?IJ  VhݪO -JH@* GG PQ/22??39//^]3/2]201"&'532>5!#3!3Ki/+jB;[=߶!?o %-aiJ9Ո@T@1 Z  0  [ Z_  /     ?3/3?39/^]]/32/]q201%3##!#3!3Ð٦ VhJI@)G G  G P  P?3/3?39//^]2/3201!!#3!33#B춶{{J9P}F=@ Z Z  _ _ ?3?3/9/32/]22/01%#"&5332>73##9e^\12R=-VY`8" G9W: J'%JK@-FG G   P P ?3?3/9/]/^]]22/01#".5332673##3o,W\e9RX/idYT0 /TsDfXV:9q@< l|[:J)      @XHc s T 5 E  &        _   ?3/3_]2_]?333?/]222]/]q2]2293301]]]]+]]]q]]]]]]]]]qq!##3333##46767#򚹰lJI?9Xw4=GIsJ$@$$$$$$i$Z$H$)$9$$ $UeF7&   I$$I{$$P??3/3_]3?333/]32/]293301_]]]]]]]]]]]]]]]]]]]]]]]3###.'#3>7{{{ǃ  JP}EJDy>IKJp"QK>=JN",!i&$6R&%+5+5&D6@ $&%'"%+5+5!+&$jR&%+55+55&Dj @ &&-(,%+55+55-^#i&(6R& %+5+5H&H6@ & %+5+5T{)?@$$[+%[ 0/%_ __ ?32?9//]3/]201"5>32#"&&55!.2>7!#oO&P]oCٓKIЇz7b7d0M}Z6c#Kw),  l髮hgRzGfA~xuDH^'I@+"H)#H#PP Q?22?9//^]q3/]q2102#".55!&&#"5>267!-wƏOHolx@8aYT,+SW`d Bg^J҇֔OGnq  %DqP,T{+&jR@ .&04%+55+55H&j@ ,&.2%+55+55+&jR& %+55+55&j&%+55+55/+&jR(&*. %+55+55&j%&'+%+55+55B K@)WF[ [ "  _a` ?32?9/2/]3/9/3/01]]#"&'532654&##5!5!JsGC͉nU+`cc.Ϻ{=;6df`t@"-$ Ѧ;J$F@& J$$J F&!  N!P"P ?32?9/2/]39/]3/01#"&'732>54.##5!5!HhNL{z>!Tbo;M\3;l[w=@rlnK$"0YNV{P%}횅F&MR@ &%+5+5-o&M@ & %+5+5F+&jR@ &%+55+55-&j@ & %+55+55T{+&2jR@ &%+55+55sX&Rj& %+55+55T{~sX^T{+&~jR@ .&04 %+55+55sX&j#&%) %+55+55DL+&jR&"%+55+55%&j&Ǵ! %+55+55&MR@ &%+5+5Ryo&\M@ & %+5+5+&jR&"%+55+55Ry&\j@ &! %+55+55s&SRR@ &R#%+55+55Ry!&\S^@ &^" %+55+55F+&jR@ &%+55+55%&j@ &%+55+55+d 8@# Z 0_ _?3/?/]q2/10!3##d#J .@ FGPP?3/?/]2/01!!!3##ˠJ}`m+&jR@ & %+55+55qZ&j@ &%+55+55mdH@& Z___` /??9/32//322/9/]01!!!3#"&'532655##53dPn}'?:"/1#ل 11mJH@% I GP O  P Q??9/32/32/322//9/01!#53!!!!3#"&'532655#n~&?;".2ل 115m&; %+]55`mwJ&[^P 6^ %++]555 @ H  &   H  ) @ H& H )   @ @ _  ?3?39/3322/833/83/8399//3/83933333]+]+]+]+01##!5!33!KNL{`/`jJ·@$ H   H H@ HI  H  F@7H       O ?3?39/3322/]33/3/]33/393333399//01]+]]+]+_]+]+]+]!33!!##!)"#-rs{f1L*@Z [_` ??9//]2014>333!".#"337Ϙ~=][.WqBhJ=p_33332>5#"32>5CmO\m"#za1hpRAD,XPB^<N^0<# PTe7WWO]gr<hrg3S<CkM#@!(F%22F?;F8P&-P ?322?9/?2/]9/3901%2653#"&'##"4>323&'&&53!2>754.#"XB;"DeCn"+54.#"'>323#Ż8g]\a2%D_:nK\&btHmp93[}KW^2DcA 'He=6S:C6}6)6aOIxX9  9YwHP\^/N@)$FG++/F,10P$P0--+P?3/?39/]923/3/32/3/201!4.##532>54&#"'66323#>fK>dH'/RPP-?]scq=3G+6T:+/I1'@-MM '%$HjF5Q;) ,B[>}0S@. 0 00 #&&2 _+$$_` ?32/?9/?/]99//]9901##"'532>7667!32653#".5-  0N>3';BD9*NmDCnP,tQgn: <]q6;9сww-ib.,`lJ)I@(IF))) F+ P O$ ?3323?9//]99//]10##"&'532667!32653#".5- &0:E)1%=0% 7HA:$InJGqO*ՑY'uo=}{5ib.%WhyH@*8   G__???39/3/]]2]]9/30132653#".5!#3!3>EE:%JoKKnH$ꦦww-ib.,`l-Vh{{JP@1IGW IHXIP P?2?9/?/]2]]9/]301!332653#".55!#"7H?:#FiGClL(ޢJ9=5ib.%WhJuo(I@*(( 'Z*[  _(_/_@H"_??39/+]2/]2/39/01!#"&&546632&&#"32>5!4oyҍHP؈sKH:^Vd7-YWRmBIii,*"2QډٚU7osq\^(A@#(( ?'G*H  N(P"N??39/2/]3/]39/01!#".54>32&&#"32>5!{2qȄAGЊoM=<[[\/%S^QnBJDȉGOӄҔP%'-:mb]p>-PqC@@&Z  0Z0__??9/2/]]/]]0132653#".5!5!!qR\\R2]QP_5^_ww-ib.']s)oJ<@# GG PP?2?9//]]/]015!!32653#".5)51P;i_/_`[f7AbA 5ib..bi5D;I@'1'' =Z [116a&#`', ` ?32?329/]9/]3/22/9/014>32.#"33#"3267#".54>75.:H+) O&##$7P ,P N ?2?]2?9/32?/]3/]2/2222229/01!5!##".54>323&'&&55!5!533##%2>754.#"/h=Nb>aq>>qa=bO= {OmC DoTK"=.F̆΋G,: !7+,YZ'af4! 0@_/22/3/]3/3/01#.'53#.'53d"RM@+.0e"RM?+.0SXQ"QQLSXQ"QQLD@#?Oo @ /22/33/39333/]3/01#&&'#56673'>73#+d3l46j3e3t00t3N -j7e"T00T";EE;,.4!3232673-3t00t3e3j64l3d$HE?(*\0B)&JE>(*\0B;EE;"T00T"Z"*20Q;!"+10Q;!9 -@  @  /22//3/]01>73#%#"&'332>7% -j8dn,LnGm0D+$B3",.5!7e8j-!,LnGm0D+$B3",g<!5.,7'#'6654&#"56632,LnGm0D+$B3"+#-V 8A9+' &cd7'".#"#>3232673,LnGm0C,$A3"/$HE?(*\0B)&JE>(*\0B \v \ T.Digitized data copyright 2007, Google Corporation.Droid Sans MonoRegularAscender - Droid Sans MonoVersion 1.00DroidSansMonoDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.Licensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0Digitized data copyright 2007, Google Corporation.Droid Sans MonoRegularAscender - Droid Sans MonoVersion 1.00 build 112DroidSansMonoDroid is a trademark of Google and may be registered in certain jurisdictions.Ascender CorporationDroid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication.http://www.ascendercorp.com/http://www.ascendercorp.com/typedesigners.htmlLicensed under the Apache License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0ff  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.nulluni00AD overscoreperiodcenteredAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflexCdotcdotDcarondcaronDcroatdcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflexGdotgdot Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek IdotaccentIJij Jcircumflex jcircumflex Kcommaaccent kcommaaccent kgreenlandicLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflex Tcommaaccent tcommaaccentTcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute Scommaaccent scommaaccentmacrontonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonos afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061 afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109 afii10110 afii10193 afii10050 afii10098WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave afii00208 underscoredbl quotereversedminutesecond exclamdbl nsuperior afii08941pesetaEuro afii61248 afii61289 afii61352 estimated oneeighth threeeighths fiveeighths seveneighthsDeltauniFB01uniFB02 cyrillicbrevedotlessjcaroncommaaccent commaaccentcommaaccentrotate zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperioruni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni200BuniFEFFuniFFFCuniFFFDuni01F0uni02BCuni03D1uni03D2uni03D6uni1E3Euni1E3Funi1E00uni1E01uni1F4Duni02F3 dasiaoxiauniFB03uniFB04OhornohornUhornuhornuni0300uni0301uni0303hookdotbelowuni0400uni040Duni0450uni045Duni0460uni0461uni0462uni0463uni0464uni0465uni0466uni0467uni0468uni0469uni046Auni046Buni046Cuni046Duni046Euni046Funi0470uni0471uni0472uni0473uni0474uni0475uni0476uni0477uni0478uni0479uni047Auni047Buni047Cuni047Duni047Euni047Funi0480uni0481uni0482uni0483uni0484uni0485uni0486uni0488uni0489uni048Auni048Buni048Cuni048Duni048Euni048Funi0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9uni04FAuni04FBuni04FCuni04FDuni04FEuni04FFuni0500uni0501uni0502uni0503uni0504uni0505uni0506uni0507uni0508uni0509uni050Auni050Buni050Cuni050Duni050Euni050Funi0510uni0511uni0512uni0513uni1EA0uni1EA1uni1EA2uni1EA3uni1EA4uni1EA5uni1EA6uni1EA7uni1EA8uni1EA9uni1EAAuni1EABuni1EACuni1EADuni1EAEuni1EAFuni1EB0uni1EB1uni1EB2uni1EB3uni1EB4uni1EB5uni1EB6uni1EB7uni1EB8uni1EB9uni1EBAuni1EBBuni1EBCuni1EBDuni1EBEuni1EBFuni1EC0uni1EC1uni1EC2uni1EC3uni1EC4uni1EC5uni1EC6uni1EC7uni1EC8uni1EC9uni1ECAuni1ECBuni1ECCuni1ECDuni1ECEuni1ECFuni1ED0uni1ED1uni1ED2uni1ED3uni1ED4uni1ED5uni1ED6uni1ED7uni1ED8uni1ED9uni1EDAuni1EDBuni1EDCuni1EDDuni1EDEuni1EDFuni1EE0uni1EE1uni1EE2uni1EE3uni1EE4uni1EE5uni1EE6uni1EE7uni1EE8uni1EE9uni1EEAuni1EEBuni1EECuni1EEDuni1EEEuni1EEFuni1EF0uni1EF1uni1EF4uni1EF5uni1EF6uni1EF7uni1EF8uni1EF9uni20ABuni030Fcircumflexacutecombcircumflexgravecombcircumflexhookcombcircumflextildecombbreveacutecombbrevegravecomb brevehookcombbrevetildecombcyrillichookleftcyrillicbighookUCcyrillicbighookLCfritzing-app-0.9.2b/resources/fonts/NOTICE000066400000000000000000000247071250202676700203660ustar00rootroot00000000000000 Copyright (c) 2005-2008, The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS fritzing-app-0.9.2b/resources/fonts/OCRA.ttf000066400000000000000000000355601250202676700207240ustar00rootroot00000000000000pFFTMe;TGDEF9 GPOS;$0GSUBꡗ9XOS/2nxVcmap(gasp9glyfY#W\.head 6hhea*4$hmtx$loca{0pmaxp]X namel.4post 80q\Kg_< ̊3S̊3SW,|RR,Z|uZ@1 #*PfEd@ % 8ZRoqqqqqqqqqqqqqqqqqqqqqqnqqqqqqqqqqqqqqqqqqqqqqqpqqqpqqqqqqqqqiqqqqqqqqqfqqqq7qqWqqqqqqqqmqqqqq7]}$B%% _$@%%{*r  !"#$%&'()*+,-./0123456789:;<=>?@BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`mnpqseorfAa0^: T~<j0\>fHz8t*Dp V  > ~  0 N z ~  t  R,pb>xN F|Rtb&P^ %546;2+"&46;2#"&'1113**oe 475!#"&5465'#"&'o * )r*$ %  J2qc =A46;5#"&46;54623546232+32+"&=#"&=#"&735#q111*a*1111*a*1aa\o*xxxx*owwwwGoqc 16463!5!"&=46;5463232#!!2+#"&=#"q[[*Dxx*Dwwqc /747632#"&546;2+"&546;2+"&q  scc)cc  UUTTqc.6A754?'&=46;27632#"/+"&7;7'754&+"q\` Y>`>Y}k3!47Jb>YeO8kNUo`EOfE>YY>Ekr,  8;? Y>0rB*[^.T 46;2#"&ccT  54?632#"/&+u uu u+&E8""8 74?6=4/&54632#"& uu u++u3""8EE8qUc374?'&54632546327632#"/#"&=#"&qss  ss bb  bb qc46;5463232+#"&=#"qq**d46;2"&=#"**q)c5463!2#!"&qs\**9%546;2+"&ccUUqc 747632#"&qs3  Yqc 7463!2#!"&7!!q<)((==()U&* mqc -87546;22654&+"#"&5476;2#"'#"&726=#"qX=d(.- 67DIiY=9*,8=Xe(1>X -#$12jH<=Y''X>nd 7>2#"&/##"&73n"''R3Kqc "3!2#'326=4&+5326=4&+q(RxFFxR)<<))<<) xR%Y>>Y%Rxe=(%);2+";2+"&'&'&qeK- g g ,IJ52$/<0$>3qc (746;#"&546;2+"&732?654/&+q11,IfeK-$ gg $3B0$4f4$/G"qc 3!2#!32+!2#qZ *qc 7!2#!32+"&q*3*qc *74?6;2+";26=#"&46;+"&q*-KcZ>?XE6:"g*>ZYqc 7462!462"&5!"&q*(***3!Y!qc 746;#"&5463!2+32#!"&qs3B1 75462;265462+"&*_*Z>_>ZC>YYqc 7462632 #"'"&q*9`*3   qc 3462!2#q*Zqc 7373"&5#"&='"&q~{z*ba*3ٯ'Nqc 73462#"&q**3(&Xqc )4?>32#"&/&632?654/&#"qk?&'?kk?'&?ke lkl l52))4f4)).W<"qc 7!2+"&326=4&+qZ>ZZ>*e3Y>>Zpqc !@74?63232+'#"&7;7'&54632>54&+qF /2J#,A%K"-2Hel%   "{^=I2)%" $=^@I2\^  $  0qc #7!2+#"'#"&326=4&+qZ>Z[=:E*e3Z>4>Z 4qc ,7462;25&=46;2"&54&+"+"&q* C.7Q* tA/7P  &-BP7  "(/CPqc 5!"&=##"&5#"&q*ba*"t"qc 7462;265462+"&q**Z>>YCC>YYqc 54625462#"'q** "# %z qc +74623>7463237462+"'+"'q*))*9b az`0& C &0Ea##qc #747&54632632#"' #"&q3 ::   qc 546275462#"&5q**sgDDgBpc 7!"&5463!!2#!ph5A@g@qc 7463!2+32#!"&73#qsd003GBqc 4632#"'&qsY  qc 746;#"&5463!2#!"&%3#qs]003BYGBpcb7632#"/#"&5p  qc 463!2#!"&qs21 46;2#"'&c  qc8&47546;24.+"&46;2#"&5+"&7;754&+"qX=  =W J =Xek8>X! *U<+X>?,qc )C74626;2+".'"&7;2>76=4.'&+"q*DCK 5)8K6*eV K K V3@ .D$J  J qc8&7547>;2+";2+"/&q4 3!: VV 9)V4xE- 1* J xI $J-qc -H75467676;25462"&=+".'&7;2?6=4/&+"q*')8K**6K  4e KVV K0; $Y +G   J xJ qc84A754>76;2#!3!2#!".'&7!54&+"q )8}   5   4e(<}#<$  .D|    +J6 I $46;546;2+"32+"&5#"1hJyy -cc*1*"Jh- "*`q,c8BY754>76;25462+"&46;2>76=+"./&7;2?6=4/&+"q )8K*)86K4d;K VV K  $$*-E6 JNJ qb 746276;2#"&5.+"&q*`&+9=W  G*3=U<si16*746;#"&46;232#!"&546;2+"&ccbc223n*`**,16/4632;265#"&46;2+"&'546;2+"& bY>b8V11M*>XJ5/**qc 7462%632#"'%"&q*0*3q  *1 746;#"&546;232#!"&bbb3Bij8.746326327632#"&'&+#"&54+"&i)-=$!*/HDK*3#0B/o:Aqb8 746276;2#"&5.+"&q*`&+9=W  G*3"=U<siqc8&@754>76;2+".'&7;2>76=4&+"q )8} 5)8} 4e }<}#<$ .D$+G   6 q,cM,J462>;2+".'"&;2?6=4/&+"q*  70  5V)97 *e   WW Z )&&D.J$   J  K [ q,c8-H75467676;25462"&=+".'&7;2?6=4/&+"q*')8K**6K  4e KVV K0; $Y +G   J xJ qc8746276;2"&=4&+"&q*w c=Y*Q*3;fY=qb8474632;2654'%.5476;2#"&+"+"'&q& "*%&5K0 - &5Z?I>] " xC'3$&? + xM.?Y5qc*46;546232+;2>32+"&5#"q1*d  U7d=X1*ww*4KY==qc8 4632;7462"&=+"&'q G**a&+9U;qc854625462+"'&q** !?! UJSJU ~fm8+46327546327>2+"/+"&/f BB ( 317814lrrrrl#ʪ__qc8#74?'&546327632#"/#"&q  3 q,c8#46;7#"'&=46235462+"qgC" * * "*S UJ,JU qc87547!"&463!2!2#!"&q`u<s3* R**qc *46;26=46;2+32+"&=4&+"qa=(''(=aq*)<9,,9<)7 %3#"&46327e3!!qc *746;547&=#"&546;2;2+"+"&q'')<bb<)39,,9<)*)<qc &5463226=462#"'&=4&""&q]<:X(*\=<+,(*oAVX?4ooAU+.=4oW|%!W%>7546;2+"&3qc 4762"&=47%5'#"&q*$c*1 UU&* qc .746;7#"&46;7>;2+"32+32#!"&q>EC P4;Fs3*-@*qc )46;5&5463263232+#"&=#"q*G   * 46;2"&5465 c"3(!d546;2+"&=#"&2c*qTc 463!2#!"qsq**qc 34623!"&=#q*a,*b1Yqc 7!462"&5!"&q***3!Y!qc 462!462##"&5q*(*T!z!qc "%1747632#"/##"&5462"&3'75462"&q "# # %% #**K**3    __ gUUtUUme #'7.=46;2#"&/##"&35#3'#m#0<)(=0#'( F48$E)<<)E$84CEhqc (+7476;2+32+32+"&=##"&735qbbbbe2 #@3 *w!qc 174632462#"'"&546;>32+%#"&q6**]3)XK+%+%qc &2BN547676;2+".'5'&5462"&;2?5'&+"5462"&qY#D$R5#%+! Q**dv vv  v(**2 ~(5 *q 2 L9&  $qUU 3 ;UUqc 1@P74?.54?>32>32#"&'#"&'&#"32?654.'qB!k?&*A B#k?')A e " l W"l  3 q ?#=52).#' q @$=34).#'h  ,CD"  qc '37462;265462+"&5462"&75462"&q**Z>?Xc****hh>ZY,UUUU7R37eeI&V$!p a'    B,       .v (7   Matthew Skala (2011-12); based on code by Richard B. Wales (1988-89) and Tor LillqvistMatthew Skala (2011-12); based on code by Richard B. Wales (1988-89) and Tor LillqvistOCRAOCRARegularRegularFontForge 2.0 : OCR A : 27-9-2012FontForge 2.0 : OCR A : 27-9-2012OCR AOCR AVersion 2 Version 2 OCRAOCRAAlternate hyphenAlternate hyphenAlternate commaAlternate commaAlternate apostropheAlternate apostropheAlternate question markAlternate question markAlternate periodAlternate periodu  !"#$%&'()*+,-./0123456789:;<=>?@BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`  bcfgh uni25A0 period.alt question.altquotesingle.alt comma.alt hyphen.altuni2440uni2441uni2442uni2502t DDFLTlatn$aalt&ss01,ss022ss038ss04>ss05D&.60dhlpt."( ghic"d "RB"] YY ,.DFLTlatnmŮ3P̊3Sfritzing-app-0.9.2b/resources/images/000077500000000000000000000000001250202676700175645ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/images/AboutBoxLogoShield.png000066400000000000000000000072631250202676700237770ustar00rootroot00000000000000PNG  IHDRdۄWtEXtSoftwareAdobe ImageReadyqe<UIDATx[lm/ظU#\ U*C}P!$@M(uHEyU"xR2m:<{j P,hS EHHnZ_* ˇҞmj3G>*7P,l £8C/z+שTOju|wzB}lL >^'~N7AO{5~"⨤vN~; rH)A:P]בPB"3?1"&iέ, 1*f'eTSϰG&p)gTБ+R,싾%3Yc%wP`'}z}8B4Q:2 WX=% qt6n a>! Bݐ C 4˻K%Y%q\݁;f "+{Y1Cᮈ QI)"䁆! B BbfM"s&[67,ኹ!ޕkº嶿lװ͟;/\BVԒkܒE#15⒠kfâeW"Cj6;PnnS:Ych@Y-\3X3GE tS"E@f{7U@]?>rrjvnN>FqN!8.}]Bo?B7Ȗra{ya'߮X&2e B0h\ / y}4. Wƈ-Q !PAC]sk^H Z݉+NEEX|j0ȇ #jI .r@2Epq VR/n)q {W$k+I- BbF,R)P0\U|6l>ȱzik5P("J\%Q {P}"VCEYd!"n{!Wb[IFJ;V~g - BRmƯ'ŘX8Tx64醐irVs=вpT )$AdO,3S{Ǐߦ߾ bA!&ΛYO\\bAS0]nb@(JVvMbA!,$a)"B@rѶx'5MV$hYmk]~DEb\cd0~1R+"hLJ*X7@:Ў B M!\YKQ{wbB/b i el*RfyFp-LI*&e,gI`/7Ll3ٱXNK W-rI_*dyN~rR0S`H+yIVsX`rskcO~ tc'rwAЍiJiCJ9QQGtbѳJuKhQC kdt\).$v64" ++$[{W/y\#9yeBh֡$MX$[Lf7b|-d>}Nv׋=~.,f+EPe!pqa< >hE1D/1˾JWu%`ۀѲp#yٵ8شYwN{=Fڤߦž̇01T|k1ly@70*.ly - BH~Ev=pAł"r^IJbAܻOzrNg0`#v?_ f+ȄK(XHFWVf*Fљ籡YR4U\Nv"&+=#8(D6w]pX/q;{*b:Y6Ra#C3+/W{ةv\?{Q tl|gCƷG}tݹ㦿@_U\=\y µ#)$bT7;S>^_N"/ Csg*(P6gW1 *$G($ɠ7l߅qcզ+5'! "8|u`'w:l 44|||;G$eA3FL/v( KOងzLx+>4> P,ˀr/Ai~O(*S4n C\`Y@}ښ3m)!hw(JۤaĬ',)K(^ɑ]\bAh\D`lZXP,s]40*-u*`+OuH" "DpDܙ2qEMSqs Sn@,FN.X$3F3HX4t=uj вmͭy vxXWYX}XD eB(!$7ͷmRTd`=Z!nII^)L֎ Pdt\_H代BeA73IҞt;I(Yi,wtC!bAXB(!bAXB\H3[$!ĊX 0!tC! BłB P,! yG@IENDB`fritzing-app-0.9.2b/resources/images/aboutbox_CC.png000066400000000000000000000015101250202676700224570ustar00rootroot00000000000000PNG  IHDR/ &sBIT|d pHYs B4tEXtCreation Time01/02/09ktEXtSoftwareMacromedia Fireworks 8hxIDATHVU@:uu p p*  D[ˇq==Kw;s{{B,\Xȝ]6H^nz o'߄_7f1YYD7 "(4fv}zUdVNv)~!B$_9[ڍv ]E[¾\BlcdFj569\.+׉fv-ѯ'4Jm#60 {O$w"ﵜ [ƴȅh0PUo&[*Z'q,DNsp>)=޶;337;ٝ}ܑFihHAeNVfd!;<ə{_ 4`Y&S/5Gw<%/x#_cjQک]Td [{68.0d ScJX9:vC.0 ]1;$x'xlHIJRN{=5'w8;m?npF'yIENDB`fritzing-app-0.9.2b/resources/images/aboutbox_FHP.png000066400000000000000000000657721250202676700226330ustar00rootroot00000000000000PNG  IHDR)VsBIT|d pHYs B4tEXtCreation Time01/02/09ktEXtSoftwareMacromedia Fireworks 8hxprVWx 0 g#v:,*v&ROY9` }j[OFPawt$Mp[ÊT{O綛ݣtp7mYeݽﰇh[yM[*6umZ:m8ABb lzG*#ex_/@{Wn=o՟:"fpvk@ ?ZGY`#XÇc1|j1|t-cLci !!d0Iq7sJ`c7'g&Sl Rxl%_Z#8{p3V\r|nE||SVsӾZ3ö1lC#WscRW!r9,s$|c<+a2ԁ[>0*|"Bl8R-nAUbr;Rtꂊ NG_֎m2w uA> ڴGv)s.x'EL W\ Arv@thj#%4/ !9,XN'rr|97ܒ"C0Exf 'H ; ^7E\шa&l8rRLӊ=650v(751BЂ|&[Z&6f"}Țͽ Jrk2,вPf0 0V\99`(Av_ "S1)p2p4k< yG+52dG"`YL)0A%ߋ\Z{% f4ԃagzh0_U܃^E؀tZ2] )J-J ֛"0|8 i+#x$+L gX3Ji$45MAScrBLB|6Ĺٗ,22B&CȼeRz7'zXld0 &2\p[5ekG9FuW렚< 5i_x *9l!=1!%.x*zY9,nJ8H7#.P#Bhb͓HZ,F/LZEY& =U$٣x>Ws9% ,1 wS2m9Vn]e'`43&]-P(HB'K5G:lPK)e҉s1|3F!?^Yp b&+cjsӄڐ爘a2Xm̀lǁl1^ClC`xL)N'"Hҭ~} ~!E9+1g0A"ԩ$RɈ#=yὥ .Fb 7c gV[W2a32_%7=p8A~ p`/gM/L>9 Hi'uzFW<$&4eou{a\/S1ye״p|6FC4bk̚J|F-SZ ǔlΈFv/cޣ}7y&*dQy4 '_Q %+EYhe0 z(ujo&8aj\ ԩd7?h±IpE Zaܺ{ķII0V&͑` /AgmNdI|:о"u& eTak aL%yssBv<Y4/%2[=ͲObH*,x$k]ƺ44[3ۺ-tuE|IdIKKZb"mL|&WESTWd?8*gMF8qAU$|i3͖. '31ɷ(Ls#+I\"iL;KEجsjY0VѭGp^w·Iyt/C{I>N3gz<2J@dbEK,U酓I&>㷔t̟0l7T^ t)WtLԥJذ]jeƙMsq/&f ,[Ŵi9P[$uvq -"yZ4e !,)CRbfGc~(]z~cF^] ЁC0$vMFKqp~RfiqעSz=VwȊs,h_ФhYjM&iIP-z !ȔM_S~ f/'{G/aiW4RU+XjZAkG\|OŘrz*EkMgr+3. Ao1o^޳PFsrSN.[IDÑsD?2Oԝeԕ$gT+3nƢ܋]Ui|+6<?K9^N\&YIDzH<?K9^NZu&z%2j"@*g)IfҲ+iS.}N?ߢS.gs('eeY>ldM8otGx<&'S9mAZ g5b@>)'!ٰYkVmv,x9iF{p?!ņcuяIg 5m{֬J_(ؙۑ3ޤ[傟 (vkSf ^@[e6=ټ'+&B]޶x$vٛ[M. pICjvU-h%-Gst3"ܪ|uf ٟ]XѾ`m{Ƶ-jwDo7˯3IEŘD~V*M'3>}Ƅ_E_b芡+re3>U<&~m;/[-SkgAm8[@5LM36qO10Z;ql^H衱=M |U&|%ǀka|)*_PeRFH 8_J$oGu)Z)!FC 9 Л߆1PwwWУoq-z s@mDӒ'C0>v"#4s2M @v0ާC%vQAF"^B?C=J"qz`qKWx ǯL!ۜOz9?Sq9{?Jz?*ӟ질?).:NC@R־g=~oEk!c ׾CU.cs" ф'o -h=lVc2E3H4ʢ -H5Þ]T/WCN֔_{GK#keۗ-kb_Wa?j<2 , ݠQXO]uI9puYG#G#|.oւw/c\S`3ڻ$uNh罂KVogVSZF9-GYZ?Q̀Сw*ylYlV3z.OZ?HKqg#S7 dX)bq?YVl@]1#x^R(` ]9EsU>eO9v(0\UعԇSj-1(nĤtj<+o|N:X>)2μq3Qoܢ9r0}7HVY^yFld3cS'i2y.7|clSvW!hvt#9z9pK3i=-Y>uJuGolI*j"\f>ݗ'z_Vf|o]/Žyg W{fN*iԩi5b{My7 f+'lzWp=s*c4<&ͽx#WGͿ1Nݐ|ͻ[%BOg5`R1m*DoD{-:cu8b?oM؃@XHwy}7yӅs}7_ >A/G h޽؅Nnz%;'.VM}P+}mQmFpf /8֦?wOL,]}BϾv?;M%DOqNu3,Z8$=/s3'oqaor}I%-~nWbqڥظĚRBeEM(l> =,z\ = 'pI6wv߂>@>+%4*<#Q}kFO۴ː.4bUiW0k wAL#*ocg u݁ă;qp oYHâpE \=j5ҵ~:D.j`WmkBSx]N0Æ WM- 2*5X|DZ=fLc(F? hҶ BLrGpodgd/e>f 9]WA\\Lf[xilϣTs1H QlHاEt(SAZ_Y X mkBTWx흍8 FSHI!)$FRHnw HYx3ꇤsaaaaxIǏ'U{o_ھgW9 o'GW {>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O- 92b?Tlk%?_21B sY5>:>c=1Ow y^- ڶ,XzusM#גU]>H_yYv!ۉ_mi Rus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, l gX #vQg Bٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'-(W? źvƔOʙRv[K?[A}?-wmՑ}g\=c}M ggg DŽ-B^k_g?F? v0||؎=ǧHPgs/hؑI t~{n^}ZyD5XWvO)"c0vY Z|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8gʱL{? 0 0 _k3>z_\S |<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu l+6v<ï k7]/lc[`On}򚄫 G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ 1Gg{+ҏlw<=}GݽFƨ^)zIpG K֜{{e G12ۭqiumf>.}~a? 0 0 [u+7Svq֭y΅ ?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo 9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3 _[_*mtcmC>qSL=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^U O7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU? 0 0 0 0 0 0 0.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwx b)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-tĒyNAgC \NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`% Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=o G<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy czA;w9zszWHVax3 %mkBTx흍) q ĉ8D^>׻gI@XjjgiЃ`0 `0 ?ϟ|:seQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/ D:3D&򈼹e^Hyi#/OGzϪ߯_~ :sMe#M3Y#=2 QЙ[\s=E8}E>GȩT ڲTg-}VfoSVwzV}./>~!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-k dW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ: `0 :8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV U?)V>ғ)x|Yҁgi\yi^cUo*= !TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x )/OS yUo2e)Ve3'wgGg=J^`0  ľu kU,Ksؑ5nY,bXw{ w&3QהNQev ]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fzt|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz `0 *\?W8GY:Dgcg< 2+'W6qn؟{ru"wU쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP ~n%hUG4(_sn|W}Tg&x^c,Fѭ+ <#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3 `0Q[ veO\k^8֔v<Zbz\Opbn$~}oz3ј mK vU]^iNWA#x딫jt q :E= z%օq)CcYEqyRG-+u (K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_Eб Vq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7 `0]kIu+eL]ւoA^;=GR?v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{ ?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0 leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR( VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l? `0 `0 `{~i`oLy>uoi\qK|}7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;y`$jwymkBT6x횉m0]HI!)$FR?6c>>~sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/rˆ_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{G}?v✽3X~j{zTAO^ʰ>?sy|G)PL&=]ԏqYWdY4?M&>Y*Q_Dnu:<)j|%.9=s_ߔoQ;LBW⼱ɿkoz?{_FCrEj~^6wTk~ڿ)8H>7_[0}x$az?e[߁{H={ܓU{ ..T}6ڳ-F`p]k߅~b  О$wݓٱ|sCoA+q3lOx@(0a+? T,_7s\Ϙ^Bl1)C+k(FyN"8dPC_9>O0&l4Im+nwGrŰ)/tihf ѸX>E)<,6s45zb?J\<OM%O#(76:= ӋYAƒH Ls6MXBcX&ǘJte. 3.je(??Lj=%wZizFTx$kP8Em jAOހ>~؆B9 ֤8UKCvjbL Cy ;mj P. DkwUE€3ܨ8xUJs\ɟ+;}sFQ(KIXݛƨ 1 +KdX];Jģcx$D׷X`i @l̏rnm$^9΄zBGϞQ=nfkDe; <a>,⢞jk0B[p($Ǡp4 nq`XƓ vϵ.xHnorJ5Hu뇗 f a[Z:>36[g RL؍?( &w.7C#~B{] UW 71jk~ecGrD.=K@WDZM0倐0\xvqNZ ># BE )&yA}t?B Ym(WIpɱ |2+\2 )l8tl@Z.Be񅋍RSƃm>dIl'N adĢG3%#)?$s _5=YBR#-k"qGP-e"f%֩-ϓ378M9ϊ,_*n;HEBƱcl~ ˝[/sagIE2,z1t:kLș壋G){7ond{@rP>kwk׽ #kXfyEAB9uM4P=_lgW؇N#_nGpp ,ZUu6ȓVӰ0EK7*|]{75F\ԶzQz! uH>upT٣o3P)[^6` -d&*=%fY<^ط`_6|h3ء>2 Pq7ώ ,NsjF=B` 큳CiU)R鐏@LҮǧmb<2FHRqùFXi䎲OmGA}:*u f:@ʫRH.66jcGOpO- 6HKJU:Jǃv,3DZEƮqq7p?ȌK%ȧ$;?Qr6pP7`a^=R_)m>D3#£ _' Iɭu͋C-Rne㯄ssL<ȭ/R)|Lt_1Lk=rr 4/gEr~PnB[\g[{gYvRW' {Fem1{ wL;7&$xc0 n&u@5sCCձm8Heft x{q(aтa?Q%l4ςxmWI׆GC1kQ3iJh,KRO`ʲ4)%b6B8\pe;u)ko)#WSncRx{[sXv195_0Kՙ7>Tp5ٴl3S"؝LX睫[5m Q="u}pϘ*xbՉ#iM+@Z! Ϯ~jYݬ$?5mtu] %@݅:4h8ۃtu3; ΑO1A/r R*5i&j#Y2:$Z(ad@>'z L뇶6Z8|`6"X1_z' F-я?X^ A:?1;h/KVB' vOnFS ƤQ{=kh7MwXQp\v͓O/. N3HKRlK"q^Wh1wt h@3e6N|I;y?8t[[! $,ήLe"z%IކAkRl!3u8ځy?_W)AbCO!rza5Sn֗#<43y6"R߃CQ&>[# BHǽ{vekOTlq(UH͵h ݔ8,@tՂL{p/*L"d_y k,4 G̖bD>,.ok"D;|7[.DCA#ilϟI֬Dq]+eE _-- ڰc^Lq1~CCC9gNH8BkhJ#Z-`VoMa 9r$պZ-hkh ?C$ ^tď9d(8P݅]ڶw[wl;dn׆oKd Hބ(DInI M_(5)6H/Y1 QRk,nXHʉ?>df&6^EJmt{CCc`0ʅv5x<\9Yc}106"״!֏9dl:' 1H"z'7QqɌ#KR./CVgQȬ\ `?d1yuM6Ƶ8ZX]8^pwQE &1frRKi$GݜЕh3'{;;~FK37ku<pdʎ+C RMzƏ7)nҀ lEGyl:̑IoBS%|ЕsTulebA}Aʹ10A{KʘӺtjdLI=r PRg_LbR Şl?␔)![Fo wi&k^CV(t@pW2{hxHGRn͉eCbxԉ6GQd27\ثdS=\Ff*0ۣOP5(rZߙxQZ>~GAeN-jY7Ҿn;n?ӹ"Px}/NW:݊&׾:x" ꭥу;R펔 c䛅љElmG§a= h¨BG_uYnZ쫭FYs U"zM&:Gnu.DX5Xn;}ԫ%XO?~2&Frjj8 yA*W I9/ub)Zl: s 85J>~iI3Yԕ;:#hELם[ROd^GA˩f~Y!En0~/A Km>^WYq"<цF*c:xw|͞w%ehRgd9̕v3v Dgh>>?3hYDkgC(ʹƒԕSԜ| 2Q94(?OGQ34 fccPopTYaW(>@tX4`LGٞpɄaŰl\[9c26U M6f,'C4i?W~psϠ?kAKrŵk@I|>^xs?\`,D̒5W^w DMXf_8<%|8_왉pP1Wlm߃f?4:́_Ԕv M;k:p_sj؎qw]$F}y ,b'N=o0, ~M YR46+!}@~ujctCP.Y(x׎z?70WXFܣo3z0c8RGg0 TU򄽻w"/4֏CQ`[{Ocn]+{{ N!33+5]qpj' r9FDȬ)~: 9Gmx2-?sraG"yvUpa;Ră A\& ?#n 0eed~oq嶭!!DzP^H)>oȑ.ļԶ=Hy7S-M ?8ycߧq|#5"2Б lm#UeΤVbM͘jAc7Z ]> 4gb s 2WRsKg6 's8qzTT[R[w)I95xWj #!nN+zPڔ KgTE,?{^RDݥ=Ru^zîc&D'i74SJߔ&HUG[crͦ<׿~4}څh;lpAZ%XZ;tQ?yk1+Ƴu6[ Dc4Ɯ*dB#!}e>samhG3c^8u9󼵕⸈߂UyB;f "Yi=D =4&|C3g]~WgjhSIXU"1A5Fr4{AljwTt6</N \Rta| i>T.Wo>>xϯY{緷m,J{gg}v~)]s!?wXGFl!7U|Cnfﳅ:.@mq%臔Ru?.:aBֺE#Gg'yXDuSWNJD)21ѵVagWPqȒ s?¶@g")s\T{f3go^w:^"{d#!φt},nyWFKv„X4|VB~,˘_&fjp/WԍwaO H 3I`u1ͤ+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_Wݚw)IDATH;KAAFEFF@2ة@,D & a}\,blRȁafϹΙ]/;@#hlړL&SN)9`8WյHU`(Y;IȿKGU՟!"p ;&9|1bQS{Ve`*6LFYU "ROSPUD {` Lz|3΋{4kƌ{'<.HVDP64$ow~~,uG UbQ'gq_=9%lw= d "2m3شI&NvaVBqAUj}'}k5ck'pkf s[8#kIENDB`fritzing-app-0.9.2b/resources/images/aboutbox_scrollfade.png000066400000000000000000000036351250202676700243220ustar00rootroot00000000000000PNG  IHDRztEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp $=IDATx]r0Q:]eK-<}VM(te93m#_:/_Giږ+ gd܇ͽ^}kz}c)'b˙=8G` >i)72;}I|s a@a@a@a@aa@a@a@a@a@a@a@a@a@a@a@a@a@a@a@@a@a@a@a@aa@a@a@a@a@a@a@a@a@a@@a@a@a@ay\.?{Js\Surrlduonk7K6Wm=ae'n>~#Kؽ=QY1еcV;%] xud ׻rۇ|X\׺gE) ?K@;J IENDB`fritzing-app-0.9.2b/resources/images/breadboard_icon.png000066400000000000000000000026321250202676700233720ustar00rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs  tIME3NtEXtCommentCreated with GIMPWIDAThMHIceBp$r/9/.֏z1l\A0&уv7M|,E]Pqу"qdam1Z=8N.TU_WjpLϞ=wwwBJ̌<FGGBɓ'ذtsDD|S177")MauuUN9Ánahh(^ "[#@ %U> !RwUHDeees玴Z[[($ PUղ~jj Ϸ#r"mX^^nY@DQ>>ׄH&`fi]~UZDpppaF33n޼ 0rFQ__sj,\.޼ys [CC‡066זmmm̸v>|xԁX,e@-޻wuuuH$ف03﷬'"re}}}b QUUdK ;j0 tttH>fi(--bӧOQXXh 933XZYY0 \r>-x<ܸqò*J#EQ0550^:'ҙ &%fF0iYyBLNNJÔr0RZfioocqq+^555R?3iٽ===B}8 )MAA^4s^|O>]ȼHH$fDQ犊 {!Q\\ 󛏓OLL`tt4h4 g_(.[n߾mϿ(X^^"B_퉦@II/#=rUK,c6RU~ؒ()G/XL5A._,$3X%W`d0 vW(, LIENDB`fritzing-app-0.9.2b/resources/images/cursor/000077500000000000000000000000001250202676700211015ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/images/cursor/bendleg.bmp000066400000000000000000000003001250202676700231720ustar00rootroot00000000000000BM>(   Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/bendleg_mask.bmp000066400000000000000000000003001250202676700242050ustar00rootroot00000000000000BM>(   ϟfritzing-app-0.9.2b/resources/images/cursor/bendpoint.bmp000066400000000000000000000002761250202676700235700ustar00rootroot00000000000000BM>(   fritzing-app-0.9.2b/resources/images/cursor/bendpoint_mask.bmp000066400000000000000000000002761250202676700246030ustar00rootroot00000000000000BM>(   pxp0x??fritzing-app-0.9.2b/resources/images/cursor/curve.bmp000066400000000000000000000003001250202676700227160ustar00rootroot00000000000000BM>(   ##Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/curve_mask.bmp000066400000000000000000000003001250202676700237310ustar00rootroot00000000000000BM>(   ?πfritzing-app-0.9.2b/resources/images/cursor/magic_wand.bmp000066400000000000000000000003001250202676700236630ustar00rootroot00000000000000BM>(   Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/magic_wand_mask.bmp000066400000000000000000000003001250202676700246760ustar00rootroot00000000000000BM>(   πfritzing-app-0.9.2b/resources/images/cursor/make_wire.bmp000066400000000000000000000003001250202676700235350ustar00rootroot00000000000000BM>(   `   Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/make_wire_mask.bmp000066400000000000000000000003001250202676700245500ustar00rootroot00000000000000BM>(   `{??Ϗfritzing-app-0.9.2b/resources/images/cursor/new_bendpoint.bmp000066400000000000000000000003001250202676700244250ustar00rootroot00000000000000BM>(   @ @Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/new_bendpoint_mask.bmp000066400000000000000000000003001250202676700254400ustar00rootroot00000000000000BM>(   @8pp8χfritzing-app-0.9.2b/resources/images/cursor/part_move.bmp000066400000000000000000000003001250202676700235660ustar00rootroot00000000000000BM>(   Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/part_move_mask.bmp000066400000000000000000000003001250202676700246010ustar00rootroot00000000000000BM>(   πfritzing-app-0.9.2b/resources/images/cursor/rotate.bmp000066400000000000000000000003001250202676700230700ustar00rootroot00000000000000BM>(   @@@@1~0fritzing-app-0.9.2b/resources/images/cursor/rotate_mask.bmp000066400000000000000000000003001250202676700241030ustar00rootroot00000000000000BM>(   @9~8fritzing-app-0.9.2b/resources/images/cursor/rubberband_move.bmp000066400000000000000000000003001250202676700247260ustar00rootroot00000000000000BM>(   $$Fl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/rubberband_move_mask.bmp000066400000000000000000000003001250202676700257410ustar00rootroot00000000000000BM>(   ..τfritzing-app-0.9.2b/resources/images/cursor/scale.bmp000066400000000000000000000002761250202676700226750ustar00rootroot00000000000000BM>(   ??fritzing-app-0.9.2b/resources/images/cursor/scale_mask.bmp000066400000000000000000000003001250202676700236740ustar00rootroot00000000000000BM>(   ???????πfritzing-app-0.9.2b/resources/images/cursor/spot_face_cutter.bmp000066400000000000000000000003001250202676700251230ustar00rootroot00000000000000BM>(   xFl|~|xp`@fritzing-app-0.9.2b/resources/images/cursor/spot_face_cutter_mask.bmp000066400000000000000000000003001250202676700261360ustar00rootroot00000000000000BM>(   πfritzing-app-0.9.2b/resources/images/dot.png000066400000000000000000000005001250202676700210530ustar00rootroot00000000000000PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<IDATxb``IX   @hUfZn#Y@q:y埿bX~/rƪ j l0G,$@=In=y8{ÁKOf9!UHL$8`#[ 1Zj;@ۗ8 48,HrhP>v5A IHYȆC UQ< F( 9]I߬2IENDB`fritzing-app-0.9.2b/resources/images/fritzing_icon.icns000066400000000000000000001266631250202676700233240ustar00rootroot00000000000000icnsTOC hics#Hics8is32ds8mkICN#icl8il322l8mkit32Nt8mk@ic08 ic09/ics#Hics8@@@@@@@@@@@@@@@@@@@@@@@@AA@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@A99A@@@@@@@@@@@9@@@@@@@@@@@9@@@@@@@@@@@A9:A@@@@@@@@@@@@9:@@@@@@@@@@@@@@@@@@@@@@@@@:]@@@@@@@@@@@@@@@@@@@@@@@@@@@:@@@@@@@@@@@@@@@A@@@@@@@@is32dՈՆԈՉۈփ߅؃Åĝ2.**+2.[120D׬12)c_(.2,~ާ02-i‰12'`T&2+cW,21302/O]D0215ޭ2316N413.-+-.""N!"6ԥ!"WS"tܠ "] "TF"WI"!# "AR6 "!%ܦ"!"#!&@$!#s8mkICN#icl8@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AAAAA@@@@@@@@@@@@@@@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A9999@@@@@@@@@@@@@@@@@@@@@@@A9A@@@@@@@@@@@@@@@@@@@@@@@@@@A9A@@@@@@@@@@@@@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A9A@@@@@@@@@@@@@@@@@@@@@@@@@@A9@@@@@@@@@@@@@@@@@@@@@@@@@@@A9@@@@@@@@@@@@@@@@@@@@@@@@@@@A9A@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@9]@@@@@@@@@@@@@@@@@@@@@@@@@9+މ:@@@@@@@@@@@@@@@@@@@@@@@@:+@@@@@@@@@@@@@@@@@@@@@@@@@@9@@@@@@@@@@@@@@@@@@@@@@@@@@@:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@AA@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeil322ՂՕՓד ٓҀՓՓ ՑՒۖՖԗԗԖזՔ qՓ AVՓוՖ՘Ռ֝םϝ2/*)-2,K\/2,g612/E312 *wssm@02)"+02 0+&u'--2 0JLL2120%u&/2)x*2)x*2&s(2.E60217-2 ,hCaG/2 *vQ.2 /N712,d,2-XJ,2.)*/20 ""=O"[&!"7#!" wmhhb1 " t " j" -Ža"g !" C" /=?>!!" j"m"m"h"7' "!'" ]8V9" lD" @'!"{X"K{<"" l8mkit32N֢րՉՋވՂ҅ހރւӅ߆hIEJmЅLFKEPӅjFKEsJKJN߄FKGфڄKJOoEKDySDJKJDX܅ކvOIP{܅ Ԁ֥222222222222222210.,+*+.12.*1AVgrz{pV8*02/,Qܒ<.2+GC/21*n,21,D/21,`,2*g,2+db-20<ݛG/2*-20?E/2*u?.2*ày\<*0214׈r,)*+-020F'2-[712+p*2*)2)*2)~*2)~*2)~*2)~*20,*) y!)*,121*?j҈ͬe:+1204܁01210,2,lV.2+)20͡*212ԡ*2.š*2*}*2.M=02,o],2,MғC,2.*6IZ`XY`XG3*/21/-#{$-/12)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2)~*2'z)2,31-2*\ҊU*2*yp*2*yn*2,\R-216Ӓ212*u+215׆ů012-_7 =T.2* Ņ*2+9 E*210ʄՄ,211̈́  ,210Ʉ؄,2+@N*2*"х*2-[IPхP.213цۇ/2*zm+212ɒ/2-RI.2+ka+2+ja+2+OI+2-1rl/.21+0Qù}N.+12.**,.,)*.22222222222222"""""""""""""""""! !"!3I[gpeI( "Dى-"85"!b"!}5"!S"z["XU" -ڛ8"" 06"kߓ0"{oP,"!$Ԉg "8z"N'!"e"u"x"s"t"t"t" ~n "!/^ψɦY*!" $w !"! "aH""! ɡ"!"С""r"?/ "dQ"?Ί4" &;MTSSKMSK8#"!p!"t"t"t"t"t"t"t"t"t"t"t"t"t"t"t"t"t"t"p"#!"OϊH"oe"oc"OD"!'В"!"yj"!%Ԇª !"S,3G" z"+8"! ƄŅ҄"!!Ʉ"! ńՄ"4B"΅v"O@ GͅC"!#͆؇"pb"!#Œ"D;"`U"_U"A;"!g`"! Cvs@!" !"""""""""""""" t8mk@ic08 PNG  IHDR\rf$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+IDATx ՕO~ޠYvA[%h܍;97&%%%lj`#N͸E#.((*4KC/4~ۜS j^U~Qr~_˽\c !@$Vh · 1!&a:@p @ @B| b; · 1!&a:@p @ @B| b; · 1!&a:@p @ @B| b; · 1!&a:@p @ DCl;Lϖ@&Mċg2͕ "RצK_ɝI')"g"AdD)-Hq k [)JYx6 ܪ1B~9 &! G±pX*j؇b)ZSGR">#EEdɭ;Xs(Tw7Z7RߗSwGߴwdbRe\fHlfdRɁc(6OygArS u-xڟC,yD GATP JrSr 9d_ W(nW9Sk`5xW\Ŵ榫)a=D!vCAȞǩp\^w 9eb/[ 5x eRI-V7M~w~r4OhsT=rY 1~@7H.=ƫ4Q:]p@[b[ wBq/ڛ9YϮ"$+)\qyWP^N~$WHS)75pWPo󲑊U8faa^)ȍ yGrZv|Ej[_P@ M=:HιɶVsdEi˼W(WxDRC'l?ٺﭥtW{)9eܴmWXLPrd|O1 $Z<]-M7YW˨wF=㓿H  j'+ɤQ R;o:l. pњv[S|jE(tb P3EX0lgo :йv, BG:`N@@Br  @7 Hx3y1J/+B_2i姰X-;𪁁GZZ *ăyVYe FE{qO'Cҗ[B0zOXSz`O\PX|>`q$hȠP(?qFN hYO=vcg'9S/(.ΦK֧O|d Ǭ@ZP6'$7o\kI-O | z._s)$5#?O\`.:B"eT9\1K'OppS{𕟯9x+`_o ) SqIT15PA0?գ+>%ٿz|@]oϣDɔ>@pM;-'$RZFeSb j8F^j5_PAyŎ*Rj}bPx lD)~!a]|ǸeRYQIsweHmLɎ"R@&YCۈ\$w_n~W(㡽B&ά @F[O>M){,Y ]T:w#ڸ}̐!ƕ0g 6! `>3m@q%  !hC+a' 9@@m\ C@>}fhJ @3CІ@WO`r6 ڸ}̐!ƕ0g 6! `>3m@q%  !hC+a' 9@@m\ C@>}fhJ @3CІ@WO`r6 ڸ}̐!ƕ0g 6! `>3m@q%  y#JQz3qLzPA/vmI&CxEkj暟PAEŮQ`d{"6b0Mn8,] W}0hskpxjٵ%P3{2QRg  })њ:g4s<: 5v7i 'cNQ~5y*1̤{S&țv!j@ptTtm_ *9*ˍEN?j$nT2}" j儊G|0/Om,HwK4 lO~~jqTʏ=/(؀r?켋STZy/J`Mn j^ |S?BR61dA`m F}<7nJ٥!Ei;hܗI&ܪ@x! O@PYPܽ=n%]ǜwRtۖ0ϳ=$.4?3WE_1}Ҵb) E%QpؑtcϽ'+|9K10ȃexɞߚG|c>M$3xݬ^&/Gs(ALN6@]>o_nfk~@=);T:,u#{w_K.|4BQ[ r =< AV6_C}xg_(_bvoVB P ^CA?όNrDpf+9na_ͫQ{'(݊m}bZoZɁIW˟1cx(j2@Hߊ@Dk.Esy$A%._xeT1eJzWz$+@ A @@BdV VdB@'D"" 8&l0@`; N `E`EA  !p2L++2! a"XXv@ A @@BdV VdB@'D"" 8&l`& DW~hO pKF@FlО^jb l'0 @`hOa XXО@{@&f= =. `M`{@@{] A  ڻ55 @w1 kk6hb l'0 @`hOa XXО@{@&f= =. `M`{@@{] Ac"/̑C IENDB`ic09/ۉPNG  IHDRx$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl++jIDATx}'ᇃeZ"UA`T\5j)JauRᤚU(U^/-JkpB49esjUҊ95$"L,}%1ػg3zvLwf=Ul, @@UgVUb  @E@**l  @` @ 6] @@ @  d  @@@MW2 @B¦+ PPaӕLP@J&@}T( Tt% @>@**l  @` @ 6] @@ @  d  @@@MW2 @B¦+ PPaӕLP@J&@}T( Tt% @>@**l  @` @ 6] @@ @  d  @@@MW2 @B¦+ PPaӕLP@J&@}T( Tt% @>@**l  @` @ 6] @@ @  d  @@@MW2 @B¦+ PPaӕLP@J&@}T(pv5+m֬''{xcS㏍ &=$V n|:yL+3gk_z?|9? _xV`gjEV($/͆;v\qjtG'R:  hL+^o}Ca W-~:;p_j^w@d rw̍@FJ753kז> tGj @TC,No)~s)#sw4kO ߲Vh5`6I]@hEWΧ]uo} _(J ]׿U؈I$XD$]0 ld~]nl$YD"tt$^`WgMc'™0 5v]E vUK{2,@ ]v}W`0҃zؔMhZi|@|tOie˸Ο-B`H`H}&0@zyj'0n; ,={ǔc-]kH+@ͨp*@MWx|53w[@[Q }nע 3K(*,@&p6X[@-l|S 8O 7^3 MTΪ"ڨ!m1)Mo/ @ S(n s+V'hK( u5Hv?lL@9@9TI _@#@`duP:zJ]0fv]#}+ ~tP+{h`~EsRCZ[?x-0|O{O?Yo*T@k<{s Mo,\/ҩ Z3AG700-W.w`aT?0(*N캮=H7c, & Fo5 l嶚WD@`P`P~Q }ʟjӍG?tb nu lq_;#sw`x`AE_Q×)50`XE__o[\`\Y7aZa" q.חu꿝wzzzS,u 8U ;d~}r55h~{ي\ u!?6տ@D bW̩8]@?}# 酙,͝{_j^<'}m!0` ]2Q u 3tOӫA=DV@@ALq3u>~s7{-. ^dz5?Jɟŵ% % (PrHhnxs{;oHK\gp/jF@ B`;lmWYɪlpƶP@igxVzI\R7Nˮ7Nr~@L f_̪Rk^S*OL>B@Y@YTM u[ڧrd7o+ m]}u{`0A@%\x{0M12Μ9oԅ,}ͨ0yZV 0g!@\ުl@>7}̭rr{g,~;>o@J&@ ְ,=s'2`eN~6C^[J O?TSPC+q7vL0PL0ρ TmbX6츦I`eW4Lv`؞vKn{훏o~22(V!BAZΚ &!ƺm3Ç>F:a wX}\?.6{615 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@15 K@%k\ X@S#@\%@1q lq8'YsY3獺'@gj1?AOΧT /7?|9]پOH6δW칵<{sIu45l^{F4 Q(0Q 캶hO?e0Hsdҙ eeQ= W}u][nsdfape::4P-ZجۺO}7?{' xzf \w_6M33J.ur*՗΂\o 0N`}3L^n}C[Άp+3$˭A.J}HgFrtC?;p \KL(;B3+"`W!`f~Rmn7 - -n{ҝM)[$ЗЗB ]˞U0r 4_ рt%=-1m!@ /fճ@:e!?ݢ3h5(.?oƤ*-ČzrmnZh^%g34l@6ZA `ϭchHl!@ fӳ@:o/0:3U % ޯ_G/m̖8pZ"?P@:-~;n&oa!@ fѳ@z>Oxm,V,@d_ {RH`9`9: 0X$]W÷Y{``?J2m :}.ןc;##c,8U^@zg~yl{?4ߟ?^]+_UK7falJJZN)3գ/5|ʟa`ܜ_}承_Fofoj]ߋ?r /G(VWmF?M:uI|ɟ/4?͒ gsw6G?4M~5 pp~m\w&/sSSgYO]/~M QtB00ڳ@_{_PieOdN3L] m&@U@h6\3d9_盳mG>Ԥ#.vBi[tYĻ?h^)Կy&`Îᬗm0it%ggmB@B6{Xm,];9o%]Hg"-D1\ #a5a&ߺ;ZT1_gh=RA 5tXwt#;ܳa0g &-mswO+c~O"x_4vF* q2H7S_{z6O+"0~`=TH`?o[)ǣpX !ˮ3ߍ#,Ll!@__o[Y =(’I|y",~*`b>7b(KL.~v 5 &%PPU;~oMr컪  @r@ PPgUݳH[\~ ŵTA6w~i5^|Iyƶ@~C*\]!eR€Ǟ[?y;WO^_Q.M{@.~WW aj_xl<_bN?^x9Y35+΄V1'~~1zIʟoC= /yϞ'|@N]c:fͫ 0 C8@zWɷ d2>@:D0Xټ/ lTV, "=[H 7[&@`Q@#T'ptr{۸- 6/jx?0/)Y^@f0@:pT ۆF@8 o+`oo㘅~mS^tiqzꟇcm+V* T) inZmjՊ+swUSbigZu|4`/^*. `52ii~'v#sw= t" th&bt#N{_7F!C@ȡjQ SL/.zG#) 5ҁMӵ-]J3PQ G kkY:YR* mccH!3W׭t(Vg ) oۡY!`e-J;)VD"t fS'j&%N@&枀廒长)/c-@[t){nn; 'Q j)"T[HEYNrm ҩgnI3!>ܧ_E EUQ+t #g@ҙ 8U* 0Y35칵<{0a)=`m\ ;ir[.eI]/ pB@8a+S l}CerF`mS5[%!mYX - M  K]u?xG#kG%;4 cyZ ]H! Xג2aɟ_@+X )y`zwЯ|T>v 93@W7.~HOg R'0 `m2R8s]Ѥg ,-f-@  @d.j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y@(j#@-@  @d-0V @6 " XMJJ @@c5(Y^r}j#@8GeV @% PrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ  @@@UhZ`&@% %wWm @E@h, ] @j PPrwFZ?WWH #IENDB`fritzing-app-0.9.2b/resources/images/fritzing_icon.ico000066400000000000000000000442441250202676700231340ustar00rootroot00000000000000f@@(00$% 3t<hXfF6: d g9liVЛ'*[+ei%>!W8`6RM_7屇[[8y9/E5V)YNΠ}o~O;8Xsr{z7oR@3ky=PCsN`<ҿͫSvVN`>9SV˔ ˕t0@@)h_l}Țq믂wvG;;n9κ T+"KU@ZnNQU9.7xF]}g|{wJ'0knzߵP_ ˔3<~-/`W^57H%?ѧU,H+SFQ٪ ?f/.U'Vb3(+WҧH_}>l7Sx5 VKg0 ̹!=i,6>^q9]1Ѵ4Ub`ە9RAҋ_#GY9C Śåba|YhV*@ 752] t 1 c a\ ŷ}Eڼ ooU4f ͞j~i=!մ~-s i3 f7 Q}A4}k 53-rA[djM?f[OE#O,(g4@Yǚ#g=@Q^!k̡e/*NkvPwyWᐭw91%l_{w~q][+ȝSwg`PO3 %Upb2         @$áw&1.)έʁQƐ'LVr-@ ƙUtcG_L^ E9=V<+/~YX@;2 Ӏ%)wMf ѲR+[A٧cTD +TI}sUkB͚USW'#Ǩ?,H%?X&G3T0k> F`k2[xCr #?/_EN}8*yG,@z}y)߮sݗY@)}Y$eptg)΁4Lq6F3oFQ<ӹ:eXm*,a&Os7wXP|ƽwvjo5?ՙ>~n_}]1}q1aljnbQy X^{a:s]?^>tKRծZ2&= :{rO%ߢ Wڿ҃7LP1?mޤGnfXrV\b[m^-sZ^=oV.4CcYTXeav~/俐^;~X z^TQhΟ֮{;~1G bc/6>x}ܥ=:]}Āc*ea ba3v0lvne@~ K 6jO?gOpL Q82l[QK})2l$B,,@L--qoQ?>~%El}۸[ Oa^~eP"X[6 pCw2V KCl~"3t`r=1vvƽõpYp<=rŽU+>c?kȶm=y/}R=[p(Ck;Jp1aۺnꝽ}u_lvn@1wdASl 5h6Y gGڹhj\MФަbc?Q}Dշsw>A 56stC[1b*F8yKtERzVw,$@Wo+bԽĄa2)I0 jް$G: )uOH$*Sꣴo.!*H} ֞Йa~)pzb)oԢyY0/5կx")-hשEw#ې7SǓJ Uwɿ DNWE=/uut;3a f}fB ٸ*ǩ׼ja̟Gղeׯ~^X33eF D>v"~C%HE.2Rar H֜\espHaO?c R* @@@@@@`[gLWK@@@@@@@tGW?IENDB`(@"26E/>#3@NHUJW'7O[O\s}(8:Hgr)8LKFR|Xcpy Rlw,:jPCQq|%5;I~1@]ikvzN[- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww!t uvopq rsl. mnjk (e fgh i_ `aVbc d[ \VVV]R ^X YVVVVZ I TUVVW (N OPQR ?@ A???B;< =>: 8 96 74 5*+,-./ 0...123( )( )& '$ %! "#        (0`"2.=[gkv2A-==KR_%5HU)8AO*9'7&6#39G*:r}TaJWUa?M$4IVu6D%4@N]h6Eep;J/>}Ze0?K)]OU`:Gt5CKXZf8GJWP]>L*  {|}[,~&x yz"s tuv wl mnop qrh ieejk c deefg ; ]^_` abZ[ \GTUV WXY$Q RS&, -* -* -, -* -* -NO, PDDEFGHI JKK-LM>?@ ABC;< =9: ./0123 455678, -* +'( ) ! "#$$$%&     ( @"25Cw$40@S`#3$3[fN[IW6D*9r|+:mwVbWc'6;JR^KXES0?Ta " ! " > "6789 :;<=./01 2345+, -#$%& '()* ! "    (0"27Es}#3(8$49Gxr|grepeqN[,<Yeit5D,;IVZf]h)8%5R__jJV(7[gP\0?9GwCP&6$ UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTTTTTTTTTTTTTTTTTTTTTTTTS OPQRK8LMNEFGHIJD>?@ABCD:;<=789456456./0123)* +,-$%&%'( !"# ( "23A?M[f}3B#32Aepf<âP)؈/ŕűQ6kń4[i"_]('s=kn}{=g X@ @ @ @P,RVԼ6pf+SZisU45/uʝWo ?7}zbwIP+v{SPTa3zユ{ C]7@[WW CɉΎ 6 bOO >kֈA }9scY[)(ZszM%rL"r{z'_+R<_Ԝ'\*2:{}Vdtg~u=~dT}ױJ czwYԿd;W¶?/#N_Q_';Fbv >{|}?uՙ?W٣V?D@W}GG~˯2wրJgEPaa3!\~h}X|na F1qKO屶hܸ˖R~|i'oDo|^(;W܉n>ꩃQ.7eHPG}υ 8lx+7̌ܶPZ{N^r?<4OPA屶a?)Dh6@?"?1u.oʵ\x?gΐG ɉmZ;(/Tj]?7}Ԫ1*S+lnKR{>@Je@Aɉdc/*_>aIM'oL#>ݹ=y@ @ @ @eψ=@ @ @ t ryIENDB`fritzing-app-0.9.2b/resources/images/fritzing_logo_background.png000066400000000000000000000067371250202676700253620ustar00rootroot00000000000000PNG  IHDR,PtEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp % SIDATxylgַP I/Δ+"@G @ @(9 -wh!@ډ?#ٙyv"B %!aB JHPB„2P SSS*}L/>xL%yF0Qtę,OgйAbX|F:C}|L+l V@^7~@snT|(FrVLA9_L Q@̲/1NȽ>v&9׍vb;3;”5 ~j`@tG>´a-LmS+%pCv%L&1S0Jo/z]5$y=&Ky{ώKA337Nj6B3c'fSB+o6\O_9M"o!3|{,\T2(a̡ ! z^;&}+%ZI'l 益γ<϶RVDeX!Lܟ_rm8) U ai6x,L,I_ń#aƵqS˹O$Eu,8?C*Ư yw0"~Ŷau}^i ` Ƿtznj:F~x1b(n4m9cE۶13= jJo{Xf&Od c;ѡ{+ve^7qc$/S.i)m%J/4& !^z֩Q$,DRاm-N~_h u2^Ǭ5 pGm1e2/͸OzzwᐱB]+:AdE !HhXGO"2~SKNI،]Y߇X@{`ĜcYH$,I;Pmo uSqq6'; [b }-^ 6\a.hrU?v!*hVhR%H2׊It ̡M8g*FN" *x6Ǎ>k]qOIS /$Zjal"*avG aN_X<, wQ˅O`>YandQb\$:濚 ͆$ $Q#`v6;kI,I)nT]c9hNA+ ¤qڴ0Yn,e!Luq_$Ld;h,Z ױ2jF#6W? Ur}::aQ(ra#'jf-/_(=M jb3'X=6r ~qX\ȂhI>^Fe , f2ZdQEƛ8WP| y(9iAO-ӗY:Bَy^8cq.cjLh0W1ʯA-뾆Uq ׵BbD8(JVSX`(Y7iCjyLg",h)M: n'U^{Aoi38q,q*28y 4%9r/ٟTz9[ n^}[ dWmqyD+f\4a1v"cqv$F][弿20!ƽ XU|Vε FП\ڨ?ܻĜjuPH1v0@}~z-zVzr-5ZW'(Ob>U9|яLxUu]ͤ}27=$bʏcD|*+cuiy3'D&Vo mAMwUӱxg<ޗĽGy V91VnJLFbc1HTifK]0[FЫ ,X7$I~jiXB*cc@6Uwo}d}vWc]fZxdvKHZG\0TƢ[ 6(EqWq!a(!.sDpqQB1,ԑB LoJ*HJp>nI!ac9J xeJEd2֐0SVOqW 멻(@, %$L(!aB JHP$PߜBIENDB`fritzing-app-0.9.2b/resources/images/helpImageBreadboard.png000066400000000000000000000126371250202676700241440ustar00rootroot00000000000000PNG  IHDRYYU sRGBbKGD pHYs  tIME 2tEXtCommentCreated with GIMPWIDATxo\G?Uu۷lMMId˒%K#%dֆf,f `S~ڿe l0gd$ق7o!we߾}DQD&8n1r9uaꫯbnn\;wyLT1HBc᫯O[XJܹ,333H)1<v g KmdA)E6E˲fh72x_kLZXZAhB&_-ԉuQ(0Ơun$慍1XՕ'(q14lYꫯrq̱cǸ|2lq6e{N|'D*K3خTVWl7?:gts?33åKi6'Nŋ# =p]۶T*|Wm;1t8]m8do~ۈ8Dp"c<'}M䫧w,hp1OGkܙlrё) ɐfm;]ie)(&4rBja%Թ / L/LB'`;adHpK$N}|k8xeYH)S9G[j2V& ޸ q$7 Z#''c7hRAކ8FNL+`;W~!maI 7:(²,$IBoGBj8 ^ \5"&z!D &d%DMq"&)caBJ9X!ᆮd5AصA_[7Cѓ}` $n#1Om;ď:\r&:Ra$#j~A8BH-DH9Xݳpia-.]aFbA,\C 'A*ј(D%$j10Bl˦= KN~Rx8T;6z[Qmm&I@kZZ׋pSkM" C1H%ya*8"*f3`:#afe!}hcIBT:N:j4u5qCU6zH)YZZ"cѺ`&3!c:6(ٵ`!Ymu2qL"X ~E$c6 c F#RESSS# Z.qAp)~)-ђ1aj#S>cRgzLiVq0 :,|wޡ4`>1rU]l$P)r92R"kΣ9u : t:$kA'Q>}ӧOrD7tKZ`7h Q Fc8|:ʢЉ#"cY8EAݼ *eg7܌AasBІ mމ}MzI)X]%' d#&9[aB),Np#!1QOB1Do͏y !қwwHs~?w{9,(Ddb;"Q=x%g~np#S#63[\.;|wsX/kb?2Th)Iv6eaKֽԻOws=2^%ǝ!zNKVB^#I^n+FfLJaSlQNbIPKJ6]BA@\:_0?a&#!~.qBǏPY _mRrX| ZxJb)Orym~ƠSGR[¯,U+b>Ø.֮7bȇmqBHk9GVwsHӼ5L퇱э>!k+2: ~pKM!KUy5}pD*r]>׻FcY$ȇwYt9/_9g|ˍ~R)=ygiL6z@cuD} j(QH.Gg\%B9 q@;8+6A3ghz[${}4;?#x艉=g/=DJF?)ecCH%#$aahl>S@L<${uX/[ $qȭ7XK,}GMsA*,2MSY||{*ޓJ~(BBIrP~5VXӟ*=+aW++ ~E!*O|CwJ)f fsOAA/,a8NzO?lbY֮/ ' FxH>4!vii4||ZmS9(Gӡ^Rl4Rb[6<`yi8^آ$X,r!ݻٷovׯRjCA^ZPVi7`rޑ,ѕ;;pt)ГN211_ 4r$I㏩T*#hc Fk2Nܮ)CP`rzwqxURqY ssscT*擛7Y]]E:Z{&pyrj}E۷Zm$qBalqN$Nv]U ˲x7ٿ? iw1}bȃ(dYZ~wŴ[2.nu(x׸~ZZJѯriγx|cOdbecL:׳5jaF¼yzySAF~[*9'wĶ->yqB6v/4 n5H8m4UU@˲cbb˲^96V p h4ҋ[Y{|eYTέLjch4<| բRY&#6J)rtLfo /K۶d2=z'$p lvSeNqPnY]TYu^Okijv[V[u/<0a333LNN"@JVnȋr_W ֮8J%&''Y]]<\oXySR %%V$ܿ'ξqde[J!4Z-SSq}ξqd2xYr#Vy[[i'!:e{V/ €l^E^`87txXh!091Ayr0 5KqKbqqN-t8JLMOGQ/ft| np=!祕0nu{a\.CC&N9Ƕ3tdY$68MˌxG6MCD'AH6n RJ0$]Un6}埆s[Ea8p XqQEіuɍ˳mFrǠ/r|snOpUՃ$!I#C=WVVVi>699Np.ڊ6RzjlP.7]x\c0; עlb\.oZo X zܻw7oig<ċVWWq>O>!GR\b{- 7>>juyr LfKnRDTZdя~ďd= 1a7f8jm=nwĊMഺ߾yض/;~^ml޷- glڳb;C~}w= = IbUwkXȀk0/W{ܦQg5ö.IENDB`fritzing-app-0.9.2b/resources/images/helpImagePCB.png000066400000000000000000000001721250202676700225120ustar00rootroot00000000000000PNG  IHDRZtRNS pHYs  IDATxc@>`bEϳ2ݜ;k眝Q4d$ H  $ H  $ 7fu]wø{ UJQ ( R~1_Ƌ0q\r~LVt]]]8x L&֬Y?ixMֆ/ÇF ioE*P(raӦMS fYNGe>%%%AݻO> y@X +Vlٲ%288ǏprMm7o ~NBww7ʐdp};w͛74@AR8qbrM p8a֥i={l63[":˗ڵkXtinؽ{7V\[vqF+7qWJUUz3iQ$ 8Nqx^ T?bdd$vlxhYMc߾}PUH/%nGGGPvŽA]RSlllfjfr8@UUt:sv{nf#Id2y}ˋ#H-ž={8nݺp8 MӰsNc<3ͧ˩jժUόxۧa#';l29rlv/_&>}zqR#DQVVVtE۷'uP LR;RS 4 $ɁVWWo߾tpBogϞnd2޽{X, u^"===% 8p%%%| ζiXWczzzv'A"׮]˭[2M9&Ͳf0imD0 "ic>~(_JZk9s Ng9G*B)A:::!"Os.zzz>"anHԕz 322$(0P,P(^7nfݻ,8Ο?Okk+Z1?~:[tt:Muu5tڗ T*aԕ&1cҥKtww;Ν֭[>t+++~\.*Όı?s/I\˗/s "caa*<ށ={FT"R<~BumhhRA*ڑ} cN>pQ%tiON|kkkqg6$=1/^\5J)]Ƌ/x-yƃ{auuCUٳ~KJǎ#377S(v~F^fggGkMSSl[i12 UzL֬0 ~:mmmhr r92핇~׊s'OfQJyQ.1xJaGR?jjjvh3Ѵ1d _>Fh؀IENDB`fritzing-app-0.9.2b/resources/images/icons/000077500000000000000000000000001250202676700206775ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/images/icons/TabScrollArrowButtonDownNormal.png000066400000000000000000000003361250202676700275040ustar00rootroot00000000000000PNG  IHDR ޜtEXtSoftwareAdobe ImageReadyqe<IDATxb`03g< w!==`BLDhUˀb @ j]2dZGl5~ @#[xbL]2a!,0|$7.bGdE&**X \Vp&fIENDB`fritzing-app-0.9.2b/resources/images/icons/TabScrollArrowButtonRightPressed.png000066400000000000000000000003231250202676700300230ustar00rootroot00000000000000PNG  IHDR /@tEXtSoftwareAdobe ImageReadyqe<uIDATxb` h< 0Ai ) x=Pq?6P_`3`8 QDDRLqXp(Ut#"tAV,  tt#]WBIENDB`fritzing-app-0.9.2b/resources/images/icons/TabScrollArrowButtonUpNormal.png000066400000000000000000000003171250202676700271600ustar00rootroot00000000000000PNG  IHDR ޜtEXtSoftwareAdobe ImageReadyqe<qIDATxb`%9sf?SÈGsZo f uBhtL8I3B&lRX` F<Pƒq`o\%#DaIENDB`fritzing-app-0.9.2b/resources/images/icons/TabScrollArrowButtonUpPressed.png000066400000000000000000000003261250202676700273350ustar00rootroot00000000000000PNG  IHDR ޜtEXtSoftwareAdobe ImageReadyqe<xIDATxb`%ha|jhR7mP:P@l4Z&X^M!36,j%X #(߸Jx IV ![IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetBreadboardActive_icon.png000066400000000000000000000005141250202676700273710ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxT 0@F  @@@@@7 dzMIcT.kK"@ !Qk]"!/G98 x*XtkSJU&R?\0`Ӭ+ډ0?.OluX?{ t8݈,c|y:d%s3Sw` Fn^*/IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetBreadboardHover_icon.png000066400000000000000000000005541250202676700272450ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxT0t%hJ VV6bjhb`Rvϯ{3L4;sGrٻ J9888:m>,  ~Yt <_;|>ROtY$lݖDt4Kg>Qm`} ;58q~2tXT5fYX:}5rI .yt (tR",`Чo`gp/6m%^aNʭ̜IesP;Cj×+ѿ iG,[ßlt/ [`4lAR'W|G+{nã NS9IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetCodeActive_icon.png000066400000000000000000000003061250202676700262150ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<hIDATxb``Q oʑb{ !ϓe x@- b 'R 'r f `H "D2]) |É,*(2|Q0@^c85IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetCodeHover_icon.png000066400000000000000000000004211250202676700260630ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxb``Q 9 X9&R R~<%L$^X4%$ZZpH-qYDMAjbuc P}@BjC "f|Qu'H/̄\D% ':W.NRNF%膏Q0 F }^#IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetCodeInactive_icon.png000066400000000000000000000004171250202676700265470ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxb``Q X9&R R~<%L$^8k֬ 8BiKI4|P TZ㲄 aDnjKٳ/wˁK 9AČO1`dfB."l/@#hPe,9CI#`Q@$0elIENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetPcbActive_icon.png000066400000000000000000000003571250202676700260550ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxb``qI_H%Pj9_π@Ӂ3:tX@ʟar,$ nb塴  n 4ȑLb3SHV:aP`Q@03ukwIENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetPcbHover_icon.png000066400000000000000000000004301250202676700257150ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxb``qI4s*J-`# BY(xP{CqBK zhMM^*7q#I^J | .BL |=e=!pU# oGR]HJ,`%((!-G(D˸)ԏ IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetPcbInactive_icon.png000066400000000000000000000004241250202676700263770ustar00rootroot00000000000000PNG  IHDR$.tEXtSoftwareAdobe ImageReadyqe<IDATxb``qI)J-`# BY(x0k֬rMB=々H`U!T/#P-%oF >5!<@\ "~Auz{ >RC@A᪈Gގ x!h-G(D+EsտMIENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetSchematicActive_icon.png000066400000000000000000000004551250202676700272500ustar00rootroot00000000000000PNG  IHDR$$ZTtEXtSoftwareAdobe ImageReadyqe<IDATx 0iv6MA@6(x&c"yҼk_I((9WA6=zb*jKOLX kثYg o&(`.3{-:M|7 s;RV|_k/&Vai~G㯴-zEQ3 0YUIENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetSchematicHover_icon.png000066400000000000000000000005011250202676700271100ustar00rootroot00000000000000PNG  IHDR$$ZTtEXtSoftwareAdobe ImageReadyqe<IDATx @ExHjZ&v`B.hpdHyϰ3(2 0r6Pz=Gh%S Zz4EI e"7Ў=3<_Rjݡ)%t=<_c|spZW )yg#/kqq@OziZhha0 4z>Nas F5`YIENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetSchematicInactive_icon.png000066400000000000000000000004761250202676700276020ustar00rootroot00000000000000PNG  IHDR$$ZTtEXtSoftwareAdobe ImageReadyqe<IDATx @ :P++ WE;`KM2LFbtoa7yO20 ]BA{4/2Z4j)<ID hh={(򼐿 C3-4@+✛3@OuƐ+yKꄧ< Cx1I4Zi&|' :,5xa O RK|3IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetWelcomeActive_icon.png000066400000000000000000000005001250202676700267320ustar00rootroot00000000000000PNG  IHDR$k/tEXtSoftwareAdobe ImageReadyqe<IDATxb``FR5H9`BA @j>.y& Rg| e H @\l##2z"PtA"' XIX`DĄ(Xak3b5<C)̄΃1de{ 21dٗ^pona@mzx0Z"@'IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetWelcomeHover_icon.png000066400000000000000000000005671250202676700266170ustar00rootroot00000000000000PNG  IHDR$k/tEXtSoftwareAdobe ImageReadyqe<IDATxb``FR54s:),RXH4(H%DA ,} { a= R@,$,M x @l+OL(}hmRP#`fv1'X_I4qb{@7. PCa90?U"$X9XԸ`d&Z# J<@C8%'\RrrqhЃZo  I;Q"IENDB`fritzing-app-0.9.2b/resources/images/icons/TabWidgetWelcomeInactive_icon.png000066400000000000000000000005571250202676700272750ustar00rootroot00000000000000PNG  IHDR$k/tEXtSoftwareAdobe ImageReadyqe<IDATxb``FR59),RXH4(H%DA ,} 5k2z"P#= eH+"R>Gf?T<вR  V0y(}hiRP#`fv1'_={Db_bƦ"0">Mpq PCa90cgg'D JOΝs>}&4ђVm>ZD`x- F+ z0Z"@*FMvIENDB`fritzing-app-0.9.2b/resources/images/icons/Toolbar_Icon_Order.png000066400000000000000000000155311250202676700251170ustar00rootroot00000000000000PNG  IHDR@@iqtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp Toolbar Icons v4 ̇IDATx[ t\y{]$[`% XlŔ&IӜiO,mh9ImӜI6c,rc7˛dْZg3oޙFevNz̛!躎?CCyq_Cw'SyvFUvVEas~H_|G7߇ /|mU,n}Puy.4BBxO텙*Jׯ\ >1k {/ŀ;xЇYL??}މԭ+|^'^*7cusK4jp `Ν3i( Gӵ;I/Ҙ.HZ&EOd4[TQքP2х[7*i<1[\d" Ԡ΀".eYӴ@PU  i-B0p p0$5,0^-#lK,Ɔ/OIQ)>hhN縱T:'}`,C4EpZP\@phFRg!lwi1(V2d Ƌj{x ȱx^_ P+Z=hxЂAwL htOYǭ`8Eȉ4@ʼn/cg7bvA ܥ%S~us~€vٳF6lÇg݋ bzg퉣co'2l 5HUI0*("'֖nJ)h0؉Z5; i{n.7r!sV&qjhp? MH޹* );͈^nnZB!B =j@0ZSTGCF|: UqA^XɃvۭ/x1t *̮%0a{ğ|O[_(oY)*,ƷCg=a/Q\/.ɪ?8È8 ###Ef4KKYp8=J DTyoʕ+Z ~7@grc֭شi-7?3eG͢ Sptq|$kVEY)Cj0:Х@8\6`Bk[ 5;a8B2#`h8{ݥ¡.lB0M- s3Ɗ+xcgD }xop7OԋJ|omu*N?׳q&/)*ÒPj5q(Ȅ乃ևcRP43n:ƹft]z[󿖼q˖'JfΚ`[L ooC@t-Xt?2D4ƤvqmIĐhAd x >g Sh.P^ t :N5#-. ~ʂ ~$|'QW?k}WNj;>dD岬:slj#tlh1vL=+ƉjOO?Sͱvԭ=߇so8vp ׭kA`&'pF\* * vg<: PX3y3{y3 0yPQi!nv'#@Ɠ]Rdy!bu@+f_[0A c^zrk) 8:NLsqN6\ 1~G as!TsX "_ ƾ%rGmG) ~oѲ<]{S'(,w݉oYd l^3O] (M%, W %8 EGM 0!ڃNf ͫoF\.nst ƻoSY^SDW=H}H(G9D/-ENQќ![xJ/T ylF{qَ+l26Ek/|2hsY@Ȑ-7SJ 9E/|j?+2I}2hʻ BF=nbavlEh#uJ<dNU `OZZ_YfYͶ$k ,nl gohc #Cwqb'B2 ,|" F\ ,^ &~Gq"GX|Ҫrlb^;]a78/GiDI Qa'AF|t:}+L q3sxIdZ<2G)Ц)Gb (4/ kb5i"b1yvT.b-s//G09<^Ȩ`!f8* yӄ )2`m G/oFשῦrg1[ȃOX_jx\vA>ιԁfchY#d0O<`|{;}aiQڦe{)7O\SQK˹%h[~L?OCFӉn9mu8 Ts^㮵~lG JRҪ !  xER_/W#n1]3'yW>W9׺ FY!Cqeb6M2CRc:B^^+qen+JgNl$N;$GIV@ F'^_F|WJ뙓֋ zp:ܼyȱ)[̰I\Y$ "8) N#p>8+08&vr(F=טS.ISX"?~e߲=}}w|?ᖅ_pvu)ݨ0ΆТuy;hV}?# C#{'ɫMK}Y.5`cw๥tRy- Y;e]@0X0굗V/6}_a݃S46S8x++jjg -m'Ƚ5!LuPKR"qur&?vڜ(tbޢ9(**"rjN!ă?tĸru5`Dž+9>+! ȴX4o~S՛7>&FZ`Hx֡}M.rԃҚpQ"xp(4iG }}]XPȷfsڞ>ryfTͪZΜ Cׄ[f=̒ Ղt@uJ1CCiw뎢cp@+ #A{ъ N)(p۽-N^X)VO>#"t4k C8}dȶv=o+L͂a]n jLVӃEaj~sCPJ#J\K3#A0pCjF W=`Χʾ%Td18:-QyGmOF@lGB@E>]-}eŴ@qn*F  l#dᔅհD2ur1 /yd},{gf1Kxh Fvr-GJoF̭Am\\u/#dMK{ 6AvPö=<QZ/1&,v?*&~P+"< tkHMPKQI2a0A]t'+p.|){EBxgjT4ǞƷD2&p<72~Qؼ ݐRf?T(Jjb)%H=LྞkX}j."΅pPNVdB~>;s'W|xbʠf,ZT8)uLC21_HEUqQG^4uXw'ޓYf#}eRL!]*(W|gۅЊۗ~YY;m4]GMqF]U WSdL'[:flLKgs#fD3ZCݟYtm+/(T k{;F[b#A%&DsJW`LOP:NM2Tɛy,k{,OlȖGNk_2k+:'[IZMF/ޭȅnyv$S4R6qYoz "W@HY0egs:XW}gߖN`L7ښgq)4OVJWSR sxXaZ2c>fOE} ] ّ !Tx1pW T!|Z N~LPIENDB`fritzing-app-0.9.2b/resources/images/icons/WS-blogLogo.png000066400000000000000000000022501250202676700234770ustar00rootroot00000000000000PNG  IHDRc"tEXtSoftwareAdobe ImageReadyqe<JIDATxY[HQ=Z|^$IB ~4B  !J-," {}0G-0|bzM њ{:w/{ջ`;93>=vI'ؿWx% /^E)N_v{Vfdf.aNEWj,/g{jN4\WZDht"v{LW|)fw)6oŒY󋊡5M/RʠWU7c/2~oM9(GŢyZ}ꡃ vA_^P&jo5 Omxו&~h82'4:PX0@M3$RVx~\soJo=!f@ȔMP;AFk[uSr!f~{{vM<*rLzm.ƌ_\ޣʐ5m!r@<bqT$k hPUf=/#Q51璗 /G FIENDB`fritzing-app-0.9.2b/resources/images/icons/WS-fabLogo.png000066400000000000000000000021341250202676700233050ustar00rootroot00000000000000PNG  IHDR]ltEXtSoftwareAdobe ImageReadyqe<IDATxYKHTQE!& Ҡ \H&r\@MPBžHڤ7A EĈbLS`:b~\3s4x?̽s?{4 ~Anpؚo II,#+DIm.\Nǿ%}KIJmhA?e4fۑ47<(kχǘ@&iJNUWu6rA4H~`Ӵ̴GO{VyM=WDz0$(%5-H<`K&Ģ=>};'ɯ8>%KعC2~)s-(sZY e,!ɶ րw.k,iy &Io;}kiQȩhIRnr:|vN<|68=(K̖`SІu*F|oGT;_xa[͜gVth*>Ccei Q&lWuBvʹJF̑H7/8:)ep6; >̅|DZ=~Kv]`6s촐H_H5kN4]O5c+kGn=K!ăh1l'¹"9'g܈>8;1hEhIY9,H yl"eV8NhXKrB+-)Y NC}ؤAGZHIMUGDVCӱ-i;Qp( :+)]$=Q$ܜ+DKTL6TШѳn7k:dEȔ?= NArS2y;vQ2ʥ\ij {N~aҪ^2 0PyTcC) hWΥme}nz'\.1+sLGuw:26k1G6|E IENDB`fritzing-app-0.9.2b/resources/images/icons/WS-fzz-icon.png000066400000000000000000000004401250202676700234710ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxbdkFJѼ @Q4Lx`_/h JTCٻ`lÂK#9o0k5?o]hQVBQ j΃ 'ZU3#inI=FRC8gSYqhͬR2 j >B`$Ϳ=a-i\g"v ׼})MZ `&=uIENDB`fritzing-app-0.9.2b/resources/images/icons/WS-galleryLogo.png000066400000000000000000000025341250202676700242200ustar00rootroot00000000000000PNG  IHDRsztEXtSoftwareAdobe ImageReadyqe<IDATxY]LqGhNIևM7M* 7q\XV1nb a\E7lJV2TVСsz9kxۻ=y kLK'XX&LUl ;Nٰɴaic1ODMP)QS]mik7Trk5#w~QI=O x1xpi"VTU+\ϲh&Vr.Е21<&9~T"zg/T3mԅϊwG3iw<.S e/T|ε!Q'DB)@w=">p }}."Q*&j/ͣ;6}CM a8RdUh)0(saSiNzɯDsnuuR< 5wEכWLw_Cqs4i ܲȂpR5)i!1n@lSkO'k509hde \.b,$P~F\~+ >gJ"H @a4l Հdll}[z[ٲ6q֣FGG-iM.Bq?s& 10eUd#M< !$< t+`JHSPr1TQQʠ:?1N;9YAl#+sS,1 e1v;VIc.HI9d鯌x<(nҜ?{D,ƄRf 6_Ky41P'OY# LyNs;"dPV+ _y0mPbl7'Cޒ#>'|4F Yn#s#Cdh/R&s,jP3 uY>J*"YɈ!]Z\y y2MC 0 2|~+8 Ey K)6cQCF3 9 *6DdABIENDB`fritzing-app-0.9.2b/resources/images/icons/WS-open-icon.png000066400000000000000000000004311250202676700236210ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxb`(.X,h@IjzCCC*AA 3o߾͐USgg''''8m`A@4<9{˗ :UWWMCPPXA4k֬ @΃O,-- A` mm I7,CH'%i8` xTIENDB`fritzing-app-0.9.2b/resources/images/icons/WS-shopLogo.png000066400000000000000000000023071250202676700235300ustar00rootroot00000000000000PNG  IHDRf2tEXtSoftwareAdobe ImageReadyqe<iIDATxYMHTQ8jI6e( ?ABAbJZUb*2j*ڦZ?`j3Λ738oL9py{Ϝ[։t f[XD(0Q5WLq̔mXdߟc6dnm Vwt25mAok-Jj^)'8|TKuek*5aSA@ =M_j1==3:`lP l>K冀WS+4 SmOTݑ 2d6uVjC_zc'hf8u #RdJ>EiT`H%g9/ng1UQq*a>O>}e*0c~6P1oBS]!E cu>ꣵg(*p` ́80̅N 0h N|B|A@ӄ< wo)l cw%4A;*+= OS#M|9.OȁeA. 02szP$dPD@ZN@ n'Ù3* 5 o@&7K ƓG>1<sNcdP Ppn 0dURTO0SG޼LY5qA .>0GC["//v@qZ3QD7[h``6 T~GO`w%5{2Pk~+`@wQd׃.^s5peR9]֋Hm5+4Z>rH?_@Qv(+[/#gQ2}ګ\OrC  "]6Eg ei.ӡ(  k+9p#CDD"*'kr0v8ѯԱ~$G>E+ceIENDB`fritzing-app-0.9.2b/resources/images/icons/arrowButtonDown.png000066400000000000000000000003361250202676700245650ustar00rootroot00000000000000PNG  IHDR ޜtEXtSoftwareAdobe ImageReadyqe<IDATxb`03g< w!==`BLDhUˀb @ j]2dZGl5~ @#[xbL]2a!,0|$7.bGdE&**X \Vp&fIENDB`fritzing-app-0.9.2b/resources/images/icons/arrowButtonUp.png000066400000000000000000000003171250202676700242410ustar00rootroot00000000000000PNG  IHDR ޜtEXtSoftwareAdobe ImageReadyqe<qIDATxb`%9sf?SÈGsZo f uBhtL8I3B&lRX` F<Pƒq`o\%#DaIENDB`fritzing-app-0.9.2b/resources/images/icons/asterisk.png000066400000000000000000000005131250202676700232310ustar00rootroot00000000000000PNG  IHDR w&sBIT|d pHYs  ~tEXtCreation Time04/22/10#@itEXtSoftwareMacromedia Fireworks 8hxIDATa 0?  8$L9@$tp0$ ~A d4]/ Qܵ4g5;2H&3{ڪ?̻}Po*F-ڬwۂiq]UQMqR)9>#RtD;Üw8`k /*s,IENDB`fritzing-app-0.9.2b/resources/images/icons/check.png000066400000000000000000000002661250202676700224660ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<XIDATxb`6`'&q" .̚5TD3PP$hllٳ)(ilxtE(AR]6(P3&lhIENDB`fritzing-app-0.9.2b/resources/images/icons/checkactive.png000066400000000000000000000002661250202676700236620ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<XIDATxb`6`'$)q".=~ *GQ"H(t`} 4J6q<" )ހ(Ga$LCIENDB`fritzing-app-0.9.2b/resources/images/icons/checkhover.png000066400000000000000000000002621250202676700235260ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<TIDATxb`6`'RMHD&"];~TDPPH 4J6q<"t7{ O0Π $}dIENDB`fritzing-app-0.9.2b/resources/images/icons/combobox-arrow.png000066400000000000000000000002731250202676700243470ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<]IDATxb`0"fΜH P!===q(LL cEj:<2r/Lp h<%A`IENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetCloseHover_icon.png000066400000000000000000000002651250202676700264760ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<WIDATxb` |T X@r 6T (CH$Bl(DS̀jh}3b0uCىP9@ V/SIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetCloseNormal_icon.png000066400000000000000000000055001250202676700266400ustar00rootroot00000000000000PNG  IHDR 2Ͻ pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FkIDATxڌ Oz:FI0+#3@k̀ c"R{Oy*0""Pz0x xnNgt(NIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetClosePressed_icon.png000066400000000000000000000002641250202676700270170ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<VIDATxb` 4s, 9 *vQCr X$B`v P)f@Vl5A@Ⱦd1躡D |))*-sIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetCollapseHover_icon.png000066400000000000000000000004251250202676700271710ustar00rootroot00000000000000PNG  IHDR v4A pHYs   cHRMn's@m1ee'IDATxڤ= 0 ,|ўç2k ї٧HBu$ӟ9j]ΙV !\k硪OBS L;?=n=0hyFD*e!ƸO%D1e `6RJmf>$wn^ef|IX|IENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetCollapseNormal_icon.png000066400000000000000000000004221250202676700273330ustar00rootroot00000000000000PNG  IHDR v4A pHYs   cHRMn's@m1ee'IDATxĒ0 E9I#dl ` gpP  ~%KR˲pK "gRy8瞫܀Rp&]y!nqzk-]}t !lK JW"1f_s&T;mI/ A łIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetCollapsePressed_icon.png000066400000000000000000000004431250202676700275130ustar00rootroot00000000000000PNG  IHDR v4A pHYs   cHRMn's@m1ee'IDATxڤ 0FiPC<L"/ib %)ww?S1F CzGs'༁"  "upLreY=u]dNӄ~2$WU_mP ,<[Y;"r;y*k;̂ 6IENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetEmpty_icon.png000066400000000000000000000005251250202676700255220ustar00rootroot00000000000000PNG  IHDR _sRGBbKGD pHYs  tIME $2vIDAT(ϝ-05 `QXbX4 gE8*̲Sۮ?կ im/˒iL4[(Ո@DR[@D>EY9)ju Mb{A,X$Mj@gA H46'c䇃4aA )=X< /-PIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetFloatNormal_icon.png000066400000000000000000000002731250202676700266420ustar00rootroot00000000000000PNG  IHDR Vu\tEXtSoftwareAdobe ImageReadyqe<]IDATxb` 0"sf͚u Mb{A,X$Mj@gA H46'c䇃4aA )=X< %IIENDB`fritzing-app-0.9.2b/resources/images/icons/dockWidgetFloatPressed_icon.png000066400000000000000000000002731250202676700270170ustar00rootroot00000000000000PNG  IHDR Vu\tEXtSoftwareAdobe ImageReadyqe<]IDATxb` 0"s9~?&RlE= ,&5 糠 LzAl0 L ,L``cIENDB`fritzing-app-0.9.2b/resources/images/icons/fabquote_button_hover.png000066400000000000000000000004541250202676700260140ustar00rootroot00000000000000PNG  IHDR,֦sBIT|d pHYs  ~tEXtSoftwareMacromedia Fireworks 8hxIDATx10/؈FY f\7{8A@hA@hA@hA@hA@hA@hA@hA@hA@hóx8̢A@hA@hCS$IENDB`fritzing-app-0.9.2b/resources/images/icons/fabquote_button_press.png000066400000000000000000000004601250202676700260220ustar00rootroot00000000000000PNG  IHDR,֦sBIT|d pHYs  ~tEXtSoftwareMacromedia Fireworks 8hxIDATxA0 /بF=*&epB|vl4 B 4 B 4 B 4 B 4 B 4 B 4 B 4 B 4 B 0a6A&gIENDB`fritzing-app-0.9.2b/resources/images/icons/fabquote_button_release.png000066400000000000000000000004561250202676700263130ustar00rootroot00000000000000PNG  IHDR,֦sBIT|d pHYs  ~tEXtSoftwareMacromedia Fireworks 8hxIDATx10PTd)Qp;_|k `A@hA@hA@hA@hA@hA@hA@hA@hA@hf B 4 B dIENDB`fritzing-app-0.9.2b/resources/images/icons/noArrow_icon.png000066400000000000000000000001331250202676700240410ustar00rootroot00000000000000PNG  IHDRĉ pHYs+ IDATxc````zWPIENDB`fritzing-app-0.9.2b/resources/images/icons/nocheck.png000066400000000000000000000017601250202676700230230ustar00rootroot00000000000000PNG  IHDR 2ϽtEXtSoftwareAdobe ImageReadyqe<fiTXtXML:com.adobe.xmp & IDATxb` }?`T!^ LbWظIENDB`fritzing-app-0.9.2b/resources/images/icons/noicon.png000066400000000000000000000002061250202676700226700ustar00rootroot00000000000000PNG  IHDR$$htEXtSoftwareAdobe ImageReadyqe<PLTEU~IDATxb``Q@,04>-IENDB`fritzing-app-0.9.2b/resources/images/icons/noteResizeGrip.png000066400000000000000000000002621250202676700243560ustar00rootroot00000000000000PNG  IHDRRWsBIT|d pHYs B4tEXtSoftwareMacromedia Fireworks 8hx)IDATc?MpMnܒ._1%a:`4#A;uj8IENDB`fritzing-app-0.9.2b/resources/images/icons/partsBinCombinedMenuHover_icon.png000066400000000000000000000002471250202676700274740ustar00rootroot00000000000000PNG  IHDR otEXtSoftwareAdobe ImageReadyqe<IIDATxb`OjňbP{ %N*($E,HlG >T{#4_ >`";|lIENDB`fritzing-app-0.9.2b/resources/images/icons/partsBinCombinedMenuPressed_icon.png000066400000000000000000000002471250202676700300160ustar00rootroot00000000000000PNG  IHDR otEXtSoftwareAdobe ImageReadyqe<IIDATxb`&y~gD1=r'"$# @Hн F/0.]IENDB`fritzing-app-0.9.2b/resources/images/icons/partsBinCombinedMenu_icon.png000066400000000000000000000002471250202676700264700ustar00rootroot00000000000000PNG  IHDR otEXtSoftwareAdobe ImageReadyqe<IIDATxb`g͚ňbP{ %N*($E,HlG >T{#4_ >`>E}IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomInEnabled.png000066400000000000000000000005041250202676700263130ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0 $Q`#01bēݠl@YiB-"l8 hHTL@[Fo8:@=0+r T/P`$uuo*).)`|Xpax:[Q:>XVCyrst$?9cqw ,j:o;p|[6K΄gOӘw[1u zV hHG[bA'IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomInFocus.png000066400000000000000000000005111250202676700260360ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxbd@,T= č|o} 2"iLR@ 4q> Oq>/Bd\26d#T>Y@D4 bhbRddS!q jDlN@a z(̏X?0i@`Ȁ HtH4C in:H[a) ]INaH$-m;@Uُb}*4IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomInHorButton.png000066400000000000000000000005041250202676700267050ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0 $Q`#01bēݠl@YiB-"l8 hHTL@[Fo8:@=0+r T/P`$uuo*).)`|Xpax:[Q:>XVCyrst$?9cqw ,j:o;p|[6K΄gOӘw[1u zV hHG[bA'IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomInPressed.png000066400000000000000000000005061250202676700263700ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0?#0NL@ L(ln.y%MPc6Q98S9` 9J@(d; 7܃Pte,8 0<_k5(L +*mhԐ1Ovknu֙'~EM^yo sMSʱ3i*4'c7 6̯nsJ4팣~j߿-az IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomInVerButton.png000066400000000000000000000005041250202676700267110ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0 $Q`#01bēݠl@YiB-"l8 hHTL@[Fo8:@=0+r T/P`$uuo*).)`|Xpax:[Q:>XVCyrst$?9cqw ,j:o;p|[6K΄gOӘw[1u zV hHG[bA'IENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomOutEnabled.png000066400000000000000000000004771250202676700265250ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0,0n(_|& L@ 7Q@GpKK.Mۻ^kLt]b : CpF#` X8{`@W{kuFV*ݺ(ůs΅xVG-ȏv͙ U;7Rx vBs =[TVʪ0>ef*y;QW=yX-^ͱtIENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomOutFocus.png000066400000000000000000000005031250202676700262400ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxbd@,T= č|o} 2"iLR@ 4q> Oq>/Bd\26d#T>Y@D~>[LP?l*d B3AMͩT(Lz4R|@<2"ap) Dg;1ASN>4*x>F@ѵ$MҶԩi\`X-VIENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomOutHorButton.png000066400000000000000000000004771250202676700271170ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0,0n(_|& L@ 7Q@GpKK.Mۻ^kLt]b : CpF#` X8{`@W{kuFV*ݺ(ůs΅xVG-ȏv͙ U;7Rx vBs =[TVʪ0>ef*y;QW=yX-^ͱtIENDB`fritzing-app-0.9.2b/resources/images/icons/partsEditorZoomOutPressed.png000066400000000000000000000005021250202676700265650ustar00rootroot00000000000000PNG  IHDR;֕JtEXtSoftwareAdobe ImageReadyqe<IDATxڜS 0lcqF`@t .@7Q@ـ??^rE_ri޽^Qqڬ 9ں P{?,Z%<`(٬V# $yKLa u%ɅWi ef*y;QW=yX-^ͱtIENDB`fritzing-app-0.9.2b/resources/images/icons/parts_plural_v3_plur.png000066400000000000000000000002061250202676700255650ustar00rootroot00000000000000PNG  IHDR$$htEXtSoftwareAdobe ImageReadyqe<PLTEU~IDATxb``Q@,04>-IENDB`fritzing-app-0.9.2b/resources/images/icons/parts_plural_v3_sing.png000066400000000000000000000002061250202676700255430ustar00rootroot00000000000000PNG  IHDR$$htEXtSoftwareAdobe ImageReadyqe<PLTEU~IDATxb``Q@,04>-IENDB`fritzing-app-0.9.2b/resources/images/icons/searchField.png000066400000000000000000000005151250202676700236170ustar00rootroot00000000000000PNG  IHDRhtEXtSoftwareAdobe ImageReadyqe<IDATxb?2@"u  `(2`oXa@̆M dTjd`bE @ M1IDATxb?1H@},׍r7*U8p(dY @.Eh;IENDB`fritzing-app-0.9.2b/resources/images/icons/segmentedSwitcherXActiveFocus.png000066400000000000000000000016751250202676700273660ustar00rootroot00000000000000PNG  IHDR $tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp &1IDATxb?1H@},׍r7*U8p(dY @.Eh;IENDB`fritzing-app-0.9.2b/resources/images/icons/segmentedSwitcherXActiveFocusHover.png000066400000000000000000000016751250202676700303720ustar00rootroot00000000000000PNG  IHDR $tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp v&1IDATxb?1H@},׍r7*U8p(dY @.Eh;IENDB`fritzing-app-0.9.2b/resources/images/icons/segmentedSwitcherXInactiveDimmed.png000066400000000000000000000016741250202676700300340ustar00rootroot00000000000000PNG  IHDR $tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp /0IDATxb?1H@},n?8pT!q{D+0 ЍIENDB`fritzing-app-0.9.2b/resources/images/icons/segmentedSwitcherXInactiveFocus.png000066400000000000000000000016741250202676700277140ustar00rootroot00000000000000PNG  IHDR $tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp 50IDATxb?1H@},n?8pT!q{D+0 ЍIENDB`fritzing-app-0.9.2b/resources/images/icons/segmentedSwitcherXInactiveFocusHover.png000066400000000000000000000016741250202676700307200ustar00rootroot00000000000000PNG  IHDR $tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp 2m0IDATxb?1H@},ϟ??8pT!q{D+0e ]IENDB`fritzing-app-0.9.2b/resources/images/icons/smalToolarrow-inactive.png000066400000000000000000000003641250202676700260550ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<IDATxbdiQQ@ f-[(g:q~ !WS "/}v:ƖdoϜ ?~ͰnȄ S<|VRR@&xϜa)D[/_୫ 5D7w7ՉIENDB`fritzing-app-0.9.2b/resources/images/icons/smalToolarrow-normal.png000066400000000000000000000003401250202676700255350ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<IDATxbd&y   ~\π2Au,0cӶ`vaS*-ǧ` b A 3P~IENDB`fritzing-app-0.9.2b/resources/images/icons/spinArrowButtonUpNormal.png000066400000000000000000000002541250202676700262440ustar00rootroot00000000000000PNG  IHDR tEXtSoftwareAdobe ImageReadyqe<NIDATxb`9s|&DŽEqc(0)6R_T,@I(fq wIENDB`fritzing-app-0.9.2b/resources/images/icons/spinArrowButtonUpPressed.png000066400000000000000000000002671250202676700264250ustar00rootroot00000000000000PNG  IHDR tEXtSoftwareAdobe ImageReadyqe<YIDATxb`h䘱(NR @l(p?hf=~CPh>"Pf`B؏E1Tl?`O[i`?IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerBDisabled_icon.png000066400000000000000000000004241250202676700277420ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbd LK+R@xbYhHHⳀ\} BD@CFa @z8-G_<.}@<Ґ3C0d*ވ73!Gm9{G S`!D`rQ@ H s&et2 hFyFh# 弹nȞT8IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerBEnabled_icon.png000066400000000000000000000007111250202676700275640ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<kIDATxVAN0wz'^Pz@r\xA ;f6% S!#Dd2ލVY?Xn܁eP{4s,k0e߀w5z 3 iH󀠖\%5 p5S4&[ŚjT Ys40>l0IƢ:19FF^{[0)Ԁ: Ls^A*tS2P!ki=J/ 閽 ҙ}cwa S[ Y=u`ytC#C 0e_RJ !/dtUlR-ĄC;^'(I <˚:OvߗjFWIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerBPressed_icon.png000066400000000000000000000005511250202676700276410ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe< IDATxbd 4s| V@< L@,s@G݇ Ȯ|!:?Ĉ.F Y `!\P(|cbC >JC 6A!DK>:(Q'Md-Q@ H s&et2  ]@K} BQa5FF F> _RGf@ň*C)n7Ԡ}GMQjIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerDisabled_icon.png000066400000000000000000000004241250202676700276400ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbd LK+R@xbYhHHⳀ\} BD@CFa @z8-G_<.}@<Ґ3C0d*ވ73!Gm9{G S`!D`rQ@ H s&et2 hFyFh# 弹nȞT8IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerEnabled_icon.png000066400000000000000000000004611250202676700274640ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxb` @ 5A@}9PD8=FFFF٠z qh(/~ 9 #K@XpPHR@v=TrsT>TLS d2r~Q0 HX ɁbvЇ42 6Fy0!6Z4IDIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerPressed_icon.png000066400000000000000000000004451250202676700275410ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbd 4s| V@< L@,s@G݇ Ȯ|!:?Ĉ.F Y `!\P(|cbC >JC 6A!DK>:(Q'Md-Q@ H s&et2 hFyFh# 4` >IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerTDisabled_icon.png000066400000000000000000000005601250202676700277650ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxV 0㿎n?N L@tF`6GIc"O/!z}uzE1-5n,1`ʼUf= ]h{h> |39ԑcќ?4 0|͔ CM'CMyL %t%J468F5Ҙ2"H$iA0)?j|u :IJӐ2 iJ/! 1jSA:һohlX}gygy`b8IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerTEnabled_icon.png000066400000000000000000000007321250202676700276110ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<|IDATxVAN0t*=O(?H^@x̡́s /? ? wLY#jb 2(q&kw 1f~h`nECǐztc;S[<`E 3R5 d<+P3Y؄C;p vx)!JK$R_/ϔ:1O}#FtU>K򜸾3Qn<##<ڀd!cIYRz45JV1|Z!%&}fX4tނҺؖYaQ1.IC}M91;U6m$/6NMtÙ: L贳ԽD'wP3dMS>s![j#IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarActiveLayerTPressed_icon.png000066400000000000000000000005611250202676700276640ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxb` ]@K} B0@J BE1!CKS C2Q@"M?SX&F(Y#3%Ɖ\B+}D *.B QNP[Q!4'WQ Ft1b6}b5@>E1э<( )\UP!DK>:(Q'Md-@MQCIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAdHocPartDisabled_icon.png000066400000000000000000000034741250202676700272450ustar00rootroot00000000000000PNG  IHDR szz pHYs   cHRMn's@m1ee'IDATxė]hY}3LMd6,R۽" z^݊xqqAZEXւJ k/,$-$%)i4M̤c>ߙ=Nj&i[l/9GXk68s~Iu?`m <<8k2:4d2 lm5GD;;;?|;=JG"Z k_ ;  lyL}Lg:bDQTPU(ܝ[%6P{t><9 BZT-R* q5{8b/Bb+<J,|\X6mjg*'jD}IjO^K**$rF҉1[~OLLw#j?JWiT^wD&(A3S@I/300!ħ<1dcB $ߞt5NDR ~T@)gmZ.%|B1B)@4Tr ?zQB:>$۷uZ>Z TH+xK8,ZR+4S1d2GkZEOk8KKKHb~A2eU(!ܐDH|@ytqm39B x:>BH)<\e``MDkcJRP +%#B k헁7eWWKB#;Cb% P(luFSRf_W fB:mg}HPxO"(( wh4X__߮Mv0JBZVlYi@*<(z{{|KjtW|ߟFP-"7Xaf%O^|ܺZy[ݻG$T*8GKT"r9\^^ssgv#FI$ fggȑ#Q*pSSSh9vX:ؿ%}Q⿕U1pFFFZ1)%lv5?ZVk=hu)ketttpxxxu]VVVքz]<>}~, VK)oLLLfyf&&&.[d}}}R7n|W){ĉדo^B,,,`7իWY__ѣc8p;w\<3X, T_P(sMh_J,..[8O !Jr2TJ>n͹Ç')c[L&s@xŋz[E`W\iݷaƘFjʸj@#OR9SiίLOO_Kӿ;`_(6+Et[_梦ٷ@+ՏӬlΝx3J=Ų1ȿ?@%˵[uY^^Tg@XV[5 Uk`Q)IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAdHocPartPressed_icon.png000066400000000000000000000034271250202676700271410ustar00rootroot00000000000000PNG  IHDR szz pHYs   cHRMn's@m1ee'IDATxė_lWΝfqgcj)$h#<  T< 4(B<""T4O!(ie'N`?4x޵ǻ;;;]IִFJW3s|aiy뺏{%Ԁ1}6"6?J|}/`w~&N?}#R'#7[ZgjEcex5]?+ =#dC}XX$%86G#G;V˥83(yub p8oT(eXu:ԑD"AŔUO~y^[Mb_JOyυK@Ojg-,]rZ ȖdQc=ɀJgTHxȺ-U lBcb؇^QFc*_q7/mb*СZFE0V뾓<. (k.~e;N Z:VP0x꽈NooB=>[ٷ:vlA ŭ5NK (J)?C{X,F& L277( 'NtSSS(8uƘx&ؿ$vBVVVZ344(CCC`Akl6/TՕƷ>(k#PAqX^^. !jY|gdd3gC6eaaB2()卉1]]]mmmO?311qy6 wvv޻vڷ0|ɓx^^^ !T*Wy<ϣjJVyΝjwww oJ)Ӗe, 1F4V'?R*L&ֿo߾]?L -..޸|` mJqRW,gff. zUZ hZ2n*r΃>cv<==F&yynnn¦G~֪ixg``x/< ցԶwfẮ===F$䛍gu20 >Z& (/M!3SPIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAdHocPart_icon.png000066400000000000000000000107251250202676700256120ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxė_LT?ܹ8((E dq]0 YY#a6Mӧ֍}"1}ifCQjYw²8gg`3s'k+i/s}~{uuAx+Pp `fkG 7\͑Q eee[*SApoޝ&E a]/++:/ & I}<::: ׹@H=5\ZuE @KF^"lj@F\{T8ڷyp18 D\F[AT՟!@X#{-wb,-.o!(`bf>nkBm7$X`ş ͎"W|D67'|&ж2i䔂c9T`rfEQK2q ւ c[8Oc9{ίk>R(~(kA h`]R7 T.Ȃ xIZnѲoH`iY[[@-/D&466Eݽ{ivs7w~]l@9!({ !*$IMMM{MF#%yB[, >\EUq-O\._ X__TUC6QuQUUG4RxJp3}!jKƀG03g6nUCŽ3Ws!ؾsO]8(4bq@獎xw}+|8$ *lL.䪙ZYY/[ϺXeEd2cϞ=$ E۶IHms >">TUu׮]۝ byyy9rib&ccc+a=%I^HF I8ǁ(UeYUo^!EūDA(eǟ ZZZ8t_vuu- Hm?$ ۶)w,A֭[Afggz$I9ȀmZ(@{{;Ge׮]Foo/Յ8MMM3J}JeOQkI4M:::8u\rq0MI8x`4sgΜ0HTU"[ L&󸽽\uuu.\Hxoߦ7np1$Nb}}}\t)x{Ttʖt]/$)='N8TWSS3uLӼ}P(D" gzzj×/_>L&?+ ɳg~2<<@6 (;w}LFuXťh4:,IRlSUu뺕Y'===_9rh#m X>֬`ݻw>!2Xz?^g1 l6dɄZ[[D?Kl/**UgVg{ggOf?#/3_ ע;0_ S5&2IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAutorouteDisabled_icon.png000066400000000000000000000007431250202676700274230ustar00rootroot00000000000000PNG  IHDR S4tEXtSoftwareAdobe ImageReadyqe<IDATxVm0veAؠBi&(L@'( tY:9vX:) ou"KxɮTȗ pWZ#}w~6 h ʷ  )~M%L/6#3DjX {aGOY0t\RgWmZ2)\Qd|b`A %V k] e_LΚP an>%;G L-Mw`s~wZ@Ӟwwl&[n]wy +WşYb:f m 8P_.,DZ5^i/Ok3ڋ,ƭEW V~>!҃IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAutorouteEnabled_icon.png000066400000000000000000000007451250202676700272500ustar00rootroot00000000000000PNG  IHDR S4tEXtSoftwareAdobe ImageReadyqe<IDATxVMV0N}eޠG u ܠ.sIMi){RB232?1FZ;/qDa!(2C^NϽ;0 \K|@RAۘ'W A л=%z@4 c^QUGy'D)enA}&Ys=hwz&m^kZ#΀Vũ3._6Qͨ1* Xs_ϣ]޲p tN'W dM[,P99Яc{:PqfN,hS5;_ $|sIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarAutoroutePressed_icon.png000066400000000000000000000007701250202676700273210ustar00rootroot00000000000000PNG  IHDR S4tEXtSoftwareAdobe ImageReadyqe<IDATxVKN0MnX k7HOPFun܀fAXgR;R׵4qf0l @k8BMyn8ΛOpZ⹣|]*Í=GE+.a+Pyocr`) {PIsykXSσK~@5 Y ~JY ]dTDĺu bj7(O})>/|h_hk]+KWB5 fn'6,+l.XP0>u~e /"G[R 9P਍PC-EI @'9(|WkRi*Aq9. F"pfԱxD˄(! Zc qifgTxU =G*>(TT"hڙCI<1kB8M裎-vHrb4Ҳ00h IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarDiyEnabled_icon.png000066400000000000000000000005531250202676700260030ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe< IDATxb`# 6`H?f0$H'G( F\*ؑ>,\O[>>@l#-)PsȡK@R? ,x|\kR/@PT,9@RB(t=HK81!E PCAvBvV11 B0zj.K BD}`4M:jQxjzЪ%h@,@6I{ gIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarDiyPressed_icon.png000066400000000000000000000006101250202676700260500ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<*IDATxbd#hR;=:&@ȁu4d>1D0vt=* u CB D1>Q@@ϧ-@:h?2#-I` )(pF롖$Rl+5)Ђ 4TDQ #8`3XeBW@JF-ȱ4г|B*<񂁪fh} r*[KFig4L$Z5SP&QGS ;$91iYMlDS\DfIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarEditPartDisabled_toolbar_icon.png000066400000000000000000000107041250202676700306700ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxڴ]lNBl jJWAݪ@Aڈ>VU%T}ٕXk/h7D@[!JbX 7- !)4pRplOb{<;}maYGi4s=? q(a!BiڻliN"B}o* Ø 躎i !>Zb$R8i. Fmݺu K){bn/ ]4-_r~o%O*)uXsO)l)?9큼ո\OFGGnݺb.,; )%3::5k077+Rec6RJ ðC((88y*XTj躎> e{{;Ϟ=[ y *m۶W'.}JqyL not].WX700F27 :K x8{ذa_J_& (_ROOs93 F@ ༴ {zzƍw!~b ޽{ l۶ؼ./t)!Ė$#\GzcgXCCht:_9qB%÷H666~(d.;.pǭ[شiXl*)AF;|wȼrQYYRYͶmf1M2FFF4Ċ ïڲy@Ps_זּxzxhnnݽ{7tF,r5!PJ~'B D]0dryA3()׺ ]͛놆~t]\m\;p@ŋ~yG)K!/yϞ=%w2fҏLIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarEditPartEnabled_icon.png000066400000000000000000000110671250202676700267740ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FbIDATxڴ{hT9gcJ!h!J0\tVK/K)HICc/YB1xEZh1&h%jj.Obl21390]c8g>{{WI| }YQUu}}}zuI( |_E4Ms\l6,6Y bAUUVn*$|hH(J8n#I;mJV,s<@UU5o;Zb+cdYh5Ku:::X,^>$IȲ̴iӾ_:wD-L(l6O͞=O(J+bQ$?Ȳid̙Di|B1~x$ k.iݴ%^L!EQHIIѩSf{;0Bpea øvGnjNj39g/\P,]4SKqee6oillL OCC}}}Jo4 xvwi !ކK,˖-D +W,BSVVƖ-[4-rY$t!W1@x=Bi%%I 0#P~~>:.\@CCC.;N<Od~qΝ$C OD,ȲLaa!bƍcF0 㨪:eᩪWHOOaZZS uC#==.N8AsssBvu5{mmmO~m֭<i3 4>>>NOO} 222ɲ˩fdd`XHMM%/)A_|! (`s4QEQЃt4 Box?(ڵki}+Fu!Db" N|ݻ'O" ++Dk066(@qq1UUU8*hbymĊD"D" pŋuEQ4<###9s(((a*++|2_p8<{͚5(@tlln4gϞ!۷oƍA$:礥QQQH8Q^^ܳgO+YVی3FSRR3giB-Z(ζmhmmvLvv6|gMNNzjiiqL;EL~+555455zOB.]2*++esq;wh4 ŋy^"PTT4zskkk24__r\$. 9G~!޽[YUUkiZRRR2 _h:&V:0 ]z%77wӆ 'KaZ#xF;|ޱcGs]]dYѣ%MU@z=>ܙ`yopp-iЀWԇLtt\:;;39Q(޽{ijjݿ?Ph@ Í ev^^^)@CVBor}s̙y.v:D"aϟb̚5믇7@7_UUu[.ŊƀVIԛNүF?[|_Xf7v(ɦ2||@ρr(5Cv]XVi&Gmmy1l6-EQB;>x`vO正ġqz녒$e2UZZ:sZ QIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarExport_diy_icon.png000066400000000000000000000725221250202676700261360ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B4tEXtSoftwareMacromedia Fireworks 8hxprVWxn@g:kJ:NHE*D_/ qA8HC\ !"fvqy-gf?l+?~SV,K,5ֺ^h[.JUQ(/ y^y%KukfPPb9h"'[<_~{wۚ= wkGUasok}lgwʇlL°dM(I9̒1duC@`1Vy03y<;QDo*5f}.`|CeBO—^\@ Mب&q~@?D*MڍM^Kj&oSqDЎ Î0$j:b/@ )}I8<0 0 0 0 0 0 0g=cCwHmkBF)3mkTSx]YwƒƱe[rOü9sb'(X CP$lNjK<<P)ڱq>O64 w<1Fδ>'޴In}*Ztc~}NuzTnw o>1A BCl+Ot\BpiL[f8f{IyuW(a3Fb ll|acL<a8S;r|"-E-`LIip}P18_3>6">qZӘfE˦2hTʠQ4*FM@ɡŸނECM1s] -=#!3L2لŚa7h`Λ^]_>1Pꃼɳese0f10p0w@)6 7|F-*{QV3 ;jʐ$B@$srNa, ϣ mX2!7Z[zE+YU~q:ƳHFT7PQ-b 'R%֭hV=fZszr+WRt ^Gl/M࣯Q"G^hxQ4ԦH~RoURcf ¶lSnj#%򿚿$ ,gZN' q|7ܒ"C42͘; u.{&x1LQ\шa&|̪8rRl|cKg1 a Scxz L,95)Bňu;KIIA ]вZ6ʌ 2ژ~ Gފ1'40 Erb(Ed(2ˆkVI#gY`F+s!<򔭔}Z?ʌBZY{% f4ԃ!a'[=CP".1V' _n)GH(e֬QZh[aD&}nwGυt̺tfBFh[*vš Dي&R|iJϙ< .,~33Ψda}bJ ,13։$EEk8):U]xGΟ!`R 8}xV(8X,كm2k|Ē&]s1|jLdpi6“NC @~N:ׅYȐ{l32XÀyρѫC:}n[^/IL 7&2 ɰ7|=4CQ4q(#xD"O4ot%)IfEEppm!pZy>)~ϴU1mTBfOOXIp2 y_24|qjh-Rc+#ޠOaRT,OAXb( D@rІ4u6&ɇz'1VBhqMF;, ټfkXe 8In  qn;=.Cq!aG`1n&aY&Nb蕀Ж*KZ̐׹RiPF͇oq+|cnԪJR4Vs~-B b YP2!nBdSbk42Df A04Ԑa;rss& 7m6"Z3#݄Q63_GRzZUWKXf%Vr{'v RdI[)dK2_0F"錻Al ;ͩ&9Iά%We,2 \Qx"KsN s+vմZeD:n6bjx˶Cߌ73wN(]iVY k8GIi%M`2mk@M}a:w.` 1hcY5bꞗaʦxe. ~к~ȡsfڲmjoS:ך o֞] SZkeRyzȨ/m3S؜讶}T)J9{ηGzSfηϺ@ 'hѴl6UoE%ݪb} 0Mis-j8К3 "gpUas&Od_.) քY`Q#M菂E&;K[&(#zUOHɵA \ie(|UR5En"d[jP&3o ()Wݮ{3i⯗*mF@/w~^#8k%=(m~+A?G_sXjT֠MOݘQ+uCQg>\)ag?&/]MtMCkv@ыh,ŸѦޒ utetbEvy{&e8!b5*ja|CX4G OcgQRscUpm+\s}B{p1@r<;ܟ?vpK߆ ٕ ?Z#ߣ17ipII e_{Z2-4*S3!+^])k$wH #/4N砻@A'?҈cqf;>DG1݊q.QtvQۚkv^:;[5;\svވcf蚡v5C ]]7^3tKghkkfhCfh~>%(֜]s9[9욳 pCٿFO5G/͚k9D#5C t6jf舡%Mfi5;v3jvy`o#fu]5;ao/fu]5Cao'fu]5Ca:u]5go1u]5G||;w5C3jzm8 ?&eghMղTLu: 3Yez)pC,k$͑ `DB}JJY UtPkNi]CoD ׶\0 v36EŸ뉊X'Zg&CоC cBfh׬f蚡XbOa.G?MHq(y"ftT8{>`&BmsDkX ygLv{L7+r^-Ok P ;g]C ߯I[;q{'0w$=Pgy6#hUВŔ,nhcni@5!/ -D~%:"eRE&֭Vt)t rWu+ق{dzvQ_&/R+B$5pF~deQq╲=0OHyڣ爑9"!OyDg-L^'kc O{"b& ވTedh=bh15;\swwbfUhVeܹYI{1ͅ.{]tۿ}͊nY(~qEss6zG.>_K+Cפ%.FۇwNۋ?&YgR>: Wӹъ'Uuie=_q {HfRڧȵGM!%!hm2+G\WŒ~5aϑLlֽQyYc2ǽ壘;Ēl]egTA$w>:[RiX GU4x<4ccpOTA:@PkZS,h9UHhUd(Р. ތ"Oy^gl3cQq簟xNlZ\G?B^gk[k^H!βlNW*Mwy Xٕ8p /,G=_,i 33vҚz">A"&<&E#< ]4 4!ׄ#'5A|%u̫ 'gh¦o2MsqA@ B {| xgsU%|y!ɶ/qwwV>X'0ӌؾ􌯱Vž[i>fyZMbFJuI)?a5[QbUd"3Ѽ/Dfւ7tI1ɻY9KB 0m6f5mDRl>AގgۢIa/8#^u/7bIz5/Wؾdx}jǯ|a2wzo%Si Wi>mvqk2꽆_^CGо>cׄƯzc{}5\qqlS?aǪ̾ZaG|=0l ɞ.>/=Ρ ]Ĩs~BY@Ig.8ڶn)!Ed$uVu hݯ: լר ?RgW[3|64p.ב" :dG4Y|ڡx|ڦ<V7n>J7Emu|ߵfHVj]S!O}'O>އU'X+lmÅ^'ѷK,piTѠm;Z|ҽ]DG.dLZ;Ix6L;ϴՍ$A7J[q&@ F.6zpܣ(pze{DT1m::BiݥչT`%;I+zttIӞ-:gw!G~8*u> o>1A  frXif ǫa`cuFtJYqŴֺ߃i#"/o&pNywz?h'`h?,Fݳͤs.ROۤ]›t d{ ;C߶Tp ㉅˾us<(w>Ev clܞ{S,ڬ8tI;^bg_Хo}R~2|O*)wz֡&Q=\YTrs7PG~'+TXS**vwoӈw_ñPyt i(/=Oo)帝-S *!]K<{xzu8;$V$)\thNRa6H :{:t$4yh`bhC6Qfc zt׾읜!8{'paCmhk/JU|Go:qpNmR@ qInmkBSx]N0Æ WM- 2*5X|DZ=fLc(F? hҶ BLrGpodgd/e>f 9]WA\\Lf[xilϣTs1H QlHاEt(SAZ_Y X mkBTWx흍8 FSHI!)$FRHnw HYx3ꇤsaaaaxIǏ'U{o_ھgW9 o'GW {>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O- 92b?Tlk%?_21B sY5>:>c=1Ow y^- ڶ,XzusM#גU]>H_yYv!ۉ_mi Rus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, l gX #vQg Bٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'-(W? źvƔOʙRv[K?[A}?-wmՑ}g\=c}M ggg DŽ-B^k_g?F? v0||؎=ǧHPgs/hؑI t~{n^}ZyD5XWvO)"c0vY Z|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8gʱL{? 0 0 _k3>z_\S |<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu l+6v<ï k7]/lc[`On}򚄫 G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ 1Gg{+ҏlw<=}GݽFƨ^)zIpG K֜{{e G12ۭqiumf>.}~a? 0 0 [u+7Svq֭y΅ ?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo 9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3 _[_*mtcmC>qSL=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^U O7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU? 0 0 0 0 0 0 0.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwx b)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-tĒyNAgC \NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`% Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=o G<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy czA;w9zszWHVax3 %mkBT~xilTU#-]( (KQT (!,$h?bbBB[[M1FK$Dli$h "eEjtB(\'L;C$s7e,y9/G VF(cFuI_˗~ W}1?>0g1@$(I75JrRjˤubip *MFcYn\m+5zKuqUn7lyp3gf_펮j1cZj_[5`ւfz*zNo$UY9|ik7ןzvdk֛rq@btW/I|viŪߵ?]*i;.lۡ7`P?YYcyvu6HG{ĴH)j{׀^~yla9{u`B}ãZ?65<*E/ex#Q9QN[ukp2HR@?$M>k~PG?j4cƘ5'ݗ"M Xԁ6<33dAI*EN4k Gm.vL+/NDM JǏ?67I7N ظw=e;<>{ w#^N$fM:u$^sc$~]rb_(lNG 7e>Zz_qϔLy [5AL7\ss?U~_~trFb%J|$yRqUr匴Vo6m|ٰaD--O.+ׯ+**ټysY_\\l圗'[RXXxٓ_k@+-[t~]ۺu+;WqkWo=,o׀wzL4{.:擿x毯hz}p3kwqm1"/}osRvڝ_feeܛ Y -f}@>CϝUҕg% -1M7ۚig՟.zmkBTx흍) q ĉ8D^>׻gI@XjjgiЃ`0 `0 ?ϟ|:seQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/ D:3D&򈼹e^Hyi#/OGzϪ߯_~ :sMe#M3Y#=2 QЙ[\s=E8}E>GȩT ڲTg-}VfoSVwzV}./>~!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-k dW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ: `0 :8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV U?)V>ғ)x|Yҁgi\yi^cUo*= !TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x )/OS yUo2e)Ve3'wgGg=J^`0  ľu kU,Ksؑ5nY,bXw{ w&3QהNQev ]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fzt|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz `0 *\?W8GY:Dgcg< 2+'W6qn؟{ru"wU쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP ~n%hUG4(_sn|W}Tg&x^c,Fѭ+ <#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3 `0Q[ veO\k^8֔v<Zbz\Opbn$~}oz3ј mK vU]^iNWA#x딫jt q :E= z%օq)CcYEqyRG-+u (K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_Eб Vq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7 `0]kIu+eL]ւoA^;=GR?v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{ ?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0 leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR( VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l? `0 `0 `{~i`oLy>uoi\qK|}7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;y`$jwymkBT6x횉m0]HI!)$FR?6c>>~sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/rˆ_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{G}?v✽3X~j{zTAO^ʰ>?sy|G)PU{ ..T}6ڳ-F`p]k߅~b  О$wݓٱ|sCoA+q3lOx@(0a+? T,_7s\Ϙ^Bl1)C+k(FyN"8dPC_9>O0&l4Im+nwGrŰ)/tihf ѸX>E)<,6s45zb?J\<OM%O#(76:= ӋYAƒH Ls6MXBcX&ǘJte. 3.je(??Lj=%wZizFTx$kP8Em jAOހ>~؆B9 ֤8UKCvjbL Cy ;mj P. DkwUE€3ܨ8xUJs\ɟ+;}sFQ(KIXݛƨ 1 +KdX];Jģcx$D׷X`i @l̏rnm$^9΄zBGϞQ=nfkDe; <a>,⢞jk0B[p($Ǡp4 nq`XƓ vϵ.xHnorJ5Hu뇗 f a[Z:>36[g RL؍?( &w.7C#~B{] UW 71jk~ecGrD.=K@WDZM0倐0\xvqNZ ># BE )&yA}t?B Ym(WIpɱ |2+\2 )l8tl@Z.Be񅋍RSƃm>dIl'N adĢG3%#)?$s _5=YBR#-k"qGP-e"f%֩-ϓ378M9ϊ,_*n;HEBƱcl~ ˝[/sagIE2,z1t:kLș壋G){7ond{@rP>kwk׽ #kXfyEAB9uM4P=_lgW؇N#_nGpp ,ZUu6ȓVӰ0EK7*|]{75F\ԶzQz! uH>upT٣o3P)[^6` -d&*=%fY<^ط`_6|h3ء>2 Pq7ώ ,NsjF=B` 큳CiU)R鐏@LҮǧmb<2FHRqùFXi䎲OmGA}:*u f:@ʫRH.66jcGOpO- 6HKJU:Jǃv,3DZEƮqq7p?ȌK%ȧ$;?Qr6pP7`a^=R_)m>D3#£ _' Iɭu͋C-Rne㯄ssL<ȭ/R)|Lt_1Lk=rr 4/gEr~PnB[\g[{gYvRW' {Fem1{ wL;7&$xc0 n&u@5sCCձm8Heft x{q(aтa?Q%l4ςxmWI׆GC1kQ3iJh,KRO`ʲ4)%b6B8\pe;u)ko)#WSncRx{[sXv195_0Kՙ7>Tp5ٴl3S"؝LX睫[5m Q="u}pϘ*xbՉ#iM+@Z! Ϯ~jYݬ$?5mtu] %@݅:4h8ۃtu3; ΑO1A/r R*5i&j#Y2:$Z(ad@>'z L뇶6Z8|`6"X1_z' F-я?X^ A:?1;h/KVB' vOnFS ƤQ{=kh7MwXQp\v͓O/. N3HKRlK"q^Wh1wt h@3e6N|I;y?8t[[! $,ήLe"z%IކAkRl!3u8ځy?_W)AbCO!rza5Sn֗#<43y6"R߃CQ&>[# BHǽ{vekOTlq(UH͵h ݔ8,@tՂL{p/*L"d_y k,4 G̖bD>,.ok"D;|7[.DCA#ilϟI֬Dq]+eE _-- ڰc^Lq1~CCC9gNH8BkhJ#Z-`VoMa 9r$պZ-hkh ?C$ ^tď9d(8P݅]ڶw[wl;dn׆oKd Hބ(DInI M_(5)6H/Y1 QRk,nXHʉ?>df&6^EJmt{CCc`0ʅv5x<\9Yc}106"״!֏9dl:' 1H"z'7QqɌ#KR./CVgQȬ\ `?d1yuM6Ƶ8ZX]8^pwQE &1frRKi$GݜЕh3'{;;~FK37ku<pdʎ+C RMzƏ7)nҀ lEGyl:̑IoBS%|ЕsTulebA}Aʹ10A{KʘӺtjdLI=r PRg_LbR Şl?␔)![Fo wi&k^CV(t@pW2{hxHGRn͉eCbxԉ6GQd27\ثdS=\Ff*0ۣOP5(rZߙxQZ>~GAeN-jY7Ҿn;n?ӹ"Px}/NW:݊&׾:x" ꭥу;R펔 c䛅љElmG§a= h¨BG_uYnZ쫭FYs U"zM&:Gnu.DX5Xn;}ԫ%XO?~2&Frjj8 yA*W I9/ub)Zl: s 85J>~iI3Yԕ;:#hELם[ROd^GA˩f~Y!En0~/A Km>^WYq"<цF*c:xw|͞w%ehRgd9̕v3v Dgh>>?3hYDkgC(ʹƒԕSԜ| 2Q94(?OGQ34 fccPopTYaW(>@tX4`LGٞpɄaŰl\[9c26U M6f,'C4i?W~psϠ?kAKrŵk@I|>^xs?\`,D̒5W^w DMXf_8<%|8_왉pP1Wlm߃f?4:́_Ԕv M;k:p_sj؎qw]$F}y ,b'N=o0, ~M YR46+!}@~ujctCP.Y(x׎z?70WXFܣo3z0c8RGg0 TU򄽻w"/4֏CQ`[{Ocn]+{{ N!33+5]qpj' r9FDȬ)~: 9Gmx2-?sraG"yvUpa;Ră A\& ?#n 0eed~oq嶭!!DzP^H)>oȑ.ļԶ=Hy7S-M ?8ycߧq|#5"2Б lm#UeΤVbM͘jAc7Z ]> 4gb s 2WRsKg6 's8qzTT[R[w)I95xWj #!nN+zPڔ KgTE,?{^RDݥ=Ru^zîc&D'i74SJߔ&HUG[crͦ<׿~4}څh;lpAZ%XZ;tQ?yk1+Ƴu6[ Dc4Ɯ*dB#!}e>samhG3c^8u9󼵕⸈߂UyB;f "Yi=D =4&|C3g]~WgjhSIXU"1A5Fr4{AljwTt6</N \Rta| i>T.Wo>>xϯY{緷m,J{gg}v~)]s!?wXGFl!7U|Cnfﳅ:.@mq%臔Ru?.:aBֺE#Gg'yXDuSWNJD)21ѵVagWPqȒ s?¶@g")s\T{f3go^w:^"{d#!φt},nyWFKv„X4|VB~,˘_&fjp/WԍwaO H 3I`u1ͤ+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_Wݚw)^IDATXŗ_U?眙{s2RI+?&!33zA%%^z)@B7猠"?RDb]w;;3O;3ݻ5apf~Ϝ9#s&Z~`KЯZ6qL68ۅOذuPB L:l20wHscHMxэO<~`0@e$BT<Zk$A넕+o?Q`$R@ >2/1!$r5wvã4:B,xvoeަj&vBR SA f|0' OD;@ 5Vh<. =9e&H)}T"њKWC|ӶS}b)Zq֚%>IvPJR* UG؈c RHV~NY^M+;jC(FGC~eFųxH)sqARF)E`iu@nMm~B1GXp>/ޑ׼9G'|Ql9acw[gviB'J)y^TTj4Oq;̾ K4#阛K\= bAՀ@55 DEIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarExport_gbr_icon.png000066400000000000000000000100701250202676700261110ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FcIDATxė]h\E3snMc_mS?(U( RQA>(*HWEOZQ`!M䦛9>f$vg99 5 0 *DkMEAy8Nc-[U\ 'M -5aU+X/u, X>] 1+֑h 3vC"|"X !$tz{}1-1Y7^6ݕ vX!9!fL4zu56ά_XSv1TeB4R) ԩ3T\zɶ&W @DQDFxG|wgQ @)I*eҒPN<0D ɺǗ,NT>Q"<>RD9R !I"(qi SQS[믆gX5w>gug;M|8 C!40 Zψ9u$qYj>jE;-0fQJ!F)h` , gVs|E^u;JY 6>W ys|dF,{x6XkJ͖r%\UcQ̔͛|LFK?di Op!u TXYn~B)Ņm, xXV* f UkBscurmZZ2R撕0TEnNXx|.H%Ei1ݛJ7FR;z)6< tϝo?ё&ˋ{"bYJ-^UQ`r^1xGh{lWp˦[巣[>4ͤY!{, 03 $" ٻFJIOOxǑ#G줫 1=JXL2###KpO?;w"ĉr-cWWb6mڄeYddoyt:q]wfu 2buf8áCXr%i.:\.$GP`hht:ƍ8}4 كm>|jt>*|˲(JضU*JvZl :;;+_ΗmT*vA__|\M瓽dttjJwwyesF@|T*Fkk+2::J[[r9Q. ߏeYXns211ļ\h><`jhh#qAXaZk^TBh!D p3L5Xn:Nms!m:-곱*0?T^IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarExport_gbx_icon.png000066400000000000000000000100711250202676700261200ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FdIDATxė[lTE3svݖRJ b4b(MŨ/QI_H|1h Dc,<eKB{ݞ=B[Ld;27Gh?U$zs~h p].rߵa>؀Q@\=ZS,:-]豟{uѼFhyY1(Ej}<|cUA2D%nĢ4'sJ!I$]zq j*%eͻB >ah' )AU])a(L3~b-Gm 9+_N#LU?î`?#~~H!R0qaN $J%1]tp\ BҹrH_fei&yh$k'4ހR98 ` ,PJ5$ R$&aD&QaőJoVyE'zhkmņW6Pq&Uڈc2@8!V_|\xaLQJ!F)YTi/bVˬh<7. ٽR WW.{ȤZwqdNJ%>"s&FyA O:>2!/xgZdņ1}d)ʞ׹Uf,@v䲯iȐJ%c6^ 0 B'vд{cZ_)HcQëbW'R)Et+q[5{1Z#ڞ穯4MK300>m8u5*Wpߺ/b|R j[,+rچi@JIK@*t:MPL&C]] |r9}ti(-Z;vl2юZZZlڴFrLV֭[y@^~z9rȤgl… `YlܸbHJd\.={8~8ͤiOWW׌sS eYڊiaY=fr9z{{q'NN'"@w keuQќJpg~fvfZj!"TJa8dȖ:G榨7FxYnNN zp JTIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarExport_jpeg_icon.png000066400000000000000000000100031250202676700262600ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F.IDATxėkTU{[jkkj$I(҇>6AIf~H.J8Ә>}>As.Zk&ʾ 00KSDkMx8v /u;Qv 4LW5Bw=wPkF˲A 0kK<\/^}@ca2"r0C7DL'V|GI<g~Z5BȒj,Ȭ `R!DEWJa ˊC,Xwo>C̒eTr]_ϰIi !RJLĊp=Wqz1{U <_7gG(%L2 EH!imS_Vhei6Xtgo@Qt16%+޿gvS>2RH8R !" ri豠jKG*4T,;go|^ C!8h+b#aʊ;EJYLRn? L_˳^|?C2.Sv<*3.PƔ7iL#9wQtcSy,+-+$o]h9X,%L- u ~Wo٦xA3-ƝqEz-OGˣF?s 8Z65yAk=ev3^Pq<~/Ls43O4yXaH) 0= 1<<̲eB022ӧIRtttDΞ=K.#JF,#p4e Jhmm/ߋj*hiiXڵk~,Ǐg͚5455dRҥKsPL&n }0ML&Ckk+TtPi,B!rIuinn,PlZϧd2I? 'ONdÆ 5 H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxėTU?̮Jk4Y:fRnE?F mHE&E?5PH Yٴ՝quyn9;3nЅ<=sZ6QUV퍞j5ab'󧾼o@ 2D@ښDkMxYuÓZ{HXyY5` tq=Xt?#V$#Q @F fd af|%$IzVd7a`j:!+˚bZ1>\$ ëBLJ) CaY z~}`nY11Uű<痋'_ !RJLJ$|)M|M~>5Ð q]9pW^y>a^RD$Na()Sv] @ o,g~z2ZJ@_̙dPa2BkH(H&-0b$ bz2̌Tߎ MP!]XpۼB` @k=7hVL ҹǎgt-QD)d J,ug6/]ډvCv=RauUw`CDoe_ܺ;܆V:\%\AG94Oyb7A^Oa*EM}d)&PFLX|"=ϮGߦeXV"vY3pN4]z2IS$u , EA[rB7I2o[_ 뭈*،B уi\>چ ro Lkk eTu-_5Nu]r w?oG1k^gff\,ٲ ,0Laa+#}?8GGGtttfÇ@ QK$twwJgg'k׮ ɐN1MիWG[[Lf y\.eY\2ޓfmH&^,bddnD\ gϞOCm;}4 L&mxS7fTΝ;W'7ffhhd2yH>ԑ#G8sL8Z2+"^=idqWr5Fp\.m-[AZkn*!"TJaST)H;NDes{ۢqk귱Jp(F[-IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarExport_png_icon.png000066400000000000000000000100241250202676700261220ustar00rootroot00000000000000PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F?IDATxė[lTE9ݖb -h0H0$@Q_|(Hb Y  !K0XKBZru{C.ۖvg2Gj?E09 sZk0\%qnܶYH4! ,¡&<'sX3O| ,}м>dC 6Ry}}-+wx HG@F fa @I,mS?ZAȼ[Y h|B:' iA%0mMB7qf>ry>}0 !RJLĶ,<ܺ&3e}],30 u}ÿ pZ$eRUPٜAwEeG^F~&K8Nh|y/8.sd{jb ,(PJ51Rb6abƀ @Dx}wuX9C'X^7kvb^< C!$LŦ(7hCPG..?cuBJYn%:%u H͉4a%>2&*|UQ0a͘OM"^bACeG|=>&WcV! +W5EseWX߸8e޵R{#tj سW bÿ/g ʋ^?]u@۫s=z0񤽎 H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxė[h\EM416QkzQU"mb( R#g+`)(xAbV$TCP6qusOe @XaܿG1 <qש /p$w-y5Wyhb}1nH1% "Kgw9T5oڎzR ) J@@Pemm1N5!wUVwtqplu|'RjKg#`q-~p#xȘ7 KsV@'&,>~ RH)3.^I{ym6bYRh>Aswf8h䆕Wف7Og~cf}%7Yc߃Og]?-o7:.| Ŏ"gRWTo`qr={_ώoH崊&n} ˲Z4H) 5= RJִ=ihnn]]glRDKK tttL&9<;w$NL&k\ QAHR$37288xr룱aFGGs/ Ʌ #044ŋ˗//XH׋iQ)WNOOO%[/b,/5US`URX!t>/ln<}_c1#0B@)i x<vNTߎaۜ Ǫ9Ztm,3* \2J3IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarFlipDisabled_icon.png000066400000000000000000000006771250202676700263340ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<aIDATxUm0(d ` 2Ag  Z6}']$+KlxS~|>{%dr9r"YJRO.9 $fL2eC@R`U`2&g2wI@;n RdqX5gtJCw f}ι hD܁$WvEɍҜ{ m7坚TVd(mdbKE4=HUA窸堓4\BM mG>:jƺGRk+҅c/)O^)P w= M; Nrq+.`DzIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarFlipEnabled_icon.png000066400000000000000000000007071250202676700261510ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<iIDATxԕm@E|9PLIs9gӁAJp̙`#"/AHÊa3SJM'ބacXRx6$Jvcu\ )Ĕ(LG HW'u[@wyѹ3HWZbr5l7( NY> 4)Bݹ^ _(zM?~G cMlG <#)^<: trg܊ .[ A؟ /T6/Pv,h p3795"a@ Pɼ:|)~ H;>WQiu5Y;z. ,9ʜ0IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarFlipPressed_icon.png000066400000000000000000000007221250202676700262210ustar00rootroot00000000000000PNG  IHDRtEXtSoftwareAdobe ImageReadyqe<tIDATx̕M0Ɠ*nޠa E\ ـn@;A%g͍c"vmTX)vs]h>W); ά({@0#Z ;*_dcqvfx@^W5h+N;H5ZwkQ3S:@9y VmZ~7 䵗E tCw¶uޠ#xlM M eSWhZc|֨th +A"( S1d]לi\k=x=h՘sa )ܚ42niE覝p& wbl)0ɰ:=j{k `x8Gm}?`F%IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarMonitorCodeDisabled_icon.png000066400000000000000000000002261250202676700276520ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<8IDATxb``Q@̙H9`Qw k2Gj`a l`IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarMonitorCodeEnabled_icon.png000066400000000000000000000002141250202676700274720ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<.IDATxб wh)C$ne9wR/*7IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarMonitorCodePressed_icon.png000066400000000000000000000002261250202676700275500ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<8IDATxb``Q@i;P#5ՀhQ0 FMJV@IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNewCodeDisabled_icon.png000066400000000000000000000005031250202676700267520ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`C L2D?@:.-Ra(WJ+Bh@|hI?懊rI1D71( Đ")1@j=R Z)f1ہXM  o]ݓ[/_@`??@}kA.GZ%8P/bC [,4) AqHB@(ĕpTͯXEh&$8WeIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNewCodeEnabled_icon.png000066400000000000000000000003721250202676700266010ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`H  D@ŴP:'@ h@?B:! | ~-x?4,i 0B(q]Ȁ^hq; T`@#(`00 g;oIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNewCodePressed_icon.png000066400000000000000000000005101250202676700266460ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`$ϩxB1,d}[e.@ @q hb9C| ~eC bGZ{ RP|;@ |\H bebGR7h|(@^Aq9A%P@!N$5IJ@K&`[@|&``/z,=h=`+BGz o@@6/IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNotesDisabled_icon.png000066400000000000000000000003201250202676700265130ustar00rootroot00000000000000PNG  IHDRw=tEXtSoftwareAdobe ImageReadyqe<rIDATxԱ ! (pM YɇŇo"zɞ6(#F"@e]Ef)hA` :yta nw4- 0TQcLtIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNotesEnabled_icon.png000066400000000000000000000003201250202676700263360ustar00rootroot00000000000000PNG  IHDRw=tEXtSoftwareAdobe ImageReadyqe<rIDATxԱ ! (pM YɇŇo"zɞ6(#F"@e]Ef)hA` :yta nw4- 0TQcLtIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarNotesPressed_icon.png000066400000000000000000000003541250202676700264200ustar00rootroot00000000000000PNG  IHDRw=tEXtSoftwareAdobe ImageReadyqe<IDATxbl<`@Ďu_A@ F FRL#&|>,hഄ>k U,g &$L.OX(Cb|F8WTZ0jC"JE}p`#"4R H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxڔK\G[owOOOGDA"  ^Y&R), X P`   ###%`[==s}U}̝q'[:]?U4~ު? $@ 8@xz??]Ԟg~/f._~W.s* Ԃ9\_$_y X+^?}Nn򩿼ǿϞ~^~-skKrnKy2 ([urA},ݸ. /&?hQ0䥏=njڭ\#5[-ߟϿ`LT>a5@լm>X;tՉ;A34Vux޲RRS(#,No>_EROj_xg֚gKv=05wNnog̞cĮvDJUbW3j$ЉhSZP6gN*P RWvnwGt$:2'XS5RJY桝=9p`MKN)̳mq]ˊʥ|֫\Q7Ibm&0m 25*Ԣ>9*aVv8Ԕ &l2ö"Ics"ШQΦyrdEH#9ZYʳxXʾz`7ז2,uY'ݙT,}gdr(\" C6JcHB  ЧNy<u2y)>%{jY@=gdQqNeArJ FFlVsi/u)%'cL).nTU>cPN-Ђ@о (r };ın&ܒ.0B̪ D[uyhhgp'7؇OF.ϓb1Sbq$b -F-IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarProgramCodeEnabled_icon.png000066400000000000000000000002541250202676700274560ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<NIDATxb``+@,0:@8`C@ ci8QiZQ@,0!޼zIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarProgramCodePressed_icon.png000066400000000000000000000003671250202676700275360ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`4s*@|~@>&*zd:Fn}H9B`@@ 1 Fj'"RHTLXphRTr ! i&' XV#bjIک]Z8[Q@W`EKIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarRotateDisabled_icon.png000066400000000000000000000007401250202676700266670ustar00rootroot00000000000000PNG  IHDR^tEXtSoftwareAdobe ImageReadyqe<IDATxڼq0Ee p:p:p+5 $9q5RBV3_3$DvfƖݵz y ׶z;O"T#/<E) ӥ%h$ת:RwLYaj0ex)lh UBYɁ a!mLH챖K  _U^X8'uK9ÚXFf{ B ))v /s{CLk`ex{27`8BIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarRotateEnabled_icon.png000066400000000000000000000005411250202676700265110ustar00rootroot00000000000000PNG  IHDR^tEXtSoftwareAdobe ImageReadyqe<IDATx̖ @)@$ V 9@&9  #c#%6}Y9zOofBe ؊`5cjG@HzpKdP#(&h0D+h}pp垲✎$ h!BPMݓÄ|- XI)#{sYo.U_O||(<% ::[$j/xtbJd-7š np2xǍB ]_aO?YfIIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarRotatePressed_icon.png000066400000000000000000000007321250202676700265660ustar00rootroot00000000000000PNG  IHDR^tEXtSoftwareAdobe ImageReadyqe<|IDATxڼQ0 _^x f Z&l P``A a}'حtv_%˲ ˳ פF$H(윆YHWy'UXz&1c 6#GR`!ѱ%Y U/ l(Y(HFYaY˖%r b-GsYS-GIhSR9P>W\  o@@t*V!IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarSaveCodeEnabled_icon.png000066400000000000000000000003361250202676700267460ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`H`@LTp@Z0-~ >h@h@ J` N T?$ՓZtxr#0@ z ,@q?@h_  IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarSaveCodePressed_icon.png000066400000000000000000000004111250202676700270130ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb`C 4s %f0QP0À@ZN`1#) P,NR *@iEP?,O`$#,J氺I1TQU4b,,J)7Z֏90Ѭr|i"ZA/pa4 0(l^2IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarShareBG_icon.png000066400000000000000000000005201250202676700252500ustar00rootroot00000000000000PNG  IHDRPCtEXtSoftwareAdobe ImageReadyqe<IDATx왁 00#t #n N1%C^MPOJCr/ιT"N^ZR$HD" tOL1)X#$e%ϊm7+LJxvV~ț.pʢE}M]0DFOT vK՗0C"s}4}^@raRg:oxG 0J/IENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarShareDisabled_icon.png000066400000000000000000000004611250202676700264730ustar00rootroot00000000000000PNG  IHDR"/ tEXtSoftwareAdobe ImageReadyqe<IDATxb`T?78O:F*8?>yF F Bf!!R4X O z 6DMH8_ Ī"Rv?>~$ "@ X%@0R CC#95H<X>0 4j9&^ZC+A_װP1D5Br]֏  6tIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarShareEnabled_icon.png000066400000000000000000000004611250202676700263160ustar00rootroot00000000000000PNG  IHDR"/ tEXtSoftwareAdobe ImageReadyqe<IDATxb`T?78O:F*8?>yF F Bf!!R4X O z 6DMH8_ Ī"Rv?>~$ "@ X%@0R CC#95H<X>0 4j9&^ZC+A_װP1D5Br]֏  6tIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarSharePressed_icon.png000066400000000000000000000004611250202676700263710ustar00rootroot00000000000000PNG  IHDR"/ tEXtSoftwareAdobe ImageReadyqe<IDATxb`T?78O:F*8?>yF F Bf!!R4X O z 6DMH8_ Ī"Rv?>~$ "@ X%@0R CC#95H<X>0 4j9&^ZC+A_װP1D5Br]֏  6tIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarVerifyCodeDisabled_icon.png000066400000000000000000000003711250202676700274700ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb``iQQ@\K'@OWˡχr'RHcd-[HIo (bBqJ(롆RbB|| bq4d(D e1Q (ԎXtPb1IY  ZLr>GsE]F(t RIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarVerifyCodeEnabled_icon.png000066400000000000000000000003051250202676700273100ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<gIDATxb``q@X b (=A `H%=A ,As.-U; hq0 FPb]F*UIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarVerifyCodePressed_icon.png000066400000000000000000000004171250202676700273670ustar00rootroot00000000000000PNG  IHDR&tEXtSoftwareAdobe ImageReadyqe<IDATxb``P4sq.y&Zq?]-Z<ʝK#-^P{"],'b`cPnbBqJ(롆RbB|| b `W2 8~@-ZuF\bS;"%YB$e540Pj1`[LvABL0YkIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromBDisabled_icon.png000066400000000000000000000005121250202676700272660ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbd0}֬@=`@@Att i]x0 %Ɂ| +@xh'0R`! ` ]ad;*0DUtq0"l OZU3 ТX`ٳ;"MB !t\[ qhb@AV{PS=FIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromBEnabled_icon.png000066400000000000000000000003361250202676700271150ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxb``Q0 ha Z)tфjCi4^ A ``s; a@K 0O(022&"q`I찐rԬAYx{G]@R !4ҙIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromBPressed_icon.png000066400000000000000000000005021250202676700271630ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbdhR @lXJbb0b V j:j`x9 ?"'l*x d~<4 )q ^̅LsQ!@-Q(ATtFH>=- \F-<7 &%GA08-5@vGbYj @8X;,F[CQ? HBHGIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromTDisabled_icon.png000066400000000000000000000005121250202676700273100ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxbd0}֬@=`@@Att i]x0 %Ɂ| +@xh'0R`! ` ]ad;*0DUtq0"l OZU3 ТX`ٳ;"MB !t\[ qhb@AV{PS=FIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromTEnabled_icon.png000066400000000000000000000003431250202676700271350ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxb`?bJbb0b T^0\TY1  f6&rp0硥@ Ն`Q0 h Eu XDIENDB`fritzing-app-0.9.2b/resources/images/icons/toolbarViewFromTPressed_icon.png000066400000000000000000000005141250202676700272100ustar00rootroot00000000000000PNG  IHDR%}z4ptEXtSoftwareAdobe ImageReadyqe<IDATxb`?bJbb0b T^0\TY1  f6&rp0F0LP1cD"NdybRhr tIENDB`fritzing-app-0.9.2b/resources/images/icons/zoomSliderMinus.png000066400000000000000000000004061250202676700245500ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxbd@R@z? cBq<0* XL]*!jc  @$aA,E*0LxG!;pȎ"2Pv#MTxIENDB`fritzing-app-0.9.2b/resources/images/icons/zoomSliderMinusPressed.png000066400000000000000000000004671250202676700261050ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxڜR0Mր{F T:0%x/P >-dܙdoM 9É9'ч|M7R y%[!U; =2P "AŔHCa(ZCsm @đ3C'V|-jTQb|\fcK#mb:M鹀4o+gw.g˒ X)ֈTIENDB`fritzing-app-0.9.2b/resources/images/icons/zoomSliderPlus.png000066400000000000000000000004401250202676700243760ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxڜR 0 L2#t6`&*$L#tAC:LJt7v.'Ya:$z, M_u<_wl'aC^ +MRET~;j9=@AqP"6%]=Yf$x|9`M1wfd?,B=-R )#V*: IENDB`fritzing-app-0.9.2b/resources/images/icons/zoomSliderPlusPressed.png000066400000000000000000000005141250202676700257260ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxڜR 0 M*P.r  h' P'hn@o\9sig`CϕTX'//3v[S Q<O݋+֛\B[!5ɛ"XsV?zR#Ć v_>K.Y|ׁg5sRc xQ _f~qFʔ)9aE]/r sVuYe2R+4R dIL)~T!j # -'wyy- =aNUS b{bF]bJ5,;9övc0BƌXWR(vBEcS^m[ D2  GI$Oc׀Od"mqb0\xS|*$OI4 Q~x"ńqYwN"I;D756hbfXcE"i[sF ,ZDdF(Sc̋B'YQFDQa80؜LぼN ]BlH+)_>?EsL nDimSj '8@gF$8&j!6۝Ŷ@ N2R1a_ >( .&h D@%OQ@ڶ}AhiC]I+K47 mP)ҽa BKTm> 3r @B*2a-U'j {ψ&^"7;|)FQTT#!QLk'#gj=ѫbiA L)恂  #SXVeM!i A;ESԙd+FP=(6)V1-4gb؜8p"_TV9vzY$[ۥTWU|RK[Mu?9GL`6:e, 6K7 X#S3f0|R+ܢQ[U~9AD[uӈ(nXI$,銾{ꙩF$PxiŔ,N5A‰&K2*Qe~7 Wp-2,f"ѷ˄j oVfc HHi9"PJ[JiÞLuڜbK 0O<&#>A'1Q[&ڕu a[ƔVdyGVNQ;Ө1쎏q3ޱaϦrP @ǀl5IN ^}[hدMlczx~3pK$ Ne3k˚aՖ~1 ; mò 4u} /`aI(m0eCz.Sêz3yV 1I3S"0a=Xðԉcmjۄ"IxmA\SdZu_s0!`_~^Bt2^F8^Naw'Ӱӎ3,(0á?Je*iy/S\SNhzF+1eǴ|I' Dqv}L&2&f:c%we6E?05I0CJ,/f6S&p"ǂtC0GKz?t<R=[}T%KeiO׎_bȪt$@{WŔa:=Oo1==f%zǩ-mug9nZjVJ(>N k[J5v9OB/k5<,00ǐtD3 I38?T0uMLXG&4P9L̤! &fvD*-Q=YCg0 7Pm &l* ʖ ;;XSIENDB`fritzing-app-0.9.2b/resources/images/inViewHelpCloseButtonBreadboard.png000066400000000000000000000003431250202676700264740ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxb`3g6RR b3B@|?72 PM lFR;f\rxLuJa5iЈE3@cb PT k@SO@RX noζݨIENDB`fritzing-app-0.9.2b/resources/images/inViewHelpCloseButtonPCB.png000066400000000000000000000003431250202676700250530ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxb`7o6RR b3B@|?72 PM lFR;f\rxLuJa5iЈE3@cb PT k@SO@RX ^wNGIENDB`fritzing-app-0.9.2b/resources/images/inViewHelpCloseButtonSchematic.png000066400000000000000000000003431250202676700263470ustar00rootroot00000000000000PNG  IHDRH-tEXtSoftwareAdobe ImageReadyqe<IDATxb`3g6RR b3B@|?72 PM lFR;f\rxLuJa5iЈE3@cb PT k@SO@RX noζݨIENDB`fritzing-app-0.9.2b/resources/images/inViewHelpPartsBinArrow.png000066400000000000000000000065141250202676700250300ustar00rootroot00000000000000PNG  IHDR}C sRGBbKGD pHYs  tIME $xtEXtCommentCreated with GIMPW IDATx{gߝl&iZZހ ("U B $>G?I?F?"Pl M7iMnM{z׷1SX{Kog$kx<~{܅ mos( ?o-f o pA0':%u:('Ֆ;Li:.JJJ d@xz^3DQT]};p`@, $%qx]ξaK!I^e3#5IW=fYzE.siiyW(;ll10l$SactaW%݆mUIsi=sbh^t];?*I%I1~  =huN;<`FQzs|Q<Ơy"aI#.+1%| 'assx \?xc tsyI F$7]@ a/q aƣ}ظtU#%g<` x=``[cj=>pk-IDZ/ݑ4 h`KzE'(|Y\瘤J:Ÿxek(!Ë݇pIӒ~%2"`|>ֹ*_ps̙Zy?̓7&q M.|UMl}_[EK$}crO:U$iؾN؍gjK'Qs?f>bPF5w$@M$} م 1r݅Gc'^p:q= s:ʹ= X7S*ǘG|yϏcnKzŹW\ܛs*|LN[̈́y#<rv7$u3)FQ ]XYGp5%8n͑eapIo ƞCmM\r갉 -pSRM|$5gyNmu?1SHj" gSo0/#QrD `y ?m%r8Vk'`Q.͉$6O:(@b~^{bӷ(#HQװٷPīhMvfDvaBsJMG=:;}O[8sY#0{ mNټ_N(:bcl“Ul|@l=ff9b90?☯>I2ӯ.枒+@=B6vwpL;-ȶ=} ]UsH)"U.JǪx;B,-x"%-q 2]ZEazQ*@([|r6wAҞq.Yy1i [RF6[]ڋ0 # m d2vd I*\RqS HvZ˝m)a[c3cHYPȰ] VӗA2wB*Ae[='G S6ișJK?O)2MH FO [gz;MfmPݛmVn3  eʍe<sزZ ջ+Ӡ vQ/z+Tfb_QWHn vZ(n[19ﳨŒXcBlK)ӫ /(ǯ+NX Y|iP꼥2))1U 8܊'`{ Ӣlf`tq8oü3aꯖU0VO~G x6iU.طXS}fېtcJЬ"i[[v|RC0eY~?tSelQbw+Y>+鷄uӒ.z}mrٶנjE!wPOzp& U/HZ*& wE5f*dN x6ɩ&xֵ!YKnuJx}Cag4qktB?[\(+=ijfLES,1.5/ <1]m+͐m{d](fM*9{[^Ff04m<*tS|aݒٰެ,[kzKc:2~WT(nM7gկKF+GXukps8{֎gu[OIrllMX.A(`Uwo$]㸞 {z@F4L@aœB TE>/[U*L6!OBy4A@QQgu.򸎆XQMf汧sQ”i 2% {QLuybn<:A췿vg|8@7*?}dk-O: 6CMem2'T-lk-&3B5gT*Qn)e-ˤr;ŞIENDB`fritzing-app-0.9.2b/resources/images/inViewHelpSwitchButtonsArrow.png000066400000000000000000000072431250202676700261260ustar00rootroot00000000000000PNG  IHDRj8gmksRGBbKGD pHYs  tIME  +tEXtCommentCreated with GIMPW IDATxwƿiI InKX61f1$$8 !o9ȟx  !$',-Y5ly_K-# c<}i]_W˭{4MqĉGQTJH4,!)T$JzKQI%]4y\rUҸ/%=!iI}$ I")O%᳦IνgH:$逤$ƽDFy%]t]SZ+q`{ョelT'0:QyIIIUuZW:X%0.|] In-IeIKZ@P 2%^G $_xg$tA2cm P;+( |q+^Ew%-lI1,I@gA-UZ`,]>+I9 h0gPA^GǺ]έqjq`vJmh:<%鼤9,`<<q3>g-5YQOa^|'eTXzM-JQ~(1?(t=k<5 Nw6=f5hM C3@U s넜qFQ4(iEQ k6I7RBF8I˰ 4*& \r D讄G'Dsp$ nL|x))SxhuUqiϗojN|Tˉ%Xր qvuq0[a7UЦ%')'w(I Irw> 7*G xgىs6AiC26ַ`J~FN8E`Av0&@{BQ@Z&rĴD}fޫX>x7[T{ݤ (hK˰Ԑ) /E`m䣌~74,q  IWzz$2LJ;mnV9CT=NeXwt@~j/b $)Vs9פ"E(͢&jc-^R䞪P+:E,P`$U( {ִm|k*?ϚT6ruLR-hO2 eyI8=EH} uIpئ7@.fc]b;4|M6gDٔIE<_EMӄg8`صpަz,g}߱[Qq/Yu54 z ŬO`6Yg EjqN||e-*[*F}VhQVUqvg;c?[#7v~C7N~Ԓq}IU&iW+;0.p0CXS4ܽAs5c:',-9ƑޱmҵLyic9BɩEQ;uRеU{ KkK]q7=P}X҈kԞ5cܩl@ ( |\@U:f۽cGe%O o(^Q۞qZᯏ nޱMu?,U>h`=uQ0mjW:$+Z>`/!Yqz>Wo~f ǚl7 !oJEdߔ[ iZle]/P)%^ɢ Gsյ >B/U}7ֵ˖1OkoSV$ %Ju=8Z˳t_WVϳZ"j(%|A@(e/}h`AeI}%ЇR>URgE۷OYGyeh[֣`Qݤ^1]?_<Hcס)0D*C[Q7р-;pjfBxX@n#g+./ԁ4|Ae{m$2?U{Oyy[<`Qm~t*8l@H́^[;Z]`8)ojΰvk}0-+o08۰2ΪqԡlS8OM%ו!lU,])"vEݟ;t_{UyNYeIY3k VZgCMBa4X-KI]=VEKVk3ӝs"t~f +_*_.ckeD硿O>*ߣ#:M*֯ПuTM|]a\DKVʧR֐:f!֯X6[2|˟ jgd|ס [}K^Hle` `A0kYWЮ:(v`+mQF67LsTW)6'!N!X넲B^E%Ug,(|S u15y p0+}r®kiAٿ^ 0:td%Z:HfտVMي1,v;9nYy 0CtKG?"w}95"t WVZrɦvvb[X\%g~Z4+K-V5hp eٶsqwWke[ Jt ~e(2ݢm:(qPV[q6iAEh'WH y #ָ*e{9݄`fMUkܿ@T0-:6 @M {͖U fritzing-app-0.9.2b/resources/images/part_sticky.svg000066400000000000000000000021401250202676700226360ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/images/pcb_icon.png000066400000000000000000000021031250202676700220420ustar00rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs  tIMEzՌtEXtCommentCreated with GIMPWIDAThOK#IƟ4d"7]h՛!"AvՋK@"sPD/&ACv쮽L4I CTzhXYYy>'|РBzuuX\\ަ5ML)!疖x ihIDATxDgu}7yg'ͻD "@!h[Rce*WCrL-R"A &޾9}9vggzyswO6ɉ겢MlD1K,S4Q1tHQ2 FM  1/ +ؘb)0ca(xQ.3a$ y9:]cI&?CC(yh>:T8;0ice=5Ufx 6=-es,8 %=Gon|p/0(ٲ +*0 &8ahhVc$/!,BLE7)=eۓ$Uc6G㖪8^?]N0E6O"A`anlvzXv r~2q bXX(a( 031~=בa/5K `9Y f&. /EдEӔh_xk/gv6U4Aa؁SMum V9U:f''߱~|ln6'tlגUMxC*\0;W|'?E&%́0!!\ hM($ ȴ̒?U5F:ixHf>xwѸvx_^^X^ҹ(o?{_tЅ(pyNG1/ ǡ'_bb7Ay&>"3aE`4E\R;>&3n9:5G-!*$E4eIS֋]A( 4^,>/r\:ϧXp4Vh68,|e% c95dɻC4MPFcY A7%AE|DtXPhtskWo|WgA} \qp &T}vv,s ʗk,'Rh6 FH9 &v1[t땥ۯ3>wǣ'(i0!JL7o?87ޠ`+bb*WM""]saX]u\rxsێȚ$A5ö9O.-Tx[F>P=y`>e9#qRI?\|MwSt[^bZlM0xN4O8^쯭_yxq]UF"GxI!) E{ch:MATɖKر<:GA7U)%C泅|5mboH[UCTt5;!/84S<ϒ% b0 cd Pn0AC ce0ZJaT@/pxBxDYN (nP4e8|(8R K>`Q8@3BBDhd`W!.7k  BiHdւs儌2>'!C@bGr("\<ÆFOqVsX9nlD% S 5b$   {7za*X/OvҲ}?x "hs䙸(5c'4#lOi"Z F?x008 hD|,P z!9Aʼn G!d dz^BT)%Z:_}l /~_fLpS󧭃d ` fP,\{p"\ նahFTSFp% .eEG,)֝^*@x>0o^ANFa[AcAoNhZPnE "zH:`! e>8v(TyUُWFc;QE j]v|zNĔf/gneҺAd4 x^DAcwk l6Q9))VUAOÆ9cNpvOͣn> `+Q$ \1TG؊qD7HQHhAqgϞNwAEΜRNxNeu)A}0!{I$ {ۭΡ)Zx$/ZX6fH<гbg.4 5y4/h+FX>s D†8#$^lKfD>+UYu Rq4, %xN`ODOʞ9MbHg^0_(6)*1T[0::4&X&1\1u\Bl"~ L07`U*1д:g/k~+zdG!:7YN#$ (&י9 /ٞxrp3|`L't\"_$0@hDyn{A*7=S5YT])"G"E<3cPY@QF*I_K*:;WVrbjzy7Ogjƞ?_?^ԗkӳdhr+Ǎ5%]*/Ot̀%웦RN R\;"gc"zAQ  .Ǡ58t|4HB1T2Iif0:,HTH|CC7шF19!|?5+IQ֨s>s" ܰ5KC'saHW5UNKoZ>qHϢ>141PdPc@y9R1V.ɦ0T #@Me{I>a,OT)884U&;Ԣ1e cєᕥ>o|_oʅNkΝۿ+ߜ'Fxm>Hr1vms8L'Pa/vsix|}0Vg>j!ʤȄBdJuzz&R.=㱁^xp .ƀۆ7=R ʙ%[)j KQ'O&f?WA백OJ$"яݘ<'¹Z:Eh=ȾKvM 2iUh~qk޸vXTꋽɨ]0Ꭺ?x|;vag?d9O۟h{G;?q1"6C0P EC;ak# %))LDDQ~C<6$s¨?xT)hSNOwv( +MFVQ5@o\fz8'74fYA˿Bx Hg")Z&41CfHa#,Ìl@HPk2'@{ָ16ީ3hz80!U=/vV\ \L0?p4jf.ßI 1" TDx%Hho h[̔RV>ZQGƟcǼV,|ӳ|m?[6̅٥EN[I4-BG78' x!IJU“dkӏmUW{[>kj2ϥs5%U9_ÿ1J{'gJ--_y˞FÓmQ,uP+wb7Jg(iq 1xS px Wz70Ug8@A@YXZZ}:OssbN]|:s}bLn{=)/^{>;Ao 8iF#el6hs$W%M NpS$' XB\ I)LYL Rwf ́eQrI@Iv:++9P״ FSV2BiV`g3<ĩqv,=S)wؕEon`9ք$q'ItFB26PDwq, ljdxV$Î&"9 J4ɛi I xߏkL%MKj&%Qˉz 1CsYQ1hlL on:kGNDEUчNRXձ; t{8¨@YfYUxYZ„-Y/R^: K zLwۀ0Sga!Q*!d!ŭ 9ad I$H@"%P~A& A1#a/~ dMUE2, fq ”"#M:=!%S$U INC0OFd[^c M-[q#w<#uy;A( UV{SFQ:eUd9|/,gO~x~~aL̕1$ƱҤG'cC'?' ΐ}F/,LDxN>x0Ŋlw#ȑ6D&=`"KL}~n9^WA+AE)gyߞZ^L\vK )>~GϿ?V6VBVоpz胴pҰf9!Xt<8VP% HS*_E]xztx̙ thgeO6D?!)L(w>X>w VR^i3l.)iw¬:1Ik k7V?ee^lepx  %дVۭFwݵ{ @@:~stK&W($lGBX'Pc37iTsv^$+\ka@%& EGtfS-,i& 3Ŀ(%I0=;[L҅TX}Hi-U&b$ӏGN:wQ5I2(rL!ų5t0("'>B#?D #sqkOwcpcFA@R9$V0"<Q-:p&f(9ecuDB~XO-H NVII̡6@SQ"cF<6a-cWAN6aE"W9NBn' 1&>X9b ݵ{ JscpO@9Aʲ=rIYxHY FD b-FD[9믽^N+[[{$*%UT̊$21h*K%}Iubd`?qk]@S 37nLճ/۷\J.T|;8OȔ,јTb`\4<ھwv7Woy3 ԧۯ~֏=1%?m%x̂>:Π1W-z;0R`zFTA Nv:?62X4W|@Y姱;Ϊ=QQAROD},|Gx:jƁ)kyAgN܃-J<А$'B*'MHl$`vEɀrC`3!,DO@H(bWJKK )Zx}>ti· @LAbi43g(rse j Ox}8nY8-k)RHENmm<(AJJrՓ;fƚw9mUZ55r;~ӿ˕ًG<}?`W{&FpܕSi׼֟?/WgR}܉ .GR%و׃f8MCs{Q;G+ӗ9N1l 91?A \s??f؉c"0@(LG%=QPAUl`Q*]狞F&'KzZ[0wQI3Lbpf,Ơ?UUҳ '$0M+ab҅&-4OjKX'}JJ]"SNd%jOF|LH$-ZI8@nT#ݘz(ԇXՌ|UAȪ R,Ⱥ3ZO;Eg/\ppȋN.o؅GaϠCmiNcxgc8f(ƁAD POĠ($NDR6 5M Ƕ3Qx}3ow~| Vg+/\+/$sK9(}!0BDMOo&hoeLJ-3@i6l>;d Gtifv9i b̤S3xnN]qWn'>E@=<;=GI!yViMTQؼ)g+5QFstpۉn=w&U.^St΂LhVz|6%ʺ-SZjm4vXTq|0uu䣣-TVkN_T=%ED1,7ߐj&ҟkXF?p3!6 @1q#W.\ RiN0VIȱ6X.^0di)9֏<4 ba0rr杩jii 'ϐsf$~ d )MypaN5RsWo~Wq˙r9dYӶȟe-kz#}Ixœ&i0@Z*g lq[Fl _ֆ]5ϔ2#ˋʼ)2-ɤuyThNOOw|Fq{L4{᎘@r)I_l"@,Kȴ?\OkZ(/ek cFeq $V쬱Ly)F&+,H`X[kw{V Ě.˵UKyW%NĔVYy𴲰Jmi9épp[i.B.qzٴb d^SDΑ83IR , ģ6~g>ILLr/T ԳE`x0t"@aJGRP@Hl;4% " g hr0$5 x57ǥ6wpks7U-g0YNdN4[͟?K]̩&|^gF.\a\A+1Med|~6'h |+,9Iax|;> ?À+ҏq!IU`2KnDa,&%5!>u}$$͜8ư2"?@F \9yא _tõNr.S+@(#^d /T[fgq5"TȉNζz D6$pMt95_{ _xz~fS]יh*SiPxG_A^">PIҀ=w@Ztm=q`ꋅjɋ-Q e/pݶ|rA;. ?[ ڙ,lKRL.V4; DF="WAw6irX@ zm0TyHF̓'ovl=пWA]ZTU^ C?)Nrx܈8"BcgP ήv!Xro|v%J%:ϟmx??|{`Ȳ]Y[Ȓe5!ZF!gM=t==qlˇHdaF:8̠2/Û8-hhxm85^{2@/ 9-Rc1A!-$MH4Axkx2r Rn8 loMbLl LJ_E4%\Vcо 8˩h K "Z[\ p$#tODQ L, UeKdMhOfh]@0+/_x[w˿r妦:cE,t\Gαm>`ΫZ/qz5!a_!,UK0)fj HZc3((Fv=k&M9@d3e2 rMĨjjkIFr6)"@NN`~_~w~{e>_y̌g, iPL\ )(9CkW_ vz-%^*άerQZ:R L9N;OOǓ>,h4%`^QhOKyݐsW~)]zEMIL8Q+f婙eq1!5C+ˆQӥR8zNEx23 Z-reI+\SN>zTu8>O.?>t!(Z^.TCaSQRDqNt'Ix(Ud{<\_yAi:(;/7 :Y‡xx<<9Zڕ/{pp:pigurY[|3;yr6wwrmHr0pP,p]R. +8ظOTslON񠷰r4Ksrl0I b5_hU2tq ӏ6xU_h.12Bevj^hCTnۓw+F.[[MO9CT}:c0vFA3𱕹sxCNUMղl1k7vȧ:x2^dkNX^avLNNAp/\}B_,$חdϪpI%3B[W>Km5m;WƖmSxWt$R#% %>rYYdȱ"R%Dő˖lQrk)j'rp,QM:9J NiROlncgys!IC`f?2vVk6/˜C1! cAZ:&A9 )Η4; ?SSFeRt .iYiFU*o ]2y>b%c1f6m(m $JwGdž&욦gaYl-c2Hͫ9Xty /)NfY/` g$K26j˝47Z-ӴTe"l(o ԌG(f*hAk֊!:#z~G \Kg#,~xɿ~p3 '/Uw "0U-[^>w/za/ӣ|-`qb*}^Jo= eٓ{vOGNv̉yF?JӞq(an<|`s)I~#6Vc%yvq̘ 9oȚΏe% CJt\sgѨ'A+;8Wyz`3=OΧs;9DbHz.R+\rU%I?*IʲW\L D ܜC>9;Bso9d7z} ^''O=C}ow̲nɏLO_tl2=MмD![8nmnܻf}+[()Kݡ6@~5] ]cgݻ1>>}]]u)!+÷vpAFJ'|er9hَ'ǎx.^ %bNdy:x$G4Dqj:M&ZB#:W8tCA5'^ (;x|J4MY2F` {& w%j݃t)(:6VCt*>Fx-qr\/+O80H <9dVLVbFR kе cw:($2qvOQșav <[_oMxI(E)2& K0@VW]/؉Gjun} IT'Z?=_vg;r20p2zc%J<}<2IdN)f'S 1Y`яY[oo߄pʩ@ɓT0|Kg?j\-?;6sI`eܣꇳӏWN tTzݕo̝?y!9' q>6 [,}X_h,9=sr_N)~X7|N(.chM&͆@ : d '>~;};ҫ_:wlgeEQ`i 1 mhJM+j/JTG~BC81VT ,$H"98β^FK퐢2pd5ű"fXzoi *hEkp=Z@m=t$h. $ {hu賌HL*>}96iY3pI s f!IbaHT qIɒ4ʴH0P?0St*t)t2'1 x{H'|ܽp򀧁DK *c%iQPR,4Q?o(.s%IJX_8t8^IB3D|;x2PJHɅ$4k;z~W^ys @&&#iG8TH#:OL"-sF7oԩ'd9Psէ=2˕@(-L:*^<69%2JVovs܉d;~^ .yx#o0((gի,緗ܿV04ŒV3@Kuv7v |`oz8?3_xFowE_s L2 @]M$:uv&n~ˑ 2cRXLӬe{{jhv8޺{nAT8wgÛO7o]5=i%ϖYz'ƒFu\\щ>jѱpm'J&;Š"- DAJd5{ xZF"ȺHYnn2{ /_фyKk[D>ŊtNQ cmֳÅW>ǯW/^z8>.g`_~_g}p'}|aZå0/jlRpqKX(E5Ȝ!DG X>BII~&G#IH4- H<7DUAEH׋zbVN_cD1FԱ?:|c7H=3z3QHFB9;k œb0 1QxQ17DE5SdumzJ"]8NhehC1 TUIWI0|<4Cn }X^< A|4\^'X2 ZᆸV{ekСyZ$a̋R8QYsiDZEU^^u`mýM EExydޕ73'{<.ZhNs\XTiNUTZ{ n2 ctz|vtb ` nHx\@q9+ӬҐײsc~۷_~Ҫ")4 I"0@NEɴ|#c~meevN:y ctkwwis$Qxiߡex4<,nGU3@MUhQ<~"ϧz(AK Co{~*A3v[Fh=QT0=P@[\T5KӀmy^$Q!^p "-&:[߯dߎC\8鑞A8lmTq91"Z@jx ZLg!wj{Fb5@HȳgxJXyps{$LXʕgbD4[v 셎mj=(O.f[8V+GƳ8!mC C}n:? C#[,zUyrlR@Mt}|] :Z{ʶч4Pӻp'gOLLKrSO06>*)(6nkJHʱ\xs/k`;ϟ909WWz ׌E!fFb $Y9rƣ,K$\ۗx6r8'e^30֌p]pcG a4BHp4n1 [Lp1sS3 'Ia$=@kmH IEQ>͈f;9٩V׮(jYTz .qくjv A0G'Bd2 $7?7~G;(,8@qZ$&ODJGf1_wDPt}OvߍDhglOZ}lD̵d&/A!bel.QcOI2|Tm;]qIJj5צ(Noۛ„䧎A֪>vUxNM`i0 -.PO%^Л͇.7SFnĉYALb[ 6/.ݰc(WZõٱWwiF'{۩._$rSxy§R{onbd o< =T=\oֶb;u~j4'n!5ӄSAq.5w7nh,-p(75㰺}_dwчC.+ 7bв}ה8rd|䉧ŗ_z姞y~llAL')!kfM751+i}uBn̩9 U%uaf\xIZmmI#SXLecZG G$! lYJ{=HP8tcƅ"v?<2G/0E^eAsgk;dT9xxB |M4!G<+p>E;0J"VZ9RH8Q-CCjFcꂜ7چQ:Zc_NظXx< 2*rhv.'r6räӹ_{"rDNJDnd9OPhr +!u>^d34=ν̓ɑyΆ,WZ ٍh2?1㯊BfonH'xlrV00t nw fGdAwoߤyݠ9@*n;~ʷBT+b\ᠶjʖ|ڵ\k7jű3RWn4wDrX"m$7W~ۨ={be\wA`c7N?WxcLW]ɌfXD]huJc]]'!L) 0{n^&Jұc N\Z=ׁJݱ!')7a ZJ3SO, Y}wy_G?ݛ@L&I'dUWm[kgϞ~~[>/\эtڵfcr{iZ 7^p}K/յNl0:VزEZbG+b~፬h:W"b8*v10LjE`xn '?x˟'/N͍qmqR:@>m 5G࿂_C9Ȃs  v}I1du`89KiN͙Zq#3܄e^lICVN1 4DJ;Cxڠ] FB5W92Ȕ)^BuC@ #a}^L32J=O'AǶpiNIoq)^`'=4Z^z(r4# 3#A`$X3<eKo'gldEQxV܀/%F9 n:jϔ X"CWU R@"H Hjuvob3?qi;/̌]mH [nPG^Qa < ;NK,@RZzmvzd|z+W?xpsLet4MRftr2(BZy] Q%5 Į__9p~LY]/1&ɢ26{6LņW MZu"e Y^Rx5.Nf1bʖU1s6nh҇'SK%IRD6)ihVٖ&leO"R%iD3_96H ڢqY7t3gJI鞺{֖ɩDJ.J[+ЊS֚̕*d0 )Y|@Ճe9P㩥޹(gdG*L>~oW|G7W,H\:WZt,-Ic_Kw!t@{W?5!+js]k˕ꍏz<}\] EtG3 aj=GJ>urWpUE“"!V DT2\2 2 @xo 3"aŋ^8%VhG410d*'3X뢚^̴" gǏ?f˛7N/.{<1+"Ay;W-]{ S@r,HxVcO|G?{"`TD*d9V7;(&/?rIDߟ7_~v_/9%W/~j\x0ͯLqyq-q,(X;D3d2L3?gΜӷVo J' ^bL,tR"֟>s(8* u/"Z$q4\t$:іjH\TmԬ$Z! -/<]{5#)D~uB6wiF!Xh5۶B@0EBE43LoJ%5U☆oHg%3s"nhŸEYEC\8yY"$!FӐ'<8䩎^iwB|Xz[ÂSG*Swk\l%Fҵu Sł@xO dԀ"/gVwcDz$ÓHh IheXr_d< bd6Ur66׮SJ5yϸ]MOӒLY^r}xG޸|NJy(ׯzsg$U\4--Hhܹ|ʍx~WdwR255{!\) Czh 1 HTڭz˕&FfhLs'ϗF9_/~{ח=Ot:*ʐ-趛n_~O_oqY]oý~󃥕Զ6|x3.UFrㅡ]Qxgoת福?x}osV; !F2X@ǎ?vO& cB7 wk 4z{apv {ES BpzG>~wnCy,ODHRȩ1ǎTq,eYEmYfgqmsa\N}LNV(m*OC aP;uؾ6:}N6}o^}ȋ2OH掘+FB\ݩo&J^ *J~dBVӶ[6;@sC%IU172VIR)5I kխՇn>ݩn 4HFӭUZ8"+ۮZ;gyUl'ByZytYx6'OmVku4\$[%+HpIt)Se(mjUHQ !m>xgS`éܘ$!:n^y_WWv:- 'j hm" S${?w?{_yٗe)񠯵\/k͝ hZiFgr#ʌ т%ã'Y8>Sk\291{˷[^>!Ykm M0Ht, "|NC - }I[)ƎʹxF w[ !yC?jFˡ`U_g-=Z=<+ N4wǃ~д * xI\[ϡѲc" x%kF{A@Eqa<5zeo[Ђ,'^մb>$CR$2ZdC'JQC4yfoAy-?p(@1N')n6'Hyh ΢I08pSȅ;x^Lݫٴfvg`0 .*ьbt2U*dd8";v<:HYjmN[ZhwIK Á --r"ڧׯ]ViKuI)"4%另g[U}DI iu|7:DS?lTwrS'G/^MDћ(Ǝ{,R Ŧxqo-{V@8IH\-ۆ(ɒcn=HRs}Ź/ʏKӬzz{&ppiF;z_$S5}\z}o۪hk=B]N*[X |#t\#gc'+V-)ͫ"rS% Sq͇?Թx2w^P:V<)TFF>7/~߽[f/zSx<)bH}еLgrx>7/מz~uU|qX8dit8>;:{<riYNzwZed4fw;uJ沙R蘃 <46fr pFR:}σk+ DoAh!G;Ċoa ˎVm-J36,JEa1ڛ'O*J.?YUqYJS_;"#@PS% LXlrJΤBʇ,',{bH&EJ5 MeǣtqmԛahENo7;mXFdQ-qb *9QFchT c+ YAB&A`ADPe-M{LPpϲȒ q.q!*CYh&QI߼taE|## =l|0HC!Ab O ] r@Dpz*^]T8KWMrOg~&sv.LR!1o۝=KaG#Šm^Iѐ^Brc)3$ dy5T0;k+K7/kv2R5RIFz-[?5tkwޠP,<=v{2󄢤R Dz]ZĴm~ )`Z{ l$4TϏ6e ڨnI XVulXݸ3}质 ?O'^{}чz?~_޼Q=>g2"2vLc@V}/K/|E@|W-__[}ޛ?сY` '.$9[(͜TqLǷQа*dco`csѺ93g!KO;+Tu8y8xF/Rmzhv]xO@?-bѡ./J3Ǧg2%[ČQԫG$:׶nr29%"7 Php0.Tu]" :be9ao|j>K,X]@{Zo.p(ol?$F}:R 9BҺjuwMyr,} A';~|MҺ^ CS󏑨G'Nɸo s~shʰrTS3yǵxPKJ!(n,\ȎCpa(SXh{kۭZttȥ$hմGW/ٜjvltPR(~ aCZl $%xIf%NU "~Tc!D z\cXKDs2Xt>vd8#]AC@<\+nmH?v8AV H~=0Rn7~p<]$DJ r:mX]};`"A`YC4SA8y!t9\c; ZvÊYd.b\HBab w B,dXGag0h%#wv<{B`8 {RSZ]j1$z |8Znܳ[+7?y^Sb1[=yWsc$'fgNV"3J~w@^x:8N"{{л(1r;&d224ӱss('=6!ʳ\\rf왧ԯm/j쮳|=^H;\8^|7/6G 08n2c".ݻkyFZ~+tj3D=?_~w03T&,S(F0ЮTg/ } |E9aHDhڋ߻XY}BRp.~SLV"BQHɒ̸Vc?~HsDFͤkn +w.B^-$2P-7FO+>ⳗ$nʊDG>10/ّQκf%ZX$%6b Nl q>ڳ Y G xWE~~se x"0@$)AɊ:AQb [ݥѤؘ-B#%M4mM:fK~H7 #L O$Px*g{VN:]fYt" GC 0܋yxx'b|}GdM@´넃.'ڶo&t~LS3H;`训6gX{x]Rix6SS9BL'<?x`2UO&mQ#*=^/`Ń# #h]=3EM A?WOe*%q{Ec/+8PN&@PK˟tuWdqل7 )^HõGL"W9"M[fuu0Datj02Ű-P0 dz1SϔO)O\m9XMx~}hkD09΍)3k>?^^ܶƑvѬ ϟo~wnnvpH1@AsQu'U,cj\{LܼFW>wʯt&Υs#+9P^2ЀW xj C6,N";^Չ*ӳw!çr!AZ@LsL 85clvܠ~x{i|I(k@ o0%"H }F%`x.b4{hkKjpck')ilbĸ0Y}^ABHd  iDÃo j118,|D =3-V'iAܛ#'!ɭ0d-MA5n )ɀ}FN3^TTwhǦXZRUGkLeKz:V!cC7)^l}t)I!{@8X#,2'z$' -ܘBu,Aq_%AD`q_w?ʍ7--n]ÆK&H+C#z$BhD\bG֎XE9]$~} 72֊#ϱ +6T䜐/pt=_>ȌxN0,L"tLe Gfo2~d$F \P9Nt"[_64}|;%A8I b<>)U54VLB`01Iֆᠵo*gO=wOJl7 |Z-WNfǏIY\~tC5kLird*Y=8uB%\o$C'{w?}Ӵl!.eG=[,[]~'?opR$ƕ ivT=t}x]4F'd֞YNt,WԁX*f&|@eS]$3N;;$UhNkd5g ·m[{f$%٢1I3A!`K2 H6v dI4f#,'TD{CNW]غ @Q~X[\\zO?7^~+}|Nh* f4G2Rh> t Ģ) EVT34hZݎt!][(U=0E7IOēU/otu]"MA4L —f$9%cNu?4kTP?ǰ < iu/1^ۮ+bRڸGPdU)^(C@q>޶USG$(,b%vP@qx/_j/,>jnI`"hP5Vʃ˰ǟj27 UͲ$Q]x:{S$5  N:ś7pēX|b`$S/wC(!6UPc(2 7*ۛ|(\+,^49}!N 9Gw{}$ɽS僃Ǟy(MlmnBэ;%rj-ný݂.]JG W~>\o?OfkMUT86I!2<Jqh(>%5gן6nOz%{G}ٵqB4 9!HfD3!xajh)]/|;R~-z-U.5t5&)2 +$ZG~6JRlDg0? SG$*KwkБPtLux_)ɍHgiD9Mqe3HBJc_{ !^sW{[ō[y}O=S)Wڒ}>Cxb}#2tVЄbuwC#mJ5Q6fo׿ǵBߝn{ @P*)nFyСxbiW^cI6KtSnb $I8t*$'KE&QUjbGaèZ0nO?M}ώiȿqZ^R g4̈́$k4S(mSu-68b8D6ߛ`U0 RTf3,jgҥ+KVCXBHVEQe5i#G_xo~W察p(XTK/ҍ}:u:ඒ8|87qÈbaDXKk=]Dlrv%lμuͽ7n)6LC08ùO^;F:`g  b2[_`] [M` Qt\`i_$=IO i7M @Rp4j٪kbMJ@CQ.,;1M'-/XGxw< | Dq\QOW }nAt&X! ސmR &,=uQ4]B$ LcB$"r;%VJ^:JP_]s__|wܺW.6ٿL@*6H'9ǮfH}{Nv\u !cpq8f^p9ܮ-! "CCN9Ǧ_:h͍ T<}J^vxrIJ";$P=]bJJ 73>p3J#*~{,]k6DzH _?(nۆf#8|(k3׃,͒hcLꍽ7n=5+t4xsgP`?e6ษ6녝@$:CrBP4֩^_w?x^.)9ֻH^GSÎOe_Ezm{uE[\$bXq{&;<~" &#K2X$H:k?F>|,Х͕fCSQk9,c[s->LΜNw=;*u_8{æؖ؍TJ-YlN$hB7; ?{eJ~#v޹gM #?4z" Ow;sJBgmsw@Ϝso~w稅87ةP$Z坅{⪮w T!pḩɖa {5pN H [kdC4GyrfE"i#zLKU c@qX\/Rjh?FҐy]}"LU7a1hh%nNٜEVvWϒt\08'2 ҆ Q3Mqn,u4jȸeւm 19~~G7ff\7~{|v^nIepLX춛zZ?Xfd2P<}‹j|[q닋h "Ic4nvG~{_ŧXFXzyg) xf7KO]<7|СZǠ,ج~;K :QHeҹf`Z7;tr8{t83jrx4lUj"ælXbd:j¾ixH.@b8FEH.@7Z 7ކ`"O9_(I B0Zk[ H<\{GJxZdž~I׹r^W^B-N CSk5K(:ӣbtƛGpOI#AwOVM%W8C7߿HgO]|59 m{'='\ E^9sW)Q_L2:0Q)-QV EUxHtSS D>U‘X6&±$iRooޕO~O~?:7U\_xRt9(MXc^x{ۿ;uT:xG?-TKT,<: dž9vtnMI CEySVPXȚ!kϩhdrL_@8ćU2/ 5˰Sk3~8@.DRdeE&!LFehih]xp kGsDaD0g ^!Щ:RݟHݫ ϼ8|~kvAʻ[p(jUCqT04T :59= >\?$q$OQD/^xb^ؙivl GS^Аې`rjJ ?=+ō d8A*U9ȩ$ ݔZ"@P h0tԫ:Å Ej E#xphdSW{CbjZOF<֑+LMvBüx0e‡G "C~.s<GbQݨbNZ5TU (ҵNtޭK3\u{o<|py}Y_[WGwCKav5fobk=, Jksv&5D gA؎ [Ra:( >{tuvA;ΰi$י6uDDHvcCyҗWɡ&IUnQXH<ܩ=vqhdѮM~ Dۗ  Ӄ"ЁD&{n@|8;{k^qc$vr"3BC!56Voo{?|/]ݠ9^^/jhgj,O|/S8 :u]gVhlk*&X$ˣ[4i&r6ticH**{ܝKwoӶ(ﯭŇɌmJ x~ܶ@sr*(ti% (".s6r]1?wKȫyGw :2n*uBӸ57Von>K(fږ/^ݴ^*3pQU7LS75cZebu1 s,j9xLئ8'5hU9 'F8Nsy6^;[M/9MvX*7l]T67k?x~S6D@  YjY%ly$;ąǿW7˯|#Qǯ-<{S̃Tl FX.7Md`Gn8c#ިnRXg8ę/R],M憽^ ;`h {&aД].ndŔw>nt@fFhhGJ4_X NtMXpTzXP"M}An.JExri>@:ͱVp| |jq#SO;~Xkogqcjg2OuI@ w[u,Er`wm|si:1#/fGI8lT+Z-{ldxOj .G㎖ (FU]jOM2Ď0,ėn8XH4 YP$!m^blRh&r^M""o&'8BqhFX:͇U)5ER:(!܊(70b<3tl(&>#fJvVwڽ;o_r͇Wv+բ!jx! FԫuHK1N~dW=wܟv՜;v7 :It.#̽DLĐK+@$^P|}V VHA~Ͷrn/>M3lkk (,\3_9՝YpaDf87y(54i (v:͖ii 0M% 2mhRi!~RP8Y,=z?_?+k+ݮ Q/J*:݆k+ > 绿7}:l.ooܸ^[K 𱦦NٲKfzzy>i"LFW!y hUEH.cjG{w?ER:D-&cr{EBj`DuW~7tVRomN$顱&IuR-yK;sw?lKuP&*b9qP^QNzH,U}71=>>u^on:e£O$2mY\{YYIq0pQ{f$$6?R+modGj4ڜn #=?' p_A|WiGS#?,+,['Ñx%L?(/vvUk!Sf6nlF?NR4ɮl'"6D@/JaH4PRiK ХNL]:|rc}aHJ*uEX.5#s Ne$-o(N- @ !$ի.ҋ31YeI\(U/ͭ,?|0{Bu C#>>G~fLD,ٚzLqW72W^Gcn3{m/]wT#s:,,1k@l.H]|d9h\:ۅޕrLwo'\:{7#)Ꮾ.sa>+Lјǩ*F1?y|"=0lX$ rZI@IҪֳ $(Q֩z]IVD9.h\yC LHbz`MiRnE eI4+3+{P([⃏)Glfhf0.npiAQD49NGG|ozz!."#9'rIXR8>`IxjU=Eiڭ|% T<T'=V:hBj:aOQ,^`m躬˘mU-<|v콵NZHd5!Isn4+@2 14A/˵JɹĴpf1_wq0_ظE.'9a3 ns QM4) 6 q<Z"h^$9N44y e6gidDAtМ`۹]X>4FUbBqC5ZbՂy8~:';@|x\Z}x;b\}؅/Kۅy᎝.=8vPaIo,‘. oXd(AʬWޟ/'?zRkaP(>/,$*MԆ2g/>o?z[ߞZݭݫA"3,é;T`# G1<"!(Bg|kB<3?˭ҜUPi[]SowZv=EуG$38|Q0?ZEM-IRx/ N,W/UsҳR +mt b-\t 9\\2ǶjTM\b{N‰DH<1  F욦w`sjB{-w(˰"z,f*u$&jw@B#+ΐ +:a\~mwisIڬw_;Oٿ>6rairޠ)R:'^m$U(uh{vquˡpSHT;B@nQ,P02?ilqc%79}+7St5۬6Wg\zi_uxXa궛fxl89rd'N02:A0{RZY} ~6yZ<3jO\_]nZ{}_#(RUz"B+[kktftbu/ 1y#=pmAhtb0;X]Dv0swn kDr>rW$`R\-L$N$6y0Ċ(bf$)#g4 b4ow?,/c=҃#ɑȰѭ-?OOyp,Uf(Vlh$60"xyTjAlɆF^̴aڏR;|֣PeCwT"(+c:`1s2^$׮-&;6u24_c5PU[:E! `,5 + {%^ YU( mܽZXȌO $ 05*]\pyuVghU^mܜsuZh˲'ae`@E@3[>t"%FQ] c'n+MU_&g `^+2X86,W*wF|[cj;?6s/Pښ0s@ D6bٛpLјʊpc쿰ԋ_w೩ǟ{_v$"խ嵛/F+,h7< `!2KLdB~A?OHii*A'N>}1Csk$/Qdϋ*\7pw D)œFֈ(M ?~-ِ66̀k̆?nȵ[uR)SI=aâ1:Zi*64Ѷ5!ivswVcb*6+!=`픐!1BAI5@Qv<,$ QGZe%펨 >y4[$I!+Z5mN~!hhRST8si`Q:f5=x5>Y/ُ}tG lW5ŃFIdiʚ"~…'Rq~hhht8*"R1=ǰ t)?Ko,  @|J{QUehqs5ܑjkyvayqёh9rl؉S#`yeM7vSf}(ĒgN?z}'b)f0x.~ů|v߹=d+<tyH.-k-j,tDz /F IQW߻uǟ?8Y'xJaH̐k؎M6=37{#Mo$r# [G3Luwޥ7 sOG ]kjUˤ- •yY;ɉ&ґH#gD a)U+Kfty=MN>2H|mkuo}fٱ3rSdk) g_Ǔ(c" rGeieu.sꦡ /sQAعYC0 ՂX4tx8\igP4E4j^G]IovnOȅ]YqI ,bB?) # BѲ5u^*$xo:%Ӌ3B(AGӁ!d Ģ1J i|>@4nمWonvەSo!64tR(>Mǽ£sHm`uDH`K)WC!bo&9@ҽ.@`$V}[U|;M66z= {N8ɧ΍sO?gg$a"N2\e8ҜL63Rm{c+K,OJBfm l~f?ep) wlJm !:4-߯X{#l(!S(-Ǐ O7lʔOLX T^[8'KMA'"H9x0`gh*y1sND1t#04 D|$Yi4{U`B51GXB"Sсt,6snVW qq M/b~K8)dNE%:v//|#G e&DMY[*]K#=dx*wX!2#)!:ՊfZn]jw vt3R1fۓh;׊ 6DO"nk^os7\d|Imk?@vJN]ljqՐ?t}E5aS'4NH\Oyol!x GjKs>^?;&G^1'K똖|M+_ˏ?y~1x|kFqw^gX/dzCS~ϰ5t RFy`dUH1ۭ|JiWyƖݍ%‰]c}KXfyR5 ;;qxl:Hm/,އz۟ pCAsNIXIkE_< Hsy~o큎Z,)][<ͱ'CF)_>ZnfDvȹCӜ_ݮ˽KV$3.z(Rn^T𰏋S(]UQ{#DT46 m%4-jV|KBn0̀M8i"|AyBl5 6!,_ZXِ5p"30͎@ &z^mv0KncJ*;ˉ#,4O! 4ABUفԷobU!uw HXI/N>N0ܮ>G?qdx<ύ%r UX$xC혲T@۟uĩgO995yY4Jfnji =ҽ79x=4}Q"du۷rt) >/Ar#_!ɓќ&۪f/߿+uʭm(8nqB"&"ZJq!(K|^~7ZÁx4F?Gu:-%džΟƫo^"mI)=%YHEUMnW=6eXۭA8cuJxKT%*P{'?vٱ#N 2vGZ.|/g1à^iD셋~黙hׂ]-޼v!>weNKӣn8E};[qܥs/D= A-5l0i9:ȅc4vyoС'g$0Vb=_mh|=鵙@(Wj)i:=d4`7ҤdãHRQ+Ks,\X{t~_`lıN{n7)ݽbӪwUT>ʀxq*>~';qa+ +kh3>~V̎e2FPHfNZ'Bh" Fj ;"cw>zsoThvV?>Cc H{ ?vQ wx\PŹ5Y FA1(u^A"0Q@։a y <4h50:"!^j&?lTXwui\GB:nH@:,wKmT E6LG$jj(֬@@@s,#x!Jr^‰څ%ePcK!l-䭷_~?z[  H$~,<$Q8֫~W/~e>z}CUfmihr:?,D8][XA*fsm4Vh_O_|nrzYHʥBqclP"D,>:} 5y&7[hftQͯs684kt[Xr gsܽKadjح D P"ۢXS>N24[Y%B\Yj7+{[3zm=tK#KkskAD3GPNlu١`x&#,޼꩹ɓcG}!Ԑ8^lj~[lY_xrŨջ-Vd(໎>sp:>{zU ~ڹny<}cCm͙&Dd$m Xlڒ7?pnrks5ZZGgz۩"Dk Cu{rd+i*RQ+(mB3@c'sHdz^[[^ݠ/Mn٥.CxLnr䙱i&޸;KOqwܓ'NT W/Fr?<8I8 oXHΞ|C߸Xqaue h`᮪'|E,K^-Ճ?1wJ{!ʯ=TT%3zJf6jeѵ;H+{ۤee9hJ/UohJWtA~n@}mGrD 97:1|x2%O8H'2#n&2~GNt7h4r?%,GbƬ#;I],W [|8ljb89Q4˲( A A>>*vkKn޼޽F }ᰏD|p:0l/'5m+~_{o[̩'!znp=2c'F?X³s\YMdS.~O_X3߲ݫK ?kt?{wHMB{ЬJ!e@28vkh9^-y`(*=7~(Z\ۄ7 G?=IVR(>bvpnjH&i%`fHժ§dzxbۭAS ܞ5<|<9t衣fMyӏ_2ihoIK d_ȳ@19IO EZJXD axPqlˋs4t/"4Pb6-vAH}YxpJ PKDbce>>S-em+CP%PLqni;5R\yr"{ [3cGs>y||n? Ý=PT&'o}=GO9xd_:3Kpdi+&F5(btV^fK~WjZ٘D2iVS,AVUG24&ШYo 5Pu<Ram.p{J,$8Bd |SWS[ˢvWVRΎx[[^>u9) ۃ[Q4KL@a 70e , . Dx檿[O~O~~+a3A4g^-n,޽u+7f碩\ΐ5 "'/D+ϰM2-2u,Ņ]Ǟ<۟|{*GF4u٩}~FrOW$o--L9}ͩFlaz ? B[[3Oa΅j}хəw],]/]z/t㉻W/ ,ugi~Xj-^`\vg`#g>D'[,3BxPZhy? tJmߤ8]]N/]PHbmCA:xa`OD&)[򒦨}G<ː(hs ]eBgy&ce[ϵuy[f'9|岩+o潻kLQ0h*z!o _p oRpJ{CpتwT{pba|sc/x/TeS?[Z7;QUyPV b+㍺6pŻ$GG:LC3ZBlnЬR{Vʃs"8jm)K M(ev|tP㪮k nzJ e)+8oP "tEsZ̀{,6p%[vyVL5*ypV!iV-(v/10=5;n:(8ѕRUsD4UV8@M *2#Q/DR72&S8Q :pp;|1ao9p siBì M;7j'3@ޑ{3I]f|C[ނ7ܬAa%Al@ =)r&i؜$}Zr.O.5MolYuBaSW+t1'x!XBU9+Vtnri<'{F Գ퍅{zixP6@jt_iNw^ÙJAmIjqW\Dc]MCr$  4;fh+\hOZ]/ QAP?,9;7乳spjmq1HR޲P_ J ֧zW(ܴmgd}hKnܘ3ߎґSc'5F;y}n9=|GJܣ=8m^{xV\Z}SA?}inn3by Å4#TD7%ܭEGZH4ܬ U )Nnj)@KR9nsiWj9֥CN,΄MoAWq ABR=Y ۘ\ MT \|ñ7eiswlmq}>t=B/~ɃQ-j5w4H5`s!yPɞc늱Org+zc|"ڷ"ܒ4 TڂWf@j3(B4 д 1_$#L9 C(-U>C?\[wd@esc7( ]P{1l=q#,Kܹ]W+6J$ä.ǖ#;,b3/E#=#=٭\,YJDgkܭ"}|!_)>sg+<_yNo@@+b|%N(h ok1ZCvgpkfV 86@-e ;R"aJ%خJ/1î:mw8.٘IOӥ)|Z7Ul&?:FOIRҫ[sg5NG¡tf$ K++n-,ժpg2Ӆ0G[oFbꘁA%UP}@1ց? !^[U\3uwz? \6`HHࠛ/RBK3\@DC ,pvRNj|bmu-Vd˗Ex $ZTBz\=87rԚm-ߚ4?}m쑮Gua#\69q%:N}8vkF#_w̃=7oۗ/uxiÍFٟ|;9?J \p_9U1o;D.-rl*dSB"tLRxGjK/;@`IS/ѡ+ѓ||m>,B;@G3 + Q4=Nja6DZRYxaɺѠ^G(aU!C+aL?Y +7t^˥;^wON{¸@ xcFr!هFM0pA# dQh+hǴwd3;ph/.^G4*0dXHuQiAph!0La]$-'̄>^ϕF?ȹt EDTmo̵v*B5H/$j @:(jʉE(tV8R(daɅzb~ ʍMW=]<#G\R"e9J,Ln31Q(ihYl yP75HOgXs(LCj9AD39! R+5v=q{L1pUrtd"H4) 3.HBetSaыatM75!][*'pU/q A +S;y ugp_|c#YZu3u{]mH7P,L[ZkHkxh@>?B n+ɫד[>:}7߾ƏgD /=ZtzIoQY>}gԪe-i67۫ʟ~l & Mi l!_'?4C$>>:\uZ)9x Wc CeYAWLEuC2.gdu#JigkiY ՑC_ۜ}ĴEuQa;[!^UQFx^,H*l ԕ\voKt"%P p؞s9?䷉uY[z+hng||99=tUMWu|D6}}c?(꒫30uCAMjwiJOʃv)[Ij:nE5iĈ?zGz#?}ٕt.]v7c @/m&"QR-EYhfb4+7UiP#i* 4B`z8?vOw8$m –,G)sr W4vxxwDχLܜwzX*k}uu5{ߌ;?o89|,ܸ}D6+JMyU=OY`>C ?s/ ,DztkN)*$.;sI)bjM^xr6l[ZYWadYE; yc׮uS$.QX_J8aԋ&#бjID)=ب[KDc.yj?`Knǎ̿qo=>`'Bhݐ($ng6jr2M)%EcaҨf`f ]Md(PcX%w zDNeh@##GH /Js|$Z\y}[^w-oݬZ[LF]nE t#>uecO^^?"e \TꝃìM j$%obK+ZII`5"wo-K %8]S+$tQ `riRO|^ Xc\z!JzmhPte;ڊVb(w{޹5sfsS۹{NcS4S륩o]RQbp#?L)7_3=y;K[ @xdaJ@# -ġv b氵A@}oҨ[%sO~tރ,Ú [()Wo]uuK'|O Vʅ ղ~xR/bt4z& 2 9RJ Ltn'HH|%kvǕrV)+v7f;_htwƗcLVU2mgN7͛ׯ\*pCCG^ͷ^Ϲ]}xᶞ^_~^V9v{]Vn?oW{qu⏾SIh_ؐ.[/%nz=MbR ]sQi]38z ĒzG8K 6ȆjTSZ' 8[r6!8ֲ5nVLCxnow_lVnԘЈ^(elFY 3[f%t8W&NX,퉄IZ\+ I1<;o%߸tސEÄI4}} ]0]x'R``)#<=Bvz0T u7Bº t4,S#x+ VnM{5)ai.2/W˅S'VHq{ rxp_sEq v*Է:8=~!_=x:) .(h=Zd%ߖO'Yђ\^N--L l ]as}$)6'YMj\%ׁ=+T_RL ;w֠-:r|TC(V8ܭ7*:mr Tj&tg  ty).ͷ& w Q"Kt0@TT\`A]3A$ 940C[hF(i;J:|"aN| 4 JH~Pi,,.LO믾|pRSlmL^|{z`C;yFhoܥTf;r'no eŗ{헞gPHwGMW*nntzSOW^ x\n ș?u$-I-K`:Xyˡʪ!kcJ6)Tbr,BTxVJ 9{!WEf ܠ8 :W7/wn߹73;r^Ykmi 9|$KRr wVp(J%gsEg9'hs|O8pO\.l%Do^i44Q evΦv7L 2p7I6 ME O _ma=ܸK xd_s4B/M#Sb=]YX$k`4AJ)Idzruib+HFףޞ@g:K&mʩԊEÇZ½\zᱷD:io,m-C 7w[g}C梅/bt=!Q)>}7)^C(_[Ur*۠+"v#tN8_.UM4 ;NhsrYfx*Z/#=*o.Y</ߺH-:Nmtv;#=ʽ;&htI)"tE0bM ih5)(afvY(6 -TMVBտ;[j{T>#9U rpzvgt |k,-CۼPPF`Ml{kB)U$4 cTV`G$@B.d<L5仭8Q5~/Ocveۮ\|oP//}伢^~Is=m>_`3.XHNx :[$I/O_yUv=V H0>_R=+V)8 ~>72%|XSn/)ԉH&&:+fɍYd[F|K^L|^v:(тGQ9&'rJ7/]/ Gܽ;n<υZGiڪ֪fZ*^-iIMQ`nDէD6Rޮ}G:ɩza)%^߰L72 0`VM![F`)rbWƶTH2D`6dYXeM5Os=qNF5Y2Mx7@ -d/ko"cL:i ?Zm 9ۗ^ȗӾ`U!P*7E3 d\@e*ATkw'l G߉'~iur*vtMŷht;;AɊ,ТWm.hfZ< btf)W]U@ {SY_<@g$0 RSRF1UK{+ӓ:|tXͦ=^g"ls iӬlO~.wׯ^Amk+we=n& ȢRp~ʥ=(FH@$HƱ4"%[ttG|U T|B3Q$Kp[^›'z~?8VF >΋?3OxTt,ǹk,]n-oʀQ@83#.PkUUI8y)t "]{]"@F4RHx ZaG>3 Mx` vQ8Q6xo888#J|* \RaJE,.kt;^`F3|f+9^8yVZ; a⊛> ?MZ}ǶȦ?K./ȋxTP$5E!B6mґ(jSR(x ~x9NL^w8侁!\:2.7tC҂Wa`%VWuėE{{A hڔF- w3Sz4pM BO(GSkł`Q}D0WLm֕'^#Iz>?1Ն>s>赻]{@w{'?wV Ś䰇nmx"1ZG'lH ズ2 n:hI/ ^mPفZ+VNbZk8w`pߩH{RdK9dvhV[G`@Kx& !Yҵ75PA/N͵z]5ҁ8⡮ky֕ynҕLi6WȾƳ_|e&_(Qr.x_{7: wԫ//ܹ ҉yuz}K+soOuEB׻ A r:PTP5OvhCgpVZ9<D88;˸E[t$$Gnw}{NDw&[DNCSʦCʊ:Q4} ZLUj5kj\W =ᰧBRkJj kOPt:ΉuVx$APs9)HI]. eXMڒB]8\tpMq6:2B&j=:z؂9~8Wb=` _fcvv8; ~[+עuB!nsn%95YqseNSo[m$pH65!pR|uAt8}j>Yu\̲17Vj'4rm4nibρ<'1vyZ*q<ȕb<-v R&hT-J!g'6 yz'ZT]Aꑾ!tBWܞ{]ήt =xCF5 D-f [+,"Col@D ;c3;ԷQ.psttNxV(tK Ԗ u#"5b]1`xJVSMwl隄}T [#pkrkt3g]-DԁdP4JjJY,dB?jŒj hQwnwZ$K֡}_uQP0C>kX:z8Iv4!7P %- 0HAJbg}2* ~@) FC+?s d˖@k -TF:0ibEGT' UӰ'IH{`Ow?=gHw4fH (]֙PD[S_ŶXL }J6|srAi89NܥB2wQwXH.t CN`xISm,߾vl={C%8f9 B ^ J^M2w鉘FtiKvGY b$p'b=°iCo qО D[4:hdȶN"섧)]B32pAja<0HDHΔD&DzZǃ .+RX2IXH*k ÿ#0rTE/!mgϼ?|QJ>53ƁO5ecDt8{lq{3]@^Ш6ގp@%ZZiTU/> N.B0sjv%k@(S7fqsN,nOCTMjEӫ=|@3Xn-'5(aM%dE΋Ͻ˗h#09#L>{gɻ'7 MR`|KxF}A+\:CY l ݅kó:d~Fb Mȭb$6m`sqpؠi9Zn2 'TZcO9Fh-LFݗ^|A22@" Ʈ--Ĵ KO6_io7fsA#h(NDj̈́TF%܁Q+ R7,ń4ܽ%5MΐD4 ZXp,1pI;t2vD$` (C6h.YM _`䁍оPفMIiG>;[AbH6Ւ\gغɱ+ҨF"|1KFl,^;vh_o}}j[^mM<42Uj~ QٔeHҚdo/\\e6fӛxk.PX[yg d)8?D*h-]d4nckP$֬&yzCh$P)gxMQC )ޑhZlY(M{+֦ NvVZKws٬? 0c\av|4ΎMa#mC^*={ w vgm U?x]/6;j*EjNNQ7 M-Y{'_H1&[G{Gs;U)9r1';mNP.N\N6fn:W k? ߾=gAu'nd6wzHô`> ,e5'6H^| axdd?6( 9.- N##cg½[3ֳ D eQpi9e#T4:i( >t2FK{&)E N4Q1D.W},,6YR%f0?`ى,rm0Φf"xF2"ω"@%)'-mwniBN,dP:!dp,p Mc<HE`@ܨ;BJ6Nz բ@KH66'9tvM0WVިsrhn'cQ9ǢR;͹˦ J0I$fE0UH@OJ&r<8aVp|bQUծ_r5 &@Ѧ6hv=1q "4t2w7avw:lU ]Z4 @hGꨆE6hl4!;hA8Pwk РgxԥzimZ.rQEWb;d9^b1eЌ'/*t*psp™*piW5Y7I8T+2o^kH>ٻVH67,v«8G;<~X!A 3$Syh( S7y<~íJ:X l^G;3pԊ+^}߾Yo Mxh:b{&ͫgBS XHN#N m &lC˒!-( 6@-TNٙ?M!l2W76bZB dm,M,z?x0F(QRDSW857Qq+wO(u%`? x~wXa1!jp :06Ad&*í( t .ׅFu"(_wH#D~!X_nv~c!ho#0 [CP ?V$(I{ oeAVU!/hJ.3M-5 q>  /H,>Q A,H4`l4Ref d$'9KBz'M$%˥L|5dH9O&8 pBUV(CvZwKn ; ﰻA)hrAfu]#?g+;PT\ȕzd3 ,ů5Ѱ՚5@Q6o_8>?SbKՔk r0oa1; #T7";޵1] u*)W{wRΞla6\126kpP孕y-hcZF9]. #,IԶ\)&]I ܡ"*||=$7C)w.1 6'2l)N gQfD\MDHW& ŢrF&.;O{vwuuv . O?~ i"NrÁ &8#u֧ xCf!vf^@^D#;@Eh{$!EN(m57L9[LO/ӌdkgs/EHB(:i& 8/ZrBDF&\\,ʴaPXfs- F,doUW^Ʊ-P}#6+(H<9 8 a /AyB-Jgr " 1P:C4} U%,xfbw@DXA5i63S J4BSHB X];ʠi&#F莀 br֪wWH]v 𼧡TR'B1@H+"V :i&ZD0 ݭ6QO;,^s^r`L45]ٜ 6PY9_zg)8`b>ZpX-b hZjpG+), 5(VU075B @*)L&S%v 4G>5 }tb\5hH@BI1I>9vuv @d*E}-}ம,Mt$ `B5ndq=+ jD//ڬ'xt}ZC(ʥ8*e8U8X"b #6(b.!` g75;KmӒBtz|/e]j6Tb~yq*b+g1bP[CC篾O?_zb`zܼa9 {Ʈ@# D뷖4j!&,(LTDL;Ơ' ^V,ײ+1jRsTM6P}Pgy{0t"8pAwbހdߨ)W^u:*L@hI;S[\4n0A#QXM2Vq=t/CدʙǦNllleIMq jkECoip hPF X2Hc gDD:HA&Ԡ}03G iPj!h1oY,hWi[blN@ n qjusu^Ѵa޴zN+*, ꉢH 6cs6KJ.[C3D>7ǚRD@s:(JHWAt:zfoCf`5'9J2`TUp{{g8nT05\M UA}U42$^ՄW `ef7Tn| ۲HBD~ E`}bF r93=9UmtttV cNP̀{%G%;d=.j+yAɥ!"=`o9V(-M-$ie-#l퓫)UڼGXK4R)ۧT2kÇO;H_)vᙟ]XLfj] |-~Mpd ;Lc)x-p¢#NjME*a:@,ƔjWFK |0|oI\PM!C B?FRP%$;]r*^{g>\ki8t"iCA?)Z UϷ/x??GIDxITy%(pbzP1+ @ǻRS*v-!ϩccOxE6[8 lde YMYjEXc6ʴ*ժ+yZ^Ռ{tRKV 9USED0^1 (Y((JHm5eRx^ʚ,9#@a9sN*HKmU-*r3‘R1 ?"؀׉X,{W9m*N:wt>9V5TTjrZm4žG?vv@yU8bQۡG)p"G}Qk"wONh>" bw5 10CpGL@? Ñ|'L~jz-zmh_בOq wI߻ 6CY_%gJOY\j{DmdgZJonR;l/:bl4V4X[MDnf P! Z i5hYO gh lo+ 0a0,1 1Prl٨.A3Ǟ>_{ɅBfڳ=z-ʆyЉz-9~z*|~XZ̆f }:Wl@R-HyQo`FW{?C8IA-$jX팞3 IU:HA8Ӡ%3oYvE-5Llͺ j|cGS뾰r:;Jr\hNe݀TQJv +T|Q5tv[QWJ)(Fh xS@ VK>Ky!ҫu^cD` e] GYZ\I 31" T lXT-Oy_8{C6:~cC}*eIUй&rP#Mhw*r'O1d ,}2np T#8>=\u1ʇ;lXy{+ذR5'MͥԹ 5nnr|KRT.\~6sGϪk7Em1bJպ^-doe˳$%ϴ!a9Vݐ - (+P1hHG(7? T"*zBC(ywŁ/y4X.qqKgl\2[@CAuݲ@L:cM7۴k@W@M }w :UE≵$]8%LO͜8;Pvx [2=}L4FÛ윿xйUTH/I81/$6 x:MFxj壒 0pT+ׂ烚ԂmWDZ7%2muK":UK _rm_H&jMD("/HMzx^r!R^)2qW-jb^-*+;ryyjrFR>VeAZ AVdmXCtͦgj}qV.EAQ"C&JDYkT ܊ ɡxLdRUoFR}kyg_093\we#7|#5Ad5mh<)p~!b T"mfaiiDS Aq$O#gWNH% C2|;ɉNw}N gDzف3%.zM? x_= HsǞ-OkƓPz; -ukփ{7͏?Pw#<64:+gNmb86<Үc+ٵ-NN8j(HT<-:dy*v:Yu YҸn8ٞl\Vƒ޾nàagnClھk!-,%?~Ͻ7_{=[c/eu\~qy6k\mKuhQR>%U8w; ]RB?9:pA^+ =k7P&v6,LL-Ƈy]i{$?kݮ ӞFZ$T0BI-c1-M6śG}\9jk./zy˾/9g sO<̳ϽtHv(rp{,ť}dVqQ (7DYe5]?/tc1Whn3tΎo|[w{zx06mޱ}ú~sWr[|;f?_{']߼a4|ruI5؅o(()s.^_u1YݺymE%}>ɣS~gMߡkolkiS{DIAF 8XH$v^ 1K=v! pDH[G?w;7~/Os{ؽ_XoC/o~~2mTlbvaik>.Xs e:r|ǝSXTI:3I' )pyfAIdڷr+;-!(<8>^#<2QģG6Btٴ Q|vN Ŷv`|mkwW^1ySS[ l^{{覿ؾyރ/9911U)I umPVcUjhz0;?Wy33Gϔ*徾Ξ DJmp=;-LЩ=OF_}SX> ĵu ['!=婉sTopYwO_^Dz{74G5Pї~oǟ<<|qV YT,6nMiض sR5ctLpVׯw\śۺ̿?>sֶ rKraܹɊ xͭݝ-yzEϓπm(jPX9$pF="GXlLvib)Oe5RU_B6ܳsǶޖ_~|pہɞvs K \QB12HA_2#1dÊ|F2(pҖy*zըJ?=ΝE6MK/ 8--]m}-]SLk*?xS7\@DK֑&C!PFQG$٦&>I(2#ENJ2$ ry4Y{s|Wr4Nu\NRhR U֖\EФg?7>^,VmַʪRa B䱞$)ȴ<.N"ܷМoZs#''}3OxqbY7-DO*t]e 9>ӱكn׿3pJ(ҵ{pw<O3J؉SEIha-D1%WVi%!*[a]j31:Ϝ=915+NevˮKDf۾ s3 ܺ \H25|¶ξ -h*Ք'sSS埾<ƩB,ؔlM&S>.0T>hXm54b&ݨ-,۳w_>O~_N,%² 0:qȩ־=0Պ7tܱcνwn'?mö g(d\9iZ5{R^(YRAc*C4 HvT68a eeq OJZw!WCn\z9_(s^)j{'?•޾+{N .s\Ω ɁѕF|(xADG5BYfm2A,$Y%J8dVu-\:B8>D)nw]s r{s+&?6azf]7WD_6s!=De<xm 54 >CXpEAd+^U^>F(f"SjOgnʹ""gI8@5(*O>3F׼TJ}0iaXF\i" [!HqsYOV`-|IF,CY7 qj h JF~e#ɸK'#d9L[lUT.3]m*w⩕+3ˑxqƅxWAQWp @;ca4ӂx pd3y@U*=*bq]!H)Vc0ԁZTM$iKtX)i5MxdG:EP9ȇ'X_\rJmen%[UjZ^."R12I0q@a9T*];:gg]Hv}ŬGݒ \`e6f BI> k3` iGݹZ:p dIFlPb-w_=ѓ8o{/?~t<hooտË+,]}~KMy5[[[\CLs{k;~׎9660︬/*E CGsj+xlzt, Rn0JXΦyM?|nbɣ\:3q2+Fˎ B=kTKK:dxйcTGO ^8w,ѷa%/oɚ~*ݤ)"'R:IZ06|JQ /Ho$T53BWLkP5ܰeC[wGGutR -0*UulÒ iU9 &X,2虄\>BB0Q\lau*LP#67Q+ۨs.㎍,~_!oLy9>Q j,cPF1\Ci'zHGb#=z1/Tg HrYd(H,"}"X6YUߪxyZP=BT`56 2`=29 ӭҭ1RlJyP?*bO$@$XJ%sR\Ÿ,`#U,rd~ U(DE󈆂GLHbt̸bDAxFq2b.If~S'\*eE\LC pWܴaӗdBm+l޲~. m!|dc㶉E#K+> ?1so❤kpt$GX1:a7jg*,?0F06Oصōet0=V/=[-Noj fnU-:yq~3~ߏ{9YrWT~JSS)h$Lk[WR(ji^^GsxWWlb| ]]Dl˪Ug$(( EyU1-~h4",N#dKJ\$#TKźnKFrxIQ5keN̩0=?yaeyٴ-8]kwRj=;%BuqR c}U_מ|7MEӱp8e點MxErR%dqJbV'ܒx2E1H2:'ʚi3Pg ѱfCW %hEyDMz( vzfa%8N䇨) 8Upe ѥb L*L_\^)vw뽌 ښ]u𝷿몫~S+-ټ0u8S05G}m{FqI Yt,.ۺZmJ>? R8%γ\\G-/Mk\.Lֽqw{w]Oz="=BЋPR=TdiwwYisoG+ ᱉|"Jb4Mk3 {c:0ƉNKۋK+[`GƆ<2+ E^XP( uQ>Qj ]!K3sҵvk8!j^Swj^:Ḏ!#+Gt@4PD"bjD3Z`@rtv@_-+(pnɫ +t#%z3DGVɂiZٙxD %H U4wqremHM|dч;ۻfK+|ud|\ ُudN$^A~CܕBDrƤ~@.>.QDU4 5rhPJ Geu3䂀6CFF|%?OZn`ˇFz $Yq T?tn艑Z@0*c[/b2?OVۨDϼP72㨌@aZ],O}zƮ-fGVemC3gK_9O tC1v=x=CĐnl-vMD jpIJ ti d2Isb^- ^DCZ$y7{6 :up4ϴ4̢թ7fgDs4bgpjqm^J˹3gͺ*~OO ~o2vQ7n4':prs ڶq%C-ݢj5DЩ0]x.-d(\+f7RÂ}b'.D} ~mk쁱 c['U +ܬ K/ zE-vmz$ pꈊZ! "KWH78i;dM@j8L o!bF"Z(Z$CW{ܳyփCꉷVp(L?XvUo~R-Pb]D>'\@T`:K\iۓ|W6⸆(rT 5{ _qî0 BL Oy 5];8rA`֖ @bT |"d\Ԗȋr<3ϥ_(G&Gϟ*#jzM-mt{Bಝ*~rHcWN$dp0,qKQe2$ ˤڹDMH,sf +P`cTux^~Ukm7R$Z[FF'L3U#jTJ!|Z!8Q֠D7bMmD5ƦiQrFb'lZ(H;l QA. QyIF;fٷ )T4plL\ם:=}Rq1M%mADbȆ={ȩ :n8~\/!U)rk Yc.񷞟9Nbj8 DJHJYR+sz o{֭^xjhrްL̑,/94PwyWU|^/L^К2L2RQ qRT3@WM}m:aA Q*Tя;ܼe+\rT^.WsϰăǣF/8HI?V; ClsV!;cԫd^utgG~d1@ #a]S]tAB+yǸ$2!UuϷ#^&Eji$θ%P@!:k.zԾ}sӾeczX|,f8X*!2rX$'8B$^t 2ӭ>!NԠJ-;IpmrOZnct5Y#eP x!lj!,+l1+Koc 3c#"Md!( ؎s kga.>*) U'ΞЍB,2ʋg^%S 7̈d (X[/*-+upD<掵R(0s"!^'2j5,Ȓշ+< Wr'wzGkWOlk]=[oVg[*պeY,$XM2QA|,ƄX`GQt@}1#J`Ao,ю  -d9 UNPpAI׫ebJ(*酅hGSB?ٓGRmwo0٩ F3Kci%ÑDBr4qt_ GҺ^+Lߴ;@"ԼZMF5..OתUV=ѿ^6>JA\H EDO=+υ${XC_ʼnӡ&eyrjbM;GG'FGg/wy>|>?yMnlݶ馛n@i. IBXH$E.lA\"MN*()™TeCrObnO̎]UšgPS82 $^@ g*X4iW$U_٨X]hKIjنUѩ;QITmR)k@:p=EeXlHyCIq[d/a }#qW94!jd"cejZX Ο~ݪ.۽+_(.V:TTJ$.J\yiјdЄ~GD$ƣOfqHRO8‘#BH*"57Pr7Gs$C]Ț'8oG8m;_(u>oś˃{GHb4pPS pKwr6?v|}]♓yîWC=xTz&4JHW[O. /'H"-J,/kxks-OChꁷqvt{vavb7VA xI %3pw^qLYr.ܾ~?|vy촩A{v_NgNZ)C!`CtiPqG]^(4']h2&D%}kt k("Dd'B g=x苚/ՊӜ"GvH"P]YԵq*r$;[{=TWYG/N_~ȦRW7,D55 ;=2>sr;&Bxy^&ξ| |ϚnV*W%EMdCWxd6'P2D5/QeYHAB\"c@*%4BWY,A\-dgz[/=UezS-z,(PږgY5krؘ"K6\96KC27?Ƒx"f$1< ^JP(j@\K\ҋ+f%`mJ X̴UiÌcQ'v=}'?]{t񼛟㍒o t03$A%"J+%;ę1ZH!JwLzЃ7tRg,X::&END:S9숥*L].=q;66ҫě"&^$ڢEY| "` ֆ@ (3)۫&QgxZE-Z<}wR6oѬ(X8fZ$M[<pm{6xiy4nt ['!GZ~qyd$֣ڛڛvukoޞb8|@dx}mƅ!uH5pjN'YW{࿋,y`W%JMe29g7=;~[c|ȫ=Hk<;u jW|&AJk6IQ cJgdݨ©4 izߎ(:f5 XĮWma-ZR~,T{9Oh4$ML0[T9/M]0t;?m'~o'g$-X5^fv\{KǓ?>^xc͎xw:_)Vfo׿n= -~;5KG.vu4W SËc=݃FL.ۨU%9oU)L$Z-8^MQ%Aʁ'y %3l:TsTZ\X(*9ADH㗏v[}wx.ϣ O Ql[gM[q&"_GL)*OQbX5Kmi77Eݝ(: Y7Z@/}(2 OUcBvVx%cT+]Yt􉇺Cob`jf(r}E,ЃgsDph;"'HZZ];=s4385uRLAVӮt**+h<Ϸ )J#d6Qb_N=~H䁛B8Y˲V 㞷_FWWibЦV!jVq.uz8Qrb_1Uc‹E7 kqu]>]w[wX_7^-E)Z>";w BЭU-3$xVo[ +)Z>r|&V^.z]G ٮU˴C8.󬤕hI]0h|og]IJCŁe?Goz?{nTO.,/4ቭB.~~şFmɱtF[?Ow go~9YRS R Ngܳf۷Crs/H?#MX̸ #dPvjTJz=57<9InޯhWQ_%g!n9}ۢo&Nn;%Du0U9bMcqr'U6tP0B5W. ,e4IJ[%F')q4aѶ]0b@H:F/~C@ ?1h\I>U I~8}Bm~o{ɱ=Ls}^ŏWQ{c- *)lL m1 #av`EZf8`!cw<'(iV._p<HBx\moZUJO,MmJ f '+*>D 6]`@|a| _|޻޼}|;3)N!KrZ/C[vDa(??k3l!\2[쯞zFL$e)a dMVQ(8Pڶ)?M- H9=\ DĦk,mY]Պ#Iq  ,’(uucegOnQͯ7 ŌJJRBڒܹ42)+EmCm`;3' d9-V%x,[|)K|MI.HK2[EMF.RVSDNKJrBDI|~vh=k'N/_=ZᮽץkuҦ(KU-=-G L}}zev+*wצx Q&R~}c#-8\UDn$$$in >p!g͠*Ee5{u_ 34:Y-Bso#NY_Z( yAGSmߧγr|7W KyN~͓ȉ&7;p^-8x)hYV;SJJvd^)R @R5 eAϱ=ӅnݼxkФ9f `sKp ǰ$C?zkV^cEQ"0Ja;[ l蘞F0,D'*5 eS4Xq+pQ,܂Ed6>٠zxXhwzkxG?~癟:9sbGW^;+]OSB’ Wz][f ƥ}w;Gò4-4ڎiG>mfspX_1VAs:G9#7Iɸ20ntk~R8>2e]^鵋C4jk_7;d6KQwQ  R_d"Bst/}'H}F ]6A!AÂ2LC-$ﱼm0(^h@$LӭW2!o-]Olw^ܩgd-ҡ ?}o~|0>Rl7Pdqd͵fDb^ɥtY[r&dLIRA5Vr*30^J:hgqJ@6-Lѩϟ!I@x@ .jMx6+ShWUsc]H&xIDYy8`Z/n94%,. pdS88¯(n8Bu7-TdkPFL9]t{>96f&G1VX`bȧPCfcx8Aߴ<ׄdW{:%BB wYmSlh"h؆e\a"F/_?w6Va8Yݘ?=Ct{Q',|BLɉt* _;@.nM2J1j0s^_>Ow KUSl!#X&Tʅ4j\<}]J @ā%C;CSٔ%2BR$ CE0\{DIYP* nTD  ۉ8 oQsD~`V;H#n<83]]2>mhd(@2Y=IP(ىitx:~ ZNT5<'PIB㺄D;:΀2&Nozm!l֖%u6m9D! iqsE k N@Ԅ͜>COE}߾񝷿twܞeff-'U Ktm@uU49XMXuaW ؜fA1Ûq1~ڮş9pȧS!UJl>SWOɉ)j+ 7AREG,uP=E>7`TaX~,ɪbs";No`hGz`^\N8zѝkkե{3_=ə+۟WKfF@؂ȉƼȫ'ހ!Dʌ>TaL<Gsrj@H4NDo@Ũk0H2ѭrKف4qq'2Vht \i+t PM!HDⶾ"L`5A=l`]y>2LL瀶ae- 7[V%[iX_h:SY^쥡ɽš/ C㯾ړ?#=X@ԩO_NJZC\7(% 5l r|_jEXC8Q)o^r'@4>DfuAo֍n˵L1JC;ӧ7l60>B'+mYUB+RJ٪5V6-7֮,C c:v'zPp< H*aXsRiJ#?C= G6C}2rkr2Ë fܡ7],3*pRXmԗ"R ȭUI ӁpXɷa'Y=;}ꉧ[rX= p[h<2n k) dA=F.SV}GBqgx4b0QoJ;7u(^z/@ώvq dRjzöa 8&ȏeWbjgN Tf|6xB*Sv[r1$jJv Nb ] l,kXT5Ϻn,^~u<+^# &G0FGُAA]{'젚.Ν}vuwO콹p6ZVx뻺AtFmMZJƗ>jwhpDUx׶T{!i!Qf3R7#At Ws-s7} +}*VNnױu%Mj!f3 LUIGlR Gf99^5U97r<в!RJBJϨ/^uzvlA`ye\kTW\5-wlLe4a9 _W9|̏Ad#lRHRRPDHEHΜ)5ɖ\` рS6_YO^m %cp0Heں^jR 2!2HFu Ev$IV"<%YUa[s46.DHԦx Ghcӭ*dpf zȫ̧>ާ,܋R `J+9AfyEn\?eCnޮV!A92u5vk]HQzZ )$VyZ C! /*]uĐd^IRT8s셱nB6"oXcgXF㚮,pC۵cmݳ뀔_plmRvrz{rmN~7Vmmc2ˉ^Ke X?岉\^Y\[ɕƁbiBKU@jkl02h!hR*#O#ӇÊn)k9@0KcX(RrJͳ-"v#.H2Jͱ=Nd9uܺ47*}Ǟ~ydEv0Vb( ?Z)!' A0\=tyǻޓ\[t)*/+kW!WE /rԨ7Bq2:j(d&Zt]5,a}8H0u%{A,no5{GtXXvP:ַ^#p!{G:ynքώAI=n{NJ.jRwo&G -Ͻpcܺ{.p^y^x~qy CBj>)b)4[06i2(9;W  ! "-tM!B.д뀫 Bʄ h*[vԊEQ4%Z jk+B!30._Yfm!pՆl@6ŊN7ԛvwU$3fe)SedRpfٕIB4\#Ktm9́r9U*!HL+ʒ >R))"ñ *Z!jNkY? U~ |Fmc8dz}J7ݒ*3_FBJ[4KF=hH:)K{4Z,W50GXU*V -(Gq : hbG KCS7M޽ۮ喤ZtZL 3KgŽ7ra8ٽNm)p]-3J{ʵ|NM-">L>w!Vf Z`v6 H;U>cP ޠēWBVd8974"k(CLe7D5s6 1uO쑖KTy*\5&s#ž^zg*͐,wFM9vo p~Sab#BvEEݾ~КdĂqL Hdr75g&[}Gn)4LR 7m#oÅY0RY<66BhCUpr{5׵x Pr(m0a=/yY̋V Piv iln<Ҫ?ޏϬv@NdѼVf`J^v}nlUmgO]:v%(\%$ٛ?G?ϼB0EPZ؜)oUVM4^gC2J_PqGO! <}fH M+Y E+]bPN(J(záq^c(FKOC-G=$vAɋl$4`RT^KjN{ZH@޼3.S&sа"P.] m`X+ 9jB'iEUC-A!> _DARXUQ@.>&'>RѦ݃՛Li<ϵf1<2^B ƚo[&ܥsZ:[ھ#'N瞝@ջ>_ٵBdBBr^Squ3nOb4<+)}q?jgilyt󐞠NrM^&Lq?vߝJJc$k/>+{o-J Ù`4Dj֪-vn,/g2j6k69 8)luX{)U{sV]PR_&qEq R<Ij햙<{wOm.q ),ŵpD#x,axVNnzb|#glD +8&+zr4&5 (006C! ${gxGQ2[M3XFMk{}QE_(UN|OXlArCCo;6Z(إ/sKͶ+pVM(H֗_>fwe÷p~?aMԅcFl2Zq{nd3h@`Go+3ng8l׀ocMЄ,386)͈T׃7PR(!ū 7BBˎ5ʉɴ*( s\BRXyoT]^4lvDnt-$iJ$ )[* A!{GaT$m,dCGO =t o6dSlH"L UYYRԕSɽm:{yhޛy4:RV'͖-.-J#O;j(pKZ ň_#.ܟQqz,Å4M$6"EkYau}O|c<vo3t|.ȕFǧH>at6Nm7z"Rpv}PH f+ gϼp Lr hwxAPJs•ƶ) i+ʚpeBaܾ BM&۳3 kbX.rbJce޳b)6r0"'DWu`Oc?2rK|j^]a~~gq!p.s"| 8ۨ7eU~oO};DMs\ݪUz 놖)P#-]SRhӂ(dv}E`Bvpj]eE8xllҁep7ABVøyF8=tM !ċ] DKElE ~{Ѡ -8bL\ሯb%XHMVۦ?O|VHuMgڪ֛ad L>](OQ<ߩV̖iN|܅Ne,A3\"?:jnQٕkBЛtd9%J 0 ;R"[0kw#{oz r_s>/& -JFIj KXFϾve0H'wz2{ w< oO`@3!/ 7\BO'^8Inw]qx莃[F1:Fkty0W.>"eH֯T8mPOR| @L/ k{caM~YnY]^)4 K8FݨՇʅ?}+[.-.\-dEWxʚnu!2lRT2Q!1s*)*Pk DUgDil*A+jP@w`;2Asyf!HdԛT00./-[}ᇗ:o| St3Z6ܩ,Mm f r޺xB݄whD*+|.?}ʟ߭u -%RX )b%> >bKXjQWDœ3g bXMO-0RR|Yd89Z>d.vDx\d5cNhv2vr]_lsrޝ[ G"׸@tS(A;k:`成 V s:KGeڪld29^;U䎥k8u׾Gꎻ;^8{wOOG`+@Q!)@MM(y:F' Q,6CorxНOϰB,]ALZYj]oyxH ~/37zxBkNQM!-!Z]l %U@u/BM}jmRS SF ѦpC@]dlȋMiOC.w!`U Iseं"3<%XF/ނ ´fu=tեS'Rjsf8x-mcoK1;ޏ~4?򽿿z挚9{y{{Qo sTO:$CG{B)EBixtC灣ZćN褬'dIYV"2̫M?Ӆ,;L?갯Z+InAlصYNB,- qk+fJpVSdb#Z.aVOg3l(ԛpa*.#:Ɏ)ޫ˅Y6ۃ5ɴfKo6IJ44js!I z4eekՍ0 qxɏ"M `j@ 2 vkW/<%dhE}4Z[^V5_Ҟ]{P0I)^Zכ /m))AN %u, "o x xAX{}][5CX"C"O-IFRL)=_SfZ{o7P=WO7@TY gwLҤPYo_]_[L"bd / ?ϊ}zADxx?c&M_FTo*lI?̈́7m@c߆xEuh|zx$˫!ӹB 蚶&"eZ399S@{jɐBnJ~8īvZ] bsufԙ3[l&Q˸#IJ0T_7ֻ$4TU U"dxϙoj%;b0B+τ`% /2U@"r l F/B<#[h]sӻwY? 3Ynֻ^>{٦''r4V.{g4ڐLb*C7WvT`r2$I*uKdOY)V;⣥{K'Įeϋ|INqەeˑ)pAŅ؀ D^߄/p$V#jB!]u=< +A- N[iNJ$9Q$amw?Ei% ؾ]O~tB{gc|qw~XrI`{ Vra#iSaѯQiҟO 59HCl=x 2<2Ë<왦h wXY^Ycdahc^_Z6%c$,GT4È$K1d_@u%%L{Qi'I쬉ح&'6w%Uqy`c8@AN HFg~^ϕY ˮ,1;xs={{߽oW~db]pԱ υC^Y( 1;S)*0fiٍVVBJ)=w~wwGO'_!juq[R-GmFϳbuy-ײ! rހYv[^RgHr6tZyh4%Fs4K='( bDI+СX2p:1^{ 0!ǫj:+ \g^Ԥ$ غ<{ 廖(kXBq࡚&L"S7 :&r7h6Hӄ~6!Ch,hV r]|+ mQI8<'v;#S :=A=;w?{𿉼/~џ>kΝ;{.n`#-[AR ep&Nr\ ~[t@3q`)VlOԆMɩkOɭ{_6?8gρV>ug7^yv~fvӯ=+˕J^{cCN9]&0H[n:5l8\P_4 bѰ Geo]6%1Xoˀ2ʵ4LK1ذ;¦s Ϭ\nx)ȎZju}!Cl7pBW_Ohz07r"+$ IRYL' [\T:1d $G+,Ќ~/R%Q%YF*⑇Mb5d4/{ƃw FzBN%,( KK4p \@c ! %rVzLv鹧c'_~a|l}ًW6ŕ 20C'ilutȌpF$}Ym[91u{;p[nW_ᥙˋ. Ll۾G>+z:bvmj+4֢2DRzs괴7]22{i8†<YQADFZ/X8[x;;xiUgW;<^vi!]_^ <`kYKˡӫڋpze)շl7kWK÷#kivns4>p\DŽ?0:mL$hbak;-KFGI(X #[+95ͅVЭ$+"V2D HǴw_w}tpQN\x}ڨT._Z50lPJKC;췛Igvy)L&@ˈ͆ٯ'jw RRt,֏$%xQ֮oVwۑn4I"bXOn6gpDrcloF^5#wZܗbe(x W" 2 R@#PXFiz=tʞ0Ҝmg.CcM=ɗmצ0dž,O }4"Q"9.:@g]B),vA2j8EnvUK94~i6z 9)^9u82g|=EKvjumu>r" g  Q_G:ނ}P={|Ç= To~Om;ۯI) wi .ir g d)+|27ʋc現P Өs YPlBNd4Hue/Ow֮eGSDytBn^f(K_y?Ha׭oI!DTL1̹Z˕2 Nq|܉]ioad\Zknf{;TD G+fhdaY wE5"wP )Ҩ@'(ǂd Yzvmlъoisdn`ltV,tv`w]߆QɣGfq(H٧|<_J\l/ܳkG[?Dwu&X9uF72$EA)R9YNqgKpg9{v=׻kve3I(9:rW9콿z$MzU~nt<'bLZ5wT!nAyنONsg;{b5,`؃g!f%kVA\%A: {OSmj7> ^ vw'Ks,h=\f&. |U<'P)BBx^o47KO|Oٟ?C4uh;[_z:~fI=e>.ezFY gA;[ۙtW._ ٹ/U1:tHe}gw:;5M^ilns3 zE CxE3v9/ڃny`aj! {tEh{m$xJ,'ݵY+US%Nϴ&Im xW{o׫g%, O&I\JysP:jI- #xO?\Z~S~}:\1A,-HnYF1l6qNm9A)x]|{݆**PogB1\=$lv>@OfL_x3E8Ο??~T*nyͶ B@#KD M\#o ah΢4CK|I~cR:hH8:tf322k(61dy[nKT+";bEj84BVj ClHׇ! DZ%`$AU6jC4xסJiQ3R)ϦCV5ĭL:P@" Mz/_BJ1D;#$c`4 b21Ž"p GfomwԤ.jIlP2Ƕ͜cB:)BQVNZMklLwWw/{S3tCBVM'4Oe7'Owh>'"a5zj?z?7%w}x⁣UȽ:6݂BF:ȆOMm^zګݬ(O/--3t5ʕa7nӴ4}gRӴ?Nr8.r]M;msDH2Zu#3-tiF8xߩ'OJ51C"I 1?{{` C3"fud(!ЀbXUDY[7;kvkZ8v?x X&|; i1G`;ox' Ѭtp8Bl2YvՂϿu53Ii~ͫoCřΨٳΛlX)݆1l ?6 ˘;6[]lmܩ{-VQEl,#ӋB1r6yWvC5_[H%7uwcy}.Aok*(`A1.L`#NNȟMﺡ:woHM䙰ݟaFP N(s(VuB>b F]6v~(vyD }4k.pƭv}=Ii#2`jI.PD,h{Crf1kʊʍ+ߐ$6@ |oNsc[j5DZHAXbc 18F;2=FofIKgoh͛gY-LqhXm\$C1="+d#L&˺^uosʛLz/~';+3I jheб (+!su'Ow}/׎L>|鵗 ޖʗ!%=[8wF 菇fw{5GN *le Pno;ae!sT(,t{,+< xH( pzw EjZQ5(Cu2mglV^>,gZ:~=5vF>$)-U__7\R]e l@"qlupbPr{NggWD*%PY]`HzLSlB`&ƍkg_ڭD&S,^k5bn'G@5G<r|!Q@> m2Rp_ge9 homf_M|In뙟<+g"fRkZb<6oܺs} #dǎ76F^=Tf:r-6D% >cE ӞӇ?墰^pڍ| xD|Bl2/+Ob&?|7MF`؉"L7C_1P4f3GYl@Y>&'@$,Pg>vƈ*ˤ3҄ى._m7_; ٰؼm܌V"q-ccX/Ndp%I*Bswnq JbuF YĹ-mX4IqFǚ a3*[߇OB1bCӨF^dbXM^02`uǸfoduL>͚ݐ$ދx.9ڏ9хGr-lkoZčG^kup ]89LΧ)nAg{UI@f?]-ǁ/Mٶkw(j^o]M¬?&phUZA@0JfSpGWݸ;|OuvAgҌtǢ$c 9FW@i@ѡ u]|Ʌ p2$kDĉ"",KBRdi(XYBhoFw";}<#KRczǍmx,/$S ;. h Ѻ '܁D©uB(D5y4#  Ρ4#3>c_?|=$EdY h"QT[V_չ#m~g٣N"WS]Iáe<[Rg"7v۹꾹,-%$^-/wg/\[Ȁhzv3E6&xnbގ4 'r4=qXcKl%{dFIƌ, ᮛ{EgT"sFĨ$vGrIecO(z,I8jA: fuJ8ng2>]Vt!>qGOo B>AijZaCr% %*/ްQ}f7DGz3hI@a%J<%2r5ccjl'~aP)ir*є96-U f2ܑR8'sMn3]E(9ְdyes^|kzm- |>5G)K(ǣeE 6AHB_:q{m4<Ҧ057]c91-ȌF7G r~4l"_Y<$'nmgrڝ^<Hwns)O#{b d |yAP3,]PTp 9'T,9y݈Cg\I(pFwH1(:f 'fa2_NkmmNYy5}GRZbSY=(Ajkh dJzwlz#;=%%W)peӼk F P88kd( |"B*u d}:\{ן{K7z}KTeQ∬:3py<ي /<p=l,_(ۭՀF_mB$ .Nz: <4ǣJu\Y`yNH\(j&* *޾|~r*k7Ξ9ƛ6 ͡a> 5cY,Q΁% LWb>5Y).P섆[tO4I+7t4eikrD(ۦXӆ!{PLmt+չ#}] lgCU}#02Lp$# 錞ˡ& zܰ4ȻrRB3tE5 @&D\'1a388(P(DҒA N V%vKm#,ǤOJHin4-~L*%)Z;"SByhJI˕}#N~[ ;vo}h K)Mǫሽ AdC"=b?>Pq@""mR1T5kKك~֨0{4 rճGʲZF#8_~Wdf6]MxEs&-JҜEFH:p $d>Յy-uAg9ʪ.BB`T8j)|g uƵ;˶oм?u9 j|p p7sQ'czbmc:za#-nq :.'<Α)< d "=OsɩXœt: ܛpEc5cttJGixN@(nMdI>b'?2T=xR769 b h[T9pJ4MRVDay% Hgmj 84!{"YC4g2 By,OO+ aLg'vر %yckkn/+3Q7Y]cp@pr" r:g*Z25ln.\G?yj KuMBj 3Iz|$jISz]EQ~zOj=ފq<rcEI^L§ݺ~[3T⌭Vm ~toP2hL"lw@lӈ\\]8x6ַ,D%]%/)"ᚱfRDf<f+1dB&FA1PMW+>wk+;{&!iݺt>zϩ iY-s.<^{ⱬj 27o]RNֲTݫa{GNRrpo^X]9poyz.)i[(+?E,CnH8|%p$-!'TES\\[uמ7x'뛆ÒUUzX􋍱 !'B1+m{ɣ|qoLW.5jj}n&SB*knt]s܁Ӏ 0v{?o\zW_ CGj%:"9 ij'`nj2-6Xj hb?b6Nꉛn(O'3\D!E!c)LF#pXE7'!TLsA5[dL6aOc?88ƶݑG?s9E&$+ko^RְG3VH:䔠&)NHeLbAvz.a#wմlSH$[? r99HL>qTԔd G2g=x"$Ɋ6:cYK1IIђ(م5~apc{sg\G7.(tazISɼ.iʅ`Tq} \Gw(ڑ3αߛNB*5AxH gejnn櫳r9)3,p{p!tWZpDG7c#hP&YI7O?~_x囍Km^ d_(nq*"%BJH$3S1zq.(|i[B&)35PqiZSta&W>$HiM׉T@P\_*M![ @fh.E!2HpPrpkQ7faj;zfBȗ%)z;;'-{_nBI||bƭl\?_15l~!ze~Zkg^q圚ItuNEڗ\7("{Xqf[x8+iF[:6G&^SJi-(^E:@ȃ"j\q*:έ?//=ZL"EMG';zD]niDu@'bGu<})5aL_uĩӔ^:\P4kneCڃLi2w Bsn~Ǿ ַΟ#Ä@#tLJ`#µ Wt{L8rD=_*?|oT$M|ҭzvoLfxc+CVА؀`HɭW#^%2 XHFNHb8gpY^-Rʀ\aΰ-MI:l7OO_xl<LQ&IÁ&0\{ &3mbNT LQ''>_,c >6۳F/]޷w{e&gt=Xdrဆ^v65xO[QVl g쪪Y*&3Ӓ$]^NBاeYǝd KF_j橸&& $_2=gE5}j"[[^s֭"$Y+6J6&;">@$V˖g5Uݹ|q*P)CmS5{G/Tz֮d+[[~% Z 5mEW5As*jsGm\%r|uF(*S/;=Է_yk׻1_C,2$\"]~Zg4T֘x'f~{m3otԩRz& kvff!\ARtrඋ(hGNc}U-o6_;}fuc}p"+3hRgHf&ք!I ;ayLɫ%y)X_J,EhT[Y}5jYFN-g+%T$GƠ כ.)/ܑ|zjq20kf2WɗʞdgQr~$Ri]}ㇵ5V  :! Nl푦7M*L,kȥ5*mz~Lipzx4lTɧn!H&#K(Yפt /r975?{-2,ED^0&'Qfnl~c[֥C}F"^`59ҁ)%bh"/U,*e- FSizmyB4%tQC Ԕ9޾xSeErz{l 7^}o|?_=* %;pxrbҍ% x;X;u@Nl7ZsAsi|ufQdzo?o}s{[\2jAto{ŧy酗k;7n2,hPa'∽f*] E3.c?dyM4kL:D3DX ?3~C9+ԁe;~o{\qnfnjf+%儀&g Ïeu^e]f2'OsK |4e$H"iAܥ) _n)69&8GQ%QXlñVQn ,ah{zaj}n`QBl8lv7hئNi?>PAs *q/a ^i@\9eܴm6CNH*. fWx}k_={<|v]UMLc<b3XI \gC;? K9*8&m<ݶƛR:SmS;n+2Dc$ b6G *#)֨Y PDlbjfENxz'YIzzC玚T Il[Hu%&IՐP /\~[TA 4ݾ$SN^'BuʝM5{iFtU@*d @\E7Q)yijCAv2ޓ"L3Lx"%9hAxÕgnݨGg kןڗ~;uF=bc]zg 12lѓF 3)صXV"qx|5o]uUOvڷ0SC^{"*d֮{돿V\qsw$H(&;$T1-̐Gqc좳ۏ1D?nMdL|<Ƿ]t:&/^Rg ˔" =ِBxlcpMϱk.# |7esӕŹc'C3|R%M?0Sv70@8خtr&YcǏ?#8qGrlK;PA#UV 7;< 5H}>|Y=N.]+V.J QD%Td /;7ǽze8ӍוDzcldh#v"bOr1#C+1d!  wR!b*CӋ]=}y^bV2n>ooB)ͣ*w`'#hebpe]8{j9':,p.P MrSK4+ʐ*6DE[<n]QH+G]/ }Et@YNg(L{ZoՇzȔʅj5f Ql@&yc @l:ضVm5pg^%-"۾iJeVjX#'1KiE^9-29LhZ~䙟>sD~jvg'淾ԕ`@bDTCf/fRŌS2d*Ǣ )$^Z Q!$cbQu2;,a aV3%-d\FKWVv:MYKesn]?/H^e@"?;6z55GEܠݰͱ P([%mS>qLH&m.pQv~PLȥy;<Idve:9#,M@aeZ&gCKZRDz8^Ɔ%xEᗢ*` |ofEv_y=̬+RpC~O[_}v% lXa@?Xx'7ϦD5̤L#\TlSэ!2 W}Ozce3|gsmJKgwv{Ɋ$!8)9@厃<ӤM%!ycRF4~F1}M>5=aEg+Xx^nx?_#>~cGsh~q:5U.37_}ǃ'RI} &\=Nch5`veXvlbs%3s "?] ~_i:1+'p_.kYiT(&$qD8;*/E, gNI"PCǎjѡo{NW+F.8j#EV"qdxvk LJI8,dNJpFUQno*ɺ 75nPw*?wK j*x B@-DQP/1sdGLCkj"+k\B`^N 7w7 dsBuzfj K9nT=c6V!虂oXE+jj5S`d\Y)(.RyJ ‰{z~k C/{? ϽxƝȈgZtRzV!p"J:g7;ߨD(i o4cnRՑ5JuکlZquUsk_ߡ?_VXꥫ)ɒJ8s"3H4#KXQ3eO&~XÇ0? IXNHf<#Iwvԟ|o@yxKOçN?¨o Ȇ"*  )1rEy<<ӥE>$XȊ{ԝ>_\Z$q-̼m#u~]6 gtuZ;"CgQEMOruqR}o\4`댺@ɩD ~=":D7ߦt&UP5͇rKfn`~Z]F1sԼv)-WMFRLoh,oÌ6[-&dN]lmza$S%!y{;[v%'RR"gǣFLuJdЙ?E4 hEF|9NҤC|剅v6$6z%JPm}z!N'8]Z,/(<ʈ Z, d|S-g޷Ņ},c # Lc4ICG@'O`5<}vӃ"''*|YRIE~cug֠5 \OCED9dı}eq:8RBH;2.%%J 3̫>2kc%Q0 lۄtkk+^8zUv%Y|WRqvgUgdfbvl6/=L{g(vӅc+W0=?=xO=8!Gq;4+'# ,!R, ~A ~@^}cog9 -s쾭ڶ A Gn^98worc)-ǝQe=k0aR-Ux8&rO?n5Q4F~}4)~vgcckckN UwmSc#}mzB@axqRiBP|'%f0p1UYؘW9~a{ck<;"Ɂ~~?̸M|􃏜zSs}UALn|፛_9w~j2Nd ?~y̒GM)8Xk,ID-"0'n Q|P16wbnKʇ';< ҳF_2'2]τY(>b x\gLhdAq<<0,iz<#C%E7LˣgcUe{eeNm7͕ <OVKSR ҄HzŐp!zx BFȄ ќf$)cs T͵嫍FM`߰>'sjCVҦ u0ML.GcMӓ0]I @dPxxp#wݯ|[o{T&¹so^Lh,ݰ'ZwDˍ6"|s8jH:Cf\L6'Wa|{ӍꨳR(M/^sھr&A`V^2V~Ʃ9}u@j(QԔLɚq\̰նӳo֔dRfSROVR3D. M9Cb9 &bɚ11_iQ8#OѴڵ+p iPBN~nfzpI%n\;ӃN20 )10LqN~s}g% 5 $$d2 V]ub"W~C˗ξWֶ667nnnÑE8 Z@/$]|yqBF;ؙ;1Nbеr+Ap(H|B#tjvhl8OjSEoJ2{N ŃtN uJBͤFۛgr)Y "Lcf\cZ$'=N&0؞s8FwdT!ٗ"Md7T/b7~FBPgs QLeYe!э!t/|7U%B!ʐsiP5,9IDo QJU<]QT]v!Y8p,v7y 5E/RYa>AŞH-0=Pvpl(ML,4B~6Nԇ z>K^(fF+;0[( bzP7τ(z;Lf3B+{sY`+;pqG@\F#j8 Xtse'a}Y\]sP.nno@гX]MZj!mPmF4Og&a|%xFW7vo \gCx3ƀUR“Nz߇=~ Ͼpҽ'o z{ʻ~yiqբ*Z~vvg ?A<ʭ7^pZhom, Ɖ8,=p\{54J ٩ͳ-T [߂bBքQzpFNJ3Tifζgf'+hʍ*1B3/!Uڿ+qpGܛΤEn-߹sRsaZa~VI "bHݥ{\OH#KYC h#@#Ƒmh$zh&L\g+f: L8}B=P|!HbPe6! (߅7n4{/+Yp;;$8T6)eӀHTR"*MWu8̜ (4ٱ&e U(qGXeBdJȻN- gHg<|cӅܒ,ĀQF+^873jޘ^Y7!D1 :^&&8@ K,|4.{MN,/ÃL&d j3d'VdO8f+s0Q6C/Ǒ{`qGngĻvW.a"=/Y2]tcs~KfK3K͵qR -s0BȊT* ڙ3N=үoFUuϴ#ټsqZ2CjG&Ҭ&OĿFD/ۆ펭E멬Z4Ԣ" q'QJN W-O?T[RS9 nݦr/Cb٢H9BG΅^ʗˀ$A˥r^zN쵽1l\[~fg.aV d+ 8&/`zK⿐F͑UIALɄ PaaqN}#Kk? )us3j+4;*BRyqo{3͝z#S~z 98#s $*cbòD#(Dx0eфtm?qdLFpJ &s1;m۶L5UzP8+ѓG$rp|D(< h$#yҺ 9M/p3#ғG$0r HZd:[N4vb(HAs\Z\]j5A[sh#8$OzY3.- 4E10Oי n<_[h6F뵖8xC֛FGԁ;AX|&kܠ >ea\#O,IOvXRd!DȮ<9_nt#42FQ$EJ%k-9g3+zkSu͸f=U ){$Za$K")1$R# tqsnCfAUBh`MwV>sp`hgB;VעM&Ү% Wc ?^a d>Qbj97+>v ?rmu.~#Obqx V-J[W³j_|Y߾&Allvjo=h55V\Yj.o;~,rC[9!aƅA;^O vʮmqlhC BUWX 5r}|(m۠PxϠiZr4 8ӡW 9oPek{L9L}x!v;nZz;GLKyk3;hw?lh{X1|#WoZh}1OXz 62đdw.It2|>KDno?X(cN>k7#CdKHf2r( 7ҽ#g^|Щ|{?Y]R +xB Ԟr0,# 4gEcx9ק+prO&Ò98'9zHGt@H0 n"Lf|HxKxFD`oi8:Zmݷo8ŒaS<|t52y-c\d'ISj4rDXC#7) h{oa +.[_9[SS[s˷/M}I SˊOzw?;G_*ZUaNsb;މ3\a9l]\,10VZ{XAwKmi.#'6 >,~imM ɓNۮkKX-c6hH2E\kng2fx|'ai!bD=xި=}orɗ^>uN*3F! \9dgP,ig(xI3 T tҼ^֓;($؊YK/Ͽ76Ή򛪦,r,+0aMc /C290i QOthrlh ?o=ȤOXP pNRD6^P c"#YYlhڃ4q JRvdAc1U5` OO() gZh1,EpGڑ DRJ ;鮞8Bn'rݙޱp<.Ȳe@qϋe h: q ĺ# [\s//.YdM;?}ds;K>2 'Ow#\KhDVC؄MžXgo-0:M T˫EW5ܾVPLWZ{c8s 1r8Q-n\?CBo͵;j~d0LygѶuFӔ]ͤ3pZwVVPwg `D& Hv![Uިo#NA1`h>uדU &A9֮_T=xDm7!*I;hh4 bPYٔG^W9} oÿ?D/}i\^ŏokqOߛELD:=` -w܃vGSu]-@'Nkw8i/.^ykܻhj:02 -I T+eZ'#\$᥈j L 7M~8s[ݛ](Z E \@% O[5<%fǞnEC #C0 ;$f{+m)J]?7û(T!FUmv[ULgYzHʸD4}Ps4˱)lpa8(αT`PWDn$d\B3tr"PZ5K%8w'Rdߤ$w3ZDwWzs] ȕɣ<4Bc'}k2< ƒmǤxeB|<4">m,9!"iv SE]DʣC:Ulj|ժ,POBFMOZx,2a!LA;>Ӣ,$ $8ߨo-=-o@<17yxp'gI@_ ûjjh6rg=vYH>g+VcP<VaV[фjxVy]&꘳"9Sطi~!4λ[s'ڕctzGNӂ>jwO eG{:hkl'ʫ+HsPRJCH2bt Z %z )"a[Sk#,|7hFP#9 l7MLQnKG)W51EϑDe۫<'GN=5fjFjD'fޙGlwda 5/,ݾ}|#?>[W>wi5ڎ-i,?XyM0hT`FbQvT5tLGGǧ&G #Rc\I!5# >gض& GZG$$^dbN)kpxVg<7^ۿt.Is0G==*"E>,`90.Gt BZ2C٩>ە+Kr  HMfygXQ))HЮ7[N%i 4(xD B3: !¤(Gn\.R>ZZe\Y,Nwŭm[`C! gZD2I1Bx9Gv5f!Z!j]2B_!5#duc!ʰxEm ! ȴh6ҽ˓r@J$BQzQ \8RRT Zݩ߿>s.܍2ё'>yر}\e٦jVVH`%)$\?*4(p47tNP{cx@ z Xgږ[=̳/ %V }u-+HFQޜ--l. ON8vJioܴ7b>zTUC %D*$HMVԕvJBTuVSQ4'GB, \ȱhjHPi<)JdP_0N=Ձ T$-EwGL([ݺu3VN=|B S}ٗ_8Я6+s3>x7M=HF+Eh? wtxNdiD)㯁*i =A6ߓ 'V+ %JRܪ%2 `=|8؆ hFq>ҚJ<[HDNХcR8jŲgPE aG2޵ #(ީ龉þE4K@ZCǂY"ݪ/޽QZZ${&{bzF'8|7^+ksq{_^x뽷ʍbvƅ +x6+0O0A`/ 위jD={Oߞ;D?GEmWik^Giq(E9QFpb:-R\A[dZ ElS/ʵu"T*n8vq7twefW*YV)KiCM#D^{WsdOzllrҶvwvպC.PDȣ.žLУ1GN2Tɰ[j=\ \34ݶ-Y4ʐСf 4ģj(96TXXcy4h[c:h$民8+OcVxhȾ9 Ϝ?MGpCifECrLn||Z?tox [M]UZ'\2c9$s^5]xLȪKp #156dz^>H@bxܸ~cUce馶Lٵ$6;9ML 9,W[gK"&㙤 xPV}lZvI'L$-ymĒx;$%||CoCpi߰P(P, Hc]+f4.BѴx"hG3tЈN\.FsmUIXk#m4F2 z~ph&m{Q@dۀ4#ZRF,ETQl vRXB%$*;&VNu'5BR\hWxwӿڮѨ%SKo\If{30c=v̑T,ZTwJ;D{b?"E…rS ᩚQѠY,tL?xh3ӓ#]9A PBA>>%v{ S=<\W3\$nzh΅ez"{ H8yTN$ :dP#> X 2h&wU,!V,eÃǘb8Y[h'=fD`W" +©CA S>9[d7l!.H iْ͖̇bk%@ 4rѸL,X ƄBuV VX[XW?|Υ˕J8xS=5ռuo\?_WijDm2D)^ mࡵe|QS m>A09)IVĞ$ikm(Z,<9wtLdNKoَ4k@bV' kZ5MbI\qtղFhvU4|Ot Wwz{`rz̓@Kw2P$N&&\w46n!,Hiw&DbBiWN6Km9uwKo`hvh 7I̻x{൷K~_~[(o-k5dBVQF {rR#%Dg99/R }$IZ\.쬯>spdt띖ޱCڧ\]a#X6uOWT5)dۋȄ_/VjsTQn#6 %"mQpdmZVWHO |Zь?nu MQl칣#;6* *P"6ࢫN=3=|٣&sQ(MUunRkM) I#YY n[-:h,F6ttZ(!砖{Md#pu\S4"3N[;Tǹ.bh$^z8rv4Q+ZER JVkw5C~WSaH,k&y(4)!R~$oN¡h6D>"I v(>?z-Lz{$$ m~h( r Eq{}k?2, ?~ܓ/=Ǐ3) mweh{FMR$)QGzxk߽yO~N)շ0_[ORHh Q*Uf"%䁸U!hשr|ķ%ALZ|>=AP8];~ZS b۵͇nxPϾչSgz}gyRϥ7\|{+yhRKghFO8bYCxwO"9Zخ$Nē2@'9F"}}c Lp_kǿ?'{[_˹Υ_|߸Pv ʚ!sLp'Jg`]̈́Jg~  8 \-x6 P% ۻ8s4ᣧ&3>EWlO:٪0dyt&>ĵ-G!/.Ż솖vC:ƒ=04 kVΖ8@ɣGN?tܼ{XMDeEGYUo 5r-X9fK餍dcL嘛 M󨠣;j" b4M&MPTr^,Jl~l4g{e3ȊH:qmňJ@Ru^Z7'\<%rͶV#>3BAoMIC+f7J+|$3yHI1CXӛvV;ߐhҪLZeIh/޻UّC\XȧDmDCe-$F΅tge(W ٧O=hisZAьHX`D)* <A GΊh;pQg<,$[Xa= Ehj @qhN(fm['AJ*𯻖5)0PWM60A{5QM&X.GpoM{ZmQ(binH2#zϺ&\Fa5'PnyD6p18~FeY#TBf{\Հ#좞' |p+'g%9Ӄ'gk(lms L6 @dYiHos7?{͟zu :~#gON%RpPT OX\94CW ^-]vO_xݹ~mzs2L 8|=1yHOo>K!9B%Izx9"PkU0}\%JDcIIC@^˨5 b'mš Ă?|6F&X)#Bq3ZMW ѨN"Q{$.%q 'XU^x?yk c>9<$r$q2 ЦZTwkn\uKB?_(6twhxtG;tpx|{d$ jl9m 3\s7 n0(Kd  {쁓eh6?pg[? @]\P..PRZTˍOuDVl+dnSJvbG}q88Ÿ:LW:3>M! ib[&CdܱpZ~Q 5XeG]+wo_,b6]IݝOzXS+*՞уGzdb,Ӕ܍k?K3ͦrFS#siS} mK5*KD -j| 0\2XI;8la,.A%T s[giQJl = Gosc'x!iETX  cZ`NE)A-@1QmF2lGWM°X^F1ȶfbqPֵ"H6U/V_$>49ϧŭf2Yr&Z.^!,!9~H:IݍeQBh"I!x H4#p,|XXs awfrNt*k~;׮..om,/>}hs_y䓧F(9oݾyR tVՠXop0Zֺ{ GRxj m OeM==jtgMWaJ3"C\EPV!4<ęQSLgb(3<])Ne}Wl@&.?ьG]SY_MzpXl! flY߭sXN dfGU-1 0S[j\lx9r"^Z[gt?pNcskKDpȾ.޼:;37tp3ӇXZضIWF]$S;Q~ HE B l۱uMikNrܹ.oJ<`K>zK\gti3 )D V*G|, -0iK [s#6jAL` [h<#jlzS$TºC u"4c?Ak!&?܎6ӣu)Id{jYʝGoz@3̸j="D$B> O˱h q0/(ƲlE4*fe65x &2Y ΕNUk֩մPqu(%Gd$%2R|xa. 0%- MFNFueލщ,|x4,Q:zc!~Awibq9 ߑy5*Ozzd Hua9"C?+ 2x!Me٦ LP#|TP[7߽sc''7}.8amy*vJdn<#:zicghTSmnڕB3aY^ݮLfRep@wE$=?s#Ó;kuH2E`JQ,0}ÌթU Qi t艣6kL}oP`Xx[W97[N~;˶kvs'Mn-4%2=#V6n߰ sԍOm<>wݟ?y[) 'HB;AI -\;pJa\6`iKݪ.b&z: MCjI Q9Vz6#|PQ[z +f.^wk#,䍥wj),ܾ9T^^^ `Bz`f%@xL-k-+&G? $[p4u]?o'f 8vVaFs8-,,]y 鍹{ݏ:x8eQ0Ѻziy].Thp`~ׂSݹD=RQ+Zdb1xJ֜6$a;<}yWN;2krf`೟g_|?? "ƞCv{cnP"708&zF ^.޼|V*m5ZuM(1ݹ|od2JeD u^mmR FPFz=h0ڨ?e6qZ rnB]b܆fdE"QJwpWrp! X6;+tdoGзC7[5qh<\$Br`Im|_.X\8x\~h$;W.~EY<?9r8qZ)lrYÓ>tJG% d_h*@yp o'F}cX;~3G啫3o-ݞ]Tj|cz9NvEh6gw<cO<E ˷gn >~)W/ܼnW7;jp|` yP2ou>d}dN)Xz4VI#HXhV5Hcj3>vtعV*µKEY ҎYFPLflд.N7t"N59phWDyx# ,qW1Y8/fv\zkj%G5v #/2rr܃e I91,Z12O;q!ڨVJu37_=%)aQLmp,XZd1jSj++aZ xe(>ږÅcc,"PY*`BQJX,Zm5U yJ-< &Y( Hv\kGLJC]| S}Y4V;\CnT`P˅m#QU1z4dT8@ CJ ruf2_YP) 'R'2i>$_o/q]Tg8.Gr2GbCdXfUC+ p)Cyw i]zG3CxtM 2jЬ :zrwDt'5!bִ,H BZK|!mTC d’B>#!N}V`}?8Z_?ՕD !羕BRalGͯ?\{ꕷDo|thD3G ǻd1!t.wT!&"__l@]LSlt6y@'[\^#fjiNnl|\43xd4u6|c펣/;:1zXFC{o$8%;;JptHZ;MLez>;Qua{t*Gc4!H0DRqء#!_jWUs]yPd}Ȑ8"%VSsN $5H/& YW#'-}ĖPJ[F<"Fm .Q&- 1;QC ԡDB&s,|k7 w,rWPXaU8'suEJxg?s2 YVyFK8"DB45u]UmMNΕϟη?C,-߻sܼaRJfN<;7n_훘8ܗxx{GuqB穯}5v_(Wbj4>}.?yo*x& E'QbC1C0x n{<]9͍3@(*>T=6 }YLK~o4U (_{Ŷ+z {!%P\h2k.ӽG5\6mF$BԐnU6DZƦ H_Fc|`pz V7\}OF +[nǒOBi?/+ZlB=A%p-nUy#bYY߰-4ѳEs )Yk P,chm[W(.dZ*ɡ@\f4(!ٳꊭ3X榆j)S.Pel=@*!-eb}Z[9TrsEHm#x42? 0`TN~ ճʆMمB"s賭zrQ ipG.^4) ˅ƉZQVkVŹHt+Kb8 KPTwOF9G!D ϵuWW5_ARhu:mEUjJ S ,P@Ӕȱ89rh!5$XxR1JjۀBp.(^IQ*~^!X<:Lh4!`qT YG!@9B] p@hfUi4vĒNlo.$UfUkTrgѕ൰l<{CO2>*+J I~`x/|uhtˌ}^7f.童]&ܭvvkŏ.@jh$6M7*0̞[8h 0. U)&6#ï`Ujy {Ϟ  T+񍯾rP.|7F}Tmw!|r]TX:0q$77ul&d(7 Oך6!=F܋aے))erjC˥C2{ː ǥ7ٮתFTP;$cutNݿz;Z,Օ΄9vXrmZ:xy7ѺVkwZ+.K2x"m r뫉Mլn>@s/kF Ux $B}+E2$!\Z8͊[t$Zi:hfȑΖ稀L0K'!JLjG,Zt4-?0ȂnR0}Ƴ5dBUЩydZbx(#|mk5\]1!8WU ;6C{Z‘'5KhSX)n,=+l햊V݆"ND&ؕL(IaA"XW*n(KfKo*JѮiE!n٦0ac:J i3#Y@.XQXC0$̤{zҾiK?Ç;:(m,< i>l!aOV|ڲf:pd%Y߷t?~象h"QݮOg.y쩧cTV=_T~wn/yTWd"Qw?OrugzL$Zö7M {{/߻:v?Y&Y ^fVҪY$Krb1L B4)Ee˖,[i{gΜ9{`[9oyi.37paIo)'^9pT U5Zf Dؽf;C-r^:d[<KEr#1{AY+ >uؙ)ά=}a# rɘLef[n6op^|5dlF=~\S,0:A&"i?4?Ѿu現KL+ ETՆ۴3Du+xex@h/gf.^0<<==]ϧuvyH,y![ ItQ$i[ Zv\\V(nkrEjuMQuРn;SXƽ&"rq362p~vph/ [z*A)<'.VJ[CC#O!AGM"ayg%܇,a1,L[xUq LsAN@)Mݰum[zV76[|{)~duoy@?SGi(N)iBKB>p(^^՟hmv{\Xnaa;/ kJu٩sz69r}E;eWF # g㏆+3&OL.,k5WwHsfsSLZz)kJ9:~[狹u[\ym%0{n)3C|cGAN^{q3.wЂx<[NXCKXAXs8)6J\*y63ހxa̺+t:$6 ɲTYbyY{&oU|Lk7?z*9<+VAT&PΝ,ʲ\u-J؂]>Vt[/2 *'iVBߺhJ!Ԡ[R.5?6Z/gRH͝U1~;?ZҴP x(V51(ńA$~nxgvn]HeGk*/(f\43[D5;1%0ުeYkW5c֍r>N;sqGߌЋ4a* %XJ-2BziXwdيh^3%3Bj0)< ӪiՄ@sfG?ԒĚ5v^ygsi;)HeVlU||g_;q,_=bR-#'.LONLL,ȴJP%t#OKj;WPJXCUBB׈JLc9#! a8Gk!+& ȳaȳnЂm)! u CCc#_g֯^s5)es,;2|?@ KJ+5pE70u5k8:b$HGxeCOжVWՊ`["y۶]Wٰ}ksS zĪYO.,T (d ՚"-$ZDNFV&snp^}o9;3E>^KEVɑєMeքyo>~z"7ٖό.7kc' B[wt3oGxe%Ҕ`X,zSщѳK \b@GWSej%;C]}e?pq\Mξwृ/[._[z폿;z2ܾrSccC]W^}+@#;/>{dѐ]neYTP.YxS'N>qvPy'~XM,AV8ӕ9Cc@946T0+mU# kO>}{n |s^͈”3Nbg1ԆE\m،Rr@Lx\RNinq^$ ՘>7=qq|FV*Uۆ^a.je%J _T++vlѭo[}āwTe߇B*N޸mW-mV5˓h_TSWtU{a~S3[jY&S3(5]=/zJ)o|s=~.5 1LQah }6 ,]-}r~0BFPEI5J..} tDHXpӬ@uh )Z%bL&H^Ok 4ߵ0m\duUa(CڤMP &j8SG ſhAa>" ㄖx*-O<5] ܟO}hdХf9 Ddm6UŻIѴ #n=4cR($8CB(= {kUӔZfL%x,BY8915 p!2x}0O:Y+)۽z˞VhE}e5Lу]aP]Xx૯Sc;>8Hy/"w~ͻ׶47wiy~ǚo#RvPB ]hohIۘc Rl#A-ASt}7oFdb v̲oK?RUu"{Rq^fئSM@B8rO+7>pRЯlڕͽ}VJ.̋.6'|wO3/, bE)2#Nԡ0 ~)5{$;9O`1d8#y^YA J@=U Xma$NMNLkrw{_dz*Yniw)YpӖ;{V+0V4}㕗әXψTa~VjhZ><7aN ;bq|Lm#dL KQ:5^߽ ũ?%wyí& &*`QtArRxlX U(VCGIhB0 .FZGa)_L.ʩ\1 Ɲ3ѾbySW⛯αg \qknڻm`{VU]u<`w@4ͤfs"ޱc|ӟ[oyˮasiiRi%;>}Ӛ|O5 sԹ^ysF#X tmG{@/yN4uuq~>/w_oJtS )ZC+Brmص{O9wa,< J9Y)yZST<,nظb\s qTWtȧ5qnqqb<͠mOr/';;W,NN0:V흝3.#fOU+Z7xEIf){C_j(iSvX8T(b(h0 +өa^y7zk4 ~ "EY1cEWVdO0*z@,@6MC`J"MuUF뙇A2x^F40d@\2?UEISZw@ƈ5$8 B2)M6+Ʀч hW9"{lS/ !/,O2].u;Z;O81JrMK5?Ť)|M6dX '.}iaU]ɗk$xZ͂Kȭ#Fyk6yyБwsA/=ά ܴnC jaa%ћD x-x6nr3\]* 1B*g-Mh_{??y> D(" ƷY aHROfrmǟ~blAY:͹>vg$%,0?311]gv|b)y{%lmurE^:{]wтL֪2ZmVopsO$+?o0 < $¢Pd )0A^03a[BT*,ɏt݆Ώ U eq(բ ˂ j@ߦm`nn^19(uX.%d8gq2SuśrRL?P0OO1iSӓO{;:Gq_Kz]#ƴQ# " )o8 юv6Md(>^Y !$]M40kZR!@BEtQ?vJ*W.QSAe TYa Q zD[ojm'~:gJaoKֵju(E<£txǯ)f_N}rpn9'x*5 i M( 엸m;wzǝ; c(/fRuAS{(M<'?~+<`ZF m| LVPAʧ?o"MSR^}k?>XLoj豷%>r?'N/f n޷^;; Dۦϝ6: BR.Qm9k2tH|w&&EID'y]c] U1!7 'W麱L/z  t.\=n;y!2t@$jR5tL\$&J~oFۋsiF]`f/m^I/Q*ͲLJ`Wg%5yEͲh1KttwEvmTR %yz#h40[>A:Yn[!%lr$̥YXNWpOc~M+)ҖJ>-ykD#ƲM'\+\,)a٨9wԙ Rla!5BD|(Լap{"pg*u+G] a_=^Tìδ8zȫm3Uaq5YGi ]cZRwuu]{W^bMH.QPE1Rg93Ԇai.c{5wbEh$ШAX@,( rtq<[%joHB{oޱ‘³CgZ;;;5Hq7lNs.wT7_y_<߹RRF>r> fFQq7-#{ϲejRZQ[9[޻ujՅ TeAgȍ[o3]C.NiW5ɧZ>ۅ>6VÊ# sT~%3<}7z{T1EyX纞N&/Xw y Kfr*, 9ʆpaj91Y іW \|y 'G&o4c(BE `t"qӹfhĸj4&C uVf~&ɏkL{$ :0a(r' s3.h֊G酌NY#t#xd!!^^j`,˷|\843Q\JDZ[: GCDK5 N1$AjB3\* g1 vW5aPB#(kd@Râ. F֠JB;[;Eo`T'B 7~Ǒeyp2A48aj/r䅱(@΄+xE48( 7bPNZ:'DNBA_(گ";l߲늫b4 dͫrv1n7#z5e8%bMe]W'zQ!w؍Z*MyXӣ|B% 0/6"KÔ{(NS9u Zo Vt|#wYX8uR}vΣR X,[#Sz7fRֵ׮߾ ȑW?>ɇOa9pMШkjj嶽_2yYLV^r`۪@TxὉAngϞ8{j4;]˚)f |1 zb u7o޷f #ݝ '7OB@Fm/I90 aGL b< $I1qdiKA@wzy+>7/:U.- ϒ,6may[Rfz"$Y8;2mhg5S&Őʙ n3ӆ9ͪ:-zl2_+d Sqb=m=]yGLR#wv5|>ec?}c)L+"'Dg7Άڸ Q2Q@'29b.ߵ/=􂩓/ ѢYO,&BAFɂEp;YfĔn0'-04Ūbma'O"[&'];u-Ɋ:;ۚZ\$:r'{OΌM/-J5ͮR + B^E}Ueۆc'`dpu 3C+fsgq%j҂:wCA۹` @fQW}@^֎WF{Mi)`0hW juE Yz(=KZ!hN)EZ,)zU`-kJ KMPqFhCѦ&GN3zZ:<0Du; (DFHDG:QJ3d_[ ~3 DwW;Ve\(z'Bqpoܷu־nwjb)P)w[ nsna&YMQ\:UiJ1׶l ́Qe?8?rL7u uTK(6 \f*X_LFfPsPTj)[.Gϝ]\r*F#ѱ nX r^-d%UM_r*^yor!^k3M < X A ;!ħXtX7c)Q^_z]￁𪈠+%޸ad Sj5j p*-fIZkj`Qӗt E{ь #SZkzV6g0vjv,_R̔KZ[{ڗoF;jL՚1Q,I(reG': 80ñ_a q'aƒX08b_S9/ {gd`2P\xnoR:W^L'%QM&Z yKG:JXHxRdc y}#?|tza˶PzavEV^v݃`[sws9sß<.TU.Z mWJ&Fw[=؇\dSI܅a,Bp8VGp)qp2vks6, &'/T4 Ț@ ;RT&ST };нeY-Ν==: H CX 16,N0*r)QA7(qsLZٶKrD |(A ͦcl;4)TsN)s ōXHXfAG(ͫ>O.ߴ>9+,F3dt?a*sXo8=`T 'X-P -7T]a~Qt/py1Ew(U.+(,<ӑfQXCCWɣ%'T[aL0K aX;oJ #=E rbeR)GreOZ`T0cER\fob'4K8X4P-%ܨ-N[0Zl|xY`{(5{@ogf~E8b+ l ] w)Clmcd 95NUcWm|ǚu::;XUSj\1Te<90J*UCQUR)r@[b]gikRQSTEO )M{t XE769@KN}+_~շڛYE/DƐ!ԝ)>L'3p=䁶AJU᭗nwmWq*y'+[su׭\]SS?{pӷvo;wo 4m %գ=?/宛 g JOwL`ìKt0yDz.&DwuGWWRQЇXFHU EdRI w3*B $p.VƒjFF ZȨ6Nj(+䒋3їԅ~ˇ X̥fg`pq/Zw J0`lG9D,̹Խ@kSW{ۑa H5hd( C8d8ͺ"[>+>5^V&FM[} 78(ϟxs|Qݾ/!5K.]ُ۷=_;v?wKo6B+O7|DO-*gKhG|Ў[\EKR*5])hJɢ|XmeN 00+h*g僃)Ϳ<Ǣ\5%\.n]&^7R]1 kL2DqM0xz$|R,IG]Dʆ@4  `81V#.)E8 3 , 3<t7@Lalq2AZvEޏ߱ѵͦf!PuQb2ڵ1ںQz > t`2@,LfmNjJ!..%ED$Ȓbހ/*r=~ܯhJ2 \j^'Z͝V+URm>Cв10@!O bLj5|4 7cB+Gn֕{pN@a[1jM]`h X0 ,̦kh^615#q 036 x UCrXye׭2ц\M͞-Պ *Ҝ9Y[. P,u< !kD胒eY7E{CZ4AG>gUtfTzCA'%zN:17q1Cq<۸_M ,F^L=B4 "^,,n޺[l"Bѱ7hw$kRx4 $ % m xpksoYșZJ L([ywkgOEd H#SN]7 إ_~oqhp_׺Z{.z'zqEg]0 fHZX6m{驩7^~@L }Z7*V7 ]3W6@ ᐄ7N :r u^`ۗ-W|zq1u5;v`ʟ/LM!dؔ N|~QD0 ISi(\A0Mr֒v(.xy6Dz('q'h)  .iEI`u3vKp?6P,{ͩ-g"4`",{B*U>tk9Ԋn)ma&T,gɦy)5yRڪWoemZ-(P7w`3'f@Ez$o9nar)I/sbe:?6Ks<B-.? {.O5l粭مJ6_x.3$1#PO< GݍZ3DCZ*Cfɡzl0 aܛ`hgpdC%,P\9,ڈh64:4%& v` ͱXPW.o۰;7l÷o>s}w ZpX6/|BRKD<Ҝt.\,* 'r?,J!Ї۠ M15xcQ諨 :{@N) y/x<9#iӻGn f!5L -CAwW* ,RYrX(KbQ arpqa$JLrb>7^D(bΟ=sk=/~ k O=hM]˗'" =yxZ{v#?߿s$? ϿlkKP#F6&jY&Zn֯|oFC `0ađgVO3eXvLґk@;Hڢh|G j^AUezVÖA˿0\L.XF 1JRdAm A1<09qh_bNѐÝ&EDn;@:-*,L"¡.*j0i:mD;N[HC#.-gSՑ'J[9 7\Zda Hr^TJVrZQuMQ4ϸ EˇPoDj&Sںs.B5uGZ{|RikBqqn>=s69=,+ڴ)J njCPL/jưTrMob8lĀT2@k5yk |N_{XSx8C[@eI. h=i[N &G;?rfpgP!B ;X߄? F,ըAI ޞ[] ~_'Tq>;dMMxW1i pKUrLEӭRYl%*=hhht6H'UPFCCwGӁXtQǗ.wgj4瞟:\ z]BSF@ӧb vf]^pl9:P ZÑ?FW%3Q LicjIZG1d jEhc F(vC)HNϫ*&{Ă8Pw>&{u]a29I-9z'ޖ^mH2*::yb>7 P1=I{#J{T8jTH+W/ffs iO@ZqنhkB *[(~|+ta#@^ì 54HxZSKj"H"ShW[_Jo6 |M A8obh Wab{C9#@ ߰q!4 &RaڴL!rӘ}px]13hNϓ;[xWOp=w422 5$ls}_xђ3t˩<Ӽf3{ZZpuzbi)o^e¡/\)De4˃k|la+ %Z2 Lf<9q!0Ev xaqpp$HpƄ9@0%%L~CΌ# @9dѪAD-  mI6 H0jĝ07&8$8|jz1[)K.oh߼kv͑(zrUΤK̖θd)0XUgZӁTznw!z|gOԫ澕h\T#XNo̥HECt~#7<hYXYX=`냶,˄.klp Y81N>![8Q (뚗uRPdlZV),!,'E-gB+*U˩KwS}vQ*ąGg uM=L/ۻ;nA;ۗw-߲\eph(*V04*NC9" 2&詑o i]f g΍V6ͦVN)MS-Gx<; :tpؘ,m1Nh 9,9@أ83N} uiAIJAG;ä!e5qRt%sHR4P?^c"|I 'kP-+- |u>73S InWm)&(k5JA=kkl:I@?JVY|:I5VU2.B[$)~'̉`.BQJ6_e҅Z%e2H"hAR#WBlQG2 Y8tT,8:9L%$km'$p:Ν63$*-k#8PEG~Tjy0ภRԡ=e+JU BIJUkٷo;:xKQJnVźh~3U8/R:Uer==ᖄR6 L `,GHy {n rNZ,6#o~dp.=v(iR]VIY)V759Ъn<O+ eut˹>O? MEx AkNWML)6.@jpO d &@"PQ;ͱĻEA|_-N3չٲ,_>qC!Pwn¡^?}o]wۏ+? Yh;?q|䗌x!~/2`T-JW2pڑuxnbbfCGG b}=o??6b0:1uU @ *t#,)ˑr&=H;#WK >X92jZAvCqD P4 p Ұp,Fi: hIG̶Pv. l t,cUlR1 ɟ@ȶhLc0֔Q(ڊ`8r=Ze}ggO YPBM˙$'x(C>P,%PF32VFX!L=%yfΝqUqG5|)8'@үu,pVefW_ѱjX(" Cvztꆎl- j Kyx}Hgαɑ?sjmxzMG8dK# @ub?Ua)I<Ԫ%U9/psa1]Ӎ`$N4- xDr,sϢ7^dSjrj1ͮ:a Zɋ5EC8 b6}W&}Xy ~'l_;>e[LVlYblRʻXkOZDgӗs`NZ8/2(Y3 rH 1$? %D {  Sl?/bo![YT*XA)ٙatO61\2EY$LIK74QiȚZRqBZJuHYv{p/!(zݒNj.ʹRA6TX֏)\pr , N7\IoPޅ'h3AG2~ycp[+ mwx'_̲9+ ]I-9JlIdcI0Ca``6 GVY-us_|>ҧzu9ZkC2x-tpJ)UA.%[<|$kF]krwpcv7>9%*fV4 qrDÙ &bu'87R CoU* 3fؖHIbd#$_9a넠ȓ]1 2Σ5`d3E rY޳M'3?~28>~=5%ڱcx -aV8$tB޹8aM ițo_7ìں"?~K/yțXc&@:c: 7:ZZ]N#(^IL(S^>kힱ=NwV<.^c2Ep!K%ْESk2fb $5]jrafۂȉ*$U8T>*\&ve],OYQ _Chƨ78ZMD C} rcn8c<SW0ub,`=gRM_.Zlб#'>tϽ<ÇَZzZʋjv3q^j m*U:SބWj%˴AU#p,+IQE!=΀NX"PAn6v}.dCuiAڎJaTX]+fGWQ<+dSSF0\|L_'m;zN<0O$a!V1jAmV@v?Aa5GȝBL"8:`T$`%=6y 3n$HRMiHCZ(s˕jXҤM'n/gKn^\#?<4mLK&HzsCn7!-<>==416:2qу19Ш#X,?{XԕDHR,R`G~y2K h[d4g yXu Ӯ^9ңm's;vwUU <\G&# $)8ʥʧ3+1.C{spv3i;e]AQVKK.jm\w +c2iK Z +ۚfAFic$RR-孍riXX\/7jQ͒m &aD2Lz J$3H8J2D$cPŕ&h1/¹ # D[7|pB@ளi9depHfؽ!FLB SNs,5Bm =ރAXfnF!g;x|{(D[k+. T喤İ|mҫgrCYn Y J[FnU #ǂ %{{H8M虠3>pk<>E`9%#YOM oH\~IL@tZl|w_2E6Ţ(soOkWzkh4S iawh030DVN$mkVkb%X5@{,vEfA F#o[ŭՕy?횙k+[Ȋth""~=tWh@Q0߇Η9]zBEp.4rͯZcDaQ!ﳫ5^bzsM֔}&w%t_.MG}=r]MlzElU.KJlU! o H|D"Ni$is,Ra8 K"#E~٠7ĢC>]% 5#LG"d Jhmv,FByRo06Gm}HI"lխӛ9q?}g;oF~k-rPXc̍scb?]W&3Z,$rX//:F+cc\.N (8ha4h\)p2\ToXlUYB2"6In{L܁Q{E Dkbٴ$I|8T 0*5@?>DsT}]pWԙiP3+=>OQ83<3%Cx|%5m}cB ]k!<pƒkˊG= \}KU0΃Gn8q{ t)6+5`0wF]x7#'_aWtu/rVld ٲ-"WGө F">Nq/.ÞLgh":n@7JjDq?xᇾT}kGY,MM:`v|Dv ,`=(^A !]/mȁ}Qw*PBp"ZQlXxmܯ~q7>ݪwmN^yc7ow6?E>Ok9UY Z/nYQ7™c -*8D:;'ie9|8!iXn``lL8m>\BЦmX@5x5nmcձ NLܬ L e[Ojˡ[.`( K=I\WP?#Aܡ׀}8=fHɁE^xYw+51n?>kk#Vf́p<}%f}իW[dNa:xFBD0'T0y{.O>d)9=0`2IyrpйXG> WD%rs"x4  C ]rax*X_899\8 6P;hJ"v^-:mcs;w8rჇncXf2,d<]+N;J㭟xkimXV}ZͺQodFM'.' eC/ _׾+˟n=n[> {osIٜӟٴV%)/ [} )hY:ջz"hK +jak|vi嵭máH]i OmHN yeuZ#L҉DGw۰p4 w3* h:`CV8uz0] kӊ2vвrу(JfR7Ob{hT{]]\$fǾp,OW"y9FHQot#e6vdf{+}}GW~1魉ھۯIXzb˪ [`.)9 10L#@c-]7FKo:2m0 [ꊪHOe2r(tG١O"+X $4^,xyCVZ2TmН.zx8zQo;${Ç&Gi:5ְ̊wqZȓ+/xfv 4͡񡁑 Fbu%b6>y anOE#iY\⥫ҙfuC/*DC2TZ T' m`W@KUgo?pj, m+,<;0@09=+0T="zQlr6.99>;^8}^P*CKՔNAB4d17JݤjZa JE8lS!ot m(fI6wu>xR1&~ڮөz<0>)x# Zɗ*Ngm">|x &rB 7Z銣[;;2Jr(;vb]V1-YqǶF=BuHi^Jfh¼}d?؍6yk Td`eɽ}2/o}ퟞz|$ $e0Mp"#.ޞc@!ɛ? mrnۈCY4tV҅R|ߛMFhC#PE8wpnO^:}6Ndc źXܺZ׭9rxPTr$^H*ug/j_¯x#|p譧ʓ;o#P] #}vMs R^cH2:fFm;zhYkӶy$rg0Y"BӛAYҊ"iTz&wIF>uvW"9KM6xcΠL9r5=8-B_>PB3yQ)BqS&׸XłrQ+ 4tOZzG'[3sp@ԎtBVpo-pՙ-V'"o;_/aX5um $;oawr1204|J£|5ñ$3Dʂ20 K y:+!{Sqhl/lEM݇:= ܃@*\ ,$)V#i1F%׿GBRd, 9 joZX&5=~G 8Xǁ{E:ŧfo[i쎑xph''k[M}kZuuchvb|+6l5vxr$ٿ{i'>+?9&\a*yJ(pOUo鹝X?IVV ˈ E2 %,6d5K"dcc)lkl`(L{sgDvhnjkl^_9]Wn̟y?[SWNۜ0!XC5Ê, 2 4u![zR)7斾NVnL1 o69wξڛk+;=2%dTr1j}C a[l ,vєS&|8@tvZ)n06>qێvܡ}##%6zasU$]EL&wQ(+t`R~׌_[8upT,M$='Y䕐+m1lS¬6Hpt=9cEѵ$S &nsJGL"d.U?jՎ{} C{,"qkX&tVF $*,t=5] lM¹/|7ei <ð effUAC6<Ң0<Ͽ/?^`Cя: I=4|*EJBƇ wje{7zwiѨ{K+Rihfon,u\a~Qc}c}cZms1c-%VZ[kfY7rM`eYז.(L>Z|Cx1wZ|"kQ.Mp@=]yUGʫgaxUcc{9o6u0T8ω 8,%rcX2t?-$)B)ǧ㨽h5yuh§4;#pi:G&*8,` [PY-`r8+cpFқN.$#и\uSdٽ{n[nyHR-am'dI\yj!?vxݥo-G"{>Zy7΄s>>Y/&sw{G5]P16fu! bIu4UF$sՎ-Di6 loFQ;ɴh$Ê HlbD*n<~geTER5t۾ hX i!itNZރM@ӳAD,3jQw&{C7 9;f V-{#Ko>\8whLIaCnH Y>3SupANU'`"6GbJ<Hp0\)E5XZQ./x'!؈p=/j* i`YQfE>pZ`Ňl7rl˥š8پZzqst:I f>v$0zpV01?3dQF/֐: oZ^fYw;qxRi on._ a kx"HCJ7瓼>52;6skOg^|eam-R0ʷe\6P)hA ;T`+KfXȯ*iw|߇g?wwNOo|\nU˦Q")-^Z"Ic_} )p,L9y"gat\@/؝xN &P&nI*o7)|B3hJThI J!dz"ULID ҼP$?4;=>7O֯^?GX\Y G;G+ TTɰ]U@a u(ܸQ(Tz;9~Qڌ~O` oinfe쎻>|C~2Yel,nl\uL5b6u#IRA8ۛ6 Kώ2Do^ytf`p|/>$wu߮oB($?Pc zxgT7I9EuZ/6-iئ|zF- yx81>73?978IMMOmŒWڿgϾT(qi#f%/TnU7 7CEP0EPxZĨjTyubr'>p=?{RvT)mئM ;YZCoL8ϬY{C۶ 3< S6_sfbo+c#qj^*,Cx%b VNlҺȭCܙ)΂m2jЌݘ:>j)v!Q{>4]hYcq02;AJģTc5u$fZkzl1*ϩo~72 :H#(mC73;Gϟ|g~q1!H":pzlBo^V(7ߥqB{|$֯- %IS8H\Q°z(s8\= zٓ}Asq:zr7q§KAkK+2R8tSvspj(ӗ&Y #SS#wS$t̷M]'Ycgwתu#DpŸ( |RpP<[%&M(9^"DŽ`ݨ-0#a|(QqD=~E5 VBPcˋ |,@Ont@!)wꃡˉ ~B*lx*ģP5QZ(ݵ'8b0KȻDSD&_Ut4S+-~Ojc#$s-(u|AdA` ˥j/s̑|T!vS!o<$Ym۞Da-5;B'Z&NS^Z#1npױ[zfFT[^Fឤ&b.|=d GZy'8wqC*0";\!+kS;}_w߰ĨՕkr܊6KNaԫrRlv2cÁߙ?wڙBe+xr`X$ ,o.GV)B,3@]=๎M"d|Lm\ʇ䶞>h,oV,=*gF&k٘sǾC{wyrc)u{10Mc!?} ȚHVJq|:!N' JZ $ Lo_<ݧ(Wp'4m',ngh (T"B+*`Mϓ;}ʚۭIw3_z}bCd8_-,^<_Z'ɟ"7]fvu\vY^6 bL tYtBE0_Q^K[O|Ѷ^>4%e:%qHd.Q @yh \`G8B/]BTLF4'_n3_pm| ە+Qn+5ha<~4@%#@MI촪|7>A^G< A,@ώ0TgG:*X"ȮT.‰v3ϩ9!`| TLRR,!OB2[y?4B^5Q^lTI R,dR.ke2D_\ fO FґD6) 7=4y 1U<]c`x^dURȤp|?yL|ti^k#3.Iebg.Η+OxFR xc+5W?_=Z$Vn Ê|wSCnVPd(!nV`5ӰDO4" f҂X.h" dٺfݳu-F[wZ$l W@Ghmݭl6}@?淾{='nۅKo2X$Y]@$"O x|*`r%Q o4*[;L O Nv͟|G+SOl5*x$C&ꇳ8iݩLWnӔ'w7_˙ "vجW*"/w>/ rzpuy~Sko5V ckH]<;oBDfhl`h,Y,Jk9@Ud p>VSYUdx:"  CVi<+|X6yv I"$.6a Hf9p[IgdrT:O@_X1Me >@ ':R7O<0V|Qf\ϩml$-O 6,ljQ1'%Z$fƳ8o5zŽ; D% NT f=ON6J+ϼ +䍠;ѭ[L]4֖6KI M 麾)jDwt8z \G g[]RUQmtylDBkdFrqQS}_!d8Dde!f5YEQ"^I:䗓N* Ln0,nl(#pjaʛjͶx`d,6fB )6yR' ~߿͂OߝI;L FZcs_][/X\Џr50eVQ__}SFp鵳W/\F/+¾cA&83pR(J#,Qj./T.0kK“gEnV$mSY y.YQnim5IF|H $Ovo,)8{uA?¦׮BNT=fgKmٳG3F4@T#sQyiʔPJ/׮ Lz~7z<Υad\ OMphLCl/1PPG^wJPnzvG_'>[o ]!5YYߑ˕V-u`<4pU$04Ii(P_B}y0+ = hy%BgV:~'=@<%F/z: p}@Bm U$| @J0}Q SxË!9(wUx?@b@*pz)'=JHReT dĪy.-Nrw|3.QU-D!Ԇ`Ո`._BǪOv,-.E>ҩkF8" d Q``pvF:X5F Fdپl5eVȦݾ{o(6խ͵FB{H" T%4Jm}w(#$,ds9^@.JpE`յ gxVM6V\F-SY;J()Nm70:gR=w-'j~$i,8e@Sq6ĮXw0"ԣ|ҙmcLZa.k}Ԅ $i9k1, [ZͶ|AP‰T4ab Jhx"*IBE\]'01*QPA*5Qbˈn=;Ͻ"(a r)j쪮̉Pm_:w.svE)98B훋EAT+'߈Ec!p 8rjlH7 ALq2'D\\c5C[mp7$ Ia"OB$߯w^lPB@T]^Sh8 Hvj#_d%; ~+?~D;nCtMC"0p>_׾>ԅŵOQ %3QQ4Tﶻ/>|.1:FqR*rLjZY-4Cn, .u.$0<x?nwjv. qIȯ:mmHBTveZzCNh& J}6IfSJT%Pjĸ^Mē5߫VWνiX<7duGo1A5xre7d-q#w_^[9)F甜K -a"qV7wyp 'jXZًo:;*2g1+t4 &#]裁9' g3Ph+8f'h4H M[w}ǻgd0Q"  HIyswu\7}Y Uu_Bx!C11fۂ'?㣻!+[˫H Of^и DB%]9%rL}ɑ1%24ӲK>E7 /d64dc.Y[Bihԏy@k{p&f'Yڅ{gxUF5I:<[֔L(0ǷC H[YDkf/^^^R5]p]|YqХjsR㬤[uM]ͦ{m/?3燽?$wƃx eef $8B$4;{èxIt"n=/CQd #iv{s3cBOjݺq| lx@vJ+_Ǿ/|6~Cow64+œ'y[Wxg_xi|*.䒩x\S86Qk0&|;~郿~hJkCD-OL(hZMOdBUIp>wԡ#/\8$.rc{{( 5_M$dzD$R- qN6 "3 4dl(/_hiĘky]N̕vY A40[6;gN{37o\YZrPhg ż!8 ra䩤BP( KeDBY@e`*=zD\dF ;! 굻CK$G~ C{G376ƕ+RQ j*ii"QB?D}"+&ixDJKPH5ۋp4qfCvڐ|DEGh(cp8#"օ;˵|߳h]@J2@a"=42Gd"-1T! F0r34!U՘Ovg$Fpu":*vp;8*2Ux#]kЃߣ&ZJ8nD>Q/3)5 %#ãEd{>rd(,<G(SmkhCxrEK-#0<&Id.nԪ+sSCDbht{0Ncť˗_x?uvױ輻ÞGO=Cn[)% UݨW+jհXI$r㣪" D*v|QK W}SCdzH%q{pwrytBt h@"vX|cib)>ˎe-T-  .z\{hsܘ l(h`sO5%|.T(VSBlAH1;Z|zGxDH\gPx݋$GYsgO1 v(!Gr +'\ ۝^Sxh3#%%gDq~-P9)pLC 98i(-H1 BB=,u~F,ž04:X`fI'.ECXm'iWn.}=2^(%|Q,\*>Ȼ:cPD0ڬ84SEY:ZѮ7d ]pS'㙸')H8/%fGvMQA0lx)S#}{sk_{_y⹧ ?>2j]pOˏ>}铯V F2c#t\1˃(zگ'?~`/\^_w0Q-Ύk) m;kggJ#{' ~+9Ee$pTD9M qYP4%D6% O#Z%2”2pu'1xE"y/BENW 4(&f1>%[=K)+I/-z.ۭҙ 3#)wh ;Oom]zG#-@>RC-ı_c-#1 Fdr9*=xHԁRYۚ\qڇ~>~{3ZZl=ς yA lWs3mau;JT fL,P9D>2(G!3'6L/.' |ŕ?V*>Z@3yLU0@PY&fb03Dn2"ƚD:M*Qk~tL.SMs`Ҿ_!ey.H7ZO"77"e!r^ B:ba,Kx*GXl6jT*{ ^>(lDzjh5~܏G?{jat:^,d,J?&<tZd&|>|⮻2fUoVkfq~1^kW^=iIJ3t<ylvZ[ZC9%N$+#JHfeXNF@Вr2'52vpaGޜh&؜ whG?smv%]UW x^q3lcur㺨U1+m˨O;|GOawW^vW-O*2K 2FLq$I;J$Td=v{%U(xf.}ÿy׃֥8'ZzgC$_W!bE .= )rc*J| p? 8TA8F5B mB:(؄{To&%VApx|T;"$3!?"]c-! ꠔ eb6'(DE|,x. p3HPlb$C݉Fө-uD1Sg h'x<#H#y *$%큇 ZrX<IElPvOkN b<<$qB>lCRzGT\X'UEM˴l.w~K%qΓлOg`N&]y.^n( ŵ+KPU }b>2ƥ5j5;xDV ;5 8/}7;7~?G/Zn48O2 qK4hYo+-s~߇|XZ[\UjC'D~l`\ެ 6#33tF9nn{B\UEAK${L4&+@Ghb(I(S UP c꺣'D(@UŊ58.ID:pU0hc3pt {3Du[֠A0uoy7RT.Wdu|n{_<=wbd(sDg4ٱPr MiIDAQ&E D.Tr]oFVowD"A*y⫏oɹ5GeHHbjB}N& KD=#YP *GwD M5cq ם7P͇C 'U9|~APU1M.X}ٳq>KHevI<ޒ2MEX!jIێ2 HIv7ؕ4#i"BB`jW]IQ\U vuS0WZ;>tJ - V!G<>GHeh ,n6GYJ6>-i*~]e!;6Z\"^u`Bx'XqT2cmpɘ/Jjy(`BN1O!ڵKVv~4LvTc6z+O{kPT\]]3z#cEFCbdQDgT˛kN* T! 1 D%?6==wvtzu_yɯ]u82}/ʓO|}`!L+Dt-7Zs={ϿOh߯W5=*Gsp{VR9 kpQxV4r<ʗ9!#CrVBy:Ҟx`;%r,u47)34z`${Fo9&+Ad5p8)SZ+D.C@DRdhn׌^01vd^O7;YQ 7cƸT 1'%6?Ca_7q^7qD/q ܮU[ }Û~'?azl/<ҫg^;{#b1D^N`R6]p-0W?BgcS JcE4xQD>iy#uYEEB%~II1*(jxibvNV氍 g$+"fvv\%j.P*W#~;B5-D6z" x~y6xy/Y"l! 8!>K>͑;pCd>kfn]xhS^,A !IFQup$x:2gN]~yV#g/.lUKkz@UMi6{9:OT8BЧ"t]02h&y5a-,,$n]mw;^}}?XPloڬVEA~0YHa&r%_KF'FoPtCQo"vE^lAȋPC< C=DJ,EA<8WάIY7msX'->7*Y*JviqY͓nV :[Mw )VmmԄPҮIhE}ʕVrt|df(hNߵ^w{S2U[4ꌅz2-*in}т&91wϞCBYxg^ [ծ^H'3J>W_.כtRWZ#1;?:vבB6Ӫ46ʆt4%2iZ[gSѢ*m{= ;͍K鸖N+)$* &Ĵvx< 7pDAQzBjY:|UcyV 9Q};~`v\g۟fOw罥A;_$Jx8ڂ0P~ʙbɟJdvl"1$xc/7"zJX}L㲜eFE[jxsPFN݅\$抹nx(ۓG8;VUf* LwiÁrh & ACOJ\>&5/XFߪYm[D&S)VPA 5ÙgH.rb KZRqϢ'ae/*}G2H1Rn& # +x8d#áv,Sҕ!D\v3噝 #^U5UOe i=I[j+ (дtNC7Ϟ؞ÚmjݞmCS DTE"k1H#o\ S" ĭbYbi m{(ƟK=wo}x,^БG`u#Ž{)]o#>wO{C$>v!߫x}{5`,*[*dND^p'pAgiǝhЌ!7h+ X?&#uIc3FV<6hdE^ɗF9m4}No^{B7=ݛn^ھz1& I5VDt+)jRKƖ۵ |dtq|B|_k篷}綯=_1\/f gD vLIg$i ^vIT-?-5ݍWڵ 3xFg<|v]SJXTizFXrP^GQA<iH5.[36DaՄz9ۅ ("2oZ8yEDDV50zvLMcc[f#&rHm՗f{c33|2S8;[vwï}Iwu Xv|^}kNQ QgU jám9ٷ8g򵫛٣w3pҞ;oWVgP7mgEXd%m#E]MUDYBZa$HM\}5}Da#O@ Sq3BkG6K^pdu*䑉S.5h7-^{3]Q h'v wuZ!x1 sڕ^kvLDya47: y N*.|=gwlk:$! 1I0g8edĢt( ppsQAWp$:hE=:D{d4[Q O-uJbkD}@8Y Ȫʆ_?ŕ]斐ڹخ9$^hJ[qBX,\;̏{vwj5u3y56n49WU,堞ZPKBm!WU7Z[kߙ>{dDu}PUsfs97/p|=•AL' YP֍Li lZH_v\;l)81>3{fm)-5Q*̋Ѥ[h:1O&B=_ѡ)&Ҡze?8rSr"٭]VT5@R y.JcCV9[S8aaZ /q:RazuQH}|c0';9azNΟ+\Oe }1P, F֋Ld y,h`v{y=xˉ;]g_>8/9rDFjz։O@Ъ'Qti(n!GDd:ʶHˉk\dyLMPTa?0_ykCy2frJ h; z2 (f1zd,잦K N2 VI')z̥3\cHfP=ZD2s94uD^.g'F8@9Pɡ78184".|?AgJ{H-XH개cC]FVbԇn\.:D .?Pס(pdiyor\pgO(͍LnuϿKgFz9{:$n^>qq*Qd#k!X(Z-kH?zݶ|cPH{omzmc'julMv;`N?(JfH{:n7_<^7626Wn._\ec{vF'⪾x[󿸺4F*39E}aELCvXͭ5v#"noo*f*tEI'$Iȏ&Ez+ ݦq(s9W:<|t #CݔM,rX]sc;!^l&Ve"KMגRkm$vΰLǼ{3#C e ؠQv,$QY-:'gg~tb~<*bA׆ .; 6\_v'_jkP>!%C7ãIʴ!ii Oh[f F_Sg?;t+/K޾k~`S3ŋW:p_::Gpa "{h c;H[Jhz:A)few1Hlg5OH1HD[ā* A}"&$ Ihˏ񑦪,°J45TK钌&9ED!za\@Y|4Ǣ%fC YA.ZoUwES}!>',H L pbXG9w_ 77z^q/C.S?y_Ls}]t G8ty5SZf4VÂ`gh,-UfJ\.r6cĨT%S]*' UFe%T䒽IlcJV:8U'?&?]TXF-U!| Pe-E$/"_kt!Z* r.!(4$%<tzϛ ;&$FJ!Qo O1@ W4wLHza6=:QDL12?3@GM0wL}Zhh#ц>$I,<54 8(4D3}%ba:k[Н$]T!d/+EUmCinU Ӛ>w=|gЪС=pĄsٱR1/ Ky[NukȠyCfzW*m5*k[N7.A'zU|ZTij2?{ lKKP zVeqke;evύMBj??_kvR|gML& MnzL;,RjΣ*'k zZ.T$14X1l7ՠ?2MO삷lPu19AR96MG5?ucQH)P+ "z2tڍjSshbJZCQϚkv IJNq:e8nuۃ(fD=]V!fx| Z~tD6Wpz9#3R#S]vG?V,o?~:>=;wS˕ ;}|CElvv]YzpnSԜmrf8?_(L(9@1nz µUvT[!g*v-H!šEnLDPd"ji\>/(dѫdwj(ʐboo4njA@ƃ RZ  ~vh=Y]Z..rN7MD1/Q@؎=evHgzZS4EtSnRrP,O#>vAFIN| }QLڎEg->=f< 5IpG/($>[t޼rYCz g B^kLZVUp ̾ħgKH7{/!nnq \VBVjv́}/W^̕%A`Z[.oI~x8$i¡q9pxʩdej!%tIW\ߡiDȃ#%I!:DG"p >BjmH1c_T/ =5W29Շ4,h- Ijn!j%3^]3-϶E芋hn_=_-yzccy_h#;b.Hpd4\]m=SȌKW[$rE%2#ˆi9ήcwݿuɧ~¡{9q}cl֠IgL^6 ׃/{o?X)wB636&#PE)d MG@Z>m܏`M;‡ Dl͉!<.ɕ*#|@ɋH?D8(E?B0~&=4?șƚlB%„v,YB%6hYZ]ƹk>$ݷlk؇仦ճ1Lʐر4PiJL;?F#Fgkn:lֳ(o'tO$l5{&8Fx _xCzg/~K}kލUȪBw:,En a \}-.;TawwVzWܖ.nY4;F&96{`O:77V~oӧ>/r" ]ץj*) = ; )գ Y<1޲No\+,Lz;~{=qǠ^_Xi9"*!Wmk MLjQScQmL.%OΎ;:1;nt{t,0.ɣ>.$3J 6IpmgH=]Fm9,&2y8F AeN#y8f14pxx>ظ5l4dw84reir] =$Sm ڼMm+={dXIuӓݻnu{hǧGsN}v+3dbdTe ^?ur}˛Ll-/\_\QQe:z&Gx,Ms%DAv<`pQg!B  i^ܮ+GsX2Z1nID8z<Nz \(r0)7{G(x>6h(>@@g]-N#`q7.WN ʍ]*1񺣷NL`kKW|A/7&I况NݨYUJ="]B(+BfykOnηXH}fOTxpf*!rhu 3D.,o©ܨudMJD^T's{qyQ=v֢ˢ(APmYR2*$$@@xS0lIZ6^pwPSRJXqL{ )qe%-zS݊j]Evncx?cg ڦȑKW/D6+'$Ymú֏?0eo9Hщ5FWTX"mB՜³7fwO^.Zw50Ō$ e0+Z ^^mm%]#}ԏ8c?z8dAG"#5&*Whgա g L;\ f2VRݶ($=1+JkA@_GFK'T:+fTby8.UX pH@%Qk.: ^uxn3Rg 7eXɃwڵh6 vq5?6 A_ݖ!>5tᒖHA0xfFU#d\~4[Fz.A ŦVHJZqʥ?wz6EIG2IU%GߖE HE!HT!4ZYNkT:v]SǎڅsZnǰZAो㥽{9o4=Ƴɟm\2}䈢co=կ?o<\4Q2K Cɲ@č7ў,2bp-luͿ;>07+o߸vm왙3=peArIo6fV 'wR%1MQsc~_+g>`1[F˷xQ ׬,܄mkm/^r|t!O@qիlTNWׯ f~~=V_m5ʉtfjLȹ})*ȏr< ^n8@,mPI0 d-e 2[%4uKdEL/1:5u ʥ^lTD:5>I|v홤KgbLdy76d7.oNwؼh<^li|*P~>&ŮP%V!<(R \!bxV6֋\x-|s!`h cD 2b\vY)"'jWi-3/7$4k#w$[ R&}Z}9ʱ4%!@)k#"k "(`I 2LJZ|LON90:5ܸI[Ơ]](!oqF_MIe(Q숾I@rX"$a6x89\rAv Gs ={4Uh.ޓ̎q!|T߁E;}\nՖ+]Kn9:;U5+ SK$K6"C 5NͤG|ӲVtQTVRzOjr{{內ҧ?w~V:l>9:]"dxm+mb5(قQ4BJx*+.eN (=uD!O;۹~SO]}3_^jv0!RX4UIA>5c7bgBo۵,?G>7=p+џ~O]=s1+]S{vONeo^tZBOkV׫Vf2SsJ2X;O?sٓg___T}mj޻mjn*!XQmdNc":^` 2B-կz%h35pf{ZmoU+Hlό+ t,4A$z:w>DqFFcY2&1/PFrP=C!B?)=iɌ" e1.HSZr#*k/ I]Ocx|k{G_xO?l/N_l , *ۙ߇A xïoWe~QѬcW ("1DF҂Kwܾ|A,k{I1̨" 7φWVm3fYza%=6+2ۄ G#LaJ: x-~# 'MTBҟѯ.NA~.m+ i@1d:K kR׵:|Df$]֒5AOM zRPeARBȪ7b"nX BJ1}]HzImvLQ5{r@F h;;&C;:9u=7n&K#IU᧫[zͰk}Z;$6B4$L JQ1}ox1!s"&FGG^ï<|S篔m(KtRUx5+EH4ljgEia ~#w6㷫cE M&7oTJ1~/3}k/VnAjl-˧smTR-h27# BCpoCw@N_ȍmouQD+KݧC͕3xub8kĥ,ZWwn{4Φ&fxZ)yçO7{t7dC`M00yȈ*:QCKr#kvjD6X-+|r.fܐo~XFmT7ouKD&H Z=nd$GވD>¥W-?3q\gyQQ$"J].Y]3ϳ#WE q"(ꐌR )p BH@mI ЃڍUU80{tIXދL$ '[潘cp xryy=ˈ(|^R$U'0EHeɡ G(EsCB,*?"O3bnn l! /_{{/:ueymy[ I+0є+z6s{ݨC>t]?>~B~1+o?~~ZFl=dn;͚ҫ7+@y5ƆVmSǽw)c3zRB 9^ dwDQH 6vL٪,/˫fv!27=S3ؘ%HaXM=deA I=x4cx/؄(ikf`YB)A`+B IAc<*r^i|߸p՘ ? @OVYjLX/.*tfLVDql_9_LMؕ3W1AU41 H]`(c wMXo-\Ȱ׎C̏"Ѐ8R '(qv,~X2vλxi#L=3QbzRN Y7QI˶: % eI:ǘm#ClaAq 4\-x] Z HcF=?r8Ր8lڰ4{];uat2/B B;$Q˱h瓽q^P܄#Y/zd*eL]ơ8f"*i3Al1NFm xNTL 1AlVnPmض {_~;~޴{Am 5+$Һ.z]m's溝^Gs/np!_AUv`8O+]Uyǎ2z7"]h)1A%|d.E\4<"@d ;S ~U6«Dvr _Z %-h)"ɁP@C11v׫7D1e6:-Hză4MlÂRDMeNt'bDviY/*d(ٔ5хOjkĸ&~kW.Cճ9ENə<䚭ǵ}ʬAwe5;tezMdrb(Cqr,B Zln//i%s]GFD qUQ`>uo\-نgN棏?zjgTT闋cҲsSZ )\ l>9 /fl[ 5EN34jխ+Ï?KlCq\b` U LƷ!Swz^Ӌbaqy??/|7>HvZ7q%*:rxņ/pG}8|w0=w[ɸ7iX#^>O  aO5iMhً'{ UxAsg) 1207XPNbu 2S$sh95&q~ ]RX4]L\c 8LWctP+ǓaY*Q^Z{>G`pj3I0F}a`vu c@~, ~4 [VGQkjƞ;<8]嬵oOJY ˪*[Wk9[B` z6o3_;ǎ.]|.AR~^*OB5Jղ-vR38J0#3[!\ ęjrs?Tv{5P {WLG#8fRDe*a,j`):fH$,ۀP*I! EI#RQŠk<\+)8LCJtZ|o/! ~7X92x)x.ib*O&ل[E^X@&%!MB&n{sI<%Z!yB#d% q[IH Xq9NRq=\77 H,KUZD)0e[ #J$v&-B2e#wd829A'mtz<ˊ1N:}o(D 1DzqMzP:`ԧyi )AGrtH+I >vͳo UDN)h40%ɇy|?oKgδ><ʹ\l/f*c0H$-8X,ekBaf M"ꬱu`CI iRU O6H)\$OtZQe2 `|ҿͿƬ=NvNo{(}ߪȈD?Rv pCw:?u |m~J&zB)7~[KOHi7kv}8\DҾcIhJRLl[&uD7\A1%A!fl#7oK;sF!*iD`7;f*[ ѐ5՞Mշ:NUhZ FoO:DBmZom\_SP,.`FkBc]VDwPrA2M|" Zݏ?_qN?߽jcuVDvy(p5SWOm9p:M 2Q؅%>ͬ[ܤG-`&cG\X PMA WVPUM^RƃAN K""g Xbc'9SKiI5@5iN$:Α])Clj;^8]XX_?x~C36vGިio= D湳P gw'qjpP(^kYv;J1BDlL2P4Kf1 [D*k`2TSI `.XY-hNZK5o\Cw\yy=8,+I I$fʪZK|L ٌ7z^ZQ0:;nq~.W! VhR,Jx|F}^6k :Y"YY{[w}~S47>{Fxݷ_GqL]~ E2\!*,iN'0:JӾ~LIW~oRJ^2cqBb/(Eӂ*A*ERj^޺~Q(_,C)a覩Nki+XeI>RE2 cA+Jl\`ҵsՊ-^{}Ï|wwah(kex- 'M[w9{8Bo| H%) m t "A;GV;LP\ݨ[[Оɐ͋ }?뒤ˋ+x%Db YBqfrhY1HC(H֥A{׬KE3uK#O344jƉǥA c'˧vuPk^ˣЙ[VcѨsݽ[so??sϾy LmF:U\?I!fTCTn^, G+ӱ%83SDž qec[w t!Ij>w3Ρ2/MI_U77s"=Iu"Uc! x3>'۩;Ͳ!w a^:đ(+ì^ ^n&!%\x玬 2A8$H$5QUs׼Suѩ85WEMr{k 83eF@”4Ew?ȖQ .R&CLl 'W IZ\ud`B7dJ:S-m^w߻7I^Uje4t9i2oϴ=HJ|U"#-d{`,ۑShXg9Zim@RF=ҶJs32ϟb* GNs8sɗ/?%0q{kssề=뺳1XpӒb70tݟ3+E0pOD6ο~g!+,29G?<_+k7u"R8ȥdgg(zǫ GJqR+VQL%MdJ#) .p^ D?BY d*Z5˳d޸ٸ>p\kA͂a5DFese)-@yzQ4KXZ 0+LQ?b\VZVm-Ŏw+\Yl6iZ<m_Xns Wׯڼv3keSSI5q̡.&'"qts1g@R߸: ӠaB߯,ul'!X t'(![L1 / ?PBz% [?{ɇ#=ϭoN,[g% E2 FVP-cKL6䙢 ҘN EhШ^yPb%葱wɐ”R{cNXg&R8C&^3tF'/>??nw{Ng2{( J9MVzh2_j޼tťeEﵧ(ƞކ/hy-VJˮVE8:NNͦ;#ns.2Ed4EtwߌGmΜ~繟p^GVH&nl=JTs zFfύpd8ؽ{[a4Ғji4M@1]N87n{=(6q.e,ǂR6d!^fJ\2 G7u+[MBD9J6W΢4\JO⡅I /{'7z^K[߾u '1|oJب }㐳ׁ0a6LG?QjHvnJrB<+V|nČDM4S 5<ϊVy|  ̑ӧh-{W)rRҖIL~7{>D5LT+ekfGħ/ $JsMTe)X#/$ |ee= e42fX36i.׭BYqowU/vB|ϩQ G!|_B)b-i`("H_>I( Π9YhA +Oo~;x\oǪ>ӨKEۄH2QWHTF[r6>-L6Ee ( LGmLрt)SF'cU,Yy|oQҟhJ<"($2t2OPUێWǟ+%ٟzĝv66QV;ui85,՛>x(p޷Z7{hQ5 <~@+vpn{xT)I7jw|/4xeRTKNR:h57w, U nwn4닇n^x'sV T5Th_<ėV k2/Iq[,k3= Xlc(Du2w]$% U4j b8 B !yӴN5GE5AR3YLnsJB4o(dS0I>G]Wjj:{ׯӗ̋o X dݽͭ^ ߃ił*nqëP?"c-ωTTD`_`u@8d S5޸rA凋+Lm$Άt\7QEڻ=ut} nŽR|،/'4sI ֯ZvA5K6:Edt8d۪ ]Yuhj ;a+]QT!z֞|Q4orW_?ˏFE٬D M{{+\>D\ڡ+DѓeL"LɈ 탉# SCGev ǕtQ5"snwk??gN_ J8W,UqQEDbLR<_IUr&I4DB ZtsZ8ڀ+ "`'qcR~M%A=oj]_N~VǛ2T=`ن=͆{b֕g.q6Dce)xP^8T"sڰ=:TJe~Gf٬;"f(*S,, !NWֶn启FNgҸ:S_wϒa8LbQV;֨5k㟴qk_0ȏ# '%qM;ijs]7x8#[EQAU.HnmCvaOPw^Pt(q$}=I}uTʒq&he絢.+4l'J Ȫ`nڙ^ޏKoޏ򡥕ێؼ~֕͝]?I^4 CAJJ%d\GQYr3=HPdR ޑCѺ[dWCP862e hVg`w>PY\ 燙) DSA s  T:Ya(ɤ7lAp9^qjMӡmG\l24P% 4gSNvK773-˜YLpcCCh?s<Q륺ޝYsjs*gʕyga~_}G~RlѨΖK! BbE|hF `(6!(Mq"͕ !; Ds>bYs )pjJES[PTNO̒Sj*VfUMÁDB%sC%eAOXOF&H8̈́.xAw+{n5+fJyaIjVcT%[,q!vk8"a|םP_,ʜ^-A[L.*~,fO0"d N+F,l+! yBi\ql{Wy;O(.ԜZUYq&2[1wqb1FcMOOvH61Tb}/riG31|(0tZ*驓9Àܕ'XT?\';JG+`צbJQƃ}46<{G!Қ`ʀQ(GbbkpP:VZ\zbs?2tB?Qq{>|wQK|g>| 䡑n#q1I1 0(&s"b 2S3 ~$ȳQ-y"@mӺ[jvqiuiQ[I+( 2)f[t:xNm)Ͳ(Yp(̯ xM9A$JG&Jz 1 ΄4b݃B,7oLriVTJ]In 1LSdͱpe*Eыx2i-!okM Yf5Ǒ ~Nɢ]+U, fG]|XbY0cNYN⹃_F՟(D{"+9e6w13Yދȣ#+"DZ Y, E}Ͽ~{ԏyux_G!RLvLۮ|ɢWV*K]6 MtKXhT Vmt,qIV1G=Ǐ*PJpd~qZ'YtD1:P)|Ȗ-Yz^(ڭeYl>ċvן+qG g[>N> nkkԍ%ީ.xFF꼡U 8OPHN2*z,$lGt@K"- (#NZCg\Y{x!Icq^%fmU[Q$7^o}=ktw,]YuЩSᒼ^HR5UJ,f2E;5QH<4sQ)-`͍,6jٰ-إ3Wty/\\l:pZӦdWѫ$(rڄO| @4,˩:5jA$@Eg"'H}((@R!/]@ D%{ pA:yꬢAld%Qc/l8Zăe cL3QIQTVeÚPi̭~8d(_@B8B_fLǁ+ⴻ+/'~{?:} ciV*\Eäh}In&|@|XΗ|9b8,s4#F&덱5F )r&D,V6NV{{KsnOӯvc'68< b't Lr:R4S+Oa~e$|CR8-A)G n{ ĔHxeŲ"̛"!I}>9( ̚XvVoCIcJi{ͬ^~(]obB^VT5TQWES*'A$&^zS O]<2Nsn s ѭ%.xk">|YnKF7 |,]\"swaer'->۾jm%˸;O? L% 1$)ƹaSBNuN,ɘ+}.#P$'oQM+{HgUZԺfr)_x1&b:VwԼqxxrLynٕk+A*Hb }fd Lb H:`‘YMt2T4&9 EHz*X&SzlD(i ]y4ndڤGa _U%Y7{nTfE!J E˱; i0Sku+tjm`qkCdTd4'?T;=Wg849Wֶ.o8~rañ۹j+ÂO;5P<`2j{.fcPBb68ƒ03 syg?]?eΣ Hzbi(6Xq(JDt^dݘBvSTQIonQV~SCsg_y~z}ՅExoS)` +NP=}UA¹jF(|.x޸QFm#jTi5Z4i-R#/^ K'N=og ~s.C,MQ %k$z+w/`}{K*}^6bWZFC[dH"Lیc ?ZJ|fVh]qy/<3 SB!۔1"Tdme$"ZBd[hc3sde2Qȑ:QYz킄u@By_+VJhų;JɝuW+ssFļE@y?eg' 2BQ]ȹU_5EDz-ȱ˖y¥d:͋Q:i<}!Pz*"ݍj"!i 7ػѿq1Emd[Tgi_ pQ)WkzsF$ -L'KYXXMo~AG.4loOߚfhswc\ں|={ CP)ԊED)'&l%Kb1G)[e-+ Y4 Vvw@#'BfУ[ osl@ CBgfJ Nь/᠊& }?(bIiA|\-2ui4D,2u3 "ִ JZm/4 &e*8<pb_Fr)B!28 %9iCe;+o"KӸvy¥C w?s|ɒ{dCpQE5:۱Y,'bQBOt_V7n n/y)PN8Lps'Z[a$U)JC;ͭ՛gXfVIo^~o~K'Zv%#|%`} FU狿=0r^}{O}ԯ} !bz!N"H:LF{vbWGPQ@N38fz u=qC9ql> \" ~h1OQ5L4S,UEȃĕ4ʤ"I"XIݘ`J Oj-[b%+M|27dqc(MdlJ3UdDM##;y,f@oR` ^]WnlۇW<>tVo;C|@2L+aQ]>ru0K5҉ P_?{(n1ɸ Yˆ OHB4nV! s;I]m$qdVLZ1-ZLiX!?wY-DG=7-[8!QY>nX$ȂmPݙ,` VUԪ(M+fa MB`֤;R-CTekhxMѸkxf2(ȒĖm8SV |Y8Qߐ$T^\&+tw}ޘ=zx}>ݸ>bc/-py7ol]ْpilsq.mK%:na&M~Osgt&,ӔgrQD7讗s:uRx։f4+c: 3 O 蜂G,*P,.L Qd ~4#]q |i2ԉ(C!(*FB 3IRlEP :7rlGe,#.?v'{[ӧW6O}czayRU`ժQl;\ZS'FFe-NirhH BbirSTŌ9㉭C"2DHj֩kk˫+ǭ?-.Qw &="EWSi2r8Lz6Cq̉k [9J@ 'ݨ5QMkpbƢQZN#'cߟʺf Ia,ɏ{LJyu>ښP@Ś3513Ɲ=_\rR\AXz]=Vm]O|]7p2${ 1ZT޸?L R?`2eIaXÄ pW/yRS Bxfa)wfe4{?~nET]9zꮥŒO8{7!@ 6MHY˔d?A%ό r D"AZI&ŬTS3O[Z!L$13bn2ͲP87͠{2+E(Qg2tc<L0~qH0Ҹ'}HPӁ?'t0pݑ̇۔q.xcŸo57 NǪ+nKRݩVJ=KeZLHZd%`d4o8 * y-9hIK|P疊Zdagۯ~Ǿw/UJ%Ǵ to%K+yi D61 D K^'fvy P[E>XOEK:dfT!6?xS,֐+@YSvɘ8q,ezg [M;0qݽΣ} $@3Z i]I6k NmEӍIy𾢚h3,TOpJJs/? RQ0?;hfW+pm &XP& {OT Z?ۊa=S43vajH*k*/jQ߶|cs$ 9 9Г3pZfkO>qя޻xh<~8hHRSU8$ U-@c'QqCwdחb1 '\I3ǘ 7#22>tժ7.^<O /wnm%LO۾y냳/\*ԴpM׸&%5HI9l"c ϛ9\N֔>F桄#75GGWX͉qϏq)cd@,["eJ$Z.4ҋ{V8qz|n aBג yŁ22r%UL74 ۷;-dI4]E 2^ N;L4 sI! h ʂfU0ڹ~e#j|Vhf9BOPCQ( Sڅ*8#1Pav^A!TjZb:7hK?ǿx^}f gX+kł L"` ;'F1V cf$(˥9ˌCy)s7IRH qȝ^NIB?g|!PAb39!b2[9^}cO\ᠲŃ@ BE%u]ڕdpǽfיN}Yd\@(DMR/-eSHކ?ݞi+iarꊈ[[?z ԝa[?Tܘ$Xq0@XD4 [Vk2@дV WIcSDl+ drV._pm MS% J=#Ԫi\5{&S_$!$d) "lBe2I##2!; S-Mǒ2vi1)9`I ?gl:PC&M~_y7o 㴲T;z!9wwn]:Ջ7v 3\bħ (Rk#{4-v2yw seX9bg69UIqX+0 g$)ט֋}kws=7C(Bq; *e-# p6$Kd 8oȸ3\ ݵkNP_(FnfѲʖزa(# 42@9!Bb Jv3 UE|ޞY\$%C7*QsB\F2FH,eh `@.:Pe:N;kyo}g^:9BԘ+jDfJ8Fu;дhb$,F9"9rvq&fdsFWe)L>O^vŅ4H:gȋ@+hg lM SKK+E hzo\p;*7X vq?·ȏP'N}]^+ oi4;Fd$fE3 fsPSvv'&`Dԏ+ipԓ2 V8!JmԬjIՄG,ķJ\(Ʈt ?<ʍu4.!XNZ4i-Zzӿ;sxsϿϜ*1t)Mmb! #E[gjsqFzv}H3E(1Mh+>IsOrY9\z~O}.mD*|QW~ڥ /šɖ:p, J~:;nhg9[%y&ç1)S;& N9)ZqFx8_bLk4*-ؤZ*.](}WFcWBW QPxPU"ʹRI޼v~̯l?ƉȇH$æoŘ0jɮd9=a/X8s$EHRlCT¥rxY( e9?HA:13n%mg9=xֻgm,_pdJYD_1|j065O͋>SzK g9a $[^^eCtMs׫tS]ǐ>bGh@mFRcw'T4u\ڃ:TǭKZqc;NU{Q߸mN:,C^J^)LyDP_(){- 8Q*Jwv2N ]=y'~W2l8Ta~g$]^~Jq:lL=QdhPiT>&釢 !)rJ:+I: e7JB q%S.O*tk^;}n Gfk,뗮^r~yJzplqlgqfiiCU(=!8r~ qzTKbQZ$RJfx}ϼy937}3܂DZ!(UJ]8e %A ,FV<XU.Ф{BF8'j|X RFVܒcӠbޅ!(4eM[lRtT/z63 e-p-TxsE$LG{I76y fLQF>\c>u<>\|Κ/ea*Uo𵁱/bJpGh +łT0cP [Hh6RtdӀ4QC>3 wЙ7z~iwֳϷ^l?1\/uz <Щl/v&Sj J*^UM1fr=PmگŤ0(O΁ ,P>: pܓ#-NI > &ԣ`b_9#c-B^FԚJ6JXW*4bIA0fӰŵ{>MlZ)>򮆧ЛEp/^#/ەvЮTe\>CVHtMҸ*yz9;Hܸtn8M581MMٌe]s P`zg;- 0EWƉ4 lݴj0֢qku˛ ػJ|AD䵫'lW8OrPy?q+Vj"sߡ-ռK%]jjzLơEaǢ82`@7l[NTwov^YZnN,Wo[,< Xĝv ӂ9z60E ah ]a00R*ikq)asRq~T)% WHjA!\IENDB`fritzing-app-0.9.2b/resources/images/remove_prop_enter.png000066400000000000000000000002711250202676700240240ustar00rootroot00000000000000PNG  IHDR Vu\tEXtSoftwareAdobe ImageReadyqe<[IDATxb`d6'`|&$@ ʞFtӠ B`6[ j@ĀID=.${tӠD@s/nIENDB`fritzing-app-0.9.2b/resources/images/remove_prop_leave.png000066400000000000000000000003121250202676700237770ustar00rootroot00000000000000PNG  IHDR Vu\tEXtSoftwareAdobe ImageReadyqe<lIDATxb`HKK X@r0>A Feχʁ#iPP!0{֬Y j@ĀIDf 7M# ZIENDB`fritzing-app-0.9.2b/resources/images/schematic_icon.png000066400000000000000000000027551250202676700232530ustar00rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs  tIME',fHtEXtCommentCreated with GIMPWHIDAThZ]HYILl%-mACTE yPD˾"RZ5VZ]>h 'Y","NlK-@( ,."f3sb3NFfs=317zppкBLzJ%p^' ZQ666N/^h ʲXV7alkk OpB!GMM055=][[,˲#Vf(#HYmmH+a,jr?B$Ic SE}$[ر/_FATS(,###^ߞxYvgfyG2}}f=3 kxjF0"II2 2 @&@&$$ ddLLIII2 2 @&@&$$ ddLLII2 2 2 @&@&$$ ddLLII2 2 @&@&@&$$H2PphԂEY }{)3ZVV':V%2 I/= lcv2"^fWG ?I2}[[VxfP j\`iJj[(&Um)^f4 ʎ$$mcJJ,]e )5 TU)\ XWI=TNܼHV[`ѸZ)^fUph|FKlsPzH`uGUX:n_,)r>'2|@ JVvZ1|A@:s^X"cJJ[kv9Yu,ͯ3/" *N{7?5z쌹zòko0vSkMWIjmyθ5u5vo4w3f7KOpnݧ9L?,ؾ3 Tmj{[֑EOʏ;K KA! $>T^_k޸ziz9յZ)2<|xㆿ4곩C.jݐ|5U6&d*#@&!T8?t?6yJwATSCXfe^d2dRÆj#Zrg~S^ȗ]WP $GLs\1cdȤb %݉XKk"\\l_3xP8rO"U:k>rוHI ]ԹKжT|KWiِU#kmG&Lbp,H/0eOgQPw:$$әcmO/Q^&wMxw/?r2Nہ$=S{޼M$Ny#ٮsϘ;t8DawO*>.mRE2vO+n# .)2a5a|C_XGKJ UM(+Ϭ;j z`Ȥ$`I]5WU[yE\J~Juz,I{0"SP K@jKV(&Hk(lSU%2)946['E_iM_) 55Jw@@,IB֗XqGAy?IUɋQsvT+& RH7pw'n\6 *)ì3}a)'O0$פaΒh:;(q$$H̻K#rFOe<(sVa'/mjeN s,gIJ 7V#'1&q$El_N$ﵷBΑ7vw3 YPqЊ%k7u}sy.xMlPLj{N.U8,@KKku30Io]̉d 9-v ٸ F+S(r6mF՟JI }[kvYx,v~նƺ"*k|);TnUzmb 6WUګeMD.C(1*g>e+ĉ|O)'_J61+^Ɋ ϐ2?5 /W'=F)wgdeQQǁ}=/uG4xh^4ݏF}RJ5l0@)<`2Ȯx{˺"y޾ ̄*izk(C F?b|k'Vl2me"NW? FO3G&3[+|Y1FXRFjS1iuSm 4̺nmB+7 -%IvH-ңI6eF0VmxZnL\t^e`3>J'L:ejvSWR&7e NsH@FpCKKWd9I>tɸҿ^SRZ;LBjY4{@0!DQI+XҶ4"yy< Fp<}>)II֚+&#Xc{*Gl'TUa:ybIW#@ 0|hy\ \\!EcUk*n$X#5. Ҫ$iuz[xHXI>$Cnčx+H+:Bm'2 ymB_I;.obL55ʖ dǓ$x%|9!Ep6$o^d;$bY|7oANA&V IY}LJ!R] PHrB RE0ZM drH$^I@&^)5M d@j$ϱwYI@Jd@ d@ HHtIq_v2 @t,SRJ&I$ $`Wm @;lB Eڱ莌pp mug$I֚]6>kLIiւER Ae/װzA^II }䘶@nzmIN񲼊M( mϸZɤIk@l粿ܽ1N$$`Σ{ٲ>sR6ˁ$"UXNkI8ZPқYwT}eISq]WN I>ǵXɉ8?-wI@R\ }`zM͂_LXĒ盪 ^R[zO{o}uKW)xYϬuTtT|OM1_SҪ^ZxȖmoRįwYp6j/">nHvBj5կf/JURjK|<(|+G'55v<^oʏE)cV!Gv$ʵ]Wv{s  3Ksrו']lw $2o#P٤m<.Cu-յ&%91؝Ȏd*7oqKI#7ﵷ^43luݽ#3ΏFtIև|GR>Yc6WU[Z I"s޸z9XCi6)Mɨ HUu?//nոe}>4XzhH_}e|K, jdj̑Ip͡=JYwH'ӿT{c,n_˿R\֑sD>Q};Lz|ӥF#x]%k^,)dyL7۷nKkio>aHZ؄oyqi>-\L|:۝%2_v U3΋|0oʴI #b#u<*g+#3vbݚ5/~a1rxzO1RVes:2)Vubg>/.R}xJJI/QSEf̝t՚ VMNQ/exU•˧?JYm%j/Iȵ'>#وUyZb.ܬƉogMҞ]J#K#曨$6K$u l7f-%kcnHdɖj*tL@,-=ui_k/_CLIΚ콮w8[;d3/nmRnl{x]x~AU_) `{땅XROdRlIGwm6ymhXtcIlM.-;T'#uVXVHDaսtV6C{ȵ`[͝K弉mZHlme O;R8gN"eKB\,dkvYk|nC Iu90R@3Jƺ4v6e;y˂ȵax~1jsm\]Ј:I]\kE@&yZLGA[ezV݁ m0]"T WRI qO؝{cF,FqeuKCQx'V7oyr{jF&!rTrKZV@IԚTVHvBJҪQ{WRcΣAQ -).^6#v4㨾YҶYcf% 5Rvu]lȾFdb.8F_*c~M?O*1q)$?wW8텿Gy:2}}\2)uk+_ބ= , xq< b(A "B ;@&@IMR;>cwdΘR9<9M9 4\L}ҳɘU(bósF-\lD&@8ɒ7$HbcJJ^\aA)vSBi===mm}}zP>ߛ?>ݽy=g爜3ڸ)C\@~-}o|衎{i _GHˤq{g` s^>8!  ٘༇t,@ɓI` ٙ`⇻I`&>@qjYK6c@:y"w?x@" z&v7kj7O7~8o=vN˿/ };v/=u1%9:[{=:"]Kܲn (lˍ$ uI`zӽKYL5nD]Ek^~+,ڰzҁ7ɮOv wK@ ͜KSNg;t52 HLj I]ӊ72I> 5{)p̻R=nu$ VlV $ uwtCLJR$$8>lX#锃J!IԞ$`cw2 2 @&@&$$ dROLII2 2 @&@&$$ d +F5IENDB`fritzing-app-0.9.2b/resources/images/splash/fab_logo_bar.png000066400000000000000000000151541250202676700241660ustar00rootroot00000000000000PNG  IHDR1Cx@tEXtSoftwareAdobe ImageReadyqe<IDATx]lUUSb飈TSPcBaqcad&ЉS&Q͂ـLV&de2f3hdm:5;#,$fKh` t;2;O{yys=}wbĹokB]|q)#Ct@ @ Np@ I@ N@8I I@ ' @8I $@ ' @&] 2skgtt¹3~Oy:b' "㤪{#EHIJIH1z3+7l~㥶]Դ-N7*3mB|^;S}H@' $>#0y)ouвի=[ĮhZ3eljtX(˥rnݍFu -.V~h_tceG|/iUy{T. )~5@ ._=Ր<|L79m~u*S(qLtp|1M!0fݾg󋊐N3;ŬGaGlZh;p="lcuW*8d̦5I[^e䥂B]끖Hض]5?Ë luOyv9Ф {d\ƥ>WIxels?eӃ>v{j>̳?>=-={i\4]aVAMONAmY90^|D1JVjQ39|5$IvBցpƅspV:8wzRUWфRN\Kml^?UYI Pa$2~ B[^z?<TO'"ɫ!AB# |կl"ilLC|z!Il5U3 ~/y1OD/d5=1cYT]Uyt`g(YV 'xY$\Շ1As5{̶[9 '5 ODZi!4~[|t^WZjU-̶Z 0Ҡocxq.S@XEb~«X$mZm] M!QT0M>A|NO/.qskHWF6vr>N .H3Hl% p^CLk#U)},{~65}oX],XXeB2ƕ*:lsw:Â9@1BŢ*: "JBy|x(pRۮAz eCb]䢑r::qӘAxnڃ[. 6|UΟlނoztF*pr Fct03³ehScU 'P&I6ClA}bR(dqJ43MU~#FK85'ִvp:ԑL TV,Ι!x>tqk06}mBHWHmt'erI(܃W $9PϤo"I_9*XC؅D|쬄\Xqu'zԒ{l mt -9B~ɕQiV];I -i==0n"ƝI~:ﵮ Î 8M!b (O$<]h:!\t#ҒOP0疑a(ΘхOBz_ޜW_ЩP Sc h*V4}'O$ІOy?g8朖vԠzVE5Nfouq-5{ K{^3pGV%<$\/x WkmWgCNg=s]mw_ qRmC 1CO2b{xAјlD^Ur^W*uAt @x5|)rၶټAޔJB&Bh6!LR &>^o+Oat?J o; +ԣtY_ ]YC1 ?9=Žwy# KXF08etWŜje빶FN0#<$Tzp5FG3V5r]!('N+3` 舮ik 3n huɸ}gTdFg6A!NF1S_^O+ Q?(Wju`[Q|'zU1c=_mjU;)2܂t򺄮khh+ k-[,"xbaPbEё >t+ 7ύ!XZP‚ o,\8J^eSWtb!m%>|n5HoFȴ:Ɔ-kpfN 2kpy٪A\"i1m2cn(pNbWE>m>e(9 q% zSt s @)'u X5@QZN/dĦ3g$IR`hM :fڋ[wdڔ9 zVjfeZZ/ {W/j.-Py_i=yj4dS#= <-T-}͸/udSnٶ'p6Ou$UYiZ| |޻S#YA 2ݨ.0ZU8%PiIe* ae 3f-QhpR~CHp?t2Ef\W5sKƼ5!Y HT?D}1bdZk&>VrmS8gF`30ߗQ ߫1{ET 化мí,*0H*3UłxI8E|fł;,K34Oz B6}Jؘں=!y'rCKJ19eQ:wrWƤp]޻}Nu84O2f`<`H%3tE:y?੧"I&2Tk]oCtCFuR'uVRar,sۀ+M]]=|o?$OP)B2B 2Xp1'tԃ'L~w-F>V8T@z*DWwp7.r_tIGyAe9^B!$? =G%oz:KXQܜ)RlN#^$$5aZ:+5OyDV/z>?Ju[GwRK4H6NϚ+\[ccX/'4`xYt=f(Ds1vQ;; Lܹ ZkeEeyz1|nmk^aW{qnyא$!)x5rSvr^B45]64brtq\]0Z A"C%9OJHK_`Aal+ \%Bخ"(#LJbĶr Ӈy0t2b>N/72ߝ^> )V jg2sk E>QGUzd/sZ]xT͞}z nD=]Jε=ZٙǕwp &i K%:Q@YhRwnpDwMc C1:2`>:0PoMgz;)l<]v*ݍD ):滣8 #.OZW=VX' v!^pںy|\\FS,@eYdAS1WʮҧC++t!a^^`I-`ǻÈSD\3m8A6Yܚr$Z޴⁇9s˦5 &Ƀ{@?Z4_~sfjS>L)]l',p3tJhr\Km|ދfq}B wIy{^P2Zf$A`1gM\`"# "U'וgz0gjսPjAAtZ”Vb>v #Bf>Ƃ *t5Q'g-tlVTT<8 2|7L,mKa`OypSWrwߍl0N|32lA2qsᒀ01R0H~՟3U׳puܹ*$)m55c+Չʏ5{6bgScZD|]U_?u~#Ƶr|T?'H !WDtO?#.`K-UݮůwW^.=A!Ҳ܋lzO{9ɶt*.z, wq XF"AƈMd#uNOKOߓQoWW4 7Ε6:;V'Rʾ VΦ[ofb\n+`(C !.b%z dwҮ0Ci`G&*AHv INl|&Ʌ (FQ`!-\M)vIN r`铲ZU W:EA|9B *8;;ɕҹ_ћ9}Q} ַ^!n}`{񪂫clZ3Y9mٲmp+I:ZD8^R76GMl@%3 tMfQ 'E;H&@ ݚ8oN%Ϝ9yC/+kZ:?~ㅖ(Ybw,;zf%UN* w) |ApǢJJK#ذ?΅rf(.lYt0rƴ|8򰀐 `a'D'CpΉ+d BPC W4OGtb{O8,4` RղCOgV8X$XR;VW?4z/> y_>?1y>>,+wmmWM т];NnSVлTո\j"&9>T>54Pp~`TͣqQ!5{@IU[%@8X0S뱯F>tN%Eb+>~~unn/2u³F;ڷi / H몬NEusxh&.qkn=\)%WY$@ 5rjUqߔwV(y;c`v_.f`7в(Jՙ}!\j_mq'}f2⿩~GV|ws`7sp(.p@ I@ N~9,P_^$#C@qN^(N\σ12:* dp@ I@ &_)c"7IENDB`fritzing-app-0.9.2b/resources/images/splash/fab_slice1.png000066400000000000000000006000011250202676700235510ustar00rootroot00000000000000PNG  IHDR1LtEXtSoftwareAdobe ImageReadyqe<IDATx<}]WuJދeE cSjc1 $NB !щ1Qq,YեF{zzy{ef=_<{H"<>~BH%9|WmߕDA!_"~˜\$b`;.)GGA/q>6d1|xSxɌ||(I|J< ^H)"31}QB?q]㍸  [=V˂ 7'A(=56 \8?f?\0x1 \^T\Ueyђů~f?ů8M4-r'k=xkihVѳ+W$L6͕2VG*BײKc7lݶ-O?iڂ,Tv78QsO>^?OP70upYR dK!,RׁMyy_ L*Q(vUĺCoKU N&]ȸ8焪"ف' "ĪxN$dA#^Q Reɍ,zHUvʕjR5&Acɤ/&-)u<`*Dw^ӆ1E|'BX-7p*ju`edY-["vTυ Nosb=u+~o>3\%m\'_VY^/?/^Ξ}y׳u񎩹YׇsMx}6.^u?~4RVEjz+J}G[]M L f{>YeFFFd:s-7KmN"*~ Rk[PxQ9^DMaoPq,(e@ FC]]-æ V!~xQ"O5V#& /Y<3X+uD1/z븶xeGSD1:_p{[[JǏR MWZXV@l1K'(:ֶvɒ^߷{O*M#E4ƿXC`2'2u*Q nԤ8wӊ$'L:؀cF [i:l67>>26xiܩ|ySTܨ$%T#Pѱ?s?a핊Hbe D|x=͑< G{\" gׂFêEzX a!GD1"<눬 XCa zB"໾"L[AN%xַlgskںc۾mOMͪchiQC h -)<}C ?_M}߼tttpGٷskSC#uQG]6_w-w+ f'fZiӇ:zlJ8h 0}?GpR</ɾTy% gsHl! p_(|°' 9'p6Q%2 UWˋ,^lK%N\bˊ;~Hqpc'/E> ~N- =)!yV5EOXY{I%Pv MPq`l0uEBrlTCm|Y} x lO K$8>zBKp?xx6/#zQD%QK$}tdr䉁MmkNF;B~fwͷ󥯾tkiF\AU5ubt_uU~sOѝrU$xD:J oܵs}oɴN_soy[[ZcjTO ë%@6@ %X|19KΓW ,|ClzgBb_GAEɕO5hDɀ`?< J߸ Kı 2MUD4=CyHLD#ȱյlێob=ePb=}yl1F/'RtMaŊUAE#0KgN<4hYҭͫj;{R-Y;o:bࠞgX:њ$'Xp'ῠjJ$8b3q5PΎ\4rqhlxдK~iNÆTm}sC6jjCZ藿fƙb &SBȂ0u^pˇ@4,Ax'`墨+`W ljsӈD\; :@0F+١Hq _ !x BR(ml<1\NĪA Dh:b$\p >ɹD* +BBT@z,D#]׬Vj;6^m߁C/~18$)|{W{Ӊ"xL{sWESG{o_B[g&_8gow̙|NcW\qߺݝ5$vI, 9?F<Ca$%-JZ2Nդ.]_N?q~hıSlw~ ?˗a7w=}[ ^ἵ;?}g??p:)WPrv׻K/lܲ%Gb{}[y'YbyTkFP')|HA1'xDD P!| cBbFxCjm(/K˪Yءٙ}pc9DHSpU7>ZHOȶteC9"db U](,ټ$8dvvh -2$o(U'#QFIUtnZ6 ."< U)6tq܅݋TJ(yDOԴO`c5k/m7ަ(z\@ܚɩR&pͶ7xli6QSsM~MdjqI̪99:v섻:3 w߷jX2x9^0V!i}B6gIam%p`Y\B+)j ,,IʢE,"Cd! "b4",2mVC I߰!#xE`6DUU*w W֮V 0jl>8<Bp ˺ZJ8WSd\+d"K-8`E@HF@-˧widїB5k9y%pں|~ܱ믿>bY}=NxW7lU;n~>"b=gf$])Y-jβ|Mc[g=x'O30>9ұtC?vӍvwI M3.5VtS&G_ȃa%YT ˤ}x!'UI$T^G&RG>!E$](R$< TBt!*Q:Q Q$MD?F( <f4Y n K ͽze]W_d]C+͞?yaj{]ͲU}M t!֘33*r%Xrw^XPtЉcy9&3H%¢)5$3qLh.Ql!)^Q)jE96WmMOL O͌MO]* ꖵw{n[)vy$ud"ؒoHRK(77M\J!%ąPqd; A!%Xb1ՐS([gbr` @89B@G1J!&gL`|"l&R"nT<Ű( "#%EX֙i&%Dy1RdYTT1 }u,_P%ү!(0q%V# ()Ɂf/=y&]-!;{3EQp8HZVXn9~-$l3(X"-ZӓG9ƾgMsч>r׵;ݸq=B%W".;;U*VDTZm!Nj)G^@).NP8 7ٯϓb1][}{];nUtͪ`pءH z  <~8ƹKk6{K_~ΘA1 \X)" q_t >n%S2!(ϐ/p\Vfђ;)T(2)/H97ml[^#Di膔֣̰O*C(!j JD Py0NdU:*O}AhjZ2za~rr3gƦ/רeҵxC} 3Z)ӒJږtэ8+o9X1$%8G)ݮpI.UV"r*@/OzйCe΄A,kj3AJ4.uusFj`|eT^xǬB'RipąBy=ydA *p¡L%|-"')}d@!!VP{gHS>@dT*OH#i d?!vEhI)d$%eISsRLȸQ2hp/I0Aq!t_ʹ)D\ᴎ5 i68eȂYŔ;^"GD0AT%8l!IJ<"QI8zLϳC1JfR~I7}k\o~^L s=W_}s>kׯ^IgsFA~H +-$ IaKyQu6շ'NfLW{Ǻ(^2Mca*40WgON{BakQ>R0We%#&G PXCE QF:([RBX*"@! eQdx &DZr4qf~x1q!|"`Z.!5IH4uj¥)cm Yڐ`s ٰ؏/BQS!+Ųxw-Xjj+岳~ÒΎw+EÉ-\qY;~Y=uf~݀| 1.IȪH # C*%J%#<'dȃJ(74\:u7b俠I2U*&ʎ]IyxAhT Uwɮ"WM9 \3!9'P9܍ʶ+bj^;p|jԊP Y ԣ f"]T\@ DĆ52H. *+ znfWN|V',nimkKHKRMJhZԩ#1iVىщKC.O|S !B;&LqPZO)CvE @ b 4@T/YZM0|ynޱL HIؾ-\芎BbggΝ=3ww{^l>^(-4l3C(ܼKV`jQGlq-X"8TZ CFDK"_!@+ ,[(*.d29dohXX0zq(|Li 'TMcɮR!@4dS,s)&BvjҮgzFL ,)⊬sT dipj,75/}8tWc=lÉ+\nWXq^g^y'O|&}{{ǭfƦF7p공M6M$ T뢺$c_x }';jijp\ڎk=mHamG+ݝ" @D@jfWYw?޷on-Y%.+<k焚T/}o檏>r]*+]ӷbչ Q-m,F]@"iYeq1C5Gӂ$TNê< ,oV+--˖<}L)-*yP)7 veR_*Q'[Y. IN'\HIL -E)9UB\nbFr ;9!5BX"F3&((Q N}E4;.؝R -7XH 68&`BEӢSxjL%l}]r֧ԟ?Ϟ[qe\ǷLό,niܻZٮ(iSSgw?]/ 6 5ǁJP.sYDAWy_ 9 {Y\ΒH,"f90ANLʑg ʽDUZz#t,KDXB q` ȮO͞T@PeD}Ǩ+ńaP5SVPMʚ3(4vXEk;ʼn`k-Rq)f'GN%Ԅ[;LJ,J\إx]Kvq[0 Rd_h…Jwr a:4 r@riuPpF;6Ԥsn`U !._>NQ4Euzo[_!a:Vm=߿ׂ&mO0T74y"2y09-6gEP*|Vʈc,{ΣlV r%%*&2/Ea]س&즬Q<);+S,%rgH]u}Ȫ;=UCݨKǩ{שE:SUrսq˕zṏSm6n{o.ܿY`qr/X$b-͍ A@d@!Sp r EO c|P:d>_? ̊:lǫ|k~mj 6`=ND2"hw#E-ۡ#!V@eIl6؛ < gB\WUL׶:6y*<xRq  R8JFU[AJ:|ٱ\Dn5?nE;I`ARl:Q79hl{E=G^޵q۶>$ǫ=o3m+}k{l?~IA^{[Ͽ'k^O_]wah". %!N82iC8o<) ȼ 8)p&aT'P\>NJr0CSfNs05fږn^Q+䳑PhO &EbxaN$TU\`KEr~ ƆΚz^"CV ؇Ć~(IBCcOB ]bE &DKLegX&oբږ/Ur8y|vti V w< ^jYo*!yrq E!I6E+@Ut5hBoilliIebF9*O\~j||pr|r$V/knH&RzsOl#)ͩ4JJi7}P8=<!1h!y"|Zw\֟K);^E_(3jc!*ԆHse)Z@PkBV< Yg:}^1e6WESQaPf6B)]ۈ>z=G#j89={/;֭ޒ.*9R!cAX(#s TM!)C_B^kϟݓO"P3]=BY⺮x֯{N}Ydwo/mQfW%m0e8T捗k߾g^޻oΝ>?Ή꘢kU >n. wUMuEg+M-Kr;}g>ܣzK|ō}gzэx~3ZseTv<߈''']{w]5Ju+<=c6_G@*N.[ {Y<e:Bj=5"MѶR |JR80F%Έ9"U-=x Wb[`cZ vաOԪRh⪆D̲ - S@ n@}2[ I^Gj4A+V-\\ArITʷ݂YQ&,dCbW AMFK Sl-F & Ct`r۷w\35>QS|{W>}tW~u?_ݶV9Y͛o;< *&P`EZ[?YIeCKy,Pքo)PU/m2"+Rnf|zH-s>[E+XS…2 ,?$*ʼnfBV^iʕ" 1˩"9Ix$2}E]2Rs4dM#g.?qH%Eϴuvy햎.6|Ǖ vɭC'G&/ϗfRM/omkmimk)Ϋz".4} !YQMD 'Q1 A9&Hk@B*F/ ^>S!U{mݍ NLŝ8`׶ksߒГrgXf:NA6Jbc!4H=GaEiR~h]hg]FQ)m+,QZN`RxT7Bh Oh80OB/i ItslE!@#`U,⯥j~wΥS;rٙGFrDe\_7dqZ₿Wڻ~Ɩ[84C>?pW4VIum\s6]zյ׬۰?ɿ5w=2;%e1 Ec#/޽aݚ X|vRP#mvuA/}EMcd9C21lv˹4 f#4mP4H~" 54%kX֔ɉفsaxҥL:D$3>E6k蔩 { xUviȅK"kS#>? B QXn àAq: vť]YV*hHKbUMCR4J" , XVmˣۦKujP[Ik·.1rڀ(&91BxQIV I! `}ӆ::sV\/<]}DㄹdSks{Sǁ{~u}?>OoX>͂;LFVlS%?>2k4`SgUQteYti)WHơw&S#:xpLqLo1V+ZJZm$Q+Ab1Pb-pmqi/\h@"/rj1vخ, jÈKj&Բ@Z F93̤xN~UwpJY::XVL ݶoveKөj4_9㯿v~+?O(K;V]ӻ[Mfrohk\š/!" *bI%P+8C`2I *& EN#A)'Fx* hgCϝ;u0n :#4&jkәTn&gǦGGڻZmbÚuM-+PG*<oȚaN!4/K6 4^N`HXbpKB-(Һ7(8S@}ԛ$5lc d@ 1=" PͺI( M  #A$54ɍ t]oupcΞ9غw1h C(^IF#i1#YQ[`?4oPC5+ָ EEf=ںfOyscokcLn57"ˆ0~淿U e˗5Farjbpo#o:a1.XHS9rG?Z,2{wĐ*~&ɤ]wS~_C:zS>~K814tq>O(D&}n"{~[l$$ɥ˗^Kb!_P@R5(S4Ȇޙm !K01%CԪBm=({`Nɺuc#I2T[[C}X&ь@mJ:hS>!XHo"Q22ľCT]- ɸa%adzSSu:J"xeWPT4hB2pH@X$&-ff B/0-sML֥XVjՖU~~,ï3cWnZ) u3W-[g>ȣ]w L-..[%0cClg ӍԇqeV$AV@$ħiVJCnce{i=68PwVn^T#㖅BE傅+h觞` uҩT! X:vBMqi<[hW+n,:[kC5PUM6>j (CCJ:}vk\DzsA` z"˚* l L2t[]SS[/cCN_ٳ<>Lq6-_fyGowGkGMqnκ4Xz| ʵKۚ;T^+>"$9"nh <v)teЙ`T~ģ81=[oڻ䩃X *6M=}kNX1>k]mmWWO<ӳ'Ϝ[-I(Sth "%*q #C854&[:d)r$4,ƣ^ hM ѐ+8 1˻QfifX~Z<HKI6Ai(.`;ЅZ6YF}˄ Oz!z@t"M7-?86O??٩)-ztC kN;wkX.s+UJ2zFEAؑGlfeZES@l/}wɲ\,Ql)khuf !7>wb\ɍ=nM:uc_r[$|AjuVrՕ#:{]ٲfO3+hȸ׌lw{ם7ٳǗ/[ r,,wWPkf]hmwv|űsK>~nj1bqx5<Ⱥf׬[z]{_-T*Q"Dz03 O^ٷBKv44iUk|6'iXLqkB& J48MէVC:ڲB!5tˢVLs{Y_ۧsJDgcm:jQ+n6/!di q6r\Ω\j# C"y\ˉPIPUѳ,8u5?W*K` DSZΣ)+|LU^TbpjX-W D x.yEULsהT*YAXȕ* :v|f÷ݴ#iDƶW>:+߾Ϲbt}df蝙ܴjpRb0^F碆U":rK%! BP|\))1Tgzw3֓O5v6v--0X l(t6G#qU sى#gN:tSҍK:j`fznRԒu/%[2D,Ieb#DlL!Tra,@7k:  {#:&HS{!ڒ4d]c-2|Pj75sm}0<`EXӹ\qccgdy~ÖVC^!X Pr(}ǻ䕔M刨y|%dE т*P]δ^@JRBH¢fn6~NꀡhȢvɐD: O^MUE`2ԃCOٸoׅ"7&l;xs&yͷ6o=9s> )̗}}_1y|~Fg6L͈EU#Ӥ+ئiK:;~quW]Jll0kH{/?SK֎[6ɉʝ{';Z:~-uUsJ4Xyvzꞃ_?s򘤫766-޼Qдqd2122ڲ1X)˪媭)=slX>Jrٲ]r_g-E|INul[w7^}WNN&&A?$Kx*۱\RN0e3j{[w\+=sY _|l$c9!煝?TF/x۝w67OCv*B&!!"7؂D" lj2*mRVZS\vvΝ͍\(K'"Dpmuy7i*2YGfE׌@ŧ2jqEWQȣ;r0_-CDq~JRc4I%xHO$mRI!H =-9Gq鑩2pJE4}@ixV e UM9Uw I+g&^VKT_}]oy!LRMmS32V!߆IRbrL^ȹ g{LH3!u_dM4yUWbšhĝS %-+tl qٗ*Sez"?ݶye5 }.^'g]=KjlI&;:[DP%IeV='*l}O$`f@ tQB>yCUB2ͫhb*Y|ʷ#4ďԣ#j3v䪢90D & "G\&&tK~|w_:{:}ں T"P k ɶEɆZ8u* i+Ι #.9յ#(1&,4}P|Pc#?$VHH:M ,F[gG}]dne/]15Ty*ձɩϏ ۥIEwlZ;coEPWW1j  H(*EMf"GJ˹-I9F'VM"*ˬǜFCVM9l#>:ڂ^ ]ײR}O .tb+-WEV\G# ,5v|RG?|±gr|nR6U. fg'j* }K,P~ >SUL!듫pTUE/_?K=Iy%pߙgN>$wZml|mϛk[sן{O>p)u܌aّ4`( oYl ֭K\<JS-WnNΆBU!88(Ne ]v%% UB/=r E)ÚdrjrJ5YU;j3Žh*[*Ξ>;pZ-kw[7_DS*_ʾE}>7FTd{}΅Z, +0 obn)~4K3 >,3ZȊ4'tJ5͠x] ^m5w*m!TYBQ$&AD*jCU.͗{ uZI2 " 4};7^}-dž/lzScSyW>=M,0bS!ctH(@I" gц 5qQٶLqYuaDʁө]낅chCjn޻?04p6ұhPBS =WTr4r5 *ЇYwfSc7qrŭԱH T]vMCRѼ>SW4 ɠa mr\ ND4袷Vg=P5ã:և ] ^:*3z;ޮ XZՓxӧQ閽ju[[;juP`d`xtlйԈS,AY 3Y;;ǥB-l0D%@WϢ$x2J&{V4&rRdK4Kgt647|<9UU쥱Ó'\"%Xj%]츋IxP>2cɺڨP豦xR}fVc'Rqm*zzz{W2!iIORUh UKO^AW,ϥK@߀eT)+N;L% 6\d5 e=E5AjQ>5U_ٞEEe*]Q4SuAK/>.tgtM*tVѤoiozO@JJg2^<>q{b6`Ϙ^d.\EU`.cУ҉ޔPF(BY/0Ne!H"Lf g!ۻ LlVŔm[՗΃7p{W ϥqUy~"t=AU҆Qt<ת$$- C :)*5ҐA_.Y %#.'I^Y5#UaK!!4h۞9HL 7>XJbK!PlMR ZȭRjd_϶fcAKSOL/ńZ+ )b\SXj;5"tY 5d%癐^*XÅ__b U$>̠lA>rf)_n<:=p2W1P̝o\[@PosKGLG2훷8%V\J&c#7 LL[zC" M_egow_:*d*lC3c7\}/w&/VRڷydK/JBvжj흝bW^inj9xADŽj"ӾHVK'6f]?olo~/X H0 [@dE`*:WJL(LMZ٪)_ ܺs6>-ܺ>zN}Y4f2H`_Kj[OgPCL͂({jPJLI 2O ml(f-V Wn8­љfvnڷg-CmwN;OZXyGbj{6hLKUYlXĐIa HZw@@̒d*w$T6R.TXBunL(2KlʂW0J=mL[L$q%*S 7{yhwuvBfxw_ElXSt?mIl B]8V`3Au<4kdjf(ر܋/E[.[Kl0p%yhxi=^^PFo_g1o76 45?yban&lZvCnyi17~k9[ Nt/uo\6O=C/17>ecEN)tw}|a%j^Zͯޤӣ7ny@ce!rTpXo}q~terk?O}]wϖS':5%nXڱs ӟ}HWK+Uz' 4,ύ뗟ʧG>_K2CFgzU%8l (Fw+14ǖxY*2&̙: zT:eS@\gumS&H"R@QL ݞLbBJ%}ruk饹e/zpGO['L&|y'm۲MJ3 8$H0RC³:W,ҽ(j.HRteӯTFoOMM9U4US&D"ݾ//ͧfrDgk؅ap)Wl rj2>j-Xg/9ZLOB r ,A@f5 0pxbԩތnUpl%۹ *AWb^ʨŵ'>yz\RMjʏ^ڲuTO} Q3klVdsQF>7i)jz,;L^rzym,z<U 1׹'fF[:r$`Nnz6+yjOMj_.TZ?p} -/ʱ#ֆ= fg7VB^}g:2n߹ud&J!rCS~uiᡍM]B^bHޮL^?@Z[W׍]t߸6'R[("ڶMY{mkmM/tD@/&3X6;ػ~d'~v]RemeY1؀gi9b ̅ѰσgPA18{@NY(AW1L+Pq[qES,(+5Ujv]Q=fr=t4ZQGD-D^$h g4V N⫫C0Nt-)kTAUGW̻*5 T+4`Z!Gߙ^j,t)B_R2aaE᱋Y#(Ulovl⣰h b0u谮E#04@BRDmdlDM5קZ"[62j7a.M&8^!yl ~(œ "^9ș\`-OTC‚8w&dCQi=p8*R ~B=09Ef-ӬY[;n0UaHÞ$1Ls]fa 0F"fXnl2TCuFL$)XR'+C0//JYTvҥSo0Ӓ[um޸\&gWgW,^u\y`wM6WM˩X AɜY5, Ḭ̇>*p0j4΅%] /yډ._=P3\w_M]zFUD,;zc;'خںwJt?&ffeKes=4u!S'ԌM?'3Dq-g(2 x̑ SЃTV]|0rU9 |}ВE/sCx񑧋<[ k[؟)WVXWO?ٿn7nuCzPO/D1fDܱ\6GHXX\x橧dMY[\51KᎮbN9Ӑ_gdA޿֏*}wʜR,/ͭY~zqzp m;U˕7|}8NP)UfЎmMUҥwN:zLmۭJcXPLB)ȼfu]!݇YĶb{PE8sC%lcr2~V*,*W!lkMxO )FMPuV)BDAM0Zqj\Ö!WQcMXvy} A \0*%9@2ӎg*($DžPvMہ8yaX3m0M/(:rv:5 *£GYtk62+lCjt} +ZM"氦&XS> fB}I^  i11u]/.՚LB52 0uzLeơX#dfC#X,UslQ%ØϦzМJs ֖tKx.)PY#UL|V>! ujI EL\!hcdt v&EϖdK5*YBJR*C] Db BMf2/Q[*B Kccw&n߹|̙s/8\O'T~}h]H1Ws|"CO&cfY[ TDb/3uk Q oWʹ&7m9"qlgHۇ{oۻw]Q*8p򵷎#/?Typa-=q/48)Η[e*d;<ȉl&DQlY(lBFGl2XwL?M*X%D1[v g!Ċ'v̑e:;ɶiI*5TF`zB=6XwB#~ n0Y&f\M5\Ν3~뵗_: 3[wRwƆJ?ikj~?aloޱ?JV%u.\}GczrlP!uڿZVʕz±羇*P3?OY3ݞÍ!`B7 sMMӿ>܇rM-5B}o~ 7l b/+5a'?뷦flǝ^;wlX) wwUf1 l osQȯੈj S0īN?o|GmP3Axv58e6<'4x` p-+kYB m_%B-iqj!c6٤mRC[K,r2TJ/S6tض#O C,S(bhaADcAa{87S81N:TW*<J0qDVUzةGu%?xU)3bհrK`%aBY4Cq PH4fu#ԛSw&._(e\CB^YYT3J[{ȺWWVVX6ihhU9zP!p]7 Aʉ1ey\ d(YSKUe EPsҤkq/Z[fk%\X BP5*dMʬ.0Y zحlЋ] iy}뭛gO_<<}E+m-;7l^#_+\JB(ںus2٘N558AV]:mV LS4-X=@[+ G DAXj5ΜLmȵl+&ǦMM TkS{L&K4|s=zs'+cV]1MCݽÞi )fBBsS³RG#g@w*4ZX045nC:8͙ чN'zZ.i>eT6֚= ,!ݹlT(R kISSZT8u:7>ؓ664Jk<*HRFF6?v8{{.ޙ|{vgoK޳/*Tfà/Zŭ\n=Do[7oohUMԸBXu( -9toOeRBD{9ܺ 󅼤Iv˵Y#'6_=q}4K][XεN뎷-/vndh ʕZӳso|;޾F̄DI1Fϝ?+x]\J?{~CˬP8{{alf]!ǛcšlʊhE gaXQi"ɦ*}r)ǰ|÷Bcj9KfDUSZ*\DW$1r){/ cٙwBτMXUrɚ\^1|(ZzA™T؄ #U L(US 71 TN;@58uå@H,+:]2&墄[n,SVJLM_tu6=4]x!` #.םWWLJ(i=ч^%썼kQ2u, bT`Ko:S JE ȣR$M@4(trymyev˗O}+_3Sg˧^-[UN/yA`:݀m!&V@Ŏ%8!IRJMF#l&xZ%n(a7,SF!%vW”guMǤ EIg uTR\묘[O$vAm_n軾&H&t`pRյ``+md:^\ѥ:L:ga*L>XHr(D(Z(t{j#Ig| (K)nn9.k>wEIzڳ=aKˌy=YuF.pAIP6 ;h%}(t"^vVKܽmƦ\ ILGŷ\p8|WKCvٺmddiYu; % SUs$UKFȃ?¡A8 r6+BPma.%p)SP64dMAzV`@B8k׾L.xĭ,?p!х\YoYY-rMR6۸kelBqjhAv`Euj/|'1wʭ[{y5U_Xױ{my}}fƛn T.wuZ_v=w7dk"8<|;G}3gLL6so|d{-Vʝ<С ~R41:R5%U6~]M$zfga&#|:tD86Zf{Y֭3nQ=3fT`0u . Fy`bqG`C,B:܄OQ5D]WxW!rΣ%TE^UQITEmU~el0VI'd<׵7HQovvVym@{Zm-.9S}zߣ-/&.JapP]Y+&Yt1Rghn )H>pߡNtܙZٙH(_* +ڲi$Vs&ܽw~~AJV=oͱGM]YX{v lZ8GV{m[tZޮEo}_I2mu#&>좉U3'`kTeUU0.x 9$wCgrP|&lǀ羫ȳNXNʹ bKK떡-oݬNPF23;_lNW*UЎtz TQ:Y1+'K1҄"ݚiJUkdD2Ȧi,'S\-8So?sbUs ZkoG[_MNj4qk~Z\/`dfA8Bh-Ϛ[AtC1*5v646㝞ul7[[wl"n7L?ukyl)3988 FR\͚"A75fU7%U3bp bc  F98?d["lW!dC e`cACWaC0B_Q}m}YK19y^ B1R^=oɱ:iM3SFE'&&o?+W.:c/nG?V R4sdˏOHTYxL. e8zGľ oa1 !g?{vuury{ww.{'kfYP5<xUf#]=ICzرïZX]>|憞/?~_{{c:<ضv߾?OǛr+KrsW^~u|UCu!u讇^}_N;O}3nό_Kw5791nS;vv/ԤJ箏 58=/}HEn&]6~gÆE]B"Z]\Yd1$X-x\h +ܻ\0.f%/i:>$dd1e$$99!L l$X_8(P~ɬF6e*N`:5nZjik6ͷ-.5QIlZ*Kik_[^ 0#O?եx<^,q{:HL,p85E <49rxƀD"t:5ۣ)2mFrc̩O-^9ȋ/~gqu7ܳeCmo{{$]w*/ E9Rv07P-r̀P*rvllho7)F焋kӗ/^fb}ogTSkҊLT(Uͩw=HkgGeh*1UELRݠfˣSŻWmzl/Z\WKљ|iQ@ަTC}e!P \u&smt3+`ji]SG8^Sx$XΌ<7qY:|*qBN:,^L@۔b.g(Vq|_Pa\ +\_/5.?00ϋO7?3~ C컁J!%~iEKsUikmįoo:zrr5>dDl<>]e_,C?ù}tvݲyo=3;25qGSX Z!>~_p£?. j\jml3ܴ2G1)!G~_nJ W/\3 bJx׽}=F7͋I2aS薑w۸nLaOYMuHPSlZ,*}l78f2/' V-At pihAh .onwBaU0KQr A]5+ť9fn*F!!UOTB$BS~1$CPa A>*ReSw/Q3k1Y1Qu͈#2  Ht tZ(/t]Tfohi380^YPE/P)(2Rq2^RR1akL!VIKKצi3.^<6vkdnU1iPQd`D;^j0 bbJ>/o7QWizl _(AAXS+cm[u,*O MPENGV#"aL7l;<dS{VtuLj]?~;xξGIu)^m$I;*SUѥԷy)*Jra298909>=3jDF{LptWsioݻ$ j׊.!%02vN.S MhI b.3w<\ۻvƩ׏"biuϮ\{6\əΖ榖ƖΦ6MqLSy|bvWKձAy@" m@0F[;'_q9i/~xFRû.RYô)@d@7 W1 ar([ҕFsz>2S=w&=][3_p'~4vJkΙ?Ogۿ{#}_Έ"sDl0CUuǶa. %Glb]+ӓU554ߓ`RũfYĜ[N_ΦWɃ=Vǵ4>s韶o~྽=]CkR)zOp駞f!%+S:xW:Ջ<@c.[^K!큒[~hÎRqѳSTq}OouPӧ'NF^o3-;FF6 oHœbJ&)O GE}(Y93;ݸr$+ƹ t?<) mbL,ר1ЈDfy5׷edҕskkktpUY5)L^ *J5rM,qހ#hOc(p4P l o2u] I˄):0B(*B% \+M:iְ(*ϣFexRG]*hhR^1N+xPwŘ JtJ.=ׂ9+9.^ؖJKf"ΈR^SmlfO][+,3^L<ҫScħz\3|hbjȪؽѶBNJBbe"- \cRnjk9f` /kK2CFFI`au/;.x,1Xa:!U e!g,(YIbw//-O~}=mm-Ҿ|h_gcV|Sr,Kj<  8cLW{<3]C'kϞȯzy'刘j(]*(I&t;~X,,.XHO~_7{'xqD6f=ovcKy~jÆiVټi^yc=LKWn{ȶg:Ns;oZ2[#l۶yt k"ՕeP(Vz\ z-\w2x Pk],IW {]\^ 55_W,+:)>3 !2MA4)KQ#  0o;6}`wO kV5n)RZ}%. 0RֲbHLUI$#IaХL6z-?Z$K]tB {NɇY>#dd3 Lע9r.ϩU5 wp"k I)f Z*i"I2/ 8rkEy)4BB4qT=-e8kmmQ8p[w:*SfQhg9F0x7WcS6Iqhc߶ 'O71<8mV+Sоl% %S$`If `BI7.?IÎupTTlQ ⤧)xRJ%_ӮT .## `NKEnjE':^v*UTuEe!<ᙀvOfm[V[z:MZRDEmO{[wGbxM*ScW#*j#EWh Ԓ1o ox38uE\5!ulLfS])kW`ub-c1fVr--NMݸ~3mBGׇжFFbr"bmn]X7eF}61LEMP5M듩RcIoji^[_wf4]ilO[XY5:us|bjRQ<)I5MM--Bsw)SzX|_O[ K.ly]7v ?Ӻ89UhrXG9`̜dyn`!:4Lx_7HLiOA|dLYCOV;G?Ծz2 &!3T3z?;w̖baa?@dSBfujlX =sui+_twWG3EFtADva,B nO}/|7GSoZ񆬑Oz_>'c&+Ŏ}{=s\gߛ);$6 ܽïOwwݼ_-?7 mTf5]55-өB2{A;ǯ9_˅B[kڻ]6451)G +Ɇd"O454,Oɂq9W^ۺG6o=5>>;qC m|c8\XYsnU421* yP;F!+1 ^9҅Sh]`9ע)AL-hԠZ)پ$IALH^uZ@ڇ/z@ŤV6M/:aM֨QH+NƍѷVha }" b.VMʆ*n,@ۡ R&S h\$lߧ7@"׵# B/ mbTp<!Ԓ'\9uO?o~/v-3ܾ[/:g$kex;y*S"`QzM/7!kb-Lb>yfdۗW|߿{xGYʆ+r2@2dY 1ؒ(El-sa`seѱȐώbA{#k ƶ#:o]_{GYt]yvW59 >UG ?z]GX0QzϳޔIvN5E;'Ndvlԡr:"gby~jd{2YаU,+*vHܲ,LZˉ)I)DkP;g`m\o|fcjNTo]-LC=.MMON.όˎ)^w{!ٞiښ6?kT*YXxMl~zܨ4,⻎`Em5Pru뉀@VǃN`efZ%fģ` z M1DfxR.$sNfHTt9F͍#uDujv%GvmkZ~el[r}"}O?zq@e6(z@5;q> 'ӓY$LueAϮӫD%yX!\v4tܾ<MBi2Mm[flΒa+H.]&.з(JX$+}C%bz %!ֺ&S#aN T(z7~Ǣ. yPY/&5-ww߃Q_%x&5?93=I\G[1ШI5W l4"Eq>A=y>!-UM8c>X @/ mʄ-[y`Sk[;-niemqj~ib3SfXhinlkmKu;l:V9wZV޸a*3<4$`xuÃb CYc;t ˀ#0'4)ܚ5RA:?;>mh3FX<\ ӱ810f !@K' s,[A+ $B,$ lt@(@ Ύ]{vxj>?7 oAc jq`d ^><XmYkTK1hUꚳw}Ϯ7}7n>vS,]G;CO/.k֮3zuk[ZZdQJǦӧ3GvolGGSv쉃oۺCVԹV~WڲJBJ]޷去Y,E4c=E6 -Lzs8NyU^]51^zKbDݔm dj/6)B+JtuP]Bǣؖ0YUhR.S":a~=kG6BeWFTSU]re S*d"bn3U87)rEEhUUud4IjWSєhEQYA)StX1ˇ%%٘sU*,Mv s-}7]Q`yDX޻'465LLYv5ޢɤTvc,jR0+}K=$y8 -5ƥmS񋧮73 ~LňkcϾ,ؑƞζz]]]$\e ˂˝+PsDA69:/ olk&1]q榦f$Bn069q}rk IGFW[)*/ܘ_xRpM6[k DB&]ˢ@;:=p6a5YxrfѢ-+Uim}͟Ջ8w؟]Qʐ݂z#6"/YY 0|s+Æ܋0CQp˕x@X?޽{'D4-\UqLlVj7:qI AUŖ0S\@J/4x&/?GxKu֫v}OYV=J%k* LrIԦ3(r(Zמh8ΖU¿{>Mk7?ݶymm;kNʔ8iZ6m}#. 2^}GbOc6lۚm&1Ո2uvGxcYߵc 39^.`z+0ߞ?zGMus DҶݾ~cTlK5t4G"Ԓ֭"484<3:lP˦"rzU$mCb(<` h=N)ABKX+!`0\{kkO z#:ĵ2޲o`;"Ԭ GXUv< ҭv"Gϡ„h rHQj"ӓH,&~_(W!kZ*[/rTcb,ȣm¹Ⲕ+bq<(Nt$T H4bP''dJJբ il% {*>sN9I-~xD|i/֔J; BPIG֭'f FDB%ToW1$P[oEƠ`U1C`enp[՚Tr˶MC-.,W٣@YeX c3ۡ a=f8E̛">tf0ǰL5#:1f*"؋7:i=XUdq~ݽ/tXY y/ "lvlRU8=uWgfƕ\m4ҲpgK:F\bF=LD`MK8/TsV٤{Nޗ}44 >HH"\ry6Y5-7^{w_wV /5{hqqvLJ`eʥs>;?rE_- k!)f~|mm,CD-@/_~v[6of]|7wO\X-Z;|+_?7g K#P̓N45/_ѷ_ؗjxΩӧ.߻D6>83qstv||P]mR)&"of<I8=i<5M&JpMH{,N\jQ(L`}-(̬%n tcncsU0Ϝ==Wt) CdTH^ :[S\jA7I50(%+!lСO@0#TRc lX,ZfOJFޥف*N:c3K?㺞[\[5IynQ8M Cp[{`e"d-bHMRGz/\xl f*hkiȶUi+#cJ𦖎+WZrH&?#d,E h b 2 )1 vcK9%sm@@W\=|#Sr7ټ|Wn;eN_;w}m=WZԦD4%k^Nʔ4z4StPKlފW̍GvaOC&58#/޹e}v/YRNQ1=7K_͆x|;B`0/>SRXyC }E]/08+?0b.vwMlذfvaszm-MϷv >v?rM]5RbD+c|x`T?tχwdZiqe,g;TQ9ZN9v︣~1fu[2ѵ_۶O*+ldCKse.Leji߿sh]>O3s ,CX3w ;L1[Z?\>bh5.NK_F&wEF!_x?Z}?~[٘vmcħׯZv.ݶEDCʖiYX-'kRyo߻ =j F39eWx@C \xy>+zlQ$3ΑV[9xLfX9R`+NdO$l:QUé@Lv+9@tTKL )-qLŽ嗊y[#FbLSRK1®-Ye_CJ޳Fߊ A0=V *a !RAL2+WG\%4c:UQtlU #7.2P60qq ( ×:yPGSoK-Gm-e7/;v>8OiQughރf%l!CaQ -.8hnP*BWpT'df -,r@ Ԓ`”,~TH W]sRd@2@ E{hrש+,}klH|ÕY:bd3\2?O%#kfi ؆ĉz "d(5V][x3׮ z6ޘ6& j7~qvl~%]=55uL ̪559WL: X~@ !euKu !/.vR8.ex ^$3gܜ8ٳcEgGoL|jn|.\)lYיz+o^O\9Т d }V~Gu]0y0a7ҳj>{ҵSw~t8 E2{GS^@ mx# #Ta\6̍r`1n`lj*lG&c@erx(:^ s3uu02~ R) ݦUQIxYc5Ecu_{L -knl:zGo}osss7*a㶮os*2omoݶ}SO?uq7v/dmn޾e?sj붝SQP#.ZZ?G_~o;]Ўۆ7ܹukשbyԕBBbFLJ$ *䵝LœLL^W>{?7Ţr^nթើf~519 H,XTr/޲먪/ Yߵ'mßJ7ya:NxS-P{\נ1E4XV~vnuYqWUth+t_j rv"=/ȱoYT"i4"0\rD o龢B:<*T2t5_(uŶ`K6%栃U,MX; ~h_T,/B. P+VYOqsÃKn[s7PXR>PM'e[0֠=P\S@DoZTeJ)U(P59†l\pِI.p W38LWWD1&JJγ{Œ#xjŪ`pei0t'i٥T$jQZVb8E\9?=mĕHm ,M,4>,fCKV%w^%Mu1lGwL%dɑjR߶gi}CCH~+Vr0>1sŋ?i;>YX42X|aYmy+|:)aClO4X%qYS t9'WPnF=r̙S7\,TM6ؔ.1-jIIC0? Ps[/nw ž %N'1Voii'ұq%h%maІ#%-49`,Q: Kͨ6=cFDAS/! [d뺪 !҂8CW.[p(oHv{tr??w濖cQjؼ{2]+ݺ*s+\eYad\NFm:,g}hpDEu˲׭\OTX[o} BFĎ? ϼ/>CfdBƹw'|c5uY+_R?=zdr~Av,YvͿ˿\zeU۷T^ܜ7-+@7RV/QYMEd,_,M/(!8AiXKXG]{mis<|մ*1-"踼HGN7^pVtw|~;< [ږ,rjI lj >Fzw )) & 8O [ haēun.J~cxv)xdhP* ;J+F1nt7USF14͵ʈ(XW"rʙ hu"Cv둨 pPS#E~T`lh)P,,Y5@ m]1y芡{DM#*XUMv }rpSe֔!PNJ&vnI6ё s'Ўg?/|k&'QpcM8yqVpx`'z ϑPEGR2V!ҁEݴD* :UFJ4 xvee Ť;tCuÈYfS2Tv=IL *UNqp 5R见kO4 n !Wk)ܨwR" ri~%7u/&<5"%HEۥ36RaGk0W.|nrg]E=2MLHLi2tPvMSdP4٘/-0o:Prq۔656dl3$L^pn#JMnK:L~d6Z{~o}x!V,ydjמg2MpLr񉸦ܱy'4}7&nB%gD$ ȸ+G(픚U}ENGcbmszn>g$(O/_ʮV(=HOM}ޏ~'>8Q)"n-2Oe TXhCITG@wh:>OE;H=p=h]\q{kڛܲΕ< Ljp8t#c~'}ryFc  bzԠGU BŶ (*6=ۨSdmM 6UmRfWʆBeQu*NYS]q UġeL=P@&zoL]5#Q5+ytAve| kJ>3@JE3K*b)+ҥR^\B>nNZ*[(|pzjR8Cn٪xMrBZEj*GÚ|lK8{|fPmh_XV+Nv\8suܩ掖֮x,s=w\n{چںLCrWN:t<6KLm4& 6 Z5 *0i脉ѼAB\*^zh,3&onHכ2e;`ܠ <:XZ(VpM% J wtUSPSSC?^W}g:z,f^ ]} R5G[o.޸|D]-;>P~r&\fXb-Zg:7&:%PG\I!ZՂ@KT5lr"5xFܵ)N(MZhkolUT݄I{Zu)rsW犵V)[7lmv3x"])U$b%ZG B v\Ь%淆 BLRxř1,t|p GLu'SyI"0@U=QW/P,ϔϱ*E_BW4-4@1lX(( x֏@fRJװZ)E:$Mp&Ѥa y -BK,.()z+=L-䯍jH4ѽsM=}ut~qct,whߛo:~4uVl[ԝilJ$ׯ2ux6HC-r_ RD< Tփ߂V\݉O>UE; ._6hn _ީj_uyKݫjSmđ3Z$XLk@ RiۦsU±u^ 4aE.&rt?cD]t[9l19wmW^~7m۱]c|(,sѽlko=OaxX)lj"Ļo-{QT&jGNL_mٺq!Vr"7snٱ,䰔qHDL峪l> Őo#=g?rˡuF$R\y咥}wllm]1ePOgwMubA'fM֢$Xx,\׺:6l4s%] N)-Ϋ"UǀH9)a7tJr:48. 7]y 3>KL9K_s㩴zjxFqآ [EX[lD`(1@Դ:eb1ӪH[G#% Q@F;3l"0`[ɉFu_G<Ctt-Q="BCa]Z*8X ZSZLsP{Y *5ۑ{{{K& *N8-#ChR[e hw5_%Uֶx 9x+鎍xZ)D'b>u5[V-ەj,wtvGBz;Gq}ϝ6z{V,]ݗic3 ՉSh%[[_GVs2۞lՒY~ ;fP^َ-"?HrFT9!֖v<4r?+-ZNɌ^3j j`j3o纉с؁HBdb6\!?T%BjX(] FWv(?tB } NҴۼu5kgJU.X4EE=~^1EzmD_ʶR- A +lUkz1;rmشau"p+mm{̹߀P2Ws.G#L>yc'~fTpBgL&/ydWygc}CPKڋ T0B<bg AgqJt )Mf`ȲYֿb˙cہ6|Φ7_U>q}<|#9,0;H'dț(~]M!(--mlΏ<&g&')I '"sd(|-vKM_P%6ںkc/]hj(@]jzTEL-758kbPxyh Q #[U4)^R!̊3*Qf8ju#a$DxDѯm,WZx[)XB ND 'Ul*!΅o \Z-Tp<< . -e=C&0|Km ]T6]QTT9{z_<xbb-_e1@1$˴((Xs^Ԍ}l6izȡwWں{{]' >3;wy3׬\tpucsWH%W''Qgʡ-dRVjɟ1sjD2,}@4k‚e*EЎlFvEE&^_k#O~㟹Or}vff˖͆ Q} <-w|-\yd꘭x#3O$6MrBubnM4\'QtP-Ɔ췿-mԗ+Ũh;"Ex"ӧnI{}s T=1z~DӶ IEluuunKS'I(iHkj)kUYbөF"3϶f|.f֢+ٖs/w`GG*YEa_^!U[gloYa֫>[i8F4O}pБ ^;35CjrѮ1Gz"LVǽ.E  A8x_-VPoufzBZٴGG&\4ovhRM@y(=Bv x W@7+5Bjynz cM>|<[1hlV\hF{`D9m6(Ex+<;=wؑx<1(ęq H.x7jL6HX)?*jF(sPYO-lj+:H4pQAlV 4(]05Rk8m߲b4el=r-Ye %j,b8BHѿB[˪` "߂6UTkҟjqftMմYv ѴJό߹tvR:;[_}vuҗ^*p9Ex(%q Ƃ  F\!`\D3~}(Rn 5ðW[Q3b$h՗m+`kqhƀZHʛ sƊpZH #ALB٫bn…オ뭗FN溦LgWw:ّf97cmmD0/ `-ib)kwaL0T~ݳgxsMmwlm]9==ekb#⥱zٝY=пfвe+ZIFbą+W&oӑ[jEggg,YS_-ߘ=sû-6uz/@O"5O}vV1cQD{?yOV'ݰqwٵcqjǾB!2zDtӡ#N}11ev =~!_%%)Dh(aXVM2Q`߉OqG{{ ]KHKƁ}oN= M+Epk[[hIJ,ʚOg#.+tM+fezn6Qڈ&_{ؒh0 gBg&V(Azt0t#{[xQݭᬦlSv_ze۶mDnH$kkZGT=7Gx;DџbvZJH"&xZBŎ1S,*/Laj񕧾rcgϕTmO߲C+VG$Ȯׯ;lt]#3:AU 4(%yJʯXFt뜌XAv+vYV|9cv1y_,9ko?jiKz{j;-I-͗b`7-_zd"I461}3N}`ً=Kh9nyviC }O*mS7[wsp`EB4$BBPԌt3X`fۖV/]O, g/\zYDod@-Wb8=;{S;{qAI.Ռ+ I'a&Jr"5iL}C÷u6ZcD2Bc2R(ˑr}J(ꁌj8r5&D95/e65eyV~И+4?/?sj!̏Qʾ+zO>w H$bLݸ~#/?ۯDі!SRA#Rucrnn6vw?}u m_̧҂h_^q8qH OȒǢΞn׶VVoO~64zl]M* j^tJPvBCc^"aW6 .*܊ ysYX f(On&3#/Ǹ h|tq\- G"/!tgG񫊦(˰.U+hAP*C_ 1huo[T|AE<e´FhŮ05PUń:sd,*kz9sD)/m-}-^ի*PGF _>ǤHô' eWwUчll kJtrb3VilS8ה4g؂#t嚇z{햚j;;6m#/z?gRԜ5M) dρ+$47z* `!ϳCo`%Ki긢f*B|AG %=! P`d.2πidq!Ψ 782sPwɑP"G1ia[dCu\X^T@Ρrـ|+w}ޥC ALV<9 pKS Т= d(5Cg;vC_d.:q){#WnI*FӑL[C8,7&&.\q.7=vܥUVl^`ɡwka`R.Lq~"WKXmVHS!m#n3Q5/W]-Uh60d}6Q#f5T,..\p郙q`RrSommF"fDhaijMc_O|6)t.{ܲ \-T*u 6ՐK[E'/[]@ܗn M7vPUZ)T2 Q*"LI, ,}K7.xcj%RZZӛlU*V5]au,O>H~>jz[4ڦ_z~҅;v9ssqL'[oS?HD \ =̳5}8pO644^qgTq:+)lИ-O?  *`!l$CU]2x¾w^j<]C" HBC\EB׎̳ĜYhSC:B1^QL&b̩ކKQd2.ʠ.c[lT`.MVI{jR/G|Ĕ mwڅ Vas 'BIfCbOE XE8@TXRq斖JxA0T\m:nt,M%z,ȔĤN/ˠ=eS7n2r| {$!`oMT)mULlaTDT2J@X,FяyRsd "◉hrk];Ơ3!_俄joUn4zhB  -ZiZoj8yĞ),뙛Ļ@Mtgph/ݫW\CcÎ"&5(P܅#D +J &) ITy'45 jӅg#4㱤kX~3] UɨS"[P4N BIlfAE y BkY )ՒQ6*78EJƈd\[XZ3ax۷.[<]SB~:?31swz{gΝύ4uֻzM2bHO1v"ZՊEˠ@Q[xo//+?|rluQNӶDٙK{w=o?wnbgRj[jX4i7g5oni\bvNq/),r{qMa&D)jBȃx`MuhbZjM6O-M7Gh~*,aks \ E^ %$(<`azQ  cW6^d/ײDB$6tH4ٟ?'B944/7:v捑κrqaO%fgs!~x;|ntG>;~U3"Ta1!lJX , ᘘo!hu2 /u0 \}&R6&!Sv˞ZCo-M9*#sSjWM;t>_HʪbUeM 9XzS@tr努FR鄢kȣM<3l1TUY3EX1ѕ.4t,dk@K>Yyk)+U ^9|`=9ddpy𺡡eCm˒y|q;﹧}؜;><Α8+ShR'uڞ{>!]rxM:\g[b*eT.y]:oؕ֜Zٸdҵ_^^zdr m!$ԐZ(IT& BI&!@B/m{mYzz=V֊Kz}7nĖ)3&'MϤ<#…#q[-$ G4Y/;a[ DykANVtp`玏z|GncnwJd[ U@@hPm4Աr8hxV-qX,P{}4QĈϠNIО%4fG@q`J'NTB0^;$a,!c*J3edl+RU9\gD: jER pt@BǙ*eд"8I>h+ᔣ`,Mrj)>P5JBS :.bb[2b2ȮvfȰ5T@ Z܊ڦ{SՊ(8K:9UQ}Szry5[~M+YrC۪U X0p7OQ81Q6ׂ_9OZ?VnT`Wr&/]Bqe&8I*pxble-z9˵CH\GB Q.KwAN PCPP2LEQq0ƻ^P qOs &z* gJR'FCf!bidTX#?߿kgy uMu&͞9}jU]E0Z1\p.]lX"QLT Pɾtz%P^i]`Jr9ؑĆ7>{?};7~oO8qbE+NRm\5 Q@>G=ROmhi6 }\*;we@&9wn}E(KGYf2,KvHQaMvoW>$$ Af>.zAuT/轷+kz/]V4}ݱȅoCeܙD55@ &Y&SP˛P[BGq<=&{X) v:͕S{_ٷokI^2I-L^yۯf~?pԣQR'?:*ِI3aHIc==+yfV)PU=敂Gő8O[pÊ?-[;::hBL`iÄMlk9}>:pe˽@P 9m߹B%,#6d0 |I|Ů- L4f9=pCp b `pI.F.OSU&XM` ]q|xo?x$3VԻm҄-g_< \ˎ۶FĠPVW9gp8Φ]A@oICRԅ*ET$iq4"x&#CrDH&q"m&~vjdz^*@m!"S*JK7Q-4R~z6) pbd"8j< `j]!"A\/3J0u uZsM "pyúemt/Ti h/ xm,t@$aMÍI;e,e0~ɦZN؂\ 4(i=WW&ΟZXub_@Z+Y o-3Ϯ}X6ã Dr_0^&j ZPQG <1PH6ㅁ;'; T!,41L-iFRd  "B^|AZ>9xUUq@[("rZ,"fTPf86vExPd ,d ΄&Uq[Ⱦ@שY/g3"븣0(21|Ev8#q7s:xn'u徾lűHPnnMNh.%.7pb!@khnG}_Wtw29A>e?Jd'˖9u@m{p *CC"p,[q͜USp 6D7ll6*&j?̦ e.J9}t Y3Q}4P #=8ĥ71+Q_JO>mbG:e:F%=1V$&^ZeU&C3?Ǐϝwۣ6-]v'D0dY MhXDjE?2 c^%g.A5tpH"3F4h;ͷ[~H8ϐJbOY,,/{B ~5Wx%ӀmyQ Z(Ζ_RI v 2b߁+;z6Kˢxtŕ|^V?p|oEK@? GP|l߱k] }Vvr,z+Ν9,FfZ0ڲuۤ)SOK4(%a5KC?{忄d, / t]zxٗf;]C4Q ` M|]s Š g?_y˗{G_↚dhHGy2>g6J^W }[_9a´I.nS,'8YV68`%4{sj 3SsQH'&CZ.ʱiR6Kfc 9NUJ)J,jḢc0@i6eZHC..κ *@ * 5Dȷ!,ϠPLZ&PvGe1; ~PDdG5 jZ@:|* Ⱑk94a;P!WjH\Bsu9cEH0Jc P\!6IӓxK>imh9#V:2{rmsw^fgh[0g?~W=8ru^.l"p`x>q"M\PZ<^RQD!-4b(A*"lV*ql!%r98`uUxJ M1MKL*;l/^'l408Y )Mz-ZЀՈ:2BL7H_ E8RVΜ>z`"As2\Ee}x(BZ!C6gJ6'P0}c[x<2c&M*KUzVuMskSsScKu.Q p`N=~䳝{mٲq,SOc:.cF]c֝N9ᣫQ dǔL&9׿uzѵnXjeCìwң?Oc{wݽhb{RnH9 `ɢ vEWb6MThic1a?ݼexpVV'GGltO{bx8p:gY@º?7hvϮm<: WaJOZڸ6y$Iztz 5Z8>Bo<^jOݺvmʍÁ)Fݟί}ub,7{HEM XڡX8eb!?&idRhꨵVs 6B@Է+>.]LCc&KI~_ X (|6Sik2D i58&1h4$41nrt,&&OrJAH%!4"f,jQq"|V-(8c$,•{c,ںEV1Ӣ?|!i+^(Bbcb r-Ukmmlj+413)FuM-dS*]B\1㍿4GQr4`$f h[Zxo N})yZmV8'@kgX&f(}a\-|/lOt|BWkj֯ruVVTdGi2FJ [?w??2ݲ}cO}kϞ:?UUUkmZM52< Z[-]}]K]۞{CWؿpӧ 0D* /Z  9l Cal۲tU70wbZ:JmXQ*9kDy, `S[9ܫUNl&TQ"6| V"j,zs3lA!gJђ6~p6lD(0_:yxUUܱUrbai~YPlhph*x!!yQ2-hhd4+p,~=P˒PmJxN]J6v !u\ ohm}PR mO麁9r-^xenKc];EQ jVBβUe+2^Pc%(Ep='vL1{ hbXrwglٱMG򠧮rB{k{˔D0;ҩ|Ј7ZbUG<]dXN=Ldu2ruS#SC#=]'9}r껗' <ח_~?_zvj_y=rڻ&pgld6GJ'KfhdjV[Cf4yG҇BQּ6OKLr9$JDohD {  D!KBAL&鱫O?hzeQS dU"ĔéFmC/^+/%F<G6jB!Mj/2,%-2DMu%/b4^b  m-Pc[NºmNlz` 8I" >Xv *W7[&=[zi8#Q kC51S-k!ܮs1Bƴ1ҡh$LɚEh2YJ$/\`umY)( W0J%Ο>EEݰ~=mݹSS'~gwOlإr$6P% Rʾd]_|ia CSlN#5#V:D {KS4ѱԇ6T'zJ tCOT{Okipq6)++X(Vr4BB*gϓY&:$jDC J#xVm kR5yh\!CtZ )ɪ,:rX4b"@2cX DBקBiދ?9|>} ic8V|8B? %pVZ^~oFxi6 ⹔$b7^ Ȕ2,CQ *RhR[_/Y4%6CSLx(⑈⸗@QQ,Ò8N E<퍿o;vx׎}!56dly]e,ˤL~\t֣ی,7YP҂]k6r`+`8:X"@R [z_zD칟sݲuL".&!xFT$GYhUxیD{UQl'd=iX;ftZ ˺xqP-ӿ?{t̾+C/?1z)g/vntߜq;/^Ew@lz(ڬ=cvEYL6;pĩ}ػı=Aj=sJKǔdKs"ugo VBHMuuC]}C'yQA&v,2$m{>~>q=zyB6QUY7iۛ^/]|{< _Wh VCϢ C1 << bG,<ml = 1u~Ҡ& <2$)d 7uL5g[?tYlr$B͑d5dDA|L^52BeM-ǰ`P)POƓBeR1]ixC!'m߼g`Mm-g߻c|K/o)cѵ>O524xh<:lin]bEIޫNym 7' t''wD7R,W!\COT ^oӆMP^r%ܔ\Q.G߼yKQ)Yrp: ?_چoGtx5,Dg㙖GGF8.[|M:x=j&=7mV qU2hsJr.dC\lXyXoF۵i󥞮}Ad蚇lXLTɒ_xqPEmmdRGk +\GMk'.JF ٕa'RMkK HfFEnZ`6KLIRچ \c*<~:N"!!%Q 0' uUT'SpI;D$dC4)$ ŘU7-7)#\BDzC"$)ER@JډKiȵBC1n AD*Yh"&8")sA<20wUS?s~ d ki7j!۸,DfyKT&{.;yיScCH ]t×g̜TxWWTNhrMc cdи'_a.ͷ_| SW7=̅sdU 81;(/_Xjdh bX{,y(#KlOF-* =۷"u_ Lm V 勪76O1̙3Ϝ9oX>znf567n :n;p VkZF؄*?]+04!l EI~^O$uvƔ,rmPVx E^{&4kԘs|r]nzΝ:rIm%P:& dThVߦӂ,Gʪb$Jn :}b7~HcՙlYmP V^yDY>l?&@/%z[Q%m$\-bX[#u\nuYB`4:&^N\ʹ/"V'JrwW&2P]z],%ԞEÐMA5ԠNDb‹*3ZFN… ƴ utp'{.?̊6HmUe_ V3\1 !l"ɓ&?E kxErۇ~gSg-\'M կXBb@:?4"D hb1[, 8h](QYΨv,Q(}?y~k<7mdɑpB>Ux 1gҙ7no;{WUJȼ=Djw{C%rJazAkUU7<żP.fCBv8EI2Ut*gR6mX{m.es~%%4! 5h Ohd*Yx(tU)Dhf?E&LP b5 ;?p=W<{ɧ2cipb(-E;t}X#FlAE\I6pIe!1q`PfVQS|g}[Љ4"d$(h`=XK`hWpgsEp. ]h9G0Lizoag&D6#TyeZ\9Ad*t 6I t2Yo脏ZOPI~*Yo5_Dqsl5S%vX}<Md|YVO;? mmm9`3D\Ë\,4׾>ȱ݅ySg{Y:K۴shQ隢}dEee mο?g/kiPS۲aƅfX=~0$[~o2q8.B~Ҥbʢ3'dXmq:qZ(op] !d<\$M- GN@_o؀-VPMo V.q=7Lty<6Ld a4'$zL vc \!@tZ'?ږS&C=+ȓ{}-%.b BLEiHOFcB)i &T^quh8VS5m&}?< xw |.E/^?|;P?aoF;sEOzス{v=K^caچcq a[8sξ={/v͙<3KFsVu(b煳JpE7.f_062j%2$ˢ#qx 6nrrTߋ;aMۗğBŚJp4R9RϏ5ϙ6+>;7uڋ2@-'8!+ jh**ӎ{#X%5f -RXЇK6) hBe CRaGo%It`8Fӊ68T[Gg۪j-Jiz SKhP ōJ[K"?5 P{EE$Z7d* b}2(Ay eo!8_#N-\<bиCZ܄IvicʔzFwXnc7dU\߼uG9zy֬Jƫ=M_<=}G^[Zj:eH, "|s]\8%QbUL!Ql~pQRςWڭ*"E ^sYF6N8guE7M/ΜPn0Rhe [.6'r'SS;+")-)Ms̫u%,;&RH9CKrإj*DBFM# `ꪾ.SpذJCHc%9v= \s1[FU5y}^_4L{|1. qNSo۴yOz΅"ԩznj W).bRhRekexѶ%leFVnH"F Y-EPD qR#vXp,ր,* HeU>0o>t|j*㗻|@ Y??*i{M˾iS!ةp@)ʂ9%>.%`MpbXo{W^\ӴtƚW=vm=wc8b)Pl{ۤ.+hQo65x,^WU;O?ټc/ݶV/p5Of?.ɟ6:ޢ3:H:2h2#.C1(_|y%[:e꘶t2E ]<z%2+[q3޴lEKlG?_[??|ɑ|ez @$+Ԋ cC5 h]{\FUQqDŃ_lAXt!lBx` n P9RQ8 7sLد+E@U6Z_abMYW|2UE,lE õ$=@va-" *M̺EO6-vK.!^ha5"=Rih(%Ay:91.%b(w- 1w,j'H؜™ ptBuA  g:TB R(%O &bxh I& t,\fA{ V4(Hn,PO8JiQtݶ54E\uhZ.,ѓ9TZ;_L6ki(oE@, Fgv$kɥ nAMks^՜_>}?D5W SC1v87>x3gM:i솺`cc]9xb _Ǿ;cXOBE<3{ϯlz}=Cx:Q14H/#:\j$$T,4!@+f!Q gj@#N#~mp ൌ2~ڢY>osfW\_[4(qBWB'bܪAQ5x5(<(zDc/&)ֵTVU마xo@WW宑H HǕOwuI`uu0t'7~[:ϟ ٭HGFH EXDR?T9ϝu3ŭ?|_geeso\4o.d|v rԊ.GK IGm5Klx<{ sS GQAHQ>!2a׵J$viq9]@KfAh8c9~Q)#| #832i /vE5)& %W.H R*{gpFY!"Y"{'X#Bd="MYrTQ<B*<,BY]3h[um6!h4侂bFb-9: Z'["#S&CZZꪣ($sc[dX# L[iTp2B#vw͚ה7W.@T15LٶLՁ)3<( J9p|}=;=Kkky,1Gl?pԅc5N:vM;Rik0?=_4el )02&52a4-WqZ~@:`5 {`_rE()e9z_w:AU?EɕKE2Y2c񔨿ɬ~` ݰc: 4r4XDp!ۢڨNr p5W(W/v\8Wd2\^N}1Ng5F֡2"Tu={7'MwZ0gvsˤdȋł7WT'5XMtvPC q yh*Y1a9\@cfÄ{Ũ4%4m D_-=[_ΝyylZxy83`,9s~o8{bmyǟyđQt^& tx"{-P mF TmOD̬lO=ă -/c޲hU^ijh&" c@YGRyD1s+ǎ(OgG>-*Nj!\ wP'"E%]qqlqR m MnÃw6cW4:z]ʪK~>;x<.Yx3٬*B 6aяbe*` a puukoyݷN81cԪ6 (r>Ƕ)ˍs~PD-RD}.a#{Ḣ<<ৡ b! y2ѡ֖%oܺy f/漢=3lޟΜYQSahZ+jV_R&J'.駷rSMCFļ"^yDv]fRilxXijr6C!2Ď`^b=rScc[?+J4Tr8'X

t!_mon](d7>8.o՛L&8> %"\RV31v-Qn$[foCm$ Ԫ5p>X&j`,t!v%`7c;D,' zº C&e! E+{:240;5:=52:4ՖQ`pBtA5M jCU MTyqg'w;'FPO(3JGʠUJgYR{.l(>3{DC.-ܿzE{wn;+Hg"4|n]-EwCO|h[»hUR(.Ӱ|ʵޱNV-k.-8lGZ XB =. ,8Nz^0]{vjjj:8#ŏ6!<_3hq-8!4A2"}88RpZёCoWCDO%d .-]koē Wj28Ѡ? 6L;/`Kxrmu*EARWрwd|md76o\Zҵj@5բ"a'gcg2OV5%F ( (*eΎ~GϼF7oM\zv;5աUȴyK坊4рju|<sl&֑ DR-,urդ6wɃmB,etYDʦŲ#4w74rjKΙP\@@̦(hEbɉ O vZ^NL@6!b6@/^{/.p;{ t%≞X((7ς dRoK%v:B+ EVФ6C ,m:Д81{ba^y4Zyё׮m粉Dxk5 9%ZIVi_Mrr^u v }~%ѰM ,~?va`b.m:eճ2[k?=ѽ< @J[K[z<<#XVp7EO:p`\Ζ Ԫd4¾bIM=|P`!ͫswom58O5w``e^|񌜜dJ,bK`m,H Ӧbk7\g]mHG~E)]V@;ο/ z\L*"aHCCqG;[#<aq៳M7_jޞb&3*óخߓl-.]?Lrj^'JJo~;pܝՖCS7ؗL$u&>*ۮM3!# "y%/ ݝm.bnc$JH@ 0]}Ue ]]{{{jl6^{ea[{ \˺8H_AN:Qi%@M~P9,gץq;KR }mm"v7*3,s28BC'o4QCīckW 1m^-ܑ7rOOkdd~qoJp|$ʰ.ԲWѩ`8 FAlyKKEItD,eK(YҽnO4R)Wry<ʫvmydl6 "_Hoe#'d\BMUӛ&g'GyZ]HR9$y?7>9uxwȡaC377ZFr ҪR`At^݂$8;51(xF^-o4M# Q:=VX:mxmQ=Bۖ6.! 7n`6 WkIpIc#ssSsM twF#R B<I$BaU 0ZZo SQvh4:<4 jb>(se*4eK{7.\L(Zv;j,jAێ,@{=P^oпzh(<0:o&U|gz;TL&.mْ$ Z%=p3;JF6n/j7E/Miko0A:fs7nnkUg-&ڂ=rHdN<׶-k9(vxqy3Xi?So<݆lUMmGU,[\{r+ X(| & JTFC~啻-ywwwC>@C*b TSKw䑐țذk6^B .T[~q|6HAf?b$ЅնfD9$d"s1lK#2,KpKR MKautu@c=XߔV BH9nrZಠdMUCل{7~j|/{ Yj|&6z|\v&B6!"V5UMnǧ 6MZ'x'eP:ՍպvD.^U'>6I@<XVAo 'j( >V-fvsH@T*@2蓛 ݉o$H,{$7Zo7uy܁_U~V.;{zz:??KVr;o6[ J@ĄB!;61$C"MM^zd M,qCo*0_A*NdKSc7 gQ*;z3#B}zcsyw?|ȹsG8ʐJ¸D2wַ \O|G׫ux6^2PI| 9^I:X^M}Mᡁ[n |D҆Q.h* e%w赚"Qx9-&@D`=zg>z|Kvw&b]>wsA}wfc+w<͜MhD}gOLV-3&@~0QLbggf;²ն% UN<'rLbRMGIdGtnr ͤ3 v+l01>ʞb9s6clKŃLnRmnzfND.ھu7]n &bYK"@\@2 |&9؝1;W"yy?͛.ucPrMWX8nqቝҨ Ȳ J6rAzeyV;ۤPɚV蓦3u,bSm}$ dMBp:w4@X:}>O졉C=ݡP p@;S5hҜU(l/_Lalzq؁KrSa a[R"/.-N&q3Ǡk;ŀ+Vr|@l^`hcvdLeu< CU B&^v#;8<(ʉDjK;<@c}*M>C9\S5UśAь s.17oO{181!R.y] 2鍃䉓Wn[w.^w~?J %pB&x34v燎OΝw3#O8SӹwW6A=J =C 㸬- lØTǑBKAvptpo*8eDhѭN:9أw:;F %\`h5| hp"6Fw8Ko^w:;">#g@)]S) 9N%`Ek4*ܬ:c&iA0y |x=B:b&T ;LJOml9A6ZhX9h<;?17/D|L|xq13sgXXaj.qx YxNLZ?CNkCL) '1P)dRثQe9;Q,j6f@i6sc9Nv5k5(: ےۢ [5C(lyDgtӺvN`kzfXlv LxGe/|QU|* _^%P!_Dn0|ަ͔ˍPr) !n4+olۏCd!a"/BT4ݑO=tиjiɣ)2$KV hGG&?v܉ UWUo4v$$r:} /{_Qf;] MNEx*ˊ/lloV %I öC3!,Q1MTJY"!0\ їöm@=t:4yV=c#S3&&Fa_@;I+OjTZf'6Xݯ_i r<23Eܢt& l4FtqbkWo껒G4[C3P8p|J{ݘ n,:L$H1mC GAJ=c0v|(J&faQh@+]>PpC0Xq0b[(%1-H`h]9m!<<:2:M]k61?CN@kꥊW.\#I=j[T04> L.{Fl\n@ggKŕbd(U~63=j/DҙUZ\#Ĵui"'xSkTxzTuV0*#rI6~v:&G!/'{B4 Q G!*6UNʑGmT@l\,Om}1.~m7kox{ݸuDGAmESjEToܽ=GKO>8ѩP< Dzj4'9R 7lpbBKB,3u ,W)w#EKD54njPC~ye]DREyj dWerͻCC}g2UP>U3_;-z[_ܸs&(M;<#g41AnL3{{F < r\C  lݿlTDH{9#S:<ܠ 椏,d ^@9.dyX$F@ bœeXa;6.K\;'ro>vᓋ> ^7nd Z]5tr Ţٽl. ';;+K:Z6VjupzAX*)6B=$ 9tjI{VE{Th:"`-pV68D.\>ˤ[F~gG{*ԆM7Ȼs5<ҼFjf/pbtrH69OK~W$?Ee3\vZ]i)Pt\/ О rK_^;XjǦ~16A~_J rp،-hQj{vex"gqx޳5H@Y%gN|J+N7K<ⵔgo{͍Іrwns/ J`3O*~<`%v`+UE$wosO>zT3ALAt5 {?ѱ?7k׷Μ{~n76j++9P$1YI a.(9#* 'YtQg2N:d[$a,Ďi[ ^Ht4W#s(΄MjH͍"8ZKWd4|^$wMi +xN>7wc1''F''B( ߽˯g{qAjW@V :cL Cb@6ލD4 Pօ$x* xxO~G6^_zXot|E  Vb*+<zsttյaAܸv}H"^Tʗ<񧛛[^`{ocWvXkjRX[ZNV=HneDPl &J%i ̜DGD mJ 8$wD=/7>7351>ә.tp kpuPM^6 Au :<;<>qC rc'6S& 3N\n(P(fjm}{c{P*֛Md`,9T9#Dh/wI:^"$;8Y&m8G\9iRh`W{C8A&u3蜙=roy=e1sc`BHוOvuvWj,9d)fRa+c>zxJPZ @,Uj2Nv^H{&/R{[<\%vwj\Aۂ6: pEH6vPbDg&TPh(Ԗ#ziJێJsɉ"ȣ:DBbz.Lr K-Z*+hTˀD5k''?/gV"6-x["UhW}>yts󏇽 0+drقspEMSoҴl߼vBϙ^/K{KղEIS[T{ޞև\bq];n82鐋tbM|zF V/("G-[}#Pw(⋎RU@Pf d RB6,6[A9\<$i4[ӓPu<tҌ`,pp.WPKUZƵwwvOaTRg"(,FeǢ6Rrȿεj=%Y4\ 11{G@p?[[{\L-$^B4iڑѽ&JH# wᶡMkZ/VΝ;uwg3KU'x]8f6+2~ʐq) ^ TlGf]BH(G#a\,@? &GhDU \YbJVe4phKFD"t7?@w8`ϣaԣ +h1u}q7W2ࣁ1+o0:0&Ag2 :&VZ{i,*8+#gȮ7b*;6."{! C>pwoV/[PkZI|<8Wʗ@;]hV_t\aA~>[COh"E 2I,C,\Rs L)JR{s'@lxAE,6+=.wğLo$GݟɩAE:9*3W^p~m:.M~DGΞn< -.oUT$;O\ۻӶH@ N+h4wleБB بe}$#5A9!~.%|?261F)ncU ýHwd}48JB]\ԳSzKU5 [ͫwR2{Ącm$X*s9s\X\_Y ~cG;G,9Y؂Zح_}zYju5ミŸKɾɱh,%8n>nV(d P7ܼ|}jn(=n9Pk*$ ^i4d$@1wKZ(:m>I~ ֱr 3V=d]h{tl`og@62P*Z &p ❮w?yR?2:O\IpQw= IAPӠ,+[;{+뛋VwvB^S5q,11؎caW8vk+߱Jf;³yǁO LL}L*%s |*H\vK5}"iզZawϿ~gb0TZElۊ/9{N qUf?{rh"xJlI ͋~Z(WpłA!d*% B8~\ld@kXZeW #VoKnog{d"R)j~2(@49:,qE J5Aun666Z0 ?@ ԅ/ׯ߸zB3.h$P-<>P@m˵'\*nO_WW f]}]yP ڤC }!40y<:5ޗCSCۺ3Si&F1C@/%+- puQ2jN to/\p;2ړ! E95wϬ7fN86Vh8x2Ezi#g2BdcX'0X"ːIE!#6!xd!M(c݇yp-%Pâ_ 61#6,%3b LLM Ei,ZZJ_O%Ȭ$~zg^O2Y[\YsQy`=ךfk?ST@$n7s77>yCGfF-LuY[ݩ nZ&> Ӌ,8pa9#:Be7m̶iA+(dvcg^|h*BY6'vF&L #LT4±'5 [ã/M{ȃ'v*P#;^n42~6>hlĢZϴXq$h ɲc?$x(0Fl~Kx8%McP< nQ:&Aڏ 3B6c:BE 7'VwGOyGn74h&X]n{V9vI#}Du2JӵT*|V(UbK"z!& HFbndM,mgzF3N޲qo;Nbqܱ6-E6.m\ }@AT_F$75g%hVB{{Ξ9 ugV.dMjShy LOz_|u @%hhX7_"_͖ âyB-`KWkbLn>6Lfs^aMPAU .lUoG<٭4hKͻn/nU[ :vv-b=Hi8 /<'bt=zl_V(SPЏ]=_2t#ξ/[4/b)ʮZј6R f6>r`l8%(EaZ43Ze-S[~/NMMϰLA&<(yuMYyi4*z/?NL ( ~_VIˍTj<2KKNv7/ҽl4 l.ܻ֠M")_P~d&96]p gpg>&sl1"V[mp )БY RUp X*'s˅Tzye#6U&RB GLPqU`DtоI?Zp:C6m.+t'FML v';}^gAME-vcB!_LW7j{PVcX/]E-HI5Q ikt&W*ZxցĒu(XmWDb`x!d#7,92xE}H2Qi +>VVocdwih֛x?too݅ӳ`BV?^H+0aUF0:l]˱`8S5&HK 5,w⁣>uFfǬzd,P(e{o潥ݺd("I۞Bëіw ?i4H(lE~=~41!Y)UhNLvZF->JC{qaaQwpS Л^_ ;{o>/|?m@ 2/UA~cOI6pZ\юRI0fn7ǸPт=srrQ͇Df^ HͯވϞxg&8Ȁv2d!}\AV#xagg/պK}!+JSD ='e7tw~lձλyY{cvBMT"};tXDhunrGvZ}Hߎ3ֶiL$d 'Gxz f1=>4<1?s<(^T[-ϻ[~ۓ9VABt%%C(ZnJe0TQϯMp:K7 3ul K/cb_|ý+jsP̀ra'h4W :b@c CZhM:p(5mNUwr#q5D Hfss/JF}3p^It\9_<[WoI<3yn?4G(KB长{%(Z-רdtT0 _Diґƈ& eZ: agL},hɼ nW1+ |pH3 `.x5G76{ノx5uQ8QU/f26zG;r{*CN:49eM5V5mlR b y$L>7#|IP&)3dB=EEZ1Kxt¸J5@8TkD:~hw@JW({<!xWW>z( ~^8Tk@XDِn줭_0RppM;jx&q`5E-˸+ mC)fh86)d}x*.Ьog;ͦAMDc`j{kDB_{d b=Xg@$Hb9.Mn)[neַSj$X0iXdNn+zbtq]=nH非82;>;5914=>ESbG)р 8!pʕZ nEE^D>74:#q<@Ai*lq)=͡ =M m^2"V6ֶR{BTJf8Q6P2#FĖ`J1IcFk{Ʃ m ҂KaF4a0ӎ/혜Rd 9aMv%m7z`鋄ܸ~F!KMZl$:[[u9qبf]6fbWW4_/^c@WOV7Od ]wyR7[Mʢ#ۇ??Ze$cG|-r aCP bv,Wg^zOV6jod3Ktu%@qP(dGG,7jiDC6ZxVDzah%nb ,WӌݝmP>yjbl@Ѐwsc HGr լ\r{Xjuxe :kLJVo]特H-[(l# 2BmUn _>S~.+@+ЄLhܾ{ʛ\rh',ZKW#ͷ]#us$E:U¾UVZ>'VM ND%A{K6;ߎq`9'龀NH`I*4?okc@R/5~A6r2Էd皺ݾs3Df-jEgy'U^}^CazŻML3  `PcDq>m"=o%XH1ly` z?J 67S^/谡n ÓO=t;aW\%өӯ+/>83zDVj@2z\n\! [clp_O,.ȊBfsB#_-3D񉾎v[i'+oNc'\bW"/ov%U{>u4(k!}ZV囉VJh<\G*PK"SN'`ES덡nli,"V74&~1kwt #F 8ʒK r#r0ZȖKJ ?43 !)[?`eah|Sr{oZ*Gy%@LyR pM3!y[J).Fj{΢,C]jh" =M߷O&E2#Ǻ ¶xu(ga-\,P RSD}/kW;3H//ᙩSOYTTPGjVT\~s+MMQZWrD*W-WWvT 7`S1Mdn>޶W0߾?PSi;ШdO9 -U]ZZ\u͎R#>>1B`ɱ]*K9D vf6 .l~#wjFtHf =,pnX=b=bDJv| 40c9/.,[ VӛEx p,g:u"CZiҾIQcX0 ͛\̀IZK=Ϙ[fn=\Ќvp4͔b0xRMP PƑLt$iС+5@ x>w37--olVutPX6kFƲXR$tR& w-M/M;}ɁX\oU(Gv 2=S QlTpdhr4>駿GD.E7MZ:qZӂ };w+F<#>%8(XZQGOwwG'UU/m㓓c=Tep\+ߘK뭡)?N-ڦb7F 19[sОJ3;\`<>>i;$4b7`Ca6,z+wlE+JY#O>) C,q7E=[7m>鐛^ 4 sYMBR!bٓZiB+X "Bi$SF5&oɫ5X^bC#]=H`D_|tEΞY~I bZ2u[d@4/5Ѡ$wJK6vmiޘl[m%Ԙf8YtcKKBas$ck)=$r0a+$Nt0L>xs[0۷;ӓV X'nJܪWTzGHvTVYMnZ 6%m$(S{~,baZ%Vm676{zTX]|Wf7/_O $#C33&ĥqKE4A(1pY`_Ts՝fj'_BSϐx{#[mΰIa 07vE:>,E*6l!#R4j!f)k"҃]lGpW3K|Q:}?).`,kw)r0e!X^ZZ^\Z≮f@{Աٹ勗{'Ml٧m2%<2/@K0|X)Pqai C˥;wrin23<&AG"6zG=}ς"^Cj KT~8tFRMALMD~TăhԲ&:>JNё X,D<<)4Y9`k PՕյu㉸( pj;.KR)rE% jİLP| L(xXHsSm+5䚵bMYGF&ljBC VP}g??y [7 E"tgi `;9Ξ,ZK:///k!fK" I<ùrJj#g aTp6ʁ1/QЛGf,>8M9PYz:cdQ$R M^u33{@1[M߿kݾr5L8tXˮllltW~6vMlwfM;ع]:A*8Ijmi}}Z-U /5MIvL ό,{{] 2馣@F9X;0Fm(KbRTvٕSB-6 C(vJ9\ʵ%ɂRv4eXn`N0H4V0HW(-6hDŽ^,ފ',mݢ)GS 4aŴx?)`2D9t@xAweAܺ%ɒ pBZi{h/wmx$ }~I $ަ=;"; 4u;{s~isgOU n*_-"jXKэ M/g+͟8727+5PAic @v-;V1Skx0fSK}AO\(#ّ,S)UZMh,7 6AD9 $ *[wR8 F7BdY*VU%s4Upxr7 \y>ԝ8^}%N:XS^]xׯW(g66>wI,,`)o숴Jo'd_ ח`,47?ʆ/>!ʞaj $;$srlh0;,/ޚ_*4/Dlj o4,⮔DmE 'tdi Fְ>XT[ )pHM]ob tQ/AP@͂$4$;DֻK8t+p_xxf&WMrT-Pb%{(4u_ے[}[PXա̇B pah:Lc)ZNFs6k(ܾF6[6xG{{E~%0GfmYv5_$9  2vllj(Iˈ؃FP ><4gFCO%QBn hGfh}]iA~}koq}kamce;=Ii)qϣ #2lrPL{opv\{J af0^:hJؖq v  !wcV m[ۣYh7uɴi&ӸeER 40BQp j+ p,8t 5K$[`^ I@Y؍ KH"GcshA@,[]ϗ4T,!IC q#Lvr. ^iT˭^| JQ[&d& Qf9R*[  ޯ[7}7޺gH 5X8J in\3m <+th&Å@0,HƽepⱨGvцYd>+Wcce'q hKŕkoT@*𸇦qZ3Zyr-eϜMz=Jn_?-v*<>=:ƉXyi(&I%WH9%eIJ K v-H;knMAGaا#bh2ÉeI. Eޤ+SUO>|fp̉ўDق +ePrտXOS3<$r+Krh=vcH/q X(dS^p ]b&EB=.! ocxDol*Adō-LVQMfEیvrx[5)-ef + }h~%8 X Ű +SuOG2k;c9+N%nNG q {}%GG1~^9J92_ wvx$eP͞:2;7ޯ^s~Uo[72P&z}ecݥ)G5-0$<;vlL{6[lE<=ϞzCPH[~j\޵݊X+_P"'{νsOO040ҵjWZZ dimr/~_*\.R9HUi"4ɥ%)S sܷ{Νk1s}{`2eӿb?7_*eK¾ >";bܦԋf\tu0AhMLLz^qg}3J*R*+jp4c"Ο[<^`: [sIJ3f9>E84r1d{J,޿314ty"m*+7{:n-N<~ҕAQwg{}4{^6MJŔkrűp ^U̷B$Lhk 8H!@N3DumdUIw|Ô8yJiy؋N_<jdlϿ^߫Vޛ[YlwҜCIP#\Ij`͵+ٶ0K$G#oZ/M]ZnlDXG{Ek"z}}sⓅgK+ۻV=BsU占)%gց]k&qFiHͅD%|iؚ tu;,ҒP3(0eP}PqC>= ͆nlXH/Z*2Hnckj (hrDI8Sl؉l: %{F;k\z{_.v[]'e ٙ_7>tmԟ GOh$MؘAkWs@]+%ۏcV*w'ΟWߺqt/ ILԜL2LBf`>wv:͖Yb.ͬ,4"g3&G6S ll=z0czsW[n/]j~ŁZA!ӟ8whrڭùL݅mzo7W06;g,qտ_c'GJOn?6C9qLsUl'HpaQMt~1V=~͝R>35==q\`^zg˕۷o\jT6tYc$&DvD&1ڵ.~LNqك%hjr ٪D2hC2DnҚ@oSfY O?k7N^<)6v<3Q8Fy1eN3HPf%šZ[^VIJB\#nEˋKM_) (\4v LNa:}v?3eVQahw Ɂq) f&PBGaVPbCc*LGͲq8㤓I@4.p 6 VC/e5\gd\S[XȘZLsv Yddҫ.Z&\n__ܻ7hƏ=i #㇆g-On ,Rnnor~ky`ޮ$.i֝ԀgEh~(h_@ԞQyJoڛoGAJ!Lw(=H<~HƗ`م&ui Rl7QnBd $ L~:Sxyqqm}ݗPi O8y~q'.n\ }>Ǿg}7N]x4ps#>w`*\GhehIBwW>XԷɋןܟ! -j M>Bd8)d:r #ryu=|♨Zmw{~&ddSFzޣ n{`ʎ Z0tvG@E*Y~'-Rrt ,HnEbiwT>sX1sU+r);} 9's?wrF''OLJӧK} ~EY12 ؓ<lǷbXT46,G1QEѪ4$slVT:S;q>XUk*ƃo#jklvyRW}Br->ѹ/pm">[#}fMġ3a3bv dIx@iwjey{ga,ˏWVwvz'lǦr)X"YƧ7%]Ղ]؋vљuF:-&9Z'1 #98H.+-T+z Xٸ\NSD;l瀱+-oO05+*^.V8p*TV \^g/}:vHihD NBs_{_tԻn;zH) :ZahtfJKlBJ)D%wrUٹlqܥG̍[=7P=4 `][9Gw_WN+UȥDžQѮ[7Y/…) {ǎݸթ啝݊3W&x5aXh/|nnkO?3u>e hQP>H4}rac#!"IOhQBEd[Z4\X{G]E%:Op_g !{I$}IX> cE$Z[0^J 8CA#eWꝕKo:݅Xvp]V>7t7mK;͠Mh,`HR*I |pO_#1딤HfaRjG%%Oi1熤LV Y PBHh͚*|WXWA+saԧLmXL /Y,%_V.*qòMh[{K '?rn"fިkz!}"o ĊGBx,Hx"Q| ,v7 Kf!|c$Uf>`O,BKAQ U8YLtf)IborW"%7 Ǹ#YbqN9E CF-ChY^ĢOZy{JkW.p NS\a)KKU^q Z.L&m 5k~59uTDV4r}vJZO~/ᗇ['&& Z &O\.?~wn8/#DdTsFoΤAd[qEhx)N79`Dǒ)E@inn+//RffJZP5ET׾߾ѿ>_ʍq)DxPF/M}k<<~|t؉xTl'9Z݊  i-o00ge CJƆ('O6w..MC\ U6r6.*bU۩w}cQ3倃YV#'(N\?AQa+dg/pQ$FK q2Z4 OeƏ>4 Z;VND[!MaeЉ',O}}AML+h;|9 u@7"+suؠ:!̜Du'uw9W )Ɇ˞2 FI&@&譬nY(?V,4Cw=JPX}M r̬Γؤ*qf_aub+/owځ?iKj"MÐNRhGTV7C!"heC}IMd"Ҹ6GΰZ: T2TQ)ak جq: SO_$ĂqMǺ\NY'B#8#9R~K,Oed-EؾAb!_ioedbH ݔUoccΣO^ %ʩ7a -6ڕ7zZRɳϟ65ZH̭z0Ł"C{D#c Lf Tx\d[,@&v.b"qqd>c#iV-NId짭f5$4ei'Vb_հ ,9"{zQnys]8UPő+N[.O˯xT_K`_[s*Չ7_wWϥTljB' J%`7宂Ls%C:0W_u nkh,tERkaZ]e"K e]g$9!NN\!t4H"xraP"(L!"QX\W^W*Ө7S=BNln^֧a t+A-:[ޜf!DDxVp| N(Tr6(@yӜ· 2(H¯KN]A L#8)"(Gai EvirfT>\iv)/0hds!- QŘe'g\&G Bth|URʶR~K4+88܆B;>s1/ήws6j6|h3dS4`u$ rͬZu pҨP +X\5r.7eCb5S$k)IySIn|&6+Pefƽ]S7^{@Z>Vk6S8<a5`aR4 1pS7{GJf#!8ïP2$]757vv}Ǒnۅl%qvc40y P60BFj}uۏSiGh;-ece Ap$ֲoeRoWƎg/_;˿oq|ޯH2c\ )?ݛ/ןfKGGA@`n7{*]ƭ h|!r:R e|tbG Z C6޻y@H@E:멓r:yѐ׎A $hE1KinO/&]Ec>zR)G?V7(twfwwzq(N]aHez{L ]jvP[R_>+FXdl[?ʜ:{bTΈEEה`bN=%군;2~s<~2Vt /mlB/KPɟՅ,|>7|oiq?s[_mלtˠB,A&ig:WDxgsYxqbp_\#A  gL:u时ѓZ@'S@PT(e{:ʴAܣg XG#\dW''LtJl֦IN f@,?~dC\F)/Ü,l٢Zpx#k,ø@hoMwa^ze#l6J}׋\jM1t %r{R5FLxv} w!S2bѡL^`tFm-J>XəCۄ5S` ꘈ} Nܣ1[DHq*4a5zRpOm )qTbj#vE$7ɔ7J7U쵬q$J?|Ч+7]bBnm6t>dӛ# S. 7E\aDZ\ֹɘt}@mR.C0|`:/#0T U$q->rBK29 gfgpr1F 2p ȥ}1 Aou0Yq y uNX3I\$Emg?{왉AM<b* dEР$JM1#nYmI75^y~( Lz@+dz0'rY}C9L`Wf77NM_='hyp NY<e$QxL^w~Vi_WƇZdKGdş~맇_'DՀtVt.z)`hε $ ry0s|1>BF5?꫿5}B/ hc5eswn|w^goePQ4"0Z-6۽ʤ [bڭmu^~wT}yL "RT.秽nmv{rÙŕ!c\aiC/&jcCiSLʢN%n}ptnbIENDB`fritzing-app-0.9.2b/resources/images/splash/fab_slice4.png000066400000000000000000005272501250202676700235720ustar00rootroot00000000000000PNG  IHDR1LtEXtSoftwareAdobe ImageReadyqe<JIDATxLW\iv3TհڢhYI'Ao EHCAA ,gLO4 S@ N97|q)'IZ乡kIĺWYgib! TBM݈U5 Q?4D0-E,ϋBMӒ$ $2(xefa"H"ޅ }_(굚eY$LbI$NQ2MOĻy4QTEdPC)^荽wMlvq!Lڶ曯1N_~7F[qQpox<' ,!9dy)eLjee\*t|t GXp0O!b8eIUTuv/VqdYClH 9!Qbt8HplݣIQ8ͺ[ZchS9UY4kGGGٙj'gWת8E8vr+qu]{K˷sƻo-,IhUm4=ofa HӔdڬ`G⪪RT\Ee4({Y 68J5d035?+w?TsJ\pw~G]ZZKSpo?~$L+o#bQt9`HdA c2>}ށ8K333E&q%$9#`kCp+5 EtX$ϡ"7N (X_@!`Vuh)" ]ߏ[k6H&-0CX=QOm)K?<)9d] J(h($W#Y}78`}abq?xr7~a{R*Uf1%.twcsyv(EooڟIrG$dTT`%Y7;??}n\ű/N<|*aq۶㚖$)Ћ *.Φ' Em*om?v^ltsygϞWB?T%YmOOUkM`߻?3=+kNGO~,'ʪȂ.a ATM#s(ҥ`Q OL"<eX6>Hl:ܒ(XY!;I&/1-4ԅ=u Gy/Vi`DM]D2x,EȮeڻahꦅ{LwwϿL0_WWOr| v 6XO QA<ڨ3^$H)LHS ܾ^HdKctQVr-tOSVKO#!3'PV?} !JnIQ`sH+V9Ut]{j9 ^ pJp ch?|q;{$|8*CU]>Q@gRU )z'/aIjq5COs: F8,` Zf|+[n^ [[ϡsU /\\Vst|<\kz- @SMôk|9Nު0F^8ۙ]Y=j,uu>͙-OW K2 2ҝtL:9F2Y_&C5 t4C + "mU;^zWo}k�87G/rZk-]?;?5{`vn;cꦉ?[8ssi/^g%I3/%ڊ\hY"OdY*\! Vb i&u9;GVM܎&33Z)x2sjCIJYu- oNTuF 2p{%2?r[I51rPd8gE 8A(kw0ų/-iḖ*fhDM$En F9* O&V :B&t$BV`܇vp0# ,r=gj{^Ra獏w_RŮv ݨt*=<yu;o]C Ut'aQ_Q3-ˀb@0 2T,QIf*P&2rmdk\5&D1ܝo0XkEJIŸ ,\W '^S:Ǎ1) ,[¥Wzn~mxy')! xRII9)dkgQ|ksk?jO/Zs邦pK>n̓R=7u{ã'a.ZlvTUǁY^S">g[&VL[oߺyfW}8=;1Mfb'cR{}6+ՋW.O&*`öR n3 Z"UȠceȒwn80h?ojY2&&WdXIjȣg0֐=W*I‰u$iK*y(#9YL;/_y]>b=;GEwt^!e;{լfW8PkjG>yWo4+^qayfꇓ ]zR086dq+uNSf,r@@0@[G&|9S(X L$: P{]Y[3,]p&G 8.5M$5U[W t(Ĝ kՏc: 9йҙ);E5$.Pjb`G)ueBJEbZzMthH)+- "qѿ J1;+ ,ChG'cR,DeY8ՐCǝ *Xu`յ!Z浹t;ss˓@3 "p2ëovS!w?/ >75iaص($ɏPqs9ಔ\\Og#Ndq6 ^;A`8V@Qاbf:)x fr|3.!g"`̈t[RdfM.UJ&9y~F'@0T= l!pCtY:Ȱ/_h+DI0~V?!<6 ׷wS3Ϝmtb@ #I*AD"7?:L ݍ|u}ggDZEE*(~HC'ŕC|Kkk?VGl=P'cbҤwD@MU .(H-S)ZUGh'z")%TntM56aIe(pu( E`|Ff~K()fӑ YCG$*H n='C|kKD Ha|3{/w8<阶:wvԙF=_w\sp)&).ԊٲQx<ދЉ}*d:D,Xp$ADHi.h,B2CbF끶QNLJAQH y K ~7JƩ, MAB|𔸀uWױ!߯2p-0N`Jqg"eͦpj) SA-/BNn1M ڄfSbx bT/ =,l{V֖??>o4+;{i5܊؝nCfsuM3MÜjAAovvq=ʼX&a"v]}XF\hl'ㄙola.SU@K\`B RSrDTTmtJЩ e.#Q0@=ǵUBQYCiDJt2L,`̅x 5i/LM8~]u]xcN~7`ujGwIrW,5ɂB9f@wJ)I=ŧٿ$ [r2J*8T&ɖ%:MaBO4 Y@qB6-7t]*I"F#fƶZU0 ϦR zȏ`Up&P`x$;"L`,b0q%%1{'Lsi;QEiΘrq:eXpm$'&N ?u GI‹ HbՅt!zBPrο_"+_Cfg'Ԩ7ƣAī+A|Hr@3Kߦ}sA_hYgK4MJy:Y5AbXr]F \EќA녒Wm~@^Vh>:DžqLdh6(:pؚa!Fx%xnG@϶d:L< >`t]A 炸TLA4-x8SI* T7GpzcTE%lЅJeN^xlp0 =gd s0 u(A& 1aOpT)h,>Eʨhj23U`"ʲҨbd_A+67ݽwϱM@ƈ͌F2k>P-E P9 !8!R 4($ko BV ͘^>=3?,f7jN8_ƣVgŦK  o LSةL20Ҝ("eVs?T|Kׅ4Lޮ<8;!O`m0.":˲.$% T2抢9jX!_pS;NS+E)d"ATUe=8 ^ Q,3Ta<S9 L>WUj1‚qnO>VkT׮J%T-r.`DaO <}R_J.20c I"0)$8PY#%`z8 l>:IŐE2-%HC4ϩsc@(]\lhozXiVTmyu1!\LnCY4Ck:GGx:P= I7ēH` QLh+'%iSPqE $l+n|4:ٴ$ PJ 9c?ʁ2AQ6[WG^YvF\жؠIxiqcY)GH9aȦCaS0h , pKX#D꼘L&@b~e!Ռc~c>0bS% je0 +S$rE#|FdB]ídL3+BnqdjUjRXd"*VlST;uko^1ALqҸAJ$Q8-'O5Uc"`qIP̂>LdRAQ޽<3W5l455QNҭLjLhI!X \@H c%\C!PA&MTSRrۜ GY巅LӏL _ f&9%)x-P$ҢPTV߂2Sj\%V= 5Ud勃stzbdR% 4;ûd%$>8AGȥ{M[ַwmOu1p4777 ]f`֘ݺu畫o|}p'OM#N{s+IJ|뼪R ?ꚪTnH,dn`>yup\tsUpd\FD]e(-쟦C𥠁BL67n2S*A@j;Lo8<>8ӱMhFԆ|6H\^&qީ "COQ'.d( @fʲAŒ0YΥO$' !"uET8aΐ9,E⺒z1wFQ3 DU kVժ5*?;t͒=JFYJìSE4.I),o=6|ky&T, 焅C^ fְKDPHpj*!.z $QwvR,PegS6<ґIsKk SP* Y) -~3 ͱss0gzEe}9RNr<0%qF'5aqV%)Wd.xyRyzs+E$ 7eq&J/aEUf r e;[[Ko'INAIt`y=p"MIZp=?SpQÌNW *V6M<§Qx<ǚ)`7z^_2DA_AӉe**J+s1Yl,$y ?Ɔnߐ4K /dÂ|A#/P55̜"(qr\?wzK/xc1jN{<77OF&.s_C\`)zpd9Uv!X(,Roۍ5Vlv;c )>2`FnR-"bTsH0J{C̴-bHSJ7n&UT,,jBnbWw,v"b .º i ~y8P~<Œ)eVW_lŞeB% ePL0-pVJ82.!ʌCaNJܧ:Qn>ق5{o*k(L] /UDX:O j5ֳͼ|a4*եR&Sxz> H !ӹ.8nB[`=BJ+rjgÍ4HOBpqCRN0E ʼnFqF9!;îV* yFVp9 e;[&`]bhN`s !").{oma~3{ }(08AܿB*!FEĒY7o/-G~Nm@1,ʔ*tM Cܺ93;YFQAr?RT>; $B1\Gp敭PDPn󰲈Qh<5܍j)vRJI*X2TʒbIf`b"RzգKGQQ#(@053l+k@p mt wN74#] U(: ET_]0l*3 e;ZF8h0W$h@ąbNM6f:GG{gU+^䂶tM?;5CMb5gOm ©F칗VTMIXYjJuReNڜljN =ij#栦Jq3a &@DF %F\^B|x;edAΎ*1eŠ09}z(ֽPentŨ9.?@e;ĆRr=1(Narꏁ 01C[gf7ݽsիfr‰[ loLTqD+.f/&ǎM3onݼpb$ftaT¨8oTAŕmf]db`GyP5~ʊp\8h"+ёcDG[m^p7??}^ Ot>e:ٴʁ* 8Ms4#ʩhۚ́".N ͈O*ϩrl;28"1z$C @EsIF?ٮq/ZYa,^pdxQ[Np]80޹+ٳvOOՅP(!RT˕*ȦG_cބצJ]1q̥2Ym!)Q$7n|2=NdrFaTV7Q3x 75Mda$@E|i{TC Hg,D̙Οϩ&8zn jiO{bV_{+]8Ea[9_B)KfA GXW=L< @(Tɯ㠘JQϪQ*ܒ֨=]zIr3bהn **T1S ^"eS"h'l6,yshd< pbDeTfFl '(p"I@LBcY!JoeL TĒaэ3K.@kr6  *ԟJ_/n\z9 Q(v%cI\ʹSQ"[rJDu%iՂ@yèUKsz!E ڲZvfڦƁTG˧fg{jjh|=L;WXGqQL\ZdU,C:<%fdj:B0>)xX1hpj"%!Hb J&B4<ӱӇu\Ř}8+ H:n*ir@ա8-{wQÕZ.TPöY2R ˃L9;EU/zt/vy.3dY FJ$}n,6 M踆Aw0A1NCA650?(0n"60NO߹ +Wi3>F\MD ϛzVxıˌ2O.`'syN~kO=}x_zy~M>9K/G6,]\芘Qu&UStQe! ~88N f!58BNS16HiJ;J@),?1ie'KG%RBYt\ ݞ,b8oi-[r/?acôb hj5 23 [g^|4PUQW LB pLB)Be_ y'mR7uSC ؛cKR/}EBT $ohNI0LfĐ!jON"e$oujE= ]7wWxݘܒ\j[j2V r 8u+?.\a:#qꖃf\#Et"wlvNj˗0>B۝"Uwb@Ꞃ` Iq;}GrL>T'LMY4fdfH؄ڤ"GGe|{Zíݝ^ر˪pȂ4I) 9#An^bH G0䀚HT~OFMP!78l*)ԖSFq`(]zbGG.^Xc^RfTLM]}!%'*娇LELT3= fok/yLSVI<<>8: `UXW5Y$3ɐK-QuUO&6E3D54#}۱aT'c7GuI淜#'4&:OkN͙~>RjȲDxw`nY ^3 %|9v^RjZ^L?~|k㥵ӫ37%G1+kѣh0~Qoo D Ee!cX7.ݙ]\e+LT eO㏌;q"2tiο|_~__}x~v,@m(:m X+a!*˩L8ά4H@0{uD8cBK8PSE5?˵lC?Gh*Pe&j{#9HѨrn5H", k+{;I0IL;s*ʏ$d`X(,`$%֫4Άi9W͈@j #+QB8 Gc;a<Ն{ej T $ D EeI3GK-/*MFcKӎnڻKK+dӬ훖 K ?GIj$\G]i B0DE6Wк̀I_el>zLOh,Y-Й4[mrB *ax48Jә@@9Ǐ>[+TgHLp;<0& F3e̦쟠r WJefSM G0"Nt8Q4ރ{ L$\Udг<fy՜jBU"q56 t)Vc{+ή,E${Ak7L^[|J\J HR)=GL.h+~ٜ_[ T6gg;z*9XI>!5.'o{pvaҐr<![[a;FN]d$T'P@h;[/L\+8XC1W(@R.*T@Zp,![2[ɥ_44r\CӼ8C]Y[r%9TN(gY"%[LuD9'縧CK$rHf[˧V),Vn}DD{;{*zz|>i;MJ9w7}{?ix?MB:R6 ;+}ɣ|haߩ$34B<SCp䜀`'Tv1SeeǪ..'9Qe|ݠDZ$$ _~thѰ88asTҒ2w@; _MY5n1uY d0EKEÉSrq,v2*k+*ǯQ4^$ ˄adz $5c( DJ*bW^J$pLDa0;יGQPY;77o\x^Gcgَ6g><[10dj'N)5'{nPȚCx) 4z4P*;A88@d )z՞jgZi$r^t1?jLاVXIРt^ \"W0$\,1Ч´Nr߷7M_X S쓏=zdeZV~g[[ 0+2݄Dh2T~@5QYYأp i 5$XWpQH5cU ;.2~er&1+*8(]qeb(ʙfT%)i&86гdlK3pa:J{f˗`v/|)NbŒD$ĩCLO^[[>ܨUBÖq)}XG/-:>_@2H^ N^ȔgɅKkkxًCR8` 2hJJ;cor47P=HO ^Z;-J~S|#(KV8!|'pUjڗ ̓8+|a9gaZBԀ0DzF֡`4T,;S4ڽie; ^'R ŔV8)zG`e& '#7ze% Blv+7wF KLMQPGViElvD77 91ӶBF(mS}'FbQ@>A$SzYc` EmچAYX䜦 04M:c[C9 *U8x*, ?vPdsUu-(3˙,\Kש//~sR60O'Ds+ *"Ҕ?ĜR[DiEQ%B#|r-O1?N)G}|BJu8h;F$~& i⇩cwo|yO~8eSܲ-%R3"أQxb+n<_Rbb$9TB"DdR0ݼy'wxpi/-@_{vMNp<{o2u{G%Tkem-J !0&(F, OR E;c?ME3մoY5,G# MPpXZ9*onlLAv gS0Vf%YDijj(Hn χ>X65CB{Ҳe8/cmǻ0SϥZR{d{83 rJT;;?3PEET-T @ӂ,@+ &qz*< BFh`@1mQR -lOq}$KUB./@/ RCM@AP]q $Rbr Neo4zIچ CYԻChPc~TDGB`;*@(|@Q>E4gIkۦsx7;3SY$?'DCr22oI;8nowXh֛)v3Eu !iyf5>]{=E3@N"eD 9T,U4X{w-/MLJH/'<-*R8 :$%ڼ~l9_" R(4@r#R\ ۮTF)$rhR<,x+[N4Ub 3!m[c<4h7pKIJBveyqine œ<3puQR{ۮɀPR>5?w3g|؍}IS#?7UGF0JnI |Im9٤'l<2 1yF|E,|Px& x ( LS SOHU0EiD]`Y6.[׈;ВN\E RNaVHrt^d~afԩ[>x~I>PN ru.1̂puAsہߓ'jY76&JAO<(o=sܥ/N?2xm 4BJa<"6nЀk) >twwwlQ[&\1G8yD˼(DBfEv7 _zAө*Gr#TIt/zѽ{/m`"$pZR@h@4n\4 yVX^BH\+R{;~X5 2 uEԁoTH1TuO,կ>L&GGC FySW{Ƿi,V-sA{3N2y C}bg9rҤ"DQvx4w{؆wysb 쓏'ax7 葨*UO2,He۸|G} Uݣ|AūaSAI'C0P,Fy,A3ԐI+9#Yk.p TsFNxhX)]7 j`8ص5(pVlݛ JhNY8ǐo$+so<}pŅݽ.--B4[ݭf@P<-8 h;lw7 |[5v7m>=|Ǹj8w͙}yeE[9s33ʧj~y=`Mo޼љjuT֜q %P)GK.<$sŭ[zWv@Q6/>g?hMMG8(mLO(#Կܻ{Xjqa *q}Ki*`4eO7 &ԑӷ7lBvƳ%4͚NI9_SEeMA<#Uԑ=z s/^:΃+\t޽(Nр,zv=>?z-YKY0iVK?M2(c4EADf={bk{vf4ieg)R033ӰZnQTNT_vdd@%9Rߊ1avo4 Fq%P+*˯*ԧ6Co­DԡAe\lVvJaw4|(+2R,;%gW;I4(mFY~uL } h^su*qthC\S|+ęDcg 2.(s#0f3O`FB:XkpizLQĶ-wXsS:T&;k!.*OE-ēi m< B[~%yN"p<!:E@ްVs:r؎Yq9 M:C!GҗMX(tm>,+WZx4TxMN(cuxM #;Vu~~/ k]V^㊁ E21LP}4Ϟ>M|\_A°qoz$&Ӎ{7olwצ*5+dDޥ2)N%4՞3L[*Ĩ{BVm~߶^:{6Z+˪NBI{ǣ3gO߻q&IKUizTH]O?ÿ+/w=$b.  VH$0U$jie:BncB/{]b6&$^@,R$]I Bu0O P%/@h3@-j.wQpk7U.ihZqj0 gM c+sL0NEgP7*B4eTbiAaD4 8'$q29>D`w9F:<􃇏p POO\pT<9UC"U3@e"pb @j܀Cu]uh/NM(iZJ~(ᰭjŜiLM VDt8g#KJ3+$t 5Iqe͈D2aTqB{R/|A +m=bӐ{4VK3-I֑Ev1yGx $yok;:\=qrpwXB1a뫯8w?on]…o!y]?#Zs r>{1:f"z`}Wte“wŋixYLy43 idX഍L5JV,c26N@HOiybfvҝ M!'r*l@bfӎtc|4'0./P6DpWl)!vATU C݂Asb Ƣy`#x,2d`+~(t3 准{9˄=PZ އ1pf1:dڑ`JYBi|7z; -t%`yr\̄:U03w;pyN$\ Cg%}Afjjrk{ٳdTiFort{k dnxҏ"dB6HSLf2y%7h?2O G5O<$ueJແ aBk$`ð 'O|Y8E4mc*S8 9wZ|謁jgϞS6F l z 6W8y?o߾~лXO9[g%]$܍5^xۿI``eEʹV-C?yʕ8JUpl`%䟌ڲim|4 EIRQ ݌zXdcy!ؽXK%MW~GNM0-isM~ȿ3ED/ +,dꈼRG&!|DLb6SXTIa J«DKAO'`.wD/>.֪1Jr1Pv&uYPOAkaC(-4x)<~@k;ܒ+cK{N@24rj:,x "Ij#U׉G}ES#DdLPU-n 5S<}QM AQ5i iTӧ^nBڞMMMUE/*xYt M.gtRT IHG7P=eH3%AS旗gf:^1ICL9e`w>wn"D^qɳ_nܿ}٧92QC S5rc|LFg%Q4{ 41Hu).1SLXDFN{*A|P0!־pջ_+pޟߴۭfZXFUw3?1 Ah{r&,NϘbڨ&aT5VNWduYñ^Gjp-F%у85IbKzrttϟP̛G{y˂{tݞ_\pI ݁iR~|to]lÚ$ΥKd hODz&H;s!2\!Dr+ڠ rU6!iT3;(>5q @,Ψp!pkP&}9*rJ9.ou27<#@R Vc' =HdhdcSjpCJFIK;M)CIB( zw#wA<Q<5?SoEN:n$X]}<' =4b#)5&$DIBr$y]3 ]MoC~ hOS//\NBS5Ѱ}[\)U~3Y1Hqrc~"'ڭVF B2R # <䱉 Hi|~tګ'Ol/ P1(K0!z:8r& I֎([9]Vm7w3t!*F\ ~mPyG'HG!~X@M58-Mݾa(n*/ tF@BXDDdxYb)D>")g6)RdF\A˥I6U)ފ]&kAn?1;"Biχ|(X<45 ccQJLZreC4$k\BQXûjD9uįٙZ {g/>s.FzŚ?6633 `=Aͽkh|`ObRKBJ 8[ϟLժ* ̩ӭVkrY9}r <-,/B) E}ӏ*O>={Bz5?;h23,D:! M4M ~1M~D4ô,Xe;IT GƓ 3Omѫ N{Am-/ϓSSK/b+~_7&'.NQx3gN#ah@KJ\A|7qtֺsG@ qw_X_^^Z+vJ(k&&TCYpjgs)FX^rExnškG֮kr+_鰋p<6$Ȩh``AO$U=@LI4BJ$ yNQ{ ϟ>|n峽GN>8<8wsg0Igp޾=8LO,5,hLf`A 2at6DƦO]rJC DQHOݿ^}dV@yPԏGw:iL_P&9A8ucSX8d4B6UrNAPFKY}7 T+*tNoPz}+S69 8qv0|lW`*Zc؈& uqZ(W;hwhų`3$O -g*ш 8gh ˘GLc&pGo|ӗ9uͣɣ5V~``-( fgd~5vVΜ˽҂3󳚩1*?VHafƏ2bX"0Z U! TA  h2(eLGŻ欜t)'Y"K|nt>8㧫V5ܸ pyq 5>1^4cctL 8HrA}˒Z7*}j躦H!Kx2HQc=l*LOfhێMLO-0!Mw7{ gts d3'9I[|n\{%Ԇ#)qbڧϟCdZ*6S6~qgw0ES0~ xB\J~͛w{Q͝^z5]UGV(y 5n9WQ; #QR hyA7PU'7j+}A_[[7BIyWp1H)Og(܏&i(4QRyc8m lNm'@=C[#"W0_G@I8yn@i @n2WouspP%"Q0+dx^Ʒ[ߚ^_~ձɑ͔%ik{\>6Jzmd豲ChF]+Jz߼uzr~2$j KeS^=z-X;۲a+Atz_İ c魿rM*ȩ+|!Ϙ*%*Rg lj"~dX.:UWz3,t&^Hז,lDIjL8p#s |ԾCqx:F^CEDhF| ~o¶Cc?"teq4TXGa*F\Zf̙P;wz#ȕZu`ЇtB!!62ZmVQAU:66qMӴN8vMb*C6=>4 _ wf|۟w;[{{;g/\vjE4IATS_n2@~jr ?ZRJT_=[{pa:EW>s9SPshl,aBU]Z^|ן?X}O-[#3sKb)qodqyl|<Թ83jt34NUT+DȩTPuT#GzdH2D4$҅A12bwg1׵/;1t_3 (0(?P%Dfih!҇OOwUti}sBA9U7kH$ œEK],P\$% `sD`:fcx<:-N 3`(sL&#Y9O:dn`GBiMxt A aED(r}^71Rڝ0#P ]DC'6s4%B}7\#8(Jn݂0ûiڐdP57!GGזfuZ@0ɕ3+"ېJy60:>?3+˳S37 Ͽ;Z:{__Z_](5QdGq& `;Z\ T8$X!Vkvvfh*"{E4UX[^C>μb(0ryLPrn<~vz-qVp&M-yfSCK"hxV^^]`tκ#xN{j~x5wqs1 ;[wtIiŲntέ=Nֺ}0ƫW}$iq&TI.< P(B n ?)cc^JA$B` Efk.ٓ;[N#:ݘ`qT X3\k׿o߼sOo|铝gϣZLwaw_|uO߹_}=31 u3 @6CM!*V'ݻNB|Jx4;}م񉽭Z._r] ;(T$(QBVꖂ={pcoN9Cd@}ӈrbQM|^8q tذzso(h _,M6v~ЅJV R*$Qn=xpnW'_<{Q-C:2'Bp3%خq8d!xaҡ{(_Q2hǦ8JU:;Q#DA14E ߓׅ ({woݸiq;ゥk@LT{ZRΣ!!5 ?NpB٣<Ãc4 E!,> 8=x#t D(m&8F81kp~J ̊(mQ06e(<5 EDHZa6!"/Y1'0Y^ RE7%,anhl~fW*Ru1&M"*)K=iNp]z}EGty8Ys,hˉq34O;^5:8$z)z` o\wg՞N}t҉+P?Z}lmdr>F' |Δ1pn/±He>pp̬)9E)^R!"c]G̓JՊ^}r W[{;Pck!I2[E-W,NMT!Wq<;S(aVkhCBlsr3P7_{fnXmAI}~&o}D)O 8ul 9mtz\΄}G12#nsE}l'WۻB #:JY-N~jnzanvg=7 !dLc'zͽKk>l/,w[OG Q'_}ů꿩VF?](l!'*}21Q؟|D(Xyn 'VMƛA%+Yj#5TYIC!"KbK1dFX3\Q7,Dw\![#:e^Xώ,Pzؓg@ŀC AP!J8Ydy}pw'޼)F&#FAX[σ3IbQ'u"4aʪ#Ur"srP(Hn>:oP@Tby}!RM%xlWyحf$t"㏧doч,Rb$kav#oM G J1djeQǻ{z0,UQ dw@)_R+: ILV ³=s ؍a/mmo߾w>(Wߋtt|A6bV(U)Mq 8\/2]%$&c}HB49D<1Qv,Z6,q7%)rR4gIH˘%p.b i>]98>nu+Ukl e i l'q<:5 韌Bg? &5Q0XIPͺ! >xnn5Ʀ~ӟN$Yt)CUCTJUFU[qUjasAvAJ6H$9z9K. kiFA87Te}okԭǏhj&(`4nrC@{@Y]{~ٜMT$ch3OTH| 5YTJv*#K'K:DHò,:K&V[V|L&ɖG^ud$keL~"H*\Ga`_{BΩ3(u@>pK4wݑr3.Uʅvxqq! c ^(](&Ǥ1ǯ> {o%DuÖY+zmdPyf3W:)\U@* .ضP0YO.LMO#)* F?:iudf.Jx j3l5&Yú P|$å:eU+JIRUuUi :b1 Қ*"ǣh. r=QQ{aX(WdYd,6.Aqwz4 )*6-5Us!D*`aӨYG@=;DrP`g)`4y4+;bNPT<`!3L뼰3by3/6߾Ç~~>ni*)hǞ*4E<~t(ggkwߺ*Z~j^Q7AA+P#y!W˹͍ Nt?9Ki/5]2,X^!TZUUyssE|xדNA *"h(Eդ\kz)w' V)N>`AX/J*XY>19hLU7bQn#M& ̅+Ia3$2 E$KGea ,UPFذ,Cyr{s˗a-Y9>:w_(ݩS'Ϟ; nik999rv?o~'?~'IUgĖF|Z̅P wyy܆ٳ,bc~VGK j\>MC-J&tc;Yw⌗ΠwF}tz:cpܕgghzN T|YfZpm$v{O>~qVV,HCj^Ԟgdy:VH:B9CtxoroCa蓳 gϟq@rPЊ 24 xMγgO]8?"BUBf@rTǎ{jR6(A29Rf>"qNTV Va|lpg$9KrG@[GUk |l;Hz>lr!HV\QZh%O"`M,ɧx YHhA,SErHsnHB#X54d4l(XO691V,.YrtO5R)@Q QB} v։qyilMkvZ'NY9qKV" B>H ;APCq\<`1#W#HpѫP"-5c\/M %![OĊ B4 #߷]ǝ6`wc㜤6VV6wGb!昚A&$$rkjzPӄou)#_] _>TN <|Aq"&GUS|T, \2K^8ץBy?19FdL=L7TYؘgǙ7{Pi,{Ip\*qб!I;0ȵ5Mqڇ[{G3)f$gʞQp) xj $|0@ wvYFB6"(!cu^:p E,DӣQd>i@\#HX,pqE:IF1%xʐuSq Qj^8i+f{2ԟBpKE! 'h zxA5!{/?ʕ~ɓx8cQz"ɟ2erYZej|4rg60b,dL x=T ȣӃ# ,Q;4@L:'lpU˂h%)< [$2B!۝N7$ 64d?w <9غ[?\Γ2P*2g~nLM~sתf g E<{.((RDv\&9#EGG5u[7!U*eɖ:a] |XtQ;ܹGDa?c5BL##ZäVO}GXHmV؁:-U$)f,8ȭ?|jc"kq$TM5:Z"n/ێp\aj~ilt\7LX2hHW†7cCiA1 4DFiRAlH҈i޺~ Ko;{~p W[OWwZcc#491i.:G;ޗ5CTLR쵪W>ꋯdIBe.L*i9S(v#da5> Տʣ#c?|#3s:[a2: ϣA߁,&F 5$dUu>cؿdG'ݱ{ gE$QeNVt*y'W > g`tNr EBϷ~ZC jMs?\tzjz>  |T6wQ A&29Zi8h*Ab1Btb!BH%@ բ(F3LH>#b*[Hc|?t+`gcĘ$P@@t;h " WU˯SIT:ZREnw }B'Xfj*|$BLB/0P(Ƅq &dIyCKu8ȉ#pè^ˎ܊%w$X@A]A/,R0q>'LkJpL|BXͪ[ȋCv,r'& L]ҩvp{nLNOT;o_97_ G1uiI5S$z`Y 1$ZbGzuH:z\)דpdEXFoP[U ^x"&AŰfV; Ax,\E&'4 @_^3V.,}jv<37(, 9?M=Y9u@VH\-MRCvb^i~}eeŶ]5.Dɓ;]C Gg'%ʠxD^?W>vm*{8j=m3sHPg$$HJD^Ν97_olOª^(XyعW/P$ކf3RDpKq(-qKʗʵA AҐzChҍBڈ+&x! S?(ON%ul{wXj*ȈI== DL,>7?umߔjUQv%!$q\+Oǿ~{ Fud<_V.&1Sl|,E)GaPn= 231HʑF3ET\|4#Xr$%p 9PObtK=u9A/X1V/L;yhcg,(q9=zp/./oOL]z \)$bTASrG Y7CNbʛf(V˛;?b)N/h{J-WšJs0=3^EIjxY)WO`E_V1 J,ȪZ{)Z4 _0e܏lH5D6 98LJdS.TX<:Oubmٓgͽís%|."1|C!}4JJ^ori^2vT>ʉyѣ$阒;t0UB胩i=,3\;U$$#v!9cII3qHAsvCd]xZ@劦ܼs'?NND[IцK ~Cq7L%+R3t8$pL$;aCfysP,q&ދD%!*aꚩWjr&$bLt29 l2D ~裓nS;Sz2vEg r1K.2:f)_D@%xTxƑR!dS5!7SBDK_~_bzy~inw;A @Qkjhbbz1CYbz}ppz>K]kq#Q L˄{Ĩ`J)8drrG]ȸXKD"˥BnQ\Z_\^h4Y Pa+|{&'gZb[^$23AkC36$0V(OMNM>yhokknz ?1jm0F!o2m9(VL f xK&zsEމaBڞ)vlmޫ,5<͡݌x|p||Vs S ?lcYpuq沈"Ex2}qlL)Vsxh꫷n8adz-EٳtbT[;qAm{ʂŁ[/n}w?;7=zvptxiv*.`)4#H\li(kiiyٳgtA@5cLp>KݮFqx01=)23ifxR/F"* :IlI2$  {c+C!k:`9PYf,~ݫKDP5)D!J Q҉ %$P5NFGjI""3p*e # Ț16cR x'ԅ kiRQ`͢x܅) w3TD8 / +)"(&}KM0dJBCp/pgN\3iU7! B4VUIUl,J^X "p|2IwlEPo("u%+\Ĵ^Z_Ō1_tL>֡72xDĤDQ2]HJpGI}Na ; |9a=oSܻOGvy_޶= 3pr +R"#+#"W RRPB%z 7vLjS}=S^XۘzvĄ q]W/\6Y;_SFLUrUSC˄MAH_YvE:˙;YM\96kE;v8:*l4&1!aм4:=9ژ@y>߹sgOti%]$Bq$'BOO W/YF4" n&#t1{,ֈ1@I$[wp?t*3Ū-[uTpw?rKn9w~zn6a8 .-7(pA@WaQ it j2&J`xW+B`yuBi^>1b&L3E9eչ10O0509rVj#qdpba_Ӱ<ЉpCjQ,Fg@Ѡ@*1c^D#Ef|dz|,Ad[fJXKu4b:rґ8I"ms :T7!PK~%zF;أM[q5g/-%["0!AR uÜi/Rᖍu(+ S@;Q 0dc]/a؉sN?sbbF-N*+/ mU%_EGr!$.NMJ0,VhE%EW0>x]׃:ZLziTs+\)~ &ukABiM}K^?S|.ftD:qYX y mskZܴ5S0 JBG 'P&A91700VwJB)$cKЅ XPE\d3K|M "M&@p|x=b?7L}nnPGWQbժPō̲{*#7CDЩ DP( xk٣c ==:kSFSgq9:8h5')bHx'Μlk{tՔ48[Xja c_KC|#lf q/xm 0##gM2ŝzW_mM_(5F+dExZ"aw0ouiН"HD՝|;?W:woݢrar' %{4BtCz_2mwQ?Ty 7([w~5xAu$El[+}op¹g])y˽/>dVST |OWϿ;{ӕ7/ߗ5Ҝ=Ai;::K&Z-v<*G;FXTFO?Q5,J2X7MЬ9ee Ee')sF)nU^Afh&( A8gk!flQJ##liRsnA A 쀋]0|9qN:qTX(qB?GgC^G1{2Ӈ++sS'O.-u1c$(=7qF'18R 7&~"vN'XgĊUCjk#L|P* M&|]a O0N⿁j˃>]NBH*S]ey||b@㽍9oa&U'&A]3iLK Ν:W=Wk|qffnԩgOO.B"dX,SsD7V8NɭIi| $ q۝gA4FC27EDt4yY,NCXO]T!d t 땚nP'T3f''~77vPz5{|ʛ$h臬r&=.B򄙸1nXXHׯ7S+OmlYbjO-QT/\SӓG{{V76˗̢dXkUtke U%QR¬Hf$S7#*ݑ\8=3Sى)TKk.4*fɣ'W.\:p7{ ^y^;oW+u_1mc+O'Y.h|"TFVKmy^yK|XojPu>a*6_2MG $ K3sj;zw>obe9n`s"|;o?p[.d1cm[V.['7ozZzq:!,f鍦㆏bM9aF6 RކZ[8Nr]͍0y.ð,;g *҈6䍲PL͐@MEŚD{1y5/%իʪƀ͘@*ysBz0T,Q\ ˤ'fz)Y}E/JKA[Xl%W4g/;.H) ?^#x4'v*0 ^T}$0bwZ9@_m_ BzPMҴ,<اc$~\K7;9>9M߈Ұ+yCOgn\_x̹s3t~g;_}:'*SZSRB SȢii&![ 0.D~աQ#=H7 #pu.zO-AGB"-cAx,rL9m|rE}-26u=.xÃgV[UccjTQ7 M901А ?PQWRٟwpcmۥ SSr<$5%wѯD(Py~%%Wݶ(wu }h *iQbL%PB(}CO(WxQF)20o:F}xuڅR\oP ^'Kŵ~dxq?|W3A4BRrDL^GX.`(g30SVD}yԹs>~7禦տ'/|~/8s+I.ݻ[׫uh` N3>0 =1 L82jK#8S[HV>|Ʌ+WǦ&C- m !8ґBLwɪWJ}4rpR){`R./#0N6Vޥo2 @U?]}x|r3Ο?~xZAwcvH5)2 clA<|~q??O߀PXxt$XoojK~&&&\[^s(R`:^,fp<*Uaxu=ǫ1>?\x8Z܁* (ag^(QBVe粐L8 !B gx# j24,U'υ,hb Z<,#Y3bSX^Π7;hW[F ,p8"^p<LcXOʣmaZGT[އᠿ6hxf]t]0oCD=g[ӷH3:p a^ CJE5"3jTVJJ<m ]{) ݝN.g7ϟ=o |.^LŹgO]._F򅡟n [Jjv;v[#\r/*׾Uv'ƧVZ=w__Y[[0 :TU;awՔTDϟҷX=9vnKp?}% <&/jxΧhf؃=$N2-* dCŐoK֊(l)?żXpf*/$ށHlS};kGǯ253;.t(C6>8`keїϖNKe=r1A< E=?Uʖ7RtMSFItru">(ڤ3k)dR r \%`m*΢`n@ㄒ.aQOABI #8c[`E=cP^fR曯ӟ%O?})czOg^o=vlJa&O\,JZU,=7Ǿq([";s^` Ή&NgpuwysINia"Sxn䃷J_RqC_"yk,>SA06K/_[z׿O^zʕYl{:?V50@+ g{@nKij_ wlCʺ{;O<ꩫ$dD_)D Q0Yֲ &ŝK 2wnvqgHwBC$;J/%rpB\s&tsv j|A֜Da}1T IpPaSw8 ^h %yaM!ʋM;뒣K8ױl:C^!m@0΁s6"# n0|`}K9M9l> 1 LCO#VQTpyhj7WVWϿteckwbfnz|?<:!`fH&0n+Ve4>13~IJhq5c/,. N j !k+ϓZ샃"nKC'0WW(5\/?by/8/Dչ3|󧎟] 8H-~%]YžT(Ɨbn@7*=:HIWo]vރb0 FVJo^vg)T\lT|ՍՒ`XVKFVHGytGm<1u<I²`paWa4[W% z[.ݽu9Yg*EB~ԬU[iLuQT`ich֛5!PTPyH^(U ,(gt/_Ͽ]167rAɀEBvi<@GYJU ]D3<'Lv:1  tA,(-ϡ4,[e,Q)T^Fߠ xqEN6F#EVR^tlj'My"ch-#6=[ixG Lk0#IQOd yȒd-y*梈WU0q3u*wKy T<՚Zk5+ BMTHƄ1 1f FTSVD1qAj [yD,O3і0+7 --DrՏ`/ EܧNdkޝ AD?)onD_/aGIعӉ_y3/R[}l-y;ȡ!OA?CR"Q8,^jZ< :1B,¢ 4AVWc$Lhղ-{ߏ^keУAs`JDk; ̝kYs^\y%!)ْ 'T.[ iGXzKd *I2K•#iSA$^ Bi͈Zb31]gڣ (a/olsm$|b~pzn~zfcs-J η%oб!3VM}xtkW}7z]5ɾ;\YyN5Ajbb%3b"ZѺLWC R|7gk HFŲj#G4$>z{˄ww(a@)I2VmgGk]yГ|D^?AK\Y)k+GGwdՔ To6l htX5N *}w ۇk;PJrırD($#, x,3'cM6Û.FZZ. 6Dl-N:XKZmXX-7 Y"9J H6t4Zc9DPTeU4Ux#ej)۴q-bÊŪ!C,t"30d6Ihsjb< _@@6.W)x$ ȴ= %ۦEă3'bN`-uz廯uKOo~yXZ:vD==3C W∫ZQ2Ha}C 66w=Ǭ4.]OQ;=EË):[OC2S<`BZB5;Xslyyɉ3g<\Y,&}h0p;nm+g TJBI|ݥY C:m%j.̱Zݠ0;v`9^?s}P~lsR),&aUUnUO JD\ȋ&8g+Jc5tu Zdp Eqák1aJC epᮉP_AÎJ378oj:Ei@i&3)&S([}4:j|Ukuܾ%@)iu]){f͆oEߣ3yƍ|s%ZY9\ehiNT r7WoDZZ|bM8bI&N \ht? Ν16c0A~<R! U|,uJҿaްvQ=8>җWG+]/6($?fĞ")R[b^t3ީ`$ :k:TVA׃.ThFS@tl cD1 £*ICzC*YCBZ筢eh7z8<:*X\!OWkku13ox%H{DJIu:~>ޚ6'?u'\g-S׍|:{F-aWl#TNE<ԔlKVzr!=X~ĩSoA7dkO9]@R;QI3yQ,Ap5O߆Ƃxj"/XR.7څ 0 ]>^8 {vt?\EZ7}ףu8˔;sA[':fkʈ@n7հlLGd狌AN^8BY6Yy [DYAſާ|b %Ĺ 5>|}01ʢx;]r }ݭ5ߛ[鵏/./593M' O2rib"q~m8hrVɕzmajDu1;w/єnļI~C+4E˙˫7o$}űq `<)l lYg^9{jey[H!UJ*2>y;eƱ䞄הauRLޣu83D&cikG V,Oe E P N鷇3ϜY~|23ݬRnԨ+NTX$Jd2jfPrsO(.dٴЋ7Jn\mg8ſy3I0vñdy,lmV% C9sUSl-A ,y iY`7\\Wl͠ yz C_(ͨxL`SOSF$뵙q'>(t RM4jg/d9 EP:8u7W=6vڞ e$3g%~;Mow'& bkUJ 1+$52ҍl~a2:m -db'sIGҊ1\<%E%CC(OTU#`,uLun%QZ2ց!#g{J#‘a*#o+*ʥtLnnxmb̅3>D"wP%w [6k`0L9>l߲oM.:/M?VSuS3ROb;NIE6ZD2շ1kf0¡84ɱA{iэ[v^r7 (!$jM 7A#[M#'TkbpL~?gcT>.feUŮ+oJXS-AʌסM>p5DBKFE.^c +lb=PX^OC#m7^a7<ֿTYʙ%X6P,mbAX/Je).,^/W#>qlJQ);po~E_/]\Y^^yL@51A%w8sZVNUfffsu vjKH5&Q|dv{(ݰ{60Mo.,L/榩w+-XӴL*,F]iKFt[GC5i4=^r 7d\X(b"Xda.* 30Ì:mKkdƓ{F .lE/@9dCJ\cR?/ՊG@%T/EA˲RwAEa1g:ߡ"5ś8'?Qw=*a0>L^3*oc1NaVL%O-CdT0)aN /K\M˥<ӧlO5JkbIq\W3tYvMѼ ꂬ?hi]p@s= `hd "dz\zq7h 7c"eDr58P}*4HQU0A1xuf:©3諆<>h<8dž L_T>5>]iAGӄɬ%k~H2L8BH^s-傉蛄8vpx@Y5os3yf;Ewo jU;Szֺp!+7iPH#b4>;٘ƍ Tx  z d$H/Dk|T)r)fFJ8Lel,sXŷNDs=S r"(H?7>xW%3['۠Jw|ϯWR%ͧ+QΖ 2҃ߜ?vafgJsnDQ[he %l//-kwG@j81*vx:Raw- 36)agH>F[9SK_}O21V%^o8=7(./?w|ܘ VԜSVШ{Co6avz=ۈ ɵXht2tQh =>65piE]Y>s< 3!qLc=+$o׿oue3Fje떚/SAzm[0W-;x#(/Ҳ01BHth !\0Q 'I8kh?5>_񉱌(n8b:nb`HZۖl HM7T>J*|S`?9Ʉ$k`STKU$I A0tblSM^h4B.쉽_W+QB9_a #nMd_4,}za;8z;WڝFld:',0濜y*5;eu!1 њʖ$+33ݿ{=Q'ly4\p\U)2 C<e[GRtKcQzn%oH/A_5Ug F"aP +/4 \8<hn]-[zE-%bX#lAOϣ̀~SxGJX2cXhBl5߿؂3փ_bySDq+..JJkŜ؜jFZv7wר sWg{dVޠ6d4nVX7V%Z(<:]f^1W?~d##MZZ?,MN^v%(K;ۛ^6D vkԈ+/LJKbwp8t0U[X,r>t%x#~P+W @xVyVQoL{;;eW&KKUzZ Z&XA=qeI'3@|"jW񞲒~,9Mx }+Ʀ&əzރJ)juz)cw~D FE@[*x.8,PgORXY ם2w߀IS,y8*g#۷>۟;qWwww$3b^Ec/\]SR|tU(MMťdzrj}usֶ6-W& L뽾x|>R!|{A,؊눮Ņ0B6FW *4o+gj0][ av-ڎƛ TQ[=-JITX\7l5vw{I ^Ua2]bq9г,S,pk5{tt] 5Ę]3C ٹ1oġK.0d5FC34KU3A@OL&m^h,3f2klX{~78`~i%w)2A'Ds*\o<}FWެMNNT|5GA71c a$k՚ibbpci&#W%k4[Q>WkokKj-TrVA J2:z:ur@w,7(]_ܞ;{6vͶƚ#3EB!~+pݽgwvgXl[[E}vޢÚRH/3-¢x$S>PWo˖٘6))77$~#_O]=g쉳Uu @ aT|~_~o?穔~(ŀi)ckGF,w FxŮ"D-  sz֜[,׫9Je(F!hez %l!$U7Zr܃{ɏ|/ClŒ 2p{ Tv={~dxwoݾBLF:Qoސ73J*,0d`f;Qp #)(sxtDLEjh3[xEkө8xBA?nߺcұSǂy}۰f?]0sfsL}fBF9#Td^Q*M"ʳ'w0rOOՌN#vBJ88{5&f^}F {oБ)A'6 bxғ/u{mѱ'H3?X^|Q2ϼ-,ބ0CP-n-Rfa(A|BLS ɹK~jV,ztSZe8D^C5&f1\ R֌bn$]?Oi"eST$Z$Ǟ2 4TBp= ]lnxoٽ'won,?TeJWUǏ:G(Pjl7 I)nX`{sswypv^3.T[r!;ˏ'RQM|K}FuKKKY-Ez_+>y\{/rSǼɆkTsZ=YL'V( G7vDD^LȅTV (U 2e}yVYX4Ѻ$Z]<\ -a+jn)(!\UaW.Ûmm jǰl}~ܹ=@`NwoOd5wN?R7!"/N$I.U"AwOxV|V !c9ϊI5pBetdAs4O6"#~v<]QK%aȁlE8i]*fGkQ/~;ޝ[jpIKru"WH [O*qpS9w, YȠ_zwif2ёNwd|Ddէ/Bf|x׻tiozkqɼA)__Rim ldv_~a6 UCD3BC 媘f]UaH&h4HM{S̾x~mv}1sn\yAT=xlVWq84G& Gy oPw}gsz4ZRiIlUJ{!vI>ƢOLi5[RUri"j7_?0r%D{瀽ϕb5BB CǼ$t g$9N-icGG-( XY պ'|?xr) w*2#0LBc#ׯ_zxxime}ww8]:ǝw?Ov .,;l|%Cs\V3-d e0\e!7m.*"DRdW}r 0p\r簦O,NWFaph8:*RHj.NgM8K x@.3 z!'@(PWq%^<D)i9=Sp-ljAL/LOO)~'/tJr &5ڱⓋ уKne8΂ຮ,6Y9BLƑcE >PbD XV8dwwO痳..qۛ;{oho8c°x.'O(޷cS+w+aߴe>#Y LEt$ڍ.T#r/(`Jѩ/ Z T JCoN|ULK{.MON)ʤpO|,dT[-/ljyȚ/\_CzI^@fS4Up:P;?2(¹U[Y}qd-a WW#/^r ƋŊm0*v֛ۯw=_-d Ӌ*ԈC1\yy)n湳QiGMBl,Qh.93<.gzlq 6[{}gpPx1"<ܮaCCS+B VA\QBKFN;6;̓vxh*=\(pr}C*r Zj,`לK<R`EAVP\khBk,4nrE K1 xja "n֛ ~[H hθ4Yiʢ3JƑp%A>0@Ƭ*޼LӀ8 7Q`FqfNZ.[m42{ưs¢u 6uJ5 2ÿ:]6IQ0 /AMr̡aE$碱QvghyMR\MXn8IsÖgZ/L5h;X|r&EΎOC hM5''!Bm Bj= rh9(h+ʒE,`E>0L'g]8pl>ޏ>8>> V9SzsRرE+[z3rql4Ȇ1]oh.TfIֈq5")-S$&|1P;m&R80]نINQɃVp&+ gT!DQr3e}/DU2A֋jpş?i6ZtEf(RhP,At|B[x=T8"ZTGFvT~}HuƠY<˵bҀKB<N\[tF\XfHQ8ÃGIJ)KT:XVtYHӲ~TwҖ1飱ZiS2:OVO =]ӿL:npU1xxokeœ~ZaNV5j~o~gCUU|M%0beN.)2'RddUQaHW~ 2 ꆚ9WϿz a3c53!$)uZQ*-jqp|6!h+\ڭkf2`PuEAfѢ-@>S;nȺnn>߻Q&1ZhV$58 "׮_|yxwvQM`c|,)bD<Gj`2LGIr?'1曯_r<65 ק'SSӸ^'xy`W $8E;mݦ3ZslfC1x̝pEQyUH6\Qˍs^7LP)0@KNG"|\6 󁖮ȡ*28@pþAS8+wil Pˆ'WL@E-H aEf9FkX@O619(|2>Kt 5Ĝ&nPaT*d2e Ύ)CҴؓ1Nm8LT?~|j._ ?)'  ߛ?w+}<"TwxtpP" o8mCR|o\aGU]}joZ+'$aRԕQ])U*%tϰM^pr;s<"IIOfY&j G[bE o>vZ.pRml޾ƭ}!_ k+X m7q,b_` B1_q ׵2a"ғ:1g)iM$bZYmJt&!n,M=cNNv\-O?`rl#!Dh88n采bY[:D'a ^W5ݸbk|+S]B0D ~lb╫~ċGd7zF&j `Fmo=9m!BPX8gƺoiώ#l c%$Ez+nPÕ|P* YN`kʵZi=Tdj?{s7'ϝn;t%[ ZI!c?1ҿV/v2?W|oSf]h#$p>9dr=K?$^APXyϾ\pqC^`bQ7_K:p#]TYh=n0Y^&(|OZGFzVx) 3 !9P@D>W(VݸKB118uE1={jq?9<֨C4 T?OAp}' K}zsK4Ü)OZy(fT9::x `>WDÄzFWr1b08ML82c7h|+ @4/{[X}06%$LEe w"`ʫ5x~OMMӻY,L; Ns2>ynX}Ɏeڑv3s5\&[T*W/ RACw$1Zpcs7+fG'rY1}|%ňCxV,˷o\kTs}y$`/w|Wi!,EqA9_~beϿWkiRj3vvlT7FW_&ݿϿۯU~’U_6̘iYelZwwWϟ_"A۴ŸJDd󐴍 N<7;/|ڳlV9EDpo^2d3\֠ݴ= p)R!I# locMH (hB#TX,+syzO9{a|Gq'QI gCYj4P)tUo8:8\{dpunAf1H@sYT6qx7 ]']jΉ&SA)fʕs\\+&NU4 -%]G-Fey$ E'@{c#xP\;q7$@xP g!UWI ."' ;; b\q[EX\v}q/mÇȚ.a`?FÓ ol+U3F㱐'YM0t,-%!0M׺WewYWVb~z+\d1^$EBG[1'p|fkIi(y(ndO5?GlxjRZ#|Nlol]ӑElOLLL|Z+fg"8"@(LnW\mXϷv/_ XꕋwAgJSp4 R2ܴ5k܀%-R("Ȣz)n1[zJ\GRԈ$.НRuvf,㕫 ]cJ[wXȣ;z fKWv[FFv fUV2ЄʼQ:OS9C?贠H#*sFG̤nEt!pGJ؄8A&Z*0H@HJ+H-i״7x?~|rDj+n\Ky׮ i6fN8b yÞ4w?0vRpjQM2%E6]tu/ _UGg Q,00 [k^YVD.&b',TV$KBS>19}n~T/`t@ANMN2!,+"W\yYYYV㵌" ]w|bO6g'NScsS3\e }ZVV*#a@9tN8`@OH"vS@?~&L"yY<#")*ZDv5m4-snAC ^ճY8aen"*eRch Q] HCg Ni2@JцPFQy>j){6  KјԵ̖~vKSSW߸YX9c@ ,'Xp9DߝT Vpexv#h<+Tls'g3łk9bq9H뛛ӳ@zFHXgp&CȵCi) 0ER%dDK?>LKy>X?>˛o|8{17J7oP豑|ޣBjr~2/87iI\E"@|n-.@SQ.ْu!\ZZr܋LuEUS\>i* $N½{7ۧbaaN!)뻯󅙹yrb@6u?|ɓZcxV?<~\ꣷnƳolLNWr- rƭW_*;{ 6Ҙ-\ѓXV+ۦ*C|b{.]bl|$\YQ6l%v. DAX̬^E/ CpyҚXL, :`=q&&'6nE$+g58cB Bx-cZE'$ϸjck?owfe^j]aYld#I GzƆ_puff׷6X҅%sj.q.FGSUIFbm /6wZ @L")p$B'{/T="rJNWxv?x/P; , p"nd /*'GvY+&bVl3=tzq|5@+!Wv% ^}d>9-gsceC(A@NA_ z^4 Xཇ'[/<9<9@ԋ߉S^N[e$V}zGqZ't!2,St?2 un~j޾sedd7 \۽rH%<^OF}w,I$ @89厛ᅌ656R4-sC 梁vD !ezl$Clj2ljHd 2 L)5> (yPYDG*\}Ddd\jrcwVk.O4M}a[Gt~;wΟs}.6D^_sl?ZOuխN0jbhۿ`>˧=l V(ÑU@B4lm} -N@JYЃjK~ќ=v}`N]4Ppo{3_C>v4M!yt̤sr_}_l}\TTwh0 OZ}/:2nQ\MNㆾR?@\Ipi$x>{{yϾ>3r+RAHakZnzjdt-P5!MJ߁NM@Kb^l6O-I!!Ϣ|5xQt\i>}݅?ʎm.~VmFQNO#жs9Aj d1:Q'%zG8xzM9߳ln/~/ _ ۿßAܐJdiD3R6RtԗΔRQѠMvŜ3aQ%SE (F91إk"1 <(,E†+}.3BE`uII%3(lc9N}g40رH HIĸVjI8/(*AB5n8'_|,EEl`; ɠyr bEB>9&yN_^e4 ijBd9۷5EG{l*V}>i:ƍ|9pʚuw0`uw:{_onDibײn+"%;VIb \?0 2wmj/_:3;ﻨeP*6FGikQ$c4BZxm/V6ʥ险Jh&H d a6$^ 9hXU.P7&U-sy PblQ',aZ2AJGWy<|$rd!6R Rů1N⇶Y+rFz4F/W?7q.ݼujJ T+ڴ|VpB%989hF8`o6_Tx0o7Aɭ@ӕGYѳz:;I9*sqL\؜h[EpP Y߅k,-> ão56|Z=?25RT23#0z”ȍiiտq~%.`8 h$wvxѽ&|&Z; &PD!Q'Yp3uYvZ7޺?W0Tur`t;/Í(ql>ܲ1<1&:"Kb`1 .U-p'wp^QUZB!/q$+dF!~a4Fkl̙nAEImmno][dL(\tb.GR0 7߳zxB [J-zO+hgk*"GΌ:z".U3rE!x /9c08:>Y\:?4M7kRcds A+Yc;*" p㰺"0 RgDly&vEM/0,kh N{8 :].|`$UZxp,\rh{4.zѦq\){nV ,Bϱ2p',v&^Y[RX:S4d0`Hqhˇ?>t}ab^bKp%t9/͢ObHX6ZZ!/oIxaC3+n\hfg,;k /kZmbv|/R&Qb~qNA9<>m{|b  /9!]mÓh^jdCbRBvԱ]c&"K2!IGh*|o:MִȥI(qÞM `;M:)YB*(1|u,c |lښlۆ9sP$uY/_{uRnӇ<@hli'g$.\vGJpna) /b˦ng!%Nd}cs?t F6Y\ WD+H็;4ƈ8F+ϰ5j%"+Ȫ<D0GW3\Ymnx ܹ ٬jFӎk,w-]4]\IQΠ2:uhI9Xw[n6Nm(*|Œ6LsƴNA6ʲ&1O}"hv,TaS]#rBa!<-[Vq8WD ߨ=\eRcvjwt8|XT R%I[=߯Gʵq@WQ 8N dO5\x\6 E7*8fAL%5I,>+h, _>bzkfz|9=d1?:> T(T|FDrݣp R&>Epþ;usYܣ<\L@)(фVdBO\ pgsD6DAiԈ!dFtTKd >;h58Irx,c'cPyl}Dn> :ˡ$\6 P 밣3''zcg S%Ү=Dr$c 3TA}98 7$EO^.' /)^u_Z1^Ͽ|vϽ4;-@e{zp{|H)ClaN4Gp|9,tU,ʨae0TVnz:2:_oL_<3Plq4<ˡθKK/A!_6=B d"ZEFbuO9 F*Y !dV؛[_o~ٰj#Ε˥gCIϴN!lX Rի>{{l1v[v$Khu w $UF|3bNH&XVAm.pٌBHbdHDPoܾ[oPxgD8荽$8h~]pLaiMs<>h^rlva$e3K DTriUSScБx^Vdu[V.r횮2xaL`6,J9$JDz6y L2䟎ؽ|g`&FCU14&GeV( c.r;G;k+[/{~ CڊTQ<>yV[i74!Iqn'|\ oh!0!XR$q I^5/~ok|4.ރg*4E?3{]'fУA҃w"SxP9!ҤО 8JȤB鈎+-{rCg4YiE>sCrfh 8d.]`m{r}wgHM}on`)E-yW[X}qoa\cdsЎ6pԺ3&_pK6sK \P70X'ɸjBmn|soS53\V 9P:ޓ$9gmuUUpq S=ˮU벦duY }D}#`OZA8%$a9W0Fh-1k5fl+b5 yA$A@TUڂ895e84mo3h5QR#!BA  DO8 C(ӵZTRHNZP"]®/]a=TKSS#W4elfNw{ox+@8Ju9<]3@{=gt\B!$fz$pC81X\;o]xۏxzrxu"&U!O8e[[Y?^LB܁kl٭pq}32|uLqk3ɡ4&B̒NLDS1RYgR'/;dllk|ӏ>::=nВ;tcXl4[-i!<-pvkd V>:t_?\r}~a0 A\B@FΘD G;D!/{wvvf~}n^vN76T$8Ϫ( th4ǸVׯ?bUG0l hR066qaz_+oFFJ]Y'@t!ArOgbd& N]QL-)FRkFfMVH<{]ą3:p1Bj6[}[tsrj6qg0h'UvĈcDܙ]Z6KR_,uR%5Jt<35 ?#J|9 y|ʒׁm8oԗ*K?}ewNd+c;o}o0KŲ\GGY&@ܟm< Z6 .iXG7RZ/)e>zzmzq+7F&n9:^GĽ1Csb~jj^St͍Z"j(cߕ5K<@rNS?|U}ygzz9M$3!|'%2:%'E@eJ5-Ȱr |RQtN2MLA.`o>S{Ř͕~ ×6ɃGK8$_(XؖyG ?=a"pS7T3l6s׃A1XT 9yi+cSc +lX$?T,tQ@(lжH4P&c&d%.Ycvg NwXP\dc AnmE&{s>HE&5,>إ D-GI BnlꄺԩLBjEz n6 gsA IT Ϩ9>X29M$y8*凡]aјfPsrC,y|.imglb,l)ccܖR [`+jduk[ojKEd߼ssyT` e$4SO҃`|\+fIS)URם+WK(}YE:d~!W Ҳ) %}sB E|æ{sƧ'+ tp6&TWH˕b)763 %Hۊ"vZ7&b^<:g{<$KMׁc}?ujCp?]dp}鐄hfi› Q}}ϙF/Ha AnD24Z BEA [.j,ry6N8"9Mч lU0lxiM>!r||rmmq"N4tL!Kb7n_Jɇ0HD890/^D.B.-qr!ӆ1 `?& y%I,O?\ۨ!dQޗ/,Պ_ï/_!rxGC(Xj)""Ĭ.gs_T2˶n1&OdehxQ7 J.6x,r&4/Y%R' a01VP] VWrBm 0! A!v\Q#B_N}cB9lmmMNO˚j9!l4mbq{%NxG@xO"E#Rە4QS7 c SR¤nd&Ù"0o9:=P+G?^hnom>$j$2x!YfEsj=- ҵc{o`a~1 =']+˜D(-7V.\, 6p,I;!2tw/o޽[}Z'\Zb,`8*m 6'l몪O(slʄz:7>Jʗ#3Qg*#wĹb~`>ј"BDoGI:,E&# XN|#,m2- Vu{ whof\<#NHBBeUU¹o{shZĢ ВT!5g_<~M>tɩB7 %T$neDzFvU?aFqTTXNZlVE5'q:/l*T+|$p$%p}["j*v x8M/ eL7F:]\*uŒӠvL><\4B!`~D-y6&2D#/fLQ8Zu ԫ(Z:R|տ-zJ~$5M#Ð2[-G=ju==Jte sEFuO{js` ȓv 6"sEKwQɜJ쪐l|Usp.]v۞k,w+%FUF8:j]GGLo}x؄0+2za+V zlȲv8p?-)2kR:ڭ_~{Λwww*7oˍgݩRQ(AM2=+ޭ "L:I( p yYMx!!uMV*Dtj\)+b]d!7EkpemOPU+:@wvvfCϴQvK;wo=>> <\0kccanblEL_8!2v%IUeFٺqmQ*nac\to`͌fŹ$UřTEO)8')wy*pH $2|WdATX'pp.6q[\&SҨ&*͓CKuه1:=yxHoS ,qw}Î}DʉKQQq!,"?8iJH{fоIf*<$6ђnӚ_(, ɕN1nHMs~ih]O;K/tTx%-MęCIKF6å3Lڠ ֨fA^KK83C"%I1L1 ζxCӲ-@Cghy+ɗl>WID @aӱJq ʭ@*Ś>7S Xշ-9!ϝݨ0 Л;dq/d4,,qr~b4k s8n}1=9511j5EN bwQNEY>53/8[f?{MDfND7TlRi ɊLg Wd/w{ZFVJ_bfx})xť\K%"@86-E&mR ; 8d/85;765e7, n71|ش w螴bTqQ}_RbgFA.to!)dL$R];&< |ϋ4?52g1 ИOFpog疑 t".h H&K ܠ62rғ{{rnlN-%Dh<`|2|h(bcN|+~G?A!DwMM.etRK\ G4WEl;onctSU;޸D}WZ+tmr?WPREرeIW]iNe=6reza8rV69B@9 /,Kq · y:g{ۛ=\x͉i=n  *j-cITDGb.oX5w p zK1^Orٙ7# 4jnGi7bcٙا}ЎJ3;fdڱI6 P@ʛ=DKoːa`U潿9wMym-iϵfg0 )'Q6@xHAFNq̭H{Z_dPD:%I@h8y*%;qc݋fG_OGzS.~򃏿x6ϡKW5ͬJϷw.l\r Օ#ͳ3\aEh?~IGGvHxUJJ<(= ?6)y#vVYߏ,ۡVs5Ce^j xqc))eYQ #IQ/.g# ǨENƥ۲D3Ï͠+j*x<EpuJw?[ί Z捬C Y] (g, ^0Heb8AkMh(a@2J&b&xh;';^nHT9gĀfz;O]rBPjdDku'.{/6ZZ7 $3SX&Hcوʋ ='Go$wڲvB$˂vi6[ kQU(?Di&M:S o Q{}C!8:y} +a x6 5`)v~WhvWJ)TI#/b粇<)Qz(MlO.ey kISf"x"9O.u*$|ߟ5vT4fXiT+uYƍm*ȷ&V]񼋣2q*r$ɍ׹=blMb"a)QB+W(#▷$U>l* >`ˊFC{'!5SQX/Z:D㌝J b$$r"'G96DNX7;{/4tG#H! @Oss8eSy YM<+HI/}ɢ_z%].(_b䳑y󟋡'x\[ʝS >Q?޴Bچ*vGUbqrdJX>R08 -yN(sTP)Io@jㆁ? pbY !{5R&g|<_Ϯ_uڭjmR)'iX $cBN~iQ6{Bqvn!"Ih<JX4UH}[ܢA{e>CQTT9j\N9/BI1%  V=};m7$H~2D=,ZV(J2<`P cT8T2={Rai|͍F ގldRV?軪,Iv"Gy+,RGpz*9d@=\u  ֿ9%_f"͗›ԧW tW{᳇X%A;;9_X9촽d/ H1ɩ'-&?R6^=d0ʅB[֪+pt˓ ģ% YI_#%JBh᝙ql<.JfMlK&# E]f˯`Gp/V6. QÙoot5j(&ȵ,`EHy,P#[\qroO0b62Y!K= pbSNh $p@\oRAUKm1TCBtTXbC.Zfe2 Q44@MPXQ2I"dkoXxm[KzVw'\u՜9?x5Njx>be:=;u4 #u(\:v,XXN;L뼛Yn,i%NFN* 9,d鳗c uFϏcIwwkVu۳Y?@U?.uF!1J1qL_IskFsvonOR!bL ؋S~ JUgyȨ ͆Si&Ep 20?:D x\Rp0D9TFLu[K,Ӻ'.a JBU"CLI.,, 9Gg}k8)RUM޽ӟʥn.o$K}M+(Pp"8ar{W_-.vamw{7 YU6ߺuA3J֍}w-.0B8QE Exv/C7N$CcO~ݝ(|.Zl` ,d7v4@)YݒVeg4>:mwz}@E,nv lej…z*=U.@B狲Xd-d b5!UKpg'41lO"'.4%/Ȝk[̬-y,;qǏ1wr\:P `k˗%AsK15f[jհ,b^m>9 2 KSk1.8*zmg=Zo]]_O׭y0ʵB~my!_ nܕߎݖTM c'a}Z]\wwH{AF*QE5 ~()5j:dE݌Q]Č"p^*Y OvLsb胜&U˦%5 &v_gA4>rA=|E8҉'s<!hswOePRF88ۨ+ȐQ=&M4`ɒp!bJxOo$s6l)Qat&|ulCp4.c?\@3 /dg{pHwch V(]{|闍[\k̔+E#%N- /p5NGNzzzqb4BlvY.(W_޸qJKq ٮg hN:Æ!Q,Fv7,ˋGHeBwY{i;33w|rg_Atw+Bb {! :jh+B069등zqimˀNN>3ӂd *6a9+*Z貙"ep"7"(AXf~,or! h'p_LeY@Q KZkv7&0 VEyݝW\Hk1&{4Q6eUB]WJ'?/;+7o>(*TS6/>wkEAN9RGoC0*~ѫ .h:&ľq H(>)yz)acu.˂&FiAuڀDUѩ\$ iê.) _;ϸt(bJ!&/xƾQ]&`D%!K ބbVױ,X7pص9NrYP4YMy@CU ;}z4|͗KkX`w~vvrضøc;@ΏO JntR\m-B=Ȗk#hT*ťq ޽Lޤ?9;lUZ\9ZNa};pz0|--fnpv:p[nw{zU,DMHgq2K؝ C\k 9ߛ\3%fZ!|2G'GBozӅ@&434A]|!w]2p)pqB.Muh*͡e:_l<@J *^lL"⢨覢-FQF?|?9[^YoUUBg2~{T-޸tI+Hi2=΃up=?bp<8vW#É,,G'6BѴuy 7y'!D'$!95c! >'VkaᄆWu m UQa=l2칽yRSF3z|hm}c/\Wz "  (y+H-b+Hl*󐈧+ ;4Ij*\w% %Q C\ T8{osI1i-UEXvI9|½'0)$ELBc?8H4D5 )qU%WϾzʥKk/m'7qZ-G>Ǣ(Aޒ'z\DR5" NO(mBטw>m֋8+ l$ B5nC 9j"C DUy-S~y|[\F A11eq)pVWhcp!<:RF8ې%`U,ie o##[$BkB"4H ~N dP2CЧ5YԞ,_غuIߥZ 8] GYAĸE\_6GǁgE/icE?W<::|އzM~Ǐ (l|g^֚ 4&A&apіyFF 9:B|y8ڤ"0y*Z'`d{׮܂Y㭝ݓ+W6"811m&|h$82lْR8ar'@[q 𹻷/.HB A(!LuQq&#)0L5pS^37v;aTBƬy}W# }=F&Xv1B8 #DMԒp'\ ep+U=[pIETQcX!&cgˌR!< &l[iA*fH{V~=??MFgLU'u|EbOYDJJ|S>Mȍ 3M͢Óe/,F XUuDW)n0y2%oX]EQGXBϏ: q!1ͧeaMGK(MD +X; U]7ț8p℩ Y,<ת#Gd}cKeT!DAx``OWeY]SqуXx}}µk6ђ*rg &I?B EtN}pB DukN"HB6 2ζjݸu`(]j?އg,FVx+ò&12hL'1/DLdM4Iz_ۺ{;)6Os,o%I"|?j5 7~tsRKXk0&aa0O\EE'S")g3wtG&`$/. izei>tT#Dq)l\y3g2 <%`:4IA ͻPgDFE7zGWRIZ:kgO8@pcCj4U5T=l2=qFE f"wktÝ4g.^ruw=; FjM &bTe?c b͠I3D8UNFE Q:zAQɔl~R!`2s(A;Wr<'S ]=BL;][O&=??eS1mz1p @t^%g, ,w$0w-rN18-D#t a䐝kF@LeI,9$ E,?BzF`l>aUp/{g'eE,TV; ? {k3p4hfA/kf^,7^܉ hE!IG}Y-ybl/PH|KRA{<rk2UTØ]wq婢E},ڎ-e^-T@7~a':, CNgM΋޻;5zj@ƣǿ G|ǿNNg \ZU$$'gۯ=kŕJ؜{ڣ|'{TI!G,$|=טgi:)Q(`3Xy3j4QN`*0aקZ|V^.NmH~5$eNm j8#DXD4UF H z}lʫ]6 @ I*l~ʉcA;^2 3qB4I"H Jt ~`)I7s+&\PK"ᣄd-PD@:L#^ G# n#\(V*rp4=.a2DR<9 @>8~]xk/Vu?{2rYÐCN94uW `&, @LBk|GQ\Xx@*q/ hd@i/̫<[&hrdTɅS%"c >j܊{v^'ej6֠c[vQ!?Dחi{VxUsضQѹHգ32vO4w @!2'v,H,bː`2Yk rOJK:h}RnndA cgLT bT  '/0@BV" UTW_i袦_qDppn4MMK]2dͽYKu{q~9<8]Z[_!!Ydd@{oݼ7v'7'xt|?a躁 c>CKի细t;޻{/?'j&r>CVuԵswNkQpo+߅*8pT87!+Q,!JbbXp vv5إ(iv%)S3X#cYʈ)4IghCF1{2DɨG~ ן3 (qtg6Lh~Mk8Íj (poGUOY(B϶=7|!+r OXU#F*L6u" G=R{FUZp̈́ 'ѵ Iei p1NBRC7$ p[MH|WR82<̒TʊBz޸? zAuYG2h?{󙥵Wn]z57~c'H_ ihȠ@] _JyC}nB_ e(ATP s9 Y1FBBF,ZϋPZE3s@u X 4_?OOuReQ P%++_xjO%LXQ,CB3W@Ƃ! { 6qbyq @ 'ߝdHL(F>?Tʪ&=!5r@ Rp*Zقhs[| ,֪߭ou Tt| #pf ,BT$S5굆c{Q:`M}5?OQv3F\ 1Q͝N΋j1s+$7/dIZj~ox㓽,y.'|ŵ[wzz8 e8h$04/8jdǖ5ڨ ^s}Z_^rx81͆/u^_P`Ck PIcblkZG6Gbjహ@7xgiK2?`xa}ajC\DA rntω؉Q 3բA`Ȟ⣓7R+d|t5jȠ-hV=O|l(2í/^q D^*,M`Ie eC |Ox'9OLm;gr K뼔юm; =eX@i$l\~L( aqae,b#`,\„N$~unqlhg :hƍhˆI<6 ڈJk4p\ʖ$Z@ES<Ƒ;l$z>t㡾~6*ΥVEM@~˱\8#dI7r=iM} 'j?.W9z3 ./piϕlN}Z$lXZ\FbsH) z.DqIZB!0hbVLv6oo>?|ƕB2܀( ߗ%J&sKGa1c(md]5Q.\0 (gGrj /ɨjNQE;>wk)BּyWje)#T b %w&pHƛ蝈8p睗;É'WW|@I\x?>:9HDҕfa.Fs~cxN!zhbWѴ㣣ów3 %1m𧇻'C8<| KR^uz oݹߗ [=)d1}inVmM&Yt=B6+#jH6FOHG e(ӎIpehWt,d%TP3{b*GFb^eЉSO-˷oMyKkyMMe}kO*A"B-UF62EO>F=+d3.B(T`cUd31I*&hO{܀«Haw]VP%Π'VVLϞ?_,^r;7&`\mr]Nk8j2W>ޘ~u,)Ԫ(gD AĶIS˞b A"<"`}pꚱ^t2F:eH]oїPv5ք}i\Y˭ZE^&/ҹwB<;P9~X^0VXN+*I)-\!c M`8^Q۟.,.kuםO0ǁ(\ wow_W8r M-eMS48jd@(Sg# U2 ÒT8] `6poy XKP?p.nѩ"mlJ)/nqY+4ֳV} 2^$Y\+c+)DՙfM7G_ζi~貒YoO{Ç#s -(!dK!mGŶ3[dV[_}/lQVa8:^X%|T3i.8+ir.BgI xw8,0{>8?9cz":ڈg^ߺ{6 FYBFccjpUVԍ^?ywۉY7*Ibp02Ebօ΋UYA0q2Rv/̴P-`=9ri! 8uQKY燇H a FSNy~)KTacፍ޸SV06/8mGJf&Ȕ.qHx8@ywl>ω? _Om_t%iBRo-E*~-Z!n~:ibR.eOl +3l4C-P>`Nz u 7b&d8l( A'`fں˕\4wq<jͭ.nlņm' X|TQ ڨ]c,<Š$Gv_E__yH,GJk:#w*;?KpIμu!AL  뱹K|0$H<,ckIQtG[[ZKJe3y{p 흜<q29?>yɅK7 RvƗLdZwFhx}pSs3;d)0 ~#ߺ~c@FuzH(nˮ5Ko>/G'Y4>99 1tܩ@z1 Πsa?''}g8vQOOAOCs&|Yc!ZBmd 9\a/3ro[!J\;G/xpx ǁә8YIߛ=\&>q Mشr5G"4_3cDGzeK1',pwWtET`1z,@%<c_ A^)h4V' DŽK~A,(JG8}}ťʅK+ZApa}1t^m(Q_r0ǠiM`HymS;T\[ۇ^? .ܠßٻwY?:Q^R0'{7Gg WY Xi( :6ܩJ>;9=>zzuUUU|Y*+J ى^Tkh^o4F8P% ٣xљngffs > XhiI#pii֪F]4 |Kr.SȼMFVD3]/M^@!BJl g |h s׶v>9.18ao{dfRQ3zBCQIxm?A5|#X-'nyG+`DaPT />^|fw޻xQ"R9Js;߃L,Upl8|0Q$HQg#?%~2h&QY,_@[X|qW ɨXP~ X|tsk{hF!#\C8EJX? |a(Az>{Y&ۛݫ7ߢ&A,%WTx%W:Douz@ cwpUxJ) rTw_Fhaq^QWKKpWI>?>*N+X$pC[YZŅ:s.aqsd&xa*_~dBߥjmN\I.Y!#/#슢?5!U(-+kqM9kq96{:JpgO"iDE |g§ )tӓSH4ed[qsa1(Ɔy#&KM]i2̫n|~*.Lg7 w0_W_< ρ@ QK葠Uwυ7Zt>G]üL>PLT7gy'Ln˽ml6u|Yֱ{xɿ'|S#D&aR켢P;@bY,TTnǁm?!Sx1eS [_|~v@P4ڬK #3vUؼKG~dgns28os`㌟ureYP 4fE`l |a twJkq}՞x{g,RC%Dz Pd3+.qD>ȏ|[A<6_pv #6DkDd-E Rg׸BՑKt4}Kehx7њ6}ؓFezLLxLHeAFt\2o\q rl'`|Dݛ"(ܠO}_mJ{$KϫU8D%lͶ4M0T,(_N& uY5C+֚3p #&5]4-F WM]5 >7O_oW)՛oc1IQi6gǁxI2pCO"A8r.f+nk:dVhʼ\i%N>R lx'Jj6'}쵤bhZ 5/r{p><|Q>ï’3M<ʰ,@ ޹{2/+-˹<(8Ò m{cyWY2eҼrV&ס |DEY\A`Y!R/C] <wNtOST97;x ze_ d0 5Q<=:;lV_g{CJ'ՆpgBƸ(N.sgT<$0{O+sy 7~jJОqhCX ]knLk +p'\rz%61f窑a WK365fr7y_Dbc7}eg.9&WI'"nU}Rq%ҁ@}U];!솉JRQFК􎌂\ 70r9UZrL,J8E;~˃qݥּmшV$*Sc5MT3)zϳg94_=YgW'ǂ˸ěE@h5j^Vz//j5Q'k. O(gʥ(okp\\XYttztzrx9X)Q1Fp}99: }.>R &|1~U@ r_9BTS[4AȒahEu ?a @-gB$Ih=>ܻqT<{,>ĆWuN$d7A) -i8#'ĹuNQnvg}HobHY H?ݝL [vZi5tarWުofjJS|Mk2đcF[nAmF-hyn0\-p@5CpIp6-hi-'ٙx;|K^'r ǧxܸ uIƌLڸpq;23 ?I)͸Y"-1I mO0 UUTT"s)N*a$wD=23vqyNq23 'WGǽNǚpuQ])Ǻ~&8M Zӵ ,OD;@eVS6fsFYhk@t :P WTf(Z]w&vrV&H)&Qaz'a?,փ1`x { wvmtOwD@,Vu'';Eil$U7>|c%pO曛כW_|JFV8Ε|RL\gn2n=~!PZ02MrAOxR 9h6皝u,.2ЙnJ=;B$j> ˲\%9 3TkN5zsNZt TJ..[F9Le5PNt?w g?bgxvS2ًKJ!OvOOS,֞[|sKknjXJ1h1@(gC~Pfդsj]][Z].uul۫FgNumga~l~8*j3oyium^//[ǃA4іc@ 9:Ncm=~F'ۢڭkб|lw0-bݧc EuָPqwtr?2 mZn!YR,Dg44$*c*@I\Bթy @LSɇAjNbW_2%n)0).=7nI Q3Y5LZ :8ȡ6ml\.. &g3)p) D)~j( ‹ gc|uTHO pyIʌl}c5/EgYYe_ÝGۏvW)cC$Eiw"s,n޸eB^3R5hzi2eNR!TU$+MEVQѰ)A,lܠV9.Jj>! InFGhc!{4"j(IөKtYrTf!| ͸&ȸ}%`L- (Z ;zT]ПqT ۵*0r?KgygZRp~T|;98 eۍf'C!EQ9DF9 r RpaZ85ݾGn[QFr,f{wgQP: +sk [^mm4ޚ#v# G.hK0)^)uMAV͌Se<&kۦk[50: _Am`>"㫌 *+"Όdʐ7m ][] [,1L$)<7MjY![\ADQrmP K-`'(:J noާ͟2 fF#9dKƦKJ9ƩEoi\GŃZ@FNє02whDqG.]Kz@ gDKbY w=L$;Bew51喙%^ƍY˟T̴vfnC [ D b0(4ǠtjAE4K 8||m[w__Z^ 0Ht 9{bUӔN Tmz{q~N埼Ka-g1BL?۝(zidtqbC[vL㭳m"ZyOB /4aOn'mvAEj!!cOb ;]^7itͲuBN^±ȟ2IXJEiV)ᅔ:%tA8Kbt>0 <$n2TKrZ+a Ӕ\&HֲB+O+4ja8)W,^B/>IԮa1jY/4{':ĆZZ~zC۹t*U,nOիoy21ӵ7Z͆_aZ,l>< ST_tb?0m20t.v)DJf FϨXU97lJ1ZC sÞL(*L*&`+--IT+>y_Q^,##Duþ#Qh䱂DE_J YM0Lqݝ *ZLӰq4KQK(#L%QǫZtX> CU D.NjAj%Ly wŊE3lEX Id*Cu#(Y9Yja!()pFt: xp4i3l3- MPJOv8>z66yF-JBLæZVG~v.oz~u {tyqjZQ?8Gi61,i]MPIE0_mMf"IhxhxzNuWBn<É4_WQF]QJ4~AbFe+`)MK(e`2WT&mh`B п$I:My[.v<eX5OC8s"qUp&f^>d~L@?MI`h4[}dl׳)Ãw_Q^!l2CfMeL",dlFB x<YFnZյN#`pMi45PEA%** ٔFu2JYȘr?&{d,1.kJM8 BGeQ?HtT*G(PA[4=;_X=z $RJǓ'Oݼu^R"]CJ q nWo\ƟFl?y=)Ӟ^SLͥP$PM,%%*eq=_m.xuL`!y{ A(BqMJJ0KBYد< ,Q; ?%#)6ISk|gr]XD/AGA iLF`q6ߕ]iw2?wmg:ҡ<ID}VMeLjNgd 10Q̬d.ƐYJdIV&+`JQ*M 33(2()l65Kd+fMΚbFi0fUAgZ ]R&G_qwl޿[ lbtji1<ƃuyN n鳧GG?OÁtgVs],$#O;6,Bzyd﷿+]l]^V4֣Ѡdrݟ JVKuj!df,VeIx<,1{P= 0%yvUSàDcXFQ IO /xT]˫B x"(C0W瀘҈aP cV{smzNr*6MYÑGӖ,//fp:'Swejnx9AX&h!x`L*TM(BUjĊ%!Wt%`&wj^믾<>:?V9iϷsmZM RhJ!rM/wv^yetdOONN(!7xo}?r\/M"EB)OxiۚMQeb h2ǁₜd2"apI]1/ 0}pPJvC6-ʄt @cE=S/XMl?-,[^Y,pok7EZ/v%t5kaKs0ЋIڂWS8N >rL2@%W 7UbY 2'deޤ?gPRUr_狘ji b1|*tdM10/]u]NY]o4,"&TERde##a(B&^JNge.@Me=> mONבG5q'Ƌ*WίPǃ[a,cdN rD>9mvHx.@z;6ȥ-@gY^%q\TMVz" TٗɪDL=-M,ƃiBh< buӲ΀~"@iNtҋ?:LN+Vٙ?S, RȤ':UI/w@p1%fŰmy9T"SsRL :]S۠`QceՠKvbt5\apm>8æ8͢ -ē?FY'JSHvcF0&d^!j xٮC}W^^{ۮշvL&>2s"(ID!f2F3G&SOvP7Ҵ発y r ggKwzMJp6MP^ҷP +-+eu6!+Fs}VA=Ő +.=(E(eh"PnB AVo _ {)/gZ/yzx7?YY[?l}훯zWϢ|w;ou?"BQH1%:&;Ij`^L}`?:9zu78Oz=)NFO Q|<&;V! ZVږ!.gxpEH2&0tI L*@@.>(1ȍNIue<ˤ,jf{?4ܺjGEgc g qITOWHP;-2/Ly#$ǣfO?,P蝝{Fkl<(H)p))a.H*hl1&tƦrkV\q}qmuayqaRUdg(@ G+3vhcsr5̱7b"N%Zq`'0Ϯ\/?⋯V+yY7_kZihRxݣCwt4CkrXSBWRp5(AU$^Xpk(% 0<nYؓĤmX`m2\2S`ٸVD뻷Ͼ_Lhӽ# q0:-k/ D4Wµ>|2iܒ<#';d6M.Ob:FFR- CY2T At:wZ^_[ZY5v(rCBCZ4. _V|DǏg/+9\cև+]\Q7J}N[UD֐!ǀᤎe۪g dz_{r p„|y޳2E <䄕7U? (Vs _`~{+^ԛnNxشnv~`DD`ə̢FN5YO (44^Q2CNِDPU`9@{ L`UT ʭ )qvl@\D܏3 u1,#CyZ-LaǘPTd%4L+|2R&G0bbjG΋hqL%sfAY\XoUfv7.6N)gӣAԍ"*Σ% XHpjo䝫n {2Կwq6M70 `D{ ' DžG ȀBG>5`y@H%L<@j=".F]悂J2N;9ԒCeAX>}PC&h)7(ǟ~o2r$gUw$H92K\M1,-MbldkY`'gڈIiۺ%i)(5-qfX- Y0G3zOq5# f,ŀjL"}h zGWfnvꍥF ~w]a]B_Ƚ OthAɆWIkb+u<"b)[nҁM(`>m N [CX-4c EOi;Rnf5H)QRF5n-_}0''ݵrZsʻۭյ+;OS=gYWonx7{av4ۦ]"ZAjԛMz|2X~S􈖗PWϋ$/NwtE3M\"Wiӷ'_E0Y3sݗ\+6%zbKeWUh 0edu /?f??<)TD"1H/ Lb^7CV*%c5t:rwgok4׼,񂐲e%5L߽CR,9Hnnod/V.jƀUDUbNL14 åg6̐l d8pp.VCYC/$SlX #Hzĉ$T * ,h},(y/9|ˉ\$YȂ_V+Ǖ hL@r뿈ls[ij7HA`kylw Ӄk\%ckXŅf(Xw`ːt[aiƜV(39hZ&S2~v{Jj*/0u$>2Ϯ֋*iD*Sp̶P' IVw08nOs[^tIc-0D<.3:PBg߽}e}״i8.,Ƴy2&AW1~8?QJujP?,VOF 1:E \kyU|=JF16N+3aQ˒ƴ7tT{N/ f2LVw,b?K6ܛo";\pvJՕ&-~b??^kb@TEqz1mnGFA,Ķ=t6l= &[% $e]5xgS'3[,B!| /_1$߆9kΠU%845#n?_ +ԗU'jC˕B AT߲RPX *p"N/&C PB,S2%4:F804C(!yt|''wrzWmluEgZ)R 8^ bly^,b&E 3x^.\C JƱT!" (ߌrf S XVEmi62+(%¤0ܘ'1$Pfp|[23yxA쮪N7-/7W_D&=|h.fSYs9{r\#&?Aw>,[`F\BlyS^ItUTMNIL'נ}IE C #R4wwoj4}Jy9+FyLr#Eމu,ޗ$|Cj5T e׊Y\PN+F'05ZOv_xncee)$Wg1ژ:V$#vWL{ ȎcSJ2Q;m56\:&0I,E)]J?``p\/ULpBRa}>~Wd"B33GF)tmG" ;)fitjܤYuN_ZB>WR"31)el`6[ ;kVUF{O=ӶƑvoݽgZN^{ESH#J3=!C2Յan C\Z'lnߜc8 ۣA>z<9UHuR ?ZB( ,ɆRJ:ta0&HXl":2K$h q.z9g$_V*P}r Ōxaq,djՒ#IٮwڕO=xk֡CnХ*΋(Rah f PB/Z'y3 A`d2%" :k=Y1 9 ָϏvvw76/.-:](J,Ό3Y*FYsa2ӼsΧ??j 2O_ݩ/7[)/k달,WfzãïZUGmwyM WhҨUF4VsI8Q8 @>?xO_o8dR<-Mf68NN{{wd9޸9}(1q> D(45TZg?tb(t=pD7cL23½ FKד85duq߭3Ƴ(ذ$m|Vko,p|*x0|((_s%)I{G( % S,H)HW,6+O?}OmAG${Aa⤳ͥ<ͥi9c%sZѧg*# f^f*t霊(g%R|1 tpe|j|1h\1ߙ~J U& \}%(\m{F樑9TlJK`w4#2FIfhA6ݸPQíBCCeEI˜ʑ ֠tOdCJUe%u:ѓ:n|VV&[[d~ ֓~8Ov/Ϳj@gfp UǣއgeoRD}2S2uhPԂt il}rt^{utrI:"yL,hmUC`̘-d8sʔkkW@S'S\k``>tp^iԯZwqN(w?^~Z}S`{俼z}G68̱<$ 4eټ9Çox\+\#0aAIv]pI*t4P{"x彖?D  `}u iƃiԂ@F/~wmm.,.j5aJZc>pw,(1.BC6I4=yMhk_}+/YpkqR);N^ʽ{5^"'ؒL*u1dzV?`aM맊ڦ)TJ +95T$S2$'QG_L;}J8nhh@aH:Y'{,5:bZ5Mndlݝ_Tz`K^UDFzG?>b8;0srAAQe\@MܛaP&AnU>kZ\0̉ei`0hVX*H?뛛MӢ3ɇdSLOw疮lyY Q΍X]>9{(v0,`a8l.H:?{>zo*o...@0E-DqL.mr{_e.!OZY2ġd` Om#I(`d3EƎkhh8==utѨ5rL2oGZeb![1s܅brzֳ'{GIṼiv5s+ksfKG@bDÇdIJ+׬to"..vv>;>\^X4 #á][_LSCWH .Sީ(Ó{W%Ee kr]|T d!8Ռh-:iV篴3Wc5Mnbj8LttjK&MGI09^y^9c/y:``f O B ]7еO()}s%Kct$ :U肪`.8(d(ccu II "*#/:QI&tA}pv 7Lؘbۚ%1\8ȓ 62wmo\G(|˶Ɠp:2l[/8fYyw@ܔ ˲h ڵp4#~YwNVSu|rtԜsMMw=x` O_P-/)*UIE%Q|defˊfwHF'[ʧ&9˩7Pp6.ΎS/[r:;?zLX%Y@0fTo$raX0 [ c',2L$# C_'禛t<}E6-A%O=lze )n-L4 #Jq$aTi.9E9=@V2G(RRөy_WYRsTN\ίBJK1rn-5pઋ$8əWk7Q0Wu )MO)`80:X*#UWzLuZ讐aZQRD_OW㰔pGj4U 4HfuTFiRׄ%$g 9OqqƶVQ)ZX"> 6ydk3ʹ֓YڣW4%cR8 J٣ٌb +l"r4뭦J]uC4MC~v$JE)7uk0-0*ԕY*6T J<zE+i:2I9/v,8Nm86F]ϛΆ/\?•+d˾Ҽ,]q? ,-vܿ瘵>}cZPJP*Zud0F+NZ iz#TNs|/>=߲\7.rQ#JJ#(g{Gߺ}K/ƔkJ|PFV_?>|p'iҙxpm7^iwJݝ AqrLL = 2J ǂs6sp2?z__~;K"J E-Nj#G.\|zPjF༗Cr\*K2p\TIY1θ UkupT;OAs -xLOSFn!pV kH:,E!)Hd3PE~t]8ywA)gR"ɒsH*j@|iro3C%/vQJHP42*LKs;9OzP?658n : ۡ3(3x)ȬĬq/?ԍyfh\5 {p\\d"SgYVfq) >7d JݹsgrQtU1zO0O,aM)H!Ga葩Sg6]F=F7q@{Mgn] ALHct&'[׺-DqRs ڢ he (wIDc]0 .<v+?ݹmM;^ZN Xül1);-?5hۮ&EIR@am̵Zt^6Yb(ؼVڲZrG.qtc:s> 15KY\6*bz!#MO YQ\ej( 1n}U21>y cZK=הyꫯئE?,zsm}}~~|Fѧ[s YMȏ2 7kd|ί_X^h8OWO/89:<׻u녱?cV p! (m|bww䬃ڙ_oNf.,.ebQ&GY (b€=ʥ< w"^%(UA(K0G-Vӏ޼w? <"fS꣚*(@bvӝ&[>qlko]:pMV.A2A`VleuL~ 1Rx,|)lv~hA*WLYS%*0r@\5}WAḥyhB"IoCd:,?fS B*ߠ`O QKy'2,Nc4HY> x{ːPa=4LE bJ+,ǃDkbƚg 0@ L Y3tu!I^y]*Hd<04<><&Y$*-q ceKA.͒rFf+.gq1 "]Y7]TJ4WweK pNUh&3miSpkrc|pn,+*WբM9(PS\D?t (_!4[- ͲLK38-$ u纷y–r&4o1+v yQ)>i-Oc!M_ϟ<94|zx|Fٗ纵Z#XQ Baᗲ^yk!m"* a;j@ru=7J(_;d"O#_bK:1 'ij찼, 9bft> @d`X9岔Wϫ孺P :UBǨe負gp .UZeϺ)8) sBV +(!o5$?;>,ywzz~tp&co?{tok0JŨ5V:qBndQSr)g^ʏ-6~NFvn)rٍG7o4Y=y[ NNtۮ5PNm1'UȨ8Gx[K9=x4fnaY6u^.z}O_ܼ^mL Fݪ(GCu=w@p8ݚss23r:hňR _6oYq|l}}9E[+ Pؙ$mS(ĭ)ƅd+a,\ >NSLK4a$wSrZ f+51x˜%6/P-udsf8*)JjUe\n=_Pb3$D@cn? R LrL5T*&Z)ݤ8#'JiƑǐc) TN"2'[;˓<'gn뫺^r9*Já̲r.&Q6gA :C)3ݞ0HT2P%gAt+Q>r"3qT! |vRX 'Na"ikA{H.\GGxm%蒢Mҿ)c%)+:+T1IZZ~ᇳҠ~5:Hڄ5u"1hZ8\|\B?fyPٝȍY9^!a?`'Xʪ,V{--UK]M#A_!=JDMU54 5Leje2[$NOf/@f+0T'S٣ՍՅ9rQ &Ni|w~NzĦy%1c7nnjaBS2!2-85'K{ZCfzf6,?DgĆ(|\_s~7)CD7ʽtCѕ;Xwhu( Boۦ _2,KJԢ^V**կt:xia{ѣSi^~\i?FŢ(s%$rvL x\h0QǣѠ7!Q7(SVDg܄%V@0dOXYQ <$7#qMLdz^w. )PsY^nP+o m!z>h@ ?<{+_}zr$ʜG0ȉKO\_b40+VKgE|7iIS1н4 ׮j,gT)hZ_~3,R-uap@UM#aG'a.nGdpq / P ܧ/}۬i7iVIJ?s& h>]Z^nZ#/4?j,~ٷ˵_[U\J "ؔ ~aJdG|u_SYm?c#ێoUBtt/v߱ i.Q ,s8t*Z#($`[nHJ3Pi@Op$r?/x7FLQ.+pԞ" -peGKXQRʹ<0fdnA=0\Oi8@6N`Ofմ4eP: s _W./-!Ph*ث8ZcY1lٖCv%RМ {v(:KϥN%͌?bnZ^o8&Hu?g-јV0gEVml=y,;e 2 `A ,) $נ?1A(Y0C &RyJϾ<+ nޥ8> _YVN&hȂ $sZiŇj|jezuRlŞcVʩ. $j@/$) *7+Q,n-%O":˱L2T4:N{çбy -sF V*!ӗd lx&c#`}F,% O!nG!8wSlb1Eq&A43ؾuG>E1_"0d ~@|yΌ&x(@_Һj_׹CHSLB,{; MMap}/ѠAݶ{w?5Nhu^2ZF]wjj8?oHj w@z.Gpt{nKPKipnPIWKIhv83<5PxK/S7W >G732rJԴM{{,`E(Сo?7~{86G83Qbcˡh6=$2zo]\??X|2:qGd'?Q!*{sDųZn8Qp&3I^THމtu2:aBE~Bcwo)N|0 ,BG%qZp"ia!x[!3j>eM=F29:8><\K̝7lW7PVIɪZU*T="fdI{d&𮓊" hTpxzL>|?0ru]2?X=ܒSURIb 5z$B֝%Tjߢ)ewc 0 ohʊ[A 4eĐ8/قJNǙR" ^{W^#F_}> ם^`ל?ßg~㍷(@҄)rc{l X؈JB_@Cbl**Gt dV\#(ff\֤ܲcl)=Q02 H׾~T(Yސ bL%RŘ{ڠ 4Aks4ǢϞ#Iiɐc4t  4i|KfX|W9m UKQo{_ z^+Y5>8eJ#E?D> R9Nb7 +C%yR]rTtuUT2xl2$hQ 4 pM5l yxvay'OpjϱcXAwt}-Ϋ~2kUw(OcJ*_'L-:vàSun"I֣ p rK֪t"]:EȬ?Q j417@.O\ X:Eև`4ZS$%U-ۭ5z8q_NMO]8{j*Tld9Ba4gj )&#z=YڋQ8]qEg%h>׉Ma !2[Gʳg(bpy@+iVo@Ѭ._)?S"/&DI]Y-&ME^%*Y^g?LIT:Ft1ECKUJ('OAb_nϵnlܧg)]^zazuӍ%,{s=x|O>yת-!3hxBDDɹL 6j%[cs[|Ae<&GkTwo!OxpS, C(MZ]Y*Kc ^Zn{Fәj/vR ~Ԝr+N<&x]\tYz;,% ƔuSbd懽W«Wi7F޸sq VxjpRI<#@)5 %ݸz//xK/ҧ)1?cJ VR#P!~Nti#nX4LzOdۄ5@3sfkf֭|o2^䉕RBCaJiqy{|cQzKrkjn4O?t‹/]vhoԚ$B5s$]<)DA" X:s!ExKXb7WR""h{7 %ý?3-\KWz)I%ea9rlfw?ȳ{GUN X44osTPQ?xν9(ÒĦ2sL,IpuVvԕ(qhh}VټyW8(7Vϡ ơߦ5/w~;5SuA|? zYIQ䏽 8F1, 8T+ΏO\U8+a(lRã"*DU\?x;z\!A]r.?Z)[!.ό, x/L;s1yqg/P"ssZAI<\T@ 4JICa%=ȂK{?"npD Sj Nb@_B)o1w#Ca_wW.\HWL'QLt#J/jZtsUo jjL 趭;hPpj ALߣ~ 3?裿~RVOH9s\o0P5űMÔϜY$Dh֩x"aVM Zqs LK[TPۯ՛Z_Ro ˢoL[$iDH(MphD֦"%hTJ_±* gε7nEbai(D$d!s )0LD45f޽sKPkFR1փ7!)'l}kFRE)m*)>Cs#YgM"2>om&kA![w炑vl*FRpo8az5 ɸst8TeP R XתZfv<9 ^j_W^(hb(jYm:J^7=7?VlݵzQg=Ɣt 9lk8=/2h6=OR,}*)}!? P\t A}碁O$\5aVqz쥇U7up =HJLW76=w>]=wO܅Ev{F# C&ZV\~ 6ԝ_uKFT+zgAɼG/_~Q5,D8##& \ Y_  e܄[9!ŗ'EYkgI. H]л<:,ѓӭʯ+}t,Uqcq2\U[1Hj~Vдt843rF=QA/J* (It,9I'R6!?> E.Ji=$52Hp GtBP.8IC@M7AYi,'Y _- =)W!qՇ۳+kJY2Fړ2Du*ԃ[^/GG;{4ZTZ Ra @AbAg@ \T`oYG?䣿7_~L/D^h L5p_ܺ}sa]^~5pAsjjffn42-StjU֨$x's%Wט !ܨCnf;Fq˯δêpDzBFѷnݺ}ugΝӭMJic&m.U& a]ȏҏEѓt;ۅ) {X? S rhQ}Nqs0wfL ФH-i PYAoZ) qVXJ5mz+elhC1KH9RApP 4c*![h xS" Y›4߽d7T, 45c,ȂIouX9[{A$G./,8~_Aw6-#}wÁx-~˷oX]YyэWO~rt=>}ҩLJ;*`NnP"zJA% rP 4(a5 Q+GV›{ QXU&.w]E3 4H<IcAOGTlmKsh<ٳPJ$$czE ڋ'G<8߾jY82HN5Ӣ:hSBSm"ճkiP9:8h3;>[O]Tܣ0L q\,IB\RY:Tiz&dh$\$Hd$X. TLN6u\S3uE@-Z~toךmp"4{`0Q+ RRc7n^|E4C UeΌ*Y]puem8}{ړ͝4N1~ߺ}[\\/>8wy;+\|Me[S 'K, ǰGݽx[pO'co\JES bOv7BG;aRs2ۈ@.Шotlg8<)~FcL3-  6Dєq+b^|ş* P65YtF5Sɘ0Y R)H4~l4^qqt4:StQ;YCtip"y 0>)ڜ h);̶-WfoU֗WΟ^i5c?}l.z Fnܤ~QښnSY対~Sx]s+9x旗f)c防Q6< Cn]B1tBtT" c 4}.oQx7̟Zҧ [ƵkiQ'HBi ]) 8:)O66=?hF,͍}IsK9HɢuRpp*RT~DfH1I`U}\U fI QNE#N{6<8t;W(?2c ywLOV>? _<!0 x5.SfEB~^X@(q* DA[P U:0R 鸧'[A(Qn(Ϩ&&d1sJPf[-pʫyکp &]6Rq:EW+xrB{qyazfbVy,:*cJv*Od7}5:vVVY NIݤΐN|(f q BDceOXTKm/M_R5[wƔ%Z_Z>::y&̷ygݎ1a Yq t}hV&I~(x"KR6*+bЍl֠`6 7wv~Z|㇏U +LG_\Iws &&X(T k4ٙNcQ7w8ً'?2KQC0^J9Vxl/k F:t3BO F@1Xz\cP1ll3IW]`I\件YתzVYױl~`?` e ;ǽN1Ey() lIZgYAp!Fb.#XfVNYpm88<<^{s zY>`4w *)'2ex]G*T5Q0Ң0b*ǤP9'òR*c O[ EѠViA=v£Y3yЂЂeڔ)<% ]'Pa JobTRRFXQazp_{++Tw;Kէ1VRLjB$/H09O[SťYL/v7?QH*fϡDؔU'ri+ֿRVJ/s }=Ҥ xţ 'l!24ǭFqLJ?Xdc ;Y?ՌY&W';{|R?v,_^^‹DJL9ЭJmӤw{Cw:hQFaDt{u@oVLL2%f~: IElxy@ ]ս~S>3ׂlxbb(< A"Haؠ8aki_.Ag^@ U&2PXhKbHWcQ\C$SXlԱcN{lI219UTSIEyUb]#h^)K sҋ:,ؕҊc)[{IC*ݕ.# 0逺j7lN+Jg,\ً &o5&.b߫dRIR3u~9!LXDQɮ},Aq֪ F(!@([I;IVR[ZZnPFxژ$$ s4,Zȏ?4I5#o8AP~JEK pcnIk M5(%MRI=w|VO}Za.3Yi&aKH$tj؍vw,ӌgt̩T%P&Vq{V>*p,ʎ(CKC"'P OgKUpzoj~ٞa$%?(URDm+\kvύL?q q S&5a:*ts\8@FZiK:u'e҂SOo%o"UDdDNq2IJ9=X{R禙,PdYdi/3)~@?ĊJXKC1:G^tBڨ !ELO"r-(.9UW0|/ $?ܹ{ ͍xHIqE{G{;mtJ"z \9*<^:3Xj\Kߦ:bcB5aMuTI$Vq$߼VDaiav9}Y=Ŋrm 6qQӭ陥eq^B/Ð<.-Yjdx+2&B A۾ޡ(ԨW>zq֨/w 6~pյ  (e;Ѡ֨owi h1Smۄ]fp<)lAdx![w) mfQ flB˯2|pyT , O(`ȤgRCr8khFQ,BM#rY`LM(=G'[k9sq,Iqt ݤ}-ĴF+q:FiG~q>N2B=PdL3::oOØ1È-8҂Ks΁Gʘt¬C[NZ*\lH,!B. 0EiI<ݞiYjVUߋٵSyrGHلgl{cse˫ R*V!c;[ ݚyzannB*+`a*畆CUҢ9P;/"%G)x4x7`z~Fa?zLZ$QGkGZ2rՑ -징r]@kyJGBL҇.`4FGaО]%D`} Zn>7 ۑKnmzfvv}uNJoQUUTU_mRRH̚5mē$y$j%q<}DܞxhTze "(^*˗^QNB%heXU0[k=?GTLNkFtuc6(d˵8˯|m.k/-.CG>=K6e<::z|]tGn<$ M6*V0vv^Y^ T&=/Ms8p!E rZ+)4KfM`^_we9FRjD 6Jt{ulA+WR>Ry:SƓiN5WƷ(ZNͲ(j6^UkMTUQ U5z9p6990 ƕ~yX/8YK/h6tCOS5spd]O򩙚T$y:E? 2,(}gEa]ĜU2g I(iI!tt01) #CA5XU/(#Ư 3 c,#bL@;_ib6a)n \P$b!')P0&62Px,x׾8n[*²E#/6lǮUfgk;8|ߣ؍J?w7.@ǣ=ԙvӷ_ӥ9M)b`!Z.P,-4IZn/Jujna`05|Kgny&C(qХͪ _tN׿>8؝_'@]pd C)9kPoM6PB(ax]9w,k!QbtKV+ozpf}WVk%⩋ժ PJbe1@0i"z{;Tжw޾a5٨&,OSohI$D}>4I#9q޸hKD?\K/%61 Fqa z b%;e!({R1Q+ZuׂϞc$uŭ" RhVYN٣P"Xa61/;1`xw#'qAO.p s!8G_a)~hBu ) >ߎ#>m޿p .5g֦WVGޟٟvN__p ٔ7/dli !; l[I%Wi,jLS";-%ܩL,XKYMݳRl(~;Z( ^?.Լd@X(l4MUNaު4vw׻ް O7Bs3j}|n7՜o4퇝A^)X3O^Y." XiU a[v0Gcnw4HdquG30@SAbS0'Q9|0ft6wIⴐ|r!X߿ ?MہJ:$\R12ONשVB?"RjW*.e_%dgPm pߢ=,| b+kBx+v~WwtW(ny3ʲ, [Q!5gW:ZOQO=JB7j G٦nAٔ\:KYn͡CEӣvo*Yлȴ[JA3 Qx,-Id b7TqJA*=7НM#hDRB&xgn4Bq+8:ݢ$N13Lੂ*AcaU%P:@CkJu JU%󫒙ΔnvhT-RI#NcW(KZ \/2EhI /8@4Nk~}߾`3P9sWOW o_ai?z)OV{B)t|?P+e4 Ufk.rB PsgB!;NLn*SOޤb*d֤-zc!զU6;Fb?n.KhqQXfxNO^8oXJkf?}oymRa&Q݅R=xt3AS%5a)J0Cz{dÒײַ>SN3P-uʢjn^`AQJGB^ˮ}ize]sjhn;2,(tAQ'ャ,M ! -3_ ԏ'6RէXoZ9EVZ/?7~t*Q-$xi@XWP)MhQM$6@CϚ6M)5jIkS;[o$u}{V־tWwu7hl␒Hmx.? _8g/&|aeٞIJ$@,F[u^Yg~yϗՠ s99ݞe;*9Qģ5UB^d)5e’tS */e0TzpOX_pՔJ8lѡXеvYlB-Kt*5xDb8J  Y5Qfœ}0TJg<OSo4kPkQbN* rJP -\ԅ l3M+B_rF^H&Gj4x~Zե,:fu6Mf ?tb&[12YFllv}OZh2l˭fSʁLT[=xt}2l5U !Ɇq)TyQ&ƶ,,К {E gՙ >4Ea JӢz'RѿQk""^Di?v#eʡPmT]Ie h[Tr $t*w@DHb *lQDaor55W~*돳9I5[H^8@<vA1PWWńsZ1 K{^ DŽ[*جU.SekG ~_YՀ5 t*B_|$r _2?4>۟z띷 ,u\lJeW[ So>^z;ӔBc‘HPU$!$+ͯ^ kyA>+]B@l$+ t&ܪhr'NL$Hۭy\_u ?L'@AA繦 TfðEƭ\ICTjnV'MOiSfl?VIz{qu{*Q[d <9؃B?@%eӱ$?CD \q]dtD&f_*mpJ@oŭjͪSi7K&CTX6,:̼('&vqA5läBɄGnbf]U$S-xZ.7L ,̡kF^* d-THe&QrVޤב0e3XPN{{^MB YS};nω7KMo~[kXLsqKf٤ԇpRC9z.w ]=J1\$ͷjMbG$G$-#hJ, B߿Hp*ڲ$L(MZL*dXrjR6GvS$IŴNq_j5{>&a2EvO.+w] |vzt[7v6F3~MR\*pZF5ARD]^ZZLJs##1_2p4?hWt  ܛNƃ~g4Nf%WR؎H헂4*X-.%JkqjLWl:Yw2V m6)RJ_(t&F"RNXHR1y;=֡ެ^m`Q)9\JPz\|$J*p`_F^#G'@H{Sfx1!ٵh@뷎N?@}|wo7C+r⏳8-IG6tյg&YDd-:~%KSMϳ !\O语./_zi{nEìeH0 @VexB _Bo' nTaӃ>tYШbY$y˸nU*TЪPX+eJi|RnlG)p.,i ey XXA:妜Qho+9g_E~if_m0E6W/^)I!!Vp-` TMZ=F):k֑M*vlA?RRe&M!RnLAS&c8]7ɜ;R0LgBڗC FaAwo ]y|W.^ j]q=]YĄ*YvOdڼDGGӱd9ݴ%IH[( (u:/2=*WTA*L”=g S2.vBeU.umÜ"(k\( L+a hgar6t sR0UېgFRU3U霳˹V&n(SZOK &|Zcu[W_zuo8TX$|P&%K}ڵLhЫ!%:fT&Fb.Y?Ze]sJraO=j  MuBCrTUX(+ld^ʔ\F֢.VuŮI p,ݲР28L(sIl<Z\|#*輠t! tYo\Ē暔it8M $*|0Ӵ,5 &Nz''vi 2: `TJq( rLJ0t0)o5hax)w{];<B0!Ơ  a#DqȊ &܎*Mv(a1w2IdHUx .RF T0TepBȈ6@?]LӲ8G4'_35(FFfYV} zt jr4iB7d} 5 "*>Hz5$9uFp(%DzRp jv#dJ&(v< S vnѳgWw Wgp*$<"Zې*Ig{,.,,o\lijxtAY@a`Ӭu&2Vm;Y0vtB<A{K. E}eWw˭T`!=hK.И)yt THi4Oqd4P(Fщ` ^395U(D)Q$ӖVRofZzjD/`ģUW$hyRٶnhPwY=G?rk(nQB?>X[`)baJ',tS*iU"J$E\hu}M0K5:΍4PIfqkәg!Wyܚ2w43!VJPq֊&%1z=vF{aO]'Tŕ`?|k|͓Ã1eZjuY^8$ kV+P:Shiްk`e"Kzr3\dUBPA֗욳s*oX *\>(B 'fr(3BP8n4ֶknͱ 5"$x&٘6&I4fL5ZNzyݻK#4U0LFHtzZݬ5UY7d+K#` uĞz*>88"4"?: ug}}}ai3fcb(,U!h>76:AfFr DˬEJ>{,wL?r ҖpdHlvMSHҒH\ mnN!@Ƶ/-%0cL4K[rR. *3:J{Go[yϦ1<0"} VzFR~/3sZ1ߡ(&z~QHD QS6:%ؗ]tʦKAŜNɴLXpZr4=;>fSw[ICKb:,1 BRY_YuG(Ofolv8zf+ 5LQUwۍ*?8OMBr(")Kb8{iw*n?>oYA_eFQ3_h3,]]z]Sm.E;70A2Bҍ nit/N%i ie]t {eMBM~4~[[۹k^wJmaS0 $@r"E..{>I<~r(=t-}1z7Dxq^^^C0vλ,-w0 Cm@ 0^ҥz5*U1'eVj "GZK[/QZ];vӕEÖ-Nyf([6l^p`ӗdg|>I<~VZ8肍U9ŕ `֣ >~$ @-+x%m= ^G~iQLٟh~,]ʹ)Q?ulwM8WZ~a{eskesiX1ա&B6#)͆ɰOȱѸS:6=qOw_^dO_,{mm6 &fYNV$ypSY2I ,L!p~n QH.~4, cUc.#>E*t8glqs5j`gE#CBuo1*0nC.$Hcw{ ɬ .;7qr99|$VawVCi$ "ƙ,$TCi{qk:k#QY,CO>M$>JcЄ[I!.. )4I `C9f/)fK2c; A4B'tթ#)= W_-4eGֱ& +# DDSNy_ X"QP Awt4d¬*cy3QL\Gkt)=qp؏µ [B0PPP !AՓ{E*tA`6.Z+hϦxW AV+G DY͈h$ jv/I]1I_ jBb {|*\)T3%I$e7Qd9ђ؛

@MݽB0Ygjo]ֻ&VcgC0Ag͠[ʭ,Tئb+$G)8eK"x40֣^#/GCx z6GTU?}L7eiA殙 Vi6:TԤ3SW+c\ks <89:sA|-D {GVry4 tR9T +O`mrT+s R9%䪥 0d2b@U]TaA'iȀgaX6jQ0#c@q욓GeN MOR " ^UH}P\u>|l# C*I r8F)zx. D& hN %.8*hSJl mZHp&3O+/0h/;3x d B ..D5 (rS0*#.xTT L/Lsm P%E^ΔBMz?흝d5 "`qp]s&#[8#bj gϾ$`nOp4Rze饎 dqywܧwڐTE;fTJͰiiC q>wi-āo@Jc%Ę8k1 U(.e x`.mQut,vL΍Jg⥫׮vѣ'Q*vY,l]XjU &Ës@z۠d޿}{|6\Z\Mˣkou=ݣRp4i/.eTmV^??9=~BkYbZ I%JVZw|F Ee,S h-[]t /AʌKՠL7]M*,Ӹ*tPsL A8Kt=΍;JDMkQ5tG Y9OThW=oD,h1Yl(Te.OyIµF( J]+/rۊB~+ew=[oÑ}uhJЀHŹ˘( UD%Ϟ߻ólc/Lht=ݝTZjʣ|x՛SJ# c}뵋/, FUYo_m-,PPi4\FѬTlVjUG+fRv ؓ 6T fATPYSo(ꫂ, cA{{Qot|ot|Jp7ϼq 'hL' 3Oo'VC;6\Ɗ];URy)*TsdqK\Q:{:"9G|N T\1NJx(LTO?ǃYX,WK&yVFhRo44Mc͢M~).]݁Ʃ)Kq@(p/!UmNTA`8 <3 ϹVqۭZmZՊt$muHL323)2Xڤ<%TIe"COiguRO 5%%?Ɏlt2{pLGvj5,0e՟ǣ>Zjd͒(o7`?ғG>7) %qGӃ=MmRؼqլ! ج6V* ;) 4[8`a襣Wa$:Em%RtA#<CqJikRgqu(8f= Orkv7cIg ʚV76-rjZw4zEbs1EV`%Xu_iԔɁC)rʐ7s?Q^ ~EM\.|U,:kI͛w.CC%/]Dj -h|q Gfp1Pe k*F2$s?u {h<+ŭmJ`6xS)L]8 ~PMƑ?" fytwRU/]BƩ3pm2eihmdUwBʴk $}Ș3DZˋZʼn0LP -/UK v](rV)#UUcQ Su_%jK¥EP)_Q1p''e7Ÿ)JƪZhm]Z\XT Cˣ`.Ipv>E1 :؂x\ z2LGחȫr\r hi`R2﵅Εk B̴Y3t6+Y]@) 9F7, LZ<[%~@0{DdF2sb c{8MBHX<E_3^pڄ6LZe1q(ꥳL YfCжhp_ Uw} ;P%]j/`iOMZuxm}C@V*= >;PˀfIYY]^\x*28,WiRTS2EQDZaV+K?0sZt'G7?UNYt*1ߗ; ihNj:;|7:*d.[yC?mxIě (mVm/RS%͞?yr65*poE} ڤժԛzuzң#)$Պ[j5pYȌ*WEUx%)= ן^뭫o%^(zw/<⋻deuƍO5O>;Tgd*vg(}K@~"kdLƓO: zۛ_a/tw|ߺ]9yi^[Qg?,S~AIf$,kִ\5Bt2 i.raVcP裓QRuib@DXh.WQZ-D bzFeۗ%wV4.zPΓWczfpP)+]=$uZ a"YZ^pWVCUtňQd.tZTR)eb8vqd*S1ŠA\2,.LρTi{f>\,VzѕKt?=KEE;ы'n7߆$Z†E)[JجH6tPL,!Oh'IJ{tӵ!k)sO_1 PZ@omuI+|iA;>gշߞLT.,.ЕJY*vΦ{>q v9kȚS5iIi'=88_+/eՆg eQ\<lTve58RIuJubQEYAG`.nXlƎjU\b{#KX 86βwA汍)@p@.\Lѣ[jH4\VC\thPs6X`*%I&=L0.p`F]i膋|" ^"[vʥB_,^ӽ3ЬG~M&Kktzqϲ,ʞ?٦3r8+i:fHTDIۖI-;{ E+Enq:ĮUɗ_~~`Ow Lk4ZNM Zieibd<ytq",ɖ,́Cv>zVj/c'D a; }=2aTJ(L#?ΗRg/_w:m)\ Y4q{dU~׮N,V zbY?Gr{T|J+ gY G)QwHs>-:W+VV/q> %Ssnd,T٬?]q10Cs]ɅY_ e1w OcOb*ʪ3U)S]b6} $d2w䄀.|Pį,X PrS.R dUCXfCP%LF{Ћ]yG/_|qI`8lbaf2/].hbP6 /.L.9c|3D)$t(ub 6쏾xKɼPSeOZ\-bxn8~,7ˆ GqX]d@=p" LTud:YlV](ɦTL.UB E.;x"ڝFs6_qz^h+}]Ӳt+rc~S%P|P Gx4 icTYSGэ9J-)'ȏGxSR;v^ݼ\Y!h[lSC>FVB**eV%Ѩ'GP0lT.`h)9z)%x2VsU#L"  ,Ac>ኆ9LUV^ǁd7}+3m¾TrH`FQ_" x'c6,\/[TPq"4) ckf)28s0<fs(fLw/m5hdF]Yg}my-d6yދg-5G &T*!\I,`jPqƀBE*E3qB9i̛=2E/mokrsY}ՔEV fV͕-x#P|!H@PFdŕW(DqCl/SJ_L 3m)GRT74T443ij Nw_^X^OeZJ{UT\T4ZSC΃JcPG3=I_tˢ5pP粤eXK2-t}{Pl.qrQVe,՘{3-K"(/~Wa_@ovQPsITjG)}i;}_3FFBqHl36aB{Ks9||_R\H޸x*n[G @elQr.L=0MKjq@@ӊҿϰRx_}ծxm/KiЬ֣xt/תoQb&*lyאJ섞p}g?瘞7K[ܡk￯Z +;;+ɨR~oIZao&EpU.`es2ӂs?g^fL襹عh޾Kw4 T_CPLUʫ$)\}he?IɴlFp<잞LF=bgQ@ HpeWQ S|1~(p uTj2V;z}6>鍦y6W$;6T`)M/xwz|rKW,^64@@&ѬdeAxYL%=ʔ][-F!婎 ,U4XSxBR)*hExѪZ,g&,EYMh![^JByS`VnΩq3*$ozp7]bΈF'SU,x$sIjƋ`:vAR|)Y- `9ǩS-N{tعvo4s6lD̠80g{=. % aZ PTĘ8 ܤNY&arNYl:9:ƊF{?7⥝HUCOX44+14!ēOx}`ꨉc֝*Qy{ㆦ*A7`7s'+ do˺6ƊJP 4L ? fݠÃ7 #dEV I1r _ eAS Z/7BIRCd+fOD{Nզ )fP}8E ;3?)GT y7qimĞ\\1 3ɪcy".jX/eԟfbPw*BB`V膮:5juOU?qO;85Hns2ms~r_ÏctœQ ;w+:PF% gU0sm^X CcrR$,.{X<&Kn98ajN7$u)U1AD֗ *2&|UR(ڸG;αXI"ڷ O$FV#/QziČMqB8X$ ]qRW$si g;-jxnT@lA Gp0r+~ќy8#đ%1.W5]bNiab[8eT+PfRiȣ?MgS~;9x*)J 2Z ߗ5V{6Ֆe9/ |WNL FIjVnpV, #ʰԐpwmj-AeCgDqdAK4Ce7#ǩ HMR:3y!#kKx!7Uc0{Zwbi:'RDê4j4#JXj?wgfS'Ӕ+K$H%-Gذ2DSXzun;Is d91O~HUXm/F|ʺCȲIY$;%q4-Ri)r9*WUHʐ̨T|X3L(ǒ刂&EU4%M_۽'߰??/szE޼}%g K$da I1!u $sM{iSfL>UPUzgcm8qDIiz#  @O6RVFˋS -Xe$4YR~|@ʌ7Q!,v\m(+˦7Oӓl0<00& zW?<-D\.CJN)AK77iY]>VնCo05b:]IPl_>d^2&?觏<$14]B+CEʭwޓ0cVV7嶖 B b:$a>.3r2-5AC/IzR'TjƚT_ KDT ĵW=}}o|wob$f!Xe8j{eZoӼ&iMd,AYZ8rzw}YA$) (3ARMmZK&`7Xmxh:% QL q J^=ۺ~sN^SK /Yd+ ;57kiHϾs/޾U_l~/GEygh}=ggk/v`ps"\b5yIM HLC}Xwܡ(<ƈKPaaG*hSJEQeɊm#JiTVmjG;\$ah9T?YH\zq!I3MyZUS"[dO5)%^4kШ>;[ӟw=SO3t? Οx|TUHrhd!EkJuQ-΅pO5j3[7(%T.SeD%+3[X7ԹUh4o/Om捦:YBÜ9 @c&!5N9aLW̞!#*l7XCA(-~N_\;ެٝ땪>z: o:^{NǪV(L̓ @?YH̑dTBWɎJ_]*]6)걙<.e:}.:"zd Z̺ϧ~km%M& (yԗ5Ir]L3R&M(a!Zzp#l?9B/EXr؄ ȄAB:*̛s6]]y4G΄y>%~/h eHeEq-&WӋ{A@EvT2u6 ƺb!]"lPYHҼ/5A,vݶzS`KuT^ :O kԛZ :owomб~TtՊhTܔp1Z%0nҞyত 0aO>ǫOW^ml=RbIo3TĮa]QWйy7Z9”"Xe3!-olCc6fHUC7\?tb>`$w.{Rpf90`CQ-.uJ/Ebe+XNwkQZxW8GY"9(q{ʼԾCMLkjhL~Bq2<@|cY\u(p:T'S`Pnx9bZtRa<"<Ȝ p|8Rd]n0 wC?eL/dI)+m =TI; ;/.Jn,O#XgU/[o[<϶.O"]z_ذ2~<>9{щ8>yٸK}ECO-[N>lyčWw%x)xj7?)kH B1޺m.VKh<ʒ V~aͽQ0L&ST\%nNHG74¬x[hjqޠS4j~Ga w8;Ր_U]<˨zkNyi<~p 9J yax.y;mKPwo"K^ 5olCK|vrNoʫ, *RUzJSsF0ϳ-miqh{L0UxezW^= %pJaiDj\SBj>xzrz;=8ŋ())} n)Lhgw:MUL8(w狫gϟ޻wpyWUcr00iv1 ^uhqozy+ھ FC>h6R]^cԔíUV]]mcǫ)^g>֊*$+Ǔ'˃{t4 ݬ= 'Kk7p'HPc ,[HF)Jwxl2 ;wޞ\Hgɍ# $wDacÒ mC۫bBgۂ<4>,8it4ؔ |,= (uȋܷEe/~OǧO,}})AEnXU {Dh1(lNź74Jl6?}(ش"%kfN3.LX3M]C7′"G[6&:^?_Y8sv[*()ڐqka|nIaIC*f%9 C;ᐨZ'#ֻF O~M}<Iy+ b]7ss^(d~ą՛ENaax޽yu|t>Z ;h0ޡ` O., P[C_[LUt(׸#u @!GLЮbb'i u蒈E>6 k1&Xep˚pׂM~)U|[u]P;]F-@O>gY_>˫U% [S*)8p5UaM>8 /Χ%5t.]Re:_4^ݡ[ڽF2+X3ɰ jdh4A@Ǧ*nie?2՚uEn& ^;용n)=OǓ˳^cIۂ"qYȁF"3;OONXӱСOWz B'K<^Leپ8yNv;u[[̢؛;fv5[}N&hwG(r٬,@YE"]fC6(P0uQa6/Ccofee,hΠO=7 \|ӯ'!td2z 2\ܼmDMB26̾)'~ *~;|Fat';EYa9&o0EB:JAfOM 5wCQxL'mS P{V*UQgqϳ)x mnde«# jP]QԨWSVVPу(OZZB&'2,fRы5/uAjVvGMY vo4:Q s5>_g= NYn8͓um%jJoqby,8 @:])^ƍ?Oa_`F`{U9u>%gF?yN'R yjrKxj^z:uێϯGf:(;v g2OVt1a&-vR<0}1YE[k./&EΦICerDZŠx")#Px!' C~#?/Pӟ/,;<3_ޏ}:Z:"pkZwA/uX^O2{]-4Q:w|,:dY" (S4Te2(è㰞O\>|9M/ώzUU eXN')~.$m b @e׏02-w"5j@)8>̵4,6J@.A4X/3 s"50$YLf*bâGi#E<(Q2RezTFއBaVuY1Ń3ވ?+V"d;T;' =JP2abG#5KSq+#FnKmВLQNhҭU&=) %yLE-cyvfx묤7nnE׏?ߢ@Sm\QQPAG1*RNQtdNZ%JbP*ߤKLu%UP e lFUqذY cXPup=9x>;߻s_'^';7ݧGSƝΰ,̬À\y}*聪k/pmLgQ$ϲw;`nSRKҫz(}2@kj|y5FT[Kw6ЗWkxaߝ65RhQbǙ`13sV{ K #[Wl,~vo om[ṽ[cmkGkO7tb.+5M"I:ne^p0|8>Y.inlQ*=/ zvZ{J,n31 gtKӼO`+;`801t5+&/.lP_B[bSP{ܴ+JgV":2MK IQҥAVc8e`Kw–Ѽ^6 X.N' pTeM:0 $ȍSJV-*bې)o %lQz.į *&AUU^Qy]qrD}^% d5+z+U!ho+hxl(s Jr 6?3@kZ(6` F[Lae O:K`Hn^Y"B b,jJ[t6#P=/JDƄE^;,))P2 ވФ҄7=9֊9S_֧ۨUYb.@NEw%=$e[Чå[YMQm~!XP#*P0K0lPr`a!7k6\,{S!|[_Y;;{k== 6IjeϻT^Uff"kf@ mNgW} Q8M&O/~}QGE*<)SYuF-0v?xӲܿ@CВ@n F*({VMxiV{"Yų)fѝO +EzU4"z2[[Kу S7̲^kVTi};4>xş/vwwqn;r/qv2U>{T"%;IYeNI%j7P+VѼf)$n SaZ%A+jYB~Hd9L9tvqe,bfӥ S|e㧥nS/O7#})-:QKN˸F{߉i+K'HL^U2m:a m(eFo7tn/ڹy򟂇U-f\ i>U ۫LJKuY2lqQMZ$mu`kt~7 l+QKoPm]6hPPPot[x!wUo.]/MvJ" Cy2eGMDְE gnU"0fS ")썎}Ɋ-c9D&αё-N}j3@=YDia~V% Љ-%᳚nfmUkp.a L,Qa=rQtE=/^*"x^U.X:3DR`;'Z΋!PHUH9MsxnǗ?^-ޤ$+rRk,a֡?Ço"jT[?_œO*aa [_2PI )@ېd]#BPLL.g;[.[៶$ .XӬqZ%:ҁn ĶD2sVѳV؈M_-ώG ư S8;0Ϲa-5E%X^eUnC/+Ag?He&ef0[GWlMUס4E*>;}'ɰۡe$ ΖBK>@VI6AZcċԐ6>xZUcAҿf9oƙzVPY!̛iZQ[{M!Ѱ{~^t1btFl, !΄4R TV[*71>mFLxk ݤd2qcćoǁ:0IENDB`fritzing-app-0.9.2b/resources/images/splash/fab_slice5.png000066400000000000000000004346411250202676700235740ustar00rootroot00000000000000PNG  IHDR1LtEXtSoftwareAdobe ImageReadyqe<9CIDATxTg$Ǖ&RgVVei]- 4 -CHk3;w~ݳYΒ!ABCHFZY)C=ᑍ+mU)"<ܟ?=FDiB28bX'k뱦?~5Ŀߐ &G?~8Q:|IQ./"p9/ Kn7P``nTE-ṟ|}-|rw1r;- c8wǔ0x>IxW77|Jc^4lse Ci;?3z 햐"-L\׎U76lQNJw?oBQǺ-n{weSϜ~ 1[3`(qcU40t l4 PH4Lya5˶ZM !"asZog")mVFqdƾa0 -~AшAxh($TpO^X`Mm0f>BG 7m 0p 0 2-KÙ0H Q=Ƭpy cA|X,7H&a]sQ`A__;503Jޠ!iG!c{:]Ev[0V SiPJY=U]6].ņ;E xQaLw?%ek'Zg] ɦL߆KB2hÍ;W|]}IadL>8wo_W޻q-ekZ6(0Z"-QPPߘ0GtH,Rz g'(½2K\%"pY|/$EzG- W#.p$ 2f$t)i4J>:}@OQQ@'N<~֛\Ǿ RdsΞ]8drQ(M]ULSƬv1$ΔW&?xv<#+zRMI \6]ML_vo1۷iC| tJ %igQ"£N&@Gn <^\}@~2 3c[?dC?\a.P 0eI\({eĪ-D= Nv5dH"mH\acAĖ :eGGWVŠ>_#3,DC5a}ߞ\0:<2T, -ww C櫳^Kۖ0P_ Քr$9˒*#&RiBenУԢJlv.;jغϴ}woݙFuP uس^j5@Ar\ĹkWO}oPK}zڱ \0$If\:&)C1@mHF˴Q@#iQ4X+@Eh $Yv5|[XFEś)DDD~ l4?p}3\M } "`y|"M߅/»/|  b AOn9ȓ`˄ L&h9f.֬Ra /ȤeTDAmE&BW9Ռ0d',pJWXjAY_WY|ma+ʁuW}O?+z͵y(Z=YS'X'U'/]k`p(J5-x'4=7描9\{^)-kوa3 @l`iwDJOւTx渾Xy`נJA?nMOHLyDi@&mP*PԔqts2C@paPI4h2!+LIv >n[չ>v~p6?i~[9 ǏJlT& tXv|Qo6_ @A|QP؀+ 23nww~i9NM8jh1qMżR)F:9j#+Eg2yg/z}2,TZh08X6l^3Aa|ӰhJǎ+&jΘ\dR*wlAA(ҿ0dS54'Pt8ʉ&!#6BhqnWM ڐ̱>U uh'Dd 1e[ȃuybC sr3Wo[nѲUY>dcȦ7&;gEՆ)oKD C2aeRvyO7vp{nGQ=v`?x~drf߳sGZ7߸*WjK2KM|k7lukd:~'`)!6 >īx<2r7aAF 11";O 8~ERD?!zӦ߶Lv (ADBh`2h31 N9 T!6wS7h?h5%*;` {LBWD#Y$8v'lx}V0@S?#a)b9f&=AZm6fӯ5ՀytwY-2V}yw:HL]C[,qh\OﱋWđc W̷bfahb%5".?~)_si ھg9櫍ږ6۲dXs;41iH.BS39Iwj{f  M"&tFYw {A໐ ܢC$rIjS1Z8pRHuCfh{#isdv ɾ>!H #e*۽kO>ZsLcmF@oeeRgNS|&P@ŘYʗ\7H~Mf5hGfU+`N6Wh=ΟZK>|)g:!*j*&^,A!pȂ DKWϞ>rYܛIF67?311U*oxO:m.znV" f`pUX#(b$w?YFMDn6 lDaR h)+Z-ƧSA9GT$Id^G -(|6#;p UGџQ6aPB9aZ&*0vlR?v;TT24"zr_?tXI5yh"4 ) jy\0[jE*-v5C;¯uW-d}~zz=;WH9+aS:k MMW/=[̧J,`+ەkW_p|" bH+ʹ|tYi5a@1z(4NfmC5lۦ8!1F4D` ^ C DZMr!B&'?+e е[`\hRÃK'Au} r` MM^1|!ŀ``=MM ġ_ F4g$\~\5;ɚG7ֶABɾ0DKѽPra&vsvzo-U`O`ׄ8Ahif2hi(d& Njj//Gdm鑄tw]^cƙǷo^[tI*_=) "]6l6O>u,^par>7;obKMU@!Ah)$2-RcD50ZK;׬j4j-:/fP#{W~7xyvͺunZ+B-TdeL\jl'hшVs=v[<`E_:վJiJrȡKgO-^s׆˟z[{س̙fjrz^s^oբV#MzN&d칞m[CscRvOW>DQϦYum|Ylt.Swf Z",zy#e ]}FaW |!cʔZ86aBrI8mIH 6AO@!mpu"&!R[4v*}WjtFL3QTHa1 ۴bE{$$9:c\PnHz.LVal  LCϠynkjk50 0 n'Fe1F0CfSizN r)mg0n%^7]#cҹeKWzj=se,QښasE֎m;ӧݷᶯ}Vj,h(xj^`dR+ PIP(jNOz_:hF/ p|F2Ł>v8I)a f wRJݰ gTsL giԤ/B`2>x!={`bbI:(tS#1bN> +/yzG+:Q-]]N~?~7,Yp;}C΃OU!u%C'w$\==bp Ӝo>~pXAx߼o>>sܱK]6?8M7GBWw<$xzs~ߠD0Id+M9Hk&9g\(3B}o8 >n+Z,B8v2f 08Wa3{@`=cԙl3̎Un,lվ6Yɦj3}}KW./}RΝ*Si0 b$2S$7";oj# mڼ߽ˋvݼtw6ENl H_o\!pS kV5(dɰJA/*=FQk*B X7L@ <C?Hl<|޴,Lɀ҄J0 ta;iXuqr0Xaī$8>L}1DPqBMX`\0 VE ft v 'Ii21Fsp-)#DR iтÆ`5oKZgQoԚ0f1^b*4j6sLT.[ڥ'/绊adծ0]Hmm_h`mmݲRrn]>э##ãÆ1]lٶ_|}[f>pj8 b;d6>+$ʈO dM v(yo 9':ga.k˱""1MYh[ o] I 0DWbAĚpc5@`ĻpJOtp! CL D $؝<7nfI&a )ǖ$4vȫjx^KwmG t(fxE^[+v`1jλ`J]]:{δEw_w)ZM H1\x=˗Zi` JeaY}oܻgՒO<ĺ Bk}? &QP!;qNS76Ii&LaIťVFORCuywcL"Y<󥄮wt#5eҔC!Sd̈듺d09qB)K8Eٟ#RbBw\t%( AST&c~/?O>??duo{Ē|w \7;5G-LW!<ƨS (5/Nj ^gR.pҎi~#=2+K]޵+WGivhX﷞~rڛ͠lW@"0$¥$:Ek*DesopGt@,@3 GUHגP1UnGqʕǏOO\11E~yUftEitwaaI0Xĉ;)ŀ1 &{&se_̧S\bÇv;?? KVZ 0Ol_ DesH~w~Uc7o—d>?9?aJٺx3QN9c MK;m;sxyQ+\)Cb KP{{|#pedlaytNnߵzw`݊! 4kjz6| г@[)b MIN:mbfԞ&"o| ;Ǒ#B(mbzALM1!āfZBnan"b6Mzf#: )?Ή.R@i/Q>tLˆb2q\.& c5DsK`$2 v۾ۖ3p fTԓ˅U_Dc aĔq[`t;GE GpmzĉT+^3&eD hHh[6oYhËKnv>+/߹kE_y6ޥDu}N crQE  OJg…ֈ-Uz8e8 %֩/# "J~*`a ;Y(:ȤHvq#I<$s!W!&...ա&=5ȫ&Tvҙ#D-cM* 61qCi\TPsgzbV<|l2?=vx<çǖ0S7lX$Q7TGchvDIL5ʲ|z}T( sT:so~ݻzbWn5kV>#oڰ%*^q9\+ e B:c4{=6'媰\Fɻ|DIKDK3Fvp NZtݻ_:s~Dٖ]yiwFLe'mhB@l$m  <-7ھcԕ##sڞꗧ-_q+ ˓/@Ad' 舣g.wo߶K7|P q\ݺ{ )Rn-N?/6]:l,péi:llX]3I)ao_OWo߉ӳýcOCCVw'-+'C3==f!p( U67)YPȄi!Ռ9h%-%qLeʒ伎"Z9i;šyh=aɨ0Hc\@8( 2 l|QarHbIz@8D _mT-"iZ\zwAhz*[D}x"XfH |A$m;[`c/dlWNpg\ToLNA"cDe7o=yŋz{8oO~o~F:5;W #` {zn>p@.uQP0Af(*_'N.<._ǥ42ZG$%*" j1NQوX~H0^L&<9uj bzR$\-6U7՜Г¦^, 3K.>%rFw/LJnN/{RK/X#p {tz}򅽛??n]tYfM$CW"xX+vyȤJJmtO?ߦt{)3CwW櫯/?)x?|} VBrwȸLWWw* "թ6C(r*fȔQY3fY^Z!PI~&gփJK MeKԒ"6"s䥥cK{?+=uN}b``78F_ ʤ^3DZCLc# `Exq/ 8{q&/[bţ_}lM7]gO􌌎9 RGӘ&]b?ßa'?Q.O՚VKD9qZԚ-gL)޾GzpkE ~C"o֜fWw_^,AEa)d ЙSS}e9,Ɓx/.q\ݵ-YL$!ژ3K;`2 Ro2ٗ.ǶBh䇡= >Dђ{"wJ"1 d]bY bE@T^rր]'dfb 87-PC%BhbXs tIc*BwRI dXDA$X`bq r@U[X,R@TA_bS8.'qBE4riD~sb(|~2=uc}  .#d聃`|agnSPOx=7_dAj s){{]^>)T*E"E&shO2BZKc.`ѤOד[ʸQs?J_X5.JCnN'x(36|)(RQ]Uف򴓲%IT I S_SdR@ ,QAz1O e*5omۍ]haX`" ]'_x׿7<~! wؘ | JO" e:wHYI6/Ib&{#YcIE "MEF_PqLw(Yįx($Uݿi$a9AyaD>d54YM]x#0ͦrc/@ly^a*kqq~W$.lNG}=/cTWifn>zoXjd|}=])C{vUzȫP$GsNN|RRL9kɮrPM8 ITJ-qĥqjR.E`} P3TG%=#$?#ݵĊ!3xwP'ZG**  f.w2VJ7mqT4|۟x}We} xW~핾lOG\9G(ç2)AUD% ŒB!{ lp_7k.{ٴ5 .\y׮moZo_r|}: 9W68)x( 3,AQ /hzlN%I:U-wXrDQD);Q"<%2̄Bwx B'4,Ɣpf 4,e9w99[w~u~95my]_ | ؖCH>cLjD:ˆIAs2FG#O[n#]̟;O]od?_(4BD8SfeRbl[UKTavzvqʎ{{/Y8*MkRwydl{`HK!eg]#~0T B4-HӽCs3ǏuRy#|zMkUwA.['r>STf`b ,#-lJJ8p#?Pmb6Ԏ70@Xf 0yq ću6T@Q4 ^/o*G˲ F)dLޜPh*f:([~2j Ҡ@??Z?H(*]TEuI`sB胣%NFȺp9U }pM=0 %.]̍RBw*i ^^|aD핆pkPGɉkgvS2|b by"rB5/2ܶ |cmu -ycۭz1רa,Z cNМW.-X8XTԐ 79s1B1 J$-rDynl3R"ihCҔ:?rQ66zbX1rCr%iZH̨\%WI62/;ӝOg< Sq=WrtgwrӓO>bK/_v߱3}w>ݚ#|Yk4_O[T؁X\ wcZDzkCi57̡V2^ܳʖ@Hh* yNI JKɐ8骩Z -J$,|/ O];]= cC{_H/u3Yr&5~_FM/8LpP0]$zeGW][?7+,a\ϝ=5K,vK0_ Rl*7Շ |az'gfz!_5r2RTyHݝ0Y6C݃wLwxF຅ƛfc|7ްprٮz+֚c4pL+#DY 9Ib*׹}BoZHxC=sBXg씐^ kBwLA slFč':}pp.S@,TT>69b&] O*C*B92'H[pDGFX8% k>=/R`<N`\C(a),"c1[Ǯ/g9 g^ܿJf".7"*WQ ·u} >O%{`1P s]]pn._ +n\AhM>gR$D |K"h0VW!" ]THp:_X  +Kr;IN(ȩ99#p8a[0#2En;G& d|k+O:_Y0Sty_zW~~@ӮMN6==ݫW.g o\'tjyg>#A1::ͥ!8P`-VhuƇ]&6ф-P!7_˗JssSKR!wU[O]0I;A^*D>MhI|i芼@-Tђʨ?i@E.知4jR!fmH ]AR%jtlS(KbP%[](N?W/YuVּX̕zB!I' PBy0IUK5)DTfVww\ٵ}[{zoxGius|оY;,n!I6sxbwL<|'SLfp0ؕfŮnX仐LegFt" ])FR(LHmV@scS l28rx}. _ iG_vz;+g/3PX9说lbE`K,,hDeZW禐1BYfd:+qdb{RᲉ@["(Drve[rm+RoVm\U'ۥ_Me7Tz\ء΄;1 @=weG9Q^( <ЃZ> K!0ea欔Yz[jآǣ1 p")};/ k6"8{ޕJm> U&Xdx7GeCBy=`?[IӮ^^ mA&۷+4Q 'unRKiǘ1aQdAL#cjԋuM i!<|dhT* v FmiF1SN sb7-҅&%혜 5DGGGF>zzꕑ~˰`LzJi.lK8|4eqrPQiQa& 2Q#KeJک+pV4>I-9t.9G!d"1YC:m_R+6ꁩȗF2e i "5:#T0'r|WOOYJe&\+׮mGc;~912B0F+[v?sʅ}M0##0%"` p\+ZQ-j4sjZk 9$dam& 7 vСcQ 3 0rg~XϢw:c˂J0z`i"s0ChvRKRπm'Dt TJg:ץ2.gX`\ 0Z7V֪բPE$N7h/w*qVHodb O&u1F1öEQ;MV{b鮔`:ttU9c9o‘l&?0: lzؠ:2-r۶o?ucb&Z.vz޳aÏz=|˖ryn:NIPcV Y'>qkg}zg;66<zv3+^}?ۿ_}vKhymPJsTz#*&4TkfGuCU'G$T{uA\w er-9{O\=vpvz~Ksl/?|WJwT{֬6%h%q=3@@{#A`O_/e q=rNg&? I:؎޾ruȁ}}bxsF:S)y-<ɫ~pltl@ W$WK]`CkV]|엍VlY&DQA(Mhkl֫33ՙ*ʿkiپH {TD؄T _f[ GY4X\bp2X$0p_O<0cŎH:zcBEt#@qΏ 1 $DpQnaSZaָENW[}Q+5ebݣ哚 },Ppzuۢ~(BWL#M]? tkW!F+t}췄d!$B/Ih\M _l4(`9\߅v[n+hq"֩CS /v;R +!+ ģPR2vES\,Wla;ɕC/?uEx`^DVT0דz3]$)3SӧϜ_M2S$PEY[gn„&ɥ]z%9_\MUJ0[9Bta&^$ANwD=\&=oe"H22-v$7Eզ%PA5"2tS#5-)ZQ5vEЙ&.o ѐk!ֳayvOv眑A;ٽڟ=bj{-}xAֹٙ/nz24"> +(f:uk f_{Rw#R>۲#f׬t-iV,t¥o;wݼz͗摱kVd;*jPԝl[F5or`ViQӪjU4h)u$T!.aq[V9XKTO4~ܳ԰AORt,R?B/T",IRV.Ԍ{ߺd׿յ[F՗|_..w|o@4; džC=Չ>1s ԑ2Y;:7: 5~=ȣA=9tc!|6 %Ka[clߺr)q#ٱ}Ʊ޾rĶcXP8V3 nFCg볳ln]p5}E3XӞoADdBʣeE J)S>z4Xaw͍>?t|,yC#I |Eݎo+05#ն)bf^5dh#Mu3B:2EhD?ll017Lt rro*>  QGıI&D=b/Τzx0zz8!^JwŎv4Py"ƚ0u}K+(_%pR z:wx8,'Dox]cDl{1ёT6QbV:7U*,ƇGFÐ4 $"\Щ6Ubײ+:jtd |@veH*8g_ dvesd,&=T(z+* [NC0: L95Eq7TNTbi'*/isJ?"Bbf ,Ræ ƛHN6<3k˖,hEzB:; t6s?;nk =p|eKܺ\>He T&S߾oT(׬b~Z\_(b{pv./}ǿyRkɹ6 V1|roц30,1C=Tuzn 8(!"ɁDL2cpʠn~h˶:a{^t-eSoM~}e7L@wkv*ܶTHvVs@vw(hX|=9!QK?#ngt'wa[CGgYpW/2Z};u-=o7);TG(TF9+/-宖(n%:{O!559sTFqjGppSx>4B5k@ƚibT SmeQ&~M=TT :oy.Ryˏ:qdvOy0BUXxʘĬƀ&7 G7ȶPxhh2xKE \&%lx ԅţ -ÖaSWL^*]ݸ|\偁XД !QٯmehKerYչG\LT{#ix2w8 p3+f1a Higdu)a4Q fuj!T)W(WQN}SMNF̳zLΤFT|>b'X)"[$|ز0z0Oز/v!51;U,ZON\9^7:9w{/_|QEAQ X!!ZV-[ݞ蘘D?13v۞ڲ,iYB+  ( %|3}߹Y.-T/߻o-K.3ǧGƓZ3/ #kQWV wM'Fy{nfuҽnz,m&#Cay͟N?\X\p9sЕ 2PuCc~iov3gX' m"AcX魰#X >:ó+h(19GH^pupsʣЊ@"Xk3s0W/^[zgV~l"pXOZQC\疎"͐[e*,BeeYhn`EbE!)pǣʒ-dEEk6aIYA+Ņ/noرc781PVCw 4E30}gЍgzF?Ң$tA?~҅_~n\3ӯ p+/ٛ_Vmeܵ7xda1mʲߥq!^~z}⾽~Nlݺ[k]5n{ 4d`z/g0P8'<&[DPJ$yyEy R vxJA8)fl W0:u{N>soKҸq $D4jRNL¬u$F٩Ɂ({?4_+%\lEU%22.Rd5j "*B|`i1si ;`!#bh$"쫩*~ĩjh0 {)ê5(5,<+VOtңgVhJĂ\ۈE —pȦD5zō(Y%M[FgHEq0l'Yz{v?mYk]ֵ$f"FV=f`^f׎|ĉ@zwz i N%PݕwhUݞIi Tɧʪtǘ3ɰ8*,"^9Shi7FBXW1XNX~XAMR' LlY}:w=w{`QbjnJu !7<4 @ 2J=G Wqhp4B^t:2A-y٠ۣ_i C0)W&[ponVWoyՕg枮b8灊3ن @<>_ÔDx“LƃPcY72`A_x3X.Gz7=g߫<*zNR aSPYzaTo]`eQ*T̬B /?Mο{,2Z5Qmpt|NVw)%I8;L0vU ɦ7#Z:O:3dnּq9MȰ;EO>xΧ{2~IHFmb?+HӈWbcJ]1iZP^Ij\j}SZV ϗByR5Tk5]9t>4-7s=Sss[og+dn_6۫xn[wjNM_^Yz[e54\*E$T^] F[(P0<5Ql`0)A[324nkkZ̴23a!fY-quQ&38/wcC힫kĚtiۗϝLN3# ~ss3s*$\w:¾}s~oCv\zN|v2 n:D yt.EZ㺮wN;u. Į[JX {Q1+MR%IHk5j~!k]c笤8wFl~ Di'j+АQ?sJvq*MSe a7&@lna]N+;4Á>% ]OKN ZBikIn/,pO;Ć )K\'BYˬP褭~% A>Ө}wG)/Y 4/2)3D;JA1,IɌS 6k1D:19W(z--7'@d$J&WEaxW:yt? dS1~ IadB)XȜԟx3V~IKDw `7Zy&F&GF]чiq~.ٮN#ūxEn:\7[ǏuJ0ڈfsȽoXom?^[ZYΙjkko2]UE8Ny}P$WРR'[̆PZĸz]0@[i`9$u_zY_ QҼk/>to~F>itdI [ի́~^zZ/w>x+++NߏVNtvhI؀.GEdýUp{#sd؞0%Vf+M<;Uo ac#(/y87`>T*\dL $,/.18䂖k~팒z28Ϟ_τSm`I% WYFCCPF uam c'<}{msvun QS4EXLT"o=6"JVՓnucl5qєT$A:[ w`2hu)o r&N7esK}`th}:|EdXrEJD MT\VFBDr[l>/͠ ]dLU@Hc@˨n@^D!F> r \s-z:'xb[7/"rZLwyCU5s2CN15I 0+\kRQ3Tx+MT{oC|zӶQ 2o"h:-N" ?jc/L/bAxjgZT@VȟN#)!? sGe=2hșapeb ]և?OZX`Σˎ*0=C7/e p*B\V$b;m+R{7>NLt,plH@^~g䣟TkjvmB7}fsx'?٣'\xw>9ir*#杻kc% wGACYYXLj\ H&-vY&ڸ9;_~r!Ij~󵧟~jt?^J?Bɬ;@Ϫ/?SO'y}wyͱߥ+ՋUՍ_/ YEwՈpG)*\kLqԽ+kK+0G&Md`秱` a<GGMPبwWWn[HUP"hu#'ܷY}ڶ6T(F.&#1nϽFgN=ߜ>|t禙?7]-JOL,[&/YE0UX+{[E=s7͚)-b%j:@]BI i u\ rq' TFW?L8ȳFQ2I5vBЏmI ]G~D.> p J h"Fv;]qf4mh( [^"tzI Hî+Y-h?^oP-`JhbsR2hSrZ+e~Zg=˃8pTkx%ڢ^>;>-VN ؿ:./"  %II#p t(V`:u]JB7FºH#wPBZVKc^eDwS;+^_w"Vdfn~&ԓTk~.#T0*IRS t"O "/`Y\,_Qޔҫ95{ȉMw;Vz͌.k~pwS5;wWRV!b"%nҭD卝.`w^Ơex?ӌ@CQC_Np+HCwKnܱ_啵noI{uHX=.tpp-+aGwvk? k{";QΖ'D8wGt!QS$0?dJ9G.džaOySX äEzUB(ݿ`9_hw_35c{y^kܙb4*ein/:qK΍OOe "5ֵ&Ј6yV?F}yee?3|XG>G#ëv7+J E`Thp(PF47 XN&PA8::600y &F2B@T99ǒpkNxq 2葫,QDi/()]c(TyXC_ Q,hxՠq8]sYG"$;M!1%%s,pQftl(uC67ֆo,yeS$$KJQ=u7 I֜fU\kKa i2:n+Z?CkW;::NL 5 oq!gG3 5 óG® *-jWՑEȓt&7qKK.H [&^%-e=F::ig PʖX>:Mί; juK͋$*Z*4:!=GK]-4)-Nb.q|c2 J\GMJLhql\J"rdQ9o ̴\S06ެs;>56j& VW7÷xxV@ĺZ#A'2'rP aS N6:1\{0oy`xH\z ҲJf۪5`ZJ(ߌ%|4S f˶ћQ)iai gq#3\ρRXtkuPBlnL0kIaXL Mܡ׈{Q~|5284;G^:qw>w}'/㓟K//~>ſG}~WV\;Z[rٰ Kj}~PADD ZQ`KM oSlZ6og+ =z7=чnnKm Ӥ^eŁg~tU|C[,G.$U2eQZu|ݿ9Wћ v (qp7y[\Y{'GzxnbmSp[4FZ2l axq\eVP1 `;U-~ᵷ\9ߨՃ<0,/ +(L!RF>1D19 ǙH.e^0H7bc=MMYuyY/dY,`墼lZJBÈ4 ez\fH?$$E RhѰ*AH:l\__waUWT+QY+ a{vz2TĜpm@ןanr{}, .Q8vNjֆ4 I{7<=HޏX0+fkW%d$[fr/p0SZB# <€W<8;1b>TH͈y_f`Rn1DLȮRBt*=z2q2~ϕ)hTxx2Iz8! vsCjiZX,Ti$҄s1HXӦi¡1ܩ;'msnízy읣|Gr>qe^8}҅ss<~#bvJh*FfYʶ9Q#+feiE%Z'JW{z]@^/Mѫژ:r53W|F󋫝ndž+Oig=X.t GrGv{Dk~Wj1 @ĉ2ΔM<7#FUVװx9Fi; .R[DVpD lϟƋ}G8ڿxv@dp8jey]&tEOUmQ6?xoAnʐue^fj^%>YhZrl>gZ'+s&Xk'c}˳t]92c;)Pi94 ׭Ґr-P>91V\%P WdEVOU yL}w !ˉ8"T> 9|jV_0BR Hj5.PJ9! Tu׳9<ړ Щ駰JG4T eϒkPkiiɤmM ^^&hi vphNX%<Vx[I&& "CudjA:u=y]43950

4;ۺyZD׾|#c]Zر_w͖Ϳ~]CDPW}qTUֽ=~&MKEe-IUW 6$9X`- E=r@n_Ll|%Wϑe ][=?.֝7p^XYfp]0=$SoQS%,aJҳdFoty(qlCv{ӭݻ}۝_wuK@)<~@UI. sW~qunvfzbqr-m۲wp|'+@^zKOZS$"4 1Mjw+ůZoeuQK'?s~-_ګF6@l= 1h%p(SM~ eLij.x1]fe $SYfVW OϿC] *m _{6AiƲJuPz]y$@Tl$p4IhFn,rԟ qeoH "** r.. IuVVdɐVO)?Cjl tFC7Y9š! 4$f)O[x) Ȓ-%0Aw-ArApRMB:b-*A\<#ԸE.`v>-]>*nx[zUc\ɎEkzCzq,XJId5XbF$pm֛&yLA؊FqH+"S+mP%Fy >v],/WʳJć^?|ɧfYI̔1DZdcr) BV tM &)kYPxӾ~k6''k?zwtUWSeB]!lZ@X2u#+V X? 0NGX-,tsv7+;ƚ92Fn}u. lh2"DL Bf$7vzv`cʷ^}ό ?a\OFsC'ԉS qeg˕M/+{?/l۳g=7n B\-aY׭l@)az/®ң6z  C63!E"kWHBOH)LI{ɱ҉cbК%rY*)'$z7FAs Ѹm~IWD쥼l8 G8#@ &HC fZUz >-[xVs FVUBz o1 0[Kk˯<桑4{ #cɻkkw=_;OsWV]:U9VZ񓢲~^2^҈2HV?`P`s%" @2 .:MӠ)zVefЄ7ɣޚ')2_ {}C/|nz_Y-XQ4~|B^d,RM䎘^$, s3N\?E{[PX QB*ísg.]}>9 :3LkC=`e]y|s-]a׵w}ǖ['7oMz= 6R:V-q^m'z_>޻r}>/nc3Oqv@-2I$;dt +-6%|hU0$ޣǦmR_n_Va'c EΈ KDnU^BI\)]dYT@ }sbȎ+'~_y'(@Q YoK"N` :]t hErAi?`˨  Ғ?%(ZƅԲ^<%a] ! Xa !\B5HTdߌ6- Mh%`*}\#LcDAהJ by#=~ʙbwuNFiuzKs¤W KYJm<У*x6Fg2$U q\{Poyؘl޶usKxUoU \mz\o qI;"eBBE(/D5xLYѸGnqo4t0/ų@ XyTS/7rOօגҩxڶ}޼-[/=o_߿{8\Z[up rT>z#HM6Q2d&\[ E04c/tv.$ gkc\ti~pȦɩ-gfv^vM.5&3rmco5Y' +??~.~|hbnKeh~}An)@$%ܻ񶹹ٙv|S{YX])<ӕs&ƍme]@x,jޮ٣DņU+X/Ŵk@t~c!.BD7'r, wl!(B4d^YcB#(섂Ud< ׊\E(Ql͎jK)+y,5IP=ĶbB5 Idΐ%C̴R"at{ EV&64 ZQ!R,QgC b t*e>Š#IpFp,~"$Vy "&ֱɂJ]`zqIW3S@cUֱKTR^5Cj iN:ȼج榠 c&VGUZy]U_R+6owb4fH(a`)\B{k -:x3yR_eA"ӯ|)붯f5s;}_8pc/?7d[vnf.]b%<Զ{sh@meHM+g;Y+ݕkSS3[[X>`x ALNmޱsdjƽ~EjNX$ >Hkx|k7m}W8$'(bW|rj r0Qgpk"+%7vUZNE*܃ xK*j5$nEѭ!+K;Jo\4ЭAz~/.ѱX\Y.I\`x LљÈlj,9ZYBB8 8"Ppw?rUC\<M^eS`Vƙ x*IdHKuqZ|ל4y,ϰJB?1#?sфqO{PQ8"5tԔ> 4H@\T6dmN&;akcEqޥFD x-l T} oOOULJ%RM ͥ7Z ޜ6`:!Zfx=PP&J9KxʲV|Zvf 3WϷ_[]+T# SMϖtwJ(",f[HUl3S? ,{2>r+_}ٓ`}5SYy铇u`5x)hP"(09 :HL[_ 7A푩U t REpXf 3G8hQq?ʹ~ϴs26M4Đ&SnH/g{OY Wlf+# 1~-kc$<8>PU5Mxrbu\{x»7G'GɵRTZvBBQ<"9gxܫU񐍒fypSF;\(-EHٕqrU3+j% Sо#Tʯ%lT`WxC4 "WXyn ²Db S3b\8>4< ~#IwZDq$CB1nJ> YxP?se3O$C@ !'/Dk|;4Z>lJ EِI^PXؿQ @5!xL`h'ML?y±ΎM:E<ǟx_zZ5-^9--"Thkf۶3*I PoCxjh䓊 !i=7N6 W8qK/6}wo5C7,yܴ̎T!05o C rx?|ln2)%A('x53?Jkݰ˪ekmw+kjZTKk'&8ǡThdX ɑְr6A`D= W4*<|#4',5" p(.#ֳaM7p?=MlЌY B^n5sJ X%Pn0J IV.A#A2р?/Iœ>[A( ¶Tp.!aR7a}҅ 5:<8e6;tTuQWrR);h^XR^mA40]دuJ(`@( =#&oVVZVs,ƨ,ӼBrE?u཰XxS#0^y[-{jw|g= Kz QKPYGhHf.CC#*}W/:.;8$G;x,3ɘݼNЊ!;0UA*&`] ׯ<"~qe]h QV0ZE\a<\OV;wGI Eo5h;^'O_N3H'駕 pD>fF[NŜADv&1z}vWS=/~xӫWz QS㓛6o6ON罠)ǧ7o~LXoISQbRI3Rᖼ",ؒ!WV1.f>kRk/![ӧN|Ņ wLov\]{¤158)K4hV"dR4Dj Aea>mEipv^LDZfMeP=Gu_PU@cldkvcQzRESτR60PZNJXjəZ$ Վ{ @԰,A 餃yVKZ&KޝeMxbW(VQ=EFyAf6L4L./;ycQm0TX;2>~9c|J(X`Fg/zz{!!@AUElaȊ\ L: ,rYGwd$!z8*4UMDBR{x&["]!{Oz^@j#NMis ׏!xSOE>˓CS[H^ݣЭPf!"q|mlv1R&I ^#+R; ;tD-lhh^]]?v{lWã3͂!Xb3F{ Zxy`*'eY;q@/wNJ~\`@,e+|WCwrYt_㎼tHFU O!xzZHVe7Ѭ/A JvH(f/8 зt,O9J{ݟ̟>71k%I-mc|\vIw;е6YjYwXL/VԕJ":aF YTZXVWrޭlCw^\tA>p^g@`rqk@"nY?3ý7qFòA8lAf/.)H 5۾2+?>:\ LrH[Ȭ"Q/WBdLn<%:Z.f]2h P91xQ(VpS Q&hu0$ZZݪSN  $D^ tiLGS>0g7@ƵU^s={Eɦ'ݛgA3+2p+ʒ( j1u"rKB,Ո.*g"%4N *כּIF0'Ou.M 6sP|V:b9"1J5⪎f"0}8;&7/,A3*u1% $&YkyP: FL.RAƵєi. ӭR6,S)3"SXCл#*fJ c#U 3 T¼#?Nx'GO_ H>V#`3Iu>{`}b6i:KM2+z}K3{#nAL cșzSK*Ԫb9RYg'ǎx_N7v\;ǗZCщqWP|Y.Wqi\9bPV f!yHc& bhǥeq4l@hp8,ȋ_p̨qqqGj5 9A+S%=,@V%Cȭޘ95tt6HaQ?0ϱ\< 8o6Wĩ J;$14uu]pv]\]~q*1/3*KU* K=JZZwu@R]asm) )70K!uDRx~F »g/{|t146&IVCAfq}mh8<աG7Qv d\57?afoTe(n#ƓhQ,@,ٌ]DTʄ'y E*+]) y}Ȇ.!/inVFϳWՓQ$,sdײ4[S3F&݃S+4|Fۚ2] i x[==j2P=j-kG 2{=;)jB/?l۔ߒ73.iLiԂ0'zbrCE5!˂ I d~ic5o}ꭃ5;n,\Yq/=8L;١~{6X6d̒@iVx,._pV%S.yAU`_ؿtp}Fcx˖ɩn=81V ƍ37 خ/ry t ^E%=S="pY*f C2 1EF6<~koԬeܬĢUuYJF!}М=vf(қY?4}I27Յm( HcfVPDRY1Sea֘.-BtW!C^a1[~%8G *׀Q EZje'D9,cB`ƥ EbvܻqlcD^GU[ogeI6/ YdKO'Tf;^w)rp#ÕL=/\{=:uE}ŔB VS=;[>C XT4ehc d+Ed{rü) aboBcmĜeASZʴfU5 p|Gݣpaac ^{E7ϾdFU ;m# ېg9kco0nKR[4K\)y(DI=EN]t] w\Aungyd0SQ /8i֚0ϋ κw[.%TP|=|ZgJ-2Lbg9$Hw~㡴$PF mt/_s~xf` u Nj.Y. g!e0a42#XWK{򨵀 },DOgRK*85;[CfKb n1 L|j 6;ZK L!)hq$s^\QHZQ$D !6rͅr)'MB0vaDd,(r9_}*0Y'qހVC6X4hF9+A(5 vA:Xq22Qh5,r=IB9ama!r-Fx$1C迹JnQ1-dp6PҔ]wju[&/?11עi޲ #l,]. !z)1qH`Du! + _qAma=P DV"ӄ<X"/!^wwJLr$tSD5VֳwA}=GkӒQΨe VhP;amLᜍx0[҈ .J$R2j&Ԇ!*2CRԂ,Y "7HT揂 dG %X/*ʰCG_e)/jEЊ:PNQV0UHJc9g9symzϼwcilh{eu}qyrxdzvj|z"5Yxa~Z:p|jn|zK}p8M2e $)ƑeV e L"C ɻ>sۯ&qZo~([ʧj鼽0A4{Ҁ_@V^ )$Z1ToHQBPm<@4kZLXn}>'9+&ZCívpšxFʬ\0m 2큸Q aQg_ƕ3AYW^JdGgI.2_O\\Cy&٠b46kZCAU*0,^FZbᡷ#(^e4VvIѸ9ũ&=?El`8`[U('A 8Ҡ9iԹbz`H-]][y۱-gzzB8/Z`UͻHT~WÜ }yZIݚJ5uv ( "磂f'DL(gE;_ÈRuه9U+v-$9HY!˸[2R3C uٵQ 8'L{0dTޫiϩ/֍&䈓,C.U~ sQHN~Z{6JpuyM?O;}ʡ7 UY #ǰWc naB0Ψ\[(o437Usd:8摵3ScOc?zc{i[65GyIk[wLm޵QĬ2 3*){Y 1'PwqV~%y-K$>I G[I{OF\r=() f6;r/|Ƨ~S3oZ,gݟ~U*Cr`/Rd@ݍ `UUѐKJ+ ]=dHoHj,dOX[y} X{RZ:\j/깋g:SU!rL*١^@K_S;*L IS^`CC>@Gf{ &kɌ`W ^{xٗCXp~d^u[QA )njs]>bqJⱏQRXRÖHb|6z`2?st!o^!elǛ& 0r% Q.9l*yU^kb`Q v<21p޾YـY/65̐}ׂ4DϖQ,NGNrQen*J;e袺'OP$\:PwI(Riƺ,#@pbV 2Ŭs31FJ m1*_m[y[FqM!Ba505| M!IMjQxv?6!? 8Qd 6zaﭜzwwO Jme;sE YQ$LB䕭lSUd%1ׄ^u;ԕ JXw(s?ϐ=KE);xV8[XrDt=H<6ϒ0;^P͗p=@ok>W H\ nGZ1mU(kJk'?" uKX7aܣ@?%p\g,!Pi}1n&]փkd""%:r#t[z_{nɧ~m56dI-Lnqsea VS!la rAHQ2TD#I2mBV@9&L5>:|fQs( l#H_^o5wGOOkh`೿oMm):hT6։;_w cVԱ#,I=gu5@OfP_1zӼVU<8!oX阊rú#0A`Vi?HƧgK=AW\B"8`Hh #`-H]\Q!8{CAozWsnZOҊN8)֥df,M#˼d4`Ay֠ǀBZ~/i5[Ow̛o|_;QMɩ4Q5 PW;cy mdal g⽼;"°htPycoh҈s *[)^Nzt// f C@&*crʦağ:ED5If6.=ᗆMj 5S.@πBzm\ hG(.0"g8t@`?xPo v)B46e񠈡2gQ%+h$߲e>!OLxL=Ien57JLj- ~cB`?=pέ{4:)t_B \&=،gfҨ~:]W+  ٲ팙7jbi-E`!JHnε [`cZBVⅵWP^j|7F<~*]8QP+9p4VuJ¾3RL1. P3'Ҵ#}z#ԗ@@ 8Q]oPJc9WZU?Gz6,yxxBE%[%*'W zaRyT2WjZUmߡƨn2φYvA['?Ѓd`q"Sd9* A}E^XzkK~4eG_TGC[Uk }6ح\L >4q|/[x[/|񋛯1r 7fEld TD/&yn0)Vl.Xu@H:I1־JW 6h<|%S͖qE ^XQp\>+koX>s|0d6$BU'-I+/AiksA" dj~Y0.Gd-GͰywvFZ,)V!f%!rh2KAգZb)X+ݸjRk~zGf\ jpZD;(yub,3DDI{Ujv-bg‰775=cv!!9Nb|ɝYɐaQE#Q ѴLbpJ#(d2I:*3^@:@j)LX?ƒT- 0VUɄj`vAsqΆƧ*^ De+?ضJFK&wSeɽ)l9q *$~CI(M+a2PݘnzPlep3d͹*Bz缼2mA% QU/aM4hX`<KVqbIu0r5<욁Á(Lӭ$f &g%!Fg0Т08w)rSy,߁@_aWDnca @"aĬ=mƁ',]y;?pr 4Jj*r~İ >'$AY6ѴRZz 75IY{"M ^Ok!`g>OmHcxl>SHꚶ)fp N F9ni-pv+/{M((xՒ;Y#3M8:tda'*9[KW#w?wmMkMl2HSY?7/˸}e95`H8=1E`^ܢg,qLAi)O<!^Up h `41Q9g|"w,-,.lmjH\:UIJ|I J H~!4skJN-[AS+}tl~1p[6bt}؏K&c~(Gf\zChp I(!LlJ }8HZO/FRZҭ[*_+C|H`=R.CSTrI@vfsK]8NX/h@ jrMK'N9u0bT=9clo]ۼu}keŪ1v}kGGϞ f|9h],-|>'g?S}p[Ξ)\8BY\ Os~E TۇF8 Lȶ+nVT P0#8^IjJ46x8]ǐ kMZ:lNC$o|+<\Q'" g5IJ5jh (+1y9UQNW@FO"GKTmM{em; &("-VJEi]!Jb&c)1D!PT!_Ґo]Wp اiCr wHYVCyDb:i|UҖ\fw؋n\/^O=8Zjx7b4*) B|aTކE z/9rY >öi4J)ڀb!7$O(e٩AFLҺ q0Mv`!1ydbnNKA` j47`'PY⨡FSR?YM!b8,b;C[*,h Yf<@A 2q^Z  L~1hjjPR,hpN̘j0g_OMdv/o^axNpbҶ%U5 EgV׮G7,_9vA}\p㜃-5QaѢ8IPҒw(_;ъ܉yTŜ"]TDž>G~)B!BkIԌV6nMǛ{ՠJh"#8ar~d~Q>}§"Ef2 z l6&kq!egf{vVy(h9u^%"Vl̆Oc 0W/ u-}p,FH<szaY=It&[I1뎪=-Fa2 ݜdT#o({WQwcI_t;6 YG{9pfg偌Nd#28b 'OO#i٢S?xȑ{ssO~xpرj@Y x}}tӛnw,t%uS*7\/~?/ ο򉃇i˭ɣ-o\i:\1p\.!Q @Jv}f 7 +k@ ⲎbS0sҀ3/ {ǏvCWze^Z9QIqi]-L^p0cd-o '"hfC*7x.B,e12#:5tFc!  ' BZ"Td\rT?r ɺtG"Teb: Y5 qȠKkxVs]D = *Vl $h!kۃV )%Ky uX@M_c Lj&, +f<='AR;VPahPYڞS3O>yƝ'֥7;p}2\]׻_L3??9p>Ӛx;oӷݾ^o(A3Me\{qgс-D+~hւQ eLb+WRc[XHN9Z4 A6C!Vdp#\Yea<'oV(4FjN" aܤB\]Yr] d::TP%rs70-@ g9 ==zvoGmYQ왆tU/}i{Vo8LΫS-T"dME7~t,S.;Nki[,\k.l\[Z>X؞ Gt#g_PG<*ptE e(叜ݐdZn1n\N W%Oz攢A j[Бg|Y]iC9G+9ts:#(<pQﰝ@^;+D%fu5hQ&5Qԭ,`q m'!Z`ʹzG!`(q%zK팊nh$vn՟ pWAЬ?IΚlbqn]e|g&PɴVlt{ 1D0X4v~&ɐʼn􍾌2ThR&(7i.x-sysf8w# v 5 9{o譯_kco|o[?pUe9Z[WVG^@ugJq^E90UρRgSjrL !6Fs )/?v:c;%5h ѱw€C>SBUeLL:[N)<a#ciJr[1+݈YINBA-(P: ߱<"G^9 t%mma.\ѫ 'p v_θzGXi*V$s0iH)gm@\&0z+Է eڝNL?tл+;4pŁ)dGH5HCހ˓F,%j9'H88!T)Q[Fȡa-N݇kjtJ> "윍gy=m)( ""I|ZVꆅUk#'z B#WgRTm >ٝ&!&E"ҹc-M4cB+cɊws(j 'ϟn v'B xᅣ$Mpݜ%K?,1be> tZ5}.QÈWqZ W*+a @<6K"qpU#>ʰTREꍓ%|!"$v(a ,/8U9ޓZWA?=Ͽyȇ/Mz4.w&??8yOD.F'̌|W,c6H*vhu %FHzZpK%\Yu ap Eճ/mt8z.]٭Ǔ>ۂi91[P%FHQ-z[rDI ȉe3/C K|>A'SpxU3:u/l%J>X"@^AW佐^y׆uYtC7]ej 2,=&O:*OH^0 Ѫ4]+CH&Vhe9i(|R]HW4mQ] O?8u&mAKG0j>86T@Yikah:"'H ؽ/wfb&N2f֨\t&M-H`v' Q%pYnR nT7w~@9p6;^UV򹤿lՕOaW7+ Օr0,.ϢnYzjO~Bٽb|_cFi[^[ٛ=Ƚ_}^AQ&ku ;mL2$6tHLsNތFne,TLH|Cxz.p5Nt*<"X \4WkE5PZ#ҎG5$SԒe Cq 'Eee@t$ON0_Nj1N$R/NSȩyF=.'#sKDBjD+vPG;kG<xht;)K22m~gKig;h+dQKv}"۩¥QDxM~: i[;/4#GFEZt4P{L}QBH!EQnv64;{RDC19t:Q.pvKõ7g"Kfe?#%h$sf)hCS9d!1Ct~oHH6Vy:d:فQwJF=RM%wQ@qNYBo2<FPYe$UݢCEʀHD9:q=cѱ]ydrKJ|*8G^y'V!@Bi"Fxnj:ivqpCQyA}qUC´,Z'ԨϤm1ϵA#o8u?bq;K3g Uu[#N~wŅ^ZYOW|gsxw4r`u{xciiĮLǰ8E "=5%ʖ+7S Bdy sn@l!SL pь.dԲkxs_>'Vcda#! #[˝J~ OK݄TDj@餃~Q\ ^pH,ihxi^XTii.E('Hg[bgWV1 >EQ xv$&CM[ö5sugZYCM$[`=I:($,6+!5L E1;3jr߯C+`mWֱ2#q}ݤ>rXoa]V2n2*wQŽXYC 2yUo&fg衊\(S Df?k#[õoy;O|䩇z G8ѶRW 3#,;lj-%+Qؓ(@z _Ϥ-#i9 ؁R9-upmisR_/Tg|j5xn +ZHWY.ʩZ4R(-\Qf#lK7w8/^Ce\'r 3H4bEŦʷH xCf.~2MJ:*:Q1 Z^QueFǍ!`cF3x#^9*CVԫbY=J:6MKєCY'fcs"DdkgKo~v?_iͿ}ځNM{&=hXնᛞ3tB1 |0o??/6D%.؃q"D&lʣWS+иYD4_q)ځgqz }q4Q;b'aGc]dBꥻeIEpIdKR=;MD'7e*;&SrI*jPh Oēp# L'ig>#2^iRW=ucWQQҋ)"U%$T'5^?G!t|ߑ,-#wi+7M "lkH{跷ǡJB[s嗮CeP8FOQQmdu-k 6/Naz+ɰ.CdX܆5yLzS{24oƩn5N9B\K%)LtjC8Nʢ҅4'p8Q0RH)K f0lu%|lsU;N0yEnN𼢠37~2۲. |p=yc XOonxPI &H ZF<18 SO`;ŤPMyZЇ<ܳ_~Ǝ6Zh^|s,FzX9[(V|>{w֩ FOBn~THɩ#5' OWIUcz~:Y94iͭ"ӝ`j8֩ xsb [xTNZ򈪮kXp( KMCVhb5| s`]̦kDѧtWhq#|6ir @{ F@_ނ%9MB 7$- 6 sPrɈnTyH9~d+J:QՀ U}j-6Tot(Q =0DZYڊ9Mx W/\;w~8rkKeoQUeDŽ-hlfA ̝ _Wr$V2ա-&ls9W1}H݆#(dv㢝ul4:%9 :V6(*y}3 z9!Ktb&[j쬀p85 g`i@1g 1Œ&QyWA*3OݍX c_J+ D*A'bEKFdEDDۡ=`e1}Pw} N!hF}z9A"!KB R'B J١5G¹'1/6 ǐKj1#"c6Ij@חVϞ9ezZ=]|ΟF+׶w&5!v|׮gtn9V,-@n3#G݄v2\/N|B_U{$%SBɘ71>zv&;"vP:qyE57=%olmtTm:fô8(x(X|2mF3p9JZ"/fmxo}>̶Ħ[X 7ʓ:3-(XӢuFܚ9fFizt 0Y3JOj(aĎQtWH`yÕګT6(ʠB:G2j jpb[PHtk.e 4t𸡛' Em4^Y!VA;9=TR\3 VLC&ܢޛ#a:̠1UX ;Hi9NVA\zhX:kR&VQ>no PbnԞM8( ^㩩4nXD b-)_L3 ^۬fdpBؕ0[$ Q)hXO0"3;;scLC3\QBEʝg=qSU/-(xO/sZO~-w|_]=z|ssk2i;!EV+CW^| GǼ綳ђHHP0VdCYn]=<cEn\MATmQDOD 'sE1;9s%jiCG孺!)--oF4]+[ HONb6 Z89.YJת%ӏ,**ts5! Ȱ'7}uo:MUO\tRFA `ֻ&JEP6_.YyPd&.Q'H  U]`GUX2푃f,TZ;mdCuG,ҧATN78ŝsW=sT֬NsJ):=1cχ(cI3q!T2R r)W`]-A j3# JIy'0sX~p:#1@>X 1;5C}\'b#Z:K](Jॳʳ(T:؊-()Hf9#c$hڄ {Dg0]R:yoi8 < ً(W[J mei#Y Zzl-5Mj u1"]t.ABt%@-D:JሞA ;Ai,W3#XF%18bhop 9_d0!X_V`Q/7Տ/p`}M\1￝&qվ[Ë)#pW$ב㘵g yȠD`r%m~EVҼ}M;M[ۑC;߿zu{:i\MFN0+x[QA}ZyoHv6ypL#鸺((q!M9D[JF#M * cAWtatЍ~DsFV|xr'$ uQv.Wu vaf }3kf/u-l=s;[+KKU6$=oGmoQIxhܼAqd=_y'7/gpCN"!U  u&Ĩ HtdP{aqR"r%-A)Q/Aψ45[Ed*jG/,,mn'S@ {>3-Z{^y\Iwh p3˄yAR d e- Lp_@B Ka?""HY1ѳU zjZ3ҷB=v%p@*ώViv!Eu`S-b#=bK!ܘdL'"x88 ӧ-鑟SW,I} WWz@y2*4"sO` h=kީ׬dqZ1F^-&)Y\DHfWu #/eN Iyj8 d.C2iEJ08>_xK1H9`/bP"Uxp ZLj?2sYVC&;۬ ,! E^nVnEO1aꀢyi(aw[991˕Ukp`.csCa]*-Q Hhhg(PqJkx˯^8qdlz< z 45OݓgM9t ;`4$Tx&0YۣdFqORN\@IuegJՓ-7Y^\H̔UfNz5;Woo]_(/]l^xg>w~_[\;?*`N$[(XrBK"u|u:?:11.^]lYcWV#3F8L.lOs6\ P]|lOLR؃S3T$ȐEoP7g/ZF&aZDX!Xiѡ&fA"@ Tb2@wm Zw ICW 噏 .jq#N9|+uI VIPZBn:m'naH7(w`0t6)2<6_l,Ĉ+)åCO|F59zp<Մ^%CmM ensGYز*O|V~h("*'aWڎp+rL MY|{a0o<7S7Th;?×O_LeKрBf&:Y$Ӭt `S.]P]Ms<<_jTѐqv39ۭKx{BYé U>^P4+ \X^ZOB<ϓp`NP*3pY[Vt$/nʱƎ B>$X\p#%0Ui6=3J+<)#zByS-gDz&U:4s'SiĄzZ(Sv ='K v.HjJpn:n~M*UYI@F^KC^Mu>䇭*=_vi0HGo+~FP`#8 5 YWG "FC<$avζ3v:5֎2@TYk㜛nT48gf3Mpu24aUsnD3* f wF<4O?)NbZ4e,bmVs "&G mO@1.ҺY*\ܫ-R =V#rf#%vm-S ˜qٿ$R94м"w}}*auIj:ky_}/n9׾~ ow9Inl1g 4*ð@#J̳_}L i~ڬ;ۣ?L)g<apڞ{T7z˗^>S|'>bQlnt-0ZZڦIߜi,*Հ(0 Be^{3㢄% 6Ei^9+ȊLp%v@Ѓ}BT۬,&ݵ| *%HQ2VH3eڭQˑ> _iik' F &0U-lX8D%4$/t׎ c-lM-˪wӐVU MMXAbtiFeϑN1wj9;~O;*ʥ뻛/=R:qh5YY=z ŏ 0.XQAvvp="_9SY *NUS*5NLA,aWF4\`؁-48Mt9S" hn!#B_.EtnC1CZe.{h%PѢv+q9M;4>&('~,I9n,$mz}Q]eRO;0lf Mz,F ]g pkйb1z}ZS{컮v_=¹GG+(RJ`,]qqJVXUV{"7J8m:%f Zb46[P:֏{+;"!eM{7/-/{:- 7*^7zvZj7_{}~όe'73} YJ`utkhfϑ?/ pDD:6J UH{H ^;\n׾3^9F>,1b Ŧ؂4ORQ<[FⳤrNI:P2!`mJ 4n0r`QDXˁ /۲ո :DB=\fCd)KD8+՝ L^Ru,1Q:ؙ#׊*Ό_ov$$JLF^qcDeZ,o9u'?ܴ8ghQ@[Qr n5N߱E2IеJN:0YX:qnMn:8Z!C$A$a-#d>&{.կ1,x^i`=RrP "-E׏xKVi`tlPorNIT \o}hm}o:Idkj? l4[/w ۓ PA. * G 0ѩx;emwrVM<2#g$9FpQN'X<xE/N?B[nA[ 85U N_6 RaZ#PBAT6Dmn6'U5j~Cy}FTŃ.Ӗ!M"UK琦+O{d2f]Td 4ڌi0$v@u ޓ&JSp1ʚTBPܠɢe߹iJֱCQ/Ö$ufbz mIlNTNVe[|83봍QcKvm,@n.׻DJ/F&DpA-KZE#bn%rJɌ?c1KL:Q T9â9LF9 ˺H3Ǒ CCގwN kz3fD>wUh;`w,: Nvhn [Sp`0>xqD"Tf [?֮;Ioy+_?y`ES"V12U2P'bRi>b$Ϡ;z?loo퍾NASwܹ3}.8씑!DI5S⫯mPM;,=~Ջ\/: 8*U+K å#/Ch:bhb:Kb@{^8(%>lEJ@Z;N{<4U2 ]x~a__F&H!0P J7:0QRRQYQ:\\co9gdNmb[U v:p J8n f_w {ux[Cٴձ|Qn, bXYO|s zǹz<۶eAg{W2]GOI?/;7< tԄx5ЉKcZ;wQ7٩6V?J(+G֞d1 ݗ#=eL;kew*ߩr,5Ϡ8ikrvhTQil`0'@Q8m IՇ ̾"xTy,RF&\بpsX̉=7z?-b ς𮣞s5 z܋_} ufqq$cÎBO@)cg*7_q2n@3ªWM:=~bvF\'>'B%08'Ao!Qm(:hX5.e(9"-b.^8*#hwvVk7p}W-VUdrII=Z9s/~;3>:ټ|[nkglo=}=C}#+;hBw}k+3;LmESa*n8Ʉ8$643SӓZ_;ShhlL\zxgw1~3HdU]]\[]..^ߙnSaWD\;עNtIU/Wt\q1A+Y]LҤ斚r):;NFҖU` Ti9(ZAF@d BI}kG٢A"\;)BB"Tg$.PBTwnUץjZ_#b*ef0+~s`Gd =?δ' e+Wo^>b/:y! L9v5yS܈hPfgm>`КV O.ˣNes:#Je %) Y*J*P! \9@LvE)*|aj,3KyWڣyE[7Y!E';cTRL#"]4/MV qFY',2Tlxۙb"?}]ƃK/ԝ9vt_H'@$5u emUAFřN>s{ Xʕ>jt#g:9V ԩp-@މ-."]9BЅY^Į?%+/91V[BsN(YBx48VިGt폖a2 ab1d';;B}?_D`8y.d E`CTᎂ6Ơh (4JHҁCwvv~ RM/ Q,igfԚ{ -ɾS9vDF0yQIAI[G?3y^ ?7tfo?s!JZnny:HŨ[T<0EEV,ր\wJ=ŐϿ?/xÑQ-: ]oem97l4Yn>_*| _lo\Օ  MMa?1qkskol}رgnO|?;O~- mR][ufui\8y%SlU1]U5 m?D-tLfpLr\ܥ"yvթOt 2M0tmxJz\LSwrdL#\zGX;⹴ݫΙJ-ފ]P->H!dخ9ҍB5U A7-  >LRuN nM*<Ù[%E ŖUr:/Y^#M ?A85hy#hUP"^o%S[16 #nwnȴbv<^ &kzVhؒ]#?bݴh/<|:on?z̙BCFAS'geeA^OMYO/kfZOW ~#~Ç'-eP?86Q=jE;1rH{ꥫ[WKtQiӣe= lSxG3dny ֿG|O|777'mM&yg&i}7>s8{oG0p{ohRQʕl3 '%DJ ^ G30M!uzGk!dlY A3ÙP!8F UBE?3ئG^oѠ:xpcL*h/{>颯qO/"^]`PAoՕ79vT騨HϗW-u1Z1DQ,KUƙEu8bL h z$Z~B۲?]]\]ΐ ϯ-}!k=(fN&EF[3-#TVn}ܩiVNEMU`6Ԧ}W_䭃#/BThկ%Q?$[ژlզ*'㽝+_pޡk Yg @&=q,D-S Z!J[w(Oqc y$5v.Jj0jKc g:8ʢВxPۃ 9$bdue9;8,C- 7 TFHԩcV䋦m3pXڠQ$ByGbm6SwnNmo7񎷽|^r-zõˇz :Gŗ!QǓQBD,}|*x1LPv` F6ݪ7N,p_~~?Zc'<[\Kw;}.n>/L̻c]+ d۵CG^pqQW`p`q<ӂVoo^_o;?T W7'4}! aypl&VWr/^x{n<6l&Mt"3q& Gdd-rU0M:1JBqlec5.A|P=BÒHZZ)(@T/p~*v 8IՃmtv&`_:zkĸjMcu]zFOI_<ҡ" ae˂ F4\4ٟPiM=)I4x eVT4.vrU!,|Ʋ6Yq)s2rhGi$k-C|=,Gf?)91;0`!0\WQ>}E[+SeLױ@| ާOK :1K3L&KUoxK#{!c=VX9OMw.08G1e K-[ ԩ,#˗``79NLKNY-rc1zPIV --h̍hm{-?suu{Nm $wu!7,֓H+eø)Jp ˓qG2Us  'xJt/4c!,"2bG;Ӓ^ںutg5O>S7cǏc[V^~{}kc`eNg7DɉI2O5\ 1fAK!ϡ؅Fb)͕ѡ#_c O}R_z՝]:zBg(؂P7~y[¥o}cKG6ә+eK7BX(#tˣ{Uϧ)"1 WgCTȘ8!J9D dM rB/ܩ/Oa@1/[xU\GIzPYD) l 5Rs6!N/Tﲠ"I& S I :9P@E'u8A˪dLۈx05HiDv+qv6zJiܦyqnѤ͑k7Ru*c8H(LC~@Az5c(U@EIj3AOW#tݴdAJ^=-˥Iw''W=qթ{ % Q* zUaDJ#"4RX/ocA%x!TzMiV#\`^],f J%0~u⒅`" 6ag1mC \*D(z<<)hmnE J4? "-(*t'-.-:7v/ϻn3C=8l9}MtȚŕӗ~B}: PUqSZWaF4+;HemG~{XߙO{ ۏ??W^{GoSu35]6ofQAbJXzt 4 yuGB0NliR[瓙a匢AƊdu3A1$vA|V 'Mٛ'4cV1/Љ/ȕOo)!0qʓgNs}_rU7tEDA_\"6 r P~u@uD2Y+7t&?_{ڥ~׻UO~Ͼz:ybayiG) &QT U̥mQ5y {fh]6[RVz!iXZ'tp=;C$H 3E Ү4ȢP[S3ugf]exk]e{qeъ bNHH rxNr}}.4Qt3P`/[zKӟ>6<'Y>l?m8[wnQK%\YzT~i.\s#˖,^\<8g.*9Mbl `e1Q 73i&?yjZ]:mz''n|;C=/p̊+ݺA/ JKc|wtX2%0H>=b =4;:bT%ðX*,QmMTe׬Zt=mk-7q=P)YYGk [m<Ș #@ԃٟ<97Dɔ ~|;:^yտO;_|+z|/9h8~՗쨾vJ޵w wܵ9;^]|6~ut4f[29%2scؿp+D#Ls[)ȼE+w/Or|mf s]۶V{h7Lp61gt }i*Vm. aES5+~-AUkV,]^ qo׾~ka853 m(6Pm AL g|7uĖGl}?ڲr/]uӧN>_sWzOYV:T^ yTa(48QDҰ2NK#'=ɨ@f0!,'P洪و9'ئjWUcfs c4*Ffx[=[5 %I.φV ;a DցO2[:(cTO 2d05T ]wp Ƃ uP#2<CұǏ9mmtxţ-8}QLṈUźptz:Ҡ\*!,~"Q$XBu+.}!h̡*Ym4z SzmpdX.Ep  lz Ҕ ؗ'#%M:R+xeM{) IbXfXkGie&6lYxoe [==b +X?83S;vyR`mvv %w8F=>a6l Q@bLUwYgoݴoxfw|.tVB`g hL%뉀Vz;1 LYyY'cC5Rr1HP,K֗_O~Lx4Tqigy X/fjVwRcR7>%>'X>aU(}W7W.^]S"=P@̠w3rjt6 Y;lq(fsq{-4jgO@ā8'm_9L,LTd Ma̙\9H~% ǜ0aDDUyx,*qd'ݜ_6XCلa7K|HkU,ct=@auu{۵Awzq#),pG9<ṳ_=CӳFCjBзpCpϲAK)mَ F"cɶPmC-۸b9m%\X18xFc[ghFWu8keeq

^bؑ5S7|szFmQB&QwOW^|aݺwWJp>3u,[Y*wũr1c1m)_jY*3FG)y#REԙO+rwc~tԙ߱3[ASVBH0M*'J"}}gnLw} qhMM]fݽ=Wͷ^{~&{WSVEm/+,ɸLXX$)ltXYTڹ~OL=~ZV[TFҮ5/=lherF2  y"|2Vtsa BD`0:c[JFl@ N00 d}b`Gq: pF$f[8ejm@a+D]pun` 6TA>X1vҜ;^IP"s][%q= BE6~;#&@~"يCx1LMM\>~E<$.[E#¶a(.#xXEҦL115Ɣ͖\f˨m$p45  }A2UE~9dG1MbQ+ 6llsÌR^ 8a2#:36~1dAqrFj(mSeH6B% VI9ތ͵(eX-K0g9DNQs:'|Vs?:8JtG}w<~p!~AS|N1驝wlGVr~# I WFTB+ܯ>0LLA򟲞OT>Dоk]ܸze‘=v֮O^'XfU Y,lq @ۦ >?βuraj6r;z|kϿ>O|=3(ƹRmq6;̍h% hMJ};ҳϏf)#ڢg"fz,c2)<-GlDU1Y 203#RI jdAAJjLؗ-C ^|i;Fו+\>bV\7{[_-wBқQ}‹W'3zK_-;LW.LMU6>9o`x͚]fXVP8(|KØ~~0:Cb$Z5|P4QUsMnۺ#~+V,ǫSF\,-cSׯ/\+8mcD)w1]תom3G{°X,XodGwxד=wogg`YۆUOhCդd$٨c(d%R8{;Q|-lv61EFeh~悹@Gb|tÈ}{]>rpm{}voD:kcu<˹L ϳP' %v, X*PNHy$ۚ#G}k; $}WS [G%+"#k֘C(rsWw:j%' ;cXu: p Gv|Kqא\6F2o.#9cxάlTp+e?q"cHR~0YD! C1N?#N8= !H+ 2"@#kQ,F (;RcaF#Pw!R'~+lik^ dEc1RI$x;i eVF{U,wV*!O޷3w˕ޅ 6%oC"RN%~ǭn\gtDn*pDDuT"BGqaw?NI^LX`H|?S&aui -IZ .~@Vl81L:n'Go\@ )$J%Iv:GIFP=|iвN[=YH&'B|! C%0 ^8򯏧ސ IU"u A~0E/8,}DOQџ >,4Ū&r5tX҈̤4%m- avF6Vul0hN3f(! S @ٿҥS(d V3Χ$Z(F??o>ġоϧ7֭Y~{hlKԥ&IDCXXWkӭ7,_w-;IjcJ#Cq4Mr/i8lj /Lm ap$WY5}jB(t`.}Ʊ)1a ӥ2|.F@ζx"k٪MC)ɸ1yG5%;,&% S($lXC\5!t_lYݵ'g?_MiO''ut/KwOS4rK {-vh]cl_/dV*R\([ #7獷/YW[I4>>n# b@FgIACYfDy*F\Vʝ]7&_l:44xϽdž/]TrQN+u[&3\A+\4.XAL;J}ڋ?ٵġ#O>ԺG5=;P *U0Vgk/Y:{C1mMDՌ%GR8<%$Krn*cԣ2 u2öFQH>F.#HEA*,8Nu1gE[bpt Ot  :@P_ 61!V+!kd8PR7;ŭ 6X:(3&qI!xfxu9zAomO6&)>뢛L9ynF'RQOVJyq+V|;_uJ(R3&\8K>vM^(znu*!V))v7ء5 46BMt4dҢOHý8-ghQHwTDi3{iOLTFo>h>,qތX&8Mj!VxB)`|U Ii FޕbM33疸 wźfJK$:ǣI#KD"Ӗ`i=bF*)IZaA!nI:V&\l:&&AG 5їp]D5j$)&p345 D|y/V5j3!-'ǧ/9Pɋ~sH|Hȡ6a6aܚAa0v|Iސ!HVA2 S1MXRϋƇȶ4ľJU k69a& ‚h 'MAڬ%"|SHʌhm8 n}i8RU,z* l$!^13 iْMw[YOTG+S?39o@t+FVo8ꡇ;Kqӱ8d^![^MגG@û02QLh'!ClǭR>dXO%6fJb/IqME$1Q$cĖ㝼t+ܾqyYHS٘{cb{P.E~_}{[5k.}7$9 055?E ]'inC-WŢUK:^ԑJEvrj]c^t+(wj5NʖG`Rl<;}X:桊Fpq= w8i@M+v=K Y4wC&6[2STXGͣvSxˆ@,7rqAROB.Q>؍Cʻ0rB!elԾ3"l'tr>,J\ G%Iƻ};0V<hG؄⨗NlHzkw* @gO)l/p4.ywF9#,[!-Y4s.:J% ,`:lJ&GqغZΣ%h Џ1;x.9F'`?A{K"T٣-b-W SKz Ab˥N=`Y98'FTBgy Ac^8, F!NXZUeKͅH?s8V>nx䴘DsWН<˛-8RT>>_={bra%]cIߕO\ߵmg>mt:]x;VÙ= ىKZ7(wS're6] v%8c>U3<6f@MfiJrvhdOn @'3LӜ+,^RTF^g'p8l4Id oe=gtHyt[w_9vhAHxX\1,U'T\:-3#zfL\jIݝ;^}l7n$.]8 P$$ѓ)<$&&UJ8`L8mET/{H +Ћ-?W(V*SO{'/<ᮻZ8csKNxo*);9s V֔XxV e"sa`dgLO0'FW-`T1G4~;^ECCA2>[EϿ;n|)V)Ǡr_?XEA_bv4hq/E 8L&2.[J,@nv::qi`{MxfI{Kv8U Di!9HqY0-}L9f'"wHc_1}ly@?Pph{>#8~zEdTE/u=ȴStCFx^ N5k JϜkN08N1 LdosXo+ڢف6ȏ[8;YC&yJX9{/avql/%z'Jmwl8=k۶Gv]v1l6zΟ8k{`ˢ+35XQO?9Yu|wvc[hVM !. 9+M8 *`֢2-gMFRmM>fx긘CqD Y,JtEK4TW xV;zuS\`^q`Μ?rœ> R0f.,DasUK?CrG?W^~M+WnټY{W\K? ~FZ@9ۃN83S2p}5[3Wo0$u7uG cѶW1&]@9|.PoImxbIy]mb:y7'ϝ+V:-TÚ'r 2L}SkPCSw89%` %5iuЧ1Ԁt(I7FD:$C%iC86-l搇X(d$yn|tQQ2hx0Ro}3oiuj%QY{nхf磃om{W_=wÏ]zOo֮s>`̽koubz;bq O} ~Z J 7w^YDhu`w\mJ5ST*,4WdH5ӬHubVf"Vz눚fu6 J.ʠu!ЯK}=?xMןz-7L:W0AC @Bc.\NiuthE굫V,]lEэkE 8TBnF$AthN%l.[ZWEKldDn 1kaㇿXyx?zө+7m Zʼnh JNRq~ۘtpʶ` `*7搻EjL8^(He2 e)Cᄎ5 ]yTfRW.\#3S+QT0YlC?{VKuJ#)WT@;Z}JG2$O(Q ;m*=G&7d[sCH. Fy$[r<Z60 IАa!L E e p(eR6cA.3$12~>ؽ?ƕ_׾Sݽz}_wnvA>D$1U=yӧGofF³wW`CZ[o= &fj)PA v %a[IMи Y BуkcڋR 6c#̊1S[u o%Z"OGǎx\;wl`OTvjxp.hhpavvE= Ղ]?Vx X"(ttx‰~ZdwwwL_QXԁwE5nQH*/鐤ClFQA{(=`qjHdz—ލV֝"Ɨ߿x:O>޻m;w,_-[t:3 H%4,mxS^@? T@5aG23^xfrVVjdE1{gJpׁG0lu S.^ =Icc,|ߋ㖾T>>Z-BKΜ>T} rкH݆Y3Uxnjk@Xڬ80j2u#5hB `NW68IýfFO sp6 ;꽺`dAj]j8^͔q6սBntɢO߷w`w}lxի#NޟZS$2WAG56"#C{(۸I!! 1zawۊ٘edHi u-&s R# B}yjŋiy5F?@c0Q-)^g040P \O ˬ#u6 4an]%T]z^(H楨AF;nA1NQVnSf☚=чP"χlFafaT'( P|FHu}أӱնF}H M->Q六~n |~EB2#0T1k ~;4{;ZuuTn%\ ‰ NOM7z8͌!qqt4[^*8Bz*Y&ۘ4:bEe!hvōAL&5 &@!UظmxwY3{ d=6TK,b[7(_ImHLCAtv%0}lh7?qc[=%11G-3DrΪ( G 1̐k/M1Mʦq(%_D҄ K3#-q}8HdM&_Nո6ӏr\čK4j 2W}}wtި~îNLڷTE6E456K KahcYUcP{ÄMp$KV^U\A2< xȴ.'(6=e,%A!/QeӢt_'OǤЀr[oO̜iԌ0`5`!m#{r6;ɦi|4Hm^p'{H,21RlY^XV`!r .҅DITXCx4;=4<(v @;Ɏ}64jBjlApJxS-z9}#o%9CPLQgiF\d9rܷzz0"jE8 ZbJRa6gkә+zqFlҶU;v{-J6#*Ea ؀K2tE!J_{ӓ'̦ێowGy{n^xJr)桫Ңv宮H G|쬵or#oؼΆ{ ^.'*86aaeLbcRhMTkM} _t`hT?fO(-!$ TdEEnnӿ!~O.{~/;M7 a6t E]X5:$BzIxMw6i`>VcjY516n;P'v0*uah'&&f'']*:+kԪ:(xy6yfÐ%#P)$}fSas0.^Pk;!ެ ru(TU+ly@?MK+%,98o_ߣVX_w|aD&3L Hj*>r;a.~e*Q>@ {ٌڞO=C%Zߠ<.4~$Mh$A7!8,V4-Ae0/qR!: `3f>+`b⠡-4|V[-Z4_J@bl2Jr^`.;1~bH`0_ ˰&ስĥ4vf&(d͇(i~Dwrdh[du$v'T{ĢI@3qa X{%ӄ$`K1C@8DAms؟"!ʹ=o~6F+:wVsSpZqU*x6^Ro>i6s[,K}ܕ};v~N;kV=?8at&q u\Tr/(&7PI$7wdy8{K{#W`,mF?4W-ݶع,-ub`:{{2ٶW^x>>=kg/S{<7 XƎզ F*;-Y56^-&u*^mf. `^c 6x{#fRuc#ӵ5vʂW:"NFD ֊s2u [E!32Tᨌ m!p!J0_ lV'ǧu2jԣW=67ď8{GɒKT[}C#_n>DoYB8TLuC\jU#_Q2{FmryT(۶>0Qg3ܻP^"\# Y$~x(X!C]kAt 4v%o!Gq.v#2zQjO8t#Cn7Ŏ(tV(ƄC|xXV+xN]h2A?i0_SF$GRs}kR_X4Z!<+W.s'//zlR$ \ jw(,,CwšOc2RUzXKl-aL3b&U`v SN-.`Q^[oP& N<eW(:v[P"nֱYOOE(4Đ$n]Ybխvzql-,V Bqw}}oٸ%k7["_.Eq Az*`8Μ޿o5P;1 4nSm8;5I⪢H%F:vP@¬lO@JH A̰mc٬AX‴cV{|0Q ~łG>p||/_aLBN#}KVW -{=_N_r滾}M C']n>7,VM~gJ#s6|.[o!5dr9aWӬu3Jv$+2d`~T] iwC塡> }!u:c( =?_q݅!B3ˌǑ rEؔ#y.uABpMg'gȉF2)m` j,Epl*K.ϰR\ 9"L~#4$ eT*;:^sƗ M,ca6s@_ż^?w9u8:oX)'::3]0hP968{?ת\\nӓ/Y7X*z]}[#hy_(v?Gx2 '&j7bn|k{&UD B}c6j .X'CIa D J<[Ub.pOhIG{ it3V~!aFhBG JI%(&/>Ҙ*ؼ̑ی٬kULiPIФ0N5 -@; 8<A$0 hwacBD`_@>pd@UB*j~qլtuUJ%D;QߙQ,;d Yx.#]pL%PZ:F! y/b'rTa7rE؊viqTIpjHH`w&ӌ&AxF$v N# t +Σ|>P;vtFLPIh4wuOg<֭tt%OAaƭV螏hӃ;,`utv[6r5rצ;$9[1c;ɓP1jD@ljIp_nA0,2Zz" %yHOqɸm_#=|+޲E'Rzu { a9/#Epsd钣.ڹgڕ۷qӭ6dV%~!`' }W 䊅驚e#aùzE"lQ+o_Ȓk;a pu؉ǏiRE7nџmODrjښ>]bI (GC?%6|`Fmr<2|nD Cplg.ca T%B qe"d}/^+.M>Zg_ڷ#v#(6\p-c'Ύkġ`cB€Z4K#׮?xH==]X2N{zV]|駥qqb9Sq74΃L(%Nab.*خa6&pDf`,sȘ {̂!h$PUTqט!8?] m}؞=p[,47£n6_sW8wJsv ځpV`hނ}CbV>mP8|3l{]I~d7KVʼnJN@)<Օ/Ĵ $fٸO?)g\reI QxoT\A'[ne`lq墭pQ ]ݽX)B* >z/^ /4)J]==3>]r< ɄDi?$Q(xݓow LQ` TⅥajA {܇LJ$3wt #aBrQF!pF7\+) ea ǧwQ_Lʼnc%) `-i\:`!a{ZB%l;g!r7_HaBA.֛ U+vsݕ2HhIh|h4aЧdz .h! 5(',Ia|BXkISe\3+v+lhei &)uϩqcB‚xD\KHq8*>$;+mn֛Ӂkݝ{oz72nijŊ;6otv\]fNow٤sG>>QY͚| 1rZe4ƝMWp-cFGO\rft~\Q[x.- ){;LdB2Ħz ^ ~sGO Gl<_ *M(tLy:я>u7 6PŊbX@rcT̕fm&[ƅaJ n*w +Sϝba#ҟ\蚷xyw߈0Կ+E>&D{!p'ibӂ@A6ePL]?j::{۶9өʮ^ۖ\=xd1v% f*˂O-2b:d`\鋎tItdz+ |%blrl9R66PB56moId HR! c93=[ca ,NjuB SsjPQ΂#M~!8qcrb|쩓Pjepo8Mu# ;G3؛ڈBk(k | 44CDPI`k=OqL`h*c+ 3kIý}-AqV;lQֻtm;|B(,Bs,@1"A [ZXw 68N: 7ᒡycz q_OmRb[Nv5N5t`1HmIIh3Hs\;ܡO޻珜Xo0`PmC}C/'ᄋlKRP1A 8>@HK (n6i_04㻖0 =Ů˗nT\J~`dpK^G[MO?ŎN[W)9A_ $Ԛ&MkR; F|wp_?ks9tL0;tQ2O9EbTb'`a;z zc'QB y5\5D]*70qUQхVETIbHPu0$-܂A``IeR+d6>PF)\h {wPaU& Y)_'ZqpN+6z^%ҁv"a`bƥg jBl&吞<E8#l]hSd8W E2:F0@ !L 20`YMIP U2'idPdݣ{n I'ޞBɇwZN@rźO}8y=ׯ]7W6<:[ǿ_qvx OwUy~_ozd{h(EA(T)DHTH2LLϼi>dx޻sW,[z|%" }AYmts[v,]tbj6?+9^6S[vVԎKTuj2I`'%$6*ȳCnY.J@^B{Q?yӖSNnr 2ᚭ~Yg>:TՎ]nO}Yh{y֪Ut#jj-tQlONN)'&f}g,EQ15RD,I6X.c^mSyFR@"48hY;gTE8\^#O*\ H' #O>g/h};wSʆ u߼u]4Tq># 8(AQ81 Ovfbl) VE2ɐ^uQ)Ͷv<JbT dJ a]KҙLIJ,krŪخSRU`=vN+.ر<>6i[gl@R}V+48T;#VBX;S"0Xi=PA"r,(q_`F)ܽGT(w;)!)V$vgإ@FTg [LXF& m|g6+{(,rY#BOtY"Q K_4̥b>=p\l! *O=! S;t`%,ӢSr$ (vchVskn8o-4K,tC/\ErMcϡۼiLqx+a Ba$ !ZU @W=ge zϬ0JOxH֍oس`^[m]U۪m3Ͽ'׿眻{~9_8wٲOmQO&\"Gh{5(whݻr5ٚq2ٚ'#^uj[+9ۼV u`v @?!J}> , Qxs,4HU_#eeYgrZ<޹tr`%U T2>A܃j\ILOڼy{iznhꜿe˶ޓtcSlYW8s1vvn߱W&;.cqCa_kqtmizCvv1FE-=[PrSpN2gW}h.B2%aI*4-u2p z|5_ Ε+lmwvq_ loL8ަǡw8gAQiwd3`;Оf(:.aIʺMgj+';/5[_/`1n?5Y*$٦h"Ӱ^,Ae97|Z4A2!NǵLUժZ05m;6 вXg6aU9-D@0]\aZC W@b*!F y@;elNN^xu5&lʕP]n`2J( &FH eT`DUQ]hJ I a\4ዱҊdXG՞ ?M $JɻݞH#ő1ձ<KĭXAMk쮞O\xoo~O3XN;̘#>GI*YΡ"LC<15@Won5yv|%1 8u6(B iz@uqhaOYj|%HKW&ABU9AsEk(p}D}Nl9=$so2hy.IKw֑뀓wy- H(-'s<7P o"eUP'S\ϖ5O VvuO8hPKBW8~TC?~D"s?dt|x@"ddibSs"+a$QMD%[^A; Ƅ(UrM /-RW^y;>~}ۏZV*Smmm N9k_W{2K̙?Q+K,gˌӻwv'W-Yb# 葲δ1*#2C0<4;.8dn'IA%[֎#/IʶcޜysY199 mM%_}gΝ31STS h>|D=V%SD6}瞻ٿ|~k6@( to>z=mknwN=M&|v\r]sn,# /F8fOdc 3K (¥FȇC N"ə4%ue`R#j;; NA b*9965ėX`0dr (k5{]Gl]y"in=.$B=3d2 =tU9T&ANm+Q躎`(1$v+.}LL~DhiaC0; O[qG (K>P^)O;n_&V>a )A_ ")(*vٱ*b^(*r\Mep4l.4V4V΁%pI;*-R<)1&j<y'ĜhVQv)»&B&u#Շ`F|_qEPXRfisƪu-]m_zRBe3Y?qbΚ:F:J<<|pTdn0NrpeY_zI*:,"I$#Vvpyb!i&4ǣ8_,S]I6l׻ PCa<XWY7K(8ՓɳLhdG^y-%s誐!ks$4,"98'Zx%*E8DPHTd[I0lgR>EK?}3-*f4ÍIjEd>yO)DYyd{AP  ӫ[aI -,\|諨8V>ihwxPdE}*P4FYz\tÅ塐cE)+m*/=D:6 ߃|~]UO=Ҟ#;7Ժcݏ9{n̋/ sld.W{xPX[ߘej[8h&\ <p9/(9etK.BQs[> j(+(St&3V&p cb:h8sa=b5Cg,$'-(lO!G.p $e F(L@%*ݤ<yV܊uQpi[h !Tz8AOtwbǔJl">Cħ5SJ0O(Eƾ:Lz]꓆l#/;,LxK69"ep"v.iX ȩ*SC7h2z'JdzDF c}u=[WL ;U3-68H8%TUn,l>']%E$>>gL]YALMzE;b(Ifly@1b!ےg+88:\,nmEcloVn9mb aym͟{ֹF BilA(>wf ldhngg,?}%;ܦc97_uʅ۱c&hTLC@ ^{ET+q@M(Ԧ"&+ŽC%̗+6q k?Z..J BpImkrCڢ޺?+%>8>ת1K lmDdZyV,N,ۖ[f-2T)˵agl80G9v!Ό)A!n!τWgj+PS3UBxW'K {n_ GX*ΤR1pДX,6^?r䰩j, Gwss߾-Gf=~l绛lh+C@KɍҺrg?sg?;-ux=l^r|e|/4w-LWK,[5Pl.6|Ȟg[(a.IP|2pˢyKmmp4ΑI>`AG+ҎO%)v਺%zlibhhoPr\=4/TJeͰC4I,7 f,+ j꺤S2lyh С߇F5@>+>} 2CCB Ic {?ڥ/hIhOVuXp2a3(谼e\&`T=s9&(MAhRq6;p*zVexUЅ^tE4:Ju6VCU3Wl]r U-+>ES3ܚ@\H+t89]HbA5VZj a)[wn;v&e3b|%)K%x}ﺫ57.?g͡G}vy7};W6<:8 oEDa,(KGXXl(c6;֭)VYs3%)<Թ0\޹iɥi}70N"I6", b1;8Z9g>pG!$#q"E1Ba;8`ּ ;AၪABDFIOr$!jQ|':u)&ƺ'F Gӹ|6e)l#~+Cu Mr%3k>^@לlɧDS%b&lm( ILھHͣ&6%N"zaQQτf*YNLUd7Ů}1vK[) MP_-?%nٵW^ƛr$LсP8 $B.Iwl}p$ʞg8MFl _/9VR)\T_86SgJ[c7_qӉHy姕9S D23m|/~~W\q߸caT\r<XҾ\h@\5iflz:Jng'U.|ԼJjZDadxdPp+VXCk:sFy]tճ+Dճ bdtR, Rx0PUJ‘ 2ɣXl!d5"Ug5K TrQ7ǐ&dL,ubSWV=A(Ņ0%rk &\LPW&g(["܀%䗡 Kuc A Y--8u@G1ٿ0)RJǢXPȽ09D$s^DK,0 M Y;~] Mm-TdpJz)ANWɲD a#?}7L gc$ag*W5,p'ܘJIxCuׯ{BJOq{{?dT:m6 sK[7ֳ+~3/fkG& 6-X2{OeoVyLwt K/uu9;³[^ijH6JiԀ "؉#P 1T[`! sؠ]9 S#켍ECH+ۭi= B:7"}hytlSkjt՜,LeT5,|Reϒ\J7Y]Y9 o/^*w[oz]h[0+|d<ҔZ̛gFXyL0KGf{ϯ]w a dErj{{{z־g^޹u;߽>y0㩸iDPJe=XdHѱ]W] F'3 EL]mؽ4$coK_p:R؜.JUdrl6Q=sgm.Z)RT@kp:KcU+HEhNN=ytb|lπƨ?3:pL)UP]1Ul?Odd[ )CW_'9pl-jDr@bO,g깤m*S.,ڳBD]]p2!a\L@p$A7NԈWIr YNHcۡ>;vR rzNjSl8"v%k Ǡ |T9>HKKI[֟(fm@;-);a\Uz'#HG$*'$|t儞 )c :?["m * #]NHl{e":.=WzhImQG4ThG$HCp/O9UUȜ 'H~B5"ëHH W}cғPUJ h mAF42) {Y&KSe-!gJ t-fXTKeP,[lFpl0~!<\'UM]I&UC|DOڞ`?4G@\ZB @BY4 E;_RX8l*>YXk:Ӻ0}]u5,w:w׼9 -p+.KNЂE_{vXǜ6SS@ P,FMbFjx蛧ʐBBRoMc4 ?pOѱC kj?wIcs&RdZMfX ϟבihPQ;w\rPCPr * 4c`_ƾ8~;S d!UAbHR E$˪BU8GhC |:DSs,RVPK"@(/ LHBW8C@)#%ޏt`[26Qq24>@U 'q_E y}ũ.d8sB0`N{nS;{*P**['|88+װBG9Z,삆#4-1@$=iIUL+!=k5IkX >QYnh"AJY,=dE+sut..`2bmRǍc Pd[0yS!q&bE|@GrC4rGzM@02ȕcE a誰F-p[KmFL.KV̒W]$ #Z<[)uy*SW0Ѣc} FXM֨d}wqMDWρ_ZIzwwVNۚ[/WYLDTAQ2];K.8hC#Z d3ۖW)e盆i*8D @rolz`B6$@vښyHP*H_ *8,%(%˄B9mzvRo{RpP0d["(BF8v~,* x؁u'ث$&jtI=7dAL2$qrQյX~J5-T-HJky+.些ޱhT s" Lt#K׌~xsOV\G=N_u-7:ȴ0(C;wwj`6e%{ݟ_kMDV9+ܢNK@W9i( !O>z,zt>Cu33<>Ͷb}Ix67 XT` &Rdb1`` <pړ]%p|4Y DQF6U`otyz(<=Rv@T$HZA hu=a=2\, L>amhF$)͔EC!>&T{ЫtUеKRZ24D!?Pr@.:;VĶ,QBg[v ٸIBPZXoxJ,?sСT"O׸+$Y|$ѰUYQN@'2O%#tSF()=Уw~ 5f}פ 4J $ AJOڿVv.]cv>+!l:QXR  (ejr]8vcC}"+6-OBbh:%fTs:iPzsDPhhj냽 hʉuшޛLNCyS˛.,gIJt>{Q1xmz՚NpqQdV1a~$H{[ X֢"td)¨+B 6J($5tX'A(E!Y-Ź4bE8o*B,TQ@J !)FQ5B=2_n`2@ݕ  SFB/0",|$9 H>َ< raB]d™"vbX6o쬉RZ$y}οo.\jTAa]fdMyO?m?g?u ~mL%m+Lc1V\WK*Bap?Al9_۾?R8~ofx( $9];:B)ÈJX\c^5cA$n󋙬* Z\-k8oɊ~lc{(7'u2`g?-Xw܅3YpT^HU~C 7D')4h# '6X!+*yU}N~7Ď$ ^U\w+|hvZ%-pAyrm^ XD ]>Q BdLt9/b%qʚjk%Kځh+$G8pHp`އ d:%*0ZX9^#i65Jތ!{rg9PID$a!h\XS1|ăx=?nO_X!eٕAA=pTCnB>+:KH0Yڽ73uɐ&vl)B t)ؾ#)Dz=b)l~ CCîe1#D]ՈW/Jտ8  2>| AI)Z$xꟘ=7>1vĉQbb^.fٙgYlF~xl{# ;jR l=4_aSK&w%d2UM&do0*˃jdTⱫ"jS兢rx ADG6c)U8h?FAx牍 { ~vd% % Jtm'Jj |V$.V˶)!;$#, Yr,aH>*'OVJLe.)8}Z<KdR{?<}s,֭>s+], ]p>v~gx䕍{~7|M7xlu^*fh`t2YgR G';q8b>?2F5}ct9v,(WB~k\y9˗,ҋXfh4V. ٢mҀB7$\*#EF7`ajuF RFrNXq5W)==Dx 5a?" xU8ŖbP"7BZ<qATNݤ>,\Щ㻈&"%!U`*&/l\.[u@H! ?aR|AH$:6>*.;4K2?@*5GI9 {v^C2 tX(H/SB,ScSS]Ih i UAb)U(h*P5[2 'D:v;~[gӱxv=E ,&'K+>v582ၻ#;/GPL60Ԋˁyd}=/oh1UeP$?10kZuv2Ô#6e޺e-XB/"NLiҁTZBQP)f1kٿu1,G3Gǧ iËFspS|2v֢W^rU_ܕ*RщzO߯ʗ\{.OܑMԢAѮ M|@sQPR)֡n$@ARE3]ĘQB5-j ȞcBCgd:T9"ю:V[t+FB 5,ܡN$Z"a.DErf{BYs=ԍ2T+RUï?|^h T8JQw0Q8ԭt%3ì >96Ïu-M_+RCx\FN-eEd*I߽WwſL^֯ lK& x_z(U7BSz{Kfru,H9rq}ޢEE}> 5F ;H*,L4RYI*󾬎MX%BրS cj|nh8 F 4văNyP(X !ʪ@A.$ [î 6 4:[,F"uc4S&HmgiPh!l_&$$Y.$6Oh\%< 'J1 yEԻр^jOZ3bcc}(d* epU_H(UY߬$+. >Ob$qz'X$W_{r`{޽D2UnP.rͅ?ڵ?DmcÃa@K L#k:[b {taKډGؐojktTe?O G';O]ERa݀Q>%s:O=4v.0x\ێ TjX?<#u 7^w7 3{H,ubth?{8Ql9kK>[sYs:RzgO$TEoQlwj[\O 5|3VݯX"2%蹳ѱE=U,PIHc4>L3f6Uv9J%ɣ'o/K>w /m۵gQ{c(C 5hX67TTXxdI[ٰw,jI׵6YNp$p$KcAB} mTS2!bY8NTښ*C%X*O5&V&\@A"̱a6naM:YMDgAÂgپ;J!A!) i`}-Tt2Aid NvG_:G>(3(  ٨ˍp% mc,5jL6(Z@`u" 0:Fx0 Ec–7!cgE;qm_rc3Vw!z1LCӇ"Af.kɁjP}:K2|mOǏ+QMIg@fOEvm,_o[omnm?iWf:/7P9>&#:*QGfg_F+VLxo7z$ZUIu=cGXřFvtǓ1׶MUa&-VJeƗB%(j%[|8R\\lS4~־tdaxp8d4E:6l;:Wؓ& }JIM ə5RWh [pLdyp mc[ \U@KьĤ AA.-L@g%`Y8zASĦ5_8SXHB("B`yRTB|@ 9K WG,9.%=WcD9>*LRU(G4AW?]S /ݿ>ϟꚛn3::Q,MKD%&ZHfR㓅'GOҟKekO 'rԒKxxlk`IEpfIЕPCW#7poA^-'|pqL$Cl-BRIrjj-ml>%t>6V[,]4{wW߮7̫ 57Y5ÑH&XS#=uuq[jnKGZ|.kFb̴Ա@'DlB~t%9 ]JJdeyhrBesҡ%Vۀ7 nDX ' HSI1<MOL$`''8%bK\T_xњ!{[c[m% d{u 5dbbA,(C\wGF8 oCFT0OO8Gbľ[Eqו+n_ωLdbr=0ѡ O>٥YU5+L%\l6lxut!!'ggFXF[fj_7SO?mjjz|lfv!w wcxNDA/D`()ڱ)(-XO*V$Cd`wOwOXadh#l%9jݰ]#CyiBN̑G`a<3PWXOgJT[X۳k77i^PHhhj65)gDfۼuMoKOnΘGFe˄a_&1={wYG.’JCpV,L BeOlQ&ЪpE,*U} ntp4 /ȧ` 9vyC@$$[+֔ >j?FIZC -ۈމ"O(DD0lyBVBKqm/e ř(vNTB`т+WeXaLTG': ũc'zYsiHEZJ5͎erϦj 56X,\/kƦ3{m߶uv4aӪR&@NUG*;Q@)5t2/LW hܲ"S8 Ah!aHtO#>Oj&KX.`?+tCv9K#(gH8,4A A,/F+<"d)03Fi+}\O(%sl1:M}p(W2Pۉpv(磶n @3ǁQhGF,ZK@gc:$f(`0VVQB}'wLE ͊60E>R?pqՌt D"wqݿM#l4r05ei%/+=a۱e.{nD"S}g;=Ҳ)&.(Նh-*޾I}l {u s:T(3b[Ky`ѣdTu=, )VG#U+W~=u5 )v[[:՘we\||,acX$X1wNےEs.ӺnzXy351>aU*Xl:Hu5u鶎9'o):(Pw&S:{QĶJz>׾&8H<gt4|^*drB, KdEz;СrC"WZIW;';bN4:*#HP,bT+reH4pr'fL}Nސ<q5[^ YXe M<^z䡋Z|of$09A%lkαJyxG{?+n9crXDqU(LJiRP8 Çk*!Ͳ껧DmnTt3IR rW P`02~l߸qZ=lIE$7wX53λ !S>cͶ4u$J_@$*}ĽQ)Dñh̀˥D"78|ɓ}t2ʊzs?􏝽&SWWv}C5#+8''yez/>q td:Y] 8h{놭],=_|R: i0؇.:c?ˡz _HcC rdg9{/``Ң ^-^vt 04IQA%z*O| ܓvB~j  TKQ񹧂BSN@vT\#H XHʄ$lGH}=E&"t%u0MEt' X+ P򐅦iD4ޗfjF(h[ϫ0Z!*|ϥ4$@/"sխLg??ߟ]~&b9km 7t˭.)n@sBi^njhkliok>vrHh@6q E06صjtii\|d t 9+ S)W\Ǣ-!0>9T4(Fh4:48s{zt<5T.l>[ \*; Tчz8ݐgߨX6CfI|ϿS@-E/lܦOuYãc#`EnI'.2^2{+5:nؾeqG"^|lKz(hVBh ȝ *=FBVc,JHDdЖ`V;HIfi*JB/*GBz49 ?V$`nAL ̸TV>bK1cjEË؍~UDRn[8r] @m@d:}`Iʘ*+uֹ{u{K{S&BYEy@e<Fy^_ܩV\O;<[& @`9<"2&x2`O|R[z/Գw۵_[+2|b*:䳺9zo:[kḩ>%;pA04#tMHw=0}3W]v/|佷a5VǒU' rHUv"SVOϿbNhRCIixUp8޺bmm[tm:3Y^k[j ET+`^J3,ı-"MkY{vj vʶZ):j!dh /Twi-AQhUMMs;"A*Q( UMl!yF- ],UIUI^ A}1% j.Q9- ,v.Y55ٗ]wԤ$tKbTf`x?*^._9=]￳molF,`io8J&_߸:u8W[?R榘^iYܒl.=_7RKr.3:%pc]#}haGpݸyoJ ,c|"z&0  pyBmt 9:{$$ܽ(܇ Fq-LIdv\Ǜ.w A4H1}\8}='uOkgk߱|žwyٟˮ[r\EU3]_5E4?AeGbg]=[U ;0D,IY $i__xlztdrfjXDxf.^N/3gzL&3BJ@ H/(6E޻UwzweU\D H3>sy={ 93}8]9ڲ- p#s !\Cazh.w Ij52mP!BALnv4M!L=b͞vɏd4 qȹd2CQ()ܠb':)ͱǫPE480H_ 4X2p΍!ABwgk;6{/2IGb쳠Mj3 .~Lv ]dpz,뺆cfI#~>ٮYj d!]F4@ߑ! O't;xKIsn ʑC)쳠#+7!Йl^LBfh9D'_/oy1Gө8Lr@z 9)"QܳqSޤCJHXbS yaa?/W- JTPE>d\ĻP\@IM*鱈8U D2Z6=1RIPHQabMрj ߕ d0I~I4_x6]|>Z1x~=PP+>΋>SYX;ڸ zi5IW( kqM34C rጄ/mq^ _i%%2%\4ߣ CvdoHh)[xлQF B:NtĢH@&0Y0eVEәo?~޽|&y9n{㗇>;gJ ɨg53)Rf)6{cWx|oεkKL2vl}_Z-M>re+[M5?w8cAZFY{2`eDy[sVm$p!t}%'7vTnm4Xs;vukmM Yؚ0:85e::^6#pUZVP%#]$IFlrp ;\Ģ6t ?dM8A(IG`'6h :W JޑZyY!",J 抸$O 6 z`ҰnQ~90BDŽ62IK\~cNN4aa dOudEt>lY[x͊``r X=ѻTTԹS1U5F̣A@ȣBۣv65Œ #!&|z 9 Ź{ D7!f @PЅeF$/oɳWJWMCC ơ3t斺cJ$bY5m\\] uvaJӍj|ɉx*y9_.NO\sRr$ ]R`y7\t{nf; X8lP/r {Uƣk..Tn1Rk T&T\n@qQܠEg;z{}w]4!ڃЎL:_`$oR%3 /vٟ?O~sBZ;:Z{Ҟ߽pͷG?׼k6_PCf&ћ\@e)#:Dy98^q8.-#`I&Lկn[V eB[ IȆ@lTp`DBk KVP-.y* N{>#3ӉᑑӧVuu>nk{˯?u7??\}BX`ڃ*s)>,i tL]'Qr߷%U@˅(I'&&nǟZT?~ib~7~O= 7\PD*ׅ5)Zљ޹W_nJt8f;,ȲnaҝJ6vtR4i6M"ž+#RŶ]ce=9P,B' LtdEP  P @tk5 "𚐻I(HNX{ jЖJ.RG%ࢲD% ,2Z RP> 32f$R?qϥb&~UX) Y,DA.uH_G  irxi|tLoY\ZZ;953tyXե:{z[km[ Nqo(ZB%_U<5+^lL%OSh{%ߋ;;bVGh@ N"TpFn޹0v=ٺ޲0 y)x=VHT9>@֤Nqz)rMH6ggy+]KB>_1饹gkU}pi~?HGIrj(B@& b+>Ɗ3 z=T^޵{+_w>U7xW~gC<>ϛ%YQ=}PHMw!Qw+:b-λ5t(KkbҔJڸinEl#i_s k09msԃMGP-@vE KƩ0Sh=E6؀YU`&  L uB#klSfGF/tuFd9(pp3Y"Wnh:sl@1`wKt' &z z:HN [.K*t*|.""@6=* Xe.( T4)hm Q%`Y0QPJ}^W5d& 7v"Bag,{+k\t}tE$ eoܹlk 22Eos;0&$8jJ< ,=U;涪e.!+$r,O/cnvO/׬_ɦd4@!3I>Pt? 믽{?Ta"(:}z- gÈ-ǔمL^VH$~+CC֮&]Z#MeY~ǚZXԂHJljC"ǎnju}{w:V4;H7XZ92= ,:NUtg׾i˥*\ *ATBJR uCXmMƖ=;?/'R~}'-8>7V?iRꇻ Vq|ȺPԇ\AYF,\f*BpB.q 4Z%>1BL@pu"$ ؀@P`w䩱j)Hx 5[dw~0qq~K_j]{b_Sr Igg,ǂ?JqQ ) oe.nO4%MOJdE$\Z͛ode<{o=7?~js[7t׾/Kۑȕ߈VKs%TIU|m~k5d=kV>IDTbGSCI,`5W.y'b-vh֍mqH.YhZm>A.LbbP,`Dev2v].aSBORpn?_ļbwHXza2XRa CUm#Kԥ*PQ׃Gb,04h,\6D :v!! >JRp~UCmEEKV6V#D@p PE3HX# {AT\F3ΠB YGGTݜ$d͗|⣌nbE*v ^n qv;uEY1VsoQ0*;76mln&V]24WRAd:x 3G$*tbٞp1х:8 Fsd!S$ //J9D!jJpv'q; HN|4*d_i:-'GF7FLS_Ujen! ,#}g?ۖܵ Ȟ.ZKoj @K@H, 79bO֚[=osydtSGD5PUEpz`6Ba|cKccŞ=v>|.)'Dj~գItv];`dž$i[6Z%q b "* 4Gn)+V_5x@&Bpi,8S[pFt_ťwq+a`XvTѐ*/zf3Lms۶y)9HgrZ_gza/&`%$+ ѭJVFKZТe O#Dx?0 6,T 1EShL/֬׿>:?rͺ\w^a¢R뢪,:+;ycgGؑs!NB2לּoϮڰ7^|%+%SfOL,+1ׯr&.ulr`-&sAja\7IN:ojj.|پ';~,jv@T ̀##s<&!,2Gh#yNF!T&PUMB;Q$ZVi<$]W5WXf)p\zm4gix%%!7vƉO.w6$APܓdM!5SꑣΏ^^y`f"?9SY^P燺:W ( 3(/Iu&HAQs+u֍18PDE#s]SL(Ll{}~?'^V/̡DxlG&`46E1^0ՐՒ3z_5ZUm#EᔁZ͎ªHt ϮoK7䐮ͧ5OS4,{,C,7PgjsQN&cZavz F}+W$ RVA; p!S LqĎ|Zћ>'Qd$%Pt n{VjU,qJh Ug8d_c#S`nȎ YAX5q:Cڠ@jtHcRȲg$kʳ&as=Q0 ;ȳZ +"gXElzthm_N,8rCaL\"C d#odweLT,jdn)lͱl#UrɭgpSQ.ss-;/=rx}Sn"Nv[B)-(}Ȟ ׵2rڮT6Q#'_J6`x&śN*<#.546ŞVƲV2h(!,D¹78bvy<4خz  uE0XqqJY >;13c %eMIH INdП)18d[!B%(K0īx08LDQS% >Ƞ36I]{/L29cV,WGigFGϜ}IF\hTt! TN5f@ꎍJ@ZB޻;hc-.}-._m$Hˬ|!qB& {{VvMMN/vE'4SF"Yl*{'?Eһpx8t)U쏙F}}s +Nrw\pNӔXda_ן_s ]& %X:*b,Xfۇ:zT4jhc<+t^wnw!GD%nI%`5Эt>{:ө\A)rA%eXBR؆Z`DNڶ<۪!Mu0M-U"d1טӴBƺrB0М.ځ }А4QQ9UI~Ь Q`HJ2nxۆUg9\eU&R,O`*G0wY) CB Mj6pj|igPgH,rȱmz`K >JBœXePvcR{؉g6G1UWjR4[U\ѱȢ>B4 4ֹNo۱}oV5v)W08cXTTE,.,g'r, }{Śu׮ڰTX(",$jӵ#5nǪ¨$END r2U…Ӈ_yE/$X&a2QU_:r T ƌm T! Db ß_|;븆2ҽ}{^58M%l.,!T S^UPӄ[,ץx9>wpYqUXe_޹5+88XtvV:tثWg:ڪ*E!yhB-,qE ʲOa 9=nN.ZLщ9 !|ۨ0aͣx@ңM ⢽x ՉN.1i,V͈cd5`IFB?`(E~>H 7|x [ C@=YK!ת8=&vAX#. "QC;% p %Pxe<䁫&(=R M$}B@p0zր Put>2g%$y+b263* ..kh '/7%)Q = Kr<j`$;wyP@P b@ `/-&k2rCtNxnx#ЈFx"Z)_RD{܀Uv5+8Gĕ$?K#G/NN[} k,Us NC#Z~w(sFb/uiq!頯j;rŮy] J$nz"gMcYAz}現G]w57lJ%,j*27=W UL$mOtvJ)lҰN, 3w_uǿx‚Sɛ*ȇT-Fwⵈ/hY2Y(\({}q5~C7u4\,_m·Qp-o9kD}. rXHEB#\dET%_;3d $Μ:oM UXXm.uD#KaaJ#f"_1EQdp \M΍Zq"")D=< ,Pi 2^DW}kYM7w---- Kr&F*Uy%t'U8+aa=^G8"q?EGHGy૤Zd:rkkUH%;~ٷk ^{ t)%wP"닼]B* 3]3$+ܺw#G4e˨hF Ɏ@ "Mٖ5%lqq`r&uv2p<誰ux,_xQ́yȲyDc} xm<_J[*np%$k2v' `q"N>y4v `ECH h"N{!ъG! < CHD ISG7#2Ob*0YgRkm|Cq> Ϭ́ƊK/hBK$qﱘ#՟UF]籼r踻PF +c.O % u45y`oK{+S3:m٧(j0XsU +5I|af辦\sJA] Y`hL}}\/~ډ#o7$P(pQBPuZUrn " Rs{X$r6;g_9KRiƐD<&7$q. ,i{>ΜaWU3/ +b+P\ 0c鑑Soڴf-7ݐ5-Tmʥ+#/K:VSj=cD:V#)ߏA͎ XwYɞ8?vbqc+412kK#}{??)*G̞#b`ekv5잞xWgZ6g=_IZ Q8sHjfZ X|k:TVQKrҴm[ܺl&ϕ N~e]yh!*H+eg(&wP 4fE.Jf4||ʕH8B0(={ EWQC,HFDCpM*X>IƗl>p[# kXѰH9 t!`&=@vp JW O1YJ C71S؉@ 4 4tu=k5jZ|zv~♤gSqv3XG@L|nV:vIzVL.U.N-)*:ԖX*Ybb܈/zBRɪCWOִT]J;[*t<-@p4Wd<ε6WŸd=22?uX olk蘚[2Р}, Ғ0A,+X>{K/o߷MTTK+YgL:u&x"ҰS0lUkҹVj..,Z ٻ7;zwnqsB ' }ͺs/ܓ;|9j$I$tnh|{O| _._k%Y(~;|h?D\ L>L(*l*/ KKjN TR2\}ͽ7o6Pq`P(ѹىj9o(&$/ /\Th\PzXbuG_Mwݶg,wKr<{b.4d+C $Br|YOPvH%p]}f$̊3̶X}}%ũ|TS{g[Ww]YK.PUp'PSC?[A+ }@  oEdЅ=69@v]]uKvx'YPED83&җ/=x #1vRDfu=ڜ]շС]퍮,fk6\5dXjji-$4Pm&\ M "^H%R Mj~Du#Nܔ]Y&q@4 : II%r4g=+T=. sqwcpTv @88PPeZgN8GՀaQO t~U>Z$ƒBi!zHvnƑr"{@OG@uam'g"wZO%[}Y6Y2T*;Rpb M~2i"!g1yJq%ί\a~rWm2s-%g"r:`~o?bo9ifDZ֣Ν_zɷ7\c I"9|rHw3"F?COȿ .Ρ. 'ND~jPbz{:zz 9vDX.R#X爲Z ~n'D BsV!UXMˤS+%GkMRW̃~O:ݐKaOL{zՊi<d PT[kjH>?okYٕ5!H[b̠&+:Wg{| J9@b/CK1rI'ŀӆQy[Cי1Ώ&Zè V {k_DX-748߳/Ir;l⪪2X#"#oEW50qZUHE7oX^cߥ뒏"~PC+aV$t#bPme>ҞAyI(:,WC'CrYGB(PKRE&[sp9 OTM?GmR$\dpHKӦ=Gs,hZN ;^DU=.,l0FԬ:־{w̹3E#Q8(6V)bv|Mc. ' ,]4&шv$g5;wnli;'gF3z﷝϶\e2 pCi(j.K> W5KK2gȪrF}H B ~ 010ekylGư$2zTH<  b޸AhGUd)0*\f;v6@prQHDN|Έ 14 PH'!ZV:$ `?#$9C3"2i]oYIehJ,;B /"L$%?[XZU8Y,^F_ hS}ovȥT.N0|rr<`9{G?ѫ/m۴?ʗ7^-e@ t5Bxlڙx|嚵jn?V۵H梭,X"~?n/|+늵*hHbw$! 'ٕ יbIWzv *}IղXC(@q,C>*RAok81ZޖHĬù QȦ{`ܛ8I ]ʾ4 7+-#f5E*Q؍Xrlh8I ?sb%KnF.Oh rjຄAhp0ʎ"%HfQŲ#T}jFMʀ+.ٳ@ I< oH|ۓ\OeADuYH ꏽcZ)ꁾƋӋS31$&yi(5^BZpX9ks{88KF̨cAT~O~crAƌU_Wrp͍ͬ(\F (fF";vؽjFd5rl@% _u8Ѩ2E61ꕝ`(N4u9:Ztl4lMV[Z;S~_>X~ڍ%M+T*t̳WZ R.m6$_on٩]ןz+ZHfBg, &Z-VB~ɷjD]%؂'Cϳ8AEWi&]&vHzgξ}$"s;^{n~n~+|"d.-h[ȏOt5%j~{LX+k:Wݸ{銑H+.B̚uBɽoHۻ+z#7Rp?cnnOk@i%mwSr.|i`>o 4.T6x2] n4} q 2HAfN)NkC .IK,ΗUH2La ]NqV6GA! jr}ͽO}_{råܖ/?wRD6M^pBEU5\҇D$uQL[a:P_<3!G I$Ƨ_|k‰o}-TD1h8Q"!}jxD[S6[RjW@ã@ @DײnOdVDB dB"`Ǫ#B $T*4CJQjc I+}2gF=HHHpO2"qNHB{YZUurrX~"n2d92V3 T F`dCʬʿkM1%#CEܶ"50rP"pk'ƅ%>y-y|PCdAB!䪚ħ#Ϧ"\c# %eEΣTyзrEG鹥%vUI@^4ALpif01vQUu/&씰$`ܖ֎G} 7 ye|GB|\atuuo|-OlDsiY7oپ}H,bU(Vk+!hϊDX4if"&; Z:Κ+&inř>W]uK; cG{߽ nܨrX:[}G̙-u,.{uksMZ-2鮿J_o!AFl+[oTcJ~f6L @: $J sE>; Q\`vsNصcxЇ_sUQ.V-p.yRD5]7]5p}v| -SWF }f&)i?p<+,p\." `ojDaej>Vݯ:n]?O}{Mi7?Kzp'~y51ܨ A#m+@9=ruZ,29T8ӈ0MeWļҀ{R!­DED%wrux'@P8 ߖh{ ]5t˶wao ^Gn5i@;>g?P;0sRWC5ZG$&@*P&È#AQwj^@)`Om8 }:@$ҮBSwLB!D@bl.@i[Z,O^:,< @V9n/-x6;YvZ !:Xp$auj7qc%,0aU+}}4r3#^}mߛ{W\iFZ.}*pDJHȝbA1sοu٥Mh4ױ\*5uHp@Hǒ,"T,eaaW NX/d&mkseͱa (C1ZkDf11v7O&"?k+8ACk;h Kj3cuY]HixoO/4jVX)N-Syl]Yj8.Xh&9=v怃ފTS"F֟z |yo햛owWȆY(@"G貮6:6?;ʺ. 3٦F3*PU죹Y|)XkX+ %j\@Ƒ!Q)fb@%M9GF69H!L @Z;%ad|^LUm,. "!ȪK~px21WJTRLہx;@k?E |QPEUA?  ?O=կ=ƂRV"PH+QE7mp7}.xN-+VPv?֗nyʅ=_w<4|@o*VϚTU.B*J bTY""9b†" ߙt:.,2Hs0>E^?ҥ8h&J,beDjXɇI85[ *̀׺~o\r*4 Z 淋Nk;1R&O#F'O.yI{K"VsȞ52RDLd||DPq蓮4Q7Ta,"-n= $4f?g" w̙Q6w+V 㝄UW&ؾ]ZaU g'Z3L# [(Ɉ jC6Ғ+#"Px1#ŽKNTdRO>OV٠-,&''3$;s?=Ra)K'vhK6ځ i"HٹJ~1e\I,I` :!!aD4Q+XEa g[,Sڸ9Ω/9X` eE4a%2g Ќ @XÀ/p@ , :!#ÂԣE>R2Y@2?*ZݣUlG8[],G]{"rtA |wY4!, D'Pq$@FZ3HZ5"|Kͫu5^/]ThmlJeQUH}u`u~iP ,H9x ?;8D5}1p@xb]5h+ʛQ#jxW{+7Mý(f$LHJdPMy.Tq; eRa[(.ץV_1ap{vKWw׫ƫ--R~QcVzZH0.S1wUO",Nf5ܰ~}G?108=g'8u7uwRq,<ҰZAl& Ղ,$*!s`}aZDniVv2'1\IyirsSw ~Nt՚ }״uuzbؾp⥓g|T*/sYvȢDPYT_8wS5Biif 'sIYD䦮4>>G""$Ű*6HCuC*B/װ@1X6XD)ce:#zh4Z__?=3;gC^[e֢10␅W5 T\;Ztt×;z6Ab^ND]WLuX\vGHJأVWc;oYl[sCȁ֔qx}Z͖@jóWWb*PF\vČsOkB?9 -Hģff;R=Kp^=X~$\≒\rpA@w=%9`004ChHB&$YtHDQI5 տGVa-K,q Q諲>e v -  B܁, LH_,;rA &:* \XI8&-O34vqrPJE[y*ߔB&RҔ {naW ^m 3ޥFqKr8jY5>/js3sd2u ]yRSjVԮ˶~p*%+դȃ~{avav.FG*r2/E|d5#C7 ;.]\)>މ~mwH&-`̶\*;oh$f4ҡ$h Ծ!#tXpTê uv'K9l\|\|IB1H7_e1dёYXn$" vo7 bwUSk,i@q &1;HuGBi`\Wa7eXcRp+HP}{ NG2ݿn3͍7c yJފL>d6eӒn^Q&[j~aNai*$&Ф}nH4@<` _$܄zM$* _QPDXyd} HX ]+X.u p  ː"cuTfEX\ݷgG'C^hM^3^l8PefwViۭܴ=*%ID$/H!G ZOHQ<c_hU*N=QĎ݇.zfumqU|;]|Y; Nĩ V "(R?B 5DIӐ4QlYq23;3;$Rw܁յյ(NNM+;M:A\!*F+0ݎFMϙlvJfM4\3C՚S;=EvCrR4LЂqB*B,[繮^͒lj YlᙄB}YaJ8k >I"HB&f\^+B礩.v,{rlDț+%R"II4vEy҄׆X sL: AMLG%i~,Υ(w,G$ƛؓL66IF"r$ތ)8.oK-䍦ET=ZiV+zH#bJg,.l>dL2D$̌ho/~~Z5| "E#F\۷s2F}vv:H-}uR>O(ԑj"Sة{tݧLHLӨRh K,XKX%SZ{Q*||axkIڠ2H ݯ(ilN 7WԴVrW1VqpW!]wƎ[ OFJOSͨ}ro=̌9z Ml?jo^ ݂"j)EĠDUSfhJi6tЉ @N6„ yzSMሥ)Y2?^vO΋OI |O&&.p҅w^2ڸXYc|NW׃Fs*UgJfL @d. Ičtȋ1` tQnÔfa.#oEt ̟pUSI'B\>/.YᏂ%.WW.^/}߾0{gS3/Duvq8•j4h =Yt+ q7~@[.*8M(SrS Ec8vx¶:onƙ4i9epqwtmR5M-ҩj6ЉXa-.{jRQk6_m†ϧ1ƻ~o@ sv~E?FTō{cӕ!t83`k$A9;F SQQ~UB/KcTXܐBD_dxkݽWƫo짵Vo tRyzڵs`߽seu{ƌwx֭M96`B۬P2,*mXY-C=S\15b(>=W壂𪵐h3P" +SBIQ$a. jw44-y^oO޹~?~kmxkUII7_>P9d~oBF1 oQ˞5m0W\S|[DPiq*6OiIk\䉮uPWM5RAʬh B w\MUf}qʘO=΢͙8{O( !G UZ6ds"]>*`vt-5J}8eXw3-KuCS s /w`Fb3geac(twF^ܜ2!0 Hn<\,ZXEWt&IlQ GvɵJ 2Xnc;,\4&UU1?;cZfOLacWDCc+q/8SAVwy (Cj-h38ER<+07>ZY.G`T@1F?ɇ^4.,>Ə+'Ow4 05AD67NG&k3Sӭ_ڱCm4 %5Va0ᖨxG=24eO ?FI8-Je) LTY](Q s5=/uB˅~9tIENDB`fritzing-app-0.9.2b/resources/images/splash/fab_slice6.png000066400000000000000000006070311250202676700235700ustar00rootroot00000000000000PNG  IHDR1LtEXtSoftwareAdobe ImageReadyqe< IDATxLe7~{;d{ EP) **k[Y P $$L;9Hfr疧;9yE0m;IK0?>K;R പW}Ǐ\˕K9H/ (NO7GR5EsŦdeXCSi?֡ߐ7¡ Fâ'{ A9 %ȥ #hH2|RGe[m.~AS8[˟K$m\ڣis) G 07< w¥\^E8`[4ئky$ Yƪj, .$SgY=SdqnG2,-h*j^kn0*'Ϝ.% 6l5]c$l0`<绌㨄b iX@hUXW,:|$sBv/?lRMgW}K߽W`=L!*=q蚛H@e&e҇Zŀ$ xQ(ߩ`Px10r.$ Ӂ$>g~p8, sGv\ElR+%p'a`h.M$eTӹTwSn\nKk" Μ;3|& 3Ber`r1+/=Qb{yO(Q O4i^ފ0>0. '0M 1៶@Bpp4 6.+1,cts!L A<K cY9W e)BJ<Q* 1Т(ФH09|C įg }DEq\$K0J 8c;/޷6Sqb6T`G@d *G[xbsJQ|TTjlUJJB[oOeM'<Ƴ}nO/joi)*6#8'bŲL6d4oN}D~Uo@lKꎦJ` B\GCcP3b&EBqp8 U<`,mjeլ%k;`t :i1_B!L4a@5Mk01XtF'aoY,@%D 9jar@97 8.ʛC9dlP>G70RRmk}M\UY.śz?rمj߶zZJY3 ; D:IS,`0bA80cÂ`pmF DDz~rI4j"͉3N;?=b3ͩȹٵc[-\{YO,..+C#{]y)O7Q##ئ lTA9T[гf@"\>pxo.\&j۸3A6%Sܼx 0^ʁ@yZb8xTtX.%Jj^k#4U#bi- %ɕ!YrjA#`Pd5"Jyݑ!eOIt|jx{cgsgw(XayF0A- B0b4YGOc$a,0NC(z4O,&ohtAqCcCaU*kU7.PTxbjtvXsS'N[ƀyVHCVakh4Gf" Y֍ rُ\t$_t"+ Բnr$] Za&9FE|P$tTumU̓|KBڦA*fX8g?uTBfj! O~s"MOZZ{V)80 V@r@y6&e0~b2t:6W(d>&pRK.:E(5[C;TW`z PHYͳ xs0a^Hbrm[&\Žp-|8t@6D;QNFYEPK%M7`khF#eR&rs|5޾'vڰyMRQfQ|i ]eP)P_.À%7;DGRJ_ǘ05??UW +.5Aoզl6H,.' 6I s ' 5?xzǮZۿ՞m!dCCgdIrUKuֶVIʅOv^fQbvwWD`ٲ'~S]aSәj!b*Oc%Ҳ LL$M.AX.Σ'и_`4a,<qo.7. lCm,-)I(4~=='RZF|矚IA!>''=ʳ<Nmں>,ie?3DVm& ݀hIR%aJ(D2\i>E;7|R)5:jiJjlVų'GL2=?]:jFϜԢ-oz@&J_߲:..3qn9)\an 26"DI x6&]K{, Xjolj%˹ql ym񚵗wX>շfUTM[4SOg-]vy r" Q[g*gC,YQ)<}"`yc`T:4*=ׁئUAy ~EUxҪd#<81mYqӥ+ljMyƮ;6P+A,L'+!kR`]S]@:I20pG 4 O_c;Xm:<IkxLa &^v$xJ@Nw.\v + Z$He;qxx6BDМ"URz-:V?{W~Slf*S"sTH q s/W.9sۦg/č-L{:]꺥n "e3ը| BR] 8Ɓ&1gasD$e \@7ҹY[Ϝ%JӶE Kf6-w!^ճ,)a_޿?NYݷaE>w۷<^{чwn(0hEIt,_D)0/"qgw\\(Y @iay,!Np)q4:" HgZB])Oc8$֟ ? %C6k&LcQJ[blkf0 'HŒIq)lDPihD 猅ЛЦ_ YE5Eoz pu_Hcl`9ܩSb J"4;3J$tj^~ˮj>s?wm0s!K(LlFM,< wӋ&PU]Mդ&uYp"vX9лfj?+=[]mGK%ꪥ^]S}+M10jlimk;)"2d fILz,D \Je`%`tk)!c9$0F`3ŁT @bˆMFc8PK5b8Bf|}?//}3Iq@~bNɺzpOjN 4`W %`9pƭUI̢ BTDsǖ[Y4,ol\0uV nni ;Nc`>xWs;3|Htu NQJ0sD]WmExrx==pB ̧`Af!G`0 1a8p<0lNe|L,@\$ðBd}MwnV %@12Y{w_(ȝkJsg-~3]r|ăݢs 0)6`yi9 |fQ.LD_$U&`cQʃH]YfyZ@}>:XliGnܲrM,Lܓ–N5CQ FA]e8O6+ %xXai@,D"Pۭ/ 8' ,.ckBQKҋ asE U1u͛o)S3kmB*9;|754 ࢹno;iUP- |0M{a~۬8}7}w ?S[:t`AHk OE/56P O^0,2u-V-݉ Jejv.i2!EjH۵!7i@m<NV.Ww:slRY}{G>p6knnnYB%E0s\XS71i FܺM[gs5 O%I 1LR*+(Eרl2 TٹTRKjնCQ@4S暸]d*!e89̖4M]`1߂"d$ $'m&:a ,1}PHKY ̀ 6PDWl$! 5g}<֛z O=3J+J9˜Cμy5 R Du$dl,yZIjP(xjF7P)7rn75rղ{x ҳji&[|yގZׂ@t,Ë wvt"jƶ&qJUj"OeyLFaAip_T(2POGBy)rP~٘mme1b-PXxɑ瞿/.hCK%j"šc/M/ꦫ7s%r Xjp4 !-um6c5tiFJP&T 6S E Z"ʐHMAJpF8)uH}OF]7S0y,H>2{xYkGOeuMܙ?shY)vvt H4ϝ{u^FuM?yi A~o(}Xw |YEYoџ}Vhj~!O $QP& \Z9m7`$%1$;tӯ_֮~<͏.<_{3(F9ݱ[D=tt=CWhGxEXb?]6 i?;o.T#!Zp ^lմ49?44=BU3-5 _q֋/Z{Ƶ[7&m{hl F i(5dԨVlJ[.,@ nr610f=1 b980FCX%XT)[FBal&T)_^e 2{o]yr!oC\[邕 Lb Yl6xMrlPWW^gt+ш"|Yi[Y~+O52 $8ҪeNW>"PRWPu%*QnMєo~hVlznlR-7oEB$ܱ/tpelktSӪXAnljj(\TJ0eYѺ JK<Ǒ$Kn[ =Sbi#p<k6ܵlղ 1)TfQx\nl𥗞9|zۦSG''HQgҋʏ~~=HI"bj:l;~]1 M>{ge;a!.qWKu3%H|ٳ6"#B>Dž"k/ds|]Kk<y2@0I&IKhhyNsc#D͋=[,[,t&h0{D\HZ>];4Gx'?fP)˱ -@A6v<{u˗oh`|&: P)?ӳ;?}Ӻk*s3p|'Qb-u@LXfl&Gd (fgy 'р z&8 Pg K9O$n[׽zlX__)ߟm;whJ1 ~U&&T@2Y?I~&Q:gcԲL& + TKU}_ccѵ tb۰Nֵ9 67ZI01EyukLY *d n.6vc*򪶛^XRQh =GBDH_$QP`e2d]"7M!wڃw7.۰byǾ%:G)J0J,ŗ!c w&!bu֬T0d4̣y_wreC@Dp44\B&H6y;&@  jIX,bf_ĵ\f{s8s Հ?MVĖ;,c 5Y.k;Vool1lnjkU #0 :P y4ai,A-Q,6)a u&;vzٔU%7Y# GYix 'Ij 0RLpJJIēg31SޯV%ZbG?]`nVv<TdM,5`3Ac̰<$WQ<\oi-y D<}hs(ɴpCwA`cؠiY ss:t躛>od(֖ &g&B:5;M \gsx-&YC>u~L8EY`` "b8!D<9gp,\!wqIdH mpPe@hOr}^H iOTt-]RB"v\sW|ñ.7}`P'aj0tؚxđÓM7ޤ3"X:En:AB@(Ӄ6myo|] #'mmLUbXWO%ʓҰiIB~O_HTs2CܹSE <DMUg"Vq :CYU&t  ʏ d(Q[P8!R@V`Wʙ}/pv±BE?]9'>^ԏ>~^3UrUȔ+r1B*ŰH@ @0! ]өh__^|qyo֮HȱdYBgݽ͟P`VA[g:1ja2 .,b-p ;MI..PY *fuuQwv.2m͸&1 X&nĜS,LL{8HjLLYb+;M[UmZN T~*WQOa%hzx=͏հ?r`k Јt| :vc8P Ӆ uPu ҙ3JA/Ee ki3K=,<u8yho]ZO$4M;s HUWJ<ɥ6?? L : HPTK>*_uҀ~Jk)IR0aa-UӠ9q9<$9\(; Y:N ( oۘ):0F (7ʢhu%@n$J~zz_5f-ռ?u%,7rzyrP nmTm*"9{uu+7]e7'?=Kg?R JM-Up,`kc6 "a6b41lilIkSa056/ڎ(M6M‚n1`rnr"FoF *مtR'jb-`\p9gpߤgbԶd# EY$ zU +z7D}TNຮ#11`}*MJP]*^o~VyMN?y_[;׃*ʫh6/y=^RzpM,b!(~煷W){{7jQ<"脫=?xd|ǖK?k[8V!/ۺ֚\ f~$ k``٤L40AT 'T@~wB#8`®wJdyL?ό]T:%m?|hGa\$,gڥ.~Jo_.Sf0Q6\]N+(u|nanllra` YíhzU89 4vt?q`ܭ]3gU_N],.QԒuć `6?M}%^V봀ɨP|U=80fxu*@7??X"\ mشi UL_G:kk^y5PhL5, CgO ~Z9:uX̵]RTkjwcG*{ڥz(b*Z. 4C%<@*]_(ʴACųY(yΫ~/}xrԓ@TQ40X1HMA^?Sg T+l![VZ÷z2gkVl\Q7>o^hio?{$eIk܀x￯cRܒaM !ͦytaLLZ*ѳlhm{Cw׭;=;'hM(M+[n4gqL/HMgW[&e#VT-WQҹ}>vrg+3'kaU`mkr`l1H9LL2 dF e@F) (05 \+t>ńߘ(E±}{m2x6S,XnBC#77nNS·߮qM(t*򬊊XNfR4,'d8~c_ݲuX4n/5*' GϟƳ˯K.iW@%D]M٬[(Ѻ !+0.&Ey&fE(ƳY@J (ImisF'ӣx:t/U'~O*E Kщ u6!{+-?9ӷ~![4ܢUՐ̑<&R-WIS:R7^AZHr=X6ȯB9SƋ扽]}eޑDs7}aja5]?E+[A |"Y7s7NGձn*)O..L`,U];Iݝ+xu|z)0ب:ph~a7wӏyOɞ2+dP:/N 4t\8nn vqGC¤ʼnY!yZķdMN7ZQ K & X3Bt؇, 0 s0eçܘnPvMd<~v3ËeCx9ɘdر>b0TH `dI5>:0xQ4uM$GcOX:/Y.u,镲7*IN10:\4Eq :bYZQJ$8  ae {I;el0E 1t6G?N،0t. 'oV_IDke%(j'B͗Zz9 +X0F2DyUWJmaT>4wCk/Z3hD|E*" S.TuZ'Qic’zD9XD;JۿuXKa^oYՁc&h oDO5xO&(pkj_fhRrg7lhϾ_o/փT2`, Z4h5??0:rpN%}nlf?~ =\KMl~{ ]y#4 xKioWjj=.|_?ļ_kNMǝrզ=W"㎝G~S"~깙OMSh6QK< H㟺mx5W|tGo8qӇVXc۶QJ^s:~<_f9цVWg WbЎ$m8 la\5 jUPb<:9"p/GX͘p(෺d,ܸqۥXMN8EV4ſ'MCh庢 2`q~yVEnxtBw<"*ǡL,~3$acK;sMM{, ~u;yeZnfBOϊ5VN8{wX.X֡BNNV* -0 ՒZ Kjnd&2B?װQ 5$Y>LJtl;&(6֔uFU< X~BS*ѺƾRQ\)! (,979?>څwYVTXmEg{W@0"21t>T3UH?=صn5/:0@ [Wǫ^ FqxX:jlkk&ʮl.ܳIfJU;?va uuDp^tx&0WfD8DiêkZ(I*rN}HHz$u!vo:vzxJs|OᑆeHXd0L]ex孝E= 8)`rV/,N9qbpqgَ͛$ދ=ߎ 4Mr,/A$ty}z?G/xY6ѝ`eb& .9r,پ?Me"KY/)bɿT `$Ű"^ 2ǴV2tC:㟿?ˢ%#$ߘZFx6v`"Ia.m9Q&Y ަl}Wԋ%˒m`c0BB R/\!@ `6Q.X]+mevg] -fyܸcll.,,n;~oX4 i@&H//odgvw~ިgwSUb R)[0X8Vh\04BP.4X14Ю$giH$7=LS===&wjf2\an#&M" C&Z䥱XJdj( b8- /£ tM8VՁ/ 2|s²i2bS$)4* 2⪏Xj%2RAOc--3y҃piIJx?4DxBWϟo`s}=dҁ. r0N> xں{%%@kY S̯- 5cT8jY9 !AUUY"bV^!CT!]P<,]xɘvZ\[[O-z!2szQ-8uCG<|^,lmm uJz F x:C{Fcɉ3sݝPfRimmxeS]9LjC;jv+fg?z}~kLNk7n 76d3W'ǽ`jTZZ: 9ۑpX(ln\;I+B\S3 -) ,H1&s J`h1y[|GaRA i5yql[+ҸK`tn1}ϟ{#])T5ƳZ]#t#o#_;>p`w9E)m1m\Z8t'gLw_}!ቌ  gc]]Jqfz)i"3@l` ,ǺB/hA)Y)hft._|5R4o&cӯѳ״t66,J38 4H:iШ5p7H Ldض:*dN5_,hCb)ݱwQwiA6H±Ǐ5m Oⓔ/ru~f#%oqYY%Q$.=0[W)""&j<t8 73mѥKhPz 'l^V 5Hp 3aRʼnm%(22 Zl)pBbs jV,@l^S9#RR&7k=nYqK_j6>Yd u⍭w6s[ " Šrp]=P+뺲W8=8s4S.I\۹_Zf1 yaugǩ%^5h}ˏyptν8kQnXKLC8M5yAj[yXIL]#pʼnm젨$<UsRv4JUuQ7ap!AUX,&np9l8b0`JDEd^ժG{;#>EJp]QT҆R*'{w5#W+!'&ܘJ,v65xl]' r. мǜR ѫZ֗ ._T[cCOǝ7(􌿱H,'47~Q73WB=MXNgKB, Eh,<UTR/ ,v]-EQbmsZP|SgMJ0XFf-]Kn΍ꢿ}nm`_s6 &1\BJs4'蝁݈BZ2Uu2 L7\ A"T58( p(^BBҀ2ΧyAD$TLR Cgݐ*iny;d**+PdbO ˋ !es e=OY6п\"]-}r~ԓO0mJ6wH8jkg'dc"u1*drV3q2Oǣ!\442.c0p"9}ԕGl p)iptRD(2Rd8& <BaWugyedխ̔!OBBs-SVU)K@u֞}OW'=[Z]ϕErrȮpMbwSV+gyoJy

LOڍӕ|~p`4T) &xr0;6_}#c_}]x]Q\qY/ ?8_l@o/zZۺjlrz؞#0+Oᄋpdlly/~➷'rdr\6 =HMKPRF+l:tzE eȣ:Wv4墨ɳ$!k(f'*0P0̯%J+"I4\^TxF(l,~WL)ـ{ οw|}'OZC,) }Iɭt@o~N%ShWцH']^2qZY+:ws'Z/GZke桞Ɔ&-4DsJCV_YN2ՍL C_-3cq<;9 FڵB.]r{xHnMͮ&S<~N0*#zdZp;"qMX${p>/$1*I԰ vٗp[6^]/Ҕ?}N}vk%M)a{,'S媅J+;@WsR{AO=oh:SKjY`$暸{Yl[d 4~רV !,4>+Z!!ğxSSWu܁9rfTUG_ l6 \İ J٤ߌCm0];Ƃ@,X1٢' P =ʁ ڽx}dty0t7VxG3'_hK剉PcdOó5s-ڹPΣS=X߼z}m ҾZj*MX2 Ld@ g t.e#3 U[c;66 /C7~?U3x\<~RFFZ8>eE)F˸m**K KdX|dodl}#" >h8-Ǔ*$Kj(5[UͦӊݽM7śLE+#lyͷ^92kve&G{'<}loXV(DU+Y(HMbv|M̪Uto{m5J YpA w~[L@V JpXD@!9C+P@;H."ZsB.r{ܩ3g;],y)C:><2Y8~aFßӷŧպz53sb{nvZuVl?wtEtS (U\k#/wo/4}W+"y2gH+~@ia &uHqT|!{ ar\5 QK rKC_䶒[kD Cu炑GZZ  U=jU\J7L̟L3^"߮}czL  O&W|> _C F"z #2݁Ξ;2$/m6jkKY5עSLĉڃ0QY;j ֬ݸKbg{;ڋ+sKJ:W=MWZc;~<=1k[&}=-ሚIo+@H}&:&Rfx ΐQh%8⸁QX"HPhyvrh+Jamg'J{886xBx^."2f˓yюx~Ͻ&NsRP5l1#2B(5l\qL8>D#1Q,jo(F,0qPbhTcB&GڃB?zTߏe,2C} OA]2 g[$4Lĩ`]d35ڲlV&g׌\?p.s\JkX=a^۬ ;yֽ{$1sV^2kϏ(OC]Gk먃B[ۏ p+@*b!H^|!s'>--pGjyqx4|no\ z-=?xl{?q5=~5McMɍ+W{=]#5L>_x43=^|Cƛ"Ia0,ơL Q \ЂN,' ,εY4GWp3jmkKZ\0 u-BOf}mj)aʊ"'2\s49ɣZW ɭD^3K餪#n{o{ǎi=zsO_\˫}CʻIYYx4QFIb; ;%h_];[ȜHVPЅNsK?H{E+'6󛙪i:㋅O}Y @*ix2zg.:mo7Ka<:,@M4i&t >Elab4Tx^5{HW)c-ҴqU,L)iD 'pEVm@vN񳣸j'"FAjypk/TJˋ' 羞F[!֤sYڂ:ttݿUJ?q*J긻~;_Ft`eہvbGS}?O˫SMGurn]C/M\FuޒjoU)oNQzwwv=Gkϙ67t7 _P0cu0}애= ' N(|rR#q4f׈3(p$qgN{`qibuC%ĚfrRѝwrsC[{RLm^(ӊGqu."I2 X׾:~q}|580QK"VNc,H߼p% fx>뙚XMlvЫjj+9޽Xds W W8,zdYx,#<Ș N٢"C2[s G)VpBTp)yrAKmW'}o{qoٗ}kK>?9R7,Im8vrU Ḓwi}fbݱe%"LRe 񦽻v-rD4ҙQPsFP@UТZ{qvr623^[{k+++Cm-jE-b ؎s~~7˿# TE,㌤ 5Ey6ZDQ ުWe'Tdv8ߥ`$\䭩Ip |XP֖F4Rj8%HmI0cB>MQlQSURj^ގβnLܨi=2TE'kC7=zo\9lsMXO_vvj?NWNjF-V5sխtIkc厡Kg| H'3}l_lnޘQ\[r< Vf҅pM+Yn2+[ = MJ"(EꡚixxjpdtĮ܄7D=˴( .HK~Tc]vDbUY&zУ(1vY/^x|wՌjRD #4+7&Ͼo~k|1xwݶcĨb`Q,AjĘ(Yb8Wn \Q\Ci"07%lڠu\Ȓ~o$ʓ,"3ԶOtyrYLs?/Ic@E0d=# ;/dyJ[swKGc\1u8Q/p.T,IߣWvgLAv mIuTlp;e/:aP[GܭͭB #i[tb ʜXK;KsKk%!V+&\YJqZ9o^>i)ϻB<0r}{n~nw?S_m-M\Yih.CTrl8m>)sIM{Ozm|x7\)45W*'_ed`"@IVU-JhrE8 XpH)>17@C`B6tbhl*>G88-}6$+R\:׺g֮ XCMT=ǽ2P]%TpI¬c͢b(@$Ի:,㈖Ά(1b2RU"^*O^>/eRٴl`&U6G-;rB.1 \  !zdcEEp,2MPI Q+sFxTŲ< ,%l"U4kn7=jcO"b Ʉ2:7mW7p3 'WeX:&,/Z:6B5U)2'Hpt_:W'_oOe7:zmcSMLWT{` =)f)8$$, 'Gl̈́X+fB~:e:nCjb56e&n ' u ~y/Y.==X-M8D>&%O.(WClG#Mx'pDl:@Gǚ8g:{2,3pn)IecMmB pn/^|}ﹹCcogRFxmќ (>)ʹ'?}цxS} Uexy Xo6 ~y4^cjs'ct5Vٽйb6n9z,PU*^ڱcI+MuFb={<0oŔd8{TJD{#*B71[[ME? C7Ԍ^ ++s1[N&7V{y(m}bP к"[ږCuI2?\R+1Hwrsb~jraاo\YY˶t޽^wZ$S 'mYL*omIj[ذ"\~brJ<ER<0'N}uz~ÿ~7jky٧\p~= Cq[dآXv4x` `wQT]ݫR,JlJGlXHn2D} .w={ZU9+zU8r6>lnst*[%,XFNW*e^qټ(;6ũ糉EVMZvciӰH(|2*e)Զud[P [BȧS[2﨏U lӱoOt,6Iȥ5Q@o݀]:xE[{⩹ W&)[(kFv4u8~6RT!K,0qNI֘%uzPÍR sxKmp01 3ڴAfPNR! 9LpDQ8|< .r:KD u"4OK].8>8Zb/ ;Mx=簩|BGePٓ[uM{篾gPMKK-ʌ['r迿}ω;;FwkXfxgON{;_9={{{ b !zN%o0:??xߚvEb$Q757Dc1wEMi YC!1h:J@Z/P w%L݅((Dmx@ `8kd0$U=NI&7n|5zڬ^v}͝N)o b4Ti5њ:Af2M{[9<tX( ߱9_Fݫ-|2Y]0J^eyK}(S{h`qzQ=-iLw 8g92ط:ќ]YmfR)?qF&Z&tBDicQ, 3|lge:r9J(-Pr= ?LC= 2NFRBSr#b{۱sE> qhȠ ]֣v)WVŪJ9h^2neibm۶.R " bf[HHEiS#(6bvPW`1! _SqK @{}N%sd '%,4"#{l1@$HEGy!!se!EY؞_d=~ų绺[ʚYK7_>|w35^W27N/?f{j8~YkE-6ǻl(8q;.-V45=\8]'n};O0X,RlkO~gy+ r{k;{Ñ8pz KT\Jx>X҃A=7b!oNpl/z6 "ydG|{nPv_,aA:"PxZ)ڶw]!JKμ 7ܻRcy+ uu%/%M2m"嶃 'Vqp<"tp5y-yE,D$NG -SiUdQ GP5 ! p\%X[ us '׾}wYpqu[5=Feo~ӯ{?ޔP78Ƒ%HX2zM$BaG!Z9^`l$hC}gÑX4  -R+nҔdxOjO88Iã>E^]IT,F3 6 IN>,R{E4`S4}b 766ͱhb}Ubz +. (psW{}KWd_DoOG"r6aYC'1u4u{7b[AD|*x桟~m:]Kg_x~2ſWުݕ-g BvͧVW5.yj:Ӊ֦͆J*RTDErz+U jnK%ƦCV5)5!cdH oP7Tfkۚ:յ">F~`_OW(S)e T:Qvx"h7r8Biq9m -zˆ8|`4/Zx햎Y znilp{etUV4i:Ҵy XQkB`ti,%xƢ#nPc& ǂ]&Sᄐ:22iWXJCH>YknXĸbY gXFQ6I:8k bKW(l:D31|1CDbY>M0* 4JdWV1_7⣍sZ&+JIcm'9mzeVvj*8eI+g΅ZKPGd;Q(m#&'Wq@$NDqnivnf_g d SE/kE/|{k.=9qHr#q:hRĒQL6" #Sa-@ஞ.II@Ix]cMyE.xXcl>e~ˇwr+\"< ^Rz+׵FbA䫲,͵#)=A-r/{t%i( ZuR}[q>p`icN-驕EB$phճlH5Yբ@/N;dFO0 'R!05o2qgĨ&(tF.A/2*DZy]lP?|據YC%6oli PY xeHo-K\=(Za1ن9,NQ dADcp' tAhlDxԊGWT4$,3<I^$2BwD+tyFv ,a9lc?eDR*,e@$psȻ;/xex`=EJ4Y 3HXEoEyCflb%WجHx S `mTuTE>}i/ 0,omt56Odg-mrƅ7ۛCV,wx(qjfoGq7NJ`8Q4*~;mGCPq|v_%eG޹s4Z ՚<@>8? i Fx p,ԕ(rXtR3AxHfR![\htBa[<.)JjVJu'z+43L\i-2mkĬ7hb@n~ojllm~NjCzYlS -X23@\ZlF9Xb㽵1mχ,ѶGv W^~gxȺVXg.^LV3|ghlw:j7PĹH/(Tj(N0UwɄ{qe*0(6ٷɰ< Kh$fk6%2Hj)PT"ێ?7vu_g}ƅ˾H:@E"WJ\ PYW,-rvI>BˆA9bnB$?dNU1r 8ec wbPߊ#bSESNMʕBVL{?u{7X8AQ&  L"וE' ġg1ְ4x2abEh72u&J1F+F/qd6mi $XlM{hO$0i2#2zn2'้+RI4 ,.z,x֢]'D8$ٖJ?{E7~ӑ[p'TkzLm.U$/4B;S5IPoa HYس4kK /`MGZfE秧ss2Y'"uG*r((wvV!Dk{*wn&-!S~=PBB9IV+熚kޘ,>C \MFNOM]=`}ǔA Cc-Ap8@P ,y l_`@!%..- Xt 7U@ <.-wwEr:'g_:'V66WQ̃djwqfh3?~+˓<^vsgtS,C6 Q,hFL?7/G}2^LXN(-g54;8 3 qcɋaEv\US*v5*UOTln}-w G;h~be,AM'5-CE R=-K qI tBVbG^8Ė*3Z$*L#aLO$5%46Ё#P!Ta- 8A|l2$Ć($Bgj(2Do]:{1Z9<擸^O֯?tUu,-[a)B$\BNp4F`FnA VPh{+H^$T_CJj(ةU*RURP]B셅B>=7AGGwVZk +2TlzseQu<l1Pa< m [hGQ$ vi3 G)5'6v0jDOa'n[f*4{>"*Et*9Z[ɤ,^sôY4݆T!}vW(}C(¼&9T?&GN>uuN){J5&2ԠV y~z NqB2\wBJX`s \˗}E,gV*fdwd~rT "H-m=}j Z>SFdlؖe G5 N,b7wSV >ZAT _}{lt|BxB G#P\z6\DvhT:F_sj~x0լ:Kʀ>_ oٰ+>E W+_ʅc)UmrBă Mu-fŐߪY6j)_}S#z4ޚ:sQlbeĒ7'Ν Q5_.dR=b)rŌAo (gzZ>T(78.4O5܂1}K%O襳>w])f*2濂ɸpQ.e/"񁾾]:NR3$s{!UGWjx $@gj&oR!QA]s4%  :Wg%S&4Oykѣ9-cW6yO=bI4LŊ[&ot`  M9}h&٦*hjImåy3wgQm:Qt<&Z:"ߠ[Nػ йa 2zȒ^ ./Gv 8/h]xЬM h/1SAw&S7[l_soM^ E` R' 6\Tl6h09&H_F`6\NSѰ/}U=$EBόy7޸͇>sU/GnH䵤S]p;M7_{lu7 -J;;m=E7>)RoS/Ov[RT}6Y;QPC.әSa;A"4\!@ c0KFc'sٍASTRn}[۝ݴapiW'fՅ5z(yp튃7.42"]rrhݲ@3WfwcJBRdJN/z""J^m?`}C}oJyC|04nͺ3OS1q҅?pD2ғOʹ V62ÇAԫ8UBO;vۯoܲ- -=˦={w;n qӃW0츔ӥضuK]<>|ul=ϴBׂ: A,X9k V52A#`Gb|>G1b:'{6CJ>XY\4zEOEnvG=ڻCIS.aʱ .4˂5W5x }-jKTI\2(\ؙ[۫~ۧjlHŒ.NMgBH|}C˚M;;:5,,lӫIRx(VF$F-#6mwtYZ. ڞ,/NLd2Kr$ՔlRkD[1B=Xk ljhzib`KՉnnN0x{Uk>8-+:䙫t窾W=dix¦"b 2UH>6hTzmi P-SK+@2~Zial!asgwlU|k Rf'ҶzUo7zq'-U b r }6%.}w* 05n0U@X #tXʛ&`33VmB Pnk_4_׻HŲ LcO`;P8׮WuHi@H+2X GˈzD |3], ɡ +(, z:jeQ *FrA[4;= b@K# Ї-@W K TV[>dXvMXJ 9!,kxܩDcJŪm ;o E`|P%H׍ n$\L԰ByBW`yT*ʌZH8 ICi-LuCʌcu[{/^[›1>ű7ݴl~n>hv*B+.#z8Z~'^:Ecut{ɏAP {8q-dK oO6 Oĵ%D'rגv}3U5/ AxϮm[BD,,ޗlՒ&A{ z//Tbݗ e)k?y_蔵TScӉM}u'^,eM1em|GemF$&@ߕM-6W|+9J9AcSaqzSClJHbDF2|#]ʨ~fvU9Tm9o=bغə9QrN|®7R"n1w{y'Jvv鋤, Z9`$>&xw6:h:{K .a+ ɅqKؤ0q"^ OIѭ lFe r7V47C)dfg)Z[?|OsU>_/f9`8:ȍ<]lL93+dj꽼"Jf;ScAq6!|%BuM747\<J%n# #Bj[Et'-4*!F#.S {՜ )&56 Eǡ(M5#([Au%"O{L~Vù.oGU Bmh$R€yb!;>zgF߹Or˹ŕGF斛>ι]5Dq,+:z˄Yx N LV;)b;Xsвge:fLSS--V8]f}c`XHv_4гԹ+f+3cgOXrpER<ګŷ}+zv֧6QV ̧-b)hpdz1\-ͤÓI-:`cIyHbE)/ CB^߶9ժU*wEMp( LJ}+W~׏U٭6^?63wuu?p oϞ>}\w`y=vZ1#" h2ڙJrطzUGS3?kg{E/cA%B 1rl?+4mٔ_ G!2lոM_dRlZ1Ѹ-2 f`TbY6H"qf k(Z2)r89:1vʊM<|c._6:cj`OZbfTLpk.sNXB(+;vFe^P XGQdS0p2QaOyy`M}T|o?3o`LM6pɐw]Mr aB:*a@"(`V}[w7;[ kj|l弥% _nnIޥuuwpQ$EϢQBdtjR Ah5 J^CA!|x  V>@Qű~;G޻BYo5MŐc0r$i:}Tci6fH0~t(yzbDJU_|\[q(ApILioH-@5Qx"iEfhfC,dE1@.Vt VKxqvpPS*:]0E\x^Kq~=g:QE|6OuwpyzztkSO_d/k1$`A \Cscɲl %c=,\T=Odyxet"3>ʜl01PYlϕǗ>te޸ '?-ۺ::Vcw|#IۯTW՘NawFSqRdqTC[ ~1i=H]Q(+[仰(360`H pM jLW57DouslPZ.q馾3v֥+*Wو(@[>#xcb,\4A)b5>8(qQJ`9ru=߱~}yi)Y=%/='(X5rf!G[[dzж`GQ>GM|IYښN|(&q Y`]3۳6Z$B`ڎXRv<ے]/a;R)Uw+WVRS S0[|4m8F~g?.c0dctX);_FPll v_yƺL[aMD$T՗TdXW z2SEd>/+CTV+l6־cӆL.YLT.ؖNA`յtTKTAvëWp8tcSWJOgTS^xp =hc&JaM)QTtwK %[ZFξG~qf8񁭃{vyTX#OO@UIѶ",ϤMK2$Ii1O|ѧF<.<5,QMڳ;gHR"m$>{yٙD$?h(rcNw 31pAwF΁(j kBT-5IRZRMg_g]͛xr`7.}|9Vm@e+:̾J BHFKm|e&>'(ufͪFD'a0&oV*7)]Rte  6N=6S#TL!fR?Xm%l7h}('TmE41VDPw6뱡#q#O_|~!-gxB~041roZճ~_'&y+wG_;yw/cccʇ-mEaï!cD6=JWwaٰyT 54+QQU|^Dn | <2 j!wbRX0DjMʈ5t`ƨitQ cdZr;Agڢ} .UJaF`o2D 39XBmN)2b-D *)]./\`: /=Y*YömFkC@O@C3΁*ADe+tT4i%.7_4|/x5T.,g&fwr֏U}EKGX}Z^\>ry0Oѹ*hsgG{K ^ W _3TKۣD ZP8%Aǁ>Z8"R'TAkS%꺘'+6$57'$@_HE(Wr%ARRqMt[畋T}.mF^S-b1 Q\_ۿgbX dx3.0ҟyWug=2?? x 0WPGM'ohn_|kqvfpz/U+7O<7MN3MDkEA-20ʧb&cl 5Ph㻺Bɼ}FYO({^ZKr)[lo۳upeZ,|s#߭[sC"[e2g_Yuv'%P:2)cEX+fZ5`'\sceJͩ2# iwr쵋gN}]}gNy;ݺ3SS`O~sX GZZ.x¥5oH$T]4v[wx]|i tTU6+^b'Xܵ# 6$|{,s׾em1PАjRڋH4)S C&Tۚ!dF?+: xi} ;&,e"4,l.h Y/ODn쌏tBk謿;6#/=Gs_g?f~qbnm#!y\}]*ƫ>x-٩%SYE/ts y=#\3@Y]UpدTJղ(vO^r!/mܶRX|W90r҆M)ZM˩K!k#BŤ^+޾m 9\2VNEzӫ~֘Q]d2~@)T79#y@ L3 NV !U$hnu1͕w( 5N-*Uj=pkL/_9B>Y~ݞR&'UکG U讗Ͳ̲ :ZJ!(Uz,; f3ʪ tXz)hp ]vZ3(d#C7ӆdxP2R0,tR/1Q^RL*~l5ę~-gT*C4f$~>`9%^T̓8SOk?ϖ}ͪ4t+;3vdDS#R$"D p>s+2ou߻G_ɖH;Q5h5D\OSNܴN)Uwïٗ7_ͦ+lXim>ٷF|%Ni 7NގC(34v>|~!3"n " <'Js.\CÅ `SA{۩FoÖݍ%QOL͗g>~8sPƵ ]/~*\:7!V^6Ք:X"0288QyU˾7 ?&pN>CI=ݪ./X>yá?I(9ǔ @M 26^٦c!Trp-;(P h 5GtҘD*DBӟY\idԙ7T"zG.WN{_&˼ي (zÎ%+RXKg %+ f OHVp Q>X4-[9l۲rEŬT3%Sa/xW2'!o¼C٠sǺկn-O MWٓ#WSv ޝTg'a,#$M6nٹzNBu]ӁWpL#^P$TT苇!ׄUJc>i{SQam]V%p{ug)!a@tW*K/}r*.,L^q}o+SgyB,.TʨV`-+0d{>K#?{JسgT挢Bb1v氩PDdz@K(-Ph[Gw v+i( =kY%=\]azKVMH1ҭɪb{UUB*2ё~*]=Υ*lsLN"#W t ӛ R9.< }ON:RZtjEV!ҏT!G@$PM\lNA{cPſ_ӴGo[jY?w^gkM_\,K\iqM\8OW[e$&&}1I][S![BdA]!JLr.=1B0pPFKJhHT#H2&Rm:,_M^ [2eˈ*a!+XLRx!$xxb3ObQЈoUB)_{$:7ݽUclxO87rÍwlZo͇~LZv]yn­i-]-?p{~??r̪u뗆rhǞ-'[ߪsoܴn}%DgϾo{$@d_C E"iRTTTxP`tk5: |,(hH *WMGzj(G¾E^%El۹zzZ ťtS,S3HLt˻ܪп~󧆲Ej MHhhc 3fg|;uVŢIJ7[ltQT5lEB̖kSE [$G{TP1}`d,t(Fb6±@Hc+-s\`j)*=T%0\GHŠaGtG&}. }(θc !a<:@jsՄ̒PbB>|o65y┝4[HvU_0рY0 ;HVL"MSjHc$%)ozHӓ=eV]T|iSgr٥\1WJ:LR6첡cwoek+wO&5,'GƯ>=7<~ށU#ܹGÅ\nq5C |ffԤj}8&b-Q WΔY$Wb<rWU=r]>\\ʮCk% ) !/x'u\-чMFזUs[zbqna1֔H-/Wǭ/\M6PJK2erقɷt4ꛚD,r>>B5Jg.}{}mx^DW;u*EBP@ R S6`(UFx،i󄃣 "B! hMTG[%|> } _+SUO(L3Tru%O9AXm jX.XH͠Ҋ;>}X$zh}%] v- a;tULz ހTZ,EtC~[v垦dS E7%\)]mh(TFLŰA16_Ac}tjdiw^515斄Fs|2gA9sU~­\;a8N!bT˕=D2I8?3=^0sW먦sPTyg?8eߝ:u{oHs Q=m^?g2T~J9T`ķdEv` Y ,yIi[잙7)A}~qXq*NJ_@%(ZT I=5EsA4ZTV˕֮噹toSSϴ3#b `HtGU tQ (2{/ 0ڬ`JB.[oBfޛ[JԬi=+W'Eq=3cmu黶zgg\5RM[19|_{{O|Jh!{g~#'.WHX H6ڣӿO~ܽeǮdƧ[eecD旮!]&`+O@^ਲH&m!XQi+ ML8˜d [eJwuٰsr%؝¬95?;13yxjj[,(:t- MdնH99ҷEzmvӭ]MQL-lN2;*岅6 (Q!Bпn9K3dnE8Չ(aijo5(vP~rDh±s>XUekp 1e)ZOYBP.'Q~T.OWE"LS VG]i!0lztN!8Tp_|rhWSiS_>q*M}+<'++W{eMpDɟ⟬`ɬ|lg~P`bE|]w bA`XU֠6]CYJR;4nEHdB8 euP0a?VUhlQ[=Ç_8h>y`Sm2J>eX ;ao^#GRai L^vkkdѬl\YbbSZmw V*L#S^*ܼvmMu{o.4]Ӓh2Yj8H%TjXY:5qh{a~^ rn*sDO>d1xӇ>om|_M5lܦ `qJ0RMKDPWT4Cm]QfY] 6]#4[mٖlƽ@= -?HH!ý?&``l^fϜ﵏$Id9sww^{yz!ż LoPˆg$ѻݱ{瞽{[sc<'w;woJ`eTY 0V^c>!Stx_:a+v;ynv !ak_0X |=kǔά^#|Ynڭn}dZ#UUb[T,^%_T >|R5]pu MO%9ELv@ *-s0_7LW}ǃ]lsunȣ?[:7_ ?K gي坦1x=i}ʂׯ7#CW;#ޡuϺdż+f};?:cJo{Wg{EKN_|'5 ׬Yq&jR3 ̪kݟ(C󮸪(õPa},q<Q#vq˹#I5U M[(ax|RiMcEìބ;ĕ/p4D@jN`)a_glK "wKٶ+ csU TP1]g04۷ْkmRw>qzӭ&%?n^"]xR{Z2:㎎!/{' a0Bՙ'!0 &*1[@K@v&bzC`!l9A՛"Pp ckrPF4@I,zƠ@_um|t+(Ia~vYL %KPP0K":DuW[fjc5뵚e(d)d) N_P'֭+/pU;pa5y\ qp*G\dc@3Z΍^<1oYV~o/AJz̄^*,0zڻ[^jYs*rT;ۺ<}}._|Ί%g:ǫ/ȔS(K.pxmxh9F!2_wh@Uocdtv1mDv:qwߚ=C)uM#}䑯O!)yhd)"⡈6i|By|f RJlꪄ rN"8A\:'A8(& '.%,i 9} iT3Jf%R[['UzDĽ|qƼ=2S ~@}!b1ht UOn hHe !/\{P;^߷-I*U+caFua__{ec΍ʲL[;>tg34UڽKKo/7yCŖim[^|ǟu}-i ,tFSO2s'EhzEmCKD,}(f'<0PWH0LBERV.Gw ̉jc(.\@ )%QTCCHv%DSJw*2w .lX>?kϽIs124vfO=m'6\?@Go[v|g/%=Or7?or|j!P`y76e0w- eT`DTQs *̺TdCP 0"bцV,QvM,%"p2$mE}M' .{Ơ 0͎"%i}[\ŜӅ$/t̄ YXCׇYʲm;UCOwS:O~gW.\n^wB>^ѥ$zS7U50L/tyN|1L+eQ1#<|.:y[aZnsL,$@C&%24n)Q=&P==؍$W@:!Ð11):".i/Zn57λsZ\52<4kxb"c!GfB(cǟ/]sЏ~>y{/: p<ϸ5fM}.p@gUYSx@NAY?<,|XKK ج"ӪD:*'):+JPe«V ryȽۇ[z۾}z?yŦO[ Q'F l {Y)NC!Y5RM >i"HGyQ0Mc>(T`D/5^+*_ fX_t1ma5AEYp8|<*D57-Q>eСmӧOҭ&&C_EN7齕BE%ǩ `~ຖe׃Xz2DU\SHm:#>oفFfJxP6*}?;ќia{Ԏ|S98UYƏvrvmWmٳUƂw饥7mnP/\,*'= ֯ݸx[ib0hy-a:lݗ(`|f!}^-Jpz#۳sB 4=eHOA(HM)dl'@r =Vc Nk"ӟb/ZG#Np* OZ\0ڛ_y=?>ޓJs6]7%79>TXc \)Q3Uw2Uzۦa}S2DSo jUjBe? %^Nn[&ZcCnQYB{ld <(Bx-ASlj^(]mb ZHLQժƒ.d{EvHHEu"֙#E/+SEؔ"R@ ؘy] z֔dDJLHbήJ@ ΃zuS5}dZؖ :wL,-'tu5`D)d=]j^ t4 -3t(321^^-Xe_nAApdALck> e,9`)x`t=(`*HX}i [Q.^ F9Q- 6Syoݖo_xV%Rm9ӧMpU5n:3^۹u)DX|i¦)ÌIwes4ͤTw"x g0jfc\Q * ̤\P`B^T(Z]vg{TKvn?yܭv*A T~?%E 0Nl_>|`K}i_Ўupl>6:6ve>?6Ϋݽ֨?|v\&n8 C,Q:7-U#oeES=orpdev8$/xc'S*M΢<}:Ba2Ri??ZX'b%*v*%Y u" =X6 +e P`]7ը7T5B M"=ux,$FQGd<1<5u8&>;i5n}ُ - k݋i]svwXw񪭯>97r=3^YS;z-Ő4*ƅXdVyGjC*[&i;sο?3v×>]zm;-[{/w] Вj\D& -l*3VpUOa?7$]MIY| ?:on͗6obrx`պ+f&/_z:%VfIdQCMTӥL?smշzϾ)><RĻKA`w|gx%}S1R̹:W8" k_4;@Yx 1-KsPFU)#(<_54tjQ$u= .S &>0bhHf*d4-2¿v!OuЗ2eFԙF#&< \ # X"LÏQ1zE qas!ldaN(tCwA69gђeT^Rf2:v/gYYt 9Uxoɥ/7Uוjxե?~gx__asv}'fJnGuO?~"W_v$H`0c;, l"+d:9 ˺xhGAL:> SKS|?H3{ Ul b6ǻI&Sɥ)vH&,-ѭuuXJ*R%+1@e9hs.dcQϝ={^YcDܡ|shC^}ɦ͗ɠQ(ZV%۰W2%\B*TM*ȑS%СeA1(l 8SOL)Ft2R攱#FFd|B @:`0  QU t=P`֋ a${:`9b- {zI  жij2BRf06iL}ʔjO𙄇L|JvqɪNնtz[_Y^{}F5}]11syB4PbLDyhUGzm-c~S\dyLi"3ۍ{n`WfQT *y)AgW! ^;&!Vd&<ԋR2HxxbIb]H$Д@^@O_!$6(y0(SbɼvFFyb.BWGK=I^G._zơw7oZ=Ru~ѥfwtm87^فD:ie/^u㌍79 M2<$8'!QP$/B5JL "umf"=mZwR;)*Z^_2L?/t%'HQdTʣHk @"VM {(Cԉ`Bo{ҒQD5\&i3.7}f016٘,r9i:ږ'}?-]wK7[<.Ύ_:16oz-Oˉs'O-_y'{}$2;gLYw-CS *%Ɣ)ėKBG:CEZCYr\u4>wN:.in+tͪs:D- ϶lR4 0AK޶(q">CW;;?pj'5b/@h*L ,h1Ț [OI$TNˤD ( H >a N*RtKNf4ׂS*5aL:b-8 M{LkXd,*{`I8AR5Ve.]! ):|0  l:q~Yc/qzz^K豇ZK㕣4h)Qh)gko9gJ q: +oG--2ˠ9ٓW$8C.HC=~vhPCY&y\a"e?0šQeHfct$Aƻx tpKTDM+V,K ;_c*zeҩپӯM[s%K\9;sr0ȫz滣i=7_~e Uꝿxƌ3/[>wd6&b` (TBlY)-ptt?{bS=.ۄDҶ0L{y \q)g7oZW_kJy{pb^ySl,ϰhp˗F%gvlIoC8 ]d TjmrW_?x_ sTT굔hRГ5d0Hd)EDxG?mW~_S:[ -f{)}Q() -up@7j^ byJfA _:Qd@f5~X l`êp2ra3L*P=5L݂}ׁb0MΔ NJF 2\ļ&*L@(3c{@ 0llD4V1쉃ZȆUO.S?UkN{fΒbMkcJWO%ܨ~XQj!4Rk{( @LQLnUN5~w`ae`fbs`)P!JaᨐEr抪Ztz%j2: V"T&x)zdP(xf>qpР߬z慞hH?|Gy2 >50DBf%(h[o^E1UB#Iohy/gΞё"PPMwwty SkAQ(.<3'j!C9VYshTQEdthѲ%K/q\OBym{'O4݂Xh?ʎ=o|_M~\CIx4{¯=?T̀՞ґJǞJ%e#T6DXVDCeJj8T$;Br)a)Yvb\4鴃 (闚˭jR%A(+W "Y4/˵W=!TSlk-;C#^jvʼno^~W|̶Kuygh-?|޻^BYN7!n !B*'c?fM]fhfDl͆Ln9D'#t?͊Ȃv,ٶm+VZ8k_KF?[}egkK eRB#[:dqd6UIP ɚV:~hZcɼWm*U 6]A Zx23!@7.vǴ3Ё(8;"Dx;Tv<:Gvzӝf.nT*zW~?Y?35+$V5ێ\Fa0 4I`0LRJc uuFE.ONvvM3{w_衇Tڽfye[tz5 "=L(OcpŸm1LCT70Q$@1UmT24إ}(L!rOI) bCuLa52Bx[,Rl;[vf3b(##T9p`E'T""+נ 1/:b4+OG"r2l>K(1*ݢOmS )L\$DJ#$ % BJJGl~l(J Y/ Nfټ) qB;b07 win ¢9?jAlE:٣%Z|8T=#hTdN}JѸR L#le5vo4J{:lXYlQwtfx˗.k5&{^~7Vcuz-1Jmn,n]ji_=4\C'5u;OK%H"!nȎKGv3-°mfx^XN j-2!_0$ H#)rr9zbZ\w:-tR۳c` Ww<WmtOgpnW 3xWTI}wn(A X,gX f*e:(.Cl۽…>#ZOMφrV4sX Y8z_X4cڍ~ߩnVo%+@ G IcNeikډV_vdϼKm{~ו;uY=EHWƮvu<5[*dEck.n0hJ<$ hAE"ʋػ GޏE+vtL;ztߖWv7HV{ٜUk/Z֐ӠbOWޭ"Y긒U"W&@<e1( nãcd\o( { $pUfa*ׯc.CAPTݮUܒdBQŇY݌"vC`,I(8( I =f1$Y@,HQr3B ˪Bj.E՟aQSNs, >Z센E5U]׋UD@bLx32:12I XAF']$87.i:= 2]m9ZhIWHTTP&H,(dh?>0^IZ*̔aŃbMH@|"whKaþ a1q T1,dOa:"JD5VRcjP3J߿xH%,@WY"T0iPm/@VYa~ȓў/ca_AbɏG^}_c#}'loYҞ}O< %S:(rF `6 QCjLkҔ@uyG(} lj+/As!ՓӌӜZe뮺}ZoeZsTP߳cu+/^B&|;?ιcSZ;EN *޵w]Kr2?4;Rs)GP( 6q"0zJOCMf!M?#hde 0 `k)<̟3;ޱl-m-G' +a8ZۥA9;MkT;Gj[N ]5s֜ѡwx[o)+裷xc1g7#Dy+/yʦ܎ }kUf!F+殆AE;Ǫ?Lvxǝz[<H] " !ɒW`^ )Xz#^7oc:蘮0oEU"$1sL Cf(Zt$cF ?.T 4 tҍ6C )Sr$Sq eSY} ?=SL -SEB:**oZ9'UxkϞ7xK} +jK+Yiz5hU69‰THqFUFK"M3X1d^<4З-3*alrpք<+<0ĀE\=cfjXV=pR 9 +a{$[BPW3LE(/[Q@Z9f^d˄ )FGTl$*{ө*%iV%^^K40с@AŨGMaa #$ԩ~}uX u4/sG.$}Q[vR/S&e[> is|Šw7PK2՞ 1V ҥ<0^:iqx $Rȅ.mK`(X-SSbP5jB WWUƞP W$EEWȈ/}n:ebEh& @)ĉ^7f^[zS.zxeKZ֤[+ nqJ*OאsAh@0L^x ]-BJ,AmZ `/h\Z?G7̘ITiyuLэJ6z hmiKc=oZXuΛϙrG?NBR|ǩ*D'~#X$E(o) Ji~ mt'BDP;?U) `,X!۝5K;Zo~~aKKIs8{ؒ W^V0rc |[]w=qzhL~羃ձ+ׯ9g\&$.R<)0;JxIcyIbTࠋe&\_vm[|g߻;7v SiKJYΚBڤPH,*.8r_h֭o?ߵt9rDom="U>S_g1Kezׄ 3.^VIg Nj8K742FAY<ρDoBv"ExH9Λ1r}ꊉhDs߶TiNte[{g&^fCR~&mS%XZ<Gc&ASVkmkP@l=? Z1KQZ˱J4lXnc0+$b(hofoMU帍OJhRQaCrNISH)KIN;X-0 ysu22zwQhk@(Pat1 }$^P3n,&db!PJ(b B/ /Rņ8~Y%@ApHU`3E?*M` ƫT\Sd "rdɤ໊d@9嶀ꧺ;=V)/hnvdKҴ+FΟ>y-wzaS|E֏[aJ[Aɵ:yfɼJ:ӷn9:lHON6x@XV`tToG;ô'F.YWr;|kɂE&'m{K_JsFkd&#!S2Vlk$jCY_?h$O~KUשv*To}}}S'ꚙs猍Wၳ#f-Jc^ixd3!TYyz,Zug7_y뮟jO'dKէ9<|vzF1֙SǼjcŪyzUڂ9fN许ux٦}آ"}JX$(3x9L= \%Szxu:iќ߶ 2/~bUYViQ+L|)¾,<IR@H\-**Uץwh'v\f1]FF-`kajf u)V sUߎ s(#XV{&(۾#fBqa+WSԏ@ܰ .ߠ8+ ]shVw(!P@oxd- 94Q(4,24B}sIhlZ1bD9r3ƽp\ma:BѪ]V˃x]BѦ&ZV>ek|:8D4T\q HXQ0㣣ak!|]6 Eë4lædQbw >>78Sg.H`-_2&#KR"O=*D nS酢P(4 ݌H0차ԎXiviK1TtDS!k^c\1 _-/9=?I [Q{kbڠ:*81P>U*pbnqB`Q2!E(r`,eu :/=0C_Y0Uq Vd;@~ K~ulxʬ9[WO)tX`_.7rɯׇtt=~G-]tԝ_ ҅T9v&HOMU)8^kѿRm;vxBk'fy/Qi3˕o7K-`fLz@xq)o*PHhsEqzol{?g\jk??|*\c6|ѣGBۗ^/<╋X{vN =أO~W#akRWtT]1W9O2K%J멖AIWN'i.{ԡp[ a rȸ,עnVcvaA>H2,F'K Ŝ~ )pBʲ,D:T-KoJ|*H麍3FnB̬HTNF!`AKp KAPHOrk&E4gSg_ز%wy/VϩNN5;1zNnG;?^(wut? oSgN2s ]kǯO4gNχxSj#Ŏr8TFGG q9mF~..Ta[mԫbںz/9ZV)OڽУw|:oiiqg{+(nK¬zϡ?nβJ]\\lޠ[oK> %(iй B߲ AW]< .M)=!JJ8TL4|>:`; *; ߠ! jaG>T/pM>^Rf, ZJ-Ԃ``Ma/wݠSnDؖA< !-"W (Q&)l~?7,o Ӣ$B,nZC*E(2%ˀ ! @.* >2!M "6U%r2N_W]%8ySMAs{55.())v0T( 3UZъI4,J. 0H#lEM#Z<],p*IPzjŁs0(',&o[V3ԠDIG*۔(*PjB~ony A9V2ryO%Bl^7X Ob׏(E'ÈV(TPBςBC$e:C㱏*t}U1pxq'_`/A+\5sxzFЧK'MQJ0tXLpPw$hn;TBQ@`Ү(0RDOZS[/V ^ .vS9 k3p͜V(+_/ӫiML~Ȟ?t`uR jOPUԶsc^r޲% |MCӷS_};VhFytD]a;;\JST(UZ~`MyFN$aМ֫?MNiLT'΍ !vÿĩB>_?2]qwN طoE WpAGYxwYEjO6X1Ȳf HMaʕ Xcrws ۞ܴ鄍/|;mƱȧ(D60Y{_"-VOO_޾?]}/9 ,Q4py6ng?zȕ_{щ't,~/<'ܶg驥+.yEou:#|U@wlrٯmK7~~d&ܲlJ$U8/x0aVrFR Cm u6T᚛V#gg'dhJvFL,<{\=ryP $=:wFX(m o8mBG!9PdWHt,gdˈ| m65SY0iYnfdZ+~Gi-f:*6m"E$H &ܦ4d3qDZl2_'dV6c$a]L(=87\7AudSVkT)F.O*h\rr xU-h ϚÉ%U#Mΐu 9e&)oY4N K|,fNХxUqZ%6Tp}eilUԷ#3ֲ)gAz48-M 3O Pgxa qeV t2+x%Medjh (Ui#0e]D={~~-ÿҌG4T^zhߞRwL<0Xī6)}SվE*kXj1 'Yl,xrhE:z渠bt +EZ,pDm6 $< qÐmMgP/fI4=u*?A^ #P\8I3^,$u6|qȆxKCbVx׈t@nILAlKWmD8 ΠቃQ AUm;jݖh9:OJY<d:ݎ(ׄ[iK6舡Q[eH/ >]NӢR)W"_Eu}%.zJVUɅIR=A7<]}9_}+֞`wd)Wchpq#C_'U~ǯO?>`U"=-r*$>gO]K"4J)a[E8 I&˾7@QaTT-p"VxN Z\t84%GV1'x6\q"ͨ6ehxIҷ[T'%ɐ>ml 1fYj E 2$*4쇡 C´]JTē ;*$!ZfTh\DE iPPRzJi/eVdCUl*je euԛ4FQnQ6B3fU\y$dYR(-mC˩F8ipP!pLC[-GDecaJއiFyqoN?&ct'V+ZE%[Isd~ޓ^}uM+?=zegg"=}4Mo<=US_y<>B˃>{{K:v ][ze(S2C]k4v#ԉ`5!,SoA ; WPJ Þ 2 "gţ dIo9pYzga$N4і$)Oڻbݦ>WQBYc84e֨gV5TR/iԆ=l"PDG!׻ ZTde[_GI{وqY]1]IV/5N،VqO:q7 o+@0^.T6FUJ @dA0SB8Ǒ OqZTN<$k}0-Dgi gUIVj[Ӆ @  /ӚjQ{,F#ID(-.v)hvQ!-G|E?hPx8NNqUĚe#;}',HE,'TS!յbYħX+ՏK" UTnktﶟdfuqO?iU/MbZ$Q<3{m@o{[VuE^o\ .=&CjLH0b<.Aĭw7Q<ݗI {|z_t˧?pŒ/cZ~ޑ$5|gs7+&E"N)$rV05LCOPWrCD\ n]$SQGup~@B6xf?kU+?87@e6h[HkmE7m^ 59L 2VMkI\߰w^vBkdכ?qK=[2>2>9]uX]Uko_SWu!sʥ|)T;:2-OS5^jӺ%ԼE_v~Mmڒ $PЌ(lF=W\peWF KPR+~GjQ}o?}麏]`|-u7<3,휸'N*y-5y["KqaGB3eCVRj;PBZl\1񉹉R&YF=h^R[2$?Ofd&`0`4*a 8,Ai=#rAk cܺUPN` ۋIlv:~" T+ESngžOBWY\srm$yZͩRQE]yJؒ2IHx}ӵ@ fвp'uA.6jd65qd!h2Ogp=YiiUiƽJa!k~qg^r 8O ",*]"e[y[KA2yCaEa!AvDڨFánY'>F)^pQ},i9g=Q(zH,9_Cx'P eW]ǬZTG w䈓CyW Dǝ9KM) cغKOMe[PyJZiN_g6ZeH{*Uٌ$˘>Y.PIܬhA3T;x+›[kH`lJqP ]YLn!PxFe(PiZy&_'; C[rlU&EZ*՗{bٽ=5љ2FR-}ˊV?޷K^ꬋb͛~xWlٿ_sd{s=zʦyFXVÅQm}W+w˾LZw@SOˊaLX[It)Tdi PV-/ R1Ñ +J-gGQ8 q`~.: ;N/>b(yGoP ōv|9$gGKjUmt#88'60 ?(jvZx̼qWx0^9:y/쌍9zLBdy#IPd)7$KTLo+W( ;6z0'3M45s |EUI1K^[RwqY̧Tn ĝ䪏ػ-ص?S>Vzݑu'419M'0Ir8NPtT|&-2xM",+ZNc㑊ޚc8Q^PVٖS4/jl^ 척B|Ii@b<$,S(Z4K\a)% T v$䄕ɃXDk5%+Ea MNNJ|=SN5'!#,!Em{W;IK6VZ1̯nL4Ȩ2=xJѲRNDžDqYU3>Y@8q.ؘQ i]KytLStϕ5x(Kߥ# HZȁGhU 3P[fkF@$FSLlU^ɬOkpCkj#ɦ*),rߪR39@(Q,F.@O[YYXnB;kBg8H0WwFZ.u%]d\F‡5Ҽ2m z O q<s[/3/Bue~IgRDžbmry'^fos^ozAXo?ٿ|ȒQpj=3ܱ2cCk Y4#K;0Y8lVʍj gw_}myGݶLnkaaΨ]5&P3"f?qrɩ% ήl3P>7:=\<7/3C,5 1Al, e~%±}c!tFY҅4>|@؏',+tU&6rMo9tl(Óخ6pG;&""4YnxڸO?};POl\as?貰 ۠1&[sv\*>L|EaZ ?k>4Џ9:ZԘwܓO8SB2p)rQ,̅g _F:AX?xo~z;'K핫׮^5D9JGJe[G v?2%W|~*u}EYy-{esQr"5NJ찌5]#QQ(jjVOFMCxx4yhQ uR4$5P;_j3[(9_W$^9$68o B ~gT1f +OD^[K1]"='%$".R^ӒL\󕦲zk%EKj?? )xP&|J!sM@bM sxPkrZ7nTsG/Y4W7fv}{;It`ݮ^t];+b8^΄p!8SStʐkKdOWXpII4Z6}Ii:ыn)D$߳ YCIY;s>ͧ] H a"E"1~_("qUfw1%6KNI(lu=[v+_-ͣa--CHCi&[ ,Q/.Z޽L*EߒRce[Kn{w/b7| |qqÍ睄 jP #o{;?˯+I=69ߞ^b;|jzJw'#J^C2u)o~ޏ2px|#T*S XQ0tDr;B$5Un ~wز_8u8! <$tjP[vJP`G =Tci#!Q MU`RTt[m{]AGC N(Nd 0E[HwaN <,26SpQ!-~gGJȨ)"Ʀ0-`4nΤT[ RHβrD'pG:ヹa] ۢH= nl^?n1ފc %de3X 8 a?cE?ULaE=ypL?c`y)مf3Fh.Eyz$63s\xr%[&ʤKV< t'i!QDnZI_%SS/ԶǦ& &;(xvHC,\? E7h=ĝ?>ăY(Set/Xb.+ml^j@."@ui9E``)"lF( Xdă~0.JGdxuSh:ebׅe"MZ6"u<閐1luї$E,ն<,jȎZgUcq#]ZζˊyU‡I PR9At)%EK-~LdMMȫ""BsRvxU%_2B-`a6Fν߃K?EB,RpMA{O"`Cc9>grdTWXD|M(Lj㘮FnGXxhP Da_w\y,J1JL{)ܜR,Tl׊ØAB$%j HiG"4 u#g!߈ oFgsLh#zOw?W~R>vmu-̋ڷsP|fM^c꓏zg.U~<dERcmmMs>1KP/Z7M2'rH&,j5Q# SZ5t-qm V)6T`f lE#qt Εkhj!~w 䩒@O79*UEҾ<&q"a= MOt8K6T<9~ 7P-CeRI-.¦|ÝtzY5%C5D8y{lFńMwӋCxM(ÂآK', Ԁݞ_TIF}:ö<DS]CD$m7Sv9(H-۶qJ:uinNJ-«$˄č7 $l:8(Pw!MZ!4Ky5˹DȊȠ($tyZ2oi}dj67Ÿ^ȑ|o<=f~O僯>^8Te22pW77;\-RS6DDZqNCQu YVZQq⪉^XMH].}ݮ7nh]O>/^2#DS*lHlcN:'֪ĦDxP 9Sms+H.M!_jV?8l.yAWb3ںCoT[7ܺGͦyڄpB. y^&,dEQX1ٸ(M% %?f :'?:}+eKJ{389blbA롻?_/<&KXbIlLIHBmYpTfÑjtZ"֦%`)9&_3é !4+J< A@B}vGèLP !" x ٰ|7 0iA@3&0W UzxZ"S2q|[HcB)pw^QR{~nƬI9C8jJUځ[PZĚsQ\ -YB\*9Y\R \,+}ZePQBwZo2|HH^ћQ"eS+>8pfxܢ*50tܩR{< fy±CR>4/8$NEOGז5Nƥ+hB%3hkJ2<,5}? "('$uu(-ߋln`+eh떴Y l* WY[}K 's5羰TR  /Mi?E0l.E;ve-"f@Fꚁr)2V*KR5WnMK HVuڸEyQ\R&ȒZHZVtp^$`?{dPÉ_fa3{\7;SȒ\u˽/v׻_zK?PX(3_% pYrጂF*'@)Sض( "MޯRcBg9C~xٖ?uC7{ݷOֶeT.~H) 0vW ߏ{tsubyvtA]*!Y [_Wqjq7jPDcE*ku9^civT!'BSCW#u I^iI`֡)JF +H#א.*sBEVە9nlt; \#-[6lF 8qƑ9,/M'l +m x7/YsƓVlvW_b xag#@!x4ɱ~D6ͱȁcJAղ@QKpIA0H5(bgYc9щ1 s(o)ʕQZbe{V8.B52\4DY*v &pQ*#pfD$W6M )fae ?K῀?KpF1i{-7HX-]ww[..[>3Ȫ#$*1Ѥ1%'SVi"T (Q8jgwޣ;sFZ#\6G>#:;YTTxh vfs[cVl&p~[FZBEDCAٞw?sëޯtV.]위 Z`dO6 B)BmZɜ!$dÍ[hZ`QVd*iIi^Tf rmZss$1%`2DOQ;#[w_\Sn@qq<ѹ޽wݹiÆ/{8he57N\|k\H?~ءjrGl8yuNu~et4JXV$};e\ݠ@Ndń2M|<4]QuuIWg-}+BI M:A LaHS6d'O%C.re58 ͕j%_RuKym^8`V,fwNDDM H4F)lUwXLj&*n R#*ڿOZ7}_ e4Ҥuxe'd5~؂Iu;ݖizyR]38 !N-ΛԷZ}iSafy \D:ݖ2!yȥW鬩Hfū\?5%c *ˈzZGA9Ĵ,x| CX-.ʱNx@6I}׬DD4 ,viW<Φb pũ!7:Đ0W ;a<E1j*+RZ2 8g? j4klfQiyFBLԂ;Έwb%N[_hf 92ie*Gz=WԼ<:iޞ lq䄹ܜb[StA ^xnwg_3=9tn?~-Զ1&˖-q??>QE9 8ZTO< {w/ٽ4*JRuPM`$_T)]//׮hnigu#S MHEb9~0w>2aG0ڔ+qREVP ɎHEOȋq pKڨdݮxyH;no8ek&}g959VEE1B&ĂHxsӽlqfhD1zQhJ%(4oW9fYV1g3ER7G.o/ڰv-g_W^ͧgi2t_8rdI[} ] 2.xb4F=rK~nGzu'&ZnzJb*cG *bMmlǸY #`CgTۂ2r!/z6]CVEwHN;ܳ(p,d#|:<̚|TJ%(iV^N=gwwPx 'ONMU蝿g>yp(/DqnYx:v=\552ጒ8B)/_z]"Rܫ͂`cQrƚHp!;5nY^d}WHGx@t>* *Oi4e XI2lb:U(*|,L0Fܵc8)@rq|Vy"\{tԠqD4+vOw?@n5V"u-çZq13jVtk<`MiGO l\]YlnW[F84B!yDS^#zA0 /}"Y)21|2R]'`)(1+b~EmezД FX?}g=p*QRb>޸mGo1xvmnp-f再z&'##o}[ƈ:;VaSIl4>̎[ڙ}AC?^%ʮ  3N6`RwO߹njWph5 G?2RE"( '鴔,ƲM47K ~&G[ %c:ee "3GRe0HW cr0-JLW_4,EMRd C|_Z{mfAbFNJet#X6W]al薉0w1UP)& 3w,Njݲ,ރ9^P1U йz֝suTĘPo:yPё۸ycHDToFi!y?t$WB>?8:6m^o\0Mg F{. L܌C AS?)PA+p,AA3b'I`w1(۰|cZ06CAL[VBAUZD W`vspqp$N]t9F 0I!UHXo۲=.R'{VuuVضkG[wu:269\1c.7ʼnӉ+r %wl(e#a' \Z+/~>Ѝ{Q@%729%ܬ`fo4n[!tn( B)@  ƉL Wv ,$8@;EںD<͂9cPSгVCT nHPZ]o$!,bC<Qkл^Dke[2JBv8_%XË́<G$@pGۿجS-@]sXy䦩~^ n}䬠qgH®9a[kB^)>7Qn߱YYXFH3kR9afFVD;}-M.?ylrXla8{G{`awܰꥡӒxTwVa ) ,\#I#j#D[^R܁Ws +[#"4YZwiv仄SPڼ?2%(1by'M̰ L BQ NaDD#jѡ4ɼM< !K: GRh0zMJK2ڪ %hO*k$ Xa5 s%IeY 7V&F*cCrv(9G!h=E;PgAJqL>VҠ-,WeC۶qu3M ޸s_pm/WO?)+_|C'c\Y 8P?mvm/divaiiveŊ( sfKg? ɱ3GO{ySz-P,d#/|ApU3Е[M 8,|}GLy) }^]],5753Jh'g7>Ev5=G/0v ca"0L?گyO}HH/|˝o{}ﹻZNN8vy8S.xϪWWT {4K (TS["m[_z{ك/h^渡{xK#O=bΘ9B[06YC-]z{F}fq+MfdM #gU͏-wČT^, tN1LyVD)ƇЄI F3({mes"-c(vT {vvX8MV?c(X#z%?1kPPGd&"a^LNdmt\ǃk m] ı$^"i3j!bCQ7$DA a⇔ zuRXtVfYA$p 0B Ѡ2F<0+p&bnI??mi.2DC/F&y %ӕRtUh#BJFozyHaSі\zveE!JL L a(tP2_s36fe0G7fviyo;^?vT5!>cBǨ't*o6ԛv2`!I ]Fw ޑ'# }ժ?Իf׾zgnޭ\a]jh  t<~YU`[##cǏ739B-/LKe߱!Rx*aܧʪKS] Rj8^zh?D@ 67t%c(Fҍ"#]A"y-C##BŠϘ'U$ Š81qCGX!fc4<[AUDȰW [w]oOZVPgZBN|t gD[#IBU2 2o6E& kn5mTL :|#zl~fsfEwȃ^w$\<{ubCP1(G ٬'_?Qt~E[JFqllYoBUÁp3P5#GWJqVז-ʾq47FKgWjm +Q3/>/~՛׭\x1dFK;ssVB10fM0g efb0~.ub8idp!44b5ZrքҪș:A~!e'hȥh,y3j{p^(MUMۦ[ޅ ~n71ppl{y_o+=r_][7<%kGεgފfyyߏMMRkݺ)ebח} /{_wJPl&W;msݴy놭Z!Z dTRt}#>d>rV_rwۋni?^uMWq3O?62=Qr\)vD\[N suWY3J"X{;|D ]Z0N@bB .!{4l9%BDQob ['*+"x}>mOSfE#fAqXsڙfH.Kա?//kC8>L?6_G&f|\M{?׿}|\sԮ{CN,_P=g'U\] g 94'RittRk- dо7$%:"5x$ZF-ͱr蹎JAs<{Z'492:-񶷾roewsڥt"ys:rܔT8&L%H+XXJy0o=-ٶUS^[햡CǏVGBO{++kl *XK1`F[h)ȴv0ysmR KŹ ZRu ^8Kbpn|sexI$=J!fb>bHq"LNs9Ҏ>3` F~DZ=#Tm$#C0yfqz"&Ô$tПJh|6򃎲P oFIDyim D`^D!lG0Cӌ@ĈN0 ()ttkm-gʜ$n2g-K)EŸE 0ёcWF '#<¢O3%\J1dJ1BƌECKu۶%v#,޳sZ͝޲=a$hy閽rcG\u5?oQf{}H V7>qx3A7$OOs)dLzK?_v,זfS'~]?VgOG&˞Ͽ7)w-OC9grbL=3gtN4C#Pjtŀ?}T> *144OF!+@5dُbTapH&MTXd>L92c)4E [lVԥ}%bZzO_|7GJ̳y \,ehIY8&;FK>I;7[CG8s} B6yɧM%|S'TyԩOoqf6S.NJ_Wc#G.ǓOoݒ/fc GleԘci.UA`WhOU#;FM14ב¢K8fm%BDl(*S0&f8-"up\lih+8PxVnf cý=|`D(Jnvlr{iQxG=eg.Cg|֤]`Ur,sM1N?3 MV˫7fͲMaϚrgtp@iUs]]~Dagdh`t|DMBv}CssPC*e$,*:8zFS48n{z''N<:8:I!~+_7gu"=6^w7`-O?B>[ZWF[>B>W[^xу#s5?LfI8myM9M?kˋQlܴi !, SeAL E5\&D0{Q:%!#tcj.E=IPMhX$](.**#F Dp$4zB*x؂ 5Aj%PV#BbJ4cs]A&=-]<> pgU%țfFcӘZ`Q !Ѐ[uC!Gh]2.$1M Sc0CτKTQg eITzR4#쎆yCQ3i9U|Hɶ.?Qv|'cGp~ia0])c$?6Ah]֥~ckͤ(N/1@FJcJl\bVɔ-W\=_lSL)F.wcO=X; C Rh3YT {D+/z#<~xphlP(z؞#7E^JSbTxf0!dDI#^Zkms-Q#ip b]c e3όȈuiԕS8 >`Ɔʴq@,BԲ"'V ?Ͼ;=kmmUbr|O)k -}(6dKLi2bvX :R#|q\]ܸ~/jE7\sԺ(Nay)mjزu{Je 3sG900>~qnyh_S~30żRa]}̰!C:n>@cG@ y_"K)p F 6!I uKbf(fi`蕵.OJ|7(jADT%)aBJLCЏ< W&)Y'.Uݚ[.d3]޾ɁMSC]%CS]o"/, _d~oK\`*b􇢐]]*=w}Wv:,icF#) ekvlhB.\ꭦjVWWZH]קNHh&5陻s}/1ݨUG/KĀ"hvlL)xQբ[gj߲-⑇޻皑28>'87sRQ3LceT_w=SF{4-426%WKdb5{r{νw6.HǎPܺ}HW>BJHGNASE '8Dkݴکi4RkV.&6m/dG*03Pc:`X\PHNTaW^dA ?dV:a4*Ͳwf9R f֔:!5ʤDb8#(q A и} BJ"p $FZA E L=%zI;2gAR+LZl34kE J03Pր&vcF1@AKn!3HU"Kx(?ֲ7b왋t~:TO ۶E^T( U'7^d6YٽEt8ѷU,wf]>ܪGXYu_my-_opׄjctPk6(<7ERJ ɪaD)fFۍ s=݊V1gt#9Mࡒ$|" 9=TMJ<`CPf|0-31b́8E5WE{{J\ż rh];s~f|pP(8 /,ի5 r/e۷x HYSd!"W|N ׏bwIUWS1Y.kN1dmqqaa \)gjvP ?SJ%meQAmnfQk4j+ &ChΞX-ECX0 ~_N Wʄ :Vۛڱ%%OL2"Qyj&3yצŹr&6m8~KTnڵo-jZfyLoٖ(䥥zϮ=nP&%.U-ϊeDא,e uAXS!lh!9rF'ژqt<6abN(e2,$D|KYtR(')̙zU8VS0&Hduuԧbgt)xy!CLPpDXD 6GKDuCn e>庪t]DCm+ė Yd׏QW8^C/_U QE#>aˁ$&4(G><+7\b3(qiu |cly]['woX_t7k U޼]ud!UB6WlmozSg̅cmљDhRzhDE%% z#4*]6lXك߷~V5{~_om*Ǜy1bM%RJGshdK:/\Nϝkuy"őqK]6Mnx/X$Jvczgllzc|j P`Rɻ Mr-M4VWtCW%C\$oaޱk\ dʡ:a V;_WshUx+n;̾|.s =>:<66U9kj ;{0.r'DlYp?+.#L𒦪CU1 zRL5LelAyyh&ȡȨ!Air- e"+ sJ[6F3Y򽀂LF7y%ka8?Lż8tv\HCgd hjY"6$|&gbf$Ns@!Rw՜2]ƌ(O) ]Oчs1B@)Cj|[k<,Yy,1QX%P2NRtoɱێPkt*մm72;^xw2sșT\ulݗN\1Ooy󟣁d/B;3 86MuGG*apS7 \(iD!Gzۈ;M2f}%unK6ﺮ=@H-L YH@WV_W-ne$ӠJW*ìL{ǿ՟$sO;F,yË bӲ27mIs} *X,h,H͢BH@0T혨̙)!2: <TE ,j1`MٮY^e(ȊjFԌ1z{c(JFmU "6)DSW| !@NHGaB|Bt&{OJf& "8H "PŞ$a|23 fYِخ0w{Eq^0 t9]PŁ;18w/6cÛ6|_9?fJOFbؙcu(hIpS+RW>_ؼizuRO_jmU' ƍ[Dhن v5zu[۶VGY9'E#;^ɑCOH¶W4g.e)IcJ_EbpYS/uwoض幧߼-R^>r`eeB.6Go'-[Zǃa3 iZ6g̡gfLYë́eM#v *5<=4[Q enwSVҥU &6OdtwKsKtNw6>)E;%D`󶗵 ck6 ty;,C=gM)a2 pUU?Co{_[5>wڵkU#Ǟ5?ɒ[UoI7 6\ {eM>;zl-Ҟ+;r.lK s%@sq oڂa}+tSMݤE[`F^.f'"@O1Jӵ-RZ9";tZcM%ߙMv=3D&ө2]HSGB>m׿կ)>~߾lU_3+xr[֭[U U%셥ё\>KO߿/}s/ ݄ʆǧ&)?PYEUTGd*I9 B= L8]C=t\#QjPeٍu%؀3Y$RD&0)nx,zhcLO6?wo]M[I~o|s>fĺ>}DvBp¥Ŝ^}UCݠIGN; n۶M!{]e{zZFfVG0{#oi~quZziU]2]y#(ǞLLjmepUZIP%Ү[̓KkCClaunն(LdCRO.XJo7/^mݽUNM/VAxL 0}lo%YɠևtŠ`0Mrb);Cct[:6L~x[nvpaԇ7ƫ](NLSfnݴ~tN֪ˍzKk>b"1DX(hJȪJshqF=pN Œ"<4b$*d*Ȓ4yݐ؝A%zmL%tLadp1^ԘXJBٮ5UA1.v](0 QH6`KEkhDs#uMՄkfASAd($&D(QzpK얃a?J]UC#hԽl*I[l֜J\C.j6qva 6V/.WW U0dYZ6:"nNa"5NnF.ũzM_s <X Jdm%R掄_1Ie E?UZVc3CT.Ю zth*$kC \b̗ HŬ6=4 8-t+ $J'~f6hN6|D[E1m̧z>x^vFhryՈpcbvbRQzN<(%0zVѪՕ|1^..\o{N.9#䲶<~U...-l֑Syo]8^oC̉rR B3gȔٞyF,(n7[?64/f6t!3 W Q4 )%Ç ]tݵ׽?o~]__/u7\JvQD^ueoz[t-{^C{m߼w̩.egk AwDxq!mfMʢ!ttAhcI#.u̕UIE^Tp֪hB1 g A_j[ߺcȖXYXfap)Hʱq~X.nȱWlO~Xޏ~u/x~Wm%P g/K <5~~$k>~;w<ԳYYk=s#z(ͧZvm0`N+* kۊa&\uu,yAh{dEQmqQ.[ 8Qє6L>.Z>zJ4G"n"^L,ߑyLM@TGpͱ̙鋒lwԆu导=q )Roϟ?] )RZ=M)$BWG&~@/K=^˩Y-  T.}Na|H[lf?|F&Ə>N믞9wm;"mJOwWf|ve ^v˙FJ#Lxow6m|#d2z\[aҘ;wspc#^681+&ΉEdH0M[!w]/3}nD=X( ]R 4hk<9=..)W)7xYrfs؈fhv^Z .@%8Ԝ)2<D6`L!tQTr}ZK2p n*\+ m1b ><|L( ƴ`-5],&\D )*r7#ej` q%N$*01C1n %\)j<۾uPzSttSCN$&!T7]=Oz?k*{ODH+K}b崚.{K;Ƨ:W劺4t?>ч{EYȰRɡ5 ֦!JΌ/0*>L%%? B pd#̤ħ%Awgl|@ǥD!27ȥ}g._sۛ^?|d6i=9|Xcp}Krޥҭ7?Jq|a:2z__?S݁<[nc,G~$ڲ%zϿj{{?}J 0F V9l+ʆUQm|2lw uP@wr^klu` ReggNLR3hl2YuAIx ^&j)X֪6Yt"R]0 y[MmmqF=eiKr+օ[Gdj˵եDv5/?8:;oH}lwm@h~ruZIZYin4='t5[eagz]?vj˓'Zks4w]e>{?uN3g&=!=@j E+^QAA`B%!@dL۷1s.wI|(RҙۏČj-Q$M@ rT"#'h tisԂٮz$0|H$b1ɉN4,\ l\Vy{.;{Bbi ppl >GK+`| y!E(*Tp-W4M$싢8'HG3iQ26D@&p+"hhiӒSPC\۬{ΞmR dY"p8 :rDTjlI,z [VfeI@!;&4ԬMJ$I"jVGemm6a56M)N kin .\yԘ$܆R}VyϷLgQo< 'L45ȉp"˗. /ࢣ߱*KuqՒ( ,/Ct骦Db% >X&[)QlTw\=b5B\#U}ѪkdO?Y+'VDMohde静Za '/o#=ߵ]sG϶t,(K(R( :E y}3 E\U9[98̚!%Y/PAfP#WA$+RH\ Os?w&w]zÍeu?N¯_tQveWx/~?HtkqElZ蝝+ Qx X̥\/=t(HLM: h\R/, jȤ,+!C=DM/K&P4. E)3Fs7'XN0\ p"Cx٦T]`D@aq>ItP9)hGiI#Q GiMAf`Vt@ynjU߰vQ)[jlxhr*KՍ (L$E&SI I)YjnlLd}dhg`U"(@tGC#MGEE p<ֆF3a ]-̛ dT|Wl~Ƕrj!_E7o Ha[Z2[C^s,h$+8Yd2JpT.iSJ"@R̋>2?b駟]p:;:7wllid,Խxr/Y8)|+O{鵭bg:9׹OOߤh(N/bS.dQ*;9ѐi|w{{,[ СwvKQ,Y4n@ `^6+g9= b$kC~xD]q  P  v =AЄTI:hyß%Y݁C؁Q较]݀LUԅcb I ND`ڛR 0p1:mMpљ|5Po{V)-(eTCXHJE!bIl4#",ןڜVxۂɖՋzJUɹްLq|'n-Eݷ+/~ƙ\XB>64񬔬oiCʡ|Qt410t,H$ŷw `lZB(dXXj1<ԅf' M&SѨrb$M8+pnj@H6LRjzu^rSbH5(VPJI)ҿXnzF,ONQuf""DL~zh~eصZ.'չfV GGgrEӧ:z)gxdLJ6* Ϟd c泹\$KL}gkk.RԚYjb*YC.:=cANQhh@~3GR-DDaigkzE!lC* !ێ,@*օ]!Y0| l ûiXeLc%EJqk`PE ^p\ gFdų>$9τ^AJ#혚Ɖ)v ٦EQMƢk]T='Eʤ%x2l>"9Aa{Jh53K'']d86wܹ?s]GN|||5׭[@2.8޾y;<9xbEg_r5WsCN+e*T]$|pw(Y~TYq ?Q`3y(!0Nv8."H:^k=<<0>\veB$*j(O}J_?xe6NcIX,a O'{oE}/V^xLVKZK|(8 l23 $␋6GK7 4TTFBQA[*-,a,M'u*",'Ps?{U_n[Rĥ={zS67FOֵb8_dg,n` TyWpeziò~OMG'765vv8p?>B Ʋjӏ`=""nQ l [|,KD8nN:1ɧ5YC7 >9c89fN =ۄcK+bv%\" afG m3hO2ZpXfE xh`ɑ3pld*ۢ 3^jժT4{ǟbfyAս꽹eN_&~P>jXv<2\8}9ZsYLcO &f֖VƧ [%YXTG;?vH>IdɅ8CލfN,'=vR,+6DyTtH(-CH>0#t8Ra*i:\.'ј$ roLvձT "FdXV;omcegoiLbrMVбWU"PTSQ2,aDNb3!>tJՇRPM%#CR}5%Cp88gyIyD9Y:z[|ә s]2]D4tys njhҁ&v7gXΪjhrGa'![ʢeXDP%.Vғڨ.GR@.T FU˱g #hGFiz$ɚVy 0KkFQ?!ZU3!jí"l& gx발’L,["'bCP&,WpB0NUŋ@lóв UՔ#2"lۦ4D_Ϋؼ ˖xqwG{Sqņw/}9Q'^{{⭋7 Gmks瑙])w醇o ^<Ȝ(Pxe(o/hkRၶ J%W"SM 6 @c6ANh.Kz +HaRg^{_z`z^3Y\[ժ=s5_{kۮÇ>E ǻ E= ׄ_zdӛz~]qL kZ0xŪGNыdwȸQ᎐aö /!cyFu(ȱ(=k"I<&9i38%3qewI|]yVw %?lmNΕj5lc3sc%|ՂXw{ߺK%XJ 6m ˡ0/GSɗx񗿽{`D"&٘^;_$,:]E)~0 pOC% Q?Q*ںzKN_lwђǾe$R.XnıZ-p*Sţ~Jeqѯʶ2xO}#c1$L'a{TZR-_~ŵJծyz6 J* NfGIOtHZD#1cp@GҙQ,PLX'PIohwL81A,yD0| D(J$Nc@, +8cc|,wlxu:$1nY ǕW R0_3iR'LL,  G[82UB T*0>M`Z&RH-݆wmjExFX[`YQY{ cZHì(חAdDXD'$F}[sJ[8_y|6ۿկ|cNoLG7UMr}Kgyc'We./n/9HFv.Q|Q(ԕEպkޯ~tvx{wo%@2:(!0.^]:mьqQ!>5(41T(<Ϊg]r5S?f9 =zΆ5e[ O jUulʿ>-kZzzzgw[Nc `D-בL6"ͪ(֟g`6BIJ#Gq )$"ۮ("DOkː $E}fdZU!C\g_1U$hc\d``7ϫg:mNn;Fi n=IH͓D,kEXu M% "b b\g@|t(׋-e}!\γ~n"hAoӾf&Ǝ ,]4>Z6!p4E^<,vsr,,rm ra]Cmϒ҅劯Cfmh33S'wuF+`T,M.dÙ<@J, I;4i߉wfqgDKúmsYM KYjq`dz±b⩆l @YT jB0aW-͌OEyoy]sD }-UC@"Lvu'ۻ U'= )H,b'3O^[eƛ,\TJgCt}n|j=m$q㓩Ģ>U~o͗}VaC9jڞOff\t? VNv.r*iO2,lV"M|3qAq[s©P6 9]-ζx4+JJр#! ZMߤ=rd(L`aUkUNE}mC;W쬪<˨RpEk\x BkWˢ# v]T ؾ$K,=R <"$Aq7PhBdar x:HA-@)HÒXTG İp{_L΁Ny^E_],' W5zlq)Ȓenm܈ f9N<eQV5N vY3jN lR(fGR_2ibpyC%fi 'b6Dt=Ƕܺ:mZ3_s%/x~bdd4VDR~EVԔK4%!* <,mHy< :8=8̎:e}RZтC8Ks4Γ Sv`X;`ZTEHQ1x%ZEav$b,L}5l@l9 Kgy }Ƣņ׵*)Ne>0n@B9hˋ lV Q ʤVZ]9 *Ct EZp:"u(F:;{PP*C1% VzZFU G?O566ԧy7yhVbGʼnOѨ#>鋛=]T9z]|., ΰԎ▆NQ͜D]m sá׺>Z/>B89 Fe|4(,iGmo޻sbTˁ ڗ <+5w•Bc;24‹llz7᷿{םCx ] I}}G'ך# c~mA"(AY`*\ex<P[I3 E8clZ=2pW+aW*Lv.?S#w>޽*GMu[mjx/[+Nꖩb>4S(<ٿЌR"gNbaj$~xHp \C?緝x& `'{+ښ ˣԓڛwoj!SG>= عx"S}uϽ971ZXX*׷|Ee}тr6mNUs9_;fydž/y\$YwżyyV:r#}i41ŤhY9D]3N]rLVsŲZKR)&a%;P8TB|׭p gMbʕRBX| Oy,A22:@ ^Xf$6kqj}|Ɓ BY؆ (x[HWfc|xUnMs51,xjǐhd`{3b4{ @/ERlUX `^I '3d /4;l8!F;ˏnu7sVl, "KH~E5Q~ j z G/x篞_gwo:gj iD`.9w JSQ 3yNs\Z]ܜJv5Yu(}CA>@.\  Vx(FwX؁](a?J&|cSgscP9[Ҍ\iɊE4e 9>29J)f٢Qt P| 3J,i.Qe>LŢ:;iJr]A٭dPF?I?lhn>^pxE睳:7ZzW =M4-^#K+'.Z g|ט1t{%Q9|+1tGI7ZL]OJZ߹ |׺xUz-.\e=G-7~냗_k 'b\GxϞ)m$H(p^SW[yxQI:JXbpHtR~n,$z+\Qm4xt3k#i@T Ṧf㱬* 0i-úl dMyx  g!{ Dj Ș AvV!3 R`=ϒ(%-B+ ;1A!>ɲ]`=MO)!6 hJek"e]/,GsQl&e7zp&$v^l]XBRB9",rѝ•XB<g[d^s􉣳vC~xVSQs*6$KT,W>^ijML>y=g nJMf&s2. WjZe 4~rlo(N8N`ٖ. @yU+L0ͱD$O,^ȡ%4χO>mnfZ mÑ%0*x{瀐=ȨRh8d\6@رt^P: =t n&o/簣 b*BV@AZ;<',&t,tus bd0@K, 5yOY1 [5aeڥZh(CP۳c۶}ztuuс(K`\:hdpeC8Q7X]&Kz 0c#F`t>K|Z0 .ŕY;.mėiRqH!fVML{$s$RlICXwBpf+_om(Nf C.z~:[2֎>r]2x?pfesW|ڟ~ v3&k/3.ɸ~ϴH< թt6NMNaK!D2*,O-.HApÒZ. ðqR [)sXAF2|GBIycxO;F(RwnXȁO 4u1]-W-,kDt[{+hc勾"O& Vn(;6*B1̉;:T|c3,^ֵtiDYa%7q]j>V?0'&zt.fF8ٴ㳲KFѝ&IZzuZzk;Gb]swoy`;[f{g*=_\n+[w^wFϏ~C/2ߨQA ahvx#1<#aovc j6C * YmfyU]dNd3l}Q7ύ'ҔPW(.zoy/7128̽tҦt$/'{2]JW{r$x>x xffMscF c;:l¿HG`XC'Ņ7 6AK`[88+PQ|L4q8(쐮HEǠ܎vv4pY>m Omh_ϲu}+k:7~[fAYɱH(dZ>90tڊ%Rc#d0N8LT%>b(&q,5/{gg&h`H8'r+d,JgE߳{O}K+īeGױ r2q՟:pĹX"z|l,[)T45b9TZ (nj 7>zgLڻh6ОG_aI(EYgƷ.cmM/hL'z=Md}:٘ Kh])K)>33W%}~Ն z[2qO~0CLOE:/|XOrW.mN @^qRu ;rixn5SGep{&p?hSqLu)px,UsQB~EFHTq stKj(8Mgo_ߺbE;yiꄹKzW_S29r/3A۔#qߺ`+GfsǶw~E<867U-( = kO\xgMjMdVsE65ji<+G28><>lPlXAxao 9u֤LǓpq|^O V.Wb=zi6:L/֭>mr81D}sCgL!pl3\Xͻs&זe,2TXECh ˉ,*&xXhċέjc QLSeC $m-˞ ˓3FT .t&TR`3iN;JRrXjmNFtfK1>3!3.wVSS!RIIӉ 㤰6͖+Uלź6xBGԺġgt˭?ػ*%]=BҀxQA `:#p(LE~'hᡁ|uW?5=;7=Y*Tr|(xF k.7\bT_ڵtʳ6lUקgG-z߶ntyע 0&bU M]/ڛn;c] 1+?'&sYj^p%?ӴL͍E^99=჋d{ ,GgiRPb$œ \!Rz干a(C*u^cʉOe P$ FU-U3 wZ"䈪ig)Aߪi}!`E" %<"8VF{(>̛P"-z4X+JXfA"rw=8"{`Z M0ِ ZZRJp; 5Ul-WwHR#M,W6DVhtq~ I …s^0S)hJ5cg߹sP7n{ꍁ]O(]^!+㫫W-R)z涝M ~~{2n~"ڗAL\|Ir٬$r>+X.o˪hr?bxhbM3SÿςXeHKh/orD2ljᅧ?ز>Zw\{;W?v~xik.WjS@?Ni/n V*g-U=]{MwܾohV71ijV1x`ZJE##EaE_xѝlg0CJR87~s^R d& `y cbp("8-P,'RբjhJlU"Sտ?Ĺg>l<{mv "x=!sl7E|ғ/A2#Ű Qx!]UǶ7Nu@z l`;ֻٖ8Ioh' λwJS& 4QMbЉ>*"5(< K(!aZ+ 3$]_3tL-o抿V[ے>:]: W\~I61Å@Kkɣ+R97 ܰ\]%)UujDqVvu/4Ea'jSC@ 9Nͭ _,`$6+5 Ao~?1:钋dՐTGn4Vp]D\7o{gn8 R XāOk#"?g!Dc bmoxTc~d195^C*/dsks#ө}g&~/ۖl`jRڳMphD"[};ӯK߲`jgz׶^I)d IaifǟDSΞNOφ/n7._1]}?IiB zQVYX>95Zℎ>N,gqF-b eTƦg3&sL2)pDV ·wgnmzc*3 e(c7*hc~jQDQf) So){r}zw^zZu[<7~h- DZzz œX_oe޶{#d  ;Zw#WIwO =wT`ҧ^[}as~2v/=Y׭HҨ:f&]S=BY0Zf::19F 7~H5+%Hag|ؑSw|JƲR) Y9S-l/IJ0)O3MCa( s cw\{>/,e s󁛕H$Oa޸J$~O(l!D2&t_IZvn擟T{o?]4'%Vn_r(p4PIih;s0hĴBp X_P-`d-ƃdlY"NvA†>SqDaQ280a,JUfxoges($O4V=FƆˣ4 >r`9l!u< s†P8kbJAlFaw[ò0RI,'l]eg,&1ʒe9$E㰀mI<:Dwa'V5lO9Dqdx_ 7zS'Y_2 :f][XJ|T%i1DhelU,c$"4BS'XzkT lZ;^8NKKkKk0{'Ķۧ/(;2X,_X|éc״4\UP kdހߡA":cXomO<|<3U YT)@4 ZqrIҢ̢~ww^x'A3̫+Jt7oBzB K>v؎}~n:}_OF#M#R4X,-m!ħ;7>zP*B +ښJ>rWŮUwT;%3oO^ѣ\{+./J|~c6Z*|(iNb'SzC+vEH*@"2ml<VB1EaF"NW-,˥* J}E_XP@:p,lIWb! ^pea( @7`ִp^CT0HwtzV+-]pC}=kd8.RZƉ^J5tE<=9UL~-(9jKkMC=+Q۰]A>[ BN$ CP8s>@Tυ6cl]X `'k%[SG!ER)g{/}wy}:‹dԴ?ct0'jh/K'p'%& urtk{ \(.H䎽׭_~b|-ݞads{'OۺtuZO;>~:ْhIk T"9ai/d2zG}O w#=DU5ksaQ?΁D] YnxupɃxʀP[@e תuZ+՚JKtrv˷]w v5)޳aUáT'om=Y&kuخV+G] m5|00pBtK4+h\$MC=m,4?)94ٹQ]fYUNCU!y?\LP:+ځ (TGsϼx|BXvT,:08??pOci1]:we B4lWV 7:6)N=PW_v|EqRh2D+ e9xtE8xB2ʼnj$Y2z 2tT!9DVܸv$I@~揊 l3I.N5ԡi]ӛ*PkVEyPZa遑>;m[;[ܔC AFx&&'CJP)痋 @^bJCkIſpU|\=L0բQ}S#7]uj-P2ww՞5f#(\ME<Vf\p)&|$uPĠ_6jÆ ,mJ4%˲2Z`7\xZjxt8rGW, h:C,2I9B@d:qXhNbuGk4YQD)JrpRq A3޴L/Cn汏xq tf"C P.6BÉk HՖt~uݼcAgáT2;q|ID',؎Gzi4|9q4.\0eފkm8 ]S‷bSX*pȦ+oR4}ўWӻl%9^'L{eBxF7d=_jƅ#_if3g-Mۘ={⫟.Gʥvԉ8ph:!]QcDn{==}\8qv"!?TR.CjEo[QOm] =-Uμ熛sULVԺ| z~N(\|^~) *;]@ eKa K(Vv7p EBb3s.Z;<~ȁ0N7XIDڣpMk.-,}:Uha8^QttzqI,`#6e`W cA&p0lm<0/A`/M1+Q(a*bh[츰Q.ƾPqq2D3n͢~70fa;btYU vΟMmO,Xt)Vޒ%6֖aG4;J%Et"39LR rP(FcmVDyivnrvp//sL X5P88=5yFXCD"Xr@>yڭi=K %N})0=5aibz֬5(dw[K$p~~[GzdQ Ca@_/cmEYS_>OvVJu7쾦k )"-ݙJxFP+lmi٬ s?\z-BYPD$ҭv޿cT)@u ޖh4`$"-m- K7bnY S1EcgٰOGxI3ȁZ \R>ia[.4Bduqᄊ}:2T' ?~j&pp89wjaQ6" Ё% J Մ4ugPD-pb P 2$ 5a]Ã&`N M*j '`m/4Wle/Mml|LIwgOK~vP/L 0r,^ so$Xxv- G?GPT붯2zj^pqf[w~6O|ᙟC*<,b0+X(ujzwbE ͧF\kLT?<{βn9パoNȿǙ%ȓ2,AA^ُ}%/vتYVE*:vy7[Z:PZȄfDXM4f:8KC&=Ѵ"m < ńtM ,aa6M)RQ+KaIWwv::=eT]}#`{[24~c,XȝOL4wPFRXEʬ^m4u]B xFk \?B,QXU؊;Xe-,Q< B>-ƗأĆ&W$ !F\~ӵÓ2UkbUzXHOs@4TWIxZZ:>u| =LP(5k,e5*j(@_ Lvn~PB*-=ug?p.^fZٺF87jf33㎟9ֻ~ϔ ZfV3 3:Awu6KUF{^LeVB=(5w_}췿۽&6n+<xW e |?Gr\WwǷ?e9xٜ]7|t~Z]3XF& сc8 1ՆifNqڋ'4f^\(d 쩅iYsP,uXwWaS2m}d+r952@Û6pV(eh.0Ur>;1902;%Џтpj:: 6@aZ4 ;񮀗&α{\$ԆTvhEP<7Mc "LR: x4B.],; p"f-AMpL緦jQ>Vi  ({<>. o۶ ۜUkMJvo M|sV\sV;}_ıL}fXUiio=wmixmAr.E#6,]YP]NRĢ1<^GY9  Zo<_}>WlK.gv[`DZ6eEmBIg2EDe9ەcl*}u|?jY%[orݳ}ϕM7uva"u#IBcYݒ||=h?nY" d+3m?@@<Պm{9µ]$Ȣ'| y;nv k#CllsĘW)jT`(X3]DYulG e,<`' zGB5N>nZhrT`_> o 'qMega -qyl؆?ie(uA: a6RbafISG )x{Z N|/E"Ixxtzzr6|Xı@؁rRvժl13uf/ c6uC)Z#U+eh w^w$('Z-|K<MUֿ?h$Mmr%Fp_Pj4iw:}a*! 4ġXTх҉מ8r쵷}4h=rŗs9BI.b;û2d@V[شQ/.d&ԖK-[D 7/ܴn*u)v 1ihVG-qO#,i1(.NV T+L4/A~,Kc.s̓#l %:CbRԊf~?z{פڻK"sr0Ƞ11$ jvV(jU3k^MrZȍ{ (8=ZSmmD겒W*?]D49{(hY>r9Q<,Y|kZ 2K8mIZNbQLN18,w9z( @ b`+Yj_Ҳ,pDx:JGrPƙB.>5?o[6K86QyND4eWqr+3~3;=C r [lIF"ccc}^8~@i!LCyYyz꨹aej3KvہU,bRdfnY`v`᱙A,VjewaTNvcrvAB} 2fkՊ‡R]]AE&MSRg~4‹/nzCmxB"G+U$Xd}‡V5zd-dE $P8&&WY`8ٷ~pl޹k'*y/ZUEq X'.39&g{f3٥("Ŧ)_Zs o;f?_lO >\|{ [ w*`%1 j LlWWg/~SmKYVG,-#w\wkEG;jKD#X!X<ɲi:R$4?]5;;:j8 Fc 0ADҳ7pX#k'&P_}mf&Y6jv~gUog6:q33}7ߡ a'ӭ>ÿ'`Z3 ZiK 8aVA~!D!hp~ SVC'][KnC]E8+H@ A;~N$ p?gBJ$h\=reOx;/Z4ԅd8\TmJq*[]GAد"2<[(Qw 6֫06\USǠ u9R3DWWϏqK%Lu1D@c!M- )lɥ~kot>0Y0i5e>0EqþpfkY].³]{N*;m*uȷ O\_OKH 2G:ƛ]C ^IGb̫(Hj73 ʟ947\A!S,n' f#[;^}<ξ?5swTφk_"Lt H M |ܕ7n~dl\IpSdEf4yYihXjYb8$yB$dpͰa5 <<%wl0XhGdK ٗ|wew=Zd9 E~OӡHjh_N5@)6KJ@o"B\g"A|Pf]Sb>&AV* '], ..HOʴe6gī/lTjAyZu~q(+MTWE}G q[B8eHx2gVnf/ϾeX,l#&h~??;a57= 3ݫ`_˕tKG8EjzELkM͊RmĉJ,eoڴ NJY?3Ofl*Ժ{Ͼb`XtM^~I@o;ggjYhE|",4%NB4lV-޸0;  ݶҁ޾ZV DSO,ALGby&,Bh"czF6QA ck $7[l[QY& 4Smj$q<2Y#(LK2(mQ`y[U i+5!Ö`QZbdnkejG#,jFYw=E' -~g#]ȋ{ǝ~vmra2?ܿ[k\ 73#W+_^=|k:{Դ奀׬U -x#P1iGlr6S (-e/z m]O9FjuؗX8EYZ\ƃzExŀy9۸+$*Qq(BTLJ w#זO8f6=YnmL$[(7+B}mayYRAT/- @Td+u e 9IɢDɐJپ;4*`s!6bӢ(Í0v9^`jMAudYFxH=DKP .@"=`M?%`㲰(Q%yWw; %%iVdUkr`{wv,OwC̷O[h߹Ms/=+|++a%̊|F{:*36@3N25`(r. Y@,*ՃoY1ҿjMLH)\l`D[GW\~ߝe×-k. ϼ֛S _w>wEJCt]ek}Oٱ"cf?R7_Wg'rG6tABk"O %`G3`H>8=JΊ7,xlZ>B5PY&2~'?k6u<0?WǀQ4VZKekp˕ﰜKv&Ѱȝn޾ۥ8iRP+(rJm&H4G=DeATݬ֮ݻgSdi-иVS Q^=7y%-lgۇ].a{,A@Cݕ1QD_%:{Ǚ s86ɨO%гHQ2%}jFWiO\.]fvx,aǕhF3z%d*řr5[(䖲R0 D_ۂHhh7JO]W3ƦCD,~+HCkM_׭]-ۻz-@)H;v(j4jӖ 2 rXm544{xՆd:uD4*H uG[̜=41yxz Ӈ̏SXxT'N|_?87;{~ԉ=wrƋ6n* (wMSr\R..]ppoCu$59gxi{Y\6rܚ n2# V,[mɉG~3"V\y6_yGw"-<]/5X1b"g&9#JnVDVV@(a # átk$ԊN3v7.?ڙFٙO=%Iݫ7&EV. ۶ZU[jclz1ښ_*xѶ B6EAWTRքvk8' yXŸOK\°NyÂ4i̫NJ@ 'ʌkrB!Eo]P^ }$?5NRz4AH,cCO]H_<p!G][)"hU^Y-c/jC\՟`xd} 6Fio?D7k[vrXrA dT皆R$\Rk ˰PA G,HUT6Z:vG6ܤӬ7f\I Cz光 ~(Dc;ac[\ ШYߘZj@|[ukiO1o{荃S/O hGKK[R A3՚@SRu֭@mh$mMIvtN.?>kcϷtt ^#R-x:ClX>^=E ۣ$n.laz1$;"G#iNא6qz Ҁct$P~p(wn>ro*@=GϜ=1vzu!um#8'iLCJU[|Aw`/W%]g*岗l ;_?tXgpaLlxFoZC>-r$ 8"@?k+z~$V8| 8ÃP@YR`xw D  ^zCw#jz4۵ulMxZ%=z~2*Z‘A]˦%Qbm,Y8`!Qk,yhl{jSTh15j98~|pU6\Lrvv;\Οڻ:z׶ʅH"P+$ QlGqX0PDE 0s%rG q]eN=n^߽h=xmc1*+,A_l72'z=#f(TV<_.ͬF뽣*ћcY-P( 2 &;qc36&$s9TN79_{Y3juW}}es$$W)(KH8_ۃnܴjZM۷o-8g?|[ek]?ز`aGS/+NMC¹ܰ *! Xtwÿz♇f yz[T5r<(( UahņaSm@i^eK &%$҂k#GKӊ*a#F[\qᮭG w%OG{=w/[nkJi5~ 1ssNG+vq!4_ы0Ka.tA;hEՑ-F6 3@ϱBL‘2D@>Zc,?0 ,(cZCoweL|GA:lz̀dpo00ΎӧsR8>rj] $Caf |fnlUQ#$ +>W+ĿklquñV504=1W,>6@>QtfpDPf|>Z>X&۾YR]([미_|緿;I?L_{}"ǻ?17w Gԣ/j91uӇn?6SI,YyzQR:ոp%Xy\I@?sdb-mG]\sg0Eچon砻)OJڰ\!׮k0d208tQT81&NAeW?qf7 z6`X9/.a!qռLeM篏5bbuZ!̄7=%:sV{dΝ *jt/fHZ٨Tt6$Ԓ{oOGIt!vt @'.=oҭ iM0_chf$g#AԐN7/btԑs:Z]x@5OP{HAOp),!!C4EAߐP'P*-  4[V+έo护v8i2[PcOwK~hmh:`7,IU ?ErRŒ"s3 4Uקs CHl+*oزqX V %DgX"' Mmm|1_ B " ^$1'򎉻]ah'Xr40h$1Nj}OW9h߬ *zwLu 7e,-͍TQ1yٹDIvtut;ޡpCX B!2on>;JJkKc٨Px~hhG;)Rmo@ Ĕ\l۶eQ1rgŝ>3yh/qtG5r䝡SFN?{dzX&?\.LXռY-E¢>7raB+$[P[Ec2rRWUvs ]{x1sى͝=6sAȱS%z[z39W1/,Zi{cR T~pz!H"cD Scl͛<ٜs͌5kWX/z G2sUO)xH ʑew^=<FԒJNXZRҵ rެRdHAB*# *qQ~0vڕP<2UH=[p([I! iTpmeU7 }b!ਸ}жaCB xMT ϫ26#Y#M rpsAy`w[mnU@lXg5@¼Ȟ@rb`6`y00ViMt[(0h lo64X5R)%U%,pW|v"XimyTwvlT#I &wǏͮ}7|l5z"y. E`InԿΖzyT :ԭ57t'wyoj,ryÁZU<}T @A:19>"fg\93?=ZR5ҖHdtg F Khryx UMN[$'TTERx$Q+ 8EMAPֱbi! X6gsڱ3RI>V1\r'݃֬oX2& PjΣZI[PѤp}sgQE a&. +^ vnGgSɘʫhQHUQ)%8B9q²pbE]]408/Y J̀F<8 oCP*Y(Vd;|Jzpr)H %gaDɱZreGӧ~5}%EH]m͚ϭ[<KpŶ|qpHnz;`,esbOZPPJě Q.J֪`o2s%]ߜ .j%&dMVHL`bF8݂[V+4$lq~VO37n|#3#:6DX*O JYjԤWMsHX' ەbtktNxKŰGư |+wTP}է6~K , O"JH*zskv`=oe^~'} W~]'74Ar&i^jn̏ˉpBa˘>7 N)Nl^4ͼ_SƛG *ۛrwxvˣ{Go)EQƵnD Gթ ׈~M" ,]`)0pTUvy%$piwp\9h8 г"(Dd/05!I.~7M!׊y6_ﮯNtmܺ}afvf<Zojh$okþn}ڪ?v6߿'uGq|SNK^Y`3 n hCl˕ԘIDQVuh GqDTpa3!ƒČ?lnyIb|ݰv`iaBY`Jv(.<|5)M捇~3;_{uբ՛66Svz H;Ѓp2S5N}G/~g4Cy]wх!$PU`R4qUrDׇq< 96Qqlzۧ~dlfrD$-_tS1vb~yM}Ĥq,LDЉ3LS0c`aϰlʧG5W,RG)_YnC&|$rhex߸nì@gۇc[" ] Auo qMD*ʒ9<~-Gr,)~ǽkZRUZY/ժ\n#'B!F!=<4#FJ|ԥH1h큛(QL6\Eq!+`g]Dɤ,>W5 "{-Mj4ڲ.OXwZR,Ox^AX,U y˘@7ږJ4:RUZݓ#a/0{>wWMv.6,h2V^?t}7뻉6"GP `C3y;{”b![7wrW_pp{UhT%{ hhFLؐ2 \7j!j}ca*G$d̈c'51d\628“!b(!bzD:X% / aB:9O 8T d \7 jҊHn$ "6L&lKּo߰y =?W^?xTKK~aMm V}_pOBHu߳s_ߚlGS'GtQEβ!ԍ@(Uba3x`(bkZ %VDl#sXxz2r\YGs9ZŪ/SA’f)Qu$rt1j|>udd8eKҩH*J7a`iuPAQ?:;a= x0ظ#(Kpն=NuuSW`/%P$N9kƅ6|/4ab;Tqbt`[,F5|oG=!l\S%X HT}! {dY&{Y LH< +8M,UAD)q1c ֭ҍQ$)TxS\ H4퉲:MGMTQsV=k\B%!\|F}j Lgr}*+\ud!(t|jx]?ufDeStբsc@v!9tegr1ɇT|&XJ޲U/VE9=F,1.C ,hldPμ ]iy51rIw˱e{M-|m z%9 R&u+M<},/q,k>4CGcHg݀4*MTkUz[9ؿΞ[yOc;}Ckj2a:Y5:t" MиHG q $Y ަ ‚l^<DQFA"Yۦ9 'cuxSvw Q')Vj!TM0 Ԩi$}Hn`?p*2y/{/uovm/c翪񞾎?\EϞ>GI"ت +fү/1sKyXS$ő3,U+@H<!_:,-#QP Ʈ˸e9Z>4-˴}7av݆ug{@X׏}llzU4z⎿#(CQ%*ڟ]/\}v.bŸ!D,!3`;CyW>;I}ӻ{7 u?&f<)_]o/ad YX u?y׿;レ* U:$,AnNFw'Diԛ!N`^%+Bd*Ǻ}c ,G+LX(~ _mk6Yw5Wtj5'g„`˅ 4Qv >$ŀQay6unK׍>݀qŋT.1UuG1x_@WSC"KFPVv.ZᣴVVxl3zj% q,F;Mи$O('8" [}d?.ڱVEϦޢQtn&w5WK"ٞ55397QgoܾuG~~^V¦Uk[}qagiVbNQ\ư^Of±$IM]VJVEfE U?'FF]OX1 EB,_+Z{i5-mF(ab(ND cu|dZEo:lC+HmS$t%从p %&o8|6e nzy*,+p|5]3M,'exY6IUê !~A<mWUWoںՃKzz,X߽wAkk{k[k#l$BoAKc뗵>t~5L9~>߰˟q^/[qI58;m?G:{r;/E\TxٳHd1jS" lt Gb #(dA!Cr`yS(ύEB"dtdU筁g V 8O ޑ8PlyȮ+Qu"_}tMopDZ={߮5kk2eR53s,W]ucc/w<˪VtR, 1L DBsL(L]~ ǿ2: ]sc`Ps"u{{7;c"!u\3ݶm󛇆8M[tipJ(t Q>@4 <h+C5 24ENBtaq.D Ђ`L+/@} 5W] "'O Dn6 bocujڐù₆Rp ӬSdЯp"ώAQ ̔IҲe3H5t薭[SK')=9C<b{BVu`qX~ 0{QvfXl͜9pb.{ݵNVCq_UJR!*O651%r,-N s=X=# {t"|,=o[SѪbvvff>ɕ* ]~Պq*LOf2Y8t/yɓg2:ܶRC1B" |LHeȈ(0JaHrX ‘X(H$DRi"joq)%N>x^yh VitNS hD_j]2["2cgKgΎm;/q/r#'-]rdϻD f}]<>ݚnlQj&; 6;{3s'$1TAm\x@PXe.ÿU,g-. r"ˉt]"ko4hC~_rMC_I :˷ԬVDQ7X:;YxSgb"W^EU]QXR(˂0"(^.pH!pLە!2AQQC z5!*lX*=Rqf#ҡVo$V rpD<\b!k/[Y}aQ;yL|T[S( %gC`cB`ղլ.Lkj_.ť-_7Wv]=D>my F>!~W^?Zi5,8++5;bJ$j!@Ăor Waè@Ad `ANʚ ~)NU!DqS UNEY?}?4& enR@Zqŏhx!Mf3ݿ\RJ梩S'z:vw?!G/5 G^ٴuU-"Иl0 fRXcO4v3S'N’ՠ@ŽNFAmhb e^B +1\Ƿ^,\c͇:+8w&\GGIr‚!g[D@&]c8kd :)Tߴxpplaƍ {}ͪheV%UqыDl.Oi5xM=ݩF)sc‹"F)sn=ҶB >ӳzC$f y]Qk2jjijk8#}ON>rBQKW ";v%YO:ۻhqggWQ+|8cd0 )yR{56v=qT1ۺ"UYN@K%[zK[KQ;P e1$jf.7sշٵBHt3adjts㙡Dz˶\E.,]՝+'g.}ɢd(ք.ˡTezlH ^j_me@n. gnXJ/YhHXrȰzW_Nΐ"L}Ӑ2'CCgT֝iȗa8:!"]'ÂO2ZpdL (s{{0\`C,Qb 8G"zLa7L8HϿVp\pZ2Ƀ|w/_X).U[;=eTR(آW wėkmݝW-Liu?րhYUV;劕XTM&ҍM8/о:]U-ǒ-+z{:7މ@5:sr1xՊ%m,]:QqJQmCV`$X2(.g)3<-8/.km~le+* I]C:~ɉB6c۫ڪi ɥ1qx}ny~ k2:zjՆrJ5\ K3y5hI˙i6nM-ոE/u[wL5G8\ TMS*RF6)9u宝[8@B}kN/CFu]L$\pn΍L : (t̢@nk׭YF䅲^1tê>Os4ʿF(( Cβt (reKj4m2^Ѣ }{OW=_??ȁ޾]q͍j?ug<RckOqa'NZ[&&RV\%H<`p-@/(@hVQ;X(*zF\JX*f,C4Xtf::l`#&m$+F)>t(;?GyO655uEC GFM4r]^y|._FqB#TsWsKB]lSdx2C*}WkllD@4]ioljjhv`h 9{CddUB3MR)恷9x䩳h͒ZTRev8@H1O_/H 2s}k=t֪r.@C:|6y% ].YB,DM1-^dejlNB]\1qm44+h lg糍'omjɨ2<7J%R^%?K>ZC3m,@Pd3#\&2=1>eZ$ђReYeLywy߿Չb(3{DSccc/[ҨJ x!ҜK8n,RU+6a:Ǟ]sǟ 54~[?v嗾ԙZdgF[#j ||<ګ^CizO&Ԟ(k_=XuQ4 VV-W0:Rp6^B9xhOtqxįj(mHR&6n݂q' k3h;(@P!,A$D ^8֒(.XfT=A#_N ;m|w_,۫ =5=7_+oww-hHCw_|7hu7?t ._t曮j\MQ-Kt(/wgϏ~T<[SZZZZS'ZMnPɆf9ET}!y8&ϡ&s2 pBɤ'7!΅,U089 bT- trj dX qd7pѦ5+6_TlizGUșM NDmϣPzx@<,p&|Nfӹ}J67/\ljT#u(g%̂}.d]Iw!b\o|z*3=1<Dit(/ӬYG|0qB{v0UZRȈƦn _۩VJ`+s֋/07;/|CcӞ{ϿW/io^bȥM`Hr17777= n[ dz11u\l9}|ntl+/?Gӏ;pbl)%ҽk6m#:M;|bv}^r񽑮$8 !֡ ]' NSgXB8~ꜥBw@K=81MM$Sixnu+zӨg1|{cOMOW0p醅k"O ~X+j5j"Djyr~|[r1`@9>Ȕj9^*-M[^eխŪ$O+,Gfpq:zd2zfj<73{ #5hx>'E"YfUhqzuc4DN "14Bw6MEYvO;˸4:EAx4$4iz:P,;hǒE _L4\P*g Iq!P}mg ۙMXyxFn3K+zxqh̚ݿ*|>A)vK5k;m8܉aEDkNQU|ǣ&=ԓGM#KTz9AUIEY3LDb}KdɁgkF[d;l2ueXD޿ 9̕ ZEQV[ҽMV}G)ei9AVX$Ɣ@??3::vG~'ܽCg3e[6{;,Yb҅+n>}=Kb .\*ek rg`pH*QcbdZ戨Y8H[ ӭV9<'d.\e ZU #pK'N965L[zR6 M4B(VjR9b!;;}s޶f QGʋ 1գsMš- hkV aYwx$\xDpi\45yZ5s#C/8T%_=;ƇU02[GCGY@T/ P䨞%bzW )Byh:ʺLJh44t5<EyFTqjU hyu8p)X[ 1rxb _ u+(B gtGGf -(8aO qqd_!=bǚ[6-*9PN=b - qQdk>֊RU L-ώVkj2_xhH=Vͷ\ԝ~~oϼܸ_^}atxO7:2RcCK[$\+WlF7֐.k6+Ec}#zmنLrJЋ>n,Ʋݸolk57t\;U-lKϜ{tutڿsOωD#,FE{{4Me3!QiAy2PAㄎ.~5T.2AFXlY΁o'!`F) lpg֜k!0w\Dq@r nl pbXY>(jؚ,?+.ܼn]s5Vh =;.HVbRU`Hx!MP2鐃$)4d,sE݁#xAE9׮^zl 7+GyY%kը!r~s~]dƺ `Q'Ncg۾=#7!҆n UCN`hPkܵM<0aѺbP 2 ?\|!l؁ qh+ukj\SMaE$jiuP)}hmM4@,ǬS3g' ljyTsKg׊$<pJ dzmIqW- hehmVxW̖T"m5 񤥪A8lZ^. A !qK  yေ!n&'x|sz)plt2\mX' HV#;>eַY^#q13rm˱LCu󾕙#|p绗-[5[̎?MLMD f #uuƹU [Dx5o{Uׯ=uRV#ܣ %R lLdrׯh*bL?a%֐=VVO)};XOڞ_XX3+jj0SHA)^=ÆjVj-(!uy+0X_dt ^E(8 Bh_]-fx'ɢ"qiҹgm`x!ժ5pxlV˗m]rTJ7{M5&/^mQȫQo\lHґ[ h-SNU} w_d-F{qǞ'6ñ:L$[Q8MJuh*=RX\4T1l:j 3#OVdyQa%ऀEaVs>%bS&mI(Pú|~~ٚ-mSE8m{wQe  \81G8u},I |_/xRC&%87XL=#ڔ?;_:ήjq=!!RE[RP(+n! @t&L&glwoy($sﵮkufΛU;4;(9dJ"5jtU$D9$.'+8pZ5tMwH{FŀS-cb9@6Ɔg8([|`I`v=wo9g^[]*\ ?abTŞpASL {8+iΉ{&?n΂4z?,?θ釧=S#o Gn嗯~w'/%k87upk;&V6}JMHHf'#,6Qy8bdޡ*d xh(QQ8L~eTTA6b */& o"\ǁZXLġc =Ul5 kzంC,z-;?;ppY zϻ7\ye'-mjF65I_`k3Q4bIm?ҡx#mHY2v1^_ :g2|m-[s?1ī2i*d<7:xJyҴp=;pH[lRLKLmKD<@NSGni J/Qn}lM693x3]`(bӖxX' OMP?X0[+ǝnWJ.@e>AW +CSyIr$:=K7 Vjߗr™m9ĎC]P`YPbh%Tl`#jdEC~h9b@L+ )΋z.f#(hJ†Ǟ{K{_nhnTeԒ dPS ᮹'y\̕J%r}C}&\$kyBsn6<0Cb9p=K`xKSDت%@Wb]= :N (B3m 8 C-ၡ+7=GL(V b&£|QjYT!N(RSL/9E4.T]Ȗ*Jl޴IiPh{s ELo'}E]zYW4.ڹ0Q# 3],LUILyD:-Q`R&%ŲK-G%m0Vqd^McXHըI|%f\YtռmX8V%_Ut?Y[ k3#{l[駯|k_}ǫ]m jcYg0KTqB)˦NFP㻀 %'5fC=nu2G{6nܺ.P۔˒n1+L0C M<$"`]Hς*$/6<@8Lt3qQtbp:䤳DWmЮѺIn{`ptt$7 7\5y>s峩!rH3HgqA>5"b\lW Z>;n4!)3ij`k /2]u%,ҙ:1WȰэv;S(Ho"؄ȍ _DOT&~-uuMDZgB 9ӆ/1'Oh_$&{krW3ӄ*pHTMʂl:<$21"Mx9P^)ib-ڰ^. 'ɡ T %1+\d*^D鑤D?j"F%-+Jh ˗iY74>[;^,sK;'9sξ 6}EC '-_O}Rkm>t%%5i}|gەqMRϷ|dcpރ.-y$ˣ E&8'*3@@+120q٥'./ rwCNn>tF]׿PTb  j'$uM-k֯˃9{P3x6Zܜ]@"FO8.Ԑj-*)n,26iR@Wbhnm'حwd4O 6*UŊ`֬.%YW po6|U' 0%8wO4 fcħYwW a2l/L7޷w@,n30kΤo%G~;~8i]UW]q`TշW6q`:!tQ";m*j,Y(ŁumX '/KkmJF(Q1+G ϵ< 7< 3nE1niQBsSA̕o׽9.JܶM]Wǯ/?o80ꌔL/bv߬K"eV aIF2>ī~l6 Wص0'(b0 è0]^!)LI,*Np$ E'=}pko>zI9;8dR}I)__I&Jp67VB'lUv9[+Q!MRF=s#ja*KND,bI+bTGO9\'5ؓɺ4⩪buוt]V[PXrƾEWZCr(9j[7T՚IspNo*ڊX ZzǞ>d󆕅 _n,2$L@zזEP8B@) Al%\FpXeI5SLCEͽG<J,g6ǣ24x)eʂ;'׊YUNؒ-+ܑDI (&|% Ű,&7yZW߿/_?n?<.kO~ݕ#[ڢFwHm?V}tۊS3=0RZMۖDv Wz7.մ#i 7[XtM@#~XI"|mM .ko2 8qkd4V;K, PhҡtK|LEx2v%u,~zʴ8*pBlTUH:q|@뵟~(lniiMԡ J##3!YMf1WphcQT!Z-&<'As?!i 2"~?Џ۶Rcc5M_x9T<K4vWQ׿/۔ & C#A'NND L%W!ÇdFtMOs"gGAc:H=8pDdoڶo)3Oٸ>ϻޛ5O/ԥ.8+6X?hS *P2ա@"?'l&jL0c2U[ ի̉mF>?t^*{t3sxC#cs'6Nu{7k8K1+ʱnKHɣ% ʢ v1e GCY@g7Gw|v#})-5 l* )E$|_8lJI(weNEHOQ?ʞ䬟|ZAw,BBuoQ@R|wߕ b4qVY\T60r VZgq: oTj+RvD}{vJ4ܐpȡ^PCm]\{0Bˮ4q[ ,[MăʡV.fszSfϘSM#t<, *PVϔR.^r^$ A6Pd:{D S]vAeHNXm],Yp (Ft Xb]66i+6UWkͲo{o$֊OF(܏+pRUw{ P&:nrk&j;n`ŒiS ,Olm6Yin?_w=4>^&sRSdpJmhà9%=Cf*ègB|lbXㄕM](N|MD ռEpwY1A8`#ȣm γm0! ^[ WawVȊL05z[<( 8݀H(:Z!=?xB8*h1i" CLHZuH!Cp8۰[Ւɉ===&|4cr`f Iws"e*SF1r&x%玟$饲C(sD+>`'mX8Ȋ BAt^LЬ{2XYFjF$.(P/\#ҤNVM¬qjp] GT !A3 Ҏf'r8/i 8ӎ;>X_w`^ÇsBE-kN?RרUQ]Z"bY֘eO$BqYaR0u{,Z~ɋg>놧yuM_92wup{S g^5!9;_,rZ&#VG҉jѱŔ涶#6M{;/}w8-٭} +'!X@/Kq=G#GTV4:;'-,8]CF#dI˥qDEUH}1lXe!ir!O.8^܃xM"9ItT.·h` h~6'­YX؞xrkVGfYt'J0.h  Q4ZH1<9#d"-֙Ȏ T&>Ѽ7QCrЉGkL-<HRW yT 2Z YW^w//gB[S~wx$|顿?fyֵ'2Cy}˖ X%Z_T}Y,)xy׃ %79(HopEg@cd5^9oS6HB- ^B8f-ZyO R>-pǑUOzfc:QcT|B qPxayG D'A*<)Rc]Ed#< $Ѧ/t4%'Do/{I] @@G/%Ra GK0lpQfjVQZeݣMg%~>w|߁ζC=i<@} z7>{o7ϟ8wKw흷eMOw_!ۖX-T"6M<[".r`,ZyW3F{G _?LsR`،<5MgE[Vx-ӄk Ϧm[7 | ]SD.Zad5*2 ,9r8. $G H #EfYA] Zxt$XM 2'+2/ozVyB^7Iǚꔠ(16ˡXNJ ~: p`cCxU]V:|p J!"ptX4)Gx5kT,}bH`Iٻ_*Lɐ,EbI.*'}qez))2Pcg]וwvm>/N>}ٟ^ys?ߕ|}|ggmrR.}顶owmn/8ϚU=\k"nPsjȴ%8,q%e1sSzSf_z=˦MpJliRk-[w2Ms1ܖQa?D}; ^M|MM}Xʶx(,`{P8_Fٕ\d_ptMm#RKe.G xs|]bxOv@XCV伩;Taa,XgyȾ SO8c ULrJ$hPv$ճW*)mX*ؾ!RIa¢BqHS&0pGsy4@De60ū G]8@=p@aoRgD 16vLEsyO=nXHeӟɉ).`^V(WHD#e ǔ6d+-EHyLO440Q)岅GϚ3ebe}q5ѣydz/B']ͧz 'SEWsЩ~nݷwFG{sϺ7w4N:s%rِ]/I2KoFC]?ta=蔳/hٻ[  O;c^xPvkkè=k Ƃ@aQiL/ r5= 85!,i$ߦ ҆i "'[i>\o{6Rml=i/f $:0cA¬Yhѡ>( FX{蝷]zxHkׯ1 E6m$6!y,Ar8dkC BBl׶ut5r *j)+d2G3]ԢK9ICvCG¡ۼéBٲCCw͙|?YeuZٽ}X?c]s"'%1 j5>d ʃ wI"(6D1yles\&A`yCS>Pa>V1VrpXJL>Z.塂zn+3 bP&1bNcmbڍ[uZ8Գ}@K|BK&M7:mJC$o PHho1b[)e-՝p0 R兔 +.I+@%d!9! (C"2żyE()tC5u]U8!T~c:q=64Bcy/Pk:< qڳE3jC*dŵ4Hh냸VBp(+hS̕ʹ /çQ G,z6.B@hm6!Q .Í,=kF"TC=~@AR.EN us2o>X (J YXwk@;|aByDqSN51XڵuͰMXW-XqN`(D&Lf1jt ul)c+3JW~8¡LյC  bgG[84*~PYvWƫ˃bpWsS5|~x{M48Ta7\x?\o|7ԅ>˿w(H1cW|}udWKf6tNC lۄ֭}톘ċmX'?QG-?6pl@L̪+,x Ԥ06nu/sEVu`r.wqT Ne10cu N]_0k阛/[Z)МXQPF3I:햇yitR.?&岱j - 8I8Ӊ c&ٸ߻>AܻI!~?[V_sPOP ƒCn'OPl85t!daĉ^2vl,߻sWsKF,rx-,1sc"-&4d# lb%% ڄ' `|}bٶmJW_n;w[;9^4w@:mys>'xZ:|9@eYͦ^lWAk$0,^HB_lI(|Hy8r &NjGKG[FBϣդ4|! X`D6 XZ<òIP8-g\P5L,YHjuՑ}ӣxA A|TCd*`VavC$ ,Z4FyO=.wꑾwz·xhyZPQ(ڽ~á%TDij8UղG_0 ˶‰|"ZMÅo+GQ@2hJ4 Ob/tPȀbpX_pN=\R%Su¢2l F g-"vdCWxXMWd TDӖgi""/$j^ RKa#0׳T*k,zМEi8t&(ɍzrZ hVIx䋎q<4d%hga $ަt'+:6?T t6RdjSc'g0XU=!8$R,¹c 1XGu|rXV,FI H2*š\P"@O{f֬~@b͗z_|=y|ݓojg]܍ϼwwnpUcw^hjS_ټwy}/Wѳ>9 v_$>5UzTiElmՎ%;GCͯ#57E U\_sd -d Q5p/ىd"-A\v,8ѱ4>TEM7]\41pfsQI ZP5V4$|mYץJ2nؾL= @zS>95  GX4o`")q7QᬀvjIebpr-~e̖K/u%4ZDR sfGVoٗkѸZ)E@ 7 qt=X ZL~5V$$_άΦL0v.<)Ehۍ[o?<)AY4\M/-MDH$WOX^ˬQ!Q.$\{%:N_*K@Cr4pF;{YSI.NRƃS\OWv2~qN+|z66gﶰdͪ4S[iw3o҅Kȼ0qb#onS}Tiܲ7ny~ؽ([DP[oݼwYg,z3N:(P]mx{Zytdury ּ鄤X7+VCC@(FB>uƅ!&&[YNS}%)Ͻi,!@[XsLJjK0(=T^4ɚ4ZhTJݣ?%w4ùL u.Ex2 ɧG XMa)R*5#rŗX3=.Ӹ'жEko]bº^5z rDޯ{CǝuO״x< Б>vH5߻;>[38k<>lK.{W޺}7oI@eђ3z8'D1m4e;շr6)T*tv hwaBFmB [Xql8Y$"4q\߮RqsxFXNYVܞ%?'9_>U?.qlx9a>pm R@໕p]%M='\R\NQ??]}\ey 5{o}7ͬ(V((Q+}LИ0DXPɗː4 ^3m4R#D)7jq ' jyF)gF0*,+G%u l8uEXDeCu$3,\<-g6PRg0;.sϿkY3b)cz0G6 0$`p2$ֽ0mڄ²?hbӦN}i%W]QZ1 '\,[dݮ ŀZ,A"#pOYbI *+CBYveQcw%(KpD!˳Ab(+ 1}@":ߓ1q "0µr&C8[rG9\36D hɑDQ#@L#"K! 7ˀ_OU-2 @(aXp Uzn6E5 ~OhlÁ.eA= VL¡gX"N:~\'X\1ǰ:>f&Ӳ! 0F {)>gy^aÇ͵&qB)&RD]/~ݤmn>]VD{bvHͪe(s:ԅ#;6_*'0MTAsڊ暚ko/oUoqfu>h ؤSoݐqM@NBaCd جȊhbg^ cz[,Y *>Z,Ѹ h3b@F|Zr(Ӏti# R1$៍bˌ?,]ypU%`BeQ,KTeJivj;ӺN]J)vH"bH $e{ݷs㿙y}9Y>s":/OM d_rP"A<;epyaɣ0; wh,[uE ٻrlx8\I\/FJ IP^%9ddE$x+pq2 r-|ky$7Q!0`C$aYxDG6JgߜDUL'3GEpL" YTQՐf%~>ۋ|5r|pFn;3p }Cec=7--?V׮#[.LCܴG|}5ozwcٜ=XR8)ui=8rC?J7R2;<04I3|bKTrAKKe}UH|q3~p (t*?wъ*M1Pu,CajC9]G08/@q,RbGjGwOZ`y,…y{Np>}/"-XÙs4Eh,&R (T(PB3x>'Kj%2eILȤ;@y-B'9&Rr*'X?IȸyMMrsh[TO_ ^|WHպ~ypp]/%!,)D~jr(B_mC@UmG!w ˆx"rrImI"n>]Ma z[#)c3ޏ,pe'8\m" EO/cۨMl M_9 X8h $GΫ]a'̨l.E"p5U . 82 6f&(H9Dz?>p]-ᾓF2 .~ HPC /$]Tox݂Ѩ89^\xWf0mTJ޼z/z*h%LZD.CaFXI)A鱁kS \M)+O?oDE-tܾO/;rAKΜq5F)?zS}[;VU뛷wC]o*ww[Ȝ-%UG/"k9t乳vmljkMʏ^K86'==x׍ _<هPL8SIENDB`fritzing-app-0.9.2b/resources/images/splash/fhp_logo_small.png000066400000000000000000000020771250202676700245570ustar00rootroot00000000000000PNG  IHDR$n] pHYs  iCCPPhotoshop ICC profilexڭka?wimD.7HQ&M[bHRzwMw":;8upA BR|/ >yxx}_H|\ג El)S#f I.k.k>$8IlRU q HmnRHjHρd;W@r#= 9H# ]i`0}d0 _A~ |yH͖Iuq/AJf)^GHtzE0ܯ8w$>@{Gw.'| OP0'o@Y͊y\1mMYöb Q?A&T 7KE_ɕo"Rl:xU^ZMPϬ{ʺ[ո06*3A1O.&6 !GÃtfį sn( ki\&3+. cHRMn's@m1ee'IDATxl?lQϫWmI $0f%"b05EJLBhF4'Vi=-ҟ_IN{|v$:f\<.48x[X:Yŷ?m?p $5[it&Zdsc!|/5`şZLv1.~+UNB=rfW.6}؆Í\MWn8C-A3X^8"[uK/1sǙP~#ZIn`c D%Y kՆ~uNz$c-&9^v֯%ٔd5R]>MrzCCI

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

perfboard socket

fritzing-app-0.9.2b/resources/parts/core/30.20Stripboard2ModuleID.fzp000066400000000000000000011177131250202676700252750ustar00rootroot00000000000000 4 JC basic single-sided stripboard 2011-06-02 Stripboard Prototyping Board Stripboard 30.20 vertical strips prototyping.stripboard.stripboard A stripboard for easily prototyping circuits stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

fritzing-app-0.9.2b/resources/parts/core/30.20StripboardModuleID.fzp000066400000000000000000011177141250202676700252140ustar00rootroot00000000000000 4 JC basic single-sided stripboard 2011-06-02 Stripboard Prototyping Board Stripboard 30.20 horizontal strips prototyping.stripboard.stripboard A stripboard for easily prototyping circuits stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

stripboard socket

fritzing-app-0.9.2b/resources/parts/core/blocker.fzp000066400000000000000000000021051250202676700225400ustar00rootroot00000000000000 4 Jonathan Cohen Copper Fill Blocker 2010-04-29 pcb copper blocker fritzing core Copper Fill Blocker copper1 discreteParts.pcb.copperblocker Blocks copper fill fritzing-app-0.9.2b/resources/parts/core/blocker0.fzp000066400000000000000000000021051250202676700226200ustar00rootroot00000000000000 4 Jonathan Cohen Copper Fill Blocker 2010-04-29 pcb copper blocker fritzing core Copper Fill Blocker copper0 discreteParts.pcb.copperblocker Blocks copper fill fritzing-app-0.9.2b/resources/parts/core/boardlogoimage.fzp000066400000000000000000000024521250202676700240770ustar00rootroot00000000000000 4 Jonathan Cohen Custom PCB Image 2012-05-30 pcb part diy fritzing core Plain Vanilla PCB 2 Custom Shape discreteParts.pcb.logo For adding images to the board layer of the board mm fritzing-app-0.9.2b/resources/parts/core/boardlogoimage_one_layer.fzp000066400000000000000000000024621250202676700261350ustar00rootroot00000000000000 4 Jonathan Cohen Custom PCB Image 2012-05-30 pcb part diy fritzing core Plain Vanilla PCB 1 Custom Shape discreteParts.pcb.logo For adding images to the board layer of the board mm fritzing-app-0.9.2b/resources/parts/core/breadboardlogoimage.fzp000066400000000000000000000023211250202676700250700ustar00rootroot00000000000000 4 Jonathan Cohen Breadboard Image 2012-10-23 breadboard part diy fritzing core Logo image discreteParts.breadboard.logo For adding images to the breadboard view mm fritzing-app-0.9.2b/resources/parts/core/breadboardlogotext.fzp000066400000000000000000000023161250202676700247760ustar00rootroot00000000000000 4 Jonathan Breadboard Text 2012-10-23 breadboard part diy fritzing core Logo logo text discreteParts.breadboard.logo For adding text to the breadboard view fritzing-app-0.9.2b/resources/parts/core/cmRuler.fzp000066400000000000000000000017061250202676700225360ustar00rootroot00000000000000 4 Mariano Crowe Ruler 2008-08-21 ruler cm Ruler 10cm An adjustable ruler cmil fritzing-app-0.9.2b/resources/parts/core/copper0logoimage.fzp000066400000000000000000000023701250202676700243570ustar00rootroot00000000000000 4 Brendan Howell Copper Image 2008-11-25 pcb part diy fritzing core Logo image copper0 discreteParts.pcb.logo For adding images to the bottom copper layer of the board mm fritzing-app-0.9.2b/resources/parts/core/copper0logotext.fzp000066400000000000000000000022721250202676700242620ustar00rootroot00000000000000 4 Brendan Howell Copper Text 2008-11-25 pcb part diy fritzing core Logo logo text copper0 discreteParts.pcb.logo.copper For adding text to the copper bottom layer of the board fritzing-app-0.9.2b/resources/parts/core/copper1logoimage.fzp000066400000000000000000000023651250202676700243640ustar00rootroot00000000000000 4 Brendan Howell Copper Image 2008-11-25 pcb part diy fritzing core Logo image copper1 discreteParts.pcb.logo For adding images to the top copper layer of the board mm fritzing-app-0.9.2b/resources/parts/core/copper1logotext.fzp000066400000000000000000000022671250202676700242670ustar00rootroot00000000000000 4 Brendan Howell Copper Text 2008-11-25 pcb part diy fritzing core Logo logo text copper1 discreteParts.pcb.logo.copper For adding text to the copper top layer of the board fritzing-app-0.9.2b/resources/parts/core/dcpower.fzp000066400000000000000000000047561250202676700226000ustar00rootroot00000000000000 4 Brendan Howell DC Power 2008-07-28 obsolete dc power symbol fritzing core obsolete power symbol dc battery/supply 5 discreteParts.power.power.dcpower A generic dc power symbol cmil Positive Supply Voltage

Ground

fritzing-app-0.9.2b/resources/parts/core/ellipse_pcb.fzp000066400000000000000000000024401250202676700234020ustar00rootroot00000000000000 4 Jonathan Cohen Ellipse PCB - Resizable 2012-06-03 pcb board diy fritzing core 1 Ellipse Plain Vanilla PCB discreteParts.pcb.ellipse.resizable Ellipse Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/ellipse_pcb_two_layers.fzp000066400000000000000000000024501250202676700256530ustar00rootroot00000000000000 4 Jonathan Cohen Ellipse PCB - Resizable 2012-06-03 pcb board diy fritzing core 2 Ellipse Plain Vanilla PCB discreteParts.pcb.ellipse.resizable Ellipse Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/ground.fzp000066400000000000000000000031631250202676700224220ustar00rootroot00000000000000 4 Brendan Howell Ground 2008-07-28 ground symbol fritzing core ground symbol discreteParts.ground.ground.ground A generic ground symbol cmil ground

fritzing-app-0.9.2b/resources/parts/core/groundplane.fzp000066400000000000000000000026131250202676700234410ustar00rootroot00000000000000 4 Fritzing Copper Fill 2009-10-22 copper fill fritzing core copper fill discreteParts.part.part.copperfill A copper fill

fritzing-app-0.9.2b/resources/parts/core/hole.fzp000066400000000000000000000020041250202676700220440ustar00rootroot00000000000000 4 Jonathan Cohen Hole 2010-04-29 pcb hole fritzing core 2.2mm,0.0mm Hole discreteParts.pcb.hole Hole with or without copper fritzing-app-0.9.2b/resources/parts/core/jumper.fzp000066400000000000000000000042401250202676700224230ustar00rootroot00000000000000 4 Brendan Howell Jumper 2008-07-28 jumper fritzing core jumper discreteParts.wire.wire.jumper A jumper cmil jumper end

the other end of the jumper

fritzing-app-0.9.2b/resources/parts/core/logoimage.fzp000066400000000000000000000023431250202676700230660ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Image 2008-11-25 pcb part diy fritzing core Logo image silkscreen discreteParts.pcb.logo For adding images to the silkscreen layer of the board mm fritzing-app-0.9.2b/resources/parts/core/logotext.fzp000066400000000000000000000022411250202676700227650ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Text 2008-11-25 pcb part diy fritzing core Logo logo text silkscreen discreteParts.pcb.logo For adding text to the silkscreen layer of the board fritzing-app-0.9.2b/resources/parts/core/netlabel.fzp000066400000000000000000000032271250202676700227130ustar00rootroot00000000000000 4 Jonathan Cohen Net Label 2012-10-02 net label symbol fritzing core net label A net label for schematic view will be connected to any other net label with the same name. cmil

fritzing-app-0.9.2b/resources/parts/core/netlabel_left.fzp000066400000000000000000000032441250202676700237240ustar00rootroot00000000000000 4 Jonathan Cohen Net Label 2012-10-02 net label symbol fritzing core obsolete net label A net label for schematic view will be connected to any other net label with the same name. cmil

fritzing-app-0.9.2b/resources/parts/core/newbreadboardlogoimage.fzp000066400000000000000000000023401250202676700256030ustar00rootroot00000000000000 4 Jonathan Cohen Breadboard Image 2012-10-23 breadboard part diy fritzing core Logo image discreteParts.breadboard.logo For adding images to the breadboard view mm fritzing-app-0.9.2b/resources/parts/core/newcopper0logoimage.fzp000066400000000000000000000023571250202676700250760ustar00rootroot00000000000000 4 Brendan Howell Copper Image 2008-11-25 pcb part diy fritzing core Logo image copper0 discreteParts.pcb.logo For adding images to the bottom copper layer of the board mm fritzing-app-0.9.2b/resources/parts/core/newcopper1logoimage.fzp000066400000000000000000000023541250202676700250740ustar00rootroot00000000000000 4 Brendan Howell Copper Image 2008-11-25 pcb part diy fritzing core Logo image copper1 discreteParts.pcb.logo For adding images to the top copper layer of the board mm fritzing-app-0.9.2b/resources/parts/core/newlogoimage.fzp000066400000000000000000000023621250202676700236010ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Image 2008-11-25 pcb part diy fritzing core Logo image silkscreen discreteParts.pcb.logo For adding images to the silkscreen layer of the board mm fritzing-app-0.9.2b/resources/parts/core/newschematiclogoimage.fzp000066400000000000000000000023261250202676700254620ustar00rootroot00000000000000 4 Brendan Howell Schematic Image 2008-11-25 schematic part diy fritzing core Logo image discreteParts.schematic.logo For adding images to the schematic view mm fritzing-app-0.9.2b/resources/parts/core/newsilkscreen0logoimage.fzp000066400000000000000000000023771250202676700257520ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Image 2008-11-25 pcb part diy fritzing core Logo image silkscreen0 discreteParts.pcb.logo For adding images to the silkscreen layer of the board mm fritzing-app-0.9.2b/resources/parts/core/note.fzp000066400000000000000000000015631250202676700220730ustar00rootroot00000000000000 4 Brendan Howell Note 2008-07-28 note fritzing core note discreteParts.note.note.note A generic note cmil fritzing-app-0.9.2b/resources/parts/core/pad.fzp000066400000000000000000000027641250202676700216760ustar00rootroot00000000000000 4 Jonathan Cohen Pad 2010-04-29 pcb Pad fritzing core pad copper1 discreteParts.pcb.pad Pad via

fritzing-app-0.9.2b/resources/parts/core/pad0.fzp000066400000000000000000000027761250202676700217610ustar00rootroot00000000000000 4 Jonathan Cohen Pad 2010-04-29 pcb Pad fritzing core pad copper0 discreteParts.pcb.pad Pad via

fritzing-app-0.9.2b/resources/parts/core/power.fzp000066400000000000000000000035261250202676700222630ustar00rootroot00000000000000 4 Brendan Howell Power 2008-07-28 power symbol fritzing core power symbol voltage reference 5 discreteParts.power.power.power A generic power symbol cmil Positive Supply Voltage

fritzing-app-0.9.2b/resources/parts/core/power_label.fzp000066400000000000000000000034561250202676700234240ustar00rootroot00000000000000 4 Brendan Howell Power 2008-07-28 power symbol fritzing core power label voltage reference 5 discreteParts.power.power.power A generic power symbol cmil Positive Supply Voltage

fritzing-app-0.9.2b/resources/parts/core/rectangle_pcb.fzp000066400000000000000000000024711250202676700237150ustar00rootroot00000000000000 4 Brendan Howell Rectangular PCB - Resizable 2008-11-25 pcb board diy fritzing core 1 Rectangle Plain Vanilla PCB discreteParts.pcb.rectangle.resizable Rectangular Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/rectangle_pcb_two_layers.fzp000066400000000000000000000025001250202676700261560ustar00rootroot00000000000000 4 Brendan Howell Rectangular PCB - Resizable 2008-11-25 pcb board diy fritzing core 2 Rectangle Plain Vanilla PCB discreteParts.pcb.rectangle.resizable Rectangular Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/roundrect_pcb.fzp000066400000000000000000000024651250202676700237610ustar00rootroot00000000000000 4 Jonathan Cohen Round Rect PCB - Resizable 2012-06-03 pcb board diy fritzing core 1 Round Rect Plain Vanilla PCB discreteParts.pcb.roundrect.resizable Round Rect Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/roundrect_pcb_two_layers.fzp000066400000000000000000000024741250202676700262310ustar00rootroot00000000000000 4 Jonathan Cohen RoundRect PCB - Resizable 2012-06-03 pcb board diy fritzing core 2 Round Rect Plain Vanilla PCB discreteParts.pcb.roundrect.resizable Round Rect Resizable Circuit Board mm fritzing-app-0.9.2b/resources/parts/core/schematic_frame.fzp000066400000000000000000000024661250202676700242430ustar00rootroot00000000000000 4 Jonathan Cohen Schematic Frame 2011-06-29 schematic frame legend fritzing core Schematic Frame discreteParts.schematic.frame.resizable Document frame for schematic view fritzing-app-0.9.2b/resources/parts/core/schematiclogoimage.fzp000066400000000000000000000023071250202676700247470ustar00rootroot00000000000000 4 Brendan Howell Schematic Image 2008-11-25 schematic part diy fritzing core Logo image discreteParts.schematic.logo For adding images to the schematic view mm fritzing-app-0.9.2b/resources/parts/core/schematiclogotext.fzp000066400000000000000000000022441250202676700246510ustar00rootroot00000000000000 4 Brendan Howell Schematic Text 2008-11-25 schematic part diy fritzing core Logo logo text discreteParts.schematic.logo For adding text to the schematic view fritzing-app-0.9.2b/resources/parts/core/silkscreen0logoimage.fzp000066400000000000000000000023601250202676700252300ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Image 2008-11-25 pcb part diy fritzing core Logo image silkscreen0 discreteParts.pcb.logo For adding images to the silkscreen layer of the board mm fritzing-app-0.9.2b/resources/parts/core/silkscreen0logotext.fzp000066400000000000000000000022561250202676700251360ustar00rootroot00000000000000 4 Brendan Howell Silkscreen Text 2008-11-25 pcb part diy fritzing core Logo logo text silkscreen0 discreteParts.pcb.logo For adding text to the silkscreen layer of the board fritzing-app-0.9.2b/resources/parts/core/via.fzp000066400000000000000000000027411250202676700217040ustar00rootroot00000000000000 4 Jonathan Cohen Via 2010-04-29 pcb via fritzing core 0.4mm,0.3mm Via discreteParts.pcb.via Via via

fritzing-app-0.9.2b/resources/parts/core/wire.fzp000066400000000000000000000055751250202676700221030ustar00rootroot00000000000000 4 Brendan Howell Wire 2008-07-28 wire fritzing core wire discreteParts.wire.wire.wire A generic wire cmil wire end

the other end of the wire

fritzing-app-0.9.2b/resources/parts/svg/000077500000000000000000000000001250202676700202475ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/000077500000000000000000000000001250202676700211775ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/breadboard/000077500000000000000000000000001250202676700232645ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/breadboard/30.20perfboard.svg000066400000000000000000003314021250202676700263370ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/breadboard/breadboardlogo.svg000066400000000000000000000004301250202676700267500ustar00rootroot00000000000000 logo fritzing-app-0.9.2b/resources/parts/svg/core/breadboard/ruler.svg000066400000000000000000000003711250202676700251370ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/breadboard/wire.svg000066400000000000000000000013421250202676700247530ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/000077500000000000000000000000001250202676700221275ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/icon/blocker.svg000066400000000000000000000022461250202676700242750ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/breadboard_logo.svg000066400000000000000000000033511250202676700257570ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/breadboard_text.svg000066400000000000000000000150671250202676700260120ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/copper0_logo.svg000066400000000000000000000037571250202676700252540ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/copper0_text.svg000066400000000000000000000157041250202676700252730ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/copper1_logo.svg000066400000000000000000000037561250202676700252540ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/copper1_text.svg000066400000000000000000000157041250202676700252740ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/groundplane.svg000066400000000000000000000013531250202676700251700ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/hole.svg000066400000000000000000000017521250202676700236040ustar00rootroot00000000000000 Hole SVG fritzing-app-0.9.2b/resources/parts/svg/core/icon/iconPerfboard.svg000066400000000000000000000202651250202676700254320ustar00rootroot00000000000000 image/svg+xml fritzing-app-0.9.2b/resources/parts/svg/core/icon/iconStripboard.svg000066400000000000000000000330201250202676700256300ustar00rootroot00000000000000 image/svg+xml fritzing-app-0.9.2b/resources/parts/svg/core/icon/jumpericon.svg000066400000000000000000000034571250202676700250340ustar00rootroot00000000000000 Jumper SVG fritzing-app-0.9.2b/resources/parts/svg/core/icon/note.svg000066400000000000000000000023351250202676700236200ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/pad.svg000066400000000000000000000012151250202676700234130ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/rectangle_pcb.svg000066400000000000000000000016251250202676700254440ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/rulericon.svg000066400000000000000000000065041250202676700246570ustar00rootroot00000000000000 cm in fritzing-app-0.9.2b/resources/parts/svg/core/icon/schematic_frame_icon.svg000066400000000000000000000026261250202676700270000ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/schematic_logo.svg000066400000000000000000000032771250202676700256410ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/schematic_text.svg000066400000000000000000000150571250202676700256640ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/silkscreen_logo.svg000066400000000000000000000041331250202676700260330ustar00rootroot00000000000000 Jumper SVG fritzing-app-0.9.2b/resources/parts/svg/core/icon/silkscreen_text.svg000066400000000000000000000157041250202676700260650ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/icon/via.svg000066400000000000000000000023451250202676700234330ustar00rootroot00000000000000 Hole SVG fritzing-app-0.9.2b/resources/parts/svg/core/icon/wireicon.svg000066400000000000000000000441541250202676700244770ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/000077500000000000000000000000001250202676700217435ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/pcb/copper1logo.svg000066400000000000000000000004161250202676700247170ustar00rootroot00000000000000 logo fritzing-app-0.9.2b/resources/parts/svg/core/pcb/ellipse_pcb.svg000066400000000000000000000011741250202676700247500ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/groundplane.svg000066400000000000000000000004501250202676700250010ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/hole.svg000066400000000000000000000005451250202676700234170ustar00rootroot00000000000000 Hole SVG fritzing-app-0.9.2b/resources/parts/svg/core/pcb/jumper.svg000066400000000000000000000014641250202676700237730ustar00rootroot00000000000000 Jumper SVG fritzing-app-0.9.2b/resources/parts/svg/core/pcb/logo.svg000066400000000000000000000004211250202676700234210ustar00rootroot00000000000000 logo fritzing-app-0.9.2b/resources/parts/svg/core/pcb/pad.svg000066400000000000000000000004551250202676700232340ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/pad0.svg000066400000000000000000000004541250202676700233130ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/rectangle_pcb.svg000066400000000000000000000015111250202676700252520ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/roundrect_pcb.svg000066400000000000000000000012721250202676700253170ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/pcb/via.svg000066400000000000000000000005571250202676700232520ustar00rootroot00000000000000 Via SVG fritzing-app-0.9.2b/resources/parts/svg/core/schematic/000077500000000000000000000000001250202676700231375ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/core/schematic/frame.svg000066400000000000000000000003141250202676700247500ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/core/schematic/netlabel.svg000066400000000000000000000013211250202676700254430ustar00rootroot00000000000000 net label fritzing-app-0.9.2b/resources/parts/svg/core/schematic/schematiclogo.svg000066400000000000000000000004271250202676700265040ustar00rootroot00000000000000 logo do not change these svg files with anything but a text editor.txt000066400000000000000000000011251250202676700342030ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svgWith the exeception of icon files, do on change resource svgs with vector graphics programs unless you are very very very very goddamn careful. For example, adobe illustrator does not recalculate stroke-width when loading SVGs when the units are not pixels. Secondarily, illustrator, inkscape, and the like tend to shove a lot of specialized extra crap into SVGs in order to facilitate later re-editing. Since many of the resource SVGs are used as generator templates, errors can proliferate beyond the single SVG that gets incorrectly changed; and the extra crap can muddy the templating process.fritzing-app-0.9.2b/resources/parts/svg/obsolete/000077500000000000000000000000001250202676700220635ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/obsolete/schematic/000077500000000000000000000000001250202676700240235ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/parts/svg/obsolete/schematic/0.3.schem.frame.svg000066400000000000000000000003131250202676700272300ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/parts/svg/obsolete/schematic/0.3.schem.netlabel.svg000066400000000000000000000012641250202676700277320ustar00rootroot00000000000000 net label fritzing-app-0.9.2b/resources/properties.xml000066400000000000000000000144451250202676700212450ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/ratsnestcolors.xml000066400000000000000000000115741250202676700221360ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/styles/000077500000000000000000000000001250202676700176425ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/styles/fritzing.qss000066400000000000000000001272141250202676700222350ustar00rootroot00000000000000/* ########### the partseditor window ############## ################################################ ################################################ ################################################ */ #PEMainWindow { font-size: 11px; color: #fff; font-family:Droid Sans; background-color:#666666; } #PEToolView::title { border:1px solid #b1b1b1; } #PEToolView, #peSVG, LayerPalette, LayerPalette::title, LayerPalette QObject { background: #d9d9d9; } #PEToolView QPushButton { font-size: 11px; /*min-width: 100px;*/ text-align: center; background: #ececec; border: 1px solid #b1b1b1; border-radius: 0px; padding: 2px; color: #323232; margin-top:0px; margin-bottom:0px; } #PEToolView QPushButton:hover { background: #fff; } #PEToolView QPushButton:pressed, #PEToolView QPushButton:on { background: #666; color: #fff; } #PEToolView QTreeWidget { background: #fff; color:#333; show-decoration-selected: 0; } #PEToolView QTreeWidget::item:selected { background:#dadada; color:#333; border:none; show-decoration-selected: 0; } #PEToolView QTreeWidget::item:selected:!active { background:transparent; color:#333; border:none; show-decoration-selected: 0; } #PEToolView QTreeWidget::item:selected:active { background:#dadada; color:#333; border:none; } #PEToolView QTreeWidget::item:hover { background: #a5a5a5; color:#fff; border:none; } /*############ parteditor tabs ################*/ QDialog QTabWidget, #pe_tabs { background:#b1b1b1; } QDialog QTabWidget::pane, #pe_tabs::pane { /*the tab-window*/ padding: 0px 0px 0px 0px; border:none; background:#d9d9d9; margin:0px; font-family: Droid Sans; font-size:14px; font-weight: regular; } QDialog QTabWidget::tab-bar, #pe_tabs::tab-bar /*this is the complete tab-bar*/ { top: 0px; left: 10px; right: 0px; font-family: Droid Sans; font-size:14px; font-weight: regular; background: #b1b1b1; } QDialog QTabWidget QTabBar::tab, #pe_tabs QTabBar::tab { margin: 0px 10px -1px 10px; font-family: Droid Sans; font-size:14px; font-weight: regular; min-height: 35px; background:#fff; min-width:120px; } QDialog QTabWidget QTabBar::tab:selected, #pe_tabs QTabBar::tab:selected /*the active tab*/ { font-family: Droid Sans; font-size:14px; background-color: transparent; font-weight: regular; color: #eee; border:none; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXActiveFocus.png); } QDialog QTabWidget QTabBar::tab:selected:hover, #pe_tabs QTabBar::tab:selected:hover /*the active tab hover*/ { font-family: Droid Sans; font-size:14px; background-color: transparent; font-weight: regular; color: #fff; border:none; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXActiveFocusHover.png); } QDialog QTabWidget QTabBar::tab:!selected, #pe_tabs QTabBar::tab:!selected { /*the inactive tabs*/ background-color: transparent; font-family: Droid Sans; font-size:14px; color: #666; font-weight:regular; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXInactiveFocusHover.png); } QDialog QTabWidget QTabBar::tab:!selected:hover, #pe_tabs QTabBar::tab:!selected:hover /*the inactive tab- hover*/ { background-color: transparent; font-family: Droid Sans; font-size:14px; border:none; color: #fff; font-weight:regular; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXInactiveFocusHover.png); } QDialog QTabWidget QToolButton, #pe_tabs QToolButton { background: rgba(217,217,217,200); border:0px; } QDialog QTabWidget QToolButton::right-arrow, #pe_tabs QToolButton::right-arrow { background-image: url(:/resources/images/icons/TabScrollArrowButtonRightNormal.png); background-repeat: none; background-position: center; } QDialog QTabWidget QToolButton::right-arrow:pressed, #pe_tabs QToolButton::right-arrow:pressed { background-image: url(:/resources/images/icons/TabScrollArrowButtonRightPressed.png); background-repeat: none; background-position: center; } QDialog QTabWidget QToolButton::left-arrow, #pe_tabs QToolButton::left-arrow{ background-image: url(:/resources/images/icons/TabScrollArrowButtonLeftNormal.png); background-repeat: none; background-position: center; } QDialog QTabWidget QToolButton::left-arrow:pressed, #pe_tabs QToolButton::left-arrow:pressed{ background-image: url(:/resources/images/icons/TabScrollArrowButtonLeftPressed.png); background-repeat: none; background-position: center; } /* ########### the main window and general things ############## ################################################ ################################################ ################################################ */ #theMainWindow { /* layout here */ background-color:#b1b1b1; /*mainbackground color - you see it behind the mainwindow-tabs*/ /* styling there */ font-size: 11px; color: #fff; font-family:Droid Sans; selection-background-color: none; selection-border: none; } QStatusBar { background-color: rgb(130,31,9); /* the statusbar at the bottom */ color: #fff; } #statusBarContainer { background-color: rgb(130,31,9);/* the statusbar at the bottom */ color: #fff; } #statusBarContainer QTooltip { border: 1px solid #fff; /* padding: 3px; */ border-radius: 1px; background:#fff; color:#333; opacity: 200; } QScrollBar:vertical { border: 0px; background:rgba(255,255,255,10); width:10px; margin: 0px 0px 0px 0px; } QScrollBar::handle:vertical { border: 2px solid #b2b2b2; border-radius: 2px; background: #b2b2b2; min-height: 5px; } QScrollBar::add-line:vertical { background: none; height: 1px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background:none; height: 1px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar:horizontal { border: 0px; background:rgba(255,255,255,10); height:10px; margin: 0px 0px 0px 0px; } QScrollBar::handle:horizontal { border: 2px solid #b2b2b2; border-radius: 2px; background: #b2b2b2; min-width: 5px; } QScrollBar::add-line:horizontal { background: none; width: 1px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background:none; width: 1px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: transparent; } /* complex property values with up and down arrows */ PCBSketchWidget QObject QDoubleSpinBox, QDoubleSpinBox { background: #fff; font-size: 11px; color: #000; border: none; } PCBSketchWidget QObject QDoubleSpinBox::down-button, QDoubleSpinBox::down-button { background: #fff; border: none; image: url(:/resources/images/icons/spinArrowButtonDownNormal.png); margin-bottom:1px; } PCBSketchWidget QObject QDoubleSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed { background: #fff; border: none; image: url(:/resources/images/icons/spinArrowButtonDownPressed.png); margin-bottom:1px; } PCBSketchWidget QObject QDoubleSpinBox::up-button, QDoubleSpinBox::up-button { background: #fff; border-bottom: none; image: url(:/resources/images/icons/spinArrowButtonUpNormal.png); } PCBSketchWidget QObject QDoubleSpinBox::up-button:pressed, DoubleSpinBox::up-button:pressed { background: #fff; border-bottom: none; image: url(:/resources/images/icons/spinArrowButtonUpPressed.png); } /* this separates palettes from each other and is movable */ MainWindow::separator { background-color: rgb(101,101,101); } MainWindow::toolbar { background-color: #fff; } MainWindow QLabel { color: rgb(50,50,50); font-family: Droid Sans; } QStatusBar { left: 6px; color: #fff; font-weight: bold; font-size: 11px; font-family: Droid Sans; } QStatusBar::item { font-family: Droid Sans; border: none; color: #fff; } /* ################### Mainmenubar window #################### */ QMenuBar { background-color: #d9d9d9; left:5px; font-family: Droid Sans; } QMenuBar::item { spacing: 10px; /* spacing between menu bar items */ padding: 7px 10px; background: #d9d9d9; color:rgb(51,51,51); background-image:none; font-family: Droid Sans; } QMenuBar::item:selected { background: #aaa; color:#fff; background-image:none; font-family: Droid Sans; } QMenuBar::item:pressed { background: #aaa; color:#fff; background-image:none; font-family: Droid Sans; } /*########### style of the dropdowns ######*/ QMenu { background-color: #d9d9d9; color:#333; margin: 0px 3px 0px 3px; border:none; font-family: Droid Sans; } QMenu::item { background-color: #d9d9d9; color:#333; padding: 2px 15px 2px 15px; font-family: Droid Sans; } QMenu::item:selected { background-color: #a5a5a5; color:#fff; font-family: Droid Sans; } QMenu::separator { background-color: #c1c1c1; height:1px; } QMenu::indicator { width: 15px; height: 15px; } QMenu::item:disabled { color:#b7b7b7; font-family: Droid Sans; } QMenu::item:disabled:selected { color:#b7b7b7; font-family: Droid Sans; background-color: #d9d9d9; } /*############## indicator:non-exclusive is a ###########*/ QCheckBox::indicator:checked, QMenu::indicator:non-exclusive:checked { image: url(:/resources/images/icons/check.png); background-color:transparent; border:none; } QCheckBox::indicator:checked:selected, QMenu::indicator:non-exclusive:checked:selected { image: url(:/resources/images/icons/checkhover.png); background-color:transparent; border:none; } QCheckBox::indicator:unchecked, QMenu::indicator:non-exclusive:unchecked { /*the checkbox for the mainmenu */ image: url(:/resources/images/icons/nocheck.png); background-color:transparent; border:transparent; } QCheckBox::indicator:unchecked:selected, QMenu::indicator:non-exclusive:unchecked:selected { image: url(:/resources/images/icons/check.png); background-color:transparent; border:none; } /*########### MAIN WINDOW TABBAR #################*/ /*the tab-window*/ #mainTabBar { qproperty-iconSize: 36px; font-family: Droid Sans; font-size:14px; font-weight: regular; margin-left:10px; } #sketch_tabs::pane { /*the tab-window*/ padding: 0px 0px 0px 0px; border:none; background:#e6eef2; margin:0px; font-family: Droid Sans; font-size:14px; font-weight: regular; } #sketch_tabs::tab-bar /*this is the complete tab-bar*/ { top: 0px; left: 10px; right: 0px; font-family: Droid Sans; font-size:14px; font-weight: regular; background: #b1b1b1; } #sketch_tabs QTabBar::tab { margin: 0px 10px -1px 0px; min-width: 150px; max-width: 150px; font-family: Droid Sans; font-size:14px; font-weight: regular; } #sketch_tabs QTabBar::tab:selected /*the active tab*/ { font-family: Droid Sans; font-size:14px; background-color: transparent; font-weight: regular; color: #eee; border:none; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXActiveFocus.png); } #sketch_tabs QTabBar::tab:selected:hover /*the active tab hover*/ { font-family: Droid Sans; font-size:14px; background-color: transparent; font-weight: regular; color: #fff; border:none; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXActiveFocusHover.png); } #sketch_tabs QTabBar::tab:!selected{ /*the inactive tabs*/ background-color: transparent; font-family: Droid Sans; font-size:14px; color: #666; font-weight:regular; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXInactiveFocusHover.png); } #sketch_tabs QTabBar::tab:!selected:hover /*the inactive tab- hover*/ { background-color: transparent; font-family: Droid Sans; font-size:14px; border:none; color: #fff; font-weight:regular; margin-bottom:-1px; background-image: url(:/resources/images/icons/segmentedSwitcherXInactiveFocusHover.png); } /* ################### WelcomeScreen styling (WC) #################### */ WelcomeView { background: #E6EEF2; border:0px; margin:0px; padding:0px; } WelcomeView QFrame { border-bottom: 8px solid #d9d9d9; font-family: Droid Sans; } WelcomeView QFrame QLabel { border:0px; font-family: Droid Sans; } /* -------- position of WS"content-blocks" ------------ */ #recentFrame { margin: 10px 0px 13px 15px; padding-bottom:5px; background: #fff; border-bottom: 8px solid #d9d9d9; font: Droid Sans; font-family: Droid Sans; max-width: 350px; min-width: 220px; } #tipFrame { margin: 0px 0px 13px 15px; background: #fff; border-bottom: 8px solid #d9d9d9; font: Droid Sans; font-family: Droid Sans; max-width: 350px; min-width: 220px; } #blogFrame { margin: 10px 15px 13px 15px; background: #fff; border-bottom: 8px solid #d9d9d9; font: Droid Sans; font-family: Droid Sans; max-width: 820px; } #shopFrame { margin: 0px 15px 13px 15px; background: #fff; border-bottom: 8px solid #d9d9d9; font: Droid Sans; font-family: Droid Sans; max-width: 820px; } /* -------------- WS-switchable Header style -------------/* /*#####this is used in blog/projects and shop/fab frame*/ #wsSwitchableFrameHeader { border-bottom: 1px solid #c4c4c4; padding: 8px 0px 8px 0px; margin:0px 5px 0px 5px; font-size:14px; font-weight:bold; min-height:18px; max-height:18px; background:#fff; } #headerTitle1 { font-size:14px; font-weight:bold; color:#c4c4c4; margin-left:0px; margin-right:0px; font-family: Droid Sans; margin-left:1px; margin-right:2px; } #headerTitle2{ color:#323232; font-size:14px; font-weight:bold; font-family: Droid Sans; margin-left:1px; margin-right:2px; } #headerTitleSpace { margin:0px, 3px; } /* ----------- WS-"recentItem"-block ------------- */ #recentTitleFrame { border-bottom: 1px solid #c4c4c4; margin:0px 5px 0px 5px; font-size:14px; font-weight:bold; min-height:34px; max-height:34px; background:#fff; padding:0px; font-family: Droid Sans; } #recentTitle { font-size:14px; font-weight:bold; color:#323232; background:#fff; margin-left:1px; margin-right:2px; font-family: Droid Sans; max-height:16px; } #recentOpenSketch, #recentNewSketch{ margin: 5px 5px 5px 5px; padding:0px; text-align:left; border:none; font-size: 12px; min-height:14px; max-height:22px; background:transparent; } #recentList { border:none; margin: 5px 5px 5px 5px; padding:0px; text-align:left; font-size: 12px; background:#fff; font: regular Droid Sans; } #recentList::item { margin:3px 0px; border:none; padding:0px; text-align:left; font-size: 12px; background:#fff; color:#666; font-weight: regular; font-family: Droid Sans; min-height:14px; max-height:24px; } #recentList::item:selected { margin:0px; border:none; padding:0px; text-align:left; font-size: 12px; background:#fff; color:#666; font-weight: regular; font-family: Droid Sans; min-height:14px; max-height:24px; } #recentSpace { padding:0px; margin:0px 5px; border-bottom: 1px solid #c4c4c4; max-height:1px; background:transparent; } #recentText { font-size: 12px; margin-left:3px; padding:0px; border:none; background:#fff; max-height:20px; min-height:20px; } #recentIcon { margin-left:1px; padding:0px; image-position:center; max-width:18px; max-height:20px; min-width:18px; min-height:20px; border:none; background:transparent; } /* ----------- WS-"blog"-block ------------- */ /******* this is the styling for the blog-frame-title ***********/ #blogTitleFrameLayout { } #blogList { border:none; margin: 5px 5px 5px 5px; padding:0px; text-align:left; font-size: 10px; background:#fff; font-weight: regular; font-family: Droid Sans; color:#656565; qproperty-titleTextColor: #000; qproperty-titleTextFontFamily: Droid Sans; qproperty-titleTextFontSize:14px; qproperty-titleTextExtraLeading:3px; qproperty-introTextColor: #656565; qproperty-introTextFontFamily:Droid Sans; qproperty-introTextFontSize:12px; qproperty-introTextExtraLeading:5px; qproperty-dateTextColor: #656565; qproperty-dateTextFontFamily: Droid Sans; qproperty-dateTextFontSize:10px; } #blogList::item { border:none; text-align:left; font-size: 15px; background:#fff; font-weight: regular; font-family: Droid Sans; border-bottom:1px solid #d4d4d4; } /******* this is the styling for the blog-footer ***********/ #blogLogo { background:#fff; min-height:22px; max-height:22px; } /* ----------- WC-"tip"-block ------------- */ #tipFrame { background: #D5E1E9; border-bottom: 8px solid #A9C6D6; } #tipTitle { color: #77ACC2; border-bottom: none; padding: 0px; margin:8px 5px 8px 5px; font-size:14px; font-family: Droid Sans; font-weight:bold; min-height:18px; max-height:18px; } #tipScrollArea { border:none; padding: 0px 0px 0px 0px; margin-right:5px; } #tipScrollArea QScrollBar { border:none; } #tipScrollArea QScrollBar:vertical{ border: 0px; background:#D5E1E9; width:10px; margin: 0px; } #tipScrollArea QScrollBar::handle:vertical{ border: 2px solid #77ACC2; border-radius: 2px; background: #77ACC2; min-height: 0px; } #tipScrollArea QScrollBar::add-line:vertical{ background: #D5E1E9; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; } #tipScrollArea QScrollBar::sub-line:vertical{ background:#D5E1E9; height: 10px; subcontrol-position: top; subcontrol-origin: margin; } #tip { background: #D5E1E9; border: none; font-family: "OCRA"; color:#2e94af; font-size:13px; qproperty-wordWrap: true; padding: 0px 10px 10px 10px; } #tipFooterFrame{ margin:5px 10px 5px 10px; border-bottom:none; } /* ----------- WS-"shop+fab"-block ------------- */ #shopContentFrame, #fabContentFrame { border:none; font-weight: regular; font-family: Droid Sans; margin:5px; height:100%; } #shopContentImage, #fabContentImage { background:#fff; min-width:45px; min-height:45px; margin:0px; padding:0px; } #shopContentTextFrame, #fabContentTextFrame{ margin: 5px 5px 5px 15px; border:none; min-width:200px; } #shopContentTextHeadline, #fabContentTextHeadline { font-size:16px; font-weight:bold; max-height:20px; font-family: Droid Sans; background:#fff; } #shopContentTextDescription, #fabContentTextDescription { font-size:14px; font-weight:regular; qproperty-wordWrap: true; font-family: Droid Sans; min-height:65px; background:#fff; } #shopContentTextCaption, #fabContentTextCaption { font-weight: regular; font-family: Droid Sans; font-size:11px; max-height:14px; background:#fff; } #blogFooterFrame, #shopFooterFrame, #fabFooterFrame { border-top:1px solid #c4c4c4; background:transparent; border-bottom:none; margin:0px 5px 8px 5px; font-weight: regular; font-family: Droid Sans; padding-top:10px; padding-right:5px; /* padding:8px 0px 8px 0px; */ min-height:25px; max-height:25px; } #blogLogoText, #shopLogoText, #fabLogoText { margin-right:5px; } /*############### a styled loading/progress bar #################### */ QProgressBar { border: none; border-radius: 0px; background-color: #821F09; text-align: center; color:#fff; font-weight:bold; } QProgressBar::chunk { background-color: #f32926; width: 10px; text-align: center; font-family: Droid Sans; } /* ############ tooltips for the partsbin and toolbar NOT the main window ########*/ QToolTip { border: 1px solid #fff; /* padding: 3px; */ border-radius: 1px; background:#fff; color:#333; opacity: 200; font-family: Droid Sans; } /* ############## RADIOBUTTON STYLING ###########*/ QWidget QRadioButton::indicator, QRadioButton::indicator { width: 13px; height: 13px; background:transparent; } QWidget QRadioButton::indicator::unchecked, QRadioButton::indicator::unchecked { image: url(:/resources/images/icons/nocheck.png); background:transparent; } QWidget QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:hover { image: url(:/resources/images/icons/checkhover.png); } QWidget QRadioButton::indicator:unchecked:pressed, QRadioButton::indicator:unchecked:pressed { image: url(:/resources/images/icons/checkactive.png); } QWidget QRadioButton::indicator:checked, QRadioButton::indicator::checked { image: url(:/resources/images/icons/check.png); } QWidget QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:hover { image: url(:/resources/images/icons/checkhover.png); } QWidget QRadioButton::indicator:checked:pressed, QRadioButton::indicator:checked:pressed { image: url(:/resources/images/icons/checkactive.png); } /* ################### the toolbar #################### */ #routingStateLabel { color: #ea9f84; background:rgb(214,50,34); font-family:Droid Sans; font-size:16px; border: 0px; background-color: transparent; margin-top: 8px; margin-bottom: 5px; } #fileToolBar QToolButton, #editToolBar QToolButton { border: none; color: rgb(214,50,34); background: rgb(214,50,34); width:75px; padding:0px 5px; } #fileToolBar QToolButton:pressed, #editToolBar QToolButton:pressed { background: rgb(242,57,38); color: rgb(214,50,34); /* doesnt work, why ??? */ margin: 0px; width:75px; padding:0px 5px; } #sketchAreaToolbar { background: rgb(214,50,34); /*background of toolbar*/ border: none; padding: 0px; } #exportButton, #viewFromButton, #activeLayerButton, #sketchToolButton { border: none; padding: 0px; height:66px; max-width:110px; min-width:95px; } #sketchAreaToolbar QLabel { font-weight: bold; color: rgb(214,50,34); border: none; padding:5px 5px 0px 5px; } #sketchAreaToolbar QToolButton { /*all the button styleing*/ border: none; color:#fff; margin: 0px; height:66px; padding:5px; font-weight: regular; width:75px; } #sketchAreaToolbar QToolButton:hover { /* hover on toolbar buttons */ background: rgb(242,57,38); border: none; color: #ececec; margin: 0px; height:66px; } #sketchAreaToolbar QToolButton:disabled { /* disabled toolbar buttons */ border: none; color: #ececec; margin: 0px; height:66px; } #sketchAreaToolbar QToolButton::menu-button { /*the little arrow to open the submenu*/ border: none; /* background-image: none; */ margin-top: 28px; margin-right:20px; background:transparent; width:10px; height:10px; float:right; } #sketchAreaToolbar QToolButton::menu-arrow { image: url(:/resources/images/icons/smalToolarrow-normal.png); border: none; padding: 4px; background:transparent; } #sketchAreaToolbar QToolButton::menu-arrow:open { border: none; image: url(:/resources/images/icons/smalToolarrow-pressed.png); padding: 4px; background:transparent; } #sketchAreaToolbar QToolButton::menu-arrow:disabled{ border: none; image: url(:/resources/images/icons/smalToolarrow-inactive.png); padding-top: 0px; padding-right:0px; margin: 2px; background:none; } #sketchAreaToolbar #shareProjectButton{ color:#fff; border-bottom: 5px solid #006737; background:#00a55b; height: 55px; width:80px; margin:5px 10px 5px 5px; padding: 3px 0px 0px 0px; } #sketchAreaToolbar #shareProjectButton:hover { color:#fff; border-bottom: 5px solid #148d50; background:#6dba82; padding: 3px 0px 0px 0px; height: 55px; width:80px; margin:5px 10px 5px 5px; } #sketchAreaToolbar #shareProjectButton:pressed { color:#fff; border-bottom: 5px solid #148d50; background:#6dba82; padding: 3px 0px 0px 0px; height: 55px; width:80px; margin:5px 10px 5px 5px; } #sketchAreaToolbar #orderFabButton{ color:#fff; border-bottom: 5px solid #3a2e2a; background:#5e4c49; padding: 3px 0px 0px 0px; height: 55px; width:80px; margin:5px 10px 5px 5px; } #sketchAreaToolbar #orderFabButton:hover { color:#fff; border-bottom: 5px solid #6d5e5a; background:#917d78; padding: 3px 0px 0px 0px; height: 55px; width:80px; margin:5px 10px 5px 5px; } #sketchAreaToolbar #orderFabButton:pressed { color:#fff; border-bottom: 5px solid #6d5e5a; background:#917d78; padding: 3px 0px 0px 0px; height: 55px; width:80px; margin:5px 10px 5px 5px; } /* ################### zoomslider #################### */ QSlider::groove:horizontal { /*this is the slider - "line" */ background:rgb(214,50,34); height: 2px; border-radius:-5px; margin-bottom:10px; margin-top:0px; } QSlider::handle:horizontal { /*this is the handle: it needs negative margin to be "bigger" than the slider - "line" */ width:10px; height:10px; margin-top: -4px; margin-bottom: -4px; background-clip: content; background-image: url(:/resources/images/icons/zoomSlider.png); } QSlider::handle:horizontal:hover { width:10px; height:10px; margin-top: -4px; margin-bottom: -4px; background-image: url(:/resources/images/icons/zoomSliderHover.png); } #ZoomSliderFrame { max-height: 16px; min-height: 16px; max-width: 202px; min-width: 202px; } #ZoomSliderValue { /*this is the number in percent of left to the zoomslider*/ margin: 0px; padding: 0px; border: none; color: #fff; background-color: transparent; width: 35px; max-width: 35px; min-width: 35px; text-align: right; } #ZoomSliderLabel { color: #CCCCCC; width: 15px; max-width: 15px; min-width: 15px; text-align: left; } #ZoomSliderButton { margin-top: 0px; margin-bottom: 0px; margin-left: 5px; margin-right: 5px; padding: 0px; border: none; width: 16px; max-width: 16px; min-width: 16px; } /* next to the zoomslider in the status bar */ #LocationLabel { font-size: 9px; font-weight: 500; color: #fff; } /* ################### the palettes #################### */ FDockWidget { /* only relevant if palette is floating and only visible with tabs inside the widget such as Parts Library */ background-color: #d9d9d9; /* this defines the title text! */ font-size: 14px; font-weight: 150; color: rgb(101,101,101); font-family: Droid Sans; titlebar-close-icon: url(:/resources/images/icons/dockWidgetEmpty_icon.png); titlebar-normal-icon: url(:/resources/images/icons/dockWidgetEmpty_icon.png); } #topMostDock { margin: 0px; margin-top: 8px; border: 0px; } #bottomMostDock { margin: 0px; margin-bottom: 8px; border: 0px; } FDockWidget::title { font-size: 20px; font-weight: 300; height: 35px; font-family: Droid Sans; /*border-top-left-radius: 5px;*/ /*border-top-right-radius: 5px;*/ background: #d9d9d9; border-top: 4px rgb(51,51,51) solid; padding-left: 6px; padding-top: 2px; padding-bottom: 0px; } FDockWidget::close-button, FDockWidget::float-button { margin: 0px; padding: 0px; border: 0px; subcontrol-position: top right; subcontrol-origin: margin; position: absolute; top: 4px; bottom: 0px; height:15px; width:15px; } FDockWidget::close-button { right: 2px; image: url(:/resources/images/icons/dockWidgetCloseNormal_icon.png); } FDockWidget::close-button:hover { border: none; image: url(:/resources/images/icons/dockWidgetCloseHover_icon.png); } FDockWidget::close-button:pressed { border: none; image: url(:/resources/images/icons/dockWidgetClosePressed_icon.png); } FDockWidget::float-button { right: 17px; image: url(:/resources/images/icons/dockWidgetFloatNormal_icon.png); } FDockWidget::float-button:hover { border: none; image: url(:/resources/images/icons/dockWidgetFloatHover_icon.png); } FDockWidget::float-button:pressed { border: none; image: url(:/resources/images/icons/dockWidgetFloatPressed_icon.png); } AutoCloseMessageBox { background-color: #FFFFE1; border: 1px solid black; padding: 5px; font-size: 12px; } /* ################### info view #################### */ HtmlInfoView { margin-right:0px; padding-right:5px; border:none; background:#d9d9d9; } HtmlInfoView QScrollBar:vertical { border: 0px; background:rgba(255,255,255,10); width:10px; margin: 0px 0px 0px 0px; } #infoViewMainFrame { background-color: #d9d9d9; border: 0px; margin: 0px; font-size:14px; } #instanceTitleEditor { /* background-color is set programmatically */ text-align: left; font-size: 16px; font-weight: 600; border: 0px; margin: 5px 5px 5px 5px; padding: 0px; background-color: #ececec; } #iconFrame { /*background-color in the icon-row*/ background-color: #d9d9d9; max-height: 34px; min-height: 34px; margin: 0px 0px 0px 5px; padding: 0px; } #iconLabel { background-color: #fff; } #infoViewLockCheckbox { font-size: 11px; padding: 0px; margin: 0px; } #infoViewPartFrame { font-size: 11px; padding: 0px; margin: 0px; color:#f0f; } /* part description/subtitle */ #infoViewPartTitle, #infoViewPartVersion { margin: 3px 5px 3px 5px; padding: 0px 0px 1px 0px; font-size: 11px; font-weight: normal; color: #323232; background: #d9d9d9; /*just the part discription titel not the part main-titel*/ } #infoViewPartUrl { margin: 0px 4px 0px 4px; padding: 0px 0px 1px 0px; font-size: 11px; font-weight: normal; color: #d63222;/*rgb(110,110,110);*/ } /* section title - these are the subtitels in the infoview (like: placement, properties, tags etc.) */ #expandableViewLabel { padding: 0px 0px 3px 0px; margin: 4px 0px 0px 4px; border: 0px; font-weight: bold; text-align: left; font-size: 11px; color: #D63222; } /* Properties */ #infoViewPropertyFrame { margin: 2px 4px 2px 0px; } #propNameLabel { font-size: 11px; color: rgb(51,51,51); min-width: 65px; max-width: 65px; margin: 0px 0px 0px 4px; padding: 3px 3px 3px 0px; border-top: 1px solid #b1b1b1; font-weight: normal; } #propValueFrame { margin: 0px; border: 0px; padding: 1px 0px 1px 0px; border-top: 1px solid #b1b1b1; } #propValueLabel { font-size: 11px; padding: 3px 3px 3px 0px; font-weight: normal; } #infoViewSpinBoxLabel { font-size: 11px; color: #000000; font-weight: normal; } #infoViewComboBox { font-size: 11px; color: rgb(0,0,0); border: none; /*padding-left: 5px;*/ /* This causes a bad side-effect where the values get covered by the arrows in the drop-down */ } #infoViewComboBox:disabled { color:#323232; background: #d9d9d9; } #infoViewComboBox:!editable:disabled { background: #d9d9d9; } #infoViewComboBox:editable:disabled { background: #d9d9d9; } #infoViewComboBox:!editable { background:#ececec; } #infoViewComboBox:hover { background: #fff; } #infoViewComboBox:on { } /* drop-down arrow of the combobox */ #infoViewComboBox::down-arrow { image: url(:/resources/images/icons/combobox-arrow.png); } /* drop-down button of the combobox */ #infoViewComboBox::drop-down:button { background: #ececec; } #infoViewComboBox::drop-down:hover { background: #ececec; } #infoViewComboBox::drop-down:on { background:#ececec; } /* drop-down list of the combobox */ #infoViewComboBox QAbstractItemView { background-color: #ececec; margin: 3px 0px; padding: 0px; color:#333; } #infoViewComboBox:editable { background: #fff; } #infoViewComboBox:editable:hover, #infoViewComboBox:editable:on { /* BUG: for some reason this background is shown _behind_ the :editable background */ background: #fff; } #infoViewComboBox:hover { background: #ececec; } #infoViewComboBox::drop-down:editable { border-left: 1px solid #989898; background: #ececec; } #infoViewLineEdit { font-size: 11px; color: rgb(0,0,0); background: #fff; border: none; } #infoViewLineEdit:hover, #infoViewLineEdit:focus { background:#fff; } #infoViewLineEdit:disabled { background: #d9d9d9; color: #3c3c3c; } /* the label between the two spinners in the schematic frame */ #infoViewOfLabel { font-size: 11px; padding: 3px 3px 3px 0px; margin: 0px; width: 30px; min-width: 30px; max-width: 30px; } /* this is the style of buttons - mostly in generic parts like: "edit pin lables"-button */ #infoViewButton { font-size: 11px; /*min-width: 100px;*/ text-align: center; background: #ececec; border: 1px solid #b1b1b1; border-radius: 0px; padding: 2px; color: #323232; margin-top:3px; margin-bottom:3px; } #infoViewButton:hover { background: #fff; } #infoViewButton:pressed, #infoViewButton:on { background: #666; color: #fff; } /* the title if you have a "advanced settings" box - i.e. gereric ics */ #infoViewGroupBox { border: 1px solid gray; font-size: 11px; font-weight: bold; margin: 5px 0px 0px 0px; padding: 15px 2px 5px 2px; } /* the text inside the advanced settings box */ #infoViewGroupBoxLabel { font-size: 11px; } #infoViewCheckBox { font-size: 11px; padding: 0px; margin-right: 2px; } /* Connections */ #connectionsFrame { margin: 0px; } #connectionsLabel { font-size: 11px; color: #575757; min-width: 65px; max-width: 65px; margin: 0px 0px 0px 4px; padding: 3px 3px 3px 0px; border-top: 1px solid #9b9b9b; } #connectionsValue { font-size: 11px; color: black; margin: 0px; border: 0px; padding: 3px 3px 3px 0px; border-top: 1px solid #9b9b9b; } /* Tags */ #tagsValue { font-size: 11px; margin: 0px 4px 0px 4px; padding: 2px 0px 0px 0px; border-top: 1px solid #9b9b9b; } /***************** Parts Bin *****************/ #partsBinHeader { margin:0; padding: 0px; max-height: 28px; height: 28px; } #partsBinHeaderSeparator { border: 2px solid #b1b1b1; } SearchLineEdit, #searchStackWidget { max-height: 20px; height: 20px; } #partsBinLabel { /*the chosen libery-labelname and background*/ background-color: #d9d9d9; font-size: 14px; color: rgb(50,50,50); font-weight: bold; /*text-transform: uppercase;*/ padding-left: 1px; margin: 0; } PartsBinIconView { padding: 3px; /*this is the size of the grey-border around the partsbin-iconview*/ } PartsBinIconView QPushButton{ padding: 3px; selection-background-color: #b1b1b1; background-color:#d9d9d9; border: 0; border-bottom: 1px solid #D0D0D0;/*this is the size of the grey-border around the partsbin-iconview*/ } PartsBinListView { /*the styling if you look the parts-window in list view mode*/ selection-background-color: #b1b1b1; background-color:#d9d9d9; border: 0; border-bottom: 1px solid #D0D0D0; } PartsBinListView::item:selected { background:#b1b1b1; color:#333; border:none; } PartsBinListView::item:selected:!active { background:#dadada; color:#333; border:none; } PartsBinListView::item:selected:active { background:#b1b1b1; color:#333; border:none; } PartsBinListView::item:hover { background: #a5a5a5; color:#fff; border:none; } #partsBinHeader, PartsBinPaletteWidget, PartsBinPaletteWidget SimpleEditableLabelWidget, PartsBinPaletteWidget InfoGraphicsView { background-color: #d9d9d9; /*background of parts library*/ border: none; } #partsBinContainer { background-color: #d9d9d9; /*background of parts library*/ border-top: 1px solid #b1b1b1; } PartsBinPaletteWidget, StackTabWidget, StackTabWidget::pane { /* trying to get rid of the line across the top of the tabs */ border: none; background-color:transparent; } StackTabBar::tab { margin: 0px 0px 0px 0px; padding: 0px; min-width: 32px; max-width: 32px; min-height: 32px; max-height: 32px; border: 0; background: #d9d9d9; /*this is the color for the active tab*/ font-weight: 600; } StackTabBar::tab:selected { /*color for not active tab*/ color: #b1b1b1; } StackTabBar::tab:!selected { background-color: #b1b1b1; /*#9b9b9b;*/ /*color for not active tab*/ color: #ff0;/*#686868;*/ } StackTabBar::tab:!selected:hover { background-color: #ececec; /*the hover status of the library buttons*/ } StackTabBar[current="true"]::tab:selected { border:5px solid #00f; /*background-color: black; color: white;*/ } /*styling for the scrolling arrows for the part-bins*/ StackTabBar QToolButton { background: rgba(217,217,217,200); border:0px; } StackTabBar QToolButton::up-arrow { background-image: url(:/resources/images/icons/TabScrollArrowButtonUpNormal.png); background-repeat: none; background-position: center; } StackTabBar QToolButton::up-arrow:pressed { background-image: url(:/resources/images/icons/TabScrollArrowButtonUpPressed.png); background-repeat: none; background-position: center; } StackTabBar QToolButton::down-arrow{ background-image: url(:/resources/images/icons/TabScrollArrowButtonDownNormal.png); background-repeat: none; background-position: center; } StackTabBar QToolButton::down-arrow:pressed{ background-image: url(:/resources/images/icons/TabScrollArrowButtonDownPressed.png); background-repeat: none; background-position: center; } #binToolButton { background-color: transparent; font-size: 11px; } #partsBinCombinedMenuButton #partsBinCombinedMenuButton:pressed { margin: 0; margin-top: 2px; margin-left: 2px; padding: 0; border: 0; width: 25px; background-color: transparent; background-attachment: fixed; background-position: 100% 100%; background-repeat: no-repeat; } #partsBinCombinedMenuButton { background-image: url(:/resources/images/icons/partsBinCombinedMenu_icon.png); background-repeat: no-repeat; border: none; height:12px; width:12px; } #partsBinCombinedMenuButton:pressed { background-image: url(:/resources/images/icons/partsBinCombinedMenuPressed_icon.png); background-repeat: no-repeat; height:12px; width:12px; } #partsBinCombinedMenuButton:hover { background-image: url(:/resources/images/icons/partsBinCombinedMenuHover_icon.png); background-repeat: no-repeat; height:12px; width:12px; } #partsBinCombinedMenuButton::menu-indicator { image: url(:/resources/images/icons/noArrow_icon.png); } /**************** LayerWindow and UndoWindow ***********************/ LayerPalette, LayerPalette::title, LayerPalette QObject { background: #d9d9d9; } QUndoView { background: #d9d9d9; show-decoration-selected: 1; } QUndoView::item:selected { background:#b1b1b1; color:#333; border:none; } QUndoView::item:selected:!active { background:#dadada; color:#333; border:none; } QUndoView::item:selected:active { background:#b1b1b1; color:#333; border:none; } QUndoView::item:hover { background: #a5a5a5; color:#fff; border:none; } /**************** Fab Quote ****************/ #quoteOrder { font-size: 16px; font-weight: bold; color: rgb(214,50,34); margin: 0px 0px 0px 18px; text-align: left; font-family: Droid Sans; font-weight: bold; } #quoteMessage { font-size: 11px; color: #000000; margin: 0px 0px 0px 10px; text-align: left; font-family: Droid Sans; } #quoteAdditional { font-size: 11px; color: #000000; margin: 0px 0px 0px 10px; text-align: left; font-family: Droid Sans; } #quoteTable { background-color: transparent; border: 0px solid transparent; margin: 0px 0px 0px 10px; font-size: 11px; font-family: Droid Sans; } #quoteTable QHeaderView { background-color: transparent; color: #000000; border: 0px solid transparent; } #quoteTable::item::disabled { margin-right: 10px; color: #000000; } #quoteVisitButton { color: #ffffff; text-align: center; /* text-align: center is not implemented. QSS is shit. */ qproperty-alignment: AlignCenter; font-size: 16px; font-family: Droid Sans; font-weight: bold; } /************************ About Box ****************************/ #aboutText { border: 0px; background-color: transparent; margin-top: 0px; margin-bottom: 0px; } /**************** sketch widgets ****************/ MainWindow { qproperty-fireQuoteDelay: 250; /* milliseconds */ background:#aaa; } SketchWidget { border: 0px; font-weight: bold; background-image:none; } PCBSketchWidget { qproperty-gridColor: rgba(150,200,250,20); qproperty-ratsnestOpacity: 1.0; qproperty-ratsnestWidth: 0.5; } BreadboardSketchWidget { qproperty-gridColor: rgba(0,50,100,20); qproperty-ratsnestOpacity: 1.0; qproperty-ratsnestWidth: 1.0; } SchematicSketchWidget { qproperty-gridColor: rgba(0,50,100,20); qproperty-ratsnestOpacity: 1.0; qproperty-ratsnestWidth: 0.5; } /**************** the breadboard-, schematic-, pcb-view switcher ****************/ WaitPushUndoStack { background-color: white; color: #0f0; } SearchLineEdit { color: #000000; font-size: 11px; font-family: Droid Sans, LucidaSans, Tahoma, Arial, sans-serif; border: 1px solid #8c8c8c; } /*############# aboutbox ################*/ /*############# colorDialog################*/ QDialog { background-color:#d9d9d9; color:#333333; } QDialog QTabWidget { background-color:#d900d9; color:#333333; } PCBSketchWidget QListWidget { background-color:#0ff; } QDialog QFrame, QDialog QFrame QLabel { color:#333333; } PCBSketchWidget QDialogButtonBox, QDialog QDialogButtonBox, QDialogButtonBox { font-size: 11px; /*min-width: 100px;*/ text-align: center; background: #ececec; border: 1px solid #b1b1b1; border-radius: 0px; padding: 10px; color: #323232; margin-top:3px; margin-bottom:3px; } QDialog QPushButton { font-size: 11px; /*min-width: 100px;*/ text-align: center; background: #ececec; border: 1px solid #b1b1b1; border-radius: 0px; padding: 2px; color: #323232; margin-top:3px; margin-bottom:3px; } PCBSketchWidget QDialogButtonBox:hover, QDialog QDialogButtonBox:hover, QDialogButtonBox:hover, QDialog QPushButton:hover { background: #fff; } PCBSketchWidget QDialogButtonBox:on, PCBSketchWidget QDialogButtonBox:pressed, QDialog QDialogButtonBox:pressed, QDialog QDialogButtonBox:on, QDialogButtonBox:pressed, QDialogButtonBox:on, QDialog QPushButton:pressed, QDialog QPushButton:on { background: #666; color: #fff; } #PrefsDialog { background:#f0f; background-color:#0ff; }fritzing-app-0.9.2b/resources/styles/linux-fritzing.qss000066400000000000000000000002501250202676700233600ustar00rootroot00000000000000/* override the combo box color because the linux menu background is dark grey so the standard color is too dim */ #infoViewComboBox { color: rgb(0xd0,0xd0,0xd0); }fritzing-app-0.9.2b/resources/styles/linux-gnome-fritzing.qss000066400000000000000000000000001250202676700244540ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/styles/linux-kde-oxygen-fritzing.qss000066400000000000000000000003021250202676700254260ustar00rootroot00000000000000/* probably obsolete now StackTabWidget::pane { position: absolute; top: 0.43em; } StackTabBar::tab { min-height: 1.5em; padding: 0; } #partsEditor QTabWidget::pane { top: 0.65em; } */fritzing-app-0.9.2b/resources/styles/mac-fritzing.qss000066400000000000000000000000421250202676700227600ustar00rootroot00000000000000/* add Mac-specific styles here */fritzing-app-0.9.2b/resources/styles/newpartseditor.qss000066400000000000000000000070661250202676700234550ustar00rootroot00000000000000/* new parts editor */ #NewNewPartsEditorConnector0Frame { background-color: #cccccc; margin: 0px; padding: 0px; border: 0px; } #NewNewPartsEditorConnector1Frame { background-color: #eeeeee; margin: 0px; padding: 0px; border: 0px; } #NewNewPartsEditorConnectorFrame { margin: 0px; padding: 0px; border: 0px; } #PESvgView { background-color: #000000; color: #000000; } #PEToolView { background-color: #000000; color: #000000; } /*try to change tab-menu without luck ... QTabWidget#peTabs ::item { background-image:none; border: 10px solid #f0f; color:#00f; font-weight:bold; } QTabWidget#peTabs{ border: 10px solid #f0f; color:#00f; font-weight:bold; background-image:none; } QTabWidget#peTabs ::pane { border: 10px solid #f0f; background-image:none; } QWidget#peTabs ::pane { border: 10px solid #f0f; background-image:none; } #peTabs QMenu { background:#f0f; background-image:none; font-size: 10px; font-weight: bold; } QMenu#peTabs { background:#f0f; background-image:none; font-size: 10px; font-weight: bold; } */ /* the Infos in the right window. */ QLabel{ background:transparent; background-image:none; font-size: 11px; } QComboBox, QPushButton, QPushButton:enabled, QPushButton:active{ background-image:none; font-size: 11px; text-align: center; background: #ececec; border: 1px solid #b1b1b1; border-radius: 0px; color: #323232; padding:5px; margin-top:3px; margin-bottom:3px; } QComboBox:hover, QPushButton:hover{ background-image:none; color: #fff; background:#666; font-size:11px; } QComboBox:pressed, QPushButton:pressed{ background-image:none; color: #d9d9d9; background:#f23926; font-size:11px; } QComboBox:disabled, QPushButton:disabled{ background-image:none; color: #656565; background:transparent; font-size:11px; } /* drop-down buton of the combobox */ QComboBox::drop-down:button { background: transparent; border:none; } QComboBox::drop-down:hover { background: #f23926; border:none; } QComboBox::drop-down:on { background: #f23926; border:none; } QComboBox::drop-down:selected { background: #f23926; border:none; } QComboBox::down-arrow { image: url(:/resources/images/icons/combobox-arrow.png); border:none; } /* drop-down list of the combobox */ QComboBox::QAbstractItemView { background-color: rgb(236,236,236); margin: 0px; padding: 0px; } QSplitter::handle { height: 4px; width: 4px; color: #666666; background-color: #666666; } /* spinbox styling for connector position */ QDoubleSpinBox { background: rgb(255,255,255); font-size: 11px; color: #000; border: none; } QDoubleSpinBox::down-button { background: #fff; border: none; image: url(:/resources/images/icons/spinArrowButtonDownNormal.png); margin-bottom:1px; } QDoubleSpinBox::down-button:pressed { background: #fff; border: none; image: url(:/resources/images/icons/spinArrowButtonDownPressed.png); margin-bottom:1px; } QDoubleSpinBox::up-button { background: #fff; border-bottom: none; image: url(:/resources/images/icons/spinArrowButtonUpNormal.png); } QDoubleSpinBox::up-button:pressed { background: #fff; border-bottom: none; image: url(:/resources/images/icons/spinArrowButtonUpPressed.png); } /* QTableView { selection-background-color: #f0f; background-image:none; image:none; } QTreeWidgetItem { selection-background-color: #f0f; background-image:none; image:none; } */fritzing-app-0.9.2b/resources/styles/partseditor.qss000066400000000000000000000105011250202676700227270ustar00rootroot00000000000000/* #partsEditor QLabel { font-family: LucidaGrande, LucidaSans, Tahoma, Arial, sans-serif; font-size: 12px; font-weight: bolder; } PartSpecificationsWidget { padding: 0px; margin: 0px; border: 0px; border-top: 2px solid #52182C; } PartSpecificationsWidget #scroll { padding: 5px; background-color: #7F7F7F; border: 0px; margin: 0px; } PartConnectorsWidget { border-top: 2px solid #52182C; background-color: #7F7F7F; } QSplitter::handle { height: 6px; width: 6px; background-image: url(':/resources/images/splitterHandle.png'); background-repeat: no-repeat; background-position: center; } PartsEditorViewsWidget QSplitter::handle { background-color: #7F7F7F; } PartsEditorView { border-radius: 5px; background-color: #D8D8D8; } SingleConnectorInfoWidget[selected="true"]{ background-color: #D8D8D8; } MismatchingConnectorWidget[selected="true"]{ background-color: #EDEDED; } SingleConnectorInfoWidget[selected="false"], MismatchingConnectorWidget[selected="false"] { background-color: transparent; } SingleConnectorInfoWidget { padding-left: 9px; } SingleConnectorInfoWidget #description { color: #777777; } #header { background-color: #330011; } #center, #footer { background-color: #52182C; } #footer { padding: 5px 0px 5px 0px; margin: 0px; border: 0px; } PartSpecificationsWidget PartEditorViewsWidget QLabel, PartSpecificationsWidget AbstractEditableLabelWidget #title, PartSpecificationsWidget HashPopulateWidget QLabel, ConnectorsInfoWidget #title { color: #52182C; } PartEditorViewsWidget { } PartSpecificationsWidget HashPopulateWidget, PartSpecificationsWidget PartEditorViewsWidget, PartSpecificationsWidget AbstractEditableLabelWidget, ConnectorsInfoWidget { background-color: #B2B2B2; border-top-left-radius: 10px; border-top-right-radius: 10px; } ConnectorsInfoWidget QScrollArea, #connInfoContent { border: 0px; background-color: #B2B2B2; } HashLineEdit { background-color: #D8D8D8; } AbstractEditableLabelWidget QLabel { color: #7F7F7F; } #createdBy { font-weight: normal; font-style: normal; padding-top: 5px; } #iconImage, #partTitle { background-color: #996B7A; } #partTitle { border-radius: 6px; padding: 4px; padding-left: 15px; } #partTitle QLabel { color: #656565; font-size: 18px; } #partsEditor QTabWidget::pane { padding: 0px; margin: 0px; border: 0px; position: absolute; } #partsEditor QTabWidget::tab-bar { left: 5px; top: 5px; } #partsEditor QTabBar::tab { margin-top: 5px; border-top-left-radius: 4px; border-top-right-radius: 4px; padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px; color: #821F09; border-bottom: 0px; min-width: 6.5em; max-width: 6.5em; margin: 0; padding: 0; min-height: 1.5em; } #partsEditor QTabBar::tab:selected { background-color: #D63222; border-bottom: 0px; font-weight: bold; } #partsEditor QTabBar::tab:!selected { border: 2px solid #D63222; border-bottom: 0px; } #partsEditor QTabBar::tab:!selected:hover { border: #F23926; } #scroll_test { background-color: green; } #mismatchConns { background-color: #d8d8d8; margin-bottom: 5px; padding-left: 2px; padding-bottom: 4px; padding-top: 4px; } #mismatchConnMsg { color: red; } #mismatchConnsHeader, #mismatchConnsFooter { font-size: 11px; color: #777777; } #mismatchConnsHeader { font-style: normal; } #mismatchConnsFooter { padding-left: 15px; } #mismatchConnsFooter { margin-top: 4px; margin-left: 3px; } PartsEditorViewsWidget { background-color: #7F7F7F; } #iconBrowseButton { margin: 0px; padding: 0px; border: 0px; } #guidelinesLabel { margin-top: 5px; font-size: 11px; } #partsEditor QComboBox, #partsEditor QPushButton, #partsEditor QPushButton:enabled, #partsEditor QPushButton:active{ background-image:none; color: #fff; background:transparent; font-size:12px; height: 34px; } #partsEditor QComboBox:hover, #partsEditor QPushButton:hover{ background-image:none; color: #d9d9d9; background:#f23926; font-size:12px; border:none; height: 34px; } #partsEditor QComboBox:pressed, #partsEditor QPushButton:pressed{ background-image:none; color: #d9d9d9; background:#f23926; font-size:12px; border:none; height: 34px; } #partsEditor QComboBox:disabled, #partsEditor QPushButton:disabled{ background-image:none; color: #656565; background:transparent; font-size:12px; border:none; height: 34px; } */fritzing-app-0.9.2b/resources/styles/programwindow.qss000066400000000000000000000134541250202676700233000ustar00rootroot00000000000000 /*this is the background behind the tabs */ #programmingWindow #center { background-color: #85807e; } /*the main styling for the tabs in the programm-tab*/ #programmingWindow QTabWidget::tab-bar { /*top: %2px;*/ left: 10px; right: 10px; /*top: 5px;*/ background-color: #ff0; color: #f0f; } /*this is the background around the tab-frames*/ #programmingWindow QTabWidget::pane { /*top: %1px; the value is swapped in at runtime in ProgramWindow::setup() */ padding: 0px; margin-top: 0px; border: 0px; background: none; } /*this is the base-styleing for the tabs*/ #programmingWindow QTabBar::tab { margin-top: 5px; margin-left: 8px; margin-right: 0px; margin-bottom: 0px; padding-top: 2px; padding-bottom: 2px; padding-left: 6px; padding-right: 6px; background: #5f5756; border: 0px; min-width: 6.5em; min-height: 1.5em; } /*the active tab*/ #programmingWindow QTabBar::tab:selected { background-color: #1c1a18; border: none; font-weight: book; color: #fff; } /*the inactive tabs*/ #programmingWindow QTabBar::tab:!selected { border: none; color: #999999; font-weight: book; background-color: #5f5756; } /*the inactive and active tab-hover-effect */ #programmingWindow QTabBar::tab:!selected:hover { background-color: #474141; border:none; color: #c1c1c1; font-weight: roman; } /*the "closebuttons" on the code-file-tabs*/ #programmingWindow QTabBar::close-button { image: url(:/resources/images/icons/dockWidgetCloseNormal_icon.png); subcontrol-position: right; padding-top: 5px; } #programmingWindow QTabBar::close-button::hover { image: url(:/resources/images/icons/dockWidgetCloseHover_icon.png); subcontrol-position: right; } #programmingWindow QTabBar::close-button::pressed { image: url(:/resources/images/icons/dockWidgetClosePressed_icon.png); subcontrol-position: right; } /*the actual code area */ #programmingWindow #code { color: #ede0ce; background-color: #1c1a18; padding-top: 8px; padding-left: 8px; border: none; } /* the splitter/drag handle between code and console */ #programmingWindow QSplitterHandle, #programmingWindow #splitter { background: #5f5453; background-color: #5f5453; color: #5f5453; } /* console output window */ #programmingWindow #console { background-color: #8c8686; color: #3c3936; border: 0px; padding-top: 8px; padding-left: 8px; } /* toolbars at the bottom (new, open, save)*/ #programmingWindow #toolbarSelector { width: 120px; min-width: 50px; max-width: 190px; padding: 0 10px; } #programmingWindow #boardSelector { /* width: 120px;*/ min-width: 50px; max-width: 160px; padding: 0 10px; } /*the closed dropdown menues for platform, board, port */ #programmingWindow #toolbarSelector QComboBox { margin-top: 5px; } /*the text below the dropdown menus (platfom, board, port)*/ #programmingWindow #toolbarSelector QLabel { color: #ffffff; font-size: 11px; font-family: Droid Sans; font-weight: normal; qproperty-alignment: AlignCenter; } /*don't know-... maybe console window*/ #programmingWindow #unableToProgramLabel { color: #333; background-color: #FFFFC2; padding-left: 5px; padding-right: 5px; padding-top: 1px; padding-bottom: 1px; } /* the dropdowns */ #programmingWindow QComboBox, #programmingWindow QPushButton, #programmingWindow QPushButton:enabled, #programmingWindow QPushButton:active{ color: #fff; background:#821f09; font-size:12px; border:none; height: 34px; padding-left:8px; padding-right:4px; } #programmingWindow QComboBox:hover, #programmingWindow QPushButton:hover{ color: #d9d9d9; background:#f23926; font-size:12px; border:none; height: 34px; } #programmingWindow QComboBox:pressed, #programmingWindow QPushButton:pressed{ color: #d9d9d9; background:#821f09; font-size:12px; border:none; height: 34px; } #programmingWindow QComboBox:disabled, #programmingWindow QPushButton:disabled{ background:#AC6A5B; color: #d1aca4; font-size:12px; border:none; height: 34px; } /* drop-down button of the combobox */ #programmingWindow QComboBox::drop-down:button { border:none; } #programmingWindow QComboBox::drop-down:hover { border:none; } #programmingWindow QComboBox::drop-down:on { border:none; } #programmingWindow QComboBox::drop-down:selected { border:none; } #programmingWindow QComboBox::down-arrow { image: url(:/resources/images/icons/combobox-arrow.png); border:none; } /* drop-down list of the combobox */ #toolBarComboBox QAbstractItemView { color: #000; background-color: #ececec; } #toolBarComboBox QAbstractItemView::item { color: #000; border-bottom: 5px solid white; margin:3px; } #toolBarComboBox QAbstractItemView::item:selected { border-bottom: 5px solid black; margin:3px; } /* scroll bars */ #programmingWindow QScrollBar:vertical { border: 0px; background:rgba(255,255,255,10); width:10px; margin: 0px 0px 0px 0px; } #programmingWindow QScrollBar::handle:vertical { border: 2px solid #b2b2b2; border-radius: 2px; background: #b2b2b2; min-height: 5px; } #programmingWindow QScrollBar::add-line:vertical { background: none; height: 1px; subcontrol-position: bottom; subcontrol-origin: margin; } #programmingWindow QScrollBar::sub-line:vertical { background:none; height: 1px; subcontrol-position: top; subcontrol-origin: margin; } /* Serial Monitor Console */ #consoleWindow QPlainTextEdit { background: #222; color: #eee; } /* not used styling */ /* #programmingWindow #header { background-color: #f0f; padding: 0px; padding-bottom: 0; } */ /* */ /* #programmingWindow { background-color: #ff0; } */ /* */ fritzing-app-0.9.2b/resources/styles/updatedialog.css000066400000000000000000000006221250202676700230160ustar00rootroot00000000000000table { border-width: 1px 1px 1px 1px; border-spacing: 2px; border-style: outset outset outset outset; border-color: white white white white; border-collapse: separate; background-color: white; } table td { border-width: 1px 1px 1px 1px; padding: 1px 1px 1px 1px; border-style: inset inset inset inset; border-color: white white white white; background-color: rgb(255, 250, 250); } fritzing-app-0.9.2b/resources/styles/win-fritzing.qss000066400000000000000000000000461250202676700230210ustar00rootroot00000000000000/* add Windows-specific styles here */fritzing-app-0.9.2b/resources/templates/000077500000000000000000000000001250202676700203155ustar00rootroot00000000000000fritzing-app-0.9.2b/resources/templates/0.3.schem.schematic_frame_template.txt000066400000000000000000000047411250202676700274660ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/bom.html000066400000000000000000000021411250202676700217560ustar00rootroot00000000000000 %1

Bill of Materials: %2

%3

%4

Assembly List

%5
Label Part Type Properties

Shopping List

%6
Amount Part Type Properties


Exported with Fritzing %7- http://fritzing.org

fritzing-app-0.9.2b/resources/templates/bom_row.html000066400000000000000000000001101250202676700226370ustar00rootroot00000000000000 %1 %2 %3 fritzing-app-0.9.2b/resources/templates/generic_dip_fzpTemplate.txt000066400000000000000000000027031250202676700257030ustar00rootroot00000000000000 4 Fritzing Part-o-matic DIP - %1 pins 2009-10-23 DIP fritzing core Generic IC DIP (Dual Inline) [THT] %1 .percent.1 IC true part.dip.%1.pins A DIP stand-in part for whatever IC you want. With %1 pins on a .percent.1 dual inline package (DIP) footprint. %2 fritzing-app-0.9.2b/resources/templates/generic_female_10thin_double_pin_header_schem_template.txt000066400000000000000000000027131250202676700337530ustar00rootroot00000000000000 %3 %4 fritzing-app-0.9.2b/resources/templates/generic_female_10thin_pin_header_schem_template.txt000066400000000000000000000013441250202676700324200ustar00rootroot00000000000000 %2 fritzing-app-0.9.2b/resources/templates/generic_female_pin_header_bread_2nd_template.txt000066400000000000000000000013351250202676700317560ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_female_pin_header_bread_template.txt000066400000000000000000000013121250202676700312060ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_female_pin_header_fzpTemplate.txt000066400000000000000000000033661250202676700305440ustar00rootroot00000000000000 4 Fritzing Part-o-matic Generic .percent.5 header - %1 pins 2009-10-23 Pin Header %1 .percent.3 .percent.1 .percent.8 .percent.9 .percent.10 THT Generic .percent.5 header %2 fritzing-app-0.9.2b/resources/templates/generic_female_pin_header_schem_template.txt000066400000000000000000000011001250202676700312230ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_male_10thin_double_pin_header_schem_template.txt000066400000000000000000000027151250202676700334420ustar00rootroot00000000000000 %3 %4 fritzing-app-0.9.2b/resources/templates/generic_male_10thin_pin_header_schem_template.txt000066400000000000000000000013431250202676700321040ustar00rootroot00000000000000 %2 fritzing-app-0.9.2b/resources/templates/generic_male_pin_header_bread_2nd_template.txt000066400000000000000000000017661250202676700314530ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_male_pin_header_bread_template.txt000066400000000000000000000017251250202676700307030ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_male_pin_header_schem_template.txt000066400000000000000000000011001250202676700307100ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_rounded_female_pin_header_bread_2nd_template.txt000066400000000000000000000027521250202676700335020ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_rounded_female_pin_header_bread_template.txt000066400000000000000000000027071250202676700327370ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/generic_sip_bread_template.txt000066400000000000000000000034471250202676700264050ustar00rootroot00000000000000 IC %3 fritzing-app-0.9.2b/resources/templates/generic_sip_connectorFzpTemplate.txt000066400000000000000000000007731250202676700276020ustar00rootroot00000000000000 pin %2

fritzing-app-0.9.2b/resources/templates/generic_sip_fzpTemplate.txt000066400000000000000000000026661250202676700257320ustar00rootroot00000000000000 4 Fritzing Part-o-matic SIP - %1 pins 2009-10-20 SIP fritzing core Generic IC SIP (Single Inline) [THT] %1 300mil IC true part.sip.%1.pins A SIP stand-in part for whatever you want. With %1 pins on a 300 mil single inline package (SIP) footprint. %2 fritzing-app-0.9.2b/resources/templates/jumper_copper0LayerTemplate.txt000066400000000000000000000006441250202676700265050ustar00rootroot00000000000000 Jumper SVG fritzing-app-0.9.2b/resources/templates/jumper_jumperwiresLayerTemplate.txt000066400000000000000000000004421250202676700275050ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/jumper_pcb_svg_2nd_template.txt000066400000000000000000000012401250202676700265160ustar00rootroot00000000000000 Fritzing footprint SVG %10 fritzing-app-0.9.2b/resources/templates/jumper_pcb_svg_template.txt000066400000000000000000000012371250202676700257610ustar00rootroot00000000000000 Fritzing footprint SVG %10 fritzing-app-0.9.2b/resources/templates/mystery_part_dipFzpTemplate.txt000066400000000000000000000030171250202676700266310ustar00rootroot00000000000000 4 Fritzing Part-o-matic Mystery Part - %1 pins 2009-11-17 mystery part fritzing core Mystery Part %1 Double Row .percent.1 ? THT true part.mystery.magical.%1.pins A dummy, proxy, ersatz, stand-in part for whatever you want. With %1 pins on a .percent.1 inline pin header footprint. %2 fritzing-app-0.9.2b/resources/templates/mystery_part_sipFzpTemplate.txt000066400000000000000000000030021250202676700266420ustar00rootroot00000000000000 4 Fritzing Part-o-matic Mystery Part - %1 pins 2009-11-17 mystery part fritzing core Mystery Part %1 Single Row 100mil ? THT true part.mystery.magical.%1.pins A dummy, proxy, ersatz, stand-in part for whatever you want. With %1 pins on a 100 mil inline pin header footprint. %2 fritzing-app-0.9.2b/resources/templates/perfboard_boardLayerTemplate.txt000066400000000000000000000005421250202676700266630ustar00rootroot00000000000000 %8 fritzing-app-0.9.2b/resources/templates/perfboard_connectorFzpTemplate.txt000066400000000000000000000007551250202676700272570ustar00rootroot00000000000000 perfboard socket

R ɓnvo$,8N2R%+' WS) e@QRx*jx,tQ5bPn|%-INm҂  :DO5-(!AQ5QĤ^VO!AɒVsIEdkKIu@e#,4tb&Н͙uNa%#҇,jdtҡr.h:#Nq5z/.}s~iQi qB@^UH v&1$  ~0~I T3Cת4,d"J|ZʘQ(܏.o퐠$ 20cqT5 4B'  -1^O&xFz,c|]e9!jwz[] Ѿ= 'H9rdGMK uҦ4f `tEXBb6҂ܜJYTNק^YhHFFJã3 RD& q@s3䝌@Q t(jBIozhbj# ZDhWZt܉tr<:0 P^^i2E2>) =#LT0iK+%_adno}q*bሯ4J5Gg$`$|'g1n>[sc>KQT,җ`fZntAI<d$f8~`%=8B5#.$uFjˬ(+(ѕ.ElbvŽ 7D|c9w9GtS/b9ҹjN[\'G6;ZLȍ[@1YN1JR!Lס*c$& pET7V?[ ZL @'@>ɿu!ߪ0Ylf-J%3bJzJ.ς'F: u9K蝂ƙq ۥh8H >J@7#- <ҺVAl s]9GA.(:N%$Կ0Agܶpd,m(>RBsxD^B|2k&EJO/Op-#C)Ŗ16̓>iZ{x:2Ԩ 퍼ѭX;tN/sՂ-$%0YXIU.2 kO.˓BTwL΀wJS6 9V¼qN= 9EIBdZnm%Ϙ}E-_ͿZO,bѢS#=)'{fA{fD%~sBѪn [Շ`ڡI)&Cf]b=_jNrd%4D~&Aݢ,(*|,1cTs.ѱN xPcF3GT+%>䁞Vzډ@ĩ$$F^-yK~:%$Ԗf#1?gIz 8 baKz!:_Adtxdp¸[~vN\gCf0ɤE9i| eCꪳ>0aK!:O4Ki:Q4>/gE :*O5G8^  nlFŅj#Bgi_1e[9}̵{gGwKiCNJ +mZ Z*$ĭY6s$i5US.p.) CnvbJɻŰ0{r)W.qݹY).f8S.Q;bJI%^hP 7ldal 3oEus;\? P2QK5XXTPS!(v<98sY>Y,`"GOsǬ܃#8C LZ6yC#vHAOBIް]Т?GxۇxYaK:ζMp $K BiQMZx{Mͳ*=O dߙRF*[xv7+ )nyUpJ:gͿ;-=]ZKfNd.$U8#|+8c2Ey =:(lϛICж$e-5;iG%dOVғJWt9)q PI2"AẨ3^ZD:Qm#8 9&_])S0[vAd`8DL>1uqhC&MU]b0/ ~>`odj/_XpSؤ]E >O( .4i(F=.wޤb~3bTX 7z G(c3I񪐐?P 'a'nDk'莇ZG*D{ulZE8sZJ %P B(:PR5x[2&i+BaCvdB#,x^#aqM奭x?Nd(۽Wx4F\;*gKf3hP 3i1bicPYw8n/섶2CCI38 Ѥ]#- 2cū%|JEב/(MD^.0OČpRvH "h>#]'a(j1mHdɡi"\s1/g~\@6=iH|DlPoekhw˛]CB*! :\?.+bҴcZHDYuX㙠vB*J1}li'I F /5iMo6!ޣ` d]]) v"& :p5Ec78DZy-ZӨ MmX@aX脩IWO__Rq m,, )!R;IM> b8 }4hJ%-%I:Z*Z 1rCQA"tָk-u.fg6Pg"R㜶+.uńyUeXUSVK;6EHɫ&qk3=Ot_$AN ZIuck&fYVvT,A)Z/tz 2&yVT {B2&P(l_xW-Ul9q`eqY9ݠ(uh8)URgO l޶{8o|?p0jrXxSD dž0m /;ybeǹɩo9fZ&rJ lMH CF^Mew(oT@]"bԻNFͷ)ɛ25h4+vЊ+ z&04B5&aKY,~>[,Dȍu/p8blQРHA^y8O\8$*f}Fz@o8T`h$Z8".}Rn4);W'JIU(S/P~3ĸO7Qc.s!>ZÄ;DuG0åX gXW m֠K &-~V"]p QKo-D {Xy5 %2L fxNN*;|#3IHQO.z Xj1҄vEC _K.DLhn=9)rԧ'O+E4Cy]b4 2\ԤXS$t*mBHy)*CK)%S̓l )AS-²Ig'#2]stFXrQ ?f~zd)g_r(C\ )/곘JDyA8oى̜lxARִXb(}xj3&9xꮾ^ "j,=$d)XuJ| ͠*zy#Ԣ&ZZcj`*骼UaQ#9dBUk#}(3>ϳyWa=w=ɜD%td!Єks*IbW~f0|D渜avBUŃht6M-=F bpTx*,}8u Fc׼^֎X,{H|6A Ù oVnWl0LZM7cKFU,|?>&mԂ^̌JRR*e>ĖwQ[ʰHn(.;-n#{kI谒v v~yƐ0BeD(|uug3ULts}eEK؋VO\37LƧU% (-۱X4tGD,gttXppk_km4q45 y0*CzrJNŵdpfNg3s @:] Xd= 0EB!u'J@y4%UoB"c4Cu]b27ݩ I(((1BI>1۠ d ؿQBwS:%j55ص Ŗ+ɐ[C^X+hB<4Mפ 5fzHEf+ic7YȗH@+`&gݰ 4xah]'b%(_˃x+kVeHW[n(pEĭR2=qqjza(:xŗHp9zrrv I(2N]?iށUYq]Ȼ:().TOE]!ET!vsQa싱O"бWm\m/ӾRe^ "Z $ rM65 P}@mM'JhwP_";#{fTQvUbM&ϯϵXQkwY2}(JϜ roͤ|7\r>Vms|"@)wBWMՆJyTu1TxX/4:P[$50/ǡŎ{Ȃv-,A=HGt~W9Z^iB݈dc_knaHw B7Gu$yn5UL& wRhszb5 ZxǕ?2py}#D5ځz2C>xL\.kB@OPsBHtW"h2}x^mĸhI1:(aT1S~ cgBom}_haړ]9{ aFd b}[@ 4uUeO|;o"w0O$_:3C̆JAn @^IqV!U LM.D_):NR@U-X>E -"D"a .Ω+S'u`V51^A^\섂s:gVH<>ۼڗ@읇l4 ǺWׇCa2&@F14qdI4X}XܶǧcU =f6?g"-Z6@~Q:_Wcc_jK1.Kxm:*j}fi< zQ ;ٍ!l{!Bfa/1ہ0z݈n!Oki 2 87JPGpPbڝCĴ$d2[J)WηK"q ~8s7KğDUm MzZL$D(sO)V3@&N͸gkdt6χ3mk?Tgz'.kQP(V CrX0<(n;KѠ0ĜujGtTו]`(+:x8S4k+RGtֶEt9>v8,"B&Q"4%V&!LGbJJqe:߯k&˒nT&dtf0(<,^H Z[(r[M=AMI5ӷ6W݁zҧ9|aH)[4@U^W87'' [ホGr,2&dy5<!GvI0 BMLKVXG INȩWQBE팸~HpU%l g4Ů ҅g)DWLQ-IU/?6-،XSH;ڵf,+ԴTz9?*3$!5z^1<,@\}*7mg7g=Ap_H6tSTr A7B$x̃ChBgapb(1Gg zՖeWxoI#aܦXߖ;cu ')[ʹ4F-soi#URKǗ+< TLmo?h}}([.Xл9L>0=4-x휖|Dh}k8ڦn r.h!TFH$M*j֌8r2'N4ZAMR8hw„ U IẠ^FGQ5&C:=~}b*pH}%='`ч9{7fYQ`7pؔ=~B2Q?r"u# 2o^pXG8ͭ?v[ JEϽR/!fmF_o%nC:{głm~"^ce"W8\tD̀\*>[ 8S^dr1F2U8ULRR@}MJr"3 e)=h X9,FH]~'KeAWaֆ16&}q'3=fmYuͬ<ˆ.BP3Gх* ObϬb|\ a Ʀb^wUmѺt:+hn׊;HX{bU(r~rdxfB!o}l$1uhw蔤.%._lԘmZUI?II}ֆJ\ܴzB̄ dz 0ȏvgA 0 \n#f=DrKT@sैUhWzYW]Xx*IQ&SB[T=,vrW{O(l-JUcRF{0 Z| <:Faa`O88}W3h&7#Zu|&]󢽌Ǘ{*#%CؾMش;~$Hy* X0F*GlVwC#1٪qggCv3/҄@Z4]pw8NLTjʑbİSQپCiZ($&YG*5-|\w*S3c <-J4ݕx7,V$*e9=FatesDŽL"cB;U[|% Ux7Օ-|uM[Oix1#tRFa8.HdsJ[`a NayHF TwhjyY9.#ج=FlUگbYELB*xI"XNPwc!cX`/`{#nBM ؑ2Y6]>1XbDhˣkL|[ s`:r.@ 6}=,Wmtum1B'Uh/UҲz.'@^@ﻳqR^m&fЊ#2d26P̉jDʴ33Nү u >W'vWW[9zܯ]`5[h~E7rȯ fz\[qehs$H0M4؅4|Q#y]1)ޓPN/?ⳇc&I'l֨`_ Z5xx5(+ATfTL^Q@CiEsKYX‡@ ܂Skr{x A˹A2GoR^*#em^SQ(w =*6ҽMms]N+"+ ۗ+BSCo^iGY,NvlxBfeit98jbJ6V)1@w'0Xu6cfx{PCjůs޾,MX(랏mG>Qq啤W$`i6pa[;0[D\_n~@r9/- 4cCa5oҮӣ*GV8}kg;Yҵs["4=l3ȣtAKf7Mqj9߀;"'px 7QJ5<1u+5P@XQ2qģ8f(5jkt5Y;c?̔vlμ2=sύ)dr~qb-)BeIQ V'{t }*ChY|SԺSG 'uh028%TN»33H6+FS>˙%,Ghy n0Els;FW8Kx F)6 : XQI وAO?4,ZɡciMHMΛRHCw׶`E۾wUxpk /;Rj›)Ij@qҋIb{'!6M zfU?(h RS{Ϲ*:Lw ;Vw6[q_M[ oU''Ӆu8p!fX؄(536y^d["z{b@2|m/kD2gӫuZjn5e`BGeHGnoC6B 27풢`'5>6z25pG(wHQPN/~[BIsP>-`ңnWByǰ/K$դϕ8O|]BPV &qi# ę~#sĿ#hk~n=hS J tX2 ըG<5vҗAU2J3xXUngɒP,ݽ?_ ;aΞh1.Ǖ8qeLZo5Sk 1DE4z_S7hI߾_y(bH u-p_<Q?Ɔ%x~RM8_~ϋT/B=ƫX즣\P/AڄAGChp.Lك7B+T5㩑RC,>Tf1 RPRZFFM0^r4;@J~^5 =`[1xgya]{9fe+*A%A({m1Cb' c7Zy0_AhQx 9dGT9Fu4:n^7O!pepa K;̾=Do  WtJ7/`5kP٨TR ҽJ!i}(P06&@IɓN4i{37}}%MFW ) fkpMTȳSn4hz h~h Yy/o恬MEzu9~Nb5X{hQn^7ou6eOv ؆)oߦY/ b|m6pF_@ls(ɆGRmh.]T|by-p_n?? :=Q2M#<85<75!Q _ -=O{"Ֆ~1U8^B!xM 2sWm K! 8w#ȦkkẢUciCS3f FTO<}L{U1 5<0V,Lm~w*ȶVCˊ yRx\Y=]Suʃ0M/{,C_ Tʀe^l0T2 bLM<&r4fha]obܘjУq3MY0套<&60Dr."0cO#jCDD \->2Q\{GeZN^^glY'/ȑ3)u?$)KcVHA<D5y熾lQAұϻu5FeB{Zq6]'I\ylu}Vc ۭ!d3c >)90K-4X&a5IB&Rk3 c$qDVvy@hm`_@\G  ׅ} ^O;h(q]V;uDW^ǂhn A{AT2XMFa,y%ϭeU23]dIt3bSX}YF?'MHO3RhW}Kf*tD-dŗ/7.jjQb|DGV'*کRU P*l>yY$Y{)-X M.ahMS cV@뚂E/ / J|= RہͰܾ%lQfԚz*AL퉩("L + O8/(́bOQ@vǪ~e("@F@mN:HG Ti`NУW )EG)7ԀIm|Ɉ.J 7!CA݁tr)6;fOL3Z `ڍ*n 4^t{?UczBTWɄ(m߹!S>la@b'6V34Aqvd9}0 -u W:xt7i3$lԷ%>:B= ^_"s6_Ȑ3>)ixO _͠=`kk =E%NCBw:84l!mtiqLOZp-MUY/kXӅ>;fC.bc@ enV?聕RqnzF3Y*u&:zF5c;uGn"ә+U#^ypjl6W"Gy`\Piз3/?.j. "i0 Dze 4^+DrK$Nl DQ "}JFpS9T +KL䈐|~RՎ=D-9#nAI9W·oxc~ I0 x4R`yo̻ݩCVDCh7:[ɽ_BվnfaK]+"!NZ uKOj%lٸW- cV.4Uf[(ҚuGEz L`^n"be5+yED  Dz X\1fD!J ių]V WLĘeAԐRbZtu>෾(5 [JUSG{GG+R.w\EZ;A-ᑒXc0)towJfY=N RǮ+lQRz ]f2,;5;SqUuM^{5H p_ Lػw}-b8=>]UHg]xm*Jeb.9FfC[40e-՛]uM]gzb6JK@7G_ 8u&G0Uf7%UFҥHUtI/8$7r\㡁qu,[曩cR~ZC||But&JO/'e'DP5҅NPC3'nڠE؂LnX`sՖ?e} |?v*S҈20ӺTюUyP>pk>7BI 3`S I J9O-Ś88(n$_NE}ța\s1>ЇµAGa,?8odk\%Y+Wi2k*2 /iUQ?wl{Q.ap1p je@.6_SX|t~T|^@ Sݏi.r{$X-xـv\sI4IനcBRtF$ =%@쿅b-=uId4g[:2;յBkK n]Na-\ȀfЁf1yQ;.xȸב&;MȾ(VW 5ZR(yۡ8c38=su- K!as4=RgrlM,uz|6` NMLCGU./%t+^Zk dx.q84R{OCn("+Ayp((Pt J>AqP;+S=G0ጦu$AUI7k6l(/hB ˟;T [t4uM-%3A4I (ЁLm1 .pv;eV}"R\"hۼP1\) qk03bD{d+p9NаKG 5BGE<_"/'& ЃRa2lvbxCa:V"R5Vlz]҃+_.(dЂ+eϨ [eRyWSc]'Ti2vK}dEtܶe)f`ȞshVz8pYiq*0{lxSkx"mli d}{D!1)-3doWmnEZU;)bT;"'& zYJCP}nx۝")O/~ L.zc pG9{%I#^嘧gzAVL\i)Wԋ3*؈3*6ta yogi{ X$/JIuŭfItLXqZHXɄjc${[x4b"A5D8aܪZ_e+ dbE-a*e_=^+_yH-2Jq"f 3F}*FMÖg\|GjDNm%/zM%ˆg"%IAvk΋Bbk8ך ֮NSchnCsaU;uձZ3 3m(A !^5k&{@(pߠj?Iď ֚/j=*ZlW| q٢F݋;T[,^ӧ/cM_Xu#B_EHR#jvʥx Ps8>V4@`r7-r6z!d csL%? 2 ]) Ȫg?))AqP,tV}GRrc8kJ*`Pmrbu3puFY1 J,YT`s[{ac'c75LUL/.^3aD mk^Ci)&ш,R2n3CaGU,JG-ThWfl'ˠbïL\EǶGda/,.%$*3ꉋ"4I2r_IOȩ) , Y:,0V!Z}/I⠇,JD54 U͉DD +424T!7{/.2zЌ#X NlnAk  ,>Sl'|w6|-#{9c{#iX{LI`VB9ŘÌYS 4{da٠e5IᓊM;g0>hҷELǥ}D'A  TPbcO$VE9ARaZt*x[{Iq "Ph/n}߾lte_zW>hvSnBzDdx@+`.K5"AhEHIbwGAs`Kmf,kE*km^+^yq)t2-eFz 3zx)R@ɐqjù{k8vϽ0$~n@FtBTuXi6g?r) gc]bb%umNe@BE%ءba8]_R-Vx`$ȼ^~m&|Bѝuo[]a*cӑmRE=l&.Cͺd zC=Qwd/yAtr߁q~u$į#ŘHut"a NZ8Ȱ7Cq=CEi"en69ErE%f iYi K+ 6U^HFEJye@JrD_Hlq = "Q@=e֊Ch,;!ׁL7i}3` xbܩ2yď`_RQk7xDDR֢M+hMl8w7f75ڈ-!.y'e{ I~= vwtIA R%Qb*3:;ѹRc2Lb$aHब+QZ8R&&nkh"v EeTqӋl4&*#<؇`&s݇]p06a}myjB ux8ӦAa@B4HQeVplзX;E:6/CҖYODY&Ozq;JʘӋJ҉hKMDyA *`y# 5 :?1 )uB&>~C/m0)fT7w#7u[a[ѽY`E2ۙ-M WzpOhaC%HuϵVpʜsc,6Z=aE`!NUP<8Lƭܣ{<}_Uw:쉨NT lm:!DMu{ؖ{hnޯ=Z|:c9d1=)2 t1p=4mV1z4T & FBNQfmblU[Ë,MԻ^SHےN%R2*4Pe6ۗ$tcwvaP4pcpd 3qi. ns0Am<Tݠ0Fv65yGm]Mr2dy 'Z{}U=!Ė)m}Yw=,"F2loЬ]w -,۲&D]\<}mS:rdi_ _#I %9f2j~t PUykes9YU|^@R7n (kI1{4Oc(D:Ob~J"ZعLk2S z0 dQBG\SDHYڵ#-vWEB)fVVKՆE}$%Fl˞hB|[0='#oagR,{ .^6A(ˬ{ *sߵ3Afxp*'"tK F- T@bpDtHGE8o~hOwwC\ S;7 4l'.E~S*a$Ol$ݣo J ~(H*2m_gft>Ab_*DP5jDH6ݸ}2m;m|&MZZSo>G߳ȣu:(w Ӓx/ib7JKQf#4:p,V &ɴ8Qw ]S. [x[AnҊa!F"M`h`2Y.9BP4㏰]C"eb|EklJqԩtU%ʥ&kw|-LOQye~~()CY{E8&Ǟuϯ^Lq5&2@Fe@O8#ݰţ2]piIl=Qhо~buY|/Q#fk0u)G7y@HYT܏`|ԚE1ÌR'wx@P)(;29I"ۥk Aoxf"G낣 Ҫ< D1zE5Gi׹ahfV3Q]QҔH5:R+m@]8G\%RB _>)H.9;ͅdNm|;M6TZxWɝӖ۴0r/7[^Bâ+="mI2,i9f*/ Pm7mE|:1} EA|>.45P,VEFrW ~S/5:BO ]=7`Oߴ@VPN3/qvN&z=40V *hGQ*Q (7J^DY$xAb6hھuq ˠӎ"ռJՆYPqU~++&v.ՃR G[U r N;S#(VƩZ9 P魳[0~-P<r%x?-*)Z뺚Z\^MzL_j%8W q0}<H -ZȺ\Bm]>C%FJ,Z(\`ٛ*`IK$ )j%w$ikY^Gop/֘t'NՒTS8)R-^Am+ܯ\m0-G@O6MݱY\/p Ǎ48&*]=3⍼zkzHGJ5s_6~w Qwi`pʿXw|~RxqzqJuKr`T j¬c=l$+`S9z-F DkSp1a}T SH|'^W&ĂG[=7@ۤx3Hw1ۋb]x`jCEOS-S pQ@oTfKHo cl<qfkhg3t1;yՈ |%]Ԧ4=Sd ,\9DF{#8-Mԡ86< oQDVNy8Z 6>kO6O@@ZzqctS[t`=/HtQBÛmp{y=';z/HG/ļ)yKV a)p4qDvP)M[RM(8]p}kΛp(%`/2ywjGR@[^u;?]V"l~lBnK_#`DvĄVΩRmG d. YDبo|i)8v[+m{K6j\#{!W5+i De dW\A֨`pV͎ꢐ(؋8:p#k!Jwf$+.8>ᩋŠcVA&ĩM1ૣ!)Tpc 0mRВYpaGl-#}.9>DD)Ѕ2Wp H3aP!ݞX8hB  &'{h?,:\Z#ן׌__{rKM'02-9.;gItIKi[rLڹu@\fd%v %ȍE ]l@Jsë=C~vd27)Rm%4qx#zi2}aXeVPdDW.MvhL]'HxY&\mΨ7e7–[ WCZ`kvrݎnĀگ@ *Qߝ*@l*9ALӛKY}Ӳ"c-_+J'ycT2x&wᙋGYL؟6]Vv\}!%O=Ssܐ0cI,Wn24j![ɘ5~ʫ+.<@u֩3 W :iirKCp(&@X(DvEO6UxWq2cʺ 0`HTW =erBM7r6Ȧu!}9wi :iCάF?)QƅۀR?lFE+CF+R湗 y)?HyVyQ YîQb\0o6ԣ#9J3#M. hD|i#%0ט/i0xj nj^QW:w$F, x 27bt*!11>2PFBh8&;ʑbzY]2qŞYapH4|C'[z4Y2hOo0|߻PRjɊ\^Gv>~"yc*V14TAnR'n8&Wr#2vtҷ'@LpI=SZaFֱXv-XrV?rn4a o Ojsè-0'=g,h1X彬Snj[>93޼,pBz!Wv!y ŋ/Bq}Ņ/yR.1PgSnL ɅJaDQ u\R_N-'plhW؏];wG:n0sů/K@zr@;aL;N4UY쌺b~#܂~48Lpf&Ҿ5ߙt * ?H`չ}7Ms&Ymi{X4A866^ДDڎ #@aHVbe/u<"JV8nChtܸXG_M~r(|g]ee6_ZGFE"Nv\iJ~{B ELhhm̒ az$_F^+.+,\کpquv C"^l-njcQǥ0B j{4?哴hʕ[rF,--{5My_Ԧŋ֯/wu\^ VCԎ] G"tכA"܏LUyYgU\mIdcHa~c78sd,Dfc0*N쁱c'R7Ǝo,cɵ!vmu vކNLSNZIZ獯pqCum}=rus"/~_b _"Ņ-OV?7jC[MX1Ч@ǂhW(kܞQC7r&Iԗ*弴Q1*oq7u%G2 _?q(ad| Τ+e-<.XC1^?V%O%#9 @H{}-^9(fky-TbBUQN_{_0la*G6:mCyӆ@qa N?(8Kł/p< \xƴ?.N _਴hN#3sܼ^~_uYaw/j4ǵ?=t5  jӿy=53'Q3\m%7FHAO m7tc@ƨ)hX`RC Q+}4DͪQ;;:pG;!dZw?÷qD.OD:5ѿSow~+ тlDUy|y"wul_jtFw2D57F hZ9ƨ;z(ƒncBnw!ꜾǨU@QllwwӍP?߹/qYz(&X Μ@ušvf.9o'Ӽ1tA$N 8M apL RqcNrdoi ~f~ 8%w\d;74'7o6~pTpp;8D65A{k8&+J{ 44@H:'C(7<hF˦gs%goeh $_j3?p\ZGܷM 0垵ciJ,IjK)ܣZH) lMN[N!l8uLUt ӑ\@i쮐+ fnsjnۼ~Q R6ұUBj|-_ygl,2#r }&!ӑso$lџCA6Hkb =gHfΫ݌5 GU:|Ԝb 2̷/yO2a"7L:L[ &ҹL%#/DWk#l&xMdDAG"4SotsoE,[Ӧ"-Ah͹ۊN)O* "cR ש\qfί_fUTzS%gy|Q|tRY熌=řVw*lFbɻ!C~Qw`)QD%}e9ܛiR2"!` 0+Aj7E瀆͛e>V5 鼃, q sOIRy.dlpCWҩxAwc[aXaTаrb.> 'Rz"im?ski~ J LiկT$x3lH]FM ƆRC6{- 31 ȨA*u¿Մ['1k#I4[T&cAމьƀAãhWe`Y]̟(+}Iϼ5 Cү oVAy' v_  K;AgàXDXh[}J/`d%\VR<ڱflcȞ]y!'j3etE"m(ſԷu`k5|,PhRU=\J< (J=O$ذ,Si@ .zzIeVcL"laCU]+cݖI,cvSm ï.kX+Vi:bIdUr$HVVI50_v|-I`fT[ }_^sZqk\v D\#duA?QԱۂoFnX7|C0_u.kGO.|iYw* dnf<.$5-a#ȡ(rexR 6Bhge2mseyP25b.aXHB}ŵj₅x Vߑ/Rޏ/Y"]i9Q* kAy>λ޺m4-5Y۠F u^'Mn"Q]4P鎃Zi*1%*c(;C|AyTi:-g}&CXsw폢@0/Y%`Hda* Q81<̩x(qWEҝp.h*iqVzC'ߝ7'gytYmtb 6Av7j:*ygJYi rh`QAiKr0,A"T{]jb0(gT t -u+Z]!Ydxb z'Jp!}>BV;нmy!d"P)ʒ2VC9[ $SFDPcJIg㐝_4jzkwhh"& ,UoA/f(<#3"d:{}̇y/Hh+Y$ܲW}ZfWV#cKBXE܃!IźFm/N1%iM@,?SAq$d)[u臏eYf|0m91-)5&Z^Y`=H[ t 08m V.=;Mh:Ml*nbh^vr{c{Ȯ0yLPŜ,p?T(vCG5W4H4o9J47094tvqRJRD0@E_ 3݉c@/Y)[\s!}rK2.ygeC1t.m}E)3jj[Cʩ"=BCV )_2W@w&jH Hǰ9}(DpV 9 wV0TCRY5s^I#UCziλ!e  1CB" C5`9>5!"h%$fXlTp[WL"1zH2!F1}R 4ԫR=:2Cr[=j9Woawb@v z'FULE%@+;n,x0 XiU;)I)QX_H<Z6 m5)k[k rQ [|rm-V֯BͿ@@ Z5$d+w,&:UHMƧj])59C`sf@1JEĨp}p8@G*!eɷ-AA13P*n$oT!! G.:L[) ,d>x-:kMK^)]v Jro.O\TԊa(PSJG tQ!2dJI!9F\: T=+"F-GkWĂem\G_Šˢ(gʛr&U@18vHbxJc0҇WszN2Kz F4Y +%j.ʾs#% GXT~ +:qn&)U"C55â(kind_!P@BEʇcI`;Y圈\ \Ċf/8K ?홊V VO{23@5'sߋ-Z:5K*d.1 +Ymh\E<$ZtB"[k1nm눸|Pu[ʈf`2VOP؆*"KU7LeeZVG\VnzZ} *),hJ"@KĿ `db5KL\mp* *#k$JHmQJpHx.>c TkXNa9&7j ngݚ DY*U`16 TU47Z9%exp}g6*x̵X~:MQ5 e)&gؙ\s7x 'q.Eu@ u :Ȩo^Zф$K 5Bl &TSl),ki2΅#BQLX!Rp/+!UeDv(-hq̫ϗ˞%!*YF)v: -lcGZM6*/87 $(ڞGBG1Yk \BgL>2\dą-mi!PbEBCe&xδP3IUaSm1x؛#ZʢaPrMA\X KVe0O]tTSb훺 V3 aH߰c::"((Y43|χ!z(>f&7z{Z lF+^HFI Nu}[c1jwwhv6g9ore~qk{J4#P^~ 8Jⶵ7(XZ|@OL]tT` ȷS C_|/kRj΀߆oP-ހ3(p 1T#W84a>K_GiR 8C'GNaM*ܧH\7kZQQT@Io`i1ցT`q`L* t (z$RlOY!6dLH[~yE*GeM*ДÊTx$DhG{XhW@qxPc>NZ4Vt8HF+@hTHma4@jp`b^Ȧs*0`xChw f^0V*0"*W(VtK^Enip@ !yQ#|{(pI*CN@2m坮c]Z{֓fTIDdKϖ4b^iI!~(@Q6P+Yay (TuR@5ݱ&@Y]Hg+y 8RdR*ׯ !KjOYp͡ Pa2|އR`I) @hKkJ% o g]q ySҾN6No)LUI&bemik16:(~TyW2Y#X|Dr}6Zր_Dt"~$@)$"ՅP @ڡzͨ>Jܕ(R(\̇p2x$N^G'v*\hn-q60fL#6=\vޱG3Lg߇}ӎ#st8ܯv\sI~ma W@PfVkn\a!x555K+φ6 v칊q+>jGˏ3>}Ԧ'~cمkKmfGrL#Ϸ!6.y˧GH} lcjm'`A)^Ǹe3y3n.NA(C7IASS5f Dq)9#ۘ f">pf B]hףC/_vagVݜBGi}tb"ڤm҂^"Ke "0"}Hw72ui${ec/TL%"Ǒ HEF-[L4VNO&k4<``rs@M\NQQ"\ھQXE v!Jl8ʪص6ΐq-8%jE,y NfftZE>^[@uH==8~. jYgۣ9MM{0@q3ּĨ#<>G〒qzXiS;z;FvUx qVij .kE'h6޶.F͌&^@Xvڌ 77<@ 6WK'x ΀ËZ$d h65$;iۥ©AcD{z vd:Qڦ5WoE2i} Y)Ze{R  ljLlLf_;JgC0 D%,deH=%\k+ L? ߊ|d\a<+$Y?jMYÕɎ5ht:xDȪJfpH*'M :aվI/ k5']~+mycYxkL] Vj>(Imllk{:[_,|c5T.AN5$m M h觀5ER o@hX^fb F0hIcsg~{Itvh^ B/Ӏ %4 >j =p(,ZKB$Ot=I;OȈ`vCl37#HT9*fl\ NUh;CzBWWRQP֎lT ϋiЄ UdF+~$6,F I|. *!#C~I8Ĝ펴+|~E댜7n*!Ч(K|vzs0J2,DFfTkP/Km 1N5c;TrO 5%.[&.\ƻ5cHIL&f菐'&bZ sX {尾0*ZSw`퓀h:`($W3=w>D*R)٦`;hT \9k}//XfI#cSit/B+N8n &*3Ce3<xOKhvfgMs0B.0֓l V+H!f3V-jg3MorV0ZuhL=Uvj~B x= .ДX&Z)(2~DbH0 =E1d$6Yػd>jVZͪqV}EZ 0zQ!| [ ?! E[%rڂ2.QʞwrGMtFcyf{A$/V@NeBC &T8bFquURAl@Ksb¬XJUV'csBnl\*@Т#]Q]]ee!Ab(/ Ob2ܾ|?9gy; U A,`[l->N}#z 7Tw/=@V٤˳b!]nLWžypoxrԲ P^fg:ZƠD*BAN1 Ng 'TLGM3dHS*kᅎk"ƻչb;$iF !D%U]&cs 9YOb`rWe1HT`h.00fXaMrBShjD SRn NFU-SlEGfqIiDD#Mc%XaRweb_ٟEnx& >uI$mΪm*%p.\M#~|J$L͚%L+j5usX%CZ"4@g7+ec*L'J,$%cP_*}yGˀdR T{4ha1(KԘ'ޠ]=BSuQ0@m{k3 Lnde} >v``pAH2z&@6Bp U͂j@P.TTTlb ɻ)!ƑB;dU4\KLzZ;3dW*@ aNFp H”&P(4( -!}$Z*c\zBrVP8qLVTlR8Uj2Hr z5SGAvhS!&|ҐٳNȚC%Gwa$,=zoUZ"peU!@fKbv,Ne<¦Za`\8̎4*]M4\"IADkkJ4KW ~'xh3ۃMXAyF<"/M(@AcXŽ5f☝G8,,| 44bu!`4V8b E^J +G%pPbQXqJt{$Ahה_756GdsSim8e^:D+Σ: `N_ $l>"Y5xˀ3L&3D;gT&vB#ך7*mCQ#,.@:¢fu#]Gf;`d\&f*77iXpM @]"Ex"QU\48k@u r#jNG lPefؓ`Y0žIE! Pd>BX<b$\Li`x]rȊ%F$39C;RPr3 cٯt2zK{/\6$EYC(dğL>R֪-xS{c q۟^󣬜|/ 8\qZHmE`.rkM]l39CJ$jQC9XYp!ӋS3r+\EH!h&rHu3XiZ5GrL@c{~{1cHWV nXxFj fBMlc.hMϾPx~;Q^ W 8(!3D0F'X|iF:V >Jiʬ~E&!0l $]2,Z8Ӑm_xFGt%X~aJ n3/e&QXL3%A6=g}*4x3f[=UH6VЧIR U9Uk % c[U-{c>L3]e:1IQv'@L%X<h"lCpvRKFx'DžR^BCxsi6+!-? 9tauc-Q聶E^#N$X4B&saQ:(zhfpU3%f7Ha| >f@~W+1.x*@l!ܺV$z- 3:4gq$@nĂ;D2))܆mLjUD%x WgIpvI$CRbQ7PX"*@v}C6ཷ3hqsQAJ,s>ԥpG^>b 2 fLMo=?32wS', ](6+TFESN.RHT/ NG ==x/Bʽ"JOsB^YE TOU k%[2$/lU)L^c{~~XB`z9n>K P͖&Ӛ(cK2`mhJ⨴ 4'Qt}VnRĶ_\ %tHH* s"Ƥ3.2O*[(KXq@a R# ~1_ɆxZړ &1byYbQY=m tmb bA /H\"n!_uz 28E 6v>HjWJ/^YYA/FAiQ|ˮV(*_Lk ]z8*&d(= U$0+aK ZH%ab'&X+|:< h'CaAuaFgl\6!㘪ίiGǡK+rfg)?w C<^ȗ?[@s1r} 污?e;Fi4G* @~Mn> 7yإ#l{>,չ|82 cΣ%q!9F͐l,j Cȑβ'A{y:TVYK׎I^olj48O^ᑞ"Op1mPָ0ڎp\1F}3yfk`ڪڴ{tzNgKg OS~g@aKg`<<f}Z? s^?˾):qZ`na z`[gu4R9Gv|'tHK:C[wfwrD3K xn挭Tt0[k>ʸ{^&tzbdHҎfxM2sF.ǀm<Ҡ0Q3˽Rjs-+myt :[<)q:};Fo4 y jD6D0\"f@" LD *2[͠NI&8F W/X(u~ɖM5vpXi׶yєu62Dn;Ky0Xy$C >fpB8!Ta=PhhEӰ7$JXL;(-ϫNJL0|E&0g]?`hP]{{hNNO1\f_NN-6h?]|88<;>j3B<=xwg_:?:ɲ }t?0}!{x-;k4zW| :GoOߞ}evg-_O?!C[eg$6r~Kxcqf؞ڪE5MVnH?P1-PѤO=LifI[Q׹H$WF6:]UHTtWj- y¹U!f::=/c黦/[_u_~o3H~׳_,^ի7?~YB^b2wgoxto~ _l?mŻ_ll/glllΛN.f~ߟ̖7z_/;\u?-7zM)eVt%Dy6&: \|Fб/ۿ>˛WR* (/K7$ηLJoOo?rdj|_T9r+@QNs=# ?OHJUBujR*"Nՠ K3KT5xQׅ삝v}~*lNǢ=DIlJ犞Uȑ U @; -?Ӡmh1xrzqt ,s/t1sE$7˜V&;̹pVnKNsL&>'ț.UtY63{)L*>׉9kC*wo͆F̺C_߀Ur-3f{de{'Xly5H2LnYCMlg XI#E eZ/RaR5y>:cOyژ6hf7I ʼ|c$mʇ<9e2L:c2}X: bg>7nIE#7+6p N—Nmd`QxϚoHi{xk4TG<ęu'Rmq*+BἊG#"= MAьQ': cuObB`N'.s^Axϑ|-,AM9:BLFDŔ<&I  Xs}JT-xޱc"+AR&, N5z"tOJm t-!X(.z>sfSvKnG,ZDtl@.Dz=g>fPVMKĖX>CcL dQPb=,b?&H @+\L}bف0afx1~{^rW%'߃EFhdX%DDȝVXx}B"ܐ,~$iHѾ=,ixJA8H%XӲZF5Vk Wi]k]G.Ѫ?{#s\ N7jHL"ѳSťڒ'I{w7Mӻ@7\M+qĚnô ךvuiFf\2zs<漏/ڱXTרfkRk5w!eaS: J_!kTLŕmՉhD;fdAl֯#e\NV`"0r.CVcYo5*_!mH!-H-4hڢ=UЏTJ|*[TA?Rn )VM0wf&Qc[RQd6_A^/R-T9`I*);|Yc'eBrm37yZnWϓ^{\`m$Xvv VG,fs] (lǶ) Yƶ~(ɂL[f+l:4Yk?f\N(uͩM)<Л] dz)'i]mI]0 ŭ9jO0#YuF&=^}CE&f~-ҽbsjHg< 4*ă,Y";MtlK@?rJDA-Nq՜"&;t˺ف'5CM|-"k8ؐZ'.yЏ*!}-Gu-۹W^Z!Wø){$ )W OK}!8OvobI'q[ؿ>j,O=,ZDrqVaA$SqoI*؉L]GpZR n͓"Z@rJLWEӜnjE\!F&ꙨnwR3Q/ΐX] t)N@5.#gW:qu(0h%J˼&2M$Z.={^zXt֠(㖐`~uzjw OW['. Sx KiQ T'zݔ,#dOQRZu{W,zRwMqm-'kZf`K,+kmf` @Q h 4d75t}$DC#$uE0Q2SvcxoġS&Q &^7Ҷp< D _^ngjJ荛=xVs w[{~v=ї $<-9'kխu"q&E5+-$ )E&Ң9m>"#|LZ(*C^CғJ_T|6zi,pZe/5!ha(\[ZeQ*\2MźEXJɫͷ_+⎦1 Sյ c_~gYf r.dЦس3T]g{ze:[46.*E"q>Y\'ע$"qv]'H;4%\>)ȝRF:$T'YqGH[CeTT:>ô r(כC%6BӬ MTKoC -9μmKrn"a um 1 _ ! Eg6؇vkcڄ8 NS0PYA~,s.93wj9h(ZN`cqyf%bmJj&)g F%^~<*"1^ARU9B?A*by+۱*+.^%V.+^|Ht1M?0KM|;a2XC\+J'WWl]I7K:˻8WnCnML缤 ~ފD]s"GK6ZѪ#{[\,G6jnoƢ8AW0xT2/L*¸K;TJ=Z;m|ͥxO"`ƒ3MgIHxwRY]<ΜnĠ`PG  o)m CE^\ ?Je;6 2aNM4#;k7p i&7%#Y䖂`@Q:|ħ‚b ٖ09kVj{GoդrʍX?p^/~t40ZnYVlA#=OR[xm;sIJ)$Md[owCQMw׍?׫-zItXRHXi:/-c2#]^|JXƔQLj A^@z6(3Ih "tPAZO$MY `5}ZX( N5'w+IUj7ȩ祰2, 7K]%^dHۍL!)dߒK;%+)Q2s5nrNbB^K^EmAP2CkO8t4/gNQٸCqŰ4|sj%ڜ̕Ű5ԻV%,HʴK2ôWq0mf T ǩ5 yPT7㕴qp=Vo:c X^ u+Wf{bƴtZ ]Rh&U]rI[)ۄ{fxmkV\RW|m/mqgmU:6 [A$m^սFS]䊍YB3Σ|PfӍpLm 1@-8r9E_9#rմ0z7_lRGfF%̳@Vpl N|I|ӛ Dwd\btZ(ӛ^Յ =88Sۥ[SꧩЙ9Edi7 ԓm6U-eu%R+`?O[*Vc#%6hQ&ڭ=77){x )I҄W|R"Eo9ou{bj_pͫe3#vdQ+` \`;H#~^3Tɡ->9]GkF*"֌ #@h#[9pH{Q'9IMI~=?aj?&UvˤѤդ^E t*q\Jg,jd[pAq;f*#܈z*aeb(Fm&1RzrEWIDfMԵ$3'clsUҬlT#O0u(xs9Nn>(g38lUh5*j >+U&i.TތAD0OoJndz9YAEdU)=D}Cw^`SBh7EsUf̯$F=-%^h5"ڵoٓ٥&K-Pu`4\_*?vR8r,yVXf /La$Dqc~(@2P c>bQXQe돗b4ڋ^؆%H%A-xՒUǛj-foJV9 kA&҃2kOτP SPṴ0*ţ*̱W@kDyx~uW. w(ΙͨrvKmOUB R;1>pu'tJ;)+O5|_V$i BQ,ݥ6_}fR?.Ӱ7լkuU֬kPty.&dfmWT`- iYjG*"KיϾ,+\r8_,i%Se4Q?KL8H.÷Ї Eԛ# lk_|\+zßzxMU70w WxOe}%=Y_M;l9r4b3oL(i_ )C#Y}BW yW3k)B?ήc5-|?oeӪke4t5ŵcE;۟E_] gogɮ,NNOېʻwo.ʫ; \mߚ>]wuО^Swu ,4ˣiė{͸J$CڽЩ.O5MMvm4ӋǻɏLL~8uk/o4IzsxI|,*5kɭĆH#CãYQeW$=7+=@xTHlȎY?z=/ko ;[e3`5p̕=597ػw|i/oƫq'h_4juf?E˚";s7BPd@;p KVl,.I7;{`_eN^GOf&aϱ7cW>"C"en"f?˚$ 0WZ}|W FaE. )kG!MڳVd"6\6'hʦ=L3fv8Ĉ̀ 0*&CX۔U(SڎƣٕBL)q}cofM ylj?mϿ[@2ict_ 4Ťzm#gR)od h?eIqvo|LS)ۡG?>R!'/&T%K8ƸM8G& p coq+qO˚-‘1kB aceoB$4xU$cv c#E;fdLS9ۡMgvރlte 'RO2Rs[T45Mi]IW L(1&L J&7&Cɏ/<Qv시|X4%].s7}tSFl/spGyjvɔ4ہ(yzq՘^coqJʇ{KOOޞli߾[xҋOώv[K])TVOK%|+/epSy8;9=x?; wo?],stA,·+˹iC'ߝ}}p˾Уm=o~CVpwˮ/~lNHkv_KeNx:%\~LJEpztrq_}{ó;}uu4>vGR?nG~Ļ$Lɺw'\;p/ݵܰ>nu0ஹٽ ޵6Rͧ>  n^'K}f%s~`ڸK6KVLgw/rL^ѝ:C˹nO}KZyWm]5;rv˾O).6Y\c 7) vgy:ߓn`7E;< /釗:!mq?J d(6eb8=><W!3bw_5YW]Du?mvsمڒ4Qrx3g62㶾t_Xيb>U4t9`qݠ}QEapP25t^1IgEwd3"%碙O[1Bt~7<ǣo \g,z̓k{](#/ 9AYD7]|0jnnwG?Wχ對ƅvۨóp'?p+7Ulx5o)>vIlqہ,V~VۿKM0v>{TGC˲ĸ_:+;A!,'>Es䪷&}xJ񶪕ɝ?Un90 8G2_t?i!_'|'稗{V~]/A>=6_,8^7vh>j]37tvן}&j{rK}N5Om򤅫mKx=a']w˓vI;=^{!vÓ6Gͨ"yTfTQ# d5)~*ثvjee9V|^Lej] S"L H&|э=LLLi;_*K3"hbe/bo%_R FQ}h;3]ELJg;@I*Fyu1]G'sW]v^r֡,SRzчP e&s?_Xjz -0){#;pmKh>ۛ۟׹ vݞB] b]cO݃=EaX= Ke½#μr1qf>s/ǀCΏ=>4%>cu/#wCwRː4EZ_ۙ?_W}wzrǣ쓽;:>/m7.+FtvoÑ|tí%WU^VrWO.RGόnl.9ݟ z 3uok5[nn<RdZOVLpJ/RȄفyY.鋘dɗV5=JD|twX-Re}Hi?1L qvNUs|7%|YaIaۙRC&wmRdr6GĒdrV${>k3 Rl}u- .)wuyB><7VO;Km,".c^e<5'Cr/bo&k}>u2o;%9'H*n\ydE8&J@#Ӷe4O=nT"mgV{sKbgrn'H{.Ǘ= ߜ:2ƳEZ+n&uoWz~m $=΅ S&mp3`V$_^&l`yN?{dv~ Vv&?&iBp|.Xꂕ\ߦ?xYMcrv%A&lH=1 fٹ6_r8\8+Sٞ:gѲaS=s'i.V=/kMW8S)ʎ } o(eL> 2q}ٕ8uM 5=sTPw$NO]S^ݕ_%xSK5Uxb;p55>k^K N%ȗڈ9^bre_Č&K&mc!>e+LܛiCܭkVDIF!gesѶ,e8evKׅ g?VӝQ Dv6G9hȏ $|_'m=Rh;_5|SMP^^"pP.כviE6GMFZ@ܵTSIKfRҎ+'SUy:S/J\P}SEahGٷ{T+ϴ¼*=jG<]0wSML{A6]o&Ŵ&n'#lJosM\d˶K/?<9<;:X%< *TÓߥN>u:=pó,TPM;9@T]^!e4I͞Wl]  X]}>jR ^4nE~.S(dncw}'mg s?~27ܢg]&㿀Ю˼ ޵6Z4}x`TK]npվo,q ⒵ҲIݐv˚Z/{K|nw^~ݢgoEJYhd*}s/SW.cpmj`nmZzW2ўK1[tN"c0E?c ;H- W !ʾ) Yv3:4 2818.CNi ,nOţ2_"IO3gU{]Z;ٛ?_uy%)."KtV껡#M!D˷O8\rYX.#p,q+K_7!R(>W}ˉپI|*v E^o"f&I2o~$aH*qirҫ$wN7t/ix'mv5"WH-oEraOVLw*A^gLȔADɔEed5f!rz~dڷe&U]NUr-xj ǶRdv*AXeہ\@L.Frly]l]YڎVd1 PN29jO=` xe4O=@h="VVɴ;5GJCN-$;_4q=䘐;qcjRyc|f,I,.V*—\qkkGDjuNF[ /Zߛ,qպ%nk6YO^ʐ)3&ўH)9sYܶȳM05^8NvY%5U٥$5%Mi4>&Hyō\o\$`xovFMzhn<ޛݺ2p1% n۠ɪrkY-* Q ƕmٰŗ3e\Kyv83HHyǮaw \ĘGz@*~sFN)nZ!PIh=G)Ӛj[@6 *E, 5ܨUA@yǮUY3a fW볪^gprgov_i}||9==Yeܗo^vCpߊZGO[R+O/ߊ˾p׷ւ@L4,EV{~ <˯= |-|53$GNqL癘#ź%PYnLOaa)˟s/oO̿f ]e?̑c`} mG8BPU%cCjͫ}9A5[T _$Izqg>oeBğB`Uudy&>ox޺(Q+=oQ=9+h14S#gy19S6nm1ioTz7Apk63ٝQ$Q 59rAKc^GBXwگKd9(S`| AwUg 3u7 $Ozp qZcjWShc}O{-Nd!+ @ċ[Fb2^S3LͰ̋fbfo*F\p bLKrɶsfǼQ}Oi} Dc^LdzstBt%,\JHa] Qu@ Rֆ=][ *G ,3! ɕvG ړN%F I`6b8Xgwpmjr΄:>>I-o!ύ.^"\AUQ|fF"Ȳ&=qHE EonRH, mUs&"5v,Pʱ[D+zdHnydSRUlFI݊ةew#f"|bg~޺l#JLscyZd9m6&q4j#z_:-G§95`r^Zv'XT %A,Pjn uAI of[zc1,*9&u9]'[> h< X'\e˪@gSMj5G\6,t3K)Uc bT!0bY{8}q [nl" s6i+l7w]Ö=w+B/V-Z6GX!tp|p]`.aIi/!_jd9hq\5ǽ9)e*}NV4P@: Jd%G3Flr̲m)*A#FLlh<wMN*iKǹQ5v<^:Zk>8aA>р#Y #$go| 7l3@9ހM0B[ %d`2ɜt5QBFti #hhsp@#WH\kz ɋ@:z&hBhloy,P.Ԣ35A:gks1q`Ir;],<7$khn; x'1J4zф#zs4-@${p#kB7(_~ ɵPYC ߫+DBNYz"4>c[ܓKr=qݓ.#nM4Ʌ<#.3@}W:5}+I%JK A ~=q@vfH [?אYTaL;sR8m x!Y9II&9e:`!r%kHq (,Bbc2YGۡi`'T;A. 4-E! v>ye6$W(Xb4GZ`CPb%VQbdE'l0RdQ0R!H, K@' H3ح4 1*2k8suG#-0g,8ZEnQ;*H~>u5dQdݭ[sb>W)6jTbDYQ=>J3ҒC ."l}%6hjlf$9Ȱ((s[7hK)  | c:lԦ)İ鱢{T@#-i0 bб9!v+~PK8DO KuFortuneteller.inoMo@9B*R[S5mQk3x-Chlgv -%iU3̬'@f,7,ʋ%sX#2G6>@n,J˂jj[Rd>%9w @۶216n_OifHWU:<0S_ŅUejHZeJ Cj$+-v"רbV 7BTaɂ%!tN(-ޞ#h? gI1(h1\.ox\)nJWZo@|u$5콣9x(NZE*74TZ&A(O41vshvU-F5+FYڡ5]Y L)'V/%ŧA2j&#:;n+';kZ݀WuMf=cY.Y>x4ɑP8ϞV=>zU- IzOgOdTҟBkrNU2j9vG+xPK8D2" f) Fortuneteller.fzPK8DO Ku9fFortuneteller.inoPK}~hfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/H-Bridge.fzz000066400000000000000000000676471250202676700322610ustar00rootroot00000000000000PKl5D/o} H-Bridge.fzksȕ6}&bo OawnӞqҞ/*UhUVRUo9 7'LI"qyo?o/nǯ_&MEm|տ_<\?}?o\޽{+H#9W^o~}LJͣ<޿}u||F?+}⧻~ek1ׯ\'՗O/}ܵMoyxտ.޹!ee>xq{WO~_s/LJ?9>bO7n]ۿ|?O3?7_o7*}w[new7?~>=X;fzns_]WW^ :Tvk26o9 [ӵߟƹWn~|~tڽx﷯ov;n7W7۫o_Yr˧W cWWVuXm ie__sX^W na 'ԉQ٫:!ʄ1_]⤗hƹ,sh?3*s݆O[_\xvm«̡Яw[v u*;`Í)=Ayq{㐲a.Wpl}_x 0:kk}:3λ7wWS*nu?bHy˛'o.Y(_!{*!o2[kEB7/BJq]nBCQKӮZCԿXԞ$NEe $odtrI- qCVMW%A*,Y!dYG\lqAa2! HLР-Òml,.ӐQ$"!vȦ#t"eX$ 6h6}vFǞ"a9"Q$,{B$B ״~+y"OIrs1&됏#p m*>iѹ$)[1%q͵*-!s:0d\r E!1 q%a$UE"1vg)였ʎ r.~0zĴ 1pΤCr.:&ΚlH~QK!yAIa3I2683I1$ _H^g\1pB:hS~&I=41USQ%~ L'$KC>iIa gDHD$0A

|^ȎsfƐguKcZ6\21p\uȇ(BEgLH %g_jSDV|uŽWWWw?lKju|__o|_qftMq{z{!QPo~4gUB+|^+6B~ydƜ4j)|"b헯_IHl_맋7Nown W>Pݽpxt}s&;Wom;) r),pW:1ܤ"Cn>qLi*=hUܾ eDך?ԻwO M=KZ"Ҍj i5X+92` #jk+y#mc`^+q<+=x+5c;x<ဵ%x\$APƏ|@y) GV!P)oR:Mʓ JԘ1 F7Er34Tq(1¡'TeH&x0qARw8ry62 l~Fp&nD8BS"\{B4sc8w*5QW)f"ŬMeVe*/,֦cBϩJEzYڏ^vLbb=z߽}d.}|Wn~|~twϿ}|w{ϯo__>/^|zI)t;+C2y, =4ZH ad¤LE2u(;eo *k`Jj\d%+Ie?qk (m!aR_n۩W?m\p8&@JM9RVJ,%MvK/.; g;Z֮ j~9 &[2N|2=r6|)RM*+تdJ.8XؔcM _Q2TaԊE8OQhh)SeCƾ޲rS-(H v`)HW45 f j+HRH~Ǿn'>txeِxb` e"SFu_|u<.=ݽw??~޾«f no_JkM3%Yk"Df}P])%o>9Q?nUVZu=AAJO)t!R?Z4ą< )L 1&t(-aR&:upI?o Q"0D,kQ%=84wLIA~ wА؎SZP'y,N@pxR>`B>q$@6J-OOwȟ]M\'Uf:Dԟ)3,3P_C'v=EPDUk2L 6Y%Vj߀v#Jˤ)um]v8L}_},zhgIJiHPJE$t+hqTv tYfd^A&>Ueѳ#0!7$"fw<9,j7'w.o#4(N2vImΊs6!LX=wq叛U: fippE&Lؤ@G< .|O/meGPR7"f &aYȓ0n9J_怡mhFfo0ekոt4|4st}H3;G-Sy6z>f~̈ c2/7dަ 4x߆ )f{>*jb w щC_vuP F&"屎_d&ta4A<`P(XIȪ(k3VrF< >NqѐTdv=W@MAџe˲LaBzUB!d$iZ?R{kWcJ"C;ȒT2eۚ%̦Fl7gȺs y?HkeQkq]\A0GWy cbyIΙM =M,s"G5aXcf~3š@{)Y"@HsXh[772=S)nMY~D?2w4DB&a'9Cx:*lbD0 3CVj$"Rۭ3Uf[{VY#6$S}@-FzVkROU$OUj+&I:KGbWИD] ^|1r-ΚM{ygC3%M-1`2=KAٱ2Ӝ7o 42á(r 6fpCOR"Jg|6l3PX4˶&B6xoHRik}Q6:l>ގ$kqUGҗn#C!w<}dý_xm^A"}wj[5oUb@{t8;#Id-SyбzGءXvvGH;;&dA髥/H;6zAA۵Xn߾(SMA60̯D/G9`a CI*'F<7FޘSI!YϷUgsnBӓ|js5=+~ &@OH>=ZIO5Oag*jsBuFkTʑϝҤ v@|D; @{W|҅$ EC\J="2T"u|D9di:UC4vlp)yܱ߻|floo^xpR?aǗjY߁ѥcHt^76IZOx"T ,ZN3R+=L]^H=ޡ/m {0v+TDZe{lkP]]ٜW΃z5 ;&% ˓r_YcrCmX d\懬/:K-eYFYڷ%Mg1Sk`-i3(Ҿ}^'IL:'ÑoRKxRy&HDIKi;\fUCXoßBoßBo|q]yQ,͗)8*Wg-ܛbkOGOV|/77 Y &Q"˽4,12D *vo*2`J`d'x Ow Mf iʾ tAa_7Ft _*xrб~'ءiW1dsT#A MloI[37cҬ!F:u>Q0e ˪uI2,1ONZY[A"UD,R/鳈L'‚*V;;2#jz :‘t ԈXꡧu ^(~$5BC$dnH!H"!b LbC#,2vC O2\)KltHcFtLe-E,֦_ =Qш̫kh?hDXdc]c9ud]i|;NTDoky:ՠĸƗNJkD۝=JX$]G.+{M1|m4WlXkWZʲkB5ȻNr}ōp$= Ɠ dLiz)WЉ.ExA%W=yone(0.Y6L2m׀0lBs{umk]Ĝ]ʦi&(.F{ZD%7fZN3c3Gd_HQuTNBs>r  +s{D659c2kF٘ KXdV˗3ԪJqP<AXЖYgMneVYG#⚑DlGFSqeVQF{&j*Y U|74- \Fb6Na GCX;(q'!u 6bF:B1`DcAb.&gCͫE%66Zolsĵfy/yn\;{f ث0 Hs aS5P킋O\qq&( G!9;RՏHºNU$!I{xX-!Q( [A*ٳY"4lLfZYz{&keg}fDpXM|ўٓzM2_&wP#DN @VV0V4'Wz~g!g /aZ. @#-Gr.e]Q*Owt2M丝Cg}f3d c73NiJDstjM$CCq|V/g~d oҡ'*u Vt# KeQJ.h4c#rV+i#K<,e[u*Z̠<3`G"iPwqZAMJb;/-@T(GZX&zX^ >3uDY-[RrE[5'Jlld[Y5n]Y `\#e[b-]YPR$*xDgƖHWl(aX1aD5t4"$i7`r-Lhq&ZJ }ze HW\QkNvMfݚ&bG70CwN L]]Z痖f2@/‘`_X5UĺCG11ukL%\ FUM޽ֿ]AS -F+MxuJ۲<˸X{yqsd\ܡ@MibMwIXCy8hy֟"j:E5‘`E1V](zYVH҄}ӢK2-0"Q_[{ބKQAruNڟYP:Ώr5!C%Æd9+1 #j:qp$=q G)zWԋ(n$ԋv,IN$Jja5Xy.GWЩ5l@ C1."`xz!KVkt]ȿN_t#Ix jQ5HNbO6B1/"б zaEBXUZ$V F X=6U7B'LU(WfJ+2꼋*b$i]4aX;p'uu ̺FPև& K2c - ƥD*:64Sqp^.ўJ)dN+ku}]7(.vC6S$M ]ڄCVN:+[Ԯ/-l{RBD&kguz*T\Dq"piƊ%i\FY54%&5+|dR]C-4[Ç$`ik4:" Hzp X=dp'*zu Zo8U8ts{$Bba&v;?&Df٫z ͹[?,bnb GLjz< \&kzX~[Y%Z)\LѰ#Zm_gbI]!FN25`NKRXL8z48ݒ;*j#/"::JȳN{Qŋ}ߋf,ȵ4[k \K0di Y„+N*a$SbG5t/6ݴF缮xD:(㈤MTZC"+UG0dz8UHƺΐEX`“jƲfV9^5= Hz0-kӲ*DZ5tz"Q IGP3*($5[ᲤpYceq SaGN5e@_,[!8b2SHEyh/4;G8B@ll֡'ju t XF9d`fFˊD>T=vU9Wj֯d")r0 +pZ//&@rs@,Af>04::S*#a4zszIX*=%X0#ѩY0S 6ႋ"ts&,+go^)Yжm323we[\왙 w vma} 42QúBxZb"XMED]$r:&j"Yla~Fщwhܽ4FpdO5(WfhG5tlZQ3K+D4-&G"M;Y_;ڦl23:Y?RS=gDa$IL AVgf=Q ܬktQIڶS娙 1jԌkHVUtvdEd-#ĚHvrNvAlOx..Xܓ|+T+ ox&E5:)үCL8be5EH.@FHw;R%ٖ^mI lטi=ֺ$F ,P\2ȂrܱSW]/hWwUOThcS{;8u6\1[a;@G8t($ibJDJ5td4#(iHIr3E)PZZQ=EFg`H>"OL >mE{ZKxlE%H:2$HzpYx艊Gd^]C'2/p /ph)/cD,^k]4`547 FH22eӎ*"#yh=#k3V('>YǢ_Z'FB‘0*F>Vbӵ=Q kVcD!$$ig`dIzg=Q 3qRurhADZv0[Њ+RҔ#%ztb_Z?N:W $ccmhCO9" ڋ~r,ɿ.oSKD)ĦYޥUzK}c1Xk,wŐ} [/i++Jae:A_ZAFH‘pNFDNul!u H>B1,H[Y LVͤi33Ԭ>uiIP3"OIͤ։)>ʥr"7k:9x&#܌8A Ր̺HB2* = 64ZAX1d^S=Q k<3aY-5ڐ3BYM<ERW!  Y.]qHfqV xxZRfte&4$4gYЩ3Hyڴl' u ,#!I{z,ɼvQNFeP텄J?UTdVbeU:NfeVЌIYDG` l|*yz)C!``1QG-.b^}q4dG`]C's0s02$[/їLbuHNV`,{bQ|QV=< "W`Z]aMU+0$b˦E"/}3,58LqnR-o>-?>}{WW?SL] ؕ_,\xS+>fVJm}yK_߹O|O7@7/,>_+_~{V{w[޾S~t;g">~}"T~} +?ß]ON>[W:7M Mwm5ڂrdN/psOfS_3~?nڃWWP P&ąVfJ؆a=˄2kl+m/ǧ_'Wۏ7o>Wo7W`o뛿ϟwWo۷_?^$xkpo?ݿ`b\h*jm,гO?4p ~drtvh~mW-+ կwtP~ys}LJwܺhz=5G8F;ZR6aF^=~e %8%K̽vOX-utщ71r?~㿣+m3:0 u/%3m{鶢7lKq ܂pfi% \?v_~q8_1~,wt70?UnX s ,U7r{iw2-пaˈ*J;4t_٭I907*~P(v2ҳN^~~Ew7TN2e< wOmRo&7]DX Sk~OKaݸR eeEr[aݥt*`1 O5ssIm| Ǫ7>ƯkutoaO//h/˛ *A{_tepY[v#2(UWŜD+e@1e)j/4.`/`YZ~ͳ[𺾄~ K'ٗh`-ʿ &K3m#c0 WOv7i_69Z;)d~W\K4eEޓގ!rsGY/fE-D%K,ԿK}_'+hlaC4MgYVڷ˯na>7yǺiC *?x Q!n  km8ŽpGr_@ՕAHExcFH2@߃~pr%<7ipszS8Rʪl3ZUA%.;qOt\sITjWAKd-!:I^H %@oeqLyqxc"+)s⠟_ |A#6`\ 'mf^n/ggqQv9gd@!m>z4qPhtI{rm8 QPp@r@Q: x,asZ B߅e&D&Nؒ~VK/|=89 m }z)`mR3fs2>Lk3|<8b x\fpyoM&9xOMJ]vY3e%3p^rǼH7_=ʶ at-`ƋW 젲fi45kWq5ރr~S<-?&Xxp)l+nG2 Q}XP6_`GqX)œ=6.lפBqeTl6^R/!0C p ,Oݳ  ZLP_5w-p:skxBCR$`70 ɴxmuN#N@ (/.gr^ Qx㩠[y t!nA&{1s\PK󀟁keD:wOo@|bpI\{\DHu)@8LM~mS/+\ l 0k%G . j$UWq L pQ3@T~v3=Jt0=u%XՁvݩhi ǟ咽wy* lV/tT ͥ[ë{x 0&6-~͒05|i]<* 9Et1\  8(Wj-V3c4;uVnɦA' vYMoNKHL BI S};yġ7q! T#nP_!+4hr4TMqoFϛ놣ֆV|!pz0l_8T(&W̘IpH x 2K hW@):X hUo2{×.`M-H΀ #2a8lg\-仕c}eMC#B|ACv|:U;C;Cte*n[.;S 1l5D+,U[o`Ha&Px/'jLBl429j)N,#/r\2] fGT †?S d5ULx _zPaԈ)p,1 C$D(‚Y"2|X3ڰ&}ΰ8yf$,wS2zL Es^,͉%bflW& O%hܙ)#}/(>^-nz̼]C #6zvN@MӢ@ :A@i@^L,֜/ MNUhxׅȀr</wN5 *\>*vQ5_rgSA@bq>;vR0 E e 0S _x A0y:*`[j;"Q ;ND>^Fqe3DCrsU[Q}KU%ɲL!"^Bv@w{ eCE}yuW *uGXXKg)fvEM(2G&n3.8Q)׎qm8JeiM6 O7@Ɂ*jxƧ<ZJ;a W0U:DHvL\Cѽ-^F'ITR|]hZJ+,d<\r@D?F_.n=t'C=,:\YP950x|3 |' ̡Eu\D$ІI-BGue[(|3Ň eA/`EwC 7Snc);MOzDM;A p.C{AoDyN<޽x}JE29΢B$w o(F5?Yo>ՐtwxG T1j(AǠ{k[ coYW4SƝzlY< 8|JD!ԩTPf=w^__s{ڕg}{Rv׶ Dב{|uT㇋K3&!7$Ro Ag*D>HY|jwKg29^B&۬ Ƥw^]fp#ú[ _VRw eݲZlyeU1,gݾ^!*Vb e(=e%V>uۘʱEޚʚ&~^kC.+i eRZV^ vYXi~f+?7 P$c&E3d'wŏ[;W^w?'C)9c [ʬI]R>n1sDҌzhAHy1@H ۑzjO- SFLK(ztbW- ]Bgjl{ :B8G]|&\ߤb-=wE_Sjb:۵4EZZ#.YKwa}ki0D{=揭ťc+z؊ZKT/*ـZHDQ(z(@ܡ4E-Q"q%f keix޵4wDZ/Z:Ճ bɌN%dF/'|]㯯OoOy/$#䆶Fy!'wO>Ă-\՟1g XKo eˤSϏOo`y۷W>?D_mO7wBZ 4 z$%n:o >{9 #I]ꁏ[qcKYY>P$ϭD# I X 6FlS 77\qw>1HzFP .r,ɾ_Ʋ/+PCf) SfEUٗ=\ &$#2JҦƂr$rTfff@5‘rʠsd@m)K>8ق7u =&(IGTǂL D. &VJajl^AFPu FC LGd% 4+N$`C';hG8L¨aa=tizG`]CgpD}LY{+M$ fYqUvYmJTlU*RΡө$bkcPb$\XЩT(p#0"?lKSw/2g@.S=!SjagȐ9!BɿϟerZ" laeP- 6{Xmx LktV:`^mŶj@Dm H"""HDJ"`Zq"v#K=no"Mh IG:*$ ӺsZτTjUk!`ueb"; %k [ȡEl]^޳=3:R ) @L1zG&#ڋy1uYXeeY!ҝ 2byir S[C.ʆ$>p4X33zUe;Y)9l|6i,5t8 4Bt7J 2 +"u^wl5SNT&t5A`K+}/Tvk./i-.vk2dŸ#:hUG~\j HLT`d-Q92!]zL)_)*TnQA%y½ R2 6"ÆM2[*G7[ް |E-# /EYdu5"B%5 5wl_Cg_+兖g}fH"%lOMaG6e}$_C'/#0h-#򭮡3-` A$ rt3"-ZˣqĹIkiWKӌIG.Cv`^b>WЩ̋(t#̋ l"BA[߄~lxbH}"K10#ҵz{=Ys?>96Ρ31]Fvk8DgIFѡ̑u Lh"H8>fVE'o/髆͝WnDc D&h$l!R%I]1&ju$'9*-ƧF9t:Jk.G%z@VMip$=SWhKWOXRVMbYQd IGը`ƒ.[ҥ˪ rAVn$\,ѥ#2i$=ɿ\+ ΑMBd}FaGʃiXaò`yn Y~̠)1*ȱ  WOtN` ĽF":smmYTz6ȦiK`u UHU/Rv([v#:&d$JzGJ W`TC(ۘ O6E9-ztpuMf@F"mWO 4+M]C#:Z22SjD7BMSv-65A̺DpcIpT!y)WҸށ!|Tt*T/*N41$ix)[) 4y$zC:؈bG8 86x 6Lt.W>6s02ȱ[\YE +|]՟lVOs fƐ}h^\<ȦԫcdE6‘`E2N@j!T#fm獤k &^$#HXtSǬATV5?m3uD R{huq$+v> \L*0cDpb}?W (jDk̴f*Vuh/lPp'|f$PC*$R ѪkUZ1ijFG9tKWZqMkH""" Hz8"'wiucFU:ݕE/B1,f,ɲ.#1,K3UNEji]#]9ҬΡ3KXYsѬNj4HȦ#:9n&`#D XNh3~$:@[5RX̓$ H-ǂDjtLNW]CgW4#$i; )ƒJ/̬TO>\IV4&+quDnU:)IuX E^5*0VE6U%"E8B<HJ'XddʬsDIژc6tJU \m x,I1K9,Kp(i͞G6W:Sֶ,"Z\Щ2H.ʎFf_H:Nl%W&bѶH:N'WfkH>]fV |N#\ VЩ(Z#,*HqrzbrVCs+h^QA% \`e%X + HPPd&t޴2jl`2-2N32;$iخ#Ŷ<&|,̲3L$7/MT,:$IrA@ ICiVd$Mc U#k:Őp$=B|24#ұ3 D=B%9@DŽ mLTnFR6bdeC:4#Z($igei)YdHnfwkܬq4_Y$ GCYM=QcTY I)Yم sAq{}x#C;̚ -OuD;{6Qu摠Qp$=yFD&hqCOD"?:Qŏ} ,.{% ~vhR%;K)?.X•J}AFG~9t~FbH>:{~ք(,VB + "1k:Dp$=QA{ΎRAD$33 fT0dIbf&f1:K2GTvH +aeLJbUn^-s3"If&O7;P>SQ GX͠zH$hC4!hD`dA AtF|kXr59({^*覰uU˳~̣JY,֗D-޳w33B:?jHgCgg4$$igPdIzg=ۅsVnPGsYEz6HIdLAIZחV&it$IwAIdH:N/HAB1>4"($IK&i) ƳD\bgTTi0`2o(gU\,R(ZWMq1R3Zz ͦ9_Lφ&B~<4]G-.l&↞{DF1tzF322#6K22K˨%,3Yn,1LPTdCS2AmH>I"ulץdE7VswdPDn9YЩ(v# n] d'ju NʈHH>Q%I\e$HZJ6bC(בuJ;v FXU^F9tC!I{(M4qe5EGdb_Zp$= QG!D^1t*$,$[Y M%q>"-:Ő=#椽R_Zl2`qXoKk2G}DR1t*)# !I{,IʖFQ e-UTɻ qGJ9tzZQEy/q"u)D7YGiH'dt#I&dTPceB66D#ұcGH>QZdT˻3:p6b$BIaH>"dQ1O `)՝bTA#IU80ԍȾ:NvQ}D"X}-~Lr 09c Z'J *nB=4sEBt%# RMRև)PK1 NHJ‘t #kMFDm$C"HH>GFEdi #K&^ܻ>]yd}9Dv05{06`^CҜWBW6D ,:̺Ì,r#AtPcaCO="%:=Q Iڃ)Y[II)0QEE0Ie+.ngbR6:)Ρk.buJw=AdAq"=O@-A=hC'v# )H( cLm:l*IjCa$ !I Ŵ C 9ٿPKl5D/o} H-Bridge.fzPK9Xofritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/MagicBoard.fzz000066400000000000000000000434041250202676700326510ustar00rootroot00000000000000PKR8DE4Fϼ MagicBoard.fz}ےF?pslG;f$2jZnI6mju̾Ȳ6%qa?`i#7@u6Hw~e4}|xuA3r1=Lo>ۏ/_?^?>~{_A2w}^^nÇ w<|*]~uqnt8yb||7{u{eWz_fWSH/Foo^]bt3pBf\qJWy.k=v=N뾼ǻǧW]><^ }o?t]~x?;1&xrEӛwfU[&rG۟u6ɽ/wGww3wg~N?0U𺼹렗M wUT5eȿ,{13iuM̵ה;"g*sO}p=up͏Wï ||p_\=\ê򻫻?ʘES.uqZ8oQaYSկ(.nax?{~uId#' bψr8yM;mY/SYןu}^<k7~8{>c!A|}jNȵô(-zbsƨv7Dh#³1ig#ƨ'QܧFp(al>xl\F ccaȺPl>@l\@rQu{^ 1؎u{c6W~->jml?5p\6Ny[Efifc3PN8:vMgGhcSƩWmv㴵`2M^ֹJ=K=(J=ӥRϓ \z-ڌ4Ei?{=h/D\Ϗo-EvXհdIcLհdqE %A {IE݋a#7F9a72>a6F>adٮ>w6 ۶E^OغN'l $'lF'lƩ'lS )s5|?=MgˏWOsL.^-{qmLvMvi.Y 2NafZaIu?]}{O/Gwd2]8 ]?^Mo]9Y_>ӟwng)5HQ3 sMbd}((3.2SҬ~hrmᄎ, Ctq?@rX@:,& -w?>~bzs XQbuFv@CV ƜOFM8D)Hh’>!&:X$錉$&C>1陏 Buh1SFIFIf5gV>lET4159`_(lȎ (6"3Y&@P#Hgt!z&#pO͏=yWBP1BETfB"L1o,Tս9FcjORkAhh^O"ShXQRz G6tdXQ3j{DD KÅ~! _"Jԁ2j،5ݮ\h0v"?bXJv)n3Fd$dUOz>[H3>Xr–zSN7% ~En'uXT'qAX(AN}o۵pKϴnB̸ ZIRս9B-S]_Tr4) D&T_=BEg#QS'$rEg'ѕ(WJ\DWEt#eeݣo*{:K5l`nhɅtT̫`@L_l<ۇQG͞bڍZWvu{ے'Tf{vEM1hSŀGz;0]+ih3>7:?>=:3սfOO_z a(!?o)h# !>|-zAP=Cb9F/XS.wibQ&6KELXƈoC~ o4(fo_>OfwPW2 yd`>v8de\; 5N׋qM|-Qseѷ2Y\a2c"Lv=iѷR:}(">E 03~ a19c\˥}c S$4E`$3t-ht:6~oUƂ{b2zE5VxD 9O#=r?v'o{SfuUAuk*0izzZҐ!X؆ich.Bpv@jK'EbRVF]ץXW}BKXuXL(ekvNDE,-aM'uYm%-~ A%bH?:u3K{@W1 grܳ-33ne(KIF[щ$-Ϧ&m?7&}Pn[+G[ K4A ?}24t Gb @%BH{$|~xz=M>>>h4aojheNWXHGgۧzT(cd߽R˄ [&2e_aH ۫h)D4Um/w3Yq->ԩ)iONJPLĆN$tݮ,2VEDmtfifĚ9~+*Fw_ү󩖓rPeEJQZ*]Y~I؀ep݂G֚v^ i-MWsMaarGQ,MΘB`yYt>rbJmO+NxFQLM1:(&u趌%ɁŒ-3)` YKYUuV+;+D ~zI P*uh+hpw`2HY$q}`$Ie2W2*$2C`hgHZ[+oU(R} `8@ u<,@K]6c&줒]u.#>J$awSXN` wM5~vgLܻt8yz@, l'ǟ@Zy\a*y/8T (iz2,iÐ%eMb) =S4\22,/zoTf`eiCZ8~څŒ=`uc:V8,QD˚h G3#`u &qVN<ɤ=0Z)C~8Zaq\>!&ؽ'9̆H6\C%/[2&uU hW֟MZ0ZPrv٩xwy;ψh4h3פ7o} [ρhZGD#)x#=Q#'A]C3AMB"^#y"T f+(ZϰFjⷙ Dݺ!$ڶ,iܹqi[$3_@)$Yҹ]̱e0[;Oд-l&ȀJ -E^_ 65 ##i@Rcm#0ieg<K$,%JvʚKOuzӎJҎg6˷ PIIu@rRH#:c~$fpY eur͊ə~H(39XDe(K2rǕ*1vFmbhͽi)@6IAqӧEILPg8:xJc6s a#C˄mH+*%錰g$$!$ֶڎRQR fP )&3j3|!(cTQ8D'GߌwA`,NBF>]3c"ͱV%B QM1l$Z4zo:*YSyylqK@9'BxSu'ɵbo&E^#V}rԱIoGs#ylϣ6\sfFD""Nq6X]byG;7+vd[4 }J!ee<yC"UFy+wN[E8nS|seoZ:պTY7jπ/ tOuN&'X`؆8OtVy(e^qKژ#89%o=(u!)!8ܲ#I!auAbXDgfLh/!Ju&gMz1KgDRЭޛ$ee<q=7Z 5V*RBTdUorm)qVm[0dWeJ.p @1KRU!}TΨTg$$VMh8۲htϜL2M09΀扵54aG/֦vR"qKmչaHm]yӶD:DiOq[陸%ddV@j8$T[c Smg&QzHţ; F{B:ޅ!֫=[@[7I)Y: kyknf>E.7y jA*C*MݐTKڶhɽCYb+zsWuct/L"2.CRR9[/ؐ d^ K1^(mH;}ZvY;-܀Z{2r%[Sùe=s_He΢yb$~RS,MŎԃ goH丂 1Eɞ413O{5OeM}DIˢ9=39LF4pRYeJ\ߛ#HSf=1んCk[0IK 9_VHbiGbi޴ j{/+I+ܹ{<{4O=\^]s/F/Ww܇?_7K^Mq%ՙ%Fq'Zٍn?<׳R%l󛫏{ˇ/wW>=>///?}ӇKLKw>I$J>Gصgb8g/#2:8y>}O372k†oW@_K߇'Nnܜ_^_E—N_ݬ1 }t6{zɯ??=<YJJ(K߳.?iUjD4 Y$8P)%s,]?tWw)_VΈ*`su1iBUvah0F6| *-p\C f\TƉeZcj4#_fۇ~b]Mq7~#No=bryw#?/!ۧ7;ҟ.zcX_~n6U14_>>>=rQ_GrN$?]?FIVJ/Џ$# 8XL8Pk@7%=̿tW>ƿ%u spp,SA9fwWӟ?<=~zr?jh} ;4INs_4|_z0Q|̴{t؎tL&äL뎭;vo όdw2ROdԽ;'/F!ܑ4k'hwȉr_sOQLHH?k8)kb Qp5gw9x|3q8a^z|?O@wnj)wBj1%:e?5Ͱqc'(|N'A))o@YJ?I Ǿ q/w OvED7 odfr*޽UxJd2f OcZI6fƝgf uh\ӨFq瓚o@p /tAj/F ~wgbxV8_P"}sԽ׸&4>u7{&r'O7t(( TAc;=BqD.k"K_ BƽJ'rϢEyq\uܯAƙ>BC˘0*3G,8ֵN4"ڏh-4 `2CL7L+~0@4Bw*a|* "B+/-hy(Y8u #УIRr4m@O^i@ڸ?Rxp79EƏb~B_O3[Һ{7]'~27#ŷ6Sx(hlqlw4omR ϢBtR4@B|Ly A|LaLeoZNˇf\.< Bev#ztEO!a 5cɺ(L,(0((0-\xQU{PeeFpo:.ۡ7}|p2p+L/IL;ӈ@`~w u<)埞Lgr$ONS,d,*k. >q5ymj ^?x!.Z!RW / ȵ?6KU1y?Ee  =Dc4ʸ c.7\gb @N@AXVX9kD%EG`If#S"Ehkq;. vi:̂.R @b%9߀}p# n7k m*দbpvcjvJ6vb㵳}i>q4iWcvMXmS_5|g4^x€a1[ pv^\ O| Rt3E' Өn^`)@"60NXVwcFP&j֣8v]w)^XeB2T-Yhdi` '݆@Wb& " Ԋ@5L2T@+s [5p~9 E9 Ah*0$5z]|ؽ8BF*^2`#ط Kyج*CÓ9f9yoxL`>c?k: UA0;fS7j1oG)MZq" '8/4 v0Yf!3D87d,'5NN8hgAGc a'R!|!{ xDA14屬&<| p  f?I#~ (3)u6@N 3s1AH[`v ux1 }C\FX@ OJߩl Q8 ઼߀=ş+b hR1wQC; 62"po^Xĸ7DHm Is@[j&?A;|x h:a` JAT j$MWQls ( p(T2N=ldHdj^Gql% >Q3B+?8boo:XE}`BG =^[Փx6L$MnP+J۠[4LTA5S0zyBcF:1vsLU% AR֒|o/ g^O~"f8j,Yr `0T}--HL+ŸI?7(DE‘6FT$߀:5 _7 "*8ojBrEji'z f9`nϠDŽ(IN(.øyRJhScw[*.h{{Ǘm 0BЧr$Cc`>)b9!xDCF@/\iPp#Ψ-昷_ojv"rꇦ-:Zh)[չ#7G8_A W:!4ZcKUYF*?#iq3C᳀VBc81 xh̓.jC ?X]%;ɉB#9#p@VĄW ;EQ"D,v<+03\#*kՄ4âhIn$TE:`|g.YE0(LQyIC p „f9<L08kewY+U9Oݸ%{˸sy= {`eHM0J {%E ;! I"tpr Zh8g\PZf`H8C0C<糱 C`,iS: 8t:Շ r8<Xgr_+ FޚM0<6պrEx. 4Gm^zʀFwI1` @lCL<R3aL}b Ob(9ف&YtA@w !B& kJ#D@`Q0 8.lG8oNU=v Q5Է4}*] H,1㱓‹1P:u׼E{H4Tga6RF?F@CFL)] o4NDI)V y#xʸ#'%$Ch/E#܏ w71tc."]H"RJ ۅۊMUkFdf(\\.o$p\!bh!Sd21|hQE`GǎN06>]O{0t0^6Ʒ* 4hUAsdh-C?`  \ (%(G/?5 9 C+װ"v@*xRq(1/:MsG$0rw ݰRý(!@4.\kq1Bq0(z8X08EtG>Ff`A}|,a@4Ag8kNr'"Nn^[hCbG|#O R )]h5/C4'h*$!8ƒ-eu W<àLf wW;@`b:61@`nUk?Za\I10"8LSt#Nűk$ @4hO2C'e< TCws ASD|nx]hl nB# bx"40*2h OeA0*AcD"A8lyocp-^oG0QЂpP8 A GfxeE0X.= 'A@=^ " ;P3Pw'  pd=h""1>,~ m͕I(ļV XTZNB3 G~v].=JxIcnPgcyLM*8aG@Ie1Ie1f0C+.$8nLYB$ 0̼Ln&ąd9a g2ʜl%QC&nq@p`rlk\8'g9 F} 0yxBۘZ4 1A2d'@W4EAǹ BK {(C`vp`K&EҚCj0Z8<]E " >^O-XW_'cObڗa7Ac` uLwrb*l<MScG 9RnZܜp@f@9J@ASTf>(0p5ڤ^;MdWpi2{RQBд{ 7UD>,xB|zO 7:[i?N WbRPԮ``V,j 5d- WqL6+P(S5x`kVll=E>xtwTU:J+/AƖkr<ѺP RBe""TPy!Tq#::1pLmdF3ހN&,2 `ވh-)Se~#cG$ 4uC|,KF80H kp vs08B7,fEхWOMuB֤Qk@? O葭ÚGS<`{bXi9Qsp1딾 d41w` )*V 8& ~Sv0s[4i~0; ~8v¤cGN2oX8|^[_#X/?w8hTxωJQp*mIШIdiϨЙUYl%/hjV-[8%bD J#Kąw)r#"s 3c9`ԩ4TxTLǩc< tɔ7 '8J\` 9F,cjK 'q AV[k-Ma'"5B7z$tۄ܅Ԭ8\s%/G]r]hk!ׄL!J}n +4!ps Un8G!4 }{#X/ >3Ǯ,tGë0:KȂy)a%3 .BO7P 8 .C*[7U2!l/)vi~o.~~xn}pO7AC7_OW׳[-kqfl8뿫$w)m(Fӷ;םk.U95Bk7 1Uv.}X1<(bxBzvS1<2rBB5ԼĮW+ Osa_iO݆j4W\wjۢAV*NCJtf- MGDU_\U|qCvwomw78"V&3[uL[ ֽn1+SǮL\m1&E{Xf{{5XSC'cWuNNSi@=tIFt@֏._wTh%冝AkR)ةD $$oÝ~VlNaw|R5lN},( hq;JT"N֔t mr莐굔M)gFlD븑 />J;Z jBp56A`&;[~{W2f WaH5a~I UT L#G H!k®CIb~Ù=3?L1?/(!tD2^/;T2)ƂqB*D[G>D'7ɶD䘛AOgK-bV4r#Y9k_FkH[u9YP#zӊuFxWX11(8 /#L "`~UQaqiv ?RC I*(v`HBA_>m>=hmO!$R6CkDCX8Y(eG6&s( *F1YHq_9[bMŵpZh8")N6l\7?./89d=C4&Kv ONd(VUr|I ]T+%>pbGе[`*upSg7jȕjȕW7fD"&(XLyf:H@L΃5]N3vy)L%n76Ό+Mb(q1$,iG-[fGegZ&vA>MB)S4Ѵh G(I-.ڶEs)>^m[(͜_Q"' EH'1ÅM!MDtHjS۠`H+*Fg`IMC'BMia'. m3\IluTI5AwoE ;RtFy-J:|NРKJ[]ٛ\bK,{U)9'IH$-7l)4C& [Z%7aC1$LF2*W&:&cƉ.()WM[]= q=7޲E7t2o% Mql 0S%@x(]밒}ZΛ7.'&@429r;` ¤@_so7_\hŘ6ܮ罋-M{'+~=`֝D:ǐ[GnѣScij)'$y؈"gVxfy̅{;w?Izoǒv$iƔ=4[*V7cw>w1`[D^-ӎzs{LX8[Ox[뀒x[`rWrqB?hΧ41Ω/H1#DHk)X[%?Yna|΄jue J%W%mZJ)>KMUVhi 4,{J^@_xbؕ=;csZg.FSeG:Jٞw#܀\).m7bV($ɶOlLyjς&O j$.f$\7cNX|O~H|/"w jς%~yNhϛ>0VZ2'}F`qy _@Jmͩ&FCTXCĎet; U!)7ޛSƍ#^XXZlmF2J.4HN)?4ʁ ÒxcBm!l;$ :$ %5 - ER]a$ѸzoڇD78yB1S^\fkST Ĉmܞ=>"g黀i4Daӫ.A%Ѹ!%Ѹ.iM %p-RT.b8Itޛ!%ѹhQrZaa љF ]bhf#V`pJXA(cJLuJZhi6,d K' zeal/!%] +?fs:Z$t~V vh*J{]c9viBGB3kГpn 89TW"mfc~`n]/Hpp¥3sێp D$zEGY_7H {>]-jܭ犞!3MʌQ֛Z&vDdJV-=fs_ZS] wϏ.>m0*7gaqdTXP]Nzm s6|>c+ܺsokpq n`t2^Ui&'7FΌ2 g2c6 qg%o>w}J'}n;ጣ5H¢6cDX ]ȴ ,y}`9-ԯ$?@I`VÐ(ת]zˣKw}zp45WiQ,qqcMa:UM>}2;8<촸zsbY%"u>}朲װ+Ef7vȹSgC\!*A7{'IU9J[gVndBӆQb]KC$~a^x"ulę;DaiWΞ(Ŷ')%$Z .iq;W=TĿ-㾡F*{cGŐZɱ&۾DG)mF *q:Qz'S[>9>YN+x_Ҋe0rҶ+'\c(C1Ul11ټrXI&V^yQRA.)rYL'$$YMR>D0dެq&Qf0IÐ&ILXG!ܻW5F*m,c2\ٍUJTf"qVa_D2[bT&STǬ}P9P鱝IJmJ7HhLze 0k,{Uz(F4JmQj;RYZ oZ|urPKR8DE4Fϼ MagicBoard.fzPK;Ffritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/Matrix.fzz000066400000000000000000001565511250202676700321350ustar00rootroot00000000000000PKm5Dzʗ Matrix.fzr8v.>owxtWЅzSPVP]q?? Wo>7.>޽+UPG{駧O7_oH_]]W?#O}u||o/ txa?\7.~{W0vwUW_n}q}~s?>7_wW։}zu[x3|z|_E'@GL绛qo߼?=/&޽`?=?)>x}s_ &jxw-LwY-?>=1b"w?͛c~WWGV몰}_> NSvޅV7Z%mRޑwoUFW,ɮۧ??|z/^nﯶ p7W7W]߿{ӳo_&_'?vvO/݂իë7}x* -W\7+ZyR3Ak,j}&y]kɶx&I] :e s9kd.j}&\}GZ@:$2P ouNZ d;Pt@u_VHjh)[q윲s9ik:sE1gnSޏh5p&[l,YE/:e"j<}&)\%z&I\)qU;'r#ojI*W/jcQ3I~H63IJB)H $I]&ugoĮl$3IJB)v`IzW/`M6Q `y%s;SY{Jɕ ɕ*EQ?r\?'hb]$eh7`'2-N:厠quUbI+wbga$`1T1rˤ;ùN8%_JZ;U1pkiʝqI@HfēV6#VwÕ$m&e6ivq#$ {h$ @R0vI(Pq3iґ_f#%-LtĀH$>F#kFA[FsFkNrШ'mo37zSMmįgmʎƣy6YLR{:'4ΛЈ_$x3&^I"c^4y0:g0Λ_$} ɋsCzSCLwTrNߙ,!5>8g_/$QG9MqF8wHF/'8ىg|}'f ř3S#t;g)ΛnIbhgnIb/nlyS3Wm$nͳXLA$gsY)-v\7s1>^$g/,w_\Dg֝G5IG@ߙd1#6><8gɘ_b#qI6cs>J&_bcj\ʧw?Wxaۿz}zӕ?5g;lEbS}sVZO.OS2ٿPi_mto>s KR:맋7Vo_=ۛjow5|&Gnx S ~&*$|jLZ,_]N(#b8舶$4$T@"g®m'cwv6՟^ i$0(I ã =kBHiA<.J߂ w(ƌE݆a҈◆bHݱ>mNx(Ȍ  5<&X^teY⠗L1zigGC&on\^_ NURl/ =>4 O@;_.[mEuv٭]6۰#Yead2b 6x1帥A-Iy-K㖔j{ޙOKKZDBٲKn23U}Ù]z|yhwh2]-;IZً~;S"ST2ud9hiYgF+l$ 6x<ӵ[gZhR}!uhrS0kDsm$YQV$KE^3@wDSh%qy怡7Lvҙg.4 ɫD X9fc*> <2ǜ0䴼/C2vhp~ւ*$KaRh/UF2-jŷIEdl)/ 3/ =`4>aоrwI\Ԣ Gã{dvep!%ozw-QeMyˤ*ߘ8_*ݽow{_fX꒼}'5Vj- 7ǻ7Wo?>ݼ~gk<^ 5w%S}=`m$t.>;ËO?}|sO<@{<+ۢyIGkfњHQ,AԱjIW]E 9e #ͩeVx1uX*l-pXٌ7$ ^MU%Jd|7DpEXR) K%ohqt`}֝*]vXJo83P1]l5Uj+AJ* 8Lc &cZU2%6$满SffIJJs6u翡3X W&V4b]rvwݭ1K OR[h伴nhuPh.%KV?k-Q5xVd-ѶhuI7| ~~5Hg׋ʽ1(5zjS}KͅcNLTOTa'<%:67 81Vy@:)KKq=wf.aס-IK=:4e —V*aW'*}ccˀohYNR޵. >]Ŀ=mrTm9jPY4Wx+,v6Ϝ+xxD#V[y&g!ApK0S+㭅͘QwOPVP)R8|Z+(ъAMna:h&Sb#q +;tZfYKRH6 ׼yPuw&tlJLաϸ{h? ٵVs@z!uoGg%v x>{#3H'~E:nR,;rt_䝽ӽj}ozI ؄45g:LOǐ;Ūz[sF gNa \`LW+:Ӆ*x3=>[g:#^ ;_ttp0 *vtz eDOlXٗmY`_:-g-_:'lߗmK/ts}.6;ӳ3L}:ӑOtn"#X%&;p;QKZsgozHfj>w:ۇNOޝN͑ޚ+li×4+u>?]B1Yֵ!kcIk򟳺kt ;<.vUPǕ(\Yqqa(ٕF /}}UChL}gzhgzIts3tLt${Oou;% hi7QW]4ނtF;}w^ߝntB vV7={S!M3ӟ`LOߙ=7}~G䦗+5=in^MW/27XLN_G}.:9} UN8eYыno:m]ROOWٟ8vgr:N_'ϼelyKzyM7{өԬ=9}|O]ۗ?r˕tPvP?qΥ<";ݬ ;G邆tž?=C8ST.IY !ELAEOl0;ݮϾcqVkbvϟt󲙟ٟeO~:ԑ4 u~[^o~:MoI9<ꔜ Uo\Dezv]_)f0tf٥]C[V)l᧑2v1zEB+]ohQ =i>t2zbǥ>.utNO˗:g-HKS٥~]8^ϥ~&Iz[̽ԱlzKq ԭ٠ .u]0gdz;=_0LQOvaNRf(ٖ2uݴUWk!$u ؞K`13VDR.K,Um m;1NarVsFח5K]/~xv#{z]s,u3Mœ׫X6%]Py\.uN%UHfz'S}j CKw٧ SgD+ԭ1[ǧ~^^:w(T9]xQrMDm}Q0ƥkez@pIo=IX6<ܒ6 `nEp_d7N6& &#e hf[^o8MoAylz<?=>]M ?ۡm.j/Ty=nb~䓩av_/gt%-ۿD(~މ k+=]|&lo] Ɯ9͟Һ\oMګIZ `ϛ燏[,Gy=k8(-$1@j;2o `9 \0!tB\9'=ؐ9GžaTf Ī#d ƹ j,EBKib AppCIAgAˊiVs2ӗe%,脋OK`Z5T愎ӳt_S-VHǷ(`K0Zʔ4 ')Xre)WggRSu4"[Ru̷ָ-nurيyg?uxRHGEGbq-&9)tiJQ+6t0RFEfODZ|6K+$a-N:[J!+GAXsa_X#-8/%I̱`>9"sk Yd5cIv%.LbCWp"FJdyu٬$YADTPiϙ*LwgY, .>3Y-HN5:uT|9ST愎ӳtϊj h _ u-Qɔ+6700όr hc9e\}|౔q[P ɾeB}L$B3:ɛ.c+5$oE|&~B ^o>S" ZH[82vRɴyrZl픆9NY/&.JQʰ&2ʂqQBQ۷xhj[9`̜32\1$Q' r2 =WIC؉ȂuIZs sZx9- 9߽;{ /eQ*9g9^φsR>[9`̜32\1$ QrѩsF+$"l>!,=c0rRYEBi)LA2l*4!^ PV `qú*uw혵TG;BOl'C2v[]'dE8{cӀ%Y҅PN?Gd%az)k3CNg]U$I ! NMeħADX4uIgBsewgjٴ\D4`ӿU.7J.S3uΧ4N; L2K: SDM̊@F 8Y@9Q# Ź(+6Oe< XNeD I 4X 0cg1^HƗwg":1$-2EDML,2tC $ Yd&6ʺߦd5&6oXl$.0\s1̢\Kgg\RUK|J%W-eE-ff"N,}Z\Bp6)U rP9w]>}2Hq}̴m:."^rΔ~@ *0-Po0 ^Բ/g `3@$_vL% `CNe/#y 60o}lJuH6-ׂ$*PARI "sfdf{$BZ{ -NpԇtstnD0fT^"n޿tpȉ-pƆCG&ɼDXpe{r$'f_<[T5iPFtsk67TтFRO5 )}{T#wsJe 3r(/NO$E݂#tΏr*sE݂/t.LPmPQ:_leZt~ چ]l,d,>CDtܗ| @P4N'vS,vf8#%AbY+[8)[SDҾYO9bZeJ 6+BOٟ+Y"i퓙r^a F'Ly9N/':<60JD2wH$I yfUo L!UCӇ=_б~؉!r/:=03>0,9;lA)I3f\Y4dYVf[3k]X炱hQSrx 3+V=hy瀡32)YYD5q1J8鈧V2<]`39 IX҈c!=tdy(iGF NM!dfsǁ4q{k y~xeFM??>X~ۯ_W_ti^xm eRI;L ڊǞ }PkpL=mǎ-fjh.2'[n;v) ywvY  :!)(g#džN^Oδ=*N94y9a5+y *vGiDmh*/:c?$'IsG%HC;j}6{DNG2 cHJ8 (S;qx%- בт*a,4w*6޳Zlhˆi>Jӂw,! ʲ(ţBkQѴf6JN_X h0du6 LbCCc}/!! ӳ7j69㴐5^9 }53+I753qPi}Ԭɺʜl^IG҃y:@D $Љ13 eXdIR&e)c\B"q8. ʤ,:tzZ0Lf!enZ5)s'Uv5݀T\iH$IOkD#ks)fdn:=)x$cb"f'ZCHd展g!hVwe6EU7;{fD((Zgы֦hh$IhXpdd{DNG2S bHJ>a%ڢ'eXfp05ZJe mԉ%uWTmUZthİ\z\DPz0tA AʆL)DujdڳDNS{6MbC#E&b#Y-z'`hRAmMe:MOIGpȹΟuq`p]6ӱUDґ`~@ 9,6tz)R IIGP4,8 EctaPP4'nydqJI8k1F 8Xy<Y98$IqD#3BD#$sqGJ>& x,ɖ(8m !$Re(ʼ,:t:/c8O MIG2ҙ.y) b"9P᪷,zh}^Kґ`^G6DDC$s )x$#Y m޺pMqʈ. ѼFN9ZthǬM9Cς?,9㲠Dwj8'ZNk^䊳шBPTgȉvHh "Y7 ,‡Q+-A3yT2wģW@wImOujM35;̪f'.$#D* ]w}*yA E}HUEmɴl^ IG҃X?q"'Z!ņN5C )IvEdg 58ځF?j$PH.'P!E1wkgBiيrZ"fKdhYcf91zr|!IXȧHCN4>2# >t#qAϠ.)2ȡIyXF'e>:=T&qbJ>&TǓw9 '0how&cCɐG:&CɦY rIYl0RIIDŽɐȒlK\ꀔNZT|F#[kAdC R KD!u媲EɐBHB>5GFrXlRH\Чfa (9F؁J `VaɬڅQWbV:7`"~Y J$d4d:>tjFPɐl"'!ņN;R12$ 1dab&p3D Nn;9S8RXeN6'HNZp(qD*XѱPX1X;D#)18X-]>&Qp0t>8 ˊXtZK>3cs;IVHN Zh{0YdH$Iװc՛O5FDc$2𑒴kŇ1AȒ M- VC LҊlLPR43;%iQRWfh($;Hivç O*aE3HWaA)tkDNF2G ѐbHJ> ,Ӗ.3+Q4#:QcZ13O!Rq}g\T=FbK hGY}@l&kC'pI:IoȉH&j3pGJҮ! I)=, (ՠn ͨLϢC'wg xJF0nvRUơbZ3f AlUhgxfC'6 %Hzh 8 LbC'7NJ)I{x ,HJ,98Ε%-OJP4( kZX3Ge0m>еt#S~A.Ig-b -5@iԓX#L0_O^3d *k*-RU !7,va3hkX5iȉvHeہ E]Îާyoe8鷥Y0ΡrSsB@Nr6ڿYth,C,sJFM\߼,2Vxr%,fы-ʊiXCQ6hdb9`̪)X dIbV.L̐4oEJEE(L"-,g19= )InJ3)Ҍ>(ӳS+͐BI:LѰv5"'Z#ņN4C !)IFizYfga HQt9 v5}0Qiѡ]r G  xTaՑE;Z"iH%$:b Yl"'!ņGE&jYQprJa_ Ia*IHKo$_[ugb:L?$mlXTi2-k: +#rY-9ɔ,6trVHI5xf)CA?DOvdK;s@ >)I[ +1eT}o`D/Zat$]1@D$S?bFJҮ btGAr;h?UYf;ZYd֬02+J 3ً@6m1ӦEnheNJґ 3,0(kDNF2E \aBRfX`dIɑ=g8`ڮqhjEvLI';%Q0nΟ5@iXZD3T-p&Fg>JrYT֫0C!4CD;$~fɬYaB$grariO RJlI B2/(W̨+IPE HT"Rc4*E hoxhC6"Ŕt$]C85"'Z#ņNpD)I/"rEf|an1CIW8pR %]9Yt P>nl|liǏZ_|G/Zy8BVhed:) …8$\ja…Ltr '~#~ce6-D#s"_8a#%i\ r0lEJQuk-4B΋_{Xtt2se2v۩da'(rXYR IG}a4l8lȉHgRHIa%b =(H-;ss9YK )Iĵ6Ԝ !/oL,"h9p#ɉX@cm6ܐ͍̼bC'%'"}Dr"Xy-G*!KVFdb_K3!"3O %it/:1cMJZW:D-#F7\}NIG  YMBD+$a8#%i̐ Ȃ̬$ 33oVת~㥢uz6>ӳv$V7,*.p&,r#E3(c4يC1CNA29 NΐGJm AeK ypi$yc=2QJ>"R֦5a9H YS paJN8?pFJQ^V^\=L> G7}:/P20402iȉ&Hb3yč= .J BpHBdz]Gg>:13;%i+U9۳Xf׭iHM #D.3Pt8葎;/rMFrёXld6R!1,б$[K``5 ^4+Xui2\gBW`.1.[EExRJS][f:9œӁt%S<֝aS Q'b 1%OJ"֌3Є6Z0f9uh?0"ƍtL,z `8#I!&v!'ņ É)IHY 1fsP"g2:C5NUJ>&Of,W>T,z /^#a0$X! q!'}ņP;R10$  7Jڭ:"` l (pűB vEviXlC6%iAC>N^0-#2 mDO7>zb=R$IGځEV&hs#r9Zl8RIIG05,@$S 355RP:t"2uv',2 +7Q ffݹ3Ξf{RRahَ#q]dcf:t#a!w1$ȱ:grȉ&Gf`gf$.N7$_ja0FFrw$|ƝWwIBfrDVi}/!9c,LBBnnUإZRZfRA4Ѽ5:6t}N,IG9YMDDK$Bc8#%iΐ Ȓ,J f oUɈ ǻ]qѢCgh+>3pmLZT=RiׄP@vݶ:S i;ڔ2EYRx Ԍ8ѐJ:f-gȉHh)RHI,SKraf0P4(/iȖt望REFw,:tZnIђ>1LDŽ)8RP"Pي%5+̢-fH#a!"acM9+6tRRH\Чf$_zY% U@Ntr"NHLIǐ0$i0@h'jjyX181$:`iFHd3pGJ>!yZxYV[Ke25kNf=jyhcJ>E*fQz\tiײnAe]%X8Q#Iwh^8q#9\,6taeH#%iŰ`Ȓ\l20rĢ6ewL&^"ΦKĔ k`3L66:,s֡C^$,S]CCN442 7I)iW0hF:1%^>/ɬpɘtzw(FdLD 팆D#)) YIA1/&X]tDN4A2/ >Rv? ! 2~Y L?Е9z XN IG҃YX4#DN4B27 }7"Kr 4n1 fڀN LʢC'&+5OLQhŖdE-.[JYxB:OM{ёVhud:-Y'h$.SS003؆BjXڷ1e&:ƙ5`c8nvllhΜ}ԖH$I&fX`d9 -6tzOiX`d)FKF9?T Ͽ^|x+7ŗywo?TTYGʴW6/p{su=+(U07yӇϷՅxOO__~zxϟu??#\a{L SV}L4LsT r?Ӆaߟnoo?5A]lp_&>ݵ%>t߽:nǻooއ78dgb_<=?>v'T~^Ij{&/Oo*ӳέҍÅa);_ދ#Motw=^+uh ,J]Cf24cnv%Nw'TX@{F0- S=YZJT_v \|}|{hA~wqݧ_w߿ã?~o.~/շ?|{?w;D??^pwte^"V>6?~}[/_KӽuAUa|?E~/@rǟ^qqh"J)xV- (hv#̄e-/ڧ;+g_9ݲ~Ś777ӧ(-wMu$9 cor{BDKVG@o6М^;j\Bc_>M*>lx%FgGKFWRd~@i_rۜ!j.EoXK/ a5eŔWS>s?l,N7TP;s-̓k*nsצ7r;F н_.waD"0?})w?RjweA} txmodV^n~(?DD; ^^Gykxx}C/%sH}]2mǙKa n:tQ]l5_}d^O@?L tb*<˽7`Tx?NnG탱7W\_M7XWV4n6+ȫ 7nNI}D.DnIn>Jp˽XoVv"75eOޜY탯ܻdr咚B3 -*[Ľf͏a?ڻSuGx4"[ѥ \W ~Iݗ 7H_zP?R ]n?үOs._ܡ=G9UG}G_V3p/.=b2`Bsc)= ht?/4mt*JfI<~o_1~J7LiIc'R`-Sٯu᩹桞2T,ᙫ?ڦ * Mu#N??h@h )!nk!ƿ;_S$@te?8 @.@2i]"CW˲s{e@1t2QBtnl5ؿnک0|6TYQnzoN>AQ2,p6a^ݽnn{s `nnZ/i/S "(*7+K/ =yO~zkh7r韃N|nvB `ȲQy^kᤪwxڏ_WjK$n{ӛVg_a<౬㱲֐ݔQQ&]vn{vɚ)"Ek>[wM(zkWKx]oH }F5<7?FWp㵩=vu'M=ӎwi1hʹ v7)L;Cϙv{Su-wm!i{bb%N0aa1oq+pR]C sGWo(q.̉znNjS W qmZ+?Lx[&_U\gmecԶE#kY4pnVPֶj'v+P[j dm+`6?gU(vv,B][`K}p翎yF*ȽFgƛm;0OսSeo__fǁW/a1E΍9o@3 }ݪ!v35SPg^R˼-@7_>սe=$t!-M/voy +`;UR{u7dn'K؜`ׅ% _蕦1sLKٞc~= ؃_Wx1lM3y;+k\7*l_E (3SR;exLoU w-~w t6 %H󫁀okew,T1rɯ"x"8v# v{j;o=ޫc`h9G( xk==e:G[P"  cTrO=qܲTaCqk'_(|t藁ڋg5R +x(sL64KDyQym۾v~lbuB =$ڧZnדFUM j׀[O̓G0)MP3W4~(¯t?c@ۉ3N0$xVŸ_XrBR%~֪Qͼ,ٿF`adKf e7dT}-^1 I^_{@\֡Em(oQBv &Gn /DPp7t+ Vl ^[9x =''`w9^)< f>3&V$ e.=RJѯ%[\zZY$େ__N@Z)>} ̛^bY!8DFn,uNGzG&KUyW_~gc`3-NVc f%aM"EeߵVoalpiGF<*&^:7`0J-ƻL> +o 0@@Om_Նâ`HzwSs]z/FE~w__XRyRb  a`n 'citYGs=u5/ُ[3ȖE׽geqިP'-~pԾ)C ]l@&KMyyN <~2RC0xyƳK9_@OK)GFOb"ൽÏR N]% ~WO7,lO=^(+H߽ OUhQrƞ 2 C!h,eg  .[%_r@]+ȋ +W*v%UIS5i?@қ@~_9 ݰ·VR"Dks\uP` ~dJX,EѼ  3< n_ 0mAC0i;A`~Y`]i'> 9"`&PS?1<0O" I:w 7pA 1 ~+9.@}̀կw l.!F+98 @r h7mhSYl}/$/M!AE{ aWR % *Wm!:wc$0_Ȁ_|W%Y~ a%ln xm2@#l~L<2a/|~ 06`  ;P3@~xAx`@# 6. #ÂR F\lT/.$A`W~0XۛyGNQS ^~_פ?cvQV10 `쏀>&* k"c6kb D{3L?sJRV۷.]E5eH½S_۷smvlW| =V hح[rz껕=9 qx.{.a#@ꉄL# yxO#mC6KȰ2"_{ҁxf+ zDH| Ba_|d!0[;/]4C 3U4c^r>AۍeجkϦ!Q`ۗ7/F:}_)ةKVr*5,9+ , A=hR}S祡xGqݣpwXm>MM)*AӝKȦQ'_<`!oM8? "z9'~EvMpu)6;UU WؚE 0pu{tikJ+nUT|oem֬~t?lL/o'j/>zg3va/;k'/T!Tb;2Zj~Y*lPyM.8X pxd3nʫ=u2qmZhtba1GO|)`GkLdenn KD8 Ɠ*jFR vn0 R]PDxחd<(Ϛ.jяza7ٹa{=5r瑅6,b_jv}ۨ=8lאuJFbɂik7<&K7ddN:`e^ݨ9y 4l? %$6[ ^[r#s~&;FUL)xX TQf E` ^3o)/ VdvèWǰoV@XU_HVEX `]C^>|^ۅ7A~EQ_5" ^6עEY[;ZZiqRZؖe}ԷPqsY_l%ky7{E셰 l#xЗa_ }ھ4_3 R V0M8TAbN+]_#;籖dž<~E}}L_S-1j8>7J6&hf:=?c[/Y Wpu(8P~Ww۲5f&b~ D.1p睆:E{9˚VL0aM_ԪL REOa:@UO$þ㧤w_AN~ v޹W2DXY$>K(!'!7PmpN`A b@? ] m„a ,jVA.0"E_#,zۚ>JYbW4!psUqBhԯm*  \zi0kV↵. .]0 0O;4SB%3 .o'@l8p\<)!:^ L;x2=ڮ_^Oﯶ/^nm?^4ws]z;ojo֘Oבgd>]JE[AG6ko?\Y6qb;7וVnnp=smD^ɋRm?j;h" V , T"@/}wضgU}Vݧ@Ϣʻwk z~'HrHJ w/>Rh2"#7k pz(sv|nz;UzeV7\QʄjmEMV,Ϻ[P+< Z 멕lx*juJl0/Yo,Պ%VG\U!d[ɔVǠP"Wh0o=VmNEp =>!xCabV7[RU h7, `ip:0+ǙEK}ճ V+TKβZUQV}'y5;8(X.M#I*"e>ۯq4;ڝFxuͽ'+g/P޽{}7`AJtuѦd; ,cvo>[I bOpP\>S"@9jp;z;jgLd$⌤8#̤&H'QiGHây' NkJRȭdR$P;Hx=g$aUGUWo`O =Ļ Ysn^ߤ['ʄj?nWFoG1~C>DTi(uSK]T m4w}k/,aoMDoq=ӸntiJ^w:?]|W._%LKDK׬K׬*/֚ӥ Uui朿^]Z.^]ڿakDt\$U򢊗KʾPgj"t{^Wŧ,) gK Tk*V*-Pfڋsz.-P[_[PYgK((.(A,˝-ᭆ%\m_oGJǛۧpފ?g;(E5QCq'# Vn/p/WB(8#9P>w4^tWFśk+շ;nB=[{wOdw7wϿFc[F磠AzuB?y᭲k" ؍rGO w(SGt:)M![!,CB&V;c!$xicT Jȴc`SJ>&y j,e9c37mT>n1EemW^LNVb#wxX&wT6ґvTct5t"q\n7͍c۵ !'4$#*ƒN-~]~} 7<ߛHHj̮;;3,5\Æ(ͬn>VRJ 6Vw$`Zd>ט,1V$,N'V'X@QvE_,5mg՜":;iXfiAbph{gc"XLu5OÔ> E*65 IuWHf:֘ʚ5(A]Í}k(\1ʝȚY79Rv?ń 22W(#H.o{eH._a>+ ENgeZuz hb933 ̐"I:l3 ''{wؑZ^/,Iϖ;8a4~%\#\,79y-*uIc#cLÎL"Cd+ℍ|ju`jnjUENX  LL/L4wlJmX# &6ڥXt 2ؘacHߢ$fZ=Ӳɱ1 s3$#@vȉeE! ")IHdiEYZ=T҂ @͊N-:t:GprqhK;'1.&fZjiSyR IX҈EAG{ޕ< RH\ڈdIntJJ,WoJj ZJWRmjl*SЮsD$0:~'ӱBfQĎ30L"C'ŰH:B֏) -RHYd8ENaŌ}D"XӲ$f f$Ł1UBjB[kTR H98SpN(ڜl2x>F VIGCXQZ}fQ@68RpR<$e qs9jp(h0 $,uS8_. nvdX򕏃> vp>߳"^}B5N)PZ5PbrkS{r|Ylh?@aR<,$[>gH( &v{L>LC'XBufxHzۮ‡fKe:1І:ґp6ga-ѷÆ`Fg :9҆9R14 z,In9b=S5 6>7S(μ=BnvltivT_NHGC8j>zjr>0S(NHI)XrQ0H(W#כ`f7u5̷Cg[l|k%i[G㆙fAe:lČt$=l!Y R$"3-h![HcI&[ j)pY*QH["oCe:{1ȘZLJME3͓YdTFIґt GN_Ӈ2: ˧D#fHa#%i׀C)iA˸l!ջ!ׯ'a;ZqCE12rCγSY/6672:t@FB>5EG4XA ,k˸&τ{Y |EVo!Z3ъ1Fct8|&^SqFB>5EǻZ aDL"Ceℌ}j{Je]]m$< ]/Y`ޅC IWd ɬ15]8#I^H@!4(ׄbL‰)Iޅ3]t:C )I/"Љ!.x'bXc?ګbX}2aņNma}D!Xe-8X3ak2k U'TG3nX\Q/gt% вǵgZ:5)#Cpv|94݂ƐņNV';: #惊(踼6 *wJٿ );( E:Xq#aeYS=eO%HUDG?O }:|YbD<>ڂG5B'ASm汁Q*_SvZ?U cRNbDU&<>묪Wm|k/0oְhB>s?8W,g=˜,)1!FKV!tS}^Xc) u`V1&{\Ѳv!cRǑY Z&.vAVjgDV^BOaa⢧lq,dt,_ٱaonq5wxWbZ9lx[/]m>2r%H$ bZpK{0-ڈ )خi>pǑ_Яip-}^̨]A]tOw߼;Z)`e]ٿz0SA]4${Rka(' H^8#(ߙa7*l0Mkb) 8 J1a 1Έ-X/lt^dXɊk`ɹM?_{Jt4#ە~ 0( "PM-Q^eǶ;5Eiz"5 ryk1 ,=k=]MZC[=u| V WZIOu-̀P!VV@O7 :WOpV ؟m1C0P\*;q,tB!b* _#{ !vDqfB(ٺ0O7[ 3.8hfP.==aVpիzua⢧l.dT+[Naa7@vGU %k0yS|-i|X DBG?N׿͂1 _'a 5 =e;Nj_ [ s o'0*fou=,;X1t *(vO^ClQtD"VBk_+ҮC5!cyk0>H5ļNZmyCf_*R"4%JaL'Z#ƑR[J'R2Io^ /oųBOa"l'xZ[uI {sVn0-//<gbF3CԈ sֻB!X8W;4r=]xS+(=\g*R`bD_WW֊NawIN04Iɽ=ص'L`O[ͦ>fL3h'[m _¨,For#R 0S{ 4jzVn,ϵM=0ٳt2-ƞugtmY1ykF,P^Š sxBIk/o*)j t%GO#\ '\Z¥1˫EӾ]mx, W1,\*|| I¥zaQ1#ҚpB…ʋ~2U`XѾ ,ן`͚5 =e{f0fU fYJAdZn;ijg {–njY;i`*R+['ӛ+[(h.ZrqXǢ׳@ySwԳPQS|eѲ ؀༅[LDI,ZPhiQ=e{hihFUY TF?*Z0h/ZKZLƴl8B8>zgKtEGO\0\0˚}R>C%`*ҽpa]lX#М4"'{W!]'%0++WR?[,.سtEEO5KWV,XN:4U1VsaO֬V'":RBJ ~2YJXScw^ɚ"wPV⢧lk֪\U ZWzN~yZVPZ"l︖e6;j>f-,@BE?ެY(hY`1 (Be⢧l,dԴC,m2\4e=dq Pf5lqfb,@BE?ޮX hX{Xaϼ5@qS(2j*V^a(r,YPz!+`)%Kε<>;J>fL- dze]gb͚+Y)5 5KWnw zOG'Ta>"ON[旷jCw c*+[uOXqy#zQ82_1Tek  oQA 74y?kJ6W@SD6Vyx6bvqȹ\҇V OkROkGɫ5]{i`*n}~`qׄ]ފME{RcWdAG^Z|ԔN$$T&ux]Jvjb>9i}u hD5V!ZF?\(-,'KV)^FOaZ(ШhZiY bi1K2ẁ5F?Si5:GfZ;i7@ٴ dF?nZ h3c-K 6y Ǵ@QӴj_r%}U"Z'7h-BOF_WP`\-ZefDR7S֬B(Y0qO"AUf= [<EOsr5-0cA,Dw`Z:4["6z)7]̈|YPrK L^Š [Ya`l,fԬ-õeӃBG7aݻ`A(hd1jx``zzv%Ԙ1zV R,^ǟ~?~Yn +0=3SȔHU~|`.tbs d2k ('+\4sV#liPlo4 T4*[Zİ bEq酌\J}5ouCf0zKCپҨL,Z--J4P͖F%%F tK%HOai(iiaiJ 3w^[-cYg"/|_C4Ignヾm!y3a 湘V|S{M%IǙHsC;a%bi+vB(@yRQϜg C2V#cgCOгFSҧ~I=S l\ mAaag|;8igU|(0AqP?۹ąY!;GFHM;U1 vv 3 -ǥRmL|\+yIY ROqQ6  PB*U4Ox~ %.KC(i-i%G !);N9`Un4M_!q?28J JlhPzLb)[ }cpVI1qCJoj_9eH?ff@@0 K\Be3PvJďJk ETXU}v\ICDڙܬ)ۛkg! ,jaLiZ;eI?X;H{CG,q=¢V@S7p0RSj,M_=-a32&vx&,Z1Z; ;@$3wgh(/鵳fPZ "dzs  jqb+vB(xˎxN+;p̑7)4p{p"ؤ~4145G5}off mexsj9;>Ĉ,J3Pti` L>۵ UY!ng<(fa,fBmb{{ldc qT%7Wc3+Y-ms*i7zTFHrwHfDɴ3nR|Sk)EH?_Y3Z[} bKֲB((>zʶːRle/ ^f&в۬eP ȋer:nfiD' ON%.HX dICGON*KZ4mEQ=15sK/d3#ULO5F4PI ƒVeI->ĒJ(Qtөa B(]@S~)iQ"H);f46;Z1BdYd9#e3nX|4Lo.F a?+PDHO^Bʎ-m5oeٶ8#I,i i zI WWJ) gIˇ+h('ӛ% #%NK\BOal4Դ4_KS;;]n/`~~B %ǖ0M-0,Ml_]1ǔw BS(UlN٬gP2Lo3~4H]X2J3PzBzzfgBϔΪao5*ES?;<z{|Y~&A\;,d3<*;bMˇ5 %dz`4r#i< !=e{`UO }MD4ӌ!77ߤ89CjS%}I$&x=>K(S5gU^@AO inhtlXBJW4P|w!5h1,meƗAI(~~$!g&CO+=c9۝m`*Uer3V|nɑ3 >jX2լzaңlʳPƎ(.h;Ҋl&pSlVb jy3l;32MHpx_?k e$>'ԪaBL'yh`j4}FƆ%.BX '&>zvoTiCY$HQ3Ιܾ{zـĞh Q!2 cPL|;ppq8,qBV (@z{f()eSǀ e7:UhCvvLҧ~]ӍQayce6HADc?ò$eG?a(h=^Pz2lP/nTT鈡^%C^OǷ-( iW>XĊ\,b 1N#=&;< ,JBLo30 `470cPz) =e{Q՝/DHG):_5JLC.JaU>u1XlE{XDږ7Y>,g8h}B K[BO2Lvtm`~4TFlNm-n6b(&{d8H[#CdT1_`ˇRU dzIEn4128,q>V(@zc((ecݵ R" #;-R0+;|J20NElm?(aC2:}kZ{To.@7'C,q~V%*Azc(g.lRFco9)gPz=e{F1G)^di<9Ɩ~2P0fi_F,q5–V7%HOai(ii K^0 {ʚҊŴvxߛ-JF*SF2--N?9eCU4PU443:!gPz =e{O "5,V3ۇi#[p1/ACghRҧ~]?3ƳtgD9Jҁ^],iK qPL-v %&C6;Gs;#B,qrV=A0SDjʙ,gC ^\Rh`ŽuJFu2ӫh%C[Olx{W4:\&_;i755\( F%.JX ) A^Ѿ U-`ZfDjex)'5}oi;;Z.^+hMqh\X̮3TQ#mb6B(PSwrDHE;E ;, t: +G4=hOܗlh!WWѸ~M $dzP㞵%EX ){ "5U4%AM0.R,ƛۅ*Z͔_X~Wg Z{AÅH?\FC]K\BB@ SwP(R*ϬV?fq`לOp5b(0E=~frLy7Ѡ, %dz`ҾZXj-Jl4Դʓ4#YL~~ W7Ҋ'XȞ<Ȱȋ--ÔR Shta2Lo3~32!g =e{P#гE~VXgߣg%CO3#=e{TLItM>Ė%[&JvKHkK#F,q5–V=0 SXEjZZaXڍknv*^s1ѴMִiivTҧ~QM܃VP<'@YOyG{aQ+E !=e{aU\c5iG<,Q O,°Ϩ͌ yylC0 A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKm5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKm5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKm5Dzʗ Matrix.fzPKm5D_ Matrix.inoPKl5Dt#SȚpart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKm5D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKm5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKm5D'0 M=svg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKm5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPK[fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/NightLight.fzz000066400000000000000000000442521250202676700327240ustar00rootroot00000000000000PKY8D]E_ NightLight.fz}r#7w K_|31n/gz.a{zf9(8D-V_h+3-*VŋD iITH|/H|p:M 廞xعo;Hf2}1ѫy 텻׳iMaқn4__txuoq<}*3F*5 Gw/d}u7Ңi~y)Cn( Egl@}sQ~pkg}߿]4~N7_^mvC~yI ˛ϟ/k 5F^ٿ[Oj2VaNOJ/:{ "y羼\N'Ltt<=\tfwO\ǣۇ_&٩xs? X?}FNo;_8>N;t7O\=Qx.}˴? ?9-n4a8 G|Tt!? o{c\uM̵הrsEPYe.|LJGH]3~S(`2^cyAK㛢Z* \|Zxpr?O?u>{Ȕ^Ie|r!DV4ÁӺVWKA=?-MՆXUy!V2UJuCB '-n$nMҲ>#9m _yn~;(b !sO"yaq)y`*y[`q)y_m(V+VuU\x֖}UR$cBڿD4E ֎o*rr%4cUhY1Z99aJ?NzM%\RyoNŢ⻓ >qo"py:"u\"M:Nuicr$$z קu-ih}Oah'-rQϙUvFTSE~Z,Fb3)F@#QJ8^)ך3&&fw[" È1y#S ƨ?M#iad>a}A ;^a6po &sN(8RO[ #yG S> _ +a;mf%T;X'w0:?a*~!TP7l$CqU|K1Jw%t{*_|[71y뗗l~:. ~p7oH꟭6奘hqiEԞ |̽4#@|Atݸ;T_s?2.*ᮃT\t&h n;q_lRpӈRGߖLj?U$z!H \PTQrc۾\e]ʿZj~n^-u*gQNIL[S뼲.fش Ɉd^5T0R!_ 3}B֡qVԠ.\dX%R8I4x)t3Hp['z/衩N5 vpfWVnf7}4pO<aV3>^dVxN=?2 >qZP_y, b(MIA6o{<'sPBbSѢ|u]Ͱ༾`CMST𕱘s n7:65ף٣: ]L;4bRӄ(Iwi RfZY!ʷѱ=)Iʝգ0>ȴ rPedG`eԥ$S֖y7x~dXU/gr_X\ lƬMN1צ%"V./;s~ayf8a_gɒ8Oۏb1f؋KIʨgOJg0b1ڥG _lj_,h[1I:Ɩ$1U{bn+#Tu;Y9*jW_k&38w ,1spa|Ҏ,1sLGV1aa\ Y,fLJ =JU1's; 9OƯǤ[LQ:ŪØ=fRL0al2iZvk\&+sUՌ8'0qia^ l{GaҐ=n] )[d'9Xě>&EzVD2$gH$RgjsB!qSr5G' ;sQa&87{>+&; Sxa%%K|8XD&M@Iʛ=jASE45iX 䰒RS`Sf hwe=*Dƅ-&f7QmXM+&}.t1.S l6כAfOlnyԝaw@<Զ"&9 $;Jꖹ)Ft؂$dL~L mj٥C͵ Ҳ0z݉n*W.[ L恓b.ݳPyU`'#;+i9>&e]ύnSEHj’hjAV5;YUeBDg\ z}Ҁ2GR)ɘ$a]fwJ3K KGRam͞K;q2rn4:!*[6C;fkDLH"7=3MhLOKE0I4i t-~ GKOM }1 m8%rgܨZ*}rʌ5Uooc@y$"_ ++̊ۊ=|i04;W|r2 @F 2qS;3xfl&U$$St<|:?F):_EaZqmYՌG'A,z|.4nWI!;zXZpbź6GmɘDD^ž\]kp̋G7S-LpDB6PxǑ:`:#T1cAI\$Fiъٕ|$n CRr%&gLLnO )HQaɵ )wjDxicrEIL \C򺙜09&}bןq}TnsD^ 5"U8DPζCo9,!ɴQk-iNUr-ÞZ_Wn7,+JK)ʹ+UukP^:J1SM7-8Bhs9*CG"m GZDY9#s_IyZ]>QKŬR2!ٱ϶$bu"LY7.;tLڮ_%o[0Ҕ6<XPPpsxY `d{=>w:N@' qP,r$&vu?Z ϖv.}A}$Ow~E )Tu[A7?*3[roa7/ 7Qc2#PNTefK⠛ʕˮ 1RXB=z+叆b4xؚ@ IUnI@oy]1aeF 9NF޻bGOȶgpsa3]Q4,Sa'|xv==` m:1e HeqO*'سr:R]) "AKVgVr%rP4v==]BgJet,zRAeˤXLH0DcWצ#FCdm&N- q%~Ou;A%%mO^7W9W! $R/GZC $V8HӶ؂AF4)k8${eZxR[T#7֟[vcΘ#o]I<x\CZ |vCAir FIrH2TDVH|vdn 娕(;flt9(5MCdQ)6,NP,{dn)h,DMZ-,n̴*SN!v^>6ж=5mg<703a^~U-翱h`\q1f+RlA-KKkqgDs"[~M2Q7|yp:}G5WH/'GUv|o١N8VG&aHf7d: g0cHk4kllQW 2Fٺb2(Qz-_g W2GNb*2Fٺb2\f^xA~X{uYBr.7RY2@0L;~ _0 >{=7drNϜ2}Oj< 0B3MYHM2*Nxif6Ú)??$a賫lGG[~6t𲕗ioQ≭͎VgrwqHNf!f%ݡ-v|NHbU+a3(QpYb9֙ي`9>i9ڎ*UѾRK,8|-[ kbkS.y#֦16h36M1bmQ)F˱mz9_݂͛S!2 Xrf|_MkOW\uJL~%g8fExr:N쓐,9/sd`\ftӒ4DYBDVE7aL†)ɬ;el2Q21j>{8YoUs;:$$HfBdTm̭ƾ_ =}TeP[5LJWGY0߯I޲ϞZj9t|п~}q8qq<~ '^:<7m)fWmґEv.+/#a.+-*i)X4C@4ef6Xc[Unv'7 DFw:MkM%5QɳZnsQ 9Jxxƿ=$񴆐%k[$Ѵ& $Ѵa$VE?We +X;ȭה(Z}sA{V΅vN,/k=!lD{Py%x3$b$pD|\xB߱02 ymRRf΅a5J!NU2&= Ҳ2#E6CLX|b2k9^wLc$Y8bf9[k9?1K&k L U$R /+ZLJAĦ8Ycȑƿ #ʚW* E"^ `FU[s|HQBA)2 m2øA13,Sx(q@R%)J\x*-^ &Y8;9c.I"#d%^!|$^$t jI0IښJ*Xj-"HD> YG#U[OXnkiI44 xKD!xL7nv$Vz "H"dU,_T-sIQPE˻-P&1FV biK;ZՉbdaZz7ՙ%Qiv$RlnRf<)k=)kA)["eL1?H^an&?šHg|jibg9Xn`gB'vf9֘|G2ʐ%~!z$~pn~f3BQkFQkJQQ6Q oWkl,J< ׺[ vI[>ee4-"mDB1JHϚĎך6o}$fzfARz0S)(8Ycvn۞>;N|fdF#|CGbDŚWKhFba Gba< [CTָ3+ TnQ)Mby Il~Yj k6+k=+XY%F{V[fe Q ,?1YDϢDj[sݵ 0_:7z@!6!5zY{$q$qjk'i٪MLtOkm`gBbCȺ !Eۧj6 5#@$jk$-5y4䶵G!ͬ?f0aYQB&RjY5*#":é |>b>}f3ʴX8K2b%5R!et9ӏȑ[*q)I{ !xlLI0IښJ"txB!.DA/[kkU0gZYboqadY.m~4{u[qzpzTY4S9CDoQIxHH^7sS#5 )/(*=]kTkdw_MҤ#B(xDݯIv dm%""M-JXIѷ&!a}ӭ(5$)Vm$%*YиDhǫߔθ%LKEZBpufKi"pGwyyq|#q9kdzYZVc̘XTRW$zo%$10$đx[[Ǯ&u˚=֦|UIRiۺGl{6A3CHbfÎIxmӨ(Yh@RC3XXZk s*:Z jRdZ~>KH|X5 `]m 9Τl$bKlE%&p$Ē\[\1QcbyEKk+_ۚHڞM=ProLp"ux[bmʾ R.&b˷g4g$x[5s[9Sk6QIaDK3]"vё ']Qn:w9׳l,UEfP\iƿʃQnQ-Hl=$1sLQnّ-Pbl9sk9? .qsicf&*kg[ӚC,.L=_  7Hxƿ &Wxm)5 )VmM(ozy?z7 udNd͗ N˛hyp[sx}\/+u ӉCC~]t#[g'4juƨUu~vr;eqS-Ͷ͋c{N_We]q'ՙ%Fq!3ln8/ T -yB,9?u,:C u} _f4_a޻RJh+4?QZX)+)Gv'2.؉HhutNYr B Q&\s)oyZ3/"qwp}'3+kP{׫nݿ.˘1 >7nVuqlW،;u+kwo?hJkL ܭ~u ŰT߸P"}uu\q*VG勇NK:5;-BnUD.+""n2uhtJuw+-q"?+7,\ے-;+}-5|9w+-T4qJbK6ara0-a(<,rDAA$EG`Ib+_S"Er1sSpPP}@44KDfA) nx Ow5܀6pSQ1gg8C1W6z;cigkL;Z2>َs8z޴4eD]VM!?{`01*,@A0,v+# ‹KY$ E@W0S m`0F$b3-4kX/{7`A2Q eŵ&Oމe~pOJX4lȒE# pҭ ti*(f @ TT KS+M40@[UP,F!]3MiQ$UFo<1.4h‰% 6"}[0;'jUL"̩'P00ȹ}m 5  V l4̖LިRǼH7'z2 0DZOp^,:,h `Z]@)zC@wNg _%D82_JIκ8$4cjl+nD1B{0T_`DQP M@y,[`N }f˂Qx3҈_ pC1 p , dt=&hwSCi ToPX"o( MC a)I0OEp`uMgwA(x/l!n@& 19*P~hGA(#9 ] ĢP%%C%Bhx0fL=R0aX@%@QR P#)h7b50UE9NhKD@pv`{oA4.N(f;k+9Xv!-zbc.)!#Uԇ V/t4 q ҃! ^@0cr A+nIhG0)SL Pc` E*a` AR,%71Xm0 D}1VngjnC%hzn_$ }\q2yHT$y`CiD AYC[ɩQY0Q E V|h!pv0 _DR f>& ((.øyRJhScw[*.hg{Ǘm 0BЧr$Ce`>)b9!xDCF*@4(8 g\s;ԯm9VC#:Zh)]]iV#zA!kBGt,hN#ԑ4pu8}]NU1bhLA?$RyE 3bkV8~{9QU&q$gȪ8/ӏ[4%b LK {aΓc0?5,# ?YH>0,fFba n^]z+q "E]c8K':K= f&4CmQ[_]4%t Nx%/;ƝHY .z\cq`-l(䓎]{+RwSX'< &dRo dɝ4h fnAmG4(4C iؗg]#(jY\{Ӧtf AN]rtګANqx9<.:V-Y91!&Pwm- ޯCt4 0=@ kF% y2aXS O@T!0SSXtv4\ະ Wc7gw Q8Uh1FP_S7 t1 ~_ N O<@hB-\e R_Hap<+˧v5j|:uc}eX1䍴bna-DG[Hp/T1ſxp?2'ܣ 7Ш'g骈tID,"UH-D]BBvW-kwWSG%3CѰ0Rty#nvʠ% FC "A F*=E|q; cE/t|?&0@wJ\V4{SV{U;i.؃p:v(͑e /'@Qb@$364\r%/A9AѮh?HZC:TCшYhh?wAL # A [|x6w"E<k 8.5@(Eo AQ LHl!?zV -åahV*yV9t=,;`0^sNVt M; HWA3Is ]s#ㅫ19GUY<]h EO݂KAӛڷehX: P 0/$E/Mqc0Q Qǀ T.p[! xEiKѧx-n$Sp_JuwQ=~Q^ l(]: 蛆2`uFAgmxavroA̺ѷ& +HB;@/~DP 88 t$zX]bc#<8 k.P%pvÖ)-`ˠNȍ@YV$O-Mж@JHD k t M0s^l(rQ/C{$v_j #: s.1GxQ`,uwp3 ʄ)x1ap!PxtA;1,.朏 &jYjƕ /[Qn0E#0r->[X\z=MD4NʡX(3|RAU¸H94774q(-[3^WDqa6vH7Je]h Oʡi OQL-AcD-E4̂Qv,v4Gd~kg,S hDaB A\ᅞ; b !H@!c80-2t" ;P3Pw'  pd=h""1>,l~ m͕^(<D% <B3 +G@;Q&/xpu3M?kvBJ@Q"9,ef`R p:_ b4Ey,܊m`q<Mi,X\ΪcQc5IaZRX)OKaM;҃(keX[7p ZqB0~з+<}0p`58qۂK p4 ̫lY0Oc0%d&_(^# em,2,^ܾz[ƫ|qd~p|xwyww.Mj7Oa!|oKLGd 83aw?TSw)]?}s%qێB9} k=;3 cH 5^ˌrgS*f2SL}O$?3/X"?C{OW>?em˼M-c"|ZJψX{ɶV=6e9VK%ǬWj9Qi2x=]CH^ux:= ݒFAJƎZ5 cR-9EZ+ UV֪lZ^:̯;A9AӸc0W}'M@ޑkN nғX6*PJV$|a?v ;iDB}2{JrG[]*(Yqv䔤J(O,8/; ,bϷL.$\eF=psJv`@n\j@1=]K"0YPX5܍ݜ=Vx\(L-*do_bl_qmY.~6kMHiGӚ6YMGgϪ9>I!ie4"0S>_>ݞsZeN-6$ *cj% N6ZŒDێ$n=:MڶE^mxM?GqK!7AZ"[$ѷjk&)A.ckUOɃB@g>7*fڧYnݳ>=8䒈Hh#^;NfwJ|pYr/sQ 8I` 5\Œ&y↖䡪jPQmBJrTPI09%*JbVUX*YomAl8Jpi sG◵9R^%nZVQ%q`%qjk+rZ^ $byt4I כDXq\Ni/nUSv9% c {4; 8H+ lOԺN UnJ'[g24g2$b$bYm%-,')d$B$˗B/MlL[ }AE!0$bs\Xkͱ܁5IA9$J$JYm!%*D'%)P$@/·sT&y,=]&PM۰Н3UHeFD&k;-CIӆx(q`2I[ED(D(9>zB$Nyt4I!&$qJ1) 9^_x~urPKh8Dt[U1 NightLight.ino]o0璴(![*]>/iӔJl䘱-1I)Ab~΋,Id$b<JQ$)~RE&D $a|%Je6@uQÜHA_$S5飤D ߘ,q22s1q|髤w1@8D4̈CV`14 Ӟc,`l*rwECD5w_wˑ,L. Il)Bɴ(zf1F cI4bT rmQ Ej,rM%\Cl p@tit+$=u_7ŀ)3lJg)x韨aekdƔf[$LΚI;j]8C3E]FQے*3mJ1=Wd^p Yޯ"k a+f[3?גsě7S"16Sz`z$64l8EE]zѮؙʹgsa{#+N5nO(xۧ1<PKY8D]E_ NightLight.fzPKh8Dt[U1 ENightLight.inoPKwHfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/PingPong.fzz000066400000000000000000001651471250202676700324130ustar00rootroot00000000000000PKV8Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzp[o6ǟOayEQeQ\Izҭh{2(V ;ĖZq(Њ<8&1Š-ҳ'At}v=y|%Yx3\ff&u [7SCCuxEiV8w":sfSgy"VML[A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$ݯ0 㻋~%t\}|SW-~𓫞z~|E~gZ=?}#ҿۓ_~Uۍf?q^lq7Y5Pp}~CZR`-}OJ;m߅Wx7 X]?yzY]Hn}njEK 0ؗW叶m?s͟{O|\==^>_(s+|0h}'|ݥZZcxh>z=Ěٽb@GǻS=ڼ}moh{0c3,eaWl}i}דsi8gqH`}R* .8p2@3d86û rf3; |jc\M{G\B{51.619~cN0=mG{ ScS Sv |Sbkm`{S@np7?+p}p;5OK1cKPwM u 9C#O{w'J2s‰_mw9.f6=5cliu!1@:W~)NW|%:c iO<2Ncl{N{Gtfc|0+6 bT%5C-P!j 0 k XkyB + *4=~@@ӊ @ig)0'Dpϻ=Cpi{OY`== @.&lxϻ=:І齧Ξ6T..lxO<lO{u i{Oh=mp'\DpϻX=?pi{O`=mnנ3 =]xԞ@ޛ(=%v y3/k2JC{.pxϼ= {v{{qpvw3pm_ V}>Ǝuig )'Lϻ !>CCi|O)p=b0>r . nϻ(!>)06..nO?i|Op=m~)ې3&>]6x՞Kڱx.=@v y3/"m220C{ .%rϼ!>r@'{ %Zu'뾼{|}~Y5X,|O?|~u;@ZR`T[6 ǯ}_^W/Wpxur?eu?l y{|vvǯ/m].,0) &֊,0ݤ6'I`m[3w/P)LL| o rˁr9AgA> <$A&>le7'u4Frr=AgK:A>u1s |=E oIN|)oO|R wSߧ0|v]ޭEnAk`o6c@;3dxlC1:tpQC1?7*P{v cxXdvdꄫA+yKX ܿgU,Ipc|y03%yJΖ7/ soB7٭6Aev+{{ߓ7 'Μ#8,qBroϏÅΠ#x3SE GQdjhko{b_\^>ܬ^_^qy'?*RQb g8V?wTMCZs2LIe_9OC7ݛo_.Zk_zuWMpk{!tL:F<%՚tZz*3jZr{Mi-I#$P2>$gÎc7l͈*՘k8 ]5~L&HX-Qc2hyr0eNntԙuQL僀r"vlQkU|DXG{[sC!0<7pv}Sʃ'H͞bu$f(c:~0?PF[{aϕQ[FmEnŁ2jFFS_ g\#uT] Qi:5=Lc`{:hWGy9W8, rJpqss=0YA1ELi޹bʨl4S4Sef*a~6]I$7Jeҳ`ܘsgW{5LZ]5Wc`F[ӭtŴLUnx7,*0%G)Ej̤tH+.5*]G>:ŕRf4%T ZQe/qG{[sS)0< k>Z̤\r P*6 ,FyZr";UVQ.**2r[$1{vUp@KI!7Q rQzNV.]yu-PF{[sf;9$:|>! e+JUҝ}zR(RɮfMHdB2?!hk+5n+U2)k6:J *TrT;瀔RV*(aZXT֜YO`&Itxsl[gپAELƧ"XL$='C ;=3ÏGBd.=2?!;փ8ku˸n{JWy]^ӣo~_~ {{>+?X5FX)J^߲!o/w>W/w7?8?o7zဏ5'x|xo㧇w?]?^~ϝPwσjsy?- aLu.W~{"+V3~aҹXAsBD)c5HQO⻡ӛoxaɑ$ɴz{Kݶ^f3(iCs98f gqw*6ZX>=,dA}+pO0e^{U ":@FRы!*)VжL&@D{|Hߺ|sMV,MfZJ sKf ێq .+' T\V̍\Kĕe\K1|Z yEP 52>p .!BPv{)Y4b+P%v޴c<1Mf JXHYve]UR/VD 4Ep ݚIUxӹtAHcX5 Y˱D'), Y oD-o, YPF \J,zڝoyipW<R+{ͳscZl֌OT`<_TfeH%yLhK,vs9fIf&xA.&+N\%E7U(URC,q m4D0]2!HP]8[GU,sVh Nܢ_҇@8֎R\wёҖ&^rEHm?)vRʌagoK7x[ϵA-!H'mO|+q=w~}˓W+]t};ݿ>Y„vjoWw|[^s"SBybyMiW>,akY!O w'2"16W Ww~X)׈ |_^Gǫۗ_?F}=ʷ8d=ݯ^B+׿Q_tq˞/^Óu'P}Јa2sEsFM[xK<><\[ b]\pI!0pw)'}M6}۬ȩ.m8F mr*J)DZU[0؞>\|SL.p}WƟ^ ?' ~ w(˿޾<8)ϴV}SMh~v؇gK狿O8 4t:0M?G^x=Oy/l* Ne7&)ahGosJMfտKM{L튪qOl"GḋOW/ǽ8 ~VB{P1td7ܲim1<>L[Oŭ3f0 rI0u]u O:ǁLd=(pa&2ω oSmƙ'< /m!ΫsI!N Hnz|$GN4_P~f4߬|g1?=> ({0; o&c8ܶ+(#e`ј,Ndb魣Od=` oX%72 ]Ϻs ܝ~vrD}Œi|D.$?1a| Pdb *?Ӈ؋4[Fu'ӣut]u׉Ko.DOΨ/l=1)0یr;yHq+\ף/Gd pur^ok;`1Ds(bR-,^?Ȗb8H-l=dwI[^<_uk8yfrF7|M4Wnc4>ƿג;KQ2_><}ɁM 痗a8}#gQb)GP(̹|M>F'88*~ `~Lv Gb[Fx>v41XurSz%M F#}MD|!R'˜:/0ǀVQ sĶX6ۍo0,$/rfQQ-mWf/Ot=8Y`<\3}$)%;F]r7!NI}g3 C|%*s2x^E#βؙ+Ogʨ0GS!v O;'@Lf'Ι7Cvc}>G61sOgb7!7b3?;@%&o(Y!>R̟:lݐXgbHkK3oraIH/Mw!}<3Ce>nD}hNh%1?@11\ӓK̟!;Ac|h3@L8Uf̀~4o#w)>3c3c~*< -6"]Tҭފi眈W%xa;>ixb,vY쑆(=wѡ! };a wBO^nVWZƳƲ˰p癿ez^WUj >X9dg8~18kCHzxKf?|S}.n»ۅI1V)a7zoKbѡRm.?==TC(sQ1׆"^LV7NnTRG$`dG/]n|ٖEօ5U BI"a%3.)a[i@#^&!bF`cGjcmL[J0JIr!<KFk**(dYQMm^zQBRlt%"Ry ]4$a2IΌD7tA7[͌|CQnƫ喊0ĸU(foC1f޶4dA+!heX+c2:ֲp3RFXB|RHϖ1.m!eF3/4!Gfޖ(c6te$ AKXeFqJh 22F4U } 6=}1k>=ʉ :7E4GhyvFyCV:cbi0i5 Ւj~tD*9dd~8mZ"5C[%zzI&&+HSSw.'$ղ!$Ug>TR'5$-\O=ު܄eh&"DALZ3id>Ri_0,QyHMuQ)üӘ .L.QLaStI&6'GKSt4z/͝᫻^jhҺ&%WD^#Tq"U8(he={A1u]>oWoC1=3K3 jBU+c-=/sIB : I]&AIG g(7u>NU&ECvN^RyC.892q[fNy S&{*H+xJ*,Hrύ:*mCW(BHg*[Jx+a3,l3 m0ޜW]:I6ځ1!ȉ#*c9ɂ6:WPR!eFYKʌo{n8J[(m)VKni*#w>&Vhm1 QJEo:l^D1LUI+"?+ӔH3C<"50Io3 ?3+u!At8*;b&Da*:d:^21a'h` LIy`g .$T QU R5Rtz/!ZU{#Tëo٪f!¢fB5M<_OyJM< 0fQ errI2?%kGU,> l rT+WT榸rqryrT"RD #Q{[sC!0_(R0Z2M.lL.-nCEk$Ap$UJ*d:~(KPR7:Bj歨>|S2Y( ZJ,lY¶֌hum/Xmp)*X6O[ִO"H Zmǵg&ZAе'rs@X,8)^ProWpW|͟i} ؚHGz"UB(Ih2#3WT9RZZ5{eyvL }-!O> dP|i3nWr5ʽN=) Сh0to :5p-`@euNL!T@85$Kh$T#:ޞ6Mr) 5VT)sYM(%z"=5Ǵgcu=?YrcN$q*D;\rG Fl(ךQJ$;9.5=9q@A \UbhuyB b)(c%_CНձF(#y힋L}]/0!VQdY2IT<~f՞c4l,XP7a_ [5#emeaIDn4 [HJ.ɑ),:U !=ITz7_M% q{{[{m[3>H05([UEinޚeIkU}-ښ!r\kmܘ'lْdl.[*W6٦x9>ET]מTvkpW66 ʬk>E}y*ޞWWct^ZV沫`$dZ AKKɏtա ~:-dOJ5֑Mvk'Ykg&ĊtHK2rqNJ(HТE[3VAeK0bcScщ6!*)V.YwG)!(e֌slwdL62u9g;r$H*<@/-\)Դ s_ӵ5)nWҒd\JE" F@ȴLbDڭI\Qk e6ۚcEs xMiH%fhd"z\MKɍE 2Xcy9ZخkOZX5WжL abg6 p;w[El] (s߮@Z;4l<@2ǡHYL$gc,%BgչUe쬕]+٩1-[ vkgYk3J=p+^SFenYB?-Z3Dƭt5e z8Ƥ(Yjj#/2eXsLƺ#`~[!ոv5q̻ѶV:knfFFi5hxdI G 8U(YrEMT;Y{[zh\siAek&HP ʖy#ZxSIisYhlcё;4 U4k&3mt%EbL6|ݣt6]6JnмH i[$l@T2ri#*/i_jA.O2t*ƿ钑ϳZ޶;a(zn~-yÀ+dDD1ẘTf~xΦ}yXo~.r|}ΩQYrUBZ&FF+HmS?=.tt$fG*)U"?RA+l\dtlOmdf-1 GBj*D*; fҿXi?5ItRךKVEFft\N甜U8"TWD TSdʮVO%RKHTdPzi駆:5z)Lq5r+κ ƦEϬd\H熔ӝxLNJsA-V\#FmYėcğJ3OX ,揊h*8X`#ZYU .47VCC'D.LN"LI6C,sYSc*UBE{2zs$˨0uR ,O_UC)mY(PQlT'#eJ8Z_&(F0FTaKj +*5"KzZ='.I9ȈtRɔ{8CfvR[QRfEK--,vukݦhyPil[[0^ZPR- ;< tnK#TbyI9cz)d2=a$3S&ȓIuMN e6DCNwC rL+LUȷAhu㵬ãlyg3IL?VԒkunaGڣ0:PM&͞N%Te )dZ>]3Av򼥏v)ޢo)%qMrʼj-#M! \ >9*Ԩ0OjqiJe4CnaTS{AC+." Ugj `aޥ$Z7v"zJ{)* 'X3xO-%T*M;O$Fz{Pw]׼a4Xk{@1TZ:V1XNrJƦWRAC uIf91$hKI&Cea.T *D,iey5ϓO{>dGQ=Йt<@ANf *XA#1~|GNmb: Rɢ.3/qq*&x^zWmqtkqryB𗃙pa$/3hjE]1g 4 Qw6FV[i{~h~XH) ndپVmJU#}n¨buɪNk- xm[$2D. f(r.?Y 2pҬ5lst=+}2J)Õxd%2vfesk{E#ͅ.BW+Q]#c %G G$Ȳ}Whmi}|5?8ڠ.[3>CҚs4hVKr~jZI4NlPZ%SYb  J?6sCݳ׵sŽk4^z{{z˧ DS"gSKʔz{Tr68 :I:, X6nOP]s rem83$^Q} ^y4NF>%SB \J,ZeȀSt(Akf|uf˽$We<9@jkP3ź +5=;| P'Fp>4s,a.)]‘:ub%(v$IVR79/uyRRY'KCb]IG1IBS9u5#\B,lZ'ѾtHY4?AK4vkƇ .u'3[PrϖbJpIikGaispT݀ ةhXdt,[D [`$AgΦ:[]@r₿)+(S)] ("^m]o+'n)ilf'(p X+o֌n `q:Uyi':I-E)PfOk{[j:/Xۙ 2)˖c!2e.KPڭ'(sݮ@Lf5(9.ۗm K# qNDKDv}M:y4f&@Z.-o3Tݚ0&@t6UYL8X "dV.3㤤x\_kF;Ѡqlc/AJ0tIX3Y'+(u PRnMm"D\fSӹ۷:,\5XvB'֌ %S8#Ɗz&Tۀ6KI",;晎%@9I̩ 5M3Z|.%e(!.6VH OkHhmQk<[J,\6%@ .[3>N亃qcM.))NDhiή(7!5۽ ˝ XIU{b)F_-%Lmo*ä-CPڭ#m8f6 }yP+!6V|+36&(sy*c} +p)lc(r X.n &Xd2NR@-!H߶mp&!J572MHf CnR% xF8a2?R4CTD,Ye¥*\Bµ.(\CݛN%L3 ¡pb֌T|(d̢kQ5i]_PDxk8myPAeKēe+[T@SK4-Sf[r?btBpb K: F܀A"^i<-mKGiX/US/(9,8sT"v [faps587>8N2e!l>c6^`P8i\ 8\7~8Otn0Yg%G@AG2e"(k)Km 55H]2'R:9Z鿉/cԵ,I\kВ*OK5sn]kGEŊj[@[J,{M曤%` [3>OP溃q|Za5(n@Aa6e>)T--Sbo9#TIqW\O2\4=; w>Ժ1@N(SCF S;Дq$:ίN,Y7KAKԹvk$yF+`ՙUNICX]7DQefgsѸWVǏBAu\Re+t.d.Oڭ)H3!q6!qLNPk/Xs\I}݋p:c"N'pѾHY͙\Ը Akf|ug3k\}塼p:ez b{堿u ίp+dƲ-A`eBuUv_|)#*۞\WF;R@qlɅsuU .dɲ͍g%@ .[3>NP]s1{ɭJ3?@MA:T@̝l"$N. Sđ|r PY͉0Akf|uf˼$WՁR0#'8.֣`0}\8UtCq,Vy ]R,Xe]R;$].FڭIU!cf2BB~8.z> j,)3qYoXI>RqZy 1X0x̓Q)PQ kTQMp47V hk; Z",LZ~%dZDDfYbߒ q. :!.EUDIzF em q&I_kkt#J]E:[Yݭ]ELֵ4Yv1kn▀${ݚiHp2©))!W. q!OrkXp̭0@hC 9OYZƊ)@:[",\Z|2[Bm0TfQƥ"UmOHk UѪzLj0FBXi{v}*eNF)lq8X{TʢhUD˥77f4;'myX%HYj79AK@\nkf|`Z 5,p,˻TaL[lxrU& Ewق6R9]kF0 9Ź%qMѡp "Gs%mj XPRBeoU9 S$Akf|R\w0`r&z$*O*$pɄi8` &#E8p@P¼ 7i,G{LLe2#AkK@̝LH,l{%rU%[o/Tb41E~z@[J,[D \[555h˫qI{8"˄E-.ښ''%DOskPJ58\AKɔe7GAKtvk \{0AN X<#l(QoHiT1z\ofcOisNK8|,а:qi%N*paK=h0 ('S}4> $s8qj$(q$ 3DXf8窴sXlyoX6bͳ3X++Q}΁EIF)eCUDU4|$vfgfi{ȑÉᘚ5AMK$̶eivK--qHJvTp*[TXӚ!bYٶ^q6g(YfwYG\@2[R,vd% .[&̶87'#!.Dp>)b%[v~e֌`Ͷz("ñzs.t%BDzlIzZ:[B:[[ &̬iexKaL\ӐIFgTCS'e9ך8٘+Nk{]lOD S%,J%.J2NNWڭ(q[]8YA.e9*GTnBw2XlP>N!2PyR<٭dJD2Ԫ[ߵuKDEk2A_K\qKTj::PL[OĴ`\pf,P5=m,Ckn.<dTYñ|4,vk \{0aI:g-e関~՜8Q\uȫ(6.Icv/D<+pn!}{ZUߠ \J,[x9 \˵[3>N0lf+cB[ЦhBw2ǢI}@8.8sR(EUL6LLDeH?AUKLLn`KsY-LLڤR0P [^(j]Q+wж&w,FK@& .ɲMf%.[3>HPZ])B$ͫm5RRgXr&V&;Y48` %ࢭ) 3;`j+DjH4nCG}מ<-%G}J@U;%.MPڭ((q[7n72K_d&M:ąN wlHM:֌ǹmn@PB[ogxfC1 -A012!EPζL"gP@J!q]Uߍ9"C.Lڊk}מFԵYš7+AsK4vk m %ʬo:R眪[RUK32Pmu'o\J $2uTun)鐉dkc"l At-iڌN\0u"pPlY !Z3 Hj(j伞mQ"CW\fKE [l)#j k֌ϑ_wھk?]Gmw?>ݯ.^~]*eC+Md}!D ,QYli5aU=Kf8ѺՔ)_]57]ϽeM E8ʽ6|#5"^BZbh7P"98 s#I嬼AD]r˪HFj311XZ %&Ujኪ"║,q)U0x16 %HˎK|sO%d [k=rϷcmFt|-Sh6"^*`NQ5c2fƦJŋ؜ )#,Y|,vk \kձKG(gn/&%Ɔ|MԷndfof)[G[Yɑyh<\y"V}$n)!lw$n Pn8Au&nfWƉu.ryHcIu?)`~~ΈU}c;{@PNj+i&\%Bd4OaH%4.n`zXl>fDtf=+e$1~p9&d@q]9>%v_z{{z˧P3P ntCLsg\ V~*B]Vj]Jp" ,PJ['ힽ4p3V㨩rj^<5^op5 Wp5.%S'QPeݚy2d.1ݼ⤵ĉj%9q,Op5hάqHmΔWE--eJ( 7v/xnjs*<ʥ$ʲUNdc\ȵ[3>NP;79W -`he]J<'e(O"mX0E.^#뉷⿑qT9\AKɔe\9 \˵[3>O{7p9ltXn)KT@J$%>kX4hs19:<ΥʲuNe\ϵ[3>P纻79<(&(|?)#ZP)-GJi}w@!e(6'_v~PYAKvk \7w3}\Zё( fX£#ۚ蘻A:cݍ#3my0AoK e{ILtAWkf|u j6E ʡW(q5cQꚈPA[uMRdٶ)L!Z5SumK׆G2ZT9MaY[{ 0f$4RjHۚHiB&`(yM\ -72CV%I%M (5h0ʶ #"S=> ~$5q:▀#(n֌<nlt4UB'\84I'~*f9֥'P̠Ac2~ힽ=> m/+).l*" w)rhmI֖"9z|(Aqkf|[ &loU`DgJPZK $38 (p (n$f f2[tEJ@'q6z楠DZe,H c #5ãZ3Rʂ@JUp 2T$4`ʔXvJo6Ɩ%hl֌\rvf3kFv2ehm."mXhm`" {>no}מԷYl(A{kf|uf{s,WԚ (%%_etIʐ8֣Hk@v/rqDPR׫DqXT0Aukf|ulufV7!r(-TH{!٩v[bh3s @15[=3ÒꣀG*ESMKP`ݚQ{A܍evj q}QeEƓ$9Lui)V*kHQ.Te@KHF<&J8m2(m}מY[](ˬ-LPڭ(5jFH#U1,'46S\uk8,C0Nbɰ]{DRdƳE`}ݚQU|Md*|=iڽxsY٢DJ'#emHs=hk׭ )ъޔP MR4'΄J'(oY#˖7qb &p֌Tn p2|[OC*N:(X̝lM=DXuIµUKG (IRRd %@ [5ݭ;"Q)a; 쳘F(Ϟl-J'oYPƶ<DzMZ[3>IPֺqYәe-O.5Q'4km KthkJI]  $# ίP#V7"hp `n@A2!d62ɻvJ=h5$¹sj+tkXsׄo](o9!˖7mJ%n֌Tn n6 %'8qrQ”+>BeX@{fr̘,:Q`h"11 !hn)ls9g$(o hnDAyÜ2[\ܨ}a.J7 ĥ7p̯v^H>TtQƛ`Qg*<ʥbv9&hq @n0c9W Epl_+<FU(p(lvNsOooO_{{tftc0c1C霽st/.S=l> ҹAkf|mlnClseιtD{\5Fuҹ*rBHcךqoY\U4qP=+p)n%q֌̭ܒANf<̕1VK9RG@<۬dZ8xtݢE؜kU3mNŗ1kT]{XPRBe:3R}ݚ>99窄t MJJV.qm 'I_kqyG:aL߮9e iJ,ͲstAkf|,)=~&: ׿xI_/~Z==~Fo.V7O?~Oo7w^}o?ן>^/_\?7WWۋw͏oo_\]gA^>^}r땿*\_t1ȇiw˵#_\??`PBxvO/xAh_\ ן?\Fx|秧6SJC3˿(~Ŕ(4w_R/O.ΕxOsG^a~ zaՅ?^1?`€xϫUһkhC뛿}|yX_Eݿ(gˬ^~a?no7/WΥD~R(wu'U \Շ_ kaύKJ`O/Y(Hm2 ~|RnY2F?) /.0jc%# nhkm;$Gо$AkAώZ@I3[5YYJ5~Ǎ  3]Jd03s:qRRo>K9Ru6ḐF8O NJ$U|X1@GonĦK;mI&?×' .6mԝi$(N˜}iC*U>)$&t,,'!0E$']4.`*\<*|7r|#7bv)L9ƿt=6*ĝNmo )]g pc2 g1W&x3>}ϥxV9잛o'ND:oC-٦L\$ӑP 1#BM}V Dn"W&ݨ4I)y`$I._My<߇'onXHfpg 5qx#Իtw;h$|ho*@e`b/j:?\(i8"q4 `&#gzx$#{0Qh3ek@Le3L \ U m{a$)46B+x%%W`W@ ǿ6lL;p" n K`J@ϒ~g־Hx3g/_FGNL`_>+d!(D!Eq0YN"?>4P3=1&Њسb]Yo(Xq|4Ƕ.ECÉyHǴ8iI"PpC:˛[=#XNv#NZndՁY?$Btp OI^tV4) !k}ŏ@w lo8*q9$yA(;Vf$`0 EI(P:lKWy;;6WDPr69'y/4g)Y1c¸Wu;i t6HA07}{\HNiJ^b#e0kR23HPZ̦Iކ9th%dn;gmG<@΀Btjz,%34^ hyPSAKKJ(r[>laY G`D iVUSHmnh%2LKbhaֶPj`=6Oxq1X]g(O)*aXC!՚.ZJ.EхB3WvĊ6ϒgP. Ie H[hiw{KbDB$IN@_!my Л2<, tl 9]`Tp̷ N2j[jf1Bp` 3vS| M+I@C fBހRZ `LA[Rn;DQq3rJk f9˘Fsc >BXIH 0XNPp̙B o4'~h۳Pbl<0mID[f7PY5_ GDti,ICvϦ+> Dyrb0_3`v'9hd4H)jx,EdH6D6H)Yf)0֜~lV Ò  cIn{"_EhaK^"p+K: 1$,ЌX!bKGot%Ĕ"Se)Dz6Ar2,P86= G)r^2Y}t.r>=]ƒ:$scgG3aXs,n?3a.$ M&l0K8 aM@6O0m|X PgWXi s`4P`xI5d)53u.&ʁb =:{y\r 9#1vbs BfU]`蟎%Lk)q*kL9A/S-QJ:MQtU~N1N&BR ?CrLPw')<\R'#E|d :&|87r,3bᑃ6.tqE~)vbeɛ_M˷#d"A>l0T A<ҏ D[,oA=`E{"}VDQ'8]t'TkgCu%* E`V\RIKЮ#A $(Yɰ|Lyf="'>'bm9]}Y&^|,` bؠ0URcΪwra_q;EsLFxB?dA37 \%WP?g#?(ܠ!$*24`An:$B DŽ{dDs7rm$=""] D6+ChJ#6R4Q0bW / 4,@S,6V90']/NP \w" +VlJC@s@"+̤lರb:p"j cpIUԜ{ ׻h1_ Z~gΥ0Lk&e|ۇpq\.7Qᆶmd/$eKK.P >4*B< 6P?\ᶬ;dž"B`9L/bY\%KB8[iMw3~L8qN: xq Rw Yy~v1Y_&*+gK Ёtܘ&Q5T8 $IĵWD2w-(/k#h^OwY2Òk.ncn#==1M beOA4alAYzM΍wb&Cz9PreΏO e4N]K\9e pp7ݛ6X)Sd1) 8h$wЅq˱ŤA%Gm~Q FaW~/-hQ4LNˍKl}r<-_0S.g.XSM3UPa.46A9%r=y M\ ڐ(`x"oJ}{閖oոiX̠{ (9fD`/&l؋𘗶`I%+Q<M88]͐ۇ.Po4~,Ez11c\Qcհbŏm{n6Kl;/%a"C??HI|{/FX_m'űi& u8k̄l!u.!.6FD}~'b6.[kFUҜL80yUD gU( %CϻA랊mm^+;P7_Tƺ΍X3۞RCE" Jp[pO2S-Fs wf糧KW*\ 5s3 N Zb^ s~)cF TjQbi:ҨNt(TwDSP ;"Tn<_rdcRD3W0BAec*?\7YmC+zYnݭo1#; gKGhn)2C* 8/uFi\fR;Q|G@Rq29 #rCm!4R.+`USx7gしX5isNfatiؓ9dda,#p؛Ro]t]sթ|=̀24 ~ #LVnEd]'?T,D/MsꝎ eq?\]\Z"JnDw;Wq`c"=xV.G x_cᚂ֜4cҸ%tDkޱB beYrVyr)LC~[{7>Vftu?]nE^,%R4q|˵̅luK%!Waw.o$q٢b/}[ =[=[rgC[4-$@ܒm7=-b/%=:T4z#<Ʋ}ar)v\D8ؖxd\S./%ר㩧?>|i4o|C 9.bvQ8j据E͓t<쥠ꡳꈂ[?: IJ Y&K䋇]v)j%1k_kbJK.iR;܈qʣp<] k8bV{/o~fǿ߽nǶD۱4Ϲ7x7.sr~ :)㜻=[aN4#cw2-Ruu%t;'hzҰ+9p1.he#O.cIS| e|3~Rcx1_ʗ7yJS|n??sV%ʭ .~m_]1߂.ZtQ|#ڼj/ysx߾?/I>Rǟ~?h}wϷOjf_>v PFI_Y]]p,y\SCxhw$!a^Ƒv>ӏG??|>7 ~־c~/FGw%yLLFb r2ke'n7w.[twVVe'+S]Vܣ[J~~Waw4~MWFa=ld v`3;G&ZIgYAͼ4ˎU+an+L|LZ7ĦWZ'vA6͒)Akd(9+\DXtƌ@,s6HΪYcVN*N"N#N1.s~3j]w\pHSgn8Z3"q/,Ig(ѭN'es gUܓM9c7 c9e6qt֧Z/,#g'(ι}pñ0^ͪZcn 3;g>Oj]jFC8+aY73%ukL &t9\Ei4}łW"/]H;wAi;'\j> L }QUd0u'GQk eExQXJz4kle (_E*^we)Ә?vS; gN|v h AuF@Kqʂ2Z* 9ҚH7̑ iVm%қO?| oM~I'ٍՊK|qȇg~ĘǾ_R/oօLW lͫ[d^I:%UkvI-A[WpWO9--[zJ`W)+pu:}by `ҜՆ`P &Vk]'WWO髕Aymޫ.o(V׫W8Q[J_]q6GkA'`_۴Iu0`R.tڲ&%>JPaխ}LnpWpBըӉVnS8:+V';2ʫӧaOmpۊidNMf]s>.ӴjfDyB9v4l϶bi:{:{DfZ0u5tL43/ [>b}m}v_G7\hU듛rzO\'76S+ԧ*Y<'YFFyfwgp'WO DGYOL7mYOQ[2W'a9w,p_ f} ֮O'ΈH/+LW6>~p˺WO#YӉh,s+V'{ՏqwrxmDt&h?lqýVN i':SL3S?Nnb}z nl7{cu:e3}>7_on6&wu?΁?7ۇO훿>};_^+}ÿNyŰۑftǤESwX;gVT1y_%MJ߅؜RK0I>$$:L>}:[Ry-ͧO)᧟ҝ?No$dzfdWMγ{|.ݶ$>R4UgbS %fHK";)zQ>'Qtxzm6>Q-Wrz)dвQKQ2o*v.X;s* Ç8V=M\ j,(ZOH%x&u!V_H)vQ9iBqTÜA+(N.ZXI剓SKMܺin11QBrZۊᣫ @K' rC:{fl4KUKNN'w(eq vanaaTmrL59uMm1&C4Q`[ O@:UܪP*;霕9Y2]~1"~(NN]NÙ˭*^9r'WnEq91Ef-023TN ;BS浔*RUi , Z'saaG5Oj4eJx%sRUIuF3Mvߦuߤ ?*1=V'u m!.DmxG{Qp4cGl,.Te_ *-[@6JFGs~sxRihRg"+-)㞆;@(]TRm^HY9ۊArhfZ=l||M!-_;~U߭5:1'E__ӕ搯ѤfEWc}̐RعHk$|2m#-HJ|t镛){/&Vʶ6|֕F3/\ֺdynC& Qn proτ ɂK-ac;M /{MgđJՆq)ṅZ]nJ䰱r'Vec(eCeldlv1? ]~JO2+l}yNl.8[d* C*;Aj mNx Mn6Rٞ2p307]>ڏSn6,Y\2m:4~lKWIǑJ&GJ.*mh kM3Vi}hJV.G [qǪ('Ъhy*)#y ..]c@~ccJq=#kL+ KǾ*ض:>* _=TXR'X1|T6R9۠8ۢ;-o+\8懕]Hc/wINrѣr9UQCbOm-j\l8!vƞUfQ]ڛrTVpTNfQKl8aW-uqm^"3Ht"@/xܧ{`sW<:i<Ko,3.B4Z\i٩>E;h%Di(Ua-'fZ^mfQ `ʒRJM6N &swڇ+JkN_3~ugӋrƶJ:(عb^'b}&X%TsFW!Qe}l|D*);*NЮmw*vՂ*_W:s+~Y@lqr8̄$uvugj@*DHs5[JXu9 +*4Skeg\UÂnC' b9J*gZfzXyoHBxR9hR+W ŭ^$(KYY^HW6vg-ftfek[kVHG.ǝ޷;K;ʄ֌'8'TT69~a\b]#Aӗ+j,A+/x4C85l+vj#Jϳm9}ej j+kjc{ﮎ5]6)Svghߎ;쀅qDؙ @V5n'.\Y*W**O9"qj1D&'V θ{ؕ-XR*H^MHA㑦,Y9PW,up4#K%AJ%J]#:'TZىd۝XZ#N9+F*sңѼërYXr\r8xrN@rr8r~МuJZy҈UJZ{ZUntr8]˕F3Upi:NǔCj%kԥTF9RAJ唓JsIW wͲ#6 ;qk5I'Iʫʗ_/ %eaphjc* JeqIeqsBIm|ݻ[xSV}S< }gZےvjkߛR,؛YS*sTjכL/ÕJG_L0JpoߐåPK]8D,wQ! PingPong.inoYn6S&k`M/hHGQ OG]lDXtMI-i2A ~LpL`?be) `he.Sx,p<|w@lĔ7/9q+/|>2g0>9 Oupf4A1{Ì& }pfD Fzl|t>=ۅ#u}|bmHQB#qf {h?݁:6OmB-!aA'P7rrv1GMc:[tt$ :dĝ1>+[tHsHzCAf!p$D^,[$O8`;Ǯ}ۨmh馝}ĺsڗ෌}b튊}^'&"΄.E@ZykMX5pr[{ZV1$4)t U"$ ;d"ITXd $I:]aaDqFRsB#6q0"xqF$!qprsR9?@P^5)Jx$kl)P5իGos6YaI0.}5>:|f8 \*]C"N2& cA 2IR fY(%"w@b%cjA_{{-嵨9R9A,LS^>tq6_<\ːyCɥTr)\vStӔ %,$B,ȘEd,$)t26rJ7\AbYrnEa\"{R }bh~[vcAF_QZE 9IT2{D"6rVޟ}nljpZ[+RZnKҸJ R ~ F$!*J%L,,&hՋ1I}kElSph´:^`39pDtQƵAh\z)1E޼V6 ݕc owJ #3aW^) a9OÝb2/slw/{-[:nw;0e4sNgEӶv)ˢ%ĔcYs'!{Oe.͠WQUU ]}bj}| &4hڃ(hqf yYdT9Aour !kg$9ȓkqls7 xWj?M{o'x&5hpz8Fp/otCu !9^V*+ C=%w6>- in+Y+b-)vgY^˖ͥ!w=@u[J)Ч.eİQ|@\NrRه7S>#%z  Tt鬕,Fɒz;` JwɊX*%ܔo a^g,A;cj]5ol8U~y8PXsLbXv]\(D֎mbUqݥWZbUO~:|ԺyUͫ?ڻy)+b tڠ9L*Y JfKIY@f0*c5Q+'p|d_*7OLjma)u"{gHn ꒓Ohry]r%R[рFUPKV8D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgoO8)|$Nb;eeYH+ݩw҄6R7~)&Ʊgf2R+>XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKV8Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKV8DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKV8Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPK/8D% %ߟQ PingPong.fzPK]8D,wQ! PingPong.inoPKV8D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKV8Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKV8D'0 M7svg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKV8DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPKUPotentiometer.fzz000066400000000000000000000452111250202676700334360ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPKh8D`G#Potentiometer.fz}r#G?`3 ZVI-ɦzM} XD$$~~FG&2ą=SJ{D|_{G FEo8܌y4_x|ndzOwXb eK®oEo< ?ʞzr|3|y4o>'g1ލG7xv?KouoHwyg/z˿O.9y]=^/?E^~t)`ʌ5_ѕtke9uq6dXǣ_jo!|{z~]݀T//zWß?O><޼O[mi^>?^w_}~ ~Lwx ezyӽoO>=M>x|M|Cѻw޻W?P_הßGio;d3W;5e(,G[ڑVP{c c^S5NۋpǛѯTn>]/+mKO7ח۟Hn?=UP߾*Ob_\W -}joaο-](zl*Jy "Zo^PJUM\;tJT=%1ހ;(W/[m{ub_.aeyݾ$t^GDk[Ӻ-o8zkY#y/?ïȿ-uYs=/?0ô6wr^'M_)omx#cm}nC61>tm}%~$%~!Qx65afoHѦ%&'MP'M KN;1v9ߐMKO;'[7$d[llENƮ>u5%2~O<[DŽ|O&⧝MSO;)vZ6M?rJ!1vj6M?l2?l2?n(ߐM Oy6Y9[{AgX'agQY{LXYIS{ʇ8Dy$ gxx?_Lu8_gWޟ9<, =KKwћ<] dz`=+/oU`]>GF+5|Fg5Ll1 K3e \k_Õk\2NY;Z=_0卻;]_ XpL.?XHQI{Na=Z-6`\_7$g4&?`Ԇ3^BP^ѕhy(F|b@-5gI9^Z^k: vVkб[Q{kFQJ_V>.ȌwWeuNc.w}Կuu֞@L 5 Hڮ0$Ҍ"G#q8@´샖iiL0x)⣤iP|NK/-ܸRN+ b="/ X̘%';z ixUQ23]LqeGpSHGׄrbV$ (}bt-1uAHDGH k^UǼca6"@HEÂ:<}4H["MH:2]Q6Wd6\KRJ'.{7[xT"L&8B3V@ ?lE98[D2U<8l̴M:ܡ\Ze5' {m1O*"ә5z!Uڢ p7Dv\u*et!qs !D($.33=Z'GG$nTNZ6QR"d&zijOn@NZDM/,dVwAX9eN:-OSxG9",WI3JN!a$,DT2q;8d&mN/s6'IRMFsmuo&9VH= xiNyUmY#5UlY$b[7\ZV;6R8#)~X#D:A,8mfn \YTc݁Lq\w*z*aw$1 FXFOߴps;m c"j8 }B$|2-9\%f`8von3\S'd| \DZB><}  FfׁkS]z]LJEf޶͹CZ#w9͹ÏZĐ֖E3[c AD6>ޕ^fƙLڒ"&{sSM^V|/Cj{%h kC4](-dɵmy3LZ\FY$6Ebx 8)#4UJfJg:P@.>y:PjN(! (㈣ Xb5P/ܰ9St KtmB˹·M||ޛ,\M}Q 1NV_`js8;L 3ZܬLj.IP4Yp.i" *#֮B=\(W@)4+ĵ )gKuP2kI2hi\>h\Ǜpu 78"knT UrpԢT`by6޵rj-x[mxr<4%ϋk Lλ$Ӷ6#ϋkCr%r`wv{geqŊs0X B*?dR%(t3eV$\"WPJ"f!q%gĔ&p]:)ɵ&9W%hsJtqM\6n‰Ѡ.jhcexœKm;4 Q;do7əl$w=23k8rEUs>uJ옏:( 1ifa O47v7Q%ThNHyڿ $lyXk.G_-E_-bF_% ;N^[o-qX[-#4}3=Rw&e +9O0yĬHJxqZSi8QׇLD@%7 (g:O2kJric7L4uHԃdtVeԄ⮖* i^_9&/H˲atn}+,/ҽo–mk LzzZWIom`H#yVˬ X, y5"M%53ն7$rr~qʉ^]/JW ~-A\I61)\w.Jfq-@IN{sx8LnYwgrc&ǗaRX]Xc.)Qe@E'xNpN9r,{,Q gUڙĭ X2kTΛuddV$ӷeeܝh7,qu&M fwH:(+bU\λG7_I52M`$MP9oם\ P\7L喕qg*iT.F% 0sLZb{[BHN9zbVg:O~&|6qfd^Kibㄖ@s뜌KZ2kVΛud d W$SS81{ZFrb͋?lj&q{sL9'XE61\de5 %ӷ!JomyӷZ9y'-fMwdeے$bdM(zyfoY*WP0&ɰ‰Nb]it>s$s6A伹%̭$̭ޛãIfnˢs 5 #ֲ"eOrUY".tP+w ٛeL4d`-&p'4mn0[r˷m$S$Szo&y%Z{`mc֦%nɔ 7/;+>ہv]/_3$6OtS=ªyV$B xJ5BFhSzk"߾9\ H9\7G~9FB\D LJE(')<+kd0סg*P\@ITk\(o#Q2kMΛĩLZL962kbs2Do͉2pPBRdR&tkvÖLĕ&t;?%$zo'-fwKʭQjo"(m26g 1^ u sA3[&s/–Lns$.IL$M<9og;rN2kH2`ܲhD ؉EJB2PSr2M(NU},.wMŽ ^h ,vnn9\hruddW$ӸgB:hq[^qqur)rLʰl(V}4uVh4N %R EQ0cD /jIʭ U2kQΚud&d&W$3h |/+Q y11Ұ&|q Ƿ[ף(5䈛uHC]~q7j[ms %V$>K2c8 iN$!"4 {+9e}8bIlk}dVM XrN]?My4!k{ߧ?'}5V9ģˋ_z(WOҟ^zA%Bd^rF1 ?`9vDib DȌL5 }6g:.ԩ)G_]ػEd^mSʄɤNYVѠSlϫdf,q"-$GF(^l\D[h _noٗRcR ϳѯ7jQNguc鋛G~W?e9Z$)z+dJŦ7nc4( nx%8A!$T4k*R6o40om|fHz_v{`,dDRan8Asygv} i9@|ڔuxmZ֦$֦4zmygWe]ȁƏLƣĕ1q~z?~R&'Nˤ_뛯^\Ѹ>KŪ /qi4ԦQ}Vy+ C}:qh њc9׼ԉЮ{}f:|t8d2T7hÃѧheOeFt,#Nsk`%}q9EYׄ+4ط:-!nlmqa +]mp"lތLU $}=<6u2륷,Ō# :GF,Gk]3vFs*}D>^ȧ|mOgZkTSkي'?9%'Z bnVB '*k\ 0Kz_fv 3URv&[uC29;IPQ qv)MlK2J;gfS`BgqETq"1ZBmq'cC{SchjMexܸ~ Ieb>3O[$;Ct[(Hk\EZI2kkH.<>%jgnA4{`n]/Z\Icdk%".s2b 2mK "NT}rXTjyAT-VƩsak=E V(C>sHlmb>.Z9Mgx?GwhՇMk7 %8wdnsomB7x2%JyOT㏿?<)$S[:︼5n孃5)ўU=a#|]緗+ePWx&^6OEGWϓY^{ k?\F;|ӯ~_5|78ڇYBh3G,W8aO1|댃H@#jˆ6@;F 0pStJ!)(/~g Ƨƾ !Q` 4p]ơbRxG/ЯO;p[ǁ}!G 0Q@bRad? a5ymj4 ^`_8!P ve*ޗX&[#Ge - =Dc4ʸclWЛA3F ' xx7pb#cpViH"xdcJpXm {#% Tq.] ;ExAHB ;ndQFl 7M%T0~U];Xڹ׎U\wct'^pj]},QxѾ glՄU&;S Axʁaq[)p ~A\څ @‚=)-\T04\j g@x+# (s1^{n_%wiQ7bLATAգQF=l;` L Da SL^1b X4ЗQ(磐2ѩ CϺScwiq.thFC mBSf}T\*̫O'P0g0ȅ(|cRy7lu`_e*߰gޞT3o6wt*r PIN.`L՚3J4g _=,po64Y4N4NhuqH Ai cl+~D3 sXp_`D1P CAyct1в\lN2_x#Cq p , o=  FLj;LoP0"blHj#I5G Y`;16A =Z WA(x/)|!nA&s19&Q~GA>6&PFs ;a *ѯ*C_%1Gd2!'FG9h'Wa. 1@5adIBi .*Р.QJAC3? ]4x+:fuN Xv`J#|n8 JHca5BQz0$j[| 0$ n0'K`X5LUA50z;aQ #A{ ,=S ,5G!hUɹ;:mXN`9v{Ox~-^@8A7y \$" o$ }B2y(T$yCk4 AYb@۠˩1Pku` f66. 64 #C$``d<Ғn>S/P"]q (R0Ч@cCt[+4*.Č4h{R㓇WP} 0B1r $Cc>iby!DCF@/\Pp#Ψ-w_okڶ¼]CFh[5E ?ϕ@8]A W!5Zc;KU;nF0'iqYOUc1љ~FY+ a_$  Qq!іbx W=A@Hp8z &,2xdpd|fTW(̍cLųC5o7leDOeE釯*sLj= + 00i,exH? "ѝqAR()"~ A/DA˵0 TVNNy'I|L9;Dhn\㽅0(1A/Ckq%B pF̘T8X09Eu>FfAc|X,YP~>Xv`<ND &BA@'$Bd\F! 菇rEb 1H5[M9 ֻ BCπ1܂%b\`ЛUhXBuG34(=s>إaǥXwjrxJT Ѩ򘰡En!D;?G&H` `:^ X chm4(?Ɇsbh Ʀd0Cb6>_[݃77 #@Fg!B0J 7!s:hR`@.phUEbdGQsAy/a-\JuÞi-`ϠMȍ@<{VO)Mз@Ϛ" [ t ]06Y/vŇ? c~/` V9fs+b#<(~瘔Sb p)Px tA?1,c ! zQ5  -)DE`rTڲ{-$ǾOhПFϒsge_e< Tcw  AKD` A?$@ rFrDaV̇yi?mBT*Q0$#*Et10q; 7#2{c, hDaB A,-Xᅑ;Lb KHA!s80 ZT|]w,(H 4Lf0N@@FDEDcXHj+BQQթJ[1aJ *۪&>nVcvL*v cXPc԰8&T!`nŰĂYit(ʳHQ цŶLzdsÅ|pEYΧqأBA/ckk5Z+zkpK xG`[--,g)F c `8G?h6| M$ eE \: Q~!X?Bf!2[d B;d%xIxq$GCʰ9`q&FD}- _*UOG0hM4HEG6=ܤQ!:T;atP#G1̉ ^aU? 4|(Jڊu<sR)4N |!*317c#VAE)JAC)l$ f1{,ph1>"ނP$1Wr0w\u8]qeщxԘj [:!!1mu8֠PV jFZWM׬0\+{}XCi訮tU:*?Bz[Z@CDB+B|.T*B*BEmUB'9bǘKt@ft P(P{xe‰ęFfX\ (7`1F@OH1z’D#7nL2`yxl@qNC?`8G#va*B](b `( dVx`TMð#rXb CSD'RLbcs߼ uiƪS1'kL][iL60Y6s&?<Q=T13+c,-1l7(&bRY"NFNAC1,G@y4-qxմT;%;|_D998= 07E Q qd88b}8 hl }:L;anΩ˿14/BM0.1$bkjuYW o̺B׈Co] SC҄bWpjBnA0q8bjeD.^}87pY Wu! 4&SLfC~1roLNW ay<]c;koWq4]y$}ܪ0'C :]cv{`*>09 <~,> §"L,~߃.+x"nG"J>aJZoಉ5z?W=e8TtP-jA&!U+$W-{ܪՀZD7;.7S]5GKt#,lJX͹C CV,c%AqEGˎc7'ˋ@E'Lw,U2؀(GCfͼu-/HflD2c[`l :uZj<ҼG7솫aKIFllEi\P ntۡ;Cxе ጽdX7?L}E1?8*\4HZrޛCi^Pi`/%䚃īCjK17 |ujӦF1]ѷ<ذ31d~f/{su3\D-[-9S/*-c#װJʐ|OzFOܵkv6RShPi;`$8cOtmQ5=xB=$֓tuaC{t Rl/5# smTA$c$rDE[qiMCZ<$A=-&t`^iFS!Ɋ$pO ]Y-]H!M{)jTЄPWFh,^1+ޅO,ɜmOPKh8D`G#Potentiometer.fzPK58DIЭHPotentiometer.inoPK}IProcessingRGB.fzz000066400000000000000000000452711250202676700332550ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPK8D7J}ProcessingRGB.fz}ے#Ǒ?`kl3 +1)id$՚Z uBuu7h6=2 $-S1%w:z7__? ſ_0n/Wd:#4c"׷7ʞ4|}ûpz0~x<ލޥ~=D~|70NUfvs@/&\*ʐY돣[֘4Fs ^9RV hk$ᮙOWo <>/.aUsts}9||]~5eoOVBKaoWy>eM>C`v4GϽ?ַrf'=>(pG-p:/pi#8xΏ[sBfLɸeO T4ry30=b Ÿ)RJČmrML)9n/5e+8=n ;W˪:Br](qI)tЀj"biL_.A|®}Ž}ZnmOiOJ+.} -Jފ޶YrھT1i)Z>s M.(瘆 ;) )i1yGE2?aWE>)8+i+ " 7QNez"N>mEqQN̝Q]( c_hj b\X,3J5a:A6?CZ;e lu2uț=oj-"Wpi \ƜO cqCK!z H춉85V1kAw>n{ILw)=1uAw>n [gǺHb;mg,1 5WǍk\ 1 {7cS%}xƯy sKs4LS?mft0Nح~c3>>)\Ǎkщݛq ;8SSe}ܸO'n3>>1܎ZǍk紜'&.y4}<M/_6xł|oy{ϭ;VR3P53T)*s I2$8~;ir~ݽ?~zyw2cs. ]ϰ}o*6p* f8{mj뉢lXLI˕r&F<17B ōeWj_IkjB.% jZ@M ) (BU&A3%%&,)(,o"K[ l"E1& i@rF»D&!KW{y;ofg pQ z! uۇJ[DJH`9,$#0i]#?$m)0JY=fyz]֚`ƊBV=Zgd[ =wBcgFpo#:_ @N$4aV=Z$i$&$#nࣼ(ix>*7׋R %t`4S~%n|Խ~Z 8uYL4TD"2aMh G4tHkdTt#& 9./tBDDT(k<2:`EMżB^/|Ua+ FJl:j )Ɍ>нQ5[>C%D'b5X.Rn<7!ḧ́EŲ8ǀj3;$xj2wGZK IL (Ig'G=w UJHU|yyzkdlMC/{W/^'gċ:a2|D:uj2ǩum"6BzEt(ٰ^t}`fVR[=yD8~(=csg~g ),E˼ҭeZL3ʤ pd~zz?lqprN-0`#V1_]9l{ ˟W. nJrvAl5̸ߐRh'08Ѐ8->4=ln'S:uZe+/Ӯme\a7B Hmwy\&@LB[QNYմ\:xV 0 -%P{5"sσ8F|CE1ya_GsfDkWC< מף戵\3v wy`uoU~☵)BԂ6U'n)b'^<9s' N3uDc~l>ns7ct_7p7d̈eo1~.>&ю[M&5wifJy׷Jt-2֚dZY\}.9%#wΒ< kn8[ZN)11Np}[d*5uHc pl?Yo$t.pi}~|"c w fdVe^pG_XfF$/zc%?b Cj r8uj-/֩ XȳH%#>dI|VbϐdZKP,SZ-3J~ 1hVLfTsyskf*7TJt| XkFS rPS,Mټ _ҙeYOTxrQxt0$L(r<GZ)55TvLM†)3jJMv} -RAZ*ufR[R"T ²՜6Uϭ)q"?KtEZjJ:(ۣLI-M٧FKR$ZPx1-KKq}ňDj}e \ň߻}D@0~y~㷴%;o߈>]roV꒝[c2\\L 7.[Tm|JE{wk3vއylg4 e'Bl^nTw'B-=$e6X SeÏe=euPe6eW0Q^ZrFfygfT7S'|y'ɴ弝 ~lƂӒryg: #E"ܹߩ.%1a%1R1pu QT",A*O4%a#L~c"uT$h$$ѐI"fXI|S2X[ImN23KMDKW6Wan$f$1CIy>9츰f<0:khw 0)7/lIpb aBQXrBl^#YaJ_]DȺ7"KԵ/ D YX8aH8ᡤ9ZX'ڝΑn$Ƒ Qn5(rޔ Qڰ_}R,Tr]pչH7 lk$qEeܛHhgaTN]ފ/K1xJ;w$6&u IqI-!ys5bMf7;{^葘Zk-BH"iuo&:."ѶRD>o)Vgn#4<֖)DmB/X@-fhA ǮkC{l4/A7`T:"9[HX !OsB4`[J|aXstywKՂ=ɘwOBcnk|rD& {C4Tw#6")`w2T:2t<в21dXoB#'5eXZTtLh ۢR2̢Gc%.kMCUu׋/!j}I,qIa 4vig<|(1pCH`uxdjIBl)^2Z+9`GYYh!t@5pԇwfA!eE͗x|p_\=\>_~?9xF?3/ Z>Ps~8^M>lgos^D SȓE;̰\fh]=˦hΖmD@DBDfÂiY_fDWkF"9Yv n%b^M#,1솘`3%n3$n-7"ؙ=;:E0piMмW"eyGU* 5M軁L, !ԙ[+L@R^*eu"eJd-aY )0C%k5#k9nfiI,,U'FLNHèJd7H[_ԶTĞj= [HUZitL9hQ9d*e[Q VkBڂ/HLFb5"^#:ڄ󎸙̑Z٪iORmN4YŦhǼߠ@3.I-BFgҗ&?B)!KRe&dHrGlWvIo- Io4&-XHmA^$LDdPҴmYkʮ)s.a*Soa`a׾%"P%6嬉@IL(ILښ$1E񎙜HL\灡rO-Jjq8fkŁ-E+%r"."&h4Q'ɹ^HHIښ$lswqI&qǼ~0ɤ"ba>DߚjrOtסH) ^*X\\rށmY(ŵ%U[R 26QmkM;WM%"U[<ܢh@ܺJrY![S(ub_gAHmlYN%U5WkSΛɎ DZD㪭iL[,zuuJb9SKlR@.mmy{YkΫFLgXJbqm"y8$$WmMhhq s2q+^*xfU-J>a+Ln )Љն׉;EGIV=ck 9vIlIlښ$-v+X_J&;fiX2@dqS=D #YğGMDHrOV-#;iv,$-w3]Gn-Hn4$͸=wSsP,r&3$ Ke) EXL Z,N4MX}4Im`$q l9m2/k9/a8'^v5y/㋽_ҳ7_^m:z^}qpy<~m[SjϽW{׫ɇ8 /|3 g)HmkE WS{J}iS e~2a~Ebx/hFOJFد eTyZ3:{9#V':!ni3:uxƠMHUmٮry6x~xkⰣ̚Eܱ1Z4(5Yn5LzQ'b+5ރZ|$ w[ҽɨ螧a6~>CGʉUlsfkY0Õdc3l{p=zǏ^RpY=smBsVq,"֦-k[+bmQx)FQ T5ή?__zIt}6}߼Bv"q+z1x7wh^eX&c,b:zfax3~x^n(}7?_؛o߼Moӻz4/z_ܽ<}yy#_~|t7N/݉DwѥՇ F+#_px=0|W=2><􏟞aɇz|_˞;0?zAAe$_}x|b3}3td88\*OO7{3{ŭpڡ[{x@q?ؿ—?Na.BLho5o=$7ppjYN{5OnyrCfPȻ~xt<=̟Lp*[x ),LF3$3ɀζ} aݱuǮ7H6z 3EYEᎤX38ACNSPfHF5Zf1Qp5gw9x|7p8a(1|-MƟ+@E{0*3G,9=2hDZh0do*V*8P?`RiTTD<^PƳp%<"G0ޝ-82G??% && 0RThԟ=ZLƵpUB݈0g?6~J͒5ا8SfrD"w[kn_ 2@Acc+5/{mP ϢBtP<;6Ly A|LaLuZC xAӟ.- BeǮ߸a=T'}"Nr@3EeDfAyIMIL5UXT,ͨM;||p2p+L.IYO#n# hWݍ'`,u>#s b gQ!8~pYĹWwȩ:ЋϟeyK֗Xᥪ`8nYAcJCo$4n pe]%@"FX@w`܈7Íxǚn@ 3ݘ+v|Դ5-vxll`Q\+sӮҔvڔl 8iWɽ`$b`8 ") f2sMQݼ>hSpDlƫ``e P&j֣8v])^XiB4-Yh̢g|/tk] &|*PKU3TJS-4LoQ(f.4Ѩ CϪQW<1.4h‰% 6"}[0;'jUL"̩'P00ȹ}m 5 0V l4̖LިSǼH7'z2 0DZOp^:,h `Z]@)zC@wNg _%D8Ğd,'5NN8hgAGc a'R!|!{ xDA14lM83y'+5.P\ pƛ$77HRm@f@cvU14ܑL 6CR`4 q]e^y`~~7U %gy wQ}*(qVpUnBO` 1p41wQC; geD:Gᾳ^{^XDwDHm Is@[j&?A;|x h:a` JAT j$MWQ| LpQQd *ݱ{>!  F J3|gg%@K6 sJHca BG`H xxuEx6L$ nP+J۠[4LTA5S0zyBCt8c` LU3J1{U`~}O [%?s3SN@8A  oK$&p@b$@_@CoC" L#P@MN ]ݍ MMx\QpZmɇ'A'hYN#%`3h18 `e@!/RJ #m a,1n+vBpOz|sעM!FQރwxu XNѐ ÀW3j y9ۊmH(*~hڠ#Z:>Eѕa.9Wbn)tDWT`i:n01 `*;`h0+')n9vo.Ѭ_AtʗuAr.Y s?z”q#枰JS1Oc|f0bQ#AQ+e/, ]BRn 0Xq7[!&LApbyCpz}1ڎ@L@ : ;`DZW!5pDU C}0'ǢxDžHR9c© GÎ7 's B rLx*}8!4ݢh5o^ -UC#8|cwQ Onll0+S<_E ё@ܡ 4ULG[_zuƘHD"RLD3 ۅ$d7۲vW> BQP4, zŹ]Hƃ>2h BBd0c+ ;lF;>N;8t>] _ ػa`%.+l)+J*4hUAsdh-K?`  \ (%(G/?5 9 C+װ"v@*xRq(1-Mg H $5a#A"a3NR\WQpǥm3CpP` @ADA7[}ajFZUӼacaކ,󑮇1wBίa*4~b0 \mG$2Dw8 98aeLȍ@<YV$O-Mж@Κ܉>X/-4!zE |7EA/蔋.<5/C4't<*$!8‹e+aP&DL 3E;+ ډE`1s>)F3eoGWzP7o1F9*9#ȵxoSbqi qRg2C'e<]*Iz͡Q)t0{ox]hl nB# bx#40*Yj;mCgA0 !*Nh 0!fȃ30XiȌX|<ш„'H p`z01;,P Q=npC]w,(@ N@a a9􈢍"Q4Wz؃S[1`JSjy8 0C48*l+orRۣo˚T<{Q|H Ӿ 5-M1(>A&U(x=2HyU;bʏ;s(,9+SsMIS݂`hR)<xiX<|DƊilUg|6&%(Mg2w/,Xcù)B- z@3`pq)3U WؒE Ci2;UӊWKM fƆZRyKyCUP [hdl)a/j U- UP- 5, F$T^h\䈎N c,8SA[LGBSo[' \J0ob/͔)Q rY~#c'LID;"Xh 3Y*Fqd9ha *DH9'`pfXVCS q#eQ44Iր~lq#0vGD+YLa\A~Ab훛tY%*LMSzL0Y: 3&f+?Q-gQ9y-4L??cj nAnaұ#'^1';2ٍ e,SVQf4D1"kcܨ+Z g7 n׷O{/!U'Vr1/S>/DF,pD@!b.s`” SBo /p]>>Ti,X,qp~,X8UǢ(ƢkN 'PRŠ~ym0-9|jW^ `&/A 39!#%}2gcHۗ!ND0mA8 ĜW>[_#X_/8hޖxωRQo86 h δgԳЙYlw-[oh".oᔈi:F gi\)\W0b k/Sv  l+0t`_-58OECп}v4?[|znh2;ʎ`鱧/?ͨq>SYd 83XvWKA#~wڋhBvtc4P_p:uvض`VjvQŒV %mڶ-}x4|.ϣO/5e|M>_)y|B}_~~or~ƛ#85[S'+ۡߞ33+Wsj͊2tTJ.+>ky!`nǓGӶfPnru=lTЮ7}y~u4ܔ* Uu f߸šRJ08C!$>3cv+sC_kK/mJ:u|8 )&9AMi?oB(!44'#LI7_oEc%j5KԶ$EǑakCΘ܅4:TW~%PB5,*⫰'1Z5CJ"nեBJܠQB'ވ.Mr&^)3ZMlLY-qD`%nm%nsP o˶4͈N| $GU5#:(Kfw(a8$UXrDfYUܪ dѱJwlu[ذ<#&vf..k[@/-u4q`V-$^$^YmMØr%$Qơ$Q`8B5J%=G%woUJn$B ‘:Cr"smuCݧ!xt\Rl)6c،)痘d Ȓd5#˙G(udxdX"3DH+wnUVnDryJIIb]ksʣذX|IgS'h0m^)D,[@D,iU8JYC*ۃ**eʝUTdF >$er8sQunfb}VxWRu-8Qʨ0sōYŭydI%$6$Ng"Tު TёJ20ed;<mM#+(:17Djh $68$6)WQVݽUe!Yz Pj_:peS\;0eRpb %qp/I5$F$FYmMrCHI̲q@I̲M0I䒫( jrZP^-h7YN#y-#C} ,9z\yוu>9[yǭ] TJY:d!nВn5CKJRmPmLRFL$˝[U!66bIvOlPϜi)EAvH5MheZh(U(UV[0}#,Itq$It5IQS7Fܪ2S1@%ψ_}Y| {Hyu-DiD i"$S|1s`QLHD2ndIDښ%';CD'ǓD'Ē$BZy"F+_=QlZ.rTI1A%b:ED-[D-iVf/sˮ%Qq%Q61d/i_]"sPK8D7J}ProcessingRGB.fzPK>eJfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/Servo.fzz000066400000000000000000000414441250202676700317610ustar00rootroot00000000000000PKܑ8D޽ @ƩServo.fz}F5w昵fH0CRM[-izZ&gdfr$sHVVh_fi#W$2#ۺ0DZe`GLrKpx-Ȉ_**8cCr3⇄[;..=o/5iOOi/AnVJrcnoG(+p$͟f{IO܀6޻Wl2s-]u㛟ǿ|}n5?樂"gߌ&La~{3~qYr޳MFC/p4j&whr?_C\t_4Sd,ݺ/ƌ6ꆘo(eȑ\ӛ'')Nǁzo3 _9xgQ* $XoB>zVSzx?F͏;{h0Z?w~) Ýz\&Jثg BdJqP9 ]VIZfHR??o)$eɳl=TSe5w,+4Ptji5oEAۭoqQn}ZJQuV*++e-ܞ?Wy-~ꮈ -QOAF:o;Pryq_(QDUEBH##%.)JQw%&^<GsyԶNQ㗝8j/8mBm_pҨھ*|b.Qegeܗ*jqwT%QB_x]pr9&{k(upQLU}Y(_ڄ"j/;IJ_pDQ+}٩LmſzJtQ F4PZ O T.c~@,[A .1[UtUEFz8 } ̹lbNeaʐ2c8¢vIQPaMCC*89 5#B"I;Pd¬{yAmC#^NTRhJ*B iB I@Q !,vcIĨ(ePгh(="?Z5\yYcHL4spw1 Q2`NTP(_󣠻7'u a "\/Ac >E/mݭwkئJ3OT*1RWFA\h;#bBImS6%F49'}/4Cymz`.)rmD<$hSOds#J⟚(rA7?1oDҐ$Vt:s-4 9Ihɬ}rq-U"a*N ]/ Vrmɪ-/[Kre n 98xJ#|P)*Aj7"e]'Ǔ-|tg(yCuSyi  "qhi iD1/= s$) &I >ETPsscOR6 ?U96@LFq|#I0b7zi}KsdE/,s>*P;ԭb&6( 8`7f/nWHMC iĐ()i!pJїzޓb(! #eХ&-45[G#)3cy񈸺OKႠjǴ2_Hr9{xs i9,ҴБ`)}J[`6F1`H41=)#R~OgEt/X# <|ͷo twᏻi턞I(o@ %î%Z&įԴT]|gr waWNED(mdr{="T\zO WPLSk# ^Shl89Y)zxnoaSдqb]5 ^ܻlmU͛5H)ʽUޭMK$Llha{sq N5;e78U{ܭ;g.wO.HҔ4hSIw髖tq;?t((DQfN \_]S^]YOz2 Z/LYoӉTxm+bc)S4qVri6@]ungF݌zmIcKSsF~K^r|˾~7-J{f%<m,mF[֚v|fT0# ;'N )?!X0&  K& <-|J1PBqF-Bei?3p=-Z3e{ HHݜD.?9m8ZlN ͩuRj? G}Vֱ/5N TXvu4y!՝79fj|Pu֯x6v)f96}@]5Ce}}F8 qg)]u04aQq5]6.U4e|1#iP/Ȩmb);l ;i rNF-s4xKVKsUm5S V#M4R#9LRm4j>Ԉ܈R_=v49`imÜ3?ޯ;(?7r\*t"D.d\jkVQߺbZ̐ldch7;MkP7 TIԏ}_úC YB,Ei\ KK.J S8LCLjqV\F´_ε qܰj/rPՉ`j1^D?O.k4TunY{ilue&  Qz4V\U"tx-ggp\;SVE~V D>,n~I[7~|T׊&K"CG^mV9f$PHO/7Ai]7-GQ#km^xkxk4qtϖΉ4?l78KaR5S'Dvr8LN(y}y&VaYH?D/ϏXtsn*2L,$vp!)aU&I_HڗSA$lĕAk#k^8t`Z@j;TX3 bSP["]k1DV&zLP7x4YH-_;1o]52_ٯJ894_~L7WPpqyL>KYfoq,۸!r ~߰Ts/2,n:ֳ 7z0Pmoo=uLMetcj#n!a9Q]>QnkEȸO'q׉%}&;p+TY7Isz89YXDH1"xY,r%89dRnrkަN(Չ&43fIP/Db,5unl[hx NYڒɊ[;ښnU٬k} ULE/Vi\׶`q# Z!,rÓXfR_]#3ӲGO9ZqQ%SU}hE/nk)lz-0)Lgc &~M7ת`\g4'k٩䤪Lbhj{-Mkpiv 18ͳy#9=~w/O(6{=cl6[s6LVM=7&0N[o>aq?xe0Y~x|zLof˯/?&y2C+; r( WqAx.vP2Ʊc]SzC:t(ǟs'Jx:Pn1GPWP'}&'U ~ߎ'po w;p?)\9ۺwNO=on&p9q2MI/MµGgZSzb96Xe1=ѢPeeWWzbQLlcAgbpFά'S@ b{¨İ[Yf(&͋rcm4̘ aXʤ.QMkLCb@DoF}X8.p%Ư!&b^CYG=NX^{lF6Yc>ZMlvYFSu}ҝ>)|?B}@ W!ځXpM,5<:;m ;tO9JV5bj} Gv!R]XVt"0ZD(RZݚ*YV8!Ён;42]XF☃'4qQo5#_8xӶC6!݃aee @(.֌.جU;§8I[`)mFupq@Ð?zQe2f!#c J*H|VV=-t'EIxejFhnXO$h'JKm!hBFL֦aϠ$u‘jjđJ|2u&kfS˘D"ґljL?['͉Q\*=;l. I\mXE'ٺʾ Kj?Z'>WSHh5Gh5HheFha1AiB%BQDF!#Eknk̯j'E #ԙJR w s7^1*DR6ۉvbyku<ݘOBA=J)f H"D^m[!Io5 IoeiN&׭dG`naSz teR>~E֢6 YO[$n'LrLNx6%Չ#$$4GjG qa'Wo@J)" ۩ 2NAd!o%9Dl hBL-S\fI[I[#H$k5H$keiN$Țnazzse*#"g;R:iNMwqa\1gQmʳDyf(ԭNyԭɸ$2$24ʪGۍ7[Ri5'!q*'m(7?-2I0\ϖÛn K2S,9it,Ht)}J;圴 Y·Ljs)#̕J䷜e7^o02_icʫ7&ۆ7+}qn5uiUU,vtwRalM#ڌ < /HQ"B%/ L.ʧb|=Q% 4~~/h B9+3=m:=rnƋGWQ6m޿;KQoldOT1:48+~w&i#q|&&jCv3eL'<+Q|W '9Saym!G=E$=|-! c,-tG=o}tX˂=3!0dϴ/ܒ9ZS97-Sb#56w ST쁛>~xܭ6ia|ۦ9.k7?M$. t/V0LZY{vh|wW 'Ik!qcޝ?~ztFx6}Mt8O|ay3_w˯O|o_/;Ώo;_|w~E~ǏGwpwFir^h:|za2X©U λ?zɇN'}qIMK^?ibx0[~*6saw"CaH)i))I5?WWJvG3CeF,{Atp—ߵ}ק` [7w~MMӴ3NۿG2ɌO ;^w o|4>/$Y)e'*)ߠ;IG0clLa$.QWٶK!;&=&2Rd=/{ᎤX3(!'ʝQk lrYC!g_)x)}Eu(/ q>Idj1$>evJ?IEBf5^$\SжřI0Yr(+S),_&SOA>nN_^> "θ;D8~G)'PU[ixH븰1>߷=O.3 pnɢ~W*OjF8Ԁ*lAjFBwKU] Kc Cb7ݒ(c 迸0ϻ;}C(PA` *ÿC/W+ếJ*%YSn3uNˤ:[ĩ<\rTn *p[<^Μ㻥T?Dg0 7*o3#z{N؎4"ڷh-42MLB  ?ThTDnzJh eACx˓-= gx %v0.o7fb @ a#x,x\4 QPЋ.X ~Dv ':R\lL]=x PLs=B@( :̂-R @b%9C|p#7⭳k2kdb.pvmqVvڅ㭋}ChGpWv%QoK*ڽjSt!| 8iWɽb€a1[ pq^]'a]!LQp.D!>a67Hf[i ъ^-@ :cb=ʲcM]|︟e AW;-M#Yhd;N@\A A@qȂ+`W@ gP䭐i1 MrP7}<1. hBG-m\f5a5D1|3N`,aOs |=hgdp޽k: U@0-jSoj1oG)MZ-5A8LgVnyK2erBV lb6lW;*i&!֬!Xbhp̃3`@W\`c0l0=@<`Xct9fBP 0҈_ HC1 p , tt3&wSi xgf(h|"`n( KC a)IЊNEH R{ ޳үX!/I49G(x<  ּ(4n<ш, c Is@[jo`L>Q|,\r 0kP% 5R+f(s (GD ݶ;y{9 Q0 \udVrXu`!J 3,w p;#$>tЃꕎA!Ѡ=h^]^VО| 3^ jD LKh¤>B43GZ_*C EB\аdBV)h5.Zʼ5 "_3lo%vvy 0T𾁖毗HL+8'?^@ CoC!a˃ B#P ACN ]ՍςMMx]Q-r䃄I |ˉpv| H]ƄJ)%)1B[bVr 9#V>ŘB} 2dڢYHRtݔ1FB+1FPnSAb@bQ~'cuc'2VLsLzS 8qbçeXR@R0yiT$kRx׈B$YP}/z s& %S[@18EV%vW `l3Z4 `}^ Ĝ~1.K 2X`DTu!xzsB1GP`y]vʄSbp]"` tػ,O,F40 J/[G:*)#dBr->[K̎{|˃aM_ (h]GP -p?'cWc@{?&2 m"^aGr/K !X뵮 )Ύ]ɀ"+5T >,,Ƥ|6Ut9f *T*SV8[;$l&8I 8G#Ȍ a8/t!Ak|C-@HAb.4dNzQwTaKP {Ql19 쐐7A%1M85O 9`p&d'4x?}4xUʔ}:H fn_g 5Ac`ӠuDuvtGe1 RޯjGTW})J- iNL8` GC@B8r@P[Hd)46KaX^UgSb(7t%i K,3-u^::K0p 1pb}go+Ʋf!:Έ?0;%<;9dC8˂ZLamw1s^P4 :x,޵"'dr'(C;\`ِr",Tı {m c:v¾]$~8+ LR>6A`]aFͲcЗq.jZu^Wy( 9!=j~l WpjB݂Qax8&Qh?eA<\`4p46nl,! 4v$B꽗C8T Cy4ja+gx~U[ؚ K#+[i+lߎ-g_ד~uy?~4Tmˎ9ap_~ͨq>}Rls6ߍ?J+1$ pRъpG=@;K`%_n} /ms#+W{NT;Ei"ĸ&6~_x9pJXb5ni>./OM-5*ɻ,fz_^8HwqUq+4e?1ZwuTd=_|΅Ia9I:l<&g_w;xO[?=gcy0,z7\&;-cY,F,*a2u`YNLv87W{ _㗽1Xph϶ j?Qq/0oT;eej$_N3- Y1MzꖾzεnGuTo)hqٞpפK-,\lĻk'ӿ6ߥO(P"54.- C($3S32-f=ѴEaX-$fTpBD_ 9J楬)hn=THz PP+*lJMH"RG PKܑ8D޽ @ƩServo.fzPK8DiuqX @Servo.inoPKmBfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/Synthesizer.fzz000066400000000000000000000556721250202676700332220ustar00rootroot00000000000000PK8DK! Tpart.sparkfun-electromechanical-buzzer-ns.fzp_69129ed5bcec2b4b26eec3be62bb1125_4.fzpVMo0+YqۭIʪm˶^ j( 6 b<ϼ癱/a@SG."/U4t K؟@&Ze+t=~[ϑ1`3Sx)sN'0i`Xi"d8ID-gh;J{Ub¿6BZd#8$<S$GI-t ^%W݈vjVCM ;%NsZ ;ũYI̲XŢW]U/SNKGRO$3مt 9at> {6VH̐,S½܉͜[Wيo':N@g Lr$,cik:0w&"T;Z(rAn<^}FY(A[n |`aK —rS#K&BAj9KU[)~)݀,jRCPBJȔ&n x_xOR ޢhi=O<٦](-8b%TS!L~-\yqԦ<}bkw\AnEr8#$d"fJO*Ǜǘ~Hp7wFԒ$*9kz?I:Tʺݐ6 -INZo}񛾦瓮[NVi(AdYNvH9X+g)SPK8D0; wsvg.breadboard.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_breadboard.svgVYk@~ϯi Z IIB@!-ZWf%N~}G+-@]"ujp=2U68#;<8mJ.ur((fUmB<nRP2^1ǖ>gy=m^2@!X㺞g> N)up0z<(q} E&WMD/jz܇7EQx"M*& ta+a1-x]F2u0}l$ӆq%t9 UՂ<Ņ:Me\Iu5LٲIˉLƱʓxޤLlU= a`A.N1''`hZZķ:߰ALa:n6&4d#Q'y-`>,:KwV"}f<$b^d[pVi"'RYj:.9B'ۧADŽ  #{X%dd>0> #Czlv-{#[keyXy GUyUso' 3.J@ 4:apFdmUlkw2:x^딶4xp/]olkc4@{\G7nxś]aⶰ ;nwE1sTɮv1zP$snp<(:AEbvX~Gߕf/PK8D/= {C ksvg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgVkoH_q~H+a<-;UJJR~01*N~} u]$.sϹ͢'VkF5Hy :mk=ۼJRU!`ϷpYֺժp( 61P wʁ~p]o @"8]t/Y3+)'$,q,H$`ww$vdRYkD Wb~mDMυ%?ϒ hW4aX؂![ ٮڝ0AakX$/]-]p$(`ny؟Yl{ۚdZJ×:3 jmPdXۘIQށH[]n RM" MH kJD :as'dCVlx2=Nh Zkb3Y;E++ Y$2:*Dc7"Cb$=KcE-=fYjoX/[ iN~6` :K|5~L^OPK8D;2bsvg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svg͔Qo0+l 6$$ )r+`GM](Iej |}뇦r&AismlNJzarQ[(}G):%a}+CS^֕G+] iڌǽ&b  &,hCv#.ADqx[)]VHiVI2O'LkѪoV<9j b檕ԩB9CPlm{CUwQFKQ߭(n+.# 'H~7vU%@*@:#' > fS q!~İΈ)_n oENuMgr@kWa8LHa~ N)sd-Z,BeoyU5TAn:LyQ㕟t1y_ϗ} utAiϕ`q&Vxkp[iJ+-;KXPKY8DN\+DISynthesizer.fz}r#G?`93 Z6u[MLEHCX}_o@f@^"=\7fw-gӛ˳f7'z7t[<&W >.>S1Rz:{̸┺Zv1)C(L.+EglB.csV}pf|}سAv?o 'ߍw;~8:9s~5Jj2l,X] bBNtx=]>O2W_*i6Xn||0_L޹/ɯ.opf?z/7 ğ?o4`1ގg>>N=ÿ|_y:pJ.8wzLޕ~OGf~NO~M~.o|S5˦Tj2_c{~eT .RvE.*̙?}z7H]3Ǿ~Ud0=~|sKh&Wy^bOMGhmyçgI`e=|rq?TvwӉӦV5(0gwp֯oȦljH]{8ռ}>{no*N?PߏZtYF.p%5Z.pj(D4R4>n_Qp"Wpz NMGY7LƎ[ɱ)8;n_q \q;+dVeI\ǭd%g7-@MID6&O##Z5rVЊi"W#Z5r>rFc"l:%$=Ԑ=T"R*#DK҇> z,1Ԣqk'Q;(e kn%gnW)anv02>\a}™}jw}Y}ܺ)GO9CO;?x5Sq)c#Km v[S![mA`/}sLCsq bk G#FM8ȝ-=M8 g)Sc)M(}ʹ(~<F'1MO9g~yjKְsޚ7%Ψ/̊ V<⬪YYYG(H [IϐoNKiX[&D3fFߞVnFWW1zhLzGP}c- _YOKҧvE't"9\}g ]Tt'ub);^Q^)루/m*dd8?<.0]!-<.~$?aڔ6ejGQ?1w :i'w/DF?bp;q'39r=X;Ǔ'`bd}۰I.gMCΚxU3=Kצ0) ̆̔4_.<غKWAYRܸ, U[nп$17B5iy iZfԴF*)%%ƟR4,`NJvߪ4z 9i #]Ax.!:hy{gu pU <ZxwDA˙rRP3HAWHAGڳK*Y4t2iՎygn2, iDِ&HK?64Giw!2x&xD$IK:fF=j茇#Q.#ѣƐ^(,s/e\LF**7#"?@Jt|\WWWfwu0.h&BC Mf;SQEJl4Z@IlU#HglT!v"z 郖{Oe}O 1~BTP" 3E:L .ی-_?1u l(TmI1У鈁b.C]DX; MP'DDH:#?(I\41:!陎b:X8υ]=J.J2C)ϬrmؕVh"ZgFTm 1QvȮ( ("3Y&DAkp#8CL(r\?^||\2>*wOv^.P N3KS]ךB`N6(e.  ea >LARaE]z( UH GKNj$PCAC{^(+RhNa:1ٕ2NGG]1P\J5t[[Lz&Y쓡G QO-~$ҙ~O:mϤXWg! ڴUKƅ !R2 fmi3 unui] ٳ0RQQ٧D@ѢWT R2 rMeLa$Lʄ&8ӡ &Q'$r~ 9eMNEѰk2ݡeL4.lvi PL3Z:j.TJw5[Qk-[sEd񍆪fL|7'v׈jWDd"V G:cO I, (Iz8i8]4jǯ)o{L|+O\[U˜R  B<^1g0μڳQ6ƙP؞Y[UN&HZf\3#vnq5R$l?3ꭐ?`~GFyk |k݃N_fō>L-9kT[|9!sZL 98M w?>gȍ-]ש{wCYcto`qRT9ѱEvl2Lwx2NX부9JJwa 9ho Xg5jھƳ}}pb +=pqãz2Z[+3[[HR};WhSM=FN/d:a₩t/]\P/b\osq|||#.BΨ\ ~:'(fٕ֎NFp3rsAza<>._>܍7N6n`LCfӇ‡~k:J}m2"xXi }_ˠg=LH*Zr*_T^UFezNd`}H"o#Gp׊H:X4Tʦ|eU9a3Eʅq\,Z'xJ:*yd¿暐ȌT;2÷ꉚgubjUb(2eJNSvڌP[ʧVd2QJE0X 2q\1Xtmlm)z|u3^Ww~'Hi\f~Vf+#f]Pg4ZuAEvYKnb5(8jQ zv,@CEP0tTs_$ihGұԀ Feq'1c .rL?cu4Б}v ;^MchNJYksIbf=UYWyuhHZ?XYHㄑcrdk!TEGVaUDYFߏ]]]8&H줗@ꑞo#at?YMN~4eo#.;T(o <՞6xIC,2Dt09t0P=fC[ՉVkS'Ց%YA ӂ,cX,>4Ŵ69j鱭Uz/ 4:uh˓f/yw^MJ _FW Zz '"~TTrZlqQ^0J`+V(/؋C]xh.e!Ȅk{YH] l) ?{ SB096nQum"ΨU~.JJX*?cԧdƽ|sGNy>>Z\Ϧ7 rf3<_?E6K=Gp)`{BL}%̈́D1ږ q~ Bzd25 Y_Դъ0~)ʈ^ =>cyUˊ`Q!"Wh}<-Қv J(SuUd\L儑->` F2u kzi^0Ϯ<9; l0A6T.hqU䱿p!5A@<0U7 cG1uȶz}m%Z8kӡr!.H:dQBYԌ\0vL^7 K8܂^)\oMhu ֪cl.QDcCv>7k˳gLL#50FzQ)1q%Q.1uSŎ ;Di;I[~IGLd'.r6$SJPQÇbmjM V82|셯,K8Q%1.N/IܭIܭޚQ$Ͱ,ٟQ3m! .rUy JLi*dlZsxcO|m=NLtwLd-BK'FIǼ?jإ+aHx°'k~N5J֘o(ۺs_%u #u$$VoM(ڒ2ڃpVQꌹ>Jj %FLk,Ê`X!~׹fFK8tFٴfQ^2-=x&u![>$궪n=SL~\| >R'qY!INJ"vc)M쭁UlAh^D2NLmݹ/ÓfGPi[^IboHZC$Im%K-.K+lFBImL)ִ#S_yd"PHF'X܄eHHp Io}[Z77IHIzkGIAah[ϛ# b%UBj,$'梈m1 %L*\ךvka5Fyf&TT/'$%Zֹg8[8[5Hl%g;R$gW ,hZI@c̮5-ՏS]dOV# (Fa9qdi}ȎuFv$zDM?p;~uRύߧ?6?~܍o_}]>^ 7'*2JH"˯׏*2&¹b[_\忻y~|9r~1psa_ HF?v?xw |H0 Fڃ8I-}?~ٌ⛉#$R*gw ƏV`fi*n20rM` _k_:9 pj.]kzH%on|q3]'r?hxppν2ӇB/_ngS W~@f7"LF2NF~w1:$#:I&,ܱM*G<3LH=w_k;ƺcgx5)*?tCQ ? j5Zf1Qp5gw9x|=r8a(ƇH 7Bj1!:e¿5a"8 mNP';mܿ4 xUIN L8v23r'/> o^D4|ZkP{׫n_zyɐetlȌ;&N CÚF}[*OjF8:tAj/FBk_;{1<+o\c(qua)qx0χ~&#qCR@T8b/TV~ _YM&r'OSgDuSJ|'rϢEEa\uܯAÙ>ʕ!a TR??fܷX8v!{:e;Јh?`/ 1 #T3Tp~ ߩ-xOyr5g'*xD`;O ZpdC~~K@L&=Lz?K ` hX>Z\ƵpUB݈0g?6~J͒5G'x6a ^CHnO{ mSx(hlql>WEcuP!YTTqz>Ѐ;)!~c:Wo)) Z?WI|xA/h "-38vƍ>idqC^&JHT`WT OpªTa=TYMs}^>h,C+\ f%)펽q6@[$]w7PwΣY>#s b gQ!8~pY[{ aM{ ]z9Y H]($"/U546>2qJb+6a]^oF00<౬rDIΏ(5ZcZ#] )a"< f)'>;aw G KCHdt(xQ+;WtwoXS hS75s~s8sU׎3ֺv.o\;]ZSK:=jS5!| 8iWɽ`$b8 ")y{ Rt7E& Өn^`)@"60NXVwcF (QV;n{V1 lh*ȊG#Kpm0b K"7j)P @VLZ4hjrr5T!:5:aHYwj&wbqp;څTh_2a#ط Kyجn*CÛ9f97P&a` ؛wM'A*fQ֌`` N:H5E>Q׫a7H -@}B찠IN.`ju՚S 4g _% ,p=Y 4Nj4NhuqH Ai4cjl+nD3B{pT_`DQP M@y,+ M:Ø\elO҈_x#C1 p , dt#&w]Ci XgPg(h|"`l( MC Y`a6A =ZWA(x/oX C 7 _@Ryp Q <(#9 -{@ybQÊz\!Y?PU<3D&́qnU0(~v2D> ts 0A#@HJ%M * Qd *4=ldH1[ 5sQ[b' ځq*Z*<1AT{픐x*::hG`H xxuGEx>`LNFA7%m0, M&eઠ)=҂P#A{ ,`OxJb,Q*E-7Cb㭆ΓՎ9nG' |DbX@,IBB0D@z @ GPQBx| Br* Tjn DTpoj劢׆fc$Z GJ0`7gbqe@1 /RJ #} 40Dx\BHVj'h=|ykѧ#c(GA;< G:Q,'hHab+ x<mMC#BUд@t|Z<-UkMq*\ Do 5pm RS=lo* H0u$ B01 *;:0+')n2 BCd0c+ ;GǎN071]bL/{0 n@Ɂ n/[xʊ_cJ}M,at*Ť9L0JLwyKA ^⃄kX; `@"8Xe# |M9;DHnXIk 5Ԙ88` pfHJ,"h:Fb 1!x3p ۂ1>, @j7P1l,mr@?z(;d0su'D} apT c*h;F&iup vv$Fi %:(˱o`` -!ЮYtZA4-h\B ԾBX'ƫ$*Q.$cXb썯8oA(Wy(Dc†*-f@4Ag8kA "7|^[!zE |7xA/蔋.<58/C6't<*!8‹-"0)2K#S" ~vbv U茝UYSV8zaG 7 g ghax6#H-H4[9@#(#/i")c.b,$dNr4EA BK {(C`v&IҚ'Cj0Z8"]E " >^O-XW_'cnDIae086 R"zȦG6Q{DUvU;bʏkk(,91+WwX>(Sl8mTN K2Vxi*F,QE) AR߁VEUzw =x,ph1>"ނP;ioiGˎ+K1*WU(jWp\ipb+5c1O6 ׊o"[:* 'BbKqhO{VCh]jPe)TJ2Zj~Y*lPyE88\ p2ށN&,83 `݈l-^)Se}#c$ tuC|,Kf8H sp ډ~98UhB+ELEY`V':MjR5E nVa-"% MYK0= 9R}szRsUɯ'jL]Sy3i`tDJ&J`UɂV(XNq3 +c,-!!l7=LZ9v~ 0"= YfRިJᡟƂ5aiNJS&_C@3FXы n8+YtC>xߣW} >0+wu(4yA8́0> & `"ʿ}}$ XձX +ⴁpy,XXcQc5!HT`԰:Vf)̸VfyPt7bK6yq b(1l$C NJNd oP/C4XD0H``gaaNȃ+_C=X_8hVxωZQohJrk4jY@gZ3rtft"(8[bEK.Ve+V]u-1Mo|a"&%2:9D;ˊFLpam1r RxT,Gӂ9W- IM2 " !fI2:X6D5BNSØrISP`l+xaIa sHpN=W(HRYa`]aA͊cH hK}/f~5V"ޚuՅ!;2,2TԄ1݂^a9p(퍊 ~\`48p4nE(! 4&SLfB~!r=PLnczAs mv,[fѯuA*V:b8N>y~/_77W.;KO.c/32wvfgw㛿V$c0Ǚ]}}I2(pRцp=;-}G7aȑ>G1^n8NrWReҬisW|cw&_M{Tz~]^ެ~w3촞`0u: ڔs~%WWQ0.em۟AR3#~4 gC!Qq#:j뽱g~h,8}j?!͗}1k0Uh|Ά dK۩|GIᾲe;ka|?n)|K|K9~fES1gɯ}yd]z<vf R@b`{lִshڞP\YYIԋnCcZ^iM\7UlOݰ{h*l%$n֚XCVzմUѪӔu4ۚZy:MWlm˽Zxl$ Ԏ5"veK- ^KzgW6][{>:bNk ͎^+vp|e;ȺD[D;BY7.clf$&J~0I"kZ>Vu.yaRg. F-eO\LG>`\ck勗HpU^h Q!lOH'U[}bpt̿!kH;Ng):OqQ< oj?_3gD3:ivNUZӜN"Rx<.i7NOu$#)yݜdh#r"XKtmù/ÐXGRZJlk'A} V1+a.^|AcV[NK9Cݧ}GWqp1|~}a7@Q(8>B\єYauᇗ‹263 [pxV&? ioZ[$Q#ei@_[|]\gJ5׊б[L5%|NzMpՙ7d5V7PڔZPZ0Z?I"mH"mִ$#~D51q*2W2cJִۚS3R<0Qsx膹хg"VR^5EIT}(ITޚ$Q%*wH ʅmdf7%*R;%TmSʕT%qÕĔzQkJ}8I\nUD\0)ǂ'l9d\HƜFd2\\8FLKkMK1/rTN/m$*%j*ף\H\5IbrKL0=opQ5Ŵ_թ1%y~ ?)UP͵r]k qy׻CCXmx"H~Z'Jr:I"-=˹/CM@(Zw 'I} Iޚ$P2.߹%2yf\&t;(nI->a[Ni2pL-\bRJm\Zw9I}Iޚ$ra(uU׍cgD7ob3"qcTEj_S@$q\|L_D& +>$!$%:>ǒiOR%/s=D4,7B2e,$(%iN\d8VQMd5m-\=Kr+u )!ȵ$[>$"WRٞ7*s LIFe횩T'I),$u6qޡR蔘[ך6N=wV}B y4MܗJ%!hXqȌZ K`> P"EFvσedcqM K}UVRޚa%{“)[GINUN mrJ8w`?ljTle"hFk3jM>Hʈ9S^y Ke(IL[Tf"Q=п١Te7LI_K5R֭MhT-q6|LW͖,Q[%%iZuR{kPR>ДY,UdK 5kjqzz16QŞ3:rj_M{hM=N6uľWZ%v(')$VRU5icH9Vggo9\gIKth^\]KTIXIYzkNqȸd_xHehRݧO` WPK8DǩR8tSynthesizer.inoQo0+A OӺƴUV>Mba|3)jE%|NzZ7iQxerpT2K3@[2J:IKa=ṔoVe\Yl=2 'OD$T-Yŝ2p /'IT$5²n25$ϐ!SΏSy4v- GL7qt@ Qza dTh\FQ O';3Iuh 9׵PK8DK! Tpart.sparkfun-electromechanical-buzzer-ns.fzp_69129ed5bcec2b4b26eec3be62bb1125_4.fzpPK8D0; wnsvg.breadboard.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_breadboard.svgPK8D/= {C k>svg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgPK8D;2b svg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svgPK8DHnUl svg.schematic.sparkfun-electromechanical_buzzer_schematic.svg_69129ed5bcec2b4b26eec3be62bb1125_schematic.svgPKY8DN\+DISynthesizer.fzPK8DǩR8tUSynthesizer.inoPKcAXTwitterSaurus.fzz000066400000000000000000000270541250202676700334520ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPKm5D2r-9TwitterSaurus.fz}ks7+x5U{f$ęS3JϹ\2E[PHv~B?H%=M6^{ 4Ňf4}tf:\{g>o2!3ܼ:A~w}fr~s1Dr8zw9d*!Wz0g߉۳7pӇwzp|q֙fP;3yoO v4l\9]p3 uN9fdi[L'4`:^F^p~a?C}N?&˛ߔԍ F'a\}u5[//G߮i,b}W7ԝrno(76<5r8b)< ۼVӟo=f< p:p~3ac(Y]jVg|U>Yڴ3>ߕ,tx3C}S¦_xy>{=2SxCru;YNM7g$:/st /rSt0t+yY;Ya0>H@*ZU 2msGg>+t*+^*B:XaQ?)QOk3?F#΋TT];sæ-*-p/=v6#$=ESjP=}©<ѭ?w~~s+:ח̷ROKWd.i?]B^PA%;$յ=4 M܁.P|CWБç96ҾUi/Nelp4~S l7rUΙv"g:.mv>s*gL'3'_n>MqEZpU#WB(YXͥd@O+G6fwp.8e3-[9WiyDVt4iBSO/jݬv{1׊$>Ѕa -–.K5,HG<.{q; ^A` tDӃG\z>+䆷ӽ R(+&+_3+ODrsR b!H߫'"Д9tx){g# [t"kch݀60#h= ,%Bz&sz~RhbJI߷gxJ`b qQcc9@{!i6 #^-egold6\,[`$b,ߨ=2:VwE԰IGmi5t 3Bb\G9$߳l굗]=UrL|eے4[1v4L.2z?4pB6&7C[Ľu|}W{)F̖|OH/smՙ2"m*\D{hr}_:PV `ꯏUE[_O ._Q X> X%eC2sEjl>˅܄kddsg"ЮX!n,}ML8Ok t;-Ӕ۩5xhcqZ )"x[Pp]}ZUM"pPe67(B$Z e Wo+;nV8IoOZF}![WtZ $!I9,)s eeB(xJ]INNc[|JK]>W <^ʍ$ʜ{L|"dˊJZ #MSmŒbfDֽĎciMzC|;X̐gjKQ%6d׉-6q)]lF15_"""0I+&Ėyjq峲G -u7,.cey=8:Ewk'jc-AGcfDY;!䘤}B9$!;Y{o^M1Tߧ1:Ew&bwxxLҾkɇ[Xom"NNllyX[x$=k lűcqba $ǁXaaz!0nToz9/qhY x}^>N^cp7ϝg(7=ܞ?w*}wFwvs¤. ssu\cyׇ H\K3YSQÿuG+cfv}tLwī\ Wg Y4>z"n:\єG"m'x+p(eftM r@;U+h{e>.*-k3--cςL!eȝߒ=GNlyrbe+򈬬-xӟf 'V1"de,{ome&*jNk2Bd<&i/ӑocTll{pDƖe=jQx$}G;Z -bcqb(qL^#-ƐR8xH*fZAŶX6;}YTL3Iun1*>&-;ST'*TqĒn1`pvTERǑKr0*YɻٖtlBm E7^Ǘ/_Ͽr{?.fOraws͋_G.g ^V7y<]z߇/?fU6yח=wT8ϜUGbM.y)]u=wON:_:e:Tp:6 ׋Q2X|S]Ӊ"~;ө?W^\zoM{A.3੫x.WM ϯ? ӵA׆7=aoNͦLGw~cW8n前1>΂W$w-%<XLάzUzyUpV36{g Mhqcm D-[`L--YWlB>W.y[y#W0f:\:btۯ>W5={['O~gzճ~w~yCGd?|u~99L`? 7E p1j^zxs\ם^L ;?Saa]TO'7Oz?^w2|Ů} wFNN7Wю kRU ZO%& '%Zv >{QƵn?^EP~T@"NVl`7aw7e%AՇ%;EYybהuCUW0bW6E72E7ϴ.qh }S7rl2m\dV X";.܆J"< h $eBA!¹,iQBvUpE-O=ȥ RZ*|,kV4DžӃ[ P뜩F.Y\'lh٭:SZVXsx=hU lU!cOǡ((=ogabE$ҙpNǗ&+  ·QE  "ʻwe&t:g&<Ȯ\E@C9Sj >8 Ft.Ũmp5,qYhMNJ};הiA+T|yP `1bPm\IU9'r3' 8t3 N+Pdݹm"IECNgꄫIpP w*YFh"#XؾeO._څhQE; АoJ 3PKa~@Dny]اe[617pB lzTz^CE$ ਡݞxEu\18jK*˺BWUe!B{QCcTq,`SyhwۋVQ-iAnAB|qg"jɸY>a*(( X&V  G)5Nj*lkPMã<[tzeuQ>t(CiZ(VM侮  >/G[hW\D{ubm/>O1*\Sbb)ͳ.W rI9y !Bk@/XT.{jHBxGΡȆi4&/vl+M +.F4؆h(. ~tuhv+\\.{!|@1p@v94% QE(0r_"7Í~@*Sgkvju2+vڥY}\Sh~)z1kcCMV>tW`Y"`XqkW:$,cH0z\j@|"-Cl?_D[aLL@'dumKY5d!aCDp͈4"SG4] \Ttv+K\ip DrhKjPB][Xaa jt$~5n]\jǠAF Ihc/@P082B\=   K`cc f.цpݻ[ + +[`E3ڮ;jA~0sf3HY->)yQX$?O.`Y fqltWӝA1D8 e,eq9$@(;f`0 >7E (ˡ<.]2k5)A 0#r/>i()HπS,F= 2cƄqj%wxga3mH$!gnH[؝L評KE HOqLuJ:`Q w ՟JB!_I-29'48 Up< H:'zTr-b݆z\RHX%$29znlr(̡ >b#ͥh0kR03HP̦ VԂ*:4Rndn;Ǽg^M@΀BpTDžQX%3^ hiyAKq0#lЃF3(M҃I"QujTaO1#c K! (aZMx$ 3X`Qf暲#;'0m|wF9niUfB'\sFp/K3 + @rÜ2F93U@4'0'北n% ynS4#+@p `$-UdX 'U9GȔ@"thp\Ŏ9ȫcN"EWE-yv(`5u˜ KIJЏ'1AypkNyB4h//D /,'b^JP+(iM08dZ&,ҭbL$i%Ox H?J/t.u17/"jV"j vQmEs?vF T2󂁅gV\iRIS?hW Ad,d8|e :*oϠHǁrA87Μ.鲔.Դ|dsG76(9 {4RVJ?w)24=LNe2ZF"))R<`R*ߜrI@/ \2;PE&jۯ H"&,ב˓DΧg )4AԭRk 0lJACc *'!tFf%+a9>. EvZ6J6~瓮e' R\wkW0@M'态D(IQeb p

A/&-=Si^&XX/C> % Σ=9?|'eNR)x{N9iPUZ8FpDGfl wJKNʤSd1)8(rJ oqЅvrv,c+ƕńAGm~R F aWW_4[Σ!(DEdrU#y=Yngk8 i:TJ"eF/2PAHМ[AKDE~壮 M\ 4Rˆ#oP)R/-ω/ U8Au H9fDdH-M0\M'Um\ K* ]<bF`4Ѳ2$*P A;]eNՏgMM Fc~~W$54,Dc ڋquGЏ`V.RW/w]ԠI7 $TVd|&ի]Ǖd9[QVi0V2Ņ[̈́HrXW^\y6yZi$[sNqIN(S΀xuv.ld5BN'+ɦ|<$)(8:,kbLi'zWZLRi`.fXhԲ:Ƥn/xs6{NκڻLouu)LrkRؤ+|5!qsN0*Lg2vFa? ϧW`Ѹie :LkȂdJz9O)4E'Ӱe,(8UDhՖ Y{=`nq_ ;G'-mѻs;I,[|aø+lF=~on~؀Hty[؇֬؂;qo[ *NK0rfH^'\`۵EC﯇jU*{7}޾j(GZ*P{0oZ}VGnnnzI`z  %|UEC_h/m1_і-FoTɠ3:+~V@텑tDUMh_U#~M"!9p#{2P _e%dqק >+Dc]{Tl[{bT̘f<fT]XT|mFDsB_Eߝ H\ N\l1bǃ${̰=Iaj sQ|Z@´L톂'iY` ֒O]]v-41ډ#WK)y 4ZWt_Dc}xWK〼]-qV,"鸵 8ݝj0> ~epN<815E71Ibm](Y;OPKm5D2r-9TwitterSaurus.fzPK>-fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/000077500000000000000000000000001250202676700304415ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/RGB/000077500000000000000000000000001250202676700310535ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/RGB/RGB.pde000066400000000000000000000026451250202676700321660ustar00rootroot00000000000000import processing.serial.*; import cc.arduino.*; Arduino meinArduino; int potPin=0; int value; int redX = 20; int greenX = 20; int blueX = 20; int redPin = 9; int greenPin = 10; int bluePin = 11; int oldGreen; int oldRed; int oldBlue; void setup() { size(255,300,P3D); println(Serial.list()); // List all the available serial ports: meinArduino = new Arduino(this, Arduino.list()[4], 57600); noStroke(); } void graphics(int theValue){ colorMode(RGB,255); background(0); fill(100); rect(0,20,width,20); rect(0,60,width,20); rect(0,100,width,20); fill(255,0,0); rect(0,20,redX,20); fill(0,255,0); rect(0,60,greenX,20); fill(0,0,255); rect(0,100,blueX,20); colorMode(HSB, 100); fill(value,100,100); rect(0,160,width,height); } void draw(){ value=meinArduino.analogRead(potPin); value=(int)map(value,0,1023,0,100); if (mousePressed==true){ if ((mouseX>0)&&(mouseX<=width)){ if ((mouseY>20)&&(mouseY<40)) { redX = mouseX; } if ((mouseY>60)&&(mouseY<80)) { greenX = mouseX; } if ((mouseY>100)&&(mouseY<120)) { blueX = mouseX; } } } graphics(value); if (redX!=oldRed){ meinArduino.analogWrite(redPin,redX); oldRed=redX; } if (greenX!=oldGreen){ meinArduino.analogWrite(greenPin,greenX); oldGreen=greenX; } if (blueX!=oldBlue){ meinArduino.analogWrite(bluePin,blueX); oldBlue=blueX; } } 000077500000000000000000000000001250202676700332275ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurusTwitterSaurus.pde000066400000000000000000000144721250202676700365760ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurusimport processing.serial.*; // Einbinden der Serial Programmbibliothek import cc.arduino.*; // Einbinden der Arduino Programmbibliothek import ddf.minim.*; // Einbinden der Minim Programmbibliothek für die Soundausgabe /* TwitterSaurus Dieses Programm sucht nach einem Suchbegriff auf Twitter. Wenn ein neuer Beitrag geschrieben wird, wird ein Sound ausgelöst und ein Servo dreht sich. Er bewegt das Maul des Dinosauriers des Fritzing Creator Kits. Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ String myQuery="Dino"; // Begriff, nach dem gesucht werden soll Twitter twitter; // Erzeugt ein Twitter-Objekt Query query; // Erzeugt ein Query-Objekt Arduino arduino; // Erzeugt ein Arduino-Objekt Minim minim; // Erzeugt ein Minim-Objekt AudioSample sound1; // Erzeugt ein AudioSample-Objekt PFont font; // Erzeugt ein PFont-Objekt long timer; // Timer wird angelegt int timeout=1000; // Timeout – wie oft soll geprüft werden? String lastMessage=""; // speichert die letzte Twittermeldung String currentMessage=""; // speichert die aktuelle Twittermeldung TwitterFactory twitterFactory; // Erstelle ein Twitter-Factory Objekt int servoPin=10; // Servo an Arduino-Pin void setup(){ size(400,200); // legt die Größe des Programmfensters fest ConfigurationBuilder cb = new ConfigurationBuilder(); // ConfigurationBuilder für Twitter cb.setOAuthConsumerKey("uzr17kGYqhgNDjTBNQd1qA"); // Hier muss Dein ConsumerKey eingegeben werden cb.setOAuthConsumerSecret("ZZUfCHruwv4d6Tn9uGz0UGebxfn4oQDikv3NeCbd14"); // Hier muss Dein ConsumerSecret eingegeben werden cb.setOAuthAccessToken("221060254-8MJIyVpXotDhemKaJKVN88L1FlCcndToB8y143LU"); // Hier muss Dein AccessToken eingegeben werden cb.setOAuthAccessTokenSecret("A2R7IkcSniMnBHYeRK02umHoIvrsHQAdx4NaMq6toY"); // Hier muss Dein AccessTokenSecret eingegeben werden twitterFactory = new TwitterFactory(cb.build()); // öffnet eine Verbindung zu Twitter twitter = twitterFactory.getInstance(); minim = new Minim(this); // Minim (Bibliothek für die Soundausgabe) wird initialisiert sound1 = minim.loadSample("sound1.wav"); // Sounddatei wird geladen font = loadFont("OCRAStd-14.vlw"); // Font-Datei wird geladen textFont(font); // Font wird initialisiert println(Arduino.list()); // Alle seriellen Geräte werden in einer Liste ausgegeben, die Nummer für das Arduino muss arduino = new Arduino(this, Arduino.list()[4]); // hier übergeben werden: Arduino.list()[nummer] arduino.pinMode(servoPin, Arduino.OUTPUT); // Servo Pin wird im Arduino als Output festgelegt } void alertMe(){ // Methode wird aufgerufen, wenn es eine neue Nachricht gibt sound1.trigger(); // Soundsample wird abgespielt arduino.analogWrite(servoPin, 120); // Servo wird gedreht delay(500); // warten arduino.analogWrite(servoPin, 20); // Servo wird gedreht delay(500); // warten } void twitterConnect(){ // Methode für die Verbindung zu Twitter try { // versuche Query query = new Query(myQuery); QueryResult result = twitter.search(query); for (Status status : result.getTweets()) { println("@" + status.getUser().getScreenName() + ":" + status.getText()); currentMessage="@" + status.getUser().getScreenName() + ":" + status.getText(); } } catch (TwitterException e) { // bei Fehler println("Couldn't connect: " + e); // Fehlermeldung wird ausgegeben }; } void draw(){ // draw Methode ist wie loop in Arduino if (millis()>timer+timeout){ // wenn wartezeit vorüber twitterConnect(); // Methodenaufruf timer=millis(); // timer wird neu gestartet } if (currentMessage.equals(lastMessage) == false) { // wenn aktuelle Nachricht anders als letzte Nachricht ist background(0); // Hindergrund füllen text(currentMessage, 10, 20,width-20,height-40); // Tweet als Text ausgeben alertMe(); // Methodenaufruf lastMessage=currentMessage; // letzteNachricht auf aktuelle Nachricht senden } } 000077500000000000000000000000001250202676700341415ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus/code000077500000000000000000000000001250202676700341405ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus/dataOCRAStd-14.vlw000066400000000000000000000752661250202676700363330ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus/data8  !  " #  $  %  &  ' (  )  *  + , - . /  0  1  2  3  4  5  6  7  8  9  :  ;  < = > ?  @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^ _ ` a b  c d  e f  g  h  i  j k  l  m n o p  q  r s t  u v w x y  z {  | }  ~                                                                                                                                                                        1 9:=  >  A B  CD  GH  PQ  R  S T U  X Y  Z[  ^ _ `  a  b  c d e  no  pq  x  yz  {|  }  ~                                 !   "  &  0 9   :   D   !" "  "  " "  " " "+ "H "`  "d "e %      -22 v gH27(2-T (gnN7#2#gNBvv-ZT}(g`7}2 TT}#2(gg2N``T}}#TTZTZ 7722-g27Bnv`n``7#g #N`=7gZ(}g2Z(}#vnn T2((v=-2N#n(gZn} g g g `Z`Z7#n g ggHg#7ZHT``}(g(Z`2BN`nH``=`nZg7(v g`222#7 B7`g`Z77777H22-(HvT#(H} }NH7-22222222222-27Hgggg g g g7 `(2 `-2Z#2gѾ2(g7-2-2Z``Z2 -g7-2-2g`Z27#T2-2-2g7T gN g n g g gg -B 7===N` g`2-2ѣ2-2-2Z`B72N2-2#-27T=222227===n2(22-22#(-272--HN2 v g g`(22#Z-#Z}T2N2-2-27N(2(222=22222-22(27B=H72B7n#H722#7 B7`g`n=HvnB-77g7v 7(B====B-((((-7(BBBBBH nB #nN= vngn(HnHB`Z7g27#Z#72-`-}#` Hv=-22`(2n`(2g`(2g `(2g `(2gZZ(gN}љN#} `7 v=ggg(((B772``g-(2N7#B--7v22H- g-(}72-22g222-222#2----g -`g(n---vZ72727=n2(2(g(-2222(2``Z22N2-22222(--gѣg g g g g gggѣ-gg g g g2 g n g g g ggn2 =(n# Zљ }`#B(-g2-}22BB2T(22222222222(-Z#-22H2222g--2-2Z2(22=22T#v==Z2-2v-##--T`-222272#B}22n727=2222(-22Ѱ2=g-g(-2-}Z =}`#(-7}2vH2-Tn(7# 22nv` # g g g g g g g`(-2222222222222222}(`(-22-2`-2`7Z`-7=Z(-2222}7-2 g(2 `(2 `(2 `(2n22(v#-}N# ZvB7BZTB}}H##((-22g #ZT}- ` g g g`2g#=} vH##Nv }--`ggggg`#(BTv#-}H Nv(#(-`2-v22v22v22v22v22v2-v2`2-v=H gZ Z}gN=vg````````T7-g#7vn}ggg} gя-nggggvZg-g-gnTgZцv gvgggn } 77-BBng 2g 2nBH} = =nNgnZZvgg2 HцT 772#n7Ѿnggggg`Bg Bgg -ggnn# 7=22nv-nggHBg ggg ggTg- g2Z(g`nn Zvgg g g`n7T}Tn ZN=gg g g g g gg nH#n-nggZg2Hgn7ggvg(g ZZ (7=n2gg g g g g`n7TTѰggg=ggZ`gZBg`( g#`-ZT#Z2Bg ggg ggTg- g2Z(BBngg -g -g`HHTg=gggg 7g-gTgngggNHn Bng 2g 2gBHя-2# ZZgg=7g(=g ggZT2 77#vTg v`#22ZHB2--222222- ц`TZ( g2g2g2g2g B =}BZ( g 7`- }g(7(Z(g 2gn2- g`Zg(gZ=n}g(T B T# }-B=v(N(Z H T( g 7`2 }n#2NBTN=Ѿ vg `HnZ n- ѣ gg=`}`H2gg g ѣn-}H n g g g g g g g g g g g g n--gngg`g7 `ggn-`(2 g7N==v77(2# g g 22-`` }}Z7Ѱv2-2T#(--HZH2gTB-(gg=g`ng7 nH g-7 =gn==N7--27B`` (-}T# `nH7-Z-77(BN7Bg g`}H n g g g nn= n g g g g n- gvB((#(vN(2NZvN}Tn}gTn#-77v`}Tn}}=T}`n`ngv g72 g  gngnTZNgnv}`} }-`2Z2#v=27 }NT(TZN gB7v7` BH(g#`7- 2gg````vgg g nZ77777}Tn=` n-g2g#g27`g2g2-g2gg7#Z` H(777= 7v(vn `g `gZgn}-`gnѣ#( g nB#-Z`--(ZBZZgggngљTN-`-2 -2 22222222222222}#- }-2T`72#g n g Ng}H }NTZH#TT#NZ` Hg -Z}v7TT`B}7n}v- 7v7}gZZBN}v `7nT2- }N2 nH#v=-TH n-}--- }N2 nH#v=-(vg( 2Z g-2- }N2 nH#v=-ng(7N(2- }N2 nH#v=-#-77gvv7 2- }N2 nH#v=-=яnn}ng-vѣ`}`=}=ggg((2--T-`#7nN22T(-2#-B--7v22H-gNNѾvN}v T-`}nv#Z`(n-THn#`}nv#Z`(n-(vg(2T`}vn#Z`(n--Tnn22Z#`}}#Z`(n-N}v T-Z}nvv#g g g gggѣ-THn#ZnvvѾ#g g g gggѣ-(vg(2TZ}nnv#g g g gggѣ--Tnn22Z#Zv}v#g g g gggѣ-ng(7(#(22}22ѣT(222-2B-N}v T7(}-n`n`B7nZ# gn7ZTH n-N`-n`n`B7nZ# gn7Z(vg( 2T-v`-n`n`B7nZ# gn7Zng(72((-n`n`B7nZ# gn7Z#-27gg-n(n`n`B7nZ# gn7Zg=N(`77v-27Z-=TH(###}nB} 2=}(2n}#Z((}ZN}v `7Z`2722222222-2-`TH}-Z` 2722222222-2-`(vg(=`Z}2722222222-2-`-Z--`T H-722222222-2-`TH}-Z` 27N-#n}2`g g`#=7(vZ Ѱ-Z##Zg#`B gn gv g  g==Z-g#7vn}ggg} gя`--(TB#Ѿ7vn}ggg} gя7`#v -HѾ2vn}ggg} gяn2( `#BѰ2vn}ggg} gя#-77n`Ѱ2vn}ggg} gя7 ng7n- `2}--- ZTg gяцnv-`TѰNvn} BяZ љv gvgggn } 72#-g=я=nNgnZZvgg2 HцT `--(TB==nNgnZZvgg2 HцT 7`#v -N7ц=nNgnZZvgg2 HцT #-77g`7ц =nNgnZZvgg2 HцT nvѾTvgg g g`n7T-цgTvgg g g`n7TnZ #HT Nvgg g g`n7TTT nn72Tvgg g g`n7Tn2(` #BT2ѾBg ggg ggTg- g2Z(-gBяBngg -g -g`HH`--(TBBBngg -g -g`HH7`#v -N=ѾBngg -g -g`HHn2( Z#=7цBngg -g -g`HH#-77g`7цBngg -g -g`HH2v7ZTNNT`7 -(-2 Bя}B`n ggZ(`T` -gZ( g2g2g2g2g B =}B`--(ZBZ( g2g2g2g2g B =}B7`#v -NT g2g2g2g2g B =}B#-77n`Z g2g2g2g2g B =}B`--(ZBT( g 7`2 }n#2NBTN=#-77n`Z g 7`2 }n#2NBTN=  ѰѰ}} 2#v`(N}g=N}TB gnnHvZ2-}-2g22g=2g 2HH2=Ѿ2#v`(N}g=N}TB} g #7g( HѰvZ2-}-2g22g=2g 2HH-7gTnT-7Hn=TB Z-N#n( 2ZT-g `#2=ZT#`2#( =(2--#2HHN2#N(N n-2v(g-=7B7Z-N#n( 2ZT-g `#2=ZT#`2#( =7(-2HHN2#N(N n-2v(g-B`T7vZ-v2}T2-}(22n22g2222n22n2-g22}T-n}n(# = N 2722-2=2`Z2#-2T22g =2n2=B2vB2-2}N2-`-22nBBg7TNv--n2-`72}T- = 7Z`(n7=-ZZ}22B 2g 2g22B2n#2 NTTH ` g n  n } g ` NNTT `2=(`vN(g7-B7T`NNNT-HH72 #(-TTBBgg NTTH ` g n  n } g ` TZZT  g#g(n`vN(g7-B7T`NNNT-HN72  Zvgg g g`n7Tg}ZZZZ7 ѾHvHn7=22222222222222-2n=#-nHg2 2`}ZZZZ=7= n7=22-2Z#2gv2=B2gZ2-2-2n=#-n-(22222-=-`(2 NHg2--2g2(7=n2g}TTNT` =g`n7T-v#nn` 2g 2g- 2` 2g22g# 2g`T2g 2gN2g2` 72Nn=gTH#`N2n2222=22222222222222----HZN=n``# 2g 2g- 2` 2g22g# 2g`T2g 2gN2g2` 72-(BH##`N2n2222=22222222222222----  Z=(NTN(- (2N=T7gv`(=H(2# ((  T2(T#BB- NT`-BZ ggn-`(-2(T-n-=}---`27v(-N#-2v-T-nљ7vg `g TѰg g} BяZ#22ѣ2}N2-v22g2-22N2(22=22B2- (gTn(gg2g7ggggg=(v22ѣ2}N2-v22g2-22N2(22=22B2- }`(n`Tv(gg2g7gggggNnHZ7Z2n77= n#}#v2(2--(B((Nn=nTT#NTBvT v7-v#2HZ##2n77= g#}#v2(2---H7nn-#NTBvT v2(v#2HT`2-B}T }HvvvB-v#-}(NT##7# я-Zv22T2 77#vTg v` nvvvv`vg-(ѣ72 }B`((TZHZN=n` nvvvv`BN72=n -}H`(((77 vn` 2g 2g 2g 2g 2g 2g 2g 27#(72g2 ((-#77 (#2222222222722 22}=2=-TvngHv-n` 2g 2g 2g 2g 2g 2g 2g 27#(72g2 ((}`T B-}Hg(2222222222722 22}=2=--Tnn22Z-Zg27N-#n}2`g g`-v#vn22ZTTT--``27 ZNZZ``27n#}v( }vn =N}`ngNZTZ``222ZTTT--``27 ZNZZ``2( }vn =N}`ngNZTZ``2B}T }HZ}vn#vѾ#Tg7=n-я-Zv22  vg `HnZ B-(gg=g`ng7 nH 7TvZvNѣ 7`#} -Nя-Zv-2 =HZTNT=g`nn Bng2nZ}2-}2Nng}H}n2( g #H=(#}((( #-N=T=nn2H`#g=H` TZ `g--g22v22Ѱ22-Z22-- ZZZZ`B7B`ZZZZZZ``N =n-vgZ ggggn--n ` ggggg7H--}v2-#(Z72vvBvZ-(2-2}2=7N} HZ 2- 2(2}2B2Z#n2ngѣZ` g gnH2ngѣZ`T-nH Z72272=gn`- Z`(  7` `n(TH7}=}}=}2v(`7(gnn}-=} 2}7n vTn-=7(7v2BT `B}2nN#Zg22 #gH(}-# (TnZ(TT( g2TZ-2Ng2 2v72nZ`N-gZgZ(gN}љN( H7 v=B(( }Z--222222222222222227NTvѣgN}=HgBggZT =vnnvBN-HH(n } gvZ722=BZ7gg}   T nvѰ N TT`gg g T-22g v`v(#B Z`#}gZ(`( #7nZ-g# B7(BNBB(`#-7#g=BH `7=}v} vn#T-B Tv`B v#BNB2`- Zv2#n7(7=(v(}#-gNvn ZBv`H=v#==g  -Zggg gg gg gg g nH#=7=gn g-TgBggg gg gg gg g nHOCRAStdOCRAStdsound1.wav000066400000000000000000000240201250202676700360660ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus/dataRIFF(WAVEfmt MMdata'~~zzx|sx{z~||}vz{~~uotswxvx~zw|~}|tkhiqzuxz|uejmtsfdokjhs{trnigccdsvoh_ebcbesoZYb^Xbjt}rlfcUSS^by{~{vm^UQIS^nq|{iXTHJRfio{of[JMMQfdn||oeUFGQWZi{~td[IDHRfjt~r_UMHKR]hnxqcWJ?IZbir}tgI;DR^^fsû~wdSDDQVXdn[J>LY^aenrYCADRaZh~Ƶvh_QMDPW_crlXI:ELXcd{{fM>BLZZ_ksŹkL?DLMSdtÿt\JFMSYV_lzq[L5CT[bjo{ǿubH?FOTZi{þztXIAPOValy~oROHKL]dfsbOBEKTYju~obHGV\LZclyõt_NDEHT\m{~m\H>JTYlrv~wqaPMTRVZ_woG1BIVfqwȿ~|zlZNLMOR`j{]H9HK]^iyxh[IKKY^\guoWDADNXix}mbVJNSP\fnzn\MHBTaekkunV?OUL[aguxbOHQH[dioxŶhSGHHSVfoq^X[USIT^ktƹwlZOF>O_pt||o_UTKMSdlktv]N>DK[djs{wi_MELU^hkr÷|hSEJGZ^iu}lN=9GXfjwbRQOMUV_`u½nW<9?Nddnwƹ|cNDBP\ZdqĴlcKAHOOUk~re_OCIWW]kxmUOFROTXtzeaS?ALSftjQINOQWbbn{ƽ~hZNDDKQbhrŶ~_KEJLTUeju}{fV?EKKQfo{j^JHJHTXfy{nYOEMRNXix{u]HKGJTeqzpJ:BLWbtrxŶ|t\KGKIR^qpVJ?HVahho~þ|rogO8L[ajgitze??GKYdmvvhMDJZ\_hcn|dL?CTV`fu~ǾzeQIDHKYfwf[TQKO^_dtgLIFMRegn~~r]ZVRORXks~s^K>FL\ivxljdZVJSXbgw¶xhXEA?Tgjy}wee^OJBZ^mtvƶyvfNHCFZbhv|kaF:G[aegujOH>L]Zdri^LFFY^^blw]I@?GYfn{¶zjZSLEK[^ktyiQ=DNX^_jzƷyhH8EGN_jwIJwrfYMBGZX^lrXF:?L_iev~žzo\FKEHRZfw~tm\LDEEZbq|x_QGCJW_hnsĿxsYFAJQUjorgREBTX^iqwsfUKMR[Z^i{y]F9F]_cgo¶~kZRGOMTZivr_KDGMXejtxycOFKJK^iv|jWKKOZSesq~tVEILNUcqld[NHLTant~zwnYCCNR_grxrdICNSY]sxvfVJQQ\bei~|lXJHNZhw}lbNDHMTbbm{þ¾v\G?JQY_t{hVDFTdnoleciؿoUE0-8K_qtshabvɭ|[?2,.>Wjvxnedm޿lL4($.Jet}ymefvѬ|X/$,E[mz}wkbq߼d?&"'6Ogw|oijϮrL+"-1A]tvljw~[?+#$9Ul{}tko̪nI.$".E_w|qkv㽞~c8#:UnqfmάoF(&Dc|zlft㽘~\52Trrhlө}~tL%&Fd|~nes⼚{]84Usuko~ͨ|~vJ)'Bcz~qkv澜{a<$3Rowhhҫ~|uN++D\y~nitƢz_>*-Kjyoqܴ|{vU4':Yuxqtȣ~eB*!#-Jh~{rtڶ|_;&!:VoynrͪtL*'Ca}uls߻~[:$'6QlzosӮqO4&!.C]uxv|äfJ-$%5Jfztr~ײxV1!)D[rytrƦc:$)8Hdz~srܹ~xO4$$(9Sn|rv̪~fD,""*Fbzrmݸ{|T7$"6Vttlsɦ|jD&#.Fd~yoo⺘||X8'$7TswntΩlG,*Ddz{nmz޹^86UosknѪtI%*B]x~rkzğ~^<$-MlxmqկvR8$;YtxrvȦlG(%+?]ytr|侜}}Y;!"/QnxquϫiD*#.B_w~stܾ|V8((39Jdwzqz׷jI4)'),#%1Jh|}swشtS9%,:Wqxuy˫kF0#"*B`ysn}޼yS5%!%7SlwoyέlH-$/?[uxv|ã~{[;,&!,Ng~|vwزsS8!$6Vpyv}ƤiI+-Id{zv~ڷ|\:&%6Uo{tqͩlH*.Dbxus}ܻ~\<("(7Nh~{uvҳrO3%".?Voxu}ǦbB*$1Mgw}trطvS6""/=Xoxv}̮hI,%&2E^vxt~ܻ|Y<*(+6Mh{yrxԲrS4#/BYpxu~˪gE-"$4Hdxvvۼ~uY;.'*7Tl|x~ϬqR8'!/B_szx}¤cD.(#1Kh~|urճoS9&$,=Wryx}̪fH/$$,Dby~xx޾y\=)"'3Lh~|z|Բ|lO8,**8Ws{y˧}eG/$$/Hdy||غ~vY9(()6Smxx̬}gG2&)Faxxv߻}|a>)$%1Mj~wvײ{xW8("(7Wt|svͩ~}jK6*&,B_zwx߿|cH0'%4Ri~}zѱxZ6#$3I\o~{z}ũjF,&.5Khz{xڶ~]='!,?Wo|urϮztM2%#*D^ywr|ägG,&(1Fe}~wwܸ~xY<(#%6Wt{ux̥~mO0#$1Cbyxxž~dD.!"6Lh|xyն|z]<&"-Pf{||պzbH1-4?Vn|ҳ~z^A.*2G]r{~ƫoT;-*7Kex}{ֺ|eI4.5FZfx}̷v[F84:JZm|~ȱs]D62;N]s~~ªnV>45DXht~ʽoWB;>JZiv}õ|lXIBDK[kx}~ûxl\OHLTany}}vndZUV]gqx}~wqjebchnty|}|vokhimsz~ztnjjlry~ytnllqw|}xtomnrw|~|xsooosy}|yusrtvy~~{xvvwy|~|zxxz{~}|zz{~~||}~~~~000077500000000000000000000000001250202676700333115ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus2TwitterSaurus2.pde000066400000000000000000000060561250202676700367410ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Processing/TwitterSaurus2/* Just a simple Processing and Twitter thingy majiggy RobotGrrl.com Code licensed under: CC-BY */ // First step is to register your Twitter application at dev.twitter.com // Once registered, you will have the info for the OAuth tokens // You can get the Access token info by clicking on the button on the // right on your twitter app's page // Good luck, and have fun! // This is where you enter your Oauth info static String OAuthConsumerKey = "uzr17kGYqhgNDjTBNQd1qA"; static String OAuthConsumerSecret = "ZZUfCHruwv4d6Tn9uGz0UGebxfn4oQDikv3NeCbd14"; // This is where you enter your Access Token info static String AccessToken = "221060254-8MJIyVpXotDhemKaJKVN88L1FlCcndToB8y143LU"; static String AccessTokenSecret = "A2R7IkcSniMnBHYeRK02umHoIvrsHQAdx4NaMq6toY"; // Just some random variables kicking around String myTimeline; java.util.List statuses = null; User[] friends; TwitterFactory twitterFactory; //Twitter twitter; Twitter twitter = TwitterFactory.getSingleton(); RequestToken requestToken; String[] theSearchTweets = new String[11]; void setup() { size(100,100); background(0); connectTwitter(); //sendTweet("Hey from Simple Processing woop woop #loadedsith #robotgirl"); //getTimeline(); getSearchTweets(); } void draw() { background(0); } // Initial connection void connectTwitter() { ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setOAuthConsumerKey(OAuthConsumerKey); cb.setOAuthConsumerSecret( OAuthConsumerSecret ); cb.setOAuthAccessToken( AccessToken); cb.setOAuthAccessTokenSecret( AccessTokenSecret ); twitterFactory = new TwitterFactory(cb.build()); twitter = twitterFactory.getInstance(); println("connected"); } // Sending a tweet void sendTweet(String t) { try { Status status = twitter.updateStatus(t); println("Successfully updated the status to [" + status.getText() + "]."); } catch(TwitterException e) { println("Send tweet: " + e + " Status code: " + e.getStatusCode()); } } // Loading up the access token private static AccessToken loadAccessToken(){ return new AccessToken(AccessToken, AccessTokenSecret); } // Get your tweets void getTimeline() { try { statuses = twitter.getUserTimeline(); } catch(TwitterException e) { println("Get timeline: " + e + " Status code: " + e.getStatusCode()); } for(int i=0; i A2 :NƆE */,A IE={N9ѷ?Nη\ʥ9]N?9Cbyr L\tȭg:ϳd3;ێ.2_p7of42.Y蛣rvҏ`O>s+ηϾazt}1m jljlomGWۡ0|v&,fǘݑ<<٬/ϏWk࿃fyEYA[o˝o秋n9ݛw/jtWw\<]nqXmclf6_@~~^.?/+~헯kJ2Ͽ{_P:h,ś;L,V_/~ظ܈ȧX-粠k/'nqNͿ~zqz:_oӶj^ޮ_f?/67\ ̧5f. mEե\B>bϦ,?f}?Ԍ:;)&rp,g/C]t0T֧ gy6`۵M]{p}~i5o~~mղI}<,ˍb5ʬe"|qշ/b\{ ܽf$>}o} \{q{:Xtid$^|ɟrnwt[7YoNTQ+x)֖!/yY?GGSݐbN}O'?/2 lbq"jΖo7|x@fBG\6,6W }\ZDNyly|jgZ?OcjjzқfQ?Nʔedt׸,+޸O-VNƾ(Wv4 i!6 ȝ;`^> vE|{\3k' "w9_-ՙwO~"eitLdxCz$ĉ&ڹo@KHXG=KruOWoo>*`??;j:=N?/GfbӿG7!BHv*TGUb3o׋Wե_52q"6Fbٍ]]T_&|TG].gjG#k+2Ũqվ^-iEQQF.? nbη;FtiZ=_Cľ jgc{Ǹf}*or5&Yb<7I̫zו@Th~}#FʲƟVn] hƵ_SW/)' IrۙR%Euy5 GRD/q$)c;9C|^/OÞEB1S,(%DD^G"*f ;Vu䩪/[>6?Bu@4l  ~]֕ "IBw<ШNŢh؆/X`iԗM(? ԄLM}F"zUH({h`¶0Qn &qAUF㾏SJ!TԮ\y-Z+o Ws?1OJ\pNCH-aܙV7xMWnBDŽuI\{TTT]GΜʅQ\|#r.Ux,T"hwZr zL0{5 rʲ"\I Zj螵@eYPd}[U`7PW5m31*AV ]iEpWst[ōϫ1ƥ0bO\*7WL SJ-sTɕsI%<ޓW4cFt9X"R+!~,$D}K}jaU.H?^=4P;0=10nՆỊTXXq >qq6DT,C ɏʠFw8tEre%xBWB(VV\W Tb,+a蠗D@ &b&Y>x7ӇÍ.nM쩘 !IlnH"^fq Ӏ^l52\خ,ɕ wvF3pCF&}"[\AA - \3FRX V{+4wa!IB'LsԤwbv[XYh MtK#n@ۀ.kbs\U=ʘO'( $lFLQ| fm1)\uk`x`e#X3R;6yKPmnʕU3'DL&hlE`Iy?6i͠讧;|c+LE8ʖmq!9$ &&AE 8D+#!=Gj(Oc{lKy#py@9B3JDbCHCY 8%ڀ 3s̘whI;HAPHA5 ԕsYEGLX`+zM;`Q o ݟvJp!K ϐ/Фc3#B\4>223h_b\DxT"!W)`lL!` Iz &jXw# ' K }VȀzSG"@L˧gB;rF&*Ͷ`Tpay=6hc&#DLBɃar^K[D7J-F\;Z*a=e%n&=B`t%vuQV&Y3[ϙWPy"Fj)ǒAK@uY,BA4F$! <9S[#ា= $bͯO'&CUMm"zo(bV q{G`xg"Z{=YF$ ҐY{˹'F%!cX)B <"SX/a RC@56KHB@H1Œs c -Հ!!YIn_ K0D@^vc-YUm{ i^S$0j/Mt(Ea5WIK:1 vV jF0phMõ7DdL 72ĒFMrVԍY#D++`KF6!E=5uKGUn{CIC++`?ubBh )0LMAFIh3p3B?$3 T‡<*#Ɔi08FynP\@nrA2/)Х>lrFyG e{ @v fݶy[&LG67\| o ) `b;LGEG߱!0i#0$ܷ3 o+ i {Ϟ2란LW6' W(zN=kJ^o\ `fۡF VKȰ2b$1h=B:_u=v`㹓ӿX*1OCj;3K:Rsqx4h]5뼂 -r {[\t 4c4ChI.:ש U3K0yi*Yf@B(Tsæ*-w kD#ZcN_|^0L)t ]iq_?m" Ït٨Q!40AꎤfV'^p9tm'X_&F@F䳈A@Y:1MB{:tpHةI(m*XHfzWEQro\6@,&=ֶntnQ/-R>Q/X4s28c.,'LtjE*yA9J1QDZ{ܥ-7etYLx ǀG<ta]qlܪ!Vu}U 2_GU:{>H96*m$W rSt|NYk,Rf)^R~A48Bɓ:,VWy¢l!q$JH:0淹9ci9²ţX@DAZE /f=fޡL@]7rizN†.K:%PDnfPvA ,9fDqHfנfHWV)vU:_ܰЕQ˵i˃Dΐ@vC&7OP.(dn?f~E?#Ej|ajǪ b<]AINŐ$u]W5D2VӾ3k\Uo:.U"͞ފx Un9H4n`þ]_CLz0E<a6|G- MÐ2"xHP֘rP;[Qq+=BW%0hd @fr lMȰ',g(9&_Aq`flCqF3]" Ak@ck_ChOc:n@0y:kʈ!ui=f4] |TQX~At:TI8źOm9#%VXMs2O*Jgm(y4}й'56KגT<|8Gf;7/nlJ 2IAJC=}՗Ҙft݂3?LuG~Wڥz;šv)q5Jb[ < @ZWelLX UK 5 \saבkvq;8 _aÉ0%9};zF ՚P@[BuPs1Rjd&MfP()؉/Ckύ4m0ݤm̃Ynןo1i t3#&Huuel((lTYM#`5(8̸uJ8t O8 ͕w`( <á ?Pv~,,qC#> {oFvedyᶌ,[s{{u7qQw>X5O+7 ߋdIMGDHTu^:d!ái7&!y6~x[e-5mW rҏk1Zy7R)Xx@5gfh< D5 lP'VHeZKgMa߷ut' udx,go}齠m醘K>Usm`v'Pc]7sUQU;3EggL(::(Ww(~w @Mx~{Q"̪L4DNw`,) u\SQ;tDxTSX&#<:O=om;`H|6*'5gM>;Q6Re|j '5P.,>+WTE_x.}֛[yҨ+onwAxYߔO׾!c׫1vsSхr2{4L])N_qnGBwp :8goý9>)|{=[>c|$3n>-1/ը5[Y}9&I|V=vۊ>pv|pʿHIr^Iw Ŀ[3:w~;"q=13@مIW'*-.~UDo#t0P>?~b<= /!55i?*yk]*Xh_oMU0~*u}LA!>t?"=Ukz\IUFSQTbPғsQp_SZn?޶\.0K#SF`E7olPM鶗q;u^я ]*vrN_^lrw@N`017忛_qj&LJI]v{/66mV-a 4cM~~)Kqߗx>yo JϦ̡|PKmxEgWorkshop_01_Blink.ino+QIMQU04*LQ(N-)-TRP(OIQ  Ѵ檅(χKL,I /,*t*J$Vj@*}1PK9xEˠ FlipFlop.inoPKmxE  wWorkshop_01_Blink.fzPKmxEg"Workshop_01_Blink.inoPKD#fritzing-app-0.9.2b/sketches/core/Fritzing Workshop/Workshop_02_FlipFlop.fzz000066400000000000000000000331431250202676700271060ustar00rootroot00000000000000PKxEˠ FlipFlop.inoMO@9Ѣ޴I5~ƴ-LDNߝ6B630Ψ.dlKEJys1.5<\[XZ[|ɬsY+4% > A2 :NƆE */,A IE={N_L<3np3oG^&p|q֙fg_Jg:ŗ;WO~y7]~fR1ptu=LH^lNڞ'Win[Թ痗}viw]\0%@;"oʖu⥛ggkջN{_~ko]/?xěoƣoƓ?^|@⼑h*sۿM8/ɳyŋxK;\ݏ.~1 Ggߒw)xǣ_&"Tx.?\o`W5iUŒ+f5wogr2S77_B7_GniU[79B^k:_TpE>m~^Kڝ;s܅KvydƝwLvCz_ݍG?DHwwv6}s7{/7:UZI/2N[PFtʳf8G> ⻞Hu~b)cLW57߄Q!8N3*:%^/A&Yc·O)x h/Y3zEW!3nc_G'qXd[ntٿ\b+*\o`uK*5%\9n,e+ cуklb݅)gDK'&w>aO34l=m8ۥQkٽЗ v/[.Ȣo " ?D LoU|[:j=|MG!kqO¥KN\lkl~3XFgKtuҺMoC_ua?az)X O4 @w캶`f;L(s ں΁^UsksYY""! 33g;ٽf5FOrEtj0+:;}g>̤ƇEpTũ&*(gVхۋo-|׿unޜME'~ُ_}}y[o>]UE:N}{ȩo_k'ġ&h&x;N>}{i]}OSd@;PSM,ͼ?piyrOS>`Ul<a!?_/?gΧ2B4w3i8M}+Jo }|2xxWd{)Ip*M%Y+Agz):7O{!03dS%3H __xZB}ș,+YLkUZg`TLo ޏm%0uJ;&53#׬NϪv~`hMgE\.]*me z|~X$‚04F­o<>TY۔qc:զ훵\wy[} ugKhӝgUڥ|Lҟ=d OE\T=粒.U[B'r>%wmS򍡒.]ܬ.W?C3#3iHO^)ͫ?lymbOp#\jXJ^w=9dmFǙTg ߀~3_Mt+}Q({#LCJTA{*..|{&aZ`;E}/5F9.˳> -G,d;wOfMw!Pg>dzLz]<@8ZVqcU*5#PpLV>0WHAe?(΅8$9.˳ \E5+XUدH$K-,vB#2,{ & rBnҘ𭎖g8XH8eJ˺vXduɒ/{P\i Q%a;x8!2hՠEalKš- bORR٪f%?NbV Zq@f%/bF;] M>jSOO5eqeC!BQ+V-%iƞjfyݘMtAEn}*)GNIC[eJ{VUj%պ + vG˰},̰fk]jvBEKH=$ˉ/J"d=|ZnclԖ.tf`h5Z*XF)>B@eOU~2i2'^ݕżt֯tfi\X;5um l?tHj2利UPeV;~44İp4k]jj.گ]Ud)RUVDJ)3U 3_ĘKZp$&\<_N"͌('d 7^op i9cE? AM>ah"hI׺bբ F4jj>!Gj9')p\@ڄ1`*~_jJ^ jYq b9*/6jm50 Zk,Ϧq#:ђ*jVUFolnV@qD:hyVqx| +EZM?%Vl\jS焴-j *xIJvHqPY7q~Fo Dr#]SŷMDx)YZn8Co 3\E? 1Z?hVocbʺT=¦w5%B M˻۲YA’Uy^7j͠ewk%4*.jjdsPeC`SX+2٘tmYH­ov9YvpU[7%0YEo!fL?2STÄ@!6=VXha")␜.$EJv1ؒmM$U|oҪaFK!2O nV*̖Y5B[f-Yy$J|vt;Ie2 5 iww7er;}s?1Jww֓~]~oٻs+x޹ ??rӳCY܏/|t b'+lJ؜KEV d^M& VcǍ#x1x0 |;߼ǥXbv]UjЂ+eKNezVBZ.ݰ/ߧW7?o'_fwz޽Ktr~P{w:<I)aྜϯwX'c.UwqY+?sNhUgt NGߦp չ6\=ËaY{׆0^ON]{S7q~9y=83x!oS]χxr:6LDTvP^hټzWoF,?Zәo0*c4#afDRf߿l;? {xVܺ_f!pv.@w7UI9ž6 <;)}&TL,sIi>OMwSIgx;\x_'ogs/םD?W߽|zW|O{'}z4|^(o Ubv|eIvx;xapM!K~nr?8~{|wIktӎ/:_/:oNUlXE*+V(?@[oarvu?y{WN^;= 얁{qO+߿qK,T+U7y܅FMEmITe'jЩ`͝+2#. E:ɻ,.KqCH]'2uZuMtj1IIG#2lXZPpi/ᲥB^qYP%2^ ׉G,Uܷ<<ńv0zB$4PVS[8άnˇ7_kuq&*tp0EݲqR؋H٬%E٫WنIB&SU.B q.(}AAz.Ig ";T?Oɺ*Kt;Qtr ƅi+HØ0:`.hĨLu%P*1P+7ʻsM(/agMR@@ &ӿ pv+WpỦ\ω:~T=eWJs-"oDȳ3;VF5?ʅ><;WB&@Kg k c!CXF^2dER\+m0IisxcjI@J " ѶQ}iEiñSAFqAshH}D0BͲF&&uFgFXWhb`h!Q1F+]"b] =(»o.H,5KD.rC% 4ܨ7OO !m*fN|mq. x%q X;Bh7הm@*2.Dr!/=dLB_ E&a [qEqSA\& 7H a ])L1p.S|",-Y4w+8KQ {o dA4&LbT2 "8z B@ 9K.lL(l#쐚`82>L1̫O'R d21 1_BPt rܻ僨[˺+G`Am{I59$tA-H}bIn\SȚ٪7#Ȇ*3nL"`dC"2q9$@RKXp4芷(gȢ 8)e<( .] j6kRA\M3B! ƒ( %8YF= Ɍ2&;T#w:C@:"A8vyv'"H4H'aLUL:&JD+(+o7a'=a%BH&W(A:2qzn91b݊z\C@X%2YIqKkC fN)sH,R$3PĬIA(5HFlG5Hp(ngII,.ECHj懣8δǢ_y+ZdD %JBH }HXFIQI1dO!"GBɫ_ugz Ғ4aZPjfztF~¢RENe@ A"1{@JH2,]ժU-y{̸NP!S]+8b{nZϼg M`ULk!SDb}\ <4 G1F@$dEiZ 7E.Vn7QiD&ZHS(A&Z$TdDWD)& @LH$(m(ڕK9#CZi z<$½)4CNr $TuX^Hbp2X Gdy95՜mhOq(/86a.ChS:IN[It6 y<|\6?mtm&I[$g]&dH#f,τ5eE<' S@Eݧ m<#Pc70"^3!P:#P @ H%c4xdN2Z93eœ8'0'²'/Yupj;9ّQEtABLZ")c9=9B0ڥP}}M ##9<;la 5u KEI?NcuDZƒst<R3Re"ROBL##P~T^KO5xNm"!KJbH"I~ p+)((~uQ>"ɪL!"SP.PTj܏QY, A4oh,mZ8t=.;`Ku'L n T$ 1`D"ڎ$2I D<` j HTU&1c2wB !h%${[\ +IoBX&N\PA*b}KIa, T\6k%x\A-PEDŽ ԏT.r[,]|Y$d9LYqt1!Ppڶ[Ai"eGl*!h,rT Rw %UuT6Ey+݄q!#峀q Ad@-1L"*tRaP.DAzv*4,]#bs#hX|mDk0X  /d09lP Q=n0DqXtk dt dQĸ@$B#q+I{TuVLXBIʠ0}Q !NhWS*UU~lǼQUߡ3Iŏ!ꏈIŏBâMD?TlHJ/%D~kuu(RB$(b]nZ)yt\pˎ+*p>`<[kzJCB/,ܒH`&XE]# 5eqGnsFpƒ|IdH\z{T-pO"S- R80UjMWإJ튁+Al%TCTp,xba3LL; )3ҫ5rkVbl2׊ǖ"k-JCyfoubHjuuB5+KQ UP#P5BB%G$:1qDm!dF*HHy3/*ʀ?X7aU(ܲ\c9FBOHYZ8ROX8"Fu$3 VeȗFIXfCJwډ8ws، HU4!ϕw1! xr&1XN&u&faiG3r8,^e9VtԅNCT1Y&R3a-nVn)qӭܒU.X)cC#7)97Ǵl_ga 0;,fVL 17Ȱ0'΃\xvDMӻ'Fj; T0@MG1W5*{љmi/E5) .V(ZRRڪlErJW"a8,LĤ4X"^<,xOQQ1S0f++l9ZL a"sՎ*`aX*B]$HGts<~J"ʉ3$^,X!e+Ѧxa}9uԄN;4^q72I"mbỐaQ&ҰsjϖǪTr>o?ᔑ+[~q{b=wմ\ XK~`)mP ն72>Tk I>?Pm)},(&+QR p~/X8T|Zx//{zϻ )B%Ɔup2,|]LX. #wɲl RRquyyVGMkT|hD޳♎(ܪ8*q[9 ^s|4^)V.4ZVGw[οX@5СEVs:CZYui}Y$90 ak%,&FYdse|8o/rWh9#"E!?R?\lL!%lRHL!BP.˿RM RnB|!6j=njլvBe]e{(!~?1\1&l\%#(:D:yRJ 2ȏ/D aem-8QcDC|t%4ij*RGr?PEZ^ Ƃbf:҉?'ڦjeo鶖Q>Ztr2ʽac0JBG W0Ns4ǠD;ThLJ+Z߆`ȏ0vD#tnݹ3]XydLMײ@-{_ݍGߤx)7^Lng[O6~wwq?|Su5(#C+ n Q>[EeN+LWUqE*Wә#W*XjkEzQ#+Ent,mcYlC,|R^Tfh'LsS$PdGkB+S >GJºmϐmoRn go2IuʹٶF|%(e>%TsSM4HƧi;\M|¸JA|I&1-/Kla o3E? ;ӜU9NL))yJm*8jQR>LMGϯj1mm}'.;NYze#+i[uqjbh\}8w5NP\⧬SF_krM^1]#Y,4>&9Ey+[v]_U>W\&A]wm}P}]Nח}zǟ?PK;xEg*`Workshop_02_FlipFlop.ino+QH/JMquRS@ A2 :NƆE */,A IE={NUc Workshop_03_FlipFlop-w-Button.fz}#7y nhƌ}H&ΝҴLRW̟,&&f2'*pG$ ֥  s_?ݏ:σpUg q__Oߏo>ۧӛۜˉ)o3LJWf/:nz7g`tsՙW_/_Or?w][= oM߸/:xy5]t WOÛ_ |oU5wO^Nף_iۧW\7n^Sesk\ݓ7ǣA0q_קLK = &+~wo}0xttU5 |^ Fߕ{~k@wFs ܾ#r2W`k5ݏ z_>>}ױc<ȯ{t_z7zӠma2~5[lN+ ֶQeӎ|EMD=-Lb|>iΝG'߼_%?V0s%u9%L<=/x[yxg5w +Uvt߹{ўrC*gv;:| $U9 pUN]oW7ySƭV%-pXU-Eۣ »FȶeV̪\W!FYsTv9-sgg,+b _Fp>J6Jg>y,n,֝OQa:m+Pd+q)sV;ƪizIpuO~ F )2`/]4u5ж¦-ɕe*묭9*sL9 Aڔu(`[nil|j.)˅$RGrN*#z\2 .A=ܖnNw>*xʚP.$0&?}QW-rcnGϥ/U-)eC@hOC)ѡ&[mt؎6̤P%kj|\wc" Gә@BTx3cKNt_A)"Eh^ 2"g7Pr*2/jF53)Tτ杋N*m,+*<\.Y˜fOu܂śzm{ :"\|`m%Э'hJ>CS潚cHڟ4଴uB.k5dYotJ>,}|J>,|HY1hK*eJ>O!B通;sm1\o'3GW2,/7`O0"Dn}*bY *@smJ?DhONߥYgOB3&$ Jծ4- lJ +slX:ih.û]'RNta4;8E}Rga,.ɦXqX"a>+rˍڶg,DW͹J hœ!<*eΝ"4ǎ4cx ^zuxER8~[[oNH?h<1x&rv=iQ=u#mщc-.I<-',7!y a_.lHe)$̮LчG7),vm9z\O^dyX޵o>,RX1“L?KJ s{&$./-a`<ػ?)alha7O>9h:š*Rv<SƼ,/cBm0n?xO\ s(sv߮?H1ykIN$7+ voU>U9u~mXo ncu;CLz!ڰ:Z@Gt8ıeH/-)#+Te[fT\ܣĶVnQ 8ڼq(^Ao E@]c%n vy#Q/Bb#-J1\ъzc~ \#-f7sTR5 岢wP\,% 9fؘKҰ!s"\_tI%~|"_hTJl,q)Ex-Xa 'b@8b;BiMA .N!_'^m!9] "r6pH C jnn9 y&2M\u\_tǚR=K? s,j*fDB,(d(Ë0H^$&X莈D#IF_}7\׌;Nia]]dvށ LGWPx+ KZKAA9Qt,1=Nܥ>eM}O:eP SO.''81? IoڅJgg*kUGQ ~xEZ֬9۫5ȇYc6k""1˥#DG1tȼ/MGќqCh}4ڊ/:ήqyuJmNoOiW%)Ĵ I,VP(s.:iAY5Z4 }9Qqy7͵7VsnhS`jcϐ`'s(%(fHQ=ZHٜ]h2!KQ.ϵ2fD*HVP#MIYU^\ԹKcYXhꍽ,.8ͥpP'2I5!լ c\[RVsmI{ZKYYf*]E"?JX`f$Xh"ZH$Y{,&b_qeiFC>S:Fё} MrKhd'|T'F䗮*V/ 'I36}`V(%k&)CN{frp!SCU_Q74*C4qi3l$/t='}>:R̼G 8q"O>EW$R$@ΰ |bD;)0QAEqKHU$i?,z[/ 'Bόj pQ\=|f x # LީHjUz"DN96unM}OM,%xJME<:*FeQ~'I2WFphHzS/Gs'ZU^4z߾ Oi ҇XY3"k/$y+ VD,_4&Vgb0Br}ο24ebCĬ/u߉DV*: \ 5KorSʉ ;2&RaήR]kۀd푀z/p,*V*yTs*wJ%NmGZWt7997iKOhl$εXnX7yWJqNYl :t-Z>(3fE1):%jrܤ+h8lPSq*QEZ;/4JJcƚ یP^`ibtwİ3j._"yHLfXMŃ$rb`*7q/3\S4:VL|[\,} %[DV#)uy4Tc\ιL$εo?HYaE^A&l@^! eMEP^7^a:P!18 Ste_ դ/Qn_g`l6V_E·VqQy3*xyy2 PѸ+*gc(i(ΈķNi,FYbbfc׉_łd]ꍾ,5/k#g)5R-HoD΃r b,o9JkHX2]qhrٗz/yA u\*$ שy5 MwE3(ZaA}Mn[lqUzG[":'&W۰ j[OЫ5H|L$)1ext`vm֠`C“m doLW=:i&ҮQ{J6%mY/q^lNKI˛J&ՙ (@㚿\?7ZHZ1/MRe;-А5lJF3Zږ#_{gȪP#ѪggHMZ:<Z7đD:m"SKr\xdʁOܔÇqijp0iP@Sz_>>}הäp}~{5~_z7q>ӏ &"4v6~7/'ӧolFD _[6+3|=V|N-Fדk*cqhGpFHY2uiUo4mF q2? >zNulA `B)3p+zK0Q9'Ik! nTuOhN> />0g^_?}`߿zëgYׯ;Cs}u>[I&N+n7Vekgfna4CUP ~q44>ᡓ×oqIMke3mFt 2VF {wC-N:~p-b=L]u5!b_{x[ŐR1h,Ib W~4wG(LN23N$s%mBXwmݵ_*2F2Rg2WK}#ܕ4]kD9ETqF4}6KYC!8_oSP)?۹̡Eu-OQD7 kyZJ/+@ZI<ֲJ_I E o'^D4|NV(z]WJ-}%]3c@|"\ÿ{d]f\96N CShwo?hJkL ܝދap rD疚Pyw)qzNK:5-Bn͈\Έ9 ]g12וN)LKȋʍ?"A&rNjt~ j*gNݙ*WZI~PI'q>bΉ7v@w~Dk,# bF%Tp ~ uߩ-x <^PƳp5<"G0ޝ-82ťG??% && 0R%Thԭ긃<;"q ?Asз4LEƏb~Bÿ3YҺPԀM'~2w#BbA 5z-JCh쵬]ŸEMhVV@B|A쮍AP`˜"sZC xAӭt^ l1WnDX(UQ8ΌCd]/J/%$*0 k lj L+`WaU0 YT Ϧݪz 4"8^`6].mw͈y  0OΪfϙ}!Gr0@KQ!_9~pYĹ{ˑS/"'t/e^5K,rRULH AcjCo$6n&+t(DzyC }Q^kHFz/W6̿EPWvsG[(>e]%@"FX@w܈7Íxǚn@JQ1g8C1Wwr?ckg\;Zs>s8:z޵ic@G*6u—=0F}  Wťx1HeB('Ly}Ѧ،w 8 c[1ލA'LԂGYyɳS| AaGS3uF<Yy4XI)(-%@5Y3f h` -ޫ((K BtjtDs֩ѫb{40Įq АdFo n`Y*C\Û9f9ϗ(_00wͻ[5(kF0[0zKv"tՙa7H -@}B갠If\`5 h@J,=+dZ]@P yp4 ptP\{"рGCP*lB0kVk\,8w3|!0HRm@f@0b~>U1tܑu ux1 cC\FX@ oJKy OQ}*Bl@Z{ * ؃P^S=`%B 1܀|M*19*P~GA(#9 ϭz@ybQݚzܡ!Y?PU<3D&́qnU0(~v2L9 ts 0A#@HJ%MX LpQ p(T2mw㞁gh Q 0tA\wVrXv`J #2 p9%$u`BGh DWuV*'{!/ A/aIhG0)˗WLJt(Xj;HbPj{U+`މ 16ΓՎ9nG' ^"1BD $~}![" Q #|(pB!H! hkt9*Pw5v7> "*875B赡Ymɇ'A'+'• Mpp`$t@ 7PJ)aOo+T\)J $7// /``L#H8}SrB$T;\iPp#Ψ-7_gmo?D:"[=MOkQt@LSܰ*>+d 1\vg*[ʂF04RLIP7l {~x ㎡Cgf%̓!jX!^\,ƮXÒ 6MH @Ȫ8/}Џ[t%b %`!<İI $`@r'ȊH)\4â٬pcfp"/V ".1EgG$ A  AFmMj.2KRD꺵(ƝHGY !zBcqU>IG J=x `v)C^nD2162qZh- ~DBc0  l#_uplH&ey]Й%@W$9u-i>'9vo:l)uIz) sC#aʸhHLSa\'Ћ9B7yFƋz]( zJzFp7cH, V!  " E 8}"swCN`F̺pz]1ڎ@MD : `DZW!5DUb S]pGԽ_k09Lć ׮7Q ZS761]UbŔ7~E/_ t_b):~dOGnuQӳ"5T)"U]x%!^׵{(3]J憢ca0*R y#avʠ' NC"A N*"^];>F;8t11],%,`ꅯ 0^6^ t.Isd-K?` rB (KP_k@/4zA r^ae$UP4bR6V H $5a#A"a·gs')1*PC[րRcJQ6@ɐ8X09EuBcda%0p ۂ1>,aդhbX0|a $swBWa *4qb0 \m$-2DwĈ@Z#?Te9 wA>5N+cKȑAbcЛuhX'ĉ f(+=s>إa';s9Q9*HPyLؐ@@"HS>$0_ D1L;ly t%C@Uݪ F0l@p#l(]: 2` tN`mxa=vzAܺW #@Fg!B0J_#7!s:hR`@. `U#1u (_̍ @x =L9hݰe c 2S##r#W^;  =C )hܰ`@#hCbC|#1o R _ѩ]58/C6'tT&!8‹20)2K#.R" ~vbvk Fa7°k#5r8) MY\K0 9R}s_sNlR0YtML-i`4#Ut0jdAԯr(XNs3 gx8]Vxvga/+&a8K~?+~ )H3tD1U55O TR£mem~_%dJªP5GÈ8WXAQ,\$L8%p)u0ۧѳ I(jcQb-hjcQb;9 A*4zR7KaM>60KI~jW^LM^^*xRP.s{[5Lۗ!L]D0L``WĜW~F뱆c_|qмT0^@ Д>W4*+,33jtf5t"(8[bA+.k5f.2N#?1qaueM|X#&69uj!``p*ÀNGӂ9wMJIM2pE!fI*:X6D5p# ć1%'qLAašЧôvz0#I$ ۄ jV^CRn@[l/f]bCkP45ǃrkB2xkRj?X+4!psLW8G!5 c{Y gcB耣U:`^&ddJXLB/dPY# eʪq6q@/hnDվ(>3ۿݎ K-7ko 䬊NsMټܶj~;K[%[l?5nx.ԶsR\1iopۿU}~j83ѧS$ƓpO IdLas)4]=S)/NLglIӦq4e Ȕ錝yn,t&"rrSCs]lvp7p͙ owͻGo.ɐ5Ӹgմ14$^oO9Zo%q5qr7`CAFkČ*!jF`A&vl!e B2Lb!6"QO>hWr&ƗVA)"{E"VOkA-k7> D&w G&BfGq~{ۗ-u;[M&R7zĶnY&)>ϝ&xE618KE;1W/[Zs'#ssAm2W$7T09ՒEvΒe2Hٕ:mM!dhbUUc Workshop_03_FlipFlop-w-Button.fzPK}xE2\!@Workshop_03_FlipFlop-w-Button.inoPKAfritzing-app-0.9.2b/sketches/core/Fritzing Workshop/Workshop_04_Fade-LED.fzz000066400000000000000000000416331250202676700266410ustar00rootroot00000000000000PKxEˠ FlipFlop.inoMO@9Ѣ޴I5~ƴ-LDNߝ6B630Ψ.dlKEJys1.5<\[XZ[|ɬsY+4% > A2 :NƆE */,A IE={N\cWorkshop_04_Fade-LED.fz}r#G~ ,v4cL}nJNiZ&gO I@CXUz}}p<$#`K 2#soFd837_^2s鋻Ѡs8|6'rrJK1 긿/ލ/&ˋ}~x?y6FWhWKW]%}ë//TnTwѹ on9WRU/4Wo˻IaZ";!]___k}++"KA.jo.o_T-脟_^\W~v9~}r;~ox {7{E#C]s5 ^իhk<~1Hג?z)8^7S _w㻯MIvpw4z~NUob"7si4x3a<ww{j]!`2r?WiM_^U]SJiXkD]9~\ yg1W_Qʮ;"*sF?_ >Vpߠhw;vJ]j|4~ջ^8p9~[c~Cm@+a _MQ FtݍO~UVWwn$!L^tܫg\J؋''Bd]{Mh(r?8%r.)eT+<ܺPyOSt?6n 3=ޛE^qu\g븘*Kg}^ /)bvϷ#_֚% -:Qls8X٦FeƏ[5p72qF#3%}>b*fy4)tE=Bh5`b?#fcg&| ,6G;3 -ؖq+1Q윘A+4?#}&Ic4',y3J3+h=) EО0A*+3-}kҊGN\og,k|t.am1)߸!=E#&cfc3Fgd9%(mz1&kn1*Vs}8kT,xd.ӹ#OM565)lPpEd5ψ]><͖C~I[,6l&M$Fgd#9)8m:1.)kB12)b|9kT,xd.Թ&ZO565)PEe 5ψ]h<.~O7MNyq0&ǧ ݼxWhM^aRӥ]YȗJj}/L.q/}8nty39ׅV_ۏOp23wT73~>n.aG%:npdPB״6H|M %h^37Se {IΗEoYӾU2YPbZl6ѐm N [./Cζ'#uyS#MJsKҧfϭ(D FU.QT(FEJsJ$ QYc ͋0t׀6h'6{6Á @a x>zӑb- 1At׀%6Xx;2H" n3MN)Tn uw< fT8g,wfZp&ҿҰ\PnJo % FXMg%CB5>d,xa3"xGΡ`EƊd7omӡT&Fqp&P0j{kř$]8󴌩0Ghk|`ɬ u20:bg ='w#=\48 йuY߯''Q9֧ǧWD\;GLTWɃ|>pu/~éW8fjY9 űQ(Y=z mlSfŬep2m5a盘0wvƲ"Kk磔XlsaqӟG>iݹnҶ ŏwK:lӲlZ{@YywogaYfp?x3W1ZH_WUۂ6hL,+VXgm=ViȅUɘcB̩E.H0MVׯH Bv6M{dC}tSsOY. ȕ@S!%6CgϿ_!zSaSaiFZw½1[>i*F{A\R)St:4GHܙ#mzO>=L}ax! rSVTk+T?\!B||v6M8;}2/'bW8valnaSVWP\]A`ICsޭ:u3-6y9(Z< ci%3 EOa6F$COv$AN~U߷>м!Qnr6aLjm `+>;(IFk#'iΥ Hqt USd"' JYVg靲)GpN6mϊ¢ YGnԶ=c9'2huUEs Q)_GT/s<N-cu3U/; =3a hhA#x`PfKTPKouQqsZ*y&iAx6l).TyHǃ `D AZ7/3mބ"G+b1F ~֎=oxtCR?'4sH!-PH?)k$䍚p7Qr-OOquEk^s$!8̱ f͈(s XY*Q#QȗaHLrYz-#1ɗ"|eoxow~4nǏ?"'mr~ [큇)Qp5tHQLmSq_VH U;Ķ;Ql~Bq큣3 NS;p dv\tnXqvV:x A\e/lM#0N뜰Za?|݌uY):F%d<ųl O<zeZ Ke% ~Ɇ5#2| ի㛧 m9ClhEy (dkCV@!F&ؘo#H j$Xi440ߑF:&D[+\dA0\аUHT.5SPH]So-I3޸ Fb&`$Z^x#Do7)HF9A !1en6(&H-^~֎dI$E&1P3.F e}EZ#gs=7=a4}2XgK 3m9@>QTQ0T+JxFbXˊՋeY"EbY-,NZdY(Ĕ*윒Uq>ZVoy&\FHʘ4kFVšmM7T,s+SmxO-+V/zcϋK32N.;s67@RrMa)e5-זL[Ҟ`VvY-KWe*ŏD.{&X-`-+V/*2c$IX~,ėj\YѐϔNit+BߟB?izZ;I'?6~9ˊՋng2D=LM)+AIʥc]P,| & gp  ]|Q"ESN?OeE{> P3lX4N"q+/s~eE$RdO7Kޖ 9m5Ŧ3ZEtWF2H*HhS'w*ZV^t H(SM#;dSaS6f)RSĢ%Ƣ+Y n̕\8%%?ԳQ/{܉ğ޷7SZv>ş>VDy֌ae*Ŋ Iʂ-uEDgMU~}Xq18;mDp M٩P$1Kwd#ѬeEDi`M&R.ۤ\r +TXkrx׊6+{$&\)5ʹ `UbyF\(ʝRS[&ǑDV@NM>cZm8s-+V/V>kޕR\uS=-悫]bGƄa&LYQLN C07i%zJjiѴ* dべ&6#XXn$1lİWx6RF&ma*Xj&ʍiL46MNd0S)5ۖ! $0lsV$ѯHlB^* うa0՘/ss 'RVxXW =<6WBYk&TsMz)WT~H ,H4f}B5K@)ذsہWrglqd 0^4B T4 s<^gtwȸ oۧ &"8vsy7M.:ϗ#@~~g0tSZӌ C219'a.`CaoaU L\qHI3[zTP lH"^#E}^xFm!12 nۨ)$B(*$ٻoÛۧj*iNZ937Nn/}2znt?_/OOz>|?|xc+w:Xy(Nrb8g ,~%ïWM[ϔv^Iq0+%}GuOOᮿP+81?Q~poāyÃӆ 쟜9 u_ FK Y3w&~(dFq Q¥jWM˫wS~NJ/Vr>J8<ч!oLc?mske57qр~2m\q}~YQvɠ9^C5 hL(en3Ro&*2i1s͍q2g}|5OיoSo;~ׯ|,_zM7whN{og?鹂=_igӕeY٥;_] :?F_uuo?>:?d?wr Wt~?]uȿu:Y6UZ,`TN .kU nԾ wo hqJkdnn.X=~w+O{R+ +7,\ۚ-;}ӭ_5|9w*Y\yhR&qB%k}['޸)FDx@&`I—R% J(-~Ƨ¶ %zA[@9©#k/4P. wxvIb@ݵ7#h +<9ߞ>gSKY/E|Re?:H;%{?.FN=Ё^|B .z!R / ȵ6KU19#q3>_|MpCܵ7nvkl +.uۑjt}W a3H+ Â&ir\V tb4tW9*iF >R 4Nj4NhuqHAi4cjl+nD3B{pT_`DQP M@y, M:ØYqT@b64>P"=?KA{rÈ TqG֙*m CR`4 q]^ecu84b(!,1 < F Qh*h7`B!{O 1p4X@U`cNH(FK ]Pq!f@+5<`SH1} w*NA #2PB8 XpA`8 cޠ~Ҷ鈐cl84=` Z:>E.SMqê\ D/!pa =RSlg* H0u$ B01 *;B pHgtB 7"b)xp~`Kj7+B7#9'pm bBA?na)`@&1gp1>5# +>"sa2 gI,"!̛E:X6bpK':K4bR\3 V6<L05ݪ,KUrf֢dow"1Gd5AOH+CEEnSWP'݃H?())W Nx!xMɤƝth a,O6: *pC0!V|yah 9wmj@g]Ե`@pTڽ)tp@J6FV%9뙷$gS$U)F-"aSMهq@|`Ģ g9vt$Q*!BRa 17Xq0[!'l& OQ 9)yo{33֞­u=Ph;bs7M5 `i C^L"֔U1G!'LvQ0 \#J0v v  Gǎa4 EL~9&PwvRx>JGCnQ4/* d@01y>:W6"+L^pG5haNvYVSH)閾|B $IVBB8)C?ZׅF=;gLOHD"RT%JBuwᕄ"z];Ct9*8hK1d<+ $8Q =dL?28 "3X{txu sŸ/t|RHzCT!CшIhZ; .ׄCd`U:͝ƨ@ nZK)F1%CrP` @ADA`4[}l pjfZUacn,󑮇i' kq h_aI78tƉÀDp#:8u;;#^8ix$:P#.8h,:~d4.!G݊arAoj_סa'ƫk?* `bKSb8G p«F"A1aC C*#M|I 09C0 4q~a TF[w2ðBeɏhLhv0Fcl :뽲rF_e& 3!HR;(~DP I0$³U 5(~17U/0Eۋ\JuÖ)-`ˠNȍ@\x<7'&[ &"qB A֋ E.je{hĘ1.K 2X|aDBt{ٜPU8/ lZwwP<äLȘB,EH+ ډE`q:6|T 0geoGW:+_G݂aFaZ|@X^z?M [Ar(%*ge_e]*Cs  AҬzox]hʼn@ F2FaVjju|Cgf OQLU1I*DEh#mL`UFy4 5HLRZ8pF09/Q Q=nt$C],(@ Lf0N@@ FDEDbcX@j(+Y(#LtsOi~:4lz*e>Qps$K/5i:N> ll:=Q? :;U~t2?GʍRBY*β PЕ45y Wey)j^@_lfXiƪ8RK)l$ B,Zpc|#EԱB7"f+KU*+8485S Aq2O|' (TM+>T]kj5k>6 ךo"(Z-~.j gB`ƖjryBU *+*V њP˚P`kBPE1RH3d Ԟz:\PF,fhL(77` 1F@OH^p =D#7nH2`oxlGNRš(\#)v@qGhjpQ6"b&,0+Γy];て0kR5[E îTD04Edq.$v7 H͙~eK5:~I1d51 7`ҌTLVU?Qv`9y-:4?\vYaڵ#'o釽c8,eՃJ^e,8 #i8T Dj <%xP)V"J7 n(ַi kw՗* B9z8/&"#S8HB_q.s`Fݳ`r0åK\oFς$EQ"..gǢEYUlz,r,4Ѐ5̒J,7`[,9&^Qs{1S6yy b0l$C NJAd o0m_g߇h0q*v^8`2Ńq\AsB\ :Ư^z|~A>vvSxA5$~CSR\YШxt*ΨЙYl9ͻ[8%bDLJ#KąUt)r#"w 35c9bԩT é" < #8uM x,5)='4TANP&\`r",XT1= kBNEk꡿o$UP0l #,8Yy ImKSj?uUYW ̺BC] !Kbf҄1݂^ax8p(eeD.^}f7][WyuTv)a%3 !Bge0)ǡXe}WNfd87O 0n/>Fu{yѰ5˫A|y,vFo3?oNF`3csۮ.`ڻ.:/ǟpU{׎=Zc9R?'YɁ2 7yMe;<xK7~jw/sR\1hp2xz=o NJpԪR<4k8_O]wNwgF _8;h6f)6Y?&̦ip3"=a`gqcV菴PM>͞$=\6{@}O(N''O COlDLecǏiȶxqDe:a{0L6)ӶyeLGL':Gu`q3?nGFf[-o|#YyXj8eD6cm4yУ+8GM?AO9{2+H@p{dsҊ;Oo-C︎הkJX7W5zhT6lֽ=x}3XO9ԧDˢ{cU"Q+ />V9T|= G?Ow0 ,rup>}j. pP(tB\äB 0UoKi׬iYאD#T8?ӓ3#b6|0Wsu1Cnh9T ?~[teXK@#XFꪚ]UCHk*)VѸq:h1䩶6F}q)ϲiqZyci" #-I`ߎrLs+0+nD VU?B8!9DLC8Åe6TClD|06Ѯ8T/Á'.hcBE"WvDlsWwZV Ko|L߅M &̎}/}+*%v%QLvnt;mF *2MS&|;Mm(cwq4nvd;>^$o7H3FV7['d4!;Incr,EX$Ze+vdWD3*BlĪb y|[WJkJ'ZRboزkԴ^jZLi .g[2bdEr='MV"`SEX^aAFwHܲb0Rjl-wZ[Hxv1;*{QY3hhA -(j#%pםn bL"5!;<-.kqq~^Dlhea[R-y7~z}y~-4QV^GEf.#!a$~r GI]Wٜu! ;!)"mY%__sEċ; fY }C?PKѐxEhV.Workshop_04_Fade-LED.ino 0E|SjA $?(vhu$!)5D&vh\w.YUM%v#cɀl3mIf8H^N#uWfVҾ̋b]Vםh,BJy"Ce8|.Ȳ6PKxEˠ FlipFlop.inoPKxE2\!Workshop_03_FlipFlop-w-Button.inoPKѐxE6{`>\cWorkshop_04_Fade-LED.fzPKѐxEhV.AWorkshop_04_Fade-LED.inoPKqBfritzing-app-0.9.2b/sketches/core/Fritzing Workshop/Workshop_05_Potentiometer.fzz000066400000000000000000000355101250202676700302340ustar00rootroot00000000000000PKxEˠ FlipFlop.inoMO@9Ѣ޴I5~ƴ-LDNߝ6B630Ψ.dlKEJys1.5<\[XZ[|ɬsY+4% > A2 :NƆE */,A IE={Nܜ'MttaI>9|vD.o~׌P7c8ӫ6^3VϷޫӺ%-Vk?'Qx?L]_W.:n x~z5v3­2O߾O B+*U#yPΜ3wn9]gzh2B'j&}o z_ގG߱D,Hדn]|TV(ESŖԽĒ]0ʳat;Ԍq}Hu~b)cLW5؄Q!qgT*5Ը[㛧[+0Lqꁍ[hR+ٯZSKoo^5[-)ȼn^m'BߗSk64xbbQ]SFkU>6w2#%o+i^#ռ?Fa:^i%5T9xżBͿ>^Q/k2u 1{b^&t,wuNGs;Jzh%NF>bvs!DMJnl)v'N6 ;N5}ޢM9ݝW;JO6۠!zܦr&M6MЧmO)"L7T3M C%)}MB/*w[tP)go A~FfpЧmB\))\@6JʧmO4<+xJBS>LlSNw֓6jjfy|Idw(S5q=o|Bp;Z:ZN|U`-t0n M7_d:Wϊ@[7[XXW$dR5vw!#~#9qcyD/֕xT blja׾ciފe*XÍ}օWiqNfrlgf^Ӳdzݹ<k._E, CdWCο_so7Fϻg" 3-9%Bӏl|i:2OFg 2W7I|4; }pڔpQ5ѡ{0μK3.fQMwUPҬr Z[8L\|~?6&ߧ#[˻o27샷M!jmӬ>4jAM=C7ZoL>C%hM>ɇ`|VZ׽e hj֯xpwл wfAzp|x":lUZـ4C|_i;/XRgwݝzf!Z.B)Ffʴ! 7T%d^1m b &F3_皀9-V4>|H|2NCh?ɗB 2Dޙn.cუ5QA&I x&`ߑR<hV6eܘ*eNq̼jmuַ1SiϬ8Xq^v)߭=d4hu5vySp湬EŤ%3ZkJ6&l1]S a?5c^a6럵6xΛL}m mH~f #YpV'lߢUO#&oT&ӏ3[ M_HXϵfjWLš;7m\ &CKK|r{yX<[[̋60l&½Rmp(-=fjN?=ҴȞG쐻9<.P§n{H!.jkIyq1;yq-~vN9۞ڵqvw{P?3=Ș4ef쎦qxZf#2FMO`G<&t[t>&@Ҟva{ƤvMŪEO/mo3UITreza=4CA.uIXR|­͞4IZ&\lޥLdkEC)T'AZ)E-j3j\Yaĺ5!g6\qbO(ZX# '2HɟyE1HQC YK ,5Y㐊lrhY yN)R7>R{-u\j˓>=JstMSvΠB(R&GK!_^AfJn*V-Hh˄0I LR2)u T"kS EzG ܋ٷD~U Eк]JxjRE瘟W./48VC %-TZXSaY ui~IV4Öce ltk#>S. }E'Mؕ7oum9AdX}= OE259áȡǖEa {b MŪEO7Clj{X4sCHxO2sJ,eki̤ǹ0^Ʌkx{n& 8w3||>K?n!5l\>>>Vq-"MAZf^PB8K,X\Avb/Iz2a,,Jgq%ZXOG$%%֩/qPXi gY%a"eXtG0D?BMUL f[Th^ !ɌLUIiQˮSfyKȚnKȖ(Vmdb5I6=˂!-x0C +(?܁D= kqD]'d-^|:֚젟IC)8ܫ9jYKm|mUٖ> dk%ZEHj;ta##"%ZGN ȵpZ@#]@@ew5{hR[N{jkO^˹+f oDP-hÿ26ԡkڳ3ѮXh?+6)>k"rؓ)Ap9e)pkf۠ސrioȖE5ht;Ap-;ٷ eT9A"FBq%k!˶꾢YČHh kSj"E˲-T%!YV; ѥ;٪f?8ObV q@f%lM6tU34PӪM=%>Քɕ Sp)ZFXh㧤U{Zl9S+ɦBl+'r#IH-ڜաeJgVUfeզ|qaڄUs%X2KejSjv "EK >bCR, itkBK&_VMNY+mف4ULpX6kC-#eQEȢHiSjG C˜v-sr>UkRHF<ϙqbmf1#f w\_-qG&a)fک=i^9ަ"-9j,G0cOkF˲6}$TLk/puUS:vWRfw"KM f1qfvZufp[mjq&`eifD DƏ2ܔ{@r>AM>aZ6ZҵXd&^mf'.f +w*Ɯqh&HGnq (}Բg[3o]`#|~بj`µ6qUM ZG Mђ*j bg+^lϸŅ;8P *Zծ7%΅\-Ě}KMr꜐WM?RE4XN)* H濧qP#91[l,ljቧdib1Cl Cy5ک{2Ӈd`X$Lؐ򮦄CHiyj[v#`%GܵQ@Wz_ގGߔͬt4ctsoo{'7']??һ=Www$:Vv;x޹_??r]YO|tK|-WbVP6j6Rծuuo&_kdb<Ϙgl h ߼7o~i38:_q-JQYj8]P:t;,_gwO&o}1('||1\tPy,Rh7C}9_N:\ƫŽgy~?_턆]vFl4m6+d΅cEߛ]?X+]K 27pa8ɉװ+oqzt~>//t^hgsaUhcHϬ_קN[aOuv4.j]cr=Bd; V{;)} TL,sIi'Cs 7SYgx3{[go ?םD?7߿|z{~o;fz_gVij4|^(o U|~beIvx3??©7.Uti2ɷxt|Ah|atdj.P)_B5!~ Ǻ{C$CC Ώ*5ZcZ#+;^SâU+yXxӣ-Ti{I(2ENxcE H2 w7*p^{\7M,3avrֵj\;^q>ѵ$-4cQG*2&D3!9{h0 }2@ %oeqLq,܀"{LR$t%78¹&NP4 ݠ͸[Yҟ@#gqQ{nr;\4blAǣG+.=ҭ1b K@"7f)05@WL^<jKj|9 U9 A*NMNp?/F5A G]ph!')bmR3`U&ׇ):7$,9 r > >_BxM&pSq0nU,VFY=e3ypj3oO9}. '."3O ^5- fjH9! kP i0Nx )%s,8sKMtŏ8Ñkϴ|=Ј&<d&tGIqeTPb6, 0gSg6HN$3sSB֙ 6@ؐű3γ;QGMP*`@|"TGD(X{XEw&oOXI;/I)<8?@cNs[jyCb1PnE=D X$zHĉ5ѠaN)sH,RaY(9"P jR 4j#05E% 3P2̶?qۓ Y]<'wGqi E8i U"4< AKv啐ב*!v4J UJ)A@dH1yKnL@AXF5LU=:#;aQNe`@ A"1z@JHXD!U[V3^;ANu`v{Oz~-0^@$ FqYE ODiiY12EQ,I }a AސCC0ȇ"׈Aжp9 ]Ƴh B @*ɧ'34|ʩxd v|A-fT4.p# RjM#> #%AmCޮ4P\JKdC+( B0!A*#P ! INn,)8 gh <fA۞hOf,"¸bD1^4\edSw@7UPqRIՂ 2LRF."Or\: rQn.8% EQf-2DD't>rЙ#9Ԡ /q`fH 31U=q?_c^:gG77DAau48&6MR$zQd]F> :T;5at_0GʏL0'^aV? ,bb0Oqk4/œb KW3d0ceWҌUXIE) ARߒTE$ b,Zr`D[~=`ުK,;*)WS(+:<: R ig±!rFzUF.4V}͊MõcĚyK弡P^i-flIi/j'(TFP5[#TY,,>rDcRX3n2 "ϼLDe(`Hl/^ZWrr~#S1zFr#)#7W7&I"p.C %ra *7"rj'͍st8b32V"UфI8rA~DW 3)_ f4Dqer,SbX*Y|uC}[Q;2Y}P !|Y]GӿC=b2Uu,VŠl<\2ue,űS[%ӭY_tm =t&ov{UES6eqLb(1lF'%]Ʒ1M]CLL # fVxd&L1(z'W_; 7ձByyy>eDX .V~/Y4}+{&43HaWifv1^w9;K<<*x"^!Q">#77`d.qa;J!/;Ms4o$qAe;m"lnŸŶ<~v!Œܝgޱ}+ Jc3 V?Aµ38,rluLFRTtOg釭 MxXNM.3v`4Yf>, =PBn艚 ZlB #Ex*U߃-$%i bCY/Lir;g׫"`:Ҷmuu^~_ogo#8vS1>;#6Ä//oB#! st#–(Rm"V܎nf%fզYvSŬ)N%̖̥6B6ڻk!L˷3F0yzNR"<>Xa@Njp2a04?x>~3=\x_dIG[/m_ /o$P2>N- Mw!1Ql0] ix^pHun>\NvajM A2 :NƆE */,A IE={N'WOL6{}Һ/&Ot*ՉTv4^[}Δ>88e.sSN*w7O/˖O׽󓓿u9\ތ;{_c7'I RNu퍟UцϭkߚQy:;q991 }|A'Q^O޿9iF}x9 =/o~׏PCqG=z{ZV銙ͭS?hɓ᠗?L]_W~mt j7~wVn}wn}!@޼(?!\рgjD]1.|ws=Μ9gs8cg2NBǛGj&}oOC:]?C?DDHOoo;/7dNw8u^.ޕ^|L$j%}[:j،2~J~ S:p^&O5c\|S'/2tU;MXP"*4NRJpk|45MSr7n 3#ޙENЏf:.jNnnHCyu=-h|VqE#'h|>ZE]|`3*E3GmoTQf8z_S ?+i>/ictM%=\I‡Tb*k ԜҞUjeXMZJl}QCY)3UgGy0󨋤99q1yUj(uv<кq옼ij `t|<+;-`5BןCǞݻJEٹagj|/'oF|ias^ߞ&ewoCT55$#N 6UW#}><]UY3yzayUn|51M5\;9d>kǚ\Wek$cN+JǣumFy^O'/,|r1:esFv=}~MNV>ڬr|yfkǜ[N*\+>r|ZIyU~|YI̵4O5\CI-BkǚoWek%c9Lǣ$my^y~Û?7lugߏqt4c{{*GM+_"j\c'܅mE̟kK(>rQߔK5wOgYC㐉_w8[/+D*߉W>loXIkx{O>g^Դ 9}VO*Խe,Kdu2/}fIqr:SdIU ?_hu0t8_̃tAy*"ٱ{犩R@d e &ՋQB")a-SaM6.A#v8q3@K_jg8!eÀ6vn^ RL7y7Ɗ݆Gj"CuKi"qS"Ky8(I3ƴY{ϊg@+fI#]H4Қ; |C7$NKWmt[!]hWWfSmQɸ~VI/^ N>!J44ȱKzSmPȃHshbբDH,b<t"[(iǃM.{7Qɧxf5It?Cy4_f"rV_# BXKɪD'iwmh'yArYw;L1&MJ<^²ujeib*?]*C꛶5{mhUZ[7 /m b_C]TnM|h3E7|xo6"\oR&:[) e{|;^]⩮rVk'^.טD\M{;;IfsBS aL~!l}ib [Yg/ag,c<2M54; *;6Ac0wU2_NTMo:ikGĒ'AoWēͅgBS 17Ef7ln.cᥜ%q7{[2%w67{[o>>M5o.ͼ2 s8";'( ˛~JlD?Lbe\>t_ؙ/0)P{OX'[훍&yhrS/b!G@WE8B}Fps:h0opNzB>8R^\tS*'_}`?RVoҷYd2uK5G-:Bp֫^jSrQ=Qƍؽ .2Ƃ68Ň jZOy\#x܎19gUj#EzSrTqc\yr凹JjmnwH3ϴCZ֟)+a]PxFCY۲=5ѡ}ER]ZT_/n{ș<ֽZO$R+>X@avH ]]UZHќe gK*#]q˳"HcXLG,eC*C3P =o|[ CުaKD-㡦 yq4CáLE:56{

L}G -/-NU GI@)hb-n\+?{3y]0\W| /lL[*Rmqӫ= kH3D6h*զ3WZ&ljD8U}ry;Ttt>6j]Hì6{2; ZUZPPEsjwE&R.%ISJxD.<-E+]=Ujxך ?PmQ&{5ʹ&H3#V R (*z+Á\> AvM>bgm4kUjчa@GMWULFxKe#ኯ(dMs10S焴͖@j)!2RUu]n0l o;i8n u8E;JEh6kqч!FüvMʫ[3}n6뤖l̢𮺄CH$A~`}!*vV [T5n70u9? H}\ROK6 >0!d*0֊Lf<­\(OI.kK2Zf4q_̟Z[VbθKNSR(.V[[ha"-bj6.q/k Zږ 5Zo;hh UF1ls-}nUMaVKrL;eYy$J3LF2_{ 芴UA2w~'7mfһϿvn@ w#naļݎ'Z7׽'Tn|Һ;pDˋo*݌G_rp啅I8I؜KEp %н^},!Ǝ; n1d|b~x/^`>*n*5Zh2\92{Uy5);FY-u`m.[7'Lnt>|~pt~P;~oPy,vRh׿v1Zkq~jk~g lcqǸ; R0P ?ǒSoj?Ż~~X+8ş8?=7kCot׋?''^îWAsIzAόy7_'dJDe ]M˫sY|a/֩t<=UB&@Kg?Ly,\ 2a⭯ EhlVh 7 BL$0?hrBwi~KΏWr4WGz# |lׄBp~֚PQZr=h6dx.ili .̿b~ҿ:sY: Tj@Y_J l(8F0jk\]V\gb̍qFϪB<)*_!akԥ?!X4Xh{A˫8AEtRwy2e~|_tT'B'%:5[\̏21JCET`YQ`WQ`^*p< R{4bQ5=zU?A>0T.cj;Xl].m̈yB A0@ݡ''eB]mhz S2FȢC) 6L?IiSzcrI@J  ѶQ}iEiõSAFA@ShH}De1iB 5*6a]Ao\g⌀0aG2$9xyl < #a뒜ۢ$Hg`G¦E=! 3( jLjFp/ # &+&(ax 59hsfʐBN b L~7n% 2 qvNm6G?;!rӴ(P0H AKx0E9'U#D )6;Ostu;2";A(*hc'"ᡦvSt "h?DqpC΃l zd8 Ty0;}r !ɉ9 ?̇LN}S$kGZPȍ#/b(29Ο!ꥯMnDɉ*WeUmxjGwa;IsLxԩH?#FHtg wJ_9:пkH/, 9D;$ JTLEEy~ @\ ncQ"݈R㳥ɘ j5ܹ$9`*A(D#A!#/P Fe[0dZTfy@cn*q %q-%֝0J+LQ'ƀ&j;"<:$uD 1@k#SU8h` |ص N+%#sd4Ky ?`q\HU2CI;d""Xƥ9lJLA1 <*oB,<6,R?Rm<\YF!Hh"Jc0wd <ӱJŀpѶ "~)?dS tDc2`0S0-ϾL(W2R< HS Jo1%R JvqJDgGBȂ5(rȍ̀4OHD2(|\ `a8ܕ$Wo=:swai+P2hy,7 z_0E(PAj'+orѩppISc~RUB;f;S9XR1cCxDRZ1.q&Xۥ ׋M+(-DҎ6,d2evJJs>o3V4UUj48 -  @rPW V\x6,4-q~<Nm,ȗZ4AIE_I" C.r 55Zn. D;ʌ"%@Fp1 h{I%;%L iq&F'@>3@#fp,kZh[:-̾ƚFĦIXD1l 6TRبG+*Hj=3mfk,D s"V;+J@+*- 'FKJR<)@4<@|u?C& 3V,XňT4/e;*퓨*'ߣjɅG|"DoIn:!yR,m2b^t\M8ЮV6M׊ǖ·k-m? 5JCeoubHjuH{V:i%BեP(*xEuEBB%G:8F.E83Q[& R(R{D o2֍d6¸ @[1bГ4R3',I 1Lms( lTNS;vna\&R.2@VΓ{][jR5XnDSaFd+p*"% "x!ݎ9Vu4ԅ N]TM1Y&R=[dyJ&kJ !*dIԯr8YN 3+k,-a1l&\{rV~c"=Pu])\X 53Diаŕ Dkʵ OT^dvcس(6W}M>Vwu?L,Dg,R8 Q1!1We A=& KB7K^CG˿C=b2Uu.VŠxm2ue.鹨蛳 Hj70K]+U߸iW'f{ ,_ۋ lPbHNJNl퍽5-]CL,H3+R< 2,̉yppkX=y|^aҼΝ' T0@M|`Jr+=̧⌶/E5) .(SRڪlEżLW"a ,LDR,/i( ()Lf++r1хb,ȩW;au# yx25.<'5ɕ`E1f$^,X!̢WjrI)(2m+5 >Nzr 6]`R⚒tliX)Ϻ+BkP<5IwB5e)mX[9- ] ɍn!]8p ,ø,H7Y #" SQ&㰉eZC`e u]6O5[hz?&λ|bwN'&WwWs^\,-yr.o3S zY#eZlszy]֝OP>}mmysֆL=£7jȔt<~t`q[hC׸|ʈ-NWoOOz^5WMi_ޥr.&ӛptݺ7tk.Yp!Ñ6§ 9bGlN!;vK78-:S0`D\cUD.F0-58Eq茟MAesg+p5EejD8KXLS2}͝o4fEǙ FUw*N`=))]uN哺y5Na]zق*j:TgmZʉLZxtp+j]_97r/ <'UOP<+Vg-y ry&Y,OZ",ūy磖7$17WpeĪh{mpi"Vd4Q.%:N&' MxM.;e>}JuVuXj#5Sż~[1 rsh )\R" 'T}gH#^즆q@r^ mOD\ث\[d" ;fnQzr2\3gފI^ScI8ay /MmUmy)I4#BwڲyuӰH',!ІMA K%c09vMMJ K6oLk-G7hH䚿#7q\N%[[:_D5gަ Qha"u`8c]^ZJ7mcK~ oϥ G@S"5](£BM6`*㍱FP,,_gѽ{U7c B]Oo}o qxݛwWɰ IƮi7z_ALl.uInMRvRN}kf{|q>6p.L YK L |i78it< J|!#ʱ'_;$9ew.H;P <툒Z!X.~ɗ+%RƗuk>@{PXS`av u7/%m 72>\Xa]ϾгxPKBxEld#Workshop_06_Automatic-Lightning.ino_K0)cڊ¨ ʆn9kz.)I!nV O瞓 iL3vNJH^YOgC?פ-pUy: w|v"I*p7%#Z|\zCT(kΖr#; !TZQ!'lP8 ^!п\39s)Wћ`z{3ӗ]dHJqTUdAOwPK xEˠ FlipFlop.inoPKBxE臭26W"Workshop_06_Automatic-Lightning.fzPKBxEld#8Workshop_06_Automatic-Lightning.inoPKp9fritzing-app-0.9.2b/sketches/core/Fritzing Workshop/Workshop_07_Servo.fzz000066400000000000000000000357631250202676700265100ustar00rootroot00000000000000PKRxEˠ FlipFlop.inoMO@9Ѣ޴I5~ƴ-LDNߝ6B630Ψ.dlKEJys1.5<\[XZ[|ɬsY+4% > A2 :NƆE */,A IE={NhrV~}0ھ_ZE盝` *x_6u67*/3(oF)cxzHӕ4_1OWҋ!B[.@W+EVTو9URpOF9Y:DqNqGm|Ló<#}fJ"ia֜JmU)?~(sϟ7Ԫ,%R?ltE3Rg)CCDOX.?q:Q`!뚿\әZ'|&fybzs{Yql|S*$3OQ7t>5sJQ?}>hcD΢u Ed|ʰnD0\gOM' Xίf댉:QytJJu4 'I;y!żizAʢ;̎{痺9Ϗȥ]ApaD}s$%3%Q?>ys)QG>c\ZΖuD|nD\LO'ZXدrz yZ gPL$,Q Ay&ai.3hNH%w&ݤןvٴ;WoKvC\f3BdiӘSBŽHZ8i烀kʥ;;̧: /{3 KVN% 0t ݣ- h﻽w -X9B{/}e؄%KQrw9I][AZʵkڋN!%irV=ɟ{ 9MAaNFmD˺FzHH &ب2XtĎyyp]c^nl!e 61-Pr3&9vmBʔ6.z:Pl%e!6P1-,>yI#1i%)Ky3I=cT!YqO(pS4׃Gg֤I{KDtV+ok8Ƣ+lm? 2'uϫփCFL ǘC%YW8$)7 8BŁx88V4Tr]rѢ>'I$O1J껻R_jĉK(;zЊhz2}n}x4돀c~s&<7A/d Nf{kԽ\wh?-vDPZʺ Š"\xyz%m$6Xxyrؿǃ7)ݦU*,9m_NjƷ| ¯VWWF9bc~Nw./Um7\c\S+ǍZ~b+T C*&zi[jq@,y2?DN8JT9o2ٚ^6^'w; X.Т︤ +b/HP?D ,nU|Z:ido0.]w~|KWBbiVD:2ԓEbӟNZW=?~CիpZ7<c@%jsƗ~惙va]n5>;ϕ ݞ;+B1 33HPibSδPDG Tgw "_|uMjB" .*9APnC.A|ke0y5zwwٟ'oW;/K}f_gTke| ؃=qFa6a7CUeɎ |/޲ e5kV/xpzG 49xԹXju3p:5 0K;C6mߥ={~~Ρ}yKxDNJ}H֯J{Ő> zZL? } ]A2bA&ctRs.IԟP|9s|E|6'yyWR|.`6!Ld.4|=4oSV$:8p/`"G2, eBc 50 wRc]+vjLF+9LTϖIa/K#OWN[9ĕ^SCK^S\t*TFn%Oy*Sf9mSRfT>ܤsp5q͠L8AY v)^d}=@TEW?,qՎ||S6Sk/|_7O0)P{OPRBZ4?J[ԴR @ cRкbgJhoTVHX?N<$VYNrNҦZ[tڭΞrT;.9*yYyh1QNJgZіGoN/0ti:zPVZEnExș<֣8ڄO$R+>Y@: a+V.#P4{~`qxjٓJVU0ZpE*2j'""| rJ %K}\L_6-{e!S/UO0SA.yXq4C-áLE:5 6yB8 O#fW51Hь=?Z|KiE=IfGKQReqRtCjcR54k-afEOGh> -N~|U@I@)h|=\Ke+S=y.+>z' 6j-g5Rnyӫ#֐^1-fl=AC5ljCњzlXÂ5aSD3=p]rڏ{xuPӾJsΘCzKQ2#[{U| ߤ`x N\#,eঢ়ᓆg^jê6Efq6[?a ZW\tGhAٵ$})Ǥ\.Rf,]<1&|v9Tjx׆Ǎ!x$&\<>"FXHUQ2Ub [vsm*|ƼђG6εXnPq.PnYfwƣɷw-ףĊ)ΥFļ4O6+AJ6SCܴ> G/ލg?t޿xrЩ(F[-<kCH)q_?d[Yx;W[,n9s+45oޤ_*%CGƒc?Yq:'sKyeO0>Kt ҟN 콕'a܏'֏w7wV'Ы}ނj%\EGLfRSiN/P& 8 N+nM?W$XO@rO.n&wӭjF  3?Ǩ,ɖR3x*Xs+{ʥ60Fx(,Uñ (8ñX!pX8-y(bC8z,\v:&e@C_omh0Xv64lx&$ ){ؒTBYmұ/p_ku~k^p0qRDo5L`mx /]xE(wr2svWhGyz "*+WCb=fm P|*/5Gexs"/+m0._R(92rb?`R.9h[(4¢ة U#0|;TQ2=Bc2B|n zd:#Њ=a,@GFX@41X04 .x ~T~ 'mW:鹸_ى b] >gףOjŦcx(<"G1$^-w7*,p^x jS7s*qlqWvŸ%>b/I^暲-1h[Wv!r AcU X*@ dXVGa\T*HX(EDW SCmK Vqc|=Z *q7yAv";(G4":U W`K  2W`VS t+%_3V ++Еh~5v]\L|:'P(ц9K.lL!!vH002>L1O'T@h > 1_&踱 pܻ彨[%풕U#/yCPTsCΙ Bב[EaQ<@cǐ۲7C AUPF! ,G=*AӖy]2Iz *Ew,8st,Iahϴ!"xQ1,C&rrf&cP ل0#_ LC N q , et2&wSh zgnHg!(XH@k`6?vu$4$!*0 > TU؄(ޕ='{{JaC"b̒s\(*?1X'RFs[j0@yb1zܒY 8*!H8!&:`樝B?pz5\ sh 5SfHЕiA.*ɡ!.1CJB! !b{R!K΀  #?Z_ WB4y.m!Ac Bh!@WU佊b t$Ș@+1Ħ!xD :y UH Z',Uұ cd }~"1{JH4,]֪U-h Dw #dos ~AY7Ja^Va #02FZZT ^!!b'I?P_"kg 7I0Ј[PtRwӳI jL>9 ?8GF d71b& I`!@Et 7%RJ( Lj$0m0ڕsF3eC+(K1Fa'9 ?w G:Y,B@4b$p4XpcQМI[3qoH^iq"ϘZC,=0w) NWÕhx<MQ"zj &MdRn e!аS^\cchH9COh+hD P86%s+.䴥d@g0i ox!.C:̄m,U rVe zLS&8@eE<& S@@yݐQArr]"RLi dd1 $6 `F@8&>S _!Pcs~\-̬z !ñ1Ύt4-rp=H# "1#A0f9'!hˣ-B #C13v'0ES`'(XCM,B%RQ? ԝA :y8NM$L{DcK %|x0%ic 0?T:HƂB8t)K9]*f z76RrJQ+iUmoyj`4hN,e|H?CFI"11@Q)Oq ꅥ(EA&(u";D PB3dNMF$@^-cfEPF:-ARRVHvZC˝Jb)ۀ%&cA(Fl$2*a-㣩a4Тf 4~g9POt=N;`:0EgcMGQ: I4Q)33Cb{9ԑDk#)Ǫ~|"ZC_Y=[ȹ12VJKJzs 0p₺⫢JQ~)")e4 *\@If<̍(EPyK(ĢӀ U.r[" pED"@Cӏt7LY!&me(GiC@ec 2a4!; %k o;^{eZpJF"$C;,~KܘL"*KE hѫ`GRfADQ~il'_aN<͹ F-3[a0"7O-M( KMYD$F5 EE!#BJ\yl1.K1XzaBLt {9 8q_lїnxA2q)"8H"ِ*]N]cK)@ QrU"hW6_Ʒ4A9T3&ǔIףzz"C=!f/@PHFoDJ1RL-o ^A!I%vVDPK$@Trqtq;ʘߦ4_$ _7&AF&֠i8("" ^_eE #\2=N-:v-! ;RC3H:  5@(ŸHQI-Ap%ԛU0,IIȕBy02Ѭ2LT`j+krR)TeMw+1~$%?F1?)1kXǒ#G$%D JEծ@"iGDrܘL乒q;_v\QV2{V$hV3VŜҤqMܒޑ "9TW;$K#@jL#Nt^c46MȦZ4 i,\r=*P80331ӕ=!!ЧЈ$q3-:ݾ{ȦQ4(6G1 K RZ vmuߊ0G ԋ椄%hV? , %]ɻAhI^'Əp_=Α܍]p& 7VrbY'% KA).lATb,a‘$e({r#S?0oTjMWK+<d-0? a`ڙplPjȹRScY\K[J}Xc#ki;5ԔK U8z[Fbð լ.jD!TKBKB%, UBu>rD' X pf 2SLUB{H}hވ0D1(-dL1Lj) MI8"FAfmC/54%PGlTM}# ")vRۙsGljH7!˕H'YШOuلq֤ֈ~bcp#2" 1#["sYPp b˿}w+uY!,,&T#`(+E1ڍGa7d߷Y- k8' ]Ӽ|?|a=bdl"}6P.ڢ+٢.b;E"4"IEnLl+eim N:ׇҰ Mٔ17)n75}Bä{%% 2MmcQ|9+secVfȩhYI|6}Bh~!(tk+|ak&h؉v7_q7eI( &E2j@4e9_u5ˣ"8jsc^#=;&$QJ8{>Mܜ[(*dQE^g| p㱰ddᶘҥ< 0- 4 /YL/{ b8v@Syo^j aKgOu0I..A?as A TA K%`0X{&q%BƁ88r4DrߙCID㙨O` u=>FWͅfaZ/m Tm.Ѓ4&M1plŚ?%[7 X iÆ9=0cLZ{lJbPFdi<];iw %; 9r؏(!xK4.w?)~'Pp0{tZXu .GCm^ oևW/2cAzD?[!*GCa+;h~GIj{/8c7>a@SY8F.GW"n~uEGZO=O#)"g_~7bÆ8;?^x6÷pOXI8٪gpcU/Eőu Vk׋B+ Kw5)w`:Jϖn>|*FRASKi"&bb)Y^Rlugnê~՝7#6WOODHZL+ oiRgib3,՗^:owNYLߟxsqR(S:#GpPbW:UpHA:rAA/~0W2<>n6]G+ْ*dHUI3+-MƚT9o mdSeE l&)GϞҸp&nft-]2]5]4)^9,<2>]co hb W imœ9%Ϟiw.e|k'>U)㪵v]ͲkxeW )7Y+|Mw\X.ReBv??nk1+p&St;jsB H&{F[^B$)nyA9baaII~h\sW(z36趱Vc^0B.9ARxPKRxEˠ FlipFlop.inoPKkxEf9a8~Workshop_07_Servo.fzPKkxE6 ?:Workshop_07_Servo.inoPK;fritzing-app-0.9.2b/sketches/core/Knock.fzz000066400000000000000000000311711250202676700206510ustar00rootroot00000000000000PKp5DB62Knock.fz}ksƖ&SEFÎTbĹdR93EQ!)o^)>Ň@>uh^{|{=gQo7zƽmlc.bncY}{>l.QhtUwLH;xtWg5POn:瑻7F#q֘&}W;\iN7gŤjc[=jeߍvw5}v/uu5.^ѫ.YGse{Ơ}~=14Zg==;=uW^,N=_,OM=};&NGN'/T^sj{k7o._&/mWUì"^IUjo٥E^Zi{n\\s3{ָi{Y;irz oZ,|'&C7[ŕ7p޶J=/?ߜ Em ͘@iSJ?ejGg'\el2pJegNzf̫IkNZmS"3*sj]ڧh^}Υ)sMa[} 0j-YјJ]HpuuTiBfo=s߀Q¶6gIgN(;RI8dteG[yfk[xY7wZ q q'ᙉ{|-y=ļ>bqϋJhM!c5E]9hdX./km8;f^39jW =%%Ohd#>i3K,)+qPa׃J< a$z& ՘I| J}JF!ԧLa\8c.$!<cC=涜Pm$Jܧā] L+]뙤! qטK|}JE'(9%#P s(~]\BlKJ*)%-oZo,/Zl<uq=]?hkhЪoϲnי9GN gZ>fO=v4uDS`5hj*\D45 .ƓjxE7>t?Y?gVnY*,FNzTPQ`S8Y/gS<Ӷ/J͹Pt6-R6>}71h1u;b|1Ӡ"lBƗuskNI8I6Y#k.I^7PBQstE?Yl}ZʥDp8P> B'j PM^L[$[>Fa-߶V.<Ҫ{խN <@-m {ӈ{2ʓ+v[5t/MV5*5tV$aF'4NJQ D< l6^pB %8W$gO t]>]*}転Ow+ >6OrK)c SYHcm35K˅ \~A8j) kLIjHO +iº8}f9>gZ̦*faM#9Dԩ2f1TǯOD~(fҬQt} c8djɺfh`0\AcL2 : RSg3K>S8I)rzVСwF&}q>R#_i" 'ʁ+T- `}忾׿ϯ?4Ư|׍Sn)l~q֝Ln^Z񽌇￵~uԝ\k'^g_L.ξUϏÇuy0LhO>Ӎ+답:qfk}7ɢEfEEܪ6|xA_5.];˶O/y3.h߼ĕqs"̋ptMQu{tD ve|8 NԉHgNWs 6pg_6Ư4S7n4:tm;u\q;.aٮ 7ҙlō^ԛF;iLnG_B} .3+/2gOӃI6j fz~f8Pх}eݿs^5n.|;~Y{LSݑǁ`im;tZ٠kdUT}P_]^k< FSD8)mF,aǓ5>L> ?Y/ՐVs@rfd5r4Hj++:%E)^ҋqh¹=t-#\Vz@G8`M '6|PLO!~q2iT $qek.փ桐8kHzszL`<мp$Y'A6 vhǣp18d;!Jj{X,xaw:7Q$XOb=Bc" ̯)L7[govr>SC4fR>n<6JOo&koRCL<&Io@F%~bM;8!Mc\X 9L*$s>QO-?:NlY V: z7cuA=118ē>FC&%ULS!ቇ~Ns1I4)r~@$ DNLlImj #X1 iix5Wv4DŦn?>VS8&iCVT+s3IE\"-t)w)ىFuRWPm@̞0%X7:-);M|yzPmEO24`PijEfUٽbf;?~R!.8-Xcd,<Ŵ&b\) *8J' vs=ŠNdoG>Xα~1`GϤ>%E|1PFMax:vu':f~變SàOк\+n]uoh{5ūc &{GjIHjk ث.Y&V;٥EgX_,K V|8 _MF|&p 14M] f>,s dq^H}Z4kMoh߲dz/B^y,L&"fN/BCq c;)b]sR.9,|i#a|߽;E7c6G!G,ᩘMg6l#T>7Fn&w(|bE+rk{darv,!U䂜`d4ENZѸmM6k2i}7\ä}f~2^\ՠ#ar?@2݌'uʍw|3.83a * HS*i6Xi|eZW mPNd/xvBV/dhVz&IuNiu|~4xLi?ģwk#Qc8~d 0N_[Vt{\S8&iFVtiKԂb%32 0:tqı4`QZjT'X&X ZFњ_t𿦸qB^fk&Zz0Ĵ*)ZRښ ``L6:N}e2ZLO|Ac(K_(2ɲh(”Mf3xJU]dĻ=ajs@U#8eqb_ˊK_(n}u.1ΥT420 (3f4' 6S>Vm3#c54|}'e\%b=~[LqQE]US8bI.γʼnY-+ZBőKpOz(|ovf-zNc_Y$uK0IaNXG#bϊ`.qh9JZV(v@6q r1E|}D˲8\Lv|39+PhSzzڵ -Q/k:} l!(,XxZzGj (# <κ-e4rgˊn?VS8&iW:Y~F?dWßW4wK󷬱}b-*S%~zWIq%KNSkfgfw7Yqxoeqo8x 7l^W\Fj8{o7߿u㛨Sn?6x[~Mw2yj2Z?7^gr[y|1f(j Q۩NjwS;Щ7&UǛh{4ht=^Edo{F#*/$1ˇ/fz:2f 7Ù\:d}\gyhx;K9o̩=2qB ^We^qgeقKEQzb:qBѿy]?+3#"q]; "$oN,V*uǩ; SH(Cut;&#G#mS}"Aw(iҷaݱ)ja/rBB%I% Ubn.ewLq܍N)Ʒ% XH١rjj+5i:ߗ$8j_E0EͲUTD%餿9%Tѫr T[Ap2ҳv'/>NL ?{pݡqWǩ2¸W&qS;˻ɚ"֒T8{Ma]X:@Sktoi?0&ԙ :bT&tps꺻ޙKT8]c8Ӿ::Un 7z/\:y: [$ʕp_S"S"wdNo3uN)\W:Dͩ8翍"WAiE)+g긫A?aߜlkJ㡥 5},î]\(B#xNHqYPdb,?T6tHa~rmB:dmjs.ٳrHSz F}1뛥S`O 4y3]w(D5jEW#x@(h8 $/ z-*'ApYUTGEEwڢ[APN?,s) :e׫e't>Rwyeˬ-]vztTݯ!ŜDef}7Q ,ˊۊRLdz*lJPuţjz6o?K|ࠩ#]i;Xm]ٲ.mw݈yB A 0@ם=AwQ,.rro SRFȢ})k7~I 7uș_z!0K~QN*Eї&X?K?("q=r -F[YZ`仼D─0* @ MrR?8hN:驸^ B]=΅(¹n.Hj:"%]7^$rw)#QndOׇOj !m*fJ\\5㌅]:'.]쓸1vDCloK:U&B":C$論^(1,Aq+#(`ʋˤ$c"+)΅6qODu@f l݊0.!I)Z R&REqɝKڷ9D!$ŠD4hP[;$WPxr+0 \ t+_3ʗVJ+ VAMN2IAM,.F5o} < .4Sd}6 *Sӛ9DB\|9nj;=ᝠ[K+`ik&wۑj~q׫Sf5HX 2Ձ[EaA4 c5Mތt#BHF> , _ʐ ^&$䎅gf]q`@" {X 6/h#N0RT.55 JPƇPƒ( %8Yzݳ Ɍ2&;T#w:C@!Au E!7$؝#F@B(1 <}B6Q" ^A]y {ş +)pK%4)Ř'縂GQz Its^7$hVԣ %Y8bȔHD[&&8o椝Bq8 !&%/‘QMIX9 *D@.p#!RjMlIPvP+ rF2g2d>EL Fr (|$3rBF*MB NxD mcCMiqvD1j1NTj'*]ID/!pa"=lk4B$N#7`Hȳ BqEyPH .#`6 i7G4O"R䱌^\ )ra$F9Q5 q$@'dQS-1CM`@X  @OWP?x>f]"6/wGFygC7."_Ojxؐ."/tpgI pb@vC)FCKKj#&IͲ`ԥ&$9#5+YB:3 IOXH+qԕ1{'%Ej",u?ugQؤA&HF$8wZazvB8N&RI@ÈDHIe`AG"5JTd.~-EJꗐns cdԭHK$y `r8^];U EEdn_ H c映bӾ (a*XPy ذ@Ha2 ̗2@(tܑ7L,.$N;ieCH0.ʄˠ$i*C; -]WE:+݄a!#峀aAd@pcDP à]0U#Y/Fx,~9|/<\@%2ZFu&x 7p"'@ԘID87@B0֋Z hȗZ0X0)]5/ĞhN*L8ҋ-"/0(FL)I"·DH ]'vbt"XLǖR qpZW|<]%QaoQbrhL)[4׃xK,]=>f/ ST,Bf)㸓w0&4A9@SDyTzoPҏ4cb6gDiF%}Ȑ{)@wUPyRI<ɢ)! )n-i'F(C~3d,i42_pƣAFj ZBH;0E X.LI4EY @ 3tA  sȈ"" H-#\r؃3{秶bJW-A<L4T vB&/U>U5i~{{c&1c?1UhXǢ Q0R`,t]$IqBg9=Uoa&nIw H0LnA]͢.xq   0ӈ#@ 9D#8 mcG>Ղ 2LRX$"O\;urQf.0%E(!0[d$)2:^O7/rЩ#9A^̐gB{~>4bzu>!f%଩'xqLlI`Q!*b:#viuw#4!͉WO (x>(S06FJR<)@4,|#+Ln*JQ2w/*QO2`a|Id%A潊iv2p5@BC[1 \ߏcik!F:UKjjRij5+16kECKۇ5?6yCMPuG:e${VJ/cj4Sa&-*ǂ"%zP!VD! ›GQ7ۊڒ-k*B%kˇe!` &NW19Y(\&L Aޘ_"ຎa(H--VҊX6Pڢآb;EUآkΜ$h[2ͪTRXqӬnE4O_J؋aLٔ1B7L4m_w01;/X"9̴Ab+01'?; F9'=hUmg{C>&sbi(7<抂FEtSyƤ΢Κ\ \=PRڪlEq~+D"}?1`XxXfNQQ1S0f++l9XLaӐo"sԎ*`a*BH`<\ xR5."'5ɖ`E3 ^ ,!eђ`SM,!g$1E=N jBLa'aM=WLR9 i`.dX`Ԣ8Aeh?u5G]"^9F0<;_[(e0{K7p p$`Gah|pӱH`ܰ][H"GU`^%d`JXB/~AQ#2q6LSy'zWū5'=83{b7>'Vno'j3i8[ܶd&ÛևzϽU+?pmO>Lهn.vsc7sXEָ9ϟ2+9zvϩq6{;%Mp9a~bꕛC 2^7f76HؘjV ?[Qj&N߹۠ \bQH&+%ŽS9u~|1sܪDn Yj5#_ 巓Q{0^sA^s߂N  ~XXhS.崕>wA)n.ܹBd+ڵFJ:}~)l$[? OwF,Q%KJLz 7=V3̯۪yw;iW|ζGb>P_,: !cmV0p(dK>z|U綾%y(چϰks?,$]_GH{%Z:^=KSׯK*_6wO9A'2e RzrQSD;H&O_|OqvN_܅evǎιO;߄'R1>g-:?x^B bK!CyP D)G͑$SEyThp .رfXm_s}$mnSI[m*71h׫_l;Rݾ(Բ74'~6.?dOVNZC-S Ђfo Æ}1])So[?PKp5DB62Knock.fzPK6-2fritzing-app-0.9.2b/sketches/core/LCD.fzz000066400000000000000000000510661250202676700202130ustar00rootroot00000000000000PK8DSQ{ILCD.fz8&1]fAfl*vgںwOYd"CSVp)R" R΢$;oe6>}{ASr1?Lo'O�H?O9atm׬_f"zß~__h>~;q0Ο-K?r}3v;ջlͯOݭT'N\*jY(w1ciuK̭淔;rȱʔp?=ݎ?ۖn|Z_gv(]~qtwW7ӗՏw,2Jh) (D¯-kbV~peR 庋GO/HB$.S%+ BdEm+uS"Rh^B kk2hO<۾J#{jrn@U*BPy]yb5j{ agϧE6W0N8_}>4Y6gSV[^| UݡQɚWeaW;(4}9LTa`2'W FchΨ\UuMt+wvwofWeN 3a˜~02<{Eu[Ut[޺o^L"y[Mt\[Y_Zu!Dn\*N]d9qGiL⻁<7/;Bqo?mkx,nZrc}O[~S3VL98cńʗ6V3B7VDg:ݫztHuzuX7sfU{u{`=a {ajK=4ic ^ [ֲ'^r{{"d+a_Q6O^ Nt=@{C' n[~/c`=Dyڶת%a/TKL=, {xzo]V9DM\aӋn9Q<̃w-+T񾇰z^ez*ssp*>aʼ-`epNaZR_ |z*>W'"Ÿ4=8=UAʰױC_GztQafS-CahR=H}U{h2uAW)~*[ֶ*^}}{h*>ax qNLJiX^<\ŷy,l_*Geo&O͸e{n?O\Re)-Z: DeƤRZYq*e ~{7k %n[QiN='2 Zr[5,\ʆj(>8 eà]`:尨o9Za 3k>>Iנ>)OW+P4N+IV$: X $ix<:uFDONm Xج®>6ﵰ~ [ZشP X2 gNMD?lZ'>;TXOu_D'iI:[:7OىT˔WN$Sԉv2ۭi%m d/f99\}bğ*'ҋ_d'yp4h kSO,0Ix't5.RWd)'?d4H ńx%(j} ?d6y0ba ?Kr*SW$q=>L;iorv2{//_Ƕ4,-9"%c%^=7؞ 2YK- F[J VzA拜Zd;ӨPE—PD—PRD—`Cu JrH]!lill -t`mRDdD#o g~28XcW-p{w[.ypGNnmZm|M_G[p)>}˨/sewn9wX}%Z-"-2 6q|"/4#XK;o%.][e>znZ@{<]h OiU 譨SyӇթ氇p)iK>`m6ogDӦ#֦ 롄  @~+ӿOkxbAK%eQGL]hoFÎzNA&0NIljTW7!NAfNs] QZyX p)mQ'\7&3[ti)/]O/6uo**1:poj?=_ BF{?NtqNx % (~VRm wYT{c[_OVg6# o'JzW mڴDm[Q߲NUJ8!z#iy"1/7ٕ;gdp{<=1v0Q)Wj'}F 3speExs/o/Ů?[{nb@3EJ& .;uaXUIշ Xg"ͤ^5K8LAN&հD*^oIWB.Gk6JΦ0y_O>+qu$LU:U#%K IiJK?A(Ar탛qm #Դzg^/~ygecEb sMR}˻  ugMCU4Tb[nfGAPmFf<G9$DKpZlY薿ׁRb*`XΡһ2Zμt#s" Ճ!ֈC"('yG⢙E阋*zv6u7򴓺$l^Mr5@QO{ mqUF!@I*9{$SM5{0X L"p/Pc:ob͵>7Qunq?a^ǟf~ףturu7_-⯾|ӧO'N__?ur?|j6-?mk{+V/k׸Q >ﶊ{FeC㧹og/s~f6ۯϗ}lj-fj2N>\?=w}+hO޸򋾛~Ͼ*W_}2܎r426~=?'!Y/_!<^<%+n:O+_=/^aMyazk2d֎mES_Q2./itsmo>~ylt=^_izss5~뇫7ܾ~bâ"Д+| ֳݕOE_WŕN`r,9QExad!s뀊Ik8=h5ꭚ-Q'3֎u=`U²lJUy9\uQs{unxI#ySC)&=Syj֥Z(1yZJ0}bKִz@."Ik.1DX>ɻpYzFgnZt*LL`=\2,*ߑ8F`1Qc]kP`엸깂gjnqP`= 鲽GK `[&I[pdXGZD"Ik<# V.bhuK8e%Άo"Ez:FeBN[mS3iYYYKq֬u###j9zu|.։۽UJER$ȎUc55i Ede5 @f2HЂZ‘fh[" UV1}#h&;^Y3!뎏H) ݙ:kMj;Si8nCHyLqݺZrك βN}mok]4*"ؚ=&3aJGF "C;C`PvH$H#𝡤u/@g#r%)1)K0* W$81lرN %k;B7#+[W0h%<0>.* XٺX -HVN4G;^Uߟ8[Q1{!#9]g65pcF.dmFEǹR0#2ψθgN(:NP2y5L"ȎV6uT<(<$k6["1sEU c)#]OFft}m)k# /uuߍmId%XJb@p3^Ĉj*"%R-̨TR3U#ljƒ\Ã2D*1?EbXC)Oj:jtQNw[CIUk(aFʜ9 PP/>æ"]%79n_*)gE"d4Bfn%+|4H3D>Z$J~Uqj%IHL˸;v2 us#sWKg2rd LbjK8r޹-"1uEՀavHx7}RWuVJ],d<%lC0\ךD@rxAōVY Rt- Ieq.W- #klㅲ# t4H3pbUq6&ɪX u #NDon"8&PKUv踭ٿ{!⃉۪.߳j:"ψ!k[=0 AΕ|U fč{gt~-?qTv\;?I)yjjP\jO%׷8'_8j{V#%-: [Xw&'LF<쁱mhr쳰EHD#G;Hd cNKx Yd'ؒi:NG!_WJbrB\)5P:v(L"R]-sr¶Ź֭H E+_J>1)?;E >L}\T{urπzI.IK{@H-|Hj"NubbW 5Zc[ qW*'3Lv0Oi-I-.Z&n|,(TXdv'cn'bdل"B `,R PnyY;Λj}DNztC>bVFHVČwLtU#MEaU%WwgXs`iॉ,ͱ4Y6IBRB(Jg'6krq<c$AQn902DJbgjJuԌO.F5X -K1 'VTH!fUtlqCgmb..k<Qjk;. sSO@ú^]&iqX4-փ"r.wXۚ jAɎ;]^d>(?fj<|ߑ=o ;͏H@ kAblU433q*(QܤXXܞ"i@AWAն!tbښF.ein XZ׋[̓I"ѧV JX6-iT-l2)0Vs!t]e*Z4/ 9( =Q[cUyjd-X_%jvkjEFpW)X']r\tݥbF@ƘV5~B 5;~D$fD&&^-ldښ$Bi③[2:bXl4ۃw Ry,!k3fkMҲ#HM.[ (14H 9mȹvjDDVmMXYBIX[HQ2.LguU*9 JG`]S mWs!xD_S9HDz\IH3BLL03ruexDKxr{vdD&ZDMu##-2yBt5Me=x*D8$ M9i!U[< %&NBX$H}\`$ORoԶ@HقJ֜@J~̍yLdن3$%2I'0ʵ.glV$ښ$F JgI(]f{'9%\BO;ၣZs p<5mG7.DNS6e# b"k^Ζu`D~DVmM ۂ,6YlIZc`>jU1"k%;ɰm_"#rLm0#RcUF" &V\y\J$t-I$tִ&.;Uu7OY*.oKO &mk[s -tJ2ͶEdkbe9]rSk%$jkZ@s"uϳ2$y,F(Nx꯳?O맫wHjje/S/ן'GNNO_AK>9|O9h6 hfplo-AWu%IC+v 3Йd᪯B}ءb׋X$CC26q565(ڝ捆L[;L3mRo4<)u[Rr/`n*ڑGsl; Xۿ^?/q2{{O)) qןn6%&3ܓΚ~fEv;=nѯc[׬Fΰp*D?np5D{&~]QpEԽ:<VB{L{ϺϷnӓ-"US\d\kʓmU3aJ-1)$=}x|7~}oq<fl@C[:TX+^h^uV!2i^۔i'!$N~uuӧO/~x~̮l+WteFiz;ZY~?_xÇQ\BO~z[|W#[0y>%I"2VOo׫f֞vGБ0IɓsgM.ahex4V;ThM Fdd䈛b k_ sblGury ᗼkUw7~xKY  ?9QC{fB e Vq}C/%K1 >>OKflRd)Aho\ø}KeI@P_Cg.H(W^ Kkm %UGm7JS~pua _7b@*( ޸;_eUD.+"gMb;Lvd+RbݗX矕\xg%ge\u^ʙ>|eʕKInPI'q>aom픁@#݈@ex@&`I•̤K(Q2J ۂPG ZxVyG;5#_:s]b2`p{YJ#U@UF:%i@ڸv?R[x&"PgƟ1?_,L'N0e/%G$u^v5j! Τ>WEc%ګ,J*D"N`34 b{mܿn+o))!ZLS^\.t^ 2ckۿT'm=eeЌ ̼Ӆk0\/Z0'TYQ%<^.v JeZ'V6]E]M#v# hݎ'xrh{{1sAȑܽ9L t-Vj72ĹsS"'t+eyK֗X]ᤪ|p"Gxd + =Dc4dq0]No\g @AXXYkk!CG`Ib+^S"+ Bhy 2E xEH2@`7Íxm'3܀6pSQ1kgXC1W6z;ci՘vdy㵵}ig?q4iWic@G*2mS_7h,4NX aح8'.#an>) oiT70 nA2VLdo P&GYqmG{7?yuB` AO[,tPhdɢ QXL43LTLf*Z -ΪQ(4Ѩ CϪQ7X͏h`mh4RDq30;'2>D5UN, aOa ^k7^][%.K2oK)M^ AXLg;/5T v0Y3]@)zC@wNg _%̋{U\)'5NN8hgAGc ua'R!|!{ xDA14pJgp5+5.P\33\!7HRm@f@cv>U14ܑL 6!)b0.21:AT1rTxV(qVpWnB+b hcvT:2"E=@, UⲤDHm Is@[j'7A;H9 tps 0A=@HJ%MX LpQQd *{z؞,ȐC#vGqI3|gg%@K Kvo8*C BG`H 8xWa<9 &`LV4`%c- M&e`)=2yBcF:Xj;9A?a=qXrBP kZ͔ymXw~r1VnkjۛI 0dXRϾ.HLL!"$~}!2x@,z @ GP`QBx}Bhr*tTjn| DTpoj|vEji'Z f9ᯔ`nϠń(I A 0.pC^F81XbV`r >#ZEB Pu XVѐ ab+ x<MEێC%BдAG|Z-U;+M*\rDo 5p#>BS舮TvTUH0$ \0`fch3|jUw`h0+h7Ek,EtQÌe!C5+XXRg8~* w85pdUML34%b LK &1'1|3`k=YF@y`Md:߽gXͼ,ɍݼI]zL E0ư)~ThO,qwdח"`!VPвk&蝌:5".Uə%{˸GVx=2X`\&u  {%E< ^[> /I"tpr Zhx3eAmG4(4C W] 04F Pڙ6%3k.r3O{N} r*{mAf :XSk%k=aۂ[]f?z”#0=abr@ `Ģ#6^c Eao@.GwI1` @lKL<R3 aL~r T]{N3׻tCt4 0=@= kF% y2aXS O@T!0z /cpua; '˜1FTZߣaXC]MO~9&PwR(]8!4=Cрk>C{H4T' 0) G`#q!xe#|k[[nͧS;6ч],Ċ!o\|Bt$YB;})hă=aFؑw h1].E r _H(UDo]p44 m.K%SCѰ0Rty#nvʠ% FC "A F*=E|qm[m cE/t,CW/|M`` h(}54\wa:v(͑e /'@Qb@ě37opɕ¿hyGB" ahVAPO*E#fEI0&<{K}7lJkq ,\kq1Bq0(zJ,"h`:Fb ѳϰ|`mAa Edj7P1l,ېv>uv`N2L. M; HW^3Is^``G 19GUe B VP? Gw N.>F݊nrNo)C'ƩU27hü= 4=\@R8׈Bī<l~rbt,HS<3_ D>}L;%?zI[_.ʠ6 qʆ2Ae i( \wht?bw)4K3;ӄ`>Y>!ȍqHxN0a l?@Ggգ(~16 as/@s*Lo[ujxDnֲz+1|ohrO_jFr'"NnX^[hCbC|#o R _)/}4wTE.ݗ+aPGL 3;+ ډE`1sPk 0;Q˲U-_0tR7o1F9*.s&G)Nŵ$ @4hOK2C'eɻ T}ss ASDixo8]hl veF2FhaT}/r{#2(8?)ʧ*Bd3[dt;d&$x= nGC T`q{D}. [1JOe>qs$Ӿ5-M1ȳKdI!U(x#ӛ2HyU[b.HQ1D:0LY4%Mivbz W%xx_<|DƊilUg|1&R ۗ~ RzSAT üZ0pG$z{ rCc?PoEL,8.E0\U8]pވ-Yj ;..0mVPFqjZJSu,0\K[X#oesPUj(-5T|-2Vm5VU.B_[#T^*/j4.rDG'1B<)-h&cP K %?7a/͔)Q rE~#&c'LID;[h 3e/Ur4 U̯5̓rh'2ᛑa*\M} ( dޔx)dMJc[,ܰ[=%rXb CG b_)־f1Qs1~tg8 EĔ*܃ɚ&K`j! R2Y]> S‘fVx1+01K~=Vzl㫯#7s@4Οjsb!pN%͕xJ7L+~F/Y %( (XQ~mْ~Uq~ DLAidpuޜeI|X#ƛ_ԪT TxTLǩc<5+,'hYh>>/ .|> -seW3Y$ޏK\BN0?c &v ^X+ m: ;alIZ$7.f5K]/fW~5V"u E_|<(w&$(vg1܂V8:p(%G.^}f7]wwWa9u- i Ļ| =Pl8<8 .C*[7e1!l/>GS-gs ci~O~C~O~˧//㇇#{`1z~l"|ԖoqfluXݒ ܥTf32z)k:RXaY1}PVDvNXר)Ws<;Y47B*Ϋ`-yz,Wr^99@IhC%WFfx.qKTD:^AL %2 ~Sif0*na#N֜?-D>cT?iWB!drh9>C}*ǕѧiGh?IC-%}:xtDzO+[ҧ>XmvRظ}*C֧O*Αi=pʁǪI' \~3r i[uH.GX~e<~x2=X_޿a9{vmr ?ik3[aX]d0px`-@u839;v߼cEn C#&LK1kjZ(%;ϦqZq G@TN-777TP9B&U11jZȞI| =<ѓP=%ճ6@ϋD='.p2q#tȺM>([|mhC#C`yXiH[<0nG`жaSHp-H딢-XuPR'qx]ak1c69k$R,oIho\Aְ#Ƒ#FD- m kɠݝ @E@H U[<ĠBIXA5EkWLeGB-&!Zf/qewCadE􈔬y숁`eb`Ue 1>"تhND|LT|H"[`@^r=(BvC#d-tq6)čHĚydlu11Ÿ5EY-,qHT.{>҃+HeͣH LҧGP:ow§1yse8/Z bDE#'%ȓ@1 T ()w+d!#|08GY紤-^HH ӵO wh8f),mS$몭iD2e4]EzV&UUdgbL\ך{VY{yYS([BPTFCR 3N\Dd󻻛֔=bd@cr$ɬ~w8͞h*t&LU )ypo uQ`-ҧHZŽC>Pc>e~1-iYiYA)65Q&!J\ 0J.\r{M7RN %x48b:@ǐ/&~+9[1A;hbN.T04 -PɎٙ&41smZBDBJHcv}y8qr-6iK4|q,q`䬗cR#kN H9I,͎HۚOkHU h['..-k`~LwiMy:gvWoCu]ug(fVCV ߵ W{I{궀__wj`1vK⨺s#lbذښkOP슬wUgT҅_Pv30lyx3PkMSun0dt%6$"{ 0$rA$rjkHVu_*r?>Z|㟪%Kõ6= )MAJepRCu0Dlr,7xgOAGVbkKGJFsJIwhlmS#f~eDMdLزG2M t=^Ny '=5ZXgY~H#b6lHڄSKA)δSvLTe \n!lPU"n02c%gIgCIgmaҳzvwwg~mYق:gUG*`d*>HU~&;@HКǒH%h" 4&onx<|M#6#A'!hcf*{ 4o}ry"cM-# mbHښ歟H W0zFΛu,5 u3fpebPt5 9ڗ ۢHCH)%8o&r!j\ 1dt䑥UQ$%ќr-;>v_|)^$s`.dTD֔/C*Tfqui[װ.+k,CbWYl-59R1j0͓:ML^ NPbښ!+SQ0`19:'H0,Ȅ"(s4%# =k[Ӕ0.\\NEKo6釴yG0e,nmH7 U`626O xCM9Iն^%N.̈} %1+ dq` -1iښl}`rKM}aJLjoLzjW҃77mWު ̤G/*WNP f`m~CK-DzDzYmM x\e-g6,g*X=,<8Qժ U2_ )fbqBݚE2UsZ@$Mu|:OeGz>Nɓ-Kd$-K$4,gOͺrrۄM"!!rJQCjU1QLWjYڔ15yK;?%Nwkր%%jkg%2$26dXw+8{PK8DSQ{ILCD.fzPK4Qfritzing-app-0.9.2b/sketches/core/LED-Matrix.fzz000066400000000000000000001003611250202676700214500ustar00rootroot00000000000000PK͚8DauV[ LED-Matrix.fzr$Ǒ.wiJ{P_(r&%jh%FW70B=cP dYYuA]""dj2#==W/hC^M_ܽļw?N<<iL_56L4Ѽ{̽|u15 _xj>psw?ygO7Oӯ^9[//v{|rߺ?鋳O7zcRW^]Oo^?}B6\qJG.z#Soxw?_ۇw_?|WoۇeBo^=^ ۻo'f?ܿzz{rbWwO7W>}ݣYue^+K/ߧr?t.4)Wg:wGor~r7@/&tRpq3QykJSeyg7H0_n]V7_^|wy槹26o~y300]A hE}O˞^~>tgx;7}z|Iu $0Q¾8BA*y0>%.) PŊ˧M=w|A,>%hJ+=B\鉑)|bnռ^9Kqٻ|Q}~yqMX7uc^? MÎ'WQE>l W=4q'0fc$)W"n;>fo+O Ӕk0nqQ{|pU*Jc,\7DP^V:GN}^{p|ԲV }f/WOU<xm ^@[(Fw{t] &:^5pK6lhR l@.@y {[*SCйFwߖ{t] :T&glhR%pZEIUmUKy|]Z*M-Z*AdCa{|[x=R ljRǗSBWГJ*Pnq74QO#dvrw#Je>lXJ:Xx|vC3:U|YzکTnRJ}*>:[ mUOJ>*|ذJm2*UT/cJ*>&+Pnq74ZNLjR4 gJM2J"yÕڐ|-WMMWdCە:{|x@nR ljRǗiWU+nhRGgt+Ն*nR Ku >pЈ:q{V,UțT*ŐI2FGa{-Y*aӞ MYaڲT'a,I{E)nRGޞNAK2w*E>&-+nRlnhRЪJw:E>lЮ6L8а:iohR%iK"6ж6Lw*|ܭ[S!x6xohR4pG¥RU64qɎ*#R'׫e//>j_u=ͫW>OfzzI]><^/7woo޿~az^.OA͛_/j̗O>]~"'[z2_>9m`Xx0"<jx9͈i._G|~ 0hlf(==wï^M>lu7pAR*\4Vr_^lWvYwV1p|e Љaeu>ue^<ǻl f0#RHÙbÇUv"K@Jb‘NI,3\[; &m81jΙZw2)*YM)grn߂V2D-~Z2(nVϛwg(vҥ,̼we &q% t5 hǾ@ǛǛW?=|{lzBYn&3ω͛ldۿ'ζ| W$^{/r^d#박F(=:" #멣FY 'nw. t$ҞTq,tX}ly"b SoT%adYW"`d]AdRwY$ NyZ$])b z̸sY蓔|YrGa )H!2sY 0UN8B(jSBv_r`^jкf#+Ќ Fxz1^m'Z9Vq֍\ZZO5z~,2Sh=o0gU ThJ'[кzb 32KcSu]*n u0Du 3F/2iG9n^*'BR= +pD殖> gbg\-e޸ι%#;35#;SqD*331\'L/)̸u`Q591̄%'L: mVFS(St(äTqR4n1N=,wp;MܓTQ̥oygCN"@W( Ol%xBTJB11 ;n0,{xDErXȑG(`BXdxm1\a!'r$/aŸCRu!g!Qc9̳8^}v$RRrE hw# he 2_|M*n?K$#17o~/>^~p?nWn B.U#kgqlϱI1i4ɂOg=~F펁 _N±-&a_&_RM+GݳxA0yxcW|mU3A1wc'.-Ǩ`4&TqaA"KTFyC9DYݨHúaAŸ`ɎR5 n0ru-uc A~`hMnU؅A.*.l)P9IHbmEB5ll5GzSw)Î'yK}5-wV?UT J%pex_2^3;{=GVbk3{X=Z:u̎)ΤT<,ᷗl~{>Gon`S3&?:DT'Gw~-/~_ч}kX~V?I<(3?)G'<鄡'=S]{.SbOwI_{̳Z,;si.%fCߗ.h}́~ _;z v@ozxt:wtI-ҷ O~K7+t=_z+/]bNZ_:C_̗n RʛMb^~ &jqs"Ԯzq[ڹL,ʹh!t9 I0,puUwTf;TaaD&1 pD1>ila6E3;diaAэɺ4ֶGCɺ$SHuQ:k VR\s-s-<" qjso V.5. zYR1T VHlgCZSfܪlz`\k jx@HaC |b8T6ŝR4FZgl4ܟm[6b/8ߩV:y6 93F}m[osNlWjܰ,y~ZYXUkA&:)V2Xd%XTc'2ܐLiT^<62`׫M52A & jS;zibWjܨ4ƸeZv>L5ncïwwlAi/|W |ڝהmy$T=#LB)k}ag~' ɰo/>~BUþ7z ə{p+*|{ߧs(II~ʭǠ3Q%5L*]PXXc6Pb=p6ܽJd|1>x0l#e"$Fu:eMƕ `"+ޞAv\+Ibs,m[{7VIhRFɐ$<ڑ 筅@ezD=xż!WCX1jtqkr5:!x F2fxaf*j|XmT >BkQnV wIBSx83_2b ^HV X.[nF6đ|[$A'lOXml2HZ:|}FI6{yMv,AƆH2 qo# R6|[(A֧lG)L٢g\ۆczG9x£l9 +pbȺaWe; xnA2o "zi 11Xi`zũ*L!xh&yAxoA{e+\y$26ʺ+Fƶ Ɓ:tTL#cnG[ijɶ> dèۺhrڼM$o'O޸8y+\zDK6DPf#N6)$)$o ̍@A{-:MSEUttrdl"+F}6`l*? MC Ei}&Por[?KZh!يmm8m\O'diQkk$#?,"p^lŔYq |ťxEGG {m(20 dP.nMe}xvu.IP.kw5l(1j3Юpnأ!mlEn'pw>poKs7pnQN灷U鑾}#odH"pUnd$'$z~&HD I {4m, AdP.ci,Mfiq7hwXّ \bMZNֺlE8fJ,=a,6 Q l8ڶrJ@5|[l}Ќt+=cJsN $ LBkaRbX?ǕTZeoQ]8ҚLHJV hĺώ#I#m[ 7w30w㉂>Ar{#PhY X6D~=!fmm(;PX[};U6V} m%G=~Ӧm oC$m}&QrͬM+oY[#A{-@L-V| V[[3$m$G}`֟#H#m9[C7kSH۶MF_9[jA#A{-@jLM]9YQ#SCX9`j"ec.@~1yo !J!1ޡg;mg"=;+wA{->J L@)6TJXY[[`.$ɆQY`i5YK! F r>wݨnFؖMlnL^]:R.ˑ  ʛ s-DkkM>M(VA,0nvŭԂ#٨*$HJ#my[CdKG ͼ%fIGz4H܀P@ovJuk adOlCt A(2o#Hz1RZ>-OѶkX$ҵu.#AA|Bj?QuL-ij95Ek#=~Ӧk ]Ck}fИQ>5niHDH>"Z ]g3٭֘ZmQn1-dðOu9-$HJ#m[tecD%n(ݶR$uYҎT -6۩ lbo-iqȺQaHՌ"R5Đ{[A\eoV]B~(f1 GߚN<%.]QԴ({tͻ{{"7RRʖiˠvJ6GG4FkjF;MhFlACGG6nAbM"f gHj9|:SіQR b&pBV~ڦү>Hߒ9Pro Yow"Z ee5jdD1 W5 ˊ)JtIA&HGLۑC0)2 5orrunʤCDeƞ)(dH܎(Hܲ7Z@eldl^{S6K SXNs'Z;ih/wkN-OdBvbq)$o Y&o`{Q5ws(DFOAV- } ''KX!ADGH< 8^">R{TEv,xs[5wT2Kr %H֎$HrI* ׹AZA,"ߟ-[[P9Vܘ 17@H8%!71g`*Y;q70%  -HjpYdm~ {ˀ ɀ"l%ߟ [TYm)#R%QVRԭM.e;Q7m7.jnYd, H2@h2^}'0yoGxfuIjyC$=tn}Nn5A%b 7bjYO;M⪅dqYadY* %2 h2 ^,`?N1Aai|~oXYYIj|@"G>D[|+ѕ0dqYdY - w& wu3ߟ HCqP(JTmZ"{+?oSHi۪)o[AࠦuGFL¬Peeo {!#f썩7J˲$<7Z,+Z{@vuEŁqX!`U]o}_ڌTTIˍ"ώ!?4@egќ*h6Vx֕m'hh1rhF1XlEhfAvtA𑋡, ?TA?Ӈؼ m"b ~{Dc.DB!|d#h47 E!H9U)F!E QA!&[xKւ=iF8c67 G;: GCXnABGs0Rzl\)N:"e hF8bc.frRCRl dhZ4'"MД*L{51·KDEާRRܻҴ#!QZH$q,qKKj՞H(*f07҄r_ Y[-'v=Mp)\4LJ2yeܛi]ᢄCWD%EV89mXNtj,vm@$7H*p9),%2 2h(mfppbJ7iM$R`LB$B&w$,{tL}lr M#%a(a ].+j5J Hd? hz7, kkM>elNYHdpcPwܣcp)gLy$цch&b(AҖFN; ˠR 8?c ߺDܿe %Ex¸m8I6ˬA)G(37A׶8RJ2(KL(9|iq!P@9X 9H6)T@tɐ)U6Fٸ{>a7D9v7ytlm`|mN!ZDI"n̖ZZLYAMR A\DM$jG$j0dz$cHhU 6Il$E5uDH)IaKSκBgTJq&yQYaYZ&9Y.cዡ!KqFm"disvlRMlWL6l[(ii3eeG*KHiD$jG$j0dZ-+$j""$j3AMޠJƆJ[WP+yZb4ǒv2d5P<@<-,OA:Xiˣ9> Oky؟ &Z]U|an4 tt)GѰ|oZPNdV(9UqL%KF2"tBGqOZ%娇z#Hz?]+9;p͚~:3OY_%굖t<:ζ,m`~OtI8Avt0Z&9YHMUjF0HjSG6F"fhaƟedQfk [n"[[1cIw9ʀr4h4SNMi$gYF#9K/(6MnaRqdeҬr"+;#dc '"),_g N\ !74u\&b—ٟ&cH#4bvY;GwڣJX\lcwbpk{F w/ Gˈ%XcC>LHn`-+j z7o$2I4J=I+ K@n~N8mK!2HDmY45V>p-[x %! ҦJh M M0N0[N8m& Z#2 9> m[޴MnNIl-%zx^wܣck k`c.6bIxv^w##i0d ,W:ف,| -Cfzh!YfmO$TXi h6K>beU9ʔ&P2Jٖ(+A,X't # 6Smd9Y4 -+Ĭt312T ÒvWN-И-i;: 9[j@1'[j9tL@Jl % l 2hCCQnQn[#J6'1_#bUXmS)er9G5[^<=|Xa.3p32PЃޭ "C)!z(a Sˀ"9>`lYk0]Ssy̦I$0hVxO%UR\Xe$MfF$jk_HJ1dHހ 2c Ё2eκ?1cl׾ZRQFIdY4]$N=hEB)־ đӦi*=T-` ?e fjlrcn"HRBv,p,ȚIxIԖbDIH1 9 Y[Kđzxڢv ؁$?K!;Ⱦݦ#\4Qe`Ԭ3`ji#ÝiFs$+Mjm -@Dmk?4AIN;fX%H2h%Y[V[f)?\t~8M;hj2CV*Kɏ)3wU (W &R;=T-|`8? I3E{V{i3$k O2,,R>rkFs$OĨ[C˼AV% S #'W3$H2Rh%b[Vi[f9ctmf@ԃTkJqXN#Gjdkk_ &@f&j,3h Cˀ?-ֽə.ڈE+Xi!.p$i` qQ%^'Qj{l1Ҫ}%T #x!9[ Z4$n ! n[_xRƤqbNyqh1>|, gӸo-1eVR}%HrnYqZ@!pVQ=h\"ҳ0GGϒS 0h"' 7[HɌ,x 3AlۿnTDHĴwG"Eb4GH> &55DK,(R) U #MTI[AI۲2ODaҶRCdr+i,vT[dE[ySM+aI;Ir di:3h CˀXO$#~ 9[3Y%邸=DFQ1 =XiCw'AT&5%6H2,(R7`P-'6Y3$mjL- [ wŽMlϒiJ6h=ː),N"mXR$1eKy7bCdnk_ 2PrUE$H2 Rh"XX½-]4VyܗECMK:Jڬ%DY\k+$hU  rҡ5 Ar=Gs|xZ_4n{m;'ņN:K:p\ 3!OHjjFs$ԩ Քy3!k9q-d s$9> s[Vƽ)9Hƽ\ #5-i7S 0ak67 ][HH& 9m22 ؁F2e޺?9+"|F^NR8Ҭ}U3t=:,qܦbh M[M0INuZ+΋2F9>&rVm f(B̅iZmTXDV(¡:i 'H־$h91d 2`rhL6v=2!ͻ!Sil8!,EzVt3=4RRb xdWX]Z.!2`}, JN;QL~̈!,}Ya6Y=lc?#L}\5#%S %[V))KZRf1[ #0lk?@j8N>e$gDEs -(]սBE[ A "Db41m7< ][JeݕF;9 [AM=isEd klYjR/ƒ JapNHaswУ#l)1Q LٓFԸ)RMi ck$5E-঴hAemb!aWk*f&qU+fBri9q 29> '[V9+b^8KI0vV!22d+Fs,d,aZ 'Y!9~؁,'n6'[6e@dAEcQœ,Iڞ$ܶ߂ ;#m*ف$.F۳5/0zk?hNYa%K5H2. &"ODaơ IL"#i(<-TJAq(#j{5O}$iCw##h0̠,vh!rB\&gqVྴѶ.X:ߕJL|\5CEٚ,0־CeE"؁-``? 0"Taf}Z>-YP j9YhaE2Q[M}#T˄ T3Y!yYZFZ_4 euYZFgmەjV)ыsY19ˊ^D~V8c$8lk?ZN8mrFsұ h ɖqoN&HaN{ m_׳d2p!]e K'VCQD5Pq%X83f ?ĎӦf,, ; lC3ZEw N,DƛbmV8VPrLmh q_A6Y7Dϒ|s$gq!b@sG,".m"gKW eֳ&PNLq6[AʖH0=2#`mu?c+-(JZ{&jg&q]SUCbz%0=ZZN9iJX"H2F9> W[V(RiUp)M5ڑA*; kQ!k*A2` @ZN9m?ekJEcMLpbhBTʸ WXU4{tM-|f:$B9! R*)\V49lMe@dqd@6gpV?ƚt&HiUwicCVRVŽ.1A7,; lE&R{RVCclZk[j &l)<-`x?# eeܟ.CQ̪ҢG@z$m7e* HwͱZRl|qV6q]'~ ]ˉMdAcY[0AYۂhX*]-$U#m(IcJ_Yzއ2X[/TC6tFzۏBmk_If"($)Am v c!-#`'kOXafiJ6! Y:SmbZH!Z odp3[ Շqk_ ߲bLIK\$\4p=Eܟ|/zL{j"܄4iFބT* %$JY)8]2cEV~ppI-`.#`/ ޟS/]U4V+3kDbdm}0w(?ܳ[.l+ڪpbR%`Pr}rY%H2%l+"=sۼ弉 0-ThXq] cK9{Y _Kt[&4F4TQlV)`KLr%'[?rk)[X[F,X۲`Ʀ 3 ^N^>DV?4y4J!s5QJ}!ZˉX @E0ڲ2ta085JҟhN.֧[ڊO$XdDu$ж(/ [N儒fp\@A2A\_4 La24"n攤G_[UӔdYJAq.ZiG~G2aǩVlYXȌuRz-2Ñ:i_P,11J)ؒYuLA  '׭-}H2@R1z)?3]`^U(- \)@% ol٬:" [@Cݾ ` )ؘn Qһ2lIBh T#vI[)9q)~l\ =V Hw R??`k]KP0z=M~_>|/__|yp?ˋo~ m<>}j>/'Onx|zzj^?+_3N9/.M_;o{\Oӻ-^?||;={cno٧뛧сɧ=`\/|uY:^ͥ_曇g{M}{/!\_?/ϳ}t;}!\6|2ɫNnݹO{e549}>{/݄ytmOE2nTiB+O7Im|P67pV E9/ @ c iNBZ 4H7o&rN(ZeXn2TPfdE;I"^F)dw$6 |n8NCryec'76`ծhNJ P+PY!jE j2G('ĭNdmo/ĭfAv" - qDqvSčI^8VD6[@)ulVNH|!q?=TJ!U9bn#%թ*bf& d\txn]cbs{@ R REVJ> A:JGNNiz2(?Sp2n4`)Jl&"lU:rXo\Cυϓ^Z(/5\+"YeEs, ˀ%Hɀ'Hzspt%^54WD4D2Yܺc $Du/*j[l#X#q_sj}' I[@-'v=ĭ ]ˀ"H9>x-a"M"G @ٴ"e#Y~4Rad#e`:~5`2aMZAV- kˉ#t!AHGs|0Aⶬ7S$qKHX-Y>r$m+Gs$|,Z imUb]#g3,5)!mMDӦm q%H9> q[$i 'IT$ekG֗e=S{׉*Q]/d0k/*![N89m&ˢ R x?c Rh9p-%&(d Hm5}Ն#Aq3)f: ޤdPѾn!dpGGdp9- &H2 h)HE &p"A8m*iE5\ ;vB,!r]HU%GsNKO.fłqR̠ee8 Yv*QA9]V@9٪ #%Tpn|wv30I79w[w${pW/>ݼ~~qԛCY%'R?K_Xߩb}W ۯ~_鷿%?_={/?<7?|sp̬o\?=ӧO'?뛫 w?f^ӻåӑ/~쏷Ggz:y.rwgMG/܁7<;Lz7$qկoă/nxs0:~y3xƳS^翾yM{]_W/ã[7o`S;?>krznL>+}v~Ǜ>^=Lw>, v?H|>m+_7^O4Ds&3 dB)9iu=ne#F+gh BIc'u8@(1"$ ŷn&JsEF)_pkb*\D_Sv?_O?TP7rA¸{8 #C+X⊜Q}b—ED85;_] vD$=w_0fOMJ/J?Ȇ_߻Kx{s'/?>iU}" _ F/£PsTøvZ_Q/srfLÿ/;d̸칰 w:i/gqw #<<%0.H(T|ݷ}18*߿tDQ`|7罡3bÄu@0Sp>#(wj`0L֣2 && z2AUFk\|thA?WgFt?":+aKZ7`O8+Љkm[ POA@Acg̕ES̾QkQ!:]km35Ob]?"|`9E"D/h~*>p"ܠ9. @YXˌw֣+H1~Pr@31YE6s~Q\Ί*ù:_~^>@HeZ^aلqIb eĭy$%DWO;̓ӏӀ)d(*KO.~/%|ޓOϟFN92^Ąu;/`k/U#X$~NCcԇu1L?BIlg9.7VgX6a<&ycc嬡 Cr_X0~}0V,z"ݳ-oSExI8Gg>;en'4>eAtz0/$2tQFX @﯃}FD<nK?&h nz* gph7约_mg4l´./M;Cϛv?HxVW-!{dbUr/X8aa`qD+R$̯A]L8&Aݼ>٦$`3ZAlVws!̠L2Ql=f7~w)_XgAaEYX4rn5N@wJv)P+X dg)`v0oՄPg!]1 MgQ3LI0?F^geF@\8 T{xm0vp`6[!"wǃSP a0Im7 `v;˻WQ:f;,``%F9uۑj tESMA8Lg""Ot^X$'ajt7$讀,WIsExO_T8aqU$0(1Lu@W܌c1 aiOft#C<ͱ t>ep  FEp73A NP= 8,gANAf΁8b`m 3U3Pp9 E,!g2ݱ:@:ܩb !8c@`e` h2c뜣vT} w=\,ATb9!xDF/&, c"Q7Q7O: xdX! !3[~6Bp$Iݡ0U_ F|p?`OS/;1wEf"Rs%o'.|.!jwQht9* 8xt?`^B#L@ T$`{G>&s|p=Wo O7N@^)+H OUkh. pPk9T "ќ@åU% G/?5A/4XAA?HXbAP TF<MHHm |<7w"x \kRcfŃFA  Z0x#agEd AjD* vr;zL; `x9k09jzUvL.#_Á /Z#c8%Rs ]h 5w ,.1F+98 881^]⭆eh2 a]H ƹ_B>4MG)k@!U6$RrBt̏fv|I$a"rGg:~@3$߄K¢ǀ6 +($?’G:D7\w`pTYc/ HCw^:1LӁ%5,aDp W׈4Ͻ~ SX{a P X`d | 0pM  @<ཱི~> whpx#i t L0k^(pQ7>; R nЩ]j4^{ќ¥bcfϲgxA1 ^̰RDp@ېHPx `B:6v6cB-~T |#xS e(0 #*,`9 aۑG6gds9 3<xG8A A(-;B^PQ zq˅PEu @ }'A9 `Q0W&zأѧB2xa3?LbQqvC`*ﻚcuM wouqS:cYL✈ؤSLd`&`W.]@I}z23u5yH\l2v5/\//\QV)Zacj]$q[;$&$u>VXX<I4[,ю46|A@! />HȐ % 5NW(y+>(Cd9!W ) o&i 9`&h#LtrOithExUʖ}8ۅ4j˸X'AgR$zxFmtN2[f6 .HuU;bΕHYjYtsWLY60%Mgu'F̗ٙ/B_ɚ2gj.N1 rn4g?v¤|<0$=pQj~~DS m,SwQ ` t޳`) VdvQchͮw U_H֌>+u y XLqBHT tp[e`^I\r0AJ[Gҿ}}%S(sVmstŹ?l.$T-%uޝ+e)9N-%gy.gHB75i~LHn fbX0,qA91|Fcc_`|ߝ;ODd%f+:KIksMFM;L{~F=/YePpPps]kv-[8%bDJKs4S1S0o6㌉&s: AHP#:K x,qf9ɸ! ")ߣxs\dr"ά%>ΩsBN ?C*,qUaJ`A b@`O}x^1`-yS娫ZxcUV(q r{B&CRbW`kBn0q0bh4MfA<hL䆹]`53:lu{vں.>OyEOחO?=]O^icn0Py+_}Ogn·gj1ypd,qflׯHܥT-jZOoUHo;:bn1p#v;/Nո( b~K|Y|0|>5l&!C9^q>'7w?ӏ|s\Q"Ns\%|"~S(y5H}R_~HLv~'źB_>=\=xwBw(oX ~̮˩rf$,+^pr.^t5UQ]Y }vd;\MdP޷j%o阪Ewn'D:CUgb J^|VUKDRev~[\0Z"eԧZ) \vDv$L0sjc>jnUoqjARQZ4ٹeNIZfgSP$ox%ȹ aLrЪFNӑZΎ56$,H=.'a\ڼ 9}N87^e*NS5TXzM3Viñ+훢6D4?Djkǻ|/ ҋyǻZ%ݍ+1Q/]6Kc]|HJZ.vIo+i>|Ixg IVSK3ej:afXc+aqP"} l_p!dAS>O_pCbfCԧ!ɢO$2k'9}DŽ yI$, )!AN$fҧaw0D}|y-d>u ه>}Qz)ǧwq$>u 9kCa4 f/0> 3Чq3Yֻnd'(YFfna&|?SŸ̳ޙc.r`-?߬p@/.Y(~M$zKġK&mp0 q3 >~f|9$|g~{}ꐿ?۟.>:Iܮo%yMW7OCɥWNԯ]9yk׺) >D^y5̦m<6ޔ RǓm$,:$K2(I/u>_[\iPV L휺8%N-pBMtc l:3LF7LUqN˒tN7 2d,HF oqdqѴ@F0̌uʏ'&%iYvMi䅾#!#X+i.YqOلU 3; UaV{h7q7u`H Bup a %UF ev8ANx|0ANx(IP/89UNh)}(*@a1M8|0|py |P惢~& .p%,=[^3$oכt] ,%$3AGfACscBTq͕, ZF.ə:93Y߻f\T#JTEv0K䩆pPr u#vmT46P@ {nk+@aMX0A:8B[ 8kY1dɶ' Y@A^x|8A^x0^ț)[О*/[ 5%ƻ8oRt} d3$@*$#%Cw#c0yZ ,y.|7!%Lİݺcwu!yOӇi0O[Vl-REؙM5$MffGfYT˯h{h +h267v'HOO$j$jd2'iwGyYP\ָJ'D*aӪr dJq61jșȊHЎp+Gt+a!t  A#iPlFi`&Sf -Dahn?n,-KH溴īaV8Eg5 =rScPoI, _W*0EJ$ozYEYq@Ȫ2(c~8qC|~#c w~me,_8 -Kps+F` رUjNQfi6;g?"W;%d6_VX˄Yqz8(ܵ8Se7Fs ZҋBU^YjzZzڝT+|&"P)@Z;ZqgS5g>Hh1 ZL6p9Ϳs]_㏟ ,u8hʓ^F=̧{,]n\gCR|9D:tߊh2$ Gk)]I^065fXyh9,V' - [)ZL-{ep6ZMcy1VX#zB/@Y>\&4aҪ? 9aFr@*WVn4%x̚se"s0.A?_ п]Mv-f=`&WGP}?{Y<Fp?FS%tiBui?DFwc։eLC049>JSnES5>G k)YIem٨A̎+0im=K)ziq{R%n}\C`s=uá -=uQ6z' 8E`h5 g["f[pnŎPKk4ASFܒdnuivIl=8%u o94jn˸inya3V&$uvw1|$(clAqm߮|AΖFS']_Rw&B(ϣSZ\TH.lFlU~ϊ-I*G9(wq1o:ˤge V!)\ti%u3^Ǯ*y~P|<邜vf%4ui2o'h!9;U9I+N\U%Hl/U_WV  ig#h*PwgOKĖfJP'$Vtv$V3t}q;KSg֒&(0I+HZMh̼+ݗ<>CK)Cu6uNJL[hY$:q+2B[d7NjBV:1ܵ1*!',zLLs`-*qw!hC&A A+ZMvt-hB03i9Z#D*1H-LyY yYp@ZMy@Ks^MJFϩJ.}ƣ,ɑͦ`(V49c6ZF[qjסԱgV~`BJ[Lx='9i@h5W _iKtլQ0;≖w[p(.ض)teq'y@׊sV!]_xG lLbW˭n$! -B ji40Nj诘cm$M'JiuG gW͐#lMɶf˘j3x㖞$J>@Hnr+"${L, R!;S;Dm5ŮhhM&6oz0NI5UҲ+JJX55,1 #pUHGUpn[!?+4\}=L\gEjwrl|BsϡhJt|+)܀fY4!J`iAMĐn5mlLT* ϾZE՞p54%bߥ?wGm-*kj|6ZIU+Z%tkj˭=!gA j)Q{%8֘!:O9^ ܩm)ix̍n+:@ӊcV j_lDoV$mgy? iI椺)!\8{7ڛ&>(ܟsp45WϵÕh\'P4Aǚ$U p5b9ޏi4Y&1އҌm BQ&MF㨞"~gPK͚8DauV[ LED-Matrix.fzPK;fritzing-app-0.9.2b/sketches/core/LED-Matrix_simple.fzz000066400000000000000000000553051250202676700230300ustar00rootroot00000000000000PKq5DX;ZLED-Matrix_simple.fzmsȑ.}a!B`^3ndz|P-ՒVRwOωoUf,x!UmL ̪ۏŻǛ_oz|%Yb$\$ݬ>s/.oox۶}7Wzxo~;["utowoWoOn\|gEcx<]]>\>\uk?V iN/?>.>~|Z_n.]>|(wk[?^\n$}v [k9䱿FYwoWGcRmlw.V:{,{ʷwW&7iOv]w=?\G?.?|zb=6o\\?.~}w>m:Po.`،ؒ9/n/C#\~uaea:1*?[|J cL-~K4c(cqr*$[;9-yjlW|U#ԇ~ kscq2_1+|p;ޭ,\VtpWhQ\zsߟux09vwz-ZwR r"u03P@k"q"%0mhMɜH }9(E5<ֽS6~/u7]<ڗY4fV/6}g%'S3 ]؎u0;V Z 3(9ZY6 ~*0Md<9@ɉB/c]ĨM$}"1s_ jAiGm"D*d%'R#3 UԦR'3SYS5qԺlGT>xz|ϧŧۏ?ʝx1U[gB%k<m:*~Uo׿?|~_]^..Yӿ܍j{?_z_-Ζ%_]\|wJ=[]???|uqL_jyVǛ۳߾͵s}!Hu̡N1X>=]-\ַ|m}헯~?.~5~tJ1櫻_*x(pniWᗯ~Pv#4,y_kLwӯN/şVǿVW׋7_q3.V{Vx+w0Wawg_/ m_W*qb}_KZ}xxzmSvY^="ӷ=&\Lyϗ,]rԿ˷K;?|{`g!oܳ=Rp+Kja~cy]Ob?g;o&Rպy55:6w|k}w?a7`"?{xIMO?/gT/d_e\jLds ٹns pq?&B~mkZZIukowZ} <*αmV}{eϔQx4\V?Xhll^ )%nJ{4Xu])n2T?USj˄۔ $*30(SjokЙꂊL%plTڣlQBʓSR[Mi_S)RiTMئdA&8 cJR5Ƕ%=eR'7Ty:U[j[xt[jp :\ u-RNǶ%5H<[;MgK2%%61,eRrNԺMijoLy}zӲ} < #;iL@Sk<1saΓ'IO7R!iHuBO'sHue j^oϠAҧ72 3JyM=jbD4k#ce񯕽Qӕ?M6JTWOt{%rWRTm{T65$PnCGΦй"InCGNI"B%oCǍ;?vRd#G]GN =R|GɸQGN=mG}QGN|UJKDSP-ou1A_*ifG*/i:Ѭ:=+H(-֧q,t^ZVІ'ڭ/\ rݙ\6K"RzyZFtyyK:vݒNmwH~i+SPo-?[FݍvQXEؖNvoό Dsw/ZZK8 ~~e WIH@׻߸ij-]jwpsk#D"g˫/lbWеAbmYj RRߤam"(T;\5@ 쳀òz 0Dv\& G>`졳].h:Eע'@ h bH!e"GA#cEIODbNޛA1ɖl)dkɳ,HRJƘsgڕ6@X]۝vQ ͓v m.ƾ[IN˶ PΎU` )M620RLN `qv:3- sҶZ A2_K_= sDZ֧X:ad].R{!ɮbt (C(Y"\q#zބ&fG缈Ԥ` 8#̴&hIۇǘ+zk]fd &1vuWG$ZQ2|w =}5Q9e}j7*<$|]McEUJ @@īfc"xʫr^Y[y^\.E^5S^N;y)/l+^YWhlQ&]TbruV۪$L" st dH#H2tk)DG*]L+nV}#L[bHs9i5zUI-*OaKȶ2em!Mg[Db] p,JŜ}"c->*钭Ȓ)KȺ4 |-hW]& >1ڥ}-y!yVZ}E{hb|4 GRc"ØJňBƜ V%QǣaaU%. qīQ#\ZӐ h%P*\=QWyUv o1C]3PvyQtV+M2{U%B5ǡxmWi/8'mRm~I/o5b#Үމ.h1M_nH)_uT`arrċ9iC"1&R-Ao-EW2UiRٮɮHE[h-"ۺN]^hXtl9P]dl&XG-"@1yiH-\QtE-CkQ˵2Kdvqzwi,?>!Y]Ю"#aOv!wrO$\lEfpiWϐ$ tqm`Ex# kċ9i;@ˌJ VU^XKe2Q#~a$]M$jgNȖV" ׋4<:\튰q|kȘİf~A#j=UԘ;% ǘ+yiˤ 5KtӢWWid^u]b~E5$ ]S2~+5"j" TȮ& WLqQMqŋ9iE3$[٨dː [K\pEj^{ Wc." M^XXuߖUZ.H|4?"WHE's!dbIQVJl-IP*ǹtݲ.L.ꎍv5@& >1ڥE\ֵ>Ra[!lW˜vu.Q4A7 tqa p{.#\It.F24^.Ee$xTn3j]K%^ݫ#kݭ'Qu=ewJ{M $FLwkp^KadxZrSd^'@]0C[W詢 )F9$`|T `&`KeY0nR}f+Whn44'm@k?ș;Ƀ|W]]Db>ޛuQYA`9o5̋&`I.*1&c.H%4嫥+I]\DJ{R}55X4`ȆCS :]^'ZZ75$Ih|4?"gQM]M.h1'm» ƘKʻ8aޥu1gjD+5uuߥ,&XDA'ƺtUクvj1t֖ J|u5,&xGzӄ l/=TIt*F2m]m°1& S0AU^RY~d kky3PvdD?b|K-J0klɓ`WR>B)S^DbjCB[V" )E5[zT%i-vOH%5eJLbd:_7l4sҶ?9d`)-DR$[h#W_$_4c>6qáX"̴/1'ma`L#21EԗeDncr1,L~uȾDwS<)fNٯNu˘;m7:w5*rWu$Ԙ> 6tπo_M 3Pv\20M00#ʹ~&s V<{6:ra4ᘓjǘ [ɽrNNMI0]mp g}HD{h|4@GL E"F6F02^z,,!)˿`~Hv:ӫBDTj#rfr+-$Xg܈ATQ;$ C卼ITAc#cR|TҠ^:H S$+:4U r)Vm7:ՈO=iXsHJ'|Mt]D;+':Hc }`Dc>#& HQHŚDBƜ O9cedyXC ,ծ,|5ƥIĥfN)NtijEe,rHOA#!CITAc#cR/>*iP/n?R'c J ȍ,ո}0rInGИ[ɳLKOm-ea,$̀h:.0fhBƜKπ1iXʨҰ1 ΧtD('$$S:&\ :$/v5[K:)%:'#j=U Ó`TPcz 6ty_ 3PvDQvb^ D0#L|j fͪa;lD=p'o5!=ɬy7曋"׫ϘErg31IN/#˳|;P/ʶxɼM𘏦yAz3y=1'mzjTV)ʆNyxT!6y!(SV@$R;yH|+8RzK#=U )="1=_@]3Pv|yQ2Ӳ SY8(n(:@&4I.N`4VFgvƶ#&+lM̀Dh:/tO#r&R`41cNP㥧̨DLQ%b )0mzD$R';%[$X·<0 }Ml$] U! F2g^0CKG(z1ewJA1W:*TגgYK\:i$^nmE'DN^`ռ;IeWY銕3]Db>ޟsg\j(^Iۇ-"1&Fe[ZZ 2y.r]L4a<,4v[Nt{̷.21ߒYZ[Tl+nHmhzE(f[ w|ZTD9iE1Z\+˵F%S'g.ar36F(:(2hۙ4ZɧRb;8ܪ&\9EF97ڮ!B:&xMĘx+ԨgGDΎ]!5ΡHE+*8J(Sk1ergƢ䴼 4+VlATA;# 42FSŌ(SnFRp#]FycCʒ\qo iW)ar@^tf iLvM=&rZL,[iiCְ2rΌv#(F\;'MK2=Ec'OȴtXcIXHƪE5A(0\ߡ{5OesRi2:1&/#GB&Y&4ӜDRDH?,X~\.OF~`Nv+cl@lf?lAn6 ( )t(1Q6K{$5)sv /=S6`Fyꈕ4 ZCƶRAQ:RZhMJϖ5aS4v*[\l-#+HbƬ+e ȑ3fXh+lĬYCg̚uG#GCa Mڹ3J U Qq,.5N^/s+cl8lQ؂ls#?*kFRPblxDtI"Mk5#sv /Is]^a6Ж"1_Vӕ eT=,I3b3&˨ ǘ$,yd:q2Fs3*"S, 6yHdc$h 2'm; &ˆ9422Mxse{$GYZ21'mse٨4M24m+b3vD oYC$$2Fњ^W'l5'M/#r|hp Z6Сё$1gVӕ)sfD 9<I7bެ3͈LjLq 'AȔ5!&&,5T"7H2&É R`HʚDD}}X$fA*fBKꗘC Y"=6#(t'1m6C{:$5Ϛ9i;5s4&I$HV*Eap&vbV& D(ZBf~wgeUY3 (H:iYh+ĬYMW&̚Q#g@tO$2&V܈YL5cqWIIɄY9He1/g\󬄈YƝfdqۏiC&)NfUy#NByY&H'뼭Zdբ`rNߓ"emY2J19~HcMA!gY{rrKE [imsY 9 hX5\4pN6UKBJ$pGF@ Q,$9>: XhZE1'mA$X&\)vX&)O0BEkz]O4}@$:*N+:Xh+?avޥTcj2=ɚD[B&ѱȘljEC&IηS6#FRe4w fD+#f%wbi٧bH#\2_]q ֨]HZv@1렋S^uD&$:@v&I1*82&y PDrhK&[t="kuU-|Ts!I2"NŪ0$E'뾱bd<ИcTBZ@C:"kmEk̴1"2"S#~bD|{-H%f1mHuJavTsc~sҶFwG p0_.XXX-w9QLu<9z\DJ"Wk;# sҶgG4&YIRDܟ(E뭠`jWD(Z-" Nu G EvV-ڎ$q}YMW&\_FB($rCtO7$R&vyLG!cR|Tj jƙVb֛\VB%PGP X K;G#9kF{+怕iAEl[,Z"OE# )t(16O{$5O9i;Dl\I0蕥KeƒLro$7ZIwzG(Z.Ug>9,Z=(;yz'd;<8P:n1$fj2eȢ~H$gMh 6FC$gz\r&H\%:v*dqZU ?,YPwdgܢHКCV2x. \SM"SG)t(16S{:%5G sv!/=fƥjU_q˾L1Q'.o3`5Z\6-&Vu{>94Z2gEL]#;mGʄy4*B"v!5GL5tf4>.7S4NIT|7 DJ*5ܬQ-l(zfv{ۆ}mJrFlU͙hzofF>&gf} ̬I֌(I3*02&;3MUETbxU'[;9vuG(Z<MUBJfA$D9MhPG#H̛teJvF?HBtO/$&VL͈Șlh7kYf3m=#1̴(aO 3A3XFmjdAR.?+hZg#MI )t(qD$:@&|IgΘdi)]h?CE~(:?I>.1]QYP9k YhoBFCgD)=HǚDc4cN>$qF@FdE Jaj$TF"-+`f׉Df(ڟesVXdfqnV7̢ 5۹4^ܡS㻫7}ԬQ$Axa "Ѵ4aԘwBtO'$&(~Iۺۄ1dLfef9 f[p(@r1[,HIs(NMv DcӘC Xӏg`Dc>`19 pGd`MQȏQXX&s'ԗXp~_6frkr~R-R?Y]~X}{GW "̕*Ns{H YƤXˇU>~pz|wş/o.?7qd;(~P |ZIau[QYŒ<}ʺ lYTns{m&WKdZDtïcrN~~r{ Hdܝv(승32P}5o[@#~ͥ\x}8;Qm]K0! z3'ASuq~$=/)84#ĭUJs()\&L@SwSRg+xT.PB3<@) ߿L}1q#3y+[;I\RO;rT*Sytތƅ>yJA9ϓLhnpgZH?U?ֹQF,u#:U" nd \~0@s `_ZdB`<+kp? @83 QtFD&kLUk4:ߴq =d]&St-܍&Gp37<N,sҹ#Nva*2 )o [sP`׹NKomY|z¯U`B|Y4${ , b{-]G,sSCti-Y^`.˲ھWvD]Q"˲h2rӉQ Xxg`6a1aO:Q5ܛo׮S4H1eZN0mb46mmk79A_$_{;vMOK;e9Z')9dN+beW#ko݆#g:9)e02uיrZ5Bߺ?#'e 30 =Dc4c.g7˵9@AXxl7 1 dQ5F5tZ;I"xLThZ?YŭS?` \uup/Eo <(I;Fx?ܨW~nJ&f pv̅3j]µkWI];DGϹvK ^m"Op uS=0DS, `QW0erq$ǠE@WpSL8?)m~ 0.[r{;`;c9z\ז|YD0!BGLGFo<le[1TP0AS3@SOՀf(50 !:5:aHYvj&9 }qp;օ689)`9mR3fsL\̚'0а0eޑ0d&n能v{ʯm+sn%۷ZֽA"."s^l^L.`˚l61p:݂¼ ͺ2`q: g]xC0c`@W@g@3lg |!{ x0RƓ 6.0Z6kRrp* 1f8 oa(Ne;zÈ xW#qG37h3RlI06$:3ew£D'55R`;U>6A g{joBV/$3/FW? |ph(#9ݼU7PA8ɢX 2!'`BxP X:a(`֠JA4 j$]Wqls p42PN==l_nP  N }u%X8zV4yOsa=,a:S Dxr>SL$-m\$t [Ãff`U0Ac`h  E|*!a` AZm%;~jnWBNۿD,pzgvf*G7hA\V##2~tӼFb?";I`/L!ިЇFC‘>Fܠ4^_St9 *vS|x/hyt?76Z%FI0|aS(ƻz$$@^B 7PJaO#%mޮ4h32`)ܓaoѧ# cGAo;4#X(UC4d$pM x|m9Oh_KіYơhmtցh +ׁRWZS 1 DCj ѥzk`"i斤Al{~x^H3 |(d9z)bf,#/<.9ƮXiw&a(z(r B$bNM%)|L9=DnՔL1*P$}YV c$}rP` @CDAa4{#aifZTn4; 6T9tݗ@2ĺp~ sBAA'$BokCB^_/@Z~h*oa` -!p^iKAnb\bЛCh\$szegü#4,um1,p&" 1oayn!Dl#&2O` J`:"/~}0$O> 쾁&qN72ðAcGAw_0&4 : :^o-܎40dx"OA t@tHS8$Q`NT0 `燄AUEbdAգ(~17^Mg7 L7^['x D-{z'"-.9Y/vhC4v1^!FtZη`>_4 AneϋPϘBf  :%o{.'frl)m1b DCoߛza\baEy4p!QqfrLeE'{?rs)8P 8){)qQgI֯ L}wN9<&On{`q$@ 0yìL^6D!(8%RL ⴈ@A8locrK #2{k,dшʄ4&1Ǒ_(Ð(7rqa: hYPݞ>068E$sEI0aa=Eh,jβOh$8{!t8uck6GW /_TOס'Q'70߃fù)- JR7.Wjq\Ma8h]qމ ovLk:~nd5ɂ`YKafL a,uwWa攉y~ o?KK-&-9IJ?| 0EzCjs?+n Us0I`w.5$8:^.nf]1DܚuMx{0%<5d)SW[} .M-c0ǑO޲˽"ċtGǫp9.ӿ.~7w/?|zw޸|Z|SbeZyxJ; X,u%kmxfd%'>7Ww{D]!3m#3 >:ɼrwlN_[Z$^_Y1O(ZweKK}7w?Wަo ʦ7_=bޕeXqU-Itfв`Ӽao/?~X|M.`\߂ۺ ?_HYO]4W.[,S6nz~17H5 $;w1NEvC6iBB2B;Sx_Yo;d%)U;MgVꅘՔ̊:\άtEcә~f%|`V'8Iy!f%'6+1H)*}!f5sqB8sUtfڷtufq8V94JMe%]k ٠5)9'2qNe{&a`g<˃%zgs+}cY͑NPa˗ZeYjv=J A-"cܯkptoQ.WvZtJS~@KÇ;A[x@- FՖ8A[&XjKT- jik[mj]V[z @-S+mib\"[44J9qz4t- ]jKT4gKCeDmiX)vO94igV[Zz4t~-MQ0\Fsn_}uzxz2FqhpF&n +_|dQة>0nsk?or_R%]+a`U&7y~|Z} ۷?>VyҸG\] Xs&HԾb~LYg-/'9 pG#[p䝸2.8¹kGPJI/.~"!* 1LC$z\hh@%yHdKaJ *F(zڍEAT5@GM#o>1%MǨt 8x(!Q5С FVl30ǜ} cl\2 cTP$<]- X}<1ұLSǹlߐz'z r)D{KHI 2Bre!MRWrY-^HhʈBǜ]]i>.3h03βݍp׭qb!QtBFi< !U<ԘXW@VH2%DPVUȂX(p_M/1'mRH=`f\`"e[p!ɭI^T`9<9i9knhjXG{E*V/ڗhzīN4ͅiab[Q \٥|Ztiǜ]4]rbJnT^]C tXV>r9i$XJ'O y0v\te>q-KjIuN(r&VԈ:3iڋ vH\TӠZb 꼸>F2_'2U7főgՋN~Đhڴ^J19|kkyԐ$mƌJ`F$be^4acNڮ<.tLL`bDTgɋC"MONxJ(g#QU;F'@5'MjFHE[#&j2aR nLa c85G̍5tf$,4vLǦ K XTd`({,Hpɰ=`<TF2 F48z"l`ٯEjmwfM[D0cL˷UL aޫ3F(ڟuMU..M$5=Ƚ)aQ蘏^T`;pdxNnAC7$׃5'bDcN>QX:0M)]'BP؆㚩0]^(4lD?Qa]YX=ˆ"|4jcW6PXZIt3D:$ڟE9i$!BDzrpj)}L YddTYZ_)Z4P,.#a9Q옏@[s DMO1Y=FB@,:@ &JIp>*1&|)Ηp s^Um~ԯQ`=sR/(HÐo_h;@j2a: t9R݄i@F^VmHCg&dT dDNCcFi.wKᛳ+! 26P*-ylc^X>K"+vc#̉DAo(vG&##QjX@:_$wW:ҽji8 5'mOȠǘOKr:lkmuxHEʷ%Z4=Q@cнnؑ+ێtA9bڭ+ݨ@Q{ỲZ f$tdaMsn 4F?$` 3"LXT fw K־u^  Xh[G" *& #a#ﵙQ` }SnDc>;>~ʍ BMv X[QKE D }u%#۫s#Rs97*1"s5&D(t;ns%jW%ySHEkz91" 89 yD"kmŏʔ7"1=DθVu9{8tDf#\Yh+r[CgͿ1ظkrA<ݭW}Vf!XA:WG(:ޓ4w㝓ȿ5 _4vT;~ \IXh'ib|4wV nL*[U9 RoVV>Yd^e s0*1&2/I~L\D_PDg"$_HEnצ,l8FdY##85CH¼ȾI6<6M؄ij50umNy .jto~fw"+CT]0HIӇ0>"1&w\̀r<Ze:,E(Z&2>ʌa@_D!$2 㣂MGg|Ji%|&v3>*1 ݟ:kw 6|3="g{ GW/!te-{D|OK{=yK^h;BEЙiq! 9O/S$|gY6)Lo(IKI2Lq$5Β&rGWYA9T[Kpy5b ,bYeKċ9iJ"1&2J;;qa I첫xLHb(9Q/U#nEvu]D޵ՕxUؘ1ˆqU2܆|5&_TAcNVEJ1&yI[FwIJ O.M! `%[wlQtDD+>1%:Rj@Ej"j梉t|P}H2PTV6Gnwf\MИؠPyD|+kڶīQt5ѶaOxȁ* [f^4c>Ԙ~j-pG9;mdix1W}n?KY0#j_`8n;aOyU@8Ou5BGkȺDEhz{X_@͈'.&|5/0$sv cLޕ˻8ޕe(d[(vFHEX׵G"*%&69=~'nD {iM䘏NxQAU Ȃ >49QHxQ`/Axma Wp2^WȼEHxMhc^UGBMκBGhHD{gh|4o}x bEƫs&&2^4QcNn?rIK!^[1ED U`yWh%i.4'm,  LvD ڗh:F;dx!fΥ6R{w#OƜ fCa &MyO%w/kP ܫQ?jx5Ec{5jjCM` D $[HD-1M^ޣ KYUиY+4vhI?# MsT0cLRK4 R_Eh#5:&pO@UlvRΑ5 /QiK܎I Z&)#bN! T¶DoeMmjDP9Nv5ž(bGS/"hqF֌X9HiVhMƜ}"cR-=.JiPU!+W5GƵәIDL>1ƥW !yȿD:ŏhZow:.,k @bT+u}u%#_H4m]m1"Rl\_R5F@bCFsҶ;&O_&2L&hGdZUvLKJk5RHʢP-1'mҩj4VeVB B #g\1 XhT1[IN5Q]A$WXh;^5] vX핱$-V{!xlj/F^ qWCg&-A"c25*//.XbeT$a,ќ}kEc6=s5^E/y8za X~G2&z9iE4Y<Y[v:`Y7,QtZC9il:IudN$Aw!MOncT&b:%2d< xY č9ikquqAkXu֏tQt&[4ѭkPWhCh|4sh#G?k 9,D9Uиazф9i;Kq9%,Zb$SXpr,#YXh8:͋/;bd,%y?(AHDߓcy){ʋrg̭ {l8L1 I9(P'FVES>l׿PKq5DX;ZLED-Matrix_simple.fzPKBmZfritzing-app-0.9.2b/sketches/core/Loop.fzz000066400000000000000000000546431250202676700205260ustar00rootroot00000000000000PKb8D53CVLoop.fzrH&8j;];f"KVeugUwlL[uu)SJTJӔZۇ:pD@ EMD@~u}}B3r2ߞ//o߿>Oo,/>,_d]FhDF]ʓ"}~9qb|2p}v9|qq2Y_'o&'yw}d'O'*3F*u~s2_Z>WR,Ь2onVk73;gʐKޝd]**8cb~fN~:Yݾp~3ؓIf~wo^rbl}uv;ݷgُ˳'pg:jT{$dZ^\r{6{\e>}g˟&SEٍg?/?^Y.n࿹L__׹D^ߞLVWO'۟_aX~r)d=l}}i޾;s>_:|X/ݍϾ_.x?ݟ D?: l.eQ&3m?,f'?5_p{1uc;{55gwg|y?}r.+OLS :e[]7QU7_uŏϗ7ɯOx& QMJfJɗ'Sg^geʥʟVzqq޽*U?zy63geywv~̉b[c+t{;?w*Q'ݳ&őGw'pWQRMcMӈ3nZUG fY*NZ"l:Pa)uP(1D)g8_C}zyd}qXX3#-$FtP"QaHE+u3'>$fX"G*>j>ßE,$b,Ϩ Q0ιz\ㄸ+xHcXne |T0bv8,]R1y8g*&9LL5Q12k5h^H M;,m(.U?o$t>Al\Հ $" X"0df( aCoT-#"`ό5BAs-H<;H<,a<$ʌKҘKDlGL>4!"'더2Tb_Qjsox_þ0\2*DξΔnK_6O zL͔G"WT7Z@x WXFľJ̔W ?#e_̾kAR^hvx[LLZ  S 1O z˔GHX>%a$LL48˸4a^2!r`;,LYwޔ ) :DI3WG ;*<'31S_) ˿Ϳ /_$(*R_-YFSXXhZM%a;,lT6]2#)*!Qf4I y 7TdJY%*S bafHĬ;H &!1&{&fQ9bfqMuJF"1;ĬNLhXE%u#/މ 5c 9b\^ȰB3r$Zz$ZӲ#4މSQIc#h1PMK-ۢez>)[O1bIeKe5ɲ}+#Q:G u!+Y}%ńg9%Uf]|B)aɂL̬f4-Jf©_cZf2SFpC&Cg 21XZh=ރҝNJܒQy!ç 2QѴjvx>밎Jq{ "ԕ=KP8|aw-{ئ#K4G` Nj`&tW$P0%"{+f:Ϥth,2yHcN>os0Fjz` F2Ii$ $"V7:-"c+GhFźlRRbTf^ltp 4CGbKb\7p nݯ~XO_|ӟN?az:;[Vdd6pz}j6Sg~ݛf!l>_g <_~TL8v~_~lr{v3W/w+,aLE- _]{jرݝNד3tuOW`&w''nye_M.L/y՟:||x?a_oW׿_ɻOWWWOy wܜݿwo+-0$d_kӯ'56v^Mnd1XM ݗbܹM~/ׯ&&WnUױ׷|6Abvی4*MHW9׷"3T+Y)g]q5fJaθ'b/EOXa%.<1ܢ+OGt-?s= t߼m5_sy>8]_}_spw1>ܡ3^A;s(O&>kt{ݷ|b~_ggh4~xȤ \z1ny}~z7z~SLYƈǿ7=>=)~xu/ͨu5 >iqXÞh#gdgS5&y癉x5|ԋLFY2srOu>^-!2/U&\go[o]9~y;R8cLoB@N %w&zu?_&A4͝=A~y7/YEc5Ju}^Dmұ"QmyqD$|68ҌFwovuP2d _FY8/8g§ՙ_\tùO7,<#!ĉ: 0!R,TLr˦ҙoƵ~VʞmeKp)>׌0oZ7GȌ`<_ Qi&l#Rfػh'Z:&<mj4kS<Um{{ޏ. TFy kف2~y<(i.TJ **K-KG}_gx.z7&:ϼ"6q-X۾1v3Go<9)sCsR8t/' 8՜0)'0@jwG_=2kڮڤ'mDI!w~אQ&DfxxF&3yRl)fW3|@*R>&|laran4?~/"! SB``=.GnbI7Ȕ/bC)S#gu~FǭpޮM4J"7V8;&Mw#i5#VG,@*u 4lEFޥi]f<,cdBBކVb dc,UR3Ig[npYhS}i6JM^3GT|ӹ/kmFǠY+74ƄJkiCY-|<=pΘ4Ru)>{ ^2Nj\SLRp*鈭mhEow[s3{b+<#˴ե{epJYmERFRن{43\:"b)|K*218{;welnxeė>5+N&Μ/x!&13 <&a { 3vez42ɻz >cDmD8 a f7wN8 I.9I*Œ\q$ "Cs3t,"?5([:ski9 Tk}Jqyi"@qW1bdžʼnÒu3~t.x=3#=33ȭ# jf (I,>\[T)0K5W c?܌= r^r91F I yL*9DΆB##,379S7S~71c3 ęa]9  +"a zG3KΌGH>ڕY@Y7bə3'fH;H,'gJ}۹'3eGά̔ nhJ}+%3Rg;eegԤYU1Ibg`ȋeg8 'vVᨱ##rٙ藝/av&8X嘊"> Cy/H)3W%v%$n0䥲3S%g*9sᨡ##r{V?зZp 9Sg?Q'rV3Nq~%groYXJDκhADB#ѳ%3ys-~m=KK!]|~~;>>f$bǢ8wq"J:nTIϯ4yl(f[x38agN2IQ*vufG~Bܧ .#zƾf8Rt3| H>9hg(_mSFژ{v0ّ)V_n\Qڰ +~$lUhf=/l} Pvt ȼ檼K4TH3=iyW#r#uCi/׶#n)6hfP[ L')˴Rͧ(?`g-ܩ"7,ᯖ-"2#„c4-/~ kYf ~~~3>u[{TcngL;S=Ghgpm'0Hv"*#yܤ67*ePLLQ%#-Di=h?ցv]R>]HrSic|B?jhE4h13"I2OfDԈU#LȌ yjjDUS#xRR#WkY78b7R e+:1xd+dIaf+i-{88Wr:lƘ\*d 3T\E2RHuJtf;Ivr_6='|G/ ̻!Tb})6J%l;.=V4Ƌʔ8CرNqF:*%Nt[*@:{?aՆIPl%S4QŠ'rcBRAAR(1dEo@b薇JFyϤpdFO2X,jd1Ed=jrG,b1Z#jT!9Q(v}/i`qE?2ڱ+石vGvLZ Eq/c9S]I͘$~jX͇໮kHL*/#N*.(u̷s4vׄun96pnm4wcMỒ1+.F~+nօ# QºBh=lKŬ#FcTaJ] mxdbuau[ w)=òu>f\J{X-,:$硢?zL u>a]h=l@s #16@ѫy)<߃D>l#z ^%7HGO}:q#NavnawdNn0N 3[?ƺ16ČߨĢrgϹXd={ai!4׆&ausaXdwUX=暰(=ln M]v,.w%Xl^7E&#Gz>l4i Mg$uV7W~E&1}E.L]v+.wW=:R{u^qzE^ɸKb+.0wuW=ڮ%>ʮdK˺"+.Q+Bu9W6n7su &VruL\;>+m G]LJjWH{\qj /1h.O梮=8{̅]J|\+N uyWl>=ln.N#Fc3cq|ؘ\\x=ln.Nc.]~+N uWl>8|ͅ_)Kbq)axsXl2({E`Q|e`aD4E'akvs)Xlw1X=rH%>ln.R, }mof׷a?/_-|{ߝ^W~rc>gmowTof9/hR}ltO7^*qRn3ᩭs>3,x9R+gy8wgXƘ%|XF' )3' &y7z4S;⟒Zn!uF)g3ogo7Q}3d):{~WIQ\ mv&ϱ~=&rU NٱRA%9(rǀH%J7xًT#cĶ+z CƎb .VWyƹǹU+| Eޘ:&AHoS#ixϔ",r %)A(rZ788#FrȰ !9ٽIQ,gUz >|4sݠG ?'A#H_eĖ,ja9=UsZ!ӗ:eFe: ; XA<NhcW\y=6L8aGgty& !=1OlK}(|U ?i2I- :RIhyT8b`6b$*|LFlq2$-XSB&Уq!Ǝȧ<L14@z~CgYOJO{Q=;Q=:kOE?]E" ,*|D"& Y_0L<aGWu&̇!qP}z核 `3ϩ׏OieC)uTfN?}bFsmV7P|HQ[5-@A~ JF8( ?M28Czq J%뗂rRe~'k3TgJ8hyom24ClCIguG?C^*?OBͬ<ѳ-aFUH:$3TB ͽ(]I_xqxfCդ<23N54R5I+7+gN \PV~  cYL'+ fjQp@#ԩ0j\ ) @҃h(87'[JiSUU.Kiqg`9A*y,dt ).,왔j9_K͆rO*93S֓i|qA0:u SH&Uy+fӝhaLk|JTgVl\Ǔ粪h"KjgḐD=3C)sXM2E{/=䡕~UmH X#H~1dΔ%S<3&e+/8gR8r/2J|5FաJJ9Lix$ _8ztu v )U@嫜ajϻ`|̗eW5{W`RiZ4ǀ{g׽Đ嫸ʟ ?)'&uF)^^LJ/G^uxm6T)Wr'&J3$J/Nj2C9)=`s0R L v3nQ(Ns]OHqX&ۦw{8ׯrLd te78&FD:^IYWnG˃aja٪ʴL:DZ'ĐLS# %Q3J5G(.=/Z!e(lf`3rR>(pa$rX!6!)oV3Njq-2n\l_R2*uޣ4#Zm StKn߹CY8CR 6 L))k*?af y{n$%vü_=7zč9 )_\eMKQ:~k!T$잍$II݌"u /:#.Bf3KeʬmK3FH;Iџ EZgİPg"3-mm2*,o k[Rq`MK)m;e1CjqKbpKͪBfLmMR͗jqFbnAGJjI5/gL:pgHU |XdAbiծ;My5pe`tUB+#!Q`%npEzHRv H,; IrKz{n+=. 4S_BKj36eh*ώIQ3vR؞r>g4o \N⇕HgSnK"2ekcXNU2OL}.cDF39x{txC)/tĕom: Hľ~hk<걐%xW8v"M.dyKs0Ƅ&3GW7Uh۔d^{E0u./){>lj>-$:l$֖]ReϼMDMq_l63iohP/{q^yԣcl)V3K>W3gY92*HꡒiӲ8!Sk3.VB{Ju4)7GƜJsޤwqX1&UE3ECde9F*-h<Zd1X{ڍ [LȒZRZI>IjGjt!Aύ.i웸qڄTdZ327lFG "ȚK d )-CKZ #$|%AH0RV۞ЌW<3UKt l ㅖDֺBnֺֺÐDJCpzNI6,~oר"[2 Mn1,:m; "9q8%d+5$ UEArVmVDZkS[Q##- 6CgloƊmrNJ y2Ѵђi5dS",lwA$ظ4W%:"hgxى$/:֋OkiKICR~һW-nl[~ l[#8KMuMKA>#ֈȔn[5xn-rxIFW³D %3 ʋ'!eD;_R2NIυFLDڃ^21*P'2Yv'2#IckQfh<% dV}MO at!2b;?sG PQ<rZ4d¹L}0I4RDzFozGK/]T⻩@=t_7Kg.lV 6c<#Ma KŅAM.p(y>}hڨ+B,s|24Ib`6ŽqЪ"X3BA~Ea[Z<,w_lqlmMܰV :ݟWWj꼪׷=狋:XTXy5j~}pv;^z}x_/O_@~}er{v3}'N&ܟl:7`O[#j c*xfМ䙒֪>pkz|>o:Ywεc˧UZ`"fܤ&켥_ͯ_+eNrU[n^f1tzy+5ߞ//2rj߾_P?}o~_n~o&_Mg7ٷ?};8}6߾|u^߽>}}OgwW站;qOt?9b}UfO&XO~X,>фYSw_Odh&D2Çńd2VnIvazw?L~/2L2)b6|9s$0:|e L8PťaY`B&FNowcǟΨSW=7o%b>}wvYN'5w ܹ)3P{~svgS5G~BO.Bvx^^=w- =%[wHz*3Eݻ#|pGXw!'}̩?En*JsNFN}{hB(5ksnjpSu#WQ~D' c9jqNNZX)#)Kmؕȸ` '"gN'()2_-̽yZ+/">qJfVs_ԿU_9>%,cƀD8Hw=NqS(iE~S*OjF8%1L /=3<ó1| oG݋q7W܄V+΀ٳNr_s>( Ps?b/T>-}߲eENέ8uS^SJie$N?"A$rJ?U}>9sڇ?`rÆ 8O1~|a?S#3Z f0)&a  ?TTD{*a~* "]>g'JxD`S82G??% && 0RThts (B 4-\hx"P?aI# Np:ӔTYMO7WA geZ^`6q\ͽ@ݱ7# +|\yzqlAȑ?9LEoVj?,Ź>/C#ENxY H]($"/U?%+hl@}Xi!#Ėm`Lsa0-a8'ycYc!QkHF#S"Eѹ(̙~BA@(0tp/]7 Jr<F%<}<܈7N)9?9͹k{];[ђk7w ]PK^զlB>q&Ө{ H o%qDxq)x1He˜('Ly}٦-4oX/{7`;e|=ʊcM>_q~W +]ohJȒG#7 {[c t Dn SjL,V2d h00Y(64 ѩ SϪSbi`݋1.thBC-m\f p Oǃ( HSw})L1  cp޼kzt`4̖Lީ=y;RMn{i}0H -@}Bb‚&*.ek:N1+М|4 X9YCRqRqBS/J3Tf]q3ÀkOBB3bhcФ3y;+5.P\ @ƻ$0HR=9̀ab#mL 6CR`6 q]ecu842pOH(\wV7@, UⴤWDH} Is@[j 栝L~x h:a` JAT j$]WQ LpQ p(T2mw㞁O7dH1K 5s8ł(hrh06+Ļ0WQ0Y)D;Së{zZUOCɩ4 %ahAä,\T3GZo*`9h `%7(wb-V2o y{'N_3ovvYpv$e82 <)oK$&+8#w" Q 3|(pB!H<! hkt9*Pw5nLDTpxԄ+^V|!p~0L_r")7 YFN(.üyRJSa bF R5 F} } 0B0r$}SrB$!&,pA`: c~Fz[Ѷ鈐cl84m1-"DKުѕi] D7b7.) DWnvT`i:n` ZI pHktēh7EoIG J= `;v)CnD2162qZhx素6t%u)U``C<\٩ S`,kS:$.t:Շ$rqx9V6PyKrE!0e y$2c nN F,:}|Fƻr](@9 IrFpׅcHLV!  @D@p6D_Q 9kߞyc.N=P;bs7M5 `i C^L"֔U1G!'La.:?p\+Ex;(4U9:v Q54 t1 8~ N yѐ'[ -@a >SpHar<#1M;ՠ9uscʦbi?SN _!jp]SKщ#]p39c*"]/H"Rm$|}ޖ(3]Jfca0*R y#avAO(2E&U=:E|s)1q_YU~ ^&6PrBVV=Ť9L/0JLw\ (KP_k@/4zA r^aE$UT4bU n@Hc!GD0v6:͝ƨ@ "S b AQ \H!3 ^ 0ȶ`a EX6r@?zXv`<םVG810 \m$2Dw|/_$Fp5!WpItV{^t.HЇ@fi { q 92x&m|xu= fhZx}}KI1¸KS\b¯8$p«F"A1aC Cfs4E% Dt-~@C0WI! 쿁[֧s0aʀd9a@PA4cp2ݡS@0XmA̺ٷ1FB$)`iFnS"(tФ] 5(~17㛨_xm/Z \s* G0#{jxDnγYb} Ƀhzn FІ Ł"509Gb`,>0S.p{ٜ Va#<(ͻ,"0)2K#S" qbv M$ eE 2\`:碠 — 2  cp! w79Hk>jPnp3x3!U=AA-a[8W)s8 7G"hyae0&hq l}lzZHa Gtz[)oW#vT})7K- aN 8` W@;6)Y>(SlX6ݘJKCd +U+}OKJQndg۲O ],DB~n .zOb 7:"NWbq\U8]q-yԘj 1}b(@Nմ╡PYat?}G>|4PZ[RF^n԰N*TGr#T6Be$$TPy!T8\ p2ށN&~+yt@p݈l-)S8B4of8pI"@W7$Ȁ pbTa6#Ab& kX 0Ninaq*\Cc ( dޖx)>k "nƳ >-JD0Ed`4 HQP68k\uJ?΃d51>ɚ&KddF:`c en,'ϸE+c\ZBBn{t̯÷s,_8<˜o.TGpЗP5G-FJI P:f) pVxp)x y}[q7mGa2Y}b*wQhy!0c1$*$:8Nq2V0Ũ4\$L$p(|{uۧѧAp*EQ" l)EYYu.b.ЀG%uZ+e*nN˓fy/ov{EŴ .1a`#opRr }Jx !L\?D0H``+paNȃ+[X#{㱚c-CM86q[ W\[ßS-gڹ:ۇٷ?˻/[|:[r5_,zA17l=vwηb>t>Ryp׷gW:1qflwۃ}ڒ Kޖs?O8t@ӹ>G;,1ʛTkp\l1"'5Ãj>AF,!h iJ{MC_G?.?GhXOCn__m|_VgRcϧT9S}ho(f7zlTN", 3fz{jۭ ?v*11Jد9Hx0ooVY{ou{j3on9תZ;kajcy&4VZl}6}ec׬$f_f?>:]{p'n-mg8bՖX`צ*Sl~tv̪$FJv'ĥF6*1R)q݁ɩW1R̈́.6-\3K?f];9u&<{ 7 FKwLgG?` ~3~m åEUƫ|p>_%(~Pe//?v,xLg7j1C;)N1g_/3S/+!}\_X}1؟jrsXP/?uw:_.~#pW\ޝ_@ƻ3'i~e=Â$ ]]2,ag?}Ʋ'`E +oBV.9#wXuXz*yv(NDd\9Z@HL,qQ Ʒ5F`ԗ>?ĸ+({ @6|/NA$]Nlۂ|:$ke3Fc{i]btU%cm/,+.;s-MxMn0^i<1q$T☘["܊37.{fn,~a9aeTmlwB3!JZ&o4G__A,L*G] ؒиs kTDh4\Jǩh(æaa!-2]ZSGs4񹨑$h:@r9OsrBv1Y',\s.|ϻ)(c{5a&鑦XH~Xn0^b7˨>cʔaL4b=+NT#J]e<[3EGdif? NCxN|8 W):ZiAjq]f{DMۆTElUv!{ѩt 7fE3}¢ kBS~*E&J,07drhZBe^),֡,%Keuci^63YJQ3Ҕdn&Z}f%z>hudrhڇĊwpV]b{[x|:m֎$VVаn%m8haUvioi۠ɋìgTf.Sz+ )֖F<=迪-FFNŖkmT7}/,{4qkDK4d"c]0yn,> }H_R d]"iId*`W=z2\ *dBCJ#6 ;m(>ug"u):Zi}mq]b{DMۆM^vr+}%H`ikl*)oH6Ӿ!Ys?PK'8DY]CLoop.inoKo0slh )mcArP,Qa7 ߻@RrDߴJK'MH+촲 5J 9*mFcܑnEu,::[ׅ)XKUȳЬBȍ4V&az 2'78uUFwIY̸h_7Ө_0 M&OX*qV-YNTK>LpkVNQe%?..t)AsuKJ夢ƹ~6MI(R;m(oS&rTR:ipdr×1x:|&2mv(s?:b9Yaq q)r~IȼhCqԏ7ς+.?BtxFlrGooF(h|S1q7*"y _\|9r~_ PKb8D53CVLoop.fzPK'8DY]CWLoop.inoPKk"Yfritzing-app-0.9.2b/sketches/core/Melody.fzz000066400000000000000000000271131250202676700210360ustar00rootroot00000000000000PKr5D?e+b$ Melody.fz}ksWlV.>巎eˉlYN>@pI K*=^@$(P=؝~2tvt>xq<=yS(B  aA6ҍlzre7hlTOFNK9=z1d'B Ny58hi|v]5O6Jl X G`9~Zy_L|9-\~3M*z(OG_jWTͼqoj@}4=??0o08kŷM~Gi%orEbC5gjvZ-ȣPȥQd1B =Ldziv*%שT5$m!zkzK}_<1_'{ ZI$\U _brO B#RIoεl a na˓;wo/% S:?M_JR3.|_Gbv>V`\ .Vݜߤ8ɑMdpx~bBe=hd/e!)#>P:,0͟lGG0eōE' dp$K{]E ~=Q7nB|Tr' g(s7!~ˑN^#MT_Cv'uAkoƺϛ쯛6\N \nyĺҮ@X,I:XB;X(e!l$rU^~nHD?x<\WԌO 墟a ^(k 0B[܄—Fuh׹S[q*G?7h磁uɢ}&9\hRu4)NE|OOPi !(۠C (-K!7?E[T)ѧ24jS¯p2)^ (|',OQ%RC L"CGTUȐѹ)5ոG$MIz[")͠U^C̽-tOTQ奨rۨrn* sL_Nj~w~zEqᗃ`\=߽{Wl~[^Ĉb9'˯-]rtrALw|xDMt .&UpRpX笗Mލ*_Deg*7}.=}nn%pv!HI~<(Wgt׸g,{fS3Ϧ`5ݜ'i=g○ΖʥIu\0.J2?̆(bx8_iO5y-Ϊ_| Ӯ' .lv[Yll>,B]jZͣNOjԕ>g_MGlo:d9Ұմ6ĦCQ§ lqp|i jTaДΚD+I#MʊF'޸)nY*ZSn&>|ҥt\;ϛ)N4έض/,&Ք 7/ƸU$u }L|ڞ->U-~ZAA** T`UV~nHYgy<\ސx_y,T |0)|К.X”Z1r5hʯeA5˪v<4d^c2)#(ulul"-a+ V2Z=-_%lOf>oPAħ))(BCe{  V=HOQvUEauP&?y-ħlRA2e7&uu ǥi](eByu (^bl^ Fd5"BҜJpF!W*EaB'&DjL Osd766 =,#we/$<͑Y8GqјF;SrJ|j*BY Ȟ"RQ~2"/?"ZN LGЭn˽MLbUol)~)u:&v>!{-?Vto||D|i:|_[o (gWI"t;sUwaמ@ȃω;01[~8e11מD\:\ջWOfM#czd]FTtdr] &D}(Q\~4ϗEPK+M)yE /FyNx좚/Ƴd!ʪpF<|yOw)^9Hjqqz#ϳql,~LKISe1l~?M,Wڊmg?>5tRDO(|e)t}}}R0~BԬϡy״Lݬi?:6>,_JU釚*zgw?˲ }<>}NEɬvɌXyRxb8\:^/]I7Ɍ%JK|֌.U&]7u iO~r愔]QQk/ _KB"]Tސ.n$xE~L(;PT!++[ tGޡ "8{g,,;"󹹙~PC=WB̈սH{RBt"2z.6msu|D؜_9/#*u {H| ڪw-ߍ&w2X,Яx/`:槃}k9;EjH[C͇U-,)28}䓩7Wy |ܚisA9.UTKGtV+mNMd8:* ǔE|Bl{{IoQX>C}m'M@&__u4~a[x.mycJ"[񘘽FD6/On~//g/M'₲PO@:FimeSumï% oG%җW/QJ,>v K]";y|V5OyČ[xlG}î{șqO;D1 ltp4}Z !|wȧ(]Wu,̾8eNq_Ҏ0=}{M]Ōi͟*IիyxIQƛϯUErCkLD^O'X_ܵ4|5|~M1paH MBiឆ]f?a3{oqp_®`-[u]SuǨkO!3zob.IV?mQ{ڧk[T9Sx[Ǡ+BUtuQ}-u7k>^~OOu`v9ގɤ\o gGn۹~|7{ˣ&hwovG&~O >\xvv]>0W>'.HDdХQ^=\ElY vk~\~W?Ⱦ?~ 쫫 8E?VSbN[6P7xg}&|<9Z-x[}D`3]`WokpR凃_'>[=Ru\Y_܄B8SA4rH:Ҳ'\[DaLe,SgF.Uka;ə&%X+XZRW*0t;XJQ rZ,OKnu(8QRU##Ԋ#:7JDzzȔ2P]˴2(vKZz{\)Wr|.8ai_wFFM"/{QZQQ&PLF5 ԁ+ TTJ2 R9vA<'}'cH+ #]Px=*|[TJwOTB`T/llϪ ^3e#C C[@gb GTdYh\}f1j2Rw2L:ﭐ Se"5`DTB(TCJw|s'ݧjv&〙"ўC}V(,%XnK]tkщwctlt3S#hI:fBIA|r&DQdPobRF#IaP%` TU̲J:nΟ"K *m Ҳ~:@{QDqL]p"ieT`"h{m-kF^Lj)iO7քg0W@A@@xkZ l լ NH*8E $R%#1jLwѫ1K<` eS.ǘ;1jys'm!7i9?dBW$H|°,YDhr_ ^+2e!48/Fj#)f+rh8x⌅$##`RZ|Y]+¸ XTm^ۏQ'@s- JO[l.+Bv,6O0- LW --Y"/r7)`dTKBI.xJý~>ɵo(#nuI@.J&Do2!/C{XZMEBqo+!v@ 3]Mqq.$?QF lӆ1γ쭄xu5DŽIIՔclre^5czpG1]v<z4㥉]c |4 Dm S֘1c dd j~BA CG $dbtE@S,]ph!g)& G%m2 `(# ͢80cd%%|9+@Bfb̻$[+{-[`e INmO;f%㨮 "+Ҧ؂'%/KV VvvYKߵf,]su6LaC,uc V*Yh^1[D"ݐUk9pһdPHY:h’i.9@VÑ5R"3bFPj"& s cQ Ƹ$Y˔Lc{CAM1hʥհXKt P[%FK̃j͟b(\GUCJLS;* xfTY&!)_dCniI&#I˳1s=d;ѩaM:@ *){JiV,ۢjM-E{҅Aޙ^EXAV;z>g2(fNvd{R.Y[&@i8 F?X^j~p$7x$hPI&XGd鐨z 7bExː:ǝҪg 9& lL*98InbJ<2%H)e OȺ89#RMl=ޜ_ z>e郏A;cq+2 I w %'|ZkIװ\xxAr /7f9*gR,eK@] d}nT+m9=" E:MǸ24;`&- QƮA6# cg[0`1-jly|i O5֝+LzQeҙAc8.I;2uhN D 1&sW8OX]|صN+g#xX&HzU688 $l3.%$EKK,P jQR{H" B?bvmFR+R0Ot H ;@aGl HB9T6K*pNVkBQbntK#,a{a"r x 7P~ | ĞBID7Q/[pl^X4e:c3"_⅁N5Ry9!1#(GXvפ&eҌ)g1R$p)xN.ZI1APPۮDoG+7-)牊^ "q?in LbS?-j[? jYQFyX014'rk %2oۼ $+cIXaCTHJo l>tʽKc%U(Oyj3 M'kr8xLQa6 luocrl@f Y| 6܃tPЂ`2wG9lPF Pd=nB0iXlNddﳞ0#8 2qHJ SP hpWZ$"\VLXBH` 0}֝q+UܼT<\%_u%iv,*E|h\ޱcp `ǰ#!~ޱcɎ3BykŰ$`7.$)7]ְaI/1$ٰWX4|M+o UÕxE1ZѰVi0V횞 4;HP,n@zM_# ZH" 9FHƒzs0ss\W$*,\3V_::[p\mpsE[nzVW]Mm)/'0҈Ncf0,brvrҘ–)C4waX*¯QH`3oڵ,ޏi]=E[zRuw._|CU_<ύ|5λtDj 7!ĖG "Ӆ< %{>yׁ/{_mo=O6`+oh};'w7QvݚoV܃oK/j\(F߃ߘȲW2 LQqijG)}2.S q'烓AFzpןCD;6E,;PKr5DX Melody.inoSMo0 Wi DGiu@Eadʆ%Uqt`G=RY;?COB',;tuqMh?v眰ߔ@8t*P2ȯOF/~̚yZa7zKB{PKr5D?e+b$ Melody.fzPKr5DX +Melody.inoPKo-fritzing-app-0.9.2b/sketches/core/MidiDrumKit.fzz000066400000000000000000000734621250202676700217770ustar00rootroot00000000000000PK֛8D]XOp MidiDrumKit.fzr#Ǖ}GwX{G_ZqXݲey|QIM$8$Z-y Nf]*p*,znTV"_o~zx~[>yE~5Y<^-o߼wW?|X^_LnVؿ}_#{ 7==޾؟///ūo&~sǻM_>-_MVwśW2kɟ~eO?^ٿڗÛWi-zx5zJ &!Wr@ʈ|z^>^&Owv,sRB_]xHWz1ׯ/x~xq~IW^|>g}zz7_gY~WL_fļ5]`ɍJ (Y}{w}ÿ߭=ݗtK,/ŏwOb8c~_gs?o.v~^Mnz}X=|X~8j2}n~W'W;o`әx߳/}?_,oZ_䟽WbwxyqztsY_SY /7_7o^erbmwܟ<^/~WWڮb}߬WtOgW8i*ﮧKʏu;hE|w==N^Wq'w{߻s+2׿/gv{mtrY٩添3~bX=<Ů $0vد)JX CV2DgWr|~<TInBFs,[5շ0f#aQ½`ٝf5`0+h|sZ?j{Ԭ_Aadfӵݣd'҉Ā$ ? +d(4`~,TZ$4Qh$[m$wZTƄXBV'[[žSp#& fEanle"p%% 'yXIr5W Y,~Y>|17K]?J#NXOG;_duyɞHE r>kr߾O92S6vي?dbL{!3Cݟ6&,<qo*0 \>]&T/i _@3K^[~oǯt#R_N o%,'o8"z05Nw_gFOm|i$Ktr-{k$p̪|C&d ^gKu$m2ձo<6.eqZi{)4YsW3V%~WV1c(\#ӟZ8%|){ 4I@íS'f {gjx'j/Gw,Ƅ#0݉n2^~oPz*l?kÅ %ZBQJNaD])JVӭߗB˷2We-H2 8] B[-4B 0e WɘJ\o1| }.!T?Q.gPy>8/b8z!+kiehYPU f%AұWDV3vyُ,K 7"9UGy̗tt袒07](p5`nbRm (] Nq;vb~p;%l!zfyY:541z`=:U ak~ڧl HGoyBCz+:ݭBgܓf0O{ S5{□s/c?ZKGt9Dntל:wviz}<[/OkI((q]s0xbO9s??ed`'2w?}ͦ;러yP/ڟWv1/5+f?}|V3N@"wDWh}6O1}ȝ썳}9LM^hA@m= w([)A;q7D6B#+K4*!f]: QAȴds~jd*"jۏQ5$j@ 9P%JBi b7/PwST[Z)UP}s 0]XB-lPH.T %F>>@#&Wj.\U!,zsbmA,s}8?<]}͟"6C 2iٍ#Uw#E堧~gy/xV=)O@uTq7.($,C<O„n nEݸ|-#^Q*dJxW(n{@`I={YܥW{yW&wsvi{)^\I" Vtbw0Q% ǢMM؜i1lGZ҈'{DFlړ}/Ϣik$9՜CDC^щ AX:5=]x?EޔMȒzO)a#fl B'5"Sv="c6>М,PPX;?ό*+y%bx]kt65Ӱrֶ| $2: a}p̿vn!i4]DvtϷ?tmdBEQǃ#"s5 G"P/ ?e]9|{+2w tY݂+!)IcK%b׬b>WH64bB䵷1FqyTWMWc_ROY]^0!JܔDhDt>t&&~+H|w*C<+N䋫O.8oܝ9Nn,1Q()zRy+hiH`#}Ѫ`&{~ΒNNҁzJ6ZKڳfΫAMxvW1AIMikW8D[g͚ĤHS>k_w2x*1y\o^?&(2)AzTth+"'%C%犒<ĔʡDZQY'n(vtvbzK@>p@DI"rI#1.0ME4TKk/ڈ"x]b!ӒW.zz)Þl-Kc& k Z' ZOzT:Vf7OJ72F1Z)rx:%b $*:֣nZtn,rtL K#jtevW"kQ ܟ<} VwOEPNEQښ=IOI|g>6Vئ!lmsNPTl)1őp+Zkc5HҮH)Tw/a-e@5hl\lHc T#'#)jǞ$(jhɥȵ*}YC` e*!%b ڵ(?J.}.YaKil( Z ڔ`P|X"*uQmPan;`Zm46%mRzaQDZn5"Xc8J%M9cэ5{$&Gէ10K l"֣@d:`Gb{OhJ&e` 7L$tT8,(EcعB8la-TD4-Oݵ eGP$GlzԶ#% m[ &]IjK|jMM a{3Mƕ@T6&a<16klDEp[m- f5L p-^qMA2"Z(Z*V5lZ#"@\(dHE)FDzħ ںLH3a[ 2Qudg}M8КZUrfרDSN0,殺$#j1ՁLTC=;*VE.zcMhv@A)HsoV6]xiXeAaqQ[jRvVQ&déD[˜,\xrXg{ȗkve& kjnՕ5[k  ZClw-# k ,!T&UMtl"+'"*ʲ:ܙF$WwaA' >Dl{tV я܈,R2ߊ(E턧 =}J _?d*&QS-ŭX64# = T@{+bFYGGF#P`bS=O#"h-Q]d[*&'eEB Ksĵ?QG߀e,%,GD.0KYlV$-vGYEJycL妻cJjjX@+WN*Њۀ[348-jq$ Yj|֓\t6 ` 0G\*.`MG"j]T]"ԛo+VG;,iPrⅵ(796=6~tY92Xa"j9bW/bܶ[ rT,!rT;YO hݶmeƵ ] DAF7 cݤo0B! U(!ҫ\l<$eLV!RM:k~\ a1DB7ծ(;>X}U;[="j otpSg(-}GK.&@4%c+ xEj\Z$jD IDl{t!=c/*E`'cORp$n` m@HtQ ȤV"(pY. D]'ɪb_JƖ;hpr~}ג,kI kT+S M#-EZO r.5 fxKQCVA4E:ؾVYkcel_QVJBj|y30F>E1#]Vyk(;󌶵 -E@GA.!Ev%l̒1CE?ժ !iE؞e҈+EqX-/xD4u\wn5ؓ5>ra1uǰz`_\^]T ᱝe?L|)!Y Jd/o@t:P/(@ttf[]\ V T!-0Pa%JgO6Nv a2oXԥF9逗xScX(оFx%Q&sijc}->VV?~}ɟy;\fgogw߽;SӧOCw{g/绫^]vq#qopmMv'ś~7b[-W_IY<}>ߓOVUby_,;WyE_^<\brc=[gwד_>+ry*zm׏zt|z~Z-ʯ7/adj~y]_Lܮ_ڃ6ǻo}3yawla2|xmeᯖAVj0x;3jf/O?+>=/jʧi<}rw5/<ۜ/[Og^JWl|3|y]_Ͼ6+?[{|[is_KRN{!OˇD 2~_:*9ha!q<]GM-b]\PLk#j|u f1FlBېYoe]R!µ9ш+!kQm>-ޭAe#@!"œ:o#-$SE : ۶Ǟ(+qۏ\t䲖%[ܧ۟\\䟮V/;k|-s 3s]Vluo_x~ch1<߭~{}};V`8J9b}rG;'m}y8qy.֟=Y<2 Nq^ #GXbv}iUf0y $3!Y Ii.|5շ0F\%r{1DHfOsQgGiE2 93^u_"XO˻1r◻AO0%HQBs`JWN<ݗV1;,?!gLv+NӓpZpIcYQ1GI H1B)c¸GIaJS_I(Å̎uшQ>Wcl8\ndfZ;V%3l)ŋL=SYdXr8j?.]ӣcx#h}7d6>P;K| \"mCs7%QE.m=\m{g>Iܶ;O#wJ?~N<՞q`7s. S}uz$9]#/]y< p55-'uʙުR:^'ix%j>H.}]|V]3IQSv5#sj<|Yn@sIұn1u“5sDDʵC XMθNcF dI`YMz '@TE%F5Q rj %rb Pܚd#S\ OGH3DL颰"1%%L) 4\3~Fs#3.6w|^p+dOI2^J᪣ /')Y+>']68--嶰Q E n0.%̻yG룦8{^h(=68rA! fL$@n=efh `[mf6dQQ"]#%ws8⊀-)uLulٮxGlFlP1$/5-YUxSQ.t-UG^G*k.DbstL8QAܒGW \ mr> ]=Mpr#+֜XȒ[c*`䲑İIk0[u4ul%4v)dT`YmGkjŔ(Ȗ<*InM" B $*X)bx I^@War%ŰN [u4=%)y\|v+so?}!?]>{\+ırSݷX~Xm_|?mZl~o~zx~[> dx{}T_߮½_ϟx;߾7o'MgٻM'V_gӧOCO^f;оif?̊9_?.W_?bݻO-ƈ"9{,Sߔ)~sI>[Gr} P(Dyzw!7^~&}[/Y(޺x_Lϯyx]|]~Ɠ>8.'yfvrW~?_82;6ju+?[ B|L~WS5h9RD##y$Q,@~9~ ]^!#7#[R;ПS3>/oy4Ui>dp?X 1X:Aϗk; zO%d~Јs}A>ۙm;ztK~Spwov^Vqnyahww_]G.sĹYnɝndTJWͷ'[fdZp`fJ.g$GT˺4 zޣ~BǻM_>-݆4Sb8)?_Hy?<V?dwȣ(;ee朎kWn,t%.Xcٜ=9gRT%ݠ{t=ݵq#nbb n; [k+<6kE`aϹzR~fRndMRn:.ƴ©L$WI(|"^EI{pjdcU"S>lmf{ؔ%Ly>ٮo[a3f]ގu{>E8)OfM=|X&!V8u#s1oŔ%<>ZV##|gq U$ò:w DI.͸X~f֠o,5OxKX}{ܾ8+2ēKOtFN Ea?3};(1 ''Ҭ(Hs$A\5A+J Ĥ!G}q) =i{.lV́Tzy@6KKGbh&6I.MQIFZw^ibs=d)-q瓦GMw*i{ԉad{ibS=ǝed$'4 whZj2z܉ *ɨFZܣMqin3F[ÆtѴzܹ ȸ3EZw5Mkǝ f:=4=lӯ=74ybh:2дVsB\~JglOyTP7v(g'f=MA\w烦‡mg&7ۣ MoGr[YiB[f{n=iɨCS[MnG!;G4>,4WDS[Mr:W4=llMn / .d&9MMSƝ5l;o4I=uhj |Թi.aN{hr{ظӞ?d;4I1wij |,&{y3IQ&mg6#'MRMƝQ wNi |yJ_~~ߗǗjw?/+*OՇ7^Ϟ/ˏWyb}G7<~_Vu/r9fw?lV?_6kp4ۙ LS]l5U f W$_D߼#펢n15~~lIu}y2ySyeҎWWW$nea?N;{znvfG]=aw{2PR\O${/v,{b$i-q:/gii:u׏jZ'EZwZPT&~t iț$|ﳠCv:NWj"&4M3դܠ, ICI4-N59G |pZ"g#7Jb$a x吙hR\KJ2[d)1FH8v.$e}NӔ#&I4DuNUȈJr*'/7Fr*sgcOձ3>=ʙt*5GM>58%1 L44jGD.0*)OFE\ EǩAhDHL!9(hIGãVx4 l-'x4,lQYʹpj ,c1nrElO9\q "əĄHmy{lC4Ȧ[z$(|"^  |T"ن>[%)3S bbRH>p}=uLg䣚8} {!}=9$fyqsMi?VVz dؓA*L = ÎWbbr2@zQ 5dOH=]U{q{?\#HrƇiɸ>R1|($HrG%;d\fwڏQGz6֐=a)=#=W;a+x{tGZz2ЎJuą>8#ȴGj H;v22ö v$:磲 v܄ɉʨ;Qx7V=!ivSW Hr<#9z*Ho;#98q?0Gl[I~ЏV?\#Ht· C@A QڵgkRFJdcĊb%Z6eqcFa^ږQZ2G)2VPV[W]|Mkq}.ZfTOhUycE8("YqJ#R+6@h 2jիZAT7烖XJ5UqYUV ]Z% Y"2HR,ܚpթ0dΫS쓁Áվ1 n]ֶ㶏oGX b/j/r̈́K+V_iSIKHl\AW>p=XUkIFHzVSJXAL4I4Q)*( JR:'Uħ",e"VPk]#ECj,3xM6!q"'j|xj0aNX\E&,VfH+D4GܭͺdZˊFF5oӛ'Cox01:F6yHJRQɶzz ;xRk $őaMhƼ Ո;@u +qV8/,i,Z[Yy||Y>?LqQ vH+@XKhf`)nA^0'9+?us{=^\ޛ~q{ {\#'ٻys+ó|9k`ֆwp6y,wܟFZ9eGi!5;{XowMNӲJm}07)SNe:qYD ?E=D ݇Q[mϣ1_+)Mqv/.p[}(Sf(7\=;,1(z4Ci1-н3YQxuM.R."z-g"m6! "Й%b!gC}HOQl~{-gEZ  ,yNU<.:tGH3>L*cF[DNE HY~ %ߴ,H ~cCGOeGeLeŰb>@Ej/SHSQ.բX&_^CĄё++X&LHh&?H,}S)@/hzo{䆿'\VM}Mûy"wvzrÉ'}*vV Ek#a cHOۮ۟=o?i!{dϒ>GD+W{J"}$//G}@}u}%7moϹ~UD+XNJ2>U:?_Db"ȜZ^T@tTZ>Hh0PG1ͤJЖE=BFYrK!(@JOrѱPo@ʞtVz N\T7%H|=Oc[kLa\XSS}ೄ1-E@ݙ%QH+WD\}BBĕ2W˦54hs G9#$n"pkpaq>!p@d0aEr0qoWDrZ'w/ްЇ F VyP.UaG[OJr0}8zP[Xȵ]Uv̶θxQ'Xǹdފ=1E CMR$|n=jIπxV [*Nh+I靖0.fjmkoR,\`mr,[7cYRZ>u=l=  ZVMx [uj4:/}HB*k ew}(~\α虍)Ec&lM>uYwdr?('Mn*u׃UG\Nv uqq+, cdmqm08F\s]@tt5{v⼣ ٥cxw0~@p?g \RrY&@p:rWE&FwvM#}-7|&7hBdlgiҲNKPSԓf:I\u4>5 pE6(&+V=Z*%&}A;ey9QzQtحэDL+ [u4>5 pe\0oI4噚զ4 \-yG"CKN&#qM+,L-a4G1e:Gz&@2ԝpmEIF啝A qNgfH÷=spp؍֟TGEl'!p:jjTL:8 m*|K Κf1NlaNjฆфp{@3 ]k9KPzf [x|&nCnr3ɭ(,`z]һYuFdwKC׷܄,m?I p[rrٮHփUG\JV_g82]6uR-)]twiaʭ :(,HSB.dd^:̪ /@fթ!2#qɬ8qd49y"e+QmƘd-MAig1}`(QʢYSf|awRY;֣\lLdD&@LX'F#[QsWM^Ro]BM)M~͖&trkMۭ&VM8jVP3I [rN7@AI᪣ &8E渲.AZ=2U%5Ma4@1 Њ{8y`D9)4䎽eOIl3[&@n%:235rɍ]/$/D~{Zηl&N M6{LE7EVZ䢙MVMpf2CMDf"1imH.,FA@ woo+va܈(A[Q1ՑƵ%.q} ˥澕1L *$WMx%ܷ ʼnN(NF8QeuH) i ߒȬ4rkMͮ؜&IQ\ZR岽p4…W@h 8v0Nwq*2NWK'[E#wֳ%Mge|9pɈdcu?>iQb]p,a^Fણ .%Atdx+KY! e:~Ỵ-wrH8PI±Y9M|,*@o}*ex4  $pфW`Ld+D*طP;]8x|m5&N. #[ p%wG)Xg"@oWpUFpdn+ Pܣ-4D-ҺiDXlk9O[ԕvɸBH׃UG^S!W_ v?umɭSY44)ewhBIdlg8KYZΒ>)N2VMx)xہ7 Fv$R##ͦ7`[bIlE` ibJ @oS>䲡MlhkZ}j:5 J[ʪ%TH~}z|B=W Ɉdj#GK ۑ`4('g"Z&p=0\u426tBo<25ȫ:9*|H0w$[J7L5&./ۭ(_"$T}))| `JWMx57\}j:9 SK m# 6aVPrX;0]܇rɨdc $-3p%w0G5T7\2AG⪣ %dd|ˋ#2\p#֑oݰ*Wh{أc7vf\ J/8.8ʎ&k9K[zՕ8D /#q %qӝ`qy^asT~KM9/iM07ᱝr٨ -vЕi"x䖞(E"&@m%:2Upt&:2uyjIFT \r:'Gp|w9{HBFB%WJ3,IzQN.#&pU:JN uRÄFuM"xf72L -DBфq"Q#B!f%\ʊ24 vp1 4OUlhȅh 8:dBc6Pk!ADCӊ  nvůE ?~ɟy;l:}n?!f_gV׳٧O'Ϸ?ϟ>]3w}~!zuYdv/o~/F1' x(qXO?)/<iSڑ|Mք?ڭůL`j=ݕx5g=s_׋},.>/?>^aߤl(} xciyܕrwϗqHw7LnkMSoF\~_ƾWH!g_gB`D4{G3eÔ!"=+Aď)+k.l`>xyoxZ=O$}N(LW$Q)^dc ^ ynbtqIT#-ROW.X^c+fHjb"W"5uc]}R >x_?!.Nk V> ;˴bN]Gϳ31<[ bQc"K(+S'WG/oĸ,VJ>|N\O~%!܁vI|N 3W,?amx+z'8vV^#dfwDXգ忋H8-_eAݛ)sU}aj%%J!{)&tx@X_+vRDU_HD[_le%DRrHū5qm:v^w֬omgmƮ/Z/vb)fP\~_$YTXAw}jӪyo܂Z?巟m(6゙N2sgztvHee/b^M3eZ?,描w˫ *f7w_iGn䆩ٷ녵wQ}wwWlUf5<ڪ>Qzcꟓ;:%f"\yS{K{{a=Ӎ]uи_E놨z`gjձ/GL+Y3m)bN!_ Gov?=.,~d>!Ƿ;Gct>iq}ͻo&?>Lnյnqp6Uak:ϸi6+\hfZ)qA_`-S{+>Ԕv{ܧ4nKc&J|b 6; vuݝ*wB5gi<(ktv >y%|IYX~Ni5'-:bAq= 'P!O]YxF9形BY3 JaKVMB(5<ð E3>Z--_Y,zL!zOpNow|՟2Dnp>@Ҟ:~::)S:~+G~xӃAD(H^ {z wZfzg(϶ZޕھlvTىއKŶo%{A{ҝztu_kjߕl6.?m&&f mltIZS^w$w{[n^lU-Ajo o}܉hB5ȔN %*=R_OfΖK/w{%vjj1 Ս~Đ ܙW~5frw!u$nO0Y«IPD^ '_SdSe<|q)vcBڳOȅxt dOI19u:ngLBy 8q+^%(dyD\)H#C1uFgԗ,7KZ Vd!zB?%d2%'>i,;}]JQ~j4$Yuj~j_(E8C= Rp J3=M>\Rm}DF;!2XU#C`IS4B1΢ޮi7זNk~3*j<ה9b{#="\k+Y@Yd'Yx_4\<Ƃ c d +4} !;Z>\Ob= WMx;MI^@Pͪ@u#9u|ÿKEk$c0؊ 6 xvym=YZ;@ͷMe* hjQ )㋩FKo*6*l{pV`ܔ6J{޹޽s&1lRD =&@NX'pwa%)Ю-wZaMoJ"f$pu5"n!JQҼP_ US~ru;K\pw]FSs>ݿw9 9}6鼣22$\DW/[S@(ڎ=MAWWM*޺BT]DfܨtM:F;GIsql/;HA"n= /\܆",/5m@)xnN `*hxp\$a.r8wdx4;qƪUʜikpAMu*Apd[W)&)lytXyiX)$geX>+ qM0M1>u PZpJOC֔&:\3NEe+6{W+H_KvB Ł0#Dld԰=ޑYz\,Z; :)*Y*|3 P lCqR4K+lcw8v e=/1E dJ<\ e5pm eUL\]h ԭ#Q~=8V@ח|82 ƛjFּfb@ 2vT0``>>Pm c$d~L;I[u4"Ss>}T}WlLF#E='}2 B#^ ذO$Ѻl-ɕrVŸ&ҳZ,@hVEQ(0pc yE@$"r CpY*{Yœ 7&43 փ!Szxڧ\6/ah ܙ$5p::Va5[(L[\d'oiMF+7hVHr\LzKuQb vi:WMp-&!vn+}Cɷ'!MgRG#aMog jLT -"ŕ$ C=q6NokZ#cD0E&GfPLFHd@+%2GvδLAmطZh84S(1MR.>ei(r,8-&X&UFNHlZ‹0&I\v elK^ >;\7ճWpݘǟhW. AE-8*q bΊخZ(N O*J Ԝ4rJ.y-#7ځbJC$=g 0.NU=hI%BM eLI@ .(SL.1ZRnIx /$pbb֭-F8Һ 2Tp2i{ܗp9 ()pO1l;5P\N[um2 CQèk:b-=s\j3 \@z\MzTKWYn&ep|oeYum +@[u4*T!&"ZSʚ:idiq(MTQ D0MFi}2b;=v\ %}'kpG%T\35$1\\I.K{UG\H*˰rS7ƛ--@[Rh8$G(h&Cm4WzQ4akF6VMxԸGqQMT7 oݦlZhϺi_(ž[w1g{ȣ#4ώ!Av }Z,c{MSABACKTI"N5A/pE_i!\LqE rNCScORF٣:plWק|+RبIWL׉RJ-(#C;GCFMS5F QL|K (#ZeQy(jhm4ĤY]/CՉG #hԺF8@ks Phņ8G:`iXh?d@F-ulNb8*2]:L'\}c8=ߎ>5p} &;13`žs}c ?ZhBDsEdD'X+&m4(#P#.56~kȰH]Eݪ $][C覠dF @%=6$3mt,EFhȈr \PsI詒ԒWvP]Cdu e6n PK8DDVMidiDrumKit.inoXmo7 _A`@{n%f6;Ab4]@ ɶttq5}/}qCH|􈢨4T \Op=%︶Nr!X̛JZҔkȍcZ܀Yn 0;`,L#f *8hp* [n)7n!(2s.F0:BB+PM#$4,O O-пQE+!AX| јXS%W!ȋsIy _nq+ZA!|iJGhn7AMgFـv(}CO?+QI[hx9X4yG> %f1Q|i4p aHCQs[+V)%ؽNe59L>!lāRZFiΫ^F " #*CiA"/Zeȇ.3.ƄhfП(\[Lf/ a\ul0eK62 zCpӜ9 bFH]|FXe`*RUo;Rip6BwYCyWlA_Ѵ2^c|JрY>Eǚ-r<*iyT~JkhdXZ; Ϲ^ս!݌1NGag]i$A=| ; Y+c̴z e9/Kg WqEYCs]謑BIEˆ*!fjqLUꏅUÕ[:}?{0x{v}1.ţFI`hq`e_ҷ Gہ+y~?=y>eܟ,,3ݟ3ۓ,3s{k!las,@ /'s+d[6?8fGr4דCW{u~{ާՅJJC{}2*6]N'yx4qu\]~|aw7y˂E}z_^CE/zۇO|?<=}7>|rwfm۵4olt;OFO?e<~|xëMJ//O _\}l\}_%TdWvXoS+jBWWFk Od^KHyxq0ŇOt:LX~x}5=;sb!llhܳXS5Xפ}:FKj bH*3 y *EB)Zu&eYhJ$76KK?^>{wWn,F 6ӦUb1٬uj=256٭b0n]TS}˵\0K!rcĻ wǻnnz,ŻYNm֫E6IWŻ86T@Pj⼾>?ycX5ly0Bۙ:^xWT)Fx"05v1 鞭 i6f-nnUFiO$l1]3BB-v{ȋ<-D^."E[oKFQlMFQ#q҆צ6x ;pFUGD?"t>]ݯ. [->γ!R?m296x]@cy@#M9a@ވJ#jd z,9 T:x 2 487N/?ón|$fh-__@<- ty{ iL&-ѥy3u)~ssOH?Ɨ֍G!bJ!pOsI8=R[P~I8^|;kܷ\* (Jܓ%3a-w' ne$3^9X %ZB,%e4ٌ 9m@Isݿ|AbhB\f$enڊXe01rleANaI-AwҨ " nyh$UivQMu.C</~vrJ;uS+O;Œ'xe; Y坔hew֬ZNQs}}ީl)WVoӚ5 \ar'3%E;޹h{&y/:ޙR<*w@>@g $K F::Rw.!s,Zxrc:h+(x'Uj5Ɍ睴w;kśM< !GPCn~JuȖ&RS%< 泳;|二xZ;." S%Y=M#KM逤.x6F s 9d >tyM<8(Q̟TDC%Pdq{Rv!׹'5QA8aIה ٹ~-_5|7hѱbσt:yn:#r)Y\!,$SrqVǩ:ƹԔB9P4[GtrبX P΁; sk7EH 4 ðtY'?ND+G paG$Ewf;ϭ=g5{Cӊ>2V 6aW]JnCǂ!ZO͒`2wՓZ/ :^8 &䎞BĦ\KEw&Nh-~X%c[qD-12a7[VmzRlJUf{v xn¡Ԕ ,WyѦG{\G!w=:VW[|fR?ōr0sXb`F$x\E)TЩ&4=݂5u4i8OlӯG]=2ҹTvqFTfVI1եjo:~+NiRXlCzt,y8MnNbAnOg4 Vf6ZպбƜlHGꊶcGbZN ~31p2*X"ƺ)Ǝ4>>3pIX&;+E$&]a[T +/kn,NiŎ#ѯgČ ;^8KD:L- EB ዛ(a,`۟1zu8CQmt9GZ3J !Ij6NjJ[-qō8Lvu;nnG6oukrັ9awQjuBل~uNqav.V)X=+;v+%))G+'rhdlWDtyHaMG+Ŀ@(1f,͕Q\k~M)!7WDU&jOߞߏg~x>^?on&=xBrz!wwY_WpDagϯL;)8{{Sމz5<kbD8QiE^s kԢn "!nff4X .ulXZ:mf11oZ,-#i):ΟV۶YH s@Ă"vᓭu(xQ=Am6vkpmnxiP՜#Y_&^VEtZ2m}bk80u֞qT<~cJ =;| }&ALBƙ9sS\BQ/6>{q&vǹcGs!](GL1 1͈_7ZVtQغ" I==b(v,L-3$8|$}f:]I;8|Q$r&`ȹDǐsǯ]DHHL19({䠍aUJ?0 de U쎽8ڠ8%&Aǵ>mVq2^ $NuA1\2#f GN6X+$z2Jq}.&E +{s"EڄiZ3R, 0/H ̘cYĕr# hGɘ펙m6g S$#m"ŏȸA182;+9ⅎ&;5Q(e}% dfr-70ybU!H^=iL%.HBFTc6U\\'N|īJБǑ.V]ѝV)E mH@0+e OĻ?ӛ~~vxz3}{t|ՇK_}5s erM;lwm5czYw4D S>vG9 ;9X(])FwuB%8aj҃'cD&ۚ,9f=0TW K}͸̰OŪL82IMXQ<"e*MǪL붶@Bڠ I)k2eD֓mL8}&8ix&R:o҇<6v7^ׁw{&Wq¥/wxjaX-:>)щ//_Y5^;խ8bt&7:Gۭ8뻵ywzzoMF|#{ >Xԉ&>6!agX¤2GB .4RN::q v;lR)$5 )pn.P{JKy>绫S\:{{ȯ4Y>'ftzs.;FjƯKwlҞku)Ҡftzoz.;"ip8=d=O1dIԄ`J`ZUqIuDqK캙EwO[hDuīFqƿM5 fcZD+MpM$~ s{kZ0C#&>NVbAF\rݥȀiNbh%‚瑉DO]y҄'䓵\h#en,#v{Qhs_0"wf=c i %?oKse51ך_Snce9vo/7&eeKlށM8 !Ok0tsrqcp i+DR`q, '{f0zVu|x>Ӄs_zwWPnv{>A0h W.+bq!%jMLdaXn*o^5h|ӻ?]~lWsL-K4fACfV0S<_%8Zc窤s^>??M{/NE& 7=\;|f`_7{?{7_p/~~p}v>pӧO><]>NF+8MC0*,V6ތO뇫qy6zT%$!}ϟL?~%{|?\Ay28I^\m6#f=P>3>?~NxI%[↓agv.*{ zgdb p+_ݐ:z9{n\{!mj:\]~|rz+PэK!w c^l2u6z V$+Elo+?{7i*7Ux L.I }2p8%mܵu>"n<1Me"Dё;/ᮤZ3(ND9ETz醢4#KrBN!Zf9nvnvp(5|-MƗVh ^[-F~ߧ̾RWRBfv+.ԉHhwtNYr B Q&\*̽˷<ۙ ߸;Dʵ^@W(UhzDf OkZIgƕ}a:_Шzq=d]ڋQݯ kJq+nB#`a )x@*p G^/~308#wuJuZD~VnY"[;+|/~5|9*Y\yhS&qB%k}['޻)FDx@&`I—R% J(OƧ¶ %zA[@9©#"{/$(`W PJ}4^dB(dqz>Ѐ;)!~k:Wo)) Z WQ|xA/h "-3&vڍ>id! ef|7Y׋D ̂\I5UX** U³i?A 2p+Ml$& t]{3lH@ n<yӗ}!Gr0@KQ!_;~pYĹ/{ȩW:Ћϗ2^ĀE/DD%Fx*&x$|G.ahƷP[a z3Hu(DzyC }]kTau^ )a"58Ŕ9#-T2. M YE xEHD [nD^p#^;&Ц nTn];^gTvĵ.\;]>tjS4!ʄ5`bUr/X,0`X VG_A,I E@WpS m0F$b3-4oX/{7`A2Q eٵ&/.n:A` `,x42hI), SJL,V0` h0@||ҊAh 0$\tjt_ռN@:@С 9K;lDvp 0Oԫ2>D5SN, aOas /|k஽ytt`_ef ^ScގTSu0w C '/ d vpY.Z3q] 䫤GسBK)88!`gAGg a'R!|!{ xDA14,&4 cf˂Sx7҈_ C1 p , dt#&wSCi XgPg(hI@06uvmq𦊡ǀ$Eا":&DG ழ݀=ٟ+b h1 QC? @@Qxnޫ~b+Bɢ!2ipKACK@ f DFR*uhj0<`r4hKD@lk }! C'uGvm%G(hRh0rQ]SB]G^ ҃!d ^@`H19ݠV$4 #h˃j`H vBcF:A{ ,`OX$DT1K(J{KnwުUaA0oD}x[njϜe` G7H@\V#RZW/ V!"qF?O(DE‘>FT$^߂5 P]Q,rC aJ & ZL80P:P ]q (0Ч@cAt[*.Čhg} 0B0r$Ce>)b9!xDCF*@4(8 gTs{ԯw ڶ"r DKǧHR^i z)nX 8 hxHMa z,h?ZO*?#iq]OUa1bLC?ì$Ry1D K1ċ5+xXR[* 9;!' 7n}\!Biea{@wHK*d9B 9a ~,:?p+EOh*;(k1.$A @IE( yBhE@hޢ $Z03 `&1#9D൫=wTԍMa` rbi?"̗Z:_bx?2'ܣ 7ШE邈xQD*EKȿ.2 BCd0c+ ;G׎N071]bLK g3zk{7 le@Qm/Z s* [0-:5b<"7q;KL[ o34 k t ]06Y/6=c~/5`RхZ9dsB@Ua#(ټ/ B 2!c QL84% w.h'f؜i6bEo?za\A60"<8吨L5#i hC);(3((*Pa:N8E&Q "i$A of%|{ɧ뷈:+5Tyˆb*WI#*EtLN(8lyocr̓/xʣA(LAb:(B30r_qQ2"8?vc. EEdAqj|`2u~q `H0">."#RF]bN̋ڊ KT4eaY hZ*6ډڕ69{*廢&-|ݎAޭ`:hpG@AL˜vlP0c8܊n"~ֺt!%u2PdFHA ,L*׮\p9_5\AV)hPhBg4VaNށ 0 Hr~VZqGh3ԌFc `8?h6NHZ4 11A2d'@SuTaK {(C`v`MIz q."i ȡeh 0Z8"]D}. [±JOG?5`'hv l豏#٨G뷈N vNݷϑrԲĀpV? $,t%MAf`hܼdO 5/  /63d,3cyW܌X߃RdK)+l$ B,Zpc|#EԱB"Wb;*SԮD!6TJ /-š>Z D**s* тP˂P`K BPE1RH3d Ԟz:DPF,fhL(77` 1F@OHp =D#7nH2`oxlGNRš(\#)v@qGhjp5!"b&,0+ΓyW;て0ko(,F`*wQhy&0b1$*$:8q2V0 \$L8%p)u0ۧAPLƢ(BX cƢ,>.!'8?c {Xm/ք>0CI'`&4mFXpPpR?`~5V"^uՙ!>;]2,seK7t zqR0~07"}pp58qBHpt2̫,,ӘL +I}Ci>}Rʬmrqf]ܒ &K g4_l\s'eQ 7O||cf;U\gj:[C&x|QK%,f~ŵ9FF8E ~On&-.VU蟰^ty=F9C:]7STuV̟.g7Ow;=Q0Q:/X"?CЏ>5kv+a|c܁x˧8&Y{a 17'9~><N@cj:NOu2O>f6ryD8=0uudޯcxGr;s"8:'pQ{гIzy?B8tB-:&l{Y?q4L0V-]@!-ȉ؏sPZ{wWȼu=3x\:1/Mj&CiҾik4)@ڹiޣgk5iρ&3֤#!</|,]Βa Im Ӯ9bCw-T<`,,Q<0uI5;kO̘Nr<}p/됵v!PKr5DIﭺ;- Mood-Light.fzPK; <fritzing-app-0.9.2b/sketches/core/Op-amp.fzz000066400000000000000000000471161250202676700207430ustar00rootroot00000000000000PK8D+lL Op-amp.fzrH.wv1_2{*n3Yeu󧌢(S!׵}}}p ^$@ u6Hs="^ǻd:߿:9 ~k_v&g$3͘ŕ<]q//4|papu߼ݏޝތghv;|uktֿ_Gv0ݼ:S1RYf8:WRU/PoG/&Iny)C( .+Egl@.}sV~pi=Y't7:;ߦNlg7Wo~qɴmn5 ERါP1=dRt_ ?,ѹ߹^LK˳Edv/Wwֹ.}N3neF:or]6<p;[2=:hOSHw54>?K:@fb񂟝z3y?NUo~~=렗\/e>j!?^c4_9? o~|u&$w/ztn{Of`<>yKg,k4T O~hͿ7]nz8&:_L"Xtj}r߲[?Rxg>2q7}ZY8᷷k XPvi|M֝c3!C0};Q2/ dy4l8< JĆ^Z.i r1kƋn\,Nqf~8pjų:ő''GIqB_>2,#Ȧlk5\K*f~{W4ޤX[N%ѽzI)-u"/QEh:%Xi㇇μ 3L!3ߣve&2c!j:쁛fq:\{C.\h%R i#$~[)ug{!\!oGPx*c9RqM2IKZ!춣d,JPo:nj[齻z77klq׿ξ_oM_|鷯~7}_zo~}z  'f/z>dx6\~77[Azd4eK8ny Ľ~~^~tvؙ}zȯ=wnGf4vT/:aäeY=h/oW~zҹr]^zśxt?"2} B~<~]'ףl<|,>_gWë|Yv<;r{%\|t'ͻ}gv3vwNǎs;oo;wj{w;ctw]n:Ɲw1_'nLc½_w5~Ywǖ\a+nܹ:n{wt<:^áoֽ߰mg:y7?t.}F;cxCm/;퍿~ ]ލ$yn;7Y ~4{?ˆz7C7G~=ݠ_|:e^%* ˆt_=G~`Gl!%pg*q&Smmf=@h854n+j"Byr&3Y(GxT5(ZAAS+ 5UJ6 (%OBjt᫳#R!%y$*Kͻ$3r*{xa,4r.yt"NxM:yS^"I 2_FO$tO3u)d]k}_WQ)UMR5OMJ3 (fY4N` )@B-naIzp>)Vz6cǙ( =aJ}#es'|:b*ww.,2c["籯@Ea̓Eޮ2x)R^>úл:@)' Z4֢Q19ٌmxM*b4-3U?ad}KB1<Khzs+KhuZ-lGnt4p,rhM΄4S)q%=s >L6$<,Ia OOP~f=M5j 1w~8 ] S8u[-3&:]د{c ~icI 68x=jJr25+#vO7 5mbmk|ئ"S~a4+O0ٝ~}Q."Df<xYq+mPwyu[8g4~Nѓ9G`xH| Km鎍HݏcW-9 8=5)RcwdMڧ2#JfEBe,: ,SuT.UKFooں:sWpwJ^&݃윷L|FcZn%C:3)f 6d2f[PT>~QђѮAUUH=~UO:l,]YEq8[sPzGL,,4cjqJ֯tl\^s(_Z" \ԊmFV~YB[4'qWcahRK@lƅ"a>aa4QbcZĕ)s(YԦ&ϖ&ܑ4}ѮDa+AOʘ4F]s%\]9TCejuyH"ɉCMۍ%[&!%!%~ⳏx喹GqAO볫˯l4ߞIYx\d~mYd,a2T+l|u#i֌ kwsՙ'pӾ8ѭ;3~cw?vֹ;9_7hiY⟐K\ :ðzpm.{ث@֝QWZ=J57?}eɪJh藽W'*U,핷0|!ZFJ|ӡҌ94^"k8f+d/Guwv)Kn0ٽ6!iGJkMemSDx}BK$SC>E=8>>-Q`Zǧ!^5hQm0wnt?Nxwz3^E~6?&ه Hp2Թ _ӳ;quA0}_N`Z}*Ka'Uڳ.ue@& "e@r'k2bqEW̵%Mesi~{"@6%m]d.i\$"4@6@s]q$XDnhr mZ7`6Y9FV8:IuɋfiD'G*SEO(zč)%DIt-n@;|bLm V=cZnHh5GZF yv-M$ϦhV ېP2 ^j$KHwVY"jTLu9L>}&kBgQRN4yĭA$ѷ$e{s|8InUpaG 4c\l]1 M-<&਍xrKy**#A+2m]R&8y\A'%`$jV)<6X^V-ERJ&~mKsܪ}IsTI\-nB{}b-oTrDjm[MV#A6h  w`FeTwEL ufGKJ*7\ɦՉ$mB#>-!.5[ё#Q5ܟ5+X=7qp׷M\cڔ|r<aRi*{4DƢĐTX|wFH\H#ʢ1JdhYDaM拺?Xo*KA*)ۈby44Vՙ!LR|JzO o\l0?WFҲh&y0xe~,I7: if#iwϜ+7$̈́OJJ3ʼs᝛*'kz3_mHmM!Mx>QcYjf)$-)5 *NLwRHEF bvvs•n[ABPJ?y44)XR k^ȸ_}3ӄ(z~:ĴxR1J R'6JcpS3Pdaqֵ>}3e4ZBrOVMTڀ`ޤʘG&+./~߿c. D⤃ggK/yإ9/ h]|\,TqfMkܵ[d^rdg"EG2TNFɈnx|fOxKڨ@@M'M[s_EL[>J|[.ʳ)I$+$lZ*vwSZ,͢&Sʄh^rh<_0ߤH.&RC}Y"v {Lo<1[|x$R0i@ɳ&n$CgE%-88۪hl Lq_ Y w#ItRQ@cGH 1{5F#k HITm~Xm5H8ք+XZ k9:΋ei+WU)Uzk.ʧJO; T_kɪhZJ=eZJfH6|6 cm\R&4y9FD`DRmU4S70u!ŨP[BC$㖆e}8{=I H-fͱpfԍ.9_\ޢ~D٢DiI7mk3I,IiO[ N6B| u ~YYKS-B|l:T3ƧFJ6$Ո"ϵ> ?$#ARy\ !ZÛytX@2f!dH X*.lJ$ζoOXIőȳkMF"muG*Ba~x;p׿^G #̵ܺ}* dpys߿:0ݜuo }U@F[7]7ͬ^eX&5pVX~zv}N/hF /ͮ˿ %_ כ?}әoxuhF{oE狛EÇƓwh0{DwQ݌rvbcnpw:bt_uHFΡo>>'O﮻?w2w|w"|nt{!t qϾ\6#nxdI)\=uʙ|ŭpڡ[{z\4!#; Gx]u 1uj.]kz4#q;^^Ow*Z o݈ vD$=w̷tNYrJ?I Ǯ /s/=/w OvED7 odfr*޽U_zysp ~3γN C kwO>gA7d8 P/~u p 難Ÿ7|{a S@*p |P/KD.DI:cSJl|'NgƟE r[o~ jgN -T-hy(Y8u#`gL~Ϗv ɤ Ag)TU9۸wEh@*J݈07(o6~4%Nva ޸CHnO[POűs+ E[B( qz m35bwlG7 wWAxМu l1ű{݈]QvHr|aЌMֽEeDfAyIMI\5UXUU,{y;Ʒok/4p]ơbvތ8G/ЯO;p[}!Gr0@aQaO ymzԫ ^?x!vKޗXᥪ#q{PVz8h|%q0.7\gb @N@AXX9oD%EG1z^ )a"Յw[LpPP}@4tKDfA) onx Ow5܀6pbpvc~ZVv}k>qtkЕ횰ڔM_gB7`bUr/X< a8/.ex'a]MQp.4m .xӠ?cXZ(+7y{_4dtAєA٣%F=l{[a t Dn S*L,V2d h0Q(棐4ѩ CEFo򋱙<c]H%6"}[p;'֫2>D1Q3V RaDu7N wa>tazSv4H"WVux0Sn jx p KBEҽUU@k@=0RU4i`Haec3|kUw '1t&!aVORy1D K1ċ5+xXR[ݜ* -:1b%vW 0n gFГed'.EͳI#!-t|-lp/ &wT@,{A"!VP0hvnCkCQ[||]dJUrv!Rw^θ-s= {`eHMp>IG J= `;v)CnD2162qZh8s^P:: *pC0!Vٹ C`,kS:$.t:Շ$r8<X-:?{JHض$g9V䬊!0ey$l+0.՜_ Xt{Fƫr]( rh@ !)0X8@Cm @D@p6D'(+ߞyCpzb(9ف&YtA@w !B& kJ#Đ@տa,:?p\+Ex;(4U=:v Q5ԷtTX?/cuc'<@hB-Be S._8k09Lć&] sG5hnN\FO—/z:旐_b):~dO[nC;gL/HD"R\Ds ߅%dw۲v/|vQPt, FŹ@[!o$!p\!b!Sd21|iQEڣSǎBancŘ.%,`ꅯ |a`%.+l)+JoUi.ك;2[  (1!:.P ҿ׀^h@$ \Ê!HIšhĴ4; .DŽCd`u>ܛ;IqQ"DEh 8.5@(h &"Cxg 0ȶ`K0"T ; vGN ǜc h_<8uƉ*h;F&iup |j 5BNCS{.HЇ@fi { q 92x&m881^]Q u ܠv) )Fqi*Z@Rx׈B$<&lH~rbvϑI`$c!WX%߇D`6 d9CPA4cp2ݡS@0XmA̺77 #@Fg!B0J_#7!s:hR`@. p`UEbdPsAy/a-\JuÞ)-`ϠMȍ@<yVKLS o35%y`m^(rQC$v1^j#: sWM1GxP`wYzE(aR&dL! "GD@"xX9-Fs3Բ@7#+-_G9#ȵxo&8vxD4p;(3( UX;LX"J+MX "[h$A Of%|{ ޖAI9 P #:hL9YDwi#mL`9"3QH f_c oAXD(sdM U(x=2HyS~is|0'0xU*β9+iJ- FKq0y2qfl܌X%(M2w;HmYd'Q'p7 ߃fC[IaRހ]d[Rt玫*+848%S A`Gէo}' (TM+U]j5K>6 גo"{zwT:JK!{ -š>z uBUk*BUl.TFKB /KBE*/ B5'9bǘK!T@ft P(P{xd23C ֍X6⡙2%Qn>ob|>1%Go]ݐd279R(,?,Rœ(#)~@s jpQt!"b&,0+Γy[{てP5)}Џm"n3nȖBDK"8`< H1͙P68k:"rbɢkbJ >ɚ &Kdd\:`c ej7 gܢL 0KKHus9J?| 0"= Yf0QC?k ¬9j1 / +Q<B阁7*Ċ^dvY­5ۊִKdYkGÈ8WeQn0H$p(ۧѻAp*EQ"N.ES4米ű(SBw0K'Knoxj<}iwK‘) 2, yp u5G?x< Ou791[ Ԑ8OЙ.|tf%t"(8[bE]VeKV]u-1Mo}a"&%yt)r#"w 3%c9?ȩS;h;"< #X:s< vd暏7 '8'&ѹ!r",9N!'X1=̶ [BNEs}o$͋P0l: #,8Yq Im%_ͺլ+f]uahk!t!K}m +85!psLWn8G!5 c{""X/ >3Ǯ,tGǫp:Lv)a&3 !Bw7Pl8p@\Rx ޖjǂoX O[غOgjSVp2]plhytpӟ1q3] .=0ˏu~_;F;eOFף?V$c0ǙՕ]dP.?=J;}GSJd~ndjwOXw8NtIg#s5z첚_ӕ-dnt?7}5D|__{Ebv6, \p{'K⺧]_|Jޝ|9W]ڨwbwgF _8k`Bqv^]o :-tXӆIi$Z=ؗtUԿNOG`){U/pB5M uR%$z Uy 6_6eyN HWN8fx J.v=3GMi}Gyƶ8V׺1F+璿9oq=8lѾֽ-.S>~P;90>D6D$ljߣP(#w}|{\2Fi:-i[Bu4ƬM:6mZ#u?lGZmPkb䰆w_{"(S3̈́{d+*txf5QQm3iXRiw*wMU@뫛S3_JRsyid];/34{˧ݽB* <6۽mU_Ҵ.> SҮs^bٰ XI 2@8cˀTgZvXH!ar0OW$H{ ilM{5ekEr4b&3JJdV8"8g*⯭d"|tM6,W-Li'cۂ)UHdNܲˌj`AHi= u q$i5Xƒm%p[$eVE? 88Ky[RLB&w$Bq9}`ł9a/ -5{(\dR=JdIfULfV#H[M `q 1ikAs7}dy)':S邾rOUĺΑ28($&wddI%5NJJ`Rr&2QM>9RdoK yNz[@D[N)xh2k+JH-qVGH7z akF 6P0͂[`\/T k~vZ..ZN Bzl(ۆjL\/bJ\F&qU226^\²7NqfHC(92V= Cgڐr*פIؘNEqG*\!$LPNk; Q*BdHUeiɖ %J׬P2b@͎)Wt,HX#\a.c5WWW&hOHJF -캴?'3 s2V j̣*0|nXSF F'Gʪ*f8È F;>$>v$ې -.nj`rZ}vqm0_N*\Oц"2ruŕ.M{5=^+ƥRZgMH"GǐT2Y;|n+!!3%mGUc:(Z&{stIbrr9lk+d"h 6jtƨDֶsbM5"CA0[wrmGDe\:yF -&1ARh([QC6,@>䉖Tu9NQAGbT3Yfv}0jf"h]؂Jr7GT&9f) st>8$W00ys0ZT >M`*i?dkN_;:]M8j? FHFㆅԚ%3wtӐ$jDW[!4oх;%^mMXVZr]of4T6Hhuf.H,2h9>x$*SWL I6bߩAZgq~dXUGbcGGDs<;>r$:؛Gctg!F%szO211*X,13df)(ID@k"|Z?Hh[\jXc;2yh[ޜZ_Ig(4g(y3Ѱ4Q|$VvtH:yS3FF$brd lĘ$%{Mϼ2M i-WP׽ϢE^`gGEIl5sLHZ nco\B gH0bo%kb$,/0$[yqSYZZ=0<Jς6K4Ս[EV\ܨgD^e&&ZJ)SX_RRoJÙF]dGOlq:V /w/u`0l~3O.}=DD߲OQ._?Hȑ`CN =JvP@kJ;}G -rrͿ!s?PK 8DXf4 Op-amp.inoe 0SܘP AD"w7M]>m#R'm`eώ$aINPK8D+lL Op-amp.fzPK 8DXf4 LOp-amp.inoPKoMfritzing-app-0.9.2b/sketches/core/Optocoupler.fzz000066400000000000000000000354441250202676700221260ustar00rootroot00000000000000PK48D{:Optocoupler.fz}rFqG>Ku3amw3OqP%qL>Ծ>Ve. =12P/JT}O~0 'Wg4!g`ܟ\ׯ~y]ln'Fj:O IEBhDB/Y4 _]LzY?\:_̇xOy<Fg|8 ^}Wo\5ټ7';>/7TbT{ 7Wg2SNuuZpqyD4ݺ_LK(ޝ<.z߮h2}u+w]O>R!r8>f7߻NgQo4d}M' Fu[0 n{a1 'ͪ9{ܫU}nu|*{o&>pݴ|N= £s(vW6-hAz2ӟW}__h0=%ƗOΘ\Ew=߸_fnt9q7C%wd:Ng'WߝZ-q_W]nAQ`ZTe7^&s{DYUP1*rAPa<~*kr(;pu tCe_גu}XvEz(aXk}8llcJ[j%*Ak_u}Vh2EdSw}"KDAVND_$N!&ʴfkm1 TeTNe`MPFTyl{MLO__뿞OFo6op}qw~~tB7nǏGLw?w<ߎa\//oeiBzyq]8* g KvVu0Ǜ|weֽMM-sC+ Uv8dx7Wf/]Z#d^'}؀z8瓻Sb2OnNWSh 5/FoЩ؝2~ByG%fĂN oûu}zd}Utr}v6pl8&Kwٻ]<Dhr[8TD?ա7tmIz]o}7;7by~C?9/p|MQo|*>72qxMU8O+BʓD=VmRL&+0dljB6:ay6UԚl }@9F?׀83Ӆ\mC7h)0qZDAPt1?ثXX(1(eQz枪V|o?ͧTO>3ՙWč3$_8\sq0,['eV܋Ԓ:yeTMCZ1]P uLg\%:ͅ6T OdfIɂDkk$'4Iar>4u}QBdp>#W qY5č{Rڒi*x\Grft1U9d: [DmNk&шMNQwhݔfSM(N IڄLJ^Dū+Zy$TЀT&{B,bڪ&zt"b 2'QZ(ig׎#uz 6V†N5EF;ؚcs`y0\,,/tdNݫpp|]rpwymj(pwӉhܻ:òg}oa!nxxp<ތ!6;Ӆm6?˺c2;7"?>=jDQ\ O$Ry` p< ]߇VE b0b]be[չ)y/sj[#(_94?jq4<؁v"KۂsijC` uWOgWmtKRrͨϣ,8KX'LH#|& +n#s"9+;4vT]كrU`3!Zd3D;,FTw] F >{"`uצOug/6| A>Qa?R&Ģ(J%| H& [H-J܂D?j-EMDgЄPiz7MFmt㬄Q<ۙyFg YarIc  ПH ,hQC硙E Ac|*$1|@>$.ΕMGCϔJ>bESCI`HRM60y4kN鳋Ks6+>8Kh=<a?vn\,T2O" \ $L:>h_`v2Q`qL1I8ՊbG_P]aAzp5z5b"QcD0u";PF8|,w?%y1~*ys4ЛhHic>q":&!gI,ZJ5>g볼.{3[S&Z^yƄb^O5yd}kM+ fRB߽RGʷ%yћ_YztV"4h1e/fJT0Tڄyڙ§':f%1nXNa'9o_w{HQUUg݇DǙ`EoY!C$(fF#V'#0-i8*DC{H"IHuRGߡqmhwSmk:6GU; GP"Wѫt,R E{ŽW(TĿWܳ W~j4?r3|t.a-kjذ(mLzaYZ,J]4V4mVk/Aij':CSV`mW_,ؙlK@ ~NRe`Z$i?"pzj#'{P3n6bO,S1j7D&L7dDN:^}҉uH4{_8fǔgW X*x2M)xjJAn9ʼٓ j)O,O:B[ܒ &N/%tAȽ>Šn>$zI )ON:ՠvnvmAdtji$O9vl(YtP;Y7ސvPK(9ăIO'&OlL?bO,󦀲M)í"u ^ކGKbp3ha~kY:߇uCJCTgIj-72VQ܀WDpޯkU7˪"k~j (\5ۓj[uֵ)Bi[@_f!nВY[9L,c K3IIiB_O'jzI.KޥHI7GbX iwB<ԊI#t8=PSU15D&h1dkwCe4nQr~[tukeG6>&XT$0\hȄJ3b3xV۲BJJ9j@eǀPR# n;3R]1#Ur7L7ot18h"h5bb/Ɩn`=bP'BmaX,4$* ]@Ļ,`h'F%Gc0ih 'My:NjImŜĘIBK)iM"Dw-~ :ہiLc8 *V7p;ro*H $SZ5ZtkSTX2fXJ/nM=ա|Q#5Z̴r4jEiI*]91sRL|IR!kmH#6AL9Y:RtUd)S aZf_R!۷˖.WW*6kCEIXbPRR4<($dGKF[DYaƓR]!̴ѠR?v委ӊ .D^|]sx%C,j2I-1]WX|矺"P'Laʼ6Ԕx_3K3|!~ }1N'CM (G㦦:Dii)yQp+c\uI̥旔+ruA@Yek6zl0u9qj:>_]^ }] y &+Mo7!kUsBx[&O-:ӖJ)|bߌ}iM+x{}u6~c21, MbHjnP1F)Ն:SeE -Mv-R:^ҒHvn*!IN'?W9`q=s sZSPʜ[í`F.'?f0gˤk!Mnh?ݎ{4!/?_0͋?q=?P?^?~6_G?Σqw~~:#nۿ^w/ݏ?&y2^wnY{beq}?=#//'l"Tt4p08_e eDEqP'0lFtd(쎔8\^ΤƟK%#L8P٣3*HddMZvSW3Wp2֣ih_]O'i)QI/ᑡ̝2}!w~W8~a%RQ,[t)5r  i,_p-'/*k ڿa3Tj|Y mբO:/*}Z쌕¿":y5F$\жř餿NYr B Q/]^^zGAVA̋3odbrʝw V<wtXŒp ϝ%0َ wA,hQaܽ2faC(3Ab*tpgẻދap ]c(::oMДqt7^-K /P̘֣+J/$0Zhwu(L,(0/()(0T \z0`Q%0qJb 6a]^oTgb @ x,x辠IΏȎ5ZaJ#+_S"E+;ň9# vih:̂.R/ @b%9߀p#n75܀6epbpvc~JΖv!91vGGϻv M},hWզhB*8iWɽ`€a1[ p~^\'a]MQp.4m nxӠ?cX}D-zeǎܻy㸟 .7<9(z4ܣ:'S ` RSVUb d)[@1xP䣐0ѩ CEF󋱚7i`]h:4R!x`6. byUׇ87s $) rn|y/&a` ؛wMA f;QV``zCv"tՅa3H -@}B"ﰠIf\`5 h@J,=+dZ]@P yp4 ptP\{"рGCPrlB0kVk\,8w3|!0HRm@f@0b~>U1tܑu ux1 cC\gFX@ oJKy OQ}*Bl@Z{ J ؃PI|!n@&(? x  (TNA=nP, } Is@[j 栝LS|4\b0 0k% *5R+F(V9S\A\" DfgqN4.| @P3ٱ-gHDu7N wa>0X)D;CëUg ^@`H19nP+K`X4LUA5S0z;R#ʠ=Nf0',`%sZȽ%7;o*snx;q!f8y3gr 0TK$&p@b/D uRy@ġ7!QpU(7 dm.@g@D&ToW64 #B$``D8R n>Ha\ƀJ)%)0XbVr 1#Z>EB} Pu XNѐ ab+ x<킶HGc+ơl-@Wu^hVB z A +05v~'gAX6=w?VqP3 \FYI,@)z)b,b5+xXR[qJT†IG J=x `;v)\'< &dRcl dAN :ѰQ_DBcpJ8!O+G<04F ٱwm @gV]:ɩ <N{~S{hvr,m,μMrE\H;4Д} _X~F39v"sL@.0b 0<؆9H~"/(9y>S@q mGl~vCI`0"-aȫ CĚRx*b @;ꏨ{yΏ3ߑyh;)cBSZѱcNSAb@bO N y0OM([DCK|bpH0q|t >lD5N+cK#n09Ǡ7oа&յ^Py}}KI1˜ǥ)&;(Rx׈B$Fs3Բ@7#+g _8N9LTtR&Gȵl&1;vxD4PJ" ?5xO TCsS ASDixo@4bb67l 1:o8+惇KZ -r P #\4NQ,;`rD!fC|'g`T &a2E_ŃD @.`(h'DH| Ba03-2!2XtC܄CP24ǁ-g ,A=JOG'5`'hv lIGmwMDžd6*Q "HySG 9RnZœpf@;r@AW[d) 6-KP2xn F,︠i.sAJo"}U| {P-ph1>"ނP{hoi㇎+K玫+848c2yL?1m?VPFqjZBSYat?}GNz9m*4*aZ[Ck5. U̅X.TF B / BE-*/gB5?r@'N\ p2UBS['2 `ވ4S@10FL! 'LID?"xIf,m/U8ői6@X& `C;8#4b*\dMHc8@Q8+Γy[;て5)5E'nBDS".IN ٷo\sC`1E*|5%L$g*Nc El7 'ܢL 0SKHũI ǎg>{X8,e2X0 |5G-F0! xJLEo7 oݐ~ߖզ/a&+O,|ѻƼ|?|D{Hi) dO!zǗ_ ű@4>Sba(74%7 L:/Y%( V(XR\ڊlAٲJS"'&4D0NweA|X#&6;9uj!``0U^a@tSѴŻf$݁&\~e3I<:X6D50CNć1O 'q kBpn~Sҿ1'`&4mFXpP&>`~yU-Ϻbx㬫, q07!15Rj[,C ~9NW8Gaj,"烃 gcB耣9`^f9dɔ%3 !0ra(SOnc!zAs mL[:ăӯظ֨7;_J[a|~O~.۝7u~3f0 ˎcw Xcr}:O29 +1ƙWfqI2HpRѕˆ{|"4Vs4_7m/N݂4_1aO{"rL@yG-_/?^ ?qڅ{X'5KY@>V4ǨD)v7]M-Qo)Jo)ߌz-,8k`f?W?eJ,[|x\Ip Մeç#x%X}ľa.mlj.R)ӥE{:)hzՒb:F Lt 7Tݓi.X ^n|-ɢQ.fykyXCN.؀J ?JP c}{7B$1U_ee uW D ^Sh,],j. f.H{yp=|m5T/kLtڊ Den`vya,pvؓ">F{OInt*PU*/UDiqsξ,ZbJm)+">5&9¶HڹӞ|wqHnbe|5+rRz!>)F6Kؤ^6lT#-W;4d(<o)zpÌwRҘӴeº|+(hb5i0zz[|$ Q&Ac4Q! R+rAv8QJ-]ED;iR4 Z&3|zW&ldȄsLHVlG.R- UOM>92Xx;coPt8@ȳi!2dYjbJTXb)f:Q퓩+$ ipj |N*z lc%~W/xgi]&T]ZvmJYE݊bōaIK&tD}$XaLO%@px4iw[l݈ M4%OpШZ=*QVõ*?.PK48D{:Optocoupler.fzPK<:fritzing-app-0.9.2b/sketches/core/Parking-Assistant.fzz000066400000000000000000000773051250202676700231570ustar00rootroot00000000000000PKm8DZ;~C Parking-Assistant.fzr#6xoM=! wvnrT**FRUu^[ kZ$AIt}1z{-wf׷'pnקO{4D>gr?p.E{n}..WrwWYroryToe/5]⍻CƘ4zMk_Sސ7\( 7?·wC7v%^|xnq-e/z - __G+ǭtO`XZvwf?{dpb,0Q½Y79| ·H;Ch4oNr-/n0l>*ܾA#V읷^NR'NaYGͺW^P}~ Ӫwx=ya˻7dwf:ߡUAwϴ7ϩٛ+^-*9͙z6Ose6f6OsbIX~;j{|gwU*|;aoQ{Bx2Oټ{゘^lU|!Wĸ}g26ذf)7 1%ǥƕd<^3 Ɔ>n&m^ǍILdw*N)v}<)5EcqFZU'j=nߙ=nMFݿVrݐM0SW7r8!$RS`IVcqx2NT} MI)hͨ2Z-+6d̨5+*)^7J(>eiJ3O0`r{;JI>9~_Ȑ-2 7rTarܞ3+TPT?X OJU6 OwVcqG+I_$9~ő gۦGXiS?gbqJ>S~d&^(Z=nT5>1ESq̸g~Rar][E]D*U\q>^lJ+UZ59P^bvz|)yT~ڊ`Uê=-0=,^MmLT,='#>LG^-&(Nj< Nj;:Lr=n OfWZJ]#/}΄#R'|٬S||zΣY>AIw 댣D%!ͩV !bI|֏JqgX/GZU:S'e-DS+x(^/JOZ!|z%j6$68yIǨ;8FjV-^Mf=Ҙ~ֺe1{W(Y*`rz2jh7$cj{ zؽ'fz;%{2;SLtv~LTv &[U' ޵ `oLZ]%^j{VVɦ !&uu f80Ug8pzNw)n;Ykh]$ݤ\E'M+*Tf մZMpϊ=$Ik MW>{6=~"ө5JMRJ Z#65M&uWkk9n*u/L03ɜ F^!jD|lzſx•~{ae+{W+,^Y4qaNszu/ jwg67$cQ| z'y57'fsb^{s:|@Qp6aj„.^9(^4^ɦN`NiqBH"3.>\7/FdR ɂ 8^0UɧUJ`ec@ez Bl b)e=0Upz;Qw )nFYo]1%lE*N5}T}"s;VI=0%I S#W?6=jϕ"7JSRYMMZ#k7bq;dIz-ǭ^)zCf= Skjl$R鳬:cL; Ot'٦Wf|&XeL+ϪaJ Udc'XKOUK1+'Xֻ li!I!V]e2%^1NTO9}A>n5tu9UWtu9m]|ܡalqx21ް|#TD,yѫԞ7:ї]~Z|^9O<\?l?zZ|w7H>\~nq>Y]]7?X(_~{ivs~៘kՋ٧ݟg8y/kˇſk/X[o~7/{_`$Dqen5_ϩ& ajc/ѧ~f'so5Z6Jm|]r7cx`p{u~jnCh!Zic% i뻇z1WNwXS%tێϺda5_Jo-oS(?8!>cZ}bȇ*1`` q4/kd&Y(rCZz終4􋠢<}uc/2ݞ x!-ly: ߐ#(q(P\>z?[q^%~ uNd5`ϩt_YTGW2iCp|y= <-1 &yt`e'f:0%``v^E!xyXHd(f<{M3/hK%ۍ2N>1.5?*<T+X;-w P òkDWE6H 9NYu&sg5,h.DӐǧshyϸZDN4d=z^xs!Py\ʣ{G0T3Ď-Rsl}1a3g(ⅹ cL/(=t9_txU(4Q Y6qMLc9O7ST ;v>hEbeB$;|ذ9Dl8Dߵյ>.6CEMX}Ɲ˔A!̏m}lr ekLJ)Ջ"ß~v{`˵Xjᚯ?.?p6Dypd>7pG'[Vr#ùq@'A_-FB挸qn֓ 4{ 8h>FT5++-@!1 xj ْ,{қޮPon@ow OBoWu15;xz;zc㬖Of.5 LGop̙hmÍMRnە >XkFJAlP"-Ix3:Y]FZ;& en#v޴ ).ܨF+@=yΓw Cx"Tۧ\,ڮ]V4vjPmܮ(OClu1L̅9C}hgx.q #XSFS6yXNvKnN8'ԓZOMl$>7pF'+NyÔnUE}|b{%aRȣ DC&\,Ooz~  C]a;KڎjvRK#f*KkPmPmtlbқԠCڹR rjNlWv. Pl2jFP zԓ|y@e&۹+FM̘s=]C0=F֘+ɠ]3p{τ=.tfJeG/0qVM{RQzU 0h M[h7-PfcuFVC<OMh$D(O \ѩ *')F(V&4쏶I#D=€fg!ڧ4,OQ7U.3ڇB)'CV%쨳_7P6W7&0j LG3FFƱ씹Iuv㛡N˴Qk?5gtiNVk$'e\@jj.4s}߳J=ڈ|рI3/m7G{~ۂ7Bt7ߣj)JQuArQNq6aVM|yP!JoUaIo9N!J5E0"{deo&{k=aٻbn飲w9sN7_nW )S= ջO4 EyDoQ3U.z 7%Uo1TFQjbZ!r.o7ޏ^`ì.F`v9U\O^lqP/tӽ"[B27E'+5'~#F3IPeOOTVa*рQ W0ۇfz ^-xw?pqp}R>ڟn_\?}/?fnǿ|_~o~5??+y~!w6?n>:o^=yۇ_e ].87[?=o~bӇOi߇}~w9w绋_yhK۰M},|[\럾7wWgv/7a?~^\} ޟ)]\꩏ð)/^n?|A>ؽup~Ь毮o/1r}toAˆxq_ÌC܇ފoPoc{7?Hss{D]Wnz~~qqnzvqz#P~vA3^!<{$>Ԅ(TGIF?_Nq_0t[Dc7G ϣ#џ^lr~AAڒQ8bSxO={{vI56{}/Ua{?~H1yL`9󇟂* k߂Ǣ,) t#$mTj;hp$@ՎJZyh<_&c;q1ZswƫA3PU5gEA7d 7E~B)).>&)m[vFx̚ȧ(L>:|3d6P1 *?jNsh.yc4.5 qLbd[6N t7k TʝmW)nf$ӡ W#!EDmxr"0Li+J+9BAZ`b-(w.mW7R(V¼kUER5{?H[*WEY\7zr*W*)QU"E0iQCI6NJKb SD1{xRzٗJVƀjTnj7gtT78Ǫs _?v]޲V:ڂZFFp2ARMk2HDF6z2Dt B0dL/㠞Aua a!"tb#FAh:8Juc*SEdZU AfOr:Zϵ@TFt4MؓdK8Wp! (fOLqQ^M"EbT)*=-"LS҃Ίf}2#Urtn/{tSkKѦdq#QlCbA$|c\#dSCI &((&HIOFe#J1JT%1VUCt,rD!7o`tNhLs7DP^aYሸvnf7t!-qN$Yfo4:[p3fy h:Mo"[EPi]!dKɢ8<d4KQGQ ٟj^ѝfMuQTn4ȖL'4SiͭO4)Ga~~OXy4<4aSDT'FP`TUG"b Ԏ̡…x%en)ܼG w>:Ou$*>:12$[Z8 j0aK{hm,fy%Z= :j$FEuA(A&`2&{NJqQ~MalRɹdE$»dsG:&Tr[ҍjW=!RjG S\:Jjhα d['J %X-%HJMFeI)V*){R^zs4jwӧY2mO\D4C-T/U^@)OQitBݭsu'.mКIWLKfTnpΩmf8e%u{HRV65{j,u ,K%I*Bx 3 KX/4?K5Y*֎MbIS6>Y ronu﷑v&XZiD( t ioivI6AE)8k!eSFQʩRTY C";ӎTKN30j'frؒ2娙L9 2`QL<K ;ԚN";]:;ב=Y*QS 1E4-XrĔ$ 1tIJ!H(LJ);fTAmWβXJR^\ښYc5 JYe4yn׍Y+7{bt,=e%y*Bx 3 Ox}` bVQ꽜Ӕ1>Mfg4HS7f/'c_:4u745!ڪ%[KF2av4aeTN@4d<LMTF /A݁r2n9#HY*u7+cci%SXjgnj~>`*`_u7k4&m{Šl*@ ֫ԉAeSFOqY@d<LFJ8G_JE7)plL)\vF*yGqnR827L-LF ܝ}x}Ջ@³Ij8i#V*Ő1zAD`o;5FAMǍ}`6z~ !{FvzoXZУ!c(tU (hڔ̪`>BŜFKPa52FoJL-њca(S{1'֎('z ؔZkmkq:iz؀,_VvDX2[sy'Lܩ<9m2G"#Y ING^9Jݓ%oH"UEzb@[RJfi! {sa umbL7oޘ Pj\De N!*vO֗;BsVX8.k1B5&+ZPX葒r"=KRxZk!UFg=)Ed 4 \, HG'5&_N0qDVS^&8742%oNj?H|1.6Q]Y~'ݶN-iAR1)+Lz=n$BXB )YqKMU,+Hݎ*H2ȩR7=dn\4oU*dn1[<2MGXց$K1>m껑̭d1j[a\Av|TA FN!ucz#u6=YVkvkn[FA궤n ԭz6!3H-)k⸑`ң/FV \NZ uK`nGn`dR7jvn\"u[FA궤n ԭt)n/'&k9Yj‘FIH(q[& 9YƇިF6+߫co EJX"%z-}|E)R_[1++oI07j2s3%QY1Y[&9Y&VY[T"J-3mdoےV +]d=΂}w \!{+ [=`Eՠe.>USeeorLIۺJl5rl UJX*%YMPnJh.qƭT g,KnW g[QUSeljٺ-Af@ҖB-IAꓰIZpȶ.QpCVVna%GFzq-,inM $mz| i!Hږ IX$4E8ki\%i[Yč*BK -,m3B4Œ$z| m!H:fR-IB Ɇ$]dͷz)XYzڪb|4`F$”dhG$hd 5 %sRnfۃ+"[`ZF(A5)R}D>B ֕ľ@yowDid.g֪R9'*B(4CJӢ#l`c$ ((ʇ\fEK3հ42N0ēԉ&KJXf!FJj%Jd7HseH-= i?$mc)+7S'CX)cj[Xe?}S'נpSXb i1bAG8qu [5~'G|Rәlۓ͕duGduY%Tg= FU*\HlNKaʄ:m@$s# ak2 :\y8-!"2oN:DvD*,0ZN$99)G(djGdjIpڭo 0! o@,:dJƤ+FHf(pP.HH'7kOqi[i&L' iH~H\P@"pm.S|2ے~Oam`y.m{ON\7ZG9IS0I=Vdir0i #lH*u[5SRĚۨpu 3ŠnVNr>52.F2CU&$HצXѵʾK*8VzW4R(fMB8@̒H׎_E}ngԢB>Z3jdgd ,Qst+Pw*$hBG-њc#Χͧh]r Χ=|Z&(94U, A@ek]t *΍lExI IYk$ka)b k6uA2d-F\V5I% rZ&$9YK#H2RTj D(L-h R2YmNmT5V![K~OWckO}SLZnp)ϗ$Kɏ! =N6є Be@hQ9Za-Χ)ablD^-txW5Z#Epe/JmP >PM0w&҃&R1Z&(95[, A@ek]& ӵDv![<}Uq-m~Z}? Vr`6v0ر.2*Q)[&9QF˄$rҵtkHY[Hei1/ղ} gnbTk%Nq~)Ό1@">~D3 iKЊ!2@0$#i0ELa&eu*2;lٝ~'GђdisiDřziŨږ9@)R1tZ&$94Š#2 lck0EElapސ,GڲIrX]E͓ckI_TrJZԀDFqZZ&,9YƋE$2 |k F4)b\EB(4C\7Dh-S\VxUlk;H>hYJy[fxcdmE8fLj%k{ g˄#'D [@ƖBuMŒ_끔IT!WZռZ595(҈ttx+H25Y $A;ejWSYa280RP:rCBVFJj\-Jnj6D1jCC +2r5U $A;ejW3yY2L[p:vEMYҰ(Ճ)WeZ;a!́į7Hf;6TA FN Ё<-#| Ox= O+%6o-jRC/FV FbU`[Wc\( ֆvUeej@DT-v UˈHZ&a oc\M]KEX⢲Z% Z5iS,lem% -Y' W$'lZ@>uT0uu᭰y ’͸ȸcW]V8,?Prjdj ޓ[cǼ]6OA64dD-*Qi9iZF@4qVx3lWG6%,jL}, H"HVhZ)%[YiYڬ|ކ*2ɲ4=A9eDiM3I|4wU ՏRm m*diQU9,9\-\vv/d!/NC^ v5s4Djl4厷)djwc?ZCZ1\-xUJ*B{ oM\v!4ۋ$'eɪ97 Q|+$;v' 0`鐋 ^e}tfYItbj%;L !^f“f@xD1~ Ö!MsVx:M(m\Ȇ6jj-c(%vO!k&(pXwIcV>DYazmRN6TKe2DSDӶð6[x36T;D7:eh, []#O뒛>Dn䴹- uˀ"H2" Ria6 Jhס!;u˘.2ј.YۨY$d'A(pKQ41LʭSnZ8Nտh-4mcBdm@Y[F A6dm9AJFHZ&KE1_v]m#dW6ix3@d iXX8n)0AΖ GNR r -# gr6y&I$"n \u'kE Sf)kY3mZ)Q)F#I20U6bc:&$řMefmXL- mˈ$HۆbIxa>-HȘ٪S7S)@\r.r06XϳaZzKeflL8t- ]#H׆t$kHt^oYcHhQdlZ_"cKXԂe[̹!zY6",Nս`-6eBdmPY[F$A6dm$%)]8jYmHC(6d=>}*ȑ[dS6bc5kxkNy$RʺLe‘ӦlL<|- _#M?_c0_+N8#=^Bv2hECkJFVeZ[_5ѭd* KT&vN$9M Q5LJR{0?Qㅋ49Bv$h,^hni/4a-@A6"M!Ot`yZ@6l ~hQB5Tjб QO"j)5\V' Qˉ$'KhhZ@6l1ZG|9PEe,&B kdБsjCcVbM98WE Վ5ojS9ZN$9Y D#H2Rak!H:$J|%EV:25BT j WOjs"."kWEV! cˉ''x)[A6lA)[쇒C,XӤt"d,D96d6 ۘz־KHێU H&؉R5 O~6ރ<,}ֆU!NؙwTX-^^7[隐v!!$E֦jSm Ve8ZlajY5$[N$9I6U A?pmؚc)ͱ9|]-_G.r_~qwn&^|x (]{ >-<>:ivs~Ջp٧-[{2O.@A R_;&70N# bs4 <4Fn bF~ 6Ok#yƔ6 R+w7el^t\xFZJ/2ߓt{uFvؓ_(&䄮S&1FJ 5q5x@Y,P"_iDBt>e=./SQ]HJpmؚ Nf&$TCAbd2m`tȕ B-Y(Zp-uSB%Bᱍ t4A b: R!huE[8woo&kz"<fqw_}ChFUCr.?=x7&|3w }l6.oY_ۇ_7B|3Yx`6)Ưn?_|1~Z޺v qwj&\Pݩ}̌q^ߍs;Ľӫ7yH[ū?~irn,>+ty]^wꁛ$k±nO$śha9i gdNög=^[s%n#ٵls(zs/o{%u5 h>ڗn(JsIF)_p_oS"*9 ZϢ|;w@w痡%cehkh Z\wZ+%("©2h`DB3g(]ڬIIiV)p5 akw oso=G= D4~~!wB֋(=nݿח'K'38{&lÝA zϳqwFxxJa 7P wߺ{:|Rb/G݃qWċ 3g&圆N ]AKboT>}߲oh=cQN >ę}`rMn{&}mqn>8sN6FCa TR?͸o;g~pW,Јh?, @&a * "~J:k2Om*S]@0|G$Q@cG??e@L&=L}ZFΖxZɅk _Qm8L“g_Ͽ7~E 'tWÌo~)bph:ÔxνD AᩅvxjSxPhxj{|-z]λ qν <||ؽ6_A#XaL2>p"ܠ9[]ڻAˌ^ҍidoTfc)Jo%$t`;0u`tفi{pxڅղ ѡʞGly_~>Q$eZެmB$1k^{7| m a |pY駹} Gr4`%Y? aˆwh᳁~z4t3ru !<@o>F &]BATdEk#UMH\)r&tz0h| %qp]>(|0#>+?P}ѽ'7:A\n0",Rk?5sG@( K2@"/Ҁ7*h+nxOwk: Asq 8sЎo36v6^h㎗..v{!ݠ)%զB&ߧ9 &J  ,0,V8q\!y5)m!>aa t?6D+zۻFPx&3Qb=ʺ׎|r[:s:D4=wЏhd/ˈpMs'uj+P W {\AhjQ(n7!$àF?eA@\8 xmvp`6kߕCCDxuN 4 rn gcymwh{ݻo̞FYlK3귎q{GS A8Lg""t(^,XIfH.`!}o85$],WIs Mx O_TqRs CN:yp:@W܈`C0 aBhOFt#:&X&p 4ep 0 AE@f QgBSl#),9PL *;Ж>x[ Rh qݽ68v"pp(La3Ql Bx{ "mw?  7Mfl9*~GK  ]>U?ɫ`]=A'迠x0fLzSZEyL~p`Ӄ%:2(5R +i.\S(p(dTv_ T`nGJ+wz t, tuBC0V?`Fh^^Sc`oHcro"D 4 K=LCL#m.*Hǀ?,z; >D *K Wb-V2/ Nw3ovvy`tKˊȰI}#-]^^1 ?""$M/D CoA#/P!4 `dSP}Ws<2XH![P' J 텳\,u~8n(+MȤm*(X;%@y:jC_BXGCc`J5p`xZygg"p040A->t$y:݇IN~@sx`]\6@t}dR 6ٟyKMr0w UM9s@ u `g@6^ϱ+]Ȅ@_ZN@?N@@Akh(-sA" 8D w>Ps{'xLzgbhh;`s# adj=@G ^`Z€W5 0GLPcȏ, 7B>`LM{&}Dji؅/-dw5w=x74 \XPŹ_ 7(70 D!C Bd` HkGЮC8h G s0z$ xq`J{OYcxR+Ȁa¤9LME _(aB$36ȗ /4DAA$ \ú`T Cшt~df9}PHh7l㹹נ(q謓ǥtCFAmGA &D@:P#"p 5 f* ~;d9@t=`x95d@54=tbx`Dp{;(:xKx8 Al 5BއSB.e9<0\ ,`{[9XA& zS]68?qb|wм /E$qKSHP1r pwy (Db _r Y#Mw|I$a rh!KR&\>[6 +tH~ G}8F6; 8?#hX7nBa1Yq #haHNs:R]ùW kDQh8_~ S x7hmZvO]@l3uOZ\!@ #CBCyh8.,0Skxgs#cF]>>x2q4SDp@)U>@Wh'.ұ9݈qsZ5 ƕw _Doa-aerD}-%vu|x^A<< PFSaD-"fIhpq;oL,v)2s.XAy4 a:(#2@_㰗 !@!ratRPEaC `@@аQWmǮN' IA/A` BE8 mrwSC/z~яyϏA~ ?"{~Lt=,=7cN1_z1.1!LZot]@It:LQI΢A2`RKv/um9a *>2$ 8w$H0L H\묻xqGl3=F98>!M2 s/h"@L.;]g!bK4 fF" ` W ) /"iͧ`% `&8Gętu'4{4l"z*e>g@ ܾ:< ڽl:XE}lz;I磺^ ]_Վة3G;s(,ʜ 8xY!T 1eK@P[:F/KwxK0/XƖ*_k):CӥM]dO ON8.B8ORmXC|hi竁+K1_8лbJcۋa!vpH1pS~OL_С⮫iMսXcG:mKگۆ^CiS [Vi/':4`T4bK23j~3*l¨gThXB'L\ pbo a2\"t୳ k %?7bav7͔Q P2Szɗ#'HI8"FI`Xp΂^`6ˁlbqM`vB@Z jp5Jwa&-`V']Ig*,Fdɚsdji`dg9y-4?eyakGN~`>Bcmqp\ÏJKr 9jAi 2Qr5k"pάEh7,*3XBN ?TpqUaJ5yoPI( 5^I>@~}UϺDuUwF]#8}횐y0K}n+4!rsn08Gqj4"7^i0vϢ 8^]ɔD/~a`S8Ep\<)hn]vL[d᭯~څU:?竛틿}~ww[\_i^@1(=/?6CL;fk;o^\\uP5ΌoKw)M#߿sN%)I+*Z9Pop#QwYjvQܫa\[81PW{CZswQ mq԰BzsSW'o~ TLpdzv G/GѵRkk彠pTe ]L9^d'񠺮%Sq¨5;\0Z:7Cp2ݵtu QQ8Ĥ&3|wS]df!u=%EZB>pTW?A+/8ʬ=1 К\Z^~(DHKgrVК4$2Z {6ۄFA5Uv'xGmW2B OچPjH,e^K1Zڎkm{3Zzt8eb^K X?OXy'YzmfBxiǑ-pv\#tZ^K!-FkîvCo%Gtt9'] H)jG#h W\~][.i>If$4.>$ɨ]omz+>?0lY|x O`!~iwˊBܟ~peadџc"yb0O(ܟ?.eAa$fFݟzOS f+Of_:n $sdI&€zK;Tnq?۝2Zc.bB`. T>[0bu[V'զv&۰$K5wƏP\ψC HaZI"B6tF%8fuV"ҍbS߆$K] #mrH/LTHaeE|X+1a@AGQkmMb$VH.(ߎ'rbID E} \8 nؚc A?< \* @L9*pԜs4? D"vO%$?)cCãױܬVUnAFW X~QQkB.z|:~ n!؅y+a0620 T2 ̴mB@\,Su]$뺩5$k.BLu@2ᜰuLX5*`&@+$UVJ}B9hkcqA:)^<} VTV\TK(XwGk>Lks'EJ_k dDdoKK 7ʲ7e͵.Jq( &Z;gL~Oƅqk4( ;:foނ,'=ѹX| t3~ )\ЁnؚRθ?Sv:N]}R" !m#w &S@ݓ+2G19!,CoNz}RMFԚx2JB:l+KppbS̼`yXXZ G^5GO"p$,o쯵r^\ ̐ʐ焱,xC?²q:Mȭ݂Z ݮڳJBb:!=Ήd91{&=փtfP"_\Qo9yqYѴ#[s|ÑٳI9sdSxc*[lC\ 2Ee[:`ϟ)\!C3G29q,?e;uar/fWZ%x!A ; KAFEpE[ׇ};\0UJqvCB|t CB2>z6!^߭k.cqxh* I5,$[H{$e?đr_pFJ|$t Zs$wt.zR!Oq # Rm9>xx="9YBANvɦ*vmm<ӑ>AۥxBq^O;ELdiYZ"$Y7K3=6himg#hɿ/ R(TR5fEf~^9nK?]ǹ$ק@i8VJ\hmY[s6!I BJ!X$kU6VR4"XNfMψ˞>-5~ Tp]J@I̔nLf NŇ_M|(IN %p\h=A#6occqg|%HY!H!T+oXkH)rwN) 5!=7Tp:p,{F`YdpE oe45ydpa%P\p:A$әfj,IM/.~ :qs鯂#949Ri.9!$7ZTVո5b(ո蠗deF&W$YV*7rqŸj` qMNA?vh7Qf-ت[`b[q>]q+٨!6zݾb8wG)>/J)U@fR@bvvgU°i_|4Ӧa7bic9N[`1}膵v:xkIbHaǛt+n09acvz2o+Zo[ocdwc-y^r K?}MօV&}~ؽ}wu7 w8\hX~6u^Km3.;ݵ~ E]?Z к.Qj?Zps=ǗקOOPKQOP+/x ZX>*"BH_@+h8|v!rB1~R=oՍј!Pɣվw7=1c1kF/$k%"T+$^q | G%FUX,cy1S}t1Vͯ% Ysb|b&Ln8*ӫ s%CQWz#$ Y^7E`Sϸfk2 "TZ0“Y&Vc5P.%8ͻa#QKtLˈ+'oLc2ky< Mi5h"08{,1ҰVP!+O)-tM29w5ks_PKm8DZ;~C Parking-Assistant.fzPKBm~fritzing-app-0.9.2b/sketches/core/Photocell.fzz000066400000000000000000000342471250202676700215440ustar00rootroot00000000000000PK8D֬d-85n Photocell.fz}FwıwN`/uhl/Fws&{H%y'NOG'ԝ~l-`L?'h.dW3߾f:S:}~r5|™4t~1ǧ'bO+t|1 *'ɜ /O|t~x~3i$p_4ԢoGǥdp O?X-m{hr/ ٓd0O~CM/ӏpOٺ-/b4OꇾYU{uPu?<~>,P";szv/0;uP7b4mᮗo^TTPo Z҆do'.Љ'R>irz~b$= ٿp:;;VV*o>Y"Ƌo~!y_^'?^$_tM]_򒮪?Bճ~ǏGMg_"X\p.NWo_hsxtxeǗb@Fuo[ 'xdz3Uq?Ϸ^2%|-t~,I>d1EMMd~<p% .A 8'|V]NGgg *kQHQd8?,ý9u^S>N'JϠYgɛY~遼JAN +~4H.[ 8&y>OgeO:%)tO_qBg`֌U.{c/x~ߌHy)MƃfLQ|O|gCIKʕ@3SFgV𮊥uKqbrnOV/͑GUjC^is"zp7ީd˔igO?ALB7?9Xi(çl0Ca!2N gP›3Fs W<>gkJ` o)24$fq/Ja3 j*bݽmʪ"&Ъ˥(^:R>ԕO7ں֬kͲ+-; /Smn^+ MFÒ;}wCV8\+d^+لmӫ| 0}LA~K(yc/\p &o5˸6y_ ͕6E%JXR$9A: @vΉK(3Es8Ϭvk)EfYn:*DM#E{¼Ji (L:f샠cf;/zLb,I87 >h6=s=68/×YMR!Yy>{:IX=/߼+}z'XCl;@nGߠa32ʮ^T Խ,g ͚;bGWdq+Żh;QAXm^`|OzkH\˶M{{󶳴UvbiS*W7T+UOf +uKuXi#i> ]'-}j[Tq9vQvۺlkݙq˔X˕ 4yKNK.0t%<,7D</HPs.\!Gm OY vijs[︼A۵`#|qs<{Wњe!4=ӎůR!hM(4w뭰xp\2e~MEUۯ + "gfߟ$-&$gM-8l oxpfzG"?l o6kщ[yi T{nDNq{|S5}&pT"&7Hl#7]%~iow6D}cg%=8/ji:!b3|+־R_ZiXq'[gۨއ'maD7d'ǝorw¿]}*q[(Pǝo;CԪ:R-NRއڐownXJ^ro}X^}fU+Jn*~ب!Nv tC~mrV*qۦǝow"?L+E~ܹvsF-[T/.J>K%~) 9aqgeeU$fV,n7EF+ǣۻEAb]"̚Vo!2@ܬ*bЂMϔx(Dfx$ӫkmē ^JQ>xM1׮+&>|FKfF(LX@I(?gշlsIޖh;a%KK$}8͹pDB*Q,w9 6!IhM|_r5+aGm<0l Ni9 .jЪz0ɿ)')Br{|1v Iw y`:H%u- źՋt!2kn硦tV>o7V .x Z﷝ʌᝩ(+S{2A{|25÷ky{| 9Ehd&|}g<3/>vv~,z4qsxhx'yl/}.N Ei"r;NdP^+ zo9T%^bɦ6p`;U[} |EꦔɌ;Y) xtHka:_X<PPDG?>JK2&"W2 R[HSs< bIA2N]9a<||wlO -jW;oQwoV׺n{t徸 OYH~'R8T1 ZО̤^zk3֏Ӟ{ͤrgRm&Y{^UU<{7jUk-A7R*L"U;d!P̳\QV7hT4lJ#t:H904썟Og<ݓJT;|V,SoBJ!m&SVE:rՓsTwfC)n%gYhe>^mT}6Ћd0kr^ާ 0j-7f+1wͼ_Qd*ӊp)$3Za ;۴d Wf \pgх ü/`Gi2ƌ|V{&S;_=V~,?ϳ0mݫX1㪕t&^ˆLN[6Dfyu?Zk;T!vu"nu_6z<1 s/u b^cw8ϴGḂnTfnarZz~N?[\ट~n[;]|gڽw改S+O9g=ӹa[=n`|R5/ m}y{(pP;;|1Ys)7NT9`%q\8׺eR'}-rr<ΤҰۥ;_Fܙ;P,cEf_ խ7K$/yFǮ&r! my3U&\< Щ mn5/Cv6TDyn!JNqAG}/#h"><~(<.S\GQRNOށ ̩܈pvC^\}od(MOe½ ڮ;Cj XRli'7q̈́/Maddhe4ҰעXy!S8`]Eάlzm#~tmōo`hv K Cc*`N`Qe"L&8:2p,|߫u0(qӖD@Cyg/A}$8nj n'3i--3n)BvcFLķ1N];B{Nl=9)CH/ GV:37v8qXE]nHxq;iܺmרӣ\Ș:K$8Ba43/Fx֏跨*x7PwY UGŪF~/M=? R%2gۧdzsd4[ϢE];4q3V|Uf}Hi8wOM]ķ[i Jwcķc2irݸg<`k-BapQKهaK7xWps*%|I|s[Q,%3R4m |_[̃vmj$?: א/an'o#Jg*Zi<7L3^8ѶVCKv%_*m{J: ckr l=:s".kmFKE2o|yбdXGӒoZ-elX9wn4,X%uM|)|ԍ!Fܚc\նn%ͽgn"JbcLmZo-~7WoqfpuVo61gL*.3yUGZ+Hێ ^sĐ]%g~tm;Đn[? 7Kld:nMSdJ[NIJj;ܚn =8y .׌q  Z:#Tb'&+u[.iLbZKL +FGrmk]Gڕ6\՚cd-ekI`*bk4F\a5E๖udmGIՎ}E#S67<,YL*$vϫ0F#Mk)۸+QZ1e24ˡeD /ܞ%s!6]x' 8 Mkzaj+dUډ%$;-C[#l1.QM#eN7RA،}[AP꽃a 0}ҶܚnI]R7 %IbaVn1]M[A%Y$r{7D8ɎiDGn>q{H[Si>82_yVںE&Oom1N&z\A$I |t~(7d^hcR=n?\_8gtk|2&Ͽ8K|Wpÿ?$_Ӌ|e?&a?Y̦h8C~(7a.N^,MI>YpuIv(h8A'gq!?0_/A {B! NK9tL)P̜c)mS>c2 y(ֽW plp(Ӓ"8SneC"e@!௷64K\pt|NPTqhyx `6ClIh*wƶb[5d>kuyk^p0q2D]Et2\glCexI “W"XpAxC. (Oo~DC ye yUlx7RuU. H #B;|a#c T 2Gbu-/Zc *|A׫t^ }s1 Е , kޒl\&LҤ"*))08Ox|SMt=:T]{U="m9h,PɴA6].m8n|ö H`" u'|rZ5+=N9-ÛsYt(ŕ~Xiqy?jQ½%y?cj䴷;0/rA̡ߥ(DDa NF$?^#ءфjkvm}WЛVc>2Ǻ!IpSc V8iI/ENThJ>PpT}.P,6KDQ9E 񚀜/0CQnd O7w%ܠ6pbg@aꡝ\g |Chk];^K!vn)% Ux.Dr!4&aI_ D @%0neqLqn"RDt08Ĺ&񉰤nA ޠ ngQNvQ@ 9r\ؘB1lCa6qPe }c|3PN,(aȥ}b |M&qc8wˇQj{5+kF0_0󂇠ǁyD7^]2GL^GnUEMrCVo uS6uW;C((!lPR5N[rNu$遨4ݱ-j6 $Vxx=ӆZ4GŰ Nj ȥ y T$.A&@0gŒP~у0 %83) z`('9ʘPAO5w-蝹!Aކ`:"EQnHNDԑFT$"S?Tb&ۓWPxWnBO pE4X$"QUPcND8>`bH%z5 %".pU B&+"qBniMt(Q; j: 2k% )5RM+e8UC9S\TCC\b ECnC3?"CA= FA tGy$8j hi( *'I](! #*CNA!(=4 BЫ6-{)A@H1Q7W%c(-MCuOXTcH DEb]hXB!U*Z{ 2AeWpĂm !3O%Y7Ja^Va #02FZZU ^!!b'I?P_" 7I0Ј PtRwӳI jL>9 ?8GF d71b& I`!@Et 7%RJ( Lj$0m0ڕsF3eC+(K1Fa'9 ?w G:Y,B@4b$p4XpcQМI[ qoI^/iۣ D[=͟0O[U$^E"z)`VZ"z A +Z%*{TG4@0ՍvMP|/]0NP1L`@)`6 nN2,NaO 04oZK٘.B_5yؘ.B/J"/._g6KrbR C3 W><ֆL0&u,KMLrղdoY)zSc qU1I{G%> ?ugaؤLZMP:9Jjëql "'`=@B8=Mbj]Цtn̳lP9 x`܄q"#A(KG7&JAc:Ra`.DA|v*ؑYѻF_!*{%Ds.H%ȻQ eX%'& b:ꭦ| B-{RsV$ɹQ znQȇ륆u2xۣ)GoKRG ^Щ]5/ȞhN*N#pE6[e{e*^РL1,&zw1$ o:BF1Rqi1 pԺGՠ7#ڕMK{-aP1Fh%POY P4OST, LâPiBsln;hQV޺+CM41i/5RQF>d̽TS:(<*WQhQT`iTJnW .0bG48⫤9!3 C4H4 RZd4Ë2w4Kc~X #z4KGI8E d!qGj`}` ^G;AA "sI0aQ#%hzأ3wҀ%) 2X02F&ZT ,@ vvM._z$IS"KD!Jd41'0\뉆w=y^Ѽ х|*zy XX2np[LRNWuW~S,=-{DLE5pMDp \Ʃ< VQxu a'6.5yUu~-Ww&Nj"wzy@ˎAch鱫Xi|OʠvNgd0Ҋdqc$Np:x xOqK YiH E)0FatjwXZN$'mobV]Sme[=!F]: U>X&*[kՃ]kPdi2ir;,`=6I7qL{CN6v[a#7C"SX*V%Kwm}dnuޭ7JZ̶ hC~}}ňZ#./=zXK=Ynڱ!JkH{9R{z[Zv,f6mH]n{7D;˩U`'>T]WD{anŬ-MH iU[D; ǮW/u{/! T['>Vi3]X4a&tmk*NO޷=}oZaK<1YZYOxL( (HFgwY;\~o/fOpt4`ڻvg珨w͢%+n}w߿o0f>[.<n|O^I~SU­o~:ϫM):QԂz"=)O+Fʹv\2wi%]]07qgP?~t[ʤo]Z}ԛR?uR8Ɠ~mwxk՗B+h8:+_vԃr5?7ВڷIugo@͘}%I>{iȘ1Kʗ=SnDUiK96/ W]+Y;sI{*o*kn GSUpb{^(QX7,}R-'|51OR'=-jŲOMHLا#pvf}ک:i''W +R5iܧݯz pW +i'+SB&MFq٧enNik* *d^q`Vgqw "_;qvn~کi⧝ᯟ`Rgq7Nܧ'v~*~^gq7Mܧ? ~nE| "FPEEw]2]̳}wb^A5|}`x؟jWhQԶWZk$FH }[ÒJ)^MƓ-hs\H:!8.Pw+DK8@ep qN xm9 TՂJwx0=AVѬHĂ%zռ~9_0mwY5lk}ƵF)']U?-|330Llq w̲UIש3sh;u{W6Y({|B0l BBCĭoBw; X*y6)am5g8E@WWT43RRY/ghF -3xİΫǟ[{/oI~VlÐú"Aj4\A=cPw<|YG‡Zg\E*"i*ɂQ"sE#6,uG]4U ?>F+(gF*\QhS ~Zj3M<ϙ-̍nrMr.|*kTXy&g^6ݾǦLxn9󰁑"g=$k ئ2gnm9s阆ݚs˙1GjUwAL%E؟ḁ5B^rSiRlJѭ)E_/4E_G粧}7)7M>MћiRMRLW{rÈ lR: Y]B;g?m|o,RBV'kZ)zi'\&ERu Ei'ѱHb۹$[g.YlIl|97{ :B+X`>aSnI d_@:zaO;wlJ94z٭OF&V.6 WTh|AX X3fcX^O_쫠ط|x2 _s3(%}|!LGE[G0]C=D)|ņ6RUm%Y< [&R/C&kR|24\m鿭AladςOK4$| !XZi->sXW"31Gƨk4֪fj %8rCkL0F k O+]HhZ3 d-?z#&LJQǠ ak6Vno[Op<.i??7ckؚ*i|4lm_xl?LL=G ! _"*Bt6u"Mx`^,XJjBթ 6t$[),IҸ1kD LkigHC M#4߭ʚ"]t_{fb2l Ue]j Z+lvCDjh V kG*"5RͷeX򼙚{80=G ώe<[ԄF%L sY?ξݛmwyW0}u:ΛUNۿPf6{|1(O=nfC:dЛŗK* ( WnkԽvmm]7f*g;a5|vz颶ܵ[A> fhꑴu7G'ݻoZg#Sls /[WU_uGӯÕKEr\^(;f8v'׃Q4߽`w'N W҉ 6DEqht~yf?}QК F`>] u @^׾n"ۻü>HoZ mL<'Xquz׃b0|^\?_w?>ܾ*1exwuUhxu7μOZx|K_[O;o>hH|p#0dx,V @Q |4F+s  dnЖ_9QVp܌DF Wl_t~'?#;\M/u׉uq+JKMƞ1>aY; *_?#J0FL- pb{7yV6OPɉQ˖iTpQ_b{^I!v\nwN"dU.XT@PXE Gٲ&[?bO,PI0bO.A&Jzf%XYCfOC*[/4Sq)qE–U)06;0J)zJ!bCVnqMYE޶:v&oJ aWbW ^n[}rܭ2uȅۄ}(8f + 5.}MC>1ҶL0‘=Vnf+Zr`6bpT1 kczħiUMl`ST6-zoV('}.jZ Q!kD=¶ﰤk{[{i؜v`ҖNb&.L@+u_~LW34 [Ԛ]R=;x\\)uߤ#hxSOoKCX/՛eS>~0\ aR\]$/|֑~׫iH3>e Ĝ<g_|]zP`z%o}߈ů)˾n﮽g H#k;nnjc;ԥ;?[h;K};i}I<-&a",3K/jbkipەJIE(ٰD'`碹ro2"ez. +<%4tn8йrk% %Er$ %ۚ P]=}p]Pc3+ i[o3y &i0!lGۨzmzys#ZAs9xN%=B>FY;ygωNϯ+f]$B'sLJ#V?ۿξça?ƣW_}zfW_]Ͼ}7_Ǐ߶׭yQwyMokw:7݋NǏG'ם&ݻAo;P<]~],ZGIȋ/ OYX鷟ƓYQ+Ɠ^|Aza0lhTh}Ͼo`A3z ;2f9 w™Tӿu8yd8{P^;LhP㬂k9ݒ.^5:+LbV?: H5m`Խn(-UQ |d(sM?5dn oޤ=,$+Je'*)0` ),^"bfd[XIfYT HN c2GpG%-JfiɡI)jcpi.[,Mf p.: { V ʡ=+䠱C]& wXmR4sy]܈y ۂ 0׽=Y>h oSȢWcJ|j%yo{9{ zpe^"$u#|QD w7*,pν$.Ԧ nJ* pXosN.3vIEh ];;AhWjİ}uE"4&aI_R"L 28 @\&0(EDW SC mKfMLw+8` T&`EvɽKYvlCXA1хF -U[p'@ W @\/,[ʭ/0BW0B jtIRYj첸y A ]hC%SȾ ;FgfSxo %,9L d7{t`I`e̜sj3oO9M^- < DnyMrerƎ!kb uS6uW;C( ,T(AӖy]2Iz *Ew,EF-I0g|{@F<$"&rrPA\ĕ`P @,=P=C8`@9̐QƄzmA 6K)h rCf8D@I ojIJ'Q0Eޞ»v#"gҷGXH;/I.49ɏ(u"e$:yR!h㆔"\ B&+"qBniMp(`樝Bsz5\ sh 5SfHЕiA.*ɡ!.1CJB!!b{!K΀ wGvhI q3^ PAO $7^ h+BAzhWm* t$ȘEA7x0JPZ4L1T!53h=:A?aRe# mg3 tUBaVh{&Ɲ;8bAVnZϼg %0/0I}-ͫDLD!!bN~0EN$&E" C#nHoPȊږBNC ]KMBC$.TNQVI|l!rFq0/z9nB/LB؁2%nJ+ZPLAmI`v`+ ). jg2ӛC RLFIA"+` I  :XTp#4gTs{үw%m8ўyVC&a_bD־Wm.5śU^B D<MQ"TR5 j^# 0$ ShZ C!A$xfAcH)jXF^\ X16!Rj6&H>F j$!' 5a %`zHPI`@8 )?+-."Ht`YE*w0/ 104oTHِ.B_h!]^Eh!_\,T@, fZP2d k%f]jB3L]%{/P~G=a!u0 A]Ct3ç\!c:u 0lD&-PF(rQ@ {yE 86T0J!LʋBA1JΎ!)[t -$l: #a{<XvMJy2j8V5Y c2ay LLX)p. OQLX^D#1vCFKY|@GwUH1Ԝ"4X1&˜hL@1 ]{ymNSsodN@0L"C ؃: ?F`$Z"Wƌ5BU# 1rh>ؑ!y)"WEZ@)BPS;ͩt $~F'c"uc/{ ct<b DcK %|"x0%ic 0?T:5jԝzۤuYs*bH(t(Pe9~OG-ب{ٲlAD(""%%+wE.Sq ,eť"_J)o"!͎?ȮED 91q|1hPIESP$cG[P46N9]RNJDNgJiB )9rY(S$}8M T]4;͉eR/']`(i@$3I{J/#9:A)A1?ENdc(Jb&Lѩih_z@ !DˡcA"·gK/)i)+P$Q;K!e%1mapP B#DAQ6ZO}A00BhQ 4~g9POt=L;`:0EgCMGQ: I4A)3S Cbs#)E1(=GRU%yB]hQ A~-Ϣ)B%aR\Rқ'аM n("sG>aҜ&ds%03O)@- *O6,P?Tmite/ d QRN?$$d:͒!! WJrڶm *M~$eBHQ4rX ((` /,Rw+o}P"0Bd|!y e[dA)hL\*: L8^;2 "x׀4Kc#zi߂Єb ➡ԔIDrnT^[1!zE h#R&tJEj 0 E}Yv4(FL1"$ЅE`i:rYwԺՠ7#ڕ2{-aP1F` =[K̎}=Oh(&JIqK"N2ƞ1i:M> lMl:*<$QYBo A δ X9RJҜpPpVB+x>S06-KP92d N,蘒y.sQJ"|U| {X-p)?I"ޢH{[REyj2! +Al!4`0 ArFzUFj M f!Fs-~h)!crPSh(/4T-gla/j'ZY T Ո\_J[!TȲ,}HN8mAd0@B'^&"Ve(#y# 6쥅qAYno$c 9FDOH[8hJ"!P7 2` q.|(I,?fJoH9Ns8B3FTY\).p PMxc<gMjF+iؕ9,edi CUF>e4c,ͻ^35:*1Y M\G0YWdyr&kr( x&~W;v9e, yp?4;?vQa±''^@K'Q:J^ ?B(E )_2i4 FJLEh7 oݐ~ߖf$U_HVFD*TRtMIe&`4C$* tH2qJs+(KP|"0z$LU iEl ?|h``yl*Eߜ$9P[2R]45ܒ4(M,><̳D0,bȘ./`1!MB.MSvX5+Jyr-4Ɠ],r`\~e3A<;X6f5h j''IBjhl}SS&)Bi`]a!1 Ka/f~~̏Rx娫<y`xTG)--a }9 PTN804C("!caɸvᶐҥ,u搅~S—,=zDLE>pMp \Ʃ< V&j asgxªO鉕Kl ә>V2O|O:i2};o_g7_oa*вc1]kн><§O}O׃QwҊdqb~ME-/Iܵ6b12Zbk-pHIKEzc4^H+W{zTksh𹍠%,) 5/#O$d})[ `4^ >ǂiy9QtyA&TYϒH巾{a+Tp&Qy/)Fr6鎦Wm\ລ\oYp ‰pArXB~aᧄ,\򴓾nDU k4̓B`WzbuZ682v/6V31_ w7BWE<9ղOέU?yw'!;DMQv "UsUi'ohT=Y>a;t!ZDYFS*rDS_Ic (IQ Nv>5vYىŽ`k`ZFĉkWl FG juO!9ö=vˉӃ0jH Yi}רpEob#7]Y1.bE'|Mݒkō>c`Jo)6MҔ65یB1kΗn\EZ8yq~˅9/ZKm3!Uޥ683aI~S2vv1P9<adI`8f(Rcz;BuKGVh90&yd{U\BI>!q5CI&&w!Ksɮ:P07y@4ixαdDl+`&-IGo4,nuK17hx[Qd$䓣l+}mmhqKq+8@̆Rakΰ a FcIv$ Yt<5`nI#GLo#9.ڰ =Gir~f܁MaĊ<XLѾ )`0lէ5E6~`q0@pҐIն5ZY{ b z)g]J;2cw&dCb(t'qJwĪiz9LLu)o+gGb05w6W ')U-hZ3bX#IC;䃕5F5 wt6WW .(Djq"Tleͣ6z -Ѭrh}kn>[ؚՐ@ PI!rm&z hҨ(!gZ~ķ9kYF3BF-"ø$VV)nAMaƬ! [+< ICw# <[Vfi0Mz2Su3NἺr5"+ai{,m+KXq`\KMpu͊7ٹ-jͮYx%u$ihqi{]5Ki)!"fTin+p;(hM&<䄮'/jTESV`U W ',}9't S[6!؛]fCͶwwUY 9v4;7+arFJ,p<|0(č B&|,{,i+fxҬ2/-RxeJN nW M!<|IbOZ<ٝnBiڲO[iJmN}HB%1׺2 kVA9VRzbqI*O]q/ 8HC {`?D9l=PiINsH-?^vPKV8Dl2h9 RGB-LED.fzPK89fritzing-app-0.9.2b/sketches/core/Relay.fzz000066400000000000000000000432121250202676700206570ustar00rootroot00000000000000PKA8DhFTRelay.fz}ɑ1wP3d"͖L>m(MohЊU($P@kP dHdFdb'<"=<>#> gt3grz5/?gÿˋw=-~s. ۜМzKC~7y]s/N/fWiM.f4l~3xų?//tKH>7_ȇ?߾nb]|7ޕ]\=?:ftp>W}]lPR(Ce?{kcҼ5ꊘ+ͯ(e-CeyO\ u$57/s7NA1j.໋2׿=Z _'ju}_e/> g!F,9KcT.Q]nĻ( ϻ>2aw}XrEQJ轣>.@9؄mQ\;QY#pw< >2>K#G(.Pg^LRww+FLcG }rUYǩ]Iϻ>Rw9QMw=}t>(k#yQ|GU}lruڽ>:qw<.>NxvGu}t*~QyWG)3R]eϼ>6yޕK{gg-Qmϼ>JSqx;jwkavTݷ(;Wx1ྫྷ^b0a;~^\KM4 qEŵ}[.VY],nxp6}:q_\L׳][w7~.n]a^,F˓؋~v[?,~*^L@0!(%&8 9QrGƖX$Tݣ>#n:,_polSdRB1\P&1bQuju@n[(e&hٞ*/o1lnI-ZΦZcO4̦:1eVb=AuNcD >FP>J0~Q^L92krJr~*)3uĔ9GrgαA8rͯ8Bשpo`H>gRB\\}C"o8!qmn6uvj7: -zog;F8WN Fh_R䊉:L)^Dc?FfmhPTXC.})OC p4esZjG=8>]D\sʺ=a}@# =5{<Ƨ7oøaRN=. OA=I~P[3ȱmɘezfo,v\zLDUu3073UZJU)];w%NkrɔQ[%B(/F[@5J3Hצ5tJO.p>j?pCb߳}xo2Xz|4..c!x絋x8[yl (Z ynr3!r)1EmVa5E,rI3)*qgunԣ @xELgEqS~Ҋ+ݳz+3ʻύFTzdR1FepW2n\>(JF5$Eܓas5:KFMł+h%£(q ("zopBVkv|^˦#M%kA]xt网CV#9wKuOrLQ0]hl@dSL6&i-7:IrIF\k5D6w݃G%ٻcx4dS2k&莸qͦ#Qxw5駚L5ljb5C4LSvifTTӔbZ9G=5;wm%_FHfVN-g/AǮfVOr$晰S0z<)!Ǩe手P&snire%"0}Dy?@y\s#9nwkfߚˁ{.XF{6&ٻO+dNNu `s&݅8j7L-w;Zc~3y ĥ qQ 9Ph_9 {KcpZv{k Hs"H ɤ6"52Nf&莸 Lr$[.zF4}DSL4ò i2js_#6brn4 9M. Nta{nmAtBKiV6ڂ(hґX84*J,4V B»DO$n$3;K ǂc,Vi"&*kp ZJ0~*Ӑ\ "g"> } y/$v2`/>$0>w ȓeAH3Gg7t$YOm@>Y:"K=WtR9_:)p (2$5Mg8rMe8m T*$v9k*XXėHys&4 ƒ'oKMh-wO"Q2yMry[GomN4C긹k:)uP/ŵ[S V >2[s$XgW}.DJ]SMMsރ[PSjJwI+4<ޠT $;LRkW_3槟̆N5,'z||8>/.&hh-ٷewwŧv膆۷ٳއ{7?D~̃MȭarKOy-"~.7];-a {6a =%@eO@_ix7lRNE],faX!|4X XDa !hL)~`ĺN&uRaBTt|fKN9697]Lmb2GR/ TrV.7(!MQ&W=^aj$AkqůGB: VChwl'ڎeG{-X afmn a40ZKq_XU@E0sb uރ)tA1rځӳ?p-%CPBQ:!IGP#\)^m5MuJbcxզK2]3Npc6]l:{p1uߏWuﻟ/_e|?]| /~ 9 NY,?~?|:{7_ncAltȯWx->y|}؍ ,g=ƿihp|48-ƣ}-l}]}?Je/^fPէެwD]_܎Ɵl:t1~~>wʼnw7炐wb:nwI='wNWb4ގFnpMܷ|ϖIW~[܌hѻ=o*Wԝ79(~?L{ʽ(l:+z7Q/o6\3Ÿw78Ɵr迻'}-5~ G{+b b42KXYQsxc&n@q`Z<ߑl?de:YY`2X=՘΍$XX0WFLlREՕm}LnRDbL1]̻J-j+4?+[40|jlyw$ʯjCڰ1 NIv!"64e~f8I.Z&jaiygE)%BcFULJ`T[Uy%c̑I\{1Ʊ6tpqbKJ5&O;֒[o Hʿ7u ZoA8Lݮ̹XVA.'+啳m2Qmѷ'Ɂ-T> +B"&un@ a~bo))$<\Ip I&O$`peg  +7e 䉸pI HnkI1s$n$nr8bW$UI;B)vr$y 6ܑD* d[i{igO~ɭsoCLIJ0%%q-DV:%%mm5mkj"~ ŢpKL-NIL!xVđS+= Qk*lNNՖX52iҢGT֜&RvmbNJ.%H]?3ER "DT$< [Ibn @I*\m$%6pr]٥UMJӊkŒeۖ֜ N, sis/0J޿Ð$%MDUk?RA I,ml,mD8~<`}Nj=T$Z횝Q6NI.`%%T[p[{Io @IJpHܦh&qL$ 5"l|q[BhNрd;NSUjx#2oqJ"qMS֪c\8jkN%i[sh;p ,jBEĻY X; RRdckHd-u mg"ob[1NT-pDۢDDMFblgC"V;Uu5"X?l행"w㔅}ik̿ͺSaّ$յaD|@#I50H.E(Eʚē'[U֦ojh)AISoH12 fSBB_&O.5GrhwXKÍ] .Nꊁ3GF)ua|)*m2w PCx3C-(5!AI)MN^0 FPsܩ[i-m9Bꘛ27 X͵&MmLL޿p%ߚĔZNwkERm5GVEkɕ-y5TiDT":fW70ގ+JQKR!y|%o$$D'_Բlr]4R庇/~gߧdp=-~M]E*b2݋M.o˗ŏBSh!td=~*VzА907Z<gdMGC-\vh8< :Ju~an4aq>tn}A@bh\U fNaC8wK3rTkRrqkG$pFQ 44"\Ӈ_l.Y3$\fgI0fDFhfwrS><wU6EbWצD:M1צ5%Ò|?L7.3 77 ڴl꼻ŧv38qb} </|LXC X 9jtlOWQXƔ=G\;A3nq RڢB*q#}a.0Z[[mTN4J\[fڕ!%$MF+mE;.bڪgr ]-݁%i%{3`oe:Q-s۴͚$cU}v'jڰAhf,l(Bc-PJlj*5(O5$x$ښHj+{)d\Hbja$,LMlhmFbi'DX7I,I޿@$&䩒&}DDV[szHtlej=_̵*"&A!HʺA;SGKY $$-"%yNbL2t$k>U?$Հep%5XMϚ6%q{ÕĔ'D>Jq `Iq9= 'ӫ_\g?o?|ݛx/_}Y6 Oќ_g7ǏGOg.nF;qOt (ͯW>,z'مӑ?]M{ߏ GUNr҇~t0~.~j{Dh|#eʃ8IL_溜7!{:2Lr)b|4 ?Zpk0~toqf5N;Tyk_NH7Ń+Ӯ eFridO\뎭;vIMs#XBL^#K'Yw 7:_Ѩzq=d8]ڋQݯo-+Q܄WNO:1{[/w+[\'qz댩3})%>'rϢE7_?3}x*WZI~PI'q>bƉ锁@#@YF 0$@SϴR! J(/~Ƨ¶ !<-o`< p?Q#@pl )=.10a8=,%*@7В5m\w_E)-܍hyF(g_1?_O3YҺ{O?LwmIbA 5z-JCh쵬]ŸEEhV>6Ly K 6ǂo)) ZȼW^K+/P̘K7"GW1uꯌcd]/J/%$*0 + l* L Opj{0bQ%ܛϡ7A geZ /V0.IY؛g@`~w u-ߞ~Ȝ397)HJO =9&rB?@z1`w Q}IE^ɱ?-W؀C4A[(0vy a0-a8ycYc!}QkHFz/W6̿E (̙. vih:̂.R/ @b%9߀p# 7kJm*fEŜ\յqhŵ ~Kh;}yn)%ä́|g4^x€a1[ p~^\ O¼=) \hiT70\ jA,x+zٻ#Z(+7;_5btATAգF.=|wI)(--@՘Y1b h` -ޫP,G!2MeS$N/|u܎vC#rw؈mm` 6Wep}cx3>@Y@ 0 ^2ky2Vl2VLީS Su2 0DZO^,;,hY%0ej@)FC@w3f  "Ğd,'5'8$41L5h67" [= D*/d0((&<- M:Ø\elO҈_x#C1 p , dt#&w]Ci XgPg(h|"`l( MC Y`a6A =ZWA(x/)|!n@&K19*P~G#?6LH(w٫~b+BWɢ!2ipKAbM0 DI12 @T4.Ѡ.JA}3?lI4. @P3展-|g([?8bo:XE}`zSv4H"W׫:+{ƓcrݠV$4 #h˃j`H vBCt81v6A?)!zqXrBT)ޒ|jyix;w!f8Vy3gr 0T./V!"qF?/(DE‘>FT$߀5 @赡Ymɇ'A'+'‘ Mpp`$$@t%n R@ #%m.W3RI0Zo_^@Z)$>Gp;NA #2pJpFmA /4ǼFzm!!تqhz@t|Z"7u}+Mqê\ DC[@=0򰃥,hN#ԑ4u8пg.'ת0NbLC?ì$@)z)b,bkV𰤶8~* DAI1wA,u?eu mH&5Ʀ@F 4Ck /KjC?[G1RN@z6ʱ?plH&ey] Й-@W$9u%i>'9vo:l)]Ij.Y s?F”q#øO7s|3n0bQ73AQ:$QeB@W3U. @bc a #')BNLApr+=ycpz}1ڎ@MD : ;`DZW!5pDUb S}pԽJGCnQ4/* d@01y>:W6"+L'jœ1 l)VLy#xJb γ¡ tUL/E' wW>4stED*"UH-E]RBv_jʇQhg E`T F2ǕAO(2E&^U=:E|yk sŸ/t,aP/|M`` (}574\Wav(&͑e /'@QbB$368ȗJ@_r4H_z C|0r +s  B$t~$@_F=$po$5FExHp\jLP083$%LDD4pF#g8`ma EX5/66T9t=@29Ǻ"оBI?8tƉÀDp#:8%vv$Fis%:(˱0\h,:~d4.!G݊arAoj_Ua,2* `bqXbrr8JU^# !n!D0:8A0$sEaaEhdz؃bMjy8 02Cx*lhrRۣp;{'c*1t ЎaG@bDaaL;U!EbX]bMDZo5]HIty\oL YHA gy92^reKÅ|pYyΧpأBA ZTD=5^XAa HrYYh9ZX4Rs*(xq~< m,(J-@HAʘ1A2d'@Su,DA BK Ql18'A'1M85@5(C83x3!U֞ t hxUʂ}8H ,; zAXD}vtVIiJCtzU)oW#vaFʍRBª~pHpgPЕ4y geKR)<xi<|0CJ3*34c#VwVQRt)sүAJ";<*|=Y<\8HFoAn(uȵٺRdKUW؊GX Sci2;Uӊ4UW|͊ õۇ5?JCidouP8ڧ\NtUjPR-hEeE5BRF$G tbs)$ Ȍn2> Ԟz:>=Z4SB10͗8B4/G8$M X8g1^0őe6@XsX Nh0ͰX eX).f(Ys{[1K!L,. G"L[x003Ȱ0'/!z7_;4ch|<݌l+PC74%ϕʊ7 LWz9^: :KPpmQpK.Ve+6]m-1MǾ0q2:9D;ˊʱFLpam1r RxT,Gӂ9WKIM2K`ECx\` 9FLcS 'qLAa'Oi'"9_#I" ۄ jVCR.@[x 6{E7j3!YW]Z(aA9!5d)-z&n 1(Fa`l/+#}pp18qBHptJ̫| Y`1f2 /{VCe8t < QxgA7_}~է⋝Kl/ C\ik|8~pnhhnPxsxǃs.z>w9;9ލ&㿮H`3ck"n%ɠ]JEk#Å8\d$5.{_7Y#].NW(l!uK&rfke)gs4t9Mo~qqѯ<7;|ߧŤf,[BϹg?GR巕 ~R]P#}1vn?(_,ftvۻJ-en-Q/N2G|'!a&GuA ]Uꚕw xS-xZn\ߝ=.:"zՒm/_mV2r4Yraأ/)|fFYlvr|ws|+WMlzNHTKb9ڭc/LdULOHQɭgˍΆo@4Zt{AI#H0diTxxJ,HJPri+42K 4͸X CYRLbdfz+i_`Hb'G9MClZ(>kX/==leC8TsO B"YgrL^^r:tWBAlI 8KwpL딪v J-qJR9i]kNQ vn4<4=1k8,1CSS`C+j:3rC!Bj=H*i1$QtLI6k ۊ eJel};fĉݖZgU4]Y7r*2-b񠓭YrTb[[s0[l[<9|{idi lm'u兘V~Jlx5GĆWq= XiH=prhQam? #82FSicvGiQ0mUrsjk{'Er!m;UpK3Rn'֗%@DN%)$Ffritzing-app-0.9.2b/sketches/core/Sabotage-Detection.fzz000066400000000000000000000650761250202676700232600ustar00rootroot00000000000000PK8DjfBSabotage-Detection.fzr#G.wvcF~fL*i9dEHCTZڟ L@fd"֥_ow×'Гrzu˓=Շv J,12%adt{~ O#9~3»˓ˋt$7vv7+e#|=ۯ}3ϳKNFnf7_hbdt3}3DcCg}4}t~Mξ?eHI3jE͟QMPb-OEB- RUӽzN1ߏ?-PAh:|oQɗ։Wzg~@u:ϓy>WzjU|kZ7175}jYl5}_~?/Nϋ{^~`ua+-l#icg[@ʓ >8t{x*`6;! ﹍ 8WqC]:{_k$)߆xa EѦCB"{(M^˻AŅILgC=;oWIٷƓnf7gg>}">?釳};Iz<{?6_C85|^c磇ɗx[݄7<,~{V\<|7>?ׇK.{x:O77ǧFbEcgՎ_L>wu|}~{y^~<xcXirfFRZat~Ղ|7za<>/zV :ߌk6^:(HOwl4zp0Z=~ޏn&O7 }zM?e3qڶםu|t6$ng>A4g3'q;}8+C.wӧ7DuF_Mf8$ť뢃02C&{Q jYs]sq{[DQLZcX'C&mhp)T$jN!auuZ&gq/uj_){Ng:-p65z h8j۝{}5:Xk)bml4U5ŕ)g x|{mqw.gějE oa<LzPы_'GN|㫟mY{)ڍ;6MQjl`2&h/CݿζFz{$F߃tklӧ=cF׆_pCy,xFOL u Y=0o2rE? ʓ®EaK fi( ;g)5+im]v/ o]zKڔnڴLX*l&M  ܦbuL<]:=a|]$w .?&ɏOSOf1d6<^>}?eD:Ηe^G!wΛ!ۻk10; N"M%LhL )e JDs9*_sp])>hIyLcb-7RfP<\u1vթecN8uj|qY2;^ޮ)zгutJ +ɒ~4tX[jV~uouriyWɀ&&]RFQ13ef̆5Ĉ%'f-sr{M"i9y'>qXb̬ (7Q!bd 4qiG@)"tЎlm goHk yYO/mjIl5 Nۂi*ގ2W> a$``: ȘQd^{`9`JF`\תUwehœmSlTr-41G)8%lur }r7s)7G !1hʍ-}ӄ9R0b\Ėb1B_wIvm3[YaxδۖMJaY^|G/mNYPb\ç> StIayuEW4bںU~g?i#FCe׋kRỹ1KͮN|f-{{Mq^$Q~H^|?VX=T|C54z*_&"4._)d^]K .POv]޶PPe7~d7܍:tcFاF8Y9?6?>3o7r$ZMJީZ 6ˑ'].aV-l8K Rhf'i0@!E/-|$qAĕOic̬ H"\(2^¬$a6ŶiwƂ+0m?A3 TjG}yaIÄoEn&r[&tzU{LFS)pV|+]I?қWoް2nH E,ڎvU 4_L{S؁r~ggIlvj/5螳H`iׂOjj(60r8i $#‰vQ9(3 =38]Py̽yބ V!;8ƙps"CWF$2A3W!nE2ti0Km.Ź%]۫+8EFA::WW;!/CҒ X\7m΋";Pp2Is_0DIo0hjTW{RMʚam*@k &3F)?T baFpmnc7 pM-fg3A .eP3|G;剖pڷy9B v1'hl^^2|Ӱq3^W $o4w$Z[B\_bMIaD.^ogs2]Y*#Yu2jgy& :^MΩmhU,i=hWHIfdlRN Ytrܲ34zks@$vP5hB0a[ !iD^v[a^ē9uO::caѝ٧}e)Wsϰ.D{qOΊIœ]Ց|ߊU[R&Ϋ<}L>G5ڡN7ea7L>3&9ZZL>3lF[G&NN>8caWF%q%T+\jbSYr?/=矔(§h_tDZSN3suovjS@/]Փ=k,qg/j%9\&L4Ɋ^n@c%+ɴ4cHo-dVZRYFK)݆ 9g2"`Rj㵑rOcW??fV79&2B~gVZfP`H5U!͈hy) C23(yo#Ι38[WNmALS{IL?Jǝ۞:Mi$J{dr70I.?LNY&K8&! g1&4ʊ^n姼K5Io-dZRPwggy JriPF'U}zQ5Jff9k] `^rb+ִ?2B5 ɆleZJ2X97ɆnLZ㡮K4d4I_D錐}Rq^bmUHb10v,3E5ۗ#997YݛIЁ$*d*\{h X)5dM3`iq-ndV_/tJM(++vJqOh6qRk90'V :&x1ÍoΫ SHFষɶhʆEb%C1ͲL WqYMVu{0X'eI&N%JGT;v\Hcژ1NR.ȊGi 6QRf\ Qs0b͚-;Ewt1ͦ_̞>l$: 0IGE^ƫDV=Oєö0%Q 铠7 H˂NVmLZU<B-pŔ%S{+خ EEDl#R$u2BbEeN6-MHʘ@*&l)fdD0ų1&XEC/J>9͹(Z0h"HQR8$TmuB}Wۀ"  tF asWf.!tGWd8֎0'2ivn؋6sĉh 9na5 06V@L(9ah2 cdq\:uk-IQRD$E >nub̍SX\rX~ "=X,fҊVv$w[L.OmqIDV3$!oƒ+yhZs3#TPT{=0Q6=Rwddt%{ۀ#9[rNt[֕&+|2K,l+W<+oHmM(Qh열[väm%Iu(N-$#gFǝi1?2;kBrXEah(KXMtΊŽE9DMrB%JVJ>JfIGG7~*X2U<:͜.nUDPqi%13!놬KeN,`Jfh`Ih-qS4ց1ZZ Z=,;㚏&:,YaȰ`_6+骹O|-eFSD!_npf): ЊH#D̒DLZ&f3#ӳP$$:;GQKW E )wKkq '9,v]F3ե7BX]5zu Q2ok BZZđږE;k뺔-Q51qQK"%3sK # B.؛\1r6hII % o"-QԪ# %Ӹ6@$GZLE;SR|P.˵Gq[!G{s ]K99/e׌+[L貢( .i e t6丩j<yD2Y+# YQbWbPn٬D+:o؜xUI2@ĭH81b=PoY"0A$w Iؒl-qS7݉y \#m-H&ouF x41#2;k?rE ̬#3r`KRHLiY Q3?Kl*X%QjɠcKԬ0l=S|MmV:Ȅ%hYp1ە Y XҺӥbz/:ޜΩ&5cų2Kn6oEH{\luvZFo78KZj ::G2Yk@2Yd&CPwwf:&kbu0mtb`㾿$[;!Q\dJn\Mr[`!8bLc;|g\,mnע &G͊MLZ@ޛãHNt\ bw1fʽ(9!˂J첂$Ӷ-|jG~n3&{+j8QlEf+dLUi2Ka2k]6&R2kC2aؙʼn ĥNb-/k.6PJcM^mv֖)a&>)ܾQg 2 :ܚӝp[`e d*-uS& {d6mnˌļ&pm3.%/?eD2u_߃co ՘:&mmc̛C4XQB)+6ˬ-IDɬM49Iݡy\ `\7CYgqaD⺭PR)6;8ٸ'&gِV׽u?\s6Q7yS-p솻EKbIZPP_LRLڄ̑Z9<ۜPSr"jdD-9d49MrUo3 S܈ Qs-.qLؼZ n`^mۺ Y Y7GLLYW2&-kEqTQYZb)],`+]'&Ԋ] (PX8۰$-I $M8 ɔ,ɔޛI\ۢF3Kېn'"L6,c1Uy[Z8 .{s<7\H-"\M)dڶo7ɴM8j溳F2kkJ2kpY[]k? lN6zƂ{Oƛr2fxdzHf~qѤ?d[m'²NHo a,:SVZcMtKs$$zoZ@"YSĝI&lf)9a%bFӘpFޭ-9xX(Au aMm ,1IZ Zrq6މ-Z 0Z7c[k/ݗQS uW:ZLyLIiV>L8//-l/fn1tu؎Mnqn nչڄ ,Z9 y3&xG 3AKC2Ak?VMZ9F]Lg'!.* D1-bϓeLa%M铴7G|d%^Z7?21k;21YI1"+ J26g,`d&(2e`LY!Qú@/ήng>o8x@Z $~}o䲏OS?A>'_'wGf"ۯ_o7 3ƥ|\"†E7XծI}V )w)t["Oe#b^w1fꈤv.TܮکߪjI`+ڈWHuʫ(SQUmȱ dzo"9gwN>HŜ]j,ǂ&.TƩڏ5f繸 \Đ\&eM8Zz־Y 葩Y7GLjʻSn`BUkbAff 3,Iaof9p)UWR OJ6WRvbddVq$G88Vt*B hn ͉S3eKi*c1S8v 4),lh\no\&M(lM9jfyH&k-@H&kF2Y[VlY6!u(*dfBr#smeo|m dڶo7DɴM49j֍][ ([7Gcnwcl4~,gR,M]n?܏{pf] X)Fbo8Xwx|{q7"ƭr~*sPB͢~< Ӟo>ߌojQ;]Of?[Qkk_>?z1׉o}C՞eOPpCSO’Nq{-ɮ^roGINrSnM}% Yvrzx>ݏ:0=3y,_N\=0mݕ#>`7a~.Z'xxvÏ>_L^xK/i$flC2GV䅞W47sNo_rzu?~]g?1pq|v웟w#Fٷof7gg>}">?̟xN1FfW76ڛ?p{w5k4k xxa:rpC7x2%J)C73G[sCJl`DGV-1ΘWϏ~Ko5$RtppOY^G [s<}-7|{dx3ҩxno0G׷w"}QWi  +)3)%R:qLތ)"+٥wTÿ,?Hdž  ׂStq臢4l𳁓B1[\C#f"/o'\8U2pAMxʅ?B\BOBW *+tTU~ nOIw^DҸS/(C^'CMlh@; x8ĬǾ =. c O9oX o^«{VǗ,,OcS[;/ԡӚF>*4L6<24 xZcx 1J_iwfx.gc *4kac㧵#CK/xqʄ: 1{z~1_W^O~=UzĶOk="/>k?\F\}:רFqoZklg 9bS, |ox(ٷ84&h#4 `r CL 7L4~0@BLD` g'+xD`38a@0 &W&0%Tht:ozћ MFw w , C+^ &KQ;o tiy 0wϻ}"(8 ȢYLaÊ0D a,#'xA|,@-̻h(S(0 U]?-khlA}xe! =TUm0w:a;xǪ[C  '.?<h$mVN5 %c[cGo>{~8hy "$N! w72p#zqЦnj* op?檦Xmg4\i*];zx1v@C/v>(h߄3:USLܠ*' Ǒ`WPĥ]O $, E@W0S}b`pF b3^- kź {?`;ebl=cM>s?-LyB`TE*[4a1|T`*SA9QLzTU xe*`8> |V!5:aHY7j:> <qp;څ8dF%of`PYUӇJ8' $ r; 6@ }az72Vie5#~˂Q{# ZiEBP uX^ѐa 3j y9gԯw5mQyVC:Fh[5#?GtDCh ѵvvxa3O f6=g;V~xGc  f$ КK]0cixq~p` Kw\U.GF0Z @ap BLi8pqyW` p f gASUVִXLVc仏 ƅXxw\q.)afQt8ŲS%NbƳ(f &47ck8|t]dJutrSwZ̅= {`ehM06IOJ= `?bfB2i72(fӒڰh1 TP=$9өp>?ah 9Vq0m*@gW]4g@g?:xk=a[S?z´#ZW1@cbf0bt/G1v4^y@T#U @ri n !&%cLϙ"0&?C1jn|{3D; àΎt4K԰=@# cF%y2aX3w@T!0z cp SIbB\.o$p\Y!h!3d2|hQE`GH̏=x8t>]@4Ag<NDܰ`@8 Ŏ"0=G`,>0S!j4^=hN|TLCp6;}Z9eb0SDpH(] ӱwZQ5ʌ -(@i䨴e'8r[Xv=MD4N,97QfŤǗū$=(gBQ6?]hl ~R#9 bx"40*Ӈyj?]T*&Mdɢib+ &td\:g wUl73 ¡q1&{r3~`IzóF%~DS 2)CO34D"kcܨ+Zڍg'Po+[3{ U'W 1/S(EG,pD@!b.sdc㔋 SBo 2,ҿC}% XձXq+ⲁX*cq;EYEߝ'NfiIVJuZ+nNmi[tכbbS6Ey bc̑7)> fo|j<}>w&bυ#&LWx1+01'uH6_x'{4cgh?Ll%PCxo868jԸxάg4љWY˨|%wZՖ7_6WJ F i\()BUW8b /=^! #pt`sn,tGë4:.Gy86qRy-~zWū-–Yb3| U/6غ;yOeͿ}8flx˟Mg_>ݜ~L~5Ne|gE(?6d#|q'ۇ*qXZ^ ܕҬnp~V})9#hm#jvT[1{'K u [/-ry|"Ps+0(ok! SS;k ߓ6JuprB2Y,X(r2Uuy_UEڕ;׬Oe䦭l߾eMYثw7٢M| T"}H5k;o`S[}^A諷jSP˼z-lP-zPZR-Şxijtbe2պܪj5MV؄Z32j9jzPى8$ohx0VZgƛW-lmClKU"D7m5pS'tm4K 5<^=hɁڴ~mކY,h'x/&fXA1ko/oDUa_ZHMpY\6(ޘz$[Q.6z]o%] %+i;IvWJ@'RIW$]0$wO$"~Es t_&઻;YZcnB)Ko7^$I"΅-Hd˛C7)I}ĝzW-Bd7W >US$ЧR$'=| Z'zP|@S֧y$_=zhpsoɐ)SìG}-S?>2 ֧Kڄ/L;uybO\v;&XuLY?}yZyDŽ_oC'vkY>mn{j l˽znTਫ਼ʘ>5P>-ܐ<~toujkc]̿߬pc17gO釧s,n> wTﻶ dn a)U1!K-7W߂9 eΖ2$e*;_S5D;%TLպC߃ck\I@A $G:mѥ$#"@!t88z2Zl޴"ɼY6a?+$W15}̈䌺8XP;v~%gW4:L" ZC$^ jmXci!hϓ96dV$>d51[Թ n - 6[(ۨ1kn_NtyCAu<h;Ųd9#%zGߢ u qˬ&R¬gnWpbxs?[ĬVvlVN6]~;3bq!PK3N[hbi9zy@D6&Q䣦$,8mbqSC^@'e S!kˈpHXW2K+sãIa{sxDɴm#)yǴMbsŠAJ۸Zu=ARo[˺t Č!pCLD-6%!ɠ?D8aV ^+:ѝ#H q$g}k`j,ƐI[n-V0X[Y!%Ӷhi[Ƭ6h["vI&ɼE ɼm>x[(q!t6ЕKmjv8ev3nytѸE5'dВ9%Sh9\ab˄ˉ7H(v}m~Q Hy\hܜcg fa*YRʜ*R0 2fѺjGږf\3r6 dvx L%8Zh;^˟H9t.lLZl/+ںH6y5[ 8 U87v)`9>9¶,I.J%J1"l[hyތ-ZڀY] 5wIH*({dR\$S-*\dY43Ů7qpV7%B ;e'lŊcaӲ/#Wl-#n$H.Z>)< ;[Ҙ='?2M;<:Dr@4Mu:ݍD ˸& i eD^dd-!xS8/Q췴!ux9d[ru1<4.^&1ņw#[% Hy-IDB*Ӯ4QqUL^x#n,?ń]2ALmxS/޴]2ATH&GkAue!l^GPmĝ?r6]0%zGիhzsezu\ [KbIS2;d(ɄƩʡ&/{^ SmCH&iSk ;;D;8Y\BEssjs{GrDE,htX3EcZI~߱(&VNҺ:HڢaAƶZI#K-aN֙7;0SAS+ ,Py!/UX/v2lrdn/,w\PH8HjN( Nv839qQz6xp:XXaRfVXC'9ײM,9Z򦖐Z4'v$96\zo&pJL// .eK0A(32lp;-³S0+]A+9w>"kEJ/P2uKini*k\਒[[r-E1Q=pu.BҽNoLJڦRDu]b!NqEB<̔ZȘk9n޸`H&fGLZceucML-N:HZCoLP21%c TKfc5SKd ɌlhDc`dĐ#[4>ʲ~ mCntQAV5i)ju\ fn(1Jؽ3%fq?8-SQ1 IhBɍ]W4^E~I{in\4 ]AI&iL%G>MmPt+⬌ĐRBn&i.JRRR6CV&->Nɲhvgu#HRuD:m˵ޘlYdcoZ0ڷ %SăJ./OܢKC#ncB@ 97mK9rYzoZ@+Qg6qI.K_mc,䌺\Nrh]97reiZ!Ar%8ecu(Π\HV:a#Ӳ(#CP~WZfei3XB#FXcFAtAj(zjGɚ栰eS2kWV!]  tK密&9j&kv5;~Wt;֚zZk!5\sHͩnɚщ +F|jM #'RSMwjזvY90fr 2D9qѽ2][u+!%0wS$Z@LZDG{.Izվ1cHg;Zh&l;YXZ8FY'p$.'>MčcGg\xZZjGВ 3r&:qU Vz.C|Mj2Sǰ rjGѧBv)Q2_k Bs8V&IE%6!H&n-xpgPK\8D:}#qSabotage-Detection.inoTmo0_ᏡC8& RNRҮEBjQb!>;!aQY{qΡ!3]=($7;%00)3ڧ6IlnL45Mf1?H GONr,LZu 6ff\rSe/9Wu]ûC̜BvU`A; rP!uI3hh.ezP h13ξˑTX"Kzu.% 0eKZfݠK|`s|I]UTC[hOӷs4n)= \-]m$.X$x~Lo~[{;;ꐽz5udV] H@Ӆ| 렔2:WTW"Fh6&PK8DjfBSabotage-Detection.fzPK\8D:}#qfSabotage-Detection.inoPKifritzing-app-0.9.2b/sketches/core/Shift_Register.fzz000066400000000000000000001000401250202676700225150ustar00rootroot00000000000000PKȝ8DV: |!t Shift_Register.fzrȕ.Gwஉc_ݞmgv{ft$$[%i$Uey NfEd&%A$ ZߺㇻɧohELfWxo?5o|lrt2~WZ1QwP=޿9q{xzLWxśwS>L^n_f_ |2Kx{緿u~t۫/ި7/Ȋ+N{ygD?>=VWח︢g_w;{e;ϝ,_feT+~~e}_ng?tcr *;ɻzx?]7OWy>3yyO^t9\ݾ^/=9_1˛ه^n 2+KO?|fݼt_.2⫇YÇև>]\ӛqۛϞW߼_ Ki>۳zuEf@];̤yg1W_Qʮ;"g*Ɵ>G7RX/u3חޝ_><ο~>-K/4įۜD??[s L{uhO=|<4#$Tg$0R¾+BLΏ8м]7&Q@{J._LiqϺ1/yvg\j{niηUsno7YDnf|s|YJ3Rsl2yNo-%,̙e˜̗4̖-s~7h>kPA[ N:hy/Z>y)A˼^aZ.a8Qe 6{@n 1lԋ);䭍.ܹBg׶d Vbh#E^"mҕdCs9l'(ݕZ=,Ȓe>p aKV8aǁdu28ν syIBf̭ԥ|pf3l \[&f|ʳ3]Jsl"OsN]-caL,˼b,Jmtf0hyם3z+%}g:^K@ҔjU<~ˇ#ƃoQć=7T)aS uJ|UJ|5J|e)#//MEa%㮄/RFMu!ʸK &/lz=p]!w=l]!10aH0u˶N]^07Tu/MoQjeEJ|=,Dw{i|Kq)<(k/M#ﲳ|]^ 0a޴|O @[WG^^ć]ݰ@|0pܵ {ԅ9dcz,Jf˚V1G^ވۂlW*as E|E|E|쥙,#a/Osq(c/TFMʸka)g/n)>p!o9>l!'8qPHKT]^:7To/OqQk5|0>4\w{y*˄q׺*<+w/O#]^C +8qHu~q׾)W)AKHPBbC |2y|qV+ ZNrofw?^}3v̤yg1W_Qʮ;"gʪ0`7Nj/޼ϳ?ܻ7.ϯn_~sxӥqq|rr7oy|06\V(uC*=ŠReX-"o:Byjʓ4:yJEbz渲%a[}R2-G3KΔ}6aI:s9NKәe{:,o;BY> ޙS ]16BYǧ3 )Xpg#Dgdq*X||d}ɇk w25> QhzDž>y=Bhy*4G[FhоCI"THPg-L]pӣәE(#wӛ''@}={|J#^8d|faѵk#pUpN!!-Iɵ6Ya> w"@C%*.}6Z"UEN;v|x|=їzH|a5(L P @i{$\aaR= {=JԒP,X#ԒTaQ@Yy{6G%dڱ0aWn#Dbe=>n&V! D 9*%.J#r{҄=B \a4]_QB e ||zR0B5Yǧ%uii#/K#u{##/mz )V#/Kg[S6BV4aFyM-?}|y3pr{MNA-ayjd^G^_]_$)>BQG3twyqwr%Mˢ=B}i KKԗ#//oP_,V9cq~c(!|.I#1|=B{dq 4Hm9B4*7%b diO_rF4qPO(4yc=",’F(O/G& ( `?7r~~ǻ]^f7[7?͞>>]Ξ/^ݘfϏۗٯ_~_/MO_O~Ƿ_LJ_Mߞ >'ݼ<~v~?T?ߜӛw?<^TW/Wp/޿M#?nn_L/>̾_ow?q\q_4{^姻ϯv&?ܾ̦Ϗn~6y|MxxXꁝoOqO˧۫_.?yy}Oav3AH>\굏;Oo/^^>t޺]tx Le[7ݻgѼt'b=\Lꭴr|s{2y}~=MIgW0&f|pr3 s5 @]ۜx=p',KK<ݟс_W ygDuk B~=6G~ϗC\-M&L]m9DEF(4lXPJM!֌REik/0uVJ%Oݨh!.Qc%:Y*U-.AA(`ǦNkRƼԡ͊$6,vМ(/5wݰ ݰ-7熅)\`^XVJLYC,~6uVRoDh>1/"13u|nў͝|4tÑU$Jq*,9ljqrtܢ*[_p_sE٬Ķ٩_B:+<3qSkS>+QE_t|~#DL-3!s"';fu tܢ:[R=t[tDnQ^f,[s?Gti]un:+;ja>nQBq2"-:RL>Y(mEVOFYEd GVG[t|ٴZ>9׿rgTu>}?=^Nq^Q5ofW8ϫdtYrPJ*P)S%^ܤLu)"RR+htG?4`8A3D? d Tk;Hw UP'tLHyeTTJсoR1B-pzwZN5_ZolcѳE)7t/8/fIq#lM]jEc78]ʇjC"!zE`*+FmM^ T ^PI܅mE+$M=|Vp>ӌg䍙qF3z3'bg^}HJ_}.ݽo|;CϬܹc ;5߳g\D|lgRN{lz ɺٱJ" A0w%@It=H$X>ܡfg RYig>{m):fM~}cS701F xsDA;M)J|6%8r޳\Dl60y}Q\9Y\v>kxJTi6u ;Y=8KTIfS{l|P1}ϋgf}:ucl0̍Mz]+_-7- *;n0[>g>/zdY=}gwg8-w`c.> PbǍڀiw`Ǎx%*gV}9Y|&< ]Z Y&v?5G Ҹ%~fp?|gߌq>ẏrRl{v /n}ygN 4K|&F^n%8R3g SS8͎<?Yo3ӊ4`s.7x l각 myRYN)b5垙Z|֩^0r,oWF0pVW)ieRٔEȫWʹKlF୯Y7 ڭ'u,祐a j,{s*xgX0%!w}%ދ}$JN$qeSNs^tJU%۶ǽr:IrL%c͑_AS_"7OSw;I짦A%Nw"$vIyi`a4U5Ԏj-s'ٷǽz> ,OvL'K9fb1TzòjTVT.IZ~Ir[UuebFpXZF[E[`KL*.aP-1;$(.14ĂlIA>إ܂l9lb}WIJ>|JE]b>GhEX͒Y!F |K|'{<K8[b ;$g!r|%}CgJ j ڃkõfI0JEjYi;-Irv둂;4*xO׮eSx3tqq7"_zP|x]M>=ܽ\ 7B{V(5m+x۬Qo/*+Y(cgw'L{]4뽼8qOoJ9ޕx{}p۷gjatݻ)e5^^ՂVY3ȇUt႞], ](FN*aV&zV GY/eQXcC-OpLB#]KU]i8 OWFqsN N.I3È+Y~H2'Te+*v4{~t9{>xzy\pQ+NlgJw#ZѫF+Wɾ7xtVD~t*y9${f݃?__VjJsc"TyjɱR81gӬY. EޔSR]#`ێ. ގ;["xXp$+59Y)ɐ=`@J!Xݕ׾tA7R.=)'FJE"%1G `. 8%ԅ^ 8;N$=>:\IGm& A*P2,LqQqKy(KYY 9p.:uw7Po g۷<`.F'(D FrZ 5lc-np$uc"xpq$5p)"ɰ>\,L.Fgf4@$t0Ck㤬 QrottysȌ#p5XOEGaW &'(XSpvdDd'p%3`6sR"b31!:ީd6\XjK5]CKwT46 MH6jE'=:\0IFSYN4Ax2(QTMASef jqoES56~:1uq4,"pj iHޔ΋@aÅdg%$Շ&39݊R̻i)RԬv@K2V|BUk۳gHTPNCUB&چU;;t=/E(Y7I2b*r! 2SĒA |hCJLMHQuQVwR;$7esS )am Lob᧐͞ ~[(*=vڼ)3Z-|),U*M^jX+'i3TMCd+{|ʈS,iń"{CNf5CդwY==ߎ!9 d Yf`XNw#wAOLI0A+Ri5$eFR7ɒTK" G[ ԆDS-cy*(O8lBm3am8=rMYZh<KU6F]NݚI}鼳17bQם>'?Ɓ\^*Cp'Ma%~=YK}V'k=b:l0IN RSēa |Z}WSLR2IeF{[TBš!JUd /YEFˍ EHMbi 0VڐB*5P(ܣc2R{`fEd'%#UJS4T>0밯"D]O*NuDNM q/It3*%z mQmɻ_yy('m '~6o36R2H"C I,bZZH\Xٶ聙 3@rfĔUA ߙ0ݷGc`C)BhA 7S F iY"I%)Rt_m~X-tnIFY$Hp3`I>fBDfҦ,)*"{+58*|Qik=9.P[ -8Wpڲ jdiYL$h  ZBZ͌87q;EI2+j}9f!hckE$ YgdY>+9ZAD5}h*3GIV^gƁ,^ȑX蘳LHXV$HaҴl,-! K4 yYZcOUncm{{+1gljP@hT93c> sfx7kI zdX$ CK r!guh]^M}8icӐb17(#-1ia&RFp1R7 ҴDr4-!,-~ KK!?,M}XBg Vow%Κ]Őo'BqXPPm- ,M[]"HRlVR-! ES4,3E*fن*Q!/+pR1-ud_m&a7hf9KI˺H,AvFNz/Vȁ,!z]r9l^E[GS)4<֎9Bϐ`nwFuWyZ"9m AƖC%dl]&(236R5$x%i]&>Dfifڢl;|җ#]+Е DFs,d"]# mWҵN $Օ Z`|-6_h oK#B .oӇITy]0$ _+sni𵾾׈Y~8i5 cZPl-6[` KKB.KIyYZ@opi*mrGVDb$kdmZC>!HIr(\-! W[h%+n!3]ӟuhH:/yIp$dq9VL)Hg_ YH(¸Z8IG=vŐm9dn $h{ (H:D}YpdMK\Uڸ#i˹Z\[ۻ'3Fێ \"wkrwIFՕlXV(`-6wKo cKlK!ֺlMe:!oF+cyF!+%0̖2bbSnbl2t'dm% D8rڬ-e- sK#ܺȼM6 Lp@1!AJaJq9-H&}UmZ\I*p;2%SiSl HM- .^ڬNf2u{]$X]aƆd- !$KLƗ'tEDiNR4 {K $C0l& 2(̭;Ho68 mTж"\epP7GVJAd-M-`dB X۲h2oW hkQK+CVd>đǧ\ f1ұ䑪y4Tr],n ΁"ޢdJDݠ$hz쌭 #r#غ9> cNFz$w5l,mWuJǞ-R&=~ogS$ktD ς'A"?[uЁѴDq,,|`-! +[XVF*_Kjx4#qi9DbcfRS:~V !=+@0|`7t49ˑޔM`nNNm,8_UFH͖8Vpeun.ekEHG/NdJ(9yl P)[w4G-e΃l5$&u%RQX$,D=:F{Zض@\+J%SmڟA@uGD0֙35;rѨwdƃ-"]E;c9rF^(K[46 2 ZJ9ZR3Y@vci˛eשJމ(҇xMGmkGVRrkBqjzo>^&akҙB5v_:5Y4 uK 'Mr' 2h(>˼77lY[YX>_qk#ZaDVa40Roc9M "j$%lT|;l, r":wZmPrF@]a"!) bEqEԮm֦##{ !;Ko CKZBhقh!(]7@0ḔR He6)Ӳ/ٞġ=Q5pk칛dlWJmBtͶa[Id[d2Q%uGG0֙p433 >i%H܎ͱ[L el|k<ѺrʥnN37GV eK *uKi WKպ9>`̭+v^#ek6"֓yL?ihB֕e!ɭo[5CH\Z&gۋndAq1 &r;5ɉy; V\FFz۴>$a癷Q./3͟wogVj8 `*)#Boi6?K)hk܏ܤ2%pB^HVe=쎎Vz-R6;^ gca8s"t K\Cg:csWFwVBs10לԹj4=ૉY&ظ݀}O9`X٪swl`7NeVZ`w4LJ <MSi]Hk_Հnځǩ4 A-&q1mn% A?ke3G<2r4rPrZ&7-L筭[v`V(f:+bٗmp-660j|lչR")s<& h$H: +#FR pI*%vw=`z\7^U`%uaaԒI%uGWBۣ  1&_ևDJc: h'IH6;$G64QR;5ɤB'ѾJ I!ժ"X"q ;JXZbqIŰ3'+on}D D-l eK$`uyx [^GBQ ߺ"f@HdjyᑕFڃMɝOj5@k;r,L Dqٛ g)  n.-s=n,&9>2J$W+O9,bS FhrW,*iEFRis<r0h%'LMaħ7EIMy<{z>ý{=W׀ |Ŀ ^0Ňo‰o&.>lD~緿}u]߂mz.v7*SIտ*p뱅u/ew O ''|VxA"ZM3)6MNQ3 Ekwz $^^e8G6K \(R򷼶 RH; R9py^0i%L2&#;Lsq p=cXprtˡj­:w7DA MNM%@pM5Η™f]"[k981 j48G3ewxAW$ K ('K2'@ h' 8s'Hfד)T(ތe$80&nhS:$nkF 3;4.%,k K$⺣9> kX?H_J/e,pQ&XАz쭰j-ܪ@ {nP` o? R)AFuGs|(9 5щq5YՕ5DJnSǩIic~jfq9Mcʌ)t!P0ږLrH6AJuGs|8A<D^WL&%drcu'(HZ~[9piGOeX-HzR&wJ|-,,F%z![#c5Odgkefk=>qI+GM?]buUSV4k.@"][`-%j][sZZw4f!7\uY+m*g]ܮ2qXG~7%~p$=AZo?AZ,-Key KHźA*yx*PM. *kH|=򐐎kJlq 3ث$0!+b^wQi'5>% dL`;*s~%Ӽ-/`c+F3F \&!SHBV"1-=%@ uG3B\0;jt,P⻤DU\_AocX8piG' ǖy 2bL.`l,~vl,݁<,d`X,!l`X+u-И:3S۸hlI8Tvq妾1*"+F0*6b[Kez Kf`.vfB\l ƆD āK;a00ԫDX%ӎ?% % uEcR7fs0Paːe/;W2MgS*-KU#.m@KW$`lLn A@0riq$ d6Ҷս1qQ~Nw3b]34[eU0)%M.`,~v,݁<,d`,!l`#$3VN*a+/%ʛ)%o< Gd؈yo1L,L,d`D;rr`b63nʩZ!.>S( \ ae:^%XKVFAIGƒHbǺ 1-Rl|e0Xj4ce3c%[_(3rY3IZYw4#4uCnNw?:b Z f=9JbЬWf04 DqDvh!/J.3 AQ n,NFvVJѕLċÅ3t'8![+T06bn\[j K$Kf`w.R/-)u%TLU-e\>31 ?ҥ0۱]mB0f3x #*鿌Dh[",9[&[ \Bܲa&tf+A*)^.U ӛ *a``WH srq!9RMpk åӦq9r CqP-Oݟ?= @i+n]a27hx\Byȁ+(RiV  ; ɸ?oSfVTᒤ2~G>2V) ̞IBω/,RiV `|; ɸ?3$3=H<MͻދL, zGs$,ɱ<Ȃn~.%6c {K#޺9> {FK~hc&srz*?{/ea@ekh}Jh-Wͮ2IH}LI 20LB eOLJABIFV9$wg)]{b>; k+ $Go9Rr,en_ѷ|`-%6i K&tnY49<'j ⑒ou 7f4.%6i K&纣9> [|NsFJKR7NVL% } L/Q$oklpGN; (AGIB,Xܲhgn6w[ں6k@l,GBVw+80;#$ϽCM ]p^i ,K *M(H@ Fຣ9> [\Ny1a^ c۪)daa2{\=`sMܤ͉`!y\J89m>A&LuGs|@A&,ݨH@c}ZRf}L7N+J^6 s)A\N+\0A>ܲhsdsupa`[ҙb|y띞HENOb^HCEq-NnC*xY!E6 +TΥms>A2JuGs|89>'~xW9Ø߹ss=>=8~iraśn^nL>]}t(e7̛8_K}Uqb¹CMx5_˯wOۇ/~I+r=5_/_//M?o'=?/'Z/'yyy~~?<]<^>K(^~ٽt:~tg\=Mxw%5rx~.^&~In;L~jBy2N;7$q/˯!~$RG#i;,!'ʽͩ?EՇn)JsIFN}}X܄pZ Q۔Ǐ׹㛩 Oԍ a3/HP00@8Z\{Z+%>o("Oe؍OdwNDB3'(ݜƬr_"*e$N Lw{x>C+n:CVK 'x~nAҡaRTP8{G?gOSGxݼu)3pHʭ? "Q%r >9k_OiF37:[\yh92L J>njox]0wD@#"KLT3T0(Pʰ>U>M@D Hީ82G?e@L&=L}XF׸ #L Ƶp oQm5'(m O?,i݀=q C'~27' O-S26ǎI3W:< Om|Ek is!No gݱ: oDx'2 kD֟^O pl>wiʂ.39v^idqCɺ(L0Y5Mkxq ϣB-*oӳu荿|@AH˰7XڄqIb s{5t c a |̝OS @iKHJ q8QgyhDN92^ V- ֗ ȵ?6KU1y_ُOv؄ZK$nϛi=gXX6a<ycc嬡 NCrX0~DsLJZT(ܲc~`"^k~3P1z S0tz0/$:vOoT$VM܈7Íx5 ܄Mg9;ڭiW+M;cіi펷v{]g(%զB*q',&aJ ' ,0,V8v^\/)y}5)c>aa t?6X+zٻVPx&a2Ql=ʚcM>oq~wk)ݯ6X4-uжhdˢspQ MD UzTlR hTa,ު WBb"&BgX`~v.|=s,.0hE% 6"l eyجT8ܙ>d fiX܆|Ӱ$,(0wջqn̞VY?g1oG)MY{qDZE>y1`q&.=VY!a PgAJ (Kx̟Œh]Xa蠎gtŭ08P&D*/`aE D`A<0P)`7e=T.A\" &YU?ݱ{F}:'C:.( 004s9 hgR@K6W, L{&!cX0azQz4J/, @iTz6PP$17sZ3 C gS Gڠ'4\T}Xvt Nރ KQ(\UwZʼ5,X;q^yE`uY3r$A_VCKJEiIqJ^B@Y-q 20`*FT$! phk098*`jx[a!ϛxAuEjf+O~a$|H M4Y1 '(.u78ER6(ưXn`r7T:&o=ܹw|yM! b| N/G4`$aW:LGa9l gםٶ"r퇦GtDKǧRkGtg(nYկ[5y1\v?BS\lo*fnF*#iAl {`*;Ɠ $`K\Ac)xq9|`w5XXR[XӚ* %H8: `bG ;QDb0$zW`&@O/hXSSw3Nk#0F7.]t}+AFwQТ. k8':KPbƳH0+hPhvNFmpYGs;c(`li: n9t:AN@sx`]Atʽd'lSy ry=­yaΎt(i5aa0;&<֔_T! zL;n>EgGi8nlG+xV;Q``1FJgO 1uc'O<¤1NnA45o^$:Tgo8 HAp< 6?nوi"];թ[ÀG6B@)r@WHt7T1Ϳ~dp?p+, 3tWD%"jD"KN]\Bv[}ݞݝ{CNu9*Y 8K d< XW,b`!S`21|-A{)=E|~wM(OӅo0pIX t2k~k@!<lH~aEn !@3?GG"%  |Fg:dIO!? 6 +LH~ΉGs8Fo: &( ଍7̿uoAʺ7W HCw^:1,8) *5(ఋK"`Uƒ5(~!6 ^)^@sSLoF;; p&`[g=ډ Xo[`!zaE Lx?G8.K 0Xa@Ztx 9Fs#cF?>k\ 21bASDp@H*|+tl]bmk?N |#$"82Qq ?Z6 ʴ 8ՉS[!` Txa0?,bQNq쪇Tï3b=Gcjc`@쏈Ӗ k"iKεd`&`W.$9W]F$gQ Qkf1vee9e  *><$ 8w$HL H\묹hqG33F| Ayrv|4!N2 H|A"@LA.aQ;]֢g bK " @`p`G \)p`$x{RNTk RL熫j&̮hhĶ,j5 [>>0m?VaBTӊw[Cf˵5HGzV\TJ[B6.dl)F^n!O+TBr.TBe%%TPy#T8X pl f2\"L07୓ TmM3eZ|)z+\OvD&ԍA Xp΂TA4lb& jX$a`гZ9G#B*\4C} dn/@Ӑ5)}:܈gmÎGR+Zf/] e7A s:F#gdw !m_O„T`%i8ơ sb\n}շznm{|Eu{};-~l%PQ@64Ψi}giϨ%3k \ VLp4Zۖmol"M"OL4D(<{N0 ^hNb%f-MX}g9u.\"`0p9Z c[ύ$ C2?QN(|>ͽsedȉBI|\SgPBN ?C*(XmnX+tv.?+'in8`]aE͚_]x 3헣j9 .QWh(q χ]ׄL](2f@iBn088`hX?ۛ6Ax?hcaq_.]0j 0?4Sb%3.O'@l8Ep\<)hn uL[zgTڙt:>9{}y}7/߿̾ݝ_ן7v Z=^&M~u_R8·wt$cƙvU%YHpRўfdÁ+ڪc1zov1qͩ~`qp&| ҫzm׋Sig9>}}?/vjYw{Y\awo\,:z+:k?n[[Mg> n_H/OO&(H@YXrxͨ-N}sv>UkN[8n7,Br ]rAE)=iJq/wT)50ٴE7I2ݞa8OzD;/-.4RO-:4c\S`2sy~wl{{CZnsnqSOq݀޹cZ^6Fm0ג<޶ۻ^wwsf>AEq y>W@rhN9 o>u|iO=vGo]᫶bha+VM-sq߆JX߯.rUb66:{US7_=쬵[55WW6nۉpYT/](nX*O/wE6a}.!wt!Ro#eY V E! zv$nَVf}9VnvE`d*&b # f9=t+ځCd#Ȱx ZB,dž&Q.DS~p\F)8H[4@#Ҏ"ɲW!]fmݹmN!]J`@mL9,ici,+ U;: UK"'Kr@͋%S@kdL(2,aok _I4 2@m.Wn@b0F 6zFs,ѬX|H|-lѡtOTkSV l@+d  a 9H]gYnNa/䃙*,Z`ݲ;- <:| L'K^ayC#聄lNZi2׾x׹HFf3#T_kb 23=iQ IёIZ"9U k$AK3 swdk aڜC5ҮK\L-zCˬyrDq$Fm!7@ ZBA6'h|43A[HOb;ˊK$h]Y6Gv|tYbX A` A Z"8YZ#K$h+ >%$h A)@,3A)w[Lx\WYZhd,͡Ȋ%HՎ$HRW# 2;w7 AG;_ڲޗLٔJmbH3!=m9mFWLAvtDALN-'ZqJzxƏ,AOyAX-d4 ]Fٕh*112wVR7g)\0l l-~,[{BqH$h >%$hsv"23AS˞,̋>m IZh}SLEҖ۸aZC H%%j#)QdC B%$ksv6#*3Y]GW۹%hZWy֫hZnUDYJP919Z"8YZ4gk >%g ?c ,6Y;V$ž!)B{ܣd="'2 ;:|tnL{^_wŕ6i3#zP"CW4D!"qm~˓qG39IqU9xMILxjvD.ujL ^xnT27/xTQD*οڰuTt{Ti/T!'=>Va$2!^v6b!] eY`dĜxSYM*8( ͑rDs;_p mɻ_yyJò*l.d m &*; io@W-.Njҕ Upl mw4Gó xYϊU$,qFJ+R):qi|=`Ľ屧NPc# A=:0QA]=Uƨѡ%7\Z7QpO.$G$M-f3rD_m]Hԡ6isg} #gHf "nm(CNn{1RS) ]InmB h'Fd&b٢r2JůWm0y!w4Gf[_"8C|t0KA~HiyQ,6vniЅӐ  ]iI r"C, \v]rҢl 1.+vAWr2yXwoE5nb,⣃X BW2lHw|6!u1,Ʃ4W$ebհB,ٯ"*3U]8LN(Eb_ wvA)s'}X`r,s rX ,G}XW2!k}C(3$U",sg}DXV6"JQ/[wfd?r{Qel@r4GN'VY с,vWc9>6fUҚpkycg9>p!!^̄nY/J;mdORc.()W8xzMu&0CR|t(KA)Ƈr|˱%T9vH0py3ynlhVH'DD kT֭mՊB/Hrai.˕.'-m ֿLMVtA~ztlR( Y@mqJY-AXD^@f Ōa kIODfi. .Ԋ),$mE}[Ö6ֿ֚Ll^xAvtpA֖WN.iV\ͦwW۸},,28yЛ̜鲝EJƨ*hBI Ö6v˭al谂-6uyOٜ9#@퐶4i[BAڶxڦ27l)iꤦ/|Q#_͑DxD-6Qc]ֿF.ʯWggov崡0*Q6R0IU"os؃eWofONƤwXljdE.h/mOPPD{M+pLD Un}QsvҖֶQ͎\巙8,mKHa wIaЁ$mh% -S-n7hZY3=-#@`n4qs3xԲ`%H"-C>T(ϵہֺ|b–( _}sZABIst [=z@i;HA }mѵ͜oj8?K,9No#fCm-gVh8R8I piFHԵ&R+q,VT-8j Vڭ Nnێ/ pY_qf%gθ~myuwlьbP1!^T&=⏈dx8.ì&âb 7G 7of9A5wݷ`uU-p9wPUJb[A@ {%u]-Pі-J?~^YnAi﫮+u_Ti#-9D hY99w rIci_2q {Y*c4nќxъse[Z1aX(7=5zD GA`ԍ{q1&(A `&vܺlc&iU-Ͼedh iXҦp `VhIo2xUDHq^g,9>8ˉ{{Y>pғ!35#Fc">kFZS13`QiO#KF%`d ItU12 0En"v䎯ڠԽ6W5u߿u.`_M#o0Fp?9 Ӷ G79f(nX -"EiEVWPQT#Ad&CIg`BiV2E8$PFP5Njҿe-;K>ѿ,jup}9Yۺt),PlqA.r|qc[{A_MAlXcƦBډPU[tB{Y/'li\x~Ғ3wm XZ*>C ij42ũ~Ē( eJG۶G5bmirJ; b4p"Ȁ{g@ѵ415g 3I`kSFJYʥ*J!FoT\\aJb.KˆYrx &8`bɁ[(:F=qv~.9~Z`.zO.j [XMiB*l%,+@nٸ쑾e>srK6(EW$m )@z9R-_c(Dtާ qq5nȽ=323ֱ3z$k}M 1#KIoMU#ˬlw)+wyEdB\sZǭlxO xXzp d&=Zl⍫Kae+[f<[s umCh\W;"Y6e:r6uPBzAH+v*N'{_.ޱIj)+%ZPR?DV| h!e_Mpa Fp`6I'CǏT}/s}= 츤BK)Mv4w/tyr֝TʸeHΥEu_O|k" 푑5ѪⰵIF0m 4-9L2ЈlӚ37je>жa4ӌ@spPK8D蘒 Shift_Register.ino}TN0}Wxim(P+VH+'qԎlRq6t̙0s1X-˂0WN&)gM,+iҠe(Z,+ LfPn@X u9B>01f-Ks80Ѕ=!| vJH d2QC 8by~baE[tឭaEGQfj Ӆw8QHH|u/N̑ڞhQ:OЉ:XV"Ψi4C![K'~bE9ҩK4e eϹƙ6~#"eBVLK8 ~WQR>.<vb4jآ¿;C^ia9a}^X ;ya#Dwr8 t!L'ONђ\I.Ko7hFפrSM؋-& #X8CeݹS< [kO 3gC(|PKȝ8DV: |!t Shift_Register.fzPK8D蘒 ;|Shift_Register.inoPKfritzing-app-0.9.2b/sketches/core/Shift_Register_2x.fzz000066400000000000000000001375151250202676700231470ustar00rootroot00000000000000PK8D1rXg]Shift_Register_2x.fz#&%[iǬҪ֘u#Z-ifȲ2YUdy}} 3^2Sj&d }p?\Ͼ_<<^~j嫿|}Ͽ꽿vPF${jvu ^UU7.ۿ^5/_}?.]\,o?\/?6~jZ^/|վaV?Ͼ]<^tzQz:z}\~&2/n^>.>|\~ 3Kg#|spqvU-=..Ik&rqn_/C5_?\~{5kߺY<|կ~qʌg=_~<=oo*5~:\\^H'/B^XЖ[./ٟ?^_ŇRY{Յvֽ/no{X_֖kٻp]u?{_?^><\]꧅>xU?ՇO񛇻w+gxqqs翿x̢~|O̬>iyWgW˛ޛ=_,Lp.1}۷OZ i'F̊-}u⽵ eY}YH#.wT-?|qHzG=W}w4+7_=+~ yiMY_?էg^}Ňb'2i^* ̅"ZW+kB)U7 Fo+{r|l-c%_LqN6mc^?v8l8{F+]=,vl{x[6c3* 6Bfs!sxm.dmts/ (u ?x^Vg3'?}ΜwW5K=hpS^ t禀ߓbqjq}wULޮanL pYn7n +$^&ny)Uew6&cřd/8q=v3 &-n}(g|e O2ww42f-I=@AUeNtv/ߙӜa:ss9,[omvMZ wrGrծ֊Yvr`.;wݦ.G9ɝ_C9Dgk NKve9ʎnЬ] .uw;WvRvt]gVL% z楑A+nhRxsx. a;w? ?j̙Ofx=ᙻUs$ wtBi{yJfG7w9=_;ՋϽ9}\^,/vKt巋յ.}g%F\2Zhr*㗯~q?no?\-xrƇίi?ݯϖ7˫W_oΚ֎[O?yPDS}8GlMGW8V~ $>A₴yq}Ip-lۻ4uGi OJo?-`{|߀|{xk&h{f2孙}̫L|̼ d{s5lEK9{] yi9@–a~Kfa+ؗ`B7wiI5pD)GSКL+楹f=Bg2,p/m x{ߞev yiL(0s e4M&^Y0M^=|.E7fZ!K (}waKg}U`.p\Dv3^];MB$]KإJ LBҲwM nv]%ErR"Y9plrDuiiV0dr. ] 0܆m`dKK#KsH#:$F&waK$d[1 /KsIa> h^&aBh.)m {KY$)7$@4o{ sJ aIi> h[ Gu vi> dNЌ] ؅-æ?]ڶT"Iiɰ#@5r،.lmVa6X.mMKDJ5d)#@ׯ>Цwadc$opSp B3va ؅+tLJ}ћ_cNjd q{OAC m^xSǕ́] 90CQ0 =)#)^z  o=)p7]/zY: \/yAvOJ60ls,m!)^z ܅x]IigwA'77sO@@KK {›8dspA3wa!$岰rئ/lnm!aIaɰ^|3wa ܅ɰ8s [ [DtNJ[- MK.Q$H8)U$H!g -` o6f7gkG9z7gWۋE5vW.y lϗ|<.qw[p~{jwe=,S?ݯO7w右ŗc0_;?Tx꼫IJg7W;?^< -׋_}蛳ꍧ#t>U:g0njFm7ޛeunf7 +9_ Qіso廊[6&oκKty?>j󒵷U[W3WS%}_/>FwW@]w{:N4ov_OZU>Q88߮v{p}z0¢aw>6mfMG\l7tBǻ:Bʅ>Av! 4kMxQJ3˕:p*> )L5<ХaⱩfk%1]uu'jzo@ǚTeQ3gVجA5{YL5JiL wslVgKM{p r .GL(nJ- =%JE\Wǵ\eRIːI5_Foʤ>>6"feREZ+/P&-A&nLZ&PL2(lAHyʤq9dJ]LP&ɤ1׊uR1 ⺉:i@}:0IF4i "DƑBP'-#餩+_I E:ir ($r(ތPRgǍBF厪L3to3JU] eMJJe@(<-GRs.C(O4 (RP(mJQ'E$.1&`;7}܍V}%".gn. A)mj̝@ ‰JiH}RHFT$#%@CH)u[b)G'tbnj)Rb)%`B4X:ݭ?nK FT\;cҶq‰biH}b Js d$y+u.`܅9NfH \,(RP,mBb)CҒR()-+A_\0K7`Dŕ,ul Xږ3K K!.^pe9Cm!K7ݵH&eRBon5}VqL*AQ#R\73YBqYj:? ZX{Ѯ-  Tj$ZooJ87(duEؤU-qsw}lgQGjk6''B\-ϚZA !N5LUo95Ezͦ욹"':bB5:*#gr[ZDwʫPyYB-BJyQɼe^ĽQ昪k/{zF̻nZ7$d.r `epWa=[ZUw"ʼ9d^;ʉ<̫P]Fq~2ȼL̛Pq "ڗC y] ȼ+)ʉVϒljf^̙^['÷9_W}izY+Yh[4`|ߌ-:fRhyN("A/b."~cR gBmǀ;,٤_n{p)M)U&b6&e=^ry$CIMZMQ+ NXM_r9}C+;9kiB@cv:8fԳ^1dʱ s/QUq);tfu,VBwRߐ#"_"/d絚3Dr:fQ:>5]½<1wBgy`yB7\l1D9r=i*cO'mn7g5YtpNR).|xh?N)b\:f!f1 1 :bww!\]GCB~|~$yH;҂]q- 4yQ!@ =}2PT𖆘's:kY26zV3kBr*jES7|bԚvЬ{?6/jjpfs}WZn^aP-ďZtU5 fwcL;}Gm 5~'V2`N50i{ְ&nSbPmC{sdyd/c!<ޫ?peB'%jt^AALE L=&Sjeۣ\Sfx)n wϻp=t#nn%ۍ96*J`{K&7G^,b|7x)yw+!AɄ9`рd?s͊Ps>d{ &O8IEOO;?ɓmIO{R gAp)珮 Xf[NSKM퓮9į"M7 l Y޲18ւ!mb0v FͮpyS#E <2h048d$/%fx)6-#m- hlD]yjI_da'ERat3#z/t1]-`<뿸"OP6 z7l%"{o8iGK.R8ױv_'ֹjcE+1SK/.{t^JT7Z<'uY+/rGsV@sy?3 j6tu;’U^́NV60v TN8${%HQWU)(JLQz. #X=N&o$jj5~M25*o8F4Lj63F,ɜ cCI[lsvW(A}?{JKAM,$_sg#()K$HGK7x&hNRN디0DZNJz~R- "*Lu`#nY6*/m 퐕ζ<RlFɶIdˡI4ZS! RĒ /$ "JĴTꗏNK#K%EHjiCZVZ-)cFaJ`X|WoyhC>:."lvA4[0L Sē /buC٩1٩ZHZ oH*BڼnSG&E(0S;Ŵ|V%fnAHǭ`doG]1+z+9zcMfȓ+>z@^`hTd&9;_rh@$ABXETN61!m5;_؈Ҧ9P_͚ 䝌ruq!JBmI^-9Ưmv(QVT+u)tbkXgeBbki#9A,CM䆤7bԟBaeԽ1008,${%&u4m[Rm# #}jXP Jf//*g׮9 #Tgf*[dێ% ?-)g͹Ȼu4+gqBy]9 d,]M݁+'KSSc 2UD| 7 U]QU5A0q8i*RUu!ҹv?k2f[q2jtMYiEwm?ܰM"B#A8: n`xi>D8[NZ`RD-.f%шL &JN2x:UCy)6qy^ev8)BV4?GIȼ3*tvŶWy70DaDKCa /muFW"q9yӇPIu@8';_0FLUJ4AbxE1Sus߿MURԷ_qx۳W˟n?_kkż:c?UOjTfߟ_vq9_Zۛ(- &s_+s#F.{\ɶ Qo=n1θa/gy>o_uR] u|rϺǧς{hl?H].A.סTf*%l>_o"&8! К'Ri2^'LP^/ ]SרN ڕRK) FPzk` W`)a'{͹F7 "E/q9)o1$. _eyH**Rû^CSVzB)M#%B ytFcNxPkq=O-uǍ9%ƹ"*/<Ry4zRKܵʲr Ge|z.n usYINV7W\@kNv;qNZ쏻\<F* oWy)˛c0WyEbǪ;{?λtvsu˻It|\gmTp#)oJ rz%s&+Hpn 5N4kY9xXrԩO oDnGyǮ:. jӭ&jV} LizЫ۽\s.\ks\.TŜ]Ё[][TS !ȕBTaT 2©։1Mʟ]QܨkqFIC[ A2F`^.C,̑fSjXz`RP,m6}2iP-EtpRŝZlQ-z3(QK3ji'rKENK EKH,Ul- G޲s.D,̑fAtXj[XiBn2P,EtpR ĝqSl>OqXgPBgSmC9VqL--C-rZZ(TZH- l- IJ^?BRi6NTX0%TKC WKc mH7[OP}ѣ&}:*@-UK2R+'Bɪb:ji.Hu:u6`e 9lJWK9='TK TKQ- k( U7}܍V} 4;`9ܡ&uTZ[2TKPKA 'ZZ"TK3ѷ@d}N@C8=LjZ*P-"ZڤzcEҒR0MꔷQ,z3(Qq;F|n۲܈_X qDP>YԌ˖zYKs d$4u2`܅9l[RbiO, &-3j)䯖 (-+ɤ7[OP}#*;Z)Ҷliajij)ȕBdR7RKʥ9\ Q2yeȥ 9NnN \.U(RP.OrjR41ܠZji*oFOHN97KǍjp} >ӜŽϤRӖ-ebni)j)BY?ɉzSj.(iA9RarZܥWi8΍Z?p/䜳qy!Gb- vXk*Zm#{G$b/fB$e4Z91NIzi:];b,]. MYQs鋯0 x^0QP4y7NЏx:q(u6)u7NVWe:3J9\jɿ?)d)Ns_Kp:eQ(ps02mh\W\85t d*icƷvYPPv yIPy n U혒_a |p&_d16t/uy1Qc;FG-ZFc* ˢa(G.ʝI^С?m;p욑Epe앓/QY,T8mĜOoq> C?v֐g NI)bۼAf!f 2e' 1;*c !旁aGCBÚ|~X9W`܃fM|,&OgGLQ41s k2`"M(<@{s9#Ĩ<6'8|SC O<9OڗC6]ǤU֋*:u0BEgP d4 D/`\/ 1M+?=9&H0ZZ!fęM5gS*gĔH)pÛM;@QkϦ=y6A!~ӎ5qJ,Hd: rMIBx-Ot 81\A7 ę.2[uk 0Qa r7̠l 1S-Nǧ .8:"" !fEq>Ilǯ0 {<l^z}Tݧi.~f.~u=M: u'E)r9wIX>mwcqJs}W1oˇuu0ywqw}W]u~&һOWmTuqO!Sɬ7g[:Go͏_6T 9~鱊H+IB$15 JO.9gH٘G"577 @6B,[->`u MD.o&7:2xo:Mo6T{7 ͊gk8%%BiGs`B?l?T-Dv hp#͡9B.o7:2xoTf,9ۋors|[h6bE El*[E8e9")'baC9Eh3t DG2[N@:Sשms"B{)Nt Ic^ a*pL> roϾZҳŒ\./aߺW|v{~U_я=-]־z}qbchgWwr1@ta1p~7Y݉~ww~=}5 _?]]|~ǫ_ϋ_HJw}q{ps~M&|ywafrC}-.s~UM_μ WV= ǫhwn׳给{=~z=,>\=.rŇӳ?|c".?q9_?\~UHfA^eu=oCunO\_Z>}k=oWrQ@Iw_>U#z]ӻ:jvݯY4B*SYrwNs|W=ϰXX_"`T9g&U9mu3Cqsm9'Vrfs&'߿o!jONq4lIn]hبx 4бeG$]S 9PVDG+'DΙ$,bjН ["M..::eŭQ$D{%'NpJy4j?ȧjo0ӮeMEJca"G4iAO /|$jL[(nfA*Zg1bl1ʤ^Sg_)"î˛Gs 1P (T!(EX2ǐo"vlv1|3cF8m4@dS)Il*㈏5zhr2\Brͭ8aӗmI}~vgqGsv DaD96%/6>]•H9;1wrhЁ#/ (c6E9]g+9 VOE]FI{dYqLe̙ Ը}&ҢRy4P$h: `f\p&BǖaC7Xt$y<_HF6=]lm<פl9:k:i<@0X \/mm5 1n>čaF4"M/t$f}#-d\ i5a:LGͶFZ\!%a Q`%YF2bfkXȁd#/&>p)l8vmr-n6ѶlRBn2Z(QgdHUe*qF[Pql :ncèaF4)bND/vLтSn\(dtWݮ_1Ol?M^9ob97q>#1v&_!##sg 8H:<23xqt |ھAjzpW-;g7/_5G}~s Wˏ%-Yqӄ6Y- `7L}y0M}9WPۆg%Jex„Å ubam1᛬kn#iuYoR69V,HdNHQ!Ltem:(k 9;mrywçD{oԞxRi[Ep?@Ybx{Sr_0i/(d82((E9"H#`bG^ށkA҄N_j;ϙp\*,S-8rWQg< 6o)mP$ [IM3wsi['+E!UVv%xG (k]\p4SX\kQK_4Yl(}dseZ| yRR7fH-*Dpn.g. &Dv¥oS$DNt.p =bduAGBOM27mԅ1@[Q58A$[?D@h!IaUWw&]v`o+PȋewL  qa*L\Hrڹ`&T!r`!"z 16$FebgbSVʶ 2 "C4cXc!иV:&HHr̦qDE$jaZmiZiж9(NQD>5盋8$kߎo@G@))1P֥ N%k"+(JJNgM u#Xo8c NKLƻ7',v<җ;WHَu lG۪7c{) 8 ApTL8  ZA6alj%]WWӡKZPGӷ폻86nZ:dX9?ToP9 `Tm08ZT(9հJ1 SԆ Ku%]?RRgԩ✘$ƺ6`6X Y7=Cͱ6N<ٸuڶzrMǾ QDi)p)p4 M3K\|?e#lZv@7o*ߚmm7x r7 LCnX0 }&'r7O|' u HLV2AޘTanbp # 8P[$\u 6_ 28 .&6)drp4GdrkLn \ڦn%m H-eMLABԥc>fPHh7Xʃ j߭ )@(\?[EN. 8bȧXml x[o1y͙% $ly$lE GseIPI0(ٔ؂ n0P \L@9ѶOr AG06P'`pZȴMXe8W܄\YKJ'-Rݮ:6(8e 8*OA$;SI5 _8 F0 ANqfy!H""B2Y6EM16[oJ*dhr6~ZF98Zl=bh< O8 LE‘Si`iZ@AhG hMLZl<% Z6(bIǼTBi`1 QPapT-,UcɐZADؚq.1[JGvyᛪ5бR-\-Hjp M0蘆gcSm}&"25A>Ei+1C9) $a[!Hq$ da0YXD@ֱ06Mq{8Qv%;ca!3BIL`m<,01SqaD,z*D db@XD@&bbz&͘k=x 2u3ADl1Ҵz7## 2 X$8Y&2L,"p fwijKq(SR N]XAI] X[շJ+2Aj6G%*4P@$uB4Tz8֩pFA_E@XM%O$n1dbH2&WfWNn6JʈeCn Pk i1V[H&.Vbl-Hz6-y3P[2usGW ( QFvaʩF:}9D.qGv ẉ($\0:JGX +b0I+)jl@&3HZ' ҷw@INv}#;)b@OFLf IH7$VxO qrIN%L (Z6L 289h$yꤱ. T\ɨr!7AI0Wr8hv"*M$fmۖxWNW7-Q\+ng0I "TS+IFs%wLY&]{ %R5 o8 H0 CN1AA0E<(+c{()HR߮!l4)<1MHiK)Hն>jpdN"jdKH" då|GeҒ5XաcƋݳsjE-01Ga ,~*3&2^ "BUlJ2q~ng\?3$V \1 ʵ4*hGESfA?E$iIsN4KLDGҚ2kqΦls4!#,2#H$A DN AAEDj+$ě:ttC1"n@ X|&Lr'`-`C0,*3[9q|$c@XD@2Jn4$OVMb,KǤec> jEGԌ +7 $ ;"'T:_ZAEf|"2u]ΧG - -VX訐5`-dD84-*Mh9ZDAndlZ!:qC49چ&X-fm-4oU>U,4#c҄Rl$ ?8 HESg2f 7"rUM?SYWۖI%R-HVH6X(S3Nm}#"Aȩ23Cȁ,"z 1[4A38h6w۝&mgL`mdat,z*u"2L,"p [6t*r}Y%V6O) 1x˂9X! bcJ@ 򲭏ðyY$\ F-"]  IҼi&`i,1KSAM" W#V~n *l F BRwqMc-01[3χ= g8 QRP #n;dj,c-qv@ غy$&.[dTt9FlDz'eA\2 F3r4ZS5EVw#$F$g44Bi 86$Hh/(vd]`(N} =[ !HVL&u(UDŚhPް+xT;foĨڦ ?;&?kl3Ե48l0\ LHf!\2?YZ p4HբRI6Vi1|'FAdaQdiqDǼ,H"w==ITuTx S8 DֆlOyZA6'\͸\m9&s@1VJ`Tmk+N}d-u Y3C`ǁ9i3c2'Z Lj@4mh; M3iZW4.9˜]m'Q0<-uuZBWhR40$D6Q"UPH?kXH݀B RHrMrL@n4)K:/q EA/g*< S \D]msu̘u`H*VoݺumHDȘq[L:7Zh$sm0'j:1Uk!Rʩ L Kwq - ez O-`m8뻀enMѵUQHKlQ 1ézHő)O!k4#[|=slZw8od'h,m0@6vL"G`B*89:x4R6#nS#ҭ27О@6$|3 ̲L $ƈ1 a 7N;R?Ḛ#a94M\D a1'CBvZ%.qI3:& pٚaBHqLp>@fQ4zJC7pR 'zC!K-`8LL 1rh7h+8O߬޴30(`BeL9iU: g$8yx2NW- dE$q;.rcAdjIp6Y g P66RI5d-&v6Y3)$jPp4G$j8QKVHޤK+}J?D8A2wkJLj0P: uԸ& A3m%*FV!{) DN$n Ryai8et=kiVmڸ/WE Aek^'( HʖH?k-ik6CZkWMI!bNyP [|9>Q$ikќIkeh]$2nʼn=,l!g]Ojmj]QlHh1 rN.mudwYIDS%k)<lp9p4$S[k5qGcDU\RcJ,: PNHζ>Lx;Hbf;Fv\3ı4hI*@ B'( -&Y% q3af! .nm0ZL9m&"H"Fφ9> YO BhKi5Q{ l  Da4RR[ WCI| (B`+YZL8m H"`h#H҆OQKzU_*"xWnc2ׄ=8v D%vEDȜXGB'&HE!BՌM e'ašQ9ژ/O 4ٜͪym֬ %!kCk5uEݮp! "I / ˒J Y$&AqֽRAHG}٪>JhXZRoukJLj0V>?CڦÌU+FUk= ~k!{)c+'aoIdm1cls䄬W[!쬴y?Uhqv{~ǻūןqLin_2vu;wANUκ݃8cG/b|1`'L&|BY* o]ǾiLN1_u˦o}- mKݏk4iy8թMRNx!QO G:r̭]6cwqf˻/_->(/Ti es0J?Bށ%H6FEr #j)4S4%SGE]OH ǵ X+Q`1 A;ZDVx0 ?8 JRІK'iC̆^Ёg9>|ྙv &hv융ٙhCN`-w[[ Ƌ';}h##C,Z$9ZtG)ZZD4R4F)O[ Ra :֮#hk) Y 2ahcO #h'(ZL9Zd/Yp4LJ虯==KJۂ A~bZWd?-k3+5›I3. Cf1d%\>Brf65%c{KUf#UI6H+ M0=MpYyI0\EN5\An90\6ey87㉹"n4&MYsf0`6f n4N]pl#5 7+1?i<0n60bt nYY-VS3hbm]>AUbcr 4!©F3 &`,&l,,r`l8p ~:v&[\T3 )sc. XYvNɆraC. fCӘif2qyF0jSUfFQhhQA F0jCE@ GQlLը[\Ofc+I[Fs$`,HϞ&X  "ai͢z H""|B̴ȸO1Br ]hVJ@P>!?%9+ ghgȊs4= G39 @#l6łG% 3ЎaFH{%A#A ?CCLRN_%A3o$h+:?IZjJ =OÜpخ؁Ah pIBp"-Ik:K\SI  PTڭHQI{.`Fx{%E#'E CFFƉIjH8_FvN̟Bv q )h aH!05E GS '4 &fh|qZY`4jugcrKm}"88 H""b͆Rb_ 7G04Y0PNLm}",+!eQYY@p4`l@L\D Ǎf9Sh$VY IYT,ANq`,~v,&` %((FR>IFebJTTvn$ekf"UI*6^ Lph0PRMm}#*+áeq!YXp4Ra)JL:.⦲ `|[QcecZKm}"++ H""bʆO&dV'df_ 7GuPp4%`,. )8 E0RV0Cʢ"h YoX5E[EecRKm}"(( H""balMedAEpSY64! U16D EFe[ &phY\@b90V6MT.1l*S4q2,[4T( fnVPوEd[aF"IGbqr?}Mf/+=A~vpWW._;?T$a[f*32?.>|\>+笥Bhzz_0B1[^]^~_g|~fٟ~v۳zv;;_1ϟ?ς=|8ǫdz3`#_ O6~]#F׽w|`r50yeOZj1׼)Iٜ`$ɻuu55>^y:ջ4_sur^;_NvQ9bjn|0Os.~C_3^Y56 w -;G:5~?)۠}S7ciyZW0cr,X;q%=ƹ~2\ccv|yS{{잙t^ÿb%Q)f*+STbgT)*D'"Hxr䆏^hנB{p=Zk#3JՠF/=>CKGiI V-| &G?;?) 2盥At懩psQ_/R[Rϝ΍bЅ*B0H<(×/!~o/AO? dØbA7kx нL}GRss؏Ϋ+ZJzFkM؁E2.|~ =>va3ua}Pu4jn2݇[o*}V oV6]^з~<mv |ajz}%GK4c,_ŕJWIJ,2o ?vz7s0m$Q}iEigU_wʙ;>"z8h| 5q0]>#`w >AuǦ .MѡIz#;SâU{>BESCGz{ (:t?F^/7ǾtnM̺Xg\~Y׮Kv^h&0qC~z5HhȽS{#n?Ά"zM l'/z vpY;f9FC*F/``W|_eiκ8$ Xgng# gڠ|!==1,ӉIpJw6kR:p* 1f,~G<?[vaV#qGlٙ3m oP$`40 I;~vt'HixR#Bx׀M0ہ6A g{nB?ӃV/$Pd2 ~| qNo@|bKD3v"E cd%!5aBz9~z:a( k0% v jR+F8s XT v20>0 N tu;-qƂ83 ȃ?:ݥwB]G0X)y4X*Va|yEB0} p3pbFDn_A`8coA!zYo=ǡy@yڪ!uV5VQ  ~=gCj ѳmUA`Ca&п,'j0.LCFh@̓!j@ 0v e'9M7z=zlЙNF֒q-LEC#a#"al1(˜\ F-z>#aeF α|!!G3Ý !cH-+P+9hr)}"sOQ 9oϿ,xvg7MQ5htAP3#b@B5 #Đ@_Gߑr_© {;:vQ5et Xl? 莟{+|>e +|j W$/0\A }:tZY=[pr 92x&Xq>q|w} a0/%X/P02)|B,tyLذ~bvMh7~I _`Ę~_tL*I=o8iۗaƠxAgG |e؇4cp  )` ,>~+{o&FB%)`"s:8„0$wY^$FD]bs#(}r7qk.K-3[=-j<*7 ;޳Yc} dpW6qr;n pAņ":|whƘ>1.K,>0`p=lNxpP8 4;uxI1(&A$o ]N.R/O:C@7#+{_G/1FN>ޟf\A'pE0)UA"=)gBQ~[|_$ـ )`Y >dLP Ǣ^0 p #J;XLIQqZDwMaCFQ6&g`tS ~şW0јpp&1ѽ*Aڍ\zNzx-:Ϩ,hLf`8CaFDEE cX(mݕн졫3ݗb; NeEa`8DA.@;w Mjzt'~El<3cc@<A<D4c0bX]MDڞI9=uQ(ƫ^G9,}k3ap:_N\V {8[ql5ij~j@pKx@a 9x^8KaqmFBL^89?0CjK>R &0Xs_ŃE\` 45N)`P"Cf!-2!2x'xIxu>Es dz~GЙkOPiPЈ U>/-|}&kx| 4 V"z|G_їsP"Uۃy1~tFaN 8` U`+-) 6\vK૷MdbƦWr&i,Ć}:hh>ټJcݟDU =-p8c|#E=7`~VGgéR&Ռ{Wp\ypb#S c1OyLv6С}WFΚj_3aF}?}җCCMP5T}-*VWj՜1jdT#בQQ`FQhTgq#:1q̄ʌn2:t{8*\PnlZ!FT߈)A=Gic Kя! msK f$RXfP%š(\# C;/ЌUjl+ELG[`V'>wP5}OFaQ7LaՈl,0"a% ظ_ztU!NH] $$l"Y3Y"J$ ~Wq9Qv<0`wKKXG{8YJ?| 0Ɔ"= UuQ?+2)xfxiX"k(g|hV" O ^ðm~Bc5dF|aUD8ab !*$:$q-2*8`\&, 1|T~@ۧpƢbVeӱ袱8cQcoN"HbZ2/X%lWLKE۫".X)`I#`(I38ab)\8aq<6śO$O\xrx?yfgG{édG' gqF;"Rg \.tpSQK\V}'񅉘FJąSt)J#"w ԑƱFLpaiF(0,G#0 }KqjOutwInX~3$ Q Sad0^p 9$)(j+x`kNa s~W(HTa`0‚Z!)seY_f]2!լg(aCք!Ki}m+4!9[+ _8G!5 c{1"\^},,nBHptFwd<ɔ_~hS1%kAPނ Qc l/p3w}au/~iiϯ?_>~?_a߾}|n;7_c?_{_?_×5ۑLg!![Aֆ'6#í?76W}Gqw~)~෍N'7aioy.k^IδꭻiB8hgZok?/Ϗ{޵L?'4 }.WuT㴯$ _Fqi+߿~qW߸J ?_HU>ۨJ;&[0 \@J{hTW %uJEGL)USiA!>YG_WDhK[VhsyJ&nly!@ˮ!J{kPJ=">;%٤PBmޚgD)m}HLisfqNOXn4]GI9neiL6tjaBsXrv wG T>=˅4[p̅S C4I& [wV^qD H([lMO橐0T492V0JXVC1]kJPtn&ElQtޚEūcGt|vOw;/yc4v)eT3| nk o>_qwNBؠQoZ$>"X$"S~r([_ŋvV-bM'I'qAly%)!,/$T&[HCvi }GPKި#TZPKٖ8u2Y4됖1>ҺaJ:*\=ךLzL |XX kօ+Eɒjk]X:^(gضXm_"W&d.Mg^q"i)CfC\x2nAZ~L*:B]E *nW0+#^;_kKv?) -(`gΏ,<?X*7m5ns7KRsd,g_ҵ-nٚ Q0 UeHcAB;bS5~bdk"V_O 2A8]7NJj^OD14-Ym+XXlޚ*B,6F*o"櫝 [=d[ ҮʺOc{ M\h3xzXN" .VK!*H2V=qzrP9B)(ZEKƲEK~լ=!gAs̈q6l'jCP]p.+͹1 )anvdgI*Zѩb;V ܞxep !mZ(:oM~*úZj+79KQ2몙(~cH(&mNlk2tFBYR<̓zr K/]KUfKlfvrFhФ)ꉪOGgZȌ³ BxVR=v1U|d .]{[_Eh%6|&xe>;]ZdE1M\L !ϵ&D0+cV%}/׉FLW vc2*B iڇ8ثKGh޳X\\x {?}㷿۟N #KX݇f=, @$\W Tkquzn+JݕWUאq,W"B9!jC*k@<QV%mi-Tn[ukehq_@܀dUs1j1ZvylcZD@v IC;y'U5b:|PnޚB~ɡʛ¾ֱ4zkp4EQ$6KfͰ-+ De僨tyʿ_K.S:+DfMB/#Dfmdps)429cT8%M= 8njTyAu nLA!!>/# K!weJ6mVHֲP}cA!ƥi@RbX$2措kTJݼˍ7^ څP0^$V+ T}gA׊x3R#*JA[_r[@ns|=UX싽rj *buo8 g~c!7ke#.G!, #~,(%DfKl@f=u#;#|>]ݳY0P>0 |<_WRBϲ JǾ:#U0Bc6[ 0vel8'Ɗ+7ۊw^ 1Z.t!n1m-_ jZB]IJnwZ1s 10mʨmk+A6oM~ V&Nf[Sm/qR !+)h F?bX7<;n-!e* iǾgU1rBvU  * eҖ-V&g"W\Ao_8MB]y+n|Z[G@@h)`v]IʿLyx;O&bM /V%61oUf!> u![⾻I6C~pfWΒʱ-&DpޚA@63M?2]N 3И{CcDdQ{ 2 '2UN@ɲ!YVk[] 5pv+e2>hTǢ"&Cw6WP %< %Du5SZx5:x7禔"2B+ )ȾZq@ bp2BK J 4[Z%3"A҈ j'vӨ9A麒ұo@WIB9K/esJ(+Tb*a]-G;)mi(]&ES[4ەV´ZB9BoD3Wi{^_9xvjkoJN6ᴎWPa1ug* `ZV{"XA!nӡY4s,|PtzIR6,?sdM=(}6oM~!,[v-LT2uJk#$s63Naz!,K&SGeJJǾe]bAL6oM~ &[nL*qs[&U9"SK՗>~:2[|h3TfJKYv!6+)!e֌ròCO[0ZnLʳKަ"iW ݆TeB GXqA&D$-N 7`Sk ZolT#ڧ,BtU-!nˮ$6t;f*!mڤBB6F*6H$caS-n@-O@KJW{{G4keʭ^>6Q}ǂ頄ڼ5l3ɷejD VaDzv2U3} ɪZB]I(VHDvP{;7&O<D% Dlrb}m,Jòi bUlt6%Di ..etc\v1K[ kKW%Oc+A86F{8XD-كÂ:F%򱬝X1U´BBVHCiovFf>Q]A b !\+#kmHS5X:yV,}@s6?% B4\WZ>˲aY!-]tɳ^5Ξ]6 +cm;HHT1Xq>P,e׆mFE򱬝Yԩhͨd)8K-)(&j٥PM5<F$NTnTF+BB62dxef',8Or%>zNVuJʣU<*B]A n JcL<Vg+*s<-J!JK&S]AU&nxU-!Zˮ$DkDdVw$4 ަ!lum6Q0 Ǿֱ6a\"ƴ aDzB$mXR1{6U㑬{j߿Ǐ$5V׎ǂ8y6, a#i U^kfܛJƨÖlh|捩dv BA]7(VH2jo;&PFl; jGm4s LS]w6<58S 2E "p\qÔ6hA 3ɣƐ{/M[T%9kPۭ($ގQ:x6x`5/*w WԑRW"8H ,{[{P#?C^+\@LqO Og۽7.G~_o:1^`)0 wqV;'j2~\kT^QUUx!ZmKWOL<"B,4,'xe#g%+?ĝehϷ&eA\ de!zˮ+|Tk4euD.[_IfnsJղ2z}[ѺX q)zkTډٳӊ6*u5%] ,ί]}hm,!f* f3dr"$Xj dIQZk %Ϸ&K!YI'/h..T&YRXvq K}[λ}+mLE䖌{?y X w^ 9f2"ǒ2&k_quN.PShwV/B7/ ^mXWɯ`a/dU;%|J?)-%:lG;sɣj"fWԒop'}܄MJA5僘mi MWNj\++.jcG6e; ynePvo/?↩Wh$Ar+'Aiv,Γ[ۭ徑ۜ ɢac0Z#g*Y$e(u{{7\QK0,]Dl0,jg*Q!D ?ךL\ߦgt (I,̰hE8%"-T"Dk$ɯeiE+6A^;ﮖH(0e3sq5y$~Q e; }éé8 x&.mZ>/!Dmθکbt8B馇jJ۹d‰ZS}MxJav#8,)^ּӱ(?IR/I" &VIV۳OjU⾋9ʐblkhy+nbI{c'+(`勐t@^IT$^ަ͊J[_-xM<ﲌN 'lFIoO_qÔ,+M`_QGʈ QpI+A횂M7t 2qҀMq5 GjEp] 萤!ȷC&E=~ S)D`^\oI+nGjz5 jJ_ v˲Aƛ /OmiXT͛tCݳQ;W0kGSEe9degg +n"yiw.A}~Y,qEl#EuDn!s9 *CӁ(i$jTډɶ^(`˲rB]L£4$d5:~*ɪj !pφPiQy,cH1ڌѤۀєh8#KnMUlR SӨB>S IwIXSud-ғ}CC9K!jkZ? jQۜ6٦I0S;v=s(V{/6&b[&K~Âؤ*/)DkhB<)5-hB9ufD2Id]tܠN.hDg 31TA-Y5bWYtQ5!0ˮ%fdd`vwSۏњBB6C4ŷYTeDQqxx.CiA30v{}W&E2uF*XNex-keBox'&o}4NIEV[[A !zӛuYBmg,Lٳ!ɤ-IneBzoj3'l72xyT~^B66I΍eftB >TB%E'j=f:Q|lk ߰6WGVڲ Q[!=79uFlȻpµi?i\ӵqm8e:`y(Z&yl,:1.!:  HXǚR3Zn+JF:@/̅JΜ-z6Ô.M g7o qi4q4gH993yj ,noBĆ(5ٚ<+_KTUCWP cIEG$7Y%8B6oM~!z.69A;VB*BL/1n [VN _&-¶Bd9)hюӚzE=YMnrF9w. f=CiUY4*eP&!MB]\ ʮ.. -8M״v9) uK%;>Fw4gܨx3tA֠8Jڦ3՚Lhڒ&K ZvA!R+%&?rQY"]zE; ڜ6NW&51( | cv l$bjM-leBoz3z[lR< 6:Wƨ8?Rܠ )$jM&Dn)rӪeWBohœ#)VOA[A!h;6 Vy+np/mJh')Ԟc[pm%B]O IɾAM@ͤs9xgm <+(g'xɉ^ΔG ]돑:hEAc41|X^NC\ZլEv&] H`ثi.[oi&#d?*YGk޵9hXdkrEz)5`-Ґۜy5Kަ kU`mVuam횖E;fyԵǫZܙN3T-".HOC[٧Ox,bXQ³ Bx668gCj6.K{栕t.u5"Xh^JtM)!P.$j4d6g$s.`µ)ZA!Xaj+ÚPJ"N:^5jqeWBBVH>vh׻ q.~-DYA!\P*`^7J{XFBEõ|1t̤б\tF`47uImźV&J83y$+M)0/VPR)O)ݛT:%x!h3@ 2pWe{( Jن|YyTTN*Abm$Z2i\C4In(wya=U?TDNpʫ%mINvi5|JC?|^v{?&f&)8?5S+8PkKV8텟GU9J=p"T=w0Qr&*̦vlʂ~HK\dWX>:,+yE@3W7.~FV=*NMlÂ%m7G3QivL7r NFpyNh|tvkb\bRعpvz;S<"pWHeY`$Xp@%.D; F\i&vLpXLXOSۣFksC3֦Պz%򰴥JAaz!gͩd[-X\VǒL{%vfhE-9OJj5ṧgoNo8 J3FnLlJZheGGstޚknt>l/y1&0z U1iNwid30~gQsޔ[. }lpDQOA``ul.4;\[^w vZq0.#Ŋv3aq1 u { mx70AȤy_lF&C%.oaumw&= 6otfۅ׷|OPK8D1rXg]Shift_Register_2x.fzPKϝ8Dj`Hi7Shift_Register_2x.inoPKfritzing-app-0.9.2b/sketches/core/Stepper_Motor.fzz000066400000000000000000000771011250202676700224110ustar00rootroot00000000000000PK28D|_Ӯ} Stepper_Motor.fzr$&rkH;f @gLԽHicYUX$dU_CW8Ov8"3"y!3@D:eKd?w㇛٧hE^wW׷xo77_Ǜ_TMEhDE߼fח+˙cxdgWo׷w>|z5{~Y|/ٟ^^~kWJUH.?_\{+Yq)7:O׋:sn/>سyX\\ÿǻWnxOo߫ٻ뫿\pR׷f~ wފ]ww~}re./{>}veW&L>ڳbq>0OwJO/Y4'>r7xLtg߾~׫ر:17ыåykB7F]s-yȅy_|}{юp; 7ןΥ.nϛyqaqWzYUk~~oᣵU5C;z?iО W^Z$JY ̹_~!Dvoy bu|JT\R7Z- }י=O=w|A? ;o|W镞j짱'OaťŲ7-_ү_d֗]5c#_!]ݡi-hQ-{xV[âs9ݐ.̵alSQ|[ cu2e#만aK1ݨmF'5jypnPQH[+^2ÓU>dj܎“ ȃ?0^8LP)9SE+&qgv>1S.\lI5t{|I|dw>3Qz~䩆1·qpϒC5rs\MGKM~RŠm /p9iKp=53F|QU͸XSiM#6Q6Uƶt*3 'WGD(7ApVVB=58q*mVś*My둛*c^77uw4"FK\O.OxJ==Pيq;c.7Q2npl̔@[>%6W"R|N-'s Āوœ`\p PzۓR~!O:n\FyŽztw؎ՃZGN3i켅ͣ"5x@%6b a'O#cw`O?%>nEJ|tcO/i7b,MvX"Lca=%Ju[)q' :^ Z@k{=n՞+!iX {:.&WET6{jJViwZ,P'gH8v0*8vO{ RiwW,LnX L-S4LbYžvKdz~%>ve{)%i7R,I&FHO4Q, Oft;(#_,Te(LG|Ss0a;gOdgO>EJ|ܫ垞e&#O \['e |hdnah2r{O=„=@6zfwl)zv>erOd ʙv_>% |~OO>ndT!%iB,Im X@O bq2* &qHRZ9އ% |r{N@Oa=87<,M6P"`Rx.{)لs}˂79,R'npXLaiwU|ZGNyh[e} %5~sjx12Gn(FϿmXݰHOa27᰸s={(sXOa*>"tݦ+|܆JOBDϋŪ6vexXў{aqyX%fS+DROa*>|܆JPʸ]{: XO bqҞv"djadڽK!' w)iwD, T&4qO+bx2񾈅|ܨ3bi25+H Cq >r$ʼn{9@{:$'f={z$)wI,T^7I, ȧ)H yraL*b%qcʞam={:&'qs]=rJÔwN,N^0cxRzg')q3= XGL<mb"v/"E>ne|܆|XǽjnI活*)ɥQvg"E>ފ|Ȳ_=j~~7ooEEG6~WwοzÍ OחOwO?7 wƿܼz1~_d{Z>oiO7OO/lvs=?_?-V??,?<\jl_y{o~gopo/>\/|́?,߽L|Ç_}.]Ο?#?.߿{zfd_O77w_[%j|kZ ׏VrwwpǙgtrzZͷ{>|}gl۫ٛw<辽}5p}nQ~z3v?-nn/g܃|?[^Ycfn.,f7׋ݣjvmtt9j!wrUs->?x|XM!PxO?^|3y^?iߟ-݇{]-z<<9m/n>'b޾m /2{ pkϱEWCuŮn[[+*L٭QV򜉺?\_콇z&Yz5CysɕzsyqYZ^j-۷FŻ-:y_~pq{g БWox W\\x7`m0%tfU}䇘w׷O!Wo?_/:tuK8cEjPS(=iՙnA߬3Puy &mz܄S5#psR1#o3Nq;؋'803Nӊ随MkI&0d)Oș_0唋JJO9RQAp5Nԉ''N|Ӧwx2xwϟ.n=|}ɖ2?>Pe4XSdž+;^KB|ތ;c#My& C׸H>֏0l#E^05,b,/f1iX9^"X: i-;52SM*)˽{9\לLy 2#&DemR%opIcЦ" 5\m2%o@fcЦNiIp׏VB% w~ rB_nf.n>ڏ?6\jgه뛽}Y;%INӄ͈$̠ibtl cmDhPn"԰o"1*CVA&c~qJ gW_W'+`/OJz("-[_Ħ.cb!|%Mؗ4.!:C!' ^3'rUJnMT;1Zո9c>gD&&F=A칉)uTѣ#`^nܙe*rTctOxOt' H*4hgn\\B悒UB~u5 6|/X<:wh_f"x#v `T[Olk[.L"2q\.OJ􂑀)Ѕ2$]cE˝0weg)'")|tt̻ QX Zn-$]B}U0O{[w\ %Ek9d0Ⅸu=uqoU(Xh!$vސ%/Rb:_:Ri.w꤈Ⱦ=3JVBؔC\/߱Rb^D Q'Y'7Ķx!dTj[E댔OuړsԵR'k>|\+N k9& LRY9ɁՁ>Zx &]`|puޥqG` S*MRmWn.~-{)#<$:k1ׅuRmRЦ&rI pS]ݦ94T:JhR5;D[[qݯ5ten^/c*ܭB5^-90v:ŝ{E2҄9N svޞe{ԇ%&&NMp9rkiΒ}N2f<ɤ?2IY/,BK~%;^eXZG\0usv˨зT$ڛb'`퍙8o)i64L+yi˘nW+YFRb4%yRDǠLwiIBbզa,tņRJ~\Lkӟ?,>>\./;JJDN*.XD`S:%S)L0Ϗ~e%s;Jt弍wsWJluǧهGW#bUD'Wo ʍ`Y|E{ )]g+f8?B5nSj{yA|%mTͣӔ!&q{%@SuvL QQҊR.iP-Td+Jn=qr6;Zxo 38;ԲJInSQ?{\ƍ:9uRvZ:e' LsK9 o lNA~:&UJH=Dzbs,d a'h}0t \O:}3 a♨k Ȏb*̧UaH0w渲|"p?}*Y2򝑉΅ c۰'C1G8HH1:%G6rK%g& -ӧ~.2wz { TME*V3ɪZ;!6֓Ne**X5sh#NV(=!i+n1TrU !1ȱcؓa#ƍdS&dx#=l$3SxIcHᛉqUiDjg ?J$(ᷳ"6#? D8I!:$QܜH9;F$"G2ʩAN |t;GܵNiv9>Jc z"QȻ'kfml^R`2? F֟svt 9CέɨN7F#C;tyaPyU  J๢hiV E%]Fs\|n0]ɺ8H/!KBɎJ k"p4a#4p)&"Ǩ>^0Mu[e_5dGie{S(ͤ.^nlkm9&1y_*bX&!SE!1!H26z2sciP)&Ƙ=^0kCni-2Lϩ10d sUE9 UlE]).b> w)SB<伹*6bL /l"2l D X; (}"%"֢"yLj8@_|m{B*b @@d ~, D #C>PF2JFSr2Q |9Ѥf.f*um\}L.uಈ)^;Fs櫉8F#p9|TLStQq#|T38#F2LDq |ؑg ݪQr_j2'?鋛W FI#>3sY])٦w3nq`,Þᤥ $o 2rNĎ{ȑsx#txr<4ik 5b8J;)ow۷ov۪79 @z~xKAHدqh#B= OFJx1ēl0r <"#2F2)RN1{t*ݫ1ONA:kfmSSc*Me!SVTTuxSJk 1O{ og;{ B=o3vFHc|1vg v#2A"BGb #0'h}0n,E=)#ޙe(VءE}r]7H;oMA;jMJRQIZMIK`%;8/{Q{yo6y'@- @yĮw䝈 qS% $sI bS;fbe5di@X^Kbix:h4TÞ5p$#d:r !Cwey98k]m{%[}JפV9Q=4&//]CAVBJHt[)(0Xcv{71$K' *=; XԆ{%}"pda#T`'ǘ=bF=]w'˼28e\tgj>R),BK23'5É829IJťD=[;"!~dicC> 'MH?;F%G6i gnkf쓺d4mI>町"5 w o!95`{9uP(mTٶ1=6bcC9 ('K9;$G.M9EV#jz~pw~u粠q+pA#a/`nG*jHyƱbfpgVwPI3. ϛquIwƱԌ<9 pSN&r:Zn lz2Se+{i>]?^Y|"4\bCB܎œRVּۧuIj/?kȝ{+[4^|-w!_tg{5Y{ͺYB-hS=p=UI^QvBx.`p VmIx%8{i-]=zo>>P(| z>`;?0އ9u%}k+{o/L TcQ83ݦkWieT8Q%*Go#{nyN4HZZdx3/9T2hL{젂)*SPejL(SW+Zg PU~rZpv.[x+x#Ko-cNp5rk@x1KLB MJbw rRF+ uB/+:9'1$Erx%9.+^1;N[l(pD"mbSF-PH+6rD 1`%Z+Xҽ *T&k1ebt-LB0y)&s+ ]E+ 6ePZ E9FGQ.JRn;D6WaQŰ۾iTA"D$3kSΰU%a.4 ֫յQcժKkpFQehL1:|N\?OH ՝x#Um% HLt|5Ƌ"U\yZFXCaaARdv0Vp-u등]:Ç/-<"RV~6;Fsկ ţ'DBM.V  /K0=9^HF=Nč1{ȑnZa5fxTNS.Wg.u&5WWuvp7X8X(4Kڼ4ir #J1&AĂ.ppl؎`QWlb/AUgx1.aA._XF!Y m\@غj"M"oSd*Jmd3Ď=!5r$ce2!t` cL/|"h>xtfn>.jmʈ8I$nݦ#f# 2q=X90{go>*j\%BE1L)U2*IAĒ."$Ơ{i)1j־x}{7׋MVh^QwpgqŇf.n>ڷ?r5 cR\5TۖhTnFL5!&9e,\c,=9zQ:,dD%c_ȟƉd>Ir HΦHC> nk Q f܌JMQE+ɣ s^j )r,W>Lmc4CH[PbҞDxZ\7ER1Ntp Q. ?K9Cr#HX6!ؔt5UxH/PR4VyU%X[H2N܍qlFGv"cؠk tm"2Z"8XZV yZ AG0dGZh&T`0;M kˑeHȶf G1MR +w +KAKhy KHB6E}`"#[JX+B1'b)^clDUcdtDr'FʒYFzJ{hntwNo{A07!xJiLC#9O Ⱦv KJҘHȄ[yv3VpY+VM|7-lWMnҘXwVS&>KG da" HVP! ǡR"2Lrh$j=쁨enMh\V[x䘨ؕb!;dYp঱Mz&LS̮ 'i,큌,p`,!xනhĎ,%Zhmhlso\a$v#?$0~IQDn LA?NeEM1=kX_S}`dkmL%:T_GZ=@ Ǡ54B݆LE5rw4SWvaޒDeT&„ \\.6i K$ hW<!C![AV((EH(1XA$뼷=9"bc$q wnxrZ' njfx4Mm=NyNG=\%4Fe S'zoMfdl;%ӎe0E%%uE#Y4MfΜ4a;J-Z,y8mh=mc,-Ӷf -B(σ^V&`-%4si K%hfx&D$f+bK#әY/[TjM'XE0Pti0le4}Ha,2M^&# A ϒrh r"rg7kb4o ζfo;P!%0|BpYW4F7lb%= sb̡=q Vnf\(O/,Hv(TK&'Sj yK#]fx(JE/-op.Qql9խ-\&+cIhme'ɅҶuoyT5(HJm, r1LQ QM@DEwj]IŠEz06$03!f=p=5ѐ^/C!sC*܃FV:j<xT֘r]UK}WbFY0 bbhByjZ4 M M 3X!H Sr„m@Dfʘka6,`"`(re%'Gϊ-0+n*`M"5{*I}Dҵ 攦Ӧl)j Ijo|MdfwƃŐ7G֛)% ZW(*Ր'RBi3Tv;ٚh^ؙL79iKr@##7cM [܅2C;<01nl4p)! ,y'1w zme]ɢT7)E*+!+" 2$wiC,-U8+D%e5G!c FX[?5u8x?N444@w( ܂QDXcgҷ0rޠ!+[01)j-T.`cw4 pE<̽V0)w˳!G7+Xnxa+`!z}B+P1K%@dm $T[u6|gyb] 9ۖ #r6lTp"TV#"kw kK '$hk_cZǦKIP[}-{\PTsq-*5l%C 2prڌ-Q- gfxAζ=pMhYu@k᢯d-:p1w@P"dmPZpD-%6QKg CKк>uˤenFCmJC;Ũ^W[|=9+%b7S 8);2@ a 8rG2"rh,3hZjTu+qoF;,-D5X?s5]fJ<,G$i;EN;A=BPZW4PZa/ umb$"(?Vqʉ1m)fI26 JmPZ$(˪#=MTŰ۔bҹ2dL9]Ui iK&Xfx@A涩37Y"%x=$7"(GVeZXyBqkp v5@ِ]R(pZ]8m@~@0D*w`S)n %UBzGe%cXA6>rmhǔ5 ֦ 1sN WלZb#av [J8`[Y@z^Yj,®^&+$ }wYYTYc%rw+`1!7%Bӎ56%@ܙ=0: 聃e{jG. m˥jHsQ7S&FK1QXlq Qr--T-`;ڦ22PcRI؉sZ,h,#sO!-{K0BUtH+?ĎӦjyj `Zw4C RMe쁪TMnb䖴ʒj'k4[ K22r1aiF$h;$h)a ZrYAn(lM4v4Y_Ն%p5-䏊5-+e5,L!Hdleb2qڌ-I- }fxHA=з:3}k&uH![K6::[GlV&r`Dq4-,`9 lO4LLĉvu`s\ q3& #8R3CDibRif2hi遦4-Wu i9> C;ErMk*ac <-%6OKo OK!ӺFmPԕvwTSd wmH i{rMztm ˨ r2Q9[R9fyn [w4 [/QRQ̴-TE(qT5U%!J*fpR.x[ & ,I݁mEr-=- ofx4AڶC mi[ m/벗Vn-j4'Gb٩q)dGV^̩@V&`uDq 9Lg)$̆MLfg<YWyڶ CLrAj8ZJ8mzArA0v(rrv7wpnQ3S/ўƞڝ'J,>?4WO_>]|﨨(e^ f/߽Z^ULֵ1sb_<_p3xx◴"-n/ﮮo}ˏOowO?Q+忿?w?7|z/r~?=?9^=;s{;ܞ݋/nVG>b'ьT_?=;_ꎟJھKNSwj^ک(%q_~ZBkݰQהy -NPAY5ҏ wc׵yg(rI-%t("2콨`7VDBgVP+[tǬIIiT-RAԸ/ %̝DD'"~/Z(;zۧǭ%u>#gbxZIvƌ=>uŭ@@:0nRwR3a'dx ޳/Gv0Hw9j&\3ax0a\XةCR*{Fgo[ʓX]DϘ}V)gX75\-c듳ob/ά:;Z\9h9ue|2 u׌ڿ|oCwyv3Z Ȅb@wRᎬ/=~~RiΚSXॿ'|QgaџOx 8#Ӽtfɤ ý`PՠH>YӀq ܝAs+Jg#ڃPͿbJwqÒc`MSf{Ӻm੹[POGAS/_R3W? Om^EK|y!N74 ϔ7kt?re ?͝{JwiZf}패T;m̾#Vj-6-+v`z]J֊*:~u7@eZN~لqIbVm_eĮyďŃWO;հOsݝS)5"QT+\}ǹ>NC#DNtsG'b V-֗ȵ{mbƽ?Svxah ƍP5okӛy3a8&ycc*ù? ~Q#ie[]o0w,Rk?Y K?^@(ڥнy!^oI-{oynx OOmpi 7v58smӎo3vuĴ-.L;LPK?h{Z·-!_{dbUr'X8aa1oq+pRH[=z3EsaL'L9}MHfZ1 ~g╉֣lrOW|e_X4mȖE#W \+aY tk)X~he)P@Z hk-a1cqV?~5 j-д&!5:k]v1\+g401]`H 3؈f.=fuTٛ>Dά8p%9 /$1YݠV? % xdX! !gK[~9Bp$yܡ0U_ Fw?2oOS#;d1nE"R+$n.|%P}ΛQhtY*Y 8xp70 X!Bd c[F *W{0iP.} G?6`?A醉)Be黏JV 0 ;2Z7'|A[Iq ^E<Ζ5q1KmGࠄAQ͛0B"p2oh 5 "XZD*r;zH;`x909 yUvL.ށh__Á /Z#?%R5| ֵV~-&7mh\8u ꗡ27`u) )xW~i *qrXJT^ !y Cfu4˓KO?848!KR a$,lu xm2@#,0 xd^4|`0uFgma = ;P3@~xAx`@# 6. #ÂR F\7 bN' KPX@A`/`0EyG? yySӃ/ikR똝ZpS:cZRœؼSWdo&`.]@Iu|2KXuYHXµr2v5_-\o.\AV)Za j^$q[;$&$uVXX<˜I4[,46|4^@! /KȐ 5N(Y#>(C`9!W/&YO^+8GZа5 q5 7"hrٗaO._{6I>6=odF-mx7mr몶N)73#egi͂༂~o*`β)iZ[p,0`7|,yi<#y [.cGጯ"cKq?jy]-B+**--F[BK  cg*hGf0^SgV&3@H iLba2GO|5)`GkLdenlj*Fq`9`A'U,쉂=,r?NY8# l50UXB$, *Ɠ=M}֤tQk~lp#0vGE;YHayda. YA7\_k:\8a`dM9Y1Y?X+a7ml7WN^g߿v¤ז|\<?ǚ$=pQru%~S ^m,SvE{9˖s9̘`SvB00H!uRaiO z\ZN2;~HfpHr3 ;Xj@3os O {moX+tv.?SWHO* 6av&5[AXK]/aw~36"uFpz͞k.Xؚ9[* 'g̣|{G>g450a.`x- 0+4SNf\~!r/U8<6p٧yoxu`B'o]է惽%n.,.ܻe>.?Ͽ׷Λ/nn6/_@1;(=vƕj1"|swwo/n֩Hg6k"nWݒd>]JE#ȠX=pA"hU Eh|ÍV{AUqE b>ŏKls+k>_D* Wo|B|? 3wYͣ70Qvp|Oڻ qO c%fmU󧇋Ƿwf(G@/[rxϨ;{ N] v>k}]@Ilxz°%Qe~o ʨTA_rAAySb5{ #%`Cd4B Q{Q +V1x 17?0`*2j`8T+ZfԪEI',2-»ӐûK8V\T95q6O;3͑2C"Ey`$DŽ/Wf^3q2G*5XIum](bKz ,IrkܴZd z}x;́]3[C]{_f"?=F\3OP>Kv=~iYK[Fttiq#'J`kd}>}iLHO/.WԹȷuf O5ޑN4@CCĊXuOY%\+bANevͮeVej쭗4ˀ$ѥ<%5ċւPFK F޲KEwp?D,DQJ{[)=^`m+D\bG-#v-qZv%Td)"!`"ճXȊT$X탥q22`Yh 'n*ܵ5s۞v%T |,&CDNdA7<$O@apjJЉ;D]ׄ6 ɹD{̓'nEPrٛMMffouN8uݟ`>r,i !mn@P,|,= ZguUk{ `G0:e,! 9l끜ՙəVے[\V5CNV,;GӃ2M^ұwF45Nf}9$52̭X0AR$enF~(갛_(6282@Qdž,:ҽU+Ű2A Hz1p=0uRfxDoߚj\4dF!fxm*c/ws:&R퍿adK- Bu4CeCIAP'AINA_H@sI$q}!`:eB4Am{ p"/[oolqaӹlp]J8mF5!ACO7thZw4RM@2 tӤm \̝i0/| @B68z !KM7$Hllx@6؁llS4=15ZJnXekO@.;H-}٧i'GEcE=O@{%;r}8Ay$Jjυаe7TҨUuLm`$Sȵ=9@5zi/ L% I!ۺV+HeGq=$lE쁲zf: I;޾X12W71O282 9 /KX7l="GΌN A !:K#!ud43|TˎO!,wF3 &YִOGcC^H|x:iρD'ֺV~u@ _Bߦhz`|3&. S됧W5q7!+ʸh\/K6N@ْ9 ƈ/ kQnҦX-Xs5\hGL\腫̕E )MhƓt[IֶYjJgiZ.4D !K-(jJ?k@r aGm//p`,vci ي8 kV@GvȲtRImM_oCTzAZ68`,%|,7lGf;,HHYw4r:8AFgkyJ"%=A|F"(;;.d؁LlpY"8fVV #ȿ5XB-fKz E~mJT4>aQW *| <08N&Nz aBVm!dI!IWiH~~+큩ӦSh HHFTeIrT"%{ i`w4:H7;&UXN[JJ9&l,ZȽ=蓠tpgO% ̘L!L2fR]ǾC02! ]d=5˝h2~LV92X)C{ܓ#i{[VDtlph]h EV9b!8rd 0Zw4VYQ2 %]1; .VF!pF5>W= Ĭ;-P Ng'*L"s࣬\,垳1Ҷfќpmp0AޖH'BsVi>BJ<}AI͖K̝[8ԭ;ۊc-s$ &Ec;!gςբ( ;C.ejnOK(is rqw%L}M\-sP -YKamU 0&) IC0?N#;p|cp- 7$jc պO5 [qi[6 S>&O`iC{'AV)S5@ vھfQ `3ݤXIQHA귩S? @h̆1V.40|R;!$΀"H̨L̺a=1וтŜ`"e !&u큟.;u*.[垥QUnI03Ñyf&e2@>68z``.%r6)p2_f  uG3*m5TGl'-LB(Z}e;- խ&uu?1D+ _Jwvhĺ&%F$VLMT'2Wǀ$]ǾBdBAr)șLe%)iZlCx(861{$j&eRBiS1j;5#} ,fx@>G쁏|LtjDAq\>Xq2vEG3|cka)AdNb2H@.: 30jSoBE-Q ʝ@XRn[   ,%vv`Ltc[džc [#eLfRF,M9[9CIm |rC%djIA$>rX;w"3%w2 A |LIל"K8!~莍Evw; YQ覧1Bp\Ҏ&wcR!q#qj]{#b{ CfCƶlBUҴ خc_X#!`lo_INi٧l7|ylͶc42F qYlA- DSNwPnߢB,Ɉcw4ÃA*;zIe$sIK %-ueiV1~M0V /7SPPΆ$ wh@e]I@ X7wOOwx0@SДiqz 0ŜdR5/F 6Ő`2 :2<=r9I8!bpV?Ը8A/d `'2o&WŅmF7\H-/jl8i(xx<ݭ׷"/lq ï0M\ z뙺EΌѢ(0O_QѢ%[Y]&G4M}>YO~9է߄t")KHBCR?7 -dZ7:\oLtw5+Mhb܏A*_&a wmJ?ȗj#rónRΤyy;j?Oq3Cݐ 3=} awçu,ZA"|A-a%LF;#GRgggxdVT g;^?&w5l>F3vMM#h(3f 19</4fr<$r3&_rWä&{L[2~aB/N0YHVJ&OK0Z|ӝ1\2VB% /S$Qq& FL,Ќ2Uh*eL0&捴V'w5fυ립Ј0GB%LT:G_?ߏSzwMJ…(75O4?rITjo{{ܙM&jQo_f4јnkO:Wq&|9QlQ#p@Ѯٔ)v`9ri35C(4T=J՗v>KY֗f\%XCcsZɪ:U:U(0/_]v gn#ΕPiqӬ#<#,CireH'fr&>ܺ $qne!o7eqmjq0|NtkQ>g7O$ {u5Pz*?ܥc4Dxk׍דkQb] $l*F yv, !-Fvps\aФiʹ"qf5tlqkTŕ(5^%PiA"U~o"Z@IO Q=!}ŤP.($6Zч\ 61w!ڜm:\*^qtՌT fȮu[~-=P khGؤ-LoaRӹ SlmTu.\nbA%kWCpO' 4j=%d j:!XP>*{͏,k@e oj=+™ QI?Poȯ:Ѹ#p3{qі&%v&\ˀȵp51۸9i$}CO69D3,1BKnHp{n~fFU_$q6Q)I=I&5~KN-dLntmlҭiWGa7ֶ+T8V8:-} ]M*OW0uJ8/V-K] +Dʮ\I2.K W'rYA˕oOtCitrbntbpݻs++s~Q^|J&: Z^@$ʾ\Ib.L դ 8w1' ;?fH~Xu$eJѸݎJ?To\ Lj˱#9C9\HA:e&[eG 2)6+(5p'{7&c., V'tpݻk1\hw I QhI}˵F Z &=F V]xțV9as8dIVdžރpo.hh#l31V`DwNz[!-F դG 0k8_eFwٮ%mcDr&;wkZT 59r~zjhdeL{>{~=xGlPp3xZ@}z/siiyK1D~²$#Rx nlcoN'edd' N+*lٻQyN ![Nld j<ݩ,]$6\iON2 T h&KscF }څ2fWAKth@M\  I gsR2>Fm,EVe,VEg 8j,9zw3^*k鑂hY&;Zv]2k$=|#n8ZF nЫxHB'9}Fd@av;h]J4 dId٬ ̀ ȯ֬ dIJ6Zd0@`8۵դEƼKNd1$>of>whE ceHa WO w۫bPK28D|_Ӯ} Stepper_Motor.fzPK>}fritzing-app-0.9.2b/sketches/core/TemperaturSensorLM35.fzz000066400000000000000000000561231250202676700235330ustar00rootroot00000000000000PKr8D6$XXTemperaturSensorLM35.fz}F5wV۶f̒`GIVIjLZ/YJv5$J}y}p $2K s_}/_ьM/f|W_=\o+Hf2}1ыkj4?d^+G"|Z}3»WcxNjh9[N|Ge7z7_fKH_>ή7_R1R˻WW2S꾚Tzn1z)S\Svqyy!Ȕ_\+*8cjzn^$\:=ݪF᧻WDž˛>_O8s2)wrosΥ₳ u\kW|q:?_mzx̵$[|{~{Jz ju}_PEz-Mo=%!9 9͔?TӊUn~zh]7G{N1}|_A;?]s=/>P8U~ͧ;69gIdN&sf]ZtSBњGEރ&X^˻NYƓ:Ol%uxTZY"o9@3L'63f<1?Zޛͅ<>NtG2>8J8L7FУ4׸|qs#'&~ȞYƑ {ScÞ`z{vqd؄o382a{RRQFgGKz{"qlfE7<8Ft҄{p3sb)&~Ȟyq {xFG82L=cTaOL7)pɰ'Lj%ÞzRv{Fp\=<;/}\d3aOnY{uU6>`89k!",Heo3y,T=`g6pt|8gGÞ=+8>qL NÞD{y@{i=;815QgGÞ#{f G'M*8 4/:ܼ|xr`gpl,\ZfŦÞ5?RQʥDZa]|ೇēN{>/j 8U|sS͎:2yq"ʰgǦ={GÞMbL>8J<4|س[yŕkg|1,_dvX_N_G;/__~-Wo^O~\Ll]Յ{tr{ev6|-o}1a`s9`4LfTdi#2nhtYfɸsQ~;d<>Opt~Щk jʶOT?/&(4ㅑR&(:KVϳy3UAemT6f$, m6LmD֩ԩfBއV?Oh6Ę4ҶHQ4&iy֦ 5B3[9򍪧]wJXh}!CBa=Z+}uU0'%=22'Ȥ }L+ʹ@%1vAˎNgѠ3Bw?)wrQޏk?qm9--|^5xŐ!ayft(2s)5g*Dڹ/F.܉|[IVri63#Di9wm'KTQrSdg67:]ACCĆ/,Yr}~i2Z$Kh&&K4"EHd4%K6Ki![RQȖ<- ~Y-f?mo˹E_o*Jz+T,m6f.Sd&e֔,I,Y%Kl>f%)Y$Kd,U hд,ifɶ<kMנ:eK|b%Tl %H0wKXO0%5w.JĴ/G>]ʗ ؄I(9Є |RmQ!D2kԒަKb-K׬eJ b/)ה/ɗ/YK(0a WPb|$.&[@F] &u)aɶs7T&&bH[wG#w|v9v-%*2OF8mY F#!R#(O{9ΑO7 '!!3% Γ~.jM#ioo"ix(tr%Ȕim9q&bg/v\ڤID| 3p*ofXf(I({m8tҥ(IVb$)- ͇i^j$*|OyDR4쪧رZj`&StnH/ JrY6gޗ( )n: ?ϗw..y?OY=ceD=ߢac4-BW!+Hƴ(xϓb)UlFbx۱-;h2jmrѮ!nHf:[а *:{Cg :˸ɘ]nw Z ֻ18+b&.SOz1x3kA%~NVA> iK܉!t{n+GֶZ*7:e1.`~̸>痳'pZ.Ν|v}#ɔVHUfd]Jq)Vk }k_LVRi?pKOwWO]o#woXW5BS)|SIi}㠇)$TdsWYqxz#$q4'b={ff:)~RWQj3]bz Ukl|}~/\Jv&q=(R9'o8L o|y ):4llw3N#VS8IiX_ iڛg.?Wp/\fq{Vyu&,=HbY'm>L !{/|;ʧ䞌4ܓeDTL.]=U~'\쌄MDtkoJ@_aHDt "dmZXLc_bu"{X&>H^,emGb >#%{Xdv w`mz?{;_˛d33|dͿᤛd#&?|?7ݭ r>\fW+<X꿇c7c縛^_V7-+ NOc~trXlt;Ǜr:^8=ΧGwؤ񋇫O#9 tzo/o1?tfZa~w~vA>V;ݏ狇zYbo_>\cV]zn<p3yA<r}fS7rh;ܻrp5]FNӨq>; G`'WFJg˛]P>Da9wK^?z<=UAdu9 d)#޳ƃjxخ{LlLs&ٜfp;^kC,at/s:ޑ߼]ncLfteLʧmC2bs'uP1ɬUpec׌]W(GeJ/_/n9,SGȤ }cV>u3m#_5V6p*#D~3UfcM"ku~O@ؘhcNe'@k[̘8wO2*UxH nTX}Q稟rNw9z)k/ ,Ia2/s38ʥ|c)WS2JdBj=}awSlIњHk]klNM{UڵTקX1t=6sl|-o[CƒZ'j.a=4O(g~cdڷfwoCY2_Tμvf9s%`eKFWʋS I|5AIo}0$UN6Sck03.lV\2r Uȿ>ubIci÷L+.LtvܧXñPR$τ ˔ '|RL4ɶnLZ㥝I Oz%#JWԔdR8O Pk@+o0+H!BIjߕ'~7ģ#ţrOuo @[4eZt>!yN_0Qӄ$ۺ=j_i$҄%xѤ3Z۳i:cU6M.r6R(:vN>:Lg 5$# ˜L4)L4 u{oNPQB,UZ8Q'0D˨AMiVSH_'fPiʴ0Hk Uw#$<$_4銡:8CcVd)oj 6(ik@@BwIC!k,Juf¾mu4K'% i"lIwt{0-^qCLǀPux+{7#:/ޠO+cڽ`/)!b{r)Bql[(YXh֐ 9jgK绅ʪ(FO}|뭆m"G]aTQ "quV ɘRPn3y<2+4ѰB T%+n Ajk틤l^ YБY ;ªȮOvԖ41ʞYT!+:)(Kѱ8I9LecA2YWҝX,0yo#+cȋed] .Y>7 RDb{*;Ό逋BKJe9#_C݀tbfmH!a.b ;(J9GLjzFeJIeivK*'[i]n[6Wsxu4/oeY~|^ϗFw/_WGf]뛯L9^ ;ʆ)Lih45&Jת6 suhǻ䢦"S/&1a+K(:Yd _Rov!tY:ψcnH 2SԢbfrw^Ю}1Y &J~cϡf26)pRn^.t'g@-Cy[4Ϟc ¥&[~rLHR# QK`  t](ܮְ#zFG |$hoEv5f91@l)3)#uT7M]B.$a(qHB$KtݤL4S$SJ569i`e3{ǠU*yzq}ŒɎYaGFD&s2X )Y"F%~za/Nܐw '%6&-r_A(Hkͮ6R:#F):P%nw<^p>ަO:A0 $ nidDJu?^k#[]rGR5Mu(5')*<VQCmwmLiH[HRƭڛT&kSڂW f8'+͐[ B#]MO+~Dj{[K@ C$οKZLVSm1IsZتIUfO:ތ]$ߍfiREdߥ5|&M-I"g;NQ KmB^zm Ⱦ /~ûܝFьV{)ϭ琅O?ή7źTd2C 7ٻeq8LZk \,vqZ\t=gݗ_^gw;J>ϯoFFy3lY._O&?~>anr1q'Njc.޾_,U4ͯ请ߍr?˟^܉dՈh4W$qaf!w 'LJ݇x5|K?8s︸5N;Tqk_= 7y^>|vBLB,KgWᚷ~;8?//n>?)ppΣ2B!U?~gS5W~@g~G/h,C+\ f%Y펽q6@_$_w7PwUcg B)`%,ҟE|Re?:H"g=9&r{2^ĀE/DD%Fx*&oHnYAcJC$4nf Ql |82+ @~\-FZo50)B[c>;ew G KCHdt(xP+;poXS hS7s~s8se׎o3vƵ%.o\;]JW?hׄզlB6qӨ{ H o%qDxq)/S<  n2sOQݼ>hSpDlƫ`e x'LԂGYqw7:x AaGS2eF<hon)%SPX0)P[L1d XВ-@_WFXBe D&@' It?Nc3zy v/n@С 9K;lDvp 0OխWep}cx2>@Y@ 0 #aIn;]ˠ[%gQV`` Nuۑjt}VA8LgVn4T vpY.[3q] 䫤^ 2Z]xCP yp4 ptP\{"рGCPV؄&a÷׸@qYp* 1f4P"=?K[l2:;𮊡㎴3U346h 868vpixRPBxǀp'ENE`sMBkVAUy{ ދ_!/Jyp Q ުEJɢ!2ipKAbM0 DI12 @T4`xThB%Qv>`xE4. @P3:c+9Z,DA;0ΐ[%@K2 p8%$u0ꅎN! =^[x>`LNA7%m0, ]&eઠ)=҂ب=Nf0xOxJb\*[r'ZeNO3ovvYpt$e82 <)o% Db1H"ry@ġ7!QpU(7 dm.@׍ Р\Q,rC aH & zL80p@t%n R@ #%m.W3RI0ZO_^@Z)$>Gp;Z  Ih!,pA`8 c~Bz[Ѷg!!qh` Z:>EҽU+]q*\ D -pk گSS4l* H0u$ B01> *;:0+')n@4Ag8kA "7lX/-tdQHb FtEZ cfWϊP<äLȘB,E;O+ E`s~[ 0geoGWz\7̿o1N9$*r&G):kMbq4mi4,rQfQU c@sn3!hb([d@4ba67l 1<:oCeUZE4x['r3@E'(V1IVfALb6<ķ19Ů^9?)a40p&1a/ !HA!s80 Zdx]7,(@ Lf0N@@ FDEDbcX@j(+\QAՉK[1aJ <ߎAឭdhvLKv cX\cа0&!xeŰĀjt(. 2b0Uv Md9a *ժl$q-,n@mmhax>#H-H4[9@#(#/i")c.XC6=.ݤQ":-;uaFʍRBª~pHpg PЕ4%y gW楸Shxi<|4C 3zUg|eJF,R+ ,'Q'p7 ߃fC[IaRހId[RW*+848%S A@էo}' (TM+^.u5%kICOѷk==;JAŖkr:ѪPʕP[ ђP˒P`kKBPI1RH3dl Ԟz:LPu# xhLb`q0#'h$_p =aI"@W7$A pbTa6#AlT0' @ʡг8#tb*\]c ( dޖ@S>k Fa7YaFdK,N%> 9R}sre 5V~8Qa蚘RO`1Y1Y?X),mYڍ<`~; ~8väcGN~bHqx\ݨJᡟƂ5ai(f@D tSbE/2xdVmEk~zKdYkGÈ8We`Qq0H$p(ۧAp*EQ"NXES4WXXtݩ R%uV+efܜfyPtwbK6yq bXaHB57<5Cپ;DsHiq<:ٓ<;}my< Ou791 Ԑ8OЙVz5^::KPpmQp+.Z+%f.6N0q*:9D;˒FLpamaԩ4RxT,Gӂ9W- I]2+`ECx\` 9FLc O☂f[k-Oi'"9B7FVE( FۅԬ8\vE7j3!YW]X(aA9!cxjRj_[,C NM-c0QH޸KLƱ/ !]t*0ddJLB/dP0)[%kcނ'e: l/>GS%nKSXikb:_Lˇ/ϖM_>ޜ/YLNߋ\vu{ˏ;>w9{0ݟ\Yg6Cv%ɠ]JEk#eݟOA+D|-*ф״]F2VHH5|Ngٯe]y\0p8?tuC+?YRL:Fb2|aL]Q~/w;KQKQ,|~/}rf.[W;r~#)Hv`ַ=nڴ٠Yq rR%NV.3TUn^ZY;PTk^q=T-䛮Q-dؠjժeU-S-۪vnURCS-cݛvEAopղ^q ԪV-ӤSlY^ѩjIyo,5`[ Y qި٠h 9AI8M <2pfjp=U ~b'1 }M=V\>D O;Y~S͸>&ݙ=aV,WDOfT-i!@Q-i>xӞbF+1nioT;-@z2./0&~toO5 TDy&Q{Tn!2++NOO5߫?ݞ[#}r~n~R_i5WWN痳'{qd}k(uAT>~D迵::r{c^;Wi,8yd-#!xb,ǓkvO$Dʣĉ%}>$  xz`@ko_vF_q7E%|DLE|">YX@3LvHV:l$/EbiSnU/ioD؟\Ӡ.$Z8|#ۃ]HXX:$r<]/$)YlnƉꘛk%r(JR*m@Xh%^T5|#LIqDv"k?[JnIʩu{0$ԪI96ymTt8$w $¶!8ύx$RX열k;zYXXmCHgHʫZhPó6Q?K1q#ZĐRیzWE gΣpbfZ(N,yN(Ѹ1$تiG \rעćSr_y<~CaG!%8=ל={j;UMRb+Oe 1-ԈѪHD,d؋XyQk)2%2KUݏ:X>נ(mm8q7 8q^:%>87wN|{|Xa.E N X7Xp}'n ' 8qRb[U1$1Aq z ( #cĢ(K|q k#wτ͇fp h蹘hυe똭%kL]:P>>ux\Blqr^q(vagra %.8'ͅY9` p[fկWzM(YbȨ[5 Kȸ&'2W}j5O"'NR,@iَiqMqըsz.~c/KXQe$dۂ7C)"qC=t]/iK4 mmW 9d!Xb:mIҲ4&ǿO=U,E.a%SGk7ͣJh)'p:;`:sa0%i&_['`](M94kANlW[ (RR%=ۚӲ8$x2U(q < \0JY.NhV;σ`J9n2Ro[}[KSuY)FK-ȕ uphkCLgJ[([@ny(#LIyHIEDI qN@$ FsKYs=`ᵛ)4QM ox[ ڹ~*l ʼn[#ou "5%pڛs}DGT8YMx\EOL <.w`u}8dVZu(*.ALMDrR~$ɺ4*ten]k\REDIUќdIy $.8a cnT/Yӗj:7)$B]rc]SAT/t5")&zɵrːx[n-JFtjH$; 26IkI y@I8theҁ4+[n* XŅdՂT$P8NʴJWU")bǺ-ɮ#1P$mePכA%N}ZlP$eUW*Bc!XqnHF97yY[;& ҎۣKIy I jo4[0:UlTRvڛA%M,$t*c p(R0EhP:dtPfRygT#t2mWחfbn*~"~P*U؉ر/At/5$VM󀒲咃.%q%joǕT,Rg fBKx@M[-tUb\Zer1.3hV i<-a$H0tӤ[M_ m1)cBH"p#IʾU{<[(\󠒲o4*)VP8Rt%U<"b );fGAq܃%i>^^r$N<`7cJ&'Y D MLQ x(N$HvXm567$$? PJ &U{<`ܠ `Iy\Iڛq%%7,B&1ihVU$ݱl&E}t6D3GpͣH*lJ}+'ۇDޚGT"$޶Ii+|F*l2ڜʨ 9wQi# :^V( D,Iy$IjoGTY_m$f<`7ͣJ,МbR|06a#*6̢`k$$p5U2GLl7MhN46?cI"h-I"hmK'h]HbhHbh-GbhbOrY m@. U)&`:@cp촚@ n Og%z^ $fǺ4*/ &5%~G!%hl 5 6Q駱Yp*[3$z$zVכ1%ѳ6$$#3OeO^l±>P*8a*kVP%ڒDVMv&& '/u#5"u Gh悆`DS;#w\XhS->8-1ޜ">(#KYFGTW`Z hZpe2.$8$$fIܗ.)_*4GGtg`Z hZp)Z08Z 8ZK(9͚58sB";vFt8OU)6~Ƭxh9EJZMf:CZZœQ[eGDǓDڂ׌95MkkQmXh}EV)U4mV8:f;DZ@Dڄhg8HZ(HZK8="UEM8|)6~J59EZ &xghHZ pHZxrj_R_kP_k KaYn n,SRFUaM3Dz㊯$$6$p$Q$d0m? 4wPKJ8D}kTemperaturSensorLM35.ino}Tn0+9I#ruK_) A gZ,)N7˺,A ݙY% ɕj XqXak8lVk%JX R[lZ,JkR@ O՗60Jb b!I6MߊDrfT.&X7ZRfc)~^Fc:tfV(}*i5$J'I6vzP=P l*N tjw9:nu̠n;L p}9% (eb]!Mq `~pVYж>hɖV4~;ͽrmƍ7+sRkQBA^e`*y^ubk5q~mIEsCb1ǝBz =`!chޝJG_ܿJt9Pdd!~?*.#?FWū3p)_{'Eo:pq7ݎ&Όw`|qZcWx+nZՙJJwC{}s7z^t5N.^O٫\¿֕+菁MZ޵q>.ygpzOslz`zo6|V`>17&2e#7B^Qs^&f2tKcҜuA̅KryN@YeZ7=/os7p?v ӛM>{p0w\w٠7YrYxx6+Cr!Ӓƽ/YQ󣳇wb2Qž8!"Z8%fKJ=[nÊm B:T+>EB+.[gִԆN._7U-F`O>؅gP'-|XM({}|M'kۺܜ/-;AWlpVRImnWwsò2#&+ھ,k^c5g&u[K&JG":c*Kw5 :>Duu{[D5>I$,Aw=FօbĦ۟ ftsg@i3Aɚ3 ITJ Hcgt$LB:\3BCI bĩ:Cs[M۞ș3 @d=<j? y7acAwPLEI(b#jGڞK0LuQgw8j8'-f?3G<&|Ew6Oog{ӛ-ʽ+ yN`ʦЊo?ƽ'O }f$6ZO_u0J Z~y1[='[|=V105G/s 91TP(Կ!𦚻7J&FSŨ('E%XI nUb9B(kXJU> m+:{j_aj 1;H%=xpP)*d% dxLdHiB(MىـG^Ŏ%Dp!3y#<\l%blc[F d 2օbP,*tDviL2pKHpIX}WK)rjm~ *N,)qyIXDk2ېhfeΆXn.{X_aoZ=#c(:P jwLj^>!vYQ"H-D]S85@dRfP{C8`H]]S9"s#H:mIMM$2QfKi嬀X&1VېTs2}6S% (hEk(梻ϸD؛܈OL9`9gRW$p*}Ɍk>YQbG-D]S85:^adV}Qa=F2LU$RtbX aGTh̸L&Xž"שK%2m.܋MBzRgHjnQtM5vCfl~K'Y .liǑr(1!E+D/UL=(nCʹT"G ;3i#(CBT@7?ȔgYjV,iL8 1Eꩰf`T9fқyba[]7_J~s"1M;|W\J7wfxzSls8Đ\aKE7cF A-Jf7 /.Wt=ZbyƋ柯ߵ޾]߾}Yv߼DB~:k }rϓ/߽ cAl_$/W/p:=vkMz׃Wgrw }],ץStbuο3r4qg_PäxnZxњߏa].Z⧁+p~2kY^bt5Zƭvn\}ߛ_.~8h9E=`As1d聛/qo>E˷ ,dֽè7wu0Ogg8o_wy5PZLi{Mv70ܐ0%"!  uv?W~s- a+H޾kU`D{B;#_^pr!Eټm`k?fU7=x?->.xܽLg7 nP&eR{^#u-xkCu !34[8t4Y>]ܪR*Q͟`P7ݍz͆%oww׷9$oQ;4 M+W{1F1؉ئex {10[dvQms2`)}-:Zn<?u!wֺGޣ]naIWJ'~|0'7Z> 暜\?NeMe-Dppc =GƼEmXG @^pb9UkƮOT&֕¼TlтoɬxXGئNI8R=XvR6" A劉o*+X4g~Ǭ^7䓬>fvC8y #ۄC&ՏN&TZ$FɕmԹo* &3?!LEa O5يc& +o, vpzFg7Ƒ>++}ƯIOl7jҡfՍ/p ɀ)@)}⽹&K t8 qQ^[|%^qh֭/!I;ď7EltR{: $*EPOi6Q!o8N}J/H$Bh64 ale%#r?j5x%[ I;b0wLX,$&ZHDhwJ ^ZJ\r^x\lxYe]f).:إH&rj4Yzܔ"AW y-jZ 47X|r բh秏CC&}.vYb}ܜ.FVGӔN?Rk3$a[rѥࢶ~VkơKaá?{=>SJXɃZ[n:")lW+Ǒ $5.>RlV^JiwJ{Ѱw?j.1$ly10N"!abi_3' @jWeцzsٮ/"a#f~iEgM /sp# .ϭcbd™RLBW@502"C46 s:I{bv"iMV` Y &J' \Yl2R /{YRIo"s}gfUEϝE !u.,9&?;vWbbp]\.U*NJ)NqYG$RS.ƖѴ>дCѴH>ޚ#Ѵ ވ3ZдӴH!Nށ#Gii'<#FJIJOr`pi$J5"isҴ8Wu.4-ՓҴBy"A{t4!hMHz{ = C*z'Iڻ0Hp ȉ4īd:!GJR&2dԴmߺW(,yn*ѶlQ4Ů_ =!;K wrP!z;NJ Wݗ6T)hէcH:b:5<% 7hHNݻBcץr8]Y4QtťT" sFY|r&b|{xwbak'wxCuaoΕE"+YfGy rP{'/Vl3#ev));.rw heC̫†ѻ6< b%ӺgÖ6wRCqVimPC$ℏ ym385{!6~ə8^s3ɺ̑YW[$M~OLJ˲%{ ,O,u19[-F!9YAMK֬ qI}$]@!>R;" 7##:I 1TMXTM1]r2)IhٲD-:6X %i!iQ46e$me6Uٙ% "aK'/Tݰx>.m=Uݓŋ!up4u$-O@2*+[D@N5@5SlEk`PXDZҚu.+o:<}f?'C>={! 7*7bH[e1y=2/cˑnǑ;=p>`E 5쬲H']GJ=:ݐEME "5tqjN"AfVUtYQsiG !G$fți1[5䳼u~1톌U=sw\H?z9I$!N@ϖ_(*Q*k XYhRIo?1$aBf/D4tXQ'i218'd[3S܎&Όw`|olf0t?c6Z1\uӃb88zvpsq.8ӏ9l~5]^AY7u? ~-ݍ>]B`ȗC0HKaSzw]cW8Яն2v-[tb1Rf|hRoFWEvJ8LZՊ]> ۿ/^q)h:y5M׭?pJe|_]-^~J^?_kZ?^toZ~E~׭͋n>tv~ֻ+M]0J:`sEAvS-췡>Lg۫V'?૽hh|"m:REe$&W_vx|Lނ I"T&p&0toyP}= *{oY-2MZuSW9E&sMo'i)G27n fwL-/hiޟ KElĊ3pʏh /HQ(fuD*&SҶI"uޤbቑl,!uG:rw}GP_H5riN}(MF 9p־YLA% <\vsÎ Z|;o@w Tj|Y mբO/*}Z쌕¿ѬWÆ"ႍm'(|N'u ?WWPApW>nN^}iνh8x(+kPUhOۤf OcZIfƕma:.iTø{KeI@P2Cg.H(Tv麻ދap _ %Q1rM]j8:od۔;yCA)P@ *߾oۅ+ếJ"%/М:chtJuK-q"O+7,\ۂ-δSqW_]i>]lor塥Mmbā|#N<}pS##Z fL0C/iC(Q^Ƨ¶ !rzA!g' xD`S82G??% && R R4ju %w5m\ 'hF4 <>@ Oh+}1%k'NP6a !G$r^v5j! [ϕ~k*EAh'ӡAB|A쎍 g)) ZuЫe?t>4\wi}FRuC28F!n6j0/U* U³i;}N{RtVË&K펽q6@[$]O;N,lAȑܿ9LERT+\\ K޻cz:Ћϗ2^ĀE/DD%𑎗brG;xd + =Dc4¸ clכN3 F pt`zSv4H"W׫*'{!ԯtZ^<Ò4aRf/ #- P1v6A?a=S8 ,*E-uk`މ 1VnjϜe`~[ qY OJhi^Db7X@,IBB_;D@z @ GPQBx<! hkt9*Pw5v7> "*875B赡Ymɇ'A'+'‘ Mpp`$t@ 7PJ)aOo+T\)J $7// /``L#H8}SrB$T;\iPp#Ψ-_Jڶ"˪G DKǧHR^i 7߅@tA!k@t,hN#ԑ4u8пg.'ת0 1t&!0+h7EoIG J=x `;v)C^nD2162qZhΨ /[G1RN@z6ʱ/86 $GQ2;MKW@sx`_VBtʝVre$lSy[\ sC#aʸhHX)0.90n0bQ{f9v"s+(PŌ@^BRa ` a !')BNLApr%y=yCNb(9ف&YtA@w !B& kJ #Đ@ꏩ{yΏg#J0Sv  ϣc0XC}M4ŀbA?@ yѐ'[ -@ >pHar<+IM>pG5hjNvY'+S,|HNz P]C?N׆F9gLE "ELD*Q.!:\Bv[+jw(3]J&ca0*R y#avʠ' NC"A N*";>A;8t11],%,`n@Ɂ n/{ʊWDs܅3 0C1i,ex@?F qI_r4H_z C|0r r  B$4o?wA\ #Cd`:͝ƨ@ vZKF1%CrP` @ADA`4[}l pjfZU󴁊acn,󑮇i' cq h_aI;8tƉÀDp#4:8q;;#^8isx$:Pc.8h,:~d4.!G݊arAoja'ƫk?*N.$c8Aر qA(Wy(Dc†*-f."#RF]bN̝ڊ KT4eaY hZ*6ډڕ69{*Ợ&~oܠpVcvLu v c8# ~`DaaL;)1CNnpv7]?kt!%je2J3@ uy6Td:BspYyΧpأBA D=spG Nn@uЊsh{XT .zOb 7:CA$[βRtrUeW؂G8`Kէ>Fc ew/5U|͂ õۇ5?ҖiCUPq[hRZ^0O,TF2bP-5,vPyA<#:1qLmdF7ށN&,e(Ay# 4{iLb`q0#'h$G8pJ"@W7$A̷ pbTa6#Ab(FRD?S U"kB+ELEY`V'8Ma֤Yk@?1 O-RD0퐃 ٷo\sC`q)E*܁ɚLvHdU.LB1Yl7 /Ȋ3 gx8]'0iؑ^1Np2A~W g,8 |5G-Fp&! xJLEo7 oݐ~ߖզ[/!' ]|?|c1=|m/ք>0 ӿ1OBMh0.f1$~/faU=̺bxcUgFxP5d)[,4!psLW8G!5 c{,"烃 gcB耣9`^9ddJ_~;Y0)ǡXeW[N{pfoW}JOl\bkܛ/lì c7sXŠu?r>)qe6s:]&|-J$LpRر,5Ïܦ5 l>Q+ܯat/,A2ʉbU[^pQ} ţw^.uf8tJX&͔B4GZ{1F_Xo \>k/Z߱+~nraEa}EY7Yo2ή[ 3X8.pW>r3"v78沷WzۮO5Q&>BVͻoQ޻ xӭi#j;3"jAA*e/֌Veωu-u \K[m3a1>ҬbClw^n.Vc:N;- JԻlЉu҈gMm^x7)9MvecZv><7دeϧ`jHu FE:4!0&Bvp9imzP/f_VsI7m6/"Ns dWmɶm Nѝ=p؊(Իa!xP(OWl 2 .NWq񈁣>~cɶMAShE4<%%KfaaI1[N^#1 =23q0)ڏ3{DxT f理9o*ܘ香EuSNebce{ rkRS%)CQ)ьxn,/aɧ&=%VUtYmN! XGMl,D UAR$|ÆU?vlu^E#wzHg7l辙Ha>ޚqO͸6cF|=>ې'"ō:I{`1 ?<k)MPKt5Dw5< TiltSwitch.fzPK;5fritzing-app-0.9.2b/sketches/core/Timer.fzz000066400000000000000000001737611250202676700207000ustar00rootroot00000000000000PK8DF;7Timer.fzr$Ǒ&=qPMI$EiggFCRBejC+쓝2" UQH/sOϷ_a9[_??sw>~X<.?Wsw%+Bᒰ<޿SyVz|zYx꓏OŇwoΖ/ge__ٛo-&*ޜ}7->t1ǧOwgX.݂kKot!n4knqio=_7o~zv˟./~⻇˻ʦk{qŕew^/sK͍R\ bR]E{u}/^=-.sᛳ뿾zxys7g?=퓷Xexh~f~bd?-.׉_ͼ+gxekϾ?b𱚏 Օ?^â?<]^/h.'|WM~ٟw_|y5Boof0Ww>č e~G;#1oU }_|/ x9oV3{.pl$7/Z=~AEqvzi?ӗ_{wӧ/9,p.ҽ9TYCZa0_RAzQnuW!߼_i 6mc^?v8/3Sg{T{ kuӡ_Y<`odrbs5kM3q-k{x?sfm@YۜvUBcSDns\)6;{)?L4 l7pE&;{;WycycJ nX@c*kp\Qyx'CINW%|r=Xk H=i^<I7Xn^<I7.YXؼ1%t=mޘHwqb`+ KZ7nqつp{J@ ]y,k'yx W8N.%tp|oyІ@`mPwp~Cq7bLﲶw FS_6y` Qܖ|WNYß~sw-22[=>n@!A>ɛ0m;!#l;!튇r9>/(ű|ؾ+oj W2/9 4; eLhC1wyIe./l!l`Z\ AVM_мc*!h{Ssmcy΀ӊ}ۋ!^/C?<@VђX+oP*GMv-lUyqǐ"yǢw4i͖. ]x vNvt}%e|6naI_"F^Jm^8x%ewx6nycɎ.. -7z P oewt &y/;@x\@Z<sG/`^v#h.z ,,) ]vh.K - -7z Pnšwg H,)/V{,_ ,@)Y 4c6zާŋSw (ehft,l.; ]vkh.kĒ@4xq{* <@Վ, ^>.^x7`.J٭X@NΎF,ЦwtgG`. 4c=w_f첛@\% ,`Vx`Rv;b=W [T.n]({e;j1~CoZhvsk/?}/.xz@Z<&^ 0@\o7`l`J}F[@"oFZf;,sQUyCxH2];,ZUz g.6d.z`wy^f..od7`[\<No7 KޙoџZT![rM 䅐,o l% تyyy}o}_n|uh/|qx~txx|Z>W~Z\\Ln>??ůw/kGyYus/_/oQmս3K4jš^}Ι#WS[u5p7ZNo~Y>]>~Ttޜ=<^^.qT@{uYs|G]?V"+ּU:+{]Ty#TN~{uxo/^,3vɿyԸɲ4`n^{v\}?!'{~iʅ&w.Ct x}[>z RѬ1d>2O2 g|: _Fra?ÿWg:n* 柚\>~qq?yxzw}O˻^a||aq|T_?Wz~[M_y[~z7\=Vyz;g|x|umGPø|*JTmCWuZeyzL\oQ*ꋋ?=//v}G&~߂v Sz`?0dJ VY~.L܉J `bHk_ `J W&F`Z|kaN2t,'4t _sN*&N1"m{`… 7ۻ" h1k]ܥ_5D FSɐnh~XT492XȃAФ<$dӂ=./tBk9 $p)t d3T` -(>Y嗦 Nsn<8]ҿoϷW_Y>}\ƈFF PٗlV~g?sA_]$O|IMtsu9ceX|:\ n'V@~Ǔ|bDĪ[:IzGܸC j 2@8V?^WhjR!#\5qB% D0 1`4lgQ#p)M=7lR_0 "N~oTبs矮>.?zxpEj{Nb5(FeӗrB aV0Π6 ߭291q ]?x '׾/n!_ Ԝi3B™MN}F\1b;#'(c(\j|Eʘs[9Ѷo~oJ=HޫG@Tx(Fy+̌|gZ6r#|ABkU)5n㹤p3k.P lWrEw7!ӨULxd # F 㝀nVIrj]i,6P yyeɹx1漲܀xwbګ*,81/X >,y96HWޠvJa<9Dl-9HlCF)y*769O8Ν#_sSjKv'9DՍ V)UsH@t署Jt?ܬR G75ꌒ{_pg=w|ƺ̙92K^"|zH]5a9减 sX?zaΞ/Γ~yipjvס s©S_{@Vècv~wخiT8uӚD;_9IZ3{{ûR^=\l;{A;`ӂ{A.wYRwYȦ\ "xS.dʙ8txfⵗhoUpbzIDZ yժe/ddV* x~ @[ޣ$m |M?y^[/Lpvo?2݌ȄIմUd2O,pߓ/ 9 ?]rc=LJq#/i!M062ջk*;3՘K^Ӊ90 YO' b: Ĝ 7 0y?=:f1 [ R'j|`SloN YUENP2iB3PS&J] MmB6xAiFSHhz)`7Jf?XAg2_0@ vn j> ?OFv4dszPݠlF@"@⩶m;m|q#5 'Fr:{?J Z!En (׏pJ< xX1M9$<2n)lӝV9}wļO O_qaMtU' 0`ۇ%ёSkkV"@"Ê8ffSV:@ ÂH?e,O(kP^t.ѵgK"wzEi*(9%TiIQ-gS(mGnC|jc m˜YѮZ:)\P0z âg{&ok( q>cgLV )|:<|0| 'jx?kە[I c<9S?RG->?!ϛ0|>v^"SiXu Wx\u!FF q bT?h,Hw F4֮?KYv>*kM .#0b:Fمb=(ȅ(N\p-IZv(/pMᓈ(Neo쌾QE5=R>CI{ eq =nޜ{AnEU .  {FQ@ F,-wz{\nbw1}SQr 1}fƘ~>QX^~(leA~bFL`L7 glw/A}~A}(; -'m.!Ơ~sǎ*z 8>' .ҁ*c41$ bP?0,u/RPZn EWJvP`/ֳ^Pߦ 귥 Cc>I*[1k1T>\a;v=K҃jcs&*"PMڀSsj9Eϓ;AwwƗJoV& V[Wbp9p H:pqw .Zv(@pap\v ˍ"M/\.!`6+g&Lc[/kƒ4h L{I{\0bWc6Å2Ɩ A&YvwZ.篸vub3 Q "Rw|b_@vc܅!|1jk7%M- c`Pdf ;q\M-޳_3(=m{m0~((lCW>a|=8,_/s9m>^ /s͛[ŐwFQJ$1Nmo!w5*͈g7Kj/ .!AL{\0pec{ϲ`4&JI.f'0ر6vώd,0uw|")b2D(v-Y/ӅMuJ0]P;@՚ P2ƻ gٿf0zx7o,+{AR' Ea8õݙ>;wo% 9܂ݎ(ϟ1֝MxƊ0'adu AqB[0T>źEXnI$V鶶T3v^Ey(:E=% uoPˏ `=.~A u7a{[Uvƪ믙UTeP iuk|BlrY/m;Ⱥ ύ" ~ u[z>!QPZ/'f|XY/.z%lf냳3 ėѳver|p/ZY 7/0흊\K/vAv;sv1Od4;cuƐwϩǴy˗E˭(=C[Řw>aJD1F{aл(JUy\۳-o!>zz|x|nB?WMd=SBO)>4M7_(fz87GIUK}|\(Ǘ)7T?k9~TY"%U_OOpuYö DNv#vJ*gs!1l#kbe-J\ a]m{{bme@W ^# 9] MxZ1laҧEHc>! ֞Dr mܦ;B;R"Qǃʫsrw&liCа_ì<[H={ܳz%pM|dԼк3CI5Ӓ77DWO.abqD;~R%Oip.kRAҶHX;cF?E<@3dS) ^I?[T5?-u'AY~a)k{L(K䖁j¬V1h,d!ތojGfbr2\)~"p/lD2n DcG2'I}J{6OUW6ԓy D qO<) N4 ͭݞ E>Q0f'^0:9!ZD!Dm`"nbQ#Tq`%GN:z3\NΕ3l2%Y#=ᫀ(O O)ONM!81D É.MZmJ Ou6oPZY?nT0z_M_~)وڥS0T& `(]_(8*#(dݱu B0`~'7{Jr]@tDaS G "8\P#hH8tY/}(GfM\a%# n&w6\R?T'(۵ڳ}2Ximm%}29 ym!E!לb"&5?gaIv5Xń1:bEhEL:l`GN:1FXĴ*b\g"VIK"&,bʽsT^ByX`b^3 YF3DѤה12&eL ,cʧ:=.cŲBוюUd˴K;:Zs%Ro8ʹPW\vD~hԽShc.k_>+ ^9Q_X⒭6m캭b˷+PVM["-{WlYbcM^X-$͠*jJYd(m}M(l!r q#ZіXБdM_H՘hgn7tՆ!)H4s憹"R{~ڳ{T{#R$o}"?xgcp:iiN; rlv13c܈?m$@БTS29 4in*m'`1S3ϳepAuDb5l $o-팏H9vvI3Ƣ x6Xibt&;d("Dv93_<],@ؑEdԓ)hںzD;iJL/mE3rflc `_CF[ab bg"G,v&!3Ď1z$cgb]Z$fgLJDuո᢭KIjmNV *0;pq Yr18ٮnSaAtd?BGhό#d'bGV=O_t<<1l3nF,?Ɉsڎ| T/TC>q d9nЅ,6e \PI5] !Dv13cF?AO /|$㟎O?UbT39UXfd<-V'^TG/'|2ku\s8$Bր |vPj'%rkLp#'bG=R1OE|ڴӰICd0wqεQ &%)d' [GNjԲ^b5as|4`"Q%NPC!]qixEqD-rNl̝1tD2v DG2&74M(3WLSfٓesTSe{rۃ\VV@GGs2PJ13X Tpٕtac˰!"G4AO 1|$|>.qLӢ"g{OFm TΜJn-sIRGk*g"Qq-dLg"]ϑ`?u-P*PaChTEsJ㕗Vݣ7=I盛r5OﵤrUVs}~?,>uQ]}]"nqk ƄRݝjMp~gg<P~i qm}<;V ڕ!nB,v]6]`8tͯx˧͂W]WЮ]jUϵ4V8F51A$Ji=sWʷߞ;~ h`.9/(Og&5Z)jUm㒈*ʹo5A[msnWfCeHkP[]=V1쿬N(2> WŶ?삪 KiXՄ-RN*8w&: #VX,БtSM;Eb޹E"\Gly"ST|k",S^7\ˮC.1l{1 m! 0p?&#;UZok8 &BGF8͈؁#3gq&nnh۪dfm>VKi)y+bmI&SVJHNMFWsp|4ǁ&enPû@H'u^{}U#kg H'H:;w葌r3@g.V{\\'#鴓-sr*hZ& qܿE "m $ya78I舴##sgш::23xwNB鴼ӵ! nզ0\]{^t#;%ʶ!*޴G96R咋fZC7qU/Zݦ,iNQC7hlS 9;_HF64INl6a٤۷rO6Z~fִ8)1`Vs|4G! Y behf3E4scG4b!MĎ /z$vZx k@I/ĐjvǿPMӚiBWZQʶ\ \jZbc bfưo8d#/&sSM_҆":ZfL5_լ|?klZkIYVQgcp-b$PaWQcJsh>DаˡF4"rL /x$|'mY89uFtH$'eB#Qj ~.d|>-.6#@Б3X,SdY6ط@?삘(P kJt&`+;"| 21xDc2&z E#H2:jjhV@`E^jw]21zsscǽɈ(Iф%+Jʬ^f۞[P:LTlÓYKo ͖pS'ب Hc&GOBQ;eioY{I6dT>1ʋ+Y)5"QvIlVT?uZɛJsPw|4GRP. m-5r|(ذG4>"de!$ ujѤmjFwE3)Zg|i{ZEܟ;Vqv(@rHjFqP{BAE4j9^~{Jtc*Ad۰!BH4j`QD /"N06(%ˉ%ڵ#bu[q2"v-JAqM23\$c92@?g9 {!EkQ BPDm.uX H7>2xnNL#0Y4O)hK?5F(IEQi: jUA,¦"پQes+T/)}*\Pi(d`Q$K qIj $Y P,yI*&n&Gz {9啲|~hE38_[v')Xd㣙b Pc,iA$LPHXGPZ7F-HQG' #(J#HQc RԓGDU1;rASQgKJu2JA"AI%t}j}}%, mJ(Neuk[̈́Tc7(doqϮˇ/,>/xj^l^as2\{,9Yz )TDhIwoB68kl([d;H1z G{# hv3P$sIႥsMNa8aͣ @6ϙY"R&̥F{+lbvwq|..q>$sJ&rCK uatnD&`GӦ>Ս,p2bh_ZSdrv I-.9!{_<^XL(( 5/.xz<>~}n?<黹wwVsoF-5V {pñ⇇_m5LPn #l=ٗ7g:v1Iʤy.:C;]p;xァU`Y_0zxs nTpaDEPt V,G 5bhI'zɤ>N\3wpk |{p)΀q5FDG28 tTZf׺5~AI\Q..o;*2^O;&r-Sg;EOw]t;>^}Xc8 s3AU'wb77ϋ$Jho#N~rvޜ(I܎J65#xHSĶ P RNIjvv}%@?XӰ p&)wQ}e4' hv3,;p~y1Fvz41 2`AԨ2B$";7ྰe mr;6Σp?IƎ ϕeqX:Χގh$2!n+Y6 Z8>[]zeLhb}j@ֶQG{鶳wW'h;;O`2+$ ~ bi0Q  +O_셨Kc9O,Qt0J)#E⼹|Ni(`P>,5Ϧ< JE ϦYO'AQ_ 70J QUń5A"7+Xu5]#ϋ-LG D`È9;,\:os(m"o5<6 68\Y'pcɬ& Sx]L^Mx &0If 09mӌ}\qV; [+xs S`qC36r9̧V5Ư}}V efM0yw . &X]0-^CN$U[`ZmgIRy lfzz WbY"`,z(;2#^QQb3j+ZL|KO_߅}>G,]H|KC{/_ 4Ω(rA܉Q7ꜰHFy";QǷqfITv}rsL_1)G, %&"p3Hs*:TC*Hpk un< 3(]ϹӤp .,1%:'Ie <q$-v (ө>M6WgoY!ȊH)Y,.![CT6Rgg6l "J~Fb&83:(Ut+O^MAirxMG{Pm^lʫ!H͙( {\񑼖:3)u sRq&#tkX#)E2N f]j)aC/_o.ѮO燏O׋sӘ`¦Kکj@c׹ /[Vw#ҙFkFeb Χ?xY.ܗU1+p07,.n?TGsN8-f̾{W׷O^a겲moDdbN0iG%МǨ;pÇ&M;BkʭAEaG;dڗ&F}liS P(Ҟ8[_{\jf aoʂW6qֶQL瓽b@%XG=1 iXB9a"W^(Hh6Z:yWƦ0bVGRp} eSͤUm/Đqv@I.>Iڸǐ q5[qA0] (WQ7 4~@Nij,n{R7AJKDC݄yk)'mWʐc@i(y\,mg;-3^X!V" rA#!iVܕhjV2T 8ʦ!vX9&=7%̑Z;Rb 'Zc}fW7JM*.Οnynv8<_<gj&txWJ=g}&2m f~́JM;m0#^UQJ Eq#ywhfY8u:a o$6jX訦-SGI:Q3o@{&s77jiEJnZJj,"wL8C7(cq7P'"!ɾ9t,Y"ݓ%JCFã%L]Zn! UKJ AEfm Sc)ƽ>zX.||h)L%”9`!͂@uM009قLl{(wRL쥞;P)[D$Aʶl9iS6Bdtaq&\.(QlMJ.lH+ :l6 gQESlZL)&N7Ɖt l) e"˦HLٚm/Qj[ <)vUS@:/z#O$n"9CA\RdA6; })'KXUH=7E>d 0 }$HVMMqKܥ3到#^F#{jwV!{K^` 2 {,% yVEB%oKj)EB|gF3Zy5-L % gd0d^Vyd*0l*HG^8?Z!/X WL]B.sa3'#"\n9[WbiE/H #1LEvMx51L% gGd@dBfוN3{U H$jF+d 3Dⓥֈ/a~%ˆm]Ĥ~i7Uf.NɱH0 ɺ1!fhL efx. Bj8?\!5YH WN@R+и@Br1Ή.τBZH S t))q)(0L 7tІ(SQBƉv)!lBJPItgXb,ϓӜH0;kEH$ H2/1ܼ C "tĐ35oBbvЩIrR'&mG0_Y"G0 G%^aM)>-D@X0) ;MNfiHWYAXѶM+ Wt!3DY/;1)Æ$lGZ(x(NA61Ql.f1>GL\;u0EyoQ!̘?SHMG},U#N؅!7g1A`Ę!i(Dő0<<)5a-f+$+W3j^V)jJ͎4X\mv$AEN;T{%albS*,17!o 'ۆR0ٶ9' o21y/~3&T.vR {jf`d^V$ {k["0A6; } #MMW1E!Ta#(m8Y[4M)FxTԕ`L(FJC5bȕCհ kh]=,w_Y>}ok?yI`2|¿1O!\VΆ1z7) ʹN^_ډt^֎YM+7N7%vV}L{ TJ׵(fu΢dA`43P=IC# D6tzjvs|#S8X&ҚTɧd+@BpE ԰R2IσĚ`@|Νc+o,)\/ HBH#H #!Ȅp+ )l]n9*Uvd_MRb`ˆIXJ {}LU[1.X]9.u⧆hUNqV0/Ӆ̴̀AX&D䅳H2sO+ /td!Iw& 1FGVFD,d+M&`&-+\U~)/F6_v~ c"+Yax4sAV؋/ H27-\+dTt1,BI!)UH #R&!.1)d|/Sn.1(RPC)GV8Sdcma0W؋/@$H2!)J'H &+RvoX!oKb1e H *$ I )Dp$ŕN71a3}iQm1}+N:$iԛƗC فYa$ n^Y!K9x_ A8IP0"\!)\B6ԌI,5ŦB@pzg>_R#D/@VTSL?”L% cȔpK 3}Vz[$gڄ/d aLBzCr=e,uqԪL`߫vkyOXNݘu9hfZPzoJ (g䉑d[0KI-s Q5{;SZ 7(-" w{nrV#Մ=]-1(mFF3N@̖`PD@A6; w$'&ws5w [nAnR@텺ILLZՅŵ0![H鏹8&d0MlC RH(rMJ%u!a iYvWn n†$la ۊy% NLL84΅#lxgYof̵f&abTXER [$$9Yf6smdۖT[GԄm~AF7= q"z(&@UHRdJ0m,P'H"!7I܄ޏyJf$na[cAGc4V%n8i[ZM594-6(UT1 o Jh]=,w_Y>}['Tue -%G٧k ]Y]bJwVH$htz9%_rȋ:7sktnɊιtXہVqg΅l (ʼ,{qt.Hl/P#[xiH5«H@" Ҹhr4.w4. f~U78ilat&LC?ǁ n (h<.L. & [MD_t<)]ljq"-rPKcU~8_0%8`\LP9˔^ r`\n8k-HԙOMzs)$\I|.{k''W<(JeJJU*{u..! vk(}$a $tD\Xmj0%O Y#ѳ@!Oc MLRtqqZɃj0HJK[*a0i"Zun̄TQWs0=(3fڐ{`dL9m/AL06 n438:MRV #%3) F$:dp2y?`p,28dQ(∤=R?aRq-C- uf~@Ai [ f)^a&> L`yx6h k!] fG̡‚"aWФ@X1ĭWq=.FEdIr!?]dK{\px!!&`"Om<퐙Wl2+bh% #BRd XHL`vAR?b0d UQM53-IEa(R^ԅ!ǭNئ>쏻8~ g1)։Iټ#?PJX"6ILJ֎fhVB\c El%$h]=,w_Y>}YGjk&m8]%T sypP P;Pdp+P0$qK i"?>"`m4p6u4kv;R8"P(`-8yRRIݺFZ;a'Ap]HDIA*.)\RY\4p4# RMOTojL;M6Z 4L$J(I$ZX !,bi3n 2hn84~.myN'-T8qYb]M[Z ),LO0>Jǘ>P2 =ga|S8.hNȂ.&6K 'HꆣRmN H]KyBdF&/\A2IxYA wb??A pr,.g- {f~(A64fS7ȲJi.T:J˥oHi9rLa .)NH:`j=.H*&Wltփ,84.*D֗CR'H" h" UIviu\+}@#J#,do3iu.\6y#썯a k'Yד>l ֟#%*#aiܒ"b SFDL1Ivi]3R],mD?~l[6OmVLj-)Qv^Nfw)np[FNL w%ef~/&Dog[I I(n5:B6f{->L3jR4[jw1;q)Bl8.Uq\T JYo)֞JV1φ-QIrxPd2BVTBvKmU¶JB6MmȹJJ,mYg!1aJ#\!YJQ>B2jIS/!z+ &DoSkUK~93WY~ _~}Շ7o>ۛoz˛?R>$3ur|]'g6vrDas`}q'\'ǹn G;1i>]38#Iܝs!Rr*g*Lp;`DtJ$|cLڌrP&) uT?hYM}ܳt@+RuJ^<`ەj4f/DcV9 aT줊Adv\j&ta XkVtګyӊ<V$1asH,DZ3QlSǾkk fwAn~*Byf*!̵R[ݯWt] el.،vlf"]^@N;$:գi=W³cxV 0۽qC#7;R fNi6&1oDAN!NkRFPI k'XS!b+#JhjZB}`'zf7e6hUߚPF͉d^Acr-N2-:)!n+)#NK ԚnJ l,Tƹ&k(֞PVo6{k9eU'㜼z9-+ [I7UJ h Ԛm>4g-WlY ӤLutcsRY8lfNo'demR6 z zkPFފJn&:$nmjM5a"5nBp&Mte\Fv\%gk#-XQhIJqKtlNR;-<.[KCTB*[pM^I(6vdepLHH;l"r((ӶdVJY{wa3f(u;~u: !f+f [1!tZ͇ft|*[*jBw޺KBtǸDn1mH(kgvjo+lt(('h[RBWRFv p[BV@Kߦl'oYte~wk:AN9am%3@c@n-~V$ KR"kBodP5+`wΰZ{վ{E?} ׇ^}xo~|󻿽kՇ>F9^0m ħh*[V etgJqhC?L+ /|× fk'-IXhDCbђfɤO4Eo7zV*>yPwV$7wgf}}K7|yWdi</g,Tَé3>HoնGqƄ D^[ ɵS*=/?/~yuQWt*4PE[+$ew[@ߎ@O.š. w/#>!!h+wD=\I+zs`鐆'^kmސ8Pfj/\xK#YM+(Je苟5X|Ԟxʹ`hl~v?u^ )5fvhR+oFy͞'8Q/՟t9_h~kv#D{QhS)WޚfQZ¯Bұ[*p~ ¯A?ØNَ٬J2Q]Xc’I;m*mL!~#DN|~Lu<ˉ,x8V$*#w 6pAfJ2(m-1Z5|6FvMs\%uZIZ;uEP\+{ 7R;6Irb[e2(m-M1\E`M^OCUׄyQ'9tYTAAO cFsI%lUG =esZ:#kRQJɮAWO ԚPd2rO6yOy^hm)D!TӧBpVjx%mDmjBB6+p[NC qkV09:)d-YU#*0Drg) \IU7US !Ԛn\*©XX.-(PYevX[l1rLx]!;NZJʾBTW@Nl/)Du0S|dB-kel ecllt ̝!@HPzwuZ*7U.]2 ~%c*}EM^OܦѰUW7 LǯW18ʥ41 Kcxkf2n}}?Q.AY\\QIpB*\\@oB)+$}F%F;W3!+$twA5d|h8/*ESN$MY { )[ca..P&.kFJk>~c\&d%y=΅sA1zʒBoJM^PCnYRTWJ:"j;JY=4{ '8mK 7*!ع낞~㼓\!(pg) \I7tK Ԛn>4W`2eՔՔKDz0ӟr$kO*vdg+rbeJJmV>'mڗi[I7UH Ԛm>4 oL\IuQ)U6nAmF)vBӍc/g[5wA)nm^wSBwJ]RxmV &P-kVJyx?3?i#>J}[MୀPmjB7IVf*ʙxBEylc"֔vhl.DpYR̬uҵ/BotB5 |hV@7[Tn3b#^`.[{JY;4{$rolRIJȾ[BW@Ll/(p'CJIY;Gʡ)z DqCtBEךTJF=JH*wldNR{; kb4ح~ݪz$oԄmjB6vߨbL,L[ym^7{V6L-б-a[I7E ԚxeDe^YgNyƮ)n"jH)g~vqȆo\cr|1yG%۔ⶢXMȭM) &t d"@m2LA֝0uiKJr~EضLکwmقE6 BvqT}gܪ%oԄmjByNr}勒uL].N8+ m%fUFNBwqĕԑ}C\U!+&qSkW)9ĹʻpPWXbt판nNDnmV!$twƚ*}}[QCO|w|DE1橒f7jcSIQ遞J䣴" B ]PACʀq8G)飊5sluWiM5ʂ%ٲlp-uӼ3\DEQ]xPkFtdP|Kʾ񭦏B W@L(6f{A!;9yVRC8:O Bi|}V(6hB0i& j<|`F5F;1zmr\u;'|¸pdW/!~+"+$n'VA7^w/TN42"7A.۹dRL.YRk3IguDg3>ؐ}K#kPY(WRUMr5bbB5 t2U*+}\rRVzg3Y?34{(EmxnĸUv=ԟx%DndmjRBvBn+~aUԴ5} CjiIΚ̽p=YQ;nS uJBUDd߬V!N+T-YPANmnp}8XQgjǰeDj)d\;h)VKLF5NI[DdV\`{P'ɠN %JԔ}[5PmjjB 7@NW9dS&5XGaŰJʵ&d ZQK.Nm*Lw /4- \IM7UQ h Ԛ`n:c`Ttܛ5]X^,u UʥKl m.w°.]t<nw6p؅63NIpZS#%kxcUE6u dgReOd:paC4ulSR(VRN cr;V9!+$tZn$|ǚqu8$sI%]TYIIPҭnKϖ7ɟ+"T_1eII[!5wڭ[BV@C(VPG(6MT6۱@,ׅ_-'cn¶ZO[֚c1Fy^\r"75)u+'J [Ԛn:c W̶Ԫtfh yDSDA1KqIt5'܇iF& ȉY~KK = HנŕNVM  aԚńJ'7Uұ*Svl k}.WE7WGFM=YW"%Dn M}j$m4& Nm\W691_FuG)%Rk-,(Yf+iDkZqIR^v:Ʊ\>uBkh+ʯM^Bq^3uy{.\}߻QuWZ=kY`OV^keZʮR}Zyg`zP^MƭGV洴$ձd|! zMhr=ckQ7,dQNkYUZIE7UM ٦l$oɸ6A`\ .<;mmԥn^i|8ԒGiSIni/HnJ;#DiRjSkBTk`Q-31)byRR*u"`kI#`JͬHymÛ}77__M,R>7> ؘҚ oHnM \QюHUDVW^Aq;FAa賏딃y}Gkx.ͣz,O \,fwY"B6#`šV9,vß>~闧HJOuNM;SʨղBɴƾwQ%w V1!|+ $oSk·)I U>|Jzt8Ź#vkN"U]cnZ&Mra9qlFtd8'oTmjJBv24r~}BI\r 1(SR9+!|ۨ@A·k0O6El+&#coLg5kmxDnҒ,ۇijG VX;3x-ێeⱲ'lkWTJ ʾm5<¶"B6f{!\|2n2^RkV?Lx[#کFM"Ԅ؊#kpmj*B6NWW׆aUףsT[{ &b[f#TGMb’.:IҬT]5 A|hV'd KLQ,s")*v6l)Aܶ`V"YF-ܞ)$lRXJʾBW@Gl%Dq󡹞LqT$%KmR@ZZaNB%kVq9Fsfıԙ۶Щgש]R9GiF6Y|M^B̎`V3Q>C %l\MDz*x45ڹz HC̊eK׾L< ;C Q qY(N c.H:·f.rӫSk +FT2BV:WtG9 5RkKgY%ni{Y 65*!8+):ZԚhm:4nivO7:MFi`eZmI%m l$6&7mYbHR}\!Dm%cV#!x+&oSkWUJ M"7ȡK!rdLbRU۽ f)ў"x+fuw+Q?}7ⶩ5 q|hV=EL!nm@co,~VX /߫ >'kPUJ*ʾB(W@Kl'rPv =֘ =t*(Y:V=sBcqvT9)!&CGuQT5yq~PdIwd%?`M^KCɺֻWXY.,*eR5eJ! x؟ A H+)4S B+ "DhSk"Ь@h2DJv2HAV{fvfgl>!=]I%TIǮ5"k%d߰V!X+ "kSkЬk2Ap-K>:׶靱{5~fıă(pplS D+ hSk~Tc8&+f$|=lJRٝ{4klӄ^IZAVR9Gb5 CU>8{QSmF&(B6fK7l"''btp;PdJBVRE o|BJB6f{5!tNFVAʧhK2(pDcAk:mrl ldKƟ#}zM0Y L+)ƴY !>Z:}e>3>Ɲ)l>>IF֜@VDžwhB܇iFKY !@;N<J nU= Ԛ%d0͈H=.[ݣe>-1}msLX%rgKlt|e>:lS3!p+ #nSkeվ]jݫ,c/>Û}7-xI__M##QNL[od2Ni+0WïO${rouzn?k<16mc;":+Mkf]ϕDN'\O(N{CI|7\CirjR, n6 ̯3:B\Q,x㣝F\> Dx@jygox2QelU=I5vX=Tpt )^26y薽ztDVVU ?>m: Ku6kǚv-KیvU Q6ԖcM9mq][Y[:QZ= J1|'Z?9FqjiVեdRuҚ%ԪzP"\7B c[>Lx[(駋 븐}-j+6U#l[eR?667mCBV@?(VPC"VifWھbZ}r(˓F:Ύ(HZsad*mv.e 7\nJeid(XF[:MBJ&y/zN-Yr*B΂r E;.4_q+7 W3Ke) ŨםZN`K閬@#AAotgуp8`'a:o5'mRCxI7tH UN^P}=[< I[sC]~ Q5iOb5ӪSr36(r"AN:|.qn5nMJ [I7UqH 1Ԛ필m>43dSNI/($"AwK{ BGB)Sl}:gŠ$BBg´P:)!d+)#F[!bZMGƽWblPZpF!]/lzI֖D*ⳤ^";Ehta1~Qǖ&m}mPⶩ5+ q|hVڭ6M:ODrNܖf$ mYkoU;(^XPt!`~}\%m%udV#!h+"mSkWЬm;nUڄ" 2i!HSR9pE֞DN;h0yl}\&m%S[wM^Dwm8A1S܉:JKv I5[ij$69._J6MǴ46Tƙxda pvV[2#٤ƕ]c"5 ܔ"@r@Upce_hs/M5KlҚ8.qBWT@'q0njjBwqz 2Ɖԋ2ɨv"+[f#Taą0:U!+(Ƹj a\%!ZƝ`'s+^dn_aL:]" Ȥ[f#d#6q¸jBwqƕT}c\50M^M'*'*c\2ɃeXDžMNƵ'bla7bQcS',pg) !\I5k_JWM= Ԛ텄zSMn2 +3(/t515$Rg8kN'Cb$ߜ,/qg A\IM-UvQ H ԚPn2W@9UN?R@M#z 3T.ZMurr}\*p%eߥ"JB7f{5Rd\te'2iR'QBI:[K mӞ[U!p;NNJJɾv"5|2@l2 q g-9*OtDIۂ5dTgf uBVRQo¸JB7f{5!; o6:_d>*2F לFvyj`ao}\''o%d8$mmj*B&p^suy-ƭH(:;Ns@&Vʨ)ݶdVڇ44k];3ʍ\: fBVRSvp=b B6f{D|2n2:-XM.'rkM5ۂ5[cfV^T>SⵒJo^+5|2^lU6*x>>lt4\1ۆY=&Y_EX>SⶒjonPB5+ |2n2əD| 9Ejg|vjg55WNM>oH+"5thbg2L%]ؕ)\̈́8m}v=pb-i}\'*Dm%eV;!+ $pSkbd\de'-ZSp!n[fY0(cn3%X:!!V+)"f^Y >Z ]Te>)ޙt4jK:q%[{*)kg0]ib쵭B55硳dlz}][1sfr['xkM']K#xZN܈7#/7~"k ʄ^f@I%|6uFҌBV@Jަl/'oy>-3{fftt醟lO%iS%ok3 ̹g㛩*)ogi [I1\UτM^Qnr>W'a_n).c JdǤCNFԌmɚ$vx)I".H0LlmK׾LCJǾ'BV@E֦l$kpհmF05弋ZF!2lTo~eךd}^$wzt,d$x-c AY U5by+Y/QC! k*^¼eۨPOe9?QI%3&ĖG큞HȞ{@JV ۽pPOcYte"ɓÚEU4U\:`64+n^݀VFlAn^Rvgl\s5қK|H}\)Dp%dukB W@Fai*Vl5RAfu'2uYR.#rk)R{滣\x6'=TAT]u;õ B[pЮ*Bٶ\[PrG<CUuEqnH:j_}bZ~ô5- nYnSܖ}Pj'pĄRnSkd rfs'&B@-@nɚB^@. rϝ}\',s%Ee4+\(}vq$GUƵCcq4q}\(p%dWE= Ԛ텄m zp[ָ9l9 8*c2|2Mu!+,{=5tS  ԚbB 0'VN';u6g< kLYI9%}sp-܇iT#okgA/:;oʢmkSLB:[n:AMl[-c^G‚ݴ4mQrF‚x농+cqmJ ![!5wd%P|hV6SRoԋBA3ZIEM)@uYk(H0T7̼Xg\BEe \%ɩ5ԄpljW(y딺X ]t_y'(טBƈW2wqQnIftT8٨P; W)!l+!+#R[lf@NpoN?똵%l'v? aT.ٌPց{E%M 5:߻QU[IEmB W@J(6f{9* W:wT`Y~S]WnUd%kToksT(68dYaW=WuzBɷBR[%PPm:4j%枪mq4TGv~Q`l7lOdV!!\#\ "kӡkfX nɳ2X ˹DjzH:FX7JR5Y> u~'b⣘?DX8;e)pL i|ԐGiSAni/Gn*"jt!l%lY*DpۡKw܊l ^٩:8uMB6i:{ɚd^lF6,伓KĦ:ťğT*kp|BJB6f{5!t+FF tRNNNB -wWt&zH)vnk{6(́UNvHk_&$o%EdV+!~+ &oSkЬo2R m zJ6sAcoG~SRJeGI)!+)#&~ \1!Z͇f|>w:vi\$[B'.nPŸ{sERV# =SQ tMŕ}\%p%udW1!+ &pSkBЬpv* 5wE]8NRvFhlhfMTbTحҌ|öQ[!jZnG`[%&Xe`ә.  z2T!jH(/6{Ԗ>(ez}ӸE}QB+z"g׉ ]RPz"5 d@rMELX.X]BfyFN=SY:딅:I!z+)'>ML Ԛ '@ogiXJQ.;(e<5.k6J)Xg 瞥/^&pm* !\I57tO Ԛ@n>4+\&&gp4%GˤڎRکwrw%ٱi )O B,WRPv[LY9!+#qSkhK\I['WI:[.HJ((%kL$'[faZQ:ǟ//Dqg Q\IQwFB(W@Ll/(:w?}<|o߽ya&\o?xӷc? |?~Qϟ>eO>7pozKQ̾ďe OQaTT.ǀw.NfX\TTtIL~p):gec[$x\8"0NWm*Z{̫>(SpOeRR;k/zAEv^ɾ3x, qV(VtVTUtleb m- !s{c:DOo?ˇW?%7w.SH/~viSX͔sɟ}Ƿ_WP.Bib~7ß/_@>O?_~_/w?=|ÿ?|/oLJ??o7o|~>~^6\m0ѷłK×~3}ӫ0G~_7/?=pwO_/?姇{h}~x8&o?L>/lfLNZōS__/Suv~KscKI7x`N?H׿q ]Ͽ~-}'pzoj7?7?z?~OUa?d隟Òykzax|ן޼+Rv <҇_똑ƾws?Sʇ><(dp<{݊ :d<Ŏx! ϴp O%3%iXڽfNb!Eқ@,aM 5ϥo&OT`y|/2<RKk5 soku;k/^ 2a ^Z<FUT}"ec();9l!o`EE_(cG?0ހs"%J+WU[ 2=x?G `Tzţp:|'Àz̨=3LOi\| aGL aT&}߇߆ KU9*t|;FS+/G.xaRT09u8j}&>VL\O<' ֵoW&%Ē0&?CҐѐ{ѿ<:i">|ɛ]=DiysB k>υ1O߆a\QFm%aUJ <0I?`rPs Ӡ-k~ *YFz@P`sƀiT5(Q&y Rի=ނ%_kQڤ`28^YGvq%Se.}08mAtpmx*QƋo vŏRs-~b[; i h F ?|a 8s> J˜aE8'LqZ4{(X ,G؍&0?Nx O9Na}UkWopK+EVm]{m$"v%߇s^p4+~z}%G9hg,:^ŕ}J ?Ii?No/ _VN;WN rq.z!ڎ$ / X j~$_%'j`C5E-̏mZp؃ Pp'=c=61pa4)£-ܤMzGv"~LV_GfI"1AAHF!oQInHO.7ax7 ̦An&S,a͍];g,v>k1v'^t&\|-u[\$,W-La [08\?K"1"+)Ɓ%8'tV?Ш 48>XAd|=.M`7 v0hȣG*nV`GN7V`n&s+У[ ^l^ \\ "tENMNX~N{/ƷCtD ]h7r\tؘඁvH 2P8a ' 'LaaK ~G;>&px{u[#UW0?0{G;@5G ?N"Ⴆ H[If,vpY`sUx;5ڽKC"^e`i7'Icv,8s 3p%t$:@+<~= V4aL/ڄt1tM*.N@ f݌xE0gSg#m8a|U#qGl378g@,B06$N$Ց(I«WUߩJ|;&D }OA+8}p+?-dDo5.@ )8oq!,_pU T&+-I7av L0 ,d C12T4o9S,* N2*?xc3hCDoR0`4 _kw,8CW4y۟߆IȢkktt >F*@z>p 1wHs{^ %44ô><*8 >aMt@83|OxIJHXXBZު7N!N=Xzhwdmpg& n qYOʤokbMJc? cq" \#np4> 0m4kׂo?76-l IP|.3MrX$IE*eXWZ @oD xąYi5FWSh1}A GuXa!7@ _0A`9lA!gwvbǡhxڪ>uVmU(}?/b :<0=yGx†i l{Z E pH0y1D w,#P/./<ƮAX=jP69#'tF _§1'=:5nK $CxHIg@8p1>+-+}bȯrDX<>˜¼QȦpA_;l ]ES(b׀&ě|t ݀Sz~\$KJM r R8}/d"|"Fd-a*CEbinSw'A&)UP@K::kۤ&-Ʀ``t:5y_[L0{(OţƆp0Aѵ [>iG<#cӄ z`ç z_6Q t&Hإ$8Kr"a!0 }$lb7zEO`x . >G ;\@jXq0V)'2&0'~b L;/5K@q(1lGmN~v!pӴTÁ@'AKr0D9W@U!0{>3NۣS$~oÄ8t11]Jy ^g ݴɁeBW|ȊUmJV@``c)eP ? "ɝA~K? 88:Ŀ4ѯya ! :1a0 T\N}GeIp~LX9{4"9^[" E2%0.wnP( h\ &A* h!|&bAc|X,@#XoC\J;a PaU0DHf;F&y/:$/@Q3$:V^ ֻ h5N+L? c|&4,q1qt}>*܆gׇRRR0 Tk%."HEbic†%)C(xvË$e `!J`:`:VIگ) o7mx#~1(^0opM2204cp  )`MX|X}ۄY)![dc\iR`NopÀ]ZI]H,twM*_̍@c/}xš xwC 2xOʍB|yט>Ojg3냈xswB= Eua1? /uHQKI_U*Cq 4{.G_ISb"DS"0  "xX-|? pco?M |<ºaaEy4p!QؓSn0VVxK404OM9]"S 04's{>&s]+ı0!,"?H>:oۇLciyxTƢ6UOXQ$9**pG pCFQ6&g`c|MTq04U(Z #w= CP=Cs0 uEeNh` {X'0ph@È(Ha OP]9=MuVLX$[ta88. P!`'ήC_]%|x&M~>El>f:xꏤ}L 3,t;nc%ǻV8pC.D;<ߺ U!yLaa1cҝpq|~Jcǻ4ޭҗձg|8S nIHL!qx/K#ٌ"J#y9RXїZh" (c.x!LMwP~ RK2( lA18w/ >@݄q+CFeQ&2_#Lt '4(Dhĉ%yuO8[":ztoρaԱDۏHӇы G@un,RjؙGW[k*"91+W%wV]I7p{J w;Wϻ6v@66a4)1{Cv}Uzb){)-:~0߫;quG gWr\yrbG5b':1>1cbڙrFfjG&_scrd))b ׽fd(B-# VCtP qTG_63r4rTgq#:1q̤ʌn2L(<:> e?X71-!F屾S1zŒ',ID?"y$3 yFIJ=QG@$(;99 jH5JQw1q,0+ΓnˡjRǬ5EHs ^Ȏp\D72Lb?z5V򯱉,&n Y!Y~`G5?P7X);yis,-a)lw=L>z{+[5a8r/4GriƂ5ii/ +Q1 O ^hV"J,| ݬS_C&k'vJ.orb18k0~H\&, 1dke|[J;nNj y@A,?ۋi,ٔsF=R&'GGvOϡl_;&b W"08 œ7ۦXx'wsBt1^L`(Ԑ87>!ͨCɒ:IKRg1Rg \ .&Mmˎ淘K[I$, 1)iܧ(A )\RoXi$֧X#FNô7B@ðT>N#X:xσ}LrǙ/ib;FeCT+TZY%>GBΰ>Ib ni|`kЧôvpO=|_#I" $ޅ\bxI:^fOɔ_~oDc8}m"2`$껱^= l/p3>pW}:moo&?/߾y>ڎcϯۏ=<]PpE;?~z㻟^_d8 1?`0mIZ$_$ЍjmXɰv,T'e:2X'eNϝZxnyil#GGđ~۝䄷Xw_ 6;驋H[ۂ j#}c0k,|(1s0:BbJ69)YHzdYJ,:cYy؋9Vj|=9r3߰Rf **2ז Ņ4k3n:?a%4ɭ^ȭLj^\*VofK6<:3[ Y7IҝhZOEc|!uZh +nz>$UµĿ̧vlĴ?|h F~珿|zsk;1ƋH f?%*0fb{q_Dxy.&220(-u/^}~"n߄c?)~!ǟ_~WU-{'Rf"E#olm@fDSG!᲎xH G!xm.$Oh1Od76'>J3|@YZة:2yNGDeNZsx^i{Fs>mL!iI?#^"'xͭk29TI{t =yDx'd`ljs[(ܑjnD51!l^J ;C *r_#c/d$6wAFLJ"8Hm;j'jV@7_< )ng&i X-]ݺ^msZI7:lȭ|wz;KTVʬM^MzFS.W0>ΈTE~=ϪW6gԃls 6+f3sf,Of8hljA46 4fLcɡ2MJDND֚2XfFDfɆ`{#2_PA6ڱk*b*Y]Ȭa 2ZM'c \OfVU&3G+jxDNҦ%Gm^só "n\q!J\EJ*Ⱦ) YMxjMKԚe@m>4+ j2c b%wzob 5b!hI#ЉѢؒBx}YOgRcm1ƒ!Q*m!BZ'3 MF$|N>Q?k6{jmA[fǜOnm.)oE?,)nJTSxPB B6P+D\*ucXg}풠3j1Rik6*ıg AAuv?g]X}坱2kl.5$Z [IM6MG; ? tAv׫ju*ZW]n T.ԚBd\ +Əǡ>♶s8wS6n<=8:G;gF4!ף&Dk ]HFk ؼ *"QGX^Gou$Z%!~+ %tvA9!v`-g7Qݰgw}lCPQ]st 6.U$c7miNW%{E0-oaۣd{rr`_{۹k_!xZS@GhV0'k1q Q!Pp.DYEe:4}у>߾NXлsQk6Wʒ5[$%&k Uaԑ}c}k ֶZ͇fb-X)% _\|<Յ6͇!\}wv)O*BжUHיּԩ[A@>j"!1lyBvڗIqԚ2B;熉(֩T-5-H886TGaTqcNfNlm.'kEdN|85)k ׾L?֦#U`MW(9gl_7.!x/P{f*GўMG HnDU=!j\Mh\!!uU9Ѿ3 :bF:edmo}ЎjBYle|s)9_;Z]uj&VaM,[֚Q9 BPbzӊjQAY5  r|ϋN/n;kM]ʭ-ZhiF%KAZe1!jM͙f$es951ɬ!Rv!|;w-%l9hI=h[߈|[f{{Nh Wb  hZ:k1KXŗJSn.#71$dX8"S% 0e[p{pL LlXMڦl(Dm󡹞DmjK~\-P?xZz^9i^8{ wv EhbT`꽚H ;bJѾƶesjRU&LP!7K\RՅc ܈N1Dh3eu^06SHW(7Cn.%:C:qADQEX^E3B9vTڸ}]$ċK ,('DnYLerC-ذ)+;7SMi՚-\f#}amm"7, NI1/) ""DěΏJJ^Pzm5Ԛm24ƪUrIi:1Ft e봔Ƥns^L[eMK֬044>iv{4. LEv WE$k_(DrEdgN&p1ԚZBGOܯn-y<O*\PAk2&py iYa}kmuPͥFhlu +O=@Τtd|I;u܏2r{\qU]In-.h Ԛ`.S]sҙBSJyS̜Kq=lǔQLJ.sḍ6ٸ ^vǬ5kf#.ϵiFk#urs1{@>.HjI)NXOixN{e:i\f;R"s׾LoTr"[Sk.B>D h,<*"X+):NP_y',7&q^#1;>0!*8+Ħ bQE)-2\Hnxqm|RĈۋ!ԚBv VUMgJ4a:5HУ?#S3譩2DoϾ9둃2rk \I}uǂ. 2p55 vۋ ԚzLrҬ;F:UyRΫfKxkg :J~^P#NO_xIIŕ{[ql߳Yڦ%bExfݽO^L~ ՕӜml+SI杵B\llr-~4E p"tė)%mdq:|j pR#UiP~4&aYz1Brs~!˭取KlH.fvvwtnM}PJsz{ơpG3GNc_(&nxU+u\Sq7JMݧY2`!k [)(_G)fvz 1ie$\8![GS)$sDqӸ ߸nH\3ȬcZ=׭gO^c<8eI`Z*~)Y@-4'}qs<3~苼>Z$>W"Q^G3jGm Tm5tk]CtCIMhEJUg 6ʽWڢrһb.˴3b."$Tِ&[_L(Ǚc6&S'.j=)ۓ0iTSN^js77@e %᪓ v X2B DEԙwB3M&g+}w!gkʽ-f@Jw\ ]Ta.9-1L"KYJ㾁iLRJ{U F'zx[[΍n\}VQ,[B_(su@k CVrM}Pm{3l)Nj}FS'0'U뮊\o|%qNsoxnWau"l[x*}t#"󬏬F~:"]݌ ޤUWĭBVI˓!@Yx&X5PR4uauďs'$i/JWZo&|Vuk)MdI-a\>7C{fam@-*bm DriNh< sx˫{+vZ>3U &vHZrX#-i⢉ %IB"6]"&}*2{O]G$ i[Cmm]xղqU<7)<ղ.ёar'\ ѵ%{8QEw#[9/2Q&am,Nc#.`HqIn,{8D-³O`,xLv뗰щ铊׺T!w%:H볃l Uʞ1}-^~PK8D}m Timer.inoXmOH_1ڀcb J R88^TN7ɪƶu7N(,5fgfyvfvΆ& 9o]Ƴ/pW1q8\"sW1Zt 'Wrd%71Qw;[/L>*g=#1Wn s x|vcivA65-So z̼׃>ĉ ktH3!!.<.wCw]Fb6wUy{ۼ|?pI|z\{ĖT9MkU9SrkȻHN-.do^(x&Fn'?d 6F%_M?Ap+G swZoiqX"̓ljIEhT#Yj7cl#qkcRcOk 'ʢTcKg/[ٜjBIYf%oQq!M+0(cR!uªg(g7x%耯,OW6|B/ܙ\YH!-7R2,vβiQΖ Ϟ-a I KӬHiiZSMIe<6 Z9R֔+*5X=?[VyO|֪@–F$Ưua3֎%,oZ&+rrGxS$};CP<2]$f ԽvMoT)C%dݙ2N!4Kis~qr$\<%杣ZQlݭFWDz(81{1&s.&Uwfr_o=ͽo>A΃l.6*ol.eF8Y6<7N*=:O:t8)du@WE|}=G?h9z {kUНg]zTYፈRw7uM=@:. RT*qdH`(bA#{ir c\]3-5P.RZ| ڪ8_Z*.~zd/u߿Ic.ҫΧʌJ<\uW2S꾺;t]O/: q_^uo~y?|߾&ӗW/_^*t8'w_:^ut`4俹^с?}Cլj_e"wo߿q/w54x?O7gzON?2foz렗B\*ʐYO;Θ4%V[J{G@YeǷϮn>}_'cE|UtpCtvݯW^BO\$5~伧0ˊwF/iGO.n~0y̧_:z$yg][yVujΤ65tc[8i2}̩I˜,\VHI˻FDžCuۓ+ X8Yߝcou>N1a:m g u,EF,ouv\3ncO;&i0.SiZ1am]3c= 㔈p~VfD:" )d\vtFmڴܭ wYg]Z%f8ҹBy%ER|QiS %뇱 DjyWcF]4Mا* ˅ k1zF]&Mا%7#yc.ƥg\Pϸ2؆7}^UxK?Gdg^,dO[l FM16S'3L E]!ϻFw0>qvoF'F'/ϻZw0>qP1N]3ϻjq0J>a;X;YR%ۈoY Hjz, ǮCОD@K7 gvVcб[I{kh<)}yj" xz)i.Vxg$ *NB)gmTLbb/DA7m#/%*w\h[GucT82q$?B()؁YJ,gbIü`' PUzr<"`6vh1j-+Z883s}7:+e=<̽C}qG'?,_|'z-dx)av-u=MJ}ӽd(2 ,+&~6s+1:~t'b6Tʥ608绀\~Sz,c7g=4àbV h̳W8ߢfںmvbYR}ma'3~6S6ӷ3ن T4kg+SDyL3Lb/sD!OTfF"3?7p,ӷδ0z e6^qU9TMɝ+bs)gz¹M q L{Δ3hhogu3h1OȉyQg.rʔ=T^+.yL93;- 4+eU ='{^.Y%8aĬafI3w­i$p-qV\lRl:uF)a~iֿw>$_:f, )wIoKlWh27Fi6GEʲ>:>}Vm5,z@-:e3?d]βєe?I Pq $c9%4enR8fk'e T`#iʲif$Hii&~Դsqi+M{ؤ#z>g|&2BH H<(7OpFJO:JX^,,6xzxue&םW>U\&UcY_Ed<fHf IV$p@ȉt5&yXcd6Y>B=,EXu95CNFো"Pqj[|O-zUM{;YHNɻ;::TeE*ap)P 1$!HG'27Xgi..my,Q|38 ù,J9X j.,K"BJ11Z*C<4dEf0pAKqj@@x0iCSKZf't)7yfLCSA=:?5$„cj:{06iw#fA]ٛ=fg<  ۏ /- [:SMef hI%M AL|@,%bPlJdi+3|.ȨSd7P$0);ЅĿ!'ifek*܃K=-3D*T4twuoIuK0DNB~WVz۲6DFqخ_QkҰJbIEvF P0G*wT1׆r[l "HZ* ΰO8ˈi)mMk\Yz '/qA$ 86EL !$֚-hX/`d-K<3Q}=p4-P䴘Ijo%V42M#,S3B ZI1C`yi`dt6jzslzFlp$‘ˮ{Q|O˜j]blG*5!V`l푐!Ē&l/J{Z1]Rʗ0<و"Q(,݊OgGjG{T_#U(It@ZCrE6eF@9g<$ bDעDT[UPClh]=MͧJh:)"k,q4qnd>$kp^Ibs4&ijEZ^3 V};*>H ֥xT*i͑jnTl;<:|5P,W"Me2PL-ꘔ*O%j5R,VR%sY翊֡qaJSreo5äN`b;DT5$G/lC.F)v$d13M|"($jo&Fh d@I)ƃQ]x2:v6CgG꼑~| ΋v$-cztI˘6 ;:ZM$fgb^T/ULgL}ƿ?www&:-Қ< U*-M sx!i&ky,LgMu#)jti{ rϟd4[}Nu2xvj)\.NR2-$UOLL4bjfتi{rϟfd9ZM[:Đb] c2/z4QL4\g@z;;,^ JW._O.vމ" aIAJm%xrϞEvVQ6?m.Ɲ+=,PVm\G7Jlձh`*"oNRI`6#[3O}aJ2-0os1"!Ҿzs|$~0L7oG{ o[J-XHV O&/D,Ӛk9F̀w(}Ӊ/qan2}|>?~vn vt r)\̉ɶb7کMo)\~BN.}pi:&;Zi!`8 ߍ<4G܇ '2-]3gn6(8=|y*=:w/_:v8{t/_ݿىc@㑂=":TR\M6?<Lcgv%_{7ڋz(ь6m@Vכ#IYA'iنIZ! 9X̴JD@X|u?U^U!uCH3`+iRIoY4- 計]scg&J7F"ʟ=mD;K<-lH#<:J'*Jj5Oef]4e)׆"h"lGTЫh zlB1S2a.=~3)DَҲm+h[VGXڿ`%ܚ$[7GTrx\KCY)~OJ\+J`OhJ .ˎ$wltRmѶ%JoMeڊN}kH}`jqxjv %8i2@oBȶ}gmVVh&5c>mnkÓDݚĒ˦nm%5"U{s| ImYmK5Jo+ J4Dj{sm;nܶ.UkQ.$$W$'1!qeGL^o uR-6;M[͑P&VG$Kd%%I؞ON-{=yIj2y5Em׆ &׶dr/. $ I,.JDI,I4lbth\Xh\7ǓDEsb\쫲(es[i<@zyqmGJN.Ye\rT%Q$Qjo'-f*^D-uL`ɬ#~Y|okLrer/ʵ-H ^8QPkL.ŵ$$W$eŵIMD&% "B=vkJ,H@zygqq@#r5zJ2{[$F$4h BG*=:5S-S|m;L)%e*Q}"%kUpIm~kM"VZ OkHR}ڛIUH\O;VF͌X 0YA"K 7\&ղ0@Һ 7ɌOg(.NQFHƉ+5)]{k1DI,(I,ڛI=I)f2 ;q?z,(`~=)8r5(aŹD"D&r-(5%U{s|$D!x -6l Ted,&3\71,z%K9.a΁ѵ1o?Ͷgĸ0l9Rg7*z^xBE+%R8mAW(Fc̬ٸ#q#-P z$:D4 t܄X>'G,D&*DK\N>;,3]dWr&d<2kf/эh>P#mrόm9q<,p$qp$Ѫ9>H*zxZl!Z Xei)*y&8$Q,˻Xɭ P6EĎBO*އ۪s"5 ][k1 I,IڛI=A-︝o]C|k%ǰՎ~/"Ӓv-,͌cin~mn/m28# }l7.5u$Bp Gbˢ9-s1 3zp,b_4Y\ Vۛ#!^0 eSl'@ >n_MHR)IlfT[`jiP[l2z)\P\0r ͸$1$1jo(- N„b[Srb[p^odur/Iozyxy5~HmH*!e$h )|ѰcF5i5q#Ѱ ca-o&a,n^*e5 9k2k6)cZKMь0v-!Ah icDbCTqp3uьR ,Y\e06ɃHZ$NH\7=$P$$M![XZ;IHw+qZǥЩ# 1ϼ~MDӢ*mc!M&ͱ&T(iq$M,kC.$yfOy[[{IE~KYV \_t؜fD=㉻ '.}܍-r܍'በ!"E!5 GmkJmph۲h@(-lLkIF'xVbmO%L])X1ODn7ig䍖QEl* XI.J8IQ(%[ JwkEw$m6imDZ~ o+H|y8?o~?~?o^Udok8~>|q}ӧ&?twz ׳tx3nx?oٟ? cθ0xWoh׽`<u~le4̿'~ _B^'ӇwOEXm?}?sk|5+_LY޻)}Uѝ;ã}gi8w;w_:fӤqk<μmex9r?}tSwѠ _Qga:LYn'ƣIߝLs7<=<~ o1*n;SgO_a,?9' Uou\},^Rh 5P}8z,/"*Jya$rLL ܡ02փ({;?: s?wQipTdzM%8E^xyB Yeɘ|H⍊>.=GpC+ GC~ Y@@aAT FXkp? Ag35+uwK[4Vm~$g?MF>CmflbPípp}BCK0 J c}{'޸)FD{@Y, 01 o*V*8P?@4Bw*>-hy(,:D ;5#z.10a8=,%**G{GP6;_K݈07(o6 Jݒu/-`׉7SfrD"w[֠ߚ4z-ΕuP!YT8wh@h/)!ވݱ:,S) ZyA{7 x@].-= B2cc~_j]QvH>'ъЌMֽEeDfAyIMIB OUX-TU<{z۷:h8.i+Xmb$1@ݱw# + u[t?=s HX"YTW+7. q8A݊~{6t5re/ЋϟeQ%K,r폍RULH\nYAcJhF{(-ma]^oz0b @N@C#x,x\4Qpb#cV8iIW"xdc Xm]bĜ BhCx ,"Q$V"=w7" /p#^Q@b7MTT/5B+_g lMhGK];^G1v@χvoK^kjSv!| 84^x€a1[ pq^\ O¼?)B \iT7`m .xӠ?c-;eb=ʊcM>q?ūw";(G4EDm tk\.]Z T+%WJ| 8abatbPLjP>h`݋1. hBG-m\f5 p Oǃ( HS0rn;1_ xLqCܱw*!햬l +.uۑjt}Vzo0ԯ1-@}Bb‚&*c7 @J,߬ohI Ai4cjl+"0 [9 D*/d`рGCP؄.a÷׸@qY* 9f4P"=8K[l2:;a3U3465 q]ecu84ֹ;u9 |eX䍴)"/z:嗐_`b)~dO[Щ.U针xYDZh!!8"z]ʇQh `V F2`$ A"A Aό*"8v|v qbsx|߃a&` va%.+l)+JoU{i.0؃p&v(͑eb '@QbA$367J@_r4Hc\z1 C~0r +j LB&MшYi?wAB Cf`-t>ܛ;IqY" D"S b AƂA(l$?f67 -áaXhV* 0G@19q'D&BA@'$혙9\!oČ@Z# n?4e9 wA15A+cKk49Ǥ7а&<*^/$ "/Mq#? #p«F"A`C Cfq4M% !rd:^a hH(I1$/$:m]?L(/P. W: јs@|oeeYMF2B> < : wY:1DP K ` 5(~6㋬_x}/z s* {0=65b<"7"vcYX>@4g8kF$":7lX/- dQHb FtEZ P A.euwT<âLBXD%AWZN0 ȃAN@?Q.=JxI1gJ~я^ɏa~ G(4,DcC[^ G1C+]R]׻.SEqM!nHa-3+I-Bz#^5 U\UP- 5, F$T^h䈉N,c-8SA[1L&@@୓  %?8nb͔)Q rF4c I8"D"3Y̗*Fqd90 U,̉9,r';pnX E\).V('O UJ0z&n 1vJ`?A>zii4n]YHbWyu- 4SLfR~roL٢p^ Cy-hnD.Ֆ–yœѯqQ6wP;🊕¶6p`|x>6O`4so::;eLoqflyAUP] KjVO컳 fFuc=c!T[LN1Y^rK.|6evoe>'_|t7ۚoרvl{<@[VjG9FdnY٧6Ut2vϷq_ fl;\t"c/Q>xj61u[ϟ^ѥnzdaQ׫NGjٛm`bf?[h G"%fރAd[ӎj`݃T6Wxeԍa !~0< xbla+s6`p VP8;Lͦ+:nӈ2M#T6+P-iL V"Uۿ(.ް'w=:g ts85ٰcq_ c/>O#.>~['^^h՟gd:'}!݁d4qycf8ֻ:C?yqYQ880YqYӕ%^WwX=냴n2O^^ͧ{s /b,w iY*"\7Jɢ OB0R8?{#OK:l'eqF #ԕI%J+q8UpЩuZ|;5PK8DxEvG|TouchSwitch.fzPK<Gfritzing-app-0.9.2b/sketches/core/TrafficLight.fzz000066400000000000000000000562011250202676700221530ustar00rootroot00000000000000PK8DD@\ITrafficLight.fzrɑ&wfP_zgLneCʤVkW @ dj_aDGfeVe]̈rĮKVGx||?\~Wdv{y7/ſ|Ǜở_Uux%T_/&חᗓ뻋7 oy4|nz/W׳7/&׏7o^>2𖿘|~x S9|br5~w ]I#9w$sG}88x7/~^L_~}bpuàw?x߽vvs9~rB˫=^?Ѭ~'~>>ޅ =~fn}ą/>!껿<u3616ps3^;7V\eo_3=3޸o~ B2p~:y=z^|x~v۟XË ) 9}-ha1ŗ}{_-^9ŻɯO4ћ^arnԌ}bp5ogd\>jҼy}^;W}v^od)a*S;lLy"<6m\6ܙu~ؾiY._Z0[_VE>T)DB{CXt(W߇m=.љ}^ϺKFOŒa/,)89*)Xoު } {x_tb}:?l 嘺\ ?al? D/CB-Z wKz Fpa;,CG' 'r9:0):c;M|_>6Zx#J ONzNp"I^6:wk➸ β:Lw>c\Z8>K-$Kcx0exY|ʥXuKEjWlXTxpÒ} Ē#_Tyx$aR} a ˔K(hǗ7iq/˸|yRi>lް6,e¤t}|v],bxuݒc"Ijȗ#Æ ʂ+W"h^Vذ,>EH)-{ ”}ˏRq=*L"ź^uT{Qqq/8*̸HuGԨ4e6lXgT|޸hMh}cyJ?v F票gnXcTҽaQr|%:Bu~ث64*V(aQi>FE"ʑ7*<.ܰL?5G=UG%T뎊˧籗fG>.<3n RqQ*"} aCHAzk/5IW%ヒqL*Mǽ6ȸW'g'#_TK6Q*MGJituo\Yp‡}}~}xq{9kXoo2{͋=.yC~v9zfE/VԿ s\+i]e`j9G"aJ7}T%8c$o.=[jþa&,D%ߋ`7w.~Xߋ݇ KE(:z=znQޮU U̅PpRUi\&+ekZ>e!k($siNRqaB@FI͛t U w¦xը8 1S)K\B$ĞI!3ddZԖ8Ach$ԏCBCq~:ڬDF=6|pq{w=/>y5}nv;+rw=~^E; R|efFP &[o@PƸF*íOy@.%~- hz=7A\x%W_^e<g 9K2kkO]$(Rbofw׷O]dls|}^q=~AsLWQUw\Ͻ`4W1يg281{Ԁg`֬5/3%.\15(5OHB2+ePn/cim[\/SϞDyՓH}̼Pb>#Qlϔ?N4Ff^-?||Sh5WdmOf̓|Iq_'+/{ޔ?:Q>v 'Tdfq|!e9̨Df8Mlf5P6~eKKrVL3d2i5Ku6D)rqfi~<'u݋Njjz~m]*aj@_H#E1GicYB3!EϭS"$(_@QGLۻr|yk4/~M*^sEy*>i+)Q \SB l)¶ܔ_{gP>{|ϼ}HGTlS?!z)y*Y D lP ߬ߊ OʲYVXGb8ԭΘqR gE ϼr<ɖxTZޥpK'368,G3۞?-.7_:^)XSBm_κvuƌ[SS8>7FOlq .d<ޞDG)ή<6>]s yC`ZO^HmSd@0N\lq Aɕ^ᅲ87њ>>>N{{}pY.xq[2_s/SsNMF5aK!qW Cg1҅+!J]PFSq,dp?dyɜt ) 1/TeT9)Xgp^y<ܡKq@Y@ş2+HνG];%yG#ʙT S0)^ATB0gӸbN.vTJyf~J%>;349[ AFsw!EێbA\^¡52 5TA9Qramw7|oɎsAݓduiN}%#XSȞ\xiqMcy&c'q++RheLcŦ kѻ.*P&;l&q6}| ϽIBH[F0&{1bкG.N]t3RP!H3s/gG+-xX? >7qS\U\x7Ϣ,)gsZUScX^hA(i}e*J83蟿!s/h/]7re/XWrif'w/g >`MssR9 b$1iE)ܿy %r}YI#Z1{Żo^þ%DlCB(br+=_`닠7L{2~ [eu%YkmrV4s$Y)w]pҧnu^ED ހ4l%"VKFq ${|^>\xvbǭ/̌RV=a`j4Nu*$)ق~nM+/,l! j25@Fۼ*nPیTJV\)͎s^(>"XlgXYb?(爉:$IJac1N.Fb |s/ENbOdƟ[13XE#H:к7[:dk.ĴFtGGt/hac4*F "c |&rq>lB#L쁅+Y(\T, c3C Ha*>'> ^Iad4Bic7mV[b+mN-b lUbX(6pVL AQbHFfP((|k=P.٪=QZ(\بX[ݪS*q)f .R<:p {A\t7\45`لH(ajn@%#OQAqyH@_E,PdFB˚] cPBA,f쁅,ԷfOC}\kGc{]: }jg"*Ke;KAWK R@=܅cU]+cH&#ᖍ$$c4"c- =uG@^h掸JgZ6?T$e*%=WKD?G۝n$tzHVg BQc49&l8t:xd"Ŗ;N37ĕ(xI?qQg@"k8ߕdA 4\B1z^y33w7/?n%cbI-s2V2YIҭ # ҹR d,V&ӊȔq{`\!q˳W ێ={;Dn>ɔ:skMLVTq_f aUw$V:rf.l;G!'۰I>>x+kMhZ$1J3K5y( I #DĐh)YQ(ZRKlhkKu&,NьK&u\ջ^)OɴFmR $ah~4$!68CCN'* M*&1~bԩh4c 1N;=0[(ݟ]<'Fƥ}eb01 ES 1aژr hZdp9-+i2SE\8,lZB072 5^վ El'㹧C AdJS[##1ڽť6@UGkh'Ƞ%SUNꗸ``ETpĀXve惘WqEed޵8~feK8x P|<,m#rPdb1½1BŞ,'ӊ6ЉWq{MZFsX,eZ%1!JءZe'OW$SM0s!Mr^tMPx<,mc0BsAKs*!7S[B,.W``E|pĀ`r>{(.¶ qt@嶝 "Gl/GcN^=>޽ĴOzș( 4JXrn#ImCdir#Ws… `Ul\=leǐC ӷ- Pe쁭l !i.b޹y\Ch[a}t1@WAJofBmKFo 1!夛Tio5D o]iomcTQݶ9vVeow^^38al)+;Um^8X0[{akeKO:CE|m/1.,Bm>VXcKNI 'r,ٽp6<)6a5>VZE1wç@nZ^(iYXڿXH`r-kTBwwn| -6ږ xKu['AڲnY^&iQڿHHr-c@B|7wn||-5>$Ω|-ãd|sBM+nf͹-Iд;JhBln0Bl$9Yz6~Apn|,љYYtµS}WReu҂v\[!0ڦY=LAbgkvbg#ɲ),s8h%JzbT+ofFv)1ubK/ V bV 1 J:R 2#҈7@͔">&,ʱy\3:%FHtH.+1 Y9D[cm1sQMDAƺ KZіH&d9Z x0Z>:2 J{!r63!3#M\* Tu?Xm-Q[v 86 Q~DifyO4c*]bHz.L8IR(7GVJAH[BQ o˪_sm+/w+A|+iV^V+&+PHY _OBW5cke+Jrԧ@Jr%FuP-f gfp.!%CMr$DFn]in˪ٝܽ="gVnDʄQ^KAmOInHݞ(:yG@$!7&6LuP-f%pib&-MR0鼯%\8:msbpAeRP[cp}16It<Ѷ&Dߊ1GF6@K anyn# Q4à (ۡ kY[ߤFu),r6ح4 BaZƅ6ۂʔU;>9+Y}Ӿ˲ $'/@pB JF*-fdMe&kAGQSzVpc+idiL$PWRmmI2Ibo}ЮciSA n]ibs˪˼[  /*rJ-idq@$Ԗ$ϭBٜ}*h~;[uhܘhr4.ctB4n,!וfx `uB q1䴹\hB\+B\nY5{r:/KY/c+݈LETW!eZQ[rzQ-E,щ6ΘpF6+^֍ -$kBn !Fוf0's6g2oR+I q#JhՐ#2WHJKdn4T8$xa +Q&']KuO(l{q63KrLrZ-g(:$;1(FQDDx26CɈ8Bmeɞ<>%L!WN n4Wn"і$aLV7*];B}+V7&6Jוfx8!&=09ɥrUҪѕa%d`K]rDrM rIme5dD!7&6KuO-fw'Yfx & \iA@>Ԗh\8}/$Pmom´qXxQ[##rdd MÍ# %դCgo)TF<7b\LTմ(1EDDɾ)&󬄓-lU &{kL.995)RÍ 'D&Fbo]iboƸ"e\Hg+9P" B2wP gzBڿ݀ܘrD.gBln,!6וfx39o=3OjWwH #swh} L;䖙3nE@@H!7&6{FuJ-MM,xֻSjbUjAHF[p럅r7J3<[6=95VZ{AJ]͑+"/j}D.wP"' 1! 11\(Bԭ+HBm@DfVodLedjdUeD*ŭSj9Hir/j} .wPs  1A崉\(`B|+B|neC%39JP'jҮqTPgiէ퓧q'J/R'ԗr$(9m)$!6Poa(۲j@Tf{[ZTM/@r4} e;lDm *iJjhKS p,W7&6K֕fxוfx@!>>fN/&+xU;żCv(+ [%4Ղʝw}(U8y3*ue 1Qeauycu#@ 4#@brgt [ 'L2H]^쫹rDH쓑F*f}iM֭ b֍ /'K2+Fu]iFSuy 6~ _7vlɫwW7}(Zctƥ,`SnU%`&8+"Ey$sاis-X^^ܗ%MF1<7g*dۦND[?^]?L./?^ c,`eӓWǫHlExO>̇cz7Qwwۻ7/78돁+Nµ?z{er:q51xE>_߄3^]ܾMo'o/>ti!bN]9iX 8us>V0ĩpޏ׷w{9}ݼY4G#hW{?m׷z^|x^{统AսF._&g߼^L>]| oŒO.P{LlyqOP;WiiSww|nGnt7<<<DqB)TywIiz.>̚/o&\~[^Nfւ1~ۏoO~ٿן<|z7߾}ǗN._w o?|u~곬ߝy8<~tNyoN'/Bwoc$E7M"VOxk_Ml7/tڹPۇo{ec,'`7Z!oӗ_|%}Rk߆NY:B0ͩ{\`&NO/o?:`ΣA<9K?~~*kgofxm}T0IտScÚJWh= 7?.gWɖc|=ygxma(jwNC`zkXE ujpCdz(ᵐ$r +U~ukoZ/#%P&HY&L6Tƛ.^xECTO_JW< >O66ez}ɣؙs>^ÿ/u8g… A:XԯdKi+˜'`tz lAۨFe>| %L`C.~W:"r@yeg:`k2Jgo[Q< 483e0JYG ϣURoOڟצMf5\\ӟu.Rr}KqpgQ>UP?s#* 0!aƓx^~0@vBg\4( "| O+@9*#O x8rˈ~qk@L#L8 v_k `dl~+䓉:lx+8g gcz/𯎇(Ap+,SUx)iAS>xk\  :߼37ŧ6mɄk2!>m.$UxB;|E.O9) ~FE˫h *Aw6]޺A2e5}FZ l@2S3Zh.>&:1Jdee|nq MMOU uM@!"/<?y 'mW:N\DMVZS8ilgnDp=*#peAt/[7nkr|}Jp#[x=ܨ~k8#6vh'W+C;Vh⎗!!vL]x'1Ћ]G.kʅ$,ګQx&a [pqSQ]!E Zt08$DX4h0 @#6`8u x&`LCE:pOW] Z; M#݊h AZ0$15v]\! "qxpp:օ6!^r1`c ط Cjyln`@5Y0N`,aaK7Q0d7^Gne(G00ǠH5GT;zgp@׉[%Kr]rBVo lc6lW;n@aIdE<ʀi .Ipc`8 ז~BzձP`l<40NDkQ°߷k b2N)LDw.V6XnZ A Hk ƃ X7h"ELQ2"2|1w &a#A)Y—1'=1(@?+0"6 kF~Քi$Ɣ杶E6x6bp%?*l"# MG1+884?jSz|l..2Kx&%9;ke~2F bFB섥=2X`\,&u d{# 4SnaF2i17:s Zhx 笡6|%u*pC !^ř C`n^ЦtnENJt6EN~ xC\At&|lto&lS]y+re!0u&#>z& S@#m_rE]c78( xMAl"@H1 +Pj*ϔ5.&wӋ|S@y1dGlNqvCiѠ`?`DZ"W!5pDUb Kgp0C WfwQ s fkxYSA@bQ~ ꎯ>XN{T =@AR )_x `qX<-;5]WIkw&0MjŒ7~5|#!&ô K*cGD8+F)c"Rl4*2s5ob9אVEy34*\WX8̊KSHSr BB%0Bd-CР=ǠH_> qbsx>T/|`M(9pY0T╕ =΀Ǣ9L/0J,pƧ8P_k.,FAr2QM4 UȤPt嗁 HB6acI#sOASbVHYZ˝kJB1GA(l$J3/' -éaXhQ<‚߆Y#]ONy'L&g)PAA'$Bd혙5\&!!^_/F8%p)/9p.H0@1h{LsI52x&UVqp⢹^[74m"s>a9NPq&8oA(E4y(Ēc%&-V<횓$(1 d:ΒRB8~Dm`6 '?ˆc@ІA5sp 2HaP0YnXUAʇ7wJFB$O%`iEnC"tХÀ] ɫ̂H5(~6_z}/z s& %3[@1x;Y|whrt znaЇ EA:ј;|C7T.]5/S5'=T87 lv,[I ,ʤ)d1S$pH@N.Bӱ7͈ Zd&xqexhCfrLFH>\V:1f/`<UbTêWI0"#*E ܜqpq;ʔ ?O#2s!XD4H WXJG!h^/8e2 "?$CIPPOEuȂNb |H0#1."`BEhLkF'SgSڊK4teh <bP1T—ږy "[ˏpGBiˏҘH~lrc8ӹ%D Jׅ6]k9QYRHaZLf书sDž|q%]EgpأBEJcko5V8‰[;$&8I^묹zqGAꁥFs 98h6NZ6 b.4d%NzQwUjE/I)TF@ $SB nO n˸A{ Ѓ2|+s$If " >/Xj]OTY%A'/'A8QbgȦ4>QN  Μ8D#F)͉ L^~X gP0t-{J WM9SҴx*iL4nl܍X-h:7hU[eQUON2`}='1S[jCz'Ui+K51Ķ"j,5$[똱0L|mԬQmKkbl-Obl2֐%=5-AyKP 2e 5*լP+ՈRo)5n)GT(Y\䈉N,c-%83Z1LKAQ)\pވjonZע8R,RG8pJ")P7A"81_j%`lT& DANYS8[ C\).V8M. N 1Tq@xt0;ѧIpiE".\5uk,sgݱIR[%s+mVܜn+p~CثZa/]pʦl^>R gl!Mwaھ3DS‘7%L 2&N)(|{'o4cgb>5Ll%PC~nJk,jZYBg3xI,ZU2pՒZ;mٷXWٷ F$,(,γӸNQA1S8niĤ֧\fN0P0*#0!6Sѵ`I'" pE Sx\bِr*,X.!g8?Ib {Zm7l ^ c:,;am畦c&i> 6I`]aA-P/x1媫Ybxc6Fxz0zM6-i .MH-c2Q*޴)Sc7,t1 9llusv5Rxw}~立ǟf?_nnzA۱ p:l: |}*Qλw׷7t$Yƫ~C%Lp-?iˊ1n =笍%1HBm7M]/<ޖKKb=M*j;Rl._އ?-/O^/+b:kZ+ nX[ ]3SJk%ۻۜ _AB݊.C{]2eemh\~~\ʮRgo j!Vnb .vnwJF3i V3]q'ƴAl`+_+9$^lAl><=Ә}8wȊ j!Э{մs!\)x<_RȃӸԽgΨKmO &o%|dM.k@ISVTN Х`ȳ?n "qn.@] ۋ#i>Hl(w7n$,/;leb)49.MѶXms9ikZ y6[[@>*0w+l؂DCnqFMoguJQh\\ -N=L. Vҽ$㐹#>7P9h!<ልtN]^rUv9lj$DҌ&:639HDlK+ Z|삒D+"Kۋ#X s9`22h |dm`Ʌp7j@byB1X#V4N""eۀ#4wryY̴ͪLnĩO}u%g+"ъPy&RKT6X!68PmT@9Y) "odAaQ A4#`:@tffeidV$&nހIO@d}{P bo Yfo2/Y*'KD$^9mVð'Qq\W\Lp|vsT6MR= ѸU$%Ѹ,8W *DFEp"T.Μ2gs8"aF #DҌ%D:^@lf L@ʞ1ښOY+(ʛ)(K+7Ѹoiϋ-DGrʩR9f#*gL$\O%R(re q4# qΆs9&.5wa+xNaR`m>E|^7G#"R+:/Ph`QWSDJ ,"UlɼlubpZ:\I݈*ih9 33C ڎ &'׶FbgCu =Leڤ{r3 )M"!'Mq(qU 3-2beǠmw3H9lAA+Z-J1l.6 9PK8DD@\ITrafficLight.fzPK=.\fritzing-app-0.9.2b/sketches/core/VirtualColorMixer.fzz000066400000000000000000000435651250202676700232500ustar00rootroot00000000000000PK'8D&KtF9VirtualColorMixer.fz}r#Ǒw#@H;*lyK!V$@ gF'9t2DBj@_/3?|=ft+Wd8O>|o?q`^^=܎z׳7ۻ L͘k7ɇWʞj>-]}0L3>ߌGWzv_z{?=f2_\NW}_-n~2cRûWW2S꾺Hx"7sw?]^ܗz/~M&Woׯ~w ^>W6Zɫf{S)~vjlzvsFftw|绦YdO&}ht?}p.xXL݃w#wg߱ř^g?ߌNFۿY urU/ sڽ6f${RvM9RVW폓''$NK/t?Ӊrrwlt/Kc̮U$o'ѯ.'=e{hVˣ.na4-f{y<(g N.3%g Bd\T;%AS"Ro@r5V=WOb.r?ѫ捞EalijJնXg#>JKd_}Oɟ $sHvRhVJFA:?=u.tZΩ۹:j jm+Ţom"qm+۸Ḕ۸ٸ:1 =1aA&rncyOHE߬6+(nxOnx->vnxO;tnsUbn{*Y:)鶉e4)鶍fbF_AamM/Q[`xE3+._as?NG3DZ-g1jkϢxǪ-g$Jegs_VvyvYd}g1iכEfާ]lyvY?B(5mRfxY}fihާ]\yveY}R]*P'^SO,Fw9ROsrdZEf'-Ud לl/ +zq)8u~UdۣՖ:B籨+4Ӯ%O,N?zL+4Ӯ)R'^Uλ [b,O,:?8Mˢ3Ӯ0; TcO+UfQ̢iWũn;*[jbsTN,J ?zLWNt-f֝XܿW qfA^3lҩ˰Ʉޏ~6V8kxOu5w( jM랢͔`ڐgL•bulճֻ ϲQ`٫[nF%}7-} XVwANSN ~lTY=jиJ?hIiF/rK-S\%oU HjH:a$K4ܹ O.![3h5)pU '"Qʷ;v-5oGYSxѱYpmADCD,>6)2j̹<>^=}-nUV^)Cn(]~PDz#WB>9Z;N`b;7$G#lC6/iv%l$U$aYUcHFVXma@e_|xd/f;<.dCN>92X7쩺RB+1£W)2v%$nwJf*7ȶ2$3BYkIP+4ǰ\5Yi;A܋@BRa7mf,ɑҚ #u/ (CHesPс$1&AlSYd/ J.R},-HCԐ2I8"@suA6"*Oa1:V Bխy҆T5&KҮ YgbhĚmP=&i!I;n:e6hERJ4v-l_6- ͈ ɬN_kJ'eρZr-J"mGG]kQΛÆ4(RjJï ۦs_")VH[U5L0yPM^ϷQ5)v7Mm`Lj iJOK<["ZNFF4G )־i'B =K-4 ZhJ~&qJO\v~,ɓCqm%iK4-eKI:!.LjΘ`ۨ)u/ܩ)IDL#ƮFn)WUi`)kjavҔ=ISǜQBTDO,ҴtKr$2ztII 9ۜz1{ *i^@JIl;jDz'-H=Hi)o{b X̬I0d)"h7' | N 4fkbΖ؅=Ȭ(Q5q!)-l5H•?&b5$bW8I̮R}f,_H-v=>Zj-Ecӵ0I9U2F$%xtJIjbFP .a29$LрrDJ72J*!mM*D]DŽA?e&,8 ^0bjQπiQ"O9[Y5z?ͅuF+J chfmj5^ͱHq^]Yg3Lb4!k|ՠ;72чLى֝2J;d4U)SZCaΔG!0[[Tkb3j3@Dx4i.lZƖ,%]yc$VEi@VST=aD?`8).w-βAlIY*KT"ʖgJ2H~YnM0~F%"e1}4GHgB]lH<:tan(vS>UyQjhNˈ_Qf.3XQW=xaJ9ea1?O6r Z}Zo_˷?m刺}7arpqw۟_EF..3NY,__\|1ȳwo7[A.xȮWx?,z?/ ̏^&wp79\-FEo/Ϸ}~b8o߻wx1^gSx?܃k'a_|;z̿ǿ^ďkAHtvwy6W}w90 S'U]/*_@ ft`vu[|t'-Cox9Gb|a4]Ϧwͨﳫd[La1j>/o]'dO'Ylju{9~xhԻz{H=aplt}p'O>Wpf+O bxӛ=L&tRyruy1.{Ni_Wz%6W6^&??8 urn<[<\޾hVN;^ץ>1݋.xYG+.h<л\Nϔδ#~/>@̈́q^ ;!r S?f,Z~X&-oUDAP7G}2ՙ+L*"E4w5ۭ/|Mi}Ϯh"L(! ]$3eKFS/B2I- Ay[uH85, x4ԍ?RD4"_r-[X(K}'&LkMgUi(ĭ$+iĩ*yFjL2`)kΡ*m *13ъж9LY`dƂMFV)zʴ4(QYfmNīf\6^M,]D^5a26ⱁ2<`3rĆc/&/|oĆk9RΒ gaĆIbK/|\ nΛ q%2_ XBD^5 |-Osն8ZpjEzmӮX8 Y4Ҫ16qD=o$$4LJV XmـeeSdV噢|TiCmk9hͬ؞PLLs2cDߚo-%5%U9>$JmoB\2pgDTNzе '׾L,8}3Ndboz $$5{k)I(I*$UN>FI@mQG2BJY%K.>l,8_eɦț^'k֊ QÉʄg>rbo#5 ! oqk!I$I*ѤC"m %a:GW'ֶԈ@EArk+~ƬMC5r8O}ނ"5 gKFekGeJs|,I(o 8`$=~x&?̡D"w5(}k\hh|ElZ$f II86ڪPRj@DMd2"*[Nw1/}ś<s{&TwIkEΛ$$Vx۪j@d-sI*~8yKwJ.>l=T<J X"2BXHnMysV]@ުQ{[U[[sUeVgl-Bl;T؛/Y\7# -'.%$.(̷V@4&iA8nÅeC<07Njdƭa1ooX)j[\/,1|z0/|n&6n(dXB)@ˁrP&LfF[ s' @ֳ8 -6a%R5΃"܂V/|n7^+h{;}e!3P/dZ3x`M!3U#etQ;*26;_% !dqİE$$'Oq[ nefP\!hfׄ̌%jj[PLͤIs(i{X3b 1Q4Z 7mΛr%v;[+4LJDWq:,[cOL1ߟe%Je2# Gm[,}417⦉VE\rYbcʶDܪOq[Umz1N3g2er44)k9D F^&l碉"*w4ȈQ$q&\iII*$-SIC)[ԙZe2cmblktF\Zi5uNрdS>LUu%$$-akI|I|*$-=_-P$DF'%U#_]WI[ ƕhg'fUF T{溜Wn`l0 ` YyZ\FH'` )tYO*Hc%$q $- ' K2w T;d4u0Il1؁I tFmL^SlmOڦ-Q$dfLmݹ/68EYcp[ayk9I Iٷ4ǒ}l$iFI`(Dr%ە(\T}3N#$rsc]W&)ٳaE[<=fަ)7NҔBٮM٢[[8[U$M+;wSmOŎ+!`%:VZ82i]*͊NNJ-rh-p+B%qXE)iaʆom%5!ieq$%V3 n-Qʚ*'%2)YQk .RV#AddnyؼidIm %N6 'gqLmkER­*$qUZ{rd98|=fgʄ߳I[|@ j9kv1RYv6KiJS<'7ST̒b7/63/.'׳C{|3/_@L~6uxܛ\ލ~'_/oG2:g/īCtC<1).1Tz֍ |~-FtaP{SviO㻇l4E;RB~w]cԬ7F\L+ؚDwێQ$K>܆{|of$!^k$s2ŭkDx]R>bsz|XgNo۝|!Pk2cp!S~ox{4ZbČ]iPktq[~}tx8p'^EffW/ zߏ&٥׽~}/UHݧ }0qwj{Da|{# q̿?/Wfb=hp2ɤ$)S&0~torf۸5:TqkoLH7+v׾us b~z{t|y!\ұfӇI~3^_-9ˌf {^og$+/j|]os%^"֟Ɉ}]d>PضO2!;̀gF[ mRtڎKpGXw!'}ͩ?E凮+J3$g#_NrZXLC\My]- NXNB¸;fA/*5\ xl~JֲJ_I Eܚa7": mNQ';2kS_Re*e$ 'Q&Gx{ӗ>ܫo" }ZV<wYƌp Hw?̸l_،; +[/0R~R30¡ И` R{5 _ދY~ㄡDQ0ኛ~E߰\0;}C(PA` *ߡ+_WVQk0A\S:g+8矕U.mIK~ f=9+[\yhS&B%cƽ|Sa)FDx@&IŸiC:(QN%O !<ѵ7rП3G( @8N pdC~K@L&=Lv?K ` Ѩ| H\ƵpUB݈0g?6JbINn ޸CHnO[ 6j)C<48Rc+ :,J&DŃ8qh@hϔ߉ݱ +G7 ^ƛ04>4 "XfLq֣+j}ɘ_fL+f|3Y׊D ̂ӥΓ[0?5a4a= 4J7/Co"`ص^0l\ݱFܘG@ +y˿=} HߜX"YT7+\>q}z6t=rUvgb`E/DD%Fx*&oHahK(-Їav3mA/>e@! N",:?8h ^0)³pG?G[.` uiKDf) onx Owُ5܀5pS11g8C>Wvz?ckgk\;Zr>s8:z޵_"V !?{31*W,0`X VG_AW<œ0?]MQp.D?a6HfZi ފ^/@6c|=ʊcMUฟ]? lhJA٣%F.=|if(Х `ȇf(P5C, 4X@`x_BtM'4NNMN~V/5܎uC#/ۂ%R,\b 0kP% 5R+F(>s ( p(42P=l,ɐo C'5Gql% >Q3[ p8#$u0ꕎN!A{% uhH׈*TPFSamWcs㽠#C{S/W6Z9FAB$`0ʉpv| 8 P ]~ (Чo+4\)J $7/ -``L#HV  IxB8tXlp; cޡ}X~tD1r1-"DKZU([K q DCj ѕUe"v|Al {~x $8$3:JI 7"aR "2`1v  ' a_d `YG@qDLaX18+p7\#2k?ՀâA$E:`|G.QEЇC( QyAC p €fcxx0d"&U!9H]%{ǸS-s|DVC섄=2X`\$&8uK {# ;! /I"vppZh8_P: `J8C0C<糾 ]`,kS:$.t:͇$r8<XUr_+Y ۖ,g꒜u0xc$Lm rEx! tg0l(v ސ(G ]0b Ί0<ؖD97frœ(@Eߵ% ^C ia{@wHK*d9B 9a -u/}p~;;-HzCT!]шy!4]@HkB!GF0vÖ6͝ƨ@ ~ZK)F1g΂A(h$J폑}aifZU\@PX|x9֝+T 0N $`9\!莇8ؐj 5Bã,v.HЇq͢ An%ȠY1L1M24q>qbë04(KI1¸KS,P1rƷE'p›F"1aC Cfy4M% @GtL*Ix$ں<#~Q^` XC6&ChM9` tN`mxa6rA̺޷& FB$)`iFn]"tpHvK{Q# ,E1h_FB S{qš 4 P2 ;  =Ysqp'.1Y/ \ Ę1.K 2X|aD\uy9 Qp ^-K/B 2!c QL)8p$yJ ^] 'frlmc@-~0 |jПA9%" ?x704qs AKD`A?$@\'E2FaVb/rw2(8)ʇ*>G14IDT0KDaCFߑ6&geNy4 O g!ha /asvX AzAnbt$C\7,@ @ߡ" FDEDbcX(~ mݕAnި`ƱAi>,G1.1&`]HItq\?t(JA!a 23ev5X\8\AW)8Zq h)V8zaG 7 gg(q#Ȍ 5'҈bl/4BjK>R &a2"/A#HL5N\+"GȌ"0f A` >  ^!n¡ y=Ԡ ]@f gB=AAaOp,RnDa10XCK4h豍#nRQ? :-W#v|aFRBª~pHpgPЕ4-)t66X/ŝX1- / dR߁ޖUUzw =x,p8c|#EֱB w"~D!KU%AiIP[*}I uU5JK*T*%%"( 1Љc̥g*X 30(0{xt23C ֍X6⥙2%Qnob`|1%Go]ݐd2/xlGbaN`~>8#aZ ]. X).f(<.7h Ug(,F`<0ֈlV"XP  77\u1N#$&)=L0Y: K&+?U-WQ9y-:4 ?X:?ci aAaұ#'V>a82 i,XSfQfh4D1"kcܨP+z g7 fOT/!U'fr.C>/Tz,pDD.b-s` KB0n OpM>>T/r_,qi_4(K}q;EQE'NM PðRŒ~0,9|fW^L`&/A K1!'%} oP/oC0;/0`"ŃqA9!|Fc5v=z?`y[;wDf<'fkGyP\`Q:JQ/K@gVBg .5.V |iʾlɾ٪ξ3"/LĤ4DxNWuϩ]m;ٌei]BU.R=XJ5 Wqp fX0K"˺f n+<]UxVzq3聊w*˽ޮL튮+\>iݞanVCd.5?"kDn|;7euĬ#u3C|΂maˢc7[gY^KbT>-$ D6+uTJjڬl~c(]وsW'*ԕ*w)uR0C gf7ZO9fnbȮfvdgL1v^O@ƴak if/їo^v}9unfؕ/޽4mM>1r+'_^Oq_򏷗N+̬g>-fv|yv^w+#N/g({~%7)rU^]8ֽL44^$TP2K4fCEHh*WUe?ΤH'8'!bGE"gK%haEd)>d7]4ޏƟ@ɒb&q6&xyZ,OqE3NJ'amMDTѸDݢ,Qu(t6lĵ -XkTΕDZ G29ίu>`ɭ`\DL?vGH[H[d\œ{[okDO;:$$|x} mEChHhUi$Y&ŸR5wPK'8D&KtF9VirtualColorMixer.fzPKBGfritzing-app-0.9.2b/sketches/core/VoltageRegulator_7800series.fzz000066400000000000000000000237211250202676700247650ustar00rootroot00000000000000PKu5D=3'VoltageRegulator_7800series.fz]mȑ~F«R̋/<=sko۳}PKX$K\*@!""f|5x*̬753l17m#LDl-ޟ͐.&8؝0l2-ѽv񆋑;3n??'w$[LlKͼ(a>\wo|r7o۹3gcoGT |e>|6Y\/\XCGOˇj9_l7WɆ=c1kw8,36ct7;w| 2@f4ulvS7RsÑ[ ~<pz:p7оOWS lb|*lϩy?.W@L^mܾc 1-p3VC%7Ca-W/lq:n{3u F˵;i83tm ;ӻ y3N7K|vosAƧ&O\r$3)MǘI`?#-·^vt! G'c᱔ᅽiytSǚNƈM#cmv{{SXT0 `Qb>H`ඩ3H` y$hZkCjt[Cr (HVhI`|A&'t|@1$&$oejIDH$$A Z 0% %q z,-ɘ0.- ɐ3 'HK? 0-Ș0- CkIꖄ}W?ZQJ(ГӒh=,-$CeK<_{b<`dqI_`۸4%#W@-a$CQ) Vڒ`5_%8]ے\bhIG>}h#- elIGĆ{iIGaDZ iIGĆiI.J_KB@tg$DU%a %U}:=- Ӓ` ԞlI@u8/$92^rx?"gAŜWY>Gf/}#/KfcuoV]{Oai,Z2?~%nqAp52yyP-#f-LnCoitr_̽~n| ʽ$4h9-&o_>xw}x_|Gku?`lL_W` _7G 2|KVGHr=f TCy@ތ4/:S}.6o_a>1VW&-nX} l<8 ?V4mj"[F B)ԧ/?6+BjHJ_w%c$fCyb̶woFk]$-`g߅}no w,N?߂ƃo :ӾLOMe6gSyJ#X?W=E|N-O"r3L=13HHe+,OYb#Bf#%;C/P#6Af+#ηGT~|*mt$6u'Q(x~S>;V>8 >䁔f8ࠒ?u 3:< X9&"_BnNMD-tDؾV,A0[ 2j(D0': Mq{|I0E\;D #_6?߂)<|vCq yUHƖv( #X̰%b9@ vHQ6_I_mO( l)e9k"?1p[Gz$X$vqS8 ,'q7ܯ^ 7ͷ˿^}U48w}>^:^Lر\]l>x!\uda]ƍ Sw}?\,{WΊ#5w}T KW/ñ+5"mK:"{dUXjY.ٴU~bٻ}zꨅ@ʯdpcNypS>5n\# )P|PTa$dV ~T߽¸e9$5ɍeJu@ {<̇}A{O8Fmnz2fuOMZpĜvDjE;/3w'%{)ƿ6sׅ&:8>diQ#u˻M-!*pbr}3}ʷ%A8.qyukuP@;b.?2X.qjX@',GAݽ\pVD$-\5="{t6х9z}.;)԰ޒN+Zrf,Pjdu.BPM{Bk% )A['F{th̉~j ~"5^Wܙ t?洹jN;,u:̄o\f?>h& ]5vs:٨ /W%,~u,;6BW/?lF' 9ŒUVB#{B|,'486 O?PȶlBEt4mn=dC  FN$0-D57TVT`E-æ JTP{2}vRi?Dg=4dZ]?Vgiz5϶Vy^ *&Ujڪz*)]q uN c3'(Fbq:^LVΪ׫*ꚥ쪕zݪ/PS@֮:sD`wDMLokH.v; Hn!p 7g,bmsAd G^i@*O0XZru|ye'Q/yJвԻBN?R hA6rBh'(->EQb_ވ_A]؆wZrB!|hO+l cy j4]BEt3aL}Uz^IJ^#($N:K2;dc[An):q1|tj0I[k@,ۉL9ȦMΈ'b뉉s|N O?^h +szwgX䁗.Q|Bzݝb t>LMӉl*!dʺV-e:H z˶A]ÀO8,ūV)8 )"eȡBQOj xofkj ^ [3'RëjnyjYZ'wg;ܽf*g1ovijP=wl8棻\`Ccέ3 V w #-&6&ayG0*LКB^ʷ G7@d;ILqml sSd,bljy8ۚRo i\5ϔ(V4Mb w:{~&f?\@ .Q( {"UUޖ$$'a=r7aq[((,jm5>[<~'=! a ~ B9r0O__\.64ܞب>|ƸJ+GR; +Xf*yOw*dQ`hg§Ċ#r,"tI2fåN3"oc*> LYcCaN¾m`mDSEˈ CBC10lD[ eAGr̅m %)pKE *ɏiP<,p&hXc, v, Oʠe)p&٤ M4Mb&3gc!?$ia, ʶtl@CO &>ְIIcdɳÎMf4m)t iMlgll{|&36Q'kf6)I!FEd[{PMfa a.Yݿ#MX.L]O^Ur$RTX&Uf4m+v jMҴJ  AI:VFhQ#^ZiRVddv:LAш0X KHe2;ˇyh' 4=wʇL|/eIv||#['3;tqi>ID:h8DIbC &em#"G}RIBWP.dtBn&=s?`tƯ+ ~W _zFoyW#zh ? >}O9Ã<4ƽNO[rD^WMը-z~ _6o+g兇l2^1ۼZ,ד٢-W{wbΗ39kC %:ޯ~ޯ6F54k57.φ{UGAq웵;yыj_{^ ]wXVۈ ރ*z C-mm-nud\O]y+j3]>ƭk =c7a}6_!~v8䧠}5vqS(B*Xq6V_3"8y*J]Q($ Y bUL WRX, Hgʅx艾䌦$EbKdf0m9DwM*OR e %b+ HN0#Mľ;Ԍټ2&^t6-E$)v\<2x**J K:WCYk Y,Z~obSD~=!)SnU9(ϙ,0 $~I`.@sRdRC[lj`Y1Y;ڴ5ŏKs gf6m)!kMA6dgRp^11j{Da/fKEZxψ=;B4 4 |P *$qXwR 09 b{L3dlj=)C6 (۪Lڠ>BNpb4m s4 _Fșq3r6`s3Y]qb i: :uzōA-ꊙ)`03thrlyJD1;?sG̲[p|WϽ:Gl ⨳0&wud0i"UCZ$`Sda'za;>^m>*T#Ms-X5R_5뤾]Y:#)h3<;bGy3D@K%,$M˲0# )QАB&g3`VL(zh.mR#%GQP'#A 'T)c!k<8|BVb$qAt *mA#R/Qʘ1%=V(jb S{(uqLIϣ%QgKsIu~{.xrcs3UWNw@aK[آ.s0<"X.L[5Tvtz'V,׮ٙ9dp۲UĮ, ܪEcYMG (~Gϕ|)#MunfJ`BKͼA鞶&J'Y|'k1>滷iJЭ}R:TbMLC"'a#iYMIuHZD@W –Q1lU P \ 8#<StfuZE;T*QL CjdhjUI7Ŏ&(#gYMnjX$m 9KPDQ񲌦eC8>62 ry^fR0K:C)u3J(YF!@C'i(5o᳠8͎hQ}Kbmo8f1FvcdYM3"Qg#+h6++'#eM˒2P %H A% IzDcl[-hZ}_ TZwY2eī)&+Ît_uGsP03+.锬' HAa0) (nt6n)C` DGc>/-{R \j"ĦkO0qּ3IoZn{L\iIG`G܏*icObGD-jm2 ߇#|XGfKf$BufM @|iYjT̎j7=ՅX͑@Q) :=N" }Ign}:@Eu*NpV:մrM.Cx- jdԢnFa&Gvr,w:>.[Fp&Rħh E ^3⊋UQRA+'tVHEx.bg#+j7.>ꖑb@H}$$׏˟d> ջmFbލe9FVmX ݷa2?C'/xiԞ| i؀Sw6zO΢DS ?H恺dA* f9RsD(`D^,gak>'K$'do$1Ul7?SdH3=C ď(kOi3<>ء t q1^Z崍M"Jc秲s}C'A$@@>b.TZI t'0Eg;u0m#鮐F~nUTc[2rW7J5T3:մYPy Zo:Va6u&ӔL;)%Wz#~ H0HGp zѬըgoZDLG]iMz/gt+~ pIjl(:-l e|/:-|mc^Ǜj@ m*F3 W7:ڕT 6phWA"Ԩvռg'Ǒe:FlZ XW5bjuba8aFD9m]Ǜa0eB]ѱLhF_pI- :Y{@,d@>bſ:ƕٴd\au1WYl6'qüc\Ǜ 1 9ebӮs ^R(WVr0C'ANQ'b5. J#f[jNEc^MKW,= \YǾb_օ88HjQ"f^T 30(Ѵ㫠KjjZTI'1(Q'j&b@2qBMRi0 LjDut,iy:v){I|ϗ)q3c%DS:RviYRFtaRB.OJ/t,iyj>t H85\{ lg?ZDm&"q:Nٴ̭:INv! lNvrQG;޴ &~#d v\ѱ8`N>:YX2 $=ȷI3Ŷrƾ}(Q2ZQg%Hw(6TX;˺|5+%H(=#g^R!ZV goq]ɶ_-@["Zq ;l!3FEL6rH0(B]):QY*6f ȦFԵ/u;= uOAG]ʐ#Lب&:QzOHd5GͣxzύEy֟Ƒ۝xRÙ~XP%Ld3Xn <*UAnY۹A cn04^$TA:CV ]>dUDV">׍({CMui^E$]< ̲3Tۡ |0KԯRr|kFJ{ pD9`4 } eBW 2l Xp( i bYυS!a;n{>F)[t"[6~VbCr;Vur3URҲJnӾ)l@C3g[/0ܱ̦Y .t֒ے ohmFX6࡯6F#Oѽ}rF1b|oi(`G@z6"51†0"8x_ ף,DzYfWJ\}GƒȘ^Yfiu"!~iLpv3$ )È쌩]ᆨvNXhYM; @5Gˑ, cG౤Rr(RS:lَute,.%?SDMKV %K0\>U|K*#TU K0DlAm-;uL5)=iw,_APKu5D=3'VoltageRegulator_7800series.fzPKLo'fritzing-app-0.9.2b/sketches/core/VoltageRegulator_with_switch.fzz000066400000000000000000000403571250202676700255140ustar00rootroot00000000000000PKu5D],O@{VoltageRegulator_with_switch.fz}k#vu7, H#kwU2f4$[_ X|nY`NL|~:wl>>~{E"rݍOұfs}y^hGb8}{wxջЖlb&Y:7Ue|xG,V}|y^u;ضž`lz:ξ">rǫp3 nyWf_Uw/mݣ`1W_?iiL?CJSl0Dt2wᯏ\}coLdOÛ]^~Ib~($߹q9x;;"l-Θ47Fs-9R2WEs;=>?ϰ~rax}xM&dfO7t6L>d,*k<̓?}b) L܄jh1ܱq)_u>[!":;.@|^ɦOՑ飛l젋MUĉtqPs7m$}8}z¥kF_Ji:&]Hdnrms( ɘ,`.5Dؗ7fý\Fȅ$J/$Kr R-[|!b #j[ C-^HrdjB2#aS_H^d xp!I%r#-B2"aS_H>dɠ##B!aN_H*d3"q!YjdPa\Hc3Ys!繐mYalIۤGl{6/%qKI|LpFޅ>6AMg*%u!: keKal/$ TAq!i P ^H*VqZ>MVP~3ȫ$((HjTD >\")502%$KvY[>WeOb) >*]`y o}Ƀ0)=[O:l(Wuct}J..s1m'rLmހ3O.U!~s -4nƽbvBŚki&6ܚKZs%{dEXSG%pqJ" f3Rk:k}2y~KgbsՅj>llc[-[Fl6KC,ڹ2,*w\jJv.!NMnkFAr+r[*ҙ~=:rU3SڭzlJu䆢q>&'1䳭z4m~b u j>r x=ͦZ|<>lK^uO; Y_mGr~Z$>Ȧt+UQFn:H)@Gʬps̨{` \EF>ٻ*ʕɘ'9'"A08!x$x\!)L)eQE,ʅuYVf4Vxꈈ*!dTHDۙ{&odCS!ȖQG1YwW w 5e$$}H>s][|AE ˫ U?CΫDTz%=Ug̅rIS=bQ(7UA>{fmAՑٖ{lemV օEB)lP6gԏA:!3kGck˛%u~8l;?6~핲ý^1pql|~F*ʦvU}U~9NĶ1RW]OtmOX+zVX%n>l{m9kwD=c&dY0e]"1{D1r3R S…V0=pB,4_ OTlc͕] aK/~/p3\g@Ƀ0CߺO'oU-j,yurI]34ApIƷrI7rɒ,r,'D.Iu4ɬ].\BUܖ%͐5 S֡qIo㒜rɽk-,)zI78NO&I hYJ&MPh uIS3`GZ@CqI P(dM&EdQ5+0˼ DTV(ĢGߟei3=faT;aĨR?CVن([,ZP85ԛ1B*=h l]r1-l4D i%'JMYZIS6 Rͼr4piE)ckqaBHhRC[>Y*aMO %J "'v|bGDP85j3hIס;´ōK# Eb˄EUBhn&AbO,u~Oo;??^wz?uk!"׫byy^x4D|1\\O8iq1z\ \%EϓQgɖu<_S3woaF:OQe6xró ~o:wϯz=o;<οǿ^O e4X$c^=Ng%q0?ӧW鷯7bdt(|1?tkolأS6{;8?GΠ תAaơc2u4ݧ{G9p{}Ϻ#f丳r> 24YB>vG<3 e)0V'ۆP ʤcY>)HqZm7(ϬVqdvTZa(tf]ucck#7}V_4Jz`1"#vߔHN>v=J"FU8)]5'"/jΥ)֦:V(G-t( eZEM1QH Eh0F?I# 5[qxcX(zI7>N+ˡ!pq|hi!5RMZ-T}&eTSv'9.-4?GT&-nxHdeƶPmV(oA:4iqEFF ,䀥j.5E&HqryxcU-\*z Y7@j䙼搦9zڎdg{q揖Y7Dmge.]&*LV.Y]x5s8I8kQаG]s PlƢ MtC "ePi "LMA2Ve43E\q~7"6u9AbKߨC+9Jc2, KJ+$vvLMoƢUiWڼNGYa S'#N-aTL,ny2DctTm>=e%Ew#nu!8ƽE =i xrbK ["BD%Tt ۖknYу79)@IݻnspAFJgކ(od10l=dͷ e( DiYIO M#0).w pZZfd$iW\IZ) ,&ܹl){XY)EqrҢ-G'uX / )0HiIZIі&逑$ i$gVJh,jircZxi "547ji2FX/V|IKj[~VZp~OwovՑ+g\Eq__( d?R!УƎg/"FsܞQ!3ZUV'eR@NUsh@)n{Ң`_ߪL $1Hg̫A ܋b^ˆn-*+6oѮ!@PNUB.B.Q/CcoJ+_c-k78;-kI8>ֻrBsӲ2$YdCD2$d GȚ .zkzMmp_8<Ŏ5@R׸,U*k78;@TG6]Azn:;RviXN# F,$NF<iYY#dGå0IjޢtWxyͬK嶘iS3 att=rӜ튚.M7ųgތ,AB֮+Q} Hߒ-++z0zA:XDNF-*-ūmbdf\svvyQ?N_ϟ;}<ο??M_?,OG}B@S}a 樂%:C9~(srp6=.#:3w;ܘ>.zw O?=;,WǷp2MVGޓAsb6u+/ߔ䗔dM=E1uOA0V0#) C>0#e)eCc)*qABOETj7wnXXM*dDFC(( gͯ_T%~TVM9ZmQw/wAQ(V,l$P0a?~W @؟8v?E8QJ;Ze*cZQmXvl>>~Wpz;~O? __;_~םC#ׯ:_x8ۂ}Wh+Wzl`ЫΟo7Ώ' ZUH*lyc'/㫽؂ݧC k#Rꓧ=%q4KZ!+b#Kn27O݀:޺!iɨw3z?~zLJaYS{W-IVbkt._K$u$LD21A=Ng!S]屽M*z<2Md$I$b_`+ib{eQɥ md-B ?;Q2~o{ڭs=N]e3'5yu⮈#nc[Qw Uƽ FJkL R;1 ;[owbX_kJڎ+n|BS~{0aϻ΅Lԡ0(P@0Cb'TwGwsw}wD. "$vR fcJ[hyYȅyyocaVw ,TtiYK' TR7fܵp`C{[;e0ve0)&a W2 .?TDnrJ ۂP˳#A>|v8Dwj1G&tfd0ᶔF*YВgkP6 4wF4 <>ٸA Oh+]1%c`pMSf^rD"XWHP5h^sPOXjs_4Z/"7h/z6LIX`k!h_?X0hsnX} xA.ͽ B2ckۿvF]QHf?+l9MEdlrfMdV^ʜFlY;R2N- 'VP.ILVm{Ԉy 0|±OeroO{VݛSHW ymROk/nA{ ݌z9\)@ ]BAX_`kwmbr>Ebgxd z8i\ %sa]n1`Nr29+\A]^iAIJ`+^S" G؟P t0/Y c(xQX"w7 iuv&M)3˛v|Ѵטv4gy>ڎ޴8zδ+4Dm6y77LLx  `Wĥb,H E@W0Sm`0͍m ~ 0NZ1 0O`0l=kMycEr AW[,:[42g̢:+5@TA @A$@mPj*9Urt(BBa$DC'LI4?F.7h`m.4hBEqc0;'j2>D5>``6# =jJ ؃PIl!n@&(? x f& (xAdݠh80fL=R+P43X`Kf @T4ՠ{TAj^; i]T(0lwױ䨱с~D+Z*} *F/C4d$pJ<錣<9=v"--5:Z$h)m]hV# 7ÍhxM#PRU1TnSK 4CỀVB/Иn$R0)Z`)4bFkVq6܏ đ 8:Uq41 ^:`)@@ !Mb'1|3`k=G@|I`MDY:߽gXͼѻy{9w"/D EE]sϖ%*y1Hv})bg:L;ukYsYB*쁧g܊tl?0ࢇqBXb,?0.&u |= E< ^[> /I"tPSA4Ԇf7Ѭ ' =ˉ+Ϻ86L $GQ2vMK:>9mAl:XSk%z¶9uAu0[=q +4E8. 4#6^c 'Ej^,  @be n %&)|LLAcyS@xz]1ڎlOL,E  `DZW!5DU C]0'Ծm!:輗xwMhă=aVؙׅF=[cLEs"yTD*Q&!:`LBqU͏‡Qh, E W ԥF2AK(2E&^h{4xvm{mѧ~_b)y ^(9pY!esGYQkUh@c~ء4G2xĀ7gbo pIhv VkX; C<8Y%` |M9x<{K}7,Jkq ꦮ5Ԙ8` P%N DD40z#gX > 0S0"b5O66d9tݧ@09Ǽ"PBItÀDpG;z&iupp !vv$z0isx$PU̱'0]0b4Zai=[Pt+9:i6 ?`r 7\UA Rܠz#)z34O\. i3_LD>}L_wc~awDYF!x`GTP7 0Fo 쎷^9܂fQlg_&FB$!iFnS J;?%<³VDգ(~160E݋s.pHvÖ)-`ˠNȍ@xm-'&h[ $q"rBA֋ E.je{hD1.K 2X|aDDtVo{POCp6e+aPGL ƒGD`+"X93*j@#+K_طG݄aF}?sc|@^z=M]A{/%2ce(e&]C}s ASDi/{o޸N?I6I#$7B >d <(8?)J^0ʆ "&ATb6ڎ18%Μ/xmʡ(LAb8ȗB^/8a2"?vc, Ez@dAq{jP}`0 ܇y `H#6."#{RF\%:1.8HP( qp& `C8&/=M%|I1;)Q^Nz ? *k+zaG &7 i]9jXTRs3(@yrv< mLHR-@HAĿ 2\^; Qn"ž!2-2:2XtC܄KAehQ8=]i " >. [1JOG7QTK'hz lIGmwMrIuTjDyrzU[br,wsW,MIn}'?p5Z/S/| KKXUg4Iր~lq3 ##,0\A쮏AtULQ:ثk:ncQ`h\;0Yɘʤ X& ~v9yc4W?'?\cj n^baܵ%'^9$;Ka?)n Us4FO3tf,BJŊVv})fQ 6Aa>%DRP5QT~bItpps=+׽U.&L A1\ Dv0zK\s+ⲁry.\ΊsQs6g T7?Wjɯ'[2e9.kC#7R %Kfk}?>D{L!t 2Lqp5_y=VI6?wSxB65~CU\=?zɛyt?GgCg \6 p2֖es㛭Ʒi:qF 34SFENf.sK粟1ބ/S;" l+a1Z0$ށ&l0 w3 ^,!'̂%~Nuq 9$!(P~VXtv.?\Sӿѓ%7uzXpRԥ.` ~5V"uթޯ>w&o QJr^ cBpt<&]r?Xۅ2Q 7=6m}W~|VX簏r3>A#FVDS&B{3a$L$ijr=Lj:it.(  'b39@9E&n?,c(4Gҕ CN~ !V< i*+zᬁGá@ HLY3qdb]DVIVɖsRN&ֻ2 hlie6,c,nX|,P i@|l/Ch{LL,Phwab`G1TL,Q DQ1fZ"vִz9'r[咰S9&a+bI!Lm6+-5 i+SPlCht VH[hw _Fm T|ݚ;ɭf|4T7p!*Bvq?O_Ff6a%t\f=jR hZ Y2迱H8>v>Rۏ)/dȘ{vvw׼IIOMOG5jk6W+1BJ9$l2ԎUw,([ŠaIt#i/%Б2D~4f7GPLFHDI/C;Nw+Zl$>]ڧӐɾ.j:&ۅ3G fyF;y;y56.J ֮ !40ZUVtgc Xȯtͱ.ewSL*-RyJ66ZҘӆ&I{r5DAa%0aꑽQ'ܾa{@mWIу^aIs$ \ 9{k'Dh|"_aBG.;\bj%ed* ^{"vg}.@d.!F3jFMNc*jiδl= ,P#B "7Is\5'1$9AK 61̠LE~fkL+݅ő> $P1T&h4IwCg.f=ɢy>:汚VpCE(-C+)z(oL#J#A,n#+f0{9Wܒӆ@ѣIҮYk Rc&u3vz<6tH zM/2=aZVVp&+TX=bwͅ0F cxjiaȱ 6_ GEץpZ8ґT6ZiwZ 9! #| S.W뛟^|CozXw_Go݇dtrϻ-i|]~3? G4`9~s2y[x?}YGVsh<'ʟ 6N~}{,o_\ӑC^aJU/ w^'&"\5ɽ3֨;b4ݓ["'*s{yY tgwo'V뿆5L/^x^&&0q닧x _,fxx&+CWbC`=N Jܛ>Ny^_<f2;Y->\&J؛G'DBM'DkUPb^uJ$\R P\ĺytGB[~*f'ڰM^av@ ݨTN.G8{8;z#9[߀@ζn6śE>-mt1)$\[ckaYHywe"kr C-5in3`n E/Z,m K"5mnWCDmv2; n*.6q+6$aQᮦٌ8P_?h3y ͵~;m Cm6UidҴ9WUg lGڑyݏOO]pkܣI֜Sd;Z{IZB% $^_]|1HD;# \IBA\I~Rwsau?UCW#.6&U{qحt]P۞Ưq/%,ɻ ok)A-}-$s-R(DWߣ]V2վ`D[PS#\IHI\ILP0 ֟>!+ w?>^I>߾}c[Bߦ}1\Lwd9|-VK+{S y|`Ͼԃo_g7K}}hܗD0z'k 0HYpXG;&WѲw;r]ac4ANәkc snzxwA+ќIB'oJDB t{M`!a&D95,kWõPHlǕ%{EЧe/KCg>sĩzéPfT¨"F hJHIp{@ ({fF$FJJ}8䉷G=bmKztFGNsg q"W\Ts1v Yo]2&hX $TqKMB8+`W'?%U1TU*< 9@+v fQ1َSV( yt<' 2qJwWD"7D h?~|ÎVn)?.OvJ^8?<1Y;f1'ŌN+ۋ0KJA.>_U%nr՟?oůw~O/z7p"!w|H>dx3߽<.Wxܭn>{_kSQ8TݭiWBUZt8V\Y_l8^.s<{i>ozя_|b>2z\~%1>pw/狷ٗx*y;Z>V/_om~Ub7] ngoSG=/+My2-?LWNl8M{#7Uo=͜zѢzL7IG+1}i6oz^߹λ3?zF+,f}3Z&'I@u_?M'{c}ʗ}0xFx\2'_dl;ׂ&Y'G#=>P݃2]eW&37:O$ |^5Z sQ4Q;{Cjl"S 􅳘J%$n)T@wUF7;5{%wBcG̪Ҫ,|b4i#UV.BfVDbOs zƥAC\H!),.6ZWj6H>ͧCT nT@IKfQWýoz zz].?[Yž;UF04"||>ƓAliһ1ˏ9mџKÂϙإ/:ٱy{yuu&lıؓcD s\@ Ik')@{ K;9+V~JPoޝI"5€_N)jR,6_Z, 5~'ߞߊٟ2aRv0l7`Ӎ6CѰ  sqqon޷V##t66*<`Hf5t1,<#0 RF}uE}s$tB?#!T}Tjؼ`x|]i!~߫0;T}G|ؓ#]H:ZScr0^:Qy%n_IC(񞢱!X۩Q.h I&:{5)`V7E/%FK/<~ܞrҙ;8~/L6=іr (6sX)B*$:ɩs ,_N[Ҷc+{wy=4dB *leب?[ ]zK^+B-ŏs[@0mAVir6z(%EA9\K:>P|hk=֙bB-μ4;ƹ1ug1vZ7I"oŵ诉nb"eG$΍tI>M7ܷ5t77!H;dR imcbN6ulӚ[R 4 v| *6ijBE]0Ur͂4{4#>A<*aXfim"8UD[ qdszюln4vqnY?d RPwG67!H[R inzhn(NZЀSdo:j9y<0Rswg@:LeD˄kOuN%:OUHG;+j)nsTbpRT,QXIP#݊ύHBۃKqnY:yvV:1'G $^iu-Q)`T:)8I: y2yL:yy4"O;RN0x#%+9r(g[P7:ڲX}dJZ%i:Ӟ$αEL)xn(ii6Iى*=vRfe>WDE!i"t8F$NH"%KB61{(|;~ BNu[\LJ#鎠E:7<淬X:󶉾&P}OXѢMXA.iv3W/<ԁRL$L|.d.f79:vOl[xI;udiV4ێs})+sFAv+G;#^01K)nI*ȚhԎhGSGyFy=Z _aWHO&8w" $[uuDhGKU1ÓHl$12V K'ǰ})NkONj^秢&5 Bp~*Jw\h3O VXpզ( IX/K5F՘D^H:yܾOoi$22$tֆUs tGDwmK,b1DB IBV/vV3ILJ:rXV=|miu MOiBӜKEѧ %Rɀ"0R612cj]L킃5+cipb{Gf*+hi W sh6L''G=фXpD0@q.n:wT񱱢ױbn\лU ipޡ5*E+wqlszeF<#ѸMҮ/m2=wvgњ{Ċ 31xĘOE|D.HGEς?$; idӜ'~tFUbUA rOs(B13Fsӵnc NNv(ہ ~v&g K"l{ҦwR6'|8'Oth@'өQ;< u~,b&,aH۳Ɯ8WX]GI"t鴒uYbIG P30:`8Б7)qO3;nh}n)\HԬ|Z, &,rkSJ鄉MD77N<@8<_A;`=߹lQt$>zxq{UX$It&nLf:!pDvcg9)pĐɷʘ b&YoJ =;E7Ѳ!u fg [ H;@l=xXIڹ8="p1$_9ܱ,Nt,h="ƎF=A,NiadHswڴL(X(@m˩? Q;:6ՑҢOo'KĘdEENlXi;ph)J6:hy_ۭ,;m.w@#/x:<= k|?Y n4ɿt o"$j$ݤgs] L9fDxHXYY1qM> ~2R/w@H,ONt*zG%d;BHIWfeYYM_ىF)XM>" R4Ih>a؄f*I‹SNq1?Znv(J՟07d%&DXfvb 8ѣ="A32!bEO@Ď6I* ~4IŚރ[;Ly`s40ぱdeESsEM)M)ʮmǔBl dgge7E$tuz wFu XYZ&i"&Yj]xmblq#hLW9E귥4GҎŎ=Isw}Iܐ˒-KlBlMΎݱEk8!="N't䬬 Y&iB"A&əm]xD`*7+-znv(JW=uTeюQ#jۋ&jqI{$(1DGʝhhr8MҎ@ 3ҌH:D >P<ӑi;Ҁ-ǃaʊtdgژc!t$l{Ѫmnr\# oX'dc;UZzW(H@I|E#fBo_q|~<vlh;8@şڑqԑE pJқ{ݬkW~1U|Y um7Y׮b,$j@hFL K?wqyR8vHX"-D/;;*VVD[Ye+?*x:t0Z.N9rK,XH:)ݼ&Y?91RisON(]%&9vƈJU, ؑ' k'eudT3Wd]?K *tm{-N,i+gb!-;XZi81M>  4DLFq`aDHrxH(ZYP8ix0alHJaDKwl{ڤ,NhOm9Mjn+-z6'xIڇLs@dca6[$VR}IacdeE32>Gm!L!VD)E[ڑE뒳H=N";Zgvh}~)~IڇH0A~fFVo⤬=q$ꄌHvB,BJl ԯ1k>&CKojB#T,8w( Xɠfca`A6 :5$_4L~q@9I) DUv,ns2*v<*v\hs@-SN .PwE)d;Zh4YpIPFdiGFJϓE m&)S4űXMƞHV$R [z㝨MIɷmv]=+;KT@OGȶIbHXɲcX7e1R*+tILY>cP1"JQ (V㑱eeE'L$CxY$g\zcMPQ&Ewl{Ѻ H=" LfQ+-Z?g)IڇHpAFmD-#O'>7#@h;)0+tN{УBx#AsYpFFM0, q/Z&~< P[aq@񯲢'H9kM>HBR`G$^v6,Nh+X,(Xič6I v4 GqRIa:,ʎƎ=!Ю,)vq%;nhmn'G3d2dihZ4-NiIE#MҴ8v؜:wBBD!p``Q5O,s@$}-+9@',*ZVpf'ڄP14`!_,v?E@J\QP0hw(Fhq d\z֘FW{M>lł -N&[<IbMqY#aEq" *'$^cbGʊ 'vu՟0"ʮ|mAi[Q$F vZ0FhH3k֦%+-z$X&i"A&yh8xR4Ž Mi'ևȥ.+o'L"qܴl TCwlkѺ,RhH 섬!c1ҢY&i"&YgDsFH")cNBicdcGʊ)xoKęfǷV}lC,O֢YIW&fGtlNGJ !m,ihmHMrU&{!pVc1+-zbvJ՟01d!ىa at7#YM dqF{$]E'd5$dGOzYi8!M>E#MwQ2c.ՇQcceE볱sNX$gmz}{zR;Rh]R)vGIY$qnRVYi,Rhad`HML&²bJ46 Wm B Ѳ㡱eeEO@>ɷhO?kΝ- BEr6ȹ.8ZpB6@xE^6EG#l2&8;=zft 8Z&i dמ1HSLq6ssM,]JԆXN ,[͟>?v*v-SK0[=dAEB)3p+l6=?LoV*2i1s{7_>&V_ogNIǯ? 7y~|Y}ٟ(׋_zoz?㛗?}>_ mWhByÇo/FOr }Aw=ܻbo'gw|Ԅ~/Vf ~|%+|/z }n:BEe$_/79{Б0Ic7{g%{٣pڡG{fU#=#{ܤWCfbIuzyG봁l2{{LK9m xd(Fd>Ԑɻf]r:m9^L&w$ϊb[xOgD_x v]@?4ᔴ}aݵu׮7xH6s(:v}G#ܕ4]kD9ETz醢4c6SjTnvnap(5| -MƗVh ^[-Ƥ~ߧ̾RWRBfu5A$\жř0h%(+U), LvUx{oyZK/"qwp +kP{׫n_zyI%tϓό+g& u_Ш?zq=d]ڋQW^ Kkk %WG]Ǹ7~)=tה0CA)P@ *\߱oEs rY'qz댩3})%/ĉ<(rDns"w>UkP#W9sڇ*-TWEc uP!YT8}ph@hϔ?ݵ+G7 Wq|xA/hkݥD([fLv֣+J}ɘ~aЌ&zQz(!QYP`S`S`V`?xR MVk߃A9*ٴ>{JeZ/V0.I̺.mw͈y  0Oߞ8gr$oNS,dJs8Ak ݍ9rB?@zR H($"/U46>,7qJbs6a]^o00@AXX9oo#kpviH"xek pXu bƜ Bh{ ,"Q$V"w7" iu/X hS7s~s8sy׎3vvvkGs];^8G;1vGGϻvK:Uaɛ˄`4^X a8/.e Xē0oA(8D?a67Hf[i ފ^n,>e|=ʲkM޻q?ŋ nx49shdΣkA8n1:g 2K"5j)P[L̙34g h0@(QHw B!gѩe~1Vwbq8څTh_2a#ط Kyجf^!͜xpe 3x [xG^00wͻ[9(ێ`6`Nm}t}W ú6H -@}BbaAL\`5 h@J,p=+dZ]@P yp4 ptP\{"рGCP؄&a׬׸@qYp* 1fB a(FN=9̀a|b#mL 6!)b0Ɔή2ݱ:AT1TV(hܕ==`%B 1܀|MbLsTЏ*?1P'PFsU?EJsJd@W`4z Va{CK@ f DFR*uhj0<`r4hKD@lk }&C@> N J >Q3V Ra䁭DuN wa> `zSv4H"W׫z*'{!otZ^<Ò4aRf/ #- P1v6A?a=S8 ,F!U+Ze^N'ov;OV;~,SN@8A 7u `"g$ }Tq2yHT$yCkD AY`@[˩0PY0Q E h+H>8 ?A?/X9`nϠń(#e@1 /RJ #} 40Dx\BHVjx&h=|y{ѧ#c(GA;T#h(G4d$pJpFmA O5ǼBzYж~tD1|6Okt@t)nXsA w!5Be,hN#ԑ4u8пg.'ת0 1t&!aV )n'9vo:Zɭ}I|m[s[$U)FM#a¸OE ?s E$QuB@3y{[I1ij0<؞D9g3OaN}b 併| O9[{vg:ndj 5# 0D)' bCN탫?a,:?p+EOh*;(k1.$A @I9P:tмEH4Tag.)LcG#s!xe#kW+Mͩ.Ŋ)o3_>k!rBB8Rt!p~)C;gLEs"yLDj-UE2݅QhgL E`T F2ǕAO(2E&^U=:E|}+ sŸ/t|>a&0@wJ\Vt{SV{Uh.كpv(&͑e /'@QbB$368ct\R% ҿ׀^h@$ \ò!HIšh2k4]; .ׄCd`솭u><;IqQ"D,!bJA(h$# +0`iƂ݆Y#]N ל"о ~pT c*h;F&i up 1vv$Fp6!Ht*˱g0\p -!ЮYtZA4-h\B ԾC89'NWqxU0C37] Hu\cg~. a<^5 * \඘B@02d ̗2cL?@C0gI! *h F0l@p#l(]: 2` tN`mxav|Yb[ #@Fg!B0J_#7!s:hR`@. `U#1u (_̍ @:zE s.P%кaePFGF ^x0:8A0$sEaaEh RFU'潟ڊ KT4eaY hZ*6ډڕ69{U˗yM*|oܠpcA;9;1c"Ӱ0&!|`mpv7]?kt!%ve2J3@ ue6:^r ֆ sd9a *tFekӓV8‰[;$&8IB+¢mFZ0ӈbl)T &a2"/A"HL hjNT "L| Ba!3-2!2XtC܄KAZe 0Z8"]D}n JOG?5`'hv l豏#٨G^AU툝+?#Fe!̉ ^~pHpgPЕ49y W %{RxiX<|q!c[w_K{SLt-sү@J/"D~>{XT .zOb 7:CJ$[R ֎+8489S Aq2@Eէg>Fk ew/4U|͜ 5ۇ5?Җӟӆ\Ci=dou0cKqhO{V<ѢPʵP[ ќP˜P`31Љc̥g*h 3X(=u2aX6쥙29Qn߈)=A#zc $ tuC|,Kf8p *DH9Osp8B3,VCW iq3eYt¬Iր~loq#0uvoD6G Y°-" p &!Ao\׆:\S' L]&k0Y: k&˥?Qv`9y-:4?\väkGN^1?{X:IqXʌ#Rx闱jZ4CLN f)2P*YxtC-MPXU_B&+O, ]|?|& N 1\ DuLiA$S(c1VeͱhrcQ:vV"9[Th@u7KaM??*%y?ٿ9.8eg 5FdII)tlK!LD06K``WĜW~Fv-Ǫz?y;T0@ Д> h }δgЙYlg זּ/oEܥ)t'&bRY".<\Gq"0(bpp0s_6È . >FNAE0*0 :SѴ`]s@Z8" 3$::X6D5p# ć1%'qLAašЧôvz0#II( Fۅ,܀%?ϺYW ͺBCʝ [CR2^ cp 8 Q?dA>8zipi8vm!8:^a,ӘL +I}Cu8t Sy4^ℰgl~>]/n5-Wj'Si]\cp籧}ݤa>}Rm|1}3}Yؑgƞö[w)ݹ܏G>8OsY 7'-yvͩ*g\zpŪvo,~E޺w%2#sQR4%~Z[{ܾ 6}K9~f?_ESyq}^{k4Ipnr3]'3mo^6mj1"v滘zx@(JLu}AV$n^ؘ|!# t-p9U³on-V6R[{^38iLD4s?u6c=Hɱϧ'Cvsr>R^]l:5.ܶ[[O=.]>3tbU1>0(s:gFxkc>tYӖtmOׯ'ܸ6E&xxW%]m]hNϷ]lNkhO-XE3Bx2?w $9HLb?šD0sG̕_'+Xgv=SswgC̙.rq%A>hY(J+IK|\%[d7"PRAw2Ri$ōcce'! 6rb9N}a#qD*IT#ױ"H5/4|IJFe*nƈjaQ9$Na%\*RjF=;zVVVo阎.DxZBeQqj5jnM(/jCҘI+s^Xɷ3Bńc p4IψXb@5%cfi$]hwqXAf㸍23 3~OitP g̟yvqgi&u\ls*Saf'ʗDv<fV7ybċcΟLɀ6o{>d B7WotbLxrwMH-9w_]6.|yYʗϳl8>yz3O?~;rs/a0{il̯Ǐ亣mkY_eR /]z7Tk?߭n:eR29%eȿ\Ƿ91\}M&o8cmyO?|t3:ɤvj?Tۥzo<\9}/=Rh&'//}=%ew#oWGm/oq7>σ_=ns' 'Vggp[8~_7Zͳ#O߽yM7hᱫ?~n;NVf6w-O^+{-s&s-i#"oo_w3u\[q%zU8V;&o:G彉=UNN:Se9ꔐVS\'zrN:aNRtx>/|N(zDNs_zXd%n>$S"SoQOhD('O PJMJbx=YMq'mޓO;)B>T"TbL{R"uA{OR\>AS"SxeoޓޓhW HUՓ +m?uJSD',-eO;e)N?I*~iKqi'.E⧝pR>)X)%0E)NaS6T$1fvStzO"Sl>T(bSNgRO;):7IiN=IMIӚNlNOcv{OrSt{OzS77ŴvFy3>&|e|񋯫\Ըx>}?/Gv.ޱwZfzP(kZ5oaKcʦ> 6Ijt6n3yӾɃ;YD7bodv9ңa g]?3xd%Rq,i0О9K}EHnPJ˝r%mgm/ҙ卻rF0M>{ a3[P@_)m)q:I+!S)Kׂ% 0#,ɶCķ)F^$=0%xiA|te2mZ)H^:.ftG7&T"C4e-D4U5kܰaʙ{<ʟIb$Y5*@ "[{sC )oD)Xا'4*f[R åEQQ`!] S~ A&〩 yjv>^xHX3oX6yOw2{3>-2յ6+ 1WXdǟg!ڒ;#1 Ahl~չ{p6&!7/jPU7 <-TOƳ]XpD6=i&tXɃC+!2E8LYES*رq|l$4tefPQA ,b<4nnnlyh'RK|4ɬ/(a)$峗}1:xnem(^J_I;Jla# y$F4U6K2\YOf4B->\Kw0Ez#qjx<)Z9k~TW$V^z{{kXR.BO;Zpx84-ڛ#cM-vx醇h:-Plޛu)MzTădwOA%#!NJ  #IsN8if9iT*Lu&y0cw8P,I0-$O.b;M;:bHH\gp1ڝ<.ǐx&nBz0+Y@JJƂ*m:{Ȱ?@&؅pZ/7db`ord8zrevuU;d*,=b F&vPփgU5^V: (h{9:f؀~V~KrI3iP9ضZ+"!csrFlim ,I ־6YlYdNkkXyu=,֑/ AOP[Oin^eрoiWo<|} . }z}zk߆{ ÎeϟvQb7.W 'Nܷ_rGwҪ#x? AX4&OWӏ8ӧi0D|gf?>/>wg+Nx1X܏ݼR˿_NU>*_gSkX~8,=ȕe`QE_Ed1{EVFp'A%2!?d An6uiG 5kiHWރQ*MCȘeDѪ(=O" eFҴo/cYeۃHY AE RFj)n )+/نį7Mbiqd g!OEܴo/ͣyS3ޢ B ^"v/.uA?Bm(Zv9o3,7.}r-%|ŰHš5+yje-"D.hCg@61)Im#Z@nCgAת][ͫZve\11eGVD؈P)UEԡLRcGx۸l$!F߃#8es6,eɞjs%آT<Y6LJfx],,eywP:dKPr޼Mmkk<('E!¶Ft-tLЪ + &XTioUYhn"kb ~,Ce"P&#e%GcZt`i'n-=_C"j-yMsHZ A$E FL-$Ra&d! KPҎrkd]oXV9pQʰYAXZ@BmyLl- C{<qT㉛<%쬧=Tr-:\>sj!Iղ2l+q;H "Mղlf-@qrof2kfW_TqZR]\Y3u%HYv)7kBΛmbg-robg:կeisX\Zc)q[oBGM T)avɎ\S-R(!&7K-"Zbj4"Djajcٍyz%*mMWV1hvp'oG.E DD˲DtKFQ X7FEY"fa:fah=u;V \Z"Euv]ߧłe| :COx&(Y@BM9XYȂn!z|=+yHfview#O, GZ#T }r MlJ\U *vUK;Kl)ZnE@IwHbimDFѳpY7cEJ j`fcf "#Z.4nM D*Y 1 ʨFDQbEem"2ٖ B RVMAl!e2\oNFmI$6O*bgA" zӀ#eg@D!7I"QA Q6alj!zG+y!hi-tѰ4R-02IEk6Ra ֜)V_ ( "iѨvL $gKҶ-h-qroh+fjh[r +a1͒!zIYeoYcqR6K xH!v8,!v&wmݦ%B zVMBA6Es/>}r_.ogů+{ߍnYZ;'ɺ_<jZγ-Om4kϓ'۝ֳqGl ^|9V\,z憎ZuurYdz~xsgʺw1w%nؿcoWByA/CNw''ru`U"﷽R ,U<(qT{G"]8qwo ynmTjxGOBXo Pbwb۞ ~Ǽ݁ w~{ƍߧa֟~d֐*)ǽ< c;Dw>Yy2CD:,ӟnoWeoX6]؛ߛiɯY‚n&g><=іDזGYw:k"X!ڬAפ8٦5im=d+1>i֏I:[N",kcMgMxNGiuTդ8UHL|g?fǫeQM{vyOl˓ =4g/X1ArקIB))C "B@C#+iۡ (5mT~n  B&Leh2= OD&96"Cmx7ch#yFE0p96!+ʺx8Ĥ^+sd}g'o/n3"N;Sat7ni|r܇G`F"ܬߛGT9R"łgOD*]d N䙣#jiz%B){nٻ//Wi?KU7 xV+o׾E`L lV0޾ru2ynZMB;:I+Qۀ193⥣8xy+̈m˭7n[|b$,>~0g<^`h -tZ[a$Gu_BczQ n )O`F% lT50$dVnvb \Q88ZjEfnMXˋ?Bvuލ`LU@[I{R&6Z}+erTiоGkl4m@!QmW.w鎐Ziܼy:tӗWt!)ky3pRDv8 Q+FXJF KŞ!ٻxe #2@fp#҉I-Af"q3"*x!5j*yq3*X-/ca=.gbZY5@ZnβzMblfCb&$q(k FQXAI{s(ɤ>OmqV X_)}i &&A+*ɎY5EV.2m Tɼ׀K嵰Qb/dL%ՁUc={ HWQGTUgI-Y$Z`ql^wprb"+YⅥbO.?X!j_}i7/+J md5{\_%PӠCʹ.C y1U>`(+*jcq ]ʔatCe$fU9"ɘm 8K#Ԋ˹I{s2bY'GN׋76_-3e RLGy)M RӴ#!fJ8+$LWTLm̔_ߵ/1(_JiHt{o}{:3}yFEFB3RDD tljD0ryUI"H })KD!vJ3U*똢/] 幽'[8(7Cu!To]G9S?/ bԑ!B\D WU,ʴU`mRYaMnJU0&%DGghBD`A"N"'w"o/__ӻ矿|wto?}]^~k8~x~{yL˟~wblrHn7xo_['Opz~Tt4x=+npuk1~Z_y2|0,>?K/b >Oay6~o%+eWӛ92uގ<~ۯg/o/ɯ9?xrwxz4=Xsn4\L߲OWbXa|(}1f?ë?tO/^VˏUG~ܽa|1zOow_5oN@۞wiνoǏϋ</>}r_.o8xa|3] {Z]혲0n_z?q]b t{NMBV/2g7PEpy:yZ`S|Щk NG+{E֬N^mA_`ԱehqfNkk鈆Y5$RCbWE/fٶgYGB65Όd"diǙqƙh>Y3@#oMXohCV3I!W~Gm~a՛o&enҧ8ܨ? ϱ|=)Bhek&ݙt3?;Yc,=F[{ |QA" rÐ}LzFį+KDjF"~/zhnZ.ĤI?EX4к撜^Tr$cak#v4CB#J\9 җ?ԉ1Rl7XRFmxbU, 0a&oN.F_θOJ2+!WYl6^[ޓrb-ǫy3 vc@"ׯO{lB*SufaGOO]3߽vs+GU}WY i\8p֓tKeuua4S%\l_z-Ś"uLی4l@gҎeq Fhh B+D[܈1Wm&Â6WVn'ř!_VG M%(Z"L1%B^ x,l*2ؽK2)-BfȮ'7MdX-(;DQ i*RAILX em?RD[*"ɠ"nф\&*g¹_D5!Kd7MdX-2(:D" i2A*-XbC3f_AAwoOG5HEE"Fd;3, Oʴ4 1ܩ&Q{u:&'>LU[4V-V Dð2_hhQEZhFB Se+և腠I˒$H ALM!jv9u 2*3aDJTJ!cI>U۳2Q jqjkL!-U;45HDj+fjjcy|2iDժ2ReUo=U۠jaW IL-nH!-S;3Gbju\Ŕ l 0:ALT,QO:SxZ\oUXv 0D.DjvKqZ lfZf{00XΨiG˞rϬ2-(Z#+Wo.M$m08E3Ov I?XZ@ҟ{!= r!CXZ fzCh-,-u-]X1UQtb) ^uΆgg7 u­U`k)o-"%M3"h {zPmM49ey.z*WUG#%D "gHX"DZ {

ݝőPTrP+K2J@ZKXr5ӉEB66ESaxG-Fm-*@SYMBd)_V.'>KH%D* ~1p &j ڄkuZ BѵroblI5061c[+tmEd-:h+'U!hT]$k Ѵ Ѵ6AiFaZ A ܛf9옡eeh/åȲ(GuﳠijѴ@TRXTO%d& Q ([7QM@Tǔ-89C/Vh~UxRds<'NvWg@:^-)m! A 6\ ;"p-roG9CS wK;nXII]-i!KO'Jf 7 HpeU=h`Ht )%T-/8R3fškBM@9[vikHÕ{<[q8[ rPS׊WLjT"G=>qD6adÎ.`'+h+a|78+Jey)8u"v,T@%(9IݍqBܭ-ND--똻+w QmYA=|qPr*$rnu"> y3Rޖcb Th[hB16i[֑YB [7̓ M@LM m*A.ҳD-2"niji!VEܺn;nmbyS7zmkD{<m+SbvLdX[o(OD#DjAْݏ*4o֛Tmp\1B)1ukOΛ n-Qronxx_kC{u<3N -=^2@h;hmyS4ӊB VVMAlSk`e϶dG&{)Vg<ɶ>L/W&wm Y;R 'ֺbo-roboEYj`ocf+_xuin9*t?ZvFU特5 1<ɡr[_[[BML9g[7L DʽiDΎ9:{i:~2~Y \_'v6Y:y8xB 2,>NWԡi8 830zx>7ʼnk6U8y9BLsRq\b^氵J{M Ō-8P{[d e/ŗ7zxx6|.cզ$鑯nC^`6On{?5MǤ@g5wotEXcpD:'>OxLYu{{;`ݽ9p@fɮ~:.ԩA^{E^: TS:ij8u84D}4,$&lg>,ݥ_.ft8xONS + " J'Yƥ$/(wil.o;log0OWs S8lY}ο:,Ɵ'ߛiɯ̟;?ƮYz=TVԋܡ4džx|QSzSz'h7Vx I$ `ܬ.^bŰ`Ġ5Sbxbؚ3҆2N<<Cډ 拏2/4a+ESobTSOƳ^8K*\jY\{|yO6 G4W0bmjG:/>hSWڴouvxYx8و$e붅z(_7`*UѴ=$zP$`-ʈӯAQiי~j0KzRW44ۮ }lyJXHǽ"116**Ć2P 2Mx(ڹĤ2ѠX$Y+ U]\iݶA۷Yσ琐~R ¸a0ǓzHfEj1LJ]vqyd00'ӧ~zz3yCξz77o?}=x//~{Xg?dj|*xT.INL8vMx{yZ s/"qWp|&Vi{B[~ke8^B$ /¸셲tA(iԯ\ä{Jm cހN1LЅ4bT:W\ ;Rw/5 _+WNnpP %(~Ӓ80.d& ^SJl'vϢU-7sq5NƎZ.MHqS>B1 N8Ӏ#C&Uû ޼=@ OeoO3[u:T8AY tV‹MW̪-mw71 +yza>J02@ԟUae_50 (o÷#gz30f+X?6KUُ%46>0qm0wy:#`[pi@ N]~ ?jy іI::I"xd#c*0XR?8ŃpSrpP}.@2:‚.r  @bSr<F<=n;?,i 7%sv3827抦ngl5li ];9'sc0m4iWcvMm 8Id@0 Kʀ(+_xc"+)΅>qODF RfZe?cX[X;n]%wiYDaBȪ'=Ma:(Z4iIW rҭ T `ȧe*SAZ Da*85 j-!5:aHY6j]v167bv TDS-m2gicx2>@Y@0 #o a, OU@0{Qef qo^put} a Hn4ɔ v0YmV@9zC@wNg _X5Yߠgiи4 g]xCP cg@W܈@c@1l0`ڳT#|!{ xA12c pJ-k5P\ pƛ on(N{rC xW-pG3ר32lI7$Ʊ;PG"HÓj³<;(wlG8+(*7`B!+ hc v4nmeD:ᾫ y bѨG%Bhx0Lz eÄ9hH?p4\ |0 0k%G *5MWqls piT2N=lP F {cJ@?C>+Zj<'Q]SBMGC^h<Cë{pVa# Z=zɽ _6E 0Чr$Cc`>ib9!xDCF@/\gG0Q[s1?~PҶ!؊~hޠ#:u|:S#:M[rGt+nX qnuDCh ѥƎ"s掤l{vX$$3:œ4h7Gk,EtQÌEe,48~9Q"q$gȪ% zh0)0-1 !]8Ob a D"kZ~'!̳H=;,.Ŧ8w̢.1EagY 8{Ab`!Vpj N5"Wsg!H{{d3pуVneC!tt<ڃ \ciulJLftpr Zhx 3ŒՏhq T0=9Ӧ|qc@r0@.iS: gVpe2>9A2vvY iN+=a[U?z´q#枰RW\'Л1B37#A4w^U@ +FwI1` @bOL< 17gJ˜ (ɻwYg ޯw!CiX`0"-ȫ ǚs*! 0{xΎ!/mGx;(P {4zko" t _ N R!N](p[DCO5:|@f#atcl4?l0"صtTөW6\CH9r=DGKXp/T19~`O[ȻN}pXVQV,H/EW"ZI?.r%!{~(jwШ27u9*AT8xpW-A@H0Z  2xd0TxfT(cGΜBal}E.ꅯ |a`%.b)+Jo5yI\4G2CbA1` CfuNj7 ̗2QO?8 g:fIfCM⤝]Am4(&? +Cd蛆s;|?H}iBa,D@zgȍqHN0a. p0Dςk@Qbl'W^9ν8an3!#r#lhОI9V" ?:U˜L"ʇV?+M☘ "H7J!eZC4 O*eWA0^CABT0+aCFQ6g`ؕ ;cg F&b8(#3s_q%0$`\zNzx-ix],(@ 4N@a a9􈢍$"q4Wz؃3b2paK?Ѽ1pT 'jWCnPԤ҇17(ܳ1^׀FXW_4g(|H^NiM1i:&; lpQ;D ;}>GʍR+¬~0X0g PД4-Slm^w -/  ^64zUgr5&} J4_= ";>|>Y4 &DOzoAn(u| UvnTÕ᪗ W؂E pC>Fc etiYjVj5 66 ׂm<{zwT: U z -->z ye-BMWBb%T B [!TY\ d8X p2MBso['(\0ob/ZhS喫FL )W#]OvD& Af}/r4 U"5"r'"a1[ M]} ( d~( 55Eg-ÒGS<a" r훛Wr5f2I*1Y4ML0YSd^IpLDCQ>ۍ)ixa 0SKXp s 9YL?| 0$=tYzu%~S 2)EO34D1"kch)V" On!_߶l-ߡW"YK$ªP5qʗK!$Q!!qïX0"a”áKܫoFIi0Uq,܊l`u>Ma,ǢZEם 'NӒ(V\Ӓ< '6{UŰ l1a0G `SC01;.0ae㸂 sB\,ŋOT<8}9~ Ou791 8N%5 5̟,3/x , 蜂b _-[oi"noHd'&bPY".<\yq0/b0p0˴ X#&6/sBa<*@Ԃ1W͗SYi>/\|[yfȩ0`I|Sa~LaNwJ9{9M&O* X,:% =M5(F[|oy=TێpKH7M^^ZY{S/}3M,8t%_ #x"ʜ+WSQu>GTQu>G:Ez|TQu>G:U|TQu>F-U|TQu>G:U|TVBb$U|T!b]NTQu>|ܥx:|C:U3Qu>xT]0G:U|TQu>G:U[U|TQu>4:U|T7U|TQuVˢ'L|Y7h9l4wʅς{?H|:> ,RQT p=}z_/*n5X}՛F+)Oȟ۞iS:~ +Pn<&^5 mA>%sk/OΎ+kz%1Y*f|J{ثMׂ@RɛboZWW4[zhUVVAjz~E^L/PZ6^,tReojb`o[*\FKUMV5)QxWzVҧ]JKl(ZI@bvD+SH.g-rU>s-ɆcF{ra6rJr+LŰ`$X`+ D|E,Ƀ/FH ,ѾvFo?VH|1ג>.^kvlׯyEk$AuŠ7߭1l<]`=tHgauCLB5MuXύZ_0?3R~Ggq}F&zܝ!v?Oh>x<}2uaa(nnn\dFN7{MyޑXMnJ j ؚK6J&類W P8܊kݳ!ܔjp%R,铠Cr{JVuyt0fY2ݙ%R *H_}ClhZWCM t}W#aܔjqVL&iW=&:䀒R$qmI+vUv`31 IDۏN,z9GZFLL-MuL[][DƮ>}rtҷu6iѴ6!cle "m{S+y(HZWAlKWz2{o!BưZk1$:@"kc6ɚK ,l[$MQRbgM{ssZ#-/k%3}[k$Cp V3H{%o UGtKa>0_`F,q({9=@FU;L(('30.'q ] X6{r|ucvl4$CH!8PӖPXWKxXiAn)e1޴uVz;JXwU,{Њ*XDKa<-iBa\@0k8feo2:r 7d;@!n8P4M(9*1fOA!R1b^7̓eE#YvLL@HwX<ԁQgG H(Ͷ{DR(/еN`Z bKDZ3"KHcf^1/ {jKڧVZ|$uI ` qroZ=iYtCfel[|K*gyvAqԨ1(qhjpʖΎb -&!%غL/LjjFCuBq<0bْ5QN܆+GRbC@Y#-(,!VR xzWǒUaJznz['Gتjd鮫F:bk Z3. Djn, u"l}PlE k|m5x_EU (¶]q#eUn%Eg)]T'Bq@[`r!6U· 6 (r׹C {P5PNٚ}u_\h:ƧEƴ"nKojeU,Cl+(!8P% 9[F !h"lQZ Eskkcf֒we3܄X[ A/VclzqfmU(-a Ѷl:X| DV٨s_ d+ [Ik mcfs,N-2~'G٪Zf-qqPBlq [KrAldYA6"l;}PE [I4ֲMw\w$ `V3uXy7ZC,nQ񵍪Lr6LNpZ(Ba6ljBUF~h˲:j\y/qs_T+y JkY;5"p}NJ [Pz@5YUj՚ve ui4\M'ӚgQ[E -z#dZqO8(4q²$;FI0zÍX8ahBy,!V(+6 i7D)H(e ";R[r qZʚf5d2, ]T$m;zAhBTy,!*(l-gTi׊ gK7ݙAp# ePƤkA|ܛXia |Lw, &*rc~UgvXA|M8W>WQ]]J)Lvǐ:ceTd׹f4$JeAfB'2-y%>jʢ4*ڃc6Al.d2O26>9kd1(U/&&&nZ NETGxBq4#-G˂H+:˜x(e1w5TE99Ÿ%R5wPKg8DH;color-fader.inoTmO0_qS:aЩ" ؤ1K46RDN@}g_.Jks=q+.ձ*%ҕnG,Õ ""t0dlJgjiC{ `-pyr$>p.5r$y]%hZ AZŮ,\[iZJ*V ːDp%uIw\ KhRe޸A% [r]{]sTlʻZ3zQ,A6/%|Ue^|(p4|C3SZKU`t;~sLq8,;$XaLPLM:LiGIjrHǠ* !~HOŘj-R!ٌ+FxټǖL¬Gy2dZhs' \M'zM\|ϯ#|^\n2[ WR(hG~5xھ SP FQ"ד(>t0o?o7'7zjʊmx}7x=[;LKarZIadr<_MW2V'͞-tyU/d| yo|_v8~-c] nO8 r:tlz;yvmef2[|obx=zLڷzxev=ߓN{Gtb6jj~[9l_ghK/>o}Kloo.LYE+M{Vx5i\ڝPj???v~U li_ܨ|P~dq?Y/ ~HBxz1NL~ODRT[78\*YAc ~$,UB_?9N{XLkۓ7>L~N'@z^?evcq)!(y.'=eust9JU{w;Mi8%m9AIsFXYW5¨NH8Nkv!&iz>_U*ZQ5{#69ʠQcqjim1jc:1F51O6gb3JѶ[v8s\-&'9f3JLSUC587R{ʀS~`OC0wQ<#Rܗ#0)?ڱ3/#jT^\=q:G|zцusPVh6{G4\T{dLJ ޅ;.6qT b1~>Q鳜~]UmO/7P_⑏؎7am*Ԧ0=vO8fF{QMדjܫr2?|=^~GŎ~X\Ͼf|?}yշzw}YMJ?C+AH׫udzxy;׋Wzj6Yo}fVۯNbG{Ҧ+x &=<] AVy: Ƴ`׶\뇏`}7^擉+YNWKbN̹3o~e??,דdd6^ۻL~?X ƃa[J:]?$/ݗaFgշ؉wuA]@l[ru@쿛ZYV jg̵n=GN6jǒnhaIH3D) SpWv뛘+*(($ KwwX[ך0G9'̅ c+kzdQH:5 Ff& %S/)?9WO,`ȓ? "PK (B 0 Yy[!q_E;Hy"?G6P_sy6-PV$MzGI$I$MSH-i0M+HQ`̌ ' ݒnRicx®F]\\ DTiL,#ZCi-dHEdKw%d^aH\" 9&,ME>V֛]w(X392t̑uWIdKdr"84K /O h_-P 5e n=gS"% +`REI`}aY#(%KRdu:v%v/;&t]έՆǨG (!dLj 5qĭG-P 5e {2#U&::̞|̦b{BG^,%pX69?ʅ7ߞQRP2ɑC%ĭQQz3HȂR6g6{;BX:2XBvu=h|ALB҇Sd))Y3M. aBsdDz6ߞr2ɑ12qW U=4W-Ħb{GFKαlmG2d$l4}4O-#T()cvC0msYAJC\q/cɋef~VMJ K@nt.v <FLp4n)7*?+sl-#K#? pƤYYo@q9}~߂IYܝ}ƒH͚K|XI3ʲY _.HBLv舼,eXCpo2eB<˸Q^qi=Z&i>"-; $Ҳf`2eČ3i"1 8"1k<"1ˈ9V0-3\ZX1# ٮ8XX֛@LqAv&fB/D.фjtxtLg`~h&!JKxMHgǂEǚC2>vei| ױ>AِQ-*HVi;2+l!A cjo!ƃ$$e4_D/Hg Ig>mq3"Je$ Ņ#rcQB=>"RW)ES4Fd{8 h9{ݢ JMۑ7-SfM Xp)q<Nt>TbJQJM%FY8!1 ČZsdZoZ֨Iތ JX&ՒAc8pskEՉ t۩@_a$R׉5j270lo%Fq Z"wkK^6sc9.o; 5"m K:RZʯ֯y6&L"g$1+-_y:s(%0"ԲH[we{ē4Ml#<wDXlƣ/EP r7u#Hhy>Gky}%q '0,/֯UC 8ڙl;4GҘ$|_^c]eWL SD *%U+G,z窵ʕYvoꆎ8W)x>AkyXzPl* T¹BBFvQDnɻ$~6%ݪGfK7$,_H\O$LH98y 5^16vQ„nɻHb^mSKIx O K(eG(\7 (ۃG-rHZNs N.maVua6w\-ۘ(M9\T{F-Sg@\3PS֚^oC|Xap?բMJ H !48Y996Os/dd Fn`53iZYoj2Ae .Be*m}&XN#K S"KkN^,Kj\{_m.(2ܣjv"DDq5vUEdˋ \+WutkWY&D#ppYn cRm%uؚ(]LSt֔摭)5'/lk: $P$sL,b?^)i[\i&qǵ9?6FJ:\B km_ ^ZiORTqU|-`H|4ytM>CUjhꈙPú RD"ZcyZ+ }ˢiui̩3Pt+^b-adh ,+ +lW@Y"IA%fŲ4ʉIp\9d ɚ&Q\q3"Iy)@J(*5?RqCSYD ->9[3PR9©̚BfjSbf-d|9|-kgd$*!)TR$*JE#_kukA@Ekq-P%r>]"gkN^ZUd>nl !9#0$.'S'ĵ2IJɘhfY4!Vڛ3A(%/orާb1u Kg$/ !O_a=1߅Q_=}0SG q"85u[bWIm%vu C>{ꓱ'fK dP6$UOƒӰ-8{Mi6":^j[s.[&~DSC5;,}ɪ>,ZJ5Rcua.P'H)YE I:ܧF*8jX/`sN|^[Vm[erYNDe[wcɑ 1ؼ9`5%P C1}5iMǚ)龎z/qjˮVfk"aJXsvE\{hϸSsv9ƚ6 Ěk:˖XsNcEĚu{Ejb1Hlڎ5NĚ\}X 6oNk8جN{*YcH@f]<9xZ =]阫uUc۽˾O_&:;Fg, Rxl##+Dic6%Jv3_o(@[ ND nNk6@J4JK?܈5ExZ#Zddk(F0 Vj\b@qƶ`m@r6blƥg#74MD1Ǖ5Z9LR#ոyT_c&|0Ꚙkͯ)e7*s@h =?rF2'sǑQS'.謵MvVg`Vy822K2%tE٢RWfߏ"nNKCe;(vXܻ(-CwdLL}2{n(%~a>6("d磄l4(5`R⣄ &uG)(xGdːWzG _ǩ7W;XVm+meeYRqN伌$r&ea.I;`9#Hw392 #Hw`ճ/ѩ*μh{ʼ۸Y=bV xzEp m$= #L[yʼۨR=#8T\IHR=#4i|FFs2^M}$zfFhIvzvFhx 34yh)m-+i&~:{ckG^z<̾sOq6ɍU4~cDF]s5| rRe{x7o_~YM.|toK?\NFߏg7nt%aW_^O'#jG,Z(j0 ?n)S:aqv>wk @h9Y->.&x^~W謻= "nl4 (-7bȤL3q(K,WsOve_8]UatReଫsD9Y"diXDV^lvU^6r9tJ%uex7n,ծDOof׎(ۚyu~mI&񟂙iѺ+RQ+>))MAvEHYϜ 9Er0R`?DpwHl88w ?j 8Nݾ #twOs9@p~>={ T3Pb;@99+QIj4p-n.FMJQHi QM_#:xniikO"࿎ t}G z.3G>)#0 "/#RЈ])Vm)h2UDbjPeDdHh '%y;@I"8yD*t#9D6z72P[E )"7M9nz$Fy?xhѣ1:*E#tM杆9#mjӥ*1*DeQvNPELI%DR'T,4{v|<Y S9\C#T?4HdF:'NIk 4=CrDGgA_ 16"P}&`CAGa!ʘ h!16!F̻#PPCpɇdv/)6~]_ןKra`>WOGq%yoc~@ۜcOfMq %av-5VPь@9%D`1; W ],a´rݒ %K >,iآH҃ O*/# VNg)tE2nq25<^%Lp钴A`Ф1޸sIx]'#H\ 8WDN@ҖI:G'%I*ߓ|,Dopndo%9p%%;v1@Fh*Zjl}4![;'mp`eT5 ). aF3#M#ք 8y(wT|Ck'-J3J&'|t\XD4BuqF\T|c;2H0[LGXFۅHkG;g1$l3ꉨ)CXYj1R@VLfn~ y[4 *q[fX!IHgg;I"5> p@YGz75ElY@IjKibxR P=~0M6D΢}>"mv$[ټyU2ܪi8 4w 7Hj=B"-IcfsGAV3lEnݛ+f6E|lZf8%B*.wRD42Cb ^zBHb_Cv!3v!-2 zBe}^6CʨDu"AN#Cޑf Cm,E0tEfы!KNͲ#Z\v_6b"O!7p[O0w mx_ %K䪽L{o+/X>7V,ijFS [9瓸7j'`)@fit;3N l̆N/ʼn2 &aq-KqcKq ʋqQğiܾHP0ֆ)%8Q=@Ik4.=G*k{]IJ,v" 0(wm&i&зP%1%6[a}⌑;[FDݛ$ q;Ki~m2 lluWQJ2"<Ol;rە$RC94w4!S c8-3 FDwʹO–HŕZtQ8O8wFwʹOH{Daqg RH sӉa.PPH4JHZ("/l{mKo*5(/{!$Rڑ$2ԏ&qAeĐs8eq~)ITAoMy|$%<.pݍp91 w75Hics0DF+-IDD RR/yj"e ![&tY$hyq 㦼ne:ъnq~|[f32`><^] >g'*7 5<H'&ۻu~J8ILSc~u7~q >Mb+z:}|]?P}?~nt;ovp4;}󷃿zYwૻh3O_ㇻjdOE#{3]nl8u2,VG^ |00}\U/~{X,׃go? |H|ήp!0V՛?n3kt\7HJTO߲~dƏ_;ö́)79&k=+cϿQ0#+k&鵿C_NꟷyvUAI;d&O\'M쟫d2=dTSW#qfoسʕK&InPI'q?am딁@#݈@x@&`IJ P* e;0>O-hy(YXu#`gLvύv ɤ Ag)TU]nڸ|Eh@*J݈07(k}6nyJwqݒpva 9HdoN[sPOITj|J{ֆګ, *DyC#ϔĸZ,SSC4twN-ˇre`ˌɏ}kGDj?idMU[fkJ[N&JHT`n LxWFwoPeJ7ܴC\'"8N`6_M[ؙk@a~ uQOFusMq'oŤNv,wDS(ˏ-7d{6`tA8AѣFn<l{a[b t Df SJL,V0` 7Q(60ѩ CmFWi`틃1.thBCqSp;'jT\"̪'P00y ޑ0$ 7;׭QV`i[Kj%D[ c1Ds Pؼ0If\`5Ek:N1+М|43Y sg)88!7`gAGg ua'R!|!{ xDA14IФ3y( @ƹ$70HR9̀ab#mL 6!)b0ƆΏ21:AT10 FS?`ڣUpUoBO 1p4و1 QC? 62"p[u߼(T˂zܡ!Yt?PU3D&́qn7(nv2}@,a Y()FQJt]1F * Qd *4==lnȐEcjf_G~J >Q3dV RamDuI:XE}`uBG DaVa<9  0&~C4%m0, ]&eઠ)=2;Q#A{ ,`=S8 ,A!hUd{뭦ʼ5 <인!f8޶z3k 0𤔷nHLT!"F?w" Q #|(pB!H<! hkt9*Pw5n DTpx劢׆fc$z GJ0`7gcq 0.pc@^Fha,1n+vBŅpOz|rrrעO!FQ.wh G:Q,+hH|0`+ x<ݖ=YVCi-@,;υ@tA\ @VcϖJA#AX6=g?VqGCgf%$MћOC`C ?`K0# a]d d` @ Ffb%vW 0n gFГEd%!){EKE}wXi.[J>\VE0}țXRy=D# ɮ?kXA[&背:k.7Ef T "u({ƭHg̾"B'ć!""^7P'-݃H?().WNx MɤƝth X˜͏Q T AL̝.plH&e~\Й@%9u!=i>%9⁶Og ~:XSk%K#aǒ[Y,f?F”#0"a[]9q@~`Ģ36s EW$QMB@3E, @bo a v$')|NLAs[.}{YS׻tCt4r0=@= cF% y2aXS w@T!0z ڇhh8q;  eDT1FPeSAb@b@ >I>O]OQ4O_ =UCF @|وaf"ض[A3sj&0 7bŔ7~\|C $0p]C?aoNؑw d1-"]/H"Rm$|Pz{óQhk,L E`T F2ǕAO(2E&U=:E|sl{m sŸ/t,Uv^6PrBVV= + 0C1i,ex(O?"ޝI|KA ^⃄kX; `@"8X坦sK$0rw/ݰ{s+)1*P}2ǥm3}rP` @ADA`4{# aifZDVY΂݆*H1XwBW0*tqb|a@"ڎIg _Hxa5!WpKt{pz$ZC]Ki { q92x&"4q.qb^G34=s>%aĥ)tj9Y>,p*WyLO@<"ٜ#M~|'09}0H chܜ? (/P,~D +ChM9` tN``=wŷ|%}3!0dx"OA t@tH5rc^)0& 8V^$FE1hDh{aZ7 Ԉg^b} ɂhܰ`@#hCbG|#1O R )o;/}6ǿh!8ƒݼC 2>c QL8,% w.'frl,1A`PˢU=_00ob rHT\fLw#7{ 4m$ (YD!gFW*Ez;Sτ%tyn8]hl vF2DaVMi=]\^0ڨ$ *Et̆Q0q;r t4GdY|ш„$YZ8 #wGz Aߘš$H"CdAq{j|`2u~q`H0">."#{RF]fbN'Wڊ KT4e$tP8Ѭ1T 'jW6GW 5i vh԰`Ё@;;&r c۱a[ 7V K !X냦 )ΏMɁ"?*ɥa-kYp97\^V)hPh8ZmjzJ@/,ޞ 0$9eZq3ԊJ#0^h4BjK>R &a2"/A"H 誷NW(e&_>Af3[d Bd%xIx q$O ؂kOiz4l<:*e>QH ;͏MԱߑgۗȦ6*Q{DwErvU[b.wHQ2Ā\Yt%MAn`hÍy[^'@_<ΐ܌m^ߘF߃E$pf>{,ph1>"ނPPE:8.p㸪\qPJ[1Nt\].1m;VPFqjZBWYat}{G笣QZ[Tl)vi/k: Tb2Z~Y*lPyA<88\ p2MBSV&nCt@n$l)SFL> 7#COX~&If,s}K1^0őe6@s'Oefốb*\]b ( d@S.k ǎFa7<لaFd p+"% eYK0}s$fP6؛k:qbɢkb >ɚ&KddF:`e wEj7 '\Fc%N.}9D.,n-Q-qqpq6SҊo˶O~FUtZvd*d[Yޝ#xEa;Ƴ->HN_.@OK`opv7H{ x6!+tNGhlӠuQBHFi YpaE<!/&"/0 3^aT/4]-.S0P PK8D%hLenpnPowerTransistor.fzPK8D!¤)LnpnPowerTransistor.inoPKMfritzing-app-0.9.2b/sketches/core/obsolete/000077500000000000000000000000001250202676700206625ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/obsolete/AutomaticLightingSystem.fzz000066400000000000000000000256711250202676700262510ustar00rootroot00000000000000PKo5D4#+AutomaticLightingSystem.fzY㸑S(ʱp{{ ;WLꖧT!g/@R*"<,Ɔ J/|vF!7j@O~o+ߛէx+d>>O7Wy\ۛzngçmpw:nj/&^_~?}s%Q &&?7?m?~UW?wvo~߳{qu5ֶ ۧf_%zK|=v?''@NFeOq{o~xyY}MW}?wjo)tPw>mo||Vkqu?%1|7to]?.E}}!WWaa&w8 !`HWkmͿvOowawكv7~B_^L9y~<٤*+/e]=\[_WNc{/+e5HjE![*{!1 69TȾgI $ݚR͏^v?g'kfWCKߔns[ҝ{BD,yb>ŷJ +&x9huW0n8:ky:}T}|U lTflݾWK M"8_h [ۺƾuֿs$+ n'Ʋq+\l{[/m {enFm?ZGvB7.v;-ʽ; f [h8[sm߆c~o3ݿ] [/m(f04pmF|簩Zk sew07/;pkACHBMcŻmT%@8!My{~  bR5!ոpvR/bJDl+.%Z/$^H&H/$Z/% đz!) .R@jENFˆn[12Caj1rC<GdÎ YH|;/۝lK}ȧxs?"j>ͣW=3כBR=Ljp! I -ĥ$| IpFho( Ip@̭ԏFHz))಩[pL0|텤c> d27ۧL0$4|*Ȕa/$ĸ/CG₥^I WNXꕣ'OoO}q~LJm|<_Mg5Ǎ~#1lwS7w:*isCB憪HrB/y?~G/FI6 Kaꟸ7帿>naqOYyD)꿫v{~n66<ɠg|(BUKNZDnIj$BQ5R$!(y47Ԍ0𗃺=-حB_8`nmqhq"S!+LrRBDBx8őDNH̉(9xFQs o*IK<\!})cfV4[Z$ca%'cb( D 3% E! Z&+4ˣ᠅Yoo '| $"!ɧ Q$l;eH'9Fܼ9칲КY`Y'?efMWp\EJw0(в8z4 m֏'?%`1=ZS. OT3 O~`Kwuc$L:G j!ջ8.S#Iw7k B-[睧_&Qgએx*Mewt~K.]vW}=_YMr AG* FY,𰠇QzG&ԣTzS8)qq~Wz26XQ w؍5Č%bÚ!NCqDa)DE4qf@LХJ vU@L{v*ϚơK7Ț݈8 5q"(rY$P("Svf^Ri 8C#a.ꁳ%3PzGTUO ׾ )bxOyQ QHHw$΃aR S;*Sr!}_&%RSޮeyS1w~J%Po&[u2,ն(EEI RDYpw()}:GB7BG$_H#~IWO٫3 4./N,pآC:2o6ul*(]./  o?J)ywyGRU k*9V8A$-i En(D 4 &"wl |I9'$sNp9[B t[$q?}ۯ7Tr|`%)q{<&`B27mY M#jSmcec! bHZr~ùlfW#NM_ oY)uo(BdE8Me!vNlȓU8JչZ֤." )w"s%$HrVuB !Trޏ_=}~tAh?` E43b5|#VF;7f]&2t }oqt>~#2v^zizk)|\/SOw>_1֛us땯fքsd>Xo2#4`1F"^ܯH~yU#bb^eΧ=K#5EGbLoY2kq0uCba,Otl?aJ1cTy,3D?H_7qpP Iql΃OHwݟ$rp|+[=4fjFX%2"Q`H~D=+0M_Mr^Eh~+{@~ HD`.7ܫW4t'YF ȧ}@O@NWh]on> p= O9<̳f>@ Āl zdM'J,?"uf^"0W}_k[×:ְbr`cF%f򚀼Wu@^R"]% yQs~@~u9"sμv5~C^C .3"ϗWifX9㤦 7ef,+͘M ^jo+8{3w`;hqLp ]K/N- ET"_$D)pDXE$Av4 /Z5pok}`r@1" P 0A Nys`d `%g^|0g )_Z4bGx󠽳$ѧQbzN"ݰX';=)Q&T8t ↭]ՐSQɓ1乎BE=yxNCLu* QZ EF=ur$Xb7oRs^si[[\Tye'ֵ${qKqg UҐS\٘9tCūT|Vd@CL{.00诲Jy d4GbSČCmbݮ+ b9uO, H;&0riIA&a< 5`a4-V V@hm@"2&[4`‚"b%4SHvy!2'2PfDy^-.J$ar1A`_oJ9p1\=TV,Xr5Ob` &ʵp6` (uC,@WC\vl]&!d"HYy*g'jdYJ BB/S ǠÖؚ`Y·d0MT͑Xop}o{jMbPqk1Ilw0HI-yraˤG[ȑ KIF4Dy&%*'}NyմAtO~ah>iq6 .)6M>}!\?PX J74Fsz"CK3^@ϯ##RDH E/c8 5#q6g쒵;(:+tӐ zc T?ܱtk lM%KY?;Z8~tdE>C0QLwUzC?l|?){uqs绛?펻zx흺ݰר2IL-oAAJiCsE#4KŬMz `͇7`@!qجQa=c3F^P=ctglHI) ʼf0{DJkeTYꑤHh$?S+4EFY}a(7324'~w{:u5Vju9?cV?mۛYJApj_|:eQ zoE!In𬾢?_V? I& .922`lv~ͼ5CC/p o0F8A8 ёqGOtXd Y~tNprfk\#.rQq\"Dh.s,Bfe.R3Q1 ,sM>6w|+dSo5GU4:x' R6IP")BC|D D}UN,/Gf⽞ZǮ>ǯ_GU %:uzcw4amB!YԶ DL"IZ$ n8ZoMř4e&-vsrh߀0g=ZIdN?ӎ?~^P@ o"+3~//@]FK?a>#$e(rэr$UW}nGCvh>;اpe^VSr%uM&YnNXG4 (?N]!"ጄ8nh8iMi-0hmLEpLBEU%i ^2@聭4> 7jq"ٰ{i!1"oei XfȢ[Je"TFA$Y{ - Zg,Z#b/b/Jd H W(L\YPtx}׾[X󧍚ix={ T MGHz\kQXZ@ވPw6^$#cY0.00( J9FHp4b["Gh}*hơ^٫JJj6ԊS*, HMo6<A4Q% 8hcjK6 GBL`ZzqF믉LC~Kn&`mZY=2a&Pq-H<{heX''Dz}*˵{:3 LqڭX`-v>ov?]߷]>ۇ[E5-~A2+JőKYsP4@9AUnu7nlO7)1`炠NkRY=,5t&`n+^3:=צk}窽z{ 6K E[;$M[BW讚d(dY-% [}M_?؄b+4 S_./N0sD 믍2T<A@VCP: GZvSPN/S:b oԮ,a~ٙ/)ױwIk_ʛISѡG"WʻYJJXL0y뒧1Đ:ք9Xa8ԪdM3~ <膴H*B gps,1r]?hjP HdVT F(FbJ@(%f)IU R "taGDbx@_`>N8Ժiᐊƹ YB)AARU"D$ISO`C-+Cw,]swՑYlDX:$LCC:aj|dVNIiJ(D0(Ld1ixʤOiSN'zYm6UPVD9>_CYwܚ͠lfKCih(KdPcD qT XJo=KmY{gLa!%yÌay%A,jW arfPqҭ @,kKijiPpx xcbԊK 8CIQ>BftHfb2Ӳ̃Ϯ[{dz\f(ҲrʡpSH4` eCX:"LC`4ḵkȘx6r #BsjQZT;gyd}~b:>;w=KAvYIΪPqw` ڇjK7iji=]q1,̀- p1ZEw_Gy-aVb2O`Y @R;+I NRR":v[@2D)T "yKc0+Ѻd46UZh#)>9z5w,ݚàHb=BXzLC@0ᒵ; F.8?FedJ/7zw|1cCT@!;0 Ѕ0πֻ'5Pʀ2 7"foC)M;s2Q.Xk%鹐׽υx,ڻ XXHl]arx3 V9fh81"3"`2Wä*H|2_sֻë'0P_#PBT[fDY`Y)%GT&%"Y:"\f | 2(2&,Bgg]2..O:tfjT]v,r\&㋌FJW0h͜Zp)%X=axD3 c*!.Y 11memsKG\PD?dG3l(J~֯(n1Wf:rn(Ts?1_h zc4F9Nt:<@`0e%k'001%qT`Ңˠ M; 8t(@+&0 9Xl]GêZsL q9 ~La}\azx3 `ʆKa@cLcrXapA5Nvdq$fSq5M4zaTzޠ5I fETqҀd*ntC *%@>T(cy30k_4I(I*D ܫZO*ԧ+_4;ᰑlLMcawx2 m?kwqCׁ.‘/3*ui KvOΝxZh7&} 4.R |#3h1B⎥L;f/pfj9T>\v $!#~`YEwKc֯.Olf.gL g0ֺd.& ЬE%3 cʀceݤCX#LC4⒵1#cEC ]+1Ho# g<{g` [Ϧ:g-$e`=Uf2⎥[3d-BXzLC1ᒵ;F.{  Vu6_-+ch<3bc2 }$*xV=πj;ng@tDՏN!,OjTC\vR###Aj$ /ZQ9:{8t:dh~֯ΦZ{@Y䳒ޔ;+YPk:%X5Aё髀A4t".YAю1lBX"R x{:w=#YɌC(3@咵 YyJ$Q$FaMa@K0 Z8f:@9|ᒵpƮ(L(b{w)kbơlMgzYl$z,_M]kdC`;nD@&!,=el%] eP0*!IӷB!Wz։g <]LfD(*f|j/dM^ "CX5Œ D2 ejQ\,@$cDb#0 ؒNʧf%SI kzຘ8;`UmaV]H_Exږaю%lL]BXLCS;4CÑ1K ^0AW R8$z' y2&ԘrȀl/hēB2B%*v/咑[B^G/P^PT1n_#`t|&\t0Hrc p}B1_~vy3Z[;ӮGH{VZѬzq0⎥sRC4dz6 axJ3 ?T>\vN@j`jЛMdPKo5D4#+AutomaticLightingSystem.fzPKH[+fritzing-app-0.9.2b/sketches/core/obsolete/Blink-SMD.fzz000066400000000000000000000077541250202676700231120ustar00rootroot00000000000000PKo5DS5z Blink-SMD.fz][s8~_a:UAH3dzRtwәe pdkJ1`cv c?$Iх3t(vb;6uZ0T `yݞp`6uvZVxCs9^~i?ր6V@N˳:n't`Evt| YFKۭ\9>nYn5~svSSPUY@b 6/^DR@Co% Pj{\& /0&*#G)O':.WۏOWg@%Loϓ"I"E~CF ztsq& )N>&?kYab\?Q7j Hc0zfU-z,a8 vDзڴOf4HyZ^Mt>bs;ާΝ G'IhhІG{ 45\/X"#Y+ٮy~O'E`Cԃ 5~"-k?6t.{z[&q邨ogO t끑ܢ̜^/Z>\],CpC+b2i: Kh~zZ$inKԕnؖ#}i {-73L~F6k4`^ v',Xٕ]0'iefM76jiL%h:}gE & \ SXMId&ǵ4yaEC RBm;''b,j{OĚg{#:LQ 5&REsNB.1jG #չ6pQԋBE XPMB!؜kPC(k` CMէ0ldܼ(2kusa,\LVAdZZ5B<6~biaC LK)i_HV: *u7lgG~6C3I 5X9hkz.Q_C)2A܊h#êN#BR;dX;¨K$2DѧO% %Y`BԚ`Gɬ%s2K }2K#Y,UzZ"Z-csYUA-bQQ2|5 G !)Р㪫;BF\~N*;KCE8 "szFFⱎ1P4/?Em`X{2v֦m9p%Ī(XХ VEM&Hڅ[~Eb[v6KR %`'d4 ugXz0N}k}4E3jc "Y|N7>D)>/O!V7v)(;f pt} 52*>nѬh[|QnI#s(Qv!D|. ES] -C츢NdpHM_Ǣԝ7>ad̢l~M .R)kZQ>?0%kU&76)>a,=*4Ϫ֠S"ƁN-t_Y EeaϜjV7% 7*AP;[T;W*dr 1U]f~}`8WKN1-H.g k ,ui`gKz~cR^ѐxt1^?gB:$[rYu{BipТzSFVaP7VOdIV}yvߟU!Wz{BՖ淃~Y3.9׻:Nӻ\'Ikk:teE} sjEP$ǬU+-(y4K&[ؗW:pT ok]a *NP1Yƭ 5^ۯQq}6חbSL0{k5H g%EwW=>\Q;WaG̢u+L1X2[^5N֫~b9S`j4rXanfk痫1ÞlG[* jE])* ׳?]tuyDIC>s3Kŗ#pԏ"!Id=s`}JLP,vTf<6?5CY; }SaASi ~i쳗IG: v[$lm4FAY^c&9N4V'iJ$TVˡbj?ovRiu cdܼ=`cLVL%KƲе)E̩dVc MSqEf)bAx"F9:4U"NXψucqLdfqNp19D<9a+ 4qMn;)D "KT.I%)4c[7Vr-+[c3=wYCp8;3 6jȂ]^^sܫNԙeY&tbd|y6=srτ{5Ϛ r!/I|'v2e*dItPKo5D; Blink-SMD.inoN0<ōiU5QvHٍrYwG ^}ypѼ^x !Zr)!#:eσSV>-3=O[!DᨱI@yeaa b1( _jH| 4X iv˔u.=~Ԩ%cg=wNh$7\ȰͫzgIKH_nIn7 dY׮(yNn\vWK{WeB۠HC?8mz=[RD^Ktvۤ6%& ӘivlDng3%.?xj|}/g[K:=#v8= D˝ve:k/nKP.lGu67.e>Qr=$ݒ ?x]vbsQt(ۋO4v!_*B<_>Q.dļ(TΔwRzKn[SJ<Aqka8,S+t&pp{_XWA7Kƃ54q$l4uuiܳ ?Zer}XK`EJLDݒO[n!bZFKz"]UU@u,$M8LwTUP}Ec[J凬_.K}׋xj\޸T=,$UifNݠ{(; XkaFK,o Wj 46-oP7 Zمv z7TgEz82 |gbg~Ҡn:rEXwid]^CĠV2 ৉#| O뱟&%$ /Ha&JAAڈt?=Nl;4^(+1evq=ߋ(0%bwQfCFLC4;z!cA$1C@M zӊ !)V p`Ov#9w! ʻ̴|ש Ru#NIv nk7q@v+wϚ[ys>Y Nͥ7 0EjVi]yIV*a;59e}l]t,w؈dQ(=vH&6 7nJQAhI M),McfA"W"M5TY };T_ZxH 8ǽVwGq/6߁vUCQ/@cokC282fLk,ɗPCe.^/z^SԵ%4m 8d:R͉+f:B@Z> IܡowWh35~K!NyZUAB/~|`_KuQSiMH;ŷl&/AIVA0_ hʻ6*vAѣ9fb0kXC2802헹-dm&v>%vʶlKp e6MVTk_ӀZbTpaAOt:xЁhnKŎ[ZT;zlofXV,KPhEݱx,C47[e 3LE>T"Hr|>f>!&6ڢ"/a9ѭWBliQc+jHOƠfm=S@ EkX^]LhE]R.aAd"l9@4mdb][BnЁV+ʣ:> (627+D؆(~Mb&c@Ķ'K`g ƁV:XөQG9l./"ip%֭ۍ-N`Dj@|yӚ֗ΘMF~ aI]MlzV_JM_ґ(鹢\\]H_/%A_*-en'T@PPH Fݣx{Gk#@y$N fsP0p7Ypf%]?}Tm[ 7f\SV4-N,U$[:X?[R?z*<=dr8SJܾ}Ir";vƼEXI>wSEZ>cl[{!.߲U cنno U\JSx&Fp1&u"x1ω@֭cBID2'UrUD9yuFXC@_}o\[D0_2x:!pe޲J#]4;v0K377譡FxS.d|v6ggg[wYwuB,y\RM &_ĪQ&c=2+nT\K-d]ZQ踦Z2zn2SMoWhbܙ`mieM4Y4oM{|OAUQ\ T͐MT2}+4S+{8覙J8:2S#cLQ)HRo,]wM`SiY ׮ճA*HxHlQR5\ ผ5en ?Q9I,N߹M-<2ѲWN@o"?Z#|3J)+ڻ8!n~Bivy.;{ 'qɩQ{3tN"ɉӭ6PKo5D; Blink.inoN0<ōiU5QvHٍrYwG ^}ypѼ^x !Zr)!#:eσSV>-3=O[!DᨱI@yeaa b1( _jH| 4X iv˔u.=~Ԩ%cg=wNh$7\ȰͫzgIm>is7M01bo=FLd2}ǑdCL-yUiѷ7c!t"mq#ǙKpw&SKL4٦miP&ҙ¨XA(%}vPq P@i`,Z'0e,]z$11,; +0 zONT@QÊ.A @s+eXcXCy^i1඙ #Y*N0#ʌ;U0ǎ H: +1]t,`1NJq*dɞtI$Pbs!$[,ST5C9T@߂I׳Ip|g^nCYQ*jp@ -_e#*PcALLᗓ᪣XwŇ{hb@Ŋw%U_Fo[ұL}G V8l6-F {>U<=bFm\2@p-FxP4 n0U%֎)CEEwD+dcT`rjkjee 4 &pNUGwt*iax9+ ;*/(}1>> QʂD}l&%Uʠ ǸS*L܉doӉS@OԥJc (@#( uS`N@!B%Yw@ȓnS{<ʒ'W4&OF={_>ڿ>{۫o^0] =7`Z&__ݜ[F{ޓoۏN6B)|3q;~*דSs\/Mӵmh޷h+ FnWg|0yN-`ϹЖ+.k3Mno݊oU]<}A0usz>sa!/ȃ3L 񦉼ۅX ӄ:&3-x-έ8{7L:W}IEF8޸75n9wiCmy܋\M_;cM3Cm<̼\{OⰫ}}-[m.=qi7jӕ]hฃE W~/E??bWA B?h5`)(h6 o蛜iɷ4V *Sj׃4)tJ/ rvX<<)sff{i udPsl"j$75!c9E[Hyg':N֣0I`hHPD1qҞldq*(P*VPk:Vc3(ȸD4f*::؍NdP0zEGZg|Fd'86uH ,{#:U- s *%kqИi#S')6J8"N,#2u*Nxp݂U'.ZrypA޶FdYU˹w­BLVDtf0A%J}kԪZSJ݇ZI;>3Xi3={^#cX`ιFL6I$DU#WM!u?>ܳbV{.@4FNWpUMJ) h|f*ezz?˨p8>闧ƮML JƎtDqcJ3;A;bBr7𧒰˳+ڐ!paTM*tYZ&@*ͲTv Npm*)v ]UAX׋r85MJ*HTM? !;G|ЏUu7ͨ McT9MeT0aBAwEMAWF~_L ~aGQ׌OR31ݐokg=vNu׋ >s'/1b~ ٤CFC Y!|ʌ SR0@fؘ8Q!F]ѴW~%+ l&m/AWbz0gQ E|{+|mśPJW%aEQ_is<SQ#K)G J>Pnbuݑ@K#6.(;JÿLgH_j-gj`3b<fߝ˞daq䧧}g72GwBϊ_?۵I"Dˇ"?2hsO#H$6M7̝]{w7*GD 4jq m/ĹdN pƇ\ގsDg*PQ 4b79&ᬥN.=ÙmpdRĭs6=L຾FQ.=E7\| 2z⁏$j{ :>麫f٫)Tۑ0w]glϿ|~ϲ aޯf1o6$ A9{GNBFN%KtWDu%Bd0%~3*{{[!Y7꫱G\a~enCyTY%WXŕJ2( gڙQ|*|=!N@"11UjGk@6W_@<p씍J:jV~%d\ꭁSd\ҍVSBe&r ױ'O ͫN/0ۜ2_(5]4GCսn[fjU乖4(OMyrVƜ 'a-pPY"sD}m]xw̹ލ&g wbܘnhwF*gla=mrl;粷9=p~mQ_-J $4Qxi0ĵYxrjk;N82z`?&i"e ی(Ή ? <6`!ce͝I KqlT'O]ki0WWI62x`17U1;G tN11*f:L<bܢ,k=x^F )ߟU~ゑ9 ˦;}|ZA8sivUxՀNuzb yb01b]1:AtDG61 ;a:sŴNFG&"e#*JL֧ΩdAI7v3ЩLk%@b'r17 *]rZ9k)m̵֎IXtISd ->NN! K[}P\2B1$uF7a鴿Μ?ܨ^ug?ףex 35/~&!~ݻIp<|wg}%uݒ< Öl_-AH ,Be #â4V8;*!'x,. RYޭj\Bn %U5AXVj|4Z-x5s%/9f #PPGTXM"(k-q )Tv$)`Т6n4K%2Dgn#!D  :#T98ĸ꼪] [.>pVM&>̯ѪJe [^L0mZ%*˻F}K(q8z(V ǸU\uqo<ΪJ>VU0cUMM'tYf#1l-mz| `˳*(Qku\06cH)?D#Vתh0 LUp|H\}[Seǂt2qN2M;M6=]gCBE}J ȡ, #lRj$ܷ2YHeHRTt  ;$ 4{ 3mGr*V$SeEQ\u+ Wa!۷.mq`dU;"R#U5,0=.l%0I* §Q9 (~PM(6\H_<-?MDBLtA`<*;cR)~P/@SI僧Jt;C&%ZضeE@JJoz#ԑq)(t?0qܦB%9q)s7jbxs7%Ts~&ۗ0{Өj86M ?nv/:ԋ_oZOpD?{n}qV½|J~9h1˧mz'~.//Wkme۫owv5\>|I# ~=zb0xxx@ -VOr:@6 Aco4љC ]_>~=߿(+k|@[˯)q_'<Y}q7?޽O,;m. /Q_2x{Ij[ZoNf8sZܻ㰵++"jRmb[`aزTS|Y4v6߈2,pyswc3"Tt/7F}!)~=6xX)Glh Sٶ*^,c.N_#++lzF2 Yl0ߵw g#Fi_ގ~ȲͩȚ'b#/K$AQB_:dO?|#$Tbٽ9PχkOޑE/e8DQ)6@ĩ67~h?: ~(鬮]Qk#rϦ,if5d@&6F_3*W-6=zCS>38+O-T[-BdV֬trۗ+]ە;C.mSAл1\hJwn#Ldd^ĩu8UnӮ{)?my5n1@X#%JSWpg dQn7e`:7†Pߢh=Y r&{9 Nj|?s7z/_{xwY_ٗѷPKo5D&KUButton-SMD.ino}O0W-K: 4h+M,&فk>$GFk@lUV ZjDmj(-l 5FJ@KktpFz %t5 $,D 1hS\v9YX֓M.:>i ȑvhJ#WEs KNkc`zځl{%{+XBz +{I veG0wv&W >6]:'AK]ifpkMA7'U1:eR%/Z]@iR`bS%E*=Ee>T4m;C(ij( _eS6~PE #kzyXLGoV"mZUF5eox'd?+Ic-ZEb'R }AE'͇y }7_h8v;'}'f>z@f/7H8m%Y/]V/#noE(~~T VinoV *=;zƝhIxE?E w2~>5nP?u*loSU[b0B<PKo5D}٢eS). Button-SMD.fzPKo5D&KU~Button-SMD.inoPKw. fritzing-app-0.9.2b/sketches/core/obsolete/Chaserlights.fzz000066400000000000000000000423071250202676700240430ustar00rootroot00000000000000PKo5D'zGDChaserlights.fzm۸vdr"x'vNy~w7ˇ; kp )^jy|ޭnU~LW}evk]i ?V׿_?,A߯n~zZnOut˗M5kZdC˶{.tPDKayBZrNHJz1E|)bf&o^}9߮o><.vś7oY<߾[ܬ7Ұݗ竗&UN~XZo3jgןl[~'/׏L 91_|ChG@x"&ՐYI;luZ'Հ :-jt'kh\2(XO: ,/Nc cY{L=E|T.#wgJE8ޙ&0 S3 &Оn([ etu4‚ִ7̖a9Iuuv(GZO (CrVKBYTw%^wPVx>dѪ KVw`֋xR@cSa(] 1'SG.2_֦hx2v[eUm&^4z&^4 |Yjuq8kqej=_֟θBi^t֝N0K!}ρ 9( vٗ=03@m0k}DR܆Rk%4~ KK3H}g?8Yቭ^g(=Ygj Jӱ:C( } 2Os8wa8!'N̂OVtLzJS4>32d 8{YLTOAoϾC:AU:A/QkD:HE\sϗu;CsPڳoa.sթqIGw`Jh(aejJ!_VV8U~wpw_fjnUjG^Wvwt̼wx;ay' -U׻^lrx춺g]}y. Oԑ'w;6bxVmdh(ֹvtrgJ,Ҥ#q$E)h((ֹ^L eQ4c(4N}+XnW[]"Zzr]{v}q͛76ݗ/ϷR?C7k-ٻϳa1u}~/q,w]Ki*^Ѧu,|^_dnIz-oRE1b*ݤ$blxi{<qo(#!yQb^GBP!H,j@ ^=Α䪔=`Nbm^-jj_]vD>7E}naI3V9?.jt?jr,n]3ܭ:u EM s,bdbb#VbP&̫ #~0Rߑw&$#n-?L­wf(J#B$DrňCL(2Sl]m짥}1}r@WG찈&;;uXHgrh>%q 4bZXl8)u}WIz я%DG8$B Iu@(>! .]eDz&??{noԵG^ha;,"UM+j[(6sxs>7|L:?۾nr4pyay;?g} dy}Hm7zYOŇsKtH":|? +Xۖ@r ta$NZY̡v3ֺYPc\~}㎂<'F Κ@UFiTY+x$շ;Zko7ֹP|uGq)Iyhaƃ|ꢧB jlӥ-y}-wǜWLfi2.w0 M9Rf"Y/&4[݇IF[6ǠUa2+np]nxu+r,xVmc$Hn*@qt SHNwZgQBVMq'iu{z' t ntnMU6Ktq=oHޡ[͎;8EO+MX*y0vH0}MR̘>GQ64l=c(Lj~n xx9(L:[p;Ґق 8t̯,!άʯޒ z1 e{ mW<1ӛR]F.MoXʞ3L~]L(AC0]]TH K7쀎7d.ϱV| v097YMt+8\a4)ʙD~l1R2{ &$B׼:|7naW7]RNH7B9ʁͭQZ.nQo8s `8W=];9\l%)9Ҩܥs|_gJ88d`@g#ʎ dhγ(qT3lvƳT(Zr1k_Yn@vRƼ֝ݒ>b6 >Q ˗2qx,h:mh?Xzmxeuz"O@1GTмQn&nRu&%T\@3uE^7,.^pp@d$l^7 ^w'j)^#-(uOwn{45Ozv7evwSe`v?i:mX򐭰fn6d:!N ddv1}c 'Ќn=;@h(Ǜ#*[:ҁMGT9y*8ǒ#n8#up-7 M.vv,i}pݝ@W÷M`wc,OI=״95m{v a߳[!s ֦tyXiIhFpBECYf`uYVD8T`=npw]U_@ݒA Z݇m;ʬ6Kڧnuu Vwa&)GV>juY=-I9N31 'QB>wZhg*PPVrVâ1676uE˜6D"ү!k]o֬RJ<5짴'DNjMιuSlzz#)xQ+s}҃ݵm97G[f~;q!:kcL֣IO9:O*q,B- |nͫK-MND¬iX | S;_Ѿ2ε4E=jB R5?9)A kNZ9d|',mG m"XP(5@,47'#%c(˃{ɞHj , J*Lv/<*dXikqR f(rYIg U-E(닖S~$_zU ߁%WdȒ@JFlH]|U|ux'xhXN0xT KkQ_c. ,y%˞׬%KIJȒ1;Y2ɒ Y@ âSBE@+hId%5lPTJ?`( hrmhĜBE2e簲:Z+ U ?eXnC֢]&͔eJa0+)HQڧJH;zDփ'mL<Z#h*७1`%b}{$u< 1J,7C#YCL U _BX8%,(uQ 3fNwnx8aE'"Un3k(OCXSJaL'9 'ZHI8j=^ e-:"oE ')~>|:v+K4)0%̀a!IF"X;I 92[c(>F:0%0X!Q@11g;J(mpZ}v0JYH$XJ7ZN4P5ğ`5AbD0 Ca֢s4PUï(QL 4L fhL]vt\ 4` e-!'CT(5p0KګI_5e)6ETIpy`/f)G,gs$6XE1(CS v) Qq0N#qHDb֢3@г0a4UERk}o@0KѶ Oh` |/`m~En ^r`a/ޘp#%9dfaR .k./N)f_II] e):SEጆ/A*2~!ond؆hLR3qɩ/5V1 uO2&#a֢]^0Uг0Dal WX(!U<0݀J x!~VC fe01r#\GCuRgq )~K~]:0 _ND%Eևm'ӉpFMBE 28a +-> T7r\pLF|X$2 L[qv&bيvHALfƯWUxÝ" F6 r-RX{&@hP+`tc ROs0R.VUJ dSH0սa.*zkͫK8k Qϫ'phuнdnϦǽ02@ʂ0rD(+o1TD9~ӈVkm <] .{mT(Z/Gek]NW@ZfV Ș4#B"EaQT(=#H3,m GfzhA`zmS J_ΦR'uL'9q`Ȭ 2F~\gwi$ЬP 0ucJQ(v5 e@܇-eҪa֢0lia4`X:"I e)Jt"^WMM@`I#z}l֢ rL)`J<+0 {q\y Ժl~NQ0kѪ'J{cMt^MoO| f)Z%!![_Pv( ӐE &E0͇hdĞF  EUdk5](1 a)XIխNodki!T2k;ZYGvzZXR#@5ğpۏi +~G BۏU F9=(Ln>~v.^~\||<͛w~qww)?߾[zΣeuRjbαbHtolmOۻqSM}$GL=c8H+TW(9Jb8}H15a- / H訸>Dz[:zaI&GZ^uu2ѠF VZL'A)HCu^4(\IFwKڠbP JLA5 s&݈ Jcwy n8bQ+Ӆݍ 94(U[Ǜנ Gհݨ#-mP-xoP&HyڳK0$~]Kgn ˑwM`hU ~z~}1!l'Lf{4-̱H^AW)wV_«nixJs5ڮ=,SP(wrgؘJ0Ogbt-q>pqyR%C#)h"2۝w"y B{""74O4q6I8=z}ĂwOq1w 8NI=Ξ-)lbH9&8Cܷ!TtA'72d(!(o=BɉB|*K&[2Q'c]?lSOfNb(XyZ5ce^fSd \?_ǯ0$S@O2l)Y[Q3Kk[ԙ,k+}:im+:t":oY[QsH[$?{쭨uQZQv=[A2Q" y^Wy*cAkdPZQ0v e`lr;fnLN]}^v8M ;+3*#ڳ=xzÖr5ݼ3AP6}`T^v\/–{E{ g}ᔢ]6,@vAZ9V/y Ӯ(ICI̡TQ~6 Lw hpv/#N:PMD:&J".B7" 88f+ڼGu!Aϣ4pQ,Bs^Nf!1¬E3a@ )P2RP]ӏ0[5J3~h0V4`(ыDQRWW'kܟr*TţWP^U*E-^يgk{yxE/+ʇ+Z/xe-:qWcm4!7%xUGl]/ $JԈUE+[Q#lm/ƀ|%|tJUR+k ս` ˔K糁H{"y|tIi6 HzD'L8®(0mۇo67jL=̎Q(uQ?jيv S>&e@90fqE+憠0~_!Oyѓ#qY/rV,'1ahӣ*X2=uZLRyYCk0E%hi/2hj!yL c7{(zxy/3?\pv*#gפ~vfL=̎(mUQ=gيyG5:d,f,tyX2"4Edwj8To{U .DB*鼟EX:yZpix2満 ǔ:^:jV{ L)5<e04T1e&^ʹ׌|kk<1N8®9(Z2:K_4З4Dcav @yvXVu tL<ʮ%g +Q6pc592̘E`8H7@ s`feezvLʌ~)S9D<r":JH@[rn0%dJ>HȐ< `>&:eUFL/%)`<0EN)bZWyANÑPnL)g)&RADG pj+N*Ȕ}BQpugmAC!x, >%`y(ؠV@A r(h0v 0cJ>c *5DtԐ= L RA(2$J88@r8H\⠐eũ9*-3Z튃̍8Xx+/qF0d`8@cJ>#l!펃@5dJ>hȀ8Zu uhTPf*2FP2 A lW?,i?82HQ0TƔ(CQ?ڊv@1h7@01$R8@rȜh@Sd  I/ Zv'A1hC@Ղv"IHA[0TBs` >]r0x͵0G eQ0hYNqU>`вV>```ʼ gCA1hAP QCڊvA2hP4dH u!p}GwIqө1zE^,$>Ҕl]bu4&MjBRJ4ZAҌ8lνwΦ E7A=DGTj+ڜ&"Ev H6C)G|y!#<ȟ32Ң|xħ"l,ӔڟV=@ F7_A=DGg+ښE_QCJS+Y#G3ڠ6^!kDΣR rRhvdgc|@Uó0wTtQ@ي>Wǀ'"x7Dr:"`5 X&o?fjVanF64JQ<(N;R_YN*3 F9\FU?DGg+ʇ_QCBGSTD8.$h$k([⿱f? քevz\CjTm&PEó0QW'PtQ?ي&Wǐp!? $"_ŧB #08"H3\៑m~2kg{w*h-ʆga m@į(я!6C)!#JHT(2QcDȪlV\(BhdU4< 3pCtԏ|e01 fut`9 ? S0@_;8mdNa>-NYH ( lEP+`c81 uP\|ds>lD?eU GK(G팿0Bo2&#i(:ja `ee sRkj%`GD$PhZODC&3hp4(1)KɠF5 Sf2ge B:!HVl"C3XmTX4b-5#E!A˯:`2d3J֞aF4^]#=&#SvFG*x HlؓHRJ B"NXW.ؕkjvRN64M@#ec7%Jg wR1wɪL5{F=Hɗ(_6mE;fU@kJhCW;~:eKz""+; 8=N8kw p;~B>Q +X 9[%_RhO{!TR:r:託Uem7>޾BmNN)gcĎra,MggWX׽tz fN"pWv{~ބO*3Dn1h pn:":H`[Ȕ]Fph/04NY4dN3ehHR8RRܭ @X^4!%IS z<>ĵh5a ^DLo0p%qaEîj":IC[@BQ"5) uQr{ $JZ^4:-6nvU[8풭rHscsPR(m=!@hg(]joTxdG(O[mE;oU{C5  ElӐqur6wyNi2r@֋f7VEateȈח;$!adHfrNr0[ ЊhCG,ULDG1 (j+:`aUɀ3Hrr)g)H^+$U*R61~:[̨W1h7HQ GV;D'i+= T;+)*!j bbThL>oX6OyS!)\v fF$y =ggi֔}N&gݪ!rżKtԯυ_ОPkHV{:!it{46W#[gh PFga$3?|R1bL)MPdQ<}ڊvO1h7ȾBю!p.4Nu +o42li9/oo?]0>=`gh23PvQNڊ>L>F ȉBAD1=rCy>S]`kS Υ=hT ,)P0[ \M6ɋB,G܃rV;\Sx$eא 0);DrtW $eAbS: U ju1[Ȣ$ Ov8!٣ipT}A`ߓx&P"P'' N0[k*Pd@N4_'Q'J mðyn0~aȒڪ2|4#FJ'qR<̨YR1h7HZW]HDG! h+=i TH" i}}S{W|=oz<{~\yu{5xai$&,\i֬|>=>>.7WE_͖O7>7~c.Ͷg7WbgwWwLzs~s~u] SP_1~/߇7F4"%œqz?<ڿsK]OJ?UѦ ~>`p$~37Z?iX-btta9w}fvOӬG>ƻ|13OۛrT,44f?{>T15H1~.tdL'M^Vט".?\"?)‚*ߧWvca`H_\Ox^vb(_Č#CR~_$u CW9Ç^=@_(F2bëDoFb]w~xE/GlNWK*b|{yxKűU51ƅDQ&`kFLTb Kᅮa_L _/yx>8Fz{x1kOJMA$~M M58?>nV\?J^0qz%IFpsŇ ` [ *bLmLh0jGQFJ=n^zYݯ STS஺H,}rwJ jĊPf(Zh栵~ky|QU(ӂҪZ%3TAg[Q]C]ΤcJ|y ZPKo5D'zGDChaserlights.fzPK=tDfritzing-app-0.9.2b/sketches/core/obsolete/Curvy-Parking-Assistant.fzz000066400000000000000000000651241250202676700260750ustar00rootroot00000000000000PKp5DKViV. Curvy-Parking-Assistant.fzmsȑ| 9}nX3=1;{{8()qM\5#4 ݨBD/3+Ǜ͗w]?=>| #[  k տ??=?~|Wxǫ盿f~ ^߯?\m_[}+__V>뻇?Ȭ7JW{mWo{{n5UJRUFYWOW߼˿dLJWo^>]=o^.חwW<=?~p3j?|_~?\חŏ5szuu֏֛MH^l탤ȌW 1}Web]ۛo^_9OuB!ƌ'Rs߯__x#zr~vt7 #$+>ʾ ~K=_d-c=|?cpwϏwxB 3xmM{C&%Z2Q42}TZOOFp{$wS-5*SMŇ`8Ƨov3<ՎO˼aVETrAo}Yw[(dt!vI-n[|Nȝn-x7w}|KG-Y4맻73K#SDH6§?޾75b2ZfhuTqAu>=OO뛻g ?erhhҴ8am47} 4ܵNt}]>`pQ_=nV99YAҧiU-Px=+Vp{Ȋ.(&:-a<6`hhQohQx}ط\~c%R[fVr~uȪFF_w}G`_wu?IqWY$T"+DBo< Ђ;k˷~;.֒Eܻ7 3 _MfvMw!Ҙmܨa_ʿY̫} ?M7S֒IEcYZGl֊%&Px:CP uXPdiG`b6skH.MogPz;/-qhg0%vnV\Q AlrKwwxO`3,Y[3ю3,@<ϳPRhEkkGsT1μm˲3.?5bŬmsvv*a翝 q鿝 P55h[;@v6[8 "c3X Y6v*~Y J!I1k!XИ}wG;;5vFώ }6j}v3og7;C6j}v3J -{Lng ݡۨu߀?GvFoJW[_cM:@omq-G|aRwUvMmNm؞tj6a6.XH~H_K mh0[Qmz%\HޛFwXk.ZBtV뼑!,Z!,Z/jAfS]^|N{saX:2c缐.jy!=".Zl(a[J#/wZ Q8Kъg)-@y)BK+ p(͵f6ih۵i-i5 ;ZeKc"(NKiy'CpZJ_N#C,)ZD\4y)@W.ȥ4B].h sKBB"&FFNBxo)=@2-Y&Cpbd : tIR^7aWI{;Ǚ Rus0 ,ِx^gFt; wgj0[QA|M\HϳFt=븣T.Y B:>빙!,Y!T,hhٌ@}>\q_ðuun.Oz!}wBE$]H?>P㶔h}1%f^HO,+ZD;;D R:7Rz :- [/?pXJ!(G.iV`tZJlNi}5WZeK$(uQKs7CZJ3C,cZDd3y)]Ӏ׬.ojʥtN^MiK=g L˜BL#HNfN=xE(p)}Ԁ?-Z6Cp@ff-@M x1R(VVO*z}yz^W~Qg׿W?=_WOW߼yzrtyɦ9~yj|ѯ7w7"//hxξ`g8;z}?}NÐ&[f?DyEAn;jo>Q+7.uxm{i|h|q}M8Ɇpwb-Ȇ6a]ϓݺi/~>x`$K_52fJ"K:^_MW .CN7}g}LJSvѴhdz _6!_ecF#ĿȱAƘ, ]EˡD&8BBԤKp0֡bZ$a4įuV<UD_0$/Q7^(Hp"|̡-Ǐ?'/*ӆߐE!ɠGW>!Å|,ż|Y"m=U{}z^݇6?\i崱LU R$-Q9F yDfyl^G P;y~===l<\wwqIc(_W$q=Q oWg/1u3;bpʝBBڧhd1Ұ ~+'KY`BruyN{H8] {VnY1>dC ysît)!m昇Lg!yuK~$gl脘1%yg+tϹ1ٓ'L<>>l|e=ɯ.6OʰmOw/woo?2*p{dO΃(yk*ӓ}g ?e DBGovƈ.otv穧t͕j47Gm 3czZ?.NlW}V^ 7}%@>CF 4.}u*>;h5z.އ"(1h?_^y4kTsROϏO|p!R;?px7_tpbK^1U <ޯk#Du"˙藿0L}>IB,=h [dN@h^ߔؚ3Z#r%Jo4]Шqa)b6v]+1uMl={E'`F|2’{Ά//>nP wfQ4RZ}1% 8R02=+OBS7SD23&-Web1ʖͪt6TҿQ>ӕbG" Q*@JJ #)Ī>A[Q4l|̔:GϝkӌL )<&XRI(b*BB\PQv!k5ut D!- .J2ϕuVQ*m&zR؋Pij(þ''_Nۛ4GO،OOOp85ʑ{x%Ҕij ٍ%(?A1I |D@딠'(8tEY*ԗ!%+;c&4nMHA\ ]V)s:E-i|A=]wtm6IUE] K 1 lj CI]}Q }3hYJXzezOXX)7vWx @MXw',qmH9+qYWL 46:"_1)_dh4KgW0(&,d#aASИxM`0_+B *u#(A2{CTu0eұ.dxjybeGte+Ia(tEMLWHY^!PXtEE+v=KӬtɑŞ/+ۄytG HWeԵ–8um(0u(`0_36:&_164xZ~$|N )"t+HWuk(.LbLY278Xlqpvᣈ2.=3Qr}TOXpv]8&c1~14 9|Ğ`2ChՓ++Q(I >]LvTEg+vV?xU27[\D  U=+ FzhSֵlal0lP8 ήMHV\*Ven|{+ؘ+ӹ(nA„0&\,`(盩I\t09-UATf foŨ /''Ϥ Vʾ+,*=vܺ*s~IV1\"ΎYJVfsmuLY@B"\&+lEEh\EȮ+HRvVӲn mtDbjpojp<VSf¨ L;+T=YqTaVVZB(NX  %ifg+42%"IjlBT"d* "扴i-eLvPV2gP ROT* Lj :%*:.m?N޽d'.-fSyoeم.}./y;/\@o>e+Kv'lŦ`̓_6Dzܻ|{x!?5k.\[1OBSZ!4 f9<-Zu 68nap0١R4lhu@V?© ŜN91ъ/B6O T\*mlLMVrD,{шbEW;6]S~ӧ=wK)haL"KŲXaEFlo #e /H؜51d{ UmmǙ[ &{.S#1V(p˝rQ ސ MhH4ٸtX+t^2P2ZG&%IA@4?]`HbIBdwY!)QdH-/#6DF@WU \ܯZ-!JȨE TTnDa6՘͡!cRHMeȚבbd3%dtbnj6챜SyX?sq^"HUj{`dIeS}[7ƱKDVnmqЕF98Nm5Bpx3Ҕ=֬pQ\aD0JU"?`_#`Ƈ[D0U iU#e8jT.6"&~pw`m]7Ũso[DbδOv"$ս;̢ HRڥ@$)-I1ʊFFQIRHw(ս@' R0"d"CL&TL0d1RgcrP Pdg7"QJE) 8@)j2m㤣!&XNN,56^KAkϦ8Kd)16/Ut"#%)7rHOb$@Jr.+,59T@";*R\PNtm.ɁDpP.<|2Tx$)헤쀤!)6jOR<\|L#Iu qIM@R='qIREZO6+enVRŨb00 NccFP ?LaTU.1nS&b[T('F~/}mDRv)Vi#Խ{G tlvuQSZ&GqU3Rw$DַVQ#U"T'L.Df(z  #!˒>AՁDhT5W ‘ɱw(2 T(GQ dseejJR$zM V0St448Ij}f-<)ƈFƖɞF EbKc',$u>t9a N'<; ऱ_p89f"-ϡߍ)IQu'!gh)uJF,Par{Ǻzq=PXGrz@>`)Pz([YS"9Qj)F2l'٠2C:^z[T$ec(0 :u 5W e@遊 E(;a627\!{2JH,Pav:^ vJ=z&ʧ)3N {=b$=TNAXN, QsQ595|C#*U{2ԉ/=`IJl Dfa"7,Χ*˳3NofA"Ȥ~.hYyY:qt}M=';Omt<{¸) V@ EZ!4 f٩gAX+ԂՉ`4,E(NEft*"#1:ZGTo> OlQdEˊqẒ9GD$ yqQ""PʙC4CZ~M;|h1>JtN{dc`FQ\#hM$@2I%Fd(F-eRkH\CC _T%Ao?>8rջ6zz~wW?=oޭ_]tuqU,V O`:6+%exɠ;4lSN8[L:>m$㑞 8 DObz\tahS?M<\UZhCgEpyva784ԏx`Fy sNgp56e"w zfSy7Iye 8n1n <t71IAL.)e&HFH$KLKOg2vME)Bw ;U.)USvbaV"\Lu. Q!1^9Tvߤ)bv"o0.(n-R*;>,U 9T=Y;&Uϥ ԊYR +ע4CVZM\bv"PWQJJf,W:*Xv/p2~> }V>}O~J6纹р<>W I۞p[7jW.c DlXٜ˳0ވ7eH$JToa MJ[\.Î\R不"(̈́3Tz\rQ$zP)%^,fe(R:D9)Щ҄0D9݉V!J"">Rd[.gg(ᏭXQl%`tks8k,I$V$t8;CI`Qr?hVK( 2V nL7[Id U*y E.<b;d0AnWIS$ 7{J%&s8;FEVġX.]X,Pbo2`)Uj=4V^x$+嗬fnGl+d oPERJs sI$'ZdYvxxP5jeƝvvK쪱0fc9`lU bJB%;xLLtu\,*1ٹep#Xi`5C. Q, 3hZJM}YbB]j\uOY^_8 Ԓ=J-*ɀ8Ş+4|&ɫS\] vQpLO]QDx\Z)yF WRWKc]aEHE. bFO#dʒhBTI}ո Wg`#0zJTuALUv@oŊhLzGtN- :'!U҅jxKǩU*HVԡ3VvPvZ M&ES/<# FM$6p]q zAlմXJ%QwaP65F]!@L4I#JP 8W! 01 E\){O0px z%$&쁜ԓU+EOEXjcu 㩶nhɰ`SZ"OI*Å JP]U7Vێ*EVn*H"$4ѵ*Q۫L0Nj[pjB(;C 8c<<(~,[b#* Z.¤ya`R٠:vMfө!a:d"]1?h])yDk-v\:,BTL)w@mOx3 Bq^3fZ&:+Z wd&Պ{2g041 F*dߣ?JX 2,S~>J{7D8a塀 y|V #XLhO L y2Y"% ELvuLh%.gqEnoqfi/|?w?o.Ww} xuf?~fӛV79|<]o/mZ{v;^=;{vY?l ^||~ʮ]^tw%WOWO__sGwYǛyuqnu{~ş^~u񛗻/Ӧw7_qo{L󻻇+>n6j?_nj?x?Wwٽ k?Sf?^=ŷ//wNVyr)ge~WO_$3=ޯ/nJ}<^dKŇÍ}ѓ_/ro?yXdJfUkA}Z.nSΤ[bcW!1IOYAO+\?/>j6r\HUȭG]qȡwÕ "bH-Sܭs*SJDOsN;n,v![wR;o)06+2[=A9Ƕīэf?'Ᾱyϓ2ГvdZYň)=h3"'uJK'׃TCyХѠR`Xdȅ(yJCL>'0!&coc"yoH@PHZ  V6Q^"J;:Sd;9^ Qo -G[KEXL g|R<6,uC(OS""/. CgMݹ6Rƽr)DHrȥv31jҕӋ|+vPFdgh0 0D(-}1U%@*_ %rJSue)=e poicgBT=^UW'}DG,"-;50RaGJ\`yNܘWz{J#.Δ8"AX9R)]H32Tʰi%νRnd: :ᅡahwvp&8rVN#mtI#,Xxl]k$uW"Y"-\RLvPz>KBJ5wDZQqERSޡkx^;(n}"*s^V4*aOuʋa1 ]{XYUĥ Jn1 K_,0:*֒-xMJ^0;0 (ٟFұkSxlq_u?cUEy"&;w`U#Fy>k aF=m]bUz9PC4ERH9 DEX.PchW"Hѥ౪DLNsoJ݉ Z#*y/хj^a EfH V/&P qT'}@%oX㵩ǃS1+MIQx$X%)&~0e)&c48q[ :Ԗ*z[,0ҍ]+MF:&jrGTH:JEBS-پ<b\iDDlhݜ (g2! DDnl2  Q-8GxT"ΫW?t xRNI/ Fh Xl.$c$1F_40SuʋCZP z] wG-&:/TˆtD)i򈥾s{ :iHbJD ]s)"\M:j֝ߍu$2PP)Z'Ѡv?ńf .˝\ ƃ~8??N78_|U߽}u=>d?z}|{xGrn~^e xz~V狇kdc?o.d}`2 ! .v1U& ŋ]vU<ɢ%[~ڡ~i{z{،Uo_NXe_fڔ#A1|Ḧ^yp{̈́TӎTN.#I bd[8RGmw<L*:|& |sA$H鲧} A*{/-//X J#^h>hP$̿D~<,MG^aЪSv|8_ͺRǵeVNAXLHpߎ(tyxr%+RFʥ 7VQʩuIn-fCl5-g; xS/iCɩ5(ĺA>&/l}_L y7a%>qUSTQdLGPgW `1hwP]͢Aɜ C4>gaLU1ghcΓ#b@J|ƜDƙA|s.,SpXmu1D5 tM|ͯqap4eqYTId}˞䇉˺I>h~[N-\ǟ/Т?t9q`SuSUT ha:xZ Y1k>z2AOY$XkI:@.z(1@%Ar{Țx%Ϳ'~\j'^QL.Wu򵬿JYbZ,e D=&B繜 '~f'^҆_L ց.kvm14p:9SlUGE82Z1p]M"O"Y_)=CFv}`ˍO?_nP^PVZA+n݀y/!c`.oחnW@k%'fzNgAͿ =O s}ο 6yZhmk voeOÍ3ł^u|U܁`:OU֓lpctOQ5xUxCӨt~,`9$wﳿah_`><g 9{=݆ss꩗V"0{K@+erJ+D /gaZ{h%26T_=6غ1aj%25 .hN3TgSPAu"eAw rOsƽZ::rwm5fD;s{P6:Y[M쭫*Օ Nng@ċ@kK0ue eE/8{wMRDmtu}ܻz ЌaL3̃kk%ƫwjllȁ-?[ bã349g`KGb$7$i51IJ?hT910 ?2/q) :kBs, i lZd&6#=O8w 'ŖF9ܮO҈*+XXL "Y၉![MX=0B2Ft "IOxS"ڥ V&BsN4[H8H{2"SGYeEAPvٹ1%"Y 6d-9@Kٹ$рoh%\vn4n^Pшʆ7{.BuA\FgV7e 9)u#E]q8P.ur eLJEX2X6h75Q+ BBNAM"&F\Py>R! WtK mʱXDd~C҉`ȵ BPp+ 48˴CVS\ rh2J~Z,b I0<–[g gTn΢H o18uƥ]嘀`-n0bIl@y$ߙqDY=+G, :dU(8dPBYrri,녢, ᑲg@(H>,:zHQcf,Q ͊oJ` 3MkSqDY= G, 2xU'0Ҭ8 dȍgȅ?Ƣuf,6H[F2ujT~۴^L&^@EW ѭ3zV+AQIsx$jJĂ"0KV j`UB"LeYẈFL;.E0iv"%+ ;RmdEbSU"tIGٙDhʄIV)ƜWz1eDLV@#Xnr!aFӆnratLIt{(i VϤ):VΒ}*A[@H)D2}*bZT*AUdTݓ L)=S!u31tPEXwP*(*9?TF\(S*O}VSR1OO%OAч< lTVhڇST NEW GݽB)Α[C+Fsa9&^&\}Z QBTX06,RJwz ߗLL'`RH2޷JJw ce"+-w @sGUJcE+x%^avWV9xu$1W!"TWP垺0|/`9/$`A ,*R %",牰Vw|u7eηJwBLHS8<T XV'f Լ Xpcry,, b,j1Ã!U.X +-ʆeѸ/{լoOgM% \p!\D+80ϟv1^P*~يyJgԛYh>&5# &{d"omh_ύvnD]?a[+0ʡGp E + d^m^_퐠cN"P*^a4ոdpd/&Gߑ`nnD-0#}(mQ|XC0lODU)؁DxRP(DE(i ZLNDE0<玆D!*[iqeQ|}G T[yBC*s%=WJ\"FM 3g|UOPU) PEWXaDzrȝp|}71ٍ(?3Ui}Obq$=\cN%ʓJmY>8 㲃Mt|y=OUPj\!O54DQd|>X;ɧObN_NQtB)8MN0S1:8FX ,N*ۣ~_dͬMXSITRI_+?t|{xؖ//z|~ppy|rVɪ|?ǟX7ck/}yL [pH"׬Ҽ,Q"Ol39aRp#rNHLLo'1a,aIPE'zaӡmqFG&>mr')v| cI@î;>b˺,[bۗF"s,/WE*B:ޞSf|uV)T7KEрV,֙¥˜4-q;-FQ7,M^3B(nWhʕ^r[$)pwFzF[4g*5e& `pC]׃ 8OuHٱWJ_ԕAXʽ3uG9uGh@kd"rp)Ɔ+iVx*ݤߐ?T! 0A+P%@U6.G.NƹM /=`*EĆ+DGDk\^z:\ȍ W2<• W\ql.D l :DR0LMŠ]^z2]*_2]9X ]^u PpU"0^,mKO+zj?3_)|E(bKXUE=yS~Y@V),Gmf^"YS%J@/NzW*JDh:Q%W W@"rcÕ p<ÕW0]o֚RI0R늡Ʉd+PG, V'*FV4eLl5[U W$BՉ*&d*dc+ JQ$y $ |s@j*6pdVV0S󹖈V' FV=D% V0u"bCÕ`uFDUNU0"rc T^XOϏo>_<\}X绛W?]JI]9̈7_~}z_i{/7_O/~Z?=>|+.׏7wJ_ O.oG?| ry?~uW?3wyzzwr]xi/^t!fs`vl/?>n>|7}uܾT"ӧW|SeZUC$Kk/-_wcm Z3?\Y|{d7>_G׬ޯWoMyCvbg kwwWOk^X^ti~}X..nmm~&1.W5^Q[k)[)B]\z}Oh`{+)l_a=9bLq4&1ޯџ0}G_u6!zO%de׈s⍾awo` zd_×?2$_ uܞ]&(ToCHҏ֩۟vǞwvbPKp5DKViV. Curvy-Parking-Assistant.fzPKHifritzing-app-0.9.2b/sketches/core/obsolete/EDGY-motor-control-stepper.fzz000066400000000000000000000444561250202676700264560ustar00rootroot00000000000000PKp5D6F1EDGY-motor-control-stepper.fzmsƱOTov\^\fzo퐿>-rY^ݬ7w?׻xyjܬ|Xbxyq5^n-~o_y~^g_}ov?Www_]R^x|޸ޭn|yqk|oXc*^)U޿Y=lnŵۅ]aˇdR؅|dv~xvo/v5^lO맧oַOۗvY^8|:la;7"{*<//ۋMq1_?'{q|J">ڟg?Z+Nfbǃ.?}goݼ3g &~}rkAda#y HLuzy7ˏ^~tKFɂ B 5僚u d')!][,$ȹ!5Z+4 9mWH:Fv>YMR%渄RD7V|KVM&QM䘑#=M&aM|OA[mtCV\hnld8NQ*r˧j@}Mk*ؿ5 a0.?95-Յo(c\"i,{Rm Cݘ |^<Yn`~%~aov\/U?l%us(~{ܑΪ4k hP=]fP] }ǩy-+7纐RH7v?t݃ $ZAZAZKf- ]u- ]u-͛RGуTPqv:ϵ4JF:c}ZRGɃ֥5Odnk)ΠAJ@OP)塔q(%p56;o6˗%n 6~C[j"v4ﰤܬpACA9i W %RE$||Y6 Zp45qÇښ.{]?Ϋ;)J./׷GWpnVK3tO(=qjQղo77Wvh[ǃNTuXܾBc%>kk/OqSfz& RqV@p&+|IURt2۱VLJSWc6sy,hɑ 9zx{K_HR!Mf#?fȱc}_Uȱ\YlewP8q4tbuR1D(rn-C+N,>gnT|LnT FvP(ɹ1zč +9ߩEs - c6D܋ gHEs!; =yL>s~-e I\jaiO-EK[idmđ ƮđbdQĒGIrsfIMF^ `VDaWaZarI0{ĺÑWtnaҽy1ĒG`W< WfI+Ҩv,TXZbI xcEbPYSbIEϚ%= `5,%%q,_YFno{p>K$eKMG`Wy =hT%@;D"{%z ^7vZ$z Ԋ{4%xZD`:QQZpˆۑg8z4/7B_)s !:r=0z: bIt'txs&B U`(I]ߢ6\wdA]RÞ$$"ɨcj2,]9QwhP zՎ8La1]1GØkZ%I!U(=PX*|C#isP(q;41nc$zVITEMBaC6@HHDDB޻ L0)7aS}F1"bRrHb[HmW0BaPcj =r i(;]9R.g2ĠX$$fIsM 0u0&SwE0 4`-*WxzA0`bWoH1+zAQЋ%wo׃r yxto YSR>rݶ|_?_?l.~^n^V맯 q|]߭~B~Eo7/??~_}}뫫o~?~{Awo~ C۫o7V/Wvhte_tt1w ;~"랝?~w7JD~{Ⱦo^.w?ۛ|}7/1F_9[f)pA_X]ҿ_^_o؍Y>]<,7׷~Yۍ~ߠ8X™jÿ_n7SundXa_=Mnb_>O]XKi%^PD##&Q,nnd/_w|pն/#ה#3_R3,L:/ Fw rgQﲟ$w ?AIח?j;!@%dӈscB7~U])V뗭5v_îrxtɪ7'!W7{\vxbeeه0}ݦJ幑 ]Ib[fd="]SPu}c%\B$=!/'abuMп0ͷViWg䬁 J/ G(sSCf-eJϫ'B->q"֕Q{1_۷WޔL[JC)Iۖb-E+?Zjv%+C"x&j8;(]Rʸ+g@)G@ 5eLZ*or@@i)RhEp9|UٻH3C5uĄCuա߰CCJ$X@ʁ$, bv^1j3eĔޡ3֋]\Li0&2%(%20~d”]{*B$x1bdhT'lL೹~~|$7x_P9P%3 ֮Szce<ޡ3V]7Vj띾 )ʖ{s# Bk#yْ|I>&ҿYn.޿m1'f'j$eb5b"HTXcA+O/#!aI~H푰)? }@RW葹@\@1z^g>5w; o? 7jUrF{&J>{KDJu;%zZgkw-)ݮ['Q$b*<sGKݯ_}Zfׇ]am] $]-Yns%2tWq|.._K{߭^)x}-Ϸw]LtwjҔdsRw <ݚ_jmuZ om!lӷ)[ԨFTt#SiVV#a 仭vN_<Yn`})KBXʀ$LnTۺt)}_mgr07:G / AC+e6d\=RW,8XjDȲm]:o)թahh_q3Kp+xTS@L2(gzZDTmf=N_G"vyFrԡ8qXgmޥZa,XQrm}±Ю!p`.U;ʞ;4<^S\+@x=/KJg'> x ѠHF(w>YJ< E-Do748vTAb2vwL"a{'@0D5ַy)5f]*i*݆$F9`Zo*awh0MRgik}()9/0yh x ӠH90ͺ>5Z"l*»tGCP! if\H0 0+.iD)…ZW |Cmiq3C4:NOiIfyP-HGϤQN-ΊxPшحx(=rFt&PDgpJ "!G6RTRqF0!zCFlõ dl|p` \91`e*1PvN"\G1QTRAR ک3@ <}CshjP析 D]F].; ة}!QV޾b]h2lQųgٻoOHS,@Q ߲6oh4يIE?FqSC)^q3<(ySzSN>.ܮWYt)#{{S мC@b2vg@cx"cC@I-*'# 5G1`I|*13,{c{ZdٯfD;(I h=khLΟ눣Ժ"Tx Ms+sڮZ0+XdD`S0b26=5\ؙy2!L dxTbUK.{K~>] E`%\|ZJ]aѝ|*̙ ^7y?#sy xlsnF/37LD9TH+!s#D9cH+О[޻N6jbL>+5?+'ŘDX% &zĢ3Q,GB0T'P ظv#b&.@RaV(]s6ʶBXB#nOaGæ-)NŰZðZ <H V;4ĀjF< b@bb w:DӑH74Ā HL>ĀȈ$&%1 QwXg ֿJb0ph81c諣nտT¯ڡS.1RF.F".p₩1[nZEdgA!!:$4RT3, B N\%d?;3bMZ\B!q9r$(C"]9U-[6omՋ3c@qq.(B15o"Hڪglg[\Pc&ca@Z0wF$=IӃLшНA `MX!b S?b2 DCF16.Q V(8'X |CAl?_ұ~bE;r K'Ma@%#Cw0 r15"Ha@#&ca@4dD ba'kv<0GWMt)%}s>1j<*7zמN V?4`E<9CU+F/p1z]f\ K$ H(ٮT?ڊRbm#] 4G5G2jNFjxSD 6&.>bTAQ,NGB0vH=2EA0MtL  0bvl"}BDݿ}1)1zKh|ڈ}`C_@"C.ЬDWC |C#`@#&c.ĸ%.L db|CÉkgF\'O#p^<%s U,]CC fcΡ/ zy"H]0#&c# ݵVs82♯j}V" ~TD3A}>Wc_0#Cw/ j1@Cz|Cԏ}ѐ(Lq)L0I`ܮ^ 4llhycJR$ KMf8:\k&4*Gv c?qtz\ƨ`'!WT0(z15:"H ڮg2Sڇ¸BeD)*D֭!VޔVh}>|C` f}ٔa0 0Xj}a0;G!=`a0O0 2"{L(1T úфD!l*+% JaSm'RDS'#HP:y49Ռx ݙÀ鈡>9sP'p =&`BlXlݡO`0b76Dૣnzy4=} U)aWT@#oh8qԌȍ U7C-E-BZ;,`DaWտ}-`2Jur N Z=Tc'M\@e#C-1t4nPň5Kj[|\܂QN0C#-ps>ohӑWϼdZdVKQ 4X}jl4LeB(z"H.g2S&Bˌ]0f~"Ի\""ycD]Q.;L+q0DuqWvH:l\kHgr kGra*Tx }8 !ޮt5q5)1fqH%B7Lʛ[ĭ]=]eyz.ﯟ-7OOW߬o?.,oVO5?8Y9yP3@#Ϣ0HQ!5fX{qnMիM8Ŵ8"D =8Ձ&Y^yQuTr RJO;-y$k|Hs'pӹSFL S^ͭZ MnJbMrܡTtwUE{WմO)c;F@#=1? øu *b$nD'pӮH{0 eZwϲ8+#n352,gj䉾fS2#ῡPw9ftCn9,<>/#Z3u;#L.(Ԗ`a&_\<gY5#z`3I"&HҶN$iD-HZy$m jI$ >u! Rl[HPH"YH>g6Jۢ2E4 wGgf7u9$m_0PsHfN!i]FvB2e417 AҶdx9C^ }wB Ki៮z͎i>v: RƑ1yy*H'WzԝCiyDw5IO&Н@oq5fڧ4%PL. ;\ Jgv[{<13M@簮;Ԧ1w,u-kϑB5DlhY Pw MbtW[C8bm-tP1{l Fga25 Mq5vVÚ1}=8k:fDP1;Ԥ?CUc`Y#Z z@Y  y $g8n 7d aJI25B>(}LsqR%s).t\T KR5TX:ΐK 撮[)YicWeg1c3QjV甡4S~TB$; D$5ɻa3ILg[)'iȜ$9fQK6l+$#Pr6f{9% )<fSCʈKR֞K?( %}(VKݎe0׻쐁*(կq@g`g@I+sB tKՕzS璉4@= \G#_3Ho[Gcd%HyI:e&Mgk .LrKLT--0Kz&J{RR%CM:%O gh(3U璭ŚKؐrh撱璳4@Il+m\?|oe~s|zl_vءͽ &cնj0aUy틻Y1(ٷdk/<*]Gy(%k5w|.͵5]뇵8v]=ؙPwy~]mcfi|:A3ɳ',/e4իFVSKA._J=*-52[{x\j( †Ԑ;S2_.d)Eoo\l. bq`cC&wcG%6Nxtj'9n!A:ؔIAbwx$;;ow259)4wgef8W[]smMλmC<F`Rn(L/PDޭ|Gv3=\ }f!Ĺ:kHMlu ٦iӣ<*&@U,}4i1A9}!)FȲr?q +C /)K CGTx}͇l%cQ4kBLqskbI8v4qpRh H5ҍ~(NdX BQxܰ0*"ÍV̝C;X]bޡ}dB֍ =vb8#mlE&J2*f6s˞9X/d&fpc~k-SX '+OeP-yptcz Ò!]{a U"VD` CCa@#*k,1&q'J_Ye*(aIc`ݦ]ޡR7IC`dwȫtȕ‘B_ S0E1\|rFZ7oFȊOzAQ|L." :O.+1@ў"ɴpD_P^fJvL6)5dFz{U%D@11.A۝:lgQMAk:\,qֆ#59 Xj2S2tźst'(AXc {7ez[v\z\Ixo:z\TPS$.PWMD]/ϝ9\+AP/D'gW*y0T;1t8;E TU40Pl^$ |}B xa|ܖ_H/5ۓ %^ǽ8D1Y?ݨ٫hؕz{Azx,]韢^h DVN~a1  jGPڭUhȘ5nCWՃmB=#b v`'8熯nґWb/!/;(GƕB,ՈpZ] vd^PcLR_8yH({oHÎ VAL  b1ؘ} E$o~d2;3jqf`&4B"H]N<c@u#&ccPcDx\͕҃Vx%;~@A2%"9|_ aF%~Haهu4 à0BG$8,zs>'pާy0T -DM3|YLO4ݬWe~ENQuP}"@A4)M p!6E:F11(-Z<)]cDgp)cޡ2 s*&k9&60abeQOpz;V G`H W1o"Ee1{dIHO MdmL &9%"=ib"+!X{ |LLd!ݏcjGL>%JD?䱑%[HteJ&4 qM =e0c)ḃʬ:Bu| QRP;9QY`*!X{ ~L' sBD7t4) 1YPhͨh^Y\?\<}6=}vnޯv>C]|ښma ݬ/ۥ^@v|?wPKp5D~EDGY-motor-control-stepper.inomRM0WUIv9HPEvM&ѲBwNZRC8{o 592_5:{4Ѕ TԶt獶@Hɡv:th/a,1ȀEm̀4H-[A;qD\.NS*M镦(2+4 v7]"T"Y(VPR'3!n.Zϰc DAH]QkX1; mL~.nJF?mvA鐭$ \Jk`{,Tth7.O{eK:'BbsDYsÛ9g1J0F2x{/jzGE*Y%TX-/ȹTkvOf|Bqثe>e.@UΪ׼"~iysRQnʇ/#%`9-DGQpG<brzY99op!*9; ^_pe8jQNƾ!+d{PKp5D6F1EDGY-motor-control-stepper.fzPKp5D~>FEDGY-motor-control-stepper.inoPKHfritzing-app-0.9.2b/sketches/core/obsolete/EDGY-motor-control-two-motors.fzz000066400000000000000000000437161250202676700271240ustar00rootroot00000000000000PKp5DfET EDGY-motor-control-two-motors.fzmsƵέwV??$v&7V$RKq  O< \Eh4_s|}xX-w?Vv47KD(NYoݛ?an~͛_vWo>yxgMsyF֛7Ѿ٭w7,oMYC|>i5koH<߾_=.nia'_{y͉[vn>1;ۇUmVK}Ê狩x9ۛsܕry/7|O8kn7L ۍV_wqkgۻÛҝߟm_~ޯr~쟯◧nu}ӛf&Mݯ?8EblNR.uNxX~Z]gϽ[mWݧEozC)GF؋ƔZKl7[-}om[]z׶O[˦5--i[): Y-GxO W+w] G$#E篛]z%\_j}mA{][>Ƶbxx:3&FM$w&Idp2Ѿ$w&|u&5ı(kvB\ zgۓDH}eLZ a3Z@5r!Uʹ$5}KOj>ބ=sIfphB' 8]? fzi(Ejig4Fkg˨ Գmi3HdkRy RxKbg\Tߙg6yB&6 f3`JsUA( ,pzۧWB!;viÈID_$yr|=. I.#I#akj߿roP?o/% >Iw3niȏ}9}`3 & .%I|8FZ8?JFZoUw'{q}i'T{&__eu9kŌ=Z y ?I=D*z r ^>*ɀ|]z}`9vE1B0H1th`/fՁw.:9“VՁ+C\x; flz<,&3FY̦ ``^0 thPq1! #ޠ~%5jETpv7(#P2kn/d ї4kWMqe'?U+d-s4iЃـ>EC&WZ?-wj+$JP?NpZWj}i wKei0 Z_jK3Hؗ]̪/ xsc\;R # hz\:СMi`ƎjsHÇd4t2-̰Yyf4O ΘU_>@A:tF ԃmh 0 j`R Cf e3쐔BIѠP%}P%^]U]RPw׻v|5+Z*ȰTt05;)תo $/ uHzsEB=>rwx%@RѾ-7KԻ[np?gWQf}Zޮ\OY}^Е +\=p{FYj K0@$)ȟPAל~rgbQD;E*;I7hsp%kShR\?\iCt*J!P]@Z}Q*}Δ(\wW UՋTkJ}J\Щ y:eDp7O%F4K:IE5#tXsqp}b10&ɳ%KQKM"Rc_HsOGp,7&E L ah\@G&ѱI߲%i‰J%2wEtlazj._1\e]YA U6ű U9r켊c:_*W,Rpbq\*x8J]iAGIydhGpJt ЈsL>4\t=w:BSłc}DUjV9=RtjSD޺=ϫ~uܼ_bn޼&̻۟IS)EEP1DyFI1,Ey$UG@oP#}F\^JDrKS_lqpS#9wu_ )"P|7vٟɧRmez< evGlSZ%Gj # !Rt{qmS51`XCo}c vҨ"DǙ]Z߈DT˅ }Te+)%3D#JX2ӕдg9֞s4%3'|YY[#VP!uNg' hl 1feGz\_M,3Ud:+f] :u|i⇪"˃6zj*AWLgiShw1E9`>֋~6NSlD@cMAQs%0 "pI0? ^2n"4抸cRK 1rPy6~4L'YcR ӓEb&;Dݣ4*B4SB!sLTjJPdLtfLNU#ʼnQs}l^iDŠNF;ASV"Jb9Reww0S)cPЌ2N xPu|\}ID [cv>P H 7)Y]e3kdpIMM K Sì{aetOya-ՐpP) |L` >R,.$4f8La11%$V(Iu7E6W#zn_#sŒ 2p#c^i>4jT;熶KC)0RDԏ5}=]oFu+g@l0_^#}yxS&b$_:! #ajc]һ` Fq[`oA#gmn- #neqH2FSÐyF'#tsye?f_}}VI~,~Y?oV)#wd;BQ!_W{L2ܺ=mH&qLuƿ>-_wNdi(Qn.Z;{4Y"3#ytk#NkQ9Դw>jI5ArHq3k=LvxY8ܳMG^m$ xVi֗7GbS;~%QEXoc>g׏~<6#rh=fO/$U90R|W AdDSD- t| \*o邏0M&x8KN5 I>†v [4L=k?9T1IP20ݦAM*u6?|%xQ e" vkp/uܩALT`T"'ɂ*Ȗ'F/՘v^!4:RGz$Ք_xȁ5F3F3sڒ{늻 O3DoуȑZDbljI|H6뇃$l8P79onFi"ȌDcDWrc&H5X(Bب)o{/\(?fP]?-$ Jf5P!-LdˌaMRl5fD(y&P%- B4}%xy$hՀ<1v:Xo:ˌ !x8fL^(Rj 7R4J!˜h`@99c8Cpz5vN3R#8\Է9THd硸y·!dua8(a8(A]FOȍAx8&7X&Rj7R45!ոJFʩE@U4Vh ⲔiPyy&FLF+Erlς1(V*#;0iP\{~Zo~U.,d%Iq:Ǐ"?zL#kt8raqgEsBD6E @V<fǔz<9HWZ&O9%su!4%'+0% Fz}802Y /H{t$$lz>=|y X$ytE@%1GUX$Y0bv^.€uirh=SRh;Bt$`LƅV Iٍ]L{ؽN&2Mc_e-Gd%Hc=, -LOu^Eޱ)Վ U>UJuւ5X\HiFH^+FҌMV{wՒ~on$a\(4ҭ V_WÇwLbCi-45,1WPhSh,eMN^4Bciű\1Iʌ1Rګ?g1HmӾԼ xI_)TBi}M։ r% `/ҿ.I-s3D-8mKLuvxBx_z Ƨ,/N3D=fn\)iRǞ]kcjT#tl{]a@!X,y]n(?R|ϴ+h ąlZ!4SG qi ԓ+ƢQy=-ww TS-@8t3 jvfkT*"Zzԛ֐ 7_.n0$,f+' ()d/v%HL1}o,FpL%Y͝YV! Ljeƥ o7aLVZaX"yԔ,O_sF򙆐=W_*D1L<{ v6e!$H:( b[a(F:'bַE0"LHo!b pbd䅰 >,uF4E@PƬ{B`>^'oHlav"l25yя<KHA5CDMnx%#՘Ƀ,Ay;v >!]J®DcA#L;ǁ-/ֽ$}znQr`%$\_taXvdFg )gs6E"|LƁU|iĽ {16")#+7oḿWT|$ӓS`GfqkZ1@ q@0 .lsSsjETX %ŗ"yM낻R2 D/OOR&{?2ǴYMJYMS[)"#ӯ sR&U"0R] Fߚ ƴY51S.Aю̝TaPB"(W(DS8 `"yM{yNJ`6) C. f%%%%a#՛\-*'8-APnE3\eWr54Gg˦F:^/!9=AяMZ @eb5vT#-)ehc"yM{T3)FZ@=ZOIIsdt4iO@*'8-AvED -6mfaÑi>ސT?Brv{H!#B8 H3L"#SqM&J%i1qgѦMqpB/լl=vdzӞlTGrtC882^3fwPkƕl׬GO2io,*A9p%?I"B[=,UB[!YHd>Hby/z8?+"@_>k[R?P 粶"\ӯ b)|+#wL{sBt`B~E?FqC):q3d<(MeuL^dѕ&9+״r$i$ P5 - +"ԊG~H$ϴP٭ ~gg@iEbu`3f͠=30;19Y(#)u81c05$Gr$*F) Fce41Yd>LS@Br6=m5\1qE x",xfbe91jq3Yd^3Z]EV0kfhi8/ct$9G&d2%9Ǥpc2h!z9"L۷:ϤpcD"5A9BfI\5xհ`d0$G^/^CT.!s+IegP3i+DQcdFEj9״1Nث0($i mK9D'T6!<}^qƍ׃pdG5rMsW!93mV$!y0(1Q<.]6϶"b.BZT)ꥠ9^=%2ϴ.d&3(~xQ^ʖ$r8j+җC-vqPѭ XL `#ϴ/π0 2"]8KbWT x0,\΁C¼)lɒ|_/M*5Q%ƺC ViĀjF8n b@bb?=|I 3H Hbr\cu4Ltv`#yM3Ds%FόwG_f;#r'u#U%1ePEՎ6DF/i!9[nH]V cBZ ")*1Dr"B ث7D:iLT|sgF]WX}TX3d/ԸRD9TL=$ҥm`)zQhV|5 FH:Wit\ms]SW!93mԍ3A3#^Pc<sg8& 8ɦ2i1(HP\kSX:|`g`Y1̎a(fW<|uKE6S4qtk"S3XQ9 3S@Br(DDFDq3 *QV(l6(xXEwi(3EL~(VKw<+A$rx?49ՌpݚĀ$w!z:"L{P g$ lgDQEV8XļI f@HΖ1a$1"v9a>HbG^,Xi_)8Z6DRtHb>$S=Brl a'baWiEIҎԡdA%`ú3IE@./yvǚ]i)&& D]0NU)l$ݸ<;+kE0^==| -_ #R  SHbA 2(Ĕ:IXs\ 橂{$S@Brv{""㑘;1I Q+D`M*gD{%b> }H>ĀTbnI,Xg$Vmڗ`F8nMb@%z :DAG1i!9 !#( QAˣ(8gXB|Al|_/)d?1UIn)u؎VmÀJF8na@bj ;=|1 ~30 ar\ c00LhmB|UVsn}DCY._^>rϴ?i9XaDŰBC*Θ*aa nh^n3Tɘ8DG0i !9z_f\ K$ -H(YI) ս}/iM]WLSI % KGI|UAxW`'(Q H]#RWi_)8"_`#2ϴ?sT}@O$$H$hVfj ő a@uf;<x&`$@e++#"Hqd 0D{UVh.}/_ f}z4zļV>r_0_X*85spo~_>k_@#$g`@$dDwcę)gu 4!lJF{a>6TIѯ€d&:BCpÀ*aCcPѭ1 \Lw!z9"L{P g &`dCld;lV3`0l W^7\D&"b|`F*v!z5"zLLPuc<2l\悑P*|<Fgz.k{5H\>e TE/2ؚn7݇UilW Iss,x6-9\U% Sw\_@U$Gt2>sgڛ*FHή"PUcDU*)nise"~yM6F$6$W8z VfYe]'y8C{u.٫ڴYD*嚞V= W93mӘ)HLjfƅ0]R1DaH,,H^ֽ}d0i%0aaHnMaLu4U(Ĉpt4G^,rXi502[ :?DG$1iߥ0[ ƒ4&0晕"HHѽ }d1iݬaH,&0cԬa qX?êME$4e0 qyk7=|͒WDG1il#$?D=FdqsH rbA Asr(jW03H`V%l,a)BduW=CܚX?ŪM{&Up] w!z="L{&Xxa0$!)JSR4X&Mho\n6UHĄ֊kڴoDO:\|9CxDOS4BrvE+1ʵ`vpawV]y{~ޯr~X&߭כw<ݤVz|cjIF "I9IBDSDUAVU}a[GFԑj544KcG8ܫ#A #G{5v׿:h@:R;v`/ц.kP'f։Nwԉ@ܶ7$RCGz5=YFzͬ ؍jFP֍&ơ[ps/(&^7Za}!`%lo?İoц;}҆"&}Td^$O^O K &`2B9iHy}4.dO V @SvvHo o1;C!=E03Cו0kuir_됉2uTG `:vB c,m}b _S eDjAf_<ԫ5#5M90j!.J$Uh6 >7!kvl_Cn6CՕ `jCFfR=quȃuKW8VŹɼF1,IڑRz)nsp7$vɓgʌ\"w虄-3ŠAwD,N+3 Vu4O3S吱4'L/$B z'<r5&:5ZId\’3 %홄$y$ T%ןc,ҠH;\*It :pVaÏbASyg3 A257 $z&aHƏHw뙄" P:$#F߭g4@i> |IH|?UR`y&aI '0wE4̀$8w%t>ӐfgԻU S:_JJ\zJc.w+9+M5#` Em Y. .R ǺxC溪iE4VHп]7wi7響ZNHP=lLrL6׵ۇgRows=#I#=7UO黟D䂰þt~|^,C>lmcuRDϛiyσ˛|Kny'쯘j̍/?9 I=5>>5:7(u !UBwør:caK7)$HQQ#ITI :}TD2)((J‘:R:U3ǭ ȈHd 3bvxǜ\@FZԥQHBHBwR2mǥMsY$T'Hge"X#) eAq:A&}wg|9& ͨS$LEN]?48kNxW;R,S.K:)T' D3&@'I4dӞD GHn x_lTb~)P"D9AYVIS.H~ZJ)$!(nѬ` X`sd>b H0i?*8sAL1Yd$ C%Z" qϭݤ hFİi_ !9)01&q9@0ZB9Iʤ#58P Chv&CaGU/4:~aKFn;W,R؊ EHheƅ, DR !H32 1lk{ŋœ| gxщ".aW_1F\ 8yz ȸ-_)czy A^*!9/(2":. 31qBh)*DpL$2Da" EdPrMNd=[ac7x0E8:#\ F**=F*1ƴ"Lg`ĸ0-X:jCk? V&h58hU}dbS&E*xZ)^\Ҹ,QГs8xM|cFHTԥǥ.D10&U!-L.>y(Br9шG_#/C\8}"ݸ0l+YI7 _^Q~ƴL!яI̝$&RQ~vd0k_0B6k_jF]1w}A=ս"b.w/R89vubyT4twDj Fk#F+.~{Ԙ~g:@:D+T Ը>%>Eʇv5zl]֢]bXB0v֡PtczUY7&ȨrT&,nΓݸT*M{}F!L}Qy k Gx!loCF_uaMD]*z:1%8 ▾8--}uk pm1&sQc ̥Os|hUc-U>| H^^`Dmk$0B#yLP4WhF |ȲTDńM^]$?jLP4W֑D/QyHJsսF.iC_Cr9Aq?oϿ[^|qu}ov{}bw׿+w5vCHnE`~>l?6j3c D&>fN<}irՔjM]x^7rXwg_?51F_l죫auu׻.+2'yW_o|_ϷjS6L,ݝ_?ɎyF|% )'NB`D4-q/#f_)DG+Z-I/)~ѕNмx~m7xڮs'%PYd9iHZS_k["{a6hU|AeRv+qi ┨FZ&0_^a5;KlTʞsL' GUzԞ(֞) V> ezpfւ WsUIY8m""dvkJ] 3JˊnʢvU_9\Y.>ZxXKLwBZ߳H8=JA݇9t ~JS4J!{ )&*@X_=oϸK3gJ/| E{B")ġI٫kIRz[UzCheƳk^xO2~{Nw1]J#B*>y%__};~_/-K_ןErOgwkwRK798{X>Iܫ㐬+$RۂtPj?,VvDdgfVaz|0VeVcR>XՎO~9g ժiƯ+@5`9$ds_S-ȩX"&3*mI0JT9MrVcvu/%F-Ovj {Vw,})'[`Ko~ϫ~npe9}XgkPKp5Dkmh!EDGY-motor-control-two-motors.inoK 0{n֫ J{q$J 6E n(xLi/)D8gu*uiD:UN<%Y+ 1+ر,2sWjK4ߊ2rK<BK# _Q4R[srYs͕XJ1уSm6VFx3ԒvPۺ%*6zߢrU|wVl+/i8PKp5DfET EDGY-motor-control-two-motors.fzPKp5Dkmh!EEDGY-motor-control-two-motors.inoPKGfritzing-app-0.9.2b/sketches/core/obsolete/EDGY-motor-control.fzz000066400000000000000000000253771250202676700247770ustar00rootroot00000000000000PKp5Dۆq7)XEDGY-motor-control.fzksF_>',2 m;ޙ/J$%Rd_@ TzHdee}~wlv^H#|D"dy@ۋ6p`RZܼxXۋf}1ykp-n櫻aZެ=,Vl?V x]7񗣛ϏO݌[wm'QIҖ|96 :Zlң3nnib D@[}7qmg}Sd/]^-l zvhr{\u{]{2O_MKzL zr;Mdej :JwqzF5fF?YoZ"ucɇv)@7UMuO$0f&Es(ôVƱEO(ç3UWL;;{J ^ÀBDb$RlnC,FP}5՝l*2@|O2>.wot+)ѐn15儚&~#i6BTjPMeé-®֏ +5SֆG724QUDaV9_6fy< B`a1O &/$o0e1eQپ%G+Yvql6wǻ 5=N>zQlߨŠ:|lvxJC ]sNuYW quC;TWq@݇}wnz7w @ ?;}' $B $nb,.@) xeY _Q@HSX"$*#`SNBdrí+>t!⸾u r,Q܊A]zOFukc,~:=@#ܲMO΃,f`֓aN΃a#5De힂mb;sr#l")Gt[w~~u|p81~^]&(ڗ`.S'[pGGwo?Z`;[^G_r{ { xlHeo0N6uhUsXn~;E3HC3+4c !'А;6#%Q@cud\]RJb` 1w@2jؘSZƘL]HGozE/RTftP JfƱq3:8eĠ) kA 6-[(WGq"%)c2u] =(@ػ @iZ-&d+"U F>/)S Cڈ8\#|9*v5QL `Uĭ4*|xఐx陑n2-ϊ9`X[5iqt;Иi>DHkr""f8юnk]ak hZ#ы[vhFoV_20}ͮ'#įGr׌ۄ1WX45vyZJX]~(&,=-Vʃ|r]TONj)ߗcPdpSlzI&¹ (83#3{+%L*ȩ PWí<;`YXʯ"%#Ux̬ G?CμM[+c2"_8~AL1Ƒ08>QJt&ݢB45vydt M bVL$W)a$ID"06sXG=՗01Vҕ vX[C?yc#tόM`ץd=P E(- c5z1`iٰ̍Ùua@Rư"0k")1sM" !ډE /oӶS`0UcL^@/rY}^ Dn,"Fibq\SdhzP`$ 5 鈩/ [pHNHr鈥bNG VܴYg |@bަ-I lԪjta= ;q-D=F9=\zZ*so mZ Pd`C=t@U]( Za6%3وm0tĒ 5E@Fh6VpbP/SW3'.XW S|DObGn:L,IwRF v,# *TDS_M[MApV*X6m9 T5dE9zC//zQUF92*=H0NDlG@/_Ӷ+g 5uDLAL*1 ,~h`!1sHD휎_ަmSa ƘLRQ'w1%gA3U*)l%s;(4w5ohiv}=+ЪkD4jh۴R.NޞhN0"}і&m,er=MMJ LLF BE#򛹆ĜN["""\t5\5@WqӺ3L F5ކhm6O1#QQY`T7b*5P# `M :ڊ> W3z= ȕU"Qs5>50WqӺ}v)թ!Mz$1&+DBWu }fFDA :E]@]ަͩ \[H0-J5W$$230 ^! ~E)`Bmȭ\iF;zCiK!f4U%bD N3q.'+KikC| 3='V>Rg:{nyRSţG@Q=X "t jΊY!ڹżM {|f(V{b |bb $)&'V0dYɊ:Zy(;i(P d,6P(,fB\{*r1c>ή×qUB!1sMXkC?yc2umXe)hl*0<(ƒ(y @m6SqIgdx} i KQE,s;U^4ހ5Xqvy0%dD;#Иi4E1&SRQk `AdPP$/H3e2 k9 6m;-VSºVBPӒAHW< srj"YhGㄣaMMԐִZ@۴LkNяhKc 9P!egل)K܁B4a2Ҙ|=GLdԁƊ123ף1(qk%h۴%Վ1.Aя~h-@֍fB_jybׄ|sB6elgf[lbef}^n xOU9}}hqc*%Je(H##$N.}ŎڨrEse 0o^l?#6w30Fz [R {]d1T;VD9 p{p7vp:; ll .3íx\Tނps/` ~@|>NlN:^|36)qEYdsK*z4'.2) *%R&W`KfBe<DF>ozv٨JYP~ry6E $N,Ѯzy hJ ۟;_Ξ*UGG=}tw, ODM)qsEbfZ D$yțRxut6BBN=AHTc<NiFi1XiG!*`|ZҴ~GcrJ7 l qIudi08RY|SD)R,E*!TWWʻ # 035q(GJ I⏉t6vcnpR0fYMd"yyD F"[u'oxi#Xh+Jh @mZF"cr؆| HJ;Q7YHټčOIKBrKZܟHFMA NgFgyD$ID4CH)**M;d+*9'߳b@ gIh$kZ-'3[a]F$Os_NעYJ )S%A5NxIJj_),_2,-% h/SmOAɕLkpU0F \Yݴ.\ a$hƊE6ƑRLa&n5KM3΢ALLecg1i, 8(?} DۓHvhMe*3jhm%[$rE3, ,ޔ8^HE&-6޽Xv"~pIIIܭԱ9̃D X[zN'B~X3-UF.m(: ~$n42q/0xkG\ @ەB.%暞F'ju{I2@,e4.Lmγ`xVJdW$HAk;#vvÄc$*yhZ)^`MZ\BRj% sYOI"֖6=_ o"984l/ՄA@NoՏHA LY:Y~L;-W?~=sˉes(v +cZ"6N(f+z0y >)a1%Nl4y!yG QEEܬfT1nЧ/+/lpINcIY֒y^:a7qz;paTLlwpQaFLF56l`Qq(,'Uq,`vwzFK}`ft7h88 +*J&x FƘԥ1&SGl0'~iĕ RRxSS V vԙ@Ncv +lvB*1KBPzłAp g#@XEӜ@dLEI_IdFD8&e4RTWGB+״=| H9ㄯ1Ufaڅlyy%/1K*ÓsbjLj؅A'uԴ=w1Y`@KcP+p-wJˡ$\:k2J]Ǯۚ ]r/OV@ucbn| eG"(¤0 b+b ­G !q#!Ȋ^rCnh 艰G'Hq?A݇*{` ~JK4,z8J>'Vxuam;,ub -r쁱O:{cwYnߥ(dM/_yt 2nj5&˿XdZmo֛WY~?$~YTXA#(܀7nz37?}*vyXO7N~If,nqt |pGE\Nُ커WvlY.W2*.KMg7}jLf)~m'˯Yu7`G?GS %Yx s>S539I/o%|gTYM6i`iCiOǶSvhS V,k*N p_ٷo>}X[Zmȶ&[s?PKp5DEDGY-motor-control.ino 0q<]3(yl`9GsRJ^pc^BopƍƦbN 7v2nTo\T3n˭{_+wrXp)i?Z5d;#͙ŏ5߸oy6/[wZIԱRx[k=yB˯q|Y; oGGN|W[ә=o_0MlO߹++#tkϾ:D8VN I+b}}~1ItSgf%F|LZwwqo Gk!Z! -p6 s.nn1񑶙JLDWx:v=uwvߛ9f~3[knZ|w6x܌R~z+^LCbx'k郵MA K][A0j9 ? ]|N`!DJ( :Btcd0T*^zƩ ؑt)&qY=VۏcF2[Pk&1CB{tAFgy0z(NćEr~ ( \I`2,}_L&mUl=v1q%tmE(b\dTBzڦsϮjԳ*tein61{%,"T6Tw Qҩ n0|\ w(@ڃiEl+ w2Πƌ@zi|RŽҰSІҎ=pd umuAJC&\+b\ PcQºAXxp8Z{Yd3^u/bɊFapeDHJj$!Xp,,~} udDlI_³,Q gOş i7S0vR(ZWB$n3Az3(46M "#,q@EzjB%! x&j )ŤHV oqn`fD]v Tt! ff<;6Ւ)_H9;EF Go Jp!tY%/U]jByMgE[Y!8ѭ|*Z !O'pQI}jP ]gAF.T4!;w[K~< , FUg?D }wem#tu'<s?a+k1>\P$B9uB b׆UZt87Q8|7usWBJNa^k;)X\JEw 1/̋I^d)q>7WB0Ly7ӠN{ `oX_9N_0 V_-٫8i`& Fg $hTozYDEݏ(,̋7+imKԐ^ ʅ! .gXg|d@͠綷zоZ2D޽LR7Ӧ7( e>Vy]HP@=fB&Eϴ9Us}xUFL@rSt1sw۹cK`K7Qb(0CI"YvC J uzA$֜Uk){*Eǟ∘FHBeUJTe$j1l8:D~MaQxi9֞EK\lUњkqMt 4"6^H$ [۵FH^-KF$_̫qtHR,AvM)},[@sq #H7d,4 \N%yN!,R֨ }vFQ:$c /dlt;@Cbz!d|@ƊH-u^4r´!x4H1[ ނ,e`^`@M(J0C8b_AP,QMrbdXcyey2 %-t9m?qeJV4Z#][zM+c [EE{ʸZq,a4H1, vt2&@ H-È k51Sk%pc 1h1;#:>M_ADZnɤR8w\rDB6圞.dδN740U LTVˑ#E[zJJNA,ƢY~Lσ`]cF~_EEkJb|NvCK`(F,z pGGCah]k+*Z{A'm }Q:)!*R#i$JuSa4?.w ;?@2"aF4]m&L!hղ9z6@֤`G]}2$ 70QJЩbxE a6UʲRXIePhЈ0;|l\,hm.&vGգv^XQ 015O>%@Qh ]eU:mY>mgAskޞ#tu'~@X*N9ֲ~z?{Ӎz||Y̝;1Od?ן5RW=O&דɛOo??@T{z'{pO]Nn[{MD,(.s4՘lCx/׆! Jc09Qяa+:O~G7&He5ŗF][Fß.G%GX!+wW?zTr7+k|3}]n;gvXyNR^}f[rKE+i {GX AF0MBl,ngF߃3La~/o [XE)@x-XΟa bs!^a˿JaEOҚ,S9t5|iKڽDo&o-έ]OgƝݭ-G@/[oKQ ;n8U*3]]jޝ `RKRڎ<ܸg1t2êA]}H1G;Gp]E j%hjxg;q%h}#\~,f~"U;Y_M|^]S&BtOřXD'[3L[۵F!Y#5"od D'~T DZdD!fAGUUZUʭ!=ٹsxggU8QubcS5{Ea: 6cP$v(,vxV3$C]XL܁8Vu-\~Po}_G^L|n{/Gʳ*"rgP-Je,J2=J[2ݰP6 !}vVQCZP; EV95,uÍ'B!Fx,ZGJ-{_> *˖|/Cv~Ǩt,̴ B__v_quգ{7i~'Iiwu=mv0'FvvfMfĀ$YOjd#Qb~B{?;]dl[yɚTL<v}]T~E1O>%׀"8R3섺uфt +_A(Iۧ VM[tFiM!* 18jzjXT>5TGS"8RB/&!PKp5D)<n Fading.fzPK7,fritzing-app-0.9.2b/sketches/core/obsolete/FlipFlop.fzz000066400000000000000000000244211250202676700231330ustar00rootroot00000000000000PKp5Di(}] FlipFlop.fz}ks6ZOdNUJIlMw'LLsvt2m"K^Iۯ_$"Aח4<5[%}닇ʟn/;[n/0rFA"ވr@뻫D?ߏOF]jr=_qA2~܂Lf,l{%́]@v4?LZn퀅]%e@Ӏ]>0&t!h1]B`v4 tcӥ3DiJVz6b#=:u U CC %4Y0r" VIH ÄFQ)N=vJбYG>o,D㣯^>x%s K^?228<[N q3Wdxm f/ }/Ii< `$G+u;E1Iؾ 6dnPV6ȑM1h lbj nΌӘ+g(H|XG9fxiFq̓3?͐sx)Ya@Pph?vZd DF4z!PdȆX0b F9_vf@GvP<ժuSju. ouimiwv k~TC fKyE~UV^5fk* 6'^.UHKg..+XCʧO|7+5Q)n+ JU?W|ֹMsY3xk;lȓa22{NG4d`s9U`n1?PJɀ1W'><4v|ħh4QګI9ѰXg5(rHHpeW7 >RCL)ObVU̱Q;bsEH&.A%&,W^L7| Vư,N+1[NjDta؎} jN-see'~""v"1% ӪC3ڂz@WHB=|z,{(n[^}5"-vru;2ڃH7oz +hlrnϓ?|u!WL|.iyxZ?~rPa7&OM-uЀ6~ԭI ]N#tZE~"id.AVK?~_ )khx(#Ә6rd:9(9 g4Oz>L7ynTopLAc$.߿i*:vJ'F3٩{K5(IX&&)/ \&#qW#TaQǖ_ꫠD'T*eܘp8d4"=hN6e F $EmVJvjjyQαvd̸m jGvC2c)9R.hHJkG6~hDɱ=<]Zi::-e07~b<PΫ6mTPphl@q\"_dO?OO]uH pjdwcxc5?\hEm.=oݞb9re2zg!O7 GIjXƧP 0nJi0KX _\r4[:b}:<"_, oSC/Dsj:=)b2ɗ8Co#gEN\gf$gRn椑5ö4w mM]`Vy'#h7Ͱ -ՒaEA.E K{1;ɤka_@b/" (Xasm۱Erht$MC#A"F/|ѝ؊xKݹ>YCH$$诜 b2J\4]PXYq.ŋƓ: QSPJh0J\2} [+,8|JAʩ#N ȗT*8qBic91VY])U*bUV8/*DDA(K YHN|i U`R𔱍6.J[|2?`RIN|cFdt'&CxTroM2p]F$'6Ih@'l ȤICD$M>S %FN4HK"K x`GC"a|r8JYQT<2de,d0:,Y3Dd-5U(K*MCÒJb!x)u]ޫW_ҕ~YO7ͺO* w_g8B˨"I=T|Q:^q 't<*a `+Q[aT.(!:9͔xtd5̑9xtiQ>4i`A6w6 ;Q!lyͲLHE1ͅj&~S{> m i3^rhA8` aC)AHB^aAԨt*B:y9=;5LwR1p6-C-'o7 O!$?87]7ӽr̴&C6XED2r""1֥CPaCM CI TQC 8aMLCM TaƼDKd^ w!I)`.#sCCBݦ0:ĉ/z=:2KDX$JO I!u#nz-~ZWdXQ<$Q *(1v7عNqd4T(s!]11 Q0Xȡ,,{ʥ uį^Cu CuhQ(Jg7̻$ޅv\aQAk2O_k5ZezIs2‹,j{oLς{ĒCncbH$ !}ܓ:2ci^y7 K2 !s%d B6D۫3S܊`0кnGFx_*VEq}=( rwN#dܔ"S")=ύVKCl`C5!Oƶۮ빗L^ьձͤPq^UI5u KLCmHt`Ka j*[a 3r|##W/aֆ0 z|" We#2X@x=ɪ aii(jGFE[Hhs#7eeR$..,2E1uh~XmQqt >U'%XCm a1DMr,P[ `f{YHAF,64Г/idrdcv\>GUxD?@Q AN:VSj'r"q)\TNCqÆ ,u!j*h%ZtWYlHipq)<&)>-[w`_F8ZF14?i8˘8VuU ˬVLÑpQq 09DM-r)ʮ 1$)rUSF$1 H1eKC#Q=厌D]௢@HҠv"WUWlYUЊ *` Xy*(`9c:X)T\UPP=Qij90tK&QnSB#XUVܠPfl&$F偰oJe/4z!zmk2Ҝ/}{3ҞamҢjWr6Yj'}lmuYqXA7>S&Nr<6DNbTSwxP\nKSSgg c}pdXꀡ3$D#F<;<6$?6Z瞧n%r(HG6YRps5-WjD8b|߫IF''XûS]苶kQo~ֶuB{{&k]+/Ʈu_'.,F˭"ryj=814K>Ak#,6N Wz\q^]־j<ni 77u9Ier)CGM9CGKq7Bayc`7πT+sG羦;5O2 &X/xDܸД{Qs;WʜZ3 T+ bT*/ʵyK f CR$@F+O`[=LD#)]$Ǣ-#b!=Kr+ڂݮGKԮ.]uXJ^-CmrzE֫8XrJ`5{[SATF M:x M:ehG}[m՛: 4] ,: i?CqyYӦ 0\!I;㹠Cc* -Tγ8 9$r<ЏY91 C/ʃH:dn]8Qt:0u"BcE=w$SCĀ٪hH.vvrC$c#$C3,!4 &x I%`УkcuU}4 &b GE@0`K,SGOfe_8v{vzfxz׊n/]/7!?;\;-{y܁,ݨ{  xD*CH4tJO -0yXSVtw  ) މ##}KW5?On;jVnjýr P/Pz%t@adHҾ$B:$b/PKp5Di(}] FlipFlop.fzPK9(fritzing-app-0.9.2b/sketches/core/obsolete/Fortuneteller.fzz000066400000000000000000002515011250202676700242530ustar00rootroot00000000000000PKp5D(fRV Fortuneteller.fzr#I{ NizdFDTK6]J9XOO?2&Ek&"Y]x2Ё~=wo>?|Ϸrtp7 xHՈhz_7ቯ/n?ϼxuOWoG14nWo.>7o>z{o.{ak{|뛻 M'Uft&?}͗ ߼i7~2?w7JO^)m-얿\fyy?=__tCEZe7wpc!-qßn>{C}pZ^]xs*?w77OoEŗ^?<޼;[aǟ~}/߼G{qwcwQ^ym§7Ϗ?]$iMmo.~JӍ"۟+[x￝’I;9gm&һ4=3+WOsȳ[%9,<󷋈]z7UjYE_H:A t1}t_n_ovX9xqo䒹͛e]?g5𸣰W lNj*VBl!-:4̀lU/ Z" XЛj z3™J=djs AلL'ja7I}^580`AoU"?XЛyKcT%pn}Dqޖ A3.a{3g.aEUN!3'.yȼeCx津bȴe~X mܬѭJbȡu[ߞ3!J.P;UR}=r_<\^ieع%\%t.Ņb\* WHjp.pݬ籢4Q 8K9 )WRr.˥\O}9z|*p!< Ϥp)_8gXMI9j|o<5{^kWԢo#׶g9ł'ci}-'gR'ʋRZ>g[)XD ZLWHs \ c]t-jRXϤ"pER3)\TLj+Ɇ:tgRX70K `\ {CUzϤo>~}ҿ/w¿:΄\muiⲭsjZ% \®\*Wʹp/Xx*ϥp+)79ZUrNa=rXxeX HIM*1WSpުքՈkPcm|jc}J{YKzaJ TΤrpu~T3^C&,I`}.s!\Ъ$.|&Uc$<ORK8W18?KugGKWnO7&/ /W/><=|x}S_V7Ϸw7%-Xق]^Wo~ww)WF+z"CLL+G>4AR6S_JR5"Rr &_?>?^=]J~{H{#IʷwiJJ5*sٜ߼0mH-,(4<]R`"~joM3ѷ_Z7Z&} (=+d=}wi@OUfApɈbG.HT5vEȟ$Hў5Q+1D))szR46K!8 zI/2b f[YPZ7:*p^q9o2X 4E&<&tuIC#^wo|sHo?-y{rxLJr|7w7yo.vu}^zO?x_U+掠qF a/K'yXμI;ڴ%\a~7k *6^"Lh}g@"'{}yIH Ye0X2L˜K?klݝynPq[X#6|>?nL| %]ǫ99MG7Q" XɪRQd2}}7?[+xV S7Sw{קǛW-|mg)7Wz/wxce4Uj_/ˇz4'MvQ9aJm\ -2,Ç/T,rQk[#xv}^dYٴIk54Y mB1& zNLjumii`#i/&sK;NUدƼqW4 HhgӯI~-ӫ6#݉ދmffN ݾe0}(®p:Z"xݴS2ksxKC+wőV =W cijd/&3`=L8t=3P7G(|J:tsx{=IWڠ 2-CuZvuyq1ſ=k&:4!hOĵTjToBhRNm|mRqid6Mh6ɤ gRdG,d.9 !'tYDE[\D }%aO\2P6㧻Jlsub)6' %"I)![\TPWRrGxHyڨM&\[O$ &ZJ &heʶWe}ۍK&4J3-r3 H}OivZy K_̗׭=כc,l)i9A_upsl60*4 ~ծMQ%j;XZ OoBa9o+aԱ2𪣍ޖ"&(2ff|ԍk Y\?]QVy]\t|ʭ+D3ϱ1R/!W=dIUbO^'k$ڙokIDUBэ F[ᥱa'r9a;FlUr'26v l׎l$yN5c-5z\XhD{M&QN| ìkL,>'/)16o_W_W "yl}d(D qEt跱)Vq"'Z^ uڅthB~!U baVo֧Vk%Zg3tգzUӕkUDl>5zU\`v_|%U{髎vW}LWulT2BQ"p'C X8ID4.\ݲG)+ujڟi c14Zt> 9nW"9ۧʊcsrORfYB9~TZќat?$3A'—3мLWqa:來=֫C^0Xg=?.s}%?.lyӶ9qO>xnH߼A誾xEz_s]=Sup^jcinULW]5Zy:c2UXh7ww?\ }H.>\}})sTNF:[ctjctj˫ȣdѩn8CF!0]Wi{ѩG=:~JOj!:K!GTRZ67H5"Ď{*>nR+mtƽm9UkUC+ *:jPCE.PJch8V' lљCa*y{Hс#E9HѯӿhE_|HW}{HF߽BȻ&LCD:7ƇV7Ƈک|+kGУ'>qm yEOll=LAGOdvr,ziq! Kw\621ѓ}ïl@TΨx~ U_@1U|A%fZ:ELca@^WVW:TYXIkssJ+kd{{xexϕ qϣkWjf;mlɺf n 7幹Xng~>dhA\wh zyU>;-P.yҌg%r J{lk#Pʜ$PKOcvSm-Üwq7l||nRX 9lt,'ږ8efFn]m9Sn\VCk5%[V<XYCcw?u[/l;Z75*ci|iex:ZM-uĵCk ֫_I/J|w}y}J8Bc 2ޟntYeWy*r,~-/Wi!.>ޭJ}zrY<)׍tvLpLS& hՆtN j>NT=eN7u+SwyƼ6vNz ~[ zv̈@.RAۜN̒C]f^ט0Mڗ]j6r&]o~ u%Ks>++55{K$2u"d2Ntb(G ,nŵjBY-irL1K6ɨۍf.EotWD 66O `%Z[tphB-hGwj (|qW&haO@;Gw0irwaʔpW:9] f)!j鮎ww swu~u3Oo* }hjpmFwg~ (*;>Z&wrtZ:I"i7+28QC-Օ2Շg4kkQWEufv_fW7Oo3L?C'I!#a]~>=euDUViďPv/t*y]t7pzCv?ԫK >HC:FasZN>CV1:0cE̕hts1F42*\)HH{@/9ؗ1o̩= ~/y2?sW@R~1m(10G%luP{o ֳVe^!87")ǣ=c l}v&\8I^1RS#|1> eR-T3A5qY ӳ!Qh:Lswɘ̇Ɨ{ʍڠȔh*d9RG@/Y=z=ͭŦ$Cp#:sgd)fsE 8FyH`[qR2qK/-[Z٣[@Cgj~b(swgLبS|(nZe;2 xh?YތőRꎵC^LI8̞gKzvAٳG8; eU6]u 9Mq stcD3q۰gc>N+2&n̍!MMqC_@3#H,8x$p/VO0O2#p#Ǵ#< hgrčvQǭuTd*-jH,ں9fgW{)I.w$Ljm2K-Mc˷[ӝvd }Y xH?aO߸1 6 ЊeCc,wFƑZ =W^pcD R1Gvčsn][Z-#Mօ|yf /ÖC+a\T@`pQ6lӿ[q?V,ρnU,8זpay2ȳfw'}6^±Ս4w#CŬU׉g&f6z@` tp5rr^e`q5|e:qcIYg=8/)WG`:#&TzIvNiWБv.P>ڵ!dZ=CGUk*D6^X}3Cjݑw yWR;ȻqyWwdOkwȻtQ_5Z n?yWYAw_6]q\3*:5vPZ Aw_:GHb%ܿ4~}+(Ufֵ?F3vJНWEA*H$Z킟FVMXXvtgѮj㈴+Fԕ;pcl@)H1V5QF9c_cP-I1S زv'J /P| PF63t=~|ϚɥN*‘FlUfxᦜiZ3dlazԨ'DwOȖ:;H̢8.13u\h!Լ{mNowwG4o1)؉r`A:F3tFp$9٪1NNd9ByȾ!n|[ Cw@_+j IPJTjJ[j/MB3nkV֋ɜjJ=MCu+Y[7F3tGU+d Gx08V7Huj- ݙj Cr:jRJk؅`fd thpH^LD4N/ӐļEDUiLk+pAȴz̴DHxV-QFpeDP3#Zͪ5$-"Z 1q#ZFTB3\9P,oEk(zZ CwZ>^eZZWSeكÎl ݑl ÑdȨl˕2Ϩr%[cVedV [ ɖˢ9PnMZ1㇔=3~޴lA0ȿzeRUG׋ÑQ+`{Z"?rC`bǐ=ص ,VmdNbLFVlD1X;kuH^Lfle21o\FgM XxbeDci%r&z=Hv/mҡ`p$bUԋ^{XvOKc$]}C~&Uzj[ ptI^ed* eUPUp^/&sW=t$_4ѭ ?+Ft辑Jac8^1j|mgr=M ?U)v IڛD*cz%& aQ 'C ߍ%_} !yW\3/_DA{Ƚ1U+f GGj"_=IW*`c=8II+qCM?ˀƞ?$}7pu,t$_/&sЗk`©zVF^{Q򯝳F|螱Zqc8^2j}mit= ;U+x I_xQysIy4)ڹd~d_C}UZ:$1oZ}bgȾֆ[RbD#Z>tW1 o-j |2VH2$m^1QJtTAyybhn1)mm^#z1FNtDw_zၪ$"~+kD{-wЫN*A^ۙvOc$a}C;$Mb^1I;2 U0coOM>ި(<3_{-M_gHb<_M HxTNčsK2cd^ˇ3#M^ɣ^;v?;c$\}CwzU CQj`㈄K#.WZ悒aüv=Rޡ䉼#Y lAX &VZ^ d___:}ܫRŽ^[vOca}C|U CW5rL|\ C[mˇ-ʽ_:5# W%qbµa43F7twU)^ IېJ0dl:V"kvz~Jv?^~]}CdX'.I֮eYԱ^ZQA#vHt< Ñt*ڪpkOSijԫoR ?9-TQ|JB9@=Z= Kwg$mM/v~4@˗h>[fLজ`<۷K'ԊÑZĄ`G3if4o*ŋ!IyL-qLeL0 ۳|~m~ȶöѭXiļ Z^ V\:BzI'NɼK'[p$9ݪ1NLv3vHLj!IyU hn#ӭ*ꋬY A, tkCG7tUiHbކnm0[6,ni0-X`ҭ:Qc8ޜnU'[vO;c[}C[uƐ ݪ4H-nEQfҋHuVmasG7tv=jz~JۮUi{8oMdDc"Ă;Ϧk<3K#^hA1I5*89{Z# gSk}d~ k4!:SPb~0e'JSAo&]ld1[Ѓ Fz|N;1҃Cv?cd}Cο6&6&㟓۰AЃ3A#=K`]Xc[z΍]GR|ޤN;X1CvO[cd}C N Y(%"}O۰'YA:Kۆ$lގ7"%H0;cH ݛ Ñt(FJphCiho()A<1TA ry|@ob]ܝ.0]=5##x1_ڝс+Q\&n?#鍙B-qꢃ} 2LA$-Y-(rDbqt5ɲf 57f;R{SjТП#|͜,/VL6fXAv#=[:tOzV+ G/VGqbZvi~ĬoĬVZ㈄̊2UEdY{Il$hW&5;ұӱSŴ iաΟ&Gel)#ټ2JQd88`V k=퐑 ݟU CZP-U𳅣D1i6HaJv?wc}CN+a bLRp|NR }-Z{;f]`[YvOb$W}Ctg{V8"G&S^rfjF5:՚~gOr*41X 9B\Cv>\nTˇnwuQZji[ohw_)ǫGU^5NFjD2ZJZ~HN+V=LrjIj ̰VFW+616HowgQZȍ3l _Dy8|9iWkwѪXKhU z j;l8Ck7sU5p9}ϢITl:U @D#ǩl.y#r'vgIpdTR Drzzhqr->E&D^~H?#z\Q 1;SkR{d*PR-*6jQ3<<򀾡[Ջ]3CZSXb/bΧ@ `Mm p$\ Ǫİ{7t@pbHR ֱlKӪbPdoiUżx-;_2-:.S5v^X@1` h!^ tojq=-q =RW 5ɼ⑙WgJ" c/!x]@TJwv?||`}C>  qHނJκ{m&fBwNSd>"\'?v^+BH2IoLjA}12{T+ I[Z`,-QYZ=r I)chaӗv?|di}CNPeizz^YmQgL1Aa𳱍^^Չ!Ñ89? {!#?z~V' I[Z`bU+ 1ic^I#/?/;eeq+fʇS^3l}yY2Io7?Nv7?*!I{xY%qL>b|LF(?7Q:|lG>7t>VX[vd̠Wz'Pa;{G|o[FJ1!GFV/#@!I{ Ff*i5{bF^l6&X^ Ñd81{#z:V' I[бZPtý351ڌ..چG-nvN*X:I۰J2OƬI־y)K:">&v>u$eˇMĎHzsRV n@lOi|o8Y2$io*cr#ww NfqQɄ*FQ7Wy{MIHzON=HY8fadɰr!@&rSHlpM-;FFt辌Rb'EY1fkv=͎ ݟUCv*iO|iS>vHٗLJ?]_}՛n?<oWwdP#hp/"7"FmiS /~黫/7ӯ??]WÇO'>=?wo/_/&o7_F}_|oyxW_~zӗަsH?)!D6~}{_c'}mK#/(/Kt^~^B\H݅rmoߕ7۴)_zw3yuO(?q?Q~IkoRbtq_onbdo{Hr\ѡQ]*㾛wx෻]¦ԥԍoTGMt#MW |>rͦowuL EWOW_skҗR5 #.; E2XZ(> pϿɨ#uc .ҿϿqK*4) sѾYz*N;RGi&Mm{n8?}YHX7VU ;\6i\x#қ$e ̀otI?/t..od?hߤ9ʸF9},#۷|16ڸd\BΥa$.e^aq,' mgNKkt glӣqM^؄z}]oTPKZ F?&-F7/kTw{~+ i.a(ĴHEHP,ceݾqRy[2 ; 5_IڔŴj-ozoELO?[LF(vYqx_ ͏ϫy*qV~EO?jή/^|* i^mvm6C֚bwWO&nEߓ~z|Wop直*d^ M)p젤QM<<~9 5!W}j2K|2Vmk?3lFx$Y MP_1ryj{̜hV ega^IӬ'n^h&*|ʩ>%sZ#?߾O/IS:HIRņ/]d|[]$3UdC6Hi hlF^ou6\c$up7e{w^dy{4*s&OL$1Nv etLI_^'/σ̓D̃Qu2uidD̿ČSJ&f2D%OMuDG{^;>5Ǚu:9q1ek<+ ^Cb3tA12fjLA:ג^1ƧC"ms2[SwBc,h WLCX!$J3+_BY %)_wcw 4$Md4"B6M ݒX 2{?|'".o9HTKȏCfE<ŝߍrN~&/c<$18 l.? 1dSN2 Y]˜k LnHE~l% sDei+p/VX"oO7OaɤJ ׸Tu(tKi2֭TYczG9b`Ld}yxx&w cf;<1M&u+ RI->JZ։xb_XEpK ^2y\w #6dZ98t~&,PlNU#Ua ܕD`SY<!V V^yTc>/cxa-p,m(*[W_V0˃"?V@4"aV%la hp~a\Klw!u?pV,C"##6LbH}OŖ5[BkgU*hu^JDL5*!G6/(,1bV!hUYv8O`q`1YqP.@Gck)@2R 5Ω1 >T+S~QܬYUX"p˫-Y8n!)Ns*.P*0- ,OGd,?s&Uߥ-2Id~4%B˶϶ T `vFR` Ka'-.iI,rG)XKQ,KJ~Uu9q~[Rym,S1=gkWWa-iu8L@J3: R +* mHe$8&~$-KXt0!e eIVNovAi@"= C4R-/l%ak2!!^dQ/VX0|¤47=5.K8h +dQ]FS3hKCб;\a[E *v |ȉ,Ize?PP$ﰀTõI ygP]I"̖WTCeJ&#V4Ũ Lp&pfG;tsَPB'3"p9oioz0%23yT0@nxH*RkA7g77x0׎r`ö:K $1r˔-2-lKx<|P]>)QT0" 0pK؇Ft"-0͂}`DGDI 5e7HOb Mv$-,) sTI$\ L[@;r!Yp`8 {XCxtM(`A SA#9kO&2*7wVF~TXʀ0e{} W; cQ7aW@DbhG 0$&c w-MAo"MldVdvt^=,mi~Me\]Ɓ*,I[)אSLCih&a\!VP\մ4qJa۬ys`s1=2C3 Q '`+HXѽP!㉅T 'Q4HѸ¤Q#c?-͚XwQå IeQS=—F+5K=~)B\Ċďlhci`C UfQXvl%T&4Yr &MKcNǑtupT4O Z̉qz$ VUࣟzr;甸3SЏ ݆ rSM#> xn阽nAg"L `U(H[DK,x{qP~1@p4ta|ԖE0u*:81B"c`rf(S!kK-7lS⭊t]_tn.(zo$b8es݂4ӞHIS bEC@u螧l 8z=P0 , m4Vw [NKiȳ\g=2,lc#ld+hhiؙjx&1-v,M|'Y@irLU:oZ&dmHcېe T$PLwŎ}88xȂiʔ"oC ɜ.]x3dI]a|lՖ,4tL@%IVHK6G.@LQG=DcTx":J4N`^ņLX`{Rt」9Aj ]BZVIZj)hFlFh9 AIa9?E exzYGRwM+A'#6aBe2)8Nţ RXl YJ t{J( C{>_ \uyF)zV ⻼lilLZjq~HHBG( vh8ީRЦ eaW0%%(Ԫ0 ,ф6-*mfVS9:HY\ŀ_I&储Gy:`o q'G4]^/,C*b ˰: D*`KDe0aP  d4m&a1w3vbA`aIg,7DO^^&'SCTPH-<1Pa@ȁeRCek/P#3#P,~Ѵ `4S5+Qde98 2M3 9BnWH(R$0)zgA T^yf4[{0¥hCoL]`*GT-Thf:}W\pS}ZDw Øwy ]״46WJ $"@+,w4oVg)ME %mC7tbD'LWQ,èQ z&^+Ŏ4 `8f#T~" .3J1 dġ3pQ< a)(rІat$C;,% NģrG AgU2H T^ l5Kv ,2GD,34-짹׈=ɍ'!n,A#@9 }aFsAZPWhAg}j.%UHzaeq_4揘BElV?$ɁeCƳ*y]3+3b*a{Ff((lC9\7  (IJ^KMJp #7 % E:̗ 1 @ t=/ۧgJ=P nt(P gbp"ǖ{ų`rV"xD[hPQX08<`D0 {,X GmNHk4 *d v}ؔe)WtQ3 uhe(@2C "pNBW%\*IXj~r{ o)ˣFKt'Js{zJ]` ڣw idHW'htK&&1ى5M}8)h`_)! hf \0r)j(z6uPWBӼC 6Zd)|bIqLHI+ $HT, l=oVo; _`ibM.lA(?t,}N)(ԈOU$f!s$9ImLhf>nqnɩ1E%[%-6lBZ<4Qd1$wT}"S %8% &nPINyWWBqslų 62*ܽd,*3V=ejLȌWLP:aCpW2 @J`ә SXv؞[F%H{ TOh3̃IDJԤ7-dR734 9 )b@"#%2’/СPBF;\Q7:.2iL}qvKEU/sA 22kClUzlj`j1?+@#BɃ/yвIh(ꗏ5ysMqT@YnQlM:0`9x-06t+ Uz'Ł F@g8gfr3;ۊ2uLejed8&SbLύ 4M!#ھu[Ag` @$X 0_j]% K c: Zo c˙QAwI>jƴϰL-1[X{okɖ| f!+Xl̑bt'V!=@uD1#0InIwە%lI[KM$]LZgb40$U(^STft:x$2L"@J'L|ci˞Cs+jM(M,8Xìa"AG:4քe|@Q/jֹ&#/]!V(ec% (tDbƌqVDfe"JkYʀYZ,F6L6/5Ħ@(P2c|W.hG2 Jޠl j&NZ#K0 bm!b ̟eKPf t3JaJ4K T0f,) I32`SxD=,~V3&ot?.;u"B"SSLfG6k l]KДUHi`v h30^1ii;!΍% !]+Lrf.wPhG*N z{ܙ qr4i!6b$-[JNuKdC`0le8YL=YC[wh8EQ?WRLT" K=K,e7AZ,LT`]R8;. d{p!U!(2 QKJeٺZѶodg˒( mzt f-ًopx;q"@c|=,kP*T&ױ²UVQisSKiA*V5łҁp3p~+]BOD l@7+`%^ 戗0v gIۗYtlS(HcDgT?p9m^e&M[0)_ dڲjf#PB@茒`6p^"9,aAXӕ2JZ I摴X^!̕3[ !A=mMep 1x7Zz:NY£+4iPfns-ɯg0˸+YAs9SvҥZfO6ju,rInQj*"K>~"RA Pn hYFMOG4!=Z(;Yj겛,-*3-E΃B"T \y=i;*ݟBۤS̄M!3aS46 ܀aOttVg>ҿ['Xm{ .& 0O T2`T7[df]N2.)KvX-\Hh56W؊Sb3*@jw|M#&1'ה 1JC4Yz&\8]'mwƠBdV^{Vǣ* ?aF& ʖ`Y*3q]~7'Y .iPj =\Yq6! ӀL`JS$ gP3,* @#q24DX8(z2#1X3 !U0+qx}! æ.ӢgʐJ#Qw +}"BJ Du+ v-$MCR8,,K ƵH9HmͨT`e- dz3k :VX0Ais<%A'|1, XN}Y4,joqyJJ~2N :i7(i,1 Rp#[.qg;8>1ȡ70* m~;Yɞ>, V2;Q8"r_:f\9FEfvdEDVDŽ\Z904}RlPgXa s'# @H`n"˵eMͶ 2%4`PXtxԄg bS8 gCёmQIlVͳيgfrXǃђȁ51SZY3icERzh[^q[ НM=R`6+"BpYfm2JgOi6R#e1+ЩRjr||Ak/MΚg|Jl\GYvA󦫑q0V(buYtVta̚0;>RYWj0n|1gd]1Gx >8f2H/O>Pd9OzCF5eJ; EaHF`zk"R".SBm21,bU(jyR`^uܐ.Jc KTc2 c5`nai㩤o $O(uG9iu-z5"l\M0ݜPLsSYf>13L/6_6,ƌVe.0̾Ҵ\|hW@)A!{&eb2FۘϤ:VQuh5$RQ U|'@^y,:90 4qXJl!VѰ w(9 hЪIK"˶RQZ$]O׸tWuS-pW^ (1H+̂>`і( Ò"(c8{nak"TICnu,D̙fM)ߘvzBl1 ؄~dWoH!'vvr8*d.$WClZ!BjE]ӹ3cG1hqb5]4Fr#hJ2cȦ)J'Wh7_Ʈ (3nJ7%1DicLCXۘnSkJgdžBv#}ftkH`IO<[ɔ.c$YKRF~):Q5DvƴL L)im/,Yqw tɮ0f6,Uj@eo21מ]S;gi/3u`%30=p=TJG6hNX`%UG~6Er,_o@6tj"0*}Ea9/y5ȃZ_6=+srrE'1G^/m)KS# hc'siAY^6.QD08l\~3KnȠvdQYuo~d*`4bR'sٕYL A蒘rto iJ>|\Ӓd-sfet;%ŔLT4YzfW쇀͔QuBA辋lZұ!-_~YX"jE"g}$x2f 5b u0;SRD9'=߀b._D1҈Q~-W4bζ1@~IH]yF Q&-g/Y$_A'jS JȤ :6gNEL"J:,eɂA|^Pwi18&_.BЖe.4Jಜ;d+&Ƀ:=i?aƢNa=}d7$ |i-€8 < d[?TnQͰ$QãuҖ#4F%ڀҲ4cr)=+r`N?!av˒' AARG L%/}00Y2PF+jan8g%CU.my[%t"󅕀RR'-b&\\aP~T"•F:j!&; F>/[TL1y=K T-S:zCf˔62.fP!)mb|وv{]EQzæOL!a_lOrIEd#vܘoz'Y\fBa6{$aF034cKGXh>}`-d7MZ% ӞIj߳(|, cU֥kѨ2;@)) cl_B[&`|iA\Ȃ^B.d1y}^lPZoUi4-3k |wű)04H'DzsyR*0g{*ue-1vVp]L)1ɔ%o\gY ^SHx@ 9"/|^9 [)RLa5UZ(omRHuXY(GhVo;2ڟDs5*%07h4l#N0Q9o d["RzOmڷG} 9] ,~,ccƤ+ATTѤ 1 9AjkUzB6iY<C۔GVL!SꜴ"tfS;a(w6l o;:5JlT7pN5g2HBJiG ^+FKVaҫЁ54p !4Գ!AfVl7hK"I\", Zicu\q"*L'&N%`R<£̈'[fNC V=&{f}`,>1Z$و7u,ͱ Tv!y4(f Ƌe- RO% 3Ki43h~~a ?#L\Mؘ4CjK~0%+c,w2LVEÌ'&ZKr#;!4hGWP'YrobU]+3eE د﷏'xF]F.!U͜=vB-F?4X(Ԟd|Ug=:߯q]k(bEq]FQ))A(~fغق1Ydagb"C-\[4i=j@Ǟ*2͆jflKxg?+0Ȕ0ARt46'9]rٜ2IN!B{O7R~swM4R&rHSyT/?M``⻝j6? 5\[F〿=䇪Egt_!e_8<)eg]Ȟti#p XכşQ^KsVkbSWw-ļjK1Lc+&44wmsIfUNVk0q{ &^EXyR靆·qD_ڴWVpn%ɌRVUQt)v4HW:4'0=Q?o^9cŞ6 8w>KT-3펛FX8st HT@FJ&GLoBðG/AL &(uzC i7T =:Ƶ|tjj>rܕ X= XG9Hda&d}{@ yͯC3؄ }-  6F~[-MAlP+ƉЗ7ގ@A?zAݎg>A#|+~X&uRB3(")tY0ء6PK?Ybgb˰ulswu< 4N4J\/ M=XGpe4`Gf-OC֪A `\6E/D ǮP36ܼ݃ë9A8ͱ@a䡮gmt-qt -d—BXP`7H.@)ju0StƝkv@@aF54fP'o½W7Xp!)OO b*:ǡ#,{䨫K;vA{`%8Ȝ_V-j;+Q,=cg 'm!OffI8:tńHbwdt&tgُA=CGr%זrv95>>y#92Aem=x8t2 ZysyXג^Lْzbsh>%l?s킶߼O|=ܜ\: ~2ߗ=3T('gb;h_iU 7rSZ$4BZ|@Ydn>;Q1Q(lZY3Tk~/否Q[y ,& x{c՘: $TgɰIw4:Q>5!0`_+)04Λ1A/QH8u#[A`wY?]z_ϥw#xX!1UzXaː`4j)apMsf2P?㲖e"Tj^)X+=竫!^tKQq{e4M^ohQ9>Sceɦ\!Wh`hK#;1}tf|͂]:aɦcgHC5]xN#n4헇b&vKwOohCp_;w]M4Pn #;{f`@eJL^unG`(R-4^m16UH(du%U+|VKuKxLoz40T` xř,D7;=2ܙakd;#X@w:Bxs*_u2=,|=$jj/?Sٴ O=K1c/`V_C܎\ѝ ,`AT?(Upn!?j4ԯ7t]9z 7>m;tjlaH!Q.lzO}_(%H멐ZML|-Dcܣ&tc|i8 <51HsY=U )RR nR-`nPuOD'E4y$(*E=Qz,f K:T-gh(m[4_iKҺSz;H0-d $@Oi>qbD(%AUuHIQC胀-沵'b1R?i"Ԝޏ d*B MXuNQ%@#&<5(vRƵYX6?t &ѿ%EtsAI+Jx91@K Ag/0~`CC3kCk&M0Dɀo}K2J B2 rh CGlHEQcxBD3$|:Q@i s݋ʯ8j KM{F8' xN9!jܷ%]鞋b-Fkxk;@cF30R7ګ{Yzq#,'+ xs͒…D-sGbr~rV,1ʰQ!)'Ibi".R%R۩Lq찐*cH&4FU9$@\]΁t72Ej 2HHreOu&RkB!dy=z 8 RCaK#zQ!"2g #ٚ~,%3dZk!QwP]I4qGϞtϦ3]!5gNe;"Əjm 1_]wU&yPh2KEB.i\BPnƛg{:22>jtj.LAͲ@s5{,b,('M/"ltMZ4 4?cm^Vo;eUi[*/b0u̶N^PdZ^0}p]./vTxZŘ c&[Dq❭a  (Ɗ; Xl]/6XmrPʱ~9'b?4[X/U/F, (z_\ZЈPNB~1Q/C ז/63N#IEX Kޗ*wH@ |ߠiz1TDĝ˪{6n/9uJ'8F0Tc謪J-]Nyr h%+\ Rr%O~i9未]9vq/bZA͈U*%TzAd^rXPc?FTpL~@ kb WBeQUjhaB+vl*u9nVmdœmb =tkǜ PhQ T J|xF򁕟BVY\q$Uݎf:7*ka+韢 2o^ ò+>H4Y<RG@JRT=*Vh'@ZcCMCyhHK"hKS&p*HL .Eǃ&dVqm-kZM]1w\jnzA*̆p-wKv;K$vdL/\<$54#l|ޞdL<A9o\CeTefrԒ8YEN*崜 B8p MQ y@EI&(pbMw5`)l톂&stoGTkeњ}Fj/"&HFcߠa[X6ﰦ^S׽ h uku: ~XhaMBҚxx5xheޢBh*u2A'O6͉ urJߡ!3&T~36Dh`byyŃ+|"ydD:+ \x?wUpV+H*.i4Ԑwd[{2od>|7zdcQenL=ר☰ORr< ev FtvxuPPREa%Y50Kƙ({5%?ʳ((:{QT248t[:(Yёoknx]DxcHĨ"Vn\|eӊf?2ԥ;MVW2P#mjcr1NQ@fԡӾ3jPPXY z"E0̒)i.^Gx9"mimUDŽmm tsF륈~!i" CjA$zuʽk6D%6ARGƻĮHYn U$ 4آ"X؞ l 2VQ miၓV E YMD!Pjb={ ,拏oKWtsN W^nV:xmw.J`x}7#*"@_ (T-qXXٚ3. v~(eg%_V1U}mēͻ i{fsulB f=4!"S{mD6 :8]4?WTzd"Ņ@ܔ{H4bVϦ|-XNHm_ TB)aOA* 㵖-^ \PBglMg6jšZw(:Yhjp"5Юt|+yML.֔мtlEIxu9ț4,}\_AO 9ěXhn;zel옵IYR /t^QFdwu\.{Rɷ':&0@袘_khV{Y[10OCڽ4s]ݍF􊳺Xu=&oِ,]m!y~P!Go<XdS7qD-$zy_^v9MIuBxΩ6ТLp( J< 8.-F:%$ }5^xa˨KM'?(%<NoRԲIs\Rj7^>B'EWQܷ^(Kl/=.~vV"r1܋,9T;  X :P ,MҿR9$*^)ke  w-!!RAhG&@5"m)xHi26ҪqQP2NƲaxxA\ վu?8>x$=,KϨ[6kRdB|Q !j^M݀˔xEh!б2 ؀pGAny-2L\q>`{rdWA.9G3iH1OW ;"L&hfʃ~^ޘJl=9=^pW].&ǯ[?;]fAz!5sMU?bpMK !\KUX:5I#3Kд$t{5ΊTBMG<[B;3uqhX ̒c¼jc~W{6z J5 lvq=qsسפ+P%)(\oXChP=”E:2\^I#T8Q5h1s󂬮i)(\ή}w 0.-#੧xY2k;>i3"bQ@%c|'{#&SҘb~Y~Y ©p"+ZFx%5&ZpfbzJLOS * -P 1|az %QUT 3+A@mRbE+"\#Lc3)-QIVڝcKᾁ&Ph̅ϓ~ew$*=4dt1dD_BeETC/"t-\tr{j#tLR}[0EadczK.a 9MR,+?c^:"k0v0d0T3j QkT-(f噳90Ǭu^;dbϑ*e C mViUl`X>r7Y'W~ 6I!`T ً$%:n$,~=:VErnA$p1x@r>.(+K„Tu0?paYhFcBYJ^*XYHp6KH7#pC2<@.ZZ=>Q9Cx2-VŖ0(ti)؎դ s$&f'tCgXgƺ ,qu5WkbBФc'tTM]ㅍku:d%q%PNg3*w&i,d= bnJ!v'Je{G۳*B" p b=27wT4b8 %%F?I'C5E- "ߺ%p7]R@3ʫ_ӑRs]k@lO.< rˤXǟCBbSb0\Pԋz]?7/E{ z D J! . RCb^o1;FW ɹXI <ƞˊI UY؆wcD! (Bn1F+~'` Su\HI “IB!g>܌.NH:̺GjDALP힅+ 7 tAC[ke¾(V/(~RUcpp*JJf{bg`D4@# ZE9ɮ!ѳP[q{@/gPȭ"=d*ƍav Tb.<>W7#ޡ:vs5b߈uE-JϜ r=ocͤ0|cLx G(݃rUFٽIq+1ӨzE&QU'TmCnvK;BH*rrQrC?Y *ɩ I L&54@+7PQ'`p1Z 7^*eb`_v:M&$H^:K;?WCd0zX>.\ K pBxи8 bΗI}=>,=:X_,~"#ZBM~A:_13ͯ,%˜$  5xY|B]=(;ك!d{ As͊/j@s7l.8ԡЧ4-28wU[p^4Ŵ;[*d: rF\DTH~ /~.!UULt5mt^&4cLѬHn*inq[.r_f.c߅DZ$Jt$&| i@袿l UwlZRF ww/e+5_0Ja#a[(@-)l OwlWzRM|nJx6O'[\u_ fRo-}J:Y[1՜*t-yͱU"O\~쓏-ф/MR|<_SvؤT@0OǙV T$j' W׋r)"i"(' [r=K0 ǚPjUhֳx"S]+%Py -n]x@6㮩TS^Zm# UD`cG.@?f.|Ax\rGDzM+q ZMOeUQ.s)M%"  zwަP}>(xa ކ (NF=_OJW>6߅cѾ 2啭Y^be"nd! PZu<~U;" 6<V2@ \!v#&&+3*H >TBSԺ<%QoS&('nR+e9kHi@*>@> A*M;Ly4GDihjO@8E%Ǫt~B˱<0+p`+MYI* @Eӡʶpb~ Ov\GOR7 Ƶ7~1mI2oj~w= 7V&u<bH"i:ȍSOSXD7#4[c}yAWXbo aL>Gj/*-4DZhg* mAl_hō i=kov[[젡9Fp[3 NɵsV0Ldc=u(p $_ ͷSMP ެJ6ży!Qz[ߧڬR{wK8 v(鈜cSbJ+"U߃7y`C]zFXH,DzrEyЖ<0B4E>Ke0҉pUΝӰ| q/mjTW%J SL79_ ۏȦP>ĉأ33nGu 1ئ(oIxiGŇݸ16t" '}%S(MVe@0 >`DTQ(09T)E\I=a**yX8C2?d)~˰9H]?C78(`]0ܔX& {=lh;y2{-!RqsQA7-'BkˤC%_ 5EGTIKQN+\iC7<)ڲ}u Cgٓ"a#P*}6}1oaF\o{Rڧ Hկ]l!y9.}8;)[ƿeG1'ߣo)-~B1)~SWNɹRA^9YAU_qLc+T|}\ykS5zx@ hg,J+ 0t俁$32rQnvl.`νnXVh>?2&&hFhHS¤|IT˚A[R.h Xz0,*g:Eel=Y*2,6t#c2,we]7#jS\OH$꒟~ZHWtfumWМt> 4~#ҝx]m}QF7s[C[Q$XL "'V}YӶ^[ȋQmxBW؝ lV8;hxJbrφ.OVLRj6mE$UA>ւJS"-:f՞T,0B@\Yn0Et|EE&\ upvp4 \`E56{~]]ϡ DfzJpɊ! '*)j [E QklKsO݀dbڣjL[n6#!\g D߈q|bFˌ>>;~W8,yvȤq'Տy2N2? ʑ6ק.]d`k@$mw 6j7..䐤BCqb*׸T!#^<{>97J8[yH0"ZZ Nۜ xtЊ`1.9Bćo^iet ,Q2:IӬavN"20VRRpqb2K5j{ž6f]fS#CGv`0ڈ=F =A6Lj L_w!Hqn-[ DgǕW^aIi1}:W̲V[̂/~r9o# il&CD@YmZuڊozKѪZ ąv3ȬC\s-O*8js%@IȂkļ N!,fTPE+ FQY"vgH5нnBdZ*AUdzi* T ;sVt5n((v D,xfa6=E]qAȽd4}l3%bɹ(nL˔+h9b4f*Al4xRz HPDjS6xj.Zj9$BRn ŝJo_GLZ /IHr@RjԴ8?f".[ s'DAZO " {{B%!+Vp.8?"u]KHz)e2UI.ɭg _b:f/r=$%ThXn]>F-~m#-ze޾#f09v0!>ZB63XЏ5Ex))J+Sp C\N[ѵi&mZU D82sO `Ơ@ag{3MlʓD5oۼUz1u5,'8 #D{!w4 L _ Q hٟD^F"(}ucco;B- 1xov+VJ5쌘غf5P}`C_qvR f}=dF@~P6!UTI}.>2 &јͷ_D&S+(ɗQp&bI~cϥt&j0H׽W\Xִs MktpO3MX`?hP1Eں[1*`UpByZL[1ԄN1ߣD"[B︸6ΌY7Kdlp0f]wds/$6Q@AfeCb0KW=CLeý4TQ$&P$O!{j[z }]uhu͔$Kq lm"ɇ G&Ll4l ZDW;7b)-fLhXBNe5|Mܭ/0PX'Fj rRJ≃Inr&c0KM|&&`Us1%2=uW/+"ʩX"|mӏs"Y1:5´^֚pk01Ur2CA(d!8sEomم 27VIe&5>6z25@:]mඃ90j$n8t7 A` r6Hz؍J31([ D5s \ӍO|]7[0F!2Ȉ>$ }9GOۉ=DIDi",|_[sQ"%GPbT@ZW0&4F=.S/G7,sy Tew ~E;X1+ >{`}MS qi鉓+w6lPBk-TE67z5j9jbN0c|}_W\Iՠ@;,QBwt?AdeW^+~3czhNajLTtMO+x}9N}ym߁dJ,4WLmL `-ƌhq 5{):ڼ!,52,_HTb1)PRZDB]m6ٮg4#J-~.z]hhhwS7 E'ے;7}uGs9)h<VXU16)[a * Zc)B9iz O|܅| ,tfXu'HȁXd+r#S7nA _".7M[F@ ,0{Dyl\fԠQ|{3n$BW7偐4|ѹMA+irLW1⪐ j^Fkd*SnhdBt 8m >O0t$@y/_sS}/:^jrbz86S܇E(ߑ[tݨMqmmm &C6[o, ·.*6;.;GAO6mmKtQ"Ps/A10#[rwV҂0`)NQRӸ`4N4!j3T{ 3f⡾4x'7Hm"zIu_Km'9%L>n`RL m>uv.7wPG{ ΏrDWXA/GI6vAiwd Νtkɒʚ?gŵY]%= Y >og|P*a(0N_Dq^ڿ *AR2"LL4r8FhFÌXDoE\yȆUP/l5*Q|Ü?j8G@TT^3SLld Īx |=it|C(0xuJ7ϭ&Q$#IVwy)_ k/.ع cPf}:9F߾ؽ9ISXv硑ozFSc%af)[i.~4.Z٪*ZDR儢P9Oq4>ZY̱swT97>s0˾ i <%!};;ۡMb@m@'e8oB # H)]V(~1k'u!>;[pX*Bkxa*ctiDN&F󐆬$:%gRɡ<3jwfI,[PnU月 Z:l<ݠ *r;PQ{pҎz0ȅ<}}Y5La,DSv0apS- /s/Er|ƘB32IGiD!3_iqaS<ͷ9 tT fՅW#J*]Z+15\$Sa!['KB1C Udepjvq bDk [Olb4^a 4yU`*PboG7h]XZˋͨ5=T6iLb쉨($LZV$&p^`Ty=yR> G T 8abn|ƾtV)QFV`ΥN7ki3Z)f" e9+V ,b[yHآg9^-1 Gq--S4-0isvCjd2!h "b- zlF&v==ʆ%X۫==$T ߼.H<BuD/@Q`㹍ͣR_~K'3Mo v~`;X VS*\4G" ܠ--Έ}JT_)ٿX{njR(=oȺ1P-]pLw27R?4,+({kĹ陼nxȃT$\ i3j=lw5A纍yGBY )U'e y3wΑ%PX('6!"QL*b&ŔǏ1E@۠*'N 'ehuIQZ0Id;4EPEGWIgˆ7Hbz OJMcq tX||Xͯ%2I05n%\Hz#|unmСJRghZ>P{a4@B@\Y yrzY𬅭?>d^NoY R_iګ֌`s1ԨuM)[e9TMrSx_ sCM+ :~EҾsALgE]U.*paR0#L@jH_=aEp92l ƪѢ3n`o# -q$lVUG#H7p}Pϗԕ Ln)O[J @ Wc;%ecW|&`_J%d&Kd]2J +hkM"#-A`4vo|-j86} UPg]xc[TŊ\sJYf 1҇UVjatw!n4O,a PKX);wzl[8Q\Cj@uQ'bZwGel(U"E5P!4l{hIm 2"I -rv-U`qe%uuMM U t@?7]L!Xktt凉l{Uu%&_KyP RYWU Zؓ9 \#>L9R``+aRh@,>t/G4=ulTsI4IcRZLfW,yJE[|-{[&;o5kK+J4mBAz hhSPڹw ܭu!5a;X_v0 FoY3W,=A~GY*HSgy]Yp9P,;\: Ba u?>@6m@qb](7n:^ּJ[Eٿ>.+{XPd&3sáY,_[_?i`F$JipLB%CJnSq{3֑:%߬~X|D1(S'W **whV(lw53Vgp$HL%"D i%aJ|4}]9]"^ 3"xd.;Nlt |7 '{Md\[S#xE󠤅P@O./"k''> &S=+F Fhad@>Ow Ҫ|Q'U>ӜQ Qe__A\@O'Tya?"Fn:n[1yzОs Rf>8,iQ*{7⚽O{, ~( .ưL+?e.%yJ.e 1wSU;"'f vKJC)~>w{ۓ"W z_&`zybK>AK $YU/us9fw˜RRR2}},2nlˏqVCS #daAݿ^ZZz9I ])ɐx,MiG:&8m(,ӊdj#${߷h`;FNn|7 Ua?(sj_Ilؓ]DUѷ[P(ٶݛ+&2=mWҩohX~tN$F`Jm=jԧbhize <*u8:Q/xPCsj=B׈=O!V9H# RPxܿz^̵=itU$e׹Wl2Mc 1چթ xռZ( 8Qvaߠj?ď VYz*z?xmZE= q[U7OT6P5Wر~%//aЫHLr)U(MKGK Ti*P3jJ[rNb_)8_I M@\X$Sj`9&?iYRpĀJ '#5/sAuxݨ,̠ @cմ E-7UDxg%).MN8w:>w7lL(VC<x;i9Z86!rb"/;Q d`J,ECvsk9&i*e #G1v pӦ6`$(Jݣ<7JLtFFy3٤%c  i0IB4MB2U,SP.? Z{*Ew1f'%%p>]QΪp"!g:vߡYx:q-aSI}T|mTdp:Eւ`,|h s[=}7Acgc5*{Ezx„6뵁Oow]ȡF4X>mlH4)}&Lg(ȫ NU< Y4D, >z $,:#y'Ҏ[IPBznv\gݖT+@з]ף{+o&rQ!U-(0V!bү{Ц-ٍ$/TAcfiUsz*QJ9 N*6^9 ]kKSGd:-E ( Hʪh0{RNa5;;2Yߧ¿v\:1?"Nlns2u P`LDbEv)d*.*6;/Q9.wm^u!iDn'ŬCz_4UE < flUBt!4u O=KQp0F0y^Fcbށ2{Ya")\K]q( ?$Z)R:`W]1`@S2~[vB19eqz;V y =u1ƪP€j T0jF?(UPPRR[Kg ln>!GO_FT2ms1C,SI-\j5\5c# =u|}x蚝D&> $>ej5&> yAQ06Lv@[6#yeiAEӖIuJL\1f偍O6iVzO9DzJ]8rdEM_3wc<>6;$5O22 Lf`wm3tDt:h^@ @%(]Wdv D[U Q,}"]M:y fDtuŽQ @.7uN¬Ȫ^37:/B1}PliU hiuѷy;trmRGiC0UbPn+]1rRS$~#q @uI`pMpczٔ@%OM Z~ih'׌ձ{Džb֑6o$u6 ]76խE-9>#š)] h>CxHLscV@١@wqBJSb.Cf7(02 kc̊`'$%))SP5QT&|E'Ѧ_sC%̑ԨV$҄R"JխuJ:P 4tfcCDrTE٨J'`&Szzx@=t./7fNhbT)xҡv֐q4{kmr8D?Hkɓ/o!V9nե KPT  }BW/=SĆ 2NטGw(?s삥S]} wDe !sY&*?$[޽9Y?p,EGF7=t4Sp‰P\82pe~2Z!QM R$G/Ij0϶Yޚj*0S$)v97mDw*ƌ:.7q)1^'V=wU$EGAH“ZO,C.5>vTdF~A07(41f~ "&zP/xuFipzl&f=S.0Q"Fw4œzKd5Fs,~[ g0Ue zJ~ 4aP2JNmcqH~p[{C6o"ZRJIM0PM3ObAK6wV p!1݆Y2*@_Qk-R#9O&e3݆d'8 Gi(6W>`~[@#A Tpq`617 #\;UXf[zB HD1nKշT'Bt5D7XZ\sWzsl޹\r4߀ȱۇ N0?ʴmzE~< vOФBQb1FrM3: 1|h1,(hpR sZ8Ҥxa5d 9EeTi{Egԥ&*#4؇@0Up!|a}mzj txqMmE _M%MxZ:,H/LHO]Sv'@zW7֎86'7Å34R6IÃP Sd Q894߀xc" m,˂ BfKsiAWXx(U+8]Wv6[awZ[n`‹mr#Lh1ﴫ]Mu@p~sQD9{UX~4ȹ83 CDHWZ$iġ0Ȩ$(t (o<`\ip.X)}NفFw(p-&B:CpeO.TdpW2GFotCB(jޓg+ַ/DgFp7\EІ;@o24/TWxm[a)cݳ,Ceړ~bQT gF%}UԳ':YRS#X{iZ`l+AזK>UvydFOkPrHbrkS3 U*ACs!ytUwSn#DFӻGY<#8Z@3lw[;0X8({ٸĄWMhǺISdɐu哯fBhaZݦ5JT$tj FMPڇ}sdk?iBDh$.Wh3Q9\4*ζ6-m^6.`7{%#j-}Q\Q& 4jΆϢR+ J> S)vB7Rc&$U˷ h=~UalI.*Lf*, FS-,,Jܵ_In^l)+&NUP*I)tb-ޗf*A_-Gbc/pFiPQq;-Xzf+E9fkzHej;[Dݳc鱍b ܗ=xW`rIv+JrW3U Wı([F,)ˢ&Rb9ZJHݹSf \{⣚B:&g; }TKϠbbv6Zn@+o/uY* JLsw5\FS3 Jr\h+TdDl lrz4_Az"~t'CCeܡ=)ЇBZ.4Bk8SrGE؜yxf@8f,.cRSP֕6퇅h4X‘USs VOSp}j5(? ]L-m8ަ;f:Hϫ%h销Q[,p{y` Г;z/fD/~VҿUe@L9T6n/#Qt\R)XR6M7CB*PPzڽ֭];cO7t@Y,5"gy'B;:{ВETTP[ݦi\Sq;_omC\²QWXoZ+i ˔f&e+YJPV-)4E!Qa/DY[*K5ӧ ql!+B]!bA&ĥj bXWGAR Dѱ+40cRТQ#ue]&%GfO܂[>äuL+G rJ-z4] ξ܅;s/ʳt5DGrʟ_1WB/G~ *~뉃#,`|{򫃒gg38EmGU [6Z6EVk8q,no7=(UAFE!c߶E 16Af^QV%|p7`w=eVԁ?s)ෙSn4X!3(籙iͱ%zIJ0%eHKrH:, =lEs=r@'CmS:8h*19ڶ(h LfOui?q sxğS|[Z.5wH"2o*f_gvy-J{eWuLٴ9Yծyh0yYgʹ۫~g؁ &ՒPu/jcz84L5L[%.QńgD!!;\aO}6G* ˄Ð+ͱc~C[]RuKأUmK9YMGNc@E **Gv" `Vɡw4\g향 oQZW<Y%mP?3`9YaѵdݚURs3ݾwҜfx$!xZzVnr!jd8̧XႷf1%jTb*΁qS+gz9&Եa_sRcHb:+!f{Cju+8D{$jh>WYn!=N{Njo H(+V!@:[bRޘvlǎm؛^{ji12Q>LCV~x5[1a̹w%Ҩkm݆͛KtM5lu2gGzJ*ccxMgb  U@F >$̬`0w=r$ɵޯ+js>'flF~c*v%Y@wscǎb8H?;|PVdr`S7_ [$Evey>vCۉ NϹCنlU6U 98 *Z<,HuffeˉG} *? ِ5-kd?kd7taSEQ=3@$vZ"31R A*!u6$3Ąo4K*,HY(ɔb"/E[ ㋨C=#HQę@ӊU WOK11ņlh5}z2@1Zlԩ# S休RL%AP3wl笫\lۻIk{yCTlKV$+Z6\Mm\dOK)%g,\ H"+*YpBA$d:*&=tMIjtaډ5Q3G9QB5FS+DInM] eRzO >bZIЊ+D"¸rR;<7Ѫy"!`; j ԧnR[#"dH44>o+6$kXBj`ǹ&t$r{ZԂ&g,Ϊ;,4LdIVDN(@yYn_ݮ'BA, ' ,tL 5g)d[sE( uci>=bɕ2vOi -c ?w`(6% e(18-(ɖCA|()sA9K -X:\f.3!6X;[d>cgjgΞ2 ,fv%M(Xflͬ_ͬʆef0lۘٲ1.3[7folZ̬Z}03W33l]xfVI;ﰳicgjg1CWCL8ZcAݑ>o m\ fhC7n m w~MM0qci,GWXk~u'kYkͫuUb^UX**yxtbuc]ƺ<ֺis;6qcZƴմZۦu% +L5u2joָ1a5iZ6UmBmմǾָuc[WU{2B1"TNWI*+ȳP!*ڿ P<$uy}Ʈ'^Kwc81vaZ3+D2{cߌ1ㅈ*ymƾv*sN]z(0vYFJN, s bWAe9gV  ʣ#]nuگ;ڸEys;~τ l],Pq3+l]غoo`JVAm[кaBꆬk Y'-d8Dօ Z+N7hkR0EкB}7zBRuihsuY2'uuoغSb Z.|Lк7[ӄe9U Űu~F [WEaeCހil}f񦶥utP Zw Ⱥ,|[кWZ7I0)dt37Z$arx [ l=ށh6 '| [nu)#)^{WG[".ML#]訜wnE +&nкpsA Z97\N ZEк2Yu6 Z`mҬ15i\I}1˜:+ݭະ`F=OJw+*4aR[f|׳q0s[&fD\ \W4%peZyڙZN%cy9u0]W#Tҍ_ ʾoi g n:;_WJ|=W#8Xq %a0T*:D؅v{6}Z7v7Q|dJTY`W;=1몋)5٘D]6q5`5dJY<vOv}zR Vأh\jGYv-+#`f naO*.]ApPoC--̛Pb1Gѐ1т='!G+%i{?/;m@V0)nE@Cb pwo Q {hcJfT!%*Nl\M]U<Ȯd@~>kx"s?L&q &qu!Nr'sjIv݋P :G80 O:a6+ͩ&0 v?D I1!EOWۖv}sђwl6ʜG$Y?{]/]55{<潜DUJ;?N)OniхIɣ_ )fj)p$cM9 Sϛ;kCʺ.G3U ^&5/ڤY釉}q{kZlr6m[^զRhRʦRU\bTe-eUuH{R( PU"mJFS`\7jmMYbjX)ݛ*B: Iv(K-?m?=H20-e,M,(\^.d,b\OZv#h$Iˈ5Ē%LV}DI@Am^` ٲ Yl%@&z.,d7x Lȭ7$6/Q)S/>(Rcd^)H7F SqhR.Wz ÍjeFL(syZWmwa{:LC1te q] rپK*OU[$`E $hCbq͇(d ,Ss0x Uj J̒SC[,yL*Lch!LQi4NF A,VחL^URBx*#9_^-٬΄eY]0_^%p2tN 6ActzfݛBn7(rHW1 oK9]i'xZr7iiNŵ`KW pUiӪ4tZeff7sn[fA%vV n7\igQ {bj#\PӆOI8GWa*R.Z1jαbԂ0 No0jeN F6 4Dݷ5G5jDUa\olD I'aQ-u}Q,֘)w-vM@vN)mD" |"mwB]o#Z-MW Ati }-FMxbtzF-IQ16w zc8Q3Fܳanӿ EӉP9#LKBe dXv BV_, Ogu9v'-[+n:a 8T$]iEBuh$ &%RnŦrjQ.pTo2uނӜ.dvV}~3PM2w-:A7mXdfhiŪ;NQNx=>ZX'Ah)xZ0iݬK{ħwt \>Ok4+-Z4q>O֎vf neMY?7t,[ncsg*ٝƦMzAS"^شNp V*d:O{Ņ-2-Iȴf*-"I\"4 4}=g1.!W{"21abe֊-(͊SfICq ͝Wm7R]^5a)^.VP%F%HWSDRI4 %R-]Kӯ e,9+R fHTY> +TKy@U\2ݰH:yr>v>5JϯHwFr!/],R]#k291]gH{֮ƙtR6ɢ ]#풩T!+DPE.#ume !Jչ !y݇DQՔ[N6vW>Lb3mSIҭf0dKLb?B@AXO 64/VU3nu_+7H-qB)֠`ud'fl~ &<%U뗗SYM ʥԦ _gfizm%֫gz\5Mˤ/CjZYVF"0fzw,T,g|kbcov9iB:&%+=d;9IrkwCnevlUKjԡ0iC0\qS!J_jJMQݍԊ)I|ꄙKUX+@p~-rV+R4GLI<,5Kq/. y"LZSaBk`Ą퇈 nMh xg mƇ  s@Y!K=@s@sL6ɽ0QmN[5VlEIB1*ǻ% M#Kۀp)[ƜL]|eV38iՁlefZQ]tbzfxIdE<( nuqTҬa`qtCJ ٤?ك[%Aa*FZWuXM&f+/IEW辔(zdJ=,^|J9B%'"e0SK 6#{L>BIoD\~bѦ+csvnEh0=o*dORyM>*Nxk H9W o#v3ӣ Qv]{bC` КgWY,*H>ߦf8SdBӒw@}k5PgU5k@_Xz33E!)ʊw>2™oQBl-`( d %u@R(U US(W\{)%GcO&-(_ ~'KӔ[i"Q. g-gr0ZβArXqlSum@:RH3mS5h^wy߼nF*\0h]r]DU,9R=kZԚg&DɑeL9n3^Lz7ra26{RNn-"W MDVqpZvk2hտy `D6MeZ9FDaUQ, M#"({or`*m:tw1h)ӟoↈ@ gD~G\X]`Г:tFo3nYu&A?B{1d-TōU˕["RALd\@w@Y ^1Sy KId~1†ZP(|dTbT7qrͶb95M*J h_Ź7"l*H}aS.#Tm&*S4ɸ/"ls"̴ܴ “\-UuZr9!|U/FN0dI//r|'Jkq{N >‰b9 n2vE7հy'AQ#>!>VWiZ9[-:Ccvݖ)ۯȤSo5) tTԐ0I 0WB+7g '7Xd*14O~v JbT&n(N e7_ fWÐD +s fq~I+U\_#JW+3n-VQrU.IZ&c5$h3  zwn{lbIn؃23c/&4HvoVs'Jc&BxSUJW9-JdmAÜSE nrLyeϦ'jax<{#7Ny JMb.l jiIDv_E5R`p&HM$`40 D~@~^.#5-k&nnl}I&D_Nf1qߵb$9ZrnK[_`_jXbŪPbZ1{t ꁊ."$źq)' +֕XQdnLHRZ޷Sں[ðRO,0Òҫ7,3ֈ:@+$&3TDW-2 %HP`鯊mjkQdwӨ sMHpZ$˄K<4琅n941q04gu՜ge#}I*/:fWoiÝg>avsz#W25۪HJf()=$DyBmt&|LKIZmjjt8Q4jxX*"Heig;0a%Qay-#,'2%B2DC _qY y|v" ޜ 3.B*fP`*kc%o!~i6CwV{A."c,,đ溔 P 1g| ݢt(3Jt ,u+Y]1YdH< U/Ip!}>hjk+{^yTJyͲL{ oʨV Bu,R+l<{fMWo Ά&kߠ4g\^2û벡kqb&n9*5xBͿH@6-):yaJxkR"7i uc&TA5M!R3tvG5^}-&M9R׌)Km rTOz<Tl 3ge'| !U`<paآ HeT`"dnhL6.e-S4Y#7j'RjNO\ܨa($(yyQ¢]L5HT$AQN**GO,eJ\%Y:HӋPBX- !he*Z'|ZdfjN纗ZԢ=PI(wIx5`p&THdɷ h[E$ڻHEĖOӯY q=΄nnu'ʈc3[!mRƂDU6SdkUD"ڙo ʈFm[qpr ܧշty",=.5jdYyX]&Uce7{$AZBTh`)\Љ+!Ek@{I3 EZs:t~dܪ,W|鰘 {Bqf,D6o{l?8Qc4&07"?.A.|Y_O15✊"&9X6QdԷTo "i41nxI/j6PA?.{ { UMM\0$c "=7)5?%Djwtfh1je N- )D)T / ;&ۚC9e$/B]َr[+㹃'fR%}AWLQ)7I!Ms*We)共<۸sLtIir}+QX6YꃕO[I*HoO"' K^yVA40T!^ZeTCr39 1L ¢ ~;aq;rv'󂲎*{ް&/h/wcLv&-h~giIHE^83ΔcaoO˸{ڑÁ7üF&kMKp_႓5W {݀64( U=4,#UA:iY3 I) Qe|jX<&m?#\ko,ّ͢NE?K)Kks! ӡ ɚxEG?]mphѾɽjF_! ^ ?63'0PPpKhf<GIJSVUsJZ[_uY_S:%*IXs7X/<lqeuQk3:\]7Gҋ7\`aG mo@f˯)l?sVwA[α5AOl]CAcTBe m `@]VODg .F[M͙ÌK媖f[&SS@?4IzH&)7!+Mp@^5J\EiwG{xbkeJX3NZF`+* v =ԶAa~))+2cCFT@ET lD**06ETxEhE=P ++ t&t:eFV@K /P!u8C4@jp`b>mbs*09< Pلoo lD?HS@ 噞+  %~;kwLE# ;"ŐN) _KQ@rBݍO{֓gTID9ͻeDω4bYvI1~}[QlJ+Yay\I 붤jtqMI|vW% I1+iq U_B:"Ԛ᪡HdP>MK$V r gq-.ٯJ.»PQg]i y)p.R唦7`&Ti [I.~N47:?j"Ƌe`MDmh{O[> 0B}Ywz$@+$!ՅР,) rzUT[-wʔߖ\{@D/Gۿ޿y飽Rdr.t50L#v@K(Tt}Nfz|>f781GG5;|iX!^/Uǻa!gخ'򞇧UgG8x۵ #b_s5u4';QdcAn3+/+8]-ODDžG?.q0 vq7"1BPs\8+43{'̷]pɮO'㸃 @EQ}׷9 $? (M\1C8t~5|8?0ןirѵpH68P+3E|%/mW$}pbf>T_ oq,<~,T%x |?㸁r|>.1b??CL8vJ9}k럯߽ےIcf:+{l;lkU ̪sdI*"-Pp ft- )")c_ZKϛzNY{@<$8H BmLrLQ1 f>>xsTKe&+lɣ/C0$0C|&AQ# Pa]9n2iC/hLl$=ML݌_(2ʾ${BP9NdlطO3::I 7@6-b9D\:hJ~i.$›BYV<U{k:cmD5pJT%ՂKz\4 ,|#F-ytҭ{K1L=Fݶ8~0d@l+O47 ;sMmDA'=!#AOqD8f=<4tTνK3w!͊1Lco3dօݨ0R$ Np|ϓ 0lw!~Vpw>0[*z@㙌AOޫAcB{C`=N`;1_I-(mCŚN# RRcV@Y_!q|‰9UvR9H,'mLelL<_x[TSҙ#@=#ɱ Yz8@V6K;UuޓIQpV#+f "zVRIXD2e W:B\*p:tDȪJcp0I:qaI3n"@1àpшvPL(xF\d9ityV |06NlcPEJR?5p#U6G,1X,brd+7j86 .JSx 1EL43OsER O@hX<ff F0jI6Gsoq{˶#$1ni< l2P AsM*V D!@4pN.|"iM+I\ZK^@v=E]y$"\]$ڋ}ZmdD` 'ÍK4qhUF$Yn'}@ *9L5:E{{vd?p|Y]WEK!^SÃ'd]۸&&<+ DDh3$DfYvOٕ /̮[`M B:N}'nvf*`q[ö:B'!9Ռ1Щ=%;DalSJD\0Rڶ#$LffOeb~!"a*fÄ.s\t@O2L6_ʇI/V^'m~lz1J 65qwôm?H D*:{smT=h_6)Nu𶀐 S!q CuS2a-cFRt 2MrE(qJcLyE:(9zH >3Ew):pȜ -q;%K}WXK$x.# mj`dT4$'TOep3"u &@agO7H:7fN=A$eDD'~ cXcR382pcGM~r<`B1elk}HjN \:`- 3qZ̤&ICG3Y?<^*I=ae7+e#BU"C|J,&eSEdsPL #N(2a@ dn %YIyB k 煤]WOҞ{i>X0-z1xa*Zx$=`u3bp#xU*P.v`**N,M 34pF2i#KL*-l 0bب' bc 6 I \i 5B!Sli`#҉rQAM1U"S[QIU!Jr"^/4`c 9. 1/bƓt`|,uBP*<:ߍH2),+`UZDq dEY+ 3!C]K=#j8ǀ5X1X?P6Ak.&n.'.0_|RSU"rO&;KD khX( '*W,O)BIK&Ҕp4{$ADkJWcDA#elic87ʢQfLm!Jp<RUAĄ;J}vN1ȭZ7asH&%RcAΓ^sL`u#P*1)b6|E1V7 ~?ޤBkJċ8U H2c5D92I" D>dL:J@xa v2-k7ЏTFƀ^Tfjюd';ԙX҂tX@pcqɛ "&uS "wa@H,C., z+b.I Ԋj[eƀ9*oE7ߢu~!RE5>(wĨII4c/ gh P<w"p`Q։g#'?(]g!q仩.9z<,-]+pPdؾׅ+؅ +ÉGƾݸccw˰YNԎ\LF .} "*8m |qY1rcV\_gpc;;մ;gt$y0jFVá \ե NO0UiUܰ@ 0gt@w[2 CM)b;Ҹ K͢>". Kӥ܀4I4YLJH27֤LVֈU@f3*EJ_k/[_8mU "Ӏ!6lŸL>1.՘دG7 >YfNQ3 .8BBOnE h.5ACkYWxRF%~7ؔɰ6*a eՔpHaSyF9cWq6_Bfx>+8danLN8U&)@3l#=eu3}0Ή)$ŋNE#9ZYpҋW3reG 4-R =^+](Q_X =LXQnj!^Z)ܰn%RdY&"%Ʋ]5BAtFaHRtPRfVa лOXҍ$oFo&uվ)(574ȏRڱ3 &) 4,XpA_~/FR\f dr̸/T<}*ɼd= =]L6V0ڴ9ᩪQƦўDc[)3:(/2]JOBV ݋cnR &xH$ې%]TޤIׅ݀RĪn1h4΅@o+T )碎1@H<ly= "rд)^ꡙUkeKBEEx> 1FXUH3ckD ,J-r{du^nnjJ$\I%q_y1<>>:aljˆ= YI /F6doMbRK&R/ P X='QĆE%ɭAnDT&YaǏ3x Ȩ M,>1t6^{GU1*9DHȸ ٳ8Yafuԑ $XXuCV@LQRQt7]FvFj ]CKH<Y@gql [E2>X_کU@vWziw4^白OڭJN <VD5/rr4A06"ij( W('67CWFOHY ;*9Äɛ#Xvh 9 |A+l)  @#Y`x%;+N,mHLwW9+s5X/[G wI#!JYAyr#E*Vħa=Օ(/δ;zǖ= FҐ7 BS]4auM$M@c㛙1ou2sN"V3[J0SGp1^L|` 빳vb33S3Xς]RN5BU%E->ZB0.N9D Yp6TFAkE•!b^YE[:ԧ*R CB5+rnqaai<)R;z*^A`1g ;9)[V@kCS<'C@KD'!|pgϲa~!헤;AWC 32ҟ*/^"t 'J&\E| Zמ^4D_7#HjKdh[5&fċ^LzM#R\.Gc + R)8Fݍ<9pAXdˊCjCR aT10WoOd H&ݦ3EF@;TEUGi{L֦63SԱhp%J7~dWP|;1@ڒQ&%ճ%XZTDhcp 1|(9gy@!2#,kSJԌ |1]ݢhQUJFi#b/`ё%v,*TLMF>2? iŦeBf9Xce<@y,oƬNh1H;,?Rr$/&2 wt}Cev7ydF(SGX=D[fư[,zpDMīGdtHwgijA5G\Ꝕ˙ :6b4pq1-M,;Aɩ\ H哀%aզO}E"ldޚ8) bIW'T,A\ :D7Y1B$Gu$&bY$R*6雧:ؠANT`Ia#@@N +R[M1w#IТAqdܞ0yjkģJ7*ȃqIˤۨa'*[5, vlj,r&=g'm8T>7R$lAY`pJ>eI+/Wf.rN7P"ӄ< A&Z [&h-U"ET)NL^X+|:GLibsǥNI ޙ*j2( JHf'@w, 7;'f95ơ~\M%Zkxa7'ʪs< Z.>2FjcdUcW9\&" d(`2=6RBQz\^6a>G$mjU؆&@5ݙ.kUbTK'5wԬ%r:h\w0u0c)8cen=R"`Ԓ8,,[bQ6TT(Aij>U$GdtHˊΥB׊&HO3fg ec<&4YXUAx>6Y$u$^6F( JM?J`tT+G}@g#8576]^.ZD?Szp[/* 0Aʹ\Bg\RzWpn#7~jDlO9eϴM@. V:tŰf< @rZ>OgJMu|?q؏Qv[Ȟ2#JZ%E1l G9P=}T6WҍcW\q& Wx{@, A0 JwFDZ&?t>\i|;>?\,|lJ[1 nr/@vz(y1@6y˾8E-lTWq0v<Ǫ??GV_ mE&C k<cMZk9$Xεi9G<1<),>%djr_&춁ʌΞ(bCU #RUO]@8ZvAa/M- }{; LW6A-WGIOv#i?TI~ z?r;o~5@L]E 0Sf㸢G2ք*p|>#Hn~"w$(~9S@sp<Ж1Q<2*sWԸoo}mCV㌽+Pgb8G_γ7IӞPsewˇ^Cx>sUSF K {%*9LjzL\7̋W˟0tʴз8؊*χ \WxЌ>f^$L,ŒoMמ+^ft_UbX6><WKA.Ǡ}q'}'A) h<>Ta+ YV)}q<ǭZ8Fo\6 2usA5"}n\".blaW@" LB*r|͠NA&y X(@vl&Û+8F4X|Ѵj~6rL=V0E;GQ@gL45 Hql ~UBí=Dǫ`M;ކ $QSo? ;h3,/Odb~XȄ_."Ly&>\>]?0(fbmzu3޿p/?|_ދBCoո[xEzw~Ӈ?]wwo_4G]__>ϯp޽x=z|9Rxy=o>߼yÇr^ˏoÇw/ƥ{?˛w o䀈m*!Oo>oKoͿp?g\}g\Ӈ9g1AAD?Χ[ɯxyOOkYAW&^EE1Tv<?f|9>.q)7~)~yvͨ.Ӈׇo(~.O-=#{SeMy*a Q.uO @C&BcXeO;=ak@?gp_??\}zw]Z[WF}c oo_IJ0xb@Ď2;o:oO% ?ǧ?^eɷ7o? |ÛOlY;Oĸy=CP밬,OmG?y?ҺWCy Ogk7~i"=p8t7 4JT/WOR;H#B Wۣya%[4/Ȃ|&WFb{h(g (}/s-⟣Eaf_\SfRB0D;3Q/<*-X =w٩VVod=~A歋*aUO| yB,WfWfۙ*i4 adok=z 4is򠶇KbJK11ӧ?Oz}S5I\?ڹ :?;G"B"D(oT>McEqh~n]̷.ha.=e-~-BsRGUx>scEjJH 'x<s>>ws7:ڗbAfprp/#8EFc3!%Z7/G#ϝz%w=F`5!&ߧ L˼y)R22k9yDvH-ooؒLshvthuiBhT\35ò,eſ7E.o"gq| y4ˏ=Gd/a0^%e4 V|ǎ.[e.x<~pܥɦ@Ze9|yj9;:Ѳj=h B,W NJXp̻"ũ0P!I/4vqԛT?Ge. !݃Rl}0շoDsdS)PtFD[˵<*{/|?29(Ġr SP.x|̀,}倬\n@dR&[K$H쳧!?zΕVB0@`>scisc 5!Og] efǚ@Md,xمZ4_]YYwO#2[޿I9l=shvA hhw,B^?dXLtG]ٸXn&+>,^d(vF㉏'E1|gc}/YKv&(,^f4$` aF`3>6V&B1][y{'~ܳs>>P=)v>1I.xK|L~RPKp5D(fRV Fortuneteller.fzPK>Rfritzing-app-0.9.2b/sketches/core/obsolete/H-Bridge.fzz000066400000000000000000000460611250202676700230050ustar00rootroot00000000000000PKp5DL'عK H-Bridge.fzYs$`p^oGmiYĝx/ .Ev7AeKRUDfe"$Ihba'x /p~_??/O\bAX!oE߇绗/o_iO\ $#s/׏o.ߑˋzۛ]C_vlc|Q^R"z}aw{q/?=ǧ??Ɨ7׷ݷO=?&yxx\y}W=ſwyOZ>nW ] k,[ xiv÷?~k_틗gkT,u_jSn}i_/??=qR~75]ۯ\/K+pzV8~܇OxG avSؽ{oN;B=b/ԗ_K_|?o>Ǐ?y/ןxY/o˭\!~ pUioƶto<_qyEHrsyK60_H`lLc۝:,$GLRnG,O#=;<[7\еK~e:;B;"׬Om <78`|xd/g,qZqm\/cyx_6 QDq"u5L7aIS7oo Bp߅9>6LR>aWɡD*gb}]}@b|RR_d-aa1ܝp$"O׿OUD)+W JJ,4)!I6KCnU*b|5,zD(zD,i1NZӺ1ߦm`M*V $"i;Ȟb;6uĺ;OIrǤI)LN(&D$ȓu[%$e։6t޶ jaVkF-M}eL^vr[)LL[)K63F%1v.H)$P[Rf`0ZD~ǐ\ٹ1" : \~BR{)яV\vB5.Yt^ARqAsņ7V* ;z#ei\ll(y)1 [/Hu.-\NZ=opsIaS5V Os9{+ 8:)#L$}#EEd# 8]5A(X!.>]϶Ta9pmp߹0UqJ}J֡&pb+ Ir5a4wz@6RQ8\Syw {"J]a N~¨׭ptd+)}Hv1\0*\:T.F6Ri8n()5L@GRm7Ro8(ٹpɊ6vTT}#UcRy8|k=L@R}S"P dR7Rl 1 WՆRب7l|S_^o׎_-_r7z޿<}}ݿ\}~~}){az?>~䇫/MzO_?UըvT?]RU^lGF/hůN 2J5 1EZbrd~KVbgY|(x}~.{W;Ono />?|*E)O_o^ׇmZ~JEưHFd~!")s(CpZۇ7XyN9+}׌`K@[R0UnY:np2,H!o*bEkzm~Rr"D#Q ŢBN˯hxO5Gy$R,y Rߡ #wǵk\tcbNJ7b*1ʃ\[3zj$tu# _ʷ!dJuƘB%t%ObLӡ[S1 at !fDlj11\> Vx d\y)1J@P̘;Iq@QWN|xQf!UOAX%@ۈwU5p'/^% +GsݗycbkVU8xTujLZ%:EݜTeLxSJ0%|F3b]1NMUS]]-SsWnbYmEewǯoϰC/N\qofȍ+b^( $}o( m( =jix4~#Xzao05'p[:?3NZtPn0xF'H00.J+7PI7Pz  w624y tatPm䡀w߰K7O|Bm~'m3xt 7I>P|洛;' ^D,9ap'A- 8~%`O d'pٜru2s~d bm'@9^&3<uV voVb(bH`/,[KɺU`9[6A*Ct‘PYJ *Fd"6пڠ/V9up8"hsJ>Sӎ ^ft60Tp4UppJ$dz%edl-%KHNT@b#UfMV5$g'"!i3pSMZ Q6qw:,b) ^OI`" #LτM䥤l`pIiA;A@hX5A=eVdl-%G"NSjB3L B$"4p >|ԟ; 9| ӨP})P}&CZ3֘BZ|i1k݌Yoj?, Ԁ~<&F::Gdc2]1'! Q I@RRݙN姝=+f9ww`>Rq .TCr>ӞUK>!PETAZ^ ,-]XWgh\ʢroIF6{9]ш,\FHGNW<ҥ4AhtIZ K[t:ݼ%HIl;K 5K0N?Ȍ#L^eԌ9$MᏌՀKy!l֔9{6FL~dY;ؘ9W1y*tX32a:u# aj0)œ* Ɣj!C4bVI4Sr/%LP5u_bڸ`*d/zh*<0pBl %?dڐgeiv<2gk;SetnU5pvn@`59SLyՔB*~hǨ=w0 9g Rb?[a&C0FX+I̜9lz>dr(`5D[dKZ*zL;pc܉0gOʄ0ݨvtlDH)iQH׮UVi}fL1Hd2Ty;$X9 U11w#)xdⳁ!z ̙#Ll\Oo2V-Vpz=iY3.íW&Z+r^CTJRhFNW5q`J2)^{&f]E__&t ~FXk6(ft l7 u $#.١K ]1ܔ7P K~Òo +[hgth\C qyQ#QIkүI?Ѥ_l8,D"z+tgG0\3Q3a2rmѿ \_?N7g>樑{{_.6hs?[ȑB')̟L̏h("Zq$//'_}uZ??}zqc4/ /~Q0/  ;~fGWvC]0wPx/A$i8r!cL2fWT+G Yw WW0W-FU+2k/zYy@w,GI07[>ĔYyלZJV v\,Yy3Cr^t p# W_Fʲ J^Ii1Ѐ!mE5r C!㺜;F(TI*̏8TٽX^^6P CU-q8byb/ KFtbsTʖOTH G8$PwMap%el%uR(Vk#od.I$)ZཌX(=D, .&BcJ)*aE&-Gt-D~{Le:Př窖tih[VG&͆鰊߭^FP3QوM~!t#tX9 WLT=Ba;5ppׇǧT?~N',N-҇մ>ƠE(U2z(9\M."ƓC|i$5Ua/ß#8ԔLV#~Èj`"m5yG56f2C {w񙤸.5 jyx~zXmχŞV)Ş;e:1cn+%׹jgUSYjB0 !^A"o %^f o ePx¶՘Tx*+ j̫~M{@fٯr%/3_F9 /m$$^o\onˣ3Wی\ ]ro. q!.`C?PNxQ^$opa6ۛwa]QD0νJ(7-sLĸ^]Turounݛ>{s2ͭ˧l5^1@!u^R~Kx^{^KK'gə59sS{i̡xFFvpf7#L`ݳ%&L{-O\J6$@ Ju_PKH1-[Mpk$6ݼi`:dℏćL!AgF#Lgu$'yxOO؁9 Nvcr~<Ɉx/+ k;cFN)GNWAbgy;RYdM,J,z’D9[3s'Ғб?>ahN/q=Q(gazB!{ͮ0;y<ړ%ˬ>α 1Cމ<RoU-.%Y!Z=][% 8E,!C{ ŞT)S6{ξʿƀO <-BeHh]ç4F9\&?g)@7>,3<-:#)lgRR&Rwu|d\J2ߙ*stds&kS#n}%ǥ?o/ GFlEhFHK1jN#+;.2S pU%7gFRX} {!˘E+\]fe+N/VH.#PVBTgj3>;TDhzC2LPVVVl(noUj 8= H.dP>V4.9ee{~h xãBHiGXrэƝ9c,xwr;_e2p͑~$t$ ov¼ '\7oRafq‘%ZHT%mH MU@>p$Z!-r@{1K̴Z4?:m.y婫o8THӢ*[z EQIAQ@x v;1r`#q@no /3 3uzgQB=2+~$1ĂfK|Ka4QqXy6mM[x!!=fEe/`"h'%5ξD04xy4AэT4trYd_R(f0\4 -_&!Lf2h&]c&l^klq\ D`JaJޞ`#ֵM5tRgj-%f fD/@R1b' ^Nb0#%oO/ "K29L$&,%bh rM,CraF3 a#HF ӫ͖ X2ՐmnVm\F 7RFܛ,q,,[*cYtHmSH ){֏f29L"ajG:D7@ 8Kedk.SQb ݱ_C*25$tPArŞKg#ɬ[;xAf_:*0Dr2ّXRLj##!,tf]+Wsk+10c Xh"eQ3`STHӣʠhA4qļ%Fئ26;9;0U=R2(  `z5=)fkb&1$3Y %oO!1 R#cƱ٥8S%#:~ ~Q-6Q V{c./W"PH{a1 M;:QfQRkZ,6;(Ӵg]ҹJ麧mż%FM$RYJuu#<\2⑒' Hf&3(C8Riu:Ru`_Te&s3Y{(۪L6_@jݘ5ӘԗƀG:McP$-/pȀrܜc.S)y{AQ8&dXS [9x]|ޞQ{xAȜi4+~4&$rOMVVcל$>2""+5'd<ؕd[[e.̜I6 ~LE;2 \IȺkE\?V7D6_3LCd? eNoMO SGwfU٪a:sS0{? k .ShOɔ-F0ƀ`25hF^T@TB _\!dPw>= ,J7K2$C`$p=/ B45R&S6+”LY)%# u{La=&#X Z@z9ͻ+By?JssͮB4(:b]&{"./Kd7,b* {jD0C0"er%"-9Fq w?p)c{r$0(0B1W}uM$>#Du#eA\œ}qWR)z|Rh+!5/W o:, zRu aB Ht`$RXH1!#tX=r@̱uK`4$ Qɀd I҉ UTJ*?Ӊfbf2`?:=,cRXFeN"He9Ab| hE=@ L+YP$yjL0=ˠH@.a+(Ob{/N[9FU rXZ6/i EvҕRtXTzH:^p5$:V egVsaNϏ_ zLB/ {ϠG@>s)\F)9J! o})z8_mth.Sca&{{Ş[Pj8tT1IӀu$,ɑVDguc K4Nl6?e?*{xDr/E3v7'SPzj֥-;t6{2XDeKd h%(5PXoe0$OAlvְ֣ǐeN r q3(L`8@Õ=t`* Qgh29M-V^EX7_VjP_ޟAԀJJ: jP$>+K46*'@% m mPZwd(P/آs3LiM4eZ["¦5=1mvmk4/Ւt<=ӀB!39M |)|DBZ!Wiv/?=?A\erקW=~,pǏW??Dwgߟ~^.T(/ן\Vv/?_ZdLV gHzKUꚮR>MwܭT ^xFB7K8GZ#}MWbϞ.iZwL8JN؞=8k aDhH=F^qFͲLn9ABt<ݳ; F4^!D+e* )y{J M3 F\IQ@RVf29M8l a/+L^k*Ex,%b D@x9xye:,9XLԘZUeHkuUjWL) ˎcSY2g9MW17.3 B~}W+) /.EdwL[.J`*F!a-lѲ=ɂٍ2l9MH+W1W8FWO)$ ΩkЋMֈ90rOie@.!LHۣFH @g*Ҭ51-5o,6?(X鰂\H#a `Į:zϣGF1p\HG@Sa{k0 c١Kd `gX]"T”="y;-)8!#үYYƯni0zD9V@'y2E)y{ {э:<kL#պƈ(R0ǻ/b؈k@#@Sys?y;ˁԃyCyoixPJM<%\%Pxh# 21Nw4V4i;ɂgVg}/{CL1%ĝcBM2cv׼)SF-V>"v) wP2^)yc֊`PUq`Q!GD}dk&\gtu:M2i9MvfD jo 9Ed+I~w]HICF]"k_tX:zPZ-8J;{ǎLb.aȍ"߂ !QE1aX3MTꚻfbdrF"W׎*TWw膝J8{lnSXH RD) yt2s=HFH’ D lL Ԛ=(tԊtb| ҁ]Qg:MA VD':c3F&.S7R!+p(cP 鸤k%u.B^ƀEU& 3quzLHӬf: :Bx/2kL`-F@̢"0f1-Iw;SiNO5"IE&-pP0o#p MZKg4$-jEFae [PE#)oL[ FAЖP$e[VWb=ֹW|B-#l^Ճs׉2x~(rV=KPF(bӆ%#vޡfCG10St-&f0LS ٣7_#=Z좖P˜11fNםpm)9,:H=;rDy ǐLf.a鈎 QhA#XeF93I|e"0 fSE(WV2Y!)6lQ 9 ͺ Q٢t$%xz,ё؄{Lh.SPIHHJ IHX 0O,r֙![Wy:7K@i1H $~G Ԋ-0Dg,@8' \ -F H,p1pHc.>7 DX3^z)CѡKMHӣs6Yh0A$7[1f[tM.'Grs?041'doBёu(_Md2szT5I9IH:L¡3utL:f:Y3C=%>{ˀkivjEs7ScNAgX)"6[Ads*d={HH 0752ĚH aG0K1Fspfz: |Ī6 I!F)Ǝ0Ѻ#2:M=J'%SJ2&L=HI@V+XS5Vd7%*Uz-4̌ft<=+GmϔC($q| Nz)DAVJ#] "LIShew޴šTL )1bk%^@ݭXfRx4CeWronŲHO-Ɉ2GDZ4_@%@< &%gWy@a)ЊOɑ%HNM1H"ʀ#Sd3,LEhX%JQe*T=%DIBEHbPl3Spobkp#~KPZ ]s)T8p 8>,0g$C'!퀓Q: SA2L#@$%oO)/ PxXbM ,qd%:iL(TfE1S)Cޔb ;!$}"#k )xgwy;&3EgD4'B⑒!Ykl2eꏅ@e$%oB02 9@, 5P(q;"&h*b|ӣ2.u9%gP#%oOBpHOX2B2'D Ȉ0pUo?PKp5DL'عK H-Bridge.fzPK9Kfritzing-app-0.9.2b/sketches/core/obsolete/LiquidCrystalDisplay.fzz000066400000000000000000000405361250202676700255440ustar00rootroot00000000000000PKq5DB5@LiquidCrystalDisplay.fz}mƑv!(i,iWZ+d:=P7fs4]*D P񚅮qnI(|Tsz"qd7q;dIsz^"sY@ $kI8|G(LO뙤wLī D?$q;W3w:KLk 1G1 $7]Ԧڧlq$_$#fy2$̔;BН|sy2~s=ß38'~M7xKηYsҽa5bƝKwoO$|Lm8?nG3IPr6NMmKPjjQ%ۅ=㺵OJ,ެnA<Y$ 9o/\$׮JHf ԞI2 ~!q0ș$0ggn4L#ݹa_lj>j,Hf&.<#]cm>}M K.I|Xr 2dqghӺ?o. H2oʸ s(|xi.$[]S\Yl&yK+ysI u)D/̷^zwɼwz) ~WyX|j>a<ׇa[c~{,\Wpح6_\}]-~Y߿ׯ(C"P y ww!5!;'?[?nүpesxw_|Bdo_|x ?߿=~¿_.j{Z/jAYO;?[>|>0?]}uX?</nf{|?~~kclchH%zӉ/`?Y.bק?MiܧXJ.Dt|s&<ݷ+T2Q_n}}Y^o~~{ؿ&?|XT'G=y7__Lݼ0~~؞~i{a #Ks',s]/9Gc!~'x廥D-@b?W!0"!{S[ֻ%CD }Pw-I/$:f " SX*Oo~W}vwɐ1a^6W$/HL͒WS}"wrX}h/ə\]OOP< ϏǧqzDEHNה"I*2J!b bᧄ#CC=%>%fU2O?߄iK.9{XKTwBhԣHpzz/1r2D^[RbW羐aBWA"y}x&aP J ')_? >evz!4U|!w)[U|Cˌ'_Sz֤M^XOxXH%T GP#ͯjwa{z?'ُǛ/?} +sWoYި]ݯ$6U$[U?VOznsxXv7=+Vw74+#^ċǛwۍ^ٟ+?}ݭʭUX骯_I>;|y^X?3>H-Mq)}_(l@ivfH VQX$UR֕OѨЀ)D\Rj[K.Gd7kX]qiW,[>noO̮mw{pߎ?"631; ´k~M)H>$S?jj%o|Jg\Njm)7˯|G$5M~\Xc ,KFPʶrnT[%Wz,F1W\U$ | LXq@ vϥ s4+\z]h.qRmmiaISIHN_J=Jz @5.MZOJ躺\rt]UȎ&e}yTHRnxKe| \KZz.zb2k7ԩTۉaHFQ1)4PQԡ[65ʑ9, lTm1-2  !y.js %Q{v]zն\$e*]Kkt)xU:q! Dž%HԘKg~ 4'K"b"fHn""IcW_1r˿#|Q$ͫ/ۧxxlK12_|w9C %0ʉ (`yu}zg_7gʍv=΍j5 RzaWL5i&`U/ԒE]Q3=ϡ֋ڿ<y;{y&nXa}/?:O5o=G$>rةc *O%5@Է)ϡ֋HI1UZP }kjZPf-~Uvsqw92P %TzHwZ]i@ѥ| ,J&oH>` (mIcXsy*@U8W #SH&UqGI0>YiNj"(6eכ,UA݄KrFEd%>h~{;ד_k7x/J :5phrSIst}wUo4T6$ALzY%_om$R(L %\= E?A0@4[ 'b]3]6.28E)4 k:ZayF f{ #s0Ρ)N/ g4Hq J!T(Su jg=9^]΀/hFu ~"MTS-TG di0 0|+F??3)RʬmŽH1hgnkۧ/L saIc دfG 1I"&1csX&\c} .ڭO$Md{!JMI:׶n,¯GaHHAD ~Zj앱C dxswBeIl/@\{E1SW*VTf섊 B̓=?<}nQsMh؞v3n#8.hnK)N 49ܑ6cdYY3 X!%BC$WJsS^Y|+& #Blʼ/j L$y7|qJe`2 F+x%E*JY[ޭ5~7vOm>Sgg>-.{L>gO!{1S-q+]9=ȀϜ J q~h<4-\S׾g}6KTמB ac3=IgJ*RE;nLŠTԿlc.Q P(d|ޓLp00(1  -R҉۴p(8NQ% $ j_/iw5Iv3_en>O6bՏPp0ZLNh$qv>aE̹'\gs ǽ 7[R@aH7BX|aP }@)D6(꩗ P@qtBTO,hXpMPc|&Y~KqS1T\X+.y v IT=#䷱QSCL4_DH/T}Jb6nql '_Vnj^'oc傗+f\uYjK _fZ2X6\4jHʥHLѳ}I*ѐ"*Y?l9OƼW_ QcH^8 L%`0ε0PyP a.Cnnk>6 zxVf̈  8ƃvZS)|\) "zw à0깚 "V8X#+sXi-hXPF AAC`m"ÇlxṖe0FƀC:hL+ `ϔq-ϳFU t՗- ɰ"~T e '[/ mU eL2Fg[m23-i=Xxe̸T d F mLjIjn:QIb\ϣݥ Q#\ige<כ߶m.]]rF'{q)٥tဳ࣒er9r'nO鸹[mnfal=ݽ-:&ş&[~i-8 WVZ>(Zpp&d2_}y@*O󀂍տ5;T*d q@B\>'SϏ7J18ѨO>(XP7BÍ NAaPrݸK?lH?\6Za(",kD_(31Ҿ<4DO/_i=t%ugdctF QʒKF5#y:$ Ϭ=nNge(5<}~ ikXZ(iPqvlָucì.Kn^̈́5̊rԠ(%֞ƪ[<͖ tXs wܐsѻlZbK _ fZ >f̈T l i˜␝(N[\! jJ$=DI lOڢE[&Mpv+-_}Gmz_Ypp_wq<:N<'7/ O[=K˙= ; 踨Df:Wpe!:ьkD H4A% a !6DZ Ŵ^R̥@ s&/2NX2c+P^g`gXXˌy\. L~ΉTCO*-3 .C )s)dtHု˰E3ȸΐ5Yd={] [)#J.ൡV A*(jRªbEխ\nT"; 8rYQ#(5Pr#"M˥`C9JᒷK˕E(Xa@ P0rp?ZK~`6*X>?o$WK/ :bպ’_zu1++fxլPRi[Vgx6J_kO ,>^4bB. 8vJZy%F n+Sz5OuA]tFያE 14J؉D!pSGwS#/W 1z}6K q%6SOF}b 1\}6l#895J KZ޴< IʔGVB)vxqqs(\zp8ySIIS@j#'Q-D\9c¦@cԵ!:.<7pvr0^ܰ}R(aSm(FknknJZ9r"Ri#IRu6< g/|rB%1:/R^zyteye!:.<:pvxhjɔi=B4-Ha&%x; AVPkhFXrQ N}xDKMD+2N pGłCt\pxe3  fT(28e8NYy, Ԧ6__^P9ruQ|9OfZvuQHaU 用L૯%'`SOˎzaRJ5.6  ]v-v3igU9 XY*w<]{sFژ;*h! 2XXu $#0֢fg],E<;` d  0 mBUBp\FMt [yvg-C2|Kpmגói=te0Nj_ڣ(Ohjr0u``q\a/W0l W z v*uV1($ [k:<; 9<7DEOJ9pvvhZ`ИĢXq@A B&h)d Qʠ[^WR.R%Z;)eMO*M}N %^Qɭ =`1? O"Rj:Spehi#F4  )0T :`$kAK`l(3\rd [M ϸ,ŠC3<ۺ\ 2ˆSUh_kO Š /~i Qp80+1h!rV7cwV QDjX֊|ܮ\!g!p xH- Vf!^GYJd8j (г7pvrhJpBB)IC^Ѡ, /m3u]p>g5&ap7\ruӨ}!:МhWȈ-] 6 .P峙#FcY]@Bt\Wx~e3  frc0n#[N ͕CĢTT͝jzU}yzu6`0\6mưTu1]&.0AO@)RZIJDDAaRJF K)lęWk-=L!.y6`Ppd@F`!Rd aL߿{YM=~C5^q~SXkx>X{]! a`V330=]5`00l1HU,PFZozf5 ,]p#206l  v41+:J#& P$CZ'{2f5J p^j8vıֹ>f1; h%SuCRDY%bm`Dva`%o{5bf. FTT"(]y=]]9A7o +`sgex@fe "bIq~`l>3 r3_ 1 !`ӄlU۹eͯ+(H<  `ٽݤ4t˷ y! ĀýD"({ 3IaWzL€†SnPt IkةZG$"*Rg8X녔`Vnb7# ƫ5vH:CHZ/<vE\Ix b\"";8":2\̓3㎮d@c@.& 1 GX-|%!^ce刭DYM,7Ӄy"兲5*fŎ}y06t0 '&BX41 j빗ʹ{ (l9a@cH5la 81$fu0$)(^ [)g`!UEvHMBHDH,2}x*.-GD-&4ఊe`w~=ϟU^ 1 31(.B^=F6y-q_vxe5}(uV9ۗIMkRF&x䊉8 F0.6V[q!a]D!D``0d8#2yfPt -҃r@VD҃ywܫq>ep+pYL21~8 VSBEO\Q$L!Jtyi3N~ڈPri&`hm!ۘ#)}%MPfo=98 #e$札<紘 ˎy$Ppdz&XJ f8o65E: YǀL }ǁdߝ+ǥOhՓ&b 5B^Tyf1 xI( xLN2O.X̺8d,I[c61ᒷǠ ȀLL3"ٳΫ*&'6VR!RJ>2&'cD8F] /eWQv}-i`!OW1:3+\ @)rd ]9XpۍCdpd@b35-1q(.QXXNqb8 J2dO6M`\tsb bb'W\IKPX͒gzFg^1/w'7$]pb4i!:jp| fڜ.9 l Hc`b uX d٘zMN*!L$tͩm҃͐j aK(+aZhپ4v ,`l XͶ._dnOlņ@!%o7g[``cH5pI@e%&Y&38oy=kW/ .lŌuO0  eᐡ@J\{ۧx21 S풷Q#TX@a_r `0Og_:l=D`K K2S88ʷA,a6(־b6%7(.yXP'll ]m|PIXpӍbPpct"f!:pDG!gc6Q1ᒷ/AA!IҊݩM혗oyʹLKޖfbl"1_-c}zOJM;`;:L{A(SӲ-+ jvdѾc6qZeG=3>vI Hi)YP*T7Ivw<DGb6a2ᒷ/ # qbVL]*32Jr^HI#<`2=aKޖG?`aЪ0 Ib^iKGɀ;e:LGɀK 4(+S0XYF]w7f&Dp{sG^"`OWQԕF S&Qe1ń zv854gG=3v(ftL sC_$7 ".y[̵t(Њ¤pO K&*[PKq5DB5@LiquidCrystalDisplay.fzPKEAfritzing-app-0.9.2b/sketches/core/obsolete/Loop-SMD.fzz000066400000000000000000000400761250202676700227560ustar00rootroot00000000000000PKq5Dɤt= Loop-SMD.fz}ms6+d*Nӝ[;I'uR۴-Jtw/ 2E (-"|>8y9xyzͯr5[_]` a0ABar1]7/VϻG聯,Ww嫋\n]Że:z.~5/F{mz?].z|wIx9e_kwͯҏ.R]2~wcz⯻7䗕1dNty?'oz5fkKbN,|xfr.${iXڽueKz'ܤt42FS/F$1?¬ .7j^˒~73.9LWγ8lCboi`Si7f<*`3`6\fΖE4Kq(->eqPv._LM` CCRS6H`jF6ajLͪIV3y ԅoHKڏ"B@i1Η<%@sK:@yh$G yhE !yp]Ξߒs,oqˆ L=lc;ۅb 9_v !oyn"wo8;!6 :H ٰp23)oG{Bx[^6P   R:CwxB;VJpo.5vpr a9m{|;8wvpGeOjKn@Y\{AdĶ©|c_ 5A+pxxH킂X>m<z9*:kJP 3CAghCi$44ZmT# C֛= AmJJ}(@y(AeJ @JFA)Ac9jAep Sl#ʍ+32xPz6PVMj2ի@jP6@8#p =QφgT CPbrCi!>}CP p#Gб:o=.J{f9,^`7J׊L?&2'CiZCi!!c(\+>|2&Ķp4,<1ulЛk?Z|/k/ vwwW?ׯ.9[?d/=L׷.^Lj~y&zefL'PtC~ү ^Z>GvAnzzu!h1QGYf?$I>FrAuPwz9]v0Xl~vg@)Ԋ7lmVҵ|^;`d,~^8O%0ՠѡdĶJi_A8Cr4ƚ"n2llPFl;H{ B1΂;`D{x;W.L4Tp[#. "V5(7E#H 8^;4`{DBXvǪ(VEaUHόO]_|Z" Ի_j2`ϴ6=x@Dk󼊑j1t%RK]YjM;R+3Oq+[ uXHUcO>)\]meS#I5jw hZqhIp1e-Dd̩:229Tx]jc,)"D #L&qIC525EZNY^mJ֞;(Ț"F``wѩ1D#+89$0u0uQ':Ц!z`B2%Q{i9t^RsuMԇj@¾(4m:_qfMO9Hkv18ΞgUH7bL!fC_mB_vl=K"~Y%^LEU76@Y~ ZbFWDkd;%a-FШbZk`Hh)Sמ֨4O#=1EScȈS&A"S ';=`Nc%T?IPbK|SB`LsBg> R-cabaߩ~<9H "S{R GZ1կ|** I'X@QwdYv$[Ρxs'0;;Z@߉*shQ0AB550B푛VF9c01EyTsG889$0u0uSDAPq h!LJX4vL &΀H[^Dþe*!2LL 18JU>T*{4SDUlH!Yl5;%-z*UdftFD ղRs*[7K|ţ-TS#T\֙{T ӄ#r &F7tѻL"!ȜC :X;هCApTI)TR&}i~QrB&H[{dXطJeСRT#"r G(SOAJS[MT#FuA8{qGEm#rNj(SUOaFGT+k_57CZuqgw/ۛ?۟~_wGd7].nɇ˛?N~v}d^.j}u{gogٗ7?g>}u_[; r|a]:Zz0cjU>xe /}1zX×Wd7'nqiyg|=5?46Ͽ]L_(Dzʇtvs~1~b?|}Yf ˛|^<|b^t^^Xnye_Yus#kݯffGj~?ܥ_Vj5.ͷ\ܙG>f7nx=F?wӵy#LGKf 4]Y(lK@2VINb*"Dtz<8oH*} -~60aVI RbV#pӉk ;fohtT>3XQ{6lExe@G OMLEoR`z 3HAfƵA} \-E.Rtyĉ%HEՓi-* /Y:U3_b `*kpʒB1l0O+Kp>EW$04fRRHnrBN{8u2vd$xDzX!HVRHmV"Ř 7;j,wx?L=͒@o3#%$E +%rZ;崭H Ccss9Nj[ݣowAS#Y:Fs!`E50,in(iE챬Pc!91ݱn9Wg>ܙC4/# 0¬Y4<0,vYƳvy.J1DX1"x%cNR9:jtvpn>P`EwtJw HT]YS `mjV6Oy) u)!e"2AGL,SjS@2%H$JT@1bpvQ)ET)3j|˥pAz_tDUeh 'A`PO}&%$ϑfNR$QlpHӺD3PcѳTDw tza aPQr_+&z_tD.U%)gk"TF>Ez=A9>7B'*JPCѯ U$#T!'(Rt(|YG?dx"TVCm?3`VYXݽȮNǏ^^ظb]E9I\0EY > #ZmC";|3lmu{@zՑ2msnRDiJe/VGWH@( ؞R!S 57@u5jp,Qm*Nb96, F8 ^8tE%ε5$.@FHFGTK)l3;ZܵV6l~$F Ȧ~t{ܧd3hx5ɝOAA,>ϕO0:kj 0~3`~XKI, `:Ȫ3Š}`(, Zu3(0j%J I0=EqSDNyP_膮T@9H!8&') +L:zdQ-((XEns¢z8c`Y }ceM!9y[C76ܓzgS!1ҔU#*keE#*zJ \_7R`C0p [)p^ 0%$3.^nl!*q{( V ~WB!Bu<{qǯCw+0SƆ{ty8WBWQke(֍?z,5t<(6`1D {Ry~,]w_ů`FƆ +-:w/rLA0[s\hN rULa9UcCX1A򪣑Bqg$TCO ڸB3d:@Ȣ_W Ll RtǢ_%pYԘj6'Θ'l̈rz&ً;6 TU*rRlj̹J0%6K|*Pб(G Ѣ($Aay!lT@"pcŌ^I( #e+ U+dz`+ \@#*zb+µqb'@NYrUdV- W0"p;W W@Cftˬ ̪XB˧*,%=o*@ $^$WiʫJ͝cŚIݑ\=QL0ꫴ!WLt/b˼v`AHv176\a%[0,AO>d%=%>'X+LC=+}.gIO֩!U+P(,8vu"NlQX"$gO ۹BYi ̪,$iW,)y5`]%$wwHЮzB Zմ, *J椫fbwVCOE. jSUşZU#Xy!PpAC~pP ATmS &ʎHc-r*'Br=+Onr">qOB yD;Hʇ ^pm\Eby > )2r.!9~L, btǮTK]q9G@Jta,-CDL %gi?*A )bRU#% aLr*lU9+hg`WHAb9b#oQ`s+LpA+%.#ŚJj^O~:O,.ߧs÷Y7O?xAv]mcj~YZ~_].t^ĐBgQb*мWr}73{O?yu^?xܳsB .%f>f+s a0[h>O_]<9?wǿj.:Jxl>Z}e~clwk׋twBK/V- |& gQOjW&utF՛@;ClE\8R`vWߥ7MU?gkc(vXn6/'[ TbY_P}#Q-O+c{546xt%x<Db\:~O>,tɇq7Rz7;3sDZ~:}slg L݇smg 4YķwfnrS,!%2-I.M8Xza>膋6pBP C_Egވj[q*'x'08 Vx89RbI.8gܐ6cq.^Y}*.Syl}LB Jȇ$B3D9?T$YϽ;m5qz;3so{q({Oqz[iu,S̍%ObG%\^(ޠ?\o{ ܄souQ7Ue+5J/c겞(=o@aqpp^<Q~~1JAO\b3Gzw3Or]gIϧ8Y H"EzTQ"oӟZ3j3#V IĄzsoH}ۛ; tk~μ#mo?5z Oz޶,7 C7aaQ $HA,R-.R&\c C_Egވ"moŵz qz#UgԫFEU_hO?$?w r ZIOzOP,ѸH$wHIS'&i=\svf˛sM {`q(OzH3Vh}c>Fm^ ̨7ξ1N_~ϽמF\ C_E2:؈V8qz36P_&vqD$Z77]kwaE,8 B'=7 $Bf7R]m!Lϑj/E%FQbB}@a35Q^;ݙA/s?(}ۻOMud\BL j67f fmd?J_'S'EF :!9%@"$c7`V@Cfqn_˭^dVV{׬ &y$Jf/U ߀]<4tcY&h%^W0&$v̎`9Hz#X0"`CEU T?)I%RPPB~ 7`W0"pcEU񸑖U˽- Dߦh<6Ԯ/ Br=>Sz240N4)a Krqha;TSUS'&Hcc&/HYM* ն&Hn0)ۘj {?0hFю34i$=(="ɃE|!9, fO {@YDqfHy$O,}4%±O q|?ϊTjKa "9մ7 W"$ޏCĈzNtǡC)`jIJ|!\ȡPz244EP#ĖCiv>Px{>2r'p((}( ;#"xE)JDYDɦmj!9~$ &Hdg?! PtH:.0H$*z/$ޓDdО$ HITR8,r(Ihv@1eur2TzHʆ@`bD86P@J!gͧ8A)T4<\{? $BQ(m Pc->aDrP"%7 BrS ?U.CdgőX-OUvшsIrLiedReCcR"`W})!(*$Ox)Q8Q Ori;EH~-۹Uu[!ʺJMv\]mRwr ф8Uߺ_* K }T%edSeCOl(17+TGDƥ(Br{݀OT~ §T!<&!-% % vLw*L HdA(ΨpTj`!jUSL UTmPbV$O o@`EHEv Js$EZ4T7<8?@Ci]z?[Ūϡl_gVN% @@2ǙE,wpPz! {ERJ<5TR0(]m#*_=0}8=/o"PR !۟GAx "%"$\}c4P! UOэFf]) ʠt!V~$) U./%*#.@PYd*J &Rnlh!* W:"ASxЕTwJHS@C`FQB}\їȤʆpl-OQDƟKBs] Ftȟ70du$\xc}!^H H+(UvE"")I&4UKX؀r*IS@#C(M\d*vpLOM (Ddl5J"@8.=Ig狋%ۊr*k^~~#V ) E}S*P-`0D!IQM,#*Z gwC<(բCg!yA5D4BQcM%YC?\"j7ʧ{!y )$Oc琢D##*z%64\< ~TsDH}! &Fnl8R[`0(F }^P.}ٴLJ)bmN(Rlcy%*[9V#JQSOS\ ~T/.EP}ɴ EATm&ʤZd{Rj"@ ɯעǴ"jCr5 >Hʆ(E '?Gӂ_D &:Oq+\`Hý0 /@6`'$JSHʆÄpl+?A[GZp$/@A8O P'{⍭D8{"P*VC9&ӫSƢH<;'fl  *ң02t<<bçM`݊L਌Puї TL#E8ݏ$}&HJE*D vd-I HUh8={@!('pr0Srs6y!G~3M:O߰O={X. ?p1cz>};&6j?$cyxeHl7iYHZ5ybsťG]z8?,fu\.s.>C$Y HG{9OFox?*Or[SHW6myrq" k~hfk‘$z,QHX`7`aKA6ŀD xy(!D-YlUεq_>~bi̪_ׯw\3l5{ws62^G>zmox$9<j\\>=;#YVWՃF泪_kh $9֞Ű:؝wk}[wa3Wn^?PcC>qm<H؃,q jby?'Y(lb@&xO؁ Rnܽguܸ7mToxlkVnm\dSddHJO(>Z:dFe F_.F_w 4hmx6ښ ːV6[v32*lY%_qWj"4U}b7SL܎D2(ӶQ#ʴB,EQekD bo fQ&24QNQ&Ӡ%ʜ۱G$ev.jE݋D(ʀs1DZQѧ(#He _iww0$$Sv2 t$*֊;ZWfWU%$R*΁i*;|nǢfz-2Ũ`s=(nFL?[Fl19AQ:\\7>/_zf_wG'דɛߌ~ 2|G߮/&> -7r51'vhb>t|ffիbQثGnS(Woyz0|2 [rIn/{=4?̾ѧ0g(t>5j;zn+vYތfWfw.i:/܎kzvhmf;ǏZ|A[cc)c`_`%D!%Tـ[aP`ɻiAWO^SnW{ Pt6/rs􃹏 ~#Ͽ#կD#2/UfB"J*Ĺ5??|Rf[ծjjmLvBqpq P#VoI3Y|Z_^#6EÆȆunZCPv8||#kCj~o6ql:ef2f=A)sj ħlv2Uz'GMth{5Hʨv!k,p}F=gwyvtg~(^c8"ogI֬#jGd^gO֠:5 opz\GlH{P W: `34C {eiVV?Jؽ0-99CufJ WΖWф PwIpq%B=^A00 QGuvnusߨ= 7Mw77ߨ;s v]qzbVG&̻tt\gP4wls]]P9wVTjs튂61ǭ ϵ+ SfP/HΒiA-)T4nI-G-)rT^:PkPezK@Eݒj[YR`DjWJ [qޯF3c_0&߼ޤZ{k_,?m}ie~JPKq5DY]C Loop-SMD.inoKo0slh )mcArP,Qa7 ߻@RrDߴJK'MH+촲 5J 9*mFcܑnEu,::[ׅ)XKUȳЬBȍ4V&az 2'78uUFwIY̸h_7Ө_0 M&OX*qV-YNTK>LpkVNQe%?..t)AsuKJ夢ƹ~6MI(R;m(oS&rTR:ipdr×1x:|&2mv(s?:b9Yaq q)r~IȼhCqԏ7ς+.?BtxFlrGooF(h|S1q7*"y _\|9r~_ PKq5Dɤt= Loop-SMD.fzPKq5DY]C =Loop-SMD.inoPKs?fritzing-app-0.9.2b/sketches/core/obsolete/MagicBoard.fzz000066400000000000000000000255311250202676700234130ustar00rootroot00000000000000PKq5Dmvo* MagicBoard.fzmo8ߧ0}gϤz],ݛAn$qgӟ(Ɏ$K-ꡨ$eUv7?7 4+D5\]7m{w>߼~ͅ@L2Bn}|~z|sߒU~ٿ~stsNq޳b}OG{*կۗO\H_,sYл__˓3߯iM/VW7?>?~\nswc:ۯc }X=^=\7Wuݯǿf.~~kʥuiwٿh"xyzw?|鯛s1]?O.rS^?WoV_!]U?~y~6?<}WJ_ͦK6m,}+e a_*NZb}-!]c+csz\k//˻/n/ov埯~z]Xt)g=!.jkƬ՗;_8/|6//Tk&Kj605ח-$UM8x:hu*#!1ֹ֧cq}huopg\T!#uO{V1}?c "aloPV~+[IM`lشaUCM06!?]UDJ&!/&c^A;~n !/&/¦!/lW@\jl(7A4@V6 ya;>1'0lva$dOĕKoa'!KU lMrtBU0vO>. h ^V #odUr!DZ&J"y nvOO=y1 PO L ZJX5U1:,ƀwvqlԐtЎ˚Q|jkz!QTN4-%# UGN0 m)Mqⱔy㥓8`i mQrμƏJ ڍ ZJ41f:, x7~!>]Dl6s[1v: x]/$zjk Ox8 C>cu2q F0d! vK=htCBO>cDuBFSDN*K<;̱RW$!`cwg p$ ]: 2dp,%Ldᰪ6`Cj(JBjdZHv %?:y-ďmrtb';`])4X9x3+t~ڥhi]'*y -{ms_'Lk4x,ć #h!^J=[%Y _Pyyy|ڿ7PgX(E"F*^$7""#ڼccɓq őDD)(&];b$8sFɅҗb ,rdS3FA0udCҜE*% L?TE)I* IIhaJJfjxsC8e!8S`IBʼ9FT'sʑ+ZeefzJ]u)WĢ+rZA2[?| hO1bD S22\.%#0_&Y/ZTL$,e{@}{L%J繓$IQ8߂.'kcN쩂/1H~g?1^D$sJ2I@ );W["#cZX79`՘1dCxzV4mC{,:`4#&RTj&4;.>:J|;k%HqV$L*%bvxdˆNWi0T°ug2?uR.YI ߐTwRWIQ>aKO^:tCUR+\̗_TaLpY p]b 2HP˲"ZLGo:;!;ÉْsR%)H{#SF±, U6ʾ!t#uR#ccb$+W x%%_ȇ%WEȑ IE߀%ɰ͓"0UAKc*ˢPOy5-Ad6Ge{h, 'C=4C CE ]jb0uc$ZȑG8,IR^ dI(DcZJKIT77j=k'=F t+ 䡴l" 2m zbIw;ՕHQ!3O69OR(ʈRL-j-ъi-e2oQBFOA=IL#&a C`vH"%t<@Z&elG8ﲱS b`eHfɌS6u]8݀ᛋMM?+(jSά*BZFnY@Ed2@;GXOPJ׹p("$!SJYzvxPw G@B2t*"!fnyĵHHT4Cg0ҙm|ӰP C7u ô=Yx3H?!8fz݄!"~Lckb:$"M֛5G$'I $)Gq6\ C@75` L_pLљ%1Ikɚ#.oKDIu hlӘvi$p.(OQ"YzaP5 'K|LeA"ES$˃d2e(D( 2`  PFCYDZgX{(Q%(kF(;tqfFu(FQMGD p얰E>BZbZjʓ0wj$ lC60#$C+BѐXl9R&1١$%2+Rb$,DI^JƬ8#,Cb@5$3S@ g*D! $4FK[0#ՆzÀFHXw.K&`aQRU581r9Z^wM5bD@a-`ʓ_A]-Q@RtLz",s3MC

yiӮ}=ۊKZPkl( )+*ŕ6/ݎy2Q0( h?ZٯEƢ[:1:a-ѵ Դ5_t#چF'-6QAy h, pӯ~ k*G]4]7 RDlC}C{@!}g>rsYIcBZGqpRTq\;fG: S^򸚚+9S>|D "<7"Ԣdt&m64LZcycs9:FJrW\1-;N!;+vӼS@D *pܑ G7&\*jMXrk1ZxnF Lݙ) G<.1ng9N$!^'^rJu2X$ SF$"$"ehLC:lf"W&N$ sFI64&ԮQ.(1nqo QzMX$tMu<7]カ"KE"yYzP .P1GQ~cV8zy:7bm'L% @bthj4J%2(bŋFR46X̲t7_ yjxD{D2ƑLr{ CX{m[&3] D%ܗOGJr)f@̝)IOmr`j'rL<_ZmwjC|\7rb1czS֡|b`5c^RR,oLr;|nn5?ϛv_.|~<ۗǏw'_<^LeS; K%#N424)}6[z`FILDlXta'|tvǗsnrtZDj3.2|wtF;;$p*w9*anLlMIMtQ7X"w x)AcyTQJ'r;Wv/~ݤxzk]~>o7sU͵~ﻻ͋ڡ<"g?X3"`%>?o/7_jeeSn}"̔V%rvάOEAo*$,^b?S6{|V$Bz /Pm9W|{5?|=7ϫR Xβ8sW7{Xϋvo] iAF1hǔu  p-ps:zƍ6M{O]ꚼ|Y=^=(ofssG'EWT~`s lb616a7jo*~X رMءݤ5M]D v> gh!*!4#]jb@uc,61HJ]paYE׌@UG5S%5 \ <RD۳F"Z: mv z R'&KԝDB^"b*ǝehFT1>!2#X'E#c*#qe1Wd=}4_ Zm$Ͽ')ijU,4⌒[Vr2)ډ bfXՠʚI % . X } v-(5yg&t3yYYW:%]E+UоRTV2ՠhhldc0l[S݄$W\"{| 7?@zq6Է((^Q+"f/~ 2ԯ%LP HǂESB%4MKzmG֫ S=75TdW5s 6iMqwa.QWQH]' 8WLڡ,,#,C#{Q_&kR⯁_6uIC 4GT0 6s&VmY䡖\C UW{5Bd&0L_ u|H?e^P#3%9BhiSV A1鍸D[*qi6ԏjFHvM8cƣp(N%J%-C=_ fw覞+6s!,C_@#`3C^Mj34BsZޛ5C=C]@5#pSCՍqɫW|>~G_P-پޓa^k؝"T"CQLM :Bsm8Gm3IzI{biyW"1|G;\u`-Pwś&k/-xSI )8;CƒJg'gt1".A"BO|3 &nҲtWnWseIMOox^{ #]T'sZZT[KeJT>c)Yr(/P)]u0-' ]܂A*߱e!M&~B)]f1̂AeCf 촎[:̘֧l]wq(n{ R^to' E*i=8Ws)ڣLD)XfyITyMfTs֖ 2|v5@>WǬû` trYlh23;>`㑁m5T)A@>WnA v1?|7v."E-7*KvEeb-bZ/ptuNG_6%yx,O7%?wO˗曋ݯfϛ߶V6%%L_3)(IE#MEc˩A6CBy=m)¨Ngۯw?553eD/#A;Vh@^FLnu ]\لK gS$1<-ov(,;E_Sa8+ cqmvSa#%r()y;3a?0A!Dhfo#x`o;)7:ٝD:NMR9ӄ KemmZkS%3J<͜je!ya$pH,h#]٢0 hfOĚ8ҕc fvAl ̗51z ٖp !Kā]dgc0ZAgK!/Y49 zTʳ^B&zb1;I|1,$`ەӕ`KtTٙd_:ٙXFgb Sǎ0/o~|wlE/kŎn7$Dt#ӳCLUJ<$ʺ޳vv_i~zuS8DFq}VD53<De5}Щ 5`ϐ|4fT~\`vf3FߕgnZW\k!ѕ?:w VW͵iS3Ԁ<:Ijס uKIV>Yu:]^jƣtbm^‰JHdh$egbL'T4P C)@esllmS. Mi]@dTqx8Ɯ2?,2Yd.UdmFs]N~L Nu]R୥?Dڸ%X+$Ibv׾B#Lf!1 t̄{"=$mho !Y<7œ*Gg=FT 6B$q-N2M7ُT2NvFBcPWD#HJJ[4"ZvkG Ήm ʁYM^ړȎWy;)9ƢPc@5#$k7 ;CzGBvaGHnX#cLr9UXXV ;)%h%u-D$ݼvm#vmP9I*`#vҾq!!8:q$Ej!qqK"ATFxYıơ=!U8Fv>_7Ukch8֤$[!ra;X}2A &3m GGND 5$$C)!#˜x.y#s@kΉ""8 586UILt]cuf*R+Ht)#YmC ”}B5xp9U Q Ƒ2y<;KG8lUcGT;B9M 4٪"SE"!چ"P 6Ș8!@oB`3VF)\ݒBiq\ͱB̜PZIJzT,sYcY- $0$hU&kG2'!P dFD!CO)R6JIHvC0R2fo2 *s[4fw4k`C|8U%(9>56i:I_A TB*!!YB"#HO1h:@)L1 0"1@FaNF"Tbmr 1$f FVʊ((V<3?0[6rP"TڀE($vKޘUJ6`%4ֳ 4HL͖(oZ)l21*z̎<<7vG+9\9E(H )(q|EtbPϒ%hba%F8Tu&P ㅪX3nIO݊iZ:nB,$hq1T&#mKb.6k#%m-8>'Mehidqj n"PjG~<1Sl&L Y}:eVPKq5Dmvo* MagicBoard.fzPK;+fritzing-app-0.9.2b/sketches/core/obsolete/Matrix.fzz000066400000000000000000001247411250202676700226720ustar00rootroot00000000000000PKq5D+cQg Matrix.fzksv| դNةwIRI9NKfe+{f4%i| [-M{ͮT<=hZ?Wp{ux|J,o 5[B{su7??_}}|T_?M⭟o?;|߿+{sU=͏=?8\=?(t/nt7Wݿ78O9N>~?V?b.w˧>|xx?ĝzss1?~,p|?/~z[MplSY<ݼI|÷?˳{}Dox??=|8TsnC~??ڷ־___~ٯnjW/뱾^^z]qgAٷVw-U}sۿSuï7=ou;޼{x<퇻^S.MRsXk~[kW9w~><|<?~s`DQUc5~J+oc$]O͌w>k{:6} ڽPC1tB=lh8BQIeвe-2Z;Pk(z'q]mq'A]:g N¹̵h0eHqtIWYMFB୕L4ޅsj Hb!YԨ6dKaWiA[}Yr/:r4>v,L~4fUAn 6o'P.@:gcj8ADIWK{'a\᥍\[dw5PNg? N¹0u΂-을t E0kѠNº"صY;l']Y:g6Y N»Vl0Gl0Y-( js54:UV/׭RӭV8r[1YD θ:sPY/n:b@d֋;YT]ܜ: dqwf܁4Vqf3kzrZ-άn> 폋m^]׍_Tas9/nڵ1T€ܣ;Sg>%qqs "_fX;/YB4ퟸ60ȝ U@Lc Fb?#iŏA`Ep_o\8zO1qFz'q:`n4w]$q@1qـFz'ьz 6s7N cw^l#eŁc/.06..%N0>휳R |; YRj+{'^0;VoPj W{; T06)`v`|J %<F~c`t":8>qIF(.z[1Jq(N Mbk{'ъF+氶w8@5wIncQ9-m\\6r1# F/.,47/&Y݀#m9+ r(aņwl( H,}! o'ьxƕL/DD5i}l'zỗy<<=|y|wx|tS+ p8f OO??87~)a}Y~k6D2STG++c:PI¶C1̾_qNxwYß3 qR͘ȾwYn{-Ëܾy5JψВ?4.p`~&4WEarf`_TWkƼŕKmOWI][%-rmTc=G|}Kإt^L%LGlYH3VG٢Qql@ ݫld`.pEq&hJ'δP h G5МԱZ$yeP^7"45Ζ.0^ș#N/Og`_ 9-8w&h u YT="fM;1ы/g_#]U120vf\8]zJHLàK+R ]J[eݍ9? l57f!VD #Ota e8 H#No쑇g`W7Ho l89#d-g:TP]Kb#YK|[%:7_>lUR[H0u=XJlW%Zeɚ#r,ei3{}ֽk)4ڧ%,_J\hH~KWvإ4ΪKS>ƈNʐ]Ja@a-%R|VM7?ПW+xA_Dx].khȮf|\א:Vg䛄|"ZĿƙQʟr(%ڿeB*kOf5 ¤̖kݝjRYW5%$-84Yl_ε*^ŃQU) enpIJ,)Kk!-f$$%ٴh栠&V4kg7ﻙUfhgY@5:rc5JJiCh=SYѠ( Fu*:J0\B<kSʏd!9YzAёY4!){Ɖ)>@BdBM;60|5l ,04ڇSIG0*:fl#qQ&]OdgY{S8rF0O eF(c+&A( 1EʖrjRABY`h$AU|,=iFEwqMntՋ!ҞZig5WBÈfhU>rx Ifi  Dqfg  6LeMF$0 lPlT5Z[i5tXB010uI $58 R+/ȬD[VZkN4PzƕjR@` I>DD֯(f\hb})-< pd)@#!I4 &36OQŧz*TMEdXjLu2وֈd9Ft2&&ͮP e@$KvAQաNm8Xzy8@E3򑓵'ˠHHJ4i@A3WhQKPƅqZCu"S ȍ|+);GN  lʚDI`0ZȭQYF``c`2!IIji۞ Aj{{D[ZkNY_(iXajRh'L%ң#g+q&! ̭@ k ]}S8rF(Tl3+`@֭*G)BQuوky!-8uqN?f'#2P%ңfPTd}+K+6۝@+1HfdT>rw IHf%3 e3mM/qBVK)#"ZkhϬ5@%4-!lB&͎OB2 uU|,=Ϡxvn3D- S͠πGN֞@fP$!3U k %UoPH$BWqg32ud!]gAMlv5Gz  4p+'Znҵ !mxajH#)-m=%u0RB CxPGijx< := lǙvT\ $%a3XTGt{u!֒8JZVNjXѬz:TOe@%$'khfӢf8XExb_-i} 5|s2F F6N>f_# fLeF JJskٟ~V(n<pJB0,0uIBRsigJz*Q%Ke)aG5K!ZkhͭTc>Kȶ6_MJ8C6G*$Xz$[[;ULtwfJ5S5$34ڑGcHe:-I>+R~vaev.$VQQ#g=@fUYܜb%aCh=SYсEI4RMig_<fm$< LfUIFià45Bv?ϒx5b%`Ch0$K5ö43N14I֪VPs`FN֮ DžG3#DB&cV:ׯǧ>Wۺl)d >BJT3uiG)ۍesٕ^C9 Ƚ͠#tXZRk"m78ɸӺ{zERYpY!Ie~8[4j'O~>OR%dpj},,Rl[B?==<~*ʃQY9?KE>_ o"7/_='UA$(9[!pyʕz{8j[ҏfW'T )dlL'{:<zɋU)R/t]((ԋِ?}.>>qCbwX $m%-5Зж[(&6lso?G0J ŒkڗMZ6hkogXmkcŎ|Ro$ߎ鴻U5ۊ pͭsw_}qW9[QlCK#/t ]z>6 !mRxp!Aٌӹ3BB"B!<sz͊a\prÔ  zrmq4ʙù #8Ń{gRDyW{ +h ts?AH\/mwamȃdgKA'גp0q Az9鴻1.t!؃7 v_0N߰EaJ/Z Ul]iSON^'lAt`y.rn ,onж[[8a-lky'L=@8KAp5ו^@ &!, ]B݈3XInCYoC+ vЅ$BBd!hM/Y'Bҳv xXy=! A\`г tx,],B(uf : a } BXxo .!8;[Z{c q,:D_NZNNkuDD@'=x0 a]x0x> !ABXx/XHpv..y.[*[ޝ01Ѕ Lʵ YfB`Z!HʄNn sA.dӅ0a.C+Jt liKi@w}kp;@}- \i"fsr!̩ѷD1HB@]x0a}x0NJn<e?NDPDD`tZF*/5ɋ ы3 j)FXE@/BЎo-9]NޑᬖZF'2:7,8nж[Zzcp"@:īaN ׉ BNk*#v4KÃN;q+i۽xp%-:)Rym`eaÒDH{-NڻpfDLQvCS5:98ؑV]68شu_*œI"(S6΍w p}t"$}m-/,6HESo^)Ye$".Mz$ȩ ve?NEs|TJmE@/BwtA#J{O}E< od/ʬE`f8iG^T'"lozF}ׄsir3G[9~Te$[}x@yx.(g '؍s oq}'o OEoЮK ƬZ$cn~*~In_:5^x^rk% @t0';nサÓw+ <F\KhshhӋ+NL~YCpyb GN|ۡi]^Fyhk )Qq5gbBRi|/)LN6Tk 9d)kvW`蠐\= naHL% %z8L-]_8!$(v6%jHN#x[Ǭ%oV6wQ"06*'KK}5rQW`hL2L}_l(Nl_- E.eS:r2DבLZ2@Э+r\XecsO zBY,m{I$й_p#c#5@_FE9qSpM+aí]2(H+hEEҘMeBcu7UH{rt`R2Bu-aEW:rE |怴15:fkԖ5u 0p$Wڣ5N?oG& uՑ|,=2rYt%)jύ%\ZBıxgPڣ(GBSi{8 GDT2g책ZC)lY_(l IR^_T>Xؠ΢*Ӭw/LZư3T9Y{? z$0G@Zxqd3D)Wd=e kU9@=@l@l gH *#Xz4A@V}P]4 EP:BYkh4AU=ʠ(H:(֥2NeնѪ#DǂC{f`u"xg(66U@ŰBCcF#c( Ds u f!յk#Ѝ>ᝁר`#!sar(a[Kf,qa{U @O~g5!- Jō¦)ir$9JP^KͺˏK0K-<`ZƒG3LV!8l[F7瘝!u*q7f%5ļ{gX5orлϴ&.۠@VgVLxy3#Vwބ&ͫU|3JI c ^NtQr/s)JeDKV<.>ek ! z'3UՀsA QqM%CWؙHB41sn\3E9=cN2g: ,,A9%uv#+>I99L[9g9C!9:S9#rUD0v29}հ)7."!'#Szw=|d-9oZB%LOz7`z9W 0-_W0m!s̩,h3ݠPBʶB8usiQ cB՚Xj.˂ s%|VRcxټ}C{f{uaz.,{Joqd$6"V*̗pª(YfO;vɷ谄T@Zଡ଼Dv Gż- f&sxm yXU˪^DCNԈw~ܭNG-c2MsjC$^@wR2Id:&ZN?' IBC㠌ݔ–eTMtd:RY**$Y"̞SwCʮ)1)kjX6bYhhՎ -J,%2`t,˩*p# JGLx26j?+xCIK2M{;zG{2 02C+& rאH3c!-L5QS bGeΎFD2{rzXflT9 2C2DH"mMU&xkF-M,`joqroVߵ0D+^EUPiT5o=1DX, isMR.nFBiD%\2M,6 oLuc¦QQ'&n%H\|$$NCq)>gqi5fpsv՜L3"J˾$#_G _X祩o4ݎ9bhG`T>03D@=0TkmTD%ypIS#N!J#][=4׎ :y$θ3D+HJL[Th 9=cN#IE9{^m5PVNnI'dHR?HF=( }KWe.t)XɏB M.>FYٱ {U嵣$:CCC?.:UbG'J3"Nku߯,X{G(hxsrTT)O(߈9<\.>ce&4GCS%ehR9 sݫ7u s.s]B ݫzd`tL̤͆w[霂hYsu*\cAȂa6.Xt\K v=)qQ,BcT|<{ H@6(΋Z eHYAPD 86,84+L#NGB41iRB~tu1:5)[ Y#}e{k/Y#$:.z٫谌l睊wuU }8ţW'G@*69J= 8j3?\C/P 3UNU9̩negdcⰦ++m ums |Ǟ`bvO3'3X0Wɲ~K%Zn3j̟Xа33jDjG؉ ?`e,S: 3|WB?O7p滇w_>>7|xon?~SdjSTo6HF骎6iGV GKDw/A0Ϥ牨AyR%ɮ.N W^:k>Rj~zj>3Y#8C~I^sUq9jGfFʣc=뜿c$tYNG.sPj>lX@Gle5q )5ށʆ #ȯ.Z`Ujħ<xY?[170ejr,q[qYXV[~_V+wO̲]eYձnDճ<.}d6':޲ zYM"F}QYqY|Y8Eּj%#8E ]wjJU1ئtU9s=+hؚ[ٚ$0U̚…Xk=Ћ*geUYձhJC:Y]'+v4[UPyy.>,z\V8Tv Ϲ{7z>)ys s%#L\<]ynjlN/v]aeP/`O Ꮻl=B`͗ "+) :Qu!,?N# .C1KV l PM"P{tހ0p,mŇ:K Z:m@ezN G ,٥cH,maZ<-k -6V%X1llڰeh:9o C- KG/ ұKkjRkh0PㆲL:bDdt~ S ,PM19a]ILj.,3pӹtA4HAv.2BظL؏6Al/5ZZ>$ePv\KPBe&|KG Y:fp-AZZ:"fK %Q1#ctiؘ6:fkiᵴ2 -;K/^)5/@%Z, 5, 5CeҚk)7 [Ce)-5̫BC.ٔZ-6-69@vŋ3 L[Kǟ @<-ARJ6|ZZy=+Rkw/>rxxztj7?K)mfꂬ%Fk%U%j]c٪ zAfB6Ȝ^h ß }elӄ9?T;9|UE%;'_݄fͫIzFALN?6nZ5Okuz^v |`9:iXۀNq{KN?lv#,ynQ IcnÏIGY3:bQ+n lynSW>26` Iŝ:rn[dܖo("%R u1T2}7cp719ppK;,Q1lC1+in&iU=>rĭĮ.aVS u'k l'ښ}I SNK[+2>mM G tlAՋ|,ݳ:jU}FqR TRQ-l-‘ H[M[-&wOjbh&},9/뱅 I"Wkhl— RY˝ר dQrX&4rXk*kq\#9 na-8rDHR {|B bm *GN bp#!q[uEa  PTaHaAkZ`ݍRjHbCG>M vE\N`a U2Ck T7rvg8ڑR;Àz1ی `Tt*H637/!MfU+]g3Z#]+F^sB/$/T4Y`XLʹkJ|ԲBW[(54GNX#$!~.0 _mM]5%䢖55o82t ?5w% nƥ~Ջ|,=>Vl\=bXE_/%Ej oT4rhC ‘dbOZg%rHl1J}#w!xb +FޒHG\\2X`h ciQSTPSajpY+1o1 $U:z$1IԌ.e_CcnHg+KښB hXz Rl[! @\]P$#%a9@{jLse1 !Vkh4lYxzBEO%lף+04 G>]`Dc}j֋Z}y\@ ^dF3 k4W^yEC FzB~~$^7];= k2yu$2 ䷦Z vFX:  P ŽD4T,ZBXBdV9YcV )Hj-3Ěkf$Qk )hd a `sգb}ّC# rc!PTcBWP1J^@ jd P#%aX[ }IIl"Wph|@a_ Vk( 醋A -T3؜%+Gk /T=r(I^e|eJ@Ze;S!U jj5;+8t0`sW9,q""C|,]o80ʵЌZW@Bd֭nS7rvM9.!|79(]ð a%L5ھ:b[[c~ M I=+5O)Jp]1e9@\5p,1)ɡצ8!Ue@T=%lfc8W zg8-[RHIcCca ~cz S u PTXssV,vQ54ŀGN֮ǥXEGa7MMTv8A.#_X E1hrzXX [A -PTAtM?i qG01YQ~ ı@#'kq00H5Gi`X*i}O$1*C$[y6 >YR9@AdBRlƘm8|#+Ӽy<i )RI.Ar}r[ ,xgػ>HB,)!HxunL0ZHY\oƥ54#w(9Yk;FEz J\q$48&*~/$/7ґ;`H ^6-xY:/Ҝ ClZx<1FE{%zW)g 7^M\܍Y`谖g*ŏcGPD nH -ۚ mS LfU IHWLJ rkee͇TYUÿ54'`aNqz% 7!/04T/X? ~Yn Q m3Wkh |dq.8(,QpdY-o? ~߿9>BzsLJb/yoo~_N#j]6͈x#iu_ʛ</qHVbet7{٤%Uǯ]ٜI[c;fijɬJ@#wk1FDt "#"Pڀ5$:J9th!Li>D0+04u l%:NKBCYπHIJ>K~1ڭ%bƮ+5+/xof o`|%KȎpr٭Cp= XސH9A\ ]SNrd"' 3xȘbN dpsk.Ȋ7m024M(6\aklS4r6`*-p~H@ ]aG,)90A]4v@aX Qq@HgSv k^WUzqv+ &*ܭ X=6s!`TC26` I .1A*n/QT^pbr:ʚћ@ad~ڋf\Vh?il2Kf&n&7MKt j f&n&)IHes׉Ľ50HF gguH]=4W'`s> Hg "8ͽQ6wuNFzd EF6 )&;b'"1II) ,N3ҕo Ue#&.{9o،>d3$}{3lо9*[džfT$GD27t/0&wA7 qz~Sŏy{lvx9RXX7Y{*Kw:BRfU1lMTBr7M'&:RLBCd@$'kOqdȬyYKA.hϺF8֪OTe쿕8=jd6[/*(îcB>ʑz)C9ACt F9ȀJH^ W1Q~vGe(n}aB [?DקGTjF;HcPc@#'kOqя8l8A U=#DEQLB ӿl0"u[2k} cG& FŰgxnn> *TwTн0 ŖzL1*8\y)4Ow} i}wZQw9;"Z7{7TP5yv?Ċr`JN֮J/Rc95Q!GXB 56ݍԋ @ZUs:vЫcnTM#PڪkȎ)UEG ch}`JNV,%)1A^4< 4pzd*, y_(SFؓ*<][T<0U%'kTQlOS#䌝gxZo׋{h,6}6bc Ũ@Fґkxzk"=ёz@$'kQдXf&/>PkvD+*I4Hg%? t fwA4ڧ,g>K2iXrnׁf\X5+^3u>[G XԽ lEeR#,4tXJ+πU,ݻ>*IJ4Xy&Ŝ{:SMP%zB*:|^B\\5`bjTz`GN֞P$d+X)$ȉ ` IN֞P$!+ .)KMehtf72E.efHC>e?2ÈRK+Cp}ԡP  Ij# -44ЀIN֞@hP$%A0hձ}^! ߴ&ېJYft1[IX&.Q@1tDbYh谎`e`2"Id4S5hGPtߴ#f|,bQ"}뿃)9Y&X&Dz#Q14tL=5=2)B))j}p*@oИm KmoZLAcx>=j|)p!dt0j k:TH!9Y{+ &:RMBC d=0jRY@6PcW:AlmDH'.8cQO@ ϰVځaɬf EBYDG Yh谐`e`2YBёTfSowV rrqug%HymÃoySxA-V6*DSh:BYׁDD6sEJa)AZ`2Ѐ(I:6+X$sj"^p^kBM% }H Vҋw ڑ;[EFqv[|x0#'kޚJPt &.ƃ)(9Y&(]L D8SjZLX/% 0q%}DVT|!L5@>Vh@ң f7DD V Mf]>""@KjJa)de3 J@^95xQŗ֡Zqy ï|,=B1JJD?X?L5[ɉy0$'kC?UZ'cpZe/B[b(}wcȺ/sz;>=jP$aouТxQ0JlK$NC,]Dx4!9Y{ ldj#,44̀IN֞ƃ&)L$38Ip4cc٪]U7TdCǢYc?dEXl0~x,*cR4%LYNo5DɤA|d#'KO/ ұ~) H]%S ~. /n2Ŝ'NQWd `rNpk\yW`8X%shL!nTcndBc*)!ȅ x`JHNQ!$B%cprQJ<SJ㤭?k0=4IG!,=QQD*Je@$'kw"ШlH-A< 3ZGt$%),ugg6zLޮhIbj%E7|S:\0/#\kc- ڌ]~,84.^ld Pc#+ :R@BC%GN/ E?R:)ԀA y[%TDv'Q@!ca/[H!ِg;Mz?N&ȇ `GN֞ˆ@$d+F)$ȉ 8` IN֞@$!,,0 +wTiv-\tfzB8 g?(XB9V5*8}pg@#'kwu!(*Tx:$9Y{D@BRg90`Z-Q_wX*βeȺQ¬G;lY[- @aؒmsG6r؆f įи J'ŠGJ(S̩ABELUYA bA \ nQf>χ#fuq|$)cBbEC=H@N)$Ȋ ` IN֞@$!0mbљLJ()QN7>B"[ig FRKn%}IGGRJqD SUnMӫX]a"R"TJ*9Y{<%:g$xB*"9Y{rgH_s_8q%*z2H^Cc\\+݈ԧ{EW]m𧨎SdĭHLS hH@ soԌ =%f]fI`>\.[Ge,452_zGn][4h6;908tL3‘݀6,8SBt .gSBr I< kl*J)q(SwKߎO =,Qwz`A^0ukCrf)W"묭-(HN5[*CjFN֮ݟ$d#%$:RHBC IN֮ I#zԙgjKr퀄#ѫK;ms,;:w*rM:( 7g3ޚdБʁ:5'3")K L1iL =@*t|S2esw;!8R 'Bd֭>S:rvAaHA@ ] LkD̩ v*xHib3X0"ŒҀy8ͨ xgYaG [鈎0dnm2y\XLL1&-G qδuSb/k]B( |/3ӣMt(!bYw%!vJ<'3D` EM(Mё:)3#N8"$)AQsjxuʼnID][Rxz}λA&twΉ8,~>h9Y KP/Ⱀ(!A< w#=HB:4-I!I"{jq+tH NaM%wz:RB4Rk"6EQq=U vd :( W"^TErI_,118%7(u(Q <2^(vkP%؅ND> F. ё : / _0m%BSj:C++" Cj&IEh X/bW[pM gE ]S9r6DX#':RN CCp̭ XCRH C,6Zk.uF!ZyUpPcљ4B~!Mf]4)9Y{ '#:RF CC@B2x HB.KZJ /P[I%^M3~㿽tBCRGrd/ /2Ŝ<(d>ΝuZUȄ0u0U:KC CR%4:]9|d)DBB!ёBd)DHҢN\*S ɵ3-#TqR^2yz.\=庇+}+s̞rzfXL7 !pL_fE 1'QeH)A 1R')IccCvC"`ȽR6g] WȈIʑ z)#5+44.ldn^"!) L1 a*޸FFSsr)*5֩nL=4Ag>o@Yī7q" (kDs0#'kwnRTt +.੃)*9Y{R裩rv-%qF )DV'Cٍ]0{hlBY7Kk(өFhovтC |d횀 ޚPSt PM5MtDKצ YJ8Vynvlvij15(a^TelYWJhi`D6lv6BYphdH%L/L:R?BC)aGޚt/ /2ŜL!1ayYv$(̴.ˮ px&!XL?]={yēFO]} x`jGN֞@c#H":RECCT=HBV,10\v̈uRDNmS"v 4Ⱥ] Ze]14 0jٙrpjO¡\Gw}Xe@$'kO2(*U98-ёZpg@$'kO3(ZRYp*Jɬ|x|S:h jX\l}JfK}Y+ڟ^NRP$Uv޳,842ln>" S) aq0#sC"H` ^,e95ЁkNR%7 =w0=w+IG}λCׁ5PF F|d횀` [Sjw05%'k4e5P^^ PKq5Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzp[o6ǟOayEQeQ\Izҭh{2(V ;ĖZq(Њ<8&1Š-ҳ'At}v=y|%Yx3\ff&u [7SCCuxEiV8w":sfSgy"VML[A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKq5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKq5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKq5D+cQg Matrix.fzPKq5Dt#Sxgpart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKq5D,搮#]]msvg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKq5Do#Qrsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKq5D'0 Mwsvg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKq5DZU+UC{svg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPK fritzing-app-0.9.2b/sketches/core/obsolete/Nightlight.fzz000066400000000000000000000264251250202676700235270ustar00rootroot00000000000000PKr5D,' Nightlight.fz[6W(jbNi}1xfu`5.Iݿ~ R R<&Xh#TWx26p_4w+D5\?,y/,~ =~{#Mxۇ?Er??|{|{<n)>EHzi}q:6Yq{>|=!||df1khlAۛvro#zW3~)|?N4 Uu_q}nᗿ%n?)޾w ?S?ַ{ 1ZUu}6</-w )KbyVie1 ç?o*QP;-~Pe ֘7э.nw kx~W}B_o^O9n<VXen.nR~+| wLdI,Dfcc֯z˽H$ >Z%s8z~i1ҷʩgcpqh~_hor+h~NIL?}X0"R*]fn+[aS+[Xف+pWvF4[d̀=**n\n$GL$Kd~|u{~ͽ Ɲf+39H[olz&EwYfQC`?ܟpWÀ{dub6ž.va} 憻gӪ]PZU!*FWjt'JU,zt݁fWDCƺͲ.7-}Mw3w bu 6([c#ZmkhDuf+ .&:hm7~97݆lk5\H\+#[l ߏ-h6[1~~V0 鰹}ERa|?25B0d[،uőS>Xjy@}okF H0V!L~5B 􃿬gY>7LjNj . u]R8$INa81oęD0B\7?3UƭJCgRȍ+χefg=^}Xo({C7̓ל0`Ubj%ҞIvih{06dS, ! L} ï9PUE|7$焩]l` *xIfnP2 ՞IL]ꩪLKӸʩIjߝ*~ڇ>~1MA-+.-7i<w$^T`y.1%X! 뚵neڻիM*FVksA+VvB*@K0zXIgmw:u^"h$AX?#%snH-'u$$es$6)QQydqw<12KGbpl;)cE&QFԚaUAU ,n C#J91<Dٵm>}2"}v~{s={3ݛŧۧQ?ſ_|ŧ&W=7"ڧEKcq0x~(sd MHXQd65MmioHo_ ,yX738G71 3͐4Y|u،yQ$SOG.czޭk$.~VB퍆/@wڷڇ.מ^Wɗ"˙/q !װ ɜŜj"a޿kasv^$ܨ!1Z*{jIv8?^q=m:N_aZwOf Hh>>ctSty|9iܥxl9_/,[=U~@c߱f߰yzj&DdHdsCF4LF%H1q6ƺBYy2'Z!a,4bx# @F[6es{b֭+n_~ v ;VҴtu{`NGntPfi4 {ڻuեbNꞎ{3IdLxuSuCrAsH=u=mOsS_5_? Nk>>/4mZ$f:1ҫyt٠'ҩ*MvidJ`jW?&@?M2?ӎz*OM}|A!.bF쬽r0ivZ9}0eaXt{ o/ٚj;蟞Xk T}VM w~mE=_毁?>60΁=7Ԯ$(3{Z [=R\mH.G$_oK#D#hZ?Zbk*=?P?KYZ?riȄ]Q@cOs^׏l0bւ^!:9`&.u$I / +%i/QmBYS)BKIV_Jb*oQ;Ʈ%]<yWLJZ&%dH,<9gbg$| NjG@K!ef~"(dԹ$#ƃW j|; ;D΀gO޸!`DN 0ɓ vix2mВ;wآԑ9'w<ӦdF~* o^BfƛpIٝz3XUT\)#$@0biYN*ʠg{?\A۱t^p P< ~Lo7JͩLJYIEvhf5IW6倕+xk'd@(O!.F!6g bY JV:ԍUv WGDajS\&4D;<ن:ΖhdnZnQ2ԅ|gjF$!`(-'9y$CLHuFYaYm+ǐ\ e .~ĜFȨ)!3Y_x.+NuWj6I&-,Cg[Y+7A0v18%a49c'+xR+ EH-Y\5>l-F.J:z1 7fDfpk֡4{tm璥3Z|@inz2q#Mg#7E4022>]* hҋ1kqg dk ggg- na!̢[ϊF:3 cDvSg] c|ED 9I8Rg ȔnpSA\2pEE3GR"$K[۝iﱚ 4؅ (T˘ ^֒%(놱 zm~ j(P'q h/Ѐxy vT-np\n|cйvT1DH5hv@ZљNtYH2.2@>~O8#$Ո#ѤN8'ɒt9#vSBvWr4MνZ #Պ;]'OЙʅ#vS0H=,E 3*ȃhc~\#Ȓ$3e@~[s͸JҵɀĩC YA*&dUE93Z`X<>1C3F;- \F-1ʩL jƀhPNܸ<ANLMiPSA&uU3(E3;-K|I%KRKߔ*DkL"Q-e:~ ҷNWMNb-On,SvceKq{x7 IuChw’)1/i~156,̈́~3YYUsuZWő{.XW|'Foz )^D.qd:pxM55t&Y7^@._0ZV6xˊ9'D˪~',R]0^V#VURfU$Gxt+/6XJ"K7+ UGͼ.\"S\ƖCӫ<ǟ_7cԊ,>뻧}H}!< QOX&IKٜAsd_X7w0~:P=М6zVa`9q ޝDBu'PsaFt> ,;V>m &@9}iMVA2Ou7j؃>zԈ(\HưfivPkAp/kO֨FX 5&0 1NflEi47#JG.P6Tu/wMKE;bfk=w64L UDn"xgd$ݻ)ymn w7H6#M⴨M s[wC{( %kFp~%H +)X DU;^HRB U2p|Ye v&K" Ȧjl@h1"j/GTFCᎥ/OoÕ9tPh%P<)L@[~E7x`V9HU<\v12 lX@P~)%_?|d& pV_#am#a골 SJ;n H6F Z6$Ca평ȶ) |d $`$dH6F0 (b,8Oy%xHW"dF2t| wjt( Vd] zcq n`L3Qu|ݎ) Tpډ ~qOthG+.Yj"$E8鼞CgJ*-@$rN`LYsD#6m[ Rv3ʥ278",'A79XfZ/&X?ܱrʀ+Q5 X4ͭ:^A xf|V>Ȑ6h3g 6c`Cd#< C\ZPV.A{_01ᎥɀbM4Ctx!FS;\5 D?d0S'2`?2~wKbX(u|>'.C? ?ݿlmDg߿_}_W?,y]G/jj5RiDV|ZYۋ#dW^T#x8FR7)<bϻx?..@%jWy}5'ZDpEbV^ mҷ j(T^s{U ogL 6tDT&uJ]u{aU ﯠAl~))G4+WŰ/ R+P s&Hn6!e4LF5Yq=<ņ$λ 1=s臰JbOۆqfTmo}a[@c,&wOan9`,>뻧K,|xqIahڊL_N]fLM,ևSKe[]8`o_8i`tιq :16?&4] :^Verahm;dTG۞tâݍx7pY9 R<ҽan{Þ7Lu,[2ѫ _IVRս %M9դt%MEդ]+ rcBZH`$(v&uEmx&Qfq35|]i* _v3(=Ym#I5; rs4W /Hۆ.Y W9Įa3uZ((ZtdzIUlYd."u>‚ۜNGQmH-pjKʆ>@K7:)I=&Ȓ7+|W!8: (ϧ/yll,V1{C"⒵˃"]_ zNpo db貆&R#T{ԝP]6`ԴDRFd]2ЮJÖY",/&OPAIG&8 2NÔǭ XBbS>=1/w`ZYK~Ib{ yon^’eqs ƿU`_,D9TL%6T¾o:RJu8W;H6,ыĀbGVI􈨾`r5 iJHԠjtm IU{Ix裄*H$hxj$lIiNRlJ3N3LJ3Nj)NiV6EK $ nz&=Lm0qe^ML҅Jr|SI@v1CtOv/hٟw/\"iMKR$SWtql J#T 3ʚ ^0uay1 A>vi* 4ݝ`Q.roQO߳b*/LRQgRp(z&HpQÏJ rX0|w橄~7YE\2zi:z>ؗȎ.چ 8Tqeph S 43UR$A.< a/2 V$rl||$&]<#:nZA 苿N6Pd*l/'x ɌICdtfAk,0$&`hj@ŽXiNQf]w,(<8R%Oh'ПYK7N  H&Fʑ79TDJK־"-kDv@%k_ELdDoƈC)Lj(#\0!XD펥#"'H26=!LpW!ĆTDvT=@!LqW@! ֲqxm9_¦űEHe*iF51Y,[ Go1cV]c0cqii kV.8c$:ۃnrN) ̜g\yo},P*{F- Y ^8i9uab2-UE\yՑN J2Uw.z";'B֌XD7tIN "2$p9pҦ|eDI f;M[4HG:4`TJ*N8x1Qc@5uk |Ȏ6{<|8nm1 =o9e!F1r$:T7 EKV|w֥Buɹc) ȉS #( $Hx)z9`i+3V7Hx1^ÇT9]EEvㄖɌ'$C9;UBIV~cb։Ϩ _^]:bЮم@%ci [h=jT3\6QS{Q>< چvM}0]K 0 l7 /%K{BޤE3ˇ:P$;Y!`㨡Ry|THpZd~9 GDI93>k:ԍ'όBȎB6ԉ' BёP,I:Ĝrl?`V EB%HEoOC;G apqHwDV9LJUYIv /`#05%k_Ì@td]DvT=aK־ɐsʑ#>CZX#՞A2XަgŌc&/֋[h KHOZMdG5hKΨ )!Q,,#zYow=[~]O'2C? ?ݿlmg߿_}_W?A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$"-e3OCKO̪T-]I&Y%ٽ/eLfdɬ`@Sm2% g>>O?o)D#n w7^_x~ Nۏ{?==|=|߿3{?_}?n?}8wo|xxĝzbq(M?}cû:Uo~~K|χV\{'N;ō~χ7&χ/ŷ_/SPǛLJz(_ۧS|Co;T~Ϸy>W׍o\ />?V| *:pW\EY{P}o{{GA;m߾|S?]Sq#]n|<|z~o?hwgo>߾Nru_OcWKa5zV \˯z{/txxx~Ma*a_1V|"2Z7 =T=S<R6>]0ޏ@vqwh{ާh 16><<.7l9vx͞.elݵ5s >c[mȶ_zҺRYق%hbKl(Y'f˽s^ S,&+:q`c}2Scf%9xPQNG,e];)~"42QRԹBwȝ⏚ o'h^ ^ "Ͻ/m zK{"IB1%,m,Oʒ0^JsKq>Xy~=_ͧC㵗ZSp+>;Sވ]~GQuN~|:<>]n|<|z~oOwg]IxCY4_=?8OcWKaOzѸ@jAVkũq3_A=%Vcgu;7~?${2\0ŭZYfXFɬkqg]9uqs$ŭ^"ŝu} V@u֋絸e|¼XeY^;j`l338ŝuM%nx.ZYIJ*o26wO2`n pQQ8X)Ga[Yg=@~) cu÷WHN:|ga l B4xDɷOHbk6S_fl28?ɳŏIbi_3kv =p6#7UF:gu6_;kk8;jw8טиnB#ul\Fz'#zi1_;ak`\7IɋkCFs Lx*|;ԓNRǔIⰂ@IۻRCE(5$*(5Ĺ+5;_RCIO(j9`Ӫ*<ͷU&wĊUk7+N%S#%Z:Y^~{~yz>|x(>If߿w?⿷o>?g[w?tLk]*K6Sn?\;W -A3z{n"CS%X6 {3c~P}c74& @oL)U['Y%vRU*yyyd0V%GA&܌gMݧFcfLN*YZE1 oŘdsCfMzfd`>Dz@1xi Ƥɜ33]H5InQ~CQNwBLkU~DؑTo C'!U%B[.d&b 3TDUzW}qYDp,CMFTV#YFE3<#Y¬$yLeP_76 vzw -9any(~>-[|RNKr32JbTP=O;3ы 1=5fw29O3.0z4 40+{Sڂ0<,Y4P[CiJPV|Lu-q/G0tQy~~|^\W%)&VG%[x_D ݫx7ut _!5]"^`/ e\x)`e,+ΓeIJ-A+_ٲ\&ّ/& ]^|iK#h{ C{rVFu%1@|}7%+);1+ZAL]B@\]2j\,ޡ{ 'U/x$ ЬtAp M% \^<3 ŗR4E񩥙(aڗja2'V KL-Ov}Ej%?&ZKeg*M=<*F?%FŒhWKp^cxݍc\[w9p;T:>7?w|sO?]xGHn݁\Sּq77Ϗ:|:O_>;<}͇/kdz%p>|.˨Ɨ)^{eu"//Y} qmlaҹ/h2ttOD%1rX\-YK|;yp sO? 4-w\03dI8@P:a˒5 ΐT.{sփk)4ljoI'%9tdKR{JNҥ)pƊ,pN@mzp)$lgK.l)d_k +iX},T8Kn1R%|-: i? +Y[[bz/X,$i)`גB%9^񂅻46R,,1WU\JJA`yua{KV'Ap6%St, -4xBhn+qT+,abFu#Vjo>==<~|yYUTC/pV%~u:"UCZew'ͱ~d|ĻOqǡ@o<~{_}(~w qcovwtxgt}AYZY^d_2O/ۡ[||h>ݜ&ӛ?-n4ii#IiMI6G}kl.Eq"_VOC"Ihh# g[AR7?]V{@=?^8 ld 6 mҹ|\%B 6NP{PS/F^c{6x;!84[?kd AM򂾈6/F\"]Ʃ]އ]#h5 "8kdx팮108˻&rmY[T5 PR1S%9'BhNsފSO_¡%N]K:"csOKBu}0ɼf.ז+e.nu'4Ş&= F `ƙVKi\5 J8jW5 R8jLVϻ%WWƹW$ݿ௤o|? یVi_+iį3+O5tc)KiQG) 5 R8lt) 6i# 'Q8l FWԔ0Ki㤰zZب41 J85l~r(AM6N^;ElS$J9=6NYIrn6)6*JPY qe_\?]?</>˓sO,Pܮ{ރU*/[t5 YW75Rkyz:r|8Om`f߿wosN8/O-SjP+7$?^H}LS;mAǯ>?~9$'U])ɰ;4"%wޔ0F+77 &<7BRc`di0xh(*a#Z/_q@`RJQFat"$cukxl$'KO{@"`OL(0̖PS3'WZr(%| FEo6ky@v63‘'6xPx\(@gưN* 7L+nQRjy׈ yCٔekO 6-WWePUIԠI4㚜#RK>딝5Be+#uTe`$$&mb(4{._ܗ\;qq"w¨iF|,TRjN[\E:.(80DI`0Z(“بWҶ1Zg踄`fg2iI $58 R6ȬD[WZg A4PzD†jRpd3L!H΍//nƅ&VaLsGD&,.iLVGoՋ*\"2Ns &[\LdFD&[-p6$ `jR3ePTIIep"*+9"fhT>rp f<.(h -h"+_Ɨ$x;qj\D!c|r2>c5JJih,1 Rǎ(9HfޡdT>rp Hf%3 e3]M,_—DGQhƓvk< UEL LkJBB"$0Nk e59ӢռCG=IJiPd$&3׺%?[I :Ch/L]B؄\Mj2[d@$Xz2AQxvUjUQθ.^Z3< j zddEA"?Y}d#tj0*q7g32pe!]g^Mlq53Gz  4p+릍':a* 5!mxajH#1-n?Hjo?RB Cxҡgxf`d3aGKj,[g 34ˀH>^ `4$9i-3Ւת.կBgʼCé d3@2l\4c0L]/U^;AJʈ:0}';'SImrgR-pd5qA곁Lo$08 1縖gŋP۠5ḕ`g2iIDRsqϔ%D,Yn-LPHha4js֗ ip$`(ⶐ\M*8h@$KO38"ʻSDwbg08\1@2< j vdXG?bbe@ GP6 Ӟh3ЁY Acz+,nfRC↰Hi$ AQ-TxpδR3ŏ/P +6 y&4xEDQZ (0( ԪzNl}+g0qscaR8R⎰gA4( R|v^j˳:ToM k5l]bh0u#'k  H;"bq g,oeAYv#\7;ETJeN;] lYam l6[*&5-4Fc`$KONi""ɉ,Z:Q )˃HdޡDV;rF(d\*SPLThKqIiƍIUl+N4 VҰlAƁ3 J"uW<ֺB; jޡ ɤe4 \\F .jnZ"(w4r֦Yg Dhs;óJ jJf["y`I>n 3khg(czhPUJ;Ĉd+`FNnDžg3.DD&cN9ׯS²Vfl)d>BxǦ˴HᲥBRNbS眏k͠Gr;alZRk"pF qu9HeޡgdnΠH4(FvϞRb:7~po<_c!|?>ce>pP(o>|<|/7?CP ޿4Y„vWf]7opϧkNSp*6bOŗO{j-7]di[!ZQHn)f =:􁽜TغrXݵퟮw_>>+oO?]ߝw/Çc93S]_^U<ϽO?')-C凕,%%qe4sD   Ux?j#_zuQ^^>\myz /O1Ɖfur$JNy|84gw?.p NG?j#w3Obm5|܉o`NMz*7[mﲳo5Tؗf5-N̸BY"D,\1CrPg >=Vo߾lVn><&U$NN&~Ufά^>_?~C&౥}_[A}хa-6Ʀ0017!͵>$o°]10<,'C0LyRg\p0P0 o7us&=MA#\»i AwO|110΍BG!p!yō!S kIx5k NO7F1Ac{PҶO q B&Vq7s҅To9KfAAB`cכBЎ!ea!lﰙ*w.-]a|cr_CA[xf8a9VeP>؀8~ oB}_C>E?FZf2g5?(??hڏ}_ VҶ2ƣ+ 8b3 ,  WSqje$h !jÙ}xH%UusC\  zxϊ,CI 2%[-;(Cf aG ]m ȣ-n2R Ւ6}$8m226kAc0ek?~>/$e+?qRAi/DXcCK92u!_.8cS, BwB'8+^0:],(B,a1O%F6΍#k?G>!?F*<) &|ڜbK =1Q̺20) G*lˈQl0'b'Zu8݄[zGQb%g(e_ #`1Fع߷'?R~ -Fh #@y #icZy.7 %a #{ b#3XI"{,4Zvbp+ ~xiq=2N/rG|(<C1fպ;ľpS!}iWk{UPW{ƫGW ͻœ﫿p{|Kf߿/%ʠ(Ͽ{hÝ0Y,-rJmw_<>抮:u|pq{S2B- cέb~F3dd8rt⯋PʰpC%#Z@RkR0~K.(q^0r7 BGmlynӍ+e{34ZZRҖ^1j!,^1[g - ,hq AŭQD.Q؞ӽ0#ɑP lZ8ڴm]1 ɬX9 .8ʇyLr+wZ ]*z̢t<{H]ޡs P13uMM(9 2-yW :SYsUoO FL";Fm|9/JNk@0@ f6ґX~yn ϕt!``1lt"V6~ !zydF>FBKhshhkЋ+N„cQЏ/T8r2[2HM(EU]'UHm-ޯFQTZ,&Sc_j=~rl)kqg訐 \ n$+a$Q V'U'dĆ& \ SC_t$U}K"@D캁4^ƼCK`FdiXO9jZ;!{y#|,1Ɇf -mix#p*sDа:$ґ%FeҖRuŅlYOS(Ϗk.Gb0L?.-%:LJ91(qqjb aa63xؘǖIe <GCҟ, ɔύ%\FJXghx0 jdYp#"=ޣJ"jaU Rg걕:C),աY_(l YR Ư9׌0(.n\6OItXN#LQ7X o(|:V֞+z>B(ל`F Eǩ`2B[&\h0U)suX9GXYtb'4:x?xjgZT CQ灬CwgV=?,ͬry&U|5;)QnsW>xJ*i(,@^UV?suf ]ٚމ`L$~(!*vI! ݫaLe$"r@7 B(W~/^: SPmo.fI=I;:LJ)@I:9L[:H{ՐLK:}C*"y;SHǥNqatNFR's;p>w2Cȝ7!5'd0m[\4"wzUC05LK;7F ݫdblސ;MdTwJ l+|_iZҮQf]Rm=SjM,ǰ%'*9L̍7WaJc,"Ws|1]7k+^㾾> c`[DζVJ͏ls 3{"ݜN$l- \o(K]A3 kPhx+(HqՎ^e[' N[Ǿd_}C^@şw*T;KTʮ(1= VcXe@#+CKIJ t%" @TLM!uPC[^L.?;:UD\fJwWeŏv$Ʉ LM&r$%:+L!"`]0&M)8WhNL%F٨9sfez fez&s5EvB-+$ĚůYV})@TEWxU1Bx5M)U=ÅE j5S sŸD_ȤL2ډO0H6o!ḿ\n$h$5o.o:.ț\|DMr|.+ڭ'dvx欃;<' o^1͈86(~ /gG 5X'IoG0`2Ԝ>PӻD@=0TFA$ tuu]]i e->kh'T;ь.A" S8r2S@4Lc@N(!?xM6kH_Cj9 jkkW0 9f*@:.#ۇj5|cxpU#9]7zT8Ǩ'NE`V8R`!AlT 3N{4Ngʒ%cUUI['m1uyU3Vn%#?$Μ^pi'R1uKF"Tq޻gԵ?/sAgC'`+g,Ԏ:|c7dx@bS9 3|?Op/ oOwg] ݿ; #ٺ$-N*hP[g9oOOw|d~dL?sVLj >.>u}S5 W<_>@LqU#Οϝ MŒ HNd1.8K>\\U/tJՌ[ .8u%oy]|LIʌ Nu+g%Oy%{J#\=qӝtte&k9ӿe)'[9{cug Wf ǃ{y'S| YV<0A/߲HeXŲ2^VV$U+;|dŒ Π} Ƀ֗R`OL jRHʷFN_JT,+Hj%,˲gnʧ%31yS7N׼ \pubR03i:Ts1$mxL:;n/hJ%,$5re5éW,N=MΊ*J&L -9;W2I7'SM_%JVy$x\ 4aIN~YXs(zZR& EUb3ĊC \i z'D݅8tJ]Uq!!VU!_^çPoߞz}n><Z.eovwtx.^ec'cʩ+S Bc=~0?~C<]10?޿t*ͼS[u^Z;/P M%Xi#~y_%K浄}*(ӴwZ& YXyR^T'O 6Kڅ# MR'[y4νk')Yw%vF>Ab MVO#kjckh儍5Ilf:4Zԇ)ce3ӡkVXyީT,ɏskGkg֎=!ɯlq0$}Bj; :0az,bvدB:&b9cguaJ&Y~CzHLbl]N(̥'LFZU-2oyuȰzؼ{翥3?0Bpswͮ8r3ǖ\F LҌv 77 |&TCG0?ͮa~T$`q{]Kgbz~L}l-m~(j|-Ar&n F]KP3yLLtil1]Z=_|t-AZZ;k||-|9.{,{-M}ۘ}gЍ}lkn\k_Rv3c*8lKO^pgb)k7[jWo>`+@2YK3\@F]@]rHZ]he.%uV}T@AGvzfڰ ^Ꙭk_FqkW? E/k`dicK lݭKoFkߌ'B "{KIPNئ=_ͧC㵗xˇ?p۲U/|矿~×b_ϝ]7Oq)űygLg֧ۭ_N'+rbwY5sD½Uo,@Ғ&ʖyUĈukvQ%a@?xMa߹=v̾_<>(f9L~|s{\^GAiUV4國?m&>c#Kw^pdY)m)}%-=Ïu6tW5r0"[m-םp%yśH[ޡ->0:uܒ ikf8–gh`` ^cW+6;_`S0"oad $o=G4rF-ɀVy2CsQM d?Nےˆl^ً)`vVړkRK}b8L/RTRq\9 n簎p9Lk"騆=x1.Wh@ -9Y{2Q "n[d#ei[eVJ@ 7aNn}7bhHMb˻m  K?Xnc\1(Xի58l$rd& Ս{f'\`a@jm0*r:H+7/԰<a5agI a<6Is;5W:zT9jBH^@E#K~֋ e h}]QBi!T紾P*9YgcG~u%^rB._X8d9ه@ `.dm-а/zgъ͑k@,˭~Ps GDԒ] ju*ܢSPe' !xyǺLM o#.,qa344TC¤9Q()_5|0$2ʑ{OiLE|)({$j'_Wx¯_]7~rZq/ dKjk) ӃgZcQ/(J9l+,IWp"'kψwAe@jS[Elo+X1\I:CaV-FYl-vDrgh wA|,=Fz׋ܓ_u6U/rt%QA*W^GEA,ÕH^{i>\ywl)pe@ߚ* ;34x/,`lN\-PjT5wZj//W=rv tb0ojH"gk;QWHkJR_eL-3 -AL`Kգf0lk*G>rE57}G{yb/FN֞yE9b `u,񡘔Dʶ*~awCu>(9Y{Z+yknm/Ц@5#KO~͙kT/_ʃ0ꑓ'(H<+cRپNC=*>lFq5 ZBBCe9YT9lq"287]qӅ'k4h.g#hNzC0e9},k#3sE6. Go!(M<|ud?٣"ۃ=4 VQS=bNCm| :aINҹcGBGn qS̶w.Gh)!!XzT@rt.CCQ!^vTAu0uܖ2m0< k/pTa.-10 ]g:ᜐ#m6mq{4LJI)=94ik`) Ԉ\DIAILv% ML=qf⑚3CUޡ;@(!b\$5l+ 6C!y;Wț&rX3)oX87Ty ܚc32s`u㽬FWS mL&H.W216SSӦv4]$geeEU4:8d2"lzUA0u6CDZ!kvUB21v"5#irr.;vjXծZv Odqj{gi!Ӌ6!Mi]ȜCfmќ~v.0d H$#%PVFkkTQ1\+bh@㧟 ;(Z*KŜ,'Z$Ʊ ıTT|̧j$ xC6tl4ݎvrXgY#9O34a&.*s}ɾm6} pH_g ;I|NIEˉu QqC36э֜Q|, p/J(Pݸv0;t.d9YnI`q ݸ金IBM`HrDޓT ~!b]\BQG0 F4$ kX?ʀO<ZqƴiޡX!FFV~Ĩsmm3P9Y{]*G}1^T:d""0lnMa0XP3@ ~DELc‹u?U~4v%Wc7ȼC` SKǀ$'` -XS:11 eX9摍fXlہm<|C`JGNX:D>q42AI\D%vʹ üCZ?(&bbs$&1l$/0pN-SCw(8CHL(ӑ Jb)3J{+f0Oq")V 51'kEf$-LLC`²)|C>sY$9$ #*7G' bYÅ!N'`N \X:tB_s4̈0 Yi!XM\Xn Bg訖`ˉ$ L ;3W exCJ%$y9T5Ǒ8ROAub`&𜃁A^#opdJ״@95Z\5b!}O).V344^T=d@wtҖra74<4T>r ""!GqV"ӎ.uܩ+&5˰E[Ubp4 vfaZ:!yJ ƕc&怔@F%V TJ v*x5w:CI zd2( "F&*Ra1>~U8?N',[)3tDY ˦FʀHd"vMɔcl[y&2FFC"r|؀qP8t6M7ƘDU\ogIm'.79o;%%QsL'<@TA5O/Pl~3Wghp |d5XBb^Aamsy6/;}މ6r(Z[O!yH 8]lH&.hS3t\J0704AuxQ0pc"UhI}aےt p$ Aѐ (#)` ֻaâ/˜*-KFL9pPλL|tÅm#yFjF>" sȶTTHנ/lU5 T>r( _+۸K|ِ*EW\1;Jy[-uo#Q18V,D v4Hǯ>?~9t]\IjsI: (4EWmno(=iμ6<%8pVJ+#m%gD:#P> 9Y{r Ą$8UVk1\v9aܰaFssLh'ϟ.v'5  -uPdlA8 Yh@'74/̀(HL0G9(qĴ&ҽtTytBllN7rw ѳDwjsf$Jf} 5rPRhʖW! Ԑ|,=Gz2 BT`B dtFEYљ FY3DAgwμCW3Mr :@:/mJgm|Cq td98D>"\f9sDP^sITB fAN֞Ce@R7OaJJ_㈤p"3J"1Q2o !3 0h22 0.p>nYտmhbQfegޡ38',=ʹvs6kK +ϒ=Z_j2ag7#|$$#O20}ytC:d&Y xdbtPJG4-Qb7żCXyR !b66I%DRNWC)%AՏ|<ĠhG{*@ 1‘g b Ӫ#T9P"Abޡa a&rd =}`ؙ0K:=t.%'m#YQ. A@b@$#O&1(⑜\z P3H xD$1;=y= h%*`x0Y{e{=]k%k9,R}Yw Fm1HkgU2{_^rc99 2$>qPaoP ` xƘR Ea֓i0bg ;tUPQ9DnN^qN %ԸaRǜՍ)l+gdf1b( TRINf D|Cu3dD=bYD=зvѕ-5n;YC5lp:$}g$31\pGXJ:BgU#$3( ¼ Kg2I  p\Wuĺ#I7BC<u١ .yN=Jy643ի+X<ìFb( TR΀Hj: rET+l:.fɤ lvoX_m:,qbH7™w"m>ќ™Je 4Jg') L%!AQt挨@g7t\9 iPD$1:"*A< 3g g*2YxT`Sv9 :dn6wKqbJR26zQ<c@#9- v 5nz€hGL! !ӂeLgkJmDEgdݨY_,)ύpaOQa + m"0?48<SBT"#,Q>Ro 1fGf](HAn8;Tgޡ+YPvs֗ gr¼g2vybg !h0|,=ҠHB`oDz#i+`L 30 D4I#cڕ v)Ip*-. AH d)Y Ҵ¶酥&JHjCI c醚`ƕ5C:#hU.kq?c3n-6$Qǖ+N"W!訆 L%~ ;|CG53d D9"2bL`0IrlQTdsi--T(IU;N`ޡbFĜ=Fz dgj.Hg;k-H{ۂPn0, ) AՐ|,=:GA> A|C GN\#p5$&d&!Y,2As9 t+%6g|Nsx H,Ǯ!T F}:R8Xx {ߔ6bS?1t۞@6P^RohXhd9D8bX0"uk澔%qk UL%kdžyAl2icJMtyAJ(c-9KՄ\@ƌf٦c  - XC )[D3M#f U:&LkEK]Y6&.N3B, oj-xbZ12ڐѬ<>'vSN},/`~# gTJpILg tE|C[Տ=#rECbZ2d(IJTiWLn3\μCOB2[̪r1VCR"C_y0Z}SXSy x$Czca0u#'CO00dd8ŲǔBowJO0a;4< GNC [ CX=5 TI'&7%AՐ|,=ɀsx!* A0 ` 9Y{Qt˂eLFf R l'd&2Ŝ='.f"`(>LX+dyߔѠ*I>DE1ژ/}d42a*HN֞DE"2܄QPӚ.I+G qJhF%:Ȣ91;n83ÀTNFÙ",Bn3:f8N4(EZ"YРP . tA|CWhS>rvC@.=*"seUJ^N lTM([\P:0>Jg*'Kψz#nTLDkӫezlqkDQ$A QΆ t6|CGb$Ae#Z}xe), hM/S@->B;48*f9sstSȶԦMl)9I$Fyƣwh`V\H> Q^ohp` dxFFb♊g  "pU]lZv93l9* pBJPʼ'+Iٿ,7c|#c#oЀ,P~oYzkݒbivUvպ=E`rNlqwhx{ lN֞c@6x/Xxhy%:y whh{ZI荨@o74=Ps( D4AiKLG'K򅢅GźWU-ҼC!%:9˅41^O=Iz8iJaTJdF"#;}"*AD G4g h,DWJZ%{s lqawhX.#-=<ڽ%ueBR`4 "[D?4 ~dlH cu e2 =#"1D0 Q٭$a ؖ [|+w m>`?)CM)/0b1ڀaC|Ԑ|,=Gb[~@Q7t0#'kO104qyLR<~-'8]yVU6 RABjA2OŐ֊*p_Y"eF b`$#u4,Pol \I x$}鹿@be Yw,-i|'Yzpa$G;LҴD lX2=eN 폾aڶ#%'18ѮD^셽z@e#cKVm@o74<ldnmXC %hn^ ERǬHF06lqwh0i r0AXg2Oe}a;! 0⑏' G@X$2`" 9Y{FD IJ e\\;[:nUiW h(K,{lq=bw0)=~OB$[ ɒ=!7gQ::iG{*i&$zA4**F>Fa`"Yρ 7|CGc< xdF@""X"c{1Z(4NP#b!~_PeSGzăP#%fPD$%±FQrA*Xz2AIn t;|C#a@#'k0(úau3~郰Ϗ"?o~pxtGa_n>|9.-{DbU|9s ZWp<Dn63 ? tO^u *XߊcƜO/v\K?f:WЕتr%]obm уQ :<_]ʔ#)sg+EQ xPjadoTW.,JopG%gm5Lƞ2}S VcSI E0'z*}eq~c$E@( "( E u#cJzlϬ$Sj-.WE" O\!bBPODJ<+0)aC4A#UHZ\i^@r&ֻ燏_}~rfB<4q/T(aQaO̳^ȋJAt&Dx3K<26` ‘*@ ݟZi@#&nN;ᙚCjuic_HFn F'Zcw*ݜ"{뗔A-yzb 4HH> bP#yMX2D gg:vΔ#h)o mFWt y@g0wrۤ2?H#-5-?awh0T|,m-+Ϣ $ tH|CW 5򑓵-[RLinORwh8y:.ҨŐM) ci!AJ 4򑓵Қ)&i Ҧd%t 3`:olƭ| ;QT$&Ȍ-zŬ%N!TYլ[qɉtf,B|(v02fҼveI^䴇,4ň=(af҅zMCkH>vcVp Й4_k%ZFH$88#>?([B+=μ0$O'4#4$#h> S@r@&#4v[BVPgsdφB$ųT(Q?1"gfAS 2H, BT`Rg@ALe0*ֿbT:ct)Yvulg^e'wڛ8[ ΆwӴ7{p֣(XGVt4:^t"-,QH!43LS DDbLh#-v3ĭ"&ϻMq h^`DK3FDGR蠘0Sic8+=μ%3T D?k BT`RgLg Ĥ3Dtvxb(\gD(Q?18rެ% di?h`C3ft2- , 1E2AeBZ'-̶KhJ>ߢֱͼh0ۋ=O[AGNwED6F H]ͪf d|UJИׇ16Dc‘5#}CF|D* {XD"Y=M/ׇE0VXt0bDr=fO4{ vف,L8TXQpga HNޞuDDb2d6@#M-# fTpk^Q&vG|q,r`8*bgȪnZl&a*xz4 8T`Qg^}T;rCяf##@0f)v"*)TbS,M0E(߫dM(>E7{Y4<7&0ogm]@dMaa9~sdRU$yC#|2Pp*8 iҘ]8-uQاeTa4OwOTa+)kD3w%D7 F4L%Ӫ ZLPH!4) Yy[BLh.BV"%iEk\L tDbEA) n[40$#OhQC#| @dmQ mi&.Y l.RwmvpD=8Gpe$&Ș& 0Ҧβ# >T=6<  &m-; i<ї4*JqD7 Na I>h("uCF"| 0$'oO4 h.2I@J\W&ZnɢPv;RԠ&f#Dކ&Qn~vuf/ohJ#$X04=)">*`lo%I6QU jO6հyF7'oOAM6͞>*JhWF5 f4L) DF3ZrX tD=@D$&Ȉ1MP",JG % b#+ isANޞibĸ>jJS0di*%xz4HrH ULc "#11F4i=n#Ivlf^g"s4Kmh4#Mάo^t|8"Gώ : LȔaFNޞ` 3QB X_ & 2TNޞ`fO ISl\^tԏ|<=@DX w .@aPvĤu1A:CBvShY[J@6~2i0izH9yoy2Qَ8į1%X"UPRW͉o_Z:9=y]xJcxx`vKFb :T`Qpgcꑓ{$E P WhlGqNU%B1ĔIf3!o':c+Itٍ]QA;#O5 d1TW6R'B|1e:rE0av񔵄ʃjcbe^lLp{eaHCX.#k0KZ27 &3L D9Ytt6Ԑ=@t$&E.8uwQPFګmt@f2󚆓J[;Kfjx8J*):l[R9Tox UICe0*BC"| 9y{HLF\g F;;cadX:0H;LZH@Z!hH]w1kXbնCiP"#xD#*0)3]0%$'oO4i&r-F'0M*B ʮ;ԲHw|veQTޛTkhzĸ -hƀ=% J}|6((X)(=JH>f0C0󙆃~`!1LF3f+Vf4(e1'oOȞiYf 'lbDQ<&" J6džgC$h1v)86\ȹ1^7=\6"=k|NAe⑏SpǦD*0(P3 ߷* 9y{ HL(ӑA@d*j!7hXWSͮu]kaV)X Ȱ|l+7<6c^`T|<=@#5*0(D3]0%$'oO!2Id.*qJ3!2Hsvgpi:D6;`YœzTgF)Z즱M SB24fPH!3d{XA"B㑡A@3iر}l`j%%quw/ yMz@7+PT́c݋ۍv,T۲ّU~@C|<=:[",8PGa2i0JHNޞ-C`"3:Jn=jl֣d^s*'oG2mCѭ HMC |F> c0c#cs =`$&&00luק ]IJoZtڛ[ (H_0֗[1br6Q$۲ ->_4t"X"ɱ,4Q1H3iEP  EFW gªaDbdZf Y4.fQ?[4dl4P6u~`(Ô|<=`d#1 = L@2L FDb"Yvќ*$]jz 4VXvwƒbXz46k~d Q 8PaG!0i1PSGD'TTֳ2%&3O١T!1i2 -Db/X4@Vxw bڑoV 3dC| d0%$'oO٬"#1,nhN U =b4њn4jG{gsӎ(i$'oO2OfO4d'Ր=&(Pv (C|<=Pd#1*0(H3] H""1,nhN--U 'nA֕skU0ֵZ*}&Pt]ʘ!DeD)ήE_Sj@#1-yȣ0t틘 ёLKC`r4:ng^Zv3eW&.)ìvHiCLB+} e!x`vF-᪡Cg>f򑓷{D2Q4\&q±=QɇaTYGB yMLY̒G9y[]t.Kk J!(CgBP4TEbUC$|*9y[JPZь!PZ.h5j$B6;*5]0rJ:Cgzeٕ ف"+"*0)x3]0$'o"1-rKioݪb+ܴsTwy[QUS#Ҽ}T~@*$z5e4[D')oJiRGS$hDF#|*!9y{HDL,2 L[IEh-qzPpͤͮV kaۼvL+:_|T8qN0g#zzA3N2m=e_g/no~}qvyͻ_|zx/~Ż5_˷o;/ً?7۳#ًjWyfpmY^} ~E'_*Z8aJgf 5}Y`hWIS}U7A&7\C+/ Ff/;>Ur3%֙$W8j`? glU["y__|ׯv&zn8QpqPyĞz.^ܼ9˛J]=R}r{U5Fx7ϝ]UKŇ쨘f?^jVz^Y-uhXYCXKn2+%9ʚz~3N/37H[ %tMRqQ#QU`kLS}wLj5n/>|_UwwzE͗^~|~~ߵЛWͧ祇hkdѸwUooPG֒h5 LS!ۻkְ5['sՆRG]zZ^9ϯ=|{{׫_*ѨOlȋTruU}cnסNӟ߾|\S}HޔKoμBisڛ?z1o|`]KͧWw/q%?]]>yKv|W!Ս%\NTgӘdzi#n8ٺbsߐK9>%\~;~"IϾ7iol"-ǀN$=;^j '(lY{/ Ė 6fUgMH !%݄knl)4VMhi$Ѷ 4Bhc# apV 896b$ &89IKG1G5 %W[<Վ8lk:u8f"5MR.}g74~ٝnXphLhaEE{d"jա)߇D~h5(dF')N|W_xi OJ(x(*)GpJu;'(r R$鞝7+dgRl9&uTah.REq[Ji1hˤˇ1GWA{8TZ:9G3`*8AK2E0W$;"OgY>D(i_f%OB3NGuPKr5D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgoO8)|$Nb;eeYH+ݩw҄6R7~)&Ʊgf2R+>XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKr5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKr5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKr5Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKs5Dl2ie Ping-Pong.fzPKr5D,搮#]tsvg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKr5Do#QΡsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKr5D'0 Msvg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKr5DZU+UZsvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPK"fritzing-app-0.9.2b/sketches/core/obsolete/Pingpong.fzz000066400000000000000000001602151250202676700232030ustar00rootroot00000000000000PKs5Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzp[o6ǟOayEQeQ\Izҭh{2(V ;ĖZq(Њ<8&1Š-ҳ'At}v=y|%Yx3\ff&u [7SCCuxEiV8w":sfSgy"VML[A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$%&S!l:eﻱ?q2g88SJ,@aI4zPLk5pG~*#rG][ѯKԆ|2e a_vA`>$LCx-r+q.&7[Y>~n̉=o[Xg]h hM$jP~AdJs X\ }o ъ+=̀}@md}Q>dF9@A |ES O)/ph:Äs4ith}bLӰ~ n ;T 6c}ETՒfLv2EKK q/ jx,x23\SDzgcnIf@iMdx-ƞ3E4s&l` 9뤤oݸ]ճ%{JPL`GvH0Lߑ 8#Vh8h gé + Crֽ H@X!0X+ngD XI6V'Df#~;fUݑߜPˆgt+B6;Kif U*qɮ8y2JyD6;ʴ6oHPh-ݼ][Qyn^T-$~vDVooW]>IT+EN$QE* ]PKs5D#ho Pingpong.fz[su~>U2GXIvxHc 6Yay O@55 ,"k!\7_/n^=|(}"TA 7ݵyz_쿏R՗}Mg>\|ǯ7Çފ~Ά_=|x~x|_pǿ/ҝxzp/.7߲DE7?o[k~&[eF0o'io/ʼ|y^=zxm6߮3gze/;a/jzu^|./}8}w>.2k ÈUmÇD:-͈Tʢ{H$O]m{|1Aֹ֧q}huhy1=<>7Kެ9V ۻi}m6d[mk]K, [3l4}Ow">͆b5hںnl;Z*ݗٙ׶Hkm}vPֶ>6gNY:e͖iiIy]؏ kۤuZk۞~D9Gٔu~Slf3l!h6sg`lf۴4;es|`@"H}O2sYٛ y+JIcߗtXTm-aeg@VN#R0Ȕ=@Llՙ IDI#R۔%Cֶa==av簶30{$-9m8Y ='K/'F LגyhB|۷14Aۿ~|z?W_ w+Y!kc~M!'o# CIн$}&[1Q)9yb蔅pz#B %n#FRC籶HhYo$+C,v{@IO) LH7߱DY/c?0$'`蔅$$I(jL_Hdo]:e u:y 'qs#az@/Le΢H}RIH}W:F;  FR$ַDdgn%kYcN2eYo$1~!nKF&V2<i zezw?>C?4+VThr6b0uQ}V586/'Pr@:ecj8NڶFK籷Hjio$S,퍤~@IO) LJ7h߹TYSSXIy ً`b{ aIO) IJ` ؘv`߾`1uʂmǑ΍wY[7~$v|pF;HRFa< 7inL_TLl6vo%!?+乕IK$NXJj~*ٽ[IJϯ$W|GZ]/^^^|DN?/i}jqk^OVP{c c~jΔ>\er򺿽ze|p x}]}}͐Ou_~w?^/U p|Q@F:.^ Sr`w>H!ړ9(I/nN:9s0vL&eZ;̾S',ni-4(^<ŝt2=HUҋNg yI/&^I_T)R^.tĀ] 5as7IZm62JqXʶٖS"Ea q.IL4OfȍT }c3|#]@ƆMSC r x>lUneDӾGĮRIo詩[mc)K6F)HbGob0D*7ة8ob k{#񊝺 ĭFb;uZLamo$nkmc⼑),.vnI0zqÒNscb 8n)X:e !@bVl{#q!a}ņb3Ql nD3vRl0vWl0>ņѧYiOGo-yzrtr5+!9s8f O_>8~)a}X~k6DOD;u,%~bv6{//}|7JˈВ?4.p`*笤 )Gar&`OklBGsWحDF]]岈mu]T(\XQ7Qd0K%A7zԌ'Mݤ- Fc`Km׻b<5fbd[o!(F/5d=4#c7F+ҍxTGţJc`Pe:JgTCs}mLG#Dn!݈=/MC0K&љ2T"Sdl);[=Rr\Dn0ʓɠ``&8s(,u4:(M (G˛%C;52 ̺(EsŻa+Ui}~W{D"6#;n-=Y +SAo&@O4 -H[$gNH\B%W" x`˘{~i}~{P#ZYWFqaҹlŸ5 <%ѩ}xPƬ%B|.%,U DaTBtk9l{:3{-ZJCk.yvqޛGE{rb-lKihEOlcq wJ@bYԝHj̚&Zȷ6{/IdP5صd%ٝ 1 8p%(_l9h 5Tҗ6)Zi/-sy3;G{&9/(I鿄beeZ^:xKĀ8"ׁEϓ?P=+Y>!89?|x]<+s~əO"w6Q4z>Їo?V}ݧ/o?6!.{Hds?oo_옏VҶҷ6n^ﳿ2(lNuk<Bp}}ӱ掽XD@#onB7p rMXfRH~tʡ6O6kĽ@+j rKM}t~WWrx.1}ұnZDvq- ܨwu吖]_,ʁ,]OՙX:<@X#X7u% 5z"g2T%!nz/^bD\5@58ꈤ"!T}y9L=>\8R|R`I׍=s - \qA%&KiΥ4JZ9̤R@wvP.=ؤ[# yRZI+t>mqA]௤\6P\ؕ#]:o,Xn,]xwv列ΧCQ/q/Kiȗ 5R_ 烍gW麳Pc`ؕ``l ;r$LSvXN%h+ix;DL҅RR.њf;u2n {qE3#(ė9={ۡsr?Z‚ M[6986#Io4"[}z|}}}s,Rs)i%6hSS-$o!ɨH:V&d&o ՅCvG 5%m^B C<,ƙNo*j(%{N&3$~epYfmql.&?VjSSK1D6f"˹xXŋfTe?Tc |ꓙS-P >eg}Q mp֞ pVʒh0$K p"7ݠg\dRњ<:LHhG<&s<.i gưZ(]+.&NA& d}"upBհlx&D:ȠH:{dFC?2㚜sŋigF0 fP#%k?,#!1,nC6GuIP rհѹ"hm N AJBg@צSrJa-SYр( Fܶ8i6[B010eI $58 ReUdV9BRZm Gh0d!a 5B iդ)#g`*I:DE(θjWrjCg8>))Y{H\#eŅ2  mTvw߷Q,Wqb+ALeӡGW=NΠYlP6+BY`T($XYʌDZYË;G6bT4*)Y{y f<.(h2-i"/0$ˑ3E@ mӗ&I' %S3 l6 -(2% < VV91ӏr\#_K@010e) Ĥ Lb>@$|:BѴc=x#x5)lt~?Y`4J{G5BQhSTcӡ`C(36t3‘D5BP⦚Yʴ9DzmV$ڞԼ{l~"eӡLB\f'>WF#N2J{AQ̘%=:,0u;m'D#NG3򑒵Ahi\4P,S6SD $ZiC=2"ՆP3x6UQ L]1-0SO0e* !AhyT#SF^jک ̢EGbbi@U(M6t RBnB؈6^M 4h: c|EE糝;Q7q&T6S(RYm4򑒵 f& M͊N`|r6SHD:.zch֧ gyBj˂JR`keaH–, 0Km2 Lef+Jf@$qkVP ҆:Ok)e$#"Ymt$30Rv2\$%9aiLTFұt}uU#!֒8STM+Qolt4BYpt(*!)Yq If6.1d5]/_;2LʈVڦ0MN';%S g]d匳ɒR:)g-SY2"L(t{Y0>kXq-dk#AM9s@)UkDy,־&ۃP̩hBU˳>WFS4Xsml6:o,0t9P%I= ,gZsѵ3CURwL35B=?*)Y7Xbtl#E'% go=bx"g-x~ WY\ͦJJi"v Le3(JeVΩ3LËGRCT[I>,0EϠH4J+@4e1@ajgg0sqS€qW>$L: ci݉dq(;MY)j<8SjCy)q&0Xm f0u#%k H;"d1 -ΔǯDbp]*,Ų{Ӿ=^ Yl@|V6VL ]i,0tt,;,Nd'aJ c0 vdqP#&ɸTP$UThK q]c|2kq٬}p9dI)(mtWNA8Ɩ, h@d@3Dx(rjm;avz%0d4 \\HR$/*{2}t6 Ѭ6tYo |n1@%)ltW$f0U$K4O543NэfPE\a$`FJ.)ǙG1=DDcZ]C#ml&XmYc|jo iG֏>FuE ;t4$]#2w^ cknHsuZB1lcYM:‘:Ah$f믏ӛl:Wד̞sv?sn&Z{z~d5 Tïw7;K.eeoe5')n8Z}ffA3 l|# o 6f2=Y&6/GueYԚ1ʕ[!c窕!mu6:>6[ d: ~uPKP<kx| ~?1`ؖ, GEv"9?-C8醣 ƭ"KgZ5ѝjau:îxˊb餣)z񅂣\PtZ0'J%>L%> YT3 *D :_,4[<YπHHL5pA,8[3YĠ(GD㱣5XcfRjvy. A YXHG TR1ɍ <[HZ$Q kQzuHbݢ$̲$D:bXŕwDZј1K8zP?YM)^<[V5<"3 &\O=ɡ .}#abM1e* BY&CԴ gdn@6 LfQ6 LFWT0#Z{%MxG 0v*.6Blejb`P-ĎC< 3♒.Tv1a9JT6S* @5$K&3(4M݅d֞Cdv29*HJ@gPT$")`0RK!-2k$Sʒz}NXHAsBmqY!l\ݒmLH1iۛW zH.6[i6 z` 5y9ɍ:BI[YH8'wG5j9NW{tu7$X?-Qia^5: TARF"1MGf4 Ѥ$PSu8B.Z?qʉuRZO8DF !itϗіz f1#fmh$B{#Y@gV@ 6BCgF )Y{AQ;W@(Ms$VY%]3o(m7FiV؄+ kPVaq%JAJk:` I:9p"5<>2Zp S?R6?5` gZ3MAP1Y+tPEj߫rd%Nȃ#,@6 fzaYoi *5Iʎ b" ?D4S cghPddiD `C3A"3hVC (Vzƨ;óqh-}ZrA*bJBgɘNjm {(*>ҹdQbar$3|S i9΁+!X?5lCMkd6m,ꘔ`#SA 5aUhn#(p7R85` f&2)hf8a?2ɌӭM0v' N' NG@6 hjz/CEJL} BMC~vtiq?:}? eeGfYy{ZybLX'0T > &|dm )֗qm` Ӳp ;YN Oqz XK~b?4XaIFZ` HJ.IH}t4>:f:Tk/ƈĺr`#ATƀZUDRfyP=޹|N(K{d.6F64tFŽrk5VלT'/i~JkJM'M*4tu7VMoBخnJ+ߴ _|{5^vcn"40R2[Ky}c}nT'Zwcմu +qߴ _|c5^m'QkeljֺzWغ* 0J"%kSk6mڮ&J2C'naH:nYpdiXQ 1N& [\g 5Y$Ok{(%oeRfvm<-SŶO M+p׾µ0Vn%bwP)jR_{ MEqSQ7UƦ 6&^l%XB_wb{.My}fi;:@ }C'ajH:|]5?İ}7L IC@d$&vzRZÕ. 3l ̀GJֶX;D\kAP]-鰑2X[EKnRȄmIJX8<^ lC3 ﺇf B[:ߴ<Րt, ~,~h6qR&@%3 AQtqfV=h%L:lP6FL",H9^lиMhy2)^ޘ"Cj+mPy?Rl-T}I FdtY3QzhMϦP›⬦B]{ӴyUsc6M;&I oPwD*K-GQؐ+J-7Yc~BNX9CoZT?ұt4wVQ ֦ͻXJHJf@d$&Ŏ QؿS `7[lnJfH9pl5Eszn:B@k:`H: hPI6s|SAR>"LGn`deuiFlK_q-r?[ Grh:'궚Vw3h{,yI =DQ_N[.ʝl'`45MѺqY9͜)V YkGtYM[i^) 8)nIF)'/I-A uTs=TyqwI[s ̵a5= k0bzcUU$%Y]rb-wUt,(֩5`mpؼdEE"bQ1 FU.]%t}C%(/p:-P)9}pYrZCG!!5Lg05$K3 κv!jZNYp tSAR:"1LD3hQvtwdPnΖg1:sO]75ֆ!YMO8aXgHNd9~t"?YЩ|85L|:iCSЧcJ.=pI q 2 39kj/6tCv 6WMs:`ijBޖXel\ڼZ^X2fn(z锅RX{jr7Q&j,aLZf]$'V&HQw w<^l۩U4 r^rj|@({zSU[Msoڼ?Ž1 DD3l77;)3Դ~Sˎ* Yd?%k7_s;AL 6!X1X&H:#Ԏ=$~$]рIia^Ku'H!^ ~J= ƺuIaC'Ôt,?tnPjx! S6R# YeFUN} nQɷܧ%|an.%FPyI^5}:/>FZh:,Î˶PPv0Â)+O2/͛n~ӊvIܼ-ĝwW)IN{*kLisb M;7W[M;WX{gyUsgPT,=aLxI]GJYV0)Y{H\=դؿbVpt,?@p 5- dmLؾxd!@$&E``v4(#}2 d=L6@ Ĥ`jLW2ˬ $7Ul,5H|I*像?W8 Ԉ P5XH-b,bSjZ Щ<VARvo"1y,r"Q;)K8nDƖA& @g|%8^l kSHnm$Q5Db!EetT##0 ߽~{O=t==?f:~Ç/g?5{'fߓ;Rkq{9?][==\xz||ԫ{ iCNnPZĺ3Ѧv3~x}|g߳!8χׅ]_0d -AQ|Ҵ9D8VDI~q|2x:Dw}?z.#|xQ' s?66,}ѥ g=,w|;JuqNaa5m~G,?JwmR(|(w#zmd?G/ܽ}+[D8%?oo_ZC-h hEˊCv$XUtѦMXLJ 6#h)ܑ9VϞ{Vb" YAxޕ}ʏĐo=]WY87KY%N|<}YnF:?E,T؉9pyVt99kw*nEqÈPElp2*>37;50Mv̲{g)wL=+ݳꞕcRQRv,G*c#zCM]W`1-ɲ$|֕\\FzwJtѢs3*+*3tҎv"h&\۷ZG+9inh.䝴#h6Cmzm{wK.ZUsu2]@}&Bh~\-{/p q 1mJVrZ*p`DawF-zha<:h>WA@U1ug ڨ[ ϖ ]vhAǢ@-:h[6,xAL S,(uuD ڜ?,!T숡LSZ~ j|О"un#tТc3* :*Vv5 PB|R+Ҿm.Feg}a y߬} }mڰo) uhh}mVvHZؑ+7uҊw'mRʕ<*GҊ֚HE/-Tg><'U7vgU獅ValHZΫeGJE/mpBN A2EzFMvC60q/}Қۅ1]V~,zpo*PZ@¿Vfrlʡ|L{idK^Zxϩ3* 9*{Mbi)-7 ʖvR:4z)3MvCr OD/-nZWsӎy&秊nZnU(ibا" M HsG%7j7[w:U ݴ覅(yI芛#[Ezr%p mrKj^OfN]a??~C[ѝ߲g;Vdi \6t SFlC'tl'c-It']\qb|BEC.qʹ@ tT9R2ul  \;.'EU]-@HovS#oZ}5ad]jP5X@ ))-DW;1r€NIᵃ.I-5 j=jB:̜ p#%C=$+/%z[zYf F k񔒥%sU|QW`l#%s8%w[m 5S9"WmD#ґ%th|f2@2v\蚟Z~Z&G JjU)sEͩJf{\_ !Vͧ}~׈0at?dqzb ̈<>-0VA906ʾ; ' ʌ-`z6iE]EɁ"L҇DjE},˰7JhU:24ai8Ld&i0wV;s2D]&_ ,4td~!%BYDU=14}**$ Y"̞R+uwvW1ar He t$ehTS.* MGSf^&eztY&c~DuRSD"/l!'3]t p^*S}uQ*_JAuXсp`t`,fTQ5Ɯ ^Oa,fphp`,f`2(Sĭ*$LckQ fsq CEST}J졢!"c6OfWȘ_.I_hDJaL(iT)st:Rf`hx eLuc񂥓L,Vt g&s3ejH'iPΦq8'9R;ʣyko c!#\ǎchC_ T6(3D/Q}!eҨư[ISLl!l]k=4ʜibGTfhVjh {FAhTPV|&k 7G}#j2E{A$x# A34tꑀA3f"3葉%i e)GTkֆNBbAK 0T vi)$Y5Cf"3P՝en*280bUV{Ҏ0id*&plmofIUږ̭aϔ|Ϻfm(1@ڇv4n'wpecqod53x ʉMK!2ҕ g3>zD/_w$&d+JWXJ}Ҫ(dʧabTY>![sUNd.' >Ȅ 2w1/f_ƢBUO=H9]0BӇMVNX:o1Q; cPMT f*?o^er򺿽ze|pCw>7S?ΩZdrjz0Ma5HW`䇎ۜ =+\(~Y~x <v%?y_Aռ|1UU5/-N /6m҂vqVmaskn}-͔dھk0!}k݀}-@g fAgS.{[ =tz )\Dz뢒̬ 4<^lŴ-emz\֍iޣrvCB;:V/Ϻn5E#Ŗ&{\w/㐒vmGع/hE(,&PƼkЋ̺ז3uT/mz^͋b\\ng]Gu_4mloC!=Ԗvz @ymTccv!Y ;D*=‡J@ڤkYish ֪ ßd[!g`& V*T[̢~tv$ 9}UznS^j7 PffqJ y/FI8S귂'*vJ$zCu{eVWD8 \:˷L{ll}sog)m] -B7tPwu4"u@EOȴȳZ)0$i?#^#9 #S~Ϋ&aKyPؐF ^nlku7)B_;jA |MlFyXCP#^}`C]uSr(ڵ MLo0Ur߯y7V8i/7kGx*ZIXCn@0$njg eSc:@jT7$!@C-ù~Q*%yS۾G)uF(%yO[s'u=Q'+:IM*>G8v5 79CqA!<پP(1|A} NbU'Q''ǽ,u>!KmGIȭ`鹣:A'ޭ;PGu}km_q#}l8C^"%[C/KKuyK׹`5L|pD,=iy]lDn4;*s5.3[;[yvz᠆&rkaz 40tswvЮ/-CD;nF~ ܞ?%xǷ|y||z~}ۙ moaR<8bB㗫/?|aj;/ojI+Z3F`ߊx8ˈE =Ae}_>_\|,|CA?Mw_^|s¹I{|{~B>桿NQ6=5 %۵xw-A{^w^g>pՊiZTR8K)c=UuROO+:+J1fuВbȒ(4T>ҵ4ct%y #ccEޤC"/StMAS\Hڀ%$mj댊Juiq"w.rGіPyaʜ"m bMk [* Mx3 n?"X%`F:>&W1C6QE4CwKmv٫6t/BjGDr4.{ |XY .VRU%%x5]j[M68&nh kNV0ұ kP-XtK;쏿sŰŠ%BЂZpE#%kO#1i+I0Ph*źAqIr%F |AW6l<2dpynڑ8V`s-z[V\X{$'y`HE,%` $oݗG4rF-ɀw]v=1EQgyY-IjCfy) 8{-W{֏h6rX`$X'э9&Ӛija/@,TAd2 fwUGDc .(k#KQV)ltA \ 3-],d/g<덁WiJu]4xIjSYF:>,sWP1$5ˌ ĮT3Rv>UWb1_\Cfy5" $[ap3HYӲE:]D+VGP#fE̪ ; hd!@#"k'\ kbR~t(]Xх +[ &dmхM MF zT8ұ! 10,y!.W9RvctT.}Wc͡ju.G暩+2WmԲҙ*Nj!su%ƮbixCXQXBRQp+rrAe@ˇTVۘ%V# gCɰeu;/5l@?6 [Mj:F:]`4cy쪉mRx;SSPU/RvkF.('[5g_b-Gt̏U:qG:^ k0x5d2 ׆uA ؾ jc8*$WE1V>#G:̂y]`5#%k7!&u $:Bu1#RD]3jC'Su00%k-@qiyn:*G:gE5/!v#g/FJnE9b `յ'ſDJ6P_iXQ)Yߡb]"8p6^S+iՌt, \\RjC)Yב݈G\y,eL@jN鱢gXAq5%.:C C)Y۫0_:ܴeĮ aF:.0ZҌ" BE/Kq ӑ HJW[j>(_X${1$L1LˊA:ܴ<_SՍt,]R !a W4RvI6Μ8L^@kdۢ"5hpCL jCWZbH^AkkC:#xN/K5P24 [k]ӹ fdj;wE6twqSUB%JJ(jPek +8tzAy:^ ++viN$ЩF:.08ъ^^'YFJ.9Sژ襍X|Q VPdjO}!IcKb(1ZG26␹6A ,OwW4tDaէ:eOCDp>iI-OaNyʧ06{Ps㵶oh(ѺQڐXLxP_Tԍi<-0e’XN֌St`vmeNՀ; o+VdɢS굋P8%+hU=T;N#unZζw`K#ȖCOE _~͆^>=^|hs '6/vjU w1J,VrAM3|x}|g\fsVċ3Q/D /j\^iτVnnm\7׿Llx]L+6VBzc+|!ϓvǭ$—k;Qtqe'm=чo?\.qrKM!yۗ?1$~AVҷʗLJ )I>[OYK~ngGW~؆}?gAz=D'9qʘ|m=eYٯ5%LX>W}V|َ@C1{0?$3v'_hٸxzi<}\vw]ʁZ?tɿ@BZy/u_Fו #E E܊NQݚk96$YD0CTTsI SjX$IJ0(Sm\ˊ. qZey;$:=i-xc|0&q&aia0H %%Z{\ZT˓aVFkZv )Oxc7Tx9}/8tPb}sarTV7 _`ԣ!ꑎ{bQ[O&l>BC=ȠHHD"kXp(Sȴ#LWNDIܢU'q}/Q$&!nZ0N,s#ǕJ­jU26S$.0ezY\>i,l^DUU8Ô (DVOJK7W*_p󸥾Yo f 7YCܴH~SOGcy hoxMלFyCOp_Hf,8tP Iڀu$" ,`2G2ēfCDH8&=^ l8$J7Ӎ<:ǀG:}HE8`@YH9՜`$$T=R2( " (JU$aW֨]q¸?XV:CB Yo z-UNM7ͷh:9y k馣2(ڱ<)gJe$t{A?D 0 (ĭ XF⡙ufcRcLTuW%"]{V2I +,[a*NʔX(M(R:k-SpXV72s,PcʕZ(F-M"Dr)2\岑jC SYdD?qPԶm^ØD[29`ߎC}oe1Q'$ЉoP5#KW X腚ӹU: fd5X7bK\A!Fo=BV%z&`aJy7N74:^`7Ak^9ˈ\O܀jFJwE7٠]PKs5D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgoO8)|$Nb;eeYH+ݩw҄6R7~)&Ʊgf2R+>XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKs5D5WePsvg.breadboard.starter-poti2.svg_b74d7502644af62082cfb907907ef696_breadboard.svg]Yo$Ǒ~m?yŒ i,Yh/'i PIqdzGDY%7 hgEeEy͟~y>o~{Ys?~gǟw_7뚿맇͗~84H 7=Y/׿||8>5}*EYϷwytB>}?B0. Ǯi>ݾycbZ1y{Ͼxx?}<.~./} ӏbvzsp:ᝲXW]{|}o5?\?;>x{R~ܾ?yo@ٮy{ys>LJ[у\TbaX&>dN<e {߳0h(KLA [j||LJ&|Yj){G&f P`<Gi\7_ki&;Dzp4\ܚ)aʨ'qaN)PWN& KS>d+RETF'XT)H(FQc|sab@w;J]?kRgDc_<NJ_?a?Hp\Zmg~ K ,|^#^?4vSyx[Ǖ  :XC&`լlM~.+?҉e?G*  .z(9j*˶tMdq!~nz<(9XoiEZ7weDI44m*O9ޛ,T qb>D=~AZB5=blEF B? ]'+{[Ug5P1{l gmcMUC}U sJzGt3q`6kr%/mdٌ&XMĬXM&Ŗ6-0[f-4Al: HNN*!T ?C6 _@F^~OT镊}Lrpx <\e^r7*beeg,)7* up2㤘ݷO4ƴCT0Npfkj4\A0$hH4mD0pf4`*@T:D( z ,䃀%ќ 晌4!C<| ^#"ɩM+"_1sFK3$2F*XBʳ4T 4'uMC8*Z8j؊RK1xܠV՚7# T,6вe敮=`P8}Y>rЂ9H$29U}I4aF4+IF ာp! l'ĈUJHڎhʎHs<@c\W~4M21T.,4/eLFU̖jT.UT?KTK](# 4Բڣ-[-ou+tU{YxKA3ks[^AD^}9ӒOI$YGj_!T#QB깼l7ïwa$ HwCl90NYM2/PNd#rw3zc Fx0H%э@^!;4ސE`HX0#dQ Q6ԁk !(f-9Ei**lR+d h?HɤinUV .WNC1(qJRcH7w?qC˩MU<ٲlӌ9gR"r&QhJfcLcЊDVF㼦aO> ω׏+$`ozx!vE+@P8Y V9Lf+R1bUΆf+ҝ܈xn 0x@3RBDUvj1u55xg05-F+j0l\Z -kE3@6!ύ G9t!52t3@YQ] x.a2 \ DZV6vp]EMY^$bE3 b]1J W;G5 Aّ!#+[hZrkkU9^9&WS0kҝoReG7^CErxHTVCI֤;W t:f'1%GEk K) KZ(栰5zkæZΥ@4+|QZ)Sժb9b05+ xfRcB+kMs@3 VU8kBYMkYO\6c8!dz `)1w2fB-a4&SNͰ[cf 9"1y,E땟`B1LwЛcE3zq\!ZUXakhl+W"wTؚ|y:,/Zh!`iTk/Y7cck-[uX4yC%wЛ㱼c@QZvF,Z%kIs@{U栕l5]Q+lMs5%\oH [FdzTQ+lMsl^ܺIEza$ᗂhyxLn(xI+/汨5ys46Kuw^ ;?xږ5ys,6/.zi*-خ.YsDbrs$6|Q7~kYzYaibȴf5^q\Z/V3N^jeRm.[};mmO;0wnxaܲV߹Ujm.5LfgzbqyYN1Ȥwl/1惆`>nOfG'nqԌ6;y>^אn=w ʘ0y/ @@lCLLw.'_Dqo<<p<3.OnT>!S);~|,QE W`tJCwJ"#PUYqqAs*ֆR<,h5$yҞiI{iG`F {}eYίˇߧ /d~ @h6fwW]t_ RȜ/3'w:7=l 4GMnZϥVyZmpWm(NtN3С}BoeI,I[(2ڗ\ .eHņ߫ V=Կ1v |C22*)-ƇQ3c?Czӟ!ҷnN P?ű:bl4hF|0/CJb2ضiM͠a$.U{•t?&6(QI9R )hf> %(aC/)T &4%{U|@_l$ep56^i(_ a DZ"OIs#)]Sjj=!KŌY ͉sfh(T(s㒸wL0G$N5&4'jYf?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tq}JͻovC/c\WÛp8=vW=W|y(<%Xv?GlWKɅvn皡἗kUÏow;(o~5ww~n^?N\.OSwxӃ^_Tb[^O1JA hڼ~4;쪂VUo|w:+e;KksE=s.4hv@̴wN6W<(l}dfG#c +kstW@t[.0r[@~X9=J6A#1hɑRK$'%'J<]CveKqe )쀹c !E*y$fFDTܴ&9;3x9H,mHodJ5첔cV{E㿧ʐw\|E}-~@uѕ1[w*Yh+#z@0X诲9odݛ:X-Y[ 1… n…P q? (?{#tBnV:hSlƿe :5`&ˌFFg l/,8dxxdVu,YaH~@th[d9rpQ"Ey8RO[1E>fNM|ml̖kj׻]Ejbx|hˢ{ Ϩ՗X~w{[Gӈ^L5W!uKވw4äbmsa;h@N7BJ߂47`^M+3n dπɰ۪ Zw%P VlE2;;DZVFYY3ō6|T^CUaJ]e2 3 p2 n5Nv>^?n>@`:pulcw?vLjPu0p8XTC=zK-R/=u=Sg*eZ|6>OXVReHm.?J AMY!k!Y}q!4*%j5A6P%igrKK>w9x [ 50ʁQ*0+<v¬%aD4 m!&{NjTΪV陕 i܉5#Xʢ=iWY#h*CsMîhq^f T9[?t-03+|pM2P嶦XߜCz4{<\OA FXo9WV̳8Bev3E701(LalCJM*,XW Su 6Fc#0 rrbsjhTcmv;VV`Ў.f6@\0 &kܸbvfOj D $cUP/ &% uM HI*p[d T0]T >w2 ATjWd:7Rl)GLRG4Eft0RSik$fE[DW81R'h -(q,5$߄QT 'oge.%SBNkx'ZXeĉOF1;K#*eX>k@p9eUd#ĦM)M ZhR:݀ |anc3gOK\Nu=?˜<yh͘fuaZ1Qd*дӀGT)9Y!M"Ќ#۠j1"@3&s 44&Di\/Cu"H&Mr={ÚD ڐ@v-:bx9akd%$ّ,FR.hIVn ڊAϰL# $5DsZ"YiLt:ɲ wĈ^Ȑj 8 JuvBUr'U#+="icKf4De>HLeeH5fy'e  pE+EУʺb+ی` T1B{4B"?L-rЕ?*4Qтƒ+4}Yd) -o^[rA?Fi24_3-4.vܤ$--;E>Z |P77n$ڠ04DFM4k⦯#'[Qఢe$هg_Jt8jDCT4@'TS$kRxXmsqOe @B7ӂ\\9d5hfGC'xZ6{H n&,16\tG+ӿ7Wk%љVaEH.!Ĩ lή.*NJhJRpvcpnMద%$E l= R8)z70F4 ly6Lɚ<ִ̓;[[D](M# '*e s%t[G*lmr8Ő4/%fF2T)7k7U9&.̈fz8A`[G+lebkǚT)y,5! NB{b\iU c㔍dc2h)BK8y,5aK1] cJ0JsL1]Qq [s:8\C\$dz rz%\H&je|].|ȅO$yN&,Ub6`.(%vƷ6rbJ 奂=U,@Eֆ.c[0ŔEJ7[[`i?FK/15) ${R3[[jI+w# r9ksF/q5aKZKFyiIO2Z2Kl om%-+W"reKVdڨe܁yĵd:6jkYx\뙊EZ\5H[(I::j+B` Hʵو8$V,tMF,c:o_:vKl om2v_%ݪ%"Yژe9,ަJK7ލG:|.=^#80^:TUiꝱzSUkq"s0Kc乗f[L{kln٢LWq|"N@Oh֙:尐M%s~nКXq:"/s4\&\VOҫ3;2Az+EBdž0oGwfiyr9(0i^7q'>ݦRsW_}wMo@>O5w].hgLߥ|^Xqc|$m _Mvnl }ݸi~VEdq/茀x(pGZ64H3]rd3jf繎; :pw7 |Ҿ* ѡtc~k)UHoN wAጕ Z0UZ309ՇmWEiD%E[ZnMw|"b}d 83?] Do&hF,kgL_ᛐ^V5Pq~j.?bj>#g:5=pHq CL#QN#ibz PS_ۢ(uٙpf0J,VBclHc6 |NaTf۲t_7kj}Bja +dz";20xD!)sCw);C%\OT1g5X#)BJV)ՙ+vRوI -3Ug]憗J?H/PKs5D'0 Msvg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgmo0W\iѤbl%UjJ}RT %մ$ `kTEl2 y.ƃelӣÀkJ5+35y$6IEوQv?p3UC\)F8Ռ!"2N/` i1&QYC\VteL-L3QyV\?NIm5,Y($WD/wL^ecc5yOTxkQV\M pOP.jY!T'Vo9#ehedaTXyTnS0?y'njYE봈"TRƴYing8j~1({F[Fo9ppۦU¥ ZWܯw\Tz)^x y &qCkEh}'102??\;NiL٧("D͔t7'QL~ =߳R%1^1,zR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKs5DEsvg.pcb.starter-poti-pcb.svg_b74d7502644af62082cfb907907ef696_pcb.svgmO0)nދ8vIFҦ!mB+v|e/b|w4>ZMLtN889>_˷3( t8Jfo3}#"WeU(>_ٶЦ|p.x ' NW2π8G.UNɲn66 cA62SGKElؤ,TLIaD)Z&ˣ(tUr'P Ŗ!ru)bYQ宥؜j 1 IJqi\2% 3t#gLetus܆؈01]W\Vq ]IHo((vw-ϵ@;YP#LsmI%ްzF#Vn`JuQәYgKQ]{FCw;aV؛?^9}}=k[~_%FtNKѩ4)ISj׆*ea@?jܣ^$<^DoD4_ 5Ч^ۼzͯ2-S#߁BTOTZ ?sa8>r=:ukxGDZ?ҿ5}V,֑X?6f t 3v뿚PKs5DxKsvg.schematic.basic_poti.svg_b74d7502644af62082cfb907907ef696_schematic.svgT]k0}ﯸS /e6( Fj#I+;NҬ4c~Ws1~Yuc8e#6s|n'bi2;muh]=/{p_R%e|}\C.&h|{L!ڔ9Pg[4mdٶ4-J"W0F≱ėMj9jzI5=߿\4JAwp*Kme)Wan8_ IB,iDi=9ƾ09#W0u 2qf~5·Kbb_k EofB)Oi^-Z v( ;xBt1)0h^LzW DLH ?c4NSV+c{XwQdD3cAE$Ox&xn z!2y'g!J`8̡ ?;6:NF7p&2er,Qb<qPYPt3^]PKs5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKs5Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKs5D L 9part.pot-small.fzp_e55c4e524988a0331c383c6d9b004770_8.fzpPKs5D#ho Pingpong.fzPKs5D,搮#]Wrsvg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKs5D5WePwsvg.breadboard.starter-poti2.svg_b74d7502644af62082cfb907907ef696_breadboard.svgPKs5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKs5D2H#WaC!svg.icon.starter-poti.svg_b74d7502644af62082cfb907907ef696_icon.svgPKs5D'0 MTsvg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKs5DEsvg.pcb.starter-poti-pcb.svg_b74d7502644af62082cfb907907ef696_pcb.svgPKs5DxKsvg.schematic.basic_poti.svg_b74d7502644af62082cfb907907ef696_schematic.svgPKs5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPK sfritzing-app-0.9.2b/sketches/core/obsolete/Potentiometer.fzz000066400000000000000000000265761250202676700242730ustar00rootroot00000000000000PKs5DQg5,Potentiometer.fz[sFϧPh}`Dލ9;CITPlݟT$@5 ]ؘUz\=6/KvioVj~ܹ__Wwۛk W$쿽IFݓ}.H/w+OjVlfhG~s+6_Hk!ӿ>gл_7oɹn7aW7w~z}=뫏v_6_g yzy?:o.nq[;v,^~Inn?)I^t}ßXͧpuws=3?_ms$m/>'[VX}XDx>uw\yp|-?Œ-{u"X+vO}X$H}}rlOYcn{)y޿߿pgr<>×SN?4[g/ۍYXW7]~-_l5Պ $l./^H`Lia8$GLnEo#u;\WmQR3J_toe8kλ9-􋓲KK}f>'wV+fx>Ѹy&;̼tvxf\ZR1$He͓:Z|X%VX$.`{浭 aN!Zl] C^-tV! t[ ymӰֶ kp|@?lڭw݊'Uǃ`kn7[ƺf!?"I6ż>w^G1 lMEnljiƺpTyMam0V^ʆ!궦hUTR$cI#//[]PڥY3C\HzYԇˆY1:ZCZ I65tRRB8! ɪ!"Kɩ6x"1: 7I;-%14RrWB:ӨS1:J/$nir0Bs0 ɜοҦ06Ǥi0 RҦ'Sxr!Ӻ *Ү0uҎӉT^HQ>@ ai/$C$j(R4jW$RR^SÈh.%^H:է1:/SS>aB́V*{ca/$@f!Uk):ZOd]6Ww߬w.y]Y[^ajwZLnV?||u봝1Qkwj_#eǑ1Ff~%4;w}y͚zsyh'E)V޾m]w¹Ml{U~γܸ2H+b޽L ɏ]u7w7ԌA(?-xkZ_`Z_`q+FC"(^9y"vYMcΨS )ݰu9Mcs0LQ搐9)oΔ0Oj dfdzOΘ0>c7#$iGOQWyOQ̕FLW\L߿+o?&?ɯwgK߿_l?rAsܭee盧ĭ4;_o?ٟ~LU2ogˁl%ȰXۦՈQ}8%T1 +ϯ! 4#T@uf_'Ju?ŘWfǙO ,Mˤ5n1B^%“+cVCK`)^pwƏ:Z6m\,/̲g;on05Qzy}F8;z4wXfQƚ| ^p鉶Jm|1QK^}UYilXw >}TJush}J4Ď^)/;u2Svy}ӟWL|G2UtNp.d 8X.r`Kh\װ&;7SX1[KS~]W.>KՅ#Νp KB t.1FRf1|W)-T[X1FBIbvc+(6bLeoh4w p:8/u,;,X4f3-捲SĎO rNAox`tެfMS=8r%R͞"0vhvˁ}_Bs?NPIeQ0mJA@Ӗx}pBJitV[Krw4Wn^|c>1>8dt }_Hs?NWtpA8t2Z\:k]t4|=O!'wC\RB̆b L:2e\")2z='F=bdfGNp] M/'4xLܡ [aa/&: J,R,?eXK8x eipfpN {޴{S4|ˁ}C_C3?T_pZD={Gå+uh,GyW ?>9>>M௤'+ih"">јwNӓvI|Bۓ9"r%=6/.=a*=mO q}O Xg&= c4b-.0tT5DZd HFX3MILy9O[khGJҰ9wC})mt&e0͝{p(CB5#F$qCiY$kcB=$2k'bhͬ@m'=+Of>;Ĵ#@A ҵ:AgYO3ݏp\0 80eYDtGN>BHit FBB2t+##BKĎ i379"W@ݙU!FʣG"'3i$]s`ZWII8Yq*f΀I8IwfN7(m=9mނ0WsTdEDκw"ϡ7ӘxfYvyPhPZYNg=%Ρjh`$#NA*&0X纝x5&3M d hPddDJtTJSO%Ԝduؔ[$xn;厳C2ܖDKO z+b6udj칛?WО%vPcycR1 hF`LqL.*˴6m֨l4+(!FLÎFC #Oj$vT7P~ C^*Md~m82j5\f9*2K %2WD)`sy@MMV թ^Z5"qO@J?2%%e"dzP=וk } y^D %ݕHHJ9bMIJ"zauƈ>R܋R>sN1W=2|$_uD;$gh P Ҁc=v6=I7 hnm1Q9#K*;bg`IS^5mgB'0Lk_8٣6 .a$sC[(Ѷ"e*QYQ)*I"S9輜#Bx6?,!V}y!;uDPB:s0ˌC'*%N iyxkX5A#z(ǭ79uWF*!Y "!aX#bQ@0i"S(ء,Q62rN@Qa>$a ̯WxN9=]+ 2&3wۋ%w9/xh߿R6kwxkc`_T-#W#b/`1-G 흉zJH֮Z#+gZCKd #uzHBՑp,}:K\hvM'$GHn.!atL#brE50] iuA ;{S̼C@ee@p0 !$b5B8HU:OJuE,<Y0`e tLFdA@A~ 181"0 FLR:IjX"^,ViRFb5xTHn cSOcVR`"GVa C9@=# !Xҏ"zz!|C*HHn gTdL8tѰK"sEPe*W}xdH:w*)m~_Ѹ@R1)r$&9rFU3?#MOjp$KC5y#7)7'U k'ߌF-`d$"n27*nC@"]Ȟ#yOv}.x0#\[A(X ʡ0I`*t",@?" E*$[L^=Hgsh@#pk֐qL jdvn&1oWD뇈MzoJ 5Fb^3QqUHE# QYwQTV=YMO("k]EJ!AFuCJ,],9~x쩛ZŽ" c:]9Yv5+64cseO2F(cv`HF&ވDB dHFƤ4=.HTt1+oL/FrV(-g27$k_@i|lJ#,y3BƬn9*)s6XE#L- ҭ1 Li:@Q#L `Fw6oXv&nT 4_4&±4m^H1=>DO#"o2i#BLQL0DM14D%;?߮6a[G `Uy`AZVRwP,>#WJŒ D-&Ǯn.bD ў\,@$cL2AbVREʧts_BDPN8J7e[LG(&jW e@], |6361dL(vVSPLrPyH꡽7p,? 7t f0$$k%3@"2e e dfO?17^wۻOOɳe߯m_6gx0w}6r`˵kRUT DeV"ֵ~j)$Q5ΪvtD2}"4'²)q^8' Qe2'L\Ƽ>~1%V4K}﷦=3YKkbuRNa^l-+B"nY}²y^^SZ\*cH~!x(˪ZQܬV]V@A=dmgt9]t1X{P !ygu=)$ks̚,-.-I<'Ԅ !NcpġYz.1=m F?ʉϟ ՉA؛`P!85TRk۰fސR9 b SVVSU&n#x £|B֓sRTd+*UZoy#TZ*(l, Zei=N>|ffBM`Ջɶ(Ի&qodՌ7 F5t1ޮd#GEhEEZ5QQ'X#ę\vb( " ,-S1I8*ţ ~-ܽTfGpaIF# é=Xq%XƈxF=)W;ʎҊ:vEL L+\ea) w 2JduYC#dA /8b1=i]_E+ЈWPn}QK`,CMj$C4Ĕt:#tyomqA11bnj<_4%LɂQ&mdrtٟ^;@uF1j.WbE6=Hۃ -WMG@~5pEk,=,1YWpK2iNDKu,@3/٬"MfI1zt8|f4yQז=ݎ~$^_0*2qT?ADfdWѢ9NEv ڗXsq0V)!k%#tBΞUD꡽rp#KG2 15s=DO#ohd\ڗ Fo'`Ԃ*&Nh{h>^F9ɠ>al2SBd(+YZ @J%G#('hEvoB ksCsH8Yp5dj8燈~H3ՏݺTHgLgxID1*X+]UYP"3Pg/Ϝh'5+UI F0~B@dʡ} cvlH?f^D: Og@$$k_PEEƤZJ5"+Yv8l c(!Y8r 88+f*$,&b cDF1Z/""|CW6} 1MhU(dNX礘!Zd4+RH־c-ҽc֌+h Q촆stHgC{L n =ݐgL ڗxFAa֙*ȕ E'bZ#H<,MEe3Z#.x6ГR\Pg|o` I8ngPDdz!7t8)!Y8"!#™g#L]EX\;Gv峉(Y|쁔}g}b4Vod;!hV=7Ԑp,h =HgL m Igzd:qtUR>̈́APwFg;`G:Og f/ې}T1Z|}TI±tkF"o>)/7?U}AQ| Iq:"E8&갚W gAWdT7y4p,ݾ|tN1DO#o8S:B%@cLi)aF\8UDa膔Y}5qLGe.pSCT6UP6J_Qrd c`EA&~D> Od g s:r?}5sF}XQ!*R=/(恏!Y[T_gF7rS6aY7E` B\Ha`B+ Wld؁bE bJ#D}dmQanOX%\ʎe7OOG$d6uSlw?^o3v(I~6Jg7ZYdE}Nvl$^۷҈~ݼnn⮭5i~xxM^s 0!|>zEvA ?)~{wy}SꟉkE}6dw]7O,zn[ou?Q@晈.p)f͌wy0K VWpA'#r؜OK+I^IE]{ ^PH9rtV h%)+撜!/gSb3逦l&7RdiT{n n, `)nZJ?>XJ3?ƥ:1R(XKRT51TAD1Wa U>"R0!ɼA~~0$ 2KdT~G_kҐiXdKI @khf Ϡ2;UT>^eeOjVlE?՟wo۟ӯ*i/f:Wa<~JҢr2/,V+T +jm| yp]SU#>]ɷw[PKs5DQg5,Potentiometer.fzPK>*-fritzing-app-0.9.2b/sketches/core/obsolete/Processing_RGB.fzz000066400000000000000000000503151250202676700242270ustar00rootroot00000000000000PKs5D L 9part.pot-small.fzp_e55c4e524988a0331c383c6d9b004770_8.fzpWN0}+,͵W)͊$$V9ɴxđgvMIi%gϙIK*l~Z9, ϖ_?oYd-,ׯ]P-wYg9φ>%&S!l:eﻱ?q2g88SJ,@aI4zPLk5pG~*#rG][ѯKԆ|2e a_vA`>$LCx-r+q.&7[Y>~n̉=o[Xg]h hM$jP~AdJs X\ }o ъ+=̀}@md}Q>dF9@A |ES O)/ph:Äs4ith}bLӰ~ n ;T 6c}ETՒfLv2EKK q/ jx,x23\SDzgcnIf@iMdx-ƞ3E4s&l` 9뤤oݸ]ճ%{JPL`GvH0Lߑ 8#Vh8h gé + Crֽ H@X!0X+ngD XI6V'Df#~;fUݑߜPˆgt+B6;Kif U*qɮ8y2JyD6;ʴ6oHPh-ݼ][Qyn^T-$~vDVooW]>IT+EN$QE* ]PKs5D⫫ZProcessing_RGB.fz][㶕~_ą;'v\IjS۩˔ZzT$ER@˶.xx~wo7קxܮ_W_nY DrMVszY??&μOfOϛlv^|yl!^.RX wYyƳf]~n>wS}VDy_/?%_6wwcmY~$?og;r_yiW珫ox_^,ZC*qU7n?[D8|6Q+~i? Lۻ?m:os5) xw7yi56m^ /~w?lcaz%͇'K;rw%ey/嚁gO-)ܾ>b1^=~gG@Jvk=~o_jQi 7ߗ36I4NN~1{ce? ŀ6n|e:#Q6퟽|c55>Ѳl 0 #ՇU=䪍2%fo5dcVNr62gq* NFوJNCeNHlioXF`2N[eǃYv/K:ݲ!'5>]Pxd$Vi;өSvE>d}&C& HU}1}ɤijiYOn0Sz]$3O@zRl^f^wmxJ<_WqÙ Ur؛bY<`(=8 e}poZ][͒wR[ V]goBa5)2(Fc#,QX@EHdzF 6CYA"c Ab' аPީ=de ZW68ӕ]=Ex\wP" +FYf p@U%FW\RKr\Pp (Hp$1H(ׁ簐c|f=H( )CbTI'5Q<Z#p"LZ#hQ&eq{Hp LvAX!2'MPE)j OsL #C!K<B.ltD):QJ1`Ri&iH%HF+`!Jr4rz!S@zb2@K6bUB{SNg9p8Dh_)~|0mO,K 7+aX^]kaz Ȅ (a^yFaa)pCx& 4*/y*1A4kZL,yE$W)e0נN['N7Rukv߷2Ld9HzknyS4)<\xIW6 )~iWѣwae=D nUb )Ť0<\jSL(fC ɕ8D3DUbp%dEc<ŴZ> wDf 0/ρ8O:u.GŨeбBv8W a>҃LOvH-A-u]$L981&<֓'bQ<ͬmCE1>d2Of6.A+ᩦкo#d*e~)0Kw1߰t[q gsq5|7׼<q)07- ̷!ͤpow9n/gy^߿_"ju~xx0ttG}n2YϞwSM~=OjO'|9KXBN'W057&;O8N54 cEiT芶$_і7Vr} 8gBT4ɻTqIwM8ρ 602 O lV9e(SH?͛Kյ\v|Z5BFϙTw.ohɄ̝LxP*f5b0saŴNS"T kipzWQ???v?YVOz}H\ e/;TEX^Ke[~ WЧ}nd?8; p%Z96-Yq >"21 X`њkL)ARQPjGW1Hr= @2F#B FH0I<:.+4 RV־!‚ضi@|3g؇7v]vۍxQo`R: c-za=\(t cOKA^joal8H0PFH-"0 -Cp/&ۙD49 %8 c('y #Fy RaH07D >-0ه7.3 #Ƌ- gFuة_[GC8oad->*oab8f #-Q1aI4H`aa`aGyD(][HɁ$dx #pC}8pc[첻0r I@咚OT5"\$\GZoͅ$DH 7M) J$b2l)KrY p,ԐzE72gJrIi-cCURqZdP^\Wj:V*j\WFxnB\CNJ( ; T=cJ-DŽѶa32!9YmD,>>+x<03HRn "fuH.4SO1-VP쉧M(ҝ_b822żfбBxUWg7 (K={-$a/@2Մ{]7~Q7L(t=AnWO7zk;Id;-O8:EhdWOH0RAM`5WFg+D&ӳ]5iSlIJdƆצ@}mr-n{BPM# C au(n-v΍̺ƖAg;Zݲq7t+<{\9M24ʊ2SsB">fZ0HjI|9$xh99KUtB5Y {'Tl3lGbP,ƍpf;ȶs4*qvZYiHՇm,#}ҭR/zϙmNS#q?MU$4f2ns;IؙKDS$ݤ#jKHߡ5jA~sC FukoupRe(뭝nu-W؛ZaaT.0a #a9K% #R^B!5zlY4tt'CLwF{䥮Oa}l@tYQE(䜤%uJc!S᪮ H!%(@"BM$4&ĤNѐ'JI0!*0ǎWc7ľ op>&(ĺH2Dr(,{v[)x%XTHK_4vu#`u؁ x;1tWKTr ОRP;SO.y5XRcYM.Z?fD sv(ga Zo: :U34$Ю窡"I]ɡ`IRhPRRCNJNQ^ـx_#CEFv4:;\ 1&%K$#Y$av$yTEE$ YH襰ڋ/Xtdoȋ<8A)^ s < 'a Cm`wp- 30$b$GsoxVF`M*ttId+MPH0 =* =<3X蒪mWSP#: Q'^Cm~zu"J `@!^ax1C9f]Cϩ ji 9:]QKܸNgN/ΐI"c:ݦ&'^eanmNCTmE!^]̫amzϼNDyA (̫2,xu\xWsJ:.iچ{W! Bɐv("h L 3u9z4"=yqGF켋6uFɾnuD5 3;- @#.P3ơgrq8\Ҳ xtI[ aa Qx(ac_MC_=9⎌~ՁA!U]DWЋLpGu`cud񁇍C^0a%-[eՁ.W^^(LP rb,ԫqԫ̼#^A ; /WIPpG-A߫ 2 p6Nz s ::^LWsERJJ:!؝+Y:'TU 짻ӓkOTOСVtDu|;RIG J푂;ikD9bӴ=`K;RcIzkgVh}vA)$; r}mw>l4č=pTE -SrD87 2G$k_e]]뻫@jC-y"A֭w+GdoI #q7Jl6#7YYC7ξ :{o זHڀN~EaSL : +"N8cB'i1 S(v+E, ӉCvCڶILFmU$_%BxH`u @\Ҷ] ;RۻpGT`Fe`!)FLgV@ibS嘗—@Q_'Cs\ԫ D*KuXIXv,ۛ&j` ]"@^#J)UCaYDy)OXX撙, qxY;oy̳ěDGBd(bR^=7, &s!H+ÓBN:Ꭶ!2twI"$,R(!FD0 5<To~{Ys?~gǟw_7뚿맇͗~84H 7=Y/׿||8>5}*EYϷwytB>}?B0. Ǯi>ݾycbZ1y{Ͼxx?}<.~./} ӏbvzsp:ᝲXW]{|}o5?\?;>x{R~ܾ?yo@ٮy{ys>LJ[у\TbaX&>dN<e {߳0h(KLA [j||LJ&|Yj){G&f P`<Gi\7_ki&;Dzp4\ܚ)aʨ'qaN)PWN& KS>d+RETF'XT)H(FQc|sab@w;J]?kRgDc_<NJ_?a?Hp\Zmg~ K ,|^#^?4vSyx[Ǖ  :XC&`լlM~.+?҉e?G*  .z(9j*˶tMdq!~nz<(9XoiEZ7weDI44m*O9ޛ,T qb>D=~AZB5=blEF B? ]'+{[Ug5P1{l gmcMUC}U sJzGt3q`6kr%/mdٌ&XMĬXM&Ŗ6-0[f-4Al: HNN*!T ?C6 _@F^~OT镊}Lrpx <\e^r7*beeg,)7* up2㤘ݷO4ƴCT0Npfkj4\A0$hH4mD0pf4`*@T:D( z ,䃀%ќ 晌4!C<| ^#"ɩM+"_1sFK3$2F*XBʳ4T 4'uMC8*Z8j؊RK1xܠV՚7# T,6вe敮=`P8}Y>rЂ9H$29U}I4aF4+IF ာp! l'ĈUJHڎhʎHs<@c\W~4M21T.,4/eLFU̖jT.UT?KTK](# 4Բڣ-[-ou+tU{YxKA3ks[^AD^}9ӒOI$YGj_!T#QB깼l7ïwa$ HwCl90NYM2/PNd#rw3zc Fx0H%э@^!;4ސE`HX0#dQ Q6ԁk !(f-9Ei**lR+d h?HɤinUV .WNC1(qJRcH7w?qC˩MU<ٲlӌ9gR"r&QhJfcLcЊDVF㼦aO> ω׏+$`ozx!vE+@P8Y V9Lf+R1bUΆf+ҝ܈xn 0x@3RBDUvj1u55xg05-F+j0l\Z -kE3@6!ύ G9t!52t3@YQ] x.a2 \ DZV6vp]EMY^$bE3 b]1J W;G5 Aّ!#+[hZrkkU9^9&WS0kҝoReG7^CErxHTVCI֤;W t:f'1%GEk K) KZ(栰5zkæZΥ@4+|QZ)Sժb9b05+ xfRcB+kMs@3 VU8kBYMkYO\6c8!dz `)1w2fB-a4&SNͰ[cf 9"1y,E땟`B1LwЛcE3zq\!ZUXakhl+W"wTؚ|y:,/Zh!`iTk/Y7cck-[uX4yC%wЛ㱼c@QZvF,Z%kIs@{U栕l5]Q+lMs5%\oH [FdzTQ+lMsl^ܺIEza$ᗂhyxLn(xI+/汨5ys46Kuw^ ;?xږ5ys,6/.zi*-خ.YsDbrs$6|Q7~kYzYaibȴf5^q\Z/V3N^jeRm.[};mmO;0wnxaܲV߹Ujm.5LfgzbqyYN1Ȥwl/1惆`>nOfG'nqԌ6;y>^אn=w ʘ0y/ @@lCLLw.'_Dqo<<p<3.OnT>!S);~|,QE W`tJCwJ"#PUYqqAs*ֆR<,h5$yҞiI{iG`F {}eYίˇߧ /d~ @h6fwW]t_ RȜ/3'w:7=l 4GMnZϥVyZmpWm(NtN3С}BoeI,I[(2ڗ\ .eHņ߫ V=Կ1v |C22*)-ƇQ3c?Czӟ!ҷnN P?ű:bl4hF|0/CJb2ضiM͠a$.U{•t?&6(QI9R )hf> %(aC/)T &4%{U|@_l$ep56^i(_ a DZ"OIs#)]Sjj=!KŌY ͉sfh(T(s㒸wL0G$N5&4'jYf}JͻovC/c\WÛp8=vW=W|y(<%Xv?GlWKɅvn皡἗kUÏow;(o~5ww~n^?N\.OSwxӃ^_Tb[^O1JA hڼ~4;쪂VUo|w:+e;KksE=s.4hv@̴wN6W<(l}dfG#c +kstW@t[.0r[@~X9=J6A#1hɑRK$'%'J<]CveKqe )쀹c !E*y$fFDTܴ&9;3x9H,mHodJ5첔cV{E㿧ʐw\|E}-~@uѕ1[w*Yh+#z@0X诲9odݛ:X-Y[ 1… n…P q? (?{#tBnV:hSlƿe :5`&ˌFFg l/,8dxxdVu,YaH~@th[d9rpQ"Ey8RO[1E>fNM|ml̖kj׻]Ejbx|hˢ{ Ϩ՗X~w{[Gӈ^L5W!uKވw4äbmsa;h@N7BJ߂47`^M+3n dπɰ۪ Zw%P VlE2;;DZVFYY3ō6|T^CUaJ]e2 3 p2 n5Nv>^?n>@`:pulcw?vLjPu0p8XTC=zK-R/=u=Sg*eZ|6>OXVReHm.?J AMY!k!Y}q!4*%j5A6P%igrKK>w9x [ 50ʁQ*0+<v¬%aD4 m!&{NjTΪV陕 i܉5#Xʢ=iWY#h*CsMîhq^f T9[?t-03+|pM2P嶦XߜCz4{<\OA FXo9WV̳8Bev3E701(LalCJM*,XW Su 6Fc#0 rrbsjhTcmv;VV`Ў.f6@\0 &kܸbvfOj D $cUP/ &% uM HI*p[d T0]T >w2 ATjWd:7Rl)GLRG4Eft0RSik$fE[DW81R'h -(q,5$߄QT 'oge.%SBNkx'ZXeĉOF1;K#*eX>k@p9eUd#ĦM)M ZhR:݀ |anc3gOK\Nu=?˜<yh͘fuaZ1Qd*дӀGT)9Y!M"Ќ#۠j1"@3&s 44&Di\/Cu"H&Mr={ÚD ڐ@v-:bx9akd%$ّ,FR.hIVn ڊAϰL# $5DsZ"YiLt:ɲ wĈ^Ȑj 8 JuvBUr'U#+="icKf4De>HLeeH5fy'e  pE+EУʺb+ی` T1B{4B"?L-rЕ?*4Qтƒ+4}Yd) -o^[rA?Fi24_3-4.vܤ$--;E>Z |P77n$ڠ04DFM4k⦯#'[Qఢe$هg_Jt8jDCT4@'TS$kRxXmsqOe @B7ӂ\\9d5hfGC'xZ6{H n&,16\tG+ӿ7Wk%љVaEH.!Ĩ lή.*NJhJRpvcpnMద%$E l= R8)z70F4 ly6Lɚ<ִ̓;[[D](M# '*e s%t[G*lmr8Ő4/%fF2T)7k7U9&.̈fz8A`[G+lebkǚT)y,5! NB{b\iU c㔍dc2h)BK8y,5aK1] cJ0JsL1]Qq [s:8\C\$dz rz%\H&je|].|ȅO$yN&,Ub6`.(%vƷ6rbJ 奂=U,@Eֆ.c[0ŔEJ7[[`i?FK/15) ${R3[[jI+w# r9ksF/q5aKZKFyiIO2Z2Kl om%-+W"reKVdڨe܁yĵd:6jkYx\뙊EZ\5H[(I::j+B` Hʵو8$V,tMF,c:o_:vKl om2v_%ݪ%"Yژe9,ަJK7ލG:|.=^#80^:TUiꝱzSUkq"s0Kc乗f[L{kln٢LWq|"N@Oh֙:尐M%s~nКXq:"/s4\&\VOҫ3;2Az+EBdž0oGwfiyr9(0i^7q'>ݦRsW_}wMo@>O5w].hgLߥ|^Xqc|$m _Mvnl }ݸi~VEdq/茀x(pGZ64H3]rd3jf繎; :pw7 |Ҿ* ѡtc~k)UHoN wAጕ Z0UZ309ՇmWEiD%E[ZnMw|"b}d 83?] Do&hF,kgL_ᛐ^V5Pq~j.?bj>#g:5=pHq CL#QN#ibz PS_ۢ(uٙpf0J,VBclHc6 |NaTf۲t_7kj}Bja +dz";20xD!)sCw);C%\OT1g5X#)BJV)ՙ+vRوI -3Ug]憗J?H/PKs5DEsvg.pcb.starter-poti-pcb.svg_b74d7502644af62082cfb907907ef696_pcb.svgmO0)nދ8vIFҦ!mB+v|e/b|w4>ZMLtN889>_˷3( t8Jfo3}#"WeU(>_ٶЦ|p.x ' NW2π8G.UNɲn66 cA62SGKElؤ,TLIaD)Z&ˣ(tUr'P Ŗ!ru)bYQ宥؜j 1 IJqi\2% 3t#gLetus܆؈01]W\Vq ]IHo((vw-ϵ@;YP#LsmI%ްzF#Vn`JuQәYgKQ]{FCw;aV؛?^9}}=k[~_%FtNKѩ4)ISj׆*ea@?jܣ^$<^DoD4_ 5Ч^ۼzͯ2-S#߁BTOTZ ?sa8>r=:ukxGDZ?ҿ5}V,֑X?6f t 3v뿚PKs5DxKsvg.schematic.basic_poti.svg_b74d7502644af62082cfb907907ef696_schematic.svgT]k0}ﯸS /e6( Fj#I+;NҬ4c~Ws1~Yuc8e#6s|n'bi2;muh]=/{p_R%e|}\C.&h|{L!ڔ9Pg[4mdٶ4-J"W0F≱ėMj9jzI5=߿\4JAwp*Kme)Wan8_ IB,iDi=9ƾ09#W0u 2qf~5·Kbb_k EofB)Oi^-Z v( ;xBt1)0h^LzW DLH ?c4NSV+c{XwQdD3cAE$Ox&xn z!2y'g!J`8̡ ?;6:NF7p&2er,Qb<qPYPt3^]PKs5D L 9part.pot-small.fzp_e55c4e524988a0331c383c6d9b004770_8.fzpPKs5D⫫ZProcessing_RGB.fzPKs5D5WePsvg.breadboard.starter-poti2.svg_b74d7502644af62082cfb907907ef696_breadboard.svgPKs5D2H#WaC4svg.icon.starter-poti.svg_b74d7502644af62082cfb907907ef696_icon.svgPKs5DE5Hsvg.pcb.starter-poti-pcb.svg_b74d7502644af62082cfb907907ef696_pcb.svgPKs5DxKKsvg.schematic.basic_poti.svg_b74d7502644af62082cfb907907ef696_schematic.svgPK6Nfritzing-app-0.9.2b/sketches/core/obsolete/Servo.fzz000066400000000000000000000270051250202676700225170ustar00rootroot00000000000000PKs5D!z-Servo.fz}ksF\u=a&]vϝ$HbEjH^~3@_I&] /E=7qLn6`]W//0R_"!b2_D\7]۽IFս>wWWˋ_K.&e~ypu9'=.VMw`y}1-vK-*fkD|1ݽH)!_%"9̗o뷛6\ίn֏zo [-s`tAj~.7:.&ۻïK|Y,Of u@}A=4]p?- /g<wqxo~@珻.m3 /X̿_/}_nqnlFc\]'gLI]%&‹DLNgfVVG}gyKpn Tk]Bo%<̍R^=}_ٿٛ}mg^}h<\_ή֛`|yAs9{&Jq;׏L?UsKlȹ8,sqUN'-ʇ>'%>+ʉQ(9qS"ek LVZůt 8Uf›X'׳M]?na:hD5?$abͨ[oF\Tτ(c"|L)Na$|⅏{qo's(I*bD)b~_-vLfo J^AɊ ]=&=KM,|̥$lOG#j̀@x#>ji/n C.6nZ*a2i7@Rz@Bܯ,EU"&$4b Q$kBpڡ몰j>24$n)XD@D> *YrT23 6hRNvQU`ءkK1d@ji>X 2˒ BaSKXvĎZm^`DU I@}drscUPU*T(2E:8/Vi+pM+; w|T\e[ 1JKx)S 9H dʔheF@$Zhӕ ȈVϟGk" ~km_]UżWuV鿡WRj0þKC0F2 kuҏƻ^vM^hq(zR .bVyI!ah rk %U $?)kE٨R[GJ %#"aU$Zg)n5.=c5aoYEѭbg! 3OD+P`irq0 7!Q}¬^5ZUe0E֤(ɒmzs?''АSblk)ҏLGf2Rl?CvS7@d|ܽ>$(vq ^EI*Q6ؙ-$q 4O s#Κ"!q`e^lgi.?Xr{ϖBiwЮ6mf]m*NކB}[SxVSwۨr,#{u,!̮[\"Jz~"O8K766>fk1P';^ \i1Y=_XEs=$j;wrop- KRޭʩԷ}Q9Zg7z2l .-tz0ʝ*ߔ;ԀQN}c`ΞzJ(d&|3 =%΢."'L")qکdj(.pS-d'.P)D ͈+VXR/#\7z~y0xcNQS"C&r\Ӕ„wl=Z3F3dOD\G>a#LH?C _q4hRkYiJ H8A݄$hdsP[:%I@1:lhdhMokE[HN~}%e o70=ySH˗iS&dkU)ArA V.QA Q3 ʀjzY9e{OMh < H/3Ũ.<,%{#GkjQ;$G|\z~E!ɚ)L`xIAq$%U :nV*ڹHFXv}ԨX`/ڮa X`cԊH_.ԎvLʓ=a)æ G5M^vN8TU2Ze F &W[kۇ"8Ai[Җv8Vόa .#f9zY"ڵPXӀct']6=_=K$0*GJEk0 HL)9qc,LF,?8I`k+`A P8Gm7J 9af[988MpPHXh@ 3 &m{E%`- $`vT hhvF*`;ƧD^B{c_eݣSbMΙ#qc(6k_%x׳߷f;:x?{zVzjfXnp}3o珻`9Y>aZVGJh;'.HDFm'FmXTo5rw&cWf촙ڷ6ك_LmL~(+s]/Z >MwJ=? K20L |M:K#YQN߮'Z[˰qy_}˷V$vs&t$P 1!ⱽ|$yO@=pnmgH`1{hFdh?3vf&Ruz 6,{M(/YYd0.igݩD B}ޞ쀺=gɣQsFmϵnĝaQښ˭Pm>[%Lg;é46J]pa3qradV ̨)6Ί$"nt 5q\#\GG0fN;h{Ve7Md Qp. zQ+H)Aq/\3 a fJ4]?qN0_#_c!*d {\'f_Q l.L&+3|j"fؤ9WPPdH"&%b #8jJU:]pq_G(-'0m`$eT@f1\R$a9jt HI}>7%ȕ}l:)q+ +!R$FNߘ?-6q0GŊE.!h*|`?,1t, 'ؑRaMڮN"1Fc> >F |S>>Yr;x?1VpVN@|{9lį@p/3 Afc|'rq*W%.2;Q7)jIhh Z j9 A9"*m{uԶL&#T|&`M0q%,C 'd Fb;DGeMΙ#1d@6fz $'e)M`3"aN&Z4+17W@(6/k(kՎtf KhGDh,\5#>33#\pfI o@g^83jPmSY9Df4E/4sJ#O4ȗq[qUtL{ U&m;bߢنHZ߮ >ji:-z3_G͞aq;#ʰ'+O w^Xw rr}?wv_f>|@ZongcE*,tX2sc>=7>#H&np=SZqL_J"VRBę.%z^=u5kO44̚#5Q܆\3i֌ê᪡X8𪡟^UCjs]5™֍tu(bu`z 1|FܺQw(znCjȝlɉ' }~&ӪUdt̩Jlf/hr'nbY{-x.d %L|J:ŵO^XhcK&M7]&ecFڢb>CPTqZS7OJl<|hxأ䚩pcl ǼD{ &E7`^P`c@EK`^SꥀKeKLra^\;U*jG䈟/9%R|)Y~aX‘HUGOh:/jAp' c3vhx8V&jEk䀟/C} $FXȐ|9%]RH[WvDTk2HQ?_2Ɗ];#)aBPSV"!s#%a B:|n-=ʠ b]qLk3a04(2 CSC34C#iWH|e;^V*ھ1P5]n'dYSACjjfqyw' \D!:Zx+sA9:#L\S.R(yqlN|HnH8Wh{88vMprީ\r=gX"bIG dkq\ķ聈- p|L5+oAVt-|+a;ydLbZ L"mZ%2\#uq ,ڤ& WC| >UrZ9/ڌXh>QptLk!XIM8a9 8H<]H*D}ո^ҙ-M#ĆXzGJE'=Iɇ!)qS< ::ѱ|nt ,jأt bMǺXh<0b1((2$%3=qK0lǘl@T:6֋3c@ K0iqBxYhW^>t}^:Fe]pL;- 6i -"2Be'\%A*utʺ:sT]2UlҶRPfggM$bf;:f/y &أ~km3DGñ26`MN٧dd|`F 0ԩ<GU2$bd;FV&#)893cdMFZ`QQL`B=K6Fc]qCt=+큎$  Iɼ)@rc,[R)p@ƩTQ$hY#GJE2Zc\5 LdE==Q! |eX,=i|Z:,4`ԀNMD2acȀlT dyqCGAѣi2$c+큏la <\ 9Yw(Xz (LGɀ ؼ;tee=2bd!I,GX܎` NژrTNMnr dHUtu..g\̕\,=\ &jأ\ bH"iq`e=p0ap0(1$4 p CpwA)Q%TubݩܑMnBFr¢bjwN:(}cd]PGu?DG2 (ؤ&  H]dy qA%kPnw $-#>Pnmμz[߿m%{Xd7T1J5xIL u'h:&jM0Ct4FG+MN3/R@t);8x>LbF7RÊό/Ը`ˁ#9%s?GN,{4]0;ǫ F+͸rDL@@ekoV \ nfo "*AoK`Ff<ƙj{Jkszd^9l&ov%01 5 ?F&pL;TPcHF6p7[ոkwTP 6iAOI#A/e%!Evr;r/9&أ際p@dݹh8V&C8(LI RȀM)o̚vy„kLQR9f_|wd ZBIvw=NK4DGsѴ2{;@&m'g퉁[0r]އuk, f\rie쟉:wVL">XI'c0!M9cQiXhd &vؤ{fPcHB6p!9GݹY᎖vkT#Q?cZIiYWH[Ws,_k\#P$GuqL{\#PIM8s4=rq׊8Я%٣eၤHZh39Rhrϗ̇@^zH*,EU#zv3nfƙW酢u;~/y &أă #s!: o>lv@y9pn!`h=Iqe blYhT34&m7I5/uq,_hX2DG2 eP&m7I(r0oҜ@`S!LD&1꺭\%F<'0lmv)K~JDaJ~47+,It쀋"#sf8~V&ڽPI   kSPcWGFCv#k;9j k|{d}a|G+u (jأ{dPcd2DGq2{d@&m7`PcHe8ؿַuR/|{ج5>>MVŇb~|G OHOɜn3p@L2T\`cXɞ?ӿXϏ`]W/$9 VW嗏?}Ɯ?Ͽ^Of׳ٛL~ 2|9n{z6zs;{?-3-831B5Wۗ_zQ9;~6H TX_~1dѡL#IOSB*ri3].0ӖrB%;ZnW3zSrL/Wn7u+\_'b=oj=N_.W XeCILn=hȏL!ӯ(C˻+|v3s$K[YC'R"L(>O ׇfT2Ы>$N?׷I!C[VD$sW(z!2iYEo'37}|ڠ,>1]J"%(]qWj7k_ſ/L~]|/?zɟ?\%3mzLPi-۝LzζfY_=z:n6gm#2B#CTُ@Bz!.B7j3e2 ߧTmx8"ެǷU: U.2?FOT Ώ7ϦDSjee VˇTKovf{^:xxs^z5ޛ.Xy?0 6&mTшxy5 AJ8 /T3h:v_OB}TUxiN0?l  N~h&fd4晨tIK|"/&kN#ieixCSͨ-,~ ]Poe=Jj=Ը`m9VPgTz5j\A>)zwh)/DRVeq4V[(PTǤby>+r°EUr{>;'XHZ$i',_J`$ JJ㌕nnG5)*dSTInST)O3o2 Q&تI}[`^>bJxQ:>7DT& U&HlM1Xؘ0뤫1Q8iQwQ$ IǑDzBDEkoEOzqS>o?\\:& s>͗S,|╽{]S*¸rX E;NPKs5D!z-Servo.fzPK6-fritzing-app-0.9.2b/sketches/core/obsolete/Synthesizer.fzz000066400000000000000000000360401250202676700237470ustar00rootroot00000000000000PKt5DK! Tpart.sparkfun-electromechanical-buzzer-ns.fzp_69129ed5bcec2b4b26eec3be62bb1125_4.fzpVMo0+YqۭIʪm˶^ j( 6 b<ϼ癱/a@SG."/U4t K؟@&Ze+t=~[ϑ1`3Sx)sN'0i`Xi"d8ID-gh;J{Ub¿6BZd#8$<S$GI-t ^%W݈vjVCM ;%NsZ ;ũYI̲XŢW]U/SNKGRO$3مt 9at> {6VH̐,S½܉͜[Wيo':N@g Lr$,cik:0w&"T;Z(rAn<^}FY(A[n |`aK —rS#K&BAj9KU[)~)݀,jRCPBJȔ&n x_xOR ޢhi=O<٦](-8b%TS!L~-\yqԦ<}bkw\AnEr8#$d"fJO*Ǜǘ~Hp7wFԒ$*9kz?I:Tʺݐ6 -INZo}񛾦瓮[NVi(AdYNvH9X+g)SPKt5D0; wsvg.breadboard.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_breadboard.svgVYk@~ϯi Z IIB@!-ZWf%N~}G+-@]"ujp=2U68#;<8mJ.ur((fUmB<nRP2^1ǖ>gy=m^2@!X㺞g> N)up0z<(q} E&WMD/jz܇7EQx"M*& ta+a1-x]F2u0}l$ӆq%t9 UՂ<Ņ:Me\Iu5LٲIˉLƱʓxޤLlU= a`A.N1''`hZZķ:߰ALa:n6&4d#Q'y-`>,:KwV"}f<$b^d[pVi"'RYj:.9B'ۧADŽ  #{X%dd>0> #Czlv-{#[keyXy GUyUso' 3.J@ 4:apFdmUlkw2:x^딶4xp/]olkc4@{\G7nxś]aⶰ ;nwE1sTɮv1zP$snp<(:AEbvX~Gߕf/PKt5D/= {C ksvg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgVkoH_q~H+a<-;UJJR~01*N~} u]$.sϹ͢'VkF5Hy :mk=ۼJRU!`ϷpYֺժp( 61P wʁ~p]o @"8]t/Y3+)'$,q,H$`ww$vdRYkD Wb~mDMυ%?ϒ hW4aX؂![ ٮڝ0AakX$/]-]p$(`ny؟Yl{ۚdZJ×:3 jmPdXۘIQށH[]n RM" MH kJD :as'dCVlx2=Nh Zkb3Y;E++ Y$2:*Dc7"Cb$=KcE-=fYjoX/[ iN~6` :K|5~L^OPKt5D;2bsvg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svg͔Qo0+l 6$$ )r+`GM](Iej |}뇦r&AismlNJzarQ[(}G):%a}+CS^֕G+] iڌǽ&b  &,hCv#.ADqx[)]VHiVI2O'LkѪoV<9j b檕ԩB9CPlm{CUwQFKQ߭(n+.# 'H~7vU%@*@:#' > fS q!~İΈ)_n oENuMgr@kWa8LHa~ N)sd-Z,BeoyU5TAn:LyQ㕟t1y_ϗ} utAiϕ`q&Vxkp[iJ+-;KXPKt5DWw3'$Synthesizer.fz[o8S쾙lU=b=3})؎R>bJݥCh i>7;}?#8>yoVzsj/?U>>.O\} v^ $#dwtZ뿽\_ŗfy?le^_v7__}ݞ>&MCo~_ӝӏ_?wf}?^!cws@ۂWC`s ַu~ӗKx<<F;@v*yK>:O I:Ou!)o[p}>1[|mOO^㵷aٯ+%e˾I7//=^Ӄ16=B܅Wawo[*vKw,Kqm7 ?7:|8lݻw7?&y}2Kw.G?pnCOeFWo1=/]}߮BS@WB11^H`LTfe>$ԑ} GIEr}/8=k;f}~K1 CFM}mnkICc cdiI߳& s Yl)a<ˌ x`[i62=Rj.[t5$*b"Lb dd3vs6f"B1@ؚ TD|ke_SP19agPM9Ƹ&`*Ba >N5(sd}z%-i_o B۱"J"w*h#9i9PR}&SC a^/65gEiLCĴz751mɘvQzB|{&Xgφ)x sM$Σ7|8D<cF\3φ<8!?aBt^p /Е9< sbd/ŏw66,ƥ cVDkkx\/ģgk ޏ_ ^_8;:d"|{MF0ƅz!KFҁ2޼lL2J{2R(KWួCS0Uչ_!șx0c `8㈲ x+J)'Qmk0i ج ҟL dpdvvk EKY`ߺ43xRV+nQg'-26Йh) *[ZMej0Cz)++[yLTwćo nS6t8=ܺeՏOzx9;4|@1; 1zѸck׾<|xEYŽCzڬCFMyr {D) Uxz;}ӕ; f|gho)c☆ߘ $fO,3̛S\2Š~4u-:7@גDC{*22U{2'<"#+8VpՈ, B4ݧq͂8#-]&;p`Ԣ\0& EZ1Ę䢑ftseaJ01UeQAIY*)Q!U&BBf{4YVרvKW!Lz8Sp̄oQ7:t\٠iE=2!ᙦWp\eDhE~i-;CKCzx]V+ӣe7ѥif@ tHte.)p<~NӔD:% wW (/%A\+<:o]2ƑU aiFotxYߴ94ufh*X$8W"ݕѡeuP-ѲZ~jشOt&TŰkHX+!p"|.v[2U~+s!no RPiE-L1FXIB%#F<%́+4mkǕڤ@eb\IHRK$ *U~c3g쬑0 MYljL dC\Z945stX`hcdXJܛ9@SUH@zM9Ai"|1A hjt;٫~|e~j|^qp:^A~ߚkYАh%gV+[l0rY #T6ZgU㘰G<`J'_v֩#ǘS1zegGM"=ϮK7Y2:wf`RP}u,u/0"0 M batMLV㥲\1p :k0bHաFT%)1Iwqִ!oTK:'|i5vu:Hd:,2l>-%@4BIر,mzLa||:Y`Z,!c!>7&bz DF\٦0͗Up:ȋB2K//VppYљ~aMӋKjA伓yBDܙ*; JCӥ T6ʮ@%N.U9,11Oꂚ#$eGze),H!%bD .y:$*4-bbPuQ.)2'%SH]YX.U;015X-]Q'cK[c,l 0֡zHǤʨ/'|DlQ{Ytn}B|(b a<s̳/Q[DrtAG^Ʀ+.(6:ʦ4p("824_P3|kU&1d.LM{T .p WkD1i/* vrګpҋr_ ^+Y3D}^_= ndK 1}HUX>O#y{Ǜ?ǧn>>Dwxܝo 7?vSk|A b˼OP.Q}<뷻\O+4U9_lVoc!bɬY d_X”Wip?i +} w#J T\=聰1%z@XRSG̈X7/x=Zϻ(SP/\/veKsD/R*2зVqyStf1; ]e0Hmo<L7Mv7Ai׽&/D,ꇫO]DJd_JEyIԼr$^^i B[ZhixouWåf #_tls4^ ~$͍I!pn'$ c W::1pKLg>&e&>tjwxmx8/7qƬ0qS8XMP<4N =sCb7x$B IEm"%D" G^uŽ\(=&>gʹ(3-̃p Mu*,ix]mTߝ%%nrkp/]m^HWH+2 xpXGCjP>^8W?qNJNV9T҇PJʥX _Ԏd=BW\Cb OPLfkejniʠd:4ڰhKβ}I5\̩DT0ԷrinmL#2p!vLl? dCr8P}R{A6Yyd4ؠvhнCMٰM@I Q$k#Ái 5b;xQG0JM*2H0v~HCnfÔ0wlv͹q{SSX7Izq$tNa \L_*$1!uBhW&5.}R 6ÁXA0&kEU1Al\ǁX,&}P(gZ/\u^Q9&36JA:랝j$WB~*ec#7uQL8(O+яt rM;kMnsx eX&a`z3;ý V)YܭZS\ֽ2Sn)ZHISZ5 9D34U>1rcDk  ._Yf*[KT ʣ { (u0XѴO$T-`bgD#Kz0`pEW"'4FEce9e<78ӠKr1; v/C8/&{2'aŖe^#l]R:r XGeDN”˭ XFơ2FYɤO܊6 P[ $l/xX?z}s_[oV,; Ekns׻*mr zۮW߃jiS}wޤL&%0EJg~)@6EC$D%c]Jl!%'GϠ/IWb6eU=wmlQBAVPx{( .f(MTcjG'#%db aE^ ‹钗 `]SG9(lRf:@L9o*( !EW@x!3&z4g+OmrE<6౉.Os**2PZaaZ ! H+6 H# 9b uH~<@8!DIO+}x$|y6! 'GO{WzIR81q f*eyҤBH Abő2zZ(ʱ R bₓd[“SU ,Q|w*?.tfDP`ucQV#C<"#3$)%.0RT98]Eqi2eq|k&#~?qeh7ciQ4`bP,Bλ.ش?P ڢY WFd25.QL mE^3uvPfl/ح)&l{,6`XC.U6vhcQW0@0XJ`%봃 Ai`&+!#a Va)8'!؇4ݻJ>>t?İG$ |v9ŀ?+҇&^aHr`ˁpg}(k۷<=HwhٸE\zU&t>$9IG(Q~Q~=r#j^Nj^NB]NX0f^OԗV " FPx|>s%ixu9}ͼq]3 dM`=*4nX.|pStHCxWN߮pf=S9|X-ohyr)iE"J *ȞůED)IᏚ[kn6N˺Vg [;tZ{^UtFY}H3uVR$T)[s[k`̓xhAǷt-d=0gT}$?b/!g\<IO(\cށP&k4ciXN]FdOqyMM{*#6Y;%#8`:B_+[XeHkD]y x~p.!Yw4e8WXRY*x1i*kvKWT@CdJ)ǐ-NXR֧ IcVI(m}O`>`]a?<֕(0(t~[ +%*&" -*.J)cI| .؂JM͛SdOr\/no 5#) '˩)ctfq*?;m&l".ېuģT.1V\v[̔ U)lv( r#(h845_hd> 1"QN1>⃪!Eڡ_yS[q}^ӓP5Qi^pWPQdPv9`PЙi}d0&kfZ+3`=Eġ=a^/ ˲Րѐq108 #r W:ˡ}o c MN`"0_L6YG6f"!{.S8akqpcL!pKΦB` :*o1oMtwYD |^&bԪPЙI 햮Z 1mS:hvh(ǘ5rW"Drn=/C./J,ʛpMb9EWM!c E^gz:3 jnm1W|aw=.bǘ/G94}AʱY#~VuQ:*oZgdum]t5wwMT ׊\ù$XMt_m_@4+$LMBYt_m\`@cD#c>ec̺ TJQx bGܙ(hf=u1r(Q )V^NybPJ$*\qegR)WVԙIish bwђ=E1ih"LCkVh֘L-2}0u|0/H1.i9YszxjH#}^_{fcʽdhb>J"2!K2{ew  `l^Cd? qij?d픆@paSu>pX*ёp~~}@ LeZ!D: #WsE0 :X.kq@ѐ ȞJaP-DIƤB GS )4*Lۖgsd HyQd( ÀZi:Bg&AaFH$X+|845폀@&k7cҟ?2idJQ@%/߉s禼iA\jK55v1Rr(ZD#g𪶚Bg&/a[l2tXM(1&)ŽGBZZ4',zq 4yK76 `N)~M9%@cN9a[ ᘇ;ȇ)MMʇMnPcD0<Oid* ONB$2(,9>xSsvg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgPKt5D;2b svg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svgPKt5DHnUl svg.schematic.sparkfun-electromechanical_buzzer_schematic.svg_69129ed5bcec2b4b26eec3be62bb1125_schematic.svgPKt5DWw3'$Synthesizer.fzPK&8fritzing-app-0.9.2b/sketches/core/obsolete/TwitterSaurus.fzz000066400000000000000000000126421250202676700242670ustar00rootroot00000000000000PKu5DӨ¬ NNTwitterSaurus.fz]m8~/S5d[tVҙIR3d2R40 t~ A5[iu|$=:ёt5Fw3\|vVk[\ h,b3ܡI1Fc긓cpp.]b\>ܼB=#,躷MwH=u٨g?/+gC3ܑ?q H3սyoV,d-F7[]~pc2f=c"E>e .zb0_nW`Y>gC4Uį+oʙy/ OVl3lԙ|wx,;_=Û͏w'O;LS>̉uy⟲}ï gVDI`d e~mTWf%\-12Ttf#|,᦭錯{+}랱(#0Wڻ[ɇ_CoR/{҂z' fEe1<:tT;q ׯDV'_Od?GԖ_P`oXV-Eal[R1x ߯{0!4L_ZV4pTIw0~ΤV,?=[wcC8]g/ P)/(`Z:EF !oq@FH+sc g(;P@VHR|f>$M˷ƷH}Es{OHNfRWЎJ-ZiiF0c|(̅@5rKY79WQvj]ak./Ksb{ڑurg_.y봊Ow IiCI2;%Pe0g ce*g]%7:eyXHcIJ2| DiZйWZk-䑺[ݲkpq%M)wzᾬڃ8MI ΓkJ{e(m86MXCKsYȊD\\D>4!o" bA  fVG0/]I03@9+L 9Z k~fZ'7-ri@eŠlF%o_nЦr_.@5.I%ňs Ngv- 0?t}F}AhmgKԃ<[R厪g wc>*QonhAuTP*vHIZ'F4[7 ;BBomrN'|#c[ bH<F S9GtTP*'Hs,,GIɺ| @>A$1acGR+K=d}mDc8ԕBIʎ>cce'';Cc+˂F?eԶl.ao'+;)fCE5J'2C5‘&k \  0ͮ律\ xYGΚM5NZ<.|$ ֞$håZ֎;-nv2AXљXhC:eDnqS2̧<$ l{&wo⽛&UYLʻJ~uX< ̝ރ;=~0,@eq}vgo:dS~z:X:?m>3 g1Fbrų8R7?n>/~b|ng}ܘOr7_lVjõ)M%(o2?G22v!a%KX~XK vKY\^_sMdT b_[F?HUјm!+/yX$,3;~(^ȁty e߉a-kwu=\9b[2U]0,)?彤=G[ þ|}a?} #ϡ:2; !JP%|#gg n0TwLY$t+;Ⱦ.W$m,~., }RVr|`s&Ab!- QN넏h؉GNJDO~AdC8&($'k6[Zp2&eN8YwமZ[BHRVTRJH`0{~SKN=j&czD#cE1MMM&yЃaDam䇖i^T Ek;S$a̍k+ ͸X H D*v[Q'Ot1]p|D}t|H1=M>`rLi]xYN"VHH$lԑB&&)#e2M=7)N',#e0EǎN9~ѓgDX:1NN;i~GGNJDkAdC&($k4Kp O蕢)iь[i% XMggcbG{,]ivݎ~`&kB4hX/LI]x_ӹ'1yCoϹOm?Σ?ېm?7;eϽ{i(<a4r}%q{1G!poH#H~.Z2'#B}SUDH!zM+籗u}ufTiF/9A]bWb<BkY Sˢŵ\k^Wee;j]2zU(a\F <i& U`͐{~&~[g7&Oϸw̉SErx*G@`T{~*'87T'4RoΣՑO*p]3oФՋdoP2_dTm Zama*J f~cH1 ,vv`'5u4IZt(]PcѥeJ%0w[gøkL]0,m0YZJK,]}Ia:MZR;QҪ5VҒkk,K$_hRuQ8SיjeEޗ:*ȭ3w[C4Ձ[Ӛy3@/Ni͂SkRi &Lz *y[}(ɐ-8 PYl,i~GDeQL6 V4q0oZb7ae2p8=[7pd],i50ch6:"(W,X$ Дm#eku$H'p#!:@d}mDcї$a ?K:X$zZbX&k[A/4n ]4ӳ<G= o:?GjM9C8bwQSi5F}Nfritzing-app-0.9.2b/sketches/core/obsolete/earthquakeDetection.fzz000066400000000000000000000201131250202676700254030ustar00rootroot00000000000000PKp5D#\?earthquakeDetection.fz]mw6_UMD ov=['mi{4_rd%U8~I/DR34sb p>gf0xy|r5 NWz 0Xt,Oj7 ]kE|3y_ ť=šp;#z:##۱r\ O?Bsq`47hb˩uz"_6 }KthѽJv5uWVx!u b&gFTn!FUFҶL@͙mXܣa]1s~_K-y 0› NRѝ AL#_{R/}MtntG[溎;(at&o>{P/buE|,SkoWV6. %ͷ͵]Yv3JzƋϩ0X4f-*y"a}FbuPt.&Nߌſ8>r1)Y4yӿit;A3% -'X8b Me=zǏWʔ q*Y7=̥V8L&P-GyI)eBӁx uEQTN_6)X1Q}cF,,y;_6:jcE^7U,_h4I'rVq+Ɇ\,&Zxl]b:~z?AΟ^]'06mNbNRXnkaX/ Xܤ u` /fT 8zIlBaI?[Y[/'F+gڟhvKyz:F|-kEwY}&D{3ׂZH|q6b{vT&΅7@FtR&aG,d$N ѕfܟ-&%#z%Q"~7΄M}㕐0t1׷|c89VheTMx_jm{u `1, XSEn@8[wӉyF݁T6^dWI) yb3FHMQoڝ]͟*Urbs'/hAܧJ@T\}vYcs2U3}7XΒra9UWڀ5-GC Ĩ} E#Q]>#J1ScF4L1b@r5Qg=9;Pljd)TA*zuX|d]\{A[RI*R1Bq(#uIhV!ni!ӪTюxI.RMlz0LV/-Kp+V%Z -dVnʄS~)N|dϪ QE5'K=bQ1JDORE!v"6;&H 5Zh=cO6 z/U +Xz!aOE-ÂzD]>@rGѐ<<<Z4h7w {0:ih1,V3ܭh7 MP+J$MY&E/Ęؘ.ի͞N|4>Zw͏珦atbB}W6Whv+_c0+0ʑpZ^lXҘf2dGA_lnQ4ohaF 1pUPD 'DUWbaE9Tt-ڱg*\!.Xl6(ٷqN*jI]Kߖ^εD2nB-F^OnPDJq2Ģ^%5[PY4JlG+ B|^lj&|lgPiktT>CXԛy8 *0FoF-AfaoSaC$#|stݡ$晼6yT> ܨn\d=mYUeZ4܇*n ^|ppW.Nj;Ҍsi2̌[*d$,iyaҐT]ժ.H쨢+$eQEu3JcjVj>jMK#8k&"86r zr&}FxlcNKY7Aq&CF!Ey-)l{7bi ll7:,Kb^)VÏ>'_Ar8Ev!DVF#@Sxl'day&J6/_>/_artIR;:BE\B|N6N{aqdXG`"1ꫩlRL®l6cTOD2g ms*Q+xu 0 i &Q#NhI?V+2&Ek$lueT $"ڔN6HiL#hUڦMЁV!0xL$lu%M^9^zv|9+ { ̩% FO9K 4T &\XCq &D2wsjQ &F`v'dO)eO&H4͚ӸG1(HL :{jˎleO@v;2{* vGWeO@!x86{*ZЫ'Ih=5hspw`sHD0y sGmFI)*;a7(p .ZϽ3״U8?R +Pm@Y]NyEr[c'0>)-V@ q…quLZHf-Ū@abQ(r^SsBTslj;@-B5@I1+Z;<L|\aatjwxK1M.鵮3 4~k]돯1B"q&R0as۾ZóRihyˎ!祳"ٔۊC k i8A8'=Fc춞EHk11MBDfIIX1iSfIa&K[Zm%]OP hOeܨ8֟)4\΍zk/FNX; VӆBXe.O6n_:Ē7ĚV;’t $m *# J%[7V7ݏ7E <"V%rPٙ!"of ĬN@EtـTӃA%D*2_ SrMڷl "yLZ[ λLu Bnz  H{T  Pxjڠ@ѹcldy8 &fOL#kǨTc5h3=Q/z(Qn3T<ӭʴf,,V Hxţ@!G bxy"έ`K;,6hY]; @}_ W]#s}-A@3\}Q*Zn'0 O&ЩO{("E V@hK{Ǫ7 `&9+&F2$cR;sIp6#=8 ,G޳-hsmO(%>`GZRR!k4 .yqxs3R dSY>\-kэ6Ny4 DZXԻ_ӫ y>|ʯ__g_nfg.g)1k|LWgoˡϮgRT^Wo+?͹|+?jb׿<מ_DȝI+hy=uQPEdL*ug]WGPqafz)y|z):_}N'ܪ:|/~y|w_}KJ #2V|m__?=ח~7o_??x{7}LJ7?ӛǟ_ūo7|}67o?+y߼뛏oŸZqn>?oۗyo[Wo?=>/9>뻯FWL~|lZ/Ͽ>|ݮ^o_j+?(ߙ?o_"q~qĚ?LzOoi?͗o'mpNŧo޾Ȗ?~8cE/N}y3l1޹p ;n& ~9>Jj8=Nk>=^ahs))==gC @fV h3#/ۋBj¤D[z+&hA916R 1b0FsH0߹oÞр.N 00O#> BJN$S#8a$=Tp)By)FNa~S$Y܂7ƈӮѠ&;.R`M^M'锢DN5a)7c5%MLj)e7)b=T'1婎D%pE89RX/fa-%1wGz9 qND*.4UwfÃO\(lr + ʷf8"z%r% -I;[gE ȒFE>/*Ni=s*SWΎorȓOㅡc3Bns,ݚzxlz]ϔȎB>?bD]0TSܚ} }˪ =չ쌙D6cuϐ"V1C]*ղ?i޾y{LRT(dk`sϖQkVfHфi2B] FTI*XƳa08QZV)0 7X!r3r B% ije3`@np%d+ B^ U$! (Tc3D3D"xՂUeU<+V* WTK|?eQCDqUEVWĪ`Ī`M$*"z i[S0IurMQlT &R`sZ ZdSS]@>5@)an +BY~" mMQE^3OijEosjTTZ9>P"JϥjZznVZy|+e$LcI$K*J*ւIʳ Zm~KRT0ȧlV^TGa,!uUV W9NE(O&D@춾]`.oܱ("P/~}EST @lg(QS鸝DYƾZm@.*Rr[ElJfb@$4:0P M(s%;mYNZ#%G]F}WĉINI5HG Rb}8)1Ӷ^]9`DJ[[l,#KY3{.]a&)]Oϳ nm}@'0*zt+93B l+1\8Cϭ=)CO8%]V/WQvRyΈ0ұ'eq՞d>(GUHgJ~MȰwǕŏ:Ҕ+MQzH4Ny4Cb!$Jg g9Y2YBZX-(q IL3Lΐ"Y2{;p8ڠq! Z۳ aـk)-0zElmcqccԵCCIfWazmXf }-s*TVε? 'U'Lb4Pc4$(VI 'C Nqb B^Lr3PdU3$ȧDVEo?06P1STRj[pIҫzzLN2w@ePStQI@C4Vi((Ή P:.J('\vkWO0Ak#E>O<'^qƓ19F+ǵLCS..\R;݊) J)7@Bxujdn~#ѠFh* L@lۆ*8,('L/'F0HՆmT&` mX-:"la~{V"?F"k[FEV_]ƣR(v+'#z v=1.MKeՏf1-Rs.{ڪVk8ll YƖX^j,ybIцro͍p:SzDdt 45 =&Ѓk ,FsZBTcT!'M95*F`u|)^1cCOye36]z*|: X "yNiS[)&;J/1-J*3M)kPdkPRSUY;w ]NgSx,aOMN?[*'m.:ߖxkqU?W\X[T Iaw<@RbؤyD5_ 2:Cc <TL-g0R. FVCfH)Ü,e%8 l7b|ݫ Ѥu jE춞Qh4N*?t7uPrM)b'5^G4T@lgPQM) aAnq8w7݀,/.fdWћQOkسR'&a7lBUQ+=AcxWWV xJ5#ߺķR$(X |*E-&cϹ%<$Ό#P}UhB'@SF>ye+C8ZBa{%76A]zm5U?=BM%[(@F 7"ERKE }w_|Wʮg,d"7SbV-W%:Ɵ&u ĖNKFFnS4 K;124tF~.~PR1:Ŀ[,3?8PVCmt ߇^;eδBl;1t:+K+5ie2XB^pg*8~ @!=\T&1;- ]܈-F,9,(7k7b^c- = bK'_߃ƙ (1d5 X#H.R(˟=-&1Gz,ȓMiqzT~S߅"8O |I6@^59xO.e5I/_f ɦ@^3̞dS+Svj lj [1݃ OG2BI*`z?@m]pAרot"Stŗ.EmTW><*ga,f}T[ }#|gB-jyT?VE><P3daWw'j0urOzkBXt)$azi?o3mDdž_jwL-+.<HJzK qΘSqcчASIO/uמOzBZIǩ`B-Nq;@JHGDocAě1s*+I#[زpu !תrhP%vrv#k4xwJ%=u- ^'Zزp"[tpب[زpN+x][.NwC-GtHCtR]khZCS(ZzCG /c-k 54/T _KO踻@H-4xQK7eCZI/heh:,\zxvWIhNR̎`!nWIx2ݟ}XO@qе}H U!ૐjO$k Ⱥnq7_K8Wjw [R'3,Z:<ѵw+C.0qyhAZG1x}KQ:9ki!&k e-moHz3PK+5@LB-L XKKiyܵ4Fki+ZKյ^ ͥG- y૾y㗯o>}>{ho_~忿{|7_˿z|Ƿ_^}~ëK/~쾑p߼kbgUv=Wdwzͯ_}!?DKΟ;?zW[t}2{}|.[&û_:|vZn_UN2عJ0*e?zLzc4Y1Fcr(afQB_ %#u(`s5l9#-Bl1!{% B!bBAI:[Èɖ0ѢD>$s'@'-rvZ6t-8@KMx1N *CiٴzyljX1"h2YE!"N끯KK i9۔ӕ/j3`j 4 7h)Noh ! o*S#El2͕QFI2rt#;X{54@-׿CQ;ocarM[{D-:/==\r;Q!8YɐADw^^N%,BdCk#jcb>]'lml-͆.>=j9ktFQ'ο:նFK'/$pQN.aDknÈF6#KDvƊIf65|tiXA"nrYu!p1D&mDM.g,d#oK&[ JŒ~fRL6.;<'^yAg9K8xY@LgШ;򶬖FK'a%'F7ٻzd2LL \-@@<EyAۛFKFSA{ d94cti.mYM>Ew#ԗ1rG#i/9qe{#RP|C#j$o.'0)RQYsj FͻNh=ÁPޖxk-0 G6[{D-97[yAG[MTǁ0Zq N0 't$oKP[7[TL,:bJh7}WKDLBzQOHM>o.u jo-pyޑ|<(-A H'A8¶6z[ 1I:!R[PI4;zVW6F"K8\vzuō Eq~q4y$L&>iT(tL6 w\IR+L:ZcD:q@D:+ v (!/(n>J@`iHMFb$F)L\gތNal׸T2{m w\i(5p3@/&"K vF c$^TTti0H":gJk*j: 3eȵ8TtĝQ!kF t#ѴSdiXvR*!D>ݔw $6qДn6sXG_/ 0- MRsp DEbHv}v6[S{D-zpCnM7Q G7 :83ÂzfP8Ӵk"=0x~o̓8ў^<(uv fCohp66$30p:npMFlh[>QcCѥ 3j.L=P l+7^hd( ee$ 2dQFFbAHuZ"@M q:$6If-h8ߊ!G։L%I 's׏νpMBF+L9 x!09b&<"Hoiy5DFl3" EgQрm?7ҩD: &4 Cm(N|+wx!+/pk* BygBZ6۸BFN \ZhXrbuxCE2h>N@`jXOJee4 ) Qj<5qVقlp\Q0u \k<t*&E #T41YZ'P 04R(.. yA?&KD FT|F'0QN)~>JkOѱ&"9/ ?ѱ{k~v=i%W^з֬B{~Q!ue`Ё\j!WmYsC|˯ق]mޚ !ru=P :ܚ=XP9, 5Y 㚍m@F:5  B{x!+/hШPti%7:%hʥq1M)C#P_I>|H3LgCȉomq* .4]ZƂL8Y4%N/zt\^u \G6OX9 N P(gdi@XaO E#ѥuSc|Z*p-Cfdg6{n 6+?HH;ݤu hbG7{ցx݅?0'yoeK7qZÄɳrICl%oIk/ʽCx;cp;B [$J@`i0M7YU7Hs$ 0mCK'ǀ{9Dԝ=n=#[jn8F1K+9O11Ve>dM|m_k'tpTgvlq́$oCy2 G L")Sa$:ff&&R6')㱥:`5Ktr^j5ITwd \ڂ M,E8JP-}#$Z$-!LSs.B]uU'v.ݪCFqŖGNj)j2SB& IbN+P1F %S&S%jԚ4Ax|v6Eq)E zR9i+4'㞙g6 t#Tj] A L9!p#bT38uHK1cy CT YxL;{6d̕ iu5Z.a2bJjJI^pG$S"DO&Bσcþ(n ]%UV] ]5:(A'ԞS&mKUkUU VŷR&&RTccH q?C$A QZGx tUK[L?`Q!F>]VT) DWIOyC[㟴P7} Y$lt,ehH⺊r8*$RO:Upª)Vʰ~XQ! Q'rO2Tk4jyk)aBEUvtΫ4xh7N90I#ܜp„ c>_j\ʄz"YOϩQXue抏{$#Oݒ$n\9nċ"Kh *x% Jdfvε2JҁZaP 켚  02)+%U7;PXCQC{c-n ͔&ZgeE`H,8]gI ŸcDq$:i)ƃ(dt.NG愋K8n@n;QkA}4 AGK$94)ДHadHRPs?بt ٨;͖''JT 1,{*=9!M&LE7foC9f2Nd}FJ+b:;CUU̫*3*H\ByDtL"+'O,(4Ӳw@-?p¤Tpl#MIr9'NR)b]MsйD>Tszs"54K+4t&qVWCRO-9ơFXX`.,?!m .Hd΄߫.'iA9G\dTy Uq& 5vPTP1IxjN`'ƮsTNϩk qO)>VtJ` |$rD%#V 'X '-(I21Q4?s"M6N>v'Gϼ6x>-ՎH3Ej~xLR;o6BvO!cO)c׳Pl*0>\pLG92u0R{ E9?@EW`$@/8qFTc'ҏs2&ڟ 42j5H bz]BL(5; 0?2/8'TL DZ낾2rWt9roulsKyѴ!36hrH֠ rcI,o,ytBIpTI3|˻? JMd`hRbHiBq5p>uP1ISOՏrIW쁜Фǟ>?~x|xeo ٙ__y կ?快K{zם2WQ1r9~;p-'pG' =m?:-Xq=1iN8uj|jGK7gB\ ǥgD*V .E!߯*^_FB!~x`MEPer}3S]Do>7]"\CDiծX~$d0U{؋IezuҐcbƒcAzuYѽ$rDz/L9kRl~-9io?,#9FA? vF/nyA/;^%]Ō+hϳ_g{&!ēDo$,ҟwrnx q' .Bnh= &cG'h$>,igQI|TqMoèjp &Dq|{}{;ǏTˆ*S)dN?y<8W 󵹭hHQ}o_qk g~z? VV'Ytn^г_/hlҘTEz%z >qA!O~?^!;T3/wmmZh=^iu_q/ЋI н~%v.)"><}n9U&k+%;нa5gzA-,a^K7U A[ӈ]24<U<[! JO-Y ?L+eH8ݠRiƥɠ%V6:v ,7!㓚 Z>֯с }dPM$%L 4+Էd~;گ=c Z>zӁ~F7jnи ;­)-g7hܠ_ܠk~n]>( ZI<+ *C=)HлA$ nP%c_v 6A Wܠ0oB' 7گėB5 /KVyARCto_„{$( 7䯖ėt^ 𤛘a%<[W_1\=LkGp [ppsb%;d KNhߏU6,+!{Òyla97LY\x楶| DޗazpEcwxZPSRJc/AʪFղjx:dwԽQ-tǷ_Bs}#fwptakY;B?;~"[]S ~5ѩGtO~@^vN/]M:??[6Gft&1 ׂotJB d/GOb3~ H0ܹJSxЩ V\*`!`yA$ӝ ꠀFF5y¥*IAx, @l׍8Z@& r#GHK-Y8|G@l;MD^t$SKQ'YJ)*cLaHmcLn禫)/Gӿ|n49Ar"5\g:|;+LL, aGa>0P/8͍4E^Kr)ˌp%#GYxy@z8PsbN5fR' G:#uYLvnԴ'uw;v8$*p&3n!B@ 41-JLC'G@=G.$P7@F.UW3ody#!_Dg6/8 ܸbVԟ\^S[JYu镚8sK@>3wot~02XGήҤv]F51v9&xQʮcՉnT!+{q!9@B^ P^+_Q\| Lm2jtH[C I3jhy+e[ Ήc_~%el\[C;'>1LJ|h:詮e> 9bFou#1mx/d||j"KKĆ6Ɔf^]l+< :PBN|hc[r3![u2҆7xlT!Z!T(\+|s+go+"NKzqҍFl=(p]]k§ͮV0b-i bbD3)DpOp>FYեˌ*bIpEPTȈ uE=CPH?vʈ.7F4 FB`D){sΈ#BP#r32>n\̈ F$bfګm6~#-'Y"!J!@fL\DKF6Ff^5rxa"> 7j.i9C30ѡth×!F29J] e14d71=Y6&CN [vvTNZ;C"܂c:@q;ҹЗM<6^!0I =wpjGLKU. h2o0>i~NΫ NP&s]@PپdomkA:8Ra 01D ?vCu?:dp/&f^!`"b6>Ե0!qkS0GŃ*s!$#LFl4a9NlBSS%&J 7\J Ku9Ih'V eؒH=)p/pBQN$Cjl ǥ(Q^;9O J4M .}ZLΐp"ʜا@H(.:4=%vL*.Qϵ츔 $To01ԾBp)9J(0S3D#B RMX0c+P4 5>) <P0zLu דaƞI(' FO惉윦DF 9>d&GXgqG ez+ }}*45*pejCy:ux/&f^!`Bb/Gm 5OT0 EF]O!v%yͤ1%bƫ[:?ahNa鍇?$3\Rr)v,&gŠ/TvI@S^,KSqCéَDIa`HVhrjvr &Jec Q^I4mW_'?Cj;͔Q0>;A)k79>33%C!9=KIa\jYMF4 )@ (a$qJLRv'qi(6EQKSpu˨( q -ec1 )r"04)H &?aNYu!1O4I[&1M~bJmLn\7$Zmyd3yFͲ}UjxSV@ڼVb3]M` M߁ƚ)*-4 :G V/YTmDf^"C'DqauI"]WuFJ'*@I1B(`OPT7+~TM'^% wr('w]@S!,'m4mMSʁ k*n zҦyUuUqK$#nth4RT?mrjAB[R;y踆)25H k A 15MQE+(2g5'N)'$ܳ(IUfJx¶IX9 Z@FSVKV !Bc%x|гKA BZB&c'eRA*or#5=?4vvGd`1…=Wd3%eU;YMVw@_hjv (^1trz( `` (``2 Oee`(PKGY^DWn$GLC{nnU) } f45Lc5 XQ>u%XHƂ !ChdTY<ʒġbi ӥUtpw+JeKV(]z x ţV!J%0t%0{C RdQyK9q%zBވޑ$$S)ҞY0vD' {$H})%A O_ JAZJ1E(.FS #)p%9~ `)&>(R 76\(VXqBPIC`gCi $n gpN%$^QY؍ w*WaE5ڑN VlE&f^)"bCҒj%^WeNa \?K*&D6SRRE Ɔ%+D?)c̥$LZt% ێ 7]J3HH+1C_MY.v& Lc?0XQ~&͕`! ƣ(MW&3F6u s, Ce9C:5Pu*3Ay@9Xhv5d ZtgzLp8ъj#\4y5n0\(akKSt{Tt]H*0Q m*`"&chQReP@Hn>"8&L!P1b`B0B\@f\Pq{LNTj9U 5\-L0Lu+Z4I5:I):ARA*fPuk#ϚTP4Ȩ271X K#oS֧ZszL4C}L&coRcZZW] hjvEV0S@Equu%VHۘR+x2`F$"GK}}?Ti}W˫_}_yW~}9GC|?߼׿ׇM*JٹkZ)lF~c?#߼ŏ_~v/·!+諧 q[^zEڇe?-r=1icz]|jG-.lLDiG5dOI/~;|pӛ[3׆g@Jw׵⎿BD< gw{<(1ǂF5&P}ahK> I`+ _G;D:_`=>x_k; ӂ(uHvs֬`_fe/5Wl-J^/dm7-#8>i!>~wDta.1zznR~r$>n7Ɨ;AB?{-n Vf"!~u̴P-Vz] ̲{t'9c/H_%(ĈS<"r5ڡΔ54#E:}ߜ~w @?wϞpP$oerb{t-Mrf @8SX3Vleeo`Iqp%ӀiW[Ht#CťDᲧL~NO)1>g\Ls¥{?KXW+[ݝWV.5;(Q#d.&*zw0½˕2oDDf7EE~-"͹n2%wheoZpt5.醞VyH Rb|DoN`nXdЀ+^2ղ!&R2gp-FH1 z7c3E{PI(LND()V v1o#v;~%FQ.H}EXOi`7KE,YP_<`͏;Td+X-"ݥ3$1jPl:(>uFޑ5Cy'炘,ciؿ ƏB:? eZѫ}j=P8~̢yk ~reg}=VkŶ>P.su;5w^5iB藤?&w[q\|_ Krqamɹ5.h䇛n)UB]cE xa1g#mUk'$gnleWD0/jO0F0g`D-m +ue274zU W]@?TL\Rp?|O\_7:KOsN޹|O;g o kF0/劈}9]y+䖐p}k쒘qK01/R) H=929AX").gDqBރKSƪnVu<_ͫbPKu5D PQ1 treeduino.fzPK:&Rfritzing-app-0.9.2b/sketches/index.xml000066400000000000000000000447111250202676700177560ustar00rootroot00000000000000 fritzing-app-0.9.2b/src/000077500000000000000000000000001250202676700150745ustar00rootroot00000000000000fritzing-app-0.9.2b/src/autoroute/000077500000000000000000000000001250202676700171235ustar00rootroot00000000000000fritzing-app-0.9.2b/src/autoroute/autorouteprogressdialog.cpp000066400000000000000000000141331250202676700246250ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "autorouteprogressdialog.h" #include "../debugdialog.h" #include "zoomcontrols.h" #include #include #include #include #include #include static const int ScrollAmount = 40; ArrowButton::ArrowButton(int scrollX, int scrollY, ZoomableGraphicsView * view, const QString & path) : QLabel() { m_scrollX = scrollX; m_scrollY = scrollY; m_view = view; setPixmap(QPixmap(path)); } void ArrowButton::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); if (m_scrollX != 0) { QScrollBar * scrollBar = m_view->horizontalScrollBar(); scrollBar->setValue(scrollBar->value() - m_scrollX); } else if (m_scrollY != 0) { QScrollBar * scrollBar = m_view->verticalScrollBar(); scrollBar->setValue(scrollBar->value() - m_scrollY); } } ///////////////////////////////////// AutorouteProgressDialog::AutorouteProgressDialog(const QString & title, bool zoomAndPan, bool stopButton, bool bestButton, bool spin, ZoomableGraphicsView * view, QWidget *parent) : QDialog(parent) { Qt::WindowFlags flags = windowFlags(); flags ^= Qt::WindowCloseButtonHint; flags ^= Qt::WindowContextHelpButtonHint; setWindowFlags(flags); this->setWindowTitle(title); QVBoxLayout * vLayout = new QVBoxLayout(this); m_progressBar = new QProgressBar(this); vLayout->addWidget(m_progressBar); m_spinLabel = NULL; m_spinBox = NULL; if (spin) { QFrame * frame = new QFrame(this); m_spinLabel = new QLabel(this); m_spinBox = new QSpinBox(this); m_spinBox->setMinimum(1); m_spinBox->setMaximum(99999); connect(m_spinBox, SIGNAL(valueChanged(int)), this, SLOT(internalSpinChange(int))); QHBoxLayout * hBoxLayout = new QHBoxLayout(frame); hBoxLayout->addStretch(); hBoxLayout->addWidget(m_spinLabel); hBoxLayout->addWidget(m_spinBox); vLayout->addWidget(frame); } m_message = new QLabel(this); vLayout->addWidget(m_message); m_message2 = new QLabel(this); vLayout->addWidget(m_message2); if (zoomAndPan) { QGroupBox * groupBox = new QGroupBox(tr("zoom and pan controls")); QHBoxLayout *lo2 = new QHBoxLayout(groupBox); lo2->setSpacing(1); lo2->setMargin(0); //TODO: use the zoom slider instead lo2->addWidget(new ZoomControls(view, groupBox)); lo2->addSpacerItem(new QSpacerItem ( 10, 0, QSizePolicy::Expanding)); QFrame * frame = new QFrame(); QGridLayout *gridLayout = new QGridLayout(frame); QString imgPath = ":/resources/images/icons/arrowButton%1.png"; ArrowButton * label = new ArrowButton(0, -ScrollAmount, view, imgPath.arg("Up")); gridLayout->addWidget(label, 0, 1); label = new ArrowButton(0, ScrollAmount, view, imgPath.arg("Down")); gridLayout->addWidget(label, 2, 1); label = new ArrowButton(-ScrollAmount, 0, view, imgPath.arg("Left")); gridLayout->addWidget(label, 0, 0, 3, 1); label = new ArrowButton(ScrollAmount, 0, view, imgPath.arg("Right")); gridLayout->addWidget(label, 0, 2, 3, 1); lo2->addWidget(frame); vLayout->addSpacing(7); vLayout->addWidget(groupBox); vLayout->addSpacing(7); } //QPushButton * button = new QPushButton(tr("Skip current trace"), this); //connect(button, SIGNAL(clicked()), this, SLOT(sendSkip())); //vLayout->addWidget(button); m_buttonBox = new QDialogButtonBox(stopButton ? QDialogButtonBox::Ok | QDialogButtonBox::Cancel : QDialogButtonBox::Cancel); if (stopButton) { m_buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Stop Now")); connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(sendStop())); } if (bestButton) { QPushButton * best = new QPushButton(tr("Best So Far")); m_buttonBox->addButton(best, QDialogButtonBox::ActionRole); connect(best, SIGNAL(clicked()), this, SLOT(sendBest())); } m_buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(sendCancel())); vLayout->addWidget(m_buttonBox); this->setLayout(vLayout); } AutorouteProgressDialog::~AutorouteProgressDialog() { } void AutorouteProgressDialog::setMinimum(int minimum) { m_progressBar->setMinimum(minimum); } void AutorouteProgressDialog::setMaximum(int maximum) { m_progressBar->setMaximum(maximum); } void AutorouteProgressDialog::setValue(int value) { m_progressBar->setValue(value); } void AutorouteProgressDialog::sendSkip() { emit skip(); } void AutorouteProgressDialog::sendCancel() { emit cancel(); } void AutorouteProgressDialog::sendStop() { emit stop(); } void AutorouteProgressDialog::sendBest() { emit best(); } void AutorouteProgressDialog::closeEvent(QCloseEvent *event) { sendCancel(); QDialog::closeEvent(event); } void AutorouteProgressDialog::setMessage(const QString & text) { m_message->setText(text); } void AutorouteProgressDialog::setMessage2(const QString & text) { m_message2->setText(text); } void AutorouteProgressDialog::setSpinLabel(const QString & text) { m_spinLabel->setText(text); } void AutorouteProgressDialog::setSpinValue(int value) { m_spinBox->setValue(value); } void AutorouteProgressDialog::internalSpinChange(int value) { emit spinChange(value); } void AutorouteProgressDialog::disableButtons() { m_buttonBox->setEnabled(false); } fritzing-app-0.9.2b/src/autoroute/autorouteprogressdialog.h000066400000000000000000000046231250202676700242750ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef AUTOROUTEPROGRESSDIALOG_H #define AUTOROUTEPROGRESSDIALOG_H #include #include #include #include #include class AutorouteProgressDialog : public QDialog { Q_OBJECT public: AutorouteProgressDialog(const QString & title, bool zoomAndPan, bool stopButton, bool bestButton, bool spin, class ZoomableGraphicsView * view, QWidget *parent = 0); ~AutorouteProgressDialog(); protected: void closeEvent(QCloseEvent *); public slots: void setMinimum(int); void setMaximum(int); void setValue(int); void sendSkip(); void sendCancel(); void sendStop(); void setSpinLabel(const QString &); void setMessage(const QString &); void setMessage2(const QString &); void setSpinValue(int); void disableButtons(); void sendBest(); signals: void skip(); void cancel(); void stop(); void best(); void spinChange(int); protected slots: void internalSpinChange(int); protected: QProgressBar * m_progressBar; QLabel * m_spinLabel; QLabel * m_message; QLabel * m_message2; QSpinBox * m_spinBox; QDialogButtonBox * m_buttonBox; }; class ArrowButton : public QLabel { Q_OBJECT public: ArrowButton(int scrollX, int scrollY, ZoomableGraphicsView * view, const QString & path); protected: void mousePressEvent(QMouseEvent *event); protected: int m_scrollX; int m_scrollY; ZoomableGraphicsView * m_view; }; #endif fritzing-app-0.9.2b/src/autoroute/autorouter.cpp000066400000000000000000000372441250202676700220520ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.a Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6947 $: $Author: irascibl@gmail.com $: $Date: 2013-04-03 06:45:22 +0200 (Mi, 03. Apr 2013) $ ********************************************************************/ #include "autorouter.h" #include "../sketch/pcbsketchwidget.h" #include "../debugdialog.h" #include "../items/symbolpaletteitem.h" #include "../items/virtualwire.h" #include "../items/tracewire.h" #include "../items/jumperitem.h" #include "../items/via.h" #include "../utils/graphicsutils.h" #include "../connectors/connectoritem.h" #include "../items/moduleidnames.h" #include "../processeventblocker.h" #include "../referencemodel/referencemodel.h" #include #include #include const QString Autorouter::MaxCyclesName("cmrouter/maxcycles"); Autorouter::Autorouter(PCBSketchWidget * sketchWidget) { m_sketchWidget = sketchWidget; m_useBest = m_stopTracing = m_cancelTrace = m_cancelled = false; } Autorouter::~Autorouter(void) { } void Autorouter::cleanUpNets() { foreach (QList * connectorItems, m_allPartConnectorItems) { delete connectorItems; } m_allPartConnectorItems.clear(); } void Autorouter::updateRoutingStatus() { RoutingStatus routingStatus; routingStatus.zero(); m_sketchWidget->updateRoutingStatus(routingStatus, true); } TraceWire * Autorouter::drawOneTrace(QPointF fromPos, QPointF toPos, double width, ViewLayer::ViewLayerPlacement viewLayerPlacement) { //DebugDialog::debug(QString("trace %1,%2 %3,%4").arg(fromPos.x()).arg(fromPos.y()).arg(toPos.x()).arg(toPos.y())); #ifndef QT_NO_DEBUG if (qAbs(fromPos.x() - toPos.x()) < 0.01 && qAbs(fromPos.y() - toPos.y()) < 0.01) { DebugDialog::debug("zero length trace", fromPos); } #endif long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setWireFlags(m_sketchWidget->getTraceFlag()); viewGeometry.setAutoroutable(true); viewGeometry.setLoc(fromPos); QLineF line(0, 0, toPos.x() - fromPos.x(), toPos.y() - fromPos.y()); viewGeometry.setLine(line); ItemBase * trace = m_sketchWidget->addItem(m_sketchWidget->referenceModel()->retrieveModelPart(ModuleIDNames::WireModuleIDName), viewLayerPlacement, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); if (trace == NULL) { // we're in trouble DebugDialog::debug("autorouter unable to draw one trace"); return NULL; } // addItem calls trace->setSelected(true) so unselect it (TODO: this may no longer be necessar) trace->setSelected(false); TraceWire * traceWire = dynamic_cast(trace); if (traceWire == NULL) { DebugDialog::debug("autorouter unable to draw one trace as trace"); return NULL; } m_sketchWidget->setClipEnds(traceWire, false); traceWire->setColorString(m_sketchWidget->traceColor(viewLayerPlacement), 1.0, false); traceWire->setWireWidth(width, m_sketchWidget, m_sketchWidget->getWireStrokeWidth(traceWire, width)); return traceWire; } void Autorouter::cancel() { m_cancelled = true; } void Autorouter::cancelTrace() { m_cancelTrace = true; } void Autorouter::stopTracing() { m_stopTracing = true; } void Autorouter::useBest() { m_useBest = m_stopTracing = true; } void Autorouter::initUndo(QUndoCommand * parentCommand) { // autoroutable traces, jumpers and vias are saved on the undo command and deleted // non-autoroutable traces, jumpers and via are not deleted QList toDelete; QList collidingItems; if (m_pcbType) { collidingItems = m_sketchWidget->scene()->collidingItems(m_board); foreach (QGraphicsItem * item, collidingItems) { JumperItem * jumperItem = dynamic_cast(item); if (jumperItem == NULL) continue; if (jumperItem->getAutoroutable()) { addUndoConnection(false, jumperItem, parentCommand); toDelete.append(jumperItem); continue; } // deal with the traces connecting the jumperitem to the part QList both; foreach (ConnectorItem * ci, jumperItem->connector0()->connectedToItems()) both.append(ci); foreach (ConnectorItem * ci, jumperItem->connector1()->connectedToItems()) both.append(ci); foreach (ConnectorItem * connectorItem, both) { TraceWire * w = qobject_cast(connectorItem->attachedTo()); if (w == NULL) continue; if (!w->isTraceType(m_sketchWidget->getTraceFlag())) continue; QList wires; QList ends; w->collectChained(wires, ends); foreach (Wire * wire, wires) { // make sure the jumper item doesn't lose its wires wire->setAutoroutable(false); } } } foreach (QGraphicsItem * item, collidingItems) { Via * via = dynamic_cast(item); if (via == NULL) continue; if (via->getAutoroutable()) { addUndoConnection(false, via, parentCommand); toDelete.append(via); continue; } // deal with the traces connecting the via to the part QList both; foreach (ConnectorItem * ci, via->connectorItem()->connectedToItems()) both.append(ci); foreach (ConnectorItem * ci, via->connectorItem()->getCrossLayerConnectorItem()->connectedToItems()) both.append(ci); foreach (ConnectorItem * connectorItem, both) { TraceWire * w = qobject_cast(connectorItem->attachedTo()); if (w == NULL) continue; if (!w->isTraceType(m_sketchWidget->getTraceFlag())) continue; QList wires; QList ends; w->collectChained(wires, ends); foreach (Wire * wire, wires) { // make sure the via doesn't lose its wires wire->setAutoroutable(false); } } } } else { collidingItems = m_sketchWidget->scene()->items(); foreach (QGraphicsItem * item, collidingItems) { SymbolPaletteItem * netLabel = dynamic_cast(item); if (netLabel == NULL) continue; if (!netLabel->isOnlyNetLabel()) continue; if (netLabel->getAutoroutable()) { addUndoConnection(false, netLabel, parentCommand); toDelete.append(netLabel); continue; } // deal with the traces connecting the netlabel to the part foreach (ConnectorItem * connectorItem, netLabel->connector0()->connectedToItems()) { TraceWire * w = qobject_cast(connectorItem->attachedTo()); if (w == NULL) continue; if (!w->isTraceType(m_sketchWidget->getTraceFlag())) continue; QList wires; QList ends; w->collectChained(wires, ends); foreach (Wire * wire, wires) { // make sure the netlabel doesn't lose its wires wire->setAutoroutable(false); } } } } QList visited; foreach (QGraphicsItem * item, collidingItems) { TraceWire * traceWire = dynamic_cast(item); if (traceWire == NULL) continue; if (!traceWire->isTraceType(m_sketchWidget->getTraceFlag())) continue; if (traceWire->getAutoroutable()) continue; if (visited.contains(traceWire)) continue; QList wires; QList ends; traceWire->collectChained(wires, ends); foreach (Wire * wire, wires) { visited << qobject_cast(wire); if (wire->getAutoroutable()) { wire->setAutoroutable(false); } } } foreach (QGraphicsItem * item, collidingItems) { TraceWire * traceWire = dynamic_cast(item); if (traceWire == NULL) continue; if (!traceWire->isTraceType(m_sketchWidget->getTraceFlag())) continue; if (!traceWire->getAutoroutable()) continue; toDelete.append(traceWire); addUndoConnection(false, traceWire, parentCommand); } foreach (ItemBase * itemBase, toDelete) { m_sketchWidget->makeDeleteItemCommand(itemBase, BaseCommand::CrossView, parentCommand); } foreach (ItemBase * itemBase, toDelete) { m_sketchWidget->deleteItem(itemBase, true, true, false); } } void Autorouter::addUndoConnection(bool connect, Via * via, QUndoCommand * parentCommand) { addUndoConnection(connect, via->connectorItem(), BaseCommand::CrossView, parentCommand); addUndoConnection(connect, via->connectorItem()->getCrossLayerConnectorItem(), BaseCommand::CrossView, parentCommand); } void Autorouter::addUndoConnection(bool connect, SymbolPaletteItem * netLabel, QUndoCommand * parentCommand) { addUndoConnection(connect, netLabel->connector0(), BaseCommand::CrossView, parentCommand); } void Autorouter::addUndoConnection(bool connect, JumperItem * jumperItem, QUndoCommand * parentCommand) { addUndoConnection(connect, jumperItem->connector0(), BaseCommand::CrossView, parentCommand); addUndoConnection(connect, jumperItem->connector1(), BaseCommand::CrossView, parentCommand); } void Autorouter::addUndoConnection(bool connect, TraceWire * traceWire, QUndoCommand * parentCommand) { addUndoConnection(connect, traceWire->connector0(), BaseCommand::CrossView, parentCommand); addUndoConnection(connect, traceWire->connector1(), BaseCommand::CrossView, parentCommand); } void Autorouter::addUndoConnection(bool connect, ConnectorItem * connectorItem, BaseCommand::CrossViewType crossView, QUndoCommand * parentCommand) { foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { VirtualWire * vw = qobject_cast(toConnectorItem->attachedTo()); if (vw != NULL) continue; ChangeConnectionCommand * ccc = new ChangeConnectionCommand(m_sketchWidget, crossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), connectorItem->attachedToID(), connectorItem->connectorSharedID(), ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), connect, parentCommand); ccc->setUpdateConnections(false); } } void Autorouter::restoreOriginalState(QUndoCommand * parentCommand) { QUndoStack undoStack; undoStack.push(parentCommand); undoStack.undo(); } void Autorouter::clearTracesAndJumpers() { QList toDelete; foreach (QGraphicsItem * item, (m_board == NULL) ? m_sketchWidget->scene()->items() : m_sketchWidget->scene()->collidingItems(m_board)) { if (m_pcbType) { JumperItem * jumperItem = dynamic_cast(item); if (jumperItem != NULL) { if (jumperItem->getAutoroutable()) { toDelete.append(jumperItem); } continue; } Via * via = dynamic_cast(item); if (via != NULL) { if (via->getAutoroutable()) { toDelete.append(via); } continue; } } else { SymbolPaletteItem * netLabel = dynamic_cast(item); if (netLabel != NULL && netLabel->isOnlyNetLabel()) { if (netLabel->getAutoroutable()) { toDelete.append(netLabel); } continue; } } TraceWire * traceWire = dynamic_cast(item); if (traceWire != NULL) { if (traceWire->isTraceType(m_sketchWidget->getTraceFlag()) && traceWire->getAutoroutable()) { toDelete.append(traceWire); } continue; } } foreach (ItemBase * itemBase, toDelete) { m_sketchWidget->deleteItem(itemBase, true, true, false); } } void Autorouter::doCancel(QUndoCommand * parentCommand) { emit setProgressMessage(tr("Routing canceled! Now cleaning up...")); ProcessEventBlocker::processEvents(); restoreOriginalState(parentCommand); cleanUpNets(); } void Autorouter::addToUndo(QUndoCommand * parentCommand) { QList wires; QList jumperItems; QList vias; QList netLabels; foreach (QGraphicsItem * item, (m_board == NULL) ? m_sketchWidget->scene()->items() : m_sketchWidget->scene()->collidingItems(m_board)) { TraceWire * wire = dynamic_cast(item); if (wire != NULL) { if (!wire->getAutoroutable()) continue; if (!wire->isTraceType(m_sketchWidget->getTraceFlag())) continue; m_sketchWidget->setClipEnds(wire, true); wire->update(); addWireToUndo(wire, parentCommand); wires.append(wire); continue; } if (m_pcbType) { JumperItem * jumperItem = dynamic_cast(item); if (jumperItem != NULL) { jumperItems.append(jumperItem); if (!jumperItem->getAutoroutable()) { continue; } jumperItem->saveParams(); QPointF pos, c0, c1; jumperItem->getParams(pos, c0, c1); new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, ModuleIDNames::JumperModuleIDName, jumperItem->viewLayerPlacement(), jumperItem->getViewGeometry(), jumperItem->id(), false, -1, parentCommand); new ResizeJumperItemCommand(m_sketchWidget, jumperItem->id(), pos, c0, c1, pos, c0, c1, parentCommand); new CheckStickyCommand(m_sketchWidget, BaseCommand::SingleView, jumperItem->id(), false, CheckStickyCommand::RemoveOnly, parentCommand); continue; } Via * via = dynamic_cast(item); if (via != NULL) { vias.append(via); if (!via->getAutoroutable()) { continue; } new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, ModuleIDNames::ViaModuleIDName, via->viewLayerPlacement(), via->getViewGeometry(), via->id(), false, -1, parentCommand); new CheckStickyCommand(m_sketchWidget, BaseCommand::SingleView, via->id(), false, CheckStickyCommand::RemoveOnly, parentCommand); new SetPropCommand(m_sketchWidget, via->id(), "hole size", via->holeSize(), via->holeSize(), true, parentCommand); continue; } } else { SymbolPaletteItem * netLabel = dynamic_cast(item); if (netLabel != NULL && netLabel->isOnlyNetLabel()) { netLabels.append(netLabel); if (!netLabel->getAutoroutable()) { continue; } new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, netLabel->moduleID(), netLabel->viewLayerPlacement(), netLabel->getViewGeometry(), netLabel->id(), false, -1, parentCommand); new SetPropCommand(m_sketchWidget, netLabel->id(), "label", netLabel->label(), netLabel->label(), true, parentCommand); continue; } } } foreach (TraceWire * traceWire, wires) { //traceWire->debugInfo("trace"); addUndoConnection(true, traceWire, parentCommand); } foreach (JumperItem * jumperItem, jumperItems) { addUndoConnection(true, jumperItem, parentCommand); } foreach (Via * via, vias) { addUndoConnection(true, via, parentCommand); } foreach (SymbolPaletteItem * netLabel, netLabels) { addUndoConnection(true, netLabel, parentCommand); } } void Autorouter::addWireToUndo(Wire * wire, QUndoCommand * parentCommand) { if (wire == NULL) return; new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, ModuleIDNames::WireModuleIDName, wire->viewLayerPlacement(), wire->getViewGeometry(), wire->id(), false, -1, parentCommand); new CheckStickyCommand(m_sketchWidget, BaseCommand::SingleView, wire->id(), false, CheckStickyCommand::RemoveOnly, parentCommand); new WireWidthChangeCommand(m_sketchWidget, wire->id(), wire->width(), wire->width(), parentCommand); new WireColorChangeCommand(m_sketchWidget, wire->id(), wire->colorString(), wire->colorString(), wire->opacity(), wire->opacity(), parentCommand); } void Autorouter::setMaxCycles(int maxCycles) { m_maxCycles = maxCycles; QSettings settings; settings.setValue(MaxCyclesName, maxCycles); } fritzing-app-0.9.2b/src/autoroute/autorouter.h000066400000000000000000000065411250202676700215130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef AUTOROUTER_H #define AUTOROUTER_H #include #include #include #include #include #include #include #include #include #include "../viewgeometry.h" #include "../viewlayer.h" #include "../connectors/connectoritem.h" #include "../commands.h" class Autorouter : public QObject { Q_OBJECT public: Autorouter(class PCBSketchWidget *); virtual ~Autorouter(void); virtual void start()=0; public: static const QString MaxCyclesName; protected: virtual void cleanUpNets(); virtual void updateRoutingStatus(); virtual class TraceWire * drawOneTrace(QPointF fromPos, QPointF toPos, double width, ViewLayer::ViewLayerPlacement); void initUndo(QUndoCommand * parentCommand); void addUndoConnection(bool connect, class SymbolPaletteItem *, QUndoCommand * parentCommand); void addUndoConnection(bool connect, class JumperItem *, QUndoCommand * parentCommand); void addUndoConnection(bool connect, class Via *, QUndoCommand * parentCommand); void addUndoConnection(bool connect, TraceWire *, QUndoCommand * parentCommand); void addUndoConnection(bool connect, ConnectorItem *, BaseCommand::CrossViewType, QUndoCommand * parentCommand); void restoreOriginalState(QUndoCommand * parentCommand); void doCancel(QUndoCommand * parentCommand); void clearTracesAndJumpers(); void addToUndo(QUndoCommand * parentCommand); void addWireToUndo(Wire * wire, QUndoCommand * parentCommand); public slots: virtual void cancel(); virtual void cancelTrace(); virtual void stopTracing(); virtual void useBest(); virtual void setMaxCycles(int); signals: void setMaximumProgress(int); void setProgressValue(int); void wantTopVisible(); void wantBottomVisible(); void wantBothVisible(); void setProgressMessage(const QString &); void setProgressMessage2(const QString &); void setCycleMessage(const QString &); void setCycleCount(int); void disableButtons(); protected: class PCBSketchWidget * m_sketchWidget; QList< QList* > m_allPartConnectorItems; bool m_cancelled; bool m_cancelTrace; bool m_stopTracing; bool m_useBest; bool m_bothSidesNow; int m_maximumProgressPart; int m_currentProgressPart; QGraphicsItem * m_board; int m_maxCycles; double m_keepoutPixels; QRectF m_maxRect; bool m_pcbType; }; #endif fritzing-app-0.9.2b/src/autoroute/autoroutersettingsdialog.cpp000066400000000000000000000314421250202676700250050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ /////////////////////////////////////// // todo: // save and reload as settings // enable/disable custom on radio presses // change wording on custom via // actually modify the autorouter // enable single vs. double-sided settings /////////////////////////////////////// #include "autoroutersettingsdialog.h" #include #include #include #include #include #include #include #include #include "../items/tracewire.h" #include "../items/via.h" #include "../fsvgrenderer.h" #include "../sketch/pcbsketchwidget.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "drc.h" const QString AutorouterSettingsDialog::AutorouteTraceWidth = "autorouteTraceWidth"; AutorouterSettingsDialog::AutorouterSettingsDialog(QHash & settings, QWidget *parent) : QDialog(parent) { m_traceWidth = settings.value(AutorouteTraceWidth).toInt(); Via::initHoleSettings(m_holeSettings); m_holeSettings.ringThickness = settings.value(Via::AutorouteViaRingThickness); m_holeSettings.holeDiameter = settings.value(Via::AutorouteViaHoleSize); this->setWindowTitle(QObject::tr("Autorouter Settings")); QVBoxLayout * windowLayout = new QVBoxLayout(); this->setLayout(windowLayout); QGroupBox * prodGroupBox = new QGroupBox(tr("Production type"), this); QVBoxLayout * prodLayout = new QVBoxLayout(); prodGroupBox->setLayout(prodLayout); m_homebrewButton = new QRadioButton(tr("homebrew"), this); connect(m_homebrewButton, SIGNAL(clicked(bool)), this, SLOT(production(bool))); m_professionalButton = new QRadioButton(tr("professional"), this); connect(m_professionalButton, SIGNAL(clicked(bool)), this, SLOT(production(bool))); m_customButton = new QRadioButton(tr("custom"), this); connect(m_customButton, SIGNAL(clicked(bool)), this, SLOT(production(bool))); m_customFrame = new QFrame(this); QHBoxLayout * customFrameLayout = new QHBoxLayout(this); m_customFrame->setLayout(customFrameLayout); customFrameLayout->addSpacing(5); QFrame * innerFrame = new QFrame(this); QVBoxLayout * innerFrameLayout = new QVBoxLayout(this); innerFrame->setLayout(innerFrameLayout); QWidget * traceWidget = createTraceWidget(); QWidget * keepoutWidget = createKeepoutWidget(settings.value(DRC::KeepoutSettingName)); QWidget * viaWidget = createViaWidget(); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); innerFrameLayout->addWidget(traceWidget); innerFrameLayout->addWidget(keepoutWidget); innerFrameLayout->addWidget(viaWidget); customFrameLayout->addWidget(innerFrame); prodLayout->addWidget(m_homebrewButton); prodLayout->addWidget(m_professionalButton); prodLayout->addWidget(m_customButton); prodLayout->addWidget(m_customFrame); windowLayout->addWidget(prodGroupBox); windowLayout->addSpacerItem(new QSpacerItem(1, 10, QSizePolicy::Preferred, QSizePolicy::Expanding)); windowLayout->addWidget(buttonBox); enableCustom(initProductionType()); } AutorouterSettingsDialog::~AutorouterSettingsDialog() { } void AutorouterSettingsDialog::production(bool checked) { Q_UNUSED(checked); QString units; if (sender() == m_homebrewButton) { enableCustom(false); changeHoleSize(sender()->property("holesize").toString() + "," + sender()->property("ringthickness").toString()); setTraceWidth(16); setDefaultKeepout(); } else if (sender() == m_professionalButton) { enableCustom(false); changeHoleSize(sender()->property("holesize").toString() + "," + sender()->property("ringthickness").toString()); setTraceWidth(24); setDefaultKeepout(); } else if (sender() == m_customButton) { enableCustom(true); } } void AutorouterSettingsDialog::enableCustom(bool enable) { m_customFrame->setVisible(enable); } bool AutorouterSettingsDialog::initProductionType() { m_homebrewButton->setChecked(false); m_professionalButton->setChecked(false); int custom = 0; QString keepoutString = getKeepoutString(); double mils = TextUtils::convertToInches(keepoutString) * 1000; if (qAbs(mils - DRC::KeepoutDefaultMils) >= 1) { custom++; } double standard = GraphicsUtils::pixels2mils(Wire::STANDARD_TRACE_WIDTH, GraphicsUtils::SVGDPI); if (qAbs(m_traceWidth - standard) >= 1) { custom++; } custom++; // assume the holesize/ringthickness won't match double rt = TextUtils::convertToInches(m_holeSettings.ringThickness); double hs = TextUtils::convertToInches(m_holeSettings.holeDiameter); foreach (QString name, m_holeSettings.holeThing->holeSizeKeys) { // have to loop through all values to set up the two buttons QStringList values = m_holeSettings.holeThing->holeSizes.value(name).split(","); QString ringThickness = values[1]; QString holeSize = values[0]; if (!name.isEmpty() && !ringThickness.isEmpty() && !holeSize.isEmpty()) { QRadioButton * button = NULL; if (name.contains("home", Qt::CaseInsensitive)) button = m_homebrewButton; else if (name.contains("standard", Qt::CaseInsensitive)) button = m_professionalButton; if (button) { button->setProperty("ringthickness", ringThickness); button->setProperty("holesize", holeSize); double krt = TextUtils::convertToInches(ringThickness); double khs = TextUtils::convertToInches(holeSize); if (qAbs(rt - krt) < 0.001 && qAbs(hs - khs) < 0.001) { // holesize/ringthickness match after all if (--custom == 0) { button->setChecked(true); } } } } } m_customButton->setChecked(custom > 0); return custom > 0; } void AutorouterSettingsDialog::widthEntry(const QString & text) { int w = TraceWire::widthEntry(text, sender()); if (w == 0) return; m_traceWidth = w; } void AutorouterSettingsDialog::changeHoleSize(const QString & newSize) { QString s = newSize; PaletteItem::setHoleSize(s, false, m_holeSettings); } void AutorouterSettingsDialog::changeUnits(bool) { QString newVal = PaletteItem::changeUnits(m_holeSettings); } void AutorouterSettingsDialog::changeDiameter() { if (PaletteItem::changeDiameter(m_holeSettings, sender())) { QLineEdit * edit = qobject_cast(sender()); changeHoleSize(edit->text() + m_holeSettings.currentUnits() + "," + m_holeSettings.ringThickness); } } void AutorouterSettingsDialog::changeThickness() { if (PaletteItem::changeThickness(m_holeSettings, sender())) { QLineEdit * edit = qobject_cast(sender()); changeHoleSize(m_holeSettings.holeDiameter + "," + edit->text() + m_holeSettings.currentUnits()); } } void AutorouterSettingsDialog::setTraceWidth(int width) { for (int i = 0; i > m_traceWidthComboBox->count(); i++) { if (m_traceWidthComboBox->itemData(i).toInt() == width) { m_traceWidthComboBox->setCurrentIndex(i); return; } } } QWidget * AutorouterSettingsDialog::createKeepoutWidget(const QString & keepoutString) { QGroupBox * keepoutGroupBox = new QGroupBox(tr("Keepout"), this); QVBoxLayout * vLayout = new QVBoxLayout(); QLabel * label = new QLabel(tr("Keepout is the minimum distance between copper elements on different nets.")); //label->setWordWrap(true); // setting wordwrap here seems to break the layout vLayout->addWidget(label); label = new QLabel(tr("A keepout of 0.01 inch (0.254 mm) is a good default.")); vLayout->addWidget(label); label = new QLabel(tr("Note: the smaller the keepout, the slower the DRC and Autorouter will run.")); vLayout->addWidget(label); QFrame * frame = new QFrame; QHBoxLayout * frameLayout = new QHBoxLayout; m_keepoutSpinBox = new QDoubleSpinBox; m_keepoutSpinBox->setDecimals(4); m_keepoutSpinBox->setLocale(QLocale::C); connect(m_keepoutSpinBox, SIGNAL(valueChanged(double)), this, SLOT(keepoutEntry())); frameLayout->addWidget(m_keepoutSpinBox); m_inRadio = new QRadioButton("in"); frameLayout->addWidget(m_inRadio); connect(m_inRadio, SIGNAL(clicked()), this, SLOT(toInches())); m_mmRadio = new QRadioButton("mm"); frameLayout->addWidget(m_mmRadio); connect(m_mmRadio, SIGNAL(clicked()), this, SLOT(toMM())); m_keepoutMils = TextUtils::convertToInches(keepoutString) * 1000; if (keepoutString.endsWith("mm")) { toMM(); m_mmRadio->setChecked(true); } else { toInches(); m_inRadio->setChecked(true); } frame->setLayout(frameLayout); vLayout->addWidget(frame); keepoutGroupBox->setLayout(vLayout); return keepoutGroupBox; } QWidget * AutorouterSettingsDialog::createTraceWidget() { QGroupBox * traceGroupBox = new QGroupBox(tr("Trace width"), this); QBoxLayout * traceLayout = new QVBoxLayout(); m_traceWidthComboBox = TraceWire::createWidthComboBox(m_traceWidth, traceGroupBox); connect(m_traceWidthComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(widthEntry(const QString &))); traceLayout->addWidget(m_traceWidthComboBox); traceGroupBox->setLayout(traceLayout); return traceGroupBox; } QWidget * AutorouterSettingsDialog::createViaWidget() { QGroupBox * viaGroupBox = new QGroupBox("Via size", this); QVBoxLayout * viaLayout = new QVBoxLayout(); QWidget * viaWidget = Hole::createHoleSettings(viaGroupBox, m_holeSettings, true, "", true); connect(m_holeSettings.sizesComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(changeHoleSize(const QString &))); connect(m_holeSettings.mmRadioButton, SIGNAL(toggled(bool)), this, SLOT(changeUnits(bool))); connect(m_holeSettings.inRadioButton, SIGNAL(toggled(bool)), this, SLOT(changeUnits(bool))); connect(m_holeSettings.diameterEdit, SIGNAL(editingFinished()), this, SLOT(changeDiameter())); connect(m_holeSettings.thicknessEdit, SIGNAL(editingFinished()), this, SLOT(changeThickness())); viaLayout->addWidget(viaWidget); viaGroupBox->setLayout(viaLayout); return viaGroupBox; } void AutorouterSettingsDialog::toInches() { m_keepoutSpinBox->blockSignals(true); m_keepoutSpinBox->setRange(.001, 1); m_keepoutSpinBox->setSingleStep(.001); m_keepoutSpinBox->setValue(m_keepoutMils / 1000); m_keepoutSpinBox->blockSignals(false); } void AutorouterSettingsDialog::toMM() { m_keepoutSpinBox->blockSignals(true); m_keepoutSpinBox->setRange(.001 * 25.4, 1); m_keepoutSpinBox->setSingleStep(.01); m_keepoutSpinBox->setValue(m_keepoutMils * 25.4 / 1000); m_keepoutSpinBox->blockSignals(false); } void AutorouterSettingsDialog::keepoutEntry() { double k = m_keepoutSpinBox->value(); if (m_inRadio->isChecked()) { m_keepoutMils = k * 1000; } else { m_keepoutMils = k * 1000 / 25.4; } } void AutorouterSettingsDialog::setDefaultKeepout() { m_keepoutMils = DRC::KeepoutDefaultMils; double inches = DRC::KeepoutDefaultMils / 1000; if (m_inRadio->isChecked()) { m_keepoutSpinBox->setValue(inches); } else { m_keepoutSpinBox->setValue(inches * 25.4); } } QHash AutorouterSettingsDialog::getSettings() { QHash settings; settings.insert(DRC::KeepoutSettingName, getKeepoutString()); settings.insert(Via::AutorouteViaHoleSize, m_holeSettings.holeDiameter); settings.insert(Via::AutorouteViaRingThickness, m_holeSettings.ringThickness); settings.insert(AutorouteTraceWidth, QString::number(m_traceWidth)); return settings; } QString AutorouterSettingsDialog::getKeepoutString() { double k = m_keepoutSpinBox->value(); if (m_inRadio->isChecked()) { return QString("%1in").arg(k); } else { return QString("%1mm").arg(k); } } fritzing-app-0.9.2b/src/autoroute/autoroutersettingsdialog.h000066400000000000000000000047341250202676700244560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef AUTOROUTERSETTINGSDIALOG_H #define AUTOROUTERSETTINGSDIALOG_H #include #include #include #include #include #include #include "../items/via.h" class AutorouterSettingsDialog : public QDialog { Q_OBJECT public: AutorouterSettingsDialog(QHash & settings, QWidget *parent = 0); ~AutorouterSettingsDialog(); QHash getSettings(); protected slots: void production(bool); void widthEntry(const QString &); void changeUnits(bool); void changeHoleSize(const QString &); void changeDiameter(); void changeThickness(); void toInches(); void toMM(); void keepoutEntry(); protected: void enableCustom(bool enable); bool initProductionType(); void setTraceWidth(int newWidth); QWidget * createViaWidget(); QWidget * createTraceWidget(); QWidget * createKeepoutWidget(const QString & keepoutString); QString getKeepoutString(); void setDefaultKeepout(); protected: QRadioButton * m_homebrewButton; QRadioButton * m_professionalButton; QRadioButton * m_customButton; HoleSettings m_holeSettings; QFrame * m_customFrame; QComboBox * m_traceWidthComboBox; int m_traceWidth; double m_keepoutMils; bool m_inches; QDoubleSpinBox * m_keepoutSpinBox; QRadioButton * m_inRadio; QRadioButton * m_mmRadio; public: static const QString AutorouteTraceWidth; }; #endif // AUTOROUTERSETTINGSDIALOG_H fritzing-app-0.9.2b/src/autoroute/cmrouter/000077500000000000000000000000001250202676700207635ustar00rootroot00000000000000fritzing-app-0.9.2b/src/autoroute/cmrouter/DBcell.cpp000066400000000000000000000274051250202676700226240ustar00rootroot00000000000000/* * DBcell.c -- * * Place and Delete subcells * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #include #include #include "tile.h" int placeCellFunc(Tile *, UserData); int deleteCellFunc(Tile *, UserData); Tile * clipCellTile(Tile * tile, Plane * plane, TileRect * rect); void cellTileMerge(Tile * tile, Plane * plane, int direction); bool ctbListMatch (Tile *tp1, Tile *tp2); struct searchArg { TileRect * rect; Plane * plane; QGraphicsItem * body; Tile::TileType type; }; #define TOPLEFT 10 #define TOPLEFTRIGHT 11 #define TOPBOTTOM 12 #define TOPBOTTOMLEFT 14 #define TOPBOTTOMLEFTRIGHT 15 /* * ---------------------------------------------------------------------------- * * DBPlaceCell -- * * Add a CellUse to the subcell tile plane of a CellDef. * Assumes prior check that the new CellUse is not an exact duplicate * of one already in place. * * Results: * None. * * Side effects: * Modifies the subcell tile plane of the given CellDef. * Resets the plowing delta of the CellUse to 0. Sets the * CellDef's parent pointer to point to the parent def. * * ---------------------------------------------------------------------------- */ void DBPlaceCell (Plane * plane, TileRect * rect, QGraphicsItem * body, Tile::TileType type) /* argument to TiSrArea(), placeCellFunc() */ /* argument to TiSrArea(), placeCellFunc() */ { struct searchArg arg; /* argument to placeCellFunc() */ arg.rect = rect; arg.plane = plane; arg.body = body; arg.type = type; (void) TiSrArea((Tile *) NULL, plane, rect, placeCellFunc, (UserData) &arg); } /* * ---------------------------------------------------------------------------- * DBDeleteCell -- * * Remove a CellUse from the subcell tile plane of a CellDef. * * Results: * None. * * Side effects: * Modifies the subcell tile plane of the CellDef, sets the * parent pointer of the deleted CellUse to NULL. * ---------------------------------------------------------------------------- */ void DBDeleteCell (Plane * plane, TileRect * rect) /* argument to TiSrArea(), deleteCellFunc() */ /* argument to TiSrArea(), deleteCellFunc() */ { struct searchArg arg; /* argument to deleteCellFunc() */ (void) TiSrArea((Tile *) NULL, plane, rect, deleteCellFunc, (UserData) &arg); } /* * ---------------------------------------------------------------------------- * placeCellFunc -- * * Add a new subcell to a tile. * Clip the tile with respect to the subcell's bounding box. * Insert the new CellTileBody into the linked list in ascending order * based on the celluse pointer. * This function is passed to TiSrArea. * * Results: * 0 is always returned. * * Side effects: * Modifies the subcell tile plane of the appropriate CellDef. * Allocates a new CellTileBody. * ---------------------------------------------------------------------------- */ int placeCellFunc (Tile * tile, UserData data) /* target tile */ /* celluse, rect, plane */ { struct searchArg * arg = (struct searchArg *) data; Tile * tp = clipCellTile (tile, arg->plane, arg->rect); TiSetType(tp, arg->type); TiSetBody(tp, arg->body); /* merge tiles back into the the plane */ /* requires that TiSrArea visit tiles in NW to SE wavefront */ if ( RIGHT(tp) == arg->rect->xmaxi) { if (YMIN(tp) == arg->rect->ymini) cellTileMerge (tp, arg->plane, TOPBOTTOMLEFTRIGHT); else cellTileMerge (tp, arg->plane, TOPLEFTRIGHT); } else if (YMIN(tp) == arg->rect->ymini) cellTileMerge (tp, arg->plane, TOPBOTTOMLEFT); else cellTileMerge (tp, arg->plane, TOPLEFT); return 0; } /* * ---------------------------------------------------------------------------- * deleteCellFunc -- * * Remove a subcell from a tile. * This function is passed to TiSrArea. * * Results: * Always returns 0. * * Side effects: * Modifies the subcell tile plane of the appropriate CellDef. * Deallocates a CellTileBody. * ---------------------------------------------------------------------------- */ int deleteCellFunc (Tile * tile, UserData data) { struct searchArg * arg = (struct searchArg *) data; /* merge tiles back into the the plane */ /* requires that TiSrArea visit tiles in NW to SE wavefront */ if ( RIGHT(tile) == arg->rect->xmaxi) { if (YMIN(tile) == arg->rect->ymini) cellTileMerge (tile, arg->plane, TOPBOTTOMLEFTRIGHT); else cellTileMerge (tile, arg->plane, TOPLEFTRIGHT); } else if (YMIN(tile) == arg->rect->ymini) cellTileMerge (tile, arg->plane, TOPBOTTOMLEFT); else cellTileMerge (tile, arg->plane, TOPLEFT); return (0); } /* * ---------------------------------------------------------------------------- * clipCellTile -- * * Clip the given tile against the given rectangle. * * Results: * Returns a pointer to the clipped tile. * * Side effects: * Modifies the database plane that contains the given tile. * ---------------------------------------------------------------------------- */ Tile * clipCellTile (Tile * tile, Plane * plane, TileRect * rect) { Tile * newtile; if (YMAX(tile) > rect->ymaxi) { newtile = TiSplitY (tile, rect->ymaxi); /* no merge */ } if (YMIN(tile) < rect->ymini) { newtile = tile; tile = TiSplitY (tile, rect->ymini); /* no merge */ } if (RIGHT(tile) > rect->xmaxi) { newtile = TiSplitX (tile, rect->xmaxi); cellTileMerge (newtile, plane, TOPBOTTOM); } if (LEFT(tile) < rect->xmini) { newtile = tile; tile = TiSplitX (tile, rect->xmini); cellTileMerge (newtile, plane, TOPBOTTOM); } return (tile); } /* clipCellTile */ /* * ---------------------------------------------------------------------------- * cellTileMerge -- * * Merge the given tile with its plane in the directions specified. * * Results: * None. * * Side effects: * Modifies the database plane that contains the given tile. * ---------------------------------------------------------------------------- */ void cellTileMerge (Tile * tile, Plane * plane, int direction) /* YMAX = 8, YMIN = 4, LEFT = 2, RIGHT = 1 */ { TilePoint topleft, bottomright; Tile * dummy, * tpleft, * tpright, * tp1, * tp2; topleft.xi = LEFT(tile); topleft.yi = YMAX(tile); bottomright.xi = RIGHT(tile); bottomright.yi = YMIN(tile); if ((direction >> 1) % 2) /* LEFT */ { tpright = tile; tpleft = BL(tpright); while (YMIN(tpleft) < topleft.yi) /* go up left edge */ { if (ctbListMatch (tpleft, tpright)) { if (YMIN(tpleft) < YMIN(tpright)) { dummy = tpleft; tpleft = TiSplitY (tpleft, YMIN(tpright)); } else if (YMIN(tpleft) > YMIN(tpright)) { dummy = tpright; tpright = TiSplitY (tpright, YMIN(tpleft)); } if (YMAX(tpleft) > YMAX(tpright)) { dummy = TiSplitY (tpleft, YMAX(tpright)); } else if (YMAX(tpright) > YMAX(tpleft)) { dummy = TiSplitY (tpright, YMAX(tpleft)); } // if (plane->pl_hint == tpright) plane->pl_hint = tpleft; TiJoinX (tpleft, tpright, plane); /* tpright disappears */ tpright = RT(tpleft); if (YMIN(tpright) < topleft.yi) tpleft = BL(tpright); else tpleft = tpright; /* we're off the top of the tile */ /* this will break the while loop */ } /* if (ctbListMatch (tpleft, tpright)) */ else tpleft = RT(tpleft); } /* while */ tile = tpleft; /* for TiSrPoint in next IF statement */ } if (direction % 2) /* RIGHT */ { tpright = TiSrPoint (tile, plane, bottomright.xi, bottomright.yi); tpleft = TiSrPoint (tpright, plane, bottomright.xi - MINDIFF, bottomright.yi); while (YMIN(tpright) < topleft.yi) /* go up right edge */ { if (ctbListMatch (tpleft, tpright)) { if (YMIN(tpright) < YMIN(tpleft)) { dummy = tpright; tpright = TiSplitY (tpright, YMIN(tpleft)); } else if (YMIN(tpleft) < YMIN(tpright)) { dummy = tpleft; tpleft = TiSplitY (tpleft, YMIN(tpright)); } if (YMAX(tpright) > YMAX(tpleft)) { dummy = TiSplitY (tpright, YMAX(tpleft)); } else if (YMAX(tpleft) > YMAX(tpright)) { dummy = TiSplitY (tpleft, YMAX(tpright)); } // if (plane->pl_hint == tpright) plane->pl_hint = tpleft; TiJoinX (tpleft, tpright, plane); /* tpright disappears */ tpright = RT(tpleft); while (LEFT(tpright) > bottomright.xi) tpright = BL(tpright); /* tpleft can be garbage if we're off the top of the loop, */ /* but it doesn't matter since the expression tests tpright */ tpleft = BL(tpright); } /* if (ctbListMatch (tpleft, tpright)) */ else { tpright = RT(tpright); while (LEFT(tpright) > bottomright.xi) tpright = BL(tpright); tpleft = BL(tpright); /* left side merges may have */ /* created more tiles */ } } /* while */ tile = tpright; /* for TiSrPoint in next IF statement */ } if ((direction >> 3) % 2) /* YMAX */ { tp1 = TiSrPoint (tile, plane, topleft.xi, topleft.yi); /* merge across top */ tp2 = TiSrPoint (tile, plane, topleft.xi, topleft.yi - MINDIFF);/* top slice of original tile */ if ((LEFT(tp1) == LEFT(tp2) ) && (RIGHT(tp1) == RIGHT(tp2)) && (ctbListMatch (tp1, tp2) )) { // if (plane->pl_hint == tp2) plane->pl_hint = tp1; TiJoinY (tp1, tp2, plane); } tile = tp1; /* for TiSrPoint in next IF statement */ } if ((direction >> 2) % 2) /* YMIN */ { /* bottom slice of orig tile */ tp1 = TiSrPoint (tile, plane, bottomright.xi - MINDIFF, bottomright.yi); tp2 = TiSrPoint (tile, plane, bottomright.xi - MINDIFF, bottomright.yi - MINDIFF); /* merge across bottom */ if ((LEFT(tp1) == LEFT(tp2) ) && (RIGHT(tp1) == RIGHT(tp2)) && (ctbListMatch (tp1, tp2) )) { // if (plane->pl_hint == tp2) plane->pl_hint = tp1; TiJoinY (tp1, tp2, plane); } } } /* * ---------------------------------------------------------------------------- * ctbListMatch -- * * Compare two linked lists of CellTileBodies, assuming that they are * sorted in ascending order by celluse pointers. * * Results: * True if the tiles have identical lists of CellTileBodies. * * Side effects: * None. * ---------------------------------------------------------------------------- */ bool ctbListMatch (Tile *tp1, Tile *tp2) { return (tp1->ti_body == tp2->ti_body) && (tp1->ti_type == tp2->ti_type); } /* * ---------------------------------------------------------------------------- * TiInsertTile -- * * create a tile with the given rect and insert it into the plane. * * Results: * the new Tile. * * Side effects: * Modifies the database plane that contains the given tile. * ---------------------------------------------------------------------------- */ Tile* TiInsertTile(Plane * plane, TileRect * rect, QGraphicsItem * body, Tile::TileType type) { DBPlaceCell(plane, rect, body, type); return TiSrPoint(NULL, plane, rect->xmini, rect->ymini); } fritzing-app-0.9.2b/src/autoroute/cmrouter/cmrouter.cpp000066400000000000000000000532321250202676700233340ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** This router is based on the one described in Contour: A Tile-based Gridless Router http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-3.pdf Plus additional ideas from An Efficient Tile-Based ECO Router with Routing Graph Reduction http://www.cis.nctu.edu.tw/~ylli/paper/f69-li.pdf The corner stitching code is a modified version of code from the Magic VLSI Layout Tool http://opencircuitdesign.com/magic/ ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ // TODO: // // run separate beginning overlap check with half keepout width? // // would be nice to eliminate ratsnests as we go // // think of orderings like simulated annealing or genetic algorithms // // option to turn off propagation feedback? // remove debugging output and extra calls to processEvents // // still seeing a few thin tiles going across the board: // this is because the thick tiles above and below are wider than the thin tile // // slide corner: if dogleg is too close to other connectors, slide it more towards the middle // // bugs: // why does the same routing task give different results (qSort?) // especially annoying in schematic view when sometimes wires flow along wires and sometimes don't, for the same routing task // border seems asymmetric // still some funny shaped routes (thin tile problem?) // jumper item: sometimes one end doesn't route // schematic view: some lines still overlap // split_original_wire.fz shouldn't have two jumpers // stepper motor example: not putting jumper item in space to the left of a connector where there is clearly open space // is this due to a blocking thin tile? // some traces violate drc // // catching 1st repeat to end rip-up-and-reroute is not valid // // longer route than expected: // It is possible that the shortest tile route is actually longer than the shortest crow-fly route. // For example, in the following case, route ABC will reach goal before ABDEF: // ------- // | A | // ------------------------------------ // | B | // ------------------------------------ // | | | D | // | | -------------- // | C | | E | // | | ------------------- // | | | F | // ------------------------------------------ // | GOAL | // ------------------------------------------ // There is a way to deal with this in the following paper: http://eie507.eie.polyu.edu.hk/projects/sp-tiles-00980255.pdf // // #include "cmrouter.h" #include "../../sketch/pcbsketchwidget.h" #include "../../debugdialog.h" #include "../../items/virtualwire.h" #include "../../items/tracewire.h" #include "../../items/jumperitem.h" #include "../../items/via.h" #include "../../items/resizableboard.h" #include "../../utils/graphicsutils.h" #include "../../utils/graphutils.h" #include "../../utils/textutils.h" #include "../../connectors/connectoritem.h" #include "../../items/moduleidnames.h" #include "../../processeventblocker.h" #include "../../svg/groundplanegenerator.h" #include "../../svg/svgfilesplitter.h" #include "../../fsvgrenderer.h" #include "tile.h" #include "tileutils.h" #include #include #include #include //#include // forces a dependency on qt 4.7 #include #include static const int MaximumProgress = 1000; static int TileStandardWireWidth = 0; static int TileHalfStandardWireWidth = 0; static double StandardWireWidth = 0; static double HalfStandardWireWidth = 0; static const double CloseEnough = 0.5; static const int GridEntryAlpha = 128; //static qint64 seedNextTime = 0; //static qint64 propagateUnitTime = 0; static const int DefaultMaxCycles = 10; #ifndef QT_NO_DEBUG #define DGI(item) drawGridItem(item) #else #define DGI(item) Q_UNUSED(item) #endif static inline double dot(const QPointF & p1, const QPointF & p2) { return (p1.x() * p2.x()) + (p1.y() * p2.y()); } bool tilePointRectXLessThan(TilePointRect * tpr1, TilePointRect * tpr2) { return tpr1->tilePoint.xi <= tpr2->tilePoint.xi; } bool tilePointRectYGreaterThan(TilePointRect * tpr1, TilePointRect * tpr2) { return tpr1->tilePoint.yi >= tpr2->tilePoint.yi; } /////////////////////////////////////////////// // // tile functions static inline void infoTile(const QString & message, Tile * tile) { if (tile == NULL) { DebugDialog::debug("infoTile: tile is NULL"); return; } DebugDialog::debug(QString("tile:%1 lb:%2 bl:%3 tr:%4 rt%5") .arg((long) tile, 0, 16) .arg((long) tile->ti_lb, 0, 16) .arg((long) tile->ti_bl, 0, 16) .arg((long) tile->ti_tr, 0, 16) .arg((long) tile->ti_rt, 0, 16)); DebugDialog::debug(QString("%1 tile:%2 l:%3 t:%4 w:%5 h:%6 type:%7 body:%8") .arg(message) .arg((long) tile, 0, 16) .arg(LEFT(tile)) .arg(YMIN(tile)) .arg(WIDTH(tile)) .arg(HEIGHT(tile)) .arg(TiGetType(tile)) .arg((long) TiGetBody(tile), 0, 16) ); } static inline void infoTileRect(const QString & message, const TileRect & tileRect) { DebugDialog::debug(QString("%1 l:%2 t:%3 w:%4 h:%5") .arg(message) .arg(tileRect.xmini) .arg(tileRect.ymini) .arg(tileRect.xmaxi - tileRect.xmini) .arg(tileRect.ymaxi - tileRect.ymini) ); } static inline int manhattan(TileRect & tr1, TileRect & tr2) { int dx = qAbs(tr1.xmaxi - tr2.xmaxi); dx = qMin(qAbs(tr1.xmaxi - tr2.xmini), dx); dx = qMin(qAbs(tr1.xmini - tr2.xmaxi), dx); dx = qMin(qAbs(tr1.xmini - tr2.xmini), dx); int dy = qAbs(tr1.ymaxi - tr2.ymaxi); dy = qMin(qAbs(tr1.ymaxi - tr2.ymini), dy); dy = qMin(qAbs(tr1.ymini - tr2.ymaxi), dy); dy = qMin(qAbs(tr1.ymini - tr2.ymini), dy); return dx + dy; } static inline GridEntry * TiGetGridEntry(Tile * tile) { return dynamic_cast(TiGetClient(tile)); } void extendToBounds(TileRect & from, TileRect & to) { // bail if it already extends to or past the bounds if (from.xmini <= to.xmini) return; if (from.xmaxi >= to.xmaxi) return; if (from.ymini <= to.ymini) return; if (from.ymaxi >= to.ymaxi) return; int which = 0; int dmin = from.xmini - to.xmini; if (to.xmaxi - from.xmaxi < dmin) { which = 1; dmin = to.xmaxi - from.xmaxi; } if (from.ymini - to.ymini < dmin) { which = 2; dmin = from.ymini - to.ymini; } if (to.ymaxi - from.ymaxi < dmin) { which = 3; dmin = to.ymaxi - from.ymaxi; } switch(which) { case 0: from.xmini = to.xmini; return; case 1: from.xmaxi = to.xmaxi; return; case 2: from.ymini = to.ymini; return; case 3: from.ymaxi = to.ymaxi; return; default: break; } } //////////////////////////////////////////////////////////////////// // // tile crawling functions int checkAlready(Tile * tile, UserData userData) { switch (TiGetType(tile)) { case Tile::SPACE: case Tile::SPACE2: case Tile::SCHEMATICWIRESPACE: case Tile::BUFFER: return 0; default: break; } QList * tiles = (QList *) userData; tiles->append(tile); return 0; } int prepDeleteTile(Tile * tile, UserData userData) { switch(TiGetType(tile)) { case Tile::DUMMYLEFT: case Tile::DUMMYRIGHT: case Tile::DUMMYTOP: case Tile::DUMMYBOTTOM: return 0; default: break; } //infoTile("prep delete", tile); QSet * tiles = (QSet *) userData; tiles->insert(tile); return 0; } //////////////////////////////////////////////////////////////////// GridEntry::GridEntry(QRectF & r, QGraphicsItem * parent) : QGraphicsRectItem(r, parent) { m_drawn = false; setAcceptedMouseButtons(Qt::NoButton); setAcceptHoverEvents(false); } bool GridEntry::drawn() { return m_drawn; } void GridEntry::setDrawn(bool d) { m_drawn = d; } //////////////////////////////////////////////////////////////////// CMRouter::CMRouter(PCBSketchWidget * sketchWidget, ItemBase * board, bool adjustIf) : QObject() { m_board = board; m_sketchWidget = sketchWidget; m_unionPlane = m_union90Plane = NULL; if (m_board) { m_maxRect = m_board->sceneBoundingRect(); } else { m_maxRect = m_sketchWidget->scene()->itemsBoundingRect(); if (adjustIf) { m_maxRect.adjust(-m_maxRect.width() / 2, -m_maxRect.height() / 2, m_maxRect.width() / 2, m_maxRect.height() / 2); } } QMatrix matrix90; matrix90.rotate(90); m_maxRect90 = matrix90.mapRect(m_maxRect); qrectToTile(m_maxRect, m_tileMaxRect); setUpWidths(m_sketchWidget->getAutorouterTraceWidth()); } CMRouter::~CMRouter() { } Plane * CMRouter::initPlane(bool rotate90) { Tile * bufferTile = TiAlloc(); TiSetType(bufferTile, Tile::BUFFER); TiSetBody(bufferTile, NULL); QRectF bufferRect(rotate90 ? m_maxRect90 : m_maxRect); TileRect br; qrectToTile(bufferRect, br); bufferRect.adjust(-bufferRect.width(), -bufferRect.height(), bufferRect.width(), bufferRect.height()); //DebugDialog::debug("max rect", m_maxRect); //DebugDialog::debug("max rect 90", m_maxRect90); int l = fasterRealToTile(bufferRect.left()); int t = fasterRealToTile(bufferRect.top()); int r = fasterRealToTile(bufferRect.right()); int b = fasterRealToTile(bufferRect.bottom()); SETLEFT(bufferTile, l); SETYMIN(bufferTile, t); // TILE is Math Y-axis not computer-graphic Y-axis Plane * thePlane = TiNewPlane(bufferTile, br.xmini, br.ymini, br.xmaxi, br.ymaxi); SETRIGHT(bufferTile, r); SETYMAX(bufferTile, b); // TILE is Math Y-axis not computer-graphic Y-axis // do not use InsertTile here TiInsertTile(thePlane, &thePlane->maxRect, NULL, Tile::SPACE); //infoTileRect("insert", thePlane->maxRect); return thePlane; } /* void CMRouter::shortenUs(QList & allPoints, JSubedge * subedge) { // TODO: this could be implemented recursively as a child tile space // with the goals being the sides of the U-shape and the obstacles copied in from the parent tile space // for now just look for a straight line int ix = 0; while (ix < allPoints.count() - 3) { QPointF p0 = allPoints.at(ix); QPointF p1 = allPoints.at(ix + 1); QPointF p2 = allPoints.at(ix + 2); QPointF p3 = allPoints.at(ix + 3); ix += 1; TileRect tileRect; if (p1.x() == p2.x()) { if ((p0.x() > p1.x() && p3.x() > p2.x()) || (p0.x() < p1.x() && p3.x() < p2.x())) { // opening to left or right bool targetGreater; if (p0.x() < p1.x()) { // opening left targetGreater = false; realsToTile(tileRect, qMax(p0.x(), p3.x()), qMin(p0.y(), p3.y()), p2.x(), qMax(p0.y(), p3.y())); } else { // opening right targetGreater = true; realsToTile(tileRect, p2.x(), qMin(p0.y(), p3.y()), qMin(p0.x(), p3.x()), qMax(p0.y(), p3.y())); } if (findShortcut(tileRect, true, targetGreater, subedge, allPoints, ix - 1)) { ix--; } } else { // not a U-shape continue; } } else if (p1.y() == p2.y()) { if ((p0.y() > p1.y() && p3.y() > p2.y()) || (p0.y() < p1.y() && p3.y() < p2.y())) { // opening to top or bottom bool targetGreater; if (p0.y() < p1.y()) { // opening top targetGreater = false; realsToTile(tileRect, qMin(p0.x(), p3.x()), qMax(p0.y(), p3.y()), qMax(p0.x(), p3.x()), p2.y()); } else { // opening bottom targetGreater = true; realsToTile(tileRect, qMin(p0.x(), p3.x()), p2.y(), qMax(p0.x(), p3.x()), qMin(p0.y(), p3.y())); } if (findShortcut(tileRect, false, targetGreater, subedge, allPoints, ix - 1)) { ix--; } } else { // not a U-shape continue; } } } } */ GridEntry * CMRouter::drawGridItem(Tile * tile) { return NULL; if (tile == NULL) return NULL; QRectF r; tileToQRect(tile, r); GridEntry * gridEntry = TiGetGridEntry(tile); if (gridEntry == NULL) { gridEntry = new GridEntry(r, NULL); gridEntry->setZValue(m_sketchWidget->getTopZ()); TiSetClient(tile, gridEntry); } else { QRectF br = gridEntry->boundingRect(); if (br != r) { gridEntry->setRect(r); gridEntry->setDrawn(false); } } if (gridEntry->drawn()) return gridEntry; QColor c; switch (TiGetType(tile)) { case Tile::SPACE: c = QColor(255, 255, 0, GridEntryAlpha); break; case Tile::SPACE2: c = QColor(200, 200, 0, GridEntryAlpha); break; case Tile::SOURCE: c = QColor(0, 255, 0, GridEntryAlpha); break; case Tile::DESTINATION: c = QColor(0, 0, 255, GridEntryAlpha); break; case Tile::SCHEMATICWIRESPACE: c = QColor(255, 192, 203, GridEntryAlpha); break; case Tile::OBSTACLE: c = QColor(60, 60, 60, GridEntryAlpha); break; default: c = QColor(255, 0, 0, GridEntryAlpha); break; } gridEntry->setPen(c); gridEntry->setBrush(QBrush(c)); if (gridEntry->scene() == NULL) { m_sketchWidget->scene()->addItem(gridEntry); } gridEntry->show(); gridEntry->setDrawn(true); ProcessEventBlocker::processEvents(); return gridEntry; } Tile * CMRouter::addTile(NonConnectorItem * nci, Tile::TileType type, Plane * thePlane, QList & alreadyTiled, CMRouter::OverlapType overlapType) { QRectF r = nci->attachedTo()->mapRectToScene(nci->rect()); TileRect tileRect; realsToTile(tileRect, r.left() - m_keepoutPixels, r.top() - m_keepoutPixels, r.right() + m_keepoutPixels, r.bottom() + m_keepoutPixels); Tile * tile = insertTile(thePlane, tileRect, alreadyTiled, nci, type, overlapType); DGI(tile); return tile; } void CMRouter::hideTiles() { foreach (QGraphicsItem * item, m_sketchWidget->items()) { GridEntry * gridEntry = dynamic_cast(item); if (gridEntry) gridEntry->setVisible(false); } } void CMRouter::clearPlane(Plane * thePlane) { if (thePlane == NULL) return; QSet tiles; //infoTileRect("clear", thePlane->maxRect); TiSrArea(NULL, thePlane, &thePlane->maxRect, prepDeleteTile, &tiles); foreach (Tile * tile, tiles) { TiFree(tile); } TiFreePlane(thePlane); } void CMRouter::displayBadTiles(QList & alreadyTiled) { //hideTiles(); foreach (Tile * tile, alreadyTiled) { TileRect tileRect; TiToRect(tile, &tileRect); displayBadTileRect(tileRect); } displayBadTileRect(m_overlappingTileRect); } void CMRouter::displayBadTileRect(TileRect & tileRect) { QRectF r; tileRectToQRect(tileRect, r); GridEntry * gridEntry = new GridEntry(r, NULL); gridEntry->setZValue(m_sketchWidget->getTopZ()); QColor c(255, 0, 0, GridEntryAlpha); gridEntry->setPen(c); gridEntry->setBrush(QBrush(c)); m_sketchWidget->scene()->addItem(gridEntry); gridEntry->show(); ProcessEventBlocker::processEvents(); } Tile * CMRouter::insertTile(Plane * thePlane, QRectF & rect, QList & alreadyTiled, QGraphicsItem * item, Tile::TileType tileType, CMRouter::OverlapType overlapType) { TileRect tileRect; qrectToTile(rect, tileRect); return insertTile(thePlane, tileRect, alreadyTiled, item, tileType, overlapType); } Tile * CMRouter::insertTile(Plane * thePlane, TileRect & tileRect, QList &, QGraphicsItem * item, Tile::TileType tileType, CMRouter::OverlapType overlapType) { //infoTileRect("insert tile", tileRect); if (tileRect.xmaxi - tileRect.xmini <= 0 || tileRect.ymaxi - tileRect.ymini <= 0) { DebugDialog::debug("attempting to insert zero width tile"); return NULL; } if (tileRect.xmaxi > thePlane->maxRect.xmaxi) { tileRect.xmaxi = thePlane->maxRect.xmaxi; } if (tileRect.xmini < thePlane->maxRect.xmini) { tileRect.xmini = thePlane->maxRect.xmini; } if (tileRect.ymaxi > thePlane->maxRect.ymaxi) { tileRect.ymaxi = thePlane->maxRect.ymaxi; } if (tileRect.ymini < thePlane->maxRect.ymini) { tileRect.ymini = thePlane->maxRect.ymini; } if (tileRect.xmaxi - tileRect.xmini <= 0 || tileRect.ymaxi - tileRect.ymini <= 0) { return NULL; } bool gotOverlap = false; if (overlapType != CMRouter::IgnoreAllOverlaps) { //TiSrArea(NULL, thePlane, &tileRect, checkAlready, &alreadyTiled); } if (gotOverlap) { m_overlappingTileRect = tileRect; DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!! overlaps not allowed !!!!!!!!!!!!!!!!!!!!!!"); return NULL; } Tile * newTile = TiInsertTile(thePlane, &tileRect, item, tileType); insertUnion(tileRect, item, tileType); DGI(newTile); return newTile; } bool CMRouter::overlapsOnly(QGraphicsItem *, QList & alreadyTiled) { bool doClip = false; for (int i = alreadyTiled.count() - 1; i >= 0; i--) { Tile * intersectingTile = alreadyTiled.at(i); if (dynamic_cast(TiGetBody(intersectingTile)) != NULL || dynamic_cast(TiGetBody(intersectingTile)) != NULL) { doClip = true; continue; } alreadyTiled.removeAt(i); } return doClip; } bool CMRouter::allowEquipotentialOverlaps(QGraphicsItem * item, QList & alreadyTiled) { bool collected = false; QList equipotential; Wire * w = dynamic_cast(item); if (w) { equipotential.append(w->connector0()); } else { ConnectorItem * ci = dynamic_cast(item); equipotential.append(ci); } foreach (Tile * intersectingTile, alreadyTiled) { QGraphicsItem * bodyItem = TiGetBody(intersectingTile); ConnectorItem * ci = dynamic_cast(bodyItem); if (ci != NULL) { if (!collected) { ConnectorItem::collectEqualPotential(equipotential, false, ViewGeometry::NoFlag); collected = true; } if (!equipotential.contains(ci)) { // overlap not allowed //infoTile("intersecting", intersectingTile); return false; } } else { Wire * w = dynamic_cast(bodyItem); if (w == NULL) return false; if (!collected) { ConnectorItem::collectEqualPotential(equipotential, false, ViewGeometry::NoFlag); collected = true; } if (!equipotential.contains(w->connector0())) { // overlap not allowed //infoTile("intersecting", intersectingTile); return false; } } } return true; } void CMRouter::clearGridEntries() { foreach (QGraphicsItem * item, m_sketchWidget->scene()->items()) { GridEntry * gridEntry = dynamic_cast(item); if (gridEntry == NULL) continue; delete gridEntry; } } bool CMRouter::insideV(const QPointF & check, const QPointF & vertex) { // form the V from p2 QPointF lv(vertex.x() - 10 + vertex.y() - check.y(), check.y() + 10); QPointF rv(vertex.x() + 10 - vertex.y() + check.y(), check.y() + 10); // the rest of this from: http://www.blackpawn.com/texts/pointinpoly/default.html QPointF v0 = rv - vertex; QPointF v1 = lv - vertex; QPointF v2 = check - vertex; // Compute dot products double dot00 = dot(v0, v0); double dot01 = dot(v0, v1); double dot02 = dot(v0, v2); double dot11 = dot(v1, v1); double dot12 = dot(v1, v2); // Compute barycentric coordinates double invDenom = 1 / (dot00 * dot11 - dot01 * dot01); double u = (dot11 * dot02 - dot01 * dot12) * invDenom; double v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in or on triangle return (u >= 0) && (v >= 0) && (u + v <= 1); } void CMRouter::insertUnion(TileRect & tileRect, QGraphicsItem *, Tile::TileType tileType) { if (m_unionPlane == NULL) return; if (tileType == Tile::SPACE) return; if (tileType == Tile::SPACE2) return; TiInsertTile(m_unionPlane, &tileRect, NULL, Tile::OBSTACLE); //infoTileRect("union", tileRect); TileRect tileRect90; tileRotate90(tileRect, tileRect90); if (tileRect90.xmaxi > m_union90Plane->maxRect.xmaxi) { tileRect90.xmaxi = m_union90Plane->maxRect.xmaxi; } if (tileRect90.xmini < m_union90Plane->maxRect.xmini) { tileRect90.xmini = m_union90Plane->maxRect.xmini; } if (tileRect90.ymaxi > m_union90Plane->maxRect.ymaxi) { tileRect90.ymaxi = m_union90Plane->maxRect.ymaxi; } if (tileRect90.ymini < m_union90Plane->maxRect.ymini) { tileRect90.ymini = m_union90Plane->maxRect.ymini; } if (tileRect90.xmaxi - tileRect90.xmini <= 0 || tileRect90.ymaxi - tileRect90.ymini <= 0) { return; } TiInsertTile(m_union90Plane, &tileRect90, NULL, Tile::OBSTACLE); } void CMRouter::drawTileRect(TileRect & tileRect, QColor & color) { QRectF r; tileRectToQRect(tileRect, r); GridEntry * gridEntry = new GridEntry(r, NULL); gridEntry->setZValue(m_sketchWidget->getTopZ()); gridEntry->setPen(color); gridEntry->setBrush(QBrush(color)); m_sketchWidget->scene()->addItem(gridEntry); gridEntry->show(); //ProcessEventBlocker::processEvents(); } TileRect CMRouter::boardRect() { return m_tileMaxRect; } void CMRouter::setUpWidths(double width) { StandardWireWidth = width; TileStandardWireWidth = fasterRealToTile(StandardWireWidth); HalfStandardWireWidth = StandardWireWidth / 2; TileHalfStandardWireWidth = fasterRealToTile(HalfStandardWireWidth); } void CMRouter::setKeepout(double keepout) { m_keepoutPixels = keepout; } void CMRouter::drcClean() { clearGridEntries(); if (m_unionPlane) { clearPlane(m_unionPlane); m_unionPlane = NULL; } if (m_union90Plane) { clearPlane(m_union90Plane); m_union90Plane = NULL; } } fritzing-app-0.9.2b/src/autoroute/cmrouter/cmrouter.h000066400000000000000000000070231250202676700227760ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6705 $: $Author: irascibl@gmail.com $: $Date: 2012-12-12 15:36:22 +0100 (Mi, 12. Dez 2012) $ ********************************************************************/ #ifndef JROUTER_H #define JROUTER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../viewgeometry.h" #include "../../viewlayer.h" #include "../autorouter.h" #include "tile.h" struct TilePointRect { TilePoint tilePoint; TileRect tileRect; }; class GridEntry : public QGraphicsRectItem { public: public: GridEntry(QRectF &, QGraphicsItem * parent); bool drawn(); void setDrawn(bool); protected: bool m_drawn; }; //////////////////////////////////// class CMRouter : public QObject { Q_OBJECT public: CMRouter(class PCBSketchWidget *, ItemBase * board, bool adjustIf); ~CMRouter(void); public: enum OverlapType { IgnoreAllOverlaps = 0, ClipAllOverlaps, ReportAllOverlaps, AllowEquipotentialOverlaps }; public: Plane * initPlane(bool rotate90); Tile * insertTile(Plane* thePlane, QRectF &tileRect, QList &alreadyTiled, QGraphicsItem *, Tile::TileType type, CMRouter::OverlapType); TileRect boardRect(); void setKeepout(double); void drcClean(); protected: GridEntry * drawGridItem(Tile * tile); void hideTiles(); void displayBadTiles(QList & alreadyTiled); void displayBadTileRect(TileRect & tileRect); Tile * addTile(class NonConnectorItem * nci, Tile::TileType type, Plane *, QList & alreadyTiled, CMRouter::OverlapType); Tile * insertTile(Plane* thePlane, TileRect &tileRect, QList &alreadyTiled, QGraphicsItem *, Tile::TileType type, CMRouter::OverlapType); void clearGridEntries(); void cleanPoints(QList & allPoints, Plane *); bool insideV(const QPointF & check, const QPointF & vertex); void makeAlignTiles(QMultiHash &, Plane * thePlane); bool overlapsOnly(QGraphicsItem * item, QList & alreadyTiled); void clearPlane(Plane * thePlane); bool allowEquipotentialOverlaps(QGraphicsItem * item, QList & alreadyTiled); void insertUnion(TileRect & tileRect, QGraphicsItem *, Tile::TileType tileType); void drawTileRect(TileRect & tileRect, QColor & color); void setUpWidths(double width); protected: TileRect m_tileMaxRect; QRectF m_maxRect90; TileRect m_overlappingTileRect; QList m_planes; Plane * m_unionPlane; Plane * m_union90Plane; ItemBase * m_board; QRectF m_maxRect; QString m_error; PCBSketchWidget * m_sketchWidget; double m_keepoutPixels; }; #endif fritzing-app-0.9.2b/src/autoroute/cmrouter/search.cpp000066400000000000000000000035151250202676700227400ustar00rootroot00000000000000/* * search.c -- * * Point searching. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #include #include "tile.h" /* * -------------------------------------------------------------------- * * TiSrPoint -- * * Search for a point. * * Results: * A pointer to the tile containing the point. * The bottom and left edge of a tile are considered part of * the tile; the top and right edge are not. * * Side effects: * Updates the hint tile in the supplied plane to point * to the tile found. * * -------------------------------------------------------------------- */ Tile * TiSrPoint(Tile * hintTile, Plane * plane, int x, int y) /* Pointer to tile at which to begin search. * If this is NULL, use the hint tile stored * with the plane instead. */ /* Plane (containing hint tile pointer) */ /* Point for which to search */ { Tile *tp = (hintTile) ? hintTile : plane->pl_hint; TilePoint point; point.xi = x; point.yi = y; plane->pl_hint = tp = gotoPoint(tp, point); return(tp); } fritzing-app-0.9.2b/src/autoroute/cmrouter/search2.cpp000066400000000000000000000160511250202676700230210ustar00rootroot00000000000000/* * search2.c -- * * Area searching. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #include #include "tile.h" int MINDIFF = 1; /* -------------------- Local function headers ------------------------ */ int tiSrAreaEnum(Tile *enumRT, int enumBottom, TileRect *rect, TileCallback, UserData arg); /* * -------------------------------------------------------------------- * * TiSrArea -- * * Find all tiles contained in or incident upon a given area. * Applies the given procedure to all tiles found. The procedure * should be of the following form: * * int * func(tile, cdata) * Tile *tile; * UserData cdata; * { * } * * Func normally should return 0. If it returns 1 then the search * will be aborted. * * THIS PROCEDURE IS OBSOLETE EXCEPT FOR THE SUBCELL PLANE. USE * DBSrPaintArea() IF YOU WANT TO SEARCH FOR PAINT TILES. * * Results: * 0 is returned if the search completed normally. 1 is returned * if it aborted. * * Side effects: * Whatever side effects result from application of the * supplied procedure. * * NOTE: * The procedure called is free to do anything it wishes to tiles * which have already been visited in the area search, but it must * not affect anything about tiles not visited other than possibly * corner stitches to tiles already visited. * * ************************************************************************* * ************************************************************************* * **** **** * **** WARNING **** * **** **** * **** This code is INCREDIBLY sensitive to modification! **** * **** Change it only with the utmost caution, or you'll **** * **** be verrry sorry! **** * **** **** * ************************************************************************* * ************************************************************************* * * -------------------------------------------------------------------- */ int TiSrArea(Tile *hintTile, Plane *plane, TileRect *rect, TileCallback tileCallback, UserData arg) /* Tile at which to begin search, if not NULL. * If this is NULL, use the hint tile supplied * with plane. */ /* Plane in which tiles lie. This is used to * provide a hint tile in case hintTile == NULL. * The hint tile in the plane is updated to be * the last tile visited in the area enumeration. */ /* Area to search */ /* Function to apply at each tile */ /* Additional argument to pass to (*func)() */ { TilePoint here; Tile *tp, *enumTR, *enumTile; int enumRight, enumBottom; /* * We will scan from top to bottom along the left hand edge * of the search area, searching for tiles. Each tile we * find in this search will be enumerated. */ here.xi = rect->xmini; here.yi = rect->ymaxi - MINDIFF; enumTile = hintTile ? hintTile : plane->pl_hint; plane->pl_hint = enumTile = gotoPoint(enumTile, here); while (here.yi >= rect->ymini) { /* * Find the tile (tp) immediately below the one to be * enumerated (enumTile). This must be done before we enumerate * the tile, as the filter function applied to enumerate * it can result in its deallocation or modification in * some other way. */ here.yi = YMIN(enumTile) - MINDIFF; tp = enumTile; plane->pl_hint = tp = gotoPoint(tp, here); enumRight = RIGHT(enumTile); enumBottom = YMIN(enumTile); enumTR = TR(enumTile); if ((*tileCallback)(enumTile, arg)) return 1; /* * If the right boundary of the tile being enumerated is * inside of the search area, recursively enumerate * tiles to its right. */ if (enumRight < rect->xmaxi) if (tiSrAreaEnum(enumTR, enumBottom, rect, tileCallback, arg)) return 1; enumTile = tp; } return 0; } /* * -------------------------------------------------------------------- * * tiSrAreaEnum -- * * Perform the recursive edge search of the tile which has just been * enumerated in an area search. The arguments passed are the RT * corner stitch and bottom coordinate of the tile just enumerated. * * Results: * 0 is returned if the search completed normally, 1 if * it was aborted. * * Side effects: * Attempts to enumerate recursively each tile found in walking * along the right edge of the tile just enumerated. Whatever * side effects occur result from the application of the client's * filter function. * * -------------------------------------------------------------------- */ int tiSrAreaEnum( Tile *enumRT, int enumBottom, TileRect *rect, TileCallback tileCallback, UserData arg) /* TR corner stitch of tile just enumerated */ /* Bottom coordinate of tile just enumerated */ /* Area to search */ /* Function to apply at each tile */ /* Additional argument to pass to (*func)() */ { Tile *tp, *tpLB, *tpTR; int tpRight, tpNextTop, tpBottom, srchBottom; int atBottom = (enumBottom <= rect->ymini); /* * Begin examination of tiles along right edge. * A tile to the right of the one being enumerated is enumerable if: * - its bottom lies at or above that of the tile being enumerated, or, * - the bottom of the tile being enumerated lies at or below the * bottom of the search rectangle. */ if ((srchBottom = enumBottom) < rect->ymini) srchBottom = rect->ymini; for (tp = enumRT, tpNextTop = YMAX(tp); tpNextTop > srchBottom; tp = tpLB) { /* * Since the client's filter function may result in this tile * being deallocated or otherwise modified, we must extract * all the information we will need from the tile before we * apply the filter function. */ tpLB = LB(tp); tpNextTop = YMAX(tpLB); /* Since YMAX(tpLB) comes from tp */ if (YMIN(tp) < rect->ymaxi && (atBottom || YMIN(tp) >= enumBottom)) { /* * We extract more information from the tile, which we will use * after applying the filter function. */ tpRight = RIGHT(tp); tpBottom = YMIN(tp); tpTR = TR(tp); if ((*tileCallback)(tp, arg)) return 1; /* * If the right boundary of the tile being enumerated is * inside of the search area, recursively enumerate * tiles to its right. */ if (tpRight < rect->xmaxi) if (tiSrAreaEnum(tpTR, tpBottom, rect, tileCallback, arg)) return 1; } } return 0; } fritzing-app-0.9.2b/src/autoroute/cmrouter/tile.cpp000066400000000000000000000445011250202676700224300ustar00rootroot00000000000000/* * tile.c -- * * Basic tile manipulation * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #include #include #include #include "tile.h" void dupTileBody(Tile * oldtp, Tile * newtp); /* * Debugging version of TiSetBody() macro in tile.h * Includes sanity check that a tile at "infinity" * is not being set to a type other than space. */ /* void TiSetBody(tp, b) Tile *tp; BodyPointer b; { if (b != (BodyPointer)0 && b != (BodyPointer)(-1)) if (RIGHT(tp) == INFINITY || YMAX(tp) == INFINITY || LEFT(tp) == MINFINITY || YMIN(tp) == MINFINITY) TxError("Error: Tile at infinity set to non-space value %d\n", (int)b); tp->ti_body = b; } */ /* * Rectangle that defines the maximum extent of any plane. * No tile created by the user should ever extend outside of * this area. */ int TINFINITY = (std::numeric_limits::max() >> 2) - 4; int MINFINITY = -TINFINITY; /* * -------------------------------------------------------------------- * * TiNewPlane -- * * Allocate and initialize a new tile plane. * * Results: * A newly allocated Plane with all corner stitches set * appropriately. * * Side effects: * Adjusts the corner stitches of the Tile supplied to * point to the appropriate bounding tile in the newly * created Plane. * * -------------------------------------------------------------------- */ Plane * TiNewPlane(Tile *tile, int minx, int miny, int maxx, int maxy) /* Tile to become initial tile of plane. * May be NULL. */ { Plane *newplane; static Tile *infinityTile = (Tile *) NULL; newplane = new Plane; newplane->pl_top = TiAlloc(); newplane->pl_right = TiAlloc(); newplane->pl_bottom = TiAlloc(); newplane->pl_left = TiAlloc(); newplane->maxRect.xmini = minx; newplane->maxRect.ymini = miny; newplane->maxRect.xmaxi = maxx; newplane->maxRect.ymaxi = maxy; /* * Since the lower left coordinates of the TR and RT * stitches of a tile are used to determine its upper right, * we must give the boundary tiles a meaningful TR and RT. * To make certain that these tiles don't have zero width * or height, we use a dummy tile at (TINFINITY+1,TINFINITY+1). */ if (infinityTile == (Tile *) NULL) { infinityTile = TiAlloc(); SETLEFT(infinityTile, TINFINITY+1); SETYMIN(infinityTile, TINFINITY+1); } if (tile) { SETRT(tile, newplane->pl_top); SETTR(tile, newplane->pl_right); SETLB(tile, newplane->pl_bottom); SETBL(tile, newplane->pl_left); } SETLEFT(newplane->pl_bottom, MINFINITY); SETYMIN(newplane->pl_bottom, MINFINITY); SETRT(newplane->pl_bottom, tile); SETTR(newplane->pl_bottom, newplane->pl_right); SETLB(newplane->pl_bottom, BADTILE); SETBL(newplane->pl_bottom, newplane->pl_left); TiSetBody(newplane->pl_bottom, 0); TiSetType(newplane->pl_bottom, Tile::DUMMYBOTTOM); SETLEFT(newplane->pl_top, MINFINITY); SETYMIN(newplane->pl_top, TINFINITY); SETRT(newplane->pl_top, infinityTile); SETTR(newplane->pl_top, newplane->pl_right); SETLB(newplane->pl_top, tile); SETBL(newplane->pl_top, newplane->pl_left); TiSetBody(newplane->pl_top, 0); TiSetType(newplane->pl_bottom, Tile::DUMMYTOP); SETLEFT(newplane->pl_left, MINFINITY); SETYMIN(newplane->pl_left, MINFINITY); SETRT(newplane->pl_left, newplane->pl_top); SETTR(newplane->pl_left, tile); SETLB(newplane->pl_left, newplane->pl_bottom); SETBL(newplane->pl_left, BADTILE); TiSetBody(newplane->pl_left, 0); TiSetType(newplane->pl_bottom, Tile::DUMMYLEFT); SETLEFT(newplane->pl_right, TINFINITY); SETYMIN(newplane->pl_right, MINFINITY); SETRT(newplane->pl_right, newplane->pl_top); SETTR(newplane->pl_right, infinityTile); SETLB(newplane->pl_right, newplane->pl_bottom); SETBL(newplane->pl_right, tile); TiSetBody(newplane->pl_right, 0); TiSetType(newplane->pl_bottom, Tile::DUMMYRIGHT); newplane->pl_hint = tile; return (newplane); } /* * -------------------------------------------------------------------- * * TiFreePlane -- * * Free the storage associated with a tile plane. * Only the plane itself and its four border tiles are deallocated. * * Results: * None. * * Side effects: * Frees memory. * * -------------------------------------------------------------------- */ void TiFreePlane(Plane *plane) /* Plane to be freed */ { TiFree(plane->pl_left); TiFree(plane->pl_right); TiFree(plane->pl_top); TiFree(plane->pl_bottom); delete plane; } /* * -------------------------------------------------------------------- * * TiToRect -- * * Convert a tile to a rectangle. * * Results: * None. * * Side effects: * Sets *rect to the bounding box for the supplied tile. * * -------------------------------------------------------------------- */ void TiToRect(Tile *tile, TileRect *rect) /* Tile whose bounding box is to be stored in *rect */ /* Pointer to rect to be set to bounding box */ { rect->xmini = LEFT(tile); rect->xmaxi = RIGHT(tile); rect->ymini = YMIN(tile); rect->ymaxi = YMAX(tile); } /* * -------------------------------------------------------------------- * * TiSplitX -- * * Given a tile and an X coordinate, split the tile into two * along a line running vertically through the given coordinate. * * Results: * Returns the new tile resulting from the splitting, which * is the tile occupying the right-hand half of the original * tile. * * Side effects: * Modifies the corner stitches in the database to reflect * the presence of two tiles in place of the original one. * * -------------------------------------------------------------------- */ Tile * TiSplitX(Tile *tile, int x) /* Tile to be split */ /* X coordinate of split */ { Tile *newtile; Tile *tp; //ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX"); newtile = TiAlloc(); dupTileBody(tile, newtile); SETLEFT(newtile, x); SETYMIN(newtile, YMIN(tile)); SETBL(newtile, tile); SETTR(newtile, TR(tile)); SETRT(newtile, RT(tile)); /* * Adjust corner stitches along the right edge */ for (tp = TR(tile); BL(tp) == tile; tp = LB(tp)) SETBL(tp, newtile); SETTR(tile, newtile); /* * Adjust corner stitches along the top edge */ for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp)) SETLB(tp, newtile); SETRT(tile, tp); /* * Adjust corner stitches along the bottom edge */ for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp)) /* nothing */; SETLB(newtile, tp); while (RT(tp) == tile) { SETRT(tp, newtile); tp = TR(tp); } return (newtile); } /* * -------------------------------------------------------------------- * * TiSplitY -- * * Given a tile and a Y coordinate, split the tile into two * along a horizontal line running through the given coordinate. * * Results: * Returns the new tile resulting from the splitting, which * is the tile occupying the top half of the original * tile. * * Side effects: * Modifies the corner stitches in the database to reflect * the presence of two tiles in place of the original one. * * -------------------------------------------------------------------- */ Tile * TiSplitY(Tile *tile, int y) /* Tile to be split */ /* Y coordinate of split */ { Tile *newtile; Tile *tp; //ASSERT(y > YMIN(tile) && y < YMAX(tile), "TiSplitY"); newtile = TiAlloc(); dupTileBody(tile, newtile); SETLEFT(newtile, LEFT(tile)); SETYMIN(newtile, y); SETLB(newtile, tile); SETRT(newtile, RT(tile)); SETTR(newtile, TR(tile)); /* * Adjust corner stitches along top edge */ for (tp = RT(tile); LB(tp) == tile; tp = BL(tp)) SETLB(tp, newtile); SETRT(tile, newtile); /* * Adjust corner stitches along right edge */ for (tp = TR(tile); YMIN(tp) >= y; tp = LB(tp)) SETBL(tp, newtile); SETTR(tile, tp); /* * Adjust corner stitches along left edge */ for (tp = BL(tile); YMAX(tp) <= y; tp = RT(tp)) /* nothing */; SETBL(newtile, tp); while (TR(tp) == tile) { SETTR(tp, newtile); tp = RT(tp); } return (newtile); } /* * -------------------------------------------------------------------- * * TiSplitX_Left -- * * Given a tile and an X coordinate, split the tile into two * along a line running vertically through the given coordinate. * Intended for use when plowing to the left. * * Results: * Returns the new tile resulting from the splitting, which * is the tile occupying the left-hand half of the original * tile. * * Side effects: * Modifies the corner stitches in the database to reflect * the presence of two tiles in place of the original one. * * -------------------------------------------------------------------- */ Tile * TiSplitX_Left(Tile *tile, int x) /* Tile to be split */ /* X coordinate of split */ { Tile *newtile; Tile *tp; //ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX"); newtile = TiAlloc(); dupTileBody(tile, newtile); SETLEFT(newtile, LEFT(tile)); SETLEFT(tile, x); SETYMIN(newtile, YMIN(tile)); SETBL(newtile, BL(tile)); SETLB(newtile, LB(tile)); SETTR(newtile, tile); SETBL(tile, newtile); /* Adjust corner stitches along the left edge */ for (tp = BL(newtile); TR(tp) == tile; tp = RT(tp)) SETTR(tp, newtile); /* Adjust corner stitches along the top edge */ for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp)) /* nothing */; SETRT(newtile, tp); for ( ; LB(tp) == tile; tp = BL(tp)) SETLB(tp, newtile); /* Adjust corner stitches along the bottom edge */ for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp)) SETRT(tp, newtile); SETLB(tile, tp); return (newtile); } /* * -------------------------------------------------------------------- * * TiSplitY_Bottom -- * * Given a tile and a Y coordinate, split the tile into two * along a horizontal line running through the given coordinate. * Used when plowing down. * * Results: * Returns the new tile resulting from the splitting, which * is the tile occupying the bottom half of the original * tile. * * Side effects: * Modifies the corner stitches in the database to reflect * the presence of two tiles in place of the original one. * * -------------------------------------------------------------------- */ Tile * TiSplitY_Bottom(Tile *tile, int y) /* Tile to be split */ /* Y coordinate of split */ { Tile *newtile; Tile *tp; //ASSERT(y > YMIN(tile) && y < YMAX(tile), "TiSplitY"); newtile = TiAlloc(); dupTileBody(tile, newtile); SETLEFT(newtile, LEFT(tile)); SETYMIN(newtile, YMIN(tile)); SETYMIN(tile, y); SETRT(newtile, tile); SETLB(newtile, LB(tile)); SETBL(newtile, BL(tile)); SETLB(tile, newtile); /* Adjust corner stitches along bottom edge */ for (tp = LB(newtile); RT(tp) == tile; tp = TR(tp)) SETRT(tp, newtile); /* Adjust corner stitches along right edge */ for (tp = TR(tile); YMIN(tp) >= y; tp = LB(tp)) /* nothing */; SETTR(newtile, tp); for ( ; BL(tp) == tile; tp = LB(tp)) SETBL(tp, newtile); /* Adjust corner stitches along left edge */ for (tp = BL(tile); YMAX(tp) <= y; tp = RT(tp)) SETTR(tp, newtile); SETBL(tile, tp); return (newtile); } /* * -------------------------------------------------------------------- * * TiJoinX -- * * Given two tiles sharing an entire common vertical edge, replace * them with a single tile occupying the union of their areas. * * Results: * None. * * Side effects: * The first tile is simply relinked to reflect its new size. * The second tile is deallocated. Corner stitches in the * neighboring tiles are updated to reflect the new structure. * If the hint tile pointer in the supplied plane pointed to * the second tile, it is adjusted to point instead to the * first. * * -------------------------------------------------------------------- */ void TiJoinX(Tile *tile1, Tile *tile2, Plane *plane) /* First tile, remains allocated after call */ /* Second tile, deallocated by call */ /* Plane in which hint tile is updated */ { Tile *tp; /* * Basic algorithm: * * Update all the corner stitches in the neighbors of tile2 * to point to tile1. * Update the corner stitches of tile1 along the shared edge * to be those of tile2. * Change the bottom or left coordinate of tile1 if appropriate. * Deallocate tile2. */ //ASSERT(YMIN(tile1)==YMIN(tile2) && YMAX(tile1)==YMAX(tile2), "TiJoinX"); //ASSERT(LEFT(tile1)==RIGHT(tile2) || RIGHT(tile1)==LEFT(tile2), "TiJoinX"); /* * Update stitches along top of tile */ for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp)) SETLB(tp, tile1); /* * Update stitches along bottom of tile */ for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp)) SETRT(tp, tile1); /* * Update stitches along either left or right, depending * on relative position of the two tiles. */ //ASSERT(LEFT(tile1) != LEFT(tile2), "TiJoinX"); if (LEFT(tile1) < LEFT(tile2)) { for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp)) SETBL(tp, tile1); SETTR(tile1, TR(tile2)); SETRT(tile1, RT(tile2)); } else { for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp)) SETTR(tp, tile1); SETBL(tile1, BL(tile2)); SETLB(tile1, LB(tile2)); SETLEFT(tile1, LEFT(tile2)); } if (plane->pl_hint == tile2) plane->pl_hint = tile1; TiFree(tile2); } /* * -------------------------------------------------------------------- * * TiJoinY -- * * Given two tiles sharing an entire common horizontal edge, replace * them with a single tile occupying the union of their areas. * * Results: * None. * * Side effects: * The first tile is simply relinked to reflect its new size. * The second tile is deallocated. Corner stitches in the * neighboring tiles are updated to reflect the new structure. * If the hint tile pointer in the supplied plane pointed to * the second tile, it is adjusted to point instead to the * first. * * -------------------------------------------------------------------- */ void TiJoinY(Tile *tile1, Tile *tile2, Plane *plane) /* First tile, remains allocated after call */ /* Second tile, deallocated by call */ /* Plane in which hint tile is updated */ { if (tile1 == tile2) { return; } Tile *tp; /* * Basic algorithm: * * Update all the corner stitches in the neighbors of tile2 * to point to tile1. * Update the corner stitches of tile1 along the shared edge * to be those of tile2. * Change the bottom or left coordinate of tile1 if appropriate. * Deallocate tile2. */ //ASSERT(LEFT(tile1)==LEFT(tile2) && RIGHT(tile1)==RIGHT(tile2), "TiJoinY"); //ASSERT(YMAX(tile1)==YMIN(tile2) || YMIN(tile1)==YMAX(tile2), "TiJoinY"); /* * Update stitches along right of tile. */ for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp)) SETBL(tp, tile1); /* * Update stitches along left of tile. */ for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp)) SETTR(tp, tile1); /* * Update stitches along either top or bottom, depending * on relative position of the two tiles. */ //ASSERT(YMIN(tile1) != YMIN(tile2), "TiJoinY"); if (YMIN(tile1) < YMIN(tile2)) { for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp)) SETLB(tp, tile1); SETRT(tile1, RT(tile2)); SETTR(tile1, TR(tile2)); } else { for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp)) SETRT(tp, tile1); SETLB(tile1, LB(tile2)); SETBL(tile1, BL(tile2)); SETYMIN(tile1, YMIN(tile2)); } if (plane->pl_hint == tile2) plane->pl_hint = tile1; TiFree(tile2); } /* * -------------------------------------------------------------------- * * TiAlloc --- * * Memory allocation for tiles * * Results: * Pointer to an initialized memory location for a tile. * * -------------------------------------------------------------------- */ Tile * TiAlloc() { Tile *newtile; newtile = new Tile; TiSetClient(newtile, 0); TiSetBody(newtile, 0); TiSetType(newtile, Tile::NOTYPE); //qDebug() << "alloc" << (long) newtile; SETLB(newtile, 0); SETBL(newtile, 0); SETRT(newtile, 0); SETTR(newtile, 0); return (newtile); } /* * -------------------------------------------------------------------- * * TiFree --- * * Release memory allocation for tiles * * Results: * None. * * -------------------------------------------------------------------- */ void TiFree(Tile *tp) { delete tp; } Tile* gotoPoint(Tile * tp, TilePoint p) { if (p.yi < YMIN(tp)) do tp = LB(tp); while (p.yi < YMIN(tp)); else while (p.yi >= YMAX(tp)) tp = RT(tp); if (p.xi < LEFT(tp)) do { do tp = BL(tp); while (p.xi < LEFT(tp)); if (p.yi < YMAX(tp)) break; do tp = RT(tp); while (p.yi >= YMAX(tp)); } while (p.xi < LEFT(tp)); else while (p.xi >= RIGHT(tp)) { do tp = TR(tp); while (p.xi >= RIGHT(tp)); if (p.yi >= YMIN(tp)) break; do tp = LB(tp); while (p.yi < YMIN(tp)); } return tp; } /* * ---------------------------------------------------------------------------- * dupTileBody -- * * Duplicate the body of an old tile as the body for a new tile. * * Results: * None. * * Side effects: * Allocates new CellTileBodies unless the old tile was a space tile. * ---------------------------------------------------------------------------- */ void dupTileBody (Tile * oldtp, Tile * newtp) { TiSetBody(newtp, TiGetBody(oldtp)); TiSetType(newtp, TiGetType(oldtp)); } fritzing-app-0.9.2b/src/autoroute/cmrouter/tile.h000066400000000000000000000212451250202676700220750ustar00rootroot00000000000000/* * tile.h -- * * Definitions of the basic tile structures * The definitions in this file are all that is visible to * the Ti (tile) modules. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* * * rcsid "$Header: /usr/cvsroot/magic-7.5/tiles/tile.h,v 1.7 2010/05/03 15:16:57 tim Exp $" */ #ifndef _TILES_H #define _TILES_H #include #include // note: Tile uses math axes as opposed to computer graphic axes. In other words y increases up. struct TileRect { int xmini; int ymini; int xmaxi; int ymaxi; }; struct TilePoint { int xi; int yi; }; /* * A tile is the basic unit used for representing both space and * solid area in a plane. It has the following structure: * * RT * ^ * | * ------------------------- * | | ---> TR * | | * | | * | (lower left) | * BL <--- ------------------------- * | * v * LB * * The (x, y) coordinates of the lower left corner of the tile are stored, * along with four "corner stitches": RT, TR, BL, LB. * * Space tiles are distinguished at a higher level by having a distinguished * tile body. */ typedef void * UserData; struct Tile { enum TileType { NOTYPE = 0, BUFFER = 1, SPACE, SPACE2, SCHEMATICWIRESPACE, SOURCE, DESTINATION, OBSTACLE, DUMMYLEFT = 999999, DUMMYTOP, DUMMYRIGHT, DUMMYBOTTOM }; struct Tile *ti_lb; /* Left bottom corner stitch */ struct Tile *ti_bl; /* Bottom left corner stitch */ struct Tile *ti_tr; /* Top right corner stitch */ struct Tile *ti_rt; /* Right top corner stitch */ TilePoint ti_ll; /* Lower left coordinate */ TileType ti_type; /* another free field */ QGraphicsItem * ti_body; /* Body of tile */ QGraphicsItem * ti_client; /* This space for hire. */ }; /* * The following macros make it appear as though both * the lower left and upper right coordinates of a tile * are stored inside it. */ inline Tile* LB(Tile* tileP) { return tileP->ti_lb; } inline Tile* BL(Tile* tileP) { return tileP->ti_bl; } inline Tile* TR(Tile* tileP) { return tileP->ti_tr; } inline Tile* RT(Tile* tileP) { return tileP->ti_rt; } inline void SETLB(Tile* tileP, Tile * val) { tileP->ti_lb = val; if (val == tileP) { int a = 0; a = a + 1; return; }} inline void SETBL(Tile* tileP, Tile * val) { tileP->ti_bl = val; if (val == tileP) { int a = 0; a = a + 1; return; }} inline void SETTR(Tile* tileP, Tile * val) { tileP->ti_tr = val; if (val == tileP) { int a = 0; a = a + 1; return; }} inline void SETRT(Tile* tileP, Tile * val) { tileP->ti_rt = val; if (val == tileP) { int a = 0; a = a + 1; return; }} inline int YMIN(Tile* tileP) { return tileP->ti_ll.yi; } inline int LEFT(Tile* tileP) { return tileP->ti_ll.xi; } inline int YMAX(Tile* tileP) { return YMIN(RT(tileP)); } inline int RIGHT(Tile* tileP) { return LEFT(TR(tileP)); } inline int WIDTH(Tile* tileP) { return RIGHT(tileP) - LEFT(tileP); } inline int HEIGHT(Tile* tileP) { return YMAX(tileP) - YMIN(tileP); } inline void SETYMIN(Tile* tileP, int val) { tileP->ti_ll.yi = val; } inline void SETLEFT(Tile* tileP, int val) { tileP->ti_ll.xi = val; } inline void SETYMAX(Tile* tileP, int val) { SETYMIN(RT(tileP), val); } inline void SETRIGHT(Tile* tileP, int val) { SETLEFT(TR(tileP), val); } typedef void (*TileFunc)(Tile *); /* ----------------------- Tile planes -------------------------------- */ /* * A plane of tiles consists of the four special tiles needed to * surround all internal tiles on all sides. Logically, these * tiles appear as below, except for the fact that all are located * off at infinity. * * -------------------------------------- * |\ /| * | \ / | * | \ TOP / | * | \ / | * | \ / | * | -------------------------- | * | | | | * |LEFT | |RIGHT| * | | | | * | -------------------------- | * | / \ | * | / \ | * | / BOTTOM \ | * | / \ | * |/ \| * -------------------------------------- */ struct Plane { Tile *pl_left; /* Left pseudo-tile */ Tile *pl_top; /* Top pseudo-tile */ Tile *pl_right; /* Right pseudo-tile */ Tile *pl_bottom; /* Bottom pseudo-tile */ Tile *pl_hint; /* Pointer to a "hint" at which to * begin searching. */ TileRect maxRect; }; /* * The following coordinate, TINFINITY, is used to represent a * tile location outside of the tile plane. * * It must be possible to represent TINFINITY+1 as well as * INFINITY. * * Also, because locations involving TINFINITY may be transformed, * it is desirable that additions and subtractions of small integers * from either TINFINITY or MINFINITY not cause overflow. * * Consequently, we define TINFINITY to be the largest integer * representable in wordsize - 2 bits. */ extern int TINFINITY; extern int MINFINITY; extern int MINDIFF; typedef int (*TileCallback)(Tile *, UserData); /* ------------------------ Flags, etc -------------------------------- */ #define BADTILE ((Tile *) 0) /* Invalid tile pointer */ /* ============== Function headers and external interface ============= */ /* * The following macros and procedures should be all that are * ever needed by modules other than the tile module. */ Plane *TiNewPlane(Tile *tile, int minx, int miny, int maxx, int maxy); void TiFreePlane(Plane *plane); void TiToRect(Tile *tile, TileRect *rect); Tile *TiSplitX(Tile *tile, int x); Tile *TiSplitY(Tile *tile, int y); Tile *TiSplitX_Left(Tile *tile, int x); Tile *TiSplitY_Bottom(Tile *tile, int y); void TiJoinX(Tile *tile1, Tile *tile2, Plane *plane); void TiJoinY(Tile *tile1, Tile *tile2, Plane *plane); int TiSrArea(Tile *hintTile, Plane *plane, TileRect *rect, TileCallback, UserData arg); Tile *TiSrPoint( Tile * hintTile, Plane * plane, int x, int y); Tile* TiInsertTile(Plane *, TileRect * rect, QGraphicsItem * body, Tile::TileType type); #define TiBottom(tileP) (YMIN(tileP)) #define TiLeft(tileP) (LEFT(tileP)) #define TiTop(tileP) (YMAX(tileP)) #define TiRight(tileP) (RIGHT(tileP)) inline Tile::TileType TiGetType(Tile * tileP) { return tileP->ti_type; } inline void TiSetType(Tile *tileP, Tile::TileType t) { tileP->ti_type = t; } inline QGraphicsItem * TiGetBody(Tile * tileP) { return tileP->ti_body; } /* See diagnostic subroutine version in tile.c */ inline void TiSetBody(Tile *tileP, QGraphicsItem *b) { tileP->ti_body = b; } inline QGraphicsItem * TiGetClient(Tile * tileP) { return tileP->ti_client ; } inline void TiSetClient(Tile *tileP, QGraphicsItem * b) { tileP->ti_client = b; } Tile *TiAlloc(); void TiFree(Tile *); /* #define EnclosePoint(tile,point) ((LEFT(tile) <= (point)->p_x ) && \ ((point)->p_x < RIGHT(tile)) && \ (YMIN(tile) <= (point)->p_y ) && \ ((point)->p_y < YMAX(tile) )) #define EnclosePoint4Sides(tile,point) ((LEFT(tile) <= (point)->p_x ) && \ ((point)->p_x <= RIGHT(tile)) && \ (YMIN(tile) <= (point)->p_y ) && \ ((point)->p_y <= YMAX(tile) )) */ /* The four macros below are for finding next tile RIGHT, UP, LEFT or DOWN * from current tile at a given coordinate value. * * For example, NEXT_TILE_RIGHT points tResult to tile to right of t * at y-coordinate y. */ #define NEXT_TILE_RIGHT(tResult, t, y) \ for ((tResult) = TR(t); YMIN(tResult) > (y); (tResult) = LB(tResult)) \ /* Nothing */; #define NEXT_TILE_UP(tResult, t, x) \ for ((tResult) = RT(t); LEFT(tResult) > (x); (tResult) = BL(tResult)) \ /* Nothing */; #define NEXT_TILE_LEFT(tResult, t, y) \ for ((tResult) = BL(t); YMAX(tResult) <= (y); (tResult) = RT(tResult)) \ /* Nothing */; #define NEXT_TILE_DOWN(tResult, t, x) \ for ((tResult) = LB(t); RIGHT(tResult) <= (x); (tResult) = TR(tResult)) \ /* Nothing */; //#define TiSrPointNoHint(plane, point) (TiSrPoint((Tile *) NULL, plane, point)) Tile * gotoPoint(Tile * tile, TilePoint p); #endif /* _TILES_H */ fritzing-app-0.9.2b/src/autoroute/cmrouter/tileutils.h000066400000000000000000000055301250202676700231550ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 2979 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef TILEUTILS #define TILEUTILS #include "tile.h" static const int TILEFACTOR = 1000; inline int fasterRealToTile(double x) { return qRound(x * TILEFACTOR); } inline void realsToTile(TileRect & tileRect, double l, double t, double r, double b) { tileRect.xmini = fasterRealToTile(l); tileRect.ymini = fasterRealToTile(t); tileRect.xmaxi = fasterRealToTile(r); tileRect.ymaxi = fasterRealToTile(b); } inline void qrectToTile(QRectF & rect, TileRect & tileRect) { realsToTile(tileRect, rect.left(), rect.top(), rect.right(), rect.bottom()); } inline int realToTile(double x) { return qRound(x * TILEFACTOR); } inline double tileToReal(int x) { return x / ((double) TILEFACTOR); } inline void tileRectToQRect(TileRect & tileRect, QRectF & rect) { rect.setCoords(tileToReal(tileRect.xmini), tileToReal(tileRect.ymini), tileToReal(tileRect.xmaxi), tileToReal(tileRect.ymaxi)); } inline void tileToQRect(Tile * tile, QRectF & rect) { TileRect tileRect; TiToRect(tile, &tileRect); tileRectToQRect(tileRect, rect); } inline void tileRotate90(TileRect & tileRect, TileRect & tileRect90) { // x' = x*cos - y*sin // y' = x*sin + y*cos // where cos90 = 0 and sin90 = 1 (effectively clockwise) // rotate top right corner of rect tileRect90.xmini = -tileRect.ymaxi; tileRect90.ymini = tileRect.xmini; // swap width and height tileRect90.xmaxi = tileRect90.xmini + (tileRect.ymaxi - tileRect.ymini); tileRect90.ymaxi = tileRect90.ymini + (tileRect.xmaxi - tileRect.xmini); } inline void tileUnrotate90(TileRect & tileRect90, TileRect & tileRect) { tileRect.xmini = tileRect90.ymini; tileRect.ymaxi = -tileRect90.xmini; // swap width and height tileRect.xmaxi = tileRect.xmini + (tileRect90.ymaxi - tileRect90.ymini); tileRect.ymini = tileRect.ymaxi - (tileRect90.xmaxi - tileRect90.xmini); } #endif fritzing-app-0.9.2b/src/autoroute/drc.cpp000066400000000000000000001222121250202676700203770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.a Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6991 $: $Author: irascibl@gmail.com $: $Date: 2013-04-26 15:24:41 +0200 (Fr, 26. Apr 2013) $ ********************************************************************/ #include "drc.h" #include "../connectors/svgidlayer.h" #include "../sketch/pcbsketchwidget.h" #include "../debugdialog.h" #include "../items/virtualwire.h" #include "../items/tracewire.h" #include "../items/via.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../connectors/connectoritem.h" #include "../items/moduleidnames.h" #include "../processeventblocker.h" #include "../fsvgrenderer.h" #include "../viewlayer.h" #include "../processeventblocker.h" #include #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////// // // // deal with invisible connectors // // if a part is already overlapping, leave it out of future checking? // // /////////////////////////////////////////// const QString DRC::AlsoNet = "alsoNet"; const QString DRC::NotNet = "notnet"; const QString DRC::Net = "net"; const uchar DRC::BitTable[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; bool pixelsCollide(QImage * image1, QImage * image2, QImage * image3, int x1, int y1, int x2, int y2, uint clr, QList & points) { bool result = false; const uchar * bits1 = image1->constScanLine(0); const uchar * bits2 = image2->constScanLine(0); int bytesPerLine = image1->bytesPerLine(); for (int y = y1; y < y2; y++) { int offset = y * bytesPerLine; for (int x = x1; x < x2; x++) { //QRgb p1 = image1->pixel(x, y); //if (p1 == 0xffffffff) continue; //QRgb p2 = image2->pixel(x, y); //if (p2 == 0xffffffff) continue; int byteOffset = (x >> 3) + offset; uchar mask = DRC::BitTable[x & 7]; if (*(bits1 + byteOffset) & mask) continue; if (*(bits2 + byteOffset) & mask) continue; image3->setPixel(x, y, clr); //DebugDialog::debug(QString("p1:%1 p2:%2").arg(p1, 0, 16).arg(p2, 0, 16)); result = true; if (points.count() < 1000) { points.append(QPointF(x, y)); } } } return result; } QStringList getNames(CollidingThing * collidingThing) { QStringList names; QList itemBases; if (collidingThing->nonConnectorItem) { itemBases << collidingThing->nonConnectorItem->attachedTo(); } foreach (ItemBase * itemBase, itemBases) { if (itemBase) { itemBase = itemBase->layerKinChief(); QString name = QObject::tr("Part %1 '%2'").arg(itemBase->title()) .arg(itemBase->instanceTitle()); names << name; } } return names; } void allGs(QDomElement & element) { element.setTagName("g"); QDomElement child = element.firstChildElement(); while (!child.isNull()) { allGs(child); child = child.nextSiblingElement(); } } /////////////////////////////////////////////// DRCResultsDialog::DRCResultsDialog(const QString & message, const QStringList & messages, const QList & collidingThings, QGraphicsPixmapItem * displayItem, QImage * displayImage, PCBSketchWidget * sketchWidget, QWidget *parent) : QDialog(parent) { setAttribute(Qt::WA_DeleteOnClose, true); m_messages = messages; m_sketchWidget = sketchWidget; m_displayItem = displayItem; if (m_displayItem) { m_displayItem->setFlags(0); } m_displayImage = displayImage; m_collidingThings = collidingThings; this->setWindowTitle(tr("DRC Results")); QVBoxLayout * vLayout = new QVBoxLayout(this); QLabel * label = new QLabel(message); label->setWordWrap(true); vLayout->addWidget(label); label = new QLabel(tr("Click on an item in the list to highlight of overlap it refers to.")); label->setWordWrap(true); vLayout->addWidget(label); label = new QLabel(tr("Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.")); label->setWordWrap(true); vLayout->addWidget(label); QListWidget *listWidget = new QListWidget(); for (int ix = 0; ix < messages.count(); ix++) { QListWidgetItem * item = new QListWidgetItem(messages.at(ix)); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); item->setData(Qt::UserRole, ix); listWidget->addItem(item); } vLayout->addWidget(listWidget); connect(listWidget, SIGNAL(itemPressed(QListWidgetItem *)), this, SLOT(pressedSlot(QListWidgetItem *))); connect(listWidget, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(releasedSlot(QListWidgetItem *))); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); connect(buttonBox, SIGNAL(accepted()), this, SLOT(close())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } DRCResultsDialog::~DRCResultsDialog() { if (m_displayItem != NULL && m_sketchWidget != NULL) { delete m_displayItem; } if (m_displayImage != NULL) { delete m_displayImage; } foreach (CollidingThing * collidingThing, m_collidingThings) { delete collidingThing; } m_collidingThings.clear(); } void DRCResultsDialog::pressedSlot(QListWidgetItem * item) { if (item == NULL) return; int ix = item->data(Qt::UserRole).toInt(); CollidingThing * collidingThing = m_collidingThings.at(ix); foreach (QPointF p, collidingThing->atPixels) { m_displayImage->setPixel(p.x(), p.y(), 2 /* 0xffffff00 */); } QPixmap pixmap = QPixmap::fromImage(*m_displayImage); m_displayItem->setPixmap(pixmap); if (collidingThing->nonConnectorItem) { m_sketchWidget->selectItem(collidingThing->nonConnectorItem->attachedTo()); } } void DRCResultsDialog::releasedSlot(QListWidgetItem * item) { if (item == NULL) return; int ix = item->data(Qt::UserRole).toInt(); CollidingThing * collidingThing = m_collidingThings.at(ix); foreach (QPointF p, collidingThing->atPixels) { m_displayImage->setPixel(p.x(), p.y(), 1 /* 0x80ff0000 */); } QPixmap pixmap = QPixmap::fromImage(*m_displayImage); m_displayItem->setPixmap(pixmap); } /////////////////////////////////////////// const QString DRC::KeepoutSettingName("DRC_Keepout"); const double DRC::KeepoutDefaultMils = 10; /////////////////////////////////////////////// static QString CancelledMessage; /////////////////////////////////////////// DRC::DRC(PCBSketchWidget * sketchWidget, ItemBase * board) { CancelledMessage = tr("DRC was cancelled."); m_cancelled = false; m_sketchWidget = sketchWidget; m_board = board; m_displayItem = NULL; m_displayImage = NULL; m_plusImage = NULL; m_minusImage = NULL; } DRC::~DRC(void) { if (m_displayItem) { delete m_displayItem; } if (m_plusImage) { delete m_plusImage; } if (m_minusImage) { delete m_minusImage; } if (m_displayImage) { delete m_displayImage; } foreach (QDomDocument * doc, m_masterDocs) { delete doc; } } QStringList DRC::start(bool showOkMessage, double keepoutMils) { QString message; QStringList messages; QList collidingThings; bool result = startAux(message, messages, collidingThings, keepoutMils); if (result) { if (messages.count() == 0) { message = tr("Your sketch is ready for production: there are no connectors or traces that overlap or are too close together."); } else { message = tr("The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. ") + tr("Reposition them and run the DRC again to find more problems"); } } #ifndef QT_NO_DEBUG m_displayImage->save(FolderUtils::getUserDataStorePath("") + "/testDRCDisplay.png"); #endif emit wantBothVisible(); emit setProgressValue(m_maxProgress); emit hideProgress(); if (messages.count() == 0) { if (showOkMessage) { QMessageBox::information(m_sketchWidget->window(), tr("Fritzing"), message); } } else { DRCResultsDialog * dialog = new DRCResultsDialog(message, messages, collidingThings, m_displayItem, m_displayImage, m_sketchWidget, m_sketchWidget->window()); if (showOkMessage) { dialog->show(); } else { dialog->exec(); } m_displayItem = NULL; m_displayImage = NULL; } return messages; } bool DRC::startAux(QString & message, QStringList & messages, QList & collidingThings, double keepoutMils) { bool bothSidesNow = m_sketchWidget->boardLayers() == 2; QList visited; QList< QList > equis; QList< QList > singletons; foreach (QGraphicsItem * item, m_sketchWidget->scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->attachedTo()->isEverVisible()) continue; if (connectorItem->attachedTo()->getRatsnest()) continue; if (visited.contains(connectorItem)) continue; QList equi; equi.append(connectorItem); ConnectorItem::collectEqualPotential(equi, bothSidesNow, (ViewGeometry::RatsnestFlag | ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag) ^ m_sketchWidget->getTraceFlag()); visited.append(equi); if (equi.count() == 1) { singletons.append(equi); continue; } ItemBase * firstPart = connectorItem->attachedTo()->layerKinChief(); bool gotTwo = false; foreach (ConnectorItem * equ, equi) { if (equ->attachedTo()->layerKinChief() != firstPart) { gotTwo = true; break; } } if (!gotTwo) { singletons.append(equi); continue; } equis.append(equi); } m_maxProgress = equis.count() + singletons.count() + 1; if (bothSidesNow) m_maxProgress *= 2; emit setMaximumProgress(m_maxProgress); int progress = 1; emit setProgressValue(progress); ProcessEventBlocker::processEvents(); double dpi = qMax((double) 250, 1000 / keepoutMils); // turns out making a variable dpi doesn't work due to vector-to-raster issues QRectF boardRect = m_board->sceneBoundingRect(); QRectF sourceRes(0, 0, boardRect.width() * dpi / GraphicsUtils::SVGDPI, boardRect.height() * dpi / GraphicsUtils::SVGDPI); QSize imgSize(qCeil(sourceRes.width()), qCeil(sourceRes.height())); m_plusImage = new QImage(imgSize, QImage::Format_Mono); m_plusImage->fill(0xffffffff); m_minusImage = new QImage(imgSize, QImage::Format_Mono); m_minusImage->fill(0); m_displayImage = new QImage(imgSize, QImage::Format_Indexed8); m_displayImage->setColor(0, 0); m_displayImage->setColor(1, 0x80ff0000); m_displayImage->setColor(2, 0xffffff00); m_displayImage->fill(0); if (!makeBoard(m_minusImage, sourceRes)) { message = tr("Fritzing error: unable to render board svg."); return false; } extendBorder(1, m_minusImage); // since the resolution = keepout, extend by 1 QList layerSpecs; layerSpecs << ViewLayer::NewBottom; if (bothSidesNow) layerSpecs << ViewLayer::NewTop; int emptyMasterCount = 0; foreach (ViewLayer::ViewLayerPlacement viewLayerPlacement, layerSpecs) { if (viewLayerPlacement == ViewLayer::NewTop) { emit wantTopVisible(); m_plusImage->fill(0xffffffff); } else emit wantBottomVisible(); LayerList viewLayerIDs = ViewLayer::copperLayers(viewLayerPlacement); viewLayerIDs.removeOne(ViewLayer::GroundPlane0); viewLayerIDs.removeOne(ViewLayer::GroundPlane1); RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = renderThing.selectedItems = renderThing.renderBlocker = false; QString master = m_sketchWidget->renderToSVG(renderThing, m_board, viewLayerIDs); if (master.isEmpty()) { if (++emptyMasterCount == layerSpecs.count()) { message = tr("No traces or connectors to check"); return false; } progress++; continue; } QDomDocument * masterDoc = new QDomDocument(); m_masterDocs.insert(viewLayerPlacement, masterDoc); QString errorStr; int errorLine; int errorColumn; if (!masterDoc->setContent(master, &errorStr, &errorLine, &errorColumn)) { message = tr("Unexpected SVG rendering failure--contact fritzing.org"); return false; } ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } QDomElement root = masterDoc->documentElement(); SvgFileSplitter::forceStrokeWidth(root, 2 * keepoutMils, "#000000", true, false); ItemBase::renderOne(masterDoc, m_plusImage, sourceRes); ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } QList atPixels; if (pixelsCollide(m_plusImage, m_minusImage, m_displayImage, 0, 0, imgSize.width(), imgSize.height(), 1 /* 0x80ff0000 */, atPixels)) { CollidingThing * collidingThing = findItemsAt(atPixels, m_board, viewLayerIDs, keepoutMils, dpi, true, NULL); QString msg = tr("Too close to a border (%1 layer)") .arg(viewLayerPlacement == ViewLayer::NewTop ? ItemBase::TranslatedPropertyNames.value("top") : ItemBase::TranslatedPropertyNames.value("bottom")) ; emit setProgressMessage(msg); messages << msg; collidingThings << collidingThing; updateDisplay(); } emit setProgressValue(progress++); ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } } // we are checking all the singletons at once // but the DRC will miss it if any of them overlap each other while (singletons.count() > 0) { QList combined; QList singleton = singletons.takeFirst(); ItemBase * chief = singleton.at(0)->attachedTo()->layerKinChief(); combined.append(singleton); for (int ix = singletons.count() - 1; ix >= 0; ix--) { QList candidate = singletons.at(ix); if (candidate.at(0)->attachedTo()->layerKinChief() == chief) { combined.append(candidate); singletons.removeAt(ix); } } equis.append(combined); } int index = 0; foreach (ViewLayer::ViewLayerPlacement viewLayerPlacement, layerSpecs) { if (viewLayerPlacement == ViewLayer::NewTop) emit wantTopVisible(); else emit wantBottomVisible(); QDomDocument * masterDoc = m_masterDocs.value(viewLayerPlacement, NULL); if (masterDoc == NULL) continue; LayerList viewLayerIDs = ViewLayer::copperLayers(viewLayerPlacement); viewLayerIDs.removeOne(ViewLayer::GroundPlane0); viewLayerIDs.removeOne(ViewLayer::GroundPlane1); foreach (QList equi, equis) { bool inLayer = false; foreach (ConnectorItem * equ, equi) { if (viewLayerIDs.contains(equ->attachedToViewLayerID())) { inLayer = true; break; } } if (!inLayer) { progress++; continue; } // we have a net; m_plusImage->fill(0xffffffff); m_minusImage->fill(0xffffffff); splitNet(masterDoc, equi, m_minusImage, m_plusImage, sourceRes, viewLayerPlacement, index++, keepoutMils); QHash rects; QList wires; foreach (ConnectorItem * equ, equi) { if (viewLayerIDs.contains(equ->attachedToViewLayerID())) { if (equ->attachedToItemType() == ModelPart::Wire) { Wire * wire = qobject_cast(equ->attachedTo()); if (!wires.contains(wire)) { wires.append(wire); // could break diagonal wires into a series of rects rects.insert(equ, wire->sceneBoundingRect()); } } else { rects.insert(equ, equ->sceneBoundingRect()); } } } ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } foreach (ConnectorItem * equ, rects.keys()) { QRectF rect = rects.value(equ).intersected(boardRect); double l = (rect.left() - boardRect.left()) * dpi / GraphicsUtils::SVGDPI; double t = (rect.top() - boardRect.top()) * dpi / GraphicsUtils::SVGDPI; double r = (rect.right() - boardRect.left()) * dpi / GraphicsUtils::SVGDPI; double b = (rect.bottom() - boardRect.top()) * dpi / GraphicsUtils::SVGDPI; //DebugDialog::debug(QString("l:%1 t:%2 r:%3 b:%4").arg(l).arg(t).arg(r).arg(b)); QList atPixels; if (pixelsCollide(m_plusImage, m_minusImage, m_displayImage, l, t, r, b, 1 /* 0x80ff0000 */, atPixels)) { #ifndef QT_NO_DEBUG m_plusImage->save(FolderUtils::getUserDataStorePath("") + QString("/collidePlus%1_%2.png").arg(viewLayerPlacement).arg(index)); m_minusImage->save(FolderUtils::getUserDataStorePath("") + QString("/collideMinus%1_%2.png").arg(viewLayerPlacement).arg(index)); #endif CollidingThing * collidingThing = findItemsAt(atPixels, m_board, viewLayerIDs, keepoutMils, dpi, false, equ); QStringList names = getNames(collidingThing); QString name0 = names.at(0); QString msg = tr("%1 is overlapping (%2 layer)") .arg(name0) .arg(viewLayerPlacement == ViewLayer::NewTop ? ItemBase::TranslatedPropertyNames.value("top") : ItemBase::TranslatedPropertyNames.value("bottom")) ; messages << msg; collidingThings << collidingThing; emit setProgressMessage(msg); updateDisplay(); } } emit setProgressValue(progress++); ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } } } checkHoles(messages, collidingThings, dpi); checkCopperBoth(messages, collidingThings, dpi); return true; } bool DRC::makeBoard(QImage * image, QRectF & sourceRes) { LayerList viewLayerIDs; viewLayerIDs << ViewLayer::Board; RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = renderThing.selectedItems = renderThing.renderBlocker = false; QString boardSvg = m_sketchWidget->renderToSVG(renderThing, m_board, viewLayerIDs); if (boardSvg.isEmpty()) { return false; } QByteArray boardByteArray; QString tempColor("#ffffff"); QStringList exceptions; exceptions << "none" << ""; if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) { return false; } QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); DebugDialog::debug("boardbounds", sourceRes); renderer.render(&painter /*, sourceRes */); painter.end(); // board should be white, borders should be black #ifndef QT_NO_DEBUG image->save(FolderUtils::getUserDataStorePath("") + "/testDRCBoard.png"); #endif return true; } void DRC::splitNet(QDomDocument * masterDoc, QList & equi, QImage * minusImage, QImage * plusImage, QRectF & sourceRes, ViewLayer::ViewLayerPlacement viewLayerPlacement, int index, double keepoutMils) { // deal with connectors on the same part, even though they are not on the same net // in other words, make sure there are no overlaps of connectors on the same part QList net; QList alsoNet; QList notNet; Markers markers; markers.outID = AlsoNet; markers.inTerminalID = markers.inSvgID = markers.inSvgAndID = markers.inNoID = Net; splitNetPrep(masterDoc, equi, markers, net, alsoNet, notNet, true); foreach (QDomElement element, notNet) element.setTagName("g"); foreach (QDomElement element, alsoNet) element.setTagName("g"); foreach (QDomElement element, net) { // want the normal size SvgFileSplitter::forceStrokeWidth(element, -2 * keepoutMils, "#000000", false, false); } ItemBase::renderOne(masterDoc, plusImage, sourceRes); foreach (QDomElement element, net) { // restore to keepout size SvgFileSplitter::forceStrokeWidth(element, 2 * keepoutMils, "#000000", false, false); } #ifndef QT_NO_DEBUG plusImage->save(FolderUtils::getUserDataStorePath("") + QString("/splitNetPlus%1_%2.png").arg(viewLayerPlacement).arg(index)); #else Q_UNUSED(viewLayerPlacement); Q_UNUSED(index); #endif // now want notnet foreach (QDomElement element, net) { element.removeAttribute("net"); element.setTagName("g"); } foreach (QDomElement element, alsoNet) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } foreach (QDomElement element, notNet) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } ItemBase::renderOne(masterDoc, minusImage, sourceRes); #ifndef QT_NO_DEBUG minusImage->save(FolderUtils::getUserDataStorePath("") + QString("/splitNetMinus%1_%2.png").arg(viewLayerPlacement).arg(index)); #endif // master doc restored to original state foreach (QDomElement element, net) { element.setTagName(element.attribute("former")); } } void DRC::splitNetPrep(QDomDocument * masterDoc, QList & equi, const Markers & markers, QList & net, QList & alsoNet, QList & notNet, bool checkIntersection) { QMultiHash partSvgIDs; QMultiHash partTerminalIDs; QHash bothIDs; QMultiHash itemBases; QSet wireIDs; foreach (ConnectorItem * equ, equi) { ItemBase * itemBase = equ->attachedTo(); if (itemBase == NULL) continue; if (itemBase->itemType() == ModelPart::Wire) { wireIDs.insert(QString::number(itemBase->id())); } if (equ->connector() == NULL) { // this shouldn't happen itemBase->debugInfo("!!!!!!!!!!!!!!!!!!!!!!!!!!!!! missing connector !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); equ->debugInfo("missing connector"); continue; } QString sid = QString::number(itemBase->id()); SvgIdLayer * svgIdLayer = equ->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); partSvgIDs.insert(sid, svgIdLayer->m_svgId); if (!svgIdLayer->m_terminalId.isEmpty()) { partTerminalIDs.insert(sid, svgIdLayer->m_terminalId); bothIDs.insert(sid + svgIdLayer->m_svgId, svgIdLayer->m_terminalId); } itemBases.insert(sid, itemBase); } QList todo; todo << masterDoc->documentElement(); bool firstTime = true; while (!todo.isEmpty()) { QDomElement element = todo.takeFirst(); //QString string; //QTextStream stream(&string); //element.save(stream, 0); QDomElement child = element.firstChildElement(); while (!child.isNull()) { todo << child; child = child.nextSiblingElement(); } if (firstTime) { // don't include the root element firstTime = false; continue; } QString partID = element.attribute("partID"); if (!partID.isEmpty()) { QStringList svgIDs = partSvgIDs.values(partID); QStringList terminalIDs = partTerminalIDs.values(partID); if (svgIDs.count() == 0) { markSubs(element, NotNet); } else if (wireIDs.contains(partID)) { markSubs(element, Net); } else { splitSubs(masterDoc, element, partID, markers, svgIDs, terminalIDs, itemBases.values(partID), bothIDs, checkIntersection); } } if (element.tagName() == "g") { element.removeAttribute("net"); continue; } element.setAttribute("former", element.tagName()); if (element.attribute("net") == Net) { net.append(element); } else if (element.attribute("net") == AlsoNet) { alsoNet.append(element); } else { // assume the element belongs to notNet notNet.append(element); } } } void DRC::markSubs(QDomElement & root, const QString & mark) { QList todo; todo << root; while (!todo.isEmpty()) { QDomElement element = todo.takeFirst(); element.setAttribute("net", mark); QDomElement child = element.firstChildElement(); while (!child.isNull()) { todo << child; child = child.nextSiblingElement(); } } } void DRC::splitSubs(QDomDocument * doc, QDomElement & root, const QString & partID, const Markers & markers, const QStringList & svgIDs, const QStringList & terminalIDs, const QList & itemBases, QHash & bothIDs, bool checkIntersection) { //QString string; //QTextStream stream(&string); //root.save(stream, 0); QStringList notSvgIDs; QStringList notTerminalIDs; if (checkIntersection && itemBases.count() > 0) { ItemBase * itemBase = itemBases.at(0); foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { SvgIdLayer * svgIdLayer = connectorItem->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); if (!svgIDs.contains(svgIdLayer->m_svgId)) { notSvgIDs.append(svgIdLayer->m_svgId); } if (!svgIdLayer->m_terminalId.isEmpty()) { if (!terminalIDs.contains(svgIdLayer->m_terminalId)) { notTerminalIDs.append(svgIdLayer->m_terminalId); } } } } // split subelements of a part into separate nets QList todo; QList netElements; todo << root; while (!todo.isEmpty()) { QDomElement element = todo.takeFirst(); QString svgID = element.attribute("id"); if (!svgID.isEmpty()) { if (svgIDs.contains(svgID)) { if (bothIDs.value(partID + svgID).isEmpty()) { // no terminal point markSubs(element, markers.inSvgID); } else { // privilege the terminal point over the pin/pad markSubs(element, markers.inSvgAndID); } netElements << element; // save these for intersection checks // all children are marked so don't add these to todo continue; } else if (notSvgIDs.contains(svgID)) { markSubs(element, markers.outID); // all children are marked so don't add these to todo continue; } else if (terminalIDs.contains(svgID)) { markSubs(element, markers.inTerminalID); continue; } else if (notTerminalIDs.contains(svgID)) { markSubs(element, markers.outID); continue; } } QDomElement child = element.firstChildElement(); while (!child.isNull()) { todo << child; child = child.nextSiblingElement(); } } QList toCheck; todo << root; while (!todo.isEmpty()) { QDomElement element = todo.takeFirst(); QString net = element.attribute("net"); if (net == AlsoNet) continue; else if (net == Net) continue; else if (net == NotNet) continue; else if (!checkIntersection) { element.setAttribute("net", markers.outID); } else if (element.tagName() != "g") { element.setAttribute("oldid", element.attribute("id")); element.setAttribute("id", QString("_____toCheck_____%1").arg(toCheck.count())); toCheck << element; } QDomElement child = element.firstChildElement(); while (!child.isNull()) { todo << child; child = child.nextSiblingElement(); } } if (toCheck.count() > 0) { // deal with elements that are effectively part of a connector, but aren't separately labeled // such as a rect which overlaps a circle QDomElement masterRoot = doc->documentElement(); QString svg = QString("\n") .arg(masterRoot.attribute("width")) .arg(masterRoot.attribute("height")) .arg(masterRoot.attribute("viewBox")); QString string; QTextStream stream(&string); root.save(stream, 0); svg += string; svg += ""; QSvgRenderer renderer; renderer.load(svg.toUtf8()); QList netRects; foreach (QDomElement element, netElements) { QString id = element.attribute("id"); QRectF r = renderer.matrixForElement(id).mapRect(renderer.boundsOnElement(id)); netRects << r; } QList checkRects; foreach (QDomElement element, toCheck) { QString id = element.attribute("id"); QRectF r = renderer.matrixForElement(id).mapRect(renderer.boundsOnElement(id)); checkRects << r; element.setAttribute("id", element.attribute("oldid")); } for (int i = 0; i < checkRects.count(); i++) { QRectF checkr = checkRects.at(i); QDomElement checkElement = toCheck.at(i); bool gotOne = false; double carea = checkr.width() * checkr.height(); foreach (QRectF netr, netRects) { QRectF sect = netr.intersected(checkr); if (sect.isEmpty()) continue; double area = sect.width() * sect.height(); double netArea = netr.width() * netr.height(); if ((area > netArea * .5) && (netArea * 2 > carea)) { markSubs(checkElement, markers.inNoID); gotOne = true; break; } } if (!gotOne) { markSubs(checkElement, markers.outID); } } } } void DRC::updateDisplay() { QPixmap pixmap = QPixmap::fromImage(*m_displayImage); if (m_displayItem == NULL) { m_displayItem = new QGraphicsPixmapItem(pixmap); m_displayItem->setPos(m_board->sceneBoundingRect().topLeft()); m_sketchWidget->scene()->addItem(m_displayItem); m_displayItem->setZValue(5000); m_displayItem->setScale(m_board->sceneBoundingRect().width() / m_displayImage->width()); // GraphicsUtils::SVGDPI / dpi m_displayItem->setVisible(true); } else { m_displayItem->setPixmap(pixmap); } ProcessEventBlocker::processEvents(); } void DRC::cancel() { m_cancelled = true; } CollidingThing * DRC::findItemsAt(QList & atPixels, ItemBase * board, const LayerList & viewLayerIDs, double keepoutMils, double dpi, bool skipHoles, ConnectorItem * already) { Q_UNUSED(board); Q_UNUSED(viewLayerIDs); Q_UNUSED(keepoutMils); Q_UNUSED(dpi); Q_UNUSED(skipHoles); CollidingThing * collidingThing = new CollidingThing; collidingThing->nonConnectorItem = already; collidingThing->atPixels = atPixels; return collidingThing; } void DRC::extendBorder(double keepout, QImage * image) { // TODO: scanlines // keepout in terms of the board grid size QImage copy = image->copy(); int h = image->height(); int w = image->width(); int ikeepout = qCeil(keepout); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if (copy.pixel(x, y) != 0xff000000) { continue; } for (int dy = y - ikeepout; dy <= y + ikeepout; dy++) { if (dy < 0) continue; if (dy >= h) continue; for (int dx = x - ikeepout; dx <= x + ikeepout; dx++) { if (dx < 0) continue; if (dx >= w) continue; // extend border by keepout image->setPixel(dx, dy, 0); } } } } } void DRC::checkHoles(QStringList & messages, QList & collidingThings, double dpi) { QRectF boardRect = m_board->sceneBoundingRect(); foreach (QGraphicsItem * item, m_sketchWidget->scene()->collidingItems(m_board)) { NonConnectorItem * nci = dynamic_cast(item); if (nci == NULL) continue; QRectF ncibr = nci->sceneBoundingRect(); if (boardRect.contains(ncibr)) continue; if (nci->attachedToItemType() == ModelPart::Wire) continue; if (nci->attachedToItemType() == ModelPart::CopperFill) continue; // TODO: skip pad part, logo item, smds QRectF ir = boardRect.intersected(ncibr); int x = qFloor((ir.left() - boardRect.left()) * dpi / GraphicsUtils::SVGDPI); if (x < 0) x = 0; int y = qFloor((ir.top() - boardRect.top()) * dpi / GraphicsUtils::SVGDPI); if (y < 0) y = 0; int w = qCeil(ir.width() * dpi / GraphicsUtils::SVGDPI); if (x + w > m_displayImage->width()) w = m_displayImage->width() - x; int h = qCeil(ir.height() * dpi / GraphicsUtils::SVGDPI); if (y + h > m_displayImage->height()) h = m_displayImage->height() - y; CollidingThing * collidingThing = new CollidingThing; collidingThing->nonConnectorItem = nci; for (int iy = 0; iy < h; iy++) { for (int ix = 0; ix < w; ix++) { QPoint p(ix + x, iy + y); m_displayImage->setPixel(p, 1); collidingThing->atPixels << p; } } QStringList names = getNames(collidingThing); QString name0 = names.at(0); QString msg = tr("A hole in %1 may lie outside the border of the board and would be clipped.") .arg(name0) ; messages << msg; collidingThings << collidingThing; emit setProgressMessage(msg); updateDisplay(); } } void DRC::checkCopperBoth(QStringList & messages, QList & collidingThings, double dpi) { QRectF boardRect = m_board->sceneBoundingRect(); QList visited; foreach (QGraphicsItem * item, m_sketchWidget->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isEverVisible()) continue; if (itemBase->modelPart()->isCore()) continue; itemBase = itemBase->layerKinChief(); if (visited.contains(itemBase)) continue; visited << itemBase; QRectF ibr = item->sceneBoundingRect(); if (!boardRect.intersects(ibr)) continue; QString fzpPath = itemBase->modelPart()->path(); QFile file(fzpPath); if (!file.open(QFile::ReadOnly)) { DebugDialog::debug(QString("unable to open %1").arg(fzpPath)); continue; } QString fzp = file.readAll(); file.close(); bool copper0 = fzp.contains("copper0"); bool copper1 = fzp.contains("copper1"); if (!copper1 && !copper0) continue; QString svgPath = itemBase->fsvgRenderer()->filename(); QFile file2(svgPath); if (!file2.open(QFile::ReadOnly)) { DebugDialog::debug(QString("itembase svg file open failure %1").arg(itemBase->id())); continue; } QString svg = file2.readAll(); file2.close(); QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("itembase svg xml failure %1 %2 %3 %4").arg(itemBase->id()).arg(errorStr).arg(errorLine).arg(errorColumn)); continue; } QSet missing; QDomElement root = doc.documentElement(); if (copper1) { foreach(ConnectorItem * ci, missingCopper("copper1", ViewLayer::Copper1, itemBase, root)) { missing << ci; } } if (copper0) { foreach (ConnectorItem * ci, missingCopper("copper0", ViewLayer::Copper0, itemBase, root)) { missing << ci; } } foreach (ConnectorItem * ci, missing) { QRectF ir = boardRect.intersected(ci->sceneBoundingRect()); int x = qFloor((ir.left() - boardRect.left()) * dpi / GraphicsUtils::SVGDPI); if (x < 0) x = 0; int y = qFloor((ir.top() - boardRect.top()) * dpi / GraphicsUtils::SVGDPI); if (y < 0) y = 0; int w = qCeil(ir.width() * dpi / GraphicsUtils::SVGDPI); if (x + w > m_displayImage->width()) w = m_displayImage->width() - x; int h = qCeil(ir.height() * dpi / GraphicsUtils::SVGDPI); if (y + h > m_displayImage->height()) h = m_displayImage->height() - y; CollidingThing * collidingThing = new CollidingThing; collidingThing->nonConnectorItem = ci; for (int iy = 0; iy < h; iy++) { for (int ix = 0; ix < w; ix++) { QPoint p(ix + x, iy + y); m_displayImage->setPixel(p, 1); collidingThing->atPixels << p; } } QStringList names = getNames(collidingThing); QString name0 = names.at(0); QString msg = tr("Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer.") .arg(ci->connectorSharedName()) .arg(name0) ; messages << msg; collidingThings << collidingThing; emit setProgressMessage(msg); updateDisplay(); } } } QList DRC::missingCopper(const QString & layerName, ViewLayer::ViewLayerID viewLayerID, ItemBase * itemBase, const QDomElement & root) { QDomElement copperElement = TextUtils::findElementWithAttribute(root, "id", layerName); QList missing; foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { SvgIdLayer * svgIdLayer = connectorItem->connector()->fullPinInfo(itemBase->viewID(), viewLayerID); if (svgIdLayer == NULL) { DebugDialog::debug(QString("missing pin info for %1").arg(itemBase->id())); missing << connectorItem; continue; } QDomElement element = TextUtils::findElementWithAttribute(copperElement, "id", svgIdLayer->m_svgId); if (element.isNull()) { missing << connectorItem; } } return missing; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/drc.h�������������������������������������������������������������0000664�0000000�0000000�00000011246�12502026767�0020050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef DRC_H #define DRC_H #include #include #include #include #include #include #include #include #include #include #include "../svg/svgfilesplitter.h" #include "../viewlayer.h" struct CollidingThing { QPointer nonConnectorItem; QList atPixels; }; struct Markers { QString inSvgID; QString inSvgAndID; QString inTerminalID; QString inNoID; QString outID; }; class DRC : public QObject { Q_OBJECT public: DRC(class PCBSketchWidget *, class ItemBase * board); virtual ~DRC(void); QStringList start(bool showOkMessage, double keepoutMils); public: static void splitNetPrep(QDomDocument * masterDoc, QList & equi, const Markers &, QList & net, QList & alsoNet, QList & notNet, bool checkIntersection); static void extendBorder(double keepoutImagePixels, QImage * image); public slots: void cancel(); signals: void hideProgress(); void setMaximumProgress(int); void setProgressValue(int); void wantTopVisible(); void wantBottomVisible(); void wantBothVisible(); void setProgressMessage(const QString &); public: static const QString NotNet; static const QString AlsoNet; static const QString Net; static const uchar BitTable[]; static const QString KeepoutSettingName; static const double KeepoutDefaultMils; protected: bool makeBoard(QImage *, QRectF & sourceRes); void splitNet(QDomDocument *, QList & , QImage * minusImage, QImage * plusImage, QRectF & sourceRes, ViewLayer::ViewLayerPlacement viewLayerPlacement, int index, double keepoutMils); void updateDisplay(); bool startAux(QString & message, QStringList & messages, QList &, double keepoutMils); CollidingThing * findItemsAt(QList &, ItemBase * board, const LayerList & viewLayerIDs, double keepout, double dpi, bool skipHoles, ConnectorItem * already); void checkHoles(QStringList & messages, QList & collidingThings, double dpi); void checkCopperBoth(QStringList & messages, QList & collidingThings, double dpi); QList missingCopper(const QString & layerName, ViewLayer::ViewLayerID, ItemBase *, const QDomElement & svgRoot); protected: static void markSubs(QDomElement & root, const QString & mark); static void splitSubs(QDomDocument *, QDomElement & root, const QString & partID, const Markers &, const QStringList & svgIDs, const QStringList & terminalIDs, const QList &, QHash & both, bool checkIntersection); protected: class PCBSketchWidget * m_sketchWidget; class ItemBase * m_board; double m_keepout; QImage * m_plusImage; QImage * m_minusImage; QImage * m_displayImage; QGraphicsPixmapItem * m_displayItem; QHash m_masterDocs; bool m_cancelled; int m_maxProgress; }; class DRCResultsDialog : public QDialog { Q_OBJECT public: DRCResultsDialog(const QString & message, const QStringList & messages, const QList &, QGraphicsPixmapItem * displayItem, QImage * displayImage, class PCBSketchWidget * sketchWidget, QWidget *parent = 0); ~DRCResultsDialog(); protected slots: void pressedSlot(QListWidgetItem *); void releasedSlot(QListWidgetItem *); protected: QStringList m_messages; QList m_collidingThings; QPointer m_sketchWidget; QGraphicsPixmapItem * m_displayItem; QImage * m_displayImage; }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/eventeater.cpp����������������������������������������������������0000664�0000000�0000000�00000004643�12502026767�0022000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "eventeater.h" #include "../debugdialog.h" EventEater::EventEater(QObject * parent) : QObject(parent) { } bool EventEater::eventFilter(QObject *obj, QEvent *event) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::HoverEnter: case QEvent::HoverLeave: case QEvent::WinEventAct: case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverLeave: case QEvent::GraphicsSceneHoverMove: case QEvent::GraphicsSceneMouseDoubleClick: case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMousePress: case QEvent::GraphicsSceneMouseRelease: case QEvent::NonClientAreaMouseButtonDblClick: case QEvent::NonClientAreaMouseButtonPress: case QEvent::NonClientAreaMouseButtonRelease: case QEvent::NonClientAreaMouseMove: { bool gotOne = false; foreach (QWidget * widget, m_allowedWidgets) { for (QObject * parentObj = obj; parentObj != NULL; parentObj = parentObj->parent()) { if (parentObj == widget) { gotOne = true; break; } } } if (!gotOne) { // filter out the event return true; } } break; default: break; } return QObject::eventFilter(obj, event); } void EventEater::allowEventsIn(QWidget * widget) { m_allowedWidgets.append(widget); } ���������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/eventeater.h������������������������������������������������������0000664�0000000�0000000�00000002573�12502026767�0021445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef EVENTEATER_H #define EVENTEATER_H #include #include #include #include class EventEater : public QObject { Q_OBJECT public: EventEater(QObject * parent = 0); void allowEventsIn(QWidget *); protected: bool eventFilter(QObject *obj, QEvent *event); protected: QList m_allowedWidgets; }; #endif �������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/mazerouter/�������������������������������������������������������0000775�0000000�0000000�00000000000�12502026767�0021320�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/mazerouter/mazerouter.cpp�����������������������������������������0000664�0000000�0000000�00000366142�12502026767�0024235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6966 $: $Author: irascibl@gmail.com $: $Date: 2013-04-15 11:25:51 +0200 (Mo, 15. Apr 2013) $ ********************************************************************/ // with lots of suggestions from http://cc.ee.ntu.edu.tw/~ywchang/Courses/PD/unit6.pdf // and some help from http://workbench.lafayette.edu/~nestorj/cadapplets/MazeApplet/src/ // more (unused) suggestions at http://embedded.eecs.berkeley.edu/Alumni/pinhong/ee244/4-routing.PDF // TODO: // // jumper placement must be away from vias and vv // how to create test case // // test if source touches target // // add max cycles to settings dialog? // // figure out what is taking so long once the router is creating traces // change connection is calling ratsnestconnect for every pair and calls collectEqualPotential // // net reordering/rip-up-and-reroute // is there a better way than move back by one? // // raster back to vector // curve-fitting? use a bezier? http://kobus.ca/seminars/ugrad/NM5_curve_s02.pdf // // dynamic cost function based on distance to any target point? // // allow multiple routes to reach GridTarget--eliminate all queued GridPoints with greater cost // // what happens with expanded schematic frame? // #include "mazerouter.h" #include "../../sketch/pcbsketchwidget.h" #include "../../debugdialog.h" #include "../../items/virtualwire.h" #include "../../items/tracewire.h" #include "../../items/jumperitem.h" #include "../../items/symbolpaletteitem.h" #include "../../items/via.h" #include "../../items/resizableboard.h" #include "../../utils/graphicsutils.h" #include "../../utils/graphutils.h" #include "../../utils/textutils.h" #include "../../utils/folderutils.h" #include "../../connectors/connectoritem.h" #include "../../items/moduleidnames.h" #include "../../processeventblocker.h" #include "../../svg/groundplanegenerator.h" #include "../../svg/svgfilesplitter.h" #include "../../fsvgrenderer.h" #include "../drc.h" #include "../../connectors/svgidlayer.h" #include #include #include #include #include ////////////////////////////////////// static const int OptimizeFactor = 2; //static int routeNumber = 0; static QString CancelledMessage; static const int DefaultMaxCycles = 100; static const GridValue GridBoardObstacle = std::numeric_limits::max(); static const GridValue GridPartObstacle = GridBoardObstacle - 1; static const GridValue GridSource = GridBoardObstacle - 2; static const GridValue GridTarget = GridBoardObstacle - 3; static const GridValue GridAvoid = GridBoardObstacle - 4; static const GridValue GridTempObstacle = GridBoardObstacle - 5; static const GridValue GridSourceFlag = (GridBoardObstacle / 2) + 1; static const uint Layer1Cost = 100; static const uint CrossLayerCost = 100; static const uint ViaCost = 2000; static const uint AvoidCost = 7; static const uchar GridPointDone = 1; static const uchar GridPointStepYPlus = 2; static const uchar GridPointStepYMinus = 4; static const uchar GridPointStepXPlus = 8; static const uchar GridPointStepXMinus = 16; static const uchar GridPointStepStart = 32; static const uchar GridPointJumperLeft = 64; static const uchar GridPointJumperRight = 128; //static const uchar GridPointNorth = 2; //static const uchar GridPointEast = 4; //static const uchar GridPointSouth = 8; //static const uchar GridPointWest = 16; static const uchar JumperStart = 1; static const uchar JumperEnd = 2; static const uchar JumperLeft = 4; static const uchar JumperRight = 8; static const double MinTraceManhattanLength = 0.1; // pixels //////////////////////////////////////////////////////////////////// QPointF getStepPoint(QPointF p, uchar flags, double gridPixels) { if ((flags & GridPointStepXPlus) != 0) { p.setX(p.x() + (gridPixels / 2)); return p; } if ((flags & GridPointStepXMinus) != 0) { p.setX(p.x() - (gridPixels / 2)); return p; } if ((flags & GridPointStepYPlus) != 0) { p.setY(p.y() + (gridPixels / 2)); return p; } p.setY(p.y() - (gridPixels / 2)); return p; } uchar getStepFlag(GridPoint & gp1, GridPoint & gp2) { if (gp1.y == gp2.y) { double avg = (gp1.x + gp2.x) / 2.0; return (avg > gp1.x) ? GridPointStepXPlus : GridPointStepXMinus; } double avg = (gp1.y + gp2.y) / 2.0; return (avg > gp1.y) ? GridPointStepYPlus : GridPointStepYMinus; } QPointF getPixelCenter(GridPoint & gp, QPointF & topLeft, double gridPixels) { return QPointF((gp.x * gridPixels) + topLeft.x() + (gridPixels / 2), (gp.y * gridPixels) + topLeft.y() + (gridPixels / 2)); } uint getColor(GridValue val) { if (val == GridBoardObstacle) return 0xff000000; else if (val == GridPartObstacle) return 0xff404040; else if (val == 0) return 0; else if (val == GridSource) return 0xff00ff00; else if (val == GridTarget) return 0xffff0000; else if (val == GridAvoid) return 0xff808080; else if (val == GridTempObstacle) return 0xff00ffff; else if (val & GridSourceFlag) return 0xff60d060; else return 0xffff6060; } void fastCopy(QImage * from, QImage * to) { uchar * fromBits = from->scanLine(0); uchar * toBits = to->scanLine(0); long bytes = from->bytesPerLine() * from->height(); memcpy(toBits, fromBits, bytes); } bool atLeast(const QPointF & p1, const QPointF & p2) { return (qAbs(p1.x() - p2.x()) >= MinTraceManhattanLength) || (qAbs(p1.y() - p2.y()) >= MinTraceManhattanLength); } void printOrder(const QString & msg, QList & order) { QString string(msg); foreach (int i, order) { string += " " + QString::number(i); } DebugDialog::debug(string); } QString getPartID(const QDomElement & element) { QString partID = element.attribute("partID"); if (!partID.isEmpty()) return partID; QDomNode parent = element.parentNode(); if (parent.isNull()) return ""; return getPartID(parent.toElement()); } bool idsMatch(const QDomElement & element, QMultiHash & partIDs) { QString partID = getPartID(element); QStringList IDs = partIDs.values(partID); if (IDs.count() == 0) return false; QDomElement tempElement = element; while (tempElement.attribute("partID").isEmpty()) { QString id = tempElement.attribute("id"); if (!id.isEmpty() && IDs.contains(id)) return true; tempElement = tempElement.parentNode().toElement(); } return false; } bool byPinsWithin(Net * n1, Net * n2) { if (n1->pinsWithin < n2->pinsWithin) return true; if (n1->pinsWithin > n2->pinsWithin) return false; return n1->net->count() <= n2->net->count(); } bool byOrder(Trace & t1, Trace & t2) { return (t1.order < t2.order); } /* inline double initialCost(QPoint p1, QPoint p2) { //return qAbs(p1.x() - p2.x()) + qAbs(p1.y() - p2.y()); return qSqrt(GraphicsUtils::distanceSqd(p1, p2)); } */ inline double distanceCost(const QPoint & p1, const QPoint & p2) { return GraphicsUtils::distanceSqd(p1, p2); } inline double manhattanCost(const QPoint & p1, const QPoint & p2) { return qMax(qAbs(p1.x() - p2.x()), qAbs(p1.y() - p2.y())); } inline int gridPointInt(Grid * grid, GridPoint & gp) { return (gp.z * grid->x * grid->y) + (gp.y * grid->x) + gp.x; } bool jumperWillFit(GridPoint & gridPoint, const Grid * grid, int halfSize) { for (int z = 0; z < grid->z; z++) { for (int y = -halfSize; y <= halfSize; y++) { int py = gridPoint.y + y; if (py < 0) return false; if (py >= grid->y) return false; for (int x = -halfSize; x <= halfSize; x++) { int px = x + gridPoint.x; if (px < 0) return false; if (px >= grid->x) return false; GridValue val = grid->at(px, py, z); if (val == GridPartObstacle || val == GridBoardObstacle || val == GridSource || val == GridTarget || val == GridAvoid|| val == GridTempObstacle) return false; } } } return true; } bool schematicJumperWillFitAux(GridPoint & gridPoint, const Grid * grid, int halfSize, int xl, int xr) { int underCount = 0; for (int y = -halfSize; y <= halfSize; y++) { if (y < 0) return false; if (y >= grid->y) return false; for (int x = xl; x <= xr; x++) { if (x < 0) return false; if (x >= grid->x) return false; GridValue val = grid->at(gridPoint.x + x, gridPoint.y + y, 0); if (val == GridPartObstacle || val == GridBoardObstacle || val == GridSource || val == GridTarget || val == GridAvoid|| val == GridTempObstacle) { return false; } if (val < gridPoint.baseCost) { if (++underCount > xr - xl) return false; } } } return true; } bool schematicJumperWillFit(GridPoint & gridPoint, const Grid * grid, int halfSize) { if (schematicJumperWillFitAux(gridPoint, grid, halfSize, -(halfSize * 2), 0)) { gridPoint.flags |= GridPointJumperLeft; return true; } if (schematicJumperWillFitAux(gridPoint, grid, halfSize, 0, halfSize * 2)) { gridPoint.flags |= GridPointJumperRight; return true; } return false; } void initMarkers(Markers & markers, bool pcbType) { markers.outID = DRC::NotNet; markers.inTerminalID = pcbType ? DRC::AlsoNet : DRC::Net; markers.inSvgID = DRC::Net; markers.inSvgAndID = pcbType ? DRC::Net : DRC::AlsoNet; markers.inNoID = DRC::Net; } //////////////////////////////////////////////////////////////////// bool GridPoint::operator<(const GridPoint& other) const { // make sure lower cost is first return qCost > other.qCost; } GridPoint::GridPoint(QPoint p, int zed) { z = zed; x = p.x(); y = p.y(); flags = 0; } GridPoint::GridPoint() { flags = 0; } //////////////////////////////////////////////////////////////////// Grid::Grid(int sx, int sy, int sz) { x = sx; y = sy; z = sz; data = (GridValue *) malloc(x * y * z * sizeof(GridValue)); // calloc initializes grid to 0 } GridValue Grid::at(int sx, int sy, int sz) const { return *(data + (sz * y * x) + (sy * x) + sx); } void Grid::setAt(int sx, int sy, int sz, GridValue value) { *(data + (sz * y * x) + (sy * x) + sx) = value; } QList Grid::init(int sx, int sy, int sz, int width, int height, const QImage & image, GridValue value, bool collectPoints) { QList points; const uchar * bits1 = image.constScanLine(0); int bytesPerLine = image.bytesPerLine(); for (int iy = sy; iy < sy + height; iy++) { int offset = iy * bytesPerLine; for (int ix = sx; ix < sx + width; ix++) { int byteOffset = (ix >> 3) + offset; uchar mask = DRC::BitTable[ix & 7]; //if (routeNumber > 40) { // DebugDialog::debug(QString("image %1 %2, %3").arg(image.width()).arg(image.height()).arg(image.isNull())); // DebugDialog::debug(QString("init point %1 %2 %3").arg(ix).arg(iy).arg(sz)); // DebugDialog::debug(QString("init grid %1 %2 %3, %4").arg(x).arg(y).arg(z).arg((long) data, 0, 16)); //} if ((*(bits1 + byteOffset)) & mask) continue; //if (routeNumber > 40) DebugDialog::debug("after mask"); setAt(ix, iy, sz, value); //if (routeNumber > 40) // DebugDialog::debug("set"); if (collectPoints) { points.append(QPoint(ix, iy)); } } } return points; } QList Grid::init4(int sx, int sy, int sz, int width, int height, const QImage * image, GridValue value, bool collectPoints) { // pixels are 4 x 4 bits QList points; const uchar * bits1 = image->constScanLine(0); int bytesPerLine = image->bytesPerLine(); for (int iy = sy; iy < sy + height; iy++) { int offset = iy * bytesPerLine * 4; for (int ix = sx; ix < sx + width; ix++) { int byteOffset = (ix >> 1) + offset; uchar mask = ix & 1 ? 0x0f : 0xf0; if ((*(bits1 + byteOffset) & mask) != mask) ; else if ((*(bits1 + byteOffset + bytesPerLine) & mask) != mask) ; else if ((*(bits1 + byteOffset + bytesPerLine + bytesPerLine) & mask) != mask) ; else if ((*(bits1 + byteOffset + bytesPerLine + bytesPerLine + bytesPerLine) & mask) != mask) ; else continue; // "pixel" is all white setAt(ix, iy, sz, value); if (collectPoints) { points.append(QPoint(ix, iy)); } } } return points; } void Grid::copy(int fromIndex, int toIndex) { memcpy(((uchar *) data) + toIndex * x * y * sizeof(GridValue), ((uchar *) data) + fromIndex * x * y * sizeof(GridValue), x * y * sizeof(GridValue)); } void Grid::clear() { memset(data, 0, x * y * z * sizeof(GridValue)); } void Grid::free() { if (data) { ::free(data); data = NULL; } } //////////////////////////////////////////////////////////////////// Score::Score() { totalRoutedCount = totalViaCount = 0; anyUnrouted = false; reorderNet = -1; } void Score::setOrdering(const NetOrdering & _ordering) { reorderNet = -1; if (ordering.order.count() > 0) { bool remove = false; for (int i = 0; i < ordering.order.count(); i++) { if (!remove && (ordering.order.at(i) == _ordering.order.at(i))) continue; remove = true; int netIndex = ordering.order.at(i); traces.remove(netIndex); int c = routedCount.value(netIndex); routedCount.remove(netIndex); totalRoutedCount -= c; c = viaCount.value(netIndex); viaCount.remove(netIndex); totalViaCount -= c; } } ordering = _ordering; //printOrder("new ", ordering.order); } //////////////////////////////////////////////////////////////////// static const long IDs[] = { 1452191, 9781580, 9781600, 9781620, 9781640, 9781660, 9781680, 9781700 }; static inline bool hasID(ConnectorItem * s) { for (unsigned int i = 0; i < sizeof(IDs) / sizeof(long); i++) { if (s->attachedToID() == IDs[i]) return true; } return false; } void ConnectionThing::add(ConnectorItem * s, ConnectorItem * d) { //if (hasID(s) || hasID(d)) { // s->debugInfo("addc"); // d->debugInfo("\t"); //} sd.insert(s, d); sd.insert(d, s); } void ConnectionThing::remove(ConnectorItem * s) { //if (hasID(s)) { // s->debugInfo("remc"); //} sd.remove(s); } void ConnectionThing::remove(ConnectorItem * s, ConnectorItem * d) { //if (hasID(s) || hasID(d)) { // s->debugInfo("remc"); // d->debugInfo("\t"); //} sd.remove(s, d); sd.remove(d, s); } bool ConnectionThing::multi(ConnectorItem * s) { //if (hasID(s)) { // s->debugInfo("mulc"); //} return sd.values(s).count() > 1; } QList ConnectionThing::values(ConnectorItem * s) { //if (hasID(s)) { // s->debugInfo("valc"); //} QList result; foreach (ConnectorItem * d, sd.values(s)) { if (d == NULL) continue; if (sd.values(d).count() == 0) continue; result << d; //if (hasID(s)) d->debugInfo("\t"); } return result; } //////////////////////////////////////////////////////////////////// MazeRouter::MazeRouter(PCBSketchWidget * sketchWidget, QGraphicsItem * board, bool adjustIf) : Autorouter(sketchWidget) { m_netLabelIndex = -1; m_grid = NULL; m_displayItem[0] = m_displayItem[1] = NULL; m_boardImage = m_spareImage = m_spareImage2 = m_displayImage[0] = m_displayImage[1] = NULL; CancelledMessage = tr("Autorouter was cancelled."); QSettings settings; m_maxCycles = settings.value(MaxCyclesName, DefaultMaxCycles).toInt(); m_bothSidesNow = sketchWidget->routeBothSides(); m_pcbType = sketchWidget->autorouteTypePCB(); m_board = board; m_temporaryBoard = false; if (m_board) { m_maxRect = m_board->sceneBoundingRect(); } else { QRectF itemsBoundingRect; foreach(QGraphicsItem *item, m_sketchWidget->scene()->items()) { if (!item->isVisible()) continue; itemsBoundingRect |= item->sceneBoundingRect(); } m_maxRect = itemsBoundingRect; // itemsBoundingRect is not reliable. m_sketchWidget->scene()->itemsBoundingRect(); if (adjustIf) { m_maxRect.adjust(-m_maxRect.width() / 2, -m_maxRect.height() / 2, m_maxRect.width() / 2, m_maxRect.height() / 2); } m_board = new QGraphicsRectItem(m_maxRect); m_board->setVisible(false); m_sketchWidget->scene()->addItem(m_board); m_temporaryBoard = true; } m_standardWireWidth = m_sketchWidget->getAutorouterTraceWidth(); /* // for debugging leave the last result hanging around QList pixmapItems; foreach (QGraphicsItem * item, m_sketchWidget->scene()->items()) { QGraphicsPixmapItem * pixmapItem = dynamic_cast(item); if (pixmapItem) pixmapItems << pixmapItem; } foreach (QGraphicsPixmapItem * pixmapItem, pixmapItems) { delete pixmapItem; } */ ViewGeometry vg; vg.setWireFlags(m_sketchWidget->getTraceFlag()); ViewLayer::ViewLayerID bottom = sketchWidget->getWireViewLayerID(vg, ViewLayer::NewBottom); m_viewLayerIDs << bottom; if (m_bothSidesNow) { ViewLayer::ViewLayerID top = sketchWidget->getWireViewLayerID(vg, ViewLayer::NewTop); m_viewLayerIDs.append(top); } } MazeRouter::~MazeRouter() { foreach (QDomDocument * doc, m_masterDocs) { delete doc; } if (m_displayItem[0]) { delete m_displayItem[0]; } if (m_displayItem[1]) { delete m_displayItem[1]; } if (m_displayImage[0]) { delete m_displayImage[0]; } if (m_displayImage[1]) { delete m_displayImage[1]; } if (m_temporaryBoard && m_board != NULL) { delete m_board; } if (m_grid) { m_grid->free(); delete m_grid; } if (m_boardImage) { delete m_boardImage; } if (m_spareImage) { delete m_spareImage; } if (m_spareImage2) { delete m_spareImage2; } } void MazeRouter::start() { if (m_pcbType) { if (m_board == NULL) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Cannot autoroute: no board (or multiple boards) found")); return; } m_jumperWillFitFunction = jumperWillFit; m_costFunction = distanceCost; m_traceColors[0] = 0xa0F28A00; m_traceColors[1] = 0xa0FFCB33; } else { m_jumperWillFitFunction = schematicJumperWillFit; m_costFunction = manhattanCost; m_traceColors[0] = m_traceColors[1] = 0xa0303030; } m_keepoutPixels = m_sketchWidget->getKeepout(); // 15 mils space (in pixels) m_gridPixels = qMax(m_standardWireWidth, m_keepoutPixels); m_keepoutMils = m_keepoutPixels * GraphicsUtils::StandardFritzingDPI / GraphicsUtils::SVGDPI; m_keepoutGrid = m_keepoutPixels / m_gridPixels; m_keepoutGridInt = qCeil(m_keepoutGrid); double ringThickness, holeSize; m_sketchWidget->getViaSize(ringThickness, holeSize); int gridViaSize = qCeil((ringThickness + ringThickness + holeSize + m_keepoutPixels + m_keepoutPixels) / m_gridPixels); m_halfGridViaSize = gridViaSize / 2; QSizeF jumperSize = m_sketchWidget->jumperItemSize(); int gridJumperSize = qCeil((qMax(jumperSize.width(), jumperSize.height()) + m_keepoutPixels + m_keepoutPixels) / m_gridPixels); m_halfGridJumperSize = gridJumperSize / 2; emit setMaximumProgress(m_maxCycles); emit setProgressMessage(""); emit setCycleMessage("round 1 of:"); emit setCycleCount(m_maxCycles); m_sketchWidget->ensureTraceLayersVisible(); QHash indexer; m_sketchWidget->collectAllNets(indexer, m_allPartConnectorItems, false, m_bothSidesNow); removeOffBoardAnd(m_pcbType, true, m_bothSidesNow); if (m_allPartConnectorItems.count() == 0) { QString message = m_pcbType ? QObject::tr("No connections (on the PCB) to route.") : QObject::tr("No connections to route."); QMessageBox::information(NULL, QObject::tr("Fritzing"), message); Autorouter::cleanUpNets(); return; } QUndoCommand * parentCommand = new QUndoCommand("Autoroute"); new CleanUpWiresCommand(m_sketchWidget, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(m_sketchWidget, CleanUpWiresCommand::UndoOnly, parentCommand); initUndo(parentCommand); NetList netList; int totalToRoute = 0; for (int i = 0; i < m_allPartConnectorItems.count(); i++) { Net * net = new Net; net->net = m_allPartConnectorItems[i]; //foreach (ConnectorItem * connectorItem, *(net->net)) { // connectorItem->debugInfo("all parts"); //} QList todo; todo.append(*(net->net)); while (todo.count() > 0) { ConnectorItem * first = todo.takeFirst(); QList equi; equi.append(first); ConnectorItem::collectEqualPotential(equi, m_bothSidesNow, (ViewGeometry::RatsnestFlag | ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag) ^ m_sketchWidget->getTraceFlag()); foreach (ConnectorItem * equ, equi) { todo.removeOne(equ); //equ->debugInfo("equi"); } net->subnets.append(equi); } if (net->subnets.count() < 2) { // net is already routed continue; } net->pinsWithin = findPinsWithin(net->net); netList.nets << net; totalToRoute += net->net->count() - 1; } qSort(netList.nets.begin(), netList.nets.end(), byPinsWithin); NetOrdering initialOrdering; int ix = 0; foreach (Net * net, netList.nets) { // id is the same as the order in netList initialOrdering.order << ix; net->id = ix++; } if (m_bothSidesNow) { emit wantBothVisible(); } ProcessEventBlocker::processEvents(); // to keep the app from freezing if (m_cancelled || m_stopTracing) { restoreOriginalState(parentCommand); cleanUpNets(netList); return; } QSizeF gridSize(m_maxRect.width() / m_gridPixels, m_maxRect.height() / m_gridPixels); QSize boardImageSize(qCeil(gridSize.width()), qCeil(gridSize.height())); m_grid = new Grid(boardImageSize.width(), boardImageSize.height(), m_bothSidesNow ? 2 : 1); if (m_grid->data == NULL) { QMessageBox::information(NULL, QObject::tr("Fritzing"), "Out of memory--unable to proceed"); restoreOriginalState(parentCommand); cleanUpNets(netList); return; } m_boardImage = new QImage(boardImageSize.width() * 4, boardImageSize.height() * 4, QImage::Format_Mono); m_spareImage = new QImage(boardImageSize.width() * 4, boardImageSize.height() * 4, QImage::Format_Mono); if (m_temporaryBoard) { m_boardImage->fill(0xffffffff); } else { m_boardImage->fill(0); QRectF r4(QPointF(0, 0), gridSize * 4); makeBoard(m_boardImage, m_keepoutGrid * 4, r4); } GraphicsUtils::drawBorder(m_boardImage, 4); ProcessEventBlocker::processEvents(); // to keep the app from freezing if (m_cancelled || m_stopTracing) { restoreOriginalState(parentCommand); cleanUpNets(netList); return; } m_displayImage[0] = new QImage(boardImageSize, QImage::Format_ARGB32); m_displayImage[0]->fill(0); m_displayImage[1] = new QImage(boardImageSize, QImage::Format_ARGB32); m_displayImage[1]->fill(0); QString message; bool gotMasters = makeMasters(message); if (m_cancelled || m_stopTracing || !gotMasters) { restoreOriginalState(parentCommand); cleanUpNets(netList); return; } QList allOrderings; allOrderings << initialOrdering; Score bestScore; Score currentScore; int run = 0; for (; run < m_maxCycles && run < allOrderings.count(); run++) { QString msg= tr("best so far: %1 of %2 routed").arg(bestScore.totalRoutedCount).arg(totalToRoute); if (m_pcbType) { msg += tr(" with %n vias", "", bestScore.totalViaCount); } emit setProgressMessage(msg); emit setCycleMessage(tr("round %1 of:").arg(run + 1)); emit setProgressValue(run); ProcessEventBlocker::processEvents(); currentScore.setOrdering(allOrderings.at(run)); currentScore.anyUnrouted = false; routeNets(netList, false, currentScore, gridSize, allOrderings); if (bestScore.ordering.order.count() == 0) { bestScore = currentScore; } else { if (currentScore.totalRoutedCount > bestScore.totalRoutedCount) { bestScore = currentScore; } else if (currentScore.totalRoutedCount == bestScore.totalRoutedCount && currentScore.totalViaCount < bestScore.totalViaCount) { bestScore = currentScore; } } if (m_cancelled || bestScore.anyUnrouted == false || m_stopTracing) break; } emit disableButtons(); //DebugDialog::debug("done running"); if (m_cancelled) { doCancel(parentCommand); return; } if (m_stopTracing) { QString msg = tr("Routing stopped!"); msg += " "; if (m_useBest) msg += tr("Use best so far..."); emit setProgressMessage(msg); if (m_useBest) { routeNets(netList, true, bestScore, gridSize, allOrderings); } } else if (!bestScore.anyUnrouted) { emit setProgressMessage(tr("Routing complete!")); emit setProgressValue(m_maxCycles); } else { emit setCycleMessage(tr("round %1 of:").arg(run)); QString msg; if (run < m_maxCycles) msg = tr("Routing unsuccessful; stopping at round %1.").arg(run); else msg = tr("Routing reached maximum round %1.").arg(m_maxCycles); msg += " "; msg += tr("Use best so far..."); emit setProgressMessage(msg); printOrder("best ", bestScore.ordering.order); routeNets(netList, true, bestScore, gridSize, allOrderings); emit setProgressValue(m_maxCycles); } ProcessEventBlocker::processEvents(); if (m_grid) { m_grid->free(); delete m_grid; m_grid = NULL; } if (m_boardImage) { delete m_boardImage; m_boardImage = NULL; } if (m_spareImage) { delete m_spareImage; m_spareImage = NULL; } m_boardImage = new QImage(m_maxRect.width() * OptimizeFactor, m_maxRect.height() * OptimizeFactor, QImage::Format_Mono); m_spareImage = new QImage(m_maxRect.width() * OptimizeFactor, m_maxRect.height() * OptimizeFactor, QImage::Format_Mono); m_spareImage2 = new QImage(m_maxRect.width() * OptimizeFactor, m_maxRect.height() * OptimizeFactor, QImage::Format_Mono); if (m_temporaryBoard) { m_boardImage->fill(0xffffffff); } else { m_boardImage->fill(0); QRectF r2(0, 0, m_boardImage->width(), m_boardImage->height()); makeBoard(m_boardImage, m_keepoutPixels * 2, r2); } GraphicsUtils::drawBorder(m_boardImage, 2); createTraces(netList, bestScore, parentCommand); cleanUpNets(netList); new CleanUpRatsnestsCommand(m_sketchWidget, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(m_sketchWidget, CleanUpWiresCommand::RedoOnly, parentCommand); m_sketchWidget->blockUI(true); m_commandCount = BaseCommand::totalChildCount(parentCommand); emit setMaximumProgress(m_commandCount); emit setProgressMessage2(tr("Preparing undo...")); if (m_displayItem[0]) { m_displayItem[0]->setVisible(false); } if (m_displayItem[1]) { m_displayItem[1]->setVisible(false); } ProcessEventBlocker::processEvents(); m_cleanupCount = 0; m_sketchWidget->pushCommand(parentCommand, this); m_sketchWidget->blockUI(false); m_sketchWidget->repaint(); DebugDialog::debug("\n\n\nautorouting complete\n\n\n"); } int MazeRouter::findPinsWithin(QList * net) { int count = 0; QRectF r; foreach (ConnectorItem * connectorItem, *net) { r |= connectorItem->sceneBoundingRect(); } foreach (QGraphicsItem * item, m_sketchWidget->scene()->items(r)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (net->contains(connectorItem)) continue; count++; } return count; } bool MazeRouter::makeBoard(QImage * boardImage, double keepoutGrid, const QRectF & renderRect) { LayerList viewLayerIDs; viewLayerIDs << ViewLayer::Board; RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString boardSvg = m_sketchWidget->renderToSVG(renderThing, m_board, viewLayerIDs); if (boardSvg.isEmpty()) { return false; } QByteArray boardByteArray; QString tempColor("#ffffff"); QStringList exceptions; exceptions << "none" << ""; if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) { return false; } QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(boardImage); painter.setRenderHint(QPainter::Antialiasing, false); renderer.render(&painter, renderRect); painter.end(); // board should be white, borders should be black #ifndef QT_NO_DEBUG //boardImage->save(FolderUtils::getUserDataStorePath("") + "/mazeMakeBoard.png"); #endif // extend it given that the board image is * 4 DRC::extendBorder(keepoutGrid, boardImage); #ifndef QT_NO_DEBUG //boardImage->save(FolderUtils::getUserDataStorePath("") + "/mazeMakeBoard2.png"); #endif return true; } bool MazeRouter::makeMasters(QString & message) { QList layerSpecs; layerSpecs << ViewLayer::NewBottom; if (m_bothSidesNow) layerSpecs << ViewLayer::NewTop; foreach (ViewLayer::ViewLayerPlacement viewLayerPlacement, layerSpecs) { LayerList viewLayerIDs = m_sketchWidget->routingLayers(viewLayerPlacement); RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = renderThing.selectedItems = renderThing.renderBlocker = false; QString master = m_sketchWidget->renderToSVG(renderThing, m_board, viewLayerIDs); if (master.isEmpty()) { continue; } QDomDocument * masterDoc = new QDomDocument(); m_masterDocs.insert(viewLayerPlacement, masterDoc); QString errorStr; int errorLine; int errorColumn; if (!masterDoc->setContent(master, &errorStr, &errorLine, &errorColumn)) { message = tr("Unexpected SVG rendering failure--contact fritzing.org"); return false; } ProcessEventBlocker::processEvents(); if (m_cancelled) { message = CancelledMessage; return false; } QDomElement root = masterDoc->documentElement(); SvgFileSplitter::forceStrokeWidth(root, 2 * m_keepoutMils, "#000000", true, true); //QString forDebugging = masterDoc->toByteArray(); //DebugDialog::debug("master " + forDebugging); } return true; } bool MazeRouter::routeNets(NetList & netList, bool makeJumper, Score & currentScore, const QSizeF gridSize, QList & allOrderings) { RouteThing routeThing; routeThing.netElements[0] = NetElements(); routeThing.netElements[1] = NetElements(); routeThing.r = QRectF(QPointF(0, 0), gridSize); routeThing.r4 = QRectF(QPointF(0, 0), gridSize * 4); routeThing.layerSpecs << ViewLayer::NewBottom; if (m_bothSidesNow) routeThing.layerSpecs << ViewLayer::NewTop; bool result = true; initTraceDisplay(); bool previousTraces = false; foreach (int netIndex, currentScore.ordering.order) { if (m_cancelled || m_stopTracing) { return false; } Net * net = netList.nets.at(netIndex); /* DebugDialog::debug(QString("routing net %1, subnets %2, traces %3, routed %4") .arg(netIndex) .arg(net->subnets.count()) .arg(currentScore.traces.values(netIndex).count()) .arg(currentScore.routedCount.value(netIndex)) ); */ if (currentScore.routedCount.value(netIndex) == net->subnets.count() - 1) { // this net was fully routed in a previous run foreach (Trace trace, currentScore.traces.values(netIndex)) { displayTrace(trace); } previousTraces = true; continue; } if (previousTraces) { updateDisplay(0); if (m_bothSidesNow) updateDisplay(1); } if (currentScore.routedCount.value(netIndex) > 0) { // should only be here when makeJumpers = true // remove the set of routed traces for this net--the net was not completely routed // we didn't get all the way through before currentScore.totalRoutedCount -= currentScore.routedCount.value(netIndex); currentScore.routedCount.insert(netIndex, 0); currentScore.totalViaCount -= currentScore.viaCount.value(netIndex); currentScore.viaCount.insert(netIndex, 0); currentScore.traces.remove(netIndex); } //foreach (ConnectorItem * connectorItem, *(net->net)) { // if (connectorItem->attachedTo()->layerKinChief()->id() == 12407630) { // connectorItem->debugInfo("what"); // break; // } //} QList< QList > subnets; foreach (QList subnet, net->subnets) { QList copy(subnet); subnets.append(copy); } //DebugDialog::debug("find nearest pair"); findNearestPair(subnets, routeThing.nearest); QPointF ip = routeThing.nearest.ic->sceneAdjustedTerminalPoint(NULL) - m_maxRect.topLeft(); routeThing.gridSourcePoint = QPoint(ip.x() / m_gridPixels, ip.y() / m_gridPixels); QPointF jp = routeThing.nearest.jc->sceneAdjustedTerminalPoint(NULL) - m_maxRect.topLeft(); routeThing.gridTargetPoint = QPoint(jp.x() / m_gridPixels, jp.y() / m_gridPixels); m_grid->clear(); m_grid->init4(0, 0, 0, m_grid->x, m_grid->y, m_boardImage, GridBoardObstacle, false); if (m_bothSidesNow) { m_grid->copy(0, 1); } QList traces = currentScore.traces.values(); if (m_pcbType) { traceObstacles(traces, netIndex, m_grid, m_keepoutGridInt); } else { traceAvoids(traces, netIndex, routeThing); } foreach (ViewLayer::ViewLayerPlacement viewLayerPlacement, routeThing.layerSpecs) { int z = viewLayerPlacement == ViewLayer::NewBottom ? 0 : 1; QDomDocument * masterDoc = m_masterDocs.value(viewLayerPlacement); //QString before = masterDoc->toString(); Markers markers; initMarkers(markers, m_pcbType); DRC::splitNetPrep(masterDoc, *(net->net), markers, routeThing.netElements[z].net, routeThing.netElements[z].alsoNet, routeThing.netElements[z].notNet, true); foreach (QDomElement element, routeThing.netElements[z].net) { element.setTagName("g"); } foreach (QDomElement element, routeThing.netElements[z].alsoNet) { element.setTagName("g"); } //QString after = masterDoc->toString(); //DebugDialog::debug("obstacles from board"); m_spareImage->fill(0xffffffff); ItemBase::renderOne(masterDoc, m_spareImage, routeThing.r4); #ifndef QT_NO_DEBUG //m_spareImage->save(FolderUtils::getUserDataStorePath("") + QString("/obstacles%1_%2.png").arg(netIndex, 2, 10, QChar('0')).arg(viewLayerPlacement)); #endif m_grid->init4(0, 0, z, m_grid->x, m_grid->y, m_spareImage, GridPartObstacle, false); //DebugDialog::debug("obstacles from board done"); prepSourceAndTarget(masterDoc, routeThing, subnets, z, viewLayerPlacement); } //updateDisplay(m_grid, 0); //if (m_bothSidesNow) updateDisplay(m_grid, 1); //DebugDialog::debug(QString("before route one %1").arg(netIndex)); routeThing.unrouted = false; if (!routeOne(makeJumper, currentScore, netIndex, routeThing, allOrderings)) { result = false; } //DebugDialog::debug(QString("after route one %1 %2").arg(netIndex).arg(result)); while (result && subnets.count() > 2) { /* DebugDialog::debug(QString("\nnearest %1 %2").arg(routeThing.nearest.i).arg(routeThing.nearest.j)); routeThing.nearest.ic->debugInfo("\ti"); routeThing.nearest.jc->debugInfo("\tj"); int ix = 0; foreach (QList subnet, subnets) { foreach(ConnectorItem * connectorItem, subnet) { connectorItem->debugInfo(QString::number(ix)); } ix++; } */ result = routeNext(makeJumper, routeThing, subnets, currentScore, netIndex, allOrderings); } routeThing.netElements[0].net.clear(); routeThing.netElements[0].notNet.clear(); routeThing.netElements[0].alsoNet.clear(); routeThing.netElements[1].net.clear(); routeThing.netElements[1].notNet.clear(); routeThing.netElements[1].alsoNet.clear(); routeThing.sourceQ = std::priority_queue(); routeThing.targetQ = std::priority_queue(); if (result == false) break; } return result; } bool MazeRouter::routeOne(bool makeJumper, Score & currentScore, int netIndex, RouteThing & routeThing, QList & allOrderings) { //DebugDialog::debug("start route()"); Trace newTrace; int viaCount; routeThing.bestDistanceToSource = routeThing.bestDistanceToTarget = std::numeric_limits::max(); //DebugDialog::debug(QString("jumper d %1, %2").arg(routeThing.bestDistanceToSource).arg(routeThing.bestDistanceToTarget)); newTrace.gridPoints = route(routeThing, viaCount); if (m_cancelled || m_stopTracing) { return false; } //DebugDialog::debug("after route()"); if (newTrace.gridPoints.count() == 0) { if (makeJumper) { routeJumper(netIndex, routeThing, currentScore); } else { routeThing.unrouted = true; if (currentScore.reorderNet < 0) { for (int i = 0; i < currentScore.ordering.order.count(); i++) { if (currentScore.ordering.order.at(i) == netIndex) { if (moveBack(currentScore, i, allOrderings)) { currentScore.reorderNet = netIndex; } break; } } } currentScore.anyUnrouted = true; if (currentScore.reorderNet >= 0) { // rip up and reroute unless this net is already the first one on the list return false; } // unable to move the 0th net so keep going } } else { insertTrace(newTrace, netIndex, currentScore, viaCount, true); updateDisplay(0); if (m_bothSidesNow) updateDisplay(1); } //DebugDialog::debug("end routeOne()"); return true; } bool MazeRouter::routeNext(bool makeJumper, RouteThing & routeThing, QList< QList > & subnets, Score & currentScore, int netIndex, QList & allOrderings) { bool result = true; QList combined; if (routeThing.unrouted) { if (routeThing.nearest.i < routeThing.nearest.j) { subnets.removeAt(routeThing.nearest.j); combined = subnets.takeAt(routeThing.nearest.i); } else { combined = subnets.takeAt(routeThing.nearest.i); subnets.removeAt(routeThing.nearest.j); } } else { combined.append(subnets.at(routeThing.nearest.i)); combined.append(subnets.at(routeThing.nearest.j)); if (routeThing.nearest.i < routeThing.nearest.j) { subnets.removeAt(routeThing.nearest.j); subnets.removeAt(routeThing.nearest.i); } else { subnets.removeAt(routeThing.nearest.i); subnets.removeAt(routeThing.nearest.j); } } subnets.prepend(combined); routeThing.nearest.i = 0; routeThing.nearest.j = -1; routeThing.nearest.distance = std::numeric_limits::max(); findNearestPair(subnets, 0, combined, routeThing.nearest); QPointF ip = routeThing.nearest.ic->sceneAdjustedTerminalPoint(NULL) - m_maxRect.topLeft(); routeThing.gridSourcePoint = QPoint(ip.x() / m_gridPixels, ip.y() / m_gridPixels); QPointF jp = routeThing.nearest.jc->sceneAdjustedTerminalPoint(NULL) - m_maxRect.topLeft(); routeThing.gridTargetPoint = QPoint(jp.x() / m_gridPixels, jp.y() / m_gridPixels); routeThing.sourceQ = std::priority_queue(); routeThing.targetQ = std::priority_queue(); if (!m_pcbType) { QList traces = currentScore.traces.values(); traceAvoids(traces, netIndex, routeThing); } foreach (ViewLayer::ViewLayerPlacement viewLayerPlacement, routeThing.layerSpecs) { int z = viewLayerPlacement == ViewLayer::NewBottom ? 0 : 1; QDomDocument * masterDoc = m_masterDocs.value(viewLayerPlacement); prepSourceAndTarget(masterDoc, routeThing, subnets, z, viewLayerPlacement); } // redraw traces from this net foreach (Trace trace, currentScore.traces.values(netIndex)) { foreach (GridPoint gridPoint, trace.gridPoints) { m_grid->setAt(gridPoint.x, gridPoint.y, gridPoint.z, GridSource); gridPoint.qCost = gridPoint.baseCost = /* initialCost(QPoint(gridPoint.x, gridPoint.y), routeThing.gridTarget) + */ 0; gridPoint.flags = 0; //DebugDialog::debug(QString("pushing trace %1 %2 %3, %4, %5").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(gridPoint.qCost).arg(routeThing.pq.size())); routeThing.sourceQ.push(gridPoint); } } //updateDisplay(m_grid, 0); //if (m_bothSidesNow) updateDisplay(m_grid, 1); routeThing.unrouted = false; result = routeOne(makeJumper, currentScore, netIndex, routeThing, allOrderings); return result; } bool MazeRouter::moveBack(Score & currentScore, int index, QList & allOrderings) { if (index == 0) { return false; // nowhere to move back to } QList order(currentScore.ordering.order); //printOrder("start", order); int netIndex = order.takeAt(index); //printOrder("minus", order); for (int i = index - 1; i >= 0; i--) { bool done = true; order.insert(i, netIndex); //printOrder("plus ", order); foreach (NetOrdering ordering, allOrderings) { bool gotOne = true; for (int j = 0; j < order.count(); j++) { if (order.at(j) != ordering.order.at(j)) { gotOne = false; break; } } if (gotOne) { done = false; break; } } if (done == true) { NetOrdering newOrdering; newOrdering.order = order; allOrderings.append(newOrdering); //printOrder("done ", newOrdering.order); /* const static int watch[] = { 0, 1, 2, 3, 6, 12, 14, 4, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 }; // {0, 1, 2, 4, 3, 12, 6, 14, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64}; bool matches = true; for (int i = 0; i < order.count(); i++) { if (order.at(i) != watch[i]) { matches = false; break; } } if (matches) { DebugDialog::debug("order matches"); } */ return true; } order.removeAt(i); } return false; } void MazeRouter::prepSourceAndTarget(QDomDocument * masterDoc, RouteThing & routeThing, QList< QList > & subnets, int z, ViewLayer::ViewLayerPlacement viewLayerPlacement) { foreach (QDomElement element, routeThing.netElements[z].notNet) { element.setTagName("g"); } foreach (QDomElement element, routeThing.netElements[z].alsoNet) { element.setTagName("g"); } //QString debug = masterDoc->toString(4); foreach (QDomElement element, routeThing.netElements[z].net) { // QString str; // QTextStream stream(&str); // element.save(stream, 0); // DebugDialog::debug(str); SvgFileSplitter::forceStrokeWidth(element, -2 * m_keepoutMils, "#000000", false, false); } QList li = subnets.at(routeThing.nearest.i); QList sourcePoints = renderSource(masterDoc, z, viewLayerPlacement, m_grid, routeThing.netElements[z].net, li, GridSource, true, routeThing.r4); foreach (QPoint p, sourcePoints) { GridPoint gridPoint(p, z); gridPoint.qCost = gridPoint.baseCost = /* initialCost(p, routeThing.gridTarget) + */ 0; //DebugDialog::debug(QString("pushing source %1 %2 %3, %4, %5").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(gridPoint.qCost).arg(routeThing.pq.size())); routeThing.sourceQ.push(gridPoint); } QList lj = subnets.at(routeThing.nearest.j); QList targetPoints = renderSource(masterDoc, z, viewLayerPlacement, m_grid, routeThing.netElements[z].net, lj, GridTarget, true, routeThing.r4); foreach (QPoint p, targetPoints) { GridPoint gridPoint(p, z); gridPoint.qCost = gridPoint.baseCost = /* initialCost(p, routeThing.gridTarget) + */ 0; //DebugDialog::debug(QString("pushing source %1 %2 %3, %4, %5").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(gridPoint.qCost).arg(routeThing.pq.size())); routeThing.targetQ.push(gridPoint); } foreach (QDomElement element, routeThing.netElements[z].net) { SvgFileSplitter::forceStrokeWidth(element, 2 * m_keepoutMils, "#000000", false, false); } // restore masterdoc foreach (QDomElement element, routeThing.netElements[z].net) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } foreach (QDomElement element, routeThing.netElements[z].notNet) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } foreach (QDomElement element, routeThing.netElements[z].alsoNet) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } } void MazeRouter::findNearestPair(QList< QList > & subnets, Nearest & nearest) { nearest.distance = std::numeric_limits::max(); nearest.i = nearest.j = -1; nearest.ic = nearest.jc = NULL; for (int i = 0; i < subnets.count() - 1; i++) { QList inet = subnets.at(i); findNearestPair(subnets, i, inet, nearest); } } void MazeRouter::findNearestPair(QList< QList > & subnets, int inetix, QList & inet, Nearest & nearest) { for (int j = inetix + 1; j < subnets.count(); j++) { QList jnet = subnets.at(j); foreach (ConnectorItem * ic, inet) { QPointF ip = ic->sceneAdjustedTerminalPoint(NULL); ConnectorItem * icc = ic->getCrossLayerConnectorItem(); foreach (ConnectorItem * jc, jnet) { ConnectorItem * jcc = jc->getCrossLayerConnectorItem(); if (jc == ic || jcc == ic) continue; QPointF jp = jc->sceneAdjustedTerminalPoint(NULL); double d = qSqrt(GraphicsUtils::distanceSqd(ip, jp)) / m_gridPixels; if (ic->attachedToViewLayerID() != jc->attachedToViewLayerID()) { if (jcc != NULL || icc != NULL) { // may not need a via d += CrossLayerCost; } else { // requires at least one via d += ViaCost; } } else { if (jcc != NULL && icc != NULL && ic->attachedToViewLayerID() == ViewLayer::Copper1) { // route on the bottom when possible d += Layer1Cost; } } if (d < nearest.distance) { nearest.distance = d; nearest.i = inetix; nearest.j = j; nearest.ic = ic; nearest.jc = jc; } } } } } QList MazeRouter::renderSource(QDomDocument * masterDoc, int z, ViewLayer::ViewLayerPlacement viewLayerPlacement, Grid * grid, QList & netElements, QList & subnet, GridValue value, bool clearElements, const QRectF & renderRect) { if (clearElements) { foreach (QDomElement element, netElements) { element.setTagName("g"); } } m_spareImage->fill(0xffffffff); QMultiHash partIDs; QMultiHash terminalIDs; QList terminalPoints; QRectF itemsBoundingRect; foreach (ConnectorItem * connectorItem, subnet) { ItemBase * itemBase = connectorItem->attachedTo(); SvgIdLayer * svgIdLayer = connectorItem->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); partIDs.insert(QString::number(itemBase->id()), svgIdLayer->m_svgId); if (!svgIdLayer->m_terminalId.isEmpty()) { terminalIDs.insert(QString::number(itemBase->id()), svgIdLayer->m_terminalId); terminalPoints << connectorItem; } itemsBoundingRect |= connectorItem->sceneBoundingRect(); } foreach (QDomElement element, netElements) { if (idsMatch(element, partIDs)) { element.setTagName(element.attribute("former")); } else if (idsMatch(element, terminalIDs)) { element.setTagName(element.attribute("former")); } } int x1 = qFloor((itemsBoundingRect.left() - m_maxRect.left()) / m_gridPixels); int y1 = qFloor((itemsBoundingRect.top() - m_maxRect.top()) / m_gridPixels); int x2 = qCeil((itemsBoundingRect.right() - m_maxRect.left()) / m_gridPixels); int y2 = qCeil((itemsBoundingRect.bottom() - m_maxRect.top()) / m_gridPixels); ItemBase::renderOne(masterDoc, m_spareImage, renderRect); #ifndef QT_NO_DEBUG //static int rsi = 0; //m_spareImage->save(FolderUtils::getUserDataStorePath("") + QString("/rendersource%1_%2.png").arg(rsi++,3,10,QChar('0')).arg(z)); #endif QList points = grid->init4(x1, y1, z, x2 - x1, y2 - y1, m_spareImage, value, true); // terminal point hack (mostly for schematic view) foreach (ConnectorItem * connectorItem, terminalPoints) { if (ViewLayer::specFromID(connectorItem->attachedTo()->viewLayerID()) != viewLayerPlacement) { continue; } QPointF p = connectorItem->sceneAdjustedTerminalPoint(NULL); QRectF r = connectorItem->attachedTo()->sceneBoundingRect().adjusted(-m_keepoutPixels, -m_keepoutPixels, m_keepoutPixels, m_keepoutPixels); QPointF closest(p.x(), r.top()); double d = qAbs(p.y() - r.top()); int dx = 0; int dy = -1; if (qAbs(p.y() - r.bottom()) < d) { d = qAbs(p.y() - r.bottom()); closest = QPointF(p.x(), r.bottom()); dy = 1; dx = 0; } if (qAbs(p.x() - r.left()) < d) { d = qAbs(p.x() - r.left()); closest = QPointF(r.left(), p.y()); dx = -1; dy = 0; } if (qAbs(p.x() - r.right()) < d) { d = qAbs(p.x() - r.right()); closest = QPointF(r.right(), p.y()); dy = 0; dx = 1; } double y1, y2, x1, x2; double yp = (p.y() - m_maxRect.top()) / m_gridPixels; double xp = (p.x() - m_maxRect.left()) / m_gridPixels; double yc = (closest.y() - m_maxRect.top()) / m_gridPixels; double xc = (closest.x() - m_maxRect.left()) / m_gridPixels; if (closest.x() == p.x()) { x1 = x2 = qRound((p.x() - m_maxRect.left()) / m_gridPixels); y1 = (yp < yc) ? qFloor(yp) : qCeil(yp); y2 = (yp < yc) ? qCeil(yc) : qFloor(yc); if (y2 < y1) { double temp = y2; y2 = y1; y1 = temp; } } else { y1 = y2 = qRound((p.y() - m_maxRect.top()) / m_gridPixels); x1 = (xp < xc) ? qFloor(xp) : qCeil(xp); x2 = (xp < xc) ? qCeil(xc) : qFloor(xc); if (x2 < x1) { double temp = x2; x2 = x1; x1 = temp; } } int xo = qRound(xc); int yo = qRound(yc); // remove obstacles we can draw through while (true) { xo += dx; yo += dy; if (grid->at(xo, yo, z) != GridAvoid) break; grid->setAt(xo, yo, z, 0); } for (int iy = y1; iy <= y2; iy++) { for (int ix = x1; ix <= x2; ix++) { GridValue val = grid->at(ix, iy, z); if (val == GridPartObstacle || val == GridAvoid) { // make an empty path up to the source point grid->setAt(ix, iy, z, 0); } } } int xr = qRound(xp); int yr = qRound(yp); if (grid->at(xr, yr, z) != GridBoardObstacle) { grid->setAt(xr, yr, z, value); points << QPoint(xr, yr); } } return points; } QList MazeRouter::route(RouteThing & routeThing, int & viaCount) { //DebugDialog::debug(QString("start route() %1").arg(routeNumber++)); viaCount = 0; GridPoint done; bool result = false; while (!routeThing.sourceQ.empty() && !routeThing.targetQ.empty()) { GridPoint gp = routeThing.sourceQ.top(); GridPoint gpt = routeThing.targetQ.top(); if (gpt.qCost < gp.qCost) { gp = gpt; routeThing.targetQ.pop(); routeThing.targetValue = GridSource; routeThing.sourceValue = GridTarget; } else { routeThing.sourceQ.pop(); routeThing.targetValue = GridTarget; routeThing.sourceValue = GridSource; } if (gp.flags & GridPointDone) { done = gp; result = true; break; } expand(gp, routeThing); if (m_cancelled || m_stopTracing) { break; } } //DebugDialog::debug(QString("routing result %1").arg(result)); QList points; if (!result) { //updateDisplay(m_grid, 0); //DebugDialog::debug(QString("done routing no points")); return points; } done.baseCost = std::numeric_limits::max(); // make sure this is the largest value for either traceback QList sourcePoints = traceBack(done, m_grid, viaCount, GridTarget, GridSource); // trace back to source QList targetPoints = traceBack(done, m_grid, viaCount, GridSource, GridTarget); // trace back to target if (sourcePoints.count() == 0 || targetPoints.count() == 0) { DebugDialog::debug("traceback zero points"); return points; } else { targetPoints.takeFirst(); // redundant point foreach (GridPoint gp, targetPoints) points.prepend(gp); points.append(sourcePoints); } clearExpansion(m_grid); //DebugDialog::debug(QString("done with route() %1").arg(points.count())); return points; } QList MazeRouter::traceBack(GridPoint gridPoint, Grid * grid, int & viaCount, GridValue sourceValue, GridValue targetValue) { //DebugDialog::debug(QString("traceback %1 %2 %3").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z)); QList points; points << gridPoint; while (true) { if (gridPoint.baseCost == targetValue) { // done break; } // can only be one neighbor with lower value GridPoint next = traceBackOne(gridPoint, grid, -1, 0, 0, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { next = traceBackOne(gridPoint, grid, 1, 0, 0, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { next = traceBackOne(gridPoint, grid, 0, -1, 0, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { next = traceBackOne(gridPoint, grid, 0, 1, 0, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { next = traceBackOne(gridPoint, grid, 0, 0, -1, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { next = traceBackOne(gridPoint, grid, 0, 0, 1, sourceValue, targetValue); if (next.baseCost == GridBoardObstacle) { // traceback failed--is this possible? points.clear(); break; } } } } } } //if (grid->at(next.x - 1, next.y, next.z) != GridObstacle) next.flags |= GridPointWest; //if (grid->at(next.x + 1, next.y, next.z) != GridObstacle) next.flags |= GridPointEast; //if (grid->at(next.x, next.y - 1, next.z) != GridObstacle) next.flags |= GridPointNorth; //if (grid->at(next.x, next.y + 1, next.z) != GridObstacle) next.flags |= GridPointSouth; points << next; if (next.z != gridPoint.z) viaCount++; gridPoint = next; } /* QString costs("costs "); foreach (GridPoint gridPoint, points) { costs += QString::number(gridPoint.baseCost) + " "; } DebugDialog::debug(costs); */ return points; } GridPoint MazeRouter::traceBackOne(GridPoint & gridPoint, Grid * grid, int dx, int dy, int dz, GridValue sourceValue, GridValue targetValue) { GridPoint next; next.baseCost = GridBoardObstacle; next.x = gridPoint.x + dx; if (next.x < 0 || next.x >= grid->x) { return next; } next.y = gridPoint.y + dy; if (next.y < 0 || next.y >= grid->y) { return next; } next.z = gridPoint.z + dz; if (next.z < 0 || next.z >= grid->z) { return next; } GridValue nextval = grid->at(next.x, next.y, next.z); if (nextval == GridBoardObstacle || nextval == GridPartObstacle || nextval == sourceValue || nextval == 0 || nextval == GridTempObstacle) return next; if (nextval == targetValue) { // done! next.baseCost = targetValue; return next; } if (targetValue == GridSource) { if ((nextval & GridSourceFlag) == 0) return next; nextval ^= GridSourceFlag; } else { if (nextval & GridSourceFlag) return next; } if (nextval < gridPoint.baseCost) { next.baseCost = nextval; } return next; } void MazeRouter::expand(GridPoint & gridPoint, RouteThing & routeThing) { //static bool debugit = false; //if (routeNumber > 41 && routeThing.pq.size() > 8200) debugit = true; //if (debugit) { // DebugDialog::debug(QString("expand %1 %2 %3, %4").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(routeThing.pq.size())); //} if (gridPoint.x > 0) expandOne(gridPoint, routeThing, -1, 0, 0, false); if (gridPoint.x < m_grid->x - 1) expandOne(gridPoint, routeThing, 1, 0, 0, false); if (gridPoint.y > 0) expandOne(gridPoint, routeThing, 0, -1, 0, false); if (gridPoint.y < m_grid->y - 1) expandOne(gridPoint, routeThing, 0, 1, 0, false); if (m_bothSidesNow) { if (gridPoint.z > 0) expandOne(gridPoint, routeThing, 0, 0, -1, true); if (gridPoint.z < m_grid->z - 1) expandOne(gridPoint, routeThing, 0, 0, 1, true); } //if (debugit) { // DebugDialog::debug("expand done"); //} } void MazeRouter::expandOne(GridPoint & gridPoint, RouteThing & routeThing, int dx, int dy, int dz, bool crossLayer) { GridPoint next; next.x = gridPoint.x + dx; next.y = gridPoint.y + dy; next.z = gridPoint.z + dz; //DebugDialog::debug(QString("expand one %1,%2,%3 cl:%4").arg(next.x).arg(next.y).arg(next.z).arg(crossLayer)); bool writeable = false; bool avoid = false; GridValue nextval = m_grid->at(next.x, next.y, next.z); if (nextval == GridPartObstacle || nextval == GridBoardObstacle || nextval == routeThing.sourceValue || nextval == GridTempObstacle) { //DebugDialog::debug("exit expand one"); return; } if (nextval == routeThing.targetValue) { //DebugDialog::debug("found grid target"); next.flags |= GridPointDone; } else if (nextval == 0) { writeable = true; } else if (nextval == GridAvoid) { bool contains = true; for (int i = 1; i <= 3; i++) { if (!routeThing.avoids.contains(((next.y - (i * dy)) * m_grid->x) + next.x - (i * dx))) { contains = false; break; } } if (contains) { // do not allow more than 3 in a row in the same direction? return; } avoid = writeable = true; if (dx == 0) { if (m_grid->at(next.x - 1, next.y, next.z) == GridAvoid) { m_grid->setAt(next.x - 1, next.y, next.z, GridTempObstacle); } if (m_grid->at(next.x + 1, next.y, next.z) == GridAvoid) { m_grid->setAt(next.x + 1, next.y, next.z, GridTempObstacle); } } else { if (m_grid->at(next.x, next.y - 1, next.z) == GridAvoid) { m_grid->setAt(next.x, next.y - 1, next.z, GridTempObstacle); } if (m_grid->at(next.x, next.y + 1, next.z) == GridAvoid) { m_grid->setAt(next.x, next.y + 1, next.z, GridTempObstacle); } } } else { // already been here: see if source and target expansions have intersected if (routeThing.sourceValue == GridSource) { if (nextval & GridSourceFlag) return; next.flags |= GridPointDone; } else { if ((nextval & GridSourceFlag) == 0) return; next.flags |= GridPointDone; } } // any way to skip viaWillFit or put it off until actually needed? if (crossLayer) { if (!viaWillFit(next, m_grid)) return; // only way to cross layers is with a via //QPointF center = getPixelCenter(next, m_maxRect.topLeft(), m_gridPixels); //DebugDialog::debug(QString("via will fit %1,%2,%3 %4,%5").arg(next.x).arg(next.y).arg(next.z).arg(center.x()).arg(center.y())); } next.baseCost = gridPoint.baseCost; if (crossLayer) { next.baseCost += ViaCost; } else if (avoid) { next.baseCost += AvoidCost; } next.baseCost++; /* int increment = 5; // assume because of obstacles around the board that we can never be off grid from (next.x, next.y) switch(grid->at(next.x - 1, next.y, next.z)) { case GridObstacle: case GridSource: case GridTarget: increment--; default: break; } switch(grid->at(next.x + 1, next.y, next.z)) { case GridObstacle: case GridSource: case GridTarget: increment--; default: break; } switch(grid->at(next.x, next.y - 1, next.z)) { case GridObstacle: case GridSource: case GridTarget: increment--; default: break; } switch(grid->at(next.x, next.y + 1, next.z)) { case GridObstacle: case GridSource: case GridTarget: increment--; default: break; } next.cost += increment; */ if (nextval == routeThing.targetValue) { next.qCost = next.baseCost; } else { double d = (m_costFunction)(QPoint(next.x, next.y), (routeThing.sourceValue == GridSource) ? routeThing.gridTargetPoint : routeThing.gridSourcePoint); next.qCost = next.baseCost + d; if (routeThing.sourceValue == GridSource) { if (d < routeThing.bestDistanceToTarget) { //DebugDialog::debug(QString("best d target %1, %2,%3").arg(d).arg(next.x).arg(next.y)); routeThing.bestDistanceToTarget = d; routeThing.bestLocationToTarget = next; } } else { if (d < routeThing.bestDistanceToSource) { //DebugDialog::debug(QString("best d source %1, %2,%3").arg(d).arg(next.x).arg(next.y)); routeThing.bestDistanceToSource = d; routeThing.bestLocationToSource = next; } } } // can think about pushing multiple points here //DebugDialog::debug(QString("pushing next %1 %2 %3, %4, %5").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(gridPoint.qCost).arg(routeThing.pq.size())); if (routeThing.sourceValue == GridSource) routeThing.sourceQ.push(next); else routeThing.targetQ.push(next); if (writeable) { GridValue flag = (routeThing.sourceValue == GridSource) ? GridSourceFlag : 0; m_grid->setAt(next.x, next.y, next.z, next.baseCost | flag); } //DebugDialog::debug("done expand one"); //if (routeThing.searchForJumper) { // updateDisplay(next); //} } bool MazeRouter::viaWillFit(GridPoint & gridPoint, Grid * grid) { for (int y = -m_halfGridViaSize; y <= m_halfGridViaSize; y++) { int py = y + gridPoint.y; if (py < 0) return false; if (py >= grid->y) return false; for (int x = -m_halfGridViaSize; x <= m_halfGridViaSize; x++) { int px = x + gridPoint.x; if (px < 0) return false; if (px >= grid->x) return false; for (int z = 0; z < grid->z; z++) { GridValue val = grid->at(px, py, z); if (val == GridPartObstacle || val == GridBoardObstacle || val == GridSource || val == GridTarget || val == GridTempObstacle || val == GridAvoid) return false; } } } return true; } void MazeRouter::updateDisplay(int iz) { QPixmap pixmap = QPixmap::fromImage(*m_displayImage[iz]); if (m_displayItem[iz] == NULL) { m_displayItem[iz] = new QGraphicsPixmapItem(pixmap); m_displayItem[iz]->setFlag(QGraphicsItem::ItemIsSelectable, false); m_displayItem[iz]->setFlag(QGraphicsItem::ItemIsMovable, false); //m_displayItem[iz]->setPos(iz == 1 ? m_maxRect.topLeft() : m_maxRect.topRight()); m_displayItem[iz]->setPos(m_maxRect.topLeft()); m_sketchWidget->scene()->addItem(m_displayItem[iz]); m_displayItem[iz]->setZValue(5000); //m_displayItem[iz]->setZValue(m_sketchWidget->viewLayers().value(iz == 0 ? ViewLayer::Copper0 : ViewLayer::Copper1)->nextZ()); m_displayItem[iz]->setScale(m_gridPixels); // m_maxRect.width() / m_displayImage[iz]->width() m_displayItem[iz]->setVisible(true); } else { m_displayItem[iz]->setPixmap(pixmap); } ProcessEventBlocker::processEvents(); } void MazeRouter::updateDisplay(Grid * grid, int iz) { m_displayImage[iz]->fill(0); for (int y = 0; y < grid->y; y++) { for (int x = 0; x < grid->x; x++) { uint color = getColor(grid->at(x, y, iz)); if (color) m_displayImage[iz]->setPixel(x, y, color); } } updateDisplay(iz); } void MazeRouter::updateDisplay(GridPoint & gridPoint) { //static int counter = 0; //if (counter++ % 2 == 0) { uint color = getColor(m_grid->at(gridPoint.x, gridPoint.y, gridPoint.z)); if (color) { m_displayImage[gridPoint.z]->setPixel(gridPoint.x, gridPoint.y, color); updateDisplay(gridPoint.z); } //} } void MazeRouter::clearExpansion(Grid * grid) { // TODO: keep a list of expansion points instead? for (int z = 0; z < grid->z; z++) { for (int y = 0; y < grid->y; y++) { for (int x = 0; x < grid->x; x++) { GridValue val = grid->at(x, y, z); if (val == 0 || val == GridPartObstacle || val == GridBoardObstacle) ; else grid->setAt(x, y, z, 0); } } } } void MazeRouter::initTraceDisplay() { m_displayImage[0]->fill(0); m_displayImage[1]->fill(0); } void MazeRouter::displayTrace(Trace & trace) { if (trace.gridPoints.count() == 0) { DebugDialog::debug("trace with no points"); return; } int lastz = trace.gridPoints.at(0).z; foreach (GridPoint gridPoint, trace.gridPoints) { if (gridPoint.z != lastz) { for (int y = -m_halfGridViaSize; y <= m_halfGridViaSize; y++) { for (int x = -m_halfGridViaSize; x <= m_halfGridViaSize; x++) { m_displayImage[1]->setPixel(x + gridPoint.x, y + gridPoint.y, 0x80ff0000); } } lastz = gridPoint.z; } else { m_displayImage[lastz]->setPixel(gridPoint.x, gridPoint.y, m_traceColors[lastz]); } } if (trace.flags) { GridPoint gridPoint = trace.gridPoints.first(); int xl, xr; if (trace.flags & JumperLeft) { xl = -(m_halfGridJumperSize * 2); xr = 0; } else if (trace.flags & JumperRight) { xl = 0; xr = m_halfGridJumperSize * 2; } else { xl = -m_halfGridJumperSize; xr = m_halfGridJumperSize; } for (int y = -m_halfGridJumperSize; y <= m_halfGridJumperSize; y++) { for (int x = xl; x <= xr; x++) { m_displayImage[0]->setPixel(x + gridPoint.x, y + gridPoint.y, 0x800000ff); } } } } void MazeRouter::traceObstacles(QList & traces, int netIndex, Grid * grid, int ikeepout) { // treat traces from previous nets as obstacles foreach (Trace trace, traces) { if (trace.netIndex == netIndex) continue; int lastZ = trace.gridPoints.at(0).z; foreach (GridPoint gridPoint, trace.gridPoints) { if (gridPoint.z != lastZ) { for (int y = -m_halfGridViaSize; y <= m_halfGridViaSize; y++) { for (int x = -m_halfGridViaSize; x <= m_halfGridViaSize; x++) { grid->setAt(gridPoint.x + x, gridPoint.y + y, 0, GridBoardObstacle); grid->setAt(gridPoint.x + x, gridPoint.y + y, 1, GridBoardObstacle); } } lastZ = gridPoint.z; } else { for (int y = -ikeepout; y <= ikeepout; y++) { for (int x = -ikeepout; x <= ikeepout; x++) { grid->setAt(gridPoint.x + x, gridPoint.y + y, gridPoint.z, GridBoardObstacle); } } } } if (trace.flags) { GridPoint gridPoint = trace.gridPoints.first(); // jumper is always centered in this case for (int y = -m_halfGridJumperSize; y <= m_halfGridJumperSize; y++) { for (int x = -m_halfGridJumperSize; x <= m_halfGridJumperSize; x++) { grid->setAt(gridPoint.x + x, gridPoint.y + y, 0, GridBoardObstacle); if (m_bothSidesNow) { grid->setAt(gridPoint.x + x, gridPoint.y + y, 1, GridBoardObstacle); } } } } } } void MazeRouter::traceAvoids(QList & traces, int netIndex, RouteThing & routeThing) { // treat traces from previous nets as semi-obstacles routeThing.avoids.clear(); foreach (Trace trace, traces) { if (trace.netIndex == netIndex) continue; foreach (GridPoint gridPoint, trace.gridPoints) { for (int y = -m_keepoutGridInt; y <= m_keepoutGridInt; y++) { for (int x = -m_keepoutGridInt; x <= m_keepoutGridInt; x++) { GridValue val = m_grid->at(gridPoint.x + x, gridPoint.y + y, 0); if (val == GridPartObstacle || val == GridBoardObstacle || val == GridSource || val == GridTarget) continue; m_grid->setAt(gridPoint.x + x, gridPoint.y + y, 0, GridAvoid); routeThing.avoids.insert(((gridPoint.y + y) * m_grid->x) + x + gridPoint.x); } } } if (trace.flags) { GridPoint gridPoint = trace.gridPoints.first(); int xl, xr; if (gridPoint.flags & GridPointJumperLeft) { xl = -(m_halfGridJumperSize * 2); xr = 0; } else { xl = 0; xr = m_halfGridJumperSize * 2; } for (int y = -m_halfGridJumperSize; y <= m_halfGridJumperSize; y++) { for (int x = xl; x <= xr; x++) { m_grid->setAt(gridPoint.x + x, gridPoint.y + y, 0, GridBoardObstacle); } } } } } void MazeRouter::cleanUpNets(NetList & netList) { foreach(Net * net, netList.nets) { delete net; } netList.nets.clear(); Autorouter::cleanUpNets(); } void MazeRouter::createTraces(NetList & netList, Score & bestScore, QUndoCommand * parentCommand) { QPointF topLeft = m_maxRect.topLeft(); QMultiHash allVias; QMultiHash allJumperItems; QMultiHash allNetLabels; QMultiHash > > allBundles; ConnectionThing connectionThing; emit setMaximumProgress(bestScore.ordering.order.count() * 2); emit setProgressMessage2(tr("Optimizing traces...")); int progress = 0; foreach (int netIndex, bestScore.ordering.order) { emit setProgressValue(progress++); //DebugDialog::debug(QString("tracing net %1").arg(netIndex)); QList traces = bestScore.traces.values(netIndex); qSort(traces.begin(), traces.end(), byOrder); TraceThing traceThing; traceThing.jumperItem = NULL; traceThing.netLabel = NULL; traceThing.topLeft = m_maxRect.topLeft(); int newTraceIndex = 0; Net * net = netList.nets.at(netIndex); for (int tix = 0; tix < traces.count(); tix++) { Trace trace = traces.at(tix); QList gridPoints = trace.gridPoints; // TODO: nicer curve-fitting removeColinear(gridPoints); removeSteps(gridPoints); if (trace.flags & JumperStart) { Trace trace2 = traces.at(tix + 1); traceThing.nextTraceStart = trace2.gridPoints.first(); } createTrace(trace, gridPoints, traceThing, connectionThing, net); QList< QPointer > bundle; if (traceThing.newTraces.count() > newTraceIndex) { ViewLayer::ViewLayerID viewLayerID = traceThing.newTraces.at(newTraceIndex)->viewLayerID(); for (; newTraceIndex < traceThing.newTraces.count(); newTraceIndex++) { TraceWire * traceWire = traceThing.newTraces.at(newTraceIndex); if (traceWire->viewLayerID() != viewLayerID) { allBundles.insert(netIndex, bundle); bundle.clear(); viewLayerID = traceWire->viewLayerID(); } bundle << traceWire; } } else { DebugDialog::debug("create trace failed"); } allBundles.insert(netIndex, bundle); } foreach (SymbolPaletteItem * netLabel, traceThing.newNetLabels) { allNetLabels.insert(netIndex, netLabel); } foreach (Via * via, traceThing.newVias) { allVias.insert(netIndex, via); } foreach (JumperItem * jumperItem, traceThing.newJumperItems) { allJumperItems.insert(netIndex, jumperItem); } } //DebugDialog::debug("before optimize"); optimizeTraces(bestScore.ordering.order, allBundles, allVias, allJumperItems, allNetLabels, netList, connectionThing); //DebugDialog::debug("after optimize"); foreach (SymbolPaletteItem * netLabel, allNetLabels) { addNetLabelToUndo(netLabel, parentCommand); } foreach (Via * via, allVias) { addViaToUndo(via, parentCommand); } foreach (JumperItem * jumperItem, allJumperItems) { addJumperToUndo(jumperItem, parentCommand); } foreach (QList< QPointer > bundle, allBundles) { foreach (TraceWire * traceWire, bundle) { addWireToUndo(traceWire, parentCommand); } } foreach (ConnectorItem * source, connectionThing.sd.uniqueKeys()) { foreach (ConnectorItem * dest, connectionThing.values(source)) { addConnectionToUndo(source, dest, parentCommand); } } QList modelParts; foreach (QList< QPointer > bundle, allBundles) { foreach (TraceWire * traceWire, bundle) { if (traceWire) { modelParts << traceWire->modelPart(); delete traceWire; } } } foreach (Via * via, allVias.values()) { via->removeLayerKin(); modelParts << via->modelPart(); delete via; } foreach (JumperItem * jumperItem, allJumperItems.values()) { jumperItem->removeLayerKin(); modelParts << jumperItem->modelPart(); delete jumperItem; } foreach (SymbolPaletteItem * netLabel, allNetLabels.values()) { modelParts << netLabel->modelPart(); delete netLabel; } foreach (ModelPart * modelPart, modelParts) { modelPart->setParent(NULL); delete modelPart; } DebugDialog::debug("create traces complete"); } void MazeRouter::createTrace(Trace & trace, QList & gridPoints, TraceThing & traceThing, ConnectionThing & connectionThing, Net * net) { //DebugDialog::debug(QString("create trace net:%1").arg(net->id)); if (trace.flags & JumperStart) { if (m_pcbType) { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; ItemBase * itemBase = m_sketchWidget->addItem(m_sketchWidget->referenceModel()->retrieveModelPart(ModuleIDNames::JumperModuleIDName), ViewLayer::NewTop, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); traceThing.jumperItem = dynamic_cast(itemBase); traceThing.jumperItem->setAutoroutable(true); m_sketchWidget->scene()->addItem(traceThing.jumperItem); QPointF c1 = getPixelCenter(trace.gridPoints.first(), traceThing.topLeft, m_gridPixels); QPointF c2 = getPixelCenter(traceThing.nextTraceStart, traceThing.topLeft, m_gridPixels); traceThing.jumperItem->resize(c1, c2); traceThing.newJumperItems << traceThing.jumperItem; } else { traceThing.netLabel = makeNetLabel(trace.gridPoints.first(), NULL, trace.flags); traceThing.newNetLabels << traceThing.netLabel; } } else if (trace.flags & JumperEnd) { if (m_pcbType) { // keep the jumperItem we have from JumperStart } else { traceThing.netLabel = makeNetLabel(trace.gridPoints.first(), traceThing.netLabel, trace.flags); traceThing.newNetLabels << traceThing.netLabel; } } else traceThing.jumperItem = NULL; bool onTraceS, onTraceD; QPointF traceAnchorS, traceAnchorD; ConnectorItem * sourceConnectorItem = NULL; if (traceThing.jumperItem) { onTraceS = onTraceD = false; sourceConnectorItem = (trace.flags & JumperStart) ? traceThing.jumperItem->connector0() : traceThing.jumperItem->connector1(); } else if (traceThing.netLabel) { sourceConnectorItem = traceThing.netLabel->connector0(); } else { sourceConnectorItem = findAnchor(gridPoints.first(), traceThing, net, traceAnchorS, onTraceS, NULL); } if (sourceConnectorItem == NULL) { DebugDialog::debug("missing source connector"); return; } ConnectorItem * destConnectorItem = findAnchor(gridPoints.last(), traceThing, net, traceAnchorD, onTraceD, sourceConnectorItem); if (destConnectorItem == NULL) { /* GridPoint gp = gridPoints.last(); for (int x = gp.x - 5; x < gp.x + 5; x++) { m_displayImage[gp.z]->setPixel(x, gp.y, 0xff000000); } for (int y = gp.y - 5; y < gp.y + 5; y++) { m_displayImage[gp.z]->setPixel(gp.x, y, 0xff000000); } updateDisplay(gp.z); */ DebugDialog::debug("missing dest connector"); return; } //if (sourceConnectorItem->attachedTo() == destConnectorItem->attachedTo()) { // sourceConnectorItem->debugInfo("source"); // destConnectorItem->debugInfo("dest"); //} QPointF sourcePoint = sourceConnectorItem->sceneAdjustedTerminalPoint(NULL); QPointF destPoint = destConnectorItem->sceneAdjustedTerminalPoint(NULL); bool skipFirst = false; bool skipLast = false; GridPoint gp = gridPoints.last(); QPointF center = getPixelCenter(gp, traceThing.topLeft, m_gridPixels); if (!atLeast(center, destPoint)) { // don't need this last point skipLast = true; } gp = gridPoints.first(); center = getPixelCenter(gp, traceThing.topLeft, m_gridPixels); if (!atLeast(center, sourcePoint)) { skipFirst = true; } // convert grid-based points to normal svg-space points and add the inbetween points necessitated by removeSteps() QList newPoints; for (int i = 0; i < gridPoints.count(); i++) { GridPoint gp1 = gridPoints.at(i); QPointF c1 = getPixelCenter(gp1, traceThing.topLeft, m_gridPixels); PointZ v1(c1, gp1.z); newPoints << v1; if ((gp1.flags & GridPointStepStart) == 0) continue; GridPoint gp2 = gridPoints.at(i + 1); QPointF c2 = getPixelCenter(gp2, traceThing.topLeft, m_gridPixels); QPointF p = getStepPoint(c1, gp1.flags, m_gridPixels); PointZ v2(p, gp1.z); newPoints << v2; QPointF q = getStepPoint(c2, gp2.flags, m_gridPixels); PointZ v3(q, gp2.z); newPoints << v3; //DebugDialog::debug(QString("remove2 %1,%2 %3,%4").arg(c1.x()).arg(c1.y()).arg(p.x()).arg(p.y())); //DebugDialog::debug(QString("\t%1,%2 %3,%4").arg(q.x()).arg(q.y()).arg(c2.x()).arg(c2.y())); } if (skipLast) { newPoints.takeLast(); } PointZ point = newPoints.takeFirst(); if (skipFirst) { point = newPoints.takeFirst(); } int lastz = point.z; ConnectorItem * nextSource = NULL; if (onTraceS) { if (!atLeast(sourcePoint, traceAnchorS)) { onTraceS = false; } else if (atLeast(point.p, traceAnchorS)) { onTraceS = false; } } if (onTraceS) { TraceWire * traceWire1 = drawOneTrace(sourcePoint, traceAnchorS, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(sourceConnectorItem, traceWire1->connector0()); traceThing.newTraces << traceWire1; TraceWire* traceWire2 = drawOneTrace(traceAnchorS, point.p, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(traceWire1->connector1(), traceWire2->connector0()); nextSource = traceWire2->connector1(); traceThing.newTraces << traceWire2; } else { TraceWire * traceWire = drawOneTrace(sourcePoint, point.p, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(sourceConnectorItem, traceWire->connector0()); nextSource = traceWire->connector1(); traceThing.newTraces << traceWire; } foreach (PointZ newPoint, newPoints) { if (newPoint.z == lastz) { TraceWire * traceWire = drawOneTrace(point.p, newPoint.p, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(nextSource, traceWire->connector0()); nextSource = traceWire->connector1(); traceThing.newTraces << traceWire; } else { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; double ringThickness, holeSize; m_sketchWidget->getViaSize(ringThickness, holeSize); double halfVia = (ringThickness + ringThickness + holeSize) / 2; viewGeometry.setLoc(QPointF(newPoint.p.x() - halfVia - Hole::OffsetPixels, newPoint.p.y() - halfVia - Hole::OffsetPixels)); ItemBase * itemBase = m_sketchWidget->addItem(m_sketchWidget->referenceModel()->retrieveModelPart(ModuleIDNames::ViaModuleIDName), ViewLayer::NewTop, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); //DebugDialog::debug(QString("back from adding via %1").arg((long) itemBase, 0, 16)); Via * via = qobject_cast(itemBase); via->setAutoroutable(true); via->setHoleSize(QString("%1in,%2in") .arg(holeSize / GraphicsUtils::SVGDPI) .arg(ringThickness / GraphicsUtils::SVGDPI), false); connectionThing.add(nextSource, via->connectorItem()); nextSource = via->connectorItem(); traceThing.newVias << via; lastz = newPoint.z; } point = newPoint; } if (onTraceD) { if (!atLeast(destPoint, traceAnchorD)) { onTraceD = false; } else if (!atLeast(point.p, traceAnchorD)) { onTraceD = false; } } if (onTraceD) { TraceWire * traceWire1 = drawOneTrace(point.p, traceAnchorD, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(nextSource, traceWire1->connector0()); traceThing.newTraces << traceWire1; TraceWire * traceWire2 = drawOneTrace(traceAnchorD, destPoint, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(traceWire1->connector1(), traceWire2->connector0()); connectionThing.add(traceWire2->connector1(), destConnectorItem); traceThing.newTraces << traceWire2; } else { TraceWire * traceWire = drawOneTrace(point.p, destPoint, m_standardWireWidth, lastz == 0 ? ViewLayer::NewBottom : ViewLayer::NewTop); connectionThing.add(nextSource, traceWire->connector0()); connectionThing.add(traceWire->connector1(), destConnectorItem); traceThing.newTraces << traceWire; } } ConnectorItem * MazeRouter::findAnchor(GridPoint gp, TraceThing & traceThing, Net * net, QPointF & p, bool & onTrace, ConnectorItem * already) { QRectF gridRect(gp.x * m_gridPixels + traceThing.topLeft.x(), gp.y * m_gridPixels + traceThing.topLeft.y(), m_gridPixels, m_gridPixels); ConnectorItem * connectorItem = findAnchor(gp, gridRect, traceThing, net, p, onTrace, already); if (connectorItem != NULL) { //if (connectorItem->attachedToID() == 9781620) { // connectorItem->debugInfo("9781620"); //} if (connectorItem->attachedToItemType() != ModelPart::Wire) { return connectorItem; } // otherwise keep looking } gridRect.adjust(-m_gridPixels, -m_gridPixels, m_gridPixels, m_gridPixels); return findAnchor(gp, gridRect, traceThing, net, p, onTrace, already); } ConnectorItem * MazeRouter::findAnchor(GridPoint gp, const QRectF & gridRect, TraceThing & traceThing, Net * net, QPointF & p, bool & onTrace, ConnectorItem * already) { ConnectorItem * alreadyCross = NULL; if (already != NULL) alreadyCross = already->getCrossLayerConnectorItem(); QList traceWires; QList traceConnectorItems; foreach (QGraphicsItem * item, m_sketchWidget->scene()->items(gridRect)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem) { if (!connectorItem->attachedTo()->isEverVisible()) continue; if (connectorItem == already) continue; if (connectorItem == alreadyCross) continue; if (already != NULL && connectorItem->attachedTo() == already->attachedTo()) { ConnectorItem * cross = connectorItem->getCrossLayerConnectorItem(); if (cross != NULL) { if (cross == already) continue; if (cross == alreadyCross) continue; } } //connectorItem->debugInfo("candidate"); bool isCandidate = (gp.z == 0 && m_sketchWidget->attachedToBottomLayer(connectorItem)) || (gp.z == 1 && m_sketchWidget->attachedToTopLayer(connectorItem)) ; if (!isCandidate) continue; bool traceConnector = false; if (net->net->contains(connectorItem)) ; else { TraceWire * traceWire = qobject_cast(connectorItem->attachedTo()); if (traceWire == NULL) { Via * via = qobject_cast(connectorItem->attachedTo()->layerKinChief()); if (via == NULL) isCandidate = false; else isCandidate = traceThing.newVias.contains(via); } else { traceConnector = isCandidate = traceThing.newTraces.contains(traceWire); } } if (!isCandidate) continue; if (traceConnector) { traceConnectorItems << connectorItem; continue; } else { //if (traceConnectorItems.count() > 0) { // connectorItem->debugInfo("chose not trace"); //} onTrace = false; p = connectorItem->sceneAdjustedTerminalPoint(NULL); return connectorItem; } } TraceWire * traceWire = dynamic_cast(item); if (traceWire == NULL) continue; if (!traceWire->isEverVisible()) continue; // only do traces if no connectorItem is found traceWires.append(traceWire); } if (traceConnectorItems.count() > 0) { //if (traceConnectorItems.count() > 1) { // foreach (ConnectorItem * connectorItem, traceConnectorItems) { // connectorItem->debugInfo("on trace"); // } //} onTrace = false; ConnectorItem * connectorItem = traceConnectorItems.takeLast(); p = connectorItem->sceneAdjustedTerminalPoint(NULL); return connectorItem; } foreach (TraceWire * traceWire, traceWires) { //traceWire->debugInfo("trace candidate"); bool isCandidate = (gp.z == 0 && m_sketchWidget->attachedToBottomLayer(traceWire->connector0())) || (gp.z == 1 && m_sketchWidget->attachedToTopLayer(traceWire->connector0())); if (!isCandidate) continue; if (traceThing.newTraces.contains(traceWire)) ; else if (net->net->contains(traceWire->connector0())) ; else continue; onTrace = true; QPointF center = gridRect.center(); QPointF p0 = traceWire->connector0()->sceneAdjustedTerminalPoint(NULL); QPointF p1 = traceWire->connector1()->sceneAdjustedTerminalPoint(NULL); double d0 = GraphicsUtils::distanceSqd(p0, center); double d1 = GraphicsUtils::distanceSqd(p1, center); double dx, dy, distanceSegment; bool atEndpoint; GraphicsUtils::distanceFromLine(center.x(), center.y(), p0.x(), p0.y(), p1.x(), p1.y(), dx, dy, distanceSegment, atEndpoint); if (atEndpoint) { DebugDialog::debug("at endpoint shouldn't happen"); } p.setX(dx); p.setY(dy); if (d0 <= d1) { return traceWire->connector0(); } else { return traceWire->connector1(); } } DebugDialog::debug("overlap not found"); return NULL; } void MazeRouter::removeColinear(QList & gridPoints) { // eliminate redundant colinear points int ix = 0; while (ix < gridPoints.count() - 2) { GridPoint p1 = gridPoints[ix]; GridPoint p2 = gridPoints[ix + 1]; if (p1.z == p2.z) { GridPoint p3 = gridPoints[ix + 2]; if (p2.z == p3.z) { if (p1.x == p2.x && p2.x == p3.x) { gridPoints.removeAt(ix + 1); continue; } else if (p1.y == p2.y && p2.y == p3.y) { gridPoints.removeAt(ix + 1); continue; } } } ix++; } } void MazeRouter::removeSteps(QList & gridPoints) { // eliminate 45 degree runs for (int ix = 0; ix < gridPoints.count() - 2; ix++) { removeStep(ix, gridPoints); } } void MazeRouter::removeStep(int ix, QList & gridPoints) { GridPoint p1 = gridPoints[ix]; GridPoint p2 = gridPoints[ix + 1]; if (p1.z != p2.z) return; GridPoint p3 = gridPoints[ix + 2]; if (p2.z != p3.z) return; int dx1 = p2.x - p1.x; int dy1 = p2.y - p1.y; if ((qAbs(dx1) == 1 && dy1 == 0) || (dx1 == 0 && qAbs(dy1) == 1)) ; else return; int dx2 = p3.x - p2.x; int dy2 = p3.y - p2.y; bool step = false; if (dx1 == 0) { step = (dy2 == 0 && qAbs(dx2) == 1); } else { step = (dx2 == 0 && qAbs(dy2) == 1); } if (!step) return; int count = 1; int flag = 0; for (int jx = ix + 3; jx < gridPoints.count(); jx++, flag++) { GridPoint p4 = gridPoints[jx]; int dx3 = p4.x - p3.x; int dy3 = p4.y - p3.y; if (flag % 2 == 0) { if (dx3 == dx1 && dy3 == dy1) { count++; } else break; } else { if (dx3 == dx2 && dy3 == dy2) { count++; } else break; } p2 = p3; p3 = p4; } gridPoints[ix].flags = getStepFlag(gridPoints[ix], gridPoints[ix + 1]) | GridPointStepStart; int jx = ix + count + 1; gridPoints[jx].flags = getStepFlag(gridPoints[jx], gridPoints[jx - 1]); /* QPointF topLeft = m_maxRect.topLeft(); DebugDialog::debug(QString("removing %1").arg(count)); for (int i = 0; i < count + 2; i++) { QPointF p = getPixelCenter(gridPoints[ix + i], topLeft, m_gridPixels); DebugDialog::debug(QString("\t%1,%2 %3,%4").arg(gridPoints[ix + i].x).arg(gridPoints[ix + i].y).arg(p.x()).arg(p.y())); } */ while (--count >= 0) { gridPoints.removeAt(ix + 1); } } void MazeRouter::addConnectionToUndo(ConnectorItem * from, ConnectorItem * to, QUndoCommand * parentCommand) { if (from == NULL || to == NULL) return; ChangeConnectionCommand * ccc = new ChangeConnectionCommand(m_sketchWidget, BaseCommand::CrossView, from->attachedToID(), from->connectorSharedID(), to->attachedToID(), to->connectorSharedID(), ViewLayer::specFromID(from->attachedToViewLayerID()), true, parentCommand); ccc->setUpdateConnections(false); } void MazeRouter::addViaToUndo(Via * via, QUndoCommand * parentCommand) { new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, ModuleIDNames::ViaModuleIDName, via->viewLayerPlacement(), via->getViewGeometry(), via->id(), false, -1, parentCommand); new SetPropCommand(m_sketchWidget, via->id(), "hole size", via->holeSize(), via->holeSize(), true, parentCommand); new CheckStickyCommand(m_sketchWidget, BaseCommand::SingleView, via->id(), false, CheckStickyCommand::RemoveOnly, parentCommand); } void MazeRouter::addJumperToUndo(JumperItem * jumperItem, QUndoCommand * parentCommand) { jumperItem->saveParams(); QPointF pos, c0, c1; jumperItem->getParams(pos, c0, c1); new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, ModuleIDNames::JumperModuleIDName, jumperItem->viewLayerPlacement(), jumperItem->getViewGeometry(), jumperItem->id(), false, -1, parentCommand); new ResizeJumperItemCommand(m_sketchWidget, jumperItem->id(), pos, c0, c1, pos, c0, c1, parentCommand); new CheckStickyCommand(m_sketchWidget, BaseCommand::SingleView, jumperItem->id(), false, CheckStickyCommand::RemoveOnly, parentCommand); } void MazeRouter::addNetLabelToUndo(SymbolPaletteItem * netLabel, QUndoCommand * parentCommand) { new AddItemCommand(m_sketchWidget, BaseCommand::CrossView, netLabel->moduleID(), netLabel->viewLayerPlacement(), netLabel->getViewGeometry(), netLabel->id(), false, -1, parentCommand); new SetPropCommand(m_sketchWidget, netLabel->id(), "label", netLabel->getLabel(), netLabel->getLabel(), true, parentCommand); } void MazeRouter::insertTrace(Trace & newTrace, int netIndex, Score & currentScore, int viaCount, bool incRouted) { if (newTrace.gridPoints.count() == 0) { DebugDialog::debug("trace with no points"); return; } //DebugDialog::debug(QString("insert trace %1").arg(newTrace.gridPoints.count())); newTrace.netIndex = netIndex; newTrace.order = currentScore.traces.values(netIndex).count(); currentScore.traces.insert(netIndex, newTrace); if (incRouted) { currentScore.routedCount.insert(netIndex, currentScore.routedCount.value(netIndex) + 1); currentScore.totalRoutedCount++; } currentScore.viaCount.insert(netIndex, currentScore.viaCount.value(netIndex, 0) + viaCount); currentScore.totalViaCount += viaCount; displayTrace(newTrace); //DebugDialog::debug(QString("done insert trace")); } void MazeRouter::incCommandProgress() { emit setProgressValue(m_cleanupCount++); int modulo = m_commandCount / 100; if (modulo > 0 && m_cleanupCount % modulo == 0) { ProcessEventBlocker::processEvents(); } //DebugDialog::debug(QString("cleanup:%1, cc:%2").arg(m_cleanupCount).arg(m_commandCount)); } void MazeRouter::setMaxCycles(int maxCycles) { Autorouter::setMaxCycles(maxCycles); emit setMaximumProgress(maxCycles); } SymbolPaletteItem * MazeRouter::makeNetLabel(GridPoint & center, SymbolPaletteItem * pairedNetLabel, uchar traceFlags) { // flags & JumperLeft means position the netlabel to the left of center, the netlabel points right if (m_netLabelIndex < 0) { m_netLabelIndex = 0; foreach (QGraphicsItem * item, m_sketchWidget->scene()->items()) { SymbolPaletteItem * netLabel = dynamic_cast(item); if (netLabel == NULL || !netLabel->isOnlyNetLabel()) continue; bool ok; int ix = netLabel->getLabel().toInt(&ok); if (ok && ix > m_netLabelIndex) m_netLabelIndex = ix; } } if (pairedNetLabel == NULL) { m_netLabelIndex++; } long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; ItemBase * itemBase = m_sketchWidget->addItem(m_sketchWidget->referenceModel()->retrieveModelPart(traceFlags & JumperLeft ? ModuleIDNames::NetLabelModuleIDName : ModuleIDNames::LeftNetLabelModuleIDName), ViewLayer::NewBottom, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); SymbolPaletteItem * netLabel = dynamic_cast(itemBase); netLabel->setAutoroutable(true); netLabel->setLabel(QString::number(m_netLabelIndex)); QPointF tl = m_maxRect.topLeft(); QPointF c1 = getPixelCenter(center, tl, m_gridPixels); QSizeF size = netLabel->boundingRect().size(); int x = c1.x(); if (traceFlags & JumperLeft) { x -= size.width(); } netLabel->setPos(x, c1.y() - (size.height() / 2)); //DebugDialog::debug(QString("ix:%1 tl:%2 %3,%4").arg(m_netLabelIndex).arg(traceFlags).arg(x).arg(c1.y() - (size.height() / 2))); netLabel->saveGeometry(); return netLabel; } void MazeRouter::routeJumper(int netIndex, RouteThing & routeThing, Score & currentScore) { if (routeThing.bestDistanceToTarget == std::numeric_limits::max() || routeThing.bestDistanceToSource == std::numeric_limits::max()) { // never got started on this route return; } //DebugDialog::debug(QString("route jumper %1, %2").arg(routeThing.bestDistanceToSource).arg(routeThing.bestDistanceToTarget)); //updateDisplay(0); //if (m_bothSidesNow) updateDisplay(1); bool routeBothEnds = true; Trace sourceTrace; if (!m_pcbType) { // is there already a net label on this net? // TODO: which subnet has the jumper? foreach (Trace trace, currentScore.traces.values(netIndex)) { if (trace.flags & JumperStart) { sourceTrace = trace; routeBothEnds = false; break; } } } //updateDisplay(m_grid, 0); //if (m_bothSidesNow) updateDisplay(m_grid, 1); GridPoint gp1 = lookForJumper(routeThing.bestLocationToTarget, GridSource, routeThing.gridTargetPoint); if (gp1.baseCost == GridBoardObstacle) return; GridPoint gp2 = lookForJumper(routeThing.bestLocationToSource, GridTarget, routeThing.gridSourcePoint); if (gp2.baseCost == GridBoardObstacle) return; int sourceViaCount; if (routeBothEnds) { sourceTrace.flags = JumperStart; if (gp1.flags & GridPointJumperLeft) sourceTrace.flags |= JumperLeft; else if (gp1.flags & GridPointJumperRight) sourceTrace.flags |= JumperRight; sourceTrace.gridPoints = traceBack(gp1, m_grid, sourceViaCount, GridTarget, GridSource); // trace back to source } Trace destTrace; destTrace.flags = JumperEnd; if (gp2.flags & GridPointJumperLeft) destTrace.flags |= JumperLeft; else if (gp2.flags & GridPointJumperRight) destTrace.flags |= JumperRight; int targetViaCount; destTrace.gridPoints = traceBack(gp2, m_grid, targetViaCount, GridSource, GridTarget); // trace back to target if (routeBothEnds) { insertTrace(sourceTrace, netIndex, currentScore, sourceViaCount, false); } insertTrace(destTrace, netIndex, currentScore, targetViaCount, true); updateDisplay(0); if (m_bothSidesNow) updateDisplay(1); clearExpansion(m_grid); } GridPoint MazeRouter::lookForJumper(GridPoint initial, GridValue targetValue, QPoint targetLocation) { QSet already; std::priority_queue pq; initial.qCost = 0; pq.push(initial); already.insert(gridPointInt(m_grid, initial)); while (!pq.empty()) { GridPoint gp = pq.top(); pq.pop(); gp.baseCost = m_grid->at(gp.x, gp.y, gp.z); /* GridValue bc = gp.baseCost; if (targetValue == GridSource) bc ^= GridSourceFlag; bc *= 3; if (bc > 255) bc = 255; m_displayImage[gp.z]->setPixel(gp.x, gp.y, 0xff000000 | (bc << 16) | (bc << 8) | bc); updateDisplay(gp.z); */ if ((*m_jumperWillFitFunction)(gp, m_grid, m_halfGridJumperSize)) { if (targetValue == GridSource) gp.baseCost ^= GridSourceFlag; //m_displayImage[gp.z]->setPixel(gp.x, gp.y, 0xff0000ff); //updateDisplay(gp.z); //updateDisplay(gp.z); //QPointF p = getPixelCenter(gp, m_maxRect.topLeft(), m_gridPixels); //DebugDialog::debug(QString("jumper location %1").arg(gp.flags), p); return gp; } if (gp.x > 0) expandOneJ(gp, pq, -1, 0, 0, targetValue, targetLocation, already); if (gp.x < m_grid->x - 1) expandOneJ(gp, pq, 1, 0, 0, targetValue, targetLocation, already); if (gp.y > 0) expandOneJ(gp, pq, 0, -1, 0, targetValue, targetLocation, already); if (gp.y < m_grid->y - 1) expandOneJ(gp, pq, 0, 1, 0, targetValue, targetLocation, already); if (m_bothSidesNow) { if (gp.z > 0) expandOneJ(gp, pq, 0, 0, -1, targetValue, targetLocation, already); if (gp.z < m_grid->z - 1) expandOneJ(gp, pq, 0, 0, 1, targetValue, targetLocation, already); } } GridPoint failed; failed.baseCost = GridBoardObstacle; return failed; } void MazeRouter::expandOneJ(GridPoint & gridPoint, std::priority_queue & pq, int dx, int dy, int dz, GridValue targetValue, QPoint targetLocation, QSet & already) { GridPoint next; next.x = gridPoint.x + dx; next.y = gridPoint.y + dy; next.z = gridPoint.z + dz; int gpi = gridPointInt(m_grid, next); if (already.contains(gpi)) return; already.insert(gpi); GridValue nextval = m_grid->at(next.x, next.y, next.z); if (nextval == GridPartObstacle || nextval == GridBoardObstacle || nextval == GridSource || nextval == GridTempObstacle || nextval == GridTarget || nextval == GridAvoid) return; else if (nextval == 0) return; else { // already been here: see if it's the right expansion if (targetValue == GridSource) { if ((nextval & GridSourceFlag) == 0) return; } else { if (nextval & GridSourceFlag) return; } } double d = (m_costFunction)(QPoint(next.x, next.y), targetLocation); next.qCost = d; next.baseCost = 0; //DebugDialog::debug(QString("pushing next %1 %2 %3, %4, %5").arg(gridPoint.x).arg(gridPoint.y).arg(gridPoint.z).arg(gridPoint.qCost).arg(routeThing.pq.size())); pq.push(next); } void MazeRouter::removeOffBoardAnd(bool isPCBType, bool removeSingletons, bool bothSides) { QRectF boardRect; if (m_board) boardRect = m_board->sceneBoundingRect(); // remove any vias or jumperItems that will be deleted, also remove off-board items for (int i = m_allPartConnectorItems.count() - 1; i >= 0; i--) { QList * connectorItems = m_allPartConnectorItems.at(i); if (removeSingletons) { if (connectorItems->count() < 2) { connectorItems->clear(); } else if (connectorItems->count() == 2) { if (connectorItems->at(0) == connectorItems->at(1)->getCrossLayerConnectorItem()) { connectorItems->clear(); } } } for (int j = connectorItems->count() - 1; j >= 0; j--) { ConnectorItem * connectorItem = connectorItems->at(j); //connectorItem->debugInfo("pci"); bool doRemove = false; if (connectorItem->attachedToItemType() == ModelPart::Via) { Via * via = qobject_cast(connectorItem->attachedTo()->layerKinChief()); doRemove = via->getAutoroutable(); } else if (connectorItem->attachedToItemType() == ModelPart::Jumper) { JumperItem * jumperItem = qobject_cast(connectorItem->attachedTo()->layerKinChief()); doRemove = jumperItem->getAutoroutable(); } else if (connectorItem->attachedToItemType() == ModelPart::Symbol) { SymbolPaletteItem * netLabel = qobject_cast(connectorItem->attachedTo()->layerKinChief()); doRemove = netLabel->getAutoroutable() && netLabel->isOnlyNetLabel(); } if (!bothSides && connectorItem->attachedToViewLayerID() == ViewLayer::Copper1) doRemove = true; if (!doRemove && isPCBType) { if (!connectorItem->sceneBoundingRect().intersects(boardRect)) { doRemove = true; } } if (doRemove) { connectorItems->removeAt(j); } } if (connectorItems->count() == 0) { m_allPartConnectorItems.removeAt(i); delete connectorItems; } } } void MazeRouter::optimizeTraces(QList & order, QMultiHash > > & bundles, QMultiHash & vias, QMultiHash & jumperItems, QMultiHash & netLabels, NetList & netList, ConnectionThing & connectionThing) { QList layerSpecs; layerSpecs << ViewLayer::NewBottom; if (m_bothSidesNow) layerSpecs << ViewLayer::NewTop; QRectF r2(0, 0, m_boardImage->width(), m_boardImage->height()); QPointF topLeft = m_maxRect.topLeft(); //QList order2(order); //order2.append(order); int progress = order.count(); foreach (int netIndex, order) { emit setProgressValue(progress++); Net * net = netList.nets.at(netIndex); foreach (ViewLayer::ViewLayerPlacement layerSpec, layerSpecs) { fastCopy(m_boardImage, m_spareImage); QDomDocument * masterDoc = m_masterDocs.value(layerSpec); //QString before = masterDoc->toString(); Markers markers; initMarkers(markers, m_pcbType); NetElements netElements; DRC::splitNetPrep(masterDoc, *(net->net), markers, netElements.net, netElements.alsoNet, netElements.notNet, true); foreach (QDomElement element, netElements.net) { element.setTagName("g"); } foreach (QDomElement element, netElements.alsoNet) { element.setTagName("g"); } ItemBase::renderOne(masterDoc, m_spareImage, r2); //QString after = masterDoc->toString(); foreach (QDomElement element, netElements.net) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } foreach (QDomElement element, netElements.alsoNet) { element.setTagName(element.attribute("former")); element.removeAttribute("net"); } foreach (QDomElement element, netElements.notNet) { element.removeAttribute("net"); } QPainter painter; painter.begin(m_spareImage); QPen pen = painter.pen(); pen.setColor(0xff000000); QBrush brush(QColor(0xff000000)); painter.setBrush(brush); foreach (int otherIndex, order) { if (otherIndex == netIndex) continue; foreach(QList< QPointer > bundle, bundles.values(otherIndex)) { if (bundle.count() == 0) continue; if (ViewLayer::specFromID(bundle.at(0)->viewLayerID()) != layerSpec) continue; pen.setWidthF((bundle.at(0)->width() + m_keepoutPixels + m_keepoutPixels) * OptimizeFactor); painter.setPen(pen); foreach (TraceWire * traceWire, bundle) { if (traceWire == NULL) continue; QPointF p1 = (traceWire->connector0()->sceneAdjustedTerminalPoint(NULL) - topLeft) * OptimizeFactor; QPointF p2 = (traceWire->connector1()->sceneAdjustedTerminalPoint(NULL) - topLeft) * OptimizeFactor; painter.drawLine(p1, p2); } } painter.setPen(Qt::NoPen); foreach (Via * via, vias.values(otherIndex)) { QPointF p = (via->connectorItem()->sceneAdjustedTerminalPoint(NULL) - topLeft) * OptimizeFactor; double rad = ((via->connectorItem()->sceneBoundingRect().width() / 2) + m_keepoutPixels) * OptimizeFactor; painter.drawEllipse(p, rad, rad); } foreach (JumperItem * jumperItem, jumperItems.values(otherIndex)) { QPointF p = (jumperItem->connector0()->sceneAdjustedTerminalPoint(NULL) - topLeft) * OptimizeFactor; double rad = ((jumperItem->connector0()->sceneBoundingRect().width() / 2) + m_keepoutPixels) * OptimizeFactor; painter.drawEllipse(p, rad, rad); p = (jumperItem->connector1()->sceneAdjustedTerminalPoint(NULL) - topLeft) * OptimizeFactor; painter.drawEllipse(p, rad, rad); } foreach (SymbolPaletteItem * netLabel, netLabels.values(otherIndex)) { QRectF r = netLabel->sceneBoundingRect(); painter.drawRect((r.left() - topLeft.x() - m_keepoutPixels) * OptimizeFactor, (r.top() - topLeft.y() - m_keepoutPixels) * OptimizeFactor, (r.width() + m_keepoutPixels) * OptimizeFactor, (r.height() + m_keepoutPixels) * OptimizeFactor); } } foreach (SymbolPaletteItem * netLabel, netLabels.values(netIndex)) { QRectF r = netLabel->sceneBoundingRect(); painter.drawRect((r.left() - topLeft.x() - m_keepoutPixels) * OptimizeFactor, (r.top() - topLeft.y() - m_keepoutPixels) * OptimizeFactor, (r.width() + m_keepoutPixels) * OptimizeFactor, (r.height() + m_keepoutPixels) * OptimizeFactor); } painter.end(); #ifndef QT_NO_DEBUG //m_spareImage->save(FolderUtils::getUserDataStorePath("") + QString("/optimizeObstacles%1_%2.png").arg(netIndex, 2, 10, QChar('0')).arg(layerSpec)); #endif // finally test all combinations of each bundle // identify traces in bundles with source and dest that cannot be deleted // remove source/dest (delete and keep QPointers?) // schematic view must replace with two 90-degree lines foreach(QList< QPointer > bundle, bundles.values(netIndex)) { if (bundle.count() == 0) continue; for (int i = bundle.count() - 1; i >= 0; i--) { TraceWire * traceWire = bundle.at(i); if (traceWire == NULL) bundle.removeAt(i); } if (ViewLayer::specFromID(bundle.at(0)->viewLayerID()) != layerSpec) { // all wires in a single bundle are in the same layer continue; } /* QList tos = connectionThing.values(bundle.first()->connector0()); foreach (ConnectorItem * to, tos) { if (to->attachedToItemType() == ModelPart::Via) { to->debugInfo("start hooked to via"); } } tos = connectionThing.values(bundle.last()->connector1()); foreach (ConnectorItem * to, tos) { if (to->attachedToItemType() == ModelPart::Via) { to->debugInfo("end hooked to via"); } } */ QVector points(bundle.count() + 1, QPointF(0, 0)); QVector splits(bundle.count() + 1, false); int index = 0; foreach (TraceWire * traceWire, bundle) { if (connectionThing.multi(traceWire->connector0())) splits.replace(index, true); points.replace(index, traceWire->connector0()->sceneAdjustedTerminalPoint(NULL)); index++; if (connectionThing.multi(traceWire->connector1())) splits.replace(index, true); points.replace(index, traceWire->connector1()->sceneAdjustedTerminalPoint(NULL)); } splits.replace(0, false); splits.replace(splits.count() - 1, true); QList pointsSoFar; QList bundleSoFar; int startIndex = 0; for (int pix = 0; pix < points.count(); pix++) { pointsSoFar << points.at(pix); if (pix < points.count() - 1) { bundleSoFar << bundle.at(pix); } if (splits.at(pix)) { reducePoints(pointsSoFar, topLeft, bundleSoFar, startIndex, pix, connectionThing, netIndex, layerSpec); pointsSoFar.clear(); bundleSoFar.clear(); pointsSoFar << points.at(pix); if (pix < points.count() - 1) bundleSoFar << bundle.at(pix); startIndex = pix; } } } } } } void MazeRouter::reducePoints(QList & points, QPointF topLeft, QList & bundle, int startIndex, int endIndex, ConnectionThing & connectionThing, int netIndex, ViewLayer::ViewLayerPlacement layerSpec) { Q_UNUSED(netIndex); Q_UNUSED(layerSpec); #ifndef QT_NO_DEBUG //int inc = 0; #endif double width = bundle.at(0)->width() * OptimizeFactor; for (int separation = endIndex - startIndex; separation > 1; separation--) { for (int ix = 0; ix < points.count() - separation; ix++) { QPointF p1 = (points.at(ix) - topLeft) * OptimizeFactor; QPointF p2 = (points.at(ix + separation) - topLeft) * OptimizeFactor; double minX = qMax(0.0, qMin(p1.x(), p2.x()) - width); double minY = qMax(0.0, qMin(p1.y(), p2.y()) - width); double maxX = qMin(m_spareImage2->width() - 1.0, qMax(p1.x(), p2.x()) + width); double maxY = qMin(m_spareImage2->height() - 1.0, qMax(p1.y(), p2.y()) + width); int corners = 1; if (!m_pcbType) { if (qAbs(p1.x() - p2.x()) >= 1 && qAbs(p1.y() - p2.y()) >= 1) { corners = 2; if (separation == 2) continue; // since we already have two lines, do nothing } } for (int corner = 0; corner < corners; corner++) { m_spareImage2->fill(0xffffffff); QPainter painter; painter.begin(m_spareImage2); QPen pen = painter.pen(); pen.setColor(0xff000000); pen.setWidthF(width); painter.setPen(pen); if (corners == 1) { painter.drawLine(p1, p2); } else { if (corner == 0) { // vertical then horizontal painter.drawLine(p1.x(), p1.y(), p1.x(), p2.y()); painter.drawLine(p1.x(), p2.y(), p2.x(), p2.y()); } else { // horizontal then vertical painter.drawLine(p1.x(), p1.y(), p2.x(), p1.y()); painter.drawLine(p2.x(), p1.y(), p2.x(), p2.y()); } } painter.end(); #ifndef QT_NO_DEBUG //m_spareImage2->save(FolderUtils::getUserDataStorePath("") + QString("/optimizeTrace%1_%2_%3.png").arg(netIndex,2,10,QChar('0')).arg(layerSpec).arg(inc++,3,10,QChar('0'))); #endif bool overlaps = false; for (int y = minY; y <= maxY && !overlaps; y++) { for (int x = minX; x <= maxX && !overlaps; x++) { if (m_spareImage->pixel(x, y) == 0xffffffff) continue; if (m_spareImage2->pixel(x, y) == 0xffffffff) continue; overlaps = true; } } if (overlaps) continue; TraceWire * traceWire = bundle.at(ix); TraceWire * last = bundle.at(ix + separation - 1); TraceWire * next = bundle.at(ix + 1); QList newDests = connectionThing.values(last->connector1()); QPointF unop_p2 = (p2 / OptimizeFactor) + topLeft; if (corners == 2) { TraceWire * afterNext = bundle.at(ix + 2); QPointF middle; if (corner == 0) { middle.setX(p1.x()); middle.setY(p2.y()); } else { middle.setX(p2.x()); middle.setY(p1.y()); } middle = (middle / OptimizeFactor) + topLeft; traceWire->setLineAnd(QLineF(QPointF(0, 0), middle - traceWire->pos()), traceWire->pos(), true); traceWire->saveGeometry(); traceWire->update(); next->setLineAnd(QLineF(QPointF(0, 0), unop_p2 - middle), middle, true); next->saveGeometry(); next->update(); foreach (ConnectorItem * newDest, newDests) { connectionThing.add(next->connector1(), newDest); } connectionThing.remove(next->connector1(), afterNext->connector0()); for (int i = 1; i < separation - 1; i++) { TraceWire * tw = bundle.takeAt(ix + 2); connectionThing.remove(tw->connector0()); connectionThing.remove(tw->connector1()); ModelPart * modelPart = tw->modelPart(); delete tw; modelPart->setParent(NULL); delete modelPart; points.removeAt(ix + 2); } points.replace(ix + 1, middle); } else { traceWire->setLineAnd(QLineF(QPointF(0, 0), unop_p2 - traceWire->pos()), traceWire->pos(), true); traceWire->saveGeometry(); traceWire->update(); foreach (ConnectorItem * newDest, newDests) { connectionThing.add(traceWire->connector1(), newDest); } connectionThing.remove(traceWire->connector1(), next->connector0()); for (int i = 0; i < separation - 1; i++) { TraceWire * tw = bundle.takeAt(ix + 1); connectionThing.remove(tw->connector0()); connectionThing.remove(tw->connector1()); ModelPart * modelPart = tw->modelPart(); delete tw; modelPart->setParent(NULL); delete modelPart; points.removeAt(ix + 1); } } break; } } } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/mazerouter/mazerouter.h�������������������������������������������0000664�0000000�0000000�00000022626�12502026767�0023676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef MAZEROUTER_H #define MAZEROUTER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../viewgeometry.h" #include "../../viewlayer.h" #include "../../commands.h" #include "../autorouter.h" typedef quint64 GridValue; struct GridPoint { int x, y, z; GridValue baseCost; double qCost; uchar flags; bool operator<(const GridPoint&) const; GridPoint(QPoint, int); GridPoint(); }; struct PointZ { QPointF p; int z; PointZ(QPointF _p, int _z) { p = _p; z = _z; } }; struct Net { QList* net; QList< QList > subnets; int pinsWithin; int id; }; struct NetList { QList nets; }; struct Trace { int netIndex; int order; uchar flags; QList gridPoints; Trace() { flags = 0; } }; struct NetOrdering { QList order; }; struct Score { NetOrdering ordering; QMultiHash traces; QHash routedCount; QHash viaCount; int totalRoutedCount; int totalViaCount; int reorderNet; bool anyUnrouted; Score(); void setOrdering(const NetOrdering &); }; struct Nearest { int i, j; double distance; ConnectorItem * ic; ConnectorItem * jc; }; struct Grid { GridValue * data; int x; int y; int z; Grid(int x, int y, int layers); GridValue at(int x, int y, int z) const; void setAt(int x, int y, int z, GridValue value); QList init(int x, int y, int z, int width, int height, const QImage &, GridValue value, bool collectPoints); QList init4(int x, int y, int z, int width, int height, const QImage *, GridValue value, bool collectPoints); void clear(); void free(); void copy(int fromIndex, int toIndex); }; struct NetElements { QList net; QList alsoNet; QList notNet; }; struct RouteThing { QRectF r; QRectF r4; QList layerSpecs; Nearest nearest; std::priority_queue sourceQ; std::priority_queue targetQ; QPoint gridSourcePoint; QPoint gridTargetPoint; GridValue sourceValue; GridValue targetValue; double bestDistanceToTarget; double bestDistanceToSource; GridPoint bestLocationToTarget; GridPoint bestLocationToSource; bool unrouted; NetElements netElements[2]; QSet avoids; }; struct TraceThing { QList newTraces; QList newVias; QList newJumperItems; QList newNetLabels; JumperItem * jumperItem; SymbolPaletteItem * netLabel; QPointF topLeft; GridPoint nextTraceStart; }; struct ConnectionThing { QMultiHash > sd; void add(ConnectorItem * s, ConnectorItem * d); void remove(ConnectorItem * s); void remove(ConnectorItem * s, ConnectorItem * d); bool multi(ConnectorItem * s); QList values(ConnectorItem * s); }; typedef bool (*JumperWillFitFunction)(GridPoint &, const Grid *, int halfSize); typedef double (*CostFunction)(const QPoint & p1, const QPoint & p2); //////////////////////////////////// class MazeRouter : public Autorouter { Q_OBJECT public: MazeRouter(class PCBSketchWidget *, QGraphicsItem * board, bool adjustIf); ~MazeRouter(void); void start(); protected: void setUpWidths(double width); int findPinsWithin(QList * net); bool makeBoard(QImage *, double keepout, const QRectF & r); bool makeMasters(QString &); bool routeNets(NetList &, bool makeJumper, Score & currentScore, const QSizeF gridSize, QList & allOrderings); bool routeOne(bool makeJumper, Score & currentScore, int netIndex, RouteThing &, QList & allOrderings); void findNearestPair(QList< QList > & subnets, Nearest &); void findNearestPair(QList< QList > & subnets, int i, QList & inet, Nearest &); QList renderSource(QDomDocument * masterDoc, int z, ViewLayer::ViewLayerPlacement, Grid * grid, QList & netElements, QList & subnet, GridValue value, bool clearElements, const QRectF & r); QList route(RouteThing &, int & viaCount); void expand(GridPoint &, RouteThing &); void expandOne(GridPoint &, RouteThing &, int dx, int dy, int dz, bool crossLayer); bool viaWillFit(GridPoint &, Grid * grid); QList traceBack(GridPoint, Grid *, int & viaCount, GridValue sourceValue, GridValue targetValue); GridPoint traceBackOne(GridPoint &, Grid *, int dx, int dy, int dz, GridValue sourceValue, GridValue targetValue); void updateDisplay(int iz); void updateDisplay(Grid *, int iz); void updateDisplay(GridPoint &); void clearExpansion(Grid * grid); void prepSourceAndTarget(QDomDocument * masterdoc, RouteThing &, QList< QList > & subnets, int z, ViewLayer::ViewLayerPlacement); bool moveBack(Score & currentScore, int index, QList & allOrderings); void displayTrace(Trace &); void initTraceDisplay(); void traceObstacles(QList & traces, int netIndex, Grid * grid, int ikeepout); void traceAvoids(QList & traces, int netIndex, RouteThing & routeThing); bool routeNext(bool makeJumper, RouteThing &, QList< QList > & subnets, Score & currentScore, int netIndex, QList & allOrderings); void cleanUpNets(NetList &); void createTraces(NetList & netList, Score & bestScore, QUndoCommand * parentCommand); void createTrace(Trace &, QList &, TraceThing &, ConnectionThing &, Net *); void removeColinear(QList & gridPoints); void removeSteps(QList & gridPoints); void removeStep(int ix, QList & gridPoints); ConnectorItem * findAnchor(GridPoint gp, TraceThing &, Net * net, QPointF & p, bool & onTrace, ConnectorItem * already); ConnectorItem * findAnchor(GridPoint gp, const QRectF &, TraceThing &, Net * net, QPointF & p, bool & onTrace, ConnectorItem * already); void addConnectionToUndo(ConnectorItem * from, ConnectorItem * to, QUndoCommand * parentCommand); void addViaToUndo(Via *, QUndoCommand * parentCommand); void addJumperToUndo(JumperItem *, QUndoCommand * parentCommand); void routeJumper(int netIndex, RouteThing &, Score & currentScore); void insertTrace(Trace & newTrace, int netIndex, Score & currentScore, int viaCount, bool incRouted); SymbolPaletteItem * makeNetLabel(GridPoint & center, SymbolPaletteItem * pairedNetLabel, uchar traceFlags); void addNetLabelToUndo(SymbolPaletteItem * netLabel, QUndoCommand * parentCommand); GridPoint lookForJumper(GridPoint initial, GridValue targetValue, QPoint targetLocation); void expandOneJ(GridPoint & gridPoint, std::priority_queue & pq, int dx, int dy, int dz, GridValue targetValue, QPoint targetLocation, QSet & already); void removeOffBoardAnd(bool isPCBType, bool removeSingletons, bool bothSides); void optimizeTraces(QList & order, QMultiHash > > &, QMultiHash &, QMultiHash &, QMultiHash &, NetList &, ConnectionThing &); void reducePoints(QList & points, QPointF topLeft, QList & bundle, int startIndex, int endIndex, ConnectionThing &, int netIndex, ViewLayer::ViewLayerPlacement); public slots: void incCommandProgress(); void setMaxCycles(int); protected: LayerList m_viewLayerIDs; QHash m_masterDocs; double m_keepoutMils; double m_keepoutGrid; int m_keepoutGridInt; int m_halfGridViaSize; int m_halfGridJumperSize; double m_gridPixels; double m_standardWireWidth; QImage * m_displayImage[2]; QImage * m_boardImage; QImage * m_spareImage; QImage * m_spareImage2; QGraphicsPixmapItem * m_displayItem[2]; bool m_temporaryBoard; CostFunction m_costFunction; JumperWillFitFunction m_jumperWillFitFunction; uint m_traceColors[2]; Grid * m_grid; int m_cleanupCount; int m_netLabelIndex; int m_commandCount; }; #endif ����������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/autoroute/panelizer.cpp�����������������������������������������������������0000664�0000000�0000000�00000201544�12502026767�0021626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "panelizer.h" #include "../debugdialog.h" #include "../sketch/pcbsketchwidget.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/folderutils.h" #include "../items/resizableboard.h" #include "../items/logoitem.h" #include "../items/groundplane.h" #include "../fsvgrenderer.h" #include "../fapplication.h" #include "../svg/gerbergenerator.h" #include "../referencemodel/referencemodel.h" #include "../version/version.h" #include "../processeventblocker.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include "cmrouter/tileutils.h" #include #include #include #include #include #include #include static int OutlineLayer = 0; static int SilkTopLayer = 0; static QString PanelizerOutputPath; static QSet PanelizerFileNames; /////////////////////////////////////////////////////////// void collectTexts(const QString & svg, QStringList & strings) { QDomDocument doc; doc.setContent(svg); QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName("text"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement textElement = domNodeList.at(i).toElement(); QString string; QDomNodeList childList = textElement.childNodes(); for (int j = 0; j < childList.count(); j++) { QDomNode child = childList.item(j); if (child.isText()) { string.append(child.nodeValue()); } } strings.append(string); } } bool byOptionalPriority(PanelItem * p1, PanelItem * p2) { return p1->optionalPriority > p2->optionalPriority; } bool areaGreaterThan(PanelItem * p1, PanelItem * p2) { return p1->boardSizeInches.width() * p1->boardSizeInches.height() > p2->boardSizeInches.width() * p2->boardSizeInches.height(); } int allSpaces(Tile * tile, UserData userData) { QList * tiles = (QList *) userData; if (TiGetType(tile) == Tile::SPACE) { tiles->append(tile); return 0; } tiles->clear(); return 1; // stop the search } int allObstacles(Tile * tile, UserData userData) { if (TiGetType(tile) == Tile::OBSTACLE) { QList * obstacles = (QList *) userData; obstacles->append(tile); } return 0; } static int PlanePairIndex = 0; static double Worst = std::numeric_limits::max() / 4; int roomOn(Tile * tile, TileRect & tileRect, BestPlace * bestPlace) { int w = tileRect.xmaxi - tileRect.xmini; int h = tileRect.ymaxi - tileRect.ymini; if (bestPlace->width <= w && bestPlace->height <= h) { bestPlace->bestTile = tile; return 1; } TileRect temp; temp.xmini = tileRect.xmini; temp.xmaxi = temp.xmini + bestPlace->width; temp.ymini = tileRect.ymini; temp.ymaxi = temp.ymini + bestPlace->height; QList spaces; TiSrArea(tile, bestPlace->plane, &temp, allSpaces, &spaces); if (spaces.count()) { bestPlace->bestTile = tile; return 1; } return 0; } int roomAnywhere(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); return roomOn(tile, tileRect, bestPlace); } int roomOnTop(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); if (tileRect.ymini != bestPlace->maxRect.ymini) return 0; return roomOn(tile, tileRect, bestPlace); } int roomOnBottom(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); if (tileRect.ymaxi != bestPlace->maxRect.ymaxi) return 0; return roomOn(tile, tileRect, bestPlace); } int roomOnLeft(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); if (tileRect.xmini != bestPlace->maxRect.xmini) return 0; return roomOn(tile, tileRect, bestPlace); } int roomOnRight(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); if (tileRect.xmaxi != bestPlace->maxRect.xmaxi) return 0; return roomOn(tile, tileRect, bestPlace); } BestPlace::BestPlace() { bestTile = NULL; bestArea = Worst; } PanelItem::PanelItem() { produced = 0; boardID = 0; refPanelItem = NULL; } PanelItem::PanelItem(PanelItem * from) { this->produced = from->produced; this->boardName = from->boardName; this->path = from->path; this->required = from->required; this->maxOptional = from->maxOptional; this->optionalPriority = from->optionalPriority; this->boardSizeInches = from->boardSizeInches; this->boardID = from->boardID; this->refPanelItem = from; } ///////////////////////////////////////////////////////////////////////////////// void Panelizer::panelize(FApplication * app, const QString & panelFilename, bool customPartsOnly) { QString msg = "panelize"; if (customPartsOnly) msg += " custom parts"; initPanelizerOutput(panelFilename, msg); QFile panelizerFile(panelFilename); QFileInfo info(panelFilename); QDir copyDir = info.absoluteDir(); copyDir.cd("copies"); if (!copyDir.exists()) { writePanelizerOutput(QString("unable to create 'copies' folder in '%1'").arg(info.absoluteDir().absolutePath())); return; } QString errorStr; int errorLine; int errorColumn; DebugDialog::setEnabled(true); QDomDocument panelizerDocument; if (!panelizerDocument.setContent(&panelizerFile, true, &errorStr, &errorLine, &errorColumn)) { writePanelizerOutput(QString("Unable to parse '%1': '%2' line:%3 column:%4").arg(panelFilename).arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement panelizerRoot = panelizerDocument.documentElement(); if (panelizerRoot.isNull() || panelizerRoot.tagName() != "panelizer") { writePanelizerOutput(QString("root element is not 'panelizer'")); return; } PanelParams panelParams; if (!initPanelParams(panelizerRoot, panelParams)) return; QFileInfo pinfo(panelFilename); QDir outputDir = pinfo.absoluteDir(); if (customPartsOnly) { outputDir.mkdir("custom"); outputDir.cd("custom"); } outputDir.mkdir("svg"); outputDir.mkdir("gerber"); outputDir.mkdir("fz"); QDir svgDir(outputDir); svgDir.cd("svg"); if (!svgDir.exists()) { writePanelizerOutput(QString("unable to create svg folder in '%1'").arg(pinfo.absolutePath())); return; } DebugDialog::debug(QString("svg folder '%1'\n").arg(svgDir.absolutePath())); QDir gerberDir(outputDir); gerberDir.cd("gerber"); if (!gerberDir.exists()) { writePanelizerOutput(QString("unable to create gerber folder in '%1'").arg(pinfo.absolutePath())); return; } DebugDialog::debug(QString("gerber folder '%1'\n").arg(gerberDir.absolutePath())); QDir fzDir(outputDir); fzDir.cd("fz"); if (!fzDir.exists()) { writePanelizerOutput(QString("unable to create fz folder in '%1'").arg(pinfo.absolutePath())); return; } DebugDialog::debug(QString("fz folder '%1'\n").arg(fzDir.absolutePath())); QDomElement boards = panelizerRoot.firstChildElement("boards"); QDomElement board = boards.firstChildElement("board"); if (board.isNull()) { writePanelizerOutput(QString("no elements found")); return; } QHash fzzFilePaths; QDomElement paths = panelizerRoot.firstChildElement("paths"); QDomElement path = paths.firstChildElement("path"); if (path.isNull()) { writePanelizerOutput(QString("no elements found")); return; } collectFiles(pinfo.absoluteDir(), path, fzzFilePaths); if (fzzFilePaths.count() == 0) { writePanelizerOutput(QString("no fzz files found in paths")); return; } board = boards.firstChildElement("board"); if (!checkBoards(board, fzzFilePaths)) return; app->createUserDataStoreFolderStructure(); app->registerFonts(); app->loadReferenceModel("", false); QList layerThingList; layerThingList.append(LayerThing("outline", ViewLayer::outlineLayers(), SVG2gerber::ForOutline, GerberGenerator::OutlineSuffix)); layerThingList.append(LayerThing("copper_top", ViewLayer::copperLayers(ViewLayer::NewTop), SVG2gerber::ForCopper, GerberGenerator::CopperTopSuffix)); layerThingList.append(LayerThing("copper_bottom", ViewLayer::copperLayers(ViewLayer::NewBottom), SVG2gerber::ForCopper, GerberGenerator::CopperBottomSuffix)); layerThingList.append(LayerThing("mask_top", ViewLayer::maskLayers(ViewLayer::NewTop), SVG2gerber::ForMask, GerberGenerator:: MaskTopSuffix)); layerThingList.append(LayerThing("mask_bottom", ViewLayer::maskLayers(ViewLayer::NewBottom), SVG2gerber::ForMask, GerberGenerator::MaskBottomSuffix)); layerThingList.append(LayerThing("paste_mask_top", ViewLayer::maskLayers(ViewLayer::NewTop), SVG2gerber::ForPasteMask, GerberGenerator:: PasteMaskTopSuffix)); layerThingList.append(LayerThing("paste_mask_bottom", ViewLayer::maskLayers(ViewLayer::NewBottom), SVG2gerber::ForPasteMask, GerberGenerator::PasteMaskBottomSuffix)); layerThingList.append(LayerThing("silk_top", ViewLayer::silkLayers(ViewLayer::NewTop), SVG2gerber::ForSilk, GerberGenerator::SilkTopSuffix)); layerThingList.append(LayerThing("silk_bottom", ViewLayer::silkLayers(ViewLayer::NewBottom), SVG2gerber::ForSilk, GerberGenerator::SilkBottomSuffix)); layerThingList.append(LayerThing("drill", ViewLayer::drillLayers(), SVG2gerber::ForDrill, GerberGenerator::DrillSuffix)); for (int i = 0; i < layerThingList.count(); i++) { LayerThing layerThing = layerThingList.at(i); if (layerThing.name.compare("outline") == 0) OutlineLayer = i; else if (layerThing.name.compare("silk_top") == 0) SilkTopLayer = i; } QList refPanelItems; board = boards.firstChildElement("board"); if (!openWindows(board, fzzFilePaths, app, panelParams, fzDir, svgDir, refPanelItems, layerThingList, customPartsOnly, copyDir)) return; QList planePairs; QList insertPanelItems; int duplicates = bestFitLoop(refPanelItems, panelParams, customPartsOnly, planePairs, insertPanelItems, svgDir); foreach (PanelItem * panelItem, insertPanelItems) { if (panelItem->refPanelItem) { panelItem->refPanelItem->produced += duplicates; } } QString custom = customPartsOnly ? "custom." : ""; foreach (PlanePair * planePair, planePairs) { planePair->layoutSVG += ""; QString fname = svgDir.absoluteFilePath(QString("%1%2.panel_%3.layout.svg").arg(custom).arg(panelParams.prefix).arg(planePair->index)); TextUtils::writeUtf8(fname, planePair->layoutSVG); } foreach (PlanePair * planePair, planePairs) { for (int i = 0; i < layerThingList.count(); i++) { planePair->svgs << TextUtils::makeSVGHeader(1, GraphicsUtils::StandardFritzingDPI, planePair->panelWidth, planePair->panelHeight); } QList needToRotate; foreach (PanelItem * panelItem, insertPanelItems) { if (panelItem->planePair != planePair) continue; DebugDialog::debug(QString("placing %1 on panel %2").arg(panelItem->boardName).arg(planePair->index)); doOnePanelItem(planePair, layerThingList, panelItem, svgDir); } DebugDialog::debug("after placement"); QString prefix = QString("%1%2.panel_%3").arg(custom).arg(panelParams.prefix).arg(planePair->index); for (int i = 0; i < planePair->svgs.count(); i++) { if (planePair->svgs.at(i).isEmpty()) continue; planePair->svgs.replace(i, planePair->svgs.at(i) + ""); QString fname = svgDir.absoluteFilePath(QString("%1.%2.svg").arg(prefix).arg(layerThingList.at(i).name)); TextUtils::writeUtf8(fname, planePair->svgs.at(i)); QString suffix = layerThingList.at(i).suffix; DebugDialog::debug("converting " + prefix + " " + suffix); QSizeF svgSize(planePair->panelWidth, planePair->panelHeight); SVG2gerber::ForWhy forWhy = layerThingList.at(i).forWhy; if (forWhy == SVG2gerber::ForMask || forWhy == SVG2gerber::ForPasteMask) forWhy = SVG2gerber::ForCopper; GerberGenerator::doEnd(planePair->svgs.at(i), 2, layerThingList.at(i).name, forWhy, svgSize * GraphicsUtils::StandardFritzingDPI, gerberDir.absolutePath(), prefix, suffix, false); DebugDialog::debug("after converting " + prefix + " " + suffix); } QDomDocument doc; QString merger = planePair->svgs.at(OutlineLayer); merger.replace("black", "#90f0a0"); merger.replace("#000000", "#90f0a0"); merger.replace("fill-opacity=\"0.5\"", "fill-opacity=\"1\""); //DebugDialog::debug("outline identification"); //DebugDialog::debug(merger); //DebugDialog::debug(""); TextUtils::mergeSvg(doc, merger, ""); merger = planePair->svgs.at(SilkTopLayer); merger.replace("black", "#909090"); merger.replace("#000000", "#909090"); //DebugDialog::debug("silk identification"); //DebugDialog::debug(merger); //DebugDialog::debug(""); TextUtils::mergeSvg(doc, merger, ""); merger = planePair->layoutSVG; // layout merger.replace("'red'", "'none'"); // hide background rect //DebugDialog::debug("layout identification"); //DebugDialog::debug(merger); //DebugDialog::debug(""); TextUtils::mergeSvg(doc, merger, ""); merger = TextUtils::mergeSvgFinish(doc); int endix = merger.lastIndexOf(""); QString text = "%3 panel %4 %5 %6\n"; text = text .arg(planePair->panelWidth * GraphicsUtils::StandardFritzingDPI) .arg(planePair->panelHeight * GraphicsUtils::StandardFritzingDPI + (250 / 2)) .arg(outputDir.dirName()) .arg(planePair->index) .arg(panelParams.prefix) .arg(QTime::currentTime().toString()) ; merger.insert(endix, text); QString fname = svgDir.absoluteFilePath(QString("%1.%2.svg").arg(prefix).arg("identification")); TextUtils::writeUtf8(fname, merger); // save to pdf QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); QString pdfname = fname; pdfname.replace(".svg", ".pdf"); printer.setOutputFileName(pdfname); int res = printer.resolution(); // now convert to pdf QSvgRenderer svgRenderer; svgRenderer.load(merger.toLatin1()); double trueWidth = planePair->panelWidth; double trueHeight = planePair->panelHeight; QRectF target(0, 0, trueWidth * res, trueHeight * res); QSizeF psize((target.width() + printer.paperRect().width() - printer.width()) / res, (target.height() + printer.paperRect().height() - printer.height()) / res); printer.setPaperSize(psize, QPrinter::Inch); QPainter painter; if (painter.begin(&printer)) { svgRenderer.render(&painter, target); } painter.end(); } boards = panelizerRoot.firstChildElement("boards"); board = boards.firstChildElement("board"); while (!board.isNull()) { foreach (PanelItem * panelItem, refPanelItems) { if (panelItem->path.endsWith("/" + board.attribute("name"))) { board.setAttribute("produced", panelItem->produced); break; } } board = board.nextSiblingElement("board"); } TextUtils::writeUtf8(panelFilename, panelizerDocument.toString(4)); QString message = QString("Panelizer finished: %1 panel(s), with %2 additional copy(ies) for each panel").arg(planePairs.count()).arg(duplicates - 1); writePanelizerOutput("--------------------------------"); writePanelizerOutput(message); QMessageBox::information(NULL, QObject::tr("Fritzing"), message); } void Panelizer::bestFit(QList & insertPanelItems, PanelParams & panelParams, QList & planePairs, bool customPartsOnly) { foreach (PanelItem * panelItem, insertPanelItems) { bestFitOne(panelItem, panelParams, planePairs, true, customPartsOnly); } } bool Panelizer::bestFitOne(PanelItem * panelItem, PanelParams & panelParams, QList & planePairs, bool createNew, bool customPartsOnly) { //DebugDialog::debug(QString("panel %1").arg(panelItem->boardName)); BestPlace bestPlace1, bestPlace2; bestPlace1.rotate90 = bestPlace2.rotate90 = false; bestPlace1.width = bestPlace2.width = realToTile(panelItem->boardSizeInches.width() + panelParams.panelSpacing); bestPlace1.height = bestPlace2.height = realToTile(panelItem->boardSizeInches.height() + panelParams.panelSpacing); int ppix = 0; while (ppix < planePairs.count()) { PlanePair * planePair = planePairs.at(ppix); bestPlace1.plane = planePair->thePlane; bestPlace2.plane = planePair->thePlane90; bestPlace1.maxRect = planePair->tilePanelRect; TiSrArea(NULL, planePair->thePlane, &planePair->tilePanelRect, placeBestFit, &bestPlace1); if (customPartsOnly) { // make sure board is rotated bestPlace1.bestTile = NULL; DebugDialog::debug("forcing rotation"); } if (bestPlace1.bestTile == NULL) { bestPlace2.maxRect = planePair->tilePanelRect90; TiSrArea(NULL, planePair->thePlane90, &planePair->tilePanelRect90, placeBestFit, &bestPlace2); } if (bestPlace1.bestTile == NULL && bestPlace2.bestTile == NULL ) { if (++ppix < planePairs.count()) { // try next panel continue; } if (!createNew) { return false; } // create next panel planePair = makePlanePair(panelParams, true); planePairs << planePair; DebugDialog::debug(QString("ran out of room placing %1").arg(panelItem->boardName)); continue; } bool use2 = false; if (bestPlace1.bestTile == NULL) { use2 = true; } else if (bestPlace2.bestTile == NULL) { } else { // never actually get here use2 = bestPlace2.bestArea < bestPlace1.bestArea; } if (use2) { tileUnrotate90(bestPlace2.bestTileRect, bestPlace1.bestTileRect); bestPlace1.rotate90 = !bestPlace2.rotate90; } panelItem->x = tileToReal(bestPlace1.bestTileRect.xmini) ; panelItem->y = tileToReal(bestPlace1.bestTileRect.ymini); panelItem->rotate90 = bestPlace1.rotate90; DebugDialog::debug(QString("setting rotate90:%1 %2").arg(panelItem->rotate90).arg(panelItem->path)); panelItem->planePair = planePair; TileRect tileRect; tileRect.xmini = bestPlace1.bestTileRect.xmini; tileRect.ymini = bestPlace1.bestTileRect.ymini; if (bestPlace1.rotate90) { tileRect.xmaxi = tileRect.xmini + bestPlace1.height; tileRect.ymaxi = tileRect.ymini + bestPlace1.width; } else { tileRect.ymaxi = tileRect.ymini + bestPlace1.height; tileRect.xmaxi = tileRect.xmini + bestPlace1.width; } double w = panelItem->boardSizeInches.width(); double h = panelItem->boardSizeInches.height(); if (panelItem->rotate90) { w = h; h = panelItem->boardSizeInches.width(); } planePair->layoutSVG += QString("\n") .arg(panelItem->x * GraphicsUtils::StandardFritzingDPI) .arg(panelItem->y * GraphicsUtils::StandardFritzingDPI) .arg(GraphicsUtils::StandardFritzingDPI * w) .arg(GraphicsUtils::StandardFritzingDPI * h); QStringList strings = QFileInfo(panelItem->path).completeBaseName().split("_"); if (strings.count() >= 5) { QString start = strings.takeFirst(); QStringList middle; middle << strings.at(0) << strings.at(1) << strings.at(2); strings.removeAt(0); strings.removeAt(0); strings.removeAt(0); QString end = strings.join("_"); strings.clear(); strings << start << middle.join(" ") << end; } double cx = GraphicsUtils::StandardFritzingDPI * (panelItem->x + (w / 2)); int fontSize1 = 250; int fontSize2 = 150; int fontSize = fontSize1; double cy = GraphicsUtils::StandardFritzingDPI * (panelItem->y + (h / 2)); cy -= ((strings.count() - 1) * fontSize2 / 2); foreach (QString string, strings) { planePair->layoutSVG += QString("%4\n") .arg(cx) .arg(cy) .arg(fontSize) .arg(string) .arg(OCRAFontName); cy += fontSize; if (fontSize == fontSize1) fontSize = fontSize2; } TiInsertTile(planePair->thePlane, &tileRect, NULL, Tile::OBSTACLE); TileRect tileRect90; tileRotate90(tileRect, tileRect90); TiInsertTile(planePair->thePlane90, &tileRect90, NULL, Tile::OBSTACLE); return true; } DebugDialog::debug("bestFitOne should never reach here"); return false; } PlanePair * Panelizer::makePlanePair(PanelParams & panelParams, bool big) { PlanePair * planePair = new PlanePair; if (big) { foreach (PanelType * panelType, panelParams.panelTypes) { if (panelType->name == "big") { planePair->panelWidth = panelType->width; planePair->panelHeight = panelType->height; break; } } } else { foreach (PanelType * panelType, panelParams.panelTypes) { if (panelType->name == "small") { planePair->panelWidth = panelType->width; planePair->panelHeight = panelType->height; break; } } } // for debugging planePair->layoutSVG = TextUtils::makeSVGHeader(1, GraphicsUtils::StandardFritzingDPI, planePair->panelWidth, planePair->panelHeight); planePair->index = PlanePairIndex++; Tile * bufferTile = TiAlloc(); TiSetType(bufferTile, Tile::BUFFER); TiSetBody(bufferTile, NULL); QRectF panelRect(0, 0, planePair->panelWidth + panelParams.panelSpacing - panelParams.panelBorder, planePair->panelHeight + panelParams.panelSpacing - panelParams.panelBorder); int l = fasterRealToTile(panelRect.left() - 10); int t = fasterRealToTile(panelRect.top() - 10); int r = fasterRealToTile(panelRect.right() + 10); int b = fasterRealToTile(panelRect.bottom() + 10); SETLEFT(bufferTile, l); SETYMIN(bufferTile, t); planePair->thePlane = TiNewPlane(bufferTile, l, t, r, b); SETRIGHT(bufferTile, r); SETYMAX(bufferTile, b); qrectToTile(panelRect, planePair->tilePanelRect); TiInsertTile(planePair->thePlane, &planePair->tilePanelRect, NULL, Tile::SPACE); QMatrix matrix90; matrix90.rotate(90); QRectF panelRect90 = matrix90.mapRect(panelRect); Tile * bufferTile90 = TiAlloc(); TiSetType(bufferTile90, Tile::BUFFER); TiSetBody(bufferTile90, NULL); l = fasterRealToTile(panelRect90.left() - 10); t = fasterRealToTile(panelRect90.top() - 10); r = fasterRealToTile(panelRect90.right() + 10); b = fasterRealToTile(panelRect90.bottom() + 10); SETLEFT(bufferTile90, l); SETYMIN(bufferTile90, t); planePair->thePlane90 = TiNewPlane(bufferTile90, l, t, r, b); SETRIGHT(bufferTile90, r); SETYMAX(bufferTile90, b); qrectToTile(panelRect90, planePair->tilePanelRect90); TiInsertTile(planePair->thePlane90, &planePair->tilePanelRect90, NULL, Tile::SPACE); return planePair; } void Panelizer::collectFiles(const QDir & outputFolder, QDomElement & path, QHash & fzzFilePaths) { QList dirList; dirList << outputFolder; while (!path.isNull()) { QDomNode node = path.firstChild(); if (!node.isText()) { DebugDialog::debug(QString("missing text in element")); return; } QString p = node.nodeValue().trimmed(); DebugDialog::debug("p folder " + p); QString savep = p; if (savep.startsWith(".")) { p = outputFolder.absolutePath() + "/" + savep; } QDir dir(p); if (!dir.exists()) { DebugDialog::debug(QString("Directory '%1' doesn't exist").arg(p)); return; } dirList << dir; path = path.nextSiblingElement("path"); } foreach (QDir dir, dirList) { DebugDialog::debug("directory " + dir.absolutePath()); QStringList filepaths; QStringList filters("*" + FritzingBundleExtension); FolderUtils::collectFiles(dir, filters, filepaths, false); foreach (QString filepath, filepaths) { QFileInfo fileInfo(filepath); fzzFilePaths.insert(fileInfo.fileName(), filepath); } } } bool Panelizer::checkBoards(QDomElement & board, QHash & fzzFilePaths) { while (!board.isNull()) { QString boardname = board.attribute("name"); //DebugDialog::debug(QString("board %1").arg(boardname)); bool ok; int optional = board.attribute("maxOptionalCount", "").toInt(&ok); if (!ok) { writePanelizerOutput(QString("maxOptionalCount for board '%1' not an integer: '%2'").arg(boardname).arg(board.attribute("maxOptionalCount"))); return false; } int optionalPriority = board.attribute("optionalPriority", "").toInt(&ok); Q_UNUSED(optionalPriority); if (!ok) { writePanelizerOutput(QString("optionalPriority for board '%1' not an integer: '%2'").arg(boardname).arg(board.attribute("optionalPriority"))); return false; } int required = board.attribute("requiredCount", "").toInt(&ok); if (!ok) { writePanelizerOutput(QString("required for board '%1' not an integer: '%2'").arg(boardname).arg(board.attribute("maxOptionalCount"))); return false; } if (optional > 0 || required> 0) { QString path = fzzFilePaths.value(boardname, ""); if (path.isEmpty()) { writePanelizerOutput(QString("File for board '%1' not found in search paths").arg(boardname)); return false; } } else { writePanelizerOutput(QString("skipping board '%1'").arg(boardname)); } board = board.nextSiblingElement("board"); } return true; } bool Panelizer::openWindows(QDomElement & boardElement, QHash & fzzFilePaths, FApplication * app, PanelParams & panelParams, QDir & fzDir, QDir & svgDir, QList & refPanelItems, QList & layerThingList, bool customPartsOnly, QDir & copyDir) { QDir rotateDir(svgDir); QDir norotateDir(svgDir); rotateDir.mkdir("rotate"); rotateDir.cd("rotate"); norotateDir.mkdir("norotate"); norotateDir.cd("norotate"); PanelType * bigPanelType = NULL; foreach (PanelType * panelType, panelParams.panelTypes) { if (panelType->name == "big") { bigPanelType = panelType; break; } } if (bigPanelType == NULL) { writePanelizerOutput("No panel types defined"); return false; } while (!boardElement.isNull()) { int required = boardElement.attribute("requiredCount", "").toInt(); int optional = boardElement.attribute("maxOptionalCount", "").toInt(); int priority = boardElement.attribute("optionalPriority", "").toInt(); if (customPartsOnly) { optional = 0; if (required > 1) required = 1; } if (required == 0 && optional == 0) { boardElement = boardElement.nextSiblingElement("board"); continue; } QString boardName = boardElement.attribute("name"); QString originalPath = fzzFilePaths.value(boardName, ""); QFileInfo originalInfo(originalPath); QString copyPath = copyDir.absoluteFilePath(boardName); QFileInfo copyInfo(copyPath); if (!copyInfo.exists()) { writePanelizerOutput(QString("failed to load copy'%1'").arg(copyPath)); return false; } if (!originalInfo.exists()) { writePanelizerOutput(QString("failed to find original'%1'").arg(originalPath)); return false; } if (originalInfo.lastModified() > copyInfo.lastModified()) { writePanelizerOutput(QString("copy %1 is not up to date--rerun the inscriber").arg(copyPath)); return false; } MainWindow * mainWindow = app->openWindowForService(false, 3); mainWindow->setCloseSilently(true); FolderUtils::setOpenSaveFolderAux(fzDir.absolutePath()); if (!mainWindow->loadWhich(copyPath, false, false, false, "")) { writePanelizerOutput(QString("failed to load '%1'").arg(copyPath)); return false; } if (customPartsOnly && !mainWindow->hasAnyAlien() && !mainWindow->hasCustomBoardShape() && (mainWindow->pcbView()->checkLoadedTraces() == 0) && (checkDonuts(mainWindow, false) == 0) && (checkText(mainWindow, false) == 0) ) { mainWindow->close(); delete mainWindow, boardElement = boardElement.nextSiblingElement("board"); continue; } foreach (QGraphicsItem * item, mainWindow->pcbView()->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBase->setMoveLock(false); } QList boards = mainWindow->pcbView()->findBoard(); foreach (ItemBase * boardItem, boards) { PanelItem * panelItem = new PanelItem; panelItem->boardName = boardName; panelItem->path = originalPath; panelItem->required = required; panelItem->maxOptional = optional; panelItem->optionalPriority = priority; panelItem->boardID = boardItem->id(); QRectF sbr = boardItem->layerKinChief()->sceneBoundingRect(); panelItem->boardSizeInches = sbr.size() / GraphicsUtils::SVGDPI; DebugDialog::debug(QString("board size inches c %1, %2, %3") .arg(panelItem->boardSizeInches.width()) .arg(panelItem->boardSizeInches.height()) .arg(copyPath)); /* QSizeF boardSize = boardItem->size(); ResizableBoard * resizableBoard = qobject_cast(boardItem->layerKinChief()); if (resizableBoard != NULL) { panelItem->boardSizeInches = resizableBoard->getSizeMM() / 25.4; DebugDialog::debug(QString("board size inches a %1, %2, %3") .arg(panelItem->boardSizeInches.width()) .arg(panelItem->boardSizeInches.height()) .arg(path), boardItem->sceneBoundingRect()); } else { panelItem->boardSizeInches = boardSize / GraphicsUtils::SVGDPI; DebugDialog::debug(QString("board size inches b %1, %2, %3") .arg(panelItem->boardSizeInches.width()) .arg(panelItem->boardSizeInches.height()) .arg(path), boardItem->sceneBoundingRect()); } */ bool tooBig = false; if (panelItem->boardSizeInches.width() >= bigPanelType->width) { tooBig = panelItem->boardSizeInches.width() >= bigPanelType->height; if (!tooBig) { tooBig = panelItem->boardSizeInches.height() >= bigPanelType->width; } } if (!tooBig) { if (panelItem->boardSizeInches.height() >= bigPanelType->height) { tooBig = panelItem->boardSizeInches.height() >= bigPanelType->width; if (!tooBig) { tooBig = panelItem->boardSizeInches.width() >= bigPanelType->height; } } } if (tooBig) { writePanelizerOutput(QString("board is too big for panel '%1'").arg(originalPath)); return false; } makeSVGs(mainWindow, boardItem, boardName, layerThingList, norotateDir, copyInfo); refPanelItems << panelItem; } // now save the rotated version mainWindow->pcbView()->selectAllItems(true, false); QMatrix matrix; mainWindow->pcbView()->rotateX(90, false, NULL); foreach (ItemBase * boardItem, boards) { makeSVGs(mainWindow, boardItem, boardName, layerThingList, rotateDir, copyInfo); } mainWindow->close(); delete mainWindow, boardElement = boardElement.nextSiblingElement("board"); } return true; } bool Panelizer::initPanelParams(QDomElement & root, PanelParams & panelParams) { panelParams.prefix = root.attribute("prefix"); if (panelParams.prefix.isEmpty()) { writePanelizerOutput(QString("Output file prefix not specified")); return false; } QDomElement panels = root.firstChildElement("panels"); QDomElement panel = panels.firstChildElement("panel"); while (!panel.isNull()) { PanelType * panelType = new PanelType; panelType->name = panel.attribute("name"); bool ok; panelType->width = TextUtils::convertToInches(panel.attribute("width"), &ok, false); if (!ok) { writePanelizerOutput(QString("Can't parse panel width '%1'").arg(panel.attribute("width"))); return false; } panelType->height = TextUtils::convertToInches(panel.attribute("height"), &ok, false); if (!ok) { writePanelizerOutput(QString("Can't parse panel height '%1'").arg(panel.attribute("height"))); return false; } panelType->c1 = panel.attribute("c1").toDouble(&ok); if (!ok) { writePanelizerOutput(QString("Can't parse panel c1 '%1'").arg(panel.attribute("c1"))); return false; } panelType->c2 = panel.attribute("c2").toDouble(&ok); if (!ok) { writePanelizerOutput(QString("Can't parse panel c2 '%1'").arg(panel.attribute("c2"))); return false; } panelParams.panelTypes << panelType; panel = panel.nextSiblingElement("panel"); } if (panelParams.panelTypes.count() == 0) { writePanelizerOutput(QString("No panel types defined.")); return false; } bool ok; panelParams.panelSpacing = TextUtils::convertToInches(root.attribute("spacing"), &ok, false); if (!ok) { writePanelizerOutput(QString("Can't parse panel spacing '%1'").arg(root.attribute("spacing"))); return false; } panelParams.panelBorder = TextUtils::convertToInches(root.attribute("border"), &ok, false); if (!ok) { writePanelizerOutput(QString("Can't parse panel border '%1'").arg(root.attribute("border"))); return false; } return true; } int Panelizer::placeBestFit(Tile * tile, UserData userData) { if (TiGetType(tile) != Tile::SPACE) return 0; BestPlace * bestPlace = (BestPlace *) userData; TileRect tileRect; TiToRect(tile, &tileRect); int w = tileRect.xmaxi - tileRect.xmini; int h = tileRect.ymaxi - tileRect.ymini; if (bestPlace->width > w && bestPlace->height > w) { return 0; } int fitCount = 0; bool fit[4]; double area[4]; for (int i = 0; i < 4; i++) { fit[i] = false; area[i] = Worst; } if (w >= bestPlace->width && h >= bestPlace->height) { fit[0] = true; area[0] = (w * h) - (bestPlace->width * bestPlace->height); fitCount++; } if (h >= bestPlace->width && w >= bestPlace->height) { fit[1] = true; area[1] = (w * h) - (bestPlace->width * bestPlace->height); fitCount++; } if (!fit[0] && w >= bestPlace->width) { // see if adjacent tiles below are open TileRect temp; temp.xmini = tileRect.xmini; temp.xmaxi = temp.xmini + bestPlace->width; temp.ymini = tileRect.ymini; temp.ymaxi = temp.ymini + bestPlace->height; if (temp.ymaxi < bestPlace->maxRect.ymaxi) { QList spaces; TiSrArea(tile, bestPlace->plane, &temp, allSpaces, &spaces); if (spaces.count()) { int y = temp.ymaxi; foreach (Tile * t, spaces) { if (YMAX(t) > y) y = YMAX(t); // find the bottom of the lowest open tile } fit[2] = true; fitCount++; area[2] = (w * (y - temp.ymini)) - (bestPlace->width * bestPlace->height); } } } if (!fit[1] && w >= bestPlace->height) { // see if adjacent tiles below are open TileRect temp; temp.xmini = tileRect.xmini; temp.xmaxi = temp.xmini + bestPlace->height; temp.ymini = tileRect.ymini; temp.ymaxi = temp.ymini + bestPlace->width; if (temp.ymaxi < bestPlace->maxRect.ymaxi) { QList spaces; TiSrArea(tile, bestPlace->plane, &temp, allSpaces, &spaces); if (spaces.count()) { int y = temp.ymaxi; foreach (Tile * t, spaces) { if (YMAX(t) > y) y = YMAX(t); // find the bottom of the lowest open tile } fit[3] = true; fitCount++; area[3] = (w * (y - temp.ymini)) - (bestPlace->width * bestPlace->height); } } } if (fitCount == 0) return 0; // area is white space remaining after board has been inserteds int result = -1; for (int i = 0; i < 4; i++) { if (area[i] < bestPlace->bestArea) { result = i; break; } } if (result < 0) return 0; // current bestArea is better bestPlace->bestTile = tile; bestPlace->bestTileRect = tileRect; if (fitCount == 1 || (bestPlace->width == bestPlace->height)) { if (fit[0] || fit[2]) { bestPlace->rotate90 = false; } else { bestPlace->rotate90 = true; } bestPlace->bestArea = area[result]; return 0; } if (TiGetType(BL(tile)) == Tile::BUFFER) { // this is a leftmost tile // select for creating the biggest area after putting in the tile; double a1 = (w - bestPlace->width) * (bestPlace->height); double a2 = (h - bestPlace->height) * w; double a = qMax(a1, a2); double b1 = (w - bestPlace->height) * (bestPlace->width); double b2 = (h - bestPlace->width) * w; double b = qMax(b1, b2); bestPlace->rotate90 = (a < b); if (bestPlace->rotate90) { bestPlace->bestArea = fit[1] ? area[1] : area[3]; } else { bestPlace->bestArea = fit[0] ? area[0] : area[2]; } return 0; } TileRect temp; temp.xmini = bestPlace->maxRect.xmini; temp.xmaxi = tileRect.xmini - 1; temp.ymini = tileRect.ymini; temp.ymaxi = tileRect.ymaxi; QList obstacles; TiSrArea(tile, bestPlace->plane, &temp, allObstacles, &obstacles); int maxBottom = 0; foreach (Tile * obstacle, obstacles) { if (YMAX(obstacle) > maxBottom) maxBottom = YMAX(obstacle); } if (tileRect.ymini + bestPlace->width <= maxBottom && tileRect.ymini + bestPlace->height <= maxBottom) { // use the max length if (bestPlace->width >= bestPlace->height) { bestPlace->rotate90 = true; bestPlace->bestArea = fit[1] ? area[1] : area[3]; } else { bestPlace->rotate90 = false; bestPlace->bestArea = fit[0] ? area[0] : area[2]; } return 0; } if (tileRect.ymini + bestPlace->width > maxBottom && tileRect.ymini + bestPlace->height > maxBottom) { // use the min length if (bestPlace->width <= bestPlace->height) { bestPlace->rotate90 = true; bestPlace->bestArea = fit[1] ? area[1] : area[3]; } else { bestPlace->rotate90 = false; bestPlace->bestArea = fit[0] ? area[0] : area[2]; } return 0; } if (tileRect.ymini + bestPlace->width <= maxBottom) { bestPlace->rotate90 = true; bestPlace->bestArea = fit[1] ? area[1] : area[3]; return 0; } bestPlace->rotate90 = false; bestPlace->bestArea = fit[0] ? area[0] : area[2]; return 0; } void Panelizer::addOptional(int optionalCount, QList & refPanelItems, QList & insertPanelItems, PanelParams & panelParams, QList & planePairs) { if (optionalCount == 0) return; QList copies(refPanelItems); qSort(copies.begin(), copies.end(), byOptionalPriority); while (optionalCount > 0) { int pool = 0; int priority = -1; foreach(PanelItem * panelItem, copies) { if (panelItem->maxOptional > 0) { if (priority == -1) priority = panelItem->optionalPriority; if (panelItem->optionalPriority == priority) { pool += panelItem->maxOptional; } else break; } } if (pool == 0) break; int ix = qFloor(qrand() * pool / (double) RAND_MAX); int soFar = 0; foreach (PanelItem * panelItem, copies) { if (panelItem->maxOptional == 0) continue; if (panelItem->optionalPriority != priority) continue; if (ix >= soFar && ix < soFar + panelItem->maxOptional) { PanelItem * copy = new PanelItem(panelItem); if (bestFitOne(copy, panelParams, planePairs, false, false)) { // got one panelItem->maxOptional--; optionalCount--; insertPanelItems.append(copy); } else { // don't bother trying this one again optionalCount -= panelItem->maxOptional; panelItem->maxOptional = 0; } break; } soFar += panelItem->maxOptional; } } } ///////////////////////////////////////////////////////////////////////////////// void Panelizer::inscribe(FApplication * app, const QString & panelFilename, bool drc, bool noMessages) { initPanelizerOutput(panelFilename, "inscribe"); QFile file(panelFilename); QFileInfo info(panelFilename); QDir copyDir = info.absoluteDir(); copyDir.mkdir("copies"); copyDir.cd("copies"); if (!copyDir.exists()) { DebugDialog::debug(QString("unable to create 'copies' folder in '%1'").arg(info.absoluteDir().absolutePath())); return; } QString errorStr; int errorLine; int errorColumn; DebugDialog::setEnabled(true); QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { writePanelizerOutput(QString("Unable to parse '%1': '%2' line:%3 column:%4").arg(panelFilename).arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); if (root.isNull() || root.tagName() != "panelizer") { writePanelizerOutput(QString("root element is not 'panelizer'")); return; } PanelParams panelParams; if (!initPanelParams(root, panelParams)) return; QDir outputDir = QDir::temp(); QDir fzDir(outputDir); fzDir.cd("fz"); if (!fzDir.exists()) { writePanelizerOutput(QString("unable to create fz folder in '%1'").arg(outputDir.absolutePath())); return; } DebugDialog::debug(QString("fz folder '%1'\n").arg(fzDir.absolutePath())); QDomElement boards = root.firstChildElement("boards"); QDomElement board = boards.firstChildElement("board"); if (board.isNull()) { writePanelizerOutput(QString("no elements found")); return; } QHash fzzFilePaths; QDomElement paths = root.firstChildElement("paths"); QDomElement path = paths.firstChildElement("path"); if (path.isNull()) { writePanelizerOutput(QString("no elements found")); return; } QFileInfo pinfo(panelFilename); collectFiles(pinfo.absoluteDir(), path, fzzFilePaths); if (fzzFilePaths.count() == 0) { writePanelizerOutput(QString("no fzz files found in paths")); return; } board = boards.firstChildElement("board"); if (!checkBoards(board, fzzFilePaths)) return; app->createUserDataStoreFolderStructure(); app->registerFonts(); app->loadReferenceModel("", false); board = boards.firstChildElement("board"); while (!board.isNull()) { MainWindow * mainWindow = inscribeBoard(board, fzzFilePaths, app, fzDir, drc, noMessages, copyDir); if (mainWindow) { mainWindow->setCloseSilently(true); mainWindow->close(); delete mainWindow; } board = board.nextSiblingElement("board"); } writePanelizerFilenames(panelFilename); // TODO: delete temp fz folder } MainWindow * Panelizer::inscribeBoard(QDomElement & board, QHash & fzzFilePaths, FApplication * app, QDir & fzDir, bool drc, bool noMessages, QDir & copyDir) { QString boardName = board.attribute("name"); int optional = board.attribute("maxOptionalCount", "").toInt(); int required = board.attribute("requiredCount", "").toInt(); if (optional <= 0 && required <= 0) return NULL; QString originalPath = fzzFilePaths.value(boardName, ""); QFileInfo originalInfo(originalPath); QString copyPath = copyDir.absoluteFilePath(originalInfo.fileName()); QFileInfo copyInfo(copyPath); if (!copyInfo.exists()) { } else { DebugDialog::debug(""); //DebugDialog::debug(oldPath); //DebugDialog::debug(copyPath); DebugDialog::debug(QString("%1 original=%2, copy=%3").arg(originalInfo.fileName()).arg(originalInfo.lastModified().toString()).arg(copyInfo.lastModified().toString())); if (originalInfo.lastModified() <= copyInfo.lastModified()) { DebugDialog::debug(QString("copy %1 is up to date").arg(copyPath)); return NULL; } } QFile file(originalPath); bool ok = FolderUtils::slamCopy(file, copyPath); if (!ok) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("unable to copy file '%1' to '%2'.").arg(originalPath).arg(copyPath)); return NULL; } MainWindow * mainWindow = app->openWindowForService(false, 3); FolderUtils::setOpenSaveFolderAux(fzDir.absolutePath()); if (!mainWindow->loadWhich(copyPath, false, false, false, "")) { writePanelizerOutput(QString("failed to load '%1'").arg(copyPath)); return mainWindow; } // performance optimization mainWindow->pcbView()->setGridSize("0.1in"); mainWindow->pcbView()->showGrid(false); QList items = mainWindow->pcbView()->selectAllObsolete(); if (items.count() > 0) { QFileInfo info(copyPath); writePanelizerOutput(QString("%2 ... %1 obsolete items").arg(items.count()).arg(info.fileName())); } int moved = mainWindow->pcbView()->checkLoadedTraces(); if (moved > 0) { QFileInfo info(originalPath); QString message = QObject::tr("%2 ... %1 wires moved from their saved position").arg(moved).arg(info.fileName()); if (!noMessages) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), message); } writePanelizerOutput(message); collectFilenames(info.fileName()); } foreach (QGraphicsItem * item, mainWindow->pcbView()->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBase->setMoveLock(false); } QString fritzingVersion = mainWindow->fritzingVersion(); VersionThing versionThing; versionThing.majorVersion = 0; versionThing.minorVersion = 7; versionThing.minorSubVersion = 0; versionThing.releaseModifier = ""; VersionThing versionThingFz; Version::toVersionThing(fritzingVersion, versionThingFz); bool oldGround = !Version::greaterThan(versionThing, versionThingFz); bool filled = false; QList boards = mainWindow->pcbView()->findBoard(); bool wasOne = false; foreach (ItemBase * boardItem, boards) { mainWindow->pcbView()->selectAllItems(false, false); boardItem->setSelected(true); if (boardItem->prop("layers").compare("1") == 0) { mainWindow->swapLayers(boardItem, 2, "", 0); ProcessEventBlocker::processEvents(); wasOne = true; } LayerList groundLayers; groundLayers << ViewLayer::GroundPlane0 << ViewLayer::GroundPlane1; foreach (ViewLayer::ViewLayerID viewLayerID, groundLayers) { QString fillType = mainWindow->pcbView()->characterizeGroundFill(viewLayerID); if (fillType == GroundPlane::fillTypeNone) { mainWindow->copperFill(viewLayerID); ProcessEventBlocker::processEvents(); filled = true; } else if ((fillType == GroundPlane::fillTypeGround) && oldGround) { mainWindow->groundFill(viewLayerID); ProcessEventBlocker::processEvents(); filled = true; } } } if (filled) { mainWindow->saveAsShareable(copyPath, true); DebugDialog::debug(QString("%1 filled:%2").arg(copyPath).arg(filled)); } checkDonuts(mainWindow, !noMessages); checkText(mainWindow, !noMessages); if (drc) { foreach (ItemBase * boardItem, boards) { mainWindow->pcbView()->resetKeepout(); mainWindow->pcbView()->selectAllItems(false, false); boardItem->setSelected(true); QStringList messages = mainWindow->newDesignRulesCheck(false); if (messages.count() > 0) { QFileInfo info(mainWindow->fileName()); writePanelizerOutput(QString("%2 ... %1 drc complaints").arg(messages.count()).arg(info.fileName())); collectFilenames(info.fileName()); //foreach (QString message, messages) { // writePanelizerOutput("\t" + message); //} } } } return mainWindow; } void Panelizer::makeSVGs(MainWindow * mainWindow, ItemBase * board, const QString & boardName, QList & layerThingList, QDir & saveDir, QFileInfo & copyInfo) { try { QString maskTop; QString maskBottom; QStringList texts; QMultiHash treatAsCircle; bool needsRedo = false; int missing = 0; foreach (LayerThing layerThing, layerThingList) { QString name = layerThing.name; QString filename = saveDir.absoluteFilePath(QString("%1_%2_%3.svg").arg(boardName).arg(board->id()).arg(name)); QFileInfo info(filename); if (info.exists()) { if (info.lastModified() <= copyInfo.lastModified()) { // need to save these files again needsRedo = true; break; } } else { missing++; } } if (!needsRedo) { if (missing < layerThingList.count()) { // assume some number of missing files wouldn't have been written out anyway // but if all are missing, then they were never written in the first place return; } } foreach (LayerThing layerThing, layerThingList) { QString name = layerThing.name; QString filename = saveDir.absoluteFilePath(QString("%1_%2_%3.svg").arg(boardName).arg(board->id()).arg(name)); SVG2gerber::ForWhy forWhy = layerThing.forWhy; QList copperLogoItems, holes; switch (forWhy) { case SVG2gerber::ForPasteMask: mainWindow->pcbView()->hideHoles(holes); case SVG2gerber::ForMask: mainWindow->pcbView()->hideCopperLogoItems(copperLogoItems); default: break; } RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString one = mainWindow->pcbView()->renderToSVG(renderThing, board, layerThing.layerList); QString clipString; bool wantText = false; switch (forWhy) { case SVG2gerber::ForOutline: one = GerberGenerator::cleanOutline(one); break; case SVG2gerber::ForPasteMask: mainWindow->pcbView()->restoreCopperLogoItems(copperLogoItems); mainWindow->pcbView()->restoreCopperLogoItems(holes); one = mainWindow->pcbView()->makePasteMask(one, board, GraphicsUtils::StandardFritzingDPI, layerThing.layerList); if (one.isEmpty()) continue; forWhy = SVG2gerber::ForCopper; break; case SVG2gerber::ForMask: mainWindow->pcbView()->restoreCopperLogoItems(copperLogoItems); one = TextUtils::expandAndFill(one, "black", GerberGenerator::MaskClearanceMils * 2); forWhy = SVG2gerber::ForCopper; if (name.contains("bottom")) { maskBottom = one; } else { maskTop = one; } break; case SVG2gerber::ForSilk: wantText = true; if (name.contains("bottom")) { clipString = maskBottom; } else { clipString = maskTop; } break; case SVG2gerber::ForCopper: case SVG2gerber::ForDrill: treatAsCircle.clear(); foreach (QGraphicsItem * item, mainWindow->pcbView()->scene()->collidingItems(board)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->isPath()) continue; if (connectorItem->radius() == 0) continue; treatAsCircle.insert(connectorItem->attachedToID(), connectorItem); } wantText = true; break; default: wantText = true; break; } if (wantText) { collectTexts(one, texts); //DebugDialog::debug("one " + one); } QString two = GerberGenerator::clipToBoard(one, board, name, forWhy, clipString, true, treatAsCircle); treatAsCircle.clear(); if (two.isEmpty()) continue; TextUtils::writeUtf8(filename, two); } if (texts.count() > 0) { QString filename = saveDir.absoluteFilePath(QString("%1_%2_%3.txt").arg(boardName).arg(board->id()).arg("texts")); TextUtils::writeUtf8(filename, texts.join("\n")); } } catch (const char * msg) { DebugDialog::debug(QString("panelizer error 1 %1 %2").arg(boardName).arg(msg)); } catch (const QString & msg) { DebugDialog::debug(QString("panelizer error 2 %1 %2").arg(boardName).arg(msg)); } catch (...) { DebugDialog::debug(QString("panelizer error 3 %1").arg(boardName)); } } void Panelizer::doOnePanelItem(PlanePair * planePair, QList & layerThingList, PanelItem * panelItem, QDir & svgDir) { try { for (int i = 0; i < planePair->svgs.count(); i++) { QString name = layerThingList.at(i).name; QString rot = panelItem->rotate90 ? "rotate" : "norotate"; QString filename = svgDir.absoluteFilePath(QString("%1/%2_%3_%4.svg").arg(rot).arg(panelItem->boardName).arg(panelItem->boardID).arg(name)); QFile file(filename); if (file.open(QFile::ReadOnly)) { QString one = file.readAll(); if (one.isEmpty()) continue; int left = one.indexOf("", left + 1); int right = one.lastIndexOf("<"); one = QString("\n").arg(panelItem->x * GraphicsUtils::StandardFritzingDPI).arg(panelItem->y * GraphicsUtils::StandardFritzingDPI) + one.mid(left + 1, right - left - 1) + "\n"; planePair->svgs.replace(i, planePair->svgs.at(i) + one); } else { DebugDialog::debug(QString("panelizer error? 1 %1 %2").arg(filename).arg("one text not found")); } } } catch (const char * msg) { DebugDialog::debug(QString("panelizer error 1 %1 %2").arg(panelItem->boardName).arg(msg)); } catch (const QString & msg) { DebugDialog::debug(QString("panelizer error 2 %1 %2").arg(panelItem->boardName).arg(msg)); } catch (...) { DebugDialog::debug(QString("panelizer error 3 %1").arg(panelItem->boardName)); } } void Panelizer::shrinkLastPanel( QList & planePairs, QList & insertPanelItems, PanelParams & panelParams, bool customPartsOnly) { PlanePair * lastPlanePair = planePairs.last(); PlanePair * smallPlanePair = makePlanePair(panelParams, false); smallPlanePair->index = lastPlanePair->index; QList smallPlanePairs; smallPlanePairs << smallPlanePair; bool canFitSmaller = true; QList smallPanelItems; foreach (PanelItem * panelItem, insertPanelItems) { if (panelItem->planePair != lastPlanePair) continue; PanelItem * copy = new PanelItem(panelItem); smallPanelItems << copy; if (!bestFitOne(copy, panelParams, smallPlanePairs, false, customPartsOnly)) { canFitSmaller = false; } } if (canFitSmaller) { foreach (PanelItem * panelItem, insertPanelItems) { if (panelItem->planePair != lastPlanePair) continue; insertPanelItems.removeOne(panelItem); delete panelItem; } planePairs.removeOne(lastPlanePair); delete lastPlanePair; insertPanelItems.append(smallPanelItems); planePairs.append(smallPlanePair); } else { foreach (PanelItem * copy, smallPanelItems) { delete copy; } delete smallPlanePair; } } int Panelizer::checkText(MainWindow * mainWindow, bool displayMessage) { QHash svgHash; QList missing; foreach (QGraphicsItem * item, mainWindow->pcbView()->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isEverVisible()) continue; double factor; QString itemSvg = itemBase->retrieveSvg(itemBase->viewLayerID(), svgHash, false, GraphicsUtils::StandardFritzingDPI, factor); if (itemSvg.isEmpty()) continue; QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(itemSvg, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("itembase svg failure %1").arg(itemBase->id())); continue; } QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName("path"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement textElement = domNodeList.at(i).toElement(); if (textElement.attribute("fill").isEmpty() && textElement.attribute("stroke").isEmpty() && textElement.attribute("stroke-width").isEmpty()) { missing.append(itemBase); break; } } } if (displayMessage && missing.count() > 0) { mainWindow->pcbView()->selectAllItems(false, false); mainWindow->pcbView()->selectItems(missing); QMessageBox::warning(NULL, "Text", QString("There are %1 possible instances of parts with elements missing stroke/fill/stroke-width attributes").arg(missing.count())); } if (missing.count() > 0) { QFileInfo info(mainWindow->fileName()); writePanelizerOutput(QString("%2 ... There are %1 possible instances of parts with elements missing stroke/fill/stroke-width attributes") .arg(missing.count()).arg(info.fileName()) ); collectFilenames(info.fileName()); } return missing.count(); } int Panelizer::checkDonuts(MainWindow * mainWindow, bool displayMessage) { QList donuts; foreach (QGraphicsItem * item, mainWindow->pcbView()->scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->attachedTo()->isEverVisible()) continue; if (connectorItem->isPath() && connectorItem->getCrossLayerConnectorItem() != NULL) { // && connectorItem->radius() == 0 connectorItem->debugInfo("possible donut"); connectorItem->attachedTo()->debugInfo("\t"); donuts << connectorItem; } } if (displayMessage && donuts.count() > 0) { mainWindow->pcbView()->selectAllItems(false, false); QSet itemBases; foreach (ConnectorItem * connectorItem, donuts) { itemBases.insert(connectorItem->attachedTo()); } mainWindow->pcbView()->selectItems(itemBases.toList()); QMessageBox::warning(NULL, "Donuts", QString("There are %1 possible donut connectors").arg(donuts.count() / 2)); } if (donuts.count() > 0) { QFileInfo info(mainWindow->fileName()); writePanelizerOutput(QString("%2 ... %1 possible donuts").arg(donuts.count() / 2).arg(info.fileName())); collectFilenames(mainWindow->fileName()); } return donuts.count() / 2; } int Panelizer::bestFitLoop(QList & refPanelItems, PanelParams & panelParams, bool customPartsOnly, QList & returnPlanePairs, QList & returnInsertPanelItems, const QDir & svgDir) { int optionalCount = 0; foreach (PanelItem * panelItem, refPanelItems) { optionalCount += panelItem->maxOptional; } QDir intermediates(svgDir); intermediates.mkdir("intermediates"); intermediates.cd("intermediates"); double bestCost = 0; double bestDivisor = 1; bool firstTime = true; for (int divisor = 1; true; divisor++) { QList planePairs; QList insertPanelItems; PlanePairIndex = 0; // reset to zero for each new list of PlanePairs bool stillMoreThanOne = false; foreach (PanelItem * panelItem, refPanelItems) { int count = (panelItem->required + divisor - 1) / divisor; if (count > 1) stillMoreThanOne = true; for (int i = 0; i < count; i++) { PanelItem * copy = new PanelItem(panelItem); insertPanelItems.append(copy); } } planePairs << makePlanePair(panelParams, true); qSort(insertPanelItems.begin(), insertPanelItems.end(), areaGreaterThan); bestFit(insertPanelItems, panelParams, planePairs, customPartsOnly); shrinkLastPanel(planePairs, insertPanelItems, panelParams, customPartsOnly); double cost = calcCost(panelParams, planePairs, divisor); foreach (PlanePair * planePair, planePairs) { planePair->layoutSVG += ""; QString fname = intermediates.absoluteFilePath(QString("%3.divisor_%4.cost_%1.panel_%2.layout_.svg") .arg(panelParams.prefix).arg(planePair->index).arg(divisor).arg(cost) ); TextUtils::writeUtf8(fname, planePair->layoutSVG); // make sure to leave layoutSVG without a trailing since optionals are added later planePair->layoutSVG.chop(6); } DebugDialog::debug(""); DebugDialog::debug(QString("%1 panels, %2 additional copies of each: cost %3").arg(planePairs.count()).arg(divisor - 1).arg(cost)); DebugDialog::debug(""); if (firstTime) { bestCost = cost; bestDivisor = 1; returnPlanePairs = planePairs; returnInsertPanelItems = insertPanelItems; firstTime = false; } else { if (cost < bestCost) { bestCost = cost; bestDivisor = divisor; foreach (PlanePair * planePair, returnPlanePairs) { delete planePair; } foreach (PanelItem * panelItem, returnInsertPanelItems) { delete panelItem; } returnPlanePairs.clear(); returnInsertPanelItems.clear(); returnPlanePairs = planePairs; returnInsertPanelItems = insertPanelItems; } } if (customPartsOnly) break; if (planePairs.count() == 1) break; if (!stillMoreThanOne) break; } addOptional(optionalCount, refPanelItems, returnInsertPanelItems, panelParams, returnPlanePairs); return bestDivisor; } double Panelizer::calcCost(PanelParams & panelParams, QList & planePairs, int divisor) { double total = 0; foreach (PlanePair * planePair, planePairs) { foreach (PanelType * panelType, panelParams.panelTypes) { if (planePair->panelWidth == panelType->width && planePair->panelHeight == panelType->height) { total += panelType->c1; total += panelType->c2 * (divisor - 1); break; } } } return total; } void Panelizer::writePanelizerOutput(const QString & message) { DebugDialog::debug(message); if (PanelizerOutputPath.length() > 0) { QFile file(PanelizerOutputPath); if (file.open(QFile::Append)) { QTextStream out(&file); out.setCodec("UTF-8"); out << message << "\n"; file.close(); } } } void Panelizer::initPanelizerOutput(const QString & panelFilename, const QString & msg) { PanelizerFileNames.clear(); QFileInfo info(panelFilename); PanelizerOutputPath = info.absoluteDir().absoluteFilePath("panelizer_output.txt"); QDateTime dt = QDateTime::currentDateTime(); writePanelizerOutput(QString("\n--------- %1 --- %2 ---") .arg(msg).arg(dt.toString()) ); } void Panelizer::collectFilenames(const QString & filename) { if (filename.endsWith(".fz")) { PanelizerFileNames.insert(filename + "z"); } else PanelizerFileNames.insert(filename); } void Panelizer::writePanelizerFilenames(const QString & panelFilename) { if (PanelizerFileNames.count() == 0) return; QFileInfo info(panelFilename); QDateTime dt = QDateTime::currentDateTime(); QString path = info.absoluteDir().absoluteFilePath("panelizer_files_%1.txt").arg(dt.toString().replace(":", ".")); QFile file(path); if (file.open(QFile::WriteOnly)) { QTextStream out(&file); out.setCodec("UTF-8"); foreach (QString name, PanelizerFileNames) { out << name << "\n"; } file.close(); } } fritzing-app-0.9.2b/src/autoroute/panelizer.h000066400000000000000000000117641250202676700212760ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6968 $: $Author: irascibl@gmail.com $: $Date: 2013-04-15 17:44:14 +0200 (Mo, 15. Apr 2013) $ ********************************************************************/ #ifndef PANELIZER_H #define PANELIZER_H #include #include #include "../mainwindow/mainwindow.h" #include "../items/itembase.h" #include "cmrouter/tile.h" struct PlanePair { Plane * thePlane; Plane * thePlane90; TileRect tilePanelRect; TileRect tilePanelRect90; double panelWidth; double panelHeight; QStringList svgs; QString layoutSVG; int index; }; struct PanelItem { // per window QString boardName; QString path; int required; int maxOptional; int optionalPriority; int produced; QSizeF boardSizeInches; long boardID; PanelItem * refPanelItem; // per instance double x, y; bool rotate90; PlanePair * planePair; PanelItem(); PanelItem(PanelItem * from); }; struct BestPlace { Tile * bestTile; TileRect bestTileRect; TileRect maxRect; int width; int height; double bestArea; bool rotate90; Plane* plane; BestPlace(); }; struct PanelType { double width; double height; double c1; double c2; QString name; }; struct PanelParams { QList panelTypes; double panelSpacing; double panelBorder; QString prefix; }; struct LayerThing { LayerList layerList; QString name; SVG2gerber::ForWhy forWhy; QString suffix; LayerThing(const QString & n, LayerList ll, SVG2gerber::ForWhy fw, const QString & s) { layerList = ll; name = n; forWhy = fw; suffix = s; } }; class Panelizer { public: static void panelize(class FApplication *, const QString & panelFilename, bool customPartsOnly); static void inscribe(class FApplication *, const QString & panelFilename, bool drc, bool noMessages); static int placeBestFit(Tile * tile, UserData userData); static int checkDonuts(MainWindow *, bool displayMessage); static int checkText(MainWindow *, bool displayMessage); protected: static bool initPanelParams(QDomElement & root, PanelParams &); static PlanePair * makePlanePair(PanelParams &, bool big); static void collectFiles(const QDir & outputDir, QDomElement & path, QHash & fzzFilePaths); static bool checkBoards(QDomElement & board, QHash & fzzFilePaths); static bool openWindows(QDomElement & board, QHash & fzzFilePaths, class FApplication *, PanelParams &, QDir & fzDir, QDir & svgDir, QList & refPanelItems, QList & layerThingList, bool customPartsOnly, QDir & copyDir); static void bestFit(QList & insertPanelItems, PanelParams &, QList &, bool customPartsOnly); static bool bestFitOne(PanelItem * panelItem, PanelParams & panelParams, QList & planePairs, bool createNew, bool customPartsOnly); static void addOptional(int optionalCount, QList & refPanelItems, QList & insertPanelItems, PanelParams &, QList &); static class MainWindow * inscribeBoard(QDomElement & board, QHash & fzzFilePaths, FApplication * app, QDir & fzDir, bool drc, bool noMessages, QDir & copyDir); static void doOnePanelItem(PlanePair * planePair, QList & layerThingList, PanelItem * panelItem, QDir & svgDir); static void makeSVGs(MainWindow *, ItemBase *, const QString & boardName, QList & layerThingList, QDir & saveDir, QFileInfo & copyInfo); static void shrinkLastPanel( QList & planePairs, QList & insertPanelItems, PanelParams &, bool customPartsOnly); static int bestFitLoop(QList & refPanelItems, PanelParams &, bool customPartsOnly, QList & returnPlanePairs, QList & returnInsertPanelItems, const QDir & svgDir); static double calcCost(PanelParams &, QList &, int divisor); static void writePanelizerOutput(const QString & message); static void initPanelizerOutput(const QString & filename, const QString & initialMsg); static void collectFilenames(const QString & filenames); static void writePanelizerFilenames(const QString & panelFilename); }; #endif fritzing-app-0.9.2b/src/autoroute/zoomcontrols.cpp000066400000000000000000000067061250202676700224100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "zoomcontrols.h" #include "../debugdialog.h" #include "../utils/zoomslider.h" ZoomButton::ZoomButton(QBoxLayout::Direction dir, ZoomButton::ZoomType type, ZoomableGraphicsView* view, QWidget *parent) : QLabel(parent) { QString imgPath = ":/resources/images/icons/partsEditorZoom%1%2Button.png"; QString typeStr = type==ZoomButton::ZoomIn? "In": "Out"; QString dirStr; if(dir == QBoxLayout::LeftToRight || dir == QBoxLayout::RightToLeft) { dirStr = "Hor"; } else if(dir == QBoxLayout::TopToBottom || dir == QBoxLayout::BottomToTop) { dirStr = "Ver"; } imgPath = imgPath.arg(typeStr).arg(dirStr); m_step = 5*ZoomSlider::ZoomStep; m_type = type; m_owner = view; connect(this, SIGNAL(clicked()), this, SLOT(zoom()) ); setPixmap(QPixmap(imgPath)); } void ZoomButton::zoom() { int inOrOut = m_type == ZoomButton::ZoomIn? 1: -1; m_owner->relativeZoom(inOrOut*m_step, false); m_owner->ensureFixedToBottomRightItems(); } void ZoomButton::mousePressEvent(QMouseEvent *event) { //QLabel::mousePressEvent(event); Q_UNUSED(event); emit clicked(); } void ZoomButton::enterEvent(QEvent *event) { QLabel::enterEvent(event); } void ZoomButton::leaveEvent(QEvent *event) { QLabel::leaveEvent(event); } /////////////////////////////////////////////////////////// ZoomControlsPrivate::ZoomControlsPrivate(ZoomableGraphicsView* view, QBoxLayout::Direction dir, QWidget *parent) : QFrame(parent) { //setObjectName("zoomControls"); m_zoomInButton = new ZoomButton(dir, ZoomButton::ZoomIn, view, this); m_zoomOutButton = new ZoomButton(dir, ZoomButton::ZoomOut, view, this); m_boxLayout = new QBoxLayout(dir,this); m_boxLayout->addWidget(m_zoomInButton); m_boxLayout->addWidget(m_zoomOutButton); m_boxLayout->setMargin(2); m_boxLayout->setSpacing(2); setStyleSheet("background-color: transparent;"); } /////////////////////////////////////////////////////////// ZoomControls::ZoomControls(ZoomableGraphicsView *view, QWidget *parent) : ZoomControlsPrivate(view, QBoxLayout::RightToLeft, parent) { m_zoomLabel = new QLabel(this); m_zoomLabel->setFixedWidth(35); connect(view, SIGNAL(zoomChanged(double)),this,SLOT(updateLabel(double))); m_boxLayout->insertWidget(1,m_zoomLabel); // in the middle m_boxLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Minimum)); // at the beginning updateLabel(view->currentZoom()); } void ZoomControls::updateLabel(double zoom) { m_zoomLabel->setText(QString("%1%").arg((int)zoom)); } fritzing-app-0.9.2b/src/autoroute/zoomcontrols.h000066400000000000000000000043001250202676700220410ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ZOOMCONTROLS_H_ #define ZOOMCONTROLS_H_ #include #include #include "../sketch/zoomablegraphicsview.h" class ZoomButton : public QLabel { Q_OBJECT public: enum ZoomType {ZoomIn, ZoomOut}; public: ZoomButton(QBoxLayout::Direction dir, ZoomButton::ZoomType type, ZoomableGraphicsView* view, QWidget *parent); signals: void clicked(); protected slots: void zoom(); protected: void enterEvent(QEvent *event); void leaveEvent(QEvent *event); void mousePressEvent(QMouseEvent *event); ZoomableGraphicsView *m_owner; double m_step; ZoomButton::ZoomType m_type; }; class ZoomControlsPrivate : public QFrame { public: ZoomControlsPrivate(ZoomableGraphicsView*, QBoxLayout::Direction = QBoxLayout::TopToBottom, QWidget *parent=0); ZoomButton *zoomInButton(); ZoomButton *zoomOutButton(); protected: ZoomButton *m_zoomInButton; ZoomButton *m_zoomOutButton; QBoxLayout *m_boxLayout; }; class ZoomControls : public ZoomControlsPrivate { Q_OBJECT public: ZoomControls(ZoomableGraphicsView *view, QWidget *parent); protected slots: void updateLabel(double zoom); protected: QLabel *m_zoomLabel; }; #endif /* ZOOMCONTROLS_H_ */ fritzing-app-0.9.2b/src/commands.cpp000066400000000000000000001746361250202676700174220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #include "commands.h" #include "debugdialog.h" #include "sketch/sketchwidget.h" #include "waitpushundostack.h" #include "items/wire.h" #include "connectors/connectoritem.h" #include "items/moduleidnames.h" #include "utils/bezier.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// CommandProgress::CommandProgress() { m_active = false; } void CommandProgress::setActive(bool active) { m_active = active; } bool CommandProgress::active() { return m_active; } void CommandProgress::emitUndo() { emit incUndo(); } void CommandProgress::emitRedo() { emit incRedo(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// int SelectItemCommand::selectItemCommandID = 3; int ChangeNoteTextCommand::changeNoteTextCommandID = 5; int BaseCommand::nextIndex = 0; CommandProgress BaseCommand::m_commandProgress; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// BaseCommand::BaseCommand(BaseCommand::CrossViewType crossViewType, SketchWidget* sketchWidget, QUndoCommand *parent) : QUndoCommand(parent) { m_skipFirstRedo = m_undoOnly = m_redoOnly = false; m_crossViewType = crossViewType; m_sketchWidget = sketchWidget; m_parentCommand = parent; m_index = BaseCommand::nextIndex++; } BaseCommand::~BaseCommand() { foreach (BaseCommand * baseCommand, m_commands) { delete baseCommand; } m_commands.clear(); } BaseCommand::CrossViewType BaseCommand::crossViewType() const { return m_crossViewType; } void BaseCommand::setCrossViewType(BaseCommand::CrossViewType crossViewType) { m_crossViewType = crossViewType; } SketchWidget* BaseCommand::sketchWidget() const { return m_sketchWidget; } QString BaseCommand::getDebugString() const { return QString("%1 %2").arg(getParamString()).arg(text()); } void BaseCommand::setUndoOnly() { m_undoOnly = true; } void BaseCommand::setRedoOnly() { m_redoOnly = true; } void BaseCommand::setSkipFirstRedo() { m_skipFirstRedo = true; } QString BaseCommand::getParamString() const { return QString("%1 %2") .arg(m_sketchWidget->viewName()) .arg((m_crossViewType == BaseCommand::SingleView) ? "single-view" : "cross-view"); } int BaseCommand::subCommandCount() const { return m_commands.count(); } const BaseCommand * BaseCommand::subCommand(int ix) const { if (ix < 0) return NULL; if (ix >= m_commands.count()) return NULL; return m_commands.at(ix); } void BaseCommand::addSubCommand(BaseCommand * subCommand) { m_commands.append(subCommand); #ifndef QT_NO_DEBUG if (m_sketchWidget != NULL) { m_sketchWidget->undoStack()->writeUndo(subCommand, 4, this); } #endif } const QUndoCommand * BaseCommand::parentCommand() const { return m_parentCommand; } void BaseCommand::subUndo() { for (int i = m_commands.count() - 1; i >= 0; i--) { m_commands[i]->undo(); } } void BaseCommand::subRedo() { foreach (BaseCommand * command, m_commands) { command->redo(); } } void BaseCommand::subUndo(int index) { if (index < 0 || index >= m_commands.count()) return; m_commands[index]->undo(); } void BaseCommand::subRedo(int index) { if (index < 0 || index >= m_commands.count()) return; m_commands[index]->redo(); } int BaseCommand::index() const { return m_index; } void BaseCommand::undo() { if (m_commandProgress.active()) m_commandProgress.emitUndo(); } void BaseCommand::redo() { if (m_commandProgress.active()) m_commandProgress.emitRedo(); } CommandProgress * BaseCommand::initProgress() { m_commandProgress.setActive(true); return &m_commandProgress; } void BaseCommand::clearProgress() { m_commandProgress.setActive(false); } int BaseCommand::totalChildCount(const QUndoCommand * command) { int cc = command->childCount(); int tcc = cc; for (int i = 0; i < cc; i++) { tcc += totalChildCount(command->child(i)); } return tcc; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// AddDeleteItemCommand::AddDeleteItemCommand(SketchWidget* sketchWidget, BaseCommand::CrossViewType crossViewType, QString moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewGeometry & viewGeometry, qint64 id, long modelIndex, QUndoCommand *parent) : BaseCommand(crossViewType, sketchWidget, parent) { m_dropOrigin = NULL; m_moduleID = moduleID; m_viewGeometry = viewGeometry; m_itemID = id; m_modelIndex = modelIndex; m_viewLayerPlacement = viewLayerPlacement; } QString AddDeleteItemCommand::getParamString() const { return BaseCommand::getParamString() + QString(" moduleid:%1 id:%2 modelindex:%3 flags:%4") .arg(m_moduleID) .arg(m_itemID) .arg(m_modelIndex) .arg(m_viewGeometry.flagsAsInt()); } long AddDeleteItemCommand::itemID() const { return m_itemID; } void AddDeleteItemCommand::setDropOrigin(SketchWidget * sketchWidget) { m_dropOrigin = sketchWidget; } SketchWidget * AddDeleteItemCommand::dropOrigin() { return m_dropOrigin; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// AddItemCommand::AddItemCommand(SketchWidget* sketchWidget, BaseCommand::CrossViewType crossViewType, QString moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewGeometry & viewGeometry, qint64 id, bool updateInfoView, long modelIndex, QUndoCommand *parent) : AddDeleteItemCommand(sketchWidget, crossViewType, moduleID, viewLayerPlacement, viewGeometry, id, modelIndex, parent) { m_module = false; m_updateInfoView = updateInfoView; } void AddItemCommand::undo() { m_sketchWidget->deleteItem(m_itemID, true, true, false); BaseCommand::undo(); } void AddItemCommand::redo() { if (!m_skipFirstRedo) { m_sketchWidget->addItem(m_moduleID, m_viewLayerPlacement, m_crossViewType, m_viewGeometry, m_itemID, m_modelIndex, this); } m_skipFirstRedo = false; BaseCommand::redo(); } QString AddItemCommand::getParamString() const { return "AddItemCommand " + AddDeleteItemCommand::getParamString() + QString(" loc:%1,%2 pt1:%3,%4 pt2:%5,%6") .arg(m_viewGeometry.loc().x()).arg(m_viewGeometry.loc().y()) .arg(m_viewGeometry.line().p1().x()).arg(m_viewGeometry.line().p1().y()) .arg(m_viewGeometry.line().p2().x()).arg(m_viewGeometry.line().p2().y()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// DeleteItemCommand::DeleteItemCommand(SketchWidget* sketchWidget,BaseCommand::CrossViewType crossViewType, QString moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewGeometry & viewGeometry, qint64 id, long modelIndex, QUndoCommand *parent) : AddDeleteItemCommand(sketchWidget, crossViewType, moduleID, viewLayerPlacement, viewGeometry, id, modelIndex, parent) { } void DeleteItemCommand::undo() { m_sketchWidget->addItem(m_moduleID, m_viewLayerPlacement, m_crossViewType, m_viewGeometry, m_itemID, m_modelIndex, this); BaseCommand::undo(); } void DeleteItemCommand::redo() { m_sketchWidget->deleteItem(m_itemID, true, m_crossViewType == BaseCommand::CrossView, false); BaseCommand::redo(); } QString DeleteItemCommand::getParamString() const { return "DeleteItemCommand " + AddDeleteItemCommand::getParamString(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// MoveItemCommand::MoveItemCommand(SketchWidget* sketchWidget, long itemID, ViewGeometry & oldG, ViewGeometry & newG, bool updateRatsnest, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_updateRatsnest = updateRatsnest; m_itemID = itemID; m_old = oldG; m_new = newG; } void MoveItemCommand::undo() { m_sketchWidget->moveItem(m_itemID, m_old, m_updateRatsnest); BaseCommand::undo(); } void MoveItemCommand::redo() { m_sketchWidget->moveItem(m_itemID, m_new, m_updateRatsnest); BaseCommand::redo(); } QString MoveItemCommand::getParamString() const { return QString("MoveItemCommand ") + BaseCommand::getParamString() + QString(" id:%1 old.x:%2 old.y:%3 old.px:%4 old.py:%5 new.x:%6 new.y:%7 new.px:%8 new.py:%9") .arg(m_itemID) .arg(m_old.loc().x()) .arg(m_old.loc().y()) .arg(m_old.line().p2().x()) .arg(m_old.line().p2().y()) .arg(m_new.loc().x()) .arg(m_new.loc().y()) .arg(m_new.line().p2().x()) .arg(m_new.line().p2().y()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// SimpleMoveItemCommand::SimpleMoveItemCommand(SketchWidget* sketchWidget, long itemID, QPointF & oldP, QPointF & newP, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_old = oldP; m_new = newP; } void SimpleMoveItemCommand::undo() { m_sketchWidget->simpleMoveItem(m_itemID, m_old); BaseCommand::undo(); } void SimpleMoveItemCommand::redo() { m_sketchWidget->simpleMoveItem(m_itemID, m_new); BaseCommand::redo(); } QString SimpleMoveItemCommand::getParamString() const { return QString("SimpleMoveItemCommand ") + BaseCommand::getParamString() + QString(" id:%1 old.x:%2 old.y:%3 new.x:%4 new.y:%5") .arg(m_itemID) .arg(m_old.x()) .arg(m_old.y()) .arg(m_new.x()) .arg(m_new.y()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// MoveItemsCommand::MoveItemsCommand(SketchWidget* sketchWidget, bool updateRatsnest, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_updateRatsnest = updateRatsnest; } void MoveItemsCommand::undo() { foreach(MoveItemThing moveItemThing, m_items) { m_sketchWidget->moveItem(moveItemThing.id, moveItemThing.oldPos, m_updateRatsnest); } foreach (long id, m_wires.keys()) { m_sketchWidget->updateWire(id, m_wires.value(id), m_updateRatsnest); } BaseCommand::undo(); } void MoveItemsCommand::redo() { foreach(MoveItemThing moveItemThing, m_items) { m_sketchWidget->moveItem(moveItemThing.id, moveItemThing.newPos, m_updateRatsnest); } foreach (long id, m_wires.keys()) { m_sketchWidget->updateWire(id, m_wires.value(id), m_updateRatsnest); } BaseCommand::redo(); } void MoveItemsCommand::addWire(long id, const QString & connectorID) { m_wires.insert(id, connectorID); } void MoveItemsCommand::addItem(long id, const QPointF & oldPos, const QPointF & newPos) { MoveItemThing moveItemThing; moveItemThing.id = id; moveItemThing.oldPos = oldPos; moveItemThing.newPos = newPos; m_items.append(moveItemThing); } QString MoveItemsCommand::getParamString() const { return QString("MoveItemsCommand ") + BaseCommand::getParamString() + QString(" items:%1 wires:%2") .arg(m_items.count()) .arg(m_wires.count()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// RotateItemCommand::RotateItemCommand(SketchWidget* sketchWidget, long itemID, double degrees, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_degrees = degrees; } void RotateItemCommand::undo() { m_sketchWidget->rotateItem(m_itemID, -m_degrees); BaseCommand::undo(); } void RotateItemCommand::redo() { m_sketchWidget->rotateItem(m_itemID, m_degrees); BaseCommand::redo(); } QString RotateItemCommand::getParamString() const { return QString("RotateItemCommand ") + BaseCommand::getParamString() + QString(" id:%1 by:%2") .arg(m_itemID) .arg(m_degrees); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// FlipItemCommand::FlipItemCommand(SketchWidget* sketchWidget, long itemID, Qt::Orientations orientation, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_orientation = orientation; } void FlipItemCommand::undo() { redo(); BaseCommand::undo(); } void FlipItemCommand::redo() { m_sketchWidget->flipItem(m_itemID, m_orientation); BaseCommand::redo(); } QString FlipItemCommand::getParamString() const { return QString("FlipItemCommand ") + BaseCommand::getParamString() + QString(" id:%1 by:%2") .arg(m_itemID) .arg(m_orientation); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeConnectionCommand::ChangeConnectionCommand(SketchWidget * sketchWidget, BaseCommand::CrossViewType crossView, long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, QUndoCommand * parent) : BaseCommand(crossView, sketchWidget, parent) { //DebugDialog::debug(QString("ccc: from %1 %2; to %3 %4").arg(fromID).arg(fromConnectorID).arg(toID).arg(toConnectorID) ); m_enabled = true; m_fromID = fromID; m_fromConnectorID = fromConnectorID; m_toID = toID; m_toConnectorID = toConnectorID; m_connect = connect; m_updateConnections = true; m_viewLayerPlacement = viewLayerPlacement; } void ChangeConnectionCommand::undo() { if (m_enabled) { m_sketchWidget->changeConnection(m_fromID, m_fromConnectorID, m_toID, m_toConnectorID, m_viewLayerPlacement, !m_connect, m_crossViewType == CrossView, m_updateConnections); BaseCommand::undo(); } } void ChangeConnectionCommand::redo() { if (m_enabled) { m_sketchWidget->changeConnection(m_fromID, m_fromConnectorID, m_toID, m_toConnectorID, m_viewLayerPlacement, m_connect, m_crossViewType == CrossView, m_updateConnections); BaseCommand::redo(); } } void ChangeConnectionCommand::setUpdateConnections(bool updatem) { m_updateConnections = updatem; } void ChangeConnectionCommand::disable() { m_enabled = false; } QString ChangeConnectionCommand::getParamString() const { return QString("ChangeConnectionCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 connid:%2 toid:%3 connid:%4 vlspec:%5 connect:%6") .arg(m_fromID) .arg(m_fromConnectorID) .arg(m_toID) .arg(m_toConnectorID) .arg(m_viewLayerPlacement) .arg(m_connect); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeWireCommand::ChangeWireCommand(SketchWidget* sketchWidget, long fromID, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, bool updateConnections, bool updateRatsnest, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_updateRatsnest = updateRatsnest; m_fromID = fromID; m_oldLine = oldLine; m_newLine = newLine; m_oldPos = oldPos; m_newPos = newPos; m_updateConnections = updateConnections; } void ChangeWireCommand::undo() { if (!m_redoOnly) { m_sketchWidget->changeWire(m_fromID, m_oldLine, m_oldPos, m_updateConnections, m_updateRatsnest); } BaseCommand::undo(); } void ChangeWireCommand::redo() { if (!m_undoOnly) { m_sketchWidget->changeWire(m_fromID, m_newLine, m_newPos, m_updateConnections, m_updateRatsnest); } BaseCommand::redo(); } QString ChangeWireCommand::getParamString() const { return QString("ChangeWireCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 oldp:%2,%3 newP:%4,%5 oldr:%7,%8,%9,%10 newr:%11,%12,%13,%14") .arg(m_fromID) .arg(m_oldPos.x()).arg(m_oldPos.y()) .arg(m_newPos.x()).arg(m_newPos.y()) .arg(m_oldLine.x1()).arg(m_oldLine.y1()).arg(m_oldLine.x2()).arg(m_oldLine.y2()) .arg(m_newLine.x1()).arg(m_newLine.y1()).arg(m_newLine.x2()).arg(m_newLine.y2()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeWireCurveCommand::ChangeWireCurveCommand(SketchWidget* sketchWidget, long fromID, const Bezier * oldBezier, const Bezier * newBezier, bool wasAutoroutable, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_wasAutoroutable = wasAutoroutable; m_oldBezier = m_newBezier = NULL; if (oldBezier) { m_oldBezier = new Bezier; m_oldBezier->copy(oldBezier); } if (newBezier) { m_newBezier = new Bezier; m_newBezier->copy(newBezier); } } void ChangeWireCurveCommand::undo() { if (!m_redoOnly) { m_sketchWidget->changeWireCurve(m_fromID, m_oldBezier, m_wasAutoroutable); } BaseCommand::undo(); } void ChangeWireCurveCommand::redo() { if (!m_undoOnly) { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { m_sketchWidget->changeWireCurve(m_fromID, m_newBezier, false); } } BaseCommand::redo(); } QString ChangeWireCurveCommand::getParamString() const { QString oldBezier; QString newBezier; if (m_oldBezier) { oldBezier += QString("(%1,%2)").arg(m_oldBezier->cp0().x()).arg(m_oldBezier->cp0().y()); oldBezier += QString("(%1,%2)").arg(m_oldBezier->cp1().x()).arg(m_oldBezier->cp1().y()); } if (m_newBezier) { newBezier += QString("(%1,%2)").arg(m_newBezier->cp0().x()).arg(m_newBezier->cp0().y()); newBezier += QString("(%1,%2)").arg(m_newBezier->cp1().x()).arg(m_newBezier->cp1().y()); } return QString("ChangeWireCurveCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 oldp:%2 newp:%3") .arg(m_fromID) .arg(oldBezier) .arg(newBezier) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeLegCommand::ChangeLegCommand(SketchWidget* sketchWidget, long fromID, const QString & fromConnectorID, const QPolygonF & oldLeg, const QPolygonF & newLeg, bool relative, bool active, const QString & why, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_why = why; m_simple = false; m_fromID = fromID; m_oldLeg = oldLeg; m_newLeg = newLeg; m_relative = relative; m_fromConnectorID = fromConnectorID; m_active = active; } void ChangeLegCommand::undo() { if (!m_redoOnly) { m_sketchWidget->changeLeg(m_fromID, m_fromConnectorID, m_oldLeg, m_relative, m_why); } BaseCommand::undo(); } void ChangeLegCommand::setSimple() { m_simple = true; } void ChangeLegCommand::redo() { if (!m_undoOnly) { if (m_simple) { m_sketchWidget->changeLeg(m_fromID, m_fromConnectorID, m_newLeg, m_relative, m_why); } else { m_sketchWidget->recalcLeg(m_fromID, m_fromConnectorID, m_newLeg, m_relative, m_active, m_why); } } BaseCommand::redo(); } QString ChangeLegCommand::getParamString() const { QString oldLeg; QString newLeg; foreach (QPointF p, m_oldLeg) { oldLeg += QString("(%1,%2)").arg(p.x()).arg(p.y()); } foreach (QPointF p, m_newLeg) { newLeg += QString("(%1,%2)").arg(p.x()).arg(p.y()); } return QString("ChangeLegCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 fromc:%2 %3 old:%4 new:%5") .arg(m_fromID) .arg(m_fromConnectorID) .arg(m_why) .arg(oldLeg) .arg(newLeg) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// MoveLegBendpointCommand::MoveLegBendpointCommand(SketchWidget* sketchWidget, long fromID, const QString & fromConnectorID, int index, QPointF oldPos, QPointF newPos, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_oldPos = oldPos; m_newPos = newPos; m_fromConnectorID = fromConnectorID; m_index = index; } void MoveLegBendpointCommand::undo() { if (!m_redoOnly) { m_sketchWidget->moveLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_oldPos); } BaseCommand::undo(); } void MoveLegBendpointCommand::redo() { if (!m_undoOnly) { m_sketchWidget->moveLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_newPos); } BaseCommand::redo(); } QString MoveLegBendpointCommand::getParamString() const { return QString("MoveLegBendpointCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 fromc:%2 ix:%3 old:%4,%5 new:%6,%7") .arg(m_fromID) .arg(m_fromConnectorID) .arg(m_index) .arg(m_oldPos.x()) .arg(m_oldPos.y()) .arg(m_newPos.x()) .arg(m_newPos.y()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeLegCurveCommand::ChangeLegCurveCommand(SketchWidget* sketchWidget, long fromID, const QString & connectorID, int index, const Bezier * oldBezier, const Bezier * newBezier, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_oldBezier = m_newBezier = NULL; if (oldBezier) { m_oldBezier = new Bezier; m_oldBezier->copy(oldBezier); } if (newBezier) { m_newBezier = new Bezier; m_newBezier->copy(newBezier); } m_fromConnectorID = connectorID; m_index = index; } void ChangeLegCurveCommand::undo() { m_sketchWidget->changeLegCurve(m_fromID, m_fromConnectorID, m_index, m_oldBezier); BaseCommand::undo(); } void ChangeLegCurveCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else if (!m_undoOnly) { m_sketchWidget->changeLegCurve(m_fromID, m_fromConnectorID, m_index, m_newBezier); } BaseCommand::redo(); } QString ChangeLegCurveCommand::getParamString() const { QString oldBezier; QString newBezier; if (m_oldBezier) { oldBezier += QString("(%1,%2)").arg(m_oldBezier->cp0().x()).arg(m_oldBezier->cp0().y()); oldBezier += QString("(%1,%2)").arg(m_oldBezier->cp1().x()).arg(m_oldBezier->cp1().y()); } if (m_newBezier) { newBezier += QString("(%1,%2)").arg(m_newBezier->cp0().x()).arg(m_newBezier->cp0().y()); newBezier += QString("(%1,%2)").arg(m_newBezier->cp1().x()).arg(m_newBezier->cp1().y()); } return QString("ChangeLegCurveCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 oldp:%2 newp:%3") .arg(m_fromID) .arg(oldBezier) .arg(newBezier) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeLegBendpointCommand::ChangeLegBendpointCommand(SketchWidget* sketchWidget, long fromID, const QString & connectorID, int oldCount, int newCount, int index, QPointF pos, const Bezier * bezier0, const Bezier * bezier1, const Bezier * bezier2, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_bezier0 = m_bezier1 = m_bezier2 = NULL; if (bezier0 != NULL) { m_bezier0 = new Bezier; m_bezier0->copy(bezier0); } if (bezier1 != NULL) { m_bezier1 = new Bezier; m_bezier1->copy(bezier1); } if (bezier2 != NULL) { m_bezier2 = new Bezier; m_bezier2->copy(bezier2); } m_fromConnectorID = connectorID; m_index = index; m_oldCount = oldCount; m_newCount = newCount; m_pos = pos; } void ChangeLegBendpointCommand::undo() { if (m_newCount < m_oldCount) { m_sketchWidget->addLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_pos, m_bezier0, m_bezier1); } else { m_sketchWidget->removeLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_bezier0); } BaseCommand::undo(); } void ChangeLegBendpointCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { if (m_newCount > m_oldCount) { m_sketchWidget->addLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_pos, m_bezier1, m_bezier2); } else { m_sketchWidget->removeLegBendpoint(m_fromID, m_fromConnectorID, m_index, m_bezier2); } } BaseCommand::redo(); } QString ChangeLegBendpointCommand::getParamString() const { QString bezier; if (m_bezier0) { bezier += QString("(%1,%2)").arg(m_bezier0->cp0().x()).arg(m_bezier0->cp0().y()); bezier += QString("(%1,%2)").arg(m_bezier0->cp1().x()).arg(m_bezier0->cp1().y()); } return QString("ChangeLegBendpointCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 newp:%2") .arg(m_fromID) .arg(bezier) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// RotateLegCommand::RotateLegCommand(SketchWidget* sketchWidget, long fromID, const QString & fromConnectorID, const QPolygonF & oldLeg, bool active, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_oldLeg = oldLeg; m_fromConnectorID = fromConnectorID; m_active = active; } void RotateLegCommand::undo() { BaseCommand::undo(); } void RotateLegCommand::redo() { m_sketchWidget->rotateLeg(m_fromID, m_fromConnectorID, m_oldLeg, m_active); BaseCommand::redo(); } QString RotateLegCommand::getParamString() const { QString oldLeg; foreach (QPointF p, m_oldLeg) { oldLeg += QString("(%1,%2)").arg(p.x()).arg(p.y()); } return QString("RotateLegCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 fromc:%2 old:%3") .arg(m_fromID) .arg(m_fromConnectorID) .arg(oldLeg) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeLayerCommand::ChangeLayerCommand(SketchWidget *sketchWidget, long fromID, double oldZ, double newZ, ViewLayer::ViewLayerID oldLayer, ViewLayer::ViewLayerID newLayer, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_oldZ = oldZ; m_newZ = newZ; m_oldLayer = oldLayer; m_newLayer = newLayer; } void ChangeLayerCommand::undo() { m_sketchWidget->changeLayer(m_fromID, m_oldZ, m_oldLayer); BaseCommand::undo(); } void ChangeLayerCommand::redo() { m_sketchWidget->changeLayer(m_fromID, m_newZ, m_newLayer); BaseCommand::redo(); } QString ChangeLayerCommand::getParamString() const { return QString("ChangeLayerCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 oldZ:%2 newZ:%3 oldL:%4 newL:%5") .arg(m_fromID) .arg(m_oldZ) .arg(m_newZ) .arg(m_oldLayer) .arg(m_newLayer) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// SelectItemCommand::SelectItemCommand(SketchWidget* sketchWidget, SelectItemType type, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_type = type; m_updated = false; } int SelectItemCommand::id() const { return selectItemCommandID; } void SelectItemCommand::setSelectItemType(SelectItemType type) { m_type = type; } void SelectItemCommand::copyUndo(SelectItemCommand * sother) { this->m_undoIDs.clear(); for (int i = 0; i < sother->m_undoIDs.size(); i++) { this->m_undoIDs.append(sother->m_undoIDs[i]); } } void SelectItemCommand::copyRedo(SelectItemCommand * sother) { this->m_redoIDs.clear(); for (int i = 0; i < sother->m_redoIDs.size(); i++) { this->m_redoIDs.append(sother->m_redoIDs[i]); } } void SelectItemCommand::clearRedo() { m_redoIDs.clear(); } bool SelectItemCommand::mergeWith(const QUndoCommand *other) { // "this" is earlier; "other" is later if (other->id() != id()) { return false; } const SelectItemCommand * sother = dynamic_cast(other); if (sother == NULL) return false; if (sother->crossViewType() != this->crossViewType()) { return false; } this->m_redoIDs.clear(); for (int i = 0; i < sother->m_redoIDs.size(); i++) { this->m_redoIDs.append(sother->m_redoIDs[i]); } this->setText(sother->text()); return true; } void SelectItemCommand::undo() { selectAllFromStack(m_undoIDs, true, true); BaseCommand::undo(); } void SelectItemCommand::redo() { switch( m_type ){ case NormalSelect: selectAllFromStack(m_redoIDs, true, true); break; case NormalDeselect: selectAllFromStack(m_redoIDs, false, false); break; case SelectAll: m_sketchWidget->selectAllItems(true, m_crossViewType == BaseCommand::CrossView); break; case DeselectAll: m_sketchWidget->selectAllItems(false, m_crossViewType == BaseCommand::CrossView); break; } BaseCommand::redo(); } void SelectItemCommand::selectAllFromStack(QList & stack, bool select, bool updateInfoView) { m_sketchWidget->clearSelection(); for (int i = 0; i < stack.size(); i++) { m_sketchWidget->selectItem(stack[i], select, updateInfoView, m_crossViewType == BaseCommand::CrossView); } } void SelectItemCommand::addUndo(long id) { m_undoIDs.append(id); } void SelectItemCommand::addRedo(long id) { if(m_type == NormalSelect) { m_redoIDs.append(id); } } QString SelectItemCommand::getParamString() const { return QString("SelectItemCommand ") + BaseCommand::getParamString() + QString(" type:%1") .arg(m_type); } bool SelectItemCommand::updated() { return m_updated; } void SelectItemCommand::setUpdated(bool updated) { m_updated = updated; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeZCommand::ChangeZCommand(SketchWidget* sketchWidget, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { } ChangeZCommand::~ChangeZCommand() { foreach (RealPair * realpair, m_triplets) { delete realpair; } m_triplets.clear(); } void ChangeZCommand::addTriplet(long id, double oldZ, double newZ) { m_triplets.insert(id, new RealPair (oldZ, newZ)); } void ChangeZCommand::undo() { m_sketchWidget->changeZ(m_triplets, first); BaseCommand::undo(); } void ChangeZCommand::redo() { m_sketchWidget->changeZ(m_triplets, second); BaseCommand::redo(); } double ChangeZCommand::first(RealPair * pair) { return pair->first; } double ChangeZCommand::second(RealPair * pair) { return pair->second; } QString ChangeZCommand::getParamString() const { return QString("ChangeZCommand ") + BaseCommand::getParamString(); } //////////////////////////////////////////singlev/////////////////////////////////////////////////////////////////////// CheckStickyCommand::CheckStickyCommand(SketchWidget* sketchWidget, BaseCommand::CrossViewType crossViewType, long itemID, bool checkCurrent, CheckType checkType, QUndoCommand *parent) : BaseCommand(crossViewType, sketchWidget, parent) { m_itemID = itemID; m_skipFirstRedo = true; m_checkType = checkType; m_checkCurrent = checkCurrent; } CheckStickyCommand::~CheckStickyCommand() { foreach (StickyThing * stickyThing, m_stickyList) { delete stickyThing; } m_stickyList.clear(); } void CheckStickyCommand::undo() { if (m_checkType == RedoOnly) return; foreach (StickyThing * stickyThing, m_stickyList) { if (m_checkType == RemoveOnly) { stickyThing->sketchWidget->stickem(stickyThing->fromID, stickyThing->toID, !stickyThing->stickem); } else { stickyThing->sketchWidget->stickem(stickyThing->fromID, stickyThing->toID, stickyThing->stickem); } } BaseCommand::undo(); } void CheckStickyCommand::redo() { if (m_checkType == UndoOnly) return; if (m_skipFirstRedo) { m_sketchWidget->checkSticky(m_itemID, m_crossViewType == BaseCommand::CrossView, m_checkCurrent, this); m_skipFirstRedo = false; } else { foreach (StickyThing * stickyThing, m_stickyList) { stickyThing->sketchWidget->stickem(stickyThing->fromID, stickyThing->toID, stickyThing->stickem); } } BaseCommand::redo(); } QString CheckStickyCommand::getParamString() const { return QString("CheckStickyCommand ") + BaseCommand::getParamString() + QString("id:%1") .arg(this->m_stickyList.count()); } void CheckStickyCommand::stick(SketchWidget * sketchWidget, long fromID, long toID, bool stickem) { StickyThing * stickyThing = new StickyThing; stickyThing->sketchWidget = sketchWidget; stickyThing->fromID = fromID; stickyThing->toID = toID; stickyThing->stickem = stickem; m_stickyList.append(stickyThing); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// CleanUpWiresCommand::CleanUpWiresCommand(SketchWidget* sketchWidget, CleanUpWiresCommand::Direction direction, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_direction = direction; } void CleanUpWiresCommand::undo() { foreach (RatsnestConnectThing rct, m_ratsnestConnectThings) { m_sketchWidget->ratsnestConnect(rct.id, rct.connectorID, !rct.connect, true); } if (m_sketchWidgets.count() > 0) { subUndo(); } if (m_direction == UndoOnly) { m_sketchWidget->cleanUpWires(m_crossViewType == BaseCommand::CrossView, NULL); } BaseCommand::undo(); } void CleanUpWiresCommand::redo() { foreach (RatsnestConnectThing rct, m_ratsnestConnectThings) { m_sketchWidget->ratsnestConnect(rct.id, rct.connectorID, rct.connect, true); } if (m_sketchWidgets.count() > 0) { subRedo(); } if (m_direction == RedoOnly) { m_sketchWidget->cleanUpWires(m_crossViewType == BaseCommand::CrossView, this); } BaseCommand::redo(); } void CleanUpWiresCommand::addRatsnestConnect(long id, const QString & connectorID, bool connect) { RatsnestConnectThing rct; rct.id = id; rct.connectorID = connectorID; rct.connect = connect; m_ratsnestConnectThings.append(rct); } void CleanUpWiresCommand::addRoutingStatus(SketchWidget * sketchWidget, const RoutingStatus & oldRoutingStatus, const RoutingStatus & newRoutingStatus) { addSubCommand(new RoutingStatusCommand(sketchWidget, oldRoutingStatus, newRoutingStatus, NULL)); } void CleanUpWiresCommand::setDirection(CleanUpWiresCommand::Direction direction) { m_direction = direction; } CleanUpWiresCommand::Direction CleanUpWiresCommand::direction() { return m_direction; } void CleanUpWiresCommand::addTrace(SketchWidget * sketchWidget, Wire * wire) { if (m_parentCommand) { for (int i = 0; i < m_parentCommand->childCount(); i++) { const DeleteItemCommand * command = dynamic_cast(m_parentCommand->child(i)); if (command == NULL) continue; if (command->itemID() == wire->id()) { return; } } } m_sketchWidgets.insert(sketchWidget); addSubCommand(new WireColorChangeCommand(sketchWidget, wire->id(), wire->colorString(), wire->colorString(), wire->opacity(), wire->opacity(), NULL)); addSubCommand(new WireWidthChangeCommand(sketchWidget, wire->id(), wire->width(), wire->width(), NULL)); foreach (ConnectorItem * toConnectorItem, wire->connector0()->connectedToItems()) { addSubCommand(new ChangeConnectionCommand(sketchWidget, BaseCommand::CrossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), wire->id(), "connector0", ViewLayer::specFromID(wire->viewLayerID()), false, NULL)); } foreach (ConnectorItem * toConnectorItem, wire->connector1()->connectedToItems()) { addSubCommand(new ChangeConnectionCommand(sketchWidget, BaseCommand::CrossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), wire->id(), "connector1", ViewLayer::specFromID(wire->viewLayerID()), false, NULL)); } addSubCommand(new DeleteItemCommand(sketchWidget, BaseCommand::CrossView, ModuleIDNames::WireModuleIDName, wire->viewLayerPlacement(), wire->getViewGeometry(), wire->id(), wire->modelPart()->modelIndex(), NULL)); } bool CleanUpWiresCommand::hasTraces(SketchWidget * sketchWidget) { return m_sketchWidgets.contains(sketchWidget); } QString CleanUpWiresCommand::getParamString() const { return QString("CleanUpWiresCommand ") + BaseCommand::getParamString() + QString(" direction %1").arg(m_direction); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// CleanUpRatsnestsCommand::CleanUpRatsnestsCommand(SketchWidget* sketchWidget, CleanUpWiresCommand::Direction direction, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { if (direction == CleanUpWiresCommand::UndoOnly) m_undoOnly = true; if (direction == CleanUpWiresCommand::RedoOnly) m_redoOnly = true; } void CleanUpRatsnestsCommand::undo() { if (m_undoOnly) { m_sketchWidget->cleanupRatsnests(true); } BaseCommand::undo(); } void CleanUpRatsnestsCommand::redo() { if (m_redoOnly) { m_sketchWidget->cleanupRatsnests(true); } BaseCommand::redo(); } QString CleanUpRatsnestsCommand::getParamString() const { return QString("CleanUpRatsnestsCommand ") + BaseCommand::getParamString() ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// WireColorChangeCommand::WireColorChangeCommand(SketchWidget* sketchWidget, long wireId, const QString &oldColor, const QString &newColor, double oldOpacity, double newOpacity, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_wireId = wireId; m_oldColor = oldColor; m_newColor = newColor; m_oldOpacity = oldOpacity; m_newOpacity = newOpacity; } void WireColorChangeCommand::undo() { m_sketchWidget->changeWireColor(m_wireId, m_oldColor, m_oldOpacity); BaseCommand::undo(); } void WireColorChangeCommand::redo() { m_sketchWidget->changeWireColor(m_wireId, m_newColor, m_newOpacity); BaseCommand::redo(); } QString WireColorChangeCommand::getParamString() const { return QString("WireColorChangeCommand ") + BaseCommand::getParamString() + QString(" id:%1 oldcolor:%2 oldop:%3 newcolor:%4 newop:%5") .arg(m_wireId).arg(m_oldColor).arg(m_oldOpacity).arg(m_newColor).arg(m_newOpacity); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// WireWidthChangeCommand::WireWidthChangeCommand(SketchWidget* sketchWidget, long wireId, double oldWidth, double newWidth, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_wireId = wireId; m_oldWidth = oldWidth; m_newWidth = newWidth; } void WireWidthChangeCommand::undo() { m_sketchWidget->changeWireWidth(m_wireId, m_oldWidth); BaseCommand::undo(); } void WireWidthChangeCommand::redo() { m_sketchWidget->changeWireWidth(m_wireId, m_newWidth); BaseCommand::redo(); } QString WireWidthChangeCommand::getParamString() const { return QString("WireWidthChangeCommand ") + BaseCommand::getParamString() + QString(" id:%1 oldw:%2 neww:%3") .arg(m_wireId).arg(m_oldWidth).arg(m_newWidth); } /////////////////////////////////////////// RoutingStatusCommand::RoutingStatusCommand(SketchWidget * sketchWidget, const RoutingStatus & oldRoutingStatus, const RoutingStatus & newRoutingStatus, QUndoCommand * parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_oldRoutingStatus = oldRoutingStatus; m_newRoutingStatus = newRoutingStatus; } void RoutingStatusCommand::undo() { m_sketchWidget->forwardRoutingStatus(m_oldRoutingStatus); BaseCommand::undo(); } void RoutingStatusCommand::redo() { m_sketchWidget->forwardRoutingStatus(m_newRoutingStatus); BaseCommand::redo(); } QString RoutingStatusCommand::getParamString() const { return QString("RoutingStatusCommand ") + BaseCommand::getParamString() + QString(" oldnet:%1 oldnetrouted:%2 oldconnectors:%3 oldjumpers:%4 newnet:%51 newnetrouted:%6 newconnectors:%7 newjumpers:%8 ") .arg(m_oldRoutingStatus.m_netCount).arg(m_oldRoutingStatus.m_netRoutedCount).arg(m_oldRoutingStatus.m_connectorsLeftToRoute).arg(m_oldRoutingStatus.m_jumperItemCount) .arg(m_newRoutingStatus.m_netCount).arg(m_newRoutingStatus.m_netRoutedCount).arg(m_newRoutingStatus.m_connectorsLeftToRoute).arg(m_newRoutingStatus.m_jumperItemCount); } /////////////////////////////////////////////// ShowLabelFirstTimeCommand::ShowLabelFirstTimeCommand(SketchWidget *sketchWidget, CrossViewType crossView, long id, bool oldVis, bool newVis, QUndoCommand *parent) : BaseCommand(crossView, sketchWidget, parent) { m_itemID = id; m_oldVis = oldVis; m_newVis = newVis; } void ShowLabelFirstTimeCommand::undo() { BaseCommand::undo(); } void ShowLabelFirstTimeCommand::redo() { m_sketchWidget->showLabelFirstTime(m_itemID, m_newVis, true); BaseCommand::redo(); } QString ShowLabelFirstTimeCommand::getParamString() const { return QString("ShowLabelFirstTimeCommand ") + BaseCommand::getParamString() + QString(" id:%1 %2 %3") .arg(m_itemID).arg(m_oldVis).arg(m_newVis); } /////////////////////////////////////////////// RestoreLabelCommand::RestoreLabelCommand(SketchWidget *sketchWidget,long id, QDomElement & element, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = id; m_element = element; // seems to be safe to keep a copy of the element even though the document may no longer exist } void RestoreLabelCommand::undo() { BaseCommand::undo(); } void RestoreLabelCommand::redo() { m_sketchWidget->restorePartLabel(m_itemID, m_element); BaseCommand::redo(); } QString RestoreLabelCommand::getParamString() const { return QString("RestoreLabelCommand ") + BaseCommand::getParamString() + QString(" id:%1") .arg(m_itemID); } /////////////////////////////////////////////// MoveLabelCommand::MoveLabelCommand(SketchWidget *sketchWidget, long id, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = id; m_oldPos = oldPos; m_newPos = newPos; m_oldOffset = oldOffset; m_newOffset = newOffset; } void MoveLabelCommand::undo() { m_sketchWidget->movePartLabel(m_itemID, m_oldPos, m_oldOffset); BaseCommand::undo(); } void MoveLabelCommand::redo() { m_sketchWidget->movePartLabel(m_itemID, m_newPos, m_newOffset); BaseCommand::redo(); } QString MoveLabelCommand::getParamString() const { return QString("MoveLabelCommand ") + BaseCommand::getParamString() + QString(" id:%1") .arg(m_itemID); } /////////////////////////////////////////////// MoveLockCommand::MoveLockCommand(SketchWidget *sketchWidget, long id, bool oldLock, bool newLock, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = id; m_oldLock = oldLock; m_newLock = newLock; } void MoveLockCommand::undo() { m_sketchWidget->setMoveLock(m_itemID, m_oldLock); BaseCommand::undo(); } void MoveLockCommand::redo() { m_sketchWidget->setMoveLock(m_itemID, m_newLock); BaseCommand::redo(); } QString MoveLockCommand::getParamString() const { return QString("MoveLockCommand ") + BaseCommand::getParamString() + QString(" id:%1 o:%2 n:%3") .arg(m_itemID) .arg(m_oldLock) .arg(m_newLock); } /////////////////////////////////////////////// ChangeLabelTextCommand::ChangeLabelTextCommand(SketchWidget *sketchWidget, long id, const QString & oldText, const QString & newText, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_itemID = id; m_oldText = oldText; m_newText = newText; } void ChangeLabelTextCommand::undo() { m_sketchWidget->setInstanceTitle(m_itemID, m_newText, m_oldText, false, true); BaseCommand::undo(); } void ChangeLabelTextCommand::redo() { m_sketchWidget->setInstanceTitle(m_itemID, m_oldText, m_newText, false, true); BaseCommand::redo(); } QString ChangeLabelTextCommand::getParamString() const { return QString("ChangeLabelTextCommand ") + BaseCommand::getParamString() + QString(" id:%1 old:%2 new:%3") .arg(m_itemID).arg(m_oldText).arg(m_newText); } /////////////////////////////////////////////// IncLabelTextCommand::IncLabelTextCommand(SketchWidget *sketchWidget, long id, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_itemID = id; } void IncLabelTextCommand::undo() { // only used when creating new parts via paste BaseCommand::undo(); } void IncLabelTextCommand::redo() { if (!m_skipFirstRedo) { m_sketchWidget->incInstanceTitle(m_itemID); } BaseCommand::redo(); } QString IncLabelTextCommand::getParamString() const { return QString("IncLabelTextCommand ") + BaseCommand::getParamString() + QString(" id:%1") .arg(m_itemID); }/////////////////////////////////////////////// ChangeNoteTextCommand::ChangeNoteTextCommand(SketchWidget *sketchWidget, long id, const QString & oldText, const QString & newText, QSizeF oldSize, QSizeF newSize, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_itemID = id; m_oldText = oldText; m_newText = newText; m_oldSize = oldSize; m_newSize = newSize; } void ChangeNoteTextCommand::undo() { m_sketchWidget->setNoteText(m_itemID, m_oldText); if (m_oldSize != m_newSize) { m_sketchWidget->resizeNote(m_itemID, m_oldSize); } BaseCommand::undo(); } void ChangeNoteTextCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; return; } m_sketchWidget->setNoteText(m_itemID, m_newText); if (m_oldSize != m_newSize) { m_sketchWidget->resizeNote(m_itemID, m_newSize); } BaseCommand::redo(); } int ChangeNoteTextCommand::id() const { return changeNoteTextCommandID; } bool ChangeNoteTextCommand::mergeWith(const QUndoCommand *other) { // "this" is earlier; "other" is later if (other->id() != id()) { return false; } const ChangeNoteTextCommand * sother = dynamic_cast(other); if (sother == NULL) return false; if (sother->m_itemID != m_itemID) { // this is not the same label so don't merge return false; } m_newSize = sother->m_newSize; m_newText = sother->m_newText; return true; } QString ChangeNoteTextCommand::getParamString() const { return QString("ChangeNoteTextCommand ") + BaseCommand::getParamString() + QString(" id:%1 old:%2 new:%3") .arg(m_itemID).arg(m_oldText).arg(m_newText); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// RotateFlipLabelCommand::RotateFlipLabelCommand(SketchWidget* sketchWidget, long itemID, double degrees, Qt::Orientations orientation, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_degrees = degrees; m_orientation = orientation; } void RotateFlipLabelCommand::undo() { m_sketchWidget->rotateFlipPartLabel(m_itemID, -m_degrees, m_orientation); BaseCommand::undo(); } void RotateFlipLabelCommand::redo() { m_sketchWidget->rotateFlipPartLabel(m_itemID, m_degrees, m_orientation); BaseCommand::redo(); } QString RotateFlipLabelCommand::getParamString() const { return QString("RotateFlipLabelCommand ") + BaseCommand::getParamString() + QString(" id:%1 degrees:%2 orientation:%3") .arg(m_itemID).arg(m_degrees).arg(m_orientation); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ResizeNoteCommand::ResizeNoteCommand(SketchWidget* sketchWidget, long itemID, const QSizeF & oldSize, const QSizeF & newSize, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_oldSize = oldSize; m_newSize = newSize; } void ResizeNoteCommand::undo() { m_sketchWidget->resizeNote(m_itemID, m_oldSize); BaseCommand::undo(); } void ResizeNoteCommand::redo() { m_sketchWidget->resizeNote(m_itemID, m_newSize); BaseCommand::redo(); } QString ResizeNoteCommand::getParamString() const { return QString("ResizeNoteCommand ") + BaseCommand::getParamString() + QString(" id:%1 oldsz:%2 %3 newsz:%4 %5") .arg(m_itemID).arg(m_oldSize.width()).arg(m_oldSize.height()).arg(m_newSize.width()).arg(m_newSize.height()); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ResizeBoardCommand::ResizeBoardCommand(SketchWidget * sketchWidget, long itemID, double oldWidth, double oldHeight, double newWidth, double newHeight, QUndoCommand * parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_oldWidth = oldWidth; m_newWidth = newWidth; m_oldHeight = oldHeight; m_newHeight = newHeight; } void ResizeBoardCommand::undo() { if (!m_redoOnly) { m_sketchWidget->resizeBoard(m_itemID, m_oldWidth, m_oldHeight); } BaseCommand::undo(); } void ResizeBoardCommand::redo() { if (!m_undoOnly) { m_sketchWidget->resizeBoard(m_itemID, m_newWidth, m_newHeight); } BaseCommand::redo(); } QString ResizeBoardCommand::getParamString() const { return QString("ResizeBoardCommand ") + BaseCommand::getParamString() + QString(" id:%1 ow:%2 oh:%3 nw:%4 nh:%5") .arg(m_itemID) .arg(m_oldWidth) .arg(m_oldHeight) .arg(m_newWidth) .arg(m_newHeight); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// TransformItemCommand::TransformItemCommand(SketchWidget *sketchWidget, long id, const QMatrix & oldMatrix, const QMatrix & newMatrix, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = id; m_oldMatrix = oldMatrix; m_newMatrix = newMatrix; } void TransformItemCommand::undo() { m_sketchWidget->transformItem(m_itemID, m_oldMatrix); BaseCommand::undo(); } void TransformItemCommand::redo() { m_sketchWidget->transformItem(m_itemID, m_newMatrix); BaseCommand::redo(); } QString TransformItemCommand::getParamString() const { return QString("TransformItemCommand ") + BaseCommand::getParamString() + QString(" id:%1") .arg(m_itemID); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// SetResistanceCommand::SetResistanceCommand(SketchWidget * sketchWidget, long itemID, QString oldResistance, QString newResistance, QString oldPinSpacing, QString newPinSpacing, QUndoCommand * parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_itemID = itemID; m_oldResistance = oldResistance; m_newResistance = newResistance; m_oldPinSpacing = oldPinSpacing; m_newPinSpacing = newPinSpacing; } void SetResistanceCommand::undo() { m_sketchWidget->setResistance(m_itemID, m_oldResistance, m_oldPinSpacing, true); BaseCommand::undo(); } void SetResistanceCommand::redo() { m_sketchWidget->setResistance(m_itemID, m_newResistance, m_newPinSpacing, true); BaseCommand::redo(); } QString SetResistanceCommand::getParamString() const { return QString("SetResistanceCommand ") + BaseCommand::getParamString() + QString(" id:%1 ov:%2 nv:%3") .arg(m_itemID) .arg(m_oldResistance) .arg(m_newResistance); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// SetPropCommand::SetPropCommand(SketchWidget * sketchWidget, long itemID, QString prop, QString oldValue, QString newValue, bool redraw, QUndoCommand * parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_redraw = redraw; m_itemID = itemID; m_prop = prop; m_oldValue = oldValue; m_newValue = newValue; } void SetPropCommand::undo() { m_sketchWidget->setProp(m_itemID, m_prop, m_oldValue, m_redraw, true); BaseCommand::undo(); } void SetPropCommand::redo() { m_sketchWidget->setProp(m_itemID, m_prop, m_newValue, m_redraw, true); BaseCommand::redo(); } QString SetPropCommand::getParamString() const { return QString("SetPropCommand ") + BaseCommand::getParamString() + QString(" id:%1 p:%2 o:%3 n:%4") .arg(m_itemID) .arg(m_prop) .arg(m_oldValue) .arg(m_newValue); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ResizeJumperItemCommand::ResizeJumperItemCommand(SketchWidget * sketchWidget, long itemID, QPointF oldPos, QPointF oldC0, QPointF oldC1, QPointF newPos, QPointF newC0, QPointF newC1, QUndoCommand * parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = itemID; m_oldPos = oldPos; m_newPos = newPos; m_oldC0 = oldC0; m_newC0 = newC0; m_oldC1 = oldC1; m_newC1 = newC1; } void ResizeJumperItemCommand::undo() { m_sketchWidget->resizeJumperItem(m_itemID, m_oldPos, m_oldC0, m_oldC1); BaseCommand::undo(); } void ResizeJumperItemCommand::redo() { m_sketchWidget->resizeJumperItem(m_itemID, m_newPos, m_newC0, m_newC1); BaseCommand::redo(); } QString ResizeJumperItemCommand::getParamString() const { return QString("ResizeJumperItemCommand ") + BaseCommand::getParamString() + QString(" id:%1 op:%2,%3 oc0:%4,%5 oc1:%6,%7 np:%8,%9 nc0:%10,%11 nc1:%12,%13") .arg(m_itemID) .arg(m_oldPos.x()).arg(m_oldPos.y()) .arg(m_oldC0.x()).arg(m_oldC0.y()) .arg(m_oldC1.x()).arg(m_oldC1.y()) .arg(m_newPos.x()).arg(m_newPos.y()) .arg(m_newC0.x()).arg(m_newC0.y()) .arg(m_newC1.x()).arg(m_newC1.y()) ; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ShowLabelCommand::ShowLabelCommand(class SketchWidget *sketchWidget, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { } void ShowLabelCommand::undo() { foreach (long id, m_idStates.keys()) { m_sketchWidget->showPartLabel(id, (m_idStates.value(id) & 2) != 0); } BaseCommand::undo(); } void ShowLabelCommand::redo() { foreach (long id, m_idStates.keys()) { m_sketchWidget->showPartLabel(id, (m_idStates.value(id) & 1) != 0); } BaseCommand::redo(); } void ShowLabelCommand::add(long id, bool prev, bool post) { int v = 0; if (prev) v += 2; if (post) v += 1; m_idStates.insert(id, v); } QString ShowLabelCommand::getParamString() const { return QString("ShowLabelCommand ") + BaseCommand::getParamString(); } /////////////////////////////////////////////// LoadLogoImageCommand::LoadLogoImageCommand(SketchWidget *sketchWidget, long id, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_itemID = id; m_oldFilename = oldFilename; m_newFilename = newFilename; m_oldAspectRatio = oldAspectRatio; m_oldSvg = oldSvg; m_addName = addName; } void LoadLogoImageCommand::undo() { if (!m_redoOnly) { m_sketchWidget->loadLogoImage(m_itemID, m_oldSvg, m_oldAspectRatio, m_oldFilename); } BaseCommand::undo(); } void LoadLogoImageCommand::redo() { if (m_newFilename.isEmpty()) { } else if (!m_undoOnly) { m_sketchWidget->loadLogoImage(m_itemID, m_newFilename, m_addName); } BaseCommand::redo(); } QString LoadLogoImageCommand::getParamString() const { return QString("LoadLogoImageCommand ") + BaseCommand::getParamString() + QString(" id:%1 old:%2 new:%3") .arg(m_itemID).arg(m_oldFilename).arg(m_newFilename); } /////////////////////////////////////////////// ChangeBoardLayersCommand::ChangeBoardLayersCommand(SketchWidget *sketchWidget, int oldLayers, int newLayers, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_oldLayers = oldLayers; m_newLayers = newLayers; } void ChangeBoardLayersCommand::undo() { m_sketchWidget->changeBoardLayers(m_oldLayers, true); for (int i = childCount() - 1; i >= 0; i--) { ((QUndoCommand *) child(i))->undo(); } BaseCommand::undo(); } void ChangeBoardLayersCommand::redo() { m_sketchWidget->changeBoardLayers(m_newLayers, true); for (int i = 0; i < childCount(); i++) { ((QUndoCommand *) child(i))->redo(); } BaseCommand::redo(); } QString ChangeBoardLayersCommand::getParamString() const { return QString("ChangeBoardLayersCommand ") + BaseCommand::getParamString() + QString(" old:%1 new:%2") .arg(m_oldLayers).arg(m_newLayers); } /////////////////////////////////////////////// SetDropOffsetCommand::SetDropOffsetCommand(SketchWidget *sketchWidget, long id, QPointF dropOffset, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_itemID = id; m_dropOffset = dropOffset; } void SetDropOffsetCommand::undo() { // only used when creating new parts BaseCommand::undo(); } void SetDropOffsetCommand::redo() { m_sketchWidget->setItemDropOffset(m_itemID, m_dropOffset); BaseCommand::redo(); } QString SetDropOffsetCommand::getParamString() const { return QString("SetDropOffsetCommand ") + BaseCommand::getParamString() + QString(" id:%1 %2,%3") .arg(m_itemID).arg(m_dropOffset.x()).arg(m_dropOffset.y()); } /////////////////////////////////////////////// RenamePinsCommand::RenamePinsCommand(SketchWidget *sketchWidget, long id, const QStringList & oldOnes, const QStringList & newOnes, bool singleRow, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_oldLabels = oldOnes; m_newLabels = newOnes; m_itemID = id; m_singleRow = singleRow; } void RenamePinsCommand::undo() { m_sketchWidget->renamePins(m_itemID, m_oldLabels, m_singleRow); BaseCommand::undo(); } void RenamePinsCommand::redo() { m_sketchWidget->renamePins(m_itemID, m_newLabels, m_singleRow); BaseCommand::redo(); } QString RenamePinsCommand::getParamString() const { return QString("RenamePinsCommand ") + BaseCommand::getParamString() + QString(" id:%1 sr:%2") .arg(m_itemID).arg(m_singleRow); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// GroundFillSeedCommand::GroundFillSeedCommand(SketchWidget* sketchWidget, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { setText(QObject::tr("Set Ground Fill Seed")); } void GroundFillSeedCommand::undo() { foreach(GFSThing gfsThing, m_items) { m_sketchWidget->setGroundFillSeed(gfsThing.id, gfsThing.connectorID, !gfsThing.seed); } BaseCommand::undo(); } void GroundFillSeedCommand::redo() { foreach(GFSThing gfsThing, m_items) { m_sketchWidget->setGroundFillSeed(gfsThing.id, gfsThing.connectorID, gfsThing.seed); } BaseCommand::redo(); } void GroundFillSeedCommand::addItem(long id, const QString & connectorID, bool seed) { GFSThing gfsThing; gfsThing.id = id; gfsThing.connectorID = connectorID; gfsThing.seed = seed; m_items.append(gfsThing); } QString GroundFillSeedCommand::getParamString() const { return QString("GroundFillSeedCommand ") + BaseCommand::getParamString() + QString(" items:%1") .arg(m_items.count()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// WireExtrasCommand::WireExtrasCommand(SketchWidget* sketchWidget, long fromID, const QDomElement & oldExtras, const QDomElement & newExtras, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_newExtras = newExtras; m_oldExtras = oldExtras; } void WireExtrasCommand::undo() { if (!m_redoOnly) { m_sketchWidget->setWireExtras(m_fromID, m_oldExtras); } BaseCommand::undo(); } void WireExtrasCommand::redo() { if (!m_undoOnly) { m_sketchWidget->setWireExtras(m_fromID, m_newExtras); } BaseCommand::redo(); } QString WireExtrasCommand::getParamString() const { return QString("WireExtrasCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 ") .arg(m_fromID) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// HidePartLayerCommand::HidePartLayerCommand(SketchWidget *sketchWidget, long fromID, ViewLayer::ViewLayerID layerID, bool wasHidden, bool isHidden, QUndoCommand *parent) : BaseCommand(BaseCommand::SingleView, sketchWidget, parent) { m_fromID = fromID; m_wasHidden = wasHidden; m_isHidden = isHidden; m_layerID = layerID; } void HidePartLayerCommand::undo() { m_sketchWidget->hidePartLayer(m_fromID, m_layerID, m_wasHidden); BaseCommand::undo(); } void HidePartLayerCommand::redo() { m_sketchWidget->hidePartLayer(m_fromID, m_layerID, m_isHidden); BaseCommand::redo(); } QString HidePartLayerCommand::getParamString() const { return QString("HidePartLayerCommand ") + BaseCommand::getParamString() + QString(" fromid:%1 l:%2 was:%3 is:%4") .arg(m_fromID) .arg(m_layerID) .arg(m_wasHidden) .arg(m_isHidden) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// AddSubpartCommand::AddSubpartCommand(SketchWidget *sketchWidget, CrossViewType crossView, long id, long subpartID, QUndoCommand *parent) : BaseCommand(crossView, sketchWidget, parent) { m_itemID = id; m_subpartItemID = subpartID; } void AddSubpartCommand::undo() { if (!m_redoOnly) { m_sketchWidget->addSubpart(m_itemID, m_subpartItemID, true); } BaseCommand::undo(); } void AddSubpartCommand::redo() { if (!m_undoOnly) { m_sketchWidget->addSubpart(m_itemID, m_subpartItemID, true); } BaseCommand::redo(); } QString AddSubpartCommand::getParamString() const { return QString("AddSubpartCommand ") + BaseCommand::getParamString() + QString(" id:%1 subpart id:%2") .arg(m_itemID) .arg(m_subpartItemID) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PackItemsCommand::PackItemsCommand(SketchWidget *sketchWidget, int columns, const QList & ids, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, sketchWidget, parent) { m_ids = ids; m_columns = columns; m_firstTime = true; } void PackItemsCommand::undo() { BaseCommand::undo(); } void PackItemsCommand::redo() { if (m_firstTime) { m_sketchWidget->packItems(m_columns, m_ids, m_parentCommand, true); m_firstTime = false; } BaseCommand::redo(); } QString PackItemsCommand::getParamString() const { return QString("PackItemsCommand ") + BaseCommand::getParamString() + QString(" columns:%1 count:%2") .arg(m_columns) .arg(m_ids.count()) ; } //////////////////////////////////// TemporaryCommand::TemporaryCommand(const QString & text) : QUndoCommand(text) { m_enabled = true; } TemporaryCommand::~TemporaryCommand() { } void TemporaryCommand::setEnabled(bool enabled) { m_enabled = enabled; } void TemporaryCommand::redo() { if (m_enabled) { QUndoCommand::redo(); } } fritzing-app-0.9.2b/src/commands.h000066400000000000000000000645471250202676700170660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify\ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #ifndef COMMANDS_H #define COMMANDS_H #include #include #include #include "viewgeometry.h" #include "viewlayer.h" #include "routingstatus.h" #include "utils/misc.h" #include "items/itembase.h" ///////////////////////////////////////////// class CommandProgress : public QObject { Q_OBJECT public: CommandProgress(); void setActive(bool); bool active(); void emitUndo(); void emitRedo(); signals: void incUndo(); void incRedo(); protected: bool m_active; }; ///////////////////////////////////////////// class BaseCommand : public QUndoCommand { public: enum CrossViewType { SingleView, CrossView }; public: BaseCommand(BaseCommand::CrossViewType, class SketchWidget*, QUndoCommand* parent); ~BaseCommand(); BaseCommand::CrossViewType crossViewType() const; void setCrossViewType(BaseCommand::CrossViewType); class SketchWidget* sketchWidget() const; int subCommandCount() const; const BaseCommand * subCommand(int index) const; virtual QString getDebugString() const; const QUndoCommand * parentCommand() const; void addSubCommand(BaseCommand * subCommand); void subUndo(); void subRedo(); void subUndo(int index); void subRedo(int index); int index() const; void setUndoOnly(); void setRedoOnly(); void setSkipFirstRedo(); void undo(); void redo(); static int totalChildCount(const QUndoCommand *); static CommandProgress * initProgress(); static void clearProgress(); protected: virtual QString getParamString() const; static int nextIndex; protected: BaseCommand::CrossViewType m_crossViewType; class SketchWidget *m_sketchWidget; QList m_commands; QUndoCommand * m_parentCommand; int m_index; bool m_undoOnly; bool m_redoOnly; bool m_skipFirstRedo; static CommandProgress m_commandProgress; }; ///////////////////////////////////////////// class AddDeleteItemCommand : public BaseCommand { public: AddDeleteItemCommand(class SketchWidget * sketchWidget, BaseCommand::CrossViewType, QString moduleID, ViewLayer::ViewLayerPlacement, ViewGeometry &, qint64 id, long modelIndex, QUndoCommand *parent); long itemID() const; void setDropOrigin(class SketchWidget *); class SketchWidget * dropOrigin(); protected: QString getParamString() const; protected: QString m_moduleID; long m_itemID; ViewGeometry m_viewGeometry; long m_modelIndex; class SketchWidget * m_dropOrigin; ViewLayer::ViewLayerPlacement m_viewLayerPlacement; }; ///////////////////////////////////////////// class AddItemCommand : public AddDeleteItemCommand { public: AddItemCommand(class SketchWidget *sketchWidget, BaseCommand::CrossViewType, QString moduleID, ViewLayer::ViewLayerPlacement, ViewGeometry &, qint64 id, bool updateInfoView, long modelIndex, QUndoCommand *parent); void undo(); void redo(); void addRestoreIndexesCommand(class RestoreIndexesCommand *); protected: QString getParamString() const; protected: bool m_updateInfoView; bool m_module; RestoreIndexesCommand * m_restoreIndexesCommand; }; ///////////////////////////////////////////// class DeleteItemCommand : public AddDeleteItemCommand { public: DeleteItemCommand(class SketchWidget *sketchWidget, BaseCommand::CrossViewType, QString moduleID, ViewLayer::ViewLayerPlacement, ViewGeometry &, qint64 id, long modelIndex, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; }; ///////////////////////////////////////////// class MoveItemCommand : public BaseCommand { public: MoveItemCommand(class SketchWidget *sketchWidget, long id, ViewGeometry & oldG, ViewGeometry & newG, bool updateRatsnest, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: bool m_updateRatsnest; long m_itemID; ViewGeometry m_old; ViewGeometry m_new; }; ///////////////////////////////////////////// class SimpleMoveItemCommand : public BaseCommand { public: SimpleMoveItemCommand(class SketchWidget *sketchWidget, long id, QPointF & oldP, QPointF & newP, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QPointF m_old; QPointF m_new; }; ///////////////////////////////////////////// struct MoveItemThing { long id; QPointF oldPos; QPointF newPos; }; class MoveItemsCommand : public BaseCommand { public: MoveItemsCommand(class SketchWidget *sketchWidget, bool updateRatsnest, QUndoCommand *parent); void undo(); void redo(); void addItem(long id, const QPointF & oldPos, const QPointF & newPos); void addWire(long id, const QString & connectorID); protected: QString getParamString() const; protected: bool m_updateRatsnest; QHash m_wires; QList m_items; }; ///////////////////////////////////////////// class RotateItemCommand : public BaseCommand { public: RotateItemCommand(class SketchWidget *sketchWidget, long id, double degrees, QUndoCommand *parent); void undo(); void redo(); protected: virtual QString getParamString() const; protected: long m_itemID; double m_degrees; }; ///////////////////////////////////////////// class FlipItemCommand : public BaseCommand { public: FlipItemCommand(class SketchWidget *sketchWidget, long id, Qt::Orientations orientation, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; Qt::Orientations m_orientation; }; ///////////////////////////////////////////// class TransformItemCommand : public BaseCommand { public: TransformItemCommand(class SketchWidget *sketchWidget, long id, const class QMatrix & oldMatrix, const class QMatrix & newMatrix, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QMatrix m_oldMatrix; QMatrix m_newMatrix; }; ///////////////////////////////////////////// class ChangeConnectionCommand : public BaseCommand { public: ChangeConnectionCommand(class SketchWidget * sketchWidget, BaseCommand::CrossViewType, long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, QUndoCommand * parent); void undo(); void redo(); void setUpdateConnections(bool updatem); void disable(); protected: QString getParamString() const; protected: long m_fromID; long m_toID; QString m_fromConnectorID; QString m_toConnectorID; bool m_connect; bool m_updateConnections; ViewLayer::ViewLayerPlacement m_viewLayerPlacement; bool m_enabled; }; ///////////////////////////////////////////// class ChangeWireCommand : public BaseCommand { public: ChangeWireCommand(class SketchWidget *sketchWidget, long fromID, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, bool updateConnections, bool updateRatsnest, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: bool m_updateRatsnest; long m_fromID; QLineF m_newLine; QLineF m_oldLine; QPointF m_newPos; QPointF m_oldPos; bool m_updateConnections; }; ///////////////////////////////////////////// class ChangeWireCurveCommand : public BaseCommand { public: ChangeWireCurveCommand(class SketchWidget *sketchWidget, long fromID, const class Bezier * oldBezier, const class Bezier * newBezier, bool wasAutoroutable, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; class Bezier * m_newBezier; class Bezier * m_oldBezier; bool m_wasAutoroutable; }; ///////////////////////////////////////////// class ChangeLegCommand : public BaseCommand { public: ChangeLegCommand(class SketchWidget *sketchWidget, long fromID, const QString & fromConnectorID, const QPolygonF & oldLeg, const QPolygonF & newLeg, bool relative, bool active, const QString & why, QUndoCommand *parent); void undo(); void redo(); void setSimple(); protected: QString getParamString() const; protected: QString m_fromConnectorID; long m_fromID; QPolygonF m_newLeg; QPolygonF m_oldLeg; bool m_relative; bool m_active; bool m_simple; QString m_why; }; ///////////////////////////////////////////// class MoveLegBendpointCommand : public BaseCommand { public: MoveLegBendpointCommand(class SketchWidget *sketchWidget, long fromID, const QString & fromConnectorID, int index, QPointF oldPos, QPointF newPos, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_fromConnectorID; long m_fromID; QPointF m_newPos; QPointF m_oldPos; }; ///////////////////////////////////////////// class ChangeLegCurveCommand : public BaseCommand { public: ChangeLegCurveCommand(class SketchWidget *sketchWidget, long fromID, const QString & fromConnectorID, int index, const class Bezier * oldBezier, const class Bezier * newBezier, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; class Bezier * m_newBezier; class Bezier * m_oldBezier; QString m_fromConnectorID; int m_index; }; ///////////////////////////////////////////// class ChangeLegBendpointCommand : public BaseCommand { public: ChangeLegBendpointCommand(class SketchWidget *sketchWidget, long fromID, const QString & fromConnectorID, int oldCount, int newCount, int index, QPointF pos, const class Bezier *, const class Bezier *, const class Bezier *, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; class Bezier * m_bezier0; class Bezier * m_bezier1; class Bezier * m_bezier2; QString m_fromConnectorID; int m_index; int m_oldCount; int m_newCount; QPointF m_pos; }; ///////////////////////////////////////////// class RotateLegCommand : public BaseCommand { public: RotateLegCommand(class SketchWidget *sketchWidget, long fromID, const QString & fromConnectorID, const QPolygonF & oldLeg, bool active, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_fromConnectorID; long m_fromID; QPolygonF m_oldLeg; bool m_active; }; ///////////////////////////////////////////// class ChangeLayerCommand : public BaseCommand { public: ChangeLayerCommand(class SketchWidget *sketchWidget, long fromID, double oldZ, double newZ, ViewLayer::ViewLayerID oldLayer, ViewLayer::ViewLayerID newLayer, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; double m_newZ; double m_oldZ; ViewLayer::ViewLayerID m_newLayer; ViewLayer::ViewLayerID m_oldLayer; }; ///////////////////////////////////////////// class SelectItemCommand : public BaseCommand { public: enum SelectItemType { NormalSelect, NormalDeselect, SelectAll, DeselectAll }; public: SelectItemCommand(class SketchWidget *sketchWidget, SelectItemType type, QUndoCommand *parent); void undo(); void redo(); void addUndo(long id); void addRedo(long id); void clearRedo(); int id() const; bool mergeWith(const QUndoCommand *other); void copyUndo(SelectItemCommand * sother); void copyRedo(SelectItemCommand * sother); void setSelectItemType(SelectItemType); bool updated(); void setUpdated(bool); protected: void selectAllFromStack(QList & stack, bool select, bool updateInfoView); QString getParamString() const; protected: QList m_undoIDs; QList m_redoIDs; SelectItemType m_type; bool m_updated; protected: static int selectItemCommandID; }; ///////////////////////////////////////////// class ChangeZCommand : public BaseCommand { public: ChangeZCommand(class SketchWidget *sketchWidget, QUndoCommand *parent); ~ChangeZCommand(); void addTriplet(long id, double oldZ, double newZ); void undo(); void redo(); protected: QString getParamString() const; protected: static double first(RealPair *); static double second(RealPair *); protected: QHash m_triplets; }; struct StickyThing { SketchWidget * sketchWidget; bool stickem; long fromID; long toID; }; ///////////////////////////////////////////// class CheckStickyCommand : public BaseCommand { public: enum CheckType { UndoOnly = 0, RedoOnly, RemoveOnly }; public: CheckStickyCommand(class SketchWidget *sketchWidget, BaseCommand::CrossViewType, long itemID, bool checkCurrent, CheckType, QUndoCommand *parent); ~CheckStickyCommand(); void undo(); void redo(); void stick(SketchWidget *, long fromID, long toID, bool stickem); protected: QString getParamString() const; protected: long m_itemID; QList m_stickyList; bool m_checkCurrent; CheckType m_checkType; }; ///////////////////////////////////////////// class WireColorChangeCommand : public BaseCommand { public: WireColorChangeCommand( SketchWidget* sketchWidget, long wireId, const QString &oldColor, const QString &newColor, double oldOpacity, double newOpacity, QUndoCommand *parent=0); void undo(); void redo(); protected: QString getParamString() const; protected: long m_wireId; QString m_oldColor; QString m_newColor; double m_oldOpacity; double m_newOpacity; }; ///////////////////////////////////////////// class WireWidthChangeCommand : public BaseCommand { public: WireWidthChangeCommand( SketchWidget* sketchWidget, long wireId, double oldWidth, double newWidth, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_wireId; double m_oldWidth; double m_newWidth; }; ///////////////////////////////////////////// class RoutingStatusCommand : public BaseCommand { public: RoutingStatusCommand(class SketchWidget *, const RoutingStatus & oldRoutingStatus, const RoutingStatus & newRoutingStatus, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; protected: RoutingStatus m_oldRoutingStatus; RoutingStatus m_newRoutingStatus; }; ///////////////////////////////////////////// struct RatsnestConnectThing { long id; QString connectorID; bool connect; }; class CleanUpWiresCommand : public BaseCommand { public: enum Direction { UndoOnly = 0, RedoOnly, Noop }; public: CleanUpWiresCommand(class SketchWidget * sketchWidget, CleanUpWiresCommand::Direction, QUndoCommand * parent); void undo(); void redo(); void addRoutingStatus(SketchWidget *, const RoutingStatus & oldRoutingStatus, const RoutingStatus & newRoutingStatus); void setDirection(CleanUpWiresCommand::Direction); void addTrace(SketchWidget * sketchWidget, Wire * wire); bool hasTraces(SketchWidget *); void addRatsnestConnect(long id, const QString & connectorID, bool connect); CleanUpWiresCommand::Direction direction(); protected: QString getParamString() const; protected: QSet m_sketchWidgets; QList m_ratsnestConnectThings; CleanUpWiresCommand::Direction m_direction; }; ///////////////////////////////////////////// class CleanUpRatsnestsCommand : public BaseCommand { public: CleanUpRatsnestsCommand(class SketchWidget * sketchWidget, CleanUpWiresCommand::Direction, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; }; ///////////////////////////////////////////// class RestoreLabelCommand : public BaseCommand { public: RestoreLabelCommand(class SketchWidget *sketchWidget, long id, QDomElement &, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QDomElement m_element; }; ///////////////////////////////////////////// class ShowLabelFirstTimeCommand : public BaseCommand { public: ShowLabelFirstTimeCommand(class SketchWidget *sketchWidget, CrossViewType crossView, long id, bool oldVis, bool newVis, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; bool m_oldVis; bool m_newVis; }; ///////////////////////////////////////////// class MoveLabelCommand : public BaseCommand { public: MoveLabelCommand(class SketchWidget *sketchWidget, long id, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QPointF m_oldPos; QPointF m_newPos; QPointF m_oldOffset; QPointF m_newOffset; }; ///////////////////////////////////////////// class MoveLockCommand : public BaseCommand { public: MoveLockCommand(class SketchWidget *sketchWidget, long id, bool oldLock, bool newLock, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; bool m_oldLock; bool m_newLock; }; ///////////////////////////////////////////// class IncLabelTextCommand : public BaseCommand { public: IncLabelTextCommand(class SketchWidget *sketchWidget, long id, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; }; ///////////////////////////////////////////// class ChangeLabelTextCommand : public BaseCommand { public: ChangeLabelTextCommand(class SketchWidget *sketchWidget, long id, const QString & oldText, const QString & newText, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QString m_oldText; QString m_newText; }; ///////////////////////////////////////////// class ChangeNoteTextCommand : public BaseCommand { public: ChangeNoteTextCommand(class SketchWidget *sketchWidget, long id, const QString & oldText, const QString & newText, QSizeF oldSize, QSizeF newSize, QUndoCommand *parent); void undo(); void redo(); int id() const; bool mergeWith(const QUndoCommand *other); protected: QString getParamString() const; protected: long m_itemID; QString m_oldText; QString m_newText; QSizeF m_oldSize; QSizeF m_newSize; static int changeNoteTextCommandID; }; ///////////////////////////////////////////// class RotateFlipLabelCommand : public BaseCommand { public: RotateFlipLabelCommand(class SketchWidget *sketchWidget, long id, double degrees, Qt::Orientations, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; double m_degrees; Qt::Orientations m_orientation; }; ///////////////////////////////////////////// class ResizeNoteCommand : public BaseCommand { public: ResizeNoteCommand(class SketchWidget *sketchWidget, long id, const QSizeF & oldSize, const QSizeF & newSize, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QSizeF m_oldSize; QSizeF m_newSize; }; ///////////////////////////////////////////// class ResizeBoardCommand : public BaseCommand { public: ResizeBoardCommand(class SketchWidget *, long itemID, double oldWidth, double oldHeight, double newWidth, double newHeight, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; protected: double m_oldWidth; double m_oldHeight; double m_newWidth; double m_newHeight; long m_itemID; }; ///////////////////////////////////////////// class SetResistanceCommand : public BaseCommand { public: SetResistanceCommand(class SketchWidget *, long itemID, QString oldResistance, QString newResistance, QString oldPinSpacing, QString newPinSpacing, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_oldResistance; QString m_newResistance; QString m_oldPinSpacing; QString m_newPinSpacing; long m_itemID; }; ///////////////////////////////////////////// class SetPropCommand : public BaseCommand { public: SetPropCommand(class SketchWidget *, long itemID, QString prop, QString oldValue, QString newValue, bool redraw, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; protected: bool m_redraw; QString m_prop; QString m_oldValue; QString m_newValue; long m_itemID; }; ///////////////////////////////////////////// class ResizeJumperItemCommand : public BaseCommand { public: ResizeJumperItemCommand(class SketchWidget *, long itemID, QPointF oldPos, QPointF oldC0, QPointF oldC1, QPointF newPos, QPointF newC0, QPointF newC1, QUndoCommand * parent); void undo(); void redo(); protected: QString getParamString() const; protected: QPointF m_oldPos; QPointF m_oldC0; QPointF m_oldC1; QPointF m_newPos; QPointF m_newC0; QPointF m_newC1; long m_itemID; }; ///////////////////////////////////////////// class ShowLabelCommand : public BaseCommand { public: ShowLabelCommand(class SketchWidget *sketchWidget, QUndoCommand *parent); void undo(); void redo(); void add(long id, bool prev, bool post); protected: QString getParamString() const; protected: QHash m_idStates; }; ///////////////////////////////////////////// class LoadLogoImageCommand : public BaseCommand { public: LoadLogoImageCommand(class SketchWidget *sketchWidget, long id, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QString m_oldSvg; QSizeF m_oldAspectRatio; QString m_oldFilename; QString m_newFilename; bool m_addName; }; ///////////////////////////////////////////// class ChangeBoardLayersCommand : public BaseCommand { public: ChangeBoardLayersCommand(class SketchWidget *sketchWidget, int oldLayers, int newLayers, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: int m_oldLayers; int m_newLayers; }; ///////////////////////////////////////////// class SetDropOffsetCommand : public BaseCommand { public: SetDropOffsetCommand(class SketchWidget *sketchWidget, long id, QPointF dropOffset, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QPointF m_dropOffset; }; ///////////////////////////////////////////// class RenamePinsCommand : public BaseCommand { public: RenamePinsCommand(class SketchWidget *sketchWidget, long id, const QStringList & oldOnes, const QStringList & newOnes, bool singleRow, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; QStringList m_oldLabels; QStringList m_newLabels; bool m_singleRow; }; ///////////////////////////////////////////// struct GFSThing { long id; QString connectorID; bool seed; }; class GroundFillSeedCommand : public BaseCommand { public: GroundFillSeedCommand(class SketchWidget *sketchWidget, QUndoCommand *parent); void undo(); void redo(); void addItem(long id, const QString & connectorID, bool seed); protected: QString getParamString() const; protected: QList m_items; }; ///////////////////////////////////////////// class WireExtrasCommand : public BaseCommand { public: WireExtrasCommand(class SketchWidget *sketchWidget, long fromID, const QDomElement & oldExtras, const QDomElement & newExtras, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; QDomElement m_oldExtras; QDomElement m_newExtras; }; ///////////////////////////////////////////// class HidePartLayerCommand : public BaseCommand { public: HidePartLayerCommand(class SketchWidget *sketchWidget, long fromID, ViewLayer::ViewLayerID layerID, bool wasHidden, bool isHidden, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_fromID; double m_wasHidden; double m_isHidden; ViewLayer::ViewLayerID m_layerID; ViewLayer::ViewLayerID m_oldLayer; }; ///////////////////////////////////////////// class TemporaryCommand : public QUndoCommand { public: TemporaryCommand(const QString & text); ~TemporaryCommand(); void setEnabled(bool); void redo(); protected: bool m_enabled; }; ///////////////////////////////////////////// class AddSubpartCommand : public BaseCommand { public: AddSubpartCommand(class SketchWidget *sketchWidget, CrossViewType crossView, long id, long subpartID, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: long m_itemID; long m_subpartItemID; }; ///////////////////////////////////////////// class PackItemsCommand : public BaseCommand { public: PackItemsCommand(class SketchWidget *sketchWidget, int columns, const QList & ids, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: int m_columns; QList m_ids; bool m_firstTime; }; ///////////////////////////////////////////// #endif // COMMANDS_H fritzing-app-0.9.2b/src/connectors/000077500000000000000000000000001250202676700172515ustar00rootroot00000000000000fritzing-app-0.9.2b/src/connectors/bus.cpp000066400000000000000000000034471250202676700205560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #include "bus.h" #include "busshared.h" #include "../debugdialog.h" #include "connectoritem.h" #include "../model/modelpart.h" Bus::Bus(BusShared * busShared, ModelPart * modelPart) : QObject() { m_busShared = busShared; m_modelPart = modelPart; } const QString & Bus::id() const { if (m_busShared == NULL) return ___emptyString___; return m_busShared->id(); } const QList & Bus::connectors() const { return m_connectors; } void Bus::addConnector(Connector * connector) { // the list of connectors which make up the bus m_connectors.append(connector); } ModelPart * Bus::modelPart() { return m_modelPart; } void Bus::addSubConnector(Connector * subConnector) { m_subConnector = subConnector; } Connector * Bus::subConnector() const { return m_subConnector; }fritzing-app-0.9.2b/src/connectors/bus.h000066400000000000000000000032471250202676700202210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef BUS_H #define BUS_H #include #include #include #include #include #include #include class Bus : public QObject { Q_OBJECT public: Bus(class BusShared *, class ModelPart *); const QString & id() const; void addConnector(class Connector *); class ModelPart * modelPart(); const QList & connectors() const; Connector * subConnector() const; void addSubConnector(Connector *); protected: QList m_connectors; class Connector * m_subConnector; BusShared * m_busShared; QPointer m_modelPart; }; #endif fritzing-app-0.9.2b/src/connectors/busshared.cpp000066400000000000000000000045001250202676700217340ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6309 $: $Author: cohen@irascible.com $: $Date: 2012-08-17 11:16:43 +0200 (Fr, 17. Aug 2012) $ ********************************************************************/ #include "busshared.h" #include "connectorshared.h" #include "../debugdialog.h" #include "connectoritem.h" BusShared::BusShared(const QString & id) { m_id = id; } BusShared::BusShared(const QDomElement & busElement, const QHash > & connectorHash) { m_id = busElement.attribute("id"); QDomElement connector = busElement.firstChildElement("nodeMember"); while (!connector.isNull()) { initConnector(connector, connectorHash); connector = connector.nextSiblingElement("nodeMember"); } } void BusShared::initConnector(QDomElement & connector, const QHash > & connectorHash) { QString id = connector.attribute("connectorId"); if (id.isNull()) return; if (id.isEmpty()) return; ConnectorShared * connectorShared = connectorHash.value(id); if (connectorShared == NULL) { DebugDialog::debug(QString("no connector is found for bus nodeMember %1").arg(id)); return; } m_connectors.append(connectorShared); connectorShared->setBus(this); } void BusShared::addConnectorShared(ConnectorShared * connectorShared) { m_connectors.append(connectorShared); connectorShared->setBus(this); } const QString & BusShared::id() const { return m_id; } const QList & BusShared::connectors() { return m_connectors; } fritzing-app-0.9.2b/src/connectors/busshared.h000066400000000000000000000033031250202676700214010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6309 $: $Author: cohen@irascible.com $: $Date: 2012-08-17 11:16:43 +0200 (Fr, 17. Aug 2012) $ ********************************************************************/ #ifndef BUSSHARED_H #define BUSSHARED_H #include #include #include #include #include #include class BusShared { public: BusShared(const QDomElement & busElement, const QHash > & connectorHash); BusShared(const QString & id); const QString & id() const; const QList & connectors(); void addConnectorShared(class ConnectorShared *); protected: void initConnector(QDomElement & connector, const QHash > & connectorHash); protected: QString m_id; QList m_connectors; }; #endif fritzing-app-0.9.2b/src/connectors/connector.cpp000066400000000000000000000226721250202676700217600ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #include "connector.h" #include "connectorshared.h" #include "connectoritem.h" #include "../debugdialog.h" #include "../model/modelpart.h" #include "bus.h" #include "../fsvgrenderer.h" #include "ercdata.h" QHash Connector::Names; static const QList EmptySvgIdLayerList; static inline int QuickHash(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { return (1000 * viewID) + viewLayerID; } Connector::Connector( ConnectorShared * connectorShared, ModelPart * modelPart) { m_modelPart = modelPart; m_connectorShared = connectorShared; m_bus = NULL; } Connector::~Connector() { //DebugDialog::debug(QString("deleting connector %1 %2").arg((long) this, 0, 16).arg(connectorSharedID())); foreach (ConnectorItem * connectorItem, m_connectorItems.values()) { connectorItem->clearConnector(); } } void Connector::initNames() { if (Names.count() == 0) { Names.insert(Connector::Male, "male"); Names.insert(Connector::Female, "female"); Names.insert(Connector::Wire, "wire"); Names.insert(Connector::Pad, "pad"); } } Connector::ConnectorType Connector::connectorTypeFromName(const QString & name) { QHashIterator i(Names); while (i.hasNext()) { i.next(); if (name.compare(i.value(), Qt::CaseInsensitive ) == 0) { return i.key(); } } return Connector::Unknown; } const QString & Connector::connectorNameFromType(ConnectorType type) { return Names[type]; } Connector::ConnectorType Connector::connectorType() const { if (m_connectorShared != NULL) { return m_connectorShared->connectorType(); } return Connector::Unknown; } ConnectorShared * Connector::connectorShared() { return m_connectorShared; } void Connector::addViewItem(ConnectorItem * item) { //item->debugInfo(QString("add view item c:%1 ci:%2 b:%3").arg((long) this, 0, 16).arg((long) item, 0, 16).arg((long) m_bus.data(), 0, 16)); m_connectorItems.insert(QuickHash(item->attachedToViewID(), item->attachedToViewLayerID()), item); } void Connector::removeViewItem(ConnectorItem * item) { //DebugDialog::debug(QString("remove view item c:%1 ci:%2 b:%3").arg((long) this, 0, 16).arg((long) item, 0, 16).arg((long) m_bus.data(), 0, 16)); m_connectorItems.remove(QuickHash(item->attachedToViewID(), item->attachedToViewLayerID())); } void Connector::connectTo(Connector * connector) { if (this->modelPart() == NULL) { DebugDialog::debug("connecting bus connector 1"); } else if (connector->modelPart() == NULL) { DebugDialog::debug("connecting bus connector 2"); } if (!m_toConnectors.contains(connector)) { m_toConnectors.append(connector); } if (!connector->m_toConnectors.contains(this)) { connector->m_toConnectors.append(this); } } void Connector::disconnectFrom(Connector * connector) { m_toConnectors.removeOne(connector); connector->m_toConnectors.removeOne(this); } void Connector::saveAsPart(QXmlStreamWriter & writer) { writer.writeStartElement("connector"); writer.writeAttribute("id", connectorShared()->id()); writer.writeAttribute("type", connectorShared()->connectorTypeString()); writer.writeAttribute("name", connectorShared()->sharedName()); writer.writeTextElement("description", connectorShared()->description()); writer.writeTextElement("replacedby", connectorShared()->replacedby()); writer.writeStartElement("views"); QMultiHash pins = m_connectorShared->pins(); foreach (ViewLayer::ViewID currView, pins.uniqueKeys()) { writer.writeStartElement(ViewLayer::viewIDXmlName(currView)); foreach (SvgIdLayer * svgIdLayer, pins.values(currView)) { writer.writeStartElement("p"); writeLayerAttr(writer, svgIdLayer->m_svgViewLayerID); writeSvgIdAttr(writer, currView, svgIdLayer->m_svgId); writeTerminalIdAttr(writer, currView, svgIdLayer->m_terminalId); writer.writeEndElement(); } writer.writeEndElement(); } writer.writeEndElement(); writer.writeEndElement(); } void Connector::writeLayerAttr(QXmlStreamWriter &writer, ViewLayer::ViewLayerID viewLayerID) { writer.writeAttribute("layer",ViewLayer::viewLayerXmlNameFromID(viewLayerID)); } void Connector::writeSvgIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString connId) { Q_UNUSED(view); writer.writeAttribute("svgId",connId); } void Connector::writeTerminalIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString terminalId) { if((view == ViewLayer::BreadboardView || view == ViewLayer::SchematicView) && (!terminalId.isNull() && !terminalId.isEmpty()) ) { writer.writeAttribute("terminalId",terminalId); } else { return; } } const QList & Connector::toConnectors() { return m_toConnectors; } ConnectorItem * Connector::connectorItemByViewLayerID(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { return m_connectorItems.value(QuickHash(viewID, viewLayerID), NULL); } ConnectorItem * Connector::connectorItem(ViewLayer::ViewID viewID) { foreach (ConnectorItem * connectorItem, m_connectorItems.values()) { if (connectorItem->attachedToViewID() == viewID) return connectorItem; } return NULL; } bool Connector::connectionIsAllowed(Connector* that) { Connector::ConnectorType thisConnectorType = connectorType(); Connector::ConnectorType thatConnectorType = that->connectorType(); if (thisConnectorType == Connector::Unknown) return false; if (thatConnectorType == Connector::Unknown) return false; // unknowns are celebate if (thisConnectorType == Connector::Wire) return true; if (thatConnectorType == Connector::Wire) return true; // wires are bisexual return (thisConnectorType != thatConnectorType); // otherwise heterosexual } const QString & Connector::connectorSharedID() const { if (m_connectorShared == NULL) return ___emptyString___; return m_connectorShared->id(); } const QString & Connector::connectorSharedName() const { if (m_connectorShared == NULL) return ___emptyString___; if (!m_connectorLocalName.isEmpty()) { return m_connectorLocalName; } return m_connectorShared->sharedName(); } const QString & Connector::connectorSharedDescription() const { if (m_connectorShared == NULL) return ___emptyString___; return m_connectorShared->description(); } const QString & Connector::connectorSharedReplacedby() const { if (m_connectorShared == NULL) return ___emptyString___; return m_connectorShared->replacedby(); } ErcData * Connector::connectorSharedErcData() { if (m_connectorShared == NULL) return NULL; return m_connectorShared->ercData(); } const QString & Connector::busID() { if (m_bus == NULL) return ___emptyString___; return m_bus->id(); } Bus * Connector::bus() { return m_bus; } void Connector::setBus(Bus * bus) { m_bus = bus; } void Connector::unprocess(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { SvgIdLayer * svgIdLayer = m_connectorShared->fullPinInfo(viewID, viewLayerID); if (svgIdLayer != NULL) { svgIdLayer->unprocess(); } } SvgIdLayer * Connector::fullPinInfo(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { if (m_connectorShared == NULL) return NULL; return m_connectorShared->fullPinInfo(viewID, viewLayerID); } long Connector::modelIndex() { if (m_modelPart != NULL) return m_modelPart->modelIndex(); DebugDialog::debug(QString("saving bus connector item: how is this supposed to work?")); return 0; } ModelPart * Connector::modelPart() { return m_modelPart; } int Connector::connectorItemCount() { return m_connectorItems.count(); } QList< QPointer > Connector::viewItems() { return m_connectorItems.values(); } const QString & Connector::legID(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { if (m_connectorShared) return m_connectorShared->legID(viewID, viewLayerID); return ___emptyString___; } void Connector::setConnectorLocalName(const QString & name) { if (m_connectorShared != NULL && name.compare(m_connectorShared->sharedName()) == 0) { m_connectorLocalName.clear(); return; } m_connectorLocalName = name; } const QString & Connector::connectorLocalName() { return m_connectorLocalName; } const QList Connector::svgIdLayers() const { if (m_connectorShared) return m_connectorShared->svgIdLayers(); return EmptySvgIdLayerList; } void Connector::addPin(ViewLayer::ViewID viewID, const QString & svgId, ViewLayer::ViewLayerID viewLayerId, const QString & terminalId, const QString & legId, bool hybrid) { if (m_connectorShared) m_connectorShared->addPin(viewID, svgId, viewLayerId, terminalId, legId, hybrid); } fritzing-app-0.9.2b/src/connectors/connector.h000066400000000000000000000071731250202676700214240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #ifndef CONNECTOR_H #define CONNECTOR_H #include #include #include #include #include #include #include #include "../viewlayer.h" class Connector : public QObject { Q_OBJECT public: enum ConnectorType { Male, Female, Wire, Pad, Unknown }; public: Connector(class ConnectorShared *, class ModelPart * modelPart); ~Connector(); Connector::ConnectorType connectorType() const; void addViewItem(class ConnectorItem *); void removeViewItem(class ConnectorItem *); class ConnectorShared * connectorShared(); void connectTo(Connector *); void disconnectFrom(Connector *); void saveAsPart(QXmlStreamWriter & writer); const QList & toConnectors(); ConnectorItem * connectorItemByViewLayerID(ViewLayer::ViewID, ViewLayer::ViewLayerID); ConnectorItem * connectorItem(ViewLayer::ViewID); bool connectionIsAllowed(Connector* that); const QString & connectorSharedID() const; const QString & connectorSharedName() const; const QString & connectorSharedDescription() const; const QString & connectorSharedReplacedby() const; class ErcData * connectorSharedErcData(); const QString & busID(); class Bus * bus(); void setBus(class Bus *); long modelIndex(); ModelPart * modelPart(); int connectorItemCount(); void unprocess(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID); class SvgIdLayer * fullPinInfo(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID); const QList svgIdLayers() const; QList< QPointer > viewItems(); const QString & legID(ViewLayer::ViewID, ViewLayer::ViewLayerID); void setConnectorLocalName(const QString &); const QString & connectorLocalName(); void addPin(ViewLayer::ViewID, const QString & svgId, ViewLayer::ViewLayerID, const QString & terminalId, const QString & legId, bool hybrid); public: static void initNames(); static const QString & connectorNameFromType(ConnectorType); static ConnectorType connectorTypeFromName(const QString & name); protected: void writeLayerAttr(QXmlStreamWriter &writer, ViewLayer::ViewLayerID); void writeSvgIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString connId); void writeTerminalIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString terminalId); protected: QPointer m_connectorShared; QHash< int, QPointer > m_connectorItems; QList m_toConnectors; QPointer m_modelPart; QPointer m_bus; QString m_connectorLocalName; protected: static QHash Names; }; #endif fritzing-app-0.9.2b/src/connectors/connectoritem.cpp000066400000000000000000002366231250202676700226420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ /* rubberBand TODO: * show connectors under * undo moves & connections * adjust position so that connectorItem is in the center of connected-to connectorItem * save and load * alt/meta/ctrl to drag out a wire * rubberBand drag * update connections needs to be smarter (has to to with connecting to wires) look again at attachedMoved() * arrow key moves * hover: trigger the usual part hover highlight * drag selection should work as normal * rubberBand drag when part is stretched between two or more parts, some not being dragged correctly * if a part is locked, disable dragging the leg * fzp has "legId" (and someday? "maxlength" or is that in the svg) in

element put the leg definition as a line in the svg, with connectorNleg then on loading, remove the leg, and change the viewbox height and width this is tricky. Better if the leg extends outside the viewbox, then can easily tell which end is draggable then draw the leg as now * figure out how to make the connector longer or its clickable area bigger, or if you click on the wire within a few pixels.. since it's easy to grab, no need for some kind of fast disconnect * hover color makes a mess when dragging leg * put legItem back into connector item * export: retrieve svg must remove the rubberBand element * make it a polygon instead of a line * what to do when line length is zero * renderToSVG: make sure sceneBoundingRect is including legs * delete/undo delete * clean up pixel turds * rotate/flip do not disconnect should transform around center of the itemBase with no legs * leg cursor feedback * move behavior: what to do when dragging a leg: bendpoints * complex bent leg fails after 2nd rotate * rotate/flip undo failure * when itembase is rotated leg or bendpoint drag behavior is screwed up * rotate target is not correct * bendpoint redo (after adding multiple bendpoints) is failing * subclass leg connectoritem? not for the moment * remove bendpoint: right click, double click * bendpoints: shift-90 degree? * copy/paste connected and not * bad crash when swapping back to unrubberBand. probably some kind of boundingRect issue... * crash: swappable, swappable, undo, redo * swapping parts with rubberBand legs, can assume pins will always line up (unless legs can have diffent max distances) * no-no * no-yes * yes-no * yes-yes * rotate rubberBand, swap rubberBand, undo: crash of the item being undone. it's a prepareGeometryChange() bug * swapping when original is rotated crash swapping 3v battery for 4.8 when 3v is rotated 45 * click selection behavior should be as if selecting the part click on leg should select part * update bug when a rubberBand part has all legs connected and the part is dragged within a particular region, the part body stops updating-- but the legs follow the phantom part until the part jumps into position * export: resistors and other custom generated parts with legs (retrieve svg) curve: undo/redo at mouse release curve is killed * curve: save/load * curve: copy/paste * curve:export * curve: make straight function * curve: fix connector indicator * curve: fix connector click region * curve: connector region is not following when dragging connector when dragging to breadboard from parts bin, don't get final alignment to breadboard survival in parts editor swapping: keep bends? bendpoints: align to grid? resistor: leg y-coordinate is slightly off parts to modify ** LEDs (obsolete 5 colors and 15 SMD versions) maintain color when switching from obsolete ** RGB LEDs ** resistors ** tantalum caps ** electrolytic caps ** ceramic caps ** diodes ** tilt sensor ** temperature sensor ** light sensor ** reed switch ** 2aa battery ** 4aaa battery ** 9v battery ** stepper motors ** servo ** dc motor ** piezo ** loudspeaker ** mic ** solenoid ** peltier ** distance sensor ** transistors ** FETs ** voltage regulator ** resonator ** inductor ** crystal ------------------------------------------------- rubberBand drag with snap-disconnect after a certain length is reached parts editor support */ /////////////////////////////////////////////////////// #include "connectoritem.h" #include #include #include #include #include #include #include #include #include #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "bus.h" #include "../items/wire.h" #include "../items/virtualwire.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include "../utils/graphutils.h" #include "../utils/textutils.h" #include "../utils/ratsnestcolors.h" #include "../utils/bezier.h" #include "../utils/bezierdisplay.h" #include "../utils/cursormaster.h" #include "ercdata.h" ///////////////////////////////////////////////////////// static Bezier UndoBezier; static BezierDisplay * TheBezierDisplay = NULL; static const double StandardLegConnectorDrawEnabledLength = 5; // pixels static const double StandardLegConnectorDetectLength = 9; // pixels QList ConnectorItem::m_equalPotentialDisplayItems; const QList ConnectorItem::emptyConnectorItemList; static double MAX_DOUBLE = std::numeric_limits::max(); bool wireLessThan(ConnectorItem * c1, ConnectorItem * c2) { if (c1->connectorType() == c2->connectorType()) { // if they're the same type return the topmost return c1->zValue() > c2->zValue(); } if (c1->connectorType() == Connector::Female) { // choose the female first return true; } if (c2->connectorType() == Connector::Female) { // choose the female first return false; } if (c1->connectorType() == Connector::Male) { // choose the male first return true; } if (c2->connectorType() == Connector::Male) { // choose the male first return false; } if (c1->connectorType() == Connector::Pad) { // choose the pad first return true; } if (c2->connectorType() == Connector::Pad) { // choose the pad first return false; } // Connector::Wire last return c1->zValue() > c2->zValue(); } QColor addColor(QColor & color, int offset) { QColor rgb = color.toRgb(); rgb.setRgb(qMax(0, qMin(rgb.red() + offset, 255)), qMax(0, qMin(rgb.green() + offset, 255)),qMax(0, qMin(rgb.blue() + offset, 255))); // convert back to same color spec as original color return rgb.convertTo(color.spec()); } ///////////////////////////////////////////////////////////// ConnectorItemAction::ConnectorItemAction(QAction * action) : QAction(action) { m_connectorItem = NULL; this->setText(action->text()); this->setStatusTip(action->statusTip()); this->setCheckable(action->isCheckable()); } ConnectorItemAction::ConnectorItemAction(const QString & title, QObject * parent) : QAction(title, parent) { m_connectorItem = NULL; } void ConnectorItemAction::setConnectorItem(ConnectorItem * c) { m_connectorItem = c; } ConnectorItem * ConnectorItemAction::connectorItem() { return m_connectorItem; } ///////////////////////////////////////////////////////// ConnectorItem::ConnectorItem( Connector * connector, ItemBase * attachedTo ) : NonConnectorItem(attachedTo) { // initialize m_connectorT, otherwise will trigger qWarning("QLine::unitVector: New line does not have unit length"); // TODO: figure out why paint is being called with m_connectorT not initialized m_groundFillSeed = false; m_connectorDetectT = m_connectorDrawT = 0; m_draggingCurve = m_draggingLeg = m_rubberBandLeg = m_bigDot = m_hybrid = false; m_hoverEnterSpaceBarWasPressed = m_spaceBarWasPressed = false; m_overConnectorItem = NULL; m_connectorHovering = false; m_connector = connector; if (connector != NULL) { connector->addViewItem(this); } setAcceptHoverEvents(true); this->setCursor((attachedTo && attachedTo->itemType() == ModelPart::Wire) ? *CursorMaster::BendpointCursor : *CursorMaster::MakeWireCursor); //DebugDialog::debug(QString("%1 attached to %2") //.arg(this->connector()->connectorShared()->id()) //.arg(attachedTo->modelPartShared()->title()) ); } ConnectorItem::~ConnectorItem() { m_equalPotentialDisplayItems.removeOne(this); //DebugDialog::debug(QString("deleting connectorItem %1").arg((long) this, 0, 16)); foreach (ConnectorItem * connectorItem, m_connectedTo) { if (connectorItem != NULL) { //DebugDialog::debug(QString("temp remove %1 %2").arg(this->attachedToID()).arg(connectorItem->attachedToID())); connectorItem->tempRemove(this, this->attachedToID() != connectorItem->attachedToID()); } } if (this->connector() != NULL) { this->connector()->removeViewItem(this); } clearCurves(); } void ConnectorItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) { //debugInfo("connector hoverEnter"); /* QRectF sbr = this->sceneBoundingRect(); QPointF p = event->scenePos(); debugInfo(QString("hover %1, %2 %3 %4 %5, %6 %7") .arg((long) this, 0, 16) .arg(sbr.left()) .arg(sbr.top()) .arg(sbr.width()) .arg(sbr.height()) .arg(p.x()) .arg(p.y()) ); */ InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { m_hoverEnterSpaceBarWasPressed = true; event->ignore(); return; } //DebugDialog::debug("---CI set override cursor"); CursorMaster::instance()->addCursor(this, cursor()); bool setDefaultCursor = true; m_hoverEnterSpaceBarWasPressed = false; setHoverColor(); if (infoGraphicsView != NULL) { infoGraphicsView->hoverEnterConnectorItem(event, this); if (m_rubberBandLeg) { updateLegCursor(event->pos(), event->modifiers()); setDefaultCursor = false; } } if (this->m_attachedTo != NULL) { if (this->attachedToItemType() == ModelPart::Wire) { updateWireCursor(event->modifiers()); setDefaultCursor = false; } m_attachedTo->hoverEnterConnectorItem(event, this); } if (setDefaultCursor) CursorMaster::instance()->addCursor(this, *CursorMaster::MakeWireCursor); } void ConnectorItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { if (m_hoverEnterSpaceBarWasPressed) { event->ignore(); return; } QList visited; restoreColor(visited); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->hoverLeaveConnectorItem(event, this); } CursorMaster::instance()->removeCursor(this); if (this->m_attachedTo != NULL) { m_attachedTo->hoverLeaveConnectorItem(event, this); } //DebugDialog::debug("------CI restore override cursor"); CursorMaster::instance()->removeCursor(this); } void ConnectorItem::hoverMoveEvent ( QGraphicsSceneHoverEvent * event ) { if (m_hoverEnterSpaceBarWasPressed) { event->ignore(); return; } if (this->m_attachedTo != NULL) { m_attachedTo->hoverMoveConnectorItem(event, this); } if (m_rubberBandLeg) { updateLegCursor(event->pos(), event->modifiers()); } } Connector * ConnectorItem::connector() { return m_connector; } void ConnectorItem::clearConnectorHover() { m_connectorHovering = false; } void ConnectorItem::connectorHover(ItemBase * itemBase, bool hovering) { m_connectorHovering = hovering; if (hovering) { setHoverColor(); // could make this light up buses as well } else { QList visited; restoreColor(visited); } if (this->m_attachedTo != NULL) { m_attachedTo->connectorHover(this, itemBase, hovering); } } bool ConnectorItem::connectorHovering() { return m_connectorHovering; } void ConnectorItem::connectTo(ConnectorItem * connected) { if (m_connectedTo.contains(connected)) return; m_connectedTo.append(connected); //DebugDialog::debug(QString("connect to cc:%4 this:%1 to:%2 %3").arg((long) this, 0, 16).arg((long) connected, 0, 16).arg(connected->attachedTo()->modelPartShared()->title()).arg(m_connectedTo.count()) ); QList visited; restoreColor(visited); if (m_attachedTo != NULL) { m_attachedTo->connectionChange(this, connected, true); } } ConnectorItem * ConnectorItem::removeConnection(ItemBase * itemBase) { QList visited; for (int i = 0; i < m_connectedTo.count(); i++) { if (m_connectedTo[i]->attachedTo() == itemBase) { ConnectorItem * removed = m_connectedTo[i]; m_connectedTo.removeAt(i); if (m_attachedTo != NULL) { m_attachedTo->connectionChange(this, removed, false); } restoreColor(visited); DebugDialog::debug(QString("remove from:%1 to:%2 count%3") .arg((long) this, 0, 16) .arg(itemBase->modelPartShared()->title()) .arg(m_connectedTo.count()) ); return removed; } } return NULL; } void ConnectorItem::removeConnection(ConnectorItem * connectedItem, bool emitChange) { if (connectedItem == NULL) return; m_connectedTo.removeOne(connectedItem); QList visited; restoreColor(visited); if (emitChange) { m_attachedTo->connectionChange(this, connectedItem, false); } } void ConnectorItem::tempConnectTo(ConnectorItem * item, bool applyColor) { if (!m_connectedTo.contains(item)) m_connectedTo.append(item); if(applyColor) { QList visited; restoreColor(visited); } } void ConnectorItem::tempRemove(ConnectorItem * item, bool applyColor) { m_connectedTo.removeOne(item); if(applyColor) { QList visited; restoreColor(visited); } } void ConnectorItem::restoreColor(QList & visited) { if (visited.contains(this)) return; visited.append(this); if (!attachedTo()->isEverVisible()) return; QList connectorItems; connectorItems.append(this); collectEqualPotential(connectorItems, true, getSkipFlags()); visited.append(connectorItems); QSet attachedTo; foreach (ConnectorItem * connectorItem, connectorItems) { if (connectorItem->isEverVisible()) { if (connectorItem->attachedToItemType() != ModelPart::Wire) { attachedTo.insert(connectorItem->attachedTo()->layerKinChief()); } } } foreach (ConnectorItem * connectorItem, connectorItems) { if (connectorItem->isEverVisible()) { //QString how; if (attachedTo.count() <= 1) { if (connectorItem->connectorType() == Connector::Female) { if (connectorItem->connectionsCount() > 0) connectorItem->setUnconnectedColor(); else connectorItem->setNormalColor(); //how = "normal"; } else { connectorItem->setUnconnectedColor(); //how = "unconnected"; } } else { connectorItem->setConnectedColor(); //how = "connected"; } } } /* DebugDialog::debug(QString("restore color dobus:%1 bccount:%2 docross:%3 cid:'%4' '%5' id:%6 '%7' vid:%8 vlid:%9 %10") .arg(doBuses) .arg(busConnectionCount) .arg(doCross) .arg(this->connectorSharedID()) .arg(this->connectorSharedName()) .arg(this->attachedToID()) .arg(this->attachedToInstanceTitle()) .arg(this->attachedToViewID()) .arg(this->attachedToViewLayerID()) .arg(how) ); */ } void ConnectorItem::setConnectedColor() { if (m_attachedTo == NULL) return; QBrush brush; QPen pen; m_attachedTo->getConnectedColor(this, brush, pen, m_opacity, m_negativePenWidth, m_negativeOffsetRect); //DebugDialog::debug(QString("set connected %1 %2").arg(attachedToID()).arg(pen->width())); setColorAux(brush, pen, true); } void ConnectorItem::setNormalColor() { if (m_attachedTo == NULL) return; QBrush brush; QPen pen; m_attachedTo->getNormalColor(this, brush, pen, m_opacity, m_negativePenWidth, m_negativeOffsetRect); //DebugDialog::debug(QString("set normal %1 %2").arg(attachedToID()).arg(pen->width())); setColorAux(brush, pen, false); } void ConnectorItem::setUnconnectedColor() { if (m_attachedTo == NULL) return; QBrush brush; QPen pen; //DebugDialog::debug(QString("set unconnected %1").arg(attachedToID()) ); m_attachedTo->getUnconnectedColor(this, brush, pen, m_opacity, m_negativePenWidth, m_negativeOffsetRect); setColorAux(brush, pen, true); } void ConnectorItem::setHoverColor() { if (m_attachedTo == NULL) return; QBrush brush; QPen pen; m_attachedTo->getHoverColor(this, brush, pen, m_opacity, m_negativePenWidth, m_negativeOffsetRect); setColorAux(brush, pen, true); } void ConnectorItem::setColorAux(const QBrush & brush, const QPen & pen, bool paint) { //debugInfo(QString("setColorAux %1 %2").arg(brush.color().name()).arg(pen.color().name())); m_paint = paint; this->setBrush(brush); this->setPen(pen); update(); } void ConnectorItem::setColorAux(const QColor &color, bool paint) { setColorAux(QBrush(color), QPen(color), paint); } void ConnectorItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { //DebugDialog::debug("in connectorItem mouseReleaseEvent"); clearEqualPotentialDisplay(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (m_rubberBandLeg && m_draggingLeg) { m_draggingLeg = false; if (m_insertBendpointPossible) { // didn't move far enough; bail return; } if (m_moveCount == 0) { // never moved return; } ConnectorItem * to = releaseDrag(); if (m_draggingCurve) { m_draggingCurve = false; if (TheBezierDisplay) { delete TheBezierDisplay; TheBezierDisplay = NULL; } if (infoGraphicsView != NULL) { infoGraphicsView->prepLegCurveChange(this, m_draggingLegIndex, &UndoBezier, m_legCurves.at(m_draggingLegIndex), false); } return; } if (m_oldPolygon.count() < m_legPolygon.count()) { // we inserted a bendpoint InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->prepLegBendpointChange(this, m_oldPolygon.count(), m_legPolygon.count(), m_draggingLegIndex, m_legPolygon.at(m_draggingLegIndex), &UndoBezier, m_legCurves.at(m_draggingLegIndex -1), m_legCurves.at(m_draggingLegIndex), false); } return; } bool changeConnections = m_draggingLegIndex == m_legPolygon.count() - 1; if (to != NULL && changeConnections) { // center endpoint in the target connectorItem reposition(to->sceneAdjustedTerminalPoint(NULL), m_draggingLegIndex); } if (infoGraphicsView != NULL) { infoGraphicsView->prepLegBendpointMove(this, m_draggingLegIndex, mapToScene(m_oldPolygon.at(m_draggingLegIndex)), mapToScene(m_legPolygon.at(m_draggingLegIndex)), to, changeConnections); } return; } if (this->m_attachedTo != NULL && m_attachedTo->acceptsMouseReleaseConnectorEvent(this, event)) { m_attachedTo->mouseReleaseConnectorEvent(this, event); return; } QGraphicsRectItem::mouseReleaseEvent(event); } void ConnectorItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { if (m_rubberBandLeg) { int bendpointIndex; CursorLocation cursorLocation = findLocation(event->pos(), bendpointIndex); switch (cursorLocation) { case InBendpoint: if (bendpointIndex < m_legPolygon.count() - 1) { removeBendpoint(bendpointIndex); } break; case InSegment: insertBendpoint(event->pos(), bendpointIndex); break; default: break; } return; } if (this->m_attachedTo != NULL && m_attachedTo->acceptsMouseDoubleClickConnectorEvent(this, event)) { m_attachedTo->mouseDoubleClickConnectorEvent(this); return; } QGraphicsRectItem::mouseDoubleClickEvent(event); } void ConnectorItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { m_moveCount++; if (m_rubberBandLeg && m_draggingLeg) { if (m_draggingCurve) { Bezier * bezier = m_legCurves.at(m_draggingLegIndex); if (bezier != NULL && !bezier->isEmpty()) { prepareGeometryChange(); bezier->recalc(event->pos()); calcConnectorEnd(); update(); if (TheBezierDisplay) TheBezierDisplay->updateDisplay(this, bezier); return; } } QPointF currentPos = event->scenePos(); QPointF buttonDownPos = event->buttonDownScenePos(Qt::LeftButton); if (m_insertBendpointPossible) { if (qSqrt(GraphicsUtils::distanceSqd(currentPos, buttonDownPos)) >= QApplication::startDragDistance()) { insertBendpointAux(m_holdPos, m_draggingLegIndex); m_insertBendpointPossible = false; } else { return; } } if (event->modifiers() & Qt::ShiftModifier && m_draggingLegIndex > 0 && m_draggingLegIndex < m_legPolygon.count() - 1) { bool bendpoint = false; QPointF initialPos = mapToScene(m_legPolygon.at(m_draggingLegIndex - 1)); QPointF otherInitialPos = mapToScene(m_legPolygon.at(m_draggingLegIndex + 1)); QPointF p1(initialPos.x(), otherInitialPos.y()); double d = GraphicsUtils::distanceSqd(p1, currentPos); if (d <= 144) { bendpoint = true; currentPos = p1; } else { p1.setX(otherInitialPos.x()); p1.setY(initialPos.y()); d = GraphicsUtils::distanceSqd(p1, currentPos); if (d <= 144) { bendpoint = true; currentPos = p1; } } if (!bendpoint) { currentPos = GraphicsUtils::calcConstraint(initialPos, currentPos); } } reposition(m_holdPos + currentPos - buttonDownPos, m_draggingLegIndex); QList exclude; findConnectorUnder(true, true, exclude, true, this); return; } if (this->m_attachedTo != NULL && m_attachedTo->acceptsMouseMoveConnectorEvent(this, event)) { m_attachedTo->mouseMoveConnectorEvent(this, event); return; } QGraphicsRectItem::mouseMoveEvent(event); } void ConnectorItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { m_draggingCurve = m_draggingLeg = false; m_moveCount = 0; if (event->button() != Qt::LeftButton) { QGraphicsRectItem::mousePressEvent(event); return; } if (m_attachedTo->filterMousePressConnectorEvent(this, event)) { event->ignore(); return; } clearEqualPotentialDisplay(); InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL && infographics->spaceBarIsPressed()) { event->ignore(); return; } m_equalPotentialDisplayItems.append(this); collectEqualPotential(m_equalPotentialDisplayItems, true, ViewGeometry::NoFlag); //m_equalPotentialDisplayItems.removeAt(0); // not sure whether to leave the clicked one in or out of the list QList visited; //DebugDialog::debug("_______________________"); foreach (ConnectorItem * connectorItem, m_equalPotentialDisplayItems) { connectorItem->showEqualPotential(true, visited); //connectorItem->debugInfo("display eqp"); } if (m_rubberBandLeg && this->m_attachedTo != NULL && m_attachedTo->acceptsMousePressLegEvent(this, event)) { if (legMousePressEvent(event)) return; } if (this->m_attachedTo != NULL && m_attachedTo->acceptsMousePressConnectorEvent(this, event)) { m_attachedTo->mousePressConnectorEvent(this, event); return; } QGraphicsRectItem::mousePressEvent(event); } int ConnectorItem::connectionsCount() { return m_connectedTo.count(); } void ConnectorItem::attachedMoved(bool includeRatsnest, QList & already) { //DebugDialog::debug("attached moved"); if (!this->isVisible()) return; QSet allTo; allTo.insert(this); foreach (ConnectorItem * toConnectorItem, m_connectedTo) { allTo.insert(toConnectorItem); foreach (ConnectorItem * subTo, toConnectorItem->connectedToItems()) { allTo.insert(subTo); } } allTo.remove(this); foreach (ConnectorItem * toConnectorItem, allTo) { ItemBase * itemBase = toConnectorItem->attachedTo(); if (itemBase == NULL) continue; if (!itemBase->isVisible()) { //this->debugInfo("continue"); //itemBase->debugInfo(" "); continue; } if (itemBase->getRatsnest() && !includeRatsnest) { continue; } toConnectorItem->attachedTo()->connectedMoved(this, toConnectorItem, already); } } ConnectorItem * ConnectorItem::firstConnectedToIsh() { if (m_connectedTo.count() <= 0) return NULL; foreach (ConnectorItem * connectorItem, m_connectedTo) { if (connectorItem->attachedTo()->getRatsnest()) continue; if (!connectorItem->isVisible()) continue; return connectorItem; } // TODO: not sure whether to return invisible connectors // TODO: get rid of this function? foreach (ConnectorItem * connectorItem, m_connectedTo) { if (connectorItem->attachedTo()->getRatsnest()) continue; return connectorItem; } return NULL; } void ConnectorItem::setTerminalPoint(QPointF p) { m_terminalPoint = p; } QPointF ConnectorItem::terminalPoint() { return m_terminalPoint; } QPointF ConnectorItem::adjustedTerminalPoint() { if (m_legPolygon.count() < 2) { return m_terminalPoint + this->rect().topLeft(); } return m_legPolygon.last(); } QPointF ConnectorItem::sceneAdjustedTerminalPoint(ConnectorItem * connectee) { if ((connectee != NULL) && !m_circular && !m_shape.isEmpty() && (connectee->attachedToItemType() == ModelPart::Wire)) { Wire * wire = qobject_cast(connectee->attachedTo()); if ((wire != NULL) && !wire->getRatsnest()) { QPointF anchor = wire->otherConnector(connectee)->sceneAdjustedTerminalPoint(NULL); double newX = 0, newY = 0, newDistance = MAX_DOUBLE; int count = m_shape.elementCount(); QPointF prev; for (int i = 0; i < count; i++) { QPainterPath::Element el = m_shape.elementAt(i); if (el.isMoveTo()) { prev = this->mapToScene(QPointF(el)); } else { QPointF current = this->mapToScene(QPointF(el)); double candidateX, candidateY, candidateDistance; bool atEndpoint; GraphicsUtils::distanceFromLine(anchor.x(), anchor.y(), prev.x(), prev.y(), current.x(), current.y(), candidateX, candidateY, candidateDistance, atEndpoint); if (candidateDistance < newDistance) { newX = candidateX; newY = candidateY; newDistance = candidateDistance; //DebugDialog::debug(QString("anchor:%1,%2; new:%3,%4; %5").arg(anchor.x()).arg(anchor.y()).arg(newX).arg(newY).arg(newDistance)); } prev = current; } } //DebugDialog::debug(QString("anchor:%1,%2; new:%3,%4; %5\n\n").arg(anchor.x()).arg(anchor.y()).arg(newX).arg(newY).arg(newDistance)); return QPointF(newX, newY); } } return this->mapToScene(adjustedTerminalPoint()); } bool ConnectorItem::connectedTo(ConnectorItem * connectorItem) { return this->m_connectedTo.contains(connectorItem); } const QList< QPointer > & ConnectorItem::connectedToItems() { return m_connectedTo; } void ConnectorItem::setHidden(bool hide) { m_hidden = hide; setHiddenOrInactive(); } void ConnectorItem::setHybrid(bool h) { m_hybrid = h; setHiddenOrInactive(); } bool ConnectorItem::isHybrid() { return m_hybrid; } void ConnectorItem::setBigDot(bool bd) { m_bigDot = bd; //if (bd) { // this->debugInfo("big dot"); //} } bool ConnectorItem::isBigDot() { return m_bigDot; } void ConnectorItem::setInactive(bool inactivate) { m_inactive = inactivate; setHiddenOrInactive(); } void ConnectorItem::setHiddenOrInactive() { if (m_hidden || m_inactive || m_hybrid || m_layerHidden) { this->setAcceptedMouseButtons(Qt::NoButton); this->unsetCursor(); setAcceptHoverEvents(false); } else { this->setAcceptedMouseButtons(ALLMOUSEBUTTONS); this->setCursor(attachedToItemType() == ModelPart::Wire ? *CursorMaster::BendpointCursor : *CursorMaster::MakeWireCursor); setAcceptHoverEvents(true); } this->update(); } ConnectorItem * ConnectorItem::overConnectorItem() { return m_overConnectorItem; } void ConnectorItem::setOverConnectorItem(ConnectorItem * connectorItem) { m_overConnectorItem = connectorItem; } const QString & ConnectorItem::connectorSharedID() { if (m_connector == NULL) return ___emptyString___; return m_connector->connectorSharedID(); } const QString & ConnectorItem::connectorSharedReplacedby() { if (m_connector == NULL) return ___emptyString___; return m_connector->connectorSharedReplacedby(); } ErcData * ConnectorItem::connectorSharedErcData() { if (m_connector == NULL) return NULL; return m_connector->connectorSharedErcData(); } const QString & ConnectorItem::connectorSharedName() { if (m_connector == NULL) return ___emptyString___; return m_connector->connectorSharedName(); } const QString & ConnectorItem::connectorSharedDescription() { if (m_connector == NULL) return ___emptyString___; return m_connector->connectorSharedDescription(); } const QString & ConnectorItem::busID() { if (m_connector == NULL) return ___emptyString___; return m_connector->busID(); } ModelPartShared * ConnectorItem::modelPartShared() { if (m_attachedTo == NULL) return NULL; return m_attachedTo->modelPartShared(); } ModelPart * ConnectorItem::modelPart() { if (m_attachedTo == NULL) return NULL; return m_attachedTo->modelPart(); } Bus * ConnectorItem::bus() { if (m_connector == NULL) return NULL; return m_connector->bus(); } ViewLayer::ViewLayerID ConnectorItem::attachedToViewLayerID() { if (m_attachedTo == NULL) return ViewLayer::UnknownLayer; return m_attachedTo->viewLayerID(); } ViewLayer::ViewLayerPlacement ConnectorItem::attachedToViewLayerPlacement() { if (m_attachedTo == NULL) return ViewLayer::UnknownPlacement; return m_attachedTo->viewLayerPlacement(); } ViewLayer::ViewID ConnectorItem::attachedToViewID() { if (m_attachedTo == NULL) return ViewLayer::UnknownView; return m_attachedTo->viewID(); } Connector::ConnectorType ConnectorItem::connectorType() { if (m_connector == NULL) return Connector::Unknown; return m_connector->connectorType(); } bool ConnectorItem::chained() { foreach (ConnectorItem * toConnectorItem, m_connectedTo) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { return true; } } return false; } void ConnectorItem::saveInstance(QXmlStreamWriter & writer) { if (m_connectedTo.count() <= 0 && !m_rubberBandLeg && !m_groundFillSeed) { // no need to save if there's no connection return; } writer.writeStartElement("connector"); writer.writeAttribute("connectorId", connectorSharedID()); writer.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(attachedToViewLayerID())); if (m_groundFillSeed) { writer.writeAttribute("groundFillSeed", "true"); } writer.writeStartElement("geometry"); QPointF p = this->pos(); writer.writeAttribute("x", QString::number(p.x())); writer.writeAttribute("y", QString::number(p.y())); writer.writeEndElement(); if (m_rubberBandLeg && m_legPolygon.count() > 1) { writer.writeStartElement("leg"); for (int i = 0; i < m_legPolygon.count(); i++) { QPointF p = m_legPolygon.at(i); writer.writeStartElement("point"); writer.writeAttribute("x", QString::number(p.x())); writer.writeAttribute("y", QString::number(p.y())); writer.writeEndElement(); Bezier * bezier = m_legCurves.at(i); if (bezier == NULL) { writer.writeStartElement("bezier"); writer.writeEndElement(); } else { bezier->write(writer); } } writer.writeEndElement(); } if (m_connectedTo.count() > 0) { writer.writeStartElement("connects"); foreach (ConnectorItem * connectorItem, this->m_connectedTo) { if (connectorItem->attachedTo()->getRatsnest()) continue; connectorItem->writeConnector(writer, "connect"); } writer.writeEndElement(); } writeOtherElements(writer); writer.writeEndElement(); } void ConnectorItem::writeConnector(QXmlStreamWriter & writer, const QString & elementName) { //DebugDialog::debug(QString("write connector %1").arg(this->attachedToID())); writer.writeStartElement(elementName); writer.writeAttribute("connectorId", connectorSharedID()); writer.writeAttribute("modelIndex", QString::number(connector()->modelIndex())); writer.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(attachedToViewLayerID())); writer.writeEndElement(); } void ConnectorItem::writeOtherElements(QXmlStreamWriter & writer) { Q_UNUSED(writer); } bool ConnectorItem::wiredTo(ConnectorItem * target, ViewGeometry::WireFlags skipFlags) { QList connectorItems; connectorItems.append(this); collectEqualPotential(connectorItems, true, skipFlags); return connectorItems.contains(target); } Wire * ConnectorItem::directlyWiredTo(ConnectorItem * source, ConnectorItem * target, ViewGeometry::WireFlags flags) { QList visited; return directlyWiredToAux(source, target, flags, visited); } Wire * ConnectorItem::directlyWiredToAux(ConnectorItem * source, ConnectorItem * target, ViewGeometry::WireFlags flags, QList & visited) { if (visited.contains(source)) return NULL; QList equals; equals << source; ConnectorItem * cross = source->getCrossLayerConnectorItem(); if (cross) { if (!visited.contains(cross)) { equals << cross; } } visited.append(equals); foreach (ConnectorItem * fromItem, equals) { foreach (ConnectorItem * toConnectorItem, fromItem->m_connectedTo) { ItemBase * toItem = toConnectorItem->attachedTo(); if (toItem == NULL) { continue; // shouldn't happen } if (toItem->itemType() != ModelPart::Wire) continue; Wire * wire = qobject_cast(toItem); if (!wire->hasAnyFlag(flags)) continue; ConnectorItem * otherEnd = wire->otherConnector(toConnectorItem); bool isChained = false; foreach (ConnectorItem * otherConnectorItem, otherEnd->m_connectedTo) { if (target == otherConnectorItem) { return wire; } if (target->getCrossLayerConnectorItem() == otherConnectorItem) { return wire; } if (otherConnectorItem->attachedToItemType() == ModelPart::Wire) { //DebugDialog::debug(QString("wired from %1 to %2").arg(wire->id()).arg(otherConnectorItem->attachedToID())); isChained = true; } } if (isChained) { if (ConnectorItem::directlyWiredToAux(otherEnd, target, flags, visited)) { return wire; } } } } return NULL; } bool ConnectorItem::isConnectedToPart() { QList tempItems; tempItems << this; ConnectorItem * thisCrossConnectorItem = this->getCrossLayerConnectorItem(); QList busConnectedItems; Bus * b = bus(); if (b != NULL) { attachedTo()->busConnectorItems(b, this, busConnectedItems); } for (int i = 0; i < tempItems.count(); i++) { ConnectorItem * connectorItem = tempItems[i]; if ((connectorItem != this) && (connectorItem != thisCrossConnectorItem) && !busConnectedItems.contains(connectorItem)) { switch (connectorItem->attachedToItemType()) { case ModelPart::Symbol: case ModelPart::SchematicSubpart: case ModelPart::Jumper: case ModelPart::Part: case ModelPart::CopperFill: case ModelPart::Board: case ModelPart::Breadboard: case ModelPart::ResizableBoard: case ModelPart::Via: if (connectorItem->attachedTo()->isEverVisible()) { return true; } break; default: break; } } ConnectorItem * crossConnectorItem = connectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem != NULL) { if (!tempItems.contains(crossConnectorItem)) { tempItems.append(crossConnectorItem); } } foreach (ConnectorItem * cto, connectorItem->connectedToItems()) { if (tempItems.contains(cto)) continue; tempItems.append(cto); } Bus * bus = connectorItem->bus(); if (bus != NULL) { QList busConnectedItems; connectorItem->attachedTo()->busConnectorItems(bus, connectorItem, busConnectedItems); foreach (ConnectorItem * busConnectedItem, busConnectedItems) { if (!tempItems.contains(busConnectedItem)) { tempItems.append(busConnectedItem); } } } } return false; } void ConnectorItem::collectEqualPotential(QList & connectorItems, bool crossLayers, ViewGeometry::WireFlags skipFlags) { // collects all the connectors at the same potential // allows direct connections or wired connections //DebugDialog::debug("__________________"); QList tempItems = connectorItems; connectorItems.clear(); for (int i = 0; i < tempItems.count(); i++) { ConnectorItem * connectorItem = tempItems[i]; //connectorItem->debugInfo("testing eqp"); Wire * fromWire = (connectorItem->attachedToItemType() == ModelPart::Wire) ? qobject_cast(connectorItem->attachedTo()) : NULL; if (fromWire != NULL) { if (fromWire->hasAnyFlag(skipFlags)) { // don't add this kind of wire continue; } } else { if (crossLayers) { ConnectorItem * crossConnectorItem = connectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem != NULL) { if (!tempItems.contains(crossConnectorItem)) { tempItems.append(crossConnectorItem); } } } } // this one's a keeper connectorItems.append(connectorItem); //connectorItem->debugInfo("collect"); foreach (ConnectorItem * cto, connectorItem->connectedToItems()) { if (tempItems.contains(cto)) continue; if ((skipFlags & ViewGeometry::NormalFlag) && (fromWire == NULL) && (cto->attachedToItemType() != ModelPart::Wire)) { // direct (part-to-part) connections not allowed continue; } tempItems.append(cto); } Bus * bus = connectorItem->bus(); if (bus != NULL) { QList busConnectedItems; connectorItem->attachedTo()->busConnectorItems(bus, connectorItem, busConnectedItems); #ifndef QT_NO_DEBUG if (connectorItem->attachedToItemType() == ModelPart::Wire && busConnectedItems.count() != 2) { connectorItem->debugInfo("bus is missing"); //busConnectedItems.clear(); //connectorItem->attachedTo()->busConnectorItems(bus, busConnectedItems); } #endif foreach (ConnectorItem * busConnectedItem, busConnectedItems) { if (!tempItems.contains(busConnectedItem)) { tempItems.append(busConnectedItem); } } } } } void ConnectorItem::collectParts(QList & connectorItems, QList & partsConnectors, bool includeSymbols, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (connectorItems.count() == 0) return; //DebugDialog::debug("___________________________"); switch (viewLayerPlacement) { case ViewLayer::NewTop: case ViewLayer::NewBottom: case ViewLayer::NewTopAndBottom: break; default: DebugDialog::debug(QString("collect parts unknown spec %1").arg(viewLayerPlacement)); viewLayerPlacement = ViewLayer::NewTopAndBottom; break; } foreach (ConnectorItem * connectorItem, connectorItems) { if (connectorItem->isHybrid()) { continue; } ItemBase * candidate = connectorItem->attachedTo(); switch (candidate->itemType()) { case ModelPart::Symbol: case ModelPart::SchematicSubpart: if (!includeSymbols) break; case ModelPart::Jumper: case ModelPart::Part: case ModelPart::CopperFill: case ModelPart::Board: case ModelPart::ResizableBoard: case ModelPart::Via: collectPart(connectorItem, partsConnectors, viewLayerPlacement); break; default: break; } } } void ConnectorItem::collectPart(ConnectorItem * connectorItem, QList & partsConnectors, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (partsConnectors.contains(connectorItem)) return; ConnectorItem * crossConnectorItem = connectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem != NULL) { if (partsConnectors.contains(crossConnectorItem)) { return; } if (viewLayerPlacement == ViewLayer::NewTopAndBottom) { partsConnectors.append(crossConnectorItem); /* DebugDialog::debug(QString("collecting both: %1 %2 %3 %4") .arg(crossConnectorItem->attachedToID()) .arg(crossConnectorItem->connectorSharedID()) .arg(crossConnectorItem->attachedToViewLayerID()) .arg((long)crossConnectorItem->attachedTo(), 0, 16) ); */ } else if (viewLayerPlacement == ViewLayer::NewTop) { if (connectorItem->attachedToViewLayerID() == ViewLayer::Copper1) { } else { connectorItem = crossConnectorItem; } } else if (viewLayerPlacement == ViewLayer::NewBottom) { if (connectorItem->attachedToViewLayerID() == ViewLayer::Copper0) { } else { connectorItem = crossConnectorItem; } } } /* DebugDialog::debug(QString("collecting part: %1 %2 %3 %4") .arg(connectorItem->attachedToID()) .arg(connectorItem->connectorSharedID()) .arg(connectorItem->attachedToViewLayerID()) .arg((long) connectorItem->attachedTo(), 0, 16) ); */ partsConnectors.append(connectorItem); } void ConnectorItem::updateTooltip() { if (attachedToItemType() != ModelPart::Wire) { QString name = connectorSharedName(); bool isInt = false; name.toInt(&isInt); QString descr = connectorSharedDescription(); if (name.compare(descr, Qt::CaseInsensitive) == 0) { descr = ""; } else { descr = ":" + descr; } QString id = connectorSharedID(); int ix = IntegerFinder.indexIn(id); if (ix < 0 || isInt) { id = ""; } else { if (attachedTo()->modelPart()->hasZeroConnector()) { id = QString::number(IntegerFinder.cap(0).toInt() + 1); } else { id = IntegerFinder.cap(0); } if (!id.isEmpty()) { id = " (" + id + ")"; } } QString tt = QString("%2%3%1
%4") .arg(id) .arg(name) .arg(descr) .arg(attachedToTitle()); setToolTip(tt); return; } QList connectors; foreach(ConnectorItem * toConnectorItem, m_connectedTo) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { connectors.append(toConnectorItem); } } if (connectors.count() == 0) { setToolTip(""); return; } QString connections = QString("

"; setToolTip(ItemBase::ITEMBASE_FONT_PREFIX + connections + ItemBase::ITEMBASE_FONT_SUFFIX); } void ConnectorItem::clearConnector() { m_connector = NULL; } bool ConnectorItem::connectionIsAllowed(ConnectorItem * other) { if (!connector()->connectionIsAllowed(other->connector())) return false; if (!m_attachedTo->connectionIsAllowed(other)) return false; foreach (ConnectorItem * toConnectorItem, connectedToItems()) { if (!toConnectorItem->attachedTo()->connectionIsAllowed(other)) { return false; } } return true; } void ConnectorItem::showEqualPotential(bool show, QList & visited) { if (!show) { restoreColor(visited); return; } QBrush brush; QPen pen; m_attachedTo->getEqualPotentialColor(this, brush, pen, m_opacity, m_negativePenWidth, m_negativeOffsetRect); //DebugDialog::debug(QString("set eqp %1 %2 %3").arg(attachedToID()).arg(pen->width()).arg(pen->color().name())); setColorAux(brush, pen, true); } void ConnectorItem::clearEqualPotentialDisplay() { //DebugDialog::debug(QString("clear eqp3")); QList visited; foreach (ConnectorItem * connectorItem, m_equalPotentialDisplayItems) { connectorItem->restoreColor(visited); } m_equalPotentialDisplayItems.clear(); } bool ConnectorItem::isEverVisible() { return m_attachedTo->isEverVisible(); } bool ConnectorItem::isGrounded(ConnectorItem * c1, ConnectorItem * c2) { QList connectorItems; if (c1 != NULL) { connectorItems.append(c1); } if (c2 != NULL) { connectorItems.append(c2); } collectEqualPotential(connectorItems, true, ViewGeometry::NoFlag); foreach (ConnectorItem * end, connectorItems) { if (end->isGrounded()) return true; } return false; } bool ConnectorItem::isGrounded() { QString name = connectorSharedName(); return ((name.compare("gnd", Qt::CaseInsensitive) == 0) || // (name.compare("-", Qt::CaseInsensitive) == 0) || (name.compare("vss", Qt::CaseInsensitive) == 0) || (name.compare("ground", Qt::CaseInsensitive) == 0) ); } ConnectorItem * ConnectorItem::getCrossLayerConnectorItem() { if (m_connector == NULL) return NULL; if (m_attachedTo == NULL) return NULL; if (m_attachedTo->viewID() != ViewLayer::PCBView) return NULL; ViewLayer::ViewLayerID viewLayerID = attachedToViewLayerID(); if (viewLayerID == ViewLayer::Copper0) { return m_connector->connectorItemByViewLayerID(this->attachedToViewID(), ViewLayer::Copper1); } if (viewLayerID == ViewLayer::Copper1) { return m_connector->connectorItemByViewLayerID(this->attachedToViewID(), ViewLayer::Copper0); } return NULL; } bool ConnectorItem::isInLayers(ViewLayer::ViewLayerPlacement viewLayerPlacement) { return ViewLayer::copperLayers(viewLayerPlacement).contains(attachedToViewLayerID()); } bool ConnectorItem::isCrossLayerConnectorItem(ConnectorItem * candidate) { if (candidate == NULL) return false; ConnectorItem * cross = getCrossLayerConnectorItem(); return cross == candidate; } bool ConnectorItem::isCrossLayerFrom(ConnectorItem * candidate) { return !ViewLayer::canConnect(this->attachedToViewLayerID(), candidate->attachedToViewLayerID()); } bool isGrey(QColor color) { if (qAbs(color.red() - color.green()) > 16) return false; if (qAbs(color.red() - color.blue()) > 16) return false; if (qAbs(color.green() - color.blue()) > 16) return false; if (color.red() < 0x60) return false; if (color.red() > 0xA0) return false; return true; } void ConnectorItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { if (m_hybrid) return; if (doNotPaint()) return; if (m_legPolygon.count() > 1) { paintLeg(painter); return; } if (m_effectively == EffectivelyUnknown) { if (!m_circular && m_shape.isEmpty()) { if (this->attachedTo()->viewID() == ViewLayer::PCBView) { QRectF r = rect(); if (qAbs(r.width() - r.height()) < 0.01) m_effectively = EffectivelyCircular; else m_effectively = EffectivelyRectangular; } } } NonConnectorItem::paint(painter, option, widget); } void ConnectorItem::paintLeg(QPainter * painter) { QPen lpen = legPen(); painter->setPen(lpen); bool hasCurves = false; foreach (Bezier * bezier, m_legCurves) { if (bezier != NULL && !bezier->isEmpty()) { hasCurves = true; break; } } // draw the leg first paintLeg(painter, hasCurves); if (m_legPolygon.count() > 2) { // draw bendpoint indicators double halfWidth = lpen.widthF() / 2; painter->setPen(Qt::NoPen); QColor c = addColor(m_legColor, (qGray(m_legColor.rgb()) < 64) ? 80 : -64); painter->setBrush(c); for (int i = 1; i < m_legPolygon.count() - 1; i++) { painter->drawEllipse(m_legPolygon.at(i), halfWidth, halfWidth); } painter->setBrush(Qt::NoBrush); } if (m_attachedTo->inHover()) { // hover highlight lpen.setColor((qGray(m_legColor.rgb()) < 48) ? QColor(255, 255, 255) : QColor(0, 0, 0)); painter->setOpacity(ItemBase::HoverOpacity); painter->setPen(lpen); paintLeg(painter, hasCurves); } // now draw the connector Bezier * bezier = m_legCurves.at(m_legCurves.count() - 2); bool connectorIsCurved = (bezier != NULL && !bezier->isEmpty()); Bezier left, right; QPainterPath path; if (connectorIsCurved) { bezier->split(m_connectorDrawT, left, right); path.moveTo(right.endpoint0()); path.cubicTo(right.cp0(), right.cp1(), right.endpoint1()); } if (!isGrey(m_legColor)) { // draw an undercolor so the connectorColor will be visible on top of the leg color lpen.setColor(0x8c8c8c); // TODO: don't hardcode color painter->setOpacity(1); painter->setPen(lpen); if (connectorIsCurved) { painter->drawPath(path); } else { painter->drawLine(m_connectorDrawEnd, m_legPolygon.last()); } } QPen pen = this->pen(); pen.setWidthF(m_legStrokeWidth); pen.setCapStyle(Qt::RoundCap); painter->setOpacity(m_opacity); painter->setPen(pen); if (connectorIsCurved) { painter->drawPath(path); } else { painter->drawLine(m_connectorDrawEnd, m_legPolygon.last()); } } void ConnectorItem::paintLeg(QPainter * painter, bool hasCurves) { if (hasCurves) { for (int i = 0; i < m_legPolygon.count() -1; i++) { Bezier * bezier = m_legCurves.at(i); if (bezier && !bezier->isEmpty()) { QPainterPath path; path.moveTo(m_legPolygon.at(i)); path.cubicTo(bezier->cp0(), bezier->cp1(), m_legPolygon.at(i + 1)); painter->drawPath(path); } else { painter->drawLine(m_legPolygon.at(i), m_legPolygon.at(i + 1)); } } } else { painter->drawPolyline(m_legPolygon); } } ConnectorItem * ConnectorItem::chooseFromSpec(ViewLayer::ViewLayerPlacement viewLayerPlacement) { ConnectorItem * crossConnectorItem = getCrossLayerConnectorItem(); if (crossConnectorItem == NULL) return this; ViewLayer::ViewLayerID basis = ViewLayer::Copper0; switch (viewLayerPlacement) { case ViewLayer::NewTop: basis = ViewLayer::Copper1; break; case ViewLayer::NewBottom: basis = ViewLayer::Copper0; break; default: DebugDialog::debug(QString("unusual viewLayerPlacement %1").arg(viewLayerPlacement)); basis = ViewLayer::Copper0; break; } if (this->attachedToViewLayerID() == basis) { return this; } if (crossConnectorItem->attachedToViewLayerID() == basis) { return crossConnectorItem; } return this; } bool ConnectorItem::connectedToWires() { foreach (ConnectorItem * toConnectorItem, connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { return true; } } ConnectorItem * crossConnectorItem = getCrossLayerConnectorItem(); if (crossConnectorItem == NULL) return false; foreach (ConnectorItem * toConnectorItem, crossConnectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { return true; } } return false; } void ConnectorItem::displayRatsnest(QList & partConnectorItems, ViewGeometry::WireFlags myFlag) { bool formerColorWasNamed = false; bool gotFormerColor = false; QColor formerColor; VirtualWire * vw = NULL; foreach (ConnectorItem * fromConnectorItem, partConnectorItems) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { vw = qobject_cast(toConnectorItem->attachedTo()); if (vw != NULL) break; } if (vw != NULL) break; } if (vw != NULL) { formerColorWasNamed = vw->colorWasNamed(); formerColor = vw->color(); gotFormerColor = true; clearRatsnestDisplay(partConnectorItems); } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; if (partConnectorItems.count() < 2) return; QStringList connectorNames; ConnectorItem::collectConnectorNames(partConnectorItems, connectorNames); QColor color; bool colorWasNamed = RatsnestColors::findConnectorColor(connectorNames, color); if (!colorWasNamed) { if (!formerColorWasNamed && gotFormerColor) { color = formerColor; } else { infoGraphicsView->getRatsnestColor(color); } } ConnectorPairHash result; GraphUtils::chooseRatsnestGraph(&partConnectorItems, (ViewGeometry::RatsnestFlag | ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag) ^ myFlag, result); foreach (ConnectorItem * key, result.uniqueKeys()) { foreach (ConnectorItem * value, result.values(key)) { VirtualWire * vw = infoGraphicsView->makeOneRatsnestWire(key, value, false, color, false); if (vw) { vw->setColorWasNamed(colorWasNamed); } } } } void ConnectorItem::clearRatsnestDisplay(QList & connectorItems) { QSet ratsnests; foreach (ConnectorItem * fromConnectorItem, connectorItems) { if (fromConnectorItem == NULL) continue; foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { VirtualWire * vw = qobject_cast(toConnectorItem->attachedTo()); if (vw != NULL) { ratsnests.insert(vw); } } } foreach (VirtualWire * vw, ratsnests.values()) { ConnectorItem * c1 = vw->connector0()->firstConnectedToIsh(); if (c1 != NULL) { vw->connector0()->tempRemove(c1, false); c1->tempRemove(vw->connector0(), false); } ConnectorItem * c2 = vw->connector1()->firstConnectedToIsh(); if (c2 != NULL) { vw->connector1()->tempRemove(c2, false); c2->tempRemove(vw->connector1(), false); } //vw->debugInfo("removing rat 1"); vw->scene()->removeItem(vw); delete vw; } } void ConnectorItem::collectConnectorNames(QList & connectorItems, QStringList & connectorNames) { foreach(ConnectorItem * connectorItem, connectorItems) { if (!connectorNames.contains(connectorItem->connectorSharedName())) { connectorNames.append(connectorItem->connectorSharedName()); //DebugDialog::debug("name " + connectorItem->connectorSharedName()); } } } double ConnectorItem::calcClipRadius() { if (m_circular) { return radius() - (strokeWidth() / 2.0); } if (m_effectively == EffectivelyCircular) { double rad = rect().width() / 2; return rad - (rad / 5); } return 0; } bool ConnectorItem::isEffectivelyCircular() { return m_circular || m_effectively == EffectivelyCircular; } void ConnectorItem::debugInfo(const QString & msg) { #ifndef QT_NO_DEBUG QPointF p = sceneAdjustedTerminalPoint(NULL); QString s = QString("%1 cid:%2 cname:%3 title:%4 id:%5 type:%6 inst:%7 vlid:%8 vid:%9 spec:%10 flg:%11 hy:%12 bus:%13 r:%14 sw:%15 pos:(%16 %17)") .arg(msg) .arg(this->connectorSharedID()) .arg(this->connectorSharedName()) .arg(this->attachedToTitle()) .arg(this->attachedToID()) .arg(this->attachedToItemType()) .arg(this->attachedToInstanceTitle()) .arg(this->attachedToViewLayerID()) .arg(this->attachedToViewID()) .arg(this->attachedToViewLayerPlacement()) .arg(this->attachedTo()->wireFlags()) .arg(this->m_hybrid) .arg((long) this->bus(), 0, 16) .arg(this->m_radius) .arg(this->m_strokeWidth) .arg(p.x()) .arg(p.y()) ; //s.replace(" ", "_"); DebugDialog::debug(s); #else Q_UNUSED(msg); #endif } double ConnectorItem::minDimension() { QRectF r = this->boundingRect(); return qMin(r.width(), r.height()); } ConnectorItem * ConnectorItem::findConnectorUnder(bool useTerminalPoint, bool allowAlready, const QList & exclude, bool displayDragTooltip, ConnectorItem * other) { QList items = useTerminalPoint ? this->scene()->items(this->sceneAdjustedTerminalPoint(NULL)) : this->scene()->items(mapToScene(this->rect())); // only wires use rect QList candidates; // for the moment, take the topmost ConnectorItem that doesn't belong to me foreach (QGraphicsItem * item, items) { ConnectorItem * connectorItemUnder = dynamic_cast(item); if (connectorItemUnder == NULL) continue; if (connectorItemUnder->connector() == NULL) continue; // shouldn't happen if (attachedTo()->childItems().contains(connectorItemUnder)) continue; // don't use own connectors if (!this->connectionIsAllowed(connectorItemUnder)) { continue; } if (!allowAlready) { if (connectorItemUnder->connectedToItems().contains(this)) { continue; // already connected } } if (exclude.contains(connectorItemUnder)) continue; candidates.append(connectorItemUnder); } ConnectorItem * candidate = NULL; if (candidates.count() == 1) { candidate = candidates[0]; } else if (candidates.count() > 0) { qSort(candidates.begin(), candidates.end(), wireLessThan); candidate = candidates[0]; } if (m_overConnectorItem != NULL && candidate != m_overConnectorItem) { m_overConnectorItem->connectorHover(NULL, false); } if (candidate != NULL && candidate != m_overConnectorItem) { candidate->connectorHover(NULL, true); } m_overConnectorItem = candidate; if (candidate == NULL) { if (this->connectorHovering()) { this->connectorHover(NULL, false); } } else { if (!this->connectorHovering()) { this->connectorHover(NULL, true); } } if (displayDragTooltip) { displayTooltip(m_overConnectorItem, other); } return m_overConnectorItem; } void ConnectorItem::displayTooltip(ConnectorItem * ci, ConnectorItem * other) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; // Activate tooltip for destination connector. based on a patch submitted by bryant.mairs QString text; if (ci && ci->connectorHovering()) { if (other) { text = QString("%1: %2\n%3: %4") .arg(other->attachedToInstanceTitle()) .arg(other->connectorSharedName()) .arg(ci->attachedToInstanceTitle()) .arg(ci->connectorSharedName()); } else { text = QString("%1: %2").arg(ci->attachedToInstanceTitle()).arg(ci->connectorSharedName()); } } else { if (other) { text = QString("%1: %2") .arg(other->attachedToInstanceTitle()) .arg(other->connectorSharedName()); } } // Now use Qt's tooltip functionality to display our tooltip. // The tooltip text is first cleared as only a change in tooltip // text will update its position. // A rect is generated to smooth out position updates. // NOTE: Increasing this rect will cause the tooltip to disappear // and not reappear until another pixel move after the move that // disabled it. QPoint sp = QCursor::pos(); QToolTip::showText(sp, "", infoGraphicsView); if (!text.isEmpty()) { QPoint q = infoGraphicsView->mapFromGlobal(sp); QRect r(q.x(), q.y(), 1, 1); QToolTip::showText(sp, text, infoGraphicsView, r); } } ConnectorItem * ConnectorItem::releaseDrag() { ConnectorItem * result = m_overConnectorItem; if (m_overConnectorItem != NULL) { m_overConnectorItem->connectorHover(NULL, false); // clean up setOverConnectorItem(NULL); clearConnectorHover(); QList visited; restoreColor(visited); } attachedTo()->clearConnectorHover(); return result; } void ConnectorItem::rotateLeg(const QPolygonF & poly, bool active) { resetLeg(poly, false, active, "rotate"); } void ConnectorItem::resetLeg(const QPolygonF & poly, bool relative, bool active, const QString & why) { if (!m_rubberBandLeg) return; ConnectorItem * target = NULL; foreach (ConnectorItem * connectorItem, this->m_connectedTo) { if (connectorItem->connectorType() == Connector::Female) { target = connectorItem; break; } } if (target == NULL) { setLeg(poly, relative, why); return; } if (!active) { repositionTarget(); return; } if (why.compare("swap") == 0) { setLeg(poly, relative, why); repositionTarget(); return; } //DebugDialog::debug("connectorItem prepareGeometryChange 1"); prepareGeometryChange(); QPointF sceneNewLast = target->sceneAdjustedTerminalPoint(NULL); QPointF sceneOldLast = poly.last(); for (int i = 1; i < m_legPolygon.count(); i++) { m_legPolygon.replace(i, mapFromScene(poly.at(i) - sceneOldLast + sceneNewLast)); } calcConnectorEnd(); update(); } void ConnectorItem::setLeg(const QPolygonF & poly, bool relative, const QString & why) { Q_UNUSED(why); if (!m_rubberBandLeg) return; repoly(poly, relative); update(); } const QPolygonF & ConnectorItem::leg() { static QPolygonF emptyPoly; if (!m_rubberBandLeg) return emptyPoly; return m_legPolygon; } bool ConnectorItem::isDraggingLeg() { return m_draggingLeg; } QString ConnectorItem::makeLegSvg(QPointF offset, double dpi, double printerScale, bool blackOnly) { if (!m_rubberBandLeg) return ""; QString data("M"); QPointF p = m_legPolygon.at(0); data += TextUtils::pointToSvgString(mapToScene(p), offset, dpi, printerScale); for (int i = 1; i < m_legPolygon.count(); i++) { QPointF p = m_legPolygon.at(i); Bezier * bezier = m_legCurves.at(i - 1); if (bezier == NULL || bezier->isEmpty()) { data += "L"; data += TextUtils::pointToSvgString(mapToScene(p), offset, dpi, printerScale); } else { data += "C"; data += TextUtils::pointToSvgString(mapToScene(bezier->cp0()), offset, dpi, printerScale); data += " "; data += TextUtils::pointToSvgString(mapToScene(bezier->cp1()), offset, dpi, printerScale); data += " "; data += TextUtils::pointToSvgString(mapToScene(p), offset, dpi, printerScale); } } QString path = QString("\n") .arg(blackOnly ? "black" : m_legColor.name()) .arg(m_legStrokeWidth * dpi / printerScale) .arg(data); return path; } QPolygonF ConnectorItem::sceneAdjustedLeg() { if (!m_rubberBandLeg) return QPolygonF(); QPolygonF poly; foreach (QPointF p, m_legPolygon) { poly.append(mapToScene(p)); } return poly; } void ConnectorItem::prepareToStretch(bool activeStretch) { m_activeStretch = activeStretch; m_oldPolygon = sceneAdjustedLeg(); } void ConnectorItem::stretchBy(QPointF howMuch) { if (!m_rubberBandLeg) return; Q_UNUSED(howMuch); resetLeg(m_oldPolygon, false, m_activeStretch, "move"); // if update isn't called here then legs repaint, but body doesn't // so you get a weird "headless" effect m_attachedTo->update(); } void ConnectorItem::stretchDone(QPolygonF & oldLeg, QPolygonF & newLeg, bool & active) { oldLeg = m_oldPolygon; newLeg = sceneAdjustedLeg(); active = m_activeStretch; } void ConnectorItem::moveDone(int & index0, QPointF & oldPos0, QPointF & newPos0, int & index1, QPointF & oldPos1, QPointF & newPos1) { index0 = (m_activeStretch) ? 1 : m_legPolygon.count() - 1; oldPos0 = m_oldPolygon.at(index0); newPos0 = mapToScene(m_legPolygon.at(index0)); index1 = m_legPolygon.count() - 1; oldPos1 = m_oldPolygon.at(index1); newPos1 = mapToScene(m_legPolygon.at(index1)); } QRectF ConnectorItem::boundingRect() const { if (m_legPolygon.count() < 2) return NonConnectorItem::boundingRect(); return shape().controlPointRect(); } QPainterPath ConnectorItem::hoverShape() const { return shapeAux(2 * m_legStrokeWidth); } QPainterPath ConnectorItem::shape() const { return shapeAux(m_legStrokeWidth); } QPainterPath ConnectorItem::shapeAux(double width) const { if (m_legPolygon.count() < 2) return NonConnectorItem::shape(); QPainterPath path; path.moveTo(m_legPolygon.at(0)); for (int i = 1; i < m_legPolygon.count(); i++) { Bezier * bezier = m_legCurves.at(i - 1); if (bezier != NULL && !bezier->isEmpty()) { path.cubicTo(bezier->cp0(), bezier->cp1(), m_legPolygon.at(i)); } else { path.lineTo(m_legPolygon.at(i)); } } QPen pen = legPen(); return GraphicsUtils::shapeFromPath(path, pen, width, false); } void ConnectorItem::repositionTarget() { // this connector is connected to another part which is being dragged foreach (ConnectorItem * connectorItem, this->m_connectedTo) { if (connectorItem->connectorType() == Connector::Female) { reposition(connectorItem->sceneAdjustedTerminalPoint(NULL), m_legPolygon.count() - 1); break; } } } void ConnectorItem::reposition(QPointF sceneDestPos, int draggingIndex) { //DebugDialog::debug("connectorItem prepareGeometryChange 2"); prepareGeometryChange(); //foreach (QPointF p, m_legPolygon) DebugDialog::debug(QString("point b %1 %2").arg(p.x()).arg(p.y())); QPointF dest = mapFromScene(sceneDestPos); m_legPolygon.replace(draggingIndex, dest); //foreach (QPointF p, m_legPolygon) DebugDialog::debug(QString("point a %1 %2").arg(p.x()).arg(p.y())); calcConnectorEnd(); } void ConnectorItem::repoly(const QPolygonF & poly, bool relative) { //DebugDialog::debug("connectorItem prepareGeometryChange 3"); prepareGeometryChange(); //foreach (QPointF p, m_legPolygon) DebugDialog::debug(QString("point b %1 %2").arg(p.x()).arg(p.y())); m_legPolygon.clear(); clearCurves(); foreach (QPointF p, poly) { m_legPolygon.append(relative ? p : mapFromScene(p)); m_legCurves.append(NULL); } //foreach (QPointF p, m_legPolygon) DebugDialog::debug(QString("point a %1 %2").arg(p.x()).arg(p.y())); calcConnectorEnd(); } void ConnectorItem::calcConnectorEnd() { if (m_legPolygon.count() < 2) { m_connectorDrawEnd = m_connectorDetectEnd = QPointF(0,0); return; } QPointF p1 = m_legPolygon.last(); QPointF p0 = m_legPolygon.at(m_legPolygon.count() - 2); double dx = p1.x() - p0.x(); double dy = p1.y() - p0.y(); double lineLen = qSqrt((dx * dx) + (dy * dy)); double drawlen = qMax(0.5, qMin(lineLen, StandardLegConnectorDrawEnabledLength)); double detectlen = qMax(0.5, qMin(lineLen, StandardLegConnectorDetectLength)); Bezier * bezier = m_legCurves.at(m_legCurves.count() - 2); if (bezier == NULL || bezier->isEmpty()) { m_connectorDrawEnd = QPointF(p1 - QPointF(dx * drawlen / lineLen, dy * drawlen / lineLen)); m_connectorDetectEnd = QPointF(p1 - QPointF(dx * detectlen / lineLen, dy * detectlen / lineLen)); return; } bezier->set_endpoints(p0, p1); m_connectorDetectT = m_connectorDrawT = 0; double blen = bezier->computeCubicCurveLength(1.0, 24); if (blen < StandardLegConnectorDetectLength) { return; } m_connectorDetectT = findT(bezier, blen, StandardLegConnectorDetectLength); m_connectorDrawT = findT(bezier, blen, StandardLegConnectorDrawEnabledLength); } double ConnectorItem::findT(Bezier * bezier, double blen, double length) { // use binary search to find a value for t double tmax = 1.0; double tmin = 0; double t = 1.0 - (length / blen); while (true) { double l = bezier->computeCubicCurveLength(t, 24); if (qAbs(blen - length - l) < .0001) { return t; } if (blen - length - l > 0) { // too short tmin = t; t = (t + tmax) / 2; } else { // too long tmax = t; t = (t + tmin) / 2; } } return t; } const QString & ConnectorItem::legID(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { if (m_connector) return m_connector->legID(viewID, viewLayerID); return ___emptyString___; } void ConnectorItem::setRubberBandLeg(QColor color, double strokeWidth, QLineF parentLine) { // assumes this is only called once, when the connector is first set up /* this->debugInfo(QString("set rubber band leg %1 %2 %3 %4") .arg(parentLine.p1().x()) .arg(parentLine.p1().y()) .arg(parentLine.p2().x()) .arg(parentLine.p2().y()) ); */ m_rubberBandLeg = true; setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); setAcceptedMouseButtons(ALLMOUSEBUTTONS); // p1 is always the start point closest to the body. setPos(parentLine.p1()); m_legPolygon.append(QPointF(0,0)); m_legPolygon.append(parentLine.p2() - parentLine.p1()); m_legCurves.append(NULL); m_legCurves.append(NULL); m_legStrokeWidth = strokeWidth; m_legColor = color; reposition(m_attachedTo->mapToScene(parentLine.p2()), 1); this->setCircular(false); } bool ConnectorItem::hasRubberBandLeg() const { return m_rubberBandLeg; } void ConnectorItem::killRubberBandLeg() { // this is a hack; see the caller for explanation prepareGeometryChange(); m_rubberBandLeg = false; m_legPolygon.clear(); clearCurves(); } QPen ConnectorItem::legPen() const { if (!m_rubberBandLeg) return QPen(); QPen pen; pen.setWidthF(m_legStrokeWidth); pen.setColor(m_legColor); pen.setCapStyle(Qt::RoundCap); pen.setJoinStyle(Qt::RoundJoin); return pen; } bool ConnectorItem::legMousePressEvent(QGraphicsSceneMouseEvent *event) { m_insertBendpointPossible = false; if (attachedTo()->moveLock()) { event->ignore(); return true; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->prepLegSelection(this->attachedTo()); } int bendpointIndex; CursorLocation cursorLocation = findLocation(event->pos(), bendpointIndex); switch (cursorLocation) { case InConnector: if (event->modifiers() & altOrMetaModifier()) return false; m_holdPos = mapToScene(m_legPolygon.last()); m_draggingLeg = true; m_draggingLegIndex = m_legPolygon.count() - 1; m_oldPolygon = m_legPolygon; QGraphicsRectItem::mousePressEvent(event); return true; case InSegment: if (curvyWiresIndicated(event->modifiers())) { m_draggingLegIndex = bendpointIndex - 1; Bezier * bezier = m_legCurves.at(m_draggingLegIndex); if (bezier == NULL) { bezier = new Bezier(); m_legCurves.replace(m_draggingLegIndex, bezier); } UndoBezier.copy(bezier); if (bezier->isEmpty()) { QPointF p0 = m_legPolygon.at(m_draggingLegIndex); QPointF p1 = m_legPolygon.at(m_draggingLegIndex + 1); bezier->initToEnds(p0, p1); } bezier->initControlIndex(event->pos(), m_legStrokeWidth); m_draggingCurve = m_draggingLeg = true; TheBezierDisplay = new BezierDisplay; TheBezierDisplay->initDisplay(this, bezier); return true; } else { m_insertBendpointPossible = true; } // must continue on to InBendpoint case InBendpoint: m_draggingLegIndex = bendpointIndex; m_holdPos = event->scenePos(); m_oldPolygon = m_legPolygon; m_draggingLeg = true; QGraphicsRectItem::mousePressEvent(event); return true; case InOrigin: case InNotFound: default: event->ignore(); return true; } } ConnectorItem::CursorLocation ConnectorItem::findLocation(QPointF location, int & bendpointIndex) { QPainterPath path; Bezier * bezier = m_legCurves.at(m_legCurves.count() - 2); if (bezier == NULL || bezier->isEmpty()) { path.moveTo(m_connectorDetectEnd); path.lineTo(m_legPolygon.last()); } else { Bezier left, right; bezier->split(m_connectorDetectT, left, right); path.moveTo(right.endpoint0()); path.cubicTo(right.cp0(), right.cp1(), right.endpoint1()); } QPen pen = legPen(); path = GraphicsUtils::shapeFromPath(path, pen, m_legStrokeWidth, false); if (path.contains(location)) { return InConnector; } double wSqd = 4 * m_legStrokeWidth * m_legStrokeWidth; // hover distance for (int i = 0; i < m_legPolygon.count() - 1; i++) { QPainterPath path; path.moveTo(m_legPolygon.at(i)); Bezier * bezier = m_legCurves.at(i); if (bezier != NULL && !bezier->isEmpty()) { path.cubicTo(bezier->cp0(), bezier->cp1(), m_legPolygon.at(i + 1)); } else { path.lineTo(m_legPolygon.at(i + 1)); } path = GraphicsUtils::shapeFromPath(path, pen, m_legStrokeWidth, false); if (path.contains(location)) { double d = GraphicsUtils::distanceSqd(m_legPolygon.at(i), location); if (d <= wSqd) { bendpointIndex = i; if (i == 0) { return InOrigin; } return InBendpoint; } else { d = GraphicsUtils::distanceSqd(m_legPolygon.at(i + 1), location); if (d <= wSqd) { bendpointIndex = i + 1; return InBendpoint; } } bendpointIndex = i + 1; return InSegment; } } return InNotFound; } void ConnectorItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { if (m_hidden || m_inactive || m_hybrid) { event->ignore(); return; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setActiveConnectorItem(this); } if ((acceptedMouseButtons() & Qt::RightButton) == 0) { event->ignore(); return; } if (!m_rubberBandLeg) { event->ignore(); return; } int bendpointIndex; CursorLocation cursorLocation = findLocation(event->pos(), bendpointIndex); switch (cursorLocation) { case InSegment: { QMenu menu; QAction * addAction = menu.addAction(tr("Add bendpoint")); addAction->setData(1); Bezier * bezier = m_legCurves.at(bendpointIndex - 1); if (bezier != NULL && !bezier->isEmpty()) { QAction * straightenAction = menu.addAction(tr("Straighten curve")); straightenAction->setData(2); } QAction *selectedAction = menu.exec(event->screenPos()); if (selectedAction) { if (selectedAction->data().toInt() == 1) { insertBendpoint(event->pos(), bendpointIndex); } else if (selectedAction->data().toInt() == 2) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { Bezier newBezier; infoGraphicsView->prepLegCurveChange(this, bendpointIndex - 1,bezier, &newBezier, true); } } } } return; case InBendpoint: if (bendpointIndex < m_legPolygon.count() - 1) { QMenu menu; menu.addAction(tr("Remove bendpoint")); QAction *selectedAction = menu.exec(event->screenPos()); if (selectedAction) { removeBendpoint(bendpointIndex); } return; } default: break; } event->ignore(); return; } void ConnectorItem::insertBendpoint(QPointF p, int bendpointIndex) { prepareGeometryChange(); m_oldPolygon = m_legPolygon; insertBendpointAux(p, bendpointIndex); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->prepLegBendpointChange(this, m_oldPolygon.count(), m_legPolygon.count(), bendpointIndex, p, &UndoBezier, m_legCurves.at(bendpointIndex - 1), m_legCurves.at(bendpointIndex), false); } calcConnectorEnd(); update(); } Bezier * ConnectorItem::insertBendpointAux(QPointF p, int bendpointIndex) { UndoBezier.clear(); m_legPolygon.insert(bendpointIndex, p); m_legCurves.insert(bendpointIndex, NULL); Bezier * bezier = m_legCurves.at(bendpointIndex - 1); if (bezier == NULL || bezier->isEmpty()) return NULL; QPointF p0 = m_legPolygon.at(bendpointIndex - 1); QPointF p1 = m_legPolygon.at(bendpointIndex + 1); bezier->set_endpoints(p0, p1); UndoBezier.copy(bezier); double t = bezier->findSplit(p, m_legStrokeWidth); Bezier left, right; bezier->split(t, left, right); replaceBezier(bendpointIndex - 1, &left); replaceBezier(bendpointIndex, &right); return NULL; } void ConnectorItem::removeBendpoint(int bendpointIndex) { prepareGeometryChange(); Bezier b0, b1; b0.copy(m_legCurves.at(bendpointIndex - 1)); QPointF p0 = m_legPolygon.at(bendpointIndex - 1); QPointF p1 = m_legPolygon.at(bendpointIndex); b0.set_endpoints(p0, p1); b1.copy(m_legCurves.at(bendpointIndex)); p0 = m_legPolygon.at(bendpointIndex); p1 = m_legPolygon.at(bendpointIndex + 1); b0.set_endpoints(p0, p1); m_oldPolygon = m_legPolygon; QPointF p = m_legPolygon.at(bendpointIndex); m_legPolygon.remove(bendpointIndex); Bezier b2 = b0.join(&b1); replaceBezier(bendpointIndex - 1, &b2); Bezier * bezier = m_legCurves.at(bendpointIndex); m_legCurves.remove(bendpointIndex); if (bezier) delete bezier; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->prepLegBendpointChange(this, m_oldPolygon.count(), m_legPolygon.count(), bendpointIndex, p, &b0, &b1, &b2, false); } calcConnectorEnd(); update(); } void ConnectorItem::clearCurves() { foreach (Bezier * bezier, m_legCurves) { if (bezier != NULL) delete bezier; } m_legCurves.clear(); } void ConnectorItem::changeLegCurve(int index, const Bezier *newBezier) { prepareGeometryChange(); replaceBezier(index, newBezier); calcConnectorEnd(); update(); } void ConnectorItem::addLegBendpoint(int index, QPointF p, const Bezier * bezierLeft, const Bezier * bezierRight) { prepareGeometryChange(); m_legPolygon.insert(index, p); m_legCurves.insert(index, NULL); replaceBezier(index - 1, bezierLeft); replaceBezier(index, bezierRight); calcConnectorEnd(); update(); } void ConnectorItem::removeLegBendpoint(int index, const Bezier * newBezier) { prepareGeometryChange(); m_legPolygon.remove(index); Bezier * bezier = m_legCurves.at(index); if (bezier) delete bezier; m_legCurves.remove(index); replaceBezier(index - 1, newBezier); calcConnectorEnd(); update(); } void ConnectorItem::moveLegBendpoint(int index, QPointF p) { m_legPolygon.replace(index, mapFromScene(p)); calcConnectorEnd(); update(); } const QVector & ConnectorItem::beziers() { return m_legCurves; } void ConnectorItem::replaceBezier(int index, const Bezier * newBezier) { Bezier * bezier = m_legCurves.at(index); if (bezier == NULL && newBezier == NULL) { } else if (bezier && newBezier) { bezier->copy(newBezier); } else if (newBezier) { bezier = new Bezier; m_legCurves.replace(index , bezier); bezier->copy(newBezier); } else if (bezier) { bezier->clear(); } } void ConnectorItem::cursorKeyEvent(Qt::KeyboardModifiers modifiers) { if (m_rubberBandLeg) { if (m_draggingLeg) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);; if (infoGraphicsView) { QPoint p = infoGraphicsView->mapFromGlobal(QCursor::pos()); QPointF r = infoGraphicsView->mapToScene(p); // DebugDialog::debug(QString("got key event %1").arg(keyEvent->modifiers())); updateLegCursor(mapFromScene(r), modifiers); } } else if (attachedToItemType() == ModelPart::Wire) { updateWireCursor(modifiers); } } void ConnectorItem::updateWireCursor(Qt::KeyboardModifiers modifiers) { //DebugDialog::debug("uwc"); QCursor cursor = *CursorMaster::BendpointCursor; if (isBendpoint()) { //DebugDialog::debug("uwc bend"); if (modifiers & altOrMetaModifier()) { //DebugDialog::debug("uwc alt"); Wire * wire = qobject_cast(attachedTo()); if (wire != NULL && wire->canChainMultiple()) { //DebugDialog::debug("uwc make wire"); cursor = *CursorMaster::MakeWireCursor; } } } CursorMaster::instance()->addCursor(this, cursor); } void ConnectorItem::updateLegCursor(QPointF p, Qt::KeyboardModifiers modifiers) { int bendpointIndex; CursorLocation cursorLocation = findLocation(p, bendpointIndex); QCursor cursor; switch (cursorLocation) { case InOrigin: cursor = *attachedTo()->getCursor(modifiers); break; case InBendpoint: cursor = *CursorMaster::BendpointCursor; break; case InSegment: cursor = curvyWiresIndicated(modifiers) ? *CursorMaster::MakeCurveCursor : *CursorMaster::NewBendpointCursor; break; case InConnector: cursor = (modifiers & altOrMetaModifier()) ? *CursorMaster::MakeWireCursor : *CursorMaster::BendlegCursor; break; default: cursor = Qt::ArrowCursor; break; } CursorMaster::instance()->addCursor(this, cursor); } bool ConnectorItem::curvyWiresIndicated(Qt::KeyboardModifiers modifiers) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return true; return infoGraphicsView->curvyWiresIndicated(modifiers); } bool ConnectorItem::isBendpoint() { if (connectionsCount() == 0) return false; foreach (ConnectorItem * ci, connectedToItems()) { if (ci->attachedToItemType() != ModelPart::Wire) { return false; } } return true; } void ConnectorItem::setConnectorLocalName(const QString & name) { if (m_connector) { m_connector->setConnectorLocalName(name); } } bool ConnectorItem::isGroundFillSeed() { return m_groundFillSeed; } void ConnectorItem::setGroundFillSeed(bool seed) { m_groundFillSeed = seed; ConnectorItem * cross = this->getCrossLayerConnectorItem(); if (cross) cross->m_groundFillSeed = seed; } ViewGeometry::WireFlags ConnectorItem::getSkipFlags() { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return ViewGeometry::RatsnestFlag; return (ViewGeometry::RatsnestFlag | ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag) ^ infoGraphicsView->getTraceFlag(); } fritzing-app-0.9.2b/src/connectors/connectoritem.h000066400000000000000000000232101250202676700222710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef CONNECTORITEM_H #define CONNECTORITEM_H #include "nonconnectoritem.h" #include "connector.h" #include "../utils/cursormaster.h" #include #include class LegItem; class ConnectorItemAction : public QAction { Q_OBJECT public: ConnectorItemAction(QAction *); ConnectorItemAction(const QString & text, QObject * parent); void setConnectorItem(ConnectorItem *); ConnectorItem * connectorItem(); protected: ConnectorItem * m_connectorItem; }; class ConnectorItem : public NonConnectorItem, public CursorKeyListener { Q_OBJECT public: ConnectorItem(Connector *, ItemBase* attachedTo); ~ConnectorItem(); Connector * connector(); void connectorHover(class ItemBase *, bool hovering); bool connectorHovering(); void clearConnectorHover(); void connectTo(ConnectorItem *); int connectionsCount(); void attachedMoved(bool includeRatsnest, QList & already); ConnectorItem * removeConnection(ItemBase *); void removeConnection(ConnectorItem *, bool emitChange); ConnectorItem * firstConnectedToIsh(); void setTerminalPoint(QPointF); QPointF terminalPoint(); QPointF adjustedTerminalPoint(); QPointF sceneAdjustedTerminalPoint(ConnectorItem * anchor); bool connectedTo(ConnectorItem *); const QList< QPointer > & connectedToItems(); void setHidden(bool hidden); void setInactive(bool inactivate); ConnectorItem * overConnectorItem(); void setOverConnectorItem(ConnectorItem *); ViewLayer::ViewLayerID attachedToViewLayerID(); ViewLayer::ViewLayerPlacement attachedToViewLayerPlacement(); ViewLayer::ViewID attachedToViewID(); const QString & connectorSharedID(); const QString & connectorSharedName(); const QString & connectorSharedDescription(); const QString & connectorSharedReplacedby(); class ErcData * connectorSharedErcData(); const QString & busID(); ModelPartShared * modelPartShared(); ModelPart * modelPart(); class Bus * bus(); void tempConnectTo(ConnectorItem * item, bool applyColor); void tempRemove(ConnectorItem * item, bool applyColor); Connector::ConnectorType connectorType(); bool chained(); void saveInstance(QXmlStreamWriter & ); void writeConnector(QXmlStreamWriter & writer, const QString & elementName); bool wiredTo(ConnectorItem *, ViewGeometry::WireFlags skipFlags); void clearConnector(); bool connectionIsAllowed(ConnectorItem * other); void restoreColor(QList & visited); void showEqualPotential(bool show, QList & visited); void setHoverColor(); bool isGrounded(); ConnectorItem * chooseFromSpec(ViewLayer::ViewLayerPlacement); bool connectedToWires(); bool isCrossLayerConnectorItem(ConnectorItem * candidate); bool isCrossLayerFrom(ConnectorItem * candidate); bool isInLayers(ViewLayer::ViewLayerPlacement); ConnectorItem * getCrossLayerConnectorItem(); void displayRatsnest(QList & partsConnectorItems, ViewGeometry::WireFlags myFlag); void clearRatsnestDisplay(QList & connectorItems); double calcClipRadius(); bool isEffectivelyCircular(); void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); void debugInfo(const QString & msg); double minDimension(); void setHybrid(bool); bool isHybrid(); void setBigDot(bool); bool isBigDot(); ConnectorItem * findConnectorUnder(bool useTerminalPoint, bool allowAlready, const QList & exclude, bool displayDragTooltip, ConnectorItem * other); ConnectorItem * releaseDrag(); // rubberBand leg functions bool isDraggingLeg(); void setRubberBandLeg(QColor color, double strokeWidth, QLineF parentLine); bool hasRubberBandLeg() const; void rotateLeg(const QPolygonF &, bool active); void setLeg(const QPolygonF &, bool relative, const QString & why); void resetLeg(const QPolygonF &, bool relative, bool active, const QString & why); const QPolygonF & leg(); QString makeLegSvg(QPointF offset, double dpi, double printerScale, bool blackOnly); QPolygonF sceneAdjustedLeg(); void prepareToStretch(bool activeStretch); void stretchBy(QPointF howMuch); void stretchDone(QPolygonF & oldLeg, QPolygonF & newLeg, bool & active); void moveDone(int & index0, QPointF & oldPos0, QPointF & newPos0, int & index1, QPointF & oldPos1, QPointF & newPos1); void killRubberBandLeg(); // hack; see caller QRectF boundingRect() const; const QString & legID(ViewLayer::ViewID, ViewLayer::ViewLayerID); QPainterPath shape() const; QPainterPath hoverShape() const; void changeLegCurve(int index, const class Bezier *); void addLegBendpoint(int index, QPointF, const class Bezier *, const class Bezier *); void removeLegBendpoint(int index, const class Bezier *); void moveLegBendpoint(int index, QPointF); const QVector & beziers(); bool isBendpoint(); void cursorKeyEvent(Qt::KeyboardModifiers modifiers); void setConnectorLocalName(const QString & name); void updateTooltip(); bool isGroundFillSeed(); void setGroundFillSeed(bool); protected: void hoverEnterEvent( QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ); void hoverMoveEvent( QGraphicsSceneHoverEvent * event ); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); void setNormalColor(); void setConnectedColor(); void setUnconnectedColor(); void setColorAux(const QBrush & brush, const QPen & pen, bool paint); void setColorAux(const QColor &color, bool paint=true); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void writeOtherElements(QXmlStreamWriter & writer); static class Wire * directlyWiredToAux(ConnectorItem * source, ConnectorItem * target, ViewGeometry::WireFlags flags, QList & visited); bool isEverVisible(); void setHiddenOrInactive(); bool isConnectedToPart(); void displayTooltip(ConnectorItem * over, ConnectorItem * other); void reposition(QPointF sceneDestPos, int draggingIndex); void repositionTarget(); void calcConnectorEnd(); QPen legPen() const; bool legMousePressEvent(QGraphicsSceneMouseEvent *event); void repoly(const QPolygonF & poly, bool relative); QPainterPath shapeAux(double width) const; ViewGeometry::WireFlags getSkipFlags(); enum CursorLocation { InNotFound = 0, InConnector, InBendpoint, InOrigin, InSegment }; CursorLocation findLocation(QPointF, int & bendpointIndex); void insertBendpoint(QPointF pos, int bendpointIndex); Bezier * insertBendpointAux(QPointF p, int bendpointIndex); void removeBendpoint(int bendpointIndex); void clearCurves(); void paintLeg(QPainter * painter); void paintLeg(QPainter * painter, bool hasCurves); void replaceBezier(int index, const Bezier * newBezier); void updateLegCursor(QPointF p, Qt::KeyboardModifiers modifiers); void updateWireCursor(Qt::KeyboardModifiers modifiers); bool curvyWiresIndicated(Qt::KeyboardModifiers); double findT(Bezier * bezier, double blen, double length); protected: QPointer m_connector; QList< QPointer > m_connectedTo; QPointF m_terminalPoint; QPointer m_overConnectorItem; bool m_connectorHovering; bool m_spaceBarWasPressed; bool m_hoverEnterSpaceBarWasPressed; bool m_hybrid; bool m_bigDot; bool m_rubberBandLeg; QPolygonF m_oldPolygon; bool m_draggingLeg; bool m_draggingCurve; int m_draggingLegIndex; bool m_activeStretch; QPointF m_holdPos; QPolygonF m_legPolygon; QVector m_legCurves; double m_legStrokeWidth; QColor m_legColor; bool m_insertBendpointPossible; QPointF m_connectorDetectEnd; QPointF m_connectorDrawEnd; double m_connectorDrawT; double m_connectorDetectT; bool m_groundFillSeed; int m_moveCount; protected: static QList m_equalPotentialDisplayItems; protected: static void collectPart(ConnectorItem * connectorItem, QList & partsConnectors, ViewLayer::ViewLayerPlacement); public: static void collectEqualPotential(QList & connectorItems, bool crossLayers, ViewGeometry::WireFlags skipFlags); static void collectParts(QList & connectorItems, QList & partsConnectors, bool includeSymbols, ViewLayer::ViewLayerPlacement); static void clearEqualPotentialDisplay(); static bool isGrounded(ConnectorItem * c1, ConnectorItem * c2); static void collectConnectorNames(QList & connectorItems, QStringList & connectorNames); static class Wire * directlyWiredTo(ConnectorItem * source, ConnectorItem * target, ViewGeometry::WireFlags flags); public: static const QList emptyConnectorItemList; }; Q_DECLARE_METATYPE(ConnectorItem*); #endif fritzing-app-0.9.2b/src/connectors/connectorshared.cpp000066400000000000000000000160451250202676700231440ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #include "connectorshared.h" #include "../debugdialog.h" #include "connector.h" #include "busshared.h" #include "ercdata.h" #include ConnectorShared::ConnectorShared() { m_id = ""; m_name = ""; m_typeString = ""; m_type = Connector::Unknown; m_description = ""; m_bus = NULL; m_ercData = NULL; } ConnectorShared::ConnectorShared( const QDomElement & domElement ) { m_ercData = NULL; m_id = domElement.attribute("id", ""); m_name = domElement.attribute("name", ""); m_replacedby = domElement.attribute("replacedby", ""); //DebugDialog::debug(QString("\tname:%1 id:%2").arg(m_name).arg(m_id)); m_typeString = domElement.attribute("type", ""); m_type = Connector::connectorTypeFromName(m_typeString); m_description = domElement.firstChildElement("description").text(); QDomElement erc = domElement.firstChildElement("erc"); if (!erc.isNull()) { m_ercData = new ErcData(erc); } loadPins(domElement); if (m_type == Connector::Unknown) { foreach (SvgIdLayer * svgIdLayer, m_pins.values()) { if (svgIdLayer->m_svgId.endsWith("pad")) { m_type = Connector::Pad; m_typeString = Connector::connectorNameFromType(m_type); break; } } } m_bus = NULL; } ConnectorShared::~ConnectorShared() { foreach (SvgIdLayer * svgIdLayer, m_pins.values()) { delete svgIdLayer; } m_pins.clear(); if (m_ercData) { delete m_ercData; } } const QString & ConnectorShared::id() const { return m_id; } void ConnectorShared::setId(QString id) { m_id = id; } const QString & ConnectorShared::description() { return m_description; } void ConnectorShared::setDescription(QString description) { m_description = description; } const QString & ConnectorShared::sharedName() { return m_name; } void ConnectorShared::setSharedName(QString name) { m_name = name; } Connector::ConnectorType ConnectorShared::connectorType() { return m_type; } const QString & ConnectorShared::connectorTypeString() { return m_typeString; } void ConnectorShared::setConnectorType(QString type) { m_typeString = type; m_type = Connector::connectorTypeFromName(type); } void ConnectorShared::setConnectorType(Connector::ConnectorType type) { m_typeString = Connector::connectorNameFromType(type); m_type = type; } const QString & ConnectorShared::replacedby() const { return m_replacedby; } void ConnectorShared::setReplacedby(QString replacedby) { m_replacedby = replacedby; } const QMultiHash & ConnectorShared::pins() { return m_pins; } void ConnectorShared::insertPin(ViewLayer::ViewID layer, SvgIdLayer * svgIdLayer) { m_pins.insert(layer, svgIdLayer); } void ConnectorShared::addPin(ViewLayer::ViewID viewID, const QString & svgId, ViewLayer::ViewLayerID viewLayerID, const QString & terminalId, const QString & legId, bool hybrid) { SvgIdLayer * svgIdLayer = new SvgIdLayer(viewID); svgIdLayer->m_svgViewLayerID = viewLayerID; svgIdLayer->m_svgId = svgId; svgIdLayer->m_terminalId = terminalId; svgIdLayer->m_hybrid = hybrid; svgIdLayer->m_legId = legId; m_pins.insert(viewID, svgIdLayer); // DebugDialog::debug(QString("insert a %1 %2 %3").arg(layer).arg(connectorId).arg(viewLayerID)); } void ConnectorShared::removePins(ViewLayer::ViewID layer) { m_pins.remove(layer); if (m_pins.values(layer).size() != 0) { throw "ConnectorShared::removePins"; } } void ConnectorShared::removePin(ViewLayer::ViewID layer, SvgIdLayer * svgIdLayer) { m_pins.remove(layer, svgIdLayer); } SvgIdLayer * ConnectorShared::fullPinInfo(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID) { QList svgLayers = m_pins.values(viewId); foreach ( SvgIdLayer * svgIdLayer, svgLayers) { if (svgIdLayer->m_svgViewLayerID == viewLayerID) { return svgIdLayer; } } return NULL; } const QString & ConnectorShared::legID(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID) { QList svgLayers = m_pins.values(viewId); foreach ( SvgIdLayer * svgIdLayer, svgLayers) { if (svgIdLayer->m_svgViewLayerID == viewLayerID) { return svgIdLayer->m_legId; } } return ___emptyString___; } void ConnectorShared::loadPins(const QDomElement & domElement) { //if(m_domElement == NULL) return; // TODO: this is view-related stuff and it would be nice if the model didn't know about it QDomElement viewsTag = domElement.firstChildElement("views"); loadPin(viewsTag.firstChildElement("breadboardView"),ViewLayer::BreadboardView); loadPin(viewsTag.firstChildElement("schematicView"),ViewLayer::SchematicView); loadPin(viewsTag.firstChildElement("pcbView"),ViewLayer::PCBView); } void ConnectorShared::loadPin(QDomElement elem, ViewLayer::ViewID viewID) { QDomElement pinElem = elem.firstChildElement("p"); while (!pinElem.isNull()) { //QString temp; //QTextStream stream(&temp); //pinElem.save(stream, 0); //stream.flush(); QString svgId = pinElem.attribute("svgId"); //svgId = svgId.left(svgId.lastIndexOf(QRegExp("\\d"))+1); QString layer = pinElem.attribute("layer"); SvgIdLayer * svgIdLayer = new SvgIdLayer(viewID); svgIdLayer->m_hybrid = (pinElem.attribute("hybrid").compare("yes") == 0); svgIdLayer->m_legId = pinElem.attribute("legId"); svgIdLayer->m_svgId = svgId; svgIdLayer->m_svgViewLayerID = ViewLayer::viewLayerIDFromXmlString(layer); //DebugDialog::debug(QString("svg id view layer id %1, %2").arg(svgIdLayer->m_viewLayerID).arg(layer)); svgIdLayer->m_terminalId = pinElem.attribute("terminalId"); //if (!svgIdLayer->m_terminalId.isEmpty()) { // DebugDialog::debug("terminalid " + svgIdLayer->m_terminalId); //} m_pins.insert(viewID, svgIdLayer); //DebugDialog::debug(QString("insert b %1 %2 %3").arg(viewId).arg(svgId).arg(layer)); pinElem = pinElem.nextSiblingElement("p"); } } void ConnectorShared::setBus(BusShared * bus) { m_bus = bus; } BusShared * ConnectorShared::bus() { return m_bus; } const QString & ConnectorShared::busID() { if (m_bus == NULL) return ___emptyString___; return m_bus->id(); } ErcData * ConnectorShared::ercData() { return m_ercData; } const QList ConnectorShared::svgIdLayers() const { return m_pins.values(); } fritzing-app-0.9.2b/src/connectors/connectorshared.h000066400000000000000000000056661250202676700226200ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef CONNECTORSHARED_H #define CONNECTORSHARED_H #include #include #include #include "../viewlayer.h" #include "connector.h" #include "svgidlayer.h" class ConnectorShared : public QObject { Q_OBJECT public: ConnectorShared(); ConnectorShared(const QDomElement & domElement); ~ConnectorShared(); const QString & id() const; void setId(QString id); const QString & description(); void setDescription(QString description); const QString & sharedName(); void setSharedName(QString name); const QString & connectorTypeString(); void setConnectorType(QString type); void setConnectorType(Connector::ConnectorType); Connector::ConnectorType connectorType(); const QString & replacedby() const; void setReplacedby(QString); const QString & legID(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID); const QMultiHash &pins(); SvgIdLayer * fullPinInfo(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID); const QList svgIdLayers() const; void addPin(ViewLayer::ViewID, const QString & svgId, ViewLayer::ViewLayerID, const QString & terminalId, const QString & legId, bool hybrid); void insertPin(ViewLayer::ViewID layer, SvgIdLayer * svgIdLayer); void removePins(ViewLayer::ViewID layer); void removePin(ViewLayer::ViewID layer, SvgIdLayer * svgIdLayer); class BusShared * bus(); void setBus(class BusShared *); const QString & busID(); class ErcData * ercData(); protected: void loadPins(const QDomElement & domElement); void loadPin(QDomElement elem, ViewLayer::ViewID viewId); QString m_description; QString m_id; QString m_name; QString m_typeString; QString m_replacedby; Connector::ConnectorType m_type; QString m_ercType; class ErcData * m_ercData; class BusShared * m_bus; QMultiHash m_pins; }; static QList ___emptyConnectorSharedList___; #endif fritzing-app-0.9.2b/src/connectors/ercdata.cpp000066400000000000000000000116621250202676700213660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "ercdata.h" ValidReal::ValidReal() { m_ok = false; } bool ValidReal::isValid() { return m_ok; } double ValidReal::value() { return m_value; } void ValidReal::setValue(double v) { m_value = v; m_ok = true; } bool ValidReal::setValue(const QString & v) { m_value = v.toDouble(&m_ok); return m_ok; } ////////////////////////////////////////////////////////// ErcData::ErcData(const QDomElement & ercElement) { m_eType = UnknownEType; m_currentFlow = UnknownFlow; m_ignore = Never; QString eType = ercElement.attribute("etype"); if (eType.compare("VCC", Qt::CaseInsensitive) == 0) { m_eType = VCC; } else if (eType.compare("ground", Qt::CaseInsensitive) == 0) { m_eType = Ground; } QString ig = ercElement.attribute("ignore"); if (ig.compare("ifUnconnected", Qt::CaseInsensitive) == 0) { m_ignore = IfUnconnected; } else if (ig.compare("always", Qt::CaseInsensitive) == 0) { m_ignore = Always; } QDomElement ercChild = ercElement.firstChildElement(); while (!ercChild.isNull()) { QString nodeName = ercChild.nodeName(); if (nodeName.compare("voltage", Qt::CaseInsensitive) == 0) { readVoltage(ercChild); } else if (nodeName.compare("current", Qt::CaseInsensitive) == 0) { readCurrent(ercChild); } ercChild = ercChild.nextSiblingElement(); } } void ErcData::readCurrent(QDomElement & currentElement) { m_currentMin.setValue(currentElement.attribute("valueMin")); m_currentMax.setValue(currentElement.attribute("valueMax")); m_current.setValue(currentElement.attribute("value")); QString flow = currentElement.attribute("flow"); if (flow.compare("source", Qt::CaseInsensitive) == 0) { m_currentFlow = Source; } else if (flow.compare("sink", Qt::CaseInsensitive) == 0) { m_currentFlow = Sink; } else { m_currentFlow = UnknownFlow; } } void ErcData::readVoltage(QDomElement & voltageElement) { m_voltageMin.setValue(voltageElement.attribute("valueMin")); m_voltageMax.setValue(voltageElement.attribute("valueMax")); m_voltage.setValue(voltageElement.attribute("value")); } bool ErcData::writeToElement(QDomElement & ercElement, QDomDocument & doc) { switch (m_eType) { case Ground: ercElement.setAttribute("etype", "ground"); writeCurrent(ercElement, doc); break; case VCC: ercElement.setAttribute("etype", "VCC"); writeCurrent(ercElement, doc); writeVoltage(ercElement, doc); break; default: return false; } return true; } void ErcData::writeCurrent(QDomElement & parent, QDomDocument & doc) { if (m_current.isValid() || m_currentMin.isValid() || m_currentMax.isValid() || m_currentFlow != UnknownFlow) { QDomElement currentElement = doc.createElement("current"); parent.appendChild(currentElement); if (m_current.isValid()) { currentElement.setAttribute("value", QString::number(m_current.value())); } if (m_currentMin.isValid()) { currentElement.setAttribute("valueMin", QString::number(m_currentMin.value())); } if (m_currentMax.isValid()) { currentElement.setAttribute("valueMax", QString::number(m_currentMax.value())); } switch (m_currentFlow) { case Source: currentElement.setAttribute("flow", "source"); break; case Sink: currentElement.setAttribute("flow", "sink"); break; default: break; } } } void ErcData::writeVoltage(QDomElement & parent, QDomDocument & doc) { if (m_voltage.isValid() || m_voltageMin.isValid() || m_voltageMax.isValid()) { QDomElement voltageElement = doc.createElement("voltage"); parent.appendChild(voltageElement); if (m_voltage.isValid()) { voltageElement.setAttribute("value", QString::number(m_voltage.value())); } if (m_voltageMin.isValid()) { voltageElement.setAttribute("valueMin", QString::number(m_voltageMin.value())); } if (m_voltageMax.isValid()) { voltageElement.setAttribute("valueMax", QString::number(m_voltageMax.value())); } } } ErcData::EType ErcData::eType() { return m_eType; } ErcData::Ignore ErcData::ignore() { return m_ignore; } fritzing-app-0.9.2b/src/connectors/ercdata.h000066400000000000000000000040451250202676700210300ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ERCDATA_H #define ERCDATA_H #include #include #include #include class ValidReal { public: ValidReal(); bool isValid(); double value(); void setValue(double); bool setValue(const QString &); protected: bool m_ok; double m_value; }; class ErcData { public: enum EType { Ground, VCC, UnknownEType }; enum CurrentFlow { Source, Sink, UnknownFlow }; enum Ignore { Never, Always, IfUnconnected }; public: ErcData(const QDomElement & ercElement); bool writeToElement(QDomElement & ercElement, QDomDocument & doc); EType eType(); Ignore ignore(); protected: void readVoltage(QDomElement &); void readCurrent(QDomElement &); void writeVoltage(QDomElement &, QDomDocument &); void writeCurrent(QDomElement &, QDomDocument &); protected: EType m_eType; Ignore m_ignore; ValidReal m_voltage; ValidReal m_voltageMin; ValidReal m_voltageMax; ValidReal m_current; ValidReal m_currentMin; ValidReal m_currentMax; CurrentFlow m_currentFlow; }; #endif fritzing-app-0.9.2b/src/connectors/nonconnectoritem.cpp000066400000000000000000000137251250202676700233510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "nonconnectoritem.h" #include #include #include #include #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../utils/graphicsutils.h" #include "../model/modelpart.h" //static const double EffectiveAdjustment = 1.25; static const double EffectiveAdjustmentFactor = 5.0 / 15.0; ///////////////////////////////////////////////////////// NonConnectorItem::NonConnectorItem(ItemBase * attachedTo) : QGraphicsRectItem(attachedTo) { m_effectively = EffectivelyUnknown; m_radius = m_strokeWidth = 0; m_layerHidden = m_isPath = m_inactive = m_hidden = false; m_attachedTo = attachedTo; setAcceptHoverEvents(false); setAcceptedMouseButtons(Qt::NoButton); setFlag(QGraphicsItem::ItemIsMovable, false); setFlag(QGraphicsItem::ItemIsSelectable, false); setFlag(QGraphicsItem::ItemIsFocusable, false); } NonConnectorItem::~NonConnectorItem() { } ItemBase * NonConnectorItem::attachedTo() { return m_attachedTo; } bool NonConnectorItem::doNotPaint() { return (m_hidden || m_inactive || !m_paint || m_layerHidden); } void NonConnectorItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { if (doNotPaint()) return; painter->setOpacity(m_opacity); /* DebugDialog::debug(QString("id:%1 %2 w:%3 %4 c:%5 ec:%6 er:%7 neg:%8 w:%9") .arg(attachedToID()) .arg(attachedToTitle()) .arg(pen().width()) .arg(pen().color().name()) .arg(m_circular) .arg(m_effectivelyCircular) .arg(m_effectivelyRectangular) .arg(m_negativePenWidth) .arg(rect().width()) ); */ if (m_circular) { painter->setBrush(brush()); if (m_negativePenWidth < 0) { // for wires painter->setPen(Qt::NoPen); if (!m_negativeOffsetRect) { painter->drawEllipse(rect().center(), m_negativePenWidth, m_negativePenWidth); } else { int pw = m_negativePenWidth + 1; painter->drawEllipse(rect().adjusted(-pw, -pw, pw, pw)); } } else { // for parts QRectF r = rect(); if (r.width() > 0 && r.height() > 0) { double delta = .66 * m_strokeWidth; painter->setPen(pen()); painter->drawEllipse(r.adjusted(delta, delta, -delta, -delta)); } } } else if (!m_shape.isEmpty()) { painter->setBrush(brush()); painter->setPen(pen()); painter->drawPath(m_shape); } else if (m_effectively == EffectivelyCircular) { QRectF r = rect(); if (r.width() > 0 && r.height() > 0) { painter->setBrush(brush()); painter->setPen(pen()); double delta = r.width() * EffectiveAdjustmentFactor; painter->drawEllipse(r.adjusted(delta, delta, -delta, -delta)); } } else if (m_effectively == EffectivelyRectangular) { QRectF r = rect(); if (r.width() > 0 && r.height() > 0) { painter->setBrush(brush()); painter->setPen(pen()); double delta = qMin(r.width(), r.height()) * EffectiveAdjustmentFactor; painter->drawRect(r.adjusted(delta, delta, -delta, -delta)); } } else { QGraphicsRectItem::paint(painter, option, widget); } } void NonConnectorItem::setHidden(bool hide) { m_hidden = hide; this->update(); } bool NonConnectorItem::hidden() { return m_hidden; } void NonConnectorItem::setLayerHidden(bool hide) { m_layerHidden = hide; this->update(); } bool NonConnectorItem::layerHidden() { return m_layerHidden; } void NonConnectorItem::setInactive(bool inactivate) { m_inactive = inactivate; this->update(); } bool NonConnectorItem::inactive() { return m_inactive; } long NonConnectorItem::attachedToID() { if (attachedTo() == NULL) return -1; return attachedTo()->id(); } const QString & NonConnectorItem::attachedToTitle() { if (attachedTo() == NULL) return ___emptyString___; return attachedTo()->title(); } const QString & NonConnectorItem::attachedToInstanceTitle() { if (attachedTo() == NULL) return ___emptyString___; return attachedTo()->instanceTitle(); } void NonConnectorItem::setCircular(bool circular) { m_circular = circular; } void NonConnectorItem::setRadius(double radius, double strokeWidth) { m_radius = radius; m_strokeWidth = strokeWidth; m_circular = (m_radius > 0); } void NonConnectorItem::setIsPath(bool path) { m_isPath = path; } bool NonConnectorItem::isPath() { return m_isPath; } double NonConnectorItem::radius() { return m_radius; } double NonConnectorItem::strokeWidth() { return m_strokeWidth; } QPainterPath NonConnectorItem::shape() const { if (m_circular || m_effectively == EffectivelyCircular) { QPainterPath path; path.addEllipse(rect()); return GraphicsUtils::shapeFromPath(path, pen(), pen().widthF(), true); } else if (!m_shape.isEmpty()) { return m_shape; } return QGraphicsRectItem::shape(); } void NonConnectorItem::setShape(QPainterPath & pp) { // so far only used by GroundPlane m_shape = GraphicsUtils::shapeFromPath(pp, pen(), pen().widthF(), true); } int NonConnectorItem::attachedToItemType() { if (m_attachedTo == NULL) return ModelPart::Unknown; return m_attachedTo->itemType(); } fritzing-app-0.9.2b/src/connectors/nonconnectoritem.h000066400000000000000000000050171250202676700230110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef NONCONNECTORITEM_H #define NONCONNECTORITEM_H #include #include #include #include #include #include #include "../items/itembase.h" class NonConnectorItem : public QObject, public QGraphicsRectItem { Q_OBJECT public: NonConnectorItem(ItemBase* attachedTo); ~NonConnectorItem(); ItemBase * attachedTo(); virtual void setHidden(bool hidden); bool hidden(); virtual void setInactive(bool inactivate); bool inactive(); virtual void setLayerHidden(bool hidden); bool layerHidden(); long attachedToID(); const QString & attachedToTitle(); const QString & attachedToInstanceTitle(); void setCircular(bool); void setRadius(double radius, double strokeWidth); double radius(); double strokeWidth(); void setShape(QPainterPath &); void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); QPainterPath shape() const; void setIsPath(bool); bool isPath(); int attachedToItemType(); protected: bool doNotPaint(); enum Effectively { EffectivelyCircular = 1, EffectivelyRectangular, EffectivelyPolygonal, EffectivelyUnknown }; protected: QPointer m_attachedTo; bool m_hidden; bool m_layerHidden; bool m_inactive; bool m_paint; double m_opacity; bool m_circular; Effectively m_effectively; double m_radius; double m_strokeWidth; double m_negativePenWidth; bool m_negativeOffsetRect; QPainterPath m_shape; bool m_isPath; }; #endif fritzing-app-0.9.2b/src/connectors/svgidlayer.cpp000066400000000000000000000061441250202676700221330ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "svgidlayer.h" SvgIdLayer::SvgIdLayer(ViewLayer::ViewID viewID) { m_viewID = viewID; m_pointRectBottom.processed = m_pointRectTop.processed = m_path = m_hybrid = false; m_radius = m_strokeWidth = 0; } SvgIdLayer * SvgIdLayer::copyLayer() { SvgIdLayer * toSvgIdLayer = new SvgIdLayer(m_viewID); *toSvgIdLayer = *this; return toSvgIdLayer; } QPointF SvgIdLayer::point(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewBottom) return m_pointRectBottom.point; return m_pointRectTop.point; } QRectF SvgIdLayer::rect(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewBottom) return m_pointRectBottom.rect; return m_pointRectTop.rect; } bool SvgIdLayer::processed(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewBottom) return m_pointRectBottom.processed; return m_pointRectTop.processed; } bool SvgIdLayer::svgVisible(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewBottom) return m_pointRectBottom.svgVisible; return m_pointRectTop.svgVisible; } void SvgIdLayer::unprocess() { m_pointRectTop.processed = m_pointRectBottom.processed = false; } void SvgIdLayer::setInvisible(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewBottom) { m_pointRectBottom.svgVisible = false; m_pointRectBottom.processed = true; return; } m_pointRectTop.svgVisible = false; m_pointRectTop.processed = true; } void SvgIdLayer::setPointRect(ViewLayer::ViewLayerPlacement viewLayerPlacement, QPointF point, QRectF rect, bool svgVisible) { if (viewLayerPlacement == ViewLayer::NewBottom) { m_pointRectBottom.svgVisible = svgVisible; m_pointRectBottom.processed = true; m_pointRectBottom.point = point; m_pointRectBottom.rect = rect; return; } m_pointRectTop.svgVisible = svgVisible; m_pointRectTop.processed = true; m_pointRectTop.point = point; m_pointRectTop.rect = rect; } fritzing-app-0.9.2b/src/connectors/svgidlayer.h000066400000000000000000000040121250202676700215700ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef SVGIDLAYER_H #define SVGIDLAYER_H #include #include "../viewlayer.h" struct PointRect { QRectF rect; QPointF point; bool processed; bool svgVisible; }; class SvgIdLayer { public: SvgIdLayer(ViewLayer::ViewID); SvgIdLayer * copyLayer(); QPointF point(ViewLayer::ViewLayerPlacement); QRectF rect(ViewLayer::ViewLayerPlacement); bool processed(ViewLayer::ViewLayerPlacement); bool svgVisible(ViewLayer::ViewLayerPlacement); void unprocess(); void setInvisible(ViewLayer::ViewLayerPlacement); void setPointRect(ViewLayer::ViewLayerPlacement, QPointF, QRectF, bool svgVisible); public: QString m_svgId; QString m_terminalId; ViewLayer::ViewID m_viewID; ViewLayer::ViewLayerID m_svgViewLayerID; bool m_hybrid; double m_radius; double m_strokeWidth; QString m_legId; QString m_legColor; double m_legStrokeWidth; QLineF m_legLine; bool m_path; protected: PointRect m_pointRectBottom; PointRect m_pointRectTop; protected: }; #endif fritzing-app-0.9.2b/src/debugdialog.cpp000066400000000000000000000130201250202676700200420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "debugdialog.h" #include "utils/folderutils.h" #include #include #include #include #include #include #include DebugDialog* DebugDialog::singleton = NULL; QFile DebugDialog::m_file; #ifdef QT_NO_DEBUG bool DebugDialog::m_enabled = false; #else bool DebugDialog::m_enabled = true; #endif QEvent::Type DebugEventType = (QEvent::Type) (QEvent::User + 1); class DebugEvent : public QEvent { public: QString m_message; QObject * m_ancestor; DebugDialog::DebugLevel m_debugLevel; DebugEvent(QString message, DebugDialog::DebugLevel debugLevel, QObject * ancestor) : QEvent(DebugEventType) { this->m_message = message; this->m_ancestor = ancestor; this->m_debugLevel = debugLevel; } }; DebugDialog::DebugDialog(QWidget *parent) : QDialog(parent) { // Let's set the icon this->setWindowIcon(QIcon(QPixmap(":resources/images/fritzing_icon.png"))); singleton = this; m_debugLevel = DebugDialog::Debug; setWindowTitle(tr("for debugging")); resize(400, 300); m_textEdit = new QTextEdit(this); m_textEdit->setGeometry(QRect(10, 10, 381, 281)); QString path = FolderUtils::getUserDataStorePath(""); path += "/debug.txt"; m_file.setFileName(path); m_file.remove(); } DebugDialog::~DebugDialog() { if (m_textEdit) { delete m_textEdit; } } bool DebugDialog::event(QEvent *e) { if (e->type() == DebugEventType) { this->m_textEdit->append(((DebugEvent *) e)->m_message); emit debugBroadcast(((DebugEvent *) e)->m_message, ((DebugEvent *) e)->m_debugLevel,((DebugEvent *) e)->m_ancestor); // need to delete these events at some point... // but it's tricky if the message is being used elsewhere return true; } else { return QDialog::event(e); } } void DebugDialog::resizeEvent(QResizeEvent *e) { int w = this->width(); int h = this->height(); QRect geom = this->m_textEdit->geometry(); geom.setWidth(w - geom.left() - geom.left()); geom.setHeight( h - geom.top() - geom.top()); this->m_textEdit->setGeometry(geom); return QDialog::resizeEvent(e); } void DebugDialog::debug(QString prefix, const QPointF &point, DebugLevel debug, QObject *ancestor) { QString msg = prefix+QString(" point: x=%1 y=%2").arg(point.x()).arg(point.y()); DebugDialog::debug(msg,debug,ancestor); } void DebugDialog::debug(QString prefix, const QRectF &rect, DebugLevel debug, QObject *ancestor) { QString msg = prefix+QString(" rect: x=%1 y=%2 w=%3 h=%4") .arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()); DebugDialog::debug(msg,debug,ancestor); } void DebugDialog::debug(QString prefix, const QPoint &point, DebugLevel debug, QObject *ancestor) { QString msg = prefix+QString(" point: x=%1 y=%2").arg(point.x()).arg(point.y()); DebugDialog::debug(msg,debug,ancestor); } void DebugDialog::debug(QString prefix, const QRect &rect, DebugLevel debug, QObject *ancestor) { QString msg = prefix+QString(" rect: x=%1 y=%2 w=%3 h=%4") .arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()); DebugDialog::debug(msg,debug,ancestor); } void DebugDialog::debug(QString message, DebugLevel debugLevel, QObject * ancestor) { if (!m_enabled) return; if (singleton == NULL) { new DebugDialog(); //singleton->show(); } if (debugLevel < singleton->m_debugLevel) { return; } qDebug() << message; if (m_file.open(QIODevice::Append | QIODevice::Text)) { QTextStream out(&m_file); out.setCodec("UTF-8"); out << message << "\n"; m_file.close(); } DebugEvent* de = new DebugEvent(message, debugLevel, ancestor); QCoreApplication::postEvent(singleton, de); } void DebugDialog::hideDebug() { if (singleton != NULL) { singleton->hide(); } } void DebugDialog::showDebug() { if (singleton == NULL) { new DebugDialog(); } singleton->show(); } void DebugDialog::closeDebug() { if (singleton != NULL) { singleton->close(); } } bool DebugDialog::visible() { if (singleton == NULL) return false; return singleton->isVisible(); } bool DebugDialog::connectToBroadcast(QObject * receiver, const char* slot) { if (singleton == NULL) { new DebugDialog(); } return connect(singleton, SIGNAL(debugBroadcast(const QString &, QObject *)), receiver, slot ); } void DebugDialog::setDebugLevel(DebugLevel debugLevel) { if (singleton == NULL) { new DebugDialog(); } singleton->m_debugLevel = debugLevel; } void DebugDialog::cleanup() { if (singleton) { delete singleton; singleton = NULL; } } bool DebugDialog::enabled() { return m_enabled; } void DebugDialog::setEnabled(bool enabled) { m_enabled = enabled; } fritzing-app-0.9.2b/src/debugdialog.h000066400000000000000000000046421250202676700175210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef DEBUGDIALOG_H #define DEBUGDIALOG_H #include #include #include #include #include #include "utils/misc.h" class DebugDialog : public QDialog { Q_OBJECT private: DebugDialog(QWidget *parent = 0); ~DebugDialog(); public: enum DebugLevel { Debug, Info, Warning, Error }; public: static void debug(QString, const QPointF &point, DebugLevel = Debug, QObject * ancestor = 0); static void debug(QString, const QRectF &rect, DebugLevel = Debug, QObject * ancestor = 0); static void debug(QString, const QPoint &point, DebugLevel = Debug, QObject * ancestor = 0); static void debug(QString, const QRect &rect, DebugLevel = Debug, QObject * ancestor = 0); static void debug(QString, DebugLevel = Debug, QObject * ancestor = 0); static void hideDebug(); static void showDebug(); static void closeDebug(); static bool visible(); static bool connectToBroadcast(QObject * receiver, const char* slot); static void setDebugLevel(DebugLevel); static void cleanup(); static void setEnabled(bool); static bool enabled(); protected: bool event ( QEvent * e ); void resizeEvent ( QResizeEvent * event ); protected: static DebugDialog* singleton; static QFile m_file; static bool m_enabled; QPointer m_textEdit; DebugLevel m_debugLevel; signals: void debugBroadcast(const QString & message, DebugLevel, QObject * ancestor); }; #endif fritzing-app-0.9.2b/src/dialogs/000077500000000000000000000000001250202676700165165ustar00rootroot00000000000000fritzing-app-0.9.2b/src/dialogs/groundfillseeddialog.cpp000066400000000000000000000135601250202676700234150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "groundfillseeddialog.h" #include "../debugdialog.h" #include "../connectors/connectoritem.h" #include "../sketch/pcbsketchwidget.h" #include #include #include ///////////////////////////////////////////////////////// GroundFillSeedDialog::GroundFillSeedDialog(PCBSketchWidget * sketchWidget, QList & connectorItems, const QString & intro, QWidget *parent) : QDialog(parent) { m_sketchWidget = sketchWidget; m_connectorItems = connectorItems; m_activeConnectorItem = NULL; m_doFill = false; this->setWindowTitle(QObject::tr("Ground Fill Seed Editor")); QVBoxLayout * vLayout = new QVBoxLayout(this); if (!intro.isEmpty()) { QLabel * label = new QLabel(intro); label->setWordWrap(true); vLayout->addWidget(label); } QLabel * label = new QLabel(tr("The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, " "the flooded area includes traces and connectors that are connected to 'ground' connectors. " "Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. " "It also may be that there are multiple nets with a ground connector, " "and you might only want one of the nets to be filled.\n\n" "This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds.\n\n" "Click an item to highlight its connections in the sketch.\n\n" "It is also possible to choose a connector as a ground fill seed by right-clicking a connector and " "choosing the 'Set Ground Fill Seed' context menu option.")); label->setWordWrap(true); vLayout->addWidget(label); m_listWidget = new QListWidget(this); int ix = 0; foreach (ConnectorItem * connectorItem, connectorItems) { QListWidgetItem *item = new QListWidgetItem; item->setData(Qt::DisplayRole, connectorItem->connectorSharedName()); item->setData(Qt::CheckStateRole, connectorItem->isGroundFillSeed() ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, ix++); connectorItem->updateTooltip(); item->setToolTip(connectorItem->toolTip()); m_listWidget->addItem(item); } connect(m_listWidget, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(clickedSlot(QListWidgetItem *))); connect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(changedSlot(QListWidgetItem *))); vLayout->addWidget(m_listWidget); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Yes | QDialogButtonBox::Cancel); QPushButton * cancelButton = buttonBox->button(QDialogButtonBox::Cancel); cancelButton->setText(tr("Cancel")); cancelButton->setDefault(false); QPushButton * okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setText(tr("OK")); okButton->setDefault(true); m_doFillButton = buttonBox->button(QDialogButtonBox::Yes); m_doFillButton->setDefault(false); connect(m_doFillButton, SIGNAL(clicked(bool)), this, SLOT(doFill(bool))); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); changedSlot(NULL); } GroundFillSeedDialog::~GroundFillSeedDialog() { } void GroundFillSeedDialog::changedSlot(QListWidgetItem *) { bool checked = false; for (int i = 0; i < m_listWidget->count(); i++) { if (m_listWidget->item(i)->checkState() == Qt::Checked) { checked = true; break; } } m_doFillButton->setText(checked ? tr("OK and ground fill") : tr("OK and copper fill")); } void GroundFillSeedDialog::clickedSlot(QListWidgetItem * item) { int ix = -1; if (item != NULL) { ix = item->data(Qt::UserRole).toInt(); } showEqualPotential(m_activeConnectorItem, false); m_activeConnectorItem = (ix >= 0 && ix < m_connectorItems.count()) ? m_connectorItems.at(ix) : NULL; showEqualPotential(m_activeConnectorItem, true); } void GroundFillSeedDialog::showEqualPotential(ConnectorItem * connectorItem, bool show) { if (connectorItem) { QList connectorItems; connectorItems.append(connectorItem); ConnectorItem::collectEqualPotential(connectorItems, true, ViewGeometry::NoFlag); QList visited; foreach (ConnectorItem * ci, connectorItems) { ci->showEqualPotential(show, visited); } } } void GroundFillSeedDialog::accept() { showEqualPotential(m_activeConnectorItem, false); QDialog::accept(); } void GroundFillSeedDialog::reject() { showEqualPotential(m_activeConnectorItem, false); QDialog::reject(); } void GroundFillSeedDialog::getResults(QList & results) { for (int i = 0; i < m_listWidget->count(); i++) { results.append(m_listWidget->item(i)->checkState() == Qt::Checked); } } bool GroundFillSeedDialog::getFill() { return m_doFill; } void GroundFillSeedDialog::doFill(bool) { m_doFill = true; accept(); } fritzing-app-0.9.2b/src/dialogs/groundfillseeddialog.h000066400000000000000000000036111250202676700230560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef GROUNDFILLSEEDDIALOG_H #define GROUNDFILLSEEDDIALOG_H #include #include #include #include #include class GroundFillSeedDialog : public QDialog { Q_OBJECT public: GroundFillSeedDialog(class PCBSketchWidget *, QList &, const QString & intro, QWidget *parent = 0); ~GroundFillSeedDialog(); void getResults(QList & results); bool getFill(); public slots: void clickedSlot(QListWidgetItem *); void changedSlot(QListWidgetItem *); void accept(); void reject(); void doFill(bool); protected: void showEqualPotential(ConnectorItem * connectorItem, bool show); protected: PCBSketchWidget * m_sketchWidget; QList m_connectorItems; QListWidget * m_listWidget; ConnectorItem * m_activeConnectorItem; bool m_doFill; QPushButton * m_doFillButton; }; #endif fritzing-app-0.9.2b/src/dialogs/pinlabeldialog.cpp000066400000000000000000000213401250202676700221700ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "pinlabeldialog.h" #include "../debugdialog.h" #include #include #include #include #include #include #include // TODO: // // would be nice to update schematic view with new pin labels // // reasons for not doing save: // undo would require a lot of work to implement and would require saving the old dom document // every instance of the part in all open documents would have to be updated PinLabelUndoCommand::PinLabelUndoCommand(PinLabelDialog * pinLabelDialog, int index, QLineEdit * lineEdit, const QString & previous, const QString & next) : QUndoCommand() { m_pinLabelDialog = pinLabelDialog; m_previous = previous; m_next = next; m_index = index; m_lineEdit = lineEdit; } void PinLabelUndoCommand::undo() { m_pinLabelDialog->setLabelText(m_index, m_lineEdit, m_previous); } void PinLabelUndoCommand::redo() { m_pinLabelDialog->setLabelText(m_index, m_lineEdit, m_next); } ///////////////////////////////////////////////////////// PinLabelDialog::PinLabelDialog(const QStringList & labels, bool singleRow, const QString & chipLabel, bool isCore, QWidget *parent) : QDialog(parent) { m_isCore = isCore; m_labels = labels; m_doSaveAs = true; this->setWindowTitle(QObject::tr("Pin Label Editor")); QVBoxLayout * vLayout = new QVBoxLayout(this); QScrollArea * scrollArea = new QScrollArea(this); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QFrame * frame = new QFrame(this); QHBoxLayout * hLayout = new QHBoxLayout(frame); QFrame * labelsFrame = initLabels(labels, singleRow, chipLabel); QFrame * textFrame = new QFrame(); QVBoxLayout * textLayout = new QVBoxLayout(frame); QLabel * label = new QLabel("" + tr("

Pin Label Editor

") + tr("

Click on a label next to a pin number to rename that pin.") + " " + tr("You can use the tab key to move through the labels in order.

") + ""); label->setMaximumWidth(150); label->setWordWrap(true); textLayout->addWidget(label); textLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); textFrame->setLayout(textLayout); hLayout->addWidget(labelsFrame); hLayout->addSpacing(15); hLayout->addWidget(textFrame); frame->setLayout(hLayout); scrollArea->setWidget(frame); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel); QPushButton * cancelButton = buttonBox->button(QDialogButtonBox::Cancel); cancelButton->setText(tr("Cancel")); cancelButton->setDefault(false); m_saveAsButton = buttonBox->button(QDialogButtonBox::Save); m_saveAsButton->setText(tr("Save")); m_saveAsButton->setEnabled(false); m_saveAsButton->setDefault(false); m_undoButton = new QPushButton(tr("Undo")); m_undoButton->setEnabled(false); m_undoButton->setDefault(false); m_redoButton = new QPushButton(tr("Redo")); m_redoButton->setEnabled(false); m_redoButton->setDefault(false); buttonBox->addButton(m_undoButton, QDialogButtonBox::ResetRole); buttonBox->addButton(m_redoButton, QDialogButtonBox::ResetRole); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(scrollArea); vLayout->addWidget(buttonBox); this->setLayout(vLayout); connect(buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); connect(&m_undoStack, SIGNAL(canRedoChanged(bool)), this, SLOT(undoChanged(bool))); connect(&m_undoStack, SIGNAL(canUndoChanged(bool)), this, SLOT(undoChanged(bool))); connect(&m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoChanged(bool))); } PinLabelDialog::~PinLabelDialog() { } QFrame * PinLabelDialog::initLabels(const QStringList & labels, bool singleRow, const QString & chipLabel) { QFrame * frame = new QFrame(); QVBoxLayout * vLayout = new QVBoxLayout(); QLabel * label = new QLabel("

" + chipLabel + "

"); label->setAlignment(Qt::AlignCenter); QFrame * subFrame = new QFrame(); if (singleRow) { QGridLayout * gridLayout = new QGridLayout(); gridLayout->setMargin(0); gridLayout->setSpacing(3); for (int i = 0; i < labels.count(); i++) { makeOnePinEntry(i, labels.at(i), Qt::AlignLeft, i, gridLayout); } subFrame->setLayout(gridLayout); } else { QHBoxLayout * hLayout = new QHBoxLayout(); QFrame * lFrame = new QFrame(); QGridLayout * lLayout = new QGridLayout; lLayout->setMargin(0); lLayout->setSpacing(3); for (int i = 0; i < labels.count() / 2; i++) { makeOnePinEntry(i, labels.at(i), Qt::AlignLeft, i, lLayout); } lFrame->setLayout(lLayout); QFrame * rFrame = new QFrame(); QGridLayout * rLayout = new QGridLayout; rLayout->setMargin(0); rLayout->setSpacing(3); int row = labels.count() - 1; for (int i = labels.count() / 2; i < labels.count(); i++) { makeOnePinEntry(i, labels.at(i), Qt::AlignRight, row--, rLayout); } rFrame->setLayout(rLayout); hLayout->addWidget(lFrame); hLayout->addSpacing(15); hLayout->addWidget(rFrame); subFrame->setLayout(hLayout); } vLayout->addWidget(label); vLayout->addWidget(subFrame); frame->setLayout(vLayout); return frame; } void PinLabelDialog::makeOnePinEntry(int index, const QString & text, Qt::Alignment alignment, int row, QGridLayout * gridLayout) { QLineEdit * label = new QLineEdit(); label->setText(QString::number(index + 1)); label->setMaximumWidth(20); label->setMinimumWidth(20); label->setFrame(false); label->setEnabled(false); QLineEdit * lEdit = new QLineEdit(); lEdit->setMaximumWidth(65); lEdit->setAlignment(alignment); lEdit->setText(text); lEdit->setProperty("index", index); lEdit->setProperty("prev", text); connect(lEdit, SIGNAL(editingFinished()), this, SLOT(labelChanged())); connect(lEdit, SIGNAL(textEdited(const QString &)), this, SLOT(labelEdited(const QString &))); if (alignment == Qt::AlignLeft) { label->setAlignment(Qt::AlignRight); gridLayout->addWidget(label, row, 0); gridLayout->addWidget(lEdit, row, 1); } else { label->setAlignment(Qt::AlignLeft); gridLayout->addWidget(lEdit, row, 0); gridLayout->addWidget(label, row, 1); } } void PinLabelDialog::labelChanged() { QLineEdit * lineEdit = qobject_cast(sender()); if (lineEdit == NULL) return; bool ok; int index = lineEdit->property("index").toInt(&ok); if (!ok) return; if (index < 0) return; if (index >= m_labels.count()) return; PinLabelUndoCommand * pluc = new PinLabelUndoCommand(this, index, lineEdit, lineEdit->property("prev").toString(), lineEdit->text()); lineEdit->setProperty("prev", lineEdit->text()); m_undoStack.push(pluc); } void PinLabelDialog::labelEdited(const QString &) { m_saveAsButton->setEnabled(true); } const QStringList & PinLabelDialog::labels() { return m_labels; } void PinLabelDialog::setLabelText(int index, QLineEdit * lineEdit, const QString & text) { m_labels.replace(index, text); lineEdit->setText(text); lineEdit->setProperty("prev", text); } void PinLabelDialog::buttonClicked(QAbstractButton * button) { if (button == m_undoButton) { m_undoStack.undo(); } else if (button == m_redoButton) { m_undoStack.redo(); } } bool PinLabelDialog::doSaveAs() { return m_doSaveAs; } void PinLabelDialog::undoChanged(bool) { bool redo = false; bool undo = false; bool saveAs = false; if (m_undoStack.canUndo()) { saveAs = undo = true; } if (m_undoStack.canRedo()) { redo = true; } m_saveAsButton->setEnabled(saveAs); m_undoButton->setEnabled(undo); m_redoButton->setEnabled(redo); } void PinLabelDialog::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: return; default: QDialog::keyPressEvent(e); } } fritzing-app-0.9.2b/src/dialogs/pinlabeldialog.h000066400000000000000000000047231250202676700216430ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef PINLABELDIALOG_H #define PINLABELDIALOG_H #include #include #include #include #include #include #include #include #include class PinLabelDialog : public QDialog { Q_OBJECT public: PinLabelDialog(const QStringList & labels, bool singleRow, const QString & chipLabel, bool isCore, QWidget *parent = 0); ~PinLabelDialog(); const QStringList & labels(); void setLabelText(int index, QLineEdit *, const QString & text); bool doSaveAs(); protected slots: void labelChanged(); void buttonClicked(QAbstractButton *); void undoChanged(bool); void labelEdited(const QString &) ; protected: QFrame * initLabels(const QStringList & labels, bool singleRow, const QString & chipLabel); void makeOnePinEntry(int index, const QString & label, Qt::Alignment alignment, int row, QGridLayout *); void keyPressEvent(QKeyEvent *e); protected: bool m_isCore; QStringList m_labels; QUndoStack m_undoStack; QPushButton * m_saveAsButton; QPushButton * m_undoButton; QPushButton * m_redoButton; bool m_doSaveAs; }; class PinLabelUndoCommand : public QUndoCommand { public: PinLabelUndoCommand(PinLabelDialog *, int index, QLineEdit *, const QString & previous, const QString & next); void undo(); void redo(); protected: QString m_previous; QString m_next; PinLabelDialog * m_pinLabelDialog; int m_index; QLineEdit * m_lineEdit; }; #endif fritzing-app-0.9.2b/src/dialogs/prefsdialog.cpp000066400000000000000000000423771250202676700215360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6972 $: $Author: irascibl@gmail.com $: $Date: 2013-04-18 07:18:04 +0200 (Do, 18. Apr 2013) $ ********************************************************************/ #include "prefsdialog.h" #include "../debugdialog.h" #include "translatorlistmodel.h" #include "../items/itembase.h" #include "../utils/clickablelabel.h" #include "setcolordialog.h" #include "../sketch/zoomablegraphicsview.h" #include "../mainwindow/mainwindow.h" #include "../utils/folderutils.h" #include #include #include #include #include #include #include #include #include #include #include #define MARGIN 5 #define FORMLABELWIDTH 195 #define SPACING 15 PrefsDialog::PrefsDialog(const QString & language, QWidget *parent) : QDialog(parent) { this->setWindowTitle(QObject::tr("Preferences")); m_name = language; m_cleared = false; m_wheelMapping = (int) ZoomableGraphicsView::wheelMapping(); } PrefsDialog::~PrefsDialog() { } void PrefsDialog::initViewInfo(int index, const QString & viewName, const QString & shortName, bool curvy) { m_viewInfoThings[index].index = index; m_viewInfoThings[index].viewName = viewName; m_viewInfoThings[index].shortName = shortName; m_viewInfoThings[index].curvy = curvy; } void PrefsDialog::initLayout(QFileInfoList & languages, QList platforms) { m_tabWidget = new QTabWidget(); m_general = new QWidget(); m_breadboard = new QWidget(); m_schematic = new QWidget(); m_pcb = new QWidget(); m_code = new QWidget(); m_tabWidget->setObjectName("preDia_tabs"); m_tabWidget->addTab(m_general, tr("General")); m_tabWidget->addTab(m_breadboard, m_viewInfoThings[0].viewName); m_tabWidget->addTab(m_schematic, m_viewInfoThings[1].viewName); m_tabWidget->addTab(m_pcb, m_viewInfoThings[2].viewName); m_tabWidget->addTab(m_code, tr("Code View")); QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(m_tabWidget); initGeneral(m_general, languages); initBreadboard(m_breadboard, &m_viewInfoThings[0]); initSchematic(m_schematic, &m_viewInfoThings[1]); initPCB(m_pcb, &m_viewInfoThings[2]); initCode(m_code, platforms); m_platforms = platforms; QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } void PrefsDialog::initGeneral(QWidget * widget, QFileInfoList & languages) { QVBoxLayout * vLayout = new QVBoxLayout(); // TODO: if no translation files found, don't put up the translation part of this dialog vLayout->addWidget(createLanguageForm(languages)); vLayout->addWidget(createColorForm()); vLayout->addWidget(createZoomerForm()); vLayout->addWidget(createAutosaveForm()); vLayout->addWidget(createOtherForm()); widget->setLayout(vLayout); } void PrefsDialog::initBreadboard(QWidget * widget, ViewInfoThing * viewInfoThing) { QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(createCurvyForm(viewInfoThing)); vLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Preferred, QSizePolicy::Expanding)); widget->setLayout(vLayout); } void PrefsDialog::initSchematic(QWidget * widget, ViewInfoThing * viewInfoThing) { QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(createCurvyForm(viewInfoThing)); vLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Preferred, QSizePolicy::Expanding)); widget->setLayout(vLayout); } void PrefsDialog::initPCB(QWidget * widget, ViewInfoThing * viewInfoThing) { QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(createCurvyForm(viewInfoThing)); vLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Preferred, QSizePolicy::Expanding)); widget->setLayout(vLayout); } void PrefsDialog::initCode(QWidget * widget, QList platforms) { QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(createProgrammerForm(platforms)); vLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Preferred, QSizePolicy::Expanding)); widget->setLayout(vLayout); } QWidget * PrefsDialog::createZoomerForm() { QGroupBox * zoomer = new QGroupBox(tr("Mouse Wheel Behavior"), this ); QHBoxLayout * zhlayout = new QHBoxLayout(); zhlayout->setSpacing(SPACING); QFrame * frame = new QFrame(); frame->setFixedWidth(FORMLABELWIDTH); QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->setSpacing(0); vLayout->setMargin(0); for (int i = 0; i < 3; i++) { m_wheelLabel[i] = new QLabel(); vLayout->addWidget(m_wheelLabel[i]); } updateWheelText(); frame->setLayout(vLayout); zhlayout->addWidget(frame); QPushButton * pushButton = new QPushButton(tr("Change Wheel Behavior"), this); connect(pushButton, SIGNAL(clicked()), this, SLOT(changeWheelBehavior())); zhlayout->addWidget(pushButton); zoomer->setLayout(zhlayout); return zoomer; } QWidget * PrefsDialog::createAutosaveForm() { QGroupBox * autosave = new QGroupBox(tr("Autosave"), this ); QHBoxLayout * zhlayout = new QHBoxLayout(); zhlayout->setSpacing(SPACING); QCheckBox * box = new QCheckBox(tr("Autosave every:")); box->setChecked(MainWindow::AutosaveEnabled); zhlayout->addWidget(box); zhlayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); QSpinBox * spinBox = new QSpinBox; spinBox->setMinimum(1); spinBox->setMaximum(60); spinBox->setValue(MainWindow::AutosaveTimeoutMinutes); spinBox->setMaximumWidth(80); zhlayout->addWidget(spinBox); QLabel * label = new QLabel(tr("minutes")); zhlayout->addWidget(label); autosave->setLayout(zhlayout); connect(box, SIGNAL(clicked(bool)), this, SLOT(toggleAutosave(bool))); connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(changeAutosavePeriod(int))); return autosave; } QWidget * PrefsDialog::createLanguageForm(QFileInfoList & languages) { QGroupBox * formGroupBox = new QGroupBox(tr("Language")); QVBoxLayout *layout = new QVBoxLayout(); QComboBox* comboBox = new QComboBox(this); m_translatorListModel = new TranslatorListModel(languages, this); comboBox->setModel(m_translatorListModel); comboBox->setCurrentIndex(m_translatorListModel->findIndex(m_name)); connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeLanguage(int))); layout->addWidget(comboBox); QLabel * ll = new QLabel(); ll->setMinimumHeight(45); ll->setWordWrap(true); ll->setText(QObject::tr("Please note that a new language setting will not take effect " "until the next time you run Fritzing.")); layout->addWidget(ll); formGroupBox->setLayout(layout); return formGroupBox; } QWidget* PrefsDialog::createColorForm() { QGroupBox * formGroupBox = new QGroupBox(tr("Colors")); QVBoxLayout *layout = new QVBoxLayout(); layout->setSpacing(0); layout->setMargin(0); QFrame * f1 = new QFrame(); QHBoxLayout * h1 = new QHBoxLayout(); h1->setSpacing(SPACING); QLabel * c1 = new QLabel(QObject::tr("Connected highlight color")); c1->setWordWrap(true); c1->setFixedWidth(FORMLABELWIDTH); h1->addWidget(c1); QColor connectedColor = ItemBase::connectedColor(); ClickableLabel * cl1 = new ClickableLabel(tr("%1 (click to change...)").arg(connectedColor.name()), this); connect(cl1, SIGNAL(clicked()), this, SLOT(setConnectedColor())); cl1->setPalette(QPalette(connectedColor)); cl1->setAutoFillBackground(true); cl1->setMargin(MARGIN); h1->addWidget(cl1); f1->setLayout(h1); layout->addWidget(f1); QFrame * f2 = new QFrame(); QHBoxLayout * h2 = new QHBoxLayout(); h2->setSpacing(SPACING); QLabel * c2 = new QLabel(QObject::tr("Unconnected highlight color")); c2->setWordWrap(true); c2->setFixedWidth(FORMLABELWIDTH); h2->addWidget(c2); QColor unconnectedColor = ItemBase::unconnectedColor(); ClickableLabel * cl2 = new ClickableLabel(tr("%1 (click to change...)").arg(unconnectedColor.name()), this); connect(cl2, SIGNAL(clicked()), this, SLOT(setUnconnectedColor())); cl2->setPalette(QPalette(unconnectedColor)); cl2->setAutoFillBackground(true); cl2->setMargin(MARGIN); h2->addWidget(cl2); f2->setLayout(h2); layout->addWidget(f2); formGroupBox->setLayout(layout); return formGroupBox; } QWidget* PrefsDialog::createOtherForm() { QGroupBox * formGroupBox = new QGroupBox(tr("Clear Settings")); QHBoxLayout *layout = new QHBoxLayout(); layout->setSpacing(SPACING); QFrame * frame = new QFrame; QVBoxLayout * vlayout = new QVBoxLayout(); vlayout->setMargin(0); vlayout->setSpacing(0); QLabel * clearLabel = new QLabel(QObject::tr("Clear all saved settings and close this dialog immediately.")); clearLabel->setWordWrap(true); clearLabel->setFixedWidth(FORMLABELWIDTH); vlayout->addWidget(clearLabel); vlayout->addSpacing(SPACING); clearLabel = new QLabel(QObject::tr("This action does not delete any files; it restores settings to their default values.")); clearLabel->setWordWrap(true); clearLabel->setFixedWidth(FORMLABELWIDTH); vlayout->addWidget(clearLabel); vlayout->addSpacing(SPACING); clearLabel = new QLabel(QObject::tr("There is no undo for this action, and no further warning!!!!")); clearLabel->setWordWrap(true); clearLabel->setFixedWidth(FORMLABELWIDTH); vlayout->addWidget(clearLabel); frame->setLayout(vlayout); layout->addWidget(frame); QPushButton * clear = new QPushButton(QObject::tr("Clear Settings"), this); clear->setMaximumWidth(220); connect(clear, SIGNAL(clicked()), this, SLOT(clear())); layout->addWidget(clear); formGroupBox->setLayout(layout); return formGroupBox; } QWidget* PrefsDialog::createProgrammerForm(QList platforms) { QGroupBox * formGroupBox = new QGroupBox(tr("Platform Support")); QVBoxLayout *layout = new QVBoxLayout(); layout->setSpacing(SPACING); foreach (Platform * platform, platforms) { QLabel *platformLb = new QLabel(""); platformLb->setTextFormat(Qt::RichText); platformLb->setText(tr("%1").arg(platform->getName())); layout->addWidget(platformLb); QFrame * locationFrame = new QFrame(formGroupBox); QHBoxLayout * locationLayout = new QHBoxLayout(); locationLayout->setMargin(0); locationLayout->setSpacing(0); locationFrame->setLayout(locationLayout); QLabel *locationLb = new QLabel(tr("Location:")); locationLayout->addWidget(locationLb); locationLayout->addSpacing(SPACING); QLineEdit * locationLE = new QLineEdit(locationFrame); locationLE->setText(platform->getCommandLocation()); locationLayout->addWidget(locationLE); m_programmerLEs.insert(platform->getName(), locationLE); QPushButton * locateBtn = new QPushButton(tr("..."),locationFrame); locationLayout->addWidget(locateBtn); locateBtn->setProperty("platform", platform->getName()); connect(locateBtn, SIGNAL(clicked()), this, SLOT(chooseProgrammer())); layout->addWidget(locationFrame); QLabel *hintLb = new QLabel(""); hintLb->setTextFormat(Qt::RichText); hintLb->setOpenExternalLinks(true); hintLb->setText(tr("You need to have
%2 (version %3 or newer) installed.") .arg(platform->getDownloadUrl().toString()) .arg(platform->getIdeName()) .arg(platform->getMinVersion())); layout->addWidget(hintLb); layout->addSpacing(SPACING); } formGroupBox->setLayout(layout); return formGroupBox; } void PrefsDialog::chooseProgrammer() { QObject * button = sender(); if (button == NULL) return; QString platformName = sender()->property("platform").toString(); Platform * platform; foreach (Platform *p, m_platforms) { if (p->getName().compare(platformName) == 0) { platform = p; break; } } QString filename = FolderUtils::getOpenFileName( this, tr("Select a programmer (executable) for %1").arg(platform->getName()), FolderUtils::openSaveFolder(), "(Programmer *)" ); if (!filename.isEmpty()) { m_programmerLEs.value(platformName)->setText(filename); platform->setCommandLocation(filename); } } void PrefsDialog::changeLanguage(int index) { const QLocale * locale = m_translatorListModel->locale(index); if (locale) { m_name = locale->name(); m_settings.insert("language", m_name); } } void PrefsDialog::clear() { m_cleared = true; accept(); } bool PrefsDialog::cleared() { return m_cleared; } void PrefsDialog::setConnectedColor() { QColor cc = ItemBase::connectedColor(); QColor scc = ItemBase::standardConnectedColor(); SetColorDialog setColorDialog(tr("Connected Highlight"), cc, scc, false, this); int result = setColorDialog.exec(); if (result == QDialog::Rejected) return; QColor c = setColorDialog.selectedColor(); m_settings.insert("connectedColor", c.name()); ClickableLabel * cl = qobject_cast(sender()); if (cl) { cl->setPalette(QPalette(c)); } } void PrefsDialog::setUnconnectedColor() { QColor cc = ItemBase::unconnectedColor(); QColor scc = ItemBase::standardUnconnectedColor(); SetColorDialog setColorDialog(tr("Unconnected Highlight"), cc, scc, false, this); int result = setColorDialog.exec(); if (result == QDialog::Rejected) return; QColor c = setColorDialog.selectedColor(); m_settings.insert("unconnectedColor", c.name()); ClickableLabel * cl = qobject_cast(sender()); if (cl) { cl->setPalette(QPalette(c)); } } QHash & PrefsDialog::settings() { return m_settings; } QHash & PrefsDialog::tempSettings() { return m_tempSettings; } void PrefsDialog::changeWheelBehavior() { if (++m_wheelMapping >= ZoomableGraphicsView::WheelMappingCount) { m_wheelMapping = 0; } m_settings.insert("wheelMapping", QString("%1").arg(m_wheelMapping)); updateWheelText(); } void PrefsDialog::updateWheelText() { QString text; #ifdef Q_OS_MAC QString cKey = tr("Command"); #else QString cKey = tr("Control"); #endif switch((ZoomableGraphicsView::WheelMapping) m_wheelMapping) { case ZoomableGraphicsView::ScrollPrimary: default: text = tr("no keys down = scroll\nshift key swaps scroll axis\nAlt or %1 key = zoom").arg(cKey); break; case ZoomableGraphicsView::ZoomPrimary: text = tr("no keys down = zoom\nAlt or %1 key = scroll\nshift key swaps scroll axis").arg(cKey); break; } QStringList strings = text.split('\n'); for (int i = 0; i < 3; i++) { m_wheelLabel[i]->setText(strings.at(i)); } } void PrefsDialog::toggleAutosave(bool checked) { m_settings.insert("autosaveEnabled", QString("%1").arg(checked)); } void PrefsDialog::changeAutosavePeriod(int value) { m_settings.insert("autosavePeriod", QString("%1").arg(value)); } QWidget* PrefsDialog::createCurvyForm(ViewInfoThing * viewInfoThing) { QGroupBox * groupBox = new QGroupBox(tr("Curvy vs. straight wires")); QVBoxLayout *layout = new QVBoxLayout; QLabel * label1 = new QLabel(tr("When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) " "do you want to change the curvature of the wire (or leg) or drag out a new bendpoint?")); label1->setWordWrap(true); layout->addWidget(label1); QLabel * label2 = new QLabel(tr("This checkbox sets the default behavior. " "You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag.")); label2->setWordWrap(true); layout->addWidget(label2); layout->addSpacing(10); QCheckBox * checkbox = new QCheckBox(tr("Curvy wires and legs")); checkbox->setProperty("index", viewInfoThing->index); checkbox->setChecked(viewInfoThing->curvy); connect(checkbox, SIGNAL(clicked()), this, SLOT(curvyChanged())); layout->addWidget(checkbox); groupBox->setLayout(layout); return groupBox; } void PrefsDialog::curvyChanged() { QCheckBox * checkBox = qobject_cast(sender()); if (checkBox == NULL) return; ViewInfoThing * viewInfoThing = &m_viewInfoThings[sender()->property("index").toInt()]; m_settings.insert(QString("%1CurvyWires").arg(viewInfoThing->shortName), checkBox->isChecked() ? "1" : "0"); } fritzing-app-0.9.2b/src/dialogs/prefsdialog.h000066400000000000000000000062361250202676700211750ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6732 $: $Author: irascibl@gmail.com $: $Date: 2012-12-27 08:26:48 +0100 (Do, 27. Dez 2012) $ ********************************************************************/ #ifndef PREFSDIALOG_H #define PREFSDIALOG_H #include #include #include #include #include #include #include #include #include #include "../program/platform.h" struct ViewInfoThing { QString viewName; QString shortName; int index; bool curvy; }; class PrefsDialog : public QDialog { Q_OBJECT public: PrefsDialog(const QString & language, QWidget *parent = 0); ~PrefsDialog(); bool cleared(); QHash & settings(); QHash & tempSettings(); void initLayout(QFileInfoList & languages, QList platforms); void initViewInfo(int index, const QString & viewName, const QString & shortName, bool curvy); protected: QWidget * createLanguageForm(QFileInfoList & languages); QWidget* createOtherForm(); QWidget* createColorForm(); QWidget * createZoomerForm(); QWidget * createAutosaveForm(); QWidget *createProgrammerForm(QList platforms); void updateWheelText(); void initGeneral(QWidget * general, QFileInfoList & languages); void initBreadboard(QWidget *, ViewInfoThing *); void initSchematic(QWidget *, ViewInfoThing *); void initPCB(QWidget *, ViewInfoThing *); void initCode(QWidget *widget, QList platforms); QWidget * createCurvyForm(ViewInfoThing *); protected slots: void changeLanguage(int); void clear(); void setConnectedColor(); void setUnconnectedColor(); void changeWheelBehavior(); void toggleAutosave(bool); void changeAutosavePeriod(int); void curvyChanged(); void chooseProgrammer(); protected: QPointer m_tabWidget; QPointer m_general; QPointer m_breadboard; QPointer m_schematic; QPointer m_pcb; QPointer m_code; QPointer m_wheelLabel[3]; QList m_platforms; QHash m_programmerLEs; QHash m_settings; QHash m_tempSettings; QString m_name; class TranslatorListModel * m_translatorListModel; bool m_cleared; int m_wheelMapping; ViewInfoThing m_viewInfoThings[3]; }; #endif fritzing-app-0.9.2b/src/dialogs/quotedialog.cpp000066400000000000000000000270771250202676700215540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 7003 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 11:54:36 +0200 (Mo, 29. Apr 2013) $ ********************************************************************/ #include "quotedialog.h" #include "../debugdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include ////////////////////////////////////////////////////// static CountCost TheCountCost[QuoteDialog::MessageCount]; static double TheArea; static int TheBoardCount; static QList Counts; static bool QuoteSucceeded = false; double hundredths(double d) { double h = (int) (d * 100); return h / ((double) 100); } QChar EuroSymbol(0x20AC); QChar ThinSpaceSymbol(0x2009); ////////////////////////////////////////////////////// LabelThing::LabelThing(const QString & text, const QString & released, const QString & pressed, const QString & hover, QWidget * parent) : QLabel(text, parent) { m_state = RELEASED; m_releasedImage = QPixmap(released); m_pressedImage = QPixmap(pressed); m_hoverImage = QPixmap(hover); setMinimumSize(m_releasedImage.width(), m_releasedImage.height()); setMaximumSize(m_releasedImage.width(), m_releasedImage.height()); } void LabelThing::enterEvent(QEvent * event) { m_state = HOVER; update(); QLabel::enterEvent(event); } void LabelThing::leaveEvent(QEvent * event) { m_state = RELEASED; update(); QLabel::enterEvent(event); } void LabelThing::mousePressEvent(QMouseEvent * event) { m_state = PRESSED; update(); QLabel::mousePressEvent(event); } void LabelThing::mouseReleaseEvent(QMouseEvent * event) { m_state = RELEASED; update(); QLabel::mouseReleaseEvent(event); emit clicked(); } void LabelThing::paintEvent(QPaintEvent * event) { // use 'new QPainter()' so that delete is invoked before the QLabel::paintEvent call, otherwise the label isn't painted on mac QPainter * painter = new QPainter(this); switch (m_state) { case PRESSED: painter->drawPixmap(0, 0, m_pressedImage); setContentsMargins(0, 4, 0, 0); break; case HOVER: painter->drawPixmap(0, 0, m_hoverImage); break; case RELEASED: painter->drawPixmap(0, 0, m_releasedImage); setContentsMargins(0, 0, 0, 0); break; } delete painter; DebugDialog::debug(QString("paint event %1").arg(m_state)); QLabel::paintEvent(event); } ////////////////////////////////////////////////////// // from http://qt.onyou.ch/2010/07/08/hide-vertical-grid-lines-in-qtableview/ // custom item delegate to draw grid lines around cells class CustomDelegate : public QStyledItemDelegate { public: CustomDelegate(QTableView* tableView); protected: void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; private: QPen _gridPen; }; CustomDelegate::CustomDelegate(QTableView* tableView) { // create grid pen int gridHint = tableView->style()->styleHint(QStyle::SH_Table_GridLineColor, new QStyleOptionViewItemV4()); QColor gridColor(gridHint); _gridPen = QPen(gridColor, 0, tableView->gridStyle()); } void CustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyledItemDelegate::paint(painter, option, index); if (index.row() < 2) { QPen oldPen = painter->pen(); painter->setPen(_gridPen); // paint vertical lines //painter->drawLine(option.rect.topRight(), option.rect.bottomRight()); //vertical lines are disabled // paint horizontal lines painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); //draw only horizontal line painter->setPen(oldPen); } } ////////////////////////////////////////////////////// QuoteDialog::QuoteDialog(bool full, QWidget *parent) : QDialog(parent) { initCounts(); QFile styleSheet(":/resources/styles/fritzing.qss"); if (!styleSheet.open(QIODevice::ReadOnly)) { DebugDialog::debug("Unable to open :/resources/styles/fritzing.qss"); } else { this->setStyleSheet(styleSheet.readAll()); } setWindowTitle(tr("Fritzing Fab Quote")); QVBoxLayout * vLayout = new QVBoxLayout(this); QLabel * label = new QLabel(tr("Order your PCB from Fritzing Fab")); label->setObjectName("quoteOrder"); vLayout->addWidget(label); m_messageLabel = new QLabel(tr("")); m_messageLabel->setObjectName("quoteMessage"); vLayout->addWidget(m_messageLabel); m_tableWidget = new QTableWidget(3, MessageCount + 1); m_tableWidget->setObjectName("quoteTable"); m_tableWidget->setShowGrid(false); m_tableWidget->verticalHeader()->setVisible(false); m_tableWidget->horizontalHeader()->setVisible(false); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) m_tableWidget->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); m_tableWidget->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); #else m_tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); m_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); #endif m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_tableWidget->setItemDelegate(new CustomDelegate(m_tableWidget)); QStringList labels; labels << tr("Copies") << tr("Price per board") << tr("Price"); int ix = 0; foreach (QString labl, labels) { QTableWidgetItem * item = new QTableWidgetItem(labl); item->setFlags(0); m_tableWidget->setItem(ix, 0, item); ix += 1; } vLayout->addWidget(m_tableWidget); QString additional = tr("Please note that prices do not include shipping,
"); additional += tr("possible additional taxes, or the checking fee.
"); additional += tr("For more information on pricing see http://fab.fritzing.org/pricing."); label = new QLabel(additional); label->setObjectName("quoteAdditional"); label->setOpenExternalLinks(true); vLayout->addWidget(label); if (!full) label->setVisible(false); QFrame * frame = new QFrame; QHBoxLayout * buttonLayout = new QHBoxLayout(); LabelThing * labelThing = new LabelThing(tr("Visit Fritzing Fab"), ":/resources/images/icons/fabquote_button_release.png", ":/resources/images/icons/fabquote_button_press.png", ":/resources/images/icons/fabquote_button_hover.png" ); labelThing->setObjectName("quoteVisitButton"); connect(labelThing, SIGNAL(clicked()), this, SLOT(visitFritzingFab()), Qt::QueuedConnection); buttonLayout->addWidget(labelThing); buttonLayout->addSpacing(90); label = new QLabel(); QPixmap order(":/resources/images/icons/Toolbar_Icon_Order.png"); label->setPixmap(order); buttonLayout->addWidget(label); buttonLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding)); frame->setLayout(buttonLayout); vLayout->addWidget(frame); if (!full) frame->setVisible(false); vLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding)); this->setLayout(vLayout); this->adjustSize(); } QuoteDialog::~QuoteDialog() { } void QuoteDialog::setCountCost(int index, int count, double cost) { //DebugDialog::debug(QString("quote dialog set count cost %1 %2").arg(count).arg(cost)); if (index < 0) return; if (index >= MessageCount) return; TheCountCost[index].count = count; TheCountCost[index].cost = cost; } void QuoteDialog::setArea(double area, int boardCount) { TheBoardCount = boardCount; TheArea = area; } void QuoteDialog::setText() { //DebugDialog::debug("quote dialog set text"); QString msg = tr("The total area of the %n PCB(s) in this sketch is", "", TheBoardCount); msg += tr(" %1 cm%3 (%2 in%3).
") .arg(hundredths(TheArea)) .arg(hundredths(TheArea / (2.54 * 2.54))) .arg(QChar(178)) ; msg += tr("Use Fritzing Fab to produce a PCB from your sketch.
"); msg += tr("Take advantage of our quantity discount:"); m_messageLabel->setText(msg); for (int i = 0; i < MessageCount; i++) { int count = TheCountCost[i].count; double cost = TheCountCost[i].cost; if (count == 0) continue; if (cost == 0) continue; QTableWidgetItem * item = new QTableWidgetItem(QString::number(count)); item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); item->setFlags(0); m_tableWidget->setItem(0, i + 1, item); item = new QTableWidgetItem(QString("%1%2%3").arg(hundredths(cost/count), 13, 'F', 2).arg(ThinSpaceSymbol).arg(EuroSymbol)); item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); item->setFlags(0); m_tableWidget->setItem(1, i + 1, item); item = new QTableWidgetItem(QString("%1%2%3").arg(hundredths(cost), 13, 'F', 2).arg(ThinSpaceSymbol).arg(EuroSymbol)); item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); QFont font = item->font(); font.setBold(true); item->setFont(font); item->setFlags(0); m_tableWidget->setItem(2, i + 1, item); } // this is some bullshit because QTableWidget seems to allocate a huge amount of whitespace at right and bottom of the table int w = 10; for (int i = 0; i < m_tableWidget->columnCount(); i++) w += m_tableWidget->columnWidth(i); int h = 4; for (int i = 0; i < m_tableWidget->rowCount(); i++) h += m_tableWidget->rowHeight(i); m_tableWidget->setMaximumSize(QSize(w, h)); m_tableWidget->setMinimumSize(QSize(w, h)); this->adjustSize(); } void QuoteDialog::visitFritzingFab() { QDesktopServices::openUrl(QString("http://fab.fritzing.org/fritzing-fab")); } QString QuoteDialog::countArgs() { initCounts(); QString countArgs; foreach (int c, Counts) { countArgs += QString::number(c) + ","; } countArgs.chop(1); return countArgs; } void QuoteDialog::setQuoteSucceeded(bool succeeded) { //DebugDialog::debug(QString("quote succeeded %1").arg(succeeded)); QuoteSucceeded = succeeded; } bool QuoteDialog::quoteSucceeded() { //DebugDialog::debug(QString("check quote succeeded %1").arg(QuoteSucceeded)); return QuoteSucceeded; } void QuoteDialog::initCounts() { if (Counts.isEmpty()) { Counts << 1 << 2 << 5 << 10; } } fritzing-app-0.9.2b/src/dialogs/quotedialog.h000066400000000000000000000045501250202676700212100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef QUOTEDIALOG_H #define QUOTEDIALOG_H #include #include #include struct CountCost { int count; double cost; }; class LabelThing : public QLabel { Q_OBJECT public: LabelThing(const QString & text, const QString & released, const QString & pressed, const QString & hover, QWidget * parent = NULL); void enterEvent(QEvent * event); void leaveEvent(QEvent * event); void mousePressEvent(QMouseEvent * event); void mouseReleaseEvent(QMouseEvent * event); void paintEvent(QPaintEvent * event); public: enum State { RELEASED, PRESSED, HOVER }; signals: void clicked(); protected: QPixmap m_releasedImage; QPixmap m_pressedImage; QPixmap m_hoverImage; State m_state; }; class QuoteDialog : public QDialog { Q_OBJECT public: QuoteDialog(bool full, QWidget *parent = 0); ~QuoteDialog(); void setText(); public: static void setArea(double area, int boardCount); static void setCountCost(int index, int count, double cost); static QString countArgs(); static void setQuoteSucceeded(bool); static bool quoteSucceeded(); protected: static void initCounts(); public: static const int MessageCount = 4; protected slots: void visitFritzingFab(); protected: QLabel * m_messageLabel; QTableWidget * m_tableWidget; }; #endif fritzing-app-0.9.2b/src/dialogs/recoverydialog.cpp000066400000000000000000000155001250202676700222410ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include "recoverydialog.h" #include "../utils/folderutils.h" #include "../debugdialog.h" CenteredTreeWidget::CenteredTreeWidget(QWidget * parent) : QTreeWidget(parent) { // no luck getting this styling to work from fritzing.qss setStyleSheet("::item { margin-left: 8px; margin-right: 8px; margin-top: 1px; margin-bottom: 1px; }"); } QStyleOptionViewItem CenteredTreeWidget::viewOptions() const { // alignment not possible from a stylesheet QStyleOptionViewItem styleOptionViewItem = QTreeWidget::viewOptions(); styleOptionViewItem.displayAlignment = Qt::AlignCenter; return styleOptionViewItem; } RecoveryDialog::RecoveryDialog(QFileInfoList fileInfoList, QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags) { m_recoveryList = new CenteredTreeWidget(this); m_recoveryList->setColumnCount(3); m_recoveryList->setSelectionMode(QAbstractItemView::ExtendedSelection); m_recoveryList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_recoveryList->setSortingEnabled(false); m_recoveryList->setDragEnabled(false); m_recoveryList->setUniformRowHeights(true); // Small optimization m_recoveryList->setIconSize(QSize(0,0)); m_recoveryList->setRootIsDecorated(false); QStringList headerLabels; headerLabels << tr("File") << tr("Last backup") << tr("Last saved"); m_recoveryList->setHeaderLabels(headerLabels); m_recoveryList->header()->setDefaultAlignment(Qt::AlignCenter); m_recoveryList->header()->setDragEnabled(false); m_recoveryList->header()->setDragDropMode(QAbstractItemView::NoDragDrop); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) m_recoveryList->header()->setResizeMode(QHeaderView::ResizeToContents); m_recoveryList->header()->setMovable(false); #else m_recoveryList->header()->setSectionResizeMode(QHeaderView::ResizeToContents); m_recoveryList->header()->setSectionsMovable(false); #endif connect(m_recoveryList, SIGNAL(itemSelectionChanged()), this, SLOT(updateRecoverButton())); QTreeWidgetItem *item; foreach (QFileInfo fileInfo, fileInfoList) { item = new QTreeWidgetItem; QString originalFileName = getOriginalFileName(fileInfo.absoluteFilePath()); DebugDialog::debug(QString("Creating option for recoveryDialog file %1").arg(originalFileName)); QFileInfo originalFileInfo(originalFileName); item->setData(0, Qt::UserRole, fileInfo.absoluteFilePath()); if (originalFileInfo.exists()) { item->setText(0, originalFileInfo.fileName()); item->setToolTip(0, originalFileInfo.absoluteFilePath()); item->setData(1, Qt::UserRole, originalFileInfo.absoluteFilePath()); item->setText(2, originalFileInfo.lastModified().toString()); } else { item->setText(0, originalFileName); item->setText(2, tr("file not saved")); item->setData(1, Qt::UserRole, originalFileName); } item->setText(1, fileInfo.lastModified().toString()); DebugDialog::debug(QString("Displaying recoveryDialog text %1 and data %2").arg(item->text(0)).arg(item->data(0,Qt::UserRole).value())); m_recoveryList->addTopLevelItem(item); m_fileList << item; } QVBoxLayout *layout = new QVBoxLayout(); QLabel * label = new QLabel; label->setWordWrap(true); label->setText(tr("

Fritzing may have crashed, but some of the changes to the following files may be recovered.

" "

The date and time each file was backed-up is displayed. " "If the file was saved, that date and time is also listed for comparison.

" "

The original files are still on your disk, if they were ever saved. " "You can choose whether to overwrite the original file after you load its recovery file.

" "

Select any files you want to recover from the list below.

" )); layout->addWidget(label); layout->addWidget(m_recoveryList); QHBoxLayout *buttonLayout = new QHBoxLayout(); layout->addLayout(buttonLayout); m_recover = new QPushButton(tr("&Recover")); m_recover->setDefault(true); m_recover->setEnabled(false); m_recover->setMaximumWidth(130); connect(m_recover, SIGNAL(clicked()), this, SLOT(accept())); m_ignore = new QPushButton(tr("&Ignore")); m_ignore->setMaximumWidth(130); connect(m_ignore, SIGNAL(clicked()), this, SLOT(reject())); buttonLayout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Expanding)); buttonLayout->addWidget(m_recover); buttonLayout->addWidget(m_ignore); buttonLayout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Expanding)); setLayout(layout); layout->setSizeConstraint(QLayout::SetMinAndMaxSize); } QList RecoveryDialog::getFileList() { return m_fileList; } QString RecoveryDialog::getOriginalFileName(const QString & path) { QString originalName; QFile file(path); if (!file.open(QFile::ReadOnly)) { // TODO: not sure how else to handle this... DebugDialog::debug(QString("unable to open recovery file %1").arg(path)); return originalName; } QXmlStreamReader xml(&file); xml.setNamespaceProcessing(false); while (!xml.atEnd()) { if (xml.readNext() == QXmlStreamReader::StartElement) { QString name = xml.name().toString(); if (name == "originalFileName") { originalName = xml.readElementText(); break; } } } file.close(); return originalName; } void RecoveryDialog::updateRecoverButton() { if (m_recoveryList->selectedItems().isEmpty()) { m_recover->setEnabled(false); } else { m_recover->setEnabled(true); } } fritzing-app-0.9.2b/src/dialogs/recoverydialog.h000066400000000000000000000035371250202676700217150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef RECOVERYDIALOG_H #define RECOVERYDIALOG_H #include #include #include #include #include class CenteredTreeWidget : public QTreeWidget { Q_OBJECT public: CenteredTreeWidget(QWidget *parent = 0); protected: QStyleOptionViewItem viewOptions () const; }; class RecoveryDialog : public QDialog { Q_OBJECT public: RecoveryDialog(QFileInfoList fileList, QWidget *parent = 0, Qt::WindowFlags flags = 0); QList getFileList(); protected: QString getOriginalFileName(const QString & path); QList m_fileList; QTreeWidget *m_recoveryList; QPushButton *m_recover; QPushButton *m_ignore; protected slots: void updateRecoverButton(); }; #endif // RECOVERYDIALOG_H fritzing-app-0.9.2b/src/dialogs/setcolordialog.cpp000066400000000000000000000116321250202676700222370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "setcolordialog.h" #include "../debugdialog.h" #include "../utils/clickablelabel.h" #include #include #include #include #include #include #include #include static const int MARGIN = 5; static const int BUTTON_WIDTH = 150; ///////////////////////////////////// SetColorDialog::SetColorDialog(const QString & message, QColor & currentColor, QColor & standardColor, bool askPrefs, QWidget *parent) : QDialog(parent) { m_prefsCheckBox = NULL; m_message = message; m_currentColor = m_selectedColor = currentColor; m_standardColor = standardColor; this->setWindowTitle(tr("%1 Color...").arg(message)); QVBoxLayout * vLayout = new QVBoxLayout(this); QLabel * label = new QLabel(tr("Choose %1 color:").arg(message.toLower())); vLayout->addWidget(label); QFrame * f4 = new QFrame(); QHBoxLayout * hLayout4 = new QHBoxLayout(f4); m_selectedColorLabel = new QLabel(); setColor(currentColor); hLayout4->addWidget(m_selectedColorLabel); m_selectedColorLabel->setMargin(MARGIN); vLayout->addWidget(f4); QFrame * f2 = new QFrame(); QHBoxLayout * hLayout2 = new QHBoxLayout(f2); QPushButton *button2 = new QPushButton(tr("Reset to default")); button2->setFixedWidth(BUTTON_WIDTH); connect(button2, SIGNAL(clicked()), this, SLOT(selectStandard())); hLayout2->addWidget(button2); m_standardColorLabel = new ClickableLabel(tr("Default color (%1)").arg(standardColor.name()), this); connect(m_standardColorLabel, SIGNAL(clicked()), this, SLOT(selectStandard())); m_standardColorLabel->setPalette(QPalette(standardColor)); m_standardColorLabel->setAutoFillBackground(true); m_standardColorLabel->setMargin(MARGIN); hLayout2->addWidget(m_standardColorLabel); vLayout->addWidget(f2); QFrame * f3 = new QFrame(); QHBoxLayout * hLayout3 = new QHBoxLayout(f3); QPushButton *button3 = new QPushButton(tr("Pick custom color ...")); connect(button3, SIGNAL(clicked()), this, SLOT(selectCustom())); hLayout3->addWidget(button3); setCustomColor(currentColor); vLayout->addWidget(f3); QSpacerItem * spacerItem = new QSpacerItem( 0, 10 ); vLayout->addSpacerItem(spacerItem); if (askPrefs) { QFrame * f5 = new QFrame(); QHBoxLayout * hLayout5 = new QHBoxLayout(f5); m_prefsCheckBox = new QCheckBox(tr("Make this the default %1 color").arg(message.toLower())); hLayout5->addWidget(m_prefsCheckBox); vLayout->addWidget(f5); } QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } SetColorDialog::~SetColorDialog() { } const QColor & SetColorDialog::selectedColor() { return m_selectedColor; } void SetColorDialog::selectCurrent() { setColor(m_currentColor); } void SetColorDialog::selectStandard() { setColor(m_standardColor); } void SetColorDialog::selectLastCustom() { setColor(m_customColor); } void SetColorDialog::selectCustom() { QColor color = QColorDialog::getColor ( m_selectedColor, this, tr("Pick custom %1 color").arg(m_message.toLower())); if (!color.isValid()) return; setColor(color); setCustomColor(color); } bool SetColorDialog::isPrefsColor() { if (m_prefsCheckBox == NULL) return false; return m_prefsCheckBox->isChecked(); } void SetColorDialog::setCustomColor(const QColor & color) { m_customColor = color; } void SetColorDialog::setColor(const QColor & color) { m_selectedColor = color; m_selectedColorLabel->setText(tr("Current color (%1)").arg(color.name())); m_selectedColorLabel->setPalette(QPalette(color)); m_selectedColorLabel->setAutoFillBackground(true); } fritzing-app-0.9.2b/src/dialogs/setcolordialog.h000066400000000000000000000036071250202676700217070ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SETCOLORDIALOG_H #define SETCOLORDIALOG_H #include #include #include #include class SetColorDialog : public QDialog { Q_OBJECT public: SetColorDialog(const QString & message, QColor & currentColor, QColor & standardColor, bool askPrefs, QWidget *parent = 0); ~SetColorDialog(); const QColor & selectedColor(); bool isPrefsColor(); protected: void setColor(const QColor &); void setCustomColor(const QColor &); protected slots: void selectCurrent(); void selectCustom(); void selectLastCustom(); void selectStandard(); protected: QString m_message; QColor m_currentColor; QColor m_standardColor; QColor m_selectedColor; QColor m_customColor; QLabel * m_currentColorLabel; QLabel * m_standardColorLabel; QLabel * m_customColorLabel; QLabel * m_selectedColorLabel; QCheckBox * m_prefsCheckBox; }; #endif fritzing-app-0.9.2b/src/dialogs/translatorlistmodel.cpp000066400000000000000000000240461250202676700233360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "translatorlistmodel.h" #include "../debugdialog.h" static QVariant emptyVariant; QHash TranslatorListModel::m_languages; QList TranslatorListModel::m_localeList; // More languages written in their own language can be found // at http://www.mozilla.com/en-US/firefox/all.html // recipe for translating from mozilla strings into source code via windows: // 1. copy the string from the mozilla page into wordpad and save it as a unicode text file // 2. open that unicode text file as a binary file (e.g. in msvc) // 3. ignore the first two bytes (these are a signal that says "I'm unicode") // 4. initialize an array of ushort using the rest of the byte pairs // 5. don't forget to reverse the order of the bytes in each pair. // to add a new language to fritzing, find its two-letter language code: http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes // then in the translations.pri file, add a new line translations/fritzing_XX.ts where you substitute the two letters for "XX". // If the language has multiple dialects, then you will need to add _YY to distinguish TranslatorListModel::TranslatorListModel(QFileInfoList & fileInfoList, QObject* parent) : QAbstractListModel(parent) { if (m_languages.count() == 0) { m_languages.insert("english", tr("English - %1").arg("English")); m_languages.insert("german", tr("German - %1").arg("Deutsch")); m_languages.insert("hungarian", tr("Hungarian - %1").arg("Magyar")); m_languages.insert("estonian", tr("Estonian - %1").arg("Eesti keel")); m_languages.insert("dutch", tr("Dutch - %1").arg("Nederlands")); m_languages.insert("italian", tr("Italian - %1").arg("Italiano")); m_languages.insert("polish", tr("Polish - %1").arg("Polski")); m_languages.insert("swedish", tr("Swedish - %1").arg("Svenska")); m_languages.insert("galician", tr("Galician - %1").arg("Galego")); m_languages.insert("indonesian", tr("Indonesian - %1").arg("Bahasa Indonesia")); m_languages.insert("danish", tr("Danish - %1").arg("Dansk")); ushort t1[] = { 0x65e5, 0x672c, 0x8a9e, 0 }; m_languages.insert("japanese", tr("Japanese - %1").arg(QString::fromUtf16(t1))); ushort t2[] = { 0x0420, 0x0443, 0x0441, 0x0441, 0x043a, 0x0438, 0x0439, 0 }; m_languages.insert("russian", tr("Russian - %1").arg(QString::fromUtf16(t2))); ushort t3[] = { 0x05e2, 0x05d1, 0x05e8, 0x05d9, 0x05ea, 0 }; m_languages.insert("hebrew", tr("Hebrew - %1").arg(QString::fromUtf16(t3))); ushort t4[] = { 0x0639, 0x0631, 0x0628, 0x064a, 0 }; m_languages.insert("arabic", tr("Arabic - %1").arg(QString::fromUtf16(t4))); ushort t5[] = { 0x0939, 0x093f, 0x0928, 0x094d, 0x0926, 0x0940, 0x0020, 0x0028, 0x092d, 0x093e, 0x0930, 0x0924, 0x0029, 0 }; m_languages.insert("hindi", tr("Hindi - %1").arg(QString::fromUtf16(t5))); ushort t6[] = { 0x4e2d, 0x6587, 0x0020, 0x0028, 0x7b80, 0x4f53, 0x0029, 0 }; m_languages.insert("chinese_china", tr("Chinese (Simplified) - %1").arg(QString::fromUtf16(t6))); ushort t7[] = { 0x6b63, 0x9ad4, 0x4e2d, 0x6587, 0x0020, 0x0028, 0x7e41, 0x9ad4, 0x0029, 0 }; m_languages.insert("chinese_taiwan", tr("Chinese (Traditional) - %1").arg(QString::fromUtf16(t7))); ushort t8[] = { 0x010C, 0x65, 0x0161, 0x74, 0x69, 0x6E, 0x61, 0 }; m_languages.insert("czech", tr("Czech - %1").arg(QString::fromUtf16(t8))); ushort t9[] = { 0x52, 0x6F, 0x6D, 0xE2, 0x6E, 0x0103, 0 }; m_languages.insert("romanian", tr("Romanian - %1").arg(QString::fromUtf16(t9))); ushort t10[] = { 0x0E44, 0x0E17, 0x0E22, 0 }; m_languages.insert("thai", tr("Thai - %1").arg(QString::fromUtf16(t10))); ushort t11[] = { 0x0395, 0x03BB, 0x03BB, 0x03B7, 0x03BD, 0x03B9, 0x03BA, 0x03AC, 0}; m_languages.insert("greek", tr("Greek - %1").arg(QString::fromUtf16(t11))); ushort t12[] = { 0x0411, 0x044A, 0x043B, 0x0433, 0x0430, 0x0440, 0x0441, 0x043A, 0x0438, 0 }; m_languages.insert("bulgarian", tr("Bulgarian - %1").arg(QString::fromUtf16(t12))); ushort t13[] = { 0xD55C, 0xAD6D, 0xC5B4, 0}; m_languages.insert("korean", tr("Korean - %1").arg(QString::fromUtf16(t13))); ushort t14[] = { 0x53, 0x6C, 0x6F, 0x76, 0x65, 0x6E, 0x010D, 0x69, 0x6E, 0x61, 0}; m_languages.insert("slovak", tr("Slovak - %1").arg(QString::fromUtf16(t14))); ushort t15[] = { 0x09AC, 0x09BE, 0x0982, 0x09B2, 0x09BE, 0 }; m_languages.insert("bengali", tr("Bengali - %1").arg(QString::fromUtf16(t15))); ushort t16[] = { 0x0641, 0x0627, 0x0631, 0x0633, 0x06CC, 0 }; m_languages.insert("persian", tr("Persian - %1").arg(QString::fromUtf16(t16))); ushort t17[] = {0x53, 0x6C, 0x6F, 0x76, 0x65, 0x6E, 0x0161, 0x010D, 0x69, 0x6E, 0x61, 0 }; m_languages.insert("slovenian", tr("Slovenian - %1").arg(QString::fromUtf16(t17))); ushort t18[] = { 0x092E, 0x0930, 0x093E, 0x0920, 0x0940, 0 }; m_languages.insert("marathi", tr("Marathi - %1").arg(QString::fromUtf16(t18))); ushort t19[] = {0x0443, 0x043A, 0x0440, 0x0430, 0x0457, 0x043D, 0x0441, 0x044C, 0x043A, 0x0430, 0x0020, 0x043C, 0x043E, 0x0432, 0x0430, 0}; m_languages.insert("ukrainian", tr("Ukrainian - %1").arg(QString::fromUtf16(t19))); ushort t20[] = { 0x46, 0x72, 0x61, 0x6E, 0xE7, 0x61, 0x69, 0x73, 0 }; m_languages.insert("french", tr("French - %1").arg(QString::fromUtf16(t20))); ushort t21[] = { 0x45, 0x73, 0x70, 0x61, 0xF1, 0x6F, 0x6C, 0 }; m_languages.insert("spanish", tr("Spanish - %1").arg(QString::fromUtf16(t21))); ushort t22[] = { 0x50, 0x6F, 0x72, 0x74, 0x75, 0x67, 0x75, 0xEA, 0x73, 0x20, 0x28, 0x45, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x75, 0x29, 0 }; m_languages.insert("portuguese_portugal", tr("Portuguese (European)- %1").arg(QString::fromUtf16(t22))); ushort t23[] = { 0x50, 0x6F, 0x72, 0x74, 0x75, 0x67, 0x75, 0xEA, 0x73, 0x20, 0x28, 0x64, 0x6F, 0x20, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6C, 0x29, 0 }; m_languages.insert("portuguese_brazil", tr("Portuguese (Brazilian) - %1").arg(QString::fromUtf16(t23))); ushort t24[] = { 0x54, 0xFC, 0x72, 0x6B, 0xE7, 0x65, 0 }; m_languages.insert("turkish", tr("Turkish - %1").arg(QString::fromUtf16(t24))); ushort t25[] = { 0x043C, 0x0430, 0x043A, 0x0435, 0x0434, 0x043E, 0x043D, 0x0441, 0x043A, 0x0438, 0x20, 0x0458, 0x0430, 0x0437, 0x0438, 0x043A, 0 }; m_languages.insert("macedonian", tr("Macedonian - %1").arg(QString::fromUtf16(t25))); ushort t26[] = { 0x0441, 0x0440, 0x043F, 0x0441, 0x043a, 0x0438, 0x0020, 0x0458, 0x20, 0x0435, 0x0437, 0x0438, 0x043A, 0 }; m_languages.insert("serbian", tr("Serbian - %1").arg(QString::fromUtf16(t26))); ushort t27[] = { 0x0627, 0x0631, 0x062f, 0x0648, 0 }; m_languages.insert("urdu", tr("Urdu - %1").arg(QString::fromUtf16(t27))); } if (m_localeList.count() == 0) { foreach (QFileInfo fileinfo, fileInfoList) { QString name = fileinfo.completeBaseName(); name.replace("fritzing_", ""); QStringList names = name.split("_"); if (names.count() > 1) { name = names[0] + "_" + names[1].toUpper(); } QLocale * locale = new QLocale(name); m_localeList.append(locale); } } } TranslatorListModel::~TranslatorListModel() { } void TranslatorListModel::cleanup() { foreach (QLocale * locale, m_localeList) { delete locale; } m_localeList.clear(); } QVariant TranslatorListModel::data ( const QModelIndex & index, int role) const { if (role == Qt::DisplayRole && index.row() >= 0 && index.row() < m_localeList.count()) { QString languageString = QLocale::languageToString(m_localeList.at(index.row())->language()); QString countryString = QLocale::countryToString(m_localeList.at(index.row())->country()); //DebugDialog::debug(QString("language %1 %2").arg(languageString).arg(countryString)); // QLocale::languageToString() only returns an English string, // so put it through a language-dependent hash table. QString trLanguageString = m_languages.value(languageString.toLower(), ""); if (trLanguageString.isEmpty()) { trLanguageString = m_languages.value(languageString.toLower() + "_" + countryString.toLower(), ""); } if (trLanguageString.isEmpty()) { foreach (QString key, m_languages.keys()) { if (key.startsWith(languageString.toLower())) { return m_languages.value(key); } } return languageString; } return trLanguageString; } return emptyVariant; } int TranslatorListModel::rowCount ( const QModelIndex & parent) const { Q_UNUSED(parent); return m_localeList.count(); } const QLocale * TranslatorListModel::locale( int index) { if (index < 0 || index >= m_localeList.count()) return NULL; return m_localeList.at(index); } int TranslatorListModel::findIndex(const QString & language) { int ix = 0; foreach (QLocale * locale, m_localeList) { //DebugDialog::debug(QString("find index %1 %2").arg(language).arg(locale->name())); if (language.compare(locale->name()) == 0) return ix; ix++; } ix = 0; foreach (QLocale * locale, m_localeList) { if (locale->name().startsWith("en")) return ix; ix++; } return 0; } fritzing-app-0.9.2b/src/dialogs/translatorlistmodel.h000066400000000000000000000032651250202676700230030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef TRANSLATORLISTMODEL_H #define TRANSLATORLISTMODEL_H #include #include #include #include class TranslatorListModel : public QAbstractListModel { Q_OBJECT public: TranslatorListModel(QFileInfoList &, QObject* parent = 0); ~TranslatorListModel(); QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; int rowCount ( const QModelIndex & parent = QModelIndex() ) const ; const QLocale * locale(int index); int findIndex(const QString & language); static void cleanup(); protected: static QList m_localeList; static QHash m_languages; }; #endif fritzing-app-0.9.2b/src/dock/000077500000000000000000000000001250202676700160145ustar00rootroot00000000000000fritzing-app-0.9.2b/src/dock/layerpalette.cpp000066400000000000000000000107161250202676700212200ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "layerpalette.h" #include ViewLayerCheckBox::ViewLayerCheckBox(QWidget * parent) : QCheckBox(parent) { } ViewLayerCheckBox::~ViewLayerCheckBox() { } void ViewLayerCheckBox::setViewLayer(ViewLayer * viewLayer) { m_viewLayer = viewLayer; } ViewLayer * ViewLayerCheckBox::viewLayer() { return m_viewLayer; } ////////////////////////////////////// LayerPalette::LayerPalette(QWidget * parent) : QScrollArea(parent) { m_hideAllLayersAct = m_showAllLayersAct = NULL; QFrame * frame = new QFrame(this); m_mainLayout = new QVBoxLayout(); m_mainLayout->setSizeConstraint( QLayout::SetMinAndMaxSize ); m_mainLayout -> setObjectName("LayerWindowFrame"); for (int i = 0; i < ViewLayer::ViewLayerCount; i++) { ViewLayerCheckBox * cb = new ViewLayerCheckBox(this); connect(cb, SIGNAL(clicked(bool)), this, SLOT(setLayerVisibility(bool))); m_checkBoxes.append(cb); cb -> setObjectName("LayerCheckBox"); cb->setVisible(false); } m_groupBox = new QGroupBox(""); m_groupBox -> setObjectName("LayerWindowList"); QVBoxLayout * groupLayout = new QVBoxLayout(); groupLayout -> setObjectName("LayerWindowBoxes"); m_showAllWidget = new QCheckBox(tr("show all layers")); connect(m_showAllWidget, SIGNAL(clicked(bool)), this, SLOT(setAllLayersVisible(bool))); groupLayout->addWidget(m_showAllWidget); m_groupBox->setLayout(groupLayout); m_mainLayout->addWidget(m_groupBox); frame->setLayout(m_mainLayout); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); this->setWidget(frame); } LayerPalette::~LayerPalette() { } void LayerPalette::resetLayout(LayerHash & viewLayers, LayerList & keys) { m_mainLayout->removeWidget(m_groupBox); foreach (ViewLayerCheckBox * cb, m_checkBoxes) { m_mainLayout->removeWidget(cb); cb->setVisible(false); } int ix = 0; foreach (ViewLayer::ViewLayerID key, keys) { ViewLayer * viewLayer = viewLayers.value(key); //if (viewLayer->parentLayer()) continue; ViewLayerCheckBox * cb = m_checkBoxes[ix++]; cb->setText(viewLayer->action()->text()); cb->setViewLayer(viewLayer); cb->setVisible(true); m_mainLayout->addWidget(cb); } m_mainLayout->addWidget(m_groupBox); m_mainLayout->invalidate(); } void LayerPalette::updateLayerPalette(LayerHash & viewLayers, LayerList & keys) { m_showAllWidget->setEnabled(m_showAllLayersAct->isEnabled() || m_hideAllLayersAct->isEnabled()); m_showAllWidget->setChecked(!m_showAllLayersAct->isEnabled()); int ix = 0; foreach (ViewLayer::ViewLayerID key, keys) { ViewLayer * viewLayer = viewLayers.value(key); //if (viewLayer->parentLayer()) continue; ViewLayerCheckBox * cb = m_checkBoxes[ix++]; cb->setChecked(viewLayer->action()->isChecked()); cb->setEnabled(viewLayer->action()->isEnabled()); } } void LayerPalette::setLayerVisibility(bool) { ViewLayerCheckBox * cb = qobject_cast(sender()); if (cb == NULL) return; // want to toggle layer individually in this case cb->viewLayer()->setIncludeChildLayers(false); cb->viewLayer()->action()->trigger(); cb->viewLayer()->setIncludeChildLayers(true); } void LayerPalette::setShowAllLayersAction(QAction * action) { m_showAllLayersAct = action; } void LayerPalette::setHideAllLayersAction(QAction * action) { m_hideAllLayersAct = action; } void LayerPalette::setAllLayersVisible(bool vis) { if (vis) { if (m_showAllLayersAct) { m_showAllLayersAct->trigger(); } } else { if (m_hideAllLayersAct) { m_hideAllLayersAct->trigger(); } } } fritzing-app-0.9.2b/src/dock/layerpalette.h000066400000000000000000000041251250202676700206620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef LAYERPALETTE_H #define LAYERPALETTE_H #include #include #include #include #include #include #include #include "../viewlayer.h" class ViewLayerCheckBox : public QCheckBox { Q_OBJECT public: ViewLayerCheckBox(QWidget * parent = NULL); ~ViewLayerCheckBox(); void setViewLayer(ViewLayer *); ViewLayer * viewLayer(); protected: ViewLayer * m_viewLayer; }; class LayerPalette : public QScrollArea { Q_OBJECT public: LayerPalette(QWidget * parent = NULL); ~LayerPalette(); void updateLayerPalette(LayerHash & viewLayers, LayerList & keys); void resetLayout(LayerHash & viewLayers, LayerList & keys); void setShowAllLayersAction(QAction *); void setHideAllLayersAction(QAction *); protected slots: void setLayerVisibility(bool vis); void setAllLayersVisible(bool vis); protected: QCheckBox * m_showAllWidget; QList m_checkBoxes; QVBoxLayout * m_mainLayout; QGroupBox * m_groupBox; QAction *m_showAllLayersAct; QAction *m_hideAllLayersAct; }; #endif fritzing-app-0.9.2b/src/eagle/000077500000000000000000000000001250202676700161515ustar00rootroot00000000000000fritzing-app-0.9.2b/src/eagle/fritzing2eagle.cpp000066400000000000000000000031731250202676700215750ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6469 $: $Author: irascibl@gmail.com $: $Date: 2012-09-23 00:54:30 +0200 (So, 23. Sep 2012) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include "../items/itembase.h" #include "../sketch/pcbsketchwidget.h" #include "fritzing2eagle.h" Fritzing2Eagle* Fritzing2Eagle::singleton = NULL; Fritzing2Eagle::Fritzing2Eagle(PCBSketchWidget *m_pcbGraphicsView) { QList partList; m_pcbGraphicsView->collectParts(partList); singleton = this; } /* void Fritzing2Eagle::showOutputInfo(PCBSketchWidget m_pcbGraphicsView) { if (singleton == NULL) { new Fritzing2Eagle(); } } */ fritzing-app-0.9.2b/src/eagle/fritzing2eagle.h000066400000000000000000000025221250202676700212370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FRITZING2EAGLE_H #define FRITZING2EAGLE_H #include #include class Fritzing2Eagle { // Q_OBJECT public: Fritzing2Eagle(PCBSketchWidget *m_pcbGraphicsView); /* public: static void showOutputInfo(PCBSketchWidget m_pcbGraphicsView); */ protected: static Fritzing2Eagle* singleton; }; #endif fritzing-app-0.9.2b/src/fapplication.cpp000066400000000000000000001710251250202676700202570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6975 $: $Author: irascibl@gmail.com $: $Date: 2013-04-19 12:51:22 +0200 (Fr, 19. Apr 2013) $ ********************************************************************/ #include "fapplication.h" #include "debugdialog.h" #include "utils/misc.h" #include "mainwindow/mainwindow.h" #include "fsplashscreen.h" #include "version/version.h" #include "dialogs/prefsdialog.h" #include "fsvgrenderer.h" #include "version/versionchecker.h" #include "version/updatedialog.h" #include "itemdrag.h" #include "items/wire.h" #include "partsbinpalette/binmanager/binmanager.h" #include "help/tipsandtricks.h" #include "utils/folderutils.h" #include "utils/lockmanager.h" #include "utils/fmessagebox.h" #include "dialogs/translatorlistmodel.h" #include "partsbinpalette/partsbinview.h" #include "partsbinpalette/svgiconwidget.h" #include "partsbinpalette/partsbinpalettewidget.h" #include "items/moduleidnames.h" #include "partsbinpalette/searchlineedit.h" #include "utils/ratsnestcolors.h" #include "utils/cursormaster.h" #include "utils/textutils.h" #include "utils/graphicsutils.h" #include "infoview/htmlinfoview.h" #include "svg/gedaelement2svg.h" #include "svg/kicadmodule2svg.h" #include "svg/kicadschematic2svg.h" #include "svg/gerbergenerator.h" #include "installedfonts.h" #include "items/pinheader.h" #include "items/partfactory.h" #include "items/propertydef.h" #include "dialogs/recoverydialog.h" #include "processeventblocker.h" #include "autoroute/panelizer.h" #include "sketch/sketchwidget.h" #include "sketch/pcbsketchwidget.h" #include "help/firsttimehelpdialog.h" #include "help/aboutbox.h" // dependency injection :P #include "referencemodel/sqlitereferencemodel.h" #define CurrentReferenceModel SqliteReferenceModel #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LINUX_32 #define PLATFORM_NAME "linux-32bit" #endif #ifdef LINUX_64 #define PLATFORM_NAME "linux-64bit" #endif #ifdef Q_OS_WIN #ifdef WIN64 #define PLATFORM_NAME "windows-64bit" #else #define PLATFORM_NAME "windows" #endif #endif #ifdef Q_OS_MAC #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) || defined(QT_MAC_USE_COCOA) #define PLATFORM_NAME "mac-os-x-105" #else #define PLATFORM_NAME "mac-os-x-104" #endif #endif #ifdef Q_OS_WIN #ifndef QT_NO_DEBUG #define WIN_DEBUG #endif #endif static const double LoadProgressStart = 0.085; static const double LoadProgressEnd = 0.6; //////////////////////////////////////////////////// FServer::FServer(QObject *parent) : QTcpServer(parent) { } void FServer::incomingConnection(int socketDescriptor) { emit newConnection(socketDescriptor); } //////////////////////////////////////////////////// QMutex FServerThread::m_busy; FServerThread::FServerThread(int socketDescriptor, QObject *parent) : QThread(parent), m_socketDescriptor(socketDescriptor) { } void FServerThread::run() { QTcpSocket * socket = new QTcpSocket(); if (!socket->setSocketDescriptor(m_socketDescriptor)) { emit error(socket->error()); DebugDialog::debug(QString("Socket error %1 %2").arg(socket->error()).arg(socket->errorString())); socket->deleteLater(); return; } socket->waitForReadyRead(); QString header; while (socket->canReadLine()) { header += socket->readLine(); } DebugDialog::debug("header " + header); QStringList tokens = header.split(QRegExp("[ \r\n][ \r\n]*"), QString::SkipEmptyParts); if (tokens.count() <= 0) { writeResponse(socket, 400, "Bad Request", "", ""); return; } if (tokens[0] != "GET") { writeResponse(socket, 405, "Method Not Allowed", "", ""); return; } if (tokens.count() < 2) { writeResponse(socket, 400, "Bad Request", "", ""); return; } QStringList params = tokens.at(1).split("/", QString::SkipEmptyParts); QString command = params.takeFirst(); if (params.count() == 0) { writeResponse(socket, 400, "Bad Request", "", ""); return; } QString subFolder = params.join("/"); bool fixSubFolder = false; QString mimeType; if (command == "svg") { mimeType = "image/svg+xml"; } else if (command == "gerber") { } else if (command == "svg-tcp") { fixSubFolder = true; } else if (command == "gerber-tcp") { fixSubFolder = true; } else { writeResponse(socket, 400, "Bad Request", "", ""); return; } if (fixSubFolder) { // replace "/" that was removed from "http:/blah" above int ix = subFolder.indexOf(":/"); if (ix >= 0) { subFolder.insert(ix + 1, "/"); } } int waitInterval = 100; // 100ms to wait int timeoutSeconds = 2 * 60; // timeout after 2 minutes int attempts = timeoutSeconds * 1000 / waitInterval; // timeout a bool gotLock = false; for (int i = 0; i < attempts; i++) { if (m_busy.tryLock()) { gotLock = true; break; } } if (!gotLock) { writeResponse(socket, 503, "Service Unavailable", "", "Server busy."); return; } DebugDialog::debug(QString("emitting do command %1 %2").arg(command).arg(subFolder)); QString result; int status; emit doCommand(command, subFolder, result, status); m_busy.unlock(); if (status != 200) { writeResponse(socket, status, "failed", "", result); } else if (command.endsWith("tcp")) { QString filename = result; mimeType = "application/zip"; QFile file(filename); if (file.open(QFile::ReadOnly)) { QString response = QString("HTTP/1.0 %1 %2\r\n").arg(200).arg("ok"); response += QString("Content-Type: %1; charset=\"utf-8\"\r\n").arg(mimeType); response += QString("Content-Length: %1\r\n").arg(file.size()); response += QString("\r\n"); socket->write(response.toUtf8()); int buffersize = 8192; long remaining = file.size(); while (remaining >= buffersize) { QByteArray bytes = file.read(buffersize); socket->write(bytes); remaining -= buffersize; } if (remaining > 0) { QByteArray bytes = file.read(remaining); socket->write(bytes); } socket->disconnectFromHost(); socket->waitForDisconnected(); socket->deleteLater(); file.close(); } else { writeResponse(socket, 500, "failed", "", "local zip failure (2)"); } QFileInfo info(filename); QDir dir = info.dir(); FolderUtils::rmdir(dir); } else { writeResponse(socket, 200, "Ok", mimeType, result); } } void FServerThread::writeResponse(QTcpSocket * socket, int code, const QString & codeString, const QString & mimeType, const QString & message) { QString type = mimeType; if (type.isEmpty()) type = "text/plain"; QString response = QString("HTTP/1.0 %1 %2\r\n").arg(code).arg(codeString); response += QString("Content-Type: %1; charset=\"utf-8\"\r\n").arg(type); response += QString("Content-Length: %1\r\n").arg(message.count()); response += QString("\r\n%1").arg(message); socket->write(response.toUtf8()); socket->disconnectFromHost(); socket->waitForDisconnected(); socket->deleteLater(); } //////////////////////////////////////////////////// FApplication::FApplication( int & argc, char ** argv) : QApplication(argc, argv) { m_fServer = NULL; m_spaceBarIsPressed = false; m_mousePressed = false; m_referenceModel = NULL; m_started = false; m_updateDialog = NULL; m_lastTopmostWindow = NULL; m_serviceType = NoService; m_splash = NULL; m_arguments = arguments(); } bool FApplication::init() { //foreach (QString argument, m_arguments) { //DebugDialog::debug(QString("argument %1").arg(argument)); //} m_serviceType = NoService; QList toRemove; for (int i = 0; i < m_arguments.length(); i++) { if ((m_arguments[i].compare("-h", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-help", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--help", Qt::CaseInsensitive) == 0)) { return false; } if ((m_arguments[i].compare("-e", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-examples", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--examples", Qt::CaseInsensitive) == 0)) { DebugDialog::setEnabled(true); m_serviceType = ExampleService; m_outputFolder = " "; // otherwise program will bail out toRemove << i; } if ((m_arguments[i].compare("-d", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-debug", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--debug", Qt::CaseInsensitive) == 0)) { DebugDialog::setEnabled(true); toRemove << i; } if (i + 1 >= m_arguments.length()) continue; if ((m_arguments[i].compare("-f", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-folder", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--folder", Qt::CaseInsensitive) == 0)) { FolderUtils::setApplicationPath(m_arguments[i + 1]); // delete these so we don't try to process them as files later toRemove << i << i + 1; } if ((m_arguments[i].compare("-geda", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--geda", Qt::CaseInsensitive) == 0)) { m_serviceType = GedaService; m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } //if ((m_arguments[i].compare("-drc", Qt::CaseInsensitive) == 0) || // (m_arguments[i].compare("--drc", Qt::CaseInsensitive) == 0)) { // m_serviceType = DRCService; // m_outputFolder = m_arguments[i + 1]; // toRemove << i << i + 1; //} if ((m_arguments[i].compare("-db", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-database", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--database", Qt::CaseInsensitive) == 0)) { m_serviceType = DatabaseService; m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } if ((m_arguments[i].compare("-kicad", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--kicad", Qt::CaseInsensitive) == 0)) { m_serviceType = KicadFootprintService; m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } if ((m_arguments[i].compare("-kicadschematic", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--kicadschematic", Qt::CaseInsensitive) == 0)) { m_serviceType = KicadSchematicService; m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } if ((m_arguments[i].compare("-svg", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--svg", Qt::CaseInsensitive) == 0)) { m_serviceType = SvgService; DebugDialog::setEnabled(true); m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } if ((m_arguments[i].compare("-port", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("--port", Qt::CaseInsensitive) == 0)) { DebugDialog::setEnabled(true); bool ok; int p = m_arguments[i + 1].toInt(&ok); if (ok) { m_portNumber = p; } toRemove << i << i + 1; if (i + 2 < m_arguments.count()) { if (ok) { m_portRootFolder = m_arguments[i + 2]; m_serviceType = PortService; } toRemove << i + 2; } m_outputFolder = m_arguments[i + 1]; } if ((m_arguments[i].compare("-g", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-gerber", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--gerber", Qt::CaseInsensitive) == 0)) { m_serviceType = GerberService; DebugDialog::setEnabled(true); m_outputFolder = m_arguments[i + 1]; toRemove << i << i + 1; } if ((m_arguments[i].compare("-p", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-panel", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--panel", Qt::CaseInsensitive) == 0)) { m_serviceType = PanelizerService; m_panelFilename = m_arguments[i + 1]; m_outputFolder = " "; // otherwise program will bail out m_panelizerCustom = false; toRemove << i << i + 1; } if ((m_arguments[i].compare("-pc", Qt::CaseInsensitive) == 0)) { m_serviceType = PanelizerService; m_panelFilename = m_arguments[i + 1]; m_outputFolder = " "; // otherwise program will bail out m_panelizerCustom = true; toRemove << i << i + 1; } if ((m_arguments[i].compare("-i", Qt::CaseInsensitive) == 0) || (m_arguments[i].compare("-inscription", Qt::CaseInsensitive) == 0)|| (m_arguments[i].compare("--inscription", Qt::CaseInsensitive) == 0)) { m_serviceType = InscriptionService; m_panelFilename = m_arguments[i + 1]; m_outputFolder = " "; // otherwise program will bail out toRemove << i << i + 1; } if (m_arguments[i].compare("-ep", Qt::CaseInsensitive) == 0) { m_externalProcessPath = m_arguments[i + 1]; toRemove << i << i + 1; } if (m_arguments[i].compare("-eparg", Qt::CaseInsensitive) == 0) { m_externalProcessArgs << m_arguments[i + 1]; toRemove << i << i + 1; } if (m_arguments[i].compare("-epname", Qt::CaseInsensitive) == 0) { m_externalProcessName = m_arguments[i + 1]; toRemove << i << i + 1; } } while (toRemove.count() > 0) { int ix = toRemove.takeLast(); m_arguments.removeAt(ix); } m_started = false; m_updateDialog = NULL; m_lastTopmostWindow = NULL; connect(&m_activationTimer, SIGNAL(timeout()), this, SLOT(updateActivation())); m_activationTimer.setInterval(10); m_activationTimer.setSingleShot(true); QCoreApplication::setOrganizationName("Fritzing"); QCoreApplication::setOrganizationDomain("fritzing.org"); QCoreApplication::setApplicationName("Fritzing"); installEventFilter(this); // tell app where to search for plugins (jpeg export and sql lite) m_libPath = FolderUtils::getLibraryPath(); QApplication::addLibraryPath(m_libPath); /*QFile file("libpath.txt"); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << m_libPath; file.close(); }*/ // !!! translator must be installed before any widgets are created !!! m_translationPath = FolderUtils::getApplicationSubFolderPath("translations"); bool loaded = findTranslator(m_translationPath); Q_UNUSED(loaded); Q_INIT_RESOURCE(phoenixresources); MainWindow::initNames(); FSvgRenderer::initNames(); ViewLayer::initNames(); RatsnestColors::initNames(); Wire::initNames(); ItemBase::initNames(); ViewLayer::initNames(); Connector::initNames(); BinManager::initNames(); PaletteModel::initNames(); SvgIconWidget::initNames(); PinHeader::initNames(); CursorMaster::initCursors(); #ifdef Q_OS_MAC #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) || defined(QT_MAC_USE_COCOA) m_buildType = " Cocoa"; #else m_buildType = " Carbon"; #endif #else m_buildType = QString(PLATFORM_NAME).contains("64") ? "64" : "32"; #endif AboutBox::initBuildType(m_buildType); return true; } FApplication::~FApplication(void) { cleanupBackups(); clearModels(); if (m_updateDialog) { delete m_updateDialog; } FSvgRenderer::cleanup(); ViewLayer::cleanup(); ViewLayer::cleanup(); ItemBase::cleanup(); Wire::cleanup(); DebugDialog::cleanup(); ItemDrag::cleanup(); Version::cleanup(); TipsAndTricks::cleanup(); FirstTimeHelpDialog::cleanup(); TranslatorListModel::cleanup(); FolderUtils::cleanup(); SearchLineEdit::cleanup(); RatsnestColors::cleanup(); HtmlInfoView::cleanup(); SvgIconWidget::cleanup(); PartFactory::cleanup(); PartsBinView::cleanup(); PropertyDefMaster::cleanup(); CursorMaster::cleanup(); LockManager::cleanup(); PartsBinPaletteWidget::cleanup(); } void FApplication::clearModels() { if (m_referenceModel) { m_referenceModel->clearPartHash(); delete m_referenceModel; } } bool FApplication::spaceBarIsPressed() { return ((FApplication *) qApp)->m_spaceBarIsPressed; } bool FApplication::eventFilter(QObject *obj, QEvent *event) { // check whether the space bar is down. //qDebug() << "event" << event->type(); Q_UNUSED(obj); switch (event->type()) { case QEvent::MouseButtonPress: //DebugDialog::debug("button press"); m_mousePressed = true; break; case QEvent::MouseButtonRelease: //DebugDialog::debug("button release"); m_mousePressed = false; break; case QEvent::Drop: // at least under Windows, the MouseButtonRelease event is not triggered if the Drop event is triggered m_mousePressed = false; break; case QEvent::KeyPress: { //DebugDialog::debug(QString("key pressed %1 %2").arg(m_mousePressed).arg(QApplication::mouseButtons())); if (!m_mousePressed && !m_spaceBarIsPressed) { QKeyEvent * kevent = static_cast(event); if (!kevent->isAutoRepeat() && (kevent->key() == Qt::Key_Space)) { m_spaceBarIsPressed = true; //DebugDialog::debug("spacebar pressed"); CursorMaster::instance()->block(); setOverrideCursor(Qt::OpenHandCursor); emit spaceBarIsPressedSignal(true); } } } break; case QEvent::KeyRelease: { //DebugDialog::debug(QString("key released %1 %2").arg(m_mousePressed).arg(QApplication::mouseButtons())); if (m_spaceBarIsPressed) { QKeyEvent * kevent = static_cast(event); if (!kevent->isAutoRepeat() && (kevent->key() == Qt::Key_Space)) { m_spaceBarIsPressed = false; //DebugDialog::debug("spacebar pressed"); restoreOverrideCursor(); CursorMaster::instance()->unblock(); emit spaceBarIsPressedSignal(false); } } } break; default: break; } return false; } bool FApplication::event(QEvent *event) { switch (event->type()) { case QEvent::FileOpen: { QString path = static_cast(event)->file(); DebugDialog::debug(QString("file open %1").arg(path)); if (m_started) { loadNew(path); } else { m_filesToLoad.append(path); } } return true; default: return QApplication::event(event); } } bool FApplication::findTranslator(const QString & translationsPath) { QSettings settings; QString suffix = settings.value("language").toString(); if (suffix.isEmpty()) { suffix = QLocale::system().name(); // Returns the language and country of this locale as a string of the form "language_country", where language is a lowercase, two-letter ISO 639 language code, and country is an uppercase, two-letter ISO 3166 country code. } else { QLocale::setDefault(QLocale(suffix)); } bool loaded = m_translator.load(QString("fritzing_") + suffix.toLower(), translationsPath); DebugDialog::debug(QString("translation %1 loaded %2 from %3").arg(suffix).arg(loaded).arg(translationsPath)); if (loaded) { QApplication::installTranslator(&m_translator); } return loaded; } void FApplication::registerFonts() { registerFont(":/resources/fonts/DroidSans.ttf", true); registerFont(":/resources/fonts/DroidSans-Bold.ttf", false); registerFont(":/resources/fonts/DroidSansMono.ttf", false); registerFont(":/resources/fonts/OCRA.ttf", true); // "Droid Sans" // "Droid Sans Mono" /* QFontDatabase database; QStringList families = database.families ( ); foreach (QString string, families) { DebugDialog::debug(string); // should print out the name of the fonts you loaded } */ } ReferenceModel * FApplication::loadReferenceModel(const QString & databaseName, bool fullLoad) { m_referenceModel = new CurrentReferenceModel(); ItemBase::setReferenceModel(m_referenceModel); connect(m_referenceModel, SIGNAL(loadedPart(int, int)), this, SLOT(loadedPart(int, int))); bool dbExists = false; QDir * dir = FolderUtils::getApplicationSubFolder("parts"); QString dbPath; if (dir) { dbPath = dir->absoluteFilePath("parts.db"); QFileInfo info(dbPath); dbExists = info.exists(); } bool ok = m_referenceModel->loadAll(databaseName, fullLoad, dbExists); // loads local parts, resource parts, and any other parts in files not in the db--these part override db parts with the same moduleID if (ok && databaseName.isEmpty()) { if (dir == NULL) { } else { QFile file(dir->absoluteFilePath("parts.db")); if (file.exists()) { m_referenceModel->loadFromDB(dbPath); } } } delete dir; return m_referenceModel; } MainWindow * FApplication::openWindowForService(bool lockFiles, int initialTab) { // our MainWindows use WA_DeleteOnClose so this has to be added to the heap (via new) rather than the stack (for local vars) MainWindow * mainWindow = MainWindow::newMainWindow(m_referenceModel, "", false, lockFiles, initialTab); // this is also slow mainWindow->setReportMissingModules(false); mainWindow->noBackup(); mainWindow->noSchematicConversion(); return mainWindow; } int FApplication::serviceStartup() { if (m_outputFolder.isEmpty()) { return -1; } switch (m_serviceType) { case PortService: initService(); { MainWindow * sketch = MainWindow::newMainWindow(m_referenceModel, "", true, true, -1); if (sketch) { sketch->show(); sketch->clearFileProgressDialog(); } } return 1; case GedaService: runGedaService(); return 0; case DRCService: runDRCService(); return 0; case DatabaseService: runDatabaseService(); return 0; case KicadFootprintService: runKicadFootprintService(); return 0; case KicadSchematicService: runKicadSchematicService(); return 0; case GerberService: runGerberService(); return 0; case SvgService: runSvgService(); return 0; case PanelizerService: runPanelizerService(); return 0; case InscriptionService: runInscriptionService(); return 0; case ExampleService: runExampleService(); return 0; default: DebugDialog::debug("unknown service"); return -1; } } void FApplication::runGerberService() { initService(); runGerberServiceAux(); } void FApplication::runGerberServiceAux() { QDir dir(m_outputFolder); QString s = dir.absolutePath(); QStringList filters; filters << "*" + FritzingBundleExtension; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); MainWindow * mainWindow = openWindowForService(false, 3); m_started = true; FolderUtils::setOpenSaveFolderAux(m_outputFolder); if (mainWindow->loadWhich(filepath, false, false, false, "")) { QFileInfo info(filepath); GerberGenerator::exportToGerber(info.completeBaseName(), m_outputFolder, NULL, mainWindow->pcbView(), false); } mainWindow->setCloseSilently(true); mainWindow->close(); } } void FApplication::initService() { createUserDataStoreFolderStructure(); registerFonts(); loadReferenceModel("", false); } void FApplication::runSvgService() { initService(); runSvgServiceAux(); } void FApplication::runSvgServiceAux() { QDir dir(m_outputFolder); QString s = dir.absolutePath(); QStringList filters; filters << "*" + FritzingBundleExtension; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); MainWindow * mainWindow = openWindowForService(false, -1); m_started = true; FolderUtils::setOpenSaveFolderAux(m_outputFolder); if (mainWindow->loadWhich(filepath, false, false, false, "")) { QFileInfo info(filepath); QList ids; ids << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; foreach (ViewLayer::ViewID id, ids) { QString fn = QString("%1_%2.svg").arg(info.completeBaseName()).arg(ViewLayer::viewIDNaturalName(id)); QString svgPath = dir.absoluteFilePath(fn); mainWindow->setCurrentView(id); mainWindow->exportSvg(GraphicsUtils::StandardFritzingDPI, false, false, svgPath); } } mainWindow->setCloseSilently(true); mainWindow->close(); } } void FApplication::runDatabaseService() { createUserDataStoreFolderStructure(); DebugDialog::setEnabled(true); QDir * parent = FolderUtils::getApplicationSubFolder("pdb"); QFileInfoList dirs = parent->entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); delete parent; QStringList nameFilters; nameFilters << ("*" + FritzingPartExtension); foreach (QFileInfo dirInfo, dirs) { if (!dirInfo.isDir()) continue; QDir dir(dirInfo.absoluteFilePath()); QFileInfoList files = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); foreach (QFileInfo fileInfo, files) { QString path = fileInfo.absoluteFilePath(); QString newPath = path; newPath.replace("/pdb/", "/parts/"); QFile::rename(path, newPath); } } QFile::remove(m_outputFolder); loadReferenceModel(m_outputFolder, true); // m_outputFolder is actually a full path ending in ".db" } void FApplication::runGedaService() { try { QDir dir(m_outputFolder); QStringList filters; filters << "*.fp"; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); QString newfilepath = filepath; newfilepath.replace(".fp", ".svg"); GedaElement2Svg geda; QString svg = geda.convert(filepath, false); TextUtils::writeUtf8(newfilepath, svg); } } catch (const QString & msg) { DebugDialog::debug(msg); } catch (...) { DebugDialog::debug("who knows"); } } void FApplication::runDRCService() { m_started = true; initService(); DebugDialog::setEnabled(true); try { QDir dir(m_outputFolder); QStringList filters; filters << "*.fzz"; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); MainWindow * mainWindow = openWindowForService(false, 3); if (mainWindow == NULL) continue; mainWindow->setCloseSilently(true); if (!mainWindow->loadWhich(filepath, false, false, false, "")) { DebugDialog::debug(QString("failed to load '%1'").arg(filepath)); mainWindow->close(); delete mainWindow; continue; } mainWindow->showPCBView(); int moved = mainWindow->pcbView()->checkLoadedTraces(); if (moved > 0) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("%1 wires moved from their saved position in %2.").arg(moved).arg(filepath)); DebugDialog::debug(QString("\ncheckloadedtraces %1\n").arg(filepath)); } Panelizer::checkDonuts(mainWindow, true); Panelizer::checkText(mainWindow, true); QList boards = mainWindow->pcbView()->findBoard(); foreach (ItemBase * boardItem, boards) { mainWindow->pcbView()->selectAllItems(false, false); boardItem->setSelected(true); mainWindow->newDesignRulesCheck(false); } mainWindow->close(); delete mainWindow; } } catch (const QString & msg) { DebugDialog::debug(msg); } catch (...) { DebugDialog::debug("who knows"); } } void FApplication::runKicadFootprintService() { QDir dir(m_outputFolder); QStringList filters; filters << "*.mod"; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); QStringList moduleNames = KicadModule2Svg::listModules(filepath); foreach (QString moduleName, moduleNames) { KicadModule2Svg kicad; try { QString svg = kicad.convert(filepath, moduleName, false); if (svg.isEmpty()) { DebugDialog::debug("svg is empty " + filepath + " " + moduleName); continue; } foreach (QChar c, QString("<>:\"/\\|?*")) { moduleName.remove(c); } QString newFilePath = dir.absoluteFilePath(moduleName + "_" + filename); newFilePath.replace(".mod", ".svg"); if (!TextUtils::writeUtf8(newFilePath, svg)) { DebugDialog::debug("unable to open file " + newFilePath); } } catch (const QString & msg) { DebugDialog::debug(msg); } catch (...) { DebugDialog::debug("who knows"); } } } } void FApplication::runKicadSchematicService() { QDir dir(m_outputFolder); QStringList filters; filters << "*.lib"; QStringList filenames = dir.entryList(filters, QDir::Files); foreach (QString filename, filenames) { QString filepath = dir.absoluteFilePath(filename); QStringList defNames = KicadSchematic2Svg::listDefs(filepath); foreach (QString defName, defNames) { KicadSchematic2Svg kicad; try { QString svg = kicad.convert(filepath, defName); if (svg.isEmpty()) { DebugDialog::debug("svg is empty " + filepath + " " + defName); continue; } foreach (QChar c, QString("<>:\"/\\|?*")) { defName.remove(c); } //DebugDialog::debug(QString("converting %1 %2").arg(defName).arg(filename)); QString newFilePath = dir.absoluteFilePath(defName + "_" + filename); newFilePath.replace(".lib", ".svg"); QFile file(newFilePath); if (!TextUtils::writeUtf8(newFilePath, svg)) { DebugDialog::debug("unable to open file " + newFilePath); } } catch (const QString & msg) { DebugDialog::debug(msg); } catch (...) { DebugDialog::debug("who knows"); } } } } int FApplication::startup() { //DebugDialog::setEnabled(true); QString splashName = ":/resources/images/splash/splash_screen_start.png"; QDateTime now = QDateTime::currentDateTime(); if (now.date().month() == 4 && now.date().day() == 1) { QString aSplashName = ":/resources/images/splash/april1st.png"; QFileInfo info(aSplashName); if (info.exists()) { splashName = aSplashName; } } QPixmap pixmap(splashName); FSplashScreen splash(pixmap); m_splash = &splash; ProcessEventBlocker::processEvents(); // seems to need this (sometimes?) to display the splash screen initSplash(splash); ProcessEventBlocker::processEvents(); // DebugDialog::debug("Data Location: "+QDesktopServices::storageLocation(QDesktopServices::DataLocation)); registerFonts(); if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, LoadProgressStart); ProcessEventBlocker::processEvents(); #ifdef Q_OS_WIN // associate .fz file with fritzing app on windows (xp only--vista is different) // TODO: don't change settings if they're already set? // TODO: only do this at install time? QSettings settings1("HKEY_CLASSES_ROOT\\Fritzing", QSettings::NativeFormat); settings1.setValue(".", "Fritzing Application"); foreach (QString extension, fritzingExtensions()) { QSettings settings2("HKEY_CLASSES_ROOT\\" + extension, QSettings::NativeFormat); settings2.setValue(".", "Fritzing"); } QSettings settings3("HKEY_CLASSES_ROOT\\Fritzing\\shell\\open\\command", QSettings::NativeFormat); settings3.setValue(".", QString("\"%1\" \"%2\"") .arg(QDir::toNativeSeparators(QApplication::applicationFilePath())) .arg("%1") ); #endif cleanFzzs(); createUserDataStoreFolderStructure(); loadReferenceModel("", false); QString prevVersion; { // put this in a block so that QSettings is closed QSettings settings; prevVersion = settings.value("version").toString(); QString currVersion = Version::versionString(); if(prevVersion != currVersion) { QVariant pid = settings.value("pid"); QVariant language = settings.value("language"); settings.clear(); if (!pid.isNull()) { settings.setValue("pid", pid); } if (!language.isNull()) { settings.setValue("language", language); } } } //bool fabEnabled = settings.value(ORDERFABENABLED, QVariant(false)).toBool(); //if (!fabEnabled) { QNetworkAccessManager * manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(gotOrderFab(QNetworkReply *))); manager->get(QNetworkRequest(QUrl(QString("http://fab.fritzing.org/launched%1").arg(Version::makeRequestParamsString(true))))); //} if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, LoadProgressEnd); //DebugDialog::debug("after createUserDataStoreFolderStructure"); if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.65); ProcessEventBlocker::processEvents(); if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.825); ProcessEventBlocker::processEvents(); m_updateDialog = new UpdateDialog(); connect(m_updateDialog, SIGNAL(enableAgainSignal(bool)), this, SLOT(enableCheckUpdates(bool))); checkForUpdates(false); if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.875); DebugDialog::debug("load something"); loadSomething(prevVersion); m_started = true; if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.99); ProcessEventBlocker::processEvents(); m_splash = NULL; return 0; } void FApplication::registerFont(const QString &fontFile, bool reallyRegister) { int id = QFontDatabase::addApplicationFont(fontFile); if(id > -1 && reallyRegister) { QStringList familyNames = QFontDatabase::applicationFontFamilies(id); QFileInfo finfo(fontFile); foreach (QString family, familyNames) { InstalledFonts::InstalledFontsNameMapper.insert(family, finfo.completeBaseName()); InstalledFonts::InstalledFontsList << family; DebugDialog::debug(QString("registering font family: %1 %2").arg(family).arg(finfo.completeBaseName())); } } } void FApplication::finish() { QString currVersion = Version::versionString(); QSettings settings; settings.setValue("version", currVersion); } void FApplication::loadNew(QString path) { MainWindow * mw = MainWindow::newMainWindow(m_referenceModel, path, true, true, -1); if (!mw->loadWhich(path, false, true, true, "")) { mw->close(); } mw->clearFileProgressDialog(); } void FApplication::loadOne(MainWindow * mw, QString path, int loaded) { if (loaded == 0) { mw->showFileProgressDialog(path); mw->loadWhich(path, true, true, true, ""); } else { loadNew(path); } } void FApplication::preferences() { // delay keeps OS 7 from crashing? QTimer::singleShot(30, this, SLOT(preferencesAfter())); } void FApplication::preferencesAfter() { QDir dir(m_translationPath); QStringList nameFilters; nameFilters << "*.qm"; QFileInfoList languages = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); QSettings settings; QString language = settings.value("language").toString(); if (language.isEmpty()) { language = QLocale::system().name(); } MainWindow * mainWindow = NULL; foreach (MainWindow * mw, orderedTopLevelMainWindows()) { mainWindow = mw; break; } if (mainWindow == NULL) return; // shouldn't happen (maybe on the mac) PrefsDialog prefsDialog(language, NULL); // TODO: use the topmost MainWindow as parent int ix = 0; foreach (SketchWidget * sketchWidget, mainWindow->sketchWidgets()) { prefsDialog.initViewInfo(ix++, sketchWidget->viewName(), sketchWidget->getShortName(), sketchWidget->curvyWires()); } QList platforms = mainWindow->programmingWidget()->getAvailablePlatforms(); prefsDialog.initLayout(languages, platforms); if (QDialog::Accepted == prefsDialog.exec()) { updatePrefs(prefsDialog); } } void FApplication::updatePrefs(PrefsDialog & prefsDialog) { QSettings settings; if (prefsDialog.cleared()) { settings.clear(); return; } QHash hash = prefsDialog.settings(); QList mainWindows = orderedTopLevelMainWindows(); foreach (QString key, hash.keys()) { settings.setValue(key, hash.value(key)); if (key.compare("connectedColor") == 0) { QColor c(hash.value(key)); ItemBase::setConnectedColor(c); foreach (MainWindow * mainWindow, mainWindows) { mainWindow->redrawSketch(); } } else if (key.compare("unconnectedColor") == 0) { QColor c(hash.value(key)); ItemBase::setUnconnectedColor(c); foreach (MainWindow * mainWindow, mainWindows) { mainWindow->redrawSketch(); } } else if (key.compare("wheelMapping") == 0) { ZoomableGraphicsView::setWheelMapping((ZoomableGraphicsView::WheelMapping) hash.value(key).toInt()); } else if (key.compare("autosavePeriod") == 0) { MainWindow::setAutosavePeriod(hash.value(key).toInt()); } else if (key.compare("autosaveEnabled") == 0) { MainWindow::setAutosaveEnabled(hash.value(key).toInt()); } else if (key.contains("curvy", Qt::CaseInsensitive)) { foreach (MainWindow * mainWindow, mainWindows) { foreach (SketchWidget * sketchWidget, mainWindow->sketchWidgets()) { if (key.contains(sketchWidget->getShortName())) { sketchWidget->setCurvyWires(hash.value(key).compare("1") == 0); } } } } } } void FApplication::initSplash(FSplashScreen & splash) { QPixmap logo(":/resources/images/splash/fhp_logo_small.png"); QPixmap progress(":/resources/images/splash/splash_progressbar.png"); m_progressIndex = splash.showPixmap(progress, "progress"); if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0); // put this above the progress indicator splash.showPixmap(logo, "fhpLogo"); QString msg1 = QObject::tr("" "© 2007-%1 Fachhochschule Potsdam" "") .arg(Version::year()); splash.showMessage(msg1, "fhpText", Qt::AlignLeft | Qt::AlignTop); QString msg2 = QObject::tr("" "Version %1.%2.%3 (%4%5) %6" "") .arg(Version::majorVersion()) .arg(Version::minorVersion()) .arg(Version::minorSubVersion()) .arg(Version::modifier()) .arg(Version::shortDate()) .arg(m_buildType); splash.showMessage(msg2, "versionText", Qt::AlignRight | Qt::AlignTop); splash.show(); } struct Thing { QString moduleID; ViewLayer::ViewID viewID; ViewLayer::ViewLayerID viewLayerID; }; void FApplication::checkForUpdates() { checkForUpdates(true); } void FApplication::checkForUpdates(bool atUserRequest) { if (atUserRequest) { enableCheckUpdates(false); } VersionChecker * versionChecker = new VersionChecker(); QSettings settings; if (!atUserRequest) { // if I've already been notified about these updates, don't bug me again QString lastMainVersionChecked = settings.value("lastMainVersionChecked").toString(); if (!lastMainVersionChecked.isEmpty()) { versionChecker->ignore(lastMainVersionChecked, false); } QString lastInterimVersionChecked = settings.value("lastInterimVersionChecked").toString(); if (!lastInterimVersionChecked.isEmpty()) { versionChecker->ignore(lastInterimVersionChecked, true); } } QString atom = QString("http://fritzing.org/download/feed/atom/%1/%2") .arg(PLATFORM_NAME) .arg(Version::makeRequestParamsString(true)); DebugDialog::debug(atom); versionChecker->setUrl(atom); m_updateDialog->setAtUserRequest(atUserRequest); m_updateDialog->setVersionChecker(versionChecker); if (atUserRequest) { m_updateDialog->show(); } } void FApplication::enableCheckUpdates(bool enabled) { //DebugDialog::debug("before enable check updates"); foreach (QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWindow = qobject_cast(widget); if (mainWindow) { mainWindow->enableCheckUpdates(enabled); } } //DebugDialog::debug("after enable check updates"); } void FApplication::createUserDataStoreFolderStructure() { // make sure that the folder structure for parts and bins, exists QString userDataStorePath = FolderUtils::getUserDataStorePath(); QDir dataStore(userDataStorePath); QStringList dataFolders = FolderUtils::getUserDataStoreFolders(); foreach(QString folder, dataFolders) { if(!QFileInfo(dataStore.absolutePath()+folder).exists()) { QString folderaux = folder.startsWith("/")? folder.remove(0,1): folder; dataStore.mkpath(folder); } } FolderUtils::copyBin(BinManager::MyPartsBinLocation, BinManager::MyPartsBinTemplateLocation); FolderUtils::copyBin(BinManager::SearchBinLocation, BinManager::SearchBinTemplateLocation); PartFactory::initFolder(); } void FApplication::changeActivation(bool activate, QWidget * originator) { if (!activate) return; //DebugDialog::debug(QString("change activation %1 %2").arg(activate).arg(originator->metaObject()->className())); FritzingWindow * fritzingWindow = qobject_cast(originator); if (fritzingWindow == NULL) { fritzingWindow = qobject_cast(originator->parent()); } if (fritzingWindow == NULL) return; m_orderedTopLevelWidgets.removeOne(fritzingWindow); m_orderedTopLevelWidgets.push_front(fritzingWindow); m_activationTimer.stop(); m_activationTimer.start(); } void FApplication::updateActivation() { //DebugDialog::debug("updating activation"); FritzingWindow * prior = m_lastTopmostWindow; m_lastTopmostWindow = NULL; if (m_orderedTopLevelWidgets.count() > 0) { m_lastTopmostWindow = qobject_cast(m_orderedTopLevelWidgets.at(0)); } if (prior == m_lastTopmostWindow) { //DebugDialog::debug("done updating activation"); return; } //DebugDialog::debug(QString("last:%1, new:%2").arg((long) prior, 0, 16).arg((long) m_lastTopmostWindow.data(), 0, 16)); MainWindow * priorMainWindow = qobject_cast(prior); if (priorMainWindow != NULL) { priorMainWindow->saveDocks(); } MainWindow * lastTopmostMainWindow = qobject_cast(m_lastTopmostWindow); if (lastTopmostMainWindow != NULL) { lastTopmostMainWindow->restoreDocks(); //DebugDialog::debug("restoring active window"); } //DebugDialog::debug("done 2 updating activation"); } void FApplication::topLevelWidgetDestroyed(QObject * object) { QWidget * widget = qobject_cast(object); if (widget) { m_orderedTopLevelWidgets.removeOne(widget); } } void FApplication::closeAllWindows2() { /* Ok, near as I can tell, here's what's going on. When you quit fritzing, the function QApplication::closeAllWindows() is invoked. This goes through the top-level window list in random order and calls close() on each window, until some window says "no". The QGraphicsProxyWidgets must contain top-level windows, and at least on the mac, their response to close() seems to be setVisible(false). The random order explains why different icons disappear, or sometimes none at all. So the hack for now is to call the windows in non-random order. Eventually, maybe the SvgIconWidget class could be rewritten so that it's not using QGraphicsProxyWidget, which is really not intended for hundreds of widgets. (SvgIconWidget has been rewritten) */ // this code modified from QApplication::closeAllWindows() bool did_close = true; QWidget *w; while((w = QApplication::activeModalWidget()) && did_close) { if(!w->isVisible()) break; did_close = w->close(); } if (!did_close) return; QWidgetList list = QApplication::topLevelWidgets(); for (int i = 0; did_close && i < list.size(); ++i) { w = list.at(i); FritzingWindow *fWindow = qobject_cast(w); if (fWindow == NULL) continue; if (w->isVisible() && w->windowType() != Qt::Desktop) { did_close = w->close(); list = QApplication::topLevelWidgets(); i = -1; } } if (!did_close) return; list = QApplication::topLevelWidgets(); for (int i = 0; did_close && i < list.size(); ++i) { w = list.at(i); if (w->isVisible() && w->windowType() != Qt::Desktop) { did_close = w->close(); list = QApplication::topLevelWidgets(); i = -1; } } } bool FApplication::runAsService() { if (m_serviceType == PortService) { DebugDialog::setEnabled(true); initServer(); //return false; } return m_serviceType != NoService; } void FApplication::loadedPart(int loaded, int total) { if (total == 0) return; if (m_splash == NULL) return; //DebugDialog::debug(QString("loaded %1 %2").arg(loaded).arg(total)); if (m_progressIndex >= 0) m_splash->showProgress(m_progressIndex, LoadProgressStart + ((LoadProgressEnd - LoadProgressStart) * loaded / (double) total)); } void FApplication::externalProcessSlot(QString &name, QString &path, QStringList &args) { name = m_externalProcessName; path = m_externalProcessPath; args = m_externalProcessArgs; } bool FApplication::notify(QObject *receiver, QEvent *e) { try { //qDebug() << QString("notify %1 %2").arg(receiver->metaObject()->className()).arg(e->type()); return QApplication::notify(receiver, e); } catch (char const *str) { FMessageBox::critical(NULL, tr("Fritzing failure"), tr("Fritzing caught an exception %1 from %2 in event %3") .arg(str).arg(receiver->objectName()).arg(e->type())); } catch (std::exception& exp) { // suggested in https://code.google.com/p/fritzing/issues/detail?id=2698 qDebug() << QString("notify %1 %2").arg(receiver->metaObject()->className()).arg(e->type()); FMessageBox::critical(NULL, tr("Fritzing failure"), tr("Fritzing caught an exception from %1 in event %2: %3").arg(receiver->objectName()).arg(e->type()).arg(exp.what())); } catch (...) { FMessageBox::critical(NULL, tr("Fritzing failure"), tr("Fritzing caught an exception from %1 in event %2").arg(receiver->objectName()).arg(e->type())); } closeAllWindows2(); QApplication::exit(-1); abort(); return false; } void FApplication::loadSomething(const QString & prevVersion) { // At this point we're trying to determine what sketches to load which are from one of the following sources: // Only one of these sources will actually provide sketches to load and they're listed in order of priority: // We found sketch backups to recover // there's a previous version (open an empty sketch) // files were double-clicked // The last opened sketch // A new blank sketch initFilesToLoad(); // sets up m_filesToLoad from the command line on PC and Linux; mac uses a FileOpen event instead initBackups(); DebugDialog::debug("checking for backups"); QList sketchesToLoad = recoverBackups(); bool loadPrevious = false; if (sketchesToLoad.isEmpty()) { loadPrevious = !prevVersion.isEmpty() && Version::greaterThan(prevVersion, Version::FirstVersionWithDetachedUserData); } DebugDialog::debug(QString("load previous %1").arg(loadPrevious)); if (!loadPrevious && sketchesToLoad.isEmpty()) { // Check for double-clicked files to load DebugDialog::debug(QString("check files to load %1").arg(m_filesToLoad.count())); foreach (QString filename, m_filesToLoad) { DebugDialog::debug(QString("Loading non-service file %1").arg(filename)); MainWindow *mainWindow = MainWindow::newMainWindow(m_referenceModel, filename, true, true, -1); mainWindow->loadWhich(filename, true, true, true, ""); if (filename.endsWith(FritzingSketchExtension) || filename.endsWith(FritzingBundleExtension)) { } else { mainWindow->addDefaultParts(); } sketchesToLoad << mainWindow; } } // Find any previously open sketches to reload if (!loadPrevious && sketchesToLoad.isEmpty()) { DebugDialog::debug(QString("load last open")); // new logic here, we no longer open the most recent sketch, since it can be reached in one click from the welcome page //sketchesToLoad = loadLastOpenSketch(); } MainWindow * newBlankSketch = NULL; if (sketchesToLoad.isEmpty()) { DebugDialog::debug(QString("create empty sketch")); newBlankSketch = MainWindow::newMainWindow(m_referenceModel, "", true, true, -1); if (newBlankSketch) { // make sure to start an empty sketch with a board newBlankSketch->addDefaultParts(); // do this before call to show() sketchesToLoad << newBlankSketch; } } DebugDialog::debug(QString("finish up sketch loading")); // Finish loading the sketches and show them to the user foreach (MainWindow* sketch, sketchesToLoad) { sketch->show(); sketch->clearFileProgressDialog(); } if (loadPrevious) { doLoadPrevious(newBlankSketch); } else if (newBlankSketch) { newBlankSketch->hideTempPartsBin(); // new empty sketch defaults to welcome view newBlankSketch->showWelcomeView(); } } QList FApplication::loadLastOpenSketch() { QList sketches; QSettings settings; if(settings.value("lastOpenSketch").isNull()) return sketches; QString lastSketchPath = settings.value("lastOpenSketch").toString(); if(!QFileInfo(lastSketchPath).exists()) { settings.remove("lastOpenSketch"); return sketches; } DebugDialog::debug(QString("Loading last open sketch %1").arg(lastSketchPath)); settings.remove("lastOpenSketch"); // clear the preference, in case the load crashes MainWindow *mainWindow = MainWindow::newMainWindow(m_referenceModel, lastSketchPath, true, true, -1); mainWindow->loadWhich(lastSketchPath, true, true, true, ""); sketches << mainWindow; settings.setValue("lastOpenSketch", lastSketchPath); // the load works, so restore the preference return sketches; } void FApplication::doLoadPrevious(MainWindow * sketchWindow) { // Here we check if files need to be imported from an earlier version. // This should be done before any files are loaded as it requires a restart. // As this can generate UI it should come after the splash screen has closed. FMessageBox messageBox(sketchWindow); messageBox.setWindowTitle(tr("Import files from previous version?")); messageBox.setText(tr("Do you want to import parts and bins that you have created with earlier versions of Fritzing?\n")); messageBox.setInformativeText(tr("\nNote: You can import them later using the \"Help\" > \"Import parts and bins " "from old version...\" menu action.")); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Cancel); messageBox.setIcon(QMessageBox::Question); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Ok, tr("Import")); messageBox.setButtonText(QMessageBox::Cancel, tr("Do not import now")); QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec(); if(answer == QMessageBox::Ok) { sketchWindow->importFilesFromPrevInstall(); } } QList FApplication::recoverBackups() { QFileInfoList backupList; LockManager::checkLockedFiles("backup", backupList, m_lockedFiles, false, LockManager::FastTime); for (int i = backupList.size() - 1; i >=0; i--) { QFileInfo fileInfo = backupList.at(i); if (!fileInfo.fileName().endsWith(FritzingSketchExtension)) { backupList.removeAt(i); } } QList recoveredSketches; if (backupList.size() == 0) return recoveredSketches; RecoveryDialog recoveryDialog(backupList); int result = (QMessageBox::StandardButton)recoveryDialog.exec(); QList fileItems = recoveryDialog.getFileList(); DebugDialog::debug(QString("Recovering %1 files from recoveryDialog").arg(fileItems.size())); foreach (QTreeWidgetItem * item, fileItems) { QString backupName = item->data(0, Qt::UserRole).value(); if (result == QDialog::Accepted && item->isSelected()) { QString originalBaseName = item->text(0); DebugDialog::debug(QString("Loading recovered sketch %1").arg(originalBaseName)); QString originalPath = item->data(1, Qt::UserRole).value(); QString fileExt; QString bundledFileName = FolderUtils::getSaveFileName(NULL, tr("Please specify an .fzz file name to save to (cancel will delete the backup)"), originalPath, tr("Fritzing (*%1)").arg(FritzingBundleExtension), &fileExt); if (!bundledFileName.isEmpty()) { MainWindow *currentRecoveredSketch = MainWindow::newMainWindow(m_referenceModel, originalBaseName, true, true, -1); currentRecoveredSketch->mainLoad(backupName, bundledFileName, true); currentRecoveredSketch->saveAsShareable(bundledFileName, true); currentRecoveredSketch->setCurrentFile(bundledFileName, true, true); recoveredSketches << currentRecoveredSketch; /* if (originalPath.startsWith(untitledFileName())) { DebugDialog::debug(QString("Comparing untitled documents: %1 %2").arg(filename).arg(untitledFileName())); QRegExp regexp("\\d+"); int ix = regexp.indexIn(filename); int untitledSketchNumber = ix >= 0 ? regexp.cap(0).toInt() : 1; untitledSketchNumber++; DebugDialog::debug(QString("%1 untitled documents open, currently thinking %2").arg(untitledSketchNumber).arg(UntitledSketchIndex)); UntitledSketchIndex = UntitledSketchIndex >= untitledSketchNumber ? UntitledSketchIndex : untitledSketchNumber; } */ } } QFile::remove(backupName); } return recoveredSketches; } void FApplication::initFilesToLoad() { for (int i = 1; i < m_arguments.length(); i++) { QFileInfo fileinfo(m_arguments[i]); if (fileinfo.exists() && !fileinfo.isDir()) { m_filesToLoad << m_arguments[i]; } } } void FApplication::initBackups() { LockManager::initLockedFiles("backup", MainWindow::BackupFolder, m_lockedFiles, LockManager::FastTime); } void FApplication::cleanupBackups() { LockManager::releaseLockedFiles(MainWindow::BackupFolder, m_lockedFiles); } void FApplication::gotOrderFab(QNetworkReply * networkReply) { int responseCode = networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (responseCode == 200) { QSettings settings; settings.setValue(ORDERFABENABLED, QVariant(true)); } networkReply->manager()->deleteLater(); networkReply->deleteLater(); } void FApplication::runPanelizerService() { m_started = true; Panelizer::panelize(this, m_panelFilename, m_panelizerCustom); } void FApplication::runInscriptionService() { m_started = true; bool drc = false; bool noMessages = false; foreach (QString arg, m_arguments) { if (arg.compare("-drc", Qt::CaseInsensitive) == 0) { drc = true; } if (arg.compare("-nm", Qt::CaseInsensitive) == 0) { noMessages = true; } } Panelizer::inscribe(this, m_panelFilename, drc, noMessages); } QList FApplication::orderedTopLevelMainWindows() { QList mainWindows; foreach (QWidget * widget, m_orderedTopLevelWidgets) { MainWindow * mainWindow = qobject_cast(widget); if (mainWindow) mainWindows.append(mainWindow); } return mainWindows; } void FApplication::runExampleService() { m_started = true; initService(); QDir sketchesDir(FolderUtils::getApplicationSubFolderPath("sketches")); runExampleService(sketchesDir); } void FApplication::runExampleService(QDir & dir) { QStringList nameFilters; nameFilters << ("*" + FritzingBundleExtension); // FritzingSketchExtension QFileInfoList fileList = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); foreach (QFileInfo fileInfo, fileList) { QString path = fileInfo.absoluteFilePath(); DebugDialog::debug("sketch file " + path); MainWindow * mainWindow = openWindowForService(false, -1); if (mainWindow == NULL) continue; FolderUtils::setOpenSaveFolderAux(dir.absolutePath()); if (!mainWindow->loadWhich(path, false, false, true, "")) { DebugDialog::debug(QString("failed to load")); } else { QList items = mainWindow->selectAllObsolete(false); if (items.count() > 0) { mainWindow->swapObsolete(false, items); } mainWindow->saveAsAux(path); // path + "z" mainWindow->setCloseSilently(true); mainWindow->close(); } } QFileInfoList dirList = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks); foreach (QFileInfo dirInfo, dirList) { QDir dir(dirInfo.filePath()); runExampleService(dir); } } void FApplication::cleanFzzs() { QHash lockedFiles; QString folder; LockManager::initLockedFiles("fzz", folder, lockedFiles, LockManager::SlowTime); QFileInfoList backupList; LockManager::checkLockedFiles("fzz", backupList, lockedFiles, true, LockManager::SlowTime); LockManager::releaseLockedFiles(folder, lockedFiles); } void FApplication::initServer() { FMessageBox::BlockMessages = true; m_fServer = new FServer(this); connect(m_fServer, SIGNAL(newConnection(int)), this, SLOT(newConnection(int))); m_fServer->listen(QHostAddress::Any, m_portNumber); } void FApplication::newConnection(int socketDescription) { FServerThread *thread = new FServerThread(socketDescription, this); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(thread, SIGNAL(doCommand(const QString &, const QString &, QString &, int &)), this, SLOT(doCommand(const QString &, const QString &, QString &, int &)), Qt::BlockingQueuedConnection); thread->start(); } void FApplication::doCommand(const QString & command, const QString & params, QString & result, int & status) { status = 200; result = ""; QDir dir(m_portRootFolder); QString subfolder = params; if (command.endsWith("tcp")) { subfolder = TextUtils::getRandText(); dir.mkdir(subfolder); } dir.cd(subfolder); m_outputFolder = dir.absolutePath(); if (command.endsWith("tcp")) { QEventLoop loop; QNetworkAccessManager networkManager; QObject::connect(&networkManager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit())); QUrl url = params; QNetworkReply* reply = networkManager.get(QNetworkRequest(url)); loop.exec(); status = 404; if (reply->error() == QNetworkReply::NoError) { if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt() == 200) { if (reply->isReadable()) { int buffersize = 8192; QStringList components = params.split("/"); QString filename = components.last(); QFile file(dir.absoluteFilePath(filename)); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { status = 200; while (reply->bytesAvailable() >= buffersize) { QByteArray bytes = reply->read(buffersize); file.write(bytes); } if (reply->bytesAvailable() > 0) { file.write(reply->readAll()); } file.close(); } else { result = "unable to save to local file"; } } else { result = "response unreadable"; } } else { result = QString("bad response from url server %1").arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt()); } } else { result = QString("url get failed %1").arg(reply->error()); } reply->deleteLater(); } if (!result.isEmpty()) { // network problem return; } if (command.startsWith("svg")) { runSvgServiceAux(); QStringList nameFilters; nameFilters << ("*.svg"); QFileInfoList fileList = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); if (fileList.count() > 0) { QFile file(fileList.at(0).absoluteFilePath()); if (file.open(QFile::ReadOnly)) { result = file.readAll(); } } } else if (command.startsWith("gerber")) { runGerberServiceAux(); QStringList nameFilters; nameFilters << ("*.txt"); QFileInfoList fileList = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); if (fileList.count() > 0) { QFile file(fileList.at(0).absoluteFilePath()); if (file.open(QFile::ReadOnly)) { result = file.readAll(); } } } if (command.endsWith("tcp")) { QStringList skipSuffixes(".zip"); skipSuffixes << ".fzz"; QString filename = dir.absoluteFilePath(subfolder + ".zip"); if (FolderUtils::createZipAndSaveTo(dir, filename, skipSuffixes)) { status = 200; result = filename; } else { status = 500; result = "local zip failure"; } } } fritzing-app-0.9.2b/src/fapplication.h000066400000000000000000000130011250202676700177110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6940 $: $Author: irascibl@gmail.com $: $Date: 2013-03-26 14:00:34 +0100 (Di, 26. Mrz 2013) $ ********************************************************************/ #ifndef FAPPLICATION_H #define FAPPLICATION_H #include #include #include #include #include #include #include #include #include #include #include #include #include class FServer : public QTcpServer { Q_OBJECT public: FServer(QObject *parent = 0); signals: void newConnection(int socketDescriptor); protected: void incomingConnection(int socketDescriptor); }; class FServerThread : public QThread { Q_OBJECT public: FServerThread(int socketDescriptor, QObject *parent); void run(); void setDone(); signals: void error(QTcpSocket::SocketError socketError); void doCommand(const QString & command, const QString & params, QString & result, int & status); protected: void writeResponse(QTcpSocket *, int code, const QString & codeString, const QString & mimeType, const QString & message); protected: int m_socketDescriptor; bool m_done; protected: static QMutex m_busy; }; class FApplication : public QApplication { Q_OBJECT public: FApplication(int & argc, char ** argv); ~FApplication(void); public: bool init(); int startup(); int serviceStartup(); void finish(); class ReferenceModel * loadReferenceModel(const QString & databaseName, bool fullLoad); void registerFonts(); class MainWindow * openWindowForService(bool lockFiles, int initialTab); bool runAsService(); public: static bool spaceBarIsPressed(); signals: void spaceBarIsPressedSignal(bool); public slots: void preferences(); void preferencesAfter(); void checkForUpdates(); void checkForUpdates(bool atUserRequest); void enableCheckUpdates(bool enabled); void createUserDataStoreFolderStructure(); void changeActivation(bool activate, QWidget * originator); void updateActivation(); void topLevelWidgetDestroyed(QObject *); void closeAllWindows2(); void loadedPart(int loaded, int total); void externalProcessSlot(QString & name, QString & path, QStringList & args); void gotOrderFab(QNetworkReply *); void newConnection(int socketDescriptor); void doCommand(const QString & command, const QString & params, QString & result, int & status); protected: bool eventFilter(QObject *obj, QEvent *event); bool event(QEvent *event); bool findTranslator(const QString & translationsPath); void loadNew(QString path); void loadOne(class MainWindow *, QString path, int loaded); void initSplash(class FSplashScreen & splash); void registerFont(const QString &fontFile, bool reallyRegister); void clearModels(); bool notify(QObject *receiver, QEvent *e); void initService(); void runDRCService(); void runGedaService(); void runDatabaseService(); void runKicadFootprintService(); void runKicadSchematicService(); void runGerberService(); void runGerberServiceAux(); void runSvgService(); void runSvgServiceAux(); void runPanelizerService(); void runInscriptionService(); void runExampleService(); void runExampleService(QDir &); QList recoverBackups(); QList loadLastOpenSketch(); void doLoadPrevious(MainWindow *); void loadSomething(const QString & previousVersion); void initFilesToLoad(); void initBackups(); void cleanupBackups(); void updatePrefs(class PrefsDialog & prefsDialog); QList orderedTopLevelMainWindows(); void cleanFzzs(); void initServer(); enum ServiceType { PanelizerService = 1, InscriptionService, GerberService, GedaService, KicadSchematicService, KicadFootprintService, ExampleService, DatabaseService, SvgService, PortService, DRCService, NoService }; protected: bool m_spaceBarIsPressed; bool m_mousePressed; QTranslator m_translator; class ReferenceModel * m_referenceModel; bool m_started; QStringList m_filesToLoad; QString m_libPath; QString m_translationPath; class UpdateDialog * m_updateDialog; QTimer m_activationTimer; QPointer m_lastTopmostWindow; QList m_orderedTopLevelWidgets; QStringList m_arguments; QStringList m_externalProcessArgs; QString m_externalProcessName; QString m_externalProcessPath; ServiceType m_serviceType; int m_progressIndex; class FSplashScreen * m_splash; QString m_outputFolder; QString m_portRootFolder; QString m_panelFilename; QHash m_lockedFiles; bool m_panelizerCustom; int m_portNumber; FServer * m_fServer; QString m_buildType; }; #endif fritzing-app-0.9.2b/src/fsplashscreen.cpp000066400000000000000000000134231250202676700204430ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision$: $Author$: $Date$ ********************************************************************/ #include "fsplashscreen.h" #include "utils/misc.h" #include "debugdialog.h" #include #include #include #include FSplashScreen::FSplashScreen(const QPixmap & pixmap, Qt::WindowFlags f ) : QSplashScreen(pixmap, f) { QFile file(":/resources/images/splash/splash.xml"); if (!file.open(QFile::ReadOnly | QFile::Text)) { DebugDialog::debug("unable to load splash.xml: " + file.errorString()); return; } QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse splash.xml: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); int sliceDelay = root.attribute("sliceDelaySeconds", "0").toInt(); if (sliceDelay > 0) { QTimer::singleShot(sliceDelay * 1000, this, SLOT(displaySlice())); } QDomElement item = root.firstChildElement("item"); while (!item.isNull()) { QString id = item.attribute("id"); if (!id.isEmpty()) { int x = item.attribute("x", "0").toInt(); int y = item.attribute("y", "0").toInt(); int width = item.attribute("width", "0").toInt(); int height = item.attribute("height", "0").toInt(); QString colorName = item.attribute("color"); MessageThing * messageThing = new MessageThing(); messageThing->rect.setCoords(x, y, x + width, y + height); if (colorName.isEmpty()) { messageThing->color = QColor(0, 0, 0); } else { messageThing->color.setNamedColor(colorName); } m_items.insert(id, messageThing); } item = item.nextSiblingElement("item"); } } FSplashScreen::~FSplashScreen() { foreach (MessageThing * messageThing, m_messages) { delete messageThing; } foreach (MessageThing * messageThing, m_items) { delete messageThing; } foreach (PixmapThing * pixmapThing, m_pixmaps) { delete pixmapThing; } } void FSplashScreen::showMessage(const QString &message, const QString & id, int alignment) { MessageThing * itemMessageThing = m_items.value(id); if (itemMessageThing == NULL) return; MessageThing * messageThing = new MessageThing; messageThing->alignment = alignment; messageThing->color = itemMessageThing->color; messageThing->rect = itemMessageThing->rect;; messageThing->message = message; m_messages.append(messageThing); repaint(); } int FSplashScreen::showPixmap(const QPixmap & pixmap, const QString & id) { MessageThing * itemMessageThing = m_items.value(id); if (itemMessageThing == NULL) return -1; PixmapThing * pixmapThing = new PixmapThing; pixmapThing->rect = QRect(itemMessageThing->rect.topLeft(), pixmap.size()); pixmapThing->pixmap = pixmap; m_pixmaps.append(pixmapThing); repaint(); return m_pixmaps.count() - 1; } void FSplashScreen::showProgress(int index, double progress) { if (index < 0) return; if (index >= m_pixmaps.count()) return; int w = (int) (this->width() * progress); PixmapThing * pixmapThing = m_pixmaps[index]; pixmapThing->rect.setWidth(w); repaint(); } void FSplashScreen::drawContents ( QPainter * painter ) { // copied from QSplashScreen::drawContents painter->setRenderHint ( QPainter::Antialiasing, true ); // TODO: might need to be in the stylesheet? // pixmaps first, since they go beneath text foreach (PixmapThing * pixmapThing, m_pixmaps) { painter->drawPixmap(pixmapThing->rect, pixmapThing->pixmap); //DebugDialog::debug(QString("pixmapthing %1 %2").arg(pixmapThing->pixmap.width()).arg(pixmapThing->pixmap.height()), pixmapThing->rect); } foreach (MessageThing * messageThing, m_messages) { painter->setPen(messageThing->color); if (Qt::mightBeRichText(messageThing->message)) { QTextDocument doc; #ifdef QT_NO_TEXTHTMLPARSER doc.setPlainText(messageThing->message); #else doc.setHtml(messageThing->message); #endif doc.setTextWidth(messageThing->rect.width()); QTextCursor cursor(&doc); cursor.select(QTextCursor::Document); QTextBlockFormat fmt; fmt.setAlignment(Qt::Alignment(messageThing->alignment)); cursor.mergeBlockFormat(fmt); painter->save(); painter->translate(messageThing->rect.topLeft()); doc.drawContents(painter); painter->restore(); } else { painter->drawText(messageThing->rect, messageThing->alignment, messageThing->message); } } } void FSplashScreen::displaySlice() { QString fname = ":/resources/images/splash/fab_slice%1.png"; int highest = 0; for (int i = 1; i < 100; i++) { QFileInfo info(fname.arg(i)); if (info.exists()) { highest = i; } else break; } if (highest == 0) return; QPixmap bar(":/resources/images/splash/fab_logo_bar.png"); if (bar.isNull()) return; srand ( time(NULL) ); int ix = (rand() % highest) + 1; QPixmap slice(fname.arg(ix)); if (slice.isNull()) return; showPixmap(bar, "logoBar"); showPixmap(slice, "slice"); } fritzing-app-0.9.2b/src/fsplashscreen.h000066400000000000000000000035031250202676700201060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision$: $Author$: $Date$ ********************************************************************/ #ifndef FSPLASHSCREEN_H #define FSPLASHSCREEN_H #include #include #include struct MessageThing { QString message; QRect rect; int alignment; QColor color; }; struct PixmapThing { QPixmap pixmap; QRect rect; }; class FSplashScreen : public QSplashScreen { Q_OBJECT public: FSplashScreen(const QPixmap & pixmap = QPixmap(), Qt::WindowFlags f = 0); ~FSplashScreen(); void showMessage(const QString &message, const QString & id, int alignment = Qt::AlignLeft); int showPixmap(const QPixmap &pixmap, const QString & id); void showProgress(int index, double progress); // progress is from 0.0 to 1.0; protected: void drawContents ( QPainter * painter ); public slots: void displaySlice(); protected: QPixmap m_pixmap; QList m_messages; QList m_pixmaps; QHash m_items; }; #endif fritzing-app-0.9.2b/src/fsvgrenderer.cpp000066400000000000000000000654001250202676700203010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6988 $: $Author: irascibl@gmail.com $: $Date: 2013-04-26 12:05:48 +0200 (Fr, 26. Apr 2013) $ ********************************************************************/ #include "fsvgrenderer.h" #include "debugdialog.h" #include "svg/svgfilesplitter.h" #include "utils/textutils.h" #include "utils/graphicsutils.h" #include "utils/folderutils.h" #include "connectors/svgidlayer.h" #include #include #include #include #include #include ///////////////////////////////////////////// QString FSvgRenderer::NonConnectorName("nonconn"); static ConnectorInfo VanillaConnectorInfo; FSvgRenderer::FSvgRenderer(QObject * parent) : QSvgRenderer(parent) { m_defaultSizeF = QSizeF(0,0); } FSvgRenderer::~FSvgRenderer() { clearConnectorInfoHash(m_connectorInfoHash); clearConnectorInfoHash(m_nonConnectorInfoHash); } void FSvgRenderer::initNames() { VanillaConnectorInfo.gotPath = VanillaConnectorInfo.gotCircle = false; } void FSvgRenderer::clearConnectorInfoHash(QHash & hash) { foreach (ConnectorInfo * connectorInfo, hash.values()) { delete connectorInfo; } hash.clear(); } void FSvgRenderer::cleanup() { } QByteArray FSvgRenderer::loadSvg(const QString & filename) { LoadInfo loadInfo; loadInfo.filename = filename; return loadSvg(loadInfo); } QByteArray FSvgRenderer::loadSvg(const LoadInfo & loadInfo) { if (!QFileInfo(loadInfo.filename).exists() || !QFileInfo(loadInfo.filename).isFile()) { return QByteArray(); } QFile file(loadInfo.filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { return QByteArray(); } QByteArray contents = file.readAll(); file.close(); if (contents.length() <= 0) return QByteArray(); return loadAux(contents, loadInfo); } bool FSvgRenderer::loadSvgString(const QString & svg) { QByteArray byteArray(svg.toUtf8()); QByteArray result = loadSvg(byteArray, "", true); return (!result.isEmpty()); } bool FSvgRenderer::loadSvgString(const QString & svg, QString & newSvg) { QByteArray byteArray(svg.toUtf8()); QByteArray result = loadSvg(byteArray, "", true); newSvg = QString(result); return (!result.isEmpty()); } QByteArray FSvgRenderer::loadSvg(const QByteArray & contents, const QString & filename, bool findNonConnectors) { LoadInfo loadInfo; loadInfo.filename = filename; loadInfo.findNonConnectors = findNonConnectors; return loadAux(contents, loadInfo); } QByteArray FSvgRenderer::loadSvg(const QByteArray & contents, const LoadInfo & loadInfo) { return loadAux(contents, loadInfo); } QByteArray FSvgRenderer::loadAux(const QByteArray & theContents, const LoadInfo & loadInfo) { QByteArray cleanContents(theContents); bool cleaned = false; QString string(cleanContents); if (TextUtils::fixMuch(string, false)) { cleaned = true; } if (TextUtils::fixPixelDimensionsIn(string)) { cleaned = true; } if (cleaned) { cleanContents = string.toUtf8(); } if (loadInfo.connectorIDs.count() > 0 || !loadInfo.setColor.isEmpty() || loadInfo.findNonConnectors) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(cleanContents, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("renderer loadAux failed %1 %2 %3 %4").arg(loadInfo.filename).arg(errorStr).arg(errorLine).arg(errorColumn)); } bool resetContents = false; QDomElement root = doc.documentElement(); if (!loadInfo.setColor.isEmpty()) { QDomElement element = TextUtils::findElementWithAttribute(root, "id", loadInfo.colorElementID); if (!element.isNull()) { QStringList exceptions; exceptions << "black" << "#000000"; SvgFileSplitter::fixColorRecurse(element, loadInfo.setColor, exceptions); resetContents = true; } } if (loadInfo.connectorIDs.count() > 0) { bool init = initConnectorInfo(doc, loadInfo); resetContents = resetContents || init; } if (loadInfo.findNonConnectors) { initNonConnectorInfo(doc, loadInfo.filename); } if (resetContents) { cleanContents = TextUtils::removeXMLEntities(doc.toString()).toUtf8(); } } /* cleanContents = doc.toByteArray(); //QFile file("all.txt"); //if (file.open(QIODevice::Append)) { //QTextStream t(&file); //t << cleanContents; //file.close(); //} */ //DebugDialog::debug(cleanContents.data()); return finalLoad(cleanContents, loadInfo.filename); } QByteArray FSvgRenderer::finalLoad(QByteArray & cleanContents, const QString & filename) { QXmlStreamReader xml(cleanContents); bool result = determineDefaultSize(xml); if (!result) { return QByteArray(); } result = QSvgRenderer::load(cleanContents); if (result) { m_filename = filename; return cleanContents; } return QByteArray(); } bool FSvgRenderer::fastLoad(const QByteArray & contents) { return QSvgRenderer::load(contents); } const QString & FSvgRenderer::filename() { return m_filename; } QPixmap * FSvgRenderer::getPixmap(QSvgRenderer * renderer, QSize size) { QPixmap *pixmap = new QPixmap(size); pixmap->fill(Qt::transparent); QPainter painter(pixmap); // preserve aspect ratio QSizeF def = renderer->defaultSize(); FSvgRenderer * frenderer = qobject_cast(renderer); if (frenderer) { def = frenderer->defaultSizeF(); } double newW = size.width(); double newH = newW * def.height() / def.width(); if (newH > size.height()) { newH = size.height(); newW = newH * def.width() / def.height(); } QRectF bounds((size.width() - newW) / 2.0, (size.height() - newH) / 2.0, newW, newH); renderer->render(&painter, bounds); painter.end(); return pixmap; } bool FSvgRenderer::determineDefaultSize(QXmlStreamReader & xml) { QSizeF size = parseForWidthAndHeight(xml); m_defaultSizeF = QSizeF(size.width() * GraphicsUtils::SVGDPI, size.height() * GraphicsUtils::SVGDPI); return (size.width() != 0 && size.height() != 0); } QSizeF FSvgRenderer::parseForWidthAndHeight(QXmlStreamReader & xml) { QSizeF size = TextUtils::parseForWidthAndHeight(xml); if (size.width() != 0 && size.height() != 0) return size; QIODevice * device = xml.device(); DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); DebugDialog::debug("bad width and/or bad height in svg:"); if (device) { device->reset(); QString string(device->readAll()); DebugDialog::debug(string); } DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); return size; } QSizeF FSvgRenderer::defaultSizeF() { if (m_defaultSizeF.width() == 0 && m_defaultSizeF.height() == 0) { return defaultSize(); } return m_defaultSizeF; } void FSvgRenderer::initNonConnectorInfo(QDomDocument & domDocument, const QString & filename) { clearConnectorInfoHash(m_nonConnectorInfoHash); QDomElement root = domDocument.documentElement(); initNonConnectorInfoAux(root, filename); } void FSvgRenderer::initNonConnectorInfoAux(QDomElement & element, const QString & filename) { QString id = element.attribute("id"); if (id.startsWith(NonConnectorName, Qt::CaseInsensitive)) { ConnectorInfo * connectorInfo = initConnectorInfoStruct(element, filename, false); m_nonConnectorInfoHash.insert(id, connectorInfo); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { initNonConnectorInfoAux(child, filename); child = child.nextSiblingElement(); } } bool FSvgRenderer::initConnectorInfo(QDomDocument & domDocument, const LoadInfo & loadInfo) { bool result = false; clearConnectorInfoHash(m_connectorInfoHash); QDomElement root = domDocument.documentElement(); initConnectorInfoAux(root, loadInfo); if (loadInfo.terminalIDs.count() > 0) { initTerminalInfoAux(root, loadInfo); } if (loadInfo.legIDs.count() > 0) { initLegInfoAux(root, loadInfo, result); } return result; } void FSvgRenderer::initLegInfoAux(QDomElement & element, const LoadInfo & loadInfo, bool & gotOne) { QString id = element.attribute("id"); if (!id.isEmpty()) { int ix = loadInfo.legIDs.indexOf(id); if (ix >= 0) { //DebugDialog::debug("init leg info " + id); //foreach (QString lid, legIDs) { // DebugDialog::debug("\tleg id:" + lid); //} element.setTagName("g"); // don't want this element to actually be drawn gotOne = true; ConnectorInfo * connectorInfo = m_connectorInfoHash.value(loadInfo.connectorIDs.at(ix), NULL); if (connectorInfo) { //QString temp; //QTextStream stream(&temp); //element.save(stream, 0); //DebugDialog::debug("\t matched " + connectorIDs.at(ix) + " " + temp); connectorInfo->legMatrix = TextUtils::elementToMatrix(element); connectorInfo->legColor = element.attribute("stroke"); connectorInfo->legLine = QLineF(); connectorInfo->legStrokeWidth = 0; initLegInfoAux(element, connectorInfo); } // don't return here, might miss other legs } } QDomElement child = element.firstChildElement(); while (!child.isNull()) { initLegInfoAux(child, loadInfo, gotOne); child = child.nextSiblingElement(); } } bool FSvgRenderer::initLegInfoAux(QDomElement & element, ConnectorInfo * connectorInfo) { bool ok; double sw = element.attribute("stroke-width").toDouble(&ok); if (!ok) return false; double x1 = element.attribute("x1").toDouble(&ok); if (!ok) return false; double y1 = element.attribute("y1").toDouble(&ok); if (!ok) return false; double x2 = element.attribute("x2").toDouble(&ok); if (!ok) return false; double y2 = element.attribute("y2").toDouble(&ok); if (!ok) return false; connectorInfo->legStrokeWidth = sw; connectorInfo->legLine = QLineF(x1, y1, x2, y2); return true; } void FSvgRenderer::initTerminalInfoAux(QDomElement & element, const LoadInfo & loadInfo) { QString id = element.attribute("id"); if (!id.isEmpty()) { int ix = loadInfo.terminalIDs.indexOf(id); if (ix >= 0) { ConnectorInfo * connectorInfo = m_connectorInfoHash.value(loadInfo.connectorIDs.at(ix), NULL); if (connectorInfo) { connectorInfo->terminalMatrix = TextUtils::elementToMatrix(element); } // don't return here, might miss other terminal ids } } QDomElement child = element.firstChildElement(); while (!child.isNull()) { initTerminalInfoAux(child, loadInfo); child = child.nextSiblingElement(); } } void FSvgRenderer::initConnectorInfoAux(QDomElement & element, const LoadInfo & loadInfo) { QString id = element.attribute("id"); if (!id.isEmpty()) { if (loadInfo.connectorIDs.contains(id)) { ConnectorInfo * connectorInfo = initConnectorInfoStruct(element, loadInfo.filename, loadInfo.parsePaths); m_connectorInfoHash.insert(id, connectorInfo); } // don't return here, might miss other connectors } QDomElement child = element.firstChildElement(); while (!child.isNull()) { initConnectorInfoAux(child, loadInfo); child = child.nextSiblingElement(); } } ConnectorInfo * FSvgRenderer::initConnectorInfoStruct(QDomElement & connectorElement, const QString & filename, bool parsePaths) { ConnectorInfo * connectorInfo = new ConnectorInfo(); connectorInfo->radius = connectorInfo->strokeWidth = 0; connectorInfo->gotPath = connectorInfo->gotCircle = false; if (connectorElement.isNull()) return connectorInfo; connectorInfo->matrix = TextUtils::elementToMatrix(connectorElement); initConnectorInfoStructAux(connectorElement, connectorInfo, filename, parsePaths); return connectorInfo; } bool FSvgRenderer::initConnectorInfoStructAux(QDomElement & element, ConnectorInfo * connectorInfo, const QString & filename, bool parsePaths) { if (element.nodeName().compare("circle") == 0) { return initConnectorInfoCircle(element, connectorInfo, filename); } if (element.nodeName().compare("path") == 0) { if (!parsePaths) return false; return initConnectorInfoPath(element, connectorInfo, filename); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { if (initConnectorInfoStructAux(child, connectorInfo, filename, parsePaths)) return true; child = child.nextSiblingElement(); } return false; } bool FSvgRenderer::initConnectorInfoPath(QDomElement & element, ConnectorInfo * connectorInfo, const QString & filename) { QString id = element.attribute("id"); if (id.isEmpty()) return false; // shouldn't be here QString stroke = element.attribute("stroke"); if (stroke == "none") return false; // cannot be a circle with a hole in the center connectorInfo->gotPath = true; double sw = TextUtils::getStrokeWidth(element, 1); if (!stroke.isEmpty()) element.setAttribute("stroke", "black"); QString fill = element.attribute("fill"); if (!fill.isEmpty() && (fill != "none")) element.setAttribute("fill", "black"); QDomDocument doc = element.ownerDocument(); FSvgRenderer renderer; QByteArray byteArray = doc.toByteArray(); renderer.finalLoad(byteArray, filename); QRectF bounds = renderer.boundsOnElement(id); static const int dim = 101; int width = dim; int height = dim; if (bounds.width() - bounds.height() / (bounds.width() + bounds.height()) > .01) { height = (int) (float(dim) * bounds.height() / bounds.width()); } else if (bounds.height() - bounds.width() / (bounds.width() + bounds.height()) > .01) { width = (int) (float(dim) * bounds.width() / bounds.height()); } QImage image(width, height, QImage::Format_Mono); image.fill(0xffffffff); QPainter painter; painter.begin(&image); renderer.render(&painter, id); painter.end(); #ifndef QT_NO_DEBUG //image.save(FolderUtils::getUserDataStorePath("") + "/donutcheck.png"); #endif if (!fill.isEmpty()) element.setAttribute("fill", fill); if (!stroke.isEmpty()) element.setAttribute("stroke", stroke); //DebugDialog::debug(QString("checking connector path %1").arg(id)); int lxStart = -1, lxEnd = -1, rxStart = -1, rxEnd = -1; for (int x = 0; x < width; x++) { if (image.pixel(x, height / 2) == 0xff000000) { lxStart = x; break; } } if (lxStart < 0) return false; if (lxStart >= width / 2) return false; // not an ellipse for (int x = lxStart + 1; x < width; x++) { if (image.pixel(x, height / 2) == 0xff000000) { lxEnd = x; } else break; } if (lxEnd < 0) return false; if (lxEnd > width / 2) return false; // not an ellipse for (int x = lxEnd + 1; x < width; x++) { if (image.pixel(x, height / 2) == 0xff000000) { rxStart = x; break; } } if (rxStart < 0) return false; if (rxStart < height / 2) return false; // not an ellipse; for (int x = rxStart + 1; x < width; x++) { if (image.pixel(x, height / 2) == 0xff000000) { rxEnd = x; } else break; } if (rxEnd < 0) return false; if (qAbs(rxEnd - rxStart - (lxEnd - lxStart)) > 1) return false; // sides are not symmetric int lyStart = -1, lyEnd = -1, ryStart = -1, ryEnd = -1; for (int y = 0; y < height; y++) { if (image.pixel(width / 2, y) == 0xff000000) { lyStart = y; break; } } if (lyStart < 0) return false; if (lyStart >= height / 2) return false; // not an ellipse for (int y = lyStart + 1; y < height; y++) { if (image.pixel(width / 2, y) == 0xff000000) { lyEnd = y; } else break; } if (lyEnd < 0) return false; if (lyEnd > height / 2) return false; // not an ellipse for (int y = lyEnd + 1; y < height; y++) { if (image.pixel(width / 2, y) == 0xff000000) { ryStart = y; break; } } if (ryStart < 0) return false; if (ryStart < height / 2) return false; // not an ellipse for (int y = ryStart + 1; y < height; y++) { if (image.pixel(width / 2, y) == 0xff000000) { ryEnd = y; } else break; } if (ryEnd < 0) return false; if (qAbs((ryEnd - ryStart) - (lyEnd - lyStart)) > 1) return false; // tops not symmetric if (qAbs((rxStart - lxEnd) - (ryStart - lyEnd)) > 1) return false; // inner drill hole is not circular double r = (qMin(bounds.width(), bounds.height()) - sw) / 2; QMatrix matrix = TextUtils::elementToMatrix(element); if (!matrix.isIdentity()) { QRectF r1(0,0,r,r); QRectF r2 = matrix.mapRect(r1); if (r2.width() != r1.width()) { r = r2.width(); sw = sw * r2.width() / r1.width(); } } connectorInfo->radius = r; connectorInfo->strokeWidth = sw; connectorInfo->gotCircle = true; //DebugDialog::debug(QString("got connector path %1").arg(id)); return true; } bool FSvgRenderer::initConnectorInfoCircle(QDomElement & element, ConnectorInfo * connectorInfo, const QString & filename) { Q_UNUSED(filename); bool ok; element.attribute("cx").toDouble(&ok); if (!ok) return false; element.attribute("cy").toDouble(&ok); if (!ok) return false; double r = element.attribute("r").toDouble(&ok); if (!ok) return false; double sw = TextUtils::getStrokeWidth(element, 1); QMatrix matrix = TextUtils::elementToMatrix(element); if (!matrix.isIdentity()) { QRectF r1(0,0,r,r); QRectF r2 = matrix.mapRect(r1); if (r2.width() != r1.width()) { r = r2.width(); sw = sw * r2.width() / r1.width(); } } //DebugDialog::debug("got a circle"); connectorInfo->gotCircle = true; //connectorInfo->cbounds.setRect(cx - r - (sw / 2.0), cy - r - (sw / 2.0), (r * 2) + sw, (r * 2) + sw); connectorInfo->radius = r; connectorInfo->strokeWidth = sw; return true; } ConnectorInfo * FSvgRenderer::getConnectorInfo(const QString & connectorID) { return m_connectorInfoHash.value(connectorID, &VanillaConnectorInfo); } bool FSvgRenderer::setUpConnector(SvgIdLayer * svgIdLayer, bool ignoreTerminalPoint, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (svgIdLayer == NULL) return false; //if (svgIdLayer->m_viewID = ViewLayer::SchematicView) { // DebugDialog::debug("delete me please"); //} if (svgIdLayer->processed(viewLayerPlacement)) { // hybrids are not visible in some views return svgIdLayer->svgVisible(viewLayerPlacement) || svgIdLayer->m_hybrid; } QString connectorID = svgIdLayer->m_svgId; // boundsOnElement seems to include any matrix on the element itself. // I would swear this wasn't true before Qt4.7, but maybe I am crazy QRectF bounds = this->boundsOnElement(connectorID); if (bounds.isNull() && !svgIdLayer->m_hybrid) { // hybrids can have zero size svgIdLayer->setInvisible(viewLayerPlacement); DebugDialog::debug("renderer::setupconnector: null bounds"); return false; } QSizeF defaultSizeF = this->defaultSizeF(); QRectF viewBox = this->viewBoxF(); ConnectorInfo * connectorInfo = getConnectorInfo(connectorID); /* DebugDialog::debug(QString("connectorid:%1 m11:%2 m12:%3 m21:%4 m22:%5 dx:%6 dy:%7") .arg(connectorID) .arg(connectorInfo->matrix.m11()) .arg(connectorInfo->matrix.m12()) .arg(connectorInfo->matrix.m21()) .arg(connectorInfo->matrix.m22()) .arg(connectorInfo->matrix.dx()) .arg(connectorInfo->matrix.dy()), bounds); */ /*DebugDialog::debug(QString("identity matrix %11 %1 %2, viewbox: %3 %4 %5 %6, bounds: %7 %8 %9 %10, size: %12 %13").arg(m_modelPart->title()).arg(connectorSharedID()) .arg(viewBox.x()).arg(viewBox.y()).arg(viewBox.width()).arg(viewBox.height()) .arg(bounds.x()).arg(bounds.y()).arg(bounds.width()).arg(bounds.height()) .arg(viewID) .arg(defaultSizeF.width()).arg(defaultSizeF.height()) ); */ // some strangeness in the way that svg items and non-svg items map to screen space // might be a qt problem. //QMatrix matrix0 = connectorInfo->matrix * this->matrixForElement(connectorID); //QRectF r1 = matrix0.mapRect(bounds); QMatrix elementMatrix = this->matrixForElement(connectorID); QRectF r1 = elementMatrix.mapRect(bounds); if (connectorInfo != NULL) { if (connectorInfo->gotCircle) { QLineF l(0,0,connectorInfo->radius, 0); QLineF lm = elementMatrix.map(l); svgIdLayer->m_radius = lm.length() * defaultSizeF.width() / viewBox.width(); QLineF k(0,0,connectorInfo->strokeWidth, 0); QLineF km = elementMatrix.map(k); svgIdLayer->m_strokeWidth = km.length() * defaultSizeF.width() / viewBox.width(); //bounds = connectorInfo->cbounds; } if (connectorInfo->gotPath) { svgIdLayer->m_path = true; } } /* svgIdLayer->m_rect.setRect(r1.x() * defaultSize.width() / viewBox.width(), r1.y() * defaultSize.height() / viewBox.height(), r1.width() * defaultSize.width() / viewBox.width(), r1.height() * defaultSize.height() / viewBox.height()); */ QRectF svgRect(r1.x() * defaultSizeF.width() / viewBox.width(), r1.y() * defaultSizeF.height() / viewBox.height(), r1.width() * defaultSizeF.width() / viewBox.width(), r1.height() * defaultSizeF.height() / viewBox.height()); //if (!svgIdLayer->m_svgVisible) { //DebugDialog::debug("not vis"); //} QPointF terminal = calcTerminalPoint(svgIdLayer->m_terminalId, svgRect, ignoreTerminalPoint, viewBox, connectorInfo->terminalMatrix); svgIdLayer->setPointRect(viewLayerPlacement, terminal, svgRect, !bounds.isNull()); calcLeg(svgIdLayer, viewBox, connectorInfo); return true; } void FSvgRenderer::calcLeg(SvgIdLayer * svgIdLayer, const QRectF & viewBox, ConnectorInfo * connectorInfo) { if (svgIdLayer->m_legId.isEmpty()) return; svgIdLayer->m_legColor = connectorInfo->legColor; QSizeF defaultSizeF = this->defaultSizeF(); svgIdLayer->m_legStrokeWidth = connectorInfo->legStrokeWidth * defaultSizeF.width() / viewBox.width(); /* DebugDialog::debug( QString("calcleg leg %1 %2 %3 %4") .arg(connectorInfo->legLine.p1().x()) .arg(connectorInfo->legLine.p1().y()) .arg(connectorInfo->legLine.p2().x()) .arg(connectorInfo->legLine.p2().y()) ); */ QMatrix matrix = this->matrixForElement(svgIdLayer->m_legId) * connectorInfo->legMatrix; QPointF p1 = matrix.map(connectorInfo->legLine.p1()); QPointF p2 = matrix.map(connectorInfo->legLine.p2()); double x1 = p1.x() * defaultSizeF.width() / viewBox.width(); double y1 = p1.y() * defaultSizeF.height() / viewBox.height(); double x2 = p2.x() * defaultSizeF.width() / viewBox.width(); double y2 = p2.y() * defaultSizeF.height() / viewBox.height(); QPointF center(defaultSizeF.width() / 2, defaultSizeF.height() / 2); double d1 = GraphicsUtils::distanceSqd(QPointF(x1, y1), center); double d2 = GraphicsUtils::distanceSqd(QPointF(x2, y2), center); // find the end which is closer to the center of the viewBox (which shouldn't include the leg) if (d1 <= d2) { svgIdLayer->m_legLine = QLineF(x1, y1, x2, y2); } else { svgIdLayer->m_legLine = QLineF(x2, y2, x1, y1); } } QPointF FSvgRenderer::calcTerminalPoint(const QString & terminalId, const QRectF & connectorRect, bool ignoreTerminalPoint, const QRectF & viewBox, QMatrix & terminalMatrix) { Q_UNUSED(terminalMatrix); QPointF terminalPoint = connectorRect.center() - connectorRect.topLeft(); // default spot is centered if (ignoreTerminalPoint) { return terminalPoint; } if (terminalId.isNull() || terminalId.isEmpty()) { return terminalPoint; } if (!this->elementExists(terminalId)) { DebugDialog::debug(QString("missing expected terminal point element %1").arg(terminalId)); return terminalPoint; } QRectF tBounds = this->boundsOnElement(terminalId); if (tBounds.isNull()) { return terminalPoint; } QSizeF defaultSizeF = this->defaultSizeF(); //DebugDialog::debug( QString("terminal %5 rect %1,%2,%3,%4").arg(tBounds.x()). //arg(tBounds.y()). //arg(tBounds.width()). //arg(tBounds.height()). //arg(terminalID) ); // matrixForElement only grabs parent matrices, not any transforms in the element itself //QMatrix tMatrix = this->matrixForElement(terminalId) ; //* terminalMatrix; //QRectF terminalRect = tMatrix.mapRect(tBounds); QRectF terminalRect = this->matrixForElement(terminalId).mapRect(tBounds); QPointF c = terminalRect.center(); QPointF q(c.x() * defaultSizeF.width() / viewBox.width(), c.y() * defaultSizeF.height() / viewBox.height()); terminalPoint = q - connectorRect.topLeft(); //DebugDialog::debug( QString("terminalagain %3 rect %1,%2 ").arg(terminalPoint.x()). //arg(terminalPoint.y()). //arg(terminalID) ); return terminalPoint; } QList FSvgRenderer::setUpNonConnectors(ViewLayer::ViewLayerPlacement viewLayerPlacement) { QList list; if (m_nonConnectorInfoHash.count() == 0) return list; foreach (QString nonConnectorID, m_nonConnectorInfoHash.keys()) { SvgIdLayer * svgIdLayer = new SvgIdLayer(ViewLayer::PCBView); svgIdLayer->m_svgId = nonConnectorID; QRectF bounds = this->boundsOnElement(nonConnectorID); if (bounds.isNull()) { delete svgIdLayer; continue; } QSizeF defaultSizeF = this->defaultSizeF(); QSize defaultSize = this->defaultSize(); if ((bounds.width()) == defaultSizeF.width() && (bounds.height()) == defaultSizeF.height()) { delete svgIdLayer; continue; } QRectF viewBox = this->viewBoxF(); ConnectorInfo * connectorInfo = m_nonConnectorInfoHash.value(nonConnectorID, NULL); if (connectorInfo && connectorInfo->gotCircle) { svgIdLayer->m_radius = connectorInfo->radius * defaultSizeF.width() / viewBox.width(); svgIdLayer->m_strokeWidth = connectorInfo->strokeWidth * defaultSizeF.width() / viewBox.width(); //bounds = connectorInfo->cbounds; } // matrixForElement only grabs parent matrices, not any transforms in the element itself //QMatrix matrix0 = connectorInfo->matrix * this->matrixForElement(nonConnectorID); //QRectF r1 = matrix0.mapRect(bounds); QRectF r1 = this->matrixForElement(nonConnectorID).mapRect(bounds); QRectF svgRect(r1.x() * defaultSize.width() / viewBox.width(), r1.y() * defaultSize.height() / viewBox.height(), r1.width() * defaultSize.width() / viewBox.width(), r1.height() * defaultSize.height() / viewBox.height()); QPointF center = svgRect.center() - svgRect.topLeft(); svgIdLayer->setPointRect(viewLayerPlacement, center, svgRect, true); list.append(svgIdLayer); } return list; } fritzing-app-0.9.2b/src/fsvgrenderer.h000066400000000000000000000110661250202676700177450ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FSVGRENDERER_H #define FSVGRENDERER_H #include #include #include #include #include #include #include "viewlayer.h" struct ConnectorInfo { bool gotCircle; double radius; double strokeWidth; QMatrix matrix; //QRectF cbounds; QMatrix terminalMatrix; QMatrix legMatrix; QString legColor; QLineF legLine; double legStrokeWidth; bool gotPath; }; typedef QHash RendererHash; struct LoadInfo { QString filename; QStringList connectorIDs; QStringList terminalIDs; QStringList legIDs; QString setColor; QString colorElementID; bool findNonConnectors; bool parsePaths; LoadInfo() { findNonConnectors = parsePaths = false; } }; class FSvgRenderer : public QSvgRenderer { Q_OBJECT public: FSvgRenderer(QObject * parent = 0); ~FSvgRenderer(); QByteArray loadSvg(const LoadInfo &); QByteArray loadSvg(const QString & filename); QByteArray loadSvg( const QByteArray & contents, const LoadInfo &); // for SvgSplitter loads QByteArray loadSvg( const QByteArray & contents, const QString & filename, bool findNonConnectors); // for SvgSplitter loads bool loadSvgString(const QString & svg); bool loadSvgString(const QString & svg, QString & newSvg); bool fastLoad(const QByteArray & contents); QByteArray finalLoad(QByteArray & cleanContents, const QString & filename); const QString & filename(); QSizeF defaultSizeF(); bool setUpConnector(class SvgIdLayer * svgIdLayer, bool ignoreTerminalPoint, ViewLayer::ViewLayerPlacement); QList setUpNonConnectors(ViewLayer::ViewLayerPlacement); public: static void cleanup(); static QSizeF parseForWidthAndHeight(QXmlStreamReader &); static QPixmap * getPixmap(QSvgRenderer * renderer, QSize size); static void initNames(); protected: bool determineDefaultSize(QXmlStreamReader &); QByteArray loadAux (const QByteArray & contents, const LoadInfo &); bool initConnectorInfo(QDomDocument &, const LoadInfo &); ConnectorInfo * initConnectorInfoStruct(QDomElement & connectorElement, const QString & filename, bool parsePaths); bool initConnectorInfoStructAux(QDomElement &, ConnectorInfo * connectorInfo, const QString & filename, bool parsePaths); bool initConnectorInfoCircle(QDomElement & element, ConnectorInfo * connectorInfo, const QString & filename); bool initConnectorInfoPath(QDomElement & element, ConnectorInfo * connectorInfo, const QString & filename); void initNonConnectorInfo(QDomDocument & domDocument, const QString & filename); void initNonConnectorInfoAux(QDomElement & element, const QString & filename); void initTerminalInfoAux(QDomElement & element, const LoadInfo &); void initLegInfoAux(QDomElement & element, const LoadInfo &, bool & gotOne); void initConnectorInfoAux(QDomElement & element, const LoadInfo &); QPointF calcTerminalPoint(const QString & terminalId, const QRectF & connectorRect, bool ignoreTerminalPoint, const QRectF & viewBox, QMatrix & terminalMatrix); bool initLegInfoAux(QDomElement & element, ConnectorInfo * connectorInfo); void calcLeg(SvgIdLayer *, const QRectF & viewBox, ConnectorInfo * connectorInfo); ConnectorInfo * getConnectorInfo(const QString & connectorID); void clearConnectorInfoHash(QHash & hash); protected: QString m_filename; QSizeF m_defaultSizeF; QHash m_connectorInfoHash; QHash m_nonConnectorInfoHash; public: static QString NonConnectorName; }; #endif fritzing-app-0.9.2b/src/help/000077500000000000000000000000001250202676700160245ustar00rootroot00000000000000fritzing-app-0.9.2b/src/help/aboutbox.cpp000066400000000000000000000237751250202676700203710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6968 $: $Author: irascibl@gmail.com $: $Date: 2013-04-15 17:44:14 +0200 (Mo, 15. Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include "aboutbox.h" #include "../debugdialog.h" #include "../version/version.h" #include "../utils/expandinglabel.h" AboutBox* AboutBox::Singleton = NULL; static const int AboutWidth = 390; static const int AboutText = 210; QString AboutBox::BuildType; AboutBox::AboutBox(QWidget *parent) : QWidget(parent) { Singleton = this; // To make the application not quit when the window closes this->setAttribute(Qt::WA_QuitOnClose, false); setFixedSize(AboutWidth, 430); // the background color setStyleSheet("background-color: #E8E8E8"); // the new Default Font QFont smallFont("Droid Sans", 11); QFont extraSmallFont("Droid Sans", 9); extraSmallFont.setLetterSpacing(QFont::PercentageSpacing, 92); // Big Icon QLabel *logoShield = new QLabel(this); logoShield->setPixmap(QPixmap(":/resources/images/AboutBoxLogoShield.png")); logoShield->setGeometry(17, 8, 356, 128); // Version String QLabel *versionMain = new QLabel(this); versionMain->setText(tr("Version %1.%2.%3 (%4%5 %6) %7 [Qt %8]") .arg(Version::majorVersion()) .arg(Version::minorVersion()) .arg(Version::minorSubVersion()) .arg(Version::modifier()) .arg(Version::revision()) .arg(Version::date()) .arg(BuildType) .arg(QT_VERSION_STR) ); versionMain->setFont(smallFont); versionMain->setGeometry(45, 150, 300, 20); versionMain->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); versionMain->setTextInteractionFlags(Qt::TextSelectableByMouse); // Link to website QLabel *linkToFritzing = new QLabel(this); linkToFritzing->setText(tr("www.fritzing.org")); linkToFritzing->setOpenExternalLinks(true); linkToFritzing->setFont(smallFont); linkToFritzing->setGeometry(45, 168, 300, 18); linkToFritzing->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); // Copyright messages QLabel *copyrightGNU = new QLabel(this); copyrightGNU->setText(tr("GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest")); copyrightGNU->setFont(extraSmallFont); copyrightGNU->setGeometry(0, 398, AboutWidth, 16); copyrightGNU->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); QLabel *CC = new QLabel(this); QPixmap cc(":/resources/images/aboutbox_CC.png"); CC->setPixmap(cc); CC->setGeometry(30, this->height() - cc.height(), cc.width(), cc.height()); QLabel *FHP = new QLabel(this); QPixmap fhp(":/resources/images/aboutbox_FHP.png"); FHP->setPixmap(fhp); FHP->setGeometry(360 - fhp.width(), this->height() - fhp.height(), fhp.width(), fhp.height()); int w = qMax(fhp.width(), cc.width()); QLabel *copyrightFHP = new QLabel(this); copyrightFHP->setText(tr("2007-%1 Fachhochschule Potsdam").arg(Version::year())); copyrightFHP->setFont(extraSmallFont); copyrightFHP->setGeometry(30 + w, 414, AboutWidth - 30 - 30 - w - w, 16); copyrightFHP->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); // Scrolling Credits Text // moved data out of credits.txt so we could apply translation QString data = QString("








") + "

" + tr("Fritzing is made by: ") + tr("Prof. Reto Wettach, André Knörig, Myriel Milicevic, ") + tr("Zach Eveland, Dirk van Oosterbosch, ") + tr("Jonathan Cohen, Marcus Paeschke, Omer Yosha, ") + tr("Travis Robertson, Stefan Hermann, Brendan Howell, ") + tr("Mariano Crowe, Johannes Landstorfer, ") + tr("Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, ") + tr("Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. ") + "

" + "

" + tr("Special thanks goes out to: ") + tr("Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, ") + tr("Durrell Bishop, David Cuartielles, Fabian Hemmert, ") + tr("Gero Herkenrath, Jeff Hoefs, Tom Hulbert, ") + tr("Tom Igoe, Hans-Peter Kadel, Till Savelkoul, ") + tr("Jan Sieber, Yaniv Steiner, Olaf Val, ") + tr("Michaela Vieser and Julia Werner.") + "

" + "

" + tr("Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, ") + tr("to Gianluca Urgese for the Italian translation, ") + tr("to Nuno Pessanha Santos for the Portuguese (European) translation, ") + tr("to Yuelin and Ninjia for the Chinese (Simplified) translation, ") + tr("to Hiroshi Suzuki for the Japanese translation, ") + tr("to Robert Lee for the Chinese (Traditional) translation, ") + tr("to Vladimir Savinov for the Russian translation, " ) + tr("to Steven Noppe and Davy Uittenbogerd for the Dutch translation, " ) + tr("to Josef Dustira for the Czech translation, " ) + tr("to Jinbuhm Kim for the Korean translation, " ) + tr("to Ĺubomír Duchoň for the Slovak translation, " ) + tr("to Alexander Kaltsas for the Greek translation, " ) + tr("to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, " ) + tr("to Cihan Mete Bahadır for the Turkish translation, " ) + tr("to Nikolay Stankov for the Bulgarian translation, " ) + tr("and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. " ) + "

" + "

" + tr("Fritzing is made possible with funding from the ") + tr("MWFK Brandenburg, the sponsorship of the Design ") + tr("Department of Bauhaus-University Weimar, ") + tr("IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, ") + tr("and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab.") + "

" + "

" + tr("Special thanks goes out as well to all the students ") + tr("and alpha testers who were brave enough to give ") + tr("Fritzing a test spin. ") + "

" + tr("







"); QPixmap fadepixmap(":/resources/images/aboutbox_scrollfade.png"); m_expandingLabel = new ExpandingLabel(this, AboutWidth); m_expandingLabel->setObjectName("aboutText"); m_expandingLabel->setLabelText(data); m_expandingLabel->setFont(smallFont); m_expandingLabel->setGeometry(0, AboutText, AboutWidth, fadepixmap.height()); // setAlignment only aligns the "current paragraph" // the QTextCursor code aligns all paragraphs QTextCursor cursor(m_expandingLabel->document()); cursor.select(QTextCursor::Document); QTextBlockFormat fmt; fmt.setAlignment(Qt::AlignCenter); cursor.mergeBlockFormat(fmt); // Add a fade out and a fade in the scrollArea QLabel *scrollFade = new QLabel(this); scrollFade->setPixmap(fadepixmap); scrollFade->setGeometry(0, AboutText, AboutWidth, fadepixmap.height()); scrollFade->setStyleSheet("background-color: none"); // auto scroll timer initialization m_restartAtTop = false; m_startTime = QTime::currentTime(); m_autoScrollTimer = new QTimer(this); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) m_autoScrollTimer->setTimerType(Qt::PreciseTimer); #endif connect(m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(scrollCredits())); } void AboutBox::resetScrollAnimation() { // Only called when the window is newly loaded m_autoScrollTimer->start(35); m_startTime.start(); } void AboutBox::scrollCredits() { if (m_startTime.elapsed() >= 0 ) { //int max = m_scrollArea->verticalScrollBar()->maximum(); //int v = m_scrollArea->widget()->sizeHint().height(); if (m_restartAtTop) { // Reset at the top m_startTime.start(); m_restartAtTop = false; m_expandingLabel->verticalScrollBar()->setValue(0); return; } if (m_expandingLabel->verticalScrollBar()->value() >= m_expandingLabel->verticalScrollBar()->maximum()) { // go and reset // m_startTime.start(); m_restartAtTop = true; } else { m_expandingLabel->verticalScrollBar()->setValue(m_expandingLabel->verticalScrollBar()->value() + 1); } } } void AboutBox::initBuildType(const QString & buildType) { BuildType = buildType; } void AboutBox::hideAbout() { //DebugDialog::debug("the AboutBox gets a hide action triggered"); if (Singleton != NULL) { Singleton->hide(); } } void AboutBox::showAbout() { //DebugDialog::debug("the AboutBox gets a show action triggered"); if (Singleton == NULL) { new AboutBox(); } // scroll text now to prevent a flash of text if text was visible the last time the about box was open Singleton->m_expandingLabel->verticalScrollBar()->setValue(0); Singleton->show(); } void AboutBox::closeAbout() { //DebugDialog::debug("the AboutBox gets a close action triggered"); // Note: not every close triggers this function. we better listen to closeEvent if (Singleton != NULL) { Singleton->close(); } } void AboutBox::closeEvent(QCloseEvent *event) { // called when the window is about to close //DebugDialog::debug("the AboutBox gets a closeEvent"); m_autoScrollTimer->stop(); event->accept(); } void AboutBox::keyPressEvent ( QKeyEvent * event ) { if ((event->key() == Qt::Key_W) && (event->modifiers() & Qt::ControlModifier) ) { // We get the ctrl + W / command + W key event //DebugDialog::debug("W key!"); this->closeAbout(); } } void AboutBox::show() { QWidget::show(); m_restartAtTop = true; resetScrollAnimation(); } fritzing-app-0.9.2b/src/help/aboutbox.h000066400000000000000000000035061250202676700200240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ABOUTBOX_H #define ABOUTBOX_H #include #include #include #include class AboutBox : public QWidget { Q_OBJECT private: AboutBox(QWidget *parent = 0); void resetScrollAnimation(); private: //QScrollArea *m_scrollArea; class ExpandingLabel * m_expandingLabel; bool m_restartAtTop; QTime m_startTime; QTimer *m_autoScrollTimer; public: static void hideAbout(); static void showAbout(); static void closeAbout(); // Maybe we don't need close as a public method (we only want to hide) static void initBuildType(const QString &); public slots: void scrollCredits(); protected: static AboutBox* Singleton; static QString BuildType; protected: void closeEvent ( QCloseEvent * event ); void keyPressEvent ( QKeyEvent * event ); void show(); }; #endif fritzing-app-0.9.2b/src/help/firsttimehelpdialog.cpp000066400000000000000000000130471250202676700225740ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include #include #include "firsttimehelpdialog.h" static FirstTimeHelpDialog * Singleton = NULL; static ViewLayer::ViewID TheViewID = ViewLayer::BreadboardView; static QHash TheTexts; FirstTimeHelpDialog::FirstTimeHelpDialog(QWidget *parent) : QDialog(parent) { // Let's set the icon this->setWindowIcon(QIcon(QPixmap(":resources/images/fritzing_icon.png"))); this->setObjectName("firstTimeHelpDialog"); setWindowTitle(tr("First Time Help")); m_label = new QLabel(); m_label->setWordWrap(true); m_label->setObjectName("firstTimeHelpDialogText"); QVBoxLayout * vLayout = new QVBoxLayout(); vLayout->addWidget(m_label); this->setLayout(vLayout); this->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint); } FirstTimeHelpDialog::~FirstTimeHelpDialog() { } void FirstTimeHelpDialog::setViewID(ViewLayer::ViewID viewID) { TheViewID = viewID; if (Singleton) { Singleton->m_label->setText(TheTexts.value(TheViewID, "")); } } void FirstTimeHelpDialog::showFirstTimeHelp() { init(); Singleton->m_label->setText(TheTexts.value(TheViewID, "")); Singleton->show(); } void FirstTimeHelpDialog::hideFirstTimeHelp() { init(); Singleton->hide(); } void FirstTimeHelpDialog::cleanup() { if (Singleton) { delete Singleton; Singleton = NULL; } } void FirstTimeHelpDialog::init() { if (TheTexts.count() == 0) { QString bbText = tr( "
" "The Breadboard View is meant to look like a real-life breadboard prototype." "

" "Begin by dragging a part from the Parts Bin, which is over at the top right. " "Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. " "The process is similar to how you would arrange things in the physical world. " "

" "After you're finished creating your sketch in the breadboard view, try the other views. " "You can switch views by clicking the Tabs at the top of the window. " "Because different views have different purposes, parts will look different in the other views." ); QString schText = tr( "Welcome to the Schematic View" "

" "This is a more abstract way to look at components and connections than the Breadboard View. " "You have the same elements as you have on your breadboard, " "they just look different. This representation is closer to the traditional diagrams used by engineers." "

" "After you have drawn wires between parts, you can press <Shift>-click with the mouse to create bend points and tidy up your connections. " "The Schematic View can help you check that you have made the right connections between components. " "You can also print out your schematic for documentation." ); QString pcbText = tr( "The PCB View is where you layout the components will on a physical PCB (Printed Circuit Board)." "

" "PCBs can be made at home or in a small lab using DIY etching processes. " "They also can be sent to professional PCB manufacturing services for more precise fabrication. " "
" "
" "The first thing you will need is a board to place your parts on. " "There should already be one in your sketch, but if not, " "drag in the board icon from the Parts Bin. The icon matches thie image to the right: " "" "" "
" "

" "To lay out your PCB, arrange all the components so they fit nicely on the board. " "Then try to shift them around to minimize the length and confusion of connections. " "You can also resize rectangular boards. " "
" "
" "Once the parts are sorted out, you connect them with copper traces. " "You can drag out a trace from individual connections or use " "the autorouter to generate them. " "The Autoroute button is at the bottom of the window. The button matches the image to the right:" "" "" "
" ); TheTexts.insert(ViewLayer::BreadboardView, bbText); TheTexts.insert(ViewLayer::SchematicView, schText); TheTexts.insert(ViewLayer::PCBView, pcbText); } if (Singleton == NULL) { Singleton = new FirstTimeHelpDialog(); } } fritzing-app-0.9.2b/src/help/firsttimehelpdialog.h000066400000000000000000000027771250202676700222510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FIRSTTIMEHELPDIALOG_H #define FIRSTTIMEHELPDIALOG_H #include #include #include "../viewlayer.h" class FirstTimeHelpDialog : public QDialog { Q_OBJECT private: FirstTimeHelpDialog(QWidget *parent = 0); ~FirstTimeHelpDialog(); protected: static void init(); public: static void setViewID(ViewLayer::ViewID); static void showFirstTimeHelp(); static void hideFirstTimeHelp(); static void cleanup(); protected: QLabel * m_label; }; #endif fritzing-app-0.9.2b/src/help/tipsandtricks.cpp000066400000000000000000000300721250202676700214140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include #include #include #include #include "tipsandtricks.h" TipsAndTricks* TipsAndTricks::Singleton = NULL; QList TipsAndTricks::TipSets; TipsAndTricks::TipsAndTricks(QWidget *parent) : QDialog(parent) { initTipSets(); // Let's set the icon this->setWindowIcon(QIcon(QPixmap(":resources/images/fritzing_icon.png"))); QString html(""); html += QString("

%1

").arg(tr("Fritzing Tips and Tricks")); html += "
    "; foreach (TipSet * tipSet, TipSets) { html += QString("
  • %1

      ").arg(tipSet->heading); foreach (QString tip, tipSet->tips) { html += QString("
    • %1
    • ").arg(tip); } html += "
  • "; } html += "
"; html += ""; Singleton = this; setWindowTitle(tr("Tips and Tricks")); resize(600, 500); m_textEdit = new QTextEdit(); m_textEdit->setReadOnly(true); m_textEdit->setHtml(html); QVBoxLayout * vLayout = new QVBoxLayout(this); vLayout->addWidget(m_textEdit); } void TipsAndTricks::initTipSets() { if (TipSets.count() > 0) return; QTime now = QTime::currentTime(); qsrand(now.msec()); QString localStorage = tr("Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. " "On Mac and Linux this is usually ~/.config/Fritzing/. " "Under Windows Vista and above, it is something like C:\\Users\\[user name]\\AppData\\Roaming\\Fritzing\\; " "under Windows XP is something like C:\\Documents and Settings\\[user name]\\Application Data\\Fritzing\\."); TipSet * ts = new TipSet; ts->heading = tr("examples"); ts->tips << tr("Get a jump start by looking at the example circuits under File > Examples."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("parts"); ts->tips << tr("Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords"); ts->tips << tr("If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor"); ts->tips << tr("An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon."); ts->tips << tr("The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin)."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("moving and selection"); ts->tips << tr("To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it."); ts->tips << tr("If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu)."); ts->tips << tr("To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units."); ts->tips << tr("Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("curves and bendable legs"); ts->tips << tr("In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging."); ts->tips << tr("In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down."); ts->tips << tr("In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("rotation"); ts->tips << tr("To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag."); ts->tips << tr("To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("layers and views"); ts->tips << tr("To drag the canvas, hold down the space bar and drag with the mouse."); ts->tips << tr("To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the Layers palette from the Window menu."); ts->tips << tr("When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("part labels"); ts->tips << tr("To edit a part label, double-click it, or use the text input widget in the inspector window."); ts->tips << tr("To display different properties in a part label, as well as rotate it, or change the font, right-click the label."); ts->tips << tr("To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("wires and bendpoints"); ts->tips << tr("To add a bendpoint to a wire, double-click where you want the bendpoint."); ts->tips << tr("To delete a bendpoint from a wire, double-click it."); ts->tips << tr("In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint."); ts->tips << tr("To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion."); ts->tips << tr("Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("connections"); ts->tips << tr("To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted."); ts->tips << tr("A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("parts editor"); ts->tips << tr("Check out Parts Editor Help under the Help Menu."); ts->tips << tr("Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties."); ts->tips << tr("In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key."); ts->tips << tr("You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use Show in Folder under the File Menu"); ts->tips << localStorage; ts->tips << tr("Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("pcb layout"); ts->tips << tr("Always lead a trace straight out of a pin. This helps to prevent short circuits."); ts->tips << tr("Through-hole parts can be traced from either side of a PCB."); ts->tips << tr("It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side."); ts->tips << tr("Route traces in 45-degree angles to reduce noise."); ts->tips << tr("If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them."); ts->tips << tr("You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format."); ts->tips << tr("Use copper-blocker parts to mask out areas that you want free of copper fill."); ts->tips << tr("To change trace width, select a trace then use the width combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128)."); ts->tips << tr("To create a custom shape for your PCB, import an SVG file."); ts->tips << tr("To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino"); TipSets.append(ts); ts = new TipSet; ts->heading = tr("pcb production"); ts->tips << tr("Smaller PCBs are more affortable than larger ones. Save space and money."); ts->tips << tr("Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote."); ts->tips << tr("When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("notes"); ts->tips << tr("To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again."); TipSets.append(ts); ts = new TipSet; ts->heading = tr("local file storage"); ts->tips << localStorage; TipSets.append(ts); } TipsAndTricks::~TipsAndTricks() { } void TipsAndTricks::hideTipsAndTricks() { if (Singleton != NULL) { Singleton->hide(); } } void TipsAndTricks::showTipsAndTricks() { if (Singleton == NULL) { new TipsAndTricks(); } Singleton->show(); } void TipsAndTricks::cleanup() { if (Singleton) { delete Singleton; Singleton = NULL; } } const QString & TipsAndTricks::randomTip() { int tipCount = 0; foreach (TipSet * tipSet, TipSets) { tipCount += tipSet->tips.count(); } if (tipCount == 0) return ___emptyString___; int ix = qrand() % tipCount; tipCount = 0; foreach (TipSet * tipSet, TipSets) { int count = tipSet->tips.count(); if (tipCount + count > ix) { return tipSet->tips.at(ix - tipCount); } tipCount += count; } // should not happen return ___emptyString___; } fritzing-app-0.9.2b/src/help/tipsandtricks.h000066400000000000000000000032011250202676700210530ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef TIPSANDTRICKS_H #define TIPSANDTRICKS_H #include #include #include #include #include #include "../utils/misc.h" struct TipSet { QString heading; QStringList tips; }; class TipsAndTricks : public QDialog { Q_OBJECT private: TipsAndTricks(QWidget *parent = 0); ~TipsAndTricks(); public: static void hideTipsAndTricks(); static void showTipsAndTricks(); static void cleanup(); static const QString & randomTip(); static void initTipSets(); protected: static TipsAndTricks* Singleton; static QList TipSets; QTextEdit* m_textEdit; }; #endif fritzing-app-0.9.2b/src/infoview/000077500000000000000000000000001250202676700167225ustar00rootroot00000000000000fritzing-app-0.9.2b/src/infoview/htmlinfoview.cpp000066400000000000000000001103121250202676700221370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include "htmlinfoview.h" #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../connectors/connectorshared.h" #include "../connectors/connector.h" #include "../fsvgrenderer.h" #include "../utils/flineedit.h" #include "../items/moduleidnames.h" #include "../items/paletteitem.h" #include "../utils/clickablelabel.h" #include "../utils/textutils.h" #define HTML_EOF "\n" QPixmap * NoIcon = NULL; const int HtmlInfoView::STANDARD_ICON_IMG_WIDTH = 32; const int HtmlInfoView::STANDARD_ICON_IMG_HEIGHT = 32; const int IconSpace = 0; static const int MaxSpinBoxWidth = 60; static const int AfterSpinBoxWidth = 5; ///////////////////////////////////// QLabel * addLabel(QHBoxLayout * hboxLayout, QPixmap * pixmap) { QLabel * label = new QLabel(); label->setObjectName("iconLabel"); label->setAutoFillBackground(true); label->setPixmap(*pixmap); label->setFixedSize(pixmap->size()); hboxLayout->addWidget(label); hboxLayout->addSpacing(IconSpace); return label; } QString format3(double d) { return QString("%1").arg(d, 0, 'f', 3); } ////////////////////////////////////// TagLabel::TagLabel(QWidget * parent) : QLabel(parent) { } QSize TagLabel::sizeHint() const { QSize hint = QLabel::sizeHint(); QString t = text(); if (t.isEmpty()) return hint; QFontMetricsF fm(this->font()); double textWidth = fm.width(t); QWidget * w = this->window(); QPoint pos(0,0); pos = this->mapTo(w, pos); int myWidth = w->width() - pos.x() - 10; if (textWidth < myWidth) { return hint; } int lines = qCeil(textWidth / myWidth); int h = lines * fm.height(); return QSize(myWidth, h); } ////////////////////////////////////// HtmlInfoView::HtmlInfoView(QWidget * parent) : QScrollArea(parent) { this->setWidgetResizable(true); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_lastTitleItemBase = NULL; m_lastTagsModelPart = NULL; m_lastConnectorItem = NULL; m_lastIconItemBase = NULL; m_lastPropsModelPart = NULL; m_lastPropsItemBase = NULL; m_tinyMode = false; m_partTitle = NULL; m_partUrl = NULL; m_partVersion = NULL; m_lockCheckbox = NULL; m_stickyCheckbox = NULL; m_connDescr = NULL; m_tagsTextLabel = NULL; m_lastSwappingEnabled = false; m_lastItemBase = NULL; m_setContentTimer.setSingleShot(true); m_setContentTimer.setInterval(10); connect(&m_setContentTimer, SIGNAL(timeout()), this, SLOT(setContent())); m_currentItem = NULL; m_currentSwappingEnabled = false; m_layerWidget = NULL; } HtmlInfoView::~HtmlInfoView() { foreach (PropThing * propThing, m_propThings) { delete propThing; } m_propThings.clear(); } void HtmlInfoView::init(bool tinyMode) { m_tinyMode = tinyMode; QFrame * mainFrame = new QFrame(this); mainFrame->setObjectName("infoViewMainFrame"); QVBoxLayout *vlo = new QVBoxLayout(mainFrame); vlo->setSpacing(0); vlo->setContentsMargins(0, 0, 0, 0); vlo->setSizeConstraint( QLayout::SetMinAndMaxSize ); /* Part Title */ m_titleEdit = new FLineEdit(mainFrame); m_titleEdit->setObjectName("instanceTitleEditor"); m_titleEdit->setToolTip(tr("Change the part label here")); m_titleEdit->setAlignment(Qt::AlignLeft); connect(m_titleEdit, SIGNAL(editingFinished()), this, SLOT(setInstanceTitle()), Qt::QueuedConnection); connect(m_titleEdit, SIGNAL(mouseEnter()), this, SLOT(instanceTitleEnter())); connect(m_titleEdit, SIGNAL(mouseLeave()), this, SLOT(instanceTitleLeave())); connect(m_titleEdit, SIGNAL(editable(bool)), this, SLOT(instanceTitleEditable(bool))); setInstanceTitleColors(m_titleEdit, QColor(0xaf, 0xaf, 0xb4), QColor(0x00, 0x00, 0x00)); //b3b3b3, 575757 m_titleEdit->setAutoFillBackground(true); vlo->addWidget(m_titleEdit); if (tinyMode) m_titleEdit->setVisible(false); /* Part Icons */ if (NoIcon == NULL) { NoIcon = new QPixmap(":/resources/images/icons/noicon.png"); } QFrame * iconFrame = new QFrame(mainFrame); iconFrame->setObjectName("iconFrame"); QHBoxLayout * hboxLayout = new QHBoxLayout(); hboxLayout->setContentsMargins(0, 0, 0, 0); hboxLayout->addSpacing(IconSpace); m_icon1 = addLabel(hboxLayout, NoIcon); m_icon1->setToolTip(tr("Part breadboard view image")); m_icon2 = addLabel(hboxLayout, NoIcon); m_icon2->setToolTip(tr("Part schematic view image")); m_icon3 = addLabel(hboxLayout, NoIcon); m_icon3->setToolTip(tr("Part pcb view image")); QVBoxLayout * versionLayout = new QVBoxLayout(); QHBoxLayout * subVersionLayout = new QHBoxLayout(); m_partVersion = new QLabel(); m_partVersion->setObjectName("infoViewPartVersion"); m_partVersion->setToolTip(tr("Part version number")); m_partVersion->setOpenExternalLinks(false); m_partVersion->setAlignment(Qt::AlignLeft | Qt::AlignTop); connect(m_partVersion, SIGNAL(linkActivated(const QString &)), this, SLOT(clickObsolete(const QString &))); subVersionLayout->addWidget(m_partVersion, 0, Qt::AlignLeft); subVersionLayout->addStretch(1); versionLayout->addLayout(subVersionLayout); hboxLayout->addLayout(versionLayout); hboxLayout->addSpacerItem(new QSpacerItem(IconSpace, 1, QSizePolicy::Expanding)); iconFrame->setLayout(hboxLayout); vlo->addWidget(iconFrame); m_partUrl = new TagLabel(this); m_partUrl->setWordWrap(false); m_partUrl->setObjectName("infoViewPartUrl"); m_partUrl->setOpenExternalLinks(true); vlo->addWidget(m_partUrl); if (tinyMode) m_partUrl->setVisible(false); m_partTitle = new TagLabel(this); m_partTitle->setWordWrap(true); m_partTitle->setObjectName("infoViewPartTitle"); m_partTitle->setOpenExternalLinks(true); vlo->addWidget(m_partTitle); if (tinyMode) m_partTitle->setVisible(false); m_placementLabel = new QLabel(tr("Placement"), NULL); m_placementLabel->setObjectName("expandableViewLabel"); vlo->addWidget(m_placementLabel); m_placementFrame = new QFrame(this); m_placementFrame->setObjectName("infoViewPropertyFrame"); m_placementLayout = new QGridLayout(m_placementFrame); m_placementLayout->setSpacing(0); m_placementLayout->setContentsMargins(0, 0, 0, 0); m_layerLabel = new QLabel(tr("pcb layer"), this); m_layerLabel->setObjectName("propNameLabel"); m_layerLabel->setWordWrap(true); m_placementLayout->addWidget(m_layerLabel, 0, 0); m_layerFrame = new QFrame(this); m_layerFrame->setObjectName("propValueFrame"); m_layerLayout = new QVBoxLayout(m_layerFrame); m_layerLayout->setSpacing(0); m_layerLayout->setContentsMargins(0, 0, 0, 0); m_layerFrame->setLayout(m_layerLayout); m_placementLayout->addWidget(m_layerFrame, 0, 1); makeLocationFrame(); m_placementLayout->addWidget(m_locationLabel, 1, 0); m_placementLayout->addWidget(m_locationFrame, 1, 1); makeRotationFrame(); m_placementLayout->addWidget(m_rotationLabel, 2, 0); m_placementLayout->addWidget(m_rotationFrame, 2, 1); makeLockFrame(); m_placementLayout->addWidget(m_lockLabel, 3, 0); m_placementLayout->addWidget(m_lockFrame, 3, 1); m_placementFrame->setLayout(m_placementLayout); vlo->addWidget(m_placementFrame); m_propLabel = new QLabel(tr("Properties"), NULL); m_propLabel->setObjectName("expandableViewLabel"); vlo->addWidget(m_propLabel); m_propFrame = new QFrame(this); m_propFrame->setObjectName("infoViewPropertyFrame"); m_propLayout = new QGridLayout(m_propFrame); m_propLayout->setSpacing(0); m_propLayout->setContentsMargins(0, 0, 0, 0); m_propFrame->setLayout(m_propLayout); vlo->addWidget(m_propFrame); m_tagLabel = new QLabel(tr("Tags"), NULL); m_tagLabel->setObjectName("expandableViewLabel"); vlo->addWidget(m_tagLabel); if (tinyMode) m_tagLabel->setVisible(false); m_tagsTextLabel = new TagLabel(this); m_tagsTextLabel->setWordWrap(true); m_tagsTextLabel->setObjectName("tagsValue"); vlo->addWidget(m_tagsTextLabel); if (tinyMode) m_tagsTextLabel->setVisible(false); m_connLabel = new QLabel(tr("Connections"), NULL); m_connLabel->setObjectName("expandableViewLabel"); vlo->addWidget(m_connLabel); if (tinyMode) m_connLabel->setVisible(false); m_connFrame = new QFrame(this); m_connFrame->setObjectName("connectionsFrame"); QGridLayout * connLayout = new QGridLayout(m_connFrame); connLayout->setSpacing(0); connLayout->setContentsMargins(0, 0, 0, 0); m_connFrame->setLayout(connLayout); QLabel * descrLabel = new QLabel(tr("conn."), this); descrLabel->setObjectName("connectionsLabel"); m_connDescr = new QLabel(this); m_connDescr->setObjectName("connectionsValue"); connLayout->addWidget(descrLabel, 0, 0); connLayout->addWidget(m_connDescr, 0, 1); QLabel * nameLabel = new QLabel(tr("name"), this); nameLabel->setObjectName("connectionsLabel"); m_connName = new QLabel(this); m_connName->setObjectName("connectionsValue"); connLayout->addWidget(nameLabel, 1, 0); connLayout->addWidget(m_connName, 1, 1); QLabel * typeLabel = new QLabel(tr("type"), this); typeLabel->setObjectName("connectionsLabel"); m_connType = new QLabel(this); m_connType->setObjectName("connectionsValue"); connLayout->addWidget(typeLabel, 2, 0); connLayout->addWidget(m_connType, 2, 1); vlo->addWidget(m_connFrame); if (m_tinyMode) m_connFrame->setVisible(false); vlo->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); mainFrame->setLayout(vlo); this->setWidget(mainFrame); } void HtmlInfoView::cleanup() { if (NoIcon) { delete NoIcon; NoIcon = NULL; } } void HtmlInfoView::viewItemInfo(InfoGraphicsView *, ItemBase* item, bool swappingEnabled) { m_setContentTimer.stop(); m_lastItemBase = m_pendingItemBase = item; m_lastSwappingEnabled = m_pendingSwappingEnabled = swappingEnabled; m_setContentTimer.start(); } void HtmlInfoView::hoverEnterItem(InfoGraphicsView *, QGraphicsSceneHoverEvent *, ItemBase * item, bool swappingEnabled) { m_setContentTimer.stop(); m_pendingItemBase = item; m_pendingSwappingEnabled = swappingEnabled; m_setContentTimer.start(); } void HtmlInfoView::hoverLeaveItem(InfoGraphicsView *, QGraphicsSceneHoverEvent *, ItemBase * itemBase){ Q_UNUSED(itemBase); //DebugDialog::debug(QString("hoverLeaveItem itembase %1").arg(itemBase ? itemBase->instanceTitle() : "NULL")); m_setContentTimer.stop(); m_pendingItemBase = m_lastItemBase; m_pendingSwappingEnabled = m_lastSwappingEnabled; m_setContentTimer.start(); } void HtmlInfoView::viewConnectorItemInfo(QGraphicsSceneHoverEvent *, ConnectorItem * connectorItem) { int count = connectorItem ? connectorItem->connectionsCount() : 0; if (m_lastConnectorItem == connectorItem && m_lastConnectorItemCount == count) return; m_lastConnectorItem = connectorItem; m_lastConnectorItemCount = count; Connector * connector = NULL; if (connectorItem) { if (connectorItem->attachedTo() != m_lastItemBase) { return; } connector = connectorItem->connector(); } if (m_connDescr) { m_connDescr->setText(connectorItem ? tr("connected to %n item(s)", "", connectorItem->connectionsCount()) : ""); m_connName->setText(connector ? connector->connectorSharedName() : ""); m_connType->setText(connector ? Connector::connectorNameFromType(connector->connectorType()) : ""); } } void HtmlInfoView::hoverEnterConnectorItem(InfoGraphicsView *igv, QGraphicsSceneHoverEvent *event, ConnectorItem * item, bool swappingEnabled) { Q_UNUSED(event) Q_UNUSED(swappingEnabled) Q_UNUSED(igv) viewConnectorItemInfo(event, item); } void HtmlInfoView::hoverLeaveConnectorItem(InfoGraphicsView *igv, QGraphicsSceneHoverEvent *event, ConnectorItem *connItem) { Q_UNUSED(event); Q_UNUSED(connItem); Q_UNUSED(igv); viewConnectorItemInfo(event, NULL); } void HtmlInfoView::appendStuff(ItemBase* item, bool swappingEnabled) { Wire *wire = qobject_cast(item); if (wire) { appendWireStuff(wire, swappingEnabled); } else { appendItemStuff(item, swappingEnabled); } } void HtmlInfoView::appendWireStuff(Wire* wire, bool swappingEnabled) { if (wire == NULL) return; ModelPart *modelPart = wire->modelPart(); if (modelPart == NULL) return; if (modelPart->modelPartShared() == NULL) return; QString autoroutable = wire->getAutoroutable() ? tr("(autoroutable)") : ""; QString nameString = tr("Wire"); if (swappingEnabled) { if (wire->getRatsnest()) { nameString = tr("Ratsnest wire"); } else if(wire->getTrace()) { nameString = tr("Trace wire %1").arg(autoroutable); } } else { nameString = modelPart->description(); } partTitle(nameString, modelPart->version(), modelPart->url(), modelPart->isObsolete()); m_lockFrame->setVisible(false); m_lockLabel->setVisible(false); m_locationFrame->setVisible(false); m_locationLabel->setVisible(false); m_rotationFrame->setVisible(false); m_rotationLabel->setVisible(false); setUpTitle(wire); setUpIcons(wire, swappingEnabled); displayProps(modelPart, wire, swappingEnabled); bool hasLayer = (wire->viewID() == ViewLayer::PCBView) && wire->getViewGeometry().getPCBTrace(); m_placementFrame->setVisible(hasLayer); m_placementLabel->setVisible(hasLayer); addTags(modelPart); } void HtmlInfoView::appendItemStuff(ItemBase* base, bool swappingEnabled) { if (base == NULL) return; appendItemStuff(base, base->modelPart(), swappingEnabled); } void HtmlInfoView::appendItemStuff(ItemBase * itemBase, ModelPart * modelPart, bool swappingEnabled) { if (modelPart == NULL) return; if (modelPart->modelPartShared() == NULL) return; setUpTitle(itemBase); setUpIcons(itemBase, swappingEnabled); QString nameString; if (swappingEnabled) { nameString = (itemBase) ? itemBase->getInspectorTitle() : modelPart->title(); } else { nameString = modelPart->description(); } partTitle(nameString, modelPart->version(), modelPart->url(), modelPart->isObsolete()); m_lockFrame->setVisible(swappingEnabled); m_lockLabel->setVisible(swappingEnabled); m_lockCheckbox->setChecked(itemBase->moveLock()); m_locationFrame->setVisible(swappingEnabled); m_locationLabel->setVisible(swappingEnabled); m_locationFrame->setDisabled(itemBase->moveLock()); m_rotationFrame->setVisible(swappingEnabled); m_rotationLabel->setVisible(swappingEnabled); m_rotationFrame->setEnabled(itemBase->rotationAllowed()); setLocation(itemBase); setRotation(itemBase); if (itemBase->isBaseSticky()) { m_stickyCheckbox->setVisible(true); m_stickyCheckbox->setChecked(itemBase->isSticky()); } else { m_stickyCheckbox->setVisible(false); } displayProps(modelPart, itemBase, swappingEnabled); addTags(modelPart); m_placementLabel->setVisible(swappingEnabled); m_placementFrame->setVisible(swappingEnabled); } void HtmlInfoView::setContent() { m_setContentTimer.stop(); //DebugDialog::debug(QString("start updating %1").arg(QTime::currentTime().toString("HH:mm:ss.zzz"))); if (m_pendingItemBase == NULL) { setNullContent(); m_setContentTimer.stop(); return; } //DebugDialog::debug(QString("pending %1").arg(m_pendingItemBase->title())); m_currentSwappingEnabled = m_pendingSwappingEnabled; appendStuff(m_pendingItemBase, m_pendingSwappingEnabled); setCurrentItem(m_pendingItemBase); if (!m_tinyMode) { m_connFrame->setVisible(m_pendingSwappingEnabled); m_tagLabel->setVisible(true); m_connLabel->setVisible(m_pendingSwappingEnabled); } m_propLabel->setVisible(true); m_propFrame->setVisible(true); m_setContentTimer.stop(); //DebugDialog::debug(QString("end updating %1").arg(QTime::currentTime().toString("HH:mm:ss.zzz"))); } QSize HtmlInfoView::sizeHint() const { return QSize(DockWidthDefault, InfoViewHeightDefault); } void HtmlInfoView::setCurrentItem(ItemBase * item) { m_currentItem = item; } void HtmlInfoView::unregisterCurrentItem() { m_setContentTimer.stop(); setCurrentItem(NULL); m_pendingItemBase = NULL; m_setContentTimer.start(); } void HtmlInfoView::unregisterCurrentItemIf(long id) { if (m_currentItem == NULL) { return; } if (m_currentItem->id() == id) { unregisterCurrentItem(); } } ItemBase *HtmlInfoView::currentItem() { return m_currentItem; } void HtmlInfoView::reloadContent(InfoGraphicsView * infoGraphicsView) { if(m_currentItem) { viewItemInfo(infoGraphicsView, m_currentItem, m_currentSwappingEnabled); } } void HtmlInfoView::setNullContent() { setUpTitle(NULL); partTitle("", "", "", false); setUpIcons(NULL, false); displayProps(NULL, NULL, false); addTags(NULL); viewConnectorItemInfo(NULL, NULL); m_connFrame->setVisible(false); m_propFrame->setVisible(false); m_propLabel->setVisible(false); m_placementFrame->setVisible(false); m_placementLabel->setVisible(false); m_tagLabel->setVisible(false); m_connLabel->setVisible(false); } void HtmlInfoView::setInstanceTitle() { FLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; if (!edit->isEnabled()) return; if (m_currentItem == NULL) return; m_currentItem->setInspectorTitle(m_partTitle->text(), edit->text()); } void HtmlInfoView::instanceTitleEnter() { FLineEdit * edit = qobject_cast(sender()); if (edit->isEnabled()) { setInstanceTitleColors(edit, QColor(0xeb, 0xeb, 0xee), QColor(0x00, 0x00, 0x00)); //c8c8c8, 575757 } } void HtmlInfoView::instanceTitleLeave() { FLineEdit * edit = qobject_cast(sender()); if (edit->isEnabled()) { setInstanceTitleColors(edit, QColor(0xd2, 0xd2, 0xd7), QColor(0x00, 0x00, 0x00)); //b3b3b3, 575757 } } void HtmlInfoView::instanceTitleEditable(bool editable) { FLineEdit * edit = qobject_cast(sender()); if (editable) { setInstanceTitleColors(edit, QColor(0xff, 0xff, 0xff), QColor(0x00, 0x00, 0x00)); //fcfcfc, 000000 } else { setInstanceTitleColors(edit, QColor(0xd2, 0xd2, 0xd7), QColor(0x00, 0x00, 0x00)); //b3b3b3, 57575 } } void HtmlInfoView::setInstanceTitleColors(FLineEdit * edit, const QColor & base, const QColor & text) { edit->setStyleSheet(QString("background: rgb(%1,%2,%3); color: rgb(%4,%5,%6);") .arg(base.red()).arg(base.green()).arg(base.blue()) .arg(text.red()).arg(text.green()).arg(text.blue()) ); } void HtmlInfoView::setUpTitle(ItemBase * itemBase) { if (itemBase == m_lastTitleItemBase) { if (itemBase == NULL) return; if (itemBase->instanceTitle().compare(m_titleEdit->text()) == 0) return; } m_lastTitleItemBase = itemBase; bool titleEnabled = true; if (itemBase != NULL) { QString title = itemBase->getInspectorTitle(); if (title.isEmpty()) { // assumes a part with an empty title only comes from the parts bin palette titleEnabled = false; title = itemBase->title(); } if (itemBase->viewID() == ViewLayer::IconView) titleEnabled = false; m_titleEdit->setText(title); } else { titleEnabled = false; m_titleEdit->setText(""); } m_titleEdit->setEnabled(titleEnabled); // helps keep it left aligned? m_titleEdit->setCursorPosition(0); } void HtmlInfoView::setUpIcons(ItemBase * itemBase, bool swappingEnabled) { if (m_lastIconItemBase == itemBase) return; m_lastIconItemBase = itemBase; QPixmap *pixmap1 = NULL; QPixmap *pixmap2 = NULL; QPixmap *pixmap3 = NULL; QSize size = NoIcon->size(); if (itemBase) { itemBase->getPixmaps(pixmap1, pixmap2, pixmap3, swappingEnabled, size); } QPixmap* use1 = pixmap1; QPixmap* use2 = pixmap2; QPixmap* use3 = pixmap3; if (use1 == NULL) use1 = NoIcon; if (use2 == NULL) use2 = NoIcon; if (use3 == NULL) use3 = NoIcon; m_icon1->setPixmap(*use1); m_icon2->setPixmap(*use2); m_icon3->setPixmap(*use3); if (pixmap1 != NULL) delete pixmap1; if (pixmap2 != NULL) delete pixmap2; if (pixmap3 != NULL) delete pixmap3; } void HtmlInfoView::addTags(ModelPart * modelPart) { if (m_tagsTextLabel == NULL) return; if (m_lastTagsModelPart == modelPart) return; m_lastTagsModelPart = modelPart; if (modelPart == NULL || modelPart->tags().isEmpty()) { m_tagsTextLabel->setText(""); return; } m_tagsTextLabel->setText(modelPart->tags().join(", ")); } void HtmlInfoView::partTitle(const QString & title, const QString & version, const QString & url, bool isObsolete) { if (m_partTitle == NULL) return; if (m_lastPartTitle == title && m_lastPartVersion == version) return; m_lastPartTitle = title; m_lastPartVersion = version; if (!m_tinyMode) { if (url.isEmpty()) { m_partUrl->setVisible(false); m_partUrl->setText(""); } else { m_partUrl->setText(QString("%1").arg(url)); m_partUrl->setVisible(true); } } m_partTitle->setText(title); if (!version.isEmpty()) { m_partVersion->setText(tr("v. %1 %2").arg(version).arg(isObsolete ? QString("%1").arg(tr("obsolete")) : "")); } else m_partVersion->setText(""); } void HtmlInfoView::displayProps(ModelPart * modelPart, ItemBase * itemBase, bool swappingEnabled) { bool repeatPossible = (modelPart == m_lastPropsModelPart && itemBase == m_lastPropsItemBase && swappingEnabled == m_lastPropsSwappingEnabled); if (repeatPossible && modelPart == NULL && itemBase == NULL) { //DebugDialog::debug("display props bail"); return; } m_propLayout->setEnabled(false); if (repeatPossible) { DebugDialog::debug(QString("repeat possible %1").arg(repeatPossible)); } bool wantDebug = false; #ifndef QT_NO_DEBUG wantDebug = true; #endif QStringList keys; QHash properties = getPartProperties(modelPart, itemBase, wantDebug, keys); QString family = properties.value("family", "").toLower(); bool sl = false; if (keys.contains("layer")) { keys.removeOne("layer"); sl = (itemBase->viewID() == ViewLayer::PCBView); } showLayers(sl, itemBase, family, properties.value("layer", ""), swappingEnabled); int ix = 0; foreach(QString key, keys) { if (ix >= m_propThings.count()) { //DebugDialog::debug(QString("new prop thing %1").arg(ix)); PropThing * propThing = new PropThing; propThing->m_plugin = NULL; m_propThings.append(propThing); QLabel * propNameLabel = new QLabel(this); propNameLabel->setObjectName("propNameLabel"); propNameLabel->setWordWrap(true); propThing->m_name = propNameLabel; m_propLayout->addWidget(propNameLabel, ix, 0); QFrame * valueFrame = new QFrame(this); valueFrame->setObjectName("propValueFrame"); QVBoxLayout * vlayout = new QVBoxLayout(valueFrame); vlayout->setSpacing(0); vlayout->setContentsMargins(0, 0, 0, 0); propThing->m_layout = vlayout; propThing->m_frame = valueFrame; QLabel * propValueLabel = new QLabel(valueFrame); propValueLabel->setObjectName("propValueLabel"); propValueLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); vlayout->addWidget(propValueLabel); propThing->m_value = propValueLabel; m_propLayout->addWidget(valueFrame, ix, 1); } PropThing * propThing = m_propThings.at(ix++); QWidget * oldPlugin = propThing->m_plugin; propThing->m_plugin = NULL; QString value = properties.value(key,""); QString translatedName = ItemBase::translatePropertyName(key); QString resultKey, resultValue; QWidget * resultWidget = oldPlugin; bool result = false; bool hide = false; if (itemBase != NULL) { result = itemBase->collectExtraInfo(propThing->m_name->parentWidget(), family, key, value, swappingEnabled, resultKey, resultValue, resultWidget, hide); } QString newName; QString newValue; QWidget * newWidget = NULL; if (result && !hide) { newName = resultKey; if (resultWidget) { newWidget = resultWidget; if (resultWidget != oldPlugin) { propThing->m_layout->addWidget(resultWidget); } else { oldPlugin = NULL; } //DebugDialog::debug(QString("adding %1 %2").arg(newName).arg((long) resultWidget, 0, 16)); propThing->m_plugin = resultWidget; } else { newValue = resultValue; } } else { newName = translatedName; newValue = value; } if (oldPlugin) { clearPropThingPlugin(propThing, oldPlugin); } if (propThing->m_name->text().compare(newName) != 0) { propThing->m_name->setText(newName); } propThing->m_name->setVisible(!hide); propThing->m_frame->setVisible(!hide); if (newWidget == NULL && propThing->m_value->text().compare(newValue) != 0) { propThing->m_value->setText(newValue); } propThing->m_value->setVisible(newWidget == NULL && !hide); } for (int jx = ix; jx < m_propThings.count(); jx++) { PropThing * propThing = m_propThings.at(jx); propThing->m_name->setVisible(false); propThing->m_value->setVisible(false); propThing->m_frame->setVisible(false); if (propThing->m_plugin) { propThing->m_plugin->setVisible(false); } } m_propLayout->setEnabled(true); /* foreach (PropThing * propThing, m_propThings) { if (propThing->m_layout->count() > 1) { DebugDialog::debug(QString("too many %1").arg(propThing->m_layout->count())); } } */ } void HtmlInfoView::clearPropThingPlugin(PropThing * propThing) { if (propThing->m_plugin) { clearPropThingPlugin(propThing, propThing->m_plugin); propThing->m_plugin = NULL; } } void HtmlInfoView::clearPropThingPlugin(PropThing * propThing, QWidget * plugin) { //DebugDialog::debug(QString("clearing %1").arg((long) plugin, 0, 16)); propThing->m_layout->removeWidget(plugin); plugin->blockSignals(true); plugin->setVisible(false); // seems to trigger an unwanted focus out signal plugin->deleteLater(); } QHash HtmlInfoView::getPartProperties(ModelPart * modelPart, ItemBase * itemBase, bool wantDebug, QStringList & keys) { QHash properties; QString family; QString partNumber; if (modelPart != NULL && itemBase != NULL) { properties = itemBase->prepareProps(modelPart, wantDebug, keys); } return properties; } void HtmlInfoView::changeLock(bool lockState) { if (m_currentItem == NULL) return; if (m_currentItem->itemType() == ModelPart::Wire) return; m_currentItem->setMoveLock(lockState); m_locationFrame->setDisabled(lockState); m_rotationFrame->setDisabled(lockState); } void HtmlInfoView::changeSticky(bool lockState) { if (m_currentItem == NULL) return; if (m_currentItem->itemType() == ModelPart::Wire) return; m_currentItem->setLocalSticky(lockState); } void HtmlInfoView::clickObsolete(const QString &) { emit clickObsoleteSignal(); } void HtmlInfoView::showLayers(bool show, ItemBase * itemBase, const QString & family, const QString & value, bool swappingEnabled) { if (m_layerWidget) { m_layerLayout->removeWidget(m_layerWidget); m_layerWidget->blockSignals(true); m_layerWidget->setVisible(false); // seems to trigger an unwanted focus out signal m_layerWidget->deleteLater(); m_layerWidget = NULL; } if (itemBase == NULL) show = false; m_layerFrame->setVisible(show); m_layerLabel->setVisible(show); if (!show) return; QString resultKey, resultValue; bool hide; bool result = itemBase->collectExtraInfo(m_layerLabel->parentWidget(), family, "layer", value, swappingEnabled, resultKey, resultValue, m_layerWidget, hide); if (result && m_layerWidget != NULL) { m_layerLayout->addWidget(m_layerWidget); } } void HtmlInfoView::makeLockFrame() { m_lockLabel = new QLabel(" ", this); m_lockLabel->setObjectName("propNameLabel"); m_lockLabel->setWordWrap(true); m_lockFrame = new QFrame(this); QHBoxLayout * lockLayout = new QHBoxLayout(); lockLayout->setSpacing(0); lockLayout->setContentsMargins(0, 0, 0, 0); m_lockFrame->setObjectName("propValueFrame"); m_lockCheckbox = new QCheckBox(tr("Locked")); m_lockCheckbox->setObjectName("infoViewLockCheckbox"); m_lockCheckbox->setToolTip(tr("Change the locked state of the part in this view. A locked part can't be moved.")); connect(m_lockCheckbox, SIGNAL(clicked(bool)), this, SLOT(changeLock(bool))); lockLayout->addWidget(m_lockCheckbox); lockLayout->addSpacing(10); m_stickyCheckbox = new QCheckBox(tr("Sticky")); m_stickyCheckbox->setObjectName("infoViewLockCheckbox"); m_stickyCheckbox->setToolTip(tr("Change the \"sticky\" state of the part in this view. When a sticky part is moved, objects on top of it also move.")); connect(m_stickyCheckbox, SIGNAL(clicked(bool)), this, SLOT(changeSticky(bool))); lockLayout->addWidget(m_stickyCheckbox); lockLayout->addSpacerItem(new QSpacerItem(1,1, QSizePolicy::Expanding)); m_lockFrame->setLayout(lockLayout); } void HtmlInfoView::makeLocationFrame() { m_locationLabel = new QLabel(tr("location"), this); m_locationLabel->setObjectName("propNameLabel"); m_locationLabel->setWordWrap(true); m_locationFrame = new QFrame(this); QHBoxLayout * locationLayout = new QHBoxLayout(); locationLayout->setSpacing(0); locationLayout->setContentsMargins(0, 0, 0, 0); m_locationFrame->setObjectName("propValueFrame"); m_xEdit = new QDoubleSpinBox; m_xEdit->setDecimals(3); m_xEdit->setRange(-99999.999, 99999.999); m_xEdit->setKeyboardTracking(false); m_xEdit->setObjectName("infoViewDoubleSpinBox"); m_xEdit->setMaximumWidth(MaxSpinBoxWidth); m_xEdit->setMinimumWidth(MaxSpinBoxWidth); m_xEdit->setLocale(QLocale::C); locationLayout->addWidget(m_xEdit); locationLayout->addSpacing(AfterSpinBoxWidth); m_yEdit = new QDoubleSpinBox; m_yEdit->setDecimals(3); m_yEdit->setRange(-99999.999, 99999.999); m_yEdit->setKeyboardTracking(false); m_yEdit->setObjectName("infoViewDoubleSpinBox"); m_yEdit->setMaximumWidth(MaxSpinBoxWidth); m_yEdit->setMinimumWidth(MaxSpinBoxWidth); m_yEdit->setLocale(QLocale::C); locationLayout->addWidget(m_yEdit); locationLayout->addSpacing(3); m_unitsLabel = new ClickableLabel("px", this); m_unitsLabel->setObjectName("infoViewSpinBoxLabel"); m_unitsLabel->setCursor(Qt::PointingHandCursor); locationLayout->addWidget(m_unitsLabel); locationLayout->addSpacerItem(new QSpacerItem(1,1, QSizePolicy::Expanding)); m_locationFrame->setLayout(locationLayout); connect(m_xEdit, SIGNAL(valueChanged(double)), this, SLOT(xyEntry())); connect(m_yEdit, SIGNAL(valueChanged(double)), this, SLOT(xyEntry())); connect(m_unitsLabel, SIGNAL(clicked()), this, SLOT(unitsClicked())); unitsClicked(); // increments from px so that default is inches } void HtmlInfoView::makeRotationFrame() { m_rotationLabel = new QLabel(tr("rotation"), this); m_rotationLabel->setObjectName("propNameLabel"); m_rotationLabel->setWordWrap(true); m_rotationFrame = new QFrame(this); QHBoxLayout * rotationLayout = new QHBoxLayout(); rotationLayout->setSpacing(0); rotationLayout->setContentsMargins(0, 0, 0, 0); m_rotationFrame->setObjectName("propValueFrame"); m_rotEdit = new QDoubleSpinBox; m_rotEdit->setDecimals(1); m_rotEdit->setRange(-360, 360); m_rotEdit->setKeyboardTracking(false); m_rotEdit->setObjectName("infoViewDoubleSpinBox"); m_rotEdit->setMaximumWidth(MaxSpinBoxWidth); m_rotEdit->setMinimumWidth(MaxSpinBoxWidth); m_rotEdit->setLocale(QLocale::C); rotationLayout->addWidget(m_rotEdit); rotationLayout->addSpacing(AfterSpinBoxWidth); QLabel * label = new QLabel(tr("degrees"), this); label->setObjectName("infoViewSpinBoxLabel"); rotationLayout->addWidget(label); rotationLayout->addSpacerItem(new QSpacerItem(1,1, QSizePolicy::Expanding)); m_rotationFrame->setLayout(rotationLayout); connect(m_rotEdit, SIGNAL(valueChanged(double)), this, SLOT(rotEntry())); } void HtmlInfoView::unitsClicked() { QString units = m_unitsLabel->text(); QString xs = m_xEdit->text(); QString ys = m_yEdit->text(); double x = TextUtils::convertToInches(xs + units); double y = TextUtils::convertToInches(ys + units); double dpi = 1; double step = 1; if (units.compare("mm") == 0) { units = "px"; dpi = 90; step = 1; } else if (units.compare("px") == 0) { units = "in"; dpi = 1; step = 0.1; } else if (units.compare("in") == 0) { units = "mm"; dpi = 25.4; step = 1; } else { units = "in"; dpi = 1; step = 0.1; } m_unitsLabel->setText(units); m_xEdit->blockSignals(true); m_yEdit->blockSignals(true); m_xEdit->setSingleStep(step); m_yEdit->setSingleStep(step); if (!xs.isEmpty()) m_xEdit->setValue(x * dpi); if (!ys.isEmpty()) m_yEdit->setValue(y * dpi); m_xEdit->blockSignals(false); m_yEdit->blockSignals(false); } void HtmlInfoView::setLocation(ItemBase * itemBase) { if (itemBase == NULL) { m_xEdit->blockSignals(true); m_yEdit->blockSignals(true); m_xEdit->setEnabled(false); m_yEdit->setEnabled(false); m_xEdit->setValue(0); m_yEdit->setValue(0); m_xEdit->blockSignals(false); m_yEdit->blockSignals(false); return; } m_xEdit->setEnabled(!itemBase->moveLock()); m_yEdit->setEnabled(!itemBase->moveLock()); QString units = m_unitsLabel->text(); QPointF loc = itemBase->pos(); if (units == "px") { } else if (units == "in") { loc /= 90; } else if (units == "mm") { loc /= (90 / 25.4); } m_xEdit->blockSignals(true); m_yEdit->blockSignals(true); m_xEdit->setValue(loc.x()); m_yEdit->setValue(loc.y()); m_xEdit->blockSignals(false); m_yEdit->blockSignals(false); } void HtmlInfoView::setRotation(ItemBase * itemBase) { if (itemBase == NULL) { m_rotEdit->blockSignals(true); m_rotEdit->setEnabled(false); m_rotEdit->setValue(0); m_rotEdit->blockSignals(false); return; } double step = 90; bool enabled = true; if (itemBase->moveLock()) enabled = false; else if (!itemBase->rotationAllowed()) enabled = false; else { if (itemBase->rotation45Allowed()) step = 45; if (itemBase->freeRotationAllowed()) step = 1; } m_rotEdit->setEnabled(enabled); m_rotEdit->setSingleStep(step); QTransform transform = itemBase->transform(); double angle = atan2(transform.m12(), transform.m11()) * 180 / M_PI; m_rotEdit->blockSignals(true); m_rotEdit->setValue(angle); m_rotEdit->blockSignals(false); } void HtmlInfoView::updateLocation(ItemBase * itemBase) { if (itemBase == NULL) return; if (itemBase != m_lastItemBase) return; setLocation(itemBase); } void HtmlInfoView::updateRotation(ItemBase * itemBase) { if (itemBase == NULL) return; if (itemBase != m_lastItemBase) return; setRotation(itemBase); } void HtmlInfoView::xyEntry() { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(m_lastItemBase); if (infoGraphicsView == NULL) return; DebugDialog::debug(QString("xedit %1 %2 %3").arg(m_xEdit->text()).arg(m_yEdit->text()).arg(sender() == m_xEdit)); double x = TextUtils::convertToInches(m_xEdit->text() + m_unitsLabel->text()); double y = TextUtils::convertToInches(m_yEdit->text() + m_unitsLabel->text()); if (infoGraphicsView != NULL && m_lastItemBase != NULL) { infoGraphicsView->moveItem(m_lastItemBase, x * 90, y * 90); } } void HtmlInfoView::rotEntry() { if (m_lastItemBase != NULL) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(m_lastItemBase); if (infoGraphicsView == NULL) return; double newAngle = m_rotEdit->value(); if (m_rotEdit->singleStep() == 1) { } else { newAngle = qFloor(newAngle / m_rotEdit->singleStep()) * m_rotEdit->singleStep(); } QTransform transform = m_lastItemBase->transform(); double angle = atan2(transform.m12(), transform.m11()) * 180 / M_PI; infoGraphicsView->rotateX(newAngle - angle, false, m_lastItemBase); } } fritzing-app-0.9.2b/src/infoview/htmlinfoview.h000066400000000000000000000143701250202676700216130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6609 $: $Author: irascibl@gmail.com $: $Date: 2012-10-30 14:21:08 +0100 (Di, 30. Okt 2012) $ ********************************************************************/ #ifndef HTMLINFOVIEW_H #define HTMLINFOVIEW_H #include #include #include #include #include #include #include #include #include #include #include "../items/itembase.h" #include "../items/wire.h" #include "../connectors/connectoritem.h" #include "../referencemodel/referencemodel.h" struct PropThing { QPointer m_name; QPointer m_frame; QPointer m_value; QPointer m_plugin; QPointer m_layout; }; class TagLabel : public QLabel { Q_OBJECT public: TagLabel(QWidget * parent); protected: QSize sizeHint() const; }; class HtmlInfoView : public QScrollArea { Q_OBJECT public: HtmlInfoView(QWidget * parent = 0); ~HtmlInfoView(); QSize sizeHint() const; void setContent(const QString& html); ItemBase *currentItem(); void reloadContent(class InfoGraphicsView *); void viewItemInfo(class InfoGraphicsView *, ItemBase* item, bool swappingEnabled); void updateLocation(ItemBase *); void updateRotation(ItemBase *); void hoverEnterItem(class InfoGraphicsView *, QGraphicsSceneHoverEvent * event, ItemBase * item, bool swappingEnabled); void hoverLeaveItem(class InfoGraphicsView *, QGraphicsSceneHoverEvent * event, ItemBase * item); void hoverEnterConnectorItem(class InfoGraphicsView *, QGraphicsSceneHoverEvent * event, ConnectorItem * item, bool swappingEnabled); void hoverLeaveConnectorItem(class InfoGraphicsView *, QGraphicsSceneHoverEvent * event, ConnectorItem * item); void unregisterCurrentItem(); void unregisterCurrentItemIf(long id); void init(bool tinyMode); public: static const int STANDARD_ICON_IMG_WIDTH; static const int STANDARD_ICON_IMG_HEIGHT; static void cleanup(); static QHash getPartProperties(ModelPart * modelPart, ItemBase * itemBase, bool wantDebug, QStringList & keys); signals: void clickObsoleteSignal(); protected slots: void setContent(); void setInstanceTitle(); void instanceTitleEnter(); void instanceTitleLeave(); void instanceTitleEditable(bool editable); void changeLock(bool); void changeSticky(bool); void clickObsolete(const QString &); void xyEntry(); void unitsClicked(); void rotEntry(); protected: void appendStuff(ItemBase* item, bool swappingEnabled); //finds out if it's a wire or something else void appendWireStuff(Wire* wire, bool swappingEnabled); void appendItemStuff(ItemBase* base, bool swappingEnabled); void appendItemStuff(ItemBase * base, ModelPart * modelPart, bool swappingEnabled); void setInstanceTitleColors(class FLineEdit * edit, const QColor & base, const QColor & text); void setCurrentItem(ItemBase *); void setNullContent(); void setUpTitle(ItemBase *); void setUpIcons(ItemBase *, bool swappingEnabled); void addTags(ModelPart * modelPart); void partTitle(const QString & title, const QString & version, const QString & url, bool obsolete); void displayProps(ModelPart * modelPart, ItemBase * itemBase, bool swappingEnabled); void clearPropThingPlugin(PropThing * propThing); void clearPropThingPlugin(PropThing * propThing, QWidget * plugin); void viewConnectorItemInfo(QGraphicsSceneHoverEvent * event, ConnectorItem* item); void showLayers(bool show, ItemBase *, const QString & family, const QString & value, bool swappingEnabled); void makeLockFrame(); void makeLocationFrame(); void makeRotationFrame(); void setLocation(ItemBase *); void setRotation(ItemBase *); protected: QPointer m_currentItem; bool m_currentSwappingEnabled; // previous item (possibly hovered over) QTimer m_setContentTimer; QPointer m_lastItemBase; bool m_lastSwappingEnabled; // previous item (selected) class FLineEdit * m_titleEdit; QLabel * m_icon1; QLabel * m_icon2; QLabel * m_icon3; QLabel * m_partTitle; QLabel * m_partUrl; QLabel * m_partVersion; QLabel * m_tagsTextLabel; QLabel * m_connDescr; QLabel * m_connName; QLabel * m_connType; QLabel * m_propLabel; QLabel * m_placementLabel; QLabel * m_tagLabel; QLabel * m_connLabel; QLabel * m_layerLabel; QLabel * m_lockLabel; QLabel * m_locationLabel; QLabel * m_rotationLabel; QFrame * m_connFrame; QFrame * m_propFrame; QFrame * m_placementFrame; QFrame * m_layerFrame; QFrame * m_lockFrame; QFrame * m_locationFrame; QFrame * m_rotationFrame; QCheckBox * m_lockCheckbox; QCheckBox * m_stickyCheckbox; QGridLayout * m_propLayout; QGridLayout * m_placementLayout; QVBoxLayout * m_layerLayout; QList m_propThings; QPointer m_pendingItemBase; bool m_pendingSwappingEnabled; QWidget * m_layerWidget; QDoubleSpinBox * m_xEdit; QDoubleSpinBox * m_yEdit; QLabel * m_unitsLabel; QDoubleSpinBox * m_rotEdit; // note: these m_last items should only be checked for equality and not otherwise accessed ItemBase * m_lastTitleItemBase; QString m_lastPartTitle; QString m_lastPartVersion; ModelPart * m_lastTagsModelPart; int m_lastConnectorItemCount; ConnectorItem * m_lastConnectorItem; ItemBase * m_lastIconItemBase; ModelPart * m_lastPropsModelPart; ItemBase * m_lastPropsItemBase; bool m_lastPropsSwappingEnabled; bool m_tinyMode; }; #endif fritzing-app-0.9.2b/src/installedfonts.h000066400000000000000000000026321250202676700203010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef INSTALLEDFONTS_H #define INSTALLEDFONTS_H #include #include #include class InstalledFonts { public: static QSet InstalledFontsList; static QMultiHash InstalledFontsNameMapper; // family name to filename; SVG files seem to have to use filename // note: these static variables are initialized in fapplication.cpp }; #endif fritzing-app-0.9.2b/src/itemdrag.cpp000066400000000000000000000036671250202676700174100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6264 $: $Author: cohen@irascible.com $: $Date: 2012-08-07 17:59:08 +0200 (Di, 07. Aug 2012) $ ********************************************************************/ #include "itemdrag.h" #include "debugdialog.h" ItemDrag * ItemDrag::Singleton = new ItemDrag(); ItemDrag::ItemDrag(QObject * parent) : QObject(parent) { m_originator = NULL; m_originatorIsTempBin = false; } void ItemDrag::__dragIsDone() { m_cache.clear(); emit dragIsDoneSignal(this); } void ItemDrag::cleanup() { if (Singleton) { delete Singleton; Singleton = NULL; } } QHash & ItemDrag::cache() { return Singleton->m_cache; } ItemDrag * ItemDrag::singleton() { return Singleton; } void ItemDrag::dragIsDone() { Singleton->__dragIsDone(); } void ItemDrag::setOriginator(QWidget * originator) { Singleton->m_originator = originator; } QWidget* ItemDrag::originator() { return Singleton->m_originator; } void ItemDrag::setOriginatorIsTempBin(bool itb) { Singleton->m_originatorIsTempBin = itb; } bool ItemDrag::originatorIsTempBin() { return Singleton->m_originatorIsTempBin; } fritzing-app-0.9.2b/src/itemdrag.h000066400000000000000000000033671250202676700170520ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6264 $: $Author: cohen@irascible.com $: $Date: 2012-08-07 17:59:08 +0200 (Di, 07. Aug 2012) $ ********************************************************************/ #ifndef ITEMDRAG_H #define ITEMDRAG_H #include #include #include #include class ItemDrag : public QObject { Q_OBJECT protected: ItemDrag(QObject * parent = 0); void __dragIsDone(); public: static ItemDrag * singleton(); static QHash & cache(); static void dragIsDone(); static void cleanup(); static void setOriginator(QWidget *); static QWidget * originator(); static bool originatorIsTempBin(); static void setOriginatorIsTempBin(bool); signals: void dragIsDoneSignal(ItemDrag *); protected: QHash m_cache; QPointer m_originator; bool m_originatorIsTempBin; protected: static ItemDrag * Singleton; }; #endif fritzing-app-0.9.2b/src/items/000077500000000000000000000000001250202676700162155ustar00rootroot00000000000000fritzing-app-0.9.2b/src/items/breadboard.cpp000066400000000000000000000033401250202676700210060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "breadboard.h" Breadboard::Breadboard( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { } Breadboard::~Breadboard() { } ItemBase::PluralType Breadboard::isPlural() { return Plural; } bool Breadboard::rotation45Allowed() { return false; } void Breadboard::hoverUpdate() { } void Breadboard::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget); } bool Breadboard::stickyEnabled() { return false; } bool Breadboard::canFindConnectorsUnder() { return false; } fritzing-app-0.9.2b/src/items/breadboard.h000066400000000000000000000032171250202676700204560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef BREADBOARD_H #define BREADBOARD_H #include "paletteitem.h" class Breadboard : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Breadboard(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Breadboard(); PluralType isPlural(); void hoverUpdate(); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool stickyEnabled(); bool canFindConnectorsUnder(); public: bool rotation45Allowed(); }; #endif fritzing-app-0.9.2b/src/items/capacitor.cpp000066400000000000000000000155161250202676700206760ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "capacitor.h" #include "../utils/textutils.h" #include "../utils/focusoutcombobox.h" #include "../utils/boundedregexpvalidator.h" #include "../sketch/infographicsview.h" #include "partlabel.h" // TODO // save into parts bin Capacitor::Capacitor( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { PropertyDefMaster::initPropertyDefs(modelPart, m_propertyDefs); } Capacitor::~Capacitor() { } ItemBase::PluralType Capacitor::isPlural() { return Plural; } bool Capacitor::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { if (prop.compare(propertyDef->name, Qt::CaseInsensitive) == 0) { returnProp = TranslatedPropertyNames.value(prop); if (returnProp.isEmpty()) { returnProp = propertyDef->name; } FocusOutComboBox * focusOutComboBox = new FocusOutComboBox(); focusOutComboBox->setEnabled(swappingEnabled); focusOutComboBox->setEditable(propertyDef->editable); focusOutComboBox->setObjectName("infoViewComboBox"); QString current = m_propertyDefs.value(propertyDef); if (propertyDef->editable) { focusOutComboBox->setToolTip(tr("Select from the dropdown, or type in a %1 value").arg(returnProp)); } if (propertyDef->numeric) { if (!current.isEmpty()) { double val = TextUtils::convertFromPowerPrefixU(current, propertyDef->symbol); if (!propertyDef->menuItems.contains(val)) { propertyDef->menuItems.append(val); } } foreach(double q, propertyDef->menuItems) { QString s = TextUtils::convertToPowerPrefix(q) + propertyDef->symbol; focusOutComboBox->addItem(s); } } else { if (!current.isEmpty()) { if (!propertyDef->sMenuItems.contains(current)) { propertyDef->sMenuItems.append(current); } } focusOutComboBox->addItems(propertyDef->sMenuItems); } if (!current.isEmpty()) { int ix = focusOutComboBox->findText(current); if (ix < 0) { focusOutComboBox->addItem(current); ix = focusOutComboBox->findText(current); } focusOutComboBox->setCurrentIndex(ix); } if (propertyDef->editable) { BoundedRegExpValidator * validator = new BoundedRegExpValidator(focusOutComboBox); validator->setSymbol(propertyDef->symbol); validator->setConverter(TextUtils::convertFromPowerPrefix); if (propertyDef->maxValue > propertyDef->minValue) { validator->setBounds(propertyDef->minValue, propertyDef->maxValue); } QString pattern = QString("((\\d{1,3})|(\\d{1,3}\\.)|(\\d{1,3}\\.\\d{1,2}))[%1]{0,1}[%2]{0,1}") .arg(TextUtils::PowerPrefixesString) .arg(propertyDef->symbol); validator->setRegExp(QRegExp(pattern)); focusOutComboBox->setValidator(validator); connect(focusOutComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(propertyEntry(const QString &))); } else { connect(focusOutComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(simplePropertyEntry(const QString &))); } this->m_comboBoxes.insert(propertyDef, focusOutComboBox); returnValue = focusOutComboBox->currentText(); returnWidget = focusOutComboBox; return true; } } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void Capacitor::propertyEntry(const QString & text) { FocusOutComboBox * focusOutComboBox = qobject_cast(sender()); if (focusOutComboBox == NULL) return; foreach (PropertyDef * propertyDef, m_comboBoxes.keys()) { if (m_comboBoxes.value(propertyDef) == focusOutComboBox) { QString utext = text; if (propertyDef->numeric) { double val = TextUtils::convertFromPowerPrefixU(utext, propertyDef->symbol); if (!propertyDef->menuItems.contains(val)) { // info view is redrawn, so combobox is recreated, so the new item is added to the combo box menu propertyDef->menuItems.append(val); } } else { if (!propertyDef->sMenuItems.contains(text)) { // info view is redrawn, so combobox is recreated, so the new item is added to the combo box menu propertyDef->sMenuItems.append(text); } } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, propertyDef->name, "", m_propertyDefs.value(propertyDef, ""), utext, true); } break; } } } void Capacitor::setProp(const QString & prop, const QString & value) { foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { if (prop.compare(propertyDef->name, Qt::CaseInsensitive) == 0) { m_propertyDefs.insert(propertyDef, value); modelPart()->setLocalProp(propertyDef->name, value); if (m_partLabel) m_partLabel->displayTextsIf(); return; } } PaletteItem::setProp(prop, value); } void Capacitor::simplePropertyEntry(const QString & text) { FocusOutComboBox * focusOutComboBox = qobject_cast(sender()); if (focusOutComboBox == NULL) return; foreach (PropertyDef * propertyDef, m_comboBoxes.keys()) { if (m_comboBoxes.value(propertyDef) == focusOutComboBox) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, propertyDef->name, "", m_propertyDefs.value(propertyDef, ""), text, true); } break; } } } void Capacitor::getProperties(QHash & hash) { foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { hash.insert(propertyDef->name, m_propertyDefs.value(propertyDef)); } } fritzing-app-0.9.2b/src/items/capacitor.h000066400000000000000000000040131250202676700203310ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef CAPACITOR_H #define CAPACITOR_H #include "paletteitem.h" #include "propertydef.h" class Capacitor : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Capacitor(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Capacitor(); PluralType isPlural(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void setProp(const QString & prop, const QString & value); void getProperties(QHash &); public slots: void propertyEntry(const QString & text); void simplePropertyEntry(const QString & text); protected: QHash m_propertyDefs; QHash m_comboBoxes; }; #endif // CAPACITOR_H fritzing-app-0.9.2b/src/items/clipablewire.cpp000066400000000000000000000310131250202676700213610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "clipablewire.h" #include "../connectors/connectoritem.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include static double connectorRectClipInset = 0.5; ///////////////////////////////////////////////////////// #define CONVEX /* ======= Crossings algorithm ============================================ */ // from: http://tog.acm.org/GraphicsGems//gemsiv/ptpoly_haines/ptinpoly.c #define XCOORD 0 #define YCOORD 1 /* Shoot a test ray along +X axis. The strategy, from MacMartin, is to * compare vertex Y values to the testing point's Y and quickly discard * edges which are entirely to one side of the test ray. * * Input 2D polygon _pgon_ with _numverts_ number of vertices and test point * _point_, returns 1 if inside, 0 if outside. WINDING and CONVEX can be * defined for this test. */ int CrossingsTest( double pgon[][2], int numverts, double point[2] ) { #ifdef WINDING register int crossings ; #endif register int j, yflag0, yflag1, inside_flag, xflag0 ; register double ty, tx, *vtx0, *vtx1 ; #ifdef CONVEX register int line_flag ; #endif tx = point[XCOORD] ; ty = point[YCOORD] ; vtx0 = pgon[numverts-1] ; /* get test bit for above/below X axis */ yflag0 = ( vtx0[YCOORD] >= ty ) ; vtx1 = pgon[0] ; #ifdef WINDING crossings = 0 ; #else inside_flag = 0 ; #endif #ifdef CONVEX line_flag = 0 ; #endif for ( j = numverts+1 ; --j ; ) { yflag1 = ( vtx1[YCOORD] >= ty ) ; /* check if endpoints straddle (are on opposite sides) of X axis * (i.e. the Y's differ); if so, +X ray could intersect this edge. */ if ( yflag0 != yflag1 ) { xflag0 = ( vtx0[XCOORD] >= tx ) ; /* check if endpoints are on same side of the Y axis (i.e. X's * are the same); if so, it's easy to test if edge hits or misses. */ if ( xflag0 == ( vtx1[XCOORD] >= tx ) ) { /* if edge's X values both right of the point, must hit */ #ifdef WINDING if ( xflag0 ) crossings += ( yflag0 ? -1 : 1 ) ; #else if ( xflag0 ) inside_flag = !inside_flag ; #endif } else { /* compute intersection of pgon segment with +X ray, note * if >= point's X; if so, the ray hits it. */ if ( (vtx1[XCOORD] - (vtx1[YCOORD]-ty)* ( vtx0[XCOORD]-vtx1[XCOORD])/(vtx0[YCOORD]-vtx1[YCOORD])) >= tx ) { #ifdef WINDING crossings += ( yflag0 ? -1 : 1 ) ; #else inside_flag = !inside_flag ; #endif } } #ifdef CONVEX /* if this is second edge hit, then done testing */ if ( line_flag ) goto Exit ; /* note that one edge has been hit by the ray's line */ line_flag = true; #endif } /* move to next pair of vertices, retaining info as possible */ yflag0 = yflag1 ; vtx0 = vtx1 ; vtx1 += 2 ; } #ifdef CONVEX Exit: ; #endif #ifdef WINDING /* test if crossings is not zero */ inside_flag = (crossings != 0) ; #endif return( inside_flag ) ; } ///////////////////////////////////////////////////////// ClipableWire::ClipableWire( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool initLabel ) : Wire(modelPart, viewID, viewGeometry, id, itemMenu, initLabel) { m_clipEnds = false; m_trackHoverItem = NULL; m_justFilteredEvent = NULL; m_cachedOriginalLine.setPoints(QPointF(-99999,-99999), QPointF(-99999,-99999)); } const QLineF & ClipableWire::getPaintLine() { if (!m_clipEnds) { return Wire::getPaintLine(); } QLineF originalLine = this->line(); if (m_cachedOriginalLine == originalLine) { return m_cachedLine; } int t0c = 0; ConnectorItem* to0 = NULL; foreach (ConnectorItem * toConnectorItem, m_connector0->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { to0 = toConnectorItem; break; } t0c++; } int t1c = 0; ConnectorItem* to1 = NULL; foreach (ConnectorItem * toConnectorItem, m_connector1->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { to1 = toConnectorItem; break; } t1c++; } if ((to0 == NULL && to1 == NULL) || // no need to clip an unconnected wire (to0 == NULL && t0c == 0) || // dragging out a wire, no need to clip (to1 == NULL && t1c == 0) || // dragging out a wire, no need to clip m_dragEnd) // dragging out a wire, no need to clip { return Wire::getPaintLine(); } QPointF p1 = originalLine.p1(); QPointF p2 = originalLine.p2(); // does to0 always go with p1? calcClip(p1, p2, to0, to1); m_cachedOriginalLine = originalLine; m_cachedLine.setPoints(p1, p2); return m_cachedLine; } void ClipableWire::setClipEnds(bool clipEnds ) { if (m_clipEnds != clipEnds) { prepareGeometryChange(); m_clipEnds = clipEnds; } } void ClipableWire::calcClip(QPointF & p1, QPointF & p2, ConnectorItem * c1, ConnectorItem * c2) { if (c1 != NULL && c2 != NULL && c1->isEffectivelyCircular() && c2->isEffectivelyCircular()) { //c1->debugInfo("c1"); //c2->debugInfo("c2"); GraphicsUtils::shortenLine(p1, p2, c1->calcClipRadius() + (m_pen.width() / 2.0), c2->calcClipRadius() + (m_pen.width() / 2.0)); return; } if (c1 != NULL && c1->isEffectivelyCircular()) { GraphicsUtils::shortenLine(p1, p2, c1->calcClipRadius() + (m_pen.width() / 2.0), 0); p2 = findIntersection(c2, p2); return; } if (c2 != NULL && c2->isEffectivelyCircular()) { GraphicsUtils::shortenLine(p1, p2, 0, c2->calcClipRadius() + (m_pen.width() / 2.0)); p1 = findIntersection(c1, p1); return; } p1 = findIntersection(c1, p1); p2 = findIntersection(c2, p2); } QPointF ClipableWire::findIntersection(ConnectorItem * connectorItem, const QPointF & p) { if (connectorItem == NULL) return p; QRectF r = connectorItem->rect(); r.adjust(connectorRectClipInset, connectorRectClipInset, -connectorRectClipInset, -connectorRectClipInset); // inset it a little bit so the wire touches QPolygonF poly = this->mapFromScene(connectorItem->mapToScene(r)); QLineF l1 = this->line(); int count = poly.count(); for (int i = 0; i < count; i++) { QLineF l2(poly[i], poly[(i + 1) % count]); QPointF intersectingPoint; if (l1.intersect(l2, &intersectingPoint) == QLineF::BoundedIntersection) { return intersectingPoint; } } return this->mapFromScene(connectorItem->mapToScene(r.center())); } bool ClipableWire::filterMousePressConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { m_justFilteredEvent = NULL; if (!m_clipEnds) return false; if (m_viewID != ViewLayer::PCBView) return false; ConnectorItem * to = NULL; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { to = toConnectorItem; break; } } if (to == NULL) return false; if (insideInnerCircle(to, event->scenePos()) || !insideSpoke(this, event->scenePos())) { m_justFilteredEvent = event; event->ignore(); return true; } return false; } void ClipableWire::mousePressEvent(QGraphicsSceneMouseEvent *event) { if ((long) event == (long) m_justFilteredEvent) { event->ignore(); return; } Wire::mousePressEvent(event); } void ClipableWire::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event , ConnectorItem * item) { //Wire::hoverEnterConnectorItem(event, item); // track mouse move events for hover redirecting ConnectorItem * to = NULL; foreach (ConnectorItem * toConnectorItem, item->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { to = toConnectorItem; break; } } if (to) { m_trackHoverItem = to; m_trackHoverLastWireItem = NULL; m_trackHoverLastItem = NULL; dispatchHover(event->scenePos()); } } void ClipableWire::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { Q_UNUSED(item); Q_UNUSED(event); dispatchHoverAux(false, NULL); m_trackHoverItem = NULL; //Wire::hoverLeaveConnectorItem(event, item); } void ClipableWire::hoverMoveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { if (m_trackHoverItem) { dispatchHover(event->scenePos()); } Wire::hoverMoveConnectorItem(event, item); } void ClipableWire::dispatchHover(QPointF scenePos) { bool inInner = false; ClipableWire * inWire = NULL; if (insideInnerCircle(m_trackHoverItem, scenePos)) { //DebugDialog::debug("got inner circle"); inInner = true; } else { foreach (ConnectorItem * toConnectorItem, m_trackHoverItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) continue; ClipableWire * w = dynamic_cast(toConnectorItem->attachedTo()); if (w == NULL) continue; if (w->getRatsnest()) continue; // is there a better way to check this? if (insideSpoke(w, scenePos)) { //DebugDialog::debug("got inside spoke"); inWire = w; break; } } } dispatchHoverAux(inInner, inWire); } void ClipableWire::dispatchHoverAux(bool inInner, Wire * inWire) { if (m_trackHoverItem == NULL) return; if (inInner) { if (m_trackHoverLastItem == m_trackHoverItem) { // no change return; } if (m_trackHoverLastWireItem) { ((ItemBase *) m_trackHoverLastWireItem)->hoverLeaveConnectorItem(); m_trackHoverLastWireItem = NULL; } m_trackHoverLastItem = m_trackHoverItem; m_trackHoverLastItem->setHoverColor(); m_trackHoverLastItem->attachedTo()->hoverEnterConnectorItem(); } else if (inWire) { if (m_trackHoverLastWireItem == inWire) { // no change return; } if (m_trackHoverLastItem) { QList visited; m_trackHoverLastItem->restoreColor(visited); m_trackHoverLastItem->attachedTo()->hoverLeaveConnectorItem(); m_trackHoverLastItem = NULL; } if (m_trackHoverLastWireItem) { ((ItemBase *) m_trackHoverLastWireItem)->hoverLeaveConnectorItem(); } m_trackHoverLastWireItem = inWire; ((ItemBase *) m_trackHoverLastWireItem)->hoverEnterConnectorItem(); } else { //DebugDialog::debug("got none"); if (m_trackHoverLastItem != NULL) { QList visited; m_trackHoverLastItem->restoreColor(visited); m_trackHoverLastItem->attachedTo()->hoverLeaveConnectorItem(); m_trackHoverLastItem = NULL; } if (m_trackHoverLastWireItem != NULL) { ((ItemBase *) m_trackHoverLastWireItem)->hoverLeaveConnectorItem(); m_trackHoverLastWireItem = NULL; } } } bool ClipableWire::insideInnerCircle(ConnectorItem * connectorItem, QPointF scenePos) { QPointF localPos = connectorItem->mapFromScene(scenePos); double rad = connectorItem->radius(); if (rad <= 0) return false; rad -= ((connectorItem->strokeWidth() / 2.0)); // shrink it a little bit QRectF r = connectorItem->rect(); QPointF c = r.center(); if ( (localPos.x() - c.x()) * (localPos.x() - c.x()) + (localPos.y() - c.y()) * (localPos.y() - c.y()) < rad * rad ) { // inside the inner circle return true; } return false; } bool ClipableWire::insideSpoke(ClipableWire * wire, QPointF scenePos) { QLineF l = wire->line(); QLineF normal = l.normalVector(); normal.setLength(wire->width() / 2.0); double parallelogram[4][2]; parallelogram[0][XCOORD] = normal.p2().x(); parallelogram[0][YCOORD] = normal.p2().y(); parallelogram[1][XCOORD] = normal.p1().x() - normal.dx(); parallelogram[1][YCOORD] = normal.p1().y() - normal.dy(); parallelogram[2][XCOORD] = parallelogram[1][XCOORD] + l.dx(); parallelogram[2][YCOORD] = parallelogram[1][YCOORD] + l.dy(); parallelogram[3][XCOORD] = parallelogram[0][XCOORD] + l.dx(); parallelogram[3][YCOORD] = parallelogram[0][YCOORD] + l.dy(); QPointF mp = wire->mapFromScene(scenePos); double point[2]; point[XCOORD] = mp.x(); point[YCOORD] = mp.y(); if (CrossingsTest(parallelogram, 4, point)) { return true; } return false; } fritzing-app-0.9.2b/src/items/clipablewire.h000066400000000000000000000046141250202676700210350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef CLIPABLEWIRE_H #define CLIPABLEWIRE_H #include "wire.h" #include class ClipableWire : public Wire { public: ClipableWire( ModelPart * modelPart, ViewLayer::ViewID, const ViewGeometry & , long id, QMenu* itemMenu, bool initLabel); void setClipEnds(bool); const QLineF & getPaintLine(); bool filterMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); void mousePressEvent(QGraphicsSceneMouseEvent *event); void hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); void hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); void hoverMoveConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); protected: bool insideInnerCircle(ConnectorItem * connectorItem, QPointF localPos); bool insideSpoke(ClipableWire * wire, QPointF scenePos); void dispatchHover(QPointF scenePos); void dispatchHoverAux(bool inInner, Wire * inWire); QPointF findIntersection(ConnectorItem * connectorItem, const QPointF & p); void calcClip(QPointF & p1, QPointF & p2, ConnectorItem * c1, ConnectorItem * c2); protected: bool m_clipEnds; QLineF m_cachedLine; QLineF m_cachedOriginalLine; QGraphicsSceneMouseEvent * m_justFilteredEvent; QPointer m_trackHoverItem; QPointer m_trackHoverLastItem; QPointer m_trackHoverLastWireItem; }; #endif fritzing-app-0.9.2b/src/items/dip.cpp000066400000000000000000000427761250202676700175150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "dip.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/familypropertycombobox.h" #include "../utils/schematicrectconstants.h" #include "../connectors/connectoritem.h" #include "../sketch/infographicsview.h" #include "../fsvgrenderer.h" #include "pinheader.h" #include "partfactory.h" #include static QStringList Spacings; static int MinSipPins = 2; static int MaxSipPins = 128; static int MinDipPins = 4; static int MaxDipPins = 128; ////////////////////////////////////////////////// Dip::Dip( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : MysteryPart(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { } Dip::~Dip() { } bool Dip::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { bool result = MysteryPart::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("chip label", Qt::CaseInsensitive) == 0) { returnProp = tr("chip label"); } return result; } bool Dip::isDIP() { QString package = modelPart()->properties().value("package", ""); if (package.indexOf("dip", 0, Qt::CaseInsensitive) >= 0) return true; if (package.indexOf("sip", 0, Qt::CaseInsensitive) >= 0) return false; return family().contains("generic ic", Qt::CaseInsensitive); } bool Dip::otherPropsChange(const QMap & propsMap) { QString layout = modelPart()->properties().value("package", ""); return (layout.compare(propsMap.value("package", "")) != 0); } const QStringList & Dip::spacings() { if (Spacings.count() == 0) { Spacings << "300mil" << "400mil" << "600mil" << "900mil"; } return Spacings; } QString Dip::genSipFZP(const QString & moduleid) { return genxFZP(moduleid, "generic_sip_fzpTemplate", MinSipPins, MaxSipPins, 1); } QString Dip::genDipFZP(const QString & moduleid) { return genxFZP(moduleid, "generic_dip_fzpTemplate", MinDipPins, MaxDipPins, 2); } QStringList Dip::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("pins", Qt::CaseInsensitive) == 0) { QStringList values; value = modelPart()->properties().value("pins"); if (isDIP()) { for (int i = MinDipPins; i <= MaxDipPins; i += 2) { values << QString::number(i); } } else { for (int i = MinSipPins; i <= MaxSipPins; i++) { values << QString::number(i); } } return values; } return MysteryPart::collectValues(family, prop, value); } QString Dip::genModuleID(QMap & currPropsMap) { QString spacing = currPropsMap.value("pin spacing", "300mil"); QString value = currPropsMap.value("package"); QString pins = currPropsMap.value("pins"); if (pins.isEmpty()) pins = "16"; // pick something safe QString moduleID; if (value.contains("sip", Qt::CaseInsensitive)) { return QString("generic_sip_%1_%2").arg(pins).arg(spacing); } else { int p = pins.toInt(); if (p < 4) p = 4; if (p % 2 == 1) p--; return QString("generic_ic_dip_%1_%2").arg(p).arg(spacing); } } QString Dip::retrieveSchematicSvg(QString & svg) { bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (hasLocal) { if (this->isDIP()) { svg = makeSchematicSvg(labels); //DebugDialog::debug("make dip " + svg); } else { svg = MysteryPart::makeSchematicSvg(labels, true); } } return TextUtils::replaceTextElement(svg, "label", m_chipLabel); } QString Dip::makeSchematicSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() != 5) return ""; QString spacing; int pins = TextUtils::getPinsAndSpacing(expectedFileName, spacing); QStringList labels; for (int i = 0; i < pins; i++) { labels << QString::number(i + 1); } if (expectedFileName.contains("sip", Qt::CaseInsensitive)) { if (expectedFileName.contains(PartFactory::OldSchematicPrefix)) { return MysteryPart::obsoleteMakeSchematicSvg(labels, true); } return MysteryPart::makeSchematicSvg(labels, true); } if (expectedFileName.contains(PartFactory::OldSchematicPrefix)) { return obsoleteMakeSchematicSvg(labels); } return makeSchematicSvg(labels); } QString Dip::makeSchematicSvg(const QStringList & labels) { QDomDocument fakeDoc; QList lefts; QList rights; for (int i = 0; i < labels.count() / 2; i++) { QDomElement element = fakeDoc.createElement("contact"); element.setAttribute("connectorIndex", i); element.setAttribute("name", labels.at(i)); lefts.append(element); int j = labels.count() - i - 1; element = fakeDoc.createElement("contact"); element.setAttribute("connectorIndex", j); element.setAttribute("name", labels.at(j)); rights.append(element); } QList empty; QStringList busNames; QString ic("IC"); return SchematicRectConstants::genSchematicDIP(empty, empty, lefts, rights, empty, busNames, ic, false, false, SchematicRectConstants::simpleGetConnectorName); } QString Dip::obsoleteMakeSchematicSvg(const QStringList & labels) { int pins = labels.count(); int increment = GraphicsUtils::StandardSchematicSeparationMils; int border = 30; double totalHeight = (pins * increment / 2) + increment + border; int pinWidth = increment + increment + border; int centralWidth = increment * 4; int pinTextWidth = 0; int defaultLabelWidth = 30; int labelFontSize = 130; double textMax = defaultLabelWidth; QFont font("Droid Sans", labelFontSize * 72 / GraphicsUtils::StandardFritzingDPI, QFont::Normal); QFontMetricsF fm(font); for (int i = 0; i < labels.count(); i++) { double w = fm.width(labels.at(i)); if (w > textMax) textMax = w; } if (textMax > defaultLabelWidth) { pinTextWidth += (textMax - defaultLabelWidth) * 2 * 1000 / 72; } centralWidth += pinTextWidth; int totalWidth = centralWidth + pinWidth; QString header("\n" "\n" "\n" "\n" "IC\n"); QString svg = header .arg(totalHeight / 1000) .arg(totalHeight) .arg(totalHeight - border) .arg(totalWidth / 1000.0) .arg(totalWidth) .arg(centralWidth) .arg(totalWidth / 2.0) ; QString repeatL("\n" "\n" "\n" "%5\n"); QString repeatR("\n" "\n" "\n" "%5\n"); int y = 300; for (int i = 0; i < pins / 2; i++) { svg += repeatL.arg(15 + y).arg(y).arg(i).arg(y + 50).arg(labels.at(i)).arg(labelFontSize); svg += repeatR .arg(15 + y) .arg(y) .arg(pins - i - 1) .arg(y + 50) .arg(labels.at(pins - i - 1)) .arg(labelFontSize) .arg(totalWidth - 300) .arg(totalWidth - 15) .arg(totalWidth - 300) .arg(totalWidth - 30) .arg(totalWidth - 390) ; y += increment; } svg += "\n"; svg += "\n"; return svg; } QString Dip::makeBreadboardSvg(const QString & expectedFileName) { if (expectedFileName.contains("_sip_")) return makeBreadboardSipSvg(expectedFileName); if (expectedFileName.contains("_dip_")) return makeBreadboardDipSvg(expectedFileName); return ""; } QString Dip::makeBreadboardSipSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() != 5) return ""; int pins = pieces.at(2).toInt(); int increment = 10; double totalWidth = (pins * increment); QString svg = TextUtils::incrementTemplate(":/resources/templates/generic_sip_bread_template.txt", 1, increment * (pins - 2), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); QString repeat("\n" "\n" "\n"); QString repeats; if (pins > 2) { repeats = TextUtils::incrementTemplateString(repeat, pins - 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::incCopyPinFunction, NULL); } return svg.arg(totalWidth / 100).arg(pins - 1).arg(repeats); } QString Dip::makeBreadboardDipSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() != 6) return ""; int pins = pieces.at(3).toInt(); int increment = 10; double spacing = TextUtils::convertToInches(pieces.at(4)) * 100; QString repeatB("\n" "\n" " \n"); QString repeatT("\n" "\n" "\n"); QString header("\n" "\n" "\n" "\n" "\n" "\n" " \n" "\n" "\n" "\n" "\n" "\n" "\n" "IC\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" ".percent.2\n" ".percent.3\n" "\n" "\n"); // header came from a 300mil dip, so base case is spacing - (increment * 3) header = TextUtils::incrementTemplateString(header, 1, spacing - (increment * 3), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); header = header .arg(TextUtils::getViewBoxCoord(header, 3) / 100.0) .arg(pins - 1) .arg((pins / 2) - 1) .arg(pins / 2) .arg(OCRAFontName); header.replace("{{", "["); header.replace("}}", "]"); header = TextUtils::incrementTemplateString(header, 1, (spacing - (increment * 3)) / 2, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); header.replace("{", "["); header.replace("}", "]"); header.replace(".percent.", "%"); QString svg = TextUtils::incrementTemplateString(header, 1, increment * ((pins - 4) / 2), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); repeatB = TextUtils::incrementTemplateString(repeatB, 1, spacing - (increment * 3), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); repeatB.replace("{", "["); repeatB.replace("}", "]"); int userData[2]; userData[0] = pins - 1; userData[1] = 1; QString repeatTs = TextUtils::incrementTemplateString(repeatT, (pins - 4) / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::negIncCopyPinFunction, userData); QString repeatBs = TextUtils::incrementTemplateString(repeatB, (pins - 4) / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::incCopyPinFunction, NULL); return svg.arg(TextUtils::getViewBoxCoord(svg, 2) / 100.0).arg(repeatTs).arg(repeatBs); } bool Dip::changePinLabels(bool singleRow, bool sip) { if (m_viewID != ViewLayer::SchematicView) return true; bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (labels.count() == 0) return true; QString svg; if (singleRow) { svg = MysteryPart::makeSchematicSvg(labels, sip); } else { svg = Dip::makeSchematicSvg(labels); } QString chipLabel = modelPart()->localProp("chip label").toString(); if (!chipLabel.isEmpty()) { svg =TextUtils::replaceTextElement(svg, "label", chipLabel); } QTransform transform = untransform(); resetLayerKin(svg); resetConnectors(); retransform(transform); return true; } void Dip::addedToScene(bool temporary) { MysteryPart::addedToScene(temporary); if (this->isDIP()) { resetConnectors(); } } void Dip::swapEntry(const QString & text) { FamilyPropertyComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; bool sip = moduleID().contains("sip"); bool dip = moduleID().contains("dip"); if (comboBox->prop().contains("package", Qt::CaseInsensitive)) { sip = text.contains("sip", Qt::CaseInsensitive); dip = text.contains("dip", Qt::CaseInsensitive); if (!dip && !sip) { // one of the generic smds PaletteItem::swapEntry(text); return; } } if (sip) { generateSwap(text, genModuleID, genSipFZP, makeBreadboardSvg, makeSchematicSvg, PinHeader::makePcbSvg); } else if (dip) { generateSwap(text, genModuleID, genDipFZP, makeBreadboardSvg, makeSchematicSvg, makePcbDipSvg); } PaletteItem::swapEntry(text); } fritzing-app-0.9.2b/src/items/dip.h000066400000000000000000000047021250202676700171450ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef DIP_H #define DIP_H #include "mysterypart.h" class Dip : public MysteryPart { Q_OBJECT public: Dip(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Dip(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); QStringList collectValues(const QString & family, const QString & prop, QString & value); bool changePinLabels(bool singleRow, bool sip); void addedToScene(bool temporary); public: static QString genSipFZP(const QString & moduleid); static QString genDipFZP(const QString & moduleid); static QString genModuleID(QMap & currPropsMap); static QString makeSchematicSvg(const QString & expectedFileName); static QString makeSchematicSvg(const QStringList & labels); static QString makeBreadboardSvg(const QString & expectedFileName); static QString makeBreadboardSipSvg(const QString & expectedFileName); static QString makeBreadboardDipSvg(const QString & expectedFileName); static QString obsoleteMakeSchematicSvg(const QStringList & labels); public slots: void swapEntry(const QString & text); protected: bool isDIP(); bool otherPropsChange(const QMap & propsMap); const QStringList & spacings(); QString retrieveSchematicSvg(QString & svg); }; #endif fritzing-app-0.9.2b/src/items/groundplane.cpp000066400000000000000000000153741250202676700212510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "groundplane.h" #include "../connectors/connectoritem.h" #include "../fsvgrenderer.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include "../svg/svgfilesplitter.h" #include "../svg/groundplanegenerator.h" #include "../sketch/infographicsview.h" #include "../layerattributes.h" #include // TODO: // // delete part if copper fill fails, and remove item from undo stack // maybe that means the generator has to kick in on the dropped item, and if it fails then // there is no undo stack to worry about; if it succeeds, then copy the svg prop. // // does single poly need a connector? // QString GroundPlane::fillTypeIndividual = "individual"; QString GroundPlane::fillTypeGround = "ground"; QString GroundPlane::fillTypePlain = "plain"; QString GroundPlane::fillTypeNone = "none"; static QString IconSvg; void loadIconSvg() { if (IconSvg.isEmpty()) { QFile f(":resources/parts/svg/core/icon/groundplane.svg"); if (f.open(QFile::ReadOnly)) { IconSvg = f.readAll(); f.close(); } } } ///////////////////////////////////////////////////////// GroundPlane::GroundPlane( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_connector0 = NULL; } bool GroundPlane::setUpImage(ModelPart * modelPart, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { bool result = PaletteItem::setUpImage(modelPart, viewLayers, layerAttributes); if (layerAttributes.doConnectors) { foreach (ConnectorItem * item, cachedConnectorItems()) { // there is only one m_connector0 = item; break; } } return result; } void GroundPlane::saveParams() { } void GroundPlane::getParams() { } QString GroundPlane::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString xml = ""; if (viewLayerID == ViewLayer::GroundPlane0 || viewLayerID == ViewLayer::GroundPlane1) { xml = prop("svg"); if (!xml.isEmpty()) { return PaletteItemBase::normalizeSvg(xml, viewLayerID, blackOnly, dpi, factor); } } return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } ConnectorItem * GroundPlane::connector0() { return m_connector0; } bool GroundPlane::hasCustomSVG() { switch (m_viewID) { case ViewLayer::PCBView: return true; default: return ItemBase::hasCustomSVG(); } } void GroundPlane::setProp(const QString & prop, const QString & value) { if (prop.compare("svg", Qt::CaseInsensitive) == 0) { setSvg(value); return; } PaletteItemBase::setProp(prop, value); } void GroundPlane::addedToScene(bool temporary) { if (m_viewLayerID == ViewLayer::GroundPlane0 || m_viewLayerID == ViewLayer::GroundPlane1) { if (this->scene()) { QString svg; if (temporary) { loadIconSvg(); svg = IconSvg; } else { svg = prop("svg"); } if (!svg.isEmpty()) { setSvgAux(svg); } } } PaletteItem::addedToScene(temporary); } void GroundPlane::setSvg(const QString & svg) { modelPart()->setLocalProp("svg", svg); setSvgAux(svg); } void GroundPlane::setSvgAux(const QString & svg) { if (svg.isEmpty()) return; if (m_viewID == ViewLayer::BreadboardView || m_viewID == ViewLayer::SchematicView) return; QString xmlName = ViewLayer::viewLayerXmlNameFromID(m_viewLayerID); SvgFileSplitter splitter; QString cpy = svg; bool result = splitter.splitString(cpy, xmlName); if (result) { resetRenderer(svg); if (m_connector0) { QPainterPath painterPath = splitter.painterPath(GraphicsUtils::SVGDPI, GroundPlaneGenerator::ConnectorName); m_connector0->setRect(painterPath.boundingRect()); m_connector0->setShape(painterPath); } //QPainterPath painterPath = splitter.painterPath(GraphicsUtils::SVGDPI, xmlName); //this->setShape(painterPath); } } QString GroundPlane::svg() { return prop("svg"); } bool GroundPlane::hasPartLabel() { return false; } void GroundPlane::loadLayerKin( const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement viewLayerPlacement) { Q_UNUSED(viewLayers); Q_UNUSED(viewLayerPlacement); // GroundPlane is only on one side or another, not both } bool GroundPlane::hasPartNumberProperty() { return false; } bool GroundPlane::rotationAllowed() { return false; } bool GroundPlane::rotation45Allowed() { return false; } ItemBase::PluralType GroundPlane::isPlural() { return Singular; } bool GroundPlane::canEditPart() { return false; } QString GroundPlane::generateSvg() { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return ""; QPointF q = this->boundingRect().center() + this->pos(); //QPointF r = this->pos() + m_dropOffset; return infoGraphicsView->generateCopperFillUnit(this, q); } void GroundPlane::setDropOffset(QPointF offset) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; m_dropOffset = offset; modelPart()->setLocalProp("fillType", fillTypeIndividual); QString svg = generateSvg(); bool resolve = true; if (svg.isEmpty()) { loadIconSvg(); svg = IconSvg; resolve = false; } setSvg(svg); infoGraphicsView->resolveTemporary(resolve, this); } void GroundPlane::setShape(QPainterPath & pp) { QPen pen; m_shape = GraphicsUtils::shapeFromPath(pp, pen, pen.widthF(), true); } QPainterPath GroundPlane::shape() const { if (!m_shape.isEmpty()) { return m_shape; } return PaletteItemBase::shape(); } ViewLayer::ViewID GroundPlane::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::PCBView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } fritzing-app-0.9.2b/src/items/groundplane.h000066400000000000000000000047011250202676700207060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef GROUNDPLANE_H #define GROUNDPLANE_H #include "paletteitem.h" class GroundPlane : public PaletteItem { public: GroundPlane( ModelPart * modelPart, ViewLayer::ViewID, const ViewGeometry & , long id, QMenu* itemMenu, bool doLabel); bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); void saveParams(); void getParams(); QString retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); class ConnectorItem * connector0(); bool hasCustomSVG(); void setProp(const QString & prop, const QString & value); QString svg(); bool hasPartLabel(); void loadLayerKin( const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement viewLayerPlacement); void addedToScene(bool temporary); bool hasPartNumberProperty(); bool rotationAllowed(); bool rotation45Allowed(); PluralType isPlural(); bool canEditPart(); void setDropOffset(QPointF offset); void setShape(QPainterPath &); QPainterPath shape() const; public: static QString fillTypeIndividual; static QString fillTypeGround; static QString fillTypePlain; static QString fillTypeNone; protected: void setSvg(const QString &); void setSvgAux(const QString &); QString generateSvg(); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected: ConnectorItem * m_connector0; QPointF m_dropOffset; QPainterPath m_shape; }; #endif fritzing-app-0.9.2b/src/items/hole.cpp000066400000000000000000000234761250202676700176640ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "hole.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../commands.h" #include "../utils/textutils.h" #include "../viewlayer.h" #include "partlabel.h" #include "../connectors/nonconnectoritem.h" #include "../connectors/svgidlayer.h" #include #include #include #include #include #include #include #include #include #include const double Hole::OffsetPixels = 2; static HoleClassThing TheHoleThing; ////////////////////////////////////////////////// Hole::Hole( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { PaletteItem::setUpHoleSizes("hole", TheHoleThing); } Hole::~Hole() { } void Hole::setProp(const QString & prop, const QString & value) { if (prop.compare("hole size", Qt::CaseInsensitive) == 0) { setHoleSize(value, false); return; } PaletteItem::setProp(prop, value); } QString Hole::holeSize() { return m_holeSettings.holeSize(); } void Hole::setHoleSize(QString newSize, bool force) { //DebugDialog::debug(QString("old holesize %1").arg(viewID()) + holeSize(), sceneBoundingRect()); //foreach (QGraphicsItem * childItem, childItems()) { // DebugDialog::debug(QString(" child"), childItem->sceneBoundingRect()); //} if (PaletteItem::setHoleSize(newSize, force, m_holeSettings)) { setBoth(m_holeSettings.holeDiameter, m_holeSettings.ringThickness); modelPart()->setLocalProp("hole size", newSize); if (m_partLabel) m_partLabel->displayTextsIf(); } //DebugDialog::debug(QString("new holesize %1 ").arg(viewID()) + holeSize(), sceneBoundingRect()); //foreach (QGraphicsItem * childItem, childItems()) { // DebugDialog::debug(QString(" child"), childItem->sceneBoundingRect()); //} } QRectF Hole::getRect(const QString & newSize) { QString s = newSize; QStringList sizes = getSizes(s, m_holeSettings); if (sizes.count() < 2) return boundingRect(); double diameter = TextUtils::convertToInches(sizes.at(0)); double ringThickness = TextUtils::convertToInches(sizes.at(1)); double dim = (diameter + ringThickness + ringThickness) * GraphicsUtils::SVGDPI; //DebugDialog::debug(QString("get rect %1 %2").arg(newSize).arg(dim)); return QRectF(0, 0, dim, dim); } void Hole::setBoth(const QString & holeDiameter, const QString & ringThickness) { if (this->m_viewID != ViewLayer::PCBView) return; ItemBase * otherLayer = setBothSvg(holeDiameter, ringThickness); // there's only one NonConnectorItem foreach (SvgIdLayer * svgIdLayer, fsvgRenderer()->setUpNonConnectors(viewLayerPlacement())) { if (svgIdLayer == NULL) continue; setBothNonConnectors(this, svgIdLayer); if (otherLayer != NULL) { setBothNonConnectors(otherLayer, svgIdLayer); } delete svgIdLayer; } } ItemBase * Hole::setBothSvg(const QString & holeDiameter, const QString & ringThickness) { QString svg = makeSvg(holeDiameter, ringThickness, m_viewLayerID, true); resetRenderer(svg); //DebugDialog::debug("both"); //DebugDialog::debug(svg); QString setColor; QStringList noIDs; QString osvg; ItemBase * otherLayer = NULL; foreach (ItemBase * layerKin, m_layerKin) { if (layerKin->hasNonConnectors()) { otherLayer = layerKin; break; } } if (otherLayer) { osvg = makeSvg(holeDiameter, ringThickness, otherLayer->viewLayerID(), true); //DebugDialog::debug(osvg); otherLayer->resetRenderer(osvg); } //DebugDialog::debug("other"); return otherLayer; } void Hole::setBothNonConnectors(ItemBase * itemBase, SvgIdLayer * svgIdLayer) { foreach (QGraphicsItem * child, itemBase->childItems()) { NonConnectorItem * nonConnectorItem = dynamic_cast(child); if (nonConnectorItem == NULL) continue; //DebugDialog::debug(QString("hole set rect %1").arg(m_viewID), svgIdLayer->m_rect); nonConnectorItem->setRect(svgIdLayer->rect(viewLayerPlacement())); nonConnectorItem->setRadius(svgIdLayer->m_radius, svgIdLayer->m_strokeWidth); break; } } QString Hole::makeSvg(const QString & holeDiameter, const QString & ringThickness, ViewLayer::ViewLayerID viewLayerID, bool includeHole) { double offsetDPI = OffsetPixels / GraphicsUtils::SVGDPI; double hd = TextUtils::convertToInches(holeDiameter); double rt = TextUtils::convertToInches(ringThickness); double wInches = hd + rt + rt + offsetDPI + offsetDPI; QString svg = TextUtils::makeSVGHeader(1, GraphicsUtils::StandardFritzingDPI, wInches, wInches); hd *= GraphicsUtils::StandardFritzingDPI; rt *= GraphicsUtils::StandardFritzingDPI; offsetDPI *= GraphicsUtils::StandardFritzingDPI; QString setColor; if (viewLayerID == ViewLayer::Copper0) { setColor = ViewLayer::Copper0Color; } else if (viewLayerID == ViewLayer::Copper1) { setColor = ViewLayer::Copper1Color; } svg += QString("").arg(ViewLayer::viewLayerXmlNameFromID(viewLayerID)); QString id = makeID(); if (hd == 0) { svg += QString("") .arg(rt + offsetDPI) .arg(rt) .arg(setColor) .arg(id); } else { svg += QString("") .arg((hd / 2) + rt + offsetDPI) .arg((hd / 2) + (rt / 2)) .arg(rt) .arg(setColor) .arg(id) .arg(rt == 0 ? "black" : "none") ; if (includeHole) { svg += QString("") // set the drill attribute to 0 for gerber translation .arg((hd / 2) + rt + offsetDPI) .arg(hd / 2); } } svg += ""; //DebugDialog::debug("hole svg " + svg); return svg; } QString Hole::makeID() { return FSvgRenderer::NonConnectorName + "0"; } QString Hole::getProperty(const QString & key) { if (key.compare("hole size", Qt::CaseInsensitive) == 0) { return m_holeSettings.holeDiameter; } return PaletteItem::getProperty(key); } void Hole::addedToScene(bool temporary) { if (this->scene()) { setHoleSize(m_holeSettings.holeSize(), true); } return PaletteItem::addedToScene(temporary); } bool Hole::hasCustomSVG() { switch (m_viewID) { case ViewLayer::PCBView: return true; default: return ItemBase::hasCustomSVG(); } } ItemBase::PluralType Hole::isPlural() { return Plural; } QString Hole::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { if (m_viewID != ViewLayer::PCBView || (viewLayerID != ViewLayer::Copper0 && viewLayerID != ViewLayer::Copper1)) { return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QStringList holeSize = m_modelPart->localProp("hole size").toString().split(","); if (holeSize.length() == 2) { QString svg = makeSvg(holeSize.at(0), holeSize.at(1), viewLayerID, false); if (!svg.isEmpty()) { return PaletteItemBase::normalizeSvg(svg, viewLayerID, blackOnly, dpi, factor); } } return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } bool Hole::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("hole size", Qt::CaseInsensitive) == 0) { return collectHoleSizeInfo(TheHoleThing.holeSizeValue, parent, swappingEnabled, returnProp, returnValue, returnWidget); } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void Hole::changeHoleSize(const QString & newSize) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { QRectF holeRect = getRect(holeSize()); QRectF newHoleRect = getRect(newSize); infoGraphicsView->setHoleSize(this, "hole size", tr("hole size"), holeSize(), newSize, holeRect, newHoleRect, true); } } bool Hole::canEditPart() { return false; } bool Hole::hasPartNumberProperty() { return false; } bool Hole::rotationAllowed() { return false; } bool Hole::rotation45Allowed() { return false; } bool Hole::canFindConnectorsUnder() { return false; } ViewLayer::ViewID Hole::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::PCBView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } void Hole::changeUnits(bool) { QString newVal = PaletteItem::changeUnits(m_holeSettings); modelPart()->setLocalProp("hole size", newVal); } QRectF Hole::trueSceneBoundingRect() { QRectF r = sceneBoundingRect(); return r.adjusted(OffsetPixels, OffsetPixels, -OffsetPixels, -OffsetPixels); } fritzing-app-0.9.2b/src/items/hole.h000066400000000000000000000056141250202676700173230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef HOLE_H #define HOLE_H #include #include #include #include #include #include "paletteitem.h" class Hole : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Hole(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Hole(); QString getProperty(const QString & key); void setProp(const QString & prop, const QString & value); void setHoleSize(QString holeSize, bool force); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool hasCustomSVG(); PluralType isPlural(); QString retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool canEditPart(); void addedToScene(bool temporary); bool hasPartNumberProperty(); QString holeSize(); bool rotationAllowed(); bool rotation45Allowed(); bool canFindConnectorsUnder(); QRectF trueSceneBoundingRect(); protected slots: void changeHoleSize(const QString &); void changeUnits(bool); protected: QString makeSvg(const QString & holeDiameter, const QString & ringThickness, ViewLayer::ViewLayerID, bool includeHole); virtual QString makeID(); ItemBase * setBothSvg(const QString & holeDiameter, const QString & ringThickness); void setBothNonConnectors(ItemBase * itemBase, SvgIdLayer * svgIdLayer); virtual void setBoth(const QString & holeDiameter, const QString & thickness); QRectF getRect(const QString & newSize); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); public: static const double OffsetPixels; }; #endif fritzing-app-0.9.2b/src/items/itembase.cpp000066400000000000000000002140651250202676700205220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "itembase.h" #include "partfactory.h" #include "../debugdialog.h" #include "../model/modelpart.h" #include "../connectors/connectoritem.h" #include "../connectors/connectorshared.h" #include "../sketch/infographicsview.h" #include "../connectors/connector.h" #include "../connectors/bus.h" #include "partlabel.h" #include "../layerattributes.h" #include "../fsvgrenderer.h" #include "../svg/svgfilesplitter.h" #include "../svg/svgflattener.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/cursormaster.h" #include "../utils/clickablelabel.h" #include "../utils/familypropertycombobox.h" #include "../referencemodel/referencemodel.h" #include #include #include #include #include #include #include #include #include #include ///////////////////////////////// static QRegExp NumberMatcher; static QHash NumberMatcherValues; static const double InactiveOpacity = 0.4; bool numberValueLessThan(QString v1, QString v2) { return NumberMatcherValues.value(v1, 0) <= NumberMatcherValues.value(v2, 0); } static QSvgRenderer MoveLockRenderer; static QSvgRenderer StickyRenderer; ///////////////////////////////// class NameTriple { public: NameTriple(const QString & _xmlName, const QString & _viewName, const QString & _naturalName) { m_xmlName = _xmlName; m_viewName = _viewName; m_naturalName = _naturalName; } QString & xmlName() { return m_xmlName; } QString & viewName() { return m_viewName; } QString & naturalName() { return m_naturalName; } protected: QString m_xmlName; QString m_naturalName; QString m_viewName; }; ///////////////////////////////// const QString ItemBase::ITEMBASE_FONT_PREFIX = ""; const QString ItemBase::ITEMBASE_FONT_SUFFIX = ""; QHash ItemBase::TranslatedPropertyNames; QPointer ItemBase::TheReferenceModel = NULL; QString ItemBase::PartInstanceDefaultTitle; const QList ItemBase::EmptyList; const QColor ItemBase::HoverColor(0,0,0); const double ItemBase::HoverOpacity = .20; const QColor ItemBase::ConnectorHoverColor(0,0,255); const double ItemBase::ConnectorHoverOpacity = .40; const QColor StandardConnectedColor(0, 255, 0); const QColor StandardUnconnectedColor(255, 0, 0); QPen ItemBase::NormalPen(QColor(255,0,0)); QPen ItemBase::HoverPen(QColor(0, 0, 255)); QPen ItemBase::ConnectedPen(StandardConnectedColor); QPen ItemBase::UnconnectedPen(StandardUnconnectedColor); QPen ItemBase::ChosenPen(QColor(255,0,0)); QPen ItemBase::EqualPotentialPen(QColor(255,255,0)); QBrush ItemBase::NormalBrush(QColor(255,0,0)); QBrush ItemBase::HoverBrush(QColor(0,0,255)); QBrush ItemBase::ConnectedBrush(StandardConnectedColor); QBrush ItemBase::UnconnectedBrush(StandardUnconnectedColor); QBrush ItemBase::ChosenBrush(QColor(255,0,0)); QBrush ItemBase::EqualPotentialBrush(QColor(255,255,0)); const double ItemBase::NormalConnectorOpacity = 0.4; static QHash CachedValues; /////////////////////////////////////////////////// ItemBase::ItemBase( ModelPart* modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu ) : QGraphicsSvgItem() { m_fsvgRenderer = NULL; m_superpart = NULL; m_acceptsMousePressLegEvent = true; m_squashShape = false; //DebugDialog::debug(QString("itembase %1 %2").arg(id).arg((long) static_cast(this), 0, 16)); m_hasRubberBandLeg = m_moveLock = m_hoverEnterSpaceBarWasPressed = m_spaceBarWasPressed = false; m_moveLockItem = NULL; m_stickyItem = NULL; m_swappable = m_everVisible = true; m_rightClickedConnector = NULL; m_partLabel = NULL; m_itemMenu = itemMenu; m_hoverCount = m_connectorHoverCount = m_connectorHoverCount2 = 0; m_viewID = viewID; m_modelPart = modelPart; if (m_modelPart) { m_modelPart->addViewItem(this); } m_id = id; m_canFlipHorizontal = m_canFlipVertical = m_sticky = m_inRotation = m_inactive = m_layerHidden = m_hidden = false; setCursor(*CursorMaster::MoveCursor); m_viewGeometry.set(viewGeometry); setAcceptHoverEvents ( true ); m_zUninitialized = true; } ItemBase::~ItemBase() { //DebugDialog::debug(QString("deleting itembase %1 %2 %3").arg((long) this, 0, 16).arg(m_id).arg((long) m_modelPart, 0, 16)); if (m_partLabel) { delete m_partLabel; m_partLabel = NULL; } foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { toConnectorItem->tempRemove(connectorItem, true); } } foreach (ItemBase * itemBase, m_stickyList) { itemBase->addSticky(this, false); } if (m_modelPart != NULL) { m_modelPart->removeViewItem(this); } if (m_fsvgRenderer) { delete m_fsvgRenderer; } } void ItemBase::setTooltip() { if(m_modelPart) { QString title = instanceTitle(); if(!title.isNull() && !title.isEmpty()) { setInstanceTitleTooltip(title); } else { setDefaultTooltip(); } } else { setDefaultTooltip(); } } void ItemBase::removeTooltip() { this->setToolTip(___emptyString___); } bool ItemBase::zLessThan(ItemBase * & p1, ItemBase * & p2) { return p1->z() < p2->z(); } qint64 ItemBase::getNextID() { return ModelPart::nextIndex() * ModelPart::indexMultiplier; // make sure we leave room for layerkin inbetween } qint64 ItemBase::getNextID(qint64 index) { qint64 temp = index * ModelPart::indexMultiplier; // make sure we leave room for layerkin inbetween ModelPart::updateIndex(index); return temp; } QSizeF ItemBase::size() { return m_size; } qint64 ItemBase::id() const { return m_id; } void ItemBase::resetID() { m_id = m_modelPart->modelIndex() * ModelPart::indexMultiplier; } double ItemBase::z() { return getViewGeometry().z(); } ModelPart * ItemBase::modelPart() { return m_modelPart; } void ItemBase::setModelPart(ModelPart * modelPart) { m_modelPart = modelPart; } ModelPartShared * ItemBase::modelPartShared() { if (m_modelPart == NULL) return NULL; return m_modelPart->modelPartShared(); } void ItemBase::initNames() { if (NumberMatcher.isEmpty()) { NumberMatcher.setPattern(QString("(([0-9]+(\\.[0-9]*)?)|\\.[0-9]+)([\\s]*([") + TextUtils::PowerPrefixesString + "]))?"); } if (TranslatedPropertyNames.count() == 0) { TranslatedPropertyNames.insert("family", tr("family")); TranslatedPropertyNames.insert("type", tr("type")); TranslatedPropertyNames.insert("model", tr("model")); TranslatedPropertyNames.insert("size", tr("size")); TranslatedPropertyNames.insert("color", tr("color")); TranslatedPropertyNames.insert("resistance", tr("resistance")); TranslatedPropertyNames.insert("capacitance", tr("capacitance")); TranslatedPropertyNames.insert("inductance", tr("inductance")); TranslatedPropertyNames.insert("voltage", tr("voltage")); TranslatedPropertyNames.insert("current", tr("current")); TranslatedPropertyNames.insert("power", tr("power")); TranslatedPropertyNames.insert("pin spacing", tr("pin spacing")); TranslatedPropertyNames.insert("rated power", tr("rated power")); TranslatedPropertyNames.insert("rated voltage", tr("rated voltage")); TranslatedPropertyNames.insert("rated current", tr("rated current")); TranslatedPropertyNames.insert("version", tr("version")); TranslatedPropertyNames.insert("package", tr("package")); TranslatedPropertyNames.insert("shape", tr("shape")); TranslatedPropertyNames.insert("form", tr("form")); TranslatedPropertyNames.insert("part number", tr("part number")); TranslatedPropertyNames.insert("maximum resistance", tr("maximum resistance")); TranslatedPropertyNames.insert("pins", tr("pins")); TranslatedPropertyNames.insert("spacing", tr("spacing")); TranslatedPropertyNames.insert("pin spacing", tr("pin spacing")); TranslatedPropertyNames.insert("frequency", tr("frequency")); TranslatedPropertyNames.insert("processor", tr("processor")); TranslatedPropertyNames.insert("variant", tr("variant")); TranslatedPropertyNames.insert("layers", tr("layers")); TranslatedPropertyNames.insert("tolerance", tr("tolerance")); TranslatedPropertyNames.insert("descr", tr("descr")); TranslatedPropertyNames.insert("filename", tr("filename")); TranslatedPropertyNames.insert("title", tr("title")); TranslatedPropertyNames.insert("date", tr("date")); TranslatedPropertyNames.insert("rev", tr("rev")); TranslatedPropertyNames.insert("sheet", tr("sheet")); TranslatedPropertyNames.insert("project", tr("project")); TranslatedPropertyNames.insert("banded", tr("banded")); TranslatedPropertyNames.insert("top", tr("top")); TranslatedPropertyNames.insert("bottom", tr("bottom")); TranslatedPropertyNames.insert("copper bottom", tr("copper bottom")); TranslatedPropertyNames.insert("copper top", tr("copper top")); TranslatedPropertyNames.insert("silkscreen bottom", tr("silkscreen bottom")); TranslatedPropertyNames.insert("silkscreen top", tr("silkscreen top")); // TODO: translate more known property names from fzp files and resource xml files } PartInstanceDefaultTitle = tr("Part"); QSettings settings; QString colorName = settings.value("ConnectedColor").toString(); if (!colorName.isEmpty()) { QColor color; color.setNamedColor(colorName); setConnectedColor(color); } colorName = settings.value("UnconnectedColor").toString(); if (!colorName.isEmpty()) { QColor color; color.setNamedColor(colorName); setUnconnectedColor(color); } } void ItemBase::saveInstance(QXmlStreamWriter & streamWriter) { streamWriter.writeStartElement(ViewLayer::viewIDXmlName(m_viewID)); streamWriter.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(m_viewLayerID)); if (m_moveLock) { streamWriter.writeAttribute("locked", "true"); } if (m_superpart) { streamWriter.writeAttribute("superpart", QString::number(m_superpart->modelPart()->modelIndex())); } if (m_viewLayerPlacement == ViewLayer::NewBottom && m_viewID == ViewLayer::PCBView) { streamWriter.writeAttribute("bottom", "true"); } this->saveGeometry(); writeGeometry(streamWriter); if (m_partLabel) { m_partLabel->saveInstance(streamWriter); } QList itemBases; itemBases.append(this); itemBases.append(layerKinChief()->layerKin()); foreach (ItemBase * itemBase, itemBases) { if (itemBase->layerHidden()) { streamWriter.writeStartElement("layerHidden"); streamWriter.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(itemBase->viewLayerID())); streamWriter.writeEndElement(); } } bool saveConnectorItems = false; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0 || connectorItem->hasRubberBandLeg() || connectorItem->isGroundFillSeed()) { saveConnectorItems = true; break; } } if (saveConnectorItems) { streamWriter.writeStartElement("connectors"); foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { connectorItem->saveInstance(streamWriter); } streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } void ItemBase::writeGeometry(QXmlStreamWriter & streamWriter) { streamWriter.writeStartElement("geometry"); streamWriter.writeAttribute("z", QString::number(z())); this->saveInstanceLocation(streamWriter); // do not write attributes here streamWriter.writeEndElement(); } ViewGeometry & ItemBase::getViewGeometry() { return m_viewGeometry; } ViewLayer::ViewID ItemBase::viewID() { return m_viewID; } QString & ItemBase::viewIDName() { return ViewLayer::viewIDName(m_viewID); } ViewLayer::ViewLayerID ItemBase::viewLayerID() const { return m_viewLayerID; } void ItemBase::setViewLayerID(const QString & layerName, const LayerHash & viewLayers) { //DebugDialog::debug(QString("using z %1").arg(layerName)); setViewLayerID(ViewLayer::viewLayerIDFromXmlString(layerName), viewLayers); } void ItemBase::setViewLayerID(ViewLayer::ViewLayerID viewLayerID, const LayerHash & viewLayers) { m_viewLayerID = viewLayerID; if (m_zUninitialized) { ViewLayer * viewLayer = viewLayers.value(m_viewLayerID); if (viewLayer != NULL) { m_zUninitialized = false; if (!viewLayer->alreadyInLayer(m_viewGeometry.z())) { m_viewGeometry.setZ(viewLayer->nextZ()); } } } //DebugDialog::debug(QString("using z: %1 z:%2 lid:%3").arg(title()).arg(m_viewGeometry.z()).arg(m_viewLayerID) ); } void ItemBase::removeLayerKin() { } void ItemBase::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) { //DebugDialog::debug(QString("hover enter c %1").arg(instanceTitle())); hoverEnterConnectorItem(); } void ItemBase::hoverEnterConnectorItem() { //DebugDialog::debug(QString("hover enter c %1").arg(instanceTitle())); m_connectorHoverCount++; hoverUpdate(); } void ItemBase::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) { hoverLeaveConnectorItem(); } void ItemBase::hoverMoveConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) { } void ItemBase::hoverLeaveConnectorItem() { //DebugDialog::debug(QString("hover leave c %1").arg(instanceTitle())); m_connectorHoverCount--; hoverUpdate(); } void ItemBase::clearConnectorHover() { m_connectorHoverCount2 = 0; hoverUpdate(); } void ItemBase::connectorHover(ConnectorItem *, ItemBase *, bool hovering) { //DebugDialog::debug(QString("hover c %1 %2").arg(hovering).arg(instanceTitle())); if (hovering) { m_connectorHoverCount2++; } else { m_connectorHoverCount2--; } // DebugDialog::debug(QString("m_connectorHoverCount2 %1 %2").arg(instanceTitle()).arg(m_connectorHoverCount2)); hoverUpdate(); } void ItemBase::hoverUpdate() { this->update(); } void ItemBase::mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { } void ItemBase::mouseDoubleClickConnectorEvent(ConnectorItem *) { } void ItemBase::mouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { } void ItemBase::mouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { } bool ItemBase::filterMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return false; } bool ItemBase::acceptsMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return true; } bool ItemBase::acceptsMousePressLegEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return m_acceptsMousePressLegEvent; } void ItemBase::setAcceptsMousePressLegEvent(bool b) { m_acceptsMousePressLegEvent = b; } bool ItemBase::acceptsMouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return false; } bool ItemBase::acceptsMouseDoubleClickConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return false; } bool ItemBase::acceptsMouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return false; } void ItemBase::connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect) { Q_UNUSED(onMe); Q_UNUSED(onIt); Q_UNUSED(connect); } void ItemBase::connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already) { Q_UNUSED(from); Q_UNUSED(to); Q_UNUSED(already); } ItemBase * ItemBase::extractTopLevelItemBase(QGraphicsItem * item) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) return NULL; if (itemBase->topLevel()) return itemBase; return NULL; } bool ItemBase::topLevel() { return (this == this->layerKinChief()); } void ItemBase::setHidden(bool hide) { m_hidden = hide; updateHidden(); foreach (QGraphicsItem * item, childItems()) { NonConnectorItem * nonconnectorItem = dynamic_cast(item); if (nonconnectorItem == NULL) continue; nonconnectorItem->setHidden(hide); } } void ItemBase::setInactive(bool inactivate) { m_inactive = inactivate; updateHidden(); foreach (QGraphicsItem * item, childItems()) { NonConnectorItem * nonconnectorItem = dynamic_cast(item); if (nonconnectorItem == NULL) continue; nonconnectorItem->setInactive(inactivate); } } void ItemBase::setLayerHidden(bool layerHidden) { m_layerHidden = layerHidden; updateHidden(); foreach (QGraphicsItem * item, childItems()) { NonConnectorItem * nonconnectorItem = dynamic_cast(item); if (nonconnectorItem == NULL) continue; nonconnectorItem->setLayerHidden(layerHidden); } } void ItemBase::updateHidden() { setAcceptedMouseButtons(m_hidden || m_inactive || m_layerHidden ? Qt::NoButton : ALLMOUSEBUTTONS); setAcceptHoverEvents(!(m_hidden || m_inactive || m_layerHidden)); update(); } bool ItemBase::hidden() { return m_hidden; } bool ItemBase::layerHidden() { return m_layerHidden; } bool ItemBase::inactive() { return m_inactive; } void ItemBase::collectConnectors(ConnectorPairHash & connectorHash, SkipCheckFunction skipCheckFunction) { // Is this modelpart check obsolete? ModelPart * modelPart = this->modelPart(); if (modelPart == NULL) return; // collect all the connectorItem pairs foreach (ConnectorItem * fromConnectorItem, cachedConnectorItems()) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { if (skipCheckFunction && skipCheckFunction(toConnectorItem)) continue; connectorHash.insert(fromConnectorItem, toConnectorItem); } ConnectorItem * crossConnectorItem = fromConnectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem == NULL) continue; foreach (ConnectorItem * toConnectorItem, crossConnectorItem->connectedToItems()) { if (skipCheckFunction && skipCheckFunction(toConnectorItem)) continue; connectorHash.insert(crossConnectorItem, toConnectorItem); } } } ConnectorItem * ItemBase::findConnectorItemWithSharedID(const QString & connectorID) { Connector * connector = modelPart()->getConnector(connectorID); if (connector) { return connector->connectorItem(m_viewID); } return NULL; } ConnectorItem * ItemBase::findConnectorItemWithSharedID(const QString & connectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement) { ConnectorItem * connectorItem = findConnectorItemWithSharedID(connectorID); if (connectorItem) { return connectorItem->chooseFromSpec(viewLayerPlacement); } return NULL; } void ItemBase::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) { // debugInfo("itembase hover enter"); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { m_hoverEnterSpaceBarWasPressed = true; event->ignore(); return; } m_hoverEnterSpaceBarWasPressed = false; m_hoverCount++; //debugInfo(QString("inc hover %1").arg(m_hoverCount)); hoverUpdate(); if (infoGraphicsView != NULL) { infoGraphicsView->hoverEnterItem(event, this); } } void ItemBase::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { //DebugDialog::debug(QString("hover leave %1").arg(instanceTitle())); if (m_hoverEnterSpaceBarWasPressed) { event->ignore(); return; } m_hoverCount--; //debugInfo(QString("dec hover %1").arg(m_hoverCount)); hoverUpdate(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->hoverLeaveItem(event, this); } } void ItemBase::updateConnections(bool includeRatsnest, QList & already) { Q_UNUSED(already) Q_UNUSED(includeRatsnest); } void ItemBase::updateConnections(ConnectorItem * connectorItem, bool includeRatsnest, QList & already) { if (!already.contains(connectorItem)) { already << connectorItem; connectorItem->attachedMoved(includeRatsnest, already); } else { connectorItem->debugInfo("already"); } } const QString & ItemBase::title() { if (m_modelPart == NULL) return ___emptyString___; return m_modelPart->title(); } const QString & ItemBase::constTitle() const { if (m_modelPart == NULL) return ___emptyString___; return m_modelPart->title(); } const QString & ItemBase::spice() const { if (m_modelPart == NULL) return ___emptyString___; return m_modelPart->spice(); } const QString & ItemBase::spiceModel() const { if (m_modelPart == NULL) return ___emptyString___; return m_modelPart->spiceModel(); } bool ItemBase::getRatsnest() { return m_viewGeometry.getRatsnest(); } QList ItemBase::buses() { QList busList; if (m_modelPart == NULL) return busList; foreach (Bus * bus, m_modelPart->buses().values()) { busList.append(bus); } return busList; } void ItemBase::busConnectorItems(class Bus * bus, ConnectorItem * fromConnectorItem, QList & items) { Q_UNUSED(fromConnectorItem) if (bus == NULL) return; foreach (Connector * connector, bus->connectors()) { foreach (ConnectorItem * connectorItem, connector->viewItems()) { if (connectorItem != NULL) { //connectorItem->debugInfo(QString("on the bus %1").arg((long) connector, 0, 16)); if (connectorItem->attachedTo() == this) { items.append(connectorItem); } } } } if (m_superpart || m_subparts.count() > 0) { Connector * connector = bus->subConnector(); if (connector) { foreach (ConnectorItem * connectorItem, connector->viewItems()) { if (connectorItem != NULL) { //connectorItem->debugInfo(QString("on the bus %1").arg((long) connector, 0, 16)); if (connectorItem->attachedToViewID() == m_viewID) { items.append(connectorItem); } } } } } /* if (items.count() > 0) { fromConnectorItem->debugInfo("bus"); foreach (ConnectorItem * ci, items) { ci->debugInfo("\t"); } } */ } int ItemBase::itemType() const { if (m_modelPart == NULL) return ModelPart::Unknown; return m_modelPart->itemType(); } bool ItemBase::inHover() { return (!m_inactive && (m_connectorHoverCount > 0 || m_hoverCount > 0 || m_connectorHoverCount2 > 0)); } void ItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (inHover()) { //DebugDialog::debug(QString("chc:%1 hc:%2 chc2:%3").arg(m_connectorHoverCount).arg(m_hoverCount).arg(m_connectorHoverCount2)); layerKinChief()->paintHover(painter, option, widget); } //else { //DebugDialog::debug("no hover"); //} if (m_inactive) { painter->save(); painter->setOpacity(InactiveOpacity); } paintBody(painter, option, widget); if (option->state & QStyle::State_Selected) { layerKinChief()->paintSelected(painter, option, widget); } if (m_inactive) { painter->restore(); } } void ItemBase::paintBody(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); // Qt's SVG renderer's defaultSize is not correct when the svg has a fractional pixel size fsvgRenderer()->render(painter, boundingRectWithoutLegs()); } void ItemBase::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { paintHover(painter, option, widget, hoverShape()); } void ItemBase::paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, boundingRect(), hoverShape()); } void ItemBase::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, const QPainterPath & shape) { Q_UNUSED(widget); Q_UNUSED(option); painter->save(); if (m_connectorHoverCount > 0 || m_connectorHoverCount2 > 0) { painter->setOpacity(ConnectorHoverOpacity); painter->fillPath(shape, QBrush(ConnectorHoverColor)); } else { painter->setOpacity(HoverOpacity); painter->fillPath(shape, QBrush(HoverColor)); } painter->restore(); } void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event) { InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { event->ignore(); return; } //scene()->setItemIndexMethod(QGraphicsScene::NoIndex); //setCacheMode(QGraphicsItem::DeviceCoordinateCache); QGraphicsSvgItem::mousePressEvent(event); } void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { m_rightClickedConnector = NULL; // calling parent class so that multiple selection will work // haven't yet discovered any nasty side-effect QGraphicsSvgItem::mouseReleaseEvent(event); //scene()->setItemIndexMethod(QGraphicsScene::BspTreeIndex); // setCacheMode(QGraphicsItem::NoCache); } void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *) { } void ItemBase::setItemPos(QPointF & loc) { setPos(loc); } bool ItemBase::stickyEnabled() { return true; } bool ItemBase::isSticky() { return isBaseSticky() && isLocalSticky(); } bool ItemBase::isBaseSticky() { return m_sticky; // to cancel sticky return false; } void ItemBase::setSticky(bool s) { m_sticky = s; } bool ItemBase::isLocalSticky() { if (layerKinChief() != this) { return layerKinChief()->isLocalSticky(); } QString stickyVal = modelPart()->localProp("sticky").toString(); // return (stickyVal.compare("false") != 0); // defaults to true return (stickyVal.compare("true") == 0); // defaults to false } void ItemBase::setLocalSticky(bool s) { // dirty the window? // undo command? if (layerKinChief() != this) { layerKinChief()->setLocalSticky(s); return; } modelPart()->setLocalProp("sticky", s ? "true" : "false"); if (s) { if (m_stickyItem == NULL) { if (!StickyRenderer.isValid()) { QString fn(":resources/images/part_sticky.svg"); bool success = StickyRenderer.load(fn); Q_UNUSED(success); //DebugDialog::debug(QString("sticky load success %1").arg(success)); } m_stickyItem = new QGraphicsSvgItem(); m_stickyItem->setAcceptHoverEvents(false); m_stickyItem->setAcceptedMouseButtons(Qt::NoButton); m_stickyItem->setSharedRenderer(&StickyRenderer); m_stickyItem->setPos(m_moveLockItem == NULL ? 0 : m_moveLockItem->boundingRect().width() + 1, 0); m_stickyItem->setZValue(-99999); m_stickyItem->setParentItem(this); m_stickyItem->setVisible(true); } } else { if (m_stickyItem) { delete m_stickyItem; m_stickyItem = NULL; } } update(); } void ItemBase::addSticky(ItemBase * stickyBase, bool stickem) { stickyBase = stickyBase->layerKinChief(); //this->debugInfo(QString("add sticky %1:").arg(stickem)); //sticky->debugInfo(QString(" to")); if (stickem) { if (!isBaseSticky()) { foreach (ItemBase * oldstickingTo, m_stickyList.values()) { if (oldstickingTo == stickyBase) continue; oldstickingTo->addSticky(this, false); } m_stickyList.clear(); } m_stickyList.insert(stickyBase->id(), stickyBase); } else { m_stickyList.remove(stickyBase->id()); } } ItemBase * ItemBase::stickingTo() { if (isBaseSticky()) return NULL; if (m_stickyList.count() < 1) return NULL; if (m_stickyList.count() > 1) { DebugDialog::debug(QString("error: sticky list > 1 %1").arg(title())); } return *m_stickyList.begin(); } QList< QPointer > ItemBase::stickyList() { return m_stickyList.values(); } bool ItemBase::alreadySticking(ItemBase * itemBase) { return m_stickyList.value(itemBase->layerKinChief()->id(), NULL) != NULL; } ConnectorItem* ItemBase::newConnectorItem(Connector *connector) { return newConnectorItem(this, connector); } ConnectorItem* ItemBase::newConnectorItem(ItemBase * layerKin, Connector *connector) { return new ConnectorItem(connector, layerKin); } ConnectorItem * ItemBase::anyConnectorItem() { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { return connectorItem; } return NULL; } const QString & ItemBase::instanceTitle() const { if (m_modelPart) { return m_modelPart->instanceTitle(); } return ___emptyString___; } void ItemBase::setInstanceTitle(const QString &title, bool initial) { setInstanceTitleAux(title, initial); if (m_partLabel) { m_partLabel->setPlainText(title); } } void ItemBase::updatePartLabelInstanceTitle() { if (m_partLabel) { m_partLabel->setPlainText(instanceTitle()); } } void ItemBase::setInstanceTitleAux(const QString &title, bool initial) { if (m_modelPart) { m_modelPart->setInstanceTitle(title, initial); } setInstanceTitleTooltip(title); // InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); // if (infographics != NULL) { // infographics->setItemTooltip(this, title); // } } QString ItemBase::label() { if(m_modelPart) { return m_modelPart->label(); } return ___emptyString___; } void ItemBase::updateTooltip() { setInstanceTitleTooltip(instanceTitle()); } void ItemBase::setInstanceTitleTooltip(const QString &text) { setToolTip(""+text+"

" + ITEMBASE_FONT_PREFIX + title()+ ITEMBASE_FONT_SUFFIX); } void ItemBase::setDefaultTooltip() { if (m_modelPart) { if (m_viewID == ViewLayer::IconView) { QString base = ITEMBASE_FONT_PREFIX + "%1" + ITEMBASE_FONT_SUFFIX; if(m_modelPart->itemType() != ModelPart::Wire) { this->setToolTip(base.arg(m_modelPart->title())); } else { this->setToolTip(base.arg(m_modelPart->title() + " (" + m_modelPart->moduleID() + ")")); } return; } QString title = ItemBase::PartInstanceDefaultTitle; QString inst = instanceTitle(); if(!inst.isNull() && !inst.isEmpty()) { title = inst; } else { QString defaultTitle = label(); if(!defaultTitle.isNull() && !defaultTitle.isEmpty()) { title = defaultTitle; } } ensureUniqueTitle(title, false); setInstanceTitleTooltip(instanceTitle()); } } void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { if ((acceptedMouseButtons() & Qt::RightButton) == 0) { event->ignore(); return; } if (m_hidden || m_inactive || m_layerHidden) { event->ignore(); return; } scene()->clearSelection(); setSelected(true); if (m_itemMenu != NULL) { m_rightClickedConnector = NULL; foreach (QGraphicsItem * item, scene()->items(event->scenePos())) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (connectorItem->attachedTo() == this) { m_rightClickedConnector = connectorItem; break; } } m_itemMenu->exec(event->screenPos()); } } bool ItemBase::hasConnectors() { return cachedConnectorItems().count() > 0; } bool ItemBase::hasNonConnectors() { foreach (QGraphicsItem * childItem, childItems()) { if (dynamic_cast(childItem) != NULL) return true; } return false; } bool ItemBase::canFlip(Qt::Orientations orientations) { bool result = true; if (orientations & Qt::Horizontal) { result = result && m_canFlipHorizontal; } if (orientations & Qt::Vertical) { result = result && m_canFlipVertical; } return result; } bool ItemBase::canFlipHorizontal() { return m_canFlipHorizontal && !m_moveLock; } void ItemBase::setCanFlipHorizontal(bool cf) { m_canFlipHorizontal = cf; } bool ItemBase::canFlipVertical() { return m_canFlipVertical && !m_moveLock; } void ItemBase::setCanFlipVertical(bool cf) { m_canFlipVertical = cf; } bool ItemBase::rotationAllowed() { return !m_moveLock; } bool ItemBase::rotation45Allowed() { return !m_moveLock; } bool ItemBase::freeRotationAllowed() { return false; } void ItemBase::clearModelPart() { m_modelPart = NULL; } void ItemBase::hidePartLabel() { InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) infoGraphicsView->hidePartLabel(this); } void ItemBase::showPartLabel(bool showIt, ViewLayer* viewLayer) { if (m_partLabel) { m_partLabel->showLabel(showIt, viewLayer); } } void ItemBase::partLabelChanged(const QString & newText) { // sent from part label after inline edit InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); QString oldText = modelPart()->instanceTitle(); setInstanceTitleAux(newText, false); if (infographics != NULL) { infographics->partLabelChanged(this, oldText, newText); } } bool ItemBase::isPartLabelVisible() { if (m_partLabel == NULL) return false; if (!hasPartLabel()) return false; if (!m_partLabel->initialized()) return false; return m_partLabel->isVisible(); } void ItemBase::clearPartLabel() { m_partLabel = NULL; } void ItemBase::restorePartLabel(QDomElement & labelGeometry, ViewLayer::ViewLayerID viewLayerID) { if (m_partLabel) { m_partLabel->setPlainText(instanceTitle()); if (!labelGeometry.isNull()) { m_partLabel->restoreLabel(labelGeometry, viewLayerID); //m_partLabel->setPlainText(instanceTitle()); } } } void ItemBase::movePartLabel(QPointF newPos, QPointF newOffset) { if (m_partLabel) { m_partLabel->moveLabel(newPos, newOffset); } } void ItemBase::partLabelSetHidden(bool hide) { if (m_partLabel) { m_partLabel->setHidden(hide); } } void ItemBase::partLabelMoved(QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->partLabelMoved(this, oldPos, oldOffset, newPos, newOffset); } } void ItemBase::rotateFlipPartLabel(double degrees, Qt::Orientations orientation) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->rotateFlipPartLabel(this, degrees, orientation); } } void ItemBase::doRotateFlipPartLabel(double degrees, Qt::Orientations orientation) { if (m_partLabel) { m_partLabel->rotateFlipLabel(degrees, orientation); } } bool ItemBase::isSwappable() { return m_swappable; } void ItemBase::setSwappable(bool swappable) { m_swappable = swappable; } void ItemBase::ensureUniqueTitle(const QString & title, bool force) { if (force || instanceTitle().isEmpty() || instanceTitle().isNull()) { setInstanceTitle(modelPart()->getNextTitle(title), true); } } QVariant ItemBase::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { switch (change) { case QGraphicsItem::ItemSelectedChange: if (m_partLabel) { m_partLabel->ownerSelected(value.toBool()); } break; default: break; } return QGraphicsSvgItem::itemChange(change, value); } void ItemBase::cleanup() { } const QList & ItemBase::layerKin() { return EmptyList; } ItemBase * ItemBase::layerKinChief() { return this; } void ItemBase::rotateItem(double degrees, bool includeRatsnest) { //this->debugInfo(QString("\trotating item %1").arg(degrees)); transformItem(QTransform().rotate(degrees), includeRatsnest); } void ItemBase::flipItem(Qt::Orientations orientation) { int xScale; int yScale; if(orientation == Qt::Vertical) { xScale = 1; yScale = -1; } else if(orientation == Qt::Horizontal) { xScale = -1; yScale = 1; } else { return; } transformItem(QTransform().scale(xScale,yScale), false); } void ItemBase::transformItem(const QTransform & currTransf, bool includeRatsnest) { //debugInfo("transform item " + TextUtils::svgMatrix(currTransf)); QTransform trns = getViewGeometry().transform(); //debugInfo("\t" + TextUtils::svgMatrix(trns)); if (m_hasRubberBandLeg) { prepareGeometryChange(); } QRectF rect = this->boundingRectWithoutLegs(); //debugInfo(QString("\t bounding rect w:%1, h:%2").arg(rect.width()).arg(rect.height())); double x = rect.width() / 2.0; double y = rect.height() / 2.0; QTransform transf = QTransform().translate(-x, -y) * currTransf * QTransform().translate(x, y); getViewGeometry().setTransform(getViewGeometry().transform()*transf); this->setTransform(getViewGeometry().transform()); if (!m_hasRubberBandLeg) { QList already; updateConnections(includeRatsnest, already); } trns = getViewGeometry().transform(); //debugInfo("\t" + TextUtils::svgMatrix(trns)); update(); } void ItemBase::transformItem2(const QMatrix & matrix) { QTransform transform(matrix); transformItem(transform, false); } void ItemBase::collectWireConnectees(QSet & wires) { Q_UNUSED(wires); } bool ItemBase::collectFemaleConnectees(QSet & items) { Q_UNUSED(items); return false; // means no male connectors } void ItemBase::prepareGeometryChange() { // made public so it can be invoked from outside ItemBase class //debugInfo("itembase prepare geometry change"); QGraphicsSvgItem::prepareGeometryChange(); } void ItemBase::saveLocAndTransform(QXmlStreamWriter & streamWriter) { streamWriter.writeAttribute("x", QString::number(m_viewGeometry.loc().x())); streamWriter.writeAttribute("y", QString::number(m_viewGeometry.loc().y())); GraphicsUtils::saveTransform(streamWriter, m_viewGeometry.transform()); } FSvgRenderer * ItemBase::setUpImage(ModelPart * modelPart, LayerAttributes & layerAttributes) { // at this point "this" has not yet been added to the scene, so one cannot get back to the InfoGraphicsView ModelPartShared * modelPartShared = modelPart->modelPartShared(); if (modelPartShared == NULL) { layerAttributes.error = tr("model part problem"); return NULL; } //if (modelPartShared->moduleID() == "df9d072afa2b594ac67b60b4153ff57b_29" && viewID == ViewLayer::PCBView) { // DebugDialog::debug("here i am now"); //} //DebugDialog::debug(QString("setting z %1 %2") //.arg(this->z()) //.arg(ViewLayer::viewLayerNameFromID(viewLayerID)) ); //DebugDialog::debug(QString("set up image elapsed (1) %1").arg(t.elapsed()) ); QString filename = PartFactory::getSvgFilename(modelPart, modelPartShared->imageFileName(layerAttributes.viewID, layerAttributes.viewLayerID), true, true); //#ifndef QT_NO_DEBUG //DebugDialog::debug(QString("set up image elapsed (2) %1").arg(t.elapsed()) ); //#endif if (filename.isEmpty()) { //QString deleteme = modelPartShared->domDocument()->toString(); layerAttributes.error = tr("file for %1 %2 not found").arg(modelPartShared->title()).arg(modelPartShared->moduleID()); return NULL; } LoadInfo loadInfo; switch (layerAttributes.viewID) { case ViewLayer::PCBView: loadInfo.colorElementID = ViewLayer::viewLayerXmlNameFromID(layerAttributes.viewLayerID); switch (layerAttributes.viewLayerID) { case ViewLayer::Copper0: modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs); loadInfo.setColor = ViewLayer::Copper0Color; loadInfo.findNonConnectors = loadInfo.parsePaths = true; break; case ViewLayer::Copper1: modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs); loadInfo.setColor = ViewLayer::Copper1Color; loadInfo.findNonConnectors = loadInfo.parsePaths = true; break; case ViewLayer::Silkscreen1: loadInfo.setColor = ViewLayer::Silkscreen1Color; break; case ViewLayer::Silkscreen0: loadInfo.setColor = ViewLayer::Silkscreen0Color; break; default: break; } break; case ViewLayer::BreadboardView: modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs); break; default: // don't need connectorIDs() for schematic view since these parts do not have bendable legs or connectors with drill holes break; } FSvgRenderer * newRenderer = new FSvgRenderer(); QDomDocument flipDoc; getFlipDoc(modelPart, filename, layerAttributes.viewLayerID, layerAttributes.viewLayerPlacement, flipDoc, layerAttributes.orientation); QByteArray bytesToLoad; if (layerAttributes.viewLayerID == ViewLayer::Schematic) { bytesToLoad = SvgFileSplitter::hideText(filename); } else if (layerAttributes.viewLayerID == ViewLayer::SchematicText) { bool hasText = false; bytesToLoad = SvgFileSplitter::showText(filename, hasText); if (!hasText) { return NULL; } } else if ((layerAttributes.viewID != ViewLayer::IconView) && modelPartShared->hasMultipleLayers(layerAttributes.viewID)) { QString layerName = ViewLayer::viewLayerXmlNameFromID(layerAttributes.viewLayerID); // need to treat create "virtual" svg file for each layer SvgFileSplitter svgFileSplitter; bool result; if (flipDoc.isNull()) { result = svgFileSplitter.split(filename, layerName); } else { QString f = flipDoc.toString(); result = svgFileSplitter.splitString(f, layerName); } if (result) { bytesToLoad = svgFileSplitter.byteArray(); } } else { // only one layer, just load it directly if (flipDoc.isNull()) { QFile file(filename); file.open(QFile::ReadOnly); bytesToLoad = file.readAll(); } else { bytesToLoad = flipDoc.toByteArray(); } } QByteArray resultBytes; if (!bytesToLoad.isEmpty()) { if (makeLocalModifications(bytesToLoad, filename)) { if (layerAttributes.viewLayerID == ViewLayer::Schematic) { bytesToLoad = SvgFileSplitter::hideText2(bytesToLoad); } else if (layerAttributes.viewLayerID == ViewLayer::SchematicText) { bool hasText; bytesToLoad = SvgFileSplitter::showText2(bytesToLoad, hasText); } } loadInfo.filename = filename; resultBytes = newRenderer->loadSvg(bytesToLoad, loadInfo); } layerAttributes.setLoaded(resultBytes); #ifndef QT_NO_DEBUG // DebugDialog::debug(QString("set up image elapsed (2.3) %1").arg(t.elapsed()) ); #endif if (resultBytes.isEmpty()) { delete newRenderer; layerAttributes.error = tr("unable to create renderer for svg %1").arg(filename); newRenderer = NULL; } //DebugDialog::debug(QString("set up image elapsed (3) %1").arg(t.elapsed()) ); if (newRenderer) { layerAttributes.setFilename(newRenderer->filename()); if (layerAttributes.createShape) { createShape(layerAttributes); } } return newRenderer; } void ItemBase::updateConnectionsAux(bool includeRatsnest, QList & already) { //DebugDialog::debug("update connections"); foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { updateConnections(connectorItem, includeRatsnest, already); } } void ItemBase::figureHover() { } QString ItemBase::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { Q_UNUSED(viewLayerID); Q_UNUSED(svgHash); Q_UNUSED(blackOnly); Q_UNUSED(dpi); factor = 1; return ""; } bool ItemBase::hasConnections() { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0) return true; } return false; } void ItemBase::getConnectedColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { brush = ConnectedBrush; pen = ConnectedPen; opacity = 0.2; negativePenWidth = 0; negativeOffsetRect = true; } void ItemBase::getNormalColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { brush = NormalBrush; pen = NormalPen; opacity = NormalConnectorOpacity; negativePenWidth = 0; negativeOffsetRect = true; } void ItemBase::getUnconnectedColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { brush = UnconnectedBrush; pen = UnconnectedPen; opacity = 0.3; negativePenWidth = 0; negativeOffsetRect = true; } void ItemBase::getHoverColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { brush = HoverBrush; pen = HoverPen; opacity = NormalConnectorOpacity; negativePenWidth = 0; negativeOffsetRect = true; } void ItemBase::getEqualPotentialColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { brush = EqualPotentialBrush; pen = EqualPotentialPen; opacity = 1.0; negativePenWidth = 0; negativeOffsetRect = true; } void ItemBase::slamZ(double newZ) { double z = qFloor(m_viewGeometry.z()) + newZ; m_viewGeometry.setZ(z); setZValue(z); } bool ItemBase::isEverVisible() { return m_everVisible; } void ItemBase::setEverVisible(bool v) { m_everVisible = v; } bool ItemBase::connectionIsAllowed(ConnectorItem * other) { return ViewLayer::canConnect(this->viewLayerID(), other->attachedToViewLayerID()); } QString ItemBase::getProperty(const QString & key) { if (m_modelPart == NULL) return ""; QString result = m_modelPart->localProp(key).toString(); if (!result.isEmpty()) return result; return m_modelPart->properties().value(key, ""); } ConnectorItem * ItemBase::rightClickedConnector() { return m_rightClickedConnector; } QColor ItemBase::connectedColor() { return ConnectedPen.color(); } QColor ItemBase::unconnectedColor() { return UnconnectedPen.color(); } QColor ItemBase::standardConnectedColor() { return StandardConnectedColor; } QColor ItemBase::standardUnconnectedColor() { return StandardUnconnectedColor; } void ItemBase::setConnectedColor(QColor & c) { ConnectedPen.setColor(c); ConnectedBrush.setColor(c); } void ItemBase::setUnconnectedColor(QColor & c) { UnconnectedPen.setColor(c); UnconnectedBrush.setColor(c); } QString ItemBase::translatePropertyName(const QString & key) { return TranslatedPropertyNames.value(key.toLower(), key); } bool ItemBase::canEditPart() { return false; } bool ItemBase::hasCustomSVG() { return false; } void ItemBase::setProp(const QString & prop, const QString & value) { if (!m_modelPart) return; //DebugDialog::debug(QString("setting prop %1 %2").arg(prop).arg(value)); m_modelPart->setLocalProp(prop, value); } QString ItemBase::prop(const QString & p) { if (m_modelPart == NULL) return ""; return m_modelPart->localProp(p).toString(); } bool ItemBase::isObsolete() { if (modelPart() == NULL) return false; return modelPart()->isObsolete(); } bool ItemBase::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { Q_UNUSED(hide); // assume this is set by the caller (HtmlInfoView) returnWidget = NULL; returnProp = ItemBase::translatePropertyName(prop); returnValue = value; if (prop.compare("family", Qt::CaseInsensitive) == 0) { return true; } if (prop.compare("id", Qt::CaseInsensitive) == 0) { return true; } #ifndef QT_NO_DEBUG if (prop.compare("svg", Qt::CaseInsensitive) == 0 || prop.compare("fzp" , Qt::CaseInsensitive) == 0) { QFileInfo fileInfo(value); if (fileInfo.exists()) { ClickableLabel * label = new ClickableLabel(fileInfo.fileName(), parent); label->setProperty("path", value); label->setToolTip(value); connect(label, SIGNAL(clicked()), this, SLOT(showInFolder())); returnWidget = label; } return true; } #endif QString tempValue = value; QStringList values = collectValues(family, prop, tempValue); if (values.count() > 1) { FamilyPropertyComboBox * comboBox = new FamilyPropertyComboBox(family, prop, parent); comboBox->setObjectName("infoViewComboBox"); comboBox->addItems(values); comboBox->setCurrentIndex(comboBox->findText(tempValue)); comboBox->setEnabled(swappingEnabled); comboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(swapEntry(const QString &))); returnWidget = comboBox; m_propsMap.insert(prop, tempValue); return true; } return true; } void ItemBase::swapEntry(const QString & text) { FamilyPropertyComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; m_propsMap.insert(comboBox->prop(), text); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->swap(comboBox->family(), comboBox->prop(), m_propsMap, this); } } void ItemBase::setReferenceModel(ReferenceModel * rm) { TheReferenceModel = rm; } QStringList ItemBase::collectValues(const QString & family, const QString & prop, QString & value) { Q_UNUSED(value); if (TheReferenceModel == NULL) return ___emptyStringList___; QStringList values = CachedValues.value(family + prop, QStringList()); if (values.count() > 0) return values; values = TheReferenceModel->propValues(family, prop, true); // sort values numerically NumberMatcherValues.clear(); bool ok = true; foreach(QString opt, values) { int ix = NumberMatcher.indexIn(opt); if (ix < 0) { ok = false; break; } double n = TextUtils::convertFromPowerPrefix(NumberMatcher.cap(1) + NumberMatcher.cap(5), ""); NumberMatcherValues.insert(opt, n); } if (ok) { qSort(values.begin(), values.end(), numberValueLessThan); } CachedValues.insert(family + prop, values); //debugInfo("cached " + prop); //foreach(QString v, values) { // DebugDialog::debug("\t" + v); //} return values; } void ItemBase::resetValues(const QString & family, const QString & prop) { CachedValues.remove(family + prop); } bool ItemBase::hasPartLabel() { return true; } const QString & ItemBase::filename() { return m_filename; } void ItemBase::setFilename(const QString & fn) { m_filename = fn; } ItemBase::PluralType ItemBase::isPlural() { return ItemBase::NotSure; } ViewLayer::ViewLayerPlacement ItemBase::viewLayerPlacement() const { return m_viewLayerPlacement; } void ItemBase::setViewLayerPlacement(ViewLayer::ViewLayerPlacement viewLayerPlacement) { m_viewLayerPlacement = viewLayerPlacement; } ViewLayer::ViewLayerID ItemBase::partLabelViewLayerID() { if (m_partLabel == NULL) return ViewLayer::UnknownLayer; if (!m_partLabel->initialized()) return ViewLayer::UnknownLayer; return m_partLabel->viewLayerID(); } QString ItemBase::makePartLabelSvg(bool blackOnly, double dpi, double printerScale) { if (m_partLabel == NULL) return ""; if (!m_partLabel->initialized()) return ""; return m_partLabel->makeSvg(blackOnly, dpi, printerScale, true); } QPointF ItemBase::partLabelScenePos() { if (m_partLabel == NULL) return QPointF(); if (!m_partLabel->initialized()) return QPointF(); return m_partLabel->scenePos(); } QRectF ItemBase::partLabelSceneBoundingRect() { if (m_partLabel == NULL) return QRectF(); if (!m_partLabel->initialized()) return QRectF(); return m_partLabel->sceneBoundingRect(); } bool ItemBase::getFlipDoc(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QDomDocument & flipDoc, Qt::Orientations orientation) { if (!modelPart->flippedSMD()) { // add copper1 layer to THT if it is missing fixCopper1(modelPart, filename, viewLayerID, viewLayerPlacement, flipDoc); } if (viewLayerPlacement == ViewLayer::NewBottom) { if (modelPart->flippedSMD()) { if (viewLayerID == ViewLayer::Copper0) { SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), GraphicsUtils::SVGDPI, orientation); return true; } else if (viewLayerID == ViewLayer::Silkscreen0) { SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0), GraphicsUtils::SVGDPI, orientation); return true; } return false; } if (modelPart->itemType() == ModelPart::Part) { if (viewLayerID == ViewLayer::Copper0) { SvgFlattener::replaceElementID(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), ""); //QString t1 = flipDoc.toString(); SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), GraphicsUtils::SVGDPI, orientation); //QString t2 = flipDoc.toString(); return true; } if (viewLayerID == ViewLayer::Copper1) { SvgFlattener::replaceElementID(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ""); //QString t1 = flipDoc.toString(); SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), GraphicsUtils::SVGDPI, orientation); //QString t2 = flipDoc.toString(); return true; } else if (viewLayerID == ViewLayer::Silkscreen0) { SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0), GraphicsUtils::SVGDPI, orientation); return true; } } } return false; } bool ItemBase::fixCopper1(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QDomDocument & doc) { Q_UNUSED(viewLayerPlacement); if (viewLayerID != ViewLayer::Copper1) return false; if (!modelPart->needsCopper1()) return false; return TextUtils::addCopper1(filename, doc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1)); } void ItemBase::calcRotation(QTransform & rotation, QPointF center, ViewGeometry & vg2) { vg2.setLoc(GraphicsUtils::calcRotation(rotation, center, pos(), boundingRectWithoutLegs().center())); } void ItemBase::updateConnectors() { if (!isEverVisible()) return; QList visited; foreach(ConnectorItem * connectorItem, cachedConnectorItems()) { connectorItem->restoreColor(visited); } //DebugDialog::debug(QString("set up connectors restore:%1").arg(count)); } const QString & ItemBase::moduleID() { if (m_modelPart) return m_modelPart->moduleID(); return ___emptyString___; } bool ItemBase::moveLock() { return m_moveLock; } void ItemBase::setMoveLock(bool moveLock) { m_moveLock = moveLock; if (moveLock) { if (m_moveLockItem == NULL) { if (!MoveLockRenderer.isValid()) { QString fn(":resources/images/part_lock.svg"); bool success = MoveLockRenderer.load(fn); DebugDialog::debug(QString("movelock load success %1").arg(success)); } m_moveLockItem = new QGraphicsSvgItem(); m_moveLockItem->setAcceptHoverEvents(false); m_moveLockItem->setAcceptedMouseButtons(Qt::NoButton); m_moveLockItem->setSharedRenderer(&MoveLockRenderer); m_moveLockItem->setPos(0,0); m_moveLockItem->setZValue(-99999); m_moveLockItem->setParentItem(this); m_moveLockItem->setVisible(true); } } else { if (m_moveLockItem) { delete m_moveLockItem; m_moveLockItem = NULL; } } if (m_stickyItem) { m_stickyItem->setPos(m_moveLockItem == NULL ? 0 : m_moveLockItem->boundingRect().width() + 1, 0); } update(); } void ItemBase::debugInfo(const QString & msg) const { #ifndef QT_NO_DEBUG debugInfo2(msg); #else Q_UNUSED(msg); #endif } void ItemBase::debugInfo2(const QString & msg) const { DebugDialog::debug(QString("%1 ti:'%2' id:%3 it:'%4' vid:%9 vlid:%5 spec:%6 x:%11 y:%12 z:%10 flg:%7 gi:%8") .arg(msg) .arg(this->constTitle()) .arg(this->id()) .arg(this->instanceTitle()) .arg(this->viewLayerID()) .arg(this->viewLayerPlacement()) .arg(this->wireFlags()) .arg((long) dynamic_cast(this), 0, 16) .arg(m_viewID) .arg(this->zValue()) .arg(this->pos().x()) .arg(this->pos().y()) ); /* foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem) connectorItem->debugInfo("\t"); } */ } void ItemBase::addedToScene(bool temporary) { if (this->scene() && instanceTitle().isEmpty() && !temporary) { setTooltip(); if (isBaseSticky() && isLocalSticky()) { // ensure icon is visible setLocalSticky(true); } } } bool ItemBase::hasPartNumberProperty() { return true; } void ItemBase::collectPropsMap(QString & family, QMap & propsMap) { QHash properties; properties = m_modelPart->properties(); family = properties.value("family", ""); foreach (QString key, properties.keys()) { if (key.compare("family") == 0) continue; if (key.compare("id") == 0) continue; QString value = properties.value(key,""); QString tempValue = value; QStringList values = collectValues(family, key, tempValue); propsMap.insert(key, tempValue); DebugDialog::debug(QString("props map %1 %2").arg(key).arg(tempValue)); } } void ItemBase::setDropOffset(QPointF) { } bool ItemBase::hasRubberBandLeg() const { return m_hasRubberBandLeg; } bool ItemBase::sceneEvent(QEvent *event) { return QGraphicsSvgItem::sceneEvent(event); } const QList & ItemBase::cachedConnectorItems() { if (m_cachedConnectorItems.isEmpty()) { foreach (QGraphicsItem * childItem, childItems()) { ConnectorItem * connectorItem = dynamic_cast(childItem); if (connectorItem != NULL) m_cachedConnectorItems.append(connectorItem); } } return m_cachedConnectorItems; } const QList & ItemBase::cachedConnectorItemsConst() const { return m_cachedConnectorItems; } void ItemBase::clearConnectorItemCache() { m_cachedConnectorItems.clear(); } void ItemBase::killRubberBandLeg() { if (!hasRubberBandLeg()) return; prepareGeometryChange(); foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { connectorItem->killRubberBandLeg(); } } ViewGeometry::WireFlags ItemBase::wireFlags() const { return m_viewGeometry.wireFlags(); } QRectF ItemBase::boundingRectWithoutLegs() const { return boundingRect(); } QRectF ItemBase::boundingRect() const { FSvgRenderer * frenderer = fsvgRenderer(); if (frenderer == NULL) { return QGraphicsSvgItem::boundingRect(); } QSizeF s = frenderer->defaultSizeF(); QRectF r(0,0, s.width(), s.height()); return r; } QPainterPath ItemBase::hoverShape() const { return shape(); } const QCursor * ItemBase::getCursor(Qt::KeyboardModifiers) { return CursorMaster::MoveCursor; } PartLabel * ItemBase::partLabel() { return m_partLabel; } void ItemBase::doneLoading() { } QString ItemBase::family() { return modelPart()->family(); } QPixmap * ItemBase::getPixmap(QSize size) { return FSvgRenderer::getPixmap(renderer(), size); } FSvgRenderer * ItemBase::fsvgRenderer() const { if (m_fsvgRenderer) return m_fsvgRenderer; FSvgRenderer * f = qobject_cast(renderer()); if (f == NULL) { DebugDialog::debug("shouldn't happen: missing fsvgRenderer"); } return f; } void ItemBase::setSharedRendererEx(FSvgRenderer * newRenderer) { if (newRenderer != m_fsvgRenderer) { setSharedRenderer(newRenderer); // original renderer is deleted if it is not shared if (m_fsvgRenderer) delete m_fsvgRenderer; m_fsvgRenderer = newRenderer; } else { update(); } m_size = newRenderer->defaultSizeF(); //debugInfo(QString("set size %1, %2").arg(m_size.width()).arg(m_size.height())); } bool ItemBase::reloadRenderer(const QString & svg, bool fastLoad) { if (!svg.isEmpty()) { //DebugDialog::debug(svg); prepareGeometryChange(); bool result = fastLoad ? fsvgRenderer()->fastLoad(svg.toUtf8()) : fsvgRenderer()->loadSvgString(svg.toUtf8()); if (result) { update(); } return result; } return false; } bool ItemBase::resetRenderer(const QString & svg) { // use resetRenderer instead of reloadRender because if the svg size changes, with reloadRenderer the new image seems to be scaled to the old bounds // what I don't understand is why the old renderer causes a crash if it is deleted here QString nothing; return resetRenderer(svg, nothing); } bool ItemBase::resetRenderer(const QString & svg, QString & newSvg) { // use resetRenderer instead of reloadRender because if the svg size changes, with reloadRenderer the new image seems to be scaled to the old bounds // what I don't understand is why the old renderer causes a crash if it is deleted here FSvgRenderer * newRenderer = new FSvgRenderer(); bool result = newRenderer->loadSvgString(svg, newSvg); if (result) { //DebugDialog::debug("reloaded"); //DebugDialog::debug(newSvg); setSharedRendererEx(newRenderer); } else { delete newRenderer; } return result; } void ItemBase::getPixmaps(QPixmap * & pixmap1, QPixmap * & pixmap2, QPixmap * & pixmap3, bool swappingEnabled, QSize size) { pixmap1 = getPixmap(ViewLayer::BreadboardView, swappingEnabled, size); pixmap2 = getPixmap(ViewLayer::SchematicView, swappingEnabled, size); pixmap3 = getPixmap(ViewLayer::PCBView, swappingEnabled, size); } QPixmap * ItemBase::getPixmap(ViewLayer::ViewID vid, bool swappingEnabled, QSize size) { ItemBase * vItemBase = NULL; if (viewID() == vid) { if (!isEverVisible()) return NULL; } else { vItemBase = modelPart()->viewItem(vid); if (vItemBase && !vItemBase->isEverVisible()) return NULL; } vid = useViewIDForPixmap(vid, swappingEnabled); if (vid == ViewLayer::UnknownView) return NULL; if (viewID() == vid) { return getPixmap(size); } if (vItemBase) { return vItemBase->getPixmap(size); } if (!modelPart()->hasViewFor(vid)) return NULL; QString baseName = modelPart()->hasBaseNameFor(vid); if (baseName.isEmpty()) return NULL; QString filename = PartFactory::getSvgFilename(modelPart(), baseName, true, true); if (filename.isEmpty()) { return NULL; } QSvgRenderer renderer(filename); QPixmap * pixmap = new QPixmap(size); pixmap->fill(Qt::transparent); QPainter painter(pixmap); // preserve aspect ratio QSize def = renderer.defaultSize(); double newW = size.width(); double newH = newW * def.height() / def.width(); if (newH > size.height()) { newH = size.height(); newW = newH * def.width() / def.height(); } QRectF bounds((size.width() - newW) / 2.0, (size.height() - newH) / 2.0, newW, newH); renderer.render(&painter, bounds); painter.end(); return pixmap; } ViewLayer::ViewID ItemBase::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::BreadboardView) { return ViewLayer::IconView; } return vid; } bool ItemBase::makeLocalModifications(QByteArray &, const QString & ) { // a bottleneck for modifying part svg xml at setupImage time return false; } void ItemBase::showConnectors(const QStringList & connectorIDs) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorIDs.contains(connectorItem->connectorSharedID())) { connectorItem->setVisible(true); } } } void ItemBase::setItemIsSelectable(bool selectable) { setFlag(QGraphicsItem::ItemIsSelectable, selectable); } bool ItemBase::inRotation() { return m_inRotation; } void ItemBase::setInRotation(bool val) { m_inRotation = val; } void ItemBase::addSubpart(ItemBase * sub) { this->debugInfo("super"); sub->debugInfo("\t"); m_subparts.append(sub); sub->setSuperpart(this); foreach (ConnectorItem * connectorItem, sub->cachedConnectorItems()) { Bus * subbus = connectorItem->bus(); Connector * subconnector = NULL; if (subbus == NULL) { subconnector = connectorItem->connector(); if (subconnector) { subbus = new Bus(NULL, NULL); subconnector->setBus(subbus); } } Connector * connector = modelPart()->getConnector(connectorItem->connectorSharedID()); if (connector) { if (subbus) subbus->addSubConnector(connector); if (subconnector) { Bus * bus = connector->bus(); if (bus == NULL) { bus = new Bus(NULL, NULL); connector->setBus(bus); } bus->addSubConnector(subconnector); } } } } void ItemBase::setSuperpart(ItemBase * super) { m_superpart = super; } ItemBase * ItemBase::superpart() { return m_superpart; } ItemBase * ItemBase::findSubpart(const QString & connectorID, ViewLayer::ViewLayerPlacement spec) { foreach (ItemBase * itemBase, m_subparts) { ConnectorItem * connectorItem = itemBase->findConnectorItemWithSharedID(connectorID, spec); if (connectorItem) return itemBase; } return NULL; } const QList< QPointer > & ItemBase::subparts() { return m_subparts; } QHash ItemBase::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys) { m_propsMap.clear(); // TODO: someday get local props QHash props = modelPart->properties(); QString family = props.value("family", "").toLower(); // ensure family is first; keys = props.keys(); keys.removeOne("family"); keys.push_front("family"); // ensure part number is last QString partNumber = props.value(ModelPartShared::PartNumberPropertyName, "").toLower(); keys.removeOne(ModelPartShared::PartNumberPropertyName); if (wantDebug) { props.insert("id", QString("%1 %2 %3") .arg(QString::number(id())) .arg(modelPart->moduleID()) .arg(ViewLayer::viewLayerNameFromID(viewLayerID())) ); keys.insert(1, "id"); int insertAt = 2; PaletteItemBase * paletteItemBase = qobject_cast(this); if (paletteItemBase != NULL) { props.insert("svg", paletteItemBase->filename()); keys.insert(insertAt++, "svg"); } props.insert("class", this->metaObject()->className()); keys.insert(insertAt++, "class"); if (modelPart->modelPartShared()) { props.insert("fzp", modelPart->path()); keys.insert(insertAt++, "fzp"); } } // ensure part number is last if (hasPartNumberProperty()) { keys.append(ModelPartShared::PartNumberPropertyName); } return props; } void ItemBase::setSquashShape(bool squashShape) { m_squashShape = squashShape; } void ItemBase::createShape(LayerAttributes & layerAttributes) { switch (layerAttributes.viewID) { case ViewLayer::SchematicView: case ViewLayer::PCBView: break; default: return; } if (!isEverVisible()) return; QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(layerAttributes.loaded(), &errorStr, &errorLine, &errorColumn)) { return; } QDomElement root = doc.documentElement(); QRectF viewBox; double w, h; TextUtils::ensureViewBox(doc, 1, viewBox, true, w, h, true); double svgDPI = viewBox.width() / w; int selectionExtra = layerAttributes.viewID == ViewLayer::SchematicView ? 20 : 10; SvgFileSplitter::forceStrokeWidth(root, svgDPI * selectionExtra / GraphicsUtils::SVGDPI, "#000000", true, false); double imageDPI = GraphicsUtils::SVGDPI; QRectF sourceRes(0, 0, w * imageDPI, h * imageDPI); QSize imgSize(qCeil(sourceRes.width()), qCeil(sourceRes.height())); QImage image(imgSize, QImage::Format_Mono); image.fill(0xffffffff); renderOne(&doc, &image, sourceRes); QBitmap bitmap = QBitmap::fromImage(image); QRegion region(bitmap); m_selectionShape.addRegion(region); #ifndef QT_NODEBUG //QFileInfo info(layerAttributes.filename()); //bitmap.save(FolderUtils::getUserDataStorePath("") + "/bitmap." + info.completeBaseName() + "." + QString::number(layerAttributes.viewLayerID) + ".png"); //image.save(FolderUtils::getUserDataStorePath("") + "/image." + info.completeBaseName() + "." + QString::number(layerAttributes.viewLayerID) + ".png"); #endif } const QPainterPath & ItemBase::selectionShape() { return m_selectionShape; } void ItemBase::setTransform2(const QTransform & transform) { setTransform(transform); } void ItemBase::renderOne(QDomDocument * masterDoc, QImage * image, const QRectF & renderRect) { QByteArray byteArray = masterDoc->toByteArray(); QSvgRenderer renderer(byteArray); QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); renderer.render(&painter, renderRect); painter.end(); } void ItemBase::initLayerAttributes(LayerAttributes & layerAttributes, ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool doConnectors, bool doCreateShape) { layerAttributes.viewID = viewID; layerAttributes.viewLayerID = viewLayerID; layerAttributes.viewLayerPlacement = viewLayerPlacement; layerAttributes.doConnectors = doConnectors; layerAttributes.createShape = doCreateShape; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { layerAttributes.orientation = infoGraphicsView->smdOrientation(); } } void ItemBase::showInFolder() { QString path = sender()->property("path").toString(); if (!path.isEmpty()) { FolderUtils::showInFolder(path); QClipboard *clipboard = QApplication::clipboard(); if (clipboard != NULL) { clipboard->setText(path); } } } QString ItemBase::getInspectorTitle() { QString t = instanceTitle(); if (!t.isEmpty()) return t; return title(); } void ItemBase::setInspectorTitle(const QString & oldText, const QString & newText) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; DebugDialog::debug(QString("set instance title to %1").arg(newText)); infoGraphicsView->setInstanceTitle(id(), oldText, newText, true, false); } fritzing-app-0.9.2b/src/items/itembase.h000066400000000000000000000417061250202676700201670ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Licensetriple along with Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef ITEMBASE_H #define ITEMBASE_H #include #include #include #include #include #include #include #include #include #include #include #include #include "../viewgeometry.h" #include "../viewlayer.h" #include "../utils/misc.h" class ConnectorItem; typedef QMultiHash ConnectorPairHash; typedef bool (*SkipCheckFunction)(ConnectorItem *); class ItemBase : public QGraphicsSvgItem { Q_OBJECT public: enum PluralType { Singular, Plural, NotSure }; public: ItemBase(class ModelPart*, ViewLayer::ViewID, const ViewGeometry &, long id, QMenu * itemMenu); virtual ~ItemBase(); qint64 id() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); double z(); virtual void saveGeometry() = 0; ViewGeometry & getViewGeometry(); ViewGeometry::WireFlags wireFlags() const; virtual bool itemMoved() = 0; QSizeF size(); class ModelPart * modelPart(); void setModelPart(class ModelPart *); class ModelPartShared * modelPartShared(); virtual void writeXml(QXmlStreamWriter &) {} virtual void saveInstance(QXmlStreamWriter &); virtual void saveInstanceLocation(QXmlStreamWriter &) = 0; virtual void writeGeometry(QXmlStreamWriter &); virtual void moveItem(ViewGeometry &) = 0; virtual void setItemPos(QPointF & pos); virtual void rotateItem(double degrees, bool includeRatsnest); virtual void flipItem(Qt::Orientations orientation); virtual void transformItem(const QTransform &, bool includeRatsnest); virtual void transformItem2(const QMatrix &); virtual void removeLayerKin(); ViewLayer::ViewID viewID(); QString & viewIDName(); ViewLayer::ViewLayerID viewLayerID() const; void setViewLayerID(ViewLayer::ViewLayerID, const LayerHash & viewLayers); void setViewLayerID(const QString & layerName, const LayerHash & viewLayers); bool topLevel(); void collectConnectors(ConnectorPairHash & connectorHash, SkipCheckFunction); virtual void busConnectorItems(class Bus * bus, ConnectorItem *, QList & items); virtual void setHidden(bool hidden); virtual void setLayerHidden(bool hidden); bool hidden(); bool layerHidden(); virtual void setInactive(bool inactivate); bool inactive(); ConnectorItem * findConnectorItemWithSharedID(const QString & connectorID, ViewLayer::ViewLayerPlacement); ConnectorItem * findConnectorItemWithSharedID(const QString & connectorID); void updateConnections(ConnectorItem *, bool includeRatsnest, QList & already); virtual void updateConnections(bool includeRatsnest, QList & already); virtual const QString & title(); const QString & constTitle() const; bool getRatsnest(); QList buses(); int itemType() const; // wanted this to return ModelPart::ItemType but couldn't figure out how to get it to compile virtual bool isSticky(); virtual bool isBaseSticky(); virtual void setSticky(bool); void setLocalSticky(bool); bool isLocalSticky(); virtual void addSticky(ItemBase *, bool stickem); virtual ItemBase * stickingTo(); virtual QList< QPointer > stickyList(); virtual bool alreadySticking(ItemBase * itemBase); virtual bool stickyEnabled(); ConnectorItem * anyConnectorItem(); const QString & instanceTitle() const; QString label(); virtual void updateTooltip(); void setTooltip(); void removeTooltip(); bool hasConnectors(); bool hasNonConnectors(); bool hasConnections(); bool canFlip(Qt::Orientations); bool canFlipHorizontal(); void setCanFlipHorizontal(bool); bool canFlipVertical(); void setCanFlipVertical(bool); virtual void clearModelPart(); virtual bool hasPartLabel(); ViewLayer::ViewLayerID partLabelViewLayerID(); void clearPartLabel(); bool isPartLabelVisible(); void restorePartLabel(QDomElement & labelGeometry, ViewLayer::ViewLayerID); // on loading from a file void movePartLabel(QPointF newPos, QPointF newOffset); // coming down from the command object void partLabelMoved(QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset); // coming up from the label void partLabelSetHidden(bool hide); void rotateFlipPartLabel(double degrees, Qt::Orientations); // coming up from the label void doRotateFlipPartLabel(double degrees, Qt::Orientations); // coming down from the command object QString makePartLabelSvg(bool blackOnly, double dpi, double printerScale); QPointF partLabelScenePos(); QRectF partLabelSceneBoundingRect(); virtual bool isSwappable(); virtual void setSwappable(bool); void mousePressEvent(QGraphicsSceneMouseEvent *event); virtual void collectWireConnectees(QSet & wires); virtual bool collectFemaleConnectees(QSet & items); void prepareGeometryChange(); virtual void resetID(); void updateConnectionsAux(bool includeRatsnest, QList & already); void hoverEnterEvent( QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); virtual void figureHover(); virtual QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); virtual void slamZ(double newZ); bool isEverVisible(); void setEverVisible(bool); virtual bool connectionIsAllowed(ConnectorItem *); virtual bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); virtual QString getProperty(const QString & key); ConnectorItem * rightClickedConnector(); virtual bool canEditPart(); virtual bool hasCustomSVG(); virtual void setProp(const QString & prop, const QString & value); QString prop(const QString & p); bool isObsolete(); virtual QHash prepareProps(ModelPart *, bool wantDebug, QStringList & keys); void resetValues(const QString & family, const QString & prop); const QString & filename(); void setFilename(const QString &); virtual PluralType isPlural(); ViewLayer::ViewLayerPlacement viewLayerPlacement() const; void setViewLayerPlacement(ViewLayer::ViewLayerPlacement); virtual void calcRotation(QTransform & rotation, QPointF center, ViewGeometry &); void updateConnectors(); const QString & moduleID(); bool moveLock(); virtual void setMoveLock(bool); void debugInfo(const QString & msg) const; void debugInfo2(const QString & msg) const; virtual void addedToScene(bool temporary); virtual bool hasPartNumberProperty(); void collectPropsMap(QString & family, QMap &); virtual bool rotationAllowed(); virtual bool rotation45Allowed(); virtual bool freeRotationAllowed(); void ensureUniqueTitle(const QString &title, bool force); virtual void setDropOffset(QPointF offset); bool hasRubberBandLeg() const; void killRubberBandLeg(); bool sceneEvent(QEvent *event); void clearConnectorItemCache(); const QList & cachedConnectorItems(); const QList & cachedConnectorItemsConst() const; bool inHover(); virtual QRectF boundingRectWithoutLegs() const; QRectF boundingRect() const; virtual QPainterPath hoverShape() const; virtual const QCursor * getCursor(Qt::KeyboardModifiers); class PartLabel * partLabel(); virtual void doneLoading(); QString family(); QPixmap * getPixmap(QSize size); class FSvgRenderer * fsvgRenderer() const; void setSharedRendererEx(class FSvgRenderer *); bool reloadRenderer(const QString & svg, bool fastload); bool resetRenderer(const QString & svg); bool resetRenderer(const QString & svg, QString & newSvg); void getPixmaps(QPixmap * &, QPixmap * &, QPixmap * &, bool swappingEnabled, QSize); class FSvgRenderer * setUpImage(class ModelPart * modelPart, class LayerAttributes &); void showConnectors(const QStringList &); void setItemIsSelectable(bool selectable); virtual bool inRotation(); virtual void setInRotation(bool); const QString & spice() const; const QString & spiceModel() const; void addSubpart(ItemBase *); void setSuperpart(ItemBase *); ItemBase * superpart(); ItemBase * findSubpart(const QString & connectorID, ViewLayer::ViewLayerPlacement); const QList< QPointer > & subparts(); void setSquashShape(bool); const QPainterPath & selectionShape(); virtual void setTransform2(const QTransform &); void initLayerAttributes(LayerAttributes & layerAttributes, ViewLayer::ViewID, ViewLayer::ViewLayerID, ViewLayer::ViewLayerPlacement, bool doConnectors, bool doCreateShape); virtual QString getInspectorTitle(); virtual void setInspectorTitle(const QString & oldText, const QString & newText); public: virtual void getConnectedColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); virtual void getUnconnectedColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); virtual void getNormalColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); virtual void getHoverColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); virtual void getEqualPotentialColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); protected: static QPen NormalPen; static QPen HoverPen; static QPen ConnectedPen; static QPen UnconnectedPen; static QPen ChosenPen; static QPen EqualPotentialPen; static QBrush HoverBrush; static QBrush NormalBrush; static QBrush ConnectedBrush; static QBrush UnconnectedBrush; static QBrush ChosenBrush; static QBrush EqualPotentialBrush; static const double NormalConnectorOpacity; public: static QColor connectedColor(); static QColor unconnectedColor(); static QColor standardConnectedColor(); static QColor standardUnconnectedColor(); static void setConnectedColor(QColor &); static void setUnconnectedColor(QColor &); public: virtual void hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item); virtual void hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item); virtual void hoverMoveConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); void hoverEnterConnectorItem(); void hoverLeaveConnectorItem(); virtual void connectorHover(ConnectorItem *, ItemBase *, bool hovering); virtual void clearConnectorHover(); virtual void hoverUpdate(); virtual bool filterMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void mouseDoubleClickConnectorEvent(ConnectorItem *); virtual void mouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void mouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual bool acceptsMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual bool acceptsMousePressLegEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void setAcceptsMousePressLegEvent(bool); virtual bool acceptsMouseDoubleClickConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual bool acceptsMouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual bool acceptsMouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect); virtual void connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already); virtual ItemBase * layerKinChief(); virtual const QList & layerKin(); virtual void findConnectorsUnder() = 0; virtual ConnectorItem* newConnectorItem(class Connector *connector); virtual ConnectorItem* newConnectorItem(ItemBase * layerkin, Connector *connector); virtual void setInstanceTitle(const QString &title, bool initial); void updatePartLabelInstanceTitle(); public slots: void showPartLabel(bool show, ViewLayer *); void hidePartLabel(); void partLabelChanged(const QString &newText); virtual void swapEntry(const QString & text); void showInFolder(); public: static bool zLessThan(ItemBase * & p1, ItemBase * & p2); static qint64 getNextID(); static qint64 getNextID(qint64 fromIndex); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event ); virtual void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, const QPainterPath & shape); virtual void paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void paintBody(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value); virtual QStringList collectValues(const QString & family, const QString & prop, QString & value); void setInstanceTitleTooltip(const QString& text); virtual void setDefaultTooltip(); void setInstanceTitleAux(const QString & title, bool initial); void saveLocAndTransform(QXmlStreamWriter & streamWriter); QPixmap * getPixmap(ViewLayer::ViewID, bool swappingEnabled, QSize size); virtual ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); virtual bool makeLocalModifications(QByteArray & svg, const QString & filename); void updateHidden(); void createShape(LayerAttributes & layerAttributes); protected: static bool getFlipDoc(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement, QDomDocument &, Qt::Orientations); static bool fixCopper1(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement, QDomDocument &); protected: QSizeF m_size; qint64 m_id; ViewGeometry m_viewGeometry; QPointer m_modelPart; ViewLayer::ViewID m_viewID; ViewLayer::ViewLayerID m_viewLayerID; int m_connectorHoverCount; int m_connectorHoverCount2; int m_hoverCount; bool m_hidden; bool m_layerHidden; bool m_inactive; bool m_sticky; QHash< long, QPointer > m_stickyList; QMenu *m_itemMenu; bool m_canFlipHorizontal; bool m_canFlipVertical; bool m_zUninitialized; QPointer m_partLabel; bool m_spaceBarWasPressed; bool m_hoverEnterSpaceBarWasPressed; bool m_everVisible; ConnectorItem * m_rightClickedConnector; QMap m_propsMap; QString m_filename; ViewLayer::ViewLayerPlacement m_viewLayerPlacement; bool m_moveLock; bool m_hasRubberBandLeg; QList m_cachedConnectorItems; QGraphicsSvgItem * m_moveLockItem; QGraphicsSvgItem * m_stickyItem; FSvgRenderer * m_fsvgRenderer; bool m_acceptsMousePressLegEvent; bool m_swappable; bool m_inRotation; QPointer m_superpart; QList< QPointer > m_subparts; bool m_squashShape; QPainterPath m_selectionShape; protected: static long nextID; static QPointer TheReferenceModel; public: static const QString ITEMBASE_FONT_PREFIX; static const QString ITEMBASE_FONT_SUFFIX; static QHash TranslatedPropertyNames; static QString PartInstanceDefaultTitle; static const QList EmptyList; const static QColor HoverColor; const static double HoverOpacity; const static QColor ConnectorHoverColor; const static double ConnectorHoverOpacity; public: static void initNames(); static void cleanup(); static ItemBase * extractTopLevelItemBase(QGraphicsItem * thing); static QString translatePropertyName(const QString & key); static void setReferenceModel(class ReferenceModel *); static void renderOne(QDomDocument *, QImage *, const QRectF & renderRect); }; Q_DECLARE_METATYPE( ItemBase* ); // so we can stash them in a QVariant #endif fritzing-app-0.9.2b/src/items/jumperitem.cpp000066400000000000000000000416201250202676700211050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "jumperitem.h" #include "../connectors/connectoritem.h" #include "../fsvgrenderer.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include "../svg/svgfilesplitter.h" #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../layerattributes.h" static QString Copper0LayerTemplate = ""; static QString JumperWireLayerTemplate = ""; static const QString ShadowColor ="#1b5bb3"; static const QString JumperColor = "#418dd9"; static QHash Colors; QString makeWireImage(double w, double h, double r0x, double r0y, double r1x, double r1y, const QString & layerName, const QString & color, double thickness) { return JumperWireLayerTemplate .arg(w).arg(h) .arg(w * 1000).arg(h * 1000) .arg(r0x).arg(r0y).arg(r1x).arg(r1y) .arg(layerName) .arg(color) .arg(thickness); } void shorten(QRectF r0, QPointF r0c, QPointF r1c, double & r0x, double & r0y, double & r1x, double & r1y) { double radius = r0.width() / 2.0; GraphicsUtils::shortenLine(r0c, r1c, radius, radius); r0x = GraphicsUtils::pixels2mils(r0c.x(), GraphicsUtils::SVGDPI); r0y = GraphicsUtils::pixels2mils(r0c.y(), GraphicsUtils::SVGDPI); r1x = GraphicsUtils::pixels2mils(r1c.x(), GraphicsUtils::SVGDPI); r1y = GraphicsUtils::pixels2mils(r1c.y(), GraphicsUtils::SVGDPI); } // TODO: // ignore during autoroute? // ignore during other connections? // don't let footprints overlap during dragging ///////////////////////////////////////////////////////// JumperItem::JumperItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_originalClickItem = NULL; if (Colors.isEmpty()) { Colors.insert(ViewLayer::Copper0, ViewLayer::Copper0Color); Colors.insert(ViewLayer::Copper1, ViewLayer::Copper1Color); Colors.insert(ViewLayer::PartImage, JumperColor); Colors.insert(ViewLayer::Silkscreen1, ViewLayer::Silkscreen1Color); } m_otherItem = m_connector0 = m_connector1 = m_dragItem = NULL; if (Copper0LayerTemplate.isEmpty()) { QFile file(":/resources/templates/jumper_copper0LayerTemplate.txt"); if (file.open(QFile::ReadOnly)) { Copper0LayerTemplate = file.readAll(); file.close(); } } if (JumperWireLayerTemplate.isEmpty()) { QFile file(":/resources/templates/jumper_jumperwiresLayerTemplate.txt"); if (file.open(QFile::ReadOnly)) { JumperWireLayerTemplate = file.readAll(); file.close(); } } } JumperItem::~JumperItem() { } QRectF JumperItem::boundingRect() const { if (m_viewID != ViewLayer::PCBView) { return PaletteItem::boundingRect(); } return shape().controlPointRect(); } void JumperItem::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_viewID != ViewLayer::PCBView) { PaletteItem::paintHover(painter, option, widget); return; } ItemBase::paintHover(painter, option, widget, hoverShape()); } void JumperItem::paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_viewID != ViewLayer::PCBView) { PaletteItem::paintSelected(painter, option, widget); return; } GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, boundingRect(), hoverShape()); } QPainterPath JumperItem::hoverShape() const { if (m_viewID != ViewLayer::PCBView) { return PaletteItem::hoverShape(); } QPainterPath path; QPointF c0 = m_connector0->rect().center(); QPointF c1 = m_connector1->rect().center(); path.moveTo(c0); path.lineTo(c1); QRectF rect = m_connector0->rect(); double dx = m_connectorTL.x(); double dy = m_connectorTL.y(); rect.adjust(-dx, -dy, dx, dy); QPen pen; pen.setCapStyle(Qt::RoundCap); return GraphicsUtils::shapeFromPath(path, pen, rect.width(), false); } QPainterPath JumperItem::shape() const { return hoverShape(); } bool JumperItem::setUpImage(ModelPart * modelPart, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { bool result = PaletteItem::setUpImage(modelPart, viewLayers, layerAttributes); if (layerAttributes.doConnectors) { foreach (ConnectorItem * item, cachedConnectorItems()) { item->setCircular(true); if (item->connectorSharedName().contains('0')) { m_connector0 = item; } else if (item->connectorSharedName().contains('1')) { m_connector1 = item; } } m_connectorTL = m_connector0->rect().topLeft(); m_connectorBR = boundingRect().bottomRight() - m_connector1->rect().bottomRight(); initialResize(layerAttributes.viewID); } return result; } void JumperItem::initialResize(ViewLayer::ViewID viewID) { if (viewID != ViewLayer::PCBView) return; bool ok; double r0x = m_modelPart->localProp("r0x").toDouble(&ok); if (!ok) return; double r0y = m_modelPart->localProp("r0y").toDouble(&ok); if (!ok) return; double r1x = m_modelPart->localProp("r1x").toDouble(&ok); if (!ok) return; double r1y = m_modelPart->localProp("r1y").toDouble(&ok); if (!ok) return; resizeAux(GraphicsUtils::mils2pixels(r0x, GraphicsUtils::SVGDPI), GraphicsUtils::mils2pixels(r0y, GraphicsUtils::SVGDPI), GraphicsUtils::mils2pixels(r1x, GraphicsUtils::SVGDPI), GraphicsUtils::mils2pixels(r1y, GraphicsUtils::SVGDPI)); } bool JumperItem::mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event) { m_originalClickItem = originalItem; mousePressEvent(event); return (m_dragItem != NULL); } void JumperItem::mouseMoveEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event) { Q_UNUSED(originalItem); mouseMoveEvent(event); } void JumperItem::mouseReleaseEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event) { Q_UNUSED(originalItem); mouseReleaseEvent(event); } void JumperItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { PaletteItemBase * originalItem = m_originalClickItem; m_originalClickItem = NULL; InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL && infographics->spaceBarIsPressed()) { event->ignore(); return; } m_dragItem = NULL; QRectF rect = m_connector0->rect(); double dx = m_connectorTL.x(); double dy = m_connectorTL.y(); rect.adjust(-dx, -dy, dx, dy); if (rect.contains(event->pos())) { m_dragItem = m_connector0; m_otherItem = m_connector1; } else { rect = m_connector1->rect(); dx = m_connectorBR.x(); dy = m_connectorBR.y(); rect.adjust(-dx, -dy, dx, dy); if (rect.contains(event->pos())) { m_dragItem = m_connector1; m_otherItem = m_connector0; } else { if (originalItem) return ItemBase::mousePressEvent(event); return PaletteItem::mousePressEvent(event); } } m_dragStartScenePos = event->scenePos(); m_dragStartThisPos = this->pos(); m_dragStartConnectorPos = this->mapToScene(m_dragItem->rect().topLeft()); m_dragStartCenterPos = this->mapToScene(m_dragItem->rect().center()); m_otherPos = this->mapToScene(m_otherItem->rect().topLeft()); } void JumperItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (m_dragItem == NULL) return; // TODO: make sure the two connectors don't overlap QPointF d = event->scenePos() - m_dragStartScenePos; QPointF p = m_dragStartConnectorPos + d; emit alignMe(this, p); QPointF myPos(qMin(p.x(), m_otherPos.x()) - m_connectorTL.x(), qMin(p.y(), m_otherPos.y()) - m_connectorTL.y()); this->setPos(myPos); QRectF r = m_otherItem->rect(); r.moveTo(mapFromScene(m_otherPos)); m_otherItem->setRect(r); ConnectorItem * cross = m_otherItem->getCrossLayerConnectorItem(); if (cross) cross->setRect(r); r = m_dragItem->rect(); r.moveTo(mapFromScene(p)); m_dragItem->setRect(r); cross = m_dragItem->getCrossLayerConnectorItem(); if (cross) cross->setRect(r); resize(); QList already; ItemBase::updateConnections(m_dragItem, true, already); } void JumperItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { m_dragItem = NULL; PaletteItem::mouseReleaseEvent(event); } QString JumperItem::makeSvg(ViewLayer::ViewLayerID viewLayerID) { QRectF r0 = m_connector0->rect(); QRectF r1 = m_connector1->rect(); QRectF r = r0.united(r1); double w = GraphicsUtils::pixels2ins(r.width() + m_connectorTL.x() + m_connectorBR.x(), GraphicsUtils::SVGDPI); double h = GraphicsUtils::pixels2ins(r.height() + m_connectorTL.y() + m_connectorBR.y(), GraphicsUtils::SVGDPI); QPointF r0c = r0.center(); QPointF r1c = r1.center(); double r0x = GraphicsUtils::pixels2mils(r0c.x(), GraphicsUtils::SVGDPI); double r0y = GraphicsUtils::pixels2mils(r0c.y(), GraphicsUtils::SVGDPI); double r1x = GraphicsUtils::pixels2mils(r1c.x(), GraphicsUtils::SVGDPI); double r1y = GraphicsUtils::pixels2mils(r1c.y(), GraphicsUtils::SVGDPI); modelPart()->setLocalProp("r0x", r0x); modelPart()->setLocalProp("r0y", r0y); modelPart()->setLocalProp("r1x", r1x); modelPart()->setLocalProp("r1y", r1y); switch (viewLayerID) { case ViewLayer::Copper0: case ViewLayer::Copper1: return Copper0LayerTemplate .arg(w).arg(h) .arg(w * GraphicsUtils::StandardFritzingDPI).arg(h * GraphicsUtils::StandardFritzingDPI) .arg(r0x).arg(r0y).arg(r1x).arg(r1y) .arg(ViewLayer::viewLayerXmlNameFromID(viewLayerID)) .arg(Colors.value(viewLayerID)); //case ViewLayer::Silkscreen0: case ViewLayer::Silkscreen1: shorten(r0, r0c, r1c, r0x, r0y, r1x, r1y); return makeWireImage(w, h, r0x, r0y, r1x, r1y, ViewLayer::viewLayerXmlNameFromID(viewLayerID), Colors.value(viewLayerID), 21); case ViewLayer::PartImage: { shorten(r0, r0c, r1c, r0x, r0y, r1x, r1y); QString svg = makeWireImage(w, h, r0x, r0y, r1x, r1y, ViewLayer::viewLayerXmlNameFromID(viewLayerID), ShadowColor, 40); QString svg2 = makeWireImage(w, h, r0x, r0y, r1x, r1y, "", Colors.value(viewLayerID), 20); int ix1 = svg.indexOf("", ix1); int ix3 = svg2.indexOf("", ix3); svg.insert(ix2 + 1, svg2.mid(ix3, ix4 - ix3 + 1)); return svg; } default: break; } return ___emptyString___; } void JumperItem::resize(QPointF p0, QPointF p1) { QPointF p = calcPos(p0, p1); resize(p, p0 - p, p1 - p); } void JumperItem::resize() { if (m_viewID != ViewLayer::PCBView) return; if (m_connector0 == NULL) return; if (m_connector1 == NULL) return; prepareGeometryChange(); QString s = makeSvg(ViewLayer::Copper0); //DebugDialog::debug(s); resetRenderer(s); foreach (ItemBase * itemBase, m_layerKin) { switch(itemBase->viewLayerID()) { case ViewLayer::PartImage: case ViewLayer::Copper1: case ViewLayer::Silkscreen1: //case ViewLayer::Silkscreen0: { s = makeSvg(itemBase->viewLayerID()); itemBase->resetRenderer(s); } break; default: break; } } // DebugDialog::debug(QString("fast load result %1 %2").arg(result).arg(s)); } void JumperItem::saveParams() { m_itemPos = pos(); m_itemC0 = m_connector0->rect().center(); m_itemC1 = m_connector1->rect().center(); } void JumperItem::getParams(QPointF & p, QPointF & c0, QPointF & c1) { p = m_itemPos; c0 = m_itemC0; c1 = m_itemC1; } void JumperItem::resize(QPointF p, QPointF nc0, QPointF nc1) { resizeAux(nc0.x(), nc0.y(), nc1.x(), nc1.y()); DebugDialog::debug(QString("jumper item set pos %1 %2, %3").arg(this->id()).arg(p.x()).arg(p.y()) ); setPos(p); } void JumperItem::resizeAux(double r0x, double r0y, double r1x, double r1y) { prepareGeometryChange(); QRectF r0 = m_connector0->rect(); QRectF r1 = m_connector1->rect(); QPointF c0 = r0.center(); QPointF c1 = r1.center(); r0.translate(r0x - c0.x(), r0y - c0.y()); r1.translate(r1x - c1.x(), r1y - c1.y()); m_connector0->setRect(r0); m_connector1->setRect(r1); ConnectorItem * cc0 = m_connector0->getCrossLayerConnectorItem(); if (cc0 != NULL) { cc0->setRect(r0); } ConnectorItem * cc1 = m_connector1->getCrossLayerConnectorItem(); if (cc1 != NULL) { cc1->setRect(r1); } resize(); } QSizeF JumperItem::footprintSize() { QRectF r0 = m_connector0->rect(); return r0.size(); } QString JumperItem::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString xml = ""; switch (viewLayerID) { case ViewLayer::Copper0: case ViewLayer::Copper1: case ViewLayer::PartImage: //case ViewLayer::Silkscreen0: case ViewLayer::Silkscreen1: xml = makeSvg(viewLayerID); default: break; } if (!xml.isEmpty()) { return PaletteItemBase::normalizeSvg(xml, viewLayerID, blackOnly, dpi, factor); } return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } void JumperItem::setAutoroutable(bool ar) { m_viewGeometry.setAutoroutable(ar); } bool JumperItem::getAutoroutable() { return m_viewGeometry.getAutoroutable(); } ConnectorItem * JumperItem::connector0() { return m_connector0; } ConnectorItem * JumperItem::connector1() { return m_connector1; } bool JumperItem::hasCustomSVG() { switch (m_viewID) { case ViewLayer::PCBView: return true; default: return ItemBase::hasCustomSVG(); } } bool JumperItem::inDrag() { return m_dragItem != NULL; } void JumperItem::loadLayerKin( const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement viewLayerPlacement) { PaletteItem::loadLayerKin(viewLayers, viewLayerPlacement); resize(); } ItemBase::PluralType JumperItem::isPlural() { return Singular; } void JumperItem::addedToScene(bool temporary) { if (m_connector0 == NULL) return; if (m_connector1 == NULL) return; ConnectorItem * cc0 = m_connector0->getCrossLayerConnectorItem(); if (cc0 != NULL) { cc0->setRect(m_connector0->rect()); } ConnectorItem * cc1 = m_connector1->getCrossLayerConnectorItem(); if (cc1 != NULL) { cc1->setRect(m_connector1->rect()); } PaletteItem::addedToScene(temporary); } void JumperItem::rotateItem(double degrees, bool updateRatsnest) { Q_UNUSED(updateRatsnest); QPointF tc0, tc1; QTransform rotation; rotation.rotate(degrees); rotateEnds(rotation, tc0, tc1); resize(tc0, tc1); } void JumperItem::calcRotation(QTransform & rotation, QPointF center, ViewGeometry & vg2) { QPointF tc0, tc1; rotateEnds(rotation, tc0, tc1); QPointF p = calcPos(tc0, tc1); QPointF myCenter = mapToScene(boundingRect().center()); QTransform transf = QTransform().translate(-center.x(), -center.y()) * rotation * QTransform().translate(center.x(), center.y()); QPointF q = transf.map(myCenter); vg2.setLoc(p + q - myCenter); } void JumperItem::rotateEnds(QTransform & rotation, QPointF & tc0, QPointF & tc1) { ConnectorItem * cc0 = m_connector0; QRectF r0 = cc0->rect(); QPointF c0 = cc0->mapToScene(r0.center()); ConnectorItem * cc1 = m_connector1; QRectF r1 = cc1->rect(); QPointF c1 = cc1->mapToScene(r1.center()); QPointF c((c0.x() + c1.x()) / 2, (c0.y() + c1.y()) / 2); QTransform transf = QTransform().translate(-c.x(), -c.y()) * rotation * QTransform().translate(c.x(), c.y()); tc0 = transf.map(c0); tc1 = transf.map(c1); } QPointF JumperItem::calcPos(QPointF p0, QPointF p1) { QRectF r0 = m_connector0->rect(); QPointF p(qMin(p0.x(), p1.x()) - (r0.width() / 2) - m_connectorTL.x(), qMin(p0.y(), p1.y()) - (r0.height() / 2) - m_connectorTL.y()); return p; } QPointF JumperItem::dragOffset() { return m_dragStartConnectorPos - m_dragStartCenterPos; } void JumperItem::saveInstanceLocation(QXmlStreamWriter & streamWriter) { streamWriter.writeAttribute("x", QString::number(m_viewGeometry.loc().x())); streamWriter.writeAttribute("y", QString::number(m_viewGeometry.loc().y())); streamWriter.writeAttribute("wireFlags", QString::number(m_viewGeometry.flagsAsInt())); GraphicsUtils::saveTransform(streamWriter, m_viewGeometry.transform()); } bool JumperItem::hasPartNumberProperty() { return false; } ViewLayer::ViewID JumperItem::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::PCBView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } fritzing-app-0.9.2b/src/items/jumperitem.h000066400000000000000000000074731250202676700205620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6994 $: $Author: irascibl@gmail.com $: $Date: 2013-04-27 14:25:24 +0200 (Sa, 27. Apr 2013) $ ********************************************************************/ #ifndef JUMPERITEM_H #define JUMPERITEM_H #include "paletteitem.h" class JumperItem : public PaletteItem { Q_OBJECT public: JumperItem( ModelPart * modelPart, ViewLayer::ViewID, const ViewGeometry & , long id, QMenu* itemMenu, bool doLabel); ~JumperItem(); QPainterPath shape() const; QPainterPath hoverShape() const; bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); void saveParams(); void getParams(QPointF & pos, QPointF & c0, QPointF & c1); void resize(QPointF pos, QPointF c0, QPointF c1); void resize(QPointF p0, QPointF p1); QSizeF footprintSize(); QString retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool getAutoroutable(); void setAutoroutable(bool); class ConnectorItem * connector0(); class ConnectorItem * connector1(); bool hasCustomSVG(); bool inDrag(); void loadLayerKin( const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement); PluralType isPlural(); void addedToScene(bool temporary); void rotateItem(double degrees, bool includeRatsnest); void calcRotation(QTransform & rotation, QPointF center, ViewGeometry &); QPointF dragOffset(); void saveInstanceLocation(QXmlStreamWriter & streamWriter); bool hasPartNumberProperty(); QRectF boundingRect() const; bool mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *); void mouseMoveEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *); void mouseReleaseEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *); protected: void resize(); QString makeSvg(ViewLayer::ViewLayerID); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void resizeAux(double r0x, double r0y, double r1x, double r1y); void rotateEnds(QTransform & rotation, QPointF & tc0, QPointF & tc1); QPointF calcPos(QPointF p0, QPointF p1); void initialResize(ViewLayer::ViewID); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); signals: void alignMe(JumperItem *, QPointF & p); protected: QPointer m_dragItem; QPointer m_connector0; QPointer m_connector1; QPointer m_otherItem; QPointF m_dragStartScenePos; QPointF m_dragStartThisPos; QPointF m_dragStartConnectorPos; QPointF m_dragStartCenterPos; QPointF m_otherPos; QPointF m_connectorTL; QPointF m_connectorBR; QPointF m_itemPos; QPointF m_itemC0; QPointF m_itemC1; QPointer m_originalClickItem; }; #endif fritzing-app-0.9.2b/src/items/layerkinpaletteitem.cpp000066400000000000000000000366461250202676700230140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "layerkinpaletteitem.h" #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../layerattributes.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/folderutils.h" #include "../svg/svgfilesplitter.h" #include //////////////////////////////////////////////// static QString IDString("-_-_-text-_-_-%1"); //////////////////////////////////////////////// LayerKinPaletteItem::LayerKinPaletteItem(PaletteItemBase * chief, ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu* itemMenu) : PaletteItemBase(modelPart, viewID, viewGeometry, id, itemMenu) { m_passMouseEvents = false; m_layerKinChief = chief; setFlag(QGraphicsItem::ItemIsSelectable, true); m_modelPart->removeViewItem(this); // we don't need to save layerkin } void LayerKinPaletteItem::initLKPI(LayerAttributes & layerAttributes, const LayerHash & viewLayers) { setViewLayerPlacement(layerAttributes.viewLayerPlacement); m_ok = setUpImage(m_modelPart, viewLayers, layerAttributes); //DebugDialog::debug(QString("lk accepts hover %1 %2 %3 %4 %5").arg(title()).arg(m_viewID).arg(m_id).arg(viewLayerID).arg(this->acceptHoverEvents())); } QVariant LayerKinPaletteItem::itemChange(GraphicsItemChange change, const QVariant &value) { //DebugDialog::debug(QString("lk item change %1 %2").arg(this->id()).arg(change)); if (m_layerKinChief != NULL) { if (change == ItemSelectedChange) { bool selected = value.toBool(); if (m_blockItemSelectedChange && m_blockItemSelectedValue == selected) { m_blockItemSelectedChange = false; } else { m_layerKinChief->syncKinSelection(selected, this); } } //else if (change == ItemVisibleHasChanged && value.toBool()) { //this->setSelected(m_layerKinChief->syncSelected()); //this->setPos(m_offset + m_layerKinChief->syncMoved()); //} else if (change == ItemPositionHasChanged) { m_layerKinChief->syncKinMoved(this->m_offset, value.toPointF()); } } return PaletteItemBase::itemChange(change, value); } void LayerKinPaletteItem::setOffset(double x, double y) { m_offset.setX(x); m_offset.setY(y); this->setPos(this->pos() + m_offset); } ItemBase * LayerKinPaletteItem::layerKinChief() { return m_layerKinChief; } bool LayerKinPaletteItem::ok() { return m_ok; } void LayerKinPaletteItem::updateConnections(bool includeRatsnest, QList & already) { if (m_layerKinChief) { m_layerKinChief->updateConnections(includeRatsnest, already); } else { DebugDialog::debug("chief deleted before layerkin"); } } void LayerKinPaletteItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { m_passMouseEvents = m_layerKinChief->mousePressEventK(this, event); return; //ItemBase::mousePressEvent(event); } void LayerKinPaletteItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (m_passMouseEvents) { m_layerKinChief->mouseMoveEventK(this, event); return; } PaletteItemBase::mouseMoveEvent(event); } void LayerKinPaletteItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (m_passMouseEvents) { m_layerKinChief->mouseReleaseEventK(this, event); return; } PaletteItemBase::mouseReleaseEvent(event); } void LayerKinPaletteItem::setHidden(bool hide) { ItemBase::setHidden(hide); m_layerKinChief->figureHover(); } void LayerKinPaletteItem::setInactive(bool inactivate) { ItemBase::setInactive(inactivate); m_layerKinChief->figureHover(); } void LayerKinPaletteItem::clearModelPart() { m_layerKinChief->clearModelPart(); } bool LayerKinPaletteItem::stickyEnabled() { return m_layerKinChief->stickyEnabled(); } bool LayerKinPaletteItem::isSticky() { return m_layerKinChief->isSticky(); } bool LayerKinPaletteItem::isBaseSticky() { return m_layerKinChief->isBaseSticky(); } void LayerKinPaletteItem::setSticky(bool s) { m_layerKinChief->setSticky(s); } void LayerKinPaletteItem::addSticky(ItemBase * sticky, bool stickem) { m_layerKinChief->addSticky(sticky, stickem); } ItemBase * LayerKinPaletteItem::stickingTo() { return m_layerKinChief->stickingTo(); } QList< QPointer > LayerKinPaletteItem::stickyList() { return m_layerKinChief->stickyList(); } bool LayerKinPaletteItem::alreadySticking(ItemBase * itemBase) { return m_layerKinChief->alreadySticking(itemBase); } void LayerKinPaletteItem::resetID() { long offset = m_id % ModelPart::indexMultiplier; ItemBase::resetID(); m_id += offset; } QString LayerKinPaletteItem::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { return m_layerKinChief->retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } ConnectorItem* LayerKinPaletteItem::newConnectorItem(Connector *connector) { return m_layerKinChief->newConnectorItem(this, connector); } bool LayerKinPaletteItem::isSwappable() { return m_layerKinChief->isSwappable(); } void LayerKinPaletteItem::setSwappable(bool swappable) { m_layerKinChief->setSwappable(swappable); } bool LayerKinPaletteItem::inRotation() { return layerKinChief()->inRotation(); } void LayerKinPaletteItem::setInRotation(bool val) { layerKinChief()->setInRotation(val); } ////////////////////////////////////////////////// SchematicTextLayerKinPaletteItem::SchematicTextLayerKinPaletteItem(PaletteItemBase * chief, ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu* itemMenu) : LayerKinPaletteItem(chief, modelPart, viewID, viewGeometry, id, itemMenu) { } void SchematicTextLayerKinPaletteItem::cacheLoaded(const LayerAttributes & layerAttributes) { this->setProperty("textSvg", layerAttributes.loaded()); } void SchematicTextLayerKinPaletteItem::setTransform2(const QTransform & currTransf) { transformItem(currTransf, false); } void SchematicTextLayerKinPaletteItem::transformItem(const QTransform & currTransf, bool includeRatsnest) { Q_UNUSED(currTransf); Q_UNUSED(includeRatsnest); if (m_textThings.count() == 0) { initTextThings(); } double rotation; QTransform chiefTransform = layerKinChief()->transform(); // assume chief already has rotation bool isFlipped = GraphicsUtils::isFlipped(chiefTransform.toAffine(), rotation); QString svg; if (isFlipped) { svg = makeFlipTextSvg(); } if (svg.isEmpty()) { svg = this->property("textSvg").toByteArray(); } if (rotation >= 135 && rotation <= 225) { svg = vflip(svg, isFlipped); } reloadRenderer(svg, true); QPointF p = layerKinChief()->sceneBoundingRect().topLeft(); QTransform transform; QRectF bounds = boundingRect(); transform.translate(bounds.width() / 2, bounds.height() / 2); transform.rotate(rotation); transform.translate(bounds.width() / -2, bounds.height() / -2); this->setTransform(transform); //QMatrix m1 = chiefTransform.toAffine(); //layerKinChief()->debugInfo("chief " + TextUtils::svgMatrix(m1)); //m1 = transform.toAffine(); //debugInfo("\t " + TextUtils::svgMatrix(m1)); } void SchematicTextLayerKinPaletteItem::initTextThings() { QByteArray textSvg = this->property("textSvg").toByteArray(); QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(textSvg, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse schematic text: %1 %2 %3:\n%4").arg(errorStr).arg(errorLine).arg(errorColumn).arg(QString(textSvg))); return; } QDomElement root = doc.documentElement(); QDomNodeList nodeList = root.elementsByTagName("text"); QList texts; for (int i = 0; i < nodeList.count(); i++) { texts.append(nodeList.at(i).toElement()); } positionTexts(texts); } QString SchematicTextLayerKinPaletteItem::makeFlipTextSvg() { QByteArray textSvg = this->property("textSvg").toByteArray(); QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(textSvg, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse schematic text: %1 %2 %3:\n%4").arg(errorStr).arg(errorLine).arg(errorColumn).arg(QString(textSvg))); return ""; } QDomElement root = doc.documentElement(); QDomNodeList nodeList = root.elementsByTagName("text"); QList texts; for (int i = 0; i < nodeList.count(); i++) { texts.append(nodeList.at(i).toElement()); } int ix = 0; foreach (QDomElement text, texts) { QDomElement g = text.ownerDocument().createElement("g"); text.parentNode().insertAfter(g, text); g.appendChild(text); QMatrix m = m_textThings[ix++].flipMatrix; TextUtils::setSVGTransform(g, m); } return doc.toString(); } #define MINMAX(mx, my) \ if (mx < minX) minX = mx; \ if (mx > maxX) maxX = mx; \ if (my < minY) minY = my; \ if (my > maxY) maxY = my; void SchematicTextLayerKinPaletteItem::positionTexts(QList & texts) { // TODO: reuse these values unless the pin labels have changed //QString id = IDString.arg(0); //if (this->property(id.toUtf8().constData()).isValid()) { // // calculated this already // return; //} m_textThings.clear(); foreach (QDomElement text, texts) { text.setTagName("g"); } QRectF br = boundingRect(); QImage image(qCeil(br.width()) * 2, qCeil(br.height()) * 2, QImage::Format_Mono); // schematic text is so small it doesn't render unless bitmap is double-sized foreach (QDomElement text, texts) { TextThing textThing; QRectF viewBox; QMatrix matrix; renderText(image, text, textThing.minX, textThing.minY, textThing.maxX, textThing.maxY, matrix, viewBox); double newX = (image.width() - textThing.maxX) * viewBox.width() / image.width(); double oldX = textThing.minX * viewBox.width() / image.width(); QMatrix inv = matrix.inverted(); QMatrix t = QMatrix().translate(newX - oldX, 0); textThing.flipMatrix = matrix * t * inv; QRectF r(textThing.minX * viewBox.width() / image.width(), textThing.minY * viewBox.height() / image.height(), (textThing.maxX - textThing.minX) * viewBox.width() / image.width(), (textThing.maxY - textThing.minY) * viewBox.height() / image.height()); textThing.newRect = inv.mapRect(r); m_textThings.append(textThing); } foreach (QDomElement text, texts) { text.setTagName("text"); } } void SchematicTextLayerKinPaletteItem::renderText(QImage & image, QDomElement & text, int & minX, int & minY, int & maxX, int & maxY, QMatrix & matrix, QRectF & viewBox) { QString oldid = text.attribute("id"); text.setAttribute("id", IDString); // TODO: handle inherited fill/stroke values QString oldFill = text.attribute("fill"); text.setAttribute("fill", "black"); QString oldStroke = text.attribute("stroke"); text.setAttribute("stroke", "black"); text.setTagName("text"); image.fill(0xffffffff); QByteArray byteArray = text.ownerDocument().toByteArray(); QSvgRenderer renderer(byteArray); QPainter painter; painter.begin(&image); painter.setRenderHint(QPainter::Antialiasing, false); renderer.render(&painter /*, sourceRes */); painter.end(); #ifndef QT_NO_DEBUG image.save(FolderUtils::getUserDataStorePath("") + "/renderText.png"); #endif viewBox = renderer.viewBoxF(); double x = text.attribute("x").toDouble(); double y = text.attribute("y").toDouble(); QPointF xy(x, y); matrix = renderer.matrixForElement(IDString); QPointF mxy = matrix.map(xy); QPointF p(image.width() * mxy.x() / viewBox.width(), image.height() * mxy.y() / viewBox.height()); QPoint iq((int) p.x(), (int) p.y()); minX = image.width() + 1; maxX = -1; minY = image.height() + 1; maxY = -1; // spiral around q int limit = qMax(image.width(), image.height()); for (int lim = 0; lim < limit; lim++) { int t = qMax(0, iq.y() - lim); int b = qMin(iq.y() + lim, image.height() - 1); int l = qMax(0, iq.x() - lim); int r = qMin(iq.x() + lim, image.width() - 1); for (int iy = t; iy <= b; iy++) { if (image.pixel(l, iy) == 0xff000000) { MINMAX(l, iy); } if (image.pixel(r, iy) == 0xff000000) { MINMAX(r, iy); } } for (int ix = l + 1; ix < r; ix++) { if (image.pixel(ix, t) == 0xff000000) { MINMAX(ix, t); } if (image.pixel(ix, b) == 0xff000000) { MINMAX(ix, b); } } } text.setTagName("g"); if (oldid.isEmpty()) text.removeAttribute("id"); else text.setAttribute("id", oldid); if (oldFill.isEmpty()) text.removeAttribute("fill"); else text.setAttribute("fill", oldFill); if (oldStroke.isEmpty()) text.removeAttribute("stroke"); else text.setAttribute("stroke", oldStroke); } void SchematicTextLayerKinPaletteItem::clearTextThings() { m_textThings.clear(); } QString SchematicTextLayerKinPaletteItem::vflip(const QString & svg, bool isFlipped) { Q_UNUSED(isFlipped); QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse schematic text: %1 %2 %3:\n%4").arg(errorStr).arg(errorLine).arg(errorColumn).arg(QString(svg))); return svg; } QDomElement root = doc.documentElement(); QDomNodeList nodeList = root.elementsByTagName("text"); QList texts; for (int i = 0; i < nodeList.count(); i++) { texts.append(nodeList.at(i).toElement()); } int ix = 0; foreach (QDomElement text, texts) { QDomElement g = text.ownerDocument().createElement("g"); text.parentNode().insertAfter(g, text); g.appendChild(text); QRectF r = m_textThings[ix].newRect; ix++; QMatrix m; m.translate(r.center().x(), r.center().y()); QMatrix inv = m.inverted(); QMatrix matrix = inv * QMatrix().rotate(180) * m; TextUtils::setSVGTransform(g, matrix); } return doc.toString(); } void SchematicTextLayerKinPaletteItem::setInitialTransform(const QTransform & matrix) { setTransform2(matrix); } fritzing-app-0.9.2b/src/items/layerkinpaletteitem.h000066400000000000000000000070051250202676700224440ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef LAYERKINPALETTEITEM_H #define LAYERKINPALETTEITEM_H #include "paletteitembase.h" #include class LayerKinPaletteItem : public PaletteItemBase { Q_OBJECT public: LayerKinPaletteItem(PaletteItemBase * chief, ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu); void setOffset(double x, double y); ItemBase * layerKinChief(); bool ok(); void setHidden(bool hidden); void setInactive(bool inactivate); void clearModelPart(); void initLKPI(LayerAttributes &, const LayerHash &viewLayers); bool isSticky(); bool isBaseSticky(); void setSticky(bool); void addSticky(ItemBase *, bool stickem); ItemBase * stickingTo(); QList > stickyList(); bool alreadySticking(ItemBase * itemBase); bool stickyEnabled(); void resetID(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool isSwappable(); void setSwappable(bool); bool inRotation(); void setInRotation(bool); protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); void updateConnections(bool includeRatsnest, QList & already); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); ConnectorItem* newConnectorItem(class Connector *connector); protected: QPointer m_layerKinChief; bool m_ok; bool m_passMouseEvents; }; struct TextThing { int minX; int maxX; int minY; int maxY; QRectF newRect; QMatrix flipMatrix; }; class SchematicTextLayerKinPaletteItem : public LayerKinPaletteItem { Q_OBJECT public: SchematicTextLayerKinPaletteItem(PaletteItemBase * chief, ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu); void transformItem(const QTransform &, bool includeRatsnest); void clearTextThings(); void setTransform2(const QTransform &); public: static void renderText(QImage &, QDomElement & text, int & minX, int & minY, int & maxX, int & maxY, QMatrix &, QRectF & viewBox); protected: QString makeFlipTextSvg(); void positionTexts(QList & texts); void initTextThings(); QString vflip(const QString & svg, bool isFlipped); void setInitialTransform(const QTransform &); void cacheLoaded(const LayerAttributes &); protected: bool m_flipped; QList m_textThings; }; #endif fritzing-app-0.9.2b/src/items/led.cpp000066400000000000000000000124151250202676700174700ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "led.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../commands.h" #include "../layerattributes.h" #include "moduleidnames.h" #include "partlabel.h" static QHash BreadboardSvg; static QHash IconSvg; LED::LED( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { } LED::~LED() { } QString LED::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { switch (viewLayerID) { case ViewLayer::Breadboard: case ViewLayer::Icon: break; default: return Capacitor::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QString svg = getColorSVG(prop("color"), viewLayerID); if (svg.isEmpty()) return ""; return PaletteItemBase::normalizeSvg(svg, viewLayerID, blackOnly, dpi, factor); } void LED::addedToScene(bool temporary) { if (this->scene()) { setColor(prop("color")); } return Capacitor::addedToScene(temporary); } bool LED::hasCustomSVG() { switch (m_viewID) { case ViewLayer::BreadboardView: case ViewLayer::IconView: return true; default: return ItemBase::hasCustomSVG(); } } bool LED::canEditPart() { return true; } ItemBase::PluralType LED::isPlural() { return Plural; } void LED::setProp(const QString & prop, const QString & value) { Capacitor::setProp(prop, value); if (prop.compare("color") == 0) { setColor(value); } } void LED::slamColor(QDomElement & element, const QString & colorString) { QString id = element.attribute("id"); if (id.startsWith("color_")) { element.setAttribute("fill", colorString); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { slamColor(child, colorString); child = child.nextSiblingElement(); } } void LED::setColor(const QString & color) { switch (m_viewLayerID) { case ViewLayer::Breadboard: case ViewLayer::Icon: break; default: return; } reloadRenderer(getColorSVG(color, m_viewLayerID),true); QString title = modelPart()->modelPartShared()->title(); // bypass any local title by going to modelPartShared if (title.startsWith("red", Qt::CaseInsensitive)) { title.remove(0, 3); QStringList strings = color.split(" "); modelPart()->setLocalTitle(strings.at(0) + title); } else if (title.endsWith("blue", Qt::CaseInsensitive)) { title.chop(4); QStringList strings = color.split(" "); modelPart()->setLocalTitle(title + strings.at(0)); } } QString LED::getColorSVG(const QString & color, ViewLayer::ViewLayerID viewLayerID) { QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(viewLayerID == ViewLayer::Breadboard ? BreadboardSvg.value(m_filename) : IconSvg.value(m_filename), &errorStr, &errorLine, &errorColumn)) { return ""; } QString colorString; foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { if (propertyDef->name.compare("color") == 0) { colorString = propertyDef->adjuncts.value(color, ""); break; } } if (colorString.isEmpty()) return ""; QDomElement root = domDocument.documentElement(); slamColor(root, colorString); return domDocument.toString(); } bool LED::setUpImage(ModelPart * modelPart, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { bool result = Capacitor::setUpImage(modelPart, viewLayers, layerAttributes); if (layerAttributes.viewLayerID == ViewLayer::Breadboard && BreadboardSvg.value(m_filename).isEmpty() && result) { BreadboardSvg.insert(m_filename, QString(layerAttributes.loaded())); } else if (layerAttributes.viewLayerID == ViewLayer::Icon && IconSvg.value(m_filename).isEmpty() && result) { IconSvg.insert(m_filename, QString(layerAttributes.loaded())); } return result; } const QString & LED::title() { m_title = prop("color") + " LED"; return m_title; } ViewLayer::ViewID LED::useViewIDForPixmap(ViewLayer::ViewID vid, bool swappingEnabled) { if (swappingEnabled && vid == ViewLayer::BreadboardView) { return vid; } return ItemBase::useViewIDForPixmap(vid, swappingEnabled); } fritzing-app-0.9.2b/src/items/led.h000066400000000000000000000042261250202676700171360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef LED_H #define LED_H #include #include #include #include #include "capacitor.h" class LED : public Capacitor { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call LED(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~LED(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool hasCustomSVG(); bool canEditPart(); PluralType isPlural(); void addedToScene(bool temporary); void setProp(const QString & prop, const QString & value); bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); const QString & title(); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected: void setColor(const QString & color); void slamColor(QDomElement & element, const QString & colorString); QString getColorSVG(const QString & color, ViewLayer::ViewLayerID); protected: QString m_title; }; #endif fritzing-app-0.9.2b/src/items/logoitem.cpp000066400000000000000000001066541250202676700205540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "logoitem.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../utils/fmessagebox.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../svg/gerbergenerator.h" #include "moduleidnames.h" #include "../svg/groundplanegenerator.h" #include "../utils/cursormaster.h" #include "../debugdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include static QStringList LogoImageNames; static QStringList Logo0ImageNames; static QStringList NewLogoImageNames; static QStringList Copper0ImageNames; static QStringList Copper1ImageNames; LogoItem::LogoItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : ResizableBoard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { if (LogoImageNames.count() == 0) { // TODO: load these names from somewhere LogoImageNames << "new Made with Fritzing" << "new Fritzing icon" << "OHANDA logo" << "OSHW logo"; Logo0ImageNames << "new Made with Fritzing 0" << "new Fritzing icon 0" << "OHANDA logo 0" << "OSHW logo 0"; } m_svgOnly = false; m_standardizeColors = true; m_inLogoEntry = QTime::currentTime().addSecs(-10); m_aspectRatioCheck = NULL; m_keepAspectRatio = true; m_hasLogo = (modelPart->moduleID().endsWith(ModuleIDNames::LogoTextModuleIDName)); m_logo = modelPart->localProp("logo").toString(); if (m_hasLogo && m_logo.isEmpty()) { m_logo = modelPart->properties().value("logo", "logo"); modelPart->setLocalProp("logo", m_logo); } if (m_modelPart->moduleID() == ModuleIDNames::LogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::LogoImageModuleIDName); } else if (m_modelPart->moduleID() == ModuleIDNames::Silkscreen0LogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::Silkscreen0LogoImageModuleIDName); } else if (m_modelPart->moduleID() == ModuleIDNames::Copper1LogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::Copper1LogoImageModuleIDName); } else if (m_modelPart->moduleID() == ModuleIDNames::Copper0LogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::Copper0LogoImageModuleIDName); } else if (m_modelPart->moduleID() == ModuleIDNames::SchematicLogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::SchematicLogoImageModuleIDName); } else if (m_modelPart->moduleID() == ModuleIDNames::BreadboardLogoImageModuleIDName) { m_modelPart->modelPartShared()->setModuleID("new" + ModuleIDNames::BreadboardLogoImageModuleIDName); } } LogoItem::~LogoItem() { } bool LogoItem::hasLogo() { return m_hasLogo; } QString LogoItem::getShapeForRenderer(const QString & svg) { return svg; } void LogoItem::addedToScene(bool temporary) { if (this->scene()) { setInitialSize(); m_aspectRatio.setWidth(this->boundingRect().width()); m_aspectRatio.setHeight(this->boundingRect().height()); m_originalFilename = filename(); QString svg = prop("shape"); if (!svg.isEmpty()) { QString arString = modelPart()->localProp("aspectratio").toString(); if (!arString.isEmpty()) { m_aspectRatio = modelPart()->localProp("aspectratio").toSizeF(); } else { bool okw, okh; double w = m_modelPart->localProp("width").toDouble(&okw); double h = m_modelPart->localProp("height").toDouble(&okh); if (okw && okh) { m_aspectRatio = QSizeF(w, h); } } if (resetRenderer(getShapeForRenderer(svg))) { } else { DebugDialog::debug("bad shape in " + m_originalFilename + " " + svg); } } else { QFile f(m_originalFilename); if (f.open(QFile::ReadOnly)) { QString svg = f.readAll(); f.close(); modelPart()->setLocalProp("shape", svg); modelPart()->setLocalProp("lastfilename", m_originalFilename); initImage(); } } } return ResizableBoard::addedToScene(temporary); } bool LogoItem::canRetrieveLayer(ViewLayer::ViewLayerID viewLayerID) { return viewLayerID == layer(); } QStringList & LogoItem::getImageNames() { return isBottom() ? Logo0ImageNames : LogoImageNames; } QStringList & LogoItem::getNewImageNames() { return NewLogoImageNames; } QString LogoItem::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { if (canRetrieveLayer(viewLayerID)) { QString svg = prop("shape"); if (!svg.isEmpty()) { QString xmlName = ViewLayer::viewLayerXmlNameFromID(viewLayerID); SvgFileSplitter splitter; bool result = splitter.splitString(svg, xmlName); if (!result) { return ""; } double scaleX = 1; double scaleY = 1; if (m_hasLogo) { QDomDocument doc = splitter.domDocument(); QDomElement root = doc.documentElement(); QDomElement g = root.firstChildElement("g"); QDomElement text = g.firstChildElement("text"); // TODO: this is really a hack and resizing should change a scale factor rather than the coordinates // but it's not clear how to deal with existing sketches QString viewBox = root.attribute("viewBox"); double w = TextUtils::convertToInches(root.attribute("width")); double h = TextUtils::convertToInches(root.attribute("height")); QStringList coords = viewBox.split(" ", QString::SkipEmptyParts); double sx = w / coords.at(2).toDouble(); double sy = h / coords.at(3).toDouble(); if (qAbs(sx - sy) > .001) { // change vertical dpi to match horizontal dpi // y coordinate is really intended in relation to font size so leave it be scaleY = sy / sx; root.setAttribute("viewBox", QString("0 0 %1 %2").arg(coords.at(2)).arg(h / sx)); } } result = splitter.normalize(dpi, xmlName, blackOnly, factor); if (!result) { return ""; } QString string = splitter.elementString(xmlName); if (scaleY == 1) return string; QTransform t; t.scale(scaleX, scaleY); return TextUtils::svgTransform(string, t, false, ""); } } return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QStringList LogoItem::collectValues(const QString & family, const QString & prop, QString & value) { QStringList values = ResizableBoard::collectValues(family, prop, value); bool copperTopOK = true; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) copperTopOK = false; else if (infoGraphicsView->boardLayers() == 1) copperTopOK = false; QStringList newValues; if (prop.compare("layer", Qt::CaseInsensitive) == 0) { foreach (QString xmlName, values) { if (xmlName == ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1) && copperTopOK == false) continue; newValues << Board::convertFromXmlName(xmlName); } value = Board::convertFromXmlName(value); return newValues; } return values; } bool LogoItem::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (m_hasLogo) { if (prop.compare("logo", Qt::CaseInsensitive) == 0) { returnProp = tr("text"); returnValue = m_logo; QLineEdit * edit = new QLineEdit(parent); edit->setObjectName("infoViewLineEdit"); edit->setText(m_logo); edit->setEnabled(swappingEnabled); connect(edit, SIGNAL(editingFinished()), this, SLOT(logoEntry())); returnWidget = edit; return true; } } else { if (prop.compare("filename", Qt::CaseInsensitive) == 0) { setupLoadImage(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget); return true; } } if (prop.compare("shape", Qt::CaseInsensitive) == 0) { returnWidget = setUpDimEntry(true, !m_hasLogo, false, returnWidget); returnWidget->setEnabled(swappingEnabled); returnProp = tr("shape"); return true; } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } bool LogoItem::checkImage(const QString & filename) { Q_UNUSED(filename); return true; } void LogoItem::prepLoadImageAux(const QString & fileName, bool addName) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->loadLogoImage(this, prop("shape"), m_aspectRatio, prop("lastfilename"), fileName, addName); } } bool LogoItem::reloadImage(const QString & incomingSvg, const QSizeF & aspectRatio, const QString & fileName, bool addName) { QString svg = incomingSvg; if (isBottom()) { if (!svg.contains("_flipped_")) { svg = flipSvg(svg); } } QString shape = getShapeForRenderer(svg); bool result = resetRenderer(shape); if (result) { if (aspectRatio == QSizeF(0, 0)) { QRectF r = fsvgRenderer()->viewBoxF(); m_aspectRatio.setWidth(r.width()); m_aspectRatio.setHeight(r.height()); } else { m_aspectRatio = aspectRatio; } modelPart()->setLocalProp("aspectratio", m_aspectRatio); modelPart()->setLocalProp("shape", svg); modelPart()->setLocalProp("logo", ""); modelPart()->setLocalProp("lastfilename", fileName); QSizeF size = fsvgRenderer()->defaultSizeF(); double mmW = GraphicsUtils::pixels2mm(size.width(), GraphicsUtils::SVGDPI); double mmH = GraphicsUtils::pixels2mm(size.height(), GraphicsUtils::SVGDPI); modelPart()->setLocalProp("width", mmW); modelPart()->setLocalProp("height", mmH); modelPart()->setLocalProp("originalWidth", mmW); modelPart()->setLocalProp("originalHeight", mmH); if (addName) { if (!getNewImageNames().contains(fileName, Qt::CaseInsensitive)) { getNewImageNames().append(fileName); if (m_fileNameComboBox) { bool wasBlocked = m_fileNameComboBox->blockSignals(true); while (m_fileNameComboBox->count() > 0) { m_fileNameComboBox->removeItem(0); } setFileNameItems(); m_fileNameComboBox->blockSignals(wasBlocked); } } } m_logo = ""; setWidthAndHeight(qRound(mmW * 10) / 10.0, qRound(mmH * 10) / 10.0); return true; } else { // restore previous (not sure whether this is necessary) resetRenderer(getShapeForRenderer(prop("shape"))); unableToLoad(fileName, tr("due to a rendering error")); return false; } } void LogoItem::loadImage(const QString & fileName, bool addName) { QString svg; if (fileName.endsWith(".svg")) { QFile f(fileName); if (f.open(QFile::ReadOnly)) { svg = f.readAll(); } if (svg.isEmpty()) { unableToLoad(fileName, tr("because the svg is empty")); return; } if (svg.contains("coreldraw", Qt::CaseInsensitive) && svg.contains("cdata", Qt::CaseInsensitive)) { unableToLoad(fileName, tr("because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting")); return; } TextUtils::fixMuch(svg, true); TextUtils::fixPixelDimensionsIn(svg); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, true, &errorStr, &errorLine, &errorColumn)) { unableToLoad(fileName, tr("due to an xml problem: %1 line:%2 column:%3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { unableToLoad(fileName, tr("because the file has no root element")); return; } if (root.tagName() != "svg") { unableToLoad(fileName, tr("because the file has no element")); return; } if (m_standardizeColors) { QStringList exceptions; exceptions << "none" << ""; QString toColor(colorString()); SvgFileSplitter::changeColors(root, toColor, exceptions); // todo: change opacity? } QRectF vb; double w, h; TextUtils::ensureViewBox(domDocument, GraphicsUtils::SVGDPI, vb, true, w, h, false); QDomElement layerElement = TextUtils::findElementWithAttribute(root, "id", layerName()); if (layerElement.isNull()) { QList rootChildren; QDomNode rootChild = root.firstChild(); while (!rootChild.isNull()) { rootChildren.append(rootChild); rootChild = rootChild.nextSibling(); } QDomElement topG = domDocument.createElement("g"); topG.setAttribute("id", layerName()); root.appendChild(topG); foreach (QDomNode node, rootChildren) { topG.appendChild(node); } } svg = TextUtils::removeXMLEntities(domDocument.toString()); } else { QImage image(fileName); if (image.isNull()) { unableToLoad(fileName, tr("for unknown reasons--possibly the image file is corrupted")); return; } if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_Mono); } double res = image.dotsPerMeterX() / GraphicsUtils::InchesPerMeter; if (this->m_standardizeColors) { GroundPlaneGenerator gpg; gpg.setLayerName(layerName()); gpg.setMinRunSize(1, 1); gpg.scanImage(image, image.width(), image.height(), 1, res, colorString(), false, false, QSizeF(0, 0), 0, QPointF(0, 0)); if (gpg.newSVGs().count() < 1) { FMessageBox::information( NULL, tr("Unable to display"), tr("Unable to display image from %1").arg(fileName) ); return; } svg = gpg.mergeSVGs("", layerName()); } else { svg = TextUtils::makeSVGHeader(res, res, image.width(), image.height()); int ix = svg.lastIndexOf(">"); svg.replace(ix, 1, "xmlns:xlink='http://www.w3.org/1999/xlink'>"); QString type = "png"; QByteArray bytes; if (fileName.endsWith(".png") || fileName.endsWith(".jpg") || fileName.endsWith("jpeg")) { if (!fileName.endsWith(".png")) type = "jpg"; QFile file(fileName); file.open(QFile::ReadOnly); bytes = file.readAll(); } else { QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "PNG"); // writes image into bytes in PNG format } svg += QString("\n"; svg += ""; } } reloadImage(svg, QSizeF(0, 0), fileName, addName); } bool LogoItem::resizeMM(double mmW, double mmH, const LayerHash & viewLayers) { Q_UNUSED(viewLayers); if (mmW == 0 || mmH == 0) { return false; } // DebugDialog::debug(QString("resize mm %1 %2").arg(mmW).arg(mmH)); QRectF r = this->boundingRect(); if (qAbs(GraphicsUtils::pixels2mm(r.width(), GraphicsUtils::SVGDPI) - mmW) < .001 && qAbs(GraphicsUtils::pixels2mm(r.height(), GraphicsUtils::SVGDPI) - mmH) < .001) { return false; } double inW = GraphicsUtils::mm2mils(mmW) / 1000; double inH = GraphicsUtils::mm2mils(mmH) / 1000; // TODO: deal with aspect ratio QString svg = prop("shape"); if (svg.isEmpty()) return false; QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, &errorStr, &errorLine, &errorColumn)) { return false; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { return false; } if (root.tagName() != "svg") { return false; } root.setAttribute("width", QString::number(inW) + "in"); root.setAttribute("height", QString::number(inH) + "in"); svg = TextUtils::removeXMLEntities(domDocument.toString()); QString shape = getShapeForRenderer(svg); bool result = resetRenderer(shape); if (result) { modelPart()->setLocalProp("shape", svg); modelPart()->setLocalProp("width", mmW); modelPart()->setLocalProp("height", mmH); } setWidthAndHeight(qRound(mmW * 10) / 10.0, qRound(mmH * 10) / 10.0); return true; } void LogoItem::setProp(const QString & prop, const QString & value) { if (prop.compare("logo", Qt::CaseInsensitive) == 0) { setLogo(value, false); return; } ResizableBoard::setProp(prop, value); } void LogoItem::setLogo(QString logo, bool force) { if (!force && m_logo.compare(logo) == 0) return; if (!isEverVisible()) { return; } QString svg; QFile f(m_originalFilename); if (f.open(QFile::ReadOnly)) { svg = f.readAll(); } if (svg.isEmpty()) return; QSizeF oldSize = m_size; QXmlStreamReader streamReader(svg); QSizeF oldSvgSize = fsvgRenderer() ? fsvgRenderer()->viewBoxF().size() : QSizeF(0, 0); DebugDialog::debug(QString("size %1 %2, %3 %4").arg(m_size.width()).arg(m_size.height()).arg(oldSvgSize.width()).arg(oldSvgSize.height())); svg = hackSvg(svg, logo); QXmlStreamReader newStreamReader(svg); bool ok = rerender(svg); m_logo = logo; modelPart()->setLocalProp("logo", logo); modelPart()->setLocalProp("shape", svg); if (ok && !force) { QSizeF newSvgSize = fsvgRenderer()->viewBoxF().size(); QSizeF newSize = newSvgSize * oldSize.height() / oldSvgSize.height(); DebugDialog::debug(QString("size %1 %2, %3 %4").arg(m_size.width()).arg(m_size.height()).arg(newSize.width()).arg(newSize.height())); // set the new text to approximately the same height as the original // if the text is non-proportional that will be lost LayerHash layerHash; resizeMM(GraphicsUtils::pixels2mm(newSize.width(), GraphicsUtils::SVGDPI), GraphicsUtils::pixels2mm(newSize.height(), GraphicsUtils::SVGDPI), layerHash); //DebugDialog::debug(QString("size %1 %2").arg(m_size.width()).arg(m_size.height())); } } bool LogoItem::rerender(const QString & svg) { QString newSvg; bool result = resetRenderer(svg); if (result) { QRectF r = fsvgRenderer()->viewBoxF(); m_aspectRatio.setWidth(r.width()); m_aspectRatio.setHeight(r.height()); } return result; } QString LogoItem::getProperty(const QString & key) { if (key.compare("logo", Qt::CaseInsensitive) == 0) { return m_logo; } return PaletteItem::getProperty(key); } const QString & LogoItem::logo() { return m_logo; } bool LogoItem::canEditPart() { return false; } bool LogoItem::hasPartLabel() { return false; } void LogoItem::logoEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; logoEntryAux(edit->text()); } void LogoItem::logoEntryAux(const QString & text) { if (text.compare(this->logo()) == 0) return; // m_inLogoEntry is a hack because a focus out event was being triggered on m_widthEntry when a user hit the return key in logoentry // this triggers a call to widthEntry() which causes all kinds of havoc. (bug in version 0.7.1 and possibly earlier) m_inLogoEntry = QTime::currentTime().addSecs(1); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "logo", tr("text"), this->logo(), text, true); } } void LogoItem::initImage() { if (m_hasLogo) { setLogo(m_logo, true); return; } loadImage(m_originalFilename, false); } QString LogoItem::hackSvg(const QString & svg, const QString & logo) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) return svg; QDomElement root = doc.documentElement(); root.setAttribute("width", QString::number(logo.length() * 0.1) + "in"); QString viewBox = root.attribute("viewBox"); QStringList coords = viewBox.split(" ", QString::SkipEmptyParts); coords[2] = QString::number(logo.length() * 10); root.setAttribute("viewBox", coords.join(" ")); QStringList exceptions; exceptions << "none" << ""; QString toColor(colorString()); SvgFileSplitter::changeColors(root, toColor, exceptions); QDomNodeList domNodeList = root.elementsByTagName("text"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement node = domNodeList.item(i).toElement(); if (node.isNull()) continue; if (node.attribute("id").compare("label") != 0) continue; node.setAttribute("x", QString::number(logo.length() * 5)); QDomNodeList childList = node.childNodes(); for (int j = 0; j < childList.count(); j++) { QDomNode child = childList.item(i); if (child.isText()) { child.setNodeValue(logo); modelPart()->setLocalProp("width", logo.length() * 0.1 * 25.4); QString h = root.attribute("height"); bool ok; modelPart()->setLocalProp("height", TextUtils::convertToInches(h, &ok, false) * 25.4); if (!isBottom()) return doc.toString(); return flipSvg(doc.toString()); } } } if (!isBottom()) return svg; return flipSvg(svg); } void LogoItem::widthEntry() { if (QTime::currentTime() < m_inLogoEntry) return; QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; double w = edit->text().toDouble(); double oldW = m_modelPart->localProp("width").toDouble(); if (w == oldW) return; double h = m_modelPart->localProp("height").toDouble(); if (m_keepAspectRatio) { h = w * m_aspectRatio.height() / m_aspectRatio.width(); } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(w, h, true); } } void LogoItem::heightEntry() { if (QTime::currentTime() < m_inLogoEntry) return; QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; double h = edit->text().toDouble(); double oldH = m_modelPart->localProp("height").toDouble(); if (h == oldH) return; setHeight(h); } void LogoItem::setHeight(double h) { double w = m_modelPart->localProp("width").toDouble(); if (m_keepAspectRatio) { w = h * m_aspectRatio.width() / m_aspectRatio.height(); } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(w, h, true); } } bool LogoItem::stickyEnabled() { return true; } ItemBase::PluralType LogoItem::isPlural() { return Plural; } ViewLayer::ViewLayerID LogoItem::layer() { return isBottom() ? ViewLayer::Silkscreen0 : ViewLayer::Silkscreen1; } QString LogoItem::colorString() { return isBottom() ? ViewLayer::Silkscreen0Color : ViewLayer::Silkscreen1Color; } QString LogoItem::layerName() { return ViewLayer::viewLayerXmlNameFromID(layer()); } double LogoItem::minWidth() { double zoom = 1; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { zoom = infoGraphicsView->currentZoom() / 100; if (zoom == 0) zoom = 1; } return ResizableBoard::CornerHandleSize * 2 / zoom; } double LogoItem::minHeight() { double zoom = 1; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { zoom = infoGraphicsView->currentZoom() / 100; if (zoom == 0) zoom = 1; } return ResizableBoard::CornerHandleSize * 2 / zoom; } bool LogoItem::freeRotationAllowed(Qt::KeyboardModifiers modifiers) { if ((modifiers & altOrMetaModifier()) == 0) return false; if (!isSelected()) return false; return true; } bool LogoItem::freeRotationAllowed() { return true; } ResizableBoard::Corner LogoItem::findCorner(QPointF scenePos, Qt::KeyboardModifiers modifiers) { ResizableBoard::Corner corner = ResizableBoard::findCorner(scenePos, modifiers); if (corner == ResizableBoard::NO_CORNER) return corner; if (modifiers & altOrMetaModifier()) { // free rotate setCursor(*CursorMaster::RotateCursor); return ResizableBoard::NO_CORNER; } return corner; } void LogoItem::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { PaletteItem::paintHover(painter, option, widget); } bool LogoItem::isBottom() { QString layer = modelPart()->properties().value("layer"); return layer.contains("0") || layer.contains("bottom"); } QString LogoItem::flipSvg(const QString & svg) { QString newSvg = svg; // need the end quote in the replace since the xml for silkscreen1 is just "silkscreen" newSvg.replace("\"" + ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1) + "\"", "\"" + ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0) + "\""); newSvg.replace("'" + ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1) + "'", "'" + ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0) + "'"); newSvg.replace(ViewLayer::Silkscreen1Color, ViewLayer::Silkscreen0Color, Qt::CaseInsensitive); return flipSvgAux(newSvg); } QString LogoItem::flipSvgAux(QString & newSvg) { QMatrix m; QSvgRenderer renderer(newSvg.toUtf8()); QRectF bounds = renderer.viewBoxF(); m.translate(bounds.center().x(), bounds.center().y()); QMatrix mMinus = m.inverted(); QMatrix cm = mMinus * QMatrix().scale(-1, 1) * m; int gix = newSvg.indexOf("prop("lastfilename"); if (QFile::exists(lastfilename)) return lastfilename; DebugDialog::debug(QString("logo item image '%1' doesn't exist").arg(lastfilename)); return ""; } QString LogoItem::getInspectorTitle() { if (hasLogo()) return m_logo; return ResizableBoard::getInspectorTitle(); } void LogoItem::setInspectorTitle(const QString & oldText, const QString & newText) { if (!hasLogo()) return ResizableBoard::setInspectorTitle(oldText, newText); logoEntryAux(newText); } /////////////////////////////////////////////////////////////////////// SchematicLogoItem::SchematicLogoItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : LogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { } SchematicLogoItem::~SchematicLogoItem() { } ViewLayer::ViewLayerID SchematicLogoItem::layer() { return (m_hasLogo ? ViewLayer::SchematicText : ViewLayer::Schematic); } QString SchematicLogoItem::colorString() { return "black"; } bool SchematicLogoItem::isBottom() { return false; } /////////////////////////////////////////////////////////////////////// BreadboardLogoItem::BreadboardLogoItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : LogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_color = "#787878"; QString color = modelPart->localProp("color").toString(); if (color.isEmpty()) { color = modelPart->properties().value("color"); if (color.isEmpty()) color = m_color; modelPart->setLocalProp("color", color); } m_color = color; m_standardizeColors = false; } BreadboardLogoItem::~BreadboardLogoItem() { } ViewLayer::ViewLayerID BreadboardLogoItem::layer() { return ViewLayer::Breadboard; } QString BreadboardLogoItem::colorString() { return m_color; } bool BreadboardLogoItem::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (m_hasLogo) { if (prop.compare("color", Qt::CaseInsensitive) == 0) { returnProp = tr("color"); returnValue = m_color; QPushButton * button = new QPushButton(tr("Set text color")); button->setObjectName("infoViewButton"); connect(button, SIGNAL(pressed()), this, SLOT(changeTextColor())); returnWidget = button; return true; } } return LogoItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void BreadboardLogoItem::changeTextColor() { QColor color(m_color); QColor newColor = QColorDialog::getColor(color, NULL, tr("Select text color")); if (!newColor.isValid()) return; if (newColor.name().compare(m_color, Qt::CaseInsensitive) == 0) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "color", tr("color"), m_color, newColor.name(), true); } } void BreadboardLogoItem::setProp(const QString & prop, const QString & value) { if (m_hasLogo && prop.compare("color", Qt::CaseInsensitive) == 0) { m_color = value; modelPart()->setLocalProp("color", m_color); setLogo(m_logo, true); return; } LogoItem::setProp(prop, value); } bool BreadboardLogoItem::isBottom() { return false; } /////////////////////////////////////////////////////////////////////// CopperLogoItem::CopperLogoItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : LogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { // TODO: load these names from somewhere if (Copper1ImageNames.count() == 0) { Copper1ImageNames << "new Made with Fritzing copper1" << "new Fritzing icon copper1" << "OHANDA logo copper1" << "OSHW logo copper1"; } if (Copper0ImageNames.count() == 0) { Copper0ImageNames << "new Made with Fritzing copper0" << "new Fritzing icon copper0" << "OHANDA logo copper0" << "OSHW logo copper1"; } m_hasLogo = (modelPart->moduleID().endsWith(ModuleIDNames::LogoTextModuleIDName)); m_logo = modelPart->localProp("logo").toString(); if (m_hasLogo && m_logo.isEmpty()) { m_logo = modelPart->properties().value("logo", "logo"); modelPart->setLocalProp("logo", m_logo); } } CopperLogoItem::~CopperLogoItem() { } ViewLayer::ViewLayerID CopperLogoItem::layer() { return isBottom() ? ViewLayer::Copper0 : ViewLayer::Copper1; } QString CopperLogoItem::colorString() { return isBottom() ? ViewLayer::Copper0Color : ViewLayer::Copper1Color; } QStringList & CopperLogoItem::getImageNames() { return isBottom() ? Copper0ImageNames : Copper1ImageNames; } QString CopperLogoItem::flipSvg(const QString & svg) { QString newSvg = svg; newSvg.replace(ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0)); newSvg.replace(ViewLayer::Copper1Color, ViewLayer::Copper0Color, Qt::CaseInsensitive); return flipSvgAux(newSvg); } //////////////////////////////////////////// // todo: // // don't mess with colors at all? BoardLogoItem::BoardLogoItem(ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : LogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_hasLogo = false; m_svgOnly = true; m_standardizeColors = false; if (BoardImageNames.count() == 0) { BoardImageNames << "circle_pcb"; } } BoardLogoItem::~BoardLogoItem() { } QString BoardLogoItem::getShapeForRenderer(const QString & svg) { return ResizableBoard::getShapeForRenderer(svg, m_viewLayerID); } ViewLayer::ViewLayerID BoardLogoItem::layer() { return ViewLayer::Board; } QString BoardLogoItem::colorString() { return ViewLayer::BoardColor; } QStringList & BoardLogoItem::getImageNames() { return BoardImageNames; } QStringList & BoardLogoItem::getNewImageNames() { return NewBoardImageNames; } bool BoardLogoItem::resizeMM(double mmW, double mmH, const LayerHash & viewLayers) { bool result = LogoItem::resizeMM(mmW, mmH, viewLayers); if (!result) return result; reloadLayerKin(mmW, mmH); return result; } void BoardLogoItem::reloadLayerKin(double mmW, double mmH) { foreach (ItemBase * itemBase, m_layerKin) { if (itemBase->viewLayerID() == ViewLayer::Silkscreen1 || itemBase->viewLayerID() == ViewLayer::Silkscreen0) { QString svg = ResizableBoard::getShapeForRenderer(prop("shape"), itemBase->viewLayerID()); if (!svg.isEmpty()) { itemBase->prepareGeometryChange(); if (itemBase->resetRenderer(svg)) { itemBase->modelPart()->setLocalProp("width", mmW); itemBase->modelPart()->setLocalProp("height", mmH); } } } } } bool BoardLogoItem::canRetrieveLayer(ViewLayer::ViewLayerID viewLayerID) { return LogoItem::canRetrieveLayer(viewLayerID) || viewLayerID == LogoItem::layer() || viewLayerID == ViewLayer::Silkscreen0 || viewLayerID == ViewLayer::Silkscreen1; } bool BoardLogoItem::reloadImage(const QString & svg, const QSizeF & aspectRatio, const QString & fileName, bool addName) { bool result; if (!svg.contains(GerberGenerator::MagicBoardOutlineID, Qt::CaseInsensitive)) { QString nsvg = setBoardOutline(svg); result = LogoItem::reloadImage(nsvg, aspectRatio, fileName, addName); } else { result = LogoItem::reloadImage(svg, aspectRatio, fileName, addName); } if (!result) return result; reloadLayerKin(prop("width").toDouble(), prop("height").toDouble()); return result; } bool BoardLogoItem::checkImage(const QString & filename) { // override logoitem return ResizableBoard::checkImage(filename); } bool BoardLogoItem::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("shape", Qt::CaseInsensitive) == 0) { Board::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); returnWidget = setUpDimEntry(true, true, false, returnWidget); returnWidget->setEnabled(swappingEnabled); m_aspectRatioCheck->setEnabled(false); m_aspectRatioCheck->setChecked(true); m_aspectRatioCheck->setVisible(false); m_aspectRatioLabel->setVisible(false); returnProp = tr("shape"); return true; } return LogoItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } bool BoardLogoItem::isBottom() { return false; } fritzing-app-0.9.2b/src/items/logoitem.h000066400000000000000000000140011250202676700202010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef LOGOITEM_H #define LOGOITEM_H #include #include #include #include #include #include #include #include "resizableboard.h" class LogoItem : public ResizableBoard { Q_OBJECT public: LogoItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~LogoItem(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool resizeMM(double w, double h, const LayerHash & viewLayers); QString getProperty(const QString & key); void setLogo(QString logo, bool force); const QString & logo(); bool canEditPart(); void setProp(const QString & prop, const QString & value); bool hasPartLabel(); void loadImage(const QString & fileName, bool addName); virtual bool reloadImage(const QString & svg, const QSizeF & aspectRatio, const QString & fileName, bool addName); bool stickyEnabled(); PluralType isPlural(); void addedToScene(bool temporary); void setHeight(double h); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool hasLogo(); QString getNewLayerFileName(const QString & newLayer); QString getInspectorTitle(); void setInspectorTitle(const QString & oldText, const QString & newText); protected slots: void logoEntry(); void widthEntry(); void heightEntry(); protected: virtual QString hackSvg(const QString & svg, const QString & logo); void initImage(); void prepLoadImageAux(const QString & fileName, bool addName); virtual ViewLayer::ViewLayerID layer(); virtual QString colorString(); virtual QString layerName(); bool rerender(const QString & svg); double minWidth(); double minHeight(); bool freeRotationAllowed(Qt::KeyboardModifiers modifiers); bool freeRotationAllowed(); ResizableBoard::Corner findCorner(QPointF p, Qt::KeyboardModifiers); virtual QString getShapeForRenderer(const QString & svg); virtual bool canRetrieveLayer(ViewLayer::ViewLayerID viewLayerID); bool checkImage(const QString & filename); QStringList & getImageNames(); QStringList & getNewImageNames(); virtual bool isBottom(); virtual QString flipSvg(const QString & svg); QString flipSvgAux(QString & newSvg); QStringList collectValues(const QString & family, const QString & prop, QString & value); void logoEntryAux(const QString & newText); protected: QString m_logo; bool m_hasLogo; QString m_originalFilename; QTime m_inLogoEntry; bool m_standardizeColors; }; class CopperLogoItem : public LogoItem { Q_OBJECT public: CopperLogoItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~CopperLogoItem(); protected: ViewLayer::ViewLayerID layer(); QString colorString(); QStringList & getImageNames(); QString flipSvg(const QString & svg); }; class SchematicLogoItem : public LogoItem { Q_OBJECT public: SchematicLogoItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~SchematicLogoItem(); protected: ViewLayer::ViewLayerID layer(); QString colorString(); bool isBottom(); }; class BreadboardLogoItem : public LogoItem { Q_OBJECT public: BreadboardLogoItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~BreadboardLogoItem(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void setProp(const QString & prop, const QString & value); public slots: void changeTextColor(); protected: ViewLayer::ViewLayerID layer(); QString colorString(); bool isBottom(); protected: QString m_color; }; class BoardLogoItem : public LogoItem { Q_OBJECT public: BoardLogoItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~BoardLogoItem(); bool resizeMM(double w, double h, const LayerHash & viewLayers); bool reloadImage(const QString & svg, const QSizeF & aspectRatio, const QString & fileName, bool addName); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); protected: ViewLayer::ViewLayerID layer(); QString colorString(); QStringList & getImageNames(); QStringList & getNewImageNames(); QString getShapeForRenderer(const QString & svg); bool canRetrieveLayer(ViewLayer::ViewLayerID viewLayerID); void reloadLayerKin(double mmW, double mmH); bool checkImage(const QString & filename); bool isBottom(); }; #endif fritzing-app-0.9.2b/src/items/moduleidnames.cpp000066400000000000000000000122531250202676700215520ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6947 $: $Author: irascibl@gmail.com $: $Date: 2013-04-03 06:45:22 +0200 (Mi, 03. Apr 2013) $ ********************************************************************/ #include "moduleidnames.h" ///////////////////////////////// const QString ModuleIDNames::ModuleIDNameSuffix = "ModuleID"; const QString ModuleIDNames::RulerModuleIDName = "RulerModuleID"; const QString ModuleIDNames::BreadboardModuleIDName = "BreadboardModuleID"; const QString ModuleIDNames::FullPlusBreadboardModuleIDName = "Breadboard-RSR03MB102-ModuleID"; const QString ModuleIDNames::RectanglePCBModuleIDName = "RectanglePCBModuleID"; const QString ModuleIDNames::TwoSidedRectanglePCBModuleIDName = "TwoLayerRectanglePCBModuleID"; const QString ModuleIDNames::EllipsePCBModuleIDName = "EllipsePCBModuleID"; const QString ModuleIDNames::TwoSidedEllipsePCBModuleIDName = "TwoLayerEllipsePCBModuleID"; const QString ModuleIDNames::NoteModuleIDName = "NoteModuleID"; const QString ModuleIDNames::WireModuleIDName = "WireModuleID"; const QString ModuleIDNames::JumperModuleIDName = "JumperModuleID"; const QString ModuleIDNames::GroundPlaneModuleIDName = "GroundPlaneModuleID"; const QString ModuleIDNames::GroundModuleIDName = "GroundModuleID"; const QString ModuleIDNames::PowerModuleIDName = "PowerModuleID"; const QString ModuleIDNames::TwoPowerModuleIDName = "2PowerModuleID"; const QString ModuleIDNames::NetLabelModuleIDName = "NetLabelModuleID"; const QString ModuleIDNames::PowerLabelModuleIDName = "PowerLabelModuleID"; const QString ModuleIDNames::LeftNetLabelModuleIDName = "LeftNetLabelModuleID"; const QString ModuleIDNames::JustPowerModuleIDName = "JustPowerModuleID"; const QString ModuleIDNames::ResistorModuleIDName = "ResistorModuleID"; const QString ModuleIDNames::LogoTextModuleIDName = "LogoTextModuleID"; const QString ModuleIDNames::LogoImageModuleIDName = "LogoImageModuleID"; const QString ModuleIDNames::Silkscreen0LogoImageModuleIDName = "Silkscreen0LogoImageModuleID"; const QString ModuleIDNames::Copper1LogoTextModuleIDName = "Copper1LogoTextModuleID"; const QString ModuleIDNames::Copper1LogoImageModuleIDName = "Copper1LogoImageModuleID"; const QString ModuleIDNames::Copper0LogoTextModuleIDName = "Copper0LogoTextModuleID"; const QString ModuleIDNames::Copper0LogoImageModuleIDName = "Copper0LogoImageModuleID"; const QString ModuleIDNames::SchematicLogoTextModuleIDName = "SchematicLogoTextModuleID"; const QString ModuleIDNames::SchematicLogoImageModuleIDName = "SchematicLogoImageModuleID"; const QString ModuleIDNames::BreadboardLogoTextModuleIDName = "BreadboardLogoTextModuleID"; const QString ModuleIDNames::BreadboardLogoImageModuleIDName = "BreadboardLogoImageModuleID"; const QString ModuleIDNames::BoardLogoImageModuleIDName = "BoardLogoImageModuleID"; const QString ModuleIDNames::OneLayerBoardLogoImageModuleIDName = "OneLayerBoardLogoImageModuleID"; const QString ModuleIDNames::HoleModuleIDName = "HoleModuleID"; const QString ModuleIDNames::ViaModuleIDName = "ViaModuleID"; const QString ModuleIDNames::PadModuleIDName = "PadModuleID"; const QString ModuleIDNames::Copper0PadModuleIDName = "Copper0PadModuleID"; const QString ModuleIDNames::CapacitorModuleIDName = "CapacitorModuleID"; const QString ModuleIDNames::CrystalModuleIDName = "CrystalModuleID"; const QString ModuleIDNames::ZenerDiodeModuleIDName = "ZenerDiodeModuleID"; const QString ModuleIDNames::ThermistorModuleIDName = "ThermistorModuleID"; const QString ModuleIDNames::PotentiometerModuleIDName = "PotentiometerModuleID"; const QString ModuleIDNames::InductorModuleIDName = "InductorModuleID"; const QString ModuleIDNames::LEDModuleIDName = "LEDModuleID"; const QString ModuleIDNames::ColorFluxLEDModuleIDName = "LEDSuperfluxModuleID"; const QString ModuleIDNames::ColorLEDModuleIDName = "ColorLEDModuleID"; const QString ModuleIDNames::PerfboardModuleIDName = "PerfboardModuleID"; const QString ModuleIDNames::StripboardModuleIDName = "StripboardModuleID"; const QString ModuleIDNames::Stripboard2ModuleIDName = "Stripboard2ModuleID"; const QString ModuleIDNames::SpacerModuleIDName = "__spacer__"; const QString ModuleIDNames::SchematicFrameModuleIDName = "SchematicFrameModuleID"; const QString ModuleIDNames::CopperBlockerModuleIDName = "BlockerModuleID"; const QString ModuleIDNames::Copper0BlockerModuleIDName = "Copper0BlockerModuleID"; const QString ModuleIDNames::Copper1BlockerModuleIDName = "Copper1BlockerModuleID"; fritzing-app-0.9.2b/src/items/moduleidnames.h000066400000000000000000000071641250202676700212240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Licensetriple along with Fritzing. If not, see . ******************************************************************** $Revision: 6947 $: $Author: irascibl@gmail.com $: $Date: 2013-04-03 06:45:22 +0200 (Mi, 03. Apr 2013) $ ********************************************************************/ #ifndef MODULEIDNAMES_H #define MODULEIDNAMES_H #include class ModuleIDNames { public: static const QString ModuleIDNameSuffix; static const QString RulerModuleIDName; static const QString BreadboardModuleIDName; static const QString FullPlusBreadboardModuleIDName; static const QString RectanglePCBModuleIDName; static const QString TwoSidedRectanglePCBModuleIDName; static const QString EllipsePCBModuleIDName; static const QString TwoSidedEllipsePCBModuleIDName; static const QString NoteModuleIDName; static const QString WireModuleIDName; static const QString JumperModuleIDName; static const QString GroundPlaneModuleIDName; static const QString GroundModuleIDName; static const QString PowerModuleIDName; static const QString TwoPowerModuleIDName; static const QString NetLabelModuleIDName; static const QString PowerLabelModuleIDName; static const QString LeftNetLabelModuleIDName; static const QString JustPowerModuleIDName; static const QString ResistorModuleIDName; static const QString LogoTextModuleIDName; static const QString LogoImageModuleIDName; static const QString Silkscreen0LogoImageModuleIDName; static const QString Copper0LogoTextModuleIDName; static const QString Copper0LogoImageModuleIDName; static const QString Copper1LogoTextModuleIDName; static const QString Copper1LogoImageModuleIDName; static const QString SchematicLogoTextModuleIDName; static const QString SchematicLogoImageModuleIDName; static const QString BreadboardLogoTextModuleIDName; static const QString BreadboardLogoImageModuleIDName; static const QString BoardLogoImageModuleIDName; static const QString OneLayerBoardLogoImageModuleIDName; static const QString HoleModuleIDName; static const QString ViaModuleIDName; static const QString PadModuleIDName; static const QString Copper0PadModuleIDName; static const QString CapacitorModuleIDName; static const QString CrystalModuleIDName; static const QString ZenerDiodeModuleIDName; static const QString ThermistorModuleIDName; static const QString PotentiometerModuleIDName; static const QString InductorModuleIDName; static const QString LEDModuleIDName; static const QString ColorLEDModuleIDName; static const QString ColorFluxLEDModuleIDName; static const QString PerfboardModuleIDName; static const QString StripboardModuleIDName; static const QString Stripboard2ModuleIDName; static const QString SpacerModuleIDName; static const QString SchematicFrameModuleIDName; static const QString CopperBlockerModuleIDName; static const QString Copper1BlockerModuleIDName; static const QString Copper0BlockerModuleIDName; }; #endif fritzing-app-0.9.2b/src/items/mysterypart.cpp000066400000000000000000000577541250202676700213460ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "mysterypart.h" #include "../utils/graphicsutils.h" #include "../utils/familypropertycombobox.h" #include "../utils/schematicrectconstants.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../commands.h" #include "../utils/textutils.h" #include "../layerattributes.h" #include "partlabel.h" #include "pinheader.h" #include "partfactory.h" #include "../connectors/connectoritem.h" #include "../svg/svgfilesplitter.h" #include #include #include #include static QStringList Spacings; static QRegExp Digits("(\\d)+"); static QRegExp DigitsMil("(\\d)+mil"); static const int MinSipPins = 1; static const int MaxSipPins = 128; static const int MinDipPins = 4; static const int MaxDipPins = 128; static HoleClassThing TheHoleThing; // TODO // save into parts bin MysteryPart::MysteryPart( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_chipLabel = modelPart->localProp("chip label").toString(); if (m_chipLabel.isEmpty()) { m_chipLabel = modelPart->properties().value("chip label", "?"); modelPart->setLocalProp("chip label", m_chipLabel); } setUpHoleSizes("mystery", TheHoleThing); } MysteryPart::~MysteryPart() { } void MysteryPart::setProp(const QString & prop, const QString & value) { if (prop.compare("chip label", Qt::CaseInsensitive) == 0) { setChipLabel(value, false); return; } PaletteItem::setProp(prop, value); } void MysteryPart::setChipLabel(QString chipLabel, bool force) { if (!force && m_chipLabel.compare(chipLabel) == 0) return; m_chipLabel = chipLabel; QString svg; switch (this->m_viewID) { case ViewLayer::BreadboardView: svg = makeSvg(chipLabel, true); if (!svg.isEmpty()) { resetRenderer(svg); } break; case ViewLayer::SchematicView: { QTransform transform = untransform(); svg = makeSvg(chipLabel, false); svg = retrieveSchematicSvg(svg); resetLayerKin(svg); retransform(transform); } break; default: break; } modelPart()->setLocalProp("chip label", chipLabel); if (m_partLabel) m_partLabel->displayTextsIf(); } QString MysteryPart::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString svg = PaletteItem::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); switch (viewLayerID) { case ViewLayer::Breadboard: case ViewLayer::Icon: return TextUtils::replaceTextElement(svg, "label", m_chipLabel); case ViewLayer::Schematic: svg = retrieveSchematicSvg(svg); return TextUtils::removeSVGHeader(svg); default: break; } return svg; } QString MysteryPart::retrieveSchematicSvg(QString & svg) { bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (hasLocal) { svg = makeSchematicSvg(labels, false); } return TextUtils::replaceTextElement(svg, "label", m_chipLabel); } QString MysteryPart::makeSvg(const QString & chipLabel, bool replace) { QString path = filename(); QFile file(filename()); QString svg; if (file.open(QFile::ReadOnly)) { svg = file.readAll(); file.close(); if (!replace) return svg; return TextUtils::replaceTextElement(svg, "label", chipLabel); } return ""; } QStringList MysteryPart::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("layout", Qt::CaseInsensitive) == 0) { // TODO: translate these QStringList values; values << "Single Row" << "Double Row"; value = values.at(moduleID().contains("sip", Qt::CaseInsensitive) ? 0 : 1); return values; } if (prop.compare("pin spacing", Qt::CaseInsensitive) == 0) { QStringList values; QString spacing; TextUtils::getPinsAndSpacing(moduleID(), spacing); if (isDIP()) { foreach (QString f, spacings()) { values.append(f); } } else { values.append(spacing); } value = spacing; return values; } if (prop.compare("pins", Qt::CaseInsensitive) == 0) { QStringList values; value = modelPart()->properties().value("pins"); if (moduleID().contains("dip")) { for (int i = MinDipPins; i <= MaxDipPins; i += 2) { values << QString::number(i); } } else { for (int i = MinSipPins; i <= MaxSipPins; i++) { values << QString::number(i); } } return values; } return PaletteItem::collectValues(family, prop, value); } bool MysteryPart::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("chip label", Qt::CaseInsensitive) == 0) { returnProp = tr("label"); returnValue = m_chipLabel; QLineEdit * e1 = new QLineEdit(parent); e1->setEnabled(swappingEnabled); e1->setText(m_chipLabel); connect(e1, SIGNAL(editingFinished()), this, SLOT(chipLabelEntry())); e1->setObjectName("infoViewLineEdit"); returnWidget = e1; return true; } if (prop.compare("hole size", Qt::CaseInsensitive) == 0) { return collectHoleSizeInfo(TheHoleThing.holeSizeValue, parent, swappingEnabled, returnProp, returnValue, returnWidget); } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } QString MysteryPart::getProperty(const QString & key) { if (key.compare("chip label", Qt::CaseInsensitive) == 0) { return m_chipLabel; } return PaletteItem::getProperty(key); } QString MysteryPart::chipLabel() { return m_chipLabel; } void MysteryPart::addedToScene(bool temporary) { if (this->scene()) { setChipLabel(m_chipLabel, true); } PaletteItem::addedToScene(temporary); } const QString & MysteryPart::title() { return m_chipLabel; } bool MysteryPart::hasCustomSVG() { switch (m_viewID) { case ViewLayer::BreadboardView: case ViewLayer::SchematicView: case ViewLayer::IconView: case ViewLayer::PCBView: return true; default: return ItemBase::hasCustomSVG(); } } void MysteryPart::chipLabelEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; if (edit->text().compare(this->chipLabel()) == 0) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "chip label", tr("chip label"), this->chipLabel(), edit->text(), true); } } bool MysteryPart::isDIP() { QString layout = modelPart()->properties().value("layout", ""); return (layout.indexOf("double", 0, Qt::CaseInsensitive) >= 0); } bool MysteryPart::otherPropsChange(const QMap & propsMap) { QString layout = modelPart()->properties().value("layout", ""); return (layout.compare(propsMap.value("layout", "")) != 0); } const QStringList & MysteryPart::spacings() { if (Spacings.count() == 0) { Spacings << "100mil" << "200mil" << "300mil" << "400mil" << "500mil" << "600mil" << "700mil" << "800mil" << "900mil"; } return Spacings; } ItemBase::PluralType MysteryPart::isPlural() { return Plural; } QString MysteryPart::genSipFZP(const QString & moduleid) { return genxFZP(moduleid, "mystery_part_sipFzpTemplate", MinSipPins, MaxSipPins, 1); } QString MysteryPart::genDipFZP(const QString & moduleid) { return genxFZP(moduleid, "mystery_part_dipFzpTemplate", MinDipPins, MaxDipPins, 2); } QString MysteryPart::genxFZP(const QString & moduleid, const QString & templateName, int minPins, int maxPins, int step) { QString spacingString; TextUtils::getPinsAndSpacing(moduleid, spacingString); QString result = PaletteItem::genFZP(moduleid, templateName, minPins, maxPins, step, false); result.replace(".percent.", "%"); result = result.arg(spacingString); return hackFzpHoleSize(result, moduleid); } QString MysteryPart::hackFzpHoleSize(const QString & fzp, const QString & moduleid) { int hsix = moduleid.lastIndexOf(HoleSizePrefix); if (hsix >= 0) { return PaletteItem::hackFzpHoleSize(fzp, moduleid, hsix); } return fzp; } QString MysteryPart::genModuleID(QMap & currPropsMap) { QString value = currPropsMap.value("layout"); bool single = value.contains("single", Qt::CaseInsensitive); QString pins = currPropsMap.value("pins"); QString spacing = currPropsMap.value("pin spacing", "300mil"); if (single) { return QString("mystery_part_sip_%1_100mil").arg(pins); } else { int p = pins.toInt(); if (p < 4) p = 4; if (p % 2 == 1) p--; return QString("mystery_part_dip_%1_%2").arg(p).arg(spacing); } } QString MysteryPart::makeSchematicSvg(const QString & expectedFileName) { bool sip = expectedFileName.contains("sip", Qt::CaseInsensitive); QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(2).toInt(); QStringList labels; for (int i = 0; i < pins; i++) { labels << QString::number(i + 1); } if (expectedFileName.contains(PartFactory::OldSchematicPrefix)) { return obsoleteMakeSchematicSvg(labels, sip); } return makeSchematicSvg(labels, sip); } QString MysteryPart::makeSchematicSvg(const QStringList & labels, bool sip) { QDomDocument fakeDoc; QList lefts; for (int i = 0; i < labels.count(); i++) { QDomElement element = fakeDoc.createElement("contact"); element.setAttribute("connectorIndex", i); element.setAttribute("name", labels.at(i)); lefts.append(element); } QList empty; QStringList busNames; QString titleText = sip ? "IC" : "?"; QString svg = SchematicRectConstants::genSchematicDIP(empty, empty, lefts, empty, empty, busNames, titleText, false, false, SchematicRectConstants::simpleGetConnectorName); if (sip) return svg; // add the mystery part graphic QDomDocument doc; if (!doc.setContent(svg)) return svg; QRectF viewBox; double w, h; TextUtils::ensureViewBox(doc, GraphicsUtils::StandardFritzingDPI, viewBox, false, w, h, false); double newUnit = 1000 * SchematicRectConstants::NewUnit / 25.4; double rectStroke = 2 * 1000 * SchematicRectConstants::RectStrokeWidth / 25.4; QString circle = QString("\n"); circle += QString("?\n"); circle = circle .arg(viewBox.width() - rectStroke - (newUnit / 2)) .arg(rectStroke + (newUnit / 2)) .arg(newUnit / 2) .arg(rectStroke + (newUnit / 2) + (newUnit / 3)) // offset so the text appears in the center of the circle .arg(SchematicRectConstants::FontFamily) .arg(newUnit) ; QDomDocument temp; temp.setContent(QString("" + circle + "")); QDomElement root = doc.documentElement(); QDomElement schematic = TextUtils::findElementWithAttribute(root, "id", "schematic"); if (schematic.isNull()) return svg; QDomElement tempRoot = temp.documentElement(); schematic.appendChild(tempRoot); return doc.toString(1); } QString MysteryPart::obsoleteMakeSchematicSvg(const QStringList & labels, bool sip) { int increment = GraphicsUtils::StandardSchematicSeparationMils; // 7.5mm; int border = 30; double totalHeight = (labels.count() * increment) + increment + border; int textOffset = 50; int repeatTextOffset = 50; int fontSize = 255; int labelFontSize = 130; int defaultLabelWidth = 30; QString labelText = "?"; double textMax = defaultLabelWidth; QFont font("Droid Sans", labelFontSize * 72 / GraphicsUtils::StandardFritzingDPI, QFont::Normal); QFontMetricsF fm(font); for (int i = 0; i < labels.count(); i++) { double w = fm.width(labels.at(i)); if (w > textMax) textMax = w; } textMax = textMax * GraphicsUtils::StandardFritzingDPI / 72; int totalWidth = (5 * increment) + border; int innerWidth = 4 * increment; if (textMax > defaultLabelWidth) { totalWidth += (textMax - defaultLabelWidth); innerWidth += (textMax - defaultLabelWidth); } QString header("\n" "\n" "\n" "\n" "%6\n"); if (!sip) { header += "\n" "?\n"; } else { labelText = "IC"; fontSize = 235; textOffset = 0; } QString svg = header .arg(totalHeight / GraphicsUtils::StandardFritzingDPI) .arg(totalHeight) .arg(totalHeight - border) .arg((totalHeight / 2) + textOffset) .arg(fontSize) .arg(labelText) .arg(totalWidth / 1000.0) .arg(totalWidth) .arg(innerWidth) .arg(totalWidth - 200) .arg(increment + textMax + ((totalWidth - increment - textMax) / 2.0)) ; QString repeat("\n" "\n" "\n" "%5\n"); for (int i = 0; i < labels.count(); i++) { svg += repeat .arg(increment + (border / 2) + (i * increment)) .arg(increment + (i * increment)) .arg(i) .arg(increment + repeatTextOffset + (i * increment)) .arg(labels.at(i)) .arg(labelFontSize); } svg += "\n"; svg += "\n"; return svg; } QString MysteryPart::makeBreadboardSvg(const QString & expectedFileName) { if (expectedFileName.contains("_sip_")) return makeBreadboardSipSvg(expectedFileName); if (expectedFileName.contains("_dip_")) return makeBreadboardDipSvg(expectedFileName); return ""; } QString MysteryPart::makeBreadboardDipSvg(const QString & expectedFileName) { QString spacingString; int pins = TextUtils::getPinsAndSpacing(expectedFileName, spacingString); double spacing = TextUtils::convertToInches(spacingString) * 100; int increment = 10; QString repeatT("\n" "\n"); QString repeatB("\n" "\n"); QString header("\n" "\n" "\n" ".percent.2\n" "\n" "\n" "?\n" "\n" "?\n" ".percent.3\n" "\n" "\n"); header = TextUtils::incrementTemplateString(header, 1, spacing - increment, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); header = header.arg(TextUtils::getViewBoxCoord(header, 3) / 100.0); if (spacing == 10) { header.replace("{{6.0}}", "8.0"); header.replace("{{7.5}}", "5.5"); header.replace("{{9.2}}", "7.2"); } else { header.replace("{{6.0}}", QString::number(6.0 + ((spacing - increment) / 2))); header.replace("{{7.5}}", "7.5"); header.replace("{{9.2}}", "9.2"); } header.replace(".percent.", "%"); header.replace("{", "["); header.replace("}", "]"); QString svg = TextUtils::incrementTemplateString(header, 1, increment * ((pins - 4) / 2), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); repeatB = TextUtils::incrementTemplateString(repeatB, 1, spacing - increment, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); repeatB.replace("{", "["); repeatB.replace("}", "]"); int userData[2]; userData[0] = pins; userData[1] = 1; QString repeatTs = TextUtils::incrementTemplateString(repeatT, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::negIncCopyPinFunction, userData); QString repeatBs = TextUtils::incrementTemplateString(repeatB, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); return svg.arg(TextUtils::getViewBoxCoord(svg, 2) / 100).arg(repeatTs).arg(repeatBs); } QString MysteryPart::makeBreadboardSipSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() != 6) return ""; int pins = pieces.at(2).toInt(); int increment = 10; QString header("\n" "\n" "\n" "\n" "\n" "?\n" "\n" "?\n" "%2\n" "\n" "\n"); QString svg = TextUtils::incrementTemplateString(header, 1, increment * (pins - 1), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); QString repeat("\n" "\n"); QString repeats = TextUtils::incrementTemplateString(repeat, pins, increment, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); return svg.arg(TextUtils::getViewBoxCoord(svg, 2) / 100).arg(repeats); } bool MysteryPart::changePinLabels(bool singleRow, bool sip) { Q_UNUSED(singleRow); if (m_viewID != ViewLayer::SchematicView) return true; bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (labels.count() == 0) return true; QTransform transform = untransform(); QString svg = MysteryPart::makeSchematicSvg(labels, sip); QString chipLabel = modelPart()->localProp("chip label").toString(); if (!chipLabel.isEmpty()) { svg =TextUtils::replaceTextElement(svg, "label", chipLabel); } resetLayerKin(svg); retransform(transform); return true; } void MysteryPart::swapEntry(const QString & text) { FamilyPropertyComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; QString layout = m_propsMap.value("layout"); if (comboBox->prop().contains("layout", Qt::CaseInsensitive)) { layout = text; } if (layout.isEmpty()) { if (moduleID().contains("sip", Qt::CaseInsensitive)) { layout = "single"; } } if (layout.contains("single", Qt::CaseInsensitive)) { generateSwap(text, genModuleID, genSipFZP, makeBreadboardSvg, makeSchematicSvg, PinHeader::makePcbSvg); } else { generateSwap(text, genModuleID, genDipFZP, makeBreadboardSvg, makeSchematicSvg, makePcbDipSvg); } PaletteItem::swapEntry(text); } QString MysteryPart::makePcbDipSvg(const QString & expectedFileName) { QString spacingString; int pins = TextUtils::getPinsAndSpacing(expectedFileName, spacingString); if (pins == 0) return ""; QString header("\n" "\n" "Fritzing footprint SVG\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"); double outerBorder = 10; double silkSplitTop = 100; double offsetX = 60; double offsetY = 60; double spacing = TextUtils::convertToInches(spacingString) * GraphicsUtils::StandardFritzingDPI; double totalWidth = 120 + spacing; double totalHeight = (100 * pins / 2) + (outerBorder * 2); double center = totalWidth / 2; QString svg = header.arg(totalWidth / GraphicsUtils::StandardFritzingDPI).arg(totalHeight / GraphicsUtils::StandardFritzingDPI).arg(totalWidth).arg(totalHeight) .arg(totalHeight - outerBorder).arg(totalWidth - outerBorder) .arg(center - (silkSplitTop / 2)).arg(center + (silkSplitTop / 2)); QString circle("\n"); int y = offsetY; for (int i = 0; i < pins / 2; i++) { svg += circle.arg(offsetX).arg(y).arg(i); svg += circle.arg(totalWidth - offsetX).arg(y).arg(pins - 1 - i); y += 100; } svg += "\n"; svg += "\n"; int hsix = expectedFileName.indexOf(HoleSizePrefix); if (hsix >= 0) { return hackSvgHoleSizeAux(svg, expectedFileName); } return svg; } fritzing-app-0.9.2b/src/items/mysterypart.h000066400000000000000000000070531250202676700207760ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef MYSTERYPART_H #define MYSTERYPART_H #include #include #include #include #include "paletteitem.h" class MysteryPart : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call MysteryPart(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~MysteryPart(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); QString getProperty(const QString & key); void setProp(const QString & prop, const QString & value); void setChipLabel(QString label, bool force); QString chipLabel(); const QString & title(); bool hasCustomSVG(); PluralType isPlural(); void addedToScene(bool temporary); bool changePinLabels(bool singleRow, bool sip); public slots: void chipLabelEntry(); void swapEntry(const QString & text); public: static QString genSipFZP(const QString & moduleid); static QString genDipFZP(const QString & moduleid); static QString genModuleID(QMap & currPropsMap); static QString makeSchematicSvg(const QString & expectedFileName); static QString makeSchematicSvg(const QStringList & labels, bool sip); static QString obsoleteMakeSchematicSvg(const QStringList & labels, bool sip); static QString makeBreadboardSvg(const QString & expectedFileName); static QString makeBreadboardSipSvg(const QString & expectedFileName); static QString makeBreadboardDipSvg(const QString & expectedFileName); static QString makePcbDipSvg(const QString & expectedFileName); protected: QString makeSvg(const QString & chipLabel, bool replace); QStringList collectValues(const QString & family, const QString & prop, QString & value); virtual bool isDIP(); virtual bool otherPropsChange(const QMap & propsMap); virtual const QStringList & spacings(); virtual QString retrieveSchematicSvg(QString & svg); protected: static QString hackFzpHoleSize(const QString & fzp, const QString & moduleid); static QString genxFZP(const QString & moduleid, const QString & templateName, int minPins, int maxPins, int step); protected: static int NoExcusePins; protected: QString m_chipLabel; QString m_title; }; #endif fritzing-app-0.9.2b/src/items/note.cpp000066400000000000000000000601261250202676700176730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "note.h" #include "../debugdialog.h" #include "../sketch/infographicsview.h" #include "../model/modelpart.h" #include "../utils/resizehandle.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include #include #include #include #include #include #include #include #include #include #include // TODO: // ** search for ModelPart:: and fix up // check which menu items don't apply // ** selection // ** delete // ** move // ** undo delete + text // ** resize // ** undo resize // anchor // ** undo change text // ** undo selection // ** undo move // ** layers and z order // ** hide and show layer // ** save and load // format: bold, italic, size (small normal large huge), color?, // undo format // heads-up controls // copy/paste // ** z-order manipulation // hover // ** multiple selection // ** icon in taskbar (why does it show up as text until you update it?) const int Note::emptyMinWidth = 40; const int Note::emptyMinHeight = 25; const int Note::initialMinWidth = 140; const int Note::initialMinHeight = 45; const int borderWidth = 7; const int TriangleOffset = 7; const double InactiveOpacity = 0.5; QString Note::initialTextString; QRegExp UrlTag(""); /////////////////////////////////////// void findA(QDomElement element, QList & aElements) { if (element.tagName().compare("a", Qt::CaseInsensitive) == 0) { aElements.append(element); return; } QDomElement c = element.firstChildElement(); while (!c.isNull()) { findA(c, aElements); c = c.nextSiblingElement(); } } QString addText(const QString & text, bool inUrl) { if (text.isEmpty()) return ""; return QString("%2\n") .arg(inUrl ? "#0000ff" : "#000000") .arg(TextUtils::convertExtendedChars(TextUtils::escapeAnd(text))) ; } /////////////////////////////////////// class NoteGraphicsTextItem : public QGraphicsTextItem { public: NoteGraphicsTextItem(QGraphicsItem * parent = NULL); protected: void focusInEvent(QFocusEvent *); void focusOutEvent(QFocusEvent *); }; NoteGraphicsTextItem::NoteGraphicsTextItem(QGraphicsItem * parent) : QGraphicsTextItem(parent) { const QTextFrameFormat format = document()->rootFrame()->frameFormat(); QTextFrameFormat altFormat(format); altFormat.setMargin(0); // so document never thinks a mouse click is a move event document()->rootFrame()->setFrameFormat(altFormat); } void NoteGraphicsTextItem::focusInEvent(QFocusEvent * event) { InfoGraphicsView * igv = InfoGraphicsView::getInfoGraphicsView(this); if (igv != NULL) { igv->setNoteFocus(this, true); } QApplication::instance()->installEventFilter((Note *) this->parentItem()); QGraphicsTextItem::focusInEvent(event); DebugDialog::debug("note focus in"); } void NoteGraphicsTextItem::focusOutEvent(QFocusEvent * event) { InfoGraphicsView * igv = InfoGraphicsView::getInfoGraphicsView(this); if (igv != NULL) { igv->setNoteFocus(this, false); } QApplication::instance()->removeEventFilter((Note *) this->parentItem()); QGraphicsTextItem::focusOutEvent(event); DebugDialog::debug("note focus out"); } ////////////////////////////////////////// LinkDialog::LinkDialog(QWidget *parent) : QDialog(parent) { this->setWindowTitle(QObject::tr("Edit link")); QVBoxLayout * vLayout = new QVBoxLayout(this); QGroupBox * formGroupBox = new QGroupBox(this); QFormLayout * formLayout = new QFormLayout(); m_urlEdit = new QLineEdit(this); m_urlEdit->setFixedHeight(25); m_urlEdit->setFixedWidth(200); formLayout->addRow(tr("url:"), m_urlEdit ); m_textEdit = new QLineEdit(this); m_textEdit->setFixedHeight(25); m_textEdit->setFixedWidth(200); formLayout->addRow(tr("text:"), m_textEdit ); formGroupBox->setLayout(formLayout); vLayout->addWidget(formGroupBox); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } LinkDialog::~LinkDialog() { } void LinkDialog::setText(const QString & text) { m_textEdit->setText(text); } void LinkDialog::setUrl(const QString & url) { m_urlEdit->setText(url); } QString LinkDialog::text() { return m_textEdit->text(); } QString LinkDialog::url() { return m_urlEdit->text(); } ///////////////////////////////////////////// Note::Note( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu* itemMenu) : ItemBase(modelPart, viewID, viewGeometry, id, itemMenu) { m_charsAdded = 0; if (initialTextString.isEmpty()) { initialTextString = tr("[write your note here]"); } m_inResize = NULL; this->setCursor(Qt::ArrowCursor); setFlag(QGraphicsItem::ItemIsSelectable, true); if (viewGeometry.rect().width() == 0 || viewGeometry.rect().height() == 0) { m_rect.setRect(0, 0, Note::initialMinWidth, Note::initialMinHeight); } else { m_rect.setRect(0, 0, viewGeometry.rect().width(), viewGeometry.rect().height()); } m_pen.setWidth(borderWidth); m_pen.setCosmetic(false); m_pen.setBrush(QColor(0xfa, 0xbc, 0x4f)); m_brush.setColor(QColor(0xff, 0xe9, 0xc8)); m_brush.setStyle(Qt::SolidPattern); setPos(m_viewGeometry.loc()); QPixmap pixmap(":/resources/images/icons/noteResizeGrip.png"); m_resizeGrip = new ResizeHandle(pixmap, Qt::SizeFDiagCursor, false, this); connect(m_resizeGrip, SIGNAL(mousePressSignal(QGraphicsSceneMouseEvent *, ResizeHandle *)), this, SLOT(handleMousePressSlot(QGraphicsSceneMouseEvent *, ResizeHandle *))); connect(m_resizeGrip, SIGNAL(mouseMoveSignal(QGraphicsSceneMouseEvent *, ResizeHandle *)), this, SLOT(handleMouseMoveSlot(QGraphicsSceneMouseEvent *, ResizeHandle *))); connect(m_resizeGrip, SIGNAL(mouseReleaseSignal(QGraphicsSceneMouseEvent *, ResizeHandle *)), this, SLOT(handleMouseReleaseSlot(QGraphicsSceneMouseEvent *, ResizeHandle *))); //connect(m_resizeGrip, SIGNAL(zoomChangedSignal(double)), this, SLOT(handleZoomChangedSlot(double))); m_graphicsTextItem = new NoteGraphicsTextItem(); QFont font("Droid Sans", 9, QFont::Normal); m_graphicsTextItem->setFont(font); m_graphicsTextItem->document()->setDefaultFont(font); m_graphicsTextItem->setParentItem(this); m_graphicsTextItem->setVisible(true); m_graphicsTextItem->setPlainText(initialTextString); m_graphicsTextItem->setTextInteractionFlags(Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard); m_graphicsTextItem->setCursor(Qt::IBeamCursor); m_graphicsTextItem->setOpenExternalLinks(true); connectSlots(); positionGrip(); setAcceptHoverEvents(true); } void Note::saveGeometry() { m_viewGeometry.setRect(boundingRect()); m_viewGeometry.setLoc(this->pos()); m_viewGeometry.setSelected(this->isSelected()); m_viewGeometry.setZ(this->zValue()); } bool Note::itemMoved() { return (this->pos() != m_viewGeometry.loc()); } void Note::saveInstanceLocation(QXmlStreamWriter & streamWriter) { QRectF rect = m_viewGeometry.rect(); QPointF loc = m_viewGeometry.loc(); streamWriter.writeAttribute("x", QString::number(loc.x())); streamWriter.writeAttribute("y", QString::number(loc.y())); streamWriter.writeAttribute("width", QString::number(rect.width())); streamWriter.writeAttribute("height", QString::number(rect.height())); } void Note::moveItem(ViewGeometry & viewGeometry) { this->setPos(viewGeometry.loc()); } void Note::findConnectorsUnder() { } void Note::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); if (m_hidden) return; if (m_inactive) { painter->save(); painter->setOpacity(InactiveOpacity); } painter->setPen(Qt::NoPen); painter->setBrush(m_brush); QPolygonF poly; poly.append(m_rect.topLeft()); poly.append(m_rect.topRight() + QPointF(-TriangleOffset, 0)); poly.append(m_rect.topRight() + QPointF(0, TriangleOffset)); poly.append(m_rect.bottomRight()); poly.append(m_rect.bottomLeft()); painter->drawPolygon(poly); painter->setBrush(m_pen.brush()); poly.clear(); poly.append(m_rect.topRight() + QPointF(-TriangleOffset, 0)); poly.append(m_rect.topRight() + QPointF(0, TriangleOffset)); poly.append(m_rect.topRight() + QPointF(-TriangleOffset, TriangleOffset)); painter->drawPolygon(poly); painter->setPen(m_pen); poly.clear(); poly.append(QPointF(0, m_rect.bottom() - borderWidth / 2.0)); poly.append(QPointF(m_rect.right(), m_rect.bottom() - borderWidth / 2.0)); painter->drawPolygon(poly); if (option->state & QStyle::State_Selected) { GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, boundingRect(), QPainterPath()); } if (m_inactive) { painter->restore(); } } QRectF Note::boundingRect() const { return m_rect; } QPainterPath Note::shape() const { QPainterPath path; path.addRect(boundingRect()); return path; } void Note::positionGrip() { QSizeF gripSize = m_resizeGrip->boundingRect().size(); QSizeF sz = this->boundingRect().size(); QPointF p(sz.width() - gripSize.width(), sz.height() - gripSize.height()); m_resizeGrip->setPos(p); m_graphicsTextItem->setPos(TriangleOffset / 2, TriangleOffset / 2); m_graphicsTextItem->setTextWidth(sz.width() - TriangleOffset); } void Note::mousePressEvent(QGraphicsSceneMouseEvent * event) { InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL && infographics->spaceBarIsPressed()) { m_spaceBarWasPressed = true; event->ignore(); return; } m_spaceBarWasPressed = false; m_inResize = NULL; ItemBase::mousePressEvent(event); } void Note::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { if (m_spaceBarWasPressed) { event->ignore(); return; } ItemBase::mouseMoveEvent(event); } void Note::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) { if (m_spaceBarWasPressed) { event->ignore(); return; } ItemBase::mouseReleaseEvent(event); } void Note::contentsChangeSlot(int position, int charsRemoved, int charsAdded) { Q_UNUSED(charsRemoved); m_charsAdded = charsAdded; m_charsPosition = position; } void Note::forceFormat(int position, int charsAdded) { disconnectSlots(); QTextCursor textCursor = m_graphicsTextItem->textCursor(); QTextCharFormat f; QFont font("Droid Sans", 9, QFont::Normal); f.setFont(font); f.setFontFamily("Droid Sans"); f.setFontPointSize(9); int cc = m_graphicsTextItem->document()->characterCount(); textCursor.setPosition(position, QTextCursor::MoveAnchor); if (position + charsAdded >= cc) { charsAdded--; } textCursor.setPosition(position + charsAdded, QTextCursor::KeepAnchor); //textCursor.setCharFormat(f); textCursor.mergeCharFormat(f); //DebugDialog::debug(QString("setting font tc:%1,%2 params:%3,%4") //.arg(textCursor.anchor()).arg(textCursor.position()) //.arg(position).arg(position + charsAdded)); /* textCursor = m_graphicsTextItem->textCursor(); for (int i = 0; i < charsAdded; i++) { textCursor.setPosition(position + i, QTextCursor::MoveAnchor); f = textCursor.charFormat(); DebugDialog::debug(QString("1format %1 %2 %3").arg(f.fontPointSize()).arg(f.fontFamily()).arg(f.fontWeight())); //f.setFont(font); //f.setFontPointSize(9); //f.setFontWeight(QFont::Normal); //textCursor.setCharFormat(f); //QTextCharFormat g = textCursor.charFormat(); //DebugDialog::debug(QString("2format %1 %2 %3").arg(g.fontPointSize()).arg(g.fontFamily()).arg(g.fontWeight())); } */ connectSlots(); } void Note::contentsChangedSlot() { //DebugDialog::debug(QString("contents changed ") + m_graphicsTextItem->document()->toPlainText()); if (m_charsAdded > 0) { forceFormat(m_charsPosition, m_charsAdded); } InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { QString oldText; if (m_modelPart) { oldText = m_modelPart->instanceText(); } QSizeF oldSize = m_rect.size(); QSizeF newSize = oldSize; checkSize(newSize); infoGraphicsView->noteChanged(this, oldText, m_graphicsTextItem->document()->toHtml(), oldSize, newSize); } if (m_modelPart) { m_modelPart->setInstanceText(m_graphicsTextItem->document()->toHtml()); } } void Note::checkSize(QSizeF & newSize) { QSizeF gripSize = m_resizeGrip->boundingRect().size(); QSizeF size = m_graphicsTextItem->document()->size(); if (size.height() + gripSize.height() + gripSize.height() > m_rect.height()) { prepareGeometryChange(); m_rect.setHeight(size.height() + gripSize.height() + gripSize.height()); newSize.setHeight(m_rect.height()); positionGrip(); this->update(); } } void Note::disconnectSlots() { disconnect(m_graphicsTextItem->document(), SIGNAL(contentsChanged()), this, SLOT(contentsChangedSlot())); disconnect(m_graphicsTextItem->document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(contentsChangeSlot(int, int, int))); } void Note::connectSlots() { connect(m_graphicsTextItem->document(), SIGNAL(contentsChanged()), this, SLOT(contentsChangedSlot()), Qt::DirectConnection); connect(m_graphicsTextItem->document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(contentsChangeSlot(int, int, int)), Qt::DirectConnection); } void Note::setText(const QString & text, bool check) { // disconnect the signal so it doesn't fire recursively disconnectSlots(); QString oldText = text; m_graphicsTextItem->document()->setHtml(text); connectSlots(); if (check) { QSizeF newSize; checkSize(newSize); forceFormat(0, m_graphicsTextItem->document()->characterCount()); } } QString Note::text() { return m_graphicsTextItem->document()->toHtml(); } void Note::setSize(const QSizeF & size) { prepareGeometryChange(); m_rect.setWidth(size.width()); m_rect.setHeight(size.height()); positionGrip(); } void Note::setHidden(bool hide) { ItemBase::setHidden(hide); m_graphicsTextItem->setVisible(!hide); m_resizeGrip->setVisible(!hide); } void Note::setInactive(bool inactivate) { ItemBase::setInactive(inactivate); } bool Note::eventFilter(QObject * object, QEvent * event) { if (event->type() == QEvent::Shortcut || event->type() == QEvent::ShortcutOverride) { if (!object->inherits("QGraphicsView")) { event->accept(); return true; } } if (event->type() == QEvent::KeyPress) { QKeyEvent * kevent = static_cast(event); if (kevent->matches(QKeySequence::Bold)) { QTextCursor textCursor = m_graphicsTextItem->textCursor(); QTextCharFormat cf = textCursor.charFormat(); bool isBold = cf.fontWeight() == QFont::Bold; QTextCharFormat textCharFormat; textCharFormat.setFontWeight(isBold ? QFont::Normal : QFont::Bold); textCursor.mergeCharFormat(textCharFormat); event->accept(); return true; } if (kevent->matches(QKeySequence::Italic)) { QTextCursor textCursor = m_graphicsTextItem->textCursor(); QTextCharFormat cf = textCursor.charFormat(); QTextCharFormat textCharFormat; textCharFormat.setFontItalic(!cf.fontItalic()); textCursor.mergeCharFormat(textCharFormat); event->accept(); return true; } if ((kevent->key() == Qt::Key_L) && (kevent->modifiers() & Qt::ControlModifier)) { QTimer::singleShot(75, this, SLOT(linkDialog())); event->accept(); return true; } } return false; } void Note::linkDialog() { QTextCursor textCursor = m_graphicsTextItem->textCursor(); bool gotUrl = false; if (textCursor.anchor() == textCursor.selectionStart()) { // the selection returns empty since we're between characters // so select one character forward or one character backward // to see whether we're in a url int wasAnchor = textCursor.anchor(); bool atEnd = textCursor.atEnd(); bool atStart = textCursor.atStart(); if (!atStart) { textCursor.setPosition(wasAnchor - 1, QTextCursor::KeepAnchor); QString html = textCursor.selection().toHtml(); if (UrlTag.indexIn(html) >= 0) { gotUrl = true; } } if (!gotUrl && !atEnd) { textCursor.setPosition(wasAnchor + 1, QTextCursor::KeepAnchor); QString html = textCursor.selection().toHtml(); if (UrlTag.indexIn(html) >= 0) { gotUrl = true; } } textCursor.setPosition(wasAnchor, QTextCursor::MoveAnchor); } else { QString html = textCursor.selection().toHtml(); DebugDialog::debug(html); if (UrlTag.indexIn(html) >= 0) { gotUrl = true; } } LinkDialog ld; QString originalText; QString originalUrl; if (gotUrl) { originalUrl = UrlTag.cap(1); ld.setUrl(originalUrl); QString html = m_graphicsTextItem->toHtml(); // assumes html is in xml form QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(html, &errorStr, &errorLine, &errorColumn)) { return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { return; } if (root.tagName() != "html") { return; } DebugDialog::debug(html); QList aElements; findA(root, aElements); foreach (QDomElement a, aElements) { // TODO: if multiple hrefs point to the same url this will only find the first one QString href = a.attribute("href"); if (href.isEmpty()) { href = a.attribute("HREF"); } if (href.compare(originalUrl) == 0) { QString text; if (TextUtils::findText(a, text)) { ld.setText(text); break; } else { return; } } } } int result = ld.exec(); if (result == QDialog::Accepted) { if (gotUrl) { int from = 0; while (true) { QTextCursor cursor = m_graphicsTextItem->document()->find(originalText, from); if (cursor.isNull()) { // TODO: tell the user return; } QString html = cursor.selection().toHtml(); if (html.contains(originalUrl)) { cursor.insertHtml(QString("%2").arg(ld.url()).arg(ld.text())); break; } from = cursor.selectionEnd(); } } else { textCursor.insertHtml(QString("%2").arg(ld.url()).arg(ld.text())); } } } void Note::handleZoomChangedSlot(double scale) { Q_UNUSED(scale); positionGrip(); } void Note::handleMousePressSlot(QGraphicsSceneMouseEvent * event, ResizeHandle * resizeHandle) { if (m_spaceBarWasPressed) return; saveGeometry(); QSizeF sz = this->boundingRect().size(); resizeHandle->setResizeOffset(this->pos() + QPointF(sz.width(), sz.height()) - event->scenePos()); m_inResize = resizeHandle; } void Note::handleMouseMoveSlot(QGraphicsSceneMouseEvent * event, ResizeHandle * resizeHandle) { Q_UNUSED(resizeHandle); if (!m_inResize) return; double minWidth = emptyMinWidth; double minHeight = emptyMinHeight; QSizeF gripSize = m_resizeGrip->boundingRect().size(); QSizeF minSize = m_graphicsTextItem->document()->size() + gripSize + gripSize; if (minSize.height() > minHeight) minHeight = minSize.height(); QRectF rect = boundingRect(); rect.moveTopLeft(this->pos()); double oldX1 = rect.x(); double oldY1 = rect.y(); double newX = event->scenePos().x() + m_inResize->resizeOffset().x(); double newY = event->scenePos().y() + m_inResize->resizeOffset().y(); QRectF newR; if (newX - oldX1 < minWidth) { newX = oldX1 + minWidth; } if (newY - oldY1 < minHeight) { newY = oldY1 + minHeight; } newR.setRect(0, 0, newX - oldX1, newY - oldY1); prepareGeometryChange(); m_rect = newR; positionGrip(); } void Note::handleMouseReleaseSlot(QGraphicsSceneMouseEvent * event, ResizeHandle * resizeHandle) { Q_UNUSED(resizeHandle); Q_UNUSED(event); if (!m_inResize) return; m_inResize = NULL; InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->noteSizeChanged(this, m_viewGeometry.rect().size(), m_rect.size()); } } bool Note::hasPartLabel() { return false; } bool Note::stickyEnabled() { return false; } bool Note::hasPartNumberProperty() { return false; } bool Note::rotationAllowed() { return false; } bool Note::rotation45Allowed() { return false; } QString Note::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { Q_UNUSED(svgHash); factor = 1; switch (viewLayerID) { case ViewLayer::BreadboardNote: if (viewID() != ViewLayer::BreadboardView) return ""; break; case ViewLayer::PcbNote: if (viewID() != ViewLayer::PCBView) return ""; break; case ViewLayer::SchematicNote: if (viewID() != ViewLayer::SchematicView) return ""; break; default: return ""; } QString svg = ""; QString penColor = blackOnly ? "#000000" : m_pen.color().name(); double penWidth = m_pen.widthF() * dpi / GraphicsUtils::SVGDPI; QString brushColor = blackOnly ? "none" : m_brush.color().name(); svg += QString("") .arg(penWidth / 2) .arg(penWidth / 2) .arg((m_rect.width() * dpi / GraphicsUtils::SVGDPI) - penWidth) .arg((m_rect.height() * dpi / GraphicsUtils::SVGDPI) - penWidth) .arg(brushColor) .arg(penColor) .arg(penWidth) ; QTextCursor textCursor = m_graphicsTextItem->textCursor(); QSizeF gripSize = m_resizeGrip->boundingRect().size(); double docLeft = gripSize.width(); double docTop = gripSize.height(); for (QTextBlock block = m_graphicsTextItem->document()->begin(); block.isValid(); block = block.next()) { QTextLayout * layout = block.layout(); double left = block.blockFormat().leftMargin() + docLeft + layout->position().x(); double top = block.blockFormat().topMargin() + docTop + layout->position().y(); for (int i = 0; i < layout->lineCount(); i++) { QTextLine line = layout->lineAt(i); QRectF r = line.rect(); int start = line.textStart(); int count = line.textLength(); QString soFar; svg += QString("\n") .arg((left + r.left()) * dpi / GraphicsUtils::SVGDPI) .arg((top + r.top() + line.ascent()) * dpi / GraphicsUtils::SVGDPI) .arg("Droid Sans") .arg(line.ascent() * dpi / GraphicsUtils::SVGDPI) ; bool inUrl = false; for (int i = 0; i < count; i++) { textCursor.setPosition(i + start + block.position(), QTextCursor::MoveAnchor); textCursor.setPosition(i + start + block.position() + 1, QTextCursor::KeepAnchor); QString html = textCursor.selection().toHtml(); if (UrlTag.indexIn(html) >= 0) { if (inUrl) { soFar += block.text().mid(start + i, 1); continue; } svg += addText(soFar, false); soFar = block.text().mid(start + i, 1); inUrl = true; } else { if (!inUrl) { soFar += block.text().mid(start + i, 1); continue; } svg += addText(soFar, !blackOnly); soFar = block.text().mid(start + i, 1); inUrl = false; } } svg += addText(soFar, inUrl && !blackOnly); svg += ""; } } svg += ""; return svg; } ViewLayer::ViewID Note::useViewIDForPixmap(ViewLayer::ViewID, bool) { return ViewLayer::IconView; } void Note::addedToScene(bool temporary) { positionGrip(); return ItemBase::addedToScene(temporary); } fritzing-app-0.9.2b/src/items/note.h000066400000000000000000000074671250202676700173510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef NOTE_H #define NOTE_H #include #include #include #include #include #include #include #include #include #include #include "../items/itembase.h" class Note : public ItemBase { Q_OBJECT public: Note(class ModelPart*, ViewLayer::ViewID, const ViewGeometry &, long id, QMenu * itemMenu); void saveGeometry(); bool itemMoved(); void saveInstanceLocation(QXmlStreamWriter &); void moveItem(ViewGeometry &); void findConnectorsUnder(); void setText(const QString & text, bool checkSize); QString text(); void setSize(const QSizeF & size); void setHidden(bool hide); void setInactive(bool inactivate); bool hasPartLabel(); bool stickyEnabled(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QPainterPath shape() const; bool hasPartNumberProperty(); bool rotationAllowed(); bool rotation45Allowed(); void addedToScene(bool temporary); protected: QRectF boundingRect() const; void positionGrip(); void mousePressEvent ( QGraphicsSceneMouseEvent * event ); void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ); void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ); bool eventFilter(QObject * object, QEvent * event); void checkSize(QSizeF & newSize); void connectSlots(); void disconnectSlots(); void forceFormat(int position, int charsAdded); QString retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected slots: void contentsChangeSlot(int position, int charsAdded, int charsRemoved); void contentsChangedSlot(); void linkDialog(); void handleZoomChangedSlot(double scale); void handleMousePressSlot(QGraphicsSceneMouseEvent * event, class ResizeHandle * resizeHandle); void handleMouseMoveSlot(QGraphicsSceneMouseEvent * event, class ResizeHandle * resizeHandle); void handleMouseReleaseSlot(QGraphicsSceneMouseEvent * event, class ResizeHandle * resizeHandle); public: static const int emptyMinWidth; static const int emptyMinHeight; static const int initialMinWidth; static const int initialMinHeight; static QString initialTextString; protected: QRectF m_rect; QPen m_pen; QBrush m_brush; class ResizeHandle * m_resizeGrip; class ResizeHandle * m_inResize; QGraphicsTextItem * m_graphicsTextItem; int m_charsAdded; int m_charsPosition; }; class LinkDialog : public QDialog { Q_OBJECT public: LinkDialog(QWidget *parent = 0); ~LinkDialog(); void setUrl(const QString &); void setText(const QString &); QString text(); QString url(); protected: QLineEdit * m_urlEdit; QLineEdit * m_textEdit; }; #endif fritzing-app-0.9.2b/src/items/pad.cpp000066400000000000000000000307341250202676700174740ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ // TODO: // flip for one-sided board #include "pad.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "moduleidnames.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static QString PadTemplate = ""; static double OriginalWidth = 28; static double OriginalHeight = 32; static double TheOffset = 4; Pad::Pad( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : ResizableBoard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_decimalsAfter = 2; m_copperBlocker = false; } Pad::~Pad() { } QString Pad::makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(milsW); Q_UNUSED(milsH); switch (viewLayerID) { case ViewLayer::Copper0: case ViewLayer::Copper1: break; default: return ""; } double wpx = mmW > 0 ? GraphicsUtils::mm2pixels(mmW) : OriginalWidth; double hpx = mmH > 0 ? GraphicsUtils::mm2pixels(mmH) : OriginalHeight; QString connectAt = m_modelPart->localProp("connect").toString(); QRectF terminal; double minW = qMin((double) 1.0, wpx / 3); double minH = qMin((double) 1.0, hpx / 3); if (connectAt.compare("center", Qt::CaseInsensitive) == 0) { terminal.setRect(2, 2, wpx, hpx); } else if (connectAt.compare("north", Qt::CaseInsensitive) == 0) { terminal.setRect(2, 2, wpx, minH); } else if (connectAt.compare("south", Qt::CaseInsensitive) == 0) { terminal.setRect(2, 2 + hpx - minH, wpx, minH); } else if (connectAt.compare("east", Qt::CaseInsensitive) == 0) { terminal.setRect(2 + wpx - minW, 2, minW, hpx); } else if (connectAt.compare("west", Qt::CaseInsensitive) == 0) { terminal.setRect(2, 2, minW, hpx); } QString blockerColor = (viewLayerID == ViewLayer::Copper0) ? "#A26A00" : "#aF8B33"; QString copperColor = (viewLayerID == ViewLayer::Copper0) ? ViewLayer::Copper0Color : ViewLayer::Copper1Color; QString svg = QString("\n" "\n" "\n" ) .arg(wpx + TheOffset) .arg(hpx + TheOffset) .arg(wpx) .arg(hpx) .arg(ViewLayer::viewLayerXmlNameFromID(viewLayerID)) .arg(copperBlocker() ? blockerColor : copperColor) .arg(copperBlocker() ? 0.0 : 1.0) .arg(copperBlocker() ? "zzz" : "connector0") .arg(copperBlocker() ? blockerColor : "none") .arg(copperBlocker() ? TheOffset : 0) ; if (copperBlocker()) { svg += QString("\n") .arg(TheOffset) .arg(TheOffset) .arg(wpx) .arg(hpx) .arg(blockerColor) ; svg += QString("\n") .arg(wpx) .arg(TheOffset) .arg(TheOffset) .arg(hpx) .arg(blockerColor) ; } else { svg += QString("\n") .arg(terminal.left()) .arg(terminal.top()) .arg(terminal.width()) .arg(terminal.height()) ; } svg += "\n"; //DebugDialog::debug("pad svg: " + svg); return svg; } QString Pad::makeNextLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(mmW); Q_UNUSED(mmH); Q_UNUSED(milsW); Q_UNUSED(milsH); Q_UNUSED(viewLayerID); return ""; } QString Pad::makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH) { return makeLayerSvg(moduleID().compare(ModuleIDNames::Copper0PadModuleIDName) == 0 ? ViewLayer::Copper0 : ViewLayer::Copper1, mmW, mmH, milsW, milsH); } ViewLayer::ViewID Pad::theViewID() { return ViewLayer::PCBView; } double Pad::minWidth() { return 1; } double Pad::minHeight() { return 1; } QString Pad::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { return ResizableBoard::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QStringList Pad::collectValues(const QString & family, const QString & prop, QString & value) { QStringList values = ResizableBoard::collectValues(family, prop, value); QStringList newValues; if (prop.compare("layer", Qt::CaseInsensitive) == 0) { foreach (QString xmlName, values) { newValues << Board::convertFromXmlName(xmlName); } value = Board::convertFromXmlName(value); return newValues; } return values; } bool Pad::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("shape", Qt::CaseInsensitive) == 0) { returnWidget = setUpDimEntry(false, false, false, returnWidget); returnWidget->setEnabled(swappingEnabled); returnProp = tr("shape"); return true; } if (!copperBlocker()) { if (prop.compare("connect to", Qt::CaseInsensitive) == 0) { QComboBox * comboBox = new QComboBox(); comboBox->setObjectName("infoViewComboBox"); comboBox->setEditable(false); comboBox->setEnabled(swappingEnabled); comboBox->addItem(tr("center"), "center"); comboBox->addItem(tr("north"), "north"); comboBox->addItem(tr("east"), "east"); comboBox->addItem(tr("south"), "south"); comboBox->addItem(tr("west"), "west"); QString connectAt = m_modelPart->localProp("connect").toString(); for (int i = 0; i < comboBox->count(); i++) { if (comboBox->itemData(i).toString().compare(connectAt) == 0) { comboBox->setCurrentIndex(i); break; } } connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(terminalPointEntry(const QString &))); returnWidget = comboBox; returnProp = tr("connect to"); return true; } } bool result = PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("layer") == 0 && returnWidget != NULL) { bool disabled = true; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView && infoGraphicsView->boardLayers() == 2) disabled = false; returnWidget->setDisabled(disabled); } return result; } void Pad::setProp(const QString & prop, const QString & value) { if (prop.compare("connect to", Qt::CaseInsensitive) == 0) { modelPart()->setLocalProp("connect", value); resizeMMAux(m_modelPart->localProp("width").toDouble(), m_modelPart->localProp("height").toDouble()); return; } ResizableBoard::setProp(prop, value); } bool Pad::canEditPart() { return false; } bool Pad::hasPartLabel() { return true; } bool Pad::stickyEnabled() { return true; } ItemBase::PluralType Pad::isPlural() { return Plural; } bool Pad::rotationAllowed() { return true; } bool Pad::rotation45Allowed() { return true; } bool Pad::freeRotationAllowed(Qt::KeyboardModifiers modifiers) { if ((modifiers & altOrMetaModifier()) == 0) return false; if (!isSelected()) return false; return true; } bool Pad::freeRotationAllowed() { return true; } bool Pad::hasPartNumberProperty() { return false; } void Pad::setInitialSize() { double w = m_modelPart->localProp("width").toDouble(); if (w == 0) { // set the size so the infoGraphicsView will display the size as you drag modelPart()->setLocalProp("width", GraphicsUtils::pixels2mm(OriginalWidth, GraphicsUtils::SVGDPI)); modelPart()->setLocalProp("height", GraphicsUtils::pixels2mm(OriginalHeight, GraphicsUtils::SVGDPI)); modelPart()->setLocalProp("connect", "center"); } } void Pad::resizeMMAux(double mmW, double mmH) { ResizableBoard::resizeMMAux(mmW, mmH); resetConnectors(NULL, NULL); } void Pad::addedToScene(bool temporary) { if (this->scene()) { setInitialSize(); resizeMMAux(m_modelPart->localProp("width").toDouble(), m_modelPart->localProp("height").toDouble()); } return PaletteItem::addedToScene(temporary); } void Pad::terminalPointEntry(const QString &) { QComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; QString value = comboBox->itemData(comboBox->currentIndex()).toString(); QString connectAt = m_modelPart->localProp("connect").toString(); if (connectAt.compare(value) == 0) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "connect to", tr("connect to"), connectAt, value, true); } } ResizableBoard::Corner Pad::findCorner(QPointF scenePos, Qt::KeyboardModifiers modifiers) { //return ResizableBoard::NO_CORNER; ResizableBoard::Corner corner = ResizableBoard::findCorner(scenePos, modifiers); if (corner == ResizableBoard::NO_CORNER) return corner; if (modifiers & altOrMetaModifier()) { // free rotate setCursor(*CursorMaster::RotateCursor); return ResizableBoard::NO_CORNER; } return corner; } void Pad::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { PaletteItem::paintHover(painter, option, widget); } bool Pad::copperBlocker() { return m_copperBlocker; } ////////////////////////////////////////// CopperBlocker::CopperBlocker( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Pad(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_copperBlocker = true; } CopperBlocker::~CopperBlocker() { } bool CopperBlocker::hasPartLabel() { return false; } QPainterPath CopperBlocker::hoverShape() const { if (m_viewID != ViewLayer::PCBView) { return PaletteItem::hoverShape(); } QRectF r = boundingRect(); QPainterPath path; double half = TheOffset / 2; path.moveTo(half, half); path.lineTo(r.width() - half, half); path.lineTo(r.width() - half, r.height() - half); path.lineTo(half, r.height() - half); path.closeSubpath(); path.moveTo(0, 0); path.lineTo(r.width(), r.height()); path.moveTo(r.width(), 0); path.lineTo(0, r.height()); path.moveTo(0, 0); QPen pen; pen.setCapStyle(Qt::RoundCap); return GraphicsUtils::shapeFromPath(path, pen, TheOffset, false); } QPainterPath CopperBlocker::shape() const { return hoverShape(); } QString CopperBlocker::makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH) { return makeLayerSvg(moduleID().compare(ModuleIDNames::Copper1BlockerModuleIDName) == 0 ? ViewLayer::Copper1 : ViewLayer::Copper0, mmW, mmH, milsW, milsH); }fritzing-app-0.9.2b/src/items/pad.h000066400000000000000000000070211250202676700171320ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef PAD_H #define PAD_H #include #include #include #include #include #include #include #include "resizableboard.h" class Pad : public ResizableBoard { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Pad(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Pad(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool canEditPart(); void setProp(const QString & prop, const QString & value); bool hasPartLabel(); bool stickyEnabled(); PluralType isPlural(); bool rotationAllowed(); bool rotation45Allowed(); bool freeRotationAllowed(Qt::KeyboardModifiers); bool freeRotationAllowed(); bool hasPartNumberProperty(); void setInitialSize(); void addedToScene(bool temporary); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool copperBlocker(); protected slots: void terminalPointEntry(const QString &); protected: double minWidth(); double minHeight(); ViewLayer::ViewID theViewID(); QString makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH); QString makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH); QString makeNextLayerSvg(ViewLayer::ViewLayerID, double mmW, double mmH, double milsW, double milsH); void resizeMMAux(double w, double h); ResizableBoard::Corner findCorner(QPointF, Qt::KeyboardModifiers); QStringList collectValues(const QString & family, const QString & prop, QString & value); protected: bool m_copperBlocker; }; class CopperBlocker : public Pad { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call CopperBlocker(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~CopperBlocker(); bool hasPartLabel(); QPainterPath shape() const; QPainterPath hoverShape() const; protected: QString makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH); }; #endif fritzing-app-0.9.2b/src/items/paletteitem.cpp000066400000000000000000001454001250202676700212420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "paletteitem.h" #include "../debugdialog.h" #include "../viewgeometry.h" #include "../sketch/infographicsview.h" #include "layerkinpaletteitem.h" #include "../fsvgrenderer.h" #include "partlabel.h" #include "partfactory.h" #include "../commands.h" #include "../connectors/connectoritem.h" #include "../connectors/connector.h" #include "../connectors/svgidlayer.h" #include "../layerattributes.h" #include "../dialogs/pinlabeldialog.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/familypropertycombobox.h" #include "../svg/svgfilesplitter.h" #include "wire.h" #include #include #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////// QString HoleSettings::currentUnits() { if (mmRadioButton->isChecked()) return QObject::tr("mm"); return QObject::tr("in"); } QString HoleSettings::holeSize() { return QString("%1,%2").arg(holeDiameter).arg(ringThickness); } ///////////////////////////////////////////////// static QRegExp LabelFinder("id=['|\"]label['|\"]"); static bool ByIDParseSuccessful = true; static QRegExp ConnectorFinder("connector\\d+pin"); const QString PaletteItem::HoleSizePrefix("_hs_"); int findNumber(const QString & string) { int ix = string.indexOf(IntegerFinder); if (ix < 0) { return -1; } int result = IntegerFinder.cap(0).toInt(); int length = IntegerFinder.cap(0).length(); int jx = string.lastIndexOf(IntegerFinder); if (jx >= ix + length) { return -1; } return result; } bool byID(Connector * c1, Connector * c2) { int i1 = findNumber(c1->connectorSharedID()); if (i1 < 0) { ByIDParseSuccessful = false; return true; } int i2 = findNumber(c2->connectorSharedID()); if (i2 < 0) { ByIDParseSuccessful = false; return true; } if (i2 == i1 && c1 != c2) { // should not be two connectors with the same number ByIDParseSuccessful = false; return true; } return i1 <= i2; } ///////////////////////////////////////////////// PaletteItem::PaletteItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItemBase(modelPart, viewID, viewGeometry, id, itemMenu) { m_flipCount = 0; if(doLabel) { m_partLabel = new PartLabel(this, NULL); m_partLabel->setVisible(false); } else { m_partLabel = NULL; } } PaletteItem::~PaletteItem() { if (m_partLabel) { delete m_partLabel; } } bool PaletteItem::renderImage(ModelPart * modelPart, ViewLayer::ViewID viewID, const LayerHash & viewLayers, ViewLayer::ViewLayerID viewLayerID, bool doConnectors, QString & error) { LayerAttributes layerAttributes; initLayerAttributes(layerAttributes, viewID, viewLayerID, viewLayerPlacement(), doConnectors, true); bool result = setUpImage(modelPart, viewLayers, layerAttributes); error = layerAttributes.error; m_syncMoved = this->pos(); return result; } void PaletteItem::loadLayerKin(const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (m_modelPart == NULL) return; ModelPartShared * modelPartShared = m_modelPart->modelPartShared(); if (modelPartShared == NULL) return; qint64 id = m_id + 1; ViewGeometry viewGeometry = m_viewGeometry; viewGeometry.setZ(-1); foreach (ViewLayer::ViewLayerID viewLayerID, viewLayers.keys()) { if (viewLayerID == m_viewLayerID) continue; if (!m_modelPart->hasViewFor(m_viewID, viewLayerID)) continue; if (m_modelPart->itemType() == ModelPart::CopperFill) { if (viewLayerPlacement == ViewLayer::NewTop) { if (ViewLayer::bottomLayers().contains(viewLayerID)) continue; } else { if (ViewLayer::topLayers().contains(viewLayerID)) continue; } } else if (m_modelPart->flippedSMD()) { if (viewLayerPlacement == ViewLayer::NewTop) { if (ViewLayer::bottomLayers().contains(viewLayerID)) continue; } else { if (ViewLayer::topLayers().contains(viewLayerID)) continue; } } else if (m_modelPart->itemType() == ModelPart::Part) { // through hole part if (ViewLayer::silkLayers().contains(viewLayerID)) { if (viewLayerPlacement == ViewLayer::NewTop) { if (ViewLayer::bottomLayers().contains(viewLayerID)) continue; } else { if (ViewLayer::topLayers().contains(viewLayerID)) continue; } } } makeOneKin(id, viewLayerID, viewLayerPlacement, viewGeometry, viewLayers); } } void PaletteItem::makeOneKin(qint64 & id, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewGeometry & viewGeometry, const LayerHash & viewLayers) { LayerAttributes layerAttributes; initLayerAttributes(layerAttributes, m_viewID, viewLayerID, viewLayerPlacement, true, true); LayerKinPaletteItem * lkpi = newLayerKinPaletteItem(this, m_modelPart, viewGeometry, id, m_itemMenu, viewLayers, layerAttributes); if (lkpi->ok()) { DebugDialog::debug(QString("adding layer kin %1 %2 %3 %4") .arg(id).arg(m_viewID).arg(viewLayerID) .arg((long) lkpi, 0, 16) ); addLayerKin(lkpi); id++; } else { delete lkpi; } } void PaletteItem::addLayerKin(LayerKinPaletteItem * lkpi) { m_layerKin.append(lkpi); } void PaletteItem::removeLayerKin() { // assumes paletteitem is still in scene for (int i = 0; i < m_layerKin.size(); i++) { //DebugDialog::debug(QString("removing kin %1 %2").arg(m_layerKin[i]->id()).arg(m_layerKin[i]->z())); this->scene()->removeItem(m_layerKin[i]); delete m_layerKin[i]; } m_layerKin.clear(); } void PaletteItem::syncKinSelection(bool selected, PaletteItemBase * originator) { PaletteItemBase::syncKinSelection(selected, originator); foreach (ItemBase * lkpi, m_layerKin) { if (lkpi != originator && lkpi->isSelected() != selected) { qobject_cast(lkpi)->blockItemSelectedChange(selected); lkpi->setSelected(selected); } } if (this != originator && this->isSelected() != selected) { this->blockItemSelectedChange(selected); this->setSelected(selected); } } QVariant PaletteItem::itemChange(GraphicsItemChange change, const QVariant &value) { //DebugDialog::debug(QString("chief item change %1 %2").arg(this->id()).arg(change)); if (m_layerKin.count() > 0) { if (change == ItemSelectedChange) { bool selected = value.toBool(); if (m_blockItemSelectedChange && m_blockItemSelectedValue == selected) { m_blockItemSelectedChange = false; } else { syncKinSelection(selected, this); } } //else if (change == ItemVisibleHasChanged && value.toBool()) { //this->setSelected(syncSelected()); //this->setPos(m_offset + syncMoved()); //} else if (change == ItemPositionHasChanged) { this->syncKinMoved(this->m_offset, value.toPointF()); } } if (m_partLabel && m_partLabel->initialized()) { if (change == ItemPositionHasChanged) { m_partLabel->ownerMoved(value.toPointF()); } else if (change == ItemSelectedChange) { m_partLabel->update(); } } return PaletteItemBase::itemChange(change, value); } const QList & PaletteItem::layerKin() { return m_layerKin; } void PaletteItem::rotateItem(double degrees, bool includeRatsnest) { PaletteItemBase::rotateItem(degrees, includeRatsnest); for (int i = 0; i < m_layerKin.count(); i++) { m_layerKin[i]->rotateItem(degrees, includeRatsnest); } } void PaletteItem::flipItem(Qt::Orientations orientation) { PaletteItemBase::flipItem(orientation); foreach (ItemBase * lkpi, m_layerKin) { lkpi->flipItem(orientation); } } void PaletteItem::transformItem2(const QMatrix & matrix) { PaletteItemBase::transformItem2(matrix); foreach (ItemBase * lkpi, m_layerKin) { lkpi->transformItem2(matrix); } } void PaletteItem::setTransforms() { // only ever called when loading from file // jrc 14 july 2013: this call seems redundant--transforms have already been set up by now QTransform transform = getViewGeometry().transform(); if (transform.isIdentity()) return; //debugInfo("set transforms " + TextUtils::svgMatrix(transform)); //debugInfo("\t " + TextUtils::svgMatrix(this->transform())); setTransform(transform); for (int i = 0; i < m_layerKin.count(); i++) { //debugInfo("\t " + TextUtils::svgMatrix(m_layerKin[i]->getViewGeometry().transform())); //debugInfo("\t " + TextUtils::svgMatrix(m_layerKin[i]->transform())); m_layerKin[i]->setTransform2(m_layerKin[i]->getViewGeometry().transform()); } } void PaletteItem::moveItem(ViewGeometry & viewGeometry) { PaletteItemBase::moveItem(viewGeometry); for (int i = 0; i < m_layerKin.count(); i++) { m_layerKin[i]->moveItem(viewGeometry); } } void PaletteItem::setItemPos(QPointF & loc) { PaletteItemBase::setItemPos(loc); for (int i = 0; i < m_layerKin.count(); i++) { m_layerKin[i]->setItemPos(loc); } } void PaletteItem::updateConnections(bool includeRatsnest, QList & already) { updateConnectionsAux(includeRatsnest, already); foreach (ItemBase * lkpi, m_layerKin) { lkpi->updateConnectionsAux(includeRatsnest, already); } } bool PaletteItem::collectFemaleConnectees(QSet & items) { bool hasMale = PaletteItemBase::collectFemaleConnectees(items); foreach (ItemBase * lkpi, m_layerKin) { if (lkpi->collectFemaleConnectees(items)) { hasMale = true; } } return hasMale; } void PaletteItem::collectWireConnectees(QSet & wires) { PaletteItemBase::collectWireConnectees(wires); foreach (ItemBase * lkpi, m_layerKin) { qobject_cast(lkpi)->collectWireConnectees(wires); } } bool PaletteItem::mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event) { //DebugDialog::debug("layerkinchief got mouse press event"); /* if (acceptsMousePressConnectorEvent(NULL, event) && isBuriedConnectorHit(event) ) return; foreach(LayerKinPaletteItem * lkpi, m_layerKin) { if (lkpi->isBuriedConnectorHit(event)) return; } */ return PaletteItemBase::mousePressEventK(originalItem, event); } void PaletteItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL && infographics->spaceBarIsPressed()) { event->ignore(); return; } mousePressEventK(this, event); } void PaletteItem::syncKinMoved(QPointF offset, QPointF newPos) { Q_UNUSED(offset); // ignore offset--should all be zeros now //DebugDialog::debug(QString("sync kin moved %1 %2").arg(offset.x()).arg(offset.y()) ); //m_syncMoved = pos - offset; //if (newPos != pos()) { setPos(newPos); foreach (ItemBase * lkpi, m_layerKin) { lkpi->setPos(newPos); } //} } void PaletteItem::setInstanceTitle(const QString& title, bool initial) { ItemBase::setInstanceTitle(title, initial); foreach (ItemBase * lkpi, m_layerKin) { lkpi->setInstanceTitle(title, initial); } } void PaletteItem::setHidden(bool hide) { ItemBase::setHidden(hide); figureHover(); } void PaletteItem::setInactive(bool inactivate) { ItemBase::setInactive(inactivate); figureHover(); } void PaletteItem::figureHover() { setAcceptHoverEvents(true); setAcceptedMouseButtons(ALLMOUSEBUTTONS); foreach(ItemBase * lkpi, m_layerKin) { lkpi->setAcceptHoverEvents(true); lkpi->setAcceptedMouseButtons(ALLMOUSEBUTTONS); } } void PaletteItem::clearModelPart() { foreach (ItemBase * lkpi, m_layerKin) { lkpi->setModelPart(NULL); } ItemBase::clearModelPart(); } void PaletteItem::resetID() { ItemBase::resetID(); foreach (ItemBase * lkpi, m_layerKin) { lkpi->resetID(); } } void PaletteItem::slamZ(double z) { PaletteItemBase::slamZ(z); foreach (ItemBase * lkpi, m_layerKin) { lkpi->slamZ(z); } } void PaletteItem::resetImage(InfoGraphicsView * infoGraphicsView) { foreach (Connector * connector, modelPart()->connectors()) { connector->unprocess(this->viewID(), this->viewLayerID()); } LayerAttributes layerAttributes; initLayerAttributes(layerAttributes, viewID(), viewLayerID(), viewLayerPlacement(), true, !m_selectionShape.isEmpty()); this->setUpImage(modelPart(), infoGraphicsView->viewLayers(), layerAttributes); foreach (ItemBase * layerKin, m_layerKin) { resetKinImage(layerKin, infoGraphicsView); } } void PaletteItem::resetKinImage(ItemBase * layerKin, InfoGraphicsView * infoGraphicsView) { foreach (Connector * connector, modelPart()->connectors()) { connector->unprocess(layerKin->viewID(), layerKin->viewLayerID()); } LayerAttributes layerAttributes; initLayerAttributes(layerAttributes, layerKin->viewID(), layerKin->viewLayerID(), layerKin->viewLayerPlacement(), true, !layerKin->selectionShape().isEmpty()); qobject_cast(layerKin)->setUpImage(modelPart(), infoGraphicsView->viewLayers(), layerAttributes); } QString PaletteItem::genFZP(const QString & moduleid, const QString & templateName, int minPins, int maxPins, int steps, bool smd) { QString FzpTemplate = ""; QString ConnectorFzpTemplate = ""; QFile file1(QString(":/resources/templates/%1.txt").arg(templateName)); file1.open(QFile::ReadOnly); FzpTemplate = file1.readAll(); file1.close(); if (smd) { FzpTemplate.replace("", ""); } QFile file2(":/resources/templates/generic_sip_connectorFzpTemplate.txt"); file2.open(QFile::ReadOnly); ConnectorFzpTemplate = file2.readAll(); file2.close(); if (smd) { ConnectorFzpTemplate.replace("

", ""); } QStringList ss = moduleid.split("_"); int count = 0; foreach (QString s, ss) { bool ok; int c = s.toInt(&ok); if (ok) { count = c; break; } } if (count > maxPins || count < minPins) return ""; if (count % steps != 0) return ""; QString middle; for (int i = 0; i < count; i++) { middle += ConnectorFzpTemplate.arg(i).arg(i + 1); } return FzpTemplate.arg(count).arg(middle); } bool PaletteItem::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("editable pin labels", Qt::CaseInsensitive) == 0 && value.compare("true") == 0) { returnProp = ""; returnValue = value; QPushButton * button = new QPushButton(tr("Edit Pin Labels")); button->setObjectName("infoViewButton"); connect(button, SIGNAL(pressed()), this, SLOT(openPinLabelDialog())); button->setEnabled(swappingEnabled); returnWidget = button; return true; } bool result = PaletteItemBase::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("layer") == 0 && modelPart()->flippedSMD() && returnWidget != NULL) { bool disabled = true; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView && infoGraphicsView->boardLayers() == 2) disabled = false; returnWidget->setDisabled(disabled); } return result; } QStringList PaletteItem::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("layer") == 0) { if (modelPart()->flippedSMD()) { QStringList values = PaletteItemBase::collectValues(family, prop, value); for (int ix = values.count() - 1; ix >= 0; ix--) { if (values.at(ix).isEmpty()) { values.removeAt(ix); } } if (values.count() < 2) { ItemBase * itemBase = modelPart()->viewItem(ViewLayer::PCBView); if (itemBase) { values.clear(); values << TranslatedPropertyNames.value("bottom") << TranslatedPropertyNames.value("top"); if (itemBase->viewLayerID() == ViewLayer::Copper0) { value = values.at(0); } else { value = values.at(1); } } } return values; } if (modelPart()->itemType() == ModelPart::Part) { QStringList values = PaletteItemBase::collectValues(family, prop, value); if (values.count() == 0) { ItemBase * itemBase = modelPart()->viewItem(ViewLayer::PCBView); if (itemBase) { values << TranslatedPropertyNames.value("bottom") << TranslatedPropertyNames.value("top"); if (itemBase->viewLayerPlacement() == ViewLayer::NewBottom) { value = values.at(0); } else { value = values.at(1); } } } return values; } } return PaletteItemBase::collectValues(family, prop, value); } void PaletteItem::openPinLabelDialog() { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) { QMessageBox::warning( NULL, tr("Fritzing"), tr("Unable to proceed; unable to find top level view.") ); return; } QStringList labels; QList sortedConnectors = sortConnectors(); if (sortedConnectors.count() == 0) { QMessageBox::warning( NULL, tr("Fritzing"), tr("Unable to proceed; part connectors do no have standard IDs.") ); return; } foreach (Connector * connector, sortedConnectors) { labels.append(connector->connectorSharedName()); } QString chipLabel = modelPart()->localProp("chip label").toString(); if (chipLabel.isEmpty()) { chipLabel = instanceTitle(); } bool singleRow = isSingleRow(cachedConnectorItems()); PinLabelDialog pinLabelDialog(labels, singleRow, chipLabel, modelPart()->isCore(), NULL); int result = pinLabelDialog.exec(); if (result != QDialog::Accepted) return; QStringList newLabels = pinLabelDialog.labels(); if (newLabels.count() != sortedConnectors.count()) { QMessageBox::warning( NULL, tr("Fritzing"), tr("Label mismatch. Nothing was saved.") ); return; } infoGraphicsView->renamePins(this, labels, newLabels, singleRow); } void PaletteItem::renamePins(const QStringList & labels, bool singleRow) { QList sortedConnectors = sortConnectors(); for (int i = 0; i < labels.count(); i++) { Connector * connector = sortedConnectors.at(i); connector->setConnectorLocalName(labels.at(i)); } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); infoGraphicsView->changePinLabels(this, singleRow); } bool PaletteItem::isSingleRow(const QList & connectorItems) { if (connectorItems.count() == 2) { // no way to tell? so default to double return false; } else if (connectorItems.count() % 2 == 0) { QPointF p = connectorItems.at(0)->sceneAdjustedTerminalPoint(NULL); double slope = 0; for (int i = 1; i < connectorItems.count(); i++) { QPointF q = connectorItems.at(i)->sceneAdjustedTerminalPoint(NULL); if (p == q) continue; double newSlope = q.x() == p.x() ? std::numeric_limits::max() : (q.y() - p.y()) / (q.x() - p.x()); if (i == 1) { slope = newSlope; } else { double d = qAbs(newSlope - slope); if (d != 0 && d / qMax(qAbs(slope), qAbs(newSlope)) > 0.01) { return false; } } } } return true; } QList PaletteItem::sortConnectors() { QList sortedConnectors; foreach (Connector * connector, modelPart()->connectors().values()) { sortedConnectors.append(connector); } ByIDParseSuccessful = true; qSort(sortedConnectors.begin(), sortedConnectors.end(), byID); if (!ByIDParseSuccessful || sortedConnectors.count() == 0) { sortedConnectors.clear(); } return sortedConnectors; } bool PaletteItem::changePinLabels(bool singleRow, bool sip) { Q_UNUSED(singleRow); Q_UNUSED(sip); if (m_viewID != ViewLayer::SchematicView) return true; return false; } QStringList PaletteItem::getPinLabels(bool & hasLocal) { hasLocal = false; QStringList labels; QList sortedConnectors = sortConnectors(); if (sortedConnectors.count() == 0) return labels; foreach (Connector * connector, sortedConnectors) { labels.append(connector->connectorSharedName()); if (!connector->connectorLocalName().isEmpty()) { hasLocal = true; } } return labels; } void PaletteItem::resetConnectors() { if (m_viewID != ViewLayer::SchematicView) return; FSvgRenderer * renderer = fsvgRenderer(); if (renderer == NULL) return; QSizeF size = renderer->defaultSizeF(); // pixels QRectF viewBox = renderer->viewBoxF(); foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { SvgIdLayer * svgIdLayer = connectorItem->connector()->fullPinInfo(m_viewID, m_viewLayerID); if (svgIdLayer == NULL) continue; QRectF bounds = renderer->boundsOnElement(svgIdLayer->m_svgId); QPointF p(bounds.left() * size.width() / viewBox.width(), bounds.top() * size.height() / viewBox.height()); QRectF r = connectorItem->rect(); r.moveTo(p.x(), p.y()); connectorItem->setRect(r); } } void PaletteItem::resetConnectors(ItemBase * otherLayer, FSvgRenderer * otherLayerRenderer) { // there's only one connector foreach (Connector * connector, m_modelPart->connectors().values()) { if (connector == NULL) continue; connector->unprocess(m_viewID, m_viewLayerID); SvgIdLayer * svgIdLayer = connector->fullPinInfo(m_viewID, m_viewLayerID); if (svgIdLayer == NULL) continue; bool result = fsvgRenderer()->setUpConnector(svgIdLayer, false, viewLayerPlacement()); if (!result) continue; resetConnector(this, svgIdLayer); } if (otherLayer) { foreach (Connector * connector, m_modelPart->connectors().values()) { if (connector == NULL) continue; connector->unprocess(m_viewID, otherLayer->viewLayerID()); SvgIdLayer * svgIdLayer = connector->fullPinInfo(m_viewID, otherLayer->viewLayerID()); if (svgIdLayer == NULL) continue; bool result = otherLayerRenderer->setUpConnector(svgIdLayer, false, viewLayerPlacement()); if (!result) continue; resetConnector(otherLayer, svgIdLayer); } } } void PaletteItem::resetConnector(ItemBase * itemBase, SvgIdLayer * svgIdLayer) { QList already; foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { //DebugDialog::debug(QString("via set rect %1").arg(itemBase->viewID()), svgIdLayer->m_rect); connectorItem->setRect(svgIdLayer->rect(viewLayerPlacement())); connectorItem->setTerminalPoint(svgIdLayer->point(viewLayerPlacement())); connectorItem->setRadius(svgIdLayer->m_radius, svgIdLayer->m_strokeWidth); connectorItem->setIsPath(svgIdLayer->m_path); connectorItem->attachedMoved(false, already); break; } } bool PaletteItem::collectHoleSizeInfo(const QString & defaultHoleSizeValue, QWidget * parent, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget) { returnProp = tr("hole size"); returnValue = m_modelPart->localProp("hole size").toString(); if (returnValue.isEmpty()) { returnValue = defaultHoleSizeValue; } QWidget * frame = createHoleSettings(parent, m_holeSettings, swappingEnabled, returnValue, true); connect(m_holeSettings.sizesComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(changeHoleSize(const QString &))); connect(m_holeSettings.mmRadioButton, SIGNAL(toggled(bool)), this, SLOT(changeUnits(bool))); connect(m_holeSettings.inRadioButton, SIGNAL(toggled(bool)), this, SLOT(changeUnits(bool))); connect(m_holeSettings.diameterEdit, SIGNAL(editingFinished()), this, SLOT(changeDiameter())); connect(m_holeSettings.thicknessEdit, SIGNAL(editingFinished()), this, SLOT(changeThickness())); returnWidget = frame; return true; } void PaletteItem::setUpHoleSizes(const QString & type, HoleClassThing & holeThing) { if (holeThing.holeSizes.count() == 0) { setUpHoleSizesAux(holeThing, type); } initHoleSettings(m_holeSettings, &holeThing); QStringList localHoleSize = modelPart()->localProp("hole size").toString().split(","); if (localHoleSize.count() == 2) { m_holeSettings.ringThickness = localHoleSize.at(1); m_holeSettings.holeDiameter = localHoleSize.at(0); } else { QString hs = modelPart()->properties().value("hole size"); localHoleSize = hs.split(","); if (localHoleSize.count() == 2) { modelPart()->setLocalProp("hole size", hs); m_holeSettings.ringThickness = localHoleSize.at(1); m_holeSettings.holeDiameter = localHoleSize.at(0); } else { m_holeSettings.ringThickness = holeThing.ringThickness; m_holeSettings.holeDiameter = holeThing.holeSize; } } } void PaletteItem::setUpHoleSizesAux(HoleClassThing & holeThing, const QString & type) { QFile file(":/resources/vias.xml"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("failed loading properties %1 line:%2 col:%3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) return; if (root.tagName() != "vias") return; QDomElement ve = root.firstChildElement("via"); while (!ve.isNull()) { QString rt = ve.attribute("ringthickness"); QString hs = ve.attribute("holesize"); QString name = ve.attribute("name"); QString isOK = ve.attribute(type); if (isOK.toInt() == 1) { if (ve.attribute(type + "default").compare("yes") == 0) { if (holeThing.ringThickness.isEmpty()) { holeThing.ringThickness = rt; } if (holeThing.holeSize.isEmpty()) { holeThing.holeSize = hs; } } bool ok; double val = TextUtils::convertToInches(ve.attribute(type + "ringthicknesslow"), &ok, false); if (ok) { holeThing.ringThicknessRange.setX(val); } val = TextUtils::convertToInches(ve.attribute(type + "ringthicknesshigh"), &ok, false); if (ok) { holeThing.ringThicknessRange.setY(val); } val = TextUtils::convertToInches(ve.attribute(type + "holediameterlow"), &ok, false); if (ok) { holeThing.holeDiameterRange.setX(val); } val = TextUtils::convertToInches(ve.attribute(type + "holediameterhigh"), &ok, false); if (ok) { holeThing.holeDiameterRange.setY(val); } holeThing.holeSizes.insert(name, QString("%1,%2").arg(hs).arg(rt)); holeThing.holeSizeKeys.append(name); } ve = ve.nextSiblingElement("via"); } holeThing.holeSizeValue = QString("%1,%2").arg(holeThing.holeSize).arg(holeThing.ringThickness); } QWidget * PaletteItem::createHoleSettings(QWidget * parent, HoleSettings & holeSettings, bool swappingEnabled, const QString & currentHoleSize, bool advanced) { static const int RowHeight = 21; holeSettings.diameterEdit = NULL; holeSettings.thicknessEdit = NULL; holeSettings.mmRadioButton = NULL; holeSettings.inRadioButton = NULL; holeSettings.diameterValidator = NULL; holeSettings.thicknessValidator = NULL; QFrame * frame = new QFrame(parent); frame->setObjectName("infoViewPartFrame"); QVBoxLayout * vBoxLayout = new QVBoxLayout(frame); vBoxLayout->setMargin(0); vBoxLayout->setContentsMargins(0, 0, 0, 0); vBoxLayout->setSpacing(0); holeSettings.sizesComboBox = new QComboBox(frame); holeSettings.sizesComboBox->setEditable(false); holeSettings.sizesComboBox->setObjectName("infoViewComboBox"); foreach (QString key, holeSettings.holeThing->holeSizeKeys) { holeSettings.sizesComboBox->addItem(key); } holeSettings.sizesComboBox->setEnabled(swappingEnabled); vBoxLayout->addWidget(holeSettings.sizesComboBox); if (advanced) { vBoxLayout->addSpacing(4); QFrame * hFrame = new QFrame(frame); QHBoxLayout * hLayout = new QHBoxLayout(hFrame); hLayout->setMargin(0); QGroupBox * subFrame = new QGroupBox(tr("advanced settings"), frame); subFrame->setObjectName("infoViewGroupBox"); QGridLayout * gridLayout = new QGridLayout(subFrame); gridLayout->setMargin(0); QGroupBox * rbFrame = new QGroupBox("", subFrame); rbFrame->setObjectName("infoViewGroupBox"); QVBoxLayout * vbl = new QVBoxLayout(rbFrame); vbl->setMargin(0); holeSettings.inRadioButton = new QRadioButton(tr("in"), subFrame); gridLayout->addWidget(holeSettings.inRadioButton, 0, 2); holeSettings.inRadioButton->setObjectName("infoViewRadioButton"); holeSettings.mmRadioButton = new QRadioButton(tr("mm"), subFrame); gridLayout->addWidget(holeSettings.mmRadioButton, 1, 2); holeSettings.inRadioButton->setObjectName("infoViewRadioButton"); vbl->addWidget(holeSettings.inRadioButton); vbl->addWidget(holeSettings.mmRadioButton); rbFrame->setLayout(vbl); gridLayout->addWidget(rbFrame, 0, 2, 2, 1, Qt::AlignVCenter); holeSettings.diameterEdit = new QLineEdit(subFrame); holeSettings.diameterEdit->setMinimumHeight(RowHeight); holeSettings.diameterValidator = new QDoubleValidator(holeSettings.diameterEdit); holeSettings.diameterValidator->setNotation(QDoubleValidator::StandardNotation); holeSettings.diameterEdit->setValidator(holeSettings.diameterValidator); gridLayout->addWidget(holeSettings.diameterEdit, 0, 1); holeSettings.diameterEdit->setObjectName("infoViewLineEdit"); QLabel * label = new QLabel(tr("Hole Diameter")); label->setMinimumHeight(RowHeight); label->setObjectName("infoViewGroupBoxLabel"); gridLayout->addWidget(label, 0, 0); holeSettings.thicknessEdit = new QLineEdit(subFrame); holeSettings.thicknessEdit->setMinimumHeight(RowHeight); holeSettings.thicknessValidator = new QDoubleValidator(holeSettings.thicknessEdit); holeSettings.thicknessValidator->setNotation(QDoubleValidator::StandardNotation); holeSettings.thicknessEdit->setValidator(holeSettings.thicknessValidator); gridLayout->addWidget(holeSettings.thicknessEdit, 1, 1); holeSettings.thicknessEdit->setObjectName("infoViewLineEdit"); label = new QLabel(tr("Ring Thickness")); label->setMinimumHeight(RowHeight); gridLayout->addWidget(label, 1, 0); label->setObjectName("infoViewLabel"); gridLayout->setContentsMargins(10, 2, 0, 2); gridLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 3); gridLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum), 1, 3); hLayout->addWidget(subFrame); hLayout->addSpacerItem(new QSpacerItem(1,1,QSizePolicy::Expanding,QSizePolicy::Minimum)); vBoxLayout->addWidget(hFrame); holeSettings.mmRadioButton->setEnabled(swappingEnabled); holeSettings.inRadioButton->setEnabled(swappingEnabled); holeSettings.diameterEdit->setEnabled(swappingEnabled); holeSettings.thicknessEdit->setEnabled(swappingEnabled); if (currentHoleSize.contains("mm")) { holeSettings.mmRadioButton->setChecked(true); } else { holeSettings.inRadioButton->setChecked(true); } } updateEditTexts(holeSettings); updateValidators(holeSettings); updateSizes(holeSettings); return frame; } void PaletteItem::updateEditTexts(HoleSettings & holeSettings) { if (holeSettings.diameterEdit == NULL) return; if (holeSettings.thicknessEdit == NULL) return; if (holeSettings.mmRadioButton == NULL) return; double hd = TextUtils::convertToInches(holeSettings.holeDiameter); double rt = TextUtils::convertToInches(holeSettings.ringThickness); QString newVal; if (holeSettings.currentUnits() == "in") { newVal = QString("%1,%2").arg(hd).arg(rt); } else { newVal = QString("%1,%2").arg(hd * 25.4).arg(rt * 25.4); } QStringList sizes = newVal.split(","); holeSettings.diameterEdit->setText(sizes.at(0)); holeSettings.thicknessEdit->setText(sizes.at(1)); } void PaletteItem::updateSizes(HoleSettings & holeSettings) { if (holeSettings.sizesComboBox == NULL) return; int newIndex = -1; QPointF current(TextUtils::convertToInches(holeSettings.holeDiameter), TextUtils::convertToInches(holeSettings.ringThickness)); for (int ix = 0; ix < holeSettings.sizesComboBox->count(); ix++) { QString key = holeSettings.sizesComboBox->itemText(ix); QString value = holeSettings.holeThing->holeSizes.value(key, ""); QStringList sizes; if (value.isEmpty()) { sizes = key.split(","); } else { sizes = value.split(","); } if (sizes.count() < 2) continue; QPointF p(TextUtils::convertToInches(sizes.at(0)), TextUtils::convertToInches(sizes.at(1))); if (p == current) { newIndex = ix; break; } } if (newIndex < 0) { QString newItem = holeSettings.holeDiameter + "," + holeSettings.ringThickness; holeSettings.sizesComboBox->addItem(newItem); newIndex = holeSettings.sizesComboBox->findText(newItem); holeSettings.holeThing->holeSizes.insert(newItem, newItem); holeSettings.holeThing->holeSizeKeys.prepend(newItem); } // don't want to trigger another undo command bool wasBlocked = holeSettings.sizesComboBox->blockSignals(true); holeSettings.sizesComboBox->setCurrentIndex(newIndex); holeSettings.sizesComboBox->blockSignals(wasBlocked); } void PaletteItem::updateValidators(HoleSettings & holeSettings) { if (holeSettings.diameterValidator == NULL) return; if (holeSettings.thicknessValidator == NULL) return; if (holeSettings.mmRadioButton == NULL) return; QString units = holeSettings.currentUnits(); double multiplier = (units == "mm") ? 25.4 : 1.0; holeSettings.diameterValidator->setRange(holeSettings.holeThing->holeDiameterRange.x() * multiplier, holeSettings.holeThing->holeDiameterRange.y() * multiplier, 3); holeSettings.thicknessValidator->setRange(holeSettings.holeThing->ringThicknessRange.x() * multiplier, holeSettings.holeThing->ringThicknessRange.y() * multiplier, 3); } void PaletteItem::initHoleSettings(HoleSettings & holeSettings, HoleClassThing * holeThing) { holeSettings.holeThing = holeThing; holeSettings.diameterEdit = holeSettings.thicknessEdit = NULL; holeSettings.diameterValidator = holeSettings.thicknessValidator = NULL; holeSettings.inRadioButton = holeSettings.mmRadioButton = NULL; holeSettings.sizesComboBox = NULL; } bool PaletteItem::setHoleSize(QString & holeSize, bool force, HoleSettings & holeSettings) { QStringList sizes = getSizes(holeSize, holeSettings); if (sizes.count() < 2) return false; if (!force && (holeSettings.holeDiameter.compare(sizes.at(0)) == 0) && (holeSettings.ringThickness.compare(sizes.at(1)) == 0)) { return false; } holeSettings.holeDiameter = sizes.at(0); holeSettings.ringThickness = sizes.at(1); updateEditTexts(holeSettings); updateValidators(holeSettings); updateSizes(holeSettings); return true; } QStringList PaletteItem::getSizes(QString & holeSize, HoleSettings & holeSettings) { QStringList sizes; QString hashedHoleSize = holeSettings.holeThing->holeSizes.value(holeSize); if (hashedHoleSize.isEmpty()) { sizes = holeSize.split(","); } else { sizes = hashedHoleSize.split(","); holeSize = sizes[0] + "," + sizes[1]; } return sizes; } void PaletteItem::changeHoleSize(const QString & newSize) { if (this->m_viewID != ViewLayer::PCBView) { PaletteItem * paletteItem = qobject_cast(modelPart()->viewItem(ViewLayer::PCBView)); if (paletteItem == NULL) return; paletteItem->changeHoleSize(newSize); return; } QString holeSize = newSize; QStringList sizes = getSizes(holeSize, m_holeSettings); if (sizes.count() != 2) return; QString svg = hackSvgHoleSize(sizes.at(0), sizes.at(1)); if (svg.isEmpty()) return; // figure out the new filename QString newModuleID = appendHoleSize(moduleID(), sizes.at(0), sizes.at(1)); QString newFzpFilename = newModuleID + ".fzp"; QString newSvgFilename = "pcb/" + newModuleID + ".svg"; QString fzp = hackFzpHoleSize(newModuleID, newSvgFilename, sizes.at(0) + "," + sizes.at(1)); if (fzp.isEmpty()) return; if (!TextUtils::writeUtf8(PartFactory::fzpPath() + newFzpFilename, fzp)) { return; } if (!TextUtils::writeUtf8(PartFactory::partPath() + newSvgFilename, svg)) { return; } m_propsMap.insert("hole size", newSize); m_propsMap.insert("moduleID", newModuleID); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->swap(family(), newModuleID, m_propsMap, this); } } QString PaletteItem::hackFzpHoleSize(const QString & fzp, const QString & moduleid, int hsix) { QString errorStr; int errorLine; int errorColumn; QDomDocument document; bool result = document.setContent(fzp, &errorStr, &errorLine, &errorColumn); if (!result) { DebugDialog::debug(QString("bad fzp in %1:%2").arg(moduleid).arg(fzp)); } QStringList strings = moduleid.mid(hsix).split("_"); return hackFzpHoleSize(document, moduleid, "pcb/" + moduleid + ".svg", strings.at(2) + "," + strings.at(3)); } QString PaletteItem::hackFzpHoleSize(const QString & newModuleID, const QString & pcbFilename, const QString & newSize) { QFile file(modelPart()->path()); QString errorStr; int errorLine; int errorColumn; QDomDocument document; bool result = document.setContent(&file, &errorStr, &errorLine, &errorColumn); if (!result) { DebugDialog::debug(QString("bad doc fzp in %1:%2 %3 %4").arg(newModuleID).arg(errorStr).arg(errorLine).arg(errorColumn)); } return hackFzpHoleSize(document, newModuleID, pcbFilename, newSize); } QString PaletteItem::hackFzpHoleSize(QDomDocument & document, const QString & newModuleID, const QString & pcbFilename, const QString & newSize) { QDomElement root = document.documentElement(); root.setAttribute("moduleId", newModuleID); QDomElement views = root.firstChildElement("views"); QDomElement pcbView = views.firstChildElement("pcbView"); QDomElement layers = pcbView.firstChildElement("layers"); if (layers.isNull()) return ""; layers.setAttribute("image", pcbFilename); QDomElement properties = root.firstChildElement("properties"); QDomElement prop = properties.firstChildElement("property"); bool gotProp = false; while (!prop.isNull()) { QString name = prop.attribute("name"); if (name.compare("hole size", Qt::CaseInsensitive) == 0) { gotProp = true; TextUtils::replaceChildText(prop, newSize); break; } prop = prop.nextSiblingElement("property"); } if (!gotProp) return ""; return TextUtils::removeXMLEntities(document.toString()); } QString PaletteItem::hackSvgHoleSizeAux(const QString & svg, const QString & expectedFileName) { QDomDocument document; document.setContent(svg); QFileInfo info(expectedFileName); QString baseName = info.completeBaseName(); int hsix = baseName.indexOf(HoleSizePrefix); QStringList strings = baseName.mid(hsix).split("_"); return hackSvgHoleSize(document, strings.at(2), strings.at(3)); } QString PaletteItem::hackSvgHoleSize(const QString & holeDiameter, const QString & ringThickness) { QFile file(filename()); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse pcb svg xml: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return ""; } return hackSvgHoleSize(domDocument, holeDiameter, ringThickness); } QString PaletteItem::hackSvgHoleSize(QDomDocument & domDocument, const QString & holeDiameter, const QString & ringThickness) { QDomElement root = domDocument.documentElement(); double w = TextUtils::convertToInches(root.attribute("width")); QStringList vb = root.attribute("viewBox").split(" "); if (vb.count() != 4) return ""; double wp = vb.at(2).toDouble(); if (wp == 0) return ""; double dpi = wp / w; double rt = TextUtils::convertToInches(ringThickness) * dpi; double hs = TextUtils::convertToInches(holeDiameter) * dpi; double rad = (hs + rt) / 2; QDomNodeList circles = root.elementsByTagName("circle"); for (int i = 0; i < circles.count(); i++) { QDomElement circle = circles.at(i).toElement(); QString id = circle.attribute("id"); if (ConnectorFinder.indexIn(id) == 0) { circle.setAttribute("r", QString::number(rad)); circle.setAttribute("stroke-width", QString::number(rt)); } } QDomNodeList rects = root.elementsByTagName("rect"); for (int i = 0; i < rects.count(); i++) { QDomElement rect = rects.at(i).toElement(); QString id = rect.attribute("id"); if (id.compare("square") == 0) { double oldWidth = rect.attribute("width").toDouble(); double oldX = rect.attribute("x").toDouble(); double oldY = rect.attribute("y").toDouble(); rect.setAttribute("width", QString::number(rad * 2)); rect.setAttribute("height", QString::number(rad * 2)); rect.setAttribute("x", QString::number(oldX + (oldWidth / 2) - rad)); rect.setAttribute("y", QString::number(oldY + (oldWidth / 2) - rad)); rect.setAttribute("stroke-width", QString::number(rt)); } } return TextUtils::removeXMLEntities(domDocument.toString()); } QString PaletteItem::appendHoleSize(const QString & moduleid, const QString & holeSize, const QString & ringThickness) { QString baseName = moduleid; int ix = baseName.lastIndexOf(HoleSizePrefix); if (ix >= 0) { baseName.truncate(ix); } return baseName + QString("%1%2_%3").arg(HoleSizePrefix).arg(holeSize).arg(ringThickness); } void PaletteItem::generateSwap(const QString & text, GenModuleID genModuleID, GenFzp genFzp, GenSvg makeBreadboardSvg, GenSvg makeSchematicSvg, GenSvg makePcbSvg) { FamilyPropertyComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; QMap propsMap(m_propsMap); propsMap.insert(comboBox->prop(), text); QString newModuleID = genModuleID(propsMap); if (!newModuleID.contains("smd", Qt::CaseInsensitive)) { // add hole size int ix = moduleID().indexOf(HoleSizePrefix); if (ix >= 0) { newModuleID.append(moduleID().mid(ix)); } } QString path; if (!PartFactory::fzpFileExists(newModuleID, path)) { QString fzp = genFzp(newModuleID); TextUtils::writeUtf8(path, fzp); QDomDocument doc; doc.setContent(fzp); QHash viewNames; QDomElement root = doc.documentElement(); QDomElement views = root.firstChildElement("views"); QDomElement view = views.firstChildElement(); while (!view.isNull()) { viewNames.insert(view.tagName(), view.attribute("image", "")); view = view.nextSiblingElement(); } QString name = viewNames.value("breadboardView", ""); if (!PartFactory::svgFileExists(name, path)) { QString svg = makeBreadboardSvg(name); TextUtils::writeUtf8(path, svg); } name = viewNames.value("schematicView", ""); if (!PartFactory::svgFileExists(name, path)) { QString svg = makeSchematicSvg(name); TextUtils::writeUtf8(path, svg); } name = viewNames.value("pcbView", ""); if (!PartFactory::svgFileExists(name, path)) { QString svg = makePcbSvg(name); TextUtils::writeUtf8(path, svg); } } m_propsMap.insert("moduleID", newModuleID); } void PaletteItem::changeUnits(bool) { QString newVal = changeUnits(m_holeSettings); changeHoleSize(newVal); } QString PaletteItem::changeUnits(HoleSettings & holeSettings) { double hd = TextUtils::convertToInches(holeSettings.holeDiameter); double rt = TextUtils::convertToInches(holeSettings.ringThickness); QString newVal; if (holeSettings.currentUnits() == "in") { newVal = QString("%1in,%2in").arg(hd).arg(rt); } else { newVal = QString("%1mm,%2mm").arg(hd * 25.4).arg(rt * 25.4); } QStringList sizes = newVal.split(","); holeSettings.ringThickness = sizes.at(1); holeSettings.holeDiameter = sizes.at(0); updateValidators(holeSettings); updateSizes(holeSettings); updateEditTexts(holeSettings); return newVal; } void PaletteItem::changeThickness() { if (changeThickness(m_holeSettings, sender())) { QLineEdit * edit = qobject_cast(sender()); changeHoleSize(m_holeSettings.holeDiameter + "," + edit->text() + m_holeSettings.currentUnits()); } } bool PaletteItem::changeThickness(HoleSettings & holeSettings, QObject * sender) { QLineEdit * edit = qobject_cast(sender); if (edit == NULL) return false; double newValue = edit->text().toDouble(); QString temp = holeSettings.ringThickness; temp.chop(2); double oldValue = temp.toDouble(); return (newValue != oldValue); } void PaletteItem::changeDiameter() { if (changeDiameter(m_holeSettings, sender())) { QLineEdit * edit = qobject_cast(sender()); changeHoleSize(edit->text() + m_holeSettings.currentUnits() + "," + m_holeSettings.ringThickness); } } bool PaletteItem::changeDiameter(HoleSettings & holeSettings, QObject * sender) { QLineEdit * edit = qobject_cast(sender); if (edit == NULL) return false; double newValue = edit->text().toDouble(); QString temp = holeSettings.holeDiameter; temp.chop(2); double oldValue = temp.toDouble(); return (newValue != oldValue); } bool PaletteItem::makeLocalModifications(QByteArray & svg, const QString & filename) { // a bottleneck for modifying part svg xml at setupImage time // for saved-as-new-part parts (i.e. that are no longer MysteryParts) that still have a chip-label or custom pin names // also handles adding a title if there is a label id in the switch (m_viewID) { case ViewLayer::PCBView: return false; default: if (itemType() != ModelPart::Part) return false; if (filename.startsWith("icon")) return false; break; } bool gotChipLabel = false; QString chipLabel = modelPart()->properties().value("chip label", ""); if (!chipLabel.isEmpty()) { svg = TextUtils::replaceTextElement(svg, "label", chipLabel); gotChipLabel = true; } bool modified = false; if (m_viewID == ViewLayer::SchematicView) { QString value = modelPart()->properties().value("editable pin labels", ""); if (value.compare("true") == 0) { bool hasLayout, sip; QStringList labels = sipOrDipOrLabels(hasLayout, sip); if (labels.count() > 0) { svg = PartFactory::makeSchematicSipOrDipOr(labels, hasLayout, sip).toUtf8(); modified = true; } } gotChipLabel = true; } if (gotChipLabel) return modified; int rix = svg.indexOf("label"); if (rix >= 0) { rix = qMax(0, rix - 4); // backup for id=" int ix = svg.indexOf("id=\"label\"", rix); if (ix < 0) { ix = svg.indexOf("id='label'", rix); } if (ix >= 0) { int tix = svg.lastIndexOf("title()); modified = true; } } } return modified; } QStringList PaletteItem::sipOrDipOrLabels(bool & hasLayout, bool & sip) { hasLayout = sip = false; bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (labels.count() == 0) return labels; // part was formerly a mystery part or generic ic ... QHash properties = modelPart()->properties(); foreach (QString key, properties.keys()) { QString value = properties.value(key); if (key.compare("layout", Qt::CaseInsensitive) == 0) { // was a mystery part hasLayout = true; break; } if (key.compare("package") == 0) { // was a generic ic sip = value.contains("sip", Qt::CaseInsensitive); } } return labels; } void PaletteItem::resetLayerKin(const QString & svg) { QString svgNoText = SvgFileSplitter::hideText3(svg); resetRenderer(svgNoText); foreach (ItemBase * lkpi, layerKin()) { if (lkpi->viewLayerID() == ViewLayer::SchematicText) { bool hasText; QString svgText = SvgFileSplitter::showText3(svg, hasText); lkpi->resetRenderer(svgText); lkpi->setProperty("textSvg", svgText); qobject_cast(lkpi)->clearTextThings(); break; } } } QTransform PaletteItem::untransform() { //DebugDialog::debug("untransform"); QTransform chiefTransform = this->transform(); chiefTransform.setMatrix(chiefTransform.m11(), chiefTransform.m12(), chiefTransform.m13(), chiefTransform.m21(), chiefTransform.m22(), chiefTransform.m23(), 0, 0, chiefTransform.m33()); bool identity = chiefTransform.isIdentity(); if (!identity) { QTransform invert = chiefTransform.inverted(); transformItem(invert, false); foreach (ItemBase * lkpi, layerKin()) { lkpi->transformItem(invert, false); } } return chiefTransform; } void PaletteItem::retransform(const QTransform & chiefTransform) { //DebugDialog::debug("retransform"); if (!chiefTransform.isIdentity()) { transformItem(chiefTransform, false); foreach (ItemBase * lkpi, layerKin()) { lkpi->transformItem(chiefTransform, false); } } } fritzing-app-0.9.2b/src/items/paletteitem.h000066400000000000000000000171401250202676700207060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef PALETTEITEM_H #define PALETTEITEM_H #include #include #include #include #include #include #include #include #include "paletteitembase.h" #include "../viewlayer.h" typedef QString (*GenModuleID)(QMap & currPropsMap); typedef QString (*GenSvg)(const QString & expectedFileName); typedef QString (*GenFzp)(const QString &); struct HoleClassThing { QString holeSize; QString ringThickness; QString holeSizeValue; QHash holeSizes; QList holeSizeKeys; // need this for menu item ordering purposes QPointF ringThicknessRange; QPointF holeDiameterRange; }; struct HoleSettings { QString holeDiameter; QString ringThickness; HoleClassThing * holeThing; QPointer diameterValidator; QPointer thicknessValidator; QPointer diameterEdit; QPointer thicknessEdit; QPointer inRadioButton; QPointer mmRadioButton; QPointer sizesComboBox; QString currentUnits(); QString holeSize(); }; class PaletteItem : public PaletteItemBase { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call PaletteItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~PaletteItem(); void removeLayerKin(); void addLayerKin(class LayerKinPaletteItem * lkpi); const QList & layerKin(); virtual void loadLayerKin(const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement); void rotateItem(double degrees, bool includeRatsnest); void flipItem(Qt::Orientations orientation); void moveItem(ViewGeometry & viewGeometry); void transformItem2(const QMatrix &); void setItemPos(QPointF & pos); bool renderImage(ModelPart * modelPart, ViewLayer::ViewID viewID, const LayerHash & viewLayers, ViewLayer::ViewLayerID, bool doConnectors, QString & error); void setTransforms(); void syncKinMoved(QPointF offset, QPointF loc); void setInstanceTitle(const QString&, bool initial); bool swap(ModelPart* newModelPart, const LayerHash &layerHash, bool reinit, class SwapCommand *); void setHidden(bool hidden); void setInactive(bool inactivate); bool collectFemaleConnectees(QSet & items); void collectWireConnectees(QSet & wires); void clearModelPart(); bool mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *); void resetID(); void slamZ(double z); void resetImage(class InfoGraphicsView *); void resetKinImage(ItemBase * layerKin, InfoGraphicsView * infoGraphicsView); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); QStringList collectValues(const QString & family, const QString & prop, QString & value); virtual bool changePinLabels(bool singleRow, bool sip); QStringList getPinLabels(bool & hasLocal); void renamePins(const QStringList & labels, bool singleRow); void resetConnectors(); void resetConnectors(ItemBase * otherLayer, FSvgRenderer * otherLayerRenderer); void resetConnector(ItemBase * itemBase, SvgIdLayer * svgIdLayer); QStringList sipOrDipOrLabels(bool & hasLayout, bool & sip); void resetLayerKin(const QString & svg); QTransform untransform(); void retransform(const QTransform &); public: static QString genFZP(const QString & moduleid, const QString & templateName, int minPins, int maxPins, int steps, bool smd); static QWidget * createHoleSettings(QWidget * parent, HoleSettings &, bool swappingEnabled, const QString & currentHoleSize, bool advanced); static void updateValidators(HoleSettings &); static void updateEditTexts(HoleSettings &); static void updateSizes(HoleSettings &); static void initHoleSettings(HoleSettings & holeSettings, HoleClassThing *); static bool setHoleSize(QString & holeSize, bool force, HoleSettings & holeSettings); static QString changeUnits(HoleSettings &); static bool changeDiameter(HoleSettings & holeSettings, QObject * sender); static bool changeThickness(HoleSettings & holeSettings, QObject * sender); signals: void pinLabelSwap(ItemBase *, const QString & moduleID); protected slots: void openPinLabelDialog(); protected: void syncKinSelection(bool selected, PaletteItemBase * originator); QVariant itemChange(GraphicsItemChange change, const QVariant &value); void updateConnections(bool includeRatsnest, QList & already); void mousePressEvent(QGraphicsSceneMouseEvent *event); void figureHover(); bool isSingleRow(const QList & connectorItems); QList sortConnectors(); QString hackSvgHoleSize(const QString & holeDiameter, const QString & ringThickness); QString hackFzpHoleSize(const QString & moduleID, const QString & pcbFilename, const QString & holeSize); QString appendHoleSize(const QString & moduleID, const QString & holeSize, const QString & ringThickness); void generateSwap(const QString & text, GenModuleID, GenFzp, GenSvg makeBreadboardSvg, GenSvg makeSchematicSvg, GenSvg makePcbSvg); bool makeLocalModifications(QByteArray & svg, const QString & filename); void makeOneKin(qint64 & id, ViewLayer::ViewLayerID, ViewLayer::ViewLayerPlacement, ViewGeometry &, const LayerHash &); protected: void setUpHoleSizes(const QString & type, HoleClassThing &); void setUpHoleSizesAux(HoleClassThing &, const QString & type); bool collectHoleSizeInfo(const QString & defaultHoleSizeValue, QWidget * parent, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget); static QStringList getSizes(QString & holeSize, HoleSettings &); static QString hackFzpHoleSize(QDomDocument & document, const QString & newModuleID, const QString & pcbFilename, const QString & newSize); static QString hackFzpHoleSize(const QString & fzp, const QString & moduleid, int hsix); static QString hackSvgHoleSize(QDomDocument & domDocument, const QString & holeDiameter, const QString & ringThickness); static QString hackSvgHoleSizeAux(const QString & svg, const QString & expectedFileName); protected slots: virtual void changeHoleSize(const QString &); virtual void changeUnits(bool); void changeDiameter(); void changeThickness(); public: static const QString HoleSizePrefix; protected: QList m_layerKin; HoleSettings m_holeSettings; int m_flipCount; }; #endif fritzing-app-0.9.2b/src/items/paletteitembase.cpp000066400000000000000000000613511250202676700220770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "paletteitembase.h" #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../fsvgrenderer.h" #include "../svg/svgfilesplitter.h" #include "../layerattributes.h" #include "layerkinpaletteitem.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include "wire.h" #include "partlabel.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/cursormaster.h" #include #include #include #include #include #include #include #include #include static QPointF RotationCenter; static QPointF RotationAxis; static QTransform OriginalTransform; PaletteItemBase::PaletteItemBase(ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu ) : ItemBase(modelPart, viewID, viewGeometry, id, itemMenu) { m_syncSelected = false; m_offset.setX(0); m_offset.setY(0); m_blockItemSelectedChange = false; this->setPos(viewGeometry.loc()); setFlag(QGraphicsItem::ItemIsSelectable, true); setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); setAcceptHoverEvents(true); if (hasPartNumberProperty()) { QString savedValue = modelPart->localProp(ModelPartShared::PartNumberPropertyName).toString(); if (savedValue.isEmpty()) { savedValue = modelPart->properties().value(ModelPartShared::PartNumberPropertyName, ""); if (!savedValue.isEmpty()) { modelPart->setLocalProp(ModelPartShared::PartNumberPropertyName, savedValue); } } } } QRectF PaletteItemBase::boundingRectWithoutLegs() const { return QRectF(0, 0, m_size.width(), m_size.height()); } QRectF PaletteItemBase::boundingRect() const { if (!hasRubberBandLeg()) { return QRectF(0, 0, m_size.width(), m_size.height()); } //debugInfo(QString("bounding rect %1 %2 %3 %4").arg(r.left()).arg(r.top()).arg(r.width()).arg(r.height())); return shape().controlPointRect(); } QPainterPath PaletteItemBase::hoverShape() const { // TODO: figure out real shape of svg QPainterPath path; path.addRect(0, 0, m_size.width(), m_size.height()); if (!hasRubberBandLeg()) return path; foreach (ConnectorItem * connectorItem, cachedConnectorItemsConst()) { if (connectorItem->hasRubberBandLeg()) { path.addPath(connectorItem->mapToParent(connectorItem->hoverShape())); } } path.setFillRule(Qt::WindingFill); return path; } QPainterPath PaletteItemBase::shape() const { // TODO: figure out real shape of svg QPainterPath path; if (m_squashShape) return path; path.addRect(0, 0, m_size.width(), m_size.height()); if (!hasRubberBandLeg()) return path; foreach (ConnectorItem * connectorItem, cachedConnectorItemsConst()) { if (connectorItem->hasRubberBandLeg()) { path.addPath(connectorItem->mapToParent(connectorItem->shape())); } } path.setFillRule(Qt::WindingFill); return path; } void PaletteItemBase::saveGeometry() { m_viewGeometry.setLoc(this->pos()); m_viewGeometry.setSelected(this->isSelected()); m_viewGeometry.setZ(this->zValue()); } bool PaletteItemBase::itemMoved() { return (this->pos() != m_viewGeometry.loc()); } void PaletteItemBase::moveItem(ViewGeometry & viewGeometry) { this->setPos(viewGeometry.loc()); QList already; updateConnections(false, already); } void PaletteItemBase::saveInstanceLocation(QXmlStreamWriter & streamWriter) { saveLocAndTransform(streamWriter); } void PaletteItemBase::syncKinSelection(bool selected, PaletteItemBase * originator) { Q_UNUSED(originator); m_syncSelected = selected; } void PaletteItemBase::syncKinMoved(QPointF offset, QPointF newPos) { Q_UNUSED(offset); Q_UNUSED(newPos); } QPointF PaletteItemBase::syncMoved() { return m_syncMoved; } void PaletteItemBase::blockItemSelectedChange(bool selected) { m_blockItemSelectedChange = true; m_blockItemSelectedValue = selected; } bool PaletteItemBase::syncSelected() { return m_syncSelected; } void PaletteItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_hidden || m_layerHidden) return; ItemBase::paint(painter, option, widget); } void PaletteItemBase::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_hidden || m_layerHidden) return; if (!hasRubberBandLeg()) { ItemBase::paintHover(painter, option, widget); return; } QPainterPath path; path.addRect(0, 0, m_size.width(), m_size.height()); ItemBase::paintHover(painter, option, widget, path); } void PaletteItemBase::paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_hidden || m_layerHidden) return; if (!hasRubberBandLeg()) { ItemBase::paintSelected(painter, option, widget); return; } QRectF r(0, 0, m_size.width(), m_size.height()); GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, r, QPainterPath()); } void PaletteItemBase::mousePressConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->mousePressConnectorEvent(connectorItem, event); } } bool PaletteItemBase::acceptsMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent * event) { Q_UNUSED(event); //if (m_viewID != ViewLayer::PCBView) { return true; //} } bool PaletteItemBase::mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event) { Q_UNUSED(originalItem); setInRotation(false); QPointF corner; if (freeRotationAllowed(event->modifiers()) && inRotationLocation(event->scenePos(), event->modifiers(), corner)) { this->saveGeometry(); setInRotation(true); RotationCenter = mapToScene(this->boundingRectWithoutLegs().center()); RotationAxis = event->scenePos(); OriginalTransform = this->transform(); /* DebugDialog::debug(QString("%11:in rotation:%1,%2 a:%3,%4 t:%5,%6,%7,%8 %9,%10") .arg(RotationCenter.x()).arg(RotationCenter.y()) .arg(RotationAxis.x()).arg(RotationAxis.y()) .arg(OriginalTransform.m11()).arg(OriginalTransform.m12()).arg(OriginalTransform.m21()).arg(OriginalTransform.m22()) .arg(OriginalTransform.dx()).arg(OriginalTransform.dy()) .arg((long) this, 0, 16) ); */ this->debugInfo("in rotation"); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) infoGraphicsView->setAnyInRotation(); return false; } ItemBase::mousePressEvent(event); if (canFindConnectorsUnder()) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { connectorItem->setOverConnectorItem(NULL); } } return false; } void PaletteItemBase::mouseMoveEventK(PaletteItemBase *, QGraphicsSceneMouseEvent *) { } void PaletteItemBase::mouseReleaseEventK(PaletteItemBase *, QGraphicsSceneMouseEvent *) { } void PaletteItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (!inRotation()) { ItemBase::mouseMoveEvent(event); return; } // TODO: doesn't account for scaling // see http://www.gamedev.net/topic/441695-transform-matrix-decomposition/ double originalAngle = atan2(OriginalTransform.m12(), OriginalTransform.m11()) * 180 / M_PI; double a1 = atan2(RotationAxis.y() - RotationCenter.y(), RotationAxis.x() - RotationCenter.x()); double a2 = atan2(event->scenePos().y() - RotationCenter.y(), event->scenePos().x() - RotationCenter.x()); double deltaAngle = (a2 - a1) * 180 / M_PI; //DebugDialog::debug(QString("original:%1 delta:%2").arg(originalAngle).arg(deltaAngle)); switch (m_viewID) { case ViewLayer::BreadboardView: case ViewLayer::PCBView: { double nearest = qRound((originalAngle + deltaAngle) / 45) * 45; if (qAbs(originalAngle + deltaAngle - nearest) < 6) { deltaAngle = nearest - originalAngle; //DebugDialog::debug(QString("\tdelta angle %1").arg(deltaAngle)); } } break; case ViewLayer::SchematicView: { double nearest = qRound((originalAngle + deltaAngle) / 90) * 90; deltaAngle = nearest - originalAngle; } break; default: return; } ItemBase * chief = layerKinChief(); // restore viewGeometry to original angle chief->getViewGeometry().setTransform(OriginalTransform); foreach (ItemBase * itemBase, chief->layerKin()) { itemBase->getViewGeometry().setTransform(OriginalTransform); } //DebugDialog::debug(QString("rotating item %1 da:%2 oa:%3 %4").arg(QTime::currentTime().toString("HH:mm:ss.zzz")).arg(deltaAngle).arg(originalAngle).arg((long) this, 0, 16)); chief->rotateItem(deltaAngle, true); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(chief); if (infoGraphicsView) infoGraphicsView->updateRotation(chief); } void PaletteItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (!inRotation()) { ItemBase::mouseReleaseEvent(event); return; } setInRotation(false); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) { // TODO: doesn't account for scaling // see: http://www.gamedev.net/topic/441695-transform-matrix-decomposition/ double originalAngle = atan2(OriginalTransform.m12(), OriginalTransform.m11()) * 180 / M_PI; double currentAngle = atan2(transform().m12(), transform().m11()) * 180 / M_PI; this->layerKinChief()->rotateItem(originalAngle - currentAngle, true); // put it back; undo command will redo it saveGeometry(); infoGraphicsView->triggerRotate(this->layerKinChief(), currentAngle - originalAngle); } } bool PaletteItemBase::canFindConnectorsUnder() { return true; } void PaletteItemBase::findConnectorsUnder() { if (!canFindConnectorsUnder()) return; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { switch (connectorItem->connector()->connectorType()) { case Connector::Female: case Connector::Pad: continue; default: break; } connectorItem->findConnectorUnder(true, false, ConnectorItem::emptyConnectorItemList, false, NULL); } } bool PaletteItemBase::collectFemaleConnectees(QSet & items) { bool hasMale = false; foreach (ConnectorItem * item, cachedConnectorItems()) { if (item->connectorType() == Connector::Male) { hasMale = true; continue; } if (item->connectorType() != Connector::Female) continue; foreach (ConnectorItem * toConnectorItem, item->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) continue; if (!toConnectorItem->attachedTo()->isVisible()) continue; items.insert(toConnectorItem->attachedTo()); } } return hasMale; } void PaletteItemBase::collectWireConnectees(QSet & wires) { foreach (ConnectorItem * item, cachedConnectorItems()) { foreach (ConnectorItem * toConnectorItem, item->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { if (toConnectorItem->attachedTo()->isVisible()) { wires.insert(qobject_cast(toConnectorItem->attachedTo())); } } } } } bool PaletteItemBase::setUpImage(ModelPart * modelPart, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { FSvgRenderer * renderer = ItemBase::setUpImage(modelPart, layerAttributes); if (renderer == NULL) { return false; } cacheLoaded(layerAttributes); m_canFlipVertical = modelPart->canFlipVertical(layerAttributes.viewID); m_canFlipHorizontal = modelPart->canFlipHorizontal(layerAttributes.viewID); m_filename = layerAttributes.filename(); //DebugDialog::debug(QString("filename %1").arg(m_filename) ); setSticky(modelPart->anySticky(layerAttributes.viewID)); QString elementID = ViewLayer::viewLayerXmlNameFromID(layerAttributes.viewLayerID); setViewLayerID(elementID, viewLayers); //DebugDialog::debug(QString("setting layer %1 view:%2 z:%3").arg(modelPart->title()).arg(viewID).arg(this->z()) ); this->setZValue(this->z()); //DebugDialog::debug("loaded"); //DebugDialog::debug(layerAttributes.loaded()); this->setSharedRendererEx(renderer); m_svg = true; if (layerAttributes.doConnectors) { setUpConnectors(renderer, modelPart->ignoreTerminalPoints()); } if (!m_viewGeometry.transform().isIdentity()) { setInitialTransform(m_viewGeometry.transform()); update(); } return true; } void PaletteItemBase::setUpConnectors(FSvgRenderer * renderer, bool ignoreTerminalPoints) { clearConnectorItemCache(); if (m_viewID == ViewLayer::PCBView && ViewLayer::isNonCopperLayer(m_viewLayerID)) { //DebugDialog::debug(QString("skip connectors: %1 vid:%2 vlid:%3") // .arg(this->title()) // .arg(m_viewID) // .arg(m_viewLayerID) // ); // don't waste time return; } foreach (Connector * connector, m_modelPart->connectors().values()) { if (connector == NULL) continue; //DebugDialog::debug(QString("id:%1 vid:%2 vlid:%3") // .arg(connector->connectorSharedID()) // .arg(m_viewID) // .arg(m_viewLayerID) // ); SvgIdLayer * svgIdLayer = connector->fullPinInfo(m_viewID, m_viewLayerID); if (svgIdLayer == NULL) { DebugDialog::debug(QString("svgidlayer fail %1 vid:%2 vlid:%3 %4") .arg(connector->connectorSharedID()) .arg(m_viewID) .arg(m_viewLayerID) .arg(m_modelPart->path()) ); continue; } bool result = renderer->setUpConnector(svgIdLayer, ignoreTerminalPoints, viewLayerPlacement()); if (!result) { DebugDialog::debug(QString("setup connector fail %1 vid:%2 vlid:%3 %4") .arg(connector->connectorSharedID()) .arg(m_viewID) .arg(m_viewLayerID) .arg(m_modelPart->path()) ); continue; } ConnectorItem * connectorItem = newConnectorItem(connector); connectorItem->setHybrid(svgIdLayer->m_hybrid); connectorItem->setRect(svgIdLayer->rect(viewLayerPlacement())); connectorItem->setTerminalPoint(svgIdLayer->point(viewLayerPlacement())); connectorItem->setRadius(svgIdLayer->m_radius, svgIdLayer->m_strokeWidth); connectorItem->setIsPath(svgIdLayer->m_path); if (!svgIdLayer->m_legId.isEmpty()) { m_hasRubberBandLeg = true; connectorItem->setRubberBandLeg(QColor(svgIdLayer->m_legColor), svgIdLayer->m_legStrokeWidth, svgIdLayer->m_legLine); } //DebugDialog::debug(QString("terminal point %1 %2").arg(terminalPoint.x()).arg(terminalPoint.y()) ); } foreach (SvgIdLayer * svgIdLayer, renderer->setUpNonConnectors(viewLayerPlacement())) { if (svgIdLayer == NULL) continue; NonConnectorItem * nonConnectorItem = new NonConnectorItem(this); //DebugDialog::debug( QString("in layer %1 with z %2") //.arg(ViewLayer::viewLayerNameFromID(m_viewLayerID)) //.arg(this->zValue()) ); nonConnectorItem->setRect(svgIdLayer->rect(viewLayerPlacement())); nonConnectorItem->setRadius(svgIdLayer->m_radius, svgIdLayer->m_strokeWidth); nonConnectorItem->setIsPath(svgIdLayer->m_path); //DebugDialog::debug(QString("terminal point %1 %2").arg(terminalPoint.x()).arg(terminalPoint.y()) ); delete svgIdLayer; } } void PaletteItemBase::connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already) { // not sure this is necessary any longer return; if (from->connectorType() != Connector::Female) return; // female connectors really only operate in breadboard view if (m_viewID != ViewLayer::BreadboardView) return; QTransform t = this->transform(); if (t.isRotating()) { // map a square and see if it's a diamond QRectF test(0, 0, 10, 10); QRectF result = t.mapRect(test); if (result.width() != test.width() || result.height() != test.height()) { return; } } QPointF fromTerminalPoint = from->sceneAdjustedTerminalPoint(to); QPointF toTerminalPoint = to->sceneAdjustedTerminalPoint(from); if (fromTerminalPoint == toTerminalPoint) return; this->setPos(this->pos() + fromTerminalPoint - toTerminalPoint); updateConnections(false, already); } void PaletteItemBase::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) { // debugInfo("hover enter paletteitembase"); ItemBase::hoverEnterEvent(event); if (event->isAccepted()) { if (hasRubberBandLeg()) { //DebugDialog::debug("---pab set override cursor"); CursorMaster::instance()->addCursor(this, cursor()); bool connected = false; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0) { connected = true; break; } } } checkFreeRotation(event->modifiers(), event->scenePos()); } } void PaletteItemBase::hoverMoveEvent ( QGraphicsSceneHoverEvent * event ) { checkFreeRotation(event->modifiers(), event->scenePos()); } void PaletteItemBase::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { if (hasRubberBandLeg()) { //DebugDialog::debug("------pab restore override cursor"); } CursorMaster::instance()->removeCursor(this); ItemBase::hoverLeaveEvent(event); } void PaletteItemBase::cursorKeyEvent(Qt::KeyboardModifiers modifiers) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); QPoint p = infoGraphicsView->mapFromGlobal(QCursor::pos()); checkFreeRotation(modifiers, infoGraphicsView->mapToScene(p)); if (hasRubberBandLeg()) { QCursor cursor; if (modifiers & altOrMetaModifier()) { cursor = *CursorMaster::RubberbandCursor; } else { cursor = *CursorMaster::MoveCursor; } CursorMaster::instance()->addCursor(this, cursor); } } void PaletteItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { ItemBase::contextMenuEvent(event); } LayerKinPaletteItem *PaletteItemBase::newLayerKinPaletteItem(PaletteItemBase * chief, ModelPart * modelPart, const ViewGeometry & viewGeometry, long id, QMenu* itemMenu, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { LayerKinPaletteItem *lk = NULL; if (layerAttributes.viewLayerID == ViewLayer::SchematicText) { lk = new SchematicTextLayerKinPaletteItem(chief, modelPart, layerAttributes.viewID, viewGeometry, id, itemMenu); } else { lk = new LayerKinPaletteItem(chief, modelPart, layerAttributes.viewID, viewGeometry, id, itemMenu); } lk->initLKPI(layerAttributes, viewLayers); return lk; } QString PaletteItemBase::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString xmlName = ViewLayer::viewLayerXmlNameFromID(viewLayerID); QString path = filename(); Qt::Orientations orientation = Qt::Vertical; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) { orientation = infoGraphicsView->smdOrientation(); } QDomDocument flipDoc; getFlipDoc(modelPart(), path, viewLayerID, m_viewLayerPlacement, flipDoc, orientation); //DebugDialog::debug(QString("path: %1").arg(path)); QString svg = svgHash.value(path + xmlName, ""); if (!svg.isEmpty()) return svg; SvgFileSplitter splitter; bool result; if (flipDoc.isNull()) { result = splitter.split(path, xmlName); } else { QString f = flipDoc.toString(); result = splitter.splitString(f, xmlName); } if (!result) { return ""; } if (hasRubberBandLeg()) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (!connectorItem->hasRubberBandLeg()) continue; splitter.gReplace(connectorItem->legID(m_viewID, m_viewLayerID)); } } result = splitter.normalize(dpi, xmlName, blackOnly, factor); if (!result) { return ""; } svg = splitter.elementString(xmlName); svgHash.insert(path + xmlName, svg); return svg; } bool PaletteItemBase::canEditPart() { if (itemType() == ModelPart::Part) return true; return ItemBase::canEditPart(); } bool PaletteItemBase::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare(ModelPartShared::PartNumberPropertyName, Qt::CaseInsensitive) == 0) { returnProp = TranslatedPropertyNames.value(prop); QLineEdit * lineEdit = new QLineEdit(); lineEdit->setEnabled(swappingEnabled); QString current = m_modelPart->localProp(ModelPartShared::PartNumberPropertyName).toString(); lineEdit->setText(current); connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(partPropertyEntry())); lineEdit->setObjectName("infoViewLineEdit"); returnWidget = lineEdit; returnValue = current; return true; } return ItemBase::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void PaletteItemBase::setProp(const QString & prop, const QString & value) { if (prop.compare(ModelPartShared::PartNumberPropertyName) == 0) { modelPart()->setLocalProp(ModelPartShared::PartNumberPropertyName, value); if (m_partLabel) m_partLabel->displayTextsIf(); return; } ItemBase::setProp(prop, value); } void PaletteItemBase::partPropertyEntry() { QLineEdit * lineEdit = qobject_cast(sender()); if (lineEdit == NULL) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, ModelPartShared::PartNumberPropertyName, "", m_modelPart->localProp(ModelPartShared::PartNumberPropertyName).toString(), lineEdit->text(), true); } } const QCursor * PaletteItemBase::getCursor(Qt::KeyboardModifiers modifiers) { if (hasRubberBandLeg()) { if ((modifiers & altOrMetaModifier())) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0) { return CursorMaster::RubberbandCursor; } } } } //DebugDialog::debug("returning move cursor"); return CursorMaster::MoveCursor; } bool PaletteItemBase::freeRotationAllowed(Qt::KeyboardModifiers modifiers) { Q_UNUSED(modifiers); //if ((modifiers & altOrMetaModifier()) == 0) return false; if (!isSelected()) return false; if (this->moveLock()) return false; return rotation45Allowed(); } bool PaletteItemBase::freeRotationAllowed() { if (viewID() == ViewLayer::SchematicView) return false; return rotation45Allowed(); } bool PaletteItemBase::inRotationLocation(QPointF scenePos, Qt::KeyboardModifiers modifiers, QPointF & returnPoint) { if (!freeRotationAllowed(modifiers)) return false; if (m_viewID == ViewLayer::SchematicView) return false; QRectF r = this->boundingRectWithoutLegs(); QPolygonF polygon; polygon.append(mapToScene(r.topLeft())); polygon.append(mapToScene(r.topRight())); polygon.append(mapToScene(r.bottomRight())); polygon.append(mapToScene(r.bottomLeft())); foreach (QPointF p, polygon) { double dsqd = GraphicsUtils::distanceSqd(p, scenePos); if (dsqd < 9) { returnPoint = p; return true; } } return false; } void PaletteItemBase::checkFreeRotation(Qt::KeyboardModifiers modifiers, QPointF scenePos) { if (!freeRotationAllowed(modifiers)) return; QPointF returnPoint; bool inCorner = inRotationLocation(scenePos, modifiers, returnPoint); if (inCorner) { CursorMaster::instance()->addCursor(this, *CursorMaster::RotateCursor); } else { CursorMaster::instance()->addCursor(this, cursor()); } } QString PaletteItemBase::normalizeSvg(QString & svg, ViewLayer::ViewLayerID viewLayerID, bool blackOnly, double dpi, double & factor) { QString xmlName = ViewLayer::viewLayerXmlNameFromID(viewLayerID); SvgFileSplitter splitter; bool result = splitter.splitString(svg, xmlName); if (!result) { return ""; } result = splitter.normalize(dpi, xmlName, blackOnly, factor); if (!result) { return ""; } return splitter.elementString(xmlName); } void PaletteItemBase::setInitialTransform(const QTransform &matrix) { setTransform(matrix); } void PaletteItemBase::cacheLoaded(const LayerAttributes &) { } /* void PaletteItemBase::setPos(const QPointF & pos) { ItemBase::setPos(pos); DebugDialog::debug(QString("set pos %1 %2, %3").arg(this->id()).arg(pos.x()).arg(pos.y()) ); } void PaletteItemBase::setPos(double x, double y) { ItemBase::setPos(x, y); } */ fritzing-app-0.9.2b/src/items/paletteitembase.h000066400000000000000000000120441250202676700215370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef PALETTEITEMBASE_H #define PALETTEITEMBASE_H #include #include #include #include "../model/modelpart.h" #include "itembase.h" #include "../utils/cursormaster.h" class LayerKinPaletteItem; class PaletteItemBase : public ItemBase, public CursorKeyListener { Q_OBJECT public: PaletteItemBase(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu); void saveGeometry(); bool itemMoved(); virtual void saveInstanceLocation(QXmlStreamWriter &); void moveItem(ViewGeometry &); virtual void syncKinSelection(bool selected, PaletteItemBase *originator); virtual void syncKinMoved(QPointF offset, QPointF loc); void blockItemSelectedChange(bool selected); bool syncSelected(); QPointF syncMoved(); void mousePressConnectorEvent(class ConnectorItem *, QGraphicsSceneMouseEvent *); bool acceptsMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); void connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already); bool collectFemaleConnectees(QSet & items); void collectWireConnectees(QSet & wires); virtual bool mousePressEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event); virtual void mouseMoveEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEventK(PaletteItemBase * originalItem, QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent(QGraphicsSceneHoverEvent * event ); void hoverMoveEvent(QGraphicsSceneHoverEvent * event ); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); //bool isBuriedConnectorHit(QGraphicsSceneMouseEvent *event); QRectF boundingRect() const; QRectF boundingRectWithoutLegs() const; QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); virtual bool canEditPart(); QPainterPath shape() const; QPainterPath hoverShape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void setProp(const QString & prop, const QString & value); const QCursor * getCursor(Qt::KeyboardModifiers); void cursorKeyEvent(Qt::KeyboardModifiers modifiers); /* // for debugging void setPos(const QPointF & pos); void setPos(double x, double y); */ protected: static QString normalizeSvg(QString & svg, ViewLayer::ViewLayerID viewLayerID, bool blackOnly, double dpi, double & factor); protected: void setUpConnectors(FSvgRenderer *, bool ignoreTerminalPoints); void findConnectorsUnder(); virtual bool canFindConnectorsUnder(); bool inRotationLocation(QPointF scenePos, Qt::KeyboardModifiers modifiers, QPointF & returnPoint); virtual bool freeRotationAllowed(Qt::KeyboardModifiers modifiers); bool freeRotationAllowed(); void checkFreeRotation(Qt::KeyboardModifiers modifiers, QPointF scenePos); virtual LayerKinPaletteItem * newLayerKinPaletteItem(PaletteItemBase * chief, ModelPart *, const ViewGeometry &, long id, QMenu* itemMenu, const LayerHash &, LayerAttributes &); virtual void setInitialTransform(const QTransform &); virtual void cacheLoaded(const LayerAttributes &); protected slots: void partPropertyEntry(); protected: bool m_blockItemSelectedChange; bool m_blockItemSelectedValue; QPointF m_offset; bool m_syncSelected; QPointF m_syncMoved; bool m_svg; }; #endif fritzing-app-0.9.2b/src/items/partfactory.cpp000066400000000000000000000620231250202676700212620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6962 $: $Author: irascibl@gmail.com $: $Date: 2013-04-14 00:08:36 +0200 (So, 14. Apr 2013) $ ********************************************************************/ #include "partfactory.h" #include "../debugdialog.h" #include "../viewgeometry.h" #include "../model/modelpart.h" #include "../model/modelbase.h" #include "paletteitem.h" #include "symbolpaletteitem.h" #include "wire.h" #include "virtualwire.h" #include "tracewire.h" #include "jumperitem.h" #include "resizableboard.h" #include "logoitem.h" #include "schematicframe.h" #include "resistor.h" #include "moduleidnames.h" #include "mysterypart.h" #include "groundplane.h" #include "note.h" #include "ruler.h" #include "dip.h" #include "pinheader.h" #include "screwterminal.h" #include "hole.h" #include "via.h" #include "pad.h" #include "capacitor.h" #include "perfboard.h" #include "breadboard.h" #include "stripboard.h" #include "led.h" #include "schematicsubpart.h" #include "layerkinpaletteitem.h" #include "../utils/folderutils.h" #include "../utils/lockmanager.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include static QString PartFactoryFolderPath; static QHash LockedFiles; static QString SvgFilesDir = "svg"; static QHash SubpartOffsets; const QString PartFactory::OldSchematicPrefix("0.3.schem."); ItemBase * PartFactory::createPart( ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, QMenu * wireMenu, bool doLabel) { modelPart->setModelIndexFromMultiplied(id); // make sure the model index is synched with the id; this is not always the case when parts are first created. ItemBase * itemBase = createPartAux(modelPart, viewID, viewGeometry, id, itemMenu, wireMenu, doLabel); if (itemBase) { itemBase->setViewLayerPlacement(viewLayerPlacement); } return itemBase; } ItemBase * PartFactory::createPartAux( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, QMenu * wireMenu, bool doLabel) { switch (modelPart->itemType()) { case ModelPart::Wire: { bool ratsnest = viewGeometry.getRatsnest(); if (ratsnest) { return new VirtualWire(modelPart, viewID, viewGeometry, id, wireMenu); } if (viewGeometry.getAnyTrace()) { TraceWire * traceWire = new TraceWire(modelPart, viewID, viewGeometry, id, wireMenu); return traceWire; } return new Wire(modelPart, viewID, viewGeometry, id, wireMenu, false); } case ModelPart::Note: return new Note(modelPart, viewID, viewGeometry, id, NULL); case ModelPart::CopperFill: return new GroundPlane(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Jumper: return new JumperItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::ResizableBoard: return new ResizableBoard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Board: return new Board(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Logo: if (modelPart->moduleID().contains("copper", Qt::CaseInsensitive)) { return new CopperLogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } else if (modelPart->moduleID().contains("schematic", Qt::CaseInsensitive)) { return new SchematicLogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } else if (modelPart->moduleID().contains("breadboard", Qt::CaseInsensitive)) { return new BreadboardLogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } // make sure "board" match comes after "breadboard" match else if (modelPart->moduleID().contains("board", Qt::CaseInsensitive)) { return new BoardLogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } return new LogoItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Ruler: return new Ruler(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Symbol: if (modelPart->moduleID().contains(ModuleIDNames::NetLabelModuleIDName)) { return new NetLabel(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } return new SymbolPaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Via: return new Via(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::Hole: return new Hole(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); case ModelPart::SchematicSubpart: return new SchematicSubpart(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); default: { QString moduleID = modelPart->moduleID(); if (moduleID.endsWith(ModuleIDNames::ModuleIDNameSuffix)) { if (moduleID.endsWith(ModuleIDNames::ResistorModuleIDName)) { return new Resistor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::CapacitorModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::CrystalModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::ThermistorModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::ZenerDiodeModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::PotentiometerModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::InductorModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::TwoPowerModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::ColorLEDModuleIDName)) { return new LED(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::ColorFluxLEDModuleIDName)) { return new LED(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::LEDModuleIDName)) { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::PerfboardModuleIDName)) { return new Perfboard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::StripboardModuleIDName)) { return new Stripboard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::Stripboard2ModuleIDName)) { return new Stripboard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::SchematicFrameModuleIDName)) { return new SchematicFrame(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::PadModuleIDName)) { return new Pad(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (moduleID.endsWith(ModuleIDNames::CopperBlockerModuleIDName)) { return new CopperBlocker(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } // must get the subclasses first if (modelPart->itemType() == ModelPart::Breadboard) { return new Breadboard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } } // TODO: use the list in properties.xml if (moduleID == "alps-starter-pot9mm") { return new Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } QString family = modelPart->properties().value("family", ""); if (family.compare("mystery part", Qt::CaseInsensitive) == 0) { return new MysteryPart(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (family.compare("screw terminal", Qt::CaseInsensitive) == 0) { return new ScrewTerminal(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (family.compare("pin header", Qt::CaseInsensitive) == 0) { return new PinHeader(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } if (family.compare("generic IC", Qt::CaseInsensitive) == 0) { return new Dip(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } return new PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel); } } } QString PartFactory::getSvgFilename(ModelPart * modelPart, const QString & baseName, bool generate, bool handleSubparts) { QStringList tempPaths; QString postfix = "/"+ SvgFilesDir +"/%1/"+ baseName; QString userStore = FolderUtils::getUserDataStorePath("parts")+postfix; QString pfPath = PartFactory::folderPath() + postfix; if(!modelPart->path().isEmpty()) { QString path = modelPart->path(); path.replace("/pdb/", "/parts/"); QDir dir(path); // is a path to a filename dir.cdUp(); // lop off the filename dir.cdUp(); // parts root tempPaths << dir.absolutePath() + postfix; tempPaths << FolderUtils::getApplicationSubFolderPath("parts")+postfix; // some svgs may still be in the fritzing parts folder, though the other svgs are in the user folder if (tempPaths.at(0).compare(userStore) != 0) { tempPaths << userStore; } if (tempPaths.at(0).compare(pfPath) != 0) { tempPaths << pfPath; } //DebugDialog::debug("temp path"); //foreach (QString tempPath, tempPaths) { // DebugDialog::debug(tempPath); //} } else { DebugDialog::debug("modelPart with no path--this shouldn't happen"); tempPaths << FolderUtils::getApplicationSubFolderPath("parts")+postfix; tempPaths << userStore; } tempPaths << ":resources/parts/svg/%1/" + baseName; //DebugDialog::debug(QString("got tempPath %1").arg(tempPath)); QString filename; bool exists = false; foreach (QString tempPath, tempPaths) { foreach (QString possibleFolder, ModelPart::possibleFolders()) { filename = tempPath.arg(possibleFolder); if (QFileInfo(filename).exists()) { exists = true; if (possibleFolder == "obsolete") { DebugDialog::debug(QString("module %1:%2 obsolete svg %3").arg(modelPart->title()).arg(modelPart->moduleID()).arg(filename)); } break; } } if (exists) break; } if (!exists && generate) { filename = PartFactory::getSvgFilename(baseName); } if (handleSubparts && modelPart->modelPartShared() && modelPart->modelPartShared()->hasSubparts()) { ModelPartShared * superpart = modelPart->modelPartShared(); QString schematicName = superpart->imageFileName(ViewLayer::SchematicView); QString originalPath = getSvgFilename(modelPart, schematicName, true, false); foreach (ModelPartShared * mps, superpart->subparts()) { QString schematicFileName = mps->imageFileName(ViewLayer::SchematicView); if (schematicFileName.isEmpty()) continue; QString path = partPath() + schematicFileName; QFileInfo info(path); if (info.exists()) { mps->setSubpartOffset(SubpartOffsets.value(path, QPointF(0, 0))); continue; } QFile file(originalPath); QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(&file, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("xml failure %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); continue; } QDomElement root = doc.documentElement(); QDomElement top = showSubpart(root, mps->subpartID()); fixSubpartBounds(top, mps); SubpartOffsets.insert(path, mps->subpartOffset()); TextUtils::writeUtf8(path, doc.toString(4)); } } return filename; } QString PartFactory::getSvgFilename(const QString & fileName) { QString osFileName(fileName); osFileName.remove(OldSchematicPrefix); if (osFileName.startsWith("pcb/dip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &MysteryPart::makePcbDipSvg); } if (osFileName.startsWith("pcb/mystery_part_", Qt::CaseInsensitive)) { if (osFileName.contains("dip")) { return getSvgFilenameAux(fileName, &MysteryPart::makePcbDipSvg); } return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("breadboard/mystery_part_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &MysteryPart::makeBreadboardSvg); } if (osFileName.startsWith("breadboard/screw_terminal_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &ScrewTerminal::makeBreadboardSvg); } if (osFileName.startsWith("schematic/screw_terminal_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &ScrewTerminal::makeSchematicSvg); } if (osFileName.startsWith("pcb/screw_terminal_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &ScrewTerminal::makePcbSvg); } if (osFileName.startsWith("breadboard/generic_sip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &Dip::makeBreadboardSvg); } if (osFileName.startsWith("schematic/mystery_part_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &MysteryPart::makeSchematicSvg); } if (osFileName.startsWith("schematic/generic_sip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &MysteryPart::makeSchematicSvg); } if (osFileName.startsWith("pcb/generic_sip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("schematic/generic_ic_dip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &Dip::makeSchematicSvg); } if (osFileName.startsWith("breadboard/generic_ic_dip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &Dip::makeBreadboardSvg); } if (osFileName.startsWith("pcb/generic_ic_dip_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &MysteryPart::makePcbDipSvg); } if (osFileName.startsWith("pcb/nsjumper_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("pcb/jumper_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("pcb/shrouded_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("pcb/molex_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("pcb/longpad_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } if (osFileName.startsWith("bread/molex_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makeBreadboardSvg); } if (osFileName.startsWith("bread/longpad_", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makeBreadboardSvg); } if (osFileName.contains("pin_header", Qt::CaseInsensitive)) { if (osFileName.contains("schematic", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makeSchematicSvg); } else if (osFileName.contains("bread", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makeBreadboardSvg); } else if (osFileName.contains("pcb", Qt::CaseInsensitive)) { return getSvgFilenameAux(fileName, &PinHeader::makePcbSvg); } } if (osFileName.contains("perfboard", Qt::CaseInsensitive) || osFileName.contains("stripboard", Qt::CaseInsensitive)) { if (osFileName.contains("icon")) return fileName; return getSvgFilenameAux(fileName, &Perfboard::makeBreadboardSvg); } return ""; } bool PartFactory::svgFileExists(const QString & expectedFileName, QString & path) { QString p = FolderUtils::getApplicationSubFolderPath("parts") + "/"+ SvgFilesDir + "/core/"; if (QFileInfo(p + expectedFileName).exists()) { path = expectedFileName; return true; } path = partPath() + expectedFileName; QFileInfo info(path); return info.exists(); } QString PartFactory::getSvgFilenameAux(const QString & expectedFileName, GenSvg genSvg) { QString path; if (svgFileExists(expectedFileName, path)) return path; QString svg = (*genSvg)(expectedFileName); if (TextUtils::writeUtf8(path, svg)) { return path; } return ""; } bool PartFactory::fzpFileExists(const QString & moduleID, QString & path) { QString expectedFileName = moduleID + FritzingPartExtension; path = FolderUtils::getApplicationSubFolderPath("parts") + "/core/" + expectedFileName; if (QFileInfo(path).exists()) { path = expectedFileName; return true; } path = fzpPath() + expectedFileName; QFileInfo info(path); return info.exists(); } QString PartFactory::getFzpFilenameAux(const QString & moduleID, QString (*getFzp)(const QString &)) { QString path; if (fzpFileExists(moduleID, path)) return path; QString fzp = (*getFzp)(moduleID); if (TextUtils::writeUtf8(path, fzp)) { return path; } return ""; } QString PartFactory::getFzpFilename(const QString & moduleID) { QString filename = fzpPath() + moduleID + ".fzp"; QFileInfo info(filename); if (info.exists()) return filename; if (moduleID.endsWith(ModuleIDNames::PerfboardModuleIDName)) { return getFzpFilenameAux(moduleID, &Perfboard::genFZP); } if (moduleID.endsWith(ModuleIDNames::StripboardModuleIDName)) { return getFzpFilenameAux(moduleID, &Stripboard::genFZP); } if (moduleID.endsWith(ModuleIDNames::Stripboard2ModuleIDName)) { return getFzpFilenameAux(moduleID, &Stripboard::genFZP); } if (moduleID.startsWith("generic_ic_dip")) { return getFzpFilenameAux(moduleID, &Dip::genDipFZP); } if (moduleID.startsWith("screw_terminal")) { return getFzpFilenameAux(moduleID, &ScrewTerminal::genFZP); } if (moduleID.startsWith("generic_sip")) { return getFzpFilenameAux(moduleID, &Dip::genSipFZP); } if (moduleID.contains("_pin_header_") && moduleID.startsWith("generic_")) { return getFzpFilenameAux(moduleID, &PinHeader::genFZP); } if (moduleID.startsWith("mystery_part")) { if (moduleID.contains("dip", Qt::CaseInsensitive)) { return getFzpFilenameAux(moduleID, &MysteryPart::genDipFZP); } else { return getFzpFilenameAux(moduleID, &MysteryPart::genSipFZP); } } return ""; } void PartFactory::initFolder() { LockManager::initLockedFiles("partfactory", PartFactoryFolderPath, LockedFiles, LockManager::SlowTime); QFileInfoList backupList; LockManager::checkLockedFiles("partfactory", backupList, LockedFiles, true, LockManager::SlowTime); FolderUtils::makePartFolderHierarchy(PartFactoryFolderPath, "core"); FolderUtils::makePartFolderHierarchy(PartFactoryFolderPath, "contrib"); } void PartFactory::cleanup() { LockManager::releaseLockedFiles(PartFactoryFolderPath, LockedFiles); } ModelPart * PartFactory::fixObsoleteModuleID(QDomDocument & domDocument, QDomElement & instance, QString & moduleIDRef, ModelBase * referenceModel) { // TODO: less hard-coding if (moduleIDRef.startsWith("generic_male")) { ModelPart * modelPart = referenceModel->retrieveModelPart(moduleIDRef); if (modelPart != NULL) { instance.setAttribute("moduleIdRef", moduleIDRef); QDomElement prop = domDocument.createElement("property"); instance.appendChild(prop); prop.setAttribute("name", "form"); prop.setAttribute("value", PinHeader::MaleFormString); return modelPart; } } if (moduleIDRef.startsWith("generic_rounded_female")) { ModelPart * modelPart = referenceModel->retrieveModelPart(moduleIDRef); if (modelPart != NULL) { instance.setAttribute("moduleIdRef", moduleIDRef); QDomElement prop = domDocument.createElement("property"); instance.appendChild(prop); prop.setAttribute("name", "form"); prop.setAttribute("value", PinHeader::FemaleRoundedFormString); return modelPart; } } return NULL; } QString PartFactory::folderPath() { return PartFactoryFolderPath; } QString PartFactory::fzpPath() { return PartFactoryFolderPath + "/core/"; } QString PartFactory::partPath() { return PartFactoryFolderPath + "/svg/core/"; } QString PartFactory::makeSchematicSipOrDipOr(const QStringList & labels, bool hasLayout, bool sip) { if (hasLayout) { return MysteryPart::makeSchematicSvg(labels, false); } if (sip) { return MysteryPart::makeSchematicSvg(labels, true); } return Dip::makeSchematicSvg(labels); } QDomElement PartFactory::showSubpart(QDomElement & root, const QString & subpart) { if (subpart.isEmpty()) return ___emptyElement___; QString id = root.attribute("id"); if (id == subpart) { return root; } QDomElement top; QDomElement child = root.firstChildElement(); while (!child.isNull()) { QDomElement candidate = showSubpart(child, subpart); if (!candidate.isNull()) { top = candidate; } child = child.nextSiblingElement(); } if (root.tagName() != "g" && root.tagName() != "svg") { root.setTagName("g"); } return top; } void PartFactory::fixSubpartBounds(QDomElement & top, ModelPartShared * mps) { if (top.isNull()) return; QString transform = top.attribute("transform", ""); top.removeAttribute("transform"); QDomElement g = top.ownerDocument().createElement("g"); if (!transform.isEmpty()) g.setAttribute("transform", transform); QDomElement child = top.firstChildElement(); while (!child.isNull()) { g.appendChild(child); child = top.firstChildElement(); } top.appendChild(g); QSvgRenderer renderer; QByteArray byteArray = top.ownerDocument().toByteArray(); bool loaded = renderer.load(byteArray); if (!loaded) return; QRectF viewBox; double wignore, hignore; TextUtils::ensureViewBox(top.ownerDocument(), 1, viewBox, false, wignore, hignore, false); double sWidth, sHeight, vbWidth, vbHeight; QDomDocument doc = top.ownerDocument(); TextUtils::getSvgSizes(doc, sWidth, sHeight, vbWidth, vbHeight); QMatrix m = renderer.matrixForElement(mps->subpartID()); QRectF elementBounds = renderer.boundsOnElement(mps->subpartID()); QRectF bounds = m.mapRect(elementBounds); // bounds is in terms of the whole svg // unfortunately, QSvgRenderer doesn't deal with text bounds int w = qCeil(sWidth * GraphicsUtils::SVGDPI); int h = qCeil(sWidth * GraphicsUtils::SVGDPI); QImage image(w,h, QImage::Format_Mono); QDomNodeList nodeList = top.elementsByTagName("text"); QList texts; for (int i = 0; i < nodeList.count(); i++) { texts.append(nodeList.at(i).toElement()); } int ix = 0; foreach (QDomElement text, texts) { text.setTagName("g"); } ix = 0; foreach (QDomElement text, texts) { int minX, minY, maxX, maxY; QMatrix matrix; QRectF viewBox2; SchematicTextLayerKinPaletteItem::renderText(image, text, minX, minY, maxX, maxY, matrix, viewBox2); QRectF r(minX * viewBox.width() / image.width(), minY * viewBox.height() / image.height(), (maxX - minX) * viewBox.width() / image.width(), (maxY - minY) * viewBox.height() / image.height()); bounds |= r; } foreach (QDomElement text, texts) { text.setTagName("text"); } QDomElement root = top.ownerDocument().documentElement(); double newW = sWidth * bounds.width() / vbWidth; double newH = sHeight * bounds.height() / vbHeight; root.setAttribute("width", QString("%1in").arg(newW)); root.setAttribute("height", QString("%1in").arg(newH)); root.setAttribute("viewBox", QString("0 0 %1 %2").arg(bounds.width()).arg(bounds.height())); if (bounds.left() != 0 || bounds.top() != 0) { QDomElement g2 = top.ownerDocument().createElement("g"); g2.appendChild(g); top.appendChild(g2); g2.setAttribute("transform", QString("translate(%1,%2)").arg(-bounds.left()).arg(-bounds.top())); } mps->setSubpartOffset(QPointF(bounds.left() * sWidth / vbWidth, bounds.top() * sHeight / vbHeight)); } fritzing-app-0.9.2b/src/items/partfactory.h000066400000000000000000000053101250202676700207230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6958 $: $Author: irascibl@gmail.com $: $Date: 2013-04-07 22:56:44 +0200 (So, 07. Apr 2013) $ ********************************************************************/ #ifndef PARTFACTORY_H #define PARTFACTORY_H #include #include #include #include "../viewlayer.h" #include "paletteitem.h" class PartFactory { public: static class ItemBase * createPart(class ModelPart *, ViewLayer::ViewLayerPlacement, ViewLayer::ViewID, const class ViewGeometry & viewGeometry, long id, QMenu * itemMenu, QMenu * wireMenu, bool doLabel); static QString getSvgFilename(class ModelPart *, const QString & filename, bool generate, bool handleSubparts); static QString getFzpFilename(const QString & moduleID); static void initFolder(); static void cleanup(); static class ModelPart * fixObsoleteModuleID(QDomDocument & domDocument, QDomElement & instance, QString & moduleIDRef, class ModelBase * referenceModel); static QString folderPath(); static QString fzpPath(); static QString partPath(); static bool svgFileExists(const QString & expectedFileName, QString & path); static bool fzpFileExists(const QString & moduleID, QString & path); static QString makeSchematicSipOrDipOr(const QStringList & labels, bool hasLayout, bool sip); static QString getSvgFilename(const QString & filename); protected: static QString getFzpFilenameAux(const QString & moduleID, GenFzp); static QString getSvgFilenameAux(const QString & expectedFileName, GenSvg); static class ItemBase * createPartAux(class ModelPart *, ViewLayer::ViewID, const class ViewGeometry & viewGeometry, long id, QMenu * itemMenu, QMenu * wireMenu, bool doLabel); static QDomElement showSubpart(QDomElement & root, const QString & subpart); static void fixSubpartBounds(QDomElement &, ModelPartShared *); public: static const QString OldSchematicPrefix; }; #endif fritzing-app-0.9.2b/src/items/partlabel.cpp000066400000000000000000000604621250202676700206770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "partlabel.h" #include "../items/itembase.h" #include "../viewgeometry.h" #include "../debugdialog.h" #include "../sketch/infographicsview.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../installedfonts.h" #include "../fsvgrenderer.h" #include #include #include #include #include #include #include // TODO: // ** selection: coordinate with part selection: it's a layerkin // ** select a part, highlight its label; click a label, highlight its part // ** viewinfo update when selected // ** viewinfo for wires // ** graphics (esp. drag area vs. edit area) // ** html info box needs to update when view switches // ** undo delete text // ** undo change text // ** undo move // ** layers and z order // ** hide and show layer // ** sync hide/show checkbox with visibility state // ** save and load // ** text color needs to be separate in separate views // ** hide silkscreen should hide silkscreen label // ** delete owner: delete label // ** make label single-line (ignore enter key) // ** rotate/flip // ** undo rotate/flip // format: bold, italic, size (small normal large huge), color?, // undo format // heads-up controls // rotate/flip may need to be relative to part? // copy/paste? // z-order manipulation? // hover? // show = autoselect? // undo delete show? // close focus on enter/return? // -- multiple selection? // -- undo select // -- export to svg for export diy (silkscreen layer is not exported) enum PartLabelAction { PartLabelRotate45CW = 1, PartLabelRotate90CW, PartLabelRotate135CW, PartLabelRotate180, PartLabelRotate45CCW, PartLabelRotate90CCW, PartLabelRotate135CCW, PartLabelFlipHorizontal, PartLabelFlipVertical, PartLabelEdit, PartLabelFontSizeTiny, PartLabelFontSizeSmall, PartLabelFontSizeMedium, PartLabelFontSizeLarge, PartLabelDisplayLabelText, PartLabelHide }; ///////////////////////////////////////////// static QMultiHash AllPartLabels; static const QString LabelTextKey = ""; static const double InactiveOpacity = 0.4; /////////////////////////////////////////// PartLabel::PartLabel(ItemBase * owner, QGraphicsItem * parent) : QGraphicsSvgItem(parent) { m_renderer = NULL; m_owner = owner; m_spaceBarWasPressed = false; m_text = m_displayText = ""; m_inactive = m_hidden = m_initialized = false; m_displayKeys.append(LabelTextKey); if (m_owner->hasPartNumberProperty() && m_owner->viewID() != ViewLayer::PCBView) { m_displayKeys.append(ModelPartShared::PartNumberPropertyName); } setFlag(QGraphicsItem::ItemIsSelectable, false); setFlag(QGraphicsItem::ItemIsMovable, false); // don't move this in the standard QGraphicsItem way setVisible(false); m_viewLayerID = ViewLayer::UnknownLayer; setAcceptHoverEvents(true); AllPartLabels.insert(m_owner->id(), this); } PartLabel::~PartLabel() { AllPartLabels.remove(m_owner->id(), this); if (m_owner) { m_owner->clearPartLabel(); } } void PartLabel::showLabel(bool showIt, ViewLayer * viewLayer) { if (showIt == this->isVisible()) return; if (showIt && !m_initialized) { if (m_owner == NULL) return; if (m_owner->scene() == NULL) return; bool flipped = (viewLayer->viewLayerID() == ViewLayer::Silkscreen0Label); if (m_owner->viewID() != ViewLayer::PCBView) { foreach (QString dk, m_owner->modelPart()->displayKeys()) { if (!m_displayKeys.contains(dk)) { m_displayKeys.append(dk); } } } this->setZValue(viewLayer->nextZ()); m_viewLayerID = viewLayer->viewLayerID(); m_owner->scene()->addItem(this); setUpText(); setPlainText(m_owner->instanceTitle()); m_initialized = true; QRectF obr = m_owner->boundingRect(); QRectF tbr = QGraphicsSvgItem::boundingRect(); QPointF initial = (flipped) ? m_owner->pos() + QPointF(-tbr.width(), -tbr.height()) : m_owner->pos() + QPointF(obr.width(), -tbr.height()); this->setPos(initial); m_offset = initial - m_owner->pos(); if (flipped) { transformLabel(QTransform().scale(-1,1)); } } setVisible(showIt); } QPainterPath PartLabel::shape() const { QRectF t = boundingRect(); QPainterPath path; path.addRect(t); return path; } void PartLabel::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (!m_owner->isSelected()) { event->ignore(); return; } InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL && infographics->spaceBarIsPressed()) { m_spaceBarWasPressed = true; event->ignore(); return; } m_spaceBarWasPressed = false; if (!this->isSelected()) { this->setSelected(true); } m_doDrag = true; m_initialPosition = pos(); m_initialOffset = m_offset; } void PartLabel::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (!m_owner->isSelected()) { event->ignore(); return; } if (m_spaceBarWasPressed) { event->ignore(); return; } if (m_doDrag) { QPointF currentParentPos = mapToParent(mapFromScene(event->scenePos())); QPointF buttonDownParentPos = mapToParent(mapFromScene(event->buttonDownScenePos(Qt::LeftButton))); setPos(m_initialPosition + currentParentPos - buttonDownParentPos); m_offset = this->pos() - m_owner->pos(); return; } QGraphicsSvgItem::mouseMoveEvent(event); } void PartLabel::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (!m_owner->isSelected()) { event->ignore(); return; } if (m_spaceBarWasPressed) { event->ignore(); return; } if (m_doDrag) { m_owner->partLabelMoved(m_initialPosition, m_initialOffset, pos(), m_offset); } QGraphicsSvgItem::mouseReleaseEvent(event); } void PartLabel::setPlainText(const QString & text) { m_text = text; displayTexts(); } void PartLabel::displayTextsIf() { if (!m_initialized) return; if (m_hidden) return; if (!isVisible()) return; displayTexts(); } void PartLabel::displayTexts() { QStringList texts; foreach (QString key, m_displayKeys) { QString t; if (key.compare(LabelTextKey) == 0) { t = m_text; } else { t = m_owner->getProperty(key); } if (!t.isEmpty()) texts.append(t); } QString text = texts.join("\n"); if (text.length() == 0) { text = "?"; // make sure there's something visible } m_displayText = text; resetSvg(); } bool PartLabel::initialized() { return m_initialized; } void PartLabel::ownerMoved(QPointF newPos) { this->setPos(m_offset + newPos); } void PartLabel::setHidden(bool hide) { if (!m_initialized) return; m_hidden = hide; setHiddenOrInactive(); } void PartLabel::setInactive(bool inactivate) { if (!m_initialized) return; m_inactive = inactivate; setHiddenOrInactive(); } void PartLabel::setHiddenOrInactive() { bool hide = m_hidden || m_inactive || !m_owner->isSelected(); setAcceptedMouseButtons(hide ? Qt::NoButton : ALLMOUSEBUTTONS); setAcceptHoverEvents(!hide); update(); } ViewLayer::ViewLayerID PartLabel::viewLayerID() { return m_viewLayerID; } bool PartLabel::hidden() { return m_hidden; } bool PartLabel::inactive() { return m_inactive; } void PartLabel::saveInstance(QXmlStreamWriter & streamWriter) { if (!m_initialized) return; streamWriter.writeStartElement("titleGeometry"); streamWriter.writeAttribute("visible", isVisible() ? "true" : "false"); streamWriter.writeAttribute("x", QString::number(pos().x())); streamWriter.writeAttribute("y", QString::number(pos().y())); streamWriter.writeAttribute("z", QString::number(zValue())); streamWriter.writeAttribute("xOffset", QString::number(m_offset.x())); streamWriter.writeAttribute("yOffset", QString::number(m_offset.y())); streamWriter.writeAttribute("textColor", m_color.name()); streamWriter.writeAttribute("fontSize", QString::number(m_font.pointSizeF())); GraphicsUtils::saveTransform(streamWriter, transform()); foreach (QString key, m_displayKeys) { streamWriter.writeStartElement("displayKey"); streamWriter.writeAttribute("key", key); streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } void PartLabel::restoreLabel(QDomElement & labelGeometry, ViewLayer::ViewLayerID viewLayerID) { m_viewLayerID = viewLayerID; m_initialized = true; m_owner->scene()->addItem(this); setVisible(labelGeometry.attribute("visible").compare("true") == 0); QPointF p = pos(); bool ok = false; double x = labelGeometry.attribute("x").toDouble(&ok); if (ok) p.setX(x); double y = labelGeometry.attribute("y").toDouble(&ok); if (ok) p.setY(y); setPos(p); x = labelGeometry.attribute("xOffset").toDouble(&ok); if (ok) m_offset.setX(x); y = labelGeometry.attribute("yOffset").toDouble(&ok); if (ok) m_offset.setY(y); double z = labelGeometry.attribute("z").toDouble(&ok); if (ok) this->setZValue(z); //ignore the textColor attribute so the labels are always set from standard colors //QColor c; //c.setNamedColor(labelGeometry.attribute("textColor")); //setBrush(QBrush(c)); setUpText(); m_initialized = true; double fs = labelGeometry.attribute("fontSize").toDouble(&ok); if (!ok) { InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL) { fs = infographics->getLabelFontSizeMedium(); ok = true; } } if (ok) { m_font.setPointSizeF(fs); } m_displayKeys.clear(); QDomElement displayKey = labelGeometry.firstChildElement("displayKey"); while (!displayKey.isNull()) { m_displayKeys.append(displayKey.attribute("key")); displayKey = displayKey.nextSiblingElement("displayKey"); } if (m_displayKeys.length() == 0) { m_displayKeys.append(LabelTextKey); if (m_owner->hasPartNumberProperty()) m_displayKeys.append(ModelPartShared::PartNumberPropertyName); } displayTexts(); QTransform t; if (GraphicsUtils::loadTransform(labelGeometry.firstChildElement("transform"), t)) { setTransform(t); } } void PartLabel::moveLabel(QPointF newPos, QPointF newOffset) { this->setPos(newPos); m_offset = newOffset; } ItemBase * PartLabel::owner() { return m_owner; } void PartLabel::initMenu() { // todo: make this a static var? QAction *editAct = m_menu.addAction(tr("Edit")); editAct->setData(QVariant(PartLabelEdit)); editAct->setStatusTip(tr("Edit label text")); QAction *hideAct = m_menu.addAction(tr("Hide")); hideAct->setData(QVariant(PartLabelHide)); hideAct->setStatusTip(tr("Hide part label")); m_menu.addSeparator(); QMenu * dvmenu = m_menu.addMenu(tr("Display Values")); QMenu * rlmenu = m_menu.addMenu(tr("Flip/Rotate")); QMenu * fsmenu = m_menu.addMenu(tr("Font Size")); bool include45 = (m_owner != NULL) && (m_owner->viewID() == ViewLayer::PCBView); if (include45) { QAction *rotate45cwAct = rlmenu->addAction(tr("Rotate 45\x00B0 Clockwise")); rotate45cwAct->setData(QVariant(PartLabelRotate45CW)); rotate45cwAct->setStatusTip(tr("Rotate the label by 45 degrees clockwise")); } QAction *rotate90cwAct = rlmenu->addAction(tr("Rotate 90\x00B0 Clockwise")); rotate90cwAct->setData(QVariant(PartLabelRotate90CW)); rotate90cwAct->setStatusTip(tr("Rotate the label by 90 degrees clockwise")); if (include45) { QAction *rotate135cwAct = rlmenu->addAction(tr("Rotate 135\x00B0 Clockwise")); rotate135cwAct->setData(QVariant(PartLabelRotate135CW)); rotate135cwAct->setStatusTip(tr("Rotate the label by 135 degrees clockwise")); } QAction *rotate180Act = rlmenu->addAction(tr("Rotate 180\x00B0")); rotate180Act->setData(QVariant(PartLabelRotate180)); rotate180Act->setStatusTip(tr("Rotate the label by 180 degrees")); if (include45) { QAction *rotate135ccwAct = rlmenu->addAction(tr("Rotate 135\x00B0 Counter Clockwise")); rotate135ccwAct->setData(QVariant(PartLabelRotate135CCW)); rotate135ccwAct->setStatusTip(tr("Rotate the label by 135 degrees counter clockwise")); } QAction *rotate90ccwAct = rlmenu->addAction(tr("Rotate 90\x00B0 Counter Clockwise")); rotate90ccwAct->setData(QVariant(PartLabelRotate90CCW)); rotate90ccwAct->setStatusTip(tr("Rotate current selection 90 degrees counter clockwise")); if (include45) { QAction *rotate45ccwAct = rlmenu->addAction(tr("Rotate 45\x00B0 Counter Clockwise")); rotate45ccwAct->setData(QVariant(PartLabelRotate45CCW)); rotate45ccwAct->setStatusTip(tr("Rotate the label by 45 degrees counter clockwise")); } QAction *flipHorizontalAct = rlmenu->addAction(tr("Flip Horizontal")); flipHorizontalAct->setData(QVariant(PartLabelFlipHorizontal)); flipHorizontalAct->setStatusTip(tr("Flip label horizontally")); QAction *flipVerticalAct = rlmenu->addAction(tr("Flip Vertical")); flipVerticalAct->setData(QVariant(PartLabelFlipVertical)); flipVerticalAct->setStatusTip(tr("Flip label vertically")); m_tinyAct = fsmenu->addAction(tr("Tiny")); m_tinyAct->setData(QVariant(PartLabelFontSizeTiny)); m_tinyAct->setStatusTip(tr("Set font size to tiny")); m_tinyAct->setCheckable(true); m_tinyAct->setChecked(false); m_smallAct = fsmenu->addAction(tr("Small")); m_smallAct->setData(QVariant(PartLabelFontSizeSmall)); m_smallAct->setStatusTip(tr("Set font size to small")); m_smallAct->setCheckable(true); m_smallAct->setChecked(false); m_mediumAct = fsmenu->addAction(tr("Medium")); m_mediumAct->setData(QVariant(PartLabelFontSizeMedium)); m_mediumAct->setStatusTip(tr("Set font size to medium")); m_mediumAct->setCheckable(true); m_mediumAct->setChecked(false); m_largeAct = fsmenu->addAction(tr("Large")); m_largeAct->setData(QVariant(PartLabelFontSizeLarge)); m_largeAct->setStatusTip(tr("Set font size to large")); m_largeAct->setCheckable(true); m_largeAct->setChecked(false); m_labelAct = dvmenu->addAction(tr("Label text")); m_labelAct->setData(QVariant(PartLabelDisplayLabelText)); m_labelAct->setCheckable(true); m_labelAct->setChecked(true); m_labelAct->setStatusTip(tr("Display the text of the label")); dvmenu->addSeparator(); QHash properties = m_owner->modelPart()->properties(); foreach (QString key, properties.keys()) { QString translatedName = ItemBase::translatePropertyName(key); QAction * action = dvmenu->addAction(translatedName); action->setData(QVariant(key)); action->setCheckable(true); action->setChecked(false); action->setStatusTip(tr("Display the value of property %1").arg(translatedName)); m_displayActs.append(action); } } void PartLabel::rotateFlipLabel(double degrees, Qt::Orientations orientation) { if (degrees != 0) { transformLabel(QTransform().rotate(degrees)); } else { int xScale, yScale; if (orientation == Qt::Vertical) { xScale = 1; yScale = -1; } else if(orientation == Qt::Horizontal) { xScale = -1; yScale = 1; } else return; transformLabel(QTransform().scale(xScale,yScale)); } } void PartLabel::transformLabel(QTransform currTransf) { QRectF rect = this->boundingRect(); double x = rect.width() / 2.0; double y = rect.height() / 2.0; QTransform transf = transform() * QTransform().translate(-x, -y) * currTransf * QTransform().translate(x, y); setTransform(transf); } void PartLabel::setUpText() { InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL) { infographics->getLabelFont(m_font, m_color, m_owner); } } QVariant PartLabel::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { switch (change) { case QGraphicsItem::ItemSceneHasChanged: if (this->scene()) { } break; default: break; } return QGraphicsSvgItem::itemChange(change, value); } void PartLabel::ownerSelected(bool selected) { bool hide = !selected; if (m_hidden || m_inactive) { hide = true; } setAcceptedMouseButtons(hide ? Qt::NoButton : ALLMOUSEBUTTONS); setAcceptHoverEvents(!hide); } void PartLabel::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { if (m_hidden || m_inactive || !m_owner->isSelected()) { event->ignore(); return; } if (m_menu.isEmpty()) { initMenu(); } m_labelAct->setChecked(m_displayKeys.contains(LabelTextKey)); foreach (QAction * displayAct, m_displayActs) { QString data = displayAct->data().toString(); displayAct->setChecked(m_displayKeys.contains(data)); } m_tinyAct->setChecked(false); m_smallAct->setChecked(false); m_mediumAct->setChecked(false); m_largeAct->setChecked(false); InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics != NULL) { int fs = m_font.pointSize(); if (fs == infographics->getLabelFontSizeTiny()) { m_tinyAct->setChecked(true); } else if (fs == infographics->getLabelFontSizeSmall()) { m_smallAct->setChecked(true); } else if (fs == infographics->getLabelFontSizeMedium()) { m_mediumAct->setChecked(true); } else if (fs == infographics->getLabelFontSizeLarge()) { m_largeAct->setChecked(true); } } QAction *selectedAction = m_menu.exec(event->screenPos()); if (selectedAction == NULL) return; PartLabelAction action = (PartLabelAction) selectedAction->data().toInt(); switch (action) { case PartLabelRotate45CW: case PartLabelRotate45CCW: case PartLabelRotate90CW: case PartLabelRotate90CCW: case PartLabelRotate135CW: case PartLabelRotate135CCW: case PartLabelRotate180: case PartLabelFlipHorizontal: case PartLabelFlipVertical: rotateFlip(action); break; case PartLabelEdit: partLabelEdit(); break; case PartLabelHide: partLabelHide(); break; case PartLabelFontSizeTiny: case PartLabelFontSizeSmall: case PartLabelFontSizeMedium: case PartLabelFontSizeLarge: setFontSize(action); resetSvg(); break; case PartLabelDisplayLabelText: setLabelDisplay(LabelTextKey); break; default: setLabelDisplay(selectedAction->data().toString()); break; } } void PartLabel::rotateFlip(int action) { double degrees = 0; Qt::Orientations orientation = 0; switch (action) { case PartLabelRotate45CW: degrees = 45; break; case PartLabelRotate90CW: degrees = 90; break; case PartLabelRotate135CW: degrees = 135; break; case PartLabelRotate90CCW: degrees = 270; break; case PartLabelRotate135CCW: degrees = 225; break; case PartLabelRotate180: degrees = 180; break; case PartLabelRotate45CCW: degrees = 315; break; case PartLabelFlipHorizontal: orientation = Qt::Horizontal; break; case PartLabelFlipVertical: orientation = Qt::Vertical; break; default: break; } m_owner->rotateFlipPartLabel(degrees, orientation); } void PartLabel::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { if (!m_owner->isSelected()) { event->ignore(); return; } m_doDrag = false; partLabelEdit(); } void PartLabel::partLabelHide() { m_owner->hidePartLabel(); } void PartLabel::partLabelEdit() { bool ok; QString oldText = m_text; QString text = QInputDialog::getText((QGraphicsView *) this->scene()->parent(), tr("Set label for %1").arg(m_owner->title()), tr("Label text:"), QLineEdit::Normal, oldText, &ok); if (ok && (oldText.compare(text) != 0)) { if (m_owner) { m_owner->partLabelChanged(text); foreach (PartLabel * p, AllPartLabels.values(m_owner->id())) { p->setPlainText(text); } } } } void PartLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_hidden) return; if (m_inactive) { painter->save(); painter->setOpacity(InactiveOpacity); } if (m_owner->isSelected()) { GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, boundingRect(), shape()); } QGraphicsSvgItem::paint(painter, option, widget); if (m_inactive) { painter->restore(); } } void PartLabel::setFontSize(int action) { InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this); if (infographics == NULL) return; double fs = 0; switch (action) { case PartLabelFontSizeTiny: fs = infographics->getLabelFontSizeTiny(); break; case PartLabelFontSizeSmall: fs = infographics->getLabelFontSizeSmall(); break; case PartLabelFontSizeMedium: fs = infographics->getLabelFontSizeMedium(); break; case PartLabelFontSizeLarge: fs = infographics->getLabelFontSizeLarge(); break; default: return; } m_font.setPointSize(fs); } void PartLabel::setFontPointSize(double pointSize) { m_font.setPointSize(pointSize); resetSvg(); } void PartLabel::setLabelDisplay(const QString & key) { if (m_displayKeys.contains(key)) { m_displayKeys.removeOne(key); } else { m_displayKeys.append(key); } displayTexts(); } QString mapToSVGWeight(int w) { int percent = 50; switch (w) { case QFont::Light: percent = 25; break; case QFont::Normal: return "normal"; // 50 case QFont::DemiBold: percent = 63; break; case QFont::Bold: return "bold"; // 75 case QFont::Black: percent = 87; break; default: return "normal"; } return QString::number((qRound(8 * percent / 100.0) * 100) + 100); // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit } QString mapToSVGStyle(QFont::Style style) { switch (style) { case QFont::StyleNormal: return "normal"; case QFont::StyleOblique: return "oblique"; case QFont::StyleItalic: return "italic"; default: return "normal"; } } QString PartLabel::makeSvg(bool blackOnly, double dpi, double printerScale, bool includeTransform) { double w, h; QString svg = makeSvgAux(blackOnly, dpi, printerScale, w, h); if (includeTransform) { QTransform t = transform(); if (!t.isIdentity()) { svg = TextUtils::svgTransform(svg, t, false, QString()); } } return svg; } QString PartLabel::makeSvgAux(bool blackOnly, double dpi, double printerScale, double & w, double & h) { if (m_displayText.isEmpty()) return ""; double pixels = m_font.pointSizeF() * printerScale / 72; double y = pixels * 0.75; //DebugDialog::debug(QString("initial y:%1").arg(y)); QString svg = QString("") .arg(m_font.pointSizeF() * dpi / 72) .arg(mapToSVGStyle(m_font.style())) .arg(mapToSVGWeight(m_font.weight())) .arg(blackOnly ? "#000000" : m_color.name()) .arg(InstalledFonts::InstalledFontsNameMapper.value(m_font.family())) .arg(ViewLayer::viewLayerXmlNameFromID(m_viewLayerID) ); w = 0; QStringList texts = m_displayText.split("\n"); foreach (QString t, texts) { QString t1 = TextUtils::convertExtendedChars(TextUtils::escapeAnd(t)); svg += QString("%2") .arg(y * dpi / printerScale) .arg(t1); y += pixels; w = qMax(w, t.length() * pixels * 0.75); //DebugDialog::debug(QString("\t%1, %2").arg(w).arg(y)); } svg += ""; h = y - (pixels / 2); //QFontInfo fontInfo(m_font); //DebugDialog::debug(QString("%1 match:%2 ps:%3 sty:%4 w:%5") // .arg(fontInfo.family()) // .arg(fontInfo.exactMatch()) // .arg(fontInfo.pointSizeF()) // .arg(fontInfo.style()) // .arg(fontInfo.weight()) // ); return svg; //DebugDialog::debug(QString("final:%1 %2 %3").arg(w).arg(h).arg(m_font.toString())); } void PartLabel::resetSvg() { double w, h; QString innerSvg = makeSvgAux(false, GraphicsUtils::StandardFritzingDPI, GraphicsUtils::SVGDPI, w, h); if (innerSvg.isEmpty()) return; QString svg = TextUtils::makeSVGHeader(GraphicsUtils::SVGDPI, GraphicsUtils::StandardFritzingDPI, w, h) + innerSvg + "\n"; if (m_renderer == NULL) { m_renderer = new QSvgRenderer(this); } // using renderer()->load() doesn't seem to work, so keep a separate shared renderer as a workaround bool loaded = m_renderer->load(svg.toUtf8()); if (loaded) { setSharedRenderer(m_renderer); } } fritzing-app-0.9.2b/src/items/partlabel.h000066400000000000000000000072631250202676700203440ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef PARTLABEL_H #define PARTLABEL_H #include #include #include #include #include #include #include #include #include #include #include #include "../viewlayer.h" class PartLabel : public QGraphicsSvgItem { Q_OBJECT public: PartLabel(class ItemBase * owner, QGraphicsItem * parent = 0 ); // itembase is not the parent ~PartLabel(); void setPlainText(const QString & text); void showLabel(bool showIt, ViewLayer *); QPainterPath shape() const; bool initialized(); void ownerMoved(QPointF newPos); void setHidden(bool hide); bool hidden(); void setInactive(bool inactivate); bool inactive(); ViewLayer::ViewLayerID viewLayerID(); void saveInstance(QXmlStreamWriter & streamWriter); void restoreLabel(QDomElement & labelGeometry, ViewLayer::ViewLayerID); void moveLabel(QPointF newPos, QPointF newOffset); class ItemBase * owner(); void rotateFlipLabel(double degrees, Qt::Orientations orientation); QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value); void ownerSelected(bool selected); void displayTexts(); void displayTextsIf(); QString makeSvg(bool blackOnly, double dpi, double printerScale, bool includeTransform); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setFontPointSize(double pointSize); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void transformLabel(QTransform currTransf); void setUpText(); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); void initMenu(); void partLabelEdit(); void setFontSize(int action); void rotateFlip(int action); void setLabelDisplay(const QString & key); void setHiddenOrInactive(); void partLabelHide(); void resetSvg(); QString makeSvgAux(bool blackOnly, double dpi, double printerScale, double & w, double & h); protected: QPointer m_owner; bool m_initialized; bool m_spaceBarWasPressed; bool m_doDrag; QPointF m_initialPosition; QPointF m_initialOffset; QPointF m_offset; ViewLayer::ViewLayerID m_viewLayerID; bool m_hidden; bool m_inactive; QMenu m_menu; QString m_text; QString m_displayText; QStringList m_displayKeys; QAction * m_tinyAct; QAction * m_smallAct; QAction * m_mediumAct; QAction * m_largeAct; QAction * m_labelAct; QList m_displayActs; QColor m_color; QFont m_font; QSvgRenderer * m_renderer; }; #endif fritzing-app-0.9.2b/src/items/perfboard.cpp000066400000000000000000000252521250202676700206730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "perfboard.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/boundedregexpvalidator.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../commands.h" #include "../debugdialog.h" #include "moduleidnames.h" #include "partlabel.h" #include #include #include #include #include #include static const int ConnectorIDJump = 1000; static const int MaxXDimension = 199; static const int MinXDimension = 5; static const int MaxYDimension = 199; static const int MinYDimension = 5; static const int WarningSize = 2000; static const QString OneHole("M%1,%2a%3,%3 0 1 %5 %4,0 %3,%3 0 1 %5 -%4,0z\n"); bool Perfboard::m_gotWarning = false; ///////////////////////////////////////////////////////////////////// Perfboard::Perfboard( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_size = modelPart->localProp("size").toString(); if (m_size.isEmpty()) { m_size = modelPart->properties().value("size", "20.20"); modelPart->setLocalProp("size", m_size); } } Perfboard::~Perfboard() { } void Perfboard::setProp(const QString & prop, const QString & value) { if (prop.compare("size") != 0) { Capacitor::setProp(prop, value); return; } switch (this->m_viewID) { case ViewLayer::BreadboardView: if (value.compare(m_size) != 0) { QString temp = value; QString svg = makeBreadboardSvg(temp); reloadRenderer(svg, false); //DebugDialog::debug(svg); } break; default: break; } m_size = value; modelPart()->setLocalProp("size", value); if (m_partLabel) m_partLabel->displayTextsIf(); } QString Perfboard::makeBreadboardSvg(const QString & size) { QString BreadboardLayerTemplate = ""; QString ConnectorTemplate = ""; if (BreadboardLayerTemplate.isEmpty()) { QFile file(":/resources/templates/perfboard_boardLayerTemplate.txt"); file.open(QFile::ReadOnly); BreadboardLayerTemplate = file.readAll(); file.close(); } if (ConnectorTemplate.isEmpty()) { QFile file(":/resources/templates/perfboard_connectorTemplate.txt"); file.open(QFile::ReadOnly); ConnectorTemplate = file.readAll(); file.close(); } int x, y; getXY(x, y, size); QString middle; QString holes; double radius = 17.5; int sweepflag = 0; int top = 100; for (int iy = 0; iy < y; iy++) { int left = 100; for (int jx = 0; jx < x; jx++) { middle += ConnectorTemplate.arg(left).arg(top).arg(jx).arg(iy).arg(QString::number((iy * ConnectorIDJump) + jx)); holes += OneHole .arg(left - radius) .arg(top) .arg(radius) .arg(2 * radius) .arg(sweepflag); left += 100; } top += 100; } QString svg = BreadboardLayerTemplate .arg((x / 10.0) + 0.1) .arg((y / 10.0) + 0.1) .arg((x * 100) + 100) .arg((y * 100) + 100) .arg(holes) .arg(x * 100 - 8 + 100) .arg(y * 100 - 8 + 100) .arg(middle); return svg; } QString Perfboard::genFZP(const QString & moduleid) { QString ConnectorFzpTemplate = ""; QString FzpTemplate = ""; if (ConnectorFzpTemplate.isEmpty()) { QFile file(":/resources/templates/perfboard_connectorFzpTemplate.txt"); file.open(QFile::ReadOnly); ConnectorFzpTemplate = file.readAll(); file.close(); } if (FzpTemplate.isEmpty()) { QFile file(":/resources/templates/perfboard_fzpTemplate.txt"); file.open(QFile::ReadOnly); FzpTemplate = file.readAll(); file.close(); } int x, y; getXY(x, y, moduleid); QString middle; for (int iy = 0; iy < y; iy++) { for (int jx = 0; jx < x; jx++) { middle += ConnectorFzpTemplate.arg(jx).arg(iy).arg(QString::number((iy * ConnectorIDJump) + jx)); } } return FzpTemplate.arg(x).arg(y).arg(middle); } bool Perfboard::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("size", Qt::CaseInsensitive) == 0) { returnProp = tr("size"); returnValue = m_size; m_propsMap.insert("size", m_size); int x, y; getXY(x, y, m_size); QFrame * frame = new QFrame(); QVBoxLayout * vboxLayout = new QVBoxLayout(); vboxLayout->setAlignment(Qt::AlignLeft); vboxLayout->setSpacing(1); vboxLayout->setContentsMargins(0, 3, 0, 0); vboxLayout->setMargin(0); QFrame * subframe1 = new QFrame(); QHBoxLayout * hboxLayout1 = new QHBoxLayout(); hboxLayout1->setAlignment(Qt::AlignLeft); hboxLayout1->setContentsMargins(0, 0, 0, 0); hboxLayout1->setSpacing(2); QLabel * l1 = new QLabel(getColumnLabel()); l1->setMargin(0); l1->setObjectName("infoViewLabel"); m_xEdit = new QLineEdit(); m_xEdit->setEnabled(swappingEnabled); QIntValidator * validator = new QIntValidator(m_xEdit); validator->setRange(MinXDimension, MaxXDimension); m_xEdit->setObjectName("infoViewLineEdit"); m_xEdit->setValidator(validator); m_xEdit->setMaxLength(5); m_xEdit->setText(QString::number(x)); QFrame * subframe2 = new QFrame(); QHBoxLayout * hboxLayout2 = new QHBoxLayout(); hboxLayout2->setAlignment(Qt::AlignLeft); hboxLayout2->setContentsMargins(0, 0, 0, 0); hboxLayout2->setSpacing(2); QLabel * l2 = new QLabel(getRowLabel()); l2->setMargin(0); l2->setObjectName("infoViewLabel"); m_yEdit = new QLineEdit(); m_yEdit->setEnabled(swappingEnabled); validator = new QIntValidator(m_yEdit); validator->setRange(MinYDimension, MaxYDimension); m_yEdit->setObjectName("infoViewLineEdit"); m_yEdit->setValidator(validator); m_yEdit->setMaxLength(5); m_yEdit->setText(QString::number(y)); hboxLayout1->addWidget(l1); hboxLayout1->addWidget(m_xEdit); hboxLayout2->addWidget(l2); hboxLayout2->addWidget(m_yEdit); subframe1->setLayout(hboxLayout1); subframe2->setLayout(hboxLayout2); if (returnWidget != NULL) vboxLayout->addWidget(qobject_cast(returnWidget)); vboxLayout->addWidget(subframe1); vboxLayout->addWidget(subframe2); m_setButton = new QPushButton (tr("set board size")); m_setButton->setObjectName("infoViewButton"); connect(m_setButton, SIGNAL(pressed()), this, SLOT(changeBoardSize())); m_setButton->setEnabled(false); vboxLayout->addWidget(m_setButton); connect(m_xEdit, SIGNAL(editingFinished()), this, SLOT(enableSetButton())); connect(m_yEdit, SIGNAL(editingFinished()), this, SLOT(enableSetButton())); frame->setLayout(vboxLayout); returnWidget = frame; return true; } return Capacitor::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void Perfboard::addedToScene(bool temporary) { if (this->scene()) { QString temp = m_size; m_size = ""; setProp("size", temp); } return Capacitor::addedToScene(temporary); } bool Perfboard::canEditPart() { return false; } void Perfboard::changeBoardSize() { if (!m_gotWarning) { int x = m_xEdit->text().toInt(); int y = m_yEdit->text().toInt(); if (x * y >= WarningSize) { m_gotWarning = true; QMessageBox messageBox(NULL); messageBox.setWindowTitle(tr("Performance Warning")); messageBox.setText(tr("Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ?\n" "\nNote: this warning will not be repeated during this session." )); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Cancel); messageBox.setIcon(QMessageBox::Warning); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Ok, tr("Set new size")); messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec(); if (answer != QMessageBox::Ok) { getXY(x, y, m_size); m_xEdit->setText(QString::number(x)); m_yEdit->setText(QString::number(y)); return; } } } QString newSize = QString("%1.%2").arg(m_xEdit->text()).arg(m_yEdit->text()); m_propsMap.insert("size", newSize); foreach (QString key, m_propsMap.keys()) { DebugDialog::debug("prop " + key + " " + m_propsMap.value(key)); } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->swap(family(), "size", m_propsMap, this); } } ItemBase::PluralType Perfboard::isPlural() { return Plural; } void Perfboard::enableSetButton() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; int x, y; getXY(x, y, m_size); int vx = m_xEdit->text().toInt(); int vy = m_yEdit->text().toInt(); m_setButton->setEnabled(vx != x || vy != y); } QString Perfboard::genModuleID(QMap & currPropsMap) { QString size = currPropsMap.value("size"); return size + ModuleIDNames::PerfboardModuleIDName; } bool Perfboard::getXY(int & x, int & y, const QString & s) { QRegExp re("(\\d+)\\.(\\d+)"); int ix = re.indexIn(s); if (ix < 0) return false; bool ok; x = re.cap(1).toInt(&ok); if (!ok) return false; y = re.cap(2).toInt(&ok); return ok; } bool Perfboard::rotation45Allowed() { return false; } void Perfboard::hoverUpdate() { } void Perfboard::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget); } bool Perfboard::stickyEnabled() { return false; } bool Perfboard::canFindConnectorsUnder() { return false; } QString Perfboard::getRowLabel() { return tr("rows"); } QString Perfboard::getColumnLabel() { return tr("columns"); } fritzing-app-0.9.2b/src/items/perfboard.h000066400000000000000000000051751250202676700203420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef PERFBOARD_H #define PERFBOARD_H #include #include #include #include #include #include #include "capacitor.h" class Perfboard : public Capacitor { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Perfboard(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Perfboard(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool canEditPart(); PluralType isPlural(); void addedToScene(bool temporary); void setProp(const QString & prop, const QString & value); void hoverUpdate(); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool stickyEnabled(); bool canFindConnectorsUnder(); bool rotation45Allowed(); protected: virtual QString getRowLabel(); virtual QString getColumnLabel(); public: static QString genFZP(const QString & moduleID); static QString makeBreadboardSvg(const QString & size); static QString genModuleID(QMap & currPropsMap); protected slots: void changeBoardSize(); void enableSetButton(); protected: static bool getXY(int & x, int & y, const QString & s); protected: static bool m_gotWarning; protected: QString m_size; QPointer m_xEdit; QPointer m_yEdit; QPointer m_setButton; }; #endif fritzing-app-0.9.2b/src/items/pinheader.cpp000066400000000000000000001204571250202676700206710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "pinheader.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include "../commands.h" #include "../utils/textutils.h" #include "partlabel.h" #include "partfactory.h" #include "../sketch/infographicsview.h" #include "../connectors/connectoritem.h" #include "../connectors/connector.h" #include "../utils/familypropertycombobox.h" #include #include #include #include #include ////////////////////////////////////////////////// QString doubleCopyPinFunction(int pin, const QString & argString, void *) { return argString.arg(pin * 2).arg(pin * 2 + 1).arg(pin * 2 + 1).arg(pin * 2 + 2); } QString stdIncCopyPinFunction(int pin, const QString & argString, void *) { return argString.arg(pin).arg(pin + 1); } ////////////////////////////////////////////////// static QStringList Forms; QString PinHeader::FemaleFormString; QString PinHeader::FemaleRoundedFormString; QString PinHeader::MaleFormString; QString PinHeader::ShroudedFormString; QString PinHeader::LongPadFormString; QString PinHeader::MolexFormString; static int MinPins = 1; static int MinShroudedPins = 6; static int MaxPins = 64; static QMap Spacings; static QString ShroudedSpacing; static HoleClassThing TheHoleThing; PinHeader::PinHeader( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { setUpHoleSizes("pinheader", TheHoleThing); m_form = modelPart->localProp("form").toString(); if (m_form.isEmpty()) { m_form = modelPart->properties().value("form", FemaleFormString); modelPart->setLocalProp("form", m_form); } } PinHeader::~PinHeader() { } void PinHeader::initNames() { if (FemaleFormString.isEmpty()) { FemaleFormString = FemaleSymbolString + " (female)"; FemaleRoundedFormString = FemaleSymbolString + " (female rounded)"; MaleFormString = MaleSymbolString + " (male)"; ShroudedFormString = MaleSymbolString + " (shrouded male)"; LongPadFormString = "long pad"; MolexFormString = "molex"; } } QStringList PinHeader::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("form", Qt::CaseInsensitive) == 0) { QStringList values; foreach (QString f, forms()) { values.append(f); } value = m_form; return values; } if (prop.compare("rows", Qt::CaseInsensitive) == 0) { QStringList values; values.append("single"); values.append("double"); value = (moduleID().contains("double") || moduleID().contains("shrouded")) ? "double" : "single"; return values; } if (prop.compare("position", Qt::CaseInsensitive) == 0) { QStringList values; values.append("center"); values.append("alternating"); value = (moduleID().contains("alternating")) ? "alternating" : "center"; return values; } if (prop.compare("package", Qt::CaseInsensitive) == 0) { QStringList values; values.append("through-hole"); values.append("SMD"); value = moduleID().contains("smd") ? "SMD" : "through-hole"; return values; } if (prop.compare("pins", Qt::CaseInsensitive) == 0) { QStringList values; value = modelPart()->properties().value("pins"); int step = 1; int minP = MinPins; if (m_form.contains("shrouded")) { minP = MinShroudedPins; step = 2; } if (m_form.contains("double")) { step = 2; minP = 2; } for (int i = minP; i <= MaxPins; i += step) { values << QString::number(i); } return values; } if (prop.compare("pin spacing", Qt::CaseInsensitive) == 0) { initSpacings(); QStringList values; value = modelPart()->properties().value("pin spacing"); if (m_form.contains("shrouded")) { values.append(value); } else { foreach (QString key, Spacings.keys()) { values.append(Spacings.value(key)); } } return values; } return PaletteItem::collectValues(family, prop, value); } QString PinHeader::getProperty(const QString & key) { if (key.compare("form", Qt::CaseInsensitive) == 0) { return m_form; } return PaletteItem::getProperty(key); } void PinHeader::addedToScene(bool temporary) { if (this->scene()) { //setForm(m_form, true); } return PaletteItem::addedToScene(temporary); } const QString & PinHeader::form() { return m_form; } const QStringList & PinHeader::forms() { if (Forms.count() == 0) { Forms << FemaleFormString << FemaleRoundedFormString << MaleFormString << ShroudedFormString << LongPadFormString << MolexFormString; } return Forms; } ItemBase::PluralType PinHeader::isPlural() { return Plural; } QString PinHeader::genFZP(const QString & moduleID) { initSpacings(); QString useModuleID = moduleID; int hsix = useModuleID.lastIndexOf(HoleSizePrefix); if (hsix >= 0) useModuleID.truncate(hsix); QStringList pieces = useModuleID.split("_"); QString spacing = pieces.at(pieces.count() - 1); QString result = PaletteItem::genFZP(useModuleID, "generic_female_pin_header_fzpTemplate", MinPins, MaxPins, 1, useModuleID.contains("smd")); result.replace(".percent.", "%"); QString form = MaleFormString; QString formBread = "male"; QString formText = formBread; QString formSchematic = formBread; QString formModule = formBread; QString formPackage = useModuleID.contains("smd", Qt::CaseInsensitive) ? "smd" : "tht"; QString formPosition = useModuleID.contains("alternating", Qt::CaseInsensitive) ? "alternating" : ""; bool isDouble = useModuleID.contains("shrouded") || useModuleID.contains("double"); QString formRow = isDouble ? "double" : "single"; if (useModuleID.contains("rounded")) { form = FemaleRoundedFormString; if (useModuleID.contains("smd")) { formText = formRow + " row SMD rounded female"; formModule = formText.toLower(); formModule.replace(' ', '_'); formBread = "rounded_female"; } else { if (isDouble) { formBread = formModule = "double_row_rounded_female"; formText = "double row rounded female"; } else { formBread = formModule = "rounded_female"; formText = "rounded female"; if (!formPosition.isEmpty()) { formText += " alternating"; formModule += "_alternating"; } } } formSchematic = "female"; } else if (useModuleID.contains("longpad")) { form = LongPadFormString; formBread = formModule = "longpad"; formText = "longpad"; if (!formPosition.isEmpty()) { formText += " alternating"; formModule += "_alternating"; } } else if (useModuleID.contains("molex")) { form = MolexFormString; formBread = formModule = "molex"; formText = "molex"; } else if (useModuleID.contains("female")) { form = FemaleFormString; if (useModuleID.contains("smd")) { formText = formRow + " row SMD female"; formModule = formText.toLower(); formModule.replace(' ', '_'); formBread = "female"; } else { if (isDouble) { formBread = formModule = "double_row_female"; formText = "double row female"; } else { formBread = formModule = formText = "female"; if (!formPosition.isEmpty()) { formText += " alternating"; formModule += "_alternating"; } } } formSchematic = "female"; } else if (useModuleID.contains("shrouded")) { form = ShroudedFormString; formText = formBread = formModule = "shrouded"; } else if (useModuleID.contains("smd")) { formText = formRow + " row SMD male"; formModule = formText.toLower(); formModule.replace(' ', '_'); } else if (isDouble) { formBread = formModule = "double_row_male"; formText = "double row male"; } else if (!formPosition.isEmpty()) { formText += " alternating"; formModule += "_alternating"; } result = result .arg(Spacings.value(spacing, "")) .arg(spacing) .arg(form) .arg(formBread) .arg(formText) .arg(formSchematic) .arg(formModule) .arg(formRow) .arg(formPackage) .arg(formPosition); ; if (useModuleID.contains("smd")) { result.replace("nsjumper", QString("smd_%1_row_pin_header").arg(formRow)); result.replace("jumper", QString("smd_%1_row_pin_header").arg(formRow)); } else if (useModuleID.contains("shrouded")) { result.replace("nsjumper", "shrouded"); result.replace("jumper", "shrouded"); } else if (useModuleID.contains("longpad")) { result.replace("nsjumper", formModule); result.replace("jumper", formModule); } else if (useModuleID.contains("molex")) { result.replace("nsjumper", "molex"); result.replace("jumper", "molex"); } else if (isDouble) { result.replace("jumper", "jumper_double"); } else if (!formPosition.isEmpty()) { result.replace("nsjumper", "nsjumper_alternating"); result.replace("jumper", "jumper_alternating"); } if (hsix >= 0) { return hackFzpHoleSize(result, moduleID, hsix); } return result; } QString PinHeader::genModuleID(QMap & currPropsMap) { initSpacings(); QString pins = currPropsMap.value("pins"); int p = pins.toInt(); QString spacing = currPropsMap.value("pin spacing"); if (spacing.isEmpty()) spacing = ShroudedSpacing; QString form = currPropsMap.value("form").toLower(); QString package = currPropsMap.value("package").toLower(); QString row = currPropsMap.value("row").toLower(); QString position = currPropsMap.value("position").toLower(); QString formWord = "male"; bool isDouble = false; if (form.contains("shrouded")) { if (p < MinShroudedPins) { pins = QString::number(p = MinShroudedPins); } isDouble = true; spacing = ShroudedSpacing; formWord = "shrouded"; } else if (form.contains("long pad")) { formWord = "longpad"; if (position.contains("alternating")) { formWord += "_alternating"; } } else if (form.contains("molex")) { formWord = "molex"; } else if (form.contains("female")) { QString ff = form.contains("rounded") ? "rounded_female" : "female"; if (package.contains("smd")) { if (row.contains("single", Qt::CaseInsensitive)) { formWord = "single_row_smd_" + ff; } else { isDouble = true; formWord = "double_row_smd_" + ff; } } else { if (row.contains("single", Qt::CaseInsensitive)) { formWord = ff; if (position.contains("alternating")) { formWord += "_alternating"; } } else { isDouble = true; formWord = "double_row_" + ff; } } } else if (package.contains("smd")) { if (row.contains("single")) { formWord = "single_row_smd_male"; } else { isDouble = true; formWord = "double_row_smd_male"; } } else if (row.contains("double", Qt::CaseInsensitive)) { formWord = "double_row_male"; isDouble = true; } else if (position.contains("alternating")) { formWord += "_alternating"; } if (isDouble && (p % 2 == 1)) { pins = QString::number(p + 1); } foreach (QString key, Spacings.keys()) { if (Spacings.value(key).compare(spacing, Qt::CaseInsensitive) == 0) { return QString("generic_%1_pin_header_%2_%3").arg(formWord).arg(pins).arg(key); } } return ""; } QString PinHeader::makePcbSvg(const QString & originalExpectedFileName) { QString expectedFileName = originalExpectedFileName; int hsix = expectedFileName.indexOf(HoleSizePrefix); if (hsix >= 0) { expectedFileName.truncate(hsix); } initSpacings(); if (expectedFileName.contains("smd")) { return makePcbSMDSvg(expectedFileName); } QString spacingString; int pins = TextUtils::getPinsAndSpacing(expectedFileName, spacingString); if (pins == 0) return ""; // only one spacing for mystery parts. if (expectedFileName.contains("mystery")) spacingString = "100mil"; QString svg; if (expectedFileName.contains("shrouded")) { svg = makePcbShroudedSvg(pins); } else if (expectedFileName.contains("longpad")) { svg = makePcbLongPadSvg(pins, expectedFileName.contains("alternating")); } else if (expectedFileName.contains("molex")) { svg = makePcbMolexSvg(pins, spacingString); } else { static QString pcbLayerTemplate = ""; static QString pcbLayerTemplate2 = ""; if (pcbLayerTemplate.isEmpty()) { QFile file(":/resources/templates/jumper_pcb_svg_template.txt"); file.open(QFile::ReadOnly); pcbLayerTemplate = file.readAll(); file.close(); QFile file2(":/resources/templates/jumper_pcb_svg_2nd_template.txt"); file2.open(QFile::ReadOnly); pcbLayerTemplate2 = file2.readAll(); file2.close(); } bool isDouble = expectedFileName.contains("double"); QString useTemplate = isDouble ? pcbLayerTemplate2 : pcbLayerTemplate; double outerBorder = 15; double innerBorder = outerBorder / 2; double silkStrokeWidth = 10; double standardRadius = 27.5; double radius = 29; double copperStrokeWidth = 20; double totalWidth = (outerBorder * 2) + (silkStrokeWidth * 2) + (innerBorder * 2) + (standardRadius * 2) + copperStrokeWidth; double center = totalWidth / 2; double spacing = TextUtils::convertToInches(spacingString) * GraphicsUtils::StandardFritzingDPI; QString middle; bool addSquare = false; if (expectedFileName.contains("nsjumper")) { } else if (expectedFileName.contains("jumper")) { addSquare = true; } else { DebugDialog::debug(QString("square: expected filename is confusing %1").arg(expectedFileName)); } double lockOffset = 5; // mils double useLock = 0; if (!isDouble && expectedFileName.contains("alternating")) { useLock = lockOffset; } if (addSquare) { middle += QString( "\n") .arg(radius * 2) .arg(copperStrokeWidth) .arg(center - radius + useLock) .arg(center - radius); } QString circle("\n"); if (isDouble) { for (int i = 0; i < pins / 2; i++) { middle += circle .arg(center) .arg(center + (i * spacing)) .arg(i) .arg(radius) .arg(copperStrokeWidth); } for (int i = 0; i < pins / 2; i++) { middle += circle .arg(center) .arg(center + (i * spacing)) .arg(i) .arg(radius) .arg(copperStrokeWidth); } for (int i = pins / 2; i < pins; i++) { middle += circle .arg(center + 100) .arg(center + ((pins - i - 1) * spacing)) .arg(i) .arg(radius) .arg(copperStrokeWidth); } } else { for (int i = 0; i < pins; i++) { middle += circle .arg(center + (i % 2 == 0 ? useLock : -useLock)) .arg(center + (i * spacing)) .arg(i) .arg(radius) .arg(copperStrokeWidth); } } double totalHeight = totalWidth + (pins * spacing) - spacing; double originalTotalWidth = totalWidth; if (isDouble) { totalHeight = totalWidth + (spacing * pins / 2) - spacing; totalWidth += 100; } svg = useTemplate .arg(totalWidth / GraphicsUtils::StandardFritzingDPI) .arg(totalHeight / GraphicsUtils::StandardFritzingDPI) .arg(totalWidth) .arg(totalHeight) .arg(totalWidth - outerBorder - (silkStrokeWidth / 2)) .arg(totalHeight - outerBorder - (silkStrokeWidth / 2)) .arg(originalTotalWidth - outerBorder - (silkStrokeWidth / 2)) .arg(silkStrokeWidth) .arg(silkStrokeWidth / 2) .arg(middle); } if (hsix >= 0) { return hackSvgHoleSizeAux(svg, originalExpectedFileName); } return svg; } void PinHeader::initSpacings() { if (Spacings.count() == 0) { ShroudedSpacing = "0.1in (2.54mm)"; Spacings.insert("1mm", "0.03937in (1.0mm)"); Spacings.insert("1.25mm", "0.04921in (1.25mm)"); Spacings.insert("50mil", "0.05in (1.27mm)"); Spacings.insert("1.5mm", "0.0591in (1.5mm)"); Spacings.insert("2mm", "0.07874in (2mm)"); Spacings.insert("2.5mm", "0.09843in (2.5mm)"); Spacings.insert("100mil", ShroudedSpacing); Spacings.insert("150mil", "0.15in (3.81mm)"); Spacings.insert("0.156in", "0.156in (3.96mm)"); Spacings.insert("200mil", "0.2in (5.08mm)"); } } QString PinHeader::makeSchematicSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() < 7) return ""; bool useOldSchematic = expectedFileName.contains(PartFactory::OldSchematicPrefix); QString spacingString; int pins = TextUtils::getPinsAndSpacing(expectedFileName, spacingString); QString form = expectedFileName.contains("female") ? "female" :"male"; bool sizeTenth = expectedFileName.contains("10thin") || !useOldSchematic; // some parts before version 0.8.5 used the 0.1 grid bool isDouble = sizeTenth && expectedFileName.contains("double"); double width, unitHeight; double divisor = isDouble ? 2 : 1; if (sizeTenth) { width = isDouble ? 0.5 : 0.2; unitHeight = GraphicsUtils::StandardSchematicSeparation10thinMils / 1000; // inches } else { unitHeight = GraphicsUtils::StandardSchematicSeparationMils / 1000; // inches width = 0.87; } double unitHeightPoints = unitHeight * 72; QString header("\n" "\n" "\n"); QString svg = header.arg(unitHeight * pins / divisor).arg(unitHeightPoints * pins / divisor).arg(width).arg(width * 72); QString templateFile = QString(":/resources/templates/generic_%1_%2%3pin_header_schem_template.txt") .arg(form.contains("female") ? "female" : "male") .arg(sizeTenth ? "10thin_" : "") .arg(isDouble ? "double_" : "") ; if (sizeTenth) { if (isDouble) { svg += TextUtils::incrementTemplate(templateFile, pins / 2, unitHeightPoints, TextUtils::standardMultiplyPinFunction, doubleCopyPinFunction, NULL); } else { svg += TextUtils::incrementTemplate(templateFile, pins, unitHeightPoints, TextUtils::standardMultiplyPinFunction, stdIncCopyPinFunction, NULL); } } else { svg += TextUtils::incrementTemplate(templateFile, pins, unitHeightPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); } svg += "\n"; return svg; } QString PinHeader::makeBreadboardSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); if (pieces.count() < 7) return ""; int pinIndex = pieces.count() - 3; int pins = pieces.at(pinIndex).toInt(); if (expectedFileName.contains("shrouded")) { return makeBreadboardShroudedSvg(pins); } if (expectedFileName.contains("double") && !expectedFileName.contains("smd", Qt::CaseInsensitive)) { //return makeBreadboardDoubleSvg(expectedFileName, pins); } double unitHeight = 0.1; // inches double unitHeightPoints = unitHeight * 10000; QString header("\n" "\n" "\n"); QString fileForm; if (expectedFileName.contains("round")) { fileForm = "rounded_female"; header += "\n"; } else if (expectedFileName.contains("female")) { fileForm = "female"; header += "\n"; } else { fileForm = "male"; } QString svg = header.arg(unitHeight * pins).arg(unitHeightPoints * pins); svg += TextUtils::incrementTemplate(QString(":/resources/templates/generic_%1_pin_header_bread_template.txt").arg(fileForm), pins, unitHeightPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); svg += "\n"; return svg; } QString PinHeader::makeBreadboardDoubleSvg(const QString & expectedFileName, int pins) { QString header("\n" "\n" "\n"); QString fileForm; if (expectedFileName.contains("round")) { fileForm = "rounded_female"; header += "\n"; } else if (expectedFileName.contains("female")) { fileForm = "female"; header += "\n"; } else { fileForm = "male"; } double unitHeight = 0.1; // inches double unitHeightPoints = unitHeight * 10000; int userData[2]; userData[0] = pins; userData[1] = 1; QString svg = header.arg(unitHeight * pins / 2).arg(unitHeightPoints * pins / 2); svg += TextUtils::incrementTemplate(QString(":/resources/templates/generic_%1_pin_header_bread_template.txt").arg(fileForm), pins / 2, unitHeightPoints, TextUtils::standardMultiplyPinFunction, TextUtils::negIncCopyPinFunction, userData); svg += TextUtils::incrementTemplate(QString(":/resources/templates/generic_%1_pin_header_bread_2nd_template.txt").arg(fileForm), pins / 2, unitHeightPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); svg += "\n"; return svg; } QString PinHeader::makeBreadboardShroudedSvg(int pins) { QString header("\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "%2\n" "%3\n" "\n" "\n" "\n" ); QString repeatT("\n" "\n" "\n" "\n" "\n" "\n" ); QString repeatB("\n" "\n" "\n" "\n" "\n" "\n" ); double increment = 100; // 0.1in QString svg = TextUtils::incrementTemplateString(header, 1, increment * (pins - 2) / 2, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg.replace("{", "["); svg.replace("}", "]"); svg = TextUtils::incrementTemplateString(svg, 1, increment * (pins - 2) / 4, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); int userData[2]; userData[0] = pins; userData[1] = 1; QString repeatTs = TextUtils::incrementTemplateString(repeatT, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::negIncCopyPinFunction, userData); QString repeatBs = TextUtils::incrementTemplateString(repeatB, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); return svg.arg(TextUtils::getViewBoxCoord(svg, 2) / 1000.0).arg(repeatTs).arg(repeatBs); } QString PinHeader::makePcbShroudedSvg(int pins) { QString header("\n" "" "\n" "\n" "\n" "%2\n" "%3\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" ); QString repeatL = "\n"; QString repeatR = "\n"; double increment = 1000; // 0.1in QString svg = TextUtils::incrementTemplateString(header, 1, increment * (pins - 2) / 2, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg.replace("{", "["); svg.replace("}", "]"); svg = TextUtils::incrementTemplateString(svg, 1, increment * (pins - 2) / 4, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); int userData[2]; userData[0] = pins; userData[1] = 1; QString repeatLs = TextUtils::incrementTemplateString(repeatR, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::negIncCopyPinFunction, userData); QString repeatRs = TextUtils::incrementTemplateString(repeatL, pins / 2, increment, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); return svg.arg(TextUtils::getViewBoxCoord(svg, 3) / 10000.0).arg(repeatLs).arg(repeatRs); } QString PinHeader::makePcbLongPadSvg(int pins, bool lock) { if (lock) return makePcbLongPadLockSvg(pins); double dpi = 25.4; double originalHeight = 0.108; // inches double increment = 0.1; // inches QString header("\n" "\n" "\n" "\n" "%3\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" ); double cy = 1.3716; double cy2 = 0.8128; QString repeat = "\n" "\n"; QString repeats; for (int i = 0; i < pins; i++) { repeats += repeat.arg(i).arg(cy).arg(cy2); cy += increment * dpi; cy2 += increment * dpi; } double totalHeight = originalHeight + ((pins - 1) * increment); double lineOffset = 0.1016; // already in dpi return header.arg(totalHeight).arg(totalHeight * dpi).arg(repeats).arg(totalHeight * dpi - lineOffset); } QString PinHeader::makePcbLongPadLockSvg(int pins) { double dpi = 25.4; double originalHeight = 0.108; // inches double increment = 0.1; // inches QString header("\n" "\n" "\n" "\n" "%3\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "%4\n" "%5\n" "\n" "\n" ); QString bottom("\n" "\n" "\n" "\n" "\n"); bottom = TextUtils::incrementTemplateString(bottom, 1, increment * dpi * (pins - 1), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); QString between("\n"); QString betweens = TextUtils::incrementTemplateString(between, pins - 1, increment * dpi, TextUtils::standardMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); double ncy = 1.3716; double ncx = 1.524; double ncy2 = 0.8636; double ncx2 = 0; double offset = 0.254; QString repeat("\n" "\n"); QString repeats; for (int i = 0; i < pins; i++) { double useOffset = (i % 2 == 1) ? offset : 0; repeats += repeat.arg(i).arg(ncy).arg(ncx + useOffset).arg(ncx2 + useOffset).arg(ncy2); ncy += increment * dpi; ncy2 += increment * dpi; } double totalHeight = originalHeight + ((pins - 1) * increment); return header.arg(totalHeight).arg(totalHeight * dpi).arg(repeats).arg(bottom).arg(betweens); } QString PinHeader::makePcbMolexSvg(int pins, const QString & spacingString) { double dpi = 25.4; double originalHeight = 0.105; // inches double increment = 0.1; // inches bool ok; double inc = TextUtils::convertToInches(spacingString, &ok, false); if (ok) increment = inc; QString header("\n" "\n" "\n" "\n" "\n" "%3\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" ); double cy = 1.3335; // already in dpi QString repeat = "\n"; QString repeats; for (int i = 0; i < pins; i++) { repeats += repeat.arg(i).arg(cy + (i * increment * dpi)); } double totalHeight = originalHeight + ((pins - 1) * increment); double strokeWidth = .127; // already in dpi double h = 0.0001; return header.arg(totalHeight).arg(totalHeight * dpi).arg(repeats).arg((totalHeight * dpi) - strokeWidth).arg(qMax(h, (totalHeight * dpi) - cy - cy)); } QString PinHeader::makePcbSMDSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(5).toInt(); QString spacingString = pieces.at(6); bool singleRow = expectedFileName.contains("single"); double spacing = TextUtils::convertToInches(spacingString) * GraphicsUtils::StandardFritzingDPI; QString header("\n" "\n" "\n" "\n" "\n" "\n"); double baseWidth = 152.7559; // mils double totalHeight = 283.4646; double totalWidth = baseWidth + ((pins - 1) * spacing); double rectHeight = 102.047256; double y = 141.823; if (!singleRow) { totalHeight = 393.7; totalWidth = baseWidth + ((pins - 2) * spacing / 2); rectHeight = 200; y = 251.9685; } QString svg = header.arg(totalWidth / GraphicsUtils::StandardFritzingDPI) .arg(totalWidth) .arg(totalWidth - 4) .arg(totalHeight / GraphicsUtils::StandardFritzingDPI) .arg(totalHeight) .arg(rectHeight); double x = 51.18110; if (singleRow) { for (int i = 0; i < pins; i++) { double ay = (i % 2 == 0) ? 0 : y; svg += QString("\n").arg(i).arg(x).arg(ay); x += spacing; } } else { double holdX = x; for (int i = 0; i < pins / 2; i++) { svg += QString("\n").arg(pins - 1 - i).arg(x); x += spacing; } x = holdX; for (int i = 0; i < pins / 2; i++) { svg += QString("\n").arg(i).arg(x).arg(y); x += spacing; } } svg += "\n"; return svg; } bool PinHeader::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("hole size", Qt::CaseInsensitive) == 0) { if (moduleID().contains("smd", Qt::CaseInsensitive)) { // or call the ancestor function? return false; } else { return collectHoleSizeInfo(TheHoleThing.holeSizeValue, parent, swappingEnabled, returnProp, returnValue, returnWidget); } } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void PinHeader::swapEntry(const QString & text) { generateSwap(text, genModuleID, genFZP, makeBreadboardSvg, makeSchematicSvg, makePcbSvg); PaletteItem::swapEntry(text); } fritzing-app-0.9.2b/src/items/pinheader.h000066400000000000000000000061011250202676700203230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef PINHEADER_H #define PINHEADER_H #include #include #include #include #include "paletteitem.h" class PinHeader : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call PinHeader(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~PinHeader(); QString getProperty(const QString & key); const QString & form(); PluralType isPlural(); void addedToScene(bool temporary); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); protected: QStringList collectValues(const QString & family, const QString & prop, QString & value); public slots: void swapEntry(const QString & text); public: static QString FemaleFormString; static QString FemaleRoundedFormString; static QString MaleFormString; static QString ShroudedFormString; static QString LongPadFormString; static QString MolexFormString; public: static void initNames(); static QString genFZP(const QString & moduleid); static QString makePcbSvg(const QString & expectedFileName); static QString makePcbShroudedSvg(int pins); static QString makePcbLongPadSvg(int pins, bool lock); static QString makePcbLongPadLockSvg(int pins); static QString makePcbMolexSvg(int pins, const QString & spacingString); static QString makePcbSMDSvg(const QString & expectedFileName); static QString makeSchematicSvg(const QString & expectedFileName); static QString makeBreadboardSvg(const QString & expectedFileName); static QString makeBreadboardShroudedSvg(int pins); static QString makeBreadboardDoubleSvg(const QString & expectedFileName, int pins); protected: static const QStringList & forms(); static void initSpacings(); static QString genModuleID(QMap & currPropsMap); protected: QString m_form; }; #endif fritzing-app-0.9.2b/src/items/propertydef.cpp000066400000000000000000000110401250202676700212600ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6141 $: $Author: cohen@irascible.com $: $Date: 2012-07-04 21:20:05 +0200 (Mi, 04. Jul 2012) $ ********************************************************************/ #include "propertydef.h" #include "../debugdialog.h" #include "../model/modelpart.h" #include "../utils/textutils.h" #include #include #include #include QList PropertyDefMaster::PropertyDefs; void PropertyDefMaster::loadPropertyDefs() { QFile file(":/resources/properties.xml"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("failed loading properties %1 line:%2 col:%3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) return; if (root.tagName() != "properties") return; QDomElement propertyElement = root.firstChildElement("property"); while (!propertyElement.isNull()) { PropertyDef * propertyDef = new PropertyDef; propertyDef->name = propertyElement.attribute("name"); PropertyDefs.append(propertyDef); propertyDef->symbol = propertyElement.attribute("symbol"); propertyDef->minValue = propertyElement.attribute("minValue").toDouble(); propertyDef->maxValue = propertyElement.attribute("maxValue").toDouble(); propertyDef->defaultValue = propertyElement.attribute("defaultValue"); propertyDef->editable = propertyElement.attribute("editable", "").compare("yes") == 0; propertyDef->numeric = propertyElement.attribute("numeric", "").compare("yes") == 0; QDomElement menuItem = propertyElement.firstChildElement("menuItem"); while (!menuItem.isNull()) { QString val = menuItem.attribute("value"); if (propertyDef->numeric) { propertyDef->menuItems.append(val.toDouble()); } else { propertyDef->sMenuItems.append(val); } QString adjunct = menuItem.attribute("adjunct"); if (!adjunct.isEmpty()) { propertyDef->adjuncts.insert(val, adjunct); } menuItem = menuItem.nextSiblingElement("menuItem"); } QDomElement suffixElement = propertyElement.firstChildElement("suffix"); while (!suffixElement.isNull()) { QString suffix = suffixElement.attribute("suffix"); propertyDef->suffixes.append(suffix); suffixElement = suffixElement.nextSiblingElement("suffix"); } propertyElement = propertyElement.nextSiblingElement("property"); } } void PropertyDefMaster::cleanup() { foreach (PropertyDef * propertyDef, PropertyDefs) { delete propertyDef; } PropertyDefs.clear(); } void PropertyDefMaster::initPropertyDefs(ModelPart * modelPart, QHash & propertyDefs) { if (PropertyDefs.count() == 0) { loadPropertyDefs(); } foreach (PropertyDef * propertyDef, PropertyDefs) { foreach (QString suffix, propertyDef->suffixes) { if (!modelPart->moduleID().endsWith(suffix, Qt::CaseInsensitive)) continue; //DebugDialog::debug(QString("%1 %2").arg(suffix).arg(modelPart->moduleID())); QString defaultValue; if (propertyDef->numeric) { if (!propertyDef->defaultValue.isEmpty()) { defaultValue = TextUtils::convertToPowerPrefix(propertyDef->defaultValue.toDouble()) + propertyDef->symbol; } } else { defaultValue = propertyDef->defaultValue; } QString savedValue = modelPart->localProp(propertyDef->name).toString(); if (savedValue.isEmpty()) { savedValue = modelPart->properties().value(propertyDef->name.toLower(), defaultValue); if (!savedValue.isEmpty()) { modelPart->setLocalProp(propertyDef->name, savedValue); } } // caches the current value propertyDefs.insert(propertyDef, savedValue); } } } fritzing-app-0.9.2b/src/items/propertydef.h000066400000000000000000000032241250202676700207320ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PROPERTYDEF_H #define PROPERTYDEF_H #include #include #include struct PropertyDef { QString name; QString symbol; double minValue; double maxValue; QString defaultValue; bool numeric; bool editable; QList menuItems; QStringList sMenuItems; QHash adjuncts; QStringList suffixes; }; class PropertyDefMaster { public: static void initPropertyDefs(class ModelPart *, QHash & propertyDefs); static void cleanup(); protected: static void loadPropertyDefs(); protected: static QList PropertyDefs; }; #endif // PROPERTYDEF_H fritzing-app-0.9.2b/src/items/resistor.cpp000066400000000000000000000350771250202676700206070ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include "resistor.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/focusoutcombobox.h" #include "../utils/boundedregexpvalidator.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../commands.h" #include "../layerattributes.h" #include "moduleidnames.h" #include "partlabel.h" #include "../debugdialog.h" #include #include static QStringList Resistances; static QHash PinSpacings; static QHash ColorBands; static QString OhmSymbol(QChar(0x03A9)); static QString PlusMinusSymbol(QChar(0x0B1)); static QHash Tolerances; // TODO // save into parts bin // other manifestations of "220"? Resistor::Resistor( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Capacitor(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_changingPinSpacing = false; if (Resistances.count() == 0) { Resistances << QString("0") + OhmSymbol << QString("1") + OhmSymbol << QString("1.5") + OhmSymbol << QString("2.2") + OhmSymbol << QString("3.3") + OhmSymbol << QString("4.7") + OhmSymbol << QString("6.8") + OhmSymbol << QString("10") + OhmSymbol << QString("15") + OhmSymbol << QString("22") + OhmSymbol << QString("33") + OhmSymbol << QString("47") + OhmSymbol << QString("68") + OhmSymbol << QString("100") + OhmSymbol << QString("150") + OhmSymbol << QString("220") + OhmSymbol << QString("330") + OhmSymbol << QString("470") + OhmSymbol << QString("680") + OhmSymbol << QString("1k") + OhmSymbol << QString("1.5k") + OhmSymbol << QString("2.2k") + OhmSymbol << QString("3.3k") + OhmSymbol << QString("4.7k") + OhmSymbol << QString("6.8k") + OhmSymbol << QString("10k") + OhmSymbol << QString("15k") + OhmSymbol << QString("22k") + OhmSymbol << QString("33k") + OhmSymbol << QString("47k") + OhmSymbol << QString("68k") + OhmSymbol << QString("100k") + OhmSymbol << QString("150k") + OhmSymbol << QString("220k") + OhmSymbol << QString("330k") + OhmSymbol << QString("470k") + OhmSymbol << QString("680k") + OhmSymbol << QString("1M") + OhmSymbol; } if (PinSpacings.count() == 0) { PinSpacings.insert("100 mil (stand-up right)", "pcb/axial_stand0_2_100mil_pcb.svg"); PinSpacings.insert("100 mil (stand-up left)", "pcb/axial_stand1_2_100mil_pcb.svg"); PinSpacings.insert("200 mil", "pcb/axial_lay_2_200mil_pcb.svg"); PinSpacings.insert("300 mil", "pcb/axial_lay_2_300mil_pcb.svg"); PinSpacings.insert("400 mil", "pcb/axial_lay_2_400mil_pcb.svg"); PinSpacings.insert("500 mil", "pcb/axial_lay_2_500mil_pcb.svg"); PinSpacings.insert("600 mil", "pcb/axial_lay_2_600mil_pcb.svg"); PinSpacings.insert("800 mil", "pcb/axial_lay_2_800mil_pcb.svg"); } if (ColorBands.count() == 0) { ColorBands.insert(0, QColor(0, 0, 0)); ColorBands.insert(1, QColor(138, 61, 6)); ColorBands.insert(2, QColor(196, 8, 8)); ColorBands.insert(3, QColor(255, 77, 0)); ColorBands.insert(4, QColor(255, 213, 0)); ColorBands.insert(5, QColor(0, 163, 61)); ColorBands.insert(6, QColor(0, 96, 182)); ColorBands.insert(7, QColor(130, 16, 210)); ColorBands.insert(8, QColor(140, 140, 140)); ColorBands.insert(9, QColor(255, 255, 255)); ColorBands.insert(-1, QColor(173, 159, 78)); ColorBands.insert(-2, QColor(192, 192, 192)); } if (Tolerances.count() == 0) { // TODO: move this into properties.xml Tolerances.insert(PlusMinusSymbol + "0.05%", QColor(140, 140, 140)); Tolerances.insert(PlusMinusSymbol + "0.1%", QColor(130, 16, 210)); Tolerances.insert(PlusMinusSymbol + "0.25%", QColor(0, 96, 182)); Tolerances.insert(PlusMinusSymbol + "0.5%", QColor(0, 163, 61)); Tolerances.insert(PlusMinusSymbol + "1%", QColor(138, 61, 6)); Tolerances.insert(PlusMinusSymbol + "2%", QColor(196, 8, 8)); Tolerances.insert(PlusMinusSymbol + "5%", QColor(173, 159, 78)); Tolerances.insert(PlusMinusSymbol + "10%", QColor(192, 192, 192)); Tolerances.insert(PlusMinusSymbol + "20%", QColor(0xdb, 0xb4, 0x77)); } m_ohms = modelPart->localProp("resistance").toString(); if (m_ohms.isEmpty()) { m_ohms = modelPart->properties().value("resistance", "220"); modelPart->setLocalProp("resistance", m_ohms); } m_pinSpacing = modelPart->localProp("pin spacing").toString(); if (m_pinSpacing.isEmpty()) { m_pinSpacing = modelPart->properties().value("pin spacing", "400 mil"); modelPart->setLocalProp("pin spacing", m_pinSpacing); } updateResistances(m_ohms); } Resistor::~Resistor() { } void Resistor::setResistance(QString resistance, QString pinSpacing, bool force) { QString tolerance = prop("tolerance"); if (resistance.endsWith(OhmSymbol)) { resistance.chop(1); } modelPart()->setLocalTitle(resistance + " " + OhmSymbol + " " + tr("Resistor")); switch (this->m_viewID) { case ViewLayer::BreadboardView: if (force || resistance.compare(m_ohms) != 0) { QString svg = makeSvg(resistance, m_viewLayerID); //DebugDialog::debug(svg); reloadRenderer(svg, false); } break; case ViewLayer::PCBView: if (force || pinSpacing.compare(m_pinSpacing) != 0) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) break; if (modelPart()->properties().value("package").compare("tht", Qt::CaseInsensitive) == 0) { // pinspacing is irrelevant for SMD resistors QString filename = PinSpacings.value(pinSpacing, ""); if (filename.isEmpty()) break; QString original = modelPart()->imageFileName(m_viewID); modelPart()->setImageFileName(m_viewID, filename); m_changingPinSpacing = true; resetImage(infoGraphicsView); m_changingPinSpacing = false; modelPart()->setImageFileName(m_viewID, original); QList already; updateConnections(false, already); } } break; default: break; } m_ohms = resistance; m_pinSpacing = pinSpacing; modelPart()->setLocalProp("resistance", resistance); modelPart()->setLocalProp("pin spacing", pinSpacing); modelPart()->setLocalProp("tolerance", tolerance); updateResistances(m_ohms); if (m_partLabel) m_partLabel->displayTextsIf(); } QString Resistor::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { switch (viewLayerID) { case ViewLayer::Breadboard: case ViewLayer::Icon: break; default: return Capacitor::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QString svg = makeSvg(m_ohms, viewLayerID); return PaletteItemBase::normalizeSvg(svg, viewLayerID, blackOnly, dpi, factor); } QString Resistor::makeSvg(const QString & resistance, ViewLayer::ViewLayerID viewLayerID) { QString moduleID = this->moduleID(); double ohms = TextUtils::convertFromPowerPrefix(resistance, OhmSymbol); QString sohms = QString::number(ohms, 'e', 3); int firstband = sohms.at(0).toLatin1() - '0'; int secondband = sohms.at(2).toLatin1() - '0'; int thirdband = sohms.at(3).toLatin1() - '0'; int temp = (firstband * 10) + secondband; if (moduleID.contains("5Band")) { temp = (temp * 10) + thirdband; } int multiplier = (temp == 0) ? 0 : log10(ohms / temp); QString tolerance = prop("tolerance"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; QString fn = (viewLayerID == ViewLayer::Breadboard) ? m_breadboardSvgFile : m_iconSvgFile; QFile file(fn); if (!domDocument.setContent(&file, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("makesvg failed %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return ""; } QDomElement root = domDocument.documentElement(); setBands(root, firstband, secondband, thirdband, multiplier, tolerance); return domDocument.toString(); } void Resistor::setBands(QDomElement & element, int firstband, int secondband, int thirdband, int multiplier, const QString & tolerance) { QString id = element.attribute("id"); if (!id.isEmpty()) { if (id.compare("band_1_st") == 0) { element.setAttribute("fill", ColorBands.value(firstband, Qt::black).name()); } else if (id.compare("band_2_nd") == 0) { element.setAttribute("fill", ColorBands.value(secondband, Qt::black).name()); } else if (id.compare("band_3") == 0) { element.setAttribute("fill", ColorBands.value(thirdband, Qt::black).name()); } else if (id.compare("band_rd_multiplier") == 0) { element.setAttribute("fill", ColorBands.value(multiplier, Qt::black).name()); } else if (id.compare("gold_band") == 0) { element.setAttribute("fill", Tolerances.value(tolerance, QColor(173, 159, 78)).name()); } } QDomElement child = element.firstChildElement(); while (!child.isNull()) { setBands(child, firstband, secondband, thirdband, multiplier, tolerance); child = child.nextSiblingElement(); } } bool Resistor::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("resistance", Qt::CaseInsensitive) == 0) { returnProp = tr("resistance"); FocusOutComboBox * focusOutComboBox = new FocusOutComboBox(); focusOutComboBox->setEnabled(swappingEnabled); focusOutComboBox->setEditable(true); QString current = m_ohms + OhmSymbol; focusOutComboBox->addItems(Resistances); focusOutComboBox->setCurrentIndex(focusOutComboBox->findText(current)); BoundedRegExpValidator * validator = new BoundedRegExpValidator(focusOutComboBox); validator->setSymbol(OhmSymbol); validator->setConverter(TextUtils::convertFromPowerPrefix); validator->setBounds(0, 9900000000.0); validator->setRegExp(QRegExp(QString("((\\d{1,3})|(\\d{1,3}\\.)|(\\d{1,3}\\.\\d{1,2}))[\\x%1umkMG]{0,1}[\\x03A9]{0,1}").arg(TextUtils::MicroSymbolCode, 4, 16, QChar('0')))); focusOutComboBox->setValidator(validator); connect(focusOutComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(resistanceEntry(const QString &))); focusOutComboBox->setObjectName("infoViewComboBox"); focusOutComboBox->setToolTip(tr("You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'")); returnValue = current; returnWidget = focusOutComboBox; return true; } return Capacitor::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } QString Resistor::getProperty(const QString & key) { if (key.compare("resistance", Qt::CaseInsensitive) == 0) { return m_ohms + OhmSymbol; } if (key.compare("pin spacing", Qt::CaseInsensitive) == 0) { return m_pinSpacing; } return Capacitor::getProperty(key); } QString Resistor::resistance() { return m_ohms; } QString Resistor::pinSpacing() { return m_pinSpacing; } void Resistor::addedToScene(bool temporary) { if (this->scene()) { setResistance(m_ohms, m_pinSpacing, true); } return Capacitor::addedToScene(temporary); } const QString & Resistor::title() { m_title = QString("%1%2 Resistor").arg(m_ohms).arg(OhmSymbol); return m_title; } void Resistor::updateResistances(QString r) { if (!Resistances.contains(r + OhmSymbol)) { Resistances.append(r + OhmSymbol); } } ConnectorItem* Resistor::newConnectorItem(Connector *connector) { if (m_changingPinSpacing) { return connector->connectorItemByViewLayerID(viewID(), viewLayerID()); } return Capacitor::newConnectorItem(connector); } ConnectorItem* Resistor::newConnectorItem(ItemBase * layerKin, Connector *connector) { if (m_changingPinSpacing) { return connector->connectorItemByViewLayerID(viewID(), layerKin->viewLayerID()); } return Capacitor::newConnectorItem(layerKin, connector); } bool Resistor::hasCustomSVG() { switch (m_viewID) { case ViewLayer::BreadboardView: case ViewLayer::IconView: return true; default: return ItemBase::hasCustomSVG(); } } bool Resistor::canEditPart() { return true; } QStringList Resistor::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("pin spacing", Qt::CaseInsensitive) == 0) { QStringList values; foreach (QString f, PinSpacings.keys()) { values.append(f); } value = m_pinSpacing; return values; } return Capacitor::collectValues(family, prop, value); } void Resistor::resistanceEntry(const QString & text) { //DebugDialog::debug(QString("resistance entry %1").arg(text)); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setResistance(text, ""); } } ItemBase::PluralType Resistor::isPlural() { return Plural; } void Resistor::setProp(const QString & prop, const QString & value) { Capacitor::setProp(prop, value); if (prop.compare("tolerance") == 0) { setResistance(m_ohms, m_pinSpacing, true); } } bool Resistor::setUpImage(ModelPart * modelPart, const LayerHash & viewLayers, LayerAttributes & layerAttributes) { bool result = Capacitor::setUpImage(modelPart, viewLayers, layerAttributes); if (layerAttributes.viewLayerID == ViewLayer::Breadboard) { if (result && m_breadboardSvgFile.isEmpty()) m_breadboardSvgFile = layerAttributes.filename(); } else if (layerAttributes.viewLayerID == ViewLayer::Icon) { if (result && m_iconSvgFile.isEmpty()) m_iconSvgFile = layerAttributes.filename(); } return result; } ViewLayer::ViewID Resistor::useViewIDForPixmap(ViewLayer::ViewID vid, bool swappingEnabled) { if (swappingEnabled && vid == ViewLayer::BreadboardView) { return vid; } return ItemBase::useViewIDForPixmap(vid, swappingEnabled); } fritzing-app-0.9.2b/src/items/resistor.h000066400000000000000000000061201250202676700202370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef RESISTOR_H #define RESISTOR_H #include #include #include #include #include "capacitor.h" class Resistor : public Capacitor { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Resistor(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Resistor(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); QString getProperty(const QString & key); void setResistance(QString resistance, QString pinSpacing, bool force); QString resistance(); QString pinSpacing(); const QString & title(); bool hasCustomSVG(); bool canEditPart(); PluralType isPlural(); void addedToScene(bool temporary); void setProp(const QString & prop, const QString & value); bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); protected: QString makeSvg(const QString & ohms, ViewLayer::ViewLayerID viewLayerID); void updateResistances(QString r); ConnectorItem* newConnectorItem(class Connector *connector); ConnectorItem* newConnectorItem(ItemBase * layerkin, Connector *connector); QStringList collectValues(const QString & family, const QString & prop, QString & value); void setBands(QDomElement & element, int firstband, int secondband, int thirdband, int multiplier, const QString & tolerance); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); public slots: void resistanceEntry(const QString & text); public: static double toOhms(const QString & ohmsString, void * data); protected: QString m_ohms; QString m_pinSpacing; QString m_title; bool m_changingPinSpacing; QString m_iconSvgFile; QString m_breadboardSvgFile; }; #endif fritzing-app-0.9.2b/src/items/resizableboard.cpp000066400000000000000000001357271250202676700217300ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "resizableboard.h" #include "../utils/resizehandle.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../commands.h" #include "moduleidnames.h" #include "../layerattributes.h" #include "../debugdialog.h" #include "../svg/gerbergenerator.h" #include #include #include #include #include #include #include #include #include #include #include QList PaperSizeNames; QList PaperSizeDimensions; static QHash NamesToXmlNames; static QHash XmlNamesToNames; static QHash BoardLayerTemplates; static QHash SilkscreenLayerTemplates; static QHash Silkscreen0LayerTemplates; static const int LineThickness = 8; static const QRegExp HeightExpr("height=\\'\\d*px"); static QString StandardCustomBoardExplanation; QStringList Board::BoardImageNames; QStringList Board::NewBoardImageNames; const double ResizableBoard::CornerHandleSize = 7.0; static const double JND = (double) 0.01; QString Board::OneLayerTranslated; QString Board::TwoLayersTranslated; Board::Board( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_svgOnly = true; m_fileNameComboBox = NULL; if (isBoard(modelPart)) { if (modelPart->localProp("layers").isNull()) { modelPart->setLocalProp("layers", modelPart->properties().value("layers")); } if (itemType() == ModelPart::Board && !modelPart->properties().keys().contains("filename")) { // deal with old style custom boards modelPart->modelPartShared()->setProperty("filename", "", false); } } if (StandardCustomBoardExplanation.isEmpty()) { StandardCustomBoardExplanation = tr("\n\nA custom board svg typically has one or two silkscreen layers and one board layer.\n") + tr("Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/.\n\n"); } if (NamesToXmlNames.count() == 0) { NamesToXmlNames.insert("copper bottom", "copper0"); NamesToXmlNames.insert("copper top", "copper1"); NamesToXmlNames.insert("silkscreen bottom", "silkscreen0"); NamesToXmlNames.insert("silkscreen top", "silkscreen"); foreach (QString key, NamesToXmlNames.keys()) { XmlNamesToNames.insert(NamesToXmlNames.value(key), key); } } } Board::~Board() { } void Board::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); Q_UNUSED(option); painter->save(); painter->setOpacity(0); painter->fillPath(this->hoverShape(), QBrush(HoverColor)); painter->restore(); } QStringList Board::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("layers", Qt::CaseInsensitive) == 0) { QString realValue = modelPart()->localProp("layers").toString(); if (!realValue.isEmpty()) { value = realValue; } QStringList result; if (OneLayerTranslated.isEmpty()) { OneLayerTranslated = tr("one layer (single-sided)"); } if (TwoLayersTranslated.isEmpty()) { TwoLayersTranslated = tr("two layers (double-sided)"); } result.append(OneLayerTranslated); result.append(TwoLayersTranslated); if (value == "1") { value = OneLayerTranslated; } else if (value == "2") { value = TwoLayersTranslated; } return result; } QStringList result = PaletteItem::collectValues(family, prop, value); if (prop.compare("shape", Qt::CaseInsensitive) == 0 && isBoard(this) && !this->moduleID().contains(ModuleIDNames::BoardLogoImageModuleIDName)) { result.removeAll("Custom Shape"); } return result; } bool Board::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("filename", Qt::CaseInsensitive) == 0 && isBoard(this)) { setupLoadImage(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget); return true; } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } bool Board::rotation45Allowed() { return false; } bool Board::stickyEnabled() { return false; } ItemBase::PluralType Board::isPlural() { return Plural; } bool Board::canFindConnectorsUnder() { return false; } bool Board::isBoard(ItemBase * itemBase) { if (qobject_cast(itemBase) == NULL) return false; return isBoard(itemBase->modelPart()); } bool Board::isBoard(ModelPart * modelPart) { if (modelPart == NULL) return false; switch (modelPart->itemType()) { case ModelPart::Board: return true; case ModelPart::ResizableBoard: return true; case ModelPart::Logo: return modelPart->family().contains("pcb", Qt::CaseInsensitive); default: return false; } } void Board::setupLoadImage(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget) { Q_UNUSED(returnValue); Q_UNUSED(value); Q_UNUSED(prop); Q_UNUSED(family); Q_UNUSED(parent); returnProp = tr("image file"); QFrame * frame = new QFrame(); frame->setObjectName("infoViewPartFrame"); QVBoxLayout * vboxLayout = new QVBoxLayout(); vboxLayout->setContentsMargins(0, 0, 0, 0); vboxLayout->setSpacing(0); vboxLayout->setMargin(0); QComboBox * comboBox = new QComboBox(); comboBox->setObjectName("infoViewComboBox"); comboBox->setEditable(false); comboBox->setEnabled(swappingEnabled); m_fileNameComboBox = comboBox; setFileNameItems(); connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(fileNameEntry(const QString &))); QPushButton * button = new QPushButton (tr("load image file")); button->setObjectName("infoViewButton"); connect(button, SIGNAL(pressed()), this, SLOT(prepLoadImage())); button->setEnabled(swappingEnabled); vboxLayout->addWidget(comboBox); vboxLayout->addWidget(button); frame->setLayout(vboxLayout); returnWidget = frame; returnProp = ""; } void Board::setFileNameItems() { if (m_fileNameComboBox == NULL) return; m_fileNameComboBox->addItems(getImageNames()); m_fileNameComboBox->addItems(getNewImageNames()); int ix = 0; foreach (QString name, getImageNames()) { if (prop("lastfilename").contains(name)) { m_fileNameComboBox->setCurrentIndex(ix); return; } ix++; } foreach (QString name, getNewImageNames()) { if (prop("lastfilename").contains(name)) { m_fileNameComboBox->setCurrentIndex(ix); return; } ix++; } } QStringList & Board::getImageNames() { return BoardImageNames; } QStringList & Board::getNewImageNames() { return NewBoardImageNames; } void Board::fileNameEntry(const QString & filename) { foreach (QString name, getImageNames()) { if (filename.compare(name) == 0) { QString f = FolderUtils::getApplicationSubFolderPath("parts") + "/svg/core/pcb/" + filename + ".svg"; prepLoadImageAux(f, false); return; } } prepLoadImageAux(filename, true); } void Board::prepLoadImage() { QString imagesStr = tr("Images"); imagesStr += " ("; if (!m_svgOnly) { QList supportedImageFormats = QImageReader::supportedImageFormats(); foreach (QByteArray ba, supportedImageFormats) { imagesStr += "*." + QString(ba) + " "; } } if (!imagesStr.contains("svg")) { imagesStr += "*.svg"; } imagesStr += ")"; QString fileName = FolderUtils::getOpenFileName( NULL, tr("Select an image file to load"), "", imagesStr ); if (fileName.isEmpty()) return; if (!checkImage(fileName)) return; prepLoadImageAux(fileName, true); } bool Board::checkImage(const QString & filename) { QFile file(filename); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { unableToLoad(filename, tr("due to an xml problem: %1 line:%2 column:%3").arg(errorStr).arg(errorLine).arg(errorColumn)); return false; } QDomElement root = domDocument.documentElement(); if (root.tagName() != "svg") { unableToLoad(filename, tr("because the xml is not correctly formatted")); return false; } QList elements; TextUtils::findElementsWithAttribute(root, "id", elements); int layers = 0; QList boardElements; int silk0Layers = 0; int silk1Layers = 0; bool boardHasChildren = false; foreach (QDomElement element, elements) { QString id = element.attribute("id"); ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(id); if (viewLayerID != ViewLayer::UnknownLayer) { layers++; if (viewLayerID == ViewLayer::Board) { boardElements << element; if (element.childNodes().count() > 0) { boardHasChildren = true; } } else if (viewLayerID == ViewLayer::Silkscreen1) { silk1Layers++; } else if (viewLayerID == ViewLayer::Silkscreen0) { silk0Layers++; } } } if (boardElements.count() == 1 && !boardHasChildren) { unableToLoad(filename, tr("the element contains no shape elements") + StandardCustomBoardExplanation); return false; } if ((boardElements.count() == 1) && ((silk1Layers == 1) || (silk0Layers == 1))) { moreCheckImage(filename); return true; } if (boardElements.count() > 1) { unableToLoad(filename, tr("because there are multiple layers") + StandardCustomBoardExplanation); return false; } if (silk1Layers > 1) { unableToLoad(filename, tr("because there are multiple layers") + StandardCustomBoardExplanation); return false; } if (silk0Layers > 1) { unableToLoad(filename, tr("because there are multiple layers") + StandardCustomBoardExplanation); return false; } if (layers > 0 && boardElements.count() == 0) { unableToLoad(filename, tr("because there is no layer") + StandardCustomBoardExplanation); return false; } if (layers == 0 && root.childNodes().count() == 0) { unableToLoad(filename, tr("the svg contains no shape elements") + StandardCustomBoardExplanation); return false; } if (layers == 0 || (boardElements.count() == 1 && silk1Layers == 0 && silk1Layers == 0)) { bool result = canLoad(filename, tr("but the pcb itself will have no silkscreen layer") + StandardCustomBoardExplanation); if (result) moreCheckImage(filename); return result; } unableToLoad(filename, tr("the svg doesn't fit the custom board format") + StandardCustomBoardExplanation); return false; } void Board::moreCheckImage(const QString & filename) { QFile file(filename); file.open(QFile::ReadOnly); QString svg = file.readAll(); file.close(); QString nsvg = setBoardOutline(svg); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; domDocument.setContent(nsvg, &errorStr, &errorLine, &errorColumn); QDomElement element = TextUtils::findElementWithAttribute(domDocument.documentElement(), "id", GerberGenerator::MagicBoardOutlineID); int subpaths = 1; int mCount = 0; if (element.tagName() == "path") { QString originalPath = element.attribute("d", "").trimmed(); if (GerberGenerator::MultipleZs.indexIn(originalPath) >= 0) { QStringList ds = element.attribute("d").split("z", QString::SkipEmptyParts); subpaths = ds.count(); foreach (QString d, ds) { if (d.trimmed().startsWith("m", Qt::CaseInsensitive)) mCount++; } } } QString msg = tr("The custom shape has been loaded, and you will see the new board shortly.

"); msg += tr("Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. "); msg += tr("Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.

"); msg += tr("The rest of this message concerns 'cutouts'. "); msg += tr("These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.

"); if (subpaths == 1) { msg += tr("The custom shape has no cutouts."); } else { msg += tr("The custom shape has %n cutouts.", "", subpaths - 1); if (subpaths != mCount) { msg += tr("
However, the cutouts may not be formatted correctly."); } } msg += tr("

If you intended your custom shape to have cutouts and you did not get the expected result, "); msg += tr("it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor."); QMessageBox::information(NULL, "Custom Shape", msg); } QString Board::setBoardOutline(const QString & svg) { QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, true, &errorStr, &errorLine, &errorColumn)) { return svg; } QDomElement root = domDocument.documentElement(); if (root.tagName() != "svg") { return svg; } QDomElement board = TextUtils::findElementWithAttribute(root, "id", "board"); if (board.isNull()) { board = root; } QList leaves; TextUtils::collectLeaves(board, leaves); if (leaves.count() == 1) { QDomElement leaf = leaves.at(0); leaf.setAttribute("id", GerberGenerator::MagicBoardOutlineID); return TextUtils::removeXMLEntities(domDocument.toString()); } int ix = 0; QStringList ids; foreach (QDomElement leaf, leaves) { ids.append(leaf.attribute("id", "")); leaf.setAttribute("id", QString("____%1____").arg(ix++)); } QSvgRenderer renderer(domDocument.toByteArray()); ix = 0; foreach (QDomElement leaf, leaves) { leaf.setAttribute("id", ids.at(ix++)); } double maxArea = 0; int maxIndex = -1; for (int i = 0; i < leaves.count(); i++) { QRectF r = renderer.boundsOnElement(QString("____%1____").arg(i)); if (r.width() * r.height() > maxArea) { maxArea = r.width() * r.height(); maxIndex = i; } } if (maxIndex >= 0) { QDomElement leaf = leaves.at(maxIndex); leaf.setAttribute("id", GerberGenerator::MagicBoardOutlineID); return TextUtils::removeXMLEntities(domDocument.toString()); } return svg; } void Board::unableToLoad(const QString & fileName, const QString & reason) { QMessageBox::information( NULL, tr("Unable to load"), tr("Unable to load image from %1 %2").arg(fileName).arg(reason) ); } bool Board::canLoad(const QString & fileName, const QString & reason) { QMessageBox::StandardButton answer = QMessageBox::question( NULL, tr("Can load, but"), tr("The image from %1 can be loaded, but %2\nUse the file?").arg(fileName).arg(reason), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); return answer == QMessageBox::Yes; } void Board::prepLoadImageAux(const QString & fileName, bool addName) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->loadLogoImage(this, "", QSizeF(0,0), "", fileName, addName); } } ViewLayer::ViewID Board::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::PCBView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } QString Board::convertToXmlName(const QString & name) { foreach (QString key, ItemBase::TranslatedPropertyNames.keys()) { if (name.compare(ItemBase::TranslatedPropertyNames.value(key), Qt::CaseInsensitive) == 0) { return NamesToXmlNames.value(key); } } return name; } QString Board::convertFromXmlName(const QString & xmlName) { QString result = ItemBase::TranslatedPropertyNames.value(XmlNamesToNames.value(xmlName)); if (result.isEmpty()) return xmlName; return result; } /////////////////////////////////////////////////////////// ResizableBoard::ResizableBoard( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Board(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { fixWH(); m_keepAspectRatio = false; m_widthEditor = m_heightEditor = NULL; m_aspectRatioCheck = NULL; m_aspectRatioLabel = NULL; m_revertButton = NULL; m_paperSizeComboBox = NULL; m_corner = ResizableBoard::NO_CORNER; m_currentScale = 1.0; m_decimalsAfter = 1; } ResizableBoard::~ResizableBoard() { } void ResizableBoard::addedToScene(bool temporary) { loadTemplates(); if (this->scene()) { setInitialSize(); } Board::addedToScene(temporary); } void ResizableBoard::loadTemplates() { if (!BoardLayerTemplates.value(moduleID(), "").isEmpty()) return; QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) return; QString svg = file.readAll(); if (svg.isEmpty()) return; BoardLayerTemplates.insert(moduleID(), getShapeForRenderer(svg, ViewLayer::Board)); SilkscreenLayerTemplates.insert(moduleID(), getShapeForRenderer(svg, ViewLayer::Silkscreen1)); Silkscreen0LayerTemplates.insert(moduleID(), getShapeForRenderer(svg, ViewLayer::Silkscreen0)); } double ResizableBoard::minWidth() { return 0.25 * GraphicsUtils::SVGDPI; } double ResizableBoard::minHeight() { return 0.25 * GraphicsUtils::SVGDPI; } void ResizableBoard::mousePressEvent(QGraphicsSceneMouseEvent * event) { m_corner = ResizableBoard::NO_CORNER; if (m_spaceBarWasPressed) { Board::mousePressEvent(event); return; } double right = m_size.width(); double bottom = m_size.height(); m_resizeMousePos = event->scenePos(); m_resizeStartPos = pos(); m_resizeStartSize = m_size; m_resizeStartTopLeft = mapToScene(0, 0); m_resizeStartTopRight = mapToScene(right, 0); m_resizeStartBottomLeft = mapToScene(0, bottom); m_resizeStartBottomRight = mapToScene(right, bottom); m_corner = findCorner(event->scenePos(), event->modifiers()); switch (m_corner) { case ResizableBoard::NO_CORNER: Board::mousePressEvent(event); return; default: break; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) { setInitialSize(); infoGraphicsView->viewItemInfo(this); } } void ResizableBoard::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { if (m_corner == ResizableBoard::NO_CORNER) { Board::mouseMoveEvent(event); return; } QPointF zero = mapToScene(0, 0); QPointF ds = mapFromScene(zero + event->scenePos() - m_resizeMousePos); QPointF newPos; QSizeF size = m_resizeStartSize; switch (m_corner) { case ResizableBoard::BOTTOM_RIGHT: size.setWidth(size.width() + ds.x()); size.setHeight(size.height() + ds.y()); break; case ResizableBoard::TOP_RIGHT: size.setWidth(size.width() + ds.x()); size.setHeight(size.height() - ds.y()); break; case ResizableBoard::BOTTOM_LEFT: size.setWidth(size.width() - ds.x()); size.setHeight(size.height() + ds.y()); break; case ResizableBoard::TOP_LEFT: size.setWidth(size.width() - ds.x()); size.setHeight(size.height() - ds.y()); break; default: break; } if (size.width() < minWidth()) { DebugDialog::debug("to min width"); size.setWidth(minWidth()); } if (size.height() < minHeight()) { DebugDialog::debug("to min height"); size.setHeight(minHeight()); } if (m_keepAspectRatio) { double cw = size.height() * m_aspectRatio.width() / m_aspectRatio.height(); double ch = size.width() * m_aspectRatio.height() / m_aspectRatio.width(); if (ch < minHeight()) { DebugDialog::debug("from min height"); size.setWidth(cw); } else if (cw < minWidth()) { DebugDialog::debug("from min width"); size.setHeight(ch); } else { // figure out which one changes the area least double a1 = cw * size.height(); double a2 = ch * size.width(); double ac = m_size.width() * m_size.height(); if (qAbs(ac - a1) <= qAbs(ac - a2)) { size.setWidth(cw); } else { size.setHeight(ch); } } } bool changePos = (m_corner != ResizableBoard::BOTTOM_RIGHT); bool changeTransform = !this->transform().isIdentity(); LayerHash lh; QSizeF oldSize = m_size; resizePixels(size.width(), size.height(), lh); if (changePos) { if (changeTransform) { QTransform oldT = transform(); DebugDialog::debug(QString("t old m:%1 p:%2,%3 sz:%4,%5") .arg(TextUtils::svgMatrix(oldT)) .arg(pos().x()).arg(pos().y()) .arg(oldSize.width()).arg(oldSize.height())); double sw = size.width() / 2; double sh = size.height() / 2; QMatrix m(oldT.m11(), oldT.m12(), oldT.m21(), oldT.m22(), 0, 0); ds = m.inverted().map(ds); QTransform newT = QTransform().translate(-sw, -sh) * QTransform(m) * QTransform().translate(sw, sh); QList kin; kin << this->layerKinChief(); foreach (ItemBase * lk, this->layerKinChief()->layerKin()) { kin << lk; } foreach (ItemBase * itemBase, kin) { itemBase->getViewGeometry().setTransform(newT); itemBase->setTransform(newT); } QTransform t = transform(); DebugDialog::debug(QString("t new m:%1 p:%2,%3 sz:%4,%5") .arg(TextUtils::svgMatrix(t)) .arg(pos().x()).arg(pos().y()) .arg(size.width()).arg(size.height())); } QPointF actual; QPointF desired; switch (m_corner) { case ResizableBoard::TOP_RIGHT: actual = mapToScene(0, size.height()); desired = m_resizeStartBottomLeft; break; case ResizableBoard::BOTTOM_LEFT: actual = mapToScene(size.width(), 0); desired = m_resizeStartTopRight; break; case ResizableBoard::TOP_LEFT: actual = mapToScene(size.width(), size.height()); desired = m_resizeStartBottomRight; break; default: break; } setPos(pos() + desired - actual); } } void ResizableBoard::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) { if (m_corner == ResizableBoard::NO_CORNER) { Board::mouseReleaseEvent(event); return; } event->accept(); m_corner = ResizableBoard::NO_CORNER; setKinCursor(Qt::ArrowCursor); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) { infoGraphicsView->viewItemInfo(this); } } ViewLayer::ViewID ResizableBoard::theViewID() { return ViewLayer::PCBView; } void ResizableBoard::resizePixels(double w, double h, const LayerHash & viewLayers) { resizeMM(GraphicsUtils::pixels2mm(w, GraphicsUtils::SVGDPI), GraphicsUtils::pixels2mm(h, GraphicsUtils::SVGDPI), viewLayers); } bool ResizableBoard::resizeMM(double mmW, double mmH, const LayerHash & viewLayers) { if (mmW == 0 || mmH == 0) { LayerAttributes layerAttributes; this->initLayerAttributes(layerAttributes, m_viewID, m_viewLayerID, m_viewLayerPlacement, true, true); setUpImage(modelPart(), viewLayers, layerAttributes); modelPart()->setLocalProp("height", QVariant()); modelPart()->setLocalProp("width", QVariant()); // do the layerkin return false; } QRectF r = this->boundingRect(); if (qAbs(GraphicsUtils::pixels2mm(r.width(), GraphicsUtils::SVGDPI) - mmW) < .001 && qAbs(GraphicsUtils::pixels2mm(r.height(), GraphicsUtils::SVGDPI) - mmH) < .001) { return false; } resizeMMAux(mmW, mmH); return true; } void ResizableBoard::resizeMMAux(double mmW, double mmH) { double milsW = GraphicsUtils::mm2mils(mmW); double milsH = GraphicsUtils::mm2mils(mmH); QString s = makeFirstLayerSvg(mmW, mmH, milsW, milsH); bool result = resetRenderer(s); if (result) { modelPart()->setLocalProp("width", mmW); modelPart()->setLocalProp("height", mmH); double tens = pow(10.0, m_decimalsAfter); setWidthAndHeight(qRound(mmW * tens) / tens, qRound(mmH * tens) / tens); } // DebugDialog::debug(QString("fast load result %1 %2").arg(result).arg(s)); foreach (ItemBase * itemBase, m_layerKin) { QString s = makeNextLayerSvg(itemBase->viewLayerID(), mmW, mmH, milsW, milsH); if (!s.isEmpty()) { result = itemBase->resetRenderer(s); if (result) { itemBase->modelPart()->setLocalProp("width", mmW); itemBase->modelPart()->setLocalProp("height", mmH); } } } } void ResizableBoard::loadLayerKin( const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement viewLayerPlacement) { loadTemplates(); Board::loadLayerKin(viewLayers, viewLayerPlacement); double w = m_modelPart->localProp("width").toDouble(); if (w != 0) { resizeMM(w, m_modelPart->localProp("height").toDouble(), viewLayers); } } void ResizableBoard::setInitialSize() { double w = m_modelPart->localProp("width").toDouble(); if (w == 0) { // set the size so the infoGraphicsView will display the size as you drag QSizeF sz = this->boundingRect().size(); modelPart()->setLocalProp("width", GraphicsUtils::pixels2mm(sz.width(), GraphicsUtils::SVGDPI)); modelPart()->setLocalProp("height", GraphicsUtils::pixels2mm(sz.height(), GraphicsUtils::SVGDPI)); } } QString ResizableBoard::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { double w = m_modelPart->localProp("width").toDouble(); if (w != 0) { double h = m_modelPart->localProp("height").toDouble(); QString xml = makeLayerSvg(viewLayerID, w, h, GraphicsUtils::mm2mils(w), GraphicsUtils::mm2mils(h)); if (!xml.isEmpty()) { return PaletteItemBase::normalizeSvg(xml, viewLayerID, blackOnly, dpi, factor); } } return Board::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QSizeF ResizableBoard::getSizeMM() { double w = m_modelPart->localProp("width").toDouble(); double h = m_modelPart->localProp("height").toDouble(); return QSizeF(w, h); } QString ResizableBoard::makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { switch (viewLayerID) { case ViewLayer::Board: return makeBoardSvg(mmW, mmH, milsW, milsH); case ViewLayer::Silkscreen1: case ViewLayer::Silkscreen0: return makeSilkscreenSvg(viewLayerID, mmW, mmH, milsW, milsH); break; default: return ""; } } QString ResizableBoard::makeNextLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { if (viewLayerID == ViewLayer::Silkscreen1) return makeSilkscreenSvg(viewLayerID, mmW, mmH, milsW, milsH); if (viewLayerID == ViewLayer::Silkscreen0) return makeSilkscreenSvg(viewLayerID, mmW, mmH, milsW, milsH); return ""; } QString ResizableBoard::makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH) { return makeBoardSvg(mmW, mmH, milsW, milsH); } QString ResizableBoard::makeBoardSvg(double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(milsW); Q_UNUSED(milsH); return makeSvg(mmW, mmH, BoardLayerTemplates.value(moduleID())); } QString ResizableBoard::makeSilkscreenSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(milsW); Q_UNUSED(milsH); if (viewLayerID == ViewLayer::Silkscreen0) return makeSvg(mmW, mmH, Silkscreen0LayerTemplates.value(moduleID())); return makeSvg(mmW, mmH, SilkscreenLayerTemplates.value(moduleID())); } QString ResizableBoard::makeSvg(double mmW, double mmH, const QString & layerTemplate) { if (layerTemplate.isEmpty()) return ""; QDomDocument doc; if (!doc.setContent(layerTemplate)) return ""; QDomElement root = doc.documentElement(); static const QString mmString("%1mm"); root.setAttribute("width", mmString.arg(mmW)); root.setAttribute("height", mmString.arg(mmH)); root.setAttribute("viewBox", QString("0 0 %1 %2").arg(mmW).arg(mmH)); QList leaves; TextUtils::collectLeaves(root, leaves); if (leaves.count() > 1) return ""; QDomElement leaf = leaves.at(0); bool ok; double strokeWidth = leaf.attribute("stroke-width").toDouble(&ok); if (!ok) return ""; if (layerTemplate.contains("localProp("width").toDouble(); double h = modelPart()->localProp("height").toDouble(); m_boardSize = QSizeF(w, h); m_boardPos = pos(); } void ResizableBoard::getParams(QPointF & p, QSizeF & s) { p = m_boardPos; s = m_boardSize; } bool ResizableBoard::hasCustomSVG() { return theViewID() == m_viewID; } bool ResizableBoard::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { bool result = Board::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("shape", Qt::CaseInsensitive) == 0) { returnProp = tr("shape"); if (!m_modelPart->localProp("height").isValid()) { // display uneditable width and height QFrame * frame = new QFrame(); frame->setObjectName("infoViewPartFrame"); QVBoxLayout * vboxLayout = new QVBoxLayout(); vboxLayout->setAlignment(Qt::AlignLeft); vboxLayout->setSpacing(0); vboxLayout->setMargin(0); vboxLayout->setContentsMargins(0, 3, 0, 0); double tens = pow(10.0, m_decimalsAfter); QRectF r = this->boundingRect(); double w = qRound(GraphicsUtils::pixels2mm(r.width(), GraphicsUtils::SVGDPI) * tens) / tens; QLabel * l1 = new QLabel(tr("width: %1mm").arg(w)); l1->setMargin(0); l1->setObjectName("infoViewLabel"); double h = qRound(GraphicsUtils::pixels2mm(r.height(), GraphicsUtils::SVGDPI) * tens) / tens; QLabel * l2 = new QLabel(tr("height: %1mm").arg(h)); l2->setMargin(0); l2->setObjectName("infoViewLabel"); if (returnWidget) vboxLayout->addWidget(qobject_cast(returnWidget)); vboxLayout->addWidget(l1); vboxLayout->addWidget(l2); frame->setLayout(vboxLayout); returnValue = l1->text() + "," + l2->text(); returnWidget = frame; return true; } returnWidget = setUpDimEntry(false, false, false, returnWidget); returnWidget->setEnabled(swappingEnabled); return true; } return result; } QStringList ResizableBoard::collectValues(const QString & family, const QString & prop, QString & value) { return Board::collectValues(family, prop, value); } void ResizableBoard::paperSizeChanged(int index) { QComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; QModelIndex modelIndex = comboBox->model()->index(index,0); QSizeF size = comboBox->model()->data(modelIndex, Qt::UserRole).toSizeF(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(size.width(), size.height(), true); } } void ResizableBoard::widthEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; double w = edit->text().toDouble(); double oldW = m_modelPart->localProp("width").toDouble(); if (w == oldW) return; double h = m_modelPart->localProp("height").toDouble(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(w, h, true); } } void ResizableBoard::heightEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; double h = edit->text().toDouble(); double oldH = m_modelPart->localProp("height").toDouble(); if (h == oldH) return; double w = m_modelPart->localProp("width").toDouble(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(w, h, true); } } bool ResizableBoard::hasPartNumberProperty() { return false; } void ResizableBoard::paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_hidden || m_layerHidden) return; Board::paintSelected(painter, option, widget); // http://www.gamedev.net/topic/441695-transform-matrix-decomposition/ double m11 = painter->worldTransform().m11(); double m12 = painter->worldTransform().m12(); double scale = m_currentScale = qSqrt((m11 * m11) + (m12 * m12)); // assumes same scaling for both x and y double scalefull = CornerHandleSize / scale; double scalehalf = scalefull / 2; double bottom = m_size.height(); double right = m_size.width(); QPen pen; pen.setWidthF(1.0 / scale); pen.setColor(QColor(0, 0, 0)); QBrush brush(QColor(255, 255, 255)); painter->setPen(pen); painter->setBrush(brush); QPolygonF poly; // upper left poly.append(QPointF(0, 0)); poly.append(QPointF(0, scalefull)); poly.append(QPointF(scalehalf, scalefull)); poly.append(QPointF(scalehalf, scalehalf)); poly.append(QPointF(scalefull, scalehalf)); poly.append(QPointF(scalefull, 0)); painter->drawPolygon(poly); // upper right poly.clear(); poly.append(QPointF(right, 0)); poly.append(QPointF(right, scalefull)); poly.append(QPointF(right - scalehalf, scalefull)); poly.append(QPointF(right - scalehalf, scalehalf)); poly.append(QPointF(right - scalefull, scalehalf)); poly.append(QPointF(right - scalefull, 0)); painter->drawPolygon(poly); // lower left poly.clear(); poly.append(QPointF(0, bottom - scalefull)); poly.append(QPointF(0, bottom)); poly.append(QPointF(scalefull, bottom)); poly.append(QPointF(scalefull, bottom - scalehalf)); poly.append(QPointF(scalehalf, bottom - scalehalf)); poly.append(QPointF(scalehalf, bottom - scalefull)); painter->drawPolygon(poly); // lower right poly.clear(); poly.append(QPointF(right, bottom - scalefull)); poly.append(QPointF(right, bottom)); poly.append(QPointF(right - scalefull, bottom)); poly.append(QPointF(right - scalefull, bottom - scalehalf)); poly.append(QPointF(right - scalehalf, bottom - scalehalf)); poly.append(QPointF(right - scalehalf, bottom - scalefull)); painter->drawPolygon(poly); } bool ResizableBoard::inResize() { return m_corner != ResizableBoard::NO_CORNER; } void ResizableBoard::figureHover() { setAcceptHoverEvents(true); setAcceptedMouseButtons(ALLMOUSEBUTTONS); foreach(ItemBase * lkpi, m_layerKin) { lkpi->setAcceptHoverEvents(false); lkpi->setAcceptedMouseButtons(Qt::NoButton); } } void ResizableBoard::hoverEnterEvent( QGraphicsSceneHoverEvent * event ) { Board::hoverEnterEvent(event); } void ResizableBoard::hoverMoveEvent( QGraphicsSceneHoverEvent * event ) { Board::hoverMoveEvent(event); m_corner = findCorner(event->scenePos(), event->modifiers()); QCursor cursor; switch (m_corner) { case ResizableBoard::BOTTOM_RIGHT: case ResizableBoard::TOP_LEFT: case ResizableBoard::TOP_RIGHT: case ResizableBoard::BOTTOM_LEFT: //DebugDialog::debug("setting scale cursor"); cursor = *CursorMaster::ScaleCursor; break; default: //DebugDialog::debug("setting other cursor"); cursor = Qt::ArrowCursor; break; } setKinCursor(cursor); } void ResizableBoard::hoverLeaveEvent( QGraphicsSceneHoverEvent * event ) { setKinCursor(Qt::ArrowCursor); //DebugDialog::debug("setting arrow cursor"); Board::hoverLeaveEvent(event); } ResizableBoard::Corner ResizableBoard::findCorner(QPointF scenePos, Qt::KeyboardModifiers modifiers) { Q_UNUSED(modifiers); if (!this->isSelected()) return ResizableBoard::NO_CORNER; if (this->moveLock()) return ResizableBoard::NO_CORNER; double d = CornerHandleSize / m_currentScale; double d2 = d * d; double right = m_size.width(); double bottom = m_size.height(); //DebugDialog::debug(QString("size %1 %2").arg(right).arg(bottom)); QPointF q = mapToScene(right, bottom); if (GraphicsUtils::distanceSqd(scenePos, q) <= d2) { return ResizableBoard::BOTTOM_RIGHT; } q = mapToScene(0, 0); if (GraphicsUtils::distanceSqd(scenePos, q) <= d2) { return ResizableBoard::TOP_LEFT; } q = mapToScene(right, 0); if (GraphicsUtils::distanceSqd(scenePos, q) <= d2) { return ResizableBoard::TOP_RIGHT; } q = mapToScene(0, bottom); if (GraphicsUtils::distanceSqd(scenePos, q) <= d2) { return ResizableBoard::BOTTOM_LEFT; } return ResizableBoard::NO_CORNER; } void ResizableBoard::setKinCursor(QCursor & cursor) { ItemBase * chief = this->layerKinChief(); chief->setCursor(cursor); foreach (ItemBase * itemBase, chief->layerKin()) { itemBase->setCursor(cursor); } } void ResizableBoard::setKinCursor(Qt::CursorShape cursor) { ItemBase * chief = this->layerKinChief(); chief->setCursor(cursor); foreach (ItemBase * itemBase, chief->layerKin()) { itemBase->setCursor(cursor); } } QFrame * ResizableBoard::setUpDimEntry(bool includeAspectRatio, bool includeRevert, bool includePaperSizes, QWidget * & returnWidget) { double tens = pow(10.0, m_decimalsAfter); double w = qRound(m_modelPart->localProp("width").toDouble() * tens) / tens; // truncate to 1 decimal point double h = qRound(m_modelPart->localProp("height").toDouble() * tens) / tens; // truncate to 1 decimal point QFrame * frame = new QFrame(); frame->setObjectName("infoViewPartFrame"); QVBoxLayout * vboxLayout = new QVBoxLayout(); vboxLayout->setAlignment(Qt::AlignLeft); vboxLayout->setSpacing(1); vboxLayout->setContentsMargins(0, 3, 0, 0); QFrame * subframe1 = new QFrame(); QHBoxLayout * hboxLayout1 = new QHBoxLayout(); hboxLayout1->setAlignment(Qt::AlignLeft); hboxLayout1->setContentsMargins(0, 0, 0, 0); hboxLayout1->setSpacing(2); QFrame * subframe2 = new QFrame(); QHBoxLayout * hboxLayout2 = new QHBoxLayout(); hboxLayout2->setAlignment(Qt::AlignLeft); hboxLayout2->setContentsMargins(0, 0, 0, 0); hboxLayout2->setSpacing(2); QLabel * l1 = new QLabel(tr("width(mm)")); l1->setMargin(0); l1->setObjectName("infoViewLabel"); QLineEdit * e1 = new QLineEdit(); QDoubleValidator * validator = new QDoubleValidator(e1); validator->setRange(0.1, 999.9, m_decimalsAfter); validator->setNotation(QDoubleValidator::StandardNotation); validator->setLocale(QLocale::C); e1->setObjectName("infoViewLineEdit"); e1->setValidator(validator); e1->setMaxLength(4 + m_decimalsAfter); e1->setText(QString::number(w)); QLabel * l2 = new QLabel(tr("height(mm)")); l2->setMargin(0); l2->setObjectName("infoViewLabel"); QLineEdit * e2 = new QLineEdit(); validator = new QDoubleValidator(e1); validator->setRange(0.1, 999.9, m_decimalsAfter); validator->setNotation(QDoubleValidator::StandardNotation); validator->setLocale(QLocale::C); e2->setObjectName("infoViewLineEdit"); e2->setValidator(validator); e2->setMaxLength(4 + m_decimalsAfter); e2->setText(QString::number(h)); hboxLayout1->addWidget(l1); hboxLayout1->addWidget(e1); hboxLayout2->addWidget(l2); hboxLayout2->addWidget(e2); subframe1->setLayout(hboxLayout1); subframe2->setLayout(hboxLayout2); if (returnWidget != NULL) vboxLayout->addWidget(returnWidget); connect(e1, SIGNAL(editingFinished()), this, SLOT(widthEntry())); connect(e2, SIGNAL(editingFinished()), this, SLOT(heightEntry())); m_widthEditor = e1; m_heightEditor = e2; vboxLayout->addWidget(subframe1); vboxLayout->addWidget(subframe2); if (includeAspectRatio || includeRevert || includePaperSizes) { QFrame * subframe3 = new QFrame(); QHBoxLayout * hboxLayout3 = new QHBoxLayout(); hboxLayout3->setAlignment(Qt::AlignLeft); hboxLayout3->setContentsMargins(0, 0, 0, 0); hboxLayout3->setSpacing(0); if (includeAspectRatio) { QLabel * l3 = new QLabel(tr("keep aspect ratio")); l3->setMargin(0); l3->setObjectName("infoViewLabel"); QCheckBox * checkBox = new QCheckBox(); checkBox->setChecked(m_keepAspectRatio); checkBox->setObjectName("infoViewCheckBox"); hboxLayout3->addWidget(l3); hboxLayout3->addWidget(checkBox); connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(keepAspectRatio(bool))); m_aspectRatioCheck = checkBox; m_aspectRatioLabel = l3; } if (includeRevert) { QPushButton * pb = new QPushButton(tr("Revert")); pb->setObjectName("infoViewButton"); hboxLayout3->addWidget(pb); connect(pb, SIGNAL(clicked(bool)), this, SLOT(revertSize(bool))); double w = modelPart()->localProp("width").toDouble(); double ow = modelPart()->localProp("originalWidth").toDouble(); double h = modelPart()->localProp("height").toDouble(); double oh = modelPart()->localProp("originalHeight").toDouble(); pb->setEnabled(qAbs(w - ow) > JND || qAbs(h - oh) > JND); m_revertButton = pb; } if (includePaperSizes) { initPaperSizes(); QLabel * l3 = new QLabel(tr("size")); l3->setMargin(0); l3->setObjectName("infoViewLabel"); m_paperSizeComboBox = new QComboBox(); m_paperSizeComboBox->setObjectName("infoViewComboBox"); m_paperSizeComboBox->setEditable(false); m_paperSizeComboBox->setMinimumWidth(150); m_paperSizeComboBox->addItem(tr("custom")); for (int i = 0; i < PaperSizeNames.count(); i++) { QSizeF dim = PaperSizeDimensions.at(i); m_paperSizeComboBox->addItem(PaperSizeNames.at(i), dim); } QModelIndex modelIndex = m_paperSizeComboBox->model()->index(0,0); m_paperSizeComboBox->model()->setData(modelIndex, 0, Qt::UserRole - 1); // to make it selectable again use Qt::ItemIsSelectable | Qt::ItemIsEnabled) updatePaperSizes(w, h); connect(m_paperSizeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(paperSizeChanged(int))); hboxLayout3->addWidget(l3); hboxLayout3->addWidget(m_paperSizeComboBox); } subframe3->setLayout(hboxLayout3); vboxLayout->addWidget(subframe3); } frame->setLayout(vboxLayout); return frame; } void ResizableBoard::fixWH() { bool okw, okh; QString wstr = m_modelPart->localProp("width").toString(); QString hstr = m_modelPart->localProp("height").toString(); double w = wstr.toDouble(&okw); double h = hstr.toDouble(&okh); //DebugDialog::debug(QString("w:%1 %2 ok:%3 h:%4 %5 ok:%6") //.arg(wstr).arg(w).arg(okw) //.arg(hstr).arg(h).arg(okh)); if ((!okw && !wstr.isEmpty()) || qIsNaN(w) || qIsInf(w) || (!okh && !hstr.isEmpty()) || qIsNaN(h) || qIsInf(h)) { DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); DebugDialog::debug("bad width or height in ResizableBoard or subclass " + wstr + " " + hstr); DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); m_modelPart->setLocalProp("width", ""); m_modelPart->setLocalProp("height", ""); } } void ResizableBoard::setWidthAndHeight(double w, double h) { if (m_widthEditor) { m_widthEditor->setText(QString::number(w)); } if (m_heightEditor) { m_heightEditor->setText(QString::number(h)); } updatePaperSizes(w, h); } QString ResizableBoard::getShapeForRenderer(const QString & svg, ViewLayer::ViewLayerID viewLayerID) { QString xmlName = ViewLayer::viewLayerXmlNameFromID(viewLayerID); SvgFileSplitter splitter; QString xml = svg; bool result = splitter.splitString(xml, xmlName); if (result) { xml = splitter.elementString(xmlName); } else { xml = ""; } QString header("\n" ""; //DebugDialog::debug("resizableBoard " + header); return header; } void ResizableBoard::keepAspectRatio(bool checkState) { m_keepAspectRatio = checkState; } void ResizableBoard::revertSize(bool) { double ow = modelPart()->localProp("originalWidth").toDouble(); double oh = modelPart()->localProp("originalHeight").toDouble(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->resizeBoard(ow, oh, true); m_revertButton->setEnabled(false); } } void ResizableBoard::updatePaperSizes(double w, double h) { if (m_paperSizeComboBox == NULL) return; int currentIndex = 0; for (int i = 0; i < PaperSizeNames.count(); i++) { QSizeF dim = PaperSizeDimensions.at(i); if (qAbs(w - dim.width()) < 0.1 && qAbs(h - dim.height()) < 0.1) { currentIndex = i + 1; } } QString custom = tr("custom"); if (currentIndex == 0) { custom = QString("%1x%2").arg(w).arg(h); } m_paperSizeComboBox->setItemText(0, custom); m_paperSizeComboBox->setCurrentIndex(currentIndex); } void ResizableBoard::initPaperSizes() { if (PaperSizeNames.count() == 0) { PaperSizeNames << tr("A0 (1030x1456)") << tr("A1 (728x1030)") << tr("A2 (515x728)") << tr("A3 (364x515)") << tr("A4 (257x364)") << tr("A5 (182x257)") << tr("A6 (128x182)") << tr("Letter (8.5x11)") << tr("Legal (8.5x14)") << tr("Ledger (17x11)") << tr("Tabloid (11x17)"); PaperSizeDimensions << QSizeF(1030,1456) << QSizeF(728,1030) << QSizeF(515,728) << QSizeF(364,515) << QSizeF(257,364) << QSizeF(182,257) << QSizeF(128,182) << QSizeF(215.9,279.4) << QSizeF(215.9,355.6) << QSizeF(432,279) << QSizeF(279,432); } } �����������������������������������������fritzing-app-0.9.2b/src/items/resizableboard.h������������������������������������������������������0000664�0000000�0000000�00000016315�12502026767�0021364�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef RESIZABLEBOARD_H #define RESIZABLEBOARD_H #include #include #include #include #include #include #include #include #include #include #include "paletteitem.h" class Board : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Board(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Board(); QStringList collectValues(const QString & family, const QString & prop, QString & value); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool rotation45Allowed(); bool stickyEnabled(); PluralType isPlural(); bool canFindConnectorsUnder(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); protected: void setupLoadImage(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget); void setFileNameItems(); virtual QStringList & getImageNames(); virtual QStringList & getNewImageNames(); virtual bool checkImage(const QString & filename); void unableToLoad(const QString & fileName, const QString & reason); bool canLoad(const QString & fileName, const QString & reason); virtual void prepLoadImageAux(const QString & fileName, bool addName); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected: static void moreCheckImage(const QString & filename); static QString setBoardOutline(const QString & svg); public: static QString OneLayerTranslated; static QString TwoLayersTranslated; public: static bool isBoard(ItemBase *); static bool isBoard(ModelPart *); static QString convertToXmlName(const QString &); static QString convertFromXmlName(const QString &); protected slots: void prepLoadImage(); void fileNameEntry(const QString & filename); protected: QPointer m_fileNameComboBox; bool m_svgOnly; protected: static QStringList BoardImageNames; static QStringList NewBoardImageNames; }; class ResizableBoard : public Board { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call ResizableBoard(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~ResizableBoard(); virtual bool resizeMM(double w, double h, const LayerHash & viewLayers); void resizePixels(double w, double h, const LayerHash & viewLayers); void loadLayerKin(const LayerHash & viewLayers, ViewLayer::ViewLayerPlacement); virtual void setInitialSize(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void saveParams(); void getParams(QPointF &, QSizeF &); bool hasCustomSVG(); QSizeF getSizeMM(); void addedToScene(bool temporary); bool hasPartNumberProperty(); void paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool inResize(); void figureHover(); public slots: virtual void widthEntry(); virtual void heightEntry(); void keepAspectRatio(bool checkState); void revertSize(bool); virtual void paperSizeChanged(int); protected: enum Corner { NO_CORNER = 0, TOP_LEFT , TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; protected: void mousePressEvent(QGraphicsSceneMouseEvent * event ); void mouseMoveEvent(QGraphicsSceneMouseEvent * event ); void mouseReleaseEvent(QGraphicsSceneMouseEvent * event ); void hoverEnterEvent(QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent(QGraphicsSceneHoverEvent * event ); void hoverMoveEvent(QGraphicsSceneHoverEvent * event ); QString makeBoardSvg(double mmW, double mmH, double milsW, double milsH); QString makeSilkscreenSvg(ViewLayer::ViewLayerID, double mmW, double mmH, double milsW, double milsH); QString makeSvg(double mmW, double mmH, const QString & layerTemplate); QStringList collectValues(const QString & family, const QString & prop, QString & value); virtual void loadTemplates(); virtual double minWidth(); virtual double minHeight(); virtual ViewLayer::ViewID theViewID(); virtual QString makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH); virtual QString makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH); virtual QString makeNextLayerSvg(ViewLayer::ViewLayerID, double mmW, double mmH, double milsW, double milsH); virtual void resizeMMAux(double w, double h); virtual ResizableBoard::Corner findCorner(QPointF p, Qt::KeyboardModifiers); void setKinCursor(QCursor &); void setKinCursor(Qt::CursorShape); QFrame * setUpDimEntry(bool includeAspectRatio, bool includeRevert, bool includePaperSizes, QWidget * & returnWidget); void fixWH(); void setWidthAndHeight(double w, double h); QString getShapeForRenderer(const QString & svg, ViewLayer::ViewLayerID viewLayerID); void initPaperSizes(); void updatePaperSizes(double width, double height); protected: static const double CornerHandleSize; Corner m_corner; QSizeF m_boardSize; QPointF m_boardPos; QPointer m_widthEditor; QPointer m_heightEditor; bool m_keepAspectRatio; QSizeF m_aspectRatio; double m_currentScale; QPointer m_aspectRatioCheck; QPointer m_aspectRatioLabel; QPointer m_revertButton; QPointer m_paperSizeComboBox; QPointF m_resizeMousePos; QSizeF m_resizeStartSize; QPointF m_resizeStartPos; QPointF m_resizeStartTopLeft; QPointF m_resizeStartBottomRight; QPointF m_resizeStartTopRight; QPointF m_resizeStartBottomLeft; int m_decimalsAfter; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fritzing-app-0.9.2b/src/items/ruler.cpp�������������������������������������������������������������0000664�0000000�0000000�00000024305�12502026767�0020056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "ruler.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "moduleidnames.h" #include "../utils/textutils.h" #include "../utils/boundedregexpvalidator.h" #include #include #include #include #include #include #include static const int IndexCm = 0; static const int IndexIn = 1; static QString DefaultWidth = ""; Ruler::Ruler( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { m_widthEditor = NULL; m_unitsEditor = NULL; m_widthValidator = NULL; QString w = modelPart->localProp("width").toString(); if (w.isEmpty()) { if (DefaultWidth.isEmpty()) { DefaultWidth = modelPart->properties().value("width", "10cm"); } m_modelPart->setLocalProp("width", DefaultWidth); } } Ruler::~Ruler() { } void Ruler::resizeMM(double magnitude, double unitsFlag, const LayerHash & viewLayers) { // note this really isn't resizeMM but resizeUnits Q_UNUSED(viewLayers); double w = TextUtils::convertToInches(prop("width")); QString units((unitsFlag == IndexCm) ? "cm" : "in"); double newW = TextUtils::convertToInches(QString::number(magnitude) + units); if (w == newW) return; QString s = makeSvg(newW); bool result = resetRenderer(s); if (result) { modelPart()->setLocalProp("width", QVariant(QString::number(magnitude) + units)); } // DebugDialog::debug(QString("fast load result %1 %2").arg(result).arg(s)); } QString Ruler::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { double w = TextUtils::convertToInches(m_modelPart->localProp("width").toString()); if (w != 0) { QString xml; switch (viewLayerID) { case ViewLayer::BreadboardRuler: case ViewLayer::SchematicRuler: case ViewLayer::PcbRuler: xml = makeSvg(w); break; default: break; } if (!xml.isEmpty()) { return PaletteItemBase::normalizeSvg(xml, viewLayerID, blackOnly, dpi, factor); } } return PaletteItemBase::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } QString Ruler::makeSvg(double inches) { double cm = 1 / 2.54; double offset = 0.125; double mmW = inches * 25.4; QString svg = TextUtils::makeSVGHeader(GraphicsUtils::SVGDPI, GraphicsUtils::StandardFritzingDPI, (inches + offset + offset) * GraphicsUtils::SVGDPI, GraphicsUtils::SVGDPI); svg += ""; int counter = 0; for (int i = 0; i <= qCeil(mmW); i++) { double h = cm / 4; double x = (offset + (i / 25.4)) * GraphicsUtils::StandardFritzingDPI; if (i % 10 == 0) { h = cm / 2; double y = (h + .1) * GraphicsUtils::StandardFritzingDPI; svg += QString("%3") .arg(x) .arg(y) .arg(QString::number(counter++)); if (counter == 1) { svg += QString("cm").arg(x + 103).arg(y); } } else if (i % 5 == 0) { h = 3 * cm / 8; } svg += QString("\n") .arg(x) .arg(h * GraphicsUtils::StandardFritzingDPI); } counter = 0; for (int i = 0; i <= inches * 16; i++) { double h = 0.125; double x = (offset + (i / 16.0)) * GraphicsUtils::StandardFritzingDPI; if (i % 16 == 0) { h = .125 + (3.0 / 16); double y = 1000 - ((h + .015) * GraphicsUtils::StandardFritzingDPI); svg += QString("%3") .arg(x) .arg(y) .arg(QString::number(counter++)); if (counter == 1) { svg += QString("in").arg(x + 81).arg(y); } } else if (i % 8 == 0) { h = .125 + (2.0 / 16); } else if (i % 4 == 0) { h = .125 + (1.0 / 16); } svg += QString("\n") .arg(x) .arg(1000 - (h * GraphicsUtils::StandardFritzingDPI)); } for (int i = 0; i <= inches * 10; i++) { double x = (offset + (i / 10.0)) * GraphicsUtils::StandardFritzingDPI; double h = .125 + (3.0 / 16); double h2 = h - (cm / 4); if (i % 10 != 0) { if (i % 5 == 0) { h2 = .125 + (2.0 / 16); } svg += QString("\n") .arg(x) .arg(1000 - (h * GraphicsUtils::StandardFritzingDPI)) .arg(1000 - (h2 * GraphicsUtils::StandardFritzingDPI)); } } svg += QString("\n") .arg(offset * GraphicsUtils::StandardFritzingDPI) .arg((GraphicsUtils::StandardFritzingDPI / 2) - 40) .arg((inches + offset) * GraphicsUtils::StandardFritzingDPI); svg += "\n"; svg += QString("1/10").arg((GraphicsUtils::StandardFritzingDPI * offset / 2.0) + 7).arg(780); svg += QString("1/16").arg((GraphicsUtils::StandardFritzingDPI * offset / 2.0) + 7).arg(990); svg += ""; svg += ""; return svg; } bool Ruler::hasCustomSVG() { switch (m_viewID) { case ViewLayer::PCBView: case ViewLayer::SchematicView: case ViewLayer::BreadboardView: return true; default: return ItemBase::hasCustomSVG(); } } bool Ruler::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { bool result = PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("width", Qt::CaseInsensitive) == 0) { returnProp = tr("width"); int units = m_modelPart->localProp("width").toString().contains("cm") ? IndexCm : IndexIn; QLineEdit * e1 = new QLineEdit(); QDoubleValidator * validator = new QDoubleValidator(e1); validator->setRange(1.0, 20 * ((units == IndexCm) ? 2.54 : 1), 2); validator->setNotation(QDoubleValidator::StandardNotation); validator->setLocale(QLocale::C); e1->setValidator(validator); e1->setEnabled(swappingEnabled); QString temp = m_modelPart->localProp("width").toString(); temp.chop(2); e1->setText(temp); e1->setObjectName("infoViewLineEdit"); e1->setMaximumWidth(80); m_widthEditor = e1; m_widthValidator = validator; QComboBox * comboBox = new QComboBox(parent); comboBox->setEditable(false); comboBox->setEnabled(swappingEnabled); comboBox->addItem("cm"); comboBox->addItem("in"); comboBox->setCurrentIndex(units); m_unitsEditor = comboBox; comboBox->setObjectName("infoViewComboBox"); comboBox->setMinimumWidth(60); QHBoxLayout * hboxLayout = new QHBoxLayout(); hboxLayout->setAlignment(Qt::AlignLeft); hboxLayout->setContentsMargins(0, 0, 0, 0); hboxLayout->setSpacing(0); hboxLayout->setMargin(0); hboxLayout->addWidget(e1); hboxLayout->addWidget(comboBox); QFrame * frame = new QFrame(); frame->setLayout(hboxLayout); frame->setObjectName("infoViewPartFrame"); connect(e1, SIGNAL(editingFinished()), this, SLOT(widthEntry())); connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(unitsEntry(const QString &))); returnValue = temp + QString::number(units); returnWidget = frame; return true; } return result; } void Ruler::widthEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; QString t = edit->text(); QString w = prop("width"); w.chop(2); if (t.compare(w) == 0) { return; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { int units = (m_unitsEditor->currentText() == "cm") ? IndexCm : IndexIn; DefaultWidth = edit->text() + m_unitsEditor->currentText(); infoGraphicsView->resizeBoard(edit->text().toDouble(), units, false); } } void Ruler::unitsEntry(const QString & units) { double inches = TextUtils::convertToInches(prop("width")); if (units == "in") { modelPart()->setLocalProp("width", QVariant(QString::number(inches) + "in")); m_widthEditor->setText(QString::number(inches)); m_widthValidator->setTop(20); } else { modelPart()->setLocalProp("width", QVariant(QString::number(inches * 2.54) + "cm")); m_widthEditor->setText(QString::number(inches * 2.54)); m_widthValidator->setTop(20 * 2.54); } DefaultWidth = prop("width"); } bool Ruler::stickyEnabled() { return false; } bool Ruler::hasPartLabel() { return false; } ItemBase::PluralType Ruler::isPlural() { return Singular; } void Ruler::addedToScene(bool temporary) { if (this->scene()) { LayerHash viewLayers; QString w = prop("width"); modelPart()->setLocalProp("width", ""); // makes sure resizeMM will do the work double inches = TextUtils::convertToInches(w); if (w.endsWith("cm")) { resizeMM(inches * 2.54, IndexCm, viewLayers); } else { resizeMM(inches, IndexIn, viewLayers); } } return PaletteItem::addedToScene(temporary); } bool Ruler::hasPartNumberProperty() { return false; } bool Ruler::canFindConnectorsUnder() { return false; } ViewLayer::ViewID Ruler::useViewIDForPixmap(ViewLayer::ViewID, bool) { return ViewLayer::IconView; } fritzing-app-0.9.2b/src/items/ruler.h000066400000000000000000000047041250202676700175240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef RULER_H #define RULER_H #include #include #include #include #include #include #include "paletteitem.h" class Ruler : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Ruler(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Ruler(); void resizeMM(double magnitude, double unitsFlag, const LayerHash & viewLayers); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool hasCustomSVG(); bool stickyEnabled(); bool hasPartLabel(); PluralType isPlural(); void addedToScene(bool temporary); bool hasPartNumberProperty(); bool canFindConnectorsUnder(); public slots: void widthEntry(); void unitsEntry(const QString &); protected: QString makeSvg(double inches); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected: QPointer m_widthEditor; QPointer m_unitsEditor; QPointer m_widthValidator; }; #endif fritzing-app-0.9.2b/src/items/schematicframe.cpp000066400000000000000000000402741250202676700217030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ // TODO: // // direct editing (eventually) #include "schematicframe.h" #include "partfactory.h" #include "../utils/graphicsutils.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../svg/svgfilesplitter.h" #include "../debugdialog.h" #include "moduleidnames.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static TemplateThing SchematicTemplate; static TemplateThing OldSchematicTemplate; QHash FrameProps; static const QString DisplayFormat("dd MMM yyyy hh:mm:ss"); SchematicFrame::SchematicFrame( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : ResizableBoard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { if (FrameProps.count() == 0) { FrameProps.insert("descr", ""); FrameProps.insert("project", tr("Project")); FrameProps.insert("filename", tr("Filename")); FrameProps.insert("date", tr("Date")); FrameProps.insert("sheet", tr("Sheet")); FrameProps.insert("rev", tr("Rev")); } foreach (QString prop, FrameProps.keys()) { if (modelPart->localProp(prop).toString().isEmpty()) { modelPart->setLocalProp(prop, modelPart->properties().value(prop)); } } if (modelPart->localProp("date").toString().isEmpty()) { QDateTime dt = QDateTime::currentDateTime(); modelPart->setLocalProp("date", QString::number(dt.toTime_t())); } if (modelPart->localProp("sheet").toString().isEmpty()) { modelPart->setLocalProp("sheet","1/1"); } m_wrapInitialized = false; m_textEdit = new QTextEdit(); m_textEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); m_textEdit->setAcceptRichText(false); m_textEdit->setLineWrapMode(QTextEdit::FixedPixelWidth); } SchematicFrame::~SchematicFrame() { if (m_textEdit) { delete m_textEdit; } } void SchematicFrame::loadTemplates() { if (SchematicTemplate.svgTemplate.isEmpty()) { loadTemplate(":/resources/templates/schematic_frame_template.txt", ":/resources/parts/svg/core/schematic/frame.svg", SchematicTemplate); loadTemplate(":/resources/templates/0.3.schem.schematic_frame_template.txt", ":/resources/parts/svg/obsolete/schematic/0.3.schem.frame.svg", OldSchematicTemplate); } } void SchematicFrame::loadTemplate(const QString & tPath, const QString & fPath, TemplateThing & templateThing) { QFile file2(fPath); file2.open(QFile::ReadOnly); QString original = file2.readAll(); file2.close(); templateThing.size = QSizeF(TextUtils::getViewBoxCoord(original, 2), TextUtils::getViewBoxCoord(original, 3)); QFile file(tPath); file.open(QFile::ReadOnly); templateThing.svgTemplate = file.readAll(); file.close(); /* static QRegExp NumberFinder("(=['\"][\\[\\{]{0,1})(\\d+(\\.\\d){0,1})[\\]\\}]{0,1}['\"]"); SchematicTemplate = OldSchematicTemplate; int pos = 0; while (true) { int ix = NumberFinder.indexIn(SchematicTemplate, pos); if (ix < 0) break; double d = NumberFinder.cap(2).toDouble(); QString d3 = QString("%1").arg(d / 3, 0, 'g', 5); int offset = NumberFinder.cap(0).count(); if (SchematicTemplate.indexOf("version", ix - 7) < 0) { SchematicTemplate.replace(ix + NumberFinder.cap(1).count(), NumberFinder.cap(2).count(), d3); offset += d3.count() - NumberFinder.cap(2).count(); } pos = ix + offset; } DebugDialog::debug("schematic template " + SchematicTemplate); */ QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(templateThing.svgTemplate, true, &errorStr, &errorLine, &errorColumn)) { return; } QDomElement root = domDocument.documentElement(); QDomElement descr =TextUtils::findElementWithAttribute(root, "id", "descr"); QString xString = descr.attribute("x"); xString = xString.mid(1, xString.length() - 2); // remove the brackets; templateThing.margin = xString.toInt() * 2; templateThing.fontSize = descr.attribute("font-size").toDouble(); QDomNodeList nodeList = root.elementsByTagName("rect"); for (int i = 0; i < nodeList.count(); i++) { double sw = nodeList.at(i).toElement().attribute("stroke-width").toDouble(); if (sw != 0) templateThing.strokeWidth = sw; break; } } QString SchematicFrame::makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(mmW); Q_UNUSED(mmH); if (SchematicTemplate.svgTemplate.isEmpty()) return ""; switch (viewLayerID) { case ViewLayer::SchematicFrame: break; default: return ""; } TemplateThing & templateThing = moduleID().contains(PartFactory::OldSchematicPrefix) ? OldSchematicTemplate : SchematicTemplate; if (!m_wrapInitialized) { m_wrapInitialized = true; QFont font = m_textEdit->font(); font.setFamily("Droid Sans"); font.setWeight(QFont::Normal); font.setPointSizeF(72.0 * templateThing.fontSize / GraphicsUtils::StandardFritzingDPI); m_textEdit->setFont(font); m_textEdit->setLineWrapColumnOrWidth(GraphicsUtils::SVGDPI * (templateThing.size.width() - templateThing.margin) / GraphicsUtils::StandardFritzingDPI); } if (milsW < templateThing.size.width()) milsW = templateThing.size.width(); if (milsH < templateThing.size.height()) milsH = templateThing.size.height(); QString svg = templateThing.svgTemplate.arg(milsW / 1000).arg(milsH / 1000).arg(milsW).arg(milsH).arg(milsW - templateThing.strokeWidth).arg(milsH - templateThing.strokeWidth); svg = TextUtils::incrementTemplateString(svg, 1, milsW - templateThing.size.width(), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg.replace("{", "["); svg.replace("}", "]"); svg = TextUtils::incrementTemplateString(svg, 1, milsH - templateThing.size.height(), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); QHash hash; foreach (QString propp, FrameProps.keys()) { hash.insert(propp, prop(propp)); QString label = FrameProps.value(propp); if (!label.isEmpty()) { hash.insert(propp + " label", label); } } // figure out the width and the font QString string = prop("descr"); m_textEdit->setPlainText(string); QTextCursor textCursor = m_textEdit->cursorForPosition(QPoint(0,0)); QTextLayout * textLayout = textCursor.block().layout(); int lc2 = textLayout->lineCount(); if (lc2 > 1) { QTextLine textLine = textLayout->lineAt(0); hash.insert("descr", string.left(textLine.textLength())); textLine = textLayout->lineAt(1); string = string.mid(textLine.textStart(), textLine.textLength()); hash.insert("descr+", string); } QDateTime dt; dt.setTime_t(modelPart()->localProp("date").toUInt()); hash.insert("date", dt.toString(DisplayFormat)); DebugDialog::debug("svg " + svg); return TextUtils::convertExtendedChars(TextUtils::replaceTextElements(svg, hash)); } QString SchematicFrame::makeNextLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH) { Q_UNUSED(mmW); Q_UNUSED(mmH); Q_UNUSED(milsW); Q_UNUSED(milsH); Q_UNUSED(viewLayerID); return ""; } QString SchematicFrame::makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH) { return makeLayerSvg(ViewLayer::SchematicFrame, mmW, mmH, milsW, milsH); } ViewLayer::ViewID SchematicFrame::theViewID() { return ViewLayer::SchematicView; } double SchematicFrame::minWidth() { double w = moduleID().contains(PartFactory::OldSchematicPrefix) ? OldSchematicTemplate.size.width() : SchematicTemplate.size.width(); return w * GraphicsUtils::SVGDPI / GraphicsUtils::StandardFritzingDPI; } double SchematicFrame::minHeight() { double h = moduleID().contains(PartFactory::OldSchematicPrefix) ? OldSchematicTemplate.size.height() : SchematicTemplate.size.height(); return h * GraphicsUtils::SVGDPI / GraphicsUtils::StandardFritzingDPI; } void SchematicFrame::addedToScene(bool temporary) { if (prop("filename").isEmpty()) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { modelPart()->setLocalProp("filename", infoGraphicsView->filenameIf()); } } ResizableBoard::addedToScene(temporary); resizeMMAux(m_modelPart->localProp("width").toDouble(), m_modelPart->localProp("height").toDouble()); } QString SchematicFrame::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { return ResizableBoard::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); } bool SchematicFrame::makeLineEdit(QWidget * parent, const QString & family, const QString & propp, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget) { Q_UNUSED(value); Q_UNUSED(family); returnProp = ItemBase::TranslatedPropertyNames.value(propp.toLower()); returnValue = prop(propp); QLineEdit * e1 = new QLineEdit(parent); e1->setObjectName("infoViewLineEdit"); e1->setProperty("prop", QVariant(propp)); e1->setText(returnValue); e1->setEnabled(swappingEnabled); connect(e1, SIGNAL(editingFinished()), this, SLOT(propEntry())); returnWidget = e1; return true; } bool SchematicFrame::collectExtraInfo(QWidget * parent, const QString & family, const QString & propp, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (propp.compare("shape", Qt::CaseInsensitive) == 0) { returnWidget = setUpDimEntry(false, false, true, returnWidget); returnWidget->setEnabled(swappingEnabled); returnProp = tr("shape"); return true; } if (propp.compare("date", Qt::CaseInsensitive) == 0) { QDateTimeEdit * dateTimeEdit = new QDateTimeEdit(QDateTime::currentDateTime(), parent); QString d = prop("date"); if (!d.isEmpty()) { QDateTime dateTime; dateTime.setTime_t(d.toUInt()); dateTimeEdit->setDateTime(dateTime); } //dateTimeEdit->setCalendarPopup(true); dateTimeEdit->setDisplayFormat(DisplayFormat); connect(dateTimeEdit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(dateTimeEntry(QDateTime))); dateTimeEdit->setObjectName("infoViewDateEdit"); dateTimeEdit->setEnabled(swappingEnabled); returnProp = ItemBase::TranslatedPropertyNames.value(propp.toLower()); returnValue = prop(propp); returnWidget = dateTimeEdit; return true; } if (propp.compare("sheet", Qt::CaseInsensitive) == 0) { QString value = prop("sheet"); QStringList strings = value.split("/"); if (strings.count() != 2) { strings.clear(); strings << "1" << "1"; } QFrame * frame = new QFrame(parent); QSpinBox * spin1 = new QSpinBox(frame); spin1->setMinimum(1); spin1->setMaximum(999); spin1->setValue(strings[0].toInt()); connect(spin1, SIGNAL(valueChanged(int)), this, SLOT(sheetEntry(int))); spin1->setObjectName("infoViewSpinner"); spin1->setProperty("role", "numerator"); spin1->setEnabled(swappingEnabled); QSpinBox * spin2 = new QSpinBox(frame); spin2->setMinimum(1); spin2->setMaximum(999); spin2->setValue(strings[1].toInt()); connect(spin2, SIGNAL(valueChanged(int)), this, SLOT(sheetEntry(int))); spin2->setObjectName("infoViewSpinner"); spin2->setProperty("role", "denominator"); spin2->setEnabled(swappingEnabled); QLabel * label = new QLabel(parent); label->setText(tr("of")); label->setObjectName("infoViewOfLabel"); label->setAlignment(Qt::AlignCenter); QHBoxLayout * hBoxLayout = new QHBoxLayout(frame); hBoxLayout->addWidget(spin1); hBoxLayout->addWidget(label); hBoxLayout->addWidget(spin2); hBoxLayout->addStretch(); frame->setLayout(hBoxLayout); returnProp = ItemBase::TranslatedPropertyNames.value(propp.toLower()); returnValue = prop(propp); returnWidget = frame; return true; } if (FrameProps.keys().contains(propp)) { return makeLineEdit(parent, family, propp, value, swappingEnabled, returnProp, returnValue, returnWidget); } return PaletteItem::collectExtraInfo(parent, family, propp, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void SchematicFrame::setProp(const QString & prop, const QString & value) { ResizableBoard::setProp(prop, value); if (FrameProps.keys().contains(prop)) { modelPart()->setLocalProp(prop, value); resizeMMAux(modelPart()->localProp("width").toDouble(), modelPart()->localProp("height").toDouble()); } } bool SchematicFrame::canEditPart() { return false; } bool SchematicFrame::hasPartLabel() { return false; } bool SchematicFrame::stickyEnabled() { return false; } ItemBase::PluralType SchematicFrame::isPlural() { return Plural; } bool SchematicFrame::rotationAllowed() { return false; } bool SchematicFrame::rotation45Allowed() { return false; } bool SchematicFrame::hasPartNumberProperty() { return false; } void SchematicFrame::setInitialSize() { double w = m_modelPart->localProp("width").toDouble(); if (w == 0) { QSizeF size = moduleID().contains(PartFactory::OldSchematicPrefix) ? OldSchematicTemplate.size : SchematicTemplate.size; // set the size so the infoGraphicsView will display the size as you drag modelPart()->setLocalProp("width", 25.4 * size.width() / GraphicsUtils::StandardFritzingDPI); modelPart()->setLocalProp("height", 25.4 * size.height() / GraphicsUtils::StandardFritzingDPI); } } void SchematicFrame::propEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; QString propp = edit->property("prop").toString(); if (propp.isEmpty()) return; QString current = prop(propp); if (edit->text().compare(current) == 0) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, propp, ItemBase::TranslatedPropertyNames.value(propp), current, edit->text(), true); } } void SchematicFrame::dateTimeEntry(QDateTime dateTime) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "date", tr("date"), prop("date"), QString::number(dateTime.toTime_t()), true); } } void SchematicFrame::sheetEntry(int value) { QString role = sender()->property("role").toString(); QString sheet = prop("sheet"); QStringList strings = sheet.split("/"); if (strings.count() != 2) { strings.clear(); strings << "1" << "1"; } if (role.compare("numerator") == 0) { strings[0] = QString::number(value); } else if (role.compare("denominator") == 0) { strings[1] = QString::number(value); } else return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "sheet", tr("sheet"), prop("sheet"), strings.at(0) + "/" + strings[1], true); } } ViewLayer::ViewID SchematicFrame::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::SchematicView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } fritzing-app-0.9.2b/src/items/schematicframe.h000066400000000000000000000064261250202676700213510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef SCHEMATIC_FRAME_H #define SCHEMATIC_FRAME_H #include #include #include #include #include #include #include #include "resizableboard.h" struct TemplateThing { QString svgTemplate; QSizeF size; double margin; double fontSize; double strokeWidth; }; class SchematicFrame : public ResizableBoard { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call SchematicFrame(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~SchematicFrame(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool canEditPart(); void setProp(const QString & prop, const QString & value); bool hasPartLabel(); bool stickyEnabled(); PluralType isPlural(); void addedToScene(bool temporary); bool rotationAllowed(); bool rotation45Allowed(); bool hasPartNumberProperty(); void setInitialSize(); protected slots: void propEntry(); void dateTimeEntry(QDateTime); void sheetEntry(int); protected: double minWidth(); double minHeight(); ViewLayer::ViewID theViewID(); QString makeLayerSvg(ViewLayer::ViewLayerID viewLayerID, double mmW, double mmH, double milsW, double milsH); QString makeFirstLayerSvg(double mmW, double mmH, double milsW, double milsH); QString makeNextLayerSvg(ViewLayer::ViewLayerID, double mmW, double mmH, double milsW, double milsH); bool makeLineEdit(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); void loadTemplates(); protected: static void loadTemplate(const QString & tPath, const QString & fPath, TemplateThing &); protected: QTextEdit * m_textEdit; bool m_wrapInitialized; protected: }; #endif fritzing-app-0.9.2b/src/items/schematicsubpart.cpp000066400000000000000000000046321250202676700222670ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09 Mrz 2013) $ ********************************************************************/ #include "schematicsubpart.h" SchematicSubpart::SchematicSubpart( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { } SchematicSubpart::~SchematicSubpart() { } void SchematicSubpart::hoverEnterEvent (QGraphicsSceneHoverEvent * event) { PaletteItem::hoverEnterEvent(event); if (m_superpart) { foreach (ItemBase * itemBase, m_superpart->subparts()) { if (itemBase != this) { SchematicSubpart * subpart = qobject_cast(itemBase); if (subpart) subpart->simpleHoverEnterEvent(event); } } } } void SchematicSubpart::hoverLeaveEvent (QGraphicsSceneHoverEvent * event) { PaletteItem::hoverLeaveEvent(event); if (m_superpart) { foreach (ItemBase * itemBase, m_superpart->subparts()) { if (itemBase != this) { SchematicSubpart * subpart = qobject_cast(itemBase); if (subpart) subpart->simpleHoverLeaveEvent(event); } } } } void SchematicSubpart::simpleHoverEnterEvent (QGraphicsSceneHoverEvent * event) { PaletteItem::hoverEnterEvent(event); } void SchematicSubpart::simpleHoverLeaveEvent (QGraphicsSceneHoverEvent * event) { PaletteItem::hoverLeaveEvent(event); } fritzing-app-0.9.2b/src/items/schematicsubpart.h000066400000000000000000000033151250202676700217310ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09 Mrz 2013) $ ********************************************************************/ #ifndef SCHEMATICSUBPART_H #define SCHEMATICSUBPART_H #include "paletteitem.h" class SchematicSubpart : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call SchematicSubpart(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~SchematicSubpart(); void hoverEnterEvent(QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ); protected: void simpleHoverEnterEvent(QGraphicsSceneHoverEvent * event ); void simpleHoverLeaveEvent( QGraphicsSceneHoverEvent * event ); }; #endif fritzing-app-0.9.2b/src/items/screwterminal.cpp000066400000000000000000000276621250202676700216150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "screwterminal.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "../commands.h" #include "../utils/textutils.h" #include "../utils/schematicrectconstants.h" #include "partlabel.h" #include "partfactory.h" #include #include #include #include static const int MinPins = 2; static const int MaxPins = 20; static QHash Spacings; static HoleClassThing TheHoleThing; ScrewTerminal::ScrewTerminal( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { setUpHoleSizes("screwterminal", TheHoleThing); } ScrewTerminal::~ScrewTerminal() { } QStringList ScrewTerminal::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("pins", Qt::CaseInsensitive) == 0) { QStringList values; value = modelPart()->properties().value("pins"); for (int i = MinPins; i <= MaxPins; i++) { values << QString::number(i); } return values; } if (prop.compare("pin spacing", Qt::CaseInsensitive) == 0) { QStringList values; value = modelPart()->properties().value("pin spacing"); initSpacings(); return Spacings.values(); } return PaletteItem::collectValues(family, prop, value); } ItemBase::PluralType ScrewTerminal::isPlural() { return Plural; } QString ScrewTerminal::genFZP(const QString & moduleid) { initSpacings(); QString useModuleID = moduleid; int hsix = useModuleID.lastIndexOf(HoleSizePrefix); if (hsix >= 0) useModuleID.truncate(hsix); QStringList pieces = useModuleID.split("_"); QString result = PaletteItem::genFZP(useModuleID, "screw_terminal_fzpTemplate", MinPins, MaxPins, 1, false); result.replace(".percent.", "%"); QString spacing = pieces.at(3); result = result.arg(spacing).arg(Spacings.value(spacing, "")); if (hsix >= 0) { return hackFzpHoleSize(result, moduleid, hsix); } return result; } QString ScrewTerminal::genModuleID(QMap & currPropsMap) { initSpacings(); QString spacing = currPropsMap.value("pin spacing"); QString pins = currPropsMap.value("pins"); foreach (QString key, Spacings.keys()) { if (Spacings.value(key).compare(spacing, Qt::CaseInsensitive) == 0) { return QString("screw_terminal_%1_%2").arg(pins).arg(key); } } return ""; } void ScrewTerminal::initSpacings() { if (Spacings.count() == 0) { Spacings.insert("3.5mm", "0.137in (3.5mm)"); Spacings.insert("5.0mm", "0.197in (5.0mm)"); Spacings.insert("100mil", "0.1in (2.54mm)"); Spacings.insert("200mil", "0.2in (5.08mm)"); Spacings.insert("300mil", "0.3in (7.62mm)"); } } QString ScrewTerminal::makeBreadboardSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(2).toInt(); double increment = 0.1; // inches double incrementPoints = 100; QString header("\n" "\n" "\n" "\n" "\n" "\n"); QString svg = TextUtils::incrementTemplateString(header.arg(increment * pins), 1, incrementPoints * (pins - 1), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg += TextUtils::incrementTemplate(":/resources/templates/screw_terminal_bread_template.txt", pins, incrementPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); svg += "\n"; return svg; } QString ScrewTerminal::makeSchematicSvg(const QString & expectedFileName) { if (expectedFileName.contains(PartFactory::OldSchematicPrefix)) { return obsoleteMakeSchematicSvg(expectedFileName); } QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(2).toInt(); double increment = SchematicRectConstants::NewUnit / 25.4; double incrementPoints = 72 * increment; // 72 dpi double pinWidthPoints = 72 * SchematicRectConstants::PinWidth / 25.4; double pinLength = 2 * increment; double pinLengthPoints = 2 * incrementPoints; QString header("\n" "\n" "\n"); header = header.arg(increment + pinLength).arg(incrementPoints + pinLengthPoints); header.replace("percent", "%"); QString repeat("\n" "\n" "\n" ); repeat = repeat .arg(SchematicRectConstants::PinColor) .arg(pinWidthPoints) .arg(pinWidthPoints / 2) .arg(pinLengthPoints - pinWidthPoints) .arg(incrementPoints / 2) .arg((incrementPoints - pinWidthPoints) / 2) .arg(pinLengthPoints + (incrementPoints / 2) - pinWidthPoints) .arg((incrementPoints / 2) - pinWidthPoints) ; repeat.replace("percent", "%"); QString svg = TextUtils::incrementTemplateString(header.arg(increment * pins).arg(incrementPoints), 1, incrementPoints * (pins - 1), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg += TextUtils::incrementTemplateString(repeat, pins, incrementPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); svg += "\n"; return svg; } QString ScrewTerminal::obsoleteMakeSchematicSvg(const QString & expectedFileName) { QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(2).toInt(); double increment = GraphicsUtils::StandardSchematicSeparationMils / 1000; double incrementPoints = increment * 72; // 72 dpi QString header("\n" "\n" "\n"); QString repeat("\n" "\n" "\n" "\n"); QString svg = TextUtils::incrementTemplateString(header.arg(increment * pins).arg(incrementPoints), 1, incrementPoints * (pins - 1), TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); svg += TextUtils::incrementTemplateString(repeat, pins, incrementPoints, TextUtils::standardMultiplyPinFunction, TextUtils::standardCopyPinFunction, NULL); svg += "\n"; return svg; } QString ScrewTerminal::makePcbSvg(const QString & originalExpectedFileName) { QString expectedFileName = originalExpectedFileName; int hsix = expectedFileName.indexOf(HoleSizePrefix); if (hsix >= 0) { expectedFileName.truncate(hsix); } QStringList pieces = expectedFileName.split("_"); int pins = pieces.at(2).toInt(); bool ok; double spacing = TextUtils::convertToInches(pieces.at(3), &ok, false); if (!ok) return ""; double dpi = 1000; double width = spacing < 0.15 ? 0.256 : 0.48; double verticalX = spacing < 0.15 ? 0.196 : 0.38; double centerX = (verticalX * dpi / 2) + 10; double initialY = (spacing * dpi / 2) + 25; QString header("\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"); QString repeat("\n"); header = header.arg(width) .arg(width * dpi) .arg(pins * spacing + 0.04) .arg((width - 0.02) * dpi) .arg(verticalX * dpi) .arg(centerX - 30) .arg(initialY - 30); QString svg = TextUtils::incrementTemplateString(header, 1, pins * dpi * spacing, TextUtils::incMultiplyPinFunction, TextUtils::noCopyPinFunction, NULL); for (int i = 0; i < pins; i++) { svg += repeat.arg(centerX).arg(initialY + (i * dpi * spacing)).arg(i); } svg += "\n\n\n"; if (hsix >= 0) { return hackSvgHoleSizeAux(svg, originalExpectedFileName); } return svg; } bool ScrewTerminal::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("hole size", Qt::CaseInsensitive) == 0) { return collectHoleSizeInfo(TheHoleThing.holeSizeValue, parent, swappingEnabled, returnProp, returnValue, returnWidget); } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void ScrewTerminal::swapEntry(const QString & text) { generateSwap(text, genModuleID, genFZP, makeBreadboardSvg, makeSchematicSvg, makePcbSvg); PaletteItem::swapEntry(text); } fritzing-app-0.9.2b/src/items/screwterminal.h000066400000000000000000000043651250202676700212550ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef SCREWTERMINAL_H #define SCREWTERMINAL_H #include "paletteitem.h" class ScrewTerminal : public PaletteItem { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call ScrewTerminal(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~ScrewTerminal(); PluralType isPlural(); QStringList collectValues(const QString & family, const QString & prop, QString & value); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); public slots: void swapEntry(const QString & text); public: static QString genFZP(const QString & moduleid); static QString genModuleID(QMap & currPropsMap); static QString makeBreadboardSvg(const QString & expectedFileName); static QString makeSchematicSvg(const QString & expectedFileName); static QString obsoleteMakeSchematicSvg(const QString & expectedFileName); static QString makePcbSvg(const QString & expectedFileName); protected: static void initSpacings(); }; #endif fritzing-app-0.9.2b/src/items/stripboard.cpp000066400000000000000000000612721250202676700211020ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "stripboard.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/familypropertycombobox.h" #include "../svg/gerbergenerator.h" #include "../fsvgrenderer.h" #include "../sketch/infographicsview.h" #include "moduleidnames.h" #include "../connectors/connectoritem.h" #include "../connectors/busshared.h" #include "../connectors/connectorshared.h" #include "../debugdialog.h" #include #include ////////////////////////////////////////////////// // TODO: // // new cursors, new hover states? // disconnect and reconnect affected parts // swapping static QCursor * SpotFaceCutterCursor = NULL; static QCursor * MagicWandCursor = NULL; static bool ShiftDown = false; static QPointF OriginalShiftPos; static bool ShiftX = false; static bool ShiftY = false; static bool SpaceBarWasPressed = false; static const double MinMouseMove = 2; static QPainterPath HPath; static QPainterPath VPath; static QString HorizontalString("horizontal strips"); static QString VerticalString("vertical strips"); ///////////////////////////////////////////////////////////////////// Stripbit::Stripbit(const QPainterPath & path, int x, int y, bool horizontal, QGraphicsItem * parent = 0) : QGraphicsPathItem(path, parent) { if (SpotFaceCutterCursor == NULL) { QBitmap bitmap(":resources/images/cursor/spot_face_cutter.bmp"); QBitmap bitmapm(":resources/images/cursor/spot_face_cutter_mask.bmp"); SpotFaceCutterCursor = new QCursor(bitmap, bitmapm, 0, 0); } if (MagicWandCursor == NULL) { QBitmap bitmap(":resources/images/cursor/magic_wand.bmp"); QBitmap bitmapm(":resources/images/cursor/magic_wand_mask.bmp"); MagicWandCursor = new QCursor(bitmap, bitmapm, 0, 0); } setZValue(-999); // beneath connectorItems setPen(Qt::NoPen); // TODO: don't hardcode this color setBrush(QColor(0xbc, 0x94, 0x51)); // QColor(0xc4, 0x9c, 0x59) m_horizontal = horizontal; m_x = x; m_y = y; m_inHover = m_removed = false; setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::LeftButton); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, false); } Stripbit::~Stripbit() { } void Stripbit::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { double newOpacity = 1; if (m_removed) { if (m_inHover) newOpacity = 0.50; else newOpacity = 0.00; } else { if (m_inHover) newOpacity = 0.40; else newOpacity = 1.00; } double opacity = painter->opacity(); painter->setOpacity(newOpacity); QGraphicsPathItem::paint(painter, option, widget); painter->setOpacity(opacity); } void Stripbit::mousePressEvent(QGraphicsSceneMouseEvent *event) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { event->ignore(); return; } if (!event->buttons() && Qt::LeftButton) { event->ignore(); return; } if (dynamic_cast(this->parentItem())->moveLock()) { event->ignore(); return; } if (event->modifiers() & Qt::ShiftModifier) { ShiftDown = true; ShiftX = ShiftY = false; OriginalShiftPos = event->scenePos(); } event->accept(); dynamic_cast(this->parentItem())->initCutting(this); m_removed = !m_removed; m_inHover = false; m_changed = true; update(); //DebugDialog::debug("got press"); } void Stripbit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); dynamic_cast(this->parentItem())->reinitBuses(true); } void Stripbit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (!event->buttons() && Qt::LeftButton) return; if (ShiftDown && !(event->modifiers() & Qt::ShiftModifier)) { ShiftDown = false; } //DebugDialog::debug("got move"); Stripbit * other = NULL; QPointF p = event->scenePos(); if (ShiftDown) { if (ShiftX) { // moving along x, constrain y p.setY(OriginalShiftPos.y()); } else if (ShiftY) { // moving along y, constrain x p.setX(OriginalShiftPos.x()); } else { double dx = qAbs(p.x() - OriginalShiftPos.x()); double dy = qAbs(p.y() - OriginalShiftPos.y()); if (dx - dy > MinMouseMove) { ShiftX = true; } else if (dy - dx > MinMouseMove) { ShiftY = true; } } } if (!ShiftDown && (event->modifiers() & Qt::ShiftModifier)) { ShiftDown = true; ShiftX = ShiftY = false; OriginalShiftPos = event->scenePos(); } foreach (QGraphicsItem * item, scene()->items(p)) { other = dynamic_cast(item); if (other) break; } if (!other) return; //DebugDialog::debug("got other"); if (other->removed() == m_removed) return; //DebugDialog::debug("change other"); other->setRemoved(m_removed); other->setChanged(true); other->update(); dynamic_cast(this->parentItem())->restoreRowColors(other); } void Stripbit::hoverEnterEvent( QGraphicsSceneHoverEvent * event ) { if (dynamic_cast(this->parentItem())->moveLock()) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { SpaceBarWasPressed = true; return; } SpaceBarWasPressed = false; setCursor(m_removed ? *MagicWandCursor : *SpotFaceCutterCursor); Q_UNUSED(event); m_inHover = true; update(); } void Stripbit::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { if (dynamic_cast(this->parentItem())->moveLock()) return; if (SpaceBarWasPressed) return; unsetCursor(); Q_UNUSED(event); m_inHover = false; update(); } bool Stripbit::horizontal() { return m_horizontal; } void Stripbit::setRemoved(bool removed) { m_removed = removed; } bool Stripbit::removed() { return m_removed; } void Stripbit::setChanged(bool changed) { m_changed = changed; } bool Stripbit::changed() { return m_changed; } int Stripbit::y() { return m_y; } int Stripbit::x() { return m_x; } QString Stripbit::makeRemovedString() { return QString("%1.%2%3 ").arg(m_x).arg(m_y).arg(m_horizontal ? 'h' : 'v'); } ///////////////////////////////////////////////////////////////////// StripConnector::StripConnector() { down = right = NULL; connectorItem = NULL; } struct StripLayout { QString name; int rows; int columns; QString buses; StripLayout(QString name, int rows, int columns, QString buses); }; StripLayout::StripLayout(QString name_, int rows_, int columns_, QString buses_) { name = name_; rows = rows_; columns = columns_; buses = buses_; } static QList StripLayouts; ///////////////////////////////////////////////////////////////////// Stripboard::Stripboard( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Perfboard(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { getXY(m_x, m_y, m_size); if (StripLayouts.count() == 0) { initStripLayouts(); } m_layout = modelPart->localProp("layout").toString(); if (m_layout.isEmpty()) { m_layout = modelPart->properties().value("m_layout"); if (!m_layout.isEmpty()) { modelPart->setLocalProp("layout", m_layout); } } } Stripboard::~Stripboard() { foreach (StripConnector * sc, m_strips) { delete sc; } m_strips.clear(); } QString Stripboard::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString svg = Perfboard::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); if (svg.isEmpty()) return svg; if (!svg.contains(GerberGenerator::MagicBoardOutlineID)) return svg; /* QFile file(filename()); if (!file.open(QFile::ReadOnly | QFile::Text)) { return svg; } QString originalSvg = file.readAll(); file.close(); QString stripSvg = originalSvg.left(svg.indexOf(">") + 1); */ QString stripSvg; foreach(QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; if (stripbit->removed()) continue; QPointF p = stripbit->pos(); QRectF r = stripbit->boundingRect(); stripSvg += QString("\n") .arg(p.x() * dpi / GraphicsUtils::SVGDPI) .arg(p.y() * dpi / GraphicsUtils::SVGDPI) .arg(r.width() * dpi / GraphicsUtils::SVGDPI ) .arg(r.height() * dpi / GraphicsUtils::SVGDPI) .arg(r.height() * dpi * .5 / GraphicsUtils::SVGDPI) .arg(blackOnly ? "black" : "#c49c59") ; } svg.truncate(svg.lastIndexOf("")); return svg + stripSvg + "\n"; } QString Stripboard::genFZP(const QString & moduleid) { QString fzp = Perfboard::genFZP(moduleid); fzp.replace(ModuleIDNames::PerfboardModuleIDName, ModuleIDNames::Stripboard2ModuleIDName); fzp.replace("Perfboard", "Stripboard"); fzp.replace("perfboard", "stripboard"); fzp.replace("stripboard.svg", "perfboard.svg"); // replaced just above; restore it QString findString(""); int ix = fzp.indexOf(findString); if (ix > 0) { fzp.insert(ix + findString.count(), ""); if (moduleid.endsWith(ModuleIDNames::StripboardModuleIDName)) { fzp.insert(ix + findString.count(), "yes"); } } return fzp; } bool Stripboard::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { return Perfboard::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void Stripboard::addedToScene(bool temporary) { Perfboard::addedToScene(temporary); if (this->scene() == NULL) return; if (temporary) return; if (m_viewID != ViewLayer::BreadboardView) return; QList items = childItems(); if (HPath.isEmpty()) { makeInitialPath(); } int count = m_x * m_y; for (int i = 0; i < count; i++) { m_strips.append(new StripConnector); } bool oldStyle = false; if (moduleID().endsWith(ModuleIDNames::StripboardModuleIDName) || !modelPart()->properties().value("oldstyle", "").isEmpty()) { modelPart()->modelPartShared()->setModuleID(QString("%1.%2%3").arg(m_x).arg(m_y).arg(ModuleIDNames::Stripboard2ModuleIDName)); oldStyle = true; m_layout = HorizontalString; } QString config = prop("buses"); QString additionalConfig; foreach (ConnectorItem * ci, cachedConnectorItems()) { int cx, cy; getXY(cx, cy, ci->connectorSharedName()); StripConnector * sc = getStripConnector(cx, cy); sc->connectorItem = ci; if (cx < m_x - 1) { Stripbit * stripbit = new Stripbit(HPath, cx, cy, true, this); QRectF r = ci->rect(); stripbit->setPos(r.center().x(), r.top()); stripbit->setVisible(true); sc->right = stripbit; if (!oldStyle) { additionalConfig += stripbit->makeRemovedString(); } } if (cy < m_y - 1) { Stripbit * stripbit = new Stripbit(VPath, cx, cy, false, this); QRectF r = ci->rect(); stripbit->setPos(r.left(), r.center().y()); stripbit->setVisible(true); sc->down = stripbit; if (oldStyle) { additionalConfig += stripbit->makeRemovedString(); } } } if (config.isEmpty() || oldStyle) { config += additionalConfig; setProp("buses", config); } if (m_layout.isEmpty()) m_layout = VerticalString; QStringList removed = config.split(" ", QString::SkipEmptyParts); foreach (QString name, removed) { int cx, cy; if (getXY(cx, cy, name)) { StripConnector * sc = getStripConnector(cx, cy); bool vertical = name.contains("v"); if (vertical) { if (sc->down != NULL) sc->down->setRemoved(true); } else { if (sc->right != NULL) sc->right->setRemoved(true); } } } reinitBuses(false); } QString Stripboard::genModuleID(QMap & currPropsMap) { QString size = currPropsMap.value("size"); return size + ModuleIDNames::Stripboard2ModuleIDName; } void Stripboard::initCutting(Stripbit *) { m_beforeCut.clear(); foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; stripbit->setChanged(false); if (stripbit->removed()) { m_beforeCut += stripbit->makeRemovedString(); } } } void appendConnectors(QList & connectorItems, ConnectorItem * connectorItem) { if (connectorItem == NULL) return; foreach (ConnectorItem * ci, connectorItem->connectedToItems()) { connectorItems.append(ci); } } void Stripboard::reinitBuses(bool triggerUndo) { if (triggerUndo) { QString afterCut; QSet affectedConnectors; int changeCount = 0; bool connect = true; foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; if (stripbit->removed()) { afterCut += stripbit->makeRemovedString(); } } collectTo(affectedConnectors); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { QString changeType = (connect) ? tr("Restored") : tr("Cut") ; QString changeText = tr("%1 %n strip(s)", "", changeCount).arg(changeType); QList affected = affectedConnectors.toList(); infoGraphicsView->changeBus(this, connect, m_beforeCut, afterCut, affected, changeText, m_layout, m_layout); // affectedConnectors is used for updating ratsnests; it's just a wild guess } return; } if (viewID() != ViewLayer::BreadboardView) return; foreach (BusShared * busShared, m_buses) delete busShared; m_buses.clear(); foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; connectorItem->connector()->connectorShared()->setBus(NULL); connectorItem->connector()->setBus(NULL); continue; } } QString busPropertyString; foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; if (stripbit->removed()) { busPropertyString += stripbit->makeRemovedString(); } } QList visited; for (int iy = 0; iy < m_y; iy++) { for (int ix = 0; ix < m_x; ix++) { StripConnector * sc = getStripConnector(ix, iy); if (visited.contains(sc->connectorItem)) continue; QList connected; collectConnected(ix, iy, connected); visited.append(connected); nextBus(connected); } } modelPart()->clearBuses(); modelPart()->initBuses(); modelPart()->setLocalProp("buses", busPropertyString); QList visited2; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { connectorItem->restoreColor(visited2); } update(); } void Stripboard::collectConnected(int ix, int iy, QList & connected) { StripConnector * sc = getStripConnector(ix, iy); if (connected.contains(sc->connectorItem)) return; connected << sc->connectorItem; if (sc->right != NULL && !sc->right->removed()) { collectConnected(ix + 1, iy, connected); } if (sc->down != NULL && !sc->down->removed()) { collectConnected(ix, iy + 1, connected); } StripConnector * left = ix > 0 ? getStripConnector(ix - 1, iy) : NULL; if (left != NULL && left->right != NULL && !left->right->removed()) { collectConnected(ix - 1, iy, connected); } StripConnector * up = iy > 0 ? getStripConnector(ix, iy - 1) : NULL; if (up != NULL && up->down != NULL && !up->down->removed()) { collectConnected(ix, iy - 1, connected); } } void Stripboard::nextBus(QList & soFar) { if (soFar.count() > 1) { BusShared * busShared = new BusShared(QString::number(m_buses.count())); m_buses.append(busShared); foreach (ConnectorItem * connectorItem, soFar) { busShared->addConnectorShared(connectorItem->connector()->connectorShared()); } } soFar.clear(); } void Stripboard::setProp(const QString & prop, const QString & value) { if (prop.compare("buses") == 0) { QStringList removed = value.split(" ", QString::SkipEmptyParts); foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; QString removedString = stripbit->makeRemovedString(); removedString.chop(1); // remove trailing space bool remove = removed.contains(removedString); stripbit->setRemoved(remove); if (remove) { removed.removeOne(removedString); } } reinitBuses(false); return; } if (prop.compare("layout") == 0) { m_layout = value; } Perfboard::setProp(prop, value); } void Stripboard::getConnectedColor(ConnectorItem * ci, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { Perfboard::getConnectedColor(ci, brush, pen, opacity, negativePenWidth, negativeOffsetRect); opacity *= .66667; } void Stripboard::restoreRowColors(Stripbit * stripbit) { // TODO: find a quick way to update the buses (and connectorItem colors) in just the row... Q_UNUSED(stripbit); //int y = stripbit->y(); //stripbit = m_firstColumn.at(y); //ci->restoreColor(false, 0, false); } QString Stripboard::getRowLabel() { return tr("rows"); } QString Stripboard::getColumnLabel() { return tr("columns"); } void Stripboard::makeInitialPath() { ConnectorItem * ciFirst = NULL; ConnectorItem * ciNextH = NULL; ConnectorItem * ciNextV = NULL; foreach (ConnectorItem * ci, cachedConnectorItems()) { int cx, cy; getXY(cx, cy, ci->connectorSharedName()); if (cy == 0 && cx == 0) { ciFirst = ci; break; } } foreach (ConnectorItem * ci, cachedConnectorItems()) { int cx, cy; getXY(cx, cy, ci->connectorSharedName()); if (cy == 0 && cx == 1) { ciNextH = ci; if (ciNextV) break; } else if (cy == 1 && cx == 0) { ciNextV = ci; if (ciNextH) break; } } if (ciFirst == NULL) return; if (ciNextH == NULL) return; if (ciNextV == NULL) return; QRectF r1 = ciFirst->rect(); QRectF rh = ciNextH->rect(); double h = r1.height(); double w = rh.center().x() - r1.center().x(); r1.moveTo(-(r1.width() / 2), 0); rh.moveTo(w - (rh.width() / 2), 0); HPath.addRect(0, 0, w / 2, h); HPath.arcTo(r1, 90, -180); HPath.addRect(w / 2, 0, w / 2, h); HPath.moveTo(w, 0); HPath.arcTo(rh, 90, 180); r1 = ciFirst->rect(); QRectF rv = ciNextV->rect(); h = rv.center().y() - r1.center().y(); w = r1.width(); r1.moveTo(0, -(r1.height() / 2)); rv.moveTo(0, h - (rv.height() / 2)); VPath.addRect(0, 0, w, h / 2); VPath.arcTo(r1, 0, -180); VPath.addRect(0, h / 2, w, h / 2); VPath.moveTo(0, h); VPath.arcTo(rv, 0, 180); } StripConnector * Stripboard::getStripConnector(int ix, int iy) { return m_strips.at((iy * m_x) + ix); } void Stripboard::swapEntry(const QString & text) { FamilyPropertyComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; if (comboBox->prop().compare("layout", Qt::CaseInsensitive) == 0) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; QString afterCut; if (text.compare(HorizontalString, Qt::CaseInsensitive) == 0) { foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; if (!stripbit->horizontal()) { afterCut += stripbit->makeRemovedString(); } } } else if (text.compare(VerticalString, Qt::CaseInsensitive) == 0) { foreach (QGraphicsItem * item, childItems()) { Stripbit * stripbit = dynamic_cast(item); if (stripbit == NULL) continue; if (stripbit->horizontal()) { afterCut += stripbit->makeRemovedString(); } } } else { for (int i = 0; i < StripLayouts.count(); i++) { if (StripLayouts.at(i).name.compare(text) == 0) { StripLayout stripLayout = StripLayouts.at(i); QMap propsMap; propsMap.insert("size", QString("%1.%2").arg(stripLayout.columns).arg(stripLayout.rows)); propsMap.insert("type", "Stripboard"); propsMap.insert("buses", stripLayout.buses); propsMap.insert("layout", text); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->swap(family(), "size", propsMap, this); } return; } } } if (!afterCut.isEmpty()) { initCutting(NULL); QString changeText = tr("%1 layout").arg(text); QSet affectedConnectors; collectTo(affectedConnectors); QList affected = affectedConnectors.toList(); infoGraphicsView->changeBus(this, true, m_beforeCut, afterCut, affected, changeText, m_layout, text); // affectedConnectors is used for updating ratsnests; it's just a wild guess } return; } Perfboard::swapEntry(text); } void Stripboard::collectTo(QSet & affectedConnectors) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { affectedConnectors.insert(toConnectorItem); } } } void Stripboard::initStripLayouts() { QFile file(":/resources/templates/stripboards.xml"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse stripboards.xml: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement root = domDocument.documentElement(); QDomElement stripboard = root.firstChildElement("stripboard"); while (!stripboard.isNull()) { QString name = stripboard.attribute("name"); bool rok; int rows = stripboard.attribute("rows").toInt(&rok); bool cok; int columns = stripboard.attribute("columns").toInt(&cok); QString buses = stripboard.attribute("buses"); stripboard = stripboard.nextSiblingElement("stripboard"); if (!rok) continue; if (!cok) continue; if (name.isEmpty() || buses.isEmpty()) continue; StripLayout stripLayout(name, rows, columns, buses); StripLayouts.append(stripLayout); } } QStringList Stripboard::collectValues(const QString & family, const QString & prop, QString & value) { QStringList values = Perfboard::collectValues(family, prop, value); if (prop.compare("layout", Qt::CaseInsensitive) == 0) { foreach (StripLayout stripLayout, StripLayouts) { values.append(stripLayout.name); value = m_layout; } } return values; } fritzing-app-0.9.2b/src/items/stripboard.h000066400000000000000000000075141250202676700205460ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef STRIPBOARD_H #define STRIPBOARD_H #include #include #include #include "perfboard.h" class ConnectorItem; class Stripbit : public QGraphicsPathItem { public: Stripbit(const QPainterPath & path, int x, int y, bool horizontal, QGraphicsItem * parent); ~Stripbit(); bool horizontal(); void setRemoved(bool); bool removed(); void setChanged(bool); bool changed(); int y(); int x(); QString makeRemovedString(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void hoverEnterEvent( QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ); protected: bool m_removed; bool m_inHover; int m_x; int m_y; bool m_changed; bool m_horizontal; }; struct StripConnector { ConnectorItem * connectorItem; Stripbit * down; Stripbit * right; StripConnector(); }; class Stripboard : public Perfboard { Q_OBJECT public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call Stripboard(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Stripboard(); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void addedToScene(bool temporary); void setProp(const QString & prop, const QString & value); void reinitBuses(bool triggerUndo); void initCutting(Stripbit *); void getConnectedColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); void restoreRowColors(Stripbit * stripbit); void swapEntry(const QString & text); QStringList collectValues(const QString & family, const QString & prop, QString & value); protected: void nextBus(QList & soFar); QString getRowLabel(); QString getColumnLabel(); void makeInitialPath(); void collectConnected(int x, int y, QList & connected); StripConnector * getStripConnector(int x, int y); void collectTo(QSet &); void initStripLayouts(); public: static QString genFZP(const QString & moduleID); static QString genModuleID(QMap & currPropsMap); protected: QList m_strips; QList m_buses; QString m_beforeCut; int m_x; int m_y; QString m_layout; }; #endif fritzing-app-0.9.2b/src/items/symbolpaletteitem.cpp000066400000000000000000000516141250202676700224730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "symbolpaletteitem.h" #include "../debugdialog.h" #include "../connectors/connectoritem.h" #include "../connectors/bus.h" #include "moduleidnames.h" #include "../fsvgrenderer.h" #include "../utils/textutils.h" #include "../utils/focusoutcombobox.h" #include "../utils/graphicsutils.h" #include "../sketch/infographicsview.h" #include "partlabel.h" #include "partfactory.h" #include "layerkinpaletteitem.h" #include "../svg/svgfilesplitter.h" #include #include #include #define VOLTAGE_HASH_CONVERSION 1000000 #define FROMVOLTAGE(v) ((long) (v * VOLTAGE_HASH_CONVERSION)) static QMultiHash > LocalVoltages; // Qt doesn't do Hash keys with double static QMultiHash > LocalNetLabels; static QList< QPointer > LocalGrounds; static QList Voltages; double SymbolPaletteItem::DefaultVoltage = 5; ///////////////////////////////////////////////////// /* FocusBugLineEdit::FocusBugLineEdit(QWidget * parent) : QLineEdit(parent) { connect(this, SIGNAL(editingFinished()), this, SLOT(editingFinishedSlot())); m_lastEditingFinishedEmit = QTime::currentTime(); } FocusBugLineEdit::~FocusBugLineEdit() { } void FocusBugLineEdit::editingFinishedSlot() { QTime now = QTime::currentTime(); int d = m_lastEditingFinishedEmit.msecsTo(now); DebugDialog::debug(QString("dtime %1").arg(d)); if (d < 1000) { return; } m_lastEditingFinishedEmit = now; emit safeEditingFinished(); } */ //////////////////////////////////////// SymbolPaletteItem::SymbolPaletteItem( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : PaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { if (Voltages.count() == 0) { Voltages.append(0.0); Voltages.append(3.3); Voltages.append(5.0); Voltages.append(12.0); } m_connector0 = m_connector1 = NULL; m_voltage = 0; m_voltageReference = (modelPart->properties().value("type").compare("voltage reference") == 0); if (modelPart->moduleID().endsWith(ModuleIDNames::NetLabelModuleIDName)) { m_isNetLabel = true; } else { m_isNetLabel = modelPart->moduleID().endsWith(ModuleIDNames::PowerLabelModuleIDName); bool ok; double temp = modelPart->localProp("voltage").toDouble(&ok); if (ok) { m_voltage = temp; } else { temp = modelPart->properties().value("voltage").toDouble(&ok); if (ok) { m_voltage = SymbolPaletteItem::DefaultVoltage; } modelPart->setLocalProp("voltage", m_voltage); } if (!Voltages.contains(m_voltage)) { Voltages.append(m_voltage); } } } SymbolPaletteItem::~SymbolPaletteItem() { if (m_isNetLabel) { foreach (QString key, LocalNetLabels.uniqueKeys()) { if (m_connector0) { LocalNetLabels.remove(key, m_connector0); } if (m_connector1) { LocalNetLabels.remove(key, m_connector1); } LocalNetLabels.remove(key, NULL); // cleans null QPointers } } else { if (m_connector0) LocalGrounds.removeOne(m_connector0); if (m_connector1) LocalGrounds.removeOne(m_connector1); LocalGrounds.removeOne(NULL); // cleans null QPointers foreach (long key, LocalVoltages.uniqueKeys()) { if (m_connector0) { LocalVoltages.remove(key, m_connector0); } if (m_connector1) { LocalVoltages.remove(key, m_connector1); } LocalVoltages.remove(key, NULL); // cleans null QPointers } } } void SymbolPaletteItem::removeMeFromBus(double v) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (m_isNetLabel) { LocalNetLabels.remove(getLabel(), connectorItem); } else { double nv = useVoltage(connectorItem); if (nv == v) { //connectorItem->debugInfo(QString("remove %1").arg(useVoltage(connectorItem))); bool gotOne = LocalGrounds.removeOne(connectorItem); int count = LocalVoltages.remove(FROMVOLTAGE(v), connectorItem); LocalVoltages.remove(FROMVOLTAGE(v), NULL); if (count == 0 && !gotOne) { DebugDialog::debug(QString("removeMeFromBus failed %1 %2 %3 %4") .arg(this->id()) .arg(connectorItem->connectorSharedID()) .arg(v).arg(nv)); } } } } LocalGrounds.removeOne(NULL); // keep cleaning these out } ConnectorItem* SymbolPaletteItem::newConnectorItem(Connector *connector) { ConnectorItem * connectorItem = PaletteItemBase::newConnectorItem(connector); if (connector->connectorSharedID().compare("connector0") == 0) { m_connector0 = connectorItem; } else if (connector->connectorSharedID().compare("connector1") == 0) { m_connector1 = connectorItem; } else { return connectorItem; } if (m_isNetLabel) { LocalNetLabels.insert(getLabel(), connectorItem); } else if (connectorItem->isGrounded()) { LocalGrounds.append(connectorItem); //connectorItem->debugInfo("new ground insert"); } else { LocalVoltages.insert(FROMVOLTAGE(useVoltage(connectorItem)), connectorItem); //connectorItem->debugInfo(QString("new voltage insert %1").arg(useVoltage(connectorItem))); } return connectorItem; } void SymbolPaletteItem::busConnectorItems(Bus * bus, ConnectorItem * fromConnectorItem, QList & items) { if (bus == NULL) return; PaletteItem::busConnectorItems(bus, fromConnectorItem, items); //foreach (ConnectorItem * bc, items) { //bc->debugInfo(QString("bc %1").arg(bus->id())); //} QList< QPointer > mitems; if (m_isNetLabel) { mitems.append(LocalNetLabels.values(getLabel())); } else if (bus->id().compare("groundbus", Qt::CaseInsensitive) == 0) { mitems.append(LocalGrounds); } else { mitems.append(LocalVoltages.values(FROMVOLTAGE(m_voltage))); } foreach (ConnectorItem * connectorItem, mitems) { if (connectorItem == NULL) continue; if (connectorItem->scene() == this->scene()) { items.append(connectorItem); //connectorItem->debugInfo(QString("symbol bus %1").arg(bus->id())); } } } double SymbolPaletteItem::voltage() { return m_voltage; } void SymbolPaletteItem::setProp(const QString & prop, const QString & value) { if (prop.compare("voltage", Qt::CaseInsensitive) == 0) { setVoltage(value.toDouble()); return; } if (prop.compare("label", Qt::CaseInsensitive) == 0 && m_isNetLabel) { setLabel(value); return; } PaletteItem::setProp(prop, value); } void SymbolPaletteItem::setLabel(const QString & label) { removeMeFromBus(0); m_modelPart->setLocalProp("label", label); foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { LocalNetLabels.insert(label, connectorItem); } QTransform transform = untransform(); QString svg = makeSvg(this->viewLayerID()); resetRenderer(svg); resetLayerKin(); resetConnectors(NULL, NULL); retransform(transform); } void SymbolPaletteItem::setVoltage(double v) { removeMeFromBus(m_voltage); m_voltage = v; m_modelPart->setLocalProp("voltage", v); if (!Voltages.contains(v)) { Voltages.append(v); } if (m_isNetLabel) { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { LocalNetLabels.insert(QString::number(m_voltage), connectorItem); } } else { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->isGrounded()) { LocalGrounds.append(connectorItem); //connectorItem->debugInfo("ground insert"); } else { LocalVoltages.insert(FROMVOLTAGE(v), connectorItem); //connectorItem->debugInfo(QString("voltage insert %1").arg(useVoltage(connectorItem))); } } } if (m_viewID == ViewLayer::SchematicView) { if (m_voltageReference || m_isNetLabel) { QTransform transform = untransform(); QString svg = makeSvg(viewLayerID()); reloadRenderer(svg, false); resetLayerKin(); retransform(transform); if (m_partLabel) m_partLabel->displayTextsIf(); } } } QString SymbolPaletteItem::makeSvg(ViewLayer::ViewLayerID viewLayerID) { QString path = filename(); QFile file(filename()); QString svg; if (file.open(QFile::ReadOnly)) { svg = file.readAll(); file.close(); svg = replaceTextElement(svg); if (viewLayerID == ViewLayer::SchematicText) { bool hasText; return SvgFileSplitter::showText3(svg, hasText); } else { return SvgFileSplitter::hideText3(svg); } } return ""; } QString SymbolPaletteItem::replaceTextElement(QString svg) { double v = ((int) (m_voltage * 1000)) / 1000.0; return TextUtils::replaceTextElement(svg, "label", QString::number(v) + "V"); } QString SymbolPaletteItem::getProperty(const QString & key) { if (key.compare("voltage", Qt::CaseInsensitive) == 0) { return QString::number(m_voltage); } return PaletteItem::getProperty(key); } double SymbolPaletteItem::useVoltage(ConnectorItem * connectorItem) { return (connectorItem->connectorSharedName().compare("GND", Qt::CaseInsensitive) == 0) ? 0 : m_voltage; } ConnectorItem * SymbolPaletteItem::connector0() { return m_connector0; } ConnectorItem * SymbolPaletteItem::connector1() { return m_connector1; } void SymbolPaletteItem::addedToScene(bool temporary) { if (this->scene()) { setVoltage(m_voltage); } return PaletteItem::addedToScene(temporary); } QString SymbolPaletteItem::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { QString svg = PaletteItem::retrieveSvg(viewLayerID, svgHash, blackOnly, dpi, factor); if (m_voltageReference) { switch (viewLayerID) { case ViewLayer::Schematic: return replaceTextElement(svg); default: break; } } return svg; } bool SymbolPaletteItem::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if ((prop.compare("voltage", Qt::CaseInsensitive) == 0) && (moduleID().compare(ModuleIDNames::GroundModuleIDName) != 0)) { FocusOutComboBox * edit = new FocusOutComboBox(parent); edit->setEnabled(swappingEnabled); int ix = 0; foreach (double v, Voltages) { edit->addItem(QString::number(v)); if (v == m_voltage) { edit->setCurrentIndex(ix); } ix++; } QDoubleValidator * validator = new QDoubleValidator(edit); validator->setRange(-9999.99, 9999.99, 2); validator->setLocale(QLocale::C); validator->setNotation(QDoubleValidator::StandardNotation); validator->setLocale(QLocale::C); edit->setValidator(validator); edit->setObjectName("infoViewComboBox"); connect(edit, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(voltageEntry(const QString &))); returnWidget = edit; returnValue = m_voltage; returnProp = tr("voltage"); return true; } if (prop.compare("label", Qt::CaseInsensitive) == 0 && m_isNetLabel) { QLineEdit * edit = new QLineEdit(parent); edit->setEnabled(swappingEnabled); edit->setText(getLabel()); edit->setObjectName("infoViewLineEdit"); connect(edit, SIGNAL(editingFinished()), this, SLOT(labelEntry())); returnWidget = edit; returnValue = getLabel(); returnProp = tr("label"); return true; } return PaletteItem::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void SymbolPaletteItem::voltageEntry(const QString & text) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setVoltage(text.toDouble(), true); } } void SymbolPaletteItem::labelEntry() { QLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; QString current = getLabel(); if (edit->text().compare(current) == 0) return; if (edit->text().isEmpty()) { QMessageBox::warning(NULL, tr("Net labels"), tr("Net labels cannot be blank")); return; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "label", ItemBase::TranslatedPropertyNames.value("label"), current, edit->text(), true); } } ItemBase::PluralType SymbolPaletteItem::isPlural() { return Singular; } bool SymbolPaletteItem::hasPartNumberProperty() { return false; } ViewLayer::ViewID SymbolPaletteItem::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::SchematicView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } bool SymbolPaletteItem::hasPartLabel() { return !m_isNetLabel; } bool SymbolPaletteItem::isOnlyNetLabel() { return false; } QString SymbolPaletteItem::getLabel() { if (m_voltageReference) { return QString::number(m_voltage); } return modelPart()->localProp("label").toString(); } QString SymbolPaletteItem::getDirection() { return modelPart()->localProp("direction").toString(); } void SymbolPaletteItem::setAutoroutable(bool ar) { m_viewGeometry.setAutoroutable(ar); } bool SymbolPaletteItem::getAutoroutable() { return m_viewGeometry.getAutoroutable(); } void SymbolPaletteItem::resetLayerKin() { foreach (ItemBase * lkpi, layerKin()) { if (lkpi->viewLayerID() == ViewLayer::SchematicText) { QString svg = makeSvg(lkpi->viewLayerID()); lkpi->resetRenderer(svg); lkpi->setProperty("textSvg", svg); qobject_cast(lkpi)->clearTextThings(); break; } } } /////////////////////////////////////////////////////////////// NetLabel::NetLabel( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : SymbolPaletteItem(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { QString label = getLabel(); if (label.isEmpty()) { label = modelPart->properties().value("label"); if (label.isEmpty()) { label = tr("net label"); } modelPart->setLocalProp("label", label); } setInstanceTitle(label, true); // direction is now obsolete, new netlabels use flip QString direction = getDirection(); if (direction.isEmpty()) { direction = modelPart->properties().value("direction"); if (direction.isEmpty()) { direction = modelPart->moduleID().contains("left", Qt::CaseInsensitive) ? "left" : "right"; } modelPart->setLocalProp("direction", direction); } } NetLabel::~NetLabel() { } QString NetLabel::makeSvg(ViewLayer::ViewLayerID viewLayerID) { DebugDialog::debug("moduleid " + this->moduleID()); double divisor = moduleID().contains(PartFactory::OldSchematicPrefix) ? 1 : 3; double labelFontSize = 200 /divisor; double totalHeight = 300 / divisor; double arrowWidth = totalHeight / 2; double strokeWidth = 10 / divisor; double halfStrokeWidth = strokeWidth / 2; double labelOffset = 20 / divisor; double labelBaseLine = 220 / divisor; QFont font("Droid Sans", labelFontSize * 72 / GraphicsUtils::StandardFritzingDPI, QFont::Normal); QFontMetricsF fm(font); double textWidth = fm.width(getLabel()) * GraphicsUtils::StandardFritzingDPI / 72; double totalWidth = textWidth + arrowWidth + labelOffset; QString header("\n" "\n" "\n" ); bool goLeft = (getDirection() == "left"); // direction is now obsolete; this is left over from 0.7.12 and earlier double offset = goLeft ? arrowWidth : 0; QString svg = header.arg(totalWidth / 1000) .arg(totalHeight / 1000) .arg(totalWidth) .arg(totalHeight) .arg(ViewLayer::viewLayerXmlNameFromID(viewLayerID)) ; if (viewLayerID == ViewLayer::SchematicText) { svg += QString("%4\n") .arg(labelOffset + offset) .arg(labelBaseLine) .arg(labelFontSize) .arg(getLabel()); } else { QString pin = QString("\n"); QString terminal = QString("\n"); QString points = QString("%1,%2 %3,%4 %5,%4 %5,%6 %3,%6"); if (goLeft) { points = points.arg(halfStrokeWidth).arg(totalHeight / 2) .arg(arrowWidth).arg(halfStrokeWidth) .arg(totalWidth - halfStrokeWidth).arg(totalHeight - halfStrokeWidth); terminal = terminal.arg(0).arg(totalHeight / 2); pin = pin.arg(0).arg(0).arg(arrowWidth).arg(totalHeight); } else { points = points.arg(totalWidth - halfStrokeWidth).arg(totalHeight / 2) .arg(totalWidth - arrowWidth).arg(halfStrokeWidth) .arg(halfStrokeWidth).arg(totalHeight - halfStrokeWidth); terminal = terminal.arg(totalWidth).arg(totalHeight / 2); pin = pin.arg(totalWidth - arrowWidth - 0.1).arg(0).arg(arrowWidth).arg(totalHeight); } svg += pin; svg += terminal; svg += QString("\n") .arg(strokeWidth) .arg(points); } svg += "\n\n"; return svg; } void NetLabel::addedToScene(bool temporary) { if (this->scene() && m_viewID == ViewLayer::SchematicView) { // do not understand why plan setLabel() doesn't work the same as the Mystery Part setChipLabel() in addedToScene() if (!this->transform().isIdentity()) { // need to establish correct bounding rect here or setLabel will screw up alignment // this seems to solve half of the cases QString svg = makeSvg(this->viewLayerID()); resetRenderer(svg); resetLayerKin(); QRectF r = boundingRect(); //debugInfo(QString("added to scene %1,%2").arg(r.width()).arg(r.height())); QTransform chiefTransform = this->transform(); QTransform local; local.setMatrix(chiefTransform.m11(), chiefTransform.m12(), chiefTransform.m13(), chiefTransform.m21(), chiefTransform.m22(), chiefTransform.m23(), 0, 0, chiefTransform.m33()); if (!local.isIdentity()) { double x = r.width() / 2.0; double y = r.height() / 2.0; QTransform transf = QTransform().translate(-x, -y) * local * QTransform().translate(x, y); if (qAbs(chiefTransform.dx() - transf.dx()) > .01 || qAbs(chiefTransform.dy() - transf.dy()) > .01) { DebugDialog::debug("got the translation bug here"); this->getViewGeometry().setTransform(transf); this->setTransform2(transf); } } } setLabel(getLabel()); } // deliberately skip SymbolPaletteItem::addedToScene() return PaletteItem::addedToScene(temporary); } QString NetLabel::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor) { Q_UNUSED(svgHash); QString svg = makeSvg(viewLayerID); return PaletteItemBase::normalizeSvg(svg, viewLayerID, blackOnly, dpi, factor); } ItemBase::PluralType NetLabel::isPlural() { return Plural; } bool NetLabel::isOnlyNetLabel() { return true; } QString NetLabel::getInspectorTitle() { return getLabel(); } void NetLabel::setInspectorTitle(const QString & oldText, const QString & newText) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; infoGraphicsView->setProp(this, "label", ItemBase::TranslatedPropertyNames.value("label"), oldText, newText, true); } fritzing-app-0.9.2b/src/items/symbolpaletteitem.h000066400000000000000000000073351250202676700221410ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef SYMBOLPALETTEITEM_H #define SYMBOLPALETTEITEM_H #include "paletteitem.h" /* #include class FocusBugLineEdit : public QLineEdit { Q_OBJECT public: FocusBugLineEdit(QWidget * parent = NULL); ~FocusBugLineEdit(); signals: void safeEditingFinished(); protected slots: void editingFinishedSlot(); protected: QTime m_lastEditingFinishedEmit; }; */ class SymbolPaletteItem : public PaletteItem { Q_OBJECT public: SymbolPaletteItem(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~SymbolPaletteItem(); ConnectorItem* newConnectorItem(class Connector *connector); void busConnectorItems(class Bus * bus, ConnectorItem *, QList & items); double voltage(); void setProp(const QString & prop, const QString & value); void setVoltage(double); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); QString getProperty(const QString & key); ConnectorItem * connector0(); ConnectorItem * connector1(); PluralType isPlural(); void addedToScene(bool temporary); bool hasPartNumberProperty(); virtual bool isOnlyNetLabel(); bool hasPartLabel(); bool getAutoroutable(); void setAutoroutable(bool); void setLabel(const QString &); QString getLabel(); QString getDirection(); public: static double DefaultVoltage; public slots: void voltageEntry(const QString & text); void labelEntry(); protected: void removeMeFromBus(double voltage); double useVoltage(ConnectorItem * connectorItem); virtual QString makeSvg(ViewLayer::ViewLayerID); QString replaceTextElement(QString svg); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); void resetLayerKin(); protected: double m_voltage; QPointer m_connector0; QPointer m_connector1; bool m_voltageReference; bool m_isNetLabel; }; class NetLabel : public SymbolPaletteItem { Q_OBJECT public: NetLabel(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~NetLabel(); void addedToScene(bool temporary); QString retrieveSvg(ViewLayer::ViewLayerID, QHash & svgHash, bool blackOnly, double dpi, double & factor); PluralType isPlural(); bool isOnlyNetLabel(); QString getInspectorTitle(); void setInspectorTitle(const QString & oldText, const QString & newText); protected: QString makeSvg(ViewLayer::ViewLayerID); }; #endif fritzing-app-0.9.2b/src/items/tracewire.cpp000066400000000000000000000154271250202676700207170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "tracewire.h" #include "../sketch/infographicsview.h" #include "../connectors/connectoritem.h" #include "../utils/focusoutcombobox.h" #include const int TraceWire::MinTraceWidthMils = 8; const int TraceWire::MaxTraceWidthMils = 128; ///////////////////////////////////////////////////////// TraceWire::TraceWire( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu ) : ClipableWire(modelPart, viewID, viewGeometry, id, itemMenu, true) { m_canChainMultiple = true; m_wireDirection = TraceWire::NoDirection; } TraceWire::~TraceWire() { } QComboBox * TraceWire::createWidthComboBox(double m, QWidget * parent) { QComboBox * comboBox = new FocusOutComboBox(parent); // new QComboBox(parent); comboBox->setEditable(true); QIntValidator * intValidator = new QIntValidator(comboBox); intValidator->setRange(MinTraceWidthMils, MaxTraceWidthMils); comboBox->setValidator(intValidator); comboBox->setToolTip(tr("Select from the dropdown, or type in any value from %1 to %2").arg(MinTraceWidthMils).arg(MaxTraceWidthMils)); int ix = 0; if (!Wire::widths.contains(m)) { Wire::widths.append(m); qSort(Wire::widths.begin(), Wire::widths.end()); } foreach(long widthValue, Wire::widths) { QString widthName = Wire::widthTrans.value(widthValue, ""); QVariant val((int) widthValue); comboBox->addItem(widthName.isEmpty() ? QString::number(widthValue) : widthName, val); if (qAbs(m - widthValue) < .01) { comboBox->setCurrentIndex(ix); } ix++; } return comboBox; } bool TraceWire::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("width", Qt::CaseInsensitive) == 0) { if (viewID() != ViewLayer::PCBView) { // only in pcb view for now hide = true; return false; } returnProp = tr("width"); QComboBox * comboBox = createWidthComboBox(mils(), parent); comboBox->setEnabled(swappingEnabled); comboBox->setObjectName("infoViewComboBox"); connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(widthEntry(const QString &))); returnWidget = comboBox; returnValue = comboBox->currentText(); return true; } bool result = ClipableWire::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); if (prop.compare("layer") == 0 && returnWidget != NULL) { bool disabled = !canSwitchLayers(); if (!disabled) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL || infoGraphicsView->boardLayers() == 1) disabled = true; } returnWidget->setDisabled(disabled); } return result; return result; } void TraceWire::widthEntry(const QString & text) { int w = widthEntry(text, sender()); if (w == 0) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->changeWireWidthMils(QString::number(w)); } } int TraceWire::widthEntry(const QString & text, QObject * sender) { QComboBox * comboBox = qobject_cast(sender); if (comboBox == NULL) return 0; int w = comboBox->itemData(comboBox->currentIndex()).toInt(); if (w == 0) { // user typed in a number w = text.toInt(); } if (!Wire::widths.contains(w)) { Wire::widths.append(w); qSort(Wire::widths.begin(), Wire::widths.end()); } return w; } void TraceWire::setColorFromElement(QDomElement & element) { switch (m_viewLayerID) { case ViewLayer::Copper0Trace: element.setAttribute("color", ViewLayer::Copper0WireColor); break; case ViewLayer::Copper1Trace: element.setAttribute("color", ViewLayer::Copper1WireColor); break; case ViewLayer::SchematicTrace: //element.setAttribute("color", "#000000"); default: break; } Wire::setColorFromElement(element); } bool TraceWire::canSwitchLayers() { QList wires; QList ends; collectChained(wires, ends); foreach (ConnectorItem * end, ends) { if (end->getCrossLayerConnectorItem() == NULL) return false; } return true; } void TraceWire::setWireDirection(TraceWire::WireDirection wireDirection) { m_wireDirection = wireDirection; } TraceWire::WireDirection TraceWire::wireDirection() { return m_wireDirection; } TraceWire * TraceWire::getTrace(ConnectorItem * connectorItem) { return qobject_cast(connectorItem->attachedTo()); } void TraceWire::setSchematic(bool schematic) { m_viewGeometry.setSchematicTrace(schematic); } QHash TraceWire::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys) { QHash props = ClipableWire::prepareProps(modelPart, wantDebug, keys); if (m_viewID != ViewLayer::PCBView) return props; if (!m_viewGeometry.getPCBTrace()) return props; keys.append("layer"); props.insert("layer", ViewLayer::topLayers().contains(m_viewLayerID) ? "top" : "bottom"); return props; } QStringList TraceWire::collectValues(const QString & family, const QString & prop, QString & value) { if (prop.compare("layer") == 0) { QStringList values = ClipableWire::collectValues(family, prop, value); if (values.count() == 0) { values << TranslatedPropertyNames.value("bottom") << TranslatedPropertyNames.value("top"); if (ViewLayer::bottomLayers().contains(m_viewLayerID)) { value = values.at(0); } else { value = values.at(1); } } return values; } return ClipableWire::collectValues(family, prop, value); } fritzing-app-0.9.2b/src/items/tracewire.h000066400000000000000000000045361250202676700203630ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef TRACEWIRE_H #define TRACEWIRE_H #include "clipablewire.h" class TraceWire : public ClipableWire { Q_OBJECT public: TraceWire( ModelPart * modelPart, ViewLayer::ViewID, const ViewGeometry & , long id, QMenu* itemMenu ); ~TraceWire(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool canSwitchLayers(); void setSchematic(bool schematic); public: static TraceWire * getTrace(ConnectorItem *); static class QComboBox * createWidthComboBox(double currentMils, QWidget * parent); static int widthEntry(const QString & text, QObject * sender); QHash prepareProps(ModelPart *, bool wantDebug, QStringList & keys); QStringList collectValues(const QString & family, const QString & prop, QString & value); public: enum WireDirection { NoDirection, Vertical, Horizontal, Diagonal }; void setWireDirection(TraceWire::WireDirection); TraceWire::WireDirection wireDirection(); public: static const int MinTraceWidthMils; static const int MaxTraceWidthMils; protected: void setColorFromElement(QDomElement & element); protected slots: void widthEntry(const QString & text); protected: WireDirection m_wireDirection; }; #endif fritzing-app-0.9.2b/src/items/via.cpp000066400000000000000000000100541250202676700175000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "via.h" #include "../utils/graphicsutils.h" #include "../fsvgrenderer.h" #include "../utils/textutils.h" #include "../viewlayer.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include static HoleClassThing TheHoleThing; const QString Via::AutorouteViaHoleSize = "autorouteViaHoleSize"; const QString Via::AutorouteViaRingThickness = "autorouteViaRingThickness"; QString Via::DefaultAutorouteViaHoleSize; QString Via::DefaultAutorouteViaRingThickness; Via::Via( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel) : Hole(modelPart, viewID, viewGeometry, id, itemMenu, doLabel) { QSettings settings; QString ringThickness = settings.value(AutorouteViaRingThickness, "").toString(); QString holeSize = settings.value(AutorouteViaHoleSize, "").toString(); bool holeSizeWasEmpty = holeSize.isEmpty(); bool ringThicknessWasEmpty = holeSize.isEmpty(); PaletteItem::setUpHoleSizes("via", TheHoleThing); if (ringThicknessWasEmpty) { settings.setValue(AutorouteViaRingThickness, TheHoleThing.ringThickness); DefaultAutorouteViaRingThickness = TheHoleThing.ringThickness; } if (holeSizeWasEmpty) { settings.setValue(AutorouteViaHoleSize, TheHoleThing.holeSize); DefaultAutorouteViaHoleSize = TheHoleThing.holeSize; } //DebugDialog::debug(QString("creating via %1 %2 %3").arg((long) this, 0, 16).arg(id).arg(m_viewID)); } Via::~Via() { //DebugDialog::debug(QString("deleting via %1 %2 %3").arg((long) this, 0, 16).arg(m_id).arg(m_viewID)); } void Via::initHoleSettings(HoleSettings & holeSettings) { // called only by AutorouterSettingsDialog PaletteItem::initHoleSettings(holeSettings, &TheHoleThing); } void Via::setBoth(const QString & holeDiameter, const QString & ringThickness) { if (this->m_viewID != ViewLayer::PCBView) return; ItemBase * otherLayer = setBothSvg(holeDiameter, ringThickness); resetConnectors(otherLayer, otherLayer->fsvgRenderer()); double hd = TextUtils::convertToInches(holeDiameter) * GraphicsUtils::SVGDPI; double rt = TextUtils::convertToInches(ringThickness) * GraphicsUtils::SVGDPI; ConnectorItem * ci = connectorItem(); ci->setRadius((hd / 2) + (rt / 2), rt); ci->getCrossLayerConnectorItem()->setRadius((hd / 2) + (rt / 2), rt); } QString Via::makeID() { return "connector0pin"; } void Via::setAutoroutable(bool ar) { m_viewGeometry.setAutoroutable(ar); } bool Via::getAutoroutable() { return m_viewGeometry.getAutoroutable(); } ConnectorItem * Via::connectorItem() { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { return connectorItem; } return NULL; } void Via::saveInstanceLocation(QXmlStreamWriter & streamWriter) { streamWriter.writeAttribute("x", QString::number(m_viewGeometry.loc().x())); streamWriter.writeAttribute("y", QString::number(m_viewGeometry.loc().y())); streamWriter.writeAttribute("wireFlags", QString::number(m_viewGeometry.flagsAsInt())); GraphicsUtils::saveTransform(streamWriter, m_viewGeometry.transform()); } fritzing-app-0.9.2b/src/items/via.h000066400000000000000000000035261250202676700171530ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef VIA_H #define VIA_H #include "hole.h" class Via : public Hole { Q_OBJECT public: Via(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); ~Via(); void setAutoroutable(bool); bool getAutoroutable(); ConnectorItem * connectorItem(); void saveInstanceLocation(QXmlStreamWriter & streamWriter); public: static const QString AutorouteViaHoleSize; static const QString AutorouteViaRingThickness; static QString DefaultAutorouteViaHoleSize; static QString DefaultAutorouteViaRingThickness; public: static void initHoleSettings(HoleSettings & holeSettings); protected: QString makeID(); void setBoth(const QString & holeDiameter, const QString & thickness); protected: static void setBothConnectors(ItemBase * itemBase, SvgIdLayer * svgIdLayer); }; #endif fritzing-app-0.9.2b/src/items/virtualwire.cpp000066400000000000000000000103221250202676700212740ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "virtualwire.h" #include "../connectors/connectoritem.h" #include "../model/modelpart.h" const double VirtualWire::ShapeWidthExtra = 4; VirtualWire::VirtualWire( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu ) : ClipableWire(modelPart, viewID, viewGeometry, id, itemMenu, false) { // note: at this point in fritzing development, the VirtualWire class is only ever used for ratsnest wires modelPart->setLocalProp("ratsnest", "true"); m_colorWasNamed = false; setFlag(QGraphicsItem::ItemIsSelectable, false); } VirtualWire::~VirtualWire() { } void VirtualWire::paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { if (m_hidden) return; m_hoverCount = m_connectorHoverCount = 0; // kills any highlighting Wire::paint(painter, option, widget); } void VirtualWire::connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect) { checkVisibility(onMe, onIt, connect); } FSvgRenderer * VirtualWire::setUpConnectors(ModelPart * modelPart, ViewLayer::ViewID viewID) { FSvgRenderer * renderer = Wire::setUpConnectors(modelPart, viewID); hideConnectors(); return renderer; } void VirtualWire::hideConnectors() { // m_connector0 and m_connector1 may not yet be initialized foreach (ConnectorItem * item, cachedConnectorItems()) { item->setHidden(true); } } void VirtualWire::inactivateConnectors() { // m_connector0 and m_connector1 may not yet be initialized foreach (ConnectorItem * item, cachedConnectorItems()) { item->setInactive(true); } } void VirtualWire::setInactive(bool inactivate) { ItemBase::setInactive(inactivate); if (!inactivate) { inactivateConnectors(); } } void VirtualWire::setHidden(bool hide) { ItemBase::setHidden(hide); if (!hide) { hideConnectors(); } } void VirtualWire::tempRemoveAllConnections() { ConnectorItem * connectorItem = connector0(); for (int j = connectorItem->connectedToItems().count() - 1; j >= 0; j--) { connectorItem->connectedToItems()[j]->tempRemove(connectorItem, false); connectorItem->tempRemove(connectorItem->connectedToItems()[j], false); } connectorItem = connector1(); for (int j = connectorItem->connectedToItems().count() - 1; j >= 0; j--) { connectorItem->connectedToItems()[j]->tempRemove(connectorItem, false); connectorItem->tempRemove(connectorItem->connectedToItems()[j], false); } } void VirtualWire::mousePressEvent(QGraphicsSceneMouseEvent *event) { // ignore clicks where our connectors are supposed to be // so the click can percolate to some other graphicsitem that can use it QList items = scene()->items(event->scenePos()); if (items.contains(m_connector0) || items.contains(m_connector1)) { event->ignore(); return; } // set selectable flag temporarily here so that dragging out a bendpoint is enabled setFlag(QGraphicsItem::ItemIsSelectable, true); ClipableWire::mousePressEvent(event); setFlag(QGraphicsItem::ItemIsSelectable, false); } void VirtualWire::setColorWasNamed(bool colorWasNamed) { m_colorWasNamed = colorWasNamed; } bool VirtualWire::colorWasNamed() { return m_colorWasNamed; } QPainterPath VirtualWire::shape() const { return shapeAux(m_hoverStrokeWidth); } fritzing-app-0.9.2b/src/items/virtualwire.h000066400000000000000000000036521250202676700207510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef VIRTUALWIRE_H #define VIRTUALWIRE_H #include "clipablewire.h" class VirtualWire : public ClipableWire { Q_OBJECT public: VirtualWire( ModelPart * modelPart, ViewLayer::ViewID, const ViewGeometry & , long id, QMenu* itemMenu ); ~VirtualWire(); void setHidden(bool hidden); void setInactive(bool inactivate); void tempRemoveAllConnections(); void setColorWasNamed(bool); bool colorWasNamed(); QPainterPath shape() const; protected: void paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ); void mousePressEvent(QGraphicsSceneMouseEvent *event); void connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect); class FSvgRenderer * setUpConnectors(class ModelPart *, ViewLayer::ViewID); void hideConnectors(); void inactivateConnectors(); public: static const double ShapeWidthExtra; protected: bool m_colorWasNamed; }; #endif fritzing-app-0.9.2b/src/items/wire.cpp000066400000000000000000001542511250202676700176770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 7000 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 07:24:08 +0200 (Mo, 29. Apr 2013) $ ********************************************************************/ /* curvy To Do curvy to begin with? would have to vary with some function of angle and distance could convert control points to t values? turn curvature on/off per view --------------------------------------------------------- later: clippable wire gerber autorouter warning in PCB view modify parameters (tension, unit area)? */ ///////////////////////////////////////////////////////////////// #include "wire.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../debugdialog.h" #include "../sketch/infographicsview.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include "../fsvgrenderer.h" #include "partlabel.h" #include "../model/modelpart.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/bezier.h" #include "../utils/bezierdisplay.h" #include "../utils/cursormaster.h" #include "../utils/ratsnestcolors.h" #include "../layerattributes.h" #include QVector Wire::TheDash; QVector RatDash; QBrush BandedBrush(QColor(255, 255, 255)); QHash Wire::colorTrans; QStringList Wire::colorNames; QHash Wire::widthTrans; QList Wire::widths; double Wire::STANDARD_TRACE_WIDTH; double Wire::HALF_STANDARD_TRACE_WIDTH; double Wire::THIN_TRACE_WIDTH; const double DefaultHoverStrokeWidth = 4; static Bezier UndoBezier; static BezierDisplay * TheBezierDisplay = NULL; //////////////////////////////////////////////////////////// bool alphaLessThan(QColor * c1, QColor * c2) { return c1->alpha() < c2->alpha(); } void debugCompare(ItemBase * it) { Wire * wire = dynamic_cast(it); if (wire) { QRectF r0 = wire->connector0()->rect(); QRectF r1 = wire->connector1()->rect(); if (qAbs(r0.left() - r1.left()) < 0.1 && qAbs(r0.right() - r1.right()) < 0.1 && qAbs(r0.top() - r1.top()) < 0.1 && qAbs(r0.bottom() - r1.bottom()) < 0.1) { wire->debugInfo("zero wire"); if (wire->viewID() == ViewLayer::PCBView) { DebugDialog::debug("in pcb"); } } } } ///////////////////////////////////////////////////////////// WireAction::WireAction(QAction * action) : QAction(action) { m_wire = NULL; this->setText(action->text()); this->setStatusTip(action->statusTip()); this->setCheckable(action->isCheckable()); } WireAction::WireAction(const QString & title, QObject * parent) : QAction(title, parent) { m_wire = NULL; } void WireAction::setWire(Wire * w) { m_wire = w; } Wire * WireAction::wire() { return m_wire; } ///////////////////////////////////////////////////////////// Wire::Wire( ModelPart * modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu* itemMenu, bool initLabel) : ItemBase(modelPart, viewID, viewGeometry, id, itemMenu) { m_banded = false; m_bezier = NULL; m_displayBendpointCursor = m_canHaveCurve = true; m_hoverStrokeWidth = DefaultHoverStrokeWidth; m_connector0 = m_connector1 = NULL; m_partLabel = initLabel ? new PartLabel(this, NULL) : NULL; m_canChainMultiple = false; setFlag(QGraphicsItem::ItemIsSelectable, true ); m_connectorHover = NULL; m_opacity = 1.0; m_ignoreSelectionChange = false; //DebugDialog::debug(QString("aix line %1 %2 %3 %4").arg(this->viewGeometry().line().x1()) //.arg(this->viewGeometry().line().y1()) //.arg(this->viewGeometry().line().x2()) //.arg(this->viewGeometry().line().y2()) ); //DebugDialog::debug(QString("aix loc %1 %2").arg(this->viewGeometry().loc().x()) //.arg(this->viewGeometry().loc().y()) ); setPos(m_viewGeometry.loc()); m_dragCurve = m_dragEnd = false; } Wire::~Wire() { if (m_bezier) { delete m_bezier; } } FSvgRenderer * Wire::setUp(ViewLayer::ViewLayerID viewLayerID, const LayerHash & viewLayers, InfoGraphicsView * infoGraphicsView) { ItemBase::setViewLayerID(viewLayerID, viewLayers); FSvgRenderer * svgRenderer = setUpConnectors(m_modelPart, m_viewID); if (svgRenderer != NULL) { initEnds(m_viewGeometry, svgRenderer->viewBox(), infoGraphicsView); //debugCompare(this); } setZValue(this->z()); return svgRenderer; } void Wire::saveGeometry() { m_viewGeometry.setSelected(this->isSelected()); m_viewGeometry.setLine(this->line()); m_viewGeometry.setLoc(this->pos()); m_viewGeometry.setZ(this->zValue()); } bool Wire::itemMoved() { if (m_viewGeometry.loc() != this->pos()) return true; if (this->line().dx() != m_viewGeometry.line().dx()) return false; if (this->line().dy() != m_viewGeometry.line().dy()) return false; return (this->line() != m_viewGeometry.line()); } void Wire::moveItem(ViewGeometry & viewGeometry) { this->setPos(viewGeometry.loc()); this->setLine(viewGeometry.line()); } void Wire::initEnds(const ViewGeometry & vg, QRectF defaultRect, InfoGraphicsView * infoGraphicsView) { bool gotOne = false; bool gotTwo = false; double penWidth = 1; foreach (ConnectorItem * item, cachedConnectorItems()) { // check the name or is order good enough? if (gotOne) { gotTwo = true; m_connector1 = item; break; } else { penWidth = item->rect().width(); m_connector0 = item; gotOne = true; } } if (!gotTwo) { return; } if ((vg.line().length() == 0) && (vg.line().x1() == -1)) { this->setLine(defaultRect.left(), defaultRect.top(), defaultRect.right(), defaultRect.bottom()); } else { this->setLine(vg.line()); } setConnector0Rect(); setConnector1Rect(); m_viewGeometry.setLine(this->line()); QBrush brush(QColor(0, 0, 0)); QPen pen(brush, penWidth, Qt::SolidLine, Qt::RoundCap); this->setPen(pen); m_pen.setCapStyle(Qt::RoundCap); m_shadowPen.setCapStyle(Qt::RoundCap); if (infoGraphicsView != NULL) { infoGraphicsView->initWire(this, penWidth); } prepareGeometryChange(); } void Wire::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { if (m_hidden) return; ItemBase::paint(painter, option, widget); } void Wire::paintBody(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { Q_UNUSED(option); Q_UNUSED(widget); QPainterPath painterPath; if (m_bezier && !m_bezier->isEmpty()) { QLineF line = this->line(); painterPath.moveTo(line.p1()); painterPath.cubicTo(m_bezier->cp0(), m_bezier->cp1(), line.p2()); /* DebugDialog::debug(QString("c0x:%1,c0y:%2 c1x:%3,c1y:%4 p0x:%5,p0y:%6 p1x:%7,p1y:%8 px:%9,py:%10") .arg(m_controlPoints.at(0).x()) .arg(m_controlPoints.at(0).y()) .arg(m_controlPoints.at(1).x()) .arg(m_controlPoints.at(1).y()) .arg(m_line.p1().x()) .arg(m_line.p1().y()) .arg(m_line.p2().x()) .arg(m_line.p2().y()) .arg(pos().x()) .arg(pos().y()) ); */ } painter->setOpacity(m_inactive ? m_opacity / 2 : m_opacity); if (hasShadow()) { painter->save(); painter->setPen(m_shadowPen); if (painterPath.isEmpty()) { QLineF line = this->line(); painter->drawLine(line); } else { painter->drawPath(painterPath); } painter->restore(); } // DebugDialog::debug(QString("pen width %1 %2").arg(m_pen.widthF()).arg(m_viewID)); if (m_banded) { QBrush brush = m_pen.brush(); m_pen.setStyle(Qt::SolidLine); m_pen.setBrush(BandedBrush); painter->setPen(m_pen); if (painterPath.isEmpty()) { painter->drawLine(getPaintLine()); } else { painter->drawPath(painterPath); } m_pen.setBrush(brush); m_pen.setDashPattern(TheDash); m_pen.setCapStyle(Qt::FlatCap); } if (getRatsnest()) { m_pen.setDashPattern(RatDash); } painter->setPen(m_pen); if (painterPath.isEmpty()) { painter->drawLine(getPaintLine()); } else { painter->drawPath(painterPath); } if (m_banded) { m_pen.setStyle(Qt::SolidLine); m_pen.setCapStyle(Qt::RoundCap); } } void Wire::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); Q_UNUSED(option); painter->save(); if ((m_connectorHoverCount > 0 && !(m_dragEnd || m_dragCurve)) || m_connectorHoverCount2 > 0) { painter->setOpacity(.50); painter->fillPath(this->hoverShape(), QBrush(ConnectorHoverColor)); } else { painter->setOpacity(HoverOpacity); painter->fillPath(this->hoverShape(), QBrush(HoverColor)); } painter->restore(); } QPainterPath Wire::hoverShape() const { return shapeAux(m_hoverStrokeWidth); } QPainterPath Wire::shape() const { return shapeAux(m_pen.widthF()); } QPainterPath Wire::shapeAux(double width) const { QPainterPath path; if (m_line == QLineF()) { return path; } path.moveTo(m_line.p1()); if (m_bezier == NULL || m_bezier->isEmpty()) { path.lineTo(m_line.p2()); } else { path.cubicTo(m_bezier->cp0(), m_bezier->cp1(), m_line.p2()); } //DebugDialog::debug(QString("using hoverstrokewidth %1 %2").arg(m_id).arg(m_hoverStrokeWidth)); return GraphicsUtils::shapeFromPath(path, m_pen, width, false); } QRectF Wire::boundingRect() const { if (m_pen.widthF() == 0.0) { const double x1 = m_line.p1().x(); const double x2 = m_line.p2().x(); const double y1 = m_line.p1().y(); const double y2 = m_line.p2().y(); double lx = qMin(x1, x2); double rx = qMax(x1, x2); double ty = qMin(y1, y2); double by = qMax(y1, y2); return QRectF(lx, ty, rx - lx, by - ty); } return hoverShape().controlPointRect(); } void Wire::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { //DebugDialog::debug("checking press event"); emit wireSplitSignal(this, event->scenePos(), this->pos(), this->line()); } void Wire::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setActiveWire(this); } ItemBase::contextMenuEvent(event); } void Wire::mousePressEvent(QGraphicsSceneMouseEvent *event) { ItemBase::mousePressEvent(event); } void Wire::initDragCurve(QPointF scenePos) { if (m_bezier == NULL) { m_bezier = new Bezier(); } UndoBezier.copy(m_bezier); m_dragCurve = true; m_dragEnd = false; QPointF p0 = connector0()->sceneAdjustedTerminalPoint(NULL); QPointF p1 = connector1()->sceneAdjustedTerminalPoint(NULL); if (m_bezier->isEmpty()) { m_bezier->initToEnds(mapFromScene(p0), mapFromScene(p1)); } else { m_bezier->set_endpoints(mapFromScene(p0), mapFromScene(p1)); } m_bezier->initControlIndex(mapFromScene(scenePos), m_pen.widthF()); TheBezierDisplay = new BezierDisplay; TheBezierDisplay->initDisplay(this, m_bezier); } bool Wire::initNewBendpoint(QPointF scenePos, Bezier & left, Bezier & right) { if (m_bezier == NULL || m_bezier->isEmpty()) { UndoBezier.clear(); return false; } QPointF p0 = connector0()->sceneAdjustedTerminalPoint(NULL); QPointF p1 = connector1()->sceneAdjustedTerminalPoint(NULL); m_bezier->set_endpoints(mapFromScene(p0), mapFromScene(p1)); UndoBezier.copy(m_bezier); double t = m_bezier->findSplit(mapFromScene(scenePos), m_pen.widthF()); m_bezier->split(t, left, right); return true; } void Wire::initDragEnd(ConnectorItem * connectorItem, QPointF scenePos) { Q_UNUSED(scenePos); saveGeometry(); QLineF line = this->line(); m_drag0 = (connectorItem == m_connector0); //debugInfo("setting drag end to true"); m_dragEnd = true; m_dragCurve = false; if (m_drag0) { m_wireDragOrigin = line.p2(); //DebugDialog::debug(QString("drag near origin %1 %2").arg(m_wireDragOrigin.x()).arg(m_wireDragOrigin.y()) ); } else { m_wireDragOrigin = line.p1(); //DebugDialog::debug(QString("drag far origin %1 %2").arg(m_wireDragOrigin.x()).arg(m_wireDragOrigin.y()) ); //DebugDialog::debug(QString("drag far other %1 %2").arg(line.p2().x()).arg(line.p2().y()) ); } if (connectorItem->chained()) { QList chained; QList ends; collectChained(chained, ends); // already saved the first one for (int i = 1; i < chained.count(); i++) { chained[i]->saveGeometry(); } } } void Wire::mouseReleaseConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { Q_UNUSED(event); Q_UNUSED(connectorItem); releaseDrag(); } void Wire::mouseMoveConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { mouseMoveEventAux(this->mapFromItem(connectorItem, event->pos()), event->modifiers()); } void Wire::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { mouseMoveEventAux(event->pos(), event->modifiers()); } void Wire::mouseMoveEventAux(QPointF eventPos, Qt::KeyboardModifiers modifiers) { if (m_spaceBarWasPressed) { return; } if (m_dragCurve) { prepareGeometryChange(); dragCurve(eventPos, modifiers); update(); if (TheBezierDisplay) TheBezierDisplay->updateDisplay(this, m_bezier); return; } if (m_dragEnd == false) { return; } //debugInfo("dragging wire"); ConnectorItem * whichConnectorItem; ConnectorItem * otherConnectorItem; if (m_drag0) { whichConnectorItem = m_connector0; otherConnectorItem = m_connector1; } else { whichConnectorItem = m_connector1; otherConnectorItem = m_connector0; } if ((modifiers & Qt::ShiftModifier) != 0) { QPointF initialPos = mapFromScene(otherConnectorItem->sceneAdjustedTerminalPoint(NULL)); bool bendpoint = isBendpoint(whichConnectorItem); if (bendpoint) { bendpoint = false; foreach (ConnectorItem * ci, whichConnectorItem->connectedToItems()) { Wire * w = qobject_cast(ci->attachedTo()); ConnectorItem * oci = w->otherConnector(ci); QPointF otherInitialPos = mapFromScene(oci->sceneAdjustedTerminalPoint(NULL)); QPointF p1(initialPos.x(), otherInitialPos.y()); double d = GraphicsUtils::distanceSqd(p1, eventPos); if (d <= 144) { bendpoint = true; eventPos = p1; break; } p1.setX(otherInitialPos.x()); p1.setY(initialPos.y()); d = GraphicsUtils::distanceSqd(p1, eventPos); if (d <= 144) { bendpoint = true; eventPos = p1; break; } } } if (!bendpoint) { eventPos = GraphicsUtils::calcConstraint(initialPos, eventPos); } } if (m_drag0) { QPointF p = this->mapToScene(eventPos); QGraphicsSvgItem::setPos(p.x(), p.y()); this->setLine(0, 0, m_wireDragOrigin.x() - p.x() + m_viewGeometry.loc().x(), m_wireDragOrigin.y() - p.y() + m_viewGeometry.loc().y() ); //DebugDialog::debug(QString("drag0 wdo:(%1,%2) p:(%3,%4) vg:(%5,%6) l:(%7,%8)") // .arg(m_wireDragOrigin.x()).arg(m_wireDragOrigin.y()) // .arg(p.x()).arg(p.y()) // .arg(m_viewGeometry.loc().x()).arg(m_viewGeometry.loc().y()) // .arg(line().p2().x()).arg(line().p2().y()) // ); } else { this->setLine(m_wireDragOrigin.x(), m_wireDragOrigin.y(), eventPos.x(), eventPos.y()); //DebugDialog::debug(QString("drag1 wdo:(%1,%2) ep:(%3,%4) p:(%5,%6) l:(%7,%8)") // .arg(m_wireDragOrigin.x()).arg(m_wireDragOrigin.y()) // .arg(eventPos.x()).arg(eventPos.y()) // .arg(pos().x()).arg(pos().y()) // .arg(line().p2().x()).arg(line().p2().y()) // ); } setConnector1Rect(); QSet allTo; allTo.insert(whichConnectorItem); foreach (ConnectorItem * toConnectorItem, whichConnectorItem->connectedToItems()) { Wire * chainedWire = qobject_cast(toConnectorItem->attachedTo()); if (chainedWire == NULL) continue; allTo.insert(toConnectorItem); foreach (ConnectorItem * subTo, toConnectorItem->connectedToItems()) { allTo.insert(subTo); } } allTo.remove(whichConnectorItem); // TODO: this could all be determined once at mouse press time if (allTo.count() == 0) { // dragging one end of the wire // don't allow wire to connect back to something the other end is already directly connected to // an alternative would be to exclude all connectors in the net connected by the same kind of trace QList wires; QList ends; collectChained(wires, ends); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); //DebugDialog::debug("------------------------"); QList exclude; foreach (ConnectorItem * end, ends) { exclude << end; foreach (ConnectorItem * ci, end->connectedToItems()) { // if there is a wire growing out of one of the excluded ends, exclude the attached end exclude << ci; } foreach (ConnectorItem * toConnectorItem, end->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) continue; Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w->getRatsnest()) continue; if (!w->isTraceType(infoGraphicsView->getTraceFlag())) continue; //w->debugInfo("what wire"); QList ends2; QList wires2; w->collectChained(wires2, ends2); exclude.append(ends2); foreach (ConnectorItem * e2, ends2) { foreach (ConnectorItem * ci, e2->connectedToItems()) { // if there is a wire growing out of one of the excluded ends, exclude that end of the wire exclude << ci; } } foreach (Wire * w2, wires2) { exclude.append(w2->cachedConnectorItems()); } } } // but allow to restore connections at this end (collect chained above got both ends of this wire) foreach (ConnectorItem * toConnectorItem, whichConnectorItem->connectedToItems()) { if (ends.contains(toConnectorItem)) exclude.removeAll(toConnectorItem); } //DebugDialog::debug(""); //DebugDialog::debug("__________________"); //foreach (ConnectorItem * end, exclude) end->debugInfo("exclude"); ConnectorItem * originatingConnector = NULL; if (otherConnectorItem) { foreach (ConnectorItem * toConnectorItem, otherConnectorItem->connectedToItems()) { if (ends.contains(toConnectorItem)) { originatingConnector = toConnectorItem; break; } } } whichConnectorItem->findConnectorUnder(false, true, exclude, true, originatingConnector); } else { // dragging a bendpoint foreach (ConnectorItem * toConnectorItem, allTo) { Wire * chained = qobject_cast(toConnectorItem->attachedTo()); if (chained) { chained->simpleConnectedMoved(whichConnectorItem, toConnectorItem); } } } } void Wire::setConnector0Rect() { QRectF rect = m_connector0->rect(); rect.moveTo(0 - (rect.width() / 2.0), 0 - (rect.height() / 2.0) ); m_connector0->setRect(rect); //debugCompare(this); // QPointF p = m_connector0->mapToScene(m_connector0->rect().center()); // m_connector0->debugInfo(QString("c0:%1 %2").arg(p.x()).arg(p.y())); // p = m_connector1->mapToScene(m_connector1->rect().center()); // m_connector1->debugInfo(QString("c1:%1 %2").arg(p.x()).arg(p.y())); } void Wire::setConnector1Rect() { QRectF rect = m_connector1->rect(); rect.moveTo(this->line().dx() - (rect.width() / 2.0), this->line().dy() - (rect.height() / 2.0) ); m_connector1->setRect(rect); //debugCompare(this); // QPointF p = m_connector0->mapToScene(m_connector0->rect().center()); // m_connector0->debugInfo(QString("c0:%1 %2").arg(p.x()).arg(p.y())); // p = m_connector1->mapToScene(m_connector1->rect().center()); // m_connector1->debugInfo(QString("c1:%1 %2").arg(p.x()).arg(p.y())); } void Wire::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (m_spaceBarWasPressed) { return; } //debugInfo("wire release drag"); if (releaseDrag()) return; ItemBase::mouseReleaseEvent(event); } bool Wire::releaseDrag() { if (m_dragEnd == false && m_dragCurve == false) return false; if (m_dragCurve) { delete TheBezierDisplay; TheBezierDisplay = NULL; m_dragCurve = false; ungrabMouse(); if (UndoBezier != *m_bezier) { emit wireChangedCurveSignal(this, &UndoBezier, m_bezier, false); } return true; } //debugInfo("clearing drag end"); m_dragEnd = false; ConnectorItem * from = (m_drag0) ? m_connector0 : m_connector1; ConnectorItem * to = from->releaseDrag(); QLineF newLine = this->line(); QLineF oldLine = m_viewGeometry.line(); QPointF oldPos = m_viewGeometry.loc(); QPointF newPos = this->pos(); if (newLine != oldLine || oldPos != newPos) { emit wireChangedSignal(this, oldLine, newLine, oldPos, newPos, from, to); } return true; } void Wire::saveInstanceLocation(QXmlStreamWriter & streamWriter) { QLineF line = m_viewGeometry.line(); QPointF loc = m_viewGeometry.loc(); streamWriter.writeAttribute("x", QString::number(loc.x())); streamWriter.writeAttribute("y", QString::number(loc.y())); streamWriter.writeAttribute("x1", QString::number(line.x1())); streamWriter.writeAttribute("y1", QString::number(line.y1())); streamWriter.writeAttribute("x2", QString::number(line.x2())); streamWriter.writeAttribute("y2", QString::number(line.y2())); streamWriter.writeAttribute("wireFlags", QString::number(m_viewGeometry.flagsAsInt())); } void Wire::writeGeometry(QXmlStreamWriter & streamWriter) { ItemBase::writeGeometry(streamWriter); streamWriter.writeStartElement("wireExtras"); streamWriter.writeAttribute("mils", QString::number(mils())); streamWriter.writeAttribute("color", m_pen.brush().color().name()); streamWriter.writeAttribute("opacity", QString::number(m_opacity)); streamWriter.writeAttribute("banded", m_banded ? "1" : "0"); if (m_bezier) m_bezier->write(streamWriter); streamWriter.writeEndElement(); } void Wire::setExtras(QDomElement & element, InfoGraphicsView * infoGraphicsView) { if (element.isNull()) return; bool ok; double w = element.attribute("width").toDouble(&ok); if (ok) { setWireWidth(w, infoGraphicsView, infoGraphicsView->getWireStrokeWidth(this, w)); } else { w = element.attribute("mils").toDouble(&ok); if (ok) { double wpix = GraphicsUtils::mils2pixels(w, GraphicsUtils::SVGDPI); setWireWidth(wpix, infoGraphicsView, infoGraphicsView->getWireStrokeWidth(this, wpix)); } } m_banded = (element.attribute("banded", "") == "1"); setColorFromElement(element); QDomElement bElement = element.firstChildElement("bezier"); Bezier bezier = Bezier::fromElement(bElement); if (!bezier.isEmpty()) { prepareGeometryChange(); m_bezier = new Bezier; m_bezier->copy(&bezier); QPointF p0 = connector0()->sceneAdjustedTerminalPoint(NULL); QPointF p1 = connector1()->sceneAdjustedTerminalPoint(NULL); m_bezier->set_endpoints(mapFromScene(p0), mapFromScene(p1)); } } void Wire::setColorFromElement(QDomElement & element) { QString colorString = element.attribute("color"); if (colorString.isNull() || colorString.isEmpty()) return; bool ok; double op = element.attribute("opacity").toDouble(&ok); if (!ok) { op = 1.0; } setColorString(colorString, op, false); } void Wire::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event , ConnectorItem * item) { m_connectorHover = item; ItemBase::hoverEnterConnectorItem(event, item); } void Wire::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { m_connectorHover = NULL; ItemBase::hoverLeaveConnectorItem(event, item); } void Wire::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) { ItemBase::hoverEnterEvent(event); CursorMaster::instance()->addCursor(this, cursor()); //DebugDialog::debug("---wire set override cursor"); updateCursor(event->modifiers()); } void Wire::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { ItemBase::hoverLeaveEvent(event); //DebugDialog::debug("------wire restore override cursor"); CursorMaster::instance()->removeCursor(this); } void Wire::connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect) { checkVisibility(onMe, onIt, connect); bool movable = true; foreach (ConnectorItem * connectedTo, m_connector0->connectedToItems()) { if (connectedTo->attachedToItemType() != ModelPart::Wire) { movable = false; break; } } if (movable) { foreach (ConnectorItem * connectedTo, m_connector1->connectedToItems()) { if (connectedTo->attachedToItemType() != ModelPart::Wire) { movable = false; break; } } } } void Wire::mouseDoubleClickConnectorEvent(ConnectorItem * connectorItem) { int chained = 0; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { chained++; } else { return; } } if (chained == 1) { // near as I can tell, this is to eliminate the overrides from the connectorItem and then from the wire itself emit wireJoinSignal(this, connectorItem); } } void Wire::mousePressConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { //DebugDialog::debug("checking press connector event"); if (m_canChainMultiple && event->modifiers() & altOrMetaModifier()) { // dragging a wire out of a bendpoint InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->mousePressConnectorEvent(connectorItem, event); } return; } connectorItem->setOverConnectorItem(NULL); initDragEnd(connectorItem, event->scenePos()); } void Wire::simpleConnectedMoved(ConnectorItem * to) { // to is this wire, from is something else simpleConnectedMoved(to->firstConnectedToIsh(), to); } void Wire::simpleConnectedMoved(ConnectorItem * from, ConnectorItem * to) { if (from == NULL) return; //if (from) from->debugInfo("connected moved from"); //if (to) to->debugInfo("\tto"); // to is this wire, from is something else QPointF p1, p2; calcNewLine(from, to, p1, p2); /* QPointF oldPos = this->pos(); QPointF newPos = p1; QLineF oldLine = this->line(); QLineF newLine(0, 0, p2.x() - p1.x(), p2.y() - p1.y()); if (qAbs(oldPos.x() - newPos.x()) > 1.75 || qAbs(oldPos.y() - newPos.y()) > 1.75 || qAbs(oldLine.x1() - newLine.x1()) > 1.75 || qAbs(oldLine.x2() - newLine.x2()) > 1.75 || qAbs(oldLine.y1() - newLine.y1()) > 1.75 || qAbs(oldLine.y2() - newLine.y2()) > 1.75 ) { DebugDialog::debug("line changed"); calcNewLine(from,to,p1,p2); } */ this->setPos(p1); this->setLine(0,0, p2.x() - p1.x(), p2.y() - p1.y() ); //debugInfo(QString("set line %1 %2, %3 %4, vis:%5").arg(p1.x()).arg(p1.y()).arg(p2.x()).arg(p2.y()).arg(isVisible()) ); setConnector1Rect(); } void Wire::calcNewLine(ConnectorItem * from, ConnectorItem * to, QPointF & p1, QPointF & p2) { // to is this wire, from is something else if (to == m_connector0) { p1 = from->sceneAdjustedTerminalPoint(to); ConnectorItem * otherFrom = m_connector1->firstConnectedToIsh(); if (otherFrom == NULL) { p2 = m_connector1->mapToScene(m_connector1->rect().center()); } else { p2 = otherFrom->sceneAdjustedTerminalPoint(m_connector1); } } else { p2 = from->sceneAdjustedTerminalPoint(to); ConnectorItem * otherFrom = m_connector0->firstConnectedToIsh(); if (otherFrom == NULL) { p1 = m_connector0->mapToScene(m_connector0->rect().center()); } else { p1 = otherFrom->sceneAdjustedTerminalPoint(m_connector0); } } } void Wire::connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already) { Q_UNUSED(already); // "from" is the connector on the part // "to" is the connector on the wire //from->debugInfo("connected moved"); //to->debugInfo("\tconnected moved"); if (from->connectedToItems().contains(to) || to->connectedToItems().contains(from)) { simpleConnectedMoved(from, to); } else { //from->debugInfo("not connected"); //to->debugInfo("\t"); } } FSvgRenderer * Wire::setUpConnectors(ModelPart * modelPart, ViewLayer::ViewID viewID) { clearConnectorItemCache(); LayerAttributes layerAttributes; this->initLayerAttributes(layerAttributes, viewID, m_viewLayerID, m_viewLayerPlacement, false, false); FSvgRenderer * renderer = ItemBase::setUpImage(modelPart, layerAttributes); if (renderer == NULL) { return NULL; } foreach (Connector * connector, modelPart->connectors().values()) { if (connector == NULL) continue; SvgIdLayer * svgIdLayer = connector->fullPinInfo(viewID, m_viewLayerID); if (svgIdLayer == NULL) continue; bool result = renderer->setUpConnector(svgIdLayer, false, viewLayerPlacement()); if (!result) continue; ConnectorItem * connectorItem = newConnectorItem(connector); connectorItem->setRect(svgIdLayer->rect(viewLayerPlacement())); connectorItem->setTerminalPoint(svgIdLayer->point(viewLayerPlacement())); m_originalConnectorRect = svgIdLayer->rect(viewLayerPlacement()); connectorItem->setCircular(true); //DebugDialog::debug(QString("terminal point %1 %2").arg(terminalPoint.x()).arg(terminalPoint.y()) ); } return renderer; } /* void Wire::setPos(const QPointF & pos) { ItemBase::setPos(pos); } */ void Wire::setLineAnd(QLineF line, QPointF pos, bool useLine) { this->setPos(pos); if (useLine) this->setLine(line); setConnector1Rect(); } ConnectorItem * Wire::otherConnector(ConnectorItem * oneConnector) { if (oneConnector == m_connector0) return m_connector1; return m_connector0; } ConnectorItem * Wire::connector0() { return m_connector0; } ConnectorItem * Wire::connector1() { return m_connector1; } void Wire::findConnectorsUnder() { foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0) continue; // only check free ends connectorItem->findConnectorUnder(true, false, ConnectorItem::emptyConnectorItemList, false, NULL); } } void Wire::collectChained(QList & chained, QList & ends ) { chained.append(this); for (int i = 0; i < chained.count(); i++) { Wire * wire = chained[i]; collectChained(wire->m_connector1, chained, ends); collectChained(wire->m_connector0, chained, ends); } } void Wire::collectChained(ConnectorItem * connectorItem, QList & chained, QList & ends) { if (connectorItem == NULL) return; foreach (ConnectorItem * connectedToItem, connectorItem->connectedToItems()) { Wire * wire = qobject_cast(connectedToItem->attachedTo()); if (wire == NULL) { if (!ends.contains(connectedToItem)) { ends.append(connectedToItem); } continue; } if (chained.contains(wire)) continue; chained.append(wire); } } void Wire::collectWires(QList & wires) { if (wires.contains(this)) return; wires.append(this); //DebugDialog::debug(QString("collecting wire %1").arg(this->id()) ); collectWiresAux(wires, m_connector0); collectWiresAux(wires, m_connector1); } void Wire::collectWiresAux(QList & wires, ConnectorItem * start) { foreach (ConnectorItem * toConnectorItem, start->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { qobject_cast(toConnectorItem->attachedTo())->collectWires(wires); } } } bool Wire::stickyEnabled() { QList wires; QList ends; this->collectChained(wires, ends); foreach (ConnectorItem * connector, ends) { if (connector->connectionsCount() > 0) { return false; } } return true; } bool Wire::getTrace() { return m_viewGeometry.getAnyTrace(); } bool Wire::getRouted() { return m_viewGeometry.getRouted(); } void Wire::setRouted(bool routed) { m_viewGeometry.setRouted(routed); } void Wire::setRatsnest(bool ratsnest) { m_viewGeometry.setRatsnest(ratsnest); } void Wire::setAutoroutable(bool ar) { m_viewGeometry.setAutoroutable(ar); } bool Wire::getAutoroutable() { return m_viewGeometry.getAutoroutable(); } void Wire::setNormal(bool normal) { m_viewGeometry.setNormal(normal); } bool Wire::getNormal() { return m_viewGeometry.getNormal(); } void Wire::setColor(const QColor & color, double op) { m_pen.setBrush(QBrush(color)); m_opacity = op; m_colorName = color.name(); this->update(); } void Wire::setShadowColor(QColor & color, bool restore) { m_shadowBrush = QBrush(color); m_shadowPen.setBrush(m_shadowBrush); m_bendpointPen.setBrush(m_shadowBrush); m_bendpoint2Pen.setBrush(m_shadowBrush); QList visited; if (restore) { if (m_connector0) m_connector0->restoreColor(visited); if (m_connector1) m_connector1->restoreColor(visited); } this->update(); } const QColor & Wire::color() { return m_pen.brush().color(); } void Wire::setWireWidth(double width, InfoGraphicsView * infoGraphicsView, double hoverStrokeWidth) { if (m_pen.widthF() == width) return; prepareGeometryChange(); setPenWidth(width, infoGraphicsView, hoverStrokeWidth); QList visited; if (m_connector0) m_connector0->restoreColor(visited); if (m_connector1) m_connector1->restoreColor(visited); update(); } double Wire::width() { return m_pen.widthF(); } double Wire::shadowWidth() { return m_shadowPen.widthF(); } double Wire::mils() { return 1000 * m_pen.widthF() / GraphicsUtils::SVGDPI; } void Wire::setColorString(QString colorName, double op, bool restore) { // sets a color using the name (.e. "red") // note: colorName is associated with a Fritzing color, not a Qt color QString colorString = RatsnestColors::wireColor(m_viewID, colorName); if (colorString.isEmpty()) { colorString = colorName; } QColor c; c.setNamedColor(colorString); setColor(c, op); m_colorName = colorName; QString shadowColorString = RatsnestColors::shadowColor(m_viewID, colorName); if (shadowColorString.isEmpty()) { shadowColorString = colorString; } c.setNamedColor(shadowColorString); setShadowColor(c, restore); } QString Wire::hexString() { return m_pen.brush().color().name(); } QString Wire::shadowHexString() { return m_shadowPen.brush().color().name(); } QString Wire::colorString() { return m_colorName; } void Wire::initNames() { if (colorNames.count() > 0) return; TheDash.clear(); TheDash << 10 << 8; RatDash.clear(); RatDash << 2 << 2; widths << 8 << 12 << 16 << 24 << 32 << 48; int i = 0; widthTrans.insert(widths[i++], tr("super fine (8 mil)")); widthTrans.insert(widths[i++], tr("extra thin (12 mil)")); THIN_TRACE_WIDTH = GraphicsUtils::mils2pixels(widths[i], GraphicsUtils::SVGDPI); widthTrans.insert(widths[i++], tr("thin (16 mil)")); STANDARD_TRACE_WIDTH = GraphicsUtils::mils2pixels(widths[i], GraphicsUtils::SVGDPI); widthTrans.insert(widths[i++], tr("standard (24 mil)")); widthTrans.insert(widths[i++], tr("thick (32 mil)")); widthTrans.insert(widths[i++], tr("extra thick (48 mil)")); HALF_STANDARD_TRACE_WIDTH = STANDARD_TRACE_WIDTH / 2.0; // need a list because a hash table doesn't guarantee order colorNames.append(tr("blue")); colorNames.append(tr("red")); colorNames.append(tr("black")); colorNames.append(tr("yellow")); colorNames.append(tr("green")); colorNames.append(tr("grey")); colorNames.append(tr("white")); colorNames.append(tr("orange")); colorNames.append(tr("ochre")); colorNames.append(tr("cyan")); colorNames.append(tr("brown")); colorNames.append(tr("purple")); colorNames.append(tr("pink")); // need this hash table to translate from user's language to internal color name colorTrans.insert(tr("blue"), "blue"); colorTrans.insert(tr("red"), "red"); colorTrans.insert(tr("black"), "black"); colorTrans.insert(tr("yellow"), "yellow"); colorTrans.insert(tr("green"), "green"); colorTrans.insert(tr("grey"), "grey"); colorTrans.insert(tr("white"), "white"); colorTrans.insert(tr("orange"), "orange"); colorTrans.insert(tr("ochre"), "ochre"); colorTrans.insert(tr("cyan"), "cyan"); colorTrans.insert(tr("brown"), "brown"); colorTrans.insert(tr("purple"), "purple"); colorTrans.insert(tr("pink"), "pink"); } bool Wire::hasFlag(ViewGeometry::WireFlag flag) { return m_viewGeometry.hasFlag(flag); } bool Wire::isTraceType(ViewGeometry::WireFlag flag) { return hasFlag(flag); } bool Wire::hasAnyFlag(ViewGeometry::WireFlags flags) { return m_viewGeometry.hasAnyFlag(flags); } Wire * Wire::findTraced(ViewGeometry::WireFlags flags, QList & ends) { QList chainedWires; this->collectChained(chainedWires, ends); if (ends.count() != 2) { DebugDialog::debug(QString("wire in jumper or trace must have two ends") ); return NULL; } return ConnectorItem::directlyWiredTo(ends[0], ends[1], flags); } void Wire::setWireFlags(ViewGeometry::WireFlags wireFlags) { m_viewGeometry.setWireFlags(wireFlags); } double Wire::opacity() { return m_opacity; } void Wire::setOpacity(double opacity) { m_opacity = opacity; this->update(); } bool Wire::draggingEnd() { return m_dragEnd || m_dragCurve; } void Wire::setCanChainMultiple(bool can) { m_canChainMultiple = can; } bool Wire::canChangeColor() { if (getRatsnest()) return false; if (!getTrace()) return true; return (this->m_viewID == ViewLayer::SchematicView); } void Wire::collectDirectWires(QList & wires) { bool firstRound = false; if (!wires.contains(this)) { wires.append(this); firstRound = true; } QList junctions; if (firstRound) { // collect up to any junction collectDirectWires(m_connector0, wires, junctions); collectDirectWires(m_connector1, wires, junctions); return; } // second round: deal with junctions foreach (Wire * wire, wires) { junctions << wire->connector0() << wire->connector1(); } int ix = 0; while (ix < junctions.count()) { ConnectorItem * junction = junctions.at(ix++); QSet jwires; foreach (ConnectorItem * toConnectorItem, junction->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) break; Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (!wires.contains(w)) jwires << w; bool onlyWiresConnected = true; foreach (ConnectorItem * toToConnectorItem, toConnectorItem->connectedToItems()) { if (toToConnectorItem->attachedToItemType() != ModelPart::Wire) { onlyWiresConnected = false; break; } w = qobject_cast(toToConnectorItem->attachedTo()); if (!wires.contains(w)) jwires << w; } if (!onlyWiresConnected) break; } if (jwires.count() == 1) { // there is a junction of > 2 wires and all wires leading to it except one are already on the delete list Wire * w = jwires.values().at(0); wires << w; w->collectDirectWires(w->connector0(), wires, junctions); w->collectDirectWires(w->connector1(), wires, junctions); } } } void Wire::collectDirectWires(ConnectorItem * connectorItem, QList & wires, QList & junctions) { if (connectorItem->connectionsCount() == 0) return; if (connectorItem->connectionsCount() > 1) { if (!junctions.contains(connectorItem)) junctions.append(connectorItem); return; } ConnectorItem * toConnectorItem = connectorItem->connectedToItems().at(0); if (toConnectorItem->attachedToItemType() != ModelPart::Wire) return; if (toConnectorItem->connectionsCount() != 1) { if (!junctions.contains(connectorItem)) junctions.append(connectorItem); return; } Wire * nextWire = qobject_cast(toConnectorItem->attachedTo()); if (wires.contains(nextWire)) return; wires.append(nextWire); nextWire->collectDirectWires(nextWire->otherConnector(toConnectorItem), wires, junctions); } QVariant Wire::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemSelectedChange) { if (m_partLabel) { m_partLabel->update(); } if (!m_ignoreSelectionChange) { QList chained; QList ends; collectChained(chained, ends); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView) { infoGraphicsView->setIgnoreSelectionChangeEvents(true); } // DebugDialog::debug(QString("original wire selected %1 %2").arg(value.toBool()).arg(this->id())); foreach (Wire * wire, chained) { if (wire != this ) { wire->setIgnoreSelectionChange(true); wire->setSelected(value.toBool()); wire->setIgnoreSelectionChange(false); // DebugDialog::debug(QString("wire selected %1 %2").arg(value.toBool()).arg(wire->id())); } } if (infoGraphicsView) { infoGraphicsView->setIgnoreSelectionChangeEvents(false); } } } return ItemBase::itemChange(change, value); } void Wire::cleanup() { } void Wire::getConnectedColor(ConnectorItem * connectorItem, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) { connectorItem->setBigDot(false); ItemBase::getConnectedColor(connectorItem, brush, pen, opacity, negativePenWidth, negativeOffsetRect); int count = 0; bool bendpoint = true; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) { return; } foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w->isTraceType(infoGraphicsView->getTraceFlag())) { count++; } } else { // for drawing a big dot on the end of a part connector in schematic view if the part is connected to more than one trace bendpoint = false; if (toConnectorItem->connectionsCount() > 1) { if (infoGraphicsView->hasBigDots()) { int c = 0; foreach (ConnectorItem * totoConnectorItem, toConnectorItem->connectedToItems()) { if (totoConnectorItem->attachedToItemType() == ModelPart::Wire) { Wire * w = qobject_cast(totoConnectorItem->attachedTo()); if (w && w->isTraceType(ViewGeometry::SchematicTraceFlag) && w->isTraceType(infoGraphicsView->getTraceFlag())) { c++; } } } if (c > 1) { count = 2; break; } } } count = 0; break; } } if (count == 0) { return; } // connectorItem is a bendpoint or connects to a multiply connected connector //if (!bendpoint) { //DebugDialog::debug(QString("big dot %1 %2 %3").arg(this->id()).arg(connectorItem->connectorSharedID()).arg(count)); //} brush = m_shadowBrush; opacity = 1.0; if (count > 1) { // only ever reach here when drawing a connector that is connected to more than one trace pen = m_bendpoint2Pen; negativePenWidth = m_bendpoint2Width; negativeOffsetRect = m_negativeOffsetRect; connectorItem->setBigDot(true); } else { negativeOffsetRect = m_negativeOffsetRect; negativePenWidth = m_bendpointWidth; pen = m_bendpointPen; } } void Wire::setPenWidth(double w, InfoGraphicsView * infoGraphicsView, double hoverStrokeWidth) { m_hoverStrokeWidth = hoverStrokeWidth; //DebugDialog::debug(QString("setting hoverstrokewidth %1 %2").arg(m_id).arg(m_hoverStrokeWidth)); m_pen.setWidthF(w); infoGraphicsView->getBendpointWidths(this, w, m_bendpointWidth, m_bendpoint2Width, m_negativeOffsetRect); m_bendpointPen.setWidthF(qAbs(m_bendpointWidth)); m_bendpoint2Pen.setWidthF(qAbs(m_bendpoint2Width)); m_shadowPen.setWidthF(w + 2); } bool Wire::connectionIsAllowed(ConnectorItem * to) { if (!ItemBase::connectionIsAllowed(to)) return false; Wire * w = qobject_cast(to->attachedTo()); if (w == NULL) return true; if (w->getRatsnest()) return false; return m_viewID != ViewLayer::BreadboardView; } bool Wire::isGrounded() { return ConnectorItem::isGrounded(connector0(), connector1()); } bool Wire::acceptsMouseDoubleClickConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return true; } bool Wire::acceptsMouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return true; } bool Wire::acceptsMouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { return true; } void Wire::setIgnoreSelectionChange(bool ignore) { m_ignoreSelectionChange = ignore; } bool Wire::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide) { if (prop.compare("width", Qt::CaseInsensitive) == 0) { // don't display width property hide = true; return false; } if (prop.compare("color", Qt::CaseInsensitive) == 0) { returnProp = tr("color"); if (canChangeColor()) { QComboBox * comboBox = new QComboBox(parent); comboBox->setEditable(false); comboBox->setEnabled(swappingEnabled); comboBox->setObjectName("infoViewComboBox"); int ix = 0; QString englishCurrColor = colorString(); foreach(QString transColorName, Wire::colorNames) { QString englishColorName = Wire::colorTrans.value(transColorName); bool ok = (this->m_viewID != ViewLayer::SchematicView || englishColorName.compare("white", Qt::CaseInsensitive) != 0); if (ok) { comboBox->addItem(transColorName, QVariant(englishColorName)); if (englishColorName.compare(englishCurrColor, Qt::CaseInsensitive) == 0) { comboBox->setCurrentIndex(ix); } ix++; } } connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(colorEntry(const QString &))); if (this->hasShadow()) { QCheckBox * checkBox = new QCheckBox(tr("Banded")); checkBox->setChecked(m_banded); checkBox->setObjectName("infoViewCheckBox"); connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(setBandedProp(bool))); QFrame * frame = new QFrame(parent); QHBoxLayout * hboxLayout = new QHBoxLayout; hboxLayout->addWidget(comboBox); hboxLayout->addWidget(checkBox); frame->setLayout(hboxLayout); returnWidget = frame; } else { returnWidget = comboBox; } returnValue = comboBox->currentText(); return true; } else { returnWidget = NULL; returnValue = colorString(); return true; } } return ItemBase::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide); } void Wire::colorEntry(const QString & text) { Q_UNUSED(text); QComboBox * comboBox = qobject_cast(sender()); if (comboBox == NULL) return; QString color = comboBox->itemData(comboBox->currentIndex()).toString(); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->changeWireColor(color); } } bool Wire::hasPartLabel() { return false; } ItemBase::PluralType Wire::isPlural() { return Plural; } void Wire::checkVisibility(ConnectorItem * onMe, ConnectorItem * onIt, bool connect) { if (connect) { if (!onIt->attachedTo()->isVisible()) { this->setVisible(false); } else { ConnectorItem * other = otherConnector(onMe); foreach (ConnectorItem * toConnectorItem, other->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) continue; if (!toConnectorItem->attachedTo()->isVisible()) { this->setVisible(false); break; } } } } } bool Wire::canSwitchLayers() { return false; } bool Wire::hasPartNumberProperty() { return false; } bool Wire::rotationAllowed() { return false; } bool Wire::rotation45Allowed() { return false; } void Wire::addedToScene(bool temporary) { ItemBase::addedToScene(temporary); InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView == NULL) return; infoGraphicsView->newWire(this); } void Wire::setConnectorDimensions(double width, double height) { setConnectorDimensionsAux(connector0(), width, height); setConnectorDimensionsAux(connector1(), width, height); } void Wire::setConnectorDimensionsAux(ConnectorItem * connectorItem, double width, double height) { QPointF p = connectorItem->rect().center(); QRectF r(p.x() - (width / 2), p.y() - (height / 2), width, height); connectorItem->setRect(r); connectorItem->setTerminalPoint(r.center() - r.topLeft()); //debugCompare(connectorItem->attachedTo()); } void Wire::originalConnectorDimensions(double & width, double & height) { width = m_originalConnectorRect.width(); height = m_originalConnectorRect.height(); } bool Wire::isBendpoint(ConnectorItem * connectorItem) { return connectorItem->isBendpoint(); } double Wire::hoverStrokeWidth() { return m_hoverStrokeWidth; } const QLineF & Wire::getPaintLine() { return m_line; } /*! Returns the item's line, or a null line if no line has been set. \sa setLine() */ QLineF Wire::line() const { return m_line; } /*! Sets the item's line to be the given \a line. \sa line() */ void Wire::setLine(const QLineF &line) { //if (line.length() < 0.5) { // debugInfo("zero line"); //} if (m_line == line) return; prepareGeometryChange(); m_line = line; update(); } void Wire::setLine(double x1, double y1, double x2, double y2) { setLine(QLineF(x1, y1, x2, y2)); } /*! Returns the item's pen, or a black solid 0-width pen if no pen has been set. \sa setPen() */ QPen Wire::pen() const { return m_pen; } /*! Sets the item's pen to \a pen. If no pen is set, the line will be painted using a black solid 0-width pen. \sa pen() */ void Wire::setPen(const QPen &pen) { if (pen.widthF() != m_pen.widthF()) { prepareGeometryChange(); } m_pen = pen; update(); } bool Wire::canHaveCurve() { return m_canHaveCurve && !getRatsnest(); } void Wire::dragCurve(QPointF eventPos, Qt::KeyboardModifiers) { m_bezier->recalc(eventPos); } void Wire::changeCurve(const Bezier * bezier) { prepareGeometryChange(); if (m_bezier == NULL) m_bezier = new Bezier; m_bezier->copy(bezier); update(); } bool Wire::isCurved() { return (m_bezier != NULL) && !m_bezier->isEmpty(); } const Bezier * Wire::curve() { return m_bezier; } const Bezier * Wire::undoCurve() { return &UndoBezier; } QPolygonF Wire::sceneCurve(QPointF offset) { QPolygonF poly; if (m_bezier == NULL) return poly; if (m_bezier->isEmpty()) return poly; poly.append(m_line.p1() + pos() - offset); poly.append(m_bezier->cp0() + pos() - offset); poly.append(m_bezier->cp1() + pos() - offset); poly.append(m_line.p2() + pos() - offset); return poly; } bool Wire::hasShadow() { if (getRatsnest()) return false; if (getTrace()) return false; return m_pen.widthF() != m_shadowPen.widthF(); } void Wire::cursorKeyEvent(Qt::KeyboardModifiers modifiers) { if (m_dragEnd || m_dragCurve) return; InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);; if (infoGraphicsView) { QPoint p = infoGraphicsView->mapFromGlobal(QCursor::pos()); QPointF r = infoGraphicsView->mapToScene(p); // DebugDialog::debug(QString("got key event %1").arg(keyEvent->modifiers())); updateCursor(modifiers); } } void Wire::updateCursor(Qt::KeyboardModifiers modifiers) { if (m_connectorHover) { return; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); bool segment = false; int totalConnections = 0; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { totalConnections += connectorItem->connectionsCount(); } if (totalConnections == 2 && modifiers & altOrMetaModifier()) { segment = true; foreach (ConnectorItem * connectorItem, cachedConnectorItems()) { if (connectorItem->connectionsCount() != 1) { segment = false; break; } ConnectorItem * toConnectorItem = connectorItem->connectedToItems().at(0); if (toConnectorItem->attachedToItemType() != ModelPart::Wire) { segment = false; break; } } } if (segment) { // dragging a segment of wire between bounded by two other wires CursorMaster::instance()->addCursor(this, *CursorMaster::RubberbandCursor); } else if (totalConnections == 0) { // only in breadboard view CursorMaster::instance()->addCursor(this, *CursorMaster::MoveCursor); } else if (infoGraphicsView != NULL && infoGraphicsView->curvyWiresIndicated(modifiers)) { CursorMaster::instance()->addCursor(this, *CursorMaster::MakeCurveCursor); } else if (m_displayBendpointCursor) { CursorMaster::instance()->addCursor(this, *CursorMaster::NewBendpointCursor); } } bool Wire::canChainMultiple() { return m_canChainMultiple; } ViewLayer::ViewID Wire::useViewIDForPixmap(ViewLayer::ViewID vid, bool) { if (vid == ViewLayer::BreadboardView) { return ViewLayer::IconView; } return ViewLayer::UnknownView; } void Wire::setDisplayBendpointCursor(bool dbc) { m_displayBendpointCursor = dbc; } bool Wire::banded() { return m_banded; } void Wire::setBanded(bool banded) { m_banded = banded; QList chained; QList ends; collectChained(chained, ends); foreach (Wire * w, chained) { w->m_banded = banded; w->update(); } } void Wire::setBandedProp(bool banded) { InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL) { infoGraphicsView->setProp(this, "banded", ItemBase::TranslatedPropertyNames.value("banded"), m_banded ? "Yes" : "No", banded ? "Yes" : "No", true); } } void Wire::setProp(const QString & prop, const QString & value) { if (prop.compare("banded", Qt::CaseInsensitive) == 0) { setBanded(value == "Yes"); return; } ItemBase::setProp(prop, value); } fritzing-app-0.9.2b/src/items/wire.h000066400000000000000000000234501250202676700173400ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 7000 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 07:24:08 +0200 (Mo, 29. Apr 2013) $ ********************************************************************/ #ifndef WIRE_H #define WIRE_H #include #include #include #include #include #include #include #include #include #include "itembase.h" #include "../utils/cursormaster.h" class WireAction : public QAction { Q_OBJECT public: WireAction(QAction *); WireAction(const QString & text, QObject * parent); void setWire(Wire *); Wire * wire(); protected: Wire * m_wire; }; class Wire : public ItemBase, public CursorKeyListener { Q_OBJECT public: Wire(class ModelPart *, ViewLayer::ViewID, const ViewGeometry &, long id, QMenu * itemMenu, bool initLabel); virtual ~Wire(); // for debugging //void setPos(const QPointF & pos); // for debugging QLineF line() const; virtual void setLine(const QLineF &line); inline void setLine(double x1, double y1, double x2, double y2); QPen pen() const; void setPen(const QPen &pen); void saveGeometry(); bool itemMoved(); void saveInstanceLocation(QXmlStreamWriter &); void writeGeometry(QXmlStreamWriter &); void moveItem(ViewGeometry & viewGeometry); void hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); void hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, class ConnectorItem * item); void initDragEnd(ConnectorItem * dragEnd, QPointF scenePos); void initDragCurve(QPointF scenePos); bool initNewBendpoint(QPointF scenePos, class Bezier & left, class Bezier & right); void connectedMoved(ConnectorItem * from, ConnectorItem * to, QList & already); void setLineAnd(QLineF line, QPointF pos, bool useLine); ConnectorItem * otherConnector(ConnectorItem *); ConnectorItem * connector0(); ConnectorItem * connector1(); virtual class FSvgRenderer * setUp(ViewLayer::ViewLayerID viewLayerID, const LayerHash & viewLayers, class InfoGraphicsView *); void findConnectorsUnder(); void collectChained(QList &, QList & ends); void collectWires(QList & wires); bool stickyEnabled(); void setPcbPenBrush(QBrush & brush); bool getRouted(); void setRouted(bool); void setRatsnest(bool); void setAutoroutable(bool); bool getAutoroutable(); void setNormal(bool); bool getNormal(); bool getTrace(); bool isTraceType(ViewGeometry::WireFlag); bool hasFlag(ViewGeometry::WireFlag); bool hasAnyFlag(ViewGeometry::WireFlags); void setWireFlags(ViewGeometry::WireFlags); QString colorString(); QString hexString(); QString shadowHexString(); void setColorString(QString, double opacity, bool restore); virtual void setColor(const QColor &, double opacity); double opacity(); void setOpacity(double opacity); const QColor & color(); void setWireWidth(double width, InfoGraphicsView *, double hoverStrokeWidth); void setPenWidth(double width, InfoGraphicsView *, double hoverStrokeWidth); double width(); double shadowWidth(); double mils(); void setExtras(QDomElement &, InfoGraphicsView *); Wire * findTraced(ViewGeometry::WireFlags flags, QList & ends); bool draggingEnd(); void simpleConnectedMoved(ConnectorItem * to); void simpleConnectedMoved(ConnectorItem * from, ConnectorItem * to); void setCanChainMultiple(bool); bool canChangeColor(); void collectDirectWires(QList & wires); bool isGrounded(); bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); bool hasPartLabel(); PluralType isPlural(); virtual bool canSwitchLayers(); void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); void paintBody(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); bool hasPartNumberProperty(); bool rotationAllowed(); bool rotation45Allowed(); void addedToScene(bool temporary); void setConnectorDimensions(double width, double height); void originalConnectorDimensions(double & width, double & height); double hoverStrokeWidth(); QPainterPath hoverShape() const; QPainterPath shape() const; QRectF boundingRect() const; virtual const QLineF & getPaintLine(); bool canHaveCurve(); void changeCurve(const class Bezier *); bool isCurved(); const class Bezier * curve(); const class Bezier * undoCurve(); QPolygonF sceneCurve(QPointF offset); bool hasShadow(); bool canChainMultiple(); void cursorKeyEvent(Qt::KeyboardModifiers modifiers); void setDisplayBendpointCursor(bool); bool banded(); void setBanded(bool); void setProp(const QString & prop, const QString & value); protected slots: void colorEntry(const QString & text); void setBandedProp(bool); public: static double STANDARD_TRACE_WIDTH; static double HALF_STANDARD_TRACE_WIDTH; static double THIN_TRACE_WIDTH; public: static void initNames(); static void cleanup(); static QVector TheDash; protected: void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEventAux(QPointF eventPos, Qt::KeyboardModifiers); void dragCurve(QPointF eventPos, Qt::KeyboardModifiers); void mousePressEvent(QGraphicsSceneMouseEvent *event); void paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void initEnds(const ViewGeometry &, QRectF defaultRect, class InfoGraphicsView *); void connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect); void mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); void mouseDoubleClickConnectorEvent(ConnectorItem *); void mouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); void mouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); bool acceptsMouseDoubleClickConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); bool acceptsMouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); bool acceptsMouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual class FSvgRenderer * setUpConnectors(class ModelPart *, ViewLayer::ViewID); void collectChained(ConnectorItem * connectorItem, QList & chained, QList & ends); void setConnector0Rect(); void setConnector1Rect(); void collectWiresAux(QList & wires, ConnectorItem * start); void setShadowColor(QColor &, bool restore); void calcNewLine(ConnectorItem * from, ConnectorItem * to, QPointF & p1, QPointF & p2); void collectDirectWires(ConnectorItem * connectorItem, QList & wires, QList & junctions); QVariant itemChange(GraphicsItemChange change, const QVariant &value); void getConnectedColor(ConnectorItem *, QBrush &, QPen &, double & opacity, double & negativePenWidth, bool & negativeOffsetRect); bool connectionIsAllowed(ConnectorItem *); bool releaseDrag(); void setIgnoreSelectionChange(bool); virtual void setColorFromElement(QDomElement & element); void checkVisibility(ConnectorItem * onMe, ConnectorItem * onIt, bool connect); void setConnectorDimensionsAux(ConnectorItem *, double width, double height); bool isBendpoint(ConnectorItem * connectorItem); QPainterPath shapeAux(double width) const; void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ); void hoverEnterEvent( QGraphicsSceneHoverEvent * event ); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); void updateCursor(Qt::KeyboardModifiers); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); protected: QLineF m_line; QPen m_pen; QPointF m_wireDragOrigin; bool m_dragEnd; bool m_dragCurve; bool m_drag0; QPointer m_connectorHover; QPointer m_connector0; QPointer m_connector1; QString m_colorName; QPen m_shadowPen; QBrush m_shadowBrush; QPen m_bendpointPen; QPen m_bendpoint2Pen; double m_bendpointWidth; double m_bendpoint2Width; bool m_negativeOffsetRect; double m_opacity; bool m_canChainMultiple; bool m_ignoreSelectionChange; bool m_markedDeleted; QRectF m_originalConnectorRect; double m_hoverStrokeWidth; bool m_canHaveCurve; class Bezier * m_bezier; bool m_displayBendpointCursor; bool m_banded; public: static QStringList colorNames; static QHash colorTrans; static QHash widthTrans; static QList widths; signals: void wireChangedSignal(Wire* me, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, ConnectorItem * from, ConnectorItem * to); void wireChangedCurveSignal(Wire* me, const Bezier * oldB, const Bezier * newB, bool triggerFirstTime); void wireSplitSignal(Wire* me, QPointF newPos, QPointF oldPos, const QLineF & oldLine); void wireJoinSignal(Wire* me, ConnectorItem * clickedConnectorItem); }; #endif fritzing-app-0.9.2b/src/layerattributes.cpp000066400000000000000000000030361250202676700210250ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6926 $: $Author: irascibl@gmail.com $: $Date: 2013-03-10 21:27:34 +0100 (So, 10. Mrz 2013) $ ********************************************************************/ #include "layerattributes.h" #include "debugdialog.h" LayerAttributes::LayerAttributes() { orientation = Qt::Vertical; createShape = true; } const QString & LayerAttributes::filename() { return m_filename; } void LayerAttributes::setFilename(const QString & filename) { m_filename = filename; } const QByteArray & LayerAttributes::loaded() const { return m_loaded; } void LayerAttributes::clearLoaded() { m_loaded.clear(); } void LayerAttributes::setLoaded(const QByteArray & loaded) { m_loaded = loaded; } fritzing-app-0.9.2b/src/layerattributes.h000066400000000000000000000032111250202676700204650ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #ifndef LAYERATTRIBUTES_H #define LAYERATTRIBUTES_H #include #include #include "viewlayer.h" class LayerAttributes { public: LayerAttributes(); const QString & filename(); void setFilename(const QString &); const QByteArray & loaded() const; void clearLoaded(); void setLoaded(const QByteArray &); protected: QString m_filename; QByteArray m_loaded; public: QString error; ViewLayer::ViewID viewID; ViewLayer::ViewLayerID viewLayerID; ViewLayer::ViewLayerPlacement viewLayerPlacement; bool doConnectors; Qt::Orientations orientation; bool createShape; }; #endif fritzing-app-0.9.2b/src/lib/000077500000000000000000000000001250202676700156425ustar00rootroot00000000000000fritzing-app-0.9.2b/src/lib/qtsysteminfo/000077500000000000000000000000001250202676700204075ustar00rootroot00000000000000fritzing-app-0.9.2b/src/lib/qtsysteminfo/QtSystemInfo.cpp000066400000000000000000000337211250202676700235260ustar00rootroot00000000000000/* * File: QtSystemInfo.cpp * Author: Adrian Łubik (adrian5632@gmail.com) * License: GNU LGPL v2 or newer * Copyright: (c) 2010 Adrian Łubik */ #include "QtSystemInfo.h" #include static const char *UNKNOWN = "UNKNOWN"; class QtSystemInfoPrivate { public: QtSystemInfoPrivate() {} virtual ~QtSystemInfoPrivate() {} virtual QtSystemInfo::ArchitectureType architecture() = 0; virtual QtSystemInfo::SystemType systemType() = 0; virtual QString architectureName() = 0; virtual QString kernelName() = 0; virtual QString kernelVersion() = 0; virtual QString systemName() = 0; virtual QString systemVersion() = 0; }; // -------------------------------------------------- // // Any Unix // // -------------------------------------------------- // #ifdef Q_OS_UNIX #include class QtSystemInfoUnix: public QtSystemInfoPrivate { public: QtSystemInfoUnix():m_kernelName(UNKNOWN), m_kernelVersion(UNKNOWN), m_architectureName(UNKNOWN), m_architecture(QtSystemInfo::UnknownArchitectureType) { struct utsname buffer; if (uname(&buffer) == 0) { m_kernelVersion = buffer.release; m_kernelName = buffer.sysname; m_architectureName = buffer.machine; if (m_architectureName == "i386") m_architecture = QtSystemInfo::I386; else if (m_architectureName == "i486") m_architecture = QtSystemInfo::I486; else if (m_architectureName == "i586") m_architecture = QtSystemInfo::I586; else if (m_architectureName == "i686") m_architecture = QtSystemInfo::I686; else if (m_architectureName == "x86_64") m_architecture = QtSystemInfo::X86_64; else if (m_architectureName == "ppc") m_architecture = QtSystemInfo::MPPC; else if (m_architectureName == "ppc64") m_architecture = QtSystemInfo::MPPC64; } } virtual QString architectureName() { return m_architectureName; } virtual QtSystemInfo::ArchitectureType architecture() { return m_architecture; } virtual QString kernelName() { return m_kernelName; } virtual QString kernelVersion() { return m_kernelVersion; } virtual QtSystemInfo::SystemType systemType() { return QtSystemInfo::UnknownUnix; } virtual QString systemName() { return "Unix"; } virtual QString systemVersion() { return UNKNOWN; } private: QString m_kernelName; QString m_kernelVersion; QString m_architectureName; QtSystemInfo::ArchitectureType m_architecture; }; #endif // -------------------------------------------------- // // Mac OS X // // -------------------------------------------------- // #ifdef Q_OS_MAC #include class QtSystemInfoMac: public QtSystemInfoUnix { public: QtSystemInfoMac() {} virtual QString systemName() { return "Mac OS X"; } virtual QString systemVersion() { switch (QSysInfo::MacintoshVersion) { case QSysInfo::MV_10_0: return "10.0"; case QSysInfo::MV_10_1: return "10.1"; case QSysInfo::MV_10_2: return "10.2"; case QSysInfo::MV_10_3: return "10.3"; case QSysInfo::MV_10_4: return "10.4"; case QSysInfo::MV_10_5: return "10.5"; case QSysInfo::MV_10_6: return "10.6"; default: return UNKNOWN; } } virtual QtSystemInfo::SystemType systemType() { return QtSystemInfo::MacOSX; } }; #endif // -------------------------------------------------- // // Linux // // -------------------------------------------------- // #ifdef Q_OS_LINUX #include #include static bool scanSuSEReleaseFile(QString &name, QString &version) { name.clear(); version.clear(); QFile releaseFile("/etc/SuSE-release"); if (releaseFile.exists()) { name = "SuSE"; if (releaseFile.open(QFile::ReadOnly)) { while (!releaseFile.atEnd()) { QString line = releaseFile.readLine(500).trimmed(); if (line.startsWith("VERSION = ")) { version = line.remove(0, 10); releaseFile.close(); return true; } } releaseFile.close(); } } return false; } static bool scanRedHatReleaseFile(QString &name, QString &version) { name.clear(); version.clear(); QFile releaseFile("/etc/redhat-release"); if (releaseFile.exists() && releaseFile.open(QFile::ReadOnly)) { QRegExp fedoraRegExp("(^Fedora)\\s+[release]*\\s+([0-9]{1,2})\\s+" ); QRegExp pclinuxosRegExp("(^PCLinuxOS)\\s+release\\s+([0-9]{4})\\s+\\(PCLinuxOS\\)\\s+for"); QString line = releaseFile.readLine(500); releaseFile.close(); if (line.contains(fedoraRegExp)) { name = fedoraRegExp.cap(1); version = fedoraRegExp.cap(2); return true; } else if (line.contains(pclinuxosRegExp)) { name = pclinuxosRegExp.cap(1); version = pclinuxosRegExp.cap(2); return true; } } return false; } static bool scanLSBReleaseFile(QString &name, QString &version) { name.clear(); version.clear(); QFile releaseFile("/etc/lsb-release"); if (releaseFile.exists() && releaseFile.open(QFile::ReadOnly)) { while (!releaseFile.atEnd()) { QString line = releaseFile.readLine(500).trimmed(); if (line.startsWith("DISTRIB_ID=") && line.count() > 11) { name = line.mid(11); if (!name.isEmpty() && !version.isEmpty()) { releaseFile.close(); return true; } } else if (line.startsWith("DISTRIB_RELEASE=") && line.count() > 16) { version = line.mid(16); if (!name.isEmpty() && !version.isEmpty()) { releaseFile.close(); return true; } } } } return false; } static bool scanDebianReleaseFile(QString &name, QString &version) { name.clear(); version.clear(); QFile releaseFile("/etc/debian_version"); if (releaseFile.exists() && releaseFile.open(QFile::ReadOnly)) { QRegExp debianRegExp("(^[0-9]{1}\\.[0-9]\\s*$)"); QString line = releaseFile.readLine(100); releaseFile.close(); if (line.startsWith("lenny/sid")) { name = "Debian"; version = "4.0"; return true; } else if (line.contains(debianRegExp)) { name = "Debian"; version = debianRegExp.cap(1); return true; } } return false; } class QtSystemInfoLinux: public QtSystemInfoUnix { public: QtSystemInfoLinux() { if (scanSuSEReleaseFile(m_distributionName, m_distributionVersion)) return; if (scanRedHatReleaseFile(m_distributionName, m_distributionVersion)) return; if (scanLSBReleaseFile(m_distributionName, m_distributionVersion)) return; if (scanDebianReleaseFile(m_distributionName, m_distributionVersion)) return; m_distributionName = "Linux"; m_distributionVersion = UNKNOWN; } virtual QtSystemInfo::SystemType systemType() { return QtSystemInfo::Linux; } virtual QString systemName() { return m_distributionName; } virtual QString systemVersion() { return m_distributionVersion; } private: QString m_distributionName; QString m_distributionVersion; }; #endif // -------------------------------------------------- // // BSD // // -------------------------------------------------- // #if defined(Q_OS_BSD4) && !defined(Q_OS_DARWIN) #include #include static QString getFreeBSDDistro() { if (QFile::exists("/usr/PCBSD")) return "PCBSD"; return "FreeBSD"; } class QtSystemInfoBSD: public QtSystemInfoUnix { public: QtSystemInfoBSD() {} virtual QtSystemInfo::SystemType systemType() { # if defined(Q_OS_OPENBSD) return QtSystemInfo::OpenBSD; # elif defined(Q_OS_NETBSD) return QtSystemInfo::NetBSD; # elif defined(Q_OS_FREEBSD) return QtSystemInfo::FreeBSD; # else return QtSystemInfo::UnknownBSD; # endif } virtual QString systemName() { # if defined(Q_OS_OPENBSD) return "OpenBSD"; # elif defined(Q_OS_NETBSD) return "NetBSD"; # elif defined(Q_OS_FREEBSD) return getFreeBSDDistro(); # else return "BSD4"; # endif } virtual QString systemVersion() { QString version = kernelVersion(); QRegExp versionRx("^(\\d+\\.\\d+(\\.\\d+)?)"); if (version.contains(versionRx)) version = versionRx.cap(1); return version; } }; #endif // -------------------------------------------------- // // Windows // // -------------------------------------------------- // #ifdef Q_OS_WIN #include class QtSystemInfoWindows: public QtSystemInfoPrivate { public: QtSystemInfoWindows() {} virtual QtSystemInfo::SystemType systemType() { # ifdef Q_OS_WINCE return QtSystemInfo::WindowsCE; # else return QtSystemInfo::Windows; # endif } virtual QtSystemInfo::ArchitectureType architecture() { # if defined(Q_OS_WINCE) return QtSystemInfo::UnknownArchitectureType; # elif defined(Q_OS_WIN64) return QtSystemInfo::X86_64; # else return QtSystemInfo::I386; # endif } virtual QString architectureName() { switch (architecture()) { case QtSystemInfo::X86_64: return "x86_64"; case QtSystemInfo::I386: return "i386"; default: return UNKNOWN; } } virtual QString kernelName() { if (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) return "NT"; else if (QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) return "CE"; return UNKNOWN; } virtual QString kernelVersion() { switch (QSysInfo::WindowsVersion) { case QSysInfo::WV_4_0: return "4.0"; case QSysInfo::WV_5_0: return "5.0"; case QSysInfo::WV_5_1: return "5.1"; case QSysInfo::WV_5_2: return "5.2"; case QSysInfo::WV_6_0: return "6.0"; case QSysInfo::WV_6_1: return "6.1"; case QSysInfo::WV_CE: return "1.0"; case QSysInfo::WV_CENET: return ".NET"; case QSysInfo::WV_CE_5: return "5.x"; case QSysInfo::WV_CE_6: return "6.x"; default: return UNKNOWN; } } virtual QString systemName() { # ifdef Q_OS_WINCE return "Windows CE"; # else return "Windows"; # endif } virtual QString systemVersion() { switch (QSysInfo::WindowsVersion) { case QSysInfo::WV_NT: return "NT"; case QSysInfo::WV_2000: return "2000"; case QSysInfo::WV_XP: return "XP"; case QSysInfo::WV_2003: # ifdef Q_OS_WIN64 return "XP Proffessional 64"; # else return "2003 Server"; # endif case QSysInfo::WV_VISTA: return "Vista / Server 2008"; case QSysInfo::WV_WINDOWS7: return "7 / Server 2008 R2"; default: return UNKNOWN; } } }; #endif // -------------------------------------------------- // // Main class // // -------------------------------------------------- // QtSystemInfo::QtSystemInfo(QObject *parent): QObject(parent), #if defined(Q_OS_UNIX) # if defined(Q_OS_MAC) d(new QtSystemInfoMac()) # elif defined(Q_OS_LINUX) d(new QtSystemInfoLinux()) # elif defined(Q_OS_BSD4) d(new QtSystemInfoBSD) # else d(new QtSystemInfoUnix()) # endif #elif defined(Q_OS_WIN) d(new QtSystemInfoWindows()) #endif { } QtSystemInfo::~QtSystemInfo() { delete d; } QString QtSystemInfo::architectureName() const { return d->architectureName(); } QtSystemInfo::ArchitectureType QtSystemInfo::architecture() const { return d->architecture(); } QString QtSystemInfo::kernelVersion() const { return d->kernelVersion(); } QString QtSystemInfo::kernelName() const { return d->kernelName(); } QString QtSystemInfo::systemName() const { return d->systemName(); } QString QtSystemInfo::systemVersion() const { return d->systemVersion(); } QtSystemInfo::SystemType QtSystemInfo::systemType() const { return d->systemType(); } QString QtSystemInfo::getSystemInformation(QString format) { if (format.isEmpty()) format = "%SYS_NAME %SYS_VERSION (%KERN_NAME %KERN_VERSION %ARCH)."; format.replace("%SYS_NAME", systemName(), Qt::CaseInsensitive); format.replace("%SYS_VERSION", systemVersion(), Qt::CaseInsensitive); format.replace("%SYS_RELEASE", systemVersion(), Qt::CaseInsensitive); format.replace("%KERN_NAME", kernelName(), Qt::CaseInsensitive); format.replace("%KERN_RELEASE", kernelVersion(), Qt::CaseInsensitive); format.replace("%KERN_VERSION", kernelVersion(), Qt::CaseInsensitive); format.replace("%ARCH", architectureName(), Qt::CaseInsensitive); return format; } fritzing-app-0.9.2b/src/lib/qtsysteminfo/QtSystemInfo.h000066400000000000000000000043201250202676700231640ustar00rootroot00000000000000/* * File: QtSystemInfo.h * Author: Adrian Łubik (adrian5632@gmail.com) * License: GNU LGPL v2 or newer * Copyright: (c) 2010 Adrian Łubik */ #ifndef QTSYSTEMINFO_H #define QTSYSTEMINFO_H #define QTSYSTEMINFO_VERSION 0x009000 #include #include class QtSystemInfoPrivate; class QtSystemInfo: public QObject { public: enum SystemType { UnknownType = -1, UnknownUnix, MacOSX, Windows, WindowsCE, Linux, UnknownBSD, FreeBSD, OpenBSD, NetBSD }; enum ArchitectureType { UnknownArchitectureType = -1, I386, I486, I586, I686, X86_64, MPPC, MPPC64 }; QtSystemInfo(QObject *parent = 0); ~QtSystemInfo(); /** * @return Name of currently running system's kernel. */ QString kernelName() const; /** * @return Version of currently running system's kernel. */ QString kernelVersion() const; /** * @return Architecture of the running system. */ QString architectureName() const; /** * @return Type of currently running system's architecture. */ ArchitectureType architecture() const; /** * @return Type of currently running system. */ SystemType systemType() const; /** * @return Name of currently running system. */ QString systemName() const; /** * @return Version of currently running system. */ QString systemVersion() const; /** * @param format A format of the information to be returned. * The following strings will be replaced: * %SYS_NAME - replaced with system name. * %SYS_VERSION - replaced with system version. * %KERN_NAME - replaced with kernel name. * %KERN_VERSION - replaced with kernel version. * %ARCH - replaced with architecture. * If no format given, the method will default to: %SYS_NAME %SYS_VERSION (%KERN_NAME %KERN_VERSION %ARCH). * * @return Formatted information about the running system. */ QString getSystemInformation(QString format = QString()); private: QtSystemInfoPrivate *d; }; #endif fritzing-app-0.9.2b/src/lib/quazip/000077500000000000000000000000001250202676700171535ustar00rootroot00000000000000fritzing-app-0.9.2b/src/lib/quazip/crypt.h000066400000000000000000000113031250202676700204630ustar00rootroot00000000000000/* crypt.h -- base code for crypt/uncrypt ZIPfile Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant This code is a modified version of crypting code in Infozip distribution The encryption/decryption parts of this source code (as opposed to the non-echoing password parts) were originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). If you don't need crypting in your application, just define symbols NOCRYPT and NOUNCRYPT. This code support the "Traditional PKWARE Encryption". The new AES encryption added on Zip format by Winzip (see the page http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong Encryption is not supported. */ #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) /*********************************************************************** * Return the next byte in the pseudo-random sequence */ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) { #ifndef _WINDOWS (void) pcrc_32_tab; /* avoid "unused parameter" warning */ #endif unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; { register int keyshift = (int)((*(pkeys+1)) >> 24); (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); } return c; } /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; *(pkeys+2) = 878082192L; while (*passwd != '\0') { update_keys(pkeys,pcrc_32_tab,(int)*passwd); passwd++; } } #define zdecode(pkeys,pcrc_32_tab,c) \ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) #define zencode(pkeys,pcrc_32_tab,c,t) \ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED #define RAND_HEAD_LEN 12 /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ # endif static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) const char *passwd; /* password string */ unsigned char *buf; /* where to write header */ int bufSize; unsigned long* pkeys; const unsigned long* pcrc_32_tab; unsigned long crcForCrypting; { int n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ unsigned char header[RAND_HEAD_LEN-2]; /* random header */ static unsigned calls = 0; /* ensure different random header each time */ if (bufSize> 7) & 0xff; header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); } /* Encrypt random header (last two bytes is high word of crc) */ init_keys(passwd, pkeys, pcrc_32_tab); for (n = 0; n < RAND_HEAD_LEN-2; n++) { buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); } buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); return n; } #endif fritzing-app-0.9.2b/src/lib/quazip/ioapi.c000066400000000000000000000102771250202676700204270ustar00rootroot00000000000000/* ioapi.c -- IO base function header for compress/uncompress .zip files using zlib + zip or unzip API Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant */ #include #include #include #include #include "ioapi.h" /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif voidpf ZCALLBACK fopen_file_func OF(( voidpf opaque, const char* filename, int mode)); uLong ZCALLBACK fread_file_func OF(( voidpf opaque, voidpf stream, void* buf, uLong size)); uLong ZCALLBACK fwrite_file_func OF(( voidpf opaque, voidpf stream, const void* buf, uLong size)); long ZCALLBACK ftell_file_func OF(( voidpf opaque, voidpf stream)); long ZCALLBACK fseek_file_func OF(( voidpf opaque, voidpf stream, uLong offset, int origin)); int ZCALLBACK fclose_file_func OF(( voidpf opaque, voidpf stream)); int ZCALLBACK ferror_file_func OF(( voidpf opaque, voidpf stream)); voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) voidpf opaque; const char* filename; int mode; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif FILE* file = NULL; const char* mode_fopen = NULL; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; else if (mode & ZLIB_FILEFUNC_MODE_CREATE) mode_fopen = "wb"; if ((filename!=NULL) && (mode_fopen != NULL)) file = fopen(filename, mode_fopen); return file; } uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) voidpf opaque; voidpf stream; void* buf; uLong size; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif uLong ret; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) voidpf opaque; voidpf stream; const void* buf; uLong size; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif uLong ret; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } long ZCALLBACK ftell_file_func (opaque, stream) voidpf opaque; voidpf stream; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif long ret; ret = ftell((FILE *)stream); return ret; } long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) voidpf opaque; voidpf stream; uLong offset; int origin; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif int fseek_origin=0; long ret; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; case ZLIB_FILEFUNC_SEEK_END : fseek_origin = SEEK_END; break; case ZLIB_FILEFUNC_SEEK_SET : fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; fseek((FILE *)stream, offset, fseek_origin); return ret; } int ZCALLBACK fclose_file_func (opaque, stream) voidpf opaque; voidpf stream; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif int ret; ret = fclose((FILE *)stream); return ret; } int ZCALLBACK ferror_file_func (opaque, stream) voidpf opaque; voidpf stream; { #ifndef _WINDOWS (void) opaque; /* avoid "unused parameter" warning */ #endif int ret; ret = ferror((FILE *)stream); return ret; } void fill_fopen_filefunc (pzlib_filefunc_def) zlib_filefunc_def* pzlib_filefunc_def; { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } fritzing-app-0.9.2b/src/lib/quazip/ioapi.h000066400000000000000000000050271250202676700204310ustar00rootroot00000000000000/* ioapi.h -- IO base function header for compress/uncompress .zip files using zlib + zip or unzip API Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant */ #ifndef _ZLIBIOAPI_H #define _ZLIBIOAPI_H #define ZLIB_FILEFUNC_SEEK_CUR (1) #define ZLIB_FILEFUNC_SEEK_END (2) #define ZLIB_FILEFUNC_SEEK_SET (0) #define ZLIB_FILEFUNC_MODE_READ (1) #define ZLIB_FILEFUNC_MODE_WRITE (2) #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) #define ZLIB_FILEFUNC_MODE_EXISTING (4) #define ZLIB_FILEFUNC_MODE_CREATE (8) #ifndef ZCALLBACK #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) #define ZCALLBACK CALLBACK #else #define ZCALLBACK #endif #endif #ifdef __cplusplus extern "C" { #endif #ifdef _Z_OF #undef OF #define OF _Z_OF #endif typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef struct zlib_filefunc_def_s { open_file_func zopen_file; read_file_func zread_file; write_file_func zwrite_file; tell_file_func ztell_file; seek_file_func zseek_file; close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc_def; void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) #ifdef __cplusplus } #endif #endif fritzing-app-0.9.2b/src/lib/quazip/quazip.cpp000066400000000000000000000202171250202676700211720ustar00rootroot00000000000000/* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include #include "quazip.h" QuaZip::QuaZip(): fileNameCodec(QTextCodec::codecForLocale()), commentCodec(QTextCodec::codecForLocale()), mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK) { } QuaZip::QuaZip(const QString& zipName): fileNameCodec(QTextCodec::codecForLocale()), commentCodec(QTextCodec::codecForLocale()), zipName(zipName), mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK) { } QuaZip::~QuaZip() { if(isOpen()) close(); } bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) { zipError=UNZ_OK; if(isOpen()) { qWarning("QuaZip::open(): ZIP already opened"); return false; } switch(mode) { case mdUnzip: unzFile_f=unzOpen2(QFile::encodeName(zipName).constData(), ioApi); if(unzFile_f!=NULL) { this->mode=mode; return true; } else { zipError=UNZ_OPENERROR; return false; } case mdCreate: case mdAppend: case mdAdd: zipFile_f=zipOpen2(QFile::encodeName(zipName).constData(), mode==mdCreate?APPEND_STATUS_CREATE: mode==mdAppend?APPEND_STATUS_CREATEAFTER: APPEND_STATUS_ADDINZIP, NULL, ioApi); if(zipFile_f!=NULL) { this->mode=mode; return true; } else { zipError=UNZ_OPENERROR; return false; } default: qWarning("QuaZip::open(): unknown mode: %d", (int)mode); return false; break; } } void QuaZip::close() { zipError=UNZ_OK; switch(mode) { case mdNotOpen: qWarning("QuaZip::close(): ZIP is not open"); return; case mdUnzip: zipError=unzClose(unzFile_f); break; case mdCreate: case mdAppend: case mdAdd: zipError=zipClose(zipFile_f, commentCodec->fromUnicode(comment).constData()); break; default: qWarning("QuaZip::close(): unknown mode: %d", (int)mode); return; } if(zipError==UNZ_OK) mode=mdNotOpen; } void QuaZip::setZipName(const QString& zipName) { if(isOpen()) { qWarning("QuaZip::setZipName(): ZIP is already open!"); return; } this->zipName=zipName; } int QuaZip::getEntriesCount()const { QuaZip *fakeThis=(QuaZip*)this; // non-const fakeThis->zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode"); return -1; } unz_global_info globalInfo; if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK) return zipError; return (int)globalInfo.number_entry; } QString QuaZip::getComment()const { QuaZip *fakeThis=(QuaZip*)this; // non-const fakeThis->zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode"); return QString(); } unz_global_info globalInfo; QByteArray comment; if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK) return QString(); comment.resize(globalInfo.size_comment); if((fakeThis->zipError=unzGetGlobalComment(unzFile_f, comment.data(), comment.size()))!=UNZ_OK) return QString(); return commentCodec->toUnicode(comment); } bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs) { zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode"); return false; } if(fileName.isNull()) { hasCurrentFile_f=false; return true; } // Unicode-aware reimplementation of the unzLocateFile function if(unzFile_f==NULL) { zipError=UNZ_PARAMERROR; return false; } if(fileName.length()>MAX_FILE_NAME_LENGTH) { zipError=UNZ_PARAMERROR; return false; } bool sens; if(cs==csDefault) { #ifdef Q_OS_WIN sens=false; #else sens=true; #endif } else sens=cs==csSensitive; QString lower, current; if(!sens) lower=fileName.toLower(); hasCurrentFile_f=false; for(bool more=goToFirstFile(); more; more=goToNextFile()) { current=getCurrentFileName(); if(current.isNull()) return false; if(sens) { if(current==fileName) break; } else { if(current.toLower()==lower) break; } } return hasCurrentFile_f; } bool QuaZip::goToFirstFile() { zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); return false; } zipError=unzGoToFirstFile(unzFile_f); hasCurrentFile_f=zipError==UNZ_OK; return hasCurrentFile_f; } bool QuaZip::goToNextFile() { zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); return false; } zipError=unzGoToNextFile(unzFile_f); hasCurrentFile_f=zipError==UNZ_OK; if(zipError==UNZ_END_OF_LIST_OF_FILE) zipError=UNZ_OK; return hasCurrentFile_f; } bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const { QuaZip *fakeThis=(QuaZip*)this; // non-const fakeThis->zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode"); return false; } unz_file_info info_z; QByteArray fileName; QByteArray extra; QByteArray comment; if(info==NULL) return false; if(!isOpen()||!hasCurrentFile()) return false; if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK) return false; fileName.resize(info_z.size_filename); extra.resize(info_z.size_file_extra); comment.resize(info_z.size_file_comment); if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL, fileName.data(), fileName.size(), extra.data(), extra.size(), comment.data(), comment.size()))!=UNZ_OK) return false; info->versionCreated=info_z.version; info->versionNeeded=info_z.version_needed; info->flags=info_z.flag; info->method=info_z.compression_method; info->crc=info_z.crc; info->compressedSize=info_z.compressed_size; info->uncompressedSize=info_z.uncompressed_size; info->diskNumberStart=info_z.disk_num_start; info->internalAttr=info_z.internal_fa; info->externalAttr=info_z.external_fa; info->name=fileNameCodec->toUnicode(fileName); info->comment=commentCodec->toUnicode(comment); info->extra=extra; info->dateTime=QDateTime( QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday), QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec)); return true; } QString QuaZip::getCurrentFileName()const { QuaZip *fakeThis=(QuaZip*)this; // non-const fakeThis->zipError=UNZ_OK; if(mode!=mdUnzip) { qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode"); return QString(); } if(!isOpen()||!hasCurrentFile()) return QString(); QByteArray fileName(MAX_FILE_NAME_LENGTH, 0); if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL, fileName.data(), fileName.size(), NULL, 0, NULL, 0))!=UNZ_OK) return QString(); return fileNameCodec->toUnicode(fileName.constData()); } fritzing-app-0.9.2b/src/lib/quazip/quazip.h000066400000000000000000000354241250202676700206450ustar00rootroot00000000000000#ifndef QUA_ZIP_H #define QUA_ZIP_H /* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include #include #include "zip.h" #include "unzip.h" #include "quazipfileinfo.h" // just in case it will be defined in the later versions of the ZIP/UNZIP #ifndef UNZ_OPENERROR // define additional error code #define UNZ_OPENERROR -1000 #endif /// ZIP archive. /** \class QuaZip quazip.h * This class implements basic interface to the ZIP archive. It can be * used to read table contents of the ZIP archive and retreiving * information about the files inside it. * * You can also use this class to open files inside archive by passing * pointer to the instance of this class to the constructor of the * QuaZipFile class. But see QuaZipFile::QuaZipFile(QuaZip*, QObject*) * for the possible pitfalls. * * This class is indended to provide interface to the ZIP subpackage of * the ZIP/UNZIP package as well as to the UNZIP subpackage. But * currently it supports only UNZIP. * * The use of this class is simple - just create instance using * constructor, then set ZIP archive file name using setFile() function * (if you did not passed the name to the constructor), then open() and * then use different functions to work with it! Well, if you are * paranoid, you may also wish to call close before destructing the * instance, to check for errors on close. * * You may also use getUnzFile() and getZipFile() functions to get the * ZIP archive handle and use it with ZIP/UNZIP package API directly. * * This class supports localized file names inside ZIP archive, but you * have to set up proper codec with setCodec() function. By default, * locale codec will be used, which is probably ok for UNIX systems, but * will almost certainly fail with ZIP archives created in Windows. This * is because Windows ZIP programs have strange habit of using DOS * encoding for file names in ZIP archives. For example, ZIP archive * with cyrillic names created in Windows will have file names in \c * IBM866 encoding instead of \c WINDOWS-1251. I think that calling one * function is not much trouble, but for true platform independency it * would be nice to have some mechanism for file name encoding auto * detection using locale information. Does anyone know a good way to do * it? **/ class QuaZip { public: /// Useful constants. enum Constants { MAX_FILE_NAME_LENGTH=256 /**< Maximum file name length. Taken from \c UNZ_MAXFILENAMEINZIP constant in unzip.c. */ }; /// Open mode of the ZIP file. enum Mode { mdNotOpen, ///< ZIP file is not open. This is the initial mode. mdUnzip, ///< ZIP file is open for reading files inside it. mdCreate, ///< ZIP file was created with open() call. mdAppend, /**< ZIP file was opened in append mode. This refers to * \c APPEND_STATUS_CREATEAFTER mode in ZIP/UNZIP package * and means that zip is appended to some existing file * what is useful when that file contains * self-extractor code. This is obviously \em not what * you whant to use to add files to the existing ZIP * archive. **/ mdAdd ///< ZIP file was opened for adding files in the archive. }; /// Case sensitivity for the file names. /** This is what you specify when accessing files in the archive. * Works perfectly fine with any characters thanks to Qt's great * unicode support. This is different from ZIP/UNZIP API, where * only US-ASCII characters was supported. **/ enum CaseSensitivity { csDefault=0, ///< Default for platform. Case sensitive for UNIX, not for Windows. csSensitive=1, ///< Case sensitive. csInsensitive=2 ///< Case insensitive. }; private: QTextCodec *fileNameCodec, *commentCodec; QString zipName; QString comment; Mode mode; union { unzFile unzFile_f; zipFile zipFile_f; }; bool hasCurrentFile_f; int zipError; // not (and will not be) implemented QuaZip(const QuaZip& that); // not (and will not be) implemented QuaZip& operator=(const QuaZip& that); public: /// Constructs QuaZip object. /** Call setName() before opening constructed object. */ QuaZip(); /// Constructs QuaZip object associated with ZIP file \a zipName. QuaZip(const QString& zipName); /// Destroys QuaZip object. /** Calls close() if necessary. */ ~QuaZip(); /// Opens ZIP file. /** Argument \a ioApi specifies IO function set for ZIP/UNZIP * package to use. See unzip.h, zip.h and ioapi.h for details. By * passing NULL (the default) you just tell package to use the * default API which works just fine on UNIX platforms. I have tried * it on win32-g++ platform too and it seems it works fine there * too, so I see no reason to use win32 IO API included in original * ZIP/UNZIP package. * * ZIP archive file name will be converted to 8-bit encoding using * Qt's QFile::encodeName() function before passing it to the * ZIP/UNZIP package API. * * Returns \c true if successful, \c false otherwise. * * Argument \a mode specifies open mode of the ZIP archive. See Mode * for details. Note that there is zipOpen2() function in the * ZIP/UNZIP API which accepts \a globalcomment argument, but it * does not use it anywhere, so this open() function does not have this * argument. See setComment() if you need to set global comment. * * \note ZIP/UNZIP API open calls do not return error code - they * just return \c NULL indicating an error. But to make things * easier, quazip.h header defines additional error code \c * UNZ_ERROROPEN and getZipError() will return it if the open call * of the ZIP/UNZIP API returns \c NULL. **/ bool open(Mode mode, zlib_filefunc_def *ioApi =NULL); /// Closes ZIP file. /** Call getZipError() to determine if the close was successful. */ void close(); /// Sets the codec used to encode/decode file names inside archive. /** This is necessary to access files in the ZIP archive created * under Windows with non-latin characters in file names. For * example, file names with cyrillic letters will be in \c IBM866 * encoding. **/ void setFileNameCodec(QTextCodec *fileNameCodec) {this->fileNameCodec=fileNameCodec;} /// Sets the codec used to encode/decode file names inside archive. /** \overload * Equivalent to calling setFileNameCodec(QTextCodec::codecForName(codecName)); **/ void setFileNameCodec(const char *fileNameCodecName) {fileNameCodec=QTextCodec::codecForName(fileNameCodecName);} /// Returns the codec used to encode/decode comments inside archive. QTextCodec* getFileNameCodec()const {return fileNameCodec;} /// Sets the codec used to encode/decode comments inside archive. /** This codec defaults to locale codec, which is probably ok. **/ void setCommentCodec(QTextCodec *commentCodec) {this->commentCodec=commentCodec;} /// Sets the codec used to encode/decode comments inside archive. /** \overload * Equivalent to calling setCommentCodec(QTextCodec::codecForName(codecName)); **/ void setCommentCodec(const char *commentCodecName) {commentCodec=QTextCodec::codecForName(commentCodecName);} /// Returns the codec used to encode/decode comments inside archive. QTextCodec* getCommentCodec()const {return commentCodec;} /// Returns the name of the ZIP file. /** Returns null string if no ZIP file name has been set. * \sa setZipName() **/ QString getZipName()const {return zipName;} /// Sets the name of the ZIP file. /** Does nothing if the ZIP file is open. * * Does not reset error code returned by getZipError(). **/ void setZipName(const QString& zipName); /// Returns the mode in which ZIP file was opened. Mode getMode()const {return mode;} /// Returns \c true if ZIP file is open, \c false otherwise. bool isOpen()const {return mode!=mdNotOpen;} /// Returns the error code of the last operation. /** Returns \c UNZ_OK if the last operation was successful. * * Error code resets to \c UNZ_OK every time you call any function * that accesses something inside ZIP archive, even if it is \c * const (like getEntriesCount()). open() and close() calls reset * error code too. See documentation for the specific functions for * details on error detection. **/ int getZipError()const {return zipError;} /// Returns number of the entries in the ZIP central directory. /** Returns negative error code in the case of error. The same error * code will be returned by subsequent getZipError() call. **/ int getEntriesCount()const; /// Returns global comment in the ZIP file. QString getComment()const; /// Sets global comment in the ZIP file. /** Comment will be written to the archive on close operation. * * \sa open() **/ void setComment(const QString& comment) {this->comment=comment;} /// Sets the current file to the first file in the archive. /** Returns \c true on success, \c false otherwise. Call * getZipError() to get the error code. **/ bool goToFirstFile(); /// Sets the current file to the next file in the archive. /** Returns \c true on success, \c false otherwise. Call * getZipError() to determine if there was an error. * * Should be used only in QuaZip::mdUnzip mode. * * \note If the end of file was reached, getZipError() will return * \c UNZ_OK instead of \c UNZ_END_OF_LIST_OF_FILE. This is to make * things like this easier: * \code * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { * // do something * } * if(zip.getZipError()==UNZ_OK) { * // ok, there was no error * } * \endcode **/ bool goToNextFile(); /// Sets current file by its name. /** Returns \c true if successful, \c false otherwise. Argument \a * cs specifies case sensitivity of the file name. Call * getZipError() in the case of a failure to get error code. * * This is not a wrapper to unzLocateFile() function. That is * because I had to implement locale-specific case-insensitive * comparison. * * Here are the differences from the original implementation: * * - If the file was not found, error code is \c UNZ_OK, not \c * UNZ_END_OF_LIST_OF_FILE (see also goToNextFile()). * - If this function fails, it unsets the current file rather than * resetting it back to what it was before the call. * * If \a fileName is null string then this function unsets the * current file and return \c true. Note that you should close the * file first if it is open! See * QuaZipFile::QuaZipFile(QuaZip*,QObject*) for the details. * * Should be used only in QuaZip::mdUnzip mode. * * \sa setFileNameCodec(), CaseSensitivity **/ bool setCurrentFile(const QString& fileName, CaseSensitivity cs =csDefault); /// Returns \c true if the current file has been set. bool hasCurrentFile()const {return hasCurrentFile_f;} /// Retrieves information about the current file. /** Fills the structure pointed by \a info. Returns \c true on * success, \c false otherwise. In the latter case structure pointed * by \a info remains untouched. If there was an error, * getZipError() returns error code. * * Should be used only in QuaZip::mdUnzip mode. * * Does nothing and returns \c false in any of the following cases. * - ZIP is not open; * - ZIP does not have current file; * - \a info is \c NULL; * * In all these cases getZipError() returns \c UNZ_OK since there * is no ZIP/UNZIP API call. **/ bool getCurrentFileInfo(QuaZipFileInfo* info)const; /// Returns the current file name. /** Equivalent to calling getCurrentFileInfo() and then getting \c * name field of the QuaZipFileInfo structure, but faster and more * convenient. * * Should be used only in QuaZip::mdUnzip mode. **/ QString getCurrentFileName()const; /// Returns \c unzFile handle. /** You can use this handle to directly call UNZIP part of the * ZIP/UNZIP package functions (see unzip.h). * * \warning When using the handle returned by this function, please * keep in mind that QuaZip class is unable to detect any changes * you make in the ZIP file state (e. g. changing current file, or * closing the handle). So please do not do anything with this * handle that is possible to do with the functions of this class. * Or at least return the handle in the original state before * calling some another function of this class (including implicit * destructor calls and calls from the QuaZipFile objects that refer * to this QuaZip instance!). So if you have changed the current * file in the ZIP archive - then change it back or you may * experience some strange behavior or even crashes. **/ unzFile getUnzFile() {return unzFile_f;} /// Returns \c zipFile handle. /** You can use this handle to directly call ZIP part of the * ZIP/UNZIP package functions (see zip.h). Warnings about the * getUnzFile() function also apply to this function. **/ zipFile getZipFile() {return zipFile_f;} }; #endif fritzing-app-0.9.2b/src/lib/quazip/quazipfile.cpp000066400000000000000000000244731250202676700220420ustar00rootroot00000000000000/* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include "quazipfile.h" using namespace std; QuaZipFile::QuaZipFile(): zip(NULL), internal(true), zipError(UNZ_OK) { } QuaZipFile::QuaZipFile(QObject *parent): QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK) { } QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent): QIODevice(parent), internal(true), zipError(UNZ_OK) { zip=new QuaZip(zipName); Q_CHECK_PTR(zip); } QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName, QuaZip::CaseSensitivity cs, QObject *parent): QIODevice(parent), internal(true), zipError(UNZ_OK) { zip=new QuaZip(zipName); Q_CHECK_PTR(zip); this->fileName=fileName; this->caseSensitivity=cs; } QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent): QIODevice(parent), zip(zip), internal(false), zipError(UNZ_OK) { } QuaZipFile::~QuaZipFile() { if(isOpen()) close(); if(internal) delete zip; } QString QuaZipFile::getZipName()const { return zip==NULL?QString():zip->getZipName(); } QString QuaZipFile::getActualFileName()const { setZipError(UNZ_OK); if(zip==NULL||(openMode()&WriteOnly)) return QString(); QString name=zip->getCurrentFileName(); if(name.isNull()) setZipError(zip->getZipError()); return name; } void QuaZipFile::setZipName(const QString& zipName) { if(isOpen()) { qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name"); return; } if(zip!=NULL&&internal) delete zip; zip=new QuaZip(zipName); Q_CHECK_PTR(zip); internal=true; } void QuaZipFile::setZip(QuaZip *zip) { if(isOpen()) { qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP"); return; } if(this->zip!=NULL&&internal) delete this->zip; this->zip=zip; this->fileName=QString(); internal=false; } void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) { if(zip==NULL) { qWarning("QuaZipFile::setFileName(): call setZipName() first"); return; } if(!internal) { qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip"); return; } if(isOpen()) { qWarning("QuaZipFile::setFileName(): can not set file name for already opened file"); return; } this->fileName=fileName; this->caseSensitivity=cs; } void QuaZipFile::setZipError(int zipError)const { QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const fakeThis->zipError=zipError; if(zipError==UNZ_OK) fakeThis->setErrorString(QString()); else fakeThis->setErrorString(QString("ZIP/UNZIP API error %1").arg(zipError)); } bool QuaZipFile::open(OpenMode mode) { return open(mode, NULL); } bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) { resetZipError(); if(isOpen()) { qWarning("QuaZipFile::open(): already opened"); return false; } if(mode&Unbuffered) { qWarning("QuaZipFile::open(): Unbuffered mode is not supported"); return false; } if((mode&ReadOnly)&&!(mode&WriteOnly)) { if(internal) { if(!zip->open(QuaZip::mdUnzip)) { setZipError(zip->getZipError()); return false; } if(!zip->setCurrentFile(fileName, caseSensitivity)) { setZipError(zip->getZipError()); zip->close(); return false; } } else { if(zip==NULL) { qWarning("QuaZipFile::open(): zip is NULL"); return false; } if(zip->getMode()!=QuaZip::mdUnzip) { qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", (int)mode, (int)zip->getMode()); return false; } if(!zip->hasCurrentFile()) { qWarning("QuaZipFile::open(): zip does not have current file"); return false; } } setZipError(unzOpenCurrentFile3(zip->getUnzFile(), method, level, (int)raw, password)); if(zipError==UNZ_OK) { setOpenMode(mode); this->raw=raw; return true; } else return false; } qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); return false; } bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, const char *password, quint32 crc, int method, int level, bool raw, int windowBits, int memLevel, int strategy) { zip_fileinfo info_z; resetZipError(); if(isOpen()) { qWarning("QuaZipFile::open(): already opened"); return false; } if((mode&WriteOnly)&&!(mode&ReadOnly)) { if(internal) { qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); return false; } if(zip==NULL) { qWarning("QuaZipFile::open(): zip is NULL"); return false; } if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) { qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", (int)mode, (int)zip->getMode()); return false; } info_z.tmz_date.tm_year=info.dateTime.date().year(); info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1; info_z.tmz_date.tm_mday=info.dateTime.date().day(); info_z.tmz_date.tm_hour=info.dateTime.time().hour(); info_z.tmz_date.tm_min=info.dateTime.time().minute(); info_z.tmz_date.tm_sec=info.dateTime.time().second(); info_z.dosDate = 0; info_z.internal_fa=(uLong)info.internalAttr; info_z.external_fa=(uLong)info.externalAttr; setZipError(zipOpenNewFileInZip3(zip->getZipFile(), zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z, info.extraLocal.constData(), info.extraLocal.length(), info.extraGlobal.constData(), info.extraGlobal.length(), zip->getCommentCodec()->fromUnicode(info.comment).constData(), method, level, (int)raw, windowBits, memLevel, strategy, password, (uLong)crc)); if(zipError==UNZ_OK) { writePos=0; setOpenMode(mode); this->raw=raw; if(raw) { this->crc=crc; this->uncompressedSize=info.uncompressedSize; } return true; } else return false; } qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); return false; } bool QuaZipFile::isSequential()const { return true; } qint64 QuaZipFile::pos()const { if(zip==NULL) { qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); return -1; } if(!isOpen()) { qWarning("QuaZipFile::pos(): file is not open"); return -1; } if(openMode()&ReadOnly) return unztell(zip->getUnzFile()); else return writePos; } bool QuaZipFile::atEnd()const { if(zip==NULL) { qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); return false; } if(!isOpen()) { qWarning("QuaZipFile::atEnd(): file is not open"); return false; } if(openMode()&ReadOnly) return unzeof(zip->getUnzFile())==1; else return true; } qint64 QuaZipFile::size()const { if(!isOpen()) { qWarning("QuaZipFile::atEnd(): file is not open"); return -1; } if(openMode()&ReadOnly) return raw?csize():usize(); else return writePos; } qint64 QuaZipFile::csize()const { unz_file_info info_z; setZipError(UNZ_OK); if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); if(zipError!=UNZ_OK) return -1; return info_z.compressed_size; } qint64 QuaZipFile::usize()const { unz_file_info info_z; setZipError(UNZ_OK); if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); if(zipError!=UNZ_OK) return -1; return info_z.uncompressed_size; } bool QuaZipFile::getFileInfo(QuaZipFileInfo *info) { if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return false; zip->getCurrentFileInfo(info); setZipError(zip->getZipError()); return zipError==UNZ_OK; } void QuaZipFile::close() { resetZipError(); if(zip==NULL||!zip->isOpen()) return; if(!isOpen()) { qWarning("QuaZipFile::close(): file isn't open"); return; } if(openMode()&ReadOnly) setZipError(unzCloseCurrentFile(zip->getUnzFile())); else if(openMode()&WriteOnly) if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc)); else setZipError(zipCloseFileInZip(zip->getZipFile())); else { qWarning("Wrong open mode: %d", (int)openMode()); return; } if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); else return; if(internal) { zip->close(); setZipError(zip->getZipError()); } } qint64 QuaZipFile::readData(char *data, qint64 maxSize) { setZipError(UNZ_OK); qint64 bytesRead=unzReadCurrentFile(zip->getUnzFile(), data, (unsigned)maxSize); if(bytesRead<0) setZipError((int)bytesRead); return bytesRead; } qint64 QuaZipFile::writeData(const char* data, qint64 maxSize) { setZipError(ZIP_OK); setZipError(zipWriteInFileInZip(zip->getZipFile(), data, (uint)maxSize)); if(zipError!=ZIP_OK) return -1; else { writePos+=maxSize; return maxSize; } } fritzing-app-0.9.2b/src/lib/quazip/quazipfile.h000066400000000000000000000455141250202676700215060ustar00rootroot00000000000000#ifndef QUA_ZIPFILE_H #define QUA_ZIPFILE_H /* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2008 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include #include "quazip.h" #include "quazipnewinfo.h" /// A file inside ZIP archive. /** \class QuaZipFile quazipfile.h * This is the most interesting class. Not only it provides C++ * interface to the ZIP/UNZIP package, but also integrates it with Qt by * subclassing QIODevice. This makes possible to access files inside ZIP * archive using QTextStream or QDataStream, for example. Actually, this * is the main purpose of the whole QuaZIP library. * * You can either use existing QuaZip instance to create instance of * this class or pass ZIP archive file name to this class, in which case * it will create internal QuaZip object. See constructors' descriptions * for details. Writing is only possible with the existing instance. * * \section quazipfile-sequential Sequential or random-access? * * At the first thought, QuaZipFile has fixed size, the start and the * end and should be therefore considered random-access device. But * there is one major obstacle to making it random-access: ZIP/UNZIP API * does not support seek() operation and the only way to implement it is * through reopening the file and re-reading to the required position, * but this is prohibitely slow. * * Therefore, QuaZipFile is considered to be a sequential device. This * has advantage of availability of the ungetChar() operation (QIODevice * does not implement it properly for non-sequential devices unless they * support seek()). Disadvantage is a somewhat strange behaviour of the * size() and pos() functions. This should be kept in mind while using * this class. * **/ class QuaZipFile: public QIODevice { Q_OBJECT private: QuaZip *zip; QString fileName; QuaZip::CaseSensitivity caseSensitivity; bool raw; qint64 writePos; // these two are for writing raw files ulong uncompressedSize; quint32 crc; bool internal; int zipError; // these are not supported nor implemented QuaZipFile(const QuaZipFile& that); QuaZipFile& operator=(const QuaZipFile& that); void resetZipError()const {setZipError(UNZ_OK);} // const, but sets zipError! void setZipError(int zipError)const; protected: /// Implementation of the QIODevice::readData(). qint64 readData(char *data, qint64 maxSize); /// Implementation of the QIODevice::writeData(). qint64 writeData(const char *data, qint64 maxSize); public: /// Constructs a QuaZipFile instance. /** You should use setZipName() and setFileName() or setZip() before * trying to call open() on the constructed object. **/ QuaZipFile(); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object. * * You should use setZipName() and setFileName() or setZip() before * trying to call open() on the constructed object. **/ QuaZipFile(QObject *parent); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object and \a * zipName specifies ZIP archive file name. * * You should use setFileName() before trying to call open() on the * constructed object. * * QuaZipFile constructed by this constructor can be used for read * only access. Use QuaZipFile(QuaZip*,QObject*) for writing. **/ QuaZipFile(const QString& zipName, QObject *parent =NULL); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object, \a * zipName specifies ZIP archive file name and \a fileName and \a cs * specify a name of the file to open inside archive. * * QuaZipFile constructed by this constructor can be used for read * only access. Use QuaZipFile(QuaZip*,QObject*) for writing. * * \sa QuaZip::setCurrentFile() **/ QuaZipFile(const QString& zipName, const QString& fileName, QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =NULL); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object. * * \a zip is the pointer to the existing QuaZip object. This * QuaZipFile object then can be used to read current file in the * \a zip or to write to the file inside it. * * \warning Using this constructor for reading current file can be * tricky. Let's take the following example: * \code * QuaZip zip("archive.zip"); * zip.open(QuaZip::mdUnzip); * zip.setCurrentFile("file-in-archive"); * QuaZipFile file(&zip); * file.open(QIODevice::ReadOnly); * // ok, now we can read from the file * file.read(somewhere, some); * zip.setCurrentFile("another-file-in-archive"); // oops... * QuaZipFile anotherFile(&zip); * anotherFile.open(QIODevice::ReadOnly); * anotherFile.read(somewhere, some); // this is still ok... * file.read(somewhere, some); // and this is NOT * \endcode * So, what exactly happens here? When we change current file in the * \c zip archive, \c file that references it becomes invalid * (actually, as far as I understand ZIP/UNZIP sources, it becomes * closed, but QuaZipFile has no means to detect it). * * Summary: do not close \c zip object or change its current file as * long as QuaZipFile is open. Even better - use another constructors * which create internal QuaZip instances, one per object, and * therefore do not cause unnecessary trouble. This constructor may * be useful, though, if you already have a QuaZip instance and do * not want to access several files at once. Good example: * \code * QuaZip zip("archive.zip"); * zip.open(QuaZip::mdUnzip); * // first, we need some information about archive itself * QByteArray comment=zip.getComment(); * // and now we are going to access files inside it * QuaZipFile file(&zip); * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { * file.open(QIODevice::ReadOnly); * // do something cool with file here * file.close(); // do not forget to close! * } * zip.close(); * \endcode **/ QuaZipFile(QuaZip *zip, QObject *parent =NULL); /// Destroys a QuaZipFile instance. /** Closes file if open, destructs internal QuaZip object (if it * exists and \em is internal, of course). **/ virtual ~QuaZipFile(); /// Returns the ZIP archive file name. /** If this object was created by passing QuaZip pointer to the * constructor, this function will return that QuaZip's file name * (or null string if that object does not have file name yet). * * Otherwise, returns associated ZIP archive file name or null * string if there are no name set yet. * * \sa setZipName() getFileName() **/ QString getZipName()const; /// Returns a pointer to the associated QuaZip object. /** Returns \c NULL if there is no associated QuaZip or it is * internal (so you will not mess with it). **/ QuaZip* getZip()const; /// Returns file name. /** This function returns file name you passed to this object either * by using * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*) * or by calling setFileName(). Real name of the file may differ in * case if you used case-insensitivity. * * Returns null string if there is no file name set yet. This is the * case when this QuaZipFile operates on the existing QuaZip object * (constructor QuaZipFile(QuaZip*,QObject*) or setZip() was used). * * \sa getActualFileName **/ QString getFileName()const {return fileName;} /// Returns case sensitivity of the file name. /** This function returns case sensitivity argument you passed to * this object either by using * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*) * or by calling setFileName(). * * Returns unpredictable value if getFileName() returns null string * (this is the case when you did not used setFileName() or * constructor above). * * \sa getFileName **/ QuaZip::CaseSensitivity getCaseSensitivity()const {return caseSensitivity;} /// Returns the actual file name in the archive. /** This is \em not a ZIP archive file name, but a name of file inside * archive. It is not necessary the same name that you have passed * to the * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*), * setFileName() or QuaZip::setCurrentFile() - this is the real file * name inside archive, so it may differ in case if the file name * search was case-insensitive. * * Equivalent to calling getCurrentFileName() on the associated * QuaZip object. Returns null string if there is no associated * QuaZip object or if it does not have a current file yet. And this * is the case if you called setFileName() but did not open the * file yet. So this is perfectly fine: * \code * QuaZipFile file("somezip.zip"); * file.setFileName("somefile"); * QString name=file.getName(); // name=="somefile" * QString actual=file.getActualFileName(); // actual is null string * file.open(QIODevice::ReadOnly); * QString actual=file.getActualFileName(); // actual can be "SoMeFiLe" on Windows * \endcode * * \sa getZipName(), getFileName(), QuaZip::CaseSensitivity **/ QString getActualFileName()const; /// Sets the ZIP archive file name. /** Automatically creates internal QuaZip object and destroys * previously created internal QuaZip object, if any. * * Will do nothing if this file is already open. You must close() it * first. **/ void setZipName(const QString& zipName); /// Returns \c true if the file was opened in raw mode. /** If the file is not open, the returned value is undefined. * * \sa open(OpenMode,int*,int*,bool,const char*) **/ bool isRaw()const {return raw;} /// Binds to the existing QuaZip instance. /** This function destroys internal QuaZip object, if any, and makes * this QuaZipFile to use current file in the \a zip object for any * further operations. See QuaZipFile(QuaZip*,QObject*) for the * possible pitfalls. * * Will do nothing if the file is currently open. You must close() * it first. **/ void setZip(QuaZip *zip); /// Sets the file name. /** Will do nothing if at least one of the following conditions is * met: * - ZIP name has not been set yet (getZipName() returns null * string). * - This QuaZipFile is associated with external QuaZip. In this * case you should call that QuaZip's setCurrentFile() function * instead! * - File is already open so setting the name is meaningless. * * \sa QuaZip::setCurrentFile **/ void setFileName(const QString& fileName, QuaZip::CaseSensitivity cs =QuaZip::csDefault); /// Opens a file for reading. /** Returns \c true on success, \c false otherwise. * Call getZipError() to get error code. * * \note Since ZIP/UNZIP API provides buffered reading only, * QuaZipFile does not support unbuffered reading. So do not pass * QIODevice::Unbuffered flag in \a mode, or open will fail. **/ virtual bool open(OpenMode mode); /// Opens a file for reading. /** \overload * Argument \a password specifies a password to decrypt the file. If * it is NULL then this function behaves just like open(OpenMode). **/ bool open(OpenMode mode, const char *password) {return open(mode, NULL, NULL, false, password);} /// Opens a file for reading. /** \overload * Argument \a password specifies a password to decrypt the file. * * An integers pointed by \a method and \a level will receive codes * of the compression method and level used. See unzip.h. * * If raw is \c true then no decompression is performed. * * \a method should not be \c NULL. \a level can be \c NULL if you * don't want to know the compression level. **/ bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =NULL); /// Opens a file for writing. /** \a info argument specifies information about file. It should at * least specify a correct file name. Also, it is a good idea to * specify correct timestamp (by default, current time will be * used). See QuaZipNewInfo. * * Arguments \a password and \a crc provide necessary information * for crypting. Note that you should specify both of them if you * need crypting. If you do not, pass \c NULL as password, but you * still need to specify \a crc if you are going to use raw mode * (see below). * * Arguments \a method and \a level specify compression method and * level. * * If \a raw is \c true, no compression is performed. In this case, * \a crc and uncompressedSize field of the \a info are required. * * Arguments \a windowBits, \a memLevel, \a strategy provide zlib * algorithms tuning. See deflateInit2() in zlib. **/ bool open(OpenMode mode, const QuaZipNewInfo& info, const char *password =NULL, quint32 crc =0, int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false, int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY); /// Returns \c true, but \ref quazipfile-sequential "beware"! virtual bool isSequential()const; /// Returns current position in the file. /** Implementation of the QIODevice::pos(). When reading, this * function is a wrapper to the ZIP/UNZIP unztell(), therefore it is * unable to keep track of the ungetChar() calls (which is * non-virtual and therefore is dangerous to reimplement). So if you * are using ungetChar() feature of the QIODevice, this function * reports incorrect value until you get back characters which you * ungot. * * When writing, pos() returns number of bytes already written * (uncompressed unless you use raw mode). * * \note Although * \ref quazipfile-sequential "QuaZipFile is a sequential device" * and therefore pos() should always return zero, it does not, * because it would be misguiding. Keep this in mind. * * This function returns -1 if the file or archive is not open. * * Error code returned by getZipError() is not affected by this * function call. **/ virtual qint64 pos()const; /// Returns \c true if the end of file was reached. /** This function returns \c false in the case of error. This means * that you called this function on either not open file, or a file * in the not open archive or even on a QuaZipFile instance that * does not even have QuaZip instance associated. Do not do that * because there is no means to determine whether \c false is * returned because of error or because end of file was reached. * Well, on the other side you may interpret \c false return value * as "there is no file open to check for end of file and there is * no end of file therefore". * * When writing, this function always returns \c true (because you * are always writing to the end of file). * * Error code returned by getZipError() is not affected by this * function call. **/ virtual bool atEnd()const; /// Returns file size. /** This function returns csize() if the file is open for reading in * raw mode, usize() if it is open for reading in normal mode and * pos() if it is open for writing. * * Returns -1 on error, call getZipError() to get error code. * * \note This function returns file size despite that * \ref quazipfile-sequential "QuaZipFile is considered to be sequential device", * for which size() should return bytesAvailable() instead. But its * name would be very misguiding otherwise, so just keep in mind * this inconsistence. **/ virtual qint64 size()const; /// Returns compressed file size. /** Equivalent to calling getFileInfo() and then getting * compressedSize field, but more convenient and faster. * * File must be open for reading before calling this function. * * Returns -1 on error, call getZipError() to get error code. **/ qint64 csize()const; /// Returns uncompressed file size. /** Equivalent to calling getFileInfo() and then getting * uncompressedSize field, but more convenient and faster. See * getFileInfo() for a warning. * * File must be open for reading before calling this function. * * Returns -1 on error, call getZipError() to get error code. **/ qint64 usize()const; /// Gets information about current file. /** This function does the same thing as calling * QuaZip::getCurrentFileInfo() on the associated QuaZip object, * but you can not call getCurrentFileInfo() if the associated * QuaZip is internal (because you do not have access to it), while * you still can call this function in that case. * * File must be open for reading before calling this function. * * Returns \c false in the case of an error. **/ bool getFileInfo(QuaZipFileInfo *info); /// Closes the file. /** Call getZipError() to determine if the close was successful. **/ virtual void close(); /// Returns the error code returned by the last ZIP/UNZIP API call. int getZipError()const {return zipError;} }; #endif fritzing-app-0.9.2b/src/lib/quazip/quazipfileinfo.h000066400000000000000000000044461250202676700223610ustar00rootroot00000000000000#ifndef QUA_ZIPFILEINFO_H #define QUA_ZIPFILEINFO_H /* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include #include /// Information about a file inside archive. /** Call QuaZip::getCurrentFileInfo() or QuaZipFile::getFileInfo() to * fill this structure. */ struct QuaZipFileInfo { /// File name. QString name; /// Version created by. quint16 versionCreated; /// Version needed to extract. quint16 versionNeeded; /// General purpose flags. quint16 flags; /// Compression method. quint16 method; /// Last modification date and time. QDateTime dateTime; /// CRC. quint32 crc; /// Compressed file size. quint32 compressedSize; /// Uncompressed file size. quint32 uncompressedSize; /// Disk number start. quint16 diskNumberStart; /// Internal file attributes. quint16 internalAttr; /// External file attributes. quint32 externalAttr; /// Comment. QString comment; /// Extra field. QByteArray extra; }; #endif fritzing-app-0.9.2b/src/lib/quazip/quazipnewinfo.cpp000066400000000000000000000037611250202676700225650ustar00rootroot00000000000000/* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. */ #include #include "quazipnewinfo.h" QuaZipNewInfo::QuaZipNewInfo(const QString& name): name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0) { } QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file): name(name), internalAttr(0), externalAttr(0) { QFileInfo info(file); QDateTime lm = info.lastModified(); if (!info.exists()) dateTime = QDateTime::currentDateTime(); else dateTime = lm; } void QuaZipNewInfo::setFileDateTime(const QString& file) { QFileInfo info(file); QDateTime lm = info.lastModified(); if (info.exists()) dateTime = lm; } fritzing-app-0.9.2b/src/lib/quazip/quazipnewinfo.h000066400000000000000000000100551250202676700222240ustar00rootroot00000000000000#ifndef QUA_ZIPNEWINFO_H #define QUA_ZIPNEWINFO_H /* -- A kind of "standard" GPL license statement -- QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package Copyright (C) 2005-2007 Sergey A. Tachenov 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- A kind of "standard" GPL license statement ends here -- See COPYING file for GPL. You are also permitted to use QuaZIP under the terms of LGPL (see COPYING.LGPL). You are free to choose either license, but please note that QuaZIP makes use of Qt, which is not licensed under LGPL. So if you are using Open Source edition of Qt, you therefore MUST use GPL for your code based on QuaZIP, since it would be also based on Qt in this case. If you are Qt commercial license owner, then you are free to use QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. **/ #include #include /// Information about a file to be created. /** This structure holds information about a file to be created inside * ZIP archive. At least name should be set to something correct before * passing this structure to * QuaZipFile::open(OpenMode,const QuaZipNewInfo&,int,int,bool). **/ struct QuaZipNewInfo { /// File name. /** This field holds file name inside archive, including path relative * to archive root. **/ QString name; /// File timestamp. /** This is the last file modification date and time. Will be stored * in the archive central directory. It is a good practice to set it * to the source file timestamp instead of archive creating time. Use * setFileDateTime() or QuaZipNewInfo(const QString&, const QString&). **/ QDateTime dateTime; /// File internal attributes. quint16 internalAttr; /// File external attributes. quint32 externalAttr; /// File comment. /** Will be encoded using QuaZip::getCommentCodec(). **/ QString comment; /// File local extra field. QByteArray extraLocal; /// File global extra field. QByteArray extraGlobal; /// Uncompressed file size. /** This is only needed if you are using raw file zipping mode, i. e. * adding precompressed file in the zip archive. **/ ulong uncompressedSize; /// Constructs QuaZipNewInfo instance. /** Initializes name with \a name, dateTime with current date and * time. Attributes are initialized with zeros, comment and extra * field with null values. **/ QuaZipNewInfo(const QString& name); /// Constructs QuaZipNewInfo instance. /** Initializes name with \a name and dateTime with timestamp of the * file named \a file. If the \a file does not exists or its timestamp * is inaccessible (e. g. you do not have read permission for the * directory file in), uses current date and time. Attributes are * initialized with zeros, comment and extra field with null values. * * \sa setFileDateTime() **/ QuaZipNewInfo(const QString& name, const QString& file); /// Sets the file timestamp from the existing file. /** Use this function to set the file timestamp from the existing * file. Use it like this: * \code * QuaZipFile zipFile(&zip); * QFile file("file-to-add"); * file.open(QIODevice::ReadOnly); * QuaZipNewInfo info("file-name-in-archive"); * info.setFileDateTime("file-to-add"); // take the timestamp from file * zipFile.open(QIODevice::WriteOnly, info); * \endcode * * This function does not change dateTime if some error occured (e. g. * file is inaccessible). **/ void setFileDateTime(const QString& file); }; #endif fritzing-app-0.9.2b/src/lib/quazip/unzip.c000066400000000000000000001402431250202676700204700ustar00rootroot00000000000000/* unzip.c -- IO for uncompress .zip files using zlib Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant Read unzip.h for more info */ /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of compatibility with older software. The following is from the original crypt.c. Code woven in by Terry Thorsen 1/2003. */ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] The encryption/decryption parts of this source code (as opposed to the non-echoing password parts) were originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) */ /* This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). */ #include #include #include #include #include "unzip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef CASESENSITIVITYDEFAULT_NO # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif #ifndef UNZ_BUFSIZE #define UNZ_BUFSIZE (16384) #endif #ifndef UNZ_MAXFILENAMEINZIP #define UNZ_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; /* unz_file_info_interntal contain internal info about a file in zipfile*/ typedef struct unz_file_info_internal_s { uLong offset_curfile;/* relative offset of local header 4 bytes */ } unz_file_info_internal; /* file_in_zip_read_info_s contain internal information about a file in zipfile, when reading and decompress it */ typedef struct { char *read_buffer; /* internal buffer for compressed data */ z_stream stream; /* zLib stream structure for inflate */ uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ uLong offset_local_extrafield;/* offset of the local extra field */ uInt size_local_extrafield;/* size of the local extra field */ uLong pos_local_extrafield; /* position in the local extra field in read*/ uLong crc32; /* crc32 of all data uncompressed */ uLong crc32_wait; /* crc32 we must obtain after decompress all */ uLong rest_read_compressed; /* number of byte to be decompressed */ uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ uLong compression_method; /* compression method (0==store) */ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; } file_in_zip_read_info_s; /* unz_s contain internal information about the zipfile */ typedef struct { zlib_filefunc_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ unz_global_info gi; /* public global information */ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ uLong num_file; /* number of the current file in the zipfile*/ uLong pos_in_central_dir; /* pos of the current file in the central dir*/ uLong current_file_ok; /* flag about the usability of the current file*/ uLong central_pos; /* position of the beginning of the central dir*/ uLong size_central_dir; /* size of the central directory */ uLong offset_central_dir; /* offset of start of central directory with respect to the starting disk number */ unz_file_info cur_file_info; /* public info about the current file in zip*/ unz_file_info_internal cur_file_info_internal; /* private info about it*/ file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current file if we are decompressing it */ int encrypted; # ifndef NOUNCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const unsigned long* pcrc_32_tab; # endif } unz_s; #ifndef NOUNCRYPT #include "crypt.h" #endif /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. */ local int unzlocal_getByte OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, int *pi)); local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; int *pi; { unsigned char c; int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; return UNZ_OK; } else { if (ZERROR(*pzlib_filefunc_def,filestream)) return UNZ_ERRNO; else return UNZ_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int unzlocal_getShort OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x ; int i; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unzlocal_getLong OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x ; int i; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==UNZ_OK) err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<16; if (err==UNZ_OK) err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<24; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } /* My own strcmpi / strcasecmp */ local int strcmpcasenosensitive_internal (fileName1,fileName2) const char* fileName1; const char* fileName2; { for (;;) { char c1=*(fileName1++); char c2=*(fileName2++); if ((c1>='a') && (c1<='z')) c1 -= 0x20; if ((c2>='a') && (c2<='z')) c2 -= 0x20; if (c1=='\0') return ((c2=='\0') ? 0 : -1); if (c2=='\0') return 1; if (c1c2) return 1; } } #ifdef CASESENSITIVITYDEFAULT_NO #define CASESENSITIVITYDEFAULTVALUE 2 #else #define CASESENSITIVITYDEFAULTVALUE 1 #endif #ifndef STRCMPCASENOSENTIVEFUNCTION #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal #endif /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) const char* fileName1; const char* fileName2; int iCaseSensitivity; { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local uLong unzlocal_SearchCentralDir OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream)); local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; { unsigned char* buf; uLong uSizeFile; uLong uBackRead; uLong uMaxBack=0xffff; /* maximum size of global comment */ uLong uPosFound=0; if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } /* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer "zlib/zlib114.zip". If the zipfile cannot be opened (file doesn't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) const char *path; zlib_filefunc_def* pzlib_filefunc_def; { unz_s us; unz_s *s; uLong central_pos,uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ int err=UNZ_OK; if (unz_copyright[0]!=' ') return NULL; if (pzlib_filefunc_def==NULL) fill_fopen_filefunc(&us.z_filefunc); else us.z_filefunc = *pzlib_filefunc_def; us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); if (us.filestream==NULL) return NULL; central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); if (central_pos==0) err=UNZ_ERRNO; if (ZSEEK(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir on this disk */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* zipfile comment length */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; if ((central_pospfile_in_zip_read!=NULL) unzCloseCurrentFile(file); ZCLOSE(s->z_filefunc, s->filestream); TRYFREE(s); return UNZ_OK; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) unzFile file; unz_global_info *pglobal_info; { unz_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; *pglobal_info=s->gi; return UNZ_OK; } /* Translate date/time from Dos format to tm_unz (readable more easilty) */ local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) uLong ulDosDate; tm_unz* ptm; { uLong uDate; uDate = (uLong)(ulDosDate>>16); ptm->tm_mday = (uInt)(uDate&0x1f) ; ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; } /* Get Info about the current file in the zipfile, with internal only info */ local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, unz_file_info *pfile_info, unz_file_info_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); local int unzlocal_GetCurrentFileInfoInternal (file, pfile_info, pfile_info_internal, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize, szComment, commentBufferSize) unzFile file; unz_file_info *pfile_info; unz_file_info_internal *pfile_info_internal; char *szFileName; uLong fileNameBufferSize; void *extraField; uLong extraFieldBufferSize; char *szComment; uLong commentBufferSize; { unz_s* s; unz_file_info file_info; unz_file_info_internal file_info_internal; int err=UNZ_OK; uLong uMagic; long lSeek=0; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (ZSEEK(s->z_filefunc, s->filestream, s->pos_in_central_dir+s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* we check the magic */ if (err==UNZ_OK) { if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x02014b50) err=UNZ_BADZIPFILE; } if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) err=UNZ_ERRNO; unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) err=UNZ_ERRNO; lSeek+=file_info.size_filename; if ((err==UNZ_OK) && (szFileName!=NULL)) { uLong uSizeRead ; if (file_info.size_filename0) && (fileNameBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek -= uSizeRead; } if ((err==UNZ_OK) && (extraField!=NULL)) { uLong uSizeRead ; if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek += file_info.size_file_extra - uSizeRead; } else lSeek+=file_info.size_file_extra; if ((err==UNZ_OK) && (szComment!=NULL)) { uLong uSizeRead ; if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek+=file_info.size_file_comment - uSizeRead; } else lSeek+=file_info.size_file_comment; if ((err==UNZ_OK) && (pfile_info!=NULL)) *pfile_info=file_info; if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) *pfile_info_internal=file_info_internal; return err; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetCurrentFileInfo (file, pfile_info, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize, szComment, commentBufferSize) unzFile file; unz_file_info *pfile_info; char *szFileName; uLong fileNameBufferSize; void *extraField; uLong extraFieldBufferSize; char *szComment; uLong commentBufferSize; { return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); } /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToFirstFile (file) unzFile file; { int err=UNZ_OK; unz_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; s->pos_in_central_dir=s->offset_central_dir; s->num_file=0; err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzGoToNextFile (file) unzFile file; { unz_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ if (s->num_file+1==s->gi.number_entry) return UNZ_END_OF_LIST_OF_FILE; s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; s->num_file++; err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzipStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) unzFile file; const char *szFileName; int iCaseSensitivity; { unz_s* s; int err; /* We remember the 'current' position in the file so that we can jump * back there if we fail. */ unz_file_info cur_file_infoSaved; unz_file_info_internal cur_file_info_internalSaved; uLong num_fileSaved; uLong pos_in_central_dirSaved; if (file==NULL) return UNZ_PARAMERROR; if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; /* Save the current state */ num_fileSaved = s->num_file; pos_in_central_dirSaved = s->pos_in_central_dir; cur_file_infoSaved = s->cur_file_info; cur_file_info_internalSaved = s->cur_file_info_internal; err = unzGoToFirstFile(file); while (err == UNZ_OK) { char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; err = unzGetCurrentFileInfo(file,NULL, szCurrentFileName,sizeof(szCurrentFileName)-1, NULL,0,NULL,0); if (err == UNZ_OK) { if (unzStringFileNameCompare(szCurrentFileName, szFileName,iCaseSensitivity)==0) return UNZ_OK; err = unzGoToNextFile(file); } } /* We failed, so restore the state of the 'current file' to where we * were. */ s->num_file = num_fileSaved ; s->pos_in_central_dir = pos_in_central_dirSaved ; s->cur_file_info = cur_file_infoSaved; s->cur_file_info_internal = cur_file_info_internalSaved; return err; } /* /////////////////////////////////////////// // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) // I need random access // // Further optimization could be realized by adding an ability // to cache the directory in memory. The goal being a single // comprehensive file read to put the file I need in a memory. */ /* typedef struct unz_file_pos_s { uLong pos_in_zip_directory; // offset in file uLong num_of_file; // # of file } unz_file_pos; */ extern int ZEXPORT unzGetFilePos(file, file_pos) unzFile file; unz_file_pos* file_pos; { unz_s* s; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; file_pos->pos_in_zip_directory = s->pos_in_central_dir; file_pos->num_of_file = s->num_file; return UNZ_OK; } extern int ZEXPORT unzGoToFilePos(file, file_pos) unzFile file; unz_file_pos* file_pos; { unz_s* s; int err; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; /* jump to the right spot */ s->pos_in_central_dir = file_pos->pos_in_zip_directory; s->num_file = file_pos->num_of_file; /* set the current file */ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); /* return results */ s->current_file_ok = (err == UNZ_OK); return err; } /* // Unzip Helper Functions - should be here? /////////////////////////////////////////// */ /* Read the local header of the current zipfile Check the coherency of the local header and info in the end of central directory about this file store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, poffset_local_extrafield, psize_local_extrafield) unz_s* s; uInt* piSizeVar; uLong *poffset_local_extrafield; uInt *psize_local_extrafield; { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; int err=UNZ_OK; *piSizeVar = 0; *poffset_local_extrafield = 0; *psize_local_extrafield = 0; if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (err==UNZ_OK) { if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; } if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; /* else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) err=UNZ_BADZIPFILE; */ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) err=UNZ_ERRNO; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) err=UNZ_BADZIPFILE; if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ err=UNZ_ERRNO; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) err=UNZ_BADZIPFILE; *piSizeVar += (uInt)size_filename; if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) err=UNZ_ERRNO; *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; *psize_local_extrafield = (uInt)size_extra_field; *piSizeVar += (uInt)size_extra_field; return err; } /* Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) unzFile file; int* method; int* level; int raw; const char* password; { int err=UNZ_OK; uInt iSizeVar; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; uLong offset_local_extrafield; /* offset of the local extra field */ uInt size_local_extrafield; /* size of the local extra field */ # ifndef NOUNCRYPT char source[12]; # else if (password != NULL) return UNZ_PARAMERROR; # endif if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return UNZ_PARAMERROR; if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) return UNZ_BADZIPFILE; pfile_in_zip_read_info = (file_in_zip_read_info_s*) ALLOC(sizeof(file_in_zip_read_info_s)); if (pfile_in_zip_read_info==NULL) return UNZ_INTERNALERROR; pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; pfile_in_zip_read_info->raw=raw; if (pfile_in_zip_read_info->read_buffer==NULL) { TRYFREE(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } pfile_in_zip_read_info->stream_initialised=0; if (method!=NULL) *method = (int)s->cur_file_info.compression_method; if (level!=NULL) { *level = 6; switch (s->cur_file_info.flag & 0x06) { case 6 : *level = 1; break; case 4 : *level = 2; break; case 2 : *level = 9; break; } } if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; pfile_in_zip_read_info->filestream=s->filestream; pfile_in_zip_read_info->z_filefunc=s->z_filefunc; pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; pfile_in_zip_read_info->stream.total_out = 0; if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) { pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; pfile_in_zip_read_info->stream.next_in = (voidpf)0; pfile_in_zip_read_info->stream.avail_in = 0; err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=1; else { TRYFREE(pfile_in_zip_read_info); return err; } /* windowBits is passed < 0 to tell that there is no zlib header. * Note that in this case inflate *requires* an extra "dummy" byte * after the compressed stream in order to complete decompression and * return Z_STREAM_END. * In unzip, i don't wait absolutely Z_STREAM_END because I known the * size of both compressed and uncompressed data */ } pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ; pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ; pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; pfile_in_zip_read_info->stream.avail_in = (uInt)0; s->pfile_in_zip_read = pfile_in_zip_read_info; # ifndef NOUNCRYPT if (password != NULL) { int i; s->pcrc_32_tab = get_crc_table(); init_keys(password,s->keys,s->pcrc_32_tab); if (ZSEEK(s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, SEEK_SET)!=0) return UNZ_INTERNALERROR; if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) return UNZ_INTERNALERROR; for (i = 0; i<12; i++) zdecode(s->keys,s->pcrc_32_tab,source[i]); s->pfile_in_zip_read->pos_in_zipfile+=12; s->encrypted=1; } # endif return UNZ_OK; } extern int ZEXPORT unzOpenCurrentFile (file) unzFile file; { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } extern int ZEXPORT unzOpenCurrentFilePassword (file, password) unzFile file; const char* password; { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) unzFile file; int* method; int* level; int raw; { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /* Read bytes from the current file. buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern int ZEXPORT unzReadCurrentFile (file, buf, len) unzFile file; voidp buf; unsigned len; { int err=UNZ_OK; uInt iRead = 0; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE; if (len==0) return 0; pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; pfile_in_zip_read_info->stream.avail_out = (uInt)len; if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && (!(pfile_in_zip_read_info->raw))) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; if ((len>pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw)) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in; while (pfile_in_zip_read_info->stream.avail_out>0) { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) { uInt uReadThis = UNZ_BUFSIZE; if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; if (uReadThis == 0) return UNZ_EOF; if (ZSEEK(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->read_buffer, uReadThis)!=uReadThis) return UNZ_ERRNO; # ifndef NOUNCRYPT if(s->encrypted) { uInt i; for(i=0;iread_buffer[i] = zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif pfile_in_zip_read_info->pos_in_zipfile += uReadThis; pfile_in_zip_read_info->rest_read_compressed-=uReadThis; pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer; pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; } if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) { uInt uDoCopy,i ; if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0)) return (iRead==0) ? UNZ_EOF : iRead; if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) uDoCopy = pfile_in_zip_read_info->stream.avail_out ; else uDoCopy = pfile_in_zip_read_info->stream.avail_in ; for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; pfile_in_zip_read_info->stream.avail_in -= uDoCopy; pfile_in_zip_read_info->stream.avail_out -= uDoCopy; pfile_in_zip_read_info->stream.next_out += uDoCopy; pfile_in_zip_read_info->stream.next_in += uDoCopy; pfile_in_zip_read_info->stream.total_out += uDoCopy; iRead += uDoCopy; } else { uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; uLong uOutThis; int flush=Z_SYNC_FLUSH; uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; bufBefore = pfile_in_zip_read_info->stream.next_out; /* if ((pfile_in_zip_read_info->rest_read_uncompressed == pfile_in_zip_read_info->stream.avail_out) && (pfile_in_zip_read_info->rest_read_compressed == 0)) flush = Z_FINISH; */ err=inflate(&pfile_in_zip_read_info->stream,flush); if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) err = Z_DATA_ERROR; uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); if (err==Z_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=Z_OK) break; } } if (err==Z_OK) return iRead; return err; } /* Give the current position in uncompressed data */ extern z_off_t ZEXPORT unztell (file) unzFile file; { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; return (z_off_t)pfile_in_zip_read_info->stream.total_out; } /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzeof (file) unzFile file; { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->rest_read_uncompressed == 0) return 1; else return 0; } /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field that can be read if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) unzFile file; voidp buf; unsigned len; { unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; uInt read_now; uLong size_to_read; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield); if (buf==NULL) return (int)size_to_read; if (len>size_to_read) read_now = (uInt)size_to_read; else read_now = (uInt)len ; if (read_now==0) return 0; if (ZSEEK(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf,read_now)!=read_now) return UNZ_ERRNO; return (int)read_now; } /* Close the file in zip opened with unzipOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzCloseCurrentFile (file) unzFile file; { int err=UNZ_OK; unz_s* s; file_in_zip_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && (!pfile_in_zip_read_info->raw)) { if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } TRYFREE(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised) inflateEnd(&pfile_in_zip_read_info->stream); pfile_in_zip_read_info->stream_initialised = 0; TRYFREE(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; return err; } /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) unzFile file; char *szComment; uLong uSizeBuf; { unz_s* s; uLong uReadThis ; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; uReadThis = uSizeBuf; if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (uReadThis>0) { *szComment='\0'; if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) return UNZ_ERRNO; } if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } /* Additions by RX '2004 */ extern uLong ZEXPORT unzGetOffset (file) unzFile file; { unz_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; if (!s->current_file_ok) return 0; if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) if (s->num_file==s->gi.number_entry) return 0; return s->pos_in_central_dir; } extern int ZEXPORT unzSetOffset (file, pos) unzFile file; uLong pos; { unz_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz_s*)file; s->pos_in_central_dir = pos; s->num_file = s->gi.number_entry; /* hack */ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } fritzing-app-0.9.2b/src/lib/quazip/unzip.h000066400000000000000000000312221250202676700204710ustar00rootroot00000000000000/* unzip.h -- IO for uncompress .zip files using zlib Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. Multi volume ZipFile (span) are not supported. Encryption compatible with pkzip 2.04g only supported Old compressions used by old PKZip 1.x are not supported I WAIT FEEDBACK at mail info@winimage.com Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* for more info about .ZIP format, see http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip http://www.info-zip.org/pub/infozip/doc/ PkWare has also a specification at : ftp://ftp.pkware.com/probdesc.zip */ #ifndef _unz_H #define _unz_H #ifdef __cplusplus extern "C" { #endif #include #ifndef _ZLIBIOAPI_H #include "ioapi.h" #endif #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagunzFile__ { int unused; } unzFile__; typedef unzFile__ *unzFile; #else typedef voidp unzFile; #endif #define UNZ_OK (0) #define UNZ_END_OF_LIST_OF_FILE (-100) #define UNZ_ERRNO (Z_ERRNO) #define UNZ_EOF (0) #define UNZ_PARAMERROR (-102) #define UNZ_BADZIPFILE (-103) #define UNZ_INTERNALERROR (-104) #define UNZ_CRCERROR (-105) /* tm_unz contain date/time info */ typedef struct tm_unz_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_unz; /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ typedef struct unz_global_info_s { uLong number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info; /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_info_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ uLong compressed_size; /* compressed size 4 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info; extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, const char* fileName2, int iCaseSensitivity)); /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern unzFile ZEXPORT unzOpen OF((const char *path)); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". If the zipfile cannot be opened (file don't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ extern unzFile ZEXPORT unzOpen2 OF((const char *path, zlib_filefunc_def* pzlib_filefunc_def)); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ extern int ZEXPORT unzClose OF((unzFile file)); /* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info)); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *szComment, uLong uSizeBuf)); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToNextFile OF((unzFile file)); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzLocateFile OF((unzFile file, const char *szFileName, int iCaseSensitivity)); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ /* ****************************************** */ /* Ryan supplied functions */ /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_pos_s { uLong pos_in_zip_directory; /* offset in zip file directory */ uLong num_of_file; /* # of file */ } unz_file_pos; extern int ZEXPORT unzGetFilePos( unzFile file, unz_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos( unzFile file, unz_file_pos* file_pos); /* ****************************************** */ extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); /* Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain somes info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) */ /***************************************************************************/ /* for reading the content of the current zipfile, you can open it, read data from it, and close it (you can close it before reading all the file) */ extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, const char* password)); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, int raw)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, const char* password)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len)); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern z_off_t ZEXPORT unztell OF((unzFile file)); /* Give the current position in uncompressed data */ extern int ZEXPORT unzeof OF((unzFile file)); /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len)); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ /***************************************************************************/ /* Get the current file offset */ extern uLong ZEXPORT unzGetOffset (unzFile file); /* Set the current file offset */ extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); #ifdef __cplusplus } #endif #endif /* _unz_H */ fritzing-app-0.9.2b/src/lib/quazip/zip.c000066400000000000000000001111321250202676700201200ustar00rootroot00000000000000/* zip.c -- IO on .zip files using zlib Version 1.01e, February 12th, 2005 27 Dec 2004 Rolf Kalbermatter Modification to zipOpen2 to support globalComment retrieval. Copyright (C) 1998-2005 Gilles Vollant Read zip.h for more info */ #include #include #include #include #include #include "zip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY # define VERSIONMADEBY (0x0) /* platform depedent */ #endif #ifndef Z_BUFSIZE #define Z_BUFSIZE (16384) #endif #ifndef Z_MAXFILENAMEINZIP #define Z_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif /* #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef DEF_MEM_LEVEL #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif #endif const char zip_copyright[] = " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; #define SIZEDATA_INDATABLOCK (4096-(4*4)) #define LOCALHEADERMAGIC (0x04034b50) #define CENTRALHEADERMAGIC (0x02014b50) #define ENDHEADERMAGIC (0x06054b50) #define FLAG_LOCALHEADER_OFFSET (0x06) #define CRC_LOCALHEADER_OFFSET (0x0e) #define SIZECENTRALHEADER (0x2e) /* 46 */ typedef struct linkedlist_datablock_internal_s { struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; uLong unused; /* for future use and alignement */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; typedef struct linkedlist_data_s { linkedlist_datablock_internal* first_block; linkedlist_datablock_internal* last_block; } linkedlist_data; typedef struct { z_stream stream; /* zLib stream structure for inflate */ int stream_initialised; /* 1 is stream is initialised */ uInt pos_in_buffered_data; /* last written byte in buffered_data */ uLong pos_local_header; /* offset of the local header of the file currenty writing */ char* central_header; /* central header data for the current file */ uLong size_centralheader; /* size of the central header for cur file */ uLong flag; /* flag of the file currently writing */ int method; /* compression method of file currenty wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; #ifndef NOCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const unsigned long* pcrc_32_tab; int crypt_header_size; #endif } curfile_info; typedef struct { zlib_filefunc_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ curfile_info ci; /* info on the file curretly writing */ uLong begin_pos; /* position of the beginning of the zipfile */ uLong add_position_when_writting_offset; uLong number_entry; #ifndef NO_ADDFILEINEXISTINGZIP char *globalcomment; #endif } zip_internal; #ifndef NOCRYPT #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED #include "crypt.h" #endif local linkedlist_datablock_internal* allocate_new_datablock() { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); if (ldi!=NULL) { ldi->next_datablock = NULL ; ldi->filled_in_this_block = 0 ; ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; } return ldi; } local void free_datablock(ldi) linkedlist_datablock_internal* ldi; { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; TRYFREE(ldi); ldi = ldinext; } } local void init_linkedlist(ll) linkedlist_data* ll; { ll->first_block = ll->last_block = NULL; } #if 0 // unused local void free_linkedlist(ll) linkedlist_data* ll; { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } #endif local int add_data_in_datablock(ll,buf,len) linkedlist_data* ll; const void* buf; uLong len; { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; if (ll==NULL) return ZIP_INTERNALERROR; if (ll->last_block == NULL) { ll->first_block = ll->last_block = allocate_new_datablock(); if (ll->first_block == NULL) return ZIP_INTERNALERROR; } ldi = ll->last_block; from_copy = (unsigned char*)buf; while (len>0) { uInt copy_this; uInt i; unsigned char* to_copy; if (ldi->avail_in_this_block==0) { ldi->next_datablock = allocate_new_datablock(); if (ldi->next_datablock == NULL) return ZIP_INTERNALERROR; ldi = ldi->next_datablock ; ll->last_block = ldi; } if (ldi->avail_in_this_block < len) copy_this = (uInt)ldi->avail_in_this_block; else copy_this = (uInt)len; to_copy = &(ldi->data[ldi->filled_in_this_block]); for (i=0;ifilled_in_this_block += copy_this; ldi->avail_in_this_block -= copy_this; from_copy += copy_this ; len -= copy_this; } return ZIP_OK; } /****************************************************************************/ #ifndef NO_ADDFILEINEXISTINGZIP /* =========================================================================== Inputs a long in LSB order to the given file nbByte == 1, 2 or 4 (byte, short or long) */ local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, uLong x, int nbByte)); local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; uLong x; int nbByte; { unsigned char buf[4]; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 (X Roche) */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) return ZIP_ERRNO; else return ZIP_OK; } local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); local void ziplocal_putValue_inmemory (dest, x, nbByte) void* dest; uLong x; int nbByte; { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } } /****************************************************************************/ local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) const tm_zip* ptm; uLong dosDate; { #ifndef _WINDOWS (void) dosDate; /* avoid "unused parameter" warning */ #endif uLong year = (uLong)ptm->tm_year; if (year>1980) year-=1980; else if (year>80) year-=80; return (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ local int ziplocal_getByte OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, int *pi)); local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; int *pi; { unsigned char c; int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; return ZIP_OK; } else { if (ZERROR(*pzlib_filefunc_def,filestream)) return ZIP_ERRNO; else return ZIP_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int ziplocal_getShort OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x ; int i; int err; err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==ZIP_OK) err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==ZIP_OK) *pX = x; else *pX = 0; return err; } local int ziplocal_getLong OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; uLong *pX; { uLong x ; int i; int err; err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==ZIP_OK) err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==ZIP_OK) err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<16; if (err==ZIP_OK) err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<24; if (err==ZIP_OK) *pX = x; else *pX = 0; return err; } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local uLong ziplocal_SearchCentralDir OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream)); local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) const zlib_filefunc_def* pzlib_filefunc_def; voidpf filestream; { unsigned char* buf; uLong uSizeFile; uLong uBackRead; uLong uMaxBack=0xffff; /* maximum size of global comment */ uLong uPosFound=0; if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } #endif /* !NO_ADDFILEINEXISTINGZIP*/ /************************************************************/ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) const char *pathname; int append; zipcharpc* globalcomment; zlib_filefunc_def* pzlib_filefunc_def; { zip_internal ziinit; zip_internal* zi; int err=ZIP_OK; if (pzlib_filefunc_def==NULL) fill_fopen_filefunc(&ziinit.z_filefunc); else ziinit.z_filefunc = *pzlib_filefunc_def; ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) (ziinit.z_filefunc.opaque, pathname, (append == APPEND_STATUS_CREATE) ? (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); if (ziinit.filestream == NULL) return NULL; ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; ziinit.add_position_when_writting_offset = 0; init_linkedlist(&(ziinit.central_dir)); zi = (zip_internal*)ALLOC(sizeof(zip_internal)); if (zi==NULL) { ZCLOSE(ziinit.z_filefunc,ziinit.filestream); return NULL; } /* now we add file in a zipfile */ # ifndef NO_ADDFILEINEXISTINGZIP ziinit.globalcomment = NULL; if (append == APPEND_STATUS_ADDINZIP) { uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ uLong size_central_dir; /* size of the central directory */ uLong offset_central_dir; /* offset of start of central directory */ uLong central_pos,uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ uLong number_entry; uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ uLong size_comment; central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); if (central_pos==0) err=ZIP_ERRNO; if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; /* the signature, already checked */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) err=ZIP_ERRNO; /* number of this disk */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) err=ZIP_ERRNO; /* number of the disk with the start of the central directory */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central dir on this disk */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central dir */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) err=ZIP_ERRNO; if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=ZIP_BADZIPFILE; /* size of the central directory */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) err=ZIP_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) err=ZIP_ERRNO; /* zipfile global comment length */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) err=ZIP_ERRNO; if ((central_pos0) { ziinit.globalcomment = ALLOC(size_comment+1); if (ziinit.globalcomment) { size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); ziinit.globalcomment[size_comment]=0; } } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); ziinit.add_position_when_writting_offset = byte_before_the_zipfile; { uLong size_central_dir_to_read = size_central_dir; size_t buf_size = SIZEDATA_INDATABLOCK; void* buf_read = (void*)ALLOC(buf_size); if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) err=ZIP_ERRNO; while ((size_central_dir_to_read>0) && (err==ZIP_OK)) { uLong read_this = SIZEDATA_INDATABLOCK; if (read_this > size_central_dir_to_read) read_this = size_central_dir_to_read; if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) err=ZIP_ERRNO; if (err==ZIP_OK) err = add_data_in_datablock(&ziinit.central_dir,buf_read, (uLong)read_this); size_central_dir_to_read-=read_this; } TRYFREE(buf_read); } ziinit.begin_pos = byte_before_the_zipfile; ziinit.number_entry = number_entry_CD; if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; } if (globalcomment) { *globalcomment = ziinit.globalcomment; } # endif /* !NO_ADDFILEINEXISTINGZIP*/ if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP TRYFREE(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ TRYFREE(zi); return NULL; } else { *zi = ziinit; return (zipFile)zi; } } extern zipFile ZEXPORT zipOpen (pathname, append) const char *pathname; int append; { return zipOpen2(pathname,append,NULL,NULL); } extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting) zipFile file; const char* filename; const zip_fileinfo* zipfi; const void* extrafield_local; uInt size_extrafield_local; const void* extrafield_global; uInt size_extrafield_global; const char* comment; int method; int level; int raw; int windowBits; int memLevel; int strategy; const char* password; uLong crcForCrypting; { zip_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; # ifdef NOCRYPT if (password != NULL) return ZIP_PARAMERROR; # endif if (file == NULL) return ZIP_PARAMERROR; if ((method!=0) && (method!=Z_DEFLATED)) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); if (err != ZIP_OK) return err; } if (filename==NULL) filename="-"; if (comment==NULL) size_comment = 0; else size_comment = (uInt)strlen(comment); size_filename = (uInt)strlen(filename); if (zipfi == NULL) zi->ci.dosDate = 0; else { if (zipfi->dosDate != 0) zi->ci.dosDate = zipfi->dosDate; else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); } zi->ci.flag = 0; if ((level==8) || (level==9)) zi->ci.flag |= 2; if ((level==2)) zi->ci.flag |= 4; if ((level==1)) zi->ci.flag |= 6; if (password != NULL) zi->ci.flag |= 1; zi->ci.crc32 = 0; zi->ci.method = method; zi->ci.encrypt = 0; zi->ci.stream_initialised = 0; zi->ci.pos_in_buffered_data = 0; zi->ci.raw = raw; zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); /* version info */ ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ if (zipfi==NULL) ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); else ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); if (zipfi==NULL) ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); else ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = *(((const char*)extrafield_global)+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ size_extrafield_global+i) = *(comment+i); if (zi->ci.central_header == NULL) return ZIP_INTERNALERROR; /* write the local header */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); if ((err==ZIP_OK) && (size_filename>0)) if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) err = ZIP_ERRNO; if ((err==ZIP_OK) && (size_extrafield_local>0)) if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) !=size_extrafield_local) err = ZIP_ERRNO; zi->ci.stream.avail_in = (uInt)0; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; zi->ci.stream.total_in = 0; zi->ci.stream.total_out = 0; if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { zi->ci.stream.zalloc = (alloc_func)0; zi->ci.stream.zfree = (free_func)0; zi->ci.stream.opaque = (voidpf)0; if (windowBits>0) windowBits = -windowBits; err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); if (err==Z_OK) zi->ci.stream_initialised = 1; } # ifndef NOCRYPT zi->ci.crypt_header_size = 0; if ((err==Z_OK) && (password != NULL)) { unsigned char bufHead[RAND_HEAD_LEN]; unsigned int sizeHead; zi->ci.encrypt = 1; zi->ci.pcrc_32_tab = get_crc_table(); /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); zi->ci.crypt_header_size = sizeHead; if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) err = ZIP_ERRNO; } # endif if (err==Z_OK) zi->in_opened_file_inzip = 1; return err; } extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw) zipFile file; const char* filename; const zip_fileinfo* zipfi; const void* extrafield_local; uInt size_extrafield_local; const void* extrafield_global; uInt size_extrafield_global; const char* comment; int method; int level; int raw; { return zipOpenNewFileInZip3 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0); } extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level) zipFile file; const char* filename; const zip_fileinfo* zipfi; const void* extrafield_local; uInt size_extrafield_local; const void* extrafield_global; uInt size_extrafield_global; const char* comment; int method; int level; { return zipOpenNewFileInZip2 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, 0); } local int zipFlushWriteBuffer(zi) zip_internal* zi; { int err=ZIP_OK; if (zi->ci.encrypt != 0) { #ifndef NOCRYPT uInt i; int t; for (i=0;ici.pos_in_buffered_data;i++) zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); #endif } if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) !=zi->ci.pos_in_buffered_data) err = ZIP_ERRNO; zi->ci.pos_in_buffered_data = 0; return err; } extern int ZEXPORT zipWriteInFileInZip (file, buf, len) zipFile file; const void* buf; unsigned len; { zip_internal* zi; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.next_in = (void*)buf; zi->ci.stream.avail_in = len; zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) { if (zi->ci.stream.avail_out == 0) { if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } if(err != ZIP_OK) break; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { uLong uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_NO_FLUSH); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } else { uInt copy_this,i; if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) copy_this = zi->ci.stream.avail_in; else copy_this = zi->ci.stream.avail_out; for (i=0;ici.stream.next_out)+i) = *(((const char*)zi->ci.stream.next_in)+i); { zi->ci.stream.avail_in -= copy_this; zi->ci.stream.avail_out-= copy_this; zi->ci.stream.next_in+= copy_this; zi->ci.stream.next_out+= copy_this; zi->ci.stream.total_in+= copy_this; zi->ci.stream.total_out+= copy_this; zi->ci.pos_in_buffered_data += copy_this; } } } return err; } extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) zipFile file; uLong uncompressed_size; uLong crc32; { zip_internal* zi; uLong compressed_size; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.avail_in = 0; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) while (err==ZIP_OK) { uLong uTotalOutBefore; if (zi->ci.stream.avail_out == 0) { if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_FINISH); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } if (err==Z_STREAM_END) err=ZIP_OK; /* this is normal */ if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) err = ZIP_ERRNO; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { err=deflateEnd(&zi->ci.stream); zi->ci.stream_initialised = 0; } if (!zi->ci.raw) { crc32 = (uLong)zi->ci.crc32; uncompressed_size = (uLong)zi->ci.stream.total_in; } compressed_size = (uLong)zi->ci.stream.total_out; # ifndef NOCRYPT compressed_size += zi->ci.crypt_header_size; # endif ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ ziplocal_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ if (zi->ci.stream.data_type == Z_ASCII) ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); ziplocal_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ if (err==ZIP_OK) err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, (uLong)zi->ci.size_centralheader); free(zi->ci.central_header); if (err==ZIP_OK) { long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); if (ZSEEK(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; if (err==ZIP_OK) err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ if (err==ZIP_OK) /* compressed size, unknown */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); if (err==ZIP_OK) /* uncompressed size, unknown */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); if (ZSEEK(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; } zi->number_entry ++; zi->in_opened_file_inzip = 0; return err; } extern int ZEXPORT zipCloseFileInZip (file) zipFile file; { return zipCloseFileInZipRaw (file,0,0); } extern int ZEXPORT zipClose (file, global_comment) zipFile file; const char* global_comment; { zip_internal* zi; int err = 0; uLong size_centraldir = 0; uLong centraldir_pos_inzip; uInt size_global_comment; if (file == NULL) return ZIP_PARAMERROR; zi = (zip_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); } #ifndef NO_ADDFILEINEXISTINGZIP if (global_comment==NULL) global_comment = zi->globalcomment; #endif if (global_comment==NULL) size_global_comment = 0; else size_global_comment = (uInt)strlen(global_comment); centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); if (err==ZIP_OK) { linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; while (ldi!=NULL) { if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) if (ZWRITE(zi->z_filefunc,zi->filestream, ldi->data,ldi->filled_in_this_block) !=ldi->filled_in_this_block ) err = ZIP_ERRNO; size_centraldir += ldi->filled_in_this_block; ldi = ldi->next_datablock; } } free_datablock(zi->central_dir.first_block); if (err==ZIP_OK) /* Magic End */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); if (err==ZIP_OK) /* number of this disk */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); if (err==ZIP_OK) /* total number of entries in the central dir */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); if (err==ZIP_OK) /* size of the central directory */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); if (err==ZIP_OK) /* zipfile comment length */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); if ((err==ZIP_OK) && (size_global_comment>0)) if (ZWRITE(zi->z_filefunc,zi->filestream, global_comment,size_global_comment) != size_global_comment) err = ZIP_ERRNO; if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) if (err == ZIP_OK) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP TRYFREE(zi->globalcomment); #endif TRYFREE(zi); return err; } fritzing-app-0.9.2b/src/lib/quazip/zip.h000066400000000000000000000212211250202676700201240ustar00rootroot00000000000000/* zip.h -- IO for compress .zip files using zlib Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant This unzip package allow creates .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. Multi volume ZipFile (span) are not supported. Encryption compatible with pkzip 2.04g only supported Old compressions used by old PKZip 1.x are not supported For uncompress .zip file, look at unzip.h I WAIT FEEDBACK at mail info@winimage.com Visit also http://www.winimage.com/zLibDll/unzip.html for evolution Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* for more info about .ZIP format, see http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip http://www.info-zip.org/pub/infozip/doc/ PkWare has also a specification at : ftp://ftp.pkware.com/probdesc.zip */ #ifndef _zip_H #define _zip_H #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include #endif #ifndef _ZLIBIOAPI_H #include "ioapi.h" #endif #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagzipFile__ { int unused; } zipFile__; typedef zipFile__ *zipFile; #else typedef voidp zipFile; #endif #define ZIP_OK (0) #define ZIP_EOF (0) #define ZIP_ERRNO (Z_ERRNO) #define ZIP_PARAMERROR (-102) #define ZIP_BADZIPFILE (-103) #define ZIP_INTERNALERROR (-104) #ifndef DEF_MEM_LEVEL # if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 # else # define DEF_MEM_LEVEL MAX_MEM_LEVEL # endif #endif /* default memLevel */ /* tm_zip contain date/time info */ typedef struct tm_zip_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct { tm_zip tmz_date; /* date in understandable format */ uLong dosDate; /* if dos_date == 0, tmu_date is used */ /* uLong flag; */ /* general purpose bit flag 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ } zip_fileinfo; typedef const char* zipcharpc; #define APPEND_STATUS_CREATE (0) #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip will be created at the end of the file. (useful if the file contain a self extractor code) if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will add files in existing zip (be sure you don't add file that doesn't exist) If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. */ /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another Of couse, you can use RAW reading and writing to copy the file you did not want delte */ extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc_def)); extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level)); /* Open a file in the ZIP for writing. filename : the filename in zip (if NULL, '-' without quote will be used *zipfi contain supplemental information if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local contains the extrafield data the the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header if comment != NULL, comment contain the comment string method contain the compression method (0 for store, Z_DEFLATED for deflate) level contain the level of compression (can be Z_DEFAULT_COMPRESSION) */ extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw)); /* Same than zipOpenNewFileInZip, except if raw=1, we write raw file */ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, uLong crcForCtypting)); /* Same than zipOpenNewFileInZip2, except windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 password : crypting password (NULL for no crypting) crcForCtypting : crc of file to compress (needed for crypting) */ extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void* buf, unsigned len)); /* Write data in the zipfile */ extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); /* Close the current file in the zipfile */ extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, uLong uncompressed_size, uLong crc32)); /* Close the current file in the zipfile, for fiel opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size */ extern int ZEXPORT zipClose OF((zipFile file, const char* global_comment)); /* Close the zipfile */ #ifdef __cplusplus } #endif #endif /* _zip_H */ fritzing-app-0.9.2b/src/main.cpp000066400000000000000000000164461250202676700165370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include "fapplication.h" #include "version/version.h" #include "debugdialog.h" #include "utils/folderutils.h" #ifdef Q_OS_WIN #ifndef QT_NO_DEBUG #include "windows.h" #endif #endif #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QtMsgHandler originalMsgHandler; #define ORIGINAL_MESSAGE_HANDLER(TYPE, MSG) originalMsgHandler((TYPE), (MSG)) #else QtMessageHandler originalMsgHandler; #define ORIGINAL_MESSAGE_HANDLER(TYPE, MSG) originalMsgHandler((TYPE), context, (MSG)) #endif void writeCrashMessage(const char * msg) { QString path = FolderUtils::getUserDataStorePath(""); path += "/fritzingcrash.txt"; QFile file(path); if (file.open(QIODevice::Append | QIODevice::Text)) { QTextStream out(&file); out << QString(msg) << "\n"; file.close(); } } #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) void writeCrashMessage(const QString & msg) { writeCrashMessage(msg.toStdString().c_str()); } #endif #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) void fMessageHandler(QtMsgType type, const char *msg) #else void fMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString & msg) #endif { switch (type) { case QtDebugMsg: ORIGINAL_MESSAGE_HANDLER(type, msg); break; case QtWarningMsg: ORIGINAL_MESSAGE_HANDLER(type, msg); break; case QtCriticalMsg: ORIGINAL_MESSAGE_HANDLER(type, msg); break; case QtFatalMsg: { writeCrashMessage(msg); } // don't abort ORIGINAL_MESSAGE_HANDLER(QtWarningMsg, msg); } } int main(int argc, char *argv[]) { #ifdef _MSC_VER // just for the MS compiler #define WIN_CHECK_LEAKS #endif #ifdef Q_OS_WIN #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) originalMsgHandler = qInstallMsgHandler(fMessageHandler); #else originalMsgHandler = qInstallMessageHandler(fMessageHandler); #endif #ifndef QT_NO_DEBUG #ifdef WIN_CHECK_LEAKS HANDLE hLogFile; QString path = FolderUtils::getUserDataStorePath("") + "/fritzing_leak_log.txt"; std::wstring wstr = path.toStdWString(); LPCWSTR ptr = wstr.c_str(); hLogFile = CreateFile(ptr, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, hLogFile); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, hLogFile); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, hLogFile); _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); //_CrtSetBreakAlloc(323809); // sets a break when this memory id is allocated #endif #endif #endif int result = 0; try { //QApplication::setGraphicsSystem("raster"); FApplication * app = new FApplication(argc, argv); if (app->init()) { //DebugDialog::setDebugLevel(DebugDialog::Error); if (app->runAsService()) { // for example: -g C:\Users\jonathan\fritzing2\fz\Test_multiple.fz -go C:\Users\jonathan\fritzing2\fz\gerber result = app->serviceStartup(); if (result == 1) { result = app->exec(); } } else { result = app->startup(); if (result == 0) { result = app->exec(); } } app->finish(); } else { qDebug() << "\n" "Fritzing version " << Version::versionString() << " , Qt version " << QT_VERSION_STR << "\n" "\n" "usage: fritzing [-d] [-f path] filename\n" " fritzing [-f path] -geda folder\n" " fritzing [-f path] -gerber folder\n" " fritzing [-f path] -kicad folder\n" " fritzing [-f path] -kicadschematic folder\n" " fritzing [-f path] -svg folder\n" " fritzing [-f path] -port number\n" "\n" "user options:\n" " d,debug : runs Fritzing in debug mode, providing additional debug information\n" //" drc filename : runs a design rule check on the given sketch file\n" " f,folder : path to folder containing Fritzing parts, sketches, bins, & translations folders}]\n" " geda path : converts all gEDA footprint (.fp) files in folder to Fritzing SVGs}]\n" " g,gerber path : exports all sketches in folder to Gerber, in the same folder\n" " h,help : print this help message\n" " kicad path : converts all Kicad footprint (.mod) files in folder to Fritzing SVGs}]\n" " kicadschematic path: converts all Kicad schematic (.lib) files in folder to Fritzing SVGs}]\n" " port : runs Fritzing as a server process under \n" " svg path : exports all sketches in folder to SVGs of all views, in the same folder\n" "\n" "developer options:\n" " db path : rebuilds the internal parts database at the given path\n" " e,examples path : prepares all sketches in the folder to be included as examples\n" " ep path : external process at \n" " eparg args : external process arguments\n" " epname name : external process menu item name\n" "\n" "The -geda/-kicad/-kicadschematic/-gerber/svg options all exit Fritzing after the conversion process is complete;\n" "these options are mutually exclusive.\n" "\n" "Usually, the Fritzing executable is stored in the same folder that contains the parts/bins/sketches/translations folders,\n" "or the executable is in a child folder of the p/b/s/t folder.\n" "If this is not the case, use the -f option to point to the p/b/s/t folder.\n" "\n" "The -ep option creates a menu item to launch an external process,\n" "and puts the standard output of that process into a dialog window in Fritzing.\n" "The process path follows the -ep argument; the name of the menu item follows the -epname argument;\n" "and any arguments to pass to the external process are provided in the -eparg argments.\n" "\n"; } delete app; } catch (char const *str) { writeCrashMessage(str); } catch (...) { result = -1; } return result; } fritzing-app-0.9.2b/src/mainwindow/000077500000000000000000000000001250202676700172505ustar00rootroot00000000000000fritzing-app-0.9.2b/src/mainwindow/fdockwidget.cpp000066400000000000000000000040721250202676700222510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "fdockwidget.h" #include "../debugdialog.h" FDockWidget::FDockWidget( const QString & title, QWidget * parent) : QDockWidget(title, parent) { m_state = false; setObjectName(title.trimmed().toLower().remove(" ")); setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); } void FDockWidget::saveState() { m_state = this->isFloating() && this->isVisible(); //DebugDialog::debug(QString("dock save state %1 %2").arg(windowTitle()).arg(m_state)); } void FDockWidget::restoreState() { //DebugDialog::debug(QString("dock restore state %1 %2").arg(windowTitle()).arg(m_state)); if (m_state) { this->setVisible(true); } } bool FDockWidget::event(QEvent * e) { switch (e->type()) { case QEvent::WindowActivate: emit dockChangeActivationSignal(true, this); break; case QEvent::WindowDeactivate: emit dockChangeActivationSignal(false, this); break; default: break; } return QDockWidget::event(e); } void FDockWidget::moveEvent(QMoveEvent *event) { QDockWidget::moveEvent(event); emit positionChanged(); } fritzing-app-0.9.2b/src/mainwindow/fdockwidget.h000066400000000000000000000030501250202676700217110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FDOCKWIDGET_H #define FDOCKWIDGET_H #include #include #include #include class FDockWidget : public QDockWidget { Q_OBJECT public: FDockWidget(const QString & title, QWidget * parent = 0); void saveState(); public slots: void restoreState(); protected: bool event(QEvent *event); void moveEvent(QMoveEvent *); signals: void dockChangeActivationSignal(bool activate, QWidget * originator); void positionChanged(); protected: bool m_state; QString m_name; }; #endif fritzing-app-0.9.2b/src/mainwindow/fritzingwindow.cpp000066400000000000000000000175311250202676700230470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6609 $: $Author: irascibl@gmail.com $: $Date: 2012-10-30 14:21:08 +0100 (Di, 30. Okt 2012) $ ********************************************************************/ #include #include #include #include #include #include #include "fritzingwindow.h" #include "../debugdialog.h" #include "../utils/misc.h" #include "../utils/folderutils.h" #include "../utils/fileprogressdialog.h" const QString FritzingWindow::QtFunkyPlaceholder = QLatin1String("[*]"); // this is some weird hack Qt uses in window titles as a placeholder to setr the modified state QString FritzingWindow::ReadOnlyPlaceholder(" [READ-ONLY] "); static QString ___fritzingTitle___; QStringList FritzingWindow::OtherKnownExtensions; FritzingWindow::FritzingWindow(const QString &untitledFileName, int &untitledFileCount, QString fileExt, QWidget * parent, Qt::WindowFlags f) : QMainWindow(parent, f) { ___fritzingTitle___ = QObject::tr("Fritzing"); m_readOnly = false; // Let's set the icon this->setWindowIcon(QIcon(QPixmap(":resources/images/fritzing_icon.png"))); QString fn = untitledFileName; if(untitledFileCount > 1) { fn += " " + QString::number(untitledFileCount); } fn += fileExt; setFileName(fn); untitledFileCount++; setTitle(); m_undoStack = new WaitPushUndoStack(this); connect(m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool)) ); } void FritzingWindow::createCloseAction() { m_closeAct = new QAction(tr("&Close Window"), this); m_closeAct->setShortcut(tr("Ctrl+W")); m_closeAct->setStatusTip(tr("Close the current sketch")); connect(m_closeAct, SIGNAL(triggered()), this, SLOT(close())); } void FritzingWindow::setTitle() { setWindowTitle(tr("%1 - %2") .arg(QFileInfo(m_fwFilename).fileName()+(m_readOnly?ReadOnlyPlaceholder:"")+QtFunkyPlaceholder) .arg(fritzingTitle())); } // returns true if the user wanted to save the file bool FritzingWindow::save() { bool result; if (FolderUtils::isEmptyFileName(m_fwFilename, untitledFileName())) { result = saveAs(); } else if (m_readOnly) { result = saveAs(); } else { result = saveAsAux(m_fwFilename); } return result; } bool FritzingWindow::saveAs() { return saveAs(m_fwFilename, m_readOnly); } bool FritzingWindow::save(const QString & filename, bool readOnly) { if (FolderUtils::isEmptyFileName(filename, untitledFileName())) { return saveAs(filename, readOnly); } else if (m_readOnly) { return saveAs(filename, readOnly); } else { return saveAsAux(filename); } } bool FritzingWindow::saveAs(const QString & filename, bool readOnly) { DebugDialog::debug(QString("current path: %1").arg(QDir::currentPath())); QString fileExt; QString path; QString untitledBase = untitledFileName(); if(readOnly) { path = defaultSaveFolder() + "/" + QFileInfo(filename).fileName(); } else if(filename.startsWith(untitledBase, Qt::CaseInsensitive)) { path = defaultSaveFolder() + "/" + filename; } else if(filename.isNull() || filename.isEmpty()) { path = defaultSaveFolder(); } else { path = filename; } DebugDialog::debug(QString("current file: %1").arg(filename)); QString newFilename = FolderUtils::getSaveFileName( this, tr("Specify a file name"), path, getExtensionString(), &fileExt ); if (newFilename.isEmpty()) return false; // Cancel pressed if (readOnly && (newFilename.compare(filename, Qt::CaseInsensitive) == 0)) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("The file '%1' is read-only; please use a different filename.") .arg(newFilename) ); return false; } FileProgressDialog progress("Saving...", 0, this); QStringList extensions = getExtensions(); bool hasExtension = false; foreach (QString extension, extensions) { if(alreadyHasExtension(newFilename, extension)) { hasExtension = true; break; } } if (!hasExtension) { newFilename += extensions[0]; } return saveAsAux(newFilename); } void FritzingWindow::undoStackCleanChanged(bool isClean) { setWindowModified(!isClean); } bool FritzingWindow::alreadyHasExtension(const QString &fileName, const QString &fileExt) { // TODO: Make something prettier to manage all the supported formats at once if(!fileExt.isEmpty()) { return fileName.endsWith(fileExt); } else { foreach (QString extension, fritzingExtensions()) { if (fileName.endsWith(extension)) return true; } foreach (QString extension, OtherKnownExtensions) { if (fileName.endsWith(extension)) return true; } return false; } } bool FritzingWindow::anyModified() { return isWindowModified(); } bool FritzingWindow::beforeClosing(bool showCancel, bool & discard) { discard = false; if (anyModified()) { QMessageBox::StandardButton reply = beforeClosingMessage(m_fwFilename, showCancel); if (reply == QMessageBox::Save) { return save(); } else if (reply == QMessageBox::Discard) { discard = true; return true; } else { return false; } } else { return true; } } QMessageBox::StandardButton FritzingWindow::beforeClosingMessage(const QString & filename, bool showCancel) { QMessageBox messageBox(this); setBeforeClosingText(filename, messageBox); QMessageBox::StandardButtons buttons = QMessageBox::Save | QMessageBox::Discard; if (showCancel) { buttons |= QMessageBox::Cancel; } messageBox.setStandardButtons(buttons); messageBox.setDefaultButton(QMessageBox::Save); if (m_fwFilename.startsWith(untitledFileName())) { messageBox.setButtonText(QMessageBox::Save, tr("Save...")); } else { messageBox.setButtonText(QMessageBox::Save, tr("Save")); } messageBox.setButtonText(QMessageBox::Discard, tr("Don't Save")); if (showCancel) { messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); } messageBox.setIcon(QMessageBox::Warning); messageBox.setWindowModality(Qt::WindowModal); messageBox.button(QMessageBox::Discard)->setShortcut(tr("Ctrl+D")); return (QMessageBox::StandardButton) messageBox.exec(); } void FritzingWindow::setBeforeClosingText(const QString & filename, QMessageBox & messageBox) { QString basename = QFileInfo(filename).fileName(); messageBox.setWindowTitle(tr("Save \"%1\"").arg(basename)); messageBox.setText(tr("Do you want to save the changes you made in the document \"%1\"?").arg(basename)); messageBox.setInformativeText(tr("Your changes will be lost if you don't save them.")); } void FritzingWindow::setReadOnly(bool readOnly) { bool hasChanged = m_readOnly != readOnly; m_readOnly = readOnly; if(hasChanged) { emit readOnlyChanged(readOnly); } } const QString FritzingWindow::fritzingTitle() { return ___fritzingTitle___; } const QString & FritzingWindow::fileName() { return m_fwFilename; } void FritzingWindow::setFileName(const QString & filename) { m_fwFilename = filename; } void FritzingWindow::notClosableForAWhile() { } fritzing-app-0.9.2b/src/mainwindow/fritzingwindow.h000066400000000000000000000060031250202676700225040ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6496 $: $Author: irascibl@gmail.com $: $Date: 2012-09-30 02:00:34 +0200 (So, 30. Sep 2012) $ ********************************************************************/ #ifndef FRITZINGWINDOW_H_ #define FRITZINGWINDOW_H_ #include #include #include #include #include "../waitpushundostack.h" #include "../utils/misc.h" #include "../utils/bundler.h" class FritzingWindow : public QMainWindow, public Bundler { Q_OBJECT public: FritzingWindow(const QString &untitledFileName, int &untitledFileCount, QString fileExt, QWidget * parent = 0, Qt::WindowFlags f = 0); const QString &fileName(); void setFileName(const QString &); virtual void notClosableForAWhile(); static bool alreadyHasExtension(const QString &fileName, const QString &extension=___emptyString___); signals: void readOnlyChanged(bool isReadOnly); protected slots: void undoStackCleanChanged(bool isClean); virtual bool save(); virtual bool saveAs(); protected: bool save(const QString & filename, bool readOnly); bool saveAs(const QString & filename, bool readOnly); virtual void setTitle(); virtual const QString fritzingTitle(); virtual const QString fileExtension() = 0; virtual const QString untitledFileName() = 0; virtual int &untitledFileCount() = 0; virtual const QString defaultSaveFolder() = 0; virtual QString getExtensionString() = 0; virtual QStringList getExtensions() = 0; virtual bool saveAsAux(const QString & fileName) = 0; virtual bool beforeClosing(bool showCancel, bool & discard); // returns true if close, false if cancel QMessageBox::StandardButton beforeClosingMessage(const QString & filename, bool showCancel); virtual void setBeforeClosingText(const QString & filename, QMessageBox & messageBox); void createCloseAction(); void setReadOnly(bool readOnly); virtual bool anyModified(); protected: class WaitPushUndoStack * m_undoStack; QString m_fwFilename; bool m_readOnly; QAction *m_closeAct; QDir m_tempDir; QStatusBar *m_statusBar; protected: static QStringList OtherKnownExtensions; public: static QString ReadOnlyPlaceholder; static const QString QtFunkyPlaceholder; }; #endif /* FRITZINGWINDOW_H_ */ fritzing-app-0.9.2b/src/mainwindow/mainwindow.cpp000066400000000000000000003246541250202676700221460ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6995 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 00:56:34 +0200 (So, 28. Apr 2013) $lo ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mainwindow.h" #include "../debugdialog.h" #include "../connectors/connector.h" #include "../partsbinpalette/partsbinpalettewidget.h" #include "fdockwidget.h" #include "../infoview/htmlinfoview.h" #include "../waitpushundostack.h" #include "../layerattributes.h" #include "../sketch/breadboardsketchwidget.h" #include "../sketch/schematicsketchwidget.h" #include "../sketch/pcbsketchwidget.h" #include "../sketch/welcomeview.h" #include "../svg/svgfilesplitter.h" #include "../utils/folderutils.h" #include "../utils/fmessagebox.h" #include "../utils/lockmanager.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../items/mysterypart.h" #include "../items/moduleidnames.h" #include "../items/pinheader.h" #include "../items/perfboard.h" #include "../items/stripboard.h" #include "../items/partfactory.h" #include "../dock/layerpalette.h" #include "../items/paletteitem.h" #include "../items/virtualwire.h" #include "../items/screwterminal.h" #include "../items/dip.h" #include "../processeventblocker.h" #include "../sketchtoolbutton.h" #include "../partsbinpalette/binmanager/binmanager.h" #include "../fsvgrenderer.h" #include "../utils/fsizegrip.h" #include "../utils/expandinglabel.h" #include "../utils/autoclosemessagebox.h" #include "../utils/fileprogressdialog.h" #include "../utils/clickablelabel.h" #include "../items/resizableboard.h" #include "../items/resistor.h" #include "../items/logoitem.h" #include "../utils/zoomslider.h" #include "../partseditor/pemainwindow.h" #include "../help/firsttimehelpdialog.h" FTabWidget::FTabWidget(QWidget * parent) : QTabWidget(parent) { QTabBar * tabBar = new FTabBar; tabBar->setObjectName("mainTabBar"); //connect(this, SIGNAL(currentChanged(int)), this, SLOT(tabIndexChanged(int))); setTabBar(tabBar); } //int FTabWidget::addTab(QWidget * page, const QIcon & icon, const QIcon & hoverIcon, const QIcon & inactiveIcon, const QString & label) //{ // // assumes tabs are not deleted or reordered // m_inactiveIcons << inactiveIcon; // m_hoverIcons << hoverIcon; // m_icons << icon; // return QTabWidget::addTab(page, icon, label); //} //void FTabWidget::tabIndexChanged(int index) { // for (int i = 0; i < this->count(); ++i) { // if (i == index) setTabIcon(i, m_icons.at(i)); // else setTabIcon(i, m_inactiveIcons.at(i)); // } //} FTabBar::FTabBar() : QTabBar() { m_firstTime = true; } void FTabBar::paintEvent(QPaintEvent * event) { // this is a hack to left-align the tab text by adding spaces to the text // center-alignment is hard-coded deep into the way the tab is drawn in qcommonstyle.cpp static int offset = 15; // derived this empirically, no idea where it comes from if (m_firstTime) { m_firstTime = false; // TODO: how to append spaces from the language direction for (int i = 0; i < this->count(); ++i) { QStyleOptionTabV3 tab; initStyleOption(&tab, 0); //DebugDialog::debug(QString("state %1").arg(tab.state)); QString text = tabText(i); int added = 0; while (true) { QRect r = tab.fontMetrics.boundingRect(text); if (r.width() + iconSize().width() + offset >= tabRect(i).width()) { if (added) { text.chop(1); setTabText(i, text); } break; } text += " "; added++; } } } QTabBar::paintEvent(event); /* return; // this code mostly lifted from QTabBar::paintEvent QStyleOptionTabBarBaseV2 optTabBase; optTabBase.init(this); optTabBase.shape = this->shape(); optTabBase.documentMode = this->documentMode(); QStylePainter p(this); int selected = this->currentIndex(); for (int i = 0; i < this->count(); ++i) optTabBase.tabBarRect |= tabRect(i); optTabBase.selectedTabRect = tabRect(selected); p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase); for (int i = 0; i < this->count(); ++i) { if (i == selected) continue; QStyleOptionTabV3 tab; initStyleOption(&tab, i); drawTab(p, tab, i); } // Draw the selected tab last to get it "on top" if (selected >= 0) { QStyleOptionTabV3 tab; initStyleOption(&tab, selected); drawTab(p, tab, selected); } */ } /* void FTabBar::drawTab(QStylePainter & p, QStyleOptionTabV3 & tabV3, int index) { //tabV3.iconSize = m_pixmaps.at(index).size(); p.drawControl(QStyle::CE_TabBarTabShape, tabV3); //p.drawPixmap(tabV3.rect.left(), tabV3.rect.top(), m_pixmaps.at(index)); //QRect tr = tabV3.rect; //int alignment = Qt::AlignLeft | Qt::TextShowMnemonic; //if (!this->style()->styleHint(QStyle::SH_UnderlineShortcut, &tabV3, this)) // alignment |= Qt::TextHideMnemonic; //p.drawItemText(tr, alignment, tabV3.palette, tabV3.state & QStyle::State_Enabled, tabV3.text, QPalette::WindowText); //p.drawControl(QStyle::CE_TabBarTabLabel, tabV3); } */ /////////////////////////////////////////////// struct MissingSvgInfo { QString requestedPath; QStringList connectorSvgIds; ModelPart * modelPart; bool equal; }; bool byConnectorCount(MissingSvgInfo & m1, MissingSvgInfo & m2) { if (m1.connectorSvgIds.count() == m2.connectorSvgIds.count() && m1.modelPart != m2.modelPart) { m1.equal = m2.equal = true; } return (m1.connectorSvgIds.count() > m2.connectorSvgIds.count()); } /////////////////////////////////////////////// #define ZIP_PART QString("part.") #define ZIP_SVG QString("svg.") /////////////////////////////////////////////// // SwapTimer explained: http://code.google.com/p/fritzing/issues/detail?id=1431 SwapTimer::SwapTimer() : QTimer() { } void SwapTimer::setAll(const QString & family, const QString & prop, QMap & propsMap, ItemBase * itemBase) { m_family = family; m_prop = prop; m_propsMap = propsMap; m_itemBase = itemBase; } const QString & SwapTimer::family() { return m_family; } const QString & SwapTimer::prop() { return m_prop; } QMap SwapTimer::propsMap() { return m_propsMap; } ItemBase * SwapTimer::itemBase() { return m_itemBase; } /////////////////////////////////////////////// const QString MainWindow::UntitledSketchName = "Untitled Sketch"; int MainWindow::UntitledSketchIndex = 1; int MainWindow::CascadeFactorX = 21; int MainWindow::CascadeFactorY = 19; static const int MainWindowDefaultWidth = 840; static const int MainWindowDefaultHeight = 600; int MainWindow::AutosaveTimeoutMinutes = 10; // in minutes bool MainWindow::AutosaveEnabled = true; QString MainWindow::BackupFolder; QRegExp MainWindow::GuidMatcher = QRegExp("[A-Fa-f0-9]{32}"); ///////////////////////////////////////////// MainWindow::MainWindow(ReferenceModel *referenceModel, QWidget * parent) : FritzingWindow(untitledFileName(), untitledFileCount(), fileExtension(), parent) { m_noSchematicConversion = m_useOldSchematic = m_convertedSchematic = false; m_initialTab = 1; m_rolloverQuoteDialog = NULL; setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); setDockOptions(QMainWindow::AnimatedDocks); m_sizeGrip = new FSizeGrip(this); m_topDock = NULL; m_bottomDock = NULL; m_dontKeepMargins = true; m_settingsPrefix = "main/"; m_showWelcomeAct = m_showProgramAct = m_raiseWindowAct = m_showPartsBinIconViewAct = m_showAllLayersAct = m_hideAllLayersAct = m_rotate90cwAct = m_showBreadboardAct = m_showSchematicAct = m_showPCBAct = NULL; m_fileMenu = m_editMenu = m_partMenu = m_windowMenu = m_pcbTraceMenu = m_schematicTraceMenu = m_breadboardTraceMenu = m_viewMenu = NULL; m_infoView = NULL; m_addedToTemp = false; setAcceptDrops(true); m_activeWire = NULL; m_activeConnectorItem = NULL; m_swapTimer.setInterval(30); m_swapTimer.setParent(this); m_swapTimer.setSingleShot(true); connect(&m_swapTimer, SIGNAL(timeout()), this, SLOT(swapSelectedTimeout())); m_closeSilently = false; m_orderFabAct = NULL; m_viewFromButtonWidget = m_activeLayerButtonWidget = NULL; m_programView = m_programWindow = NULL; m_welcomeView = NULL; m_windowMenuSeparator = NULL; m_schematicWireColorMenu = m_breadboardWireColorMenu = NULL; m_checkForUpdatesAct = NULL; m_fileProgressDialog = NULL; m_currentGraphicsView = NULL; m_comboboxChanged = false; // Add a timer for autosaving m_backingUp = m_autosaveNeeded = false; connect(&m_autosaveTimer, SIGNAL(timeout()), this, SLOT(backupSketch())); m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000); m_fireQuoteTimer.setSingleShot(true); connect(&m_fireQuoteTimer, SIGNAL(timeout()), this, SLOT(fireQuote())); resize(MainWindowDefaultWidth, MainWindowDefaultHeight); m_backupFileNameAndPath = MainWindow::BackupFolder + "/" + TextUtils::getRandText() + FritzingSketchExtension; // Connect the undoStack to our autosave stuff connect(m_undoStack, SIGNAL(indexChanged(int)), this, SLOT(autosaveNeeded(int))); connect(m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool))); // Create dot icons m_dotIcon = QIcon(":/resources/images/dot.png"); m_emptyIcon = QIcon(); m_currentWidget = NULL; m_firstOpen = true; m_statusBar = new QStatusBar(this); setStatusBar(m_statusBar); m_statusBar->setSizeGripEnabled(false); QSettings settings; m_locationLabelUnits = settings.value("LocationInches", "in").toString(); // leave the m_orderFabEnabled check in case we turn off the fab button in the future m_orderFabEnabled = true; // settings.value(ORDERFABENABLED, QVariant(false)).toBool(); m_locationLabel = new ClickableLabel("", this); m_locationLabel->setObjectName("LocationLabel"); connect(m_locationLabel, SIGNAL(clicked()), this, SLOT(locationLabelClicked())); m_locationLabel->setCursor(Qt::PointingHandCursor); m_statusBar->addPermanentWidget(m_locationLabel); m_zoomSlider = new ZoomSlider(ZoomableGraphicsView::MaxScaleValue, m_statusBar); connect(m_zoomSlider, SIGNAL(zoomChanged(double)), this, SLOT(updateViewZoom(double))); m_statusBar->addPermanentWidget(m_zoomSlider); setAttribute(Qt::WA_DeleteOnClose, true); #ifdef Q_OS_MAC //setAttribute(Qt::WA_QuitOnClose, false); // restoring this temporarily (2008.12.19) #endif m_dontClose = m_closing = false; m_referenceModel = referenceModel; m_sketchModel = new SketchModel(true); QShortcut * shortcut = new QShortcut(QKeySequence(tr("Ctrl+R", "Rotate Clockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCW())); shortcut = new QShortcut(QKeySequence(tr("Alt+Ctrl+R", "Rotate Clockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand())); shortcut = new QShortcut(QKeySequence(tr("Meta+Ctrl+R", "Rotate Clockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand())); shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+R", "Rotate Counterclockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCW())); shortcut = new QShortcut(QKeySequence(tr("Alt+Shift+Ctrl+R", "Rotate Counterclockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand())); shortcut = new QShortcut(QKeySequence(tr("Meta+Shift+Ctrl+R", "Rotate Counterclockwise")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand())); shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+Tab", "Toggle Active Layer")), this); connect(shortcut, SIGNAL(activated()), this, SLOT(toggleActiveLayer())); connect(this, SIGNAL(changeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection); connect(this, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *))); connect(this, SIGNAL(externalProcessSignal(QString &, QString &, QStringList &)), qApp, SLOT(externalProcessSlot(QString &, QString &, QStringList &)), Qt::DirectConnection); } QWidget * MainWindow::createTabWidget() { //return new QStackedWidget(this); FTabWidget * tabWidget = new FTabWidget(this); tabWidget->setObjectName("sketch_tabs"); return tabWidget; } void MainWindow::addTab(QWidget * widget, const QString & label) { //Q_UNUSED(label); //qobject_cast(m_tabWidget)->addWidget(widget); qobject_cast(m_tabWidget)->addTab(widget, label); } void MainWindow::addTab(QWidget * widget, const QString & iconPath, const QString & label, bool withIcon) { if (!withIcon) { addTab(widget, label); return; } FTabWidget * tabWidget = qobject_cast(m_tabWidget); if (tabWidget == NULL) { addTab(widget, label); return; } //Q_UNUSED(label); //qobject_cast(m_tabWidget)->addWidget(widget); QIcon icon; QPixmap pixmap(iconPath); icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); QString inactivePath = iconPath; inactivePath.replace("Active", "Inactive"); QPixmap inactivePixmap(inactivePath); icon.addPixmap(inactivePixmap, QIcon::Normal, QIcon::Off); QString hoverPath = iconPath; hoverPath.replace("Active", "Hover"); QPixmap hoverPixmap(hoverPath); icon.addPixmap(hoverPixmap, QIcon::Active, QIcon::On); tabWidget->addTab(widget, icon, label); } int MainWindow::currentTabIndex() { return qobject_cast(m_tabWidget)->currentIndex(); } void MainWindow::setCurrentTabIndex(int index) { qobject_cast(m_tabWidget)->setCurrentIndex(index); } QWidget * MainWindow::currentTabWidget() { return qobject_cast(m_tabWidget)->currentWidget(); } void MainWindow::init(ReferenceModel *referenceModel, bool lockFiles) { m_tabWidget = createTabWidget(); // FTabWidget(this); setCentralWidget(m_tabWidget); m_referenceModel = referenceModel; m_restarting = false; if (m_fileProgressDialog) { m_fileProgressDialog->setValue(2); } initLockedFiles(lockFiles); initWelcomeView(); initSketchWidgets(true); initProgrammingWidget(); m_undoView = new QUndoView(); m_undoGroup = new QUndoGroup(this); m_undoView->setGroup(m_undoGroup); m_undoGroup->setActiveStack(m_undoStack); initDock(); initMenus(); moreInitDock(); createZoomOptions(m_breadboardWidget); createZoomOptions(m_schematicWidget); createZoomOptions(m_pcbWidget); m_breadboardWidget->setToolbarWidgets(getButtonsForView(ViewLayer::BreadboardView)); m_schematicWidget->setToolbarWidgets(getButtonsForView(ViewLayer::SchematicView)); m_pcbWidget->setToolbarWidgets(getButtonsForView(ViewLayer::PCBView)); initStyleSheet(); m_breadboardGraphicsView->setItemMenu(breadboardItemMenu()); m_breadboardGraphicsView->setWireMenu(breadboardWireMenu()); m_pcbGraphicsView->setWireMenu(pcbWireMenu()); m_pcbGraphicsView->setItemMenu(pcbItemMenu()); m_schematicGraphicsView->setItemMenu(schematicItemMenu()); m_schematicGraphicsView->setWireMenu(schematicWireMenu()); if (m_infoView) { m_breadboardGraphicsView->setInfoView(m_infoView); m_pcbGraphicsView->setInfoView(m_infoView); m_schematicGraphicsView->setInfoView(m_infoView); } // make sure to set the connections after the views have been created connect(m_tabWidget, SIGNAL(currentChanged ( int )), this, SLOT(tabWidget_currentChanged( int ))); connectPairs(); setInitialView(); this->installEventFilter(this); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(95); } QSettings settings; if(!settings.value(m_settingsPrefix + "state").isNull()) { restoreState(settings.value(m_settingsPrefix + "state").toByteArray()); restoreGeometry(settings.value(m_settingsPrefix + "geometry").toByteArray()); } setMinimumSize(0,0); m_tabWidget->setMinimumWidth(500); m_tabWidget->setMinimumWidth(0); connect(this, SIGNAL(readOnlyChanged(bool)), this, SLOT(applyReadOnlyChange(bool))); m_setUpDockManagerTimer.setSingleShot(true); connect(&m_setUpDockManagerTimer, SIGNAL(timeout()), this, SLOT(keepMargins())); m_setUpDockManagerTimer.start(1000); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(98); } } MainWindow::~MainWindow() { // Delete backup of this sketch if one exists. QFile::remove(m_backupFileNameAndPath); delete m_sketchModel; dontKeepMargins(); m_setUpDockManagerTimer.stop(); foreach (LinkedFile * linkedFile, m_linkedProgramFiles) { delete linkedFile; } m_linkedProgramFiles.clear(); if (!m_fzzFolder.isEmpty()) { LockManager::releaseLockedFiles(m_fzzFolder, m_fzzFiles); FolderUtils::rmdir(m_fzzFolder); } } void MainWindow::initLockedFiles(bool lockFiles) { LockManager::initLockedFiles("fzz", m_fzzFolder, m_fzzFiles, lockFiles ? LockManager::SlowTime : 0); if (lockFiles) { QFileInfoList backupList; LockManager::checkLockedFiles("fzz", backupList, m_fzzFiles, true, LockManager::SlowTime); } } void MainWindow::initSketchWidgets(bool withIcons) { //DebugDialog::debug("init sketch widgets"); // all this belongs in viewLayer.xml m_breadboardGraphicsView = new BreadboardSketchWidget(ViewLayer::BreadboardView, this); initSketchWidget(m_breadboardGraphicsView); m_breadboardWidget = new SketchAreaWidget(m_breadboardGraphicsView,this); addTab(m_breadboardWidget, ":/resources/images/icons/TabWidgetBreadboardActive_icon.png", tr("Breadboard"), withIcons); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(11); } m_schematicGraphicsView = new SchematicSketchWidget(ViewLayer::SchematicView, this); initSketchWidget(m_schematicGraphicsView); m_schematicWidget = new SketchAreaWidget(m_schematicGraphicsView, this); addTab(m_schematicWidget, ":/resources/images/icons/TabWidgetSchematicActive_icon.png", tr("Schematic"), withIcons); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(20); } m_pcbGraphicsView = new PCBSketchWidget(ViewLayer::PCBView, this); initSketchWidget(m_pcbGraphicsView); m_pcbWidget = new SketchAreaWidget(m_pcbGraphicsView, this); addTab(m_pcbWidget, ":/resources/images/icons/TabWidgetPcbActive_icon.png", tr("PCB"), withIcons); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(29); } } void MainWindow::initMenus() { // This is the magic translation that changes all the shortcut text on the menu items // to the native language instead of "Ctrl", so the German menu items will now read "Strg" // You don't actually have to translate every menu item in the .ts file, you can just leave it as "Ctrl". QShortcut::tr("Ctrl", "for naming shortcut keys on menu items"); QShortcut::tr("Alt", "for naming shortcut keys on menu items"); QShortcut::tr("Shift", "for naming shortcut keys on menu items"); QShortcut::tr("Meta", "for naming shortcut keys on menu items"); //DebugDialog::debug("create menus"); createActions(); createMenus(); //DebugDialog::debug("create toolbars"); createStatusBar(); //DebugDialog::debug("after creating status bar"); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(91); } } void MainWindow::initSketchWidget(SketchWidget * sketchWidget) { sketchWidget->setSketchModel(m_sketchModel); sketchWidget->setReferenceModel(m_referenceModel); sketchWidget->setUndoStack(m_undoStack); sketchWidget->setChainDrag(true); // enable bend points sketchWidget->initGrid(); sketchWidget->addViewLayers(); } void MainWindow::connectPairs() { connectPair(m_breadboardGraphicsView, m_schematicGraphicsView); connectPair(m_breadboardGraphicsView, m_pcbGraphicsView); connectPair(m_schematicGraphicsView, m_breadboardGraphicsView); connectPair(m_schematicGraphicsView, m_pcbGraphicsView); connectPair(m_pcbGraphicsView, m_breadboardGraphicsView); connectPair(m_pcbGraphicsView, m_schematicGraphicsView); connect(m_pcbGraphicsView, SIGNAL(groundFillSignal()), this, SLOT(groundFill())); connect(m_pcbGraphicsView, SIGNAL(copperFillSignal()), this, SLOT(copperFill())); connect(m_pcbGraphicsView, SIGNAL(swapBoardImageSignal(SketchWidget *, ItemBase *, const QString &, const QString &, bool)), this, SLOT(swapBoardImageSlot(SketchWidget *, ItemBase *, const QString &, const QString &, bool))); connect(m_breadboardGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); connect(m_schematicGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); connect(m_pcbGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); connect(m_breadboardGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *))); connect(m_schematicGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *))); connect(m_pcbGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *))); bool succeeded = connect(m_pcbGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)), this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &))); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)), this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)), this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap &, ItemBase *)), this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap &, ItemBase *))); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap &, ItemBase *)), this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap &, ItemBase *))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap &, ItemBase *)), this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap &, ItemBase *))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), this, SLOT(dropPaste(SketchWidget *))); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), this, SLOT(dropPaste(SketchWidget *))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), this, SLOT(dropPaste(SketchWidget *))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(subSwapSignal(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerPlacement, long &, QUndoCommand *)), this, SLOT(subSwapSlot(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerPlacement, long &, QUndoCommand *)), Qt::DirectConnection); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(updateLayerMenuSignal()), this, SLOT(updateLayerMenuSlot())); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(changeBoardLayersSignal(int, bool )), this, SLOT(changeBoardLayers(int, bool ))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(boardDeletedSignal()), this, SLOT(boardDeletedSlot())); succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_breadboardGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_schematicGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_pcbGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(getDroppedItemViewLayerPlacementSignal(ModelPart *, ViewLayer::ViewLayerPlacement &)), m_pcbGraphicsView, SLOT(getDroppedItemViewLayerPlacement(ModelPart *, ViewLayer::ViewLayerPlacement &)), Qt::DirectConnection); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(getDroppedItemViewLayerPlacementSignal(ModelPart *, ViewLayer::ViewLayerPlacement &)), m_pcbGraphicsView, SLOT(getDroppedItemViewLayerPlacement(ModelPart *, ViewLayer::ViewLayerPlacement &)), Qt::DirectConnection); if (!succeeded) { DebugDialog::debug("connectPair failed"); } } void MainWindow::connectPair(SketchWidget * signaller, SketchWidget * slotter) { bool succeeded = connect(signaller, SIGNAL(itemAddedSignal(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *)), slotter, SLOT(itemAddedSlot(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *))); succeeded = succeeded && connect(signaller, SIGNAL(itemDeletedSignal(long)), slotter, SLOT(itemDeletedSlot(long)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(clearSelectionSignal()), slotter, SLOT(clearSelectionSlot())); succeeded = succeeded && connect(signaller, SIGNAL(itemSelectedSignal(long, bool)), slotter, SLOT(itemSelectedSlot(long, bool))); succeeded = succeeded && connect(signaller, SIGNAL(selectAllItemsSignal(bool, bool)), slotter, SLOT(selectAllItems(bool, bool))); succeeded = succeeded && connect(signaller, SIGNAL(wireDisconnectedSignal(long, QString)), slotter, SLOT(wireDisconnectedSlot(long, QString))); succeeded = succeeded && connect(signaller, SIGNAL(wireConnectedSignal(long, QString, long, QString)), slotter, SLOT(wireConnectedSlot(long, QString, long, QString))); succeeded = succeeded && connect(signaller, SIGNAL(changeConnectionSignal(long, QString, long, QString, ViewLayer::ViewLayerPlacement, bool, bool)), slotter, SLOT(changeConnectionSlot(long, QString, long, QString, ViewLayer::ViewLayerPlacement, bool, bool))); succeeded = succeeded && connect(signaller, SIGNAL(copyBoundingRectsSignal(QHash &)), slotter, SLOT(copyBoundingRectsSlot(QHash &)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(cleanUpWiresSignal(CleanUpWiresCommand *)), slotter, SLOT(cleanUpWiresSlot(CleanUpWiresCommand *)) ); succeeded = succeeded && connect(signaller, SIGNAL(cleanupRatsnestsSignal(bool)), slotter, SLOT(cleanupRatsnests(bool)) ); succeeded = succeeded && connect(signaller, SIGNAL(checkStickySignal(long, bool, bool, CheckStickyCommand *)), slotter, SLOT(checkSticky(long, bool, bool, CheckStickyCommand *)) ); succeeded = succeeded && connect(signaller, SIGNAL(disconnectAllSignal(QList, QHash &, QUndoCommand *)), slotter, SLOT(disconnectAllSlot(QList, QHash &, QUndoCommand *)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(setResistanceSignal(long, QString, QString, bool)), slotter, SLOT(setResistance(long, QString, QString, bool))); succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandPrepSignal(ItemBase *, bool , QUndoCommand * )), slotter, SLOT(makeDeleteItemCommandPrepSlot(ItemBase * , bool , QUndoCommand * ))); succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandFinalSignal(ItemBase *, bool , QUndoCommand * )), slotter, SLOT(makeDeleteItemCommandFinalSlot(ItemBase * , bool , QUndoCommand * ))); succeeded = succeeded && connect(signaller, SIGNAL(setPropSignal(long, const QString &, const QString &, bool, bool)), slotter, SLOT(setProp(long, const QString &, const QString &, bool, bool))); succeeded = succeeded && connect(signaller, SIGNAL(setInstanceTitleSignal(long, const QString &, const QString &, bool, bool )), slotter, SLOT(setInstanceTitle(long, const QString &, const QString &, bool, bool ))); succeeded = succeeded && connect(signaller, SIGNAL(setVoltageSignal(double, bool )), slotter, SLOT(setVoltage(double, bool ))); succeeded = succeeded && connect(signaller, SIGNAL(showLabelFirstTimeSignal(long, bool, bool )), slotter, SLOT(showLabelFirstTime(long, bool, bool ))); succeeded = succeeded && connect(signaller, SIGNAL(changeBoardLayersSignal(int, bool )), slotter, SLOT(changeBoardLayers(int, bool ))); succeeded = succeeded && connect(signaller, SIGNAL(deleteTracesSignal(QSet &, QHash &, QList &, bool, QUndoCommand *)), slotter, SLOT(deleteTracesSlot(QSet &, QHash &, QList &, bool, QUndoCommand *)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(ratsnestConnectSignal(long, const QString &, bool, bool)), slotter, SLOT(ratsnestConnect(long, const QString &, bool, bool )), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(updatePartLabelInstanceTitleSignal(long)), slotter, SLOT(updatePartLabelInstanceTitleSlot(long))); succeeded = succeeded && connect(signaller, SIGNAL(changePinLabelsSignal(ItemBase *, bool)), slotter, SLOT(changePinLabelsSlot(ItemBase *, bool))); succeeded = succeeded && connect(signaller, SIGNAL(collectRatsnestSignal(QList &)), slotter, SLOT(collectRatsnestSlot(QList &)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(removeRatsnestSignal(QList &, QUndoCommand *)), slotter, SLOT(removeRatsnestSlot(QList &, QUndoCommand *)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(canConnectSignal(Wire *, ItemBase *, bool &)), slotter, SLOT(canConnect(Wire *, ItemBase *, bool &)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(swapStartSignal(SwapThing &, bool)), slotter, SLOT(swapStart(SwapThing &, bool)), Qt::DirectConnection); succeeded = succeeded && connect(signaller, SIGNAL(packItemsSignal(int, const QList &, QUndoCommand *, bool)), slotter, SLOT(packItems(int, const QList &, QUndoCommand *, bool))); succeeded = succeeded && connect(signaller, SIGNAL(addSubpartSignal(long, long, bool)), slotter, SLOT(addSubpart(long, long, bool))); if (!succeeded) { DebugDialog::debug("connectPair failed"); } } void MainWindow::setCurrentFile(const QString &filename, bool addToRecent, bool setAsLastOpened) { setFileName(filename); if (setAsLastOpened) { QSettings settings; settings.setValue("lastOpenSketch",filename); m_useOldSchematic = false; if (m_convertedSchematic) { m_convertedSchematic = false; QString gridSize = QString("%1in").arg(m_schematicGraphicsView->defaultGridSizeInches()); m_schematicGraphicsView->setGridSize(gridSize); setCurrentTabIndex(2); m_schematicGraphicsView->resizeLabels(); m_schematicGraphicsView->resizeWires(); m_schematicGraphicsView->updateWires(); setWindowModified(true); } else { QStringList files = settings.value("lastTabList").toStringList(); for (int ix = files.count() - 1; ix >= 0; ix--) { if (files[ix].mid(1) == filename) { bool ok; int lastTab = files[ix].left(1).toInt(&ok); if (ok) { setCurrentTabIndex(lastTab); } } } } } updateRaiseWindowAction(); setTitle(); if(addToRecent) { QSettings settings; QStringList files = settings.value("recentFileList").toStringList(); files.removeAll(filename); files.prepend(filename); while (files.size() > MaxRecentFiles) files.removeLast(); settings.setValue("recentFileList", files); QTimer::singleShot(1, this, SLOT(updateWelcomeViewRecentList())); // TODO: if lastTab file is not on recent list, remove it from the settings } foreach (QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWin = qobject_cast(widget); if (mainWin) mainWin->updateRecentFileActions(); } } void MainWindow::createZoomOptions(SketchAreaWidget* parent) { connect(parent->contentView(), SIGNAL(zoomChanged(double)), this, SLOT(updateZoomSlider(double))); connect(parent->contentView(), SIGNAL(zoomOutOfRange(double)), this, SLOT(updateZoomOptionsNoMatterWhat(double))); } ExpandingLabel * MainWindow::createRoutingStatusLabel(SketchAreaWidget * parent) { ExpandingLabel * routingStatusLabel = new ExpandingLabel(m_pcbWidget); connect(routingStatusLabel, SIGNAL(mousePressSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMousePress(QMouseEvent*))); connect(routingStatusLabel, SIGNAL(mouseReleaseSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMouseRelease(QMouseEvent*))); routingStatusLabel->setTextInteractionFlags(Qt::NoTextInteraction); routingStatusLabel->setCursor(Qt::WhatsThisCursor); routingStatusLabel->viewport()->setCursor(Qt::WhatsThisCursor); routingStatusLabel->setObjectName(SketchAreaWidget::RoutingStateLabelName); routingStatusLabel->setToolTip(tr("Click to highlight unconnected parts")); parent->setRoutingStatusLabel(routingStatusLabel); RoutingStatus routingStatus; routingStatus.zero(); routingStatusSlot(qobject_cast(parent->contentView()), routingStatus); return routingStatusLabel; } SketchToolButton *MainWindow::createRotateButton(SketchAreaWidget *parent) { QList rotateMenuActions; rotateMenuActions << m_rotate45ccwAct << m_rotate90ccwAct << m_rotate180Act << m_rotate90cwAct << m_rotate45cwAct; SketchToolButton * rotateButton = new SketchToolButton("Rotate",parent, rotateMenuActions); rotateButton->setDefaultAction(m_rotate90ccwAct); rotateButton->setText(tr("Rotate")); m_rotateButtons << rotateButton; return rotateButton; } SketchToolButton *MainWindow::createShareButton(SketchAreaWidget *parent) { SketchToolButton *shareButton = new SketchToolButton("Share",parent, m_shareOnlineAct); shareButton->setText(tr("Share")); shareButton->setObjectName("shareProjectButton"); shareButton->setEnabledIcon(); // seems to need this to display button icon first time return shareButton; } SketchToolButton *MainWindow::createFlipButton(SketchAreaWidget *parent) { QList flipMenuActions; flipMenuActions << m_flipHorizontalAct << m_flipVerticalAct; SketchToolButton *flipButton = new SketchToolButton("Flip",parent, flipMenuActions); flipButton->setText(tr("Flip")); m_flipButtons << flipButton; return flipButton; } SketchToolButton *MainWindow::createAutorouteButton(SketchAreaWidget *parent) { SketchToolButton *autorouteButton = new SketchToolButton("Autoroute",parent, m_newAutorouteAct); autorouteButton->setText(tr("Autoroute")); autorouteButton->setEnabledIcon(); // seems to need this to display button icon first time return autorouteButton; } SketchToolButton *MainWindow::createOrderFabButton(SketchAreaWidget *parent) { SketchToolButton *orderFabButton = new SketchToolButton("Order",parent, m_orderFabAct); orderFabButton->setText(tr("Fabricate")); orderFabButton->setObjectName("orderFabButton"); orderFabButton->setEnabledIcon();// seems to need this to display button icon first time connect(orderFabButton, SIGNAL(entered()), this, SLOT(orderFabHoverEnter())); connect(orderFabButton, SIGNAL(left()), this, SLOT(orderFabHoverLeave())); return orderFabButton; } QWidget *MainWindow::createActiveLayerButton(SketchAreaWidget *parent) { QList actions; actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct; m_activeLayerButtonWidget = new QStackedWidget; // m_activeLayerButtonWidget->setMaximumWidth(90); m_activeLayerButtonWidget->setObjectName("activeLayerButton"); SketchToolButton * button = new SketchToolButton("ActiveLayer", parent, actions); button->setDefaultAction(m_activeLayerBottomAct); button->setText(tr("Both Layers")); m_activeLayerButtonWidget->addWidget(button); button = new SketchToolButton("ActiveLayerB", parent, actions); button->setDefaultAction(m_activeLayerTopAct); button->setText(tr("Bottom Layer")); m_activeLayerButtonWidget->addWidget(button); button = new SketchToolButton("ActiveLayerT", parent, actions); button->setDefaultAction(m_activeLayerBothAct); button->setText(tr("Top Layer")); m_activeLayerButtonWidget->addWidget(button); return m_activeLayerButtonWidget; } QWidget *MainWindow::createViewFromButton(SketchAreaWidget *parent) { QList actions; actions << m_viewFromAboveAct << m_viewFromBelowAct; m_viewFromButtonWidget = new QStackedWidget; // m_viewFromButtonWidget->setMaximumWidth(95); m_viewFromButtonWidget->setObjectName("viewFromButton"); SketchToolButton * button = new SketchToolButton("ViewFromT", parent, actions); button->setDefaultAction(m_viewFromBelowAct); button->setText(tr("View from Above")); button->setEnabledIcon(); // seems to need this to display button icon first time m_viewFromButtonWidget->addWidget(button); button = new SketchToolButton("ViewFromB", parent, actions); button->setDefaultAction(m_viewFromAboveAct); button->setText(tr("View from Below")); button->setEnabledIcon(); // seems to need this to display button icon first time m_viewFromButtonWidget->addWidget(button); return m_viewFromButtonWidget; } SketchToolButton *MainWindow::createNoteButton(SketchAreaWidget *parent) { SketchToolButton *noteButton = new SketchToolButton("Notes",parent, m_addNoteAct); noteButton->setObjectName("noteButton"); noteButton->setText(tr("Add a note")); noteButton->setEnabledIcon(); // seems to need this to display button icon first time return noteButton; } SketchToolButton *MainWindow::createExportEtchableButton(SketchAreaWidget *parent) { QList actions; actions << m_exportEtchablePdfAct << m_exportEtchableSvgAct << m_exportGerberAct; SketchToolButton *exportEtchableButton = new SketchToolButton("Diy",parent, actions); exportEtchableButton->setObjectName("exportButton"); exportEtchableButton->setDefaultAction(m_exportEtchablePdfAct); exportEtchableButton->setText(tr("Export for PCB")); exportEtchableButton->setEnabledIcon(); // seems to need this to display button icon first time return exportEtchableButton; } QWidget *MainWindow::createToolbarSpacer(SketchAreaWidget *parent) { QFrame *toolbarSpacer = new QFrame(parent); QHBoxLayout *spacerLayout = new QHBoxLayout(toolbarSpacer); spacerLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); return toolbarSpacer; } QList MainWindow::getButtonsForView(ViewLayer::ViewID viewId) { QList retval; SketchAreaWidget *parent; switch(viewId) { case ViewLayer::BreadboardView: parent = m_breadboardWidget; break; case ViewLayer::SchematicView: parent = m_schematicWidget; break; case ViewLayer::PCBView: parent = m_pcbWidget; break; default: return retval; } switch(viewId) { case ViewLayer::BreadboardView: case ViewLayer::SchematicView: retval << createNoteButton(parent); default: break; } retval << createRotateButton(parent); switch (viewId) { case ViewLayer::BreadboardView: retval << createFlipButton(parent) << createRoutingStatusLabel(parent); break; case ViewLayer::SchematicView: retval << createFlipButton(parent) << createAutorouteButton(parent) << createRoutingStatusLabel(parent); break; case ViewLayer::PCBView: retval << createViewFromButton(parent) << createActiveLayerButton(parent) << createAutorouteButton(parent) << createExportEtchableButton(parent) << createRoutingStatusLabel(parent) ; if (m_orderFabEnabled) { m_orderFabButton = createOrderFabButton(parent); retval << m_orderFabButton; } break; default: break; } retval << createShareButton(parent); return retval; } void MainWindow::updateZoomSlider(double zoom) { m_zoomSlider->setValue(zoom); } SketchAreaWidget *MainWindow::currentSketchArea() { if (m_currentGraphicsView == NULL) return NULL; return dynamic_cast(m_currentGraphicsView->parent()); } void MainWindow::updateZoomOptionsNoMatterWhat(double zoom) { m_zoomSlider->setValue(zoom); } void MainWindow::updateViewZoom(double newZoom) { m_comboboxChanged = true; if(m_currentGraphicsView) m_currentGraphicsView->absoluteZoom(newZoom); } void MainWindow::createStatusBar() { m_statusBar->showMessage(tr("Ready")); } void MainWindow::tabWidget_currentChanged(int index) { SketchAreaWidget * widgetParent = dynamic_cast(currentTabWidget()); if (widgetParent == NULL) return; m_currentWidget = widgetParent; if (m_locationLabel) { m_locationLabel->setText(""); } QStatusBar *sb = statusBar(); connect(sb, SIGNAL(messageChanged(const QString &)), this, SLOT(showStatusMessage(const QString &))); widgetParent->addStatusBar(m_statusBar); if(sb != m_statusBar) sb->hide(); if (m_breadboardGraphicsView) m_breadboardGraphicsView->setCurrent(false); if (m_schematicGraphicsView) m_schematicGraphicsView->setCurrent(false); if (m_pcbGraphicsView) m_pcbGraphicsView->setCurrent(false); SketchWidget *widget = qobject_cast(widgetParent->contentView()); if(m_currentGraphicsView) { m_currentGraphicsView->saveZoom(m_zoomSlider->value()); disconnect( m_currentGraphicsView, SIGNAL(selectionChangedSignal()), this, SLOT(updateTransformationActions()) ); } m_currentGraphicsView = widget; if (m_programView) { hideShowProgramMenu(); } hideShowTraceMenu(); updateEditMenu(); if (m_showBreadboardAct) { QList actions; if (m_welcomeView) actions << m_showWelcomeAct; actions << m_showBreadboardAct << m_showSchematicAct << m_showPCBAct; if (m_programView) actions << m_showProgramAct; setActionsIcons(index, actions); } if (widget == NULL) { m_firstTimeHelpAct->setEnabled(false); return; } m_zoomSlider->setValue(m_currentGraphicsView->retrieveZoom()); FirstTimeHelpDialog::setViewID(m_currentGraphicsView->viewID()); m_firstTimeHelpAct->setEnabled(true); connect( m_currentGraphicsView, // don't connect directly to the scene here, connect to the widget's signal SIGNAL(selectionChangedSignal()), this, SLOT(updateTransformationActions()) ); updateActiveLayerButtons(); m_currentGraphicsView->setCurrent(true); // !!!!!! hack alert !!!!!!! // this item update loop seems to deal with a qt update bug: // if one view is visible and you change something in another view, // the change might not appear when you switch views until you move the item in question foreach(QGraphicsItem * item, m_currentGraphicsView->items()) { item->update(); } updateLayerMenu(true); updateTraceMenu(); updateTransformationActions(); setTitle(); if (m_infoView) { m_currentGraphicsView->updateInfoView(); } // update issue with 4.5.1?: is this still valid (4.6.x?) m_currentGraphicsView->updateConnectors(); QTimer::singleShot(10, this, SLOT(initZoom())); } void MainWindow::setActionsIcons(int index, QList & actions) { for (int i = 0; i < actions.count(); i++) { // DebugDialog::debug(QString("setting icon %1 %2").arg(i).arg(index == i)); // setting the icons seems to be broken in Qt 5, so use checkMarks instead // note that we used dots instead of checkMarks originally because // we hoped it was clearer that the items were mutually exclusive // note that using QIcon() instead of m_emptyIcon does no good // (and we used the m_emptyIcon to preserve the space at the left) // actions[i]->setIcon(index == i ? m_dotIcon : m_emptyIcon); actions[i]->setChecked(index == i); } } void MainWindow::closeEvent(QCloseEvent *event) { if (m_dontClose) { event->ignore(); return; } if (m_programWindow) { m_programWindow->close(); if (m_programWindow->isVisible()) { event->ignore(); return; } } if (!m_closeSilently) { bool whatWithAliens = whatToDoWithAlienFiles(); bool discard; if(!beforeClosing(true, discard) || !whatWithAliens ||!m_binManager->beforeClosing()) { event->ignore(); return; } if(whatWithAliens && m_binManager->hasAlienParts()) { m_binManager->createIfMyPartsNotExists(); } } //DebugDialog::debug(QString("top level windows: %1").arg(QApplication::topLevelWidgets().size())); /* foreach (QWidget * widget, QApplication::topLevelWidgets()) { QMenu * menu = qobject_cast(widget); if (menu != NULL) { continue; // QMenus are always top level widgets, even if they have parents... } DebugDialog::debug(QString("top level widget %1 %2 %3") .arg(widget->metaObject()->className()) .arg(widget->windowTitle()) .arg(widget->toolTip()) ); } */ m_closing = true; int count = 0; foreach (QWidget *widget, QApplication::topLevelWidgets()) { if (widget == this) continue; if (qobject_cast(widget) == NULL) continue; count++; } if (count == 0) { DebugDialog::closeDebug(); } QSettings settings; settings.setValue(m_settingsPrefix + "state",saveState()); settings.setValue(m_settingsPrefix + "geometry",saveGeometry()); saveLastTabList(); QMainWindow::closeEvent(event); } void MainWindow::saveLastTabList() { QSettings settings; QStringList files = settings.value("lastTabList").toStringList(); for (int ix = files.count() - 1; ix >= 0; ix--) { if (files[ix].mid(1) == m_fwFilename) files.removeAt(ix); } files.prepend(QString("%1%2").arg(this->currentTabIndex()).arg(m_fwFilename)); while (files.size() > MaxRecentFiles) files.removeLast(); settings.setValue("lastTabList", files); } bool MainWindow::whatToDoWithAlienFiles() { if (m_alienFiles.size() > 0) { QString basename = QFileInfo(m_fwFilename).fileName(); QMessageBox::StandardButton reply; reply = QMessageBox::question(this, tr("Save %1").arg(basename), m_alienPartsMsg .arg(basename), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); // TODO: translate button text if (reply == QMessageBox::Yes) { return true; } else if (reply == QMessageBox::No) { foreach(QString pathToRemove, m_alienFiles) { QFile::remove(pathToRemove); } m_alienFiles.clear(); recoverBackupedFiles(); emit alienPartsDismissed(); return true; } else { return false; } } else { return true; } } void MainWindow::acceptAlienFiles() { m_alienFiles.clear(); } bool MainWindow::eventFilter(QObject *object, QEvent *event) { if (object == this && (event->type() == QEvent::KeyPress // || event->type() == QEvent::KeyRelease || event->type() == QEvent::ShortcutOverride)) { //DebugDialog::debug(QString("event filter %1").arg(event->type()) ); updatePartMenu(); updateTraceMenu(); // On the mac, the first time the delete key is pressed, to be used as a shortcut for QAction m_deleteAct, // for some reason, the enabling of the m_deleteAct in UpdateEditMenu doesn't "take" until the next time the event loop is processed // Thereafter, the delete key works as it should. // So this call to processEvents() makes sure m_deleteAct is enabled. ProcessEventBlocker::processEvents(); } #if defined(Q_OS_MAC) && (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) // Need to process Backspace on Mac to workaround bug in Qt5 // See http://qt-project.org/forums/viewthread/36174 if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Backspace) { Qt::KeyboardModifiers modifiers = keyEvent->modifiers(); if (modifiers == Qt::NoModifier) { doDelete(); return true; } if (modifiers == Qt::AltModifier) { doDeleteMinus(); return true; } } } #endif return QMainWindow::eventFilter(object, event); } const QString MainWindow::untitledFileName() { return UntitledSketchName; } int &MainWindow::untitledFileCount() { return UntitledSketchIndex; } const QString MainWindow::fileExtension() { return FritzingBundleExtension; } const QString MainWindow::defaultSaveFolder() { return FolderUtils::openSaveFolder(); } bool MainWindow::undoStackIsEmpty() { return m_undoStack->count() == 0; } void MainWindow::setInfoViewOnHover(bool infoViewOnHover) { m_breadboardGraphicsView->setInfoViewOnHover(infoViewOnHover); m_schematicGraphicsView->setInfoViewOnHover(infoViewOnHover); m_pcbGraphicsView->setInfoViewOnHover(infoViewOnHover); m_binManager->setInfoViewOnHover(infoViewOnHover); } void MainWindow::loadBundledSketch(const QString &fileName, bool addToRecent, bool setAsLastOpened, bool checkObsolete) { QString error; if(!FolderUtils::unzipTo(fileName, m_fzzFolder, error)) { FMessageBox::warning( this, tr("Fritzing"), tr("Unable to open '%1': %2").arg(fileName).arg(error) ); return; } QDir dir(m_fzzFolder); QString binFileName = dir.absoluteFilePath(QFileInfo(BinManager::TempPartsBinTemplateLocation).fileName()); m_binManager->setTempPartsBinLocation(binFileName); FolderUtils::copyBin(binFileName, BinManager::TempPartsBinTemplateLocation); QStringList namefilters; namefilters << "*"+FritzingSketchExtension; QFileInfoList entryInfoList = dir.entryInfoList(namefilters); if (entryInfoList.count() == 0) { FMessageBox::warning( this, tr("Fritzing"), tr("No Sketch found in '%1'").arg(fileName) ); return; } QFileInfo sketchInfo = entryInfoList[0]; QString sketchName = dir.absoluteFilePath(sketchInfo.fileName()); namefilters.clear(); namefilters << "*" + FritzingPartExtension; entryInfoList = dir.entryInfoList(namefilters); namefilters.clear(); namefilters << "*.svg"; QFileInfoList svgEntryInfoList = dir.entryInfoList(namefilters); m_addedToTemp = false; QList missing; QList missingModelParts; foreach (QFileInfo fzpInfo, entryInfoList) { QFile file(dir.absoluteFilePath(fzpInfo.fileName())); if (!file.open(QFile::ReadOnly)) { DebugDialog::debug(QString("unable to open %1: %2").arg(file.fileName())); continue; } // TODO: could be more efficient by using a streamreader QString fzp = file.readAll(); file.close(); QString moduleID = TextUtils::parseForModuleID(fzp); if (moduleID.isEmpty()) { DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); DebugDialog::debug(QString("unable to find module id in %1: %2").arg(file.fileName()).arg(fzp)); DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); continue; } ModelPart * mp = m_referenceModel->retrieveModelPart(moduleID); if (mp == NULL) { QDomDocument doc; if (!doc.setContent(fzp)) { DebugDialog::debug(QString("unable to parse fzp in %1: %2").arg(file.fileName()).arg(fzp)); continue; } mp = copyToPartsFolder(fzpInfo, false, PartFactory::folderPath(), "contrib"); if (mp == NULL) { DebugDialog::debug(QString("unable to create model part in %1: %2").arg(file.fileName()).arg(fzp)); continue; } QDomElement root = doc.documentElement(); QDomElement views = root.firstChildElement("views"); QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement layers = view.firstChildElement("layers"); QString path = layers.attribute("image", ""); if (!path.isEmpty()) { bool copied = copySvg(path, svgEntryInfoList); if (!copied) { DebugDialog::debug(QString("missing svg %1").arg(path)); MissingSvgInfo msi; msi.equal = false; msi.modelPart = mp; missingModelParts << mp; msi.requestedPath = path; ViewLayer::ViewID viewID = ViewLayer::idFromXmlName(view.tagName()); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString id, terminalID; ViewLayer::getConnectorSvgIDs(connector, viewID, id, terminalID); if (!id.isEmpty()) { msi.connectorSvgIds.append(id); } connector = connector.nextSiblingElement("connector"); } missing << msi; } } view = view.nextSiblingElement(); } mp->setFzz(true); } if (!missingModelParts.contains(mp)) { m_binManager->addToTempPartsBin(mp); m_addedToTemp = true; } } qSort(missing.begin(), missing.end(), byConnectorCount); foreach (MissingSvgInfo msi, missing) { if (msi.equal) { // two or more parts have the same number of connectors--so we can't figure out how to assign them continue; } int slash = msi.requestedPath.indexOf("/"); QString suffix = msi.requestedPath.mid(slash + 1); QString prefix = msi.requestedPath.left(slash); for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) { QFileInfo svgInfo = svgEntryInfoList.at(jx); if (!svgInfo.fileName().contains(prefix, Qt::CaseInsensitive)) continue; QFile svgfile(svgInfo.absoluteFilePath()); QDomDocument svgDoc; if (!svgDoc.setContent(&svgfile)) continue; QList elements; QDomElement root = svgDoc.documentElement(); TextUtils::findElementsWithAttribute(root, "id", elements); if (elements.count() < msi.connectorSvgIds.count()) continue; QStringList ids; foreach (QDomElement element, elements) { ids << element.attribute("id"); } bool allGood = true; foreach (QString id, msi.connectorSvgIds) { if (!ids.contains(id)) { allGood = false; break; } } if (!allGood) continue; QString destPath = copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib"); // copy file with original name if (!destPath.isEmpty()) { QFileInfo destInfo(destPath); QFile file(destPath); DebugDialog::debug(QString("found missing %1").arg(destPath)); FolderUtils::slamCopy(file, destInfo.absoluteDir().absoluteFilePath(suffix)); // make another copy that has the name used in the fzp file svgEntryInfoList.removeAt(jx); break; } } } foreach (ModelPart * mp, missingModelParts) { m_binManager->addToTempPartsBin(mp); m_addedToTemp = true; } if (!m_addedToTemp) { m_binManager->hideTempPartsBin(); } // the bundled itself this->mainLoad(sketchName, "", checkObsolete); setCurrentFile(fileName, addToRecent, setAsLastOpened); } bool MainWindow::copySvg(const QString & path, QFileInfoList & svgEntryInfoList) { int slash = path.indexOf("/"); QString subpath = path.mid(slash + 1); bool gotOne = false; for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) { QFileInfo svgInfo = svgEntryInfoList.at(jx); if (svgInfo.fileName().contains(subpath)) { copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib"); svgEntryInfoList.removeAt(jx); // jrc 30 oct 2012: not sure why we can't just return at this point--can there be other matching files? gotOne = true; } } if (gotOne) return true; // deal with a bug in which all the svg files exist in the fzz but the fz file points to the wrong name // most of the time it's just a GUID difference DebugDialog::debug(QString("svg matching fz path %1 not found").arg(path)); int guidix = GuidMatcher.lastIndexIn(subpath); if (guidix < 0) return false; QString originalGuid = GuidMatcher.cap(0); QString tryPath = subpath; tryPath.replace(guidix, originalGuid.length(), "%%%%"); for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) { QFileInfo svgInfo = svgEntryInfoList.at(jx); QString tempPath = svgInfo.fileName(); guidix = GuidMatcher.lastIndexIn(tempPath); if (guidix < 0) continue; tempPath.replace(guidix, GuidMatcher.cap(0).length(), "%%%%"); if (!tempPath.contains(tryPath)) continue; QString destPath = copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib"); if (!destPath.isEmpty()) { QFile file(destPath); guidix = GuidMatcher.lastIndexIn(destPath); destPath.replace(guidix, GuidMatcher.cap(0).length(), originalGuid); FolderUtils::slamCopy(file, destPath); DebugDialog::debug(QString("found matching svg %1").arg(destPath)); svgEntryInfoList.removeAt(jx); return true; } } return false; } bool MainWindow::loadBundledNonAtomicEntity(const QString &fileName, Bundler* bundler, bool addToBin, bool dontAsk) { QDir destFolder = QDir::temp(); FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText()); QString unzipDirPath = destFolder.path(); QString error; if(!FolderUtils::unzipTo(fileName, unzipDirPath, error)) { FMessageBox::warning( this, tr("Fritzing"), tr("Unable to open shareable '%1': %2").arg(fileName).arg(error) ); // gotta return now, or loadBundledSketchAux will crash return false; } QDir unzipDir(unzipDirPath); if (bundler->preloadBundledAux(unzipDir, dontAsk)) { QList mps = moveToPartsFolder(unzipDir,this,addToBin,true,FolderUtils::getUserDataStorePath("parts"), "contrib", false); // the bundled itself bundler->loadBundledAux(unzipDir,mps); } FolderUtils::rmdir(unzipDirPath); return true; } /* void MainWindow::loadBundledPartFromWeb() { QMainWindow *mw = new QMainWindow(); QString url = "http://localhost:8081/parts_gen/choose"; QWebView *view = new QWebView(mw); mw->setCentralWidget(view); view->setUrl(QUrl(url)); mw->show(); mw->raise(); } */ ModelPart* MainWindow::loadBundledPart(const QString &fileName, bool addToBin) { QDir destFolder = QDir::temp(); FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText()); QString unzipDirPath = destFolder.path(); QString error; if(!FolderUtils::unzipTo(fileName, unzipDirPath, error)) { FMessageBox::warning( this, tr("Fritzing"), tr("Unable to open shareable part '%1': %2").arg(fileName).arg(error) ); return NULL; } QDir unzipDir(unzipDirPath); QList mps; try { mps = moveToPartsFolder(unzipDir, this, addToBin, true, FolderUtils::getUserDataStorePath("parts"), "user", true); } catch (const QString & msg) { FMessageBox::warning( this, tr("Fritzing"), msg ); return NULL; } if (mps.count() != 1) { // if this fails, that means that the bundled was wrong FMessageBox::warning( this, tr("Fritzing"), tr("Unable to load part from '%1'").arg(fileName) ); return NULL; } FolderUtils::rmdir(unzipDirPath); return mps[0]; } void MainWindow::saveBundledPart(const QString &moduleId) { QString modIdToExport; ModelPart* mp; if(moduleId.isEmpty()) { if (m_currentGraphicsView == NULL) return; PaletteItem *selectedPart = m_currentGraphicsView->getSelectedPart(); mp = selectedPart->modelPart(); modIdToExport = mp->moduleID(); } else { modIdToExport = moduleId; mp = m_referenceModel->retrieveModelPart(moduleId); } QString partTitle = mp->title(); QString fileExt; QString path = defaultSaveFolder()+"/"+partTitle+FritzingBundledPartExtension; QString bundledFileName = FolderUtils::getSaveFileName( this, tr("Specify a file name"), path, tr("Fritzing Part (*%1)").arg(FritzingBundledPartExtension), &fileExt ); if (bundledFileName.isEmpty()) return; // Cancel pressed if(!alreadyHasExtension(bundledFileName, FritzingBundledPartExtension)) { bundledFileName += FritzingBundledPartExtension; } QDir destFolder = QDir::temp(); FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText()); QString dirToRemove = destFolder.path(); QString aux = QFileInfo(bundledFileName).fileName(); QString destPartPath = // remove the last "z" from the extension destFolder.path()+"/"+aux.left(aux.size()-1); DebugDialog::debug("saving part temporarily to "+destPartPath); //bool wasModified = isWindowModified(); //QString prevFileName = m_fileName; //saveAsAux(destPartPath); //m_fileName = prevFileName; //setWindowModified(wasModified); setTitle(); saveBundledAux(mp, destFolder); QStringList skipSuffixes; if(!FolderUtils::createZipAndSaveTo(destFolder, bundledFileName, skipSuffixes)) { FMessageBox::warning( this, tr("Fritzing"), tr("Unable to export %1 to shareable sketch").arg(bundledFileName) ); } FolderUtils::rmdir(dirToRemove); } QStringList MainWindow::saveBundledAux(ModelPart *mp, const QDir &destFolder) { QStringList names; QString partPath = mp->path(); QFile file(partPath); QString fn = ZIP_PART + QFileInfo(partPath).fileName(); names << fn; FolderUtils::slamCopy(file, destFolder.path()+"/"+fn); QList viewIDs; viewIDs << ViewLayer::IconView << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; foreach (ViewLayer::ViewID viewID, viewIDs) { QString basename = mp->hasBaseNameFor(viewID); if (basename.isEmpty()) continue; QString filename = PartFactory::getSvgFilename(mp, basename, true, true); if (filename.isEmpty()) continue; QFile file(filename); basename.replace("/", "."); QString fn = ZIP_SVG + basename; names << fn; FolderUtils::slamCopy(file, destFolder.path()+"/"+fn); } return names; } QList MainWindow::moveToPartsFolder(QDir &unzipDir, MainWindow* mw, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder, bool importingSinglePart) { QStringList namefilters; QList retval; if (mw == NULL) { throw tr("MainWindow::moveToPartsFolder mainwindow missing"); } namefilters.clear(); namefilters << ZIP_PART+"*"; QList partEntryInfoList = unzipDir.entryInfoList(namefilters); if (importingSinglePart && partEntryInfoList.count() > 0) { // TODO use a stream reader QFile file(partEntryInfoList[0].absoluteFilePath()); file.open(QFile::ReadOnly); QString fzp = file.readAll(); file.close(); QString moduleID = TextUtils::parseForModuleID(fzp); if (!moduleID.isEmpty() && m_referenceModel->retrieveModelPart(moduleID) != NULL) { throw tr("There is already a part with id '%1' loaded into Fritzing.").arg(moduleID); } } namefilters.clear(); namefilters << ZIP_SVG+"*"; foreach(QFileInfo file, unzipDir.entryInfoList(namefilters)) { // svg files //DebugDialog::debug("unzip svg " + file.absoluteFilePath()); mw->copyToSvgFolder(file, addToAlien, prefixFolder, destFolder); } foreach(QFileInfo file, partEntryInfoList) { // part files //DebugDialog::debug("unzip part " + file.absoluteFilePath()); ModelPart * mp = mw->copyToPartsFolder(file, addToAlien, prefixFolder, destFolder); retval << mp; if (addToBin) { // should only be here when adding single new part m_binManager->addToMyParts(mp); } } return retval; } QString MainWindow::copyToSvgFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder) { QFile svgfile(file.filePath()); // let's make sure that we remove just the suffix QString fileName = file.fileName().remove(QRegExp("^"+ZIP_SVG)); QString viewFolder = fileName.left(fileName.indexOf(".")); fileName.remove(0, viewFolder.length() + 1); QString destFilePath = prefixFolder+"/svg/"+destFolder+"/"+viewFolder+"/"+fileName; backupExistingFileIfExists(destFilePath); if(FolderUtils::slamCopy(svgfile, destFilePath)) { if (addToAlien) { m_alienFiles << destFilePath; } return destFilePath; } return ""; } ModelPart* MainWindow::copyToPartsFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder) { QFile partfile(file.filePath()); // let's make sure that we remove just the suffix QString destFilePath = prefixFolder+"/"+destFolder+"/"+file.fileName().remove(QRegExp("^"+ZIP_PART)); backupExistingFileIfExists(destFilePath); if(FolderUtils::slamCopy(partfile, destFilePath)) { if (addToAlien) { m_alienFiles << destFilePath; m_alienPartsMsg = tr("Do you want to keep the imported parts?"); } } ModelPart *mp = m_referenceModel->loadPart(destFilePath, true); mp->setAlien(true); return mp; } void MainWindow::binSaved(bool hasPartsFromBundled) { if(hasPartsFromBundled) { // the bin will need those parts, so just keep them m_alienFiles.clear(); resetTempFolder(); } } #undef ZIP_PART #undef ZIP_SVG void MainWindow::backupExistingFileIfExists(const QString &destFilePath) { if(QFileInfo(destFilePath).exists()) { if(m_tempDir.path() == ".") { m_tempDir = QDir::temp(); FolderUtils::createFolderAnCdIntoIt(m_tempDir, TextUtils::getRandText()); DebugDialog::debug("debug folder for overwritten files: "+m_tempDir.path()); } QString fileBackupName = QFileInfo(destFilePath).fileName(); m_filesReplacedByAlienOnes << destFilePath; QFile file(destFilePath); bool alreadyExists = file.exists(); FolderUtils::slamCopy(file, m_tempDir.path()+"/"+fileBackupName); if(alreadyExists) { file.remove(destFilePath); } } } void MainWindow::recoverBackupedFiles() { foreach(QString originalFilePath, m_filesReplacedByAlienOnes) { QFile file(m_tempDir.path()+"/"+QFileInfo(originalFilePath).fileName()); if(file.exists(originalFilePath)) { file.remove(); } FolderUtils::slamCopy(file, originalFilePath); } resetTempFolder(); } void MainWindow::resetTempFolder() { if(m_tempDir.path() != ".") { FolderUtils::rmdir(m_tempDir); m_tempDir = QDir::temp(); } m_filesReplacedByAlienOnes.clear(); } void MainWindow::routingStatusSlot(SketchWidget * sketchWidget, const RoutingStatus & routingStatus) { m_routingStatus = routingStatus; QString theText; if (routingStatus.m_netCount == 0) { theText = tr("No connections to route"); } else if (routingStatus.m_netCount == routingStatus.m_netRoutedCount) { if (routingStatus.m_jumperItemCount == 0) { theText = tr("Routing completed"); } else { theText = tr("Routing completed using %n jumper part(s)", "", routingStatus.m_jumperItemCount); } } else { theText = tr("%1 of %2 nets routed - %n connector(s) still to be routed", "", routingStatus.m_connectorsLeftToRoute) .arg(routingStatus.m_netRoutedCount) .arg(routingStatus.m_netCount); } dynamic_cast(sketchWidget->parent())->routingStatusLabel()->setLabelText(theText); updateTraceMenu(); } void MainWindow::applyReadOnlyChange(bool isReadOnly) { Q_UNUSED(isReadOnly); //m_saveAct->setDisabled(isReadOnly); } const QString MainWindow::fritzingTitle() { if (m_currentGraphicsView == NULL) { return FritzingWindow::fritzingTitle(); } QString fritzing = FritzingWindow::fritzingTitle(); return tr("%1 - [%2]").arg(fritzing).arg(m_currentGraphicsView->viewName()); } QAction *MainWindow::raiseWindowAction() { return m_raiseWindowAct; } void MainWindow::raiseAndActivate() { if(isMinimized()) { showNormal(); } raise(); QTimer::singleShot(20, this, SLOT(activateWindowAux())); } void MainWindow::activateWindowAux() { activateWindow(); } void MainWindow::updateRaiseWindowAction() { QString actionText; QFileInfo fileInfo(m_fwFilename); if(fileInfo.exists()) { int lastSlashIdx = m_fwFilename.lastIndexOf("/"); int beforeLastSlashIdx = m_fwFilename.left(lastSlashIdx).lastIndexOf("/"); actionText = beforeLastSlashIdx > -1 && lastSlashIdx > -1 ? "..." : ""; actionText += m_fwFilename.right(m_fwFilename.size()-beforeLastSlashIdx-1); } else { actionText = m_fwFilename; } m_raiseWindowAct->setText(actionText); m_raiseWindowAct->setToolTip(m_fwFilename); m_raiseWindowAct->setStatusTip("raise \""+m_fwFilename+"\" window"); } QSizeGrip *MainWindow::sizeGrip() { return m_sizeGrip; } QStatusBar *MainWindow::realStatusBar() { return m_statusBar; } void MainWindow::moveEvent(QMoveEvent * event) { FritzingWindow::moveEvent(event); emit mainWindowMoved(this); } bool MainWindow::event(QEvent * e) { switch (e->type()) { case QEvent::WindowActivate: emit changeActivationSignal(true, this); break; case QEvent::WindowDeactivate: emit changeActivationSignal(false, this); break; default: break; } return FritzingWindow::event(e); } void MainWindow::resizeEvent(QResizeEvent * event) { if (m_sizeGrip) { m_sizeGrip->rearrange(); } FritzingWindow::resizeEvent(event); } void MainWindow::enableCheckUpdates(bool enabled) { if (m_checkForUpdatesAct != NULL) { m_checkForUpdatesAct->setEnabled(enabled); } } void MainWindow::swapSelectedDelay(const QString & family, const QString & prop, QMap & currPropsMap, ItemBase * itemBase) { //DebugDialog::debug("swap selected delay"); m_swapTimer.stop(); m_swapTimer.setAll(family, prop, currPropsMap, itemBase); m_swapTimer.start(); } void MainWindow::swapSelectedTimeout() { if (sender() == &m_swapTimer) { QMap map = m_swapTimer.propsMap(); swapSelectedMap(m_swapTimer.family(), m_swapTimer.prop(), map, m_swapTimer.itemBase()); } } void MainWindow::swapSelectedMap(const QString & family, const QString & prop, QMap & currPropsMap, ItemBase * itemBase) { if (itemBase == NULL) return; QString generatedModuleID = currPropsMap.value("moduleID"); bool logoPadBlocker = false; if (generatedModuleID.isEmpty()) { if (prop.compare("layer") == 0) { if (family.compare("logo") == 0 || family.compare("pad") == 0 || family.contains("blocker", Qt::CaseInsensitive)) { QString value = Board::convertToXmlName(currPropsMap.value(prop)); if (value.contains("copper1") && m_currentGraphicsView->boardLayers() == 1) { QMessageBox::warning( this, tr("No copper top layer"), tr("The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.") ); return; } // use the xml name currPropsMap.insert(prop, value); logoPadBlocker = true; } else if (itemBase->itemType() == ModelPart::Wire) { // assume this option is disabled for a one-sided board, so we would not get here? m_pcbGraphicsView->changeTraceLayer(itemBase, false, NULL); return; } } } if (generatedModuleID.isEmpty()) { if (family.compare("Prototyping Board", Qt::CaseInsensitive) == 0) { if (prop.compare("size", Qt::CaseInsensitive) == 0 || prop.compare("type", Qt::CaseInsensitive) == 0) { QString size = currPropsMap.value("size"); QString type = currPropsMap.value("type"); if (type.compare("perfboard", Qt::CaseInsensitive) == 0) { generatedModuleID = Perfboard::genModuleID(currPropsMap); } else if (type.compare("stripboard", Qt::CaseInsensitive) == 0) { generatedModuleID = Stripboard::genModuleID(currPropsMap); } } } } bool swapLayer = false; ViewLayer::ViewLayerPlacement newViewLayerPlacement = ViewLayer::UnknownPlacement; if (prop.compare("layer") == 0 && !logoPadBlocker) { if (itemBase->modelPart()->flippedSMD() || itemBase->itemType() == ModelPart::Part) { ItemBase * viewItem = itemBase->modelPart()->viewItem(ViewLayer::PCBView); if (viewItem) { ViewLayer::ViewLayerPlacement vlp = (currPropsMap.value(prop) == ItemBase::TranslatedPropertyNames.value("bottom") ? ViewLayer::NewBottom : ViewLayer::NewTop); if (viewItem->viewLayerPlacement() != newViewLayerPlacement) { swapLayer = true; newViewLayerPlacement = vlp; } } } } if (!generatedModuleID.isEmpty()) { ModelPart * modelPart = m_referenceModel->retrieveModelPart(generatedModuleID); if (modelPart == NULL) { if (!m_referenceModel->genFZP(generatedModuleID, m_referenceModel)) { return; } } swapSelectedAux(itemBase->layerKinChief(), generatedModuleID, swapLayer, newViewLayerPlacement, currPropsMap); return; } if (swapLayer) { swapSelectedAux(itemBase->layerKinChief(), itemBase->moduleID(), true, newViewLayerPlacement, currPropsMap); return; } if ((prop.compare("package", Qt::CaseSensitive) != 0) && swapSpecial(prop, currPropsMap)) { return; } foreach (QString key, currPropsMap.keys()) { QString value = currPropsMap.value(key); m_referenceModel->recordProperty(key, value); } QString moduleID = m_referenceModel->retrieveModuleIdWith(family, prop, true); bool exactMatch = m_referenceModel->lastWasExactMatch(); if (moduleID.isEmpty()) { QMessageBox::information( this, tr("Sorry!"), tr( "No part with those characteristics.\n" "We're working to avoid this message, and only let you choose between properties that do exist") ); return; } itemBase = itemBase->layerKinChief(); if(!exactMatch) { AutoCloseMessageBox::showMessage(this, tr("No exactly matching part found; Fritzing chose the closest match.")); } swapSelectedAux(itemBase, moduleID, false, ViewLayer::UnknownPlacement, currPropsMap); } bool MainWindow::swapSpecial(const QString & theProp, QMap & currPropsMap) { ItemBase * itemBase = m_infoView->currentItem(); QString pinSpacing, resistance; int layers = 0; foreach (QString key, currPropsMap.keys()) { if (key.compare("layers", Qt::CaseInsensitive) == 0) { if (!Board::isBoard(itemBase)) continue; QString value = currPropsMap.value(key, ""); if (value.compare(Board::OneLayerTranslated) == 0) { layers = 1; } else if (value.compare(Board::TwoLayersTranslated) == 0) { layers = 2; } } if (key.compare("resistance", Qt::CaseInsensitive) == 0) { resistance = currPropsMap.value(key); continue; } if (key.compare("pin spacing", Qt::CaseInsensitive) == 0) { pinSpacing = currPropsMap.value(key); continue; } } if (layers != 0) { currPropsMap.insert("layers", QString::number(layers)); if (theProp.compare("layers") == 0) { QString msg = (layers == 1) ? tr("Change to single layer pcb") : tr("Change to two layer pcb"); swapLayers(itemBase, layers, msg, SketchWidget::PropChangeDelay); return true; } } if (!resistance.isEmpty() || !pinSpacing.isEmpty()) { if (theProp.contains("band", Qt::CaseInsensitive)) { // swap 4band for 5band or vice versa. return false; } Resistor * resistor = qobject_cast(itemBase); if (resistor != NULL) { m_currentGraphicsView->setResistance(resistance, pinSpacing); return true; } } return false; } void MainWindow::swapLayers(ItemBase * itemBase, int layers, const QString & msg, int delay) { QUndoCommand* parentCommand = new QUndoCommand(msg); new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); m_pcbGraphicsView->swapLayers(itemBase, layers, parentCommand); // need to defer execution so the content of the info view doesn't change during an event that started in the info view m_undoStack->waitPush(parentCommand, delay); } void MainWindow::swapSelectedAux(ItemBase * itemBase, const QString & moduleID, bool useViewLayerPlacement, ViewLayer::ViewLayerPlacement overrideViewLayerPlacement, QMap & propsMap) { QUndoCommand* parentCommand = new QUndoCommand(tr("Swapped %1 with module %2").arg(itemBase->instanceTitle()).arg(moduleID)); new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); ViewLayer::ViewLayerPlacement viewLayerPlacement = itemBase->viewLayerPlacement(); ModelPart * modelPart = m_referenceModel->retrieveModelPart(moduleID); if (m_pcbGraphicsView->boardLayers() == 2) { if (modelPart->flippedSMD()) { //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop; if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement; } else if (modelPart->itemType() == ModelPart::Part) { //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop; if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement; } } else { if (modelPart->flippedSMD()) { viewLayerPlacement = ViewLayer::NewBottom; } else if (modelPart->itemType() == ModelPart::Part) { //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop; if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement; } } swapSelectedAuxAux(itemBase, moduleID, viewLayerPlacement, propsMap, parentCommand); // need to defer execution so the content of the info view doesn't change during an event that started in the info view m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } void MainWindow::swapBoardImageSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName) { QUndoCommand* parentCommand = new QUndoCommand(tr("Change image to %2").arg(filename)); QMap propsMap; long newID = swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerPlacement(), propsMap, parentCommand); LoadLogoImageCommand * cmd = new LoadLogoImageCommand(sketchWidget, newID, "", QSizeF(0,0), filename, filename, addName, parentCommand); cmd->setRedoOnly(); // need to defer execution so the content of the info view doesn't change during an event that started in the info view m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } void MainWindow::subSwapSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & newModuleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, long & newID, QUndoCommand * parentCommand) { Q_UNUSED(sketchWidget); QMap propsMap; newID = swapSelectedAuxAux(itemBase, newModuleID, viewLayerPlacement, propsMap, parentCommand); } long MainWindow::swapSelectedAuxAux(ItemBase * itemBase, const QString & moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QMap & propsMap, QUndoCommand * parentCommand) { long modelIndex = ModelPart::nextIndex(); QList sketchWidgets; // master view must go last, since it creates the delete command, and possibly has all the local props switch (itemBase->viewID()) { case ViewLayer::SchematicView: sketchWidgets << m_pcbGraphicsView << m_breadboardGraphicsView << m_schematicGraphicsView; break; case ViewLayer::PCBView: sketchWidgets << m_schematicGraphicsView << m_breadboardGraphicsView << m_pcbGraphicsView; break; default: sketchWidgets << m_schematicGraphicsView << m_pcbGraphicsView << m_breadboardGraphicsView; break; } SwapThing swapThing; swapThing.firstTime = true; swapThing.itemBase = itemBase; swapThing.newModelIndex = modelIndex; swapThing.newModuleID = moduleID; swapThing.viewLayerPlacement = viewLayerPlacement; swapThing.parentCommand = parentCommand; swapThing.propsMap = propsMap; swapThing.bbView = m_breadboardGraphicsView; long newID = 0; for (int i = 0; i < 3; i++) { long tempID = sketchWidgets[i]->setUpSwap(swapThing, i == 2); if (newID == 0 && tempID != 0) newID = tempID; } // TODO: z-order? return newID; } void MainWindow::svgMissingLayer(const QString & layername, const QString & path) { QMessageBox::warning( this, tr("Fritzing"), tr("Svg %1 is missing a '%2' layer. " "For more information on how to create a custom board shape, " "see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.") .arg(path) .arg(layername) ); } void MainWindow::addDefaultParts() { if (m_pcbGraphicsView == NULL) return; m_pcbGraphicsView->addDefaultParts(); m_breadboardGraphicsView->addDefaultParts(); m_schematicGraphicsView->addDefaultParts(); } MainWindow * MainWindow::newMainWindow(ReferenceModel *referenceModel, const QString & displayPath, bool showProgress, bool lockFiles, int initialTab) { MainWindow * mw = new MainWindow(referenceModel, NULL); if (showProgress) { mw->showFileProgressDialog(displayPath); } if (initialTab >= 0) mw->setInitialTab(initialTab); mw->init(referenceModel, lockFiles); return mw; } void MainWindow::clearFileProgressDialog() { if (m_fileProgressDialog) { m_fileProgressDialog->close(); delete m_fileProgressDialog; m_fileProgressDialog = NULL; } } void MainWindow::setFileProgressPath(const QString & path) { if (m_fileProgressDialog) m_fileProgressDialog->setMessage(tr("loading %1").arg(path)); } FileProgressDialog * MainWindow::fileProgressDialog() { return m_fileProgressDialog; } void MainWindow::showFileProgressDialog(const QString & path) { m_fileProgressDialog = new FileProgressDialog(tr("Loading..."), 200, this); m_fileProgressDialog->setBinLoadingChunk(50); if (!path.isEmpty()) { setFileProgressPath(QFileInfo(path).fileName()); } else { setFileProgressPath(tr("new sketch")); } } const QString &MainWindow::selectedModuleID() { if(m_currentGraphicsView) { return m_currentGraphicsView->selectedModuleID(); } else { return ___emptyString___; } } void MainWindow::redrawSketch() { QList visited; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { item->update(); ConnectorItem * c = dynamic_cast(item); if (c != NULL) { c->restoreColor(visited); } } } void MainWindow::statusMessage(QString message, int timeout) { QStatusBar * sb = realStatusBar(); if (sb != NULL) { sb->showMessage(message, timeout); } } void MainWindow::dropPaste(SketchWidget * sketchWidget) { Q_UNUSED(sketchWidget); pasteInPlace(); } void MainWindow::updateLayerMenuSlot() { updateLayerMenu(true); } bool MainWindow::save() { bool result = FritzingWindow::save(); if (result) { QSettings settings; settings.setValue("lastOpenSketch", m_fwFilename); } return result; } bool MainWindow::saveAs() { bool convertSchematic = false; if (m_schematicGraphicsView != NULL && m_schematicGraphicsView->isOldSchematic()) { QMessageBox::StandardButton reply = QMessageBox::question(this, tr("Schematic conversion"), tr("Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert?"), QMessageBox::Yes | QMessageBox::No); if (reply != QMessageBox::Yes) { return false; } convertSchematic = true; } bool result = false; if (m_fwFilename.endsWith(FritzingSketchExtension)) { result = FritzingWindow::saveAs(m_fwFilename + 'z', false); } else { result = FritzingWindow::saveAs(); } if (result) { QSettings settings; settings.setValue("lastOpenSketch", m_fwFilename); if (convertSchematic) { MainWindow * mw = revertAux(); QString gridSize = QString("%1in").arg(m_schematicGraphicsView->defaultGridSizeInches()); mw->m_schematicGraphicsView->setGridSize(gridSize); mw->m_schematicGraphicsView->resizeLabels(); mw->m_schematicGraphicsView->resizeWires(); mw->m_schematicGraphicsView->updateWires(); mw->save(); } } return result; } void MainWindow::changeBoardLayers(int layers, bool doEmit) { Q_UNUSED(doEmit); Q_UNUSED(layers); updateActiveLayerButtons(); if (m_currentGraphicsView) m_currentGraphicsView->updateConnectors(); } void MainWindow::updateActiveLayerButtons() { if (m_activeLayerButtonWidget != NULL) { int index = activeLayerIndex(); bool enabled = index >= 0; m_activeLayerButtonWidget->setCurrentIndex(index); m_activeLayerButtonWidget->setVisible(enabled); m_activeLayerBothAct->setEnabled(enabled); m_activeLayerBottomAct->setEnabled(enabled); m_activeLayerTopAct->setEnabled(enabled); QList actions; actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct; setActionsIcons(index, actions); } if (m_viewFromButtonWidget != NULL) { if (m_pcbGraphicsView) { bool viewFromBelow = m_pcbGraphicsView->viewFromBelow(); int index = (viewFromBelow ? 1 : 0); m_viewFromButtonWidget->setCurrentIndex(index); m_viewFromButtonWidget->setVisible(true); m_viewFromBelowToggleAct->setChecked(viewFromBelow); m_viewFromBelowAct->setChecked(viewFromBelow); m_viewFromAboveAct->setChecked(viewFromBelow); m_viewFromBelowToggleAct->setEnabled(true); m_viewFromBelowAct->setEnabled(true); m_viewFromAboveAct->setEnabled(true); } } } int MainWindow::activeLayerIndex() { if (m_currentGraphicsView == NULL) return -1; if (m_currentGraphicsView->boardLayers() == 2 || activeLayerWidgetAlwaysOn()) { bool copper0Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper0); bool copper1Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper1); if (copper0Visible && copper1Visible) { return 0; } else if (copper1Visible) { return 2; } else if (copper0Visible) { return 1; } } return -1; } bool MainWindow::activeLayerWidgetAlwaysOn() { return false; } /** * A slot for saving a copy of the current sketch to a temp location. * This should be called every X minutes as well as just before certain * events, such as saves, part imports, file export/printing. This relies * on the m_autosaveNeeded variable and the undoStack being dirty for * an autosave to be attempted. */ void MainWindow::backupSketch() { if (ProcessEventBlocker::isProcessing()) { // don't want to autosave during autorouting, for example return; } if (m_autosaveNeeded && !m_undoStack->isClean()) { m_autosaveNeeded = false; // clear this now in case the save takes a really long time DebugDialog::debug(QString("%1 autosaved as %2").arg(m_fwFilename).arg(m_backupFileNameAndPath)); statusBar()->showMessage(tr("Backing up '%1'").arg(m_fwFilename), 2000); ProcessEventBlocker::processEvents(); m_backingUp = true; connectStartSave(true); m_sketchModel->save(m_backupFileNameAndPath, false); connectStartSave(false); m_backingUp = false; } } /** * This function is used to trigger an autosave at the next autosave * timer event. It is connected to the QUndoStack::indexChanged(int) * signal so that any change to the undo stack triggers autosaves. * This function can be called independent of this signal and * still work properly. */ void MainWindow::autosaveNeeded(int index) { Q_UNUSED(index); //DebugDialog::debug(QString("Triggering autosave")); m_autosaveNeeded = true; } /** * delete the backup file when the undostack is clean. */ void MainWindow::undoStackCleanChanged(bool isClean) { // DebugDialog::debug(QString("Clean status changed to %1").arg(isClean)); if (isClean) { QFile::remove(m_backupFileNameAndPath); } } void MainWindow::setAutosavePeriod(int minutes) { setAutosave(minutes, AutosaveEnabled); } void MainWindow::setAutosaveEnabled(bool enabled) { setAutosave(AutosaveTimeoutMinutes, enabled); } void MainWindow::setAutosave(int minutes, bool enabled) { AutosaveTimeoutMinutes = minutes; AutosaveEnabled = enabled; foreach (QWidget * widget, QApplication::topLevelWidgets()) { MainWindow * mainWindow = qobject_cast(widget); if (mainWindow == NULL) continue; mainWindow->m_autosaveTimer.stop(); if (qobject_cast(widget)) { continue; } if (AutosaveEnabled) { // is there a way to get the current timer offset so that all the timers aren't running in sync? // or just add some random time... mainWindow->m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000); } } } bool MainWindow::hasLinkedProgramFiles(const QString & filename, QStringList & linkedProgramFiles) { QFile file(filename); file.open(QFile::ReadOnly); QXmlStreamReader xml(&file); xml.setNamespaceProcessing(false); bool done = false; while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: if (xml.name().toString().compare("program") == 0) { linkedProgramFiles.append(xml.readElementText()); break; } if (xml.name().toString().compare("views") == 0) { done = true; break; } if (xml.name().toString().compare("instances") == 0) { done = true; break; } default: break; } if (done) break; } return linkedProgramFiles.count() > 0; } QString MainWindow::getExtensionString() { return tr("Fritzing (*%1)").arg(fileExtension()); } QStringList MainWindow::getExtensions() { QStringList extensions; extensions.append(fileExtension()); return extensions; } void MainWindow::routingStatusLabelMousePress(QMouseEvent* event) { routingStatusLabelMouse(event, true); } void MainWindow::routingStatusLabelMouseRelease(QMouseEvent* event) { routingStatusLabelMouse(event, false); } void MainWindow::routingStatusLabelMouse(QMouseEvent*, bool show) { //if (show) DebugDialog::debug("-------"); if (m_currentGraphicsView == NULL) return; QSet toShow; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { VirtualWire * vw = dynamic_cast(item); if (vw == NULL) continue; foreach (ConnectorItem * connectorItem, vw->connector0()->connectedToItems()) { toShow.insert(connectorItem); } foreach (ConnectorItem * connectorItem, vw->connector1()->connectedToItems()) { toShow.insert(connectorItem); } } QList visited; foreach (ConnectorItem * connectorItem, toShow) { //if (show) { // DebugDialog::debug(QString("unrouted %1 %2 %3 %4") // .arg(connectorItem->attachedToInstanceTitle()) // .arg(connectorItem->attachedToID()) // .arg(connectorItem->attachedTo()->title()) // .arg(connectorItem->connectorSharedName())); //} if (connectorItem->isActive() && connectorItem->isVisible() && !connectorItem->hidden() && !connectorItem->layerHidden()) { connectorItem->showEqualPotential(show, visited); } else { connectorItem = connectorItem->getCrossLayerConnectorItem(); if (connectorItem) connectorItem->showEqualPotential(show, visited); } } if (!show && toShow.count() == 0) { QMessageBox::information(this, tr("Unrouted connections"), tr("There are no unrouted connections in this view.")); } } void MainWindow::setReportMissingModules(bool b) { if (m_sketchModel) { m_sketchModel->setReportMissingModules(b); } } void MainWindow::boardDeletedSlot() { activeLayerBottom(); } void MainWindow::cursorLocationSlot(double xinches, double yinches, double width, double height) { if (m_locationLabel) { QString units; double x, y, w, h; QHash precision; precision["mm"] = 1; precision["px"] = 0; precision["in"] = 3; m_locationLabel->setProperty("location", QSizeF(xinches, xinches)); if (m_locationLabelUnits.compare("mm") == 0) { units = "mm"; x = xinches * 25.4; y = yinches * 25.4; w = width * 25.4; h = height * 25.4; } else if (m_locationLabelUnits.compare("px") == 0) { units = "px"; x = xinches * GraphicsUtils::SVGDPI; y = yinches * GraphicsUtils::SVGDPI; w = width * GraphicsUtils::SVGDPI; h = height * GraphicsUtils::SVGDPI; } else { units = "in"; x = xinches; y = yinches; w = width; h = height; } if ( w*h == 0.0) { m_locationLabel->setText(tr("(x,y)=(%1, %2) %3") .arg(x, 0, 'f', precision[units]) .arg(y, 0, 'f', precision[units]) .arg(units) ); } else { m_locationLabel->setText(tr("(x, y)=(%1, %2)\t(width, height)=(%3, %4) %5") .arg(x, 0, 'f', precision[units]) .arg(y, 0, 'f', precision[units]) .arg(w, 0, 'f', precision[units]) .arg(h, 0, 'f', precision[units]) .arg(units) ); } } } void MainWindow::locationLabelClicked() { if (m_locationLabelUnits.compare("mm") == 0) { m_locationLabelUnits = "px"; } else if (m_locationLabelUnits.compare("px") == 0) { m_locationLabelUnits = "in"; } else if (m_locationLabelUnits.compare("in") == 0) { m_locationLabelUnits = "mm"; } else { m_locationLabelUnits = "in"; } if (m_locationLabel) { QVariant variant = m_locationLabel->property("location"); if (variant.isValid()) { QSizeF size = variant.toSizeF(); cursorLocationSlot(size.width(), size.height()); } else { cursorLocationSlot(0.0, 0.0); } } QSettings settings; settings.setValue("LocationInches", QVariant(m_locationLabelUnits)); } void MainWindow::filenameIfSlot(QString & filename) { filename = QFileInfo(fileName()).fileName(); } QList MainWindow::sketchWidgets() { QList list; list << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView; return list; } void MainWindow::setCloseSilently(bool cs) { m_closeSilently = cs; } PCBSketchWidget * MainWindow::pcbView() { return m_pcbGraphicsView; } void MainWindow::noBackup() { m_autosaveTimer.stop(); } void MainWindow::hideTempPartsBin() { if (m_binManager) m_binManager->hideTempPartsBin(); } void MainWindow::setActiveWire(Wire * wire) { m_activeWire = wire; } void MainWindow::setActiveConnectorItem(ConnectorItem * connectorItem) { m_activeConnectorItem = connectorItem; } const QString & MainWindow::fritzingVersion() { if (m_sketchModel) return m_sketchModel->fritzingVersion(); return ___emptyString___; } void MainWindow::dragEnterEvent(QDragEnterEvent *event) { const QMimeData* mimeData = event->mimeData(); if (mimeData->hasUrls()) { QStringList pathList; QList urlList = mimeData->urls(); // extract the local paths of the files for (int i = 0; i < urlList.size() && i < 32; ++i) { QString fn = urlList.at(i).toLocalFile(); foreach (QString ext, fritzingExtensions()) { if (fn.endsWith(ext)) { event->acceptProposedAction(); return; } } if (fn.endsWith("txt")) { QFile file(fn); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); while (!stream.atEnd()) { QString line = stream.readLine().trimmed(); foreach (QString ext, fritzingExtensions()) { if (line.endsWith(ext)) { event->acceptProposedAction(); return; } } } } } } } } void MainWindow::dropEvent(QDropEvent *event) { const QMimeData* mimeData = event->mimeData(); if (mimeData->hasUrls()) { QStringList pathList; QList urlList = mimeData->urls(); // extract the local paths of the files for (int i = 0; i < urlList.size() && i < 32; ++i) { mainLoadAux(urlList.at(i).toLocalFile()); } return; } } bool MainWindow::hasAnyAlien() { return m_addedToTemp; } void MainWindow::initStyleSheet() { QString suffix = getStyleSheetSuffix(); QFile styleSheet(QString(":/resources/styles/%1.qss").arg(suffix)); if (!styleSheet.open(QIODevice::ReadOnly)) { DebugDialog::debug(QString("Unable to open :/resources/styles/%1.qss").arg(suffix)); } else { QString platformDependantStyle = ""; QString platformDependantStylePath; #ifdef Q_OS_LINUX if(style()->metaObject()->className()==QString("OxygenStyle")) { QFile oxygenStyleSheet(QString(":/resources/styles/linux-kde-oxygen-%1.qss").arg(suffix)); if(oxygenStyleSheet.open(QIODevice::ReadOnly)) { platformDependantStyle += oxygenStyleSheet.readAll(); } } platformDependantStylePath = QString(":/resources/styles/linux-%1.qss").arg(suffix); #endif #ifdef Q_OS_MAC platformDependantStylePath = QString(":/resources/styles/mac-%1.qss").arg(suffix); #endif #ifdef Q_OS_WIN platformDependantStylePath = QString(":/resources/styles/win-%1.qss").arg(suffix); #endif QFile platformDependantStyleSheet(platformDependantStylePath); if(platformDependantStyleSheet.open(QIODevice::ReadOnly)) { platformDependantStyle += platformDependantStyleSheet.readAll(); } setStyleSheet(styleSheet.readAll()+platformDependantStyle); } } QString MainWindow::getStyleSheetSuffix() { return "fritzing"; } void MainWindow::addToMyParts(ModelPart * modelPart) { if (modelPart != NULL) m_binManager->addToMyParts(modelPart); } bool MainWindow::anyUsePart(const QString & moduleID) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWindow = qobject_cast(widget); if (mainWindow == NULL) continue; if (mainWindow->usesPart(moduleID)) { return true; } } return false; } bool MainWindow::usesPart(const QString & moduleID) { if (m_currentGraphicsView == NULL) return false; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase != NULL && itemBase->moduleID().compare(moduleID) == 0) { return true; } } return false; } bool MainWindow::updateParts(const QString & moduleID, QUndoCommand * parentCommand) { if (m_currentGraphicsView == NULL) return false; QSet itemBases; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->moduleID().compare(moduleID) != 0) continue; itemBases.insert(itemBase->layerKinChief()); } QMap propsMap; foreach (ItemBase * itemBase, itemBases) { swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerPlacement(), propsMap, parentCommand); } return true; } void MainWindow::showStatusMessage(const QString & message) { if (sender() == m_statusBar) { return; } if (message == m_statusBar->currentMessage()) { return; } //DebugDialog::debug("show message " + message); m_statusBar->blockSignals(true); m_statusBar->showMessage(message); m_statusBar->blockSignals(false); } void MainWindow::updatePartsBin(const QString & moduleID) { m_binManager->reloadPart(moduleID); } bool MainWindow::hasCustomBoardShape() { if (m_pcbGraphicsView == NULL) return false; return m_pcbGraphicsView->hasCustomBoardShape(); } void MainWindow::selectPartsWithModuleID(ModelPart * modelPart) { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->selectItemsWithModuleID(modelPart); } void MainWindow::addToSketch(QList & modelParts) { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->addToSketch(modelParts); } void MainWindow::initProgrammingWidget() { m_programView = new ProgramWindow(this); connect(m_programView, SIGNAL(linkToProgramFile(const QString &, Platform *, bool, bool)), this, SLOT(linkToProgramFile(const QString &, Platform *, bool, bool))); m_programView->setup(); SketchAreaWidget * sketchAreaWidget = new SketchAreaWidget(m_programView, this, false, true); addTab(sketchAreaWidget, ":/resources/images/icons/TabWidgetCodeActive_icon.png", tr("Code"), true); } ProgramWindow *MainWindow::programmingWidget() { return m_programView; } void MainWindow::orderFabHoverEnter() { m_fireQuoteTimer.stop(); if (!QuoteDialog::quoteSucceeded()) return; if (m_rolloverQuoteDialog && m_rolloverQuoteDialog->isVisible()) return; m_fireQuoteTimer.setInterval(fireQuoteDelay()); m_fireQuoteTimer.start(); } void MainWindow::fireQuote() { m_fireQuoteTimer.stop(); if (!QuoteDialog::quoteSucceeded()) return; m_rolloverQuoteDialog = m_pcbGraphicsView->quoteDialog(m_pcbWidget); if (m_rolloverQuoteDialog == NULL) return; //DebugDialog::debug("enter fab button"); //QWidget * toolbar = m_pcbWidget->toolbar(); //QRect r = toolbar->geometry(); //QPointF p = toolbar->parentWidget()->mapToGlobal(r.topLeft()); Qt::WindowFlags flags = m_rolloverQuoteDialog->windowFlags(); flags = Qt::Window | Qt::Dialog | Qt::FramelessWindowHint; m_rolloverQuoteDialog->setWindowFlags(flags); m_rolloverQuoteDialog->show(); // seems to require setting position after show() QRect b = m_orderFabButton->geometry(); QPoint bt = m_orderFabButton->parentWidget()->mapToGlobal(b.topRight()); QRect t = m_pcbWidget->toolbar()->geometry(); QPoint gt = m_pcbWidget->toolbar()->parentWidget()->mapToGlobal(t.topLeft()); QRect q = m_rolloverQuoteDialog->geometry(); // I don't understand why--perhaps due to the windowFlags--but q is already in global coordinates q.moveBottom(gt.y() - 20); q.moveRight(bt.x()); m_rolloverQuoteDialog->setGeometry(q); } void MainWindow::orderFabHoverLeave() { m_fireQuoteTimer.stop(); //DebugDialog::debug("leave fab button"); if (m_rolloverQuoteDialog) { m_rolloverQuoteDialog->hide(); } } void MainWindow::initWelcomeView() { m_welcomeView = new WelcomeView(this); m_welcomeView->setObjectName("WelcomeView"); SketchAreaWidget * sketchAreaWidget = new SketchAreaWidget(m_welcomeView, this, false, false); addTab(sketchAreaWidget, ":/resources/images/icons/TabWidgetWelcomeActive_icon.png", tr("Welcome"), true); } void MainWindow::setInitialView() { // do this the first time, since the current_changed signal wasn't sent int tab = 0; tabWidget_currentChanged(tab+1); tabWidget_currentChanged(tab); // default to breadboard view this->setCurrentTabIndex(m_initialTab); } void MainWindow::updateWelcomeViewRecentList(bool doEmit) { if (m_welcomeView) { m_welcomeView->updateRecent(); if (doEmit) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWin = qobject_cast(widget); if (mainWin && mainWin != this) { mainWin->updateWelcomeViewRecentList(false); } } } } } void MainWindow::initZoom() { if (m_currentGraphicsView == NULL) return; if (m_currentGraphicsView->everZoomed()) return; if (!m_currentGraphicsView->isVisible()) return; bool parts = false; foreach (QGraphicsItem * item, m_currentGraphicsView->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isEverVisible()) continue; parts = true; break; } if (parts) { m_currentGraphicsView->fitInWindow(); } m_currentGraphicsView->setEverZoomed(true); } int MainWindow::fireQuoteDelay() { return m_fireQuoteDelay; } void MainWindow::setFireQuoteDelay(int delay) { m_fireQuoteDelay = delay; } void MainWindow::noSchematicConversion() { m_noSchematicConversion = true; } void MainWindow::setInitialTab(int tab) { m_initialTab = tab; } fritzing-app-0.9.2b/src/mainwindow/mainwindow.h000066400000000000000000000765551250202676700216170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6999 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 14:14:07 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fritzingwindow.h" #include "sketchareawidget.h" #include "../viewlayer.h" #include "../program/programwindow.h" #include "../svg/svg2gerber.h" #include "../routingstatus.h" QT_BEGIN_NAMESPACE class QAction; class QListWidget; class QMenu; QT_END_NAMESPACE class FSizeGrip; typedef class FDockWidget * (*DockFactory)(const QString & title, QWidget * parent); bool sortPartList(class ItemBase * b1, class ItemBase * b2); static const QString ORDERFABENABLED = "OrderFabEnabled"; class FTabWidget : public QTabWidget { Q_OBJECT public: FTabWidget(QWidget * parent = NULL); //int addTab(QWidget * page, const QIcon & icon, const QIcon & hoverIcon, const QIcon & inactiveIcon, const QString & label); protected slots: //void tabIndexChanged(int index); protected: //QList m_inactiveIcons; //QList m_hoverIcons; //QList m_icons; }; class FTabBar : public QTabBar { Q_OBJECT public: FTabBar(); void paintEvent(QPaintEvent *); protected: bool m_firstTime; }; class SwapTimer : public QTimer { Q_OBJECT public: SwapTimer(); void setAll(const QString & family, const QString & prop, QMap & propsMap, ItemBase *); const QString & family(); const QString & prop(); QMap propsMap(); ItemBase * itemBase(); protected: QString m_family; QString m_prop; QMap m_propsMap; QPointer m_itemBase; }; struct GridSizeThing { QLineEdit * lineEdit; QDoubleValidator * validator; QRadioButton * mmButton; QRadioButton * inButton; double defaultGridSize; QString gridSizeText; QString viewName; QString shortName; GridSizeThing(const QString & viewName, const QString & shortName, double defaultSize, const QString & gridSizeText); }; class GridSizeDialog : public QDialog { Q_OBJECT public: GridSizeDialog(GridSizeThing *); GridSizeThing * gridSizeThing(); protected: GridSizeThing * m_gridSizeThing; }; struct TraceMenuThing { int boardCount; int boardSelectedCount; bool jiEnabled; bool exEnabled; bool viaEnabled; bool exChecked; bool gfrEnabled; bool gfsEnabled; TraceMenuThing() { boardCount = 0; boardSelectedCount = 0; gfsEnabled = false; jiEnabled = false; exEnabled = false; exChecked = true; viaEnabled = false; gfrEnabled = false; } }; class MainWindow : public FritzingWindow { Q_OBJECT Q_PROPERTY(int fireQuoteDelay READ fireQuoteDelay WRITE setFireQuoteDelay DESIGNABLE true) public: MainWindow(class ReferenceModel *referenceModel, QWidget * parent); MainWindow(QFile & fileToLoad); ~MainWindow(); void mainLoad(const QString & fileName, const QString & displayName, bool checkObsolete); bool loadWhich(const QString & fileName, bool setAsLastOpened, bool addToRecent, bool checkObsolete, const QString & displayName); void notClosableForAWhile(); QAction *raiseWindowAction(); QSizeGrip *sizeGrip(); QStatusBar *realStatusBar(); void enableCheckUpdates(bool enabled); void getPartsEditorNewAnd(ItemBase * fromItem); void addDefaultParts(); void init(ReferenceModel *referenceModel, bool lockFiles); void showFileProgressDialog(const QString & path); void setFileProgressPath(const QString & path); void clearFileProgressDialog(); class FileProgressDialog * fileProgressDialog(); const QString &selectedModuleID(); void saveDocks(); void restoreDocks(); void redrawSketch(); // if we consider a part as the smallest ("atomic") entity inside // fritzing, then this functions may help with the bundle tasks // on the complex entities: sketches, bins, modules (?) void saveBundledNonAtomicEntity(QString &filename, const QString &extension, Bundler *bundler, const QList &partsToSave, bool askForFilename, const QString & destFolderPath, bool saveModel, bool deleteLeftovers); bool loadBundledNonAtomicEntity(const QString &filename, Bundler *bundler, bool addToBin, bool dontAsk); void saveAsShareable(const QString & path, bool saveModel); void setCurrentFile(const QString &fileName, bool addToRecent, bool setAsLastOpened); void setReportMissingModules(bool); QList sketchWidgets(); ProgramWindow * programmingWidget(); void setCloseSilently(bool); class PCBSketchWidget * pcbView(); void noBackup(); void swapSelectedAux(ItemBase * itemBase, const QString & moduleID, bool useViewLayerPlacement, ViewLayer::ViewLayerPlacement, QMap & propsMap); void swapLayers(ItemBase * itemBase, int layers, const QString & msg, int delay); bool saveAsAux(const QString & fileName); void swapObsolete(bool displayFeedback, QList &); QList selectAllObsolete(bool displayFeedback); void hideTempPartsBin(); const QString & fritzingVersion(); void removeGroundFill(ViewLayer::ViewLayerID, QUndoCommand * parentCommand); void groundFill(ViewLayer::ViewLayerID); void copperFill(ViewLayer::ViewLayerID); bool hasAnyAlien(); void exportSvg(double res, bool selectedItems, bool flatten, const QString & filename); void setCurrentView(ViewLayer::ViewID); bool usesPart(const QString & moduleID); bool anyUsePart(const QString & moduleID); bool updateParts(const QString & moduleID, QUndoCommand * parentCommand); void updatePartsBin(const QString & moduleID); bool hasCustomBoardShape(); void selectPartsWithModuleID(ModelPart *); void addToSketch(QList &); QStringList newDesignRulesCheck(bool showOkMessage); int fireQuoteDelay(); void setFireQuoteDelay(int); void setInitialTab(int); void noSchematicConversion(); public: static void initNames(); static MainWindow * newMainWindow(ReferenceModel *referenceModel, const QString & displayPath, bool showProgress, bool lockFiles, int initialTab); static void setAutosavePeriod(int); static void setAutosaveEnabled(bool); signals: void alienPartsDismissed(); void mainWindowMoved(QWidget *); void changeActivationSignal(bool activate, QWidget * originator); void externalProcessSignal(QString & name, QString & path, QStringList & args); public slots: void ensureClosable(); ModelPart* loadBundledPart(const QString &fileName, bool addToBin); void importFilesFromPrevInstall(); void acceptAlienFiles(); void statusMessage(QString message, int timeout); void showPCBView(); void groundFill(); void removeGroundFill(); void copperFill(); void setOneGroundFillSeed(); void setGroundFillSeeds(); void clearGroundFillSeeds(); void changeBoardLayers(int layers, bool doEmit); void selectAllObsolete(); void swapObsolete(); void swapBoardImageSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName); void updateTraceMenu(); virtual void updateExportMenu(); virtual void updateFileMenu(); void showStatusMessage(const QString &); void orderFabHoverEnter(); void orderFabHoverLeave(); void setGroundFillKeepout(); void oldSchematicsSlot(const QString & filename, bool & useOldSchematics); void showWelcomeView(); protected slots: void mainLoad(); void revert(); void openRecentOrExampleFile(); void openRecentOrExampleFile(const QString & filename, const QString & actionText); void print(); void doExport(); void exportEtchable(); void about(); void tipsAndTricks(); void firstTimeHelp(); void copy(); void cut(); void paste(); void pasteInPlace(); void duplicate(); void doDelete(); void doDeleteMinus(); void selectAll(); void deselect(); void zoomIn(); void zoomOut(); void fitInWindow(); void actualSize(); void hundredPercentSize(); void alignToGrid(); void showGrid(); void setGridSize(); void setBackgroundColor(); void showBreadboardView(); void showSchematicView(); void showProgramView(); void showPartsBinIconView(); void showPartsBinListView(); virtual void updateEditMenu(); virtual void updateLayerMenu(bool resetLayout = false); void updatePartMenu(); virtual void updateWireMenu(); void updateTransformationActions(); void updateRecentFileActions(); virtual void tabWidget_currentChanged(int index); void createNewSketch(); void minimize(); void toggleToolbar(bool toggle); void togglePartLibrary(bool toggle); void toggleInfo(bool toggle); void toggleUndoHistory(bool toggle); void toggleDebuggerOutput(bool toggle); void openHelp(); void openDonate(); void openExamples(); void openPartsReference(); void visitFritzingDotOrg(); void partsEditorHelp(); virtual void updateWindowMenu(); void pageSetup(); void sendToBack(); void sendBackward(); void bringForward(); void bringToFront(); void alignLeft(); void alignRight(); void alignVerticalCenter(); void alignTop(); void alignHorizontalCenter(); void alignBottom(); void rotate90cw(); void rotate90ccw(); void rotate180(); void rotate45ccw(); void rotate45cw(); void rotateIncCCW(); void rotateIncCW(); void rotateIncCCWRubberBand(); void rotateIncCWRubberBand(); void flipHorizontal(); void flipVertical(); void showAllLayers(); void hideAllLayers(); void addBendpoint(); void convertToVia(); void convertToBendpoint(); void flattenCurve(); void disconnectAll(); void openInPartsEditorNew(); void openNewPartsEditor(class PaletteItem *); void updateZoomSlider(double zoom); void updateZoomOptionsNoMatterWhat(double zoom); void updateViewZoom(double newZoom); void setInfoViewOnHover(bool infoViewOnHover); void updateItemMenu(); void newAutoroute(); void orderFab(); void activeLayerTop(); void activeLayerBottom(); void activeLayerBoth(); void toggleActiveLayer(); void createTrace(); void excludeFromAutoroute(); void selectAllTraces(); void showUnrouted(); void selectAllCopperFill(); void updateRoutingStatus(); void selectAllExcludedTraces(); void selectAllIncludedTraces(); void selectAllJumperItems(); void selectAllVias(); void shareOnline(); void saveBundledPart(const QString &moduleId=___emptyString___); QStringList saveBundledAux(ModelPart *mp, const QDir &destFolder); void binSaved(bool hasAlienParts); void routingStatusSlot(class SketchWidget *, const RoutingStatus &); void applyReadOnlyChange(bool isReadOnly); void raiseAndActivate(); void activateWindowAux(); void showPartLabels(); void addNote(); void reportBug(); void enableDebug(); void tidyWires(); void changeWireColor(bool checked); void startSaveInstancesSlot(const QString & fileName, ModelPart *, QXmlStreamWriter &); void loadedViewsSlot(class ModelBase *, QDomElement & views); void loadedRootSlot(const QString & filename, ModelBase *, QDomElement & views); void obsoleteSMDOrientationSlot(); void exportNormalizedSVG(); void exportNormalizedFlattenedSVG(); void dumpAllParts(); void testConnectors(); void launchExternalProcess(); bool externalProcess(QString & name, QString & path, QStringList & args); void processError(QProcess::ProcessError processError); void processFinished(int exitCode, QProcess::ExitStatus exitStatus); void processReadyRead(); void processStateChanged(QProcess::ProcessState newState); void throwFakeException(); void dropPaste(SketchWidget *); void openProgramWindow(); void linkToProgramFile(const QString & filename, Platform * platform, bool addLink, bool strong); QStringList newDesignRulesCheck(); void subSwapSlot(SketchWidget *, ItemBase *, const QString & newModuleID, ViewLayer::ViewLayerPlacement, long & newID, QUndoCommand * parentCommand); void updateLayerMenuSlot(); bool save(); bool saveAs(); virtual void backupSketch(); void undoStackCleanChanged(bool isClean); void autosaveNeeded(int index = 0); void changeTraceLayer(); void routingStatusLabelMousePress(QMouseEvent*); void routingStatusLabelMouseRelease(QMouseEvent*); void selectMoveLock(); void moveLock(); void setSticky(); void autorouterSettings(); void boardDeletedSlot(); void cursorLocationSlot(double, double, double=0.0, double=0.0); void locationLabelClicked(); void swapSelectedMap(const QString & family, const QString & prop, QMap & currPropsMap, ItemBase *); void swapSelectedDelay(const QString & family, const QString & prop, QMap & currPropsMap, ItemBase *); void swapSelectedTimeout(); void filenameIfSlot(QString & filename); void openURL(); void setActiveWire(class Wire *); void setActiveConnectorItem(class ConnectorItem *); void gridUnits(bool); void restoreDefaultGrid(); void checkLoadedTraces(); void keepMargins(); void dockChangeActivation(bool activate, QWidget * originator); void addToMyParts(ModelPart *); void hidePartSilkscreen(); void fabQuote(); void findPartInSketch(); void fireQuote(); void setViewFromBelowToggle(); void setViewFromBelow(); void setViewFromAbove(); void updateWelcomeViewRecentList(bool doEmit = true); virtual void initZoom(); protected: void initSketchWidget(SketchWidget *); virtual void initProgrammingWidget(); virtual void createActions(); virtual void createFileMenuActions(); void createExportActions(); void createRaiseWindowActions(); void createOrderFabAct(); void createOpenExampleMenu(); void createActiveLayerActions(); void populateMenuFromXMLFile(QMenu *parentMenu, QStringList &actionsTracker, const QString &folderPath, const QString &indexFileName); QHash indexAvailableElements(QDomElement &domElem, const QString &srcPrefix, QStringList & actionsTracker, const QString & localeName); void populateMenuWithIndex(const QHash &, QMenu * parentMenu, QDomElement &domElem, const QString & localeName); void populateMenuFromFolderContent(QMenu *parentMenu, const QString &path); void createOpenRecentMenu(); void createEditMenuActions(); void createPartMenuActions(); virtual void createViewMenuActions(bool showWelcome); void createWindowMenuActions(); void createHelpMenuActions(); virtual void createMenus(); void createStatusBar(); virtual void connectPairs(); void connectPair(SketchWidget * signaller, SketchWidget * slotter); void closeEvent(QCloseEvent * event); void saveAsAuxAux(const QString & fileName); void printAux(QPrinter &printer, bool removeBackground, bool paginate); void exportAux(QString fileName, QImage::Format format, int quality, bool removeBackground); void notYetImplemented(QString action); bool eventFilter(QObject *obj, QEvent *event); void setActionsIcons(int index, QList &); void exportToEagle(); void exportToGerber(); void exportBOM(); void exportNetlist(); void exportSpiceNetlist(); void exportSvg(double res, bool selectedItems, bool flatten); void exportSvgWatermark(QString & svg, double res); void exportEtchable(bool wantPDF, bool wantSVG); virtual QList getButtonsForView(ViewLayer::ViewID viewId); const QString untitledFileName(); int &untitledFileCount(); const QString fileExtension(); QString getExtensionString(); QStringList getExtensions(); const QString defaultSaveFolder(); bool undoStackIsEmpty(); void createTraceMenuActions(); void hideShowTraceMenu(); void hideShowProgramMenu(); void updatePCBTraceMenu(QGraphicsItem *, TraceMenuThing &); QList moveToPartsFolder(QDir &unzipDir, MainWindow* mw, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder, bool importingSinglePart); QString copyToSvgFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder); ModelPart* copyToPartsFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder); void closeIfEmptySketch(MainWindow* mw); bool whatToDoWithAlienFiles(); void backupExistingFileIfExists(const QString &destFilePath); void recoverBackupedFiles(); void resetTempFolder(); void saveLastTabList(); virtual QMenu *breadboardItemMenu(); virtual QMenu *schematicItemMenu(); virtual QMenu *pcbItemMenu(); virtual QMenu *pcbWireMenu(); virtual QMenu *schematicWireMenu(); virtual QMenu *breadboardWireMenu(); QMenu *viewItemMenuAux(QMenu* menu); void createZoomOptions(SketchAreaWidget* parent); class SketchToolButton *createRotateButton(SketchAreaWidget *parent); SketchToolButton *createShareButton(SketchAreaWidget *parent); SketchToolButton *createFlipButton(SketchAreaWidget *parent); SketchToolButton *createAutorouteButton(SketchAreaWidget *parent); SketchToolButton *createOrderFabButton(SketchAreaWidget *parent); QWidget *createActiveLayerButton(SketchAreaWidget *parent); QWidget *createViewFromButton(SketchAreaWidget *parent); class ExpandingLabel * createRoutingStatusLabel(SketchAreaWidget *); SketchToolButton *createExportEtchableButton(SketchAreaWidget *parent); SketchToolButton *createNoteButton(SketchAreaWidget *parent); QWidget *createToolbarSpacer(SketchAreaWidget *parent); SketchAreaWidget *currentSketchArea(); const QString fritzingTitle(); virtual void updateRaiseWindowAction(); void moveEvent(QMoveEvent * event); bool event(QEvent *); void resizeEvent(QResizeEvent * event); QString genIcon(SketchWidget *, LayerList & partViewLayerIDs, LayerList & wireViewLayerIDs); bool alreadyOpen(const QString & fileName); void svgMissingLayer(const QString & layername, const QString & path); long swapSelectedAuxAux(ItemBase * itemBase, const QString & moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QMap & propsMap, QUndoCommand * parentCommand); bool swapSpecial(const QString & prop, QMap & currPropsMap); void enableAddBendpointAct(QGraphicsItem *); class FileProgressDialog * exportProgress(); QString constructFileName(const QString & differentiator, const QString & extension); bool isGroundFill(ItemBase * itemBase); QString getBoardSvg(ItemBase * board, int res, LayerList &); QString mergeBoardSvg(QString & svg, ItemBase * board, int res, bool flip, LayerList &); void updateActiveLayerButtons(); int activeLayerIndex(); bool hasLinkedProgramFiles(const QString & filename, QStringList & linkedProgramFiles); void pasteAux(bool pasteInPlace); void routingStatusLabelMouse(QMouseEvent*, bool show); class Wire * retrieveWire(); class ConnectorItem * retrieveConnectorItem(); QString getBomProps(ItemBase *); ModelPart * findReplacedby(ModelPart * originalModelPart); void groundFillAux(bool fillGroundTraces, ViewLayer::ViewLayerID viewLayerID); void groundFillAux2(bool fillGroundTraces); void connectStartSave(bool connect); void loadBundledSketch(const QString &fileName, bool addToRecent, bool setAsLastOpened, bool checkObsolete); void dropEvent(QDropEvent *event); void dragEnterEvent(QDragEnterEvent *event); void mainLoadAux(const QString & fileName); QWidget * createGridSizeForm(GridSizeThing *); void massageOutput(QString & svg, bool doMask, bool doSilk, bool doPaste, QString & maskTop, QString & maskBottom, const QString & fileName, ItemBase * board, int dpi, const LayerList &); virtual void initLockedFiles(bool lockFiles); virtual void initSketchWidgets(bool withIcons); virtual void initWelcomeView(); virtual void initDock(); virtual void initMenus(); virtual void moreInitDock(); virtual void setInitialView(); virtual void createFileMenu(); virtual void createEditMenu(); virtual void createPartMenu(); virtual void createViewMenu(); virtual void createWindowMenu(); virtual void createTraceMenus(); virtual void createHelpMenu(); virtual void createRotateSubmenu(QMenu * parentMenu); virtual void createZOrderSubmenu(QMenu * parentMenu); virtual void createZOrderWireSubmenu(QMenu * parentMenu); virtual void createAlignSubmenu(QMenu * parentMenu); virtual void createAddToBinSubmenu(QMenu * parentMenu); virtual void populateExportMenu(); // dock management void createDockWindows(); void dontKeepMargins(); class FDockWidget * makeDock(const QString & title, QWidget * widget, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area = Qt::RightDockWidgetArea, DockFactory dockFactory = NULL); class FDockWidget * dockIt(FDockWidget* dock, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area = Qt::RightDockWidgetArea); FDockWidget *newTopWidget(); FDockWidget *newBottomWidget(); void removeMargin(FDockWidget* dock); void addTopMargin(FDockWidget* dock); void addBottomMargin(FDockWidget* dock); void dockMarginAux(FDockWidget* dock, const QString &name, const QString &style); void initStyleSheet(); virtual QString getStyleSheetSuffix(); virtual QWidget * createTabWidget(); virtual void addTab(QWidget * widget, const QString & label); virtual void addTab(QWidget * widget, const QString & iconPath, const QString & label, bool withIcon); virtual int currentTabIndex(); virtual void setCurrentTabIndex(int); virtual QWidget * currentTabWidget(); virtual bool activeLayerWidgetAlwaysOn(); bool copySvg(const QString & path, QFileInfoList & svgEntryInfoList); void checkSwapObsolete(QList &, bool includeUpdateLaterMessage); QMessageBox::StandardButton oldSchematicMessage(const QString & filename); MainWindow * revertAux(); protected: static void removeActionsStartingAt(QMenu *menu, int start=0); static void setAutosave(int, bool); protected: QUndoGroup *m_undoGroup; QUndoView *m_undoView; QPointer m_breadboardWidget; QPointer m_breadboardGraphicsView; QPointer m_schematicWidget; QPointer m_schematicGraphicsView; QPointer m_pcbWidget; QPointer m_pcbGraphicsView; QPointer m_welcomeWidget; class WelcomeView * m_welcomeView; QPointer m_binManager; QPointer m_tabWidget; QPointer m_referenceModel; QPointer m_sketchModel; QPointer m_infoView; QPointer m_toolbar; bool m_closing; bool m_dontClose; bool m_firstOpen; QPointer m_currentWidget; QPointer m_currentGraphicsView; //QToolBar *m_fileToolBar; //QToolBar *m_editToolBar; QAction *m_raiseWindowAct; // Fritzing Menu QMenu *m_fritzingMenu; QAction *m_aboutAct; QAction *m_preferencesAct; QAction *m_quitAct; QAction *m_exceptionAct; // File Menu enum { MaxRecentFiles = 10 }; QMenu *m_fileMenu; QAction *m_newAct; QAction *m_openAct; QAction *m_revertAct; QMenu *m_openRecentFileMenu; QAction *m_openRecentFileActs[MaxRecentFiles]; QMenu *m_openExampleMenu; QAction *m_saveAct; QAction *m_saveAsAct; QAction *m_pageSetupAct; QAction *m_printAct; QAction *m_shareOnlineAct; QAction * m_launchExternalProcessAct; QMenu *m_zOrderMenu; QMenu *m_zOrderWireMenu; QAction *m_bringToFrontAct; QAction *m_bringForwardAct; QAction *m_sendBackwardAct; QAction *m_sendToBackAct; class WireAction *m_bringToFrontWireAct; class WireAction *m_bringForwardWireAct; class WireAction *m_sendBackwardWireAct; class WireAction *m_sendToBackWireAct; QMenu *m_alignMenu; QAction * m_alignVerticalCenterAct; QAction * m_alignHorizontalCenterAct; QAction * m_alignTopAct; QAction * m_alignLeftAct; QAction * m_alignBottomAct; QAction * m_alignRightAct; // Export Menu QMenu *m_exportMenu; QAction *m_exportJpgAct; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QAction *m_exportPsAct; #endif QAction *m_exportPngAct; QAction *m_exportPdfAct; QAction *m_exportEagleAct; QAction *m_exportGerberAct; QAction *m_exportEtchablePdfAct; QAction *m_exportEtchableSvgAct; QAction *m_exportBomAct; QAction *m_exportNetlistAct; QAction *m_exportSpiceNetlistAct; QAction *m_exportSvgAct; // Edit Menu QMenu *m_editMenu; QAction *m_undoAct; QAction *m_redoAct; QAction *m_cutAct; QAction *m_copyAct; QAction *m_pasteAct; QAction *m_pasteInPlaceAct; QAction *m_duplicateAct; QAction *m_deleteAct; QAction *m_deleteMinusAct; class WireAction *m_deleteWireAct; class WireAction *m_deleteWireMinusAct; QAction *m_selectAllAct; QAction *m_deselectAct; QAction *m_addNoteAct; // Part Menu QMenu *m_partMenu; QAction *m_infoViewOnHoverAction; QAction *m_exportNormalizedSvgAction; QAction *m_exportNormalizedFlattenedSvgAction; QAction *m_dumpAllPartsAction; QAction *m_testConnectorsAction; QAction *m_openInPartsEditorNewAct; QMenu *m_addToBinMenu; QMenu *m_rotateMenu; QAction *m_rotate90cwAct; QAction *m_rotate180Act; QAction *m_rotate90ccwAct; QAction *m_rotate45ccwAct; QAction *m_rotate45cwAct; QAction *m_moveLockAct; QAction *m_stickyAct; QAction *m_selectMoveLockAct; QAction *m_flipHorizontalAct; QAction *m_flipVerticalAct; QAction *m_showPartLabelAct; QAction *m_saveBundledPart; QAction *m_disconnectAllAct; QAction *m_selectAllObsoleteAct; QAction *m_swapObsoleteAct; QAction *m_findPartInSketchAct; QAction * m_openProgramWindowAct; QAction *m_addBendpointAct; QAction *m_convertToViaAct; QAction *m_convertToBendpointAct; QAction * m_convertToBendpointSeparator; QAction *m_flattenCurveAct; QAction *m_showAllLayersAct; QAction *m_hideAllLayersAct; QAction *m_hidePartSilkscreenAct; // View Menu QMenu *m_viewMenu; QAction *m_zoomInAct; QAction *m_zoomInShortcut; QAction *m_zoomOutAct; QAction *m_fitInWindowAct; QAction *m_actualSizeAct; QAction *m_100PercentSizeAct; QAction *m_alignToGridAct; QAction *m_showGridAct; QAction *m_setGridSizeAct; QAction *m_setBackgroundColorAct; QAction *m_showWelcomeAct; QAction *m_showBreadboardAct; QAction *m_showSchematicAct; QAction *m_showProgramAct; QAction *m_showPCBAct; QAction *m_showPartsBinIconViewAct; QAction *m_showPartsBinListViewAct; //QAction *m_toggleToolbarAct; int m_numFixedActionsInViewMenu; // Window Menu QMenu *m_windowMenu; QAction *m_minimizeAct; QAction *m_togglePartLibraryAct; QAction *m_toggleInfoAct; QAction *m_toggleUndoHistoryAct; QAction *m_toggleDebuggerOutputAct; QAction *m_windowMenuSeparator; // Trace Menu QMenu *m_pcbTraceMenu; QMenu *m_schematicTraceMenu; QMenu *m_breadboardTraceMenu; QAction *m_newAutorouteAct; QAction *m_orderFabAct; QAction *m_activeLayerTopAct; QAction *m_activeLayerBottomAct; QAction *m_activeLayerBothAct; QAction *m_viewFromBelowToggleAct; QAction *m_viewFromBelowAct; QAction *m_viewFromAboveAct; class WireAction *m_createTraceWireAct; class WireAction *m_createWireWireAct; QAction *m_createJumperAct; QAction *m_changeTraceLayerAct; class WireAction *m_changeTraceLayerWireAct; QAction *m_excludeFromAutorouteAct; class WireAction *m_excludeFromAutorouteWireAct; QAction * m_showUnroutedAct; QAction *m_selectAllTracesAct; QAction *m_selectAllWiresAct; QAction *m_selectAllCopperFillAct; QAction *m_updateRoutingStatusAct; QAction *m_selectAllExcludedTracesAct; QAction *m_selectAllIncludedTracesAct; QAction *m_selectAllJumperItemsAct; QAction *m_selectAllViasAct; QAction *m_groundFillAct; QAction *m_removeGroundFillAct; QAction *m_copperFillAct; class ConnectorItemAction *m_setOneGroundFillSeedAct; QAction *m_setGroundFillSeedsAct; QAction *m_clearGroundFillSeedsAct; QAction *m_setGroundFillKeepoutAct; QAction *m_newDesignRulesCheckAct; QAction *m_autorouterSettingsAct; QAction *m_fabQuoteAct; QAction *m_tidyWiresAct; QAction *m_checkLoadedTracesAct; // Help Menu QMenu *m_helpMenu; QAction *m_openHelpAct; QAction *m_openDonateAct; QAction *m_examplesAct; QAction *m_partsRefAct; QAction *m_visitFritzingDotOrgAct; QAction *m_checkForUpdatesAct; QAction *m_aboutQtAct; QAction *m_reportBugAct; QAction *m_enableDebugAct; QAction *m_importFilesFromPrevInstallAct; QAction *m_partsEditorHelpAct; QAction *m_tipsAndTricksAct; QAction *m_firstTimeHelpAct; // Wire Color Menu QMenu * m_breadboardWireColorMenu; QMenu * m_schematicWireColorMenu; // Dot icons QIcon m_dotIcon; QIcon m_emptyIcon; QList m_rotateButtons; QList m_flipButtons; QStackedWidget * m_activeLayerButtonWidget; QStackedWidget * m_viewFromButtonWidget; bool m_comboboxChanged; bool m_restarting; QStringList m_alienFiles; QString m_alienPartsMsg; QStringList m_filesReplacedByAlienOnes; QStringList m_openExampleActions; QPointer m_sizeGrip; QTimer m_setUpDockManagerTimer; QPointer m_fileProgressDialog; QPointer m_zoomSlider; QPointer m_locationLabel; QString m_locationLabelUnits; QByteArray m_externalProcessOutput; QPointer m_layerPalette; QPointer m_programWindow; QPointer m_programView; QList m_linkedProgramFiles; QString m_backupFileNameAndPath; QTimer m_autosaveTimer; QTimer m_fireQuoteTimer; bool m_autosaveNeeded; bool m_backingUp; QString m_bundledSketchName; RoutingStatus m_routingStatus; bool m_orderFabEnabled; bool m_closeSilently; QString m_fzzFolder; QHash m_fzzFiles; SwapTimer m_swapTimer; QPointer m_activeWire; QPointer m_activeConnectorItem; bool m_addedToTemp; QString m_settingsPrefix; bool m_convertedSchematic; bool m_useOldSchematic; bool m_noSchematicConversion; int m_initialTab; // dock management QList m_docks; FDockWidget* m_topDock; FDockWidget* m_bottomDock; QString m_oldTopDockStyle; QString m_oldBottomDockStyle; bool m_dontKeepMargins; QPointer m_rolloverQuoteDialog; bool m_obsoleteSMDOrientation; QWidget * m_orderFabButton; int m_fireQuoteDelay; public: static int AutosaveTimeoutMinutes; static bool AutosaveEnabled; static QString BackupFolder; static const int DockMinWidth; static const int DockMinHeight; protected: static const QString UntitledSketchName; static int UntitledSketchIndex; static int CascadeFactorX; static int CascadeFactorY; static QRegExp GuidMatcher; }; #endif fritzing-app-0.9.2b/src/mainwindow/mainwindow_dock.cpp000066400000000000000000000177211250202676700231400ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include "mainwindow.h" #include "../utils/fsizegrip.h" #include "../utils/misc.h" #include "../partsbinpalette/binmanager/binmanager.h" #include "../infoview/htmlinfoview.h" #include "../dock/layerpalette.h" #include "../mainwindow/fdockwidget.h" #include "../utils/fileprogressdialog.h" #include "../debugdialog.h" ///////////////////////////////////// static const int PartsBinMinHeight = 100; static const int UndoHistoryDefaultHeight = 70; static const int UndoHistoryMinHeight = UndoHistoryDefaultHeight; const int MainWindow::DockMinWidth = 130; const int MainWindow::DockMinHeight = 30; /////////////////////////////////////// void MainWindow::dockChangeActivation(bool activate, QWidget * originator) { Q_UNUSED(activate); Q_UNUSED(originator); if (!m_closing) { m_sizeGrip->rearrange(); } } void MainWindow::createDockWindows() { QWidget * widget = new QWidget(); widget->setMinimumHeight(0); widget->setMaximumHeight(0); makeDock(BinManager::Title, m_binManager, PartsBinMinHeight, PartsBinHeightDefault/*, Qt::LeftDockWidgetArea*/); makeDock(tr("Inspector"), m_infoView, InfoViewMinHeight, InfoViewHeightDefault); makeDock(tr("Undo History"), m_undoView, UndoHistoryMinHeight, UndoHistoryDefaultHeight)->hide(); m_undoView->setMinimumSize(DockMinWidth, UndoHistoryMinHeight); makeDock(tr("Layers"), m_layerPalette, DockMinWidth, DockMinHeight)->hide(); m_layerPalette->setMinimumSize(DockMinWidth, DockMinHeight); m_layerPalette->setShowAllLayersAction(m_showAllLayersAct); m_layerPalette->setHideAllLayersAction(m_hideAllLayersAct); if (m_programView == NULL) { m_windowMenu->addSeparator(); m_windowMenu->addAction(m_openProgramWindowAct); } #ifndef QT_NO_DEBUG m_windowMenu->addSeparator(); m_windowMenu->addAction(m_toggleDebuggerOutputAct); #endif m_windowMenuSeparator = m_windowMenu->addSeparator(); } FDockWidget * MainWindow::makeDock(const QString & title, QWidget * widget, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area, DockFactory dockFactory) { FDockWidget * dock = ((dockFactory) ? dockFactory(title, this) : new FDockWidget(title, this)); dock->setObjectName(title); dock->setWidget(widget); widget->setParent(dock); widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(dock, SIGNAL(positionChanged()), this, SLOT(keepMargins())); connect(dock, SIGNAL(topLevelChanged(bool)), this, SLOT(keepMargins())); connect(dock, SIGNAL(visibilityChanged(bool)), this, SLOT(keepMargins())); return dockIt(dock, dockMinHeight, dockDefaultHeight, area); } FDockWidget *MainWindow::dockIt(FDockWidget* dock, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area) { dock->setAllowedAreas(area); addDockWidget(area, dock); if (m_windowMenu) { m_windowMenu->addAction(dock->toggleViewAction()); } dock->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); dock->setMinimumSize(DockMinWidth, dockMinHeight); dock->resize(DockWidthDefault, dockDefaultHeight); connect(dock, SIGNAL(dockChangeActivationSignal(bool, QWidget *)), this, SLOT(dockChangeActivation(bool, QWidget *))); connect(dock, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *))); connect(dock, SIGNAL(dockChangeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection); m_docks << dock; return dock; } FDockWidget *MainWindow::newTopWidget() { int topMostY = 10000; FDockWidget *topWidget = NULL; foreach(FDockWidget* dock, m_docks) { if(/*!dock->isFloating() && dock->isVisible() &&*/ dockWidgetArea(dock) == Qt::RightDockWidgetArea && dock->pos().y() < topMostY) { topMostY = dock->pos().y(); topWidget = dock; } } return topWidget; } FDockWidget *MainWindow::newBottomWidget() { int bottomMostY = -1; FDockWidget *bottomWidget = NULL; foreach(FDockWidget* dock, m_docks) { if(!dock->isFloating() && dock->isVisible() && dockWidgetArea(dock) == Qt::RightDockWidgetArea && dock->pos().y() > bottomMostY) { bottomMostY = dock->pos().y(); bottomWidget = dock; } } return bottomWidget; } void MainWindow::keepMargins() { if (m_dontKeepMargins) return; /*FDockWidget* newTopWidget = this->newTopWidget(); if(m_topDock != newTopWidget) { removeMargin(m_topDock); m_topDock = newTopWidget; if(m_topDock) m_oldTopDockStyle = m_topDock->styleSheet(); addTopMargin(m_topDock); }*/ FDockWidget* newBottomWidget = this->newBottomWidget(); if(m_bottomDock != newBottomWidget) { removeMargin(m_bottomDock); m_bottomDock = newBottomWidget; if(m_bottomDock) m_oldBottomDockStyle = m_bottomDock->styleSheet(); addBottomMargin(m_bottomDock); m_sizeGrip->raise(); } } void MainWindow::removeMargin(FDockWidget* dock) { if(dock) { dockMarginAux(dock, "", m_oldBottomDockStyle); } } void MainWindow::addTopMargin(FDockWidget* dock) { if(dock) dockMarginAux(dock, "topMostDock", dock->widget()->styleSheet()); } void MainWindow::addBottomMargin(FDockWidget* dock) { if(dock) { if(qobject_cast(dock->widget())) { // already has enought space } else { dockMarginAux(dock, "bottomMostDock", dock->widget()->styleSheet()); } } } void MainWindow::dockMarginAux(FDockWidget* dock, const QString &name, const QString &style) { if(dock) { dock->widget()->setObjectName(name); dock->widget()->setStyleSheet(style); dock->setStyleSheet(dock->styleSheet()); } else { qWarning() << tr("Couldn't get the dock widget"); } } void MainWindow::dontKeepMargins() { m_dontKeepMargins = true; } void MainWindow::initDock() { m_layerPalette = new LayerPalette(this); m_infoView = new HtmlInfoView(); m_infoView->init(false); connect(m_infoView, SIGNAL(clickObsoleteSignal()), this, SLOT(selectAllObsolete())); //DebugDialog::debug("after html view"); m_binManager = new BinManager(m_referenceModel, m_infoView, m_undoStack, this); m_binManager->initStandardBins(); //DebugDialog::debug("after creating bins"); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(89); } } void MainWindow::moreInitDock() { //DebugDialog::debug("create view switcher"); createDockWindows(); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(93); } } void MainWindow::saveDocks() { for (int i = 0; i < children().count(); i++) { FDockWidget * dock = qobject_cast(children()[i]); if (dock == NULL) continue; //DebugDialog::debug(QString("saving dock %1").arg(dock->windowTitle())); dock->saveState(); if (dock->isFloating() && dock->isVisible()) { //DebugDialog::debug(QString("hiding dock %1").arg(dock->windowTitle())); dock->hide(); } } } void MainWindow::restoreDocks() { for (int i = 0; i < children().count(); i++) { FDockWidget * dock = qobject_cast(children()[i]); if (dock == NULL) continue; // DebugDialog::debug(QString("restoring dock %1").arg(dock->windowTitle())); dock->restoreState(); } } fritzing-app-0.9.2b/src/mainwindow/mainwindow_export.cpp000066400000000000000000001627711250202676700235470ustar00rootroot00000000000000/******************************************************************* skw Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "mainwindow.h" #include "../debugdialog.h" #include "../waitpushundostack.h" #include "../help/aboutbox.h" #include "../autoroute/autorouteprogressdialog.h" #include "../items/virtualwire.h" #include "../items/jumperitem.h" #include "../items/via.h" #include "../fsvgrenderer.h" #include "../items/note.h" #include "../items/partfactory.h" #include "../eagle/fritzing2eagle.h" #include "../sketch/breadboardsketchwidget.h" #include "../sketch/schematicsketchwidget.h" #include "../sketch/pcbsketchwidget.h" #include "../partsbinpalette/binmanager/binmanager.h" #include "../utils/expandinglabel.h" #include "../infoview/htmlinfoview.h" #include "../utils/bendpointaction.h" #include "../sketch/fgraphicsscene.h" #include "../utils/fileprogressdialog.h" #include "../svg/svgfilesplitter.h" #include "../version/version.h" #include "../help/tipsandtricks.h" #include "../dialogs/setcolordialog.h" #include "../utils/folderutils.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../connectors/ercdata.h" #include "../items/moduleidnames.h" #include "../utils/zoomslider.h" #include "../dock/layerpalette.h" #include "../program/programwindow.h" #include "../utils/autoclosemessagebox.h" #include "../svg/gerbergenerator.h" #include "../processeventblocker.h" static QString eagleActionType = ".eagle"; static QString gerberActionType = ".gerber"; static QString jpgActionType = ".jpg"; #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) static QString psActionType = ".ps"; #endif static QString pdfActionType = ".pdf"; static QString pngActionType = ".png"; static QString svgActionType = ".svg"; static QString bomActionType = ".html"; static QString netlistActionType = ".xml"; static QString spiceNetlistActionType = ".cir"; static QHash filePrintFormats; static QHash fileExportFormats; static QHash fileExtFormats; static QRegExp AaCc("[aAcC]"); static QRegExp LabelNumber("([^\\d]+)(.*)"); static const double InchesPerMeter = 39.3700787; //////////////////////////////////////////////////////// bool sortPartList(ItemBase * b1, ItemBase * b2) { bool result = b1->instanceTitle().toLower() < b2->instanceTitle().toLower(); int ix1 = LabelNumber.indexIn(b1->instanceTitle()); if (ix1 < 0) return result; QString label1 = LabelNumber.cap(1); QString number1 = LabelNumber.cap(2); int ix2 = LabelNumber.indexIn(b2->instanceTitle()); if (ix2 < 0) return result; QString label2 = LabelNumber.cap(1); QString number2 = LabelNumber.cap(2); if (label2.compare(label1, Qt::CaseInsensitive) != 0) return result; bool ok; double d1 = number1.toDouble(&ok); if (!ok) return result; double d2 = number2.toDouble(&ok); if (!ok) return result; return d1 < d2; } ///////////////////////////////////////////////////////// void MainWindow::initNames() { OtherKnownExtensions << jpgActionType << pdfActionType << pngActionType << svgActionType << bomActionType << netlistActionType << spiceNetlistActionType; filePrintFormats[pdfActionType] = QPrinter::PdfFormat; fileExportFormats[pngActionType] = QImage::Format_ARGB32; fileExportFormats[jpgActionType] = QImage::Format_RGB32; fileExtFormats[pdfActionType] = tr("PDF (*.pdf)"); fileExtFormats[pngActionType] = tr("PNG Image (*.png)"); fileExtFormats[jpgActionType] = tr("JPEG Image (*.jpg)"); fileExtFormats[svgActionType] = tr("SVG Image (*.svg)"); fileExtFormats[bomActionType] = tr("BoM Text File (*.html)"); #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) OtherKnownExtensions << psActionType; filePrintFormats[psActionType] = QPrinter::PostScriptFormat; fileExtFormats[psActionType] = tr("PostScript (*.ps)"); #endif QSettings settings; AutosaveEnabled = settings.value("autosaveEnabled", QString("%1").arg(AutosaveEnabled)).toBool(); AutosaveTimeoutMinutes = settings.value("autosavePeriod", QString("%1").arg(AutosaveTimeoutMinutes)).toInt(); } void MainWindow::print() { if (m_currentWidget->contentView() == m_programView) { m_programView->print(); } if (m_currentGraphicsView == NULL) return; #ifndef QT_NO_PRINTER QPrinter printer(QPrinter::HighResolution); QPrintDialog *printDialog = new QPrintDialog(&printer, this); if (printDialog->exec() == QDialog::Accepted) { m_statusBar->showMessage(tr("Printing...")); printAux(printer, true, true); m_statusBar->showMessage(tr("Ready"), 2000); } else { return; } #endif } void MainWindow::exportEtchable() { if (sender() == NULL) return; bool wantSvg = sender()->property("svg").toBool(); exportEtchable(!wantSvg, wantSvg); } void MainWindow::exportEtchable(bool wantPDF, bool wantSVG) { int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to export etchable.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Etchable export can only handle one board at a time--please select the board you want to export.")); return; } RoutingStatus routingStatus; m_pcbGraphicsView->updateRoutingStatus(NULL, routingStatus, true); if (routingStatus.m_connectorsLeftToRoute > 0) { QMessageBox msgBox(this); msgBox.setWindowModality(Qt::WindowModal); msgBox.setText(tr("All traces have not yet been routed.")); msgBox.setInformativeText(tr("Do you want to proceed anyway?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.button(QMessageBox::Yes)->setText(tr("Proceed")); msgBox.button(QMessageBox::No)->setText(tr("Cancel")); msgBox.setDefaultButton(QMessageBox::Yes); int ret = msgBox.exec(); if (ret != QMessageBox::Yes) return; } QString path = defaultSaveFolder(); QString extFmt = (wantPDF) ? fileExtFormats.value(pdfActionType) : fileExtFormats.value(svgActionType); QString fileExt = extFmt; QString suffix = (wantPDF) ? pdfActionType : svgActionType; QString prefix = ""; if (boardCount > 1) { prefix = QString("%1_%2_").arg(board->instanceTitle()).arg(board->id()); } QString exportDir = QFileDialog::getExistingDirectory(this, tr("Choose a folder for exporting"), defaultSaveFolder(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (exportDir.isEmpty()) return; FolderUtils::setOpenSaveFolder(exportDir); FileProgressDialog * fileProgressDialog = exportProgress(); QRectF r = board->sceneBoundingRect(); QSizeF boardImageSize(r.width(), r.height()); QStringList fileNames; fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_copper_bottom%1", suffix)); fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_mask_bottom%1", suffix)); fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_paste_mask_bottom%1", suffix)); if (m_pcbGraphicsView->boardLayers() > 1) { fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_copper_top%1", suffix)); fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_mask_top%1", suffix)); fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_paste_mask_top%1", suffix)); } fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_silk_top%1", suffix)); fileNames.append(exportDir + "/" + constructFileName(prefix + "etch_silk_bottom%1", suffix)); QString maskTop, maskBottom; QList copperLogoItems, holes; for (int ix = 0; ix < fileNames.count(); ix++) { bool doMask = false; bool doSilk = false; bool doPaste = false; QString fileName = fileNames[ix]; LayerList viewLayerIDs; if (fileName.contains("copper_bottom")) { viewLayerIDs << ViewLayer::GroundPlane0 << ViewLayer::Copper0 << ViewLayer::Copper0Trace; } else if (fileName.contains("mask_bottom")) { doMask = true; viewLayerIDs << ViewLayer::Copper0; doPaste = fileName.contains("paste"); } else if (fileName.contains("copper_top")) { viewLayerIDs << ViewLayer::GroundPlane1 << ViewLayer::Copper1 << ViewLayer::Copper1Trace; } else if (fileName.contains("mask_top")) { viewLayerIDs << ViewLayer::Copper1; doMask = true; doPaste = fileName.contains("paste"); } else if (fileName.contains("silk_top")) { viewLayerIDs << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label; doSilk = true; } else if (fileName.contains("silk_bottom")) { viewLayerIDs << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label; doSilk = true; } if (doMask) { m_pcbGraphicsView->hideCopperLogoItems(copperLogoItems); } if (doPaste) { m_pcbGraphicsView->hideHoles(holes); } if (wantSVG) { RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::IllustratorDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString svg = m_pcbGraphicsView->renderToSVG(renderThing, board, viewLayerIDs); massageOutput(svg, doMask, doSilk, doPaste, maskTop, maskBottom, fileName, board, GraphicsUtils::IllustratorDPI, viewLayerIDs); QString merged = mergeBoardSvg(svg, board, GraphicsUtils::IllustratorDPI, false, viewLayerIDs); TextUtils::writeUtf8(fileName.arg(""), merged); merged = mergeBoardSvg(svg, board, GraphicsUtils::IllustratorDPI, true, viewLayerIDs); TextUtils::writeUtf8(fileName.arg("_mirror"), merged); } else { QString svg; QList flips; flips << false << true; foreach (bool flip, flips) { QString mirror = flip ? "_mirror" : ""; QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(filePrintFormats[fileExt]); printer.setOutputFileName(fileName.arg(mirror)); int res = printer.resolution(); if (svg.isEmpty()) { RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = res; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; svg = m_pcbGraphicsView->renderToSVG(renderThing, board, viewLayerIDs); massageOutput(svg, doMask, doSilk, doPaste, maskTop, maskBottom, fileName, board, res, viewLayerIDs); } QString merged = mergeBoardSvg(svg, board, res, flip, viewLayerIDs); // now convert to pdf QSvgRenderer svgRenderer; svgRenderer.load(merged.toLatin1()); double trueWidth = boardImageSize.width() / GraphicsUtils::SVGDPI; double trueHeight = boardImageSize.height() / GraphicsUtils::SVGDPI; QRectF target(0, 0, trueWidth * res, trueHeight * res); QSizeF psize((target.width() + printer.paperRect().width() - printer.width()) / res, (target.height() + printer.paperRect().height() - printer.height()) / res); printer.setPaperSize(psize, QPrinter::Inch); QPainter painter; if (painter.begin(&printer)) { svgRenderer.render(&painter, target); } painter.end(); } } if (doMask) { m_pcbGraphicsView->restoreCopperLogoItems(copperLogoItems); } if (doPaste) { m_pcbGraphicsView->restoreCopperLogoItems(holes); } } m_statusBar->showMessage(tr("Sketch exported"), 2000); delete fileProgressDialog; /* int width = m_pcbGraphicsView->width(); if (m_pcbGraphicsView->verticalScrollBar()->isVisible()) { width -= m_pcbGraphicsView->verticalScrollBar()->width(); } int height = m_pcbGraphicsView->height(); if (m_pcbGraphicsView->horizontalScrollBar()->isVisible()) { height -= m_pcbGraphicsView->horizontalScrollBar()->height(); } double trueWidth = width / m_printerScale; double trueHeight = height / m_printerScale; // set everything to a 1200 dpi resolution QSize imgSize(trueWidth * 1200, trueHeight * 1200); QImage image(imgSize, QImage::Format_RGB32); image.setDotsPerMeterX(1200 * GraphicsUtils::InchesPerMeter); image.setDotsPerMeterY(1200 * GraphicsUtils::InchesPerMeter); QPainter painter; QColor color; color = m_pcbGraphicsView->background(); m_pcbGraphicsView->setBackground(QColor::fromRgb(255,255,255,255)); m_pcbGraphicsView->scene()->clearSelection(); m_pcbGraphicsView->saveLayerVisibility(); m_pcbGraphicsView->setAllLayersVisible(false); m_pcbGraphicsView->setLayerVisible(ViewLayer::Copper0, true); m_pcbGraphicsView->hideConnectors(true); painter.begin(&image); m_pcbGraphicsView->render(&painter); painter.end(); QSvgGenerator svgGenerator; svgGenerator.setFileName("c:/fritzing2/testsvggenerator.svg"); svgGenerator.setSize(QSize(width * 8, height * 8)); QPainter svgPainter(&svgGenerator); m_pcbGraphicsView->render(&svgPainter); svgPainter.end(); m_pcbGraphicsView->hideConnectors(false); m_pcbGraphicsView->setBackground(color); m_pcbGraphicsView->restoreLayerVisibility(); // TODO: restore the selection QRgb black = 0; for (int x = 0; x < imgSize.width(); x++) { for (int y = 0; y < imgSize.height(); y++) { QRgb p = image.pixel(x, y); if (p != 0xffffffff) { image.setPixel(x, y, black); } } } bool result = image.save(fileName); if (!result) { QMessageBox::warning(this, tr("Fritzing"), tr("Unable to save %1").arg(fileName) ); } */ } QString MainWindow::mergeBoardSvg(QString & svg, ItemBase * board, int res, bool flip, LayerList & viewLayerIDs) { QString boardSvg = getBoardSvg(board, res, viewLayerIDs); LayerList outlineLayerIDs = ViewLayer::outlineLayers(); RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = res; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString outlineSvg = m_pcbGraphicsView->renderToSVG(renderThing, board, outlineLayerIDs); outlineSvg = GerberGenerator::cleanOutline(outlineSvg); outlineSvg = TextUtils::slamStrokeAndFill(outlineSvg, "black", "0.5", "none"); if (!boardSvg.isEmpty() && !outlineSvg.isEmpty()) { boardSvg = TextUtils::mergeSvg(boardSvg, outlineSvg, "", false); } else if (boardSvg.isEmpty()) { boardSvg = outlineSvg; } return TextUtils::convertExtendedChars(TextUtils::mergeSvg(boardSvg, svg, "", flip)); } QString MainWindow::getBoardSvg(ItemBase * board, int res, LayerList & viewLayerIDs) { if (board == NULL) return ___emptyString___; board = board->layerKinChief(); QList boardLayers; boardLayers << board; foreach (ItemBase * lk, board->layerKin()) { boardLayers << lk; } bool gotOne = false; foreach (ItemBase * boardLayer, boardLayers) { if (viewLayerIDs.contains(boardLayer->viewLayerID())) { gotOne = true; break; } } if (!gotOne) return ""; m_pcbGraphicsView->setIgnoreSelectionChangeEvents(true); QList items = m_pcbGraphicsView->scene()->selectedItems(); foreach (QGraphicsItem * item, items) { item->setSelected(false); } board->setSelected(true); RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = res; renderThing.selectedItems = renderThing.hideTerminalPoints = true; renderThing.renderBlocker = false; QString svg = m_pcbGraphicsView->renderToSVG(renderThing, board, viewLayerIDs); board->setSelected(false); foreach (QGraphicsItem * item, items) { item->setSelected(true); } m_pcbGraphicsView->setIgnoreSelectionChangeEvents(false); return svg; } void MainWindow::doExport() { QAction * action = qobject_cast(sender()); if (action == NULL) return; QString actionType = action->data().toString(); QString path = defaultSaveFolder(); if (actionType.compare(eagleActionType) == 0) { exportToEagle(); return; } if (actionType.compare(gerberActionType) == 0) { exportToGerber(); return; } if (actionType.compare(bomActionType) == 0) { exportBOM(); return; } if (actionType.compare(netlistActionType) == 0) { exportNetlist(); return; } if (actionType.compare(spiceNetlistActionType) == 0) { exportSpiceNetlist(); return; } if (actionType.compare(svgActionType) == 0) { exportSvg(GraphicsUtils::IllustratorDPI, false, false); return; } #ifndef QT_NO_PRINTER QString fileExt; QString extFmt = fileExtFormats.value(actionType); DebugDialog::debug(QString("file export string %1").arg(extFmt)); QString fileName = FolderUtils::getSaveFileName(this, tr("Export..."), path+"/"+constructFileName("", actionType), extFmt, &fileExt ); if (fileName.isEmpty()) { return; //Cancel pressed } else { FileProgressDialog * fileProgressDialog = exportProgress(); DebugDialog::debug(fileExt+" selected to export"); if(!alreadyHasExtension(fileName, actionType)) { fileName += actionType; } if(filePrintFormats.contains(actionType)) { // PDF or PS QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(filePrintFormats[actionType]); printer.setOutputFileName(fileName); m_statusBar->showMessage(tr("Exporting...")); printAux(printer, true, false); m_statusBar->showMessage(tr("Sketch exported"), 2000); } else { // PNG... DebugDialog::debug(QString("format: %1 %2").arg(fileExt).arg(fileExportFormats[actionType])); int quality = (actionType == pngActionType ? 1 : 100); exportAux(fileName,fileExportFormats[actionType], quality, true); } delete fileProgressDialog; } #endif } void MainWindow::exportAux(QString fileName, QImage::Format format, int quality, bool removeBackground) { if (m_currentGraphicsView == NULL) return; double resMultiplier = 3; QRectF itemsBoundingRect; foreach(QGraphicsItem *item, m_currentGraphicsView->scene()->items()) { if (!item->isVisible()) continue; itemsBoundingRect |= item->sceneBoundingRect(); } QRectF source = itemsBoundingRect; // m_currentGraphicsView->scene()->itemsBoundingRect(); QGraphicsItem * watermark = m_currentGraphicsView->addWatermark(":resources/images/watermark_fritzing_outline.svg"); if (watermark) { watermark->setPos(source.right() - watermark->boundingRect().width(), source.bottom()); source.adjust(0, 0, 0, watermark->boundingRect().height()); } int width = source.width(); int height = source.height(); /* int width = m_currentGraphicsView->width(); if (m_currentGraphicsView->verticalScrollBar()->isVisible()) { width -= m_currentGraphicsView->verticalScrollBar()->width(); } int height = m_currentGraphicsView->height(); if (m_currentGraphicsView->horizontalScrollBar()->isVisible()) { height -= m_currentGraphicsView->horizontalScrollBar()->height(); } */ QSize imgSize(width * resMultiplier, height * resMultiplier); QImage image(imgSize,format); image.setDotsPerMeterX(InchesPerMeter * GraphicsUtils::SVGDPI * resMultiplier); image.setDotsPerMeterY(InchesPerMeter * GraphicsUtils::SVGDPI * resMultiplier); QPainter painter; QColor color; if (removeBackground) { color = m_currentGraphicsView->background(); m_currentGraphicsView->setBackground(QColor::fromRgb(255,255,255,255)); } painter.begin(&image); //m_currentGraphicsView->render(&painter); QRectF target(0, 0, imgSize.width(), imgSize.height()); m_currentGraphicsView->scene()->render(&painter, target, source, Qt::KeepAspectRatio); painter.end(); //image.save(FolderUtils::getUserDataStorePath("") + "/export.png"); if (removeBackground) { m_currentGraphicsView->setBackground(color); } if (watermark) { delete watermark; } QImageWriter imageWriter(fileName); if (imageWriter.supportsOption(QImageIOHandler::Description)) { imageWriter.setText("", TextUtils::CreatedWithFritzingString); } imageWriter.setQuality(quality); bool result = imageWriter.write(image); if (!result) { QMessageBox::warning(this, tr("Fritzing"), tr("Unable to save %1").arg(fileName) ); } } void MainWindow::printAux(QPrinter &printer, bool removeBackground, bool paginate) { if (m_currentGraphicsView == NULL) return; int res = printer.resolution(); double scale2 = res / GraphicsUtils::SVGDPI; DebugDialog::debug(QString("p.w:%1 p.h:%2 pager.w:%3 pager.h:%4 paperr.w:%5 paperr.h:%6 source.w:%7 source.h:%8") .arg(printer.width()) .arg(printer.height()) .arg(printer.pageRect().width()) .arg(printer.pageRect().height()) .arg(printer.paperRect().width()) .arg(printer.paperRect().height()) .arg(printer.width() / scale2) .arg(printer.height() / scale2) ); // oSceneStart oSceneEnd: shows only what's visible in the viewport, not the entire view //QPointF oSceneStart = m_currentGraphicsView->mapToScene(QPoint(0,0)); //QPointF oSceneEnd = m_currentGraphicsView->mapToScene(QPoint(m_currentGraphicsView->viewport()->width(), m_currentGraphicsView->viewport()->height())); //QRectF source(oSceneStart, oSceneEnd); QRectF itemsBoundingRect; foreach(QGraphicsItem *item, m_currentGraphicsView->scene()->items()) { if (!item->isVisible()) continue; itemsBoundingRect |= item->sceneBoundingRect(); } QRectF source = itemsBoundingRect; // m_currentGraphicsView->scene()->itemsBoundingRect(); DebugDialog::debug("items bounding rect", source); DebugDialog::debug("scene items bounding rect", m_currentGraphicsView->scene()->itemsBoundingRect()); QGraphicsItem * watermark = m_currentGraphicsView->addWatermark(":resources/images/watermark_fritzing_outline.svg"); if (watermark) { watermark->setPos(source.right() - watermark->boundingRect().width(), source.bottom()); source.adjust(0, 0, 0, watermark->boundingRect().height()); } QRectF target(0, 0, source.width() * scale2, source.height() * scale2); if (!paginate) { QSizeF psize((target.width() + printer.paperRect().width() - printer.width()) / res, (target.height() + printer.paperRect().height() - printer.height()) / res); printer.setPaperSize(psize, QPrinter::Inch); } QPainter painter; if (!painter.begin(&printer)) { if (watermark) { delete watermark; } QMessageBox::warning(this, tr("Fritzing"), tr("Cannot print to %1").arg(printer.docName())); return; } QColor color; if(removeBackground) { color = m_currentGraphicsView->background(); m_currentGraphicsView->setBackground(QColor::fromRgb(255,255,255,255)); } QList selItems = m_currentGraphicsView->scene()->selectedItems(); foreach(QGraphicsItem *item, selItems) { item->setSelected(false); } if (paginate) { int xPages = qCeil(target.width() / printer.width()); int yPages = qCeil(target.height() / printer.height()); int lastPage = xPages * yPages; int xSourcePage = qFloor(printer.width() / scale2); int ySourcePage = qFloor(printer.height() / scale2); int page = 0; for (int iy = 0; iy < yPages; iy++) { for (int ix = 0; ix < xPages; ix++) { // render to printer: QRectF pSource((ix * xSourcePage) + source.left(), (iy * ySourcePage) + source.top(), qMin(xSourcePage, (int) source.width() - (ix * xSourcePage)), qMin(ySourcePage, (int) source.height() - (iy * ySourcePage))); QRectF pTarget(0, 0, pSource.width() * scale2, pSource.height() * scale2); m_currentGraphicsView->scene()->render(&painter, pTarget, pSource, Qt::KeepAspectRatio); if (++page < lastPage) { printer.newPage(); } } } } else { m_currentGraphicsView->scene()->render(&painter, target, source, Qt::KeepAspectRatio); } foreach(QGraphicsItem *item, selItems) { item->setSelected(true); } if(removeBackground) { m_currentGraphicsView->setBackground(color); } if (watermark) { delete watermark; } DebugDialog::debug(QString("source w:%1 h:%2 target w:%5 h:%6 pres:%3 screenres:%4") .arg(source.width()) .arg(source.height()).arg(res).arg(this->physicalDpiX()) .arg(target.width()).arg(target.height()) ); //#ifndef QT_NO_CONCURRENT //QProgressDialog dialog; //dialog.setLabelText(message); // // Create a QFutureWatcher and conncect signals and slots. //QFutureWatcher futureWatcher; //QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); //QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); //QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int))); //QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); // // Start the computation. //futureWatcher.setFuture(QtConcurrent::run(painter,&QPainter::end)); //dialog.exec(); // //futureWatcher.waitForFinished(); //#endif //#ifdef QT_NO_CONCURRENT painter.end(); //#endif } bool MainWindow::saveAsAux(const QString & fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("Fritzing"), tr("Cannot write file %1:\n%2.") .arg(fileName) .arg(file.errorString())); return false; } file.close(); setReadOnly(false); //FritzingWindow::saveAsAux(fileName); saveAsAuxAux(fileName); m_autosaveNeeded = false; undoStackCleanChanged(true); m_statusBar->showMessage(tr("Saved '%1'").arg(fileName), 2000); setCurrentFile(fileName, true, true); if(m_restarting && !m_fwFilename.isEmpty()) { QSettings settings; settings.setValue("lastOpenSketch",m_fwFilename); } // mark the stack clean so we update the window dirty flag m_undoStack->setClean(); // slam it here in case we were modified due to m_linkedProgramFiles changes setWindowModified(false); m_saveAct->setEnabled(true); return true; } void MainWindow::saveAsAuxAux(const QString & fileName) { QApplication::setOverrideCursor(Qt::WaitCursor); connectStartSave(true); m_programView->saveAll(); QDir dir(this->m_fzzFolder); QStringList nameFilters("*" + FritzingSketchExtension); QFileInfoList fileList = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); foreach (QFileInfo fileInfo, fileList) { QFile file(fileInfo.absoluteFilePath()); file.remove(); } QString fzName = dir.absoluteFilePath(QFileInfo(fileName).completeBaseName() + FritzingSketchExtension); m_sketchModel->save(fzName, false); saveLastTabList(); saveAsShareable(fileName, false); connectStartSave(false); QApplication::restoreOverrideCursor(); } void MainWindow::saveAsShareable(const QString & path, bool saveModel) { QString filename = path; QHash saveParts; foreach (QGraphicsItem * item, m_pcbGraphicsView->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->modelPart() == NULL) { continue; } if (itemBase->modelPart()->isCore()) continue; if (itemBase->moduleID().contains(PartFactory::OldSchematicPrefix)) continue; saveParts.insert(itemBase->moduleID(), itemBase->modelPart()); } saveBundledNonAtomicEntity(filename, FritzingBundleExtension, this, saveParts.values(), false, m_fzzFolder, saveModel, true); } void MainWindow::saveBundledNonAtomicEntity(QString &filename, const QString &extension, Bundler *bundler, const QList &partsToSave, bool askForFilename, const QString & destFolderPath, bool saveModel, bool deleteLeftovers) { QStringList names; QString fileExt; QString path = defaultSaveFolder() + "/" + QFileInfo(filename).fileName()+"z"; QString bundledFileName = askForFilename ? FolderUtils::getSaveFileName(this, tr("Specify a file name"), path, tr("Fritzing (*%1)").arg(extension), &fileExt) : filename; if (bundledFileName.isEmpty()) return; // Cancel pressed FileProgressDialog progress("Saving...", 0, this); if(!alreadyHasExtension(bundledFileName, extension)) { bundledFileName += extension; } ProcessEventBlocker::processEvents(); QDir destFolder; QString dirToRemove; if (destFolderPath.isEmpty()) { destFolder = QDir::temp(); FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText()); dirToRemove = destFolder.path(); } else { destFolder = QDir(destFolderPath); } QString aux = QFileInfo(bundledFileName).fileName(); QString destSketchPath = // remove the last "z" from the extension destFolder.path()+"/"+aux.left(aux.size()-1); DebugDialog::debug("saving entity temporarily to "+destSketchPath); QStringList skipSuffixes; if (extension.compare(FritzingBundleExtension) == 0) { for (int i = 0; i < m_linkedProgramFiles.count(); i++) { LinkedFile * linkedFile = m_linkedProgramFiles.at(i); QFileInfo fileInfo(linkedFile->linkedFilename); QFile file(linkedFile->linkedFilename); FolderUtils::slamCopy(file, destFolder.absoluteFilePath(fileInfo.fileName())); } skipSuffixes << FritzingBinExtension << FritzingBundleExtension; } if (saveModel) { QString prevFileName = filename; ProcessEventBlocker::processEvents(); bundler->saveAsAux(destSketchPath); filename = prevFileName; } foreach(ModelPart* mp, partsToSave) { names.append(saveBundledAux(mp, destFolder)); } if (deleteLeftovers) { QStringList nameFilters; nameFilters << ("*" + FritzingPartExtension) << "*.svg"; QDir dir(destFolder); QStringList fileList = dir.entryList(nameFilters, QDir::Files | QDir::NoSymLinks); foreach (QString fileName, fileList) { if (!names.contains(fileName)) { QFile::remove(dir.absoluteFilePath(fileName)); } } } ProcessEventBlocker::processEvents(); if(!FolderUtils::createZipAndSaveTo(destFolder, bundledFileName, skipSuffixes)) { QMessageBox::warning( this, tr("Fritzing"), tr("Unable to export %1 as shareable").arg(bundledFileName) ); } if (!dirToRemove.isEmpty()) { FolderUtils::rmdir(dirToRemove); } } void MainWindow::createExportActions() { m_saveAct = new QAction(tr("&Save"), this); m_saveAct->setShortcut(tr("Ctrl+S")); m_saveAct->setStatusTip(tr("Save the current sketch")); connect(m_saveAct, SIGNAL(triggered()), this, SLOT(save())); m_saveAsAct = new QAction(tr("&Save As..."), this); m_saveAsAct->setShortcut(tr("Shift+Ctrl+S")); m_saveAsAct->setStatusTip(tr("Save the current sketch")); connect(m_saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); m_shareOnlineAct = new QAction(tr("Share online..."), this); m_shareOnlineAct->setStatusTip(tr("Post a project to the Fritzing website")); connect(m_shareOnlineAct, SIGNAL(triggered()), this, SLOT(shareOnline())); m_exportJpgAct = new QAction(tr("JPG..."), this); m_exportJpgAct->setData(jpgActionType); m_exportJpgAct->setStatusTip(tr("Export the visible area of the current sketch as a JPG image")); connect(m_exportJpgAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportPngAct = new QAction(tr("PNG..."), this); m_exportPngAct->setData(pngActionType); m_exportPngAct->setStatusTip(tr("Export the visible area of the current sketch as a PNG image")); connect(m_exportPngAct, SIGNAL(triggered()), this, SLOT(doExport())); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) m_exportPsAct = new QAction(tr("PostScript..."), this); m_exportPsAct->setData(psActionType); m_exportPsAct->setStatusTip(tr("Export the visible area of the current sketch as a PostScript image")); connect(m_exportPsAct, SIGNAL(triggered()), this, SLOT(doExport())); #endif m_exportPdfAct = new QAction(tr("PDF..."), this); m_exportPdfAct->setData(pdfActionType); m_exportPdfAct->setStatusTip(tr("Export the visible area of the current sketch as a PDF image")); connect(m_exportPdfAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportSvgAct = new QAction(tr("SVG..."), this); m_exportSvgAct->setData(svgActionType); m_exportSvgAct->setStatusTip(tr("Export the current sketch as an SVG image")); connect(m_exportSvgAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportBomAct = new QAction(tr("List of parts (&Bill of Materials)..."), this); m_exportBomAct->setData(bomActionType); m_exportBomAct->setStatusTip(tr("Save a Bill of Materials (BoM)/Shopping List as text")); connect(m_exportBomAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportNetlistAct = new QAction(tr("XML Netlist..."), this); m_exportNetlistAct->setData(netlistActionType); m_exportNetlistAct->setStatusTip(tr("Save a netlist in XML format")); connect(m_exportNetlistAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportSpiceNetlistAct = new QAction(tr("SPICE Netlist..."), this); m_exportSpiceNetlistAct->setData(spiceNetlistActionType); m_exportSpiceNetlistAct->setStatusTip(tr("Save a netlist in SPICE format")); connect(m_exportSpiceNetlistAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportEagleAct = new QAction(tr("Eagle..."), this); m_exportEagleAct->setData(eagleActionType); m_exportEagleAct->setStatusTip(tr("Export the current sketch to Eagle CAD")); connect(m_exportEagleAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportGerberAct = new QAction(tr("Extended Gerber (RS-274X)..."), this); m_exportGerberAct->setData(gerberActionType); m_exportGerberAct->setStatusTip(tr("Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production")); connect(m_exportGerberAct, SIGNAL(triggered()), this, SLOT(doExport())); m_exportEtchablePdfAct = new QAction(tr("Etchable (PDF)..."), this); m_exportEtchablePdfAct->setStatusTip(tr("Export the current sketch to PDF for DIY PCB production (photoresist)")); m_exportEtchablePdfAct->setProperty("svg", false); connect(m_exportEtchablePdfAct, SIGNAL(triggered()), this, SLOT(exportEtchable())); m_exportEtchableSvgAct = new QAction(tr("Etchable (SVG)..."), this); m_exportEtchableSvgAct->setStatusTip(tr("Export the current sketch to SVG for DIY PCB production (photoresist)")); m_exportEtchableSvgAct->setProperty("svg", true); connect(m_exportEtchableSvgAct, SIGNAL(triggered()), this, SLOT(exportEtchable())); /*m_pageSetupAct = new QAction(tr("&Page Setup..."), this); m_pageSetupAct->setShortcut(tr("Shift+Ctrl+P")); m_pageSetupAct->setStatusTip(tr("Setup the current sketch page")); connect(m_pageSetupAct, SIGNAL(triggered()), this, SLOT(pageSetup()));*/ m_printAct = new QAction(tr("&Print..."), this); m_printAct->setShortcut(tr("Ctrl+P")); m_printAct->setStatusTip(tr("Print the current view")); connect(m_printAct, SIGNAL(triggered()), this, SLOT(print())); } void MainWindow::exportToEagle() { QString text = tr("This will soon provide an export of your Fritzing sketch to the EAGLE layout " "software. If you'd like to have more exports to your favourite EDA tool, please let " "us know, or contribute."); /* QString text = tr("The Eagle export module is very experimental. If anything breaks or behaves " "strangely, please let us know."); */ QMessageBox::information(this, tr("Fritzing"), text); Fritzing2Eagle eagle = Fritzing2Eagle(m_pcbGraphicsView); /* QList partList; // bail out if something is wrong // TODO: show an error in QMessageBox if(m_currentWidget == NULL) { return; } m_pcbGraphicsView->collectParts(partList); QString exportInfoString = tr("parts include:\n"); QString exportString = tr("GRID INCH 0.005\n"); for(int i=0; i < partList.size(); i++){ QString label = partList.at(i)->instanceTitle(); QString desc = partList.at(i)->title(); QHash properties = partList.at(i)->modelPartShared()->properties(); QString package = properties["package"]; if (package == NULL) { package = tr("*** package not specified ***"); } exportInfoString += label + tr(" which is a ") + desc + tr(" in a ") + package + tr(" package.\n"); } QMessageBox::information(this, tr("Fritzing"), exportInfoString); */ /* QFile fp( fileName ); fp.open(QIODevice::WriteOnly); fp.write(bom.toUtf8(),bom.length()); fp.close(); */ /* GRID INCH 0.005 USE '/Applications/eclipse/eagle/lbr/fritzing.lbr'; ADD RESISTOR@fritzing 'R_1' R0.000 (2.3055117 2.1307087); ADD LED@fritzing 'L_2' R0.000 (5.423622 2.425197); GRID LAST; */ } void MainWindow::exportSvg(double res, bool selectedItems, bool flatten) { QString path = defaultSaveFolder(); QString fileExt; QString fileName = FolderUtils::getSaveFileName(this, tr("Export SVG..."), path+"/"+constructFileName("", svgActionType), fileExtFormats[svgActionType], &fileExt ); if (fileName.isEmpty()) return; exportSvg(res, selectedItems, flatten, fileName); } void MainWindow::exportSvg(double res, bool selectedItems, bool flatten, const QString & fileName) { FileProgressDialog * fileProgressDialog = exportProgress(); LayerList viewLayerIDs; foreach (ViewLayer * viewLayer, m_currentGraphicsView->viewLayers()) { if (viewLayer == NULL) continue; if (!viewLayer->visible()) continue; viewLayerIDs << viewLayer->viewLayerID(); } RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = false; renderThing.dpi = res; renderThing.selectedItems = selectedItems; renderThing.hideTerminalPoints = true; renderThing.renderBlocker = false; QString svg = m_currentGraphicsView->renderToSVG(renderThing, NULL, viewLayerIDs); if (svg.isEmpty()) { // tell the user something reasonable return; } if (selectedItems == false && flatten == false) { exportSvgWatermark(svg, res); } TextUtils::writeUtf8(fileName, TextUtils::convertExtendedChars(svg)); delete fileProgressDialog; } void MainWindow::exportSvgWatermark(QString & svg, double res) { QFile file(":/resources/images/watermark_fritzing_outline.svg"); if (!file.open(QFile::ReadOnly)) return; QString watermarkSvg = file.readAll(); file.close(); if (!watermarkSvg.contains(""; svg = TextUtils::mergeSvg(newSvg, svg, "", false); } void MainWindow::exportBOM() { // bail out if something is wrong // TODO: show an error in QMessageBox if (m_currentWidget == NULL) { return; } QString bomTemplate; QFile file(":/resources/templates/bom.html"); if (file.open(QFile::ReadOnly)) { bomTemplate = file.readAll(); file.close(); } else { return; } QString bomRowTemplate; QFile file2(":/resources/templates/bom_row.html"); if (file2.open(QFile::ReadOnly)) { bomRowTemplate = file2.readAll(); file2.close(); } else { return; } QList partList; QList descrList; QMultiHash descrs; m_currentGraphicsView->collectParts(partList); qSort(partList.begin(), partList.end(), sortPartList); foreach (ItemBase * itemBase, partList) { if (itemBase->itemType() != ModelPart::Part) continue; QString desc = itemBase->title() + "%%%%%" + getBomProps(itemBase); // keeps different parts separate if there are no properties descrs.insert(desc, itemBase); if (!descrList.contains(desc)) { descrList.append(desc); } } QString assemblyString; foreach (ItemBase * itemBase, partList) { if (itemBase->itemType() != ModelPart::Part) continue; assemblyString += bomRowTemplate.arg(itemBase->instanceTitle()).arg(itemBase->title()).arg(getBomProps(itemBase)); } QString shoppingListString; foreach (QString descr, descrList) { QList itemBases = descrs.values(descr); QStringList split = descr.split("%%%%%"); shoppingListString += bomRowTemplate.arg(itemBases.count()).arg(split.at(0)).arg(split.at(1)); } QString bom = bomTemplate .arg("Fritzing Bill of Materials") .arg(QFileInfo(m_fwFilename).fileName()) .arg(m_fwFilename) .arg(QDateTime::currentDateTime().toString("dddd, MMMM d yyyy, hh:mm:ss")) .arg(assemblyString) .arg(shoppingListString) .arg(QString("%1.%2.%3").arg(Version::majorVersion()).arg(Version::minorVersion()).arg(Version::minorSubVersion())); QString path = defaultSaveFolder(); QString fileExt; QString extFmt = fileExtFormats.value(bomActionType); QString fname = path+"/"+constructFileName("bom", bomActionType); DebugDialog::debug(QString("fname %1\n%2").arg(fname).arg(extFmt)); QString fileName = FolderUtils::getSaveFileName(this, tr("Export Bill of Materials (BoM)..."), fname, extFmt, &fileExt ); if (fileName.isEmpty()) { return; //Cancel pressed } FileProgressDialog * fileProgressDialog = exportProgress(); DebugDialog::debug(fileExt+" selected to export"); if(!alreadyHasExtension(fileName, bomActionType)) { fileName += bomActionType; } if (!TextUtils::writeUtf8(fileName, bom)) { QMessageBox::warning(this, tr("Fritzing"), tr("Unable to save BOM file, but the text is on the clipboard.")); } QFileInfo info(fileName); if (info.exists()) { QDesktopServices::openUrl(QString("file:///%1").arg(fileName)); } QClipboard *clipboard = QApplication::clipboard(); if (clipboard != NULL) { clipboard->setText(bom); } delete fileProgressDialog; } void MainWindow::exportSpiceNetlist() { if (m_schematicGraphicsView == NULL) return; // examples: // http://www.allaboutcircuits.com/vol_5/chpt_7/8.html // http://cutler.eecs.berkeley.edu/classes/icbook/spice/UserGuide/elements_fr.html // http://www.csd.uoc.gr/~hy422/2011s/datasheets/ngspice-user-manual.pdf QString path = defaultSaveFolder(); QString fileExt; QString extFmt = fileExtFormats.value(spiceNetlistActionType); QString fname = path + "/" + constructFileName("spice", spiceNetlistActionType); //DebugDialog::debug(QString("fname %1\n%2").arg(fname).arg(extFmt)); QString fileName = FolderUtils::getSaveFileName(this, tr("Export SPICE Netlist..."), fname, extFmt, &fileExt ); if (fileName.isEmpty()) { return; //Cancel pressed } static QRegExp curlies("\\{([^\\}]*)\\}"); QFileInfo fileInfo(m_fwFilename); QString output = fileInfo.completeBaseName(); output += "\n"; QHash indexer; QList< QList* > netList; this->m_schematicGraphicsView->collectAllNets(indexer, netList, true, false); //DebugDialog::debug("_______________"); QSet itemBases; QList * ground = NULL; foreach (QList * net, netList) { if (net->count() < 2) continue; foreach (ConnectorItem * ci, *net) { //ci->debugInfo("net"); if (ci->isGrounded()) { ground = net; } itemBases.insert(ci->attachedTo()); } //DebugDialog::debug("_______________"); } if (ground) { // make sure ground is index zero netList.removeOne(ground); netList.prepend(ground); } //DebugDialog::debug("_______________"); //DebugDialog::debug("_______________"); DebugDialog::debug("_______________"); foreach (QList * net, netList) { if (net->count() < 2) continue; foreach (ConnectorItem * ci, *net) { ci->debugInfo("net"); } DebugDialog::debug("_______________"); } //DebugDialog::debug("_______________"); //DebugDialog::debug("_______________"); foreach (ItemBase * itemBase, itemBases) { QString spice = itemBase->spice(); if (spice.isEmpty()) continue; while (true) { int ix = curlies.indexIn(spice); if (ix < 0) break; QString token = curlies.cap(1).toLower(); QString replacement; if (token == "instancetitle") { replacement = itemBase->instanceTitle(); if (ix > 0 && replacement.at(0).toLower() == spice.at(ix - 1).toLower()) { // if the type letter is repeated replacement = replacement.mid(1); } replacement.replace(" ", "_"); } else if (token.startsWith("net ")) { QString cname = token.mid(4).trimmed(); foreach (ConnectorItem * ci, itemBase->cachedConnectorItems()) { if (ci->connectorSharedID().toLower() == cname) { int ix = -1; foreach (QList * net, netList) { ix++; if (net->contains(ci)) break; } replacement = QString::number(ix); break; } } } else { QVariant variant = itemBase->modelPart()->localProp(token); if (variant.isNull()) { replacement = itemBase->modelPart()->properties().value(token, ""); } else { replacement = variant.toString(); } } spice.replace(ix, curlies.cap(0).count(), replacement); DebugDialog::debug("spice " + spice); } output += spice; } output += "\n"; // remove redundant models QStringList models; foreach (ItemBase * itemBase, itemBases) { QString spiceModel = itemBase->spiceModel(); if (spiceModel.isEmpty()) continue; if (models.contains(spiceModel, Qt::CaseInsensitive)) continue; models.append(spiceModel); } foreach (QString model, models) { output += model; output += "\n"; } QString incl = ".include"; if (output.contains(incl, Qt::CaseInsensitive)) { QStringList lines = output.split("\n"); QList paths; paths << FolderUtils::getApplicationSubFolder("pdb"); paths << FolderUtils::getApplicationSubFolder("parts"); paths << new QDir(FolderUtils::getUserDataStorePath("parts")); QString output2; foreach (QString line, lines) { int ix = line.toLower().indexOf(incl); if (ix < 0) { output2 += line + "\n"; continue; } QString temp = line; temp.replace(ix, incl.length(), ""); QString filename = temp.trimmed(); bool gotOne = false; foreach (QDir * dir, paths) { foreach (QString folder, ModelPart::possibleFolders()) { QDir sub(*dir); sub.cd(folder); sub.cd("spicemodels"); if (QFile::exists(sub.absoluteFilePath(filename))) { output2 += incl.toUpper() + " " + QDir::toNativeSeparators(sub.absoluteFilePath(filename)) + "\n"; gotOne = true; break; } } if (gotOne) break; } // can't find the include file, so just restore the original line if (!gotOne) { output2 += line + "\n"; } } output = output2; foreach (QDir * dir, paths) delete dir; } output += ".TRAN 1ms 100ms\n"; output += "* .AC DEC 100 100 1MEG\n"; output += ".END\n"; foreach (QList * net, netList) { delete net; } netList.clear(); QClipboard *clipboard = QApplication::clipboard(); if (clipboard != NULL) { clipboard->setText(output); } //DebugDialog::debug(fileExt + " selected to export"); if(!alreadyHasExtension(fileName, spiceNetlistActionType)) { fileName += spiceNetlistActionType; } TextUtils::writeUtf8(fileName, output); } void MainWindow::exportNetlist() { QHash indexer; QList< QList* > netList; this->m_currentGraphicsView->collectAllNets(indexer, netList, true, m_currentGraphicsView->boardLayers() > 1); QDomDocument doc; doc.setContent(QString("\n") + TextUtils::CreatedWithFritzingXmlComment); QDomElement netlist = doc.createElement("netlist"); doc.appendChild(netlist); netlist.setAttribute("sketch", QFileInfo(m_fwFilename).fileName()); netlist.setAttribute("date", QDateTime::currentDateTime().toString()); // TODO: filter out 'ignore' connectors QList< QList* > deleteNets; foreach (QList * net, netList) { QList deleteItems; foreach (ConnectorItem * connectorItem, *net) { ErcData * ercData = connectorItem->connectorSharedErcData(); if (ercData == NULL) continue; if (ercData->ignore() == ErcData::Always) { deleteItems.append(connectorItem); } else if ((ercData->ignore() == ErcData::IfUnconnected) && (net->count() == 1)) { deleteItems.append(connectorItem); } } foreach (ConnectorItem * connectorItem, deleteItems) { net->removeOne(connectorItem); } if (net->count() == 0) { deleteNets.append(net); } } foreach (QList * net, deleteNets) { netList.removeOne(net); } foreach (QList * net, netList) { QDomElement netElement = doc.createElement("net"); netlist.appendChild(netElement); foreach (ConnectorItem * connectorItem, *net) { QDomElement connector = doc.createElement("connector"); netElement.appendChild(connector); connector.setAttribute("id", connectorItem->connectorSharedID()); connector.setAttribute("name", connectorItem->connectorSharedName()); QDomElement part = doc.createElement("part"); connector.appendChild(part); ItemBase * itemBase = connectorItem->attachedTo(); part.setAttribute("id", itemBase->id()); part.setAttribute("label", itemBase->instanceTitle()); part.setAttribute("title", itemBase->title()); ErcData * ercData = connectorItem->connectorSharedErcData(); if (ercData != NULL) { QDomElement erc = doc.createElement("erc"); if (ercData->writeToElement(erc, doc)) { connector.appendChild(erc); } } } } foreach (QList * net, netList) { delete net; } netList.clear(); QString path = defaultSaveFolder(); QString fileExt; QString extFmt = fileExtFormats.value(netlistActionType); QString fname = path + "/" +constructFileName("netlist", netlistActionType); //DebugDialog::debug(QString("fname %1\n%2").arg(fname).arg(extFmt)); QString fileName = FolderUtils::getSaveFileName(this, tr("Export Netlist..."), fname, extFmt, &fileExt ); if (fileName.isEmpty()) { return; //Cancel pressed } FileProgressDialog * fileProgressDialog = exportProgress(); //DebugDialog::debug(fileExt + " selected to export"); if(!alreadyHasExtension(fileName, netlistActionType)) { fileName += netlistActionType; } QFile fp( fileName ); fp.open(QIODevice::WriteOnly); fp.write(doc.toByteArray()); fp.close(); QClipboard *clipboard = QApplication::clipboard(); if (clipboard != NULL) { clipboard->setText(doc.toByteArray()); } delete fileProgressDialog; } FileProgressDialog * MainWindow::exportProgress() { return (new FileProgressDialog("Exporting...", 0, this)); } void MainWindow::exportNormalizedSVG() { exportSvg(GraphicsUtils::StandardFritzingDPI, true, false); } void MainWindow::exportNormalizedFlattenedSVG() { exportSvg(GraphicsUtils::StandardFritzingDPI, true, true); } QString MainWindow::getBomProps(ItemBase * itemBase) { if (itemBase == NULL) return ""; QStringList keys; QHash properties = HtmlInfoView::getPartProperties(itemBase->modelPart(), itemBase, false, keys); QString pString; foreach (QString key, keys) { if (key.compare("family") == 0) continue; QString value = properties.value(key); QWidget widget; QWidget * resultWidget = NULL; QString resultKey, resultValue; bool hide; itemBase->collectExtraInfo(&widget, properties.value("family"), key, value, false, resultKey, resultValue, resultWidget, hide); if (resultValue.isEmpty()) continue; pString += ItemBase::translatePropertyName(resultKey) + " " + resultValue + "; "; } if (pString.length() > 2) pString.chop(2); return pString; } void MainWindow::exportToGerber() { //NOTE: this assumes just one board per sketch int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); // barf an error if there's no board if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to export to Gerber.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Gerber export can only handle one board at a time--please select the board you want to export.")); return; } QString exportDir = QFileDialog::getExistingDirectory(this, tr("Choose a folder for exporting"), defaultSaveFolder(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (exportDir.isEmpty()) return; FileProgressDialog * fileProgressDialog = exportProgress(); FolderUtils::setOpenSaveFolder(exportDir); m_pcbGraphicsView->saveLayerVisibility(); m_pcbGraphicsView->setAllLayersVisible(true); QFileInfo info(m_fwFilename); QString prefix = info.completeBaseName(); if (boardCount > 1) { prefix += QString("_%1_%2").arg(board->instanceTitle()).arg(board->id()); } GerberGenerator::exportToGerber(prefix, exportDir, board, m_pcbGraphicsView, true); m_pcbGraphicsView->restoreLayerVisibility(); m_statusBar->showMessage(tr("Sketch exported to Gerber"), 2000); delete fileProgressDialog; } void MainWindow::connectStartSave(bool doConnect) { if (doConnect) { connect(m_sketchModel->root(), SIGNAL(startSaveInstances(const QString &, ModelPart *, QXmlStreamWriter &)), this, SLOT(startSaveInstancesSlot(const QString &, ModelPart *, QXmlStreamWriter &)), Qt::DirectConnection); } else { disconnect(m_sketchModel->root(), SIGNAL(startSaveInstances(const QString &, ModelPart *, QXmlStreamWriter &)), this, SLOT(startSaveInstancesSlot(const QString &, ModelPart *, QXmlStreamWriter &))); } } QString MainWindow::constructFileName(const QString & differentiator, const QString & suffix) { QString fn = QFileInfo(m_fwFilename).completeBaseName(); fn += "_" + (differentiator.isEmpty() ? m_currentGraphicsView->getShortName() : differentiator); return fn + suffix; } void MainWindow::massageOutput(QString & svg, bool doMask, bool doSilk, bool doPaste, QString & maskTop, QString & maskBottom, const QString & fileName, ItemBase * board, int dpi, const LayerList & viewLayerIDs) { if (doPaste) { // must test doPaste first, since doMask will also be true svg = pcbView()->makePasteMask(svg, board, dpi, viewLayerIDs); } else if (doSilk) { QString use = (fileName.contains("bottom")) ? maskBottom : maskTop; use = TextUtils::expandAndFill(use, "white", GerberGenerator::MaskClearanceMils * 2 * dpi / 1000); svg = TextUtils::mergeSvg(svg, use, "", false); } else if (doMask) { if (fileName.contains("bottom")) maskBottom = svg; else maskTop = svg; svg = TextUtils::expandAndFill(svg, "black", GerberGenerator::MaskClearanceMils * 2 * dpi / 1000); } } void MainWindow::dumpAllParts() { if (m_currentGraphicsView == NULL) return; QList already; foreach (QGraphicsItem * item, m_currentGraphicsView->items()) { ItemBase * ib = dynamic_cast(item); if (ib == NULL) continue; ItemBase * chief = ib->layerKinChief(); if (already.contains(chief)) continue; already << chief; QList itemBases; itemBases << chief; itemBases.append(chief->layerKin()); foreach (ItemBase * itemBase, itemBases) { itemBase->debugInfo(""); foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { if (connectorItem->connectionsCount() > 0) { connectorItem->debugInfo("\t"); foreach (ConnectorItem * to, connectorItem->connectedToItems()) { to->debugInfo("\t\t"); } } } } } } fritzing-app-0.9.2b/src/mainwindow/mainwindow_menu.cpp000066400000000000000000005001571250202676700231640ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6999 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 14:14:07 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "mainwindow.h" #include "../debugdialog.h" #include "../waitpushundostack.h" #include "../partseditor/pemainwindow.h" #include "../help/aboutbox.h" #include "../autoroute/mazerouter/mazerouter.h" #include "../autoroute/autorouteprogressdialog.h" #include "../autoroute/drc.h" #include "../items/virtualwire.h" #include "../items/resizableboard.h" #include "../items/jumperitem.h" #include "../items/via.h" #include "../fsvgrenderer.h" #include "../items/note.h" #include "../eagle/fritzing2eagle.h" #include "../sketch/breadboardsketchwidget.h" #include "../sketch/schematicsketchwidget.h" #include "../sketch/pcbsketchwidget.h" #include "../partsbinpalette/binmanager/binmanager.h" #include "../utils/expandinglabel.h" #include "../infoview/htmlinfoview.h" #include "../utils/bendpointaction.h" #include "../sketch/fgraphicsscene.h" #include "../utils/fmessagebox.h" #include "../utils/fileprogressdialog.h" #include "../svg/svgfilesplitter.h" #include "../version/version.h" #include "../svg/groundplanegenerator.h" #include "../help/tipsandtricks.h" #include "../dialogs/setcolordialog.h" #include "../utils/folderutils.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../connectors/ercdata.h" #include "../items/moduleidnames.h" #include "../utils/zoomslider.h" #include "../dock/layerpalette.h" #include "../program/programwindow.h" #include "../utils/autoclosemessagebox.h" #include "../processeventblocker.h" #include "../sketchtoolbutton.h" #include "../help/firsttimehelpdialog.h" //////////////////////////////////////////////////////// // help struct to create the example menu from a xml file struct SketchDescriptor { SketchDescriptor(const QString &_id, const QString &_name, const QString &_src, QAction * _action) { id = _id; name = _name; src = _src; action = _action; } QString id; QString name; QString src; QAction * action; }; bool sortSketchDescriptors(SketchDescriptor * s1, SketchDescriptor * s2){ return s1->name.toLower() < s2->name.toLower(); } QDomElement getBestLanguageChild(const QString & localeName, const QDomElement & parent) { QDomElement language = parent.firstChildElement("language"); QDomElement backupLang; while (!language.isNull()) { if (language.attribute("country") == "en") backupLang = language; if (localeName.endsWith(language.attribute("country"))) { return language; } language = language.nextSiblingElement("language"); } return backupLang; } //////////////////////////////////////////////////////// GridSizeThing::GridSizeThing(const QString & vName, const QString & sName, double defaultSize, const QString & gsText) { defaultGridSize = defaultSize; viewName = vName; shortName = sName; gridSizeText = gsText; } GridSizeDialog::GridSizeDialog(GridSizeThing * gridSizeThing) : QDialog() { m_gridSizeThing = gridSizeThing; } GridSizeThing * GridSizeDialog::gridSizeThing() { return m_gridSizeThing; } ///////////////////////////////////////////////////////// void MainWindow::closeIfEmptySketch(MainWindow* mw) { int cascFactorX; int cascFactorY; // close empty sketch window if user opens from a file if (FolderUtils::isEmptyFileName(mw->m_fwFilename, untitledFileName()) && mw->undoStackIsEmpty()) { QTimer::singleShot(0, mw, SLOT(close()) ); cascFactorX = 0; cascFactorY = 0; } else { cascFactorX = CascadeFactorX; cascFactorY = CascadeFactorY; } mw->move(x()+cascFactorX,y()+cascFactorY); mw->show(); } void MainWindow::mainLoad() { QString path; // if it's the first time load is called use Documents folder if(m_firstOpen){ path = defaultSaveFolder(); m_firstOpen = false; } else { path = ""; } QString fileName = FolderUtils::getOpenFileName( this, tr("Select a Fritzing File to Open"), path, tr("Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5)") .arg(FritzingSketchExtension) .arg(FritzingBundleExtension) .arg(FritzingBundledPartExtension) .arg(FritzingBinExtension) .arg(FritzingBundledBinExtension) ); if (fileName.isEmpty()) return; if (fileName.endsWith(FritzingBundledPartExtension)) { m_binManager->importPartToMineBin(fileName); return; } if (fileName.endsWith(FritzingBinExtension) || fileName.endsWith(FritzingBundledBinExtension)) { m_binManager->openBinIn(fileName, false); return; } mainLoadAux(fileName); } void MainWindow::mainLoadAux(const QString & fileName) { if (fileName.isNull()) return; if (fileName.endsWith(".txt")) { QFileInfo info(fileName); QFile file(fileName); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); while (!stream.atEnd()) { QString line = stream.readLine().trimmed(); foreach (QString ext, fritzingExtensions()) { if (line.endsWith(ext)) { QFileInfo lineInfo(line); if (lineInfo.exists()) { mainLoadAux(line); } else { QFileInfo lineInfo(info.absoluteDir().absoluteFilePath(line)); if (lineInfo.exists()) { mainLoadAux(lineInfo.absoluteFilePath()); } } break; } } } } return; } if (!fileName.endsWith(FritzingSketchExtension) && !fileName.endsWith(FritzingBundleExtension)) { loadWhich(fileName, false, false, true, ""); return; } if (alreadyOpen(fileName)) return; QFile file(fileName); if (!file.exists()) { FMessageBox::warning(this, tr("Fritzing"), tr("Cannot find file %1.") .arg(fileName)); return; } if (!file.open(QFile::ReadOnly | QFile::Text)) { FMessageBox::warning(this, tr("Fritzing"), tr("Cannot read file 1 %1:\n%2.") .arg(fileName) .arg(file.errorString())); return; } file.close(); MainWindow* mw = newMainWindow(m_referenceModel, fileName, true, true, -1); mw->loadWhich(fileName, true, true, true, ""); mw->clearFileProgressDialog(); closeIfEmptySketch(mw); } void MainWindow::revert() { QMessageBox::StandardButton answer = QMessageBox::question( this, tr("Revert?"), tr("This operation can not be undone--you will lose all of your changes." "\n\nGo ahead and revert?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ); // TODO: make button texts translatable if (answer != QMessageBox::Yes) { return; } revertAux(); } MainWindow * MainWindow::revertAux() { MainWindow* mw = newMainWindow( m_referenceModel, fileName(), true, true, this->currentTabIndex()); mw->setGeometry(this->geometry()); QFileInfo info(fileName()); if (info.exists() || !FolderUtils::isEmptyFileName(this->m_fwFilename, untitledFileName())) { mw->loadWhich(fileName(), true, true, true, ""); } else { mw->addDefaultParts(); mw->show(); mw->hideTempPartsBin(); } mw->clearFileProgressDialog(); // TODO: restore zoom, scroll, etc. for each view mw->setCurrentTabIndex(currentTabIndex()); this->setCloseSilently(true); this->close(); return mw; } bool MainWindow::loadWhich(const QString & fileName, bool setAsLastOpened, bool addToRecent, bool checkObsolete, const QString & displayName) { if (!QFileInfo(fileName).exists()) { FMessageBox::warning(NULL, tr("Fritzing"), tr("File '%1' not found").arg(fileName)); return false; } bool result = false; if (fileName.endsWith(FritzingSketchExtension)) { QFileInfo info(fileName); FMessageBox messageBox(NULL); messageBox.setWindowTitle(tr("the .fz file format is obsolete")); messageBox.setText(tr("The .fz file format has been deprecated.\n\nWould you like to convert '%1' to the .fzz format now or open it read-only?\n").arg(info.fileName())); messageBox.setInformativeText(tr("The conversion process will not modify '%1'.").arg(info.fileName())); messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Yes); messageBox.setIcon(QMessageBox::Question); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Yes, tr("Convert")); messageBox.setButtonText(QMessageBox::No, tr("Read-only")); messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec(); if (answer == QMessageBox::Cancel) return false; QString bundledFileName; if (answer == QMessageBox::Yes) { QString fileExt; bundledFileName = FolderUtils::getSaveFileName(this, tr("Please specify an .fzz file name to save '%1' to").arg(info.fileName()), fileName + "z", tr("Fritzing (*%1)").arg(FritzingBundleExtension), &fileExt); if (bundledFileName.isEmpty()) return false; } mainLoad(fileName, displayName, checkObsolete); result = true; QFile file(fileName); QDir dest(m_fzzFolder); FolderUtils::slamCopy(file, dest.absoluteFilePath(info.fileName())); // copy the .fz file directly if (answer == QMessageBox::Yes) { saveAsShareable(bundledFileName, false); // false to prevent saving a bundle inside the bundle setCurrentFile(bundledFileName, addToRecent, setAsLastOpened); } else { this->setReadOnly(true); setCurrentFile(fileName, false, false); } } else if(fileName.endsWith(FritzingBundleExtension)) { loadBundledSketch(fileName, addToRecent, setAsLastOpened, checkObsolete); result = true; } else if ( fileName.endsWith(FritzingBinExtension) || fileName.endsWith(FritzingBundledBinExtension) ) { m_binManager->load(fileName); result = true; } else if (fileName.endsWith(FritzingPartExtension)) { notYetImplemented(tr("directly loading parts")); } else if (fileName.endsWith(FritzingBundledPartExtension)) { loadBundledPart(fileName, true); result = true; } if (result) { this->show(); } return result; } void MainWindow::mainLoad(const QString & fileName, const QString & displayName, bool checkObsolete) { if (m_fileProgressDialog) { m_fileProgressDialog->setMaximum(200); m_fileProgressDialog->setValue(102); } this->show(); ProcessEventBlocker::processEvents(); QString displayName2 = displayName; if (displayName.isEmpty()) { QFileInfo fileInfo(fileName); displayName2 = fileInfo.fileName(); } if (m_fileProgressDialog) { m_fileProgressDialog->setMessage(tr("loading %1 (model)").arg(displayName2)); m_fileProgressDialog->setValue(110); } ProcessEventBlocker::processEvents(); QList modelParts; connect(m_sketchModel, SIGNAL(loadedViews(ModelBase *, QDomElement &)), this, SLOT(loadedViewsSlot(ModelBase *, QDomElement &)), Qt::DirectConnection); connect(m_sketchModel, SIGNAL(loadedRoot(const QString &, ModelBase *, QDomElement &)), this, SLOT(loadedRootSlot(const QString &, ModelBase *, QDomElement &)), Qt::DirectConnection); connect(m_sketchModel, SIGNAL(obsoleteSMDOrientationSignal()), this, SLOT(obsoleteSMDOrientationSlot()), Qt::DirectConnection); connect(m_sketchModel, SIGNAL(oldSchematicsSignal(const QString &, bool &)), this, SLOT(oldSchematicsSlot(const QString &, bool &)), Qt::DirectConnection); m_obsoleteSMDOrientation = false; m_sketchModel->loadFromFile(fileName, m_referenceModel, modelParts, true); //DebugDialog::debug("core loaded"); disconnect(m_sketchModel, SIGNAL(loadedViews(ModelBase *, QDomElement &)), this, SLOT(loadedViewsSlot(ModelBase *, QDomElement &))); disconnect(m_sketchModel, SIGNAL(loadedRoot(const QString &, ModelBase *, QDomElement &)), this, SLOT(loadedRootSlot(const QString &, ModelBase *, QDomElement &))); disconnect(m_sketchModel, SIGNAL(obsoleteSMDOrientationSignal()), this, SLOT(obsoleteSMDOrientationSlot())); ProcessEventBlocker::processEvents(); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(155); m_fileProgressDialog->setMessage(tr("loading %1 (breadboard)").arg(displayName2)); } QList newIDs; m_breadboardGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs); ProcessEventBlocker::processEvents(); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(170); m_fileProgressDialog->setMessage(tr("loading %1 (pcb)").arg(displayName2)); } newIDs.clear(); m_pcbGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs); ProcessEventBlocker::processEvents(); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(185); m_fileProgressDialog->setMessage(tr("loading %1 (schematic)").arg(displayName2)); } newIDs.clear(); m_schematicGraphicsView->setConvertSchematic(m_convertedSchematic); m_schematicGraphicsView->setOldSchematic(this->m_useOldSchematic); m_schematicGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs); m_schematicGraphicsView->setConvertSchematic(false); ProcessEventBlocker::processEvents(); if (m_fileProgressDialog) { m_fileProgressDialog->setValue(198); } if (m_obsoleteSMDOrientation) { QSet toConvert; foreach (QGraphicsItem * item, m_pcbGraphicsView->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBase = itemBase->layerKinChief(); if (itemBase->modelPart()->flippedSMD() && itemBase->viewLayerPlacement() == ViewLayer::NewBottom) { toConvert.insert(itemBase); } } QList already; foreach (ItemBase * itemBase, toConvert) { PaletteItem * paletteItem = qobject_cast(itemBase); if (paletteItem == NULL) continue; // shouldn't happen paletteItem->rotateItem(180, true); } } if (m_programView) { QFileInfo fileInfo(m_fwFilename); m_programView->linkFiles(m_linkedProgramFiles, fileInfo.absoluteDir().absolutePath()); } if (!m_useOldSchematic && checkObsolete) { if (m_pcbGraphicsView) { QList items = m_pcbGraphicsView->selectAllObsolete(); if (items.count() > 0) { checkSwapObsolete(items, true); } } } initZoom(); } void MainWindow::copy() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->copy(); } void MainWindow::cut() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->cut(); } void MainWindow::pasteInPlace() { pasteAux(true); } void MainWindow::paste() { pasteAux(false); } void MainWindow::pasteAux(bool pasteInPlace) { if (m_currentGraphicsView == NULL) return; QClipboard *clipboard = QApplication::clipboard(); if (clipboard == NULL) { // shouldn't happen return; } const QMimeData* mimeData = clipboard->mimeData(QClipboard::Clipboard); if (mimeData == NULL) return; if (!mimeData->hasFormat("application/x-dnditemsdata")) return; QByteArray itemData = mimeData->data("application/x-dnditemsdata"); QList modelParts; QHash boundingRects; if (m_sketchModel->paste(m_referenceModel, itemData, modelParts, boundingRects, false)) { QUndoCommand * parentCommand = new QUndoCommand("Paste"); QList sketchWidgets; sketchWidgets << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView; sketchWidgets.removeOne(m_currentGraphicsView); sketchWidgets.prepend(m_currentGraphicsView); QList newIDs; foreach (SketchWidget * sketchWidget, sketchWidgets) { newIDs.clear(); QRectF r; QRectF boundingRect = boundingRects.value(sketchWidget->viewName(), r); sketchWidget->loadFromModelParts(modelParts, BaseCommand::SingleView, parentCommand, true, pasteInPlace ? &r : &boundingRect, false, newIDs); } foreach (long id, newIDs) { new IncLabelTextCommand(m_breadboardGraphicsView, id, parentCommand); } m_breadboardGraphicsView->setPasting(true); m_pcbGraphicsView->setPasting(true); m_schematicGraphicsView->setPasting(true); m_undoStack->push(parentCommand); m_breadboardGraphicsView->setPasting(false); m_pcbGraphicsView->setPasting(false); m_schematicGraphicsView->setPasting(false); } m_currentGraphicsView->updateInfoView(); } void MainWindow::duplicate() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->copy(); paste(); //m_currentGraphicsView->duplicate(); } void MainWindow::doDelete() { //DebugDialog::debug(QString("invoking do delete") ); if (m_currentGraphicsView != NULL) { m_currentGraphicsView->deleteSelected(retrieveWire(), false); } } void MainWindow::doDeleteMinus() { if (m_currentGraphicsView != NULL) { m_currentGraphicsView->deleteSelected(retrieveWire(), true); } } void MainWindow::selectAll() { if (m_currentGraphicsView != NULL) { m_currentGraphicsView->selectDeselectAllCommand(true); } } void MainWindow::deselect() { if (m_currentGraphicsView != NULL) { m_currentGraphicsView->selectDeselectAllCommand(false); } } void MainWindow::about() { AboutBox::showAbout(); } void MainWindow::tipsAndTricks() { TipsAndTricks::showTipsAndTricks(); } void MainWindow::firstTimeHelp() { if (m_currentGraphicsView == NULL) return; FirstTimeHelpDialog::setViewID(m_currentGraphicsView->viewID()); FirstTimeHelpDialog::showFirstTimeHelp(); } void MainWindow::createActions() { createRaiseWindowActions(); createFileMenuActions(); createEditMenuActions(); createPartMenuActions(); createViewMenuActions(true); createWindowMenuActions(); createHelpMenuActions(); createTraceMenuActions(); } void MainWindow::createRaiseWindowActions() { m_raiseWindowAct = new QAction(m_fwFilename, this); m_raiseWindowAct->setCheckable(true); connect( m_raiseWindowAct, SIGNAL(triggered()), this, SLOT(raiseAndActivate())); updateRaiseWindowAction(); } void MainWindow::createFileMenuActions() { m_newAct = new QAction(tr("New"), this); m_newAct->setShortcut(tr("Ctrl+N")); m_newAct->setStatusTip(tr("Create a new sketch")); connect(m_newAct, SIGNAL(triggered()), this, SLOT(createNewSketch())); m_openAct = new QAction(tr("&Open..."), this); m_openAct->setShortcut(tr("Ctrl+O")); m_openAct->setStatusTip(tr("Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)")); connect(m_openAct, SIGNAL(triggered()), this, SLOT(mainLoad())); m_revertAct = new QAction(tr("Revert"), this); m_revertAct->setStatusTip(tr("Reload the sketch")); connect(m_revertAct, SIGNAL(triggered()), this, SLOT(revert())); createOpenRecentMenu(); createOpenExampleMenu(); createCloseAction(); createExportActions(); createOrderFabAct(); QString name; QString path; QStringList args; if (externalProcess(name, path, args)) { m_launchExternalProcessAct = new QAction(name, this); m_launchExternalProcessAct->setStatusTip(tr("Shell launch %1").arg(path)); connect(m_launchExternalProcessAct, SIGNAL(triggered()), this, SLOT(launchExternalProcess())); } #ifndef QT_NO_DEBUG m_exceptionAct = new QAction(tr("throw test exception"), this); m_exceptionAct->setStatusTip(tr("throw a fake exception to see what happens")); connect(m_exceptionAct, SIGNAL(triggered()), this, SLOT(throwFakeException())); #endif m_quitAct = new QAction(tr("&Quit"), this); m_quitAct->setShortcut(tr("Ctrl+Q")); m_quitAct->setStatusTip(tr("Quit the application")); connect(m_quitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows2())); m_quitAct->setMenuRole(QAction::QuitRole); } void MainWindow::createOpenExampleMenu() { m_openExampleMenu = new QMenu(tr("&Open Example"), this); QString folderPath = FolderUtils::getApplicationSubFolderPath("sketches")+"/"; populateMenuFromXMLFile(m_openExampleMenu, m_openExampleActions, folderPath, "index.xml"); } void MainWindow::populateMenuFromXMLFile(QMenu *parentMenu, QStringList &actionsTracker, const QString &folderPath, const QString &indexFileName) { QDomDocument dom; QFile file(folderPath+indexFileName); dom.setContent(&file); QDomElement domElem = dom.documentElement(); QDomElement indexDomElem = domElem.firstChildElement("sketches"); QDomElement taxonomyDomElem = domElem.firstChildElement("categories"); QLocale locale; QString localeName = locale.name().toLower(); // get default translation, a string of the form "language_country" where country is a two-letter code. QHash index = indexAvailableElements(indexDomElem, folderPath, actionsTracker, localeName); QList sketchDescriptors(index.values()); qSort(sketchDescriptors.begin(), sketchDescriptors.end(), sortSketchDescriptors); if (sketchDescriptors.size() > 0) { // set up the "all" category QDomElement all = dom.createElement("category"); taxonomyDomElem.appendChild(all); QDomElement language = dom.createElement("language"); language.setAttribute("name", tr("All")); all.appendChild(language); foreach (SketchDescriptor * sketchDescriptor, sketchDescriptors) { QDomElement sketch = dom.createElement("sketch"); sketch.setAttribute("id", sketchDescriptor->id); all.appendChild(sketch); } } populateMenuWithIndex(index, parentMenu, taxonomyDomElem, localeName); foreach (SketchDescriptor * sketchDescriptor, index.values()) { delete sketchDescriptor; } } QHash MainWindow::indexAvailableElements(QDomElement &domElem, const QString &srcPrefix, QStringList & actionsTracker, const QString & localeName) { QHash retval; QDomElement sketch = domElem.firstChildElement("sketch"); // TODO: eventually need to deal with language/country differences like pt_br vs. pt_pt while(!sketch.isNull()) { const QString id = sketch.attribute("id"); QDomElement bestLang = getBestLanguageChild(localeName, sketch); QString name = bestLang.attribute("name"); QString srcAux = bestLang.attribute("src"); // if it's an absolute path, don't prefix it const QString src = QFileInfo(srcAux).exists()? srcAux: srcPrefix+srcAux; if(QFileInfo(src).exists()) { actionsTracker << name; QAction * action = new QAction(name, this); action->setData(src); connect(action,SIGNAL(triggered()),this,SLOT(openRecentOrExampleFile())); retval[id] = new SketchDescriptor(id,name,src, action); } sketch = sketch.nextSiblingElement("sketch"); } return retval; } void MainWindow::populateMenuWithIndex(const QHash &index, QMenu * parentMenu, QDomElement &domElem, const QString & localeName) { // note: the element here is not the same as the element in indexAvailableElements() QDomElement e = domElem.firstChildElement(); while(!e.isNull()) { if (e.nodeName() == "sketch") { QString id = e.attribute("id"); if (!id.isEmpty()) { if(index[id]) { SketchDescriptor * sketchDescriptor = index[id]; parentMenu->addAction(sketchDescriptor->action); } else { qWarning() << tr("MainWindow::populateMenuWithIndex: couldn't load example with id='%1'").arg(id); } } } else if (e.nodeName() == "category") { QDomElement bestLang = getBestLanguageChild(localeName, e); QString name = bestLang.attribute("name"); QMenu * currMenu = new QMenu(name, parentMenu); parentMenu->addMenu(currMenu); populateMenuWithIndex(index, currMenu, e, localeName); } else if (e.nodeName() == "separator") { parentMenu->addSeparator(); } else if (e.nodeName() == "url") { QDomElement bestLang = getBestLanguageChild(localeName, e); QAction * action = new QAction(bestLang.attribute("name"), this); action->setData(bestLang.attribute("href")); connect(action, SIGNAL(triggered()), this, SLOT(openURL())); parentMenu->addAction(action); } e = e.nextSiblingElement(); } } void MainWindow::populateMenuFromFolderContent(QMenu * parentMenu, const QString &path) { QDir *currDir = new QDir(path); QStringList content = currDir->entryList(QDir::AllEntries | QDir::NoDotAndDotDot); if(content.size() > 0) { for(int i=0; i < content.size(); i++) { QString currFile = content.at(i); QString currFilePath = currDir->absoluteFilePath(currFile); if(QFileInfo(currFilePath).isDir()) { QMenu * currMenu = new QMenu(currFile, parentMenu); parentMenu->addMenu(currMenu); populateMenuFromFolderContent(currMenu, currFilePath); } else { QString actionText = QFileInfo(currFilePath).completeBaseName(); m_openExampleActions << actionText; QAction * currAction = new QAction(actionText, this); currAction->setData(currFilePath); connect(currAction,SIGNAL(triggered()),this,SLOT(openRecentOrExampleFile())); parentMenu->addAction(currAction); } } } else { parentMenu->setEnabled(false); } delete currDir; } void MainWindow::createOpenRecentMenu() { m_openRecentFileMenu = new QMenu(tr("&Open Recent Files"), this); for (int i = 0; i < MaxRecentFiles; ++i) { m_openRecentFileActs[i] = new QAction(this); m_openRecentFileActs[i]->setVisible(false); connect(m_openRecentFileActs[i], SIGNAL(triggered()),this, SLOT(openRecentOrExampleFile())); } for (int i = 0; i < MaxRecentFiles; ++i) { m_openRecentFileMenu->addAction(m_openRecentFileActs[i]); } updateRecentFileActions(); } void MainWindow::updateFileMenu() { m_printAct->setEnabled(m_currentGraphicsView != NULL || m_currentWidget->contentView() == m_programView); updateRecentFileActions(); m_orderFabAct->setEnabled(true); m_revertAct->setEnabled(m_undoStack->canUndo()); } void MainWindow::updateRecentFileActions() { QSettings settings; QStringList files = settings.value("recentFileList").toStringList(); int ix = 0; for (int i = 0; i < files.size(); ++i) { QFileInfo finfo(files[i]); if (!finfo.exists()) continue; QString text = tr("&%1 %2").arg(ix + 1).arg(finfo.fileName()); m_openRecentFileActs[ix]->setText(text); m_openRecentFileActs[ix]->setData(files[i]); m_openRecentFileActs[ix]->setVisible(true); m_openRecentFileActs[ix]->setStatusTip(files[i]); if (++ix >= (int) MaxRecentFiles) { break; } } for (int j = ix; j < MaxRecentFiles; ++j) { m_openRecentFileActs[j]->setVisible(false); } m_openRecentFileMenu->setEnabled(ix > 0); } void MainWindow::createEditMenuActions() { m_undoAct = m_undoGroup->createUndoAction(this, tr("Undo")); m_undoAct->setShortcuts(QKeySequence::Undo); m_undoAct->setText(tr("Undo")); m_redoAct = m_undoGroup->createRedoAction(this, tr("Redo")); m_redoAct->setShortcuts(QKeySequence::Redo); m_redoAct->setText(tr("Redo")); m_cutAct = new QAction(tr("&Cut"), this); m_cutAct->setShortcut(QKeySequence::Cut); m_cutAct->setStatusTip(tr("Cut selection")); connect(m_cutAct, SIGNAL(triggered()), this, SLOT(cut())); m_copyAct = new QAction(tr("&Copy"), this); m_copyAct->setShortcut(QKeySequence::Copy); m_copyAct->setStatusTip(tr("Copy selection")); connect(m_copyAct, SIGNAL(triggered()), this, SLOT(copy())); m_pasteAct = new QAction(tr("&Paste"), this); m_pasteAct->setShortcut(QKeySequence::Paste); m_pasteAct->setStatusTip(tr("Paste clipboard contents")); connect(m_pasteAct, SIGNAL(triggered()), this, SLOT(paste())); m_pasteInPlaceAct = new QAction(tr("Paste in Place"), this); m_pasteInPlaceAct->setShortcut(tr("Ctrl+Shift+V")); m_pasteInPlaceAct->setStatusTip(tr("Paste clipboard contents in place")); connect(m_pasteInPlaceAct, SIGNAL(triggered()), this, SLOT(pasteInPlace())); m_duplicateAct = new QAction(tr("&Duplicate"), this); m_duplicateAct->setShortcut(tr("Ctrl+D")); m_duplicateAct->setStatusTip(tr("Duplicate selection")); connect(m_duplicateAct, SIGNAL(triggered()), this, SLOT(duplicate())); m_deleteAct = new QAction(tr("&Delete"), this); m_deleteAct->setStatusTip(tr("Delete selection")); connect(m_deleteAct, SIGNAL(triggered()), this, SLOT(doDelete())); #ifdef Q_OS_MAC m_deleteAct->setShortcut(Qt::Key_Backspace); #else m_deleteAct->setShortcut(QKeySequence::Delete); #endif m_deleteMinusAct = new QAction(tr("Delete Minus"), this); m_deleteMinusAct->setStatusTip(tr("Delete selection without attached wires")); connect(m_deleteMinusAct, SIGNAL(triggered()), this, SLOT(doDeleteMinus())); #ifdef Q_OS_MAC m_deleteMinusAct->setShortcut(Qt::Key_Backspace | Qt::AltModifier); #endif m_deleteWireAct = new WireAction(m_deleteAct); m_deleteWireAct->setText(tr("&Delete Wire")); connect(m_deleteWireAct, SIGNAL(triggered()), this, SLOT(doDelete())); m_deleteWireMinusAct = new WireAction(m_deleteMinusAct); m_deleteWireMinusAct->setText(tr("Delete Wire up to bendpoints")); connect(m_deleteWireMinusAct, SIGNAL(triggered()), this, SLOT(doDeleteMinus())); m_selectAllAct = new QAction(tr("&Select All"), this); m_selectAllAct->setShortcut(QKeySequence::SelectAll); m_selectAllAct->setStatusTip(tr("Select all elements")); connect(m_selectAllAct, SIGNAL(triggered()), this, SLOT(selectAll())); m_deselectAct = new QAction(tr("&Deselect"), this); m_deselectAct->setStatusTip(tr("Deselect")); connect(m_deselectAct, SIGNAL(triggered()), this, SLOT(deselect())); m_addNoteAct = new QAction(tr("Add Note"), this); m_addNoteAct->setStatusTip(tr("Add a note")); connect(m_addNoteAct, SIGNAL(triggered()), this, SLOT(addNote())); m_preferencesAct = new QAction(tr("&Preferences..."), this); m_preferencesAct->setStatusTip(tr("Show the application's about box")); m_preferencesAct->setMenuRole(QAction::PreferencesRole); // make sure this is added to the correct menu on mac connect(m_preferencesAct, SIGNAL(triggered()), QApplication::instance(), SLOT(preferences())); } void MainWindow::createPartMenuActions() { m_openInPartsEditorNewAct = new QAction(tr("Edit (new parts editor)"), this); m_openInPartsEditorNewAct->setStatusTip(tr("Open the new parts editor on an existing part")); connect(m_openInPartsEditorNewAct, SIGNAL(triggered()), this, SLOT(openInPartsEditorNew())); m_disconnectAllAct = new QAction(tr("Disconnect All Wires"), this); m_disconnectAllAct->setStatusTip(tr("Disconnect all wires connected to this connector")); connect(m_disconnectAllAct, SIGNAL(triggered()), this, SLOT(disconnectAll())); #ifndef QT_NO_DEBUG m_infoViewOnHoverAction = new QAction(tr("Update InfoView on hover"), this); m_infoViewOnHoverAction->setCheckable(true); bool infoViewOnHover = true; m_infoViewOnHoverAction->setChecked(infoViewOnHover); setInfoViewOnHover(infoViewOnHover); connect(m_infoViewOnHoverAction, SIGNAL(toggled(bool)), this, SLOT(setInfoViewOnHover(bool))); m_exportNormalizedSvgAction = new QAction(tr("Export Normalized SVG"), this); m_exportNormalizedSvgAction->setStatusTip(tr("Export 1000 dpi SVG of this part in this view")); connect(m_exportNormalizedSvgAction, SIGNAL(triggered()), this, SLOT(exportNormalizedSVG())); m_exportNormalizedFlattenedSvgAction = new QAction(tr("Export Normalized Flattened SVG"), this); m_exportNormalizedFlattenedSvgAction->setStatusTip(tr("Export 1000 dpi Flattened SVG of this part in this view")); connect(m_exportNormalizedFlattenedSvgAction, SIGNAL(triggered()), this, SLOT(exportNormalizedFlattenedSVG())); m_dumpAllPartsAction = new QAction(tr("Dump all parts"), this); m_dumpAllPartsAction->setStatusTip(tr("Debug dump all parts in this view")); connect(m_dumpAllPartsAction, SIGNAL(triggered()), this, SLOT(dumpAllParts())); m_testConnectorsAction = new QAction(tr("Test Connectors"), this); m_testConnectorsAction->setStatusTip(tr("Connect all connectors to a single test part")); connect(m_testConnectorsAction, SIGNAL(triggered()), this, SLOT(testConnectors())); #endif m_rotate45cwAct = new QAction(tr("Rotate 45\x00B0 Clockwise"), this); m_rotate45cwAct->setStatusTip(tr("Rotate current selection 45 degrees clockwise")); connect(m_rotate45cwAct, SIGNAL(triggered()), this, SLOT(rotate45cw())); m_rotate90cwAct = new QAction(tr("Rotate 90\x00B0 Clockwise"), this); m_rotate90cwAct->setStatusTip(tr("Rotate the selected parts by 90 degrees clockwise")); connect(m_rotate90cwAct, SIGNAL(triggered()), this, SLOT(rotate90cw())); m_rotate180Act = new QAction(tr("Rotate 180\x00B0"), this); m_rotate180Act->setStatusTip(tr("Rotate the selected parts by 180 degrees")); connect(m_rotate180Act, SIGNAL(triggered()), this, SLOT(rotate180())); m_rotate90ccwAct = new QAction(tr("Rotate 90\x00B0 Counter Clockwise"), this); m_rotate90ccwAct->setStatusTip(tr("Rotate current selection 90 degrees counter clockwise")); connect(m_rotate90ccwAct, SIGNAL(triggered()), this, SLOT(rotate90ccw())); m_rotate45ccwAct = new QAction(tr("Rotate 45\x00B0 Counter Clockwise"), this); m_rotate45ccwAct->setStatusTip(tr("Rotate current selection 45 degrees counter clockwise")); connect(m_rotate45ccwAct, SIGNAL(triggered()), this, SLOT(rotate45ccw())); m_flipHorizontalAct = new QAction(tr("&Flip Horizontal"), this); m_flipHorizontalAct->setStatusTip(tr("Flip current selection horizontally")); connect(m_flipHorizontalAct, SIGNAL(triggered()), this, SLOT(flipHorizontal())); m_flipVerticalAct = new QAction(tr("&Flip Vertical"), this); m_flipVerticalAct->setStatusTip(tr("Flip current selection vertically")); connect(m_flipVerticalAct, SIGNAL(triggered()), this, SLOT(flipVertical())); m_bringToFrontAct = new QAction(tr("Bring to Front"), this); m_bringToFrontAct->setShortcut(tr("Shift+Ctrl+]")); m_bringToFrontAct->setStatusTip(tr("Bring selected object(s) to front of their layer")); connect(m_bringToFrontAct, SIGNAL(triggered()), this, SLOT(bringToFront())); m_bringToFrontWireAct = new WireAction(m_bringToFrontAct); connect(m_bringToFrontWireAct, SIGNAL(triggered()), this, SLOT(bringToFront())); m_bringForwardAct = new QAction(tr("Bring Forward"), this); m_bringForwardAct->setShortcut(tr("Ctrl+]")); m_bringForwardAct->setStatusTip(tr("Bring selected object(s) forward in their layer")); connect(m_bringForwardAct, SIGNAL(triggered()), this, SLOT(bringForward())); m_bringForwardWireAct = new WireAction(m_bringForwardAct); connect(m_bringForwardWireAct, SIGNAL(triggered()), this, SLOT(bringForward())); m_sendBackwardAct = new QAction(tr("Send Backward"), this); m_sendBackwardAct->setShortcut(tr("Ctrl+[")); m_sendBackwardAct->setStatusTip(tr("Send selected object(s) back in their layer")); connect(m_sendBackwardAct, SIGNAL(triggered()), this, SLOT(sendBackward())); m_sendBackwardWireAct = new WireAction(m_sendBackwardAct); connect(m_sendBackwardWireAct, SIGNAL(triggered()), this, SLOT(sendBackward())); m_sendToBackAct = new QAction(tr("Send to Back"), this); m_sendToBackAct->setShortcut(tr("Shift+Ctrl+[")); m_sendToBackAct->setStatusTip(tr("Send selected object(s) to the back of their layer")); connect(m_sendToBackAct, SIGNAL(triggered()), this, SLOT(sendToBack())); m_sendToBackWireAct = new WireAction(m_sendToBackAct); connect(m_sendToBackWireAct, SIGNAL(triggered()), this, SLOT(sendToBack())); m_alignLeftAct = new QAction(tr("Align Left"), this); m_alignLeftAct->setStatusTip(tr("Align selected items at the left")); connect(m_alignLeftAct, SIGNAL(triggered()), this, SLOT(alignLeft())); m_alignHorizontalCenterAct = new QAction(tr("Align Horizontal Center"), this); m_alignHorizontalCenterAct->setStatusTip(tr("Align selected items at the horizontal center")); connect(m_alignHorizontalCenterAct, SIGNAL(triggered()), this, SLOT(alignHorizontalCenter())); m_alignRightAct = new QAction(tr("Align Right"), this); m_alignRightAct->setStatusTip(tr("Align selected items at the right")); connect(m_alignRightAct, SIGNAL(triggered()), this, SLOT(alignRight())); m_alignTopAct = new QAction(tr("Align Top"), this); m_alignTopAct->setStatusTip(tr("Align selected items at the top")); connect(m_alignTopAct, SIGNAL(triggered()), this, SLOT(alignTop())); m_alignVerticalCenterAct = new QAction(tr("Align Vertical Center"), this); m_alignVerticalCenterAct->setStatusTip(tr("Align selected items at the vertical center")); connect(m_alignVerticalCenterAct, SIGNAL(triggered()), this, SLOT(alignVerticalCenter())); m_alignBottomAct = new QAction(tr("Align Bottom"), this); m_alignBottomAct->setStatusTip(tr("Align selected items at the bottom")); connect(m_alignBottomAct, SIGNAL(triggered()), this, SLOT(alignBottom())); m_moveLockAct = new QAction(tr("Lock Part"), this); m_moveLockAct->setStatusTip(tr("Prevent a part from being moved")); m_moveLockAct->setCheckable(true); connect(m_moveLockAct, SIGNAL(triggered()), this, SLOT(moveLock())); m_stickyAct = new QAction(tr("Sticky"), this); m_stickyAct->setStatusTip(tr("If a \"sticky\" part is moved, parts on top of it are also moved")); m_stickyAct->setCheckable(true); connect(m_stickyAct, SIGNAL(triggered()), this, SLOT(setSticky())); m_selectMoveLockAct = new QAction(tr("Select All Locked Parts"), this); m_selectMoveLockAct->setStatusTip(tr("Select all parts that can't be moved")); connect(m_selectMoveLockAct, SIGNAL(triggered()), this, SLOT(selectMoveLock())); m_showPartLabelAct = new QAction(tr("&Show part label"), this); m_showPartLabelAct->setStatusTip(tr("Show/hide the label for the selected parts")); connect(m_showPartLabelAct, SIGNAL(triggered()), this, SLOT(showPartLabels())); m_saveBundledPart = new QAction(tr("&Export..."), this); m_saveBundledPart->setStatusTip(tr("Export selected part")); connect(m_saveBundledPart, SIGNAL(triggered()), this, SLOT(saveBundledPart())); m_addBendpointAct = new BendpointAction(tr("Add Bendpoint"), this); m_addBendpointAct->setStatusTip(tr("Add a bendpoint to the selected wire")); connect(m_addBendpointAct, SIGNAL(triggered()), this, SLOT(addBendpoint())); m_convertToViaAct = new BendpointAction(tr("Convert Bendpoint to Via"), this); m_convertToViaAct->setStatusTip(tr("Convert the bendpoint to a via")); connect(m_convertToViaAct, SIGNAL(triggered()), this, SLOT(convertToVia())); m_convertToBendpointAct = new QAction(tr("Convert Via to Bendpoint"), this); m_convertToBendpointAct->setStatusTip(tr("Convert the via to a bendpoint")); connect(m_convertToBendpointAct, SIGNAL(triggered()), this, SLOT(convertToBendpoint())); m_flattenCurveAct = new BendpointAction(tr("Straighten Curve"), this); m_flattenCurveAct->setStatusTip(tr("Straighten the curve of the selected wire")); connect(m_flattenCurveAct, SIGNAL(triggered()), this, SLOT(flattenCurve())); m_selectAllObsoleteAct = new QAction(tr("Select outdated parts"), this); m_selectAllObsoleteAct->setStatusTip(tr("Select outdated parts")); connect(m_selectAllObsoleteAct, SIGNAL(triggered()), this, SLOT(selectAllObsolete())); m_swapObsoleteAct = new QAction(tr("Update selected parts"), this); m_swapObsoleteAct->setStatusTip(tr("Update selected parts")); connect(m_swapObsoleteAct, SIGNAL(triggered()), this, SLOT(swapObsolete())); m_findPartInSketchAct = new QAction(tr("Find part in sketch..."), this); m_findPartInSketchAct->setStatusTip(tr("Search for parts in a sketch by matching text")); connect(m_findPartInSketchAct, SIGNAL(triggered()), this, SLOT(findPartInSketch())); m_openProgramWindowAct = new QAction(tr("Open programming window"), this); m_openProgramWindowAct->setStatusTip(tr("Open microcontroller programming window")); connect(m_openProgramWindowAct, SIGNAL(triggered()), this, SLOT(openProgramWindow())); m_hidePartSilkscreenAct = new QAction(tr("Hide part silkscreen"), this); m_hidePartSilkscreenAct->setStatusTip(tr("Hide/show the silkscreen layer for only this part")); connect(m_hidePartSilkscreenAct, SIGNAL(triggered()), this, SLOT(hidePartSilkscreen())); } void MainWindow::createViewMenuActions(bool showWelcome) { m_zoomInAct = new QAction(tr("&Zoom In"), this); m_zoomInAct->setShortcut(tr("Ctrl++")); m_zoomInAct->setStatusTip(tr("Zoom in")); connect(m_zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn())); // instead of creating a filter to grab the shortcut, let's create a new action // and append it to the window m_zoomInShortcut = new QAction(this); m_zoomInShortcut->setShortcut(tr("Ctrl+=")); connect(m_zoomInShortcut, SIGNAL(triggered()), this, SLOT(zoomIn())); this->addAction(m_zoomInShortcut); m_zoomOutAct = new QAction(tr("&Zoom Out"), this); m_zoomOutAct->setShortcut(tr("Ctrl+-")); m_zoomOutAct->setStatusTip(tr("Zoom out")); connect(m_zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut())); m_fitInWindowAct = new QAction(tr("&Fit in Window"), this); m_fitInWindowAct->setShortcut(tr("Ctrl+0")); m_fitInWindowAct->setStatusTip(tr("Fit in window")); connect(m_fitInWindowAct, SIGNAL(triggered()), this, SLOT(fitInWindow())); m_actualSizeAct = new QAction(tr("&Actual Size"), this); m_actualSizeAct->setStatusTip(tr("Actual (real world physical) size")); connect(m_actualSizeAct, SIGNAL(triggered()), this, SLOT(actualSize())); m_100PercentSizeAct = new QAction(tr("100% Size"), this); m_100PercentSizeAct->setShortcut(tr("Shift+Ctrl+0")); m_100PercentSizeAct->setStatusTip(tr("100% (pixel) size")); connect(m_100PercentSizeAct, SIGNAL(triggered()), this, SLOT(hundredPercentSize())); m_alignToGridAct = new QAction(tr("Align to Grid"), this); m_alignToGridAct->setStatusTip(tr("Align items to grid when dragging")); m_alignToGridAct->setCheckable(true); connect(m_alignToGridAct, SIGNAL(triggered()), this, SLOT(alignToGrid())); m_showGridAct = new QAction(tr("Show Grid"), this); m_showGridAct->setStatusTip(tr("Show the grid")); m_showGridAct->setCheckable(true); connect(m_showGridAct, SIGNAL(triggered()), this, SLOT(showGrid())); m_setGridSizeAct = new QAction(tr("Set Grid Size..."), this); m_setGridSizeAct->setStatusTip(tr("Set the size of the grid in this view")); connect(m_setGridSizeAct, SIGNAL(triggered()), this, SLOT(setGridSize())); m_setBackgroundColorAct = new QAction(tr("Set Background Color..."), this); m_setBackgroundColorAct->setStatusTip(tr("Set the background color of this view")); connect(m_setBackgroundColorAct, SIGNAL(triggered()), this, SLOT(setBackgroundColor())); QStringList controls; controls << tr("Ctrl+1") << tr("Ctrl+2") << tr("Ctrl+3") << tr("Ctrl+4") << tr("Ctrl+5"); int controlIndex = 0; if (showWelcome) { m_showWelcomeAct = new QAction(tr("&Show Welcome"), this); m_showWelcomeAct->setShortcut(controls.at(controlIndex++)); m_showWelcomeAct->setStatusTip(tr("Show the welcome view")); m_showWelcomeAct->setCheckable(true); connect(m_showWelcomeAct, SIGNAL(triggered()), this, SLOT(showWelcomeView())); } m_showBreadboardAct = new QAction(tr("&Show Breadboard"), this); m_showBreadboardAct->setShortcut(controls.at(controlIndex++)); m_showBreadboardAct->setStatusTip(tr("Show the breadboard view")); m_showBreadboardAct->setCheckable(true); connect(m_showBreadboardAct, SIGNAL(triggered()), this, SLOT(showBreadboardView())); m_showSchematicAct = new QAction(tr("&Show Schematic"), this); m_showSchematicAct->setShortcut(controls.at(controlIndex++)); m_showSchematicAct->setStatusTip(tr("Show the schematic view")); m_showSchematicAct->setCheckable(true); connect(m_showSchematicAct, SIGNAL(triggered()), this, SLOT(showSchematicView())); m_showPCBAct = new QAction(tr("&Show PCB"), this); m_showPCBAct->setShortcut(controls.at(controlIndex++)); m_showPCBAct->setStatusTip(tr("Show the PCB view")); m_showPCBAct->setCheckable(true); connect(m_showPCBAct, SIGNAL(triggered()), this, SLOT(showPCBView())); if (m_programView) { m_showProgramAct = new QAction(tr("Show Code"), this); m_showProgramAct->setShortcut(controls.at(controlIndex++)); m_showProgramAct->setStatusTip(tr("Show the code (programming) view")); m_showProgramAct->setCheckable(true); connect(m_showProgramAct, SIGNAL(triggered()), this, SLOT(showProgramView())); QList viewMenuActions; if (m_welcomeView) viewMenuActions << m_showWelcomeAct; viewMenuActions << m_showBreadboardAct << m_showSchematicAct << m_showPCBAct << m_showProgramAct; m_programView->createViewMenuActions(viewMenuActions); } m_showPartsBinIconViewAct = new QAction(tr("Show Parts Bin Icon View"), this); m_showPartsBinIconViewAct->setStatusTip(tr("Display the parts bin in an icon view")); m_showPartsBinIconViewAct->setCheckable(true); connect(m_showPartsBinIconViewAct, SIGNAL(triggered()), this, SLOT(showPartsBinIconView())); m_showPartsBinListViewAct = new QAction(tr("Show Parts Bin List View"), this); m_showPartsBinListViewAct->setStatusTip(tr("Display the parts bin in a list view")); m_showPartsBinListViewAct->setCheckable(true); connect(m_showPartsBinListViewAct, SIGNAL(triggered()), this, SLOT(showPartsBinListView())); m_showAllLayersAct = new QAction(tr("&Show All Layers"), this); m_showAllLayersAct->setStatusTip(tr("Show all the available layers for the current view")); connect(m_showAllLayersAct, SIGNAL(triggered()), this, SLOT(showAllLayers())); m_hideAllLayersAct = new QAction(tr("&Hide All Layers"), this); m_hideAllLayersAct->setStatusTip(tr("Hide all the layers of the current view")); connect(m_hideAllLayersAct, SIGNAL(triggered()), this, SLOT(hideAllLayers())); } void MainWindow::createWindowMenuActions() { m_minimizeAct = new QAction(tr("&Minimize"), this); m_minimizeAct->setShortcut(tr("Ctrl+M")); m_minimizeAct->setStatusTip(tr("Minimize current window")); connect(m_minimizeAct, SIGNAL(triggered(bool)), this, SLOT(minimize())); /* m_toggleToolbarAct = new QAction(tr("&Toolbar"), this); m_toggleToolbarAct->setShortcut(tr("Shift+Ctrl+T")); m_toggleToolbarAct->setCheckable(true); m_toggleToolbarAct->setChecked(true); m_toggleToolbarAct->setStatusTip(tr("Toggle Toolbar visibility")); connect(m_toggleToolbarAct, SIGNAL(triggered(bool)), this, SLOT(toggleToolbar(bool))); */ m_toggleDebuggerOutputAct = new QAction(tr("Debugger Output"), this); m_toggleDebuggerOutputAct->setCheckable(true); connect(m_toggleDebuggerOutputAct, SIGNAL(triggered(bool)), this, SLOT(toggleDebuggerOutput(bool))); } void MainWindow::createHelpMenuActions() { m_openHelpAct = new QAction(tr("Online Tutorials"), this); m_openHelpAct->setShortcut(tr("Ctrl+?")); m_openHelpAct->setStatusTip(tr("Open Fritzing help")); connect(m_openHelpAct, SIGNAL(triggered(bool)), this, SLOT(openHelp())); m_openDonateAct = new QAction(tr("Donate to Fritzing"), this); m_openDonateAct->setStatusTip(tr("Open Fritzing donation web page")); connect(m_openDonateAct, SIGNAL(triggered(bool)), this, SLOT(openDonate())); m_examplesAct = new QAction(tr("Online Projects Gallery"), this); m_examplesAct->setStatusTip(tr("Open Fritzing examples")); connect(m_examplesAct, SIGNAL(triggered(bool)), this, SLOT(openExamples())); m_partsRefAct = new QAction(tr("Online Parts Reference"), this); m_partsRefAct->setStatusTip(tr("Open Parts Reference")); connect(m_partsRefAct, SIGNAL(triggered(bool)), this, SLOT(openPartsReference())); /*m_visitFritzingDotOrgAct = new QAction(tr("Visit fritzing.org"), this); m_visitFritzingDotOrgAct->setStatusTip(tr("www.fritzing.org")); connect(m_visitFritzingDotOrgAct, SIGNAL(triggered(bool)), this, SLOT(visitFritzingDotOrg()));*/ m_checkForUpdatesAct = new QAction(tr("Check for updates..."), this); m_checkForUpdatesAct->setStatusTip(tr("Check whether a newer version of Fritzing is available for download")); connect(m_checkForUpdatesAct, SIGNAL(triggered()), QApplication::instance(), SLOT(checkForUpdates())); m_aboutAct = new QAction(tr("&About"), this); m_aboutAct->setStatusTip(tr("Show the application's about box")); connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about())); m_aboutAct->setMenuRole(QAction::AboutRole); m_tipsAndTricksAct = new QAction(tr("Tips, Tricks and Shortcuts"), this); m_tipsAndTricksAct->setStatusTip(tr("Display some handy Fritzing tips and tricks")); connect(m_tipsAndTricksAct, SIGNAL(triggered()), this, SLOT(tipsAndTricks())); m_firstTimeHelpAct = new QAction(tr("First Time Help"), this); m_firstTimeHelpAct->setStatusTip(tr("Display First Time Help")); connect(m_firstTimeHelpAct, SIGNAL(triggered()), this, SLOT(firstTimeHelp())); m_aboutQtAct = new QAction(tr("&About Qt"), this); m_aboutQtAct->setStatusTip(tr("Show Qt's about box")); connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); m_reportBugAct = new QAction(tr("Report a bug..."), this); m_reportBugAct->setStatusTip(tr("Report a but you've found in Fritzing")); connect(m_reportBugAct, SIGNAL(triggered()), this, SLOT(reportBug())); m_enableDebugAct = new QAction(tr("Enable debugging log"), this); m_enableDebugAct->setStatusTip(tr("Report a but you've found in Fritzing")); m_enableDebugAct->setCheckable(true); m_enableDebugAct->setChecked(DebugDialog::enabled()); connect(m_enableDebugAct, SIGNAL(triggered()), this, SLOT(enableDebug())); m_importFilesFromPrevInstallAct = new QAction(tr("&Import parts and bins from old version..."), this); m_importFilesFromPrevInstallAct->setStatusTip(tr("Import parts and bins from previous installation")); connect(m_importFilesFromPrevInstallAct, SIGNAL(triggered()), this, SLOT(importFilesFromPrevInstall())); m_partsEditorHelpAct = new QAction(tr("Parts Editor Help"), this); m_partsEditorHelpAct->setStatusTip(tr("Display Parts Editor help in a browser")); connect(m_partsEditorHelpAct, SIGNAL(triggered(bool)), this, SLOT(partsEditorHelp())); } void MainWindow::createMenus() { createFileMenu(); createEditMenu(); createPartMenu(); createViewMenu(); m_programView->initMenus(menuBar()); createWindowMenu(); createTraceMenus(); createHelpMenu(); } void MainWindow::createRotateSubmenu(QMenu * parentMenu) { QMenu *rotateMenu = parentMenu->addMenu(tr("Rotate")); rotateMenu->addAction(m_rotate45cwAct); rotateMenu->addAction(m_rotate90cwAct); rotateMenu->addAction(m_rotate180Act); rotateMenu->addAction(m_rotate90ccwAct); rotateMenu->addAction(m_rotate45ccwAct); } void MainWindow::createZOrderSubmenu(QMenu * parentMenu) { QMenu *zOrderMenu = parentMenu->addMenu(tr("Raise and Lower")); zOrderMenu->addAction(m_bringToFrontAct); zOrderMenu->addAction(m_bringForwardAct); zOrderMenu->addAction(m_sendBackwardAct); zOrderMenu->addAction(m_sendToBackAct); } void MainWindow::createZOrderWireSubmenu(QMenu * parentMenu) { QMenu *zOrderWireMenu = parentMenu->addMenu(tr("Raise and Lower")); zOrderWireMenu->addAction(m_bringToFrontWireAct); zOrderWireMenu->addAction(m_bringForwardWireAct); zOrderWireMenu->addAction(m_sendBackwardWireAct); zOrderWireMenu->addAction(m_sendToBackWireAct); } void MainWindow::createAlignSubmenu(QMenu * parentMenu) { QMenu *alignMenu = parentMenu->addMenu(tr("Align")); alignMenu->addAction(m_alignLeftAct); alignMenu->addAction(m_alignHorizontalCenterAct); alignMenu->addAction(m_alignRightAct); alignMenu->addAction(m_alignTopAct); alignMenu->addAction(m_alignVerticalCenterAct); alignMenu->addAction(m_alignBottomAct); } void MainWindow::createAddToBinSubmenu(QMenu * parentMenu) { QMenu *addToBinMenu = parentMenu->addMenu(tr("&Add to bin...")); addToBinMenu->setStatusTip(tr("Add selected part to bin")); QList acts = m_binManager->openedBinsActions(selectedModuleID()); addToBinMenu->addActions(acts); } void MainWindow::createFileMenu() { m_fileMenu = menuBar()->addMenu(tr("&File")); m_fileMenu->addAction(m_newAct); m_fileMenu->addAction(m_openAct); m_fileMenu->addAction(m_revertAct); m_fileMenu->addMenu(m_openRecentFileMenu); m_fileMenu->addMenu(m_openExampleMenu); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_closeAct); m_fileMenu->addAction(m_saveAct); m_fileMenu->addAction(m_saveAsAct); m_fileMenu->addAction(m_shareOnlineAct); if (m_orderFabEnabled) { m_fileMenu->addAction(m_orderFabAct); } m_fileMenu->addSeparator(); m_exportMenu = m_fileMenu->addMenu(tr("&Export")); connect(m_exportMenu, SIGNAL(aboutToShow()), this, SLOT(updateExportMenu())); //m_fileMenu->addAction(m_pageSetupAct); m_fileMenu->addAction(m_printAct); QString name; QString path; QStringList args; if (externalProcess(name, path, args)) { m_fileMenu->addSeparator(); m_fileMenu->addAction(m_launchExternalProcessAct); } #ifndef QT_NO_DEBUG m_fileMenu->addSeparator(); m_fileMenu->addAction(m_exceptionAct); #endif m_fileMenu->addSeparator(); m_fileMenu->addAction(m_quitAct); connect(m_fileMenu, SIGNAL(aboutToShow()), this, SLOT(updateFileMenu())); populateExportMenu(); m_exportMenu->addAction(m_exportBomAct); m_exportMenu->addAction(m_exportNetlistAct); m_exportMenu->addAction(m_exportSpiceNetlistAct); //m_exportMenu->addAction(m_exportEagleAct); } void MainWindow::populateExportMenu() { QMenu * imageMenu = m_exportMenu->addMenu(tr("as Image")); imageMenu->addAction(m_exportPngAct); imageMenu->addAction(m_exportJpgAct); imageMenu->addSeparator(); imageMenu->addAction(m_exportSvgAct); imageMenu->addAction(m_exportPdfAct); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) imageMenu->addAction(m_exportPsAct); #endif QMenu * productionMenu = m_exportMenu->addMenu(tr("for Production")); productionMenu->addAction(m_exportEtchablePdfAct); productionMenu->addAction(m_exportEtchableSvgAct); productionMenu->addSeparator(); productionMenu->addAction(m_exportGerberAct); } void MainWindow::createEditMenu() { m_editMenu = menuBar()->addMenu(tr("&Edit")); m_editMenu->addAction(m_undoAct); m_editMenu->addAction(m_redoAct); m_editMenu->addSeparator(); m_editMenu->addAction(m_cutAct); m_editMenu->addAction(m_copyAct); m_editMenu->addAction(m_pasteAct); m_editMenu->addAction(m_pasteInPlaceAct); m_editMenu->addAction(m_duplicateAct); m_editMenu->addAction(m_deleteAct); m_editMenu->addAction(m_deleteMinusAct); m_editMenu->addSeparator(); m_editMenu->addAction(m_selectAllAct); m_editMenu->addAction(m_deselectAct); m_editMenu->addSeparator(); m_editMenu->addAction(m_addNoteAct); m_editMenu->addSeparator(); m_editMenu->addAction(m_preferencesAct); updateEditMenu(); connect(m_editMenu, SIGNAL(aboutToShow()), this, SLOT(updateEditMenu())); } void MainWindow::createPartMenu() { m_partMenu = menuBar()->addMenu(tr("&Part")); connect(m_partMenu, SIGNAL(aboutToShow()), this, SLOT(updatePartMenu())); m_partMenu->addAction(m_openInPartsEditorNewAct); m_partMenu->addSeparator(); m_partMenu->addAction(m_saveBundledPart); m_partMenu->addSeparator(); m_partMenu->addAction(m_flipHorizontalAct); m_partMenu->addAction(m_flipVerticalAct); createRotateSubmenu(m_partMenu); createZOrderSubmenu(m_partMenu); createZOrderWireSubmenu(m_partMenu); createAlignSubmenu(m_partMenu); m_partMenu->addAction(m_moveLockAct); m_partMenu->addAction(m_stickyAct); m_partMenu->addAction(m_selectMoveLockAct); m_partMenu->addSeparator(); createAddToBinSubmenu(m_partMenu); m_partMenu->addAction(m_showPartLabelAct); m_partMenu->addSeparator(); m_partMenu->addAction(m_selectAllObsoleteAct); m_partMenu->addAction(m_swapObsoleteAct); m_partMenu->addSeparator(); m_partMenu->addAction(m_findPartInSketchAct); #ifndef QT_NO_DEBUG m_partMenu->addAction(m_dumpAllPartsAction); #endif } void MainWindow::createViewMenu() { m_viewMenu = menuBar()->addMenu(tr("&View")); m_viewMenu->addAction(m_zoomInAct); m_viewMenu->addAction(m_zoomOutAct); m_viewMenu->addAction(m_fitInWindowAct); m_viewMenu->addAction(m_actualSizeAct); m_viewMenu->addAction(m_100PercentSizeAct); m_viewMenu->addSeparator(); m_viewMenu->addAction(m_alignToGridAct); m_viewMenu->addAction(m_showGridAct); m_viewMenu->addAction(m_setGridSizeAct); m_viewMenu->addAction(m_setBackgroundColorAct); m_viewMenu->addSeparator(); if (m_welcomeView) m_viewMenu->addAction(m_showWelcomeAct); m_viewMenu->addAction(m_showBreadboardAct); m_viewMenu->addAction(m_showSchematicAct); m_viewMenu->addAction(m_showPCBAct); if (m_programView) m_viewMenu->addAction(m_showProgramAct); m_viewMenu->addSeparator(); if (m_binManager) { m_viewMenu->addAction(m_showPartsBinIconViewAct); m_viewMenu->addAction(m_showPartsBinListViewAct); m_viewMenu->addSeparator(); } connect(m_viewMenu, SIGNAL(aboutToShow()), this, SLOT(updateLayerMenu())); m_numFixedActionsInViewMenu = m_viewMenu->actions().size(); } void MainWindow::createWindowMenu() { m_windowMenu = menuBar()->addMenu(tr("&Window")); m_windowMenu->addAction(m_minimizeAct); m_windowMenu->addSeparator(); //m_windowMenu->addAction(m_toggleToolbarAct); updateWindowMenu(); connect(m_windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu())); } void MainWindow::createTraceMenus() { m_pcbTraceMenu = menuBar()->addMenu(tr("&Routing")); m_pcbTraceMenu->addAction(m_newAutorouteAct); m_pcbTraceMenu->addAction(m_newDesignRulesCheckAct); m_pcbTraceMenu->addAction(m_autorouterSettingsAct); m_pcbTraceMenu->addAction(m_fabQuoteAct); QMenu * groundFillMenu = m_pcbTraceMenu->addMenu(tr("Ground Fill")); groundFillMenu->addAction(m_copperFillAct); groundFillMenu->addAction(m_groundFillAct); groundFillMenu->addAction(m_removeGroundFillAct); groundFillMenu->addAction(m_setGroundFillSeedsAct); groundFillMenu->addAction(m_clearGroundFillSeedsAct); groundFillMenu->addAction(m_setGroundFillKeepoutAct); //m_pcbTraceMenu->addAction(m_updateRoutingStatusAct); m_pcbTraceMenu->addSeparator(); m_pcbTraceMenu->addAction(m_viewFromBelowToggleAct); m_pcbTraceMenu->addAction(m_activeLayerBothAct); m_pcbTraceMenu->addAction(m_activeLayerBottomAct); m_pcbTraceMenu->addAction(m_activeLayerTopAct); m_pcbTraceMenu->addSeparator(); m_pcbTraceMenu->addAction(m_changeTraceLayerAct); m_pcbTraceMenu->addAction(m_excludeFromAutorouteAct); m_pcbTraceMenu->addSeparator(); m_pcbTraceMenu->addAction(m_showUnroutedAct); m_pcbTraceMenu->addAction(m_selectAllTracesAct); m_pcbTraceMenu->addAction(m_selectAllExcludedTracesAct); m_pcbTraceMenu->addAction(m_selectAllIncludedTracesAct); m_pcbTraceMenu->addAction(m_selectAllJumperItemsAct); m_pcbTraceMenu->addAction(m_selectAllViasAct); m_pcbTraceMenu->addAction(m_selectAllCopperFillAct); //m_pcbTraceMenu->addSeparator(); //m_pcbTraceMenu->addAction(m_checkLoadedTracesAct); m_schematicTraceMenu = menuBar()->addMenu(tr("&Routing")); m_schematicTraceMenu->addAction(m_newAutorouteAct); m_schematicTraceMenu->addAction(m_excludeFromAutorouteAct); m_schematicTraceMenu->addAction(m_showUnroutedAct); m_schematicTraceMenu->addAction(m_selectAllTracesAct); m_schematicTraceMenu->addAction(m_selectAllExcludedTracesAct); m_schematicTraceMenu->addAction(m_selectAllIncludedTracesAct); //m_schematicTraceMenu->addAction(m_updateRoutingStatusAct); #ifndef QT_NO_DEBUG m_schematicTraceMenu->addAction(m_tidyWiresAct); #endif m_breadboardTraceMenu = menuBar()->addMenu(tr("&Routing")); m_breadboardTraceMenu->addAction(m_showUnroutedAct); m_breadboardTraceMenu->addAction(m_selectAllWiresAct); updateTraceMenu(); connect(m_pcbTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu())); connect(m_schematicTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu())); connect(m_breadboardTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu())); menuBar()->addSeparator(); } void MainWindow::createHelpMenu() { m_helpMenu = menuBar()->addMenu(tr("&Help")); m_helpMenu->addAction(m_openHelpAct); m_helpMenu->addAction(m_examplesAct); m_helpMenu->addAction(m_partsRefAct); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_partsEditorHelpAct); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_checkForUpdatesAct); m_helpMenu->addAction(m_importFilesFromPrevInstallAct); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_reportBugAct); m_helpMenu->addAction(m_enableDebugAct); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_aboutAct); m_helpMenu->addAction(m_openDonateAct); m_helpMenu->addAction(m_tipsAndTricksAct); m_helpMenu->addAction(m_firstTimeHelpAct); #ifndef QT_NO_DEBUG m_helpMenu->addAction(m_aboutQtAct); #endif } void MainWindow::updateLayerMenu(bool resetLayout) { if (m_viewMenu == NULL) return; if (m_showAllLayersAct == NULL) return; QList actions; actions << m_zoomInAct << m_zoomOutAct << m_zoomInShortcut << m_fitInWindowAct << m_actualSizeAct << m_100PercentSizeAct << m_alignToGridAct << m_showGridAct << m_setGridSizeAct << m_setBackgroundColorAct; bool enabled = (m_currentGraphicsView != NULL); foreach (QAction * action, actions) action->setEnabled(enabled); actions.clear(); if (m_showPartsBinIconViewAct) { if (m_binManager) { m_showPartsBinIconViewAct->setEnabled(true); m_showPartsBinListViewAct->setEnabled(true); actions << m_showPartsBinIconViewAct << m_showPartsBinListViewAct; setActionsIcons(m_binManager->currentViewIsIconView() ? 0 : 1, actions); } else { m_showPartsBinIconViewAct->setEnabled(false); m_showPartsBinListViewAct->setEnabled(false); } } removeActionsStartingAt(m_viewMenu, m_numFixedActionsInViewMenu); if (m_showAllLayersAct) m_viewMenu->addAction(m_showAllLayersAct); if (m_hideAllLayersAct) m_viewMenu->addAction(m_hideAllLayersAct); m_hideAllLayersAct->setEnabled(false); m_showAllLayersAct->setEnabled(false); if (m_currentGraphicsView == NULL) { return; } m_alignToGridAct->setChecked(m_currentGraphicsView->alignedToGrid()); m_showGridAct->setChecked(m_currentGraphicsView->showingGrid()); LayerHash viewLayers = m_currentGraphicsView->viewLayers(); LayerList keys = viewLayers.keys(); // make sure they're in ascending order when inserting into the menu qSort(keys.begin(), keys.end()); foreach (ViewLayer::ViewLayerID key, keys) { ViewLayer * viewLayer = viewLayers.value(key); //DebugDialog::debug(QString("Layer: %1 is %2").arg(viewLayer->action()->text()).arg(viewLayer->action()->isEnabled())); if (viewLayer != NULL) { if (viewLayer->parentLayer()) continue; m_viewMenu->addAction(viewLayer->action()); disconnect(viewLayer->action(), SIGNAL(triggered()), this, SLOT(updateLayerMenu())); connect(viewLayer->action(), SIGNAL(triggered()), this, SLOT(updateLayerMenu())); } } if (keys.count() <= 0) return; ViewLayer *prev = viewLayers.value(keys[0]); if (prev == NULL) { // jrc: I think prev == NULL is actually a side effect from an earlier bug // but I haven't figured out the cause yet // at any rate, when this bug occurs, keys[0] is some big negative number that looks like an // uninitialized or scrambled layerID DebugDialog::debug(QString("updateAllLayersActions keys[0] failed %1").arg(keys[0]) ); return; } bool sameState = prev->action()->isChecked(); bool checked = prev->action()->isChecked(); //DebugDialog::debug(QString("Layer: %1 is %2").arg(prev->action()->text()).arg(prev->action()->isChecked())); for (int i = 1; i < keys.count(); i++) { ViewLayer *viewLayer = viewLayers.value(keys[i]); //DebugDialog::debug(QString("Layer: %1 is %2").arg(viewLayer->action()->text()).arg(viewLayer->action()->isChecked())); if (viewLayer != NULL) { if (prev != NULL && prev->action()->isChecked() != viewLayer->action()->isChecked() ) { // if the actions aren't all checked or unchecked I don't bother about the "checked" variable sameState = false; break; } else { sameState = true; checked = viewLayer->action()->isChecked(); } prev = viewLayer; } } //DebugDialog::debug(QString("sameState: %1").arg(sameState)); //DebugDialog::debug(QString("checked: %1").arg(checked)); if (sameState) { if(checked) { m_hideAllLayersAct->setEnabled(true); } else { m_showAllLayersAct->setEnabled(true); } } else { m_showAllLayersAct->setEnabled(true); m_hideAllLayersAct->setEnabled(true); } if (resetLayout) { m_layerPalette->resetLayout(viewLayers, keys); } m_layerPalette->updateLayerPalette(viewLayers, keys); } void MainWindow::updateWireMenu() { // assumes update wire menu is only called when right-clicking a wire // and that wire is cached by the menu in Wire::mousePressEvent Wire * wire = m_activeWire; m_activeWire = NULL; if (wire) { enableAddBendpointAct(wire); } bool enableAll = true; bool deleteOK = false; bool createTraceOK = false; bool excludeOK = false; bool enableZOK = true; bool gotRat = false; bool ctlOK = false; if (wire != NULL) { if (wire->getRatsnest()) { QList ends; Wire * jt = wire->findTraced(m_currentGraphicsView->getTraceFlag(), ends); createTraceOK = (jt == NULL) || (!jt->getTrace()); deleteOK = true; gotRat = true; enableZOK = false; } else if (wire->getTrace()) { deleteOK = true; excludeOK = true; m_excludeFromAutorouteWireAct->setChecked(!wire->getAutoroutable()); if (m_currentGraphicsView == m_pcbGraphicsView && m_currentGraphicsView->boardLayers() > 1) { if (wire->canSwitchLayers()) { if (ViewLayer::topLayers().contains(wire->viewLayerID())) { m_changeTraceLayerWireAct->setText(tr("Move to bottom layer")); } else { m_changeTraceLayerWireAct->setText(tr("Move to top layer")); } ctlOK = true; } } } else { deleteOK = true; } } QMenu* wireColorMenu = (m_currentGraphicsView == m_breadboardGraphicsView ? m_breadboardWireColorMenu : m_schematicWireColorMenu); if (wire) { wireColorMenu->setEnabled(true); QString colorString = wire->colorString(); //DebugDialog::debug("wire colorstring " + colorString); foreach (QAction * action, wireColorMenu->actions()) { QString colorName = action->data().toString(); //DebugDialog::debug("colorname " + colorName); action->setChecked(colorName.compare(colorString) == 0); } } else { wireColorMenu->setEnabled(false); } m_bringToFrontWireAct->setWire(wire); m_bringForwardWireAct->setWire(wire); m_sendBackwardWireAct->setWire(wire); m_sendToBackWireAct->setWire(wire); m_createTraceWireAct->setWire(wire); m_createWireWireAct->setWire(wire); m_deleteWireAct->setWire(wire); m_deleteWireMinusAct->setWire(wire); m_excludeFromAutorouteWireAct->setWire(wire); m_changeTraceLayerWireAct->setWire(wire); m_bringToFrontWireAct->setEnabled(enableZOK); m_bringForwardWireAct->setEnabled(enableZOK); m_sendBackwardWireAct->setEnabled(enableZOK); m_sendToBackWireAct->setEnabled(enableZOK); m_createTraceWireAct->setEnabled(enableAll && createTraceOK); m_createWireWireAct->setEnabled(enableAll && createTraceOK); m_deleteWireAct->setEnabled(enableAll && deleteOK); m_deleteWireMinusAct->setEnabled(enableAll && deleteOK && !gotRat); m_excludeFromAutorouteWireAct->setEnabled(enableAll && excludeOK); m_changeTraceLayerAct->setEnabled(ctlOK); m_changeTraceLayerWireAct->setEnabled(ctlOK); if (gotRat) { m_deleteWireAct->setText(tr("Delete Ratsnest Line")); } else { m_deleteWireAct->setText(tr("Delete Wire")); } } void MainWindow::updatePartMenu() { if (m_partMenu == NULL) return; if (m_currentGraphicsView == NULL) { foreach (QAction * action, m_partMenu->actions()) { action->setEnabled(false); } return; } ItemCount itemCount = m_currentGraphicsView->calcItemCount(); bool enable = true; bool zenable = true; if (itemCount.selCount <= 0) { zenable = enable = false; } else { if (itemCount.itemsCount == itemCount.selCount) { // if all items are selected // z-reordering is a no-op zenable = false; } } m_alignLeftAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); m_alignRightAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); m_alignTopAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); m_alignBottomAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); m_alignVerticalCenterAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); m_alignHorizontalCenterAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1); //DebugDialog::debug(QString("enable layer actions %1")upat.arg(enable)); m_bringToFrontAct->setEnabled(zenable); m_bringForwardAct->setEnabled(zenable); m_sendBackwardAct->setEnabled(zenable); m_sendToBackAct->setEnabled(zenable); m_moveLockAct->setEnabled(itemCount.selCount > 0 && itemCount.selCount > itemCount.wireCount); m_moveLockAct->setChecked(itemCount.moveLockCount > 0); m_selectMoveLockAct->setEnabled(true); m_showPartLabelAct->setEnabled((itemCount.hasLabelCount > 0) && enable); m_showPartLabelAct->setText(itemCount.visLabelCount == itemCount.hasLabelCount ? tr("Hide part label") : tr("Show part label")); m_showPartLabelAct->setData(itemCount.visLabelCount != itemCount.hasLabelCount); bool renable = (itemCount.selRotatable > 0); bool renable45 = (itemCount.sel45Rotatable > 0); //DebugDialog::debug(QString("enable rotate (2) %1").arg(enable)); m_rotate90cwAct->setEnabled(renable && enable); m_rotate180Act->setEnabled(renable && enable); m_rotate90ccwAct->setEnabled(renable && enable); m_rotate45ccwAct->setEnabled(renable && renable45 && enable); m_rotate45cwAct->setEnabled(renable && renable45 && enable); m_flipHorizontalAct->setEnabled(enable && (itemCount.selHFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView)); m_flipVerticalAct->setEnabled(enable && (itemCount.selVFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView)); updateItemMenu(); updateEditMenu(); bool ctbpVisible = false; bool ctbpEnabled = false; if (itemCount.selCount == 1) { ItemBase * itemBase = dynamic_cast(m_currentGraphicsView->scene()->selectedItems()[0]); enableAddBendpointAct(itemBase); Via * via = qobject_cast(itemBase->layerKinChief()); if (via) { ctbpVisible = true; int count = 0; QList viaConnectorItems; viaConnectorItems << via->connectorItem(); if (via->connectorItem()->getCrossLayerConnectorItem()) { viaConnectorItems << via->connectorItem()->getCrossLayerConnectorItem(); } foreach (ConnectorItem * viaConnectorItem, viaConnectorItems) { foreach (ConnectorItem * connectorItem, viaConnectorItem->connectedToItems()) { Wire * wire = qobject_cast(connectorItem->attachedTo()); if (wire == NULL) continue; if (wire->getRatsnest()) continue; if (wire->isTraceType(m_currentGraphicsView->getTraceFlag())) { count++; if (count > 1) { ctbpEnabled = true; break; } } } if (count > 1) break; } } m_openInPartsEditorNewAct->setEnabled(itemBase->canEditPart()); m_stickyAct->setVisible(itemBase->isBaseSticky()); m_stickyAct->setEnabled(true); m_stickyAct->setChecked(itemBase->isBaseSticky() && itemBase->isLocalSticky()); QList itemBases; itemBases.append(itemBase); itemBases.append(itemBase->layerKinChief()->layerKin()); bool hpsa = false; foreach (ItemBase * lkpi, itemBases) { if (lkpi->viewLayerID() == ViewLayer::Silkscreen1 || lkpi->viewLayerID() == ViewLayer::Silkscreen0) { hpsa = true; m_hidePartSilkscreenAct->setText(lkpi->layerHidden() ? tr("Show part silkscreen") : tr("Hide part silkscreen")); break; } } m_hidePartSilkscreenAct->setEnabled(hpsa); } else { m_hidePartSilkscreenAct->setEnabled(false); m_stickyAct->setVisible(false); m_openInPartsEditorNewAct->setEnabled(false); } m_convertToBendpointAct->setEnabled(ctbpEnabled); m_convertToBendpointAct->setVisible(ctbpVisible); m_convertToBendpointSeparator->setVisible(ctbpVisible); // TODO: only enable if there is an obsolete part in the sketch m_selectAllObsoleteAct->setEnabled(true); m_swapObsoleteAct->setEnabled(itemCount.obsoleteCount > 0); m_findPartInSketchAct->setEnabled(m_currentGraphicsView != NULL); m_openProgramWindowAct->setEnabled(true); } void MainWindow::updateTransformationActions() { // update buttons in sketch toolbar at bottom if (m_currentGraphicsView == NULL) return; if (m_rotate90cwAct == NULL) return; ItemCount itemCount = m_currentGraphicsView->calcItemCount(); bool enable = (itemCount.selRotatable > 0); bool renable = (itemCount.sel45Rotatable > 0); //DebugDialog::debug(QString("enable rotate (1) %1").arg(enable)); m_rotate90cwAct->setEnabled(enable); m_rotate180Act->setEnabled(enable); m_rotate90ccwAct->setEnabled(enable); m_rotate45ccwAct->setEnabled(enable && renable); m_rotate45cwAct->setEnabled(enable && renable); foreach(SketchToolButton* rotateButton, m_rotateButtons) { rotateButton->setEnabled(enable); } m_flipHorizontalAct->setEnabled((itemCount.selHFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView)); m_flipVerticalAct->setEnabled((itemCount.selVFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView)); enable = m_flipHorizontalAct->isEnabled() || m_flipVerticalAct->isEnabled(); foreach(SketchToolButton* flipButton, m_flipButtons) { flipButton->setEnabled(enable); } } void MainWindow::updateItemMenu() { if (m_currentGraphicsView == NULL) return; ConnectorItem * activeConnectorItem = m_activeConnectorItem; m_activeConnectorItem = NULL; QList items = m_currentGraphicsView->scene()->selectedItems(); int selCount = 0; ItemBase * itemBase = NULL; foreach(QGraphicsItem * item, items) { ItemBase * ib = ItemBase::extractTopLevelItemBase(item); if (ib == NULL) continue; selCount++; if (selCount == 1) itemBase = ib; else if (selCount > 1) break; } PaletteItem *selected = qobject_cast(itemBase); bool enabled = (selCount == 1) && (selected != NULL); m_saveBundledPart->setEnabled(enabled && !selected->modelPart()->isCore()); // can't open wire in parts editor enabled &= selected != NULL && itemBase != NULL && itemBase->canEditPart(); m_disconnectAllAct->setEnabled(enabled && m_currentGraphicsView->canDisconnectAll() && (itemBase->rightClickedConnector() != NULL)); bool gfsEnabled = false; if (activeConnectorItem) { if (activeConnectorItem->attachedToItemType() != ModelPart::CopperFill) { gfsEnabled = true; m_setOneGroundFillSeedAct->setChecked(activeConnectorItem->isGroundFillSeed()); } } m_setOneGroundFillSeedAct->setEnabled(gfsEnabled); m_setOneGroundFillSeedAct->setConnectorItem(activeConnectorItem); } void MainWindow::updateEditMenu() { if (m_currentGraphicsView == NULL) { foreach (QAction * action, m_editMenu->actions()) { action->setEnabled(action == m_preferencesAct); } return; } foreach (QAction * action, m_editMenu->actions()) { action->setEnabled(true); } QClipboard *clipboard = QApplication::clipboard(); m_pasteAct->setEnabled(false); m_pasteInPlaceAct->setEnabled(false); if (clipboard != NULL) { const QMimeData *mimeData = clipboard->mimeData(QClipboard::Clipboard); if (mimeData != NULL) { if (mimeData->hasFormat("application/x-dnditemsdata")) { m_pasteAct->setEnabled(true); m_pasteInPlaceAct->setEnabled(true); //DebugDialog::debug(QString("paste enabled: true")); } } } const QList items = m_currentGraphicsView->scene()->selectedItems(); bool copyActsEnabled = false; bool deleteActsEnabled = false; foreach (QGraphicsItem * item, items) { if (m_currentGraphicsView->canDeleteItem(item, items.count())) { deleteActsEnabled = true; } if (m_currentGraphicsView->canCopyItem(item, items.count())) { copyActsEnabled = true; } } //DebugDialog::debug(QString("enable cut/copy/duplicate/delete %1 %2 %3").arg(copyActsEnabled).arg(deleteActsEnabled).arg(m_currentWidget->viewID()) ); m_deleteAct->setEnabled(deleteActsEnabled); m_deleteMinusAct->setEnabled(deleteActsEnabled); m_deleteAct->setText(tr("Delete")); m_cutAct->setEnabled(deleteActsEnabled && copyActsEnabled); m_copyAct->setEnabled(copyActsEnabled); m_duplicateAct->setEnabled(copyActsEnabled); } void MainWindow::updateTraceMenu() { if (m_pcbTraceMenu == NULL) return; bool tEnabled = false; bool twEnabled = false; bool ctlEnabled = false; bool arEnabled = false; TraceMenuThing traceMenuThing; if (m_currentGraphicsView != NULL) { QList items = m_currentGraphicsView->scene()->items(); foreach (QGraphicsItem * item, items) { Wire * wire = dynamic_cast(item); if (wire == NULL) { if (m_currentGraphicsView == m_pcbGraphicsView) { updatePCBTraceMenu(item, traceMenuThing); } continue; } if (!wire->isEverVisible()) continue; if (wire->getRatsnest()) { //rEnabled = true; //if (wire->isSelected()) { //ctEnabled = true; //} } else if (wire->isTraceType(m_currentGraphicsView->getTraceFlag())) { arEnabled = true; tEnabled = true; twEnabled = true; if (wire->isSelected()) { traceMenuThing.exEnabled = true; if (wire->getAutoroutable()) { traceMenuThing.exChecked = false; } } if (m_currentGraphicsView == m_pcbGraphicsView && m_currentGraphicsView->boardLayers() > 1) { if (wire->canSwitchLayers()) { ctlEnabled = true; } } } } } if (!arEnabled) { if (m_currentGraphicsView != NULL) { arEnabled = m_currentGraphicsView->hasAnyNets(); } } bool anyOrNo = (traceMenuThing.boardCount >= 1 || m_currentGraphicsView != m_pcbGraphicsView); m_excludeFromAutorouteAct->setEnabled(traceMenuThing.exEnabled); m_excludeFromAutorouteAct->setChecked(traceMenuThing.exChecked); m_changeTraceLayerAct->setEnabled(ctlEnabled); m_orderFabAct->setEnabled(traceMenuThing.boardCount > 0); m_showUnroutedAct->setEnabled(true); m_selectAllTracesAct->setEnabled(tEnabled && anyOrNo); m_selectAllWiresAct->setEnabled(tEnabled && anyOrNo); m_selectAllCopperFillAct->setEnabled(traceMenuThing.gfrEnabled && traceMenuThing.boardCount >= 1); m_selectAllExcludedTracesAct->setEnabled(tEnabled && anyOrNo); m_selectAllIncludedTracesAct->setEnabled(tEnabled && anyOrNo); m_selectAllJumperItemsAct->setEnabled(traceMenuThing.jiEnabled && traceMenuThing.boardCount >= 1); m_selectAllViasAct->setEnabled(traceMenuThing.viaEnabled && traceMenuThing.boardCount >= 1); m_tidyWiresAct->setEnabled(twEnabled); QString sides; if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0) && m_pcbGraphicsView->layerIsActive(ViewLayer::Copper1)) { sides = tr("top and bottom"); } else if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0)) { sides = tr("bottom"); } else sides = tr("top"); QString groundFillString = tr("Ground Fill (%1)").arg(sides); QString copperFillString = tr("Copper Fill (%1)").arg(sides); m_groundFillAct->setEnabled(traceMenuThing.boardCount >= 1); m_groundFillAct->setText(groundFillString); m_copperFillAct->setEnabled(traceMenuThing.boardCount >= 1); m_copperFillAct->setText(copperFillString); m_removeGroundFillAct->setEnabled(traceMenuThing.gfrEnabled && traceMenuThing.boardCount >= 1); // TODO: set and clear enabler logic m_setGroundFillSeedsAct->setEnabled(traceMenuThing.gfsEnabled && traceMenuThing.boardCount >= 1); m_clearGroundFillSeedsAct->setEnabled(traceMenuThing.gfsEnabled && traceMenuThing.boardCount >= 1); m_newDesignRulesCheckAct->setEnabled(traceMenuThing.boardCount >= 1); m_checkLoadedTracesAct->setEnabled(true); m_autorouterSettingsAct->setEnabled(m_currentGraphicsView == m_pcbGraphicsView); m_updateRoutingStatusAct->setEnabled(true); m_fabQuoteAct->setEnabled(m_currentGraphicsView == m_pcbGraphicsView); } void MainWindow::updatePCBTraceMenu(QGraphicsItem * item, TraceMenuThing & traceMenuThing) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) return; if (!itemBase->isEverVisible()) return; if (!traceMenuThing.gfsEnabled) { traceMenuThing.gfsEnabled = itemBase->itemType() != ModelPart::CopperFill && itemBase->hasConnectors(); } if (Board::isBoard(itemBase)) { traceMenuThing.boardCount++; if (itemBase->isSelected()) traceMenuThing.boardSelectedCount++; } switch (itemBase->itemType()) { case ModelPart::Jumper: traceMenuThing.jiEnabled = true; if (itemBase->isSelected()) { traceMenuThing.exEnabled = true; if (qobject_cast(itemBase->layerKinChief())->getAutoroutable()) { traceMenuThing.exChecked = false; } } break; case ModelPart::Via: traceMenuThing.viaEnabled = true; if (itemBase->isSelected()) { traceMenuThing.exEnabled = true; if (qobject_cast(itemBase->layerKinChief())->getAutoroutable()) { traceMenuThing.exChecked = false; } } break; case ModelPart::CopperFill: traceMenuThing.gfrEnabled = true; default: break; } } void MainWindow::zoomIn() { m_zoomSlider->zoomIn(); } void MainWindow::zoomOut() { m_zoomSlider->zoomOut(); } void MainWindow::fitInWindow() { if (m_currentGraphicsView == NULL) return; double newZoom = m_currentGraphicsView->fitInWindow(); m_zoomSlider->setValue(newZoom); } void MainWindow::hundredPercentSize() { m_currentGraphicsView->absoluteZoom(100); m_zoomSlider->setValue(100); } void MainWindow::actualSize() { QMessageBox::information(this, tr("Actual Size"), tr("It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so " "'actual size' as currently implemented is only a guess. " "Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up." )); int dpi = this->physicalDpiX(); int l = this->logicalDpiX(); DebugDialog::debug(QString("actual size %1 %2").arg(dpi).arg(l)); // remember the parameter to the next two functions is a percent m_currentGraphicsView->absoluteZoom(dpi * 100.0 / GraphicsUtils::SVGDPI); m_zoomSlider->setValue(dpi * 100.0 / GraphicsUtils::SVGDPI); } void MainWindow::showWelcomeView() { setCurrentTabIndex(0); } void MainWindow::showBreadboardView() { int ix = (m_welcomeView == NULL) ? 0 : 1; setCurrentTabIndex(ix); } void MainWindow::showSchematicView() { int ix = (m_welcomeView == NULL) ? 1 : 2; setCurrentTabIndex(ix); } void MainWindow::showPCBView() { int ix = (m_welcomeView == NULL) ? 2 : 3; setCurrentTabIndex(ix); } void MainWindow::showProgramView() { int ix = (m_welcomeView == NULL) ? 3 : 4; setCurrentTabIndex(ix); } void MainWindow::setCurrentView(ViewLayer::ViewID viewID) { if (viewID == ViewLayer::BreadboardView) showBreadboardView(); else if (viewID == ViewLayer::SchematicView) showSchematicView(); else if (viewID == ViewLayer::PCBView) showPCBView(); } void MainWindow::showPartsBinIconView() { if (m_binManager) m_binManager->toIconView(); } void MainWindow::showPartsBinListView() { if (m_binManager) m_binManager->toListView(); } void MainWindow::openHelp() { QDesktopServices::openUrl(QString("http://fritzing.org/learning/")); } void MainWindow::openDonate() { QDesktopServices::openUrl(QString("http://fritzing.org/shop/donations/")); } void MainWindow::openExamples() { QDesktopServices::openUrl(QString("http://fritzing.org/projects/")); } void MainWindow::openPartsReference() { QDesktopServices::openUrl(QString("http://fritzing.org/parts/")); } void MainWindow::visitFritzingDotOrg() { QDesktopServices::openUrl(QString("http://www.fritzing.org")); } void MainWindow::reportBug() { QDesktopServices::openUrl(QString("https://github.com/fritzing/fritzing-app/issues")); } void MainWindow::partsEditorHelp() { QDir * dir = FolderUtils::getApplicationSubFolder("help"); QString path = dir->absoluteFilePath("parts_editor_help.html"); if (QFileInfo(path).exists()) { QDesktopServices::openUrl(QString("file:///%1").arg(path)); } } void MainWindow::enableDebug() { DebugDialog::setEnabled(m_enableDebugAct->isChecked()); if (!m_windowMenu->actions().contains(m_toggleDebuggerOutputAct)) { m_windowMenu->insertSeparator(m_windowMenuSeparator); m_windowMenu->insertAction(m_windowMenuSeparator, m_toggleDebuggerOutputAct); toggleDebuggerOutput(true); } } void MainWindow::openNewPartsEditor(PaletteItem * paletteItem) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { PEMainWindow * peMainWindow = qobject_cast(widget); if (peMainWindow == NULL) continue; if (peMainWindow->editsModuleID(paletteItem->moduleID())) { if (peMainWindow->isMinimized()) peMainWindow->showNormal(); else peMainWindow->show(); peMainWindow->raise(); return; } } PEMainWindow * peMainWindow = new PEMainWindow(m_referenceModel, NULL); peMainWindow->init(m_referenceModel, false); if (peMainWindow->setInitialItem(paletteItem)) { peMainWindow->show(); peMainWindow->raise(); connect(peMainWindow, SIGNAL(addToMyPartsSignal(ModelPart *)), this, SLOT(addToMyParts(ModelPart *))); } else { delete peMainWindow; } } void MainWindow::getPartsEditorNewAnd(ItemBase * fromItem) { PaletteItem * paletteItem = qobject_cast(fromItem); if (paletteItem == NULL) return; openNewPartsEditor(paletteItem); } void MainWindow::openInPartsEditorNew() { if (m_currentGraphicsView == NULL) return; PaletteItem *selectedPart = m_currentGraphicsView->getSelectedPart(); openNewPartsEditor(selectedPart); } void MainWindow::createNewSketch() { MainWindow* mw = newMainWindow(m_referenceModel, "", true, true, -1); mw->move(x()+CascadeFactorX,y()+CascadeFactorY); ProcessEventBlocker::processEvents(); mw->addDefaultParts(); mw->show(); mw->hideTempPartsBin(); QSettings settings; settings.remove("lastOpenSketch"); mw->clearFileProgressDialog(); } void MainWindow::minimize() { this->showMinimized(); } void MainWindow::toggleToolbar(bool toggle) { Q_UNUSED(toggle); /*if(toggle) { this->m_fileToolBar->show(); this->m_editToolBar->show(); } else { this->m_fileToolBar->hide(); this->m_editToolBar->hide(); }*/ } void MainWindow::togglePartLibrary(bool toggle) { if(toggle) { m_binManager->show(); } else { m_binManager->hide(); } } void MainWindow::toggleInfo(bool toggle) { if(toggle) { ((QDockWidget*)m_infoView->parent())->show(); } else { ((QDockWidget*)m_infoView->parent())->hide(); } } void MainWindow::toggleUndoHistory(bool toggle) { if(toggle) { ((QDockWidget*)m_undoView->parent())->show(); } else { ((QDockWidget*)m_undoView->parent())->hide(); } } void MainWindow::toggleDebuggerOutput(bool toggle) { if (toggle) { DebugDialog::showDebug(); } else { } } void MainWindow::updateWindowMenu() { m_toggleDebuggerOutputAct->setChecked(DebugDialog::visible()); foreach (QWidget * widget, QApplication::topLevelWidgets()) { MainWindow * mainWindow = qobject_cast(widget); if (mainWindow == NULL) continue; QAction *action = mainWindow->raiseWindowAction(); if (action != NULL) { action->setChecked(action == m_raiseWindowAct); m_windowMenu->addAction(action); } } } void MainWindow::pageSetup() { notYetImplemented(tr("Page Setup")); } void MainWindow::notYetImplemented(QString action) { QMessageBox::warning(this, tr("Fritzing"), tr("Sorry, \"%1\" has not been implemented yet").arg(action)); } void MainWindow::rotateIncCW() { if (m_currentGraphicsView == NULL) return; if (m_rotate45cwAct->isEnabled()) { rotate45cw(); } else if (m_rotate90cwAct->isEnabled()) { rotate90cw(); } } void MainWindow::rotateIncCWRubberBand() { if (m_currentGraphicsView == NULL) return; if (m_rotate45cwAct->isEnabled()) { m_currentGraphicsView->rotateX(45, true, NULL); } else if (m_rotate90cwAct->isEnabled()) { m_currentGraphicsView->rotateX(90, true, NULL); } } void MainWindow::rotateIncCCW() { if (m_currentGraphicsView == NULL) return; if (m_rotate45ccwAct->isEnabled()) { m_currentGraphicsView->rotateX(315, true, NULL); } else if (m_rotate90ccwAct->isEnabled()) { m_currentGraphicsView->rotateX(270, true, NULL); } } void MainWindow::rotateIncCCWRubberBand() { if (m_currentGraphicsView == NULL) return; if (m_rotate45ccwAct->isEnabled()) { m_currentGraphicsView->rotateX(315, true, NULL); } else if (m_rotate90ccwAct->isEnabled()) { m_currentGraphicsView->rotateX(270, true, NULL); } } void MainWindow::rotate90cw() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->rotateX(90, false, NULL); } void MainWindow::rotate90ccw() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->rotateX(270, false, NULL); } void MainWindow::rotate45ccw() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->rotateX(315, false, NULL); } void MainWindow::rotate45cw() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->rotateX(45, false, NULL); } void MainWindow::rotate180() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->rotateX(180, false, NULL); } void MainWindow::flipHorizontal() { m_currentGraphicsView->flipX(Qt::Horizontal, false); } void MainWindow::flipVertical() { m_currentGraphicsView->flipX(Qt::Vertical, false); } void MainWindow::sendToBack() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->sendToBack(); } void MainWindow::sendBackward() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->sendBackward(); } void MainWindow::bringForward() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->bringForward(); } void MainWindow::bringToFront() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->bringToFront(); } void MainWindow::alignLeft() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignLeft); } void MainWindow::alignVerticalCenter() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignVCenter); } void MainWindow::alignRight() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignRight); } void MainWindow::alignTop() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignTop); } void MainWindow::alignHorizontalCenter() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignHCenter); } void MainWindow::alignBottom() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignItems(Qt::AlignBottom); } void MainWindow::showAllLayers() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->setAllLayersVisible(true); updateLayerMenu(); } void MainWindow::hideAllLayers() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->setAllLayersVisible(false); updateLayerMenu(); } void MainWindow::openURL() { QAction *action = qobject_cast(sender()); if (action == NULL) return; QString href = action->data().toString(); if (href.isEmpty()) return; QDesktopServices::openUrl(href); } void MainWindow::openRecentOrExampleFile() { QAction *action = qobject_cast(sender()); if (action) { openRecentOrExampleFile(action->data().toString(), action->text()); } } void MainWindow::openRecentOrExampleFile(const QString & filename, const QString & actionText) { if (alreadyOpen(filename)) { return; } if (!QFileInfo(filename).exists()) { QMessageBox::warning(NULL, tr("Fritzing"), tr("File '%1' not found").arg(filename)); return; } MainWindow* mw = newMainWindow(m_referenceModel, filename, true, true, -1); bool readOnly = m_openExampleActions.contains(actionText); mw->setReadOnly(readOnly); mw->loadWhich(filename, !readOnly,!readOnly,!readOnly, ""); mw->clearFileProgressDialog(); closeIfEmptySketch(mw); } void MainWindow::removeActionsStartingAt(QMenu * menu, int start) { QList actions = menu->actions(); if(start == 0) { menu->clear(); } else { for(int i=start; i < actions.size(); i++) { menu->removeAction(actions.at(i)); } } } void MainWindow::hideShowProgramMenu() { if (m_currentWidget == NULL) return; bool show = m_programView == NULL || m_currentWidget->contentView() != m_programView; //if (m_fileMenu) m_fileMenu->menuAction()->setVisible(show); if (m_viewMenu) { m_viewMenu->menuAction()->setVisible(show); m_viewMenu->setEnabled(show); } if (m_partMenu) { m_partMenu->menuAction()->setVisible(show); m_partMenu->setEnabled(show); } if (m_editMenu) { m_editMenu->menuAction()->setVisible(show); m_editMenu->setEnabled(show); m_copyAct->setEnabled(show); m_cutAct->setEnabled(show); m_selectAllAct->setEnabled(show); m_undoAct->setEnabled(show); m_redoAct->setEnabled(show); } if (m_programView) m_programView->showMenus(!show); } void MainWindow::hideShowTraceMenu() { if (m_pcbTraceMenu) m_pcbTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_pcbGraphicsView); if (m_schematicTraceMenu) m_schematicTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_schematicGraphicsView); if (m_breadboardTraceMenu) m_breadboardTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_breadboardGraphicsView); } void MainWindow::createTraceMenuActions() { m_newAutorouteAct = new QAction(tr("Autoroute"), this); m_newAutorouteAct->setStatusTip(tr("Autoroute connections...")); m_newAutorouteAct->setShortcut(tr("Shift+Ctrl+A")); connect(m_newAutorouteAct, SIGNAL(triggered()), this, SLOT(newAutoroute())); createOrderFabAct(); createActiveLayerActions(); QAction * traceAct = new QAction(tr("&Create trace from ratsnest"), this); traceAct->setStatusTip(tr("Create a trace from the ratsnest line")); m_createTraceWireAct = new WireAction(traceAct); connect(m_createTraceWireAct, SIGNAL(triggered()), this, SLOT(createTrace())); traceAct = new QAction(tr("&Create wire from ratsnest"), this); traceAct->setStatusTip(tr("Create a wire from the ratsnest line")); m_createWireWireAct = new WireAction(traceAct); connect(m_createWireWireAct, SIGNAL(triggered()), this, SLOT(createTrace())); m_excludeFromAutorouteAct = new QAction(tr("Do not autoroute"), this); m_excludeFromAutorouteAct->setStatusTip(tr("When autorouting, do not rip up this trace wire, via, or jumper item")); connect(m_excludeFromAutorouteAct, SIGNAL(triggered()), this, SLOT(excludeFromAutoroute())); m_excludeFromAutorouteAct->setCheckable(true); m_excludeFromAutorouteWireAct = new WireAction(m_excludeFromAutorouteAct); connect(m_excludeFromAutorouteWireAct, SIGNAL(triggered()), this, SLOT(excludeFromAutoroute())); m_changeTraceLayerAct = new QAction(tr("Move to other side of the board"), this); m_changeTraceLayerAct->setStatusTip(tr("Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)")); connect(m_changeTraceLayerAct, SIGNAL(triggered()), this, SLOT(changeTraceLayer())); m_changeTraceLayerWireAct = new WireAction(m_changeTraceLayerAct); connect(m_changeTraceLayerWireAct, SIGNAL(triggered()), this, SLOT(changeTraceLayer())); m_showUnroutedAct = new QAction(tr("Show unrouted"), this); m_showUnroutedAct->setStatusTip(tr("Highlight all unrouted connectors")); connect(m_showUnroutedAct, SIGNAL(triggered()), this, SLOT(showUnrouted())); m_selectAllTracesAct = new QAction(tr("Select All Traces"), this); m_selectAllTracesAct->setStatusTip(tr("Select all trace wires")); connect(m_selectAllTracesAct, SIGNAL(triggered()), this, SLOT(selectAllTraces())); m_selectAllWiresAct = new QAction(tr("Select All Wires"), this); m_selectAllWiresAct->setStatusTip(tr("Select all wires")); connect(m_selectAllWiresAct, SIGNAL(triggered()), this, SLOT(selectAllTraces())); m_selectAllCopperFillAct = new QAction(tr("Select All CopperFill"), this); m_selectAllCopperFillAct->setStatusTip(tr("Select all copper fill items")); connect(m_selectAllCopperFillAct, SIGNAL(triggered()), this, SLOT(selectAllCopperFill())); m_updateRoutingStatusAct = new QAction(tr("Force Update Routing Status and Ratsnests"), this); m_updateRoutingStatusAct->setStatusTip(tr("Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)")); connect(m_updateRoutingStatusAct, SIGNAL(triggered()), this, SLOT(updateRoutingStatus())); m_selectAllExcludedTracesAct = new QAction(tr("Select All \"Don't Autoroute\" Traces"), this); m_selectAllExcludedTracesAct->setStatusTip(tr("Select all trace wires excluded from autorouting")); connect(m_selectAllExcludedTracesAct, SIGNAL(triggered()), this, SLOT(selectAllExcludedTraces())); m_selectAllIncludedTracesAct = new QAction(tr("Select All Autoroutable Traces"), this); m_selectAllIncludedTracesAct->setStatusTip(tr("Select all trace wires that can be changed during autorouting")); connect(m_selectAllIncludedTracesAct, SIGNAL(triggered()), this, SLOT(selectAllIncludedTraces())); m_selectAllJumperItemsAct = new QAction(tr("Select All Jumpers"), this); m_selectAllJumperItemsAct->setStatusTip(tr("Select all jumper item parts")); connect(m_selectAllJumperItemsAct, SIGNAL(triggered()), this, SLOT(selectAllJumperItems())); m_selectAllViasAct = new QAction(tr("Select All Vias"), this); m_selectAllViasAct->setStatusTip(tr("Select all via parts")); connect(m_selectAllViasAct, SIGNAL(triggered()), this, SLOT(selectAllVias())); m_tidyWiresAct = new QAction(tr("Tidy Wires"), this); m_tidyWiresAct->setStatusTip(tr("Tidy selected wires")); connect(m_tidyWiresAct, SIGNAL(triggered()), this, SLOT(tidyWires())); m_groundFillAct = new QAction(tr("Ground Fill"), this); m_groundFillAct->setStatusTip(tr("Fill empty regions of the copper layer--fill will include all traces connected to a GROUND")); connect(m_groundFillAct, SIGNAL(triggered()), this, SLOT(groundFill())); m_copperFillAct = new QAction(tr("Copper Fill"), this); m_copperFillAct->setStatusTip(tr("Fill empty regions of the copper layer--not including traces connected to a GROUND")); connect(m_copperFillAct, SIGNAL(triggered()), this, SLOT(copperFill())); m_removeGroundFillAct = new QAction(tr("Remove Copper Fill"), this); m_removeGroundFillAct->setStatusTip(tr("Remove the copper fill")); connect(m_removeGroundFillAct, SIGNAL(triggered()), this, SLOT(removeGroundFill())); m_setGroundFillSeedsAct = new QAction(tr("Choose Ground Fill Seed(s)..."), this); m_setGroundFillSeedsAct->setStatusTip(tr("Fill empty regions of the copper layer--fill will include all traces connected to the seeds")); connect(m_setGroundFillSeedsAct, SIGNAL(triggered()), this, SLOT(setGroundFillSeeds())); m_setOneGroundFillSeedAct = new ConnectorItemAction(tr("Set Ground Fill Seed"), this); m_setOneGroundFillSeedAct->setStatusTip(tr("Treat this connector and its connections as a 'ground' during ground fill.")); m_setOneGroundFillSeedAct->setCheckable(true); connect(m_setOneGroundFillSeedAct, SIGNAL(triggered()), this, SLOT(setOneGroundFillSeed())); m_clearGroundFillSeedsAct = new ConnectorItemAction(tr("Clear Ground Fill Seeds"), this); m_clearGroundFillSeedsAct->setStatusTip(tr("Clear ground fill seeds--enable copper fill only.")); connect(m_clearGroundFillSeedsAct, SIGNAL(triggered()), this, SLOT(clearGroundFillSeeds())); m_setGroundFillKeepoutAct = new QAction(tr("Set Ground Fill Keepout..."), this); m_setGroundFillKeepoutAct->setStatusTip(tr("Set the minimum distance between ground fill and traces or connectors")); connect(m_setGroundFillKeepoutAct, SIGNAL(triggered()), this, SLOT(setGroundFillKeepout())); m_newDesignRulesCheckAct = new QAction(tr("Design Rules Check (DRC)"), this); m_newDesignRulesCheckAct->setStatusTip(tr("Highlights any parts that are too close together for safe board production")); m_newDesignRulesCheckAct->setShortcut(tr("Shift+Ctrl+D")); connect(m_newDesignRulesCheckAct, SIGNAL(triggered()), this, SLOT(newDesignRulesCheck())); m_checkLoadedTracesAct = new QAction(tr("Check Loaded Traces"), this); m_checkLoadedTracesAct->setStatusTip(tr("Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier")); connect(m_checkLoadedTracesAct, SIGNAL(triggered()), this, SLOT(checkLoadedTraces())); m_autorouterSettingsAct = new QAction(tr("Autorouter/DRC settings..."), this); m_autorouterSettingsAct->setStatusTip(tr("Set autorouting parameters including keepout...")); connect(m_autorouterSettingsAct, SIGNAL(triggered()), this, SLOT(autorouterSettings())); m_fabQuoteAct = new QAction(tr("Fritzing Fab Quote..."), this); m_fabQuoteAct->setStatusTip(tr("How much would it could to produce a PCB from this sketch with Fritzing Fab")); connect(m_fabQuoteAct, SIGNAL(triggered()), this, SLOT(fabQuote())); } void MainWindow::createActiveLayerActions() { m_viewFromBelowToggleAct = new QAction(tr("View from below"), this); m_viewFromBelowToggleAct->setStatusTip(tr("View the PCB from the bottom layers upwards")); m_viewFromBelowToggleAct->setCheckable(true); m_viewFromBelowToggleAct->setChecked(false); connect(m_viewFromBelowToggleAct, SIGNAL(triggered()), this, SLOT(setViewFromBelowToggle())); m_viewFromBelowAct = new QAction(tr("View from below"), this); m_viewFromBelowAct->setStatusTip(tr("View the PCB from the bottom layers upwards")); m_viewFromBelowAct->setCheckable(true); connect(m_viewFromBelowAct, SIGNAL(triggered()), this, SLOT(setViewFromBelow())); m_viewFromAboveAct = new QAction(tr("View from above"), this); m_viewFromAboveAct->setStatusTip(tr("View the PCB from the top layers downwards")); m_viewFromAboveAct->setCheckable(true); connect(m_viewFromAboveAct, SIGNAL(triggered()), this, SLOT(setViewFromAbove())); m_activeLayerBothAct = new QAction(tr("Set both copper layers clickable"), this); m_activeLayerBothAct->setStatusTip(tr("Set both copper layers clickable")); m_activeLayerBothAct->setShortcut(tr("Shift+Ctrl+3")); m_activeLayerBothAct->setCheckable(true); connect(m_activeLayerBothAct, SIGNAL(triggered()), this, SLOT(activeLayerBoth())); m_activeLayerTopAct = new QAction(tr("Set copper top layer clickable"), this); m_activeLayerTopAct->setStatusTip(tr("Set copper top layer clickable")); m_activeLayerTopAct->setShortcut(tr("Shift+Ctrl+2")); m_activeLayerTopAct->setCheckable(true); connect(m_activeLayerTopAct, SIGNAL(triggered()), this, SLOT(activeLayerTop())); m_activeLayerBottomAct = new QAction(tr("Set copper bottom layer clickable"), this); m_activeLayerBottomAct->setStatusTip(tr("Set copper bottom layer clickable")); m_activeLayerBottomAct->setShortcut(tr("Shift+Ctrl+1")); m_activeLayerBottomAct->setCheckable(true); connect(m_activeLayerBottomAct, SIGNAL(triggered()), this, SLOT(activeLayerBottom())); } void MainWindow::activeLayerBoth() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->setLayerActive(ViewLayer::Copper1, true); pcbSketchWidget->setLayerActive(ViewLayer::Copper0, true); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, true); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, true); AutoCloseMessageBox::showMessage(this, tr("Copper Top and Copper Bottom layers are both active")); updateActiveLayerButtons(); } void MainWindow::activeLayerTop() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->setLayerActive(ViewLayer::Copper1, true); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, true); pcbSketchWidget->setLayerActive(ViewLayer::Copper0, false); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, false); AutoCloseMessageBox::showMessage(this, tr("Copper Top layer is active")); updateActiveLayerButtons(); } void MainWindow::activeLayerBottom() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->setLayerActive(ViewLayer::Copper1, false); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, false); pcbSketchWidget->setLayerActive(ViewLayer::Copper0, true); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, true); AutoCloseMessageBox::showMessage(this, tr("Copper Bottom layer is active")); updateActiveLayerButtons(); } void MainWindow::toggleActiveLayer() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; int index = activeLayerIndex(); switch (index) { case 0: activeLayerBottom(); return; case 1: activeLayerTop(); return; case 2: activeLayerBoth(); return; default: return; } } void MainWindow::createOrderFabAct() { if (m_orderFabAct != NULL) return; m_orderFabAct = new QAction(tr("Order a PCB..."), this); m_orderFabAct->setStatusTip(tr("Order a PCB created from your sketch--from fabulous Fritzing Fab")); connect(m_orderFabAct, SIGNAL(triggered()), this, SLOT(orderFab())); } void MainWindow::newAutoroute() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; ItemBase * board = NULL; if (pcbSketchWidget->autorouteTypePCB()) { int boardCount; board = pcbSketchWidget->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use the autorouter.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please select the board you want to autoroute. The autorouter can only handle one board at a time.")); return; } } dynamic_cast(pcbSketchWidget->parent())->routingStatusLabel()->setText(tr("Autorouting...")); bool copper0Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper0); bool copper1Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper1); AutorouteProgressDialog progress(tr("Autorouting Progress..."), true, true, true, true, pcbSketchWidget, this); progress.setModal(true); progress.show(); QRect pr = progress.frameGeometry(); QRect wr = this->frameGeometry(); progress.move(wr.right() - pr.width(), pr.top()); pcbSketchWidget->scene()->clearSelection(); pcbSketchWidget->setIgnoreSelectionChangeEvents(true); Autorouter * autorouter = NULL; autorouter = new MazeRouter(pcbSketchWidget, board, true); connect(autorouter, SIGNAL(wantTopVisible()), this, SLOT(activeLayerTop()), Qt::DirectConnection); connect(autorouter, SIGNAL(wantBottomVisible()), this, SLOT(activeLayerBottom()), Qt::DirectConnection); connect(autorouter, SIGNAL(wantBothVisible()), this, SLOT(activeLayerBoth()), Qt::DirectConnection); connect(&progress, SIGNAL(cancel()), autorouter, SLOT(cancel()), Qt::DirectConnection); connect(&progress, SIGNAL(skip()), autorouter, SLOT(cancelTrace()), Qt::DirectConnection); connect(&progress, SIGNAL(stop()), autorouter, SLOT(stopTracing()), Qt::DirectConnection); connect(&progress, SIGNAL(best()), autorouter, SLOT(useBest()), Qt::DirectConnection); connect(&progress, SIGNAL(spinChange(int)), autorouter, SLOT(setMaxCycles(int)), Qt::DirectConnection); connect(autorouter, SIGNAL(setMaximumProgress(int)), &progress, SLOT(setMaximum(int)), Qt::DirectConnection); connect(autorouter, SIGNAL(setProgressValue(int)), &progress, SLOT(setValue(int)), Qt::DirectConnection); connect(autorouter, SIGNAL(setProgressMessage(const QString &)), &progress, SLOT(setMessage(const QString &))); connect(autorouter, SIGNAL(setProgressMessage2(const QString &)), &progress, SLOT(setMessage2(const QString &))); connect(autorouter, SIGNAL(setCycleMessage(const QString &)), &progress, SLOT(setSpinLabel(const QString &))); connect(autorouter, SIGNAL(setCycleCount(int)), &progress, SLOT(setSpinValue(int))); connect(autorouter, SIGNAL(disableButtons()), &progress, SLOT(disableButtons())); ProcessEventBlocker::processEvents(); ProcessEventBlocker::block(); autorouter->start(); pcbSketchWidget->setIgnoreSelectionChangeEvents(false); delete autorouter; pcbSketchWidget->setLayerActive(ViewLayer::Copper1, copper1Active); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, copper1Active); pcbSketchWidget->setLayerActive(ViewLayer::Copper0, copper0Active); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, copper0Active); updateActiveLayerButtons(); ProcessEventBlocker::unblock(); } void MainWindow::createTrace() { m_currentGraphicsView->createTrace(retrieveWire(), true); } void MainWindow::excludeFromAutoroute() { Wire * wire = retrieveWire(); PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->excludeFromAutoroute(wire == NULL ? m_excludeFromAutorouteAct->isChecked() : m_excludeFromAutorouteWireAct->isChecked()); } void MainWindow::selectAllTraces() { m_currentGraphicsView->selectAllWires(m_currentGraphicsView->getTraceFlag()); } void MainWindow::updateRoutingStatus() { RoutingStatus routingStatus; routingStatus.zero(); m_currentGraphicsView->updateRoutingStatus(NULL, routingStatus, true); } void MainWindow::selectAllExcludedTraces() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->selectAllExcludedTraces(); } void MainWindow::selectAllIncludedTraces() { PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return; pcbSketchWidget->selectAllIncludedTraces(); } void MainWindow::selectAllJumperItems() { m_pcbGraphicsView->selectAllItemType(ModelPart::Jumper, tr("jumpers")); } void MainWindow::selectAllCopperFill() { m_pcbGraphicsView->selectAllItemType(ModelPart::CopperFill, tr("copperfill")); } void MainWindow::selectAllVias() { m_pcbGraphicsView->selectAllItemType(ModelPart::Via, tr("vias")); } void MainWindow::notClosableForAWhile() { m_dontClose = true; QTimer::singleShot(500, this, SLOT(ensureClosable())); } void MainWindow::ensureClosable() { m_dontClose = false; } void MainWindow::showPartLabels() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->showPartLabels(m_showPartLabelAct->data().toBool()); } void MainWindow::addNote() { if (m_currentGraphicsView == NULL) return; ViewGeometry vg; vg.setRect(0, 0, Note::initialMinWidth, Note::initialMinHeight); QPointF tl = m_currentGraphicsView->mapToScene(QPoint(0, 0)); QSizeF vpSize = m_currentGraphicsView->viewport()->size(); tl.setX(tl.x() + ((vpSize.width() - Note::initialMinWidth) / 2.0)); tl.setY(tl.y() + ((vpSize.height() - Note::initialMinHeight) / 2.0)); vg.setLoc(tl); QUndoCommand * parentCommand = new QUndoCommand(tr("Add Note")); m_currentGraphicsView->stackSelectionState(false, parentCommand); m_currentGraphicsView->scene()->clearSelection(); new AddItemCommand(m_currentGraphicsView, BaseCommand::SingleView, ModuleIDNames::NoteModuleIDName, m_currentGraphicsView->defaultViewLayerPlacement(NULL), vg, ItemBase::getNextID(), false, -1, parentCommand); m_undoStack->push(parentCommand); } bool MainWindow::alreadyOpen(const QString & fileName) { foreach (QWidget * widget, QApplication::topLevelWidgets()) { MainWindow * mainWindow = qobject_cast(widget); if (mainWindow == NULL) continue; // don't load two copies of the same file if (mainWindow->fileName().compare(fileName) == 0) { mainWindow->raise(); return true; } } return false; } void MainWindow::enableAddBendpointAct(QGraphicsItem * graphicsItem) { m_addBendpointAct->setEnabled(false); m_convertToViaAct->setEnabled(false); m_flattenCurveAct->setEnabled(false); Wire * wire = dynamic_cast(graphicsItem); if (wire == NULL) return; if (wire->getRatsnest()) return; m_flattenCurveAct->setEnabled(wire->isCurved()); BendpointAction * bendpointAction = qobject_cast(m_addBendpointAct); BendpointAction * convertToViaAction = qobject_cast(m_convertToViaAct); FGraphicsScene * scene = qobject_cast(graphicsItem->scene()); if (scene != NULL) { bendpointAction->setLastLocation(scene->lastContextMenuPos()); convertToViaAction->setLastLocation(scene->lastContextMenuPos()); } bool enabled = false; bool ctvEnabled = false; if (m_currentGraphicsView->lastHoverEnterConnectorItem()) { bendpointAction->setText(tr("Remove Bendpoint")); bendpointAction->setLastHoverEnterConnectorItem(m_currentGraphicsView->lastHoverEnterConnectorItem()); bendpointAction->setLastHoverEnterItem(NULL); convertToViaAction->setLastHoverEnterConnectorItem(m_currentGraphicsView->lastHoverEnterConnectorItem()); convertToViaAction->setLastHoverEnterItem(NULL); ctvEnabled = enabled = true; } else if (m_currentGraphicsView->lastHoverEnterItem()) { bendpointAction->setText(tr("Add Bendpoint")); bendpointAction->setLastHoverEnterItem(m_currentGraphicsView->lastHoverEnterItem()); bendpointAction->setLastHoverEnterConnectorItem(NULL); convertToViaAction->setLastHoverEnterItem(NULL); convertToViaAction->setLastHoverEnterConnectorItem(NULL); enabled = true; } else { bendpointAction->setLastHoverEnterItem(NULL); bendpointAction->setLastHoverEnterConnectorItem(NULL); convertToViaAction->setLastHoverEnterItem(NULL); convertToViaAction->setLastHoverEnterConnectorItem(NULL); } m_addBendpointAct->setEnabled(enabled); m_convertToViaAct->setEnabled(ctvEnabled && (m_currentGraphicsView == m_pcbGraphicsView)); } void MainWindow::addBendpoint() { BendpointAction * bendpointAction = qobject_cast(m_addBendpointAct); m_currentGraphicsView->addBendpoint(bendpointAction->lastHoverEnterItem(), bendpointAction->lastHoverEnterConnectorItem(), bendpointAction->lastLocation()); } void MainWindow::convertToVia() { BendpointAction * bendpointAction = qobject_cast(m_convertToViaAct); m_pcbGraphicsView->convertToVia(bendpointAction->lastHoverEnterConnectorItem()); } void MainWindow::convertToBendpoint() { m_pcbGraphicsView->convertToBendpoint(); } void MainWindow::flattenCurve() { BendpointAction * bendpointAction = qobject_cast(m_addBendpointAct); m_currentGraphicsView->flattenCurve(bendpointAction->lastHoverEnterItem(), bendpointAction->lastHoverEnterConnectorItem(), bendpointAction->lastLocation()); } void MainWindow::importFilesFromPrevInstall() { QString prevInstallPath = QFileDialog::getExistingDirectory( this, tr("Please choose the previous Fritzing folder..."), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if(prevInstallPath.isNull()) return; if(!QFileInfo(prevInstallPath+"/parts").exists()) { FMessageBox::critical( this, QObject::tr("Fritzing"), tr("The folder \"%1\" isn't a Fritzing installation folder").arg(prevInstallPath)); return; } QString userDataPath = FolderUtils::getUserDataStorePath(); // replicate dirs QStringList foldersToCopy = FolderUtils::getUserDataStoreFolders(); foreach(QString folder, foldersToCopy) { FolderUtils::replicateDir(QDir(prevInstallPath+folder), QDir(userDataPath+folder)); } // cleanup old bins QDir dataStoreBins(userDataPath); dataStoreBins.cd("bins"); QStringList binsToRemove; binsToRemove << "allParts.fzb" << "artreenoBin.fzb" << "E6SetBin.fzb" << "pin_headers.fzb"; foreach(QString binToRemove, binsToRemove) { dataStoreBins.remove(binToRemove); } // make sure to add the old my_parts.fzp to the folder QString myPartsBinRelPath = "/bins/my_parts.fzb"; QFile myOldPartsBinFile(prevInstallPath+myPartsBinRelPath); if(myOldPartsBinFile.exists()) { QDateTime now = QDateTime::currentDateTime(); QString newNamePostfix = QString("__imported_on__%1.fzb").arg(now.toString("yyyy-MM-dd_hh-mm-ss")); FolderUtils::slamCopy(myOldPartsBinFile, userDataPath+myPartsBinRelPath.replace(".fzb",newNamePostfix)); } FMessageBox::information( this, QObject::tr("Fritzing"), tr("You will have to restart Fritzing in order to use the imported parts")); } void MainWindow::tidyWires() { m_currentGraphicsView->tidyWires(); } void MainWindow::copperFill() { groundFillAux2(false); } void MainWindow::groundFill() { groundFillAux2(true); } void MainWindow::groundFillAux2(bool fillGroundTraces) { if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0) && m_pcbGraphicsView->layerIsActive(ViewLayer::Copper1)) { groundFillAux(fillGroundTraces, ViewLayer::UnknownLayer); } else if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0)) { groundFillAux(fillGroundTraces, ViewLayer::GroundPlane0); } else { groundFillAux(fillGroundTraces, ViewLayer::GroundPlane1); } } void MainWindow::copperFill(ViewLayer::ViewLayerID viewLayerID) { groundFillAux(false, viewLayerID); } void MainWindow::groundFill(ViewLayer::ViewLayerID viewLayerID) { groundFillAux(true, viewLayerID); } void MainWindow::groundFillAux(bool fillGroundTraces, ViewLayer::ViewLayerID viewLayerID) { // TODO: // what about leftover temp files from crashes? // clear ground plane when anything changes // some polygons can be combined // remove old ground plane modules from paletteModel and database if (m_pcbGraphicsView == NULL) return; int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please select a PCB--copper fill only works for one board at a time.")); return; } FileProgressDialog fileProgress(tr("Generating %1 fill...").arg(fillGroundTraces ? tr("ground") : tr("copper")), 0, this); fileProgress.setIndeterminate(); QUndoCommand * parentCommand = new QUndoCommand(fillGroundTraces ? tr("Ground Fill") : tr("Copper Fill")); m_pcbGraphicsView->blockUI(true); removeGroundFill(viewLayerID, parentCommand); if (m_pcbGraphicsView->groundFill(fillGroundTraces, viewLayerID, parentCommand)) { m_undoStack->push(parentCommand); } else { delete parentCommand; } m_pcbGraphicsView->blockUI(false); } void MainWindow::removeGroundFill() { removeGroundFill(ViewLayer::UnknownLayer, NULL); } void MainWindow::removeGroundFill(ViewLayer::ViewLayerID viewLayerID, QUndoCommand * parentCommand) { QSet toDelete; int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to remove copper fill.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please select a PCB--ground fill operations only work on a one board at a time.")); return; } foreach (QGraphicsItem * item, m_pcbGraphicsView->scene()->collidingItems(board)) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->moveLock()) continue; if (!isGroundFill(itemBase)) continue; if (viewLayerID != ViewLayer::UnknownLayer) { if (itemBase->viewLayerID() != viewLayerID) continue; } toDelete.insert(itemBase->layerKinChief()); } if (toDelete.count() == 0) return; bool push = (parentCommand == NULL); if (push) { parentCommand = new QUndoCommand(tr("Remove copper fill")); } new CleanUpWiresCommand(m_pcbGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(m_pcbGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand); m_pcbGraphicsView->deleteMiddle(toDelete, parentCommand); foreach (ItemBase * itemBase, toDelete) { itemBase->saveGeometry(); m_pcbGraphicsView->makeDeleteItemCommand(itemBase, BaseCommand::CrossView, parentCommand); } new CleanUpRatsnestsCommand(m_pcbGraphicsView, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(m_pcbGraphicsView, CleanUpWiresCommand::RedoOnly, parentCommand); if (push) { m_undoStack->push(parentCommand); } else { foreach (ItemBase * itemBase, toDelete) { // move them out of the way because they are about to be deleted anyhow itemBase->setPos(itemBase->pos() + board->sceneBoundingRect().bottomRight() + QPointF(10000, 10000)); } } } bool MainWindow::isGroundFill(ItemBase * itemBase) { return (itemBase->itemType() == ModelPart::CopperFill); } QMenu *MainWindow::breadboardItemMenu() { QMenu *menu = new QMenu(QObject::tr("Part"), this); createRotateSubmenu(menu); return viewItemMenuAux(menu); } QMenu *MainWindow::schematicItemMenu() { QMenu *menu = new QMenu(QObject::tr("Part"), this); createRotateSubmenu(menu); menu->addAction(m_flipHorizontalAct); menu->addAction(m_flipVerticalAct); return viewItemMenuAux(menu); } QMenu *MainWindow::pcbItemMenu() { QMenu *menu = new QMenu(QObject::tr("Part"), this); createRotateSubmenu(menu); menu = viewItemMenuAux(menu); menu->addAction(m_hidePartSilkscreenAct); menu->addSeparator(); menu->addAction(m_convertToBendpointAct); m_convertToBendpointSeparator = menu->addSeparator(); menu->addAction(m_setOneGroundFillSeedAct); menu->addAction(m_clearGroundFillSeedsAct); return menu; } QMenu *MainWindow::breadboardWireMenu() { QMenu *menu = new QMenu(QObject::tr("Wire"), this); createZOrderWireSubmenu(menu); menu->addSeparator(); m_breadboardWireColorMenu = menu->addMenu(tr("&Wire Color")); foreach(QString colorName, Wire::colorNames) { QString colorValue = Wire::colorTrans.value(colorName); QAction * action = new QAction(colorName, this); m_breadboardWireColorMenu->addAction(action); action->setData(colorValue); action->setCheckable(true); action->setChecked(false); connect(action, SIGNAL(triggered(bool)), this, SLOT(changeWireColor(bool))); } menu->addAction(m_createWireWireAct); menu->addSeparator(); menu->addAction(m_deleteWireAct); menu->addAction(m_deleteWireMinusAct); menu->addSeparator(); menu->addAction(m_addBendpointAct); menu->addAction(m_flattenCurveAct); #ifndef QT_NO_DEBUG menu->addSeparator(); menu->addAction(m_infoViewOnHoverAction); #endif connect( menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu())); return menu; } QMenu *MainWindow::pcbWireMenu() { QMenu *menu = new QMenu(QObject::tr("Wire"), this); createZOrderWireSubmenu(menu); menu->addSeparator(); menu->addAction(m_changeTraceLayerWireAct); menu->addAction(m_createTraceWireAct); menu->addAction(m_excludeFromAutorouteWireAct); menu->addSeparator(); menu->addAction(m_deleteWireAct); menu->addAction(m_deleteWireMinusAct); menu->addSeparator(); menu->addAction(m_addBendpointAct); menu->addAction(m_convertToViaAct); menu->addAction(m_flattenCurveAct); #ifndef QT_NO_DEBUG menu->addSeparator(); menu->addAction(m_infoViewOnHoverAction); #endif connect(menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu())); return menu; } QMenu *MainWindow::schematicWireMenu() { QMenu *menu = new QMenu(QObject::tr("Wire"), this); createZOrderWireSubmenu(menu); menu->addSeparator(); m_schematicWireColorMenu = menu->addMenu(tr("&Wire Color")); foreach(QString colorName, Wire::colorNames) { QString colorValue = Wire::colorTrans.value(colorName); if (colorValue == "white") continue; QAction * action = new QAction(colorName, this); m_schematicWireColorMenu->addAction(action); action->setData(colorValue); action->setCheckable(true); connect(action, SIGNAL(triggered(bool)), this, SLOT(changeWireColor(bool))); } menu->addAction(m_createTraceWireAct); menu->addAction(m_excludeFromAutorouteWireAct); menu->addSeparator(); menu->addAction(m_deleteWireAct); menu->addAction(m_deleteWireMinusAct); menu->addSeparator(); menu->addAction(m_addBendpointAct); #ifndef QT_NO_DEBUG menu->addSeparator(); menu->addAction(m_infoViewOnHoverAction); #endif connect( menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu())); return menu; } QMenu *MainWindow::viewItemMenuAux(QMenu* menu) { createZOrderWireSubmenu(menu); menu->addAction(m_moveLockAct); menu->addAction(m_stickyAct); menu->addSeparator(); menu->addAction(m_copyAct); menu->addAction(m_duplicateAct); menu->addAction(m_deleteAct); menu->addAction(m_deleteMinusAct); #ifndef QT_NO_DEBUG menu->addSeparator(); menu->addAction(m_disconnectAllAct); #endif menu->addSeparator(); menu->addAction(m_openInPartsEditorNewAct); createAddToBinSubmenu(menu); menu->addSeparator(); menu->addAction(m_showPartLabelAct); #ifndef QT_NO_DEBUG menu->addSeparator(); menu->addAction(m_infoViewOnHoverAction); menu->addAction(m_exportNormalizedSvgAction); menu->addAction(m_exportNormalizedFlattenedSvgAction); menu->addAction(m_testConnectorsAction); #endif connect( menu, SIGNAL(aboutToShow()), this, SLOT(updatePartMenu()) ); return menu; } void MainWindow::changeWireColor(bool checked) { if (checked == false) { // choosing the same color again (assuming this action can only apply to a single wire at a time) return; } QAction * action = qobject_cast(sender()); if (action == NULL) return; QString colorName = action->data().toString(); if (colorName.isEmpty()) return; m_currentGraphicsView->changeWireColor(colorName); } void MainWindow::startSaveInstancesSlot(const QString & fileName, ModelPart *, QXmlStreamWriter & streamWriter) { Q_UNUSED(fileName); if (m_backingUp) { streamWriter.writeTextElement("originalFileName", m_fwFilename); } if (m_pcbGraphicsView) { QList boards = m_pcbGraphicsView->findBoard(); if (boards.count()) { streamWriter.writeStartElement("boards"); foreach (ItemBase * board, boards) { QRectF r = board->sceneBoundingRect(); double w = 2.54 * r.width() / GraphicsUtils::SVGDPI; double h = 2.54 * r.height() / GraphicsUtils::SVGDPI; streamWriter.writeStartElement("board"); streamWriter.writeAttribute("moduleId", QString("%1").arg(board->moduleID())); streamWriter.writeAttribute("title", QString("%1").arg(board->title())); streamWriter.writeAttribute("instance", QString("%1").arg(board->instanceTitle())); streamWriter.writeAttribute("width", QString("%1cm").arg(w)); streamWriter.writeAttribute("height", QString("%1cm").arg(h)); streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } } if (m_linkedProgramFiles.count() > 0) { streamWriter.writeStartElement("programs"); QSettings settings; streamWriter.writeAttribute("pid", settings.value("pid").toString()); foreach (LinkedFile * linkedFile, m_linkedProgramFiles) { streamWriter.writeStartElement("program"); streamWriter.writeAttribute("language", linkedFile->platform); streamWriter.writeCharacters(linkedFile->linkedFilename); streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } streamWriter.writeStartElement("views"); QList views; views << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView; foreach (SketchWidget * sketchWidget, views) { streamWriter.writeStartElement("view"); streamWriter.writeAttribute("name", ViewLayer::viewIDXmlName(sketchWidget->viewID())); streamWriter.writeAttribute("backgroundColor", sketchWidget->background().name()); streamWriter.writeAttribute("gridSize", sketchWidget->gridSizeText()); streamWriter.writeAttribute("showGrid", sketchWidget->showingGrid() ? "1" : "0"); streamWriter.writeAttribute("alignToGrid", sketchWidget->alignedToGrid() ? "1" : "0"); streamWriter.writeAttribute("viewFromBelow", sketchWidget->viewFromBelow() ? "1" : "0"); QHash autorouterSettings = sketchWidget->getAutorouterSettings(); foreach (QString key, autorouterSettings.keys()) { streamWriter.writeAttribute(key, autorouterSettings.value(key)); } streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } void MainWindow::obsoleteSMDOrientationSlot() { m_obsoleteSMDOrientation = true; } void MainWindow::oldSchematicsSlot(const QString &filename, bool & useOldSchematics) { useOldSchematics = m_convertedSchematic = m_useOldSchematic = false; if (m_noSchematicConversion) return; if (m_readOnly) { useOldSchematics = m_useOldSchematic = true; return; } QMessageBox::StandardButton answer = oldSchematicMessage(filename); if (answer == QMessageBox::No) { useOldSchematics = m_useOldSchematic = true; this->setReadOnly(true); } else { m_convertedSchematic = true; } } QMessageBox::StandardButton MainWindow::oldSchematicMessage(const QString & filename) { QFileInfo info(filename); FMessageBox messageBox(NULL); messageBox.setWindowTitle(tr("Schematic view update")); messageBox.setText(tr("There is a new graphics standard for schematic-view part images, beginning with version 0.8.6.\n\n") + tr("Would you like to convert '%1' to the new standard now or open the file read-only?\n").arg(info.fileName()) ); messageBox.setInformativeText("

  • " + tr("The conversion process will not modify '%1', until you save the file. ").arg(info.fileName()) + + "
  • " + tr("You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. ") + + "
  • " + tr("Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor.") + + "
" ); messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); messageBox.setDefaultButton(QMessageBox::Yes); messageBox.setIcon(QMessageBox::Question); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Yes, tr("Convert")); messageBox.setButtonText(QMessageBox::No, tr("Read-only")); return (QMessageBox::StandardButton) messageBox.exec(); } void MainWindow::loadedRootSlot(const QString & fname, ModelBase *, QDomElement & root) { if (root.isNull()) return; QDomElement programs = root.firstChildElement("programs"); if (programs.isNull()) return; QString thatPid = programs.attribute("pid"); QSettings settings; QString thisPid = settings.value("pid").toString(); bool sameMachine = thatPid.isEmpty() || (!thisPid.isEmpty() && (thatPid.compare(thisPid) == 0)); QFileInfo fileInfo(fname); QDir dir = fileInfo.absoluteDir(); QDomElement program = programs.firstChildElement("program"); while (!program.isNull()) { bool obsolete = false; bool inBundle = false; QString text; TextUtils::findText(program, text); if (!text.isEmpty()) { QString platform = program.attribute("language"); QString path; if (thatPid.isEmpty()) { // pre 0.7.0 relative path QFileInfo newFileInfo(text); dir.cd(newFileInfo.dir().path()); path = dir.absoluteFilePath(newFileInfo.fileName()); obsolete = true; } else { path = text; } LinkedFile * linkedFile = new LinkedFile; QFileInfo info(path); if (!(sameMachine && info.exists())) { inBundle = true; path = dir.absoluteFilePath(info.fileName()); } linkedFile->linkedFilename = path; linkedFile->platform = platform; linkedFile->fileFlags = LinkedFile::NoFlag; if (sameMachine) linkedFile->fileFlags |= LinkedFile::SameMachineFlag; if (obsolete) linkedFile->fileFlags |= LinkedFile::ObsoleteFlag; if (inBundle) linkedFile->fileFlags |= LinkedFile::InBundleFlag; if (this->m_readOnly) linkedFile->fileFlags |= LinkedFile::ReadOnlyFlag; m_linkedProgramFiles.append(linkedFile); } program = program.nextSiblingElement("program"); } } void MainWindow::loadedViewsSlot(ModelBase *, QDomElement & views) { if (views.isNull()) return; QDomElement view = views.firstChildElement("view"); while (!view.isNull()) { QString name = view.attribute("name"); ViewLayer::ViewID viewID = ViewLayer::idFromXmlName(name); SketchWidget * sketchWidget = NULL; switch (viewID) { case ViewLayer::BreadboardView: sketchWidget = m_breadboardGraphicsView; break; case ViewLayer::SchematicView: sketchWidget = m_schematicGraphicsView; break; case ViewLayer::PCBView: sketchWidget = m_pcbGraphicsView; break; default: break; } if (sketchWidget) { QString colorName = view.attribute("backgroundColor", ""); QString gridSizeText = view.attribute("gridSize", ""); QString alignToGridText = view.attribute("alignToGrid", ""); QString showGridText = view.attribute("showGrid", ""); QString viewFromBelowText = view.attribute("viewFromBelow", ""); QHash autorouterSettings; QDomNamedNodeMap map = view.attributes(); for (int m = 0; m < map.count(); m++) { QDomNode node = map.item(m); autorouterSettings.insert(node.nodeName(), node.nodeValue()); } sketchWidget->setAutorouterSettings(autorouterSettings); QColor color; color.setNamedColor(colorName); bool redraw = false; if (color.isValid()) { sketchWidget->setBackground(color); redraw = true; } if (!alignToGridText.isEmpty()) { sketchWidget->alignToGrid(alignToGridText.compare("1") == 0); } if (!showGridText.isEmpty()) { sketchWidget->showGrid(showGridText.compare("1") == 0); redraw = 1; } if (!gridSizeText.isEmpty()) { sketchWidget->setGridSize(gridSizeText); redraw = true; } if (!viewFromBelowText.isEmpty()) { sketchWidget->setViewFromBelow(viewFromBelowText.compare("1") == 0); redraw = 1; } if (redraw) sketchWidget->invalidateScene(); } view = view.nextSiblingElement("view"); } } void MainWindow::disconnectAll() { m_currentGraphicsView->disconnectAll(); } bool MainWindow::externalProcess(QString & name, QString & path, QStringList & args) { emit externalProcessSignal(name, path, args); if (path.isEmpty()) return false; if (name.isEmpty()) { name = tr("Launch %1...").arg(path); } return true; } void MainWindow::launchExternalProcess() { QString name; QString path; QStringList args; if (!externalProcess(name, path, args)) return; args.append("-sketch"); args.append(fileName()); m_externalProcessOutput.clear(); QFileInfo f = QFileInfo(path); QProcess * process = new QProcess(this); process->setWorkingDirectory(f.dir().absolutePath()); process->setProcessChannelMode(QProcess::MergedChannels); process->setReadChannel(QProcess::StandardOutput); connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(processReadyRead())); connect(process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); process->start(path, args); } void MainWindow::processError(QProcess::ProcessError processError) { DebugDialog::debug(QString("process error %1").arg(processError)); } void MainWindow::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { DebugDialog::debug(QString("process finished %1 %2").arg(exitCode).arg(exitStatus)); QString name, path; QStringList args; externalProcess(name, path, args); QMessageBox::information(this, name, QString(m_externalProcessOutput)); sender()->deleteLater(); } void MainWindow::processReadyRead() { QByteArray byteArray = qobject_cast(sender())->readAllStandardOutput(); m_externalProcessOutput.append(byteArray); DebugDialog::debug(byteArray.data()); } void MainWindow::processStateChanged(QProcess::ProcessState newState) { switch(newState) { case QProcess::Running: DebugDialog::debug(QString("process running")); break; case QProcess::Starting: DebugDialog::debug(QString("process starting")); break; case QProcess::NotRunning: DebugDialog::debug(QString("process not running")); break; } } void MainWindow::shareOnline() { QDesktopServices::openUrl(QString("http://fritzing.org/projects/create/")); } void MainWindow::selectAllObsolete() { selectAllObsolete(true); } QList MainWindow::selectAllObsolete(bool displayFeedback) { QList items = m_pcbGraphicsView->selectAllObsolete(); if (!displayFeedback) return items; if (items.count() <= 0) { QMessageBox::information(this, tr("Fritzing"), tr("No outdated parts found.\nAll your parts are up-to-date.") ); } else { checkSwapObsolete(items, false); } return items; } void MainWindow::checkSwapObsolete(QList & items, bool includeUpdateLaterMessage) { QString msg = includeUpdateLaterMessage ? tr("\n\nNote: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. ") : ""; QMessageBox::StandardButton answer = FMessageBox::question( this, tr("Outdated parts"), tr("There are %n outdated part(s) in this sketch. ", "", items.count()) + tr("We strongly recommend that you update these %n parts to the latest version. ", "", items.count()) + tr("This may result in changes to your sketch, as parts or connectors may be shifted. ") + msg + tr("\n\nDo you want to update now?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ); // TODO: make button texts translatable if (answer == QMessageBox::Yes) { swapObsolete(true, items); } } ModelPart * MainWindow::findReplacedby(ModelPart * originalModelPart) { ModelPart * newModelPart = originalModelPart; while (true) { QString newModuleID = newModelPart->replacedby(); if (newModuleID.isEmpty()) { return ((newModelPart == originalModelPart) ? NULL : newModelPart); } ModelPart * tempModelPart = this->m_referenceModel->retrieveModelPart(newModuleID); if (tempModelPart == NULL) { // something's screwy return NULL; } newModelPart = tempModelPart; } } void MainWindow::swapObsolete() { QList items; swapObsolete(true, items); } void MainWindow::swapObsolete(bool displayFeedback, QList & items) { QSet itemBases; if (items.count() == 0) { foreach (QGraphicsItem * item, m_pcbGraphicsView->scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isObsolete()) continue; itemBase = itemBase->layerKinChief(); itemBases.insert(itemBase); } if (itemBases.count() <= 0) return; } else { foreach (ItemBase * itemBase, items) itemBases.insert(itemBase); } QUndoCommand* parentCommand = new QUndoCommand(); int count = 0; QMap propsMap; foreach (ItemBase * itemBase, itemBases) { ModelPart * newModelPart = findReplacedby(itemBase->modelPart()); if (newModelPart == NULL) { FMessageBox::information( this, tr("Sorry!"), tr( "unable to find replacement for %1.\n").arg(itemBase->title()) ); continue; } count++; long newID = swapSelectedAuxAux(itemBase, newModelPart->moduleID(), itemBase->viewLayerPlacement(), propsMap, parentCommand); if (itemBase->modelPart()) { // special case for swapping old resistors. QString resistance = itemBase->modelPart()->properties().value("resistance", ""); if (!resistance.isEmpty()) { QChar r = resistance.at(resistance.length() - 1); ushort ohm = r.unicode(); if (ohm == 8486) { // ends with the ohm symbol resistance.chop(1); } } QString footprint = itemBase->modelPart()->properties().value("footprint", ""); if (!resistance.isEmpty() && !footprint.isEmpty()) { new SetResistanceCommand(m_currentGraphicsView, newID, resistance, resistance, footprint, footprint, parentCommand); } // special case for swapping LEDs if (newModelPart->moduleID().contains(ModuleIDNames::ColorLEDModuleIDName)) { QString oldColor = itemBase->modelPart()->properties().value("color"); QString newColor; if (oldColor.contains("red", Qt::CaseInsensitive)) { newColor = "Red (633nm)"; } else if (oldColor.contains("blue", Qt::CaseInsensitive)) { newColor = "Blue (430nm)"; } else if (oldColor.contains("yellow", Qt::CaseInsensitive)) { newColor = "Yellow (585nm)"; } else if (oldColor.contains("green", Qt::CaseInsensitive)) { newColor = "Green (555nm)"; } else if (oldColor.contains("white", Qt::CaseInsensitive)) { newColor = "White (4500K)"; } if (newColor.length() > 0) { new SetPropCommand(m_currentGraphicsView, newID, "color", newColor, newColor, true, parentCommand); } } } } if (count == 0) { delete parentCommand; } else { parentCommand->setText(tr("Update %1 part(s)", "").arg(count)); m_undoStack->push(parentCommand); } if (displayFeedback) { QMessageBox::information(this, tr("Fritzing"), tr("Successfully updated %1 part(s).\n" "Please check all views for potential side-effects.").arg(count) ); } DebugDialog::debug(QString("updated %1 obsolete in %2").arg(count).arg(m_fwFilename)); } void MainWindow::throwFakeException() { throw "fake exception"; } void MainWindow::alignToGrid() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->alignToGrid(m_alignToGridAct->isChecked()); setWindowModified(true); } void MainWindow::showGrid() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->showGrid(m_showGridAct->isChecked()); setWindowModified(true); } void MainWindow::setGridSize() { GridSizeThing gridSizeThing(m_currentGraphicsView->viewName(), m_currentGraphicsView->getShortName(), m_currentGraphicsView->defaultGridSizeInches(), m_currentGraphicsView->gridSizeText()); GridSizeDialog dialog(&gridSizeThing); dialog.setWindowTitle(QObject::tr("Set Grid Size")); QVBoxLayout * vLayout = new QVBoxLayout(&dialog); vLayout->addWidget(createGridSizeForm(&gridSizeThing)); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); vLayout->addWidget(buttonBox); int result = dialog.exec(); if (result == QDialog::Accepted) { QString units = (gridSizeThing.inButton->isChecked() ? "in" : "mm"); m_currentGraphicsView->setGridSize(gridSizeThing.lineEdit->text() + units); setWindowModified(true); } } QWidget * MainWindow::createGridSizeForm(GridSizeThing * gridSizeThing) { this->setObjectName("gridSizeDia"); QGroupBox * over = new QGroupBox("", this); QVBoxLayout * vLayout = new QVBoxLayout(); QLabel * explain = new QLabel(tr("Set the grid size for %1.").arg(gridSizeThing->viewName)); vLayout->addWidget(explain); QGroupBox * groupBox = new QGroupBox(this); QHBoxLayout * hLayout = new QHBoxLayout(); QLabel * label = new QLabel(tr("Grid Size:")); hLayout->addWidget(label); gridSizeThing->lineEdit = new QLineEdit(); gridSizeThing->lineEdit->setFixedWidth(55); gridSizeThing->validator = new QDoubleValidator(gridSizeThing->lineEdit); gridSizeThing->validator->setRange(0.001, 1.0, 4); gridSizeThing->validator->setNotation(QDoubleValidator::StandardNotation); gridSizeThing->validator->setLocale(QLocale::C); gridSizeThing->lineEdit->setValidator(gridSizeThing->validator); hLayout->addWidget(gridSizeThing->lineEdit); gridSizeThing->inButton = new QRadioButton(tr("in"), this); hLayout->addWidget(gridSizeThing->inButton); gridSizeThing->mmButton = new QRadioButton(tr("mm"), this); hLayout->addWidget(gridSizeThing->mmButton); groupBox->setLayout(hLayout); vLayout->addWidget(groupBox); vLayout->addSpacing(5); QPushButton * pushButton = new QPushButton(this); pushButton->setText(tr("Restore Default")); pushButton->setMaximumWidth(150); vLayout->addWidget(pushButton); vLayout->addSpacing(10); over->setLayout(vLayout); if (gridSizeThing->gridSizeText.length() <= 2) { gridSizeThing->inButton->setChecked(true); gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->defaultGridSize)); } else { if (gridSizeThing->gridSizeText.endsWith("mm")) { gridSizeThing->mmButton->setChecked(true); gridSizeThing->validator->setTop(25.4); } else { gridSizeThing->inButton->setChecked(true); } QString szString = gridSizeThing->gridSizeText; szString.chop(2); gridSizeThing->lineEdit->setText(szString); } connect(gridSizeThing->inButton, SIGNAL(clicked(bool)), this, SLOT(gridUnits(bool))); connect(pushButton, SIGNAL(clicked()), this, SLOT(restoreDefaultGrid())); connect(gridSizeThing->mmButton, SIGNAL(clicked(bool)), this, SLOT(gridUnits(bool))); return over; } void MainWindow::openProgramWindow() { if (m_programWindow) { m_programWindow->setVisible(true); m_programWindow->raise(); return; } m_programWindow = new ProgramWindow(); connect(m_programWindow, SIGNAL(linkToProgramFile(const QString &, Platform *, bool, bool)), this, SLOT(linkToProgramFile(const QString &, Platform *, bool, bool))); connect(m_programWindow, SIGNAL(changeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection); connect(m_programWindow, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *))); QFileInfo fileInfo(m_fwFilename); m_programWindow->setup(); m_programWindow->linkFiles(m_linkedProgramFiles, fileInfo.absoluteDir().absolutePath()); m_programWindow->setVisible(true); } void MainWindow::linkToProgramFile(const QString & filename, Platform * platform, bool addLink, bool strong) { #ifdef Q_OS_WIN Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive; #else Qt::CaseSensitivity sensitivity = Qt::CaseSensitive; #endif if (addLink && strong) { bool gotOne = false; foreach (LinkedFile * linkedFile, m_linkedProgramFiles) { if (linkedFile->linkedFilename.compare(filename, sensitivity) == 0) { if (linkedFile->platform != platform->getName()) { linkedFile->platform = platform->getName(); this->setWindowModified(true); } gotOne = true; break; } } if (!gotOne) { LinkedFile * linkedFile = new LinkedFile; linkedFile->linkedFilename = filename; linkedFile->platform = platform->getName(); m_linkedProgramFiles.append(linkedFile); this->setWindowModified(true); } return; } else { for (int i = 0; i < m_linkedProgramFiles.count(); i++) { LinkedFile * linkedFile = m_linkedProgramFiles.at(i); if (linkedFile->linkedFilename.compare(filename, sensitivity) == 0) { if (strong) { m_linkedProgramFiles.removeAt(i); this->setWindowModified(true); } else { if (linkedFile->platform != platform->getName()) { linkedFile->platform = platform->getName(); this->setWindowModified(true); } } return; } } } } QStringList MainWindow::newDesignRulesCheck() { return newDesignRulesCheck(true); } QStringList MainWindow::newDesignRulesCheck(bool showOkMessage) { QStringList results; if (m_currentGraphicsView == NULL) return results; PCBSketchWidget * pcbSketchWidget = qobject_cast(m_currentGraphicsView); if (pcbSketchWidget == NULL) return results; ItemBase * board = NULL; if (pcbSketchWidget->autorouteTypePCB()) { int boardCount; board = pcbSketchWidget->findSelectedBoard(boardCount); if (boardCount == 0) { QString message = tr("Your sketch does not have a board yet! DRC only works with a PCB."); results << message; FMessageBox::critical(this, tr("Fritzing"), message); return results; } if (board == NULL) { QString message = tr("Please select a PCB. DRC only works on one board at a time."); results << message; FMessageBox::critical(this, tr("Fritzing"), message); return results; } } bool copper0Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper0); bool copper1Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper1); AutorouteProgressDialog progress(tr("DRC Progress..."), true, false, false, false, pcbSketchWidget, this); progress.setModal(true); progress.show(); QRect pr = progress.frameGeometry(); QRect wr = pcbSketchWidget->frameGeometry(); QPoint p = pcbSketchWidget->mapTo(this, wr.topRight()); progress.move(p.x() - pr.width(), pr.top()); DRC drc(pcbSketchWidget, board); connect(&drc, SIGNAL(wantTopVisible()), this, SLOT(activeLayerTop()), Qt::DirectConnection); connect(&drc, SIGNAL(wantBottomVisible()), this, SLOT(activeLayerBottom()), Qt::DirectConnection); connect(&drc, SIGNAL(wantBothVisible()), this, SLOT(activeLayerBoth()), Qt::DirectConnection); connect(&progress, SIGNAL(cancel()), &drc, SLOT(cancel()), Qt::DirectConnection); connect(&drc, SIGNAL(setMaximumProgress(int)), &progress, SLOT(setMaximum(int)), Qt::DirectConnection); connect(&drc, SIGNAL(setProgressValue(int)), &progress, SLOT(setValue(int)), Qt::DirectConnection); connect(&drc, SIGNAL(setProgressMessage(const QString &)), &progress, SLOT(setMessage(const QString &))); connect(&drc, SIGNAL(hideProgress()), &progress, SLOT(close())); ProcessEventBlocker::processEvents(); ProcessEventBlocker::block(); results = drc.start(showOkMessage, pcbSketchWidget->getKeepout() * 1000 / GraphicsUtils::SVGDPI); // pixels to mils ProcessEventBlocker::unblock(); pcbSketchWidget->setLayerActive(ViewLayer::Copper1, copper1Active); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, copper1Active); pcbSketchWidget->setLayerActive(ViewLayer::Copper0, copper0Active); pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, copper0Active); updateActiveLayerButtons(); return results; } void MainWindow::changeTraceLayer() { if (m_currentGraphicsView == NULL) return; if (m_currentGraphicsView != m_pcbGraphicsView) return; Wire * wire = retrieveWire(); m_pcbGraphicsView->changeTraceLayer(wire, false, NULL); } Wire * MainWindow::retrieveWire() { WireAction * wireAction = qobject_cast(sender()); if (wireAction == NULL) return NULL; return wireAction->wire(); } ConnectorItem * MainWindow::retrieveConnectorItem() { ConnectorItemAction * connectorItemAction = qobject_cast(sender()); if (connectorItemAction == NULL) return NULL; return connectorItemAction->connectorItem(); } void MainWindow::setSticky() { QList items = m_currentGraphicsView->scene()->selectedItems(); if (items.count() < 1) return; ItemBase * itemBase = dynamic_cast(items.at(0)); if (itemBase == NULL) return; if (!itemBase->isBaseSticky()) return; itemBase->setLocalSticky(!itemBase->isLocalSticky()); } void MainWindow::moveLock() { bool moveLock = true; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->selectedItems()) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item); if (itemBase == NULL) continue; if (itemBase->itemType() == ModelPart::Wire) continue; if (itemBase->moveLock()) { moveLock = false; break; } } ItemBase * viewedItem = m_infoView->currentItem(); foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->selectedItems()) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item); if (itemBase == NULL) continue; if (itemBase->itemType() == ModelPart::Wire) continue; itemBase->setMoveLock(moveLock); if (viewedItem && viewedItem->layerKinChief() == itemBase->layerKinChief()) { m_currentGraphicsView->viewItemInfo(itemBase); } } } void MainWindow::selectMoveLock() { m_currentGraphicsView->selectAllMoveLock(); } void MainWindow::autorouterSettings() { if (m_currentGraphicsView != m_pcbGraphicsView) return; m_pcbGraphicsView->autorouterSettings(); } void MainWindow::orderFab() { QDesktopServices::openUrl(QString("http://fab.fritzing.org/")); } void MainWindow::setGroundFillSeeds() { int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please select a PCB. Copper fill operations only work on one board at a time.")); return; } m_pcbGraphicsView->setGroundFillSeeds(); } void MainWindow::clearGroundFillSeeds() { int boardCount; ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount); if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please select a PCB. Copper fill operations only work on one board at a time.")); return; } m_pcbGraphicsView->clearGroundFillSeeds(); } void MainWindow::setOneGroundFillSeed() { ConnectorItemAction * action = qobject_cast(sender()); if (action == NULL) return; ConnectorItem * connectorItem = action->connectorItem(); if (connectorItem == NULL) return; GroundFillSeedCommand * command = new GroundFillSeedCommand(m_pcbGraphicsView, NULL); command->addItem(connectorItem->attachedToID(), connectorItem->connectorSharedID(), action->isChecked()); m_undoStack->push(command); } void MainWindow::gridUnits(bool checked) { QWidget * widget = qobject_cast(sender()); if (widget == NULL) return; GridSizeDialog * dialog = qobject_cast(widget->window()); if (dialog == NULL) return; GridSizeThing * gridSizeThing = dialog->gridSizeThing(); QString units; if (sender() == gridSizeThing->inButton) { units = (checked) ? "in" : "mm"; } else { units = (checked) ? "mm" : "in"; } if (units.startsWith("mm")) { gridSizeThing->validator->setTop(25.4); gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->lineEdit->text().toDouble() * 25.4)); } else { gridSizeThing->validator->setTop(1.0); gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->lineEdit->text().toDouble() / 25.4)); } } void MainWindow::restoreDefaultGrid() { QWidget * widget = qobject_cast(sender()); if (widget == NULL) return; GridSizeDialog * dialog = qobject_cast(widget->window()); if (dialog == NULL) return; GridSizeThing * gridSizeThing = dialog->gridSizeThing(); gridSizeThing->inButton->setChecked(true); gridSizeThing->mmButton->setChecked(false); gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->defaultGridSize)); } void MainWindow::setBackgroundColor() { QColor cc = m_currentGraphicsView->background(); QColor scc = m_currentGraphicsView->standardBackground(); SetColorDialog setColorDialog(tr("%1 background").arg(m_currentGraphicsView->viewName()), cc, scc, true, this); int result = setColorDialog.exec(); if (result == QDialog::Rejected) return; QColor newColor = setColorDialog.selectedColor(); m_currentGraphicsView->setBackgroundColor(newColor, setColorDialog.isPrefsColor()); setWindowModified(true); } void MainWindow::checkLoadedTraces() { if (m_pcbGraphicsView) m_pcbGraphicsView->checkLoadedTraces(); } void MainWindow::showUnrouted() { m_currentGraphicsView->showUnrouted(); } void MainWindow::hidePartSilkscreen() { m_pcbGraphicsView->hidePartSilkscreen(); } void MainWindow::fabQuote() { if (m_pcbGraphicsView) m_pcbGraphicsView->fabQuote(); } void MainWindow::findPartInSketch() { static QString lastSearchText; if (m_currentGraphicsView == NULL) return; bool ok; QString text = QInputDialog::getText(this, tr("Enter Text"), tr("Text will match part label, description, title, etc. Enter text to search for:"), QLineEdit::Normal, lastSearchText, &ok); if (!ok || text.isEmpty()) return; lastSearchText = text; QSet itemBases; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBases.insert(itemBase->layerKinChief()); } QStringList strings; strings << text; QList matched; foreach (ItemBase * itemBase, itemBases) { #ifndef QT_NO_DEBUG if (QString::number(itemBase->id()).contains(text)) { matched << itemBase; continue; } #endif if (itemBase->instanceTitle().contains(text, Qt::CaseInsensitive)) { matched << itemBase; continue; } QList modelParts; m_referenceModel->search(itemBase->modelPart(), strings, modelParts, true); if (modelParts.count() > 0) { matched << itemBase; } } if (matched.count() == 0) { QMessageBox::information(this, tr("Search"), tr("No parts matched search term '%1'.").arg(text)); return; } m_currentGraphicsView->selectItems(matched); } void MainWindow::setGroundFillKeepout() { if (m_pcbGraphicsView != NULL) m_pcbGraphicsView->setGroundFillKeepout(); } void MainWindow::setViewFromBelowToggle() { if (m_pcbGraphicsView != NULL) { m_pcbGraphicsView->setViewFromBelow(m_viewFromBelowToggleAct->isChecked()); updateActiveLayerButtons(); } } void MainWindow::setViewFromBelow() { if (m_pcbGraphicsView != NULL) { m_pcbGraphicsView->setViewFromBelow(true); updateActiveLayerButtons(); } } void MainWindow::setViewFromAbove() { if (m_pcbGraphicsView != NULL) { m_pcbGraphicsView->setViewFromBelow(false); updateActiveLayerButtons(); } } void MainWindow::updateExportMenu() { bool enabled = m_currentGraphicsView != NULL; foreach (QAction * action, m_exportMenu->actions()) { action->setEnabled(enabled); } } void MainWindow::testConnectors() { if (m_currentGraphicsView == NULL) return; m_currentGraphicsView->testConnectors(); } fritzing-app-0.9.2b/src/mainwindow/sketchareawidget.cpp000066400000000000000000000113511250202676700232730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include "sketchareawidget.h" const QString SketchAreaWidget::RoutingStateLabelName = "routingStateLabel"; SketchAreaWidget::SketchAreaWidget(QWidget *contentView, QMainWindow *parent) : QFrame(parent) { init(contentView, parent, true, true); } SketchAreaWidget::SketchAreaWidget(QWidget *contentView, QMainWindow *parent, bool hasToolBar, bool hasStatusBar) : QFrame(parent) { init (contentView, parent, hasToolBar, hasStatusBar); } SketchAreaWidget::~SketchAreaWidget() { // TODO Auto-generated destructor stub } void SketchAreaWidget::init(QWidget *contentView, QMainWindow *parent, bool hasToolBar, bool hasStatusBar) { m_contentView = contentView; contentView->setParent(this); createLayout(); QVBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(0); layout->setSpacing(0); layout->addWidget(contentView); layout->addWidget(m_toolbar); if (!hasToolBar) m_toolbar->hide(); layout->addWidget(m_statusBarArea); if (!hasStatusBar) m_statusBarArea->hide(); m_statusBarArea->setFixedHeight(parent->statusBar()->height()*3/4); } QWidget *SketchAreaWidget::contentView() { return m_contentView; } void SketchAreaWidget::createLayout() { m_toolbar = new QFrame(this); m_toolbar->setObjectName("sketchAreaToolbar"); m_toolbar->setFixedHeight(66); QFrame *leftButtons = new QFrame(m_toolbar); m_leftButtonsContainer = new QHBoxLayout(leftButtons); m_leftButtonsContainer->setMargin(0); m_leftButtonsContainer->setSpacing(0); QFrame *middleButtons = new QFrame(m_toolbar); middleButtons->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::MinimumExpanding); m_middleButtonsContainer = new QVBoxLayout(middleButtons); m_middleButtonsContainer->setSpacing(0); m_middleButtonsContainer->setMargin(0); QFrame *rightButtons = new QFrame(m_toolbar); m_rightButtonsContainer = new QHBoxLayout(rightButtons); m_rightButtonsContainer->setMargin(0); m_rightButtonsContainer->setSpacing(0); QHBoxLayout *toolbarLayout = new QHBoxLayout(m_toolbar); toolbarLayout->setMargin(0); toolbarLayout->setSpacing(0); toolbarLayout->addWidget(leftButtons); toolbarLayout->addWidget(middleButtons); toolbarLayout->addWidget(rightButtons); m_statusBarArea = new QFrame(this); m_statusBarArea->setObjectName("statusBarContainer"); QVBoxLayout *statusbarlayout = new QVBoxLayout(m_statusBarArea); statusbarlayout->setMargin(0); statusbarlayout->setSpacing(0); } void SketchAreaWidget::setToolbarWidgets(QList widgets) { bool goLeft = true; foreach(QWidget* widget, widgets) { if(widget->objectName() != RoutingStateLabelName) { if (goLeft) m_leftButtonsContainer->addWidget(widget); else m_rightButtonsContainer->addWidget(widget); } else { m_middleButtonsContainer->addSpacerItem(new QSpacerItem(0,1,QSizePolicy::Maximum)); m_middleButtonsContainer->addWidget(widget); m_middleButtonsContainer->addSpacerItem(new QSpacerItem(0,1,QSizePolicy::Maximum)); goLeft = false; } } } void SketchAreaWidget::addStatusBar(QStatusBar *statusBar) { m_statusBarArea->layout()->addWidget(statusBar); } QWidget *SketchAreaWidget::separator(QWidget* parent) { QLabel *separator = new QLabel(parent); separator->setPixmap(QPixmap(":/resources/images/toolbar_icons/toolbar_separator.png")); separator->setStyleSheet("margin-left: 1px; margin-right: 1px;"); separator->setObjectName("ToolBarSeparator"); return separator; } void SketchAreaWidget::setRoutingStatusLabel(ExpandingLabel * rsl) { m_routingStatusLabel = rsl; } ExpandingLabel * SketchAreaWidget::routingStatusLabel() { return m_routingStatusLabel; } QFrame * SketchAreaWidget::toolbar() { return m_toolbar; } fritzing-app-0.9.2b/src/mainwindow/sketchareawidget.h000066400000000000000000000042011250202676700227340ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SKETCHAREAWIDGET_H_ #define SKETCHAREAWIDGET_H_ #include #include #include #include class SketchAreaWidget : public QFrame { Q_OBJECT public: SketchAreaWidget(QWidget *contentView, QMainWindow *parent); SketchAreaWidget(QWidget *contentView, QMainWindow *parent, bool hasToolBar, bool hasStatusBar); virtual ~SketchAreaWidget(); QWidget* contentView(); void setToolbarWidgets(QList buttons); void addStatusBar(QStatusBar *); static QWidget *separator(QWidget* parent); class ExpandingLabel * routingStatusLabel(); void setRoutingStatusLabel(ExpandingLabel *); QFrame * toolbar(); protected: void init(QWidget *contentView, QMainWindow *parent, bool hasToolBar, bool hasStatusBar); void createLayout(); public: static const QString RoutingStateLabelName; protected: QWidget *m_contentView; QFrame *m_toolbar; QHBoxLayout *m_leftButtonsContainer; QVBoxLayout *m_middleButtonsContainer; QHBoxLayout *m_rightButtonsContainer; QFrame *m_statusBarArea; class ExpandingLabel * m_routingStatusLabel; }; #endif /* SKETCHAREAWIDGET_H_ */ fritzing-app-0.9.2b/src/model/000077500000000000000000000000001250202676700161745ustar00rootroot00000000000000fritzing-app-0.9.2b/src/model/modelbase.cpp000066400000000000000000000723321250202676700206420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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.old You should have received a copy of the GNU General Public License along with Fritzing. If not, see . ******************************************************************** $Revision: 6963 $: $Author: irascibl@gmail.com $: $Date: 2013-04-14 10:13:52 +0200 (So, 14. Apr 2013) $ ********************************************************************/ #include "modelbase.h" #include "../debugdialog.h" #include "../items/partfactory.h" #include "../items/moduleidnames.h" #include "../utils/textutils.h" #include "../utils/folderutils.h" #include "../utils/fmessagebox.h" #include "../version/version.h" #include "../viewgeometry.h" #include QList ModelBase::CoreList; ///////////////////////////////////////////////// ModelBase::ModelBase( bool makeRoot ) { m_useOldSchematics = false; m_reportMissingModules = true; m_referenceModel = NULL; m_root = NULL; if (makeRoot) { m_root = new ModelPart(); m_root->setModelPartShared(new ModelPartSharedRoot()); } } ModelBase::~ModelBase() { if (m_root) { ModelPartShared * modelPartShared = m_root->modelPartShared(); if (modelPartShared) { m_root->setModelPartShared(NULL); delete modelPartShared; } delete m_root; } } ModelPart * ModelBase::root() { return m_root; } ModelPart * ModelBase::retrieveModelPart(const QString & /* moduleID */) { return NULL; } // loads a model from an fz file--assumes a reference model exists with all parts bool ModelBase::loadFromFile(const QString & fileName, ModelBase * referenceModel, QList & modelParts, bool checkViews) { m_referenceModel = referenceModel; QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { FMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Cannot read file %1:\n%2.") .arg(fileName) .arg(file.errorString())); return false; } QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("Parse error (1) at line %1, column %2:\n%3\n%4") .arg(errorLine) .arg(errorColumn) .arg(errorStr) .arg(fileName)); return false; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file %1 is not a Fritzing file (2).").arg(fileName)); return false; } emit loadedRoot(fileName, this, root); if (root.tagName() != "module") { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file %1 is not a Fritzing file (4).").arg(fileName)); return false; } bool checkForOldSchematics = true; bool checkForRats = true; bool checkForTraces = true; bool checkForMysteryParts = true; bool checkForObsoleteSMDOrientation = true; m_fritzingVersion = root.attribute("fritzingVersion"); if (m_fritzingVersion.length() > 0) { // with version 0.4.3 ratsnests in fz files are obsolete VersionThing versionThingRats; versionThingRats.majorVersion = 0; versionThingRats.minorVersion = 4; versionThingRats.minorSubVersion = 2; versionThingRats.releaseModifier = ""; VersionThing versionThingFz; Version::toVersionThing(m_fritzingVersion,versionThingFz); checkForRats = !Version::greaterThan(versionThingRats, versionThingFz); // with version 0.6.5 traces are copied to all views versionThingRats.minorVersion = 6; versionThingRats.minorSubVersion = 4; checkForTraces = !Version::greaterThan(versionThingRats, versionThingFz); // with version 0.7.6 mystery part spacing implementation changes versionThingRats.minorVersion = 7; versionThingRats.minorSubVersion = 5; checkForMysteryParts = !Version::greaterThan(versionThingRats, versionThingFz); // with version 0.8.0 flipSMD is horizontal versionThingRats.minorVersion = 7; versionThingRats.minorSubVersion = 13; checkForObsoleteSMDOrientation = !Version::greaterThan(versionThingRats, versionThingFz); // with version 0.8.6 we get a new schematic template versionThingRats.minorVersion = 8; versionThingRats.minorSubVersion = 5; checkForOldSchematics = !Version::greaterThan(versionThingRats, versionThingFz); } ModelPartSharedRoot * modelPartSharedRoot = this->rootModelPartShared(); QDomElement title = root.firstChildElement("title"); if (!title.isNull()) { if (modelPartSharedRoot) { modelPartSharedRoot->setTitle(title.text()); } } // ensures changeBinIcon() is not available // this may be a bug? QString iconFilename = root.attribute("icon"); if (iconFilename.isEmpty()) { iconFilename = title.text() + ".png"; } if (!iconFilename.isEmpty()) { if (modelPartSharedRoot) { modelPartSharedRoot->setIcon(iconFilename); } } QString searchTerm = root.attribute("search"); if (!searchTerm.isEmpty() && modelPartSharedRoot != NULL) { modelPartSharedRoot->setSearchTerm(searchTerm); } QDomElement views = root.firstChildElement("views"); emit loadedViews(this, views); QDomElement instances = root.firstChildElement("instances"); if (instances.isNull()) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file %1 is not a Fritzing file (3).").arg(fileName)); return false; } // delete any aready-existing model parts for (int i = m_root->children().count() - 1; i >= 0; i--) { QObject* child = m_root->children()[i]; child->setParent(NULL); delete child; } emit loadingInstances(this, instances); if (checkForRats) { QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { QDomElement nextInstance = instance.nextSiblingElement("instance"); if (isRatsnest(instance)) { instances.removeChild(instance); } instance = nextInstance; } } if (checkForTraces) { QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { checkTraces(instance); instance = instance.nextSiblingElement("instance"); } } if (checkForMysteryParts) { QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { checkMystery(instance); instance = instance.nextSiblingElement("instance"); } } if (checkForObsoleteSMDOrientation) { QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { if (checkObsoleteOrientation(instance)) { emit obsoleteSMDOrientationSignal(); break; } instance = instance.nextSiblingElement("instance"); } } m_useOldSchematics = false; if (checkForOldSchematics) { QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { if (checkOldSchematics(instance)) { emit oldSchematicsSignal(fileName, m_useOldSchematics); break; } instance = instance.nextSiblingElement("instance"); } } bool result = loadInstances(domDocument, instances, modelParts, checkViews); emit loadedInstances(this, instances); return result; } ModelPart * ModelBase::fixObsoleteModuleID(QDomDocument & domDocument, QDomElement & instance, QString & moduleIDRef) { return PartFactory::fixObsoleteModuleID(domDocument, instance, moduleIDRef, m_referenceModel); } bool ModelBase::loadInstances(QDomDocument & domDocument, QDomElement & instances, QList & modelParts, bool checkViews) { QHash missingModules; QDomElement instance = instances.firstChildElement("instance"); ModelPart* modelPart = NULL; while (!instance.isNull()) { emit loadingInstance(this, instance); if (checkViews) { QDomElement views = instance.firstChildElement("views"); QDomElement view = views.firstChildElement(); if (views.isNull() || view.isNull()) { // do not load a part with no views //QString text; //QTextStream stream(&text); //instance.save(stream, 0); //DebugDialog::debug(text); instance = instance.nextSiblingElement("instance"); continue; } } // for now assume all parts are in the palette QString moduleIDRef = instance.attribute("moduleIdRef"); //DebugDialog::debug("loading " + moduleIDRef); if (moduleIDRef.compare(ModuleIDNames::SpacerModuleIDName) == 0) { ModelPart * mp = new ModelPart(ModelPart::Space); mp->setInstanceText(instance.attribute("path")); mp->setParent(m_root); mp->modelPartShared()->setModuleID(ModuleIDNames::SpacerModuleIDName); mp->modelPartShared()->setPath(instance.attribute("path")); modelParts.append(mp); instance = instance.nextSiblingElement("instance"); continue; } bool generated = false; modelPart = m_referenceModel->retrieveModelPart(moduleIDRef); if (modelPart == NULL) { DebugDialog::debug(QString("module id %1 not found in database").arg(moduleIDRef)); modelPart = fixObsoleteModuleID(domDocument, instance, moduleIDRef); if (modelPart == NULL) { modelPart = genFZP(moduleIDRef, m_referenceModel); if (modelPart != NULL) { instance.setAttribute("moduleIdRef", modelPart->moduleID()); moduleIDRef = modelPart->moduleID(); generated = true; } if (modelPart == NULL) { missingModules.insert(moduleIDRef, instance.attribute("path")); instance = instance.nextSiblingElement("instance"); continue; } } } if (modelPart->isCore() && m_useOldSchematics) { modelPart = createOldSchematicPart(modelPart, moduleIDRef); } modelPart->setInBin(true); modelPart = addModelPart(m_root, modelPart); modelPart->setInstanceDomElement(instance); modelParts.append(modelPart); // TODO Mariano: i think this is not the way QString instanceTitle = instance.firstChildElement("title").text(); if(!instanceTitle.isNull() && !instanceTitle.isEmpty()) { modelPart->setInstanceTitle(instanceTitle, false); } QDomElement localConnectors = instance.firstChildElement("localConnectors"); QDomElement localConnector = localConnectors.firstChildElement("localConnector"); while (!localConnector.isNull()) { modelPart->setConnectorLocalName(localConnector.attribute("id"), localConnector.attribute("name")); localConnector = localConnector.nextSiblingElement("localConnector"); } QString instanceText = instance.firstChildElement("text").text(); if(!instanceText.isNull() && !instanceText.isEmpty()) { modelPart->setInstanceText(instanceText); } bool ok; long index = instance.attribute("modelIndex").toLong(&ok); if (ok) { // set the index so we can find the same model part later, as we continue loading modelPart->setModelIndex(index); } // note: this QDomNamedNodeMap loop is obsolete, but leaving it here so that old sketches don't get broken (jc, 22 Oct 2009) QDomNamedNodeMap map = instance.attributes(); for (int m = 0; m < map.count(); m++) { QDomNode node = map.item(m); QString nodeName = node.nodeName(); if (nodeName.isEmpty()) continue; if (nodeName.compare("moduleIdRef") == 0) continue; if (nodeName.compare("modelIndex") == 0) continue; if (nodeName.compare("originalModelIndex") == 0) continue; if (nodeName.compare("path") == 0) continue; modelPart->setLocalProp(nodeName, node.nodeValue()); } // "property" loop replaces previous QDomNamedNodeMap loop (jc, 22 Oct 2009) QDomElement prop = instance.firstChildElement("property"); while(!prop.isNull()) { QString name = prop.attribute("name"); if (!name.isEmpty()) { QString value = prop.attribute("value"); if (!value.isEmpty()) { modelPart->setLocalProp(name, value); } } prop = prop.nextSiblingElement("property"); } instance = instance.nextSiblingElement("instance"); } if (m_reportMissingModules && missingModules.count() > 0) { QString unableToFind = QString("%1
") .arg(tr("Unable to find the following %n part(s):", "", missingModules.count())); foreach (QString key, missingModules.keys()) { unableToFind += QString("") .arg(key).arg(tr("at")).arg(missingModules.value(key, "")); } unableToFind += "
'%1'%2'%3'
"; FMessageBox::warning(NULL, QObject::tr("Fritzing"), unableToFind); } return true; } ModelPart * ModelBase::addModelPart(ModelPart * parent, ModelPart * copyChild) { //if (copyChild->moduleID() == "df9d072afa2b594ac67b60b4153ff57b_29") { // DebugDialog::debug("alive in here"); //} ModelPart * modelPart = new ModelPart(); modelPart->copyNew(copyChild); modelPart->setParent(parent); modelPart->initConnectors(); modelPart->flipSMDAnd(); return modelPart; } ModelPart * ModelBase::addPart(QString newPartPath, bool addToReference) { Q_UNUSED(newPartPath); Q_UNUSED(addToReference); throw "ModelBase::addPart should not be invoked"; return NULL; } ModelPart * ModelBase::addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists) { Q_UNUSED(updateIdAlreadyExists); Q_UNUSED(newPartPath); Q_UNUSED(addToReference); throw "ModelBase::addPart should not be invoked"; return NULL; } // TODO Mariano: this function should never get called. Make pure virtual bool ModelBase::addPart(ModelPart * modelPart, bool update) { Q_UNUSED(modelPart); Q_UNUSED(update); throw "ModelBase::addPart should not be invoked"; return false; } void ModelBase::save(const QString & fileName, bool asPart) { QFileInfo info(fileName); QDir dir = info.absoluteDir(); QString temp = dir.absoluteFilePath("temp.xml"); QFile file1(temp); if (!file1.open(QFile::WriteOnly | QFile::Text)) { FMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Cannot write file temp:\n%1\n%2\n%3.") .arg(temp) .arg(fileName) .arg(file1.errorString()) ); return; } QXmlStreamWriter streamWriter(&file1); save(fileName, streamWriter, asPart); file1.close(); QFile original(fileName); if(original.exists() && !original.remove()) { file1.remove(); FMessageBox::warning( NULL, tr("File save failed!"), tr("Couldn't overwrite file '%1'.\nReason: %2 (errcode %3)") .arg(fileName) .arg(original.errorString()) .arg(original.error()) ); return; } file1.rename(fileName); } void ModelBase::save(const QString & fileName, QXmlStreamWriter & streamWriter, bool asPart) { streamWriter.setAutoFormatting(true); if(asPart) { m_root->saveAsPart(streamWriter, true); } else { m_root->saveInstances(fileName, streamWriter, true); } } bool ModelBase::paste(ModelBase * referenceModel, QByteArray & data, QList & modelParts, QHash & boundingRects, bool preserveIndex) { m_referenceModel = referenceModel; QDomDocument domDocument; QString errorStr; int errorLine; int errorColumn; bool result = domDocument.setContent(data, &errorStr, &errorLine, &errorColumn); if (!result) return false; QDomElement module = domDocument.documentElement(); if (module.isNull()) { return false; } QDomElement boundingRectsElement = module.firstChildElement("boundingRects"); if (!boundingRectsElement.isNull()) { QDomElement boundingRect = boundingRectsElement.firstChildElement("boundingRect"); while (!boundingRect.isNull()) { QString name = boundingRect.attribute("name"); QString rect = boundingRect.attribute("rect"); QRectF br; if (!rect.isEmpty()) { QStringList s = rect.split(" "); if (s.count() == 4) { QRectF r(s[0].toDouble(), s[1].toDouble(), s[2].toDouble(), s[3].toDouble()); br = r; } } boundingRects.insert(name, br); boundingRect = boundingRect.nextSiblingElement("boundingRect"); } } QDomElement instances = module.firstChildElement("instances"); if (instances.isNull()) { return false; } if (!preserveIndex) { // need to map modelIndexes from copied parts to new modelIndexes QHash oldToNew; QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { long oldModelIndex = instance.attribute("modelIndex").toLong(); oldToNew.insert(oldModelIndex, ModelPart::nextIndex()); instance = instance.nextSiblingElement("instance"); } renewModelIndexes(instances, "instance", oldToNew); } //QFile file("test.xml"); //file.open(QFile::WriteOnly); //file.write(domDocument.toByteArray()); //file.close(); return loadInstances(domDocument, instances, modelParts, true); } void ModelBase::renewModelIndexes(QDomElement & parentElement, const QString & childName, QHash & oldToNew) { QDomElement instance = parentElement.firstChildElement(childName); while (!instance.isNull()) { long oldModelIndex = instance.attribute("modelIndex").toLong(); instance.setAttribute("modelIndex", QString::number(oldToNew.value(oldModelIndex))); QDomElement views = instance.firstChildElement("views"); if (!views.isNull()) { QDomElement view = views.firstChildElement(); while (!view.isNull()) { bool ok; int superpart = view.attribute("superpart").toLong(&ok); if (ok) { view.setAttribute("superpart", QString::number(oldToNew.value(superpart))); } QDomElement connectors = view.firstChildElement("connectors"); if (!connectors.isNull()) { QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement connects = connector.firstChildElement("connects"); if (!connects.isNull()) { QDomElement connect = connects.firstChildElement("connect"); while (!connect.isNull()) { bool ok; oldModelIndex = connect.attribute("modelIndex").toLong(&ok); if (ok) { long newModelIndex = oldToNew.value(oldModelIndex, -1); if (newModelIndex != -1) { connect.setAttribute("modelIndex", QString::number(newModelIndex)); } else { //DebugDialog::debug(QString("keep old model index %1").arg(oldModelIndex)); } } connect = connect.nextSiblingElement("connect"); } } connector = connector.nextSiblingElement("connector"); } } view = view.nextSiblingElement(); } } instance = instance.nextSiblingElement(childName); } } void ModelBase::setReportMissingModules(bool b) { m_reportMissingModules = b; } ModelPart * ModelBase::genFZP(const QString & moduleID, ModelBase * referenceModel) { QString path = PartFactory::getFzpFilename(moduleID); if (path.isEmpty()) return NULL; ModelPart* mp = referenceModel->addPart(path, true, true); if (mp) mp->setCore(true); return mp; } ModelPartSharedRoot * ModelBase::rootModelPartShared() { if (m_root == NULL) return NULL; return m_root->modelPartSharedRoot(); } bool ModelBase::isRatsnest(QDomElement & instance) { QString moduleIDRef = instance.attribute("moduleIdRef"); if (moduleIDRef.compare(ModuleIDNames::WireModuleIDName) != 0) return false; QDomElement views = instance.firstChildElement("views"); if (views.isNull()) return false; QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement geometry = view.firstChildElement("geometry"); if (!geometry.isNull()) { int flags = geometry.attribute("wireFlags").toInt(); if (flags & ViewGeometry::RatsnestFlag) { return true; } if (flags & ViewGeometry::ObsoleteJumperFlag) { return true; } } view = view.nextSiblingElement(); } return false; } bool ModelBase::checkOldSchematics(QDomElement & instance) { if (instance.attribute("moduleIdRef").compare(ModuleIDNames::WireModuleIDName) != 0) { return false; } QDomElement views = instance.firstChildElement("views"); QDomElement schematicView = views.firstChildElement("schematicView"); QDomElement geometry = schematicView.firstChildElement("geometry"); if (geometry.isNull()) return false; int flags = geometry.attribute("wireFlags", "0").toInt(); return (flags & ViewGeometry::SchematicTraceFlag) != 0; } bool ModelBase::checkObsoleteOrientation(QDomElement & instance) { QString flippedSMD = instance.attribute("flippedSMD", ""); if (flippedSMD != "true") return false; QDomElement views = instance.firstChildElement("views"); QDomElement pcbView = views.firstChildElement("pcbView"); return (pcbView.attribute("layer", "") == "copper0"); } void ModelBase::checkTraces(QDomElement & instance) { QString moduleIDRef = instance.attribute("moduleIdRef"); if (moduleIDRef.compare(ModuleIDNames::WireModuleIDName) != 0) return; QDomElement views = instance.firstChildElement("views"); if (views.isNull()) return; QDomElement bbView = views.firstChildElement("breadboardView"); QDomElement schView = views.firstChildElement("schematicView"); QDomElement pcbView = views.firstChildElement("pcbView"); if (!bbView.isNull() && !schView.isNull() && !pcbView.isNull()) { // if it's a breadboard wire; just make sure flag is correct QList elements; elements << bbView << schView << pcbView; foreach (QDomElement element, elements) { QDomElement geometry = element.firstChildElement("geometry"); if (!geometry.isNull()) { int flags = geometry.attribute("wireFlags").toInt(); if (flags & ViewGeometry::PCBTraceFlag) return; // not a breadboard wire, bail out if (flags & ViewGeometry::SchematicTraceFlag) return; // not a breadboard wire, bail out if ((flags & ViewGeometry::NormalFlag) == 0) { flags |= ViewGeometry::NormalFlag; geometry.setAttribute("wireFlags", QString::number(flags)); } } } return; } if (!bbView.isNull()) { QDomElement geometry = bbView.firstChildElement("geometry"); if (!geometry.isNull()) { int flags = geometry.attribute("wireFlags").toInt(); if ((flags & ViewGeometry::NormalFlag) == 0) { flags |= ViewGeometry::NormalFlag; geometry.setAttribute("wireFlags", QString::number(flags)); } } schView = bbView.cloneNode(true).toElement(); pcbView = bbView.cloneNode(true).toElement(); schView.setTagName("schematicView"); pcbView.setTagName("pcbView"); views.appendChild(pcbView); views.appendChild(schView); return; } if (!schView.isNull()) { QDomElement geometry = schView.firstChildElement("geometry"); if (!geometry.isNull()) { int flags = geometry.attribute("wireFlags").toInt(); if (flags & ViewGeometry::PCBTraceFlag) { flags ^= ViewGeometry::PCBTraceFlag; flags |= ViewGeometry::SchematicTraceFlag; geometry.setAttribute("wireFlags", QString::number(flags)); } } pcbView = schView.cloneNode(true).toElement(); bbView = schView.cloneNode(true).toElement(); pcbView.setTagName("pcbView"); bbView.setTagName("breadboardView"); views.appendChild(bbView); views.appendChild(pcbView); return; } if (!pcbView.isNull()) { schView = pcbView.cloneNode(true).toElement(); bbView = pcbView.cloneNode(true).toElement(); schView.setTagName("schematicView"); bbView.setTagName("breadboardView"); views.appendChild(bbView); views.appendChild(schView); return; } QDomElement iconView = views.firstChildElement("iconView"); if (!iconView.isNull()) return; QString string; QTextStream stream(&string); instance.save(stream, 0); stream.flush(); DebugDialog::debug(QString("no wire view elements in fz file %1").arg(string)); } const QString & ModelBase::fritzingVersion() { return m_fritzingVersion; } void ModelBase::setReferenceModel(ModelBase * modelBase) { m_referenceModel = modelBase; } void ModelBase::checkMystery(QDomElement & instance) { QString moduleIDRef = instance.attribute("moduleIdRef"); bool mystery = false; bool sip = false; bool dip = false; if (moduleIDRef.contains("mystery", Qt::CaseInsensitive)) mystery = true; else if (moduleIDRef.contains("sip", Qt::CaseInsensitive)) sip = true; else if (moduleIDRef.contains("dip", Qt::CaseInsensitive)) dip = true; else return; QString spacing; int pins = TextUtils::getPinsAndSpacing(moduleIDRef, spacing); QDomElement prop = instance.firstChildElement("property"); while (!prop.isNull()) { if (prop.attribute("name", "").compare("spacing") == 0) { QString trueSpacing = prop.attribute("value", ""); if (trueSpacing.isEmpty()) trueSpacing = "300mil"; if (moduleIDRef.contains(spacing)) { moduleIDRef.replace(spacing, trueSpacing); instance.setAttribute("moduleIdRef", moduleIDRef); return; } // if we're here, it's a single sided mystery part. moduleIDRef = QString("mystery_part_sip_%1_100mil").arg(pins); instance.setAttribute("moduleIdRef", moduleIDRef); return; } prop = prop.nextSiblingElement("property"); } } bool ModelBase::onCoreList(const QString & moduleID) { // CoreList contains db entries that are (presumably) overridden by an fzp in the parts folder return CoreList.contains(moduleID); } ModelPart * ModelBase::createOldSchematicPart(ModelPart * modelPart, QString & moduleIDRef) { QString schematicFilename = modelPart->imageFileName(ViewLayer::SchematicView, ViewLayer::Schematic); if (!schematicFilename.startsWith("schematic")) { schematicFilename = modelPart->imageFileName(ViewLayer::SchematicView, ViewLayer::SchematicFrame); if (!schematicFilename.startsWith("schematic")) { return modelPart; } } DebugDialog::debug("schematic " + schematicFilename); QString oldModuleIDRef = PartFactory::OldSchematicPrefix + moduleIDRef; ModelPart * oldModelPart = m_referenceModel->retrieveModelPart(oldModuleIDRef); // cached after the first time it's created if (oldModelPart) { moduleIDRef = oldModuleIDRef; return oldModelPart; } int ix = schematicFilename.indexOf("/"); schematicFilename.insert(ix + 1, PartFactory::OldSchematicPrefix); QString oldSvgPath = FolderUtils::getApplicationSubFolderPath("parts") + "/svg/obsolete/"+ schematicFilename; oldModelPart = createOldSchematicPartAux(modelPart, oldModuleIDRef, schematicFilename, oldSvgPath); if (oldModelPart) { moduleIDRef = oldModuleIDRef; return oldModelPart; } oldSvgPath = ":resources/parts/svg/obsolete/"+ schematicFilename; oldModelPart = createOldSchematicPartAux(modelPart, oldModuleIDRef, schematicFilename, oldSvgPath); if (oldModelPart) { moduleIDRef = oldModuleIDRef; return oldModelPart; } // see whether it's a generated part oldSvgPath = PartFactory::getSvgFilename(schematicFilename); if (!oldSvgPath.isEmpty()) { oldModelPart = createOldSchematicPartAux(modelPart, oldModuleIDRef, schematicFilename, oldSvgPath); if (oldModelPart) { moduleIDRef = oldModuleIDRef; return oldModelPart; } } return modelPart; } ModelPart * ModelBase::createOldSchematicPartAux(ModelPart * modelPart, const QString & oldModuleIDRef, const QString & oldSchematicFileName, const QString & oldSvgPath) { if (!QFile::exists(oldSvgPath)) return NULL; // create oldModelPart, set up the new image file name, add it to refmodel QFile newFzp(modelPart->path()); QDomDocument oldDoc; bool ok = oldDoc.setContent(&newFzp); if (!ok) { // this shouldn't happen return NULL; } QDomElement root = oldDoc.documentElement(); root.setAttribute("moduleId", oldModuleIDRef); QDomElement views = root.firstChildElement("views"); QDomElement schematicView = views.firstChildElement("schematicView"); QDomElement layers = schematicView.firstChildElement("layers"); if (layers.isNull()) { // this shouldn't happen return NULL; } layers.setAttribute("image", oldSchematicFileName); QString oldFzpPath = PartFactory::fzpPath() + oldModuleIDRef + ".fzp"; if (!TextUtils::writeUtf8(oldFzpPath, oldDoc.toString())) { // this shouldn't happen return NULL; } ModelPart * oldModelPart = m_referenceModel->addPart(oldFzpPath, true, true); oldModelPart->setCore(modelPart->isCore()); oldModelPart->setContrib(modelPart->isContrib()); return oldModelPart; } fritzing-app-0.9.2b/src/model/modelbase.h000066400000000000000000000073711250202676700203100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6565 $: $Author: irascibl@gmail.com $: $Date: 2012-10-15 12:10:48 +0200 (Mo, 15. Okt 2012) $ ********************************************************************/ #ifndef MODELBASE_H #define MODELBASE_H #include #include "modelpart.h" class ModelBase : public QObject { Q_OBJECT public: ModelBase(bool makeRoot); virtual ~ModelBase(); ModelPart * root(); ModelPartSharedRoot * rootModelPartShared(); virtual ModelPart* retrieveModelPart(const QString & moduleID); virtual ModelPart * addModelPart(ModelPart * parent, ModelPart * copyChild); bool loadFromFile(const QString & fileName, ModelBase* referenceModel, QList & modelParts, bool checkInstances); void save(const QString & fileName, bool asPart); void save(const QString & fileName, class QXmlStreamWriter &, bool asPart); virtual ModelPart * addPart(QString newPartPath, bool addToReference); virtual bool addPart(ModelPart * modelPart, bool update); virtual ModelPart * addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists); bool paste(ModelBase * referenceModel, QByteArray & data, QList & modelParts, QHash & boundingRects, bool preserveIndex); void setReportMissingModules(bool); ModelPart * genFZP(const QString & moduleID, ModelBase * referenceModel); const QString & fritzingVersion(); void setReferenceModel(ModelBase *); public: static bool onCoreList(const QString & moduleID); signals: void loadedViews(ModelBase *, QDomElement & views); void loadedRoot(const QString & fileName, ModelBase *, QDomElement & root); void loadingInstances(ModelBase *, QDomElement & instances); void loadingInstance(ModelBase *, QDomElement & instance); void loadedInstances(ModelBase *, QDomElement & instances); void obsoleteSMDOrientationSignal(); void oldSchematicsSignal(const QString & filename, bool & useOldSchematics); protected: void renewModelIndexes(QDomElement & root, const QString & childName, QHash & oldToNew); bool loadInstances(QDomDocument &, QDomElement & root, QList & modelParts, bool checkViews); ModelPart * fixObsoleteModuleID(QDomDocument & domDocument, QDomElement & instance, QString & moduleIDRef); static bool isRatsnest(QDomElement & instance); static void checkTraces(QDomElement & instance); static void checkMystery(QDomElement & instance); static bool checkObsoleteOrientation(QDomElement & instance); static bool checkOldSchematics(QDomElement & instance); ModelPart * createOldSchematicPart(ModelPart *, QString & moduleIDRef); ModelPart * createOldSchematicPartAux(ModelPart *, const QString & oldModuleIDRef, const QString & oldSchematicFileName, const QString & oldSvgPath); protected: QPointer m_root; QPointer m_referenceModel; bool m_reportMissingModules; QString m_fritzingVersion; bool m_useOldSchematics; protected: static QList CoreList; }; #endif fritzing-app-0.9.2b/src/model/modelpart.cpp000066400000000000000000000705601250202676700206770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6956 $: $Author: irascibl@gmail.com $: $Date: 2013-04-07 12:14:50 +0200 (So, 07. Apr 2013) $ ********************************************************************/ #include "modelpart.h" #include "../debugdialog.h" #include "../connectors/connectorshared.h" #include "../connectors/busshared.h" #include "../connectors/bus.h" #include "../version/version.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../items/itembase.h" #include "../items/partfactory.h" #include #include long ModelPart::m_nextIndex = 0; const int ModelPart::indexMultiplier = 10; QStringList ModelPart::m_possibleFolders; typedef QHash InstanceTitleIncrementHash; static QHash AllInstanceTitleIncrements; InstanceTitleIncrementHash NullInstanceTitleIncrements; static const QRegExp InstanceTitleRegExp("^(.*[^\\d])(\\d+)$"); static const QList EmptyViewImages; //////////////////////////////////////// ModelPart::ModelPart(ItemType type) : QObject() { commonInit(type); m_modelPartShared = NULL; m_index = m_nextIndex++; } ModelPart::ModelPart(QDomDocument & domDocument, const QString & path, ItemType type) : QObject() { commonInit(type); m_modelPartShared = new ModelPartShared(domDocument, path); m_modelPartShared->addOwner(this); } void ModelPart::commonInit(ItemType type) { m_type = type; m_locationFlags = 0; m_indexSynched = false; } ModelPart::~ModelPart() { //DebugDialog::debug(QString("deleting modelpart %1 %2").arg((long) this, 0, 16).arg(m_index)); clearOldInstanceTitle(m_instanceTitle); InstanceTitleIncrementHash * itih = AllInstanceTitleIncrements.value(this); if (itih) { AllInstanceTitleIncrements.remove(this); foreach (ModelPartList * list, itih->values()) { delete list; } delete itih; } foreach (Connector * connector, m_connectorHash.values()) { delete connector; } m_connectorHash.clear(); clearBuses(); } const QString & ModelPart::moduleID() const { if (m_modelPartShared != NULL) return m_modelPartShared->moduleID(); return ___emptyString___; } const QString & ModelPart::label() { if (m_modelPartShared != NULL) return m_modelPartShared->label(); return ___emptyString___; } const QString & ModelPart::author() { if (m_modelPartShared != NULL) return m_modelPartShared->author(); return ___emptyString___; } const QString & ModelPart::taxonomy() { if (m_modelPartShared != NULL) return m_modelPartShared->taxonomy(); return ___emptyString___; } const QString & ModelPart::uri() { if (m_modelPartShared != NULL) return m_modelPartShared->uri(); return ___emptyString___; } const QDate & ModelPart::date() { if (m_modelPartShared != NULL) return m_modelPartShared->date(); static QDate tempDate; tempDate = QDate::currentDate(); return tempDate; } void ModelPart::setItemType(ItemType t) { m_type = t; } void ModelPart::copy(ModelPart * modelPart) { if (modelPart == NULL) return; m_type = modelPart->itemType(); m_modelPartShared = modelPart->modelPartShared(); if (m_modelPartShared) m_modelPartShared->addOwner(this); m_locationFlags = modelPart->m_locationFlags; } void ModelPart::copyNew(ModelPart * modelPart) { copy(modelPart); } void ModelPart::copyStuff(ModelPart * modelPart) { modelPartShared()->copy(modelPart->modelPartShared()); } ModelPartShared * ModelPart::modelPartShared() { if(!m_modelPartShared) { m_modelPartShared = new ModelPartShared(); m_modelPartShared->addOwner(this); } return m_modelPartShared; } ModelPartSharedRoot * ModelPart::modelPartSharedRoot() { return qobject_cast(m_modelPartShared); } void ModelPart::setModelPartShared(ModelPartShared * modelPartShared) { m_modelPartShared = modelPartShared; if (modelPartShared) m_modelPartShared->addOwner(this); } void ModelPart::addViewItem(ItemBase * item) { m_viewItems.append(item); } void ModelPart::removeViewItem(ItemBase * item) { m_viewItems.removeOne(item); } ItemBase * ModelPart::viewItem(QGraphicsScene * scene) { foreach (ItemBase * itemBase, m_viewItems) { if (itemBase->scene() == scene) return itemBase; } return NULL; } ItemBase * ModelPart::viewItem(ViewLayer::ViewID viewID) { foreach (ItemBase * itemBase, m_viewItems) { if (itemBase->viewID() == viewID) return itemBase; } return NULL; } void ModelPart::saveInstances(const QString & fileName, QXmlStreamWriter & streamWriter, bool startDocument) { if (startDocument) { streamWriter.writeStartDocument(); streamWriter.writeStartElement("module"); streamWriter.writeAttribute("fritzingVersion", Version::versionString()); ModelPartSharedRoot * root = modelPartSharedRoot(); if (root) { if (!root->icon().isEmpty()) { streamWriter.writeAttribute("icon", root->icon()); } if (!root->searchTerm().isEmpty()) { streamWriter.writeAttribute("search", root->searchTerm()); } } QString title = this->title(); if(!title.isNull() && !title.isEmpty()) { streamWriter.writeTextElement("title",title); } emit startSaveInstances(fileName, this, streamWriter); streamWriter.writeStartElement("instances"); } if (parent() != NULL) { // m_viewItems.size() > 0 saveInstance(streamWriter); } QList children = this->children(); if(m_orderedChildren.count() > 0) { children = m_orderedChildren; } QList::const_iterator i; for (i = children.constBegin(); i != children.constEnd(); ++i) { ModelPart* mp = qobject_cast(*i); if (mp == NULL) continue; mp->saveInstances(fileName, streamWriter, false); } if (startDocument) { streamWriter.writeEndElement(); // instances streamWriter.writeEndElement(); // module streamWriter.writeEndDocument(); } } void ModelPart::saveInstance(QXmlStreamWriter & streamWriter) { if (localProp("ratsnest").toBool()) { return; // don't save virtual wires } streamWriter.writeStartElement("instance"); if (m_modelPartShared != NULL) { QString moduleIdRef = m_modelPartShared->moduleID(); moduleIdRef.remove(PartFactory::OldSchematicPrefix); streamWriter.writeAttribute("moduleIdRef", moduleIdRef); streamWriter.writeAttribute("modelIndex", QString::number(m_index)); streamWriter.writeAttribute("path", m_modelPartShared->path()); if (m_modelPartShared->flippedSMD()) { streamWriter.writeAttribute("flippedSMD", "true"); } } bool writeLocal = false; foreach (Connector * connector, this->connectors()) { if (!connector->connectorLocalName().isEmpty()) { writeLocal = true; break; } } if (writeLocal) { streamWriter.writeStartElement("localConnectors"); foreach (Connector * connector, this->connectors()) { if (!connector->connectorLocalName().isEmpty()) { streamWriter.writeStartElement("localConnector"); streamWriter.writeAttribute("id", connector->connectorSharedID()); streamWriter.writeAttribute("name", TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(connector->connectorLocalName()))); streamWriter.writeEndElement(); } } streamWriter.writeEndElement(); } foreach (QByteArray byteArray, dynamicPropertyNames()) { streamWriter.writeStartElement("property"); streamWriter.writeAttribute("name", byteArray.data()); streamWriter.writeAttribute("value", property(byteArray.data()).toString()); streamWriter.writeEndElement(); } QString title = instanceTitle(); if(!title.isNull() && !title.isEmpty()) { writeTag(streamWriter,"title",title); } QString text = instanceText(); if(!text.isNull() && !text.isEmpty()) { streamWriter.writeStartElement("text"); streamWriter.writeCharacters(text); streamWriter.writeEndElement(); } // tell the views to write themselves out streamWriter.writeStartElement("views"); foreach (ItemBase * itemBase, m_viewItems) { itemBase->saveInstance(streamWriter); } streamWriter.writeEndElement(); // views streamWriter.writeEndElement(); //instance } void ModelPart::writeTag(QXmlStreamWriter & streamWriter, QString tagName, QString tagValue) { if(!tagValue.isEmpty()) { streamWriter.writeTextElement(tagName,tagValue); } } void ModelPart::writeNestedTag(QXmlStreamWriter & streamWriter, QString tagName, const QStringList &values, QString childTag) { if(values.count() > 0) { streamWriter.writeStartElement(tagName); for(int i=0; i &values, QString childTag, QString attrName) { streamWriter.writeStartElement(tagName); for(int i=0; imoduleID(); moduleID.remove(PartFactory::OldSchematicPrefix); streamWriter.writeAttribute("moduleId", moduleID); writeTag(streamWriter,"version",m_modelPartShared->version()); writeTag(streamWriter,"author",m_modelPartShared->author()); writeTag(streamWriter,"title",title()); writeTag(streamWriter,"label",m_modelPartShared->label()); writeTag(streamWriter,"date",m_modelPartShared->dateAsStr()); writeNestedTag(streamWriter,"tags",m_modelPartShared->tags(),"tag"); writeNestedTag(streamWriter,"properties",m_modelPartShared->properties(),"property","name"); writeTag(streamWriter,"taxonomy",m_modelPartShared->taxonomy()); writeTag(streamWriter,"description",m_modelPartShared->description()); QString spice = m_modelPartShared->spice(); if (!spice.isEmpty()) { streamWriter.writeStartElement("spice"); QStringList lines = spice.split("\r",QString::SkipEmptyParts); foreach (QString line, lines) { writeTag(streamWriter, "line", line); } QString spiceModel = m_modelPartShared->spiceModel(); if (!spiceModel.isEmpty()) { lines = spiceModel.split("\r",QString::SkipEmptyParts); foreach (QString line, lines) { writeTag(streamWriter, "model", line); } } streamWriter.writeEndElement(); } writeTag(streamWriter,"spice",m_modelPartShared->spice()); writeTag(streamWriter,"url",m_modelPartShared->url()); } if (m_viewItems.size() > 0) { if (startDocument) { streamWriter.writeStartElement("views"); } for (int i = 0; i < m_viewItems.size(); i++) { ItemBase * item = m_viewItems[i]; item->writeXml(streamWriter); } if(startDocument) { streamWriter.writeEndElement(); } streamWriter.writeStartElement("connectors"); const QList< QPointer > connectors = m_modelPartShared->connectorsShared(); for (int i = 0; i < connectors.count(); i++) { Connector * connector = new Connector(connectors[i], this); connector->saveAsPart(streamWriter); delete connector; } streamWriter.writeEndElement(); } QList::const_iterator i; for (i = children().constBegin(); i != children().constEnd(); ++i) { ModelPart * mp = qobject_cast(*i); if (mp == NULL) continue; mp->saveAsPart(streamWriter, false); } if (startDocument) { streamWriter.writeEndElement(); streamWriter.writeEndElement(); streamWriter.writeEndDocument(); } } void ModelPart::initConnectors(bool force) { if(m_modelPartShared == NULL) return; if(force) { foreach (Connector * connector, m_connectorHash.values()) { // due to craziness in the parts editor // m_deletedConnectors.append(connector); delete connector; } m_connectorHash.clear(); clearBuses(); } if(m_connectorHash.count() > 0) return; // already done m_modelPartShared->initConnectors(); foreach (ConnectorShared * connectorShared, m_modelPartShared->connectorsShared()) { Connector * connector = new Connector(connectorShared, this); m_connectorHash.insert(connectorShared->id(), connector); } initBuses(); } void ModelPart::clearBuses() { foreach (Bus * bus, m_busHash.values()) { delete bus; } m_busHash.clear(); } void ModelPart::initBuses() { foreach (Connector * connector, m_connectorHash.values()) { BusShared * busShared = connector->connectorShared()->bus(); if (busShared != NULL) { Bus * bus = m_busHash.value(busShared->id()); if (bus == NULL) { bus = new Bus(busShared, this); m_busHash.insert(busShared->id(), bus); } connector->setBus(bus); bus->addConnector(connector); } } } const QHash > & ModelPart::connectors() { return m_connectorHash; } long ModelPart::modelIndex() { return m_index; } void ModelPart::setModelIndex(long index) { m_index = index; updateIndex(index); } void ModelPart::setModelIndexFromMultiplied(long multiplied) { if (m_indexSynched) { // this is gross. m_index should always be itemBase->id() / ModelPart::indexMultiplier // but sometimes multiple parts reuse the same model part, so this makes sure we don't overwrite // when temporarily reusing a modelpart. Eventually always create a new model part and get rid of modelIndex if (m_index != multiplied / ModelPart::indexMultiplier) { //DebugDialog::debug("temporary model part?"); } return; } m_indexSynched = true; setModelIndex(multiplied / ModelPart::indexMultiplier); } void ModelPart::updateIndex(long index) { if (index >= m_nextIndex) { m_nextIndex = index + 1; } } long ModelPart::nextIndex() { return m_nextIndex++; } void ModelPart::setInstanceDomElement(const QDomElement & domElement) { //DebugDialog::debug(QString("model part instance %1").arg((long) this, 0, 16)); m_instanceDomElement = domElement; } const QDomElement & ModelPart::instanceDomElement() { return m_instanceDomElement; } const QString & ModelPart::fritzingVersion() { if (m_modelPartShared != NULL) return m_modelPartShared->fritzingVersion(); return ___emptyString___; } const QString & ModelPart::title() { if (!m_localTitle.isEmpty()) return m_localTitle; if (m_modelPartShared != NULL) return m_modelPartShared->title(); return m_localTitle; } void ModelPart::setLocalTitle(const QString & localTitle) { m_localTitle = localTitle; } const QString & ModelPart::version() { if (m_modelPartShared != NULL) return m_modelPartShared->version(); return ___emptyString___; } const QString & ModelPart::path() { if (m_modelPartShared != NULL) return m_modelPartShared->path(); return ___emptyString___; } const QString & ModelPart::description() { if (m_modelPartShared != NULL) return m_modelPartShared->description(); return ___emptyString___; } const QString & ModelPart::spice() { if (m_modelPartShared != NULL) return m_modelPartShared->spice(); return ___emptyString___; } const QString & ModelPart::spiceModel() { if (m_modelPartShared != NULL) return m_modelPartShared->spiceModel(); return ___emptyString___; } const QString & ModelPart::url() { if (m_modelPartShared != NULL) return m_modelPartShared->url(); return ___emptyString___; } const QStringList & ModelPart::tags() { if (m_modelPartShared != NULL) return m_modelPartShared->tags(); return ___emptyStringList___; } const QHash & ModelPart::properties() const { if (m_modelPartShared != NULL) return m_modelPartShared->properties(); return ___emptyStringHash___; } Connector * ModelPart::getConnector(const QString & id) { return m_connectorHash.value(id); } const QHash > & ModelPart::buses() { return m_busHash; } Bus * ModelPart::bus(const QString & busID) { return m_busHash.value(busID); } bool ModelPart::ignoreTerminalPoints() { if (m_modelPartShared != NULL) return m_modelPartShared->ignoreTerminalPoints(); return true; } bool ModelPart::isCore() { return (m_locationFlags & CoreFlag) != 0; } void ModelPart::setCore(bool core) { setLocationFlag(core, CoreFlag); } bool ModelPart::isContrib() { return (m_locationFlags & ContribFlag) != 0; } void ModelPart::setContrib(bool contrib) { setLocationFlag(contrib, ContribFlag); } bool ModelPart::isAlien() { return (m_locationFlags & AlienFlag) != 0;; } void ModelPart::setAlien(bool alien) { setLocationFlag(alien, AlienFlag); } bool ModelPart::isInBin() { return (m_locationFlags & InBinFlag) != 0;; } void ModelPart::setInBin(bool inBin) { setLocationFlag(inBin, InBinFlag); } bool ModelPart::isFzz() { return (m_locationFlags & FzzFlag) != 0;; } void ModelPart::setFzz(bool fzz) { setLocationFlag(fzz, FzzFlag); } void ModelPart::setLocationFlag(bool setting, LocationFlag flag) { if (setting) { m_locationFlags |= flag; } else { m_locationFlags &= ~flag; } } bool ModelPart::hasViewID(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->hasViewID(viewID); return false; } bool ModelPart::canFlipVertical(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->canFlipVertical(viewID); return false; } bool ModelPart::canFlipHorizontal(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->canFlipHorizontal(viewID); return false; } LayerList ModelPart::viewLayers(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->viewLayers(viewID); LayerList layerList; return layerList; } QString ModelPart::imageFileName(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->imageFileName(viewID); return ""; } QString ModelPart::imageFileName(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { if (m_modelPartShared) return m_modelPartShared->imageFileName(viewID, viewLayerID); return ""; } bool ModelPart::anySticky(ViewLayer::ViewID viewID) { if (m_modelPartShared) return m_modelPartShared->anySticky(viewID); return false; } QList ModelPart::getAllParts() { QList retval; QList::const_iterator i; for (i = children().constBegin(); i != children().constEnd(); ++i) { ModelPart* mp = qobject_cast(*i); if (mp == NULL) continue; retval << mp; } return retval; } QList ModelPart::getAllNonCoreParts() { QList retval; QList::const_iterator i; for (i = children().constBegin(); i != children().constEnd(); ++i) { ModelPart* mp = qobject_cast(*i); if (mp == NULL) continue; if(!mp->isCore()) { retval << mp; } } return retval; } bool ModelPart::hasViewID(long id) { foreach (ItemBase * item, m_viewItems) { if (item->id() == id) return true; } return false; } const QString & ModelPart::instanceTitle() const { return m_instanceTitle; } const QString & ModelPart::instanceText() { return m_instanceText; } void ModelPart::setInstanceText(QString text) { m_instanceText = text; } void ModelPart::clearOldInstanceTitle(const QString & title) { InstanceTitleIncrementHash * itih = NULL; if (parent() == NULL) { itih = &NullInstanceTitleIncrements; } else { itih = AllInstanceTitleIncrements.value(parent(), NULL); } if (itih == NULL) return; //DebugDialog::debug(QString("clearing title:%1 ix:%2").arg(title).arg(modelPart->modelIndex())); QString prefix = title; int ix = InstanceTitleRegExp.indexIn(title); if (ix >= 0) { prefix = InstanceTitleRegExp.cap(1); } ModelPartList * modelParts = itih->value(prefix, NULL); if (modelParts) { modelParts->removeOne(this); //DebugDialog::debug(QString("\tc:%1").arg(modelParts->count())); } } ModelPartList * ModelPart::ensureInstanceTitleIncrements(const QString & prefix) { InstanceTitleIncrementHash * itih = NULL; if (parent() == NULL) { itih = &NullInstanceTitleIncrements; } else { itih = AllInstanceTitleIncrements.value(parent(), NULL); if (itih == NULL) { itih = new InstanceTitleIncrementHash; AllInstanceTitleIncrements.insert(parent(), itih); } } ModelPartList * modelParts = itih->value(prefix, NULL); if (modelParts == NULL) { modelParts = new ModelPartList; itih->insert(prefix, modelParts); } return modelParts; } void ModelPart::setInstanceTitle(QString title, bool initial) { if (initial) { if (setSubpartInstanceTitle()) return; } if (title.compare(m_instanceTitle) == 0) return; clearOldInstanceTitle(m_instanceTitle); m_instanceTitle = title; QString prefix = title; int ix = InstanceTitleRegExp.indexIn(title); if (ix >= 0) { prefix = InstanceTitleRegExp.cap(1); ModelPartList * modelParts = ensureInstanceTitleIncrements(prefix); modelParts->append(this); } //DebugDialog::debug(QString("adding title:%1 ix:%2 c:%3").arg(title).arg(modelIndex()).arg(modelParts->count())); if (m_modelPartShared && m_modelPartShared->hasSubparts()) { if (m_viewItems.count() > 0) { ItemBase * itemBase = m_viewItems.last(); if (itemBase) { foreach (ItemBase * subpart, itemBase->subparts()) { subpart->setInstanceTitle("", true); // will end up calling setSubpartInstanceTitle() } } } } } bool ModelPart::setSubpartInstanceTitle() { if (m_modelPartShared == NULL) return false; if (m_modelPartShared->superpart() == NULL) return false; if (m_viewItems.count() <= 0) return false; ItemBase * itemBase = m_viewItems.last(); if (itemBase == NULL) return false; itemBase = itemBase->superpart(); if (itemBase == NULL) return false; QString superTitle = itemBase->instanceTitle(); if (superTitle.isEmpty()) return false; QString label = m_modelPartShared->label(); if (label.isEmpty()) return false; m_instanceTitle = superTitle + "_" + label; return true; } QString ModelPart::getNextTitle(const QString & title) { QString prefix = title; int ix = InstanceTitleRegExp.indexIn(title); if (ix >= 0) { prefix = InstanceTitleRegExp.cap(1); } else { bool allDigits = true; foreach (QChar c, title) { if (!c.isDigit()) { allDigits = false; break; } } if (allDigits) { return title; } } // TODO: if this were a sorted list, ModelPartList * modelParts = ensureInstanceTitleIncrements(prefix); int highestSoFar = 0; bool gotNull = false; foreach (ModelPart * modelPart, *modelParts) { if (modelPart == NULL) { gotNull = true; continue; } QString title = modelPart->instanceTitle(); title.remove(0, prefix.length()); int count = title.toInt(); // returns zero on failure if (count > highestSoFar) { highestSoFar = count; } } if (gotNull) { modelParts->removeAll(NULL); } //DebugDialog::debug(QString("returning increment %1, %2").arg(prefix).arg(highestSoFar + 1)); return QString("%1%2").arg(prefix).arg(highestSoFar + 1); } void ModelPart::setOrderedChildren(QList children) { m_orderedChildren = children; } void ModelPart::setLocalProp(const char * name, const QVariant & value) { //DebugDialog::debug(QString("mp set prop %1 %2").arg(name).arg(value.toString())); QObject::setProperty(name, value); } QVariant ModelPart::localProp(const char * name) const { return property(name); } void ModelPart::setLocalProp(const QString & name, const QVariant & value) { QByteArray b = name.toLatin1(); setLocalProp(b.data(), value); } QVariant ModelPart::localProp(const QString & name) const { QByteArray b = name.toLatin1(); return localProp(b.data()); } const QStringList & ModelPart::possibleFolders() { if (m_possibleFolders.count() == 0) { m_possibleFolders << "core" << "obsolete" << "contrib" << "user"; } return m_possibleFolders; } const QString & ModelPart::replacedby() { if (m_modelPartShared != NULL) return m_modelPartShared->replacedby(); return ___emptyString___; } bool ModelPart::isObsolete() { if (m_modelPartShared != NULL) return !m_modelPartShared->replacedby().isEmpty(); return false; } bool ModelPart::flippedSMD() { if (m_modelPartShared != NULL) { return m_modelPartShared->flippedSMD(); } return false; } bool ModelPart::needsCopper1() { if (m_modelPartShared != NULL) { return m_modelPartShared->needsCopper1(); } return false; } bool ModelPart::hasViewFor(ViewLayer::ViewID viewID) { if (m_modelPartShared == NULL) return false; return m_modelPartShared->hasViewFor(viewID); } bool ModelPart::hasViewFor(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { if (m_modelPartShared == NULL) return false; return m_modelPartShared->hasViewFor(viewID, viewLayerID); } QString ModelPart::hasBaseNameFor(ViewLayer::ViewID viewID) { if (m_modelPartShared == NULL) return ___emptyString___; return m_modelPartShared->hasBaseNameFor(viewID); } const QStringList & ModelPart::displayKeys() { if (m_modelPartShared == NULL) return ___emptyStringList___; return m_modelPartShared->displayKeys(); } ModelPart::ItemType ModelPart::itemType() const { return m_type; }; void ModelPart::setConnectorLocalName(const QString & id, const QString & name) { if (id.isEmpty()) return; Connector * connector = m_connectorHash.value(id, NULL); if (connector) { connector->setConnectorLocalName(name); } } QString ModelPart::connectorLocalName(const QString & id) { if (id.isEmpty()) return ""; Connector * connector = m_connectorHash.value(id, NULL); if (connector) { return connector->connectorLocalName(); } return ""; } QString ModelPart::family(){ if (m_modelPartShared) return m_modelPartShared->family(); return ""; } bool ModelPart::hasViewItems() { return (m_viewItems.count() > 0); } void ModelPart::setDBID(qulonglong dbid) { if (m_modelPartShared) m_modelPartShared->setDBID(dbid); } qulonglong ModelPart::dbid() { if (m_modelPartShared) return m_modelPartShared->dbid(); return 0; } const QList ModelPart::viewImages() { if (m_modelPartShared) return m_modelPartShared->viewImages(); return EmptyViewImages; } void ModelPart::setViewImage(ViewImage * viewImage) { if (m_modelPartShared) m_modelPartShared->setViewImage(viewImage); } void ModelPart::setTag(const QString & tag) { if (m_modelPartShared) m_modelPartShared->setTag(tag); } void ModelPart::setProperty(const QString & name, const QString &value, bool showInLabel) { if (m_modelPartShared) m_modelPartShared->setProperty(name, value, showInLabel); } bool ModelPart::showInLabel(const QString & propertyName) { if (m_modelPartShared) return m_modelPartShared->showInLabel(propertyName); return false; } void ModelPart::addConnector(Connector * connector) { m_connectorHash.insert(connector->connectorSharedID(), connector); if (m_modelPartShared) m_modelPartShared->addConnector(connector->connectorShared()); } void ModelPart::flipSMDAnd() { if (m_modelPartShared) m_modelPartShared->flipSMDAnd(); } void ModelPart::setImageFileName(ViewLayer::ViewID viewID, const QString & filename) { if (m_modelPartShared) m_modelPartShared->setImageFileName(viewID, filename); } void ModelPart::lookForZeroConnector() { if (m_modelPartShared) m_modelPartShared->lookForZeroConnector(); } bool ModelPart::hasZeroConnector() { if (m_modelPartShared) return m_modelPartShared->hasZeroConnector(); return false; } void ModelPart::killViewItems() { foreach (ItemBase * itemBase, m_viewItems) { if (itemBase) delete itemBase; } m_viewItems.clear(); } bool ModelPart::hasSubparts() { if (m_modelPartShared) return m_modelPartShared->hasSubparts(); return false; } void ModelPart::setSubpartID(const QString & id) { if (m_modelPartShared) m_modelPartShared->setSubpartID(id); } fritzing-app-0.9.2b/src/model/modelpart.h000066400000000000000000000167701250202676700203470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6956 $: $Author: irascibl@gmail.com $: $Date: 2013-04-07 12:14:50 +0200 (So, 07. Apr 2013) $ ********************************************************************/ #ifndef MODELPART_H #define MODELPART_H #include #include #include #include #include #include #include #include #include #include #include #include "modelpartshared.h" #include "../connectors/connector.h" #include "../connectors/bus.h" class ModelPart : public QObject { Q_OBJECT public: enum ItemType { Part, Wire, Breadboard, Board, ResizableBoard, Note, Symbol, Jumper, CopperFill, Logo, Hole, Via, Ruler, SchematicSubpart, Space, Unknown }; enum LocationFlag { NoFlag = 0, CoreFlag = 1, ContribFlag = 2, AlienFlag = 4, FzzFlag = 8, InBinFlag = 16 }; Q_DECLARE_FLAGS(LocationFlags, LocationFlag) public: ModelPart(QDomDocument &, const QString& path, ItemType type); ModelPart(ItemType type = ModelPart::Unknown); ~ModelPart(); ModelPart::ItemType itemType() const; void setItemType(ItemType); const QString & moduleID() const; void copy(ModelPart *); void copyNew(ModelPart *); void copyStuff(ModelPart * modelPart); ModelPartShared * modelPartShared(); ModelPartSharedRoot * modelPartSharedRoot(); void setModelPartShared(ModelPartShared *modelPartShared); void saveInstances(const QString & fileName, QXmlStreamWriter & streamWriter, bool startDocument); void saveAsPart(QXmlStreamWriter & streamWriter, bool startDocument); void addViewItem(class ItemBase *); void removeViewItem(class ItemBase *); void killViewItems(); class ItemBase * viewItem(QGraphicsScene * scene); class ItemBase * viewItem(ViewLayer::ViewID); bool hasViewItems(); void initConnectors(bool force=false); const QHash > & connectors(); long modelIndex(); void setModelIndex(long index); void setModelIndexFromMultiplied(long multipliedIndex); void setInstanceDomElement(const QDomElement &); const QDomElement & instanceDomElement(); Connector * getConnector(const QString & id); const QString & fritzingVersion(); const QString & title(); const QString & description(); const QString & spice(); const QString & spiceModel(); const QString & url(); const QStringList & tags(); const QStringList & displayKeys(); const QHash & properties() const; const QHash > & buses(); const QString & taxonomy(); const QString & version(); const QString & path(); const QString & label(); const QString & author(); const QString & language(); const QString & uri(); const QDate & date(); QString family(); void setDBID(qulonglong); qulonglong dbid(); Bus * bus(const QString & busID); bool ignoreTerminalPoints(); bool isCore(); void setCore(bool core); bool isContrib(); void setContrib(bool contrib); bool isAlien(); // from "outside" void setAlien(bool alien); bool isFzz(); // from "outside" void setFzz(bool alien); void setLocationFlag(bool setting, LocationFlag flag); bool isInBin(); void setInBin(bool); bool hasViewID(ViewLayer::ViewID); bool canFlipVertical(ViewLayer::ViewID); bool canFlipHorizontal(ViewLayer::ViewID); bool anySticky(ViewLayer::ViewID); QString imageFileName(ViewLayer::ViewID); void setImageFileName(ViewLayer::ViewID, const QString & filename); QString imageFileName(ViewLayer::ViewID, ViewLayer::ViewLayerID); LayerList viewLayers(ViewLayer::ViewID); void setViewImage(struct ViewImage *); QList getAllParts(); QList getAllNonCoreParts(); bool hasViewID(long id); const QString & instanceTitle() const; const QString & instanceText(); void setInstanceTitle(QString, bool initial); void setInstanceText(QString); QString getNextTitle(const QString & candidate); void setOrderedChildren(QList children); void setLocalProp(const QString & name, const QVariant & value); QVariant localProp(const QString & name) const; void setLocalProp(const char * name, const QVariant & value); QVariant localProp(const char * name) const; void setTag(const QString &tag); void setProperty(const QString & key, const QString & value, bool showInLabel); bool showInLabel(const QString & key); const QString & replacedby(); bool isObsolete(); bool flippedSMD(); bool needsCopper1(); bool hasViewFor(ViewLayer::ViewID); bool hasViewFor(ViewLayer::ViewID, ViewLayer::ViewLayerID); QString hasBaseNameFor(ViewLayer::ViewID); void initBuses(); void clearBuses(); void setConnectorLocalName(const QString & id, const QString & name); QString connectorLocalName(const QString & id); void setLocalTitle(const QString &); const QList viewImages(); void addConnector(Connector *); void flipSMDAnd(); void lookForZeroConnector(); bool hasZeroConnector(); bool hasSubparts(); void setSubpartID(const QString &); public: static long nextIndex(); static void updateIndex(long index); static const int indexMultiplier; static const QStringList & possibleFolders(); signals: void startSaveInstances(const QString & fileName, ModelPart *, QXmlStreamWriter &); protected: void writeTag(QXmlStreamWriter & streamWriter, QString tagName, QString tagValue); void writeNestedTag(QXmlStreamWriter & streamWriter, QString tagName, const QStringList &values, QString childTag); void writeNestedTag(QXmlStreamWriter & streamWriter, QString tagName, const QHash &values, QString childTag, QString attrName); void commonInit(ItemType type); void saveInstance(QXmlStreamWriter & streamWriter); QList< QPointer > * ensureInstanceTitleIncrements(const QString & prefix); void clearOldInstanceTitle(const QString & title); bool setSubpartInstanceTitle(); protected: QList< QPointer > m_viewItems; ItemType m_type; QPointer m_modelPartShared; QHash > m_connectorHash; QHash > m_busHash; long m_index; // only used at save time to identify model parts in the xml QDomElement m_instanceDomElement; // only used at load time (so far) LocationFlags m_locationFlags; bool m_indexSynched; QString m_instanceTitle; QString m_instanceText; QString m_localTitle; QList m_orderedChildren; protected: static QHash itemTypeNames; static long m_nextIndex; static QStringList m_possibleFolders; }; Q_DECLARE_METATYPE( ModelPart* ); // so we can stash them in a QVariant typedef QList< QPointer > ModelPartList; Q_DECLARE_OPERATORS_FOR_FLAGS(ModelPart::LocationFlags) #endif fritzing-app-0.9.2b/src/model/modelpartshared.cpp000066400000000000000000000604671250202676700220730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #include "modelpartshared.h" #include "../connectors/connectorshared.h" #include "../debugdialog.h" #include "../connectors/busshared.h" #include #include #include void copyPinAttributes(QDomElement & from, QDomElement & to) { to.setAttribute("svgId", from.attribute("svgId")); QString terminalId = from.attribute("terminalId"); if (!terminalId.isEmpty()) { to.setAttribute("terminalId", terminalId); } QString hybrid = from.attribute("hybrid"); if (!hybrid.isEmpty()) { to.setAttribute("hybrid", hybrid); } QString legId = from.attribute("legId"); if (!legId.isEmpty()) { to.setAttribute("legId", legId); } } /////////////////////////////////////////////// ViewImage::ViewImage(ViewLayer::ViewID vi) { flipped = sticky = layers = 0; canFlipVertical = canFlipHorizontal = false; viewID = vi; } /////////////////////////////////////////////// const QString & ModelPartSharedRoot::icon() { return m_icon; } void ModelPartSharedRoot::setIcon(const QString & filename) { m_icon = filename; } const QString & ModelPartSharedRoot::searchTerm() { return m_searchTerm; } void ModelPartSharedRoot::setSearchTerm(const QString & searchTerm) { m_searchTerm = searchTerm; } /////////////////////////////////////////////// const QString ModelPartShared::PartNumberPropertyName = "part number"; ModelPartShared::ModelPartShared() { commonInit(); m_path = ""; } ModelPartShared::ModelPartShared(QDomDocument & domDocument, const QString & path) { commonInit(); m_path = path; setDomDocument(domDocument); } void ModelPartShared::commonInit() { m_moduleID = ""; m_dbid = 0; m_ownerCount = 0; m_hasZeroConnector = m_flippedSMD = m_connectorsInitialized = m_ignoreTerminalPoints = m_needsCopper1 = false; m_superpart = NULL; } ModelPartShared::~ModelPartShared() { foreach (ConnectorShared * connectorShared, m_connectorSharedHash.values()) { delete connectorShared; } m_connectorSharedHash.clear(); foreach (ViewImage * viewImage, m_viewImages.values()) { delete viewImage; } m_viewImages.clear(); foreach (BusShared * busShared, m_buses.values()) { delete busShared; } m_buses.clear(); } bool ModelPartShared::setDomDocument(QDomDocument & domDocument) { static qulonglong one = 1; QDomElement root = domDocument.documentElement(); if (root.isNull()) { return false; } if (root.tagName() != "module") { return false; } loadTagText(root, "title", m_title); loadTagText(root, "label", m_label); loadTagText(root, "version", m_version); loadTagText(root, "author", m_author); loadTagText(root, "description", m_description); loadTagText(root, "url", m_url); loadTagText(root, "taxonomy", m_taxonomy); loadTagText(root, "date", m_date); QDomElement version = root.firstChildElement("version"); if (!version.isNull()) { m_replacedby = version.attribute("replacedby"); } QDomElement spice = root.firstChildElement("spice"); QDomElement line = spice.firstChildElement("line"); while (!line.isNull()) { m_spice += line.text(); m_spice += "\n"; line = line.nextSiblingElement("line"); } QDomElement model = spice.firstChildElement("model"); while (!model.isNull()) { m_spiceModel += model.text(); m_spiceModel += "\n"; model = model.nextSiblingElement("model"); } populateTags(root, m_tags); populateProperties(root, m_properties, m_displayKeys); //foreach (QString key, m_displayKeys) { // DebugDialog::debug("set display " + m_moduleID + " " + key); //} ensurePartNumberProperty(); m_moduleID = root.attribute("moduleId", ""); m_fritzingVersion = root.attribute("fritzingVersion", ""); QDomElement views = root.firstChildElement("views"); if (!views.isNull()) { QDomElement view = views.firstChildElement(); while (!view.isNull()) { ViewLayer::ViewID viewID = ViewLayer::idFromXmlName(view.nodeName()); ViewImage * viewImage = new ViewImage(viewID); m_viewImages.insert(viewID, viewImage); viewImage->canFlipHorizontal = view.attribute("fliphorizontal","").compare("true") == 0; viewImage->canFlipVertical = view.attribute("flipvertical","").compare("true") == 0; QDomElement layers = view.firstChildElement("layers"); if (!layers.isNull()) { viewImage->image = layers.attribute("image", ""); QDomElement layer = layers.firstChildElement("layer"); while (!layer.isNull()) { ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(layer.attribute("layerId")); qulonglong sticky = (layer.attribute("sticky", "").compare("true") == 0) ? 1 : 0; viewImage->layers |= (one << viewLayerID); viewImage->sticky |= (sticky << viewLayerID); layer = layer.nextSiblingElement("layer"); } } addSchematicText(viewImage); view = view.nextSiblingElement(); } } return true; } void ModelPartShared::loadTagText(QDomElement parent, QString tagName, QString &field) { QDomElement tagElement = parent.firstChildElement(tagName); if (!tagElement.isNull()) { field = tagElement.text(); } } void ModelPartShared::populateTags(QDomElement parent, QStringList &list) { QDomElement tags = parent.firstChildElement("tags"); QDomElement tag = tags.firstChildElement("tag"); while (!tag.isNull()) { list << tag.text(); tag = tag.nextSiblingElement("tag"); } } void ModelPartShared::populateProperties(QDomElement parent, QHash &hash, QStringList & displayKeys) { QDomElement properties = parent.firstChildElement("properties"); QDomElement prop = properties.firstChildElement("property"); while (!prop.isNull()) { QString name = prop.attribute("name"); QString value = prop.text(); hash.insert(name.toLower().trimmed(),value); if (prop.attribute("showInLabel", "").compare("yes", Qt::CaseInsensitive) == 0) { displayKeys.append(name); } prop = prop.nextSiblingElement("property"); } } const QString & ModelPartShared::title() { return m_title; } void ModelPartShared::setTitle(QString title) { m_title = title; } const QString & ModelPartShared::label() const { return m_label; } void ModelPartShared::setLabel(QString label) { m_label = label; } const QString & ModelPartShared::uri() { return m_uri; } void ModelPartShared::setUri(QString uri) { m_uri = uri; } const QString & ModelPartShared::version() { return m_version; } void ModelPartShared::setVersion(QString version) { m_version = version; } const QString & ModelPartShared::author() { return m_author; } void ModelPartShared::setAuthor(QString author) { m_author = author; } const QString & ModelPartShared::description() { return m_description; } const QString & ModelPartShared::url() { return m_url; } const QString & ModelPartShared::spice() { return m_spice; } const QString & ModelPartShared::spiceModel() { return m_spiceModel; } void ModelPartShared::setDescription(QString description) { m_description = description; } void ModelPartShared::setSpice(QString spice) { m_spice = spice; } void ModelPartShared::setSpiceModel(QString model) { m_spiceModel = model; } void ModelPartShared::setUrl(QString url) { m_url = url; } const QDate & ModelPartShared::date() { // return *new QDate(QDate::fromString(m_date,Qt::ISODate)); // causes memory leak static QDate tempDate; tempDate = QDate::fromString(m_date,Qt::ISODate); return tempDate; } void ModelPartShared::setDate(QDate date) { m_date = date.toString(Qt::ISODate); } const QString & ModelPartShared::dateAsStr() { return m_date; } void ModelPartShared::setDate(QString date) { m_date = date; } const QStringList & ModelPartShared::tags() { return m_tags; } void ModelPartShared::setTags(const QStringList &tags) { m_tags = tags; } void ModelPartShared::setTag(const QString &tag) { m_tags.append(tag); } QString ModelPartShared::family() { return m_properties.value("family"); } void ModelPartShared::setFamily(const QString &family) { m_properties.insert("family",family); } QHash & ModelPartShared::properties() { return m_properties; } void ModelPartShared::setProperties(const QHash &properties) { m_properties = properties; ensurePartNumberProperty(); } const QString & ModelPartShared::path() { return m_path; } void ModelPartShared::setPath(QString path) { m_path = path; } const QString & ModelPartShared::taxonomy() { return m_taxonomy; } void ModelPartShared::setTaxonomy(QString taxonomy) { m_taxonomy = taxonomy; } const QString & ModelPartShared::moduleID() { return m_moduleID; } void ModelPartShared::setModuleID(QString moduleID) { m_moduleID = moduleID; } const QList< QPointer > ModelPartShared::connectorsShared() { return m_connectorSharedHash.values(); } void ModelPartShared::setConnectorsShared(QList< QPointer > connectors) { for (int i = 0; i < connectors.size(); i++) { ConnectorShared* cs = connectors[i]; m_connectorSharedHash[cs->id()] = cs; } } void ModelPartShared::setConnectorsInitialized(bool init) { m_connectorsInitialized = init; } void ModelPartShared::initConnectors() { if (m_connectorsInitialized) return; QFile file(m_path); QString errorStr; int errorLine; int errorColumn; QDomDocument doc; doc.setContent(&file, &errorStr, &errorLine, &errorColumn); m_connectorsInitialized = true; QDomElement root = doc.documentElement(); if (root.isNull()) { return; } QDomElement connectors = root.firstChildElement("connectors"); if (connectors.isNull()) return; m_ignoreTerminalPoints = (connectors.attribute("ignoreTerminalPoints").compare("true", Qt::CaseInsensitive) == 0); //DebugDialog::debug(QString("part:%1 %2").arg(m_moduleID).arg(m_title)); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { ConnectorShared * connectorShared = new ConnectorShared(connector); m_connectorSharedHash.insert(connectorShared->id(), connectorShared); connector = connector.nextSiblingElement("connector"); } lookForZeroConnector(); QDomElement buses = root.firstChildElement("buses"); if (!buses.isNull()) { QDomElement busElement = buses.firstChildElement("bus"); while (!busElement.isNull()) { BusShared * busShared = new BusShared(busElement, m_connectorSharedHash); m_buses.insert(busShared->id(), busShared); busElement = busElement.nextSiblingElement("bus"); } } //DebugDialog::debug(QString("model %1 has %2 connectors and %3 bus connectors").arg(this->title()).arg(m_connectorSharedHash.count()).arg(m_buses.count()) ); } ConnectorShared * ModelPartShared::getConnectorShared(const QString & id) { return m_connectorSharedHash.value(id); } bool ModelPartShared::ignoreTerminalPoints() { return m_ignoreTerminalPoints; } void ModelPartShared::copy(ModelPartShared* other) { setAuthor(other->author()); setConnectorsShared(other->connectorsShared()); setDate(other->date()); setLabel(other->label()); setDescription(other->description()); setSpice(other->spice()); setSpiceModel(other->spiceModel()); setUrl(other->url()); setFamily(other->family()); setProperties(other->properties()); setTags(other->tags()); setTaxonomy(other->taxonomy()); setTitle(other->title()); setUri(other->uri()); setVersion(other->version()); setSuperpart(other->superpart()); foreach (ViewLayer::ViewID viewID, other->m_viewImages.keys()) { ViewImage * otherViewImage = other->m_viewImages.value(viewID); ViewImage * viewImage = new ViewImage(viewID); viewImage->layers = otherViewImage->layers; viewImage->sticky = otherViewImage->sticky; viewImage->canFlipHorizontal = otherViewImage->canFlipHorizontal; viewImage->canFlipVertical = otherViewImage->canFlipVertical; viewImage->image = otherViewImage->image; m_viewImages.insert(viewID, viewImage); } } void ModelPartShared::setProperty(const QString & key, const QString & value, bool showInLabel) { m_properties.insert(key, value); if (showInLabel) { m_displayKeys.append(key); } } const QString & ModelPartShared::replacedby() { return m_replacedby; } void ModelPartShared::setReplacedby(const QString & replacedby) { m_replacedby = replacedby; } void ModelPartShared::setFlippedSMD(bool f) { m_flippedSMD = f; } bool ModelPartShared::flippedSMD() { return m_flippedSMD; } bool ModelPartShared::needsCopper1() { return m_needsCopper1; } void ModelPartShared::connectorIDs(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID, QStringList & connectorIDs, QStringList & terminalIDs, QStringList & legIDs) { foreach (ConnectorShared * connectorShared, m_connectorSharedHash.values()) { SvgIdLayer * svgIdLayer = connectorShared->fullPinInfo(viewID, viewLayerID); if (svgIdLayer == NULL) { continue; } else { connectorIDs.append(svgIdLayer->m_svgId); terminalIDs.append(svgIdLayer->m_terminalId); legIDs.append(svgIdLayer->m_legId); } } } void ModelPartShared::flipSMDAnd() { if (this->path().startsWith(ResourcePath)) { // assume resources are set up exactly as intended //DebugDialog::debug(QString("skip flip %1").arg(path())); return; } static qulonglong one = 1; ViewImage * viewImage = m_viewImages.value(ViewLayer::PCBView); // needs to be called after initConnectors() LayerList layerList = viewLayers(ViewLayer::PCBView); if (layerList.isEmpty()) return; if (!layerList.contains(ViewLayer::Copper0) && !layerList.contains(ViewLayer::Copper1)) { return; } if (layerList.contains(ViewLayer::Copper0)) { // THT here if (!layerList.contains(ViewLayer::Copper1)) { // fill in missing copper1 layer m_needsCopper1 = true; viewImage->layers |= (one << ViewLayer::Copper1); copyPins(ViewLayer::Copper0, ViewLayer::Copper1); } // prep for placing on the bottom if (layerList.contains(ViewLayer::Silkscreen1) && !layerList.contains(ViewLayer::Silkscreen0)) { //DebugDialog::debug(QString("silk0 %1 %2").arg(this->title()).arg(this->moduleID())); viewImage->layers |= (one << ViewLayer::Silkscreen0); layerList << ViewLayer::Silkscreen0; } if (layerList.contains(ViewLayer::Silkscreen0)) { viewImage->flipped |= (one << ViewLayer::Silkscreen0); } // swap layer for any tht part if (!m_properties.keys().contains("layer")) { // used for swapping part from copper1 to copper0 m_properties.insert("layer", ""); } return; } setFlippedSMD(true); // DebugDialog::debug("set flipped smd " + moduleID()); if (!m_properties.keys().contains("layer")) { // used for swapping part from copper1 to copper0 m_properties.insert("layer", ""); } if (!layerList.contains(ViewLayer::Copper0)) { viewImage->layers |= (one << ViewLayer::Copper0); } viewImage->flipped |= (one << ViewLayer::Copper0); if (layerList.contains(ViewLayer::Silkscreen1) && !layerList.contains(ViewLayer::Silkscreen0)) { viewImage->layers |= (one << ViewLayer::Silkscreen0); layerList << ViewLayer::Silkscreen0; } if (layerList.contains(ViewLayer::Silkscreen0)) { viewImage->flipped |= (one << ViewLayer::Silkscreen0); } //if (this->moduleID() == "df9d072afa2b594ac67b60b4153ff57b_29") { // DebugDialog::debug("alive in here"); //} copyPins(ViewLayer::Copper1, ViewLayer::Copper0); } bool ModelPartShared::hasViewFor(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID, NULL); if (viewImage == NULL) return false; return viewImage->layers != 0; } bool ModelPartShared::hasViewFor(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { ViewImage * viewImage = m_viewImages.value(viewID, NULL); if (viewImage == NULL) return false; qulonglong one = 1; return (viewImage->layers & (one << viewLayerID)) != 0; } QString ModelPartShared::hasBaseNameFor(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID, NULL); if (viewImage == NULL) return ""; return viewImage->image; } const QStringList & ModelPartShared::displayKeys() { return m_displayKeys; } void ModelPartShared::ensurePartNumberProperty() { if (!m_properties.keys().contains(PartNumberPropertyName)) { m_properties.insert(PartNumberPropertyName, ""); m_displayKeys.append(PartNumberPropertyName); } } void ModelPartShared::setDBID(qulonglong dbid) { m_dbid = dbid; } qulonglong ModelPartShared::dbid() { return m_dbid; } const QString & ModelPartShared::fritzingVersion() { return m_fritzingVersion; } void ModelPartShared::setFritzingVersion(const QString & fv) { m_fritzingVersion = fv; } void ModelPartShared::setViewImage(ViewImage * viewImage) { ViewImage * old = m_viewImages.value(viewImage->viewID); if (old) delete old; m_viewImages.insert(viewImage->viewID, viewImage); addSchematicText(viewImage); } const QList ModelPartShared::viewImages() { return m_viewImages.values(); } QString ModelPartShared::imageFileName(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return ""; qulonglong one = 1; if ((viewImage->layers & (one << viewLayerID)) == 0) return ""; // DebugDialog::debug(QString("image filename %1 %2 %3").arg(viewImage->image).arg(viewID).arg(viewLayerID)); return viewImage->image; } QString ModelPartShared::imageFileName(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return ""; return viewImage->image; } void ModelPartShared::setImageFileName(ViewLayer::ViewID viewID, const QString & filename) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return; viewImage->image = filename; } bool ModelPartShared::hasViewID(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return false; return viewImage->layers != 0; } bool ModelPartShared::hasMultipleLayers(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return false; // http://eli.thegreenplace.net/2004/07/30/a-cool-algorithm-for-counting-ones-in-a-bitstring/ qulonglong layers = viewImage->layers; return ((layers & (layers - 1)) != 0); } qulonglong layers(ViewImage * viewImage) { return viewImage->layers; } qulonglong flipped(ViewImage * viewImage) { return viewImage->flipped; } LayerList ModelPartShared::viewLayersFlipped(ViewLayer::ViewID viewID) { return viewLayersAux(viewID, flipped); } LayerList ModelPartShared::viewLayers(ViewLayer::ViewID viewID) { return viewLayersAux(viewID, layers); } LayerList ModelPartShared::viewLayersAux(ViewLayer::ViewID viewID, qulonglong (*accessor)(ViewImage *)) { static QHash ToLayerIDs; LayerList layerList; ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return layerList; // http://eli.thegreenplace.net/2004/07/30/a-cool-algorithm-for-counting-ones-in-a-bitstring/ if (ToLayerIDs.isEmpty()) { qulonglong one = 1; for (int ix = 0; ix < ViewLayer::ViewLayerCount; ix++) { ToLayerIDs.insert(one, (ViewLayer::ViewLayerID) ix); one = one << 1; } } qulonglong layers = accessor(viewImage); while (layers) { qulonglong removeLeast = layers & (layers - 1); qulonglong diff = layers - removeLeast; layerList << ToLayerIDs.value(diff); layers = removeLeast; } return layerList; } bool ModelPartShared::canFlipHorizontal(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return false; return viewImage->canFlipHorizontal; } bool ModelPartShared::canFlipVertical(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return false; return viewImage->canFlipVertical; } bool ModelPartShared::anySticky(ViewLayer::ViewID viewID) { ViewImage * viewImage = m_viewImages.value(viewID); if (viewImage == NULL) return false; return (viewImage->sticky != 0); } void ModelPartShared::addConnector(ConnectorShared * connectorShared) { m_connectorSharedHash.insert(connectorShared->id(), connectorShared); } void ModelPartShared::copyPins(ViewLayer::ViewLayerID from, ViewLayer::ViewLayerID to) { foreach (ConnectorShared * connectorShared, m_connectorSharedHash.values()) { SvgIdLayer * svgIdLayer = connectorShared->fullPinInfo(ViewLayer::PCBView, to); if (svgIdLayer) { // already there continue; } svgIdLayer = connectorShared->fullPinInfo(ViewLayer::PCBView, from); if (svgIdLayer == NULL) { DebugDialog::debug(QString("missing connector in %1").arg(moduleID())); continue; } SvgIdLayer * newSvgIdLayer = svgIdLayer->copyLayer(); newSvgIdLayer->m_svgViewLayerID = to; connectorShared->insertPin(ViewLayer::PCBView, newSvgIdLayer); } } void ModelPartShared::insertBus(BusShared * busShared) { m_buses.insert(busShared->id(), busShared); } void ModelPartShared::lookForZeroConnector() { foreach (QString key, m_connectorSharedHash.keys()) { int ix = IntegerFinder.indexIn(key); if (ix >= 0) { if (IntegerFinder.cap(0) == "0") { m_hasZeroConnector = true; return; } } } } bool ModelPartShared::hasZeroConnector() { return m_hasZeroConnector; } void ModelPartShared::addOwner(QObject * owner) { m_ownerCount++; connect(owner, SIGNAL(destroyed()), this, SLOT(removeOwner())); } void ModelPartShared::removeOwner() { if (--m_ownerCount == 0) { // DebugDialog::debug(QString("last owner %1").arg(moduleID())); // this->deleteLater(); } } void ModelPartShared::addSchematicText(ViewImage * viewImage) { if (viewImage->viewID != ViewLayer::SchematicView) return; qulonglong one = 1; if ((viewImage->layers & (one << ViewLayer::Schematic)) == 0) return; viewImage->canFlipHorizontal = viewImage->canFlipVertical = true; viewImage->layers |= (one << ViewLayer::SchematicText); } bool ModelPartShared::showInLabel(const QString & propertyName) { //foreach (QString key, m_displayKeys) { // DebugDialog::debug("check display " + m_moduleID + " " + key); //} return m_displayKeys.contains(propertyName, Qt::CaseInsensitive); } const QList< QPointer > & ModelPartShared::subparts() { return m_subparts; } void ModelPartShared::addSubpart(ModelPartShared * subpart) { if (subpart == NULL) return; m_subparts.append(subpart); subpart->setSuperpart(this); } ModelPartShared * ModelPartShared::superpart() { return m_superpart; } void ModelPartShared::setSuperpart(ModelPartShared * sup) { m_superpart = sup; } bool ModelPartShared::hasSubparts() { return m_subparts.count() > 0; } void ModelPartShared::setSubpartID(const QString & id) { m_subpartID = id; } const QString & ModelPartShared::subpartID() const { return m_subpartID; } QPointF ModelPartShared::subpartOffset() const { return m_subpartOffset; } void ModelPartShared::setSubpartOffset(QPointF p) { m_subpartOffset = p; } fritzing-app-0.9.2b/src/model/modelpartshared.h000066400000000000000000000154651250202676700215360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef MODELPARTSHARED_H #define MODELPARTSHARED_H #include #include #include #include #include #include #include #include "../viewlayer.h" struct ViewImage { ViewLayer::ViewID viewID; qulonglong layers; qulonglong sticky; qulonglong flipped; QString image; bool canFlipHorizontal; bool canFlipVertical; ViewImage(ViewLayer::ViewID); }; class ModelPartShared : public QObject { Q_OBJECT public: ModelPartShared(); ModelPartShared(QDomDocument &, const QString & path); ~ModelPartShared(); //QDomDocument * domDocument(); void copy(ModelPartShared* other); const QString & uri(); void setUri(QString); const QString & moduleID(); void setModuleID(QString); const QString & version(); void setVersion(QString); const QString & author(); void setAuthor(QString); const QString & description(); void setDescription(QString); const QString & spice(); void setSpice(QString); const QString & spiceModel(); void setSpiceModel(QString); const QString & url(); void setUrl(QString); const QString & title(); void setTitle(QString); const QString & label() const; void setLabel(QString); const QDate & date(); void setDate(QDate); const QString & dateAsStr(); void setDate(QString); void setDBID(qulonglong); qulonglong dbid(); const QString & fritzingVersion(); void setFritzingVersion(const QString &); const QList viewImages(); QString imageFileName(ViewLayer::ViewID, ViewLayer::ViewLayerID); void setImageFileName(ViewLayer::ViewID, const QString & filename); QString imageFileName(ViewLayer::ViewID); const QList< QPointer > & subparts(); void addSubpart(ModelPartShared * subpart); bool hasSubparts(); void setSubpartID(const QString &); const QString & subpartID() const; ModelPartShared * superpart(); void setSuperpart(ModelPartShared *); bool anySticky(ViewLayer::ViewID); bool hasMultipleLayers(ViewLayer::ViewID); bool canFlipHorizontal(ViewLayer::ViewID); bool canFlipVertical(ViewLayer::ViewID); bool hasViewID(ViewLayer::ViewID viewID); LayerList viewLayers(ViewLayer::ViewID viewID); LayerList viewLayersFlipped(ViewLayer::ViewID viewID); const QString & path(); void setPath(QString path); const QString & taxonomy(); void setTaxonomy(QString taxonomy); const QList< QPointer > connectorsShared(); void setConnectorsShared(QList< QPointer > connectors); void connectorIDs(ViewLayer::ViewID viewId, ViewLayer::ViewLayerID viewLayerID, QStringList & connectorIDs, QStringList & terminalIDs, QStringList & legIDs); const QStringList &tags(); void setTags(const QStringList &tags); void setTag(const QString &tag); QString family(); void setFamily(const QString &family); QHash & properties(); void setProperties(const QHash &properties); const QStringList & displayKeys(); void initConnectors(); void setConnectorsInitialized(bool); ConnectorShared * getConnectorShared(const QString & id); bool ignoreTerminalPoints(); void setProperty(const QString & key, const QString & value, bool showInLabel); bool showInLabel(const QString & key); const QString & replacedby(); void setReplacedby(const QString & replacedby); void flipSMDAnd(); void setFlippedSMD(bool); bool flippedSMD(); bool needsCopper1(); bool hasViewFor(ViewLayer::ViewID); bool hasViewFor(ViewLayer::ViewID, ViewLayer::ViewLayerID); QString hasBaseNameFor(ViewLayer::ViewID); void setViewImage(ViewImage *); void addConnector(ConnectorShared *); void insertBus(class BusShared *); void lookForZeroConnector(); bool hasZeroConnector(); void addOwner(QObject *); void setSubpartOffset(QPointF); QPointF subpartOffset() const; protected: void loadTagText(QDomElement parent, QString tagName, QString &field); // used to populate de StringList that contains both the and the values void populateTags(QDomElement parent, QStringList &list); void populateProperties(QDomElement parent, QHash &hash, QStringList & displayKeys); void commonInit(); void ensurePartNumberProperty(); void copyPins(ViewLayer::ViewLayerID from, ViewLayer::ViewLayerID to); LayerList viewLayersAux(ViewLayer::ViewID viewID, qulonglong (*accessor)(ViewImage *)); void addSchematicText(ViewImage *); bool setDomDocument(QDomDocument &); protected slots: void removeOwner(); public: static const QString PartNumberPropertyName; protected: //QDomDocument* m_domDocument; QString m_uri; QString m_moduleID; QString m_fritzingVersion; QString m_version; QString m_author; QString m_title; QString m_label; QString m_description; QString m_spice; QString m_spiceModel; QString m_url; QString m_date; QString m_replacedby; QString m_path; QString m_taxonomy; QStringList m_tags; QStringList m_displayKeys; QHash m_properties; QHash > m_connectorSharedHash; QHash m_buses; QHash m_viewImages; bool m_connectorsInitialized; bool m_ignoreTerminalPoints; bool m_flippedSMD; bool m_needsCopper1; // for converting pre-two-layer parts qulonglong m_dbid; bool m_hasZeroConnector; int m_ownerCount; QList< QPointer > m_subparts; QPointer m_superpart; QString m_subpartID; QPointF m_subpartOffset; }; class ModelPartSharedRoot : public ModelPartShared { Q_OBJECT public: const QString & icon(); void setIcon(const QString & filename); const QString & searchTerm(); void setSearchTerm(const QString & searchTerm); protected: QString m_icon; QString m_searchTerm; }; #endif fritzing-app-0.9.2b/src/model/palettemodel.cpp000066400000000000000000000537201250202676700213660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 7004 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 13:10:59 +0200 (Mo, 29. Apr 2013) $ ********************************************************************/ #include "palettemodel.h" #include #include #include #include #include #include "../debugdialog.h" #include "modelpart.h" #include "../version/version.h" #include "../layerattributes.h" #include "../utils/folderutils.h" #include "../utils/fmessagebox.h" #include "../utils/textutils.h" #include "../items/moduleidnames.h" #include "../items/partfactory.h" bool PaletteModel::CreateTempPartsBinFile = true; static bool JustAppendAllPartsInstances = false; static bool FirstTime = true; QString PaletteModel::ContribPartsBinFilePath; static QString FritzingContribPath; const static QString InstanceTemplate( "\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\n"); void setFlip(ViewLayer::ViewID viewID, QXmlStreamReader & xml, QHash & viewImages) { bool fv = xml.attributes().value("flipvertical", "").toString().compare("true") == 0; bool fh = xml.attributes().value("fliphorizontal", "").toString().compare("true") == 0; viewImages.value(viewID)->canFlipHorizontal = fh; viewImages.value(viewID)->canFlipVertical = fv; } ///////////////////////////////////// PaletteModel::PaletteModel() : ModelBase(true) { m_loadedFromFile = false; m_loadingContrib = false; m_fullLoad = false; } PaletteModel::PaletteModel(bool makeRoot, bool doInit) : ModelBase( makeRoot ) { m_loadedFromFile = false; m_loadingContrib = false; m_fullLoad = false; if (doInit) { initParts(false); } } PaletteModel::~PaletteModel() { foreach (ModelPart * modelPart, m_partHash.values()) { delete modelPart; } } void PaletteModel::initParts(bool dbExists) { QDir * dir = FolderUtils::getApplicationSubFolder("parts"); if (dir == NULL) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("Parts folder not found.") ); return; } FritzingContribPath = dir->absoluteFilePath("contrib"); delete dir; loadParts(dbExists); if (m_root == NULL) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("No parts found.") ); } } void PaletteModel::initNames() { ContribPartsBinFilePath = FolderUtils::getUserDataStorePath("bins")+"/contribParts" + FritzingBinExtension; } ModelPart * PaletteModel::retrieveModelPart(const QString & moduleID) { ModelPart * modelPart = m_partHash.value(moduleID, NULL); if (modelPart != NULL) return modelPart; if (m_referenceModel != NULL) { return m_referenceModel->retrieveModelPart(moduleID); } return NULL; } bool PaletteModel::containsModelPart(const QString & moduleID) { return m_partHash.contains(moduleID); } void PaletteModel::loadParts(bool dbExists) { QStringList nameFilters; nameFilters << "*" + FritzingPartExtension; JustAppendAllPartsInstances = true; /// !!!!!!!!!!!!!!!! "JustAppendAllPartsInstances = CreateAllPartsBinFile" /// !!!!!!!!!!!!!!!! is incorrect /// !!!!!!!!!!!!!!!! this flag was originally set up because sometimes we were appending a /// !!!!!!!!!!!!!!!! single instance into an already existing file, /// !!!!!!!!!!!!!!!! so simply appending new items as text gave us xml errors. /// !!!!!!!!!!!!!!!! The problem was that there was no easy way to set the flag directly on the actual /// !!!!!!!!!!!!!!!! function being used: PaletteModel::LoadPart(), though maybe this deserves another look. /// !!!!!!!!!!!!!!!! However, since we're starting from scratch in LoadParts, we can use the much faster /// !!!!!!!!!!!!!!!! file append method. Since CreateAllPartsBinFile is false in release mode, /// !!!!!!!!!!!!!!!! Fritzing was taking forever to start up. if (FirstTime) { } int totalPartCount = 0; emit loadedPart(0, totalPartCount); QDir * dir1 = FolderUtils::getApplicationSubFolder("parts"); if (dir1 != NULL) { countParts(*dir1, nameFilters, totalPartCount); } QDir dir2(FolderUtils::getUserDataStorePath("parts")); countParts(dir2, nameFilters, totalPartCount); QDir dir3(":/resources/parts"); if (m_fullLoad || !dbExists) { countParts(dir3, nameFilters, totalPartCount); } int loadingPart = 0; if (dir1 != NULL) { loadPartsAux(*dir1, nameFilters, loadingPart, totalPartCount); delete dir1; } loadPartsAux(dir2, nameFilters, loadingPart, totalPartCount); if (m_fullLoad || !dbExists) { // otherwise these will already be in the database loadPartsAux(dir3, nameFilters, loadingPart, totalPartCount); } if (FirstTime) { } JustAppendAllPartsInstances = false; /// !!!!!!!!!!!!!!!! "JustAppendAllPartsInstances = !CreateAllPartsBinFile" /// !!!!!!!!!!!!!!!! is incorrect /// !!!!!!!!!!!!!!!! See above. We simply want to restore the default, so that other functions calling /// !!!!!!!!!!!!!!!! writeInstanceInCommonBin via LoadPart() will use the slower DomDocument methods, /// !!!!!!!!!!!!!!!! since in that case we are appending to an already existing file. FirstTime = false; } void PaletteModel::countParts(QDir & dir, QStringList & nameFilters, int & partCount) { QStringList list = dir.entryList(nameFilters, QDir::Files | QDir::NoSymLinks); partCount += list.size(); QStringList dirs = dir.entryList(QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); for (int i = 0; i < dirs.size(); ++i) { QString temp2 = dirs[i]; dir.cd(temp2); countParts(dir, nameFilters, partCount); dir.cdUp(); } } void PaletteModel::loadPartsAux(QDir & dir, QStringList & nameFilters, int & loadingPart, int totalPartCount) { //QString temp = dir.absolutePath(); QFileInfoList list = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); QString path = fileInfo.absoluteFilePath (); //DebugDialog::debug(QString("part path:%1 core? %2").arg(path).arg(m_loadingCore? "true" : "false")); loadPart(path, false); emit loadedPart(++loadingPart, totalPartCount); //DebugDialog::debug("loadedok"); } QStringList dirs = dir.entryList(QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); for (int i = 0; i < dirs.size(); ++i) { QString temp2 = dirs[i]; dir.cd(temp2); m_loadingContrib = (temp2 == "contrib"); loadPartsAux(dir, nameFilters, loadingPart, totalPartCount); dir.cdUp(); } } ModelPart * PaletteModel::loadPart(const QString & path, bool update) { QFile file(path); if (!file.open(QFile::ReadOnly | QFile::Text)) { FMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Cannot read file %1:\n%2.") .arg(path) .arg(file.errorString())); return NULL; } //DebugDialog::debug(QString("loading %2 %1").arg(path).arg(QTime::currentTime().toString("HH:mm:ss.zzz"))); ModelPart::ItemType type = ModelPart::Part; QString moduleID; QString title; QString propertiesText; QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("Parse error (2) at line %1, column %2:\n%3\n%4") .arg(errorLine) .arg(errorColumn) .arg(errorStr) .arg(path)); return NULL; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { //QMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file is not a Fritzing file (8).")); return NULL; } if (root.tagName() != "module") { //QMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file is not a Fritzing file (9).")); return NULL; } moduleID = root.attribute("moduleId"); if (moduleID.isNull() || moduleID.isEmpty()) { //QMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("The file is not a Fritzing file (10).")); return NULL; } // check if it's a wire QDomElement propertiesElement = root.firstChildElement("properties"); propertiesText = propertiesElement.text(); QDomElement t = root.firstChildElement("title"); TextUtils::findText(t, title); //DebugDialog::debug("module ID " + moduleID); // FIXME: properties is nested right now if (moduleID.compare(ModuleIDNames::WireModuleIDName) == 0) { type = ModelPart::Wire; } else if (moduleID.compare(ModuleIDNames::JumperModuleIDName) == 0) { type = ModelPart::Jumper; } else if (moduleID.endsWith(ModuleIDNames::LogoImageModuleIDName)) { type = ModelPart::Logo; } else if (moduleID.endsWith(ModuleIDNames::LogoTextModuleIDName)) { type = ModelPart::Logo; } else if (moduleID.compare(ModuleIDNames::GroundPlaneModuleIDName) == 0) { type = ModelPart::CopperFill; } else if (moduleID.compare(ModuleIDNames::NoteModuleIDName) == 0) { type = ModelPart::Note; } else if (moduleID.endsWith(ModuleIDNames::TwoPowerModuleIDName)) { type = ModelPart::Part; } else if (moduleID.endsWith(ModuleIDNames::PowerModuleIDName)) { type = ModelPart::Symbol; } else if (moduleID.compare(ModuleIDNames::GroundModuleIDName) == 0) { type = ModelPart::Symbol; } else if (moduleID.endsWith(ModuleIDNames::NetLabelModuleIDName)) { type = ModelPart::Symbol; } else if (moduleID.compare(ModuleIDNames::PowerLabelModuleIDName) == 0) { type = ModelPart::Symbol; } else if (moduleID.compare(ModuleIDNames::RulerModuleIDName) == 0) { type = ModelPart::Ruler; } else if (moduleID.compare(ModuleIDNames::ViaModuleIDName) == 0) { type = ModelPart::Via; } else if (moduleID.compare(ModuleIDNames::HoleModuleIDName) == 0) { type = ModelPart::Hole; } else if (moduleID.endsWith(ModuleIDNames::PerfboardModuleIDName)) { type = ModelPart::Breadboard; } else if (moduleID.endsWith(ModuleIDNames::StripboardModuleIDName)) { type = ModelPart::Breadboard; } else if (moduleID.endsWith(ModuleIDNames::Stripboard2ModuleIDName)) { type = ModelPart::Breadboard; } else if (propertiesText.contains("breadboard", Qt::CaseInsensitive)) { type = ModelPart::Breadboard; } else if (propertiesText.contains("plain vanilla pcb", Qt::CaseInsensitive)) { if (propertiesText.contains("shield", Qt::CaseInsensitive) || title.contains("custom", Qt::CaseInsensitive)) { type = ModelPart::Board; } else { type = ModelPart::ResizableBoard; } } ModelPart * modelPart = new ModelPart(domDocument, path, type); if (modelPart == NULL) return NULL; if (path.startsWith(ResourcePath)) { modelPart->setCore(true); } else if (onCoreList(moduleID)) { // for database entries which have existing fzp files. modelPart->setCore(true); } modelPart->setContrib(m_loadingContrib); QDomElement subparts = root.firstChildElement("schematic-subparts"); QDomElement subpart = subparts.firstChildElement("subpart"); while (!subpart.isNull()) { ModelPart * subModelPart = makeSubpart(modelPart, subpart); m_partHash.insert(subModelPart->moduleID(), subModelPart); subpart = subpart.nextSiblingElement("subpart"); } if (m_partHash.value(moduleID, NULL)) { if(!update) { FMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("The part '%1' at '%2' does not have a unique module id '%3'.") .arg(modelPart->title()) .arg(path) .arg(moduleID)); return NULL; } else { m_partHash[moduleID]->copyStuff(modelPart); } } else { m_partHash.insert(moduleID, modelPart); } if (m_root == NULL) { m_root = modelPart; } else { modelPart->setParent(m_root); } return modelPart; } bool PaletteModel::loadFromFile(const QString & fileName, ModelBase * referenceModel, bool checkViews) { QList modelParts; bool result = ModelBase::loadFromFile(fileName, referenceModel, modelParts, checkViews); if (result) { m_loadedFromFile = true; m_loadedFrom = fileName; } return result; } bool PaletteModel::loadedFromFile() { return m_loadedFromFile; } QString PaletteModel::loadedFrom() { if(m_loadedFromFile) { return m_loadedFrom; } else { return ___emptyString___; } } ModelPart * PaletteModel::addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists) { /*ModelPart * modelPart = loadPart(newPartPath, updateIdAlreadyExists);; if (m_referenceModel != NULL && addToReference) { modelPart = m_referenceModel->addPart(newPartPath, addToReference); if (modelPart != NULL) { return addModelPart( m_root, modelPart); } }*/ ModelPart * modelPart = loadPart(newPartPath, updateIdAlreadyExists); if (m_referenceModel && addToReference) { m_referenceModel->addPart(modelPart,updateIdAlreadyExists); } return modelPart; } void PaletteModel::removePart(const QString &moduleID) { ModelPart *mpToRemove = NULL; QList::const_iterator i; for (i = m_root->children().constBegin(); i != m_root->children().constEnd(); ++i) { ModelPart* mp = qobject_cast(*i); if (mp == NULL) continue; //DebugDialog::debug(QString("remove part %1").arg(mp->moduleID())); if(mp->moduleID() == moduleID) { mpToRemove = mp; break; } } if(mpToRemove) { mpToRemove->setParent(NULL); delete mpToRemove; } //DebugDialog::debug(QString("part hash count %1").arg(m_partHash.count())); m_partHash.remove(moduleID); //DebugDialog::debug(QString("part hash count %1").arg(m_partHash.count())); } void PaletteModel::removeParts() { QList modelParts; foreach (QObject * child, m_root->children()) { ModelPart * modelPart = qobject_cast(child); if (modelPart == NULL) continue; modelParts.append(modelPart); } foreach(ModelPart * modelPart, modelParts) { modelPart->setParent(NULL); m_partHash.remove(modelPart->moduleID()); delete modelPart; } } void PaletteModel::clearPartHash() { foreach (ModelPart * modelPart, m_partHash.values()) { ModelPartShared * modelPartShared = modelPart->modelPartShared(); if (modelPartShared) { modelPart->setModelPartShared(NULL); delete modelPartShared; } delete modelPart; } m_partHash.clear(); } void PaletteModel::setOrdererChildren(QList children) { m_root->setOrderedChildren(children); } QList PaletteModel::search(const QString & searchText, bool allowObsolete) { QList modelParts; QStringList strings = searchText.split(" "); search(m_root, strings, modelParts, allowObsolete); return modelParts; } void PaletteModel::search(ModelPart * modelPart, const QStringList & searchStrings, QList & modelParts, bool allowObsolete) { // TODO: eventually move all this into the database? // or use lucene // or google search api int count = 0; foreach (QString searchString, searchStrings) { bool gotOne = false; if (modelPart->title().contains(searchString, Qt::CaseInsensitive)) { gotOne = true; } else if (modelPart->description().contains(searchString, Qt::CaseInsensitive)) { gotOne = true; } else if (modelPart->url().contains(searchString, Qt::CaseInsensitive)) { gotOne = true; } else if (modelPart->author().contains(searchString, Qt::CaseInsensitive)) { gotOne = true; } else if (modelPart->moduleID().contains(searchString, Qt::CaseInsensitive)) { gotOne = true; } else { foreach (QString string, modelPart->tags()) { if (string.contains(searchString, Qt::CaseInsensitive)) { gotOne = true; break; } } } if (!gotOne) { foreach (QString string, modelPart->properties().values()) { if (string.contains(searchString, Qt::CaseInsensitive)) { gotOne = true; break; } } } if (!gotOne) { foreach (QString string, modelPart->properties().keys()) { if (string.contains(searchString, Qt::CaseInsensitive)) { gotOne = true; break; } } } if (!gotOne) break; count++; } if ((count == searchStrings.count()) && !modelParts.contains(modelPart)) { if (!allowObsolete && modelPart->isObsolete()) { } else { modelParts.append(modelPart); emit addSearchMaximum(1); } } emit addSearchMaximum(modelPart->children().count()); foreach(QObject * child, modelPart->children()) { ModelPart * mp = qobject_cast(child); if (mp == NULL) continue; search(mp, searchStrings, modelParts, allowObsolete); emit incSearch(); } } QList PaletteModel::findContribNoBin() { QList modelParts; foreach (ModelPart * modelPart, m_partHash.values()) { if (modelPart->isContrib()) { if (!modelPart->isInBin()) { modelParts << modelPart; } } } return modelParts; } ModelPart * PaletteModel::makeSubpart(ModelPart * originalModelPart, const QDomElement & originalSubpart) { QString newLabel = originalSubpart.attribute("label"); QString newID = originalSubpart.attribute("id"); QDomElement originalRoot = originalSubpart.ownerDocument().documentElement(); QString moduleID = originalRoot.attribute("moduleId") + "_" + newID; ModelPart * modelPart = retrieveModelPart(moduleID); if (modelPart) { return modelPart; } QDomDocument subdoc = originalSubpart.ownerDocument().cloneNode(true).toDocument(); QDomElement root = subdoc.documentElement(); QDomElement subparts = root.firstChildElement("schematic-subparts"); root.removeChild(subparts); root.setAttribute("moduleId", moduleID); QDomElement label = root.firstChildElement("label"); if (!label.isNull()) { TextUtils::replaceChildText(label, newLabel); } QDomElement views = root.firstChildElement("views"); QDomElement schematicView = views.firstChildElement(ViewLayer::viewIDXmlName(ViewLayer::SchematicView)); QDomElement schematicLayers = schematicView.firstChildElement("layers"); QString image = schematicLayers.attribute("image"); image.replace(".svg", "_" + newID + ".svg"); schematicLayers.setAttribute("image", image); views.removeChild(schematicView); QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement layers = view.firstChildElement("layers"); view.removeChild(layers); layers = schematicLayers.cloneNode(true).toElement(); view.appendChild(layers); view = view.nextSiblingElement(); } views.appendChild(schematicView); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); QHash connectorHash; while (!connector.isNull()) { QDomElement next = connector.nextSiblingElement("connector"); connectors.removeChild(connector); connectorHash.insert(connector.attribute("id"), connector); connector = next; } QDomElement originalConnectors = originalSubpart.firstChildElement("connectors"); QDomElement originalConnector = originalConnectors.firstChildElement("connector"); QString schematicLayerName = ViewLayer::viewLayerXmlNameFromID(ViewLayer::Schematic); while (!originalConnector.isNull()) { QString id = originalConnector.attribute("id"); QDomElement connector = connectorHash.value(id); connectors.appendChild(connector); QDomElement cviews = connector.firstChildElement("views"); QDomElement view = cviews.firstChildElement(); while (!view.isNull()) { QDomElement p = view.firstChildElement("p"); bool firstTime = true; while (!p.isNull()) { QDomElement next = p.nextSiblingElement("p"); if (firstTime) { p.setAttribute("layer", schematicLayerName); firstTime = false; } else { view.removeChild(p); } p = next; } view = view.nextSiblingElement(); } originalConnector = originalConnector.nextSiblingElement("connector"); } QString path = PartFactory::fzpPath() + moduleID + ".fzp"; QString fzp = subdoc.toString(4); TextUtils::writeUtf8(path, fzp); modelPart = new ModelPart(subdoc, path, ModelPart::SchematicSubpart); modelPart->setSubpartID(newID); originalModelPart->modelPartShared()->addSubpart(modelPart->modelPartShared()); m_partHash.insert(moduleID, modelPart); return modelPart; } QList PaletteModel::allParts() { QList modelParts; foreach (ModelPart * modelPart, m_partHash.values()) { if (!modelPart->isObsolete()) modelParts.append(modelPart); } return modelParts; } fritzing-app-0.9.2b/src/model/palettemodel.h000066400000000000000000000060341250202676700210270ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #ifndef PALETTEMODEL_H #define PALETTEMODEL_H #include "modelpart.h" #include "modelbase.h" #include #include #include #include #include class PaletteModel : public ModelBase { Q_OBJECT public: PaletteModel(); PaletteModel(bool makeRoot, bool doInit); ~PaletteModel(); ModelPart * retrieveModelPart(const QString & moduleID); virtual bool containsModelPart(const QString & moduleID); virtual ModelPart * loadPart(const QString & path, bool update); void clear(); bool loadedFromFile(); QString loadedFrom(); bool loadFromFile(const QString & fileName, ModelBase* referenceModel, bool checkViews); ModelPart * addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists); void removePart(const QString &moduleID); void removeParts(); QList search(const QString & searchText, bool allowObsolete); void clearPartHash(); void setOrdererChildren(QList children); void search(ModelPart * modelPart, const QStringList & searchStrings, QList & modelParts, bool allowObsolete); QList findContribNoBin(); QList allParts(); protected: QHash m_partHash; bool m_loadedFromFile; QString m_loadedFrom; // The file this was loaded from, only if m_loadedFromFile == true bool m_loadingContrib; bool m_fullLoad; signals: void loadedPart(int i, int total); void incSearch(); void addSearchMaximum(int); protected: virtual void initParts(bool dbExists); void loadParts(bool dbExists); void loadPartsAux(QDir & dir, QStringList & nameFilters, int & loadedPart, int totalParts); void countParts(QDir & dir, QStringList & nameFilters, int & partCount); ModelPart * makeSubpart(ModelPart * originalModelPart, const QDomElement & originalSubparth); protected: static bool CreateContribPartsBinFile; static QString ContribPartsBinFilePath; static bool CreateTempPartsBinFile; static QString TempPartsBinFilePath; public: static void initNames(); }; #endif fritzing-app-0.9.2b/src/model/sketchmodel.cpp000066400000000000000000000042731250202676700212100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "sketchmodel.h" #include "../debugdialog.h" #include #include #include #include #include SketchModel::SketchModel(bool makeRoot) : ModelBase(makeRoot) { } SketchModel::SketchModel(ModelPart * root) : ModelBase(false) { m_root = root; } void SketchModel::removeModelPart(ModelPart * modelPart) { modelPart->setParent(NULL); //DebugDialog::debug(QString("model count %1").arg(root()->children().size())); } ModelPart * SketchModel::findModelPart(const QString & moduleID, long id) { if (m_root == NULL) return NULL; return findModelPartAux(m_root, moduleID, id); } ModelPart * SketchModel::findModelPartAux(ModelPart * modelPart, const QString & moduleID, long id) { if (modelPart->moduleID().compare(moduleID) == 0) { if (modelPart->hasViewID(id)) { return modelPart; } if (modelPart->modelIndex() * ModelPart::indexMultiplier == id) { return modelPart; } } foreach (QObject * child, modelPart->children()) { ModelPart * mp = qobject_cast(child); if (mp == NULL) continue; mp = findModelPartAux(mp, moduleID, id); if (mp != NULL) { return mp; } } return NULL; } fritzing-app-0.9.2b/src/model/sketchmodel.h000066400000000000000000000027421250202676700206540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SKETCHMODEL_H #define SKETCHMODEL_H #include "modelpart.h" #include "modelbase.h" #include #include class SketchModel : public ModelBase { Q_OBJECT public: SketchModel(bool makeRoot); SketchModel(ModelPart * root); void removeModelPart(ModelPart *); ModelPart * findModelPart(const QString & moduleID, long id); protected: ModelPart * findModelPartAux(ModelPart * modelPart, const QString & moduleID, long id); }; #endif fritzing-app-0.9.2b/src/partsbinpalette/000077500000000000000000000000001250202676700202755ustar00rootroot00000000000000fritzing-app-0.9.2b/src/partsbinpalette/binmanager/000077500000000000000000000000001250202676700224005ustar00rootroot00000000000000fritzing-app-0.9.2b/src/partsbinpalette/binmanager/binmanager.cpp000066400000000000000000001225741250202676700252220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6962 $: $Author: irascibl@gmail.com $: $Date: 2013-04-14 00:08:36 +0200 (So, 14. Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include "binmanager.h" #include "stacktabwidget.h" #include "stacktabbar.h" #include "../../model/modelpart.h" #include "../../mainwindow/mainwindow.h" #include "../../model/palettemodel.h" #include "../../waitpushundostack.h" #include "../../debugdialog.h" #include "../../utils/folderutils.h" #include "../../utils/textutils.h" #include "../../utils/fileprogressdialog.h" #include "../../referencemodel/referencemodel.h" #include "../../items/partfactory.h" #include "../partsbinpalettewidget.h" #include "../partsbinview.h" /////////////////////////////////////////////////////////// QString BinLocation::toString(BinLocation::Location location) { switch (location) { case BinLocation::User: return "user"; case BinLocation::More: return "more"; case BinLocation::App: return "app"; case BinLocation::Outside: default: return "outside"; } } BinLocation::Location BinLocation::fromString(const QString & locationString) { if (locationString.compare("user", Qt::CaseInsensitive) == 0) return BinLocation::User; if (locationString.compare("more", Qt::CaseInsensitive) == 0) return BinLocation::More; if (locationString.compare("app", Qt::CaseInsensitive) == 0) return BinLocation::App; return BinLocation::Outside; } BinLocation::Location BinLocation::findLocation(const QString & filename) { if (filename.startsWith(FolderUtils::getUserDataStorePath("bins"))) { return BinLocation::User; } else if (filename.startsWith(FolderUtils::getApplicationSubFolderPath("bins") + "/more")) { return BinLocation::More; } else if (filename.startsWith(FolderUtils::getApplicationSubFolderPath("bins"))) { return BinLocation::App; } return BinLocation::Outside; } /////////////////////////////////////////////////////////// QString BinManager::Title; QString BinManager::MyPartsBinLocation; QString BinManager::MyPartsBinTemplateLocation; QString BinManager::SearchBinLocation; QString BinManager::SearchBinTemplateLocation; QString BinManager::ContribPartsBinLocation; QString BinManager::TempPartsBinTemplateLocation; QString BinManager::CorePartsBinLocation; QString BinManager::StandardBinStyle = "background-color: gray;"; QString BinManager::CurrentBinStyle = "background-color: black;"; QHash BinManager::StandardBinIcons; BinManager::BinManager(class ReferenceModel *referenceModel, class HtmlInfoView *infoView, WaitPushUndoStack *undoStack, MainWindow* parent) : QFrame(parent) { BinManager::Title = tr("Parts"); m_combinedMenu = NULL; m_showListViewAction = m_showIconViewAction = NULL; m_referenceModel = referenceModel; m_infoView = infoView; m_undoStack = undoStack; m_defaultSaveFolder = FolderUtils::getUserDataStorePath("bins"); m_mainWindow = parent; m_currentBin = NULL; connect(this, SIGNAL(savePartAsBundled(const QString &)), m_mainWindow, SLOT(saveBundledPart(const QString &))); m_unsavedBinsCount = 0; QVBoxLayout *lo = new QVBoxLayout(this); m_stackTabWidget = new StackTabWidget(this); m_stackTabWidget->setTabPosition(QTabWidget::West); lo->addWidget(m_stackTabWidget); lo->setMargin(0); lo->setSpacing(0); setMaximumHeight(500); } BinManager::~BinManager() { } void BinManager::initStandardBins() { createCombinedMenu(); createContextMenus(); //DebugDialog::debug("init bin manager"); QList actualLocations; findAllBins(actualLocations); hackLocalContrib(actualLocations); restoreStateAndGeometry(actualLocations); foreach (BinLocation * location, actualLocations) { PartsBinPaletteWidget* bin = newBin(); bin->load(location->path, m_mainWindow->fileProgressDialog(), true); m_stackTabWidget->addTab(bin, bin->icon(), bin->title()); m_stackTabWidget->stackTabBar()->setTabToolTip(m_stackTabWidget->count() - 1, bin->title()); registerBin(bin); delete location; } actualLocations.clear(); //DebugDialog::debug("open core bin"); openCoreBinIn(); //DebugDialog::debug("after core bin"); currentChanged(m_stackTabWidget->currentIndex()); connectTabWidget(); } void BinManager::addBin(PartsBinPaletteWidget* bin) { m_stackTabWidget->addTab(bin, bin->icon(), bin->title()); registerBin(bin); setAsCurrentBin(bin); } void BinManager::registerBin(PartsBinPaletteWidget* bin) { if (!bin->fileName().isEmpty()) { m_openedBins[bin->fileName()] = bin; if (bin->fileName().compare(CorePartsBinLocation) == 0) { bin->setAllowsChanges(false); } else if (bin->fileName().compare(SearchBinLocation) == 0) { bin->setAllowsChanges(false); } else if (bin->fileName().compare(ContribPartsBinLocation) == 0) { bin->setAllowsChanges(false); } else if (bin->fileName().compare(m_tempPartsBinLocation) == 0) { bin->setAllowsChanges(false); } else if (bin->fileName().contains(FolderUtils::getApplicationSubFolderPath("bins"))) { bin->setAllowsChanges(false); } } } void BinManager::connectTabWidget() { connect( m_stackTabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)) ); connect( m_stackTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)) ); } void BinManager::insertBin(PartsBinPaletteWidget* bin, int index) { registerBin(bin); m_stackTabWidget->insertTab(index, bin, bin->icon(), bin->title()); m_stackTabWidget->setCurrentIndex(index); } bool BinManager::beforeClosing() { bool retval = true; for(int j = 0; j < m_stackTabWidget->count(); j++) { PartsBinPaletteWidget *bin = qobject_cast(m_stackTabWidget->widget(j)); if (bin && !bin->fastLoaded()) { setAsCurrentTab(bin); retval = retval && bin->beforeClosing(); if(!retval) break; } } if(retval) { saveStateAndGeometry(); } return retval; } void BinManager::setAsCurrentTab(PartsBinPaletteWidget* bin) { m_stackTabWidget->setCurrentWidget(bin); } bool BinManager::hasAlienParts() { return false; } void BinManager::setInfoViewOnHover(bool infoViewOnHover) { Q_UNUSED(infoViewOnHover); } void BinManager::addNewPart(ModelPart *modelPart) { PartsBinPaletteWidget* myPartsBin = getOrOpenMyPartsBin(); myPartsBin->addPart(modelPart); setDirtyTab(myPartsBin); } PartsBinPaletteWidget* BinManager::getOrOpenMyPartsBin() { return getOrOpenBin(MyPartsBinLocation, MyPartsBinTemplateLocation); } PartsBinPaletteWidget* BinManager::getOrOpenSearchBin() { PartsBinPaletteWidget * bin = getOrOpenBin(SearchBinLocation, SearchBinTemplateLocation); if (bin) { bin->setSaveQuietly(true); } return bin; } PartsBinPaletteWidget* BinManager::getOrOpenBin(const QString & binLocation, const QString & binTemplateLocation) { PartsBinPaletteWidget* partsBin = findBin(binLocation); if(!partsBin) { QString fileToOpen = QFileInfo(binLocation).exists() ? binLocation : createIfBinNotExists(binLocation, binTemplateLocation); partsBin = openBinIn(fileToOpen, false); } if (partsBin != NULL && partsBin->fastLoaded()) { partsBin->load(partsBin->fileName(), partsBin, false); } return partsBin; } PartsBinPaletteWidget* BinManager::findBin(const QString & binLocation) { for (int i = 0; i < m_stackTabWidget->count(); i++) { PartsBinPaletteWidget* bin = (PartsBinPaletteWidget *) m_stackTabWidget->widget(i); if(bin->fileName() == binLocation) { return bin; } } return NULL; } QString BinManager::createIfMyPartsNotExists() { return createIfBinNotExists(MyPartsBinLocation, MyPartsBinTemplateLocation); } QString BinManager::createIfSearchNotExists() { return createIfBinNotExists(SearchBinLocation, SearchBinTemplateLocation); } QString BinManager::createIfBinNotExists(const QString & dest, const QString & source) { QString binPath = dest; QFile file(source); FolderUtils::slamCopy(file, binPath); return binPath; } void BinManager::addPartToBin(ModelPart *modelPart, int position) { PartsBinPaletteWidget *bin = m_currentBin? m_currentBin: getOrOpenMyPartsBin(); addPartToBinAux(bin,modelPart,position); } void BinManager::addToMyParts(ModelPart *modelPart) { PartsBinPaletteWidget *bin = getOrOpenMyPartsBin(); if (bin) { addPartToBinAux(bin,modelPart); setAsCurrentTab(bin); } } void BinManager::addToTempPartsBin(ModelPart *modelPart) { PartsBinPaletteWidget *bin = getOrOpenBin(m_tempPartsBinLocation, TempPartsBinTemplateLocation); if (bin) { addPartToBinAux(bin,modelPart); setAsCurrentTab(bin); bin->setDirty(false); } } void BinManager::hideTempPartsBin() { for (int i = 0; i < m_stackTabWidget->count(); i++) { PartsBinPaletteWidget* bin = (PartsBinPaletteWidget *) m_stackTabWidget->widget(i); if (bin->fileName().compare(m_tempPartsBinLocation) == 0) { m_stackTabWidget->removeTab(i); break; } } } void BinManager::addPartToBinAux(PartsBinPaletteWidget *bin, ModelPart *modelPart, int position) { if(bin) { if (bin->fastLoaded()) { bin->load(bin->fileName(), bin, false); } bin->addPart(modelPart, position); setDirtyTab(bin); } } void BinManager::load(const QString& filename) { openBin(filename); } void BinManager::setDirtyTab(PartsBinPaletteWidget* w, bool dirty) { /* if (!w->windowTitle().contains(FritzingWindow::QtFunkyPlaceholder)) { // trying to deal with the warning in QWidget::setWindowModified // but setting the title here doesn't work QString t = w->windowTitle(); if (t.isEmpty()) t = " "; w->setWindowTitle(t); } */ w->setWindowModified(dirty); if(m_stackTabWidget != NULL) { int tabIdx = m_stackTabWidget->indexOf(w); m_stackTabWidget->setTabText(tabIdx, w->title()+(dirty? " *": "")); } else { qWarning() << tr("BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty").arg(w->title()); } } void BinManager::updateTitle(PartsBinPaletteWidget* w, const QString& newTitle) { if(m_stackTabWidget != NULL) { m_stackTabWidget->setTabText(m_stackTabWidget->indexOf(w), newTitle+" *"); setDirtyTab(w); } else { qWarning() << tr("BinManager::updateTitle: Couldn't set the bin '%1' as dirty").arg(w->title()); } } PartsBinPaletteWidget* BinManager::newBinIn() { PartsBinPaletteWidget* bin = newBin(); bin->setPaletteModel(new PaletteModel(true, false), true); bin->setTitle(tr("New bin (%1)").arg(++m_unsavedBinsCount)); insertBin(bin, m_stackTabWidget->count()); bin->setReadOnly(false); renameBin(); return bin; } PartsBinPaletteWidget* BinManager::openBinIn(QString fileName, bool fastLoad) { if(fileName.isNull() || fileName.isEmpty()) { fileName = QFileDialog::getOpenFileName( this, tr("Select a Fritzing Parts Bin file to open"), m_defaultSaveFolder, tr("Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2)") .arg(FritzingBinExtension).arg(FritzingBundledBinExtension) ); if (fileName.isNull()) return NULL; } PartsBinPaletteWidget* bin = NULL; bool createNewOne = false; if(m_openedBins.contains(fileName)) { bin = m_openedBins[fileName]; if(m_stackTabWidget) { m_stackTabWidget->setCurrentWidget(bin); } else { m_openedBins.remove(fileName); createNewOne = true; } } else { createNewOne = true; } if(createNewOne) { bin = newBin(); if(bin->open(fileName, bin, fastLoad)) { m_openedBins[fileName] = bin; insertBin(bin, m_stackTabWidget->count()); // to force the user to take a decision of what to do with the imported parts if(fileName.endsWith(FritzingBundledBinExtension)) { setDirtyTab(bin); } } } if (!fastLoad) { setAsCurrentBin(bin); } return bin; } PartsBinPaletteWidget* BinManager::openCoreBinIn() { PartsBinPaletteWidget* bin = findBin(CorePartsBinLocation); if (bin != NULL) { setAsCurrentTab(bin); } else { bin = newBin(); bin->setAllowsChanges(false); bin->load(BinManager::CorePartsBinLocation, bin, false); insertBin(bin, 0); } setAsCurrentBin(bin); return bin; } PartsBinPaletteWidget* BinManager::newBin() { PartsBinPaletteWidget* bin = new PartsBinPaletteWidget(m_referenceModel, m_infoView, m_undoStack,this); connect( bin, SIGNAL(fileNameUpdated(PartsBinPaletteWidget*, const QString&, const QString&)), this, SLOT(updateFileName(PartsBinPaletteWidget*, const QString&, const QString&)) ); connect( bin, SIGNAL(focused(PartsBinPaletteWidget*)), this, SLOT(setAsCurrentBin(PartsBinPaletteWidget*)) ); connect(bin, SIGNAL(saved(bool)), m_mainWindow, SLOT(binSaved(bool))); connect(m_mainWindow, SIGNAL(alienPartsDismissed()), bin, SLOT(removeAlienParts())); return bin; } void BinManager::currentChanged(int index) { for (int i = 0; i < m_stackTabWidget->count(); i++) { PartsBinPaletteWidget* bin = (PartsBinPaletteWidget *) m_stackTabWidget->widget(i); if (bin == NULL) continue; if (!bin->hasMonoIcon()) continue; if (i == index) { m_stackTabWidget->setTabIcon(i, bin->icon()); } else { m_stackTabWidget->setTabIcon(i, bin->monoIcon()); } } PartsBinPaletteWidget *bin = getBin(index); if (bin) setAsCurrentBin(bin); } void BinManager::setAsCurrentBin(PartsBinPaletteWidget* bin) { if (bin == NULL) { qWarning() << tr("Cannot set a NULL bin as the current one"); return; } if (bin->fastLoaded()) { bin->load(bin->fileName(), bin, false); } if (m_currentBin == bin) return; if (bin->fileName().compare(SearchBinLocation) == 0) { bin->focusSearch(); } /* // jrc 3-july-2013 commented out this stylesheet change: // it causes the tab bar to lose its scroll position // the stylesheet change is commented out in the qss file, so visually it's a no-op QString style = m_mainWindow->styleSheet(); if(m_currentBin && m_stackTabWidget) { StackTabBar *currTabBar = m_stackTabWidget->stackTabBar(); currTabBar->setProperty("current","false"); currTabBar->setStyleSheet(""); currTabBar->setStyleSheet(style); } if(m_stackTabWidget) { m_currentBin = bin; StackTabBar *currTabBar = m_stackTabWidget->stackTabBar(); currTabBar->setProperty("current","true"); currTabBar->setStyleSheet(""); currTabBar->setStyleSheet(style); } */ } void BinManager::closeBinIn(int index) { if (m_stackTabWidget->count() == 1) return; int realIndex = index == -1? m_stackTabWidget->currentIndex(): index; PartsBinPaletteWidget *w = getBin(realIndex); if(w && w->beforeClosing()) { m_stackTabWidget->removeTab(realIndex); m_openedBins.remove(w->fileName()); } } PartsBinPaletteWidget* BinManager::getBin(int index) { return qobject_cast(m_stackTabWidget->widget(index)); } PartsBinPaletteWidget* BinManager::currentBin() { return qobject_cast(m_stackTabWidget->currentWidget()); } void BinManager::updateFileName(PartsBinPaletteWidget* bin, const QString &newFileName, const QString &oldFilename) { m_openedBins.remove(oldFilename); m_openedBins[newFileName] = bin; } void BinManager::saveStateAndGeometry() { QSettings settings; settings.remove("bins2"); // clean up previous state settings.beginGroup("bins2"); for(int j = m_stackTabWidget->count() - 1; j >= 0; j--) { PartsBinPaletteWidget *bin = qobject_cast(m_stackTabWidget->widget(j)); if (bin) { settings.beginGroup(QString::number(j)); settings.setValue("location", BinLocation::toString(bin->location())); settings.setValue("title", bin->title()); settings.setValue("path", bin->fileName()); settings.endGroup(); } } settings.endGroup(); } void BinManager::restoreStateAndGeometry(QList & actualLocations) { QList theoreticalLocations; QSettings settings; settings.beginGroup("bins2"); int size = settings.childGroups().size(); if (size == 0) { // first time readTheoreticalLocations(theoreticalLocations); } else { for (int i = 0; i < size; ++i) { settings.beginGroup(QString::number(i)); BinLocation * location = new BinLocation; location->location = BinLocation::fromString(settings.value("location").toString()); location->path = settings.value("path").toString(); location->title = settings.value("title").toString(); theoreticalLocations.append(location); settings.endGroup(); } } foreach (BinLocation * location, actualLocations) { location->marked = false; } foreach (BinLocation * tLocation, theoreticalLocations) { foreach (BinLocation * aLocation, actualLocations) { if (aLocation->title.compare(tLocation->title) == 0 && aLocation->location == tLocation->location) { aLocation->marked = true; break; } } } QList tempLocations(actualLocations); actualLocations.clear(); foreach (BinLocation * tLocation, theoreticalLocations) { tLocation->marked = false; bool gotOne = false; for (int ix = 0; ix < tempLocations.count(); ix++) { BinLocation * aLocation = tempLocations[ix]; if (aLocation->title.compare(tLocation->title) == 0 && aLocation->location == tLocation->location) { gotOne = true; actualLocations.append(aLocation); tempLocations.removeAt(ix); //DebugDialog::debug("adding loc 1 " + aLocation->path); break; } } if (gotOne) continue; if (tLocation->title == "___*___") { for (int ix = 0; ix < tempLocations.count(); ix++) { BinLocation * aLocation = tempLocations[ix]; if (!aLocation->marked && aLocation->location == tLocation->location) { gotOne = true; actualLocations.append(aLocation); tempLocations.removeAt(ix); //DebugDialog::debug("adding loc 2 " + aLocation->path); break; } } } if (gotOne) continue; if (!tLocation->path.isEmpty()) { QFileInfo info(tLocation->path); if (info.exists()) { //DebugDialog::debug("adding loc 3 " + tLocation->path); actualLocations.append(tLocation); tLocation->marked = true; } } } foreach (BinLocation * tLocation, theoreticalLocations) { if (!tLocation->marked) { delete tLocation; } } // catch the leftovers actualLocations.append(tempLocations); //foreach (BinLocation * aLocation, tempLocations) { //DebugDialog::debug("adding loc 4 " + aLocation->path); //} } void BinManager::readTheoreticalLocations(QList & theoreticalLocations) { QFile file(":/resources/bins/order.xml"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse order.xml: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } QDomElement bin = domDocument.documentElement().firstChildElement("bin"); while (!bin.isNull()) { BinLocation * location = new BinLocation; location->title = bin.attribute("title", ""); location->location = BinLocation::fromString(bin.attribute("location", "")); theoreticalLocations.append(location); bin = bin.nextSiblingElement("bin"); } } void BinManager::hackLocalContrib(QList & locations) { // with release 0.7.12, there is no more local contrib bin // so clear out existing local contrib bins by copying parts to mine bin BinLocation * localContrib = NULL; BinLocation * myParts = NULL; foreach (BinLocation * location, locations) { if (location->location == BinLocation::User) { if (location->title == "Contributed Parts") { localContrib = location; } else if (location->title == "My Parts") { myParts = location; } } } if (localContrib == NULL) return; if (myParts == NULL) { createIfBinNotExists(MyPartsBinLocation, MyPartsBinTemplateLocation); myParts = new BinLocation; myParts->location = BinLocation::User; myParts->path = MyPartsBinLocation; QString icon; getBinTitle(myParts->path, myParts->title, icon); locations.append(myParts); } QString errorStr; int errorLine; int errorColumn; QFile contribFile(localContrib->path); QDomDocument contribDoc; bool result = contribDoc.setContent(&contribFile, true, &errorStr, &errorLine, &errorColumn); locations.removeOne(localContrib); contribFile.close(); bool removed = contribFile.remove(); if (!removed) { DebugDialog::debug("failed to remove contrib bin"); } if (!result) return; QFile myPartsFile(myParts->path); QDomDocument myPartsDoc; if (!myPartsDoc.setContent(&myPartsFile, true, &errorStr, &errorLine, &errorColumn)) { return; } QDomElement myPartsRoot = myPartsDoc.documentElement(); QDomElement myPartsInstances = myPartsRoot.firstChildElement("instances"); bool changed = false; QDomElement contribRoot = contribDoc.documentElement(); QDomElement contribInstances = contribRoot.firstChildElement("instances"); QDomElement contribInstance = contribInstances.firstChildElement("instance"); while (!contribInstance.isNull()) { QString moduleIDRef = contribInstance.attribute("moduleIdRef"); QDomElement myPartsInstance = myPartsInstances.firstChildElement("instance"); bool already = false; while (!myPartsInstance.isNull()) { QString midr = myPartsInstance.attribute("moduleIdRef"); if (midr == moduleIDRef) { already = true; break; } myPartsInstance = myPartsInstance.nextSiblingElement("instance"); } if (!already) { QDomNode node = contribInstance.cloneNode(true); myPartsInstances.appendChild(node); changed = true; } contribInstance = contribInstance.nextSiblingElement("instance"); } if (changed) { TextUtils::writeUtf8(myParts->path, myPartsDoc.toString(0)); } } void BinManager::findAllBins(QList & locations) { BinLocation * location = new BinLocation; location->location = BinLocation::App; location->path = CorePartsBinLocation; QString icon; getBinTitle(location->path, location->title, icon); locations.append(location); location = new BinLocation; location->location = BinLocation::App; location->path = ContribPartsBinLocation; getBinTitle(location->path, location->title, icon); locations.append(location); QDir userBinsDir(FolderUtils::getUserDataStorePath("bins")); findBins(userBinsDir, locations, BinLocation::User); QDir dir(FolderUtils::getApplicationSubFolderPath("bins")); dir.cd("more"); findBins(dir, locations, BinLocation::More); } void BinManager::findBins(QDir & dir, QList & locations, BinLocation::Location loc) { QStringList filters; filters << "*"+FritzingBinExtension; QFileInfoList files = dir.entryInfoList(filters); foreach(QFileInfo info, files) { BinLocation * location = new BinLocation; location->path = info.absoluteFilePath(); location->location = loc; QString icon; getBinTitle(location->path, location->title, icon); locations.append(location); } } bool BinManager::getBinTitle(const QString & filename, QString & binName, QString & iconName) { QFile file(filename); file.open(QFile::ReadOnly); QXmlStreamReader xml(&file); xml.setNamespaceProcessing(false); while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: if (xml.name().toString().compare("module") == 0) { iconName = xml.attributes().value("icon").toString(); } else if (xml.name().toString().compare("title") == 0) { binName = xml.readElementText(); return true; } break; default: break; } } return false; } void BinManager::tabCloseRequested(int index) { closeBinIn(index); } void BinManager::addPartTo(PartsBinPaletteWidget* bin, ModelPart* mp, bool setDirty) { if(mp) { bool alreadyIn = bin->contains(mp->moduleID()); bin->addPart(mp); if(!alreadyIn && setDirty) { setDirtyTab(bin,true); } } } void BinManager::editSelectedPartNewFrom(PartsBinPaletteWidget* bin) { ItemBase * itemBase = bin->selectedItemBase(); m_mainWindow->getPartsEditorNewAnd(itemBase); } bool BinManager::isTabReorderingEvent(QDropEvent* event) { const QMimeData *m = event->mimeData(); QStringList formats = m->formats(); return formats.contains("action") && (m->data("action") == "tab-reordering"); } const QString &BinManager::getSelectedModuleIDFromSketch() { return m_mainWindow->selectedModuleID(); } QList BinManager::openedBinsActions(const QString &moduleId) { QMap titlesAndActions; // QMap sorts values by key for (int i = 0; i < m_stackTabWidget->count(); i++) { PartsBinPaletteWidget* pppw = (PartsBinPaletteWidget *) m_stackTabWidget->widget(i); if (pppw->readOnly()) continue; QAction *act = pppw->addPartToMeAction(); act->setEnabled(!pppw->contains(moduleId)); titlesAndActions[pppw->title()] = act; } return titlesAndActions.values(); } void BinManager::openBin(const QString &filename) { openBinIn(filename, false); } MainWindow* BinManager::mainWindow() { return m_mainWindow; } void BinManager::initNames() { BinManager::MyPartsBinLocation = FolderUtils::getUserDataStorePath("bins")+"/my_parts.fzb"; BinManager::MyPartsBinTemplateLocation =":/resources/bins/my_parts.fzb"; BinManager::SearchBinLocation = FolderUtils::getUserDataStorePath("bins")+"/search.fzb"; BinManager::SearchBinTemplateLocation =":/resources/bins/search.fzb"; BinManager::ContribPartsBinLocation = FolderUtils::getApplicationSubFolderPath("bins")+"/contribParts.fzb"; BinManager::CorePartsBinLocation = FolderUtils::getApplicationSubFolderPath("bins")+"/core.fzb"; BinManager::TempPartsBinTemplateLocation =":/resources/bins/temp.fzb"; StandardBinIcons.insert(BinManager::MyPartsBinLocation, "Mine.png"); StandardBinIcons.insert(BinManager::SearchBinLocation, "Search.png"); StandardBinIcons.insert(BinManager::ContribPartsBinLocation, "Contrib.png"); StandardBinIcons.insert(BinManager::CorePartsBinLocation, "Core.png"); } void BinManager::search(const QString & searchText) { PartsBinPaletteWidget * searchBin = getOrOpenSearchBin(); if (searchBin == NULL) return; FileProgressDialog progress(tr("Searching..."), 0, this); progress.setIncValueMod(10); connect(m_referenceModel, SIGNAL(addSearchMaximum(int)), &progress, SLOT(addMaximum(int))); connect(m_referenceModel, SIGNAL(incSearch()), &progress, SLOT(incValue())); QList modelParts = m_referenceModel->search(searchText, false); progress.setIncValueMod(1); searchBin->removeParts(); foreach (ModelPart * modelPart, modelParts) { //DebugDialog::debug(modelPart->title()); if (modelPart->itemType() == ModelPart::SchematicSubpart) { } else if (modelPart->moduleID().contains(PartFactory::OldSchematicPrefix)) { } else { this->addPartTo(searchBin, modelPart, false); } progress.incValue(); } setDirtyTab(searchBin); } bool BinManager::currentViewIsIconView() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return true; return bin->currentViewIsIconView(); } void BinManager::toIconView() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; bin->toIconView(); } void BinManager::toListView() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; bin->toListView(); } void BinManager::updateBinCombinedMenuCurrent() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; updateBinCombinedMenu(bin); } void BinManager::updateBinCombinedMenu(PartsBinPaletteWidget * bin) { if (m_combinedMenu == NULL) return; m_saveBinAction->setEnabled(bin->allowsChanges()); m_renameBinAction->setEnabled(bin->canClose()); m_closeBinAction->setEnabled(bin->canClose()); m_deleteBinAction->setEnabled(bin->canClose()); ItemBase *itemBase = bin->selectedItemBase(); bool enabled = (itemBase != NULL); m_editPartNewAction->setEnabled(enabled && itemBase->canEditPart()); bool enableAnyway = false; #ifndef QT_NO_DEBUG enableAnyway = true; #endif m_exportPartAction->setEnabled(enabled && (!itemBase->modelPart()->isCore() || enableAnyway)); m_removePartAction->setEnabled(enabled && bin->allowsChanges()); m_findPartAction->setEnabled(enabled); } void BinManager::createCombinedMenu() { m_combinedMenu = new QMenu(tr("Bin"), this); m_openAction = new QAction(tr("Import..."), this); m_openAction->setStatusTip(tr("Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)")); connect(m_openAction, SIGNAL(triggered()), this, SLOT(mainLoad())); m_newBinAction = new QAction(tr("New Bin..."), this); m_newBinAction->setStatusTip(tr("Create a new parts bin")); connect(m_newBinAction, SIGNAL(triggered()),this, SLOT(newBinIn())); m_closeBinAction = new QAction(tr("Close Bin"), this); m_closeBinAction->setStatusTip(tr("Close parts bin")); connect(m_closeBinAction, SIGNAL(triggered()),this, SLOT(closeBin())); m_deleteBinAction = new QAction(tr("Delete Bin"), this); m_deleteBinAction->setStatusTip(tr("Delete parts bin")); connect(m_deleteBinAction, SIGNAL(triggered()),this, SLOT(deleteBin())); m_saveBinAction = new QAction(tr("Save Bin"), this); m_saveBinAction->setStatusTip(tr("Save parts bin")); connect(m_saveBinAction, SIGNAL(triggered()),this, SLOT(saveBin())); m_saveBinAsAction = new QAction(tr("Save Bin As..."), this); m_saveBinAsAction->setStatusTip(tr("Save parts bin as...")); connect(m_saveBinAsAction, SIGNAL(triggered()),this, SLOT(saveBinAs())); m_saveBinAsBundledAction = new QAction(tr("Export Bin..."), this); m_saveBinAsBundledAction->setStatusTip(tr("Save parts bin in compressed format...")); connect(m_saveBinAsBundledAction, SIGNAL(triggered()),this, SLOT(saveBundledBin())); m_renameBinAction = new QAction(tr("Rename Bin..."), this); m_renameBinAction->setStatusTip(tr("Rename parts bin...")); connect(m_renameBinAction, SIGNAL(triggered()),this, SLOT(renameBin())); m_copyToSketchAction = new QAction(tr("Copy to Sketch"), this); m_copyToSketchAction->setStatusTip(tr("Copy all the parts in the bin to a sketch")); connect(m_copyToSketchAction, SIGNAL(triggered()),this, SLOT(copyToSketch())); m_copyAllToSketchAction = new QAction(tr("Copy all to Sketch"), this); m_copyAllToSketchAction->setStatusTip(tr("Copy all loaded parts to the sketch")); connect(m_copyAllToSketchAction, SIGNAL(triggered()),this, SLOT(copyAllToSketch())); m_showListViewAction = new QAction(tr("Show Bin in List View"), this); m_showListViewAction->setCheckable(true); m_showListViewAction->setStatusTip(tr("Display parts as a list")); connect(m_showListViewAction, SIGNAL(triggered()),this, SLOT(toListView())); m_showIconViewAction = new QAction(tr("Show Bin in Icon View"), this); m_showIconViewAction->setCheckable(true); m_showIconViewAction->setStatusTip(tr("Display parts as icons")); connect(m_showIconViewAction, SIGNAL(triggered()),this, SLOT(toIconView())); m_combinedMenu->addAction(m_openAction); m_combinedMenu->addSeparator(); m_combinedMenu->addAction(m_newBinAction); m_combinedMenu->addAction(m_closeBinAction); m_combinedMenu->addAction(m_deleteBinAction); m_combinedMenu->addAction(m_saveBinAction); m_combinedMenu->addAction(m_saveBinAsAction); m_combinedMenu->addAction(m_saveBinAsBundledAction); m_combinedMenu->addAction(m_renameBinAction); #ifndef QT_NO_DEBUG m_combinedMenu->addAction(m_copyToSketchAction); m_combinedMenu->addAction(m_copyAllToSketchAction); #endif m_combinedMenu->addSeparator(); m_combinedMenu->addAction(m_showIconViewAction); m_combinedMenu->addAction(m_showListViewAction); m_editPartNewAction = new QAction(tr("Edit Part (new parts editor)..."),this); m_exportPartAction = new QAction(tr("Export Part..."),this); m_removePartAction = new QAction(tr("Remove Part"),this); m_findPartAction = new QAction(tr("Find Part in Sketch"),this); connect(m_editPartNewAction, SIGNAL(triggered()),this, SLOT(editSelectedNew())); connect(m_exportPartAction, SIGNAL(triggered()),this, SLOT(exportSelected())); connect(m_removePartAction, SIGNAL(triggered()),this, SLOT(removeSelected())); connect(m_findPartAction, SIGNAL(triggered()),this, SLOT(findSelected())); connect(m_combinedMenu, SIGNAL(aboutToShow()), this, SLOT(updateBinCombinedMenuCurrent())); m_combinedMenu->addSeparator(); m_combinedMenu->addAction(m_editPartNewAction); m_combinedMenu->addAction(m_exportPartAction); m_combinedMenu->addAction(m_removePartAction); m_combinedMenu->addAction(m_findPartAction); } void BinManager::createContextMenus() { m_binContextMenu = new QMenu(this); m_binContextMenu->addAction(m_closeBinAction); m_binContextMenu->addAction(m_deleteBinAction); m_binContextMenu->addAction(m_saveBinAction); m_binContextMenu->addAction(m_saveBinAsAction); m_binContextMenu->addAction(m_saveBinAsBundledAction); m_binContextMenu->addAction(m_renameBinAction); m_partContextMenu = new QMenu(this); m_partContextMenu->addAction(m_editPartNewAction); m_partContextMenu->addAction(m_exportPartAction); m_partContextMenu->addAction(m_removePartAction); m_partContextMenu->addAction(m_findPartAction); } void BinManager::closeBin() { closeBinIn(-1); } void BinManager::deleteBin() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; QMessageBox::StandardButton answer = QMessageBox::question( this, tr("Delete bin"), tr("Do you really want to delete bin '%1'? This action cannot be undone.").arg(bin->title()), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); // TODO: make button texts translatable if (answer != QMessageBox::Yes) return; QString filename = bin->fileName(); closeBinIn(-1); QFile::remove(filename); } void BinManager::importPartToMineBin(const QString & filename) { if (!filename.isEmpty() && !filename.isNull()) { PartsBinPaletteWidget * bin = getOrOpenBin(MyPartsBinLocation, MyPartsBinTemplateLocation); if (bin == NULL) return; setAsCurrentTab(bin); importPart(filename, bin); } } void BinManager::importPartToCurrentBin(const QString & filename) { if (!filename.isEmpty() && !filename.isNull()) { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; importPart(filename, bin); } } void BinManager::importPart(const QString & filename, PartsBinPaletteWidget * bin) { ModelPart *mp = m_mainWindow->loadBundledPart(filename, !bin->allowsChanges()); if (bin->allowsChanges()) { addPartTo(bin, mp, true); } } void BinManager::editSelectedNew() { editSelectedPartNewFrom(currentBin()); } void BinManager::renameBin() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; if (!currentBin()->allowsChanges()) { // TODO: disable menu item instead QMessageBox::warning(this, tr("Read-only bin"), tr("This bin cannot be renamed.")); return; } bool ok; QString newTitle = QInputDialog::getText( this, tr("Rename bin"), tr("Please choose a name for the bin:"), QLineEdit::Normal, bin->title(), &ok ); if(ok) { bin->setTitle(newTitle); m_stackTabWidget->stackTabBar()->setTabToolTip(m_stackTabWidget->currentIndex(), newTitle); bin->addPartToMeAction()->setText(newTitle); updateTitle(bin, newTitle); } } void BinManager::saveBin() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; bool result = bin->save(); if (result) setDirtyTab(currentBin(),false); } void BinManager::saveBinAs() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; bin->saveAs(); } void BinManager::updateViewChecks(bool iconView) { if (m_showListViewAction == NULL) return; if (m_showIconViewAction == NULL) return; if (iconView) { m_showListViewAction->setChecked(false); m_showIconViewAction->setChecked(true); } else { m_showListViewAction->setChecked(true); m_showIconViewAction->setChecked(false); } } QMenu * BinManager::binContextMenu(PartsBinPaletteWidget * bin) { updateBinCombinedMenu(bin); return m_binContextMenu; } QMenu * BinManager::partContextMenu(PartsBinPaletteWidget * bin) { updateBinCombinedMenu(bin); return m_partContextMenu; } QMenu * BinManager::combinedMenu(PartsBinPaletteWidget * bin) { updateBinCombinedMenu(bin); return m_combinedMenu; } QMenu * BinManager::combinedMenu() { return m_combinedMenu; } bool BinManager::removeSelected() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return false; ModelPart * mp = bin->selectedModelPart(); if (mp == NULL) return false; if (m_mainWindow->anyUsePart(mp->moduleID())) { QMessageBox::warning(this, tr("Remove from Bin"), tr("Unable to remove part '%1'--it is in use in a sketch").arg(mp->title())); return false; } QMessageBox::StandardButton answer = QMessageBox::question( this, tr("Remove from bin"), tr("Do you really want to remove '%1' from the bin? This operation cannot be undone.").arg(mp->title()), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); // TODO: make button texts translatable if(answer != QMessageBox::Yes) return false; m_undoStack->push(new QUndoCommand("Parts bin: part removed")); bin->removePart(mp->moduleID(), mp->path()); bin->setDirty(); return true; } void BinManager::findSelected() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; ModelPart * mp = bin->selectedModelPart(); if (mp == NULL) return; m_mainWindow->selectPartsWithModuleID(mp); } void BinManager::exportSelected() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; ModelPart * mp = bin->selectedModelPart(); if (mp == NULL) return; emit savePartAsBundled(mp->moduleID()); } void BinManager::saveBundledBin() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; bin->saveBundledBin(); } void BinManager::setTabIcon(PartsBinPaletteWidget* w, QIcon * icon) { if (m_stackTabWidget != NULL) { int tabIdx = m_stackTabWidget->indexOf(w); m_stackTabWidget->setTabIcon(tabIdx, *icon); } } void BinManager::copyFilesToContrib(ModelPart * mp, QWidget * originator) { PartsBinPaletteWidget * bin = qobject_cast(originator); if (bin == NULL) return; if (bin->fileName().compare(m_tempPartsBinLocation) != 0) return; // only copy from temp bin QString path = mp->path(); if (path.isEmpty()) return; QFileInfo info(path); QFile fzp(path); QString parts = FolderUtils::getUserDataStorePath("parts"); FolderUtils::slamCopy(fzp, parts + "/contrib/" + info.fileName()); QString prefix = parts + "/svg/contrib/"; QDir dir = info.absoluteDir(); dir.cdUp(); dir.cd("svg"); dir.cd("contrib"); QList viewIDs; viewIDs << ViewLayer::IconView << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; foreach (ViewLayer::ViewID viewID, viewIDs) { QString fn = mp->hasBaseNameFor(viewID); if (!fn.isEmpty()) { QFile svg(dir.absoluteFilePath(fn)); FolderUtils::slamCopy(svg, prefix + fn); } } } bool BinManager::isTempPartsBin(PartsBinPaletteWidget * bin) { return bin->fileName().compare(m_tempPartsBinLocation) == 0; } void BinManager::setTempPartsBinLocation(const QString & name) { m_tempPartsBinLocation = name; //StandardBinIcons.insert(m_tempPartsBinLocation, "Temp.png"); } void BinManager::mainLoad() { QString path = m_defaultSaveFolder; QString fileName = FolderUtils::getOpenFileName( this, tr("Select a Fritzing File to Open"), path, tr("Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3)") .arg(FritzingBundledPartExtension) .arg(FritzingBinExtension) .arg(FritzingBundledBinExtension) ); if (fileName.isEmpty()) return; if (fileName.endsWith(FritzingBundledPartExtension)) { importPartToCurrentBin(fileName); return; } if (fileName.endsWith(FritzingBinExtension) || fileName.endsWith(FritzingBundledBinExtension)) { openBinIn(fileName, false); } } void BinManager::hideTabBar() { m_stackTabWidget->stackTabBar()->hide(); } void BinManager::reloadPart(const QString & moduleID) { PartsBinView::removePartReference(moduleID); for(int j = 0; j < m_stackTabWidget->count(); j++) { PartsBinPaletteWidget *bin = qobject_cast(m_stackTabWidget->widget(j)); if (bin == NULL) continue; bin->reloadPart(moduleID); } } void BinManager::copyToSketch() { PartsBinPaletteWidget * bin = currentBin(); if (bin == NULL) return; QList modelParts = bin->getAllParts(); if (modelParts.count() == 0) return; if (m_mainWindow) { m_mainWindow->addToSketch(modelParts); } } void BinManager::copyAllToSketch() { QList modelParts; if (m_mainWindow) { m_mainWindow->addToSketch(modelParts); } } fritzing-app-0.9.2b/src/partsbinpalette/binmanager/binmanager.h000066400000000000000000000164561250202676700246700ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef BINMANAGER_H_ #define BINMANAGER_H_ #include #include #include #include #include class ModelPart; class PaletteModel; class MainWindow; class PartsBinPaletteWidget; struct BinLocation { enum Location { More, User, App, Outside, Any }; QString path; QString title; Location location; bool marked; static QString toString(BinLocation::Location location); static BinLocation::Location findLocation(const QString & filename); static BinLocation::Location fromString(const QString & locationString); }; class BinManager : public QFrame { Q_OBJECT public: BinManager(class ReferenceModel *referenceModel, class HtmlInfoView *infoView, class WaitPushUndoStack *undoStack, MainWindow* parent); virtual ~BinManager(); void initStandardBins(); void addBin(PartsBinPaletteWidget* bin); void insertBin(PartsBinPaletteWidget* bin, int index); void addPartToBin(ModelPart *modelPart, int position = -1); void addToMyParts(ModelPart *modelPart); void addToTempPartsBin(ModelPart *modelPart); void hideTempPartsBin(); void addNewPart(ModelPart *modelPart); bool beforeClosing(); bool hasAlienParts(); QString createIfMyPartsNotExists(); QString createIfSearchNotExists(); QString createIfBinNotExists(const QString & dest, const QString & source); void setInfoViewOnHover(bool infoViewOnHover); void load(const QString&); void setDirtyTab(PartsBinPaletteWidget* w, bool dirty=true); void updateTitle(PartsBinPaletteWidget* w, const QString& newTitle); void openBin(const QString &fileName); PartsBinPaletteWidget* openBinIn(QString fileName, bool fastLoad); PartsBinPaletteWidget* openCoreBinIn(); void closeBinIn(int index); void addPartTo(PartsBinPaletteWidget* bin, ModelPart* mp, bool setDirty); void editSelectedPartNewFrom(PartsBinPaletteWidget* bin); const QString &getSelectedModuleIDFromSketch(); QList openedBinsActions(const QString &moduleId); MainWindow* mainWindow(); void search(const QString & searchText); bool currentViewIsIconView(); void updateViewChecks(bool iconView); QMenu * binContextMenu(PartsBinPaletteWidget *); QMenu * partContextMenu(PartsBinPaletteWidget *); QMenu * combinedMenu(PartsBinPaletteWidget *); QMenu * combinedMenu(); void setTabIcon(PartsBinPaletteWidget* w, QIcon *); void copyFilesToContrib(ModelPart *, QWidget * originator); void importPartToCurrentBin(const QString & filename); void importPartToMineBin(const QString & filename); bool isTempPartsBin(PartsBinPaletteWidget * bin); void setTempPartsBinLocation(const QString & filename); void hideTabBar(); void reloadPart(const QString & moduleID); signals: void savePartAsBundled(const QString &moduleId); public slots: void updateBinCombinedMenuCurrent(); void toIconView(); void toListView(); void setAsCurrentBin(PartsBinPaletteWidget* bin); protected slots: void updateFileName(PartsBinPaletteWidget* bin, const QString &newFileName, const QString &oldFilename); void currentChanged(int); void tabCloseRequested(int); PartsBinPaletteWidget* newBinIn(); void closeBin(); void deleteBin(); void editSelectedNew(); void saveBin(); void saveBinAs(); void renameBin(); void copyToSketch(); void copyAllToSketch(); void exportSelected(); bool removeSelected(); void findSelected(); void saveBundledBin(); void mainLoad(); protected: void createMenu(); PartsBinPaletteWidget* newBin(); void registerBin(PartsBinPaletteWidget* bin); PartsBinPaletteWidget* getBin(int index); PartsBinPaletteWidget* currentBin(); void setAsCurrentTab(PartsBinPaletteWidget* bin); PartsBinPaletteWidget* getOrOpenMyPartsBin(); PartsBinPaletteWidget* getOrOpenSearchBin(); PartsBinPaletteWidget* getOrOpenBin(const QString & dest, const QString & source); void connectTabWidget(); void addPartToBinAux(PartsBinPaletteWidget *bin, ModelPart *modelPart, int position = -1); PartsBinPaletteWidget* findBin(const QString & binLocation); void createCombinedMenu(); void createContextMenus(); void saveStateAndGeometry(); void restoreStateAndGeometry(QList & actualLocations); void findAllBins(QList & actualLocations); void findBins(QDir &, QList & actualLocations, BinLocation::Location); void readTheoreticalLocations(QList & theoreticalLocations); void updateBinCombinedMenu(PartsBinPaletteWidget * bin); void importPart(const QString & filename, PartsBinPaletteWidget * bin); void hackLocalContrib(QList &); protected: ReferenceModel *m_referenceModel; HtmlInfoView *m_infoView; WaitPushUndoStack *m_undoStack; MainWindow *m_mainWindow; PartsBinPaletteWidget *m_currentBin; class StackTabWidget* m_stackTabWidget; QHash m_openedBins; int m_unsavedBinsCount; QString m_defaultSaveFolder; QMenu *m_binContextMenu; QMenu *m_combinedMenu; QAction *m_openAction; QAction *m_newBinAction; QAction *m_closeBinAction; QAction *m_deleteBinAction; QAction *m_saveBinAction; QAction *m_saveBinAsAction; QAction *m_saveBinAsBundledAction; QAction *m_renameBinAction; QAction *m_copyToSketchAction; QAction *m_copyAllToSketchAction; QAction *m_showListViewAction; QAction *m_showIconViewAction; QMenu *m_partContextMenu; QMenu *m_partMenu; QAction *m_editPartNewAction; QAction *m_exportPartAction; QAction *m_removePartAction; QAction *m_findPartAction; QString m_tempPartsBinLocation; protected: static QString StandardBinStyle; static QString CurrentBinStyle; public: static QString Title; static QString CorePartsBinLocation; static QString MyPartsBinLocation; static QString MyPartsBinTemplateLocation; static QString SearchBinLocation; static QString SearchBinTemplateLocation; static QString ContribPartsBinLocation; static QString TempPartsBinTemplateLocation; static QHash StandardBinIcons; static bool isTabReorderingEvent(QDropEvent* event); static void initNames(); static bool getBinTitle(const QString & filename, QString & binTitle, QString & binIcon); }; #endif /* BINMANAGER_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/binmanager/stacktabbar.cpp000066400000000000000000000106701250202676700253710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6549 $: $Author: irascibl@gmail.com $: $Date: 2012-10-11 06:54:26 +0200 (Do, 11. Okt 2012) $ ********************************************************************/ #include #include #include #include #include #include #include "stacktabbar.h" #include "stacktabwidget.h" #include "../partsbinpalettewidget.h" #include "../partsbinview.h" #include "../../debugdialog.h" StackTabBar::StackTabBar(StackTabWidget *parent) : QTabBar(parent) { setAcceptDrops(true); this->setUsesScrollButtons(true); //this->setContentsMargins(0,0,0,0); //this->setTabsClosable(true); setMovable(true); m_parent = parent; setProperty("current","false"); setExpanding(false); setElideMode(Qt::ElideRight); setIconSize(QSize(32, 32)); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); m_dragMoveTimer.setSingleShot(true); m_dragMoveTimer.setInterval(250); connect(&m_dragMoveTimer, SIGNAL(timeout()), this, SLOT(setIndex())); } bool StackTabBar::mimeIsAction(const QMimeData* m, const QString& action) { if(m) { QStringList formats = m->formats(); return formats.contains("action") && (m->data("action") == action); } else { return false; } } void StackTabBar::dragEnterEvent(QDragEnterEvent* event) { // Only accept if it's an part-reordering request const QMimeData *m = event->mimeData(); if (mimeIsAction(m, "part-reordering")) { event->acceptProposedAction(); } } void StackTabBar::dragLeaveEvent(QDragLeaveEvent *event) { Q_UNUSED(event); m_dragMoveTimer.stop(); } void StackTabBar::dragMoveEvent(QDragMoveEvent* event) { const QMimeData *m = event->mimeData(); int index = tabAt(event->pos()); if ((event->source() != this) && mimeIsAction(m,"part-reordering")) { PartsBinPaletteWidget* bin = qobject_cast(m_parent->widget(index)); if(bin && bin->allowsChanges()) { event->acceptProposedAction(); m_dragMoveTimer.setProperty("index", index); if (!m_dragMoveTimer.isActive()) { DebugDialog::debug("starting drag move timer"); m_dragMoveTimer.start(); } //DebugDialog::debug(QString("setting index %1").arg(index)); } } } void StackTabBar::dropEvent(QDropEvent* event) { int toIndex = tabAt(event->pos()); const QMimeData *m = event->mimeData(); if(mimeIsAction(m, "part-reordering")) { PartsBinPaletteWidget* bin = qobject_cast(m_parent->widget(toIndex)); if(bin && bin->allowsChanges()) { bin->currentView()->dropEventAux(event,true); } } event->acceptProposedAction(); } void StackTabBar::showContextMenu(const QPoint &point) { if (point.isNull()) return; int tabIndex = this->tabAt(point); PartsBinPaletteWidget* bin = qobject_cast(m_parent->widget(tabIndex)); if (bin == NULL) return; setCurrentIndex(tabIndex); QMenu * contextMenu = bin->binContextMenu(); if (contextMenu) { contextMenu->exec(this->mapToGlobal(point)); } delete contextMenu; } void StackTabBar::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QStylePainter painter(this); for(int i = 0; i < this->count(); ++i) { QStyleOptionTabV2 option; initStyleOption(&option, i); option.shape = RoundedNorth; option.text = ""; painter.drawControl(QStyle::CE_TabBarTab, option); } } void StackTabBar::setIndex() { if (sender() == NULL) return; bool ok = false; int index = sender()->property("index").toInt(&ok); if (!ok) return; setCurrentIndex(index); } fritzing-app-0.9.2b/src/partsbinpalette/binmanager/stacktabbar.h000066400000000000000000000033071250202676700250350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef STACKTABBAR_H_ #define STACKTABBAR_H_ #include #include class StackTabBar : public QTabBar { Q_OBJECT public: StackTabBar(class StackTabWidget *parent); protected: void dragEnterEvent(QDragEnterEvent* event); void dragLeaveEvent(QDragLeaveEvent* event); void dragMoveEvent(QDragMoveEvent* event); void dropEvent(QDropEvent* event); void paintEvent(QPaintEvent *event); bool mimeIsAction(const class QMimeData* m, const QString& action); public slots: void setIndex(); protected slots: void showContextMenu(const QPoint &point); protected: class StackTabWidget* m_parent; QTimer m_dragMoveTimer; }; #endif /* STACKTABBAR_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/binmanager/stacktabwidget.cpp000066400000000000000000000033431250202676700261070ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "stacktabwidget.h" #include "stacktabbar.h" #include "../../debugdialog.h" StackTabWidget::StackTabWidget(QWidget *parent) : QTabWidget(parent) { setElideMode(Qt::ElideRight); setTabBar(new StackTabBar(this)); connect( this, SIGNAL(currentChanged(int)), this, SLOT(informCurrentChanged(int)) ); connect( this, SIGNAL(tabCloseRequested(int)), this, SLOT(informTabCloseRequested(int)) ); } StackTabBar *StackTabWidget::stackTabBar() { return qobject_cast(tabBar()); } void StackTabWidget::informCurrentChanged(int index) { emit currentChanged(this,index); } void StackTabWidget::informTabCloseRequested(int index) { emit tabCloseRequested(this, index); } fritzing-app-0.9.2b/src/partsbinpalette/binmanager/stacktabwidget.h000066400000000000000000000031571250202676700255570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef STACKTABWIDGET_H_ #define STACKTABWIDGET_H_ #include #include #include #include // originally extracted from http://wiki.qtcentre.org/index.php?title=Movable_Tabs class StackTabWidget : public QTabWidget { Q_OBJECT public: StackTabWidget(QWidget *parent); class StackTabBar *stackTabBar(); public slots: void informCurrentChanged(int index); void informTabCloseRequested(int index); signals: void currentChanged(StackTabWidget *, int index); void tabCloseRequested(StackTabWidget *, int index); }; #endif /* STACKTABWIDGET_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/graphicsflowlayout.cpp000066400000000000000000000057661250202676700247450ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6924 $: $Author: irascibl@gmail.com $: $Date: 2013-03-10 16:58:25 +0100 (So, 10. Mrz 2013) $ ********************************************************************/ #include "graphicsflowlayout.h" #include "../utils/misc.h" static const int SpaceBefore = 5; static const int SpaceAfter = 3; GraphicsFlowLayout::GraphicsFlowLayout(QGraphicsLayoutItem *parent, int spacing) : QGraphicsLinearLayout(parent) { setSpacing(spacing); } void GraphicsFlowLayout::widgetEvent(QEvent * e) { Q_UNUSED(e) } void GraphicsFlowLayout::setGeometry(const QRectF &rect) { QGraphicsLinearLayout::setGeometry(rect); doLayout(rect); } int GraphicsFlowLayout::heightForWidth(int width) { int height = doLayout(QRectF(0, 0, width, 0)); return height; } int GraphicsFlowLayout::doLayout(const QRectF &rect) { double x = rect.x(); double y = rect.y(); double lineHeight = 0; for(int i=0; i < count(); i++) { QGraphicsLayoutItem* item = itemAt(i); int nextX = x + item->preferredSize().width() + spacing(); if (item->sizePolicy().horizontalPolicy() == QSizePolicy::Expanding) { int myY = y + lineHeight + spacing() + SpaceBefore; QRectF r(QPoint(rect.x(), myY), item->preferredSize()); item->setGeometry(r); x = rect.x(); y = myY + item->preferredSize().height() + spacing() + SpaceAfter; continue; } if (nextX - spacing() > rect.right() && lineHeight > 0) { x = rect.x(); y = y + lineHeight + spacing(); nextX = x + item->preferredSize().width() + spacing(); lineHeight = 0; } item->setGeometry(QRectF(QPoint(x, y), item->preferredSize())); x = nextX; // item->preferredSize().height() returns qreal, armel compiler complains lineHeight = qMax(lineHeight, item->preferredSize().height()); } m_lastWidth = rect.width(); return y + lineHeight - rect.y(); } void GraphicsFlowLayout::clear() { QList itemsToRemove; for(int i=0; i < count(); i++) { itemsToRemove << itemAt(i); } foreach(QGraphicsLayoutItem* iToR, itemsToRemove) { removeItem(iToR); } } int GraphicsFlowLayout::indexOf(const QGraphicsLayoutItem *item) { for(int i=0; i < count(); i++) { if(itemAt(i) == item) return i; } return -1; } fritzing-app-0.9.2b/src/partsbinpalette/graphicsflowlayout.h000066400000000000000000000031211250202676700243710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef GRAPHICSFLOWLAYOUT_H_ #define GRAPHICSFLOWLAYOUT_H_ #include #include #include #include class GraphicsFlowLayout : public QGraphicsLinearLayout { public: GraphicsFlowLayout(QGraphicsLayoutItem *parent, int spacing); void setGeometry(const QRectF &rect); int heightForWidth(int width); void clear(); int indexOf(const QGraphicsLayoutItem *item); protected: void widgetEvent(QEvent * e); int doLayout(const QRectF &rect); double m_lastWidth; }; #endif /* GRAPHICSFLOWLAYOUT_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/partsbincommands.cpp000066400000000000000000000071641250202676700243550ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "partsbincommands.h" #include "partsbinpalettewidget.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinBaseCommand::PartsBinBaseCommand(class PartsBinPaletteWidget* bin, QUndoCommand* parent) : QUndoCommand(parent) { m_bin = bin; } class PartsBinPaletteWidget* PartsBinBaseCommand::bin() { return m_bin; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinAddRemoveArrangeCommand::PartsBinAddRemoveArrangeCommand(class PartsBinPaletteWidget* bin, QString moduleID, QUndoCommand *parent) : PartsBinBaseCommand(bin, parent) { m_moduleID = moduleID; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinAddRemoveCommand::PartsBinAddRemoveCommand(class PartsBinPaletteWidget* bin, QString moduleID, QString path, int index, QUndoCommand *parent) : PartsBinAddRemoveArrangeCommand(bin, moduleID, parent) { m_index = index; m_path = path; } void PartsBinAddRemoveCommand::add() { m_bin->addPart(m_moduleID, m_index); } void PartsBinAddRemoveCommand::remove() { m_bin->removePart(m_moduleID, m_path); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinAddCommand::PartsBinAddCommand(class PartsBinPaletteWidget* bin, QString moduleID, QString path, int index, QUndoCommand *parent) : PartsBinAddRemoveCommand(bin, moduleID, path, index, parent) {} void PartsBinAddCommand::undo() { remove(); } void PartsBinAddCommand::redo() { add(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinRemoveCommand::PartsBinRemoveCommand(class PartsBinPaletteWidget* bin, QString moduleID, QString path, int index, QUndoCommand *parent) : PartsBinAddRemoveCommand(bin, moduleID, path, index, parent) {} void PartsBinRemoveCommand::undo() { add(); } void PartsBinRemoveCommand::redo() { remove(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PartsBinArrangeCommand::PartsBinArrangeCommand(class PartsBinPaletteWidget* bin, QString moduleID, int oldIndex, int newIndex, QUndoCommand *parent) : PartsBinAddRemoveArrangeCommand(bin, moduleID, parent) { m_oldIndex = oldIndex; m_newIndex = newIndex; } void PartsBinArrangeCommand::undo() { } void PartsBinArrangeCommand::redo() { } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// fritzing-app-0.9.2b/src/partsbinpalette/partsbincommands.h000066400000000000000000000051611250202676700240150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSBINCOMMANDS_H #define PARTSBINCOMMANDS_H #include #include class PartsBinBaseCommand : public QUndoCommand { public: PartsBinBaseCommand(class PartsBinPaletteWidget*, QUndoCommand* parent = 0); class PartsBinPaletteWidget* bin(); protected: class PartsBinPaletteWidget* m_bin; }; class PartsBinAddRemoveArrangeCommand : public PartsBinBaseCommand { public: PartsBinAddRemoveArrangeCommand(class PartsBinPaletteWidget*, QString moduleID, QUndoCommand *parent = 0); protected: QString m_moduleID; }; class PartsBinAddRemoveCommand : public PartsBinAddRemoveArrangeCommand { public: PartsBinAddRemoveCommand(class PartsBinPaletteWidget*, QString moduleID, QString path, int index, QUndoCommand *parent = 0); protected: void add(); void remove(); int m_index; QString m_path; }; class PartsBinAddCommand : public PartsBinAddRemoveCommand { public: PartsBinAddCommand(class PartsBinPaletteWidget*, QString moduleID, QString path, int index = -1, QUndoCommand *parent = 0); void undo(); void redo(); }; class PartsBinRemoveCommand : public PartsBinAddRemoveCommand { public: PartsBinRemoveCommand(class PartsBinPaletteWidget*, QString moduleID, QString path, int index = -1, QUndoCommand *parent = 0); void undo(); void redo(); }; class PartsBinArrangeCommand : public PartsBinAddRemoveArrangeCommand { public: PartsBinArrangeCommand(class PartsBinPaletteWidget*, QString moduleID, int oldIndex, int newIndex, QUndoCommand *parent = 0); void undo(); void redo(); protected: int m_oldIndex; int m_newIndex; }; #endif // PARTSBINCOMMANDS_H fritzing-app-0.9.2b/src/partsbinpalette/partsbiniconview.cpp000066400000000000000000000321661250202676700243770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include #include #include #include #include "partsbiniconview.h" #include "graphicsflowlayout.h" #include "../items/paletteitem.h" #include "../debugdialog.h" #include "svgiconwidget.h" #include "../model/palettemodel.h" #include "../items/partfactory.h" #include "partsbinpalettewidget.h" #define ICON_SPACING 5 PartsBinIconView::PartsBinIconView(ReferenceModel* referenceModel, PartsBinPaletteWidget *parent) : InfoGraphicsView((QWidget*)parent), PartsBinView(referenceModel, parent) { setAcceptWheelEvents(false); setFrameStyle(QFrame::Raised | QFrame::StyledPanel); setAlignment(Qt::AlignLeft | Qt::AlignTop); setAcceptDrops(true); QGraphicsScene* scene = new QGraphicsScene(this); this->setScene(scene); m_layouter = NULL; m_layout = NULL; setupLayout(); //connect(scene, SIGNAL(selectionChanged()), this, SLOT(informNewSelection())); //connect(scene, SIGNAL(changed(const QList&)), this, SLOT(informNewSelection())); m_noSelectionChangeEmition = false; setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setContextMenuPolicy(Qt::CustomContextMenu); connect( this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)) ); } void PartsBinIconView::setupLayout() { // TODO Mariano: smells like leak, but if this two lines are uncommented there's a crash // Also tried to iterate through layout children, but didn't work // Mariano: see under doClear--deleting m_layouter automatically deletes m_layout //delete m_layouter; //delete m_layout; m_layouter = new QGraphicsWidget; m_layout = new GraphicsFlowLayout(m_layouter, ICON_SPACING); scene()->addItem(m_layouter); } void PartsBinIconView::updateSize(QSize newSize) { updateSizeAux(newSize.width()); } void PartsBinIconView::updateSize() { updateSizeAux(width()); } void PartsBinIconView::updateSizeAux(int width) { setSceneRect(0, 0, width, m_layout->heightForWidth(width)); } void PartsBinIconView::resizeEvent(QResizeEvent * event) { InfoGraphicsView::resizeEvent(event); updateSize(event->size()); } void PartsBinIconView::mousePressEvent(QMouseEvent *event) { SvgIconWidget* icon = svgIconWidgetAt(event->pos()); if (icon == NULL || event->button() != Qt::LeftButton) { QGraphicsView::mousePressEvent(event); if (icon == NULL) { viewItemInfo(NULL); } } else { if (icon != NULL) { QList items = scene()->selectedItems(); for (int i = 0; i < items.count(); i++) { // not sure why clearSelection doesn't do the update, but whatever... items[i]->setSelected(false); items[i]->update(); } icon->setSelected(true); icon->update(); QPointF mts = this->mapToScene(event->pos()); QString moduleID = icon->moduleID(); QPoint hotspot = (mts.toPoint()-icon->pos().toPoint()); viewItemInfo(icon->itemBase()); mousePressOnItem(event->pos(), moduleID, icon->rect().size().toSize(), (mts - icon->pos()), hotspot ); } else { viewItemInfo(NULL); } } informNewSelection(); } void PartsBinIconView::doClear() { PartsBinView::doClear(); m_layout->clear(); delete m_layouter; // deleting layouter deletes layout delete scene(); // deleting scene deletes QGraphicsItems setScene(new QGraphicsScene(this)); setupLayout(); } void PartsBinIconView::addPart(ModelPart * model, int position) { PartsBinView::addPart(model, position); updateSize(); } void PartsBinIconView::removePart(const QString &moduleID) { SvgIconWidget *itemToRemove = NULL; int position = 0; foreach(QGraphicsItem *gIt, m_layouter->childItems()) { SvgIconWidget *it = dynamic_cast(gIt); if(it && it->moduleID() == moduleID) { itemToRemove = it; break; } else { position++; } } if(itemToRemove) { m_itemBaseHash.remove(moduleID); itemToRemove->setParentItem(NULL); m_noSelectionChangeEmition = true; m_layout->removeItem(itemToRemove); delete itemToRemove; } setSelected(position, true); updateSize(); } void PartsBinIconView::removeParts() { QList itemsToRemove; foreach(QGraphicsItem *gIt, m_layouter->childItems()) { SvgIconWidget *it = dynamic_cast(gIt); if(it) { itemsToRemove.append(it); } } m_itemBaseHash.clear(); foreach (SvgIconWidget * itemToRemove, itemsToRemove) { m_noSelectionChangeEmition = true; itemToRemove->setParentItem(NULL); m_layout->removeItem(itemToRemove); delete itemToRemove; } updateSize(); } int PartsBinIconView::setItemAux(ModelPart * modelPart, int position) { if (!modelPart || modelPart->itemType() == ModelPart::Unknown) { // don't want the empty root item to appear in the view return position; } emit settingItem(); QString moduleID = modelPart->moduleID(); if (contains(moduleID)) { return position; } SvgIconWidget* svgicon = NULL; if (modelPart->itemType() != ModelPart::Space) { ItemBase::PluralType plural; ItemBase * itemBase = loadItemBase(moduleID, plural); svgicon = new SvgIconWidget(modelPart, ViewLayer::IconView, itemBase, plural == ItemBase::Plural); } else { svgicon = new SvgIconWidget(modelPart, ViewLayer::IconView, NULL, false); } if(position > -1) { m_layout->insertItem(position, svgicon); } else { m_layout->addItem(svgicon); position = m_layout->count() - 1; } return position; } void PartsBinIconView::setPaletteModel(PaletteModel *model, bool clear) { PartsBinView::setPaletteModel(model, clear); updateSize(); } void PartsBinIconView::loadFromModel(PaletteModel * model) { ModelPart* root = model->root(); QList::const_iterator i; for (i = root->children().constBegin(); i != root->children().constEnd(); ++i) { ModelPart* mp = qobject_cast(*i); if (mp == NULL) continue; QDomElement instance = mp->instanceDomElement(); if (instance.isNull()) continue; QDomElement views = instance.firstChildElement("views"); if (views.isNull()) continue; QString name = ViewLayer::viewIDXmlName(ViewLayer::IconView); QDomElement view = views.firstChildElement(name); if (view.isNull()) continue; QDomElement geometry = view.firstChildElement("geometry"); if (geometry.isNull()) continue; setItemAux(mp); } } ModelPart *PartsBinIconView::selectedModelPart() { SvgIconWidget *icon = dynamic_cast(selectedAux()); if(icon) { return icon->modelPart(); } else { return NULL; } } ItemBase *PartsBinIconView::selectedItemBase() { SvgIconWidget *icon = dynamic_cast(selectedAux()); if(icon) { return icon->itemBase(); } else { return NULL; } } void PartsBinIconView::setSelected(int position, bool doEmit) { QGraphicsLayoutItem *glIt = m_layout->itemAt(position); if(SvgIconWidget *item = dynamic_cast(glIt)) { m_noSelectionChangeEmition = true; scene()->clearSelection(); m_noSelectionChangeEmition = !doEmit; item->setSelected(true); } } bool PartsBinIconView::swappingEnabled(ItemBase * itemBase) { Q_UNUSED(itemBase); return false; } int PartsBinIconView::selectedIndex() { int idx = 0; foreach(QGraphicsItem *it, scene()->items()) { SvgIconWidget *icon = dynamic_cast(it); if(icon) { if(icon->isSelected()) { return idx; } else { idx++; } } } return -1; } void PartsBinIconView::informNewSelection() { if(!m_noSelectionChangeEmition) { emit selectionChanged(selectedIndex()); } else { m_noSelectionChangeEmition = false; } } void PartsBinIconView::dragMoveEvent(QDragMoveEvent* event) { dragMoveEnterEventAux(event); } void PartsBinIconView::dropEvent(QDropEvent* event) { dropEventAux(event); } void PartsBinIconView::moveItem(int fromIndex, int toIndex) { itemMoved(fromIndex,toIndex); emit informItemMoved(fromIndex, toIndex); } void PartsBinIconView::itemMoved(int fromIndex, int toIndex) { QGraphicsLayoutItem *item = m_layout->itemAt(fromIndex); m_layout->removeItem(item); m_layout->insertItem(toIndex,item); updateSize(); setSelected(toIndex,/*doEmit*/false); } int PartsBinIconView::itemIndexAt(const QPoint& pos, bool &trustIt) { trustIt = true; SvgIconWidget *item = svgIconWidgetAt(pos); if(item) { int foundIdx = m_layout->indexOf(item); /*if(foundIdx != -1) { // no trouble finding it return foundIdx; } //else: something weird happened, the item exists, // but it should have and index > -1 */ if(foundIdx == -1) { // no indicator shown trustIt = false; } return foundIdx; } if(!inEmptyArea(pos)) { // let's see if moving around the point we can find a real item return m_layout->indexOf(closestItemTo(pos)); } else { // it's beyond the icons area, so -1 is OK return -1; } } bool PartsBinIconView::inEmptyArea(const QPoint& pos) { // used only by internal drag and drop if(m_layout->count() == 0) { return true; } else { QGraphicsLayoutItem *lastItem = m_layout->itemAt(m_layout->count()-1); QPointF itemBottomRightPoint = lastItem->graphicsItem()->mapToScene(lastItem->contentsRect().bottomRight()); return itemBottomRightPoint.y() < pos.y() || ( itemBottomRightPoint.y() >= pos.y() && itemBottomRightPoint.x() < pos.x() ); } } QGraphicsWidget* PartsBinIconView::closestItemTo(const QPoint& pos) { QPointF realPos = mapToScene(pos); SvgIconWidget *item = NULL; this -> setObjectName("partsIcon"); if((item = svgIconWidgetAt(realPos.x()+ICON_SPACING,realPos.y()+ICON_SPACING))) { return item; } if((item = svgIconWidgetAt(realPos.x()-ICON_SPACING,realPos.y()+ICON_SPACING))) { return item; } if((item = svgIconWidgetAt(realPos.x()+ICON_SPACING,realPos.y()-ICON_SPACING))) { return item; } if((item = svgIconWidgetAt(realPos.x()-ICON_SPACING,realPos.y()-ICON_SPACING))) { return item; } return NULL; } QList PartsBinIconView::orderedChildren() { QList result; for(int i=0; i < m_layout->count(); i++) { SvgIconWidget *it = dynamic_cast(m_layout->itemAt(i)); if(it) { result << it->modelPart(); } } return result; } void PartsBinIconView::showContextMenu(const QPoint& pos) { SvgIconWidget *it = svgIconWidgetAt(pos); QMenu *menu; if(it) { scene()->clearSelection(); it->setSelected(true); menu = m_parent->partContextMenu(); } else { menu = m_parent->combinedMenu(); } menu->exec(mapToGlobal(pos)); } SvgIconWidget * PartsBinIconView::svgIconWidgetAt(int x, int y) { return svgIconWidgetAt(QPoint(x, y)); } SvgIconWidget * PartsBinIconView::svgIconWidgetAt(const QPoint & pos) { QGraphicsItem * item = itemAt(pos); while (item != NULL) { SvgIconWidget * svgIconWidget = dynamic_cast(item); if (svgIconWidget != NULL) { return svgIconWidget; } item = item->parentItem(); } return NULL; } void PartsBinIconView::reloadPart(const QString & moduleID) { if (!contains(moduleID)) return; for (int i = 0; i < m_layout->count(); i++) { SvgIconWidget *it = dynamic_cast(m_layout->itemAt(i)); if (it == NULL) continue; if (it->itemBase()->moduleID().compare(moduleID) != 0) continue; ItemBase::PluralType plural; ItemBase * itemBase = loadItemBase(moduleID, plural); it->setItemBase(itemBase, plural); return; } } ItemBase * PartsBinIconView::loadItemBase(const QString & moduleID, ItemBase::PluralType & plural) { ItemBase * itemBase = ItemBaseHash.value(moduleID); ModelPart * modelPart = m_referenceModel->retrieveModelPart(moduleID); if (itemBase == NULL) { itemBase = PartFactory::createPart(modelPart, ViewLayer::NewTop, ViewLayer::IconView, ViewGeometry(), ItemBase::getNextID(), NULL, NULL, false); ItemBaseHash.insert(moduleID, itemBase); } m_itemBaseHash.insert(moduleID, itemBase); plural = itemBase->isPlural(); if (plural == ItemBase::NotSure) { QHash properties = modelPart->properties(); QString family = properties.value("family", "").toLower(); foreach (QString key, properties.keys()) { QStringList values = m_referenceModel->propValues(family, key, true); if (values.length() > 1) { plural = ItemBase::Plural; break; } } } return itemBase; } fritzing-app-0.9.2b/src/partsbinpalette/partsbiniconview.h000066400000000000000000000061371250202676700240430ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6494 $: $Author: irascibl@gmail.com $: $Date: 2012-09-29 17:40:27 +0200 (Sa, 29. Sep 2012) $ ********************************************************************/ #ifndef ICONVIEW_H_ #define ICONVIEW_H_ #include #include #include "partsbinview.h" #include "../sketch/infographicsview.h" QT_BEGIN_NAMESPACE class QDragEnterEvent; class QDropEvent; QT_END_NAMESPACE class PartsBinIconView : public InfoGraphicsView, public PartsBinView { Q_OBJECT public: PartsBinIconView(ReferenceModel* referenceModel, PartsBinPaletteWidget *parent); void loadFromModel(class PaletteModel *); void setPaletteModel(class PaletteModel *model, bool clear=false); void addPart(ModelPart * model, int position = -1); void removePart(const QString &moduleID); void removeParts(); bool swappingEnabled(ItemBase *); ModelPart *selectedModelPart(); ItemBase *selectedItemBase(); int selectedIndex(); QList orderedChildren(); void reloadPart(const QString & moduleID); protected: void doClear(); void moveItem(int fromIndex, int toIndex); int itemIndexAt(const QPoint& pos, bool &trustIt); void mousePressEvent(QMouseEvent *event); void dragMoveEvent(QDragMoveEvent* event); void dropEvent(QDropEvent* event); int setItemAux(ModelPart *, int position = -1); void resizeEvent(QResizeEvent * event); void updateSize(QSize newSize); void updateSize(); void updateSizeAux(int width); void setupLayout(); bool inEmptyArea(const QPoint& pos); QGraphicsWidget* closestItemTo(const QPoint& pos); class SvgIconWidget * svgIconWidgetAt(const QPoint & pos); class SvgIconWidget * svgIconWidgetAt(int x, int y); ItemBase * loadItemBase(const QString & moduleID, ItemBase::PluralType &); public slots: void setSelected(int position, bool doEmit=false); void informNewSelection(); void itemMoved(int fromIndex, int toIndex); protected slots: void showContextMenu(const QPoint& pos); signals: void informItemMoved(int fromIndex, int toIndex); void selectionChanged(int index); void settingItem(); protected: LayerHash m_viewLayers; QGraphicsWidget *m_layouter; class GraphicsFlowLayout *m_layout; QMenu *m_itemMenu; bool m_noSelectionChangeEmition; }; #endif /* ICONVIEW_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/partsbinlistview.cpp000066400000000000000000000250251250202676700244160ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6934 $: $Author: irascibl@gmail.com $: $Date: 2013-03-22 08:35:24 +0100 (Fr, 22. Mrz 2013) $ ********************************************************************/ #include #include #include "../debugdialog.h" #include "../infoview/htmlinfoview.h" #include "../items/itembase.h" #include "../fsvgrenderer.h" #include "../itemdrag.h" #include "../items/partfactory.h" #include "../layerattributes.h" #include "partsbinpalettewidget.h" #include "partsbinlistview.h" static const QColor SectionHeaderBackgroundColor(128, 128, 128); static const QColor SectionHeaderForegroundColor(32, 32, 32); PartsBinListView::PartsBinListView(ReferenceModel* referenceModel, PartsBinPaletteWidget *parent) : QListWidget((QWidget *) parent), PartsBinView(referenceModel, parent) { m_infoView = NULL; m_hoverItem = NULL; m_infoViewOnHover = true; setMouseTracking(true); setSpacing(2); setIconSize(QSize(16,16)); setSortingEnabled(false); setDragEnabled(true); viewport()->setAcceptDrops(true); setDropIndicatorShown(true); setDragDropMode(QAbstractItemView::DragDrop); setAcceptDrops(true); setContextMenuPolicy(Qt::CustomContextMenu); connect( this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)) ); } PartsBinListView::~PartsBinListView() { } void PartsBinListView::doClear() { m_hoverItem = NULL; PartsBinView::doClear(); clear(); } int PartsBinListView::setItemAux(ModelPart * modelPart, int position) { if (modelPart->modelPartShared() == NULL) return position; if (modelPart->itemType() == ModelPart::Unknown) { // don't want the empty root to appear in the view return position; } emit settingItem(); QString moduleID = modelPart->moduleID(); if (contains(moduleID)) { return position; } QListWidgetItem * lwi = new QListWidgetItem(modelPart->title()); if (modelPart->itemType() == ModelPart::Space) { lwi->setBackground(QBrush(SectionHeaderBackgroundColor)); lwi->setForeground(QBrush(SectionHeaderForegroundColor)); lwi->setData(Qt::UserRole, 0); lwi->setFlags(0); lwi->setText(" " + TranslatedCategoryNames.value(modelPart->instanceText(), modelPart->instanceText())); } else { loadImage(modelPart, lwi, moduleID); } if(position > -1 && position < count()) { insertItem(position, lwi); } else { addItem(lwi); position = this->count(); } return position; } void PartsBinListView::mouseMoveEvent(QMouseEvent *event) { if(m_infoViewOnHover) { QListWidgetItem * item = itemAt(event->pos()); if (item != NULL) { showInfo(item); } else { m_hoverItem = NULL; } } QListWidget::mouseMoveEvent(event); } void PartsBinListView::showInfo(QListWidgetItem * item) { if (item == m_hoverItem) { // no change return; } if (m_hoverItem != NULL && m_infoView != NULL) { ItemBase * itemBase = itemItemBase(m_hoverItem); if (itemBase != NULL) { m_infoView->hoverLeaveItem(NULL, NULL, itemBase); } } if (item == NULL) { return; } m_hoverItem = item; if (m_infoView != NULL) { ItemBase * itemBase = itemItemBase(item); if (itemBase != NULL) { m_infoView->hoverEnterItem(NULL, NULL, itemBase, swappingEnabled()); } } } void PartsBinListView::mousePressEvent(QMouseEvent *event) { m_dragStartPos = event->pos(); QListWidget::mousePressEvent(event); QListWidgetItem * current = currentItem(); if (current == NULL) { m_hoverItem = NULL; if (m_infoView != NULL) m_infoView->viewItemInfo(NULL, NULL, false); return; } showInfo(current); if (m_infoView != NULL) m_infoView->viewItemInfo(NULL, itemItemBase(current), false); } void PartsBinListView::setInfoView(HtmlInfoView * infoView) { m_infoView = infoView; } void PartsBinListView::removePart(const QString &moduleID) { m_hoverItem = NULL; int idxToRemove = position(moduleID); if(idxToRemove > -1) { m_itemBaseHash.remove(moduleID); delete takeItem(idxToRemove); } } void PartsBinListView::removeParts() { m_hoverItem = NULL; m_itemBaseHash.clear(); while (count() > 0) { delete takeItem(0); } } int PartsBinListView::position(const QString &moduleID) { for(int i=0; i < count(); i++) { if(itemModuleID(item(i)) == moduleID) { return i; } } return -1; } ItemBase * PartsBinListView::itemItemBase(const QListWidgetItem *item) const { return item->data(Qt::UserRole).value(); } ModelPart *PartsBinListView::itemModelPart(const QListWidgetItem *item) const { ItemBase * itemBase = itemItemBase(item); if (itemBase == NULL) return NULL; return itemBase->modelPart(); } const QString &PartsBinListView::itemModuleID(const QListWidgetItem *item) { ModelPart *modelPart = itemModelPart(item); if (modelPart == NULL) { // this shouldn't happen? return ___emptyString___; } return modelPart->moduleID(); } ItemBase *PartsBinListView::selectedItemBase() { if(selectedItems().size()==1) { return itemItemBase(selectedItems()[0]); } return NULL; } ModelPart *PartsBinListView::selectedModelPart() { if(selectedItems().size()==1) { return itemModelPart(selectedItems()[0]); } return NULL; } bool PartsBinListView::swappingEnabled() { return false; } void PartsBinListView::setSelected(int position, bool doEmit) { Q_UNUSED(doEmit); if(position > -1 && position < count()) { item(position)->setSelected(true); } else { setCurrentRow(position); } } /*void PartsBinListView::dragEnterEvent(QDragEnterEvent* event) { dragMoveEnterEventAux(event); }*/ void PartsBinListView::dropEvent(QDropEvent* event) { dropEventAux(event); QListWidget::dropEvent(event); } void PartsBinListView::startDrag(Qt::DropActions supportedActions) { QListWidget::startDrag(supportedActions); ItemDrag::dragIsDone(); } void PartsBinListView::moveItem(int fromIndex, int toIndex) { itemMoved(fromIndex,toIndex); emit informItemMoved(fromIndex, toIndex); } void PartsBinListView::itemMoved(int fromIndex, int toIndex) { QListWidgetItem *item = takeItem(fromIndex); insertItem(toIndex,item); //setItemSelected(item,true); setSelected(toIndex); } int PartsBinListView::itemIndexAt(const QPoint& pos, bool &trustIt) { trustIt = true; QListWidgetItem *item = itemAt(pos); if(item) { return row(item); } else if(rect().contains(pos)) { trustIt = false; return -1; } else { return -1; } } bool PartsBinListView::dropMimeData(int index, const QMimeData *data, Qt::DropAction action) { Q_UNUSED(index); Q_UNUSED(action); if(data->hasFormat("action") && (data->data("action") == "part-reordering")) { /*QByteArray itemData = data->data("application/x-dnditemdata"); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString moduleID; QPointF offset; dataStream >> moduleID >> offset; ModelPart *modelPart = m_partHash[moduleID]; QModelIndex idx = model()->index(index, 0); model()->setData(idx, qVariantFromValue(modelPart), Qt::UserRole);*/ return true; } else { return false; } return true; } QMimeData * PartsBinListView::mimeData(const QList items) const { if (items.count()>1) { throw "PartsBinListView::mimeData too many items"; } if(items.count()==1) { QListWidgetItem * item = items.at(0); ModelPart * modelPart = itemModelPart(item); QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << modelPart->moduleID() << QPointF(0,0); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-dnditemdata", itemData); mimeData->setData("action", "part-reordering"); return mimeData; } else { return QListWidget::mimeData(items); } } QStringList PartsBinListView::mimeTypes() const { QStringList list; list << "application/x-dnditemdata" << "action"; return list; } QList PartsBinListView::orderedChildren() { QList result; for(int i=0; i < count(); i++) { ModelPart *mp = itemModelPart(item(i)); if(mp) { result << mp; } } return result; } void PartsBinListView::showContextMenu(const QPoint& pos) { QListWidgetItem *it = itemAt(pos); QMenu *menu; if(it) { clearSelection(); it->setSelected(true); menu = m_parent->partContextMenu(); } else { menu = m_parent->combinedMenu(); } menu->exec(mapToGlobal(pos)); } void PartsBinListView::reloadPart(const QString & moduleID) { if (!contains(moduleID)) return; for(int i = 0; i < count(); i++) { QListWidgetItem * lwi = item(i); ItemBase * itemBase = itemItemBase(lwi); if (itemBase == NULL) continue; if (itemBase->moduleID().compare(moduleID) == 0) { lwi->setText(itemBase->title()); loadImage(itemBase->modelPart(), lwi, moduleID); return; } } } void PartsBinListView::loadImage(ModelPart * modelPart, QListWidgetItem * lwi, const QString & moduleID) { ItemBase * itemBase = ItemBaseHash.value(moduleID); if (itemBase == NULL) { itemBase = PartFactory::createPart(modelPart, ViewLayer::NewTop, ViewLayer::IconView, ViewGeometry(), ItemBase::getNextID(), NULL, NULL, false); ItemBaseHash.insert(moduleID, itemBase); LayerAttributes layerAttributes; itemBase->initLayerAttributes(layerAttributes, ViewLayer::IconView, ViewLayer::Icon, itemBase->viewLayerPlacement(), false, false); FSvgRenderer * renderer = itemBase->setUpImage(modelPart, layerAttributes); if (renderer != NULL) { if (itemBase) { itemBase->setFilename(renderer->filename()); } itemBase->setSharedRendererEx(renderer); } } lwi->setData(Qt::UserRole, qVariantFromValue( itemBase ) ); QSize size(HtmlInfoView::STANDARD_ICON_IMG_WIDTH, HtmlInfoView::STANDARD_ICON_IMG_HEIGHT); QPixmap * pixmap = FSvgRenderer::getPixmap(itemBase->renderer(), size); lwi->setIcon(QIcon(*pixmap)); delete pixmap; lwi->setData(Qt::UserRole + 1, itemBase->renderer()->defaultSize()); m_itemBaseHash.insert(moduleID, itemBase); } fritzing-app-0.9.2b/src/partsbinpalette/partsbinlistview.h000066400000000000000000000056211250202676700240630ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef LISTVIEW_H_ #define LISTVIEW_H_ #include #include #include "partsbinview.h" class PartsBinListView : public QListWidget, public PartsBinView { Q_OBJECT public: PartsBinListView(ReferenceModel* referenceModel, PartsBinPaletteWidget *parent); ~PartsBinListView(); void setInfoView(class HtmlInfoView *); void removePart(const QString &moduleID); void removeParts(); ModelPart *selectedModelPart(); ItemBase *selectedItemBase(); bool swappingEnabled(); int position(const QString &moduleID); QList orderedChildren(); void reloadPart(const QString & moduleID); public slots: void setSelected(int position, bool doEmit=false); void itemMoved(int fromIndex, int toIndex); protected slots: void showContextMenu(const QPoint& pos); signals: void informItemMoved(int fromIndex, int toIndex); void settingItem(); protected: void doClear(); void moveItem(int fromIndex, int toIndex); int itemIndexAt(const QPoint& pos, bool &trustIt); void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); //void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); void startDrag(Qt::DropActions supportedActions); int setItemAux(ModelPart * modelPart, int position = -1); ModelPart *itemModelPart(const QListWidgetItem *item) const; ItemBase *itemItemBase(const QListWidgetItem *item) const; const QString& itemModuleID(const QListWidgetItem *item); void showInfo(QListWidgetItem * item); bool dropMimeData(int index, const QMimeData *data, Qt::DropAction action); QMimeData * mimeData(const QList items) const; QStringList mimeTypes() const; void loadImage(ModelPart *, QListWidgetItem * lwi, const QString & moduleID); protected: class HtmlInfoView * m_infoView; QListWidgetItem * m_hoverItem; }; #endif /* LISTVIEW_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/partsbinpalettewidget.cpp000066400000000000000000000714741250202676700254230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "partsbinpalettewidget.h" #include "partsbincommands.h" #include "partsbiniconview.h" #include "partsbinlistview.h" #include "searchlineedit.h" #include "../utils/misc.h" #include "../debugdialog.h" #include "../infoview/htmlinfoview.h" #include "../utils/fileprogressdialog.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../mainwindow/mainwindow.h" // TODO: PartsBinPaletteWidget should not call MainWindow functions static QString CustomIconName = "Custom1.png"; static QString CustomIconTitle = "Fritzing Custom Icon"; inline bool isCustomSvg(const QString & string) { return string.startsWith(" PaletteBinModels; static QIcon EmptyIcon; ////////////////////////////////////////////// PartsBinPaletteWidget::PartsBinPaletteWidget(ReferenceModel *referenceModel, HtmlInfoView *infoView, WaitPushUndoStack *undoStack, BinManager* manager) : QFrame(manager) { m_binLabel = NULL; m_monoIcon = m_icon = NULL; m_searchLineEdit = NULL; m_saveQuietly = false; m_fastLoaded = false; m_model = NULL; m_loadingProgressDialog = NULL; setAcceptDrops(true); setAllowsChanges(true); m_manager = manager; m_referenceModel = referenceModel; m_canDeleteModel = false; m_orderHasChanged = false; Q_UNUSED(undoStack); m_undoStack = new WaitPushUndoStack(this); connect(m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool)) ); m_iconView = new PartsBinIconView(m_referenceModel, this); m_iconView->setInfoView(infoView); m_listView = new PartsBinListView(m_referenceModel, this); m_listView->setInfoView(infoView); m_stackedWidget = new QStackedWidget(this); m_stackedWidget->addWidget(m_iconView); m_stackedWidget->addWidget(m_listView); QVBoxLayout * vbl = new QVBoxLayout(this); vbl->setMargin(3); vbl->setSpacing(0); m_header = NULL; setupHeader(); if (m_header) { vbl->addWidget(m_header); QFrame * separator = new QFrame(); separator->setMaximumHeight(1); separator->setObjectName("partsBinHeaderSeparator"); separator->setFrameShape(QFrame::HLine); separator->setFrameShadow(QFrame::Plain); vbl->addWidget(separator); } vbl->addWidget(m_stackedWidget); this->setLayout(vbl); setObjectName("partsBinContainer"); toIconView(); m_defaultSaveFolder = FolderUtils::getUserDataStorePath("bins"); m_untitledFileName = tr("Untitled Bin"); connect(m_listView, SIGNAL(currentRowChanged(int)), m_iconView, SLOT(setSelected(int))); connect(m_iconView, SIGNAL(selectionChanged(int)), m_listView, SLOT(setSelected(int))); connect(m_listView, SIGNAL(currentRowChanged(int)), m_manager, SLOT(updateBinCombinedMenuCurrent())); connect(m_iconView, SIGNAL(selectionChanged(int)), m_manager, SLOT(updateBinCombinedMenuCurrent())); connect(m_listView, SIGNAL(informItemMoved(int,int)), m_iconView, SLOT(itemMoved(int,int))); connect(m_iconView, SIGNAL(informItemMoved(int,int)), m_listView, SLOT(itemMoved(int,int))); connect(m_listView, SIGNAL(informItemMoved(int,int)), this, SLOT(itemMoved())); connect(m_iconView, SIGNAL(informItemMoved(int,int)), this, SLOT(itemMoved())); if (m_binLabel) m_binLabel->setText(m_title); m_addPartToMeAction = new QAction(m_title,this); connect(m_addPartToMeAction, SIGNAL(triggered()),this, SLOT(addSketchPartToMe())); installEventFilter(this); } PartsBinPaletteWidget::~PartsBinPaletteWidget() { if (m_canDeleteModel && m_model != NULL) { delete m_model; m_model = NULL; } if (m_icon) delete m_icon; if (m_monoIcon) delete m_monoIcon; } void PartsBinPaletteWidget::cleanup() { foreach (PaletteModel * paletteModel, PaletteBinModels) { delete paletteModel; } PaletteBinModels.clear(); } QSize PartsBinPaletteWidget::sizeHint() const { return QSize(DockWidthDefault, PartsBinHeightDefault); } QString PartsBinPaletteWidget::title() const { return m_title; } void PartsBinPaletteWidget::setTitle(const QString &title) { if(m_title != title) { m_title = title; if (m_binLabel) m_binLabel->setText(title); } } void PartsBinPaletteWidget::setupHeader() { QMenu * combinedMenu = m_manager->combinedMenu(); if (combinedMenu == NULL) return; m_combinedBinMenuButton = newToolButton("partsBinCombinedMenuButton", ___emptyString___, ___emptyString___); m_combinedBinMenuButton->setMenu(combinedMenu); m_binLabel = new QLabel(this); m_binLabel->setObjectName("partsBinLabel"); m_binLabel->setWordWrap(false); m_searchLineEdit = new SearchLineEdit(this); m_searchLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); connect(m_searchLineEdit, SIGNAL(returnPressed()), this, SLOT(search())); m_searchStackedWidget = new QStackedWidget(this); m_searchStackedWidget->setObjectName("searchStackedWidget"); m_searchStackedWidget->addWidget(m_binLabel); m_searchStackedWidget->addWidget(m_searchLineEdit); m_header = new QFrame(this); m_header->setObjectName("partsBinHeader"); QHBoxLayout * hbl = new QHBoxLayout(); hbl->setSpacing(0); hbl->setMargin(0); hbl->addWidget(m_searchStackedWidget); hbl->addWidget(m_combinedBinMenuButton); m_header->setLayout(hbl); } void PartsBinPaletteWidget::setView(PartsBinView *view) { m_currentView = view; if(m_currentView == m_iconView) { m_stackedWidget->setCurrentIndex(0); m_manager->updateViewChecks(true); } else { m_stackedWidget->setCurrentIndex(1); m_manager->updateViewChecks(false); } } void PartsBinPaletteWidget::toIconView() { setView(m_iconView); } void PartsBinPaletteWidget::toListView() { disconnect(m_listView, SIGNAL(currentRowChanged(int)), m_iconView, SLOT(setSelected(int))); setView(m_listView); connect(m_listView, SIGNAL(currentRowChanged(int)), m_iconView, SLOT(setSelected(int))); } bool PartsBinPaletteWidget::saveAsAux(const QString &filename) { FileProgressDialog progress("Saving...", 0, this); QString oldFilename = m_fileName; setFilename(filename); QString title = this->title(); if(!title.isNull() && !title.isEmpty()) { ModelPartSharedRoot * root = m_model->rootModelPartShared(); if (root) root->setTitle(title); } if(m_orderHasChanged) { m_model->setOrdererChildren(m_iconView->orderedChildren()); } m_model->save(filename, false); if(m_orderHasChanged) { m_model->setOrdererChildren(QList()); m_orderHasChanged = false; } m_undoStack->setClean(); m_location = BinLocation::findLocation(filename); if(oldFilename != m_fileName) { emit fileNameUpdated(this,m_fileName,oldFilename); } emit saved(hasAlienParts()); foreach (QString path, m_removed) { bool result = QFile::remove(path); if (!result) { DebugDialog::debug("unable to delete '" + path + "' from bin"); } } m_removed.clear(); return true; } void PartsBinPaletteWidget::loadFromModel(PaletteModel *model) { m_iconView->loadFromModel(model); m_listView->setPaletteModel(model); afterModelSetted(model); m_canDeleteModel = false; // FApplication is holding this model, so don't delete it setFilename(model->loadedFrom()); } void PartsBinPaletteWidget::setPaletteModel(PaletteModel *model, bool clear) { m_iconView->setPaletteModel(model, clear); m_listView->setPaletteModel(model, clear); afterModelSetted(model); } void PartsBinPaletteWidget::afterModelSetted(PaletteModel *model) { grabTitle(model); m_model = model; m_undoStack->setClean(); setFilename(model->loadedFrom()); } void PartsBinPaletteWidget::grabTitle(PaletteModel *model) { ModelPartSharedRoot * root = model->rootModelPartShared(); if (!root) return; QString iconFilename = root->icon(); grabTitle(root->title(), iconFilename); root->setIcon(iconFilename); if (m_searchLineEdit) m_searchLineEdit->setText(root->searchTerm()); } void PartsBinPaletteWidget::grabTitle(const QString & title, QString & iconFilename) { m_title = title; m_addPartToMeAction->setText(m_title); if (m_binLabel) m_binLabel->setText(m_title); QString temp = BinManager::StandardBinIcons.value(m_fileName, ""); if (!temp.isEmpty()) { iconFilename = temp; } else if (iconFilename.isEmpty()) { iconFilename = CustomIconName; } if (isCustomSvg(iconFilename)) { // convert to image int w = TextUtils::getViewBoxCoord(iconFilename, 2); int h = TextUtils::getViewBoxCoord(iconFilename, 3); QImage image(w, h, QImage::Format_ARGB32); image.fill(0); QRectF target(0, 0, w, h); QSvgRenderer renderer(iconFilename.toUtf8()); QPainter painter; painter.begin(&image); renderer.render(&painter, target); painter.end(); //image.save(FolderUtils::getUserDataStorePath("") + "/test icon.png"); m_icon = new QIcon(QPixmap::fromImage(image)); m_monoIcon = new QIcon(":resources/bins/icons/Custom1-mono.png"); // TODO: hack svg to make a mono icon } else { QFileInfo info(m_fileName); QDir dir = info.absoluteDir(); QString path = dir.absoluteFilePath(iconFilename); QFile file1(path); if (file1.exists()) { m_icon = new QIcon(path); } else { path = ":resources/bins/icons/" + iconFilename; QFile file2(path); if (file2.exists()) { m_icon = new QIcon(path); } } if (m_icon) { int ix = path.lastIndexOf("."); path.insert(ix, "-mono"); QFile file3(path); if (file3.exists()) { m_monoIcon = new QIcon(path); } } } } void PartsBinPaletteWidget::addPart(ModelPart *modelPart, int position) { if (m_model == NULL) { return; } ModelPart *mp = m_model->addModelPart(m_model->root(),modelPart); m_iconView->addPart(mp, position); m_listView->addPart(mp, position); if(modelPart->isAlien()) { m_alienParts << mp->moduleID(); } } QToolButton* PartsBinPaletteWidget::newToolButton(const QString& btnObjName, const QString& imgPath, const QString &text) { QToolButton *toolBtn = new QToolButton(this); toolBtn->setObjectName(btnObjName); toolBtn->setToolButtonStyle(Qt::ToolButtonIconOnly); toolBtn->setArrowType(Qt::NoArrow); if (!text.isEmpty()) { toolBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolBtn->setText(text); } toolBtn->setPopupMode(QToolButton::InstantPopup); if (!imgPath.isEmpty()) { toolBtn->setIcon(QIcon(imgPath)); } toolBtn->setArrowType(Qt::NoArrow); return toolBtn; } bool PartsBinPaletteWidget::save() { bool result = true; if (FolderUtils::isEmptyFileName(m_fileName,m_untitledFileName) || currentBinIsCore()) { result = saveAs(); } else { saveAsAux(m_fileName); } return result; } bool PartsBinPaletteWidget::saveAs() { QString fileExt; QString fileName = QFileDialog::getSaveFileName( this, tr("Specify a file name"), (m_fileName.isNull() || m_fileName.isEmpty() || /* it's a resource */ m_fileName.startsWith(":"))? m_defaultSaveFolder+"/"+title()+FritzingBinExtension: m_fileName, tr("Fritzing Bin (*%1)").arg(FritzingBinExtension), &fileExt ); if (fileName.isEmpty()) return false; // Cancel pressed if(!FritzingWindow::alreadyHasExtension(fileName, FritzingBinExtension)) { fileName += FritzingBinExtension; } saveAsAux(fileName); return true; } void PartsBinPaletteWidget::saveBundledBin() { bool wasModified = m_isDirty; m_manager->mainWindow()->saveBundledNonAtomicEntity( m_fileName, FritzingBundledBinExtension, this, m_model->root()->getAllNonCoreParts(), true, "", true, false ); setDirty(wasModified); } bool PartsBinPaletteWidget::loadBundledAux(QDir &unzipDir, QList mps) { QStringList namefilters; namefilters << "*"+FritzingBinExtension; this->load(unzipDir.entryInfoList(namefilters)[0].filePath(), this, false); foreach(ModelPart* mp, mps) { if(mp->isAlien()) { // double check m_alienParts << mp->moduleID(); } } setFilename(___emptyString___); return true; } bool PartsBinPaletteWidget::open(QString fileName, QWidget * progressTarget, bool fastLoad) { QFile file(fileName); if (!file.exists()) { QMessageBox::warning(NULL, tr("Fritzing"), tr("Cannot find file %1.") .arg(fileName)); return false; } if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(NULL, tr("Fritzing"), tr("Cannot read file %1:\n%2.") .arg(fileName) .arg(file.errorString())); return false; } file.close(); if(fileName.endsWith(FritzingBinExtension)) { load(fileName, progressTarget, fastLoad); m_isDirty = false; } else if(fileName.endsWith(FritzingBundledBinExtension)) { return m_manager->mainWindow()->loadBundledNonAtomicEntity(fileName,this,false, false); } return true; } void PartsBinPaletteWidget::load(const QString &filename, QWidget * progressTarget, bool fastLoad) { // TODO deleting this local palette reference model deletes modelPartShared held by the palette bin modelParts //PaletteModel * paletteReferenceModel = new PaletteModel(true, true); m_location = BinLocation::findLocation(filename); //DebugDialog::debug("loading bin"); if (fastLoad) { QString binName, iconName; if (BinManager::getBinTitle(filename, binName, iconName)) { m_fileName = filename; grabTitle(binName, iconName); m_fastLoaded = true; } return; } m_fastLoaded = false; PaletteModel * paletteBinModel = PaletteBinModels.value(filename); if (paletteBinModel == NULL) { paletteBinModel = new PaletteModel(true, false); //DebugDialog::debug("after palette model"); QString name = m_title; if (name.isEmpty()) name = QFileInfo(filename).completeBaseName(); bool deleteWhenDone = false; if (progressTarget != NULL) { //DebugDialog::debug("open progress " + filename); deleteWhenDone = true; progressTarget = m_loadingProgressDialog = new FileProgressDialog(tr("Loading..."), 200, progressTarget); m_loadingProgressDialog->setBinLoadingChunk(200); m_loadingProgressDialog->setBinLoadingCount(1); m_loadingProgressDialog->setMessage(tr("loading bin '%1'").arg(name)); m_loadingProgressDialog->show(); } if (progressTarget) { connect(paletteBinModel, SIGNAL(loadingInstances(ModelBase *, QDomElement &)), progressTarget, SLOT(loadingInstancesSlot(ModelBase *, QDomElement &))); connect(paletteBinModel, SIGNAL(loadingInstance(ModelBase *, QDomElement &)), progressTarget, SLOT(loadingInstanceSlot(ModelBase *, QDomElement &))); connect(m_iconView, SIGNAL(settingItem()), progressTarget, SLOT(settingItemSlot())); connect(m_listView, SIGNAL(settingItem()), progressTarget, SLOT(settingItemSlot())); } DebugDialog::debug(QString("loading bin '%1'").arg(name)); bool result = paletteBinModel->loadFromFile(filename, m_referenceModel, false); //DebugDialog::debug(QString("done loading bin '%1'").arg(name)); if (!result) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Fritzing cannot load the parts bin")); } else { m_fileName = filename; setPaletteModel(paletteBinModel,true); PaletteBinModels.insert(filename, paletteBinModel); } if (progressTarget) { //DebugDialog::debug("close progress " + filename); disconnect(paletteBinModel, SIGNAL(loadingInstances(ModelBase *, QDomElement &)), progressTarget, SLOT(loadingInstancesSlot(ModelBase *, QDomElement &))); disconnect(paletteBinModel, SIGNAL(loadingInstance(ModelBase *, QDomElement &)), progressTarget, SLOT(loadingInstanceSlot(ModelBase *, QDomElement &))); disconnect(m_iconView, SIGNAL(settingItem()), progressTarget, SLOT(settingItemSlot())); disconnect(m_listView, SIGNAL(settingItem()), progressTarget, SLOT(settingItemSlot())); if (deleteWhenDone) { m_loadingProgressDialog->close(); delete m_loadingProgressDialog; } m_loadingProgressDialog = NULL; } } else { m_fileName = filename; setPaletteModel(paletteBinModel,true); } //DebugDialog::debug("done loading bin"); //delete paletteReferenceModel; } void PartsBinPaletteWidget::undoStackCleanChanged(bool isClean) { if(!isClean && currentBinIsCore()) { setFilename(QString::null); } setWindowModified(!isClean); m_manager->setDirtyTab(this,isClean); } bool PartsBinPaletteWidget::currentBinIsCore() { return m_fileName == BinManager::CorePartsBinLocation; } bool PartsBinPaletteWidget::beforeClosing() { bool retval; if (this->isWindowModified()) { QMessageBox::StandardButton reply; if (m_saveQuietly) { reply = QMessageBox::Save; } else { QMessageBox messageBox(this); messageBox.setWindowTitle(tr("Save bin \"%1\"").arg(title())); messageBox.setText(tr("Do you want to save the changes you made in the bin \"%1\"?").arg(title())); messageBox.setInformativeText(tr("Your changes will be lost if you don't save them.")); messageBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Save); messageBox.setIcon(QMessageBox::Warning); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Save, tr("Save")); messageBox.setButtonText(QMessageBox::Discard, tr("Don't Save")); messageBox.button(QMessageBox::Discard)->setShortcut(tr("Ctrl+D")); messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); reply = (QMessageBox::StandardButton)messageBox.exec(); } if (reply == QMessageBox::Save) { retval = save(); } else if (reply == QMessageBox::Discard) { retval = true; } else { retval = false; } } else { retval = true; } return retval; } void PartsBinPaletteWidget::closeEvent(QCloseEvent* event) { QFrame::closeEvent(event); } void PartsBinPaletteWidget::mousePressEvent(QMouseEvent* event) { emit focused(this); QFrame::mousePressEvent(event); } ModelPart * PartsBinPaletteWidget::selectedModelPart() { return m_currentView->selectedModelPart(); } ItemBase * PartsBinPaletteWidget::selectedItemBase() { return m_currentView->selectedItemBase(); } bool PartsBinPaletteWidget::contains(const QString &moduleID) { return m_iconView->contains(moduleID); } bool PartsBinPaletteWidget::hasAlienParts() { return m_alienParts.size() > 0; } void PartsBinPaletteWidget::addPart(const QString& moduleID, int position) { ModelPart *modelPart = m_referenceModel->retrieveModelPart(moduleID); addPart(modelPart, position); } void PartsBinPaletteWidget::removePart(const QString & moduleID, const QString & path) { m_iconView->removePart(moduleID); m_listView->removePart(moduleID); // remove the model part from the model last, as this deletes it, // and the removePart calls above still need the modelpart m_model->removePart(moduleID); if (path.contains(FolderUtils::getUserDataStorePath())) { m_removed << path; } } void PartsBinPaletteWidget::removeParts() { m_iconView->removeParts(); m_listView->removeParts(); // remove the model part from the model last, as this deletes it, // and the removePart calls above still need the modelpart m_model->removeParts(); } void PartsBinPaletteWidget::removeAlienParts() { foreach(QString moduleID, m_alienParts) { removePart(moduleID, ""); } m_alienParts.clear(); } void PartsBinPaletteWidget::setInfoViewOnHover(bool infoViewOnHover) { if(m_iconView) m_iconView->setInfoViewOnHover(infoViewOnHover); if(m_listView) m_listView->setInfoViewOnHover(infoViewOnHover); } void PartsBinPaletteWidget::addPartCommand(const QString& moduleID) { /*bool updating = alreadyIn(moduleID); QString partTitle = m_referenceModel->partTitle(moduleID); if(partTitle.isEmpty()) partTitle = moduleID; QString undoStackMsg; if(!updating) { undoStackMsg = tr("\"%1\" added to bin").arg(partTitle); } else { undoStackMsg = tr("\"%1\" updated in bin").arg(partTitle); } QUndoCommand *parentCmd = new QUndoCommand(undoStackMsg); int index = m_listView->position(moduleID); new PartsBinAddCommand(this, moduleID, index, parentCmd); m_undoStack->push(parentCmd);*/ QMessageBox::StandardButton answer = QMessageBox::question( this, tr("Add to bin"), tr("Do you really want to add the selected part to the bin?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ); // TODO: make button texts translatable if(answer == QMessageBox::Yes) { int index = m_listView->position(moduleID); m_undoStack->push(new QUndoCommand("Parts bin: part added")); addPart(moduleID, index); } } void PartsBinPaletteWidget::itemMoved() { m_orderHasChanged = true; m_manager->setDirtyTab(this); } void PartsBinPaletteWidget::setDirty(bool dirty) { m_manager->setDirtyTab(this, dirty); m_isDirty = dirty; } const QString &PartsBinPaletteWidget::fileName() { return m_fileName; } bool PartsBinPaletteWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == this) { if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::GraphicsSceneDragMove || event->type() == QEvent::GraphicsSceneDrop || event->type() == QEvent::GraphicsSceneMousePress ) { emit focused(this); } } return QFrame::eventFilter(obj, event); } PartsBinView *PartsBinPaletteWidget::currentView() { return m_currentView; } void PartsBinPaletteWidget::dragEnterEvent(QDragEnterEvent *event) { QFrame::dragEnterEvent(event); } void PartsBinPaletteWidget::dragLeaveEvent(QDragLeaveEvent *event) { QFrame::dragLeaveEvent(event); } void PartsBinPaletteWidget::dragMoveEvent(QDragMoveEvent *event) { QFrame::dragMoveEvent(event); } void PartsBinPaletteWidget::dropEvent(QDropEvent *event) { QFrame::dropEvent(event); } QAction *PartsBinPaletteWidget::addPartToMeAction() { return m_addPartToMeAction; } void PartsBinPaletteWidget::addSketchPartToMe() { m_manager->openBinIn(this->m_fileName, false); QString moduleID = m_manager->getSelectedModuleIDFromSketch(); if (moduleID.isEmpty()) return; bool wasAlreadyIn = contains(moduleID); addPart(moduleID, -1); if(!wasAlreadyIn) { setDirty(); } } void PartsBinPaletteWidget::setFilename(const QString &filename) { m_fileName = filename; if (m_fileName.compare(BinManager::SearchBinLocation) == 0) { m_searchStackedWidget->setCurrentIndex(1); } bool acceptIt = !currentBinIsCore(); setAcceptDrops(acceptIt); m_iconView->setAcceptDrops(acceptIt); m_listView->setAcceptDrops(acceptIt); } void PartsBinPaletteWidget::search() { SearchLineEdit * edit = qobject_cast(sender()); if (edit == NULL) return; QString searchText = edit->text(); if (searchText.isEmpty()) return; ModelPartSharedRoot * root = m_model->rootModelPartShared(); if (root) { root->setSearchTerm(searchText); } m_manager->search(searchText); } bool PartsBinPaletteWidget::allowsChanges() { return m_allowsChanges; } bool PartsBinPaletteWidget::readOnly() { return !allowsChanges(); } void PartsBinPaletteWidget::setAllowsChanges(bool allowsChanges) { m_allowsChanges = allowsChanges; } void PartsBinPaletteWidget::setReadOnly(bool readOnly) { setAllowsChanges(!readOnly); } void PartsBinPaletteWidget::focusSearch() { if (m_searchLineEdit) { QTimer::singleShot(20, this, SLOT(focusSearchAfter())); } } void PartsBinPaletteWidget::focusSearchAfter() { //DebugDialog::debug("focus search after"); if (m_searchLineEdit->decoy()) { m_searchLineEdit->setDecoy(false); } m_searchLineEdit->setFocus(Qt::OtherFocusReason); } void PartsBinPaletteWidget::setSaveQuietly(bool saveQuietly) { m_saveQuietly = saveQuietly; } bool PartsBinPaletteWidget::currentViewIsIconView() { if (m_currentView == NULL) return true; return (m_currentView == m_iconView); } QIcon PartsBinPaletteWidget::icon() { if (m_icon) return *m_icon; return EmptyIcon; } bool PartsBinPaletteWidget::hasMonoIcon() { return m_monoIcon != NULL; } QIcon PartsBinPaletteWidget::monoIcon() { if (m_monoIcon) return *m_monoIcon; return EmptyIcon; } QMenu * PartsBinPaletteWidget::combinedMenu() { return m_manager->combinedMenu(this); } QMenu * PartsBinPaletteWidget::partContextMenu() { return m_manager->partContextMenu(this); } QMenu * PartsBinPaletteWidget::binContextMenu() { QMenu * menu = m_manager->binContextMenu(this); if (menu == NULL) return NULL; QMenu * newMenu = new QMenu(); foreach (QAction * action, menu->actions()) { newMenu->addAction(action); } // TODO: need to enable/disable actions based on this bin ModelPartSharedRoot * root = (m_model == NULL) ? NULL : m_model->rootModelPartShared(); if (root) { QString iconFilename = root->icon(); if (iconFilename.compare(CustomIconName) == 0 || isCustomSvg(iconFilename)) { newMenu->addSeparator(); QAction * action = new QAction(tr("Change icon color..."), newMenu); action->setToolTip(tr("Change the color of the icon for this bin.")); connect(action, SIGNAL(triggered()), this, SLOT(changeIconColor())); newMenu->addAction(action); } } return newMenu; } void PartsBinPaletteWidget::changeIconColor() { QImage image(":resources/bins/icons/" + CustomIconName); QColor initial(image.pixel(image.width() / 2, image.height() / 2)); QColor color = QColorDialog::getColor(initial, this, tr("Select a color for this icon"), 0 ); if (!color.isValid()) return; QRgb match = initial.rgba(); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { QRgb rgb = image.pixel(x, y); if (qRed(rgb) == qRed(match) && qBlue(rgb) == qBlue(match) && qGreen(rgb) == qGreen(match)) { image.setPixel(x, y, (color.rgb() & 0xffffff) | (qAlpha(rgb) << 24)); } } } #ifndef QT_NO_DEBUG //QFileInfo info(m_fileName); //image.save(FolderUtils::getUserDataStorePath("") + "/" + info.completeBaseName() + ".png"); #endif delete m_icon; m_icon = new QIcon(QPixmap::fromImage(image)); m_manager->setTabIcon(this, m_icon); setDirty(); ModelPartSharedRoot * root = m_model->rootModelPartShared(); if (root) { QSvgGenerator svgGenerator; svgGenerator.setResolution(90); svgGenerator.setTitle(CustomIconTitle); QBuffer buffer; svgGenerator.setOutputDevice(&buffer); QSize sz = image.size(); svgGenerator.setSize(sz); svgGenerator.setViewBox(QRect(0, 0, sz.width(), sz.height())); QPainter svgPainter(&svgGenerator); svgPainter.drawImage(QPoint(0,0), image); svgPainter.end(); QString svg(buffer.buffer()); root->setIcon(svg); } } bool PartsBinPaletteWidget::fastLoaded() { return m_fastLoaded; } BinLocation::Location PartsBinPaletteWidget::location() { return m_location; } bool PartsBinPaletteWidget::canClose() { switch (m_location) { case BinLocation::User: if (m_fileName.compare(BinManager::SearchBinLocation) == 0) return false; if (m_fileName.compare(BinManager::ContribPartsBinLocation) == 0) return false; if (m_fileName.compare(BinManager::MyPartsBinLocation) == 0) return false; if (m_manager->isTempPartsBin(this)) return false; return true; case BinLocation::More: return false; case BinLocation::App: return false; case BinLocation::Outside: default: return true; } } void PartsBinPaletteWidget::copyFilesToContrib(ModelPart * mp, QWidget * originator) { m_manager->copyFilesToContrib(mp, originator); } ModelPart * PartsBinPaletteWidget::root() { if (m_model == NULL) return NULL; return m_model->root(); } bool PartsBinPaletteWidget::isTempPartsBin() { return m_manager->isTempPartsBin(this); } void PartsBinPaletteWidget::reloadPart(const QString & moduleID) { m_iconView->reloadPart(moduleID); m_listView->reloadPart(moduleID); } QList PartsBinPaletteWidget::getAllParts() { QList empty; if (m_model == NULL) return empty; if (m_model->root() == NULL) return empty; return m_model->root()->getAllParts(); } fritzing-app-0.9.2b/src/partsbinpalette/partsbinpalettewidget.h000066400000000000000000000130461250202676700250570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . *********************************************** ********************* $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSBINPALETTEWIDGET_H_ #define PARTSBINPALETTEWIDGET_H_ #include #include #include #include #include "../model/palettemodel.h" #include "../model/modelpart.h" #include "../waitpushundostack.h" #include "../utils/fileprogressdialog.h" #include "../utils/bundler.h" #include "binmanager/binmanager.h" class PartsBinPaletteWidget : public QFrame, public Bundler { Q_OBJECT public: PartsBinPaletteWidget(class ReferenceModel *referenceModel, class HtmlInfoView *infoView, WaitPushUndoStack *undoStack, class BinManager* manager); ~PartsBinPaletteWidget(); QSize sizeHint() const; QString title() const; void setTitle(const QString &title); void loadFromModel(PaletteModel *model); void setPaletteModel(PaletteModel *model, bool clear = false); void addPart(ModelPart *modelPart, int position = -1); bool currentBinIsCore(); bool beforeClosing(); bool canClose(); ModelPart * selectedModelPart(); ItemBase * selectedItemBase(); bool hasAlienParts(); QList getAllParts(); void setInfoViewOnHover(bool infoViewOnHover); void addPart(const QString& moduleID, int position); void addNewPart(ModelPart *modelPart); void removePart(const QString & moduleID, const QString & path); void removeParts(); void load(const QString& filename, QWidget * progressTarget, bool fastLoad); bool contains(const QString &moduleID); void setDirty(bool dirty=true); const QString &fileName(); class PartsBinView *currentView(); QAction *addPartToMeAction(); bool allowsChanges(); bool readOnly(); void setAllowsChanges(bool); void setReadOnly(bool); void focusSearch(); void setSaveQuietly(bool); bool open(QString fileName, QWidget * progressTarget, bool fastLoad); bool currentViewIsIconView(); QIcon icon(); QIcon monoIcon(); bool hasMonoIcon(); void saveBundledBin(); QMenu * combinedMenu(); QMenu * binContextMenu(); QMenu * partContextMenu(); bool fastLoaded(); BinLocation::Location location(); void copyFilesToContrib(ModelPart *, QWidget * originator); ModelPart * root(); bool isTempPartsBin(); void reloadPart(const QString & moduleID); public slots: void addPartCommand(const QString& moduleID); void removeAlienParts(); void itemMoved(); void toIconView(); void toListView(); bool save(); bool saveAs(); void changeIconColor(); protected slots: void undoStackCleanChanged(bool isClean); void addSketchPartToMe(); void search(); void focusSearchAfter(); signals: void saved(bool hasPartsFromBundled); void fileNameUpdated(PartsBinPaletteWidget*, const QString &newFileName, const QString &oldFilename); void focused(PartsBinPaletteWidget*); protected: void dragEnterEvent(QDragEnterEvent *event); void dragLeaveEvent(QDragLeaveEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); void closeEvent(QCloseEvent *event); void mousePressEvent(QMouseEvent *event); bool eventFilter(QObject *obj, QEvent *event); void setupHeader(); void grabTitle(PaletteModel *model); void grabTitle(const QString & title, QString & iconFilename); void setView(class PartsBinView *view); bool saveAsAux(const QString &filename); void afterModelSetted(PaletteModel *model); QToolButton* newToolButton(const QString& btnObjName, const QString& imgPath, const QString &text); bool loadBundledAux(QDir &unzipDir, QList mps); void setFilename(const QString &filename); protected: PaletteModel *m_model; ReferenceModel *m_referenceModel; bool m_canDeleteModel; bool m_orderHasChanged; QString m_fileName; QString m_defaultSaveFolder; QString m_untitledFileName; QString m_title; bool m_isDirty; PartsBinView *m_currentView; class PartsBinIconView *m_iconView; class PartsBinListView *m_listView; QFrame *m_header; QLabel * m_binLabel; class SearchLineEdit * m_searchLineEdit; QToolButton * m_combinedBinMenuButton; WaitPushUndoStack *m_undoStack; BinManager *m_manager; QStringList m_alienParts; bool m_allowsChanges; bool m_saveQuietly; FileProgressDialog * m_loadingProgressDialog; QIcon * m_icon; QIcon * m_monoIcon; QAction *m_addPartToMeAction; QStackedWidget * m_stackedWidget; QStackedWidget * m_searchStackedWidget; bool m_fastLoaded; BinLocation::Location m_location; QStringList m_removed; public: static void cleanup(); public: static QString Title; }; #endif /* PARTSBINPALETTEWIDGET_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/partsbinview.cpp000066400000000000000000000162141250202676700235220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6494 $: $Author: irascibl@gmail.com $: $Date: 2012-09-29 17:40:27 +0200 (Sa, 29. Sep 2012) $ ********************************************************************/ #include #include #include #include #include "partsbinview.h" #include "partsbinpalettewidget.h" #include "../itemdrag.h" #include "../utils/misc.h" QHash PartsBinView::TranslatedCategoryNames; QHash PartsBinView::ItemBaseHash; PartsBinView::PartsBinView(ReferenceModel *referenceModel, PartsBinPaletteWidget *parent) { if (TranslatedCategoryNames.count() == 0) { TranslatedCategoryNames.insert("Basic", QObject::tr("Basic")); TranslatedCategoryNames.insert("Input", QObject::tr("Input")); TranslatedCategoryNames.insert("Output", QObject::tr("Output")); TranslatedCategoryNames.insert("ICs", QObject::tr("ICs")); TranslatedCategoryNames.insert("Power", QObject::tr("Power")); TranslatedCategoryNames.insert("Connection", QObject::tr("Connection")); TranslatedCategoryNames.insert("Microcontroller", QObject::tr("Microcontroller")); TranslatedCategoryNames.insert("Breadboard View", QObject::tr("Breadboard View")); TranslatedCategoryNames.insert("Schematic View", QObject::tr("Schematic View")); TranslatedCategoryNames.insert("PCB View", QObject::tr("PCB View")); TranslatedCategoryNames.insert("Tools", QObject::tr("Tools")); TranslatedCategoryNames.insert("Shields", QObject::tr("Shields")); TranslatedCategoryNames.insert("LilyPad", QObject::tr("LilyPad")); TranslatedCategoryNames.insert("Other", QObject::tr("Other")); TranslatedCategoryNames.insert("Sensors", QObject::tr("Sensors")); } m_referenceModel = referenceModel; m_parent = parent; } PartsBinView::~PartsBinView() { } void PartsBinView::cleanup() { foreach (ItemBase * itemBase, ItemBaseHash.values()) { delete itemBase; } } void PartsBinView::setPaletteModel(PaletteModel * model, bool clear) { if (clear) { doClear(); } if (model->root() == NULL) return; setItemAux(model->root()); setItem(model->root()); } void PartsBinView::reloadParts(PaletteModel * model) { setPaletteModel(model, true); } void PartsBinView::doClear() { m_itemBaseHash.clear(); } void PartsBinView::removePartReference(const QString & moduleID) { ItemBase * itemBase = ItemBaseHash.value(moduleID); if (itemBase) { ItemBaseHash.remove(moduleID); itemBase->deleteLater(); } } void PartsBinView::setItem(ModelPart * modelPart) { QList::const_iterator i; for (i = modelPart->children().constBegin(); i != modelPart->children().constEnd(); ++i) { setItemAux(dynamic_cast(*i)); } for (i = modelPart->children().constBegin(); i != modelPart->children().constEnd(); ++i) { setItem(dynamic_cast(*i)); } } void PartsBinView::addPart(ModelPart * model, int position) { int newPosition = setItemAux(model, position); setSelected(newPosition); } void PartsBinView::mousePressOnItem(const QPoint &dragStartPos, const QString &moduleId, const QSize &size, const QPointF &dataPoint, const QPoint &hotspot) { if (moduleId.isEmpty()) return; m_dragStartPos = dragStartPos; QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << moduleId << dataPoint; QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-dnditemdata", itemData); mimeData->setData("action", "part-reordering"); ItemDrag::setOriginator(this->m_parent); ItemDrag::setOriginatorIsTempBin(m_parent->isTempPartsBin()); QDrag * drag = new QDrag(dynamic_cast(this)); drag->setMimeData(mimeData); /* #ifndef Q_OS_LINUX // transparency doesn't seem to work for linux QPixmap pixmap(size); pixmap.fill(Qt::transparent); QPainter painter; painter.begin(&pixmap); QPen pen(QColor(0,0,0,127)); pen.setStyle(Qt::DashLine); pen.setWidth(1); painter.setPen(pen); painter.drawRect(0,0,pixmap.width() - 1, pixmap.height() - 1); painter.end(); drag->setPixmap(pixmap); drag->setHotSpot(hotspot); #else Q_UNUSED(hotspot); Q_UNUSED(size); #endif */ Q_UNUSED(hotspot); Q_UNUSED(size); // can set the pixmap, but can't hide it //QPixmap * pixmap = pitem->pixmap(); //if (pixmap != NULL) { //drag.setPixmap(*pixmap); //drag.setHotSpot(mts.toPoint() - pitem->pos().toPoint()); // // setDragCursor doesn't seem to help //drag.setDragCursor(*pitem->pixmap(), Qt::MoveAction); //drag.setDragCursor(*pitem->pixmap(), Qt::CopyAction); //drag.setDragCursor(*pitem->pixmap(), Qt::LinkAction); //drag.setDragCursor(*pitem->pixmap(), Qt::IgnoreAction); drag->exec(); /*if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) { } else { }*/ ItemDrag::dragIsDone(); } void PartsBinView::dragMoveEnterEventAux(QDragMoveEvent* event) { // Only accept if it's an icon-reordering request const QMimeData* m = event->mimeData(); QStringList formats = m->formats(); if (formats.contains("action") && (m->data("action") == "part-reordering")) { event->acceptProposedAction(); } } void PartsBinView::dropEventAux(QDropEvent* event, bool justAppend) { bool trustResult; int toIndex; if(justAppend) { toIndex = -1; trustResult = true; } else { toIndex = itemIndexAt(event->pos(), trustResult); } if(!trustResult) return; if(event->source() == dynamic_cast(this)) { int fromIndex = itemIndexAt(m_dragStartPos, trustResult); if(trustResult && fromIndex != toIndex) { moveItem(fromIndex,toIndex); } } else { QByteArray itemData = event->mimeData()->data("application/x-dnditemdata"); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString moduleID; QPointF offset; dataStream >> moduleID >> offset; ModelPart * mp = m_referenceModel->retrieveModelPart(moduleID); m_parent->copyFilesToContrib(mp, ItemDrag::originator()); if(mp) { if(m_parent->contains(moduleID)) { QMessageBox::information(NULL, QObject::tr("Part already in bin"), QObject::tr("The part that you have just added,\nis already there, we won't add it again, right?")); } else { m_parent->addPart(mp,toIndex); m_parent->setDirty(); } } } event->acceptProposedAction(); } bool PartsBinView::contains(const QString &moduleID) { return m_itemBaseHash.contains(moduleID); } void PartsBinView::setInfoViewOnHover(bool infoViewOnHover) { m_infoViewOnHover = infoViewOnHover; } fritzing-app-0.9.2b/src/partsbinpalette/partsbinview.h000066400000000000000000000060011250202676700231600ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSBINVIEW_H_ #define PARTSBINVIEW_H_ #include "../model/palettemodel.h" #include "../items/paletteitem.h" #include "../referencemodel/referencemodel.h" class PartsBinPaletteWidget; class PartsBinView { public: PartsBinView(ReferenceModel *referenceModel, PartsBinPaletteWidget *parent); virtual ~PartsBinView(); // removes compiler warnings virtual void setPaletteModel(PaletteModel * model, bool clear = false); void reloadParts(PaletteModel * model); void addPart(ModelPart * model, int position = -1); virtual void removePart(const QString &moduleID) = 0; virtual void removeParts() = 0; virtual ModelPart *selectedModelPart() = 0; virtual ItemBase *selectedItemBase() = 0; bool contains(const QString &moduleID); void setInfoViewOnHover(bool infoViewOnHover); virtual QList orderedChildren() = 0; virtual void reloadPart(const QString & moduleID) = 0; void dropEventAux(QDropEvent* event, bool justAppend = false); protected: virtual void doClear(); virtual void moveItem(int fromIndex, int toIndex) = 0; virtual int itemIndexAt(const QPoint& pos, bool &trustIt) = 0; virtual void setSelected(int position, bool doEmit=false) = 0; void setItem(ModelPart * modelPart); void mousePressOnItem( const QPoint &dragStartPos, const QString &moduleId, const QSize &size, const QPointF &dataPoint = QPointF(0,0), const QPoint &hotspot = QPoint(0,0)); void dragMoveEnterEventAux(QDragMoveEvent* event); virtual int setItemAux(ModelPart * modelPart, int position = -1) = 0; public: static void cleanup(); static void removePartReference(const QString & moduleID); public: static QHash TranslatedCategoryNames; protected: ReferenceModel *m_referenceModel; PartsBinPaletteWidget *m_parent; bool m_infoViewOnHover; QPoint m_dragStartPos; QHash m_itemBaseHash; static QHash ItemBaseHash; }; #endif /* PARTSBINVIEW_H_ */ fritzing-app-0.9.2b/src/partsbinpalette/searchlineedit.cpp000066400000000000000000000060651250202676700237730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "searchlineedit.h" #include "../debugdialog.h" #include #include #include static QPixmap * SearchFieldPixmap; SearchLineEdit::SearchLineEdit(QWidget * parent) : QLineEdit(parent) { SearchFieldPixmap = NULL; setDecoy(true); } SearchLineEdit::~SearchLineEdit() { } void SearchLineEdit::cleanup() { if (SearchFieldPixmap != NULL) { delete SearchFieldPixmap; SearchFieldPixmap = NULL; } } void SearchLineEdit::mousePressEvent(QMouseEvent * event) { QLineEdit::mousePressEvent(event); emit clicked(); } void SearchLineEdit::paintEvent(QPaintEvent * event) { QLineEdit::paintEvent(event); if (SearchFieldPixmap == NULL) { SearchFieldPixmap = new QPixmap(":/resources/images/icons/searchField.png"); } if (SearchFieldPixmap == NULL) return; if (SearchFieldPixmap->isNull()) return; QPainter painter(this); QSize sz = size(); int x = sz.width() - SearchFieldPixmap->width() - 2; int y = (sz.height() - SearchFieldPixmap->height()) / 2; painter.drawPixmap(x, y, SearchFieldPixmap->width(), SearchFieldPixmap->height(), *SearchFieldPixmap); } void SearchLineEdit::enterEvent(QEvent * event) { QLineEdit::enterEvent(event); if (m_decoy) { setColors(QColor(0xc8, 0xc8, 0xc8), QColor(0x57, 0x57, 0x57)); } } void SearchLineEdit::leaveEvent(QEvent * event) { QLineEdit::leaveEvent(event); if (m_decoy) { setColors(QColor(0xb3, 0xb3, 0xb3), QColor(0x57, 0x57, 0x57)); } } void SearchLineEdit::setColors(const QColor & base, const QColor & text) { setStyleSheet(QString("background: rgb(%1,%2,%3); color: rgb(%4,%5,%6);") .arg(base.red()).arg(base.green()).arg(base.blue()) .arg(text.red()).arg(text.green()).arg(text.blue()) ); } void SearchLineEdit::setDecoy(bool d) { m_decoy = d; if (m_decoy) { setReadOnly(true); setColors(QColor(0xb3, 0xb3, 0xb3), QColor(0x57, 0x57, 0x57)); } else { setReadOnly(false); setColors(QColor(0xfc, 0xfc, 0xfc), QColor(0x00, 0x00, 0x00)); } setCursor(Qt::IBeamCursor); } bool SearchLineEdit::decoy() { return m_decoy; } fritzing-app-0.9.2b/src/partsbinpalette/searchlineedit.h000066400000000000000000000031001250202676700234230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SEARCHLINEEDIT_H #define SEARCHLINEEDIT_H #include #include class SearchLineEdit : public QLineEdit { Q_OBJECT public: SearchLineEdit(QWidget * parent = NULL); ~SearchLineEdit(); void setDecoy(bool); bool decoy(); public: static void cleanup(); signals: void clicked(); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void enterEvent( QEvent *); void leaveEvent( QEvent *); void setColors(const QColor & base, const QColor & text); protected: bool m_decoy; }; #endif fritzing-app-0.9.2b/src/partsbinpalette/svgiconwidget.cpp000066400000000000000000000155541250202676700236670ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6934 $: $Author: irascibl@gmail.com $: $Date: 2013-03-22 08:35:24 +0100 (Fr, 22. Mrz 2013) $ ********************************************************************/ #include #include #include "svgiconwidget.h" #include "../sketch/infographicsview.h" #include "../debugdialog.h" #include "../utils/misc.h" #include "../fsvgrenderer.h" #include "../items/moduleidnames.h" #include "../layerattributes.h" #include "partsbinview.h" #define SELECTED_STYLE "background-color: white;" #define NON_SELECTED_STYLE "background-color: #C2C2C2;" const QColor SectionHeaderColor(80, 80, 80); #define SELECTION_THICKNESS 2 #define HALF_SELECTION_THICKNESS 1 #define ICON_SIZE 32 #define SINGULAR_OFFSET 3 #define PLURAL_OFFSET 2 static QPixmap * PluralImage = NULL; static QPixmap * SingularImage = NULL; //////////////////////////////////////////////////////////// SvgIconPixmapItem::SvgIconPixmapItem(const QPixmap & pixmap, QGraphicsItem * parent) : QGraphicsPixmapItem(pixmap, parent) { } void SvgIconPixmapItem::setPlural(bool plural) { m_plural = plural; } void SvgIconPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QGraphicsPixmapItem::paint(painter, option, widget); if (this->parentItem()->isSelected()) { painter->save(); QPen pen = painter->pen(); pen.setColor(QColor(122, 15, 49)); pen.setWidth(SELECTION_THICKNESS); painter->setPen(pen); painter->drawRect(m_plural ? HALF_SELECTION_THICKNESS : HALF_SELECTION_THICKNESS + 1, m_plural ? HALF_SELECTION_THICKNESS : HALF_SELECTION_THICKNESS + 1, ICON_SIZE + SELECTION_THICKNESS, ICON_SIZE + SELECTION_THICKNESS); painter->restore(); } } //////////////////////////////////////////////////////////// SvgIconWidget::SvgIconWidget(ModelPart * modelPart, ViewLayer::ViewID viewID, ItemBase * itemBase, bool plural) : QGraphicsWidget() { m_moduleId = modelPart->moduleID(); m_itemBase = itemBase; if (modelPart->itemType() == ModelPart::Space) { m_moduleId = ModuleIDNames::SpacerModuleIDName; QString text = PartsBinView::TranslatedCategoryNames.value(modelPart->instanceText(), modelPart->instanceText()); this->setData(Qt::UserRole, text); if (text.isEmpty()) { this->setMaximumSize(PluralImage->size().width(), 1); } else { this->setMaximumSize(PluralImage->size().width(), 8); } setAcceptHoverEvents(false); setFlags(0); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); } else { this->setMaximumSize(PluralImage->size()); setAcceptHoverEvents(true); setFlags(QGraphicsItem::ItemIsSelectable); setupImage(plural, viewID); } } void SvgIconWidget::initNames() { if (PluralImage == NULL) { PluralImage = new QPixmap(":/resources/images/icons/parts_plural_v3_plur.png"); } if (SingularImage == NULL) { SingularImage = new QPixmap(":/resources/images/icons/parts_plural_v3_sing.png"); } } SvgIconWidget::~SvgIconWidget() { //delete m_itemBase; // these are now shared } void SvgIconWidget::cleanup() { if (PluralImage) { delete PluralImage; PluralImage = NULL; } if (SingularImage) { delete SingularImage; SingularImage = NULL; } } ItemBase *SvgIconWidget::itemBase() const { return m_itemBase; } ModelPart *SvgIconWidget::modelPart() const { return m_itemBase->modelPart(); } const QString &SvgIconWidget::moduleID() const { return m_moduleId; } void SvgIconWidget::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ){ QGraphicsWidget::hoverEnterEvent(event); InfoGraphicsView * igv = InfoGraphicsView::getInfoGraphicsView(this); if (igv) { igv->hoverEnterItem(event, m_itemBase); } } void SvgIconWidget::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) { QGraphicsWidget::hoverLeaveEvent(event); InfoGraphicsView * igv = InfoGraphicsView::getInfoGraphicsView(this); if (igv) { igv->hoverLeaveItem(event, m_itemBase); } } void SvgIconWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (m_moduleId.compare(ModuleIDNames::SpacerModuleIDName) == 0) { QString text = data(Qt::UserRole).toString(); if (!text.isEmpty()) { painter->save(); QRectF r = this->boundingRect(); QPen pen = painter->pen(); pen.setColor(SectionHeaderColor); pen.setWidth(1); painter->setPen(pen); QFont font = painter->font(); font.setPointSize(8); painter->setFont(font); painter->drawText(r.left(), r.bottom(), text); //QFontMetrics fm(font); //r.setLeft(r.left() + fm.width(text)); //r.setBottom(r.bottom() + 2); //painter->drawLine(r.left(), r.bottom(), scene()->width(), r.bottom()); painter->restore(); } return; } QGraphicsWidget::paint(painter, option, widget); } void SvgIconWidget::setItemBase(ItemBase * itemBase, bool plural) { m_itemBase = itemBase; setupImage(plural, itemBase->viewID()); } void SvgIconWidget::setupImage(bool plural, ViewLayer::ViewID viewID) { LayerAttributes layerAttributes; m_itemBase->initLayerAttributes(layerAttributes, viewID, ViewLayer::Icon, ViewLayer::NewTop, false, false); ModelPart * modelPart = m_itemBase->modelPart(); FSvgRenderer * renderer = m_itemBase->setUpImage(modelPart, layerAttributes); if (renderer == NULL) { DebugDialog::debug(QString("missing renderer for icon %1").arg(modelPart->moduleID())); } if (renderer && m_itemBase) { m_itemBase->setFilename(renderer->filename()); } QPixmap pixmap(plural ? *PluralImage : *SingularImage); QPixmap * icon = (renderer == NULL) ? NULL : FSvgRenderer::getPixmap(renderer, QSize(ICON_SIZE, ICON_SIZE)); if (icon) { QPainter painter; painter.begin(&pixmap); if (plural) { painter.drawPixmap(PLURAL_OFFSET, PLURAL_OFFSET, *icon); } else { painter.drawPixmap(SINGULAR_OFFSET, SINGULAR_OFFSET, *icon); } painter.end(); delete icon; } m_pixmapItem = new SvgIconPixmapItem(pixmap, this); m_pixmapItem->setPlural(plural); m_pixmapItem->setFlags(0); m_pixmapItem->setPos(0, 0); if (m_itemBase) { m_itemBase->setTooltip(); setToolTip(m_itemBase->toolTip()); } if (renderer) { m_itemBase->setSharedRendererEx(renderer); } } fritzing-app-0.9.2b/src/partsbinpalette/svgiconwidget.h000066400000000000000000000044131250202676700233240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef SVGICONWIDGET_H_ #define SVGICONWIDGET_H_ #include #include #include #include #include #include "../model/modelpart.h" #include "../items/itembase.h" class SvgIconPixmapItem : public QGraphicsPixmapItem { public: SvgIconPixmapItem(const QPixmap & pixmap, QGraphicsItem * parent = 0); void setPlural(bool); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: bool m_plural; }; class SvgIconWidget : public QGraphicsWidget { Q_OBJECT public: SvgIconWidget(ModelPart *, ViewLayer::ViewID, ItemBase *, bool plural); ~SvgIconWidget(); ItemBase * itemBase() const; ModelPart * modelPart() const; const QString &moduleID() const; void setItemBase(ItemBase *, bool plural); static void initNames(); static void cleanup(); protected: void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setupImage(bool plural, ViewLayer::ViewID viewID); protected: QPointer m_itemBase; SvgIconPixmapItem * m_pixmapItem; QString m_moduleId; }; #endif /* SVGICONWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/000077500000000000000000000000001250202676700174345ustar00rootroot00000000000000fritzing-app-0.9.2b/src/partseditor/baseremovebutton.h000066400000000000000000000033271250202676700231760ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision$: $Author$: $Date$ ********************************************************************/ #ifndef BASEREMOVEBUTTON_H_ #define BASEREMOVEBUTTON_H_ #include class BaseRemoveButton : public QLabel { public: BaseRemoveButton(QWidget *parent) : QLabel(parent) { m_enterIcon = QPixmap(":/resources/images/remove_prop_enter.png"); m_leaveIcon = QPixmap(":/resources/images/remove_prop_leave.png"); setPixmap(m_leaveIcon); } protected: virtual void clicked() = 0; void mousePressEvent(QMouseEvent * event) { clicked(); QLabel::mousePressEvent(event); } void enterEvent(QEvent * event) { setPixmap(m_enterIcon); QLabel::enterEvent(event); } void leaveEvent(QEvent * event) { setPixmap(m_leaveIcon); QLabel::leaveEvent(event); } protected: QPixmap m_enterIcon; QPixmap m_leaveIcon; }; #endif /* BASEREMOVEBUTTON_H_ */ fritzing-app-0.9.2b/src/partseditor/hashpopulatewidget.cpp000066400000000000000000000143651250202676700240520ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "hashpopulatewidget.h" #include "../debugdialog.h" #include "../utils/misc.h" HashLineEdit::HashLineEdit(const QString &text, bool defaultValue, QWidget *parent) : QLineEdit(text, parent) { connect(this, SIGNAL(editingFinished()), parent, SLOT(lineEditChanged())); m_firstText = text; m_isDefaultValue = defaultValue; if(defaultValue) { setStyleSheet("font-style: italic;"); connect(this,SIGNAL(textChanged(QString)),this,SLOT(updateObjectName())); } else { setStyleSheet("font-style: normal;"); } } QString HashLineEdit::textIfSetted() { if(m_isDefaultValue && !hasChanged()) { return ""; } else { return text(); } } void HashLineEdit::updateObjectName() { if(m_isDefaultValue) { if(!isModified() && !hasChanged()) { setStyleSheet("font-style: italic;"); } else { setStyleSheet("font-style: normal;"); } } } void HashLineEdit::mousePressEvent(QMouseEvent * event) { if(m_isDefaultValue && !isModified() && !hasChanged()) { setText(""); } QLineEdit::mousePressEvent(event); } bool HashLineEdit::hasChanged() { return m_firstText != text(); } void HashLineEdit::focusOutEvent(QFocusEvent * event) { if(text().isEmpty()) { setText(m_firstText); } QLineEdit::focusOutEvent(event); } HashPopulateWidget::HashPopulateWidget(const QString & title, const QHash &initValues, const QStringList &readOnlyKeys, bool keysOnly, QWidget *parent) : QFrame(parent) { m_keysOnly = keysOnly; m_lastLabel = NULL; m_lastValue = NULL; QGridLayout *layout = new QGridLayout(); layout->setColumnStretch(0,0); layout->setColumnStretch(1,1); layout->setColumnStretch(2,0); if (!title.isEmpty()) { layout->addWidget(new QLabel(title),0,0,0); } QList keys = initValues.keys(); qSort(keys); for(int i=0; i < keys.count(); i++) { HashLineEdit *name = new HashLineEdit(keys[i],false,this); HashLineEdit *value = new HashLineEdit(initValues[keys[i]],false,this); if (m_keysOnly) value->hide(); int ix = layout->rowCount(); if(readOnlyKeys.contains(keys[i])) { name->setEnabled(false); } else { HashRemoveButton *button = createRemoveButton(name, value); layout->addWidget(button,ix,3); } layout->addWidget(name,ix,0); layout->addWidget(value,ix,1,1,2); } addRow(layout); this->setLayout(layout); } HashRemoveButton *HashPopulateWidget::createRemoveButton(HashLineEdit* label, HashLineEdit* value) { HashRemoveButton *button = new HashRemoveButton(label, value, this); connect(button, SIGNAL(clicked(HashRemoveButton*)), this, SLOT(removeRow(HashRemoveButton*))); return button; } const QHash &HashPopulateWidget::hash() { static QHash theHash; theHash.clear(); for(int i=1 /*i==0 is title*/; i < gridLayout()->rowCount() /*last one is always an empty one*/; i++) { QString label; HashLineEdit *labelEdit = lineEditAt(i,0); if(labelEdit) { label = labelEdit->textIfSetted(); } QString value; HashLineEdit *valueEdit = lineEditAt(i,1); if(valueEdit) { value = valueEdit->textIfSetted(); } if(!label.isEmpty() /*&& !value.isEmpty()*/) { theHash.insert(label, value); } } return theHash; } HashLineEdit* HashPopulateWidget::lineEditAt(int row, int col) { QLayoutItem *litem = gridLayout()->itemAtPosition(row,col); return litem ? qobject_cast(litem->widget()) : NULL; } void HashPopulateWidget::addRow(QGridLayout *layout) { if(layout == NULL) { layout = gridLayout(); } if(m_lastLabel) { disconnect(m_lastLabel,SIGNAL(editingFinished()),this,SLOT(lastRowEditionCompleted())); } if(m_lastValue) { disconnect(m_lastValue,SIGNAL(editingFinished()),this,SLOT(lastRowEditionCompleted())); } int ix = layout->rowCount(); m_lastLabel = new HashLineEdit(QObject::tr("a label"),true,this); layout->addWidget(m_lastLabel,ix,0); connect(m_lastLabel,SIGNAL(editingFinished()),this,SLOT(lastRowEditionCompleted())); m_lastValue = new HashLineEdit(QObject::tr("a value"),true,this); layout->addWidget(m_lastValue,ix,1,1,2); connect(m_lastValue,SIGNAL(editingFinished()),this,SLOT(lastRowEditionCompleted())); if (m_keysOnly) m_lastValue->hide(); emit editionStarted(); } QGridLayout * HashPopulateWidget::gridLayout() { return qobject_cast(this->layout()); } void HashPopulateWidget::lastRowEditionCompleted() { if( m_lastLabel && !m_lastLabel->text().isEmpty() && m_lastLabel->hasChanged()) { if(m_lastLabel->text().isEmpty() && m_lastValue->text().isEmpty()) { // removeRow() ?; } else { HashRemoveButton *button = createRemoveButton(m_lastLabel, m_lastValue); for (int i = 0; i < gridLayout()->rowCount(); i++) { HashLineEdit * label = lineEditAt(i, 0); if (m_lastLabel == label) { gridLayout()->addWidget(button,i,3); break; } } addRow(); } } } void HashPopulateWidget::removeRow(HashRemoveButton* button) { QLayout *lo = layout(); QList widgs; widgs << button->label() << button->value() << button; foreach(QWidget* w, widgs) { lo->removeWidget(w); //w->hide(); //delete w; } lo->update(); emit changed(); } void HashPopulateWidget::lineEditChanged() { emit changed(); } fritzing-app-0.9.2b/src/partseditor/hashpopulatewidget.h000066400000000000000000000053771250202676700235220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef HASHPOPULATEWIDGET_H_ #define HASHPOPULATEWIDGET_H_ #include #include #include #include #include "baseremovebutton.h" class HashLineEdit : public QLineEdit { Q_OBJECT public: HashLineEdit(const QString &text, bool defaultValue = false, QWidget *parent = 0); bool hasChanged(); QString textIfSetted(); protected slots: void updateObjectName(); protected: void mousePressEvent(QMouseEvent * event); void focusOutEvent(QFocusEvent * event); QString m_firstText; bool m_isDefaultValue; }; class HashRemoveButton : public BaseRemoveButton { Q_OBJECT public: HashRemoveButton(QWidget* label, QWidget* value, QWidget *parent) : BaseRemoveButton(parent) { m_label = label; m_value = value; } QWidget *label() {return m_label;} QWidget *value() {return m_value;} signals: void clicked(HashRemoveButton*); protected: void clicked() { emit clicked(this); } QWidget *m_label; QWidget *m_value; }; class HashPopulateWidget : public QFrame { Q_OBJECT public: HashPopulateWidget(const QString & title, const QHash &initValues, const QStringList &readOnlyKeys, bool keysOnly, QWidget *parent); const QHash & hash(); HashLineEdit* lineEditAt(int row, int col); protected slots: void lastRowEditionCompleted(); void removeRow(HashRemoveButton*); void lineEditChanged(); signals: void editionStarted(); void changed(); protected: void addRow(QGridLayout *layout = 0); QGridLayout* gridLayout(); HashRemoveButton *createRemoveButton(HashLineEdit* label, HashLineEdit* value); HashLineEdit *m_lastLabel; HashLineEdit *m_lastValue; bool m_keysOnly; }; #endif /* HASHPOPULATEWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/kicadmoduledialog.cpp000066400000000000000000000051301250202676700236000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6385 $: $Author: cohen@irascible.com $: $Date: 2012-09-08 21:21:20 +0200 (Sa, 08. Sep 2012) $ ********************************************************************/ #include "kicadmoduledialog.h" #include "../debugdialog.h" #include "../connectors/connectoritem.h" #include "../sketch/pcbsketchwidget.h" #include #include #include #include #include ///////////////////////////////////////////////////////// KicadModuleDialog::KicadModuleDialog(const QString & partType, const QString & filename, const QStringList & modules, QWidget *parent) : QDialog(parent) { this->setWindowTitle(QObject::tr("Select %1").arg(partType)); QVBoxLayout * vLayout = new QVBoxLayout(this); QFrame * frame = new QFrame(this); QFormLayout * formLayout = new QFormLayout(); m_comboBox = new QComboBox(this); m_comboBox->addItems(modules); formLayout->addRow(QString("%1:").arg(partType), m_comboBox ); frame->setLayout(formLayout); QLabel * label = new QLabel(QString("There are %1 %3 descriptions in '%2'. Please select one.").arg(modules.count()).arg(filename).arg(partType)); vLayout->addWidget(label); vLayout->addWidget(frame); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } KicadModuleDialog::~KicadModuleDialog() { } const QString KicadModuleDialog::selectedModule() { return m_comboBox->currentText(); } fritzing-app-0.9.2b/src/partseditor/kicadmoduledialog.h000066400000000000000000000026301250202676700232470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6385 $: $Author: cohen@irascible.com $: $Date: 2012-09-08 21:21:20 +0200 (Sa, 08. Sep 2012) $ ********************************************************************/ #ifndef KICADMODULEDIALOG_H #define KICADMODULEDIALOG_H #include #include class KicadModuleDialog : public QDialog { Q_OBJECT public: KicadModuleDialog(const QString & partType, const QString & filename, const QStringList & moduleNames, QWidget *parent = 0); ~KicadModuleDialog(); const QString selectedModule(); protected: QComboBox * m_comboBox; }; #endif fritzing-app-0.9.2b/src/partseditor/obsolete/000077500000000000000000000000001250202676700212505ustar00rootroot00000000000000fritzing-app-0.9.2b/src/partseditor/obsolete/abstractconnectorinfowidget.cpp000066400000000000000000000045651250202676700275640ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "abstractconnectorinfowidget.h" #include "connectorinforemovebutton.h" #include "connectorsinfowidget.h" #include "../utils/misc.h" #include int AbstractConnectorInfoWidget::SingleConnectorHeight = 40; AbstractConnectorInfoWidget::AbstractConnectorInfoWidget(ConnectorsInfoWidget *topLevelContainer, QWidget *parent) : QFrame(parent) { m_topLevelContainer = topLevelContainer; m_removeButton = new ConnectorInfoRemoveButton(this); connect( m_removeButton, SIGNAL(clicked(AbstractConnectorInfoWidget*)), topLevelContainer, SLOT(removeConnector(AbstractConnectorInfoWidget*)) ); setMinimumWidth(100); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); setMinimumHeight(SingleConnectorHeight); } void AbstractConnectorInfoWidget::setSelected(bool selected, bool doEmitChange) { m_isSelected = selected; setProperty("selected",m_isSelected); reapplyStyle(); if(selected) { setFocus(); if(doEmitChange) { emit tellSistersImNewSelected(this); } } } void AbstractConnectorInfoWidget::reapplyStyle() { QString path = ":/resources/styles/partseditor.qss"; QFile styleSheet(path); if (!styleSheet.open(QIODevice::ReadOnly)) { qWarning("Unable to open :/resources/styles/partseditor.qss"); } else { setStyleSheet(styleSheet.readAll()); } } bool AbstractConnectorInfoWidget::isSelected() { return m_isSelected; } fritzing-app-0.9.2b/src/partseditor/obsolete/abstractconnectorinfowidget.h000066400000000000000000000036061250202676700272240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ABSTRACTCONNECTORINFOWIDGET_H_ #define ABSTRACTCONNECTORINFOWIDGET_H_ #include #include class ConnectorInfoRemoveButton; class AbstractConnectorInfoWidget : public QFrame { Q_OBJECT public: AbstractConnectorInfoWidget(class ConnectorsInfoWidget *topLevelContainer, QWidget *parent=0); virtual void setSelected(bool selected, bool doEmitChange=true); bool isSelected(); signals: void tellSistersImNewSelected(AbstractConnectorInfoWidget*); // Meant to be used in the info context void tellViewsMyConnectorIsNewSelected(const QString&); // Meant to be used in the info context void repaintNeeded(); protected: void reapplyStyle(); ConnectorsInfoWidget *m_topLevelContainer; ConnectorInfoRemoveButton *m_removeButton; volatile bool m_isSelected; static int SingleConnectorHeight; }; #endif /* ABSTRACTCONNECTORINFOWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/abstracteditablelabelwidget.cpp000066400000000000000000000074031250202676700274610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "abstracteditablelabelwidget.h" #include "../utils/misc.h" AbstractEditableLabelWidget::AbstractEditableLabelWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent, QString title, bool edited, bool noSpacing) : QFrame(parent) { m_noSpacing = noSpacing; m_edited = edited; m_isInEditionMode = false; m_undoStack = undoStack; QGridLayout *layout = new QGridLayout; if(!title.isNull() && !title.isEmpty()) { m_title = new QLabel(title, this); m_title->setObjectName("title"); layout->addWidget(m_title,0,0); } else { m_title = NULL; } setLayout(layout); m_label = new EditableLabel(text, this); connect(m_label,SIGNAL(editionStarted(QString)),this,SLOT(editionStarted(QString))); connect(this,SIGNAL(editionCompleted(QString)),m_label,SLOT(editionCompleted(QString))); m_acceptButton = new QPushButton(tr("Accept"), this); connect(m_acceptButton,SIGNAL(clicked()),this,SLOT(informEditionCompleted())); m_cancelButton = new QPushButton(tr("Cancel"), this); connect(m_cancelButton,SIGNAL(clicked()),this,SLOT(editionCanceled())); } QString AbstractEditableLabelWidget::text() { if(m_edited) { return m_label->text(); } else { return ___emptyString___; } } void AbstractEditableLabelWidget::editionStarted(QString text) { setEditionText(text); toEditionMode(); } void AbstractEditableLabelWidget::informEditionCompleted() { if(m_isInEditionMode) { m_undoStack->push(new QUndoCommand("Dummy parts editor command")); m_edited = true; emit editionCompleted(editionText()); toStandardMode(); } } void AbstractEditableLabelWidget::editionCanceled() { toStandardMode(); } void AbstractEditableLabelWidget::toStandardMode() { m_isInEditionMode = false; hide(); QGridLayout *layout = (QGridLayout*)this->layout(); myEditionWidget()->hide(); layout->removeWidget(myEditionWidget()); m_acceptButton->hide(); layout->removeWidget(m_acceptButton); m_cancelButton->hide(); layout->removeWidget(m_cancelButton); m_label->show(); layout->addWidget(m_label,1,0); setNoSpacing(layout); updateGeometry(); show(); emit editionFinished(); } void AbstractEditableLabelWidget::toEditionMode() { m_isInEditionMode = true; hide(); QGridLayout *layout = (QGridLayout*)this->layout(); m_label->hide(); layout->removeWidget(m_label); if(!m_edited) { setEmptyTextToEdit(); } myEditionWidget()->show(); layout->addWidget(myEditionWidget(),1,0,1,5); m_acceptButton->show(); layout->addWidget(m_acceptButton,2,3); m_cancelButton->show(); layout->addWidget(m_cancelButton,2,4); setNoSpacing(layout); updateGeometry(); show(); emit editionStarted(); } void AbstractEditableLabelWidget::setNoSpacing(QLayout *layout) { if(m_noSpacing) { layout->setMargin(0); layout->setSpacing(0); } } fritzing-app-0.9.2b/src/partseditor/obsolete/abstracteditablelabelwidget.h000066400000000000000000000044011250202676700271210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not,AbstractEditableLabelWidget see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include "editablelabel.h" #include "../waitpushundostack.h" #ifndef ABSTRACTEDITABLELABELWIDGET_H_ #define ABSTRACTEDITABLELABELWIDGET_H_ class AbstractEditableLabelWidget : public QFrame { Q_OBJECT public: AbstractEditableLabelWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent=0, QString title="", bool edited=false, bool noSpacing=false); QString text(); protected slots: void editionStarted(QString text); void informEditionCompleted(); void editionCanceled(); signals: void editionCompleted(QString text); void editionStarted(); void editionFinished(); protected: void toStandardMode(); void toEditionMode(); void setNoSpacing(QLayout *layout); virtual QString editionText()=0; virtual void setEditionText(QString text)=0; virtual QWidget* myEditionWidget()=0; virtual void setEmptyTextToEdit()=0; QLabel *m_title; EditableLabel *m_label; QPushButton *m_acceptButton; QPushButton *m_cancelButton; class WaitPushUndoStack * m_undoStack; bool m_noSpacing; bool m_edited; volatile bool m_isInEditionMode; }; #endif /* ABSTRACTEDITABLELABELWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/abstractimagebutton.h000066400000000000000000000034171250202676700254700ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ABSTRACTIMAGEBUTTON_H_ #define ABSTRACTIMAGEBUTTON_H_ #include #include "abstractstatesbutton.h" class AbstractImageButton : public QLabel, public AbstractStatesButton { Q_OBJECT public: AbstractImageButton(QWidget *parent=0) : QLabel(parent) { }; virtual ~AbstractImageButton() {} signals: void clicked(); protected: virtual QString imagePrefix() = 0; void setImage(const QPixmap & pixmap) { setPixmap(pixmap); } void mousePressEvent(QMouseEvent * event) { setPressedIcon(); QLabel::mousePressEvent(event); } void mouseReleaseEvent(QMouseEvent * event) { if(isEnabled()) { emit clicked(); setEnabledIcon(); } QLabel::mouseReleaseEvent(event); } }; #endif /* ABSTRACTIMAGEBUTTON_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/addremoveconnectorbutton.h000066400000000000000000000027641250202676700265470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ADDREMOVECONNECTORBUTTON_H_ #define ADDREMOVECONNECTORBUTTON_H_ #include "../utils/abstractimagebutton.h" class AddRemoveConnectorButton : public AbstractImageButton { public: AddRemoveConnectorButton(const QString &imageName, QWidget *parent=0) : AbstractImageButton(parent) { setupIcons(imageName); setEnabledIcon(); }; protected: QString imagePrefix() { return ":/resources/images/icons/partsEditorConnector"; } }; #endif /* ADDREMOVECONNECTORBUTTON_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/addremovelistwidget.cpp000066400000000000000000000063761250202676700260360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "addremovelistwidget.h" #include "../utils/misc.h" #define BUTTON_SIZE 25 AddRemoveListWidget::AddRemoveListWidget(QString title, QWidget *parent) : QGroupBox(parent) { m_label = new QLabel(title+":"); //setFixedWidth(parentWidget()->width()); m_addButton = new QPushButton(QIcon(":/resources/images/add.png"),"",this); m_addButton->setFixedSize(BUTTON_SIZE,BUTTON_SIZE); connect(m_addButton,SIGNAL(clicked()),this,SLOT(addItem())); m_removeButton = new QPushButton(QIcon(":/resources/images/remove.png"),"",this); m_removeButton->setFixedSize(BUTTON_SIZE,BUTTON_SIZE); connect(m_removeButton,SIGNAL(clicked()),this,SLOT(removeSelectedItems())); m_list = new QListWidget(this); m_list->setSelectionMode(QAbstractItemView::ContiguousSelection); m_list->setFixedHeight(BUTTON_SIZE*3); m_list->setSortingEnabled(true); int row=0; QGridLayout *layout = new QGridLayout; layout->setSpacing(1); layout->setMargin(3); layout->addWidget(m_label,row,0); layout->addWidget(m_addButton,row,1); layout->addWidget(m_removeButton,row++,2); layout->addWidget(m_list,row,0,row,3); row++; setLayout(layout); } void AddRemoveListWidget::addItem() { addItem(m_label->text().toLower().remove("s:")); } void AddRemoveListWidget::addItem(QString itemText) { QListWidgetItem *item = new QListWidgetItem(); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setText(itemText); m_list->addItem(item); m_list->editItem(item); } void AddRemoveListWidget::removeSelectedItems() { QList selitems = m_list->selectedItems(); for(int i=0; i < selitems.size(); i++) { m_list->takeItem(m_list->row(selitems[i])); } } int AddRemoveListWidget::count() { if(m_list != NULL) { return m_list->count(); } else { return 0; } } QListWidgetItem* AddRemoveListWidget::itemAt(int rowIdx) { if(m_list != NULL) { return m_list->item(rowIdx); } else { return NULL; } } QStringList& AddRemoveListWidget::getItemsText() { QStringList *retval = new QStringList(); for(int i=0; i < count(); i++) { *retval << itemAt(i)->text(); } return *retval; } void AddRemoveListWidget::setItemsText(const QStringList& texts) { for(int i=0; i < texts.count(); i++) { addItem(texts[i]); } m_list->sortItems(); } fritzing-app-0.9.2b/src/partseditor/obsolete/addremovelistwidget.h000066400000000000000000000032471250202676700254750ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ADDREMOVELISTWIDGET_H_ #define ADDREMOVELISTWIDGET_H_ #include #include #include #include class AddRemoveListWidget : public QGroupBox { Q_OBJECT public: AddRemoveListWidget(QString title, QWidget *parent=0); int count(); QListWidgetItem* itemAt(int rowIdx); QStringList& getItemsText(); void setItemsText(const QStringList& texts); protected slots: void addItem(); void addItem(QString itemText); void removeSelectedItems(); protected: QLabel *m_label; QPushButton *m_addButton; QPushButton *m_removeButton; QListWidget *m_list; }; #endif /* ADDREMOVELISTWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/connectorinforemovebutton.h000066400000000000000000000032751250202676700267500ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef CONNECTORINFOREMOVEBUTTON_H_ #define CONNECTORINFOREMOVEBUTTON_H_ #include "baseremovebutton.h" #include "abstractconnectorinfowidget.h" class ConnectorInfoRemoveButton : public BaseRemoveButton { Q_OBJECT public: ConnectorInfoRemoveButton(AbstractConnectorInfoWidget* parent) : BaseRemoveButton(parent) { m_connInfo = parent; } signals: void clicked(AbstractConnectorInfoWidget*); protected: void mousePressEvent(QMouseEvent * event) { Q_UNUSED(event) clicked(); //QLabel::mousePressEvent(event); } void clicked() { emit clicked(m_connInfo); } AbstractConnectorInfoWidget *m_connInfo; }; #endif /* CONNECTORINFOREMOVEBUTTON_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/connectorrectangle.cpp000066400000000000000000000120061250202676700256320ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include "connectorrectangle.h" #include "../sketch/zoomablegraphicsview.h" #include "../debugdialog.h" double ConnectorRectangle::ErrorIconSize = 6; ConnectorRectangle::ConnectorRectangle(QGraphicsItem* owner, bool withHandlers) : QObject() { m_minWidth = m_minHeight = 0; m_owner = owner; m_firstPaint = true; if(withHandlers) { m_topLeftHandler = new CornerHandler(this, owner, Qt::TopLeftCorner); m_topRightHandler = new CornerHandler(this, owner, Qt::TopRightCorner); m_bottomRightHandler = new CornerHandler(this, owner, Qt::BottomRightCorner); m_bottomLeftHandler = new CornerHandler(this, owner, Qt::BottomLeftCorner); m_cornerHandlers << m_topLeftHandler << m_topRightHandler << m_bottomRightHandler << m_bottomLeftHandler; setHandlersVisible(false); } else { m_topLeftHandler = m_topRightHandler = m_bottomRightHandler = m_bottomLeftHandler = NULL; } } ConnectorRectangle::~ConnectorRectangle() { } void ConnectorRectangle::setHandlersVisible(bool visible) { foreach(CornerHandler* handler, m_cornerHandlers) { handler->doSetVisible(visible); } } void ConnectorRectangle::resizeRect(double x1, double y1, double x2, double y2) { double width = x2-x1 < m_minWidth ? m_minWidth : x2-x1; double height = y2-y1 < m_minHeight ? m_minHeight : y2-y1; QRectF rect = owner()->boundingRect(); if(width != rect.width() && height != rect.height()) { emit resizeSignal(x1,y1,width,height); } } bool ConnectorRectangle::isResizable() { bool resizable; emit isResizableSignal(resizable); // must be connected via Qt::DirectConnection return resizable; } void ConnectorRectangle::paint(QPainter *painter) { QRectF rect = m_owner->boundingRect(); if(m_firstPaint && rect.width() > 0 && rect.height() > 0) { placeHandlers(); m_firstPaint = false; } bool beingResized = false; foreach(CornerHandler* handler, m_cornerHandlers) { if(handler->isBeingDragged()) { beingResized = true; break; } } if(beingResized) { foreach(CornerHandler* handler, m_cornerHandlers) { handler->doPaint(painter); } } } void ConnectorRectangle::resizingStarted() { foreach(CornerHandler* handler, m_cornerHandlers) { handler->doSetVisible(false); } } void ConnectorRectangle::resizingFinished() { foreach(CornerHandler* handler, m_cornerHandlers) { handler->doSetVisible(true); setHandlerRect(handler); } } void ConnectorRectangle::placeHandlers() { foreach(CornerHandler* handler, m_cornerHandlers) { setHandlerRect(handler); } } void ConnectorRectangle::setHandlerRect(CornerHandler* handler) { handler->doSetRect(handlerRect(handler->corner())); } QRectF ConnectorRectangle::handlerRect(Qt::Corner corner) { QRectF rect = m_owner->boundingRect(); double scale = currentScale(); //DebugDialog::debug(QString("scale %1").arg(scale)); QPointF offset(CornerHandler::Size/scale,CornerHandler::Size/scale); QPointF cornerPoint; switch(corner) { case Qt::TopLeftCorner: cornerPoint=rect.topLeft(); break; case Qt::TopRightCorner: cornerPoint=rect.topRight(); break; case Qt::BottomRightCorner: cornerPoint=rect.bottomRight(); break; case Qt::BottomLeftCorner: cornerPoint=rect.bottomLeft(); break; default: throw "ConnectorRectangle::handlerRect: unknown corner"; } return QRectF(cornerPoint-offset,cornerPoint+offset); } QRectF ConnectorRectangle::errorIconRect() { QRectF rect = m_owner->boundingRect(); double scale = currentScale(); QPointF offset(ErrorIconSize/scale,ErrorIconSize/scale); QPointF cornerPoint = rect.topLeft()-offset; return QRectF(cornerPoint-offset,cornerPoint+offset); } double ConnectorRectangle::currentScale() { if(m_owner->scene()) { ZoomableGraphicsView *sw = dynamic_cast(m_owner->scene()->parent()); if(sw) { return sw->currentZoom()/100; } } return 1; } QGraphicsItem *ConnectorRectangle::owner() { return m_owner; } void ConnectorRectangle::setMinSize(double minWidth, double minHeight) { m_minWidth = minWidth; m_minHeight = minHeight; } fritzing-app-0.9.2b/src/partseditor/obsolete/connectorrectangle.h000066400000000000000000000044131250202676700253020ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef CONNECTORRECTANGLE_H_ #define CONNECTORRECTANGLE_H_ #include "cornerhandler.h" class ConnectorRectangle : public QObject { Q_OBJECT public: enum State { Normal = 0x00000, Highlighted = 0x00001, Hover = 0x00002, Selected = 0x00003 }; ConnectorRectangle(QGraphicsItem* owner, bool withHandlers = true); ~ConnectorRectangle(); QGraphicsItem *owner(); void resizeRect(double x1, double y1, double x2, double y2); bool isResizable(); void resizingStarted(); void resizingFinished(); double currentScale(); void setMinSize(double minWidth, double minHeight); void setHandlersVisible(bool visible); QRectF handlerRect(Qt::Corner corner); QRectF errorIconRect(); void paint(QPainter *painter); signals: void resizeSignal(double x1, double y1, double x2, double y2); void isResizableSignal(bool & resizable); protected: void setHandlerRect(CornerHandler* handler); void placeHandlers(); QGraphicsItem *m_owner; CornerHandler *m_topLeftHandler; CornerHandler *m_topRightHandler; CornerHandler *m_bottomRightHandler; CornerHandler *m_bottomLeftHandler; QList m_cornerHandlers; double m_minWidth; double m_minHeight; bool m_firstPaint; public: static double ErrorIconSize; }; #endif /* CONNECTORRECTANGLE_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/connectorsinfowidget.cpp000066400000000000000000000512151250202676700262150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include "connectorsinfowidget.h" #include "addremoveconnectorbutton.h" #include "partseditorviewswidget.h" #include "../debugdialog.h" #include "../connectors/connectorshared.h" #include "../processeventblocker.h" ConnectorsInfoWidget::ConnectorsInfoWidget(WaitPushUndoStack *undoStack, QWidget *parent) : QFrame(parent) { m_objToDelete = NULL; m_selected = NULL; m_undoStack = undoStack; m_views = NULL; createScrollArea(); createToolsArea(); QGridLayout *layout = new QGridLayout(this); layout->addWidget(m_title,0,0); layout->addWidget(m_scrollArea,1,0); layout->addWidget(m_toolsContainter,2,0); layout->setContentsMargins(3, 10, 3, 10); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); setFocusPolicy(Qt::StrongFocus); installEventFilter(this); m_connRemoved = false; m_connAdded = false; } void ConnectorsInfoWidget::emitPaintNeeded() { emit repaintNeeded(); } void ConnectorsInfoWidget::createToolsArea() { m_toolsContainter = new QFrame(this); QHBoxLayout *lo = new QHBoxLayout(m_toolsContainter); QPushButton *addBtn = new QPushButton(QObject::tr("Add connector"),this); connect(addBtn, SIGNAL(clicked()), this, SLOT(addConnector())); lo->setMargin(2); lo->setSpacing(2); lo->addWidget(addBtn); lo->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); } void ConnectorsInfoWidget::createScrollArea() { m_scrollContent = new QFrame(); m_scrollContent->setObjectName("connInfoContent"); m_scrollContent->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_mismatchersFrameParent = new QFrame(this); m_mismatchersFrameParent->setObjectName("mismatchConns"); m_mismatchersFrameParent->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); QVBoxLayout *parentLo = new QVBoxLayout(m_mismatchersFrameParent); parentLo->setMargin(1); m_mismatchersFrame = new QFrame(m_mismatchersFrameParent); //m_mismatchersFrame->resize(this->width(),m_mismatchersFrame->height()); QVBoxLayout *mismatchLayout = new QVBoxLayout(m_mismatchersFrame); mismatchLayout->setMargin(0); mismatchLayout->setSpacing(0); m_mismatchersFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); QLabel *mismatchConnHeader = new QLabel(tr("Mismatching Connector IDs")); mismatchConnHeader->setObjectName("mismatchConnsHeader"); parentLo->addWidget(mismatchConnHeader); parentLo->addWidget(m_mismatchersFrame); /*QLabel *mismatchConnFooter = new QLabel(tr("These problems need to be fixed in the svg-files directly")); mismatchConnFooter->setObjectName("mismatchConnsFooter"); parentLo->addWidget(mismatchConnFooter);*/ m_mismatchersFrameParent->hide(); QVBoxLayout *scrollLayout = new QVBoxLayout(m_scrollContent); scrollLayout->setMargin(0); scrollLayout->setSpacing(0); scrollContentLayout()->addWidget(m_mismatchersFrameParent); scrollContentLayout()->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::MinimumExpanding)); m_scrollArea = new QScrollArea(this); m_scrollArea->setWidget(m_scrollContent); m_scrollArea->setWidgetResizable(true); m_title = new QLabel(" "+tr("List of Connectors")); m_title->setObjectName("title"); } void ConnectorsInfoWidget::selectionChanged(AbstractConnectorInfoWidget* selected) { if(m_selected) { m_selected->setSelected(false); } m_selected = selected; QTimer::singleShot(20, this, SLOT(emitPaintNeeded())); } void ConnectorsInfoWidget::setSelected(AbstractConnectorInfoWidget * newSelected) { if(newSelected != m_selected) { newSelected->setSelected(true,false); selectionChanged(newSelected); } } bool ConnectorsInfoWidget::eventFilter(QObject *obj, QEvent *event) { if(obj == this) { if(event->type() == QEvent::KeyPress || event->type() == QEvent::ShortcutOverride) { QKeyEvent *keyEvent = (QKeyEvent*)event; if(keyEvent->key() == Qt::Key_Up) { selectPrev(); return true; } else if(keyEvent->key() == Qt::Key_Down) { selectNext(); return true; } } } return false; } /*void ConnectorsInfoWidget::ensureSelection(int i) { // TODO Mariano: Strange bug (if this is set, each up or dow key pressed event triggers twice) if(i==1) { // 1 == the fixed idx of the tab bool found = false; if(!m_selected) { if(m_connsInfo.size() > 0) { setSelected(m_connsInfo[0]); found = true; } else if(m_mismatchConnsInfo.size() > 0) { setSelected(m_mismatchConnsInfo[0]); found = true; } if(found) { this->setFocus(); } } } }*/ void ConnectorsInfoWidget::selectNext() { if(m_selected) { int selIdx = m_connsInfo.indexOf((SingleConnectorInfoWidget*)m_selected); if(selIdx > -1 && selIdx < m_connsInfo.size()-1) { // It's a single connector setSelected(m_connsInfo[selIdx+1]); } else { selIdx = m_mismatchConnsInfo.indexOf((MismatchingConnectorWidget*)m_selected); if(selIdx > -1) { if(selIdx < m_mismatchConnsInfo.size()-1) { setSelected(m_mismatchConnsInfo[selIdx+1]); } else if(m_connsInfo.size() > 0) { setSelected(m_connsInfo[0]); } } } } } void ConnectorsInfoWidget::selectPrev() { if(m_selected) { int selIdx = m_connsInfo.indexOf((SingleConnectorInfoWidget*)m_selected); if(selIdx > -1 ) { // It's a single connector and not the first if(selIdx > 0) { setSelected(m_connsInfo[selIdx-1]); } else if(m_mismatchConnsInfo.size()>0) { setSelected(m_mismatchConnsInfo[m_mismatchConnsInfo.size()-1]); } } else { selIdx = m_mismatchConnsInfo.indexOf((MismatchingConnectorWidget*)m_selected); if(selIdx > 0) { // it's a mismatch setSelected(m_mismatchConnsInfo[selIdx-1]); } } } } void ConnectorsInfoWidget::updateLayout() { m_mismatchersFrame->updateGeometry(); m_mismatchersFrame->adjustSize(); m_mismatchersFrameParent->updateGeometry(); m_mismatchersFrameParent->adjustSize(); m_scrollContent->adjustSize(); } void ConnectorsInfoWidget::addConnectorInfo(MismatchingConnectorWidget* mcw) { if(mcw->prevConn()) { addConnectorInfo(mcw->prevConn()); } else { addConnectorInfo(mcw->connId()); } } Connector* ConnectorsInfoWidget::addConnectorInfo(QString id) { ConnectorShared *connShared = new ConnectorShared(); connShared->setId(id); connShared->addPin( ViewLayer::BreadboardView, m_views->breadboardView()->svgIdForConnector(id), m_views->breadboardView()->connectorsLayerId(), m_views->breadboardView()->terminalIdForConnector(id), "", false ); connShared->addPin( ViewLayer::SchematicView, m_views->schematicView()->svgIdForConnector(id), m_views->schematicView()->connectorsLayerId(), m_views->schematicView()->terminalIdForConnector(id), "", false ); connShared->addPin( ViewLayer::PCBView, m_views->pcbView()->svgIdForConnector(id), m_views->pcbView()->connectorsLayerId(), m_views->pcbView()->terminalIdForConnector(id), "", false ); Connector *conn = new Connector(connShared,0); // modelPart =? null addConnectorInfo(conn); return conn; } void ConnectorsInfoWidget::addConnectorInfo(Connector *conn) { QString connId = conn->connectorSharedID(); m_connIds << connId; int connCount = m_connsInfo.size(); SingleConnectorInfoWidget *sci = new SingleConnectorInfoWidget(this, m_undoStack, conn, m_scrollContent); scrollContentLayout()->insertWidget(connCount+1,sci); m_connsInfo << sci; m_allConnsInfo[connId] = sci; connect(sci,SIGNAL(editionStarted()),this,SLOT(updateLayout())); connect(sci,SIGNAL(editionFinished()),this,SLOT(updateLayout())); connect(sci,SIGNAL(tellSistersImNewSelected(AbstractConnectorInfoWidget*)),this,SLOT(selectionChanged(AbstractConnectorInfoWidget*))); connect(sci,SIGNAL(tellViewsMyConnectorIsNewSelected(const QString&)),this,SLOT(informConnectorSelection(const QString &))); connect(this,SIGNAL(editionCompleted()),sci,SLOT(editionCompleted())); m_scrollContent->updateGeometry(); } void ConnectorsInfoWidget::addMismatchingConnectorInfo(ViewLayer::ViewIdentifier viewId, QString connId) { m_connIds << connId; MismatchingConnectorWidget *mcw = new MismatchingConnectorWidget(this,viewId,connId,m_mismatchersFrame); addMismatchingConnectorInfo(mcw); connect( mcw, SIGNAL(completeConn(MismatchingConnectorWidget*)), this, SLOT(completeConn(MismatchingConnectorWidget*)) ); } void ConnectorsInfoWidget::addMismatchingConnectorInfo(MismatchingConnectorWidget *mcw) { int connCount = m_mismatchConnsInfo.size(); ((QVBoxLayout*)m_mismatchersFrame->layout())->insertWidget(connCount,mcw); m_mismatchConnsInfo << mcw; m_allConnsInfo[mcw->connId()] = mcw; connect(mcw,SIGNAL(tellSistersImNewSelected(AbstractConnectorInfoWidget*)),this,SLOT(selectionChanged(AbstractConnectorInfoWidget*))); connect(mcw,SIGNAL(tellViewsMyConnectorIsNewSelected(const QString &)),this,SLOT(informConnectorSelection(const QString &))); if(m_mismatchConnsInfo.size()==1) { m_mismatchersFrameParent->show(); } /*if(!m_selected && connCount == 0) { setSelected(mcw); }*/ foreach(ViewLayer::ViewIdentifier viewId, mcw->views()) { emit setMismatching(viewId, mcw->connId(), true); } } QVBoxLayout *ConnectorsInfoWidget::scrollContentLayout() { return (QVBoxLayout*)m_scrollContent->layout(); } void ConnectorsInfoWidget::connectorsFound(QList< QPointer > conns) { qSort(conns); QProgressDialog progress(tr("Loading connectors..."), 0, 0, conns.size(), this); progress.show(); for(int i=0; i < conns.size(); i++) { progress.setValue(i); ProcessEventBlocker::processEvents(); // to keep the app away from freezing addConnectorInfo(conns[i]); } progress.setValue(conns.size()); updateLayout(); } void ConnectorsInfoWidget::informConnectorSelection(const QString &connId) { emit connectorSelected(connId); } void ConnectorsInfoWidget::informEditionCompleted() { emit editionCompleted(); } const QList< QPointer > ConnectorsInfoWidget::connectorsShared() { QList< QPointer > connectorsShared; for(int i=0; iid(); Connector *conn = sci->connector(); //foreach (ConnectorItem * connectorItem, conn->viewItems()) { //connectorItem->debugInfo("what is this connector"); //} ConnectorShared* cs = conn->connectorShared(); //foreach (SvgIdLayer * sil, cs->pins()) { //DebugDialog::debug(QString("what is this pin %1").arg(sil->m_svgViewLayerID)); //} cs->setId(id); cs->setSharedName(sci->name()); cs->setDescription(sci->description()); cs->setConnectorType(sci->type()); connectorsShared << cs; } return connectorsShared; } void ConnectorsInfoWidget::removeTerminalPoint(const QString &connId, ViewLayer::ViewIdentifier vid) { for(int i=0; iconnector(); foreach(SvgIdLayer *sil, conn->connectorShared()->pins().values(vid)) { if(conn->connectorSharedID() == connId) { sil->m_terminalId = ___emptyString___; } } } } // If we're reloading an image, clear mismatching connectors related exclusively to that view void ConnectorsInfoWidget::clearMismatchingForView(ViewLayer::ViewIdentifier viewId) { foreach(MismatchingConnectorWidget* mcw, m_mismatchConnsInfo) { if(mcw->views().size()==1 && mcw->views()[0] == viewId) { removeMismatchingConnectorInfo(mcw, false); } } } // Updates previous connector to mismatching if they are not in the list void ConnectorsInfoWidget::singleToMismatchingNotInView(ViewLayer::ViewIdentifier viewId, const QStringList &connIds) { foreach(SingleConnectorInfoWidget* sci, m_connsInfo) { if(connIds.indexOf(sci->id()) == -1) { MismatchingConnectorWidget *mcw = sci->toMismatching(viewId); connect( mcw, SIGNAL(completeConn(MismatchingConnectorWidget*)), this, SLOT(completeConn(MismatchingConnectorWidget*)) ); removeConnectorInfo(sci,false); addMismatchingConnectorInfo(mcw); } } m_mismatchersFrame->adjustSize(); scrollContentLayout()->update(); m_mismatchersFrameParent->adjustSize(); m_mismatchersFrameParent->layout()->update(); updateLayout(); } void ConnectorsInfoWidget::syncNewConnectors(ViewLayer::ViewIdentifier viewId, const QList< QPointer > &conns) { clearMismatchingForView(viewId); // clean the old pins for this view /*foreach(QString oldId, m_connectorsPins.keys()) { m_connectorsPins[oldId].remove(viewId); }*/ QStringList connIds; foreach(Connector *conn, conns) { QString connId = conn->connectorSharedID(); connIds << connId; if(existingConnId(connId)) { SingleConnectorInfoWidget * sci = findSCI(connId); resetType(viewId, sci, conn); resetName(viewId, sci, conn); emit existingConnectorSignal(viewId, connId, sci ? sci->connector() : NULL, conn); } else { MismatchingConnectorWidget *mcw = NULL; if(( mcw = existingMismatchingConnector(connId) )) { if(mcw->onlyMissingThisView(viewId)) { Connector * prevConn = mcw->prevConn(); removeMismatchingConnectorInfo(mcw, false); // mcw was just deleted in removeMismatchingConnectorInfo so we can't use it directly if(prevConn) { addConnectorInfo(prevConn); } else { addConnectorInfo(connId); } SingleConnectorInfoWidget * sci = findSCI(connId); resetType(viewId, sci, conn); resetName(viewId, sci, conn); emit existingConnectorSignal(viewId, connId, sci ? sci->connector() : NULL, conn); } else { mcw->addViewPresence(viewId); emit setMismatching(viewId, mcw->connId(), true); } } else { addMismatchingConnectorInfo(viewId, connId); } } } //clearMismatchingForView(viewId); singleToMismatchingNotInView(viewId,connIds); } bool ConnectorsInfoWidget::existingConnId(const QString &id) { return findConnector(id) != NULL; } MismatchingConnectorWidget* ConnectorsInfoWidget::existingMismatchingConnector(const QString &id) { foreach(MismatchingConnectorWidget *mci, m_mismatchConnsInfo) { if(mci->connId() == id) { return mci; } } return NULL; } void ConnectorsInfoWidget::removeMismatchingConnectorInfo(MismatchingConnectorWidget* mcw, bool singleShot, bool alsoDeleteFromView) { m_mismatchersFrame->layout()->removeWidget(mcw); m_mismatchConnsInfo.removeOne(mcw); m_allConnsInfo.remove(mcw->connId()); if(m_mismatchConnsInfo.size()==0) { m_mismatchersFrameParent->hide(); updateLayout(); } if(alsoDeleteFromView) { emit removeConnectorFrom(mcw->connId(),ViewLayer::AllViews); } else { foreach(ViewLayer::ViewIdentifier viewId, mcw->views()) { emit setMismatching(viewId, mcw->connId(), false); } } if(m_selected == mcw) { m_selected = NULL; } m_objToDelete = mcw; if(singleShot) { QTimer::singleShot(100, this, SLOT(deleteAux())); } else { deleteAux(); } } void ConnectorsInfoWidget::removeConnectorInfo(SingleConnectorInfoWidget *sci, bool singleShot, bool alsoDeleteFromView) { m_connRemoved = true; scrollContentLayout()->removeWidget(sci); m_connsInfo.removeOne(sci); m_allConnsInfo.remove(sci->id()); if(m_selected == sci) { m_selected = NULL; } if(alsoDeleteFromView) { emit removeConnectorFrom(sci->id(), ViewLayer::AllViews); } m_objToDelete = sci; if(singleShot) { QTimer::singleShot(100, this, SLOT(deleteAux())); } else { deleteAux(); } } Connector* ConnectorsInfoWidget::findConnector(const QString &id) { foreach(SingleConnectorInfoWidget *sci, m_connsInfo) { if(sci->id() == id) { return sci->connector(); } } return NULL; } SingleConnectorInfoWidget* ConnectorsInfoWidget::findSCI(const QString &id) { foreach(SingleConnectorInfoWidget *sci, m_connsInfo) { if(sci->id() == id) { return sci; } } return NULL; } void ConnectorsInfoWidget::addConnector() { m_connAdded = true; if (m_views->breadboardView()->myItem() == NULL || m_views->schematicView()->myItem() == NULL || m_views->pcbView()->myItem() == NULL) { QMessageBox::warning( parentWidget(), tr("Couldn't add connector"), tr("Please, first load an image in each view,\nbefore adding any connectors") ); return; } QString connId = QString("connector%1").arg(nextConnId()); emit drawConnector(addConnectorInfo(connId)); if(m_allConnsInfo[connId]) { setSelected(m_allConnsInfo[connId]); } } void ConnectorsInfoWidget::removeSelectedConnector() { if(!m_selected) return; removeConnector(m_selected); } void ConnectorsInfoWidget::removeConnector(AbstractConnectorInfoWidget* connInfo) { MismatchingConnectorWidget* mismatch = dynamic_cast(connInfo); if(mismatch) { removeMismatchingConnectorInfo(mismatch, true, true); } else { SingleConnectorInfoWidget *single = dynamic_cast(connInfo); if(single) { removeConnectorInfo(single, true, true); } } } int ConnectorsInfoWidget::nextConnId() { int max = 0; foreach(QString connId, m_connIds) { QString currId = connId; if(currId.startsWith("connector")) { QString helpStr = currId.remove("connector"); if(!helpStr.isEmpty()) { bool isInt; int helpInt = helpStr.toInt(&isInt); if(isInt && max <= helpInt) { max = ++helpInt; } } } } return max; } void ConnectorsInfoWidget::deleteAux() { if(m_objToDelete) { if(m_selected == m_objToDelete) { m_selected = NULL; } delete m_objToDelete; m_objToDelete = NULL; } } int ConnectorsInfoWidget::scrollBarWidth() { return m_scrollArea->verticalScrollBar()->width(); } void ConnectorsInfoWidget::connectorSelectedInView(const QString &connId) { setSelected(m_allConnsInfo[connId]); } void ConnectorsInfoWidget::setViews(PartsEditorViewsWidget* connsView) { m_views = connsView; } void ConnectorsInfoWidget::completeConn(MismatchingConnectorWidget* mcw) { if(m_views->imagesLoadedInAllViews()) { QList missingViews = mcw->missingViews(); QList availViews = mcw->views(); QString connId = mcw->connId(); removeMismatchingConnectorInfo(mcw); if(mcw->prevConn()) { addConnectorInfo(mcw->prevConn()); } else { addConnectorInfo(connId); } Connector *connector = findConnector(connId); foreach(ViewLayer::ViewIdentifier viewId, missingViews) { emit drawConnector(viewId, connector); } foreach(ViewLayer::ViewIdentifier viewId, availViews) { emit setMismatching(viewId,connId,false); } } else { QMessageBox::information( parentWidget(), tr("Couldn't fix connector"), tr("Please, first load an image in each view,\nin order to fix this connector") ); } } bool ConnectorsInfoWidget::connectorsRemoved() { return m_connRemoved; } bool ConnectorsInfoWidget::connectorAdded() { return m_connAdded; } bool ConnectorsInfoWidget::connectorsCountChanged() { return connectorsRemoved() || connectorAdded(); } bool ConnectorsInfoWidget::hasMismatchingConnectors() { return m_mismatchConnsInfo.size() > 0; } void ConnectorsInfoWidget::resetType(ViewLayer::ViewIdentifier viewId, SingleConnectorInfoWidget * sci, Connector * conn) { if (viewId != ViewLayer::PCBView) return; if (conn->connectorType() == sci->connectorType()) return; if (conn->connectorType() == Connector::Pad) { // was male or female sci->setConnectorType(conn->connectorType()); return; } if (sci->connectorType() != Connector::Pad) return; // was pad, should it be male or female? // TODO: figure out which gender or ask the user to fix it. sci->setConnectorType(Connector::Male); } void ConnectorsInfoWidget::resetName(ViewLayer::ViewIdentifier viewId, SingleConnectorInfoWidget * sci, Connector * conn) { Q_UNUSED(viewId); if (!sci->name().startsWith("pin", Qt::CaseInsensitive)) return; // probably already changed by the user QString name = conn->connectorSharedName(); if (name.isEmpty()) return; if (name.startsWith("pin", Qt::CaseInsensitive)) return; bool ok; int num = name.toInt(&ok); if (ok) return; // just a number, don't bother Q_UNUSED(num); sci->setName(name); } fritzing-app-0.9.2b/src/partseditor/obsolete/connectorsinfowidget.h000066400000000000000000000120631250202676700256600ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef CONNECTORSINFOWIDGET_H_ #define CONNECTORSINFOWIDGET_H_ #include #include #include #include #include "singleconnectorinfowidget.h" #include "mismatchingconnectorwidget.h" class PartsEditorViewsWidget; class ConnectorsInfoWidget : public QFrame { Q_OBJECT public: ConnectorsInfoWidget(WaitPushUndoStack *undoStack, QWidget *parent=0); const QList< QPointer > connectorsShared(); QCheckBox *showTerminalPointsCheckBox(); int scrollBarWidth(); void setViews(PartsEditorViewsWidget* connsView); bool connectorsCountChanged(); bool connectorsRemoved(); bool connectorAdded(); bool hasMismatchingConnectors(); public slots: void connectorsFound(QList< QPointer >); void informConnectorSelection(const QString &); void informEditionCompleted(); void syncNewConnectors(ViewLayer::ViewIdentifier viewId, const QList< QPointer > &conns); void emitPaintNeeded(); void addConnector(); void removeSelectedConnector(); void removeConnector(AbstractConnectorInfoWidget* connInfo); void removeTerminalPoint(const QString &connId, ViewLayer::ViewIdentifier vid); signals: void connectorSelected(const QString &); void editionCompleted(); void existingConnectorSignal(ViewLayer::ViewIdentifier viewId, const QString &id, Connector* existingConnector, Connector * newConnector); void setMismatching(ViewLayer::ViewIdentifier viewId, const QString &connId, bool mismatching); void repaintNeeded(); void showTerminalPoints(bool show); void drawConnector(Connector*); void drawConnector(ViewLayer::ViewIdentifier, Connector*); void removeConnectorFrom(const QString &connId, ViewLayer::ViewIdentifier view); protected slots: void updateLayout(); void selectionChanged(AbstractConnectorInfoWidget* selected); void deleteAux(); void connectorSelectedInView(const QString &connId); void completeConn(MismatchingConnectorWidget* mcw); protected: void createScrollArea(); void createToolsArea(); void addConnectorInfo(MismatchingConnectorWidget* mcw); Connector* addConnectorInfo(QString id); void addConnectorInfo(Connector *conn); void addMismatchingConnectorInfo(MismatchingConnectorWidget *mcw); void addMismatchingConnectorInfo(ViewLayer::ViewIdentifier viewID, QString connId); QVBoxLayout *scrollContentLayout(); bool eventFilter(QObject *obj, QEvent *event); void setSelected(AbstractConnectorInfoWidget * newSelected); void selectNext(); void selectPrev(); void clearMismatchingForView(ViewLayer::ViewIdentifier viewId); void singleToMismatchingNotInView(ViewLayer::ViewIdentifier viewId, const QStringList &connIds); bool existingConnId(const QString &id); MismatchingConnectorWidget* existingMismatchingConnector(const QString &id); void removeMismatchingConnectorInfo(MismatchingConnectorWidget* mcw, bool singleShot = true, bool alsoDeleteFromView = false); void removeConnectorInfo(SingleConnectorInfoWidget *sci, bool singleShot = true, bool alsoDeleteFromView = false); Connector* findConnector(const QString &id); SingleConnectorInfoWidget * findSCI(const QString &id); int nextConnId(); void resetType(ViewLayer::ViewIdentifier viewId, SingleConnectorInfoWidget * sci, Connector * conn); void resetName(ViewLayer::ViewIdentifier viewId, SingleConnectorInfoWidget * sci, Connector * conn); protected: //QHash > m_connectorsPins; QLabel *m_title; QScrollArea *m_scrollArea; QFrame *m_scrollContent; QFrame *m_mismatchersFrame; QFrame *m_mismatchersFrameParent; QFrame *m_toolsContainter; PartsEditorViewsWidget* m_views; AbstractConnectorInfoWidget *m_selected; QList m_connsInfo; QList< QPointer > m_mismatchConnsInfo; QHash m_allConnsInfo; QStringList m_connIds; WaitPushUndoStack *m_undoStack; QObject *m_objToDelete; bool m_connRemoved; bool m_connAdded; }; #endif /* CONNECTORSINFOWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/cornerhandler.cpp000066400000000000000000000130341250202676700246030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include "cornerhandler.h" #include "connectorrectangle.h" #include "../debugdialog.h" QHash CornerHandler::pixmapHash; double CornerHandler::Size = 4; CornerHandler::CornerHandler(ConnectorRectangle *parent, QGraphicsItem* parentItem, Qt::Corner corner) : QGraphicsRectItem(parentItem) { m_parent = parent; m_corner = corner; m_resizing = false; initPixmapHash(); setFlag(QGraphicsItem::ItemIgnoresTransformations); setFlag(QGraphicsItem::ItemClipsChildrenToShape); setAcceptHoverEvents(true); doSetVisible(false); } void CornerHandler::doSetVisible(bool visible) { if(visible) { setBrush(QBrush(QColor::fromRgb(0,250,0))); } else { setBrush(QBrush()); } m_isVisible = visible; } void CornerHandler::initPixmapHash() { if(pixmapHash.isEmpty()) { pixmapHash[Qt::TopLeftCorner] = QPixmap(":/resources/images/itemselection/cornerHandlerActiveTopLeft.png"); pixmapHash[Qt::TopRightCorner] = QPixmap(":/resources/images/itemselection/cornerHandlerActiveTopRight.png"); pixmapHash[Qt::BottomRightCorner] = QPixmap(":/resources/images/itemselection/cornerHandlerActiveBottomRight.png"); pixmapHash[Qt::BottomLeftCorner] = QPixmap(":/resources/images/itemselection/cornerHandlerActiveBottomLeft.png"); } } void CornerHandler::resize(const QPointF &mousePos) { QRectF rect = m_parent->owner()->boundingRect(); double oldX1 = rect.x(); double oldY1 = rect.y(); double oldX2 = oldX1+rect.width(); double oldY2 = oldY1+rect.height(); double newX = mapToItem(m_parent->owner(),mousePos).x(); double newY = mapToItem(m_parent->owner(),mousePos).y(); switch(m_corner) { case Qt::TopLeftCorner: m_parent->resizeRect(newX,newY,oldX2,oldY2); break; case Qt::TopRightCorner: m_parent->resizeRect(oldX1,newY,newX,oldY2); break; case Qt::BottomRightCorner: m_parent->resizeRect(oldX1,oldY1,newX,newY); break; case Qt::BottomLeftCorner: m_parent->resizeRect(newX,oldY1,oldX2,newY); break; default: break; } } Qt::Corner CornerHandler::corner() { return m_corner; } void CornerHandler::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if(m_parent->isResizable() && m_resizing) { resize(event->pos()); scene()->update(); } else { QGraphicsRectItem::mouseMoveEvent(event); } } void CornerHandler::mousePressEvent(QGraphicsSceneMouseEvent *event) { if(m_isVisible) { if(m_parent->isResizable()) { m_parent->resizingStarted(); m_resizing = true; setFlag(QGraphicsItem::ItemIgnoresTransformations,false); } else { QGraphicsRectItem::mousePressEvent(event); } } else { QGraphicsRectItem::mousePressEvent(event); } } void CornerHandler::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if(m_parent->isResizable() && m_resizing) { setFlag(QGraphicsItem::ItemIgnoresTransformations,true); m_resizing = false; m_parent->resizingFinished(); } QGraphicsRectItem::mouseReleaseEvent(event); } void CornerHandler::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { QGraphicsRectItem::hoverEnterEvent(event); if(m_isVisible && m_parent->isResizable()) { setCursor(QCursor(cursorForCorner(m_corner))); } } void CornerHandler::hoverLeaveEvent(QGraphicsSceneHoverEvent * event) { if(m_isVisible && m_parent->isResizable()) { unsetCursor(); } QGraphicsRectItem::hoverLeaveEvent(event); } Qt::CursorShape CornerHandler::cursorForCorner(Qt::Corner corner) { Qt::CursorShape cursorShape = Qt::SizeFDiagCursor; switch(corner) { case Qt::TopLeftCorner: case Qt::BottomRightCorner: cursorShape = Qt::SizeFDiagCursor; break; case Qt::TopRightCorner: case Qt::BottomLeftCorner: cursorShape = Qt::SizeBDiagCursor; break; default: throw "CornerHandler::cursorForCorner unknown corner"; } return cursorShape; } bool CornerHandler::isBeingDragged() { return m_resizing; } void CornerHandler::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); if(m_isVisible && m_parent->isResizable()) { doPaint(painter); } } void CornerHandler::doPaint(QPainter *painter) { if(m_isVisible) { QRectF trgRect = m_parent->handlerRect(m_corner); //DebugDialog::debug("handler rect ", trgRect); QPixmap pm = pixmapHash[m_corner]; QRectF srcRect = QRectF(pm.rect()); //painter->drawRect(rect); painter->drawPixmap(trgRect,pm,srcRect); } } void CornerHandler::doSetRect(const QRectF &newRect) { setFlag(QGraphicsItem::ItemIgnoresTransformations,false); setRect(mapFromParent(newRect).boundingRect()); } fritzing-app-0.9.2b/src/partseditor/obsolete/cornerhandler.h000066400000000000000000000041771250202676700242600ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef CORNERHANDLER_H_ #define CORNERHANDLER_H_ #include #include class ConnectorRectangle; class CornerHandler : public QGraphicsRectItem { public: CornerHandler(ConnectorRectangle *parent, QGraphicsItem* parentItem, Qt::Corner corner); void resize(const QPointF &mousePos); Qt::Corner corner(); bool isBeingDragged(); void doSetVisible(bool visible); void doSetRect(const QRectF &newRect); void doPaint(QPainter *painter); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent * event); void hoverLeaveEvent(QGraphicsSceneHoverEvent * event); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); Qt::CursorShape cursorForCorner(Qt::Corner); void initPixmapHash(); ConnectorRectangle *m_parent; Qt::Corner m_corner; bool m_isVisible; volatile bool m_resizing; public: static QHash pixmapHash; static double Size; }; #endif /* CORNERHANDLER_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/editabledatewidget.cpp000066400000000000000000000033541250202676700255740ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "editabledatewidget.h" #include "../utils/misc.h" EditableDateWidget::EditableDateWidget(QDate date, WaitPushUndoStack *undoStack, QWidget *parent, QString title, bool edited, bool noSpacing) : AbstractEditableLabelWidget(date.toString(Qt::ISODate), undoStack, parent, title, edited, noSpacing) { m_dateEdit = new QDateEdit(this); toStandardMode(); } QString EditableDateWidget::editionText() { return m_dateEdit->date().toString(Qt::ISODate); } void EditableDateWidget::setEditionText(QString text) { m_dateEdit->setDate(QDate::fromString(text, Qt::ISODate)); } QWidget* EditableDateWidget::myEditionWidget() { return m_dateEdit; } void EditableDateWidget::setEmptyTextToEdit() { m_dateEdit->setDate(QDate()); } fritzing-app-0.9.2b/src/partseditor/obsolete/editabledatewidget.h000066400000000000000000000030651250202676700252400ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef EDITABLEDATEWIDGET_H_ #define EDITABLEDATEWIDGET_H_ #include "abstracteditablelabelwidget.h" #include class EditableDateWidget : public AbstractEditableLabelWidget { Q_OBJECT public: EditableDateWidget(QDate date, WaitPushUndoStack *undoStack, QWidget *parent=0, QString title="", bool noSpacing=false, bool edited=false); protected: QString editionText(); void setEditionText(QString text); QWidget* myEditionWidget(); void setEmptyTextToEdit(); QDateEdit *m_dateEdit; }; #endif /* EDITABLEDATEWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/editablelabel.cpp000066400000000000000000000027361250202676700245350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "editablelabel.h" #include "../utils/misc.h" EditableLabel::EditableLabel(QWidget *parent) : QLabel(parent) { setWordWrap(true); } EditableLabel::EditableLabel(const QString &text, QWidget *parent) : QLabel(text,parent) { setWordWrap(true); } void EditableLabel::editionCompleted(QString newText) { setText(newText); } void EditableLabel::mousePressEvent (QMouseEvent *event) { emit editionStarted(text()); QWidget::mousePressEvent(event); } fritzing-app-0.9.2b/src/partseditor/obsolete/editablelabel.h000066400000000000000000000027021250202676700241730ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef EDITABLELABEL_H_ #define EDITABLELABEL_H_ #include #include class EditableLabel : public QLabel { Q_OBJECT public: EditableLabel(QWidget *parent=0); EditableLabel(const QString & text, QWidget *parent=0); public slots: void editionCompleted(QString newText); signals: void editionStarted(QString); protected: void mousePressEvent(QMouseEvent *event); }; #endif /* EDITABLELABEL_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/editablelinewidget.cpp000066400000000000000000000035551250202676700256110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "editablelinewidget.h" #include "../utils/misc.h" EditableLineWidget::EditableLineWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent, QString title, bool edited, bool noSpacing) : AbstractEditableLabelWidget(text, undoStack, parent, title, edited, noSpacing) { m_lineEdit = new QLineEdit(this); toStandardMode(); } void EditableLineWidget::setValidator(const QValidator * v ) { m_lineEdit->setValidator(v); } void EditableLineWidget::setText(const QString &text) { m_lineEdit->setText(text); m_label->setText(text); } QString EditableLineWidget::editionText() { return m_lineEdit->text(); } void EditableLineWidget::setEditionText(QString text) { m_lineEdit->setText(text); } QWidget* EditableLineWidget::myEditionWidget() { return m_lineEdit; } void EditableLineWidget::setEmptyTextToEdit() { m_lineEdit->setText(""); } fritzing-app-0.9.2b/src/partseditor/obsolete/editablelinewidget.h000066400000000000000000000032101250202676700252420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef EDITABLELINEWIDGET_H_ #define EDITABLELINEWIDGET_H_ #include #include "abstracteditablelabelwidget.h" class EditableLineWidget : public AbstractEditableLabelWidget { Q_OBJECT public: EditableLineWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent=0, QString title="", bool edited=false, bool noSpacing=false); void setValidator(const QValidator * v ); void setText(const QString &text); protected: QString editionText(); void setEditionText(QString text); QWidget* myEditionWidget(); void setEmptyTextToEdit(); QLineEdit *m_lineEdit; }; #endif /* EDITABLELINEWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/editabletextwidget.cpp000066400000000000000000000033051250202676700256370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "editabletextwidget.h" #include "../utils/misc.h" EditableTextWidget::EditableTextWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent, QString title, bool edited, bool noSpacing) : AbstractEditableLabelWidget(text, undoStack, parent, title, edited, noSpacing) { m_textEdit = new QTextEdit(this); m_textEdit->setFixedHeight(70); toStandardMode(); } QString EditableTextWidget::editionText() { return m_textEdit->toPlainText(); } void EditableTextWidget::setEditionText(QString text) { m_textEdit->setText(text); } QWidget* EditableTextWidget::myEditionWidget() { return m_textEdit; } void EditableTextWidget::setEmptyTextToEdit() { m_textEdit->setText(""); } fritzing-app-0.9.2b/src/partseditor/obsolete/editabletextwidget.h000066400000000000000000000030671250202676700253110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef EDITABLETEXTWIDGET_H_ #define EDITABLETEXTWIDGET_H_ #include #include "abstracteditablelabelwidget.h" class EditableTextWidget : public AbstractEditableLabelWidget { Q_OBJECT public: EditableTextWidget(QString text, WaitPushUndoStack *undoStack, QWidget *parent=0, QString title="", bool noSpacing=false, bool edited=false); protected: QString editionText(); void setEditionText(QString text); QWidget* myEditionWidget(); void setEmptyTextToEdit(); QTextEdit *m_textEdit; }; #endif /* EDITABLETEXTWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/fixfontsdialog.cpp000066400000000000000000000137151250202676700250030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include "fixfontsdialog.h" #include "../installedfonts.h" #include "../debugdialog.h" ////////////////////////////////////////////////////////////////////////////// class FixedFontComboBox : public QComboBox { public: FixedFontComboBox(QWidget *parent, const QString &brokenFont) : QComboBox(parent) { m_brokenFont = brokenFont; } const QString &brokenFont() { return m_brokenFont; } void setBrokenFont(const QString &brokenFont) { m_brokenFont = brokenFont; } protected: QString m_brokenFont; }; ////////////////////////////////////////////////////////////////////////////// FixFontsDialog::FixFontsDialog(QWidget *parent, const QSet fontsTofix) : QDialog(parent) { setWindowTitle(tr("Unavailable fonts")); QFrame *container = new QFrame(this); container->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Expanding); QVBoxLayout *layout = new QVBoxLayout(container); layout->setSpacing(1); layout->setMargin(1); foreach (QString f, fontsTofix) { DebugDialog::debug("incoming font " + f); } m_fontsToFix = fontsTofix - InstalledFonts::InstalledFontsList; foreach (QString fontFileName, InstalledFonts::InstalledFontsNameMapper.values()) { // SVG uses filename which may not match family name (e.g. "DroidSans" and "Droid Sans") m_fontsToFix.remove(fontFileName); } QStringList availFonts = InstalledFonts::InstalledFontsList.toList(); qSort(availFonts); availFonts.insert(0,tr("-- ignore --")); int defaultIdx = availFonts.indexOf("Droid Sans"); QStringList fontsToFixList = m_fontsToFix.toList(); qSort(fontsToFixList); foreach(QString ftf, fontsToFixList) { DebugDialog::debug("font not found: "+ftf); createLine(layout,ftf,availFonts,defaultIdx); } layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding)); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); QVBoxLayout *mainLO = new QVBoxLayout(this); mainLO->setMargin(8); mainLO->setSpacing(2); QLabel *msgLabel = new QLabel(tr( "One or more fonts used in this SVG file are not available in Fritzing.\n" "Please select one of the Fritzing fonts to replace them:" ),this); msgLabel->setWordWrap(true); mainLO->addWidget(msgLabel); mainLO->addWidget(container); mainLO->addSpacerItem(new QSpacerItem(0,5)); QLabel *infoLabel = new QLabel( "For more information, please refer to the " "part creation guidelines." , this); infoLabel->setOpenExternalLinks(true); infoLabel->setWordWrap(true); mainLO->addWidget(infoLabel); mainLO->addSpacerItem(new QSpacerItem(0,5)); QHBoxLayout *btnLayout = new QHBoxLayout(); btnLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Minimum)); btnLayout->addWidget(buttonBox); mainLO->addLayout(btnLayout); setMinimumWidth(100); } FixFontsDialog::~FixFontsDialog() { } // assumes that the first item in items, is a default value void FixFontsDialog::createLine(QLayout* layout, const QString &brokenFont, const QStringList &items, int defaultIdx) { FixedFontComboBox *cb = new FixedFontComboBox(this,brokenFont); int fontValue = -1; foreach(QString font, items) { cb->addItem(font, fontValue); fontValue++; } cb->setCurrentIndex(defaultIdx); m_fixedFonts << cb; QFrame *line = new QFrame(this); line->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); QHBoxLayout *lineLO = new QHBoxLayout(line); lineLO->setSpacing(0); lineLO->setMargin(1); lineLO->addWidget(new QLabel(tr("Replace "),line)); lineLO->addWidget(new QLabel(QString("%1 ").arg(brokenFont),line)); lineLO->addWidget(new QLabel(tr("with "),line)); lineLO->addWidget(cb); layout->addWidget(line); } QSet FixFontsDialog::fontsToFix() { return m_fontsToFix; } FixedFontsHash FixFontsDialog::getFixedFontsHash() { FixedFontsHash retval; foreach(FixedFontComboBox* cb, m_fixedFonts) { int idx = cb->currentIndex(); if( idx != -1) { int value = cb->itemData(idx).toInt(); if(value > -1) { QString fixedFont = cb->itemText(idx); // at least for Droid Sans, family name is "Droid Sans" but SVGs seem to need filename ("DroidSans"). fixedFont = InstalledFonts::InstalledFontsNameMapper.value(fixedFont); retval[cb->brokenFont()] = fixedFont; } } } return retval; } FixedFontsHash FixFontsDialog::fixFonts(QWidget *parent, const QSet fontsTofix, bool &cancelPressed) { FixedFontsHash retval; cancelPressed = false; FixFontsDialog *dlg = new FixFontsDialog(parent,fontsTofix); if(dlg->fontsToFix().size() > 0) { if(dlg->exec() == QDialog::Accepted) { retval = dlg->getFixedFontsHash(); } else { cancelPressed = true; } } delete dlg; return retval; } fritzing-app-0.9.2b/src/partseditor/obsolete/fixfontsdialog.h000066400000000000000000000033421250202676700244430ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FIXFONTSDIALOG_H_ #define FIXFONTSDIALOG_H_ #include #include #define FixedFontsHash QHash class FixFontsDialog : public QDialog { Q_OBJECT public: FixFontsDialog(QWidget *parent, const QSet fontsTofix); virtual ~FixFontsDialog(); FixedFontsHash getFixedFontsHash(); QSet fontsToFix(); static FixedFontsHash fixFonts(QWidget *parent, const QSet fontsTofix, bool &cancelPressed); protected: void createLine(QLayout* layout, const QString &brokenFont, const QStringList &items, int defaultIdx); QSet m_fontsToFix; QList m_fixedFonts; }; #endif /* FIXFONTSDIALOG_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/mismatchingconnectorwidget.cpp000066400000000000000000000115401250202676700273770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include "mismatchingconnectorwidget.h" #include "connectorinforemovebutton.h" #include "../debugdialog.h" QList MismatchingConnectorWidget::AllViews; //TODO Mariano: looks like an abstracteditable, perhaps can be one MismatchingConnectorWidget::MismatchingConnectorWidget(ConnectorsInfoWidget *topLevelContainer, ViewLayer::ViewIdentifier viewId, const QString &connId, QWidget *parent, bool isInView, Connector* conn) : AbstractConnectorInfoWidget(topLevelContainer, parent) { if(AllViews.size() == 0) { AllViews << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; } m_prevConn = conn; m_connId = connId; m_connIdLabel = new QLabel(m_connId+":", this); m_connIdLabel->setObjectName("mismatchConnId"); m_connMsgLabel = new QLabel(viewsString(),this); m_connMsgLabel->setObjectName("mismatchConnMsg"); QLabel *errorImg = new QLabel(this); errorImg->setPixmap(QPixmap(":/resources/images/error_x_small.png")); if(isInView) { m_missingViews << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; addViewPresence(viewId); } else { removeViewPresence(viewId); } QPushButton *completeConnBtn = new QPushButton(tr("fix this!"),this); connect(completeConnBtn,SIGNAL(clicked()),this,SLOT(emitCompletion())); QHBoxLayout *lo = new QHBoxLayout(); lo->addWidget(errorImg); lo->addSpacerItem(new QSpacerItem(5,0)); lo->addWidget(m_connIdLabel); lo->addWidget(m_connMsgLabel); lo->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Expanding)); lo->addWidget(completeConnBtn); lo->addSpacerItem(new QSpacerItem(10,0,QSizePolicy::Minimum,QSizePolicy::Expanding)); lo->addWidget(m_removeButton); lo->setMargin(3); lo->setSpacing(3); this->setLayout(lo); //updateGeometry(); setMaximumHeight(SingleConnectorHeight); } MismatchingConnectorWidget::~MismatchingConnectorWidget() { } void MismatchingConnectorWidget::setSelected(bool selected, bool doEmitChange) { AbstractConnectorInfoWidget::setSelected(selected, doEmitChange); if(selected && !m_connId.isNull()) { emit tellViewsMyConnectorIsNewSelected(m_connId); } } bool MismatchingConnectorWidget::onlyMissingThisView(ViewLayer::ViewIdentifier viewId) { return m_missingViews.size() == 1 && m_missingViews[0] == viewId; } void MismatchingConnectorWidget::addViewPresence(ViewLayer::ViewIdentifier viewId) { m_missingViews.removeAll(viewId); m_connMsgLabel->setText(viewsString()); } void MismatchingConnectorWidget::removeViewPresence(ViewLayer::ViewIdentifier viewId) { m_missingViews << viewId; m_connMsgLabel->setText(viewsString()); } bool MismatchingConnectorWidget::presentInAllViews() { return m_missingViews.size() == 0; } const QString &MismatchingConnectorWidget::connId() { return m_connId; } Connector *MismatchingConnectorWidget::prevConn() { return m_prevConn; } QList MismatchingConnectorWidget::views() { QList list = AllViews; for(int i=0; i < m_missingViews.size(); i++) { list.removeAll(m_missingViews[i]); } return list; } QList MismatchingConnectorWidget::missingViews() { return m_missingViews; } QString MismatchingConnectorWidget::viewsString() { QString retval = tr("In "); bool notFirst = false; for(int i=0; i < AllViews.size(); i++) { ViewLayer::ViewIdentifier viewId = AllViews[i]; if(!m_missingViews.contains(viewId)) { if(notFirst) { retval += tr("and "); } retval += ViewLayer::viewIdentifierNaturalName(viewId)+" "; notFirst = true; } } retval += tr("view only"); return retval; } void MismatchingConnectorWidget::mousePressEvent(QMouseEvent * event) { if(!isSelected()) { setSelected(true); } QFrame::mousePressEvent(event); } void MismatchingConnectorWidget::emitCompletion() { emit completeConn(this); } fritzing-app-0.9.2b/src/partseditor/obsolete/mismatchingconnectorwidget.h000066400000000000000000000046631250202676700270540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef MISMATCHINGCONNECTORWIDGET_H_ #define MISMATCHINGCONNECTORWIDGET_H_ #include #include "abstractconnectorinfowidget.h" #include "../connectors/connector.h" class MismatchingConnectorWidget : public AbstractConnectorInfoWidget { Q_OBJECT public: MismatchingConnectorWidget(class ConnectorsInfoWidget *topLevelContainer, ViewLayer::ViewIdentifier viewId, const QString &connId, QWidget *parent, bool isInView = true, Connector* conn = NULL); ~MismatchingConnectorWidget(); void setSelected(bool selected, bool doEmitChange=true); bool onlyMissingThisView(ViewLayer::ViewIdentifier viewId); void addViewPresence(ViewLayer::ViewIdentifier viewId); void removeViewPresence(ViewLayer::ViewIdentifier viewId); const QString &connId(); Connector *prevConn(); QList views(); QList missingViews(); bool presentInAllViews(); signals: void completeConn(MismatchingConnectorWidget*); protected slots: void emitCompletion(); protected: void mousePressEvent(QMouseEvent * event); QString viewsString(); QList m_missingViews; QString m_connId; QPointer m_prevConn; // If this connector info used to be a not mismatching one, we save that info here QLabel *m_connIdLabel; QLabel *m_connMsgLabel; static QList AllViews; }; #endif /* MISMATCHINGCONNECTORWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partconnectorswidget.cpp000066400000000000000000000025461250202676700262330ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include "partconnectorswidget.h" #include "../utils/misc.h" PartConnectorsWidget::PartConnectorsWidget(QWidget* info, QWidget *parent) : QFrame(parent) { QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(info); layout->setMargin(4); layout->setSpacing(10); } fritzing-app-0.9.2b/src/partseditor/obsolete/partconnectorswidget.h000066400000000000000000000024101250202676700256660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTCONNECTORSWIDGET_H_ #define PARTCONNECTORSWIDGET_H_ #include class PartConnectorsWidget : public QFrame { Q_OBJECT public: PartConnectorsWidget(QWidget* info, QWidget *parent=0); }; #endif /* PARTCONNECTORSWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partinfowidget.cpp000066400000000000000000000067501250202676700250120ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "partinfowidget.h" #include "../debugdialog.h" PartInfoWidget::PartInfoWidget(QWidget *parent) : QWidget(parent) { m_version = new QLineEdit(this); m_author = new QLineEdit(this); m_title = new QLineEdit(this); //m_taxonomy = new QLineEdit(this); m_label = new QLineEdit(this); m_description = new QTextEdit(this); m_description->setFixedHeight(50); m_date = new QDateEdit(QDate::currentDate(), this); m_date->setDisplayFormat("yyyy-MM-dd"); m_tagsList = new AddRemoveListWidget(tr("Tags"),this); m_propertyList = new AddRemoveListWidget(tr("Properties"),this); int row = 0; QGridLayout *layout = new QGridLayout(); layout->setSpacing(4); layout->setMargin(3); layout->addWidget(new QLabel(tr("Version")), row, 0); layout->addWidget(m_version, row, 1); layout->addWidget(new QLabel(tr("Author")), row, 2); layout->addWidget(m_author, row++, 3); layout->addWidget(new QLabel(tr("Title")), row, 0); layout->addWidget(m_title, row++, 1, 1, 3); layout->addWidget(new QLabel(tr("Label")), row, 0); layout->addWidget(m_label, row, 1); layout->addWidget(new QLabel(tr("Description")), row, 0); layout->addWidget(m_description, row++, 1, 1, 3); /*layout->addWidget(new QLabel(tr("Taxonomy")), row, 0); layout->addWidget(m_taxonomy, row, 1);*/ layout->addWidget(new QLabel(tr("Date")), row, 2); layout->addWidget(m_date, row++, 3); layout->addWidget(m_tagsList, row, 0, 1, 2); layout->addWidget(m_propertyList, row++, 2, 1, 2); setLayout(layout); } ModelPartShared* PartInfoWidget::modelPartShared() { ModelPartShared* mps = new ModelPartShared(); mps->setVersion(m_version->text()); mps->setAuthor(m_author->text()); mps->setTitle(m_title->text()); mps->setDate(m_date->date()); //mps->setTaxonomy(m_taxonomy->text()); mps->setLabel(m_label->text()); mps->setDescription(m_description->toPlainText()); mps->setTags(m_tagsList->getItemsText()); //mps->setProperties(m_propertiesList->getItemsText()); return mps; } void PartInfoWidget::updateInfo(ModelPart * modelPart) { ModelPartShared* mps = modelPart->modelPartShared(); m_version->setText(mps->version()); m_author->setText(mps->author()); m_title->setText(mps->title()); m_date->setDate(mps->date()); //m_taxonomy->setText(mps->taxonomy()); m_label->setText(mps->label()); DebugDialog::debug("setting text: "+mps->description()); m_description->setText(mps->description()); m_tagsList->setItemsText(mps->tags()); //m_propertiesList->setItemsText(mps->properties()); } fritzing-app-0.9.2b/src/partseditor/obsolete/partinfowidget.h000066400000000000000000000033361250202676700244540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTINFOWIDGET_H_ #define PARTINFOWIDGET_H_ #include #include #include #include #include "addremovelistwidget.h" #include "../model/modelpart.h" #include "../model/modelpartshared.h" class PartInfoWidget : public QWidget { Q_OBJECT public: PartInfoWidget(QWidget *parent = 0); ModelPartShared* modelPartShared(); public slots: void updateInfo(ModelPart *); protected: QLineEdit *m_version; QLineEdit *m_author; QLineEdit *m_title; //QLineEdit *m_taxonomy; QLineEdit *m_label; QTextEdit *m_description; QDateEdit *m_date; AddRemoveListWidget * m_tagsList; AddRemoveListWidget * m_propertyList; }; #endif /* PARTINFOWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partseditormainwindow.cpp000066400000000000000000000652621250202676700264240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6417 $: $Author: cohen@irascible.com $: $Date: 2012-09-14 23:34:09 +0200 (Fr, 14. Sep 2012) $ ********************************************************************/ #include "partseditormainwindow.h" #include "pcbxml.h" #include "../debugdialog.h" #include "../mainwindow/fdockwidget.h" #include "../waitpushundostack.h" #include "editabletextwidget.h" #include "partseditorview.h" #include "partseditorviewswidget.h" #include "editabledatewidget.h" #include "hashpopulatewidget.h" #include "partspecificationswidget.h" #include "partconnectorswidget.h" #include "../model/palettemodel.h" #include "../model/sketchmodel.h" #include "../utils/folderutils.h" #include "../processeventblocker.h" #include #include #include #include #include QString PartsEditorMainWindow::TitleFreshStartText; QString PartsEditorMainWindow::LabelFreshStartText; QString PartsEditorMainWindow::DescriptionFreshStartText; QString PartsEditorMainWindow::TaxonomyFreshStartText; QString PartsEditorMainWindow::TagsFreshStartText; QString PartsEditorMainWindow::FooterText; QString PartsEditorMainWindow::UntitledPartName; QString PartsEditorMainWindow::___partsEditorName___; int PartsEditorMainWindow::UntitledPartIndex = 1; QPointer PartsEditorMainWindow::m_lastOpened = NULL; int PartsEditorMainWindow::m_closedBeforeCount = 0; bool PartsEditorMainWindow::m_closeAfterSaving = true; #ifdef QT_NO_DEBUG #define CORE_EDITION_ENABLED false #else #define CORE_EDITION_ENABLED false #endif PartsEditorMainWindow::PartsEditorMainWindow(QWidget *parent) : FritzingWindow(untitledFileName(), untitledFileCount(), fileExtension(), parent) { m_iconItem = m_breadboardItem = m_schematicItem = m_pcbItem = NULL; m_editingAlien = false; } PartsEditorMainWindow::~PartsEditorMainWindow() { if (m_iconItem) { // m_iconItem was custom-created for the PartsEditor; the other items exist in the sketch so shouldn't be deleted delete m_iconItem; } if (m_sketchModel) { // memory leak here, but delete or deleteLater causes a crash if you're editing an already existing part; a new part seems ok delete m_sketchModel; } if (m_paletteModel) { delete m_paletteModel; } } void PartsEditorMainWindow::initText() { UntitledPartName = tr("Untitled Part"); TitleFreshStartText = tr("Please find a name for me!"); LabelFreshStartText = tr("Please provide a label"); DescriptionFreshStartText = tr("You could tell a little bit about this part"); TaxonomyFreshStartText = tr("Please classify this part"); TagsFreshStartText = tr("You can add your tags to make searching easier"); FooterText = tr("created by %1 on %2"); ___partsEditorName___ = tr("Parts Editor"); } void PartsEditorMainWindow::setup(long id, ModelPart *modelPart, bool fromTemplate, ItemBase * fromItem) { ModelPart * originalModelPart = NULL; QFile styleSheet(":/resources/styles/partseditor.qss"); m_mainFrame = new QFrame(this); m_mainFrame->setObjectName("partsEditor"); m_editingAlien = modelPart? modelPart->isAlien(): false; if (!styleSheet.open(QIODevice::ReadOnly)) { qWarning("Unable to open :/resources/styles/partseditor.qss"); } else { m_mainFrame->setStyleSheet(styleSheet.readAll()); } resize(500,700); m_id = id; m_partUpdated = false; m_savedAsNewPart = false; setAttribute(Qt::WA_DeleteOnClose, true); m_paletteModel = new PaletteModel(false, false); if(modelPart == NULL){ m_lastOpened = this; m_updateEnabled = true; } else { // user only allowed to save parts, once he has saved it as a new one m_updateEnabled = modelPart->isCore()? CORE_EDITION_ENABLED: (modelPart->isContrib() || modelPart->isAlien()? false: true); m_fwFilename = modelPart->path(); setTitle(); UntitledPartIndex--; // TODO Mariano: not good enough } if(!fromTemplate) { m_sketchModel = new SketchModel(true); } else { ModelPart * mp = m_paletteModel->loadPart(m_fwFilename, false); // this seems hacky but maybe it's ok if (mp == NULL || mp->modelPartShared() == NULL) { QMessageBox::critical(this, tr("Parts Editor"), tr("Error! Cannot load part.\n"), QMessageBox::Close); QTimer::singleShot(60, this, SLOT(close())); return; } QHash properties = mp->modelPartShared()->properties(); foreach (QString key, properties.keys()) { QVariant prop = modelPart->localProp(key); if (!prop.isNull() && prop.isValid()) { QString p = prop.toString(); if (!p.isEmpty()) { mp->modelPartShared()->properties()[key] = p; if (key.compare("chip label") == 0) { mp->modelPartShared()->properties()["family"] = p; } } } } originalModelPart = modelPart; modelPart = mp; m_sketchModel = new SketchModel(modelPart); } ModelPart *mp = fromTemplate ? modelPart : NULL; createHeader(mp); createCenter(mp, fromItem); createFooter(); // copy connector local names here if any if (originalModelPart) { foreach (Connector * fromConnector, originalModelPart->connectors()) { foreach (Connector * toConnector, mp->connectors()) { if (toConnector->connectorSharedID().compare(fromConnector->connectorSharedID()) == 0) { toConnector->setConnectorLocalName(fromConnector->connectorLocalName()); } } } } layout()->setMargin(0); layout()->setSpacing(0); QGridLayout *layout = new QGridLayout(m_mainFrame); layout->setMargin(0); layout->setSpacing(0); layout->addWidget(m_headerFrame,0,0); layout->addWidget(m_centerFrame,1,0); layout->addWidget(m_footerFrame,2,0); setCentralWidget(m_mainFrame); if(fromTemplate) { m_views->setViewItems(m_breadboardItem, m_schematicItem, m_pcbItem); m_views->loadViewsImagesFromModel(m_paletteModel, m_sketchModel->root()); } setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); QSettings settings; if (!settings.value("peditor/state").isNull()) { restoreState(settings.value("peditor/state").toByteArray()); } if (!settings.value("peditor/geometry").isNull()) { restoreGeometry(settings.value("peditor/geometry").toByteArray()); } installEventFilter(this); } void PartsEditorMainWindow::createHeader(ModelPart *modelPart) { m_headerFrame = new QFrame(); m_headerFrame->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed)); m_headerFrame->setObjectName("header"); m_headerFrame->setStyleSheet("padding: 2px; padding-bottom: 0;"); int iconViewSize = 50; QGraphicsProxyWidget *startItem = modelPart? NULL: PartsEditorMainWindow::emptyViewItem("icon_icon.png",___emptyString___); m_iconViewImage = new PartsEditorView( ViewLayer::IconView, createTempFolderIfNecessary(), false, startItem, m_headerFrame, iconViewSize ); m_iconViewImage->setViewItem(m_iconItem); m_iconViewImage->setFixedSize(iconViewSize,iconViewSize); m_iconViewImage->setObjectName("iconImage"); m_iconViewImage->setSketchModel(m_sketchModel); m_iconViewImage->setUndoStack(m_undoStack); m_iconViewImage->addViewLayer(new ViewLayer(ViewLayer::Icon, true, 2.5)); m_iconViewImage->setViewLayerIDs(ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon); if(modelPart) { m_iconViewImage->loadFromModel(m_paletteModel, modelPart); } QString linkStyle = "font-size: 10px; color: #7070ff;"; QLabel *button = new QLabel( QString("%1") .arg(tr("Load icon..")) .arg(linkStyle), this); button->setObjectName("iconBrowseButton"); //button->setFixedWidth(iconViewSize); button->setFixedHeight(20); //m_iconViewImage->addFixedToBottomRight(button); connect(button, SIGNAL(linkActivated(const QString&)), m_iconViewImage, SLOT(loadFile())); QString title = modelPart ? modelPart->title() : TitleFreshStartText; m_title = new EditableLineWidget(title,m_undoStack,m_headerFrame,"",modelPart,true); m_title->setObjectName("partTitle"); m_title->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::MinimumExpanding)); QGridLayout *headerLayout = new QGridLayout(); headerLayout->addWidget(m_iconViewImage,0,0); headerLayout->addWidget(m_title,0,1); headerLayout->addWidget(button,1,0,1,2); headerLayout->setVerticalSpacing(0); headerLayout->setMargin(0); m_headerFrame->setLayout(headerLayout); } void PartsEditorMainWindow::createCenter(ModelPart *modelPart, ItemBase * fromItem) { m_moduleId = modelPart ? modelPart->moduleID() : ""; m_version = modelPart ? modelPart->version() : ""; m_uri = modelPart ? modelPart->uri() : ""; m_centerFrame = new QFrame(); m_centerFrame->setObjectName("center"); QList specWidgets; m_connsInfo = new ConnectorsInfoWidget(m_undoStack,this); m_views = new PartsEditorViewsWidget(m_sketchModel, m_undoStack, m_connsInfo, this, fromItem); QString label = modelPart ? modelPart->label() : LabelFreshStartText; m_label = new EditableLineWidget(label,m_undoStack,this,tr("Label"),modelPart); QString description = modelPart ? modelPart->description() : DescriptionFreshStartText; m_description = new EditableTextWidget(description,m_undoStack,this,tr("Description"),modelPart); /*QString taxonomy = modelPart ? modelPart->modelPartShared()->taxonomy() : TAXONOMY_FRESH_START_TEXT; m_taxonomy = new EditableLineWidget(taxonomy,m_undoStack,this,tr("Taxonomy"),modelPart); QRegExp regexp("[\\w+\\.]+\\w$"); m_taxonomy->setValidator(new QRegExpValidator(regexp,this));*/ QStringList readOnlyKeys; readOnlyKeys << "family" << "voltage" << "type"; QHash initValues; if(modelPart) { initValues = modelPart->properties(); } else { initValues["family"] = ""; //initValues["voltage"] = ""; //initValues["type"] = "Through-Hole"; } m_properties = new HashPopulateWidget(tr("Properties"),initValues,readOnlyKeys,false, this); connect(m_properties, SIGNAL(changed()), this, SLOT(propertiesChanged())); QString tags = modelPart ? modelPart->tags().join(", ") : TagsFreshStartText; m_tags = new EditableLineWidget(tags,m_undoStack,this,tr("Tags"),modelPart); m_author = new EditableLineWidget( modelPart ? modelPart->author() : QString(getenvUser()), m_undoStack, this, tr("Author"),true); connect( m_author,SIGNAL(editionCompleted(QString)), this,SLOT(updateDateAndAuthor())); m_createdOn = new EditableDateWidget( modelPart ? modelPart->date() : QDate::currentDate(), m_undoStack,this, tr("Created/Updated on"),true); connect( m_createdOn,SIGNAL(editionCompleted(QString)), this,SLOT(updateDateAndAuthor())); m_createdByText = new QLabel(FooterText.arg(m_author->text()).arg(m_createdOn->text())); m_createdByText->setObjectName("createdBy"); specWidgets << m_label << m_description /*<< m_taxonomy*/ << m_properties << m_tags << m_author << m_createdOn << m_createdByText; m_connsInfo->setViews(m_views); connect(m_connsInfo, SIGNAL(repaintNeeded()), m_views, SLOT(repaint())); connect(m_connsInfo, SIGNAL(drawConnector(Connector*)), m_views, SLOT(drawConnector(Connector*))); connect( m_connsInfo, SIGNAL(drawConnector(ViewLayer::ViewIdentifier, Connector*)), m_views, SLOT(drawConnector(ViewLayer::ViewIdentifier, Connector*)) ); connect( m_connsInfo, SIGNAL(setMismatching(ViewLayer::ViewIdentifier, const QString&, bool)), m_views, SLOT(setMismatching(ViewLayer::ViewIdentifier, const QString&, bool)) ); connect(m_connsInfo, SIGNAL(removeConnectorFrom(const QString&,ViewLayer::ViewIdentifier)), m_views, SLOT(removeConnectorFrom(const QString&,ViewLayer::ViewIdentifier))); connect(m_views, SIGNAL(connectorSelectedInView(const QString&)), m_connsInfo, SLOT(connectorSelectedInView(const QString&))); m_views->showTerminalPointsCheckBox()->setChecked(false); m_views->connectTerminalRemoval(m_connsInfo); connect( m_views, SIGNAL(connectorsFoundSignal(QList< QPointer >)), m_connsInfo, SLOT(connectorsFound(QList< QPointer >)) ); m_tabWidget = new QTabWidget(m_centerFrame); m_tabWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); m_tabWidget->addTab(new PartSpecificationsWidget(specWidgets,this),tr("Specifications")); m_tabWidget->addTab(new PartConnectorsWidget(m_connsInfo,this),tr("Connectors")); QGridLayout *tabLayout = new QGridLayout(m_tabWidget); tabLayout->setMargin(0); tabLayout->setSpacing(0); QSplitter *splitter = new QSplitter(Qt::Vertical,this); splitter->addWidget(m_views); splitter->addWidget(m_tabWidget); QGridLayout *mainLayout = new QGridLayout(m_centerFrame); mainLayout->setMargin(0); mainLayout->setSpacing(0); mainLayout->addWidget(splitter,0,0,1,1); } void PartsEditorMainWindow::connectWidgetsToSave(const QList &widgets) { for(int i=0; i < widgets.size(); i++) { connect(m_saveAsNewPartButton,SIGNAL(clicked()),widgets[i],SLOT(informEditionCompleted())); connect(this,SIGNAL(saveButtonClicked()),widgets[i],SLOT(informEditionCompleted())); } } void PartsEditorMainWindow::createFooter() { m_footerFrame = new QFrame(); m_footerFrame->setObjectName("footer"); m_footerFrame->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); m_saveAsNewPartButton = new QPushButton(tr("save as new part")); m_saveAsNewPartButton->setObjectName("saveAsPartButton"); m_saveAsNewPartButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); m_saveButton = new QPushButton(tr("save")); m_saveButton->setObjectName("saveAsButton"); m_saveButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); updateSaveButton(); QList editableLabelWidgets; editableLabelWidgets << m_title << m_label << m_description /*<< m_taxonomy*/ << m_tags << m_author << m_createdOn << m_connsInfo ; connectWidgetsToSave(editableLabelWidgets); connect(m_saveAsNewPartButton, SIGNAL(clicked()), this, SLOT(saveAs())); connect(m_saveButton, SIGNAL(clicked()), this, SLOT(save())); m_cancelCloseButton = new QPushButton(tr("cancel")); m_cancelCloseButton->setObjectName("cancelButton"); m_cancelCloseButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); connect(m_cancelCloseButton, SIGNAL(clicked()), this, SLOT(close())); QHBoxLayout *footerLayout = new QHBoxLayout; footerLayout->setMargin(0); footerLayout->setSpacing(0); footerLayout->addSpacerItem(new QSpacerItem(40,0,QSizePolicy::Minimum,QSizePolicy::Minimum)); footerLayout->addWidget(m_saveAsNewPartButton); footerLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Minimum)); footerLayout->addWidget(m_saveButton); footerLayout->addSpacerItem(new QSpacerItem(15,0,QSizePolicy::Minimum,QSizePolicy::Minimum)); footerLayout->addWidget(m_cancelCloseButton); footerLayout->addSpacerItem(new QSpacerItem(40,0,QSizePolicy::Minimum,QSizePolicy::Minimum)); m_footerFrame->setLayout(footerLayout); } QGraphicsProxyWidget *PartsEditorMainWindow::emptyViewItem(QString iconFile, QString text) { QLabel *icon = new QLabel(); icon->setPixmap(QPixmap(":/resources/images/"+iconFile)); icon->setAlignment(Qt::AlignHCenter); QLabel *label = NULL; if(!text.isNull() && !text.isEmpty()) { label = new QLabel(text); label->setAlignment(Qt::AlignHCenter); } QFrame *container = new QFrame(); container->setStyleSheet("background-color: transparent;"); QVBoxLayout *mainLo = new QVBoxLayout(container); mainLo->setMargin(0); mainLo->setSpacing(0); QHBoxLayout *lo1 = new QHBoxLayout(); lo1->addWidget(icon); lo1->setMargin(0); lo1->setSpacing(0); mainLo->addLayout(lo1); if(label) { QHBoxLayout *lo2 = new QHBoxLayout(); lo2->addWidget(label); lo2->setMargin(0); lo2->setSpacing(0); mainLo->addLayout(lo2); } QGraphicsProxyWidget *item = new QGraphicsProxyWidget(); item->setWidget(container); return item; } const QDir& PartsEditorMainWindow::createTempFolderIfNecessary() { if(m_tempDir.path() == ".") { QString randext = FolderUtils::getRandText(); m_tempDir = QDir(QDir::tempPath()); bool dirCreation = m_tempDir.mkdir(randext); if (!dirCreation) { throw "PartsEditorMainWindow::createTempFolderIfNecessary creation failure"; } if(dirCreation) { bool cdResult = m_tempDir.cd(randext); if (!cdResult) { throw "PartsEditorMainWindow::createTempFolderIfNecessary cd failure"; } } else { // will use the standard location of the temp folder // instead of a subfolder inside of it } } return m_tempDir; } bool PartsEditorMainWindow::save() { if(validateMinRequirements() && wannaSaveAfterWarning(false)) { bool result = (m_saveButton->isEnabled()) ? FritzingWindow::save() : saveAs(); if(result) { m_cancelCloseButton->setText(tr("close")); if(m_closeAfterSaving) close(); } return result; } else { return false; } } bool PartsEditorMainWindow::saveAs() { if(!validateMinRequirements()) return false; QString fileNameBU = m_fwFilename; QString moduleIdBU = m_moduleId; m_moduleId = ___emptyString___; QString title = m_title->text(); m_fwFilename = !title.isEmpty() ? title+FritzingPartExtension : QFileInfo(m_fwFilename).baseName(); // TODO Mariano: This folder should be defined in the preferences... some day QString partsFolderPath = FolderUtils::getUserDataStorePath("parts")+"/"; QString userPartsFolderPath = partsFolderPath+"user/"; bool firstTime = true; // Perhaps the user wants to use the default file name, confirm first while(m_fwFilename.isEmpty() || QFileInfo(userPartsFolderPath+m_fwFilename).exists() || (FolderUtils::isEmptyFileName(m_fwFilename,untitledFileName()) && firstTime) ) { bool ok; m_fwFilename = QInputDialog::getText( this, tr("Save as new part"), tr("There's already a file with this name.\nPlease, specify a new filename"), QLineEdit::Normal, m_fwFilename, &ok ); firstTime = false; if (!ok) { m_moduleId = moduleIdBU; m_fwFilename = fileNameBU; return false; } } m_fwFilename.replace(QRegExp("[^A-Za-z0-9\\.]"), "_"); Qt::CaseSensitivity cs = Qt::CaseSensitive; #ifdef Q_WS_WIN // seems to be necessary for Windows: getUserDataStorePath() returns a string starting with "c:" // but the file dialog returns a string beginning with "C:" cs = Qt::CaseInsensitive; #endif QString filename = !m_fwFilename.startsWith(userPartsFolderPath, cs) && !m_fwFilename.startsWith(partsFolderPath, cs) ? userPartsFolderPath+m_fwFilename : m_fwFilename; QString guid = "__"+FolderUtils::getRandText()+FritzingPartExtension; if(!alreadyHasExtension(filename, FritzingPartExtension)) { filename += guid; } else { filename.replace(FritzingPartExtension,guid); } makeNonCore(); if (!saveAsAux(filename)) return false; if(wannaSaveAfterWarning(true)) { m_savedAsNewPart = true; m_updateEnabled = true; updateButtons(); if(m_closeAfterSaving) close(); return true; } return false; } void PartsEditorMainWindow::makeNonCore() { QString oldTags = m_tags->text(); QString newTags = oldTags.replace("fritzing core","user part",Qt::CaseInsensitive); m_tags->setText(newTags); } bool PartsEditorMainWindow::saveAsAux(const QString & fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("Fritzing"), tr("Cannot write file %1:\n%2.") .arg(fileName) .arg(file.errorString())); return false; } file.close(); updateDateAndAuthor(); QApplication::setOverrideCursor(Qt::WaitCursor); m_sketchModel->root()->setModelPartShared(createModelPartShared()); QString fileNameAux = QFileInfo(fileName).fileName(); m_views->copySvgFilesToDestiny(fileNameAux); m_iconViewImage->copySvgFileToDestiny(fileNameAux); m_sketchModel->save(fileName, true); QApplication::restoreOverrideCursor(); statusBar()->showMessage(tr("Saved '%1'").arg(fileName), 2000); m_partUpdated = true; setFileName(fileName); //setCurrentFile(fileName); // mark the stack clean so we update the window dirty flag m_undoStack->setClean(); setTitle(); if(m_editingAlien) { // FIXME: this will keep ALL the external files, not just the ones that this part uses emit alienPartUsed(); m_editingAlien = false; } return true; } void PartsEditorMainWindow::updateDateAndAuthor() { m_createdByText->setText(FooterText.arg(m_author->text()).arg(m_createdOn->text())); } ModelPartShared* PartsEditorMainWindow::createModelPartShared() { ModelPartShared* shared = new ModelPartShared(); if(m_moduleId.isNull() || m_moduleId.isEmpty()) { m_moduleId = FolderUtils::getRandText(); } shared->setModuleID(m_moduleId); shared->setUri(m_uri); shared->setVersion(m_version); shared->setAuthor(m_author->text()); shared->setTitle(m_title->text()); shared->setDate(m_createdOn->text()); shared->setLabel(m_label->text()); //stuff->setTaxonomy(m_taxonomy->text()); shared->setDescription(m_description->text()); QStringList tags = m_tags->text().split(", "); shared->setTags(tags); shared->setProperties(m_properties->hash()); m_iconViewImage->aboutToSave(true); m_views->aboutToSave(); // the deal seems to be that an original modelpart is created and becomes the official sketch model (root). // the ConnectorsShared from that model are used to seed the PartsEditorConnectorsConnectorItems. // When a new image is loaded into a view, the sketch model's ConnectorsShared are replaced with newly constructed ones. // So now the sketch model points to one set of ConnectorsShared, but the original ones are still sitting // back in the PartsEditorConnectorsConnectorItems. So now we replace the new ones with the old ones. // I think. QList< QPointer > connsShared = m_connsInfo->connectorsShared(); m_views->updatePinsInfo(connsShared); shared->setConnectorsShared(m_connsInfo->connectorsShared()); return shared; } void PartsEditorMainWindow::cleanUp() { bool decUntitled = m_fwFilename.startsWith(untitledFileName()); if(decUntitled) { if(m_lastOpened == this) { UntitledPartIndex -= m_closedBeforeCount; UntitledPartIndex--; m_closedBeforeCount = 0; } else { m_closedBeforeCount++; } } if(m_tempDir.path() != ".") { FolderUtils::rmdir(m_tempDir); m_tempDir = QDir(); } } void PartsEditorMainWindow::parentAboutToClose() { if(beforeClosing(false)) { cleanUp(); } } void PartsEditorMainWindow::closeEvent(QCloseEvent *event) { if(beforeClosing()) { cleanUp(); QMainWindow::closeEvent(event); if(m_partUpdated) { emit partUpdated(m_fwFilename, m_id, !m_savedAsNewPart && (m_connsInfo->connectorsCountChanged() || m_views->connectorsPosOrSizeChanged()) ); } emit closed(m_id); } else { event->ignore(); } QSettings settings; settings.setValue("peditor/state",saveState()); settings.setValue("peditor/geometry",saveGeometry()); } const QDir& PartsEditorMainWindow::tempDir() { return createTempFolderIfNecessary(); } const QString PartsEditorMainWindow::untitledFileName() { return UntitledPartName; } int &PartsEditorMainWindow::untitledFileCount() { return UntitledPartIndex; } const QString PartsEditorMainWindow::fileExtension() { return FritzingPartExtension; } const QString PartsEditorMainWindow::defaultSaveFolder() { return QDir::currentPath()+"/parts/user/"; } void PartsEditorMainWindow::updateSaveButton() { if(m_saveButton) m_saveButton->setEnabled(m_updateEnabled); } bool PartsEditorMainWindow::wannaSaveAfterWarning(bool savingAsNew) { bool doEmit = true; bool errorFound = false; QString msg = "Some errors found:\n"; if(!m_savedAsNewPart && !savingAsNew && m_connsInfo->connectorsRemoved()) { errorFound = true; msg += "- The connectors defined in this part have changed.\n" "If you save it, you may break other sketches that already use it.\n"; } if(m_connsInfo->hasMismatchingConnectors()) { errorFound = true; msg += "- Some connectors are not present in all views." "If you save now, they will be removed.\n"; } if(errorFound) { msg += "\nDo you want to save anyway?"; QMessageBox::StandardButton btn = QMessageBox::question(this, tr("Updating existing part"), msg, QMessageBox::Yes|QMessageBox::No ); doEmit = (btn == QMessageBox::Yes); } if(doEmit) emit saveButtonClicked(); return doEmit; } void PartsEditorMainWindow::updateButtons() { m_saveAsNewPartButton->setEnabled(false); m_cancelCloseButton->setText(tr("close")); } bool PartsEditorMainWindow::eventFilter(QObject *object, QEvent *event) { if (object == this && event->type() == QEvent::ShortcutOverride) { QKeyEvent *keyEvent = dynamic_cast(event); if(keyEvent && keyEvent->matches(QKeySequence::Close)) { this->close(); event->ignore(); ProcessEventBlocker::processEvents(); #ifdef Q_WS_MAC FritzingWindow *parent = qobject_cast(parentWidget()); if(parent) { parent->notClosableForAWhile(); } #endif return true; } } return QMainWindow::eventFilter(object, event); } const QString PartsEditorMainWindow::fritzingTitle() { QString fritzing = FritzingWindow::fritzingTitle(); return tr("%1 %2").arg(fritzing).arg(___partsEditorName___); } bool PartsEditorMainWindow::event(QEvent * e) { switch (e->type()) { case QEvent::WindowActivate: emit changeActivationSignal(true, this); break; case QEvent::WindowDeactivate: emit changeActivationSignal(false, this); break; default: break; } return FritzingWindow::event(e); } bool PartsEditorMainWindow::validateMinRequirements() { if(!m_iconViewImage->isEmpty()) { return true; } else { QMessageBox::information(this, tr("Icon needed"), tr("Please, provide an icon image for this part")); return false; } } void PartsEditorMainWindow::setViewItems(ItemBase * iiItem, ItemBase* bbItem, ItemBase* schemItem, ItemBase* pcbItem) { m_iconItem = iiItem; m_breadboardItem = bbItem; m_schematicItem = schemItem; m_pcbItem = pcbItem; } QString PartsEditorMainWindow::getExtensionString() { return tr("Fritzing Parts (*%1)").arg(fileExtension()); } QStringList PartsEditorMainWindow::getExtensions() { QStringList extensions; extensions.append(fileExtension()); return extensions; } void PartsEditorMainWindow::propertiesChanged() { if (m_undoStack) { m_undoStack->push(new QUndoCommand("dummy parts editor command")); } } fritzing-app-0.9.2b/src/partseditor/obsolete/partseditormainwindow.h000066400000000000000000000116061250202676700260620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSEDITORMAINWINDOW_H_ #define PARTSEDITORMAINWINDOW_H_ #include #include #include #include #include "../mainwindow/fritzingwindow.h" #include "../model/modelpartshared.h" #include "connectorsinfowidget.h" #include "editablelinewidget.h" QT_FORWARD_DECLARE_CLASS(QGraphicsScene) QT_FORWARD_DECLARE_CLASS(QGraphicsView) QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QSplitter) class PartsEditorMainWindow : public FritzingWindow { Q_OBJECT public: PartsEditorMainWindow(QWidget *parent=0); ~PartsEditorMainWindow(); void setup(long id, ModelPart *modelPart, bool fromTemplate, class ItemBase * fromItem); void setViewItems(class ItemBase *, class ItemBase *, class ItemBase *, class ItemBase *); static const QString templatePath; const QDir& tempDir(); bool validateMinRequirements(); bool save(); signals: void partUpdated(const QString &filename, long myId, bool connectorsChanged); void closed(long id); void changeActivationSignal(bool activate, QWidget * originator); void saveButtonClicked(); void alienPartUsed(); public slots: void parentAboutToClose(); protected slots: void updateDateAndAuthor(); void propertiesChanged(); protected: bool saveAs(); bool saveAsAux(const QString & fileName); const QDir& createTempFolderIfNecessary(); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *object, QEvent *event); void createHeader(ModelPart * = 0); void createCenter(ModelPart * = 0, class ItemBase * fromItem = 0); void connectWidgetsToSave(const QList &widgets); void createFooter(); ModelPartShared* createModelPartShared(); const QString untitledFileName(); int &untitledFileCount(); const QString fileExtension(); QString getExtensionString(); QStringList getExtensions(); const QString defaultSaveFolder(); void updateSaveButton(); bool wannaSaveAfterWarning(bool savingAsNew); void updateButtons(); const QString fritzingTitle(); void cleanUp(); bool event(QEvent *); void makeNonCore(); protected: long m_id; QPointer m_paletteModel; QPointer m_sketchModel; QPointer m_iconViewImage; QPointer m_title; QPointer m_views; QPointer m_iconItem; QPointer m_breadboardItem; QPointer m_schematicItem; QPointer m_pcbItem; QPointer m_label; QPointer m_description; //QPointer m_taxonomy; QPointer m_tags; QPointer m_properties; QPointer m_author; QPointer m_createdOn; QPointer m_createdByText; QPointer m_connsInfo; QString m_version; QString m_moduleId; QString m_uri; QPointer m_saveAsNewPartButton; QPointer m_saveButton; QPointer m_cancelCloseButton; QPointer m_tabWidget; QPointer m_mainFrame; QPointer m_headerFrame; QPointer m_centerFrame; QPointer m_footerFrame; bool m_updateEnabled; bool m_partUpdated; bool m_savedAsNewPart; bool m_editingAlien; static QPointer m_lastOpened; static int m_closedBeforeCount; static QString ___partsEditorName___; static bool m_closeAfterSaving; public: static QString TitleFreshStartText; static QString LabelFreshStartText; static QString DescriptionFreshStartText; static QString TaxonomyFreshStartText; static QString TagsFreshStartText; static QString FooterText; static QString UntitledPartName; static int UntitledPartIndex; static QGraphicsProxyWidget *emptyViewItem(QString iconFile, QString text=""); static void initText(); }; #endif /* PARTSEDITORMAINWINDOW_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partseditorview.cpp000066400000000000000000001703371250202676700252220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6417 $: $Author: cohen@irascible.com $: $Date: 2012-09-14 23:34:09 +0200 (Fr, 14. Sep 2012) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "partseditorview.h" #include "partseditorconnectoritem.h" #include "fixfontsdialog.h" #include "zoomcontrols.h" #include "kicadmoduledialog.h" #include "../items/layerkinpaletteitem.h" #include "../items/partfactory.h" #include "../layerattributes.h" #include "../mainwindow/fritzingwindow.h" #include "../fsvgrenderer.h" #include "../debugdialog.h" #include "../utils/folderutils.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../utils/ratsnestcolors.h" #include "../svg/gedaelement2svg.h" #include "../svg/kicadmodule2svg.h" #include "../svg/kicadschematic2svg.h" #include "../connectors/connectorshared.h" int PartsEditorView::ConnDefaultWidth = 5; int PartsEditorView::ConnDefaultHeight = ConnDefaultWidth; PartsEditorView::PartsEditorView( ViewLayer::ViewIdentifier viewId, QDir tempDir, bool showingTerminalPoints, QGraphicsProxyWidget *startItem, QWidget *parent, int size, bool deleteModelPartOnClearScene, ItemBase * fromItem) : SketchWidget(viewId, parent, size, size) { m_alignToGrid = m_showGrid = false; m_viewItem = NULL; m_item = NULL; m_connsLayerID = ViewLayer::UnknownLayer; m_svgLoaded = false; m_deleteModelPartOnSceneClear = deleteModelPartOnClearScene; m_tempFolder = tempDir; setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setDefaultBackground(); //spec m_svgFilePath = new SvgAndPartFilePath; m_startItem = startItem; if(m_startItem) { addFixedToCenterItem(startItem); ensureFixedToCenterItems(); connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(ensureFixedItemsPositions())); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(ensureFixedItemsPositions())); connect(this, SIGNAL(resizeSignal()), this, SLOT(ensureFixedItemsPositions())); connect(this, SIGNAL(wheelSignal()), this, SLOT(ensureFixedItemsPositions())); // TODO: do we still need this? QTimer::singleShot(400, this, SLOT(ensureFixedItemsPositions())); } addDefaultLayers(fromItem); // conns m_showingTerminalPoints = showingTerminalPoints; m_lastSelectedConnId = ""; setDragMode(QGraphicsView::ScrollHandDrag); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); m_terminalPointsTimer = new QTimer(this); connect( m_terminalPointsTimer,SIGNAL(timeout()), this,SLOT(recoverTerminalPointsState()) ); m_showingTerminalPointsBackup = m_showingTerminalPoints; m_fitItemInViewTimer = new QTimer(this); m_fitItemInViewTimer->setSingleShot(true); m_fitItemInViewTimer->setInterval(200); connect(m_fitItemInViewTimer,SIGNAL(timeout()),this,SLOT(fitCenterAndDeselect())); } PartsEditorView::~PartsEditorView() { if (m_startItem) delete m_startItem; delete m_svgFilePath; clearScene(); } void PartsEditorView::addDefaultLayers(ItemBase * fromItem) { switch( m_viewIdentifier ) { case ViewLayer::BreadboardView: addBreadboardViewLayers(); break; case ViewLayer::SchematicView: addSchematicViewLayers(); break; case ViewLayer::PCBView: addPcbViewLayers(); if (fromItem && fromItem->modelPart()->flippedSMD()) { DebugDialog::debug("editing an SMD part"); setViewLayerIDs(ViewLayer::Silkscreen1, ViewLayer::Copper1Trace, ViewLayer::Copper1, ViewLayer::PcbRuler, ViewLayer::PcbNote); this->m_viewLayers.remove(ViewLayer::Copper0); this->m_viewLayers.remove(ViewLayer::Silkscreen0); this->m_viewLayers.remove(ViewLayer::Copper0Trace); } break; default: break; } } void PartsEditorView::addItemInPartsEditor(ModelPart * modelPart, SvgAndPartFilePath * svgFilePath) { if (modelPart == NULL) { throw "PartsEditorView::addItemInPartsEditor no model part"; } clearScene(); m_item = newPartsEditorPaletteItem(modelPart, svgFilePath); this->addItem(modelPart, defaultViewLayerSpec(), BaseCommand::CrossView, m_item->getViewGeometry(), m_item->id(), -1, NULL, m_item); fitCenterAndDeselect(); setItemProperties(); /*foreach(QWidget* w, m_fixedWidgets) { QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(); proxy->setWidget(w); addFixedToBottomRightItem(proxy); }*/ emit connectorsFoundSignal(this->m_viewIdentifier,m_item->connectors()); } ItemBase * PartsEditorView::addItemAux(ModelPart * modelPart, ViewLayer::ViewLayerSpec viewLayerSpec, const ViewGeometry &, long id, PaletteItem * paletteItemAux, bool doConnectors, ViewLayer::ViewIdentifier, bool temporary) { Q_UNUSED(id); Q_UNUSED(temporary); if(paletteItemAux == NULL) { paletteItemAux = newPartsEditorPaletteItem(modelPart); } PartsEditorPaletteItem *paletteItem = dynamic_cast(paletteItemAux); if (paletteItem == NULL) { throw "PartsEditorView::addItemAux paletteItem not found"; } if(paletteItem) { modelPart->initConnectors(); // is a no-op if connectors already in place QString layerFileName = getLayerFileName(modelPart); if(!layerFileName.isEmpty()) { if(paletteItem->createSvgPath(modelPart->path(), layerFileName)) { paletteItem->createSvgFile(paletteItem->svgFilePath()->absolutePath()); ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString( findConnectorsLayerId(paletteItem->svgDom()) ); if(viewLayerID == ViewLayer::UnknownLayer) { viewLayerID = getViewLayerID(modelPart, m_viewIdentifier, viewLayerSpec); } addDefaultLayers(NULL); if (m_viewItem != NULL) { QHash svgHash; QString svg = ""; foreach (ViewLayer * vl, m_viewLayers.values()) { svg += m_viewItem->retrieveSvg(vl->viewLayerID(), svgHash, false, GraphicsUtils::StandardFritzingDPI); } if (!svg.isEmpty()) { QSizeF size = m_viewItem->size(); svg = TextUtils::makeSVGHeader(GraphicsUtils::SVGDPI, GraphicsUtils::StandardFritzingDPI, size.width(), size.height()) + svg + ""; paletteItem->setItemSVG(svg); } } QString error; if (paletteItem->renderImage(modelPart, m_viewIdentifier, m_viewLayers, viewLayerID, doConnectors, error)) { addToScene(paletteItemAux, paletteItemAux->viewLayerID()); // layers are not needed on the parts editor (so far) return paletteItemAux; } } } } return NULL; } void PartsEditorView::fitCenterAndDeselect() { if(m_item) { m_item->setSelected(false); m_item->setHidden(false); m_item->setInactive(false); fitInView(m_item, Qt::KeepAspectRatio); QRectF viewRect = rect(); QRectF itemsRect = scene()->itemsBoundingRect(); double wRelation = viewRect.width() / itemsRect.width(); double hRelation = viewRect.height() / itemsRect.height(); if(wRelation < hRelation) { m_scaleValue = (wRelation * 100); } else { m_scaleValue = (hRelation * 100); } emit zoomChanged(m_scaleValue); } } void PartsEditorView::setDefaultBackground() { QString bgColor = " PartsEditorView {background-color: rgb(%1,%2,%3);} "; QColor c = standardBackground(); if (c.isValid()) { setStyleSheet(styleSheet()+bgColor.arg(c.red()).arg(c.green()).arg(c.blue())); } } void PartsEditorView::clearScene() { if(m_item) { deleteItem(m_item, m_deleteModelPartOnSceneClear, true, false); scene()->clear(); m_item = NULL; } } void PartsEditorView::removeConnectors() { QList list; for (int i = m_item->childItems().count()-1; i >= 0; i--) { PartsEditorConnectorItem * connectorItem = dynamic_cast(m_item->childItems()[i]); if (connectorItem == NULL) continue; list << connectorItem; } for(int i=0; i < list.size(); i++) { list[i]->removeFromModel(); delete list[i]; } } ModelPart *PartsEditorView::createFakeModelPart(SvgAndPartFilePath *svgpath) { const QHash connIds = getConnectorsSvgIds(svgpath->absolutePath()); const QStringList layers = getLayers(svgpath->absolutePath()); QString path = svgpath->relativePath().isEmpty() ? svgpath->absolutePath() : svgpath->relativePath(); ModelPart * mp = createFakeModelPart(connIds, layers, path); return mp; } ModelPart *PartsEditorView::createFakeModelPart(const QHash &conns, const QStringList &layers, const QString &svgFilePath) { QDomDocument *domDoc = new QDomDocument(); QString errorStr; int errorLine; int errorColumn; QString fakeFzFile = QString("\n")+ QString("<%1>\n").arg(ViewLayer::viewIdentifierXmlName(m_viewIdentifier)).arg(svgFilePath); foreach(QString layer, layers) { fakeFzFile += QString(" \n").arg(layer); } fakeFzFile += QString("\n").arg(ViewLayer::viewIdentifierXmlName(m_viewIdentifier))+ QString("\n"); QStringList defaultLayers = defaultLayerAsStringlist(); foreach(QString id, conns.keys()) { QString terminalAttr = conns[id].terminalId.isEmpty() ? "" : QString("terminalId='%1'").arg(conns[id].terminalId); QString name = conns[id].connectorName.isEmpty() ? "" : QString("name='%1'").arg(conns[id].connectorName); fakeFzFile += QString("\n").arg(id).arg(name) + QString("<%1>\n").arg(ViewLayer::viewIdentifierXmlName(m_viewIdentifier)); foreach (QString layer, defaultLayers) { if (layers.contains(layer)) { fakeFzFile += QString("

\n") .arg(layer) .arg(conns[id].connectorId) .arg(terminalAttr); } } fakeFzFile += QString("\n").arg(ViewLayer::viewIdentifierXmlName(m_viewIdentifier))+ QString("\n"); } fakeFzFile += QString("\n"); QString path = m_tempFolder.absolutePath()+"/"+FolderUtils::getRandText()+".fz"; TextUtils::writeUtf8(path, fakeFzFile); domDoc->setContent(fakeFzFile, &errorStr, &errorLine, &errorColumn); ModelPart *retval = m_sketchModel->root(); retval->modelPartShared()->setDomDocument(domDoc); retval->modelPartShared()->resetConnectorsInitialization(); retval->modelPartShared()->setPath(path); retval->initConnectors(true /*redo connectors*/); return retval; } const QHash PartsEditorView::getConnectorsSvgIds(const QString &path) { QDomDocument dom ; QFile file(path); dom.setContent(&file); QDomElement docElem = dom.documentElement(); getConnectorsSvgIdsAux(docElem); return m_svgIds; } void PartsEditorView::getConnectorsSvgIdsAux(QDomElement &docElem) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if(id.startsWith("connector") && id.endsWith("terminal")) { QString conn = id.left(id.lastIndexOf(QRegExp("\\d"))+1); ConnectorTerminalSvgIdPair pair = m_svgIds.contains(conn) ? m_svgIds[conn] : ConnectorTerminalSvgIdPair(); pair.terminalId = id; m_svgIds[conn] = pair; } else if(id.startsWith("connector") /*&& id.endsWith("pin") */ ) { QString conn = id.left(id.lastIndexOf(QRegExp("\\d"))+1); ConnectorTerminalSvgIdPair pair = m_svgIds.contains(conn) ? m_svgIds[conn] : ConnectorTerminalSvgIdPair(); pair.connectorId = id; pair.connectorName = e.attribute("connectorname"); m_svgIds[conn] = pair; } if(e.hasChildNodes()) { getConnectorsSvgIdsAux(e); } e = e.nextSiblingElement(); } } const QStringList PartsEditorView::getLayers(const QString &path) { if(m_viewIdentifier == ViewLayer::IconView) { // defaulting layer to icon for iconview return defaultLayerAsStringlist(); } else { QDomDocument dom; QFile file(path); dom.setContent(&file); return getLayers(&dom); } } const QStringList PartsEditorView::getLayers(const QDomDocument *dom, bool fakeDefaultIfNone) { QStringList retval; QDomNodeList nodeList = dom->elementsByTagName("g"); for (uint i = 0; i < nodeList.length(); i++) { QDomElement e = nodeList.item(i).toElement(); QString id = e.attribute("id"); if (id.isEmpty()) continue; if (ViewLayer::viewLayerIDFromXmlString(id) == ViewLayer::UnknownLayer) continue; retval << id; } if(fakeDefaultIfNone && retval.isEmpty()) { retval << ViewLayer::viewIdentifierNaturalName(m_viewIdentifier); } return retval; } PartsEditorPaletteItem *PartsEditorView::newPartsEditorPaletteItem(ModelPart *modelPart) { return new PartsEditorConnectorsPaletteItem(this, modelPart, m_viewIdentifier); } PartsEditorPaletteItem *PartsEditorView::newPartsEditorPaletteItem(ModelPart * modelPart, SvgAndPartFilePath *path) { return new PartsEditorConnectorsPaletteItem(this, modelPart, m_viewIdentifier, path); } QDir PartsEditorView::tempFolder() { return m_tempFolder; } QString PartsEditorView::getOrCreateViewFolderInTemp() { QString viewFolder = ViewLayer::viewIdentifierNaturalName(m_viewIdentifier); if(!QFileInfo(m_tempFolder.absolutePath()+"/"+viewFolder).exists()) { bool mkResult = m_tempFolder.mkpath(m_tempFolder.absolutePath()+"/"+viewFolder); if (!mkResult) { throw "PartsEditorView::getOrCreateViewFolderInTemp failed"; } } return viewFolder; } bool PartsEditorView::isEmpty() { return m_item == NULL; } bool PartsEditorView::ensureFilePath(const QString &filePath) { QString svgFolder = FolderUtils::getUserDataStorePath("parts")+"/svg"; Qt::CaseSensitivity cs = Qt::CaseSensitive; #ifdef Q_WS_WIN cs = Qt::CaseInsensitive; #endif if(!filePath.contains(svgFolder, cs)) { // This has to be here in order of all this, to work in release mode m_tempFolder.mkpath(QFileInfo(filePath).absoluteDir().path()); } return true; } ViewLayer::ViewLayerID PartsEditorView::connectorsLayerId() { //Q_ASSERT(m_item); findConnectorsLayerId(); return m_connsLayerID; } QString PartsEditorView::terminalIdForConnector(const QString &connId) { //Q_ASSERT(m_item) if (m_item == NULL) return ""; QString result = ""; QDomElement elem = m_item->svgDom()->documentElement(); if(terminalIdForConnectorIdAux(result, connId, elem, true)) { return result; } else { return ""; } } bool PartsEditorView::terminalIdForConnectorIdAux(QString &result, const QString &connId, QDomElement &docElem, bool wantTerminal) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if(id.startsWith(connId) && ((wantTerminal && id.endsWith("terminal")) || (!wantTerminal && !id.endsWith("terminal")))) { // the id is the one from the previous iteration result = id; return true; } else if(e.hasChildNodes()) { // potencial solution, if the next iteration returns true if(terminalIdForConnectorIdAux(result, connId, e, wantTerminal)) { return true; } } e = e.nextSiblingElement(); } return false; } void PartsEditorView::findConnectorsLayerId() { if(m_connsLayerID == ViewLayer::UnknownLayer) { if (m_item != NULL) { m_connsLayerID = ViewLayer::viewLayerIDFromXmlString( findConnectorsLayerId(m_item->svgDom()) ); } if(m_connsLayerID == ViewLayer::UnknownLayer) { m_connsLayerID = SketchWidget::defaultConnectorLayer(m_viewIdentifier); } } } QStringList PartsEditorView::findConnectorsLayerIds(QDomDocument *svgDom) { QStringList result; QDomElement docElem = svgDom->documentElement(); findConnectorsLayerIdsAux(result, docElem); if (result.count() > 0) return result; return defaultLayerAsStringlist(); } void PartsEditorView::findConnectorsLayerIdsAux(QStringList &result, QDomElement &docElem) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if (id.startsWith("connector")) { QDomElement parent = e.parentNode().toElement(); QString id = parent.attribute("id"); if (!id.isEmpty() && (ViewLayer::viewLayerIDFromXmlString(id) != ViewLayer::UnknownLayer)) { result << id; } } else if(e.hasChildNodes()) { findConnectorsLayerIdsAux(result, e); } e = e.nextSiblingElement(); } } QString PartsEditorView::findConnectorsLayerId(QDomDocument *svgDom) { QString result; QStringList layers; QDomElement docElem = svgDom->documentElement(); if(findConnectorsLayerIdAux(result, docElem, layers)) { if(ViewLayer::viewLayerIDFromXmlString(result) == ViewLayer::UnknownLayer) { foreach(QString layer, layers) { ViewLayer::ViewLayerID vlid = ViewLayer::viewLayerIDFromXmlString(layer); if(m_viewLayers.keys().contains(vlid)) { result = layer; } } } return result; } else { return defaultLayerAsStringlist().at(0); } } bool PartsEditorView::findConnectorsLayerIdAux(QString &result, QDomElement &docElem, QStringList &prevLayers) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if(id.startsWith("connector")) { // the id is the one from the previous iteration return true; } else if(e.hasChildNodes()) { // potencial solution, if the next iteration returns true result = id; prevLayers << id; if(findConnectorsLayerIdAux(result, e, prevLayers)) { return true; } } e = e.nextSiblingElement(); } return false; } QString PartsEditorView::getLayerFileName(ModelPart * modelPart) { return modelPart->imageFileName(m_viewIdentifier); } // specs void PartsEditorView::copySvgFileToDestiny(const QString &partFileName) { Qt::CaseSensitivity cs = Qt::CaseSensitive; #ifdef Q_WS_WIN cs = Qt::CaseInsensitive; #endif // if the svg file is in the temp folder, then copy it to destiny if(m_svgFilePath->absolutePath().startsWith(m_tempFolder.absolutePath(),cs)) { QString origFile = svgFilePath(); setFriendlierSvgFileName(partFileName); QString destFile = FolderUtils::getUserDataStorePath("parts")+"/svg/user/"+m_svgFilePath->relativePath(); ensureFilePath(origFile); QFile tempFile(origFile); DebugDialog::debug(QString("copying from %1 to %2") .arg(origFile) .arg(destFile)); tempFile.copy(destFile); tempFile.close(); // update the item info, to point to this file m_svgFilePath->setAbsolutePath(destFile); } } void PartsEditorView::loadFile() { QStringList extras; extras.append(""); extras.append(""); QString imageFiles; if (m_viewIdentifier == ViewLayer::PCBView) { imageFiles = tr("Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5)"); // extras[0] = "*.fp"; extras[1] = "*.mod"; } else { imageFiles = tr("Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5"); } if (m_viewIdentifier == ViewLayer::SchematicView) { extras[0] = "*.lib"; imageFiles = tr("Image & Footprint Files (%1 %2 %3 %4);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;Kicad Schematic Files (%4)%5"); // } QString origPath = FolderUtils::getOpenFileName(this, tr("Open Image"), m_originalSvgFilePath.isEmpty() ? FolderUtils::openSaveFolder() /* FolderUtils::getUserDataStorePath("parts")+"/parts/svg/" */ : m_originalSvgFilePath, imageFiles.arg("*.svg").arg("*.jpg *.jpeg").arg("*.png").arg(extras[0]).arg(extras[1]) ); if(origPath.isEmpty()) { return; // Cancel pressed } if(!origPath.endsWith(".svg")) { try { origPath = createSvgFromImage(origPath); } catch (const QString & msg) { QMessageBox::warning( NULL, tr("Conversion problem"), tr("Unable to load image file: \n%1").arg(msg) ); return; } } if(!origPath.isEmpty()) { if(m_startItem) { m_fixedToCenterItems.removeAll(m_startItem); delete m_startItem; m_startItem = NULL; } m_viewItem = NULL; // loading a new file, so m_viewItem is obsolete loadSvgFile(origPath); } } void PartsEditorView::updateModelPart(const QString& origPath) { m_undoStack->push(new QUndoCommand("Dummy parts editor command")); setSvgFilePath(origPath); copyToTempAndRenameIfNecessary(m_svgFilePath); m_item->setSvgFilePath(m_svgFilePath); ModelPart *mp = createFakeModelPart(m_svgFilePath); m_item->setModelPart(mp); } void PartsEditorView::loadSvgFile(const QString& origPath) { // back to an empty state m_drawnConns.clear(); m_removedConnIds.clear(); m_connsLayerID = ViewLayer::UnknownLayer; m_svgIds.clear(); m_svgLoaded = true; bool canceled = false; beforeSVGLoading(origPath, canceled); if(!canceled) { m_undoStack->push(new QUndoCommand("Dummy parts editor command")); setSvgFilePath(origPath); // TODO: this code reuses the current modelpart and replaces its connectors, // it would be better to delete the modelpart and create a new one // however, one would have to tidy up the various objects that rely on pointers // to the original modelpart and its connectors ModelPart * mp = createFakeModelPart(m_svgFilePath); loadSvgFile(mp); } } void PartsEditorView::beforeSVGLoading(const QString &filename, bool &canceled) { QFile file(filename); if(!file.open(QIODevice::ReadOnly )) { QMessageBox::warning( NULL, tr("Couldn't open svg file"), tr( "The file couldn't be opened. If this file defines its dimensions \n" "in non-real-world units (e.g. pixels), then they won't be translated \n" "into real life ones.\n" "Malformed font-family definitions won't be fixed either.") ); return; } QString fileContent(file.readAll()); bool fileHasChanged = (m_viewIdentifier == ViewLayer::IconView) ? false : TextUtils::fixPixelDimensionsIn(fileContent); fileHasChanged |= TextUtils::cleanSodipodi(fileContent); fileHasChanged |= TextUtils::fixViewboxOrigin(fileContent); fileHasChanged |= TextUtils::tspanRemove(fileContent); fileHasChanged |= fixFonts(fileContent,filename,canceled); if(fileHasChanged) { file.close(); if(!TextUtils::writeUtf8(filename, fileContent)) { QMessageBox::warning( NULL, tr("Couldn't write into file"), tr( "This file needs to be fixed to fit fritzing needs, but it couldn't\n" "be written.\n" "Fritzing is not compatible with this kind of svg files. Please \n" "check your permissions, and try again.\n\n" "More information at http://fritzing.org/using-svg-images-new-parts/" ) ); } } } bool PartsEditorView::fixFonts(QString &fileContent, const QString &filename, bool &canceled) { bool changed = removeFontFamilySingleQuotes(fileContent, filename); changed |= fixUnavailableFontFamilies(fileContent, filename, canceled); return changed; } bool PartsEditorView::removeFontFamilySingleQuotes(QString &fileContent, const QString &filename) { QString pattern = "font-family=\"('.*')\""; QSet wrongFontFamilies = TextUtils::getRegexpCaptures(pattern,fileContent); foreach(QString ff, wrongFontFamilies) { QString wrongFF = ff; QString fixedFF = ff.remove('\''); fileContent.replace(wrongFF,fixedFF); DebugDialog::debug( QString("removing font-family single quotes: \"%1\" to \"%2\" in file '%3'") .arg(wrongFF).arg(fixedFF).arg(filename) ); } return wrongFontFamilies.size() > 0; } bool PartsEditorView::fixUnavailableFontFamilies(QString &fileContent, const QString &filename, bool &canceled) { QSet definedFFs; definedFFs.unite(getAttrFontFamilies(fileContent)); definedFFs.unite(getFontFamiliesInsideStyleTag(fileContent)); FixedFontsHash fixedFonts = FixFontsDialog::fixFonts(this,definedFFs,canceled); if(!canceled) { foreach(QString oldF, fixedFonts.keys()) { QString newF = fixedFonts[oldF]; fileContent.replace(oldF,newF); DebugDialog::debug( QString("replacing font-family: \"%1\" to \"%2\" in file '%3'") .arg(oldF).arg(newF).arg(filename) ); } } return !canceled && fixedFonts.size() > 0; } QSet PartsEditorView::getAttrFontFamilies(const QString &fileContent) { /* * font-family defined as attr example: A0 */ QString pattern = "font-family\\s*=\\s*\"(.|[^\"]*)\\s*\""; return TextUtils::getRegexpCaptures(pattern,fileContent); } QSet PartsEditorView::getFontFamiliesInsideStyleTag(const QString &fileContent) { /* * regexp: font-family\s*:\s*(.|[^;"]*).*" * font-family defined in a style attr example: style="font-size:9;-inkscape-font-specification:Droid Sans;font-family:Droid Sans;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal" style="font-size:144px;font-style:normal;font-weight:normal;line-height:100%;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" x="18.000002" */ QString pattern = "font-family\\s*:\\s*(.|[^;\"]*).*\""; return TextUtils::getRegexpCaptures(pattern,fileContent); } void PartsEditorView::loadSvgFile(ModelPart * modelPart) { addItemInPartsEditor(modelPart, m_svgFilePath); copyToTempAndRenameIfNecessary(m_svgFilePath); m_item->setSvgFilePath(m_svgFilePath); } void PartsEditorView::loadFromModel(PaletteModel *paletteModel, ModelPart * modelPart) { clearScene(); ViewGeometry viewGeometry; this->setPaletteModel(paletteModel); m_item = (PartsEditorPaletteItem*) addItemAux(modelPart, defaultViewLayerSpec(), viewGeometry, ItemBase::getNextID(), NULL, true, m_viewIdentifier, true); fitCenterAndDeselect(); setItemProperties(); if(m_item) { if(m_startItem) { m_fixedToCenterItems.removeAll(m_startItem); delete m_startItem; m_startItem = NULL; } SvgAndPartFilePath *sp = m_item->svgFilePath(); copyToTempAndRenameIfNecessary(sp); m_item->setSvgFilePath(m_svgFilePath); } } void PartsEditorView::copyToTempAndRenameIfNecessary(SvgAndPartFilePath *filePathOrig) { m_originalSvgFilePath = filePathOrig->absolutePath(); QString userSvgFolderPath = FolderUtils::getUserDataStorePath("parts")+"/svg"; QString coreSvgFolderPath = FolderUtils::getApplicationSubFolderPath("parts")+"/svg"; QString pfSvgFolderPath = PartFactory::folderPath()+"/svg"; if(!(filePathOrig->absolutePath().startsWith(userSvgFolderPath) || filePathOrig->absolutePath().startsWith(coreSvgFolderPath) || filePathOrig->absolutePath().startsWith(pfSvgFolderPath)) ) { // it's outside the parts folder DebugDialog::debug(QString("copying from %1").arg(m_originalSvgFilePath)); QString viewFolder = ViewLayer::viewIdentifierNaturalName(m_viewIdentifier); if(!QFileInfo(m_tempFolder.path()+"/"+viewFolder).exists() && !m_tempFolder.mkdir(viewFolder)) return; if(!m_tempFolder.cd(viewFolder)) return; QString destFilePath = FolderUtils::getRandText()+".svg"; DebugDialog::debug(QString("dest file: %1").arg(m_tempFolder.absolutePath()+"/"+destFilePath)); ensureFilePath(m_tempFolder.absolutePath()+"/"+destFilePath); QFile tempFile(m_originalSvgFilePath); tempFile.copy(m_tempFolder.absolutePath()+"/"+destFilePath); tempFile.close(); if(!m_tempFolder.cd("..")) return; // out of view folder m_svgFilePath->setRelativePath(viewFolder+"/"+destFilePath); m_svgFilePath->setAbsolutePath(m_tempFolder.absolutePath()+"/"+m_svgFilePath->relativePath()); } else { QString relPathAux = filePathOrig->relativePath(); m_svgFilePath->setAbsolutePath(m_originalSvgFilePath); if (relPathAux.count("/") > 2) { throw "PartsEditorView::copyToTempAndRenameIfNecessary bad path"; } if(relPathAux.count("/") == 2) { // this means that core/user/contrib is still in the file name m_svgFilePath->setRelativePath( relPathAux.right(// remove user/core/contrib relPathAux.size() - relPathAux.indexOf("/") - 1 ) ); } else { //otherwise, just leave it as it is m_svgFilePath->setRelativePath(relPathAux); } } } void PartsEditorView::setSvgFilePath(const QString &filePath) { ensureFilePath(filePath); m_originalSvgFilePath = filePath; QString userSvgFolder = FolderUtils::getUserDataStorePath("parts")+"/svg"; QString coreSvgFolder = FolderUtils::getApplicationSubFolderPath("parts")+"/svg"; QString pfSvgFolder = PartFactory::folderPath()+"/svg"; QString tempFolder = m_tempFolder.absolutePath(); QString relative; Qt::CaseSensitivity cs = Qt::CaseSensitive; QString filePathAux = filePath; #ifdef Q_WS_WIN // seems to be necessary for Windows: getUserDataStorePath() returns a string starting with "c:" // but the file dialog returns a string beginning with "C:" cs = Qt::CaseInsensitive; #endif if(filePath.contains(userSvgFolder, cs) || filePath.contains(coreSvgFolder, cs) || filePath.contains(pfSvgFolder, cs)) { int ix = filePath.indexOf("svg"); // is core/user file relative = filePathAux.remove(0, ix + 4); //Mariano: I don't like this folder thing anymore relative = relative.mid(filePathAux.indexOf("/")+1); // remove core/user/contrib } else { // generated jpeg/png or file outside fritzing folder relative = ""; } if (m_svgFilePath) delete m_svgFilePath; m_svgFilePath = new SvgAndPartFilePath(filePath,relative); } const QString PartsEditorView::svgFilePath() { return m_svgFilePath->absolutePath(); } const SvgAndPartFilePath& PartsEditorView::svgFileSplit() { return *m_svgFilePath; } QString PartsEditorView::createSvgFromImage(const QString &origFilePath) { QString viewFolder = getOrCreateViewFolderInTemp(); QString newFilePath = m_tempFolder.absolutePath()+"/"+viewFolder+"/"+FolderUtils::getRandText()+".svg"; ensureFilePath(newFilePath); if (origFilePath.endsWith(".fp")) { // this is a geda footprint file GedaElement2Svg geda; QString svg = geda.convert(origFilePath, false); return saveSvg(svg, newFilePath); } if (origFilePath.endsWith(".lib")) { // Kicad schematic library file QStringList defs = KicadSchematic2Svg::listDefs(origFilePath); if (defs.count() == 0) { throw tr("no schematics found in %1").arg(origFilePath); } QString def; if (defs.count() > 1) { KicadModuleDialog kmd(tr("schematic part"), origFilePath, defs, this); int result = kmd.exec(); if (result != QDialog::Accepted) { return ""; } def = kmd.selectedModule(); } else { def = defs.at(0); } KicadSchematic2Svg kicad; QString svg = kicad.convert(origFilePath, def); return saveSvg(svg, newFilePath); } if (origFilePath.endsWith(".mod")) { // Kicad footprint (Module) library file QStringList modules = KicadModule2Svg::listModules(origFilePath); if (modules.count() == 0) { throw tr("no footprints found in %1").arg(origFilePath); } QString module; if (modules.count() > 1) { KicadModuleDialog kmd("footprint", origFilePath, modules, this); int result = kmd.exec(); if (result != QDialog::Accepted) { return ""; } module = kmd.selectedModule(); } else { module = modules.at(0); } KicadModule2Svg kicad; QString svg = kicad.convert(origFilePath, module, false); return saveSvg(svg, newFilePath); } // deal with png, jpg, etc.: /* %1=witdh in mm * %2=height in mm * %3=width in local coords * %4=height in local coords * %5=binary data */ /* QString svgTemplate = "\n" " \n" " \n" " \n" " \n" " "; QPixmap pixmap(origFilePath); QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer,"png"); // writes pixmap into bytes in PNG format QString svgDom = svgTemplate .arg(pixmap.widthMM()).arg(pixmap.heightMM()) .arg(pixmap.width()).arg(pixmap.height()) .arg(QString("data:image/png;base64,%2").arg(QString(bytes.toBase64()))); QFile destFile(newFilePath); if(!destFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::information(NULL, "", "file not created"); if(!destFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::information(NULL, "", "file not created 2"); } } QTextStream out(&destFile); out << svgDom; destFile.close(); qDebug() << newFilePath; bool existsResult = QFileInfo(newFilePath).exists(); Q_ASSERT(existsResult); */ QImage img(origFilePath); QSvgGenerator svgGenerator; svgGenerator.setResolution(90); svgGenerator.setFileName(newFilePath); QSize sz = img.size(); svgGenerator.setSize(sz); svgGenerator.setViewBox(QRect(0, 0, sz.width(), sz.height())); QPainter svgPainter(&svgGenerator); svgPainter.drawImage(QPoint(0,0), img); svgPainter.end(); return newFilePath; } QString PartsEditorView::setFriendlierSvgFileName(const QString &partFileName) { QString aux = partFileName; aux = aux .remove(FritzingPartExtension) .replace(" ","_"); if(aux.length()>40) aux.truncate(40); aux+=QString("__%1__%2.svg") .arg(ViewLayer::viewIdentifierNaturalName(m_viewIdentifier)) .arg(FolderUtils::getRandText()); int slashIdx = m_svgFilePath->relativePath().indexOf("/"); QString relpath = m_svgFilePath->relativePath(); QString relpath2 = relpath; QString abspath = m_svgFilePath->absolutePath(); QString viewFolder = relpath.remove(slashIdx,relpath.size()-slashIdx+1); m_svgFilePath->setAbsolutePath(abspath.remove(relpath2)+viewFolder+"/"+aux); m_svgFilePath->setRelativePath(viewFolder+"/"+aux); return aux; } // conns void PartsEditorView::wheelEvent(QWheelEvent* event) { if(m_showingTerminalPoints) { if(!m_terminalPointsTimer->isActive()) { m_showingTerminalPointsBackup = m_showingTerminalPoints; showTerminalPoints(false); m_terminalPointsTimer->start(50); } } else if(m_terminalPointsTimer->isActive()) { m_terminalPointsTimer->stop(); m_terminalPointsTimer->start(50); } SketchWidget::wheelEvent(event); } void PartsEditorView::mousePressEvent(QMouseEvent *event) { SketchWidget::mousePressEvent(event); } void PartsEditorView::mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); } void PartsEditorView::mouseReleaseEvent(QMouseEvent *event) { SketchWidget::mouseReleaseEvent(event); } void PartsEditorView::resizeEvent(QResizeEvent * event) { SketchWidget::resizeEvent(event); if(m_fitItemInViewTimer->isActive()) { m_fitItemInViewTimer->stop(); } m_fitItemInViewTimer->start(); } void PartsEditorView::drawConector(Connector *conn, bool showTerminalPoint) { QSize size(ConnDefaultWidth,ConnDefaultHeight); createConnector(conn,size,showTerminalPoint); } void PartsEditorView::createConnector(Connector *conn, const QSize &connSize, bool showTerminalPoint) { QString connId = conn->connectorSharedID(); QRectF bounds = m_item ? QRectF(m_item->boundingRect().center(),connSize) : QRectF(scene()->itemsBoundingRect().center(),connSize); PartsEditorConnectorsConnectorItem *connItem = new PartsEditorConnectorsConnectorItem(conn, m_item, m_showingTerminalPoints, bounds); m_drawnConns[connId] = connItem; connItem->setShowTerminalPoint(showTerminalPoint); m_undoStack->push(new QUndoCommand( QString("connector '%1' added to %2 view") .arg(connId).arg(ViewLayer::viewIdentifierName(m_viewIdentifier)) )); } void PartsEditorView::removeConnector(const QString &connId) { ConnectorItem *connToRemove = NULL; foreach(QGraphicsItem *item, items()) { ConnectorItem *connItem = dynamic_cast(item); if(connItem && connItem->connector()->connectorSharedID() == connId) { connToRemove = connItem; break; } } if(connToRemove) { scene()->removeItem(connToRemove); scene()->update(); m_undoStack->push(new QUndoCommand( QString("connector '%1' removed from %2 view") .arg(connId).arg(ViewLayer::viewIdentifierName(m_viewIdentifier)) )); PartsEditorConnectorsConnectorItem *connToRemoveAux = dynamic_cast(connToRemove); m_drawnConns.remove(connToRemoveAux->connectorSharedID()); m_removedConnIds << connId; } } void PartsEditorView::setItemProperties() { if(m_item) { m_item->setFlag(QGraphicsItem::ItemIsSelectable, false); m_item->setFlag(QGraphicsItem::ItemIsMovable, false); m_item->setFlag(QGraphicsItem::ItemClipsToShape, true); //m_item->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); myItem()->highlightConnectors(m_lastSelectedConnId); double size = 500; // just make sure the user get enough space to play setSceneRect(0,0,size,size); m_item->setPos((size-m_item->size().width())/2,(size-m_item->size().height())/2); centerOn(m_item); } //ensureFixedToBottomRight(m_zoomControls); } void PartsEditorView::informConnectorSelection(const QString &connId) { if(m_item) { m_lastSelectedConnId = connId; myItem()->highlightConnectors(connId); } } void PartsEditorView::informConnectorSelectionFromView(const QString &connId) { informConnectorSelection(connId); emit connectorSelected(connId); } void PartsEditorView::setMismatching(ViewLayer::ViewIdentifier viewId, const QString &id, bool mismatching) { if(m_item && viewId == m_viewIdentifier) { for (int i = 0; i < m_item->childItems().count(); i++) { PartsEditorConnectorsConnectorItem * connectorItem = dynamic_cast(m_item->childItems()[i]); if(connectorItem == NULL) continue; if(connectorItem->connector()->connectorSharedID() == id) { connectorItem->setMismatching(mismatching); } } } } void PartsEditorView::aboutToSave(bool fakeDefaultIfNone) { if(m_item) { FSvgRenderer renderer; QByteArray bytes = renderer.loadSvg(m_item->flatSvgFilePath()); if (!bytes.isEmpty()) { QRectF svgViewBox = renderer.viewBoxF(); QSizeF sceneViewBox = renderer.defaultSizeF(); QDomDocument *svgDom = m_item->svgDom(); // this may change the layers defined in the file, so // let's get the connectorsLayer after it bool somethingChanged = addDefaultLayerIfNotInSvg(svgDom, fakeDefaultIfNone); QDomElement elem = svgDom->documentElement(); somethingChanged |= removeConnectorsIfNeeded(elem); QStringList connectorsLayerIds = findConnectorsLayerIds(svgDom); foreach (QString connectorsLayerId, connectorsLayerIds) { somethingChanged |= updateTerminalPoints(svgDom, sceneViewBox, svgViewBox, connectorsLayerId); somethingChanged |= addConnectorsIfNeeded(svgDom, sceneViewBox, svgViewBox, connectorsLayerId); } somethingChanged |= (m_viewItem != NULL); if(somethingChanged) { QString viewFolder = getOrCreateViewFolderInTemp(); QString tempFile = m_tempFolder.absolutePath()+"/"+viewFolder+"/"+FolderUtils::getRandText()+".svg"; ensureFilePath(tempFile); if(!TextUtils::writeUtf8(tempFile, TextUtils::removeXMLEntities(svgDom->toString()))) { /*QMessageBox::information(NULL,"", QString("Couldn't open file for update, after drawing connectors: '%1'") .arg(tempFile) );*/ DebugDialog::debug(QString("Couldn't open file for update, after drawing connectors: '%1'").arg(tempFile)); } } } else { DebugDialog::debug("updating part view svg file: could not load file "+m_item->flatSvgFilePath()); } } } bool PartsEditorView::addConnectorsIfNeeded(QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId) { bool changed = false; if(!m_drawnConns.isEmpty()) { QRectF bounds; QString connId; foreach(PartsEditorConnectorsConnectorItem* drawnConn, m_drawnConns.values()) { bounds = drawnConn->mappedRect(); connId = drawnConn->connector()->connectorSharedID(); QRectF svgRect = mapFromSceneToSvg(bounds,sceneViewBox,svgViewBox); QString svgId = svgIdForConnector(drawnConn->connector(), connId); addRectToSvg(svgDom,svgId,svgRect, connectorsLayerId); } changed = true; } return changed; } bool PartsEditorView::addDefaultLayerIfNotInSvg(QDomDocument *svgDom, bool fakeDefaultIfNone) { QStringList defaultLayers = defaultLayerAsStringlist(); QStringList layers = getLayers(svgDom, fakeDefaultIfNone); foreach (QString defaultLayer, defaultLayers) { if (layers.contains(defaultLayer)) return false; } // jrc 4/7/2010: not sure if making a new top level layer is correct // since it could swallow other layers QDomElement docElem = svgDom->documentElement(); QDomElement newTopLevel = svgDom->createElement("g"); newTopLevel.setAttribute("id", defaultLayers.at(0)); // place the child in a aux list, cause the // qdomnodelist takes care of the references QList children; for(QDomNode child=docElem.firstChild(); !child.isNull(); child=child.nextSibling()) { children << child; } foreach(QDomNode child, children) { newTopLevel.appendChild(child); } docElem.appendChild(newTopLevel); return true; } LayerList PartsEditorView::defaultLayers() { LayerList layers; switch( m_viewIdentifier ) { case ViewLayer::IconView: layers << ViewLayer::Icon; break; case ViewLayer::BreadboardView: layers << ViewLayer::Breadboard; break; case ViewLayer::SchematicView: layers << ViewLayer::Schematic; break; case ViewLayer::PCBView: layers << ViewLayer::Copper0 << ViewLayer::Copper1; break; default: layers << ViewLayer::UnknownLayer; break; } return layers; } QStringList PartsEditorView::defaultLayerAsStringlist() { QStringList layers; foreach (ViewLayer::ViewLayerID viewLayerID, defaultLayers()) { layers << ViewLayer::viewLayerXmlNameFromID(viewLayerID); } return layers; } QString PartsEditorView::svgIdForConnector(const QString &connId) { //Q_ASSERT(m_item) if (m_item == NULL) return connId; QString result = ""; QDomElement elem = m_item->svgDom()->documentElement(); if(terminalIdForConnectorIdAux(result, connId, elem, false)) { return result; } /* foreach(Connector* conn, m_item->connectors()) { QString svgId = svgIdForConnector(conn, connId); if(connId != svgId) { return svgId; } } */ return connId; } QString PartsEditorView::svgIdForConnector(Connector* conn, const QString &connId) { if (conn->connectorShared() && conn->connectorSharedID() == connId) { foreach(SvgIdLayer *sil, conn->connectorShared()->pins().values(m_viewIdentifier)) { return sil->m_svgId; } } return connId; } bool PartsEditorView::updateTerminalPoints(QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId) { QList connsWithNewTPs; QStringList tpIdsToRemove; foreach(QGraphicsItem *item, items()) { PartsEditorConnectorsConnectorItem *citem = dynamic_cast(item); if(citem) { TerminalPointItem *tp = citem->terminalPointItem(); if (!tp) { citem->setShowTerminalPoint(citem->isShowingTerminalPoint()); tp = citem->terminalPointItem(); } QString connId = citem->connector()->connectorSharedID(); QString terminalId = connId+"terminal"; if(tp && !tp->isInTheCenter()) { if(tp->hasBeenMoved() || citem->hasBeenMoved()) { connsWithNewTPs << citem; tpIdsToRemove << terminalId; //DebugDialog::debug("<<<< MOVED! removing terminal "+terminalId+" in view: "+ViewLayer::viewIdentifierName(m_viewIdentifier)); updateSvgIdLayer(connId, terminalId, connectorsLayerId); } } else { //DebugDialog::debug("<<<< removing terminal "+terminalId+" in view: "+ViewLayer::viewIdentifierName(m_viewIdentifier)); tpIdsToRemove << terminalId; emit removeTerminalPoint(connId, m_viewIdentifier); } } } QDomElement elem = svgDom->documentElement(); removeTerminalPoints(tpIdsToRemove,elem); addNewTerminalPoints(connsWithNewTPs, svgDom, sceneViewBox, svgViewBox, connectorsLayerId); return !tpIdsToRemove.isEmpty(); } void PartsEditorView::updateSvgIdLayer(const QString &connId, const QString &terminalId, const QString &connectorsLayerId) { ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(connectorsLayerId); foreach(Connector *conn, m_item->connectors()) { foreach(SvgIdLayer *sil, conn->connectorShared()->pins().values(m_viewIdentifier)) { if(conn->connectorSharedID() == connId) { if (sil->m_svgViewLayerID == viewLayerID) { sil->m_terminalId = terminalId; return; } } } foreach(SvgIdLayer *sil, conn->connectorShared()->pins().values(m_viewIdentifier)) { if(conn->connectorSharedID() == connId) { sil->m_terminalId = terminalId; if(viewLayerID != ViewLayer::UnknownLayer) { sil->m_svgViewLayerID = viewLayerID; } } } } } void PartsEditorView::removeTerminalPoints(const QStringList &tpIdsToRemove, QDomElement &docElem) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { bool doRemove = false; QString id = e.attribute("id"); if(tpIdsToRemove.contains(id)) { doRemove = true; } else if(e.hasChildNodes()) { removeTerminalPoints(tpIdsToRemove,e); } QDomElement e2; if(doRemove) { e2 = e; } e = e.nextSiblingElement(); if(doRemove) { e2.removeAttribute("id"); } } } void PartsEditorView::addNewTerminalPoints( const QList &connsWithNewTPs, QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId ) { foreach(PartsEditorConnectorsConnectorItem* citem, connsWithNewTPs) { QString connId = citem->connector()->connectorSharedID(); TerminalPointItem *tp = citem->terminalPointItem(); if (tp == NULL) { throw "PartsEditorView::addNewTerminalPoints tp missing"; } if(tp) { QRectF tpointRect(tp->mappedPoint(), QPointF(0,0)); QRectF svgTpRect = mapFromSceneToSvg(tpointRect,sceneViewBox,svgViewBox); double halfTPSize = 0.001; // a tiny rectangle svgTpRect.setSize(QSizeF(halfTPSize*2,halfTPSize*2)); addRectToSvg(svgDom,connId+"terminal",svgTpRect, connectorsLayerId); } else { qWarning() << tr( "Parts Editor: couldn't save terminal " "point for connector %1 in %2 view") .arg(citem->connector()->connectorSharedID()) .arg(ViewLayer::viewIdentifierNaturalName(m_viewIdentifier)); } } } bool PartsEditorView::removeConnectorsIfNeeded(QDomElement &docElem) { if(!m_removedConnIds.isEmpty()) { //Q_ASSERT(docElem.tagName() == "svg"); QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if(isSupposedToBeRemoved(id)) { e.removeAttribute("id"); } else if(e.hasChildNodes()) { removeConnectorsIfNeeded(e); } e = e.nextSiblingElement(); } return true; } return false; } QRectF PartsEditorView::mapFromSceneToSvg(const QRectF &itemRect, const QSizeF &sceneViewBox, const QRectF &svgViewBox) { double relationW = svgViewBox.width() / sceneViewBox.width(); double relationH = svgViewBox.height() / sceneViewBox.height(); double x = itemRect.x() * relationW; double y = itemRect.y() * relationH; double width = itemRect.width() * relationW; double height = itemRect.height() * relationH; return QRectF(x,y,width,height); } bool PartsEditorView::addRectToSvg(QDomDocument* svgDom, const QString &id, const QRectF &rect, const QString &connectorsLayerId) { QDomElement connElem = svgDom->createElement("rect"); connElem.setAttribute("id",id); connElem.setAttribute("x",rect.x()); connElem.setAttribute("y",rect.y()); connElem.setAttribute("width",rect.width()); connElem.setAttribute("height",rect.height()); connElem.setAttribute("fill","none"); if(connectorsLayerId.isEmpty()) { svgDom->firstChildElement("svg").appendChild(connElem); return true; } else { QDomElement docElem = svgDom->documentElement(); return addRectToSvgAux(docElem, connectorsLayerId, connElem); } } bool PartsEditorView::addRectToSvgAux(QDomElement &docElem, const QString &connectorsLayerId, QDomElement &rectElem) { QDomElement e = docElem.firstChildElement(); while(!e.isNull()) { QString id = e.attribute("id"); if(id == connectorsLayerId) { e.appendChild(rectElem); return true; } else if(e.hasChildNodes()) { if(addRectToSvgAux(e, connectorsLayerId, rectElem)) { return true; } } e = e.nextSiblingElement(); } return false; } bool PartsEditorView::isSupposedToBeRemoved(const QString& id) { if (id.isEmpty()) return false; // TODO: m_removedConnIds should be svg ids and not connectorSharedIDs (from fzp) foreach(QString toBeRemoved, m_removedConnIds) { if(id.startsWith(toBeRemoved)) { QString temp = id; temp = temp.remove(0, toBeRemoved.length()); if (temp.length() == 0) return true; // assumes svg id is always prefixDsuffix where D is some string of decimal digits // and prefixD matches toBeRemoved if (!temp.at(0).isDigit()) { return true; } } } return false; } PartsEditorConnectorsPaletteItem *PartsEditorView::myItem() { return dynamic_cast(m_item.data()); } void PartsEditorView::showTerminalPoints(bool show) { m_showingTerminalPoints = show; foreach(QGraphicsItem *item, items()) { PartsEditorConnectorsConnectorItem *connItem = dynamic_cast(item); if(connItem) { connItem->setShowTerminalPoint(show); } } scene()->update(); /*if(!m_showingTerminalPoints) { m_terminalPointsTimer->stop(); }*/ } bool PartsEditorView::showingTerminalPoints() { return m_showingTerminalPoints; } void PartsEditorView::inFileDefinedConnectorChanged(PartsEditorConnectorsConnectorItem *connItem) { QString connId = connItem->connectorSharedID(); m_drawnConns[connId] = connItem; if(!m_removedConnIds.contains(connId)) { m_removedConnIds << connId; } } void PartsEditorView::addFixedToBottomRight(QWidget *widget) { m_fixedWidgets << widget; QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(); proxy->setWidget(widget); addFixedToBottomRightItem(proxy); } bool PartsEditorView::imageLoaded() { return m_item != NULL; } void PartsEditorView::drawBackground(QPainter *painter, const QRectF &rect) { SketchWidget::drawBackground(painter,rect); // 10mm spacing grid /*const int gridSize = 10*width()/widthMM(); QRectF itemRect = m_item->mapToScene(m_item->boundingRect()).boundingRect(); painter->drawRect(itemRect); double itemTop = itemRect.top(); double itemLeft = itemRect.left(); QVarLengthArray lines; for (double x = itemLeft; x < rect.right(); x += gridSize) { lines.append(QLineF(x, rect.top(), x, rect.bottom())); } for (double x = itemLeft-gridSize; x > rect.left(); x -= gridSize) { lines.append(QLineF(x, rect.top(), x, rect.bottom())); } for (double y = itemTop; y < rect.bottom(); y += gridSize) { lines.append(QLineF(rect.left(), y, rect.right(), y)); } for (double y = itemTop-gridSize; y > rect.top(); y -= gridSize) { lines.append(QLineF(rect.left(), y, rect.right(), y)); } painter->drawLines(lines.data(), lines.size());*/ } void PartsEditorView::recoverTerminalPointsState() { showTerminalPoints(m_showingTerminalPointsBackup); m_terminalPointsTimer->stop(); } bool PartsEditorView::connsPosOrSizeChanged() { foreach(QGraphicsItem *item, items()) { PartsEditorConnectorsConnectorItem *citem = dynamic_cast(item); if(citem) { TerminalPointItem *tp = citem->terminalPointItem(); if((tp && tp->hasBeenMoved()) || citem->hasBeenMoved() || citem->hasBeenResized()) { return true; } } } return false; } void PartsEditorView::setViewItem(ItemBase * item) { m_viewItem = item; } void PartsEditorView::checkConnectorLayers(ViewLayer::ViewIdentifier viewIdentifier, const QString & connId, Connector* existingConnector, Connector * newConnector) { if (m_viewIdentifier != viewIdentifier) return; Q_UNUSED(connId); QList newpins = newConnector->connectorShared()->pins().values(viewIdentifier); QList oldpins = existingConnector->connectorShared()->pins().values(viewIdentifier); LayerList layerList; QList changes; foreach (SvgIdLayer * newSvgIdLayer, newpins) { bool gotOne = false; layerList << newSvgIdLayer->m_svgViewLayerID; foreach (SvgIdLayer * oldSvgIdLayer, oldpins) { if (newSvgIdLayer->m_svgViewLayerID == oldSvgIdLayer->m_svgViewLayerID) { gotOne = true; break; } } if (!gotOne) { changes << newSvgIdLayer; } } foreach (SvgIdLayer * svgIdLayer, changes) { SvgIdLayer * cpy = svgIdLayer->copyLayer(); existingConnector->connectorShared()->insertPin(viewIdentifier, cpy); } changes.clear(); foreach (SvgIdLayer * oldSvgIdLayer, oldpins) { bool gotOne = false; foreach (SvgIdLayer * newSvgIdLayer, newpins) { if (newSvgIdLayer->m_svgViewLayerID == oldSvgIdLayer->m_svgViewLayerID) { gotOne = true; break; } } if (!gotOne) { changes << oldSvgIdLayer; } } foreach (SvgIdLayer * svgIdLayer, changes) { existingConnector->connectorShared()->removePin(viewIdentifier, svgIdLayer); } } void PartsEditorView::updatePinsInfo(QList< QPointer > connsShared) { if(!m_svgLoaded) return; // if the user has not changed the svg file, there's nothing to update ViewLayer::ViewLayerID layerID = connectorsLayerId(); QList notFound; foreach(ConnectorShared* cs, connsShared) { QString connId = cs->id(); SvgIdLayer* pinInfo = cs->fullPinInfo(m_viewIdentifier, layerID); if (pinInfo == NULL) { notFound << cs; } else if(!m_svgIds[connId].connectorId.isEmpty()) { pinInfo->m_svgId = m_svgIds[connId].connectorId; // terminal points are already updated (by the function updateTerminalPoints) // pinInfo->m_terminalId = m_svgIds[connId].terminalId; } } if (notFound.length() == 0) return; // not sure this is the right place to handle the change of connector layers... LayerList alts = ViewLayer::findAlternativeLayers(layerID); if (alts.length() == 0) return; foreach (ViewLayer::ViewLayerID vlid, alts) { QList found; foreach(ConnectorShared* cs, notFound) { QString connId = cs->id(); SvgIdLayer* pinInfo = cs->fullPinInfo(m_viewIdentifier, vlid); if (pinInfo != NULL && !m_svgIds[connId].connectorId.isEmpty()) { pinInfo->m_svgId = m_svgIds[connId].connectorId; pinInfo->m_svgViewLayerID = layerID; found << cs; } } foreach (ConnectorShared * cs, found) { notFound.removeOne(cs); } } } QString PartsEditorView::saveSvg(const QString & svg, const QString & newFilePath) { if (!TextUtils::writeUtf8(newFilePath, svg)) { throw tr("unable to open temp file %1").arg(newFilePath); } return newFilePath; } void PartsEditorView::clearFixedItems() { m_fixedToBottomLeftItems.clear(); m_fixedToBottomRightItems.clear(); m_fixedToCenterItems.clear(); m_fixedToTopLeftItems.clear(); m_fixedToTopRightItems.clear(); } void PartsEditorView::ensureFixedItemsPositions() { //DebugDialog::debug("ensure fixed items positions"); ensureFixedToBottomLeftItems(); ensureFixedToCenterItems(); ensureFixedToTopLeftItems(); ensureFixedToTopRightItems(); ensureFixedToBottomRightItems(); scene()->update(sceneRect()); } void PartsEditorView::addFixedToTopLeftItem(QGraphicsItem *item) { item->setFlag(QGraphicsItem::ItemIgnoresTransformations); if(!scene()->items().contains(item)) { scene()->addItem(item); } m_fixedToTopLeftItems << item; ensureFixedToTopLeft(item); } void PartsEditorView::addFixedToTopRightItem(QGraphicsItem *item) { item->setFlag(QGraphicsItem::ItemIgnoresTransformations); if(!scene()->items().contains(item)) { scene()->addItem(item); } m_fixedToTopRightItems << item; ensureFixedToTopRight(item); } void PartsEditorView::addFixedToBottomLeftItem(QGraphicsItem *item) { item->setFlag(QGraphicsItem::ItemIgnoresTransformations); if(!scene()->items().contains(item)) { scene()->addItem(item); } m_fixedToBottomLeftItems << item; ensureFixedToBottomLeft(item); } void PartsEditorView::addFixedToBottomRightItem(QGraphicsItem *item) { item->setFlag(QGraphicsItem::ItemIgnoresTransformations); if(!scene()->items().contains(item)) { scene()->addItem(item); } m_fixedToBottomRightItems << item; ensureFixedToBottomRight(item); } void PartsEditorView::addFixedToCenterItem(QGraphicsItem *item) { item->setFlag(QGraphicsItem::ItemIgnoresTransformations); if(!scene()->items().contains(item)) { scene()->addItem(item); } m_fixedToCenterItems << item; ensureFixedToCenter(item); } void PartsEditorView::ensureFixedToTopLeftItems() { if(isVisible()) { QList toRemove; foreach(QGraphicsItem* item, m_fixedToTopLeftItems) { if(scene()->items().contains(item)) { ensureFixedToTopLeft(item); } else { toRemove << item; } } foreach(QGraphicsItem* item, toRemove) { m_fixedToTopLeftItems.removeAll(item); } } } void PartsEditorView::ensureFixedToTopLeft(QGraphicsItem* item) { item->setPos(mapToScene(0,0)); } void PartsEditorView::ensureFixedToTopRightItems() { if(isVisible()) { QList toRemove; foreach(QGraphicsItem* item, m_fixedToTopRightItems) { if(scene()->items().contains(item)) { ensureFixedToTopRight(item); } else { toRemove << item; } } foreach(QGraphicsItem* item, toRemove) { m_fixedToTopRightItems.removeAll(item); } } } void PartsEditorView::ensureFixedToTopRight(QGraphicsItem* item) { int x = (int) (width()-fixedItemWidth(item)); int y = 0; item->setPos(mapToScene(x,y)); } void PartsEditorView::ensureFixedToBottomLeftItems() { if(isVisible()) { QList toRemove; foreach(QGraphicsItem* item, m_fixedToBottomLeftItems) { if(scene()->items().contains(item)) { ensureFixedToBottomLeft(item); } else { toRemove << item; } } foreach(QGraphicsItem* item, toRemove) { m_fixedToBottomLeftItems.removeAll(item); } } } void PartsEditorView::ensureFixedToBottomLeft(QGraphicsItem* item) { int x = 0; int y = (int) (height()-fixedItemHeight(item)); item->setPos(mapToScene(x,y)); } void PartsEditorView::ensureFixedToBottomRightItems() { if(isVisible()) { QList toRemove; foreach(QGraphicsItem* item, m_fixedToBottomRightItems) { if(scene()->items().contains(item)) { ensureFixedToBottomRight(item); } else { toRemove << item; } } foreach(QGraphicsItem* item, toRemove) { m_fixedToBottomRightItems.removeAll(item); } } } void PartsEditorView::ensureFixedToBottomRight(QGraphicsItem* item) { int x = (int) (width()-fixedItemWidth(item)); int y = (int) (height()-fixedItemHeight(item)); item->setPos(mapToScene(x,y)); } void PartsEditorView::ensureFixedToCenterItems() { if(isVisible()) { QList toRemove; foreach(QGraphicsItem* item, m_fixedToCenterItems) { if(scene()->items().contains(item)) { ensureFixedToCenter(item); } else { toRemove << item; } } foreach(QGraphicsItem* item, toRemove) { m_fixedToCenterItems.removeAll(item); } } } void PartsEditorView::ensureFixedToCenter(QGraphicsItem* item) { double x = (width()-fixedItemWidth(item))/2; double y = (height()-fixedItemHeight(item))/2; QPointF pos = mapToScene(x,y); if(pos.x() < scene()->width() && pos.y() < scene()->height()) { item->setPos(pos); } } void PartsEditorView::removeIfFixedPos(QGraphicsItem *item) { m_fixedToBottomLeftItems.removeAll(item); m_fixedToBottomRightItems.removeAll(item); m_fixedToCenterItems.removeAll(item); m_fixedToTopLeftItems.removeAll(item); m_fixedToTopRightItems.removeAll(item); } double PartsEditorView::fixedItemWidth(QGraphicsItem* item) { QGraphicsProxyWidget* gWidget = dynamic_cast(item); if(gWidget) { return gWidget->widget()->width(); } else { return item->boundingRect().width(); } } double PartsEditorView::fixedItemHeight(QGraphicsItem* item) { QGraphicsProxyWidget* gWidget = dynamic_cast(item); if(gWidget) { return gWidget->widget()->height(); } else { return item->boundingRect().height(); } } void PartsEditorView::deleteItem(ItemBase * itemBase, bool deleteModelPart, bool doEmit, bool later) { removeIfFixedPos(itemBase); SketchWidget::deleteItem(itemBase, deleteModelPart, doEmit, later); } void PartsEditorView::setPaletteModel(PaletteModel * paletteModel) { m_paletteModel = paletteModel; } fritzing-app-0.9.2b/src/partseditor/obsolete/partseditorview.h000066400000000000000000000241131250202676700246550ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSEDITORVIEW_H_ #define PARTSEDITORVIEW_H_ #include "../sketch/sketchwidget.h" #include "../model/palettemodel.h" #include "partseditorpaletteitem.h" #include "partseditorconnectorspaletteitem.h" #include "partseditorconnectorsconnectoritem.h" #include #include #include struct ConnectorTerminalSvgIdPair { ConnectorTerminalSvgIdPair() { } QString connectorId; QString terminalId; QString connectorName; }; class PartsEditorView : public SketchWidget { Q_OBJECT public: PartsEditorView( ViewLayer::ViewIdentifier, QDir tempDir, bool showingTerminalPoints, QGraphicsProxyWidget *startItem=0, QWidget *parent=0, int size=150, bool deleteModelPartOnClearScene=false, class ItemBase * fromItem = NULL); ~PartsEditorView(); // general QDir tempFolder(); bool isEmpty(); ViewLayer::ViewLayerID connectorsLayerId(); QString terminalIdForConnector(const QString &connId); void addFixedToBottomRight(QWidget *widget); bool imageLoaded(); // specs void loadSvgFile(ModelPart * modelPart); void copySvgFileToDestiny(const QString &partFileName); const QString svgFilePath(); const SvgAndPartFilePath& svgFileSplit(); // conns void drawConector(Connector *conn, bool showTerminalPoint); void removeConnector(const QString &connId); void inFileDefinedConnectorChanged(PartsEditorConnectorsConnectorItem *connItem); void aboutToSave(bool fakeDefaultIfNotIn); void updatePinsInfo(QList< QPointer > conns); void showTerminalPoints(bool show); bool showingTerminalPoints(); QString svgIdForConnector(const QString &connId); PartsEditorConnectorsPaletteItem *myItem(); bool connsPosOrSizeChanged(); void setViewItem(ItemBase *); void setPaletteModel(PaletteModel *); public slots: // general void loadFromModel(PaletteModel *paletteModel, ModelPart * modelPart); void addItemInPartsEditor(ModelPart * modelPart, SvgAndPartFilePath * svgFilePath); // specs void loadFile(); void loadSvgFile(const QString& origPath); void updateModelPart(const QString& origPath); // conns void informConnectorSelection(const QString& connId); void informConnectorSelectionFromView(const QString& connId); void setMismatching(ViewLayer::ViewIdentifier viewId, const QString &id, bool mismatching); void checkConnectorLayers(ViewLayer::ViewIdentifier, const QString & connId, Connector* existingConnector, Connector * newConnector); protected slots: void recoverTerminalPointsState(); void fitCenterAndDeselect(); void ensureFixedItemsPositions(); signals: // conns void connectorsFoundSignal(ViewLayer::ViewIdentifier viewId, const QList< QPointer > &conns); void svgFileLoadNeeded(const QString &filepath); void connectorSelected(const QString& connId); void removeTerminalPoint(const QString &connId, ViewLayer::ViewIdentifier vid); protected: // general PartsEditorPaletteItem *newPartsEditorPaletteItem(ModelPart * modelPart); PartsEditorPaletteItem *newPartsEditorPaletteItem(ModelPart * modelPart, SvgAndPartFilePath *path); void setDefaultBackground(); void clearScene(); void removeConnectors(); void addDefaultLayers(class ItemBase * fromItem); void wheelEvent(QWheelEvent* event); void drawBackground(QPainter *painter, const QRectF &rect); ItemBase * addItemAux(ModelPart * modelPart, ViewLayer::ViewLayerSpec, const ViewGeometry & viewGeometry, long id, PaletteItem* paletteItem, bool doConnectors, ViewLayer::ViewIdentifier, bool temporary); ModelPart *createFakeModelPart(SvgAndPartFilePath *svgpath); ModelPart *createFakeModelPart(const QHash &connIds, const QStringList &layers, const QString &svgFilePath); const QHash getConnectorsSvgIds(const QString &path); void getConnectorsSvgIdsAux(QDomElement &docElem); const QStringList getLayers(const QString &path); const QStringList getLayers(const QDomDocument *dom, bool fakeDefaultIfNone=true); QString getOrCreateViewFolderInTemp(); bool ensureFilePath(const QString &filePath); // TODO: retire all singular findConnectorsLayerId() for plural findConnectorsLayerIds() QStringList findConnectorsLayerIds(QDomDocument *svgDom); void findConnectorsLayerIdsAux(QStringList &result, QDomElement &docElem); void findConnectorsLayerId(); QString findConnectorsLayerId(QDomDocument *svgDom); bool findConnectorsLayerIdAux(QString &result, QDomElement &docElem, QStringList &prevLayers); bool terminalIdForConnectorIdAux(QString &result, const QString &connId, QDomElement &docElem, bool wantTerminal); QString getLayerFileName(ModelPart * modelPart); LayerList defaultLayers(); QStringList defaultLayerAsStringlist(); // SVG fixing void beforeSVGLoading(const QString &filename, bool &canceled); bool fixFonts(QString &fileContent, const QString &filename, bool &canceled); bool removeFontFamilySingleQuotes(QString &fileContent, const QString &filename); bool fixUnavailableFontFamilies(QString &fileContent, const QString &filename, bool &canceled); QSet getAttrFontFamilies(const QString &fileContent); QSet getFontFamiliesInsideStyleTag(const QString &fileContent); // specs void setSvgFilePath(const QString &filePath); void copyToTempAndRenameIfNecessary(SvgAndPartFilePath *filePathOrig); QString createSvgFromImage(const QString &filePath); QString setFriendlierSvgFileName(const QString &partFileName); // conns void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void resizeEvent(QResizeEvent * event); void connectItem(); void createConnector(Connector *conn, const QSize &connSize, bool showTerminalPoint); void setItemProperties(); bool isSupposedToBeRemoved(const QString& id); bool addConnectorsIfNeeded(QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId); bool removeConnectorsIfNeeded(QDomElement &docEle); bool updateTerminalPoints(QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId); bool addDefaultLayerIfNotInSvg(QDomDocument *svgDom, bool fakeDefaultIfNone); QString svgIdForConnector(Connector* conn, const QString &connId); void updateSvgIdLayer(const QString &connId, const QString &terminalId, const QString &connectorsLayerId); void removeTerminalPoints(const QStringList &tpIdsToRemove, QDomElement &docElem); void addNewTerminalPoints( const QList &connsWithNewTPs, QDomDocument *svgDom, const QSizeF &sceneViewBox, const QRectF &svgViewBox, const QString &connectorsLayerId ); QRectF mapFromSceneToSvg(const QRectF &sceneRect, const QSizeF &defaultSize, const QRectF &viewBox); bool addRectToSvg(QDomDocument* svgDom, const QString &id, const QRectF &rect, const QString &connectorsLayerId); bool addRectToSvgAux(QDomElement &docElem, const QString &connectorsLayerId, QDomElement &rectElem); QString saveSvg(const QString & svg, const QString & newFilePath); void addFixedToTopLeftItem(QGraphicsItem *item); void addFixedToTopRightItem(QGraphicsItem *item); void addFixedToBottomLeftItem(QGraphicsItem *item); void addFixedToCenterItem(QGraphicsItem *item); void addFixedToBottomRightItem(QGraphicsItem *item); void ensureFixedToTopLeftItems(); void ensureFixedToTopRightItems(); void ensureFixedToBottomLeftItems(); void ensureFixedToBottomRightItems(); void ensureFixedToCenterItems(); void ensureFixedToTopLeft(QGraphicsItem* item); void ensureFixedToTopRight(QGraphicsItem* item); void ensureFixedToBottomLeft(QGraphicsItem* item); void ensureFixedToBottomRight(QGraphicsItem* item); void ensureFixedToCenter(QGraphicsItem* item); void clearFixedItems(); void removeIfFixedPos(QGraphicsItem *item); double fixedItemWidth(QGraphicsItem* item); double fixedItemHeight(QGraphicsItem* item); void deleteItem(ItemBase *, bool deleteModelPart, bool doEmit, bool later); protected: QPointer m_item; // just one item per view QDir m_tempFolder; bool m_deleteModelPartOnSceneClear; QPointer m_startItem; SvgAndPartFilePath *m_svgFilePath; QString m_originalSvgFilePath; QHash m_drawnConns; QStringList m_removedConnIds; QHash m_svgIds; ViewLayer::ViewLayerID m_connsLayerID; bool m_svgLoaded; QString m_lastSelectedConnId; bool m_showingTerminalPoints; bool m_showingTerminalPointsBackup; QTimer *m_terminalPointsTimer; QList m_fixedWidgets; ItemBase * m_viewItem; QTimer *m_fitItemInViewTimer; QList m_fixedToTopLeftItems; QList m_fixedToTopRightItems; QList m_fixedToBottomLeftItems; QList m_fixedToBottomRightItems; QList m_fixedToCenterItems; PaletteModel * m_paletteModel; protected: static int ConnDefaultWidth; static int ConnDefaultHeight; }; #endif /* PARTSEDITORVIEW_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partseditorviewswidget.cpp000066400000000000000000000303411250202676700265770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include "partseditorviewswidget.h" #include "partseditormainwindow.h" #include "zoomcontrols.h" #include "../utils/misc.h" #include "../waitpushundostack.h" #include "../debugdialog.h" QString PartsEditorViewsWidget::EmptyBreadViewText; QString PartsEditorViewsWidget::EmptySchemViewText; QString PartsEditorViewsWidget::EmptyPcbViewText; PartsEditorViewsWidget::PartsEditorViewsWidget(SketchModel *sketchModel, WaitPushUndoStack *undoStack, ConnectorsInfoWidget* info, QWidget *parent, ItemBase * fromItem) : QFrame(parent) { init(); m_showTerminalPointsCheckBox = new QCheckBox(this); m_showTerminalPointsCheckBox->setText(tr("Show Anchor Points")); connect(m_showTerminalPointsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showHideTerminalPoints(int))); m_breadView = createViewImageWidget(sketchModel, undoStack, ViewLayer::BreadboardView, "breadboard_icon.png", EmptyBreadViewText, info, ViewLayer::Breadboard, fromItem); m_schemView = createViewImageWidget(sketchModel, undoStack, ViewLayer::SchematicView, "schematic_icon.png", EmptySchemViewText, info, ViewLayer::Schematic, fromItem); m_pcbView = createViewImageWidget(sketchModel, undoStack, ViewLayer::PCBView, "pcb_icon.png", EmptyPcbViewText, info, ViewLayer::Copper0, fromItem); m_breadView->setViewLayerIDs(ViewLayer::Breadboard, ViewLayer::BreadboardWire, ViewLayer::Breadboard, ViewLayer::BreadboardRuler, ViewLayer::BreadboardNote); m_schemView->setViewLayerIDs(ViewLayer::Schematic, ViewLayer::SchematicWire, ViewLayer::Schematic, ViewLayer::SchematicRuler, ViewLayer::SchematicNote); m_pcbView->setViewLayerIDs(ViewLayer::Schematic, ViewLayer::SchematicWire, ViewLayer::Schematic, ViewLayer::SchematicRuler, ViewLayer::PcbNote); connectPair(m_breadView,m_schemView); connectPair(m_schemView,m_pcbView); connectPair(m_pcbView,m_breadView); connectToThis(m_breadView); connectToThis(m_schemView); connectToThis(m_pcbView); m_viewsContainter = new QSplitter(this); m_viewsContainter->addWidget(addZoomControlsAndBrowseButton(m_breadView)); m_viewsContainter->addWidget(addZoomControlsAndBrowseButton(m_schemView)); m_viewsContainter->addWidget(addZoomControlsAndBrowseButton(m_pcbView)); m_viewsContainter->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); m_guidelines = new QLabel(tr("Please refer to the guidelines before modifying or creating parts"), this); m_guidelines->setOpenExternalLinks(true); m_guidelines->setObjectName("guidelinesLabel"); QHBoxLayout *labelLayout = new QHBoxLayout(); labelLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::MinimumExpanding,QSizePolicy::Fixed)); labelLayout->addWidget(m_guidelines); labelLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::MinimumExpanding,QSizePolicy::Fixed)); QFrame *toolsAndInfoContainer = new QFrame(this); QHBoxLayout *layout2 = new QHBoxLayout(toolsAndInfoContainer); layout2->addLayout(labelLayout); layout2->addWidget(m_showTerminalPointsCheckBox); layout2->setMargin(1); layout2->setSpacing(1); QVBoxLayout *lo = new QVBoxLayout(this); lo->addWidget(m_viewsContainter); lo->addWidget(toolsAndInfoContainer); lo->setMargin(3); lo->setSpacing(1); this->resize(width(),220); //this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); } PartsEditorViewsWidget::~PartsEditorViewsWidget() { if (m_breadView) delete m_breadView; if (m_schemView) delete m_schemView; if (m_pcbView) delete m_pcbView; } void PartsEditorViewsWidget::init() { m_connsPosChanged = false; if(EmptyBreadViewText.isEmpty()) { EmptyBreadViewText = tr("What does this\npart look like on\nthe breadboard?"); } if(EmptySchemViewText.isEmpty()) { EmptySchemViewText = tr("What does this\npart look like in\na schematic view?"); } if(EmptyPcbViewText.isEmpty()) { EmptyPcbViewText = tr("What does this\npart look like in\nthe PCB view?"); } } PartsEditorView * PartsEditorViewsWidget::createViewImageWidget( SketchModel* sketchModel, WaitPushUndoStack *undoStack, ViewLayer::ViewIdentifier viewId, QString iconFileName, QString startText, ConnectorsInfoWidget* info, ViewLayer::ViewLayerID viewLayerId, ItemBase * fromItem) { PartsEditorView * viw = new PartsEditorView(viewId,tempDir(),showingTerminalPoints(),PartsEditorMainWindow::emptyViewItem(iconFileName,startText),this, 150, false, fromItem); viw->setSketchModel(sketchModel); viw->setUndoStack(undoStack); viw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); viw->addViewLayer(new ViewLayer(viewLayerId, true, 2.5)); m_views[viewId] = viw; connect( info, SIGNAL(connectorSelected(const QString&)), viw, SLOT(informConnectorSelection(const QString&)) ); connect( viw, SIGNAL(connectorsFoundSignal(ViewLayer::ViewIdentifier, const QList< QPointer > &)), info, SLOT(syncNewConnectors(ViewLayer::ViewIdentifier, const QList< QPointer > &)) ); connect( info, SIGNAL(existingConnectorSignal(ViewLayer::ViewIdentifier, const QString &, Connector*, Connector*)), viw, SLOT(checkConnectorLayers(ViewLayer::ViewIdentifier, const QString &, Connector*, Connector*)) ); connect( info, SIGNAL(setMismatching(ViewLayer::ViewIdentifier, const QString &, bool)), viw, SLOT(setMismatching(ViewLayer::ViewIdentifier, const QString &, bool)) ); return viw; } void PartsEditorViewsWidget::copySvgFilesToDestiny(const QString &partFileName) { m_breadView->copySvgFileToDestiny(partFileName); m_schemView->copySvgFileToDestiny(partFileName); m_pcbView->copySvgFileToDestiny(partFileName); } void PartsEditorViewsWidget::loadViewsImagesFromModel(PaletteModel *paletteModel, ModelPart *modelPart) { m_breadView->scene()->clear(); m_breadView->setPaletteModel(paletteModel); m_breadView->loadFromModel(paletteModel, modelPart); m_schemView->scene()->clear(); m_schemView->setPaletteModel(paletteModel); m_schemView->loadFromModel(paletteModel, modelPart); m_pcbView->scene()->clear(); m_pcbView->setPaletteModel(paletteModel); m_pcbView->loadFromModel(paletteModel, modelPart); if(modelPart->connectors().size() > 0) { emit connectorsFoundSignal(modelPart->connectors().values()); } } const QDir& PartsEditorViewsWidget::tempDir() { return ((PartsEditorMainWindow*)parentWidget())->tempDir(); } void PartsEditorViewsWidget::connectPair(PartsEditorView *v1, PartsEditorView *v2) { connect( v1, SIGNAL(connectorSelected(const QString &)), v2, SLOT(informConnectorSelection(const QString &)) ); connect( v2, SIGNAL(connectorSelected(const QString &)), v1, SLOT(informConnectorSelection(const QString &)) ); } void PartsEditorViewsWidget::connectToThis(PartsEditorView *v) { connect( v, SIGNAL(connectorSelected(const QString &)), this, SLOT(informConnectorSelection(const QString &)) ); } void PartsEditorViewsWidget::repaint() { m_breadView->scene()->update(); m_schemView->scene()->update(); m_pcbView->scene()->update(); } void PartsEditorViewsWidget::drawConnector(Connector* conn) { bool showing = showingTerminalPoints(); m_breadView->drawConector(conn,showing); m_schemView->drawConector(conn,showing); m_pcbView->drawConector(conn,showing); } void PartsEditorViewsWidget::drawConnector(ViewLayer::ViewIdentifier viewId, Connector* conn) { bool showing = showingTerminalPoints(); m_views[viewId]->drawConector(conn,showing); } void PartsEditorViewsWidget::setMismatching(ViewLayer::ViewIdentifier viewId, const QString &connId, bool mismatching) { m_views[viewId]->setMismatching(viewId, connId, mismatching); m_views[viewId]->scene()->update(); } void PartsEditorViewsWidget::aboutToSave() { m_breadView->aboutToSave(false); m_schemView->aboutToSave(false); m_pcbView->aboutToSave(false); } void PartsEditorViewsWidget::removeConnectorFrom(const QString &connId, ViewLayer::ViewIdentifier viewId) { if(viewId == ViewLayer::AllViews) { m_breadView->removeConnector(connId); m_schemView->removeConnector(connId); m_pcbView->removeConnector(connId); } else { m_views[viewId]->removeConnector(connId); } } void PartsEditorViewsWidget::showHideTerminalPoints(int checkState) { bool show = checkStateToBool(checkState); m_breadView->showTerminalPoints(show); m_schemView->showTerminalPoints(show); m_pcbView->showTerminalPoints(show); } bool PartsEditorViewsWidget::showingTerminalPoints() { return checkStateToBool(m_showTerminalPointsCheckBox->checkState()); } bool PartsEditorViewsWidget::checkStateToBool(int checkState) { if(checkState == Qt::Checked) { return true; } else if(checkState == Qt::Unchecked) { return false; } return false; } QCheckBox *PartsEditorViewsWidget::showTerminalPointsCheckBox() { return m_showTerminalPointsCheckBox; } void PartsEditorViewsWidget::informConnectorSelection(const QString &connId) { emit connectorSelectedInView(connId); } QWidget *PartsEditorViewsWidget::addZoomControlsAndBrowseButton(PartsEditorView *view) { QFrame *container1 = new QFrame(this); QVBoxLayout *lo1 = new QVBoxLayout(container1); lo1->setSpacing(1); lo1->setMargin(0); QLabel *button = new QLabel(QString("%1").arg(tr("Load image..")), this); button->setObjectName("browseButton"); button->setMinimumWidth(85); button->setMaximumWidth(85); button->setFixedHeight(20); button->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); connect(button, SIGNAL(linkActivated(const QString&)), view, SLOT(loadFile())); QHBoxLayout *lo2 = new QHBoxLayout(); lo2->setSpacing(1); lo2->setMargin(0); lo2->addWidget(button); lo2->addWidget(new ZoomControls(view,container1)); lo1->addWidget(view); lo1->addLayout(lo2); return container1; } PartsEditorView *PartsEditorViewsWidget::breadboardView() { return m_breadView; } PartsEditorView *PartsEditorViewsWidget::schematicView() { return m_schemView; } PartsEditorView *PartsEditorViewsWidget::pcbView() { return m_pcbView; } bool PartsEditorViewsWidget::imagesLoadedInAllViews() { return m_breadView->imageLoaded() && m_schemView->imageLoaded() && m_pcbView->imageLoaded(); } void PartsEditorViewsWidget::connectTerminalRemoval(const ConnectorsInfoWidget* connsInfo) { connect( m_breadView, SIGNAL(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)), connsInfo, SLOT(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)) ); connect( m_schemView, SIGNAL(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)), connsInfo, SLOT(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)) ); connect( m_pcbView, SIGNAL(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)), connsInfo, SLOT(removeTerminalPoint(const QString&, ViewLayer::ViewIdentifier)) ); } bool PartsEditorViewsWidget::connectorsPosOrSizeChanged() { return m_breadView->connsPosOrSizeChanged() || m_schemView->connsPosOrSizeChanged() || m_pcbView->connsPosOrSizeChanged(); } void PartsEditorViewsWidget::setViewItems(ItemBase* bbItem, ItemBase* schemItem, ItemBase* pcbItem) { m_breadView->setViewItem(bbItem); m_schemView->setViewItem(schemItem); m_pcbView->setViewItem(pcbItem); } void PartsEditorViewsWidget::updatePinsInfo(QList< QPointer > connsShared) { m_breadView->updatePinsInfo(connsShared); m_schemView->updatePinsInfo(connsShared); m_pcbView->updatePinsInfo(connsShared); } fritzing-app-0.9.2b/src/partseditor/obsolete/partseditorviewswidget.h000066400000000000000000000071221250202676700262450ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSEDITORVIEWSWIDGET_H_ #define PARTSEDITORVIEWSWIDGET_H_ #include #include #include "partseditorview.h" #include "connectorsinfowidget.h" class PartsEditorViewsWidget : public QFrame { Q_OBJECT public: PartsEditorViewsWidget(SketchModel *sketchModel, class WaitPushUndoStack *undoStack, ConnectorsInfoWidget* info, QWidget *parent, class ItemBase * fromItem); ~PartsEditorViewsWidget(); void copySvgFilesToDestiny(const QString &partFileName); void loadViewsImagesFromModel(PaletteModel *paletteModel, ModelPart *modelPart); const QDir& tempDir(); void aboutToSave(); void updatePinsInfo(QList< QPointer > connsShared); QCheckBox *showTerminalPointsCheckBox(); bool imagesLoadedInAllViews(); void setViewItems(class ItemBase *, class ItemBase *, class ItemBase *); PartsEditorView *breadboardView(); PartsEditorView *schematicView(); PartsEditorView *pcbView(); void connectTerminalRemoval(const ConnectorsInfoWidget* connsInfo); bool connectorsPosOrSizeChanged(); public slots: void repaint(); void drawConnector(Connector*); void drawConnector(ViewLayer::ViewIdentifier, Connector*); void removeConnectorFrom(const QString&,ViewLayer::ViewIdentifier); void showHideTerminalPoints(int checkState); void informConnectorSelection(const QString &connId); void setMismatching(ViewLayer::ViewIdentifier viewId, const QString &id, bool mismatching); signals: void connectorsFoundSignal(QList< QPointer >); void connectorSelectedInView(const QString& connId); protected: PartsEditorView * createViewImageWidget( SketchModel* sketchModel, class WaitPushUndoStack *undoStack, ViewLayer::ViewIdentifier viewId, QString iconFileName, QString startText, ConnectorsInfoWidget* info, ViewLayer::ViewLayerID viewLayerId, class ItemBase * fromItem ); void init(); QWidget *addZoomControlsAndBrowseButton(PartsEditorView *view); bool showingTerminalPoints(); bool checkStateToBool(int checkState); void connectPair(PartsEditorView *v1, PartsEditorView *v2); void connectToThis(PartsEditorView *v); QPointer m_breadView; QPointer m_schemView; QPointer m_pcbView; QHash m_views; QSplitter *m_viewsContainter; QPointer m_showTerminalPointsCheckBox; QPointer m_guidelines; bool m_connsPosChanged; protected: static QString EmptyBreadViewText; static QString EmptySchemViewText; static QString EmptyPcbViewText; }; #endif /* PARTSEDITORVIEWSWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/partspecificationswidget.cpp000066400000000000000000000050331250202676700270530ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include "partspecificationswidget.h" #include "../debugdialog.h" PartSpecificationsWidget::PartSpecificationsWidget(QList widgets, QWidget *parent) : QScrollArea(parent) { m_scrollContent = new QFrame(this); m_scrollContent->setObjectName("scroll"); //m_scrollContent->setSizePolicy(QSizePolicy::M,QSizePolicy::Expanding); QGridLayout *layout = new QGridLayout(m_scrollContent); for(int i=0; i < widgets.size(); i++) { //widgets[i]->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); widgets[i]->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); layout->addWidget(widgets[i],i,0); if(widgets[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("editionStarted()")) > -1) { connect(widgets[i],SIGNAL(editionStarted()),this,SLOT(updateLayout())); } if(widgets[i]->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("editionFinished()")) > -1) { connect(widgets[i],SIGNAL(editionFinished()),this,SLOT(updateLayout())); } } layout->setMargin(0); layout->setSpacing(10); setWidget(m_scrollContent); setMinimumWidth(m_scrollContent->width()+15); //scrollbar setWidgetResizable(true); QGridLayout *mylayout = new QGridLayout(this); mylayout->setMargin(0); mylayout->setSpacing(0); //resize(sizeHint()); } void PartSpecificationsWidget::updateLayout() { m_scrollContent->adjustSize(); } QSize PartSpecificationsWidget::sizeHint() { //return QSize(width(),600); return QScrollArea::sizeHint(); } fritzing-app-0.9.2b/src/partseditor/obsolete/partspecificationswidget.h000066400000000000000000000026251250202676700265240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PARTSPECIFICATIONSWIDGET_H_ #define PARTSPECIFICATIONSWIDGET_H_ #include class PartSpecificationsWidget : public QScrollArea { Q_OBJECT public: PartSpecificationsWidget(QList widgets, QWidget *parent=0); QSize sizeHint(); protected slots: void updateLayout(); protected: QFrame *m_scrollContent; }; #endif /* PARTSPECIFICATIONSWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/pcbxml.cpp000066400000000000000000000227601250202676700232500ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "pcbxml.h" #include #include #include #include "../debugdialog.h" // this module converts fritzing footprint xml files to svg // TODO: mask and keepout layers // TODO: elementarc // TODO: square pins and round pads? PcbXML::PcbXML( const QDomElement & pcbDocument ) { // TODO: need some execption handling for bad elements missing attrs, etc. m_svg = new SVGDomDocument(); m_svgroot = m_svg->documentElement(); // FIXME: what happens when there is no mark - should be 0 m_markx = pcbDocument.attribute("MX").toInt(); m_marky = pcbDocument.attribute("MY").toInt(); m_units = pcbDocument.attribute("units"); m_minx = m_markx; m_miny = m_marky; m_maxx = m_markx; m_maxy = m_marky; m_pinCount = 0; m_padCount = 0; m_silkscreen = m_svg->createGroup("silkscreen"); m_copper = m_svg->createGroup("copper0"); m_keepout = m_svg->createGroup("keepout"); m_mask = m_svg->createGroup("soldermask"); m_outline = m_svg->createGroup("outline"); QDomNodeList tagList = pcbDocument.childNodes(); //TODO: eventually need to support recursing into the tree here //TODO: support footprints with multiple root elements (module style) for(uint i = 0; i < tagList.length(); i++){ drawNode(tagList.item(i)); } m_svg->setHeight(m_maxy-m_miny, m_units); m_svg->setWidth(m_maxx-m_minx, m_units); m_svg->setViewBox(0,0,m_maxx-m_minx,m_maxy-m_miny); shiftCoordinates(); m_svgFile = QDir::tempPath () + "/footprint.svg"; DebugDialog::debug(QString("temp path %1").arg(QDir::tempPath () + "/test.svg" ) ); m_svg->save(m_svgFile); } QString PcbXML::getSvgFile(){ return m_svgFile; } void PcbXML::drawNode(QDomNode node){ DebugDialog::debug("drawing node:"); QString tag = node.nodeName().toLower(); if(tag=="pin"){ DebugDialog::debug("\tPin"); drawPin(node); } else if(tag=="pad"){ DebugDialog::debug("\tPad"); drawPad(node); } else if(tag=="elementline"){ DebugDialog::debug("\tElementLine"); drawElementLine(node); } else if(tag=="elementarc"){ DebugDialog::debug("\tElementArc"); drawElementArc(node); } else if(tag=="mark"){ DebugDialog::debug("\tMark"); drawMark(node); } else { DebugDialog::debug("cannot draw - unrecognized tag"); } } void PcbXML::drawPin(QDomNode node){ QDomElement element = node.toElement(); QDomElement pin = m_svg->createElement("circle"); int x; int y; if( element.hasAttribute("aX") ){ x = element.attribute("aX").toInt(); y = element.attribute("aY").toInt(); } else { x = element.attribute("rX").toInt() + m_markx; y = element.attribute("rY").toInt() + m_marky; } int drill = element.attribute("Drill").toInt()/2; int thickness = element.attribute("Thickness").toInt()/2 - drill; int radius = drill + thickness/2; QString id = QString("connector%1pin").arg(m_pinCount); // BUG: what's up with str -> hex conversion??? bool verify; bool square=false; if(element.hasAttribute("NFlags")) { square = element.attribute("NFlags").toInt(&verify,16) & 0x0100; } else if(element.hasAttribute("SFlags")) { square = element.attribute("SFlags").toInt(&verify,16) & 0x0100; } //DebugDialog::debug(QString("NFlags: %1 Value:%2 Square:%3").arg(element.attribute("NFlags")).arg(element.attribute("NFlags").toInt(&verify,16)).arg(square)); m_pinCount++; if(square){ QDomElement sq = m_svg->createElement("rect"); sq.setAttribute("x",x-radius); sq.setAttribute("y",y-radius); sq.setAttribute("fill", "none"); sq.setAttribute("width",radius*2); sq.setAttribute("height",radius*2); sq.setAttribute("stroke", "rgb(255, 191, 0)"); sq.setAttribute("stroke-width", thickness); QDomNode tempsq = m_copper.appendChild(sq); } pin.setAttribute("cx", x); pin.setAttribute("cy", y); pin.setAttribute("r", radius); pin.setAttribute("stroke", "rgb(255, 191, 0)"); pin.setAttribute("stroke-width", thickness); pin.setAttribute("id", id); pin.setAttribute("fill", "none"); QDomNode temp = m_copper.appendChild(pin); minMax(x,y,radius+(thickness/2)); } void PcbXML::drawPad(QDomNode node){ QDomElement element = node.toElement(); QDomElement pad = m_svg->createElement("rect"); // TODO: mask and keepout layers int x1 = qMin(element.attribute("rX1").toInt(),element.attribute("rX2").toInt()) + m_markx; int x2 = qMax(element.attribute("rX1").toInt(),element.attribute("rX2").toInt()) + m_markx; int y1 = qMin(element.attribute("rY1").toInt(),element.attribute("rY2").toInt()) + m_marky; int y2 = qMax(element.attribute("rY1").toInt(),element.attribute("rY2").toInt()) + m_marky; int thickness = element.attribute("Thickness").toInt(); QString id = "connector" + QString::number(m_padCount) + "pad"; m_padCount++; int x = x1 - (thickness/2); int y = y1 - (thickness/2); int width = x2 - x1 + thickness; int height = y2 -y1 + thickness; pad.setAttribute("x", x); pad.setAttribute("y", y); pad.setAttribute("width", width); pad.setAttribute("height", height); pad.setAttribute("fill", "rgb(255, 191, 0)"); pad.setAttribute("id", id); QDomNode temp = m_copper.appendChild(pad); minMax(x,y,0); minMax(x+width,y+height,0); } void PcbXML::drawElementLine(QDomNode node){ QDomElement element = node.toElement(); QDomElement line = m_svg->createElement("line"); int x1 = element.attribute("X1").toInt() + m_markx; int y1 = element.attribute("Y1").toInt() + m_marky; int x2 = element.attribute("X2").toInt() + m_markx; int y2 = element.attribute("Y2").toInt() + m_marky; int thickness = element.attribute("Thickness").toInt(); line.setAttribute("x1", x1); line.setAttribute("y1", y1); line.setAttribute("x2", x2); line.setAttribute("y2", y2); line.setAttribute("stroke", "white"); line.setAttribute("stroke-width", thickness); QDomNode temp = m_silkscreen.appendChild(line); minMax(x1,y1,thickness); minMax(x2,y2,thickness); } void PcbXML::drawElementArc(QDomNode node){ QDomElement element = node.toElement(); // TODO: implement this with cubic bezier in svg int x = element.attribute("X").toInt() + m_markx; int y = element.attribute("Y").toInt() + m_marky; //int width = element.attribute("width").toInt()/2; //int height = element.attribute("height").toInt()/2; //int startangle = element.attribute("StartAngle").toInt(); //int endangle = element.attribute("Delta").toInt() + startangle; //int thickness = element.attribute("Thickness").toInt(); QString path = "M" + QString::number(x) + "," + QString::number(y) + " "; } // ignore for now void PcbXML::drawMark(QDomNode /*node*/){ //QDomElement element = node.toElement();QDomElement element = node.toElement(); // //int ax = element.attribute("aX").toInt(); int ax = element.attribute("aX").toInt(); //int ay = element.attribute("aY").toInt(); int ay = element.attribute("aY").toInt(); //int radius = element.attribute("Drill").toInt()/2; int radius = element.attribute("Drill").toInt()/2; //int thickness = element.attribute("Thickness").toInt(); int thickness = element.attribute("Thickness").toInt(); return; } // checks to see if input is greater or less than current min max // adjust viewbox accordingly void PcbXML::minMax(int x, int y, int width){ m_minx = qMin(x-width, m_minx); m_miny = qMin(y-width, m_miny); m_maxx = qMax(x+width, m_maxx); m_maxy = qMax(y+width, m_maxy); } // given minimum x and y coordinates shift all elements to upper left corner void PcbXML::shiftCoordinates(){ // shift lines QDomNodeList lineList = m_svgroot.elementsByTagName("line"); for(uint i = 0; i < lineList.length(); i++){ QDomElement line = lineList.item(i).toElement(); float x1 = line.attribute("x1").toFloat() - m_minx; line.setAttribute("x1", x1); float x2 = line.attribute("x2").toFloat() - m_minx; line.setAttribute("x2", x2); float y1 = line.attribute("y1").toFloat() - m_miny; line.setAttribute("y1", y1); float y2 = line.attribute("y2").toFloat() - m_miny; line.setAttribute("y2", y2); } // circles QDomNodeList circleList = m_svgroot.elementsByTagName("circle"); for(uint i = 0; i < circleList.length(); i++){ QDomElement circle = circleList.item(i).toElement(); float cx = circle.attribute("cx").toFloat() - m_minx; circle.setAttribute("cx",cx); float cy = circle.attribute("cy").toFloat() - m_miny; circle.setAttribute("cy",cy); } // rects QDomNodeList rectList = m_svgroot.elementsByTagName("rect"); for(uint i = 0; i < rectList.length(); i++){ QDomElement rect = rectList.item(i).toElement(); float x = rect.attribute("x").toFloat() - m_minx; rect.setAttribute("x", x); float y = rect.attribute("y").toFloat() - m_miny; rect.setAttribute("y", y); } //TODO: arcs return; } fritzing-app-0.9.2b/src/partseditor/obsolete/pcbxml.h000066400000000000000000000035441250202676700227140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PCBXML_H #define PCBXML_H // #include #include #include "svgdomdocument.h" // class PcbXML { public: PcbXML(const QDomElement & pcbDocument); QString getSvgFile(); private: SVGDomDocument * m_svg; QString m_svgFile; QDomElement m_svgroot; QDomElement m_silkscreen; QDomElement m_copper; QDomElement m_keepout; QDomElement m_mask; QDomElement m_outline; int m_markx; int m_marky; int m_minx; int m_miny; int m_maxx; int m_maxy; int m_pinCount; int m_padCount; QString m_units; // length units for the root element coordinates void drawNode(QDomNode node); void drawPin(QDomNode node); void drawPad(QDomNode node); void drawElementLine(QDomNode node); void drawElementArc(QDomNode node); void drawMark(QDomNode node); void minMax(int, int, int); void shiftCoordinates(); }; #endif fritzing-app-0.9.2b/src/partseditor/obsolete/resizablerectitem.cpp000066400000000000000000000024641250202676700254770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "resizablerectitem.h" ResizableRectItem::ResizableRectItem() { m_resizable = false; // not resizable by default m_handlers = NULL; } void ResizableRectItem::setResizable(bool resizable) { m_resizable = resizable; } bool ResizableRectItem::isResizable() { return m_resizable; } fritzing-app-0.9.2b/src/partseditor/obsolete/resizablerectitem.h000066400000000000000000000031251250202676700251370ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef RESIZABLERECTITEM_H_ #define RESIZABLERECTITEM_H_ #include class ConnectorRectangle; class ResizableRectItem { friend class ConnectorRectangle; public: ResizableRectItem(); virtual ~ResizableRectItem() {} virtual qreal minWidth() = 0; virtual qreal minHeight() = 0; virtual void resizeRect(qreal x, qreal y, qreal width, qreal height) = 0; virtual void doPrepareGeometryChange() = 0; void setResizable(bool resizable); bool isResizable(); protected: ConnectorRectangle *m_handlers; bool m_resizable; }; #endif /* RESIZABLERECTITEM_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/simpleeditablelabelwidget.cpp000066400000000000000000000065231250202676700271510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "simpleeditablelabelwidget.h" #include "../debugdialog.h" #include #include SimpleEditableLabelWidget::SimpleEditableLabelWidget(QUndoStack *undoStack, QWidget *parent, const QString &text, bool edited) : QFrame(parent) { setObjectName("partsBinTitle"); m_label = new QLabel(this); m_lineEdit = new QLineEdit(this); connect(m_lineEdit,SIGNAL(editingFinished()),this,SLOT(toStandardMode())); QHBoxLayout *lo = new QHBoxLayout(this); lo->setMargin(3); lo->setSpacing(0); m_hasBeenEdited = edited; m_isInEditionMode = false; m_label->setText(text); m_undoStack = undoStack; updateUndoStackIfNecessary(); toStandardMode(edited); } QString SimpleEditableLabelWidget::text() { return m_label->text(); } void SimpleEditableLabelWidget::setText(const QString &text, bool markAsEdited) { if(m_label->text() != text) { m_label->setText(text); m_hasBeenEdited = markAsEdited; updateUndoStackIfNecessary(); emit textChanged(text); } } void SimpleEditableLabelWidget::toStandardMode(bool markAsEdited) { setText(m_lineEdit->text(), markAsEdited); swapWidgets(m_label, m_lineEdit); } void SimpleEditableLabelWidget::toEditionMode() { //if(m_hasBeenEdited) { m_lineEdit->setText(m_label->text()); //} else { // Remove this part of the branch if we want the lineedit to remember what was typed the last time //m_lineEdit->setText(""); //} swapWidgets(m_lineEdit, m_label); m_lineEdit->setFocus(); } void SimpleEditableLabelWidget::swapWidgets(QWidget *toShow, QWidget *toHide) { layout()->removeWidget(toHide); toHide->hide(); layout()->addWidget(toShow); toShow->show(); m_isInEditionMode = (toShow == m_lineEdit); } void SimpleEditableLabelWidget::swapMode() { if(m_isInEditionMode) { toStandardMode(); } else { toEditionMode(); } } void SimpleEditableLabelWidget::mousePressEvent(QMouseEvent *event) { if(!m_isInEditionMode) { swapMode(); } QFrame::mousePressEvent(event); } void SimpleEditableLabelWidget::keyPressEvent(QKeyEvent *event) { if(m_isInEditionMode && event->key() == Qt::Key_Escape) { QString prevText = m_label->text(); toStandardMode(); setText(prevText); } QFrame::keyPressEvent(event); } void SimpleEditableLabelWidget::updateUndoStackIfNecessary() { if(m_hasBeenEdited) { m_undoStack->push(new QUndoCommand("Palette Widget title modified")); } } fritzing-app-0.9.2b/src/partseditor/obsolete/simpleeditablelabelwidget.h000066400000000000000000000037251250202676700266170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SIMPLEEDITABLELABELWIDGET_H_ #define SIMPLEEDITABLELABELWIDGET_H_ #include #include #include #include class SimpleEditableLabelWidget : public QFrame { Q_OBJECT public: SimpleEditableLabelWidget(QUndoStack *undoStack, QWidget *parent=0, const QString &text = "", bool edited=false); void setText(const QString &text, bool markAsEdited = true); QString text(); protected slots: void toStandardMode(bool markAsEdited = true); void toEditionMode(); signals: void textChanged(const QString& text); protected: void swapWidgets(QWidget *toShow, QWidget *toHide); void swapMode(); void mousePressEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); void updateUndoStackIfNecessary(); protected: QLabel *m_label; QLineEdit *m_lineEdit; QUndoStack *m_undoStack; bool m_hasBeenEdited; volatile bool m_isInEditionMode; }; #endif /* SIMPLEEDITABLELABELWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/singleconnectorinfowidget.cpp000066400000000000000000000257461250202676700272460ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "connectorsinfowidget.h" #include "singleconnectorinfowidget.h" #include "connectorinforemovebutton.h" #include "../connectors/connectorshared.h" #include "../debugdialog.h" static const QString PadString = "Pad"; ConnectorTypeWidget::ConnectorTypeWidget(Connector::ConnectorType type, QWidget *parent) : QFrame(parent) { m_isSelected = false; m_noEditionModeWidget = new QLabel(this); m_editionModeWidget = new QPushButton(this); connect( m_editionModeWidget, SIGNAL(clicked()), this, SLOT(toggleValue()) ); m_noEditionModeWidget->setFixedWidth(30); m_editionModeWidget->setFixedWidth(30); QVBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(2); layout->setSpacing(0); layout->addWidget(m_noEditionModeWidget); layout->addWidget(m_editionModeWidget); setType(type); } Connector::ConnectorType ConnectorTypeWidget::type() { if(text()==FemaleSymbolString) { return Connector::connectorTypeFromName("female"); } else if(text()==MaleSymbolString) { return Connector::connectorTypeFromName("male"); } else if (text()==PadString) { return Connector::connectorTypeFromName("pad"); } return Connector::Unknown; } const QString &ConnectorTypeWidget::typeAsStr() { return Connector::connectorNameFromType(type()); } void ConnectorTypeWidget::setType(Connector::ConnectorType type) { if(m_isInEditionMode) { m_typeBackUp = this->type(); } if(type == Connector::Female) { setText(FemaleSymbolString); } else if(type == Connector::Male) { setText(MaleSymbolString); } else if(type == Connector::Pad) { setText(PadString); } setToolTip(Connector::connectorNameFromType(type)); } void ConnectorTypeWidget::setSelected(bool selected) { m_isSelected = selected; } void ConnectorTypeWidget::setText(const QString &text) { m_text = text; m_noEditionModeWidget->setText(text); m_editionModeWidget->setText(text); } const QString &ConnectorTypeWidget::text() { return m_text; } void ConnectorTypeWidget::setInEditionMode(bool edition) { m_isInEditionMode = edition; m_noEditionModeWidget->setVisible(!edition); m_editionModeWidget->setVisible(edition); } void ConnectorTypeWidget::cancel() { setType(m_typeBackUp); } void ConnectorTypeWidget::toggleValue() { if(m_isSelected && m_isInEditionMode) { if(type() == Connector::Female) { setType(Connector::Pad); } else if(type() == Connector::Male) { setType(Connector::Female); } else if (type() == Connector::Pad) { setType(Connector::Male); } } } SingleConnectorInfoWidget::SingleConnectorInfoWidget(ConnectorsInfoWidget *topLevelContainer, WaitPushUndoStack *undoStack, Connector* connector, QWidget *parent) : AbstractConnectorInfoWidget(topLevelContainer,parent) { static QString EMPTY_CONN_NAME = QObject::tr("no name yet"); static QString EMPTY_CONN_DESC = QObject::tr("no description yet"); static Connector::ConnectorType EMPTY_CONN_TYPE = Connector::Male; QString name; QString description; Connector::ConnectorType type; m_undoStack = undoStack; m_connector = connector; if(connector && connector->connectorShared()) { m_id = connector->connectorSharedID(); name = connector->connectorSharedName(); if (name.isEmpty()) name = EMPTY_CONN_NAME; description = connector->connectorSharedDescription(); if (description.isEmpty()) description = EMPTY_CONN_DESC; type = connector->connectorType(); if (type == Connector::Unknown) type = EMPTY_CONN_TYPE; } else { name = EMPTY_CONN_NAME; description = EMPTY_CONN_DESC; type = EMPTY_CONN_TYPE; } m_nameLabel = new QLabel(name,this); m_nameDescSeparator = new QLabel(" - ",this); m_descLabel = new QLabel(description,this); m_descLabel->setObjectName("description"); m_type = new ConnectorTypeWidget(type, this); m_nameEdit = NULL; m_descEdit = NULL; m_nameEditContainer = new QFrame(this); QHBoxLayout *nameLO = new QHBoxLayout(m_nameEditContainer); nameLO->setSpacing(0); nameLO->setMargin(0); m_nameEditContainer->hide(); m_descEditContainer = new QFrame(this); QVBoxLayout *descLO = new QVBoxLayout(m_descEditContainer); descLO->setSpacing(0); descLO->setMargin(0); m_descEditContainer->hide(); m_acceptButton = NULL; m_cancelButton = NULL; setSelected(false); QLayout *layout = new QVBoxLayout(this); layout->setMargin(1); toStandardMode(); } QString SingleConnectorInfoWidget::id() { if (m_connector) { return m_connector->connectorSharedID(); } return m_id; } QString SingleConnectorInfoWidget::name() { return m_nameLabel->text(); } QString SingleConnectorInfoWidget::description() { return m_descLabel->text(); } QString SingleConnectorInfoWidget::type() { return m_type->typeAsStr(); } void SingleConnectorInfoWidget::startEdition() { createInputs(); m_nameEdit->setText(m_nameLabel->text()); m_descEdit->setText(m_descLabel->text()); toEditionMode(); emit editionStarted(); } void SingleConnectorInfoWidget::createInputs() { if(!m_nameEdit) { m_nameEdit = new QLineEdit(this); m_nameEditContainer->layout()->addWidget(new QLabel(tr("Name: "),this)); m_nameEditContainer->layout()->addWidget(m_nameEdit); } if(!m_descEdit) { m_descEdit = new QTextEdit(this); m_descEditContainer->layout()->addWidget(new QLabel(tr("Description:"),this)); m_descEditContainer->layout()->addWidget(m_descEdit); } } void SingleConnectorInfoWidget::editionCompleted() { if(m_isInEditionMode) { m_undoStack->push(new QUndoCommand("Dummy parts editor command")); m_nameLabel->setText(m_nameEdit->text()); m_descLabel->setText(m_descEdit->toPlainText()); toStandardMode(); emit editionFinished(); } } void SingleConnectorInfoWidget::editionCanceled() { m_type->cancel(); toStandardMode(); emit editionFinished(); } void SingleConnectorInfoWidget::toStandardMode() { hide(); setInEditionMode(false); hideIfNeeded(m_nameEditContainer); hideIfNeeded(m_descEditContainer); hideIfNeeded(m_acceptButton); hideIfNeeded(m_cancelButton); QHBoxLayout *hbLayout = new QHBoxLayout(); hbLayout->addWidget(m_type); hbLayout->addSpacerItem(new QSpacerItem(10,0)); hbLayout->addWidget(m_nameLabel); m_nameLabel->show(); hbLayout->addWidget(m_nameDescSeparator); m_nameDescSeparator->show(); hbLayout->addWidget(m_descLabel); m_descLabel->show(); hbLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); hbLayout->addWidget(m_removeButton); QVBoxLayout *layout = (QVBoxLayout*)this->layout(); layout->addLayout(hbLayout); setFixedHeight(SingleConnectorHeight); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); updateGeometry(); show(); setFocus(); } void SingleConnectorInfoWidget::toEditionMode() { hide(); setInEditionMode(true); hideIfNeeded(m_nameLabel); hideIfNeeded(m_nameDescSeparator); hideIfNeeded(m_descLabel); createInputs(); // first row QHBoxLayout *firstRowLayout = new QHBoxLayout(); firstRowLayout->addWidget(m_type); firstRowLayout->addSpacerItem(new QSpacerItem(10,0)); firstRowLayout->addWidget(m_nameEditContainer); firstRowLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); firstRowLayout->addWidget(m_removeButton); m_nameEditContainer->show(); // second row m_descEditContainer->show(); // third row if(!m_acceptButton) { m_acceptButton = new QPushButton(QObject::tr("Accept"),this); connect(m_acceptButton,SIGNAL(clicked()),this,SLOT(editionCompleted())); } m_acceptButton->show(); if(!m_cancelButton) { m_cancelButton = new QPushButton(QObject::tr("Cancel"),this); connect(m_cancelButton,SIGNAL(clicked()),this,SLOT(editionCanceled())); } m_cancelButton->show(); QHBoxLayout *thirdRowLayout = new QHBoxLayout(); thirdRowLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); thirdRowLayout->addWidget(m_acceptButton); thirdRowLayout->addWidget(m_cancelButton); QVBoxLayout *layout = (QVBoxLayout*)this->layout(); layout->addLayout(firstRowLayout); layout->addWidget(m_descEditContainer); layout->addLayout(thirdRowLayout); setFixedHeight(SingleConnectorHeight*4); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); updateGeometry(); show(); setFocus(); emit editionStarted(); } void SingleConnectorInfoWidget::hideIfNeeded(QWidget* w) { if(w) { w->hide(); layout()->removeWidget(w); } } QSize SingleConnectorInfoWidget::maximumSizeHint() const { return sizeHint(); } QSize SingleConnectorInfoWidget::minimumSizeHint() const { return sizeHint(); } QSize SingleConnectorInfoWidget::sizeHint() const { QSize retval; if(m_isInEditionMode) { retval = QSize(width(),SingleConnectorHeight*4); } else { retval = QSize(width(),SingleConnectorHeight); } return retval; } void SingleConnectorInfoWidget::setSelected(bool selected, bool doEmitChange) { AbstractConnectorInfoWidget::setSelected(selected, doEmitChange); m_type->setSelected(selected); if(selected && m_connector) { emit tellViewsMyConnectorIsNewSelected(m_connector->connectorSharedID()); } } void SingleConnectorInfoWidget::setInEditionMode(bool inEditionMode) { m_isInEditionMode = inEditionMode; m_type->setInEditionMode(inEditionMode); } bool SingleConnectorInfoWidget::isInEditionMode() { return m_isInEditionMode; } void SingleConnectorInfoWidget::mousePressEvent(QMouseEvent * event) { if(isSelected() && !isInEditionMode()) { startEdition(); } else if(!isSelected()) { setSelected(true); } QFrame::mousePressEvent(event); } Connector *SingleConnectorInfoWidget::connector() { return m_connector; } MismatchingConnectorWidget *SingleConnectorInfoWidget::toMismatching(ViewLayer::ViewIdentifier missingViewId) { MismatchingConnectorWidget *mcw = new MismatchingConnectorWidget(m_topLevelContainer,missingViewId, m_connector->connectorSharedID(), (QWidget*)parent(), false, m_connector); return mcw; } Connector::ConnectorType SingleConnectorInfoWidget::connectorType() { if (m_type == NULL) return Connector::Unknown; return m_type->type(); } void SingleConnectorInfoWidget::setConnectorType(Connector::ConnectorType type) { if (m_type) { m_type->setType(type); } } void SingleConnectorInfoWidget::setName(const QString & name) { m_nameLabel->setText(name); if (m_nameEdit) { m_nameEdit->setText(name); } } fritzing-app-0.9.2b/src/partseditor/obsolete/singleconnectorinfowidget.h000066400000000000000000000067721250202676700267110ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SINGLECONNECTORINFOWIDGET_H_ #define SINGLECONNECTORINFOWIDGET_H_ #include "../connectors/connector.h" #include "abstractconnectorinfowidget.h" #include "editablelinewidget.h" #include "editabletextwidget.h" #include "mismatchingconnectorwidget.h" class ConnectorTypeWidget : public QFrame { Q_OBJECT public: ConnectorTypeWidget(Connector::ConnectorType type = Connector::Female, QWidget *parent=0); Connector::ConnectorType type(); const QString &typeAsStr(); void setType(Connector::ConnectorType type); void setSelected(bool selected); void setInEditionMode(bool edition); void cancel(); protected slots: void toggleValue(); protected: void setText(const QString &text); const QString &text(); QLabel *m_noEditionModeWidget; QPushButton *m_editionModeWidget; QString m_text; bool m_isSelected; volatile bool m_isInEditionMode; Connector::ConnectorType m_typeBackUp; }; class SingleConnectorInfoWidget : public AbstractConnectorInfoWidget { Q_OBJECT public: SingleConnectorInfoWidget(ConnectorsInfoWidget *topLevelContainer, WaitPushUndoStack *undoStack, Connector* connector=0, QWidget *parent=0); void setSelected(bool selected, bool doEmitChange=true); void setInEditionMode(bool inEditionMode); bool isInEditionMode(); QSize sizeHint() const; QSize minimumSizeHint() const; QSize maximumSizeHint() const; Connector * connector(); QString id(); QString name(); void setName(const QString &); QString description(); QString type(); Connector::ConnectorType connectorType(); void setConnectorType(Connector::ConnectorType); MismatchingConnectorWidget *toMismatching(ViewLayer::ViewIdentifier viewId); protected slots: void editionCompleted(); void editionCanceled(); signals: void editionStarted(); void editionFinished(); //void connectorSelected(const QString&); protected: void toStandardMode(); void toEditionMode(); void startEdition(); void createInputs(); void mousePressEvent(QMouseEvent * event); void hideIfNeeded(QWidget* w); //QFrame *noEditFrame; QLabel *m_nameLabel; QLabel *m_nameDescSeparator; QLabel *m_descLabel; ConnectorTypeWidget *m_type; QFrame *m_nameEditContainer; QLineEdit *m_nameEdit; QFrame *m_descEditContainer; QTextEdit *m_descEdit; QPushButton *m_acceptButton; QPushButton *m_cancelButton; WaitPushUndoStack *m_undoStack; QPointer m_connector; QString m_id; volatile bool m_isInEditionMode; }; #endif /* SINGLECONNECTORINFOWIDGET_H_ */ fritzing-app-0.9.2b/src/partseditor/obsolete/svgdomdocument.cpp000066400000000000000000000064741250202676700250250ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "svgdomdocument.h" SVGDomDocument::SVGDomDocument( ) : QDomDocument() { QDomElement svgroot = createElement("svg"); svgroot.setAttribute("xmlns","http://www.w3.org/2000/svg"); svgroot.setAttribute("version","1.2"); svgroot.setAttribute("baseProfile","tiny"); //svgroot.setAttribute("viewBox","0 0 400 400"); //TODO: set dynamically appendChild(svgroot); QDomElement desc = createElement("desc"); QDomText descText = createTextNode("Fritzing footprint SVG"); desc.appendChild(descText); svgroot.appendChild(desc); } void SVGDomDocument::setWidth(int width, QString units){ QDomElement svgroot = documentElement(); float scaled = 1; if(units == "mils"){ scaled = qreal(width)/1000.0; units = "in"; } if(units == "cmil"){ scaled = qreal(width)/100000.0; units = "in"; } QString strwidth = QString::number(scaled) + units; svgroot.setAttribute("width",strwidth); } void SVGDomDocument::setHeight(int height, QString units){ QDomElement svgroot = documentElement(); float scaled = 1; if(units == "mils"){ scaled = qreal(height)/1000.0; units = "in"; } if(units == "cmil"){ scaled = qreal(height)/100000.0; units = "in"; } QString strheight = QString::number(scaled) + units; svgroot.setAttribute("height",strheight); } void SVGDomDocument::setViewBox(int minx, int miny, int maxx, int maxy){ QDomElement svgroot = documentElement(); QString viewBox = QString::number(minx) + " " + QString::number(miny) + " " + QString::number(maxx) + " " + QString::number(maxy); svgroot.setAttribute("viewBox", viewBox); } void SVGDomDocument::save(QString fileName){ QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(NULL, QObject::tr("Parts Editor"), QObject::tr("Cannot write to file %1:\n%2.") .arg(fileName) .arg(file.errorString())); } QTextStream out(&file); // This is kinda naughty but QDom seem to have no other way set the header! QString xmlDeclaration = "\n"; out << xmlDeclaration << toString(); file.close(); } QDomElement SVGDomDocument::createGroup(QString id){ QDomElement group = createElement("g"); group.setAttribute("id", id); documentElement().appendChild(group); return group; } fritzing-app-0.9.2b/src/partseditor/obsolete/svgdomdocument.h000066400000000000000000000025461250202676700244660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVGDOMDOCUMENT_H #define SVGDOMDOCUMENT_H // #include #include // class SVGDomDocument : public QDomDocument { public: SVGDomDocument(); QDomElement createGroup(QString id); void setHeight(int, QString); void setWidth(int, QString); void setViewBox(int, int, int, int); void save(QString fileName); }; #endif fritzing-app-0.9.2b/src/partseditor/obsolete/svgview.cpp000066400000000000000000000143101250202676700234450ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "svgview.h" #include // SVGView::SVGView(const QString &name, QWidget *parent) : QFrame(parent) { setFrameStyle(Sunken | StyledPanel); m_graphicsView = new QGraphicsView; m_graphicsView->setRenderHint(QPainter::Antialiasing, true); m_graphicsView->setDragMode(QGraphicsView::RubberBandDrag); m_graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); QSize iconSize(size, size); m_domDocument = new QDomDocument; m_zoom = 1; m_rotation = 0; QToolButton *zoomInIcon = new QToolButton; zoomInIcon->setAutoRepeat(true); zoomInIcon->setAutoRepeatInterval(33); zoomInIcon->setAutoRepeatDelay(0); zoomInIcon->setIcon(QPixmap(":/zoomin.png")); zoomInIcon->setIconSize(iconSize); QToolButton *zoomOutIcon = new QToolButton; zoomOutIcon->setAutoRepeat(true); zoomOutIcon->setAutoRepeatInterval(33); zoomOutIcon->setAutoRepeatDelay(0); zoomOutIcon->setIcon(QPixmap(":/zoomout.png")); zoomOutIcon->setIconSize(iconSize); QToolButton *rotateLeftIcon = new QToolButton; rotateLeftIcon->setIcon(QPixmap(":/rotateleft.png")); rotateLeftIcon->setIconSize(iconSize); QToolButton *rotateRightIcon = new QToolButton; rotateRightIcon->setIcon(QPixmap(":/rotateright.png")); rotateRightIcon->setIconSize(iconSize); // Label layout QHBoxLayout *labelLayout = new QHBoxLayout; m_label = new QLabel(name); //TODO: put proper icons in here m_printButton = new QToolButton; m_printButton->setIcon(QIcon(QPixmap(":/resources/images/document-print.png"))); m_printButton->setText(tr("Print")); m_printButton->setToolTip(tr("Print")); m_loadPCBXMLButton = new QToolButton; m_loadPCBXMLButton->setIcon(QIcon(QPixmap(":/resources/images/applications-accessories.png"))); m_loadPCBXMLButton->setText(tr("Import XML")); m_loadPCBXMLButton->setToolTip(tr("Import XML")); labelLayout->addWidget(m_label); labelLayout->addStretch(); labelLayout->addWidget(m_printButton); labelLayout->addWidget(m_loadPCBXMLButton); QGridLayout *topLayout = new QGridLayout; topLayout->addLayout(labelLayout, 0, 0); topLayout->addWidget(m_graphicsView, 1, 0); setLayout(topLayout); connect(rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); connect(rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight())); connect(zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn())); connect(zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut())); connect(m_printButton, SIGNAL(clicked()), this, SLOT(print())); connect(m_loadPCBXMLButton, SIGNAL(clicked()), this, SLOT(importPCBXML())); setupMatrix(); } // void SVGView::importPCBXML(){ QString path = QFileDialog::getOpenFileName(this, tr("Select Footprint XML File"), "", tr("Fritzing Footprint XML Files (*.fzfp);;All Files (*)")); QFile file(path); if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), QObject::tr("Cannot read file %1:\n%2.") .arg(path) .arg(file.errorString())); } QString errorStr; int errorLine; int errorColumn; if (!m_domDocument->setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { QMessageBox::critical(NULL, QObject::tr("Fritzing"), QObject::tr("Parse error (3) at line %1, column %2:\n%3\n%4") .arg(errorLine) .arg(errorColumn) .arg(errorStr) .arg(path)); return; } QDomElement root = m_domDocument->documentElement(); if (root.isNull()) { QMessageBox::critical(NULL, QObject::tr("Fritzing"), QObject::tr("The file %1 is not a Fritzing file (12).").arg(path)); return; } if (root.tagName().toLower() != "element") { QMessageBox::critical(NULL, QObject::tr("Fritzing"), QObject::tr("The file %1 is not a Fritzing Footprint XML file.").arg(path)); return; } drawPCBXML(&root); } void SVGView::drawPCBXML(QDomElement * rootElement) { m_pcbXML = new PcbXML(*rootElement); m_pcbWidget = new QSvgWidget(m_pcbXML->getSvgFile()); m_scene.addWidget(m_pcbWidget); m_graphicsView->setScene(&m_scene); m_graphicsView->show(); //connect(pcbWidget, SIGNAL(repaintNeeded()), this, SLOT(pcbWidget->update())); } void SVGView::setupMatrix(){ // TODO: add support for scaling and rotation QMatrix matrix; matrix.scale(qreal(1), qreal(1)); matrix.rotate(m_rotation); m_graphicsView->setMatrix(matrix); } QGraphicsView *SVGView::view() const { return m_graphicsView; } void SVGView::print() { #ifndef QT_NO_PRINTER QPrinter printer; QPrintDialog dialog(&printer, this); if (dialog.exec() == QDialog::Accepted) { QPainter painter(&printer); m_graphicsView->render(&painter); } #endif } void SVGView::zoomIn() { m_zoom++; //zoomSlider->setValue(zoomSlider->value() + 1); } void SVGView::zoomOut() { m_zoom--; //zoomSlider->setValue(zoomSlider->value() - 1); } void SVGView::rotateRight(){ } void SVGView::rotateLeft(){ } fritzing-app-0.9.2b/src/partseditor/obsolete/svgview.h000066400000000000000000000040601250202676700231130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVGVIEW_H #define SVGVIEW_H // #include #include #include #include #include #include "pcbxml.h" QT_FORWARD_DECLARE_CLASS(QGraphicsView) QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QSlider) QT_FORWARD_DECLARE_CLASS(QToolButton) class SVGView : public QFrame { Q_OBJECT public: SVGView(const QString &name, QWidget *parent = 0); QGraphicsView *view() const; private slots: void print(); void importPCBXML(); void zoomIn(); void zoomOut(); void rotateLeft(); void rotateRight(); private: QGraphicsView *m_graphicsView; QLabel *m_label; QToolButton *m_printButton; QToolButton *m_loadPCBXMLButton; QSvgRenderer *m_renderer; QSvgWidget *m_pcbWidget; PcbXML *m_pcbXML; QGraphicsScene m_scene; QDomDocument *m_domDocument; // footprint xml file // graphics layers (svg groups really) qreal m_zoom; qreal m_rotation; void setupMatrix(); void drawPCBXML(QDomElement * pcbDocument); }; #endif fritzing-app-0.9.2b/src/partseditor/pecommands.cpp000066400000000000000000000262301250202676700222710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "pecommands.h" #include "pemainwindow.h" #include "../debugdialog.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// PEBaseCommand::PEBaseCommand(PEMainWindow * peMainWindow, QUndoCommand *parent) : BaseCommand(BaseCommand::CrossView, NULL, parent) { m_peMainWindow = peMainWindow; } PEBaseCommand::~PEBaseCommand() { } QString PEBaseCommand::getParamString() const { return ""; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeMetadataCommand::ChangeMetadataCommand(PEMainWindow * peMainWindow, const QString & name, const QString & oldValue, const QString & newValue, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_name = name; m_oldValue = oldValue; m_newValue = newValue; } void ChangeMetadataCommand::undo() { m_peMainWindow->changeMetadata(m_name, m_oldValue, true); } void ChangeMetadataCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { m_peMainWindow->changeMetadata(m_name, m_newValue, true); } } QString ChangeMetadataCommand::getParamString() const { return "ChangeMetadataCommand " + QString(" name:%1, old:%2, new:%3") .arg(m_name) .arg(m_oldValue) .arg(m_newValue) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeTagsCommand::ChangeTagsCommand(PEMainWindow * peMainWindow, const QStringList & oldTags, const QStringList & newTags, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_old = oldTags; m_new = newTags; } void ChangeTagsCommand::undo() { m_peMainWindow->changeTags(m_old, true); } void ChangeTagsCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { m_peMainWindow->changeTags(m_new, true); } } QString ChangeTagsCommand::getParamString() const { return "ChangeTagsCommand " + QString(" old:%1, new:%2") .arg(m_old.count()) .arg(m_new.count()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangePropertiesCommand::ChangePropertiesCommand(PEMainWindow * peMainWindow, const QHash & oldProps, const QHash & newProps, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_old = oldProps; m_new = newProps; } void ChangePropertiesCommand::undo() { m_peMainWindow->changeProperties(m_old, true); } void ChangePropertiesCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { m_peMainWindow->changeProperties(m_new, true); } } QString ChangePropertiesCommand::getParamString() const { return "ChangePropertiesCommand " + QString(" old:%1, new:%2") .arg(m_old.count()) .arg(m_new.count()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeConnectorMetadataCommand::ChangeConnectorMetadataCommand(PEMainWindow * peMainWindow, ConnectorMetadata * oldValue, ConnectorMetadata * newValue, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_oldcm = *oldValue; m_newcm = *newValue; } void ChangeConnectorMetadataCommand::undo() { m_peMainWindow->changeConnectorMetadata(&m_oldcm, true); } void ChangeConnectorMetadataCommand::redo() { if (m_skipFirstRedo) { m_skipFirstRedo = false; } else { m_peMainWindow->changeConnectorMetadata(&m_newcm, true); } } QString ChangeConnectorMetadataCommand::getParamString() const { return "ChangeConnectorMetadataCommand " + QString(" name:%1, old:%2, new:%3") .arg(m_oldcm.connectorName) .arg(m_newcm.connectorName) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeFzpCommand::ChangeFzpCommand(PEMainWindow * peMainWindow, const QString & oldFzpFile, const QString & newFzpFile, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_oldFzpFile = oldFzpFile; m_newFzpFile = newFzpFile; } void ChangeFzpCommand::undo() { if (!m_redoOnly) { m_peMainWindow->restoreFzp(m_oldFzpFile); } } void ChangeFzpCommand::redo() { if (!m_undoOnly) { m_peMainWindow->restoreFzp(m_newFzpFile); } } QString ChangeFzpCommand::getParamString() const { return "ChangeFzpCommand " + QString(" old:%1 new:%2") .arg(m_oldFzpFile) .arg(m_newFzpFile) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeSvgCommand::ChangeSvgCommand(PEMainWindow * peMainWindow, SketchWidget * sketchWidget, const QString & oldFilename, const QString & newFilename, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_sketchWidget = sketchWidget; m_oldFilename = oldFilename; m_newFilename = newFilename; } void ChangeSvgCommand::undo() { m_peMainWindow->changeSvg(m_sketchWidget, m_oldFilename, -1); } void ChangeSvgCommand::redo() { m_peMainWindow->changeSvg(m_sketchWidget, m_newFilename, 1); } QString ChangeSvgCommand::getParamString() const { return "ChangeSvgCommand " + QString(" id:%1, old:%2, new:%3") .arg(m_sketchWidget->viewID()) .arg(m_oldFilename) .arg(m_newFilename) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// RelocateConnectorSvgCommand::RelocateConnectorSvgCommand(PEMainWindow * peMainWindow, SketchWidget * sketchWidget, const QString & id, const QString & terminalID, const QString & oldGorn, const QString & oldGornTerminal, const QString & newGorn, const QString & newGornTerminal, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_sketchWidget = sketchWidget; m_id = id; m_terminalID = terminalID; m_oldGorn = oldGorn; m_oldGornTerminal = oldGornTerminal; m_newGorn = newGorn; m_newGornTerminal = newGornTerminal; } void RelocateConnectorSvgCommand::undo() { m_peMainWindow->relocateConnectorSvg(m_sketchWidget, m_id, m_terminalID, m_newGorn, m_newGornTerminal, m_oldGorn, m_oldGornTerminal, -1); } void RelocateConnectorSvgCommand::redo() { m_peMainWindow->relocateConnectorSvg(m_sketchWidget, m_id, m_terminalID, m_oldGorn, m_oldGornTerminal, m_newGorn, m_newGornTerminal, 1); } QString RelocateConnectorSvgCommand::getParamString() const { return "RelocateConnectorSvgCommand " + QString(" vid:%1 id:%2, terminalid:%3, oldgorn:%4, oldgornterminal:%5, newgorn:%6, newgornterminal:%7") .arg(m_sketchWidget->viewID()) .arg(m_id) .arg(m_terminalID) .arg(m_oldGorn) .arg(m_oldGornTerminal) .arg(m_newGorn) .arg(m_newGornTerminal) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// MoveTerminalPointCommand::MoveTerminalPointCommand(PEMainWindow * peMainWindow, SketchWidget * sketchWidget, const QString & id, QSizeF size, QPointF oldLocation, QPointF newLocation, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_sketchWidget = sketchWidget; m_id = id; m_size = size; m_oldLocation = oldLocation; m_newLocation = newLocation; } void MoveTerminalPointCommand::undo() { m_peMainWindow->moveTerminalPoint(m_sketchWidget, m_id, m_size, m_oldLocation, -1); } void MoveTerminalPointCommand::redo() { m_peMainWindow->moveTerminalPoint(m_sketchWidget, m_id, m_size, m_newLocation, 1); } QString MoveTerminalPointCommand::getParamString() const { return "RelocateConnectorSvgCommand " + QString(" vid:%1, id:%2, old:%3,%4, new:%5,%6") .arg(m_sketchWidget->viewID()) .arg(m_id) .arg(m_oldLocation.x()) .arg(m_oldLocation.y()) .arg(m_newLocation.x()) .arg(m_newLocation.y()) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// RemoveBusConnectorCommand::RemoveBusConnectorCommand(PEMainWindow * peMainWindow, const QString & busID, const QString & connectorID, bool inverted, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_busID = busID; m_connectorID = connectorID; m_inverted = inverted; } void RemoveBusConnectorCommand::undo() { if (m_inverted) m_peMainWindow->removeBusConnector(m_busID, m_connectorID, true); else m_peMainWindow->addBusConnector(m_busID, m_connectorID); } void RemoveBusConnectorCommand::redo() { if (m_inverted) m_peMainWindow->addBusConnector(m_busID, m_connectorID); else m_peMainWindow->removeBusConnector(m_busID, m_connectorID, true); } QString RemoveBusConnectorCommand::getParamString() const { return "RemoveBusConnectorCommand " + QString(" busID:%1, connectorID:%2 inv:%3") .arg(m_busID) .arg(m_connectorID) .arg(m_inverted); ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ChangeSMDCommand::ChangeSMDCommand(PEMainWindow * peMainWindow, const QString & before, const QString & after, const QString & oldFilename, const QString & newFilename, QUndoCommand *parent) : PEBaseCommand(peMainWindow, parent) { m_before = before; m_after = after; m_oldFilename = oldFilename; m_newFilename = newFilename; } void ChangeSMDCommand::undo() { m_peMainWindow->changeSMD(m_before, m_oldFilename, -1); } void ChangeSMDCommand::redo() { m_peMainWindow->changeSMD(m_after, m_newFilename, 1); } QString ChangeSMDCommand::getParamString() const { return "ChangeSMDCommand " + QString(" before:%1, after:%2 oldpath:%3, newPath:%4, oldorig:%5, neworig:%6") .arg(m_before) .arg(m_after) .arg(m_oldFilename) .arg(m_newFilename) ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// fritzing-app-0.9.2b/src/partseditor/pecommands.h000066400000000000000000000130531250202676700217350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify\ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6570 $: $Author: irascibl@gmail.com $: $Date: 2012-10-16 06:25:29 +0200 (Di, 16. Okt 2012) $ ********************************************************************/ #ifndef PECOMMANDS_H #define PECOMMANDS_H #include "../commands.h" #include "peutils.h" ///////////////////////////////////////////// class PEBaseCommand : public BaseCommand { public: PEBaseCommand(class PEMainWindow *, QUndoCommand* parent); ~PEBaseCommand(); QString getParamString() const; protected: class PEMainWindow * m_peMainWindow; }; ///////////////////////////////////////////// class ChangeMetadataCommand : public PEBaseCommand { public: ChangeMetadataCommand(class PEMainWindow *, const QString & name, const QString & oldValue, const QString & newValue, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_name; QString m_oldValue; QString m_newValue; }; ///////////////////////////////////////////// class ChangeConnectorMetadataCommand : public PEBaseCommand { public: ChangeConnectorMetadataCommand(class PEMainWindow *, ConnectorMetadata * oldcm, ConnectorMetadata * newcm, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: ConnectorMetadata m_oldcm; ConnectorMetadata m_newcm; }; ///////////////////////////////////////////// class ChangeFzpCommand : public PEBaseCommand { public: ChangeFzpCommand(class PEMainWindow *, const QString & oldFzpFile, const QString & newFzpFile, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_oldFzpFile; QString m_newFzpFile; }; ///////////////////////////////////////////// class ChangeTagsCommand : public PEBaseCommand { public: ChangeTagsCommand(class PEMainWindow *, const QStringList & oldTabs, const QStringList & newTags, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QStringList m_old; QStringList m_new; }; ///////////////////////////////////////////// class ChangePropertiesCommand : public PEBaseCommand { public: ChangePropertiesCommand(class PEMainWindow *, const QHash & oldProps, const QHash & newProps, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QHash m_old; QHash m_new; }; ///////////////////////////////////////////// class ChangeSvgCommand : public PEBaseCommand { public: ChangeSvgCommand(class PEMainWindow *, SketchWidget *, const QString & oldFilename, const QString & newFilename, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_oldFilename; QString m_newFilename; }; ///////////////////////////////////////////// class RelocateConnectorSvgCommand : public PEBaseCommand { public: RelocateConnectorSvgCommand(class PEMainWindow *, SketchWidget *, const QString & id, const QString & terminalID, const QString & oldGorn, const QString & oldGornTerminal, const QString & newGorn, const QString & newGornTerminal, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_id; QString m_terminalID; QString m_oldGorn; QString m_oldGornTerminal; QString m_newGorn; QString m_newGornTerminal; }; ///////////////////////////////////////////// class MoveTerminalPointCommand : public PEBaseCommand { public: MoveTerminalPointCommand(class PEMainWindow *, SketchWidget *, const QString & id, QSizeF size, QPointF oldLocation, QPointF newLocation, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_id; QSizeF m_size; QPointF m_oldLocation; QPointF m_newLocation; }; ///////////////////////////////////////////// class RemoveBusConnectorCommand : public PEBaseCommand { public: RemoveBusConnectorCommand(class PEMainWindow *, const QString & busID, const QString & connectorID, bool inverted, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_busID; QString m_connectorID; bool m_inverted; }; ///////////////////////////////////////////// class ChangeSMDCommand : public PEBaseCommand { public: ChangeSMDCommand(class PEMainWindow *, const QString & before, const QString & after, const QString & oldFilename, const QString & newFilename, QUndoCommand *parent); void undo(); void redo(); protected: QString getParamString() const; protected: QString m_before; QString m_after; QString m_oldFilename; QString m_newFilename; }; ///////////////////////////////////////////// #endif // PECOMMANDS_H fritzing-app-0.9.2b/src/partseditor/peconnectorsview.cpp000066400000000000000000000206711250202676700235430ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include "peconnectorsview.h" #include "peutils.h" #include "hashpopulatewidget.h" #include "../debugdialog.h" ////////////////////////////////////// PEConnectorsView::PEConnectorsView(QWidget * parent) : QFrame(parent) { m_connectorCount = 0; this -> setObjectName("peConnectors"); /* QFile styleSheet(":/resources/styles/newpartseditor.qss"); if (!styleSheet.open(QIODevice::ReadOnly)) { DebugDialog::debug("Unable to open :/resources/styles/newpartseditor.qss"); } else { this->setStyleSheet(styleSheet.readAll()); } */ QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->setSizeConstraint( QLayout::SetMinAndMaxSize ); QLabel *explanation = new QLabel(tr("This is where you edit the connector metadata for the part")); mainLayout->addWidget(explanation); QFrame * numberFrame = new QFrame(); QHBoxLayout * numberLayout = new QHBoxLayout(); QLabel * label = new QLabel(tr("number of connectors:")); numberLayout->addWidget(label); m_numberEdit = new QLineEdit(); QValidator *validator = new QIntValidator(1, 999, this); m_numberEdit->setValidator(validator); numberLayout->addWidget(m_numberEdit); connect(m_numberEdit, SIGNAL(editingFinished()), this, SLOT(connectorCountEntry())); numberLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); numberFrame->setLayout(numberLayout); mainLayout->addWidget(numberFrame); QFrame * typeFrame = new QFrame(); QHBoxLayout * typeLayout = new QHBoxLayout(); label = new QLabel(QObject::tr("Set all to:")); label->setObjectName("NewPartsEditorLabel"); typeLayout->addWidget(label); m_radios.clear(); QRadioButton * radioButton = new QRadioButton(MaleSymbolString); QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); radioButton->setProperty("value", Connector::Male); typeLayout->addWidget(radioButton); m_radios.append(radioButton); radioButton = new QRadioButton(FemaleSymbolString); QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); radioButton->setProperty("value", Connector::Female); typeLayout->addWidget(radioButton); m_radios.append(radioButton); radioButton = new QRadioButton(QObject::tr("Pad")); QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); radioButton->setProperty("value", Connector::Pad); typeLayout->addWidget(radioButton); m_radios.append(radioButton); typeLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); typeFrame->setLayout(typeLayout); mainLayout->addWidget(typeFrame); QFrame * smdFrame = new QFrame(); QHBoxLayout * smdLayout = new QHBoxLayout(); m_tht = new QRadioButton(tr("Through-hole")); QObject::connect(m_tht, SIGNAL(clicked()), this, SLOT(smdEntry())); m_tht->setObjectName("NewPartsEditorRadio"); smdLayout->addWidget(m_tht); m_smd = new QRadioButton(tr("SMD")); QObject::connect(m_smd, SIGNAL(clicked()), this, SLOT(smdEntry())); m_smd->setObjectName("NewPartsEditorRadio"); smdLayout->addWidget(m_smd); smdLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); smdFrame->setLayout(smdLayout); mainLayout->addWidget(smdFrame); m_scrollArea = new QScrollArea; m_scrollArea->setWidgetResizable(true); m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_scrollFrame = new QFrame; m_scrollArea->setWidget(m_scrollFrame); mainLayout->addWidget(m_scrollArea); this->setLayout(mainLayout); } PEConnectorsView::~PEConnectorsView() { } void PEConnectorsView::initConnectors(QList * connectorList) { QWidget * widget = QApplication::focusWidget(); if (widget) { QList children = m_scrollFrame->findChildren(); if (children.contains(widget)) { widget->blockSignals(true); } } if (m_scrollFrame) { m_scrollArea->setWidget(NULL); delete m_scrollFrame; m_scrollFrame = NULL; } m_connectorCount = connectorList->size(); m_numberEdit->setText(QString::number(m_connectorCount)); m_scrollFrame = new QFrame(this); m_scrollFrame->setObjectName("NewPartsEditorConnectors"); QVBoxLayout *scrollLayout = new QVBoxLayout(); int ix = 0; foreach (QDomElement connector, *connectorList) { QWidget * widget = PEUtils::makeConnectorForm(connector, ix++, this, true); scrollLayout->addWidget(widget); } scrollLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); m_scrollFrame->setLayout(scrollLayout); m_scrollArea->setWidget(m_scrollFrame); } void PEConnectorsView::nameEntry() { QLineEdit * lineEdit = qobject_cast(sender()); if (lineEdit != NULL && lineEdit->isModified()) { changeConnector(); lineEdit->setModified(false); } } void PEConnectorsView::typeEntry() { changeConnector(); } void PEConnectorsView::descriptionEntry() { QLineEdit * lineEdit = qobject_cast(sender()); if (lineEdit != NULL && lineEdit->isModified()) { changeConnector(); lineEdit->setModified(false); } } void PEConnectorsView::connectorCountEntry() { if (!m_mutex.tryLock(1)) return; // need the mutex because multiple editingFinished() signals can be triggered more-or-less at once QLineEdit * lineEdit = qobject_cast(sender()); if (lineEdit != NULL && lineEdit->isModified()) { int newCount = lineEdit->text().toInt(); if (newCount != m_connectorCount) { m_connectorCount = newCount; emit connectorCountChanged(newCount); lineEdit->setModified(false); } } m_mutex.unlock(); } void PEConnectorsView::removeConnector() { bool ok; int senderIndex = sender()->property("index").toInt(&ok); if (!ok) return; ConnectorMetadata cmd; if (!PEUtils::fillInMetadata(senderIndex, m_scrollFrame, cmd)) return; QList cmdList; cmdList.append(&cmd); emit removedConnectors(cmdList); } void PEConnectorsView::changeConnector() { bool ok; int senderIndex = sender()->property("index").toInt(&ok); if (!ok) return; ConnectorMetadata cmd; if (!PEUtils::fillInMetadata(senderIndex, m_scrollFrame, cmd)) return; emit connectorMetadataChanged(&cmd); } void PEConnectorsView::allTypeEntry() { QRadioButton * radio = qobject_cast(sender()); if (radio == NULL) return; bool ok; Connector::ConnectorType ct = (Connector::ConnectorType) radio->property("value").toInt(&ok); if (!ok) return; emit connectorsTypeChanged(ct); QTimer::singleShot(10, this, SLOT(uncheckRadios())); } void PEConnectorsView::smdEntry() { QRadioButton * radio = qobject_cast(sender()); if (radio == NULL) return; emit smdChanged(radio == m_smd ? "smd" : "tht"); } void PEConnectorsView::uncheckRadios() { // this doesn't work because the buttons are "autoexclusive" foreach (QRadioButton * radio, m_radios) { radio->setChecked(false); } } void PEConnectorsView::setSMD(bool smd) { if (smd) m_smd->setChecked(true); else m_tht->setChecked(true); } fritzing-app-0.9.2b/src/partseditor/peconnectorsview.h000066400000000000000000000046641250202676700232140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6499 $: $Author: irascibl@gmail.com $: $Date: 2012-10-02 07:21:40 +0200 (Di, 02. Okt 2012) $ ********************************************************************/ #ifndef CONNECTORSVIEW_H #define CONNECTORSVIEW_H #include #include #include #include #include #include #include #include #include #include #include #include "../items/itembase.h" #include "../items/wire.h" #include "../connectors/connectoritem.h" #include "../connectors/connector.h" #include "../referencemodel/referencemodel.h" class PEConnectorsView : public QFrame { Q_OBJECT public: PEConnectorsView(QWidget * parent = 0); ~PEConnectorsView(); void initConnectors(QList * connectorList); bool anyModified(); void setSMD(bool); signals: void connectorMetadataChanged(struct ConnectorMetadata *); void removedConnectors(QList &); void connectorCountChanged(int); void connectorsTypeChanged(Connector::ConnectorType); void smdChanged(const QString &); protected slots: void nameEntry(); void descriptionEntry(); void typeEntry(); void connectorCountEntry(); void removeConnector(); void allTypeEntry(); void smdEntry(); void uncheckRadios(); protected: void changeConnector(); protected: QFrame * m_scrollFrame; QScrollArea * m_scrollArea; QLineEdit * m_numberEdit; int m_connectorCount; QMutex m_mutex; QList m_radios; QRadioButton * m_smd; QRadioButton * m_tht; }; #endif fritzing-app-0.9.2b/src/partseditor/pegraphicsitem.cpp000066400000000000000000000253401250202676700231500ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "pegraphicsitem.h" #include "../debugdialog.h" #include "../sketch/infographicsview.h" #include "../items/itembase.h" #include #include #include #include static QVector Dashes; static const int DashLength = 3; static bool ShiftDown = false; static QPointF OriginalShiftPos; static bool ShiftX = false; static bool ShiftY = false; static bool SpaceBarWasPressed = false; static const double MinMouseMove = 2; static const QColor NormalColor(0, 0, 255); static const QColor PickColor(255, 0, 255); //////////////////////////////////////////////// PEGraphicsItem::PEGraphicsItem(double x, double y, double w, double h, ItemBase * itemBase) : QGraphicsRectItem(x, y, w, h) { if (Dashes.isEmpty()) { Dashes << DashLength << DashLength; } m_itemBase = itemBase; m_pick = m_flash = false; m_terminalPoint = QPointF(w / 2, h / 2); m_dragTerminalPoint = m_showMarquee = m_showTerminalPoint = false; setAcceptedMouseButtons(Qt::LeftButton); setAcceptHoverEvents(true); //setFlag(QGraphicsItem::ItemIsSelectable, true ); setHighlighted(false); setBrush(QBrush(NormalColor)); } PEGraphicsItem::~PEGraphicsItem() { m_element.clear(); } void PEGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *) { m_wheelAccum = 0; setHighlighted(true); } void PEGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { setHighlighted(false); } void PEGraphicsItem::wheelEvent(QGraphicsSceneWheelEvent * event) { //DebugDialog::debug(QString("wheel %1 %2").arg(event->delta()).arg(event->orientation())); #ifndef Q_OS_MAC // qt 4.8.3: mac: event orientation is messed up at this point if (event->orientation() == Qt::Horizontal) return; #endif if (event->delta() == 0) return; if ((event->modifiers() & Qt::ShiftModifier) == 0) return; // delta one click forward = 120; delta one click backward = -120 int magDelta = qAbs(event->delta()); int sign = event->delta() / magDelta; int delta = sign * qMin(magDelta, 120); m_wheelAccum += delta; if (qAbs(m_wheelAccum) < 120) return; m_wheelAccum = 0; QList items; foreach (QGraphicsItem * item, scene()->items(event->scenePos())) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi) items.append(pegi); } if (items.count() < 2) return; int ix = -1; int mix = -1; for (int i = 0; i < items.count(); i++) { if (items.at(i)->highlighted()) { ix = i; break; } if (items.at(i) == this) { mix = i; } } if (ix == -1) ix = mix; if (ix == -1) { // shouldn't happen return; } ix += sign; // wrap //while (ix < 0) { // ix += items.count(); //} //ix = ix % items.count(); // don't wrap if (ix < 0) ix = 0; else if (ix >= items.count()) ix = items.count() - 1; PEGraphicsItem * theItem = items.at(ix); if (theItem->highlighted()) { theItem->flash(); } else { theItem->setHighlighted(true); } } void PEGraphicsItem::setHighlighted(bool highlighted) { if (highlighted) { m_highlighted = true; setOpacity(0.4); foreach (QGraphicsItem * item, scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) continue; if (pegi == this) continue; if (!pegi->highlighted()) continue; pegi->setHighlighted(false); } emit highlightSignal(this); } else { m_highlighted = false; setOpacity(0.001); } update(); } bool PEGraphicsItem::highlighted() { return m_highlighted; } void PEGraphicsItem::setElement(QDomElement & el) { m_element = el; } QDomElement & PEGraphicsItem::element() { return m_element; } void PEGraphicsItem::setOffset(QPointF p) { m_offset = p; } QPointF PEGraphicsItem::offset() { return m_offset; } void PEGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QGraphicsRectItem::paint(painter, option, widget); if (m_flash) { m_flash = false; QTimer::singleShot(40, this, SLOT(restoreColor())); } bool save = m_showTerminalPoint || m_showMarquee; if (save) painter->save(); if (m_showTerminalPoint) { QRectF r = rect(); QLineF l1(0, m_terminalPoint.y(), r.width(), m_terminalPoint.y()); QLineF l2(m_terminalPoint.x(), 0, m_terminalPoint.x(), r.height()); painter->setOpacity(1.0); painter->setPen(QPen(QColor(0, 0, 0), 0, Qt::SolidLine)); painter->setBrush(Qt::NoBrush); painter->drawLine(l1); painter->drawLine(l2); painter->setPen(QPen(QColor(255, 255, 255), 0, Qt::DashLine)); painter->setBrush(Qt::NoBrush); painter->drawLine(l1); painter->drawLine(l2); } if (m_showMarquee) { QRectF r = rect(); double d = qMin(r.width(), r.height()) / 16; r.adjust(d, d, -d, -d); painter->setOpacity(1.0); painter->setPen(QPen(QColor(0, 0, 0), 0, Qt::SolidLine)); painter->setBrush(Qt::NoBrush); painter->drawRect(r); painter->setPen(QPen(QColor(255, 255, 255), 0, Qt::DashLine)); painter->setBrush(Qt::NoBrush); painter->drawRect(r); } if (save) painter->restore(); } void PEGraphicsItem::showTerminalPoint(bool show) { m_showTerminalPoint = show; update(); } bool PEGraphicsItem::showingTerminalPoint() { return m_showTerminalPoint; } void PEGraphicsItem::showMarquee(bool show) { if (show) { m_showMarquee = true; foreach (QGraphicsItem * item, scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) continue; if (pegi == this) continue; if (!pegi->showingMarquee()) continue; pegi->showMarquee(false); } } else { m_showMarquee = false; } update(); } bool PEGraphicsItem::showingMarquee() { return m_showMarquee; } void PEGraphicsItem::setTerminalPoint(QPointF p) { m_pendingTerminalPoint = m_terminalPoint = p; } QPointF PEGraphicsItem::terminalPoint() { return m_terminalPoint; } void PEGraphicsItem::setPendingTerminalPoint(QPointF p) { m_pendingTerminalPoint = p; } QPointF PEGraphicsItem::pendingTerminalPoint() { return m_pendingTerminalPoint; } void PEGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event) { m_dragTerminalPoint = false; if (!m_highlighted) { // allows to click through to next layer event->ignore(); return; } if (!event->buttons() && Qt::LeftButton) { event->ignore(); return; } InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this); if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) { event->ignore(); return; } bool ignore; emit mousePressedSignal(this, ignore); if (ignore) { event->ignore(); return; } if (m_showMarquee) { QPointF p = event->pos(); if (event->modifiers() & Qt::ShiftModifier) { ShiftDown = true; ShiftX = ShiftY = false; OriginalShiftPos = p; } if (qAbs(p.x() - m_terminalPoint.x()) <= MinMouseMove && qAbs(p.y() - m_terminalPoint.y()) <= MinMouseMove) { m_dragTerminalPoint = true; m_terminalPointOrigin = m_terminalPoint; m_dragTerminalOrigin = event->pos(); } return; } event->ignore(); } void PEGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { if (!m_dragTerminalPoint) return; if (ShiftDown && !(event->modifiers() & Qt::ShiftModifier)) { ShiftDown = false; } QPointF p = event->pos(); if (ShiftDown) { if (ShiftX) { // moving along x, constrain y p.setY(OriginalShiftPos.y()); } else if (ShiftY) { // moving along y, constrain x p.setX(OriginalShiftPos.x()); } else { double dx = qAbs(p.x() - OriginalShiftPos.x()); double dy = qAbs(p.y() - OriginalShiftPos.y()); if (dx - dy > MinMouseMove) { ShiftX = true; } else if (dy - dx > MinMouseMove) { ShiftY = true; } } } else if (event->modifiers() & Qt::ShiftModifier) { ShiftDown = true; ShiftX = ShiftY = false; OriginalShiftPos = event->pos(); } QPointF newTerminalPoint = m_terminalPointOrigin + p - m_dragTerminalOrigin; if (newTerminalPoint.x() < 0) newTerminalPoint.setX(0); else if (newTerminalPoint.x() > rect().width()) newTerminalPoint.setX(rect().width()); if (newTerminalPoint.y() < 0) newTerminalPoint.setY(0); else if (newTerminalPoint.y() > rect().height()) newTerminalPoint.setY(rect().height()); m_terminalPoint = newTerminalPoint; emit terminalPointMoved(this, newTerminalPoint); update(); } void PEGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *) { if (m_dragTerminalPoint) { m_dragTerminalPoint = false; if (m_terminalPointOrigin != m_terminalPoint) { emit terminalPointChanged(this, m_terminalPointOrigin, m_terminalPoint); } } else { // relocate the connector emit mouseReleasedSignal(this); } } void PEGraphicsItem::setPickAppearance(bool pick) { m_pick = pick; setBrush(pick ? PickColor : NormalColor); } void PEGraphicsItem::flash() { m_savedOpacity = opacity(); m_flash = true; setBrush(QColor(255, 255, 255)); update(); } void PEGraphicsItem::restoreColor() { setBrush(m_pick ? PickColor : NormalColor); setOpacity(m_savedOpacity); update(); } ItemBase * PEGraphicsItem::itemBase() { return m_itemBase; } fritzing-app-0.9.2b/src/partseditor/pegraphicsitem.h000066400000000000000000000061571250202676700226220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PEGRAPHICSITEM_H_ #define PEGRAPHICSITEM_H_ #include #include #include #include #include #include #include class PEGraphicsItem : public QObject, public QGraphicsRectItem { Q_OBJECT public: PEGraphicsItem(double x, double y, double width, double height, class ItemBase *); ~PEGraphicsItem(); void hoverEnterEvent(QGraphicsSceneHoverEvent *); void hoverLeaveEvent(QGraphicsSceneHoverEvent *); void wheelEvent(QGraphicsSceneWheelEvent *); void mousePressEvent(QGraphicsSceneMouseEvent *); void mouseMoveEvent(QGraphicsSceneMouseEvent *); void mouseReleaseEvent(QGraphicsSceneMouseEvent *); void setHighlighted(bool); bool highlighted(); void setElement(QDomElement &); QDomElement & element(); void setOffset(QPointF); QPointF offset(); void showTerminalPoint(bool); bool showingTerminalPoint(); void showMarquee(bool); bool showingMarquee(); void setTerminalPoint(QPointF); QPointF terminalPoint(); void setPendingTerminalPoint(QPointF); QPointF pendingTerminalPoint(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setPickAppearance(bool); void flash(); class ItemBase * itemBase(); signals: void highlightSignal(PEGraphicsItem *); void mousePressedSignal(PEGraphicsItem *, bool & ignore); void mouseReleasedSignal(PEGraphicsItem *); void terminalPointMoved(PEGraphicsItem *, QPointF); void terminalPointChanged(PEGraphicsItem *, QPointF before, QPointF after); protected slots: void restoreColor(); protected: bool m_highlighted; bool m_flash; QDomElement m_element; QPointF m_offset; bool m_showTerminalPoint; bool m_showMarquee; QPointF m_terminalPoint; QPointF m_pendingTerminalPoint; bool m_dragTerminalPoint; QPointF m_dragTerminalOrigin; QPointF m_terminalPointOrigin; bool m_drawHighlight; int m_wheelAccum; qreal m_savedOpacity; bool m_pick; class ItemBase * m_itemBase; }; #endif /* PEGRAPHICSITEM_H_ */ fritzing-app-0.9.2b/src/partseditor/pemainwindow.cpp000066400000000000000000004155271250202676700226570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ /* TO DO ****************************************** ///////////////////////////////// first release /////////////////////////////// clicking set bus mode fucks up anchor points terminal point area is not highlighting properly ////////////////////// second release ///////////////////////////////// icon editor? need simplified infoview change color of breadboard text item for svg import check for flaws: multiple connector or terminal ids trash any other matching id loading tht into smd or v.v. can't seem to assign connectors after adding connectors why isn't swapping available when a family has new parts with multiple variant values? test button with export etchable to make sure the part is right? export etchable is disabled without a board align to grid when moving? restore editable pin labels functionality requires storing labels in the part rather than in the sketch hidden connectors allow multiple hits to the same place and add copies of the svg element if necessary restore parts bin buses secondary representation (list view) display during bus mode instead of connector list allow to delete bus, delete nodemember, add nodemember using right-click for now use the actual svg shape instead of rectangles construct a new svg with the width and height of the bounding box of the element translate the element by the current top-left of the element set the fill color and kill the stroke width properties and tags entries allow duplicates delete temp files after crash show in OS button only shows folder and not file in linux smd vs. tht after it's all over remove copper0 if part is all smd split copper0 and copper1 allow mixed tht/smd parts in fritzing but for now disable flipsmd allow smd with holes to flip? import kicad sch files? kicad schematic does not match our schematic on svg import detect all connector IDs if any are invisible, tell user this is obsolete sort connector list alphabetically or numerically? full svg outline view bendable legs same as terminalID, but must be a line use a radio buttons to distinguish? set flippable connector duplicate op add layers: put everything in silkscreen, then give copper1, copper0 checkbox what about breadboardbreadboard or other odd layers? if you click something as a connector, automatically move it into copper how to distinguish between both and top--default to both, let user set "pad" setting layer for top level group sets all children? swap connector metadata op delete op move connectors with arrow keys, or typed coordinates drag and drop later import eagle lbr eagle brd for schematic view offer lines-or-pins, rects, and a selection of standard schematic icons in the parts bin for breadboard view import generate ICs, dips, sips, breakouts for pcb view pads, pins (circle, rect, oblong), holes lines and curves? import silkscreen hybrids flip and rotate images w/in the view? taxonomy entry like tag entry? new schematic layout specs give users a family popup with all family names ditto for other properties matrix problem with move and duplicate (i.e. if element inherits a matrix from far above) even a problem when inserting hole, pad, or pin eliminate internal transforms, then insert inverted matrix, then use untransformed coords based on viewbox ***************************************************/ #include "pemainwindow.h" #include "pemetadataview.h" #include "peconnectorsview.h" #include "pecommands.h" #include "petoolview.h" #include "pesvgview.h" #include "pegraphicsitem.h" #include "kicadmoduledialog.h" #include "../debugdialog.h" #include "../sketch/breadboardsketchwidget.h" #include "../sketch/schematicsketchwidget.h" #include "../sketch/pcbsketchwidget.h" #include "../mainwindow/sketchareawidget.h" #include "../referencemodel/referencemodel.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/folderutils.h" #include "../utils/s2s.h" #include "../mainwindow/fdockwidget.h" #include "../fsvgrenderer.h" #include "../partsbinpalette/binmanager/binmanager.h" #include "../svg/gedaelement2svg.h" #include "../svg/kicadmodule2svg.h" #include "../svg/kicadschematic2svg.h" #include "../sketchtoolbutton.h" #include "../items/virtualwire.h" #include "../connectors/connectoritem.h" #include "../connectors/bus.h" #include "../installedfonts.h" #include "../dock/layerpalette.h" #include "../utils/cursormaster.h" #include "../infoview/htmlinfoview.h" #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////// static bool RubberBandLegWarning = false; static bool GotZeroConnector = false; static const QString ReferenceFileString("referenceFile"); static const int IconViewIndex = 3; static const int MetadataViewIndex = 4; static const int ConnectorsViewIndex = 5; const static int PegiZ = 5000; const static int RatZ = 6000; static long FakeGornSiblingNumber = 0; void removeGornAux(QDomElement & element) { bool hasGorn = element.hasAttribute("gorn"); bool hasOld = element.hasAttribute("oldid"); if (hasGorn && hasOld) { element.removeAttribute("gorn"); QString oldid = element.attribute("oldid"); if (oldid.isEmpty()) element.removeAttribute("id"); else element.setAttribute("id", oldid); element.removeAttribute("oldid"); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { removeGornAux(child); child = child.nextSiblingElement(); } } QString removeGorn(QString & svg) { QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { // shouldn't happen DebugDialog::debug(QString("remove gorn failure: %1 %2 %3 %4").arg(errorStr).arg(errorLine).arg(errorColumn).arg(svg)); return svg; } QDomElement root = doc.documentElement(); removeGornAux(root); return doc.toString(4); } bool byID(QDomElement & c1, QDomElement & c2) { int c1id = -1; int c2id = -1; int ix = IntegerFinder.indexIn(c1.attribute("id")); if (ix >= 0) c1id = IntegerFinder.cap(0).toInt(); ix = IntegerFinder.indexIn(c2.attribute("id")); if (ix >= 0) c2id = IntegerFinder.cap(0).toInt(); if (c1id == 0 || c2id == 0) GotZeroConnector = true; return c1id <= c2id; } void removeID(QDomElement & root, const QString & value) { if (root.attribute("id") == value) { root.removeAttribute("id"); } QDomNodeList nodeList = root.childNodes(); for (int i = 0; i < nodeList.count(); i++) { QDomNode node = nodeList.item(i); if (node.nodeType() == QDomNode::ElementNode) { QDomElement element = node.toElement(); removeID(element, value); } } } //////////////////////////////////////////////////// IconSketchWidget::IconSketchWidget(ViewLayer::ViewID viewID, QWidget *parent) : SketchWidget(viewID, parent) { m_shortName = QObject::tr("ii"); m_viewName = QObject::tr("Icon View"); initBackgroundColor(); } void IconSketchWidget::addViewLayers() { setViewLayerIDs(ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon, ViewLayer::Icon); addViewLayersAux(ViewLayer::layersForView(ViewLayer::IconView), ViewLayer::layersForViewFromBelow(ViewLayer::IconView)); } //////////////////////////////////////////////////// ViewThing::ViewThing() { itemBase = NULL; document = NULL; svgChangeCount = 0; everZoomed = false; sketchWidget = NULL; firstTime = true; busMode = false; } ///////////////////////////////////////////////////// PEMainWindow::PEMainWindow(ReferenceModel * referenceModel, QWidget * parent) : MainWindow(referenceModel, parent) { m_viewThings.insert(ViewLayer::BreadboardView, new ViewThing); m_viewThings.insert(ViewLayer::SchematicView, new ViewThing); m_viewThings.insert(ViewLayer::PCBView, new ViewThing); m_viewThings.insert(ViewLayer::IconView, new ViewThing); m_useNextPick = m_inPickMode = false; m_autosaveTimer.stop(); disconnect(&m_autosaveTimer, SIGNAL(timeout()), this, SLOT(backupSketch())); m_gaveSaveWarning = m_canSave = false; m_settingsPrefix = "pe/"; m_guid = TextUtils::getRandText(); m_prefix = "prefix0000"; m_fileIndex = 0; m_userPartsFolderPath = FolderUtils::getUserDataStorePath("parts")+"/user/"; m_userPartsFolderSvgPath = FolderUtils::getUserDataStorePath("parts")+"/svg/user/"; m_peToolView = NULL; m_peSvgView = NULL; m_connectorsView = NULL; } PEMainWindow::~PEMainWindow() { // PEGraphicsItems are still holding QDomElement so delete them before m_fzpDocument is deleted killPegi(); // kill temp files foreach (QString string, m_filesToDelete) { QFile::remove(string); } QDir dir = QDir::temp(); dir.rmdir(makeDirName()); } void PEMainWindow::closeEvent(QCloseEvent *event) { qDebug() << "close event"; QStringList messages; if (m_inFocusWidgets.count() > 0) { bool gotOne = false; // should only be one in-focus widget foreach (QWidget * widget, m_inFocusWidgets) { QLineEdit * lineEdit = qobject_cast(widget); if (lineEdit) { if (lineEdit->isModified()) { lineEdit->clearFocus(); lineEdit->setModified(false); gotOne = true; } } else { QTextEdit * textEdit = qobject_cast(widget); if (textEdit) { if (textEdit->document()->isModified()) { textEdit->clearFocus(); textEdit->document()->setModified(false); gotOne = true; } } } } if (gotOne) { messages << tr("There is one last edit still pending."); } } QString family = m_metadataView->family(); if (family.isEmpty()) { messages << tr("The 'family' property can not be blank."); } QStringList keys = m_metadataView->properties().keys(); if (keys.contains("family", Qt::CaseInsensitive)) { messages << tr("A duplicate 'family' property is not allowed"); } if (keys.contains("variant", Qt::CaseInsensitive)) { messages << tr("A duplicate 'variant' property is not allowed"); } bool discard = true; if (messages.count() > 0) { QMessageBox messageBox(this); messageBox.setWindowTitle(tr("Close without saving?")); QString message = tr("This part can not be saved as-is:\n\n"); foreach (QString string, messages) { message.append('\t'); message.append(string); messages.append("\n\n"); } message += tr("Do you want to keep working or close without saving?"); messageBox.setText(message); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Cancel); messageBox.setIcon(QMessageBox::Warning); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Ok, tr("Close without saving")); messageBox.setButtonText(QMessageBox::Cancel, tr("Keep working")); QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec(); if (answer != QMessageBox::Ok) { event->ignore(); return; } } else if (!beforeClosing(true, discard)) { event->ignore(); return; } if (!discard) { // if all connectors not found, put up a message connectorWarning(); } QSettings settings; settings.setValue(m_settingsPrefix + "state", saveState()); settings.setValue(m_settingsPrefix + "geometry", saveGeometry()); QMainWindow::closeEvent(event); } void PEMainWindow::initLockedFiles(bool) { } void PEMainWindow::initSketchWidgets(bool whatever) { Q_UNUSED(whatever); MainWindow::initSketchWidgets(false); m_iconGraphicsView = new IconSketchWidget(ViewLayer::IconView, this); initSketchWidget(m_iconGraphicsView); m_iconWidget = new SketchAreaWidget(m_iconGraphicsView,this); addTab(m_iconWidget, tr("Icon")); initSketchWidget(m_iconGraphicsView); ViewThing * viewThing = m_viewThings.value(m_breadboardGraphicsView->viewID()); viewThing->sketchWidget = m_breadboardGraphicsView; viewThing->document = &m_breadboardDocument; viewThing = m_viewThings.value(m_schematicGraphicsView->viewID()); viewThing->sketchWidget = m_schematicGraphicsView; viewThing->document = &m_schematicDocument; viewThing = m_viewThings.value(m_pcbGraphicsView->viewID()); viewThing->sketchWidget = m_pcbGraphicsView; viewThing->document = &m_pcbDocument; viewThing = m_viewThings.value(m_iconGraphicsView->viewID()); viewThing->sketchWidget = m_iconGraphicsView; viewThing->document = &m_iconDocument; foreach (ViewThing * viewThing, m_viewThings.values()) { viewThing->sketchWidget->setAcceptWheelEvents(true); viewThing->sketchWidget->setChainDrag(false); // no bendpoints viewThing->firstTime = true; viewThing->everZoomed = true; connect(viewThing->sketchWidget, SIGNAL(newWireSignal(Wire *)), this, SLOT(newWireSlot(Wire *))); connect(viewThing->sketchWidget, SIGNAL(showing(SketchWidget *)), this, SLOT(showing(SketchWidget *))); connect(viewThing->sketchWidget, SIGNAL(itemMovedSignal(ItemBase *)), this, SLOT(itemMovedSlot(ItemBase *))); connect(viewThing->sketchWidget, SIGNAL(resizedSignal(ItemBase *)), this, SLOT(resizedSlot(ItemBase *))); connect(viewThing->sketchWidget, SIGNAL(clickedItemCandidateSignal(QGraphicsItem *, bool &)), this, SLOT(clickedItemCandidateSlot(QGraphicsItem *, bool &)), Qt::DirectConnection); connect(viewThing->sketchWidget, SIGNAL(itemAddedSignal(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *)), this, SLOT(itemAddedSlot(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *))); } m_metadataView = new PEMetadataView(this); SketchAreaWidget * sketchAreaWidget = new SketchAreaWidget(m_metadataView, this, false, false); addTab(sketchAreaWidget, tr("Metadata")); connect(m_metadataView, SIGNAL(metadataChanged(const QString &, const QString &)), this, SLOT(metadataChanged(const QString &, const QString &)), Qt::DirectConnection); connect(m_metadataView, SIGNAL(tagsChanged(const QStringList &)), this, SLOT(tagsChanged(const QStringList &)), Qt::DirectConnection); connect(m_metadataView, SIGNAL(propertiesChanged(const QHash &)), this, SLOT(propertiesChanged(const QHash &)), Qt::DirectConnection); m_connectorsView = new PEConnectorsView(this); sketchAreaWidget = new SketchAreaWidget(m_connectorsView, this, false, false); addTab(sketchAreaWidget, tr("Connectors")); connect(m_connectorsView, SIGNAL(connectorMetadataChanged(ConnectorMetadata *)), this, SLOT(connectorMetadataChanged(ConnectorMetadata *)), Qt::DirectConnection); connect(m_connectorsView, SIGNAL(connectorsTypeChanged(Connector::ConnectorType)), this, SLOT(connectorsTypeChanged(Connector::ConnectorType))); connect(m_connectorsView, SIGNAL(removedConnectors(QList &)), this, SLOT(removedConnectors(QList &)), Qt::DirectConnection); connect(m_connectorsView, SIGNAL(connectorCountChanged(int)), this, SLOT(connectorCountChanged(int)), Qt::DirectConnection); connect(m_connectorsView, SIGNAL(smdChanged(const QString &)), this, SLOT(smdChanged(const QString &))); } void PEMainWindow::initDock() { m_layerPalette = new LayerPalette(this); /* m_infoView = new HtmlInfoView(); m_infoView->init(true); m_binManager = new BinManager(m_referenceModel, m_infoView, m_undoStack, this); m_binManager->openBin(":/resources/bins/pe.fzb"); m_binManager->hideTabBar(); */ } void PEMainWindow::moreInitDock() { static int BinMinHeight = 75; static int ToolDefaultHeight = 150; static int SvgDefaultHeight = 50; m_peToolView = new PEToolView(); connect(m_peToolView, SIGNAL(getSpinAmount(double &)), this, SLOT(getSpinAmount(double &)), Qt::DirectConnection); connect(m_peToolView, SIGNAL(terminalPointChanged(const QString &)), this, SLOT(terminalPointChanged(const QString &))); connect(m_peToolView, SIGNAL(terminalPointChanged(const QString &, double)), this, SLOT(terminalPointChanged(const QString &, double))); connect(m_peToolView, SIGNAL(switchedConnector(int)), this, SLOT(switchedConnector(int))); connect(m_peToolView, SIGNAL(removedConnector(const QDomElement &)), this, SLOT(removedConnector(const QDomElement &))); connect(m_peToolView, SIGNAL(pickModeChanged(bool)), this, SLOT(pickModeChanged(bool))); connect(m_peToolView, SIGNAL(busModeChanged(bool)), this, SLOT(busModeChanged(bool))); connect(m_peToolView, SIGNAL(connectorMetadataChanged(ConnectorMetadata *)), this, SLOT(connectorMetadataChanged(ConnectorMetadata *)), Qt::DirectConnection); makeDock(tr("Connectors"), m_peToolView, DockMinWidth, ToolDefaultHeight); m_peToolView->setMinimumSize(DockMinWidth, ToolDefaultHeight); m_peSvgView = new PESvgView(); makeDock(tr("SVG"), m_peSvgView, DockMinWidth, SvgDefaultHeight); m_peSvgView->setMinimumSize(DockMinWidth, SvgDefaultHeight); if (m_binManager) { QDockWidget * dockWidget = makeDock(BinManager::Title, m_binManager, DockMinWidth, BinMinHeight); dockWidget->resize(0, 0); } if (m_infoView) { makeDock(tr("Inspector"), m_infoView, InfoViewMinHeight, InfoViewHeightDefault); this -> setObjectName("PEInspector"); } makeDock(tr("Layers"), m_layerPalette, DockMinWidth, DockMinHeight)->hide(); m_layerPalette->setMinimumSize(DockMinWidth, DockMinHeight); m_layerPalette->setShowAllLayersAction(m_showAllLayersAct); m_layerPalette->setHideAllLayersAction(m_hideAllLayersAct); } void PEMainWindow::createFileMenuActions() { MainWindow::createFileMenuActions(); m_reuseBreadboardAct = new QAction(tr("Reuse breadboard image"), this); m_reuseBreadboardAct->setStatusTip(tr("Reuse the breadboard image in this view")); connect(m_reuseBreadboardAct, SIGNAL(triggered()), this, SLOT(reuseBreadboard())); m_reuseSchematicAct = new QAction(tr("Reuse schematic image"), this); m_reuseSchematicAct->setStatusTip(tr("Reuse the schematic image in this view")); connect(m_reuseSchematicAct, SIGNAL(triggered()), this, SLOT(reuseSchematic())); m_reusePCBAct = new QAction(tr("Reuse PCB image"), this); m_reusePCBAct->setStatusTip(tr("Reuse the PCB image in this view")); connect(m_reusePCBAct, SIGNAL(triggered()), this, SLOT(reusePCB())); } void PEMainWindow::createActions() { createFileMenuActions(); m_openAct->setText(tr("Load image for view...")); m_openAct->setStatusTip(tr("Open a file to use as the image for this view of the part.")); disconnect(m_openAct, SIGNAL(triggered()), this, SLOT(mainLoad())); connect(m_openAct, SIGNAL(triggered()), this, SLOT(loadImage())); m_showInOSAct = new QAction(tr("Show in Folder"), this); m_showInOSAct->setStatusTip(tr("On the desktop, open the folder containing the current svg file.")); connect(m_showInOSAct, SIGNAL(triggered()), this, SLOT(showInOS())); createEditMenuActions(); m_convertToTenthAct = new QAction(tr("Convert schematic to 0.1 inch standard"), this); m_convertToTenthAct->setStatusTip(tr("Convert pre-0.8.6 schematic image to new 0.1 inch standard")); connect(m_convertToTenthAct, SIGNAL(triggered()), this, SLOT(convertToTenth())); m_deleteBusConnectionAct = new WireAction(tr("Remove Internal Connection"), this); connect(m_deleteBusConnectionAct, SIGNAL(triggered()), this, SLOT(deleteBusConnection())); createViewMenuActions(false); createHelpMenuActions(); createWindowMenuActions(); createActiveLayerActions(); } void PEMainWindow::createMenus() { createFileMenu(); createEditMenu(); createViewMenu(); createWindowMenu(); createHelpMenu(); } void PEMainWindow::createFileMenu() { m_fileMenu = menuBar()->addMenu(tr("&File")); m_fileMenu->addAction(m_openAct); m_fileMenu->addAction(m_reuseBreadboardAct); m_fileMenu->addAction(m_reuseSchematicAct); m_fileMenu->addAction(m_reusePCBAct); //m_fileMenu->addAction(m_revertAct); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_closeAct); m_fileMenu->addAction(m_saveAct); m_fileMenu->addAction(m_saveAsAct); m_saveAsAct->setText(tr("Save as new part")); m_saveAsAct->setStatusTip(tr("Make a copy of the part and save it in the 'My Parts' Bin")); m_fileMenu->addSeparator(); m_exportMenu = m_fileMenu->addMenu(tr("&Export")); //m_fileMenu->addAction(m_pageSetupAct); m_fileMenu->addAction(m_printAct); m_fileMenu->addAction(m_showInOSAct); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_quitAct); populateExportMenu(); connect(m_fileMenu, SIGNAL(aboutToShow()), this, SLOT(updateFileMenu())); } void PEMainWindow::createEditMenu() { m_editMenu = menuBar()->addMenu(tr("&Edit")); m_editMenu->addAction(m_undoAct); m_editMenu->addAction(m_redoAct); m_editMenu->addSeparator(); m_editMenu->addAction(m_convertToTenthAct); updateEditMenu(); connect(m_editMenu, SIGNAL(aboutToShow()), this, SLOT(updateEditMenu())); } QList PEMainWindow::getButtonsForView(ViewLayer::ViewID viewID) { QList retval; SketchAreaWidget *parent; switch(viewID) { case ViewLayer::BreadboardView: parent = m_breadboardWidget; break; case ViewLayer::SchematicView: parent = m_schematicWidget; break; case ViewLayer::PCBView: parent = m_pcbWidget; break; default: return retval; } //retval << createExportEtchableButton(parent); switch (viewID) { case ViewLayer::BreadboardView: break; case ViewLayer::SchematicView: break; case ViewLayer::PCBView: // retval << createActiveLayerButton(parent); break; default: break; } return retval; } bool PEMainWindow::activeLayerWidgetAlwaysOn() { return true; } void PEMainWindow::connectPairs() { bool succeeded = true; succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_breadboardGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_schematicGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_pcbGraphicsView, SLOT(spaceBarIsPressedSlot(bool))); succeeded = succeeded && connect(m_pcbGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); succeeded = succeeded && connect(m_breadboardGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); succeeded = succeeded && connect(m_schematicGraphicsView, SIGNAL(cursorLocationSignal(double, double, double, double)), this, SLOT(cursorLocationSlot(double, double, double, double))); connect(m_breadboardGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); connect(m_schematicGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); connect(m_pcbGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *))); } QMenu *PEMainWindow::breadboardWireMenu() { QMenu *menu = new QMenu(QObject::tr("Internal Connections"), this); menu->addAction(m_deleteBusConnectionAct); connect( menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu())); return menu; } QMenu *PEMainWindow::breadboardItemMenu() { return NULL; } QMenu *PEMainWindow::schematicWireMenu() { return breadboardWireMenu(); } QMenu *PEMainWindow::schematicItemMenu() { return NULL; } QMenu *PEMainWindow::pcbWireMenu() { return breadboardWireMenu(); } QMenu *PEMainWindow::pcbItemMenu() { return NULL; } bool PEMainWindow::setInitialItem(PaletteItem * paletteItem) { m_pcbGraphicsView->setBoardLayers(2, true); m_pcbGraphicsView->setLayerActive(ViewLayer::Copper1, true); m_pcbGraphicsView->setLayerActive(ViewLayer::Copper0, true); m_pcbGraphicsView->setLayerActive(ViewLayer::Silkscreen1, true); m_pcbGraphicsView->setLayerActive(ViewLayer::Silkscreen0, true); ModelPart * originalModelPart = NULL; if (paletteItem == NULL) { // this shouldn't happen originalModelPart = m_referenceModel->retrieveModelPart("generic_ic_dip_8_300mil"); } else { originalModelPart = paletteItem->modelPart(); } m_originalFzpPath = originalModelPart->path(); m_originalModuleID = originalModelPart->moduleID(); QFileInfo info(originalModelPart->path()); QString basename = info.completeBaseName(); int ix = GuidMatcher.indexIn(basename); if (ix > 1 && basename.at(ix - 1) == '_') { int dix = ix + 32 + 1; if (basename.count() > dix) { bool gotPrefix = true; for (int i = dix; i < basename.count(); i++) { if (!basename.at(i).isDigit()) { gotPrefix = false; break; } } if (gotPrefix) { m_prefix = basename.left(ix - 1); } } } //DebugDialog::debug(QString("%1, %2").arg(info.absoluteFilePath()).arg(m_userPartsFolderPath)); m_canSave = info.absoluteFilePath().contains(m_userPartsFolderPath); if (!loadFzp(originalModelPart->path())) return false; QDomElement fzpRoot = m_fzpDocument.documentElement(); QString referenceFile = fzpRoot.attribute(ReferenceFileString); if (referenceFile.isEmpty()) { fzpRoot.setAttribute(ReferenceFileString, info.fileName()); } QDomElement views = fzpRoot.firstChildElement("views"); QDomElement author = fzpRoot.firstChildElement("author"); if (author.isNull()) { author = m_fzpDocument.createElement("author"); fzpRoot.appendChild(author); } if (author.text().isEmpty()) { TextUtils::replaceChildText(author, QString(getenvUser())); } QDomElement date = fzpRoot.firstChildElement("date"); if (date.isNull()) { date = m_fzpDocument.createElement("date"); fzpRoot.appendChild(date); } TextUtils::replaceChildText(date, QDate::currentDate().toString()); QDomElement properties = fzpRoot.firstChildElement("properties"); if (properties.isNull()) { properties = m_fzpDocument.createElement("properties"); fzpRoot.appendChild(properties); } QHash props = originalModelPart->properties(); foreach (QString key, props.keys()) { replaceProperty(key, props.value(key), properties); } // record "local" properties foreach (QByteArray byteArray, originalModelPart->dynamicPropertyNames()) { replaceProperty(byteArray, originalModelPart->property(byteArray).toString(), properties); } bool hasLegID = false; QDomElement connectors = fzpRoot.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString localName = originalModelPart->connectorLocalName(connector.attribute("id")); if (!localName.isEmpty()) { connector.setAttribute("name", localName); } if (!hasLegID) { QDomNodeList plist = connector.elementsByTagName("p"); for (int i = 0; i < plist.count(); i++) { QDomElement p = plist.at(i).toElement(); if (!p.attribute("legId").isEmpty()) { hasLegID = true; break; } } } connector = connector.nextSiblingElement("connector"); } if (hasLegID && !RubberBandLegWarning) { RubberBandLegWarning = true; QMessageBox::warning(NULL, tr("Parts Editor"), tr("This part has bendable legs. ") + tr("This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . ") + tr("If you make changes to breadboard view, or change connector metadata, the legs may no longer work. ") + tr("You can safely make changes to Schematic or PCB view.\n\n") + tr("This warning will not be repeated in this session of Fritzing") ); } // for now kill the editable pin labels property, otherwise the saved part will try to use the labels that are only found in the sketch QDomElement epl = TextUtils::findElementWithAttribute(properties, "name", "editable pin labels"); if (!epl.isNull()) { TextUtils::replaceChildText(epl, "false"); } QDomElement family = TextUtils::findElementWithAttribute(properties, "name", "family"); if (family.isNull()) { replaceProperty("family", m_guid, properties); } QDomElement variant = TextUtils::findElementWithAttribute(properties, "name", "variant"); if (variant.isNull()) { QString newVariant = makeNewVariant(family.text()); replaceProperty("variant", newVariant, properties); } foreach (ViewThing * viewThing, m_viewThings.values()) { if (viewThing->sketchWidget == NULL) continue; ItemBase * itemBase = originalModelPart->viewItem(viewThing->sketchWidget->viewID()); if (itemBase == NULL) continue; viewThing->referenceFile = getSvgReferenceFile(itemBase->filename()); if (!itemBase->hasCustomSVG()) { QFile file(itemBase->filename()); if (!file.open(QFile::ReadOnly)) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to load '%1'. Please close the parts editor without saving and try again.").arg(itemBase->filename())); continue; } QString svg = file.readAll(); insertDesc(viewThing->referenceFile, svg); TextUtils::fixMuch(svg, true); QString svgPath = makeSvgPath2(viewThing->sketchWidget); bool result = writeXml(m_userPartsFolderSvgPath + svgPath, removeGorn(svg), true); if (!result) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to write svg to %1").arg(svgPath)); return false; } continue; } QHash svgHash; QStringList svgList; double factor; foreach (ViewLayer * vl, viewThing->sketchWidget->viewLayers().values()) { QString string = itemBase->retrieveSvg(vl->viewLayerID(), svgHash, false, GraphicsUtils::StandardFritzingDPI, factor); if (!string.isEmpty()) { svgList.append(string); } } if (svgList.count() == 0) { DebugDialog::debug(QString("pe: missing custom svg %1").arg(originalModelPart->moduleID())); continue; } QString svg; if (svgList.count() == 1) { svg = svgList.at(0); } else { // deal with copper0 and copper1 layers as parent/child // have to remove whitespace in order to compare the two svgs QRegExp white("\\s"); QStringList whiteList; foreach (QString string, svgList) { string.remove(white); whiteList << string; } bool keepGoing = true; while (keepGoing) { keepGoing = false; for (int i = 0; i < whiteList.count() - 1; i++) { for (int j = i + 1; j < whiteList.count(); j++) { if (whiteList.at(i).contains(whiteList.at(j))) { keepGoing = true; whiteList.removeAt(j); svgList.removeAt(j); break; } if (whiteList.at(j).contains(whiteList.at(i))) { keepGoing = true; whiteList.removeAt(i); svgList.removeAt(i); break; } } if (keepGoing) break; } } svg = svgList.join("\n"); } QSizeF size = itemBase->size(); QString header = TextUtils::makeSVGHeader(GraphicsUtils::SVGDPI, GraphicsUtils::StandardFritzingDPI, size.width(), size.height()); header += makeDesc(viewThing->referenceFile); svg = header + svg + ""; QString svgPath = makeSvgPath2(viewThing->sketchWidget); bool result = writeXml(m_userPartsFolderSvgPath + svgPath, removeGorn(svg), true); if (!result) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to write svg to %1").arg(svgPath)); return false; } QDomElement view = views.firstChildElement(ViewLayer::viewIDXmlName(viewThing->sketchWidget->viewID())); QDomElement layers = view.firstChildElement("layers"); if (layers.isNull()) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to parse fzp file %1").arg(originalModelPart->path())); return false; } setImageAttribute(layers, svgPath); } reload(true); foreach (ViewThing * viewThing, m_viewThings.values()) { viewThing->originalSvgPath = viewThing->itemBase->filename(); viewThing->svgChangeCount = 0; } setTitle(); createRaiseWindowActions(); return true; } void PEMainWindow::initZoom() { if (m_peToolView == NULL) return; if (m_currentGraphicsView == NULL) return; ViewThing * viewThing = m_viewThings.value(m_currentGraphicsView->viewID()); if (viewThing->itemBase == NULL) return; if (!viewThing->everZoomed) { viewThing->everZoomed = true; m_currentGraphicsView->fitInWindow(); } m_peSvgView->setFilename(viewThing->referenceFile); } void PEMainWindow::setTitle() { QString title = tr("Fritzing (New) Parts Editor"); QString partTitle = getPartTitle(); QString viewName; if (m_currentGraphicsView) viewName = m_currentGraphicsView->viewName(); else if (currentTabIndex() == IconViewIndex) viewName = tr("Icon View"); else if (currentTabIndex() == MetadataViewIndex) viewName = tr("Metadata View"); else if (currentTabIndex() == ConnectorsViewIndex) viewName = tr("Connectors View"); setWindowTitle(QString("%1: %2 [%3]%4").arg(title).arg(partTitle).arg(viewName).arg(QtFunkyPlaceholder)); } void PEMainWindow::createViewMenuActions(bool showWelcome) { MainWindow::createViewMenuActions(showWelcome); m_showIconAct = new QAction(tr("Show Icon"), this); m_showIconAct->setShortcut(tr("Ctrl+4")); m_showIconAct->setStatusTip(tr("Show the icon view")); connect(m_showIconAct, SIGNAL(triggered()), this, SLOT(showIconView())); m_showMetadataViewAct = new QAction(tr("Show Metadata"), this); m_showMetadataViewAct->setShortcut(tr("Ctrl+5")); m_showMetadataViewAct->setStatusTip(tr("Show the metadata view")); connect(m_showMetadataViewAct, SIGNAL(triggered()), this, SLOT(showMetadataView())); m_showConnectorsViewAct = new QAction(tr("Show Connectors"), this); m_showConnectorsViewAct->setShortcut(tr("Ctrl+6")); m_showConnectorsViewAct->setStatusTip(tr("Show the connector metadata in a list view")); connect(m_showConnectorsViewAct, SIGNAL(triggered()), this, SLOT(showConnectorsView())); m_hideOtherViewsAct = new QAction(tr("Make only this view visible"), this); m_hideOtherViewsAct->setStatusTip(tr("The part will only be visible in this view and icon view")); connect(m_hideOtherViewsAct, SIGNAL(triggered()), this, SLOT(hideOtherViews())); } void PEMainWindow::createViewMenu() { MainWindow::createViewMenu(); bool afterNext = false; foreach (QAction * action, m_viewMenu->actions()) { if (action == m_setBackgroundColorAct) { afterNext = true; } else if (afterNext) { m_viewMenu->insertSeparator(action); m_viewMenu->insertAction(action, m_hideOtherViewsAct); break; } } afterNext = false; foreach (QAction * action, m_viewMenu->actions()) { if (action == m_showPCBAct) { afterNext = true; } else if (afterNext) { m_viewMenu->insertAction(action, m_showIconAct); m_viewMenu->insertAction(action, m_showMetadataViewAct); m_viewMenu->insertAction(action, m_showConnectorsViewAct); break; } } m_numFixedActionsInViewMenu = m_viewMenu->actions().size(); } void PEMainWindow::showMetadataView() { setCurrentTabIndex(MetadataViewIndex); } void PEMainWindow::showConnectorsView() { setCurrentTabIndex(ConnectorsViewIndex); } void PEMainWindow::showIconView() { setCurrentTabIndex(IconViewIndex); } void PEMainWindow::changeSpecialProperty(const QString & name, const QString & value) { QHash oldProperties = getOldProperties(); if (value.isEmpty()) { QMessageBox::warning(NULL, tr("Blank not allowed"), tr("The value of '%1' can not be blank.").arg(name)); m_metadataView->resetProperty(name, value); return; } if (oldProperties.value(name) == value) { return; } QHash newProperties(oldProperties); newProperties.insert(name, value); ChangePropertiesCommand * cpc = new ChangePropertiesCommand(this, oldProperties, newProperties, NULL); cpc->setText(tr("Change %1 to %2").arg(name).arg(value)); cpc->setSkipFirstRedo(); changeProperties(newProperties, false); m_undoStack->waitPush(cpc, SketchWidget::PropChangeDelay); } void PEMainWindow::metadataChanged(const QString & name, const QString & value) { qDebug() << "metadata changed"; if (name.compare("family") == 0) { changeSpecialProperty(name, value); return; } if (name.compare("variant") == 0) { QString family = m_metadataView->family(); QHash variants = m_referenceModel->allPropValues(family, "variant"); QStringList values = variants.values(value); if (m_canSave) { QString moduleID = m_fzpDocument.documentElement().attribute("moduleId"); values.removeOne(moduleID); } if (values.count() > 0) { QMessageBox::warning(NULL, tr("Must be unique"), tr("Variant '%1' is in use. The variant name must be unique.").arg(value)); return; } changeSpecialProperty(name, value); return; } QString menuText = (name.compare("description") == 0) ? tr("Change description") : tr("Change %1 to '%2'").arg(name).arg(value); // called from metadataView QDomElement root = m_fzpDocument.documentElement(); QDomElement element = root.firstChildElement(name); QString oldValue = element.text(); if (oldValue == value) return; ChangeMetadataCommand * cmc = new ChangeMetadataCommand(this, name, oldValue, value, NULL); cmc->setText(menuText); cmc->setSkipFirstRedo(); changeMetadata(name, value, false); m_undoStack->waitPush(cmc, SketchWidget::PropChangeDelay); } void PEMainWindow::changeMetadata(const QString & name, const QString & value, bool updateDisplay) { // called from command object QDomElement root = m_fzpDocument.documentElement(); TextUtils::replaceElementChildText(root, name, value); //QString test = m_fzpDocument.toString(); if (updateDisplay) { m_metadataView->initMetadata(m_fzpDocument); } } void PEMainWindow::tagsChanged(const QStringList & newTags) { // called from metadataView QDomElement root = m_fzpDocument.documentElement(); QDomElement tags = root.firstChildElement("tags"); QDomElement tag = tags.firstChildElement("tag"); QStringList oldTags; while (!tag.isNull()) { oldTags << tag.text(); tag = tag.nextSiblingElement("tag"); } ChangeTagsCommand * ctc = new ChangeTagsCommand(this, oldTags, newTags, NULL); ctc->setText(tr("Change tags")); ctc->setSkipFirstRedo(); changeTags(newTags, false); m_undoStack->waitPush(ctc, SketchWidget::PropChangeDelay); } void PEMainWindow::changeTags(const QStringList & newTags, bool updateDisplay) { QDomElement root = m_fzpDocument.documentElement(); QDomElement tags = root.firstChildElement("tags"); QDomElement tag = tags.firstChildElement("tag"); while (!tag.isNull()) { tags.removeChild(tag); tag = tags.firstChildElement("tag"); } foreach (QString newTag, newTags) { QDomElement tag = m_fzpDocument.createElement("tag"); tags.appendChild(tag); TextUtils::replaceChildText(tag, newTag); } if (updateDisplay) { m_metadataView->initMetadata(m_fzpDocument); } } void PEMainWindow::propertiesChanged(const QHash & newProperties) { qDebug() << "properties changed"; QStringList keys = newProperties.keys(); if (keys.contains("family", Qt::CaseInsensitive)) { QMessageBox::warning(NULL, tr("Duplicate problem"), tr("Duplicate 'family' property not allowed")); return; } if (keys.contains("variant", Qt::CaseInsensitive)) { QMessageBox::warning(NULL, tr("Duplicate problem"), tr("Duplicate 'variant' property not allowed")); return; } // called from metadataView QHash oldProperties = getOldProperties(); ChangePropertiesCommand * cpc = new ChangePropertiesCommand(this, oldProperties, newProperties, NULL); cpc->setText(tr("Change properties")); cpc->setSkipFirstRedo(); changeProperties(newProperties, false); m_undoStack->waitPush(cpc, SketchWidget::PropChangeDelay); } void PEMainWindow::changeProperties(const QHash & newProperties, bool updateDisplay) { bool incomingFamily = newProperties.keys().contains("family"); bool incomingVariant = newProperties.keys().contains("variant"); QDomElement root = m_fzpDocument.documentElement(); QDomElement properties = root.firstChildElement("properties"); QDomElement prop = properties.firstChildElement("property"); while (!prop.isNull()) { QDomElement next = prop.nextSiblingElement("property"); bool doRemove = true; if (prop.attribute("name") == "family" && !incomingFamily) doRemove = false; if (prop.attribute("name") == "variant" && !incomingVariant) doRemove = false; if (doRemove) { properties.removeChild(prop); } prop = next; } foreach (QString name, newProperties.keys()) { QDomElement prop = m_fzpDocument.createElement("property"); properties.appendChild(prop); prop.setAttribute("name", name); TextUtils::replaceChildText(prop, newProperties.value(name)); } if (updateDisplay) { m_metadataView->initMetadata(m_fzpDocument); } } QHash PEMainWindow::getOldProperties() { QDomElement root = m_fzpDocument.documentElement(); QDomElement properties = root.firstChildElement("properties"); QDomElement prop = properties.firstChildElement("property"); QHash oldProperties; while (!prop.isNull()) { QString name = prop.attribute("name"); QString value = prop.text(); oldProperties.insert(name, value); prop = prop.nextSiblingElement("property"); } return oldProperties; } void PEMainWindow::connectorMetadataChanged(ConnectorMetadata * cmd) { int index; QDomElement connector = findConnector(cmd->connectorID, index); if (connector.isNull()) return; ConnectorMetadata oldcmd; fillInMetadata(connector, oldcmd); ChangeConnectorMetadataCommand * ccmc = new ChangeConnectorMetadataCommand(this, &oldcmd, cmd, NULL); ccmc->setText(tr("Change connector %1").arg(cmd->connectorName)); bool skipFirstRedo = (sender() == m_connectorsView); if (skipFirstRedo) { ccmc->setSkipFirstRedo(); changeConnectorElement(connector, cmd); initConnectors(false); } m_undoStack->waitPush(ccmc, SketchWidget::PropChangeDelay); } QDomElement PEMainWindow::findConnector(const QString & id, int & index) { QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); index = 0; while (!connector.isNull()) { if (id.compare(connector.attribute("id")) == 0) { return connector; } connector = connector.nextSiblingElement("connector"); index++; } return QDomElement(); } void PEMainWindow::changeConnectorMetadata(ConnectorMetadata * cmd, bool updateDisplay) { int index; QDomElement connector = findConnector(cmd->connectorID, index); if (connector.isNull()) return; changeConnectorElement(connector, cmd); if (updateDisplay) { initConnectors(true); m_peToolView->setCurrentConnector(index); } } void PEMainWindow::changeConnectorElement(QDomElement & connector, ConnectorMetadata * cmd) { connector.setAttribute("name", cmd->connectorName); connector.setAttribute("id", cmd->connectorID); connector.setAttribute("type", Connector::connectorNameFromType(cmd->connectorType)); TextUtils::replaceElementChildText(connector, "description", cmd->connectorDescription); #ifndef QT_NO_DEBUG QDomElement description = connector.firstChildElement("description"); QString text = description.text(); DebugDialog::debug(QString("description %1").arg(text)); #endif } void PEMainWindow::initSvgTree(SketchWidget * sketchWidget, ItemBase * itemBase, QDomDocument & svgDocument) { QString errorStr; int errorLine; int errorColumn; QDomDocument tempSvgDoc; QFile file(itemBase->filename()); if (!tempSvgDoc.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse svg: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } if (itemBase->viewID() == ViewLayer::PCBView) { QDomElement root = tempSvgDoc.documentElement(); QDomElement copper0 = TextUtils::findElementWithAttribute(root, "id", "copper0"); QDomElement copper1 = TextUtils::findElementWithAttribute(root, "id", "copper1"); if (!copper0.isNull() && !copper1.isNull()) { QDomElement parent0 = copper0.parentNode().toElement(); QDomElement parent1 = copper1.parentNode().toElement(); if (parent0.attribute("id") == "copper1") ; else if (parent1.attribute("id") == "copper0") ; else { QMessageBox::warning(NULL, tr("SVG problem"), tr("This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. ").arg(itemBase->filename()) + tr("So editing may produce an invalid PCB view image")); } } } int z = PegiZ; FSvgRenderer tempRenderer; QByteArray rendered = tempRenderer.loadSvg(tempSvgDoc.toByteArray(), "", false); // cleans up the svg if (!svgDocument.setContent(rendered, true, &errorStr, &errorLine, &errorColumn)) { DebugDialog::debug(QString("unable to parse svg (2): %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn)); return; } TextUtils::gornTree(svgDocument); FSvgRenderer renderer; renderer.loadSvg(svgDocument.toByteArray(), "", false); QHash pegiHash; QList traverse; traverse << svgDocument.documentElement(); while (traverse.count() > 0) { QDomElement element = traverse.takeFirst(); // depth first QList next; QDomElement child = element.firstChildElement(); while (!child.isNull()) { next << child; child = child.nextSiblingElement(); } while (next.count() > 0) { traverse.push_front(next.takeLast()); } bool isG = false; bool isSvg = false; QString tagName = element.tagName(); if (tagName.compare("rect") == 0); else if (tagName.compare("g") == 0) { isG = true; } else if (tagName.compare("svg") == 0) { isSvg = true; } else if (tagName.compare("circle") == 0); else if (tagName.compare("ellipse") == 0); else if (tagName.compare("path") == 0); else if (tagName.compare("line") == 0); else if (tagName.compare("polyline") == 0); else if (tagName.compare("polygon") == 0); else if (tagName.compare("text") == 0); else continue; QRectF bounds = getPixelBounds(renderer, element); // known Qt bug: boundsOnElement returns zero width and height for text elements. if (bounds.width() > 0 && bounds.height() > 0) { PEGraphicsItem * pegi = makePegi(bounds.size(), bounds.topLeft(), itemBase, element, z++); pegiHash.insert(element.attribute("id"), pegi); /* QString string; QTextStream stream(&string); element.save(stream, 0); DebugDialog::debug("........"); DebugDialog::debug(string); */ } } QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString svgID, terminalID; bool ok = ViewLayer::getConnectorSvgIDs(connector, sketchWidget->viewID(), svgID, terminalID); if (ok) { PEGraphicsItem * terminalItem = pegiHash.value(terminalID, NULL); PEGraphicsItem * pegi = pegiHash.value(svgID); if (pegi == NULL) { DebugDialog::debug(QString("missing pegi for svg id %1").arg(svgID)); } else { QPointF terminalPoint = pegi->rect().center(); if (terminalItem) { terminalPoint = terminalItem->pos() - pegi->pos() + terminalItem->rect().center(); } pegi->setTerminalPoint(terminalPoint); pegi->showTerminalPoint(true); } } connector = connector.nextSiblingElement("connector"); } } void PEMainWindow::highlightSlot(PEGraphicsItem * pegi) { if (m_peToolView) { bool enableTerminalPointControls = anyMarquee(); bool vis = anyVisible(); m_peToolView->enableConnectorChanges(vis && pegi->showingMarquee(), vis && enableTerminalPointControls, m_connectorList.count() > 0, vis); } if (m_peSvgView) { m_peSvgView->highlightElement(pegi); } } void PEMainWindow::initConnectors(bool updateConnectorsView) { QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); m_connectorList.clear(); while (!connector.isNull()) { m_connectorList.append(connector); connector = connector.nextSiblingElement("connector"); } qSort(m_connectorList.begin(), m_connectorList.end(), byID); if (updateConnectorsView) { m_connectorsView->initConnectors(&m_connectorList); } m_peToolView->initConnectors(&m_connectorList); updateAssignedConnectors(); } void PEMainWindow::switchedConnector(int ix) { if (m_currentGraphicsView == NULL) return; switchedConnector(ix, m_currentGraphicsView); } void PEMainWindow::switchedConnector(int ix, SketchWidget * sketchWidget) { if (m_connectorList.count() == 0) return; QDomElement element = m_connectorList.at(ix); if (element.isNull()) return; QString svgID, terminalID; if (!ViewLayer::getConnectorSvgIDs(element, sketchWidget->viewID(), svgID, terminalID)) return; QList pegiList = getPegiList(sketchWidget); bool gotOne = false; foreach (PEGraphicsItem * pegi, pegiList) { QDomElement pegiElement = pegi->element(); if (pegiElement.attribute("id").compare(svgID) == 0) { gotOne = true; pegi->showMarquee(true); pegi->setHighlighted(true); m_peToolView->setTerminalPointCoords(pegi->terminalPoint()); m_peToolView->setTerminalPointLimits(pegi->rect().size()); break; } } if (!gotOne) { foreach (PEGraphicsItem * pegi, pegiList) { pegi->showMarquee(false); pegi->setHighlighted(false); } } } void PEMainWindow::loadImage() { if (m_currentGraphicsView == NULL) return; QStringList extras; extras.append(""); extras.append(""); QString imageFiles; if (m_currentGraphicsView->viewID() == ViewLayer::PCBView) { imageFiles = tr("Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5)"); // extras[0] = "*.fp"; extras[1] = "*.mod"; } else { imageFiles = tr("Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5"); } /* if (m_currentGraphicsView->viewID() == ViewLayer::SchematicView) { extras[0] = "*.lib"; imageFiles = tr("Image & Footprint Files (%1 %2 %3 %4);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;Kicad Schematic Files (%4)%5"); // } */ QString initialPath = FolderUtils::openSaveFolder(); ViewThing * viewThing = m_viewThings.value(m_currentGraphicsView->viewID()); ItemBase * itemBase = viewThing->itemBase; if (itemBase) { initialPath = itemBase->filename(); } QString origPath = FolderUtils::getOpenFileName(this, tr("Open Image"), initialPath, imageFiles.arg("*.svg").arg("*.jpg *.jpeg").arg("*.png").arg(extras[0]).arg(extras[1]) ); if (origPath.isEmpty()) { return; // Cancel pressed } QString newReferenceFile; QString svg; if (origPath.endsWith(".svg")) { newReferenceFile = getSvgReferenceFile(origPath); QFile origFile(origPath); if (!origFile.open(QFile::ReadOnly)) { QMessageBox::warning(NULL, tr("Conversion problem"), tr("Unable to load '%1'").arg(origPath)); return; } svg = origFile.readAll(); origFile.close(); if (svg.contains("coreldraw", Qt::CaseInsensitive) && svg.contains("cdata", Qt::CaseInsensitive)) { QMessageBox::warning(NULL, tr("Conversion problem"), tr("The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. ").arg(origPath) + tr("Please re-export the SVG file using that setting, and try loading again.") ); return; } QStringList availFonts = InstalledFonts::InstalledFontsList.toList(); if (availFonts.count() > 0) { QString destFont = availFonts.at(0); foreach (QString f, availFonts) { if (f.contains("droid", Qt::CaseInsensitive)) { destFont = f; break; } } bool reallyFixed = false; TextUtils::fixFonts(svg, destFont, reallyFixed); if (reallyFixed) { QMessageBox::information(NULL, tr("Fonts"), tr("Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1'").arg(origPath)); } } } else { newReferenceFile = origPath; if (origPath.endsWith("png") || origPath.endsWith("jpg") || origPath.endsWith("jpeg")) { QString message = tr("You may use a PNG or JPG image to construct your part, but it is better to use an SVG. ") + tr("PNG and JPG images retain their nature as bitmaps and do not look good when scaled--") + tr("so for Fritzing parts it is best to use PNG and JPG only as placeholders.") ; QMessageBox::information(NULL, tr("Use of PNG and JPG discouraged"), message); } try { svg = createSvgFromImage(origPath); } catch (const QString & msg) { QMessageBox::warning(NULL, tr("Conversion problem"), tr("Unable to load image file '%1': \n\n%2").arg(origPath).arg(msg)); return; } } if (svg.isEmpty()) { QMessageBox::warning(NULL, tr("Conversion problem"), tr("Unable to load image file '%1'").arg(origPath)); return; } QString errorStr; int errorLine; int errorColumn; QDomDocument doc; bool result = doc.setContent(svg.toUtf8(), &errorStr, &errorLine, &errorColumn); if (!result) { QMessageBox::warning(NULL, tr("SVG problem"), tr("Unable to parse '%1': %2 line:%3 column:%4").arg(origPath).arg(errorStr).arg(errorLine).arg(errorColumn)); return; } if (m_currentGraphicsView == m_pcbGraphicsView) { QDomElement root = doc.documentElement(); QDomElement check = TextUtils::findElementWithAttribute(root, "id", "copper1"); if (check.isNull()) { check = TextUtils::findElementWithAttribute(root, "id", "copper0"); } if (check.isNull()) { QString message = tr("There are no copper layers defined in: %1. ").arg(origPath) + tr("See this explanation.") + tr("

This will not be a problem in the next release of the Parts Editor, ") + tr("but for now please modify the file according to the instructions in the link.") ; QMessageBox::warning(NULL, tr("SVG problem"), message); return; } } TextUtils::fixMuch(svg, true); insertDesc(newReferenceFile, svg); QString newPath = m_userPartsFolderSvgPath + makeSvgPath2(m_currentGraphicsView); bool success = writeXml(newPath, removeGorn(svg), true); if (!success) { QMessageBox::warning(NULL, tr("Copy problem"), tr("Unable to make a local copy of: '%1'").arg(origPath)); return; } QFileInfo info(origPath); QUndoCommand * parentCommand = new QUndoCommand(QString("Load '%1'").arg(info.fileName())); new ChangeSvgCommand(this, m_currentGraphicsView, itemBase->filename(), newPath, parentCommand); m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } QString PEMainWindow::createSvgFromImage(const QString &origFilePath) { if (origFilePath.endsWith(".fp")) { // this is a geda footprint file GedaElement2Svg geda; QString svg = geda.convert(origFilePath, false); return svg; } if (origFilePath.endsWith(".lib")) { // Kicad schematic library file QStringList defs = KicadSchematic2Svg::listDefs(origFilePath); if (defs.count() == 0) { throw tr("no schematics found in %1").arg(origFilePath); } QString def; if (defs.count() > 1) { KicadModuleDialog kmd(tr("schematic part"), origFilePath, defs, this); int result = kmd.exec(); if (result != QDialog::Accepted) { return ""; } def = kmd.selectedModule(); } else { def = defs.at(0); } KicadSchematic2Svg kicad; QString svg = kicad.convert(origFilePath, def); return svg; } if (origFilePath.endsWith(".mod")) { // Kicad footprint (Module) library file QStringList modules = KicadModule2Svg::listModules(origFilePath); if (modules.count() == 0) { throw tr("no footprints found in %1").arg(origFilePath); } QString module; if (modules.count() > 1) { KicadModuleDialog kmd("footprint", origFilePath, modules, this); int result = kmd.exec(); if (result != QDialog::Accepted) { return ""; } module = kmd.selectedModule(); } else { module = modules.at(0); } KicadModule2Svg kicad; QString svg = kicad.convert(origFilePath, module, false); return svg; } // deal with png, jpg: QBuffer buffer; QImage img(origFilePath); QSvgGenerator svgGenerator; svgGenerator.setResolution(90); svgGenerator.setOutputDevice(&buffer); QSize sz = img.size(); svgGenerator.setSize(sz); svgGenerator.setViewBox(QRect(0, 0, sz.width(), sz.height())); QPainter svgPainter(&svgGenerator); svgPainter.drawImage(QPoint(0,0), img); svgPainter.end(); return QString(buffer.buffer()); } /* QString PEMainWindow::makeSvgPath(const QString & referenceFile, SketchWidget * sketchWidget, bool useIndex) { QString rf = referenceFile; if (!rf.isEmpty()) rf += "_"; QString viewName = ViewLayer::viewIDNaturalName(sketchWidget->viewID()); QString indexString; if (useIndex) indexString = QString("_%3").arg(m_fileIndex++); return QString("%1/%2%3_%1%4.svg").arg(viewName).arg(rf).arg(m_guid).arg(indexString); } */ QString PEMainWindow::makeSvgPath2(SketchWidget * sketchWidget) { QString viewName = ViewLayer::viewIDNaturalName(sketchWidget->viewID()); return QString("%1/%2_%3_%4_%1.svg").arg(viewName).arg(m_prefix).arg(m_guid).arg(m_fileIndex); } void PEMainWindow::changeSvg(SketchWidget * sketchWidget, const QString & filename, int changeDirection) { QDomElement fzpRoot = m_fzpDocument.documentElement(); setImageAttribute(fzpRoot, filename, sketchWidget->viewID()); foreach (ViewThing * viewThing, m_viewThings.values()) { foreach(ItemBase * lk, viewThing->itemBase->layerKin()) { delete lk; } delete viewThing->itemBase; viewThing->itemBase = NULL; } updateChangeCount(sketchWidget, changeDirection); reload(false); } QString PEMainWindow::makeDirName() { return "fritzing_pe_" + m_guid; } QString PEMainWindow::saveFzp() { QDir dir = QDir::temp(); QString dirName = makeDirName(); dir.mkdir(dirName); dir.cd(dirName); QString fzpPath = dir.absoluteFilePath(QString("%1_%2_%3.fzp").arg(m_prefix).arg(m_guid).arg(m_fileIndex++)); DebugDialog::debug("temp path " + fzpPath); writeXml(fzpPath, m_fzpDocument.toString(), true); return fzpPath; } void PEMainWindow::reload(bool firstTime) { Q_UNUSED(firstTime); CursorMaster::instance()->addCursor(this, Qt::WaitCursor); QList toDelete; foreach (ViewThing * viewThing, m_viewThings.values()) { if (viewThing->sketchWidget == NULL) continue; foreach (QGraphicsItem * item, viewThing->sketchWidget->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase) toDelete << itemBase; } } foreach (ItemBase * itemBase, toDelete) { delete itemBase; } killPegi(); QString fzpPath = saveFzp(); // needs a document somewhere to set up connectors--not part of the undo stack ModelPart * modelPart = new ModelPart(m_fzpDocument, fzpPath, ModelPart::Part); long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); QList itemBases; itemBases << m_iconGraphicsView->addItem(modelPart, m_iconGraphicsView->defaultViewLayerPlacement(modelPart), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); itemBases << m_breadboardGraphicsView->addItem(modelPart, m_breadboardGraphicsView->defaultViewLayerPlacement(modelPart), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); itemBases << m_schematicGraphicsView->addItem(modelPart, m_schematicGraphicsView->defaultViewLayerPlacement(modelPart), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); itemBases << m_pcbGraphicsView->addItem(modelPart, m_pcbGraphicsView->defaultViewLayerPlacement(modelPart), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); foreach (ItemBase * itemBase, itemBases) { ViewThing * viewThing = m_viewThings.value(itemBase->viewID()); viewThing->itemBase = itemBase; viewThing->referenceFile = getSvgReferenceFile(itemBase->filename()); } m_metadataView->initMetadata(m_fzpDocument); QList widgets; widgets << m_metadataView << m_peToolView << m_connectorsView; foreach (QWidget * widget, widgets) { QList lineEdits = widget->findChildren(); foreach (QLineEdit * lineEdit, lineEdits) { lineEdit->installEventFilter(this); } QList textEdits = widget->findChildren(); foreach (QTextEdit * textEdit, textEdits) { textEdit->installEventFilter(this); } } if (m_currentGraphicsView) { showing(m_currentGraphicsView); } foreach (ViewThing * viewThing, m_viewThings.values()) { initSvgTree(viewThing->sketchWidget, viewThing->itemBase, *viewThing->document); } initConnectors(true); m_connectorsView->setSMD(modelPart->flippedSMD()); foreach (ViewThing * viewThing, m_viewThings.values()) { // TODO: may have to revisit this and move all pegi items //viewThing->itemBase->setMoveLock(true); //viewThing->itemBase->setItemIsSelectable(false); viewThing->itemBase->setAcceptsMousePressLegEvent(false); viewThing->itemBase->setSwappable(false); viewThing->sketchWidget->hideConnectors(true); viewThing->everZoomed = false; } switchedConnector(m_peToolView->currentConnectorIndex()); // processEventBlocker might be enough? QTimer::singleShot(10, this, SLOT(initZoom())); CursorMaster::instance()->removeCursor(this); } void PEMainWindow::busModeChanged(bool state) { if (m_currentGraphicsView == NULL) return; if (!state) { foreach (ViewThing * viewThing, m_viewThings.values()) { viewThing->busMode = false; viewThing->sketchWidget->hideConnectors(true); } deleteBuses(); reload(false); return; } QList pegiList = getPegiList(m_currentGraphicsView); reload(false); QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); foreach (ViewThing * viewThing, m_viewThings.values()) { // items on pegiList no longer exist after reload so get them now pegiList = getPegiList(viewThing->sketchWidget); viewThing->sketchWidget->hideConnectors(true); foreach (PEGraphicsItem * pegi, pegiList) { pegi->setVisible(false); } // show connectorItems that have connectors assigned QStringList connectorIDs; QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement p = ViewLayer::getConnectorPElement(connector, viewThing->sketchWidget->viewID()); QString id = p.attribute("svgId"); foreach (PEGraphicsItem * pegi, pegiList) { QDomElement pegiElement = pegi->element(); if (pegiElement.attribute("id").compare(id) == 0) { connectorIDs.append(connector.attribute("id")); break; } } connector = connector.nextSiblingElement("connector"); } if (connectorIDs.count() > 0) { viewThing->itemBase->showConnectors(connectorIDs); } } displayBuses(); m_peToolView->enableConnectorChanges(false, false, m_connectorList.count() > 0, false); } void PEMainWindow::pickModeChanged(bool state) { if (m_currentGraphicsView == NULL) return; // never actually get state == false; m_inPickMode = state; if (m_inPickMode) { QApplication::setOverrideCursor(Qt::PointingHandCursor); foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi) pegi->setPickAppearance(true); } qApp->installEventFilter(this); } } void PEMainWindow::pegiTerminalPointMoved(PEGraphicsItem * pegi, QPointF p) { // called while terminal point is being dragged, no need for an undo operation Q_UNUSED(pegi); m_peToolView->setTerminalPointCoords(p); } void PEMainWindow::pegiTerminalPointChanged(PEGraphicsItem * pegi, QPointF before, QPointF after) { // called at the end of terminal point dragging terminalPointChangedAux(pegi, before, after); } void PEMainWindow::pegiMousePressed(PEGraphicsItem * pegi, bool & ignore) { ignore = false; if (m_useNextPick) { m_useNextPick = false; relocateConnector(pegi); return; } ViewThing * viewThing = m_viewThings.value(m_currentGraphicsView->viewID()); if (pegi->itemBase() != viewThing->itemBase) { ignore = true; return; } QString id = pegi->element().attribute("id"); if (id.isEmpty()) return; QDomElement current = m_connectorList.at(m_peToolView->currentConnectorIndex()); if (current.attribute("id").compare(id) == 0) { // already there return; } // if a connector has been clicked, make it the current connector QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement p = ViewLayer::getConnectorPElement(connector, m_currentGraphicsView->viewID()); if (p.attribute("svgId") == id || p.attribute("terminalId") == id) { m_peToolView->setCurrentConnector(connector); return; } connector = connector.nextSiblingElement("connector"); } } void PEMainWindow::pegiMouseReleased(PEGraphicsItem *) { } void PEMainWindow::relocateConnector(PEGraphicsItem * pegi) { QString newGorn = pegi->element().attribute("gorn"); QDomDocument * svgDoc = m_viewThings.value(m_currentGraphicsView->viewID())->document; QDomElement svgRoot = svgDoc->documentElement(); QDomElement newGornElement = TextUtils::findElementWithAttribute(svgRoot, "gorn", newGorn); if (newGornElement.isNull()) { return; } QDomElement fzpRoot = m_fzpDocument.documentElement(); QDomElement connectors = fzpRoot.firstChildElement("connectors"); QDomElement currentConnectorElement = m_connectorList.at(m_peToolView->currentConnectorIndex()); QString svgID, terminalID; if (!ViewLayer::getConnectorSvgIDs(currentConnectorElement, m_currentGraphicsView->viewID(), svgID, terminalID)) { return; } QDomElement oldGornElement = TextUtils::findElementWithAttribute(svgRoot, "id", svgID); QString oldGorn = oldGornElement.attribute("gorn"); QString oldGornTerminal; if (!terminalID.isEmpty()) { QDomElement element = TextUtils::findElementWithAttribute(svgRoot, "id", terminalID); oldGornTerminal = element.attribute("gorn"); } if (newGornElement.attribute("gorn").compare(oldGornElement.attribute("gorn")) == 0) { // no change return; } RelocateConnectorSvgCommand * rcsc = new RelocateConnectorSvgCommand(this, m_currentGraphicsView, svgID, terminalID, oldGorn, oldGornTerminal, newGorn, "", NULL); rcsc->setText(tr("Relocate connector %1").arg(currentConnectorElement.attribute("name"))); m_undoStack->waitPush(rcsc, SketchWidget::PropChangeDelay); } void PEMainWindow::relocateConnectorSvg(SketchWidget * sketchWidget, const QString & svgID, const QString & terminalID, const QString & oldGorn, const QString & oldGornTerminal, const QString & newGorn, const QString & newGornTerminal, int changeDirection) { ViewLayer::ViewID viewID = sketchWidget->viewID(); ViewThing * viewThing = m_viewThings.value(viewID); QDomDocument * svgDoc = viewThing->document; QDomElement svgRoot = svgDoc->documentElement(); QDomElement oldGornElement = TextUtils::findElementWithAttribute(svgRoot, "gorn", oldGorn); QDomElement oldGornTerminalElement; if (!oldGornTerminal.isEmpty()) { oldGornTerminalElement = TextUtils::findElementWithAttribute(svgRoot, "gorn", oldGornTerminal); } QDomElement newGornElement = TextUtils::findElementWithAttribute(svgRoot, "gorn", newGorn); QDomElement newGornTerminalElement; if (!newGornTerminal.isEmpty()) { newGornTerminalElement = TextUtils::findElementWithAttribute(svgRoot, "gorn", newGornTerminal); } if (!oldGornElement.isNull()) { oldGornElement.removeAttribute("id"); oldGornElement.removeAttribute("oldid"); // remove oldid so removeGorn() call later doesn't restore anything by accident } if (!oldGornTerminalElement.isNull()) { oldGornTerminalElement.removeAttribute("id"); oldGornTerminalElement.removeAttribute("oldid"); } if (!newGornElement.isNull()) { newGornElement.setAttribute("id", svgID); newGornElement.removeAttribute("oldid"); } if (!newGornTerminalElement.isNull()) { newGornTerminalElement.setAttribute("id", terminalID); newGornTerminalElement.removeAttribute("oldid"); } QDomElement fzpRoot = m_fzpDocument.documentElement(); QDomElement connectors = fzpRoot.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString cSvgID, cTerminalID; if (ViewLayer::getConnectorSvgIDs(connector, viewID, cSvgID, cTerminalID)) { if (cSvgID == svgID) break; } connector = connector.nextSiblingElement("connector"); } if (connector.isNull()) return; QDomElement p = ViewLayer::getConnectorPElement(connector, viewID); if (terminalID.isEmpty()) { p.removeAttribute("terminalId"); } else { p.setAttribute("terminalId", terminalID); } // update svg in case there is a subsequent call to reload QString newPath = m_userPartsFolderSvgPath + makeSvgPath2(sketchWidget); QString svg = TextUtils::svgNSOnly(svgDoc->toString()); writeXml(newPath, removeGorn(svg), true); setImageAttribute(fzpRoot, newPath, viewID); foreach (QGraphicsItem * item, sketchWidget->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) continue; QDomElement element = pegi->element(); if (element.attribute("gorn").compare(newGorn) == 0) { pegi->setHighlighted(true); pegi->showMarquee(true); pegi->showTerminalPoint(true); switchedConnector(m_peToolView->currentConnectorIndex(), sketchWidget); } else if (element.attribute("gorn").compare(oldGorn) == 0) { pegi->showTerminalPoint(false); pegi->showMarquee(false); } } updateAssignedConnectors(); updateChangeCount(sketchWidget, changeDirection); } bool PEMainWindow::save() { if (!canSave()) { return saveAs(false); } return saveAs(true); } bool PEMainWindow::saveAs() { return saveAs(false); } bool PEMainWindow::saveAs(bool overWrite) { bool ok = false; QString prefix = QInputDialog::getText( this, tr("Filename prefix"), tr("Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.)").arg(m_guid), QLineEdit::Normal, m_prefix, &ok ); if (!ok || prefix.isEmpty()) return false; if (prefix != m_prefix) overWrite = false; m_prefix = prefix; QDomElement fzpRoot = m_fzpDocument.documentElement(); QList affectedWindows; QList allWindows; if (overWrite) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { MainWindow *mainWindow = qobject_cast(widget); if (mainWindow == NULL) continue; if (qobject_cast(mainWindow) != NULL) continue; allWindows.append(mainWindow); if (mainWindow->usesPart(m_originalModuleID)) { affectedWindows.append(mainWindow); } } if (affectedWindows.count() > 0 && !m_gaveSaveWarning) { QMessageBox messageBox(this); messageBox.setWindowTitle(tr("Sketch Change Warning")); QString message; if (affectedWindows.count() == 1) { message = tr("The open sketch '%1' uses the part you are editing. ").arg(affectedWindows.first()->windowTitle()); message += tr("Saving this part will make a change to the sketch that cannot be undone."); } else { message = tr("The open sketches "); for (int i = 0; i < affectedWindows.count() - 1; i++) { message += tr("'%1', ").arg(affectedWindows.at(i)->windowTitle()); } message += tr("and '%1' ").arg(affectedWindows.last()->windowTitle()); message += tr("Saving this part will make a change to these sketches that cannot be undone."); } message += tr("\n\nGo ahead and save?"); messageBox.setText(message); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); messageBox.setDefaultButton(QMessageBox::Cancel); messageBox.setIcon(QMessageBox::Warning); messageBox.setWindowModality(Qt::WindowModal); messageBox.setButtonText(QMessageBox::Ok, tr("Save")); messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec(); if (answer != QMessageBox::Ok) { return false; } m_gaveSaveWarning = true; } } QDomElement views = fzpRoot.firstChildElement("views"); QHash svgPaths; foreach (ViewLayer::ViewID viewID, m_viewThings.keys()) { ViewThing * viewThing = m_viewThings.value(viewID); QDomElement view = views.firstChildElement(ViewLayer::viewIDXmlName(viewID)); QDomElement layers = view.firstChildElement("layers"); QString currentSvgPath = layers.attribute("image"); svgPaths.insert(viewID, currentSvgPath); QMultiHash extraSvg; QDomDocument writeDoc = viewThing->document->cloneNode(true).toDocument(); QDomElement svgRoot = writeDoc.documentElement(); double svgWidth, svgHeight, vbWidth, vbHeight; bool svgOK = TextUtils::getSvgSizes(writeDoc, svgWidth, svgHeight, vbWidth, vbHeight); if (svgOK) { QHash svgHash; foreach (QGraphicsItem * item, viewThing->sketchWidget->scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->layerKinChief() == viewThing->itemBase) continue; double factor; QString string = itemBase->layerKinChief()->retrieveSvg(itemBase->viewLayerID(), svgHash, false, vbWidth / svgWidth, factor); if (!string.isEmpty()) { QPointF d = itemBase->pos() - viewThing->itemBase->pos(); double dx = d.x() * (vbWidth / svgWidth) / GraphicsUtils::SVGDPI; double dy = d.y() * (vbWidth / svgWidth) / GraphicsUtils::SVGDPI; string = QString("\n%3\n\n").arg(dx).arg(dy).arg(string); extraSvg.insert(itemBase->viewLayerID(), string); } } } // deal with copper1 and copper0: // find innermost // don't save twice QDomElement copperChild; LayerList sketchLayers = viewThing->sketchWidget->viewLayers().keys(); if (sketchLayers.contains(ViewLayer::Copper0) && sketchLayers.contains(ViewLayer::Copper1)) { QDomElement copper0 = TextUtils::findElementWithAttribute(svgRoot, "id", "copper0"); QDomElement copper1 = TextUtils::findElementWithAttribute(svgRoot, "id", "copper1"); if (!copper0.isNull() && !copper1.isNull()) { QDomElement parent0 = copper0.parentNode().toElement(); QDomElement parent1 = copper1.parentNode().toElement(); if (parent0.attribute("id") == "copper1") { copperChild = copper0; } else if (parent1.attribute("id") == "copper0") { copperChild = copper1; } } if (!copperChild.isNull()) { if (extraSvg.uniqueKeys().contains(ViewLayer::Copper0)) { extraSvg.remove(ViewLayer::Copper1); } } } foreach (ViewLayer::ViewLayerID viewLayerID, extraSvg.uniqueKeys()) { QStringList svgList = extraSvg.values(viewLayerID); QDomElement svgViewElement = (viewLayerID == ViewLayer::Copper0 && !copperChild.isNull()) ? copperChild : TextUtils::findElementWithAttribute(svgRoot, "id", ViewLayer::viewLayerXmlNameFromID(viewLayerID)); if (svgViewElement.isNull()) { svgViewElement = svgRoot; } foreach (QString svg, svgList) { QDomDocument doc; doc.setContent(svg, true); QDomElement root = doc.documentElement(); foreach (ViewLayer::ViewLayerID vlid, sketchLayers) { removeID(root, ViewLayer::viewLayerXmlNameFromID(vlid)); } svgViewElement.appendChild(doc.documentElement()); } } QString svg = writeDoc.toString(); insertDesc(viewThing->referenceFile, svg); QString svgPath = makeSvgPath2(viewThing->sketchWidget); setImageAttribute(layers, svgPath); QString actualPath = m_userPartsFolderSvgPath + svgPath; bool result = writeXml(actualPath, removeGorn(svg), false); if (!result) { // TODO: warn user } } QDir dir(m_userPartsFolderPath); QString suffix = QString("%1_%2_%3").arg(m_prefix).arg(m_guid).arg(m_fileIndex++); QString fzpPath = dir.absoluteFilePath(QString("%1.fzp").arg(suffix)); if (overWrite) { fzpPath = m_originalFzpPath; } else { fzpRoot.setAttribute("moduleId", suffix); QString family = m_metadataView->family(); QString variant = m_metadataView->variant(); QHash variants = m_referenceModel->allPropValues(family, "variant"); QStringList values = variants.values(variant); if (values.count() > 0) { QString newVariant = makeNewVariant(family); QDomElement properties = fzpRoot.firstChildElement("properties"); replaceProperty("variant", newVariant, properties); m_metadataView->resetProperty("variant", newVariant); } } bool result = writeXml(fzpPath, m_fzpDocument.toString(), false); if (!overWrite) { m_originalFzpPath = fzpPath; m_canSave = true; m_originalModuleID = fzpRoot.attribute("moduleId"); } // restore the set of working svg files foreach (ViewLayer::ViewID viewID, m_viewThings.keys()) { QString svgPath = svgPaths.value(viewID); if (svgPath.isEmpty()) continue; QDomElement view = views.firstChildElement(ViewLayer::viewIDXmlName(viewID)); QDomElement layers = view.firstChildElement("layers"); setImageAttribute(layers, svgPath); } ModelPart * modelPart = m_referenceModel->retrieveModelPart(m_originalModuleID); if (modelPart == NULL) { modelPart = m_referenceModel->loadPart(fzpPath, true); emit addToMyPartsSignal(modelPart); } else { m_referenceModel->reloadPart(fzpPath, m_originalModuleID); WaitPushUndoStack undoStack; QUndoCommand * parentCommand = new QUndoCommand; foreach (MainWindow * mainWindow, affectedWindows) { mainWindow->updateParts(m_originalModuleID, parentCommand); } foreach (MainWindow * mainWindow, allWindows) { mainWindow->updatePartsBin(m_originalModuleID); } undoStack.push(parentCommand); } m_autosaveNeeded = false; m_undoStack->setClean(); return result; } void PEMainWindow::updateChangeCount(SketchWidget * sketchWidget, int changeDirection) { ViewThing * viewThing = m_viewThings.value(sketchWidget->viewID()); viewThing->svgChangeCount += changeDirection; } PEGraphicsItem * PEMainWindow::findConnectorItem() { if (m_currentGraphicsView == NULL) return NULL; QDomElement connector = m_connectorList.at(m_peToolView->currentConnectorIndex()); if (connector.isNull()) return NULL; QString svgID, terminalID; bool ok = ViewLayer::getConnectorSvgIDs(connector, m_currentGraphicsView->viewID(), svgID, terminalID); if (!ok) return NULL; QList pegiList = getPegiList(m_currentGraphicsView); foreach (PEGraphicsItem * pegi, pegiList) { if (pegi->element().attribute("id") == svgID) return pegi; } return NULL; } void PEMainWindow::terminalPointChanged(const QString & how) { PEGraphicsItem * pegi = findConnectorItem(); if (pegi == NULL) return; QRectF r = pegi->rect(); QPointF p = r.center(); if (how == "center") { } else if (how == "N") { p.setY(0); } else if (how == "E") { p.setX(r.width()); } else if (how == "S") { p.setY(r.height()); } else if (how == "W") { p.setX(0); } terminalPointChangedAux(pegi, pegi->terminalPoint(), p); // TODO: UndoCommand which changes fzp xml and svg xml } void PEMainWindow::terminalPointChanged(const QString & coord, double value) { PEGraphicsItem * pegi = findConnectorItem(); if (pegi == NULL) return; QPointF p = pegi->terminalPoint(); if (coord == "x") { p.setX(qMax(0.0, qMin(value, pegi->rect().width()))); } else { p.setY(qMax(0.0, qMin(value, pegi->rect().height()))); } terminalPointChangedAux(pegi, pegi->terminalPoint(), p); } void PEMainWindow::terminalPointChangedAux(PEGraphicsItem * pegi, QPointF before, QPointF after) { if (pegi->pendingTerminalPoint() == after) { return; } pegi->setPendingTerminalPoint(after); QDomElement currentConnectorElement = m_connectorList.at(m_peToolView->currentConnectorIndex()); MoveTerminalPointCommand * mtpc = new MoveTerminalPointCommand(this, this->m_currentGraphicsView, currentConnectorElement.attribute("id"), pegi->rect().size(), before, after, NULL); mtpc->setText(tr("Move terminal point")); m_undoStack->waitPush(mtpc, SketchWidget::PropChangeDelay); } void PEMainWindow::getSpinAmount(double & amount) { double zoom = m_currentGraphicsView->currentZoom() / 100; if (zoom == 0) { amount = 1; return; } amount = qMin(1.0, 1.0 / zoom); if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { amount *= 10; } } void PEMainWindow::moveTerminalPoint(SketchWidget * sketchWidget, const QString & connectorID, QSizeF size, QPointF p, int changeDirection) { // TODO: assumes these IDs are unique--need to check if they are not QPointF center(size.width() / 2, size.height() / 2); bool centered = qAbs(center.x() - p.x()) < .05 && qAbs(center.y() - p.y()) < .05; QDomElement fzpRoot = m_fzpDocument.documentElement(); QDomElement connectorElement = TextUtils::findElementWithAttribute(fzpRoot, "id", connectorID); if (connectorElement.isNull()) { DebugDialog::debug(QString("missing connector %1").arg(connectorID)); return; } QDomElement pElement = ViewLayer::getConnectorPElement(connectorElement, sketchWidget->viewID()); QString svgID = pElement.attribute("svgId"); if (svgID.isEmpty()) { DebugDialog::debug(QString("Can't find svgId for connector %1").arg(connectorID)); return; } PEGraphicsItem * connectorPegi = NULL; QList pegiList = getPegiList(sketchWidget); foreach (PEGraphicsItem * pegi, pegiList) { QDomElement pegiElement = pegi->element(); if (pegiElement.attribute("id").compare(svgID) == 0) { connectorPegi = pegi; } } if (connectorPegi == NULL) return; if (centered) { pElement.removeAttribute("terminalId"); // no need to change SVG in this case } else { ViewThing * viewThing = m_viewThings.value(sketchWidget->viewID()); QDomDocument * svgDoc = viewThing->document; QDomElement svgRoot = svgDoc->documentElement(); QDomElement svgConnectorElement = TextUtils::findElementWithAttribute(svgRoot, "id", svgID); if (svgConnectorElement.isNull()) { DebugDialog::debug(QString("Unable to find svg connector element %1").arg(svgID)); return; } QString terminalID = pElement.attribute("terminalId"); if (terminalID.isEmpty()) { terminalID = svgID; if (terminalID.endsWith("pin") || terminalID.endsWith("pad")) { terminalID.chop(3); } terminalID += "terminal"; pElement.setAttribute("terminalId", terminalID); } FSvgRenderer renderer; renderer.loadSvg(svgDoc->toByteArray(), "", false); QRectF svgBounds = renderer.boundsOnElement(svgID); double cx = p.x () * svgBounds.width() / size.width(); double cy = p.y() * svgBounds.height() / size.height(); double dx = svgBounds.width() / 1000; double dy = svgBounds.height() / 1000; QDomElement terminalElement = TextUtils::findElementWithAttribute(svgRoot, "id", terminalID); if (terminalElement.isNull()) { terminalElement = svgDoc->createElement("rect"); } else if (terminalElement.tagName() != "rect" || terminalElement.attribute("fill") != "none" || terminalElement.attribute("stroke") != "none") { terminalElement.setAttribute("id", ""); terminalElement = svgDoc->createElement("rect"); } terminalElement.setAttribute("id", terminalID); terminalElement.setAttribute("oldid", terminalID); terminalElement.setAttribute("stroke", "none"); terminalElement.setAttribute("fill", "none"); terminalElement.setAttribute("stroke-width", "0"); terminalElement.setAttribute("x", QString::number(svgBounds.left() + cx - dx)); terminalElement.setAttribute("y", QString::number(svgBounds.top() + cy - dy)); terminalElement.setAttribute("width", QString::number(dx * 2)); terminalElement.setAttribute("height", QString::number(dy * 2)); if (terminalElement.attribute("gorn").isEmpty()) { QString gorn = svgConnectorElement.attribute("gorn"); int ix = gorn.lastIndexOf("."); if (ix > 0) { gorn.truncate(ix); } gorn = QString("%1.gen%2").arg(gorn).arg(FakeGornSiblingNumber++); terminalElement.setAttribute("gorn", gorn); } svgConnectorElement.parentNode().insertAfter(terminalElement, svgConnectorElement); double oldZ = connectorPegi->zValue() + 1; foreach (PEGraphicsItem * pegi, pegiList) { QDomElement pegiElement = pegi->element(); if (pegiElement.attribute("id").compare(terminalID) == 0) { DebugDialog::debug("old pegi location", pegi->pos()); oldZ = pegi->zValue(); pegiList.removeOne(pegi); delete pegi; break; } } // update svg in case there is a subsequent call to reload QString newPath = m_userPartsFolderSvgPath + makeSvgPath2(sketchWidget); QString svg = TextUtils::svgNSOnly(svgDoc->toString()); writeXml(newPath, removeGorn(svg), true); setImageAttribute(fzpRoot, newPath, sketchWidget->viewID()); double invdx = dx * size.width() / svgBounds.width(); double invdy = dy * size.height() / svgBounds.height(); QPointF topLeft = connectorPegi->offset() + p - QPointF(invdx, invdy); PEGraphicsItem * pegi = makePegi(QSizeF(invdx * 2, invdy * 2), topLeft, viewThing->itemBase, terminalElement, oldZ); DebugDialog::debug("new pegi location", pegi->pos()); updateChangeCount(sketchWidget, changeDirection); } connectorPegi->setTerminalPoint(p); connectorPegi->update(); m_peToolView->setTerminalPointCoords(p); } void PEMainWindow::showInOS(QWidget *parent, const QString &pathIn) { Q_UNUSED(parent); FolderUtils::showInFolder(pathIn); QClipboard *clipboard = QApplication::clipboard(); if (clipboard != NULL) { clipboard->setText(pathIn); } } void PEMainWindow::showInOS() { if (m_currentGraphicsView == NULL) return; ViewThing * viewThing = m_viewThings.value(m_currentGraphicsView->viewID()); showInOS(this, viewThing->itemBase->filename()); } PEGraphicsItem * PEMainWindow::makePegi(QSizeF size, QPointF topLeft, ItemBase * itemBase, QDomElement & element, double z) { PEGraphicsItem * pegiItem = new PEGraphicsItem(0, 0, size.width(), size.height(), itemBase); pegiItem->showTerminalPoint(false); pegiItem->setPos(itemBase->pos() + topLeft); pegiItem->setZValue(z); itemBase->scene()->addItem(pegiItem); pegiItem->setElement(element); pegiItem->setOffset(topLeft); connect(pegiItem, SIGNAL(highlightSignal(PEGraphicsItem *)), this, SLOT(highlightSlot(PEGraphicsItem *))); connect(pegiItem, SIGNAL(mouseReleasedSignal(PEGraphicsItem *)), this, SLOT(pegiMouseReleased(PEGraphicsItem *))); connect(pegiItem, SIGNAL(mousePressedSignal(PEGraphicsItem *, bool &)), this, SLOT(pegiMousePressed(PEGraphicsItem *, bool &)), Qt::DirectConnection); connect(pegiItem, SIGNAL(terminalPointMoved(PEGraphicsItem *, QPointF)), this, SLOT(pegiTerminalPointMoved(PEGraphicsItem *, QPointF))); connect(pegiItem, SIGNAL(terminalPointChanged(PEGraphicsItem *, QPointF, QPointF)), this, SLOT(pegiTerminalPointChanged(PEGraphicsItem *, QPointF, QPointF))); return pegiItem; } QRectF PEMainWindow::getPixelBounds(FSvgRenderer & renderer, QDomElement & element) { QSizeF defaultSizeF = renderer.defaultSizeF(); QRectF viewBox = renderer.viewBoxF(); QString id = element.attribute("id"); QRectF r = renderer.boundsOnElement(id); QMatrix matrix = renderer.matrixForElement(id); QString oldid = element.attribute("oldid"); if (!oldid.isEmpty()) { element.setAttribute("id", oldid); element.removeAttribute("oldid"); } QRectF bounds = matrix.mapRect(r); bounds.setRect(bounds.x() * defaultSizeF.width() / viewBox.width(), bounds.y() * defaultSizeF.height() / viewBox.height(), bounds.width() * defaultSizeF.width() / viewBox.width(), bounds.height() * defaultSizeF.height() / viewBox.height()); return bounds; } bool PEMainWindow::canSave() { return m_canSave; } void PEMainWindow::tabWidget_currentChanged(int index) { MainWindow::tabWidget_currentChanged(index); if (m_peToolView == NULL) return; switchedConnector(m_peToolView->currentConnectorIndex()); bool enabled = index < IconViewIndex; m_peSvgView->setChildrenVisible(enabled); m_peToolView->setChildrenVisible(enabled); if (m_currentGraphicsView == NULL) { // update title when switching to connector and metadata view setTitle(); } else { } updateAssignedConnectors(); updateActiveLayerButtons(); } void PEMainWindow::backupSketch() { } void PEMainWindow::removedConnector(const QDomElement & element) { QList connectors; connectors.append(element); removedConnectorsAux(connectors); } void PEMainWindow::removedConnectors(QList & cmdList) { QList connectors; foreach (ConnectorMetadata * cmd, cmdList) { int index; QDomElement connector = findConnector(cmd->connectorID, index); if (connector.isNull()) return; cmd->index = index; connectors.append(connector); } removedConnectorsAux(connectors); } void PEMainWindow::removedConnectorsAux(QList & connectors) { QString originalPath = saveFzp(); foreach (QDomElement connector, connectors) { if (m_removedConnector.isEmpty()) { QTextStream stream(&m_removedConnector); connector.save(stream, 0); } connector.parentNode().removeChild(connector); } QString newPath = saveFzp(); ChangeFzpCommand * cfc = new ChangeFzpCommand(this, originalPath, newPath, NULL); QString message; if (connectors.count() == 1) { message = tr("Remove connector"); } else { message = tr("Remove %1 connectors").arg(connectors.count()); } cfc->setText(message); m_undoStack->waitPush(cfc, SketchWidget::PropChangeDelay); } void PEMainWindow::restoreFzp(const QString & fzpPath) { if (!loadFzp(fzpPath)) return; reload(false); } void PEMainWindow::setBeforeClosingText(const QString & filename, QMessageBox & messageBox) { Q_UNUSED(filename); QString partTitle = getPartTitle(); messageBox.setWindowTitle(tr("Save \"%1\"").arg(partTitle)); messageBox.setText(tr("Do you want to save the changes you made in the part \"%1\"?").arg(partTitle)); messageBox.setInformativeText(tr("Your changes will be lost if you don't save them.")); } QString PEMainWindow::getPartTitle() { QString partTitle = tr("untitled part"); QDomElement root = m_fzpDocument.documentElement(); QDomElement title = root.firstChildElement("title"); QString candidate = title.text(); if (!candidate.isEmpty()) return candidate; if (m_viewThings.count() > 0) { ViewThing * viewThing = m_viewThings.values().at(0); if (viewThing->itemBase) { candidate = viewThing->itemBase->title(); if (!candidate.isEmpty()) return candidate; } } return partTitle; } void PEMainWindow::killPegi() { foreach (ViewThing * viewThing, m_viewThings.values()) { if (viewThing->sketchWidget == NULL) continue; foreach (QGraphicsItem * item, viewThing->sketchWidget->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi) delete pegi; } } } bool PEMainWindow::loadFzp(const QString & path) { QFile file(path); QString errorStr; int errorLine; int errorColumn; bool result = m_fzpDocument.setContent(&file, &errorStr, &errorLine, &errorColumn); if (!result) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to load fzp from %1").arg(path)); return false; } return true; } void PEMainWindow::connectorCountChanged(int newCount) { QList connectorList; QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { connectorList.append(connector); connector = connector.nextSiblingElement(); } if (newCount == connectorList.count()) return; if (newCount < connectorList.count()) { qSort(connectorList.begin(), connectorList.end(), byID); QList toDelete; for (int i = newCount; i < connectorList.count(); i++) { toDelete.append(connectorList.at(i)); } removedConnectorsAux(toDelete); return; } // add connectors int id = 0; foreach (QDomElement connector, connectorList) { int ix = IntegerFinder.indexIn(connector.attribute("id")); if (ix >= 0) { int candidate = IntegerFinder.cap(0).toInt(); if (candidate > id) id = candidate; } // sometimes id = 0 but name = 1, and we are now using name = id ix = IntegerFinder.indexIn(connector.attribute("name")); if (ix >= 0) { int candidate = IntegerFinder.cap(0).toInt(); if (candidate > id) id = candidate; } } QString originalPath = saveFzp(); QDomElement connectorModel; QDomDocument tempDoc; if (connectorList.count() > 0) connectorModel = connectorList.at(0); else { tempDoc.setContent(m_removedConnector); connectorModel = tempDoc.documentElement(); if (connectorModel.isNull()) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to create new connector--you may have to start over.")); return; } } for (int i = connectorList.count(); i < newCount; i++) { id++; QDomElement element = connectorModel.cloneNode(true).toElement(); connectors.appendChild(element); QString newName = QString("pin %1").arg(id); element.setAttribute("name", newName); QString cid = QString("connector%1").arg(id); element.setAttribute("id", cid); QString svgid = cid + "pin"; QDomNodeList nodeList = element.elementsByTagName("p"); for (int n = 0; n < nodeList.count(); n++) { QDomElement p = nodeList.at(n).toElement(); p.removeAttribute("terminalId"); p.removeAttribute("legId"); p.setAttribute("svgId", svgid); } QDomElement description = element.firstChildElement("description"); if (description.isNull()) { description = m_fzpDocument.createElement("description"); element.appendChild(description); } TextUtils::replaceChildText(description, newName); } QString newPath = saveFzp(); ChangeFzpCommand * cfc = new ChangeFzpCommand(this, originalPath, newPath, NULL); QString message; if (newCount - connectorList.count() == 1) { message = tr("Add connector"); } else { message = tr("Add %1 connectors").arg(newCount - connectorList.count()); } cfc->setText(message); m_undoStack->waitPush(cfc, SketchWidget::PropChangeDelay); } bool PEMainWindow::editsModuleID(const QString & moduleID) { // only to detect whether a user tries to open the parts editor on the same part twice return (m_originalModuleID.compare(moduleID) == 0); } /* QString PEMainWindow::getFzpReferenceFile() { QString referenceFile = m_fzpDocument.documentElement().attribute(ReferenceFileString); if (!referenceFile.isEmpty()) referenceFile += "_"; return referenceFile; } */ QString PEMainWindow::getSvgReferenceFile(const QString & filename) { QFileInfo info(filename); QString referenceFile = info.fileName(); QFile file(filename); if (!file.open(QFile::ReadOnly)) return referenceFile; QString svg = file.readAll(); if (!svg.contains(ReferenceFileString)) return referenceFile; QXmlStreamReader xml(svg.toUtf8()); xml.setNamespaceProcessing(false); bool inDesc = false; while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: { QString name = xml.name().toString(); if (inDesc && name.compare(ReferenceFileString) == 0) { QString candidate = xml.readElementText().trimmed(); if (candidate.isEmpty()) return referenceFile; return candidate; } if (name.compare("desc") == 0) { inDesc = true; } } break; case QXmlStreamReader::EndElement: { QString name = xml.name().toString(); if (name.compare("desc") == 0) { inDesc = false; } } break; default: break; } } return referenceFile; } QString PEMainWindow::makeDesc(const QString & referenceFile) { return QString("\n<%2>%1\n").arg(referenceFile).arg(ReferenceFileString); } void PEMainWindow::updateWindowMenu() { } void PEMainWindow::updateRaiseWindowAction() { QString title = tr("Fritzing (New) Parts Editor"); QString partTitle = getPartTitle(); QString actionText = QString("%1: %2").arg(title).arg(partTitle); m_raiseWindowAct->setText(actionText); m_raiseWindowAct->setToolTip(actionText); m_raiseWindowAct->setStatusTip("raise \""+actionText+"\" window"); } bool PEMainWindow::writeXml(const QString & path, const QString & xml, bool temp) { bool result = TextUtils::writeUtf8(path, TextUtils::svgNSOnly(xml)); if (result) { if (temp) m_filesToDelete.append(path); else m_filesToDelete.removeAll(path); } return result; } void PEMainWindow::displayBuses() { deleteBuses(); QDomElement root = m_fzpDocument.documentElement(); QDomElement buses = root.firstChildElement("buses"); QDomElement bus = buses.firstChildElement("bus"); while (!bus.isNull()) { QDomElement nodeMember = bus.firstChildElement("nodeMember"); QSet connectorIDs; while (!nodeMember.isNull()) { QString connectorID = nodeMember.attribute("connectorId"); if (!connectorID.isEmpty()) { connectorIDs.insert(connectorID); } nodeMember = nodeMember.nextSiblingElement("nodeMember"); } foreach (ViewLayer::ViewID viewID, m_viewThings.keys()) { ViewThing * viewThing = m_viewThings.value(viewID); QList connectorItems; foreach (QString connectorID, connectorIDs) { ConnectorItem * connectorItem = viewThing->itemBase->findConnectorItemWithSharedID(connectorID, viewThing->itemBase->viewLayerPlacement()); if (connectorItem) connectorItems.append(connectorItem); } for (int i = 0; i < connectorItems.count() - 1; i++) { ConnectorItem * c1 = connectorItems.at(i); ConnectorItem * c2 = connectorItems.at(i + 1); Wire * wire = viewThing->sketchWidget->makeOneRatsnestWire(c1, c2, false, QColor(0, 255, 0), true); wire->setZValue(RatZ); } } bus = bus.nextSiblingElement("bus"); } } void PEMainWindow::updateWireMenu() { // assumes update wire menu is only called when right-clicking a wire // and that wire is cached by the menu in Wire::mousePressEvent Wire * wire = m_activeWire; m_activeWire = NULL; m_deleteBusConnectionAct->setWire(wire); m_deleteBusConnectionAct->setEnabled(true); } void PEMainWindow::deleteBusConnection() { WireAction * wireAction = qobject_cast(sender()); if (wireAction == NULL) return; Wire * wire = wireAction->wire(); if (wire == NULL) return; QList wires; QList ends; wire->collectChained(wires, ends); if (ends.count() != 2) return; QString id0 = ends.at(0)->connectorSharedID(); QString id1 = ends.at(1)->connectorSharedID(); QDomElement root = m_fzpDocument.documentElement(); QDomElement buses = root.firstChildElement("buses"); QDomElement bus = buses.firstChildElement("bus"); QDomElement nodeMember0; QDomElement nodeMember1; while (!bus.isNull()) { nodeMember0 = TextUtils::findElementWithAttribute(bus, "connectorId", id0); nodeMember1 = TextUtils::findElementWithAttribute(bus, "connectorId", id1); if (!nodeMember0.isNull() && !nodeMember1.isNull()) break; bus = bus.nextSiblingElement("bus"); } QString busID = bus.attribute("id"); if (nodeMember0.isNull() || nodeMember1.isNull()) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Internal connections are very messed up.")); return; } QUndoCommand * parentCommand = new QUndoCommand(); QStringList names; names << ends.at(0)->connectorSharedName() << ends.at(1)->connectorSharedName() ; new RemoveBusConnectorCommand(this, busID, id0, false, parentCommand); new RemoveBusConnectorCommand(this, busID, id1, false, parentCommand); if (ends.at(0)->connectedToItems().count() > 1) { // restore it names.removeAt(0); new RemoveBusConnectorCommand(this, busID, id0, true, parentCommand); } if (ends.at(1)->connectedToItems().count() > 1) { // restore it new RemoveBusConnectorCommand(this, busID, id1, true, parentCommand); } parentCommand->setText(tr("Remove internal connection from '%1'").arg(names.at(0))); m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } void PEMainWindow::newWireSlot(Wire * wire) { wire->setDisplayBendpointCursor(false); disconnect(wire, 0, m_viewThings.value(wire->viewID())->sketchWidget, 0); connect(wire, SIGNAL(wireChangedSignal(Wire*, const QLineF & , const QLineF & , QPointF, QPointF, ConnectorItem *, ConnectorItem *) ), this, SLOT(wireChangedSlot(Wire*, const QLineF & , const QLineF & , QPointF, QPointF, ConnectorItem *, ConnectorItem *)), Qt::DirectConnection); // DirectConnection means call the slot directly like a subroutine, without waiting for a thread or queue } void PEMainWindow::wireChangedSlot(Wire* wire, const QLineF &, const QLineF &, QPointF, QPointF, ConnectorItem * fromOnWire, ConnectorItem * to) { wire->deleteLater(); if (to == NULL) return; ConnectorItem * from = wire->otherConnector(fromOnWire)->firstConnectedToIsh(); if (from == NULL) return; QDomElement root = m_fzpDocument.documentElement(); QDomElement buses = root.firstChildElement("buses"); if (buses.isNull()) { buses = m_fzpDocument.createElement("buses"); root.appendChild(buses); } QDomElement fromBus = findNodeMemberBus(buses, from->connectorSharedID()); QString fromBusID = fromBus.attribute("id"); QDomElement toBus = findNodeMemberBus(buses, to->connectorSharedID()); QString toBusID = toBus.attribute("id"); QString busID = fromBusID.isEmpty() ? toBusID : fromBusID; if (busID.isEmpty()) { int theMax = std::numeric_limits::max(); for (int ix = 1; ix < theMax; ix++) { QString candidate = QString("internal%1").arg(ix); QDomElement busElement = findBus(buses, candidate); if (busElement.isNull()) { busID = candidate; break; } } } QUndoCommand * parentCommand = new QUndoCommand(tr("Add internal connection from '%1' to '%2'").arg(from->connectorSharedName()).arg(to->connectorSharedName())); if (!fromBusID.isEmpty()) { // changing the bus for this nodeMember new RemoveBusConnectorCommand(this, fromBusID, from->connectorSharedID(), false, parentCommand); } if (!toBusID.isEmpty()) { // changing the bus for this nodeMember new RemoveBusConnectorCommand(this, toBusID, to->connectorSharedID(), false, parentCommand); } new RemoveBusConnectorCommand(this, busID, from->connectorSharedID(), true, parentCommand); new RemoveBusConnectorCommand(this, busID, to->connectorSharedID(), true, parentCommand); m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } QDomElement PEMainWindow::findBus(const QDomElement & buses, const QString & id) { QDomElement busElement = buses.firstChildElement("bus"); while (!busElement.isNull()) { if (busElement.attribute("id").compare(id) == 0) { return busElement; } busElement = busElement.nextSiblingElement("bus"); } return QDomElement(); } QDomElement PEMainWindow::findNodeMemberBus(const QDomElement & buses, const QString & connectorID) { QDomElement bus = buses.firstChildElement("bus"); while (!bus.isNull()) { QDomElement nodeMember = bus.firstChildElement("nodeMember"); while (!nodeMember.isNull()) { if (nodeMember.attribute("connectorId").compare(connectorID) == 0) { return bus; } nodeMember = nodeMember.nextSiblingElement("nodeMember"); } bus = bus.nextSiblingElement("bus"); } return QDomElement(); } void PEMainWindow::addBusConnector(const QString & busID, const QString & connectorID) { // called from command object removeBusConnector(busID, connectorID, false); // keep the dom very clean QDomElement root = m_fzpDocument.documentElement(); QDomElement buses = root.firstChildElement("buses"); if (buses.isNull()) { m_fzpDocument.createElement("buses"); root.appendChild(buses); } QDomElement theBusElement = findBus(buses, busID); if (theBusElement.isNull()) { theBusElement = m_fzpDocument.createElement("bus"); theBusElement.setAttribute("id", busID); buses.appendChild(theBusElement); } QDomElement nodeMember = m_fzpDocument.createElement("nodeMember"); nodeMember.setAttribute("connectorId", connectorID); theBusElement.appendChild(nodeMember); displayBuses(); } void PEMainWindow::removeBusConnector(const QString & busID, const QString & connectorID, bool display) { // called from command object // for the sake of cleaning, deletes all matching nodeMembers so be careful about the order of deletion and addition within the same parentCommand Q_UNUSED(busID); QDomElement root = m_fzpDocument.documentElement(); QDomElement buses = root.firstChildElement("buses"); QDomElement bus = buses.firstChildElement("bus"); QList toDelete; while (!bus.isNull()) { QDomElement nodeMember = bus.firstChildElement("nodeMember"); while (!nodeMember.isNull()) { if (nodeMember.attribute("connectorId").compare(connectorID) == 0) { toDelete.append(nodeMember); } nodeMember = nodeMember.nextSiblingElement("nodeMember"); } bus = bus.nextSiblingElement("bus"); } foreach (QDomElement element, toDelete) { element.parentNode().removeChild(element); } if (display) displayBuses(); } void PEMainWindow::replaceProperty(const QString & key, const QString & value, QDomElement & properties) { QDomElement prop = properties.firstChildElement("property"); while (!prop.isNull()) { QString name = prop.attribute("name"); if (name.compare(key, Qt::CaseInsensitive) == 0) { TextUtils::replaceChildText(prop, value); return; } prop = prop.nextSiblingElement("property"); } prop = m_fzpDocument.createElement("property"); properties.appendChild(prop); prop.setAttribute("name", key); TextUtils::replaceChildText(prop, value); } QWidget * PEMainWindow::createTabWidget() { QTabWidget * tabWidget = new QTabWidget(this); tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); tabWidget->setObjectName("pe_tabs"); return tabWidget; } void PEMainWindow::addTab(QWidget * widget, const QString & label) { qobject_cast(m_tabWidget)->addTab(widget, label); this -> setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } int PEMainWindow::currentTabIndex() { return qobject_cast(m_tabWidget)->currentIndex(); } void PEMainWindow::setCurrentTabIndex(int index) { qobject_cast(m_tabWidget)->setCurrentIndex(index); } QWidget * PEMainWindow::currentTabWidget() { return qobject_cast(m_tabWidget)->currentWidget(); } bool PEMainWindow::event(QEvent * e) { if (e->type() == QEvent::Close) { //qDebug() << "event close"; //if (m_inFocusWidgets.count() > 0) { // e->ignore(); // qDebug() << "bail in focus"; // return true; //} } return MainWindow::event(e); } bool PEMainWindow::eventFilter(QObject *object, QEvent *event) { if (m_inPickMode) { switch (event->type()) { case QEvent::MouseButtonPress: clearPickMode(); { QMouseEvent * mouseEvent = static_cast(event); m_useNextPick = (mouseEvent->button() == Qt::LeftButton); } QTimer::singleShot(1, this, SLOT(resetNextPick())); break; case QEvent::ApplicationActivate: case QEvent::ApplicationDeactivate: case QEvent::WindowActivate: case QEvent::WindowDeactivate: case QEvent::NonClientAreaMouseButtonPress: clearPickMode(); break; case QEvent::KeyPress: { QKeyEvent * kevent = static_cast(event); if (kevent->key() == Qt::Key_Escape) { clearPickMode(); return true; } } default: break; } return false; } //qDebug() << "event" << event->type(); if (event->type() == QEvent::FocusIn) { QLineEdit * lineEdit = qobject_cast(object); if (lineEdit != NULL) { if (lineEdit->window() == this) { qDebug() << "inc focus"; m_inFocusWidgets << lineEdit; } } else { QTextEdit * textEdit = qobject_cast(object); if (textEdit != NULL && textEdit->window() == this) { qDebug() << "inc focus"; m_inFocusWidgets << textEdit; } } } if (event->type() == QEvent::FocusOut) { QLineEdit * lineEdit = qobject_cast(object); if (lineEdit != NULL) { if (lineEdit->window() == this) { qDebug() << "dec focus"; m_inFocusWidgets.removeOne(lineEdit); } } else { QTextEdit * textEdit = qobject_cast(object); if (textEdit != NULL && textEdit->window() == this) { qDebug() << "inc focus"; m_inFocusWidgets.removeOne(textEdit); } } } return false; } void PEMainWindow::closeLater() { close(); } void PEMainWindow::resetNextPick() { m_useNextPick = false; } void PEMainWindow::clearPickMode() { qApp->removeEventFilter(this); m_useNextPick = m_inPickMode = false; QApplication::restoreOverrideCursor(); if (m_currentGraphicsView) { foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi) pegi->setPickAppearance(false); } } } QList PEMainWindow::getPegiList(SketchWidget * sketchWidget) { // DebugDialog::debug("-----------------------------"); QList pegiList; foreach (QGraphicsItem * item, sketchWidget->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) continue; pegiList.append(pegi); /* if (pegi->showingTerminalPoint() || pegi->showingMarquee() || !pegi->element().attribute("id").isEmpty()) { DebugDialog::debug(QString("pegi m:%1 t:%2 %3") .arg(pegi->showingMarquee()) .arg(pegi->showingTerminalPoint()) .arg(pegi->element().attribute("id"))); } */ } //DebugDialog::debug("-----------------------------"); return pegiList; } void PEMainWindow::deleteBuses() { QList toDelete; foreach (ViewThing * viewThing, m_viewThings.values()) { foreach (QGraphicsItem * item, viewThing->sketchWidget->scene()->items()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; toDelete << wire; } } foreach (Wire * wire, toDelete) { delete wire; } } void PEMainWindow::connectorsTypeChanged(Connector::ConnectorType ct) { QUndoCommand * parentCommand = NULL; QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { ConnectorMetadata oldCmd; fillInMetadata(connector, oldCmd); if (oldCmd.connectorType != ct) { if (parentCommand == NULL) { parentCommand = new QUndoCommand(tr("Change all connectors to %1").arg(Connector::connectorNameFromType(ct))); } ConnectorMetadata cmd = oldCmd; cmd.connectorType = ct; new ChangeConnectorMetadataCommand(this, &oldCmd, &cmd, parentCommand); } connector = connector.nextSiblingElement("connector"); } if (parentCommand) { m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } } void PEMainWindow::fillInMetadata(const QDomElement & connector, ConnectorMetadata & cmd) { cmd.connectorID = connector.attribute("id"); cmd.connectorType = Connector::connectorTypeFromName(connector.attribute("type")); cmd.connectorName = connector.attribute("name"); QDomElement description = connector.firstChildElement("description"); cmd.connectorDescription = description.text(); } void PEMainWindow::smdChanged(const QString & after) { QString before; bool toSMD = true; if (after.compare("smd", Qt::CaseInsensitive) != 0) { before = "smd"; toSMD = false; } ViewThing * viewThing = m_viewThings.value(ViewLayer::PCBView); ItemBase * itemBase = viewThing->itemBase; if (itemBase == NULL) return; QFile file(itemBase->filename()); QDomDocument svgDoc; svgDoc.setContent(&file); QDomElement svgRoot = svgDoc.documentElement(); QDomElement svgCopper0 = TextUtils::findElementWithAttribute(svgRoot, "id", "copper0"); QDomElement svgCopper1 = TextUtils::findElementWithAttribute(svgRoot, "id", "copper1"); if (svgCopper0.isNull() && svgCopper1.isNull()) { QMessageBox::critical(NULL, tr("Parts Editor"), tr("Unable to parse '%1'").arg(itemBase->filename())); return; } if (toSMD) { if (svgCopper0.isNull() && !svgCopper1.isNull()) { // everything is fine } else if (svgCopper1.isNull()) { // just needs a swap svgCopper0.setAttribute("id", "copper1"); } else { svgCopper0.removeAttribute("id"); } } else { if (!svgCopper0.isNull() && !svgCopper1.isNull()) { // everything is fine } else if (svgCopper1.isNull()) { svgCopper1 = m_pcbDocument.createElement("g"); svgCopper1.setAttribute("id", "copper1"); svgRoot.appendChild(svgCopper1); QDomElement child = svgCopper0.firstChildElement(); while (!child.isNull()) { QDomElement next = child.nextSiblingElement(); svgCopper1.appendChild(child); child = next; } svgCopper0.appendChild(svgCopper1); } else { svgCopper0 = m_pcbDocument.createElement("g"); svgCopper0.setAttribute("id", "copper0"); svgRoot.appendChild(svgCopper0); QDomElement child = svgCopper1.firstChildElement(); while (!child.isNull()) { QDomElement next = child.nextSiblingElement(); svgCopper0.appendChild(child); child = next; } svgCopper1.appendChild(svgCopper0); } } QString newPath = m_userPartsFolderSvgPath + makeSvgPath2(m_pcbGraphicsView); QString svg = TextUtils::svgNSOnly(svgDoc.toString()); writeXml(newPath, removeGorn(svg), true); ChangeSMDCommand * csc = new ChangeSMDCommand(this, before, after, itemBase->filename(), newPath, NULL); csc->setText(tr("Change to %1").arg(after)); m_undoStack->waitPush(csc, SketchWidget::PropChangeDelay); } void PEMainWindow::changeSMD(const QString & after, const QString & filename, int changeDirection) { QDomElement root = m_fzpDocument.documentElement(); QDomElement views = root.firstChildElement("views"); QDomElement pcbView = views.firstChildElement("pcbView"); QDomElement layers = pcbView.firstChildElement("layers"); QDomElement copper0 = TextUtils::findElementWithAttribute(layers, "layerId", "copper0"); QDomElement copper1 = TextUtils::findElementWithAttribute(layers, "layerId", "copper1"); bool toSMD = true; if (after.compare("smd", Qt::CaseInsensitive) == 0) { if (!copper0.isNull()) { copper0.parentNode().removeChild(copper0); } } else { toSMD = false; if (copper0.isNull()) { copper0 = m_fzpDocument.createElement("layer"); copper0.setAttribute("layerId", "copper0"); layers.appendChild(copper0); } } if (copper1.isNull()) { copper1 = m_fzpDocument.createElement("layer"); copper1.setAttribute("layerId", "copper1"); layers.appendChild(copper1); } QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { setConnectorSMD(toSMD, connector); connector = connector.nextSiblingElement("connector"); } changeSvg(m_pcbGraphicsView, filename, changeDirection); } void PEMainWindow::setConnectorSMD(bool toSMD, QDomElement & connector) { QDomElement views = connector.firstChildElement("views"); QDomElement pcbView = views.firstChildElement("pcbView"); QDomElement copper0 = TextUtils::findElementWithAttribute(pcbView, "layer", "copper0"); QDomElement copper1 = TextUtils::findElementWithAttribute(pcbView, "layer", "copper1"); if (copper0.isNull() && copper1.isNull()) { // SVG is seriously messed up DebugDialog::debug("setting SMD is very broken"); return; } if (toSMD) { if (copper0.isNull() && !copper1.isNull()) { // already correct return; } if (copper1.isNull()) { // swap it to copper1 copper0.setAttribute("layer", "copper1"); return; } // remove the extra layer copper0.parentNode().removeChild(copper0); return; } if (!copper0.isNull() && !copper1.isNull()) { // already correct return; } if (copper1.isNull()) { copper1 = copper0.cloneNode(true).toElement(); copper0.parentNode().appendChild(copper1); copper1.setAttribute("layer", "copper1"); return; } copper0 = copper1.cloneNode(true).toElement(); copper1.parentNode().appendChild(copper0); copper0.setAttribute("layer", "copper0"); } void PEMainWindow::reuseBreadboard() { reuseImage(ViewLayer::BreadboardView); } void PEMainWindow::reuseSchematic() { reuseImage(ViewLayer::SchematicView); } void PEMainWindow::reusePCB() { reuseImage(ViewLayer::PCBView); } void PEMainWindow::reuseImage(ViewLayer::ViewID viewID) { if (m_currentGraphicsView == NULL) return; ViewThing * afterViewThing = m_viewThings.value(viewID); if (afterViewThing->itemBase == NULL) return; QString afterFilename = afterViewThing->itemBase->filename(); ViewThing * beforeViewThing = m_viewThings.value(m_currentGraphicsView->viewID()); ChangeSvgCommand * csc = new ChangeSvgCommand(this, m_currentGraphicsView, beforeViewThing->itemBase->filename(), afterFilename, NULL); QFileInfo info(afterFilename); csc->setText(QString("Load '%1'").arg(info.fileName())); m_undoStack->waitPush(csc, SketchWidget::PropChangeDelay); } void PEMainWindow::updateFileMenu() { MainWindow::updateFileMenu(); m_saveAct->setEnabled(canSave()); /* QHash enabled; enabled.insert(ViewLayer::BreadboardView, true); enabled.insert(ViewLayer::SchematicView, true); enabled.insert(ViewLayer::PCBView, true); bool enableAll = true; if (m_currentGraphicsView == NULL) { enableAll = false; } else { ViewLayer::ViewID viewID = m_currentGraphicsView->viewID(); enabled.insert(viewID, false); } m_reuseBreadboardAct->setEnabled(enableAll && enabled.value(ViewLayer::BreadboardView)); m_reuseSchematicAct->setEnabled(enableAll && enabled.value(ViewLayer::SchematicView)); m_reusePCBAct->setEnabled(enableAll && enabled.value(ViewLayer::PCBView)); */ bool enabled = m_currentGraphicsView != NULL && m_currentGraphicsView->viewID() == ViewLayer::IconView; m_reuseBreadboardAct->setEnabled(enabled); m_reuseSchematicAct->setEnabled(enabled); m_reusePCBAct->setEnabled(enabled); } void PEMainWindow::setImageAttribute(QDomElement & fzpRoot, const QString & svgPath, ViewLayer::ViewID viewID) { QDomElement views = fzpRoot.firstChildElement("views"); QDomElement view = views.firstChildElement(ViewLayer::viewIDXmlName(viewID)); QDomElement layers = view.firstChildElement("layers"); QFileInfo info(svgPath); QDir dir = info.absoluteDir(); QString shortName = dir.dirName() + "/" + info.fileName(); setImageAttribute(layers, shortName); } void PEMainWindow::setImageAttribute(QDomElement & layers, const QString & svgPath) { layers.setAttribute("image", svgPath); QDomElement layer = layers.firstChildElement("layer"); if (!layer.isNull()) return; layer = m_fzpDocument.createElement("layer"); layers.appendChild(layer); layer.setAttribute("layerId", ViewLayer::viewLayerXmlNameFromID(ViewLayer::UnknownLayer)); } void PEMainWindow::updateLayerMenu(bool resetLayout) { MainWindow::updateLayerMenu(resetLayout); bool enabled = false; if (m_currentGraphicsView != NULL) { switch (m_currentGraphicsView->viewID()) { case ViewLayer::BreadboardView: case ViewLayer::SchematicView: case ViewLayer::PCBView: enabled = true; default: break; } } m_hideOtherViewsAct->setEnabled(enabled); } void PEMainWindow::hideOtherViews() { if (m_currentGraphicsView == NULL) return; ViewLayer::ViewID afterViewID = m_currentGraphicsView->viewID(); ItemBase * afterItemBase = m_viewThings.value(afterViewID)->itemBase; if (afterItemBase == NULL) return; QString afterFilename = afterItemBase->filename(); QList viewIDList; viewIDList << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView; viewIDList.removeOne(afterViewID); QString originalPath = saveFzp(); QString afterViewName = ViewLayer::viewIDXmlName(afterViewID); QStringList beforeViewNames; foreach (ViewLayer::ViewID viewID, viewIDList) { beforeViewNames << ViewLayer::viewIDXmlName(viewID); } QDomElement root = m_fzpDocument.documentElement(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement views = connector.firstChildElement("views"); QDomElement afterView = views.firstChildElement(afterViewName); foreach (QString name, beforeViewNames) { QDomElement toRemove = views.firstChildElement(name); if (!toRemove.isNull()) { toRemove.parentNode().removeChild(toRemove); } QDomElement toReplace = afterView.cloneNode(true).toElement(); toReplace.setTagName(name); views.appendChild(toReplace); } connector = connector.nextSiblingElement("connector"); } QDomElement views = root.firstChildElement("views"); QDomElement afterView = views.firstChildElement(afterViewName); foreach (QString name, beforeViewNames) { QDomElement toRemove = views.firstChildElement(name); if (!toRemove.isNull()) { toRemove.parentNode().removeChild(toRemove); } QDomElement toReplace = afterView.cloneNode(true).toElement(); toReplace.setTagName(name); views.appendChild(toReplace); } QString newPath = saveFzp(); ChangeFzpCommand * cfc = new ChangeFzpCommand(this, originalPath, newPath, NULL); cfc->setText(tr("Make only %1 view visible").arg(m_currentGraphicsView->viewName())); m_undoStack->waitPush(cfc, SketchWidget::PropChangeDelay); } QString PEMainWindow::makeNewVariant(const QString & family) { QStringList variants = m_referenceModel->propValues(family, "variant", true); int theMax = std::numeric_limits::max(); QString candidate; for (int i = 1; i < theMax; i++) { candidate = QString("variant %1").arg(i); if (!variants.contains(candidate, Qt::CaseInsensitive)) break; } return candidate; } void PEMainWindow::updateAssignedConnectors() { if (m_currentGraphicsView == NULL) return; QDomDocument * doc = m_viewThings.value(m_currentGraphicsView->viewID())->document; if (doc) m_peToolView->showAssignedConnectors(doc, m_currentGraphicsView->viewID()); } void PEMainWindow::connectorWarning() { QHash unassigned; foreach (ViewLayer::ViewID viewID, m_viewThings.keys()) { unassigned.insert(viewID, 0); } int unassignedTotal = 0; QDomElement fzpRoot = m_fzpDocument.documentElement(); QDomElement connectors = fzpRoot.firstChildElement("connectors"); foreach (ViewLayer::ViewID viewID, m_viewThings.keys()) { if (viewID == ViewLayer::IconView) continue; QDomDocument * svgDoc = m_viewThings.value(viewID)->document; QDomElement svgRoot = svgDoc->documentElement(); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString svgID, terminalID; if (ViewLayer::getConnectorSvgIDs(connector, viewID, svgID, terminalID)) { QDomElement element = TextUtils::findElementWithAttribute(svgRoot, "id", svgID); if (element.isNull()) { unassigned.insert(viewID, 1 + unassigned.value(viewID)); unassignedTotal++; } } else { unassigned.insert(viewID, 1 + unassigned.value(viewID)); unassignedTotal++; } connector = connector.nextSiblingElement("connector"); } } if (unassignedTotal > 0) { int viewCount = 0; foreach (ViewLayer::ViewID viewID, unassigned.keys()) { if (unassigned.value(viewID) > 0) viewCount++; } QMessageBox::warning(NULL, tr("Parts Editor"), tr("This part has %n unassigned connectors ", "", unassignedTotal) + tr("across %n views. ", "", viewCount) + tr("Until all connectors are assigned to SVG elements, the part will not work correctly. ") + tr("Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later.") ); } } void PEMainWindow::showing(SketchWidget * sketchWidget) { ViewThing * viewThing = m_viewThings.value(sketchWidget->viewID()); if (viewThing->firstTime) { viewThing->firstTime = false; QPointF offset = viewThing->sketchWidget->alignOneToGrid(viewThing->itemBase); if (offset.x() != 0 || offset.y() != 0) { QList pegiList = getPegiList(sketchWidget); foreach (PEGraphicsItem * pegi, pegiList) { pegi->setPos(pegi->pos() + offset); pegi->setOffset(pegi->offset() + offset); } } } } bool PEMainWindow::anyMarquee() { if (m_currentGraphicsView == NULL) return false; QList pegiList = getPegiList(m_currentGraphicsView); foreach (PEGraphicsItem * pegi, pegiList) { if (pegi->showingMarquee()) { return true; } } return false; } bool PEMainWindow::anyVisible() { if (m_currentGraphicsView == NULL) return false; foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) continue; return pegi->isVisible(); } return false; } void PEMainWindow::changeReferenceFile(ViewLayer::ViewID viewID, const QString referenceFile) { ViewThing * viewThing = m_viewThings.value(viewID); if (viewThing == NULL) { // shouldn't happen DebugDialog::debug(QString("missing view thing for %1").arg(viewID)); return; } viewThing->referenceFile = referenceFile; } void PEMainWindow::insertDesc(const QString & referenceFile, QString & svg) { if (svg.contains(ReferenceFileString)) return; int ix = svg.indexOf("= 0) { int jx = svg.indexOf(">", ix); if (jx > ix) { svg.insert(jx + 1, makeDesc(referenceFile)); } } } void PEMainWindow::itemAddedSlot(ModelPart *, ItemBase * itemBase, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, SketchWidget *) { Q_UNUSED(id); if (itemBase == NULL) return; if (itemBase->viewID() != m_currentGraphicsView->viewID()) return; QDomElement element; double z = 0; foreach (PEGraphicsItem * pegi, getPegiList(m_currentGraphicsView)) { if (pegi->zValue() > z) z = pegi->zValue(); } QRectF bounds = itemBase->boundingRect(); makePegi(bounds.size(), QPointF(0, 0), itemBase, element, z + 1); } void PEMainWindow::itemMovedSlot(ItemBase * itemBase) { if (itemBase == NULL) return; if (itemBase->viewID() != m_currentGraphicsView->viewID()) return; foreach (PEGraphicsItem * pegi, getPegiList(m_currentGraphicsView)) { if (pegi->itemBase() == itemBase) { pegi->setPos(itemBase->pos() + pegi->offset()); } } } void PEMainWindow::resizedSlot(ItemBase * itemBase) { if (itemBase == NULL) return; if (itemBase->viewID() != m_currentGraphicsView->viewID()) return; foreach (PEGraphicsItem * pegi, getPegiList(m_currentGraphicsView)) { if (pegi->itemBase() == itemBase) { pegi->setPos(itemBase->pos() + pegi->offset()); QRectF bounds = itemBase->boundingRect(); pegi->setRect(bounds); } } } void PEMainWindow::clickedItemCandidateSlot(QGraphicsItem * item, bool & ok) { PEGraphicsItem * pegi = dynamic_cast(item); if (pegi == NULL) { ok = true; return; } ok = pegi->showingMarquee(); } void PEMainWindow::initProgrammingWidget() { } void PEMainWindow::initWelcomeView() { } void PEMainWindow::setInitialView() { // do this the first time, since the current_changed signal wasn't sent int tab = 0; tabWidget_currentChanged(tab+1); tabWidget_currentChanged(tab); } void PEMainWindow::updateExportMenu() { foreach (QAction * action, m_exportMenu->actions()) { action->setEnabled(false); } } void PEMainWindow::convertToTenth() { if (m_currentGraphicsView == NULL) return; if (m_currentGraphicsView->viewID() != ViewLayer::SchematicView) return; QString originalFzpPath = saveFzp(); QString newFzpPath = saveFzp(); ViewThing * viewThing = m_viewThings.value(m_currentGraphicsView->viewID()); QString originalSvgPath = viewThing->itemBase->filename(); QString newSvgPath = m_userPartsFolderSvgPath + makeSvgPath2(m_currentGraphicsView); QFile::copy(originalSvgPath, newSvgPath); S2S s2s(false); connect(&s2s, SIGNAL(messageSignal(const QString &)), this, SLOT(s2sMessageSlot(const QString &))); bool result = s2s.onefzp(newFzpPath, newSvgPath); if (!result) return; // if conversion fails QUndoCommand * parentCommand = new QUndoCommand("Convert Schematic"); new ChangeFzpCommand(this, originalFzpPath, newFzpPath, parentCommand); new ChangeSvgCommand(this, m_currentGraphicsView, originalSvgPath, newSvgPath, parentCommand); m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay); } void PEMainWindow::s2sMessageSlot(const QString & message) { QMessageBox::information(this, "Schematic Conversion", message); } void PEMainWindow::updateEditMenu() { MainWindow::updateEditMenu(); m_convertToTenthAct->setEnabled(m_currentGraphicsView != NULL && m_currentGraphicsView->viewID() == ViewLayer::SchematicView); } fritzing-app-0.9.2b/src/partseditor/pemainwindow.h000066400000000000000000000243161250202676700223140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6943 $: $Author: irascibl@gmail.com $: $Date: 2013-03-30 14:06:38 +0100 (Sa, 30. Mrz 2013) $ ********************************************************************/ #ifndef PEMAINWINDOW_H_ #define PEMAINWINDOW_H_ #include "../mainwindow/mainwindow.h" #include "../model/modelpartshared.h" #include "../sketch/sketchwidget.h" #include "peconnectorsview.h" class IconSketchWidget : public SketchWidget { Q_OBJECT public: IconSketchWidget(ViewLayer::ViewID, QWidget *parent=0); void addViewLayers(); }; struct ViewThing { ItemBase * itemBase; QDomDocument * document; int svgChangeCount; bool everZoomed; SketchWidget * sketchWidget; QString referenceFile; QString originalSvgPath; bool firstTime; bool busMode; ViewThing(); }; class PEMainWindow : public MainWindow { Q_OBJECT public: PEMainWindow(class ReferenceModel * referenceModel, QWidget * parent); ~PEMainWindow(); bool setInitialItem(class PaletteItem *); void changeTags(const QStringList &, bool updateDisplay); void changeProperties(const QHash &, bool updateDisplay); void changeMetadata(const QString & name, const QString & value, bool updateDisplay); void changeConnectorMetadata(ConnectorMetadata *, bool updateDisplay); void changeSvg(SketchWidget *, const QString & filename, int changeDirection); void relocateConnectorSvg(SketchWidget *, const QString & id, const QString & terminalID, const QString & oldGorn, const QString & oldGornTerminal, const QString & newGorn, const QString & newGornTerminal, int changeDirection); void moveTerminalPoint(SketchWidget *, const QString & id, QSizeF, QPointF, int changeDirection); void restoreFzp(const QString & filename); bool editsModuleID(const QString &); void addBusConnector(const QString & busID, const QString & connectorID); void removeBusConnector(const QString & busID, const QString & connectorID, bool display); void changeSMD(const QString & smd, const QString & filename, int changeDirection); void changeReferenceFile(ViewLayer::ViewID viewID, const QString referenceFile); void changeOriginalFile(ViewLayer::ViewID viewID, const QString originalFile, int changeCount); signals: void addToMyPartsSignal(ModelPart *); public slots: void metadataChanged(const QString & name, const QString & value); void propertiesChanged(const QHash &); void tagsChanged(const QStringList &); void connectorMetadataChanged(struct ConnectorMetadata *); void removedConnectors(QList &); void highlightSlot(class PEGraphicsItem *); void pegiMousePressed(class PEGraphicsItem *, bool & ignore); void pegiMouseReleased(class PEGraphicsItem *); void pegiTerminalPointMoved(class PEGraphicsItem *, QPointF); void pegiTerminalPointChanged(class PEGraphicsItem *, QPointF before, QPointF after); void switchedConnector(int); void removedConnector(const QDomElement &); void terminalPointChanged(const QString & how); void terminalPointChanged(const QString & coord, double value); void getSpinAmount(double & amount); void pickModeChanged(bool); void busModeChanged(bool); void connectorCountChanged(int); void deleteBusConnection(); void newWireSlot(Wire *); void wireChangedSlot(class Wire*, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, ConnectorItem * from, ConnectorItem * to); void connectorsTypeChanged(Connector::ConnectorType); void smdChanged(const QString &); void showing(SketchWidget *); void updateExportMenu(); void updateEditMenu(); void s2sMessageSlot(const QString & message); protected: void closeEvent(QCloseEvent * event); bool event(QEvent *); void initLockedFiles(bool lockFiles); void initSketchWidgets(bool withIcons); void initProgrammingWidget(); void initDock(); void moreInitDock(); void setInitialView(); void createActions(); void createMenus(); QList getButtonsForView(ViewLayer::ViewID); void connectPairs(); QMenu *breadboardItemMenu(); QMenu *schematicItemMenu(); QMenu *pcbItemMenu(); QMenu *pcbWireMenu(); QMenu *schematicWireMenu(); QMenu *breadboardWireMenu(); void setTitle(); void createViewMenuActions(bool showWelcome); void createFileMenuActions(); void createViewMenu(); void createEditMenu(); QHash getOldProperties(); QDomElement findConnector(const QString & id, int & index); void changeConnectorElement(QDomElement & connector, ConnectorMetadata *); void initSvgTree(SketchWidget *, ItemBase *, QDomDocument &); void initConnectors(bool updateConnectorsView); QString createSvgFromImage(const QString &origFilePath); // QString makeSvgPath(const QString & referenceFile, SketchWidget * sketchWidget, bool useIndex); QString makeSvgPath2(SketchWidget * sketchWidget); QString saveFzp(); void reload(bool firstTime); void createFileMenu(); void updateChangeCount(SketchWidget * sketchWidget, int changeDirection); class PEGraphicsItem * findConnectorItem(); void terminalPointChangedAux(PEGraphicsItem * pegi, QPointF before, QPointF after); void showInOS(QWidget *parent, const QString &pathIn); void switchedConnector(int, SketchWidget *); PEGraphicsItem * makePegi(QSizeF size, QPointF topLeft, ItemBase * itemBase, QDomElement & element, double z); QRectF getPixelBounds(FSvgRenderer & renderer, QDomElement & element); bool canSave(); bool saveAs(bool overWrite); void setBeforeClosingText(const QString & filename, QMessageBox & messageBox); QString getPartTitle(); void killPegi(); bool loadFzp(const QString & path); void removedConnectorsAux(QList & connectors); //QString getFzpReferenceFile(); QString getSvgReferenceFile(const QString & filename); QString makeDesc(const QString & referenceFile); void insertDesc(const QString & referenceFile, QString & svg); void updateRaiseWindowAction(); bool writeXml(const QString & path, const QString & text, bool temp); void displayBuses(); QDomElement findBus(const QDomElement &, const QString &); QDomElement findNodeMemberBus(const QDomElement & buses, const QString & connectorID); void replaceProperty(const QString & key, const QString & value, QDomElement & properties); QWidget * createTabWidget(); void addTab(QWidget * widget, const QString & label); int currentTabIndex(); void setCurrentTabIndex(int); QWidget * currentTabWidget(); void changeSpecialProperty(const QString & name, const QString & value); bool eventFilter(QObject *, QEvent *); void relocateConnector(PEGraphicsItem * pegi); void clearPickMode(); void deleteBuses(); QList getPegiList(SketchWidget *); void fillInMetadata(const QDomElement & connector, ConnectorMetadata & cmd); void setConnectorSMD(bool toSMD, QDomElement & connector); bool activeLayerWidgetAlwaysOn(); void updateFileMenu(); void reuseImage(ViewLayer::ViewID); void setImageAttribute(QDomElement & layers, const QString & image); void setImageAttribute(QDomElement & fzpRoot, const QString & svgPath, ViewLayer::ViewID viewID); QString makeNewVariant(const QString & family); void connectorWarning(); bool anyMarquee(); bool anyVisible(); QString makeDirName(); void initWelcomeView(); protected slots: void initZoom(); void showMetadataView(); void showConnectorsView(); void showIconView(); void loadImage(); bool save(); bool saveAs(); void showInOS(); void tabWidget_currentChanged(int index); void backupSketch(); void updateWindowMenu(); void updateWireMenu(); void closeLater(); void resetNextPick(); void reuseBreadboard(); void reuseSchematic(); void reusePCB(); void convertToTenth(); void hideOtherViews(); void updateLayerMenu(bool resetLayout = false); void updateAssignedConnectors(); void itemAddedSlot(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, SketchWidget * dropOrigin); void itemMovedSlot(ItemBase *); void clickedItemCandidateSlot(QGraphicsItem *, bool & ok); void resizedSlot(ItemBase *); protected: QDomDocument m_fzpDocument; QDomDocument m_iconDocument; QDomDocument m_breadboardDocument; QDomDocument m_schematicDocument; QDomDocument m_pcbDocument; QAction * m_showMetadataViewAct; QAction * m_showConnectorsViewAct; QAction * m_showIconAct; QAction * m_showInOSAct; class WireAction * m_deleteBusConnectionAct; QAction * m_reuseBreadboardAct; QAction * m_reuseSchematicAct; QAction * m_reusePCBAct; QAction * m_hideOtherViewsAct; QAction * m_convertToTenthAct; QPointer m_iconWidget; QPointer m_iconGraphicsView; class PEMetadataView * m_metadataView; class PEConnectorsView * m_connectorsView; class PEToolView * m_peToolView; class PESvgView * m_peSvgView; QString m_guid; QString m_prefix; int m_fileIndex; QHash m_viewThings; QString m_userPartsFolderPath; QString m_userPartsFolderSvgPath; bool m_canSave; QString m_originalFzpPath; QString m_originalModuleID; bool m_gaveSaveWarning; QStringList m_filesToDelete; QList< QPointer > m_inFocusWidgets; bool m_inPickMode; bool m_useNextPick; QList m_connectorList; QString m_removedConnector; }; #endif /* PEMAINWINDOW_H_ */ fritzing-app-0.9.2b/src/partseditor/pemetadataview.cpp000066400000000000000000000230661250202676700231470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include "pemetadataview.h" #include "hashpopulatewidget.h" ////////////////////////////////////// FocusOutTextEdit::FocusOutTextEdit(QWidget * parent) : QTextEdit(parent) { } FocusOutTextEdit::~FocusOutTextEdit() { } void FocusOutTextEdit::focusOutEvent(QFocusEvent * e) { QTextEdit::focusOutEvent(e); if (document()->isModified()) { emit focusOut(); document()->setModified(false); } } ////////////////////////////////////// PEMetadataView::PEMetadataView(QWidget * parent) : QScrollArea(parent) { m_mainFrame = NULL; this->setWidgetResizable(true); this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } PEMetadataView::~PEMetadataView() { } void PEMetadataView::titleEntry() { if (m_titleEdit->isModified()) { emit metadataChanged("title", m_titleEdit->text()); m_titleEdit->setModified(false); } } void PEMetadataView::authorEntry() { if (m_authorEdit->isModified()) { emit metadataChanged("author", m_authorEdit->text()); m_authorEdit->setModified(false); } } void PEMetadataView::descriptionEntry() { if (m_descriptionEdit->document()->isModified()) { emit metadataChanged("description", m_descriptionEdit->toHtml()); m_descriptionEdit->document()->setModified(false); } } void PEMetadataView::urlEntry() { if (m_urlEdit->isModified()) { emit metadataChanged("url", m_urlEdit->text()); m_urlEdit->setModified(false); } } void PEMetadataView::labelEntry() { if (m_labelEdit->isModified()) { emit metadataChanged("label", m_labelEdit->text()); m_labelEdit->setModified(false); } } void PEMetadataView::familyEntry() { if (m_familyEdit->isModified()) { emit metadataChanged("family", m_familyEdit->text()); m_familyEdit->setModified(false); } } void PEMetadataView::variantEntry() { if (m_variantEdit->isModified()) { emit metadataChanged("variant", m_variantEdit->text()); m_variantEdit->setModified(false); } } void PEMetadataView::dateEntry() { } void PEMetadataView::propertiesEntry() { emit propertiesChanged(m_propertiesEdit->hash()); } const QHash & PEMetadataView::properties() { return m_propertiesEdit->hash(); } void PEMetadataView::tagsEntry() { static QStringList keys; keys = m_tagsEdit->hash().keys(); emit tagsChanged(keys); } void PEMetadataView::initMetadata(const QDomDocument & doc) { QWidget * widget = QApplication::focusWidget(); if (widget) { QList children = m_mainFrame->findChildren(); if (children.contains(widget)) { widget->blockSignals(true); } } if (m_mainFrame) { this->setWidget(NULL); delete m_mainFrame; m_mainFrame = NULL; } QDomElement root = doc.documentElement(); QDomElement label = root.firstChildElement("label"); QDomElement author = root.firstChildElement("author"); QDomElement descr = root.firstChildElement("description"); QDomElement title = root.firstChildElement("title"); QDomElement date = root.firstChildElement("date"); QDomElement url = root.firstChildElement("url"); QStringList readOnlyKeys; QHash tagHash; QDomElement tags = root.firstChildElement("tags"); QDomElement tag = tags.firstChildElement("tag"); while (!tag.isNull()) { tagHash.insert(tag.text(), ""); tag = tag.nextSiblingElement("tag"); } QString family; QString variant; QHash propertyHash; QDomElement properties = root.firstChildElement("properties"); QDomElement prop = properties.firstChildElement("property"); while (!prop.isNull()) { QString name = prop.attribute("name"); QString value = prop.text(); if (name.compare("family", Qt::CaseInsensitive) == 0) { family = value; } else if (name.compare("variant", Qt::CaseInsensitive) == 0) { variant = value; } else { propertyHash.insert(name, value); } prop = prop.nextSiblingElement("property"); } m_mainFrame = new QFrame(this); m_mainFrame->setObjectName("metadataMainFrame"); QVBoxLayout *mainLayout = new QVBoxLayout(m_mainFrame); mainLayout->setSizeConstraint( QLayout::SetMinAndMaxSize ); QLabel *explanation = new QLabel(tr("This is where you edit the metadata for the part ...")); mainLayout->addWidget(explanation); QFormLayout * formLayout = new QFormLayout(); QFrame * formFrame = new QFrame; mainLayout->addWidget(formFrame); m_titleEdit = new QLineEdit(); m_titleEdit->setText(title.text()); connect(m_titleEdit, SIGNAL(editingFinished()), this, SLOT(titleEntry())); m_titleEdit->setObjectName("PartsEditorLineEdit"); m_titleEdit->setStatusTip(tr("Set the part's title")); formLayout->addRow(tr("Title"), m_titleEdit); m_dateEdit = new QLineEdit(); m_dateEdit->setText(date.text()); connect(m_dateEdit, SIGNAL(editingFinished()), this, SLOT(dateEntry())); m_dateEdit->setObjectName("PartsEditorLineEdit"); m_dateEdit->setStatusTip(tr("Set the part's date")); m_dateEdit->setEnabled(false); formLayout->addRow(tr("Date"), m_dateEdit); m_authorEdit = new QLineEdit(); m_authorEdit->setText(author.text()); connect(m_authorEdit, SIGNAL(editingFinished()), this, SLOT(authorEntry())); m_authorEdit->setObjectName("PartsEditorLineEdit"); m_authorEdit->setStatusTip(tr("Set the part's author")); formLayout->addRow(tr("Author"), m_authorEdit); m_descriptionEdit = new FocusOutTextEdit(); m_descriptionEdit->setText(descr.text()); m_descriptionEdit->document()->setModified(false); connect(m_descriptionEdit, SIGNAL(focusOut()), this, SLOT(descriptionEntry())); m_descriptionEdit->setObjectName("PartsEditorTextEdit"); m_descriptionEdit->setStatusTip(tr("Set the part's description--you can use simple html (as defined by Qt's Rich Text)")); formLayout->addRow(tr("Description"), m_descriptionEdit); m_labelEdit = new QLineEdit(); m_labelEdit->setText(label.text()); connect(m_labelEdit, SIGNAL(editingFinished()), this, SLOT(labelEntry())); m_labelEdit->setObjectName("PartsEditorLineEdit"); m_labelEdit->setStatusTip(tr("Set the default part label prefix")); formLayout->addRow(tr("Label"), m_labelEdit); m_urlEdit = new QLineEdit(); m_urlEdit->setText(url.text()); connect(m_urlEdit, SIGNAL(editingFinished()), this, SLOT(urlEntry())); m_urlEdit->setObjectName("PartsEditorLineEdit"); m_urlEdit->setStatusTip(tr("Set the part's url if it is described on a web page")); formLayout->addRow(tr("URL"), m_urlEdit); m_familyEdit = new QLineEdit(); m_familyEdit->setText(family); connect(m_familyEdit, SIGNAL(editingFinished()), this, SLOT(familyEntry())); m_familyEdit->setObjectName("PartsEditorLineEdit"); m_familyEdit->setStatusTip(tr("Set the part's family--what other parts is this part related to")); formLayout->addRow(tr("Family"), m_familyEdit); m_variantEdit = new QLineEdit(); m_variantEdit->setText(variant); connect(m_variantEdit, SIGNAL(editingFinished()), this, SLOT(variantEntry())); m_variantEdit->setObjectName("PartsEditorLineEdit"); m_variantEdit->setStatusTip(tr("Set the part's variant--this makes it unique from all other parts in the same family")); formLayout->addRow(tr("Variant"), m_variantEdit); m_propertiesEdit = new HashPopulateWidget("", propertyHash, readOnlyKeys, false, this); m_propertiesEdit->setObjectName("PartsEditorPropertiesEdit"); m_propertiesEdit->setStatusTip(tr("Set the part's properties")); connect(m_propertiesEdit, SIGNAL(changed()), this, SLOT(propertiesEntry())); formLayout->addRow(tr("Properties"), m_propertiesEdit); m_tagsEdit = new HashPopulateWidget("", tagHash, readOnlyKeys, true, this); m_tagsEdit->setObjectName("PartsEditorPropertiesEdit"); m_tagsEdit->setStatusTip(tr("Set the part's tags")); connect(m_tagsEdit, SIGNAL(changed()), this, SLOT(tagsEntry())); formLayout->addRow(tr("Tags"), m_tagsEdit); formFrame->setLayout(formLayout); m_mainFrame->setLayout(mainLayout); this->setWidget(m_mainFrame); } void PEMetadataView::resetProperty(const QString & name, const QString & value) { if (name == "family") m_familyEdit->setText(value); else if (name == "variant") m_variantEdit->setText(value); } QString PEMetadataView::family() { return m_familyEdit->text(); } QString PEMetadataView::variant() { return m_variantEdit->text(); } fritzing-app-0.9.2b/src/partseditor/pemetadataview.h000066400000000000000000000055121250202676700226100ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6483 $: $Author: irascibl@gmail.com $: $Date: 2012-09-26 15:45:37 +0200 (Mi, 26. Sep 2012) $ ********************************************************************/ #ifndef METADATAVIEW_H #define METADATAVIEW_H #include #include #include #include #include #include #include #include #include #include #include "../items/itembase.h" #include "../items/wire.h" #include "../connectors/connectoritem.h" #include "../referencemodel/referencemodel.h" class PEMetadataView : public QScrollArea { Q_OBJECT public: PEMetadataView(QWidget * parent = 0); ~PEMetadataView(); void initMetadata(const QDomDocument &); void resetProperty(const QString & name, const QString & value); QString family(); QString variant(); const QHash & properties(); signals: void metadataChanged(const QString & name, const QString & value); void propertiesChanged(const QHash &); void tagsChanged(const QStringList &); protected slots: void titleEntry(); void authorEntry(); void descriptionEntry(); void labelEntry(); void familyEntry(); void variantEntry(); void dateEntry(); void urlEntry(); void propertiesEntry(); void tagsEntry(); protected: QPointer m_titleEdit; QPointer m_dateEdit; QPointer m_authorEdit; QPointer m_familyEdit; QPointer m_variantEdit; QPointer m_labelEdit; QPointer m_urlEdit; QPointer m_descriptionEdit; QPointer m_propertiesEdit; QPointer m_tagsEdit; QPointer m_mainFrame; }; class FocusOutTextEdit :public QTextEdit { Q_OBJECT public: FocusOutTextEdit(QWidget * parent = 0); ~FocusOutTextEdit(); signals: void focusOut(); protected: void focusOutEvent(QFocusEvent *); }; #endif fritzing-app-0.9.2b/src/partseditor/pesvgview.cpp000066400000000000000000000104051250202676700221570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "pesvgview.h" #include "pegraphicsitem.h" #include "peutils.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../debugdialog.h" #include #include #include #include #include #include ////////////////////////////////////// PESvgView::PESvgView(QWidget * parent) : QFrame(parent) { this->setObjectName("peSVG"); m_pegi = NULL; QVBoxLayout * mainLayout = new QVBoxLayout; m_filename = new QLabel(); mainLayout->addWidget(m_filename); QFrame * boundsFrame = new QFrame; QHBoxLayout * boundsLayout = new QHBoxLayout; QLabel * label = new QLabel("x:"); boundsLayout->addWidget(label); m_x = new QLabel; boundsLayout->addWidget(m_x); boundsLayout->addSpacing(PEUtils::Spacing); label = new QLabel("y:"); boundsLayout->addWidget(label); m_y = new QLabel; boundsLayout->addWidget(m_y); boundsLayout->addSpacing(PEUtils::Spacing); label = new QLabel(tr("width:")); boundsLayout->addWidget(label); m_width = new QLabel; boundsLayout->addWidget(m_width); boundsLayout->addSpacing(PEUtils::Spacing); label = new QLabel(tr("height:")); boundsLayout->addWidget(label); m_height = new QLabel; boundsLayout->addWidget(m_height); boundsLayout->addSpacing(PEUtils::Spacing); m_units = new QLabel(); boundsLayout->addWidget(m_units); boundsLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); boundsFrame->setLayout(boundsLayout); mainLayout->addWidget(boundsFrame); m_svgElement = new QLabel; m_svgElement->setWordWrap(false); m_svgElement->setTextFormat(Qt::PlainText); mainLayout->addWidget(m_svgElement); mainLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); //this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); this->setLayout(mainLayout); } PESvgView::~PESvgView() { } void PESvgView::highlightElement(PEGraphicsItem * pegi) { m_pegi = pegi; if (pegi == NULL) { m_svgElement->setText(""); m_x->setText(""); m_y->setText(""); m_width->setText(""); m_height->setText(""); return; } QString string; QTextStream stream(&string); pegi->element().save(stream, 0); string = TextUtils::killXMLNS(string); int ix = string.indexOf("\n"); if (ix > 0) { int jx = string.indexOf("\n", ix + 1); if (jx >= 0) { string.truncate(jx - 1); } else { string.truncate(ix + 200); } } else { string.truncate(200); } m_svgElement->setText(string); QPointF p = pegi->offset(); m_x->setText(PEUtils::convertUnitsStr(p.x())); m_y->setText(PEUtils::convertUnitsStr(p.y())); QRectF r = pegi->rect(); m_width->setText(PEUtils::convertUnitsStr(r.width())); m_height->setText(PEUtils::convertUnitsStr(r.height())); m_units->setText(QString("(%1)").arg(PEUtils::Units)); } void PESvgView::setChildrenVisible(bool vis) { foreach (QWidget * widget, findChildren()) { widget->setVisible(vis); } } void PESvgView::setFilename(const QString & filename) { m_filename->setText(filename); } fritzing-app-0.9.2b/src/partseditor/pesvgview.h000066400000000000000000000033221250202676700216240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PESVGVIEW_H #define PESVGVIEW_H #include #include #include #include #include #include #include #include #include #include class PESvgView : public QFrame { Q_OBJECT public: PESvgView(QWidget * parent = NULL); ~PESvgView(); void highlightElement(class PEGraphicsItem *); void setChildrenVisible(bool vis); void setFilename(const QString &); protected: QLabel * m_svgElement; QLabel * m_height; QLabel * m_width; QLabel * m_x; QLabel * m_y; QLabel * m_filename; QLabel * m_units; class PEGraphicsItem * m_pegi; }; #endif fritzing-app-0.9.2b/src/partseditor/petoolview.cpp000066400000000000000000000365761250202676700223560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "peutils.h" #include "petoolview.h" #include "pegraphicsitem.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../debugdialog.h" #include #include #include #include #include #include #include ////////////////////////////////////// static QPixmap * CheckImage = NULL; static QPixmap * NoCheckImage = NULL; ////////////////////////////////////// PEDoubleSpinBox::PEDoubleSpinBox(QWidget * parent) : QDoubleSpinBox(parent) { } void PEDoubleSpinBox::stepBy(int steps) { double amount; emit getSpinAmount(amount); setSingleStep(amount); QDoubleSpinBox::stepBy(steps); } ////////////////////////////////////// PEToolView::PEToolView(QWidget * parent) : QFrame (parent) { m_assignButton = NULL; if (CheckImage == NULL) CheckImage = new QPixmap(":/resources/images/icons/check.png"); if (NoCheckImage == NULL) NoCheckImage = new QPixmap(":/resources/images/icons/nocheck.png"); this->setObjectName("PEToolView"); /* QFile styleSheet(":/resources/styles/newpartseditor.qss"); if (!styleSheet.open(QIODevice::ReadOnly)) { DebugDialog::debug("Unable to open :/resources/styles/newpartseditor.qss"); } else { this->setStyleSheet(styleSheet.readAll()); } */ m_pegi = NULL; QVBoxLayout * mainLayout = new QVBoxLayout; mainLayout -> setObjectName("connectorFrame"); QSplitter * splitter = new QSplitter(Qt::Vertical); mainLayout->addWidget(splitter); QFrame * connectorsFrame = new QFrame; QVBoxLayout * connectorsLayout = new QVBoxLayout; QLabel * label = new QLabel(tr("Connector List (a checkmark means the graphic was selected)")); connectorsLayout->addWidget(label); m_connectorListWidget = new QTreeWidget(); m_connectorListWidget->setColumnCount(2); connect(m_connectorListWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(switchConnector(QTreeWidgetItem *, QTreeWidgetItem *))); connectorsLayout->addWidget(m_connectorListWidget); m_busModeBox = new QCheckBox(tr("Set Internal Connections")); m_busModeBox->setChecked(false); m_busModeBox->setToolTip(tr("Set this checkbox to edit internal connections by drawing wires")); connect(m_busModeBox, SIGNAL(clicked(bool)), this, SLOT(busModeChangedSlot(bool))); connectorsLayout->addWidget(m_busModeBox); connectorsFrame->setLayout(connectorsLayout); splitter->addWidget(connectorsFrame); m_connectorInfoGroupBox = new QGroupBox; m_connectorInfoLayout = new QVBoxLayout; m_connectorInfoWidget = new QFrame; // a placeholder for PEUtils::connectorForm m_connectorInfoLayout->addWidget(m_connectorInfoWidget); m_terminalPointGroupBox = new QGroupBox("Terminal point"); m_terminalPointGroupBox->setToolTip(tr("Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector")); QVBoxLayout * anchorGroupLayout = new QVBoxLayout; QFrame * posRadioFrame = new QFrame; QHBoxLayout * posRadioLayout = new QHBoxLayout; QList positionNames; positionNames << "Center" << "W" << "N" << "S" << "E"; QList trPositionNames; trPositionNames << tr("Center") << tr("W") << tr("N") << tr("S") << tr("E"); QList trLongNames; trLongNames << tr("center") << tr("west") << tr("north") << tr("south") << tr("east"); for (int i = 0; i < positionNames.count(); i++) { QPushButton * button = new QPushButton(trPositionNames.at(i)); button->setProperty("how", positionNames.at(i)); button->setToolTip(tr("Sets the connector's terminal point to %1.").arg(trLongNames.at(i))); connect(button, SIGNAL(clicked()), this, SLOT(buttonChangeTerminalPoint())); posRadioLayout->addWidget(button); m_buttons.append(button); } posRadioLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); posRadioFrame->setLayout(posRadioLayout); anchorGroupLayout->addWidget(posRadioFrame); QFrame * posNumberFrame = new QFrame; QHBoxLayout * posNumberLayout = new QHBoxLayout; label = new QLabel("x"); posNumberLayout->addWidget(label); m_terminalPointX = new PEDoubleSpinBox; m_terminalPointX->setDecimals(4); m_terminalPointX->setToolTip(tr("Modifies the x-coordinate of the terminal point")); posNumberLayout->addWidget(m_terminalPointX); connect(m_terminalPointX, SIGNAL(getSpinAmount(double &)), this, SLOT(getSpinAmountSlot(double &)), Qt::DirectConnection); connect(m_terminalPointX, SIGNAL(valueChanged(double)), this, SLOT(terminalPointEntry())); posNumberLayout->addSpacing(PEUtils::Spacing); label = new QLabel("y"); posNumberLayout->addWidget(label); m_terminalPointY = new PEDoubleSpinBox; m_terminalPointY->setDecimals(4); m_terminalPointY->setToolTip(tr("Modifies the y-coordinate of the terminal point")); posNumberLayout->addWidget(m_terminalPointY); connect(m_terminalPointY, SIGNAL(getSpinAmount(double &)), this, SLOT(getSpinAmountSlot(double &)), Qt::DirectConnection); connect(m_terminalPointY, SIGNAL(valueChanged(double)), this, SLOT(terminalPointEntry())); posNumberLayout->addSpacing(PEUtils::Spacing); m_units = new QLabel(); posNumberLayout->addWidget(m_units); posNumberLayout->addSpacing(PEUtils::Spacing); m_terminalPointDragState = new QLabel(tr("Dragging disabled")); posNumberLayout->addWidget(m_terminalPointDragState); posNumberLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); posNumberFrame->setLayout(posNumberLayout); anchorGroupLayout->addWidget(posNumberFrame); m_terminalPointGroupBox->setLayout(anchorGroupLayout); m_connectorInfoLayout->addWidget(m_terminalPointGroupBox); m_connectorInfoLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); m_connectorInfoGroupBox->setLayout(m_connectorInfoLayout); splitter->addWidget(m_connectorInfoGroupBox); //this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //this->setWidget(splitter); this->setLayout(mainLayout); m_connectorListWidget->resize(m_connectorListWidget->width(), 0); enableConnectorChanges(false, false, false, false); } PEToolView::~PEToolView() { } void PEToolView::enableConnectorChanges(bool enableTerminalPointDrag, bool enableTerminalPointControls, bool enableInfo, bool enableAssign) { if (m_assignButton) { m_assignButton->setEnabled(enableAssign); } if (m_terminalPointGroupBox) { m_terminalPointGroupBox->setEnabled(enableTerminalPointControls); } if (m_connectorInfoWidget) { m_connectorInfoWidget->setEnabled(enableInfo); } if (m_terminalPointDragState) { if (enableTerminalPointDrag) { m_terminalPointDragState->setText(tr("Dragging enabled")); m_terminalPointDragState->setEnabled(true); } else { m_terminalPointDragState->setText(tr("Dragging disabled")); m_terminalPointDragState->setEnabled(false); } } } void PEToolView::initConnectors(QList * connectorList) { m_connectorListWidget->blockSignals(true); m_connectorListWidget->clear(); // deletes QTreeWidgetItems m_connectorList = connectorList; for (int ix = 0; ix < connectorList->count(); ix++) { QDomElement connector = connectorList->at(ix); QTreeWidgetItem *item = new QTreeWidgetItem; item->setData(0, Qt::DisplayRole, connector.attribute("name")); item->setData(0, Qt::UserRole, ix); item->setData(1, Qt::UserRole, ix); item->setData(0, Qt::DecorationRole, *NoCheckImage); m_connectorListWidget->addTopLevelItem(item); QLabel * label = new QLabel(""); //label->setPixmap(*NoCheckImage); m_connectorListWidget->setItemWidget(item, 1, label); } if (connectorList->count() > 0) { m_connectorListWidget->setCurrentItem(m_connectorListWidget->topLevelItem(0)); switchConnector(m_connectorListWidget->currentItem(), NULL); } m_connectorListWidget->blockSignals(false); } void PEToolView::showAssignedConnectors(const QDomDocument * svgDoc, ViewLayer::ViewID viewID) { QDomElement svgRoot = svgDoc->documentElement(); for (int i = 0; i < m_connectorListWidget->topLevelItemCount(); i++) { QTreeWidgetItem * item = m_connectorListWidget->topLevelItem(i); int index = item->data(0, Qt::UserRole).toInt(); QDomElement connector = m_connectorList->at(index); QString svgID, terminalID; bool ok = ViewLayer::getConnectorSvgIDs(connector, viewID, svgID, terminalID); if (!ok) { continue; } QDomElement element = TextUtils::findElementWithAttribute(svgRoot, "id", svgID); if (element.isNull()) { item->setData(0, Qt::DecorationRole, *NoCheckImage); } else { item->setData(0, Qt::DecorationRole, *CheckImage); } } hideConnectorListStuff(); m_connectorListWidget->repaint(); } void PEToolView::switchConnector(QTreeWidgetItem * current, QTreeWidgetItem * previous) { Q_UNUSED(previous); QWidget * widget = QApplication::focusWidget(); if (widget) { QList children = m_connectorInfoWidget->findChildren(); if (children.contains(widget)) { widget->blockSignals(true); } } if (m_connectorInfoWidget) { delete m_connectorInfoWidget; m_connectorInfoWidget = NULL; } if (current == NULL) return; int index = current->data(0, Qt::UserRole).toInt(); QDomElement element = m_connectorList->at(index); int pos = 99999; for (int ix = 0; ix < m_connectorInfoLayout->count(); ix++) { QLayoutItem * item = m_connectorInfoLayout->itemAt(ix); if (item->widget() == m_terminalPointGroupBox) { pos = ix; break; } } m_connectorInfoWidget = PEUtils::makeConnectorForm(element, index, this, false); m_connectorInfoLayout->insertWidget(pos, m_connectorInfoWidget); m_connectorInfoGroupBox->setTitle(tr("Connector %1").arg(element.attribute("name"))); m_units->setText(QString("(%1)").arg(PEUtils::Units)); hideConnectorListStuff(); emit switchedConnector(index); } void PEToolView::busModeChangedSlot(bool state) { emit busModeChanged(state); } void PEToolView::nameEntry() { changeConnector(); } void PEToolView::typeEntry() { changeConnector(); } void PEToolView::descriptionEntry() { changeConnector(); } void PEToolView::changeConnector() { QTreeWidgetItem * item = m_connectorListWidget->currentItem(); if (item == NULL) return; int index = item->data(0, Qt::UserRole).toInt(); ConnectorMetadata cmd; if (!PEUtils::fillInMetadata(index, this, cmd)) return; emit connectorMetadataChanged(&cmd); } void PEToolView::setCurrentConnector(const QDomElement & newConnector) { for (int ix = 0; ix < m_connectorListWidget->topLevelItemCount(); ix++) { QTreeWidgetItem * item = m_connectorListWidget->topLevelItem(ix); int index = item->data(0, Qt::UserRole).toInt(); QDomElement connector = m_connectorList->at(index); if (connector.attribute("id") == newConnector.attribute("id")) { m_connectorListWidget->setCurrentItem(item); hideConnectorListStuff(); return; } } } int PEToolView::currentConnectorIndex() { QTreeWidgetItem * item = m_connectorListWidget->currentItem(); if (item == NULL) return -1; int index = item->data(0, Qt::UserRole).toInt(); return index; } void PEToolView::setTerminalPointCoords(QPointF p) { m_terminalPointX->blockSignals(true); m_terminalPointY->blockSignals(true); m_terminalPointX->setValue(PEUtils::convertUnits(p.x())); m_terminalPointY->setValue(PEUtils::convertUnits(p.y())); m_terminalPointX->blockSignals(false); m_terminalPointY->blockSignals(false); } void PEToolView::setTerminalPointLimits(QSizeF sz) { m_terminalPointX->setRange(0, sz.width()); m_terminalPointY->setRange(0, sz.height()); } void PEToolView::buttonChangeTerminalPoint() { QString how = sender()->property("how").toString(); emit terminalPointChanged(how); } void PEToolView::terminalPointEntry() { if (sender() == m_terminalPointX) { emit terminalPointChanged("x", PEUtils::unconvertUnits(m_terminalPointX->value())); } else if (sender() == m_terminalPointY) { emit terminalPointChanged("y", PEUtils::unconvertUnits(m_terminalPointY->value())); } } void PEToolView::getSpinAmountSlot(double & d) { emit getSpinAmount(d); } void PEToolView::removeConnector() { QTreeWidgetItem * item = m_connectorListWidget->currentItem(); if (item == NULL) return; int index = item->data(0, Qt::UserRole).toInt(); QDomElement element = m_connectorList->at(index); emit removedConnector(element); } void PEToolView::setChildrenVisible(bool vis) { foreach (QWidget * widget, findChildren()) { widget->setVisible(vis); } } void PEToolView::pickModeChangedSlot() { emit pickModeChanged(true); } void PEToolView::hideConnectorListStuff() { m_connectorListWidget->setHeaderHidden(true); QTreeWidgetItem * current = m_connectorListWidget->currentItem(); for (int i = 0; i < m_connectorListWidget->topLevelItemCount(); i++) { QTreeWidgetItem * item = m_connectorListWidget->topLevelItem(i); QWidget * widget = m_connectorListWidget->itemWidget(item, 1); if (qobject_cast(widget)) { if (item == current) ; // button is already there else { // remove the button and add the label m_connectorListWidget->removeItemWidget(item, 1); QLabel * label = new QLabel(); //label->setPixmap(*NoCheckImage); m_connectorListWidget->setItemWidget(item, 1, label); } } else { if (item != current) ; // label is already there else { m_assignButton = new QPushButton(tr("Select graphic")); m_assignButton->setMaximumWidth(150); connect(m_assignButton, SIGNAL(clicked()), this, SLOT(pickModeChangedSlot()), Qt::DirectConnection); m_assignButton->setToolTip(tr("Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it.")); m_connectorListWidget->setItemWidget(item, 1, m_assignButton); } } } } void PEToolView::setCurrentConnector(int ix) { m_connectorListWidget->setCurrentItem(m_connectorListWidget->topLevelItem(ix)); switchConnector(m_connectorListWidget->currentItem(), NULL); } fritzing-app-0.9.2b/src/partseditor/petoolview.h000066400000000000000000000070161250202676700220060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef PETOOLVIEW_H #define PETOOLVIEW_H #include #include #include #include #include #include #include #include #include #include #include #include "../viewlayer.h" class PEDoubleSpinBox : public QDoubleSpinBox { Q_OBJECT public: PEDoubleSpinBox(QWidget * parent = 0); void stepBy (int steps); signals: void getSpinAmount(double &); }; class PEToolView : public QFrame { Q_OBJECT public: PEToolView(QWidget * parent = NULL); ~PEToolView(); void initConnectors(QList * connectorList); int currentConnectorIndex(); void setCurrentConnector(const QDomElement &); void setCurrentConnector(int index); void setTerminalPointCoords(QPointF); void setTerminalPointLimits(QSizeF); void setChildrenVisible(bool vis); void enableConnectorChanges(bool enableTerminalPointDrag, bool enableTerminalPointControls, bool enableInfo, bool enableAssign); void showAssignedConnectors(const QDomDocument * svgDoc, ViewLayer::ViewID); signals: void switchedConnector(int); void removedConnector(const QDomElement &); void pickModeChanged(bool); void busModeChanged(bool); void terminalPointChanged(const QString & how); void terminalPointChanged(const QString & coord, double value); void getSpinAmount(double &); void connectorMetadataChanged(struct ConnectorMetadata *); protected slots: void switchConnector(QTreeWidgetItem * current, QTreeWidgetItem * previous); void pickModeChangedSlot(); void busModeChangedSlot(bool); void descriptionEntry(); void typeEntry(); void nameEntry(); void buttonChangeTerminalPoint(); void terminalPointEntry(); void getSpinAmountSlot(double &); void removeConnector(); protected: void changeConnector(); void hideConnectorListStuff(); protected: QPointer m_connectorListWidget; QList m_buttons; QPointer m_pegi; QList * m_connectorList; QPointer m_connectorInfoGroupBox; QPointer m_connectorInfoLayout; QPointer m_connectorInfoWidget; QPointer m_busModeBox; QPointer m_terminalPointX; QPointer m_terminalPointY; QPointer m_units; QPointer m_terminalPointGroupBox; QPointer m_terminalPointDragState; QPointer m_assignButton; }; #endif fritzing-app-0.9.2b/src/partseditor/peutils.cpp000066400000000000000000000202051250202676700216240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "peutils.h" #include "hashpopulatewidget.h" #include "../debugdialog.h" #include "../utils/graphicsutils.h" #include #include #include #include #include #include #include QString PEUtils::Units = "mm"; const int PEUtils::Spacing = 10; ///////////////////////////////////////////////////////// QString PEUtils::convertUnitsStr(double val) { return QString::number(PEUtils::convertUnits(val)); } double PEUtils::convertUnits(double val) { if (Units.compare("in") == 0) { return val / GraphicsUtils::SVGDPI; } else if (Units.compare("mm") == 0) { return val * 25.4 / GraphicsUtils::SVGDPI; } return val; } double PEUtils::unconvertUnits(double val) { if (Units.compare("in") == 0) { return val * GraphicsUtils::SVGDPI; } else if (Units.compare("mm") == 0) { return val * GraphicsUtils::SVGDPI / 25.4; } return val; } QWidget * PEUtils::makeConnectorForm(const QDomElement & connector, int index, QObject * slotHolder, bool alternating) { QFrame * frame = new QFrame(); if (alternating) { frame->setObjectName(index % 2 == 0 ? "NewPartsEditorConnector0Frame" : "NewPartsEditorConnector1Frame"); } else { frame->setObjectName("NewPartsEditorConnectorFrame"); } QVBoxLayout * mainLayout = new QVBoxLayout(); mainLayout->setMargin(0); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); QFrame * nameFrame = new QFrame(); QHBoxLayout * nameLayout = new QHBoxLayout(); QLabel * justLabel = new QLabel(QObject::tr("Name:")); justLabel->setObjectName("NewPartsEditorLabel"); nameLayout->addWidget(justLabel); QLineEdit * nameEdit = new QLineEdit(); nameEdit->setText(connector.attribute("name")); QObject::connect(nameEdit, SIGNAL(editingFinished()), slotHolder, SLOT(nameEntry())); nameEdit->setObjectName("NewPartsEditorLineEdit"); nameEdit->setStatusTip(QObject::tr("Set the connectors's title")); nameEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); nameEdit->setProperty("index", index); nameEdit->setProperty("type", "name"); nameEdit->setProperty("id", connector.attribute("id")); nameLayout->addWidget(nameEdit); nameLayout->addSpacing(Spacing); HashRemoveButton * hashRemoveButton = new HashRemoveButton(NULL, NULL, NULL); hashRemoveButton->setProperty("index", index); QObject::connect(hashRemoveButton, SIGNAL(clicked(HashRemoveButton *)), slotHolder, SLOT(removeConnector())); nameLayout->addWidget(hashRemoveButton); nameFrame->setLayout(nameLayout); mainLayout->addWidget(nameFrame); QFrame * descriptionFrame = new QFrame(); QHBoxLayout * descriptionLayout = new QHBoxLayout(); justLabel = new QLabel(QObject::tr("Description:")); justLabel->setObjectName("NewPartsEditorLabel"); descriptionLayout->addWidget(justLabel); QLineEdit * descriptionEdit = new QLineEdit(); QDomElement description = connector.firstChildElement("description"); descriptionEdit->setText(description.text()); QObject::connect(descriptionEdit, SIGNAL(editingFinished()), slotHolder, SLOT(descriptionEntry())); descriptionEdit->setObjectName("NewPartsEditorLineEdit"); descriptionEdit->setStatusTip(QObject::tr("Set the connectors's description")); descriptionEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); descriptionEdit->setProperty("index", index); descriptionEdit->setProperty("type", "description"); descriptionLayout->addWidget(descriptionEdit); descriptionFrame->setLayout(descriptionLayout); mainLayout->addWidget(descriptionFrame); QFrame * idFrame = new QFrame(); QHBoxLayout * idLayout = new QHBoxLayout(); justLabel = new QLabel(QObject::tr("id:")); justLabel->setObjectName("NewPartsEditorLabel"); idLayout->addWidget(justLabel); justLabel = new QLabel(connector.attribute("id")); justLabel->setObjectName("NewPartsEditorLabel"); idLayout->addWidget(justLabel); idLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); Connector::ConnectorType ctype = Connector::connectorTypeFromName(connector.attribute("type")); justLabel = new QLabel(QObject::tr("type:")); justLabel->setObjectName("NewPartsEditorLabel"); idLayout->addWidget(justLabel); QRadioButton * radioButton = new QRadioButton(MaleSymbolString); QObject::connect(radioButton, SIGNAL(clicked()), slotHolder, SLOT(typeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); if (ctype == Connector::Male) radioButton->setChecked(true); radioButton->setProperty("value", Connector::Male); radioButton->setProperty("index", index); radioButton->setProperty("type", "radio"); idLayout->addWidget(radioButton); radioButton = new QRadioButton(FemaleSymbolString); QObject::connect(radioButton, SIGNAL(clicked()), slotHolder, SLOT(typeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); if (ctype == Connector::Female) radioButton->setChecked(true); radioButton->setProperty("value", Connector::Female); radioButton->setProperty("index", index); radioButton->setProperty("type", "radio"); idLayout->addWidget(radioButton); radioButton = new QRadioButton(QObject::tr("Pad")); QObject::connect(radioButton, SIGNAL(clicked()), slotHolder, SLOT(typeEntry())); radioButton->setObjectName("NewPartsEditorRadio"); if (ctype == Connector::Pad) radioButton->setChecked(true); radioButton->setProperty("value", Connector::Pad); idLayout->addWidget(radioButton); radioButton->setProperty("index", index); radioButton->setProperty("type", "radio"); idLayout->addSpacing(Spacing); idFrame->setLayout(idLayout); mainLayout->addWidget(idFrame); frame->setLayout(mainLayout); return frame; } bool PEUtils::fillInMetadata(int senderIndex, QWidget * parent, ConnectorMetadata & cmd) { bool result = false; QList widgets = parent->findChildren(); foreach (QWidget * widget, widgets) { bool ok; int index = widget->property("index").toInt(&ok); if (!ok) continue; if (index != senderIndex) continue; QString type = widget->property("type").toString(); if (type == "name") { QLineEdit * lineEdit = qobject_cast(widget); if (lineEdit == NULL) continue; cmd.connectorName = lineEdit->text(); cmd.connectorID = widget->property("id").toString(); result = true; } else if (type == "radio") { QRadioButton * radioButton = qobject_cast(widget); if (radioButton == NULL) continue; if (!radioButton->isChecked()) continue; cmd.connectorType = (Connector::ConnectorType) radioButton->property("value").toInt(); } else if (type == "description") { QLineEdit * lineEdit = qobject_cast(widget); if (lineEdit == NULL) continue; cmd.connectorDescription = lineEdit->text(); } } return result; } fritzing-app-0.9.2b/src/partseditor/peutils.h000066400000000000000000000033641250202676700213000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PEUTILS_H #define PEUTILS_H #include "../connectors/connector.h" #include #include struct ConnectorMetadata { Connector::ConnectorType connectorType; QString connectorName; QString connectorDescription; QString connectorID; int index; }; class PEUtils { public: static QString convertUnitsStr(double val); static double convertUnits(double val); static double unconvertUnits(double val); static QWidget * makeConnectorForm(const QDomElement & connector, int index, QObject * slotHolder, bool alternating); static bool fillInMetadata(int senderIndex, QWidget * parentWidget, ConnectorMetadata & cmd); public: static QString Units; const static int Spacing; }; #endif fritzing-app-0.9.2b/src/processeventblocker.cpp000066400000000000000000000043531250202676700216670ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "processeventblocker.h" #include #include ProcessEventBlocker * ProcessEventBlocker::m_singleton = new ProcessEventBlocker(); ProcessEventBlocker::ProcessEventBlocker() { m_count = 0; } void ProcessEventBlocker::processEvents() { m_singleton->_processEvents(); } void ProcessEventBlocker::processEvents(int maxTime) { m_singleton->_processEvents(maxTime); } bool ProcessEventBlocker::isProcessing() { return m_singleton->_isProcessing(); } void ProcessEventBlocker::block() { return m_singleton->_inc(1); } void ProcessEventBlocker::unblock() { return m_singleton->_inc(-1); } void ProcessEventBlocker::_processEvents() { m_mutex.lock(); m_count++; m_mutex.unlock(); QApplication::processEvents(); m_mutex.lock(); m_count--; m_mutex.unlock(); } void ProcessEventBlocker::_processEvents(int maxTime) { m_mutex.lock(); m_count++; m_mutex.unlock(); QApplication::processEvents(QEventLoop::AllEvents, maxTime); m_mutex.lock(); m_count--; m_mutex.unlock(); } bool ProcessEventBlocker::_isProcessing() { m_mutex.lock(); bool result = m_count > 0; m_mutex.unlock(); return result; } void ProcessEventBlocker::_inc(int i) { m_mutex.lock(); m_count += i; m_mutex.unlock(); } fritzing-app-0.9.2b/src/processeventblocker.h000066400000000000000000000031061250202676700213270ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PROCESSEVENTBLOCKER_H_ #define PROCESSEVENTBLOCKER_H_ #include class ProcessEventBlocker { protected: ProcessEventBlocker(); ~ProcessEventBlocker(); bool _isProcessing(); void _processEvents(); void _processEvents(int maxTime); void _inc(int i); public: static void processEvents(); static void processEvents(int maxTime); static bool isProcessing(); static void block(); static void unblock(); protected: int m_count; QMutex m_mutex; protected: static ProcessEventBlocker * m_singleton; }; #endif /* PROCESSEVENTBLOCKER_H_ */ fritzing-app-0.9.2b/src/program/000077500000000000000000000000001250202676700165435ustar00rootroot00000000000000fritzing-app-0.9.2b/src/program/console.cpp000066400000000000000000000062141250202676700207140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "console.h" #include #include Console::Console(QWidget *parent) : QPlainTextEdit(parent) , localEchoEnabled(false) { document()->setMaximumBlockCount(1000); QFont font = document()->defaultFont(); font.setFamily("Droid Sans Mono"); document()->setDefaultFont(font); //setCenterOnScroll(true); } void Console::putData(const QByteArray &data) { insertPlainText(QString(data)); QScrollBar *bar = verticalScrollBar(); bar->setValue(bar->maximum()); } void Console::setLocalEchoEnabled(bool set) { localEchoEnabled = set; } void Console::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Backspace: case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: break; default: if (localEchoEnabled) QPlainTextEdit::keyPressEvent(e); emit getData(e->text().toLocal8Bit()); } } void Console::mousePressEvent(QMouseEvent *e) { Q_UNUSED(e) setFocus(); } void Console::mouseDoubleClickEvent(QMouseEvent *e) { Q_UNUSED(e) } void Console::contextMenuEvent(QContextMenuEvent *e) { Q_UNUSED(e) } fritzing-app-0.9.2b/src/program/console.h000066400000000000000000000050701250202676700203600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONSOLE_H #define CONSOLE_H #include class Console : public QPlainTextEdit { Q_OBJECT signals: void getData(const QByteArray &data); public: explicit Console(QWidget *parent = 0); void putData(const QByteArray &data); void setLocalEchoEnabled(bool set); protected: virtual void keyPressEvent(QKeyEvent *e); virtual void mousePressEvent(QMouseEvent *e); virtual void mouseDoubleClickEvent(QMouseEvent *e); virtual void contextMenuEvent(QContextMenuEvent *e); private: bool localEchoEnabled; }; #endif // CONSOLE_H fritzing-app-0.9.2b/src/program/consolesettings.cpp000066400000000000000000000204051250202676700224730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consolesettings.h" #include "ui_consolesettings.h" #include #include #include QT_USE_NAMESPACE ConsoleSettings::ConsoleSettings(QWidget *parent) : QDialog(parent), ui(new Ui::ConsoleSettings) { ui->setupUi(this); intValidator = new QIntValidator(0, 4000000, this); ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert); connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(apply())); connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)), this, SLOT(showPortInfo(int))); connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)), this, SLOT(checkCustomBaudRatePolicy(int))); fillPortsParameters(); fillPortsInfo(); updateSettings(); } ConsoleSettings::~ConsoleSettings() { delete ui; } ConsoleSettings::Settings ConsoleSettings::settings() const { return currentSettings; } void ConsoleSettings::showPortInfo(int idx) { if (idx != -1) { QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList(); ui->descriptionLabel->setText(tr("Description: %1").arg(list.at(1))); ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.at(2))); ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.at(3))); ui->locationLabel->setText(tr("Location: %1").arg(list.at(4))); ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.at(5))); ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.at(6))); } } void ConsoleSettings::apply() { updateSettings(); hide(); } void ConsoleSettings::checkCustomBaudRatePolicy(int idx) { bool isCustomBaudRate = !ui->baudRateBox->itemData(idx).isValid(); ui->baudRateBox->setEditable(isCustomBaudRate); if (isCustomBaudRate) { ui->baudRateBox->clearEditText(); QLineEdit *edit = ui->baudRateBox->lineEdit(); edit->setValidator(intValidator); } } void ConsoleSettings::fillPortsParameters() { ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600); ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200); ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400); ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200); ui->baudRateBox->addItem(QStringLiteral("Custom")); ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5); ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6); ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7); ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8); ui->dataBitsBox->setCurrentIndex(3); ui->parityBox->addItem(QStringLiteral("None"), QSerialPort::NoParity); ui->parityBox->addItem(QStringLiteral("Even"), QSerialPort::EvenParity); ui->parityBox->addItem(QStringLiteral("Odd"), QSerialPort::OddParity); ui->parityBox->addItem(QStringLiteral("Mark"), QSerialPort::MarkParity); ui->parityBox->addItem(QStringLiteral("Space"), QSerialPort::SpaceParity); ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop); #ifdef Q_OS_WIN ui->stopBitsBox->addItem(QStringLiteral("1.5"), QSerialPort::OneAndHalfStop); #endif ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop); ui->flowControlBox->addItem(QStringLiteral("None"), QSerialPort::NoFlowControl); ui->flowControlBox->addItem(QStringLiteral("RTS/CTS"), QSerialPort::HardwareControl); ui->flowControlBox->addItem(QStringLiteral("XON/XOFF"), QSerialPort::SoftwareControl); } void ConsoleSettings::fillPortsInfo() { ui->serialPortInfoListBox->clear(); static const QString blankString = QObject::tr("N/A"); QString description; QString manufacturer; QString serialNumber; foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { QStringList list; description = info.description(); manufacturer = info.manufacturer(); //serialNumber = info.serialNumber(); list << info.portName() << (!description.isEmpty() ? description : blankString) << (!manufacturer.isEmpty() ? manufacturer : blankString) << (!serialNumber.isEmpty() ? serialNumber : blankString) << info.systemLocation() << (info.vendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : blankString) << (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : blankString); ui->serialPortInfoListBox->addItem(list.first(), list); } } void ConsoleSettings::selectPortName(const QString portName) { if (portName.isEmpty()) return; int ix = ui->serialPortInfoListBox->findText(portName); if (ix >= 0) { currentSettings.name = portName; ui->serialPortInfoListBox->setCurrentIndex(ix); } } void ConsoleSettings::updateSettings() { currentSettings.name = ui->serialPortInfoListBox->currentText(); if (ui->baudRateBox->currentIndex() == 4) { currentSettings.baudRate = ui->baudRateBox->currentText().toInt(); } else { currentSettings.baudRate = static_cast( ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt()); } currentSettings.stringBaudRate = QString::number(currentSettings.baudRate); currentSettings.dataBits = static_cast( ui->dataBitsBox->itemData(ui->dataBitsBox->currentIndex()).toInt()); currentSettings.stringDataBits = ui->dataBitsBox->currentText(); currentSettings.parity = static_cast( ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt()); currentSettings.stringParity = ui->parityBox->currentText(); currentSettings.stopBits = static_cast( ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt()); currentSettings.stringStopBits = ui->stopBitsBox->currentText(); currentSettings.flowControl = static_cast( ui->flowControlBox->itemData(ui->flowControlBox->currentIndex()).toInt()); currentSettings.stringFlowControl = ui->flowControlBox->currentText(); currentSettings.localEchoEnabled = ui->localEchoCheckBox->isChecked(); } fritzing-app-0.9.2b/src/program/consolesettings.h000066400000000000000000000062561250202676700221500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONSOLESETTINGS_H #define CONSOLESETTINGS_H #include #include QT_USE_NAMESPACE QT_BEGIN_NAMESPACE namespace Ui { class ConsoleSettings; } class QIntValidator; QT_END_NAMESPACE class ConsoleSettings : public QDialog { Q_OBJECT public: struct Settings { QString name; qint32 baudRate; QString stringBaudRate; QSerialPort::DataBits dataBits; QString stringDataBits; QSerialPort::Parity parity; QString stringParity; QSerialPort::StopBits stopBits; QString stringStopBits; QSerialPort::FlowControl flowControl; QString stringFlowControl; bool localEchoEnabled; }; explicit ConsoleSettings(QWidget *parent = 0); ~ConsoleSettings(); Settings settings() const; void selectPortName(const QString portName); private slots: void showPortInfo(int idx); void apply(); void checkCustomBaudRatePolicy(int idx); private: void fillPortsParameters(); void fillPortsInfo(); void updateSettings(); private: Ui::ConsoleSettings *ui; Settings currentSettings; QIntValidator *intValidator; }; #endif // CONSOLESETTINGS_H fritzing-app-0.9.2b/src/program/consolesettings.ui000066400000000000000000000116311250202676700223270ustar00rootroot00000000000000 ConsoleSettings 0 0 400 336 Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Qt::Horizontal 96 20 Apply Additional options Local echo true fritzing-app-0.9.2b/src/program/consolewindow.cpp000066400000000000000000000164421250202676700221500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consolewindow.h" #include "ui_consolewindow.h" #include "console.h" #include "consolesettings.h" #include #include #include #include ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::ConsoleWindow) { QFile styleSheet(":/resources/styles/programwindow.qss"); this->setObjectName("consoleWindow"); if (!styleSheet.open(QIODevice::ReadOnly)) { qWarning("Unable to open :/resources/styles/programwindow.qss"); } else { QString ss = styleSheet.readAll(); #ifdef Q_OS_MAC int paneLoc = 4; int tabBarLoc = 0; #else int paneLoc = -1; int tabBarLoc = 5; #endif ss = ss.arg(paneLoc).arg(tabBarLoc); this->setStyleSheet(ss); } ui->setupUi(this); console = new Console; console->setEnabled(false); setCentralWidget(console); serial = new QSerialPort(this); settings = new ConsoleSettings; QSettings settings; if (!settings.value("consolewindow/state").isNull()) { restoreState(settings.value("consolewindow/state").toByteArray()); } if (!settings.value("consolewindow/geometry").isNull()) { restoreGeometry(settings.value("consolewindow/geometry").toByteArray()); } ui->actionConnect->setEnabled(true); ui->actionDisconnect->setEnabled(false); ui->actionQuit->setEnabled(true); ui->actionConfigure->setEnabled(true); initActionsConnections(); connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError))); connect(serial, SIGNAL(readyRead()), this, SLOT(readData())); connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray))); } ConsoleWindow::~ConsoleWindow() { delete settings; delete ui; } void ConsoleWindow::closeEvent(QCloseEvent *event) { closeSerialPort(); QSettings settings; settings.setValue("consolewindow/geometry", saveGeometry()); settings.setValue("consolewindow/tate", saveState()); QMainWindow::closeEvent(event); } void ConsoleWindow::openSerialPort(const QString portName) { if (portName.isEmpty()) return; settings->selectPortName(portName); if (serial->isOpen()) { if (serial->portName().compare(portName) != 0) { closeSerialPort(); openSerialPort(); } } else { openSerialPort(); } } void ConsoleWindow::openSerialPort() { ConsoleSettings::Settings p = settings->settings(); serial->setPortName(p.name); if (serial->open(QIODevice::ReadWrite)) { serial->setBaudRate(p.baudRate); serial->setDataBits(p.dataBits); serial->setParity(p.parity); serial->setStopBits(p.stopBits); serial->setFlowControl(p.flowControl); console->setEnabled(true); console->setLocalEchoEnabled(p.localEchoEnabled); ui->actionConnect->setEnabled(false); ui->actionDisconnect->setEnabled(true); ui->actionConfigure->setEnabled(false); ui->statusBar->showMessage(tr("Connected to %1 : %2, %3, %4, %5, %6") .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits) .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl)); } else { QMessageBox::critical(this, tr("Error"), serial->errorString()); ui->statusBar->showMessage(tr("Serial port open error")); } } void ConsoleWindow::closeSerialPort(const QString portName) { if (portName.isEmpty()) return; if (portName.compare(serial->portName()) == 0) { closeSerialPort(); } } void ConsoleWindow::closeSerialPort() { if (serial->isOpen()) { serial->close(); console->setEnabled(false); ui->actionConnect->setEnabled(true); ui->actionDisconnect->setEnabled(false); ui->actionConfigure->setEnabled(true); ui->statusBar->showMessage(tr("Disconnected")); } } void ConsoleWindow::about() { QMessageBox::about(this, tr("About Serial Monitor"), tr("This terminal displays the serial communication on the " "selected port, usually between your computer and the " "connected microcontroller.")); } void ConsoleWindow::writeData(const QByteArray &data) { serial->write(data); } void ConsoleWindow::readData() { QByteArray data = serial->readAll(); console->putData(data); } void ConsoleWindow::handleError(QSerialPort::SerialPortError error) { if (error == QSerialPort::ResourceError) { QMessageBox::critical(this, tr("Critical Error"), serial->errorString()); closeSerialPort(); } } void ConsoleWindow::initActionsConnections() { connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(openSerialPort())); connect(ui->actionDisconnect, SIGNAL(triggered()), this, SLOT(closeSerialPort())); connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(close())); connect(ui->actionConfigure, SIGNAL(triggered()), settings, SLOT(show())); connect(ui->actionClear, SIGNAL(triggered()), console, SLOT(clear())); connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); connect(ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); } fritzing-app-0.9.2b/src/program/consolewindow.h000066400000000000000000000056341250202676700216160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2012 Denis Shienkov ** Copyright (C) 2012 Laszlo Papp ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSerialPort module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONSOLEWINDOW_H #define CONSOLEWINDOW_H #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class ConsoleWindow; } QT_END_NAMESPACE class Console; class ConsoleSettings; class ConsoleWindow : public QMainWindow { Q_OBJECT public: explicit ConsoleWindow(QWidget *parent = 0); ~ConsoleWindow(); void openSerialPort(const QString portName); void closeSerialPort(const QString portName); protected: void closeEvent(QCloseEvent *event); private slots: void openSerialPort(); void closeSerialPort(); void about(); void writeData(const QByteArray &data); void readData(); void handleError(QSerialPort::SerialPortError error); private: void initActionsConnections(); private: Ui::ConsoleWindow *ui; Console *console; ConsoleSettings *settings; QSerialPort *serial; }; #endif // CONSOLEWINDOW_H fritzing-app-0.9.2b/src/program/consolewindow.ui000066400000000000000000000067471250202676700220120ustar00rootroot00000000000000 ConsoleWindow 0 0 400 300 Serial Monitor 0 0 400 22 Monitor Tools TopToolBarArea false &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L :/images/application-exit.png:/images/application-exit.png &Quit Ctrl+Q fritzing-app-0.9.2b/src/program/highlighter.cpp000066400000000000000000000143601250202676700215510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "highlighter.h" #include "syntaxer.h" #include "../debugdialog.h" #include #include #define STRINGOFFSET 10 #define COMMENTOFFSET 100 static const QChar CEscapeChar('\\'); QHash Highlighter::m_styleFormats; Highlighter::Highlighter(QTextEdit * textEdit) : QSyntaxHighlighter(textEdit) { m_syntaxer = NULL; } Highlighter::~Highlighter() { } void Highlighter::loadStyles(const QString & filename) { QFile file(filename); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) return; if (root.tagName() != "styles") return; QDomElement style = root.firstChildElement("style"); while (!style.isNull()) { QTextCharFormat * tcf = new QTextCharFormat(); QColor color(Qt::black); QString colorString = style.attribute("color"); if (!colorString.isEmpty()) { color.setNamedColor(colorString); tcf->setForeground(QBrush(color)); } QString italicString = style.attribute("italic"); if (italicString.compare("1") == 0) { tcf->setFontItalic(true); } QString boldString = style.attribute("bold"); if (boldString.compare("1") == 0) { tcf->setFontWeight(QFont::Bold); } QString underlineString = style.attribute("underline"); if (underlineString.compare("1") == 0) { tcf->setFontUnderline(true); } m_styleFormats.insert(style.attribute("name"), tcf); style = style.nextSiblingElement("style"); } } void Highlighter::setSyntaxer(Syntaxer * syntaxer) { m_syntaxer = syntaxer; } Syntaxer * Highlighter::syntaxer() { return m_syntaxer; } void Highlighter::highlightBlock(const QString &text) { if (!m_syntaxer) return; if (text.isEmpty()) { setCurrentBlockState(previousBlockState()); return; } setCurrentBlockState(0); int startCommentIndex = -1; int startStringIndex = -1; const CommentInfo * currentCommentInfo = NULL; int pbs = previousBlockState(); if (pbs <= 0) { m_syntaxer->matchCommentStart(text, 0, startCommentIndex, currentCommentInfo); } else if (pbs >= COMMENTOFFSET) { currentCommentInfo = m_syntaxer->getCommentInfo(previousBlockState() - COMMENTOFFSET); startCommentIndex = 0; } else if (pbs == STRINGOFFSET) { startStringIndex = 0; } QString noComment = text; while (startCommentIndex >= 0) { int endIndex = currentCommentInfo->m_multiLine ? text.indexOf(currentCommentInfo->m_end, startCommentIndex, currentCommentInfo->m_caseSensitive) : text.length(); int commentLength; if (endIndex == -1) { setCurrentBlockState(currentCommentInfo->m_index + COMMENTOFFSET); commentLength = text.length() - startCommentIndex; } else { commentLength = endIndex - startCommentIndex + currentCommentInfo->m_end.length(); } noComment.replace(startCommentIndex, commentLength, QString(commentLength, ' ')); QTextCharFormat * cf = m_styleFormats.value("Comment", NULL); if (cf != NULL) { setFormat(startCommentIndex, commentLength, *cf); } m_syntaxer->matchCommentStart(text, startCommentIndex + commentLength, startCommentIndex, currentCommentInfo); } highlightStrings(startStringIndex, noComment); highlightTerms(noComment); } void Highlighter::highlightStrings(int startStringIndex, QString & text) { if (startStringIndex < 0) { startStringIndex = m_syntaxer->matchStringStart(text, 0); } // TODO: not handling "" as a way to escape-quote while (startStringIndex >= 0) { int endIndex = -1; int ssi = startStringIndex; while (true) { endIndex = m_syntaxer->matchStringEnd(text, ssi + 1); if (!m_syntaxer->hlCStringChar()) { // only some languages use \ to escape break; } if (endIndex == -1) { break; } // TODO: escape char is backslash only; are there others in other compilers? if (text.at(endIndex - 1) != CEscapeChar) { break; } ssi = endIndex; } int stringLength; if (endIndex == -1) { setCurrentBlockState(STRINGOFFSET); stringLength = text.length() - startStringIndex; } else { stringLength = endIndex - startStringIndex + 1; } text.replace(startStringIndex, stringLength, QString(stringLength, ' ')); QTextCharFormat * sf = m_styleFormats.value("String", NULL); if (sf != NULL) { setFormat(startStringIndex, stringLength, *sf); } startStringIndex = m_syntaxer->matchStringStart(text, startStringIndex + stringLength); } } void Highlighter::highlightTerms(const QString & text) { int lastWordBreak = 0; int textLength = text.length(); int b; while (lastWordBreak < textLength) { for (b = lastWordBreak; b < textLength; b++) { if (!isWordChar(text.at(b))) break; } if (b > lastWordBreak) { TrieLeaf * leaf = NULL; if (m_syntaxer->matches(text.mid(lastWordBreak, b - lastWordBreak), leaf)) { SyntaxerTrieLeaf * stl = dynamic_cast(leaf); if (stl != NULL) { QString format = Syntaxer::formatFromList(stl->name()); QTextCharFormat * tcf = m_styleFormats.value(format, NULL); if (tcf != NULL) { setFormat(lastWordBreak, b - lastWordBreak, *tcf); } } } } lastWordBreak = b + 1; } } bool Highlighter::isWordChar(QChar c) { return c.isLetterOrNumber() || c == '#' || c == '_'; } fritzing-app-0.9.2b/src/program/highlighter.h000066400000000000000000000033521250202676700212150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef HIGHLIGHTER_H_ #define HIGHLIGHTER_H_ #include #include #include #include #include class Highlighter : public QSyntaxHighlighter { Q_OBJECT public: Highlighter(QTextEdit * parent); ~Highlighter(); void setSyntaxer(class Syntaxer *); class Syntaxer * syntaxer(); public: static void loadStyles(const QString & filename); protected: void highlightBlock(const QString & text); bool isWordChar(QChar c); void highlightTerms(const QString & text); void highlightStrings(int startStringIndex, QString & text); protected: QPointer m_syntaxer; static QHash m_styleFormats; }; #endif /* HIGHLIGHTER_H_ */ fritzing-app-0.9.2b/src/program/platform.cpp000066400000000000000000000073371250202676700211050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ********************************************************************/ #include "platform.h" #include "syntaxer.h" #include "../utils/folderutils.h" #include #include Platform::Platform(const QString &name) : QObject() { m_name = name; initSyntaxer(); initCommandLocation(); } Platform::~Platform() { // nothing to do } QString Platform::getName() const { return m_name; } void Platform::upload(QWidget * source, const QString &port, const QString &board, const QString &fileLocation) { // stub } Syntaxer * Platform::getSyntaxer() { return m_syntaxer; } void Platform::initSyntaxer() { Syntaxer * syntaxer = new Syntaxer(); QDir dir(FolderUtils::getApplicationSubFolderPath("translations")); dir.cd("syntax"); QStringList nameFilters; nameFilters << "*.xml"; QFileInfoList list = dir.entryInfoList(nameFilters, QDir::Files | QDir::NoSymLinks); foreach (QFileInfo fileInfo, list) { if (fileInfo.completeBaseName().compare(getName(), Qt::CaseInsensitive) == 0) { syntaxer->loadSyntax(fileInfo.absoluteFilePath()); break; } } m_syntaxer = syntaxer; } void Platform::initCommandLocation() { QSettings settings; m_commandLocation = settings.value(QString("programwindow/programmer.%1").arg(getName())).toString(); } QString Platform::getCommandLocation() const { return m_commandLocation; } void Platform::setCommandLocation(const QString &commandLocation) { m_commandLocation = commandLocation; QSettings settings; settings.setValue(QString("programwindow/programmer.%1").arg(getName()), commandLocation); emit commandLocationChanged(); } QStringList Platform::getExtensions() const { return m_extensions; } void Platform::setExtensions(const QStringList &suffixes) { m_extensions = suffixes; } QMap Platform::getBoards() const { return m_boards; } void Platform::setBoards(const QMap &boards) { m_boards = boards; } QUrl Platform::getReferenceUrl() const { return m_referenceUrl; } void Platform::setReferenceUrl(const QUrl &referenceUrl) { m_referenceUrl = referenceUrl; } bool Platform::canProgram() const { return m_canProgram; } void Platform::setCanProgram(bool canProgram) { m_canProgram = canProgram; } QUrl Platform::getDownloadUrl() const { return m_downloadUrl; } void Platform::setDownloadUrl(const QUrl &downloadUrl) { m_downloadUrl = downloadUrl; } QString Platform::getMinVersion() const { return m_minVersion; } void Platform::setMinVersion(const QString &minVersion) { m_minVersion = minVersion; } QString Platform::getDefaultBoardName() const { return m_defaultBoardName; } void Platform::setDefaultBoardName(const QString &defaultBoardName) { m_defaultBoardName = defaultBoardName; } QString Platform::getIdeName() const { return m_ideName; } void Platform::setIdeName(const QString &ideName) { m_ideName = ideName; } fritzing-app-0.9.2b/src/program/platform.h000066400000000000000000000051021250202676700205360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ********************************************************************/ #include "syntaxer.h" #include #include #include #include #include #include #include #include #ifndef PLATFORM_H #define PLATFORM_H class Platform : public QObject { Q_OBJECT public: Platform(const QString &name); ~Platform(); virtual void upload(QWidget *source, const QString &port, const QString &board, const QString &fileLocation); Syntaxer *getSyntaxer(); QString getName() const; QString getCommandLocation() const; void setCommandLocation(const QString &commandLocation); QStringList getExtensions() const; void setExtensions(const QStringList &suffixes); QMap getBoards() const; void setBoards(const QMap &boards); QUrl getReferenceUrl() const; void setReferenceUrl(const QUrl &referenceUrl); bool canProgram() const; void setCanProgram(bool canProgram); QUrl getDownloadUrl() const; void setDownloadUrl(const QUrl &downloadUrl); QString getMinVersion() const; void setMinVersion(const QString &minVersion); QString getDefaultBoardName() const; void setDefaultBoardName(const QString &defaultBoardName); QString getIdeName() const; void setIdeName(const QString &ideName); signals: void commandLocationChanged(); protected: QString m_name; QString m_commandLocation; bool m_canProgram; QStringList m_extensions; QMap m_boards; QString m_defaultBoardName; QUrl m_referenceUrl; QString m_ideName; QUrl m_downloadUrl; QString m_minVersion; private: void initSyntaxer(); void initCommandLocation(); private: QPointer m_syntaxer; }; #endif // PLATFORM_H fritzing-app-0.9.2b/src/program/platformarduino.cpp000066400000000000000000000076451250202676700224710ustar00rootroot00000000000000#include "platformarduino.h" #include "programtab.h" #include #include #include PlatformArduino::PlatformArduino() : Platform(QString("Arduino")) { setReferenceUrl(QUrl(QString("http://arduino.cc/en/Reference/"))); setIdeName("Arduino IDE"); setDownloadUrl(QUrl("http://arduino.cc/en/Main/Software")); setMinVersion("1.5.2"); setCanProgram(true); setExtensions(QStringList() << ".ino" << ".pde"); QMap boards; // https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/avr/boards.txt boards.insert("Arduino UNO", "arduino:avr:uno"); boards.insert("Arduino Yún", "arduino:avr:yun"); boards.insert("Arduino Mega/2560", "arduino:avr:mega"); boards.insert("Arduino Duemilanove/Diecemila", "arduino:avr:diecimila"); boards.insert("Arduino Nano", "arduino:avr:nano"); boards.insert("Arduino Mega ADK", "arduino:avr:megaADK"); boards.insert("Arduino Leonardo", "arduino:avr:leonardo"); boards.insert("Arduino Micro", "arduino:avr:micro"); boards.insert("Arduino Esplora", "arduino:avr:Esplora"); boards.insert("Arduino Mini", "arduino:avr:mini"); boards.insert("Arduino Ethernet", "arduino:avr:ethernet"); boards.insert("Arduino Fio", "arduino:avr:fio"); boards.insert("Arduino BT", "arduino:avr:bt"); boards.insert("Lilypad Arduino USB", "arduino:avr:LilyPadUSB"); boards.insert("LilyPad Arduino ", "arduino:avr:lilypad"); boards.insert("Arduino Pro/Pro Mini", "arduino:avr:pro"); boards.insert("Arduino NG or older", "arduino:avr:atmegang"); boards.insert("Arduino Robot Control", "arduino:avr:robotControl"); boards.insert("Arduino Robot Motor", "arduino:avr:robotMotor"); // https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/boards.txt boards.insert("Arduino Due (Programming Port)", "arduino:sam:arduino_due_x_dbg"); boards.insert("Arduino Due (Native USB Port)", "arduino:sam:arduino_due_x"); setBoards(boards); setDefaultBoardName("Arduino UNO"); } void PlatformArduino::upload(QWidget *source, const QString &port, const QString &board, const QString &fileLocation) { QProcess * process = new QProcess(this); process->setProcessChannelMode(QProcess::MergedChannels); process->setReadChannel(QProcess::StandardOutput); connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), source, SLOT(programProcessFinished(int, QProcess::ExitStatus))); connect(process, SIGNAL(readyReadStandardOutput()), source, SLOT(programProcessReadyRead())); // Make sure .ino is in its own folder with same name (as required by Arduino compiler), // otherwise create a subfolder and copy the file there. QFileInfo fileInfo(fileLocation); QString tmpFilePath = fileInfo.absoluteFilePath(); QString dirName = fileInfo.dir().dirName(); QString sketchName = fileInfo.baseName(); if (dirName.compare(sketchName, Qt::CaseInsensitive) != 0) { QString tmpSketchName(sketchName.append("_TMP")); fileInfo.dir().mkdir(tmpSketchName); tmpFilePath = fileInfo.absolutePath().append("/").append(tmpSketchName).append("/") .append(fileInfo.baseName().append("_TMP.").append(fileInfo.suffix())); if (QFile::exists(tmpFilePath)) QFile::remove(tmpFilePath); QFile::copy(fileInfo.absoluteFilePath(), tmpFilePath); } QStringList args; // see https://github.com/arduino/Arduino/blob/ide-1.5.x/build/shared/manpage.adoc //args.append(QString("--verbose")); args.append(QString("--board")); args.append(getBoards().value(board)); args.append(QString("--port")); args.append(port); args.append(QString("--upload")); args.append(QDir::toNativeSeparators(tmpFilePath)); ProgramTab *tab = qobject_cast(source); if (tab) tab->appendToConsole(tr("Running %1 %2").arg(getCommandLocation()).arg(args.join(" "))); process->start(getCommandLocation(), args); } fritzing-app-0.9.2b/src/program/platformarduino.h000066400000000000000000000004641250202676700221260ustar00rootroot00000000000000#include "platform.h" #include #ifndef PLATFORMARDUINO_H #define PLATFORMARDUINO_H class PlatformArduino : public Platform { public: PlatformArduino(); void upload(QWidget *source, const QString &port, const QString &board, const QString &fileLocation); }; #endif // PLATFORMARDUINO_H fritzing-app-0.9.2b/src/program/platformlaunchpad.cpp000066400000000000000000000012371250202676700227560ustar00rootroot00000000000000#include "platformlaunchpad.h" PlatformLaunchpad::PlatformLaunchpad() : Platform(QString("Launchpad")) { setReferenceUrl(QUrl("http://energia.nu/reference/")); setDownloadUrl(QUrl("http://www.ti.com/tool/msp430-flasher")); // http://energia.nu/download/ doesn't seem to have command line support setMinVersion("1.0"); setCanProgram(true); setExtensions(QStringList() << ".txt"); } void PlatformLaunchpad::upload(const QString &port, const QString &board, const QString &fileLocation, QTextEdit *console) { // see http://www.ti.com/tool/msp430-flasher // http://processors.wiki.ti.com/index.php/MSP430_Flasher_-_Command_Line_Programmer } fritzing-app-0.9.2b/src/program/platformlaunchpad.h000066400000000000000000000004551250202676700224240ustar00rootroot00000000000000#include "platform.h" #ifndef PLATFORMLAUNCHPAD_H #define PLATFORMLAUNCHPAD_H class PlatformLaunchpad : public Platform { public: PlatformLaunchpad(); void upload(const QString &port, const QString &board, const QString &fileLocation, QTextEdit *console); }; #endif // PLATFORMLAUNCHPAD_H fritzing-app-0.9.2b/src/program/platformpicaxe.cpp000066400000000000000000000050631250202676700222710ustar00rootroot00000000000000#include "platformpicaxe.h" #include #include #include #include "programtab.h" PlatformPicaxe::PlatformPicaxe() : Platform(QString("PICAXE")) { setReferenceUrl(QUrl("http://www.picaxe.com/BASIC-Commands")); setCanProgram(true); setIdeName("PICAXE Compilers"); setDownloadUrl(QUrl("http://www.picaxe.com/Software/Drivers/PICAXE-Compilers/")); setMinVersion("2.0"); setExtensions(QStringList() << ".bas" << ".BAS"); QMap boards; boards.insert("PICAXE-08", "picaxe08"); boards.insert("PICAXE-08M", "picaxe08m"); boards.insert("PICAXE-08M2", "picaxe08m2"); boards.insert("PICAXE-08M2LE", "picaxe08m2le"); boards.insert("PICAXE-14M", "picaxe14m"); boards.insert("PICAXE-14M2", "picaxe14m2"); boards.insert("PICAXE-18", "picaxe18"); boards.insert("PICAXE-18A", "picaxe18a"); boards.insert("PICAXE-18M", "picaxe18m"); boards.insert("PICAXE-18M2", "picaxe18m2"); boards.insert("PICAXE-18X", "picaxe18x"); boards.insert("PICAXE-20", "picaxe20"); boards.insert("PICAXE-20M2", "picaxe20m2"); boards.insert("PICAXE-20X2", "picaxe20x2"); boards.insert("PICAXE-28", "picaxe28"); boards.insert("PICAXE-28A", "picaxe28a"); boards.insert("PICAXE-28X", "picaxe28x"); boards.insert("PICAXE-28X1", "picaxe28x1"); boards.insert("PICAXE-28X2", "picaxe28x2"); boards.insert("PICAXE-40X", "picaxe28x"); boards.insert("PICAXE-40X1", "picaxe28x1"); boards.insert("PICAXE-40X2", "picaxe28x2"); setBoards(boards); setDefaultBoardName("PICAXE-08M"); } void PlatformPicaxe::upload(QWidget *source, const QString &port, const QString &board, const QString &fileLocation) { // see http://www.picaxe.com/docs/beta_compiler.pdf QProcess * process = new QProcess(this); process->setProcessChannelMode(QProcess::MergedChannels); process->setReadChannel(QProcess::StandardOutput); connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), source, SLOT(programProcessFinished(int, QProcess::ExitStatus))); connect(process, SIGNAL(readyReadStandardOutput()), source, SLOT(programProcessReadyRead())); QFileInfo cmdFileInfo(getCommandLocation()); QString cmd(cmdFileInfo.absoluteDir().absolutePath().append("/").append(getBoards().value(board))); QStringList args; args.append(QString("-c%1").arg(port)); args.append(fileLocation); ProgramTab *tab = qobject_cast(source); if (tab) tab->appendToConsole(tr("Running %1 %2").arg(cmd).arg(args.join(" "))); process->start(cmd, args); } fritzing-app-0.9.2b/src/program/platformpicaxe.h000066400000000000000000000004571250202676700217400ustar00rootroot00000000000000#include "platform.h" #include #ifndef PLATFORMPICAXE_H #define PLATFORMPICAXE_H class PlatformPicaxe : public Platform { public: PlatformPicaxe(); void upload(QWidget *source, const QString &port, const QString &board, const QString &fileLocation); }; #endif // PLATFORMPICAXE_H fritzing-app-0.9.2b/src/program/programtab.cpp000066400000000000000000000676651250202676700214310ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "programtab.h" #include "highlighter.h" #include "syntaxer.h" #include "consolewindow.h" #include "../debugdialog.h" #include "../utils/folderutils.h" #include "../sketchtoolbutton.h" #include #include #include #include #include #include #include #include #include #include static const QChar Quote91Char(0x91); static QString UnableToProgramMessage; ///////////////////////////////////////// SerialPortComboBox::SerialPortComboBox() : QComboBox() { } void SerialPortComboBox::showPopup() { emit aboutToShow(); QComboBox::showPopup(); } ///////////////////////////////////////// DeleteDialog::DeleteDialog(const QString & title, const QString & text, bool deleteFileCheckBox, QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags) { // we use this dialog instead of the normal QMessageBox because it's currently hard if not impossible to add a checkbox to QMessageBox. // supposedly this will be fixed in a future release of Qt. this->setWindowTitle(title); this->setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); QVBoxLayout * vlayout = new QVBoxLayout(this); QFrame * frame = new QFrame(this); QHBoxLayout * hlayout = new QHBoxLayout(frame); QLabel * iconLabel = new QLabel; iconLabel->setPixmap(QMessageBox::standardIcon(QMessageBox::Warning)); iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QLabel * label = new QLabel; label->setWordWrap(true); label->setText(text); hlayout->addWidget(iconLabel); hlayout->addWidget(label); vlayout->addWidget(frame); m_checkBox = NULL; if (deleteFileCheckBox) { m_checkBox = new QCheckBox(tr("Also delete the file")); vlayout->addSpacing(7); vlayout->addWidget(m_checkBox); vlayout->addSpacing(15); } m_buttonBox = new QDialogButtonBox; m_buttonBox->addButton(QDialogButtonBox::Yes); m_buttonBox->addButton(QDialogButtonBox::No); m_buttonBox->button(QDialogButtonBox::Yes)->setText(tr("Remove")); m_buttonBox->button(QDialogButtonBox::No)->setText(tr("Don't remove")); QObject::connect(m_buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*))); vlayout->addWidget(m_buttonBox); this->setModal(true); } void DeleteDialog::buttonClicked(QAbstractButton * button) { this->done(m_buttonBox->standardButton(button)); } bool DeleteDialog::deleteFileChecked() { if (m_checkBox == NULL) return false; return m_checkBox->isChecked(); } ///////////////////////////////////////////// QIcon * AsteriskIcon = NULL; ProgramTab::ProgramTab(QString & filename, QWidget *parent) : QFrame(parent) { if (UnableToProgramMessage.isEmpty()) { UnableToProgramMessage = tr("While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller."); } m_tabWidget = NULL; while (parent != NULL) { QTabWidget * tabWidget = qobject_cast(parent); if (tabWidget) { m_tabWidget = tabWidget; break; } parent = parent->parentWidget(); } if (AsteriskIcon == NULL) { AsteriskIcon = new QIcon(":/resources/images/icons/asterisk.png"); } m_canCopy = false; m_canCut = false; m_canUndo = false; m_canRedo = false; m_canPaste = false; //m_platform = NULL; m_port = ""; m_board = ""; m_filename = filename; m_updateEnabled = false; QGridLayout *editLayout = new QGridLayout(this); editLayout->setMargin(0); editLayout->setSpacing(0); while (m_programWindow == NULL) { m_programWindow = qobject_cast(parent); parent = parent->parentWidget(); } // m_textEdit needs to be initialized before createFooter so // some signals get connected properly. m_textEdit = new QTextEdit; m_textEdit->setObjectName("code"); m_textEdit->setFontFamily("Droid Sans Mono"); m_textEdit->setLineWrapMode(QTextEdit::NoWrap); QFontMetrics fm(m_textEdit->currentFont()); m_textEdit->setTabStopWidth(fm.averageCharWidth() * 2); m_textEdit->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); m_textEdit->setUndoRedoEnabled(true); connect(m_textEdit, SIGNAL(textChanged()), this, SLOT(textChanged())); connect(m_textEdit, SIGNAL(undoAvailable(bool)), this, SLOT(enableUndo(bool))); connect(m_textEdit, SIGNAL(redoAvailable(bool)), this, SLOT(enableRedo(bool))); connect(m_textEdit, SIGNAL(copyAvailable(bool)), this, SLOT(enableCopy(bool))); connect(m_textEdit, SIGNAL(copyAvailable(bool)), this, SLOT(enableCut(bool))); // Reuse copy signal for cut m_highlighter = new Highlighter(m_textEdit); QSplitter * splitter = new QSplitter; splitter->setObjectName("splitter"); splitter->setOrientation(Qt::Vertical); editLayout->addWidget(splitter, 1, 0); splitter->addWidget(m_textEdit); m_console = new QPlainTextEdit(); m_console->setObjectName("console"); m_console->setReadOnly(true); QFont font = m_console->document()->defaultFont(); font.setFamily("Droid Sans Mono"); m_console->document()->setDefaultFont(font); splitter->addWidget(m_console); splitter->setStretchFactor(0, 8); splitter->setStretchFactor(1, 2); m_toolbar = new QFrame(this); m_toolbar->setObjectName("sketchAreaToolbar"); m_toolbar->setFixedHeight(66); QFrame *leftButtons = new QFrame(m_toolbar); m_leftButtonsContainer = new QHBoxLayout(leftButtons); m_leftButtonsContainer->setMargin(0); m_leftButtonsContainer->setSpacing(0); QFrame *middleButtons = new QFrame(m_toolbar); middleButtons->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::MinimumExpanding); m_middleButtonsContainer = new QHBoxLayout(middleButtons); m_middleButtonsContainer->setSpacing(0); m_middleButtonsContainer->setMargin(0); QFrame *rightButtons = new QFrame(m_toolbar); m_rightButtonsContainer = new QHBoxLayout(rightButtons); m_rightButtonsContainer->setMargin(0); m_rightButtonsContainer->setSpacing(0); QHBoxLayout *toolbarLayout = new QHBoxLayout(m_toolbar); toolbarLayout->setMargin(0); toolbarLayout->setSpacing(0); toolbarLayout->addWidget(leftButtons); toolbarLayout->addWidget(middleButtons); toolbarLayout->addWidget(rightButtons); editLayout->addWidget(m_toolbar,2,0); //createToolBarMenu(); } ProgramTab::~ProgramTab() { } /** * We override the showEvent for the tab to trigger a menu update */ void ProgramTab::showEvent(QShowEvent *event) { QFrame::showEvent(event); m_textEdit->setFocus(); updateMenu(); } void ProgramTab::initMenus() { m_newButton = new SketchToolButton("NewCode", this, m_programWindow->m_newAction); m_newButton->setText(tr("New")); m_newButton->setObjectName("newCodeButton"); m_newButton->setEnabledIcon(); // seems to need this to display button icon first time m_leftButtonsContainer->addWidget(m_newButton); m_openButton = new SketchToolButton("OpenCode", this, m_programWindow->m_openAction); m_openButton->setText(tr("Open")); m_openButton->setObjectName("openCodeButton"); m_openButton->setEnabledIcon(); // seems to need this to display button icon first time m_leftButtonsContainer->addWidget(m_openButton); m_saveButton = new SketchToolButton("SaveCode", this, m_programWindow->m_saveAction); m_saveButton->setText(tr("Save")); m_saveButton->setObjectName("saveCodeButton"); m_saveButton->setEnabledIcon(); // seems to need this to display button icon first time m_leftButtonsContainer->addWidget(m_saveButton); // Platform selection QFrame *platformSelector = new QFrame(m_middleButtonsContainer->parentWidget()); platformSelector->setObjectName("toolbarSelector"); QVBoxLayout *platformSelectionContainer = new QVBoxLayout(platformSelector); platformSelectionContainer->setSpacing(0); platformSelectionContainer->setMargin(0); QLabel * platformLabel = new QLabel(tr("Platform"), this); m_platformComboBox = new QComboBox(); m_platformComboBox->setObjectName("toolBarComboBox"); m_platformComboBox->setEditable(false); m_platformComboBox->setEnabled(true); foreach (Platform * platform, m_programWindow->getAvailablePlatforms()) { m_platformComboBox->addItem(platform->getName()); } QSettings settings; QString currentPlatform = settings.value("programwindow/platform", "").toString(); if (currentPlatform.isEmpty()) { currentPlatform = m_platformComboBox->currentText(); // TODO } platformSelectionContainer->addWidget(m_platformComboBox); platformSelectionContainer->addWidget(platformLabel); m_rightButtonsContainer->addWidget(platformSelector); connect(this, SIGNAL(platformChanged(Platform *)), m_programWindow, SLOT(updateBoards())); connect(this, SIGNAL(platformChanged(Platform *)), this, SLOT(updateBoards())); setPlatform(currentPlatform, false); // Board selection QFrame *boardSelector = new QFrame(m_middleButtonsContainer->parentWidget()); boardSelector->setObjectName("toolbarSelector"); QVBoxLayout *boardSelectionContainer = new QVBoxLayout(boardSelector); boardSelectionContainer->setSpacing(0); boardSelectionContainer->setMargin(0); QLabel * boardLabel = new QLabel(tr("Board"), this); m_boardComboBox = new QComboBox(); m_boardComboBox->setObjectName("toolBarComboBox"); m_boardComboBox->setEditable(false); m_boardComboBox->setEnabled(true); updateBoards(); QString currentBoard = settings.value("programwindow/board", "").toString(); if (currentBoard.isEmpty()) { currentBoard = m_boardComboBox->currentText(); } else if (!m_programWindow->getBoards().contains(currentBoard)) { currentBoard = m_boardComboBox->currentText(); } setBoard(currentBoard); boardSelectionContainer->addWidget(m_boardComboBox); boardSelectionContainer->addWidget(boardLabel); m_rightButtonsContainer->addWidget(boardSelector); // Port selection QFrame *portSelector = new QFrame(m_middleButtonsContainer->parentWidget()); portSelector->setObjectName("toolbarSelector"); QVBoxLayout *portSelectionContainer = new QVBoxLayout(portSelector); portSelectionContainer->setSpacing(0); portSelectionContainer->setMargin(0); QLabel * portLabel = new QLabel(tr("Port"), this); m_portComboBox = new SerialPortComboBox(); m_portComboBox->setObjectName("toolBarComboBox"); m_portComboBox->setEditable(false); m_portComboBox->setEnabled(true); QList ports = m_programWindow->getSerialPorts(); foreach (const QSerialPortInfo port, ports) m_portComboBox->addItem(port.portName(), port.systemLocation()); QString currentPort = settings.value("programwindow/port", "").toString(); if (currentPort.isEmpty()) { currentPort = m_portComboBox->currentText(); } else if (!m_programWindow->hasPort(currentPort)) { currentPort = m_portComboBox->currentText(); } setPort(currentPort); portSelectionContainer->addWidget(m_portComboBox); portSelectionContainer->addWidget(portLabel); m_rightButtonsContainer->addWidget(portSelector); // connect last so these signals aren't triggered during initialization connect(m_platformComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(setPlatform(const QString &))); connect(m_portComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(setPort(const QString &))); connect(m_portComboBox, SIGNAL(aboutToShow()), this, SLOT(updateSerialPorts()), Qt::DirectConnection); connect(m_boardComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(setBoard(const QString &))); m_monitorButton = new SketchToolButton("MonitorCode", this, m_programWindow->m_monitorAction); m_monitorButton->setText(tr("Serial Monitor")); m_monitorButton->setObjectName("monitorCodeButton"); m_monitorButton->setEnabledIcon(); // seems to need this to display button icon first time m_rightButtonsContainer->addWidget(m_monitorButton); m_programButton = new SketchToolButton("ProgramCode", this, m_programWindow->m_programAction); m_programButton->setText(tr("Upload")); m_programButton->setObjectName("programCodeButton"); m_programButton->setEnabledIcon(); // seems to need this to display button icon first time m_rightButtonsContainer->addWidget(m_programButton); // QFrame * superFrame = new QFrame(); // QVBoxLayout * superLayout = new QVBoxLayout(); // superLayout->setMargin(0); // superLayout->setSpacing(0); // m_unableToProgramLabel = new QLabel(UnableToProgramMessage.arg("")); // m_unableToProgramLabel->setObjectName("unableToProgramLabel"); // superLayout->addWidget(footerFrame); // superLayout->addWidget(m_unableToProgramLabel); // superFrame->setLayout(superLayout); setPlatform(currentPlatform, false); } void ProgramTab::setPlatform(const QString & newPlatformName) { setPlatform(m_programWindow->getPlatformByName(newPlatformName), true); } void ProgramTab::setPlatform(const QString & newPlatformName, bool updateLink) { setPlatform(m_programWindow->getPlatformByName(newPlatformName), updateLink); } void ProgramTab::setPlatform(Platform * newPlatform) { setPlatform(newPlatform, true); } void ProgramTab::setPlatform(Platform * newPlatform, bool updateLink) { DebugDialog::debug(QString("Setting platform to %1").arg(newPlatform->getName())); bool isPlatformChanged = newPlatform != m_platform; if (updateLink && isPlatformChanged) { m_programWindow->updateLink(m_filename, newPlatform, false, false); } if (m_platform != NULL) m_platform->disconnect(SIGNAL(commandLocationChanged())); connect(newPlatform, SIGNAL(commandLocationChanged()), this, SLOT(enableProgramButton())); m_platform = newPlatform; m_platformComboBox->setCurrentIndex(m_platformComboBox->findText(newPlatform->getName())); Syntaxer * syntaxer = m_platform->getSyntaxer(); m_highlighter->setSyntaxer(syntaxer); m_highlighter->rehighlight(); updateMenu(); QSettings settings; settings.setValue("programwindow/platform", newPlatform->getName()); //bool canProgram = (syntaxer != NULL && syntaxer->canProgram()); //m_unableToProgramLabel->setVisible(!canProgram); //m_unableToProgramLabel->setText(UnableToProgramMessage.arg(newPlatform.getName())); if (updateLink && isPlatformChanged) emit platformChanged(newPlatform); } void ProgramTab::setPort(const QString & newPort) { DebugDialog::debug(QString("Setting port to %1").arg(newPort)); int ix = m_portComboBox->findText(newPort); if (ix >= 0) { m_port = newPort; m_portComboBox->setCurrentIndex(ix); m_portComboBox->setToolTip(newPort); updateMenu(); QSettings settings; settings.setValue("programwindow/port", newPort); } } void ProgramTab::setBoard(const QString & newBoard) { DebugDialog::debug(QString("Setting board to %1").arg(newBoard)); int ix = m_boardComboBox->findText(newBoard); if (ix >= 0) { m_board = newBoard; m_boardComboBox->setCurrentIndex(ix); m_boardComboBox->setToolTip(newBoard); updateMenu(); QSettings settings; settings.setValue("programwindow/board", newBoard); } } bool ProgramTab::loadProgramFile() { if (isModified() || !m_textEdit->document()->isEmpty()) { m_programWindow->loadProgramFileNew(); return false; } QString fileName = FolderUtils::getOpenFileName( this, tr("Select a program file to load"), FolderUtils::openSaveFolder(), m_highlighter->syntaxer()->extensionString() ); if (fileName.isEmpty()) return false; return loadProgramFile(fileName, "", true); } bool ProgramTab::loadProgramFile(const QString & fileName, const QString & altFileName, bool updateLink) { DebugDialog::debug("program tab load program file"); if (m_programWindow->alreadyHasProgram(fileName)) { return false; } DebugDialog::debug("checking file"); QFile file(fileName); if (!file.open(QFile::ReadOnly)) { m_programWindow->updateLink(fileName, m_platform, false, true); if (!altFileName.isEmpty()) { file.setFileName(altFileName); if (!file.open(QFile::ReadOnly)) { QFileInfo fileInfo(fileName); QString fn = FolderUtils::getOpenFileName( NULL, tr("Fritzing is unable to find '%1', please locate it").arg(fileInfo.fileName()), FolderUtils::openSaveFolder(), tr("Code (*.%1)").arg(fileInfo.suffix()) ); if (fn.isEmpty()) return false; file.setFileName(fn); if (!file.open(QFile::ReadOnly)) { return false; } } } } DebugDialog::debug("about to read"); m_filename = file.fileName(); QString text = file.readAll(); // clean out 0x91, mostly due to picaxe files for (int i = 0; i < text.count(); i++) { if (text[i] == Quote91Char) { text[i] = '\''; } } DebugDialog::debug("about to set text"); m_textEdit->setText(text); setClean(); QFileInfo fileInfo(m_filename); m_tabWidget->setTabText(m_tabWidget->currentIndex(), fileInfo.fileName()); m_tabWidget->setTabToolTip(m_tabWidget->currentIndex(), m_filename); DebugDialog::debug("about to update link"); if (updateLink) { m_programWindow->updateLink(m_filename, m_platform, true, true); } return true; } void ProgramTab::textChanged() { QIcon tabIcon = m_tabWidget->tabIcon(m_tabWidget->currentIndex()); bool modified = isModified(); if (m_saveButton) { m_saveButton->setEnabled(modified); } updateMenu(); // calls enableProgramButton if (tabIcon.isNull()) { if (modified) { m_tabWidget->setTabIcon(m_tabWidget->currentIndex(), *AsteriskIcon); } } else { if (!modified) { m_tabWidget->setTabIcon(m_tabWidget->currentIndex(), QIcon()); } } } void ProgramTab::undo() { m_textEdit->undo(); } void ProgramTab::enableUndo(bool enable) { m_canUndo = enable; m_saveButton->setEnabled(m_canUndo); updateMenu(); } void ProgramTab::redo() { m_textEdit->redo(); } void ProgramTab::enableRedo(bool enable) { m_canRedo = enable; updateMenu(); } void ProgramTab::cut() { m_textEdit->cut(); } void ProgramTab::enableCut(bool enable) { m_canCut = enable; updateMenu(); } void ProgramTab::copy() { m_textEdit->copy(); } void ProgramTab::enableCopy(bool enable) { m_canCopy = enable; updateMenu(); } void ProgramTab::paste() { m_textEdit->paste(); } void ProgramTab::enablePaste(bool enable) { m_canPaste = enable; updateMenu(); } void ProgramTab::selectAll() { m_textEdit->selectAll(); } void ProgramTab::deleteTab() { bool deleteFile = false; if (!m_textEdit->document()->isEmpty()) { QString name = QFileInfo(m_filename).fileName(); if (name.isEmpty()) { name = m_tabWidget->tabText(m_tabWidget->currentIndex()); } DeleteDialog deleteDialog(tr("Remove \"%1\"?").arg(name), tr("Are you sure you want to remove \"%1\" from the sketch?").arg(name), !FolderUtils::isEmptyFileName(m_filename, "Untitled"), NULL, 0); int reply = deleteDialog.exec(); if (reply != QMessageBox::Yes) { return; } deleteFile = deleteDialog.deleteFileChecked(); } if (m_tabWidget) { emit wantToDelete(m_tabWidget->currentIndex(), deleteFile); this->deleteLater(); } } bool ProgramTab::isModified() { return m_textEdit->document()->isModified(); } const QString & ProgramTab::filename() { return m_filename; } void ProgramTab::setFilename(const QString & name) { m_filename = name; updateMenu(); // Here we update the widget's tab label. We need // to check that it both has the PTabWidget as its // parent and it's already been added to the PTabWidget int currentIndex = m_tabWidget->indexOf(this); if (currentIndex >= 0) { m_tabWidget->setTabText(currentIndex, name.section("/",-1)); } else { DebugDialog::debug("Negative index"); } } const QStringList & ProgramTab::extensions() { if (m_highlighter == NULL) return ___emptyStringList___; Syntaxer * syntaxer = m_highlighter->syntaxer(); if (syntaxer == NULL) return ___emptyStringList___; return syntaxer->extensions(); } const QString & ProgramTab::extensionString() { if (m_highlighter == NULL) return ___emptyString___; Syntaxer * syntaxer = m_highlighter->syntaxer(); if (syntaxer == NULL) return ___emptyString___; return syntaxer->extensionString(); } void ProgramTab::setClean() { m_textEdit->document()->setModified(false); textChanged(); } void ProgramTab::setDirty() { m_textEdit->document()->setModified(true); textChanged(); } void ProgramTab::save() { emit wantToSave(m_tabWidget->currentIndex()); } void ProgramTab::saveAs() { emit wantToSaveAs(m_tabWidget->currentIndex()); } void ProgramTab::rename() { emit wantToRename(m_tabWidget->currentIndex()); } void ProgramTab::print(QPrinter &printer) { m_textEdit->print(&printer); } void ProgramTab::setText(QString text) { m_textEdit->setPlainText(text); } QString ProgramTab::text() { return m_textEdit->toPlainText(); } bool ProgramTab::readOnly() { // TODO: return true if it's a sample file return false; } bool ProgramTab::save(const QString & filename) { QFile file(filename); if (!file.open(QFile::WriteOnly)) { return false; } QByteArray b = m_textEdit->toPlainText().toLatin1(); qint64 written = file.write(b); file.close(); bool result = (b.length() == written); if (result) { setFilename(filename); } return result; } void ProgramTab::serialMonitor() { if (m_monitorWindow == NULL) { m_monitorWindow = new ConsoleWindow(this); } m_monitorWindow->show(); m_monitorWindow->activateWindow(); m_monitorWindow->raise(); m_monitorWindow->openSerialPort(m_port); } void ProgramTab::sendProgram() { const QString commandLoc = m_platform->getCommandLocation(); if (commandLoc.isEmpty()) { m_console->setPlainText(tr("No uploader for %1 specified. Go to Preferences > Code View to configure it.").arg(m_platform->getName())); return; } if (! QFile::exists(commandLoc)) { m_console->setPlainText(tr("Uploader configured, but not found at %1").arg(commandLoc)); return; } if (isModified()) { //QMessageBox::information(this, QObject::tr("Fritzing"), tr("The file '%1' must be saved before it can be sent to the programmer.").arg(m_filename)); //return; save(); } if (m_monitorWindow != NULL) { m_monitorWindow->closeSerialPort(m_portComboBox->currentText()); } m_programButton->setEnabled(false); m_console->setPlainText(""); m_platform->upload(this, m_portComboBox->currentData().toString(), m_boardComboBox->currentText(), m_filename); } void ProgramTab::programProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { DebugDialog::debug(QString("program process finished %1 %2").arg(exitCode).arg(exitStatus)); m_programButton->setEnabled(true); sender()->deleteLater(); if (exitCode == 0) { m_console->appendPlainText(tr("Upload finished.")); } else { m_console->appendPlainText(tr("Upload failed with exit code %1, %2").arg(exitCode).arg(exitStatus)); } } void ProgramTab::programProcessReadyRead() { QByteArray byteArray = qobject_cast(sender())->readAllStandardOutput(); m_console->appendPlainText(byteArray); } /** * This function emits all the required signals to update the menu of its owning ProgramWindow. * It is currently called on the QTabWidget's currentChanged() signal. */ void ProgramTab::updateMenu() { // DebugDialog::debug(QString("Updating the menu for tab %1").arg(m_tabWidget->currentIndex())); // DebugDialog::debug(QString("Undo: %1").arg(m_canUndo)); // DebugDialog::debug(QString("Redo: %1").arg(m_canRedo)); // DebugDialog::debug(QString("Cut: %1").arg(m_canCut)); // DebugDialog::debug(QString("Copy: %1").arg(m_canCopy)); // DebugDialog::debug(QString("Paste: %1").arg(m_canPaste)); // DebugDialog::debug(QString("Platform: %1").arg(m_platform.getName())); // DebugDialog::debug(QString("Port: %1").arg(m_port)); enableProgramButton(); // Emit a signal so that the ProgramWindow can update its own UI. emit programWindowUpdateRequest(m_programButton ? m_programButton->isEnabled() : false, m_canUndo, m_canRedo, m_canCut, m_canCopy, m_canPaste, m_platform, m_port, m_board, m_filename); } void ProgramTab::updateBoards() { QString currentBoard; int index = m_boardComboBox->currentIndex(); if (index >= 0) { currentBoard = m_boardComboBox->itemText(index); } while (m_boardComboBox->count() > 0) { m_boardComboBox->removeItem(0); } QMap boardNames = m_programWindow->getBoards(); foreach (QString name, boardNames.keys()) { m_boardComboBox->addItem(name, boardNames.value(name)); } int foundIt = m_boardComboBox->findText(currentBoard); if (foundIt >= 0) m_boardComboBox->setCurrentIndex(foundIt); else setBoard(m_platform->getDefaultBoardName()); } void ProgramTab::updateSerialPorts() { QList ports = m_programWindow->getSerialPorts(); QList newPorts; foreach (QSerialPortInfo port, ports) { if (m_portComboBox->findText(port.portName()) < 0) { newPorts.append(port); } } QList obsoletePorts; for (int i = 0; i < m_portComboBox->count(); i++) { QString portName = m_portComboBox->itemText(i); if (!m_programWindow->hasPort(portName)) { obsoletePorts.append(i); } if (i == m_portComboBox->currentIndex()) { // TODO: what? } } for (int i = obsoletePorts.count() - 1; i >= 0; i--) { m_portComboBox->removeItem(obsoletePorts.at(i)); } foreach (QSerialPortInfo port, newPorts) { m_portComboBox->addItem(port.portName(), port.systemLocation()); } enableProgramButton(); enableMonitorButton(); } Platform * ProgramTab::platform() { return m_platform; } void ProgramTab::enableMonitorButton() { if (m_monitorButton == NULL) return; bool enabled = true; if (m_portComboBox->count() == 0) { enabled = false; } m_monitorButton->setEnabled(enabled); } void ProgramTab::enableProgramButton() { if (m_programButton == NULL) return; bool enabled = true; // always enable, to show helpful error message if no programmer is set up /* if (m_platform->getCommandLocation().isEmpty()) { enabled = false; } if (enabled && m_portComboBox->count() == 0) { enabled = false; } if (enabled && m_textEdit->document()->isEmpty()) { enabled = false; } */ m_programButton->setEnabled(enabled); } void ProgramTab::appendToConsole(const QString & text) { m_console->appendPlainText(text); } fritzing-app-0.9.2b/src/program/programtab.h000066400000000000000000000130641250202676700210560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef PROGRAMTAB_H_ #define PROGRAMTAB_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "programwindow.h" #include "consolewindow.h" #include "../sketchtoolbutton.h" class SerialPortComboBox : public QComboBox { Q_OBJECT public: SerialPortComboBox(); protected: void showPopup(); signals: void aboutToShow(); }; class ProgramTab : public QFrame { Q_OBJECT public: ProgramTab(QString & filename, QWidget * parent); ~ProgramTab(); void showEvent(QShowEvent *event); bool isModified(); const QString & filename(); void setFilename(const QString &); const QStringList & extensions(); const QString & extensionString(); bool readOnly(); void setClean(); void setDirty(); bool save(const QString & filename); bool loadProgramFile(const QString & filename, const QString & altFilename, bool noUpdate); void print(QPrinter & printer); void setText(QString text); QString text(); Platform *platform(); void setPlatform(const QString & newPlatformName, bool updateLink); void setPlatform(Platform * newPlatform, bool updateLink); void appendToConsole(const QString &); void initMenus(); public slots: void setPlatform(const QString & newPlatformName); void setPlatform(Platform * newPlatform); void setPort(const QString &); void setBoard(const QString &); bool loadProgramFile(); void textChanged(); void undo(); void enableUndo(bool enable); void redo(); void enableRedo(bool enable); void cut(); void enableCut(bool enable); void copy(); void enableCopy(bool enable); void paste(); void enablePaste(bool enable); void selectAll(); void deleteTab(); void save(); void saveAs(); void rename(); void serialMonitor(); void sendProgram(); void programProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void programProcessReadyRead(); void updateMenu(); void updateSerialPorts(); void updateBoards(); signals: // TODO: since ProgramTab has m_programWindow most/all of these signals could be replaced by direct // calls to ProgramWindow public functions void wantToSave(int); void wantToSaveAs(int); void wantToRename(int); void wantToDelete(int, bool deleteFile); void platformChanged(Platform * newPlatform); void programWindowUpdateRequest(bool programEnable, bool undoEnable, bool redoEnable, bool cutEnable, bool copyEnable, bool pasteEnable, Platform * platform, const QString & port, const QString & board, const QString & filename); protected: QFrame * createFooter(); protected slots: void enableProgramButton(); void enableMonitorButton(); protected: QPointer m_newButton; QPointer m_openButton; QPointer m_saveButton; QPointer m_cancelCloseButton; QPointer m_monitorButton; QPointer m_programButton; QPointer m_portComboBox; QPointer m_platformComboBox; QPointer m_boardComboBox; QPointer m_textEdit; QPointer m_console; QPointer m_tabWidget; QPointer m_unableToProgramLabel; QPointer m_toolbar; QHBoxLayout *m_leftButtonsContainer; QHBoxLayout *m_middleButtonsContainer; QHBoxLayout *m_rightButtonsContainer; bool m_updateEnabled; QPointer m_monitorWindow; QPointer m_programWindow; // Store the status of selected text, undo, and redo actions // so this tab can emit the proper status of these actions // on activation bool m_canUndo; bool m_canRedo; bool m_canCopy; bool m_canCut; bool m_canPaste; QPointer m_platform; QString m_port; QString m_board; QPointer m_highlighter; QString m_filename; }; class DeleteDialog : public QDialog { Q_OBJECT public: DeleteDialog(const QString & title, const QString & text, bool deleteFileCheckBox, QWidget * parent = 0, Qt::WindowFlags f = 0); bool deleteFileChecked(); protected slots: void buttonClicked(QAbstractButton * button); protected: QDialogButtonBox * m_buttonBox; QCheckBox * m_checkBox; }; #endif /* PROGRAMTAB_H_ */ fritzing-app-0.9.2b/src/program/programwindow.cpp000066400000000000000000000704701250202676700221560ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ ///////////////////////////////////////////// // // TODO // // integrate dirty // remove old program window // enable all buttons, and give error messages (i.e. where is IDE) #include "programwindow.h" #include "highlighter.h" #include "syntaxer.h" #include "programtab.h" #include "platformarduino.h" #include "platformpicaxe.h" #include "../debugdialog.h" #include "../waitpushundostack.h" #include "../utils/folderutils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////// PTabWidget::PTabWidget(QWidget * parent) : QTabWidget(parent) { m_lastTabIndex = -1; connect(tabBar(), SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); } QTabBar * PTabWidget::tabBar() { return QTabWidget::tabBar(); } void PTabWidget::tabChanged(int index) { // Hide the close button on the old tab if (m_lastTabIndex >= 0) { QAbstractButton *tabButton = qobject_cast(tabBar()->tabButton(m_lastTabIndex, QTabBar::LeftSide)); if (!tabButton) { tabButton = qobject_cast(tabBar()->tabButton(m_lastTabIndex, QTabBar::RightSide)); } if (tabButton) { tabButton->hide(); } } m_lastTabIndex = index; // Show the close button on the new tab if (m_lastTabIndex >= 0) { QAbstractButton *tabButton = qobject_cast(tabBar()->tabButton(m_lastTabIndex, QTabBar::LeftSide)); if (!tabButton) { tabButton = qobject_cast(tabBar()->tabButton(m_lastTabIndex, QTabBar::RightSide)); } if (tabButton) { tabButton->show(); } } } /////////////////////////////////////////////// static int UntitledIndex = 1; QList ProgramWindow::m_platforms; QString ProgramWindow::NoBoardName; ProgramWindow::ProgramWindow(QWidget *parent) : FritzingWindow("", untitledFileCount(), "", parent) { QFile styleSheet(":/resources/styles/programwindow.qss"); this->setObjectName("programmingWindow"); if (!styleSheet.open(QIODevice::ReadOnly)) { qWarning("Unable to open :/resources/styles/programwindow.qss"); } else { QString ss = styleSheet.readAll(); #ifdef Q_OS_MAC int paneLoc = 4; int tabBarLoc = 0; #else int paneLoc = -1; int tabBarLoc = 5; #endif ss = ss.arg(paneLoc).arg(tabBarLoc); this->setStyleSheet(ss); } if (m_platforms.count() == 0) { initPlatforms(); } if (NoBoardName.isEmpty()) { NoBoardName = tr("No boards available"); } m_savingProgramTab = NULL; UntitledIndex--; // incremented by FritzingWindow ProgramWindow::setTitle(); // set to something weird by FritzingWindow } ProgramWindow::~ProgramWindow() { } void ProgramWindow::setup() { if (parentWidget() == NULL) { resize(500,700); setAttribute(Qt::WA_DeleteOnClose, true); } QFrame * mainFrame = new QFrame(this); QFrame * headerFrame = createHeader(); QFrame * centerFrame = createCenter(); layout()->setMargin(0); layout()->setSpacing(0); QGridLayout *layout = new QGridLayout(mainFrame); layout->setMargin(0); layout->setSpacing(0); layout->addWidget(headerFrame,0,0); layout->addWidget(centerFrame,1,0); setCentralWidget(mainFrame); setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); QSettings settings; if (!settings.value("programwindow/state").isNull()) { restoreState(settings.value("programwindow/state").toByteArray()); } if (!settings.value("programwindow/geometry").isNull()) { restoreGeometry(settings.value("programwindow/geometry").toByteArray()); } installEventFilter(this); } void ProgramWindow::initMenus(QMenuBar * menubar) { QAction *currentAction; m_editMenu = menubar->addMenu(tr("&Edit")); m_undoAction = new QAction(tr("Undo"), this); m_undoAction->setShortcuts(QKeySequence::Undo); m_undoAction->setEnabled(false); connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo())); m_editMenu->addAction(m_undoAction); m_redoAction = new QAction(tr("Redo"), this); m_redoAction->setShortcuts(QKeySequence::Redo); m_redoAction->setEnabled(false); connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo())); m_editMenu->addAction(m_redoAction); m_editMenu->addSeparator(); m_cutAction = new QAction(tr("&Cut"), this); m_cutAction->setShortcut(QKeySequence::Cut); m_cutAction->setStatusTip(tr("Cut selection")); m_cutAction->setEnabled(false); connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cut())); m_editMenu->addAction(m_cutAction); m_copyAction = new QAction(tr("&Copy"), this); m_copyAction->setShortcut(QKeySequence::Copy); m_copyAction->setStatusTip(tr("Copy selection")); m_copyAction->setEnabled(false); connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copy())); m_editMenu->addAction(m_copyAction); m_pasteAction = new QAction(tr("&Paste"), this); m_pasteAction->setShortcut(QKeySequence::Paste); m_pasteAction->setStatusTip(tr("Paste clipboard contents")); // TODO: Check clipboard status and disable appropriately here connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); m_editMenu->addAction(m_pasteAction); m_editMenu->addSeparator(); m_selectAction = new QAction(tr("&Select All"), this); m_selectAction->setShortcut(QKeySequence::SelectAll); m_selectAction->setStatusTip(tr("Select all text")); connect(m_selectAction, SIGNAL(triggered()), this, SLOT(selectAll())); m_editMenu->addAction(m_selectAction); m_editMenu->addSeparator(); m_preferencesAction = new QAction(tr("&Preferences..."), this); m_preferencesAction->setStatusTip(tr("Show the application's about box")); connect(m_preferencesAction, SIGNAL(triggered()), QApplication::instance(), SLOT(preferences())); m_editMenu->addAction(m_preferencesAction); m_programMenu = menubar->addMenu(tr("&Code")); m_newAction = new QAction(tr("&New Tab"), this); m_newAction->setShortcut(QKeySequence::AddTab); m_newAction->setStatusTip(tr("Create a new program tab")); connect(m_newAction, SIGNAL(triggered()), this, SLOT(addTab())); m_programMenu->addAction(m_newAction); m_openAction = new QAction(tr("&Import Code..."), this); m_openAction->setShortcut(tr("Alt+Ctrl+I")); m_openAction->setStatusTip(tr("Import a program from a file")); connect(m_openAction, SIGNAL(triggered()), this, SLOT(loadProgramFile())); m_programMenu->addAction(m_openAction); m_saveAction = new QAction(tr("&Save Tab"), this); m_saveAction->setShortcut(tr("Alt+Ctrl+S")); m_saveAction->setStatusTip(tr("Save the current program tab")); connect(m_saveAction, SIGNAL(triggered()), this, SLOT(saveCurrentTab())); m_programMenu->addAction(m_saveAction); currentAction = new QAction(tr("&Rename Tab"), this); currentAction->setShortcut(tr("Alt+Ctrl+R")); currentAction->setStatusTip(tr("Rename the current program tab")); connect(currentAction, SIGNAL(triggered()), this, SLOT(rename())); m_programMenu->addAction(currentAction); currentAction = new QAction(tr("Close Tab"), this); currentAction->setShortcut(tr("Alt+Ctrl+W")); currentAction->setStatusTip(tr("Remove the current program tab from the sketch")); connect(currentAction, SIGNAL(triggered()), this, SLOT(closeCurrentTab())); m_programMenu->addAction(currentAction); m_programMenu->addSeparator(); m_platformMenu = new QMenu(tr("Platform"), this); m_programMenu->addMenu(m_platformMenu); QSettings settings; QString currentPlatform = settings.value("programwindow/platform", "").toString(); QList platforms = getAvailablePlatforms(); m_platformActionGroup = new QActionGroup(this); foreach (Platform * platform, platforms) { currentAction = new QAction(platform->getName(), this); currentAction->setCheckable(true); m_platformActions.insert(platform, currentAction); m_platformActionGroup->addAction(currentAction); m_platformMenu->addAction(currentAction); if (!currentPlatform.isEmpty()) { if (platform->getName().compare(currentPlatform) == 0) { currentAction->setChecked(true); } } } connect(m_platformMenu, SIGNAL(triggered(QAction*)), this, SLOT(setPlatform(QAction*))); m_boardMenu = new QMenu(tr("Board"), this); m_programMenu->addMenu(m_boardMenu); m_boardActionGroup = new QActionGroup(this); updateBoards(); connect(m_boardMenu, SIGNAL(triggered(QAction*)), this, SLOT(setBoard(QAction*))); m_serialPortMenu = new QMenu(tr("Port"), this); m_programMenu->addMenu(m_serialPortMenu); m_serialPortActionGroup = new QActionGroup(this); updateSerialPorts(); connect(m_serialPortMenu, SIGNAL(triggered(QAction*)), this, SLOT(setPort(QAction*))); connect(m_serialPortMenu, SIGNAL(aboutToShow()), this, SLOT(updateSerialPorts()), Qt::DirectConnection); m_programMenu->addSeparator(); m_monitorAction = new QAction(tr("Serial Monitor"), this); m_monitorAction->setShortcut(tr("Ctrl+M")); m_monitorAction->setStatusTip(tr("Monitor the serial port communication")); m_monitorAction->setEnabled(false); connect(m_monitorAction, SIGNAL(triggered()), this, SLOT(serialMonitor())); m_programMenu->addAction(m_monitorAction); m_programAction = new QAction(tr("Upload"), this); m_programAction->setShortcut(tr("Ctrl+U")); m_programAction->setStatusTip(tr("Upload the current program onto a microcontroller")); m_programAction->setEnabled(false); connect(m_programAction, SIGNAL(triggered()), this, SLOT(sendProgram())); m_programMenu->addAction(m_programAction); m_viewMenu = menubar->addMenu(tr("&View")); foreach (QAction * action, m_viewMenuActions) { m_viewMenu->addAction(action); } addTab(); // the initial ProgramTab must be created after all actions are set up } void ProgramWindow::showMenus(bool show) { if (m_editMenu) { m_editMenu->menuAction()->setVisible(show); m_editMenu->setEnabled(show); m_undoAction->setEnabled(show); m_redoAction->setEnabled(show); m_cutAction->setEnabled(show); m_copyAction->setEnabled(show); m_pasteAction->setEnabled(show); m_selectAction->setEnabled(show); } if (m_programMenu) { m_programMenu->menuAction()->setVisible(show); m_programMenu->setEnabled(show); } if (m_viewMenu) { m_viewMenu->menuAction()->setVisible(show); m_viewMenu->setEnabled(show); } } void ProgramWindow::createViewMenuActions(QList & actions) { m_viewMenuActions = actions; } void ProgramWindow::linkFiles(const QList & linkedFiles, const QString & alternativePath) { if (linkedFiles.isEmpty()) return; bool firstTime = true; foreach (LinkedFile * linkedFile, linkedFiles) { ProgramTab * programTab = NULL; if (firstTime) { firstTime = false; programTab = indexWidget(0); } else { programTab = addTab(); } QDir dir(alternativePath); QFileInfo fileInfo(linkedFile->linkedFilename); programTab->loadProgramFile(linkedFile->linkedFilename, dir.absoluteFilePath(fileInfo.fileName()), false); if ((linkedFile->fileFlags & LinkedFile::InBundleFlag) && ((linkedFile->fileFlags & LinkedFile::ReadOnlyFlag) == 0)) { if (linkedFile->fileFlags & LinkedFile::SameMachineFlag) { programTab->appendToConsole(tr("File '%1' was restored from the .fzz file; the local copy was not found.").arg(fileInfo.fileName())); } else { programTab->appendToConsole(tr("File '%1' was restored from the .fzz file; save a local copy to work with an external editor.").arg(fileInfo.fileName())); } } if (hasPlatform(linkedFile->platform)) { programTab->setPlatform(linkedFile->platform, false); } else { linkedFile->platform.clear(); } } } QFrame * ProgramWindow::createHeader() { QFrame * headerFrame = new QFrame(); headerFrame->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed)); headerFrame->setObjectName("header"); return headerFrame; } QFrame * ProgramWindow::createCenter() { QFrame * centerFrame = new QFrame(this); centerFrame->setObjectName("center"); m_tabWidget = new PTabWidget(centerFrame); m_tabWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); m_tabWidget->setMovable(true); m_tabWidget->setTabsClosable(true); m_tabWidget->setUsesScrollButtons(false); m_tabWidget->setElideMode(Qt::ElideLeft); connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int))); //addTab(); QGridLayout *tabLayout = new QGridLayout(m_tabWidget); tabLayout->setMargin(0); tabLayout->setSpacing(0); QGridLayout *mainLayout = new QGridLayout(centerFrame); mainLayout->setMargin(0); mainLayout->setSpacing(0); mainLayout->addWidget(m_tabWidget,0,0,1,1); return centerFrame; } void ProgramWindow::cleanUp() { } /** * eventFilter here is used to catch the keyboard shortcuts that trigger the close event * for ProgramWindow. If there are more than one tab widget the standard close shortcut * should only close the current tab instead of closing the whole window. Every other * case is ignored and handled by closeEvent() like normal. */ bool ProgramWindow::eventFilter(QObject * object, QEvent * event) { if (object == this && event->type() == QEvent::ShortcutOverride) { QKeyEvent *keyEvent = dynamic_cast(event); if(keyEvent && keyEvent->matches(QKeySequence::Close) && m_tabWidget->count() > 1 ) { return true; } } return QMainWindow::eventFilter(object, event); } /** * Reimplement closeEvent to save any modified documents before closing. */ void ProgramWindow::closeEvent(QCloseEvent *event) { bool discard; if(beforeClosing(true, discard)) { cleanUp(); QMainWindow::closeEvent(event); emit closed(); } else { event->ignore(); } QSettings settings; settings.setValue("programwindow/state",saveState()); settings.setValue("programwindow/geometry",saveGeometry()); } const QString ProgramWindow::untitledFileName() { return "Untitled"; } const QString ProgramWindow::fileExtension() { return ""; } const QString ProgramWindow::defaultSaveFolder() { return FolderUtils::openSaveFolder(); } bool ProgramWindow::event(QEvent * e) { switch (e->type()) { case QEvent::WindowActivate: emit changeActivationSignal(true, this); break; case QEvent::WindowDeactivate: emit changeActivationSignal(false, this); break; default: break; } return FritzingWindow::event(e); } int & ProgramWindow::untitledFileCount() { return UntitledIndex; } void ProgramWindow::setTitle() { setWindowTitle(tr("Code Window")); } void ProgramWindow::setTitle(const QString & filename) { setWindowTitle(tr("Code Window - %1").arg(filename)); } /** * Create and open a new tab within the PTabWidget child. * This function handled connecting all the appropriate signals * and setting an appropriate filename. */ ProgramTab * ProgramWindow::addTab() { QString name = (UntitledIndex == 1) ? untitledFileName() : tr("%1%2").arg(untitledFileName()).arg(UntitledIndex); ProgramTab * programTab = new ProgramTab(name, m_tabWidget); connect(programTab, SIGNAL(wantToSave(int)), this, SLOT(tabSave(int))); connect(programTab, SIGNAL(wantToSaveAs(int)), this, SLOT(tabSaveAs(int))); connect(programTab, SIGNAL(wantToRename(int)), this, SLOT(tabRename(int))); connect(programTab, SIGNAL(wantToDelete(int, bool)), this, SLOT(tabDelete(int, bool)), Qt::DirectConnection); connect(programTab, SIGNAL(programWindowUpdateRequest(bool, bool, bool, bool, bool, bool, Platform *, const QString &, const QString &, const QString &)), this, SLOT(updateMenu(bool, bool, bool, bool, bool, bool, Platform *, const QString &, const QString &, const QString &))); int ix = m_tabWidget->addTab(programTab, name); m_tabWidget->setCurrentIndex(ix); programTab->initMenus(); UntitledIndex++; return programTab; } /** * A function for closing the current displayed tab. * I'm using a ProgramWindow method instead of calling deleteTab() * directly as I believe it's more apropos. */ void ProgramWindow::closeCurrentTab() { closeTab(m_tabWidget->currentIndex()); } void ProgramWindow::closeTab(int index) { ProgramTab * pTab = indexWidget(index); if (pTab) { emit linkToProgramFile(pTab->filename(), NULL, false, true); pTab->deleteTab(); } } /** * This slot is for updating the tab-dependent menu items. * - program * - undo/redo * - cut/copy */ void ProgramWindow::updateMenu(bool programEnable, bool undoEnable, bool redoEnable, bool cutEnable, bool copyEnable, bool pasteEnable, Platform* platform, const QString & port, const QString & board, const QString & filename) { ProgramTab * programTab = currentWidget(); m_saveAction->setEnabled(programTab->isModified()); m_monitorAction->setEnabled(!port.isEmpty()); m_programAction->setEnabled(programEnable); m_undoAction->setEnabled(undoEnable); m_redoAction->setEnabled(redoEnable); m_cutAction->setEnabled(cutEnable); m_copyAction->setEnabled(copyEnable); m_pasteAction->setEnabled(pasteEnable); QAction *lang = m_platformActions.value(platform); if (lang) { lang->setChecked(true); } QAction *portAction = m_portActions.value(port); if (portAction) { portAction->setChecked(true); } QAction *boardAction = m_boardActions.value(board); if (boardAction) { boardAction->setChecked(true); } setTitle(filename); } void ProgramWindow::setPlatform(QAction* action) { currentWidget()->setPlatform(action->text()); } void ProgramWindow::setPort(QAction* action) { currentWidget()->setPort(action->text()); } void ProgramWindow::setBoard(QAction* action) { currentWidget()->setBoard(action->text()); } bool ProgramWindow::beforeClosing(bool showCancel, bool & discard) { discard = false; for (int i = 0; i < m_tabWidget->count(); i++) { if (!beforeClosingTab(i, showCancel)) { return false; } } return true; } bool ProgramWindow::beforeClosingTab(int index, bool showCancel) { ProgramTab * programTab = indexWidget(index); if (programTab == NULL) return true; if (!programTab->isModified()) return true; QMessageBox::StandardButton reply = beforeClosingMessage(programTab->filename(), showCancel); if (reply == QMessageBox::Save) { return prepSave(programTab, false); } if (reply == QMessageBox::Discard) { return true; } return false; } void ProgramWindow::print() { #ifndef QT_NO_PRINTER QPrinter printer(QPrinter::HighResolution); QPrintDialog printDialog(&printer, this); if (printDialog.exec() == QDialog::Accepted) { currentWidget()->print(printer); } #endif } // overrides MainWindow::saveAsAux bool ProgramWindow::saveAsAux(const QString & fileName) { if (!m_savingProgramTab) return false; bool result = m_savingProgramTab->save(fileName); m_savingProgramTab = NULL; return result; } void ProgramWindow::tabDelete(int index, bool deleteFile) { ProgramTab * programTab = indexWidget(index); QString fname = programTab->filename(); m_tabWidget->removeTab(index); if (m_tabWidget->count() == 0) { addTab(); } if (deleteFile) { QFile file(fname); file.remove(); } } void ProgramWindow::saveAll() { for (int i= 0; i < m_tabWidget->count(); i++) tabSave(i); } void ProgramWindow::saveCurrentTab() { tabSave(m_tabWidget->currentIndex()); } void ProgramWindow::tabSave(int index) { ProgramTab * programTab =indexWidget(index); if (programTab == NULL) return; prepSave(programTab, false); } void ProgramWindow::tabSaveAs(int index) { ProgramTab * programTab = indexWidget(index); if (programTab == NULL) return; prepSave(programTab, true); } void ProgramWindow::tabRename(int index) { ProgramTab * programTab = indexWidget(index); if (programTab == NULL) return; QString oldFileName = programTab->filename(); if (prepSave(programTab, true)) { if (programTab->filename() != oldFileName) { QFile oldFile(oldFileName); if (oldFile.exists()) { oldFile.remove(); emit linkToProgramFile(oldFileName, NULL, false, true); } } } } void ProgramWindow::duplicateTab() { ProgramTab * oldTab = currentWidget(); if (oldTab == NULL) return; ProgramTab * newTab = addTab(); newTab->setText(oldTab->text()); } void ProgramWindow::tabBeforeClosing(int index, bool & ok) { ok = beforeClosingTab(index, true); } bool ProgramWindow::prepSave(ProgramTab * programTab, bool saveAsFlag) { m_savingProgramTab = programTab; // need this for the saveAsAux call if (!programTab->isModified()) return false; bool result = (saveAsFlag) ? saveAs(programTab->filename(), programTab->readOnly()) : save(programTab->filename(), programTab->readOnly()); if (result) { programTab->setClean(); emit linkToProgramFile(programTab->filename(), programTab->platform(), true, true); } return result; } void ProgramWindow::initPlatforms() { QDir dir(FolderUtils::getApplicationSubFolderPath("translations")); Highlighter::loadStyles(dir.absolutePath().append("/syntax/styles.xml")); m_platforms << new PlatformArduino() << new PlatformPicaxe(); } QList ProgramWindow::getAvailablePlatforms() { return m_platforms; } Platform * ProgramWindow::getPlatformByName(const QString & platformName) { foreach (Platform * platform, getAvailablePlatforms()) { if (platform->getName().compare(platformName, Qt::CaseInsensitive) == 0) return platform; } return NULL; } bool ProgramWindow::hasPlatform(const QString & platformName) { return getPlatformByName(platformName) != NULL; } const QMap ProgramWindow::getBoards() { if (currentWidget() && currentWidget()->platform()) return currentWidget()->platform()->getBoards(); QMap boards; boards.insert(NoBoardName, NoBoardName); return boards; } QAction * ProgramWindow::addBoard(const QString & name, const QString & definition) { QAction * currentAction = new QAction(name, this); currentAction->setCheckable(true); currentAction->setData(definition); m_boardActions.insert(name, currentAction); m_boardMenu->addAction(currentAction); m_boardActionGroup->addAction(currentAction); return currentAction; } void ProgramWindow::updateBoards() { QMap boards = getBoards(); m_boardActions.clear(); foreach (QAction * action, m_boardActionGroup->actions()) m_boardActionGroup->removeAction(action); m_boardMenu->clear(); QMapIterator i(boards); while (i.hasNext()) { i.next(); addBoard(i.key(), i.value()); } } void ProgramWindow::loadProgramFile() { DebugDialog::debug("loading program file"); currentWidget()->loadProgramFile(); } void ProgramWindow::loadProgramFileNew() { ProgramTab * programTab = addTab(); if (programTab) { if (!programTab->loadProgramFile()) { delete programTab; } } } void ProgramWindow::rename() { currentWidget()->rename(); } void ProgramWindow::undo() { currentWidget()->undo(); } void ProgramWindow::redo() { currentWidget()->redo(); } void ProgramWindow::cut() { currentWidget()->cut(); } void ProgramWindow::copy() { currentWidget()->copy(); } void ProgramWindow::paste() { currentWidget()->paste(); } void ProgramWindow::selectAll() { currentWidget()->selectAll(); } void ProgramWindow::serialMonitor() { currentWidget()->serialMonitor(); } void ProgramWindow::sendProgram() { currentWidget()->sendProgram(); } ProgramTab * ProgramWindow::currentWidget() { return qobject_cast(m_tabWidget->currentWidget()); } ProgramTab * ProgramWindow::indexWidget(int index) { return qobject_cast(m_tabWidget->widget(index)); } bool ProgramWindow::alreadyHasProgram(const QString & filename) { DebugDialog::debug("already has program"); for (int i = 0; i < m_tabWidget->count(); i++) { ProgramTab * tab = indexWidget(i); if (tab->filename() == filename) { m_tabWidget->setCurrentIndex(i); return true; } } return false; } QString ProgramWindow::getExtensionString() { ProgramTab * pt = currentWidget(); if (pt == NULL) return ""; return pt->extensionString(); } QStringList ProgramWindow::getExtensions() { ProgramTab * pt = currentWidget(); if (pt == NULL) return QStringList(); return pt->extensions(); } QList ProgramWindow::getSerialPorts() { QList ports; ports = QSerialPortInfo::availablePorts(); /* // on the pc, handy for testing the UI when there are no serial ports ports.removeOne("COM0"); ports.removeOne("COM1"); ports.removeOne("COM2"); ports.removeOne("COM3"); */ return ports; } void ProgramWindow::updateSerialPorts() { QList ports = getSerialPorts(); m_portActions.clear(); foreach (QAction * action, m_serialPortActionGroup->actions()) m_serialPortActionGroup->removeAction(action); m_serialPortMenu->clear(); foreach (QSerialPortInfo port, ports) { addPort(port); } } QAction * ProgramWindow::addPort(QSerialPortInfo port) { QAction * currentAction = new QAction(port.portName(), this); currentAction->setCheckable(true); currentAction->setData(port.systemLocation()); m_portActions.insert(port.portName(), currentAction); m_serialPortMenu->addAction(currentAction); m_serialPortActionGroup->addAction(currentAction); return currentAction; } bool ProgramWindow::hasPort(const QString & portName) { foreach (QSerialPortInfo port, getSerialPorts()) { if (port.portName().compare(portName) == 0) return true; } return false; } void ProgramWindow::updateLink(const QString & filename, Platform * platform, bool addlink, bool strong) { DebugDialog::debug("updating link"); emit linkToProgramFile(filename, platform, addlink, strong); } void ProgramWindow::portProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { DebugDialog::debug(QString("process finished %1 %2").arg(exitCode).arg(exitStatus)); // parse the text and update the combo box sender()->deleteLater(); } void ProgramWindow::portProcessReadyRead() { m_ports.clear(); QByteArray byteArray = qobject_cast(sender())->readAllStandardOutput(); QTextStream textStream(byteArray, QIODevice::ReadOnly); while (true) { QString line = textStream.readLine(); if (line.isNull()) break; if (!line.contains("tty")) continue; if (!line.contains("serial", Qt::CaseInsensitive)) continue; QStringList candidates = line.split(" "); foreach (QString candidate, candidates) { if (candidate.contains("tty")) { m_ports.append(candidate); break; } } } } fritzing-app-0.9.2b/src/program/programwindow.h000066400000000000000000000141221250202676700216130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\ the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef PROGRAMWINDOW_H_ #define PROGRAMWINDOW_H_ #include #include #include #include #include #include #include #include #include // #include #include #include #include "platform.h" #include "syntaxer.h" #include "../mainwindow/fritzingwindow.h" struct LinkedFile { enum FileFlag { NoFlag = 0, SameMachineFlag = 1, ObsoleteFlag = 2, InBundleFlag = 4, ReadOnlyFlag = 8 }; Q_DECLARE_FLAGS(FileFlags, FileFlag) QString linkedFilename; QString platform; FileFlags fileFlags; }; class PTabWidget : public QTabWidget { Q_OBJECT protected slots: void tabChanged(int index); protected: int m_lastTabIndex; public: PTabWidget(QWidget * parent); QTabBar * tabBar(); }; class ProgramWindow : public FritzingWindow { Q_OBJECT public: ProgramWindow(QWidget *parent=0); ~ProgramWindow(); void setup(); void initMenus(QMenuBar * menubar); void linkFiles(const QList &, const QString & alternativePath); const QString defaultSaveFolder(); QList getSerialPorts(); QList getAvailablePlatforms(); bool hasPlatform(const QString &platformName); Platform *getPlatformByName(const QString &platformName); const QMap getBoards(); bool hasPort(const QString &portName); void loadProgramFileNew(); bool alreadyHasProgram(const QString &); void updateLink(const QString & filename, Platform *platform, bool addlink, bool strong); void showMenus(bool); void createViewMenuActions(QList &); void print(); public slots: void saveAll(); signals: void closed(); void changeActivationSignal(bool activate, QWidget * originator); void linkToProgramFile(const QString & filename, Platform * platform, bool addlink, bool strong); protected slots: void loadProgramFile(); class ProgramTab * addTab(); void closeCurrentTab(); void closeTab(int index); void saveCurrentTab(); void tabSave(int); void tabSaveAs(int); void tabRename(int); void duplicateTab(); void tabBeforeClosing(int, bool & ok); void tabDelete(int index, bool deleteFile); void updateMenu(bool programEnable, bool undoEnable, bool redoEnable, bool cutEnable, bool copyEnable, bool pasteEnable, Platform * platform, const QString & port, const QString & board, const QString & filename); void updateSerialPorts(); void portProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void portProcessReadyRead(); void updateBoards(); // The following methods just forward events on to the current tab void setPlatform(QAction*); void setPort(QAction*); void setBoard(QAction*); void rename(); void undo(); void redo(); void cut(); void copy(); void paste(); void selectAll(); void serialMonitor(); void sendProgram(); protected: bool event(QEvent * event); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *object, QEvent *event); QFrame * createHeader(); QFrame * createCenter(); const QString untitledFileName(); const QString fileExtension(); void cleanUp(); int &untitledFileCount(); void setTitle(); void setTitle(const QString & filename); bool saveAsAux(const QString & fileName); bool prepSave(class ProgramTab *, bool saveAsFlag); bool beforeClosingTab(int index, bool showCancel); QAction * addBoard(const QString & name, const QString & definition); QAction * addPort(QSerialPortInfo port); inline ProgramTab * currentWidget(); inline ProgramTab * indexWidget(int index); QString getExtensionString(); QStringList getExtensions(); bool beforeClosing(bool showCancel, bool & discard); // returns true if close, false if cancel QStringList getSerialPortsAux(); protected: static void initPlatforms(); public: static const QString LocateName; static QString NoBoardName; QAction *m_newAction; QAction *m_openAction; QAction *m_saveAction; QAction *m_monitorAction; QAction *m_programAction; protected: static QList m_platforms; protected: QPointer m_tabWidget; QPointer m_addButton; QPointer m_savingProgramTab; QAction *m_undoAction; QAction *m_redoAction; QAction *m_cutAction; QAction *m_copyAction; QAction *m_pasteAction; QAction *m_selectAction; QAction *m_printAction; QAction *m_preferencesAction; QMap m_platformActions; QMap m_portActions; QMap m_boardActions; QActionGroup * m_platformActionGroup; QActionGroup * m_boardActionGroup; QActionGroup * m_serialPortActionGroup; QMenu * m_platformMenu; QMenu * m_boardMenu; QMenu * m_serialPortMenu; QStringList m_ports; // temporary storage for linux QMenu* m_editMenu; QMenu* m_viewMenu; QList m_viewMenuActions; QMenu * m_programMenu; }; #endif /* ProgramWindow_H_ */ fritzing-app-0.9.2b/src/program/syntaxer.cpp000066400000000000000000000164431250202676700211340ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "syntaxer.h" #include "../debugdialog.h" #include "../utils/textutils.h" #include #include QHash Syntaxer::m_listsToFormats; Syntaxer::Syntaxer() : QObject() { m_trieRoot = NULL; } Syntaxer::~Syntaxer() { if (m_trieRoot) { delete m_trieRoot; } } bool Syntaxer::loadSyntax(const QString &filename) { QFile file(filename); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { return false; } QDomElement root = domDocument.documentElement(); if (root.isNull()) return false; if (root.tagName() != "language") return false; QDomElement highlighting = root.firstChildElement("highlighting"); if (highlighting.isNull()) return false; QDomElement general = root.firstChildElement("general"); if (general.isNull()) return false; QDomElement contexts = highlighting.firstChildElement("contexts"); if (contexts.isNull()) return false; m_hlCStringChar = false; QDomElement context = contexts.firstChildElement("context"); while (!context.isNull()) { if (context.attribute("attribute").compare("Normal Text") == 0) { m_stringDelimiter = getStringDelimiter(context); initListsToFormats(context); } else if (context.attribute("attribute").compare("String") == 0) { QDomElement HlCStringChar = context.firstChildElement("HlCStringChar"); if (!HlCStringChar.isNull()) { m_hlCStringChar = true; } } context = context.nextSiblingElement("context"); } m_canProgram = root.attribute("canProgram", "").compare("true", Qt::CaseInsensitive) == 0; m_name = root.attribute("name"); QStringList extensions = root.attribute("extensions").split(";", QString::SkipEmptyParts); if (extensions.count() > 0) { m_extensionString = m_name + " " + QObject::tr("files") + " ("; foreach (QString ext, extensions) { m_extensionString += ext + " "; int ix = ext.indexOf("."); if (ix > 0) { ext.remove(0, ix); } m_extensions.append(ext); } m_extensionString.chop(1); m_extensionString += ")"; } m_trieRoot = new TrieNode('\0'); QDomElement list = highlighting.firstChildElement("list"); while (!list.isNull()) { loadList(list); list = list.nextSiblingElement("list"); } QDomElement comments = general.firstChildElement("comments"); if (!comments.isNull()) { Qt::CaseSensitivity caseSensitivity = comments.attribute("casesensitive").compare("1") == 0 ? Qt::CaseSensitive : Qt::CaseInsensitive; QDomElement comment = comments.firstChildElement("comment"); while (!comment.isNull()) { CommentInfo * commentInfo = new CommentInfo(comment.attribute("start"), comment.attribute("end"), caseSensitivity); commentInfo->m_index = m_commentInfo.count(); m_commentInfo.append(commentInfo); comment = comment.nextSiblingElement("comment"); } } return true; } QString Syntaxer::parseForName(const QString & filename) { QFile file(filename); file.open(QFile::ReadOnly); QXmlStreamReader xml(&file); xml.setNamespaceProcessing(false); while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: if (xml.name().toString().compare("language") == 0) { return xml.attributes().value("name").toString(); } break; default: break; } } return ""; } void Syntaxer::loadList(QDomElement & list) { QString name = list.attribute("name"); SyntaxerTrieLeaf * stf = new SyntaxerTrieLeaf(name); QDomElement item = list.firstChildElement("item"); while (!item.isNull()) { QString text; if (TextUtils::findText(item, text)) { QString s = text.trimmed(); m_trieRoot->addString(s, false, stf); } item = item.nextSiblingElement("item"); } } bool Syntaxer::matches(const QString & string, TrieLeaf * & leaf) { if (m_trieRoot == NULL) return false; QString temp = string; return m_trieRoot->matches(temp, leaf); } const CommentInfo * Syntaxer::getCommentInfo(int ix) { return m_commentInfo.at(ix); } bool Syntaxer::matchCommentStart(const QString & text, int offset, int & result, const CommentInfo * & resultCommentInfo) { result = -1; foreach (CommentInfo * commentInfo, m_commentInfo) { int si = text.indexOf(commentInfo->m_start, offset, commentInfo->m_caseSensitive); if (si >= 0 && (result < 0 || si < result)) { result = si; resultCommentInfo = commentInfo; } } return (result >= offset); } int Syntaxer::matchStringStart(const QString & text, int offset) { if (m_stringDelimiter.isNull()) return -1; return text.indexOf(m_stringDelimiter, offset); } int Syntaxer::matchStringEnd(const QString & text, int offset) { return matchStringStart(text, offset); } const QStringList & Syntaxer::extensions() { return m_extensions; } const QString & Syntaxer::extensionString() { return m_extensionString; } QChar Syntaxer::getStringDelimiter(QDomElement & context) { QDomElement detectChar = context.firstChildElement("DetectChar"); while (!detectChar.isNull()) { if (detectChar.attribute("attribute").compare("String") == 0) { QString c = detectChar.attribute("char"); if (c.length() > 0) { return c.at(0); } return QChar(); } detectChar = detectChar.nextSiblingElement("DetectChar"); } return QChar(); } void Syntaxer::initListsToFormats(QDomElement & context) { QDomElement keyword = context.firstChildElement("keyword"); while (!keyword.isNull()) { QString format = keyword.attribute("attribute"); QString list = keyword.attribute("String"); if (!format.isEmpty() && !list.isEmpty()) { m_listsToFormats.insert(list, format); } keyword = keyword.nextSiblingElement("keyword"); } } QString Syntaxer::formatFromList(const QString & list) { return m_listsToFormats.value(list, ___emptyString___); } bool Syntaxer::hlCStringChar() { return m_hlCStringChar; } bool Syntaxer::canProgram() { return m_canProgram; } ////////////////////////////////////////////// SyntaxerTrieLeaf::SyntaxerTrieLeaf(QString name) { m_name = name; } SyntaxerTrieLeaf::~SyntaxerTrieLeaf() { } const QString & SyntaxerTrieLeaf::name() { return m_name; } ////////////////////////////////////////////// CommentInfo::CommentInfo(const QString & start, const QString & end, Qt::CaseSensitivity caseSensitive) { m_start = start; m_end = end; m_multiLine = !end.isEmpty(); m_caseSensitive = caseSensitive; } fritzing-app-0.9.2b/src/program/syntaxer.h000066400000000000000000000052551250202676700206000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SYNTAXER_H_ #define SYNTAXER_H_ #include #include #include #include #include "trienode.h" class CommentInfo { public: CommentInfo(const QString & start, const QString & end, Qt::CaseSensitivity); public: bool m_multiLine; QString m_start; QString m_end; int m_index; Qt::CaseSensitivity m_caseSensitive; }; class Syntaxer : public QObject { Q_OBJECT public: Syntaxer(); virtual ~Syntaxer(); bool loadSyntax(const QString & filename); bool matches(const QString & string, TrieLeaf * & leaf); const CommentInfo * getCommentInfo(int ix); bool matchCommentStart(const QString & text, int offset, int & result, const CommentInfo * & resultCommentInfo); int matchStringStart(const QString & text, int offset); int matchStringEnd(const QString & text, int offset); const QString & extensionString(); const QStringList & extensions(); bool hlCStringChar(); bool canProgram(); public: static QString parseForName(const QString & filename); static QString formatFromList(const QString & list); protected: void loadList(QDomElement & list); QChar getStringDelimiter(QDomElement & context); void initListsToFormats(QDomElement & context); protected: static QHash m_listsToFormats; protected: TrieNode * m_trieRoot; QString m_name; QString m_extensionString; QStringList m_extensions; QList m_commentInfo; QChar m_stringDelimiter; bool m_hlCStringChar; bool m_canProgram; }; class SyntaxerTrieLeaf : public TrieLeaf { public: SyntaxerTrieLeaf(QString name); ~SyntaxerTrieLeaf(); const QString & name(); protected: QString m_name; }; #endif /* SYNTAXER_H_ */ fritzing-app-0.9.2b/src/program/trienode.cpp000066400000000000000000000051621250202676700210640ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "trienode.h" #include "../debugdialog.h" #include #include TrieLeaf::TrieLeaf() { } TrieLeaf::~TrieLeaf() { } TrieNode::TrieNode(QChar c) { m_char = c; m_leafData = NULL; m_isLeaf = false; m_caseInsensitive = false; } TrieNode::~TrieNode() { foreach (TrieNode * node, m_children) { delete node; } m_children.clear(); } void TrieNode::addString(QString & string, bool caseInsensitive, TrieLeaf * leaf) { if (string.isEmpty()) { m_leafData = leaf; m_isLeaf = true; return; } QChar in(string.at(0)); QString next = string.remove(0, 1); QChar c0, c1; if (caseInsensitive) { c0 = in.toLower(); c1 = in.toUpper(); } else { c0 = c1 = in; } addStringAux(c0, next, caseInsensitive, leaf); if (c0 != c1) { addStringAux(c1, next, caseInsensitive, leaf); } } void TrieNode::addStringAux(QChar c, QString & next, bool caseInsensitive, TrieLeaf * leaf) { bool gotc = false; foreach (TrieNode * node, m_children) { if (node->matchesChar(c)) { node->addString(next, caseInsensitive, leaf); gotc = true; } } if (!gotc) { TrieNode * child = new TrieNode(c); m_children.append(child); child->addString(next, caseInsensitive, leaf); } } bool TrieNode::matchesChar(QChar c) { return (c == m_char); } bool TrieNode::matches(QString & string, TrieLeaf * & leaf) { if (string.isEmpty()) { if (m_isLeaf) { leaf = m_leafData; return true; } return false; } QChar in(string.at(0)); foreach (TrieNode * node, m_children) { if (node->matchesChar(in)) { return node->matches(string.remove(0, 1), leaf); } } return false; } fritzing-app-0.9.2b/src/program/trienode.h000066400000000000000000000032131250202676700205240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef TRIENODE_H_ #define TRIENODE_H_ #include #include class TrieLeaf { public: TrieLeaf(); virtual ~TrieLeaf(); }; class TrieNode { public: TrieNode(QChar); virtual ~TrieNode(); virtual void addString(QString & s, bool caseInsensitive, TrieLeaf * leaf); virtual bool matches(QString & string, TrieLeaf * & leaf); protected: virtual void addStringAux(QChar c, QString & next, bool caseInsensitive, TrieLeaf * leaf); virtual bool matchesChar(QChar c); protected: QChar m_char; bool m_caseInsensitive; QList m_children; TrieLeaf * m_leafData; bool m_isLeaf; }; #endif /* TRIENODE_H_ */ fritzing-app-0.9.2b/src/referencemodel/000077500000000000000000000000001250202676700200535ustar00rootroot00000000000000fritzing-app-0.9.2b/src/referencemodel/referencemodel.h000066400000000000000000000047511250202676700232120ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef REFERENCEMODEL_H_ #define REFERENCEMODEL_H_ #include "../model/palettemodel.h" class ReferenceModel : public PaletteModel { Q_OBJECT public: virtual bool loadAll(const QString & databaseName, bool fullLoad, bool dbExists) = 0; virtual bool loadFromDB(const QString & databaseName) = 0; virtual ModelPart *loadPart(const QString & path, bool update) = 0; virtual ModelPart *reloadPart(const QString & path, const QString & moduleID) = 0; virtual ModelPart *retrieveModelPart(const QString &moduleID) = 0; virtual bool addPart(ModelPart * newModel, bool update) = 0; virtual ModelPart * addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists) = 0; virtual bool updatePart(ModelPart * newModel) = 0; virtual bool swapEnabled() = 0; virtual QString partTitle(const QString & moduleID) = 0; virtual void recordProperty(const QString &name, const QString &value) = 0; virtual QString retrieveModuleIdWith(const QString &family, const QString &propertyName, bool closestMatch) = 0; virtual QString retrieveModuleId(const QString &family, const QMultiHash &properties, const QString &propertyName, bool closestMatch) = 0; virtual QStringList propValues(const QString &family, const QString &propName, bool distinct) = 0; virtual QMultiHash allPropValues(const QString &family, const QString &propName) = 0; virtual bool lastWasExactMatch() = 0; }; #endif /* REFERENCEMODEL_H_ */ fritzing-app-0.9.2b/src/referencemodel/sqlitereferencemodel.cpp000066400000000000000000001304511250202676700247640ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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.floadfrom You should have received a copy of the GNU General Public License along with Fritzing. If not, see . ******************************************************************** $Revision: 6956 $: $Author: irascibl@gmail.com $: $Date: 2013-04-07 12:14:50 +0200 (So, 07. Apr 2013) $ ********************************************************************/ // copying a table from one SQWL database to another http://sqlite.phxsoftware.com/forums/t/285.aspx #include #include #include #include #include #include #include "sqlitereferencemodel.h" #include "../debugdialog.h" #include "../connectors/svgidlayer.h" #include "../connectors/connector.h" #include "../connectors/connectorshared.h" #include "../connectors/busshared.h" #include "../utils/folderutils.h" #include "../utils/fmessagebox.h" #define MAX_CONN_TRIES 3 static const qulonglong NO_ID = std::numeric_limits::max(); void debugError(bool result, QSqlQuery & query) { if (result) return; QSqlError error = query.lastError(); DebugDialog::debug(QString("%1 %2 %3").arg(error.text()).arg(error.number()).arg(error.type())); } static ModelPart * DebugModelPart = NULL; void debugExec(const QString & msg, QSqlQuery & query) { DebugDialog::debug( "SQLITE: " + msg + "\n" "\t "+ query.lastQuery() + "\n" "\t ERROR DRIVER: "+ query.lastError().driverText() + "\n" "\t ERROR DB: " + query.lastError().databaseText() + "\n" "\t moduleid:" + (DebugModelPart == NULL ? "" : DebugModelPart->moduleID()) + "" ); QMap map = query.boundValues(); foreach (QString name, map.keys()) { DebugDialog::debug(QString("\t%1:%2").arg(name).arg(map.value(name).toString())); } } void killConnectors(QVector & connectors) { foreach (Connector * connector, connectors) { delete connector->connectorShared(); delete connector; } connectors.clear(); } void killBuses(QVector & buses) { foreach (BusShared * bus, buses) { delete bus; } buses.clear(); } QStringList FailurePartMessages; QStringList FailurePropertyMessages; void noSwappingMessage() { FMessageBox::warning(NULL, QObject::tr("Oops!"), QObject::tr("Sorry, we have a problem with the swapping mechanism.\nFritzing still works, but you won't be able to change parts properties."), QMessageBox::Ok); } /////////////////////////////////////////////////// SqliteReferenceModel::SqliteReferenceModel() { m_swappingEnabled = false; m_lastWasExactMatch = true; } bool SqliteReferenceModel::loadAll(const QString & databaseName, bool fullLoad, bool dbExists) { FailurePartMessages.clear(); FailurePropertyMessages.clear(); m_fullLoad = fullLoad; initParts(dbExists); int tries = 0; m_keepGoing = true; while(!m_swappingEnabled && tries < MAX_CONN_TRIES && m_keepGoing) { createConnection(databaseName, fullLoad); if(!m_swappingEnabled) { deleteConnection(); } tries++; } /* TODO Mariano: perhaps we should check that there are no parts with * the same family and providing exactly the same properties set */ if (!m_swappingEnabled) { noSwappingMessage(); } else if (FailurePartMessages.count() > 0) { QString message = tr("The swapping mechanism is disabled for:\n\n"); if (FailurePartMessages.count() == 1) { message += FailurePartMessages.at(0); } else if (FailurePartMessages.count() < 6) { message += FailurePartMessages.join("\n"); } else { for (int i = 0; i < 4; i++) { message += FailurePartMessages.at(i); message += ("\n"); } message += "\n" + tr("and %1 other parts").arg(FailurePartMessages.count() - 4); } FMessageBox::warning(NULL, QObject::tr("Oops!"), message, QMessageBox::Ok); } else if (FailurePropertyMessages.count() > 0) { QString message = tr("The swapping mechanism is disabled for:\n\n"); if (FailurePropertyMessages.count() == 1) { message += FailurePropertyMessages.at(0); } else if (FailurePropertyMessages.count() < 6) { message += FailurePropertyMessages.join("\n"); } else { for (int i = 0; i < 4; i++) { message += FailurePropertyMessages.at(i); message += ("\n"); } message += "\n" + tr("and %1 other properties").arg(FailurePropertyMessages.count() - 4); } FMessageBox::warning(NULL, QObject::tr("Oops!"), message, QMessageBox::Ok); } return m_swappingEnabled; } bool SqliteReferenceModel::loadFromDB(const QString & databaseName) { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "temporary"); db.setDatabaseName(databaseName); m_swappingEnabled = loadFromDB(m_database, db); if (db.isOpen()) db.close(); if (!m_swappingEnabled) { killParts(); noSwappingMessage(); } return m_swappingEnabled; } bool SqliteReferenceModel::loadFromDB(QSqlDatabase & keep_db, QSqlDatabase & db) { bool opened = false; for (int i = 0; i < MAX_CONN_TRIES; i++) { if (!db.open()) continue; opened = true; break; } if (!opened) { return false; } QSqlQuery query = db.exec("SELECT COUNT(*) FROM parts"); debugError(query.isActive(), query); if (!query.isActive() || !query.next()) return false; int count = query.value(0).toInt(); if (count == 0) { return false; } DebugDialog::debug(QString("parts count %1").arg(count)); QVector parts(count + 1, NULL); QVector oldToNew(count + 1, 0); query = db.exec("SELECT path, moduleID, id, family, version, replacedby, fritzingversion, author, title, label, date, description, spice, spicemodel, taxonomy, itemtype FROM parts"); debugError(query.isActive(), query); if (!query.isActive()) return false; QSqlQuery q2(keep_db); bool result = q2.prepare("INSERT INTO parts(moduleID, family, core) VALUES (:moduleID, :family, :core)"); debugError(result, q2); QFileInfo info(db.databaseName()); QDir partsDir = info.absoluteDir(); // parts folder while (query.next()) { int ix = 0; QString path = query.value(ix++).toString(); QString moduleID = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); if (m_partHash.value(moduleID, NULL) != NULL) { // a part with this moduleID was already loaded--the file version overrides the db version continue; } if (!path.startsWith(ResourcePath)) { // not the resources path path = partsDir.absoluteFilePath(path); if (QFileInfo(path).exists()) { // assume this is a later version of the fzp so load it later via xml CoreList << moduleID; continue; } path.replace("/parts/", "/pdb/"); } ModelPart * modelPart = new ModelPart(); ModelPartShared * modelPartShared = new ModelPartShared(); modelPart->setModelPartShared(modelPartShared); modelPartShared->setModuleID(moduleID); modelPartShared->setDBID(dbid); QString family = query.value(ix++).toString(); modelPartShared->setFamily(family); modelPartShared->setVersion(query.value(ix++).toString()); modelPartShared->setReplacedby(query.value(ix++).toString()); modelPartShared->setFritzingVersion(query.value(ix++).toString()); modelPartShared->setAuthor(query.value(ix++).toString()); modelPartShared->setTitle(query.value(ix++).toString()); modelPartShared->setLabel(query.value(ix++).toString()); modelPartShared->setDate(query.value(ix++).toString()); modelPartShared->setDescription(query.value(ix++).toString()); modelPartShared->setSpice(query.value(ix++).toString()); modelPartShared->setSpiceModel(query.value(ix++).toString()); modelPartShared->setTaxonomy(query.value(ix++).toString()); modelPart->setItemType((ModelPart::ItemType) query.value(ix++).toInt()); modelPartShared->setPath(path); modelPart->setCore(true); modelPartShared->setConnectorsInitialized(true); m_partHash.insert(modelPartShared->moduleID(), modelPart); parts[dbid] = modelPart; q2.bindValue(":moduleID", modelPartShared->moduleID()); q2.bindValue(":family", family); q2.bindValue(":core", "1"); bool result = q2.exec(); if (!result) debugExec("unable to add part to memory", q2); qulonglong newid = q2.lastInsertId().toULongLong(); oldToNew[dbid] = newid; } query = db.exec("SELECT viewid, image, layers, sticky, flipvertical, fliphorizontal, part_id FROM viewimages"); debugError(query.isActive(), query); if (!query.isActive()) return false; while (query.next()) { int ix = 0; ViewImage * viewImage = new ViewImage(ViewLayer::BreadboardView); viewImage->viewID = (ViewLayer::ViewID) query.value(ix++).toInt(); viewImage->image = query.value(ix++).toString(); viewImage->layers = query.value(ix++).toULongLong(); viewImage->sticky = query.value(ix++).toULongLong(); viewImage->canFlipVertical = query.value(ix++).toInt() == 0 ? false : true; viewImage->canFlipHorizontal = query.value(ix++).toInt() == 0 ? false : true; qulonglong dbid = query.value(ix++).toULongLong(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { parts.at(dbid)->setViewImage(viewImage); } } query = db.exec("SELECT tag, part_id FROM tags"); debugError(query.isActive(), query); if (!query.isActive()) return false; while (query.next()) { int ix = 0; QString tag = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { parts.at(dbid)->setTag(tag); } } query = db.exec("SELECT name, value, part_id, show_in_label FROM properties"); debugError(query.isActive(), query); if (!query.isActive()) return false; QSqlQuery q3(keep_db); result = q3.prepare("INSERT INTO properties(name, value, part_id, show_in_label) VALUES (:name, :value, :part_id, :show_in_label)"); debugError(result, q3); while (query.next()) { int ix = 0; QString name = query.value(ix++).toString(); QString value = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); int showInLabel = query.value(ix++).toInt(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { parts.at(dbid)->setProperty(name, value, showInLabel); q3.bindValue(":name", name.toLower().trimmed()); q3.bindValue(":value", value); q3.bindValue(":part_id", oldToNew[dbid]); q3.bindValue(":show_in_label", showInLabel); bool result = q3.exec(); if (!result) debugExec("unable to add property to memory", q3); } } query = db.exec("SELECT COUNT(*) FROM connectors"); debugError(query.isActive(), query); if (!query.isActive() || !query.next()) return false; int connectorCount = query.value(0).toInt(); if (connectorCount == 0) return false; QVector connectors(connectorCount + 1, NULL); query = db.exec("SELECT id, connectorid, type, name, description, replacedby, part_id FROM connectors"); debugError(query.isActive(), query); if (!query.isActive()) { killConnectors(connectors); return false; } while (query.next()) { int ix = 0; qulonglong cid = query.value(ix++).toULongLong(); QString connectorid = query.value(ix++).toString(); Connector::ConnectorType type = (Connector::ConnectorType) query.value(ix++).toInt(); QString name = query.value(ix++).toString(); QString description = query.value(ix++).toString(); QString replacedby = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { ConnectorShared * connectorShared = new ConnectorShared(); connectorShared->setConnectorType(type); connectorShared->setDescription(description); connectorShared->setReplacedby(replacedby); connectorShared->setSharedName(name); connectorShared->setId(connectorid); Connector * connector = new Connector(connectorShared, modelPart); modelPart->addConnector(connector); connectors[cid] = connector; } } query = db.exec("SELECT view, layer, svgid, hybrid, terminalid, legid, connector_id FROM connectorlayers"); debugError(query.isActive(), query); if (!query.isActive()) { killConnectors(connectors); return false; } while (query.next()) { int ix = 0; ViewLayer::ViewID viewID = (ViewLayer::ViewID) query.value(ix++).toInt(); ViewLayer::ViewLayerID viewLayerID = (ViewLayer::ViewLayerID) query.value(ix++).toInt(); QString svgID = query.value(ix++).toString(); bool hybrid = query.value(ix++).toInt() == 0 ? false : true; QString terminalID = query.value(ix++).toString(); QString legID = query.value(ix++).toString(); qulonglong cid = query.value(ix++).toULongLong(); Connector * connector = connectors.at(cid); if (connector) { connectors[cid]->addPin(viewID, svgID, viewLayerID, terminalID, legID, hybrid); } } query = db.exec("SELECT COUNT(*) FROM buses"); debugError(query.isActive(), query); if (!query.isActive() || !query.next()) return false; int busCount = query.value(0).toInt(); if (busCount == 0) return false; QVector buses(busCount + 1, NULL); QHash busids; query = db.exec("SELECT id, name, part_id FROM buses"); debugError(query.isActive(), query); if (!query.isActive()) { killConnectors(connectors); killBuses(buses); return false; } while (query.next()) { int ix = 0; qulonglong bid = query.value(ix++).toULongLong(); QString name = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { BusShared * busShared = new BusShared(name); ModelPart * modelPart = parts.at(dbid); modelPart->modelPartShared()->insertBus(busShared); buses[bid] = busShared; busids.insert(busShared, dbid); } } query = db.exec("SELECT connectorid, bus_id FROM busmembers"); debugError(query.isActive(), query); if (!query.isActive()) { killConnectors(connectors); killBuses(buses); return false; } while (query.next()) { int ix = 0; QString connectorid = query.value(ix++).toString(); qulonglong bid = query.value(ix++).toULongLong(); BusShared * busShared = buses[bid]; if (busShared) { qulonglong dbid = busids.value(busShared); ModelPart * modelPart = parts.at(dbid); if (modelPart) { ConnectorShared * connectorShared = modelPart->modelPartShared()->getConnectorShared(connectorid); busShared->addConnectorShared(connectorShared); } } } query = db.exec("SELECT subpart_id, part_id FROM schematic_subparts"); debugError(query.isActive(), query); if (query.isActive()) { while (query.next()) { int ix = 0; QString subpartID = query.value(ix++).toString(); qulonglong dbid = query.value(ix++).toULongLong(); ModelPart * modelPart = parts.at(dbid); if (modelPart) { QString subModuleID = modelPart->moduleID() + "_" + subpartID; ModelPart * subModelPart = m_partHash.value(subModuleID); if (subModelPart) { subModelPart->setSubpartID(subpartID); modelPart->modelPartShared()->addSubpart(subModelPart->modelPartShared()); } } } } if (m_root == NULL) { m_root = new ModelPart(); } foreach (ModelPart * modelPart, m_partHash.values()) { if (modelPart->dbid() != 0) { // initConnectors is not redundant here // there may be parts in m_partHash loaded from a file rather from the database // modelPart->initConnectors(); modelPart->flipSMDAnd(); modelPart->initBuses(); modelPart->setParent(m_root); modelPart->lookForZeroConnector(); } } return true; } SqliteReferenceModel::~SqliteReferenceModel() { deleteConnection(); } void SqliteReferenceModel::initParts(bool dbExists) { m_init = true; PaletteModel::initParts(dbExists); m_init = false; } bool SqliteReferenceModel::createConnection(const QString & databaseName, bool fullLoad) { m_swappingEnabled = true; m_database = QSqlDatabase::addDatabase("QSQLITE"); m_database.setDatabaseName(databaseName.isEmpty() ? ":memory:" : databaseName); if (!m_database.open()) { m_swappingEnabled = false; } else { m_keepGoing = false; bool gotTransaction = m_database.transaction(); DebugDialog::debug(gotTransaction ? "got transaction" : "no transaction"); bool result = createParts(m_database, fullLoad); QSqlQuery query; result = query.exec("CREATE TABLE viewimages (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "viewid INTEGER NOT NULL,\n" // ViewLayer::ViewID "image TEXT NOT NULL,\n" "layers INTEGER NOT NULL,\n" // bit flag (max 8 bytes = 64 layers) "sticky INTEGER NOT NULL,\n" // bit flag (max 8 bytes = 64 layers) "flipvertical INTEGER NOT NULL,\n" // boolean "fliphorizontal INTEGER NOT NULL,\n" // boolean "part_id INTEGER NOT NULL" ")"); debugError(result, query); result = query.exec("CREATE TABLE connectors (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "connectorid TEXT NOT NULL,\n" "type INTEGER NOT NULL,\n" "name TEXT NOT NULL,\n" "description TEXT,\n" "replacedby TEXT,\n" "part_id INTEGER NOT NULL" ")"); debugError(result, query); result = query.exec("CREATE TABLE connectorlayers (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "view INTEGER NOT NULL,\n" // ViewLayer::ViewID "layer INTEGER NOT NULL,\n" // ViewLayer::ViewLayerID "svgid TEXT NOT NULL,\n" "hybrid INTEGER NOT NULL,\n" "terminalid TEXT,\n" "legid TEXT,\n" "connector_id INTEGER NOT NULL" ")"); debugError(result, query); result = query.exec("CREATE TABLE buses (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "name TEXT NOT NULL,\n" "part_id INTEGER NOT NULL" ")"); debugError(result, query); result = query.exec("CREATE TABLE busmembers (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "connectorid TEXT NOT NULL,\n" "bus_id INTEGER NOT NULL" ")"); debugError(result, query); result = query.exec("CREATE TABLE schematic_subparts (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "label TEXT NOT NULL,\n" "subpart_id TEXT NOT NULL,\n" "part_id INTEGER NOT NULL" ")"); debugError(result, query); // TODO: create a dictionary table so redundant tags, property names, and property values aren't stored multiple times result = query.exec("CREATE TABLE tags (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,\n" "tag TEXT NOT NULL,\n" "part_id INTEGER NOT NULL" ")"); debugError(result, query); result = createProperties(m_database); result = query.exec("CREATE TRIGGER unique_part__moduleID \n" "BEFORE INSERT ON parts \n" "FOR EACH ROW BEGIN \n" "SELECT RAISE(ROLLBACK, 'insert on table \"parts\" violates unique constraint \"unique_part__moduleID\"') \n" "WHERE (SELECT count(*) FROM parts WHERE moduleID = NEW.moduleID) > 0; \n" "END; " ); debugError(result, query); if (fullLoad) { foreach(ModelPart* mp, m_partHash.values()) { mp->initConnectors(false); } } foreach(ModelPart* mp, m_partHash.values()) { addPartAux(mp, fullLoad); } createIndexes(); createMoreIndexes(m_database); m_database.commit(); } return m_swappingEnabled; } void SqliteReferenceModel::deleteConnection() { QSqlDatabase::removeDatabase("SQLITE"); } ModelPart *SqliteReferenceModel::loadPart(const QString & path, bool update) { ModelPart *modelPart = PaletteModel::loadPart(path, update); if (modelPart == NULL) return modelPart; if (!m_init) addPart(modelPart, update); return modelPart; } ModelPart *SqliteReferenceModel::retrieveModelPart(const QString &moduleID) { if (moduleID.isEmpty()) { return NULL; } return m_partHash.value(moduleID, NULL); } QString SqliteReferenceModel::retrieveModuleIdWith(const QString &family, const QString &propertyName, bool closestMatch) { QString moduleID = retrieveModuleId(family,m_recordedProperties,propertyName, closestMatch); m_recordedProperties.clear(); return moduleID; } QString SqliteReferenceModel::retrieveModuleId(const QString &family, const QMultiHash &properties, const QString &propertyName, bool closestMatch) { QString propertyValue; if(properties.size() > 0) { QString queryStr = "SELECT moduleID FROM parts part \n" "WHERE part.family = :family AND (1=1 "; QHash params; int ix = 0; foreach (QString name, properties.uniqueKeys()) { foreach (QString value, properties.values(name)) { QString propParam = QString(":prop%1").arg(ix++); queryStr += QString(" AND EXISTS (SELECT * FROM properties prop WHERE prop.part_id = part.id AND prop.name = %1_name AND prop.value = %1_value)").arg(propParam); params[propParam+"_name"] = name; params[propParam+"_value"] = value; if(name == propertyName) { propertyValue = value; } } } queryStr += ") order by part.core desc"; QSqlQuery query; query.prepare(queryStr); query.bindValue(":family",family.toLower().trimmed()); foreach(QString name, params.uniqueKeys()) { query.bindValue(name,params[name].toLower().trimmed()); } QString moduleId; if(query.exec()) { if(query.next()) { moduleId = query.value(0).toString(); //grab the first } //DebugDialog::debug("SQLITE: found: "+moduleId); } else { debugExec("couldn't retrieve part", query); } if(!moduleId.isEmpty()) { m_lastWasExactMatch = true; return moduleId; } else if(closestMatch || !propertyName.isEmpty()) { m_lastWasExactMatch = false; return closestMatchId(family, properties, propertyName, propertyValue); } else { return ___emptyString___; } } else { return ___emptyString___; } } QString SqliteReferenceModel::closestMatchId(const QString &family, const QMultiHash &properties, const QString &propertyName, const QString &propertyValue) { QStringList possibleMatches = getPossibleMatches(family, properties, propertyName, propertyValue); return getClosestMatch(family, properties, possibleMatches); } QStringList SqliteReferenceModel::getPossibleMatches(const QString &family, const QMultiHash &properties, const QString &propertyName, const QString &propertyValue) { Q_UNUSED(properties); QStringList result; QString queryStr = "SELECT moduleID FROM parts part \n" "WHERE part.family = :family AND EXISTS ( \n" "SELECT * FROM properties prop \n" "WHERE prop.part_id = part.id %1 \n" ") "; queryStr = queryStr.arg((propertyName.isEmpty()) ? "" : "AND prop.name = :prop_name AND prop.value = :prop_value "); QSqlQuery query; query.prepare(queryStr); query.bindValue(":family", family.toLower().trimmed()); if (!propertyName.isEmpty()) { query.bindValue(":prop_name", propertyName.toLower().trimmed()); query.bindValue(":prop_value", propertyValue); } if(query.exec()) { while(query.next()) { result << query.value(0).toString(); } //DebugDialog::debug(QString("SQLITE: %1 possible matches found").arg(result.size())); } else { debugExec("couldn't get possible match", query); } return result; } QString SqliteReferenceModel::getClosestMatch(const QString &family, const QMultiHash &properties, QStringList possibleMatches) { int propsInCommonCount = 0; int propsInCommonCountAux = 0; QString result; foreach(QString modId, possibleMatches) { propsInCommonCountAux = countPropsInCommon(family, properties, retrieveModelPart(modId)); if(propsInCommonCountAux > propsInCommonCount) { result = modId; propsInCommonCount = propsInCommonCountAux; } } return result; } int SqliteReferenceModel::countPropsInCommon(const QString &family, const QMultiHash &properties, const ModelPart *part2) { Q_UNUSED(family) if (part2 == NULL) { DebugDialog::debug("countPropsInCommon failure"); return 0; } int result = 0; QMultiHash props2 = part2->properties(); foreach(QString prop, properties.uniqueKeys()) { QStringList values1 = properties.values(prop); QStringList values2 = props2.values(prop); foreach (QString value1, values1) { if (values2.contains(value1)) { result++; } } } return result; } bool SqliteReferenceModel::lastWasExactMatch() { return m_lastWasExactMatch; } bool SqliteReferenceModel::addPartAux(ModelPart * newModel, bool fullLoad) { try { bool result = insertPart(newModel, fullLoad); return result; } catch (const char * msg) { DebugDialog::debug(msg); } catch (const QString & msg) { DebugDialog::debug(msg); } catch (...) { DebugDialog::debug("SqliteReferenceModel::addPartAux failure"); } return false; } bool SqliteReferenceModel::addPart(ModelPart * newModel, bool update) { bool result; if(update && containsModelPart(newModel->moduleID())) { result = updatePart(newModel); } else { result = addPartAux(newModel, false); } return result; } ModelPart * SqliteReferenceModel::addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists) { return PaletteModel::addPart(newPartPath, addToReference, updateIdAlreadyExists); } ModelPart * SqliteReferenceModel::reloadPart(const QString & path, const QString & moduleID) { m_partHash.remove(moduleID); ModelPart *modelPart = PaletteModel::loadPart(path, false); if (modelPart == NULL) return modelPart; updatePart(modelPart); return modelPart; } bool SqliteReferenceModel::updatePart(ModelPart * newModel) { if(m_swappingEnabled) { qulonglong partId = this->partId(newModel->moduleID()); if(partId != NO_ID) { removePart(partId); removeProperties(partId); return addPartAux(newModel, false); } else { return false; } } else { return false; } } bool SqliteReferenceModel::insertPart(ModelPart * modelPart, bool fullLoad) { DebugModelPart = modelPart; QHash properties = modelPart->properties(); QSqlQuery query; QString fields; QString values; if (fullLoad) { fields = " version, replacedby, fritzingversion, author, title, label, date, description, spice, spicemodel, taxonomy, itemtype, path"; values = " :version, :replacedby, :fritzingversion, :author, :title, :label, :date, :description, :spice, :spicemodel, :taxonomy, :itemtype, :path"; } else { fields = " core"; values = " :core"; } query.prepare(QString("INSERT INTO parts(moduleID, family, %1) VALUES (:moduleID, :family, %2)").arg(fields).arg(values)); query.bindValue(":moduleID", modelPart->moduleID()); query.bindValue(":family", properties.value("family").toLower().trimmed()); if (fullLoad) { QString path = modelPart->path(); QString prefix = FolderUtils::getApplicationSubFolderPath("parts"); if (path.startsWith(ResourcePath)) { } else if (path.startsWith(prefix)) { // copy the fzp away so it's not consulted at normal load time QString newPath = path; newPath.replace("/parts/", "/pdb/"); QFile::remove(newPath); QFile::rename(path, newPath); path = path.mid(prefix.count() + 1); // + 1 to remove the beginning "/" } else { bool bail = true; if (modelPart->itemType() == ModelPart::SchematicSubpart) { ModelPartShared * mps = modelPart->modelPartShared(); if (mps && mps->superpart() && mps->superpart()->path().startsWith(prefix)) { bail = false; } } if (bail) { DebugDialog::debug(QString("part path not in parts:%1").arg(path)); return true; } } query.bindValue(":version", modelPart->version()); query.bindValue(":replacedby", modelPart->replacedby()); query.bindValue(":fritzingversion", modelPart->fritzingVersion()); query.bindValue(":author", modelPart->author()); query.bindValue(":title", modelPart->title()); query.bindValue(":label", modelPart->label()); query.bindValue(":date", modelPart->date()); query.bindValue(":description", modelPart->description()); query.bindValue(":spice", modelPart->spice()); query.bindValue(":spicemodel", modelPart->spiceModel()); query.bindValue(":taxonomy", modelPart->taxonomy()); query.bindValue(":itemtype", (int) modelPart->itemType()); query.bindValue(":path", path); } else { query.bindValue(":core", modelPart->isCore() ? "1" : "0"); } if (query.exec()) { qulonglong id = query.lastInsertId().toULongLong(); modelPart->setDBID(id); foreach (QString prop, properties.keys()) { if (prop == "family") continue; bool result = insertProperty(prop, properties.value(prop), id, modelPart->showInLabel(prop)); if (fullLoad && !result) { m_swappingEnabled = false; } if (!result) { FailurePropertyMessages << tr("property '%1' in part '%2' with id '%3'.") .arg(prop).arg(modelPart->path()).arg(modelPart->moduleID()); } } if (fullLoad) { foreach (QString tag, modelPart->tags()) { insertTag(tag, id); } foreach (ViewImage * viewImage, modelPart->viewImages()) { insertViewImage(viewImage, id); } foreach (Connector * connector, modelPart->connectors().values()) { insertConnector(connector, id); } foreach (Bus * bus, modelPart->buses().values()) { insertBus(bus, id); } ModelPartShared * mps = modelPart->modelPartShared(); if (mps) { foreach (ModelPartShared * sub, mps->subparts()) { insertSubpart(sub, id); } } } } else { debugExec("couldn't insert part", query); FailurePartMessages << tr("part '%1' with id '%2'; possibly because it has no 'family' property.") .arg(modelPart->path()).arg(modelPart->moduleID()); } DebugModelPart = NULL; return true; } bool SqliteReferenceModel::insertProperty(const QString & name, const QString & value, qulonglong id, bool showInLabel) { QSqlQuery query; query.prepare("INSERT INTO properties(name, value, part_id, show_in_label) VALUES (:name, :value, :part_id, :show_in_label)"); query.bindValue(":name", name.toLower().trimmed()); query.bindValue(":value", value); query.bindValue(":part_id", id); query.bindValue(":show_in_label", showInLabel ? 1 : 0); if(!query.exec()) { debugExec("couldn't insert property", query); return false; } else { // qulonglong id = query.lastInsertId().toULongLong(); } return true; } bool SqliteReferenceModel::insertTag(const QString & tag, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO tags(tag, part_id) VALUES (:tag, :part_id)"); query.bindValue(":tag", tag.toLower().trimmed()); query.bindValue(":part_id", id); if(!query.exec()) { debugExec("couldn't insert tag", query); m_swappingEnabled = false; } else { // qulonglong id = query.lastInsertId().toULongLong(); } return true; } bool SqliteReferenceModel::insertViewImage(const ViewImage * viewImage, qulonglong id) { if (viewImage->image.isEmpty() && viewImage->layers == 0) return true; QSqlQuery query; query.prepare("INSERT INTO viewimages(viewid, image, layers, sticky, flipvertical, fliphorizontal, part_id) " "VALUES (:viewid, :image, :layers, :sticky, :flipvertical, :fliphorizontal, :part_id)"); query.bindValue(":viewid", viewImage->viewID); query.bindValue(":image", viewImage->image); query.bindValue(":layers", viewImage->layers); query.bindValue(":sticky", viewImage->sticky); query.bindValue(":flipvertical", viewImage->canFlipVertical ? 1 : 0); query.bindValue(":fliphorizontal", viewImage->canFlipHorizontal ? 1 : 0); query.bindValue(":part_id", id); if(!query.exec()) { debugExec("couldn't insert viewimage", query); m_swappingEnabled = false; } else { // qulonglong id = query.lastInsertId().toULongLong(); } return true; } bool SqliteReferenceModel::insertBus(const Bus * bus, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO buses(name, part_id) VALUES (:name, :part_id)"); query.bindValue(":name", bus->id()); query.bindValue(":part_id", id); if(!query.exec()) { debugExec("couldn't insert bus", query); m_swappingEnabled = false; } else { qulonglong bid = query.lastInsertId().toULongLong(); foreach (Connector * connector, bus->connectors()) { insertBusMember(connector, bid); } } return true; } bool SqliteReferenceModel::insertBusMember(const Connector * connector, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO busmembers(connectorid, bus_id) VALUES (:connectorid, :bus_id)"); query.bindValue(":connectorid", connector->connectorSharedID()); query.bindValue(":bus_id", id); if(!query.exec()) { debugExec("couldn't insert busmember", query); m_swappingEnabled = false; } else { //qulonglong id = query.lastInsertId().toULongLong(); } return true; } bool SqliteReferenceModel::insertConnector(const Connector * connector, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO connectors(connectorid, type, name, description, replacedby, part_id) VALUES (:connectorid, :type, :name, :description, :replacedby, :part_id)"); query.bindValue(":connectorid", connector->connectorSharedID()); query.bindValue(":type", (int) connector->connectorType()); query.bindValue(":name", connector->connectorSharedName()); query.bindValue(":description", connector->connectorSharedDescription()); query.bindValue(":replacedby", connector->connectorSharedReplacedby()); query.bindValue(":part_id", id); if(!query.exec()) { debugExec("couldn't insert connector", query); m_swappingEnabled = false; } else { qulonglong id = query.lastInsertId().toULongLong(); foreach (SvgIdLayer * layer, connector->svgIdLayers()) { insertConnectorLayer(layer, id); } } return true; } bool SqliteReferenceModel::insertConnectorLayer(const SvgIdLayer * svgIdLayer, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO connectorLayers(view, layer, svgid, hybrid, terminalid, legid, connector_id) VALUES " "(:view, :layer, :svgid, :hybrid, :terminalid, :legid, :connector_id)"); query.bindValue(":view", svgIdLayer->m_viewID); query.bindValue(":layer", svgIdLayer->m_svgViewLayerID); query.bindValue(":svgid", svgIdLayer->m_svgId); query.bindValue(":hybrid", svgIdLayer->m_hybrid ? 1 : 0); query.bindValue(":terminalid", svgIdLayer->m_terminalId); query.bindValue(":legid", svgIdLayer->m_legId); query.bindValue(":connector_id", id); if(!query.exec()) { debugExec("couldn't insert viewimage", query); m_swappingEnabled = false; } else { // qulonglong id = query.lastInsertId().toULongLong(); } return true; } QStringList SqliteReferenceModel::propValues(const QString &family, const QString &propName, bool distinct) { QStringList retval; QSqlQuery query; query.prepare(QString( "SELECT %1 prop.value FROM properties prop JOIN parts PART ON part.id = prop.part_id \n" "WHERE part.family = :family AND prop.name = :propName ORDER BY prop.value \n" ).arg(distinct ? " DISTINCT ":"") ); query.bindValue(":family",family.toLower().trimmed()); query.bindValue(":propName",propName.toLower().trimmed()); if(query.exec()) { while(query.next()) { QString value = query.value(0).toString(); if (!value.isEmpty()) retval << value; } } else { debugExec("couldn't retrieve values", query); m_swappingEnabled = false; } return retval; } QMultiHash SqliteReferenceModel::allPropValues(const QString &family, const QString &propName) { QMultiHash retval; QSqlQuery query; query.prepare(QString( "SELECT value, moduleID FROM properties prop JOIN parts part ON part.id = prop.part_id \n" "WHERE part.family = :family AND prop.name = :propName\n" ) ); query.bindValue(":family",family.toLower().trimmed()); query.bindValue(":propName",propName.toLower().trimmed()); if(query.exec()) { while(query.next()) { //QSqlRecord record = query.record(); //for (int i = 0; i < record.count(); i++) { // DebugDialog::debug("result " + record.fieldName(i) + " " + record.value(i).toString()); //} QString prop = query.value(0).toString(); if (!prop.isEmpty()) retval.insert(prop, query.value(1).toString()); } } else { debugExec("couldn't retrieve values", query); m_swappingEnabled = false; } return retval; } void SqliteReferenceModel::recordProperty(const QString &name, const QString &value) { DebugDialog::debug(QString("RECORDING PROPERTY %1:%2").arg(name).arg(value)); m_recordedProperties.insert(name,value); } bool SqliteReferenceModel::swapEnabled() { return m_swappingEnabled; } bool SqliteReferenceModel::containsModelPart(const QString & moduleID) { return partId(moduleID) != NO_ID; } qulonglong SqliteReferenceModel::partId(QString moduleID) { qulonglong partId = NO_ID; QSqlQuery query; query.prepare( "SELECT id FROM parts \n" "WHERE moduleID = :moduleID " ); query.bindValue(":moduleID",moduleID); if(query.exec()) { //DebugDialog::debug("SQLITE: retrieving id: "+moduleID); if(query.next()) { partId = query.value(0).toULongLong(); //grab the first } //DebugDialog::debug(QString("SQLITE: found: %1").arg(partId)); } else { debugExec("couldn't retrieve part", query); } return partId; } bool SqliteReferenceModel::removePart(qulonglong partId) { bool result = true; QSqlQuery query; query.prepare( "DELETE FROM parts \n" "WHERE id = :id " ); query.bindValue(":id",partId); if(query.exec()) { result = true; } else { DebugDialog::debug( "SQLITE: couldn't delete part\n" "\t "+query.lastQuery()+"\n" "\t ERROR DRIVER: "+query.lastError().driverText()+"\n" "\t ERROR DB: "+query.lastError().databaseText()+"\n" ); result = false; } return result; } bool SqliteReferenceModel::removeProperties(qulonglong partId) { bool result = true; QSqlQuery query; query.prepare( "DELETE FROM properties \n" "WHERE part_id = :id " ); query.bindValue(":id",partId); if(query.exec()) { result = true; } else { DebugDialog::debug( "SQLITE: couldn't delete properties \n" "\t "+query.lastQuery()+"\n" "\t ERROR DRIVER: "+query.lastError().driverText()+"\n" "\t ERROR DB: "+query.lastError().databaseText()+"\n" ); result = false; } return result; } QString SqliteReferenceModel::partTitle(const QString & moduleID) { ModelPart *mp = retrieveModelPart(moduleID); if(mp) { return mp->modelPartShared()->title(); } else { return ___emptyString___; } } void SqliteReferenceModel::killParts() { foreach (ModelPart * modelPart, m_partHash.values()) { delete modelPart; } m_partHash.clear(); } bool SqliteReferenceModel::createProperties(QSqlDatabase & db) { QSqlQuery query = db.exec("CREATE TABLE properties (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,\n" "name TEXT NOT NULL,\n" "value TEXT NOT NULL,\n" "show_in_label INTEGER NOT NULL,\n" "part_id INTEGER NOT NULL" ")"); debugError(query.isActive(), query); return query.isActive(); } bool SqliteReferenceModel::createParts(QSqlDatabase & db, bool fullLoad) { QString extra; if (fullLoad) { extra = "version TEXT,\n" "replacedby TEXT,\n" "fritzingversion TEXT,\n" "author TEXT,\n" "title TEXT,\n" "label TEXT,\n" "date TEXT,\n" "description TEXT,\n" "spice TEXT,\n" "spicemodel TEXT,\n" "taxonomy TEXT,\n" "itemtype INTEGER NOT NULL,\n" "path TEXT\n" ; } else { extra = "core TEXT NOT NULL\n" ; } QString string = QString("CREATE TABLE parts (\n" "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "moduleID TEXT NOT NULL,\n" "family TEXT NOT NULL,\n" "%1" ")") .arg(extra); QSqlQuery query = db.exec(string); debugError(query.isActive(), query); return query.isActive(); } bool SqliteReferenceModel::insertSubpart(ModelPartShared * mps, qulonglong id) { QSqlQuery query; query.prepare("INSERT INTO schematic_subparts(label, subpart_id, part_id) VALUES (:label, :subpart_id, :part_id)"); query.bindValue(":label", mps->label()); query.bindValue(":subpart_id", mps->subpartID()); query.bindValue(":part_id", id); if(!query.exec()) { debugExec("couldn't insert bus", query); m_swappingEnabled = false; } //else { // qulonglong sid = query.lastInsertId().toULongLong(); //} return true; } void SqliteReferenceModel::createIndexes() { // supposedly faster to add these after the data is inserted QSqlQuery query; bool result = query.exec("CREATE INDEX idx_viewimage_part_id ON viewimages (part_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_connector_part_id ON connectors (part_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_connectorlayer_connector_id ON connectorlayers (connector_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_bus_part_id ON buses (part_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_busmember_bus_id ON busmembers (bus_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_schematic_subpart_part_id ON schematic_subparts (part_id ASC)"); debugError(result, query); result = query.exec("CREATE INDEX idx_tag_part_id ON tags (part_id ASC)"); debugError(result, query); } void SqliteReferenceModel::createMoreIndexes(QSqlDatabase & db) { // supposedly faster to add these after the data is inserted QSqlQuery query = db.exec("CREATE INDEX idx_property_name ON properties (name ASC)"); debugError(query.isActive(), query); query = db.exec("CREATE INDEX idx_part_id ON parts (id ASC)"); debugError(query.isActive(), query); query = db.exec("CREATE INDEX idx_part_moduleID ON parts (moduleID ASC)"); debugError(query.isActive(), query); query = db.exec("CREATE INDEX idx_part_family ON parts (family ASC)"); debugError(query.isActive(), query); } fritzing-app-0.9.2b/src/referencemodel/sqlitereferencemodel.h000066400000000000000000000110521250202676700244240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef SQLITEREFERENCEMODEL_H_ #define SQLITEREFERENCEMODEL_H_ #include #include #include #include "referencemodel.h" class SqliteReferenceModel : public ReferenceModel { Q_OBJECT public: SqliteReferenceModel(); ~SqliteReferenceModel(); bool loadAll(const QString & databaseName, bool fullLoad, bool dbExists); bool loadFromDB(const QString & databaseName); ModelPart *loadPart(const QString & path, bool update); ModelPart *reloadPart(const QString & path, const QString & moduleID); ModelPart *retrieveModelPart(const QString &moduleID); bool addPart(ModelPart * newModel, bool update); bool updatePart(ModelPart * newModel); ModelPart * addPart(QString newPartPath, bool addToReference, bool updateIdAlreadyExists); bool swapEnabled(); bool containsModelPart(const QString & moduleID); QString partTitle(const QString & moduleID); QStringList propValues(const QString &family, const QString &propName, bool distinct); QMultiHash allPropValues(const QString &family, const QString &propName); void recordProperty(const QString &name, const QString &value); QString retrieveModuleIdWith(const QString &family, const QString &propertyName, bool closestMatch); QString retrieveModuleId(const QString &family, const QMultiHash &properties, const QString &propertyName, bool closestMatch); bool lastWasExactMatch(); protected: void initParts(bool dbExists); void killParts(); protected: bool addPartAux(ModelPart * newModel, bool fullLoad); QString closestMatchId(const QString &family, const QMultiHash &properties, const QString &propertyName, const QString &propertyValue); QStringList getPossibleMatches(const QString &family, const QMultiHash &properties, const QString &propertyName, const QString &propertyValue); QString getClosestMatch(const QString &family, const QMultiHash &properties, QStringList possibleMatches); int countPropsInCommon(const QString &family, const QMultiHash &properties, const ModelPart *part2); bool createConnection(const QString & databaseName, bool fullLoad); void deleteConnection(); bool insertPart(ModelPart *, bool fullLoad); bool insertProperty(const QString & name, const QString & value, qulonglong id, bool showInLabel); bool insertTag(const QString & tag, qulonglong id); bool insertViewImage(const struct ViewImage *, qulonglong id); bool insertConnector(const class Connector *, qulonglong id); bool insertConnectorLayer(const class SvgIdLayer *, qulonglong id); // connector db id bool insertBus(const Bus *, qulonglong id); bool insertBusMember(const Connector *, qulonglong id); qulonglong partId(QString moduleID); bool removePart(qulonglong partId); bool removeProperties(qulonglong partId); bool loadFromDB(QSqlDatabase & keep_db, QSqlDatabase & db); bool createProperties(QSqlDatabase &); bool createParts(QSqlDatabase &, bool fullLoad); bool insertSubpart(ModelPartShared *, qulonglong id); bool insertSubpartConnector(const ConnectorShared * cs, qulonglong id); void createIndexes(); void createMoreIndexes(QSqlDatabase &); protected: volatile bool m_swappingEnabled; volatile bool m_lastWasExactMatch; volatile bool m_keepGoing; bool m_init; QSqlDatabase m_database; QMultiHash m_recordedProperties; }; #endif /* SQLITEREFERENCEMODEL_H_ */ fritzing-app-0.9.2b/src/routingstatus.h000066400000000000000000000031611250202676700202010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify\ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ROUTINGSTATUS_H #define ROUTINGSTATUS_H #include "items/itembase.h" struct RoutingStatus { int m_netCount; int m_netRoutedCount; int m_connectorsLeftToRoute; int m_jumperItemCount; public: void zero() { m_netCount = m_netRoutedCount = m_connectorsLeftToRoute = m_jumperItemCount = 0; } bool operator!=(const RoutingStatus &other) const { return (m_netCount != other.m_netCount) || (m_netRoutedCount != other.m_netRoutedCount) || (m_connectorsLeftToRoute != other.m_connectorsLeftToRoute) || (m_jumperItemCount != other.m_jumperItemCount); } }; #endif // ROUTINGSTATUS_H fritzing-app-0.9.2b/src/sketch/000077500000000000000000000000001250202676700163555ustar00rootroot00000000000000fritzing-app-0.9.2b/src/sketch/breadboardsketchwidget.cpp000066400000000000000000000203331250202676700235550ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #include "breadboardsketchwidget.h" #include "../debugdialog.h" #include "../items/virtualwire.h" #include "../items/resizableboard.h" #include "../connectors/connectoritem.h" #include "../items/moduleidnames.h" #include "../waitpushundostack.h" #include static const double WireHoverStrokeFactor = 4.0; BreadboardSketchWidget::BreadboardSketchWidget(ViewLayer::ViewID viewID, QWidget *parent) : SketchWidget(viewID, parent) { m_shortName = QObject::tr("bb"); m_viewName = QObject::tr("Breadboard View"); initBackgroundColor(); } void BreadboardSketchWidget::setWireVisible(Wire * wire) { bool visible = !(wire->getTrace()); wire->setVisible(visible); wire->setEverVisible(visible); //wire->setVisible(true); // for debugging } bool BreadboardSketchWidget::collectFemaleConnectees(ItemBase * itemBase, QSet & items) { return itemBase->collectFemaleConnectees(items); } bool BreadboardSketchWidget::checkUnder() { return true; }; void BreadboardSketchWidget::findConnectorsUnder(ItemBase * item) { item->findConnectorsUnder(); } void BreadboardSketchWidget::addViewLayers() { setViewLayerIDs(ViewLayer::Breadboard, ViewLayer::BreadboardWire, ViewLayer::Breadboard, ViewLayer::BreadboardRuler, ViewLayer::BreadboardNote); addViewLayersAux(ViewLayer::layersForView(ViewLayer::BreadboardView), ViewLayer::layersForViewFromBelow(ViewLayer::BreadboardView)); } bool BreadboardSketchWidget::disconnectFromFemale(ItemBase * item, QHash & savedItems, ConnectorPairHash & connectorHash, bool doCommand, bool rubberBandLegEnabled, QUndoCommand * parentCommand) { // if item is attached to a virtual wire or a female connector in breadboard view // then disconnect it // at the moment, I think this doesn't apply to other views bool result = false; foreach (ConnectorItem * fromConnectorItem, item->cachedConnectorItems()) { if (rubberBandLegEnabled && fromConnectorItem->hasRubberBandLeg()) continue; foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { if (rubberBandLegEnabled && toConnectorItem->hasRubberBandLeg()) continue; if (toConnectorItem->connectorType() == Connector::Female) { if (savedItems.keys().contains(toConnectorItem->attachedTo()->layerKinChief()->id())) { // the thing we're connected to is also moving, so don't disconnect continue; } result = true; fromConnectorItem->tempRemove(toConnectorItem, true); toConnectorItem->tempRemove(fromConnectorItem, true); if (doCommand) { extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::NewBottom, false, parentCommand); } connectorHash.insert(fromConnectorItem, toConnectorItem); } } } return result; } BaseCommand::CrossViewType BreadboardSketchWidget::wireSplitCrossView() { return BaseCommand::CrossView; } bool BreadboardSketchWidget::canDropModelPart(ModelPart * modelPart) { if (!SketchWidget::canDropModelPart(modelPart)) return false; if (Board::isBoard(modelPart)) { return matchesLayer(modelPart); } switch (modelPart->itemType()) { case ModelPart::Logo: if (modelPart->moduleID().contains("breadboard", Qt::CaseInsensitive)) return true; case ModelPart::Symbol: case ModelPart::SchematicSubpart: case ModelPart::Jumper: case ModelPart::CopperFill: case ModelPart::Hole: case ModelPart::Via: return false; default: if (modelPart->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName)) return false; if (modelPart->moduleID().endsWith(ModuleIDNames::PadModuleIDName)) return false; if (modelPart->moduleID().endsWith(ModuleIDNames::CopperBlockerModuleIDName)) return false; return true; } } void BreadboardSketchWidget::initWire(Wire * wire, int penWidth) { if (wire->getRatsnest()) { // handle elsewhere return; } wire->setPenWidth(penWidth - 2, this, (penWidth - 2) * WireHoverStrokeFactor); wire->setColorString("blue", 1.0, false); } const QString & BreadboardSketchWidget::traceColor(ViewLayer::ViewLayerPlacement) { if (!m_lastColorSelected.isEmpty()) return m_lastColorSelected; static QString color = "blue"; return color; } double BreadboardSketchWidget::getTraceWidth() { // TODO: dig this constant out of wire.svg or somewhere else... return 2.0; } void BreadboardSketchWidget::getLabelFont(QFont & font, QColor & color, ItemBase *) { font.setFamily("Droid Sans"); font.setPointSize(9); font.setBold(false); font.setItalic(false); color.setAlpha(255); color.setRgb(0); } void BreadboardSketchWidget::setNewPartVisible(ItemBase * itemBase) { switch (itemBase->itemType()) { case ModelPart::Symbol: case ModelPart::SchematicSubpart: case ModelPart::Jumper: case ModelPart::CopperFill: case ModelPart::Logo: if (itemBase->moduleID().contains("breadboard", Qt::CaseInsensitive)) return; case ModelPart::Hole: case ModelPart::Via: itemBase->setVisible(false); itemBase->setEverVisible(false); return; default: if (itemBase->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName) || itemBase->moduleID().endsWith(ModuleIDNames::PadModuleIDName) || itemBase->moduleID().endsWith(ModuleIDNames::PowerModuleIDName)) { itemBase->setVisible(false); itemBase->setEverVisible(false); return; } break; } } bool BreadboardSketchWidget::canDisconnectAll() { return false; } bool BreadboardSketchWidget::ignoreFemale() { return false; } double BreadboardSketchWidget::defaultGridSizeInches() { return 0.1; } ViewLayer::ViewLayerID BreadboardSketchWidget::getLabelViewLayerID(ItemBase *) { return ViewLayer::BreadboardLabel; } void BreadboardSketchWidget::addDefaultParts() { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); ModelPart * modelPart = referenceModel()->retrieveModelPart(ModuleIDNames::FullPlusBreadboardModuleIDName); m_addedDefaultPart = addItem(modelPart, defaultViewLayerPlacement(modelPart), BaseCommand::CrossView, viewGeometry, newID, -1, NULL); m_addDefaultParts = true; // have to put this off until later, because positioning the item doesn't work correctly until the view is visible } void BreadboardSketchWidget::showEvent(QShowEvent * event) { SketchWidget::showEvent(event); if (m_addDefaultParts && (m_addedDefaultPart != NULL)) { m_addDefaultParts = false; QSizeF partSize = m_addedDefaultPart->size(); QSizeF vpSize = this->viewport()->size(); //if (vpSize.height() < helpSize.height() + 50 + partSize.height()) { //vpSize.setWidth(vpSize.width() - verticalScrollBar()->width()); //} QPointF p; p.setX((int) ((vpSize.width() - partSize.width()) / 2.0)); p.setY((int) ((vpSize.height() - partSize.height()) / 2.0)); QPointF q = mapToScene(p.toPoint()); m_addedDefaultPart->setPos(q); alignOneToGrid(m_addedDefaultPart); QTimer::singleShot(10, this, SLOT(vScrollToZero())); } } double BreadboardSketchWidget::getWireStrokeWidth(Wire *, double wireWidth) { return wireWidth * WireHoverStrokeFactor; } void BreadboardSketchWidget::getBendpointWidths(Wire * wire, double width, double & bendpointWidth, double & bendpoint2Width, bool & negativeOffsetRect) { Q_UNUSED(wire); Q_UNUSED(width); bendpoint2Width = bendpointWidth = -1; negativeOffsetRect = true; } fritzing-app-0.9.2b/src/sketch/breadboardsketchwidget.h000066400000000000000000000044251250202676700232260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef BREADBOARDSKETCHWIDGET_H #define BREADBOARDSKETCHWIDGET_H #include "sketchwidget.h" class BreadboardSketchWidget : public SketchWidget { Q_OBJECT public: BreadboardSketchWidget(ViewLayer::ViewID, QWidget *parent=0); void addViewLayers(); void initWire(Wire *, int penWidth); bool canDisconnectAll(); bool ignoreFemale(); void addDefaultParts(); void showEvent(QShowEvent * event); double getWireStrokeWidth(Wire *, double wireWidth); void getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect); protected: void setWireVisible(Wire * wire); bool collectFemaleConnectees(ItemBase *, QSet &); void findConnectorsUnder(ItemBase * item); bool checkUnder(); bool disconnectFromFemale(ItemBase * item, QHash & savedItems, ConnectorPairHash &, bool doCommand, bool rubberBandLegEnabled, QUndoCommand * parentCommand); BaseCommand::CrossViewType wireSplitCrossView(); bool canDropModelPart(ModelPart * modelPart); void getLabelFont(QFont &, QColor &, ItemBase *); void setNewPartVisible(ItemBase *); double defaultGridSizeInches(); ViewLayer::ViewLayerID getLabelViewLayerID(ItemBase *); double getTraceWidth(); const QString & traceColor(ViewLayer::ViewLayerPlacement); }; #endif fritzing-app-0.9.2b/src/sketch/fgraphicsscene.cpp000066400000000000000000000047451250202676700220570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "fgraphicsscene.h" #include "../items/paletteitembase.h" #include "../items/wire.h" #include "../connectors/connectoritem.h" #include "../sketch/infographicsview.h" #include FGraphicsScene::FGraphicsScene( QObject * parent) : QGraphicsScene(parent) { m_displayHandles = true; //setItemIndexMethod(QGraphicsScene::NoIndex); } void FGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) { // TODO: how do we get a QTransform? QGraphicsItem * item = this->itemAt(helpEvent->scenePos(), QTransform()); if (item == NULL) return; QString text; QPoint point; ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem) { connectorItem->updateTooltip(); } } else { itemBase->updateTooltip(); } if (!item->toolTip().isEmpty()) { text = item->toolTip(); point = helpEvent->screenPos(); } // Show or hide the tooltip QToolTip::showText(point, text); } void FGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent) { m_lastContextMenuPos = contextMenuEvent->scenePos(); QGraphicsScene::contextMenuEvent(contextMenuEvent); } QPointF FGraphicsScene::lastContextMenuPos() { return m_lastContextMenuPos; } void FGraphicsScene::setDisplayHandles(bool displayHandles) { m_displayHandles = displayHandles; } bool FGraphicsScene::displayHandles() { return m_displayHandles; } fritzing-app-0.9.2b/src/sketch/fgraphicsscene.h000066400000000000000000000030211250202676700215060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FGRAPHICSSCENE_H #define FGRAPHICSSCENE_H #include #include #include class FGraphicsScene : public QGraphicsScene { Q_OBJECT public: FGraphicsScene(QObject * parent = 0); void helpEvent(QGraphicsSceneHelpEvent *); void contextMenuEvent(QGraphicsSceneContextMenuEvent *); QPointF lastContextMenuPos(); void setDisplayHandles(bool); bool displayHandles(); protected: QPointF m_lastContextMenuPos; bool m_displayHandles; }; #endif fritzing-app-0.9.2b/src/sketch/infographicsview.cpp000066400000000000000000000276521250202676700224440ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "infographicsview.h" #include "../debugdialog.h" #include "../infoview/htmlinfoview.h" #include static LayerHash ViewLayers; InfoGraphicsView::InfoGraphicsView( QWidget * parent ) : ZoomableGraphicsView(parent) { m_infoView = NULL; m_boardLayers = 1; m_hoverEnterMode = m_hoverEnterConnectorMode = false; m_smdOrientation = Qt::Vertical; } void InfoGraphicsView::viewItemInfo(ItemBase * item) { if (m_infoView == NULL) return; m_infoView->viewItemInfo(this, item ? item->layerKinChief() : item, swappingEnabled(item)); } void InfoGraphicsView::hoverEnterItem(QGraphicsSceneHoverEvent * event, ItemBase * itemBase) { if (m_infoView == NULL) return; if (event->modifiers() & Qt::ShiftModifier || itemBase->viewID() == ViewLayer::IconView) { m_hoverEnterMode = true; m_infoView->hoverEnterItem(this, event, itemBase ? itemBase->layerKinChief() : itemBase, swappingEnabled(itemBase)); } } void InfoGraphicsView::hoverLeaveItem(QGraphicsSceneHoverEvent * event, ItemBase * itemBase) { if (m_infoView == NULL) return; if (m_hoverEnterMode) { m_hoverEnterMode = false; m_infoView->hoverLeaveItem(this, event, itemBase ? itemBase->layerKinChief() : itemBase); } } void InfoGraphicsView::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { if (m_infoView == NULL) return; if (event->modifiers() & Qt::ShiftModifier) { m_hoverEnterConnectorMode = true; m_infoView->hoverEnterConnectorItem(this, event, item, swappingEnabled(item->attachedTo())); } } void InfoGraphicsView::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item){ if (m_infoView == NULL) return; if (m_hoverEnterConnectorMode) { m_hoverEnterConnectorMode = false; m_infoView->hoverLeaveConnectorItem(this, event, item); } } void InfoGraphicsView::setInfoView(HtmlInfoView * infoView) { m_infoView = infoView; } HtmlInfoView * InfoGraphicsView::infoView() { return m_infoView; } void InfoGraphicsView::mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) { } void InfoGraphicsView::hidePartLabel(ItemBase * item) { Q_UNUSED(item); } void InfoGraphicsView::partLabelChanged(ItemBase * item, const QString &oldText, const QString & newText) { Q_UNUSED(item); Q_UNUSED(oldText); Q_UNUSED(newText); } void InfoGraphicsView::noteChanged(ItemBase * item, const QString &oldText, const QString & newText, QSizeF oldSize, QSizeF newSize) { Q_UNUSED(item); Q_UNUSED(oldText); Q_UNUSED(newText); Q_UNUSED(oldSize); Q_UNUSED(newSize); } QGraphicsItem *InfoGraphicsView::selectedAux() { QList selItems = scene()->selectedItems(); if(selItems.size() != 1) { return NULL; } else { return selItems[0]; } } void InfoGraphicsView::partLabelMoved(ItemBase * itemBase, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset) { Q_UNUSED(itemBase); Q_UNUSED(oldPos); Q_UNUSED(oldOffset); Q_UNUSED(newPos); Q_UNUSED(newOffset); } void InfoGraphicsView::rotateFlipPartLabel(ItemBase * itemBase, double degrees, Qt::Orientations flipDirection) { Q_UNUSED(itemBase); Q_UNUSED(degrees); Q_UNUSED(flipDirection); } void InfoGraphicsView::noteSizeChanged(ItemBase * itemBase, const QSizeF & oldSize, const QSizeF & newSize) { Q_UNUSED(itemBase); Q_UNUSED(oldSize); Q_UNUSED(newSize); } bool InfoGraphicsView::spaceBarIsPressed() { return false; } InfoGraphicsView * InfoGraphicsView::getInfoGraphicsView(QGraphicsItem * item) { if (item == NULL) return NULL; QGraphicsScene * scene = item->scene(); if (scene == NULL) return NULL; return dynamic_cast(scene->parent()); } void InfoGraphicsView::initWire(Wire *, int penWidth) { Q_UNUSED(penWidth); } void InfoGraphicsView::getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect) { Q_UNUSED(w); Q_UNUSED(w1); Q_UNUSED(w2); Q_UNUSED(negativeOffsetRect); } void InfoGraphicsView::getLabelFont(QFont &, QColor &, ItemBase *) { } double InfoGraphicsView::getLabelFontSizeTiny() { return 5; } double InfoGraphicsView::getLabelFontSizeSmall() { return 7; } double InfoGraphicsView::getLabelFontSizeMedium() { return 9; } double InfoGraphicsView::getLabelFontSizeLarge() { return 14; } bool InfoGraphicsView::hasBigDots() { return false; } void InfoGraphicsView::setVoltage(double v, bool doEmit) { if (doEmit) { emit setVoltageSignal(v, false); } } void InfoGraphicsView::resizeBoard(double w, double h, bool doEmit) { Q_UNUSED(w); Q_UNUSED(h); Q_UNUSED(doEmit); } void InfoGraphicsView::setResistance(QString resistance, QString pinSpacing) { Q_UNUSED(resistance); Q_UNUSED(pinSpacing); } void InfoGraphicsView::setProp(ItemBase * item, const QString & prop, const QString & trProp, const QString & oldValue, const QString & newValue, bool redraw) { Q_UNUSED(item); Q_UNUSED(prop); Q_UNUSED(trProp); Q_UNUSED(oldValue); Q_UNUSED(newValue); Q_UNUSED(redraw); } void InfoGraphicsView::setHoleSize(ItemBase * item, const QString & prop, const QString & trProp, const QString & oldValue, const QString & newValue, QRectF & oldRect, QRectF & newRect, bool redraw) { Q_UNUSED(item); Q_UNUSED(prop); Q_UNUSED(trProp); Q_UNUSED(oldValue); Q_UNUSED(newValue); Q_UNUSED(oldRect); Q_UNUSED(newRect); Q_UNUSED(redraw); } void InfoGraphicsView::changeWireWidthMils(const QString newWidth) { Q_UNUSED(newWidth); } void InfoGraphicsView::changeWireColor(const QString newColor) { Q_UNUSED(newColor); } void InfoGraphicsView::swap(const QString & family, const QString & prop, QMap & propsMap, ItemBase * itemBase) { emit swapSignal(family, prop, propsMap, itemBase); } void InfoGraphicsView::setInstanceTitle(long id, const QString & oldTitle, const QString & newTitle, bool isUndoable, bool doEmit) { Q_UNUSED(id); Q_UNUSED(newTitle); Q_UNUSED(oldTitle); Q_UNUSED(isUndoable); Q_UNUSED(doEmit); } LayerHash & InfoGraphicsView::viewLayers() { return ViewLayers; } void InfoGraphicsView::loadLogoImage(ItemBase *, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName) { Q_UNUSED(oldSvg); Q_UNUSED(oldAspectRatio); Q_UNUSED(oldFilename); Q_UNUSED(newFilename); Q_UNUSED(addName); } void InfoGraphicsView::setNoteFocus(QGraphicsItem * item, bool inFocus) { Q_UNUSED(item); Q_UNUSED(inFocus); } void InfoGraphicsView::setBoardLayers(int layers, bool redraw) { Q_UNUSED(redraw); m_boardLayers = layers; } int InfoGraphicsView::boardLayers() { return m_boardLayers; } VirtualWire * InfoGraphicsView::makeOneRatsnestWire(ConnectorItem * source, ConnectorItem * dest, bool routed, QColor color, bool force) { Q_UNUSED(source); Q_UNUSED(dest); Q_UNUSED(routed); Q_UNUSED(color); Q_UNUSED(force); return NULL; } void InfoGraphicsView::getRatsnestColor(QColor & color) { Q_UNUSED(color); } void InfoGraphicsView::changeBus(ItemBase *, bool connect, const QString & oldBus, const QString & newBus, QList &, const QString & message, const QString & oldLayout, const QString & newLayout) { Q_UNUSED(connect); Q_UNUSED(oldBus); Q_UNUSED(newBus); Q_UNUSED(message); Q_UNUSED(oldLayout); Q_UNUSED(newLayout); } const QString & InfoGraphicsView::filenameIf() { return ___emptyString___; } QString InfoGraphicsView::generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart) { Q_UNUSED(itemBase); Q_UNUSED(whereToStart); return ""; } void InfoGraphicsView::prepLegSelection(ItemBase *) { } void InfoGraphicsView::prepLegBendpointMove(ConnectorItem * from, int index, QPointF oldPos, QPointF newPos, ConnectorItem * to, bool changeConnections) { Q_UNUSED(from); Q_UNUSED(index); Q_UNUSED(oldPos); Q_UNUSED(newPos); Q_UNUSED(to); Q_UNUSED(changeConnections); } void InfoGraphicsView::prepLegCurveChange(ConnectorItem * from, int index, const class Bezier *, const class Bezier *, bool triggerFirstTime) { Q_UNUSED(from); Q_UNUSED(index); Q_UNUSED(triggerFirstTime); } void InfoGraphicsView::prepLegBendpointChange(ConnectorItem *, int oldCount, int newCount, int index, QPointF, const class Bezier *, const class Bezier *, const class Bezier *, bool triggerFirstTime) { Q_UNUSED(triggerFirstTime); Q_UNUSED(index); Q_UNUSED(oldCount); Q_UNUSED(newCount); } double InfoGraphicsView::getWireStrokeWidth(Wire *, double wireWidth) { return wireWidth; } bool InfoGraphicsView::curvyWiresIndicated(Qt::KeyboardModifiers) { return true; } void InfoGraphicsView::triggerRotate(ItemBase *, double degrees) { Q_UNUSED(degrees); } void InfoGraphicsView::changePinLabels(ItemBase * itemBase, bool singleRow) { Q_UNUSED(itemBase); Q_UNUSED(singleRow); } void InfoGraphicsView::renamePins(ItemBase *, const QStringList & oldLabels, const QStringList & newLabels, bool singleRow) { Q_UNUSED(oldLabels); Q_UNUSED(newLabels); Q_UNUSED(singleRow); } ViewGeometry::WireFlag InfoGraphicsView::getTraceFlag() { return ViewGeometry::NoFlag; } void InfoGraphicsView::setAnyInRotation() { } void InfoGraphicsView::setActiveWire(Wire * wire) { emit setActiveWireSignal(wire); } void InfoGraphicsView::setActiveConnectorItem(ConnectorItem * connectorItem) { emit setActiveConnectorItemSignal(connectorItem); } void InfoGraphicsView::resolveTemporary(bool, ItemBase *) { } void InfoGraphicsView::newWire(Wire * wire) { bool succeeded = connect(wire, SIGNAL(wireChangedSignal(Wire*, const QLineF & , const QLineF & , QPointF, QPointF, ConnectorItem *, ConnectorItem *) ), this, SLOT(wireChangedSlot(Wire*, const QLineF & , const QLineF & , QPointF, QPointF, ConnectorItem *, ConnectorItem *)), Qt::DirectConnection); // DirectConnection means call the slot directly like a subroutine, without waiting for a thread or queue succeeded = connect(wire, SIGNAL(wireChangedCurveSignal(Wire*, const Bezier *, const Bezier *, bool)), this, SLOT(wireChangedCurveSlot(Wire*, const Bezier *, const Bezier *, bool)), Qt::DirectConnection); // DirectConnection means call the slot directly like a subroutine, without waiting for a thread or queue succeeded = succeeded && connect(wire, SIGNAL(wireSplitSignal(Wire*, QPointF, QPointF, const QLineF & )), this, SLOT(wireSplitSlot(Wire*, QPointF, QPointF, const QLineF & ))); succeeded = succeeded && connect(wire, SIGNAL(wireJoinSignal(Wire*, ConnectorItem *)), this, SLOT(wireJoinSlot(Wire*, ConnectorItem*))); if (!succeeded) { DebugDialog::debug("wire signal connect failed"); } emit newWireSignal(wire); } void InfoGraphicsView::setSMDOrientation(Qt::Orientations orientation) { m_smdOrientation = orientation; } Qt::Orientations InfoGraphicsView::smdOrientation() { return m_smdOrientation; } void InfoGraphicsView::moveItem(ItemBase *, double x, double y) { Q_UNUSED(x); Q_UNUSED(y); } void InfoGraphicsView::updateRotation(ItemBase * itemBase) { if (m_infoView) m_infoView->updateRotation(itemBase); } void InfoGraphicsView::rotateX(double degrees, bool rubberBandLegEnabled, ItemBase * originatingItem) { Q_UNUSED(degrees); Q_UNUSED(rubberBandLegEnabled); Q_UNUSED(originatingItem); } fritzing-app-0.9.2b/src/sketch/infographicsview.h000066400000000000000000000151651250202676700221050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6715 $: $Author: irascibl@gmail.com $: $Date: 2012-12-17 11:27:32 +0100 (Mo, 17. Dez 2012) $ ********************************************************************/ #ifndef INFOGRAPHICSVIEW_H #define INFOGRAPHICSVIEW_H #include #include #include #include #include "../items/itembase.h" #include "zoomablegraphicsview.h" class InfoGraphicsView : public ZoomableGraphicsView { Q_OBJECT public: InfoGraphicsView(QWidget* parent = 0); virtual void viewItemInfo(ItemBase *); virtual void hoverEnterItem(QGraphicsSceneHoverEvent * event, ItemBase *); virtual void hoverLeaveItem(QGraphicsSceneHoverEvent * event, ItemBase *); void updateRotation(ItemBase *); virtual bool swappingEnabled(ItemBase *) = 0; virtual void hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem *); virtual void hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem *); void setInfoView(class HtmlInfoView *); class HtmlInfoView * infoView(); virtual void mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); virtual void hidePartLabel(ItemBase * item); virtual void partLabelMoved(ItemBase *, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset); virtual void rotateFlipPartLabel(ItemBase *, double degrees, Qt::Orientations flipDirection); virtual void noteSizeChanged(ItemBase * itemBase, const QSizeF & oldSize, const QSizeF & newSize); virtual bool spaceBarIsPressed(); virtual void initWire(class Wire *, int penWidth); virtual void setIgnoreSelectionChangeEvents(bool) {} virtual void getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect); virtual void getLabelFont(QFont &, QColor &, ItemBase *); virtual double getLabelFontSizeTiny(); virtual double getLabelFontSizeSmall(); virtual double getLabelFontSizeMedium(); virtual double getLabelFontSizeLarge(); virtual bool hasBigDots(); virtual LayerHash & viewLayers(); virtual void loadLogoImage(ItemBase *, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName); virtual void setNoteFocus(QGraphicsItem *, bool inFocus); int boardLayers(); virtual void setBoardLayers(int, bool redraw); virtual class VirtualWire * makeOneRatsnestWire(ConnectorItem * source, ConnectorItem * dest, bool routed, QColor, bool force); virtual void getRatsnestColor(QColor &); virtual void changeBus(ItemBase *, bool connect, const QString & oldBus, const QString & newBus, QList &, const QString & message, const QString & oldLayout, const QString & newLayout); virtual const QString & filenameIf(); virtual QString generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart); virtual void prepLegBendpointMove(ConnectorItem * from, int index, QPointF oldPos, QPointF newPos, ConnectorItem * to, bool changeConnections); virtual void prepLegCurveChange(ConnectorItem * from, int index, const class Bezier * oldB, const class Bezier * newB, bool triggerFirstTime); virtual void prepLegBendpointChange(ConnectorItem * from, int oldCount, int newCount, int index, QPointF pos, const class Bezier *, const class Bezier *, const class Bezier *, bool triggerFirstTime); virtual void prepLegSelection(ItemBase *); virtual double getWireStrokeWidth(Wire *, double wireWidth); virtual bool curvyWiresIndicated(Qt::KeyboardModifiers); virtual void triggerRotate(ItemBase *, double degrees); virtual void changePinLabels(ItemBase *, bool singleRow); virtual void renamePins(ItemBase *, const QStringList & oldLabels, const QStringList & newLabels, bool singleRow); virtual ViewGeometry::WireFlag getTraceFlag(); virtual void setAnyInRotation(); virtual void partLabelChanged(ItemBase *, const QString &oldText, const QString & newText); virtual void noteChanged(ItemBase *, const QString &oldText, const QString & newText, QSizeF oldSize, QSizeF newSize); virtual void setResistance(QString resistance, QString pinSpacing); virtual void setProp(ItemBase *, const QString & propName, const QString & translatedPropName, const QString & oldValue, const QString & newValue, bool redraw); virtual void setHoleSize(ItemBase *, const QString & propName, const QString & translatedPropName, const QString & oldValue, const QString & newValue, QRectF & oldRect, QRectF & newRect, bool redraw); virtual void changeWireWidthMils(const QString newWidth); virtual void changeWireColor(const QString newColor); virtual void swap(const QString & family, const QString & prop, QMap & propsMap, ItemBase *); virtual void resolveTemporary(bool, ItemBase *); virtual void newWire(Wire *); void setActiveWire(Wire *); void setActiveConnectorItem(ConnectorItem *); void setSMDOrientation(Qt::Orientations); Qt::Orientations smdOrientation(); virtual void moveItem(ItemBase *, double x, double y); virtual void rotateX(double degrees, bool rubberBandLegEnabled, ItemBase * originatingItem); public slots: virtual void setVoltage(double, bool doEmit); virtual void resizeBoard(double w, double h, bool doEmit); virtual void setInstanceTitle(long id, const QString & oldTitle, const QString & newTitle, bool isUndoable, bool doEmit); signals: void setVoltageSignal(double, bool doEmit); void swapSignal(const QString & family, const QString & prop, QMap & propsMap, ItemBase *); void changePinLabelsSignal(ItemBase *, bool singleRow); void setActiveWireSignal(Wire *); void setActiveConnectorItemSignal(ConnectorItem *); void newWireSignal(Wire *); public: static InfoGraphicsView * getInfoGraphicsView(QGraphicsItem *); protected: QGraphicsItem *selectedAux(); class HtmlInfoView *m_infoView; int m_boardLayers; bool m_hoverEnterMode; bool m_hoverEnterConnectorMode; Qt::Orientations m_smdOrientation; }; #endif fritzing-app-0.9.2b/src/sketch/pcbsketchwidget.cpp000066400000000000000000003006211250202676700222350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6998 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #include #include "pcbsketchwidget.h" #include "../debugdialog.h" #include "../items/tracewire.h" #include "../items/virtualwire.h" #include "../items/resizableboard.h" #include "../items/pad.h" #include "../waitpushundostack.h" #include "../connectors/connectoritem.h" #include "../items/moduleidnames.h" #include "../items/partlabel.h" #include "../fsvgrenderer.h" #include "../autoroute/autorouteprogressdialog.h" #include "../autoroute/drc.h" #include "../items/groundplane.h" #include "../items/jumperitem.h" #include "../utils/autoclosemessagebox.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/folderutils.h" #include "../processeventblocker.h" #include "../autoroute/cmrouter/tileutils.h" #include "../autoroute/cmrouter/cmrouter.h" #include "../autoroute/panelizer.h" #include "../autoroute/autoroutersettingsdialog.h" #include "../svg/groundplanegenerator.h" #include "../items/logoitem.h" #include "../dialogs/groundfillseeddialog.h" #include "../version/version.h" #include #include #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////// static const int MAX_INT = std::numeric_limits::max(); static const double StrokeWidthIncrement = 50; static QString PCBTraceColor1 = "trace1"; static QString PCBTraceColor = "trace"; QSizeF PCBSketchWidget::m_jumperItemSize = QSizeF(0, 0); struct DistanceThing { int distance; bool fromConnector0; }; QHash distances; bool bySize(QList * l1, QList * l2) { return l1->count() >= l2->count(); } bool distanceLessThan(ConnectorItem * end0, ConnectorItem * end1) { if (end0->connectorType() == Connector::Male && end1->connectorType() == Connector::Female) { return true; } if (end1->connectorType() == Connector::Male && end0->connectorType() == Connector::Female) { return false; } DistanceThing * dt0 = distances.value(end0, NULL); DistanceThing * dt1 = distances.value(end1, NULL); if (dt0 && dt1) { return dt0->distance <= dt1->distance; } if (dt0) { return true; } if (dt1) { return false; } return true; } ////////////////////////////////////////////////////// const char * PCBSketchWidget::FakeTraceProperty = "FakeTrace"; PCBSketchWidget::PCBSketchWidget(ViewLayer::ViewID viewID, QWidget *parent) : SketchWidget(viewID, parent) { m_rolloverQuoteDialog = NULL; m_requestQuoteTimer.setSingleShot(true); m_requestQuoteTimer.setInterval(100); connect(&m_requestQuoteTimer, SIGNAL(timeout()), this, SLOT(requestQuoteNow())); m_resizingBoard = NULL; m_resizingJumperItem = NULL; m_viewName = QObject::tr("PCB View"); m_shortName = QObject::tr("pcb"); initBackgroundColor(); m_routingStatus.zero(); m_cleanType = noClean; } void PCBSketchWidget::setWireVisible(Wire * wire) { bool visible = wire->getRatsnest() || (wire->isTraceType(this->getTraceFlag())); wire->setVisible(visible); wire->setEverVisible(visible); } void PCBSketchWidget::addViewLayers() { setViewLayerIDs(ViewLayer::Silkscreen1, ViewLayer::Copper0Trace, ViewLayer::Copper0, ViewLayer::PcbRuler, ViewLayer::PcbNote); addViewLayersAux(ViewLayer::layersForView(ViewLayer::PCBView), ViewLayer::layersForViewFromBelow(ViewLayer::PCBView)); ViewLayer * silkscreen1 = m_viewLayers.value(ViewLayer::Silkscreen1); ViewLayer * silkscreen1Label = m_viewLayers.value(ViewLayer::Silkscreen1Label); if (silkscreen1 && silkscreen1Label) { silkscreen1Label->setParentLayer(silkscreen1); } ViewLayer * silkscreen0 = m_viewLayers.value(ViewLayer::Silkscreen0); ViewLayer * silkscreen0Label = m_viewLayers.value(ViewLayer::Silkscreen0Label); if (silkscreen0 && silkscreen0Label) { silkscreen0Label->setParentLayer(silkscreen0); } ViewLayer * copper0 = m_viewLayers.value(ViewLayer::Copper0); ViewLayer * copper0Trace = m_viewLayers.value(ViewLayer::Copper0Trace); ViewLayer * copper1 = m_viewLayers.value(ViewLayer::Copper1); ViewLayer * copper1Trace = m_viewLayers.value(ViewLayer::Copper1Trace); if (copper0 && copper0Trace) { copper0Trace->setParentLayer(copper0); } ViewLayer * groundPlane0 = m_viewLayers.value(ViewLayer::GroundPlane0); if (copper0 && groundPlane0) { groundPlane0->setParentLayer(copper0); } if (copper1 && copper1Trace) { copper1Trace->setParentLayer(copper1); } ViewLayer * groundPlane1 = m_viewLayers.value(ViewLayer::GroundPlane1); if (copper1 && groundPlane1) { groundPlane1->setParentLayer(copper1); } // disable these for now //viewLayer = m_viewLayers.value(ViewLayer::Keepout); //viewLayer->action()->setEnabled(false); setBoardLayers(1, false); } ViewLayer::ViewLayerID PCBSketchWidget::multiLayerGetViewLayerID(ModelPart * modelPart, ViewLayer::ViewID viewID, ViewLayer::ViewLayerPlacement viewLayerPlacement, LayerList & layerList) { if (modelPart->itemType() == ModelPart::CopperFill) { if (viewLayerPlacement == ViewLayer::NewBottom) return ViewLayer::GroundPlane0; else if (viewLayerPlacement == ViewLayer::NewTop) return ViewLayer::GroundPlane1; } // privilege Copper if it's available ViewLayer::ViewLayerID wantLayer = (modelPart->flippedSMD() && viewLayerPlacement == ViewLayer::NewTop) ? ViewLayer::Copper1 : ViewLayer::Copper0; if (layerList.contains(wantLayer)) return wantLayer; return SketchWidget::multiLayerGetViewLayerID(modelPart, viewID, viewLayerPlacement, layerList); } bool PCBSketchWidget::canDeleteItem(QGraphicsItem * item, int count) { VirtualWire * wire = dynamic_cast(item); if (wire != NULL && count > 1) return false; return SketchWidget::canDeleteItem(item, count); } bool PCBSketchWidget::canCopyItem(QGraphicsItem * item, int count) { VirtualWire * wire = dynamic_cast(item); if (wire != NULL) { if (wire->getRatsnest()) return false; } return SketchWidget::canCopyItem(item, count); } bool PCBSketchWidget::canChainWire(Wire * wire) { bool result = SketchWidget::canChainWire(wire); if (!result) return result; if (wire->getRatsnest()) { ConnectorItem * c0 = wire->connector0()->firstConnectedToIsh(); if (c0 == NULL) return false; ConnectorItem * c1 = wire->connector1()->firstConnectedToIsh(); if (c1 == NULL) return false; return !c0->wiredTo(c1, (ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::RatsnestFlag | ViewGeometry::SchematicTraceFlag) ^ getTraceFlag()); } return result; } void PCBSketchWidget::createTrace(Wire * wire, bool useLastWireColor) { QString commandString = tr("Create Trace from Ratsnest"); SketchWidget::createTrace(wire, commandString, getTraceFlag(), useLastWireColor); ensureTraceLayerVisible(); } void PCBSketchWidget::excludeFromAutoroute(bool exclude) { foreach (QGraphicsItem * item, scene()->selectedItems()) { TraceWire * wire = dynamic_cast(item); if (wire) { if (!wire->isTraceType(getTraceFlag())) continue; QList wires; QList ends; wire->collectChained(wires, ends); foreach (Wire * w, wires) { w->setAutoroutable(!exclude); } continue; } JumperItem * jumperItem = dynamic_cast(item); if (jumperItem) { jumperItem->setAutoroutable(!exclude); continue; } Via * via = dynamic_cast(item); if (via) { via->setAutoroutable(!exclude); continue; } } } void PCBSketchWidget::selectAllExcludedTraces() { selectAllXTraces(false, QObject::tr("Select all 'Don't autoroute' traces"), autorouteTypePCB()); } void PCBSketchWidget::selectAllIncludedTraces() { selectAllXTraces(true, QObject::tr("Select all autorouteable traces"), autorouteTypePCB()); } void PCBSketchWidget::selectAllXTraces(bool autoroutable, const QString & cmdText, bool forPCB) { QList wires; QList items; if (forPCB) { int boardCount; ItemBase * board = findSelectedBoard(boardCount); if (boardCount == 0 && autorouteTypePCB()) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use this selection operation.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please click on a PCB first--this selection operation only works for one board at a time.")); return; } items = scene()->collidingItems(board); } else { items = scene()->items(); } foreach (QGraphicsItem * item, items) { TraceWire * wire = dynamic_cast(item); if (wire == NULL) continue; if (!wire->isTraceType(getTraceFlag())) continue; if (wire->getAutoroutable() == autoroutable) { wires.append(wire); } } QUndoCommand * parentCommand = new QUndoCommand(cmdText); stackSelectionState(false, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); foreach (Wire * wire, wires) { selectItemCommand->addRedo(wire->id()); } scene()->clearSelection(); m_undoStack->push(parentCommand); } const QString & PCBSketchWidget::hoverEnterPartConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { Q_UNUSED(event); Q_UNUSED(item); static QString message = tr("Click this connector to drag out a new trace."); return message; } void PCBSketchWidget::addDefaultParts() { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); // have to put this off until later, because positioning the item doesn't work correctly until the view is visible m_addedDefaultPart = addItem(referenceModel()->retrieveModelPart(ModuleIDNames::TwoSidedRectanglePCBModuleIDName), ViewLayer::NewTop, BaseCommand::CrossView, viewGeometry, newID, -1, NULL); m_addDefaultParts = true; changeBoardLayers(2, true); } void PCBSketchWidget::showEvent(QShowEvent * event) { SketchWidget::showEvent(event); dealWithDefaultParts(); } void PCBSketchWidget::dealWithDefaultParts() { if (!m_addDefaultParts) return; if (m_addedDefaultPart == NULL) return; m_addDefaultParts = false; QSizeF vpSize = this->viewport()->size(); QSizeF partSize(300, 200); //if (vpSize.height() < helpSize.height() + 50 + partSize.height()) { //vpSize.setWidth(vpSize.width() - verticalScrollBar()->width()); //} QPointF p; p.setX((int) ((vpSize.width() - partSize.width()) / 2.0)); p.setY((int) ((vpSize.height() - partSize.height()) / 2.0)); // place it QPointF q = mapToScene(p.toPoint()); m_addedDefaultPart->setPos(q); alignOneToGrid(m_addedDefaultPart); ResizableBoard * rb = qobject_cast(m_addedDefaultPart); if (rb) rb->resizePixels(partSize.width(), partSize.height(), m_viewLayers); QTimer::singleShot(10, this, SLOT(vScrollToZero())); // set both layers active by default setLayerActive(ViewLayer::Copper1, true); setLayerActive(ViewLayer::Copper0, true); setLayerActive(ViewLayer::Silkscreen1, true); setLayerActive(ViewLayer::Silkscreen0, true); } void PCBSketchWidget::setClipEnds(ClipableWire * vw, bool clipEnds) { vw->setClipEnds(clipEnds); } ViewLayer::ViewLayerID PCBSketchWidget::getDragWireViewLayerID(ConnectorItem * connectorItem) { switch (connectorItem->attachedToViewLayerID()) { case ViewLayer::Copper1: case ViewLayer::Copper1Trace: case ViewLayer::GroundPlane1: return ViewLayer::Copper1Trace; default: return ViewLayer::Copper0Trace; } } ViewLayer::ViewLayerID PCBSketchWidget::getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewGeometry.getRatsnest()) { return ViewLayer::PcbRatsnest; } if (viewGeometry.getAnyTrace()) { switch (viewLayerPlacement) { case ViewLayer::NewTop: return ViewLayer::Copper1Trace; default: return ViewLayer::Copper0Trace; } } switch (viewLayerPlacement) { case ViewLayer::NewTop: return ViewLayer::Copper1Trace; default: return m_wireViewLayerID; } } void PCBSketchWidget::initWire(Wire * wire, int penWidth) { Q_UNUSED(penWidth); if (wire->getRatsnest()) return; wire->setColorString(traceColor(wire->connector0()), 1.0, false); wire->setPenWidth(1, this, 2); } bool PCBSketchWidget::autorouteTypePCB() { return true; } const QString & PCBSketchWidget::traceColor(ConnectorItem * forColor) { switch(forColor->attachedToViewLayerID()) { case ViewLayer::Copper1: case ViewLayer::Copper1Trace: case ViewLayer::GroundPlane1: return PCBTraceColor1; default: return PCBTraceColor; } } const QString & PCBSketchWidget::traceColor(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewTop) { return PCBTraceColor1; } return PCBTraceColor; } PCBSketchWidget::CleanType PCBSketchWidget::cleanType() { return m_cleanType; } void PCBSketchWidget::ensureTraceLayersVisible() { ensureLayerVisible(ViewLayer::Copper0); ensureLayerVisible(ViewLayer::Copper0Trace); ensureLayerVisible(ViewLayer::GroundPlane0); if (m_boardLayers == 2) { ensureLayerVisible(ViewLayer::Copper1); ensureLayerVisible(ViewLayer::Copper1Trace); ensureLayerVisible(ViewLayer::GroundPlane1); } } void PCBSketchWidget::ensureTraceLayerVisible() { ensureLayerVisible(ViewLayer::Copper0); ensureLayerVisible(ViewLayer::Copper0Trace); } bool PCBSketchWidget::canChainMultiple() { return false; } void PCBSketchWidget::setNewPartVisible(ItemBase * itemBase) { if (itemBase->itemType() == ModelPart::Breadboard || itemBase->itemType() == ModelPart::Symbol || itemBase->itemType() == ModelPart::SchematicSubpart || itemBase->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName) || itemBase->moduleID().endsWith(ModuleIDNames::PowerModuleIDName)) { // don't need to see the breadboard in the other views // but it's there so connections can be more easily synched between views itemBase->setVisible(false); itemBase->setEverVisible(false); } } bool PCBSketchWidget::canDropModelPart(ModelPart * modelPart) { if (!SketchWidget::canDropModelPart(modelPart)) return false; if (Board::isBoard(modelPart)) { return matchesLayer(modelPart); } switch (modelPart->itemType()) { case ModelPart::Logo: if (modelPart->moduleID().contains("schematic", Qt::CaseInsensitive)) return false; if (modelPart->moduleID().contains("breadboard", Qt::CaseInsensitive)) return false; case ModelPart::Jumper: case ModelPart::Ruler: case ModelPart::CopperFill: return true; case ModelPart::Wire: case ModelPart::Breadboard: case ModelPart::Symbol: case ModelPart::SchematicSubpart: // can't drag and drop these parts in this view return false; default: return !modelPart->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName); } return true; } bool PCBSketchWidget::bothEndsConnected(Wire * wire, ViewGeometry::WireFlags flag, ConnectorItem * oneEnd, QList & wires, QList & partConnectorItems) { QList visited; return bothEndsConnectedAux(wire, flag, oneEnd, wires, partConnectorItems, visited); } bool PCBSketchWidget::bothEndsConnectedAux(Wire * wire, ViewGeometry::WireFlags flag, ConnectorItem * oneEnd, QList & wires, QList & partConnectorItems, QList & visited) { if (visited.contains(wire)) return false; visited.append(wire); bool result = false; ConnectorItem * otherEnd = wire->otherConnector(oneEnd); foreach (ConnectorItem * toConnectorItem, otherEnd->connectedToItems()) { if (partConnectorItems.contains(toConnectorItem)) { result = true; continue; } if (toConnectorItem->attachedToItemType() != ModelPart::Wire) continue; Wire * w = qobject_cast(toConnectorItem->attachedTo()); ViewGeometry::WireFlags wflag = w->wireFlags() & (ViewGeometry::RatsnestFlag | getTraceFlag()); if (wflag != flag) continue; result = bothEndsConnectedAux(w, flag, toConnectorItem, wires, partConnectorItems, visited) || result; // let it recurse } if (result) { wires.removeOne(wire); } return result; } bool PCBSketchWidget::canCreateWire(Wire * dragWire, ConnectorItem * from, ConnectorItem * to) { Q_UNUSED(dragWire); return ((from != NULL) && (to != NULL)); } ConnectorItem * PCBSketchWidget::findNearestPartConnectorItem(ConnectorItem * fromConnectorItem) { // find the nearest part to fromConnectorItem Wire * wire = qobject_cast(fromConnectorItem->attachedTo()); if (wire == NULL) return NULL; QList ends; calcDistances(wire, ends); clearDistances(); if (ends.count() < 1) return NULL; return ends[0]; } void PCBSketchWidget::calcDistances(Wire * wire, QList & ends) { QList chained; wire->collectChained(chained, ends); if (ends.count() < 2) return; clearDistances(); foreach (ConnectorItem * end, ends) { bool fromConnector0; QList distanceWires; int distance = calcDistance(wire, end, 0, distanceWires, fromConnector0); DistanceThing * dt = new DistanceThing; dt->distance = distance; dt->fromConnector0 = fromConnector0; DebugDialog::debug(QString("distance %1 %2 %3, %4 %5") .arg(end->attachedToID()).arg(end->attachedToTitle()).arg(end->connectorSharedID()) .arg(distance).arg(fromConnector0 ? "connector0" : "connector1")); distances.insert(end, dt); } qSort(ends.begin(), ends.end(), distanceLessThan); } void PCBSketchWidget::clearDistances() { foreach (ConnectorItem * c, distances.keys()) { DistanceThing * dt = distances.value(c, NULL); if (dt) delete dt; } distances.clear(); } int PCBSketchWidget::calcDistanceAux(ConnectorItem * from, ConnectorItem * to, int distance, QList & distanceWires) { //DebugDialog::debug(QString("calc distance aux: %1 %2, %3 %4, %5").arg(from->attachedToID()).arg(from->connectorSharedID()) //.arg(to->attachedToTitle()).arg(to->connectorSharedID()).arg(distance)); foreach (ConnectorItem * toConnectorItem, from->connectedToItems()) { if (toConnectorItem == to) { return distance; } } int result = MAX_INT; foreach (ConnectorItem * toConnectorItem, from->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) continue; Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (distanceWires.contains(w)) continue; bool fromConnector0; int temp = calcDistance(w, to, distance + 1, distanceWires, fromConnector0); if (temp < result) { result = temp; } } return result; } int PCBSketchWidget::calcDistance(Wire * wire, ConnectorItem * end, int distance, QList & distanceWires, bool & fromConnector0) { //DebugDialog::debug(QString("calc distance wire: %1 rat:%2 to %3 %4, %5").arg(wire->id()).arg(wire->getRatsnest()) //.arg(end->attachedToTitle()).arg(end->connectorSharedID()).arg(distance)); distanceWires.append(wire); int d0 = calcDistanceAux(wire->connector0(), end, distance, distanceWires); if (d0 == distance) { fromConnector0 = true; return d0; } int d1 = calcDistanceAux(wire->connector1(), end, distance, distanceWires); if (d0 <= d1) { fromConnector0 = true; return d0; } fromConnector0 = false; return d1; } void PCBSketchWidget::showGroundTraces(QList & connectorItems, bool show) { foreach (ConnectorItem * connectorItem, connectorItems) { TraceWire * trace = dynamic_cast(connectorItem->attachedTo()); if (trace == NULL) continue; if (!trace->isTraceType(getTraceFlag())) continue; trace->setVisible(show); } } void PCBSketchWidget::getLabelFont(QFont & font, QColor & color, ItemBase * itemBase) { font.setFamily(OCRAFontName); font.setPointSize(getLabelFontSizeSmall()); font.setBold(false); font.setItalic(false); color.setAlpha(255); QString name = ViewLayer::Silkscreen1Color; if (boardLayers() == 2) { if (itemBase->viewLayerPlacement() == ViewLayer::NewBottom) name = ViewLayer::Silkscreen0Color; } color.setNamedColor(name); } ViewLayer::ViewLayerID PCBSketchWidget::getLabelViewLayerID(ItemBase * itemBase) { if (boardLayers() == 2) { if (itemBase->viewLayerPlacement() == ViewLayer::NewBottom) return ViewLayer::Silkscreen0Label; } return ViewLayer::Silkscreen1Label; } double PCBSketchWidget::getLabelFontSizeTiny() { return 3; } double PCBSketchWidget::getLabelFontSizeSmall() { return 5; } double PCBSketchWidget::getLabelFontSizeMedium() { return 7; } double PCBSketchWidget::getLabelFontSizeLarge() { return 12; } void PCBSketchWidget::resizeBoard(double mmW, double mmH, bool doEmit) { Q_UNUSED(doEmit); PaletteItem * item = getSelectedPart(); if (item == NULL) return; bool handle = false; switch (item->itemType()) { case ModelPart::ResizableBoard: case ModelPart::Logo: handle = true; break; case ModelPart::Part: handle = item->moduleID().endsWith(ModuleIDNames::PadModuleIDName) || item->moduleID().endsWith(ModuleIDNames::CopperBlockerModuleIDName) || item->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName); break; default: break; } if (!handle) return SketchWidget::resizeBoard(mmW, mmH, doEmit); resizeWithHandle(item, mmW, mmH); } void PCBSketchWidget::showLabelFirstTime(long itemID, bool show, bool doEmit) { // called when new item is added, to decide whether to show part label SketchWidget::showLabelFirstTime(itemID, show, doEmit); ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; if (!canDropModelPart(itemBase->modelPart())) return; switch (itemBase->itemType()) { case ModelPart::Part: case ModelPart::Jumper: { if (itemBase->hasPartLabel()) { ViewLayer * viewLayer = m_viewLayers.value(getLabelViewLayerID(itemBase)); itemBase->showPartLabel(itemBase->isVisible(), viewLayer); itemBase->partLabelSetHidden(!viewLayer->visible()); } } break; default: break; } } ItemBase * PCBSketchWidget::findBoardBeneath(ItemBase * itemBase) { foreach (QGraphicsItem * item, scene()->collidingItems(itemBase)) { Board * board = dynamic_cast(item); if (board == NULL) continue; if (Board::isBoard(board)) return board; } return NULL; } ItemBase * PCBSketchWidget::findSelectedBoard(int & boardCount) { QList boards = findBoard(); boardCount = boards.count(); if (boards.count() == 0) return NULL; if (boards.count() == 1) return boards.at(0); int selectedCount = 0; ItemBase * selectedBoard = NULL; foreach (ItemBase * board, boards) { if (board->isSelected()) { selectedCount++; selectedBoard = board; } } if (selectedCount == 1) return selectedBoard; return NULL; } QList PCBSketchWidget::findBoard() { QSet boards; foreach (QGraphicsItem * childItem, items()) { Board * board = dynamic_cast(childItem); if (board == NULL) continue; if (Board::isBoard(board)) { boards.insert(board->layerKinChief()); } } return boards.toList(); } void PCBSketchWidget::forwardRoutingStatus(const RoutingStatus & routingStatus) { m_routingStatus = routingStatus; SketchWidget::forwardRoutingStatus(routingStatus); } double PCBSketchWidget::defaultGridSizeInches() { return 0.1; } ViewLayer::ViewLayerPlacement PCBSketchWidget::wireViewLayerPlacement(ConnectorItem * connectorItem) { switch (connectorItem->attachedToViewLayerID()) { case ViewLayer::Copper1: case ViewLayer::Copper1Trace: case ViewLayer::GroundPlane1: return ViewLayer::NewTop; default: return ViewLayer::NewBottom; } } void PCBSketchWidget::setBoardLayers(int layers, bool redraw) { SketchWidget::setBoardLayers(layers, redraw); QList viewLayerIDs; viewLayerIDs << ViewLayer::Copper1 << ViewLayer::Copper1Trace; foreach (ViewLayer::ViewLayerID viewLayerID, viewLayerIDs) { ViewLayer * layer = m_viewLayers.value(viewLayerID, NULL); if (layer) { layer->action()->setEnabled(layers == 2); layer->setVisible(layers == 2); if (redraw) { setLayerVisible(layer, layers == 2, true); if (layers == 2) { layer->action()->setChecked(true); } } } } } void PCBSketchWidget::swapLayers(ItemBase *, int newLayers, QUndoCommand * parentCommand) { QList smds; QList pads; QList already; ChangeBoardLayersCommand * changeBoardCommand = new ChangeBoardLayersCommand(this, m_boardLayers, newLayers, parentCommand); QList boards = findBoard(); foreach (ItemBase * board, boards) { new SetPropCommand(this, board->id(), "layers", QString::number(m_boardLayers), QString::number(newLayers), true, parentCommand); } if (newLayers == 2) { new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); return; } // disconnect and flip smds foreach (QGraphicsItem * item, scene()->items()) { ItemBase * smd = dynamic_cast(item); if (smd == NULL) continue; if (smd->moduleID().endsWith(ModuleIDNames::PadModuleIDName)) { pads << smd; continue; } if (!smd->modelPart()->flippedSMD()) continue; smd = smd->layerKinChief(); if (smds.contains(smd)) continue; smds.append(smd); } changeTraceLayer(NULL, true, changeBoardCommand); foreach (ItemBase * smd, smds) { long newID; emit subSwapSignal(this, smd, smd->moduleID(), (newLayers == 1) ? ViewLayer::NewBottom : ViewLayer::NewTop, newID, changeBoardCommand); } foreach (ItemBase * itemBase, pads) { Pad * pad = qobject_cast(itemBase); if (pad == NULL) continue; long newID; emit subSwapSignal(this, pad, (newLayers == 1) ? ModuleIDNames::Copper0PadModuleIDName : ModuleIDNames::PadModuleIDName, (newLayers == 1) ? ViewLayer::NewBottom : ViewLayer::NewTop, newID, changeBoardCommand); double w = pad->modelPart()->localProp("width").toDouble(); double h = pad->modelPart()->localProp("height").toDouble(); new ResizeBoardCommand(this, newID, w, h, w, h, parentCommand); } } bool PCBSketchWidget::isBoardLayerChange(ItemBase * itemBase, const QString & newModuleID, int & newLayers) { newLayers = m_boardLayers; if (!Board::isBoard(itemBase)) { // no change return false; } ModelPart * modelPart = referenceModel()->retrieveModelPart(newModuleID); if (modelPart == NULL) { // shouldn't happen return false; } QString slayers = modelPart->properties().value("layers", ""); if (slayers.isEmpty()) { // shouldn't happen return false; } bool ok; int layers = slayers.toInt(&ok); if (!ok) { // shouldn't happen return false; } newLayers = layers; return (m_boardLayers != layers); } void PCBSketchWidget::changeBoardLayers(int layers, bool doEmit) { setBoardLayers(layers, true); SketchWidget::changeBoardLayers(layers, doEmit); if (layers == 1) { this->setLayerActive(ViewLayer::Copper0, true); this->setLayerActive(ViewLayer::Silkscreen0, true); } emit updateLayerMenuSignal(); } void PCBSketchWidget::loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType crossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs) { int layers = 1; if (parentCommand == NULL) { foreach (ModelPart * modelPart, modelParts) { if (Board::isBoard(modelPart)) { QString slayers = modelPart->localProp("layers").toString(); if (slayers.isEmpty()) { slayers = modelPart->properties().value("layers", ""); } if (slayers.isEmpty()) { // shouldn't happen continue; } bool ok; int localLayers = slayers.toInt(&ok); if (!ok) { // shouldn't happen continue; } if (localLayers == 2) { layers = 2; break; } } else if (modelPart->itemType() == ModelPart::Wire) { QDomElement instance = modelPart->instanceDomElement(); QDomElement views = instance.firstChildElement("views"); QDomElement view = views.firstChildElement("pcbView"); if (view.attribute("layer").compare("copper1trace") == 0) { layers = 2; break; } } else if (modelPart->itemType() == ModelPart::CopperFill) { QDomElement instance = modelPart->instanceDomElement(); QDomElement views = instance.firstChildElement("views"); QDomElement view = views.firstChildElement("pcbView"); if (view.attribute("layer").compare("groundplane1") == 0) { layers = 2; break; } } } changeBoardLayers(layers, true); } SketchWidget::loadFromModelParts(modelParts, crossViewType, parentCommand, offsetPaste, boundingRect, seekOutsideConnections, newIDs); if (parentCommand == NULL) { changeBoardLayers(layers, true); shiftHoles(); } } bool PCBSketchWidget::isInLayers(ConnectorItem * connectorItem, ViewLayer::ViewLayerPlacement viewLayerPlacement) { return connectorItem->isInLayers(viewLayerPlacement); } bool PCBSketchWidget::routeBothSides() { return m_boardLayers > 1; } bool PCBSketchWidget::sameElectricalLayer2(ViewLayer::ViewLayerID id1, ViewLayer::ViewLayerID id2) { switch (id1) { case ViewLayer::Copper0Trace: if (id1 == id2) return true; return (id2 == ViewLayer::Copper0 || id2 == ViewLayer::GroundPlane0); case ViewLayer::Copper0: case ViewLayer::GroundPlane0: if (id1 == id2) return true; return (id2 == ViewLayer::Copper0Trace); case ViewLayer::Copper1Trace: if (id1 == id2) return true; return (id2 == ViewLayer::Copper1 || id2 == ViewLayer::GroundPlane1); case ViewLayer::Copper1: case ViewLayer::GroundPlane1: if (id1 == id2) return true; return (id2 == ViewLayer::Copper1Trace); default: break; } return false; } void PCBSketchWidget::changeTraceLayer(ItemBase * itemBase, bool force, QUndoCommand * parentCommand) { QList visitedWires; QSet changeWires; TraceWire * sample = NULL; QList items; if (itemBase != NULL) items << itemBase; else if (force) items = scene()->items(); else items = scene()->selectedItems(); foreach (QGraphicsItem * item, items) { TraceWire * tw = dynamic_cast(item); if (tw == NULL) continue; if (!tw->isTraceType(getTraceFlag())) continue; if (visitedWires.contains(tw)) continue; sample = tw; QList wires; QList ends; tw->collectChained(wires, ends); visitedWires.append(wires); if (!force) { bool canChange = true; foreach(ConnectorItem * end, ends) { if (end->getCrossLayerConnectorItem() == NULL) { canChange = false; break; } } if (!canChange) continue; } changeWires.insert(tw); } if (changeWires.count() == 0 || sample == NULL) return; bool createNew = false; if (parentCommand == NULL) { parentCommand = new QUndoCommand(tr("Change trace layer")); createNew = true; } ViewLayer::ViewLayerID newViewLayerID = (sample->viewLayerID() == ViewLayer::Copper0Trace) ? ViewLayer::Copper1Trace : ViewLayer::Copper0Trace; if (force) { // move all traces to bottom layer (force == true when switching from 2 layers to 1) newViewLayerID = ViewLayer::Copper0Trace; } foreach (Wire * wire, changeWires) { QList wires; QList ends; wire->collectChained(wires, ends); // probably safest to disconnect change the layers and reconnect, so that's why the redundant looping foreach (ConnectorItem * end, ends) { ConnectorItem * targetConnectorItem = NULL; foreach (ConnectorItem * toConnectorItem, end->connectedToItems()) { Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w == NULL) continue; if (wires.contains(w)) { targetConnectorItem = toConnectorItem; break; } } extendChangeConnectionCommand(BaseCommand::SingleView, targetConnectorItem, end, ViewLayer::specFromID(end->attachedToViewLayerID()), false, parentCommand); } foreach (Wire * w, wires) { new ChangeLayerCommand(this, w->id(), w->zValue(), m_viewLayers.value(newViewLayerID)->nextZ(), w->viewLayerID(), newViewLayerID, parentCommand); } foreach (ConnectorItem * end, ends) { ConnectorItem * targetConnectorItem = NULL; foreach (ConnectorItem * toConnectorItem, end->connectedToItems()) { Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w == NULL) continue; if (wires.contains(w)) { targetConnectorItem = toConnectorItem; break; } } new ChangeConnectionCommand(this, BaseCommand::SingleView, targetConnectorItem->attachedToID(), targetConnectorItem->connectorSharedID(), end->attachedToID(), end->connectorSharedID(), ViewLayer::specFromID(newViewLayerID), true, parentCommand); } } if (createNew) { m_undoStack->waitPush(parentCommand, PropChangeDelay); } } void PCBSketchWidget::changeLayer(long id, double z, ViewLayer::ViewLayerID viewLayerID) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; itemBase->setViewLayerID(viewLayerID, m_viewLayers); itemBase->setZValue(z); itemBase->saveGeometry(); TraceWire * tw = qobject_cast(itemBase); if (tw != NULL) { ViewLayer::ViewLayerPlacement viewLayerPlacement = ViewLayer::specFromID(viewLayerID); tw->setViewLayerPlacement(viewLayerPlacement); tw->setColorString(traceColor(viewLayerPlacement), 1.0, true); ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); tw->setInactive(!viewLayer->isActive()); tw->setHidden(!viewLayer->visible()); tw->update(); } updateInfoView(); } bool PCBSketchWidget::resizingJumperItemPress(ItemBase * itemBase) { if (itemBase == NULL) return false; JumperItem * jumperItem = qobject_cast(itemBase->layerKinChief()); if (jumperItem == NULL) return false; if (!jumperItem->inDrag()) return false; m_resizingJumperItem = jumperItem; m_resizingJumperItem->saveParams(); if (m_alignToGrid) { m_alignmentStartPoint = QPointF(0,0); ItemBase * board = findBoardBeneath(m_resizingJumperItem); QHash savedItems; QHash savedWires; if (board == NULL) { foreach (QGraphicsItem * item, scene()->items()) { PaletteItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->itemType() == ModelPart::Jumper) continue; savedItems.insert(itemBase->layerKinChief()->id(), itemBase); } } findAlignmentAnchor(board, savedItems, savedWires); m_jumperDragOffset = jumperItem->dragOffset(); connect(m_resizingJumperItem, SIGNAL(alignMe(JumperItem *, QPointF &)), this, SLOT(alignJumperItem(JumperItem *, QPointF &)), Qt::DirectConnection); } return true; } void PCBSketchWidget::alignJumperItem(JumperItem * jumperItem, QPointF & loc) { Q_UNUSED(jumperItem); if (!m_alignToGrid) return; QPointF newPos = loc - m_jumperDragOffset - m_alignmentStartPoint; double ny = GraphicsUtils::getNearestOrdinate(newPos.y(), gridSizeInches() * GraphicsUtils::SVGDPI); double nx = GraphicsUtils::getNearestOrdinate(newPos.x(), gridSizeInches() * GraphicsUtils::SVGDPI); loc.setX(loc.x() + nx - newPos.x()); loc.setY(loc.y() + ny - newPos.y()); } bool PCBSketchWidget::resizingJumperItemRelease() { if (m_resizingJumperItem == NULL) return false; if (m_alignToGrid) { disconnect(m_resizingJumperItem, SIGNAL(alignMe(JumperItem *, QPointF &)), this, SLOT(alignJumperItem(JumperItem *, QPointF &))); } resizeJumperItem(); return true; } void PCBSketchWidget::resizeJumperItem() { QPointF oldC0, oldC1; QPointF oldPos; m_resizingJumperItem->getParams(oldPos, oldC0, oldC1); QPointF newC0, newC1; QPointF newPos; m_resizingJumperItem->saveParams(); m_resizingJumperItem->getParams(newPos, newC0, newC1); QUndoCommand * cmd = new ResizeJumperItemCommand(this, m_resizingJumperItem->id(), oldPos, oldC0, oldC1, newPos, newC0, newC1, NULL); cmd->setText("Resize Jumper"); m_undoStack->waitPush(cmd, 10); m_resizingJumperItem = NULL; } bool PCBSketchWidget::canDragWire(Wire * wire) { if (wire == NULL) return false; if (wire->getRatsnest()) return false; return true; } void PCBSketchWidget::wireSplitSlot(Wire* wire, QPointF newPos, QPointF oldPos, const QLineF & oldLine) { if (!wire->getRatsnest()) { SketchWidget::wireSplitSlot(wire, newPos, oldPos, oldLine); } createTrace(wire, false); } ItemBase * PCBSketchWidget::addCopperLogoItem(ViewLayer::ViewLayerPlacement viewLayerPlacement) { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); QString moduleID = (viewLayerPlacement == ViewLayer::NewBottom) ? ModuleIDNames::Copper0LogoTextModuleIDName : ModuleIDNames::Copper1LogoTextModuleIDName; return addItem(referenceModel()->retrieveModelPart(moduleID), viewLayerPlacement, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); } bool PCBSketchWidget::hasAnyNets() { return m_routingStatus.m_netCount > 0; } QSizeF PCBSketchWidget::jumperItemSize() { if (m_jumperItemSize.width() == 0) { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); ItemBase * itemBase = addItem(referenceModel()->retrieveModelPart(ModuleIDNames::JumperModuleIDName), ViewLayer::NewTop, BaseCommand::SingleView, viewGeometry, newID, -1, NULL); if (itemBase) { JumperItem * jumperItem = qobject_cast(itemBase); m_jumperItemSize = jumperItem->connector0()->rect().size(); deleteItem(itemBase, true, false, false); } } return m_jumperItemSize; } double PCBSketchWidget::getKeepout() { QString keepoutString = m_autorouterSettings.value(DRC::KeepoutSettingName); if (keepoutString.isEmpty()) { QSettings settings; keepoutString = settings.value(DRC::KeepoutSettingName, "").toString(); } bool ok; double inches = TextUtils::convertToInches(keepoutString, &ok, false); if (!ok) { keepoutString = QString("%1in").arg(DRC::KeepoutDefaultMils / 1000); inches = DRC::KeepoutDefaultMils / 1000; } m_autorouterSettings.insert(DRC::KeepoutSettingName, keepoutString); return inches * GraphicsUtils::SVGDPI; // inches converted to pixels } void PCBSketchWidget::setKeepout(double mils) { QString keepoutString = QString("%1in").arg(mils / 1000); m_autorouterSettings.insert(DRC::KeepoutSettingName, keepoutString); } void PCBSketchWidget::resetKeepout() { setKeepout(DRC::KeepoutDefaultMils); } bool PCBSketchWidget::acceptsTrace(const ViewGeometry & viewGeometry) { return !viewGeometry.getSchematicTrace(); } ItemBase * PCBSketchWidget::placePartDroppedInOtherView(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, const ViewGeometry & viewGeometry, long id, SketchWidget * dropOrigin) { ItemBase * newItem = SketchWidget::placePartDroppedInOtherView(modelPart, viewLayerPlacement, viewGeometry, id, dropOrigin); if (newItem == NULL) return newItem; if (!newItem->isEverVisible()) return newItem; dealWithDefaultParts(); QList boards; if (autorouteTypePCB()) { boards = findBoard(); } else { boards << NULL; } foreach (ItemBase * board, boards) { // This is a 2d bin-packing problem. We can use our tile datastructure for this. // Use a simple best-fit approach for now. No idea how optimal a solution it is. CMRouter router(this, board, false); int keepout = 10; router.setKeepout(keepout); Plane * plane = router.initPlane(false); QList alreadyTiled; foreach (QGraphicsItem * item, (board) ? scene()->collidingItems(board) : scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isEverVisible()) continue; if (itemBase->layerKinChief() != itemBase) continue; if (itemBase->layerKinChief() == board) continue; if (itemBase->layerKinChief() == newItem) continue; Wire * wire = qobject_cast(itemBase); if (wire != NULL) { if (!wire->getTrace()) continue; if (!wire->isTraceType(getTraceFlag())) continue; } else if (ResizableBoard::isBoard(itemBase)) continue; // itemBase->debugInfo("tiling"); QRectF r = itemBase->sceneBoundingRect().adjusted(-keepout, -keepout, keepout, keepout); router.insertTile(plane, r, alreadyTiled, NULL, Tile::OBSTACLE, CMRouter::IgnoreAllOverlaps); } BestPlace bestPlace; bestPlace.maxRect = router.boardRect(); bestPlace.rotate90 = false; bestPlace.width = realToTile(newItem->boundingRect().width()); bestPlace.height = realToTile(newItem->boundingRect().height()); bestPlace.plane = plane; TiSrArea(NULL, plane, &bestPlace.maxRect, Panelizer::placeBestFit, &bestPlace); if (bestPlace.bestTile != NULL) { QRectF r; tileToQRect(bestPlace.bestTile, r); ItemBase * chief = newItem->layerKinChief(); chief->setPos(r.topLeft()); DebugDialog::debug(QString("placing part with rotation:%1").arg(bestPlace.rotate90), r); if (bestPlace.rotate90) { chief->rotateItem(90, false); } alignOneToGrid(newItem); } router.drcClean(); if (bestPlace.bestTile != NULL) { break; } } return newItem; } void PCBSketchWidget::autorouterSettings() { // initialize settings values if they haven't already been initialized getKeepout(); QString ringThickness, holeSize; getDefaultViaSize(ringThickness, holeSize); getAutorouterTraceWidth(); AutorouterSettingsDialog dialog(m_autorouterSettings); if (QDialog::Accepted == dialog.exec()) { m_autorouterSettings = dialog.getSettings(); QSettings settings; foreach (QString key, m_autorouterSettings.keys()) { settings.setValue(key, m_autorouterSettings.value(key)); } } } void PCBSketchWidget::getViaSize(double & ringThickness, double & holeSize) { QString ringThicknessStr, holeSizeStr; getDefaultViaSize(ringThicknessStr, holeSizeStr); double rt = TextUtils::convertToInches(ringThicknessStr); double hs = TextUtils::convertToInches(holeSizeStr); ringThickness = rt * GraphicsUtils::SVGDPI; holeSize = hs * GraphicsUtils::SVGDPI; } void PCBSketchWidget::getDefaultViaSize(QString & ringThickness, QString & holeSize) { // these settings are initialized in via.cpp ringThickness = m_autorouterSettings.value(Via::AutorouteViaRingThickness, ""); holeSize = m_autorouterSettings.value(Via::AutorouteViaHoleSize, ""); QSettings settings; if (ringThickness.isEmpty()) { ringThickness = settings.value(Via::AutorouteViaRingThickness, Via::DefaultAutorouteViaRingThickness).toString(); } if (holeSize.isEmpty()) { holeSize = settings.value(Via::AutorouteViaHoleSize, Via::DefaultAutorouteViaHoleSize).toString(); } m_autorouterSettings.insert(Via::AutorouteViaRingThickness, ringThickness); m_autorouterSettings.insert(Via::AutorouteViaHoleSize, holeSize); } void PCBSketchWidget::deleteItem(ItemBase * itemBase, bool deleteModelPart, bool doEmit, bool later) { bool boardDeleted = Board::isBoard(itemBase); SketchWidget::deleteItem(itemBase, deleteModelPart, doEmit, later); if (boardDeleted) { if (findBoard().count() == 0) { emit boardDeletedSignal(); } requestQuoteSoon(); } } double PCBSketchWidget::getTraceWidth() { return Wire::STANDARD_TRACE_WIDTH; } double PCBSketchWidget::getAutorouterTraceWidth() { QString traceWidthString = m_autorouterSettings.value(AutorouterSettingsDialog::AutorouteTraceWidth, ""); if (traceWidthString.isEmpty()) { QSettings settings; QString def = QString::number(GraphicsUtils::pixels2mils(getTraceWidth(), GraphicsUtils::SVGDPI)); traceWidthString = settings.value(AutorouterSettingsDialog::AutorouteTraceWidth, def).toString(); } m_autorouterSettings.insert(AutorouterSettingsDialog::AutorouteTraceWidth, traceWidthString); return GraphicsUtils::SVGDPI * traceWidthString.toInt() / 1000.0; // traceWidthString is in mils } void PCBSketchWidget::getBendpointWidths(Wire * wire, double width, double & bendpointWidth, double & bendpoint2Width, bool & negativeOffsetRect) { Q_UNUSED(wire); bendpointWidth = bendpoint2Width = (width / -2); negativeOffsetRect = false; } double PCBSketchWidget::getSmallerTraceWidth(double minDim) { int mils = qMax((int) GraphicsUtils::pixels2mils(minDim, GraphicsUtils::SVGDPI) - 1, TraceWire::MinTraceWidthMils); return GraphicsUtils::mils2pixels(mils, GraphicsUtils::SVGDPI); } bool PCBSketchWidget::groundFill(bool fillGroundTraces, ViewLayer::ViewLayerID viewLayerID, QUndoCommand * parentCommand) { m_groundFillSeeds = NULL; int boardCount; ItemBase * board = findSelectedBoard(boardCount); // barf an error if there's no board if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill.")); return false; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("%1 Fill: please select the board you want to apply fill to.").arg(fillGroundTraces ? tr("Ground") : tr("Copper"))); return false; } QList seeds; if (fillGroundTraces) { bool gotTrueSeeds = collectGroundFillSeeds(seeds, false); if (!gotTrueSeeds && (seeds.count() != 1)) { QString message = tr("Please designate one or more ground fill seeds before doing a ground fill.\n\n"); setGroundFillSeeds(message); return false; } ConnectorItem::collectEqualPotential(seeds, true, ViewGeometry::NoFlag); //foreach (ConnectorItem * seed, seeds) { // seed->debugInfo("seed"); //} m_groundFillSeeds = &seeds; } LayerList viewLayerIDs; viewLayerIDs << ViewLayer::Board; QRectF boardImageRect, copperImageRect; RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString boardSvg = renderToSVG(renderThing, board, viewLayerIDs); if (boardSvg.isEmpty()) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to render board svg (1).")); return false; } boardImageRect = renderThing.imageRect; renderThing.renderBlocker = true; QString svg0; if (viewLayerID == ViewLayer::UnknownLayer || viewLayerID == ViewLayer::GroundPlane0) { viewLayerIDs.clear(); viewLayerIDs << ViewLayer::Copper0 << ViewLayer::Copper0Trace << ViewLayer::GroundPlane0; // hide ground traces so the ground plane will intersect them if (fillGroundTraces) showGroundTraces(seeds, false); svg0 = renderToSVG(renderThing, board, viewLayerIDs); if (fillGroundTraces) showGroundTraces(seeds, true); if (svg0.isEmpty()) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to render copper svg (1).")); return false; } copperImageRect = renderThing.imageRect; } QString svg1; if (boardLayers() > 1 && (viewLayerID == ViewLayer::UnknownLayer || viewLayerID == ViewLayer::GroundPlane1)) { viewLayerIDs.clear(); viewLayerIDs << ViewLayer::Copper1 << ViewLayer::Copper1Trace << ViewLayer::GroundPlane1; if (fillGroundTraces) showGroundTraces(seeds, false); svg1 = renderToSVG(renderThing, board, viewLayerIDs); if (fillGroundTraces) showGroundTraces(seeds, true); if (svg1.isEmpty()) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to render copper svg (1).")); return false; } copperImageRect = renderThing.imageRect; } QStringList exceptions; exceptions << "none" << "" << background().name(); // the color of holes in the board GroundPlaneGenerator gpg0; if (!svg0.isEmpty()) { gpg0.setLayerName("groundplane"); gpg0.setStrokeWidthIncrement(StrokeWidthIncrement); gpg0.setMinRunSize(10, 10); if (fillGroundTraces) { connect(&gpg0, SIGNAL(postImageSignal(GroundPlaneGenerator *, QImage *, QImage *, QGraphicsItem *, QList *)), this, SLOT(postImageSlot(GroundPlaneGenerator *, QImage *, QImage *, QGraphicsItem *, QList *)), Qt::DirectConnection); } bool result = gpg0.generateGroundPlane(boardSvg, boardImageRect.size(), svg0, copperImageRect.size(), exceptions, board, GraphicsUtils::StandardFritzingDPI / 2.0 /* 2 MIL */, ViewLayer::Copper0Color, getKeepoutMils()); if (result == false) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to write copper fill (1).")); return false; } } GroundPlaneGenerator gpg1; if (boardLayers() > 1 && !svg1.isEmpty()) { gpg1.setLayerName("groundplane1"); gpg1.setStrokeWidthIncrement(StrokeWidthIncrement); gpg1.setMinRunSize(10, 10); if (fillGroundTraces) { connect(&gpg1, SIGNAL(postImageSignal(GroundPlaneGenerator *, QImage *, QImage *, QGraphicsItem *, QList *)), this, SLOT(postImageSlot(GroundPlaneGenerator *, QImage *, QImage *, QGraphicsItem *, QList *)), Qt::DirectConnection); } bool result = gpg1.generateGroundPlane(boardSvg, boardImageRect.size(), svg1, copperImageRect.size(), exceptions, board, GraphicsUtils::StandardFritzingDPI / 2.0 /* 2 MIL */, ViewLayer::Copper1Color, getKeepoutMils()); if (result == false) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to write copper fill (2).")); return false; } } QString fillType = (fillGroundTraces) ? GroundPlane::fillTypeGround : GroundPlane::fillTypePlain; QRectF bsbr = board->sceneBoundingRect(); int ix = 0; foreach (QString svg, gpg0.newSVGs()) { ViewGeometry vg; vg.setLoc(bsbr.topLeft() + gpg0.newOffsets()[ix++]); long newID = ItemBase::getNextID(); new AddItemCommand(this, BaseCommand::CrossView, ModuleIDNames::GroundPlaneModuleIDName, ViewLayer::NewBottom, vg, newID, false, -1, parentCommand); new SetPropCommand(this, newID, "svg", svg, svg, true, parentCommand); new SetPropCommand(this, newID, "fillType", fillType, fillType, false, parentCommand); } ix = 0; foreach (QString svg, gpg1.newSVGs()) { ViewGeometry vg; vg.setLoc(bsbr.topLeft() + gpg1.newOffsets()[ix++]); long newID = ItemBase::getNextID(); new AddItemCommand(this, BaseCommand::CrossView, ModuleIDNames::GroundPlaneModuleIDName, ViewLayer::NewTop, vg, newID, false, -1, parentCommand); new SetPropCommand(this, newID, "svg", svg, svg, true, parentCommand); new SetPropCommand(this, newID, "fillType", fillType, fillType, false, parentCommand); } return true; } QString PCBSketchWidget::generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart) { int boardCount; ItemBase * board = findSelectedBoard(boardCount); // barf an error if there's no board if (boardCount == 0) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill.")); return ""; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Copper fill: please select only the board you want to fill.")); return ""; } QRectF bsbr = board->sceneBoundingRect(); if (!bsbr.contains(whereToStart)) { QMessageBox::critical(this, tr("Fritzing"), tr("Unable to create copper fill--probably the part wasn't dropped onto the PCB.")); return ""; } LayerList viewLayerIDs; viewLayerIDs << ViewLayer::Board; QRectF boardImageRect, copperImageRect; RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString boardSvg = renderToSVG(renderThing, board, viewLayerIDs); if (boardSvg.isEmpty()) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to render board svg (1).")); return ""; } boardImageRect = renderThing.imageRect; ViewLayer::ViewLayerPlacement viewLayerPlacement = ViewLayer::NewBottom; QString color = ViewLayer::Copper0Color; QString gpLayerName = "groundplane"; if (m_boardLayers == 2 && !dropOnBottom()) { gpLayerName += "1"; color = ViewLayer::Copper1Color; viewLayerPlacement = ViewLayer::NewTop; } viewLayerIDs = ViewLayer::copperLayers(viewLayerPlacement); bool vis = itemBase->isVisible(); itemBase->setVisible(false); renderThing.renderBlocker = true; QString svg = renderToSVG(renderThing, board, viewLayerIDs); itemBase->setVisible(vis); if (svg.isEmpty()) { QMessageBox::critical(this, tr("Fritzing"), tr("Fritzing error: unable to render copper svg (1).")); return ""; } copperImageRect = renderThing.imageRect; QStringList exceptions; exceptions << "none" << "" << background().name(); // the color of holes in the board GroundPlaneGenerator gpg; gpg.setStrokeWidthIncrement(StrokeWidthIncrement); gpg.setLayerName(gpLayerName); gpg.setMinRunSize(10, 10); bool result = gpg.generateGroundPlaneUnit(boardSvg, boardImageRect.size(), svg, copperImageRect.size(), exceptions, board, GraphicsUtils::StandardFritzingDPI / 2.0 /* 2 MIL */, color, whereToStart, getKeepoutMils()); if (result == false || gpg.newSVGs().count() < 1) { QMessageBox::critical(this, tr("Fritzing"), tr("Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.")); return ""; } itemBase->setPos(bsbr.topLeft() + gpg.newOffsets()[0]); itemBase->setViewLayerID(gpLayerName, m_viewLayers); return gpg.newSVGs()[0]; } bool PCBSketchWidget::connectorItemHasSpec(ConnectorItem * connectorItem, ViewLayer::ViewLayerPlacement spec) { if (ViewLayer::specFromID(connectorItem->attachedToViewLayerID()) == spec) return true; connectorItem = connectorItem->getCrossLayerConnectorItem(); if (connectorItem == NULL) return false; return (ViewLayer::specFromID(connectorItem->attachedToViewLayerID()) == spec); } ViewLayer::ViewLayerPlacement PCBSketchWidget::createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to) { QList guesses; guesses.append(layerIsActive(ViewLayer::Copper0) ? ViewLayer::NewBottom : ViewLayer::NewTop); guesses.append(layerIsActive(ViewLayer::Copper0) ? ViewLayer::NewTop : ViewLayer::NewBottom); foreach (ViewLayer::ViewLayerPlacement guess, guesses) { if (connectorItemHasSpec(from, guess) && connectorItemHasSpec(to, guess)) { return guess; } } return ViewLayer::UnknownPlacement; } double PCBSketchWidget::getWireStrokeWidth(Wire * wire, double wireWidth) { double w, h; wire->originalConnectorDimensions(w, h); if (wireWidth < Wire::THIN_TRACE_WIDTH) { wire->setConnectorDimensions(qMin(w, wireWidth + 1), qMin(w, wireWidth + 1)); } if (wireWidth < Wire::STANDARD_TRACE_WIDTH) { wire->setConnectorDimensions(qMin(w, wireWidth + 1.5), qMin(w, wireWidth + 1.5)); } else { wire->setConnectorDimensions(w, h); } return wireWidth + 6; } Wire * PCBSketchWidget::createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement spec) { if (spec == ViewLayer::UnknownPlacement) { spec = wireViewLayerPlacement(connectorItem); } viewGeometry.setPCBTrace(true); Wire * wire = SketchWidget::createTempWireForDragging(fromWire, wireModel, connectorItem, viewGeometry, spec); if (fromWire == NULL) { wire->setColorString(traceColor(connectorItem), 1.0, false); double traceWidth = getTraceWidth(); double minDim = connectorItem->minDimension(); if (minDim < traceWidth) { traceWidth = getSmallerTraceWidth(minDim); } wire->setWireWidth(traceWidth, this, getWireStrokeWidth(wire, traceWidth)); wire->setProperty(FakeTraceProperty, true); } else { wire->setColorString(fromWire->colorString(), fromWire->opacity(), false); wire->setWireWidth(fromWire->width(), this, fromWire->hoverStrokeWidth()); } return wire; } void PCBSketchWidget::prereleaseTempWireForDragging(Wire* wire) { if (wire->property(PCBSketchWidget::FakeTraceProperty).toBool()) { // make it not look like a trace, or modifyNewWireConnections will create the wrong kind of wire wire->setWireFlags(0); } } void PCBSketchWidget::rotatePartLabels(double degrees, QTransform & transform, QPointF center, QUndoCommand * parentCommand) { QList savedValues = m_savedItems.values(); /* QSet boards; foreach (ItemBase * itemBase, savedValues) { if (Board::isBoard(itemBase)) { boards.insert(itemBase); } } if (boards.count() == 0) return; QRectF bbr; foreach (ItemBase * board, boards.values()) { bbr |= board->sceneBoundingRect(); } */ foreach (QGraphicsItem * item, scene()->items()) { PartLabel * partLabel = dynamic_cast(item); if (partLabel == NULL) continue; if (!partLabel->isVisible()) continue; //if (!bbr.intersects(partLabel->sceneBoundingRect())) continue; // if the part is on the board and the label is off the board, this does not rotate if (!savedValues.contains(partLabel->owner()->layerKinChief())) continue; QPointF offset = partLabel->pos() - partLabel->owner()->pos(); new MoveLabelCommand(this, partLabel->owner()->id(), partLabel->pos(), offset, partLabel->pos(), offset, parentCommand); new RotateFlipLabelCommand(this, partLabel->owner()->id(), degrees, 0, parentCommand); QPointF p = GraphicsUtils::calcRotation(transform, center, partLabel->pos(), partLabel->boundingRect().center()); ViewGeometry vg; partLabel->owner()->calcRotation(transform, center, vg); new MoveLabelCommand(this, partLabel->owner()->id(), p, p - vg.loc(), p, p - vg.loc(), parentCommand); } } QString PCBSketchWidget::characterizeGroundFill(ViewLayer::ViewLayerID whichGroundPlane) { QString result = GroundPlane::fillTypeNone; bool gotOne = false; int boardCount; ItemBase * board = findSelectedBoard(boardCount); foreach (QGraphicsItem * item, scene()->collidingItems(board)) { GroundPlane * gp = dynamic_cast(item); if (gp == NULL) continue; if (gp->viewLayerID() == whichGroundPlane) { gotOne = true; break; } } if (!gotOne) return result; foreach (QGraphicsItem * item, scene()->items()) { GroundPlane * gp = dynamic_cast(item); if (gp == NULL) continue; if (gp->viewLayerID() != whichGroundPlane) continue; QString fillType = gp->prop("fillType"); if (fillType.isEmpty()) { // old style fill with no property return GroundPlane::fillTypeGround; } if (fillType == GroundPlane::fillTypeGround) { // assumes multiple fill types are not possible return fillType; } if (fillType == GroundPlane::fillTypePlain) { // assumes multiple fill types are not possible return fillType; } result = fillType; } return result; } void PCBSketchWidget::setUpColor(ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Wire * wire, QUndoCommand * parentCommand) { QString tc = traceColor(fromConnectorItem); new WireColorChangeCommand(this, wire->id(), tc, tc, 1.0, 1.0, parentCommand); double traceWidth = getTraceWidth(); if (autorouteTypePCB()) { double minDim = qMin(fromConnectorItem->minDimension(), toConnectorItem->minDimension()); if (minDim < traceWidth) { traceWidth = getSmallerTraceWidth(minDim); } } new WireWidthChangeCommand(this, wire->id(), traceWidth, traceWidth, parentCommand); } ViewGeometry::WireFlag PCBSketchWidget::getTraceFlag() { return ViewGeometry::PCBTraceFlag; } void PCBSketchWidget::postImageSlot(GroundPlaneGenerator * gpg, QImage * copperImage, QImage * boardImage, QGraphicsItem * board, QList * rects) { if (m_groundFillSeeds == NULL) return; ViewLayer::ViewLayerID viewLayerID = (gpg->layerName() == "groundplane") ? ViewLayer::Copper0 : ViewLayer::Copper1; QRectF boardRect = board->sceneBoundingRect(); foreach (ConnectorItem * connectorItem, *m_groundFillSeeds) { if (connectorItem->attachedToViewLayerID() != viewLayerID) continue; if (connectorItem->attachedToItemType() == ModelPart::Wire) continue; if (!connectorItem->attachedTo()->isEverVisible()) continue; //connectorItem->debugInfo("post image b"); QRectF r = connectorItem->sceneBoundingRect(); //DebugDialog::debug("pb", r); QRectF check = r; check.setLeft(r.right()); check.setRight(r.right() + r.width()); bool checkRight = !hasNeighbor(connectorItem, viewLayerID, check); check = r; check.setLeft(r.left() - r.width()); check.setRight(r.left()); bool checkLeft = !hasNeighbor(connectorItem, viewLayerID, check); check = r; check.setTop(r.bottom()); check.setBottom(r.bottom() + r.height()); bool checkDown = !hasNeighbor(connectorItem, viewLayerID, check); check = r; check.setTop(r.top() - r.width()); check.setBottom(r.top()); bool checkUp = !hasNeighbor(connectorItem, viewLayerID, check); double x1 = (r.left() - boardRect.left()) * copperImage->width() / boardRect.width(); double x2 = (r.right() - boardRect.left()) * copperImage->width() / boardRect.width(); double y1 = (r.top() - boardRect.top()) * copperImage->height() / boardRect.height(); double y2 = (r.bottom() - boardRect.top()) * copperImage->height() / boardRect.height(); double w = x2 - x1; double h = y2 - y1; double cw = w / 4; double ch = h / 4; int cx = (x1 + x2) /2; int cy = (y1 + y2) /2; int rad = qFloor(connectorItem->calcClipRadius() * copperImage->width() / boardRect.width()); double borderl = qMax(0.0, x1 - w); double borderr = qMin(x2 + w, copperImage->width()); double bordert = qMax(0.0, y1 - h); double borderb = qMin(y2 + h, copperImage->height()); // check left, up, right, down for groundplane, and if it's there draw to it from the connector if (checkUp){ for (int y = y1; y > bordert; y--) { if ((copperImage->pixel(cx, y) & 0xffffff) || (boardImage->pixel(cx, y) == 0xff000000)) { QRectF s(cx - cw, y - 1, cw + cw, cy - y - rad); rects->append(s); break; } } } if (checkDown) { for (int y = y2; y < borderb; y++) { if ((copperImage->pixel(cx, y) & 0xffffff) || (boardImage->pixel(cx, y) == 0xff000000)) { QRectF s(cx - cw, cy + rad, cw + cw, y - cy - rad); rects->append(s); break; } } } if (checkLeft) { for (int x = x1; x > borderl; x--) { if ((copperImage->pixel(x, cy) & 0xffffff) || (boardImage->pixel(x, cy) == 0xff000000)) { QRectF s(x - 1, cy - ch, cx - x - rad, ch + ch); rects->append(s); break; } } } if (checkRight) { for (int x = x2; x < borderr; x++) { if ((copperImage->pixel(x, cy) & 0xffffff) || (boardImage->pixel(x, cy) == 0xff000000)) { QRectF s(cx + rad, cy - ch, x - cx - rad, ch + ch); rects->append(s); break; } } } DebugDialog::debug(QString("x1:%1 y1:%2 x2:%3 y2:%4").arg(x1).arg(y1).arg(x2).arg(y2)); } } bool PCBSketchWidget::hasNeighbor(ConnectorItem * connectorItem, ViewLayer::ViewLayerID viewLayerID, const QRectF & r) { foreach (QGraphicsItem * item, scene()->items(r)) { ConnectorItem * ci = dynamic_cast(item); if (ci != NULL) { if (ci->attachedToViewLayerID() != viewLayerID) continue; if (!ci->attachedTo()->isEverVisible()) continue; if (ci == connectorItem) continue; return true; } TraceWire * traceWire = dynamic_cast(item); if (traceWire != NULL) { if (!sameElectricalLayer2(traceWire->viewLayerID(), viewLayerID)) continue; if (!traceWire->isTraceType(getTraceFlag())) continue; return true; } } return false; } void PCBSketchWidget::collectThroughHole(QList & th, QList & pads, const LayerList & layerList) { foreach (QGraphicsItem * item, scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->attachedTo()->isVisible()) continue; if (!layerList.contains(connectorItem->attachedToViewLayerID())) continue; if (connectorItem->attachedTo()->moduleID().endsWith(ModuleIDNames::PadModuleIDName)) { pads.append(connectorItem); continue; } if (connectorItem->attachedTo()->modelPart()->flippedSMD()) { pads.append(connectorItem); continue; } th << connectorItem; } } void PCBSketchWidget::hideCopperLogoItems(QList & copperLogoItems) { foreach (QGraphicsItem * item, this->items()) { CopperLogoItem * logoItem = dynamic_cast(item); if (logoItem && logoItem->isVisible()) { copperLogoItems.append(logoItem); logoItem->setVisible(false); } } } void PCBSketchWidget::hideHoles(QList & holes) { foreach (QGraphicsItem * item, this->items()) { ItemBase * itemBase = dynamic_cast(item); // for some reason the layerkin of the hole doesn't have a modelPart->itemType() == ModelPart::Hole if (itemBase && itemBase->isVisible() && itemBase->layerKinChief()->modelPart()->itemType() == ModelPart::Hole) { holes.append(itemBase); itemBase->setVisible(false); } } } void PCBSketchWidget::restoreCopperLogoItems(QList & copperLogoItems) { foreach (ItemBase * logoItem, copperLogoItems) { logoItem->setVisible(true); } } void PCBSketchWidget::clearGroundFillSeeds() { QList trueSeeds; int boardCount; ItemBase * board = findSelectedBoard(boardCount); if (board == NULL) return; foreach (QGraphicsItem * item, scene()->collidingItems(board)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (connectorItem->attachedToItemType() == ModelPart::CopperFill) continue; if (connectorItem->isGroundFillSeed()) { trueSeeds.append(connectorItem); continue; } } if (trueSeeds.count() == 0) return; GroundFillSeedCommand * command = new GroundFillSeedCommand(this, NULL); command->setText(tr("Clear ground fill seeds")); foreach (ConnectorItem * connectorItem, trueSeeds) { command->addItem(connectorItem->attachedToID(), connectorItem->connectorSharedID(), false); } m_undoStack->waitPush(command, PropChangeDelay); } void PCBSketchWidget::setGroundFillSeeds() { setGroundFillSeeds(""); } void PCBSketchWidget::setGroundFillSeeds(const QString & intro) { QList seeds; collectGroundFillSeeds(seeds, true); GroundFillSeedDialog gfsd(this, seeds, intro, NULL); int result = gfsd.exec(); if (result == QDialog::Accepted) { GroundFillSeedCommand * command = NULL; QList results; gfsd.getResults(results); bool checked = false; for (int i = 0; i < seeds.count(); i++) { ConnectorItem * ci = seeds.at(i); bool isSeed = results.at(i); checked |= isSeed; if (isSeed != ci->isGroundFillSeed()) { if (command == NULL) { command = new GroundFillSeedCommand(this, NULL); } command->addItem(ci->attachedToID(), ci->connectorSharedID(), isSeed); } } if (command) { m_undoStack->push(command); } if (gfsd.getFill()) { if (checked) emit groundFillSignal(); else emit copperFillSignal(); } } } bool PCBSketchWidget::collectGroundFillSeeds(QList & seeds, bool includePotential) { QList trueSeeds; QList potentialSeeds; int boardCount; ItemBase * board = findSelectedBoard(boardCount); if (board == NULL) return false; foreach (QGraphicsItem * item, scene()->collidingItems(board)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (connectorItem->attachedToItemType() == ModelPart::CopperFill) continue; if (connectorItem->isGroundFillSeed()) { trueSeeds.append(connectorItem); continue; } if (connectorItem->isGrounded()) { potentialSeeds.append(connectorItem); } } for (int ix = 0; ix < trueSeeds.count(); ix++) { ConnectorItem * ci = trueSeeds.at(ix); QList cis; cis.append(ci); ConnectorItem::collectEqualPotential(cis, true, ViewGeometry::NoFlag); foreach (ConnectorItem * eq, cis) { if (eq != ci) trueSeeds.removeAll(eq); potentialSeeds.removeAll(eq); } } for (int ix = 0; ix < potentialSeeds.count(); ix++) { ConnectorItem * ci = potentialSeeds.at(ix); QList cis; cis.append(ci); ConnectorItem::collectEqualPotential(cis, true, ViewGeometry::NoFlag); foreach (ConnectorItem * eq, cis) { if (eq != ci) potentialSeeds.removeAll(eq); } } seeds.append(trueSeeds); if (trueSeeds.count() == 0 || includePotential) { seeds.append(potentialSeeds); } return trueSeeds.count() > 0; } void PCBSketchWidget::shiftHoles() { // vias and holes before version 0.7.3 did not have offset VersionThing versionThingOffset; versionThingOffset.majorVersion = 0; versionThingOffset.minorVersion = 7; versionThingOffset.minorSubVersion = 2; versionThingOffset.releaseModifier = "b"; VersionThing versionThingFz; Version::toVersionThing(m_sketchModel->fritzingVersion(), versionThingFz); bool doShift = !Version::greaterThan(versionThingOffset, versionThingFz); if (!doShift) return; foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; switch (itemBase->itemType()) { case ModelPart::Via: case ModelPart::Hole: itemBase->setPos(itemBase->pos().x() - (Hole::OffsetPixels / 2), itemBase->pos().y() - (Hole::OffsetPixels / 2)); break; default: continue; } } } bool PCBSketchWidget::canAlignToCenter(ItemBase * itemBase) { return qobject_cast(itemBase) != NULL; } int PCBSketchWidget::selectAllItemType(ModelPart::ItemType itemType, const QString & typeName) { int boardCount; ItemBase * board = findSelectedBoard(boardCount); if (boardCount == 0 && autorouteTypePCB()) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use this selection operation.")); return 0; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please click on a PCB first--this selection operation only works for one board at a time.")); return 0; } QSet itemBases; foreach (QGraphicsItem * item, (board == NULL ? scene()->items() : scene()->collidingItems(board))) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->itemType() != itemType) continue; itemBases.insert(itemBase->layerKinChief()); } return selectAllItems(itemBases, QObject::tr("Select all %1").arg(typeName)); } void PCBSketchWidget::selectAllWires(ViewGeometry::WireFlag flag) { int boardCount; ItemBase * board = findSelectedBoard(boardCount); if (boardCount == 0 && autorouteTypePCB()) { QMessageBox::critical(this, tr("Fritzing"), tr("Your sketch does not have a board yet! Please add a PCB in order to use this selection operation.")); return; } if (board == NULL) { QMessageBox::critical(this, tr("Fritzing"), tr("Please click on a PCB first--this selection operation only works for one board at a time.")); return; } QList items = scene()->collidingItems(board); selectAllWiresFrom(flag, items); } ViewLayer::ViewLayerPlacement PCBSketchWidget::defaultViewLayerPlacement(ModelPart * modelPart) { if (modelPart == NULL || boardLayers() == 2) return SketchWidget::defaultViewLayerPlacement(modelPart); if (modelPart->flippedSMD()) return ViewLayer::NewBottom; if (modelPart->moduleID() == ModuleIDNames::GroundPlaneModuleIDName) return ViewLayer::NewBottom; return SketchWidget::defaultViewLayerPlacement(modelPart); } QString PCBSketchWidget::checkDroppedModuleID(const QString & moduleID) { if (moduleID.endsWith(ModuleIDNames::CopperBlockerModuleIDName)) { if (dropOnBottom()) return ModuleIDNames::Copper0BlockerModuleIDName; return ModuleIDNames::Copper1BlockerModuleIDName; } if (moduleID.endsWith(ModuleIDNames::PadModuleIDName)) { if (dropOnBottom()) return ModuleIDNames::Copper0PadModuleIDName; return ModuleIDNames::PadModuleIDName; } if (moduleID.endsWith(ModuleIDNames::RectanglePCBModuleIDName)) { if (boardLayers() == 2) return ModuleIDNames::TwoSidedRectanglePCBModuleIDName; return ModuleIDNames::RectanglePCBModuleIDName; } if (moduleID.endsWith(ModuleIDNames::EllipsePCBModuleIDName)) { if (boardLayers() == 2) return ModuleIDNames::TwoSidedEllipsePCBModuleIDName; return ModuleIDNames::EllipsePCBModuleIDName; } return moduleID; } void PCBSketchWidget::convertToVia(ConnectorItem * lastHoverEnterConnectorItem) { Wire * wire = qobject_cast(lastHoverEnterConnectorItem->attachedTo()); if (wire == NULL) return; this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(QObject::tr("Convert to Via")); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); double ringThickness, holeSize; getViaSize(ringThickness, holeSize); QPointF p = lastHoverEnterConnectorItem->sceneAdjustedTerminalPoint(NULL); double d = ringThickness + (holeSize / 2) + Via::OffsetPixels; QPointF loc(p.x() - d, p.y() - d); long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(loc); new AddItemCommand(this, BaseCommand::CrossView, ModuleIDNames::ViaModuleIDName, wire->viewLayerPlacement(), viewGeometry, newID, true, -1, parentCommand); QList connectorItems; connectorItems.append(lastHoverEnterConnectorItem); for (int i = 0; i < connectorItems.count(); i++) { ConnectorItem * from = connectorItems.at(i); foreach (ConnectorItem * to, from->connectedToItems()) { Wire * w = qobject_cast(to->attachedTo()); if (w != NULL && w->isTraceType(getTraceFlag())) { if (!connectorItems.contains(to)) { connectorItems.append(to); } } } } foreach (ConnectorItem * from, connectorItems) { foreach (ConnectorItem * to, from->connectedToItems()) { Wire * w = qobject_cast(to->attachedTo()); if (w != NULL && w->isTraceType(getTraceFlag())) { new ChangeConnectionCommand(this, BaseCommand::CrossView, from->attachedToID(), from->connectorSharedID(), to->attachedToID(), to->connectorSharedID(), ViewLayer::specFromID(w->viewLayerID()), false, parentCommand); } } } foreach (ConnectorItem * from, connectorItems) { new ChangeConnectionCommand(this, BaseCommand::CrossView, from->attachedToID(), from->connectorSharedID(), newID, "connector0", ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); } SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->addRedo(newID); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void PCBSketchWidget::convertToBendpoint() { ItemBase * itemBase = NULL; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * candidate = dynamic_cast(item); if (candidate == NULL) continue; if (itemBase == NULL) itemBase = candidate->layerKinChief(); else if (candidate->layerKinChief() != itemBase) return; } Via * via = dynamic_cast(itemBase); if (via == NULL) return; QList viaConnectorItems; viaConnectorItems << via->connectorItem(); if (via->connectorItem()->getCrossLayerConnectorItem()) { viaConnectorItems << via->connectorItem()->getCrossLayerConnectorItem(); } QList targets; int copper0 = 0; int copper1 = 0; bool copper0Only = false; bool copper1Only = false; foreach (ConnectorItem * viaConnectorItem, viaConnectorItems) { foreach (ConnectorItem * connectorItem, viaConnectorItem->connectedToItems()) { Wire * wire = qobject_cast(connectorItem->attachedTo()); if (wire == NULL) continue; if (wire->getRatsnest()) continue; if (!wire->isTraceType(getTraceFlag())) continue; bool gotOne = false;; if (wire->viewLayerID() == ViewLayer::Copper0Trace) { copper0++; gotOne = true; } else if (wire->viewLayerID() == ViewLayer::Copper1Trace) { copper1++; gotOne = true; } if (!gotOne) continue; targets.append(connectorItem); QList wires; QList ends; wire->collectChained(wires, ends); foreach (ConnectorItem * end, ends) { if (end->getCrossLayerConnectorItem() == NULL) { if (ViewLayer::copperLayers(ViewLayer::NewTop).contains(end->attachedToViewLayerID())) { copper1Only = true; } else { copper0Only = true; } } } } } if (copper0Only && copper1Only) { QMessageBox::warning(this, tr("Fritzing"), tr("Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer.")); return; } this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(QObject::tr("Convert Via to Bendpoint")); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); foreach (ConnectorItem * target, targets) { new ChangeConnectionCommand(this, BaseCommand::CrossView, target->attachedToID(), target->connectorSharedID(), via->id(), via->connectorItem()->connectorSharedID(), ViewLayer::specFromID(target->attachedToViewLayerID()), false, parentCommand); } ViewLayer::ViewLayerID dest = ViewLayer::Copper0Trace; if (copper1Only) { dest = ViewLayer::Copper1Trace; } else if (!copper0Only) { if (copper1 > copper0) { dest = ViewLayer::Copper1Trace; } } if (copper0 > 0 && copper1 > 0) { foreach (ConnectorItem * target, targets) { if (target->attachedToViewLayerID() == dest) continue; Wire * wire = qobject_cast(target->attachedTo()); QList wires; QList ends; wire->collectChained(wires, ends); foreach (Wire * w, wires) { new ChangeLayerCommand(this, w->id(), w->zValue(), m_viewLayers.value(dest)->nextZ(), w->viewLayerID(), dest, parentCommand); } } } ConnectorItem * from = targets.at(0); for (int j = 1; j < targets.count(); j++) { ConnectorItem * to = targets.at(j); new ChangeConnectionCommand(this, BaseCommand::CrossView, from->attachedToID(), from->connectorSharedID(), to->attachedToID(), to->connectorSharedID(), ViewLayer::specFromID(dest), true, parentCommand); } makeDeleteItemCommand(via, BaseCommand::CrossView, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } bool PCBSketchWidget::canConnect(Wire * from, ItemBase * to) { to = to->layerKinChief(); QList kin; kin.append(to); kin.append(to->layerKin()); foreach (ItemBase * itemBase, kin) { if (!ViewLayer::isCopperLayer(itemBase->viewLayerID())) continue; if (ViewLayer::canConnect(from->viewLayerID(), itemBase->viewLayerID())) return true; } return false; } QString PCBSketchWidget::makePasteMask(const QString & svgMask, ItemBase * board, double dpi, const LayerList & maskLayerIDs) { QList throughHoles; QList pads; collectThroughHole(throughHoles, pads, maskLayerIDs); if (pads.count() == 0) return ""; QRectF boardRect = board->sceneBoundingRect(); QList connectorRects; foreach (ConnectorItem * connectorItem, throughHoles) { QRectF r = connectorItem->sceneBoundingRect(); QRectF s((r.left() - boardRect.left()) * dpi / GraphicsUtils::SVGDPI, (r.top() - boardRect.top()) * dpi / GraphicsUtils::SVGDPI, r.width() * dpi / GraphicsUtils::SVGDPI, r.height() * dpi / GraphicsUtils::SVGDPI); connectorRects << s; } QDomDocument doc; doc.setContent(svgMask); QList leaves; QDomElement root = doc.documentElement(); TextUtils::collectLeaves(root, leaves); int ix = 0; foreach (QDomElement element, leaves) { element.setAttribute("id", ix++); } QSvgRenderer renderer; renderer.load(doc.toByteArray()); foreach (QDomElement element, leaves) { QString id = element.attribute("id"); QRectF bounds = renderer.boundsOnElement(id); QRectF leafRect = renderer.matrixForElement(id).mapRect(bounds); QPointF leafCenter = leafRect.center(); foreach (QRectF r, connectorRects) { if (!leafRect.intersects(r)) continue; if (!r.contains(leafCenter)) continue; QPointF rCenter = r.center(); if (!leafRect.contains(rCenter)) continue; element.setTagName("g"); break; } } return doc.toString(); } int PCBSketchWidget::checkLoadedTraces() { ProcessEventBlocker::processEvents(); scene()->clearSelection(); QList wires; QHash lines; foreach (QGraphicsItem * item, scene()->items()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (!wire->isTraceType(getTraceFlag())) continue; ConnectorItem * c0 = wire->connector0(); ConnectorItem * c1 = wire->connector1(); QPointF p0 = c0->sceneBoundingRect().center(); QPointF p1 = c1->sceneBoundingRect().center(); QLineF line(p0, p1); lines.insert(wire, line); } foreach (Wire * wire, lines.keys()) { QList already; wire->updateConnections(wire->connector0(), false, already); wire->updateConnections(wire->connector1(), false, already); } foreach (Wire * wire, lines.keys()) { QLineF line = wire->line(); QPointF l0 = wire->pos() + line.p1(); QPointF l1 = wire->pos() + line.p2(); QLineF oldLine = lines.value(wire); double d = 0.1; if (qAbs(oldLine.p1().x() - l0.x()) > d || qAbs(oldLine.p1().y() - l0.y()) > d || qAbs(oldLine.p2().x() - l1.x()) > d || qAbs(oldLine.p2().y() - l1.y()) > d) { wires.append(wire); wire->debugInfo2(QString("wire moved from:\n%1,%2 %3,%4\n%5,%6 %7,%8") .arg(oldLine.p1().x()).arg(oldLine.p1().y()).arg(oldLine.p2().x()).arg(oldLine.p2().y()) .arg(l0.x()).arg(l0.y()).arg(l1.x()).arg(l1.y()) ); } } foreach (Wire * wire, wires) { wire->setSelected(true); } return wires.count(); } bool PCBSketchWidget::hasCustomBoardShape() { QList boards = findBoard(); foreach (ItemBase * board, boards) { if (qobject_cast(board)) return true; } return false; } ViewLayer::ViewLayerPlacement PCBSketchWidget::getViewLayerPlacement(ModelPart * modelPart, QDomElement & instance, QDomElement & view, ViewGeometry & viewGeometry) { if (modelPart->flippedSMD()) { ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(view.attribute("layer")); if (ViewLayer::bottomLayers().contains(viewLayerID)) return ViewLayer::NewBottom; return ViewLayer::NewTop; } if (modelPart->itemType() == ModelPart::Part) { QDomElement views = view.parentNode().toElement(); QDomElement pcbview = views.firstChildElement("pcbView"); bool bottom = pcbview.attribute("bottom", "").compare("true") == 0; if (bottom) return ViewLayer::NewBottom; } return SketchWidget::getViewLayerPlacement(modelPart, instance, view, viewGeometry); } LayerList PCBSketchWidget::routingLayers(ViewLayer::ViewLayerPlacement spec) { LayerList layerList = ViewLayer::copperLayers(spec); layerList.removeOne(ViewLayer::GroundPlane0); layerList.removeOne(ViewLayer::GroundPlane1); return layerList; } bool PCBSketchWidget::attachedToBottomLayer(ConnectorItem * connectorItem) { return (connectorItem->attachedToViewLayerID() == ViewLayer::Copper0) || (connectorItem->attachedToViewLayerID() == ViewLayer::Copper0Trace); } bool PCBSketchWidget::attachedToTopLayer(ConnectorItem * connectorItem) { return (connectorItem->attachedToViewLayerID() == ViewLayer::Copper1) || (connectorItem->attachedToViewLayerID() == ViewLayer::Copper1Trace); } QHash PCBSketchWidget::getAutorouterSettings() { return m_autorouterSettings; } void PCBSketchWidget::setAutorouterSettings(QHash & autorouterSettings) { QList keys; keys << DRC::KeepoutSettingName << AutorouterSettingsDialog::AutorouteTraceWidth << Via::AutorouteViaHoleSize << Via::AutorouteViaRingThickness << GroundPlaneGenerator::KeepoutSettingName; foreach (QString key, keys) { m_autorouterSettings.insert(key, autorouterSettings.value(key, "")); } } void PCBSketchWidget::hidePartSilkscreen() { ItemBase * itemBase = NULL; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * candidate = dynamic_cast(item); if (candidate == NULL) continue; itemBase = candidate->layerKinChief(); break; } if (itemBase == NULL) return; QList itemBases; itemBases.append(itemBase); itemBases.append(itemBase->layerKin()); foreach (ItemBase * lkpi, itemBases) { if (lkpi->viewLayerID() == ViewLayer::Silkscreen1 || lkpi->viewLayerID() == ViewLayer::Silkscreen0) { bool layerHidden = lkpi->layerHidden(); QUndoCommand * parentCommand = new QUndoCommand(layerHidden ? tr("Show part silkscreen") : tr("Hide part silkscreen")); new HidePartLayerCommand(this, itemBase->id(), ViewLayer::Silkscreen0, layerHidden, !layerHidden, parentCommand); new HidePartLayerCommand(this, itemBase->id(), ViewLayer::Silkscreen1, layerHidden, !layerHidden, parentCommand); m_undoStack->push(parentCommand); break; } } } void PCBSketchWidget::fabQuote() { int boardCount = 0; double area = calcBoardArea(boardCount); QuoteDialog::setArea(area, boardCount); if (boardCount == 0) { QMessageBox::information(this, tr("Fritzing Fab Quote"), tr("Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.")); return; } if (!QuoteDialog::quoteSucceeded()) { QMessageBox::information(this, tr("Fritzing Fab Quote"), tr("Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later.")); requestQuote(true); return; } m_quoteDialog = new QuoteDialog(true, this); requestQuote(true); m_quoteDialog->exec(); delete m_quoteDialog; m_quoteDialog = NULL; } void PCBSketchWidget::gotFabQuote(QNetworkReply * networkReply) { QNetworkAccessManager * manager = networkReply->manager(); QString count = manager->property("count").toString(); QStringList countArgs = count.split(","); int responseCode = networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (responseCode == 200) { QString data(networkReply->readAll()); QStringList values = data.split(","); if (values.count() == countArgs.count()) { for (int ix = 0; ix < countArgs.count(); ix++) { QString value = values.at(ix); QString c = countArgs.at(ix); bool ok; int count = c.toInt(&ok); if (!ok) continue; double cost = value.toDouble(&ok); if (!ok) continue; QuoteDialog::setCountCost(ix, count, cost); } QuoteDialog::setQuoteSucceeded(true); } if (m_quoteDialog) m_quoteDialog->setText(); if (m_rolloverQuoteDialog) m_rolloverQuoteDialog->setText(); } else { } manager->deleteLater(); networkReply->deleteLater(); } void PCBSketchWidget::requestQuote(bool byUser) { int boardCount; double area = calcBoardArea(boardCount); QuoteDialog::setArea(area, boardCount); QString paramString = Version::makeRequestParamsString(false); QNetworkAccessManager * manager = new QNetworkAccessManager(this); QString countArgs = QuoteDialog::countArgs(); manager->setProperty("count", countArgs); QString filename = QUrl::toPercentEncoding(filenameIf()); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(gotFabQuote(QNetworkReply *))); QString string = QString("http://fab.fritzing.org/fritzing-fab/quote%1&area=%2&count=%3&filename=%4&byuser=%5") .arg(paramString) .arg(area) .arg(countArgs) .arg(filename) .arg(byUser) ; QuoteDialog::setQuoteSucceeded(false); manager->get(QNetworkRequest(QUrl(string))); } double PCBSketchWidget::calcBoardArea(int & boardCount) { QList boards = findBoard(); boardCount = boards.count(); if (boardCount == 0) { return 0; } double area = 0; foreach (ItemBase * board, boards) { area += GraphicsUtils::pixels2mm(board->boundingRect().width(), GraphicsUtils::SVGDPI) * GraphicsUtils::pixels2mm(board->boundingRect().height(), GraphicsUtils::SVGDPI) / 100; } return area; } PaletteItem* PCBSketchWidget::addPartItem(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, PaletteItem * paletteItem, bool doConnectors, bool & ok, ViewLayer::ViewID viewID, bool temporary) { if (viewID == ViewLayer::PCBView && Board::isBoard(modelPart)) { requestQuoteSoon(); } return SketchWidget::addPartItem(modelPart, viewLayerPlacement, paletteItem, doConnectors, ok, viewID, temporary); } void PCBSketchWidget::requestQuoteSoon() { m_requestQuoteTimer.stop(); m_requestQuoteTimer.start(); } void PCBSketchWidget::requestQuoteNow() { m_requestQuoteTimer.stop(); requestQuote(false); } ItemBase * PCBSketchWidget::resizeBoard(long itemID, double mmW, double mmH) { ItemBase * itemBase = SketchWidget::resizeBoard(itemID, mmW, mmH); if (itemBase != NULL && Board::isBoard(itemBase)) requestQuoteSoon(); return itemBase; } QDialog * PCBSketchWidget::quoteDialog(QWidget * parent) { if (m_rolloverQuoteDialog == NULL) { m_rolloverQuoteDialog = new QuoteDialog(false, parent); requestQuote(false); } m_rolloverQuoteDialog->setText(); return m_rolloverQuoteDialog; } double PCBSketchWidget::getKeepoutMils() { QSettings settings; QString keepoutString = m_autorouterSettings.value(GroundPlaneGenerator::KeepoutSettingName); if (keepoutString.isEmpty()) { keepoutString = settings.value(GroundPlaneGenerator::KeepoutSettingName, "").toString(); } bool ok; double mils = TextUtils::convertToInches(keepoutString, &ok, false); if (ok) { mils *= 1000; // convert from inches } else { mils = GroundPlaneGenerator::KeepoutDefaultMils; } return mils; } void PCBSketchWidget::setGroundFillKeepout() { bool ok; double mils = QInputDialog::getInt(this, tr("Enter Keepout"), tr("Keepout is in mils (.001 inches).\n\n") + tr("Note that due to aliasing, distances may be too short by up to 2 mils\n") + tr("so you may want to increase the keepout value by that much.\n\n") + tr("10 mils is a good default choice.\n\n") + tr("Enter keepout value:"), qRound(getKeepoutMils()), 0, 10 * 1000, 1, &ok); if (!ok) return; QString keepoutString = QString("%1in").arg(mils / 1000); m_autorouterSettings.insert(GroundPlaneGenerator::KeepoutSettingName, keepoutString); QSettings settings; settings.setValue(GroundPlaneGenerator::KeepoutSettingName, keepoutString); } void PCBSketchWidget::setViewFromBelow(bool viewFromBelow) { if (m_viewFromBelow == viewFromBelow) return; QSet chiefs; foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; ViewLayer * viewLayer = m_viewLayers.value(itemBase->viewLayerID(), NULL); if (viewLayer == NULL) continue; double newZ = viewLayer->getZFromBelow(itemBase->z(), viewFromBelow); itemBase->setZValue(newZ); itemBase->getViewGeometry().setZ(newZ); chiefs.insert(itemBase->layerKinChief()); } foreach (ItemBase * chief, chiefs) { chief->figureHover(); } foreach (ViewLayer * viewLayer, m_viewLayers.values()) { viewLayer->setFromBelow(viewFromBelow); } // enable only with multiple layers? // active layer should be secondary mechanism? SketchWidget::setViewFromBelow(viewFromBelow); } void PCBSketchWidget::getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement & viewLayerPlacement) { if (ResizableBoard::isBoard(modelPart)) { viewLayerPlacement = ViewLayer::NewTop; return; } viewLayerPlacement = defaultViewLayerPlacement(modelPart); // top for a two layer board if (boardLayers() == 2) { if (dropOnBottom()) { viewLayerPlacement = ViewLayer::NewBottom; } return; } } bool PCBSketchWidget::dropOnBottom() { if (boardLayers() == 1) return true; if (!layerIsActive(ViewLayer::Copper0)) return false; if (!layerIsActive(ViewLayer::Copper1)) return true; return viewFromBelow(); } bool PCBSketchWidget::updateOK(ConnectorItem * c1, ConnectorItem * c2) { // don't update if both connectors belong to parts--this isn't legit in schematic or pcb view if (c1->attachedTo()->wireFlags()) return true; return c2->attachedTo()->wireFlags() != 0; } fritzing-app-0.9.2b/src/sketch/pcbsketchwidget.h000066400000000000000000000250631250202676700217060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6979 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 23:20:35 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #ifndef PCBSKETCHWIDGET_H #define PCBSKETCHWIDGET_H #include "sketchwidget.h" #include "../dialogs/quotedialog.h" #include #include #include /////////////////////////////////////////////// class PCBSketchWidget : public SketchWidget { Q_OBJECT public: PCBSketchWidget(ViewLayer::ViewID, QWidget *parent=0); void addViewLayers(); bool canDeleteItem(QGraphicsItem * item, int count); bool canCopyItem(QGraphicsItem * item, int count); void createTrace(Wire *, bool useLastWireColor); void excludeFromAutoroute(bool exclude); void selectAllExcludedTraces(); void selectAllIncludedTraces(); bool hasAnyNets(); void forwardRoutingStatus(const RoutingStatus &); void addDefaultParts(); void showEvent(QShowEvent * event); void initWire(Wire *, int penWidth); virtual bool autorouteTypePCB(); virtual double getKeepout(); void setKeepout(double mils); void resetKeepout(); virtual const QString & traceColor(ConnectorItem *); const QString & traceColor(ViewLayer::ViewLayerPlacement); virtual void ensureTraceLayersVisible(); virtual void ensureTraceLayerVisible(); bool canChainMultiple(); void setNewPartVisible(ItemBase *); void setClipEnds(class ClipableWire *, bool); void showGroundTraces(QList & seeds, bool show); virtual double getLabelFontSizeTiny(); virtual double getLabelFontSizeSmall(); virtual double getLabelFontSizeMedium(); virtual double getLabelFontSizeLarge(); ViewLayer::ViewLayerID getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); QList findBoard(); ItemBase * findSelectedBoard(int & boardCount); ItemBase * findBoardBeneath(ItemBase *); void setBoardLayers(int, bool redraw); void swapLayers(ItemBase * itemBase, int newLayers, QUndoCommand * parentCommand); void loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs); virtual bool isInLayers(ConnectorItem *, ViewLayer::ViewLayerPlacement); bool routeBothSides(); bool sameElectricalLayer2(ViewLayer::ViewLayerID, ViewLayer::ViewLayerID); void changeTraceLayer(ItemBase *, bool force, QUndoCommand * parentCommand); void changeLayer(long id, double z, ViewLayer::ViewLayerID viewLayerID); bool acceptsTrace(const ViewGeometry & viewGeometry); ItemBase * placePartDroppedInOtherView(ModelPart *, ViewLayer::ViewLayerPlacement, const ViewGeometry & viewGeometry, long id, SketchWidget * dropOrigin); void autorouterSettings(); void getViaSize(double & ringThickness, double & holeSize); void deleteItem(ItemBase *, bool deleteModelPart, bool doEmit, bool later); double getTraceWidth(); virtual double getAutorouterTraceWidth(); void getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect); double getSmallerTraceWidth(double minDim); bool groundFill(bool fillGroundTraces, ViewLayer::ViewLayerID, QUndoCommand * parentCommand); void setGroundFillSeeds(); void clearGroundFillSeeds(); QString generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart); double getWireStrokeWidth(Wire *, double wireWidth); ItemBase * addCopperLogoItem(ViewLayer::ViewLayerPlacement viewLayerPlacement); QString characterizeGroundFill(ViewLayer::ViewLayerID); ViewGeometry::WireFlag getTraceFlag(); void hideCopperLogoItems(QList &); void restoreCopperLogoItems(QList &); void hideHoles(QList &); QString makePasteMask(const QString & svgMask, ItemBase * board, double dpi, const LayerList & maskLayerIDs); int selectAllItemType(ModelPart::ItemType, const QString & typeName); bool isBoardLayerChange(ItemBase * itemBase, const QString & newModuleID, int & newLayers); void convertToVia(ConnectorItem * lastHoverEnterConnectorItem); void convertToBendpoint(); int checkLoadedTraces(); bool hasCustomBoardShape(); virtual QSizeF jumperItemSize(); virtual LayerList routingLayers(ViewLayer::ViewLayerPlacement); virtual bool attachedToTopLayer(ConnectorItem *); virtual bool attachedToBottomLayer(ConnectorItem *); QHash getAutorouterSettings(); void setAutorouterSettings(QHash &); void getDefaultViaSize(QString & ringThickness, QString & holeSize); void hidePartSilkscreen(); void fabQuote(); QDialog * quoteDialog(QWidget * parent); void setGroundFillKeepout(); void setViewFromBelow(bool); bool dropOnBottom(); ViewLayer::ViewLayerPlacement defaultViewLayerPlacement(ModelPart *); public slots: void resizeBoard(double w, double h, bool doEmit); void showLabelFirstTime(long itemID, bool show, bool doEmit); void changeBoardLayers(int layers, bool doEmit); ItemBase * resizeBoard(long id, double w, double h); public: enum CleanType { noClean, ninetyClean }; CleanType cleanType(); protected: void setWireVisible(Wire * wire); // void checkAutorouted(); ViewLayer::ViewLayerID multiLayerGetViewLayerID(ModelPart * modelPart, ViewLayer::ViewID, ViewLayer::ViewLayerPlacement, LayerList &); bool canChainWire(Wire *); bool canDragWire(Wire * wire); const QString & hoverEnterPartConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item); //bool modifyNewWireConnections(Wire * dragWire, ConnectorItem * fromOnWire, ConnectorItem * from, ConnectorItem * to, QUndoCommand * parentCommand); ViewLayer::ViewLayerID getDragWireViewLayerID(ConnectorItem *); bool canDropModelPart(ModelPart * modelPart); bool canCreateWire(Wire * dragWire, ConnectorItem * from, ConnectorItem * to); bool bothEndsConnected(Wire * wire, ViewGeometry::WireFlags, ConnectorItem * oneEnd, QList & wires, QList & partConnectorItems); void setUpColor(ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Wire * wire, QUndoCommand * parentCommand); ConnectorItem * findNearestPartConnectorItem(ConnectorItem * fromConnectorItem); bool bothEndsConnectedAux(Wire * wire, ViewGeometry::WireFlags flag, ConnectorItem * oneEnd, QList & wires, QList & partConnectorItems, QList & visited); void getLabelFont(QFont &, QColor &, ItemBase *); double defaultGridSizeInches(); ViewLayer::ViewLayerID getLabelViewLayerID(ItemBase *); ViewLayer::ViewLayerPlacement wireViewLayerPlacement(ConnectorItem *); bool resizingJumperItemPress(ItemBase *); bool resizingJumperItemRelease(); void resizeJumperItem(); void dealWithDefaultParts(); bool connectorItemHasSpec(ConnectorItem * connectorItem, ViewLayer::ViewLayerPlacement spec); ViewLayer::ViewLayerPlacement createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to); Wire * createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); void prereleaseTempWireForDragging(Wire*); void rotatePartLabels(double degrees, QTransform &, QPointF center, QUndoCommand * parentCommand); bool hasNeighbor(ConnectorItem * connectorItem, ViewLayer::ViewLayerID viewLayerID, const QRectF & r); void setGroundFillSeeds(const QString & intro); bool collectGroundFillSeeds(QList & seeds, bool includePotential); void shiftHoles(); void selectAllXTraces(bool autoroutable, const QString & cmdText, bool forPCB); bool canAlignToCenter(ItemBase *); void selectAllWires(ViewGeometry::WireFlag flag); QString checkDroppedModuleID(const QString & moduleID); bool canConnect(Wire * from, ItemBase * to); void collectThroughHole(QList & th, QList & pads, const LayerList &); ViewLayer::ViewLayerPlacement getViewLayerPlacement(ModelPart *, QDomElement & instance, QDomElement & view, ViewGeometry &); void requestQuote(bool byUser); double calcBoardArea(int & boardCount); PaletteItem* addPartItem(ModelPart * modelPart, ViewLayer::ViewLayerPlacement, PaletteItem * paletteItem, bool doConnectors, bool & ok, ViewLayer::ViewID, bool temporary); void requestQuoteSoon(); double getKeepoutMils(); bool updateOK(ConnectorItem *, ConnectorItem *); signals: void subSwapSignal(SketchWidget *, ItemBase *, const QString & newModuleID, ViewLayer::ViewLayerPlacement, long & newID, QUndoCommand * parentCommand); void boardDeletedSignal(); void groundFillSignal(); void copperFillSignal(); protected: static void calcDistances(Wire * wire, QList & ends); static void clearDistances(); static int calcDistance(Wire * wire, ConnectorItem * end, int distance, QList & distanceWires, bool & fromConnector0); static int calcDistanceAux(ConnectorItem * from, ConnectorItem * to, int distance, QList & distanceWires); protected slots: void alignJumperItem(class JumperItem *, QPointF &); void wireSplitSlot(class Wire*, QPointF newPos, QPointF oldPos, const QLineF & oldLine); void postImageSlot(class GroundPlaneGenerator *, QImage * copperImage, QImage * boardImage, QGraphicsItem * board, QList *); void gotFabQuote(QNetworkReply *); void requestQuoteNow(); void getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement &); protected: CleanType m_cleanType; QPointF m_jumperDragOffset; QPointer m_resizingJumperItem; QList * m_groundFillSeeds; QHash m_autorouterSettings; QPointer m_quoteDialog; QPointer m_rolloverQuoteDialog; QTimer m_requestQuoteTimer; protected: static QSizeF m_jumperItemSize; static const char * FakeTraceProperty; }; #endif fritzing-app-0.9.2b/src/sketch/schematicsketchwidget.cpp000066400000000000000000000471271250202676700234420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #include "schematicsketchwidget.h" #include "../debugdialog.h" #include "../items/virtualwire.h" #include "../items/symbolpaletteitem.h" #include "../items/tracewire.h" #include "../items/partlabel.h" #include "../connectors/connectoritem.h" #include "../waitpushundostack.h" #include "../items/moduleidnames.h" #include "../fsvgrenderer.h" #include "../utils/graphicsutils.h" #include "../version/version.h" #include QSizeF SchematicSketchWidget::m_jumperItemSize = QSizeF(0, 0); static QString SchematicTraceColor = "black"; static const double TraceHoverStrokeFactor = 3; static const double TraceWidthMils = 9.7222; static const double TraceWidthMilsOld = 33.3333; bool sameGround(ConnectorItem * c1, ConnectorItem * c2) { bool c1Grounded = c1->isGrounded(); bool c2Grounded = c2->isGrounded(); return (c1Grounded == c2Grounded); } /////////////////////////////////////////////////// SchematicSketchWidget::SchematicSketchWidget(ViewLayer::ViewID viewID, QWidget *parent) : PCBSketchWidget(viewID, parent) { m_oldSchematic = m_convertSchematic = false; m_shortName = QObject::tr("schem"); m_viewName = QObject::tr("Schematic View"); initBackgroundColor(); m_cleanType = ninetyClean; m_updateDotsTimer.setInterval(20); m_updateDotsTimer.setSingleShot(true); connect(&m_updateDotsTimer, SIGNAL(timeout()), this, SLOT(updateBigDots())); } void SchematicSketchWidget::addViewLayers() { setViewLayerIDs(ViewLayer::Schematic, ViewLayer::SchematicTrace, ViewLayer::Schematic, ViewLayer::SchematicRuler, ViewLayer::SchematicNote); addViewLayersAux(ViewLayer::layersForView(ViewLayer::SchematicView), ViewLayer::layersForViewFromBelow(ViewLayer::SchematicView)); } ViewLayer::ViewLayerID SchematicSketchWidget::getDragWireViewLayerID(ConnectorItem *) { return ViewLayer::SchematicTrace; } ViewLayer::ViewLayerID SchematicSketchWidget::getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewGeometry.getAnyTrace()) { return ViewLayer::SchematicTrace; } if (viewGeometry.getRatsnest()) { return ViewLayer::SchematicWire; } return SketchWidget::getWireViewLayerID(viewGeometry, viewLayerPlacement); } void SchematicSketchWidget::initWire(Wire * wire, int penWidth) { Q_UNUSED(penWidth); if (wire->getRatsnest()) { return; } wire->setPenWidth(getTraceWidth(), this, getTraceWidth() * TraceHoverStrokeFactor); wire->setColorString("black", 1.0, false); } bool SchematicSketchWidget::autorouteTypePCB() { return false; } void SchematicSketchWidget::tidyWires() { QList wires; QList visited; foreach (QGraphicsItem * item, scene()->selectedItems()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if ((wire->getViewGeometry().wireFlags() & ViewGeometry::SchematicTraceFlag) == 0) continue; if (visited.contains(wire)) continue; } } void SchematicSketchWidget::ensureTraceLayersVisible() { ensureLayerVisible(ViewLayer::SchematicTrace); } void SchematicSketchWidget::ensureTraceLayerVisible() { ensureLayerVisible(ViewLayer::SchematicTrace); } void SchematicSketchWidget::setClipEnds(ClipableWire * vw, bool) { vw->setClipEnds(false); } void SchematicSketchWidget::getBendpointWidths(Wire * wire, double width, double & bendpointWidth, double & bendpoint2Width, bool & negativeOffsetRect) { Q_UNUSED(wire); bendpointWidth = -width - 1; bendpoint2Width = width + ((m_oldSchematic) ? 3 : 1); negativeOffsetRect = true; } void SchematicSketchWidget::getLabelFont(QFont & font, QColor & color, ItemBase *) { font.setFamily("Droid Sans"); font.setPointSize(getLabelFontSizeSmall()); font.setBold(false); font.setItalic(false); color.setAlpha(255); color.setRgb(0); } void SchematicSketchWidget::setNewPartVisible(ItemBase * itemBase) { switch (itemBase->itemType()) { case ModelPart::Logo: if (itemBase->moduleID().contains("schematic", Qt::CaseInsensitive)) break; case ModelPart::Breadboard: case ModelPart::Jumper: case ModelPart::CopperFill: case ModelPart::Via: case ModelPart::Hole: // don't need to see the breadboard in the other views // but it's there so connections can be more easily synched between views itemBase->setVisible(false); itemBase->setEverVisible(false); return; default: if (itemBase->moduleID().endsWith(ModuleIDNames::PadModuleIDName)) { itemBase->setVisible(false); itemBase->setEverVisible(false); return; } break; } } bool SchematicSketchWidget::canDropModelPart(ModelPart * modelPart) { if (!SketchWidget::canDropModelPart(modelPart)) return false; switch (modelPart->itemType()) { case ModelPart::Logo: if (modelPart->moduleID().contains("schematic", Qt::CaseInsensitive)) return true; case ModelPart::Jumper: case ModelPart::CopperFill: case ModelPart::Board: case ModelPart::ResizableBoard: case ModelPart::Breadboard: case ModelPart::Via: case ModelPart::Hole: return false; case ModelPart::Symbol: case ModelPart::SchematicSubpart: return true; default: break; } if (modelPart->moduleID().endsWith(ModuleIDNames::SchematicFrameModuleIDName)) return true; if (modelPart->moduleID().endsWith(ModuleIDNames::PadModuleIDName)) return false; if (modelPart->moduleID().endsWith(ModuleIDNames::CopperBlockerModuleIDName)) return false; return PCBSketchWidget::canDropModelPart(modelPart); } bool SchematicSketchWidget::includeSymbols() { return true; } bool SchematicSketchWidget::hasBigDots() { return true; } void SchematicSketchWidget::updateBigDots() { QList connectorItems; foreach (QGraphicsItem * item, scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (connectorItem->attachedToItemType() != ModelPart::Wire) continue; TraceWire * traceWire = qobject_cast(connectorItem->attachedTo()); if (traceWire == NULL) continue; //DebugDialog::debug(QString("update big dot %1 %2").arg(traceWire->id()).arg(connectorItem->connectorSharedID())); connectorItems.append(connectorItem); } QList visited; foreach (ConnectorItem * connectorItem, connectorItems) { connectorItem->restoreColor(visited); } } void SchematicSketchWidget::changeConnection(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, bool doEmit, bool updateConnections) { m_updateDotsTimer.stop(); SketchWidget::changeConnection(fromID, fromConnectorID, toID, toConnectorID, viewLayerPlacement, connect, doEmit, updateConnections); m_updateDotsTimer.start(); } void SchematicSketchWidget::setInstanceTitle(long itemID, const QString & oldText, const QString & newText, bool isUndoable, bool doEmit) { // isUndoable is true when setInstanceTitle is called from the infoview if (isUndoable) { SymbolPaletteItem * sitem = qobject_cast(findItem(itemID)); if (sitem && sitem->isOnlyNetLabel()) { setProp(sitem, "label", ItemBase::TranslatedPropertyNames.value("label"), oldText, newText, true); return; } } SketchWidget::setInstanceTitle(itemID, oldText, newText, isUndoable, doEmit); } void SchematicSketchWidget::setProp(ItemBase * itemBase, const QString & prop, const QString & trProp, const QString & oldValue, const QString & newValue, bool redraw) { if (prop =="label") { SymbolPaletteItem * sitem = qobject_cast(itemBase); if (sitem != NULL && sitem->isOnlyNetLabel()) { if (sitem->getLabel() == newValue) { return; } QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(tr("Change label from %1 to %2").arg(oldValue).arg(newValue)); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); QList done; foreach (ConnectorItem * toConnectorItem, sitem->connector0()->connectedToItems()) { Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w == NULL) continue; if (done.contains(w)) continue; QList ends; removeWire(w, ends, done, parentCommand); } new SetPropCommand(this, itemBase->id(), "label", oldValue, newValue, true, parentCommand); new ChangeLabelTextCommand(this, itemBase->id(), oldValue, newValue, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); return; } } SketchWidget::setProp(itemBase, prop, trProp, oldValue, newValue, redraw); } void SchematicSketchWidget::setVoltage(double v, bool doEmit) { Q_UNUSED(doEmit); PaletteItem * item = getSelectedPart(); if (item == NULL) return; if (item->itemType() != ModelPart::Symbol) return; SymbolPaletteItem * sitem = qobject_cast(item); if (sitem == NULL) return; if (sitem->moduleID().compare("ground symbol", Qt::CaseInsensitive) == 0) return; if (v == sitem->voltage()) return; QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(tr("Change voltage from %1 to %2").arg(sitem->voltage()).arg(v)); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); QList done; foreach (ConnectorItem * toConnectorItem, sitem->connector0()->connectedToItems()) { Wire * w = qobject_cast(toConnectorItem->attachedTo()); if (w == NULL) continue; if (done.contains(w)) continue; QList ends; removeWire(w, ends, done, parentCommand); } new SetPropCommand(this, item->id(), "voltage", QString::number(sitem->voltage()), QString::number(v), true, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } double SchematicSketchWidget::defaultGridSizeInches() { return GraphicsUtils::StandardSchematicSeparation10thinMils / 1000; } ViewLayer::ViewLayerID SchematicSketchWidget::getLabelViewLayerID(ItemBase *) { return ViewLayer::SchematicLabel; } const QString & SchematicSketchWidget::traceColor(ConnectorItem *) { if (m_lastColorSelected.isEmpty()) return SchematicTraceColor; else return m_lastColorSelected; } const QString & SchematicSketchWidget::traceColor(ViewLayer::ViewLayerPlacement) { return SchematicTraceColor; } bool SchematicSketchWidget::isInLayers(ConnectorItem * connectorItem, ViewLayer::ViewLayerPlacement viewLayerPlacement) { Q_UNUSED(connectorItem); Q_UNUSED(viewLayerPlacement); return true; } bool SchematicSketchWidget::routeBothSides() { return false; } void SchematicSketchWidget::addDefaultParts() { SketchWidget::addDefaultParts(); } bool SchematicSketchWidget::sameElectricalLayer2(ViewLayer::ViewLayerID, ViewLayer::ViewLayerID) { // schematic is always one layer return true; } double SchematicSketchWidget::getKeepout() { return 0.1 * GraphicsUtils::SVGDPI; // in pixels } bool SchematicSketchWidget::acceptsTrace(const ViewGeometry & viewGeometry) { return viewGeometry.getSchematicTrace(); } ViewGeometry::WireFlag SchematicSketchWidget::getTraceFlag() { return ViewGeometry::SchematicTraceFlag; } double SchematicSketchWidget::getTraceWidth() { return GraphicsUtils::SVGDPI * ((m_oldSchematic ) ? TraceWidthMilsOld : TraceWidthMils) / 1000; } double SchematicSketchWidget::getAutorouterTraceWidth() { return getTraceWidth(); } void SchematicSketchWidget::extraRenderSvgStep(ItemBase * itemBase, QPointF offset, double dpi, double printerScale, QString & outputSvg) { TraceWire * traceWire = qobject_cast(itemBase); if (traceWire == NULL) return; if (traceWire->connector0()->isBigDot()) { double r = traceWire->connector0()->rect().width(); outputSvg += makeCircleSVG(traceWire->connector0()->sceneAdjustedTerminalPoint(NULL), r, offset, dpi, printerScale); } if (traceWire->connector1()->isBigDot()) { double r = traceWire->connector0()->rect().width(); outputSvg += makeCircleSVG(traceWire->connector1()->sceneAdjustedTerminalPoint(NULL), r, offset, dpi, printerScale); } } QString SchematicSketchWidget::makeCircleSVG(QPointF p, double r, QPointF offset, double dpi, double printerScale) { double cx = (p.x() - offset.x()) * dpi / printerScale; double cy = (p.y() - offset.y()) * dpi / printerScale; double rr = r * dpi / printerScale; QString stroke = "black"; return QString("") .arg(cx) .arg(cy) .arg(rr); } QString SchematicSketchWidget::generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart) { Q_UNUSED(itemBase); Q_UNUSED(whereToStart); return ""; } ViewLayer::ViewLayerPlacement SchematicSketchWidget::createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to) { return SketchWidget::createWireViewLayerPlacement(from, to); } double SchematicSketchWidget::getWireStrokeWidth(Wire *, double wireWidth) { return wireWidth * TraceHoverStrokeFactor; } Wire * SchematicSketchWidget::createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement spec) { viewGeometry.setSchematicTrace(true); Wire * wire = SketchWidget::createTempWireForDragging(fromWire, wireModel, connectorItem, viewGeometry, spec); if (fromWire) { wire->setColorString(fromWire->colorString(), fromWire->opacity(), false); } else { wire->setProperty(PCBSketchWidget::FakeTraceProperty, true); wire->setColorString(traceColor(connectorItem), 1.0, false); } return wire; } void SchematicSketchWidget::rotatePartLabels(double degrees, QTransform & transform, QPointF center, QUndoCommand * parentCommand) { PCBSketchWidget::rotatePartLabels(degrees, transform, center, parentCommand); } void SchematicSketchWidget::loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType crossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs) { SketchWidget::loadFromModelParts(modelParts, crossViewType, parentCommand, offsetPaste, boundingRect, seekOutsideConnections, newIDs); } void SchematicSketchWidget::selectAllWires(ViewGeometry::WireFlag flag) { SketchWidget::selectAllWires(flag); } bool SchematicSketchWidget::canConnect(Wire *, ItemBase *) { return true; } QString SchematicSketchWidget::checkDroppedModuleID(const QString & moduleID) { return moduleID; } LayerList SchematicSketchWidget::routingLayers(ViewLayer::ViewLayerPlacement) { LayerList layerList; layerList << ViewLayer::Schematic; return layerList; } bool SchematicSketchWidget::attachedToBottomLayer(ConnectorItem * connectorItem) { return (connectorItem->attachedToViewLayerID() == ViewLayer::Schematic) || (connectorItem->attachedToViewLayerID() == ViewLayer::SchematicTrace); } bool SchematicSketchWidget::attachedToTopLayer(ConnectorItem *) { return false; } QSizeF SchematicSketchWidget::jumperItemSize() { if (SchematicSketchWidget::m_jumperItemSize.width() == 0) { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; viewGeometry.setLoc(QPointF(0, 0)); ItemBase * itemBase = addItem(referenceModel()->retrieveModelPart(ModuleIDNames::NetLabelModuleIDName), defaultViewLayerPlacement(NULL), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); if (itemBase) { SymbolPaletteItem * netLabel = qobject_cast(itemBase); netLabel->setLabel("00"); SchematicSketchWidget::m_jumperItemSize = netLabel->boundingRect().size(); deleteItem(itemBase, true, false, false); } } return SchematicSketchWidget::m_jumperItemSize; } QHash SchematicSketchWidget::getAutorouterSettings() { return SketchWidget::getAutorouterSettings(); } void SchematicSketchWidget::setAutorouterSettings(QHash & autorouterSettings) { SketchWidget::setAutorouterSettings(autorouterSettings); } void SchematicSketchWidget::getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement & viewLayerPlacement) { SketchWidget::getDroppedItemViewLayerPlacement(modelPart, viewLayerPlacement); } ViewLayer::ViewLayerPlacement SchematicSketchWidget::getViewLayerPlacement(ModelPart * modelPart, QDomElement & instance, QDomElement & view, ViewGeometry & viewGeometry) { return SketchWidget::getViewLayerPlacement(modelPart, instance, view, viewGeometry); } void SchematicSketchWidget::viewGeometryConversionHack(ViewGeometry & viewGeometry, ModelPart * modelPart) { if (!m_convertSchematic) return; if (modelPart->itemType() == ModelPart::Wire) return; if (viewGeometry.transform().isIdentity()) return; ViewGeometry vg; ItemBase * itemBase = addItemAuxTemp(modelPart, ViewLayer::NewTop, vg, 0, true, viewID(), true); double rotation; if (GraphicsUtils::isFlipped(viewGeometry.transform().toAffine(), rotation)) { itemBase->flipItem(Qt::Horizontal); } itemBase->rotateItem(rotation, false); itemBase->saveGeometry(); viewGeometry.setTransform(itemBase->getViewGeometry().transform()); foreach (ItemBase * kin, itemBase->layerKin()) delete kin; delete itemBase; } void SchematicSketchWidget::setOldSchematic(bool old) { m_oldSchematic = old; } bool SchematicSketchWidget::isOldSchematic() { return m_oldSchematic; } void SchematicSketchWidget::setConvertSchematic(bool convert) { m_convertSchematic = convert; } void SchematicSketchWidget::resizeWires() { double tw = getTraceWidth(); double sw = getWireStrokeWidth(NULL, tw); foreach (QGraphicsItem * item, scene()->items()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (!wire->isTraceType(getTraceFlag())) continue; wire->setWireWidth(tw, this, sw); } } void SchematicSketchWidget::resizeLabels() { double fontSize = getLabelFontSizeSmall(); foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->hasPartLabel() && itemBase->partLabel() != NULL) { itemBase->partLabel()->setFontPointSize(fontSize); } } } fritzing-app-0.9.2b/src/sketch/schematicsketchwidget.h000066400000000000000000000120401250202676700230710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6979 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 23:20:35 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #ifndef SCHEMATICSKETCHWIDGET_H #define SCHEMATICSKETCHWIDGET_H #include "pcbsketchwidget.h" class SchematicSketchWidget : public PCBSketchWidget { Q_OBJECT public: SchematicSketchWidget(ViewLayer::ViewID, QWidget *parent=0); void addViewLayers(); ViewLayer::ViewLayerID getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); ViewLayer::ViewLayerID getDragWireViewLayerID(ConnectorItem *); void initWire(Wire *, int penWidth); bool autorouteTypePCB(); double getKeepout(); void tidyWires(); void ensureTraceLayersVisible(); void ensureTraceLayerVisible(); void setClipEnds(ClipableWire * vw, bool); void getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect); void getLabelFont(QFont &, QColor &, ItemBase *); void setNewPartVisible(ItemBase *); bool canDropModelPart(ModelPart * modelPart); bool includeSymbols(); bool hasBigDots(); void changeConnection(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, bool doEmit, bool updateConnections); double defaultGridSizeInches(); const QString & traceColor(ConnectorItem * forColor); const QString & traceColor(ViewLayer::ViewLayerPlacement); bool isInLayers(ConnectorItem *, ViewLayer::ViewLayerPlacement); bool routeBothSides(); void addDefaultParts(); bool sameElectricalLayer2(ViewLayer::ViewLayerID, ViewLayer::ViewLayerID); bool acceptsTrace(const ViewGeometry &); ViewGeometry::WireFlag getTraceFlag(); double getTraceWidth(); double getAutorouterTraceWidth(); QString generateCopperFillUnit(ItemBase * itemBase, QPointF whereToStart); double getWireStrokeWidth(Wire *, double wireWidth); Wire * createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); void rotatePartLabels(double degrees, QTransform &, QPointF center, QUndoCommand * parentCommand); void loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs); LayerList routingLayers(ViewLayer::ViewLayerPlacement); bool attachedToTopLayer(ConnectorItem *); bool attachedToBottomLayer(ConnectorItem *); QSizeF jumperItemSize(); QHash getAutorouterSettings(); void setAutorouterSettings(QHash &); ViewLayer::ViewLayerPlacement getViewLayerPlacement(ModelPart *, QDomElement & instance, QDomElement & view, ViewGeometry &); void setConvertSchematic(bool); void setOldSchematic(bool); bool isOldSchematic(); void resizeWires(); void resizeLabels(); public slots: void setVoltage(double voltage, bool doEmit); void setProp(ItemBase *, const QString & propName, const QString & translatedPropName, const QString & oldValue, const QString & newValue, bool redraw); void setInstanceTitle(long id, const QString & oldTitle, const QString & newTitle, bool isUndoable, bool doEmit); protected slots: void updateBigDots(); void getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement &); protected: double getRatsnestOpacity(); double getRatsnestWidth(); ViewLayer::ViewLayerID getLabelViewLayerID(ItemBase *); void extraRenderSvgStep(ItemBase *, QPointF offset, double dpi, double printerScale, QString & outputSvg); QString makeCircleSVG(QPointF p, double r, QPointF offset, double dpi, double printerScale); ViewLayer::ViewLayerPlacement createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to); void selectAllWires(ViewGeometry::WireFlag flag); bool canConnect(Wire * from, ItemBase * to); QString checkDroppedModuleID(const QString & moduleID); void viewGeometryConversionHack(ViewGeometry &, ModelPart *); protected: QTimer m_updateDotsTimer; bool m_convertSchematic; bool m_oldSchematic; static QSizeF m_jumperItemSize; }; #endif fritzing-app-0.9.2b/src/sketch/sketchwidget.cpp000066400000000000000000012120521250202676700215510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty ofro 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 Fritzing. If not, see . ******************************************************************** $Revision: 7000 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 07:24:08 +0200 (Mon, 29 Apr 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../items/partfactory.h" #include "../items/paletteitem.h" #include "../items/logoitem.h" #include "../items/pad.h" #include "../items/ruler.h" #include "../items/symbolpaletteitem.h" #include "../items/wire.h" #include "../commands.h" #include "../model/modelpart.h" #include "../debugdialog.h" #include "../items/layerkinpaletteitem.h" #include "sketchwidget.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include "../items/jumperitem.h" #include "../items/stripboard.h" #include "../items/virtualwire.h" #include "../items/tracewire.h" #include "../itemdrag.h" #include "../layerattributes.h" #include "../waitpushundostack.h" #include "fgraphicsscene.h" #include "../version/version.h" #include "../items/partlabel.h" #include "../items/note.h" #include "../svg/svgfilesplitter.h" #include "../svg/svgflattener.h" #include "../infoview/htmlinfoview.h" #include "../items/resizableboard.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/bezier.h" #include "../utils/cursormaster.h" #include "../utils/fmessagebox.h" #include "../fsvgrenderer.h" #include "../items/resistor.h" #include "../items/mysterypart.h" #include "../items/pinheader.h" #include "../items/dip.h" #include "../items/groundplane.h" #include "../items/moduleidnames.h" #include "../items/hole.h" #include "../items/capacitor.h" #include "../items/schematicframe.h" #include "../utils/graphutils.h" #include "../utils/ratsnestcolors.h" #include "../utils/cursormaster.h" ///////////////////////////////////////////////////////////////////// bool hideTerminalID(QDomDocument & doc, const QString & terminalID) { QDomElement root = doc.documentElement(); QDomElement terminal = TextUtils::findElementWithAttribute(root, "id", terminalID); if (terminal.isNull()) return false; terminal.setTagName("g"); return true; } bool ensureStrokeWidth(QDomDocument & doc, const QString & connectorID, double factor) { QDomElement root = doc.documentElement(); QDomElement connector = TextUtils::findElementWithAttribute(root, "id", connectorID); if (connector.isNull()) return false; QString stroke = connector.attribute("stroke"); if (stroke.isEmpty()) return false; QString strokeWidth = connector.attribute("stroke-width"); if (!strokeWidth.isEmpty()) return false; TextUtils::getStrokeWidth(connector, factor); // default stroke width is 1, multipled by factor return true; } ///////////////////////////////////////////////////////////////////// SizeItem::SizeItem() { } SizeItem::~SizeItem() { } ///////////////////////////////////////////////////////////////////// enum ConnectionStatus { IN_, OUT_, FREE_, UNDETERMINED_ }; static const double CloseEnough = 0.5; // in pixels, for swapping into the breadboard const int SketchWidget::MoveAutoScrollThreshold = 5; const int SketchWidget::DragAutoScrollThreshold = 10; static const int AutoRepeatDelay = 750; const int SketchWidget::PropChangeDelay = 100; bool SketchWidget::m_blockUI = false; ///////////////////////////////////////////////////////////////////// bool zLessThan(QGraphicsItem * & p1, QGraphicsItem * & p2) { return p1->zValue() < p2->zValue(); } ///////////////////////////////////////////////////////////////////// SketchWidget::SketchWidget(ViewLayer::ViewID viewID, QWidget *parent, int size, int minSize) : InfoGraphicsView(parent) { m_everZoomed = false; m_itemMenu = NULL; m_pasting = false; m_rubberBandLegWasEnabled = m_curvyWires = false; m_middleMouseIsPressed = false; m_arrowTimer.setParent(this); m_arrowTimer.setInterval(AutoRepeatDelay); m_arrowTimer.setSingleShot(true); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) m_arrowTimer.setTimerType(Qt::PreciseTimer); m_autoScrollTimer.setTimerType(Qt::PreciseTimer); #endif connect(&m_arrowTimer, SIGNAL(timeout()), this, SLOT(arrowTimerTimeout())); m_addDefaultParts = false; m_addedDefaultPart = NULL; m_movingItem = NULL; m_movingSVGRenderer = NULL; m_clearSceneRect = false; m_draggingBendpoint = false; m_zoom = 100; m_showGrid = m_alignToGrid = true; m_movingByMouse = m_movingByArrow = false; m_statusConnectState = StatusConnectNotTried; m_dragBendpointWire = NULL; m_lastHoverEnterItem = NULL; m_lastHoverEnterConnectorItem = NULL; m_spaceBarWasPressed = m_spaceBarIsPressed = false; m_current = false; m_ignoreSelectionChangeEvents = 0; m_droppingItem = NULL; m_chainDrag = false; m_bendpointWire = m_connectorDragWire = NULL; m_tempDragWireCommand = m_holdingSelectItemCommand = NULL; m_viewID = viewID; //setAlignment(Qt::AlignLeft | Qt::AlignTop); setDragMode(QGraphicsView::RubberBandDrag); setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); setAcceptDrops(true); setRenderHint(QPainter::Antialiasing, true); //setCacheMode(QGraphicsView::CacheBackground); //setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); //setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setTransformationAnchor(QGraphicsView::AnchorViewCenter); //setTransformationAnchor(QGraphicsView::AnchorUnderMouse); //setTransformationAnchor(QGraphicsView::NoAnchor); FGraphicsScene* scene = new FGraphicsScene(this); this->setScene(scene); //this->scene()->setSceneRect(0,0, rect().width(), rect().height()); // Setting the scene rect here seems to mean it never resizes when the user drags an object // outside the sceneRect bounds. So catch some signal and do the resize manually? // this->scene()->setSceneRect(0, 0, 500, 500); // if the sceneRect isn't set, the view seems to grow and scroll gracefully as new items are added // however, it doesn't shrink if items are removed. // a bit of a hack so that, when there is no scenerect set, // the first item dropped into the scene doesn't leap to the top left corner // as the scene resizes to fit the new item m_sizeItem = new SizeItem(); m_sizeItem->setLine(0, 0, rect().width(), rect().height()); //DebugDialog::debug(QString("initial rect %1 %2").arg(rect().width()).arg(rect().height())); this->scene()->addItem(m_sizeItem); m_sizeItem->setVisible(false); connect(this->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChangedSlot())); connect(QApplication::clipboard(),SIGNAL(changed(QClipboard::Mode)),this,SLOT(restartPasteCount())); restartPasteCount(); // the first time setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); resize(size, size); setMinimumSize(minSize, minSize); setLastPaletteItemSelected(NULL); m_infoViewOnHover = true; setMouseTracking(true); } SketchWidget::~SketchWidget() { foreach (ViewLayer * viewLayer, m_viewLayers.values()) { if (viewLayer == NULL) continue; delete viewLayer; } m_viewLayers.clear(); } void SketchWidget::restartPasteCount() { m_pasteCount = 0; } WaitPushUndoStack* SketchWidget::undoStack() { return m_undoStack; } void SketchWidget::setUndoStack(WaitPushUndoStack * undoStack) { m_undoStack = undoStack; } void SketchWidget::loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType crossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs) { clearHoldingSelectItem(); if (parentCommand) { SelectItemCommand * selectItemCommand = stackSelectionState(false, parentCommand); selectItemCommand->setSelectItemType(SelectItemCommand::DeselectAll); selectItemCommand->setCrossViewType(crossViewType); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); } QHash newItems; setIgnoreSelectionChangeEvents(true); QString viewName = ViewLayer::viewIDXmlName(m_viewID); QMultiMap zmap; QPointF sceneCenter = mapToScene(viewport()->rect().center()); QPointF sceneCorner; if (boundingRect) { sceneCorner.setX(sceneCenter.x() - (boundingRect->width() / 2)); sceneCorner.setY(sceneCenter.y() - (boundingRect->height() / 2)); } QHash superparts; QHash superparts2; QList zeroLength; // make parts foreach (ModelPart * mp, modelParts) { QDomElement instance = mp->instanceDomElement(); if (instance.isNull()) continue; QDomElement views = instance.firstChildElement("views"); if (views.isNull()) continue; QDomElement view = views.firstChildElement(viewName); if (view.isNull()) continue; bool locked = view.attribute("locked", "").compare("true") == 0; bool superpartOK; long superpartID = view.attribute("superpart", "").toLong(&superpartOK); if (superpartOK) { superpartID = ItemBase::getNextID(superpartID); } QDomElement geometry = view.firstChildElement("geometry"); if (geometry.isNull()) continue; ViewGeometry viewGeometry(geometry); if (mp->itemType() == ModelPart::Wire) { if (viewGeometry.hasFlag(getTraceFlag())) { QLineF l = viewGeometry.line(); if (l.p1().x() == 0 && l.p1().y() == 0 && l.p2().x() == 0 && l.p2().y() == 0) { if (view.firstChildElement("connectors").isNull() && view.nextSiblingElement().isNull()) { DebugDialog::debug(QString("wire has zero length %1 in %2").arg(mp->moduleID()).arg(m_viewID)); zeroLength.append(mp); continue; } } } } QDomElement labelGeometry = view.firstChildElement("titleGeometry"); QDomElement layerHidden = view.firstChildElement("layerHidden"); ViewLayer::ViewLayerPlacement viewLayerPlacement = getViewLayerPlacement(mp, instance, view, viewGeometry); // use a function of the model index to ensure the same parts have the same ID across views long newID = ItemBase::getNextID(mp->modelIndex()); if (parentCommand == NULL) { viewGeometryConversionHack(viewGeometry, mp); ItemBase * itemBase = addItemAux(mp, viewLayerPlacement, viewGeometry, newID, true, m_viewID, false); if (itemBase != NULL) { if (locked) { itemBase->setMoveLock(true); } if (superpartOK) { superparts.insert(itemBase, superpartID); } while (!layerHidden.isNull()) { hidePartLayer(itemBase, ViewLayer::viewLayerIDFromXmlString(layerHidden.attribute("layer")), true); layerHidden = layerHidden.nextSiblingElement("layerHidden"); } //if (itemBase->itemType() == ModelPart::ResizableBoard) { //DebugDialog::debug("sticky"); //} if (itemBase->isBaseSticky() && itemBase->isLocalSticky()) { // make sure the icon is displayed itemBase->setLocalSticky(true); } zmap.insert(viewGeometry.z() - qFloor(viewGeometry.z()), itemBase); bool gotOne = false; if (!gotOne) { PaletteItem * paletteItem = qobject_cast(itemBase); if (paletteItem != NULL) { // wires don't have transforms //paletteItem->setTransforms(); // jrc 14 july 2013: this call seems redundant--transforms have already been set up by now gotOne = true; } } if (!gotOne) { Wire * wire = qobject_cast(itemBase); if (wire != NULL) { QDomElement extras = view.firstChildElement("wireExtras"); wire->setExtras(extras, this); gotOne = true; } } if (!gotOne) { Note * note = qobject_cast(itemBase); if (note != NULL) { note->setText(mp->instanceText(), true); gotOne = true; } } // use the modelIndex from mp, not from the newly created item, because we're mapping from the modelIndex in the xml file newItems.insert(mp->modelIndex(), itemBase); if (itemBase->itemType() != ModelPart::Wire) { itemBase->restorePartLabel(labelGeometry, getLabelViewLayerID(itemBase)); } } } else { // offset pasted items so we can differentiate them from the originals if (offsetPaste) { if (m_pasteOffset.x() != 0 || m_pasteOffset.y() != 0) { viewGeometry.offset((20 * m_pasteCount) + m_pasteOffset.x(), (20 * m_pasteCount) + m_pasteOffset.y()); } else if (boundingRect && !boundingRect->isNull()) { double dx = viewGeometry.loc().x() - boundingRect->left() + sceneCorner.x() + (20 * m_pasteCount); double dy = viewGeometry.loc().y() - boundingRect->top() + sceneCorner.y() + (20 * m_pasteCount); viewGeometry.setLoc(QPointF(dx, dy)); } } newAddItemCommand(crossViewType, mp, mp->moduleID(), viewLayerPlacement, viewGeometry, newID, false, mp->modelIndex(), false, parentCommand); if (superpartOK) { superparts2.insert(newID, superpartID); } // TODO: all this part specific stuff should be in the PartFactory if (Board::isBoard(mp) || mp->itemType() == ModelPart::Logo) { bool ok; double w = mp->localProp("width").toDouble(&ok); if (ok) { double h = mp->localProp("height").toDouble(&ok); if (ok) { new ResizeBoardCommand(this, newID, w, h, w, h, parentCommand); } } } else if (mp->itemType() == ModelPart::Note) { new ChangeNoteTextCommand(this, newID, mp->instanceText(), mp->instanceText(), viewGeometry.rect().size(), viewGeometry.rect().size(), parentCommand); } else if (mp->itemType() == ModelPart::Ruler) { QString w = mp->localProp("width").toString(); QString w2 = w; w.chop(2); int units = w2.endsWith("cm") ? 0 : 1; new ResizeBoardCommand(this, newID, w.toDouble(), units, w.toDouble(), units, parentCommand); mp->setLocalProp("width", ""); // ResizeBoardCommand won't execute if the width property is already set } if (locked) { new MoveLockCommand(this, newID, true, true, parentCommand); } while (!layerHidden.isNull()) { new HidePartLayerCommand(this, newID, ViewLayer::viewLayerIDFromXmlString(layerHidden.attribute("layer")), true, true, parentCommand); layerHidden = layerHidden.nextSiblingElement("layerHidden"); } if (!labelGeometry.isNull()) { QDomElement clone = labelGeometry.cloneNode(true).toElement(); bool ok; double x = clone.attribute("x").toDouble(&ok); if (ok) { if (m_pasteOffset.x() == 0 && m_pasteOffset.y() == 0) { int dx = (boundingRect) ? boundingRect->left() : 0; x = x - dx + sceneCorner.x() + (20 * m_pasteCount); } else { x += (20 * m_pasteCount) + m_pasteOffset.x(); } clone.setAttribute("x", QString::number(x)); } double y = clone.attribute("y").toDouble(&ok); if (ok) { if (m_pasteOffset.x() == 0 && m_pasteOffset.y() == 0) { int dy = boundingRect ? boundingRect->top() : 0; y = y - dy + sceneCorner.y() + (20 * m_pasteCount); } else { y += (20 * m_pasteCount) + m_pasteOffset.y(); } clone.setAttribute("y", QString::number(y)); } new RestoreLabelCommand(this, newID, clone, parentCommand); } newIDs << newID; if (mp->moduleID() == ModuleIDNames::WireModuleIDName) { addWireExtras(newID, view, parentCommand); } } } foreach (ModelPart * mp, zeroLength) { modelParts.removeOne(mp); mp->killViewItems(); m_sketchModel->removeModelPart(mp); delete mp; } foreach (ItemBase * sub, superparts.keys()) { ItemBase * super = findItem(superparts.value(sub)); if (super) { super->addSubpart(sub); } } foreach (long newID, superparts2.keys()) { AddSubpartCommand * asc = new AddSubpartCommand(this, crossViewType, superparts2.value(newID), newID, parentCommand); asc->setRedoOnly(); } if (parentCommand) { foreach (long id, newIDs) { new CheckStickyCommand(this, crossViewType, id, false, CheckStickyCommand::RemoveOnly, parentCommand); } } if (zmap.count() > 0) { double z = 0.5; foreach (ItemBase * itemBase, zmap.values()) { itemBase->slamZ(z); z += ViewLayer::getZIncrement(); } foreach (ViewLayer * viewLayer, m_viewLayers) { if (viewLayer != NULL) viewLayer->resetNextZ(z); } } QStringList alreadyConnected; QHash legs; // now restore connections foreach (ModelPart * mp, modelParts) { QDomElement instance = mp->instanceDomElement(); if (instance.isNull()) continue; QDomElement views = instance.firstChildElement("views"); if (views.isNull()) continue; QDomElement view = views.firstChildElement(viewName); if (view.isNull()) continue; QDomElement connectors = view.firstChildElement("connectors"); if (connectors.isNull()) { continue; } QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QString fromConnectorID = connector.attribute("connectorId"); ViewLayer::ViewLayerID connectorViewLayerID = ViewLayer::viewLayerIDFromXmlString(connector.attribute("layer")); bool gfs = connector.attribute("groundFillSeed").compare("true") == 0; if (gfs) { ItemBase * fromBase = newItems.value(mp->modelIndex(), NULL); if (fromBase) { ConnectorItem * fromConnectorItem = fromBase->findConnectorItemWithSharedID(fromConnectorID, ViewLayer::specFromID(connectorViewLayerID)); if (fromConnectorItem) { fromConnectorItem->setGroundFillSeed(true); } } } QDomElement connects = connector.firstChildElement("connects"); if (!connects.isNull()) { QDomElement connect = connects.firstChildElement("connect"); while (!connect.isNull()) { handleConnect(connect, mp, fromConnectorID, connectorViewLayerID, alreadyConnected, newItems, parentCommand, seekOutsideConnections); connect = connect.nextSiblingElement("connect"); } } QDomElement leg = connector.firstChildElement("leg"); if (!leg.isNull() && !leg.firstChildElement("point").isNull()) { if (parentCommand) { legs.insert(QString::number(ItemBase::getNextID(mp->modelIndex())) + "." + fromConnectorID, leg); } else { ItemBase * fromBase = newItems.value(mp->modelIndex(), NULL); if (fromBase) { legs.insert(QString::number(fromBase->id()) + "." + fromConnectorID, leg); } } } connector = connector.nextSiblingElement("connector"); } } // must do legs after all connections are set up foreach (QString key, legs.keys()) { int ix = key.indexOf("."); if (ix <= 0) continue; QDomElement leg = legs.value(key); long id = key.left(ix).toInt(); QString fromConnectorID = key.remove(0, ix + 1); QPolygonF poly = TextUtils::polygonFromElement(leg); if (poly.count() < 2) continue; if (parentCommand) { ChangeLegCommand * clc = new ChangeLegCommand(this, id, fromConnectorID, poly, poly, true, true, "copy", parentCommand); clc->setSimple(); } else { changeLeg(id, fromConnectorID, poly, true, "load"); } QDomElement bElement = leg.firstChildElement("bezier"); int bIndex = 0; while (!bElement.isNull()) { Bezier bezier = Bezier::fromElement(bElement); if (!bezier.isEmpty()) { if (parentCommand) { new ChangeLegCurveCommand(this, id, fromConnectorID, bIndex, &bezier, &bezier, parentCommand); } else { changeLegCurve(id, fromConnectorID, bIndex, &bezier); } } bElement = bElement.nextSiblingElement("bezier"); bIndex++; } } if (parentCommand == NULL) { foreach (ItemBase * item, newItems) { item->doneLoading(); if (item->isBaseSticky()) { stickyScoop(item, false, NULL); } } m_pasteCount = 0; this->scene()->clearSelection(); cleanUpWires(false, NULL); } else { if (offsetPaste) { // m_pasteCount used for offsetting paste items, not a count of how many items are pasted m_pasteCount++; } new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); } setIgnoreSelectionChangeEvents(false); m_pasteOffset = QPointF(0,0); } void SketchWidget::handleConnect(QDomElement & connect, ModelPart * mp, const QString & fromConnectorID, ViewLayer::ViewLayerID fromViewLayerID, QStringList & alreadyConnected, QHash & newItems, QUndoCommand * parentCommand, bool seekOutsideConnections) { bool ok; QHash otherNewItems; long modelIndex = connect.attribute("modelIndex").toLong(&ok); QString toConnectorID = connect.attribute("connectorId"); ViewLayer::ViewLayerID toViewLayerID = ViewLayer::viewLayerIDFromXmlString(connect.attribute("layer")); QString already = ((mp->modelIndex() <= modelIndex) ? QString("%1.%2.%3.%4.%5.%6") : QString("%4.%5.%6.%1.%2.%3")) .arg(mp->modelIndex()).arg(fromConnectorID).arg(fromViewLayerID) .arg(modelIndex).arg(toConnectorID).arg(toViewLayerID); if (alreadyConnected.contains(already)) return; alreadyConnected.append(already); if (parentCommand == NULL) { ItemBase * fromBase = newItems.value(mp->modelIndex(), NULL); ItemBase * toBase = newItems.value(modelIndex, NULL); if (toBase == NULL) { toBase = otherNewItems.value(modelIndex, NULL); } if (fromBase == NULL || toBase == NULL) { if (!seekOutsideConnections) return; if (fromBase == NULL) { fromBase = findItem(mp->modelIndex() * ModelPart::indexMultiplier); if (fromBase == NULL) return; } if (toBase == NULL) { toBase = findItem(modelIndex * ModelPart::indexMultiplier); if (toBase == NULL) return; } } ConnectorItem * fromConnectorItem = fromBase->findConnectorItemWithSharedID(fromConnectorID, ViewLayer::specFromID(fromViewLayerID)); ConnectorItem * toConnectorItem = toBase->findConnectorItemWithSharedID(toConnectorID, ViewLayer::specFromID(toViewLayerID)); if (fromConnectorItem == NULL || toConnectorItem == NULL) { return; } fromConnectorItem->connectTo(toConnectorItem); toConnectorItem->connectTo(fromConnectorItem); fromConnectorItem->connector()->connectTo(toConnectorItem->connector()); if (fromConnectorItem->attachedToItemType() == ModelPart::Wire && toConnectorItem->attachedToItemType() == ModelPart::Wire) { fromConnectorItem->setHidden(false); toConnectorItem->setHidden(false); } ratsnestConnect(fromConnectorItem, true); ratsnestConnect(toConnectorItem, true); return; } // single view because handle connect is called from loadModelPart which gets called for each view new ChangeConnectionCommand(this, BaseCommand::SingleView, ItemBase::getNextID(mp->modelIndex()), fromConnectorID, ItemBase::getNextID(modelIndex), toConnectorID, ViewLayer::specFromID(fromViewLayerID), true, parentCommand); } void SketchWidget::addWireExtras(long newID, QDomElement & view, QUndoCommand * parentCommand) { QDomElement extras = view.firstChildElement("wireExtras"); if (extras.isNull()) return; QDomElement copy(extras); new WireExtrasCommand(this, newID, copy, copy, parentCommand); } void SketchWidget::setWireExtras(long newID, QDomElement & extras) { Wire * wire = qobject_cast(findItem(newID)); if (wire == NULL) return; wire->setExtras(extras, this); } ItemBase * SketchWidget::addItem(const QString & moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, BaseCommand::CrossViewType crossViewType, const ViewGeometry & viewGeometry, long id, long modelIndex, AddDeleteItemCommand * originatingCommand) { if (m_referenceModel == NULL) return NULL; ItemBase * itemBase = NULL; ModelPart * modelPart = m_referenceModel->retrieveModelPart(moduleID); if (modelPart != NULL) { if (!m_blockUI) { QApplication::setOverrideCursor(Qt::WaitCursor); statusMessage(tr("loading part")); } itemBase = addItem(modelPart, viewLayerPlacement, crossViewType, viewGeometry, id, modelIndex, originatingCommand); if (!m_blockUI) { statusMessage(tr("done loading"), 2000); QApplication::restoreOverrideCursor(); } } return itemBase; } ItemBase * SketchWidget::addItem(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, BaseCommand::CrossViewType crossViewType, const ViewGeometry & viewGeometry, long id, long modelIndex, AddDeleteItemCommand * originatingCommand) { ItemBase * newItem = NULL; //if (checkAlreadyExists) { // newItem = findItem(id); // if (newItem != NULL) { // newItem->debugInfo("already exists"); // } //} if (newItem == NULL) { ModelPart * mp = NULL; if (modelIndex >= 0) { // used only with Paste, so far--this assures that parts created across views will share the same ModelPart mp = m_sketchModel->findModelPart(modelPart->moduleID(), id); } if (mp == NULL) { modelPart = m_sketchModel->addModelPart(m_sketchModel->root(), modelPart); } else { modelPart = mp; } if (modelPart == NULL) return NULL; newItem = addItemAux(modelPart, viewLayerPlacement, viewGeometry, id, true, m_viewID, false); } if (crossViewType == BaseCommand::CrossView) { //DebugDialog::debug(QString("emit item added")); emit itemAddedSignal(modelPart, newItem, viewLayerPlacement, viewGeometry, id, originatingCommand ? originatingCommand->dropOrigin() : NULL); //DebugDialog::debug(QString("after emit item added")); } return newItem; } ItemBase * SketchWidget::addItemAuxTemp(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, const ViewGeometry & viewGeometry, long id, bool doConnectors, ViewLayer::ViewID viewID, bool temporary) { modelPart = m_sketchModel->addModelPart(m_sketchModel->root(), modelPart); if (modelPart == NULL) return NULL; // this is very fucked up return addItemAux(modelPart, viewLayerPlacement, viewGeometry, id, doConnectors, viewID, temporary); } ItemBase * SketchWidget::addItemAux(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, const ViewGeometry & viewGeometry, long id, bool doConnectors, ViewLayer::ViewID viewID, bool temporary) { if (viewID == ViewLayer::UnknownView) { viewID = m_viewID; } if (doConnectors) { modelPart->initConnectors(); // is a no-op if connectors already in place } ItemBase * newItem = PartFactory::createPart(modelPart, viewLayerPlacement, viewID, viewGeometry, id, m_itemMenu, m_wireMenu, true); Wire * wire = qobject_cast(newItem); if (wire) { QString descr; bool ratsnest = viewGeometry.getRatsnest(); if (ratsnest) { setClipEnds((ClipableWire *) wire, true); descr = "ratsnest"; } else if (viewGeometry.getAnyTrace() ) { setClipEnds((ClipableWire *) wire, true); descr = "trace"; } else { wire->setNormal(true); descr = "wire"; } wire->setUp(getWireViewLayerID(viewGeometry, wire->viewLayerPlacement()), m_viewLayers, this); setWireVisible(wire); wire->updateConnectors(); addToScene(wire, wire->viewLayerID()); wire->addedToScene(temporary); wire->debugInfo("add " + descr); return wire; } if (modelPart->itemType() == ModelPart::Note) { newItem->setViewLayerID(getNoteViewLayerID(), m_viewLayers); newItem->setZValue(newItem->z()); newItem->setVisible(true); addToScene(newItem, getNoteViewLayerID()); newItem->addedToScene(temporary); return newItem; } bool ok; addPartItem(modelPart, viewLayerPlacement, (PaletteItem *) newItem, doConnectors, ok, viewID, temporary); newItem->debugInfo("add part"); setNewPartVisible(newItem); newItem->updateConnectors(); return newItem; } void SketchWidget::setNewPartVisible(ItemBase * itemBase) { Q_UNUSED(itemBase); // defaults to visible, so do nothing } void SketchWidget::checkSticky(long id, bool doEmit, bool checkCurrent, CheckStickyCommand * checkStickyCommand) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; if (itemBase->hidden() || itemBase->layerHidden()) { } else if (itemBase->isBaseSticky()) { stickyScoop(itemBase, checkCurrent, checkStickyCommand); } else { ItemBase * stickyOne = overSticky(itemBase); ItemBase * wasStickyOne = itemBase->stickingTo(); if (stickyOne != wasStickyOne) { if (wasStickyOne != NULL) { wasStickyOne->addSticky(itemBase, false); itemBase->addSticky(wasStickyOne, false); if (checkStickyCommand) { checkStickyCommand->stick(this, wasStickyOne->id(), itemBase->id(), false); } } if (stickyOne != NULL) { stickyOne->addSticky(itemBase, true); itemBase->addSticky(stickyOne, true); if (checkStickyCommand) { checkStickyCommand->stick(this, stickyOne->id(), itemBase->id(), true); } } } } if (doEmit) { checkStickySignal(id, false, false, checkStickyCommand); } } PaletteItem* SketchWidget::addPartItem(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, PaletteItem * paletteItem, bool doConnectors, bool & ok, ViewLayer::ViewID viewID, bool temporary) { ok = false; ViewLayer::ViewLayerID viewLayerID = getViewLayerID(modelPart, viewID, viewLayerPlacement); if (viewLayerID == ViewLayer::UnknownLayer) { // render it only if the layer is defined in the fzp file // if the view is not defined in the part file, without this condition // fritzing crashes return paletteItem; } QString error; bool result = paletteItem->renderImage(modelPart, viewID, m_viewLayers, viewLayerID, doConnectors, error); if (!result) { bool retry = false; switch (viewLayerID) { case ViewLayer::Copper0: viewLayerID = ViewLayer::Copper1; retry = true; break; case ViewLayer::Copper1: viewLayerID = ViewLayer::Copper0; retry = true; break; default: break; } if (retry) { result = paletteItem->renderImage(modelPart, viewID, m_viewLayers, viewLayerID, doConnectors, error); } } bool hideSuper = modelPart->hasSubparts() && !temporary && viewID == ViewLayer::SchematicView; if (result) { //DebugDialog::debug(QString("addPartItem %1").arg(viewID)); addToScene(paletteItem, paletteItem->viewLayerID()); if (hideSuper) { paletteItem->setEverVisible(false); paletteItem->setVisible(false); } paletteItem->loadLayerKin(m_viewLayers, viewLayerPlacement); foreach (ItemBase * lkpi, paletteItem->layerKin()) { this->scene()->addItem(lkpi); lkpi->setHidden(!layerIsVisible(lkpi->viewLayerID())); lkpi->setInactive(!layerIsActive(lkpi->viewLayerID())); if (hideSuper) { lkpi->setEverVisible(false); lkpi->setVisible(false); } } //DebugDialog::debug(QString("after layerkin %1").arg(viewID)); ok = true; } else { // nobody falls through to here now? FMessageBox::information(NULL, QObject::tr("Fritzing"), QObject::tr("Error reading file %1: %2.").arg(modelPart->path()).arg(error) ); DebugDialog::debug(QString("addPartItem renderImage failed %1 %2").arg(modelPart->moduleID()).arg(error)); //paletteItem->modelPart()->removeViewItem(paletteItem); //delete paletteItem; //return NULL; scene()->addItem(paletteItem); //paletteItem->setVisible(false); } paletteItem->addedToScene(temporary); return paletteItem; } void SketchWidget::addToScene(ItemBase * item, ViewLayer::ViewLayerID viewLayerID) { scene()->addItem(item); item->setSelected(true); item->setHidden(!layerIsVisible(viewLayerID)); item->setInactive(!layerIsActive(viewLayerID)); } ItemBase * SketchWidget::findItem(long id) { // TODO: this needs to be optimized: could make a hash table long baseid = id / ModelPart::indexMultiplier; foreach (QGraphicsItem * item, this->scene()->items()) { ItemBase* base = dynamic_cast(item); if (base == NULL) continue; if (base->id() == id) { return base; } if (base->id() / ModelPart::indexMultiplier == baseid) { // found chief or layerkin ItemBase * chief = base->layerKinChief(); if (chief->id() == id) return chief; foreach (ItemBase * lk, chief->layerKin()) { if (lk->id() == id) return lk; } return chief; } } return NULL; } void SketchWidget::deleteItem(long id, bool deleteModelPart, bool doEmit, bool later) { ItemBase * pitem = findItem(id); DebugDialog::debug(QString("delete item (1) %1 %2 %3 %4").arg(id).arg(doEmit).arg(m_viewID).arg((long) pitem, 0, 16) ); if (pitem != NULL) { deleteItem(pitem, deleteModelPart, doEmit, later); } else { if (doEmit) { emit itemDeletedSignal(id); } } } void SketchWidget::deleteItem(ItemBase * itemBase, bool deleteModelPart, bool doEmit, bool later) { long id = itemBase->id(); DebugDialog::debug(QString("delete item (2) %1 %2 %3 %4").arg(id).arg(itemBase->title()).arg(m_viewID).arg((long) itemBase, 0, 16) ); // this is a hack to try to workaround a Qt 4.7 crash in QGraphicsSceneFindItemBspTreeVisitor::visit // when using a custom boundingRect, after deleting an item, it still appears on the visit list. // // the problem arises because the legItems are used to calculate the boundingRect() of the item. // But in the destructor, the childItems are deleted first, then the BSP tree is updated // at that point, the boundingRect() will return a different value than what's in the BSP tree, // which is the old value of the boundingRect before the legs were deleted. if (itemBase->hasRubberBandLeg()) { DebugDialog::debug("kill rubberBand"); itemBase->killRubberBandLeg(); } if (m_infoView != NULL) { m_infoView->unregisterCurrentItemIf(itemBase->id()); } if (itemBase == this->m_lastPaletteItemSelected) { setLastPaletteItemSelected(NULL); } // m_lastSelected.removeOne(itemBase); hack for 4.5.something if (deleteModelPart) { ModelPart * modelPart = itemBase->modelPart(); if (modelPart != NULL) { m_sketchModel->removeModelPart(modelPart); delete modelPart; } } itemBase->removeLayerKin(); this->scene()->removeItem(itemBase); if (later) { itemBase->deleteLater(); } else { delete itemBase; } if (doEmit) { emit itemDeletedSignal(id); } } void SketchWidget::deleteSelected(Wire * wire, bool minus) { QSet itemBases; if (wire) { itemBases << wire; } else { foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->moveLock()) continue; itemBase = itemBase->layerKinChief(); if (itemBase->moveLock()) continue; itemBases.insert(itemBase); } } if (itemBases.count() == 0) return; // assumes ratsnest is not mixed with other itembases bool rats = true; foreach (ItemBase * itemBase, itemBases) { Wire * wire = qobject_cast(itemBase); if (wire == NULL) { rats = false; break; } if (!wire->getRatsnest()) { rats = false; break; } } if (!rats) { cutDeleteAux("Delete", minus, wire); // wire is selected in this case, so don't bother sending it along return; } QUndoCommand * parentCommand = new QUndoCommand(tr("Delete ratsnest")); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); deleteRatsnest(wire, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::cutDeleteAux(QString undoStackMessage, bool minus, Wire * wire) { //DebugDialog::debug("before delete"); // get sitems first, before calling stackSelectionState // because selectedItems will return an empty list const QList sitems = scene()->selectedItems(); QSet deletedItems; if (minus && wire != NULL) { // called from wire context menu "delete to bendpoint" deletedItems.insert(wire); } else { foreach (QGraphicsItem * sitem, sitems) { if (!canDeleteItem(sitem, sitems.count())) continue; // canDeleteItem insures dynamic_cast(sitem)->layerKinChief() won't break ItemBase * itemBase = dynamic_cast(sitem)->layerKinChief(); if (itemBase->superpart()) { deletedItems.insert(itemBase->superpart()); foreach (ItemBase * sub, itemBase->superpart()->subparts()) deletedItems.insert(sub); } else if (itemBase->subparts().count() > 0) { deletedItems.insert(itemBase); foreach (ItemBase * sub, itemBase->subparts()) deletedItems.insert(sub); } else { deletedItems.insert(itemBase); } } if (!minus) { QSet allWires; foreach (ItemBase * itemBase, deletedItems) { QList connectorItems; foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { connectorItems.append(connectorItem); ConnectorItem * cross = connectorItem->getCrossLayerConnectorItem(); if (cross) connectorItems.append(cross); } foreach (ConnectorItem * connectorItem, connectorItems) { foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() != ModelPart::Wire) continue; Wire * wire = qobject_cast(toConnectorItem->attachedTo()); if (wire->getRatsnest()) continue; //if (!wire->isTraceType(getTraceFlag())) continue; // removes connected wires across views when commented out QList wires; wire->collectDirectWires(wires); foreach (Wire * w, wires) { allWires.insert(w); } } } } if (allWires.count() > 0) { QList wires = allWires.toList(); wires.at(0)->collectDirectWires(wires); foreach (Wire * w, wires) { deletedItems.insert(w); } } } } if (deletedItems.count() <= 0) { return; } QString string; if (deletedItems.count() == 1) { ItemBase * firstItem = *(deletedItems.begin()); string = tr("%1 %2").arg(undoStackMessage).arg(firstItem->title()); } else { string = tr("%1 %2 items").arg(undoStackMessage).arg(QString::number(deletedItems.count())); } QUndoCommand * parentCommand = new QUndoCommand(string); parentCommand->setText(string); deleteAux(deletedItems, parentCommand, true); } void SketchWidget::deleteAux(QSet & deletedItems, QUndoCommand * parentCommand, bool doPush) { stackSelectionState(false, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); deleteMiddle(deletedItems, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); foreach (ItemBase * itemBase, deletedItems) { if (itemBase->superpart() != NULL) { AddSubpartCommand * asc = new AddSubpartCommand(this, BaseCommand::CrossView, itemBase->superpart()->id(), itemBase->id(), parentCommand); asc->setUndoOnly(); } } // actual delete commands must come last for undo to work properly foreach (ItemBase * itemBase, deletedItems) { this->makeDeleteItemCommand(itemBase, BaseCommand::CrossView, parentCommand); } if (doPush) { m_undoStack->waitPush(parentCommand, PropChangeDelay); } } bool isVirtualWireConnector(ConnectorItem * toConnectorItem) { return (qobject_cast(toConnectorItem->attachedTo()) != NULL); } void SketchWidget::deleteMiddle(QSet & deletedItems, QUndoCommand * parentCommand) { foreach (ItemBase * itemBase, deletedItems) { foreach (ConnectorItem * fromConnectorItem, itemBase->cachedConnectorItems()) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(fromConnectorItem->attachedToViewLayerID()), false, parentCommand); fromConnectorItem->tempRemove(toConnectorItem, false); toConnectorItem->tempRemove(fromConnectorItem, false); } fromConnectorItem = fromConnectorItem->getCrossLayerConnectorItem(); if (fromConnectorItem) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(fromConnectorItem->attachedToViewLayerID()), false, parentCommand); fromConnectorItem->tempRemove(toConnectorItem, false); toConnectorItem->tempRemove(fromConnectorItem, false); } } } } } void SketchWidget::deleteTracesSlot(QSet & deletedItems, QHash & otherDeletedItems, QList & deletedIDs, bool isForeign, QUndoCommand * parentCommand) { Q_UNUSED(parentCommand); foreach (ItemBase * itemBase, deletedItems) { if (itemBase->itemType() == ModelPart::Wire) continue; if (isForeign) { itemBase = findItem(itemBase->id()); if (itemBase == NULL) continue; // only foreign items need move/transform; the current view carries its own viewgeometry itemBase->saveGeometry(); } bool isJumper = (itemBase->itemType() == ModelPart::Jumper); foreach (ConnectorItem * fromConnectorItem, itemBase->cachedConnectorItems()) { QList connectorItems; foreach (ConnectorItem * ci, fromConnectorItem->connectedToItems()) connectorItems << ci; ConnectorItem * crossConnectorItem = fromConnectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem) { foreach (ConnectorItem * ci, crossConnectorItem->connectedToItems()) connectorItems << ci; } foreach (ConnectorItem * toConnectorItem, connectorItems) { Wire * wire = qobject_cast(toConnectorItem->attachedTo()); if (wire == NULL) continue; if (isJumper || (wire->isTraceType(getTraceFlag()))) { QList wires; QList ends; wire->collectChained(wires, ends); foreach (Wire * w, wires) { if (!deletedIDs.contains(w->id())) { otherDeletedItems.insert(w, this); deletedIDs.append(w->id()); } } } } } } } ChangeConnectionCommand * SketchWidget::extendChangeConnectionCommand(BaseCommand::CrossViewType crossView, long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, QUndoCommand * parentCommand) { ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) { return NULL; // for now } ItemBase * toItem = findItem(toID); if (toItem == NULL) { return NULL; // for now } ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, viewLayerPlacement); if (fromConnectorItem == NULL) return NULL; // for now ConnectorItem * toConnectorItem = findConnectorItem(toItem, toConnectorID, viewLayerPlacement); if (toConnectorItem == NULL) return NULL; // for now return extendChangeConnectionCommand(crossView, fromConnectorItem, toConnectorItem, viewLayerPlacement, connect, parentCommand); } ChangeConnectionCommand * SketchWidget::extendChangeConnectionCommand(BaseCommand::CrossViewType crossView, ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, QUndoCommand * parentCommand) { // cases: // delete // paste // drop (wire) // drop (part) // move (part) // move (wire) // drag wire end // drag out new wire ItemBase * fromItem = fromConnectorItem->attachedTo(); if (fromItem == NULL) { return NULL; // for now } ItemBase * toItem = toConnectorItem->attachedTo(); if (toItem == NULL) { return NULL; // for now } return new ChangeConnectionCommand(this, crossView, fromItem->id(), fromConnectorItem->connectorSharedID(), toItem->id(), toConnectorItem->connectorSharedID(), viewLayerPlacement, connect, parentCommand); } long SketchWidget::createWire(ConnectorItem * from, ConnectorItem * to, ViewGeometry::WireFlags wireFlags, bool dontUpdate, BaseCommand::CrossViewType crossViewType, QUndoCommand * parentCommand) { if (from == NULL || to == NULL) { return -1; } long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; QPointF fromPos = from->sceneAdjustedTerminalPoint(NULL); viewGeometry.setLoc(fromPos); QPointF toPos = to->sceneAdjustedTerminalPoint(NULL); QLineF line(0, 0, toPos.x() - fromPos.x(), toPos.y() - fromPos.y()); viewGeometry.setLine(line); viewGeometry.setWireFlags(wireFlags); DebugDialog::debug(QString("creating wire %11: %1, flags: %6, from %7 %8, to %9 %10, frompos: %2 %3, topos: %4 %5") .arg(newID) .arg(fromPos.x()).arg(fromPos.y()) .arg(toPos.x()).arg(toPos.y()) .arg(wireFlags) .arg(from->attachedToTitle()).arg(from->connectorSharedID()) .arg(to->attachedToTitle()).arg(to->connectorSharedID()) .arg(m_viewID) ); ViewLayer::ViewLayerPlacement viewLayerPlacement = createWireViewLayerPlacement(from, to); new AddItemCommand(this, crossViewType, ModuleIDNames::WireModuleIDName, viewLayerPlacement, viewGeometry, newID, false, -1, parentCommand); new CheckStickyCommand(this, crossViewType, newID, false, CheckStickyCommand::RemoveOnly, parentCommand); ChangeConnectionCommand * ccc = new ChangeConnectionCommand(this, crossViewType, from->attachedToID(), from->connectorSharedID(), newID, "connector0", viewLayerPlacement, // ViewLayer::specFromID(from->attachedToViewLayerID()) true, parentCommand); ccc->setUpdateConnections(!dontUpdate); ccc = new ChangeConnectionCommand(this, crossViewType, to->attachedToID(), to->connectorSharedID(), newID, "connector1", viewLayerPlacement, // ViewLayer::specFromID(to->attachedToViewLayerID()) true, parentCommand); ccc->setUpdateConnections(!dontUpdate); return newID; } ViewLayer::ViewLayerPlacement SketchWidget::createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to) { Q_UNUSED(to); return from->attachedToViewLayerPlacement(); } void SketchWidget::moveItem(long id, ViewGeometry & viewGeometry, bool updateRatsnest) { ItemBase * itemBase = findItem(id); if (itemBase != NULL) { if (updateRatsnest) { ratsnestConnect(itemBase, true); } itemBase->moveItem(viewGeometry); if (m_infoView) m_infoView->updateLocation(itemBase); } } void SketchWidget::simpleMoveItem(long id, QPointF p) { ItemBase * itemBase = findItem(id); if (itemBase != NULL) { itemBase->setItemPos(p); if (m_infoView) m_infoView->updateLocation(itemBase); } } void SketchWidget::moveItem(long id, const QPointF & p, bool updateRatsnest) { ItemBase * itemBase = findItem(id); if (itemBase != NULL) { itemBase->setPos(p); if (updateRatsnest) { ratsnestConnect(itemBase, true); } emit itemMovedSignal(itemBase); if (m_infoView) m_infoView->updateLocation(itemBase); } } void SketchWidget::updateWire(long id, const QString & connectorID, bool updateRatsnest) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; Wire * wire = qobject_cast(itemBase); if (wire == NULL) return; ConnectorItem * connectorItem = findConnectorItem(wire, connectorID, ViewLayer::specFromID(wire->viewLayerID())); if (connectorItem == NULL) return; if (updateRatsnest) { ratsnestConnect(connectorItem, true); } wire->simpleConnectedMoved(connectorItem); } void SketchWidget::rotateItem(long id, double degrees) { //DebugDialog::debug(QString("rotating %1 %2").arg(id).arg(degrees) ); if (!isVisible()) return; ItemBase * itemBase = findItem(id); if (itemBase != NULL) { itemBase->rotateItem(degrees, false); if (m_infoView) m_infoView->updateRotation(itemBase); } } void SketchWidget::transformItem(long id, const QMatrix & matrix) { ItemBase * itemBase = findItem(id); if (itemBase != NULL) { itemBase->transformItem2(matrix); if (m_infoView) m_infoView->updateRotation(itemBase); } } void SketchWidget::flipItem(long id, Qt::Orientations orientation) { //DebugDialog::debug(QString("flipping %1 %2").arg(id).arg(orientation) ); if (!isVisible()) return; ItemBase * itemBase = findItem(id); if (itemBase != NULL) { itemBase->flipItem(orientation); if (m_infoView) m_infoView->updateRotation(itemBase); ratsnestConnect(itemBase, true); } } void SketchWidget::changeWire(long fromID, QLineF line, QPointF pos, bool updateConnections, bool updateRatsnest) { /* DebugDialog::debug(QString("change wire %1; %2,%3,%4,%5; %6,%7; %8") .arg(fromID) .arg(line.x1()) .arg(line.y1()) .arg(line.x2()) .arg(line.y2()) .arg(pos.x()) .arg(pos.y()) .arg(updateConnections) ); */ ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) return; Wire* wire = dynamic_cast(fromItem); if (wire == NULL) return; wire->setLineAnd(line, pos, true); if (updateConnections) { QList already; wire->updateConnections(wire->connector0(), false, already); wire->updateConnections(wire->connector1(), false, already); } if (updateRatsnest) { ratsnestConnect(wire->connector0(), true); ratsnestConnect(wire->connector1(), true); } } void SketchWidget::rotateLeg(long fromID, const QString & fromConnectorID, const QPolygonF & leg, bool active) { ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) { DebugDialog::debug("rotate leg exit 1"); return; } ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, ViewLayer::specFromID(fromItem->viewLayerID())); if (fromConnectorItem == NULL) { DebugDialog::debug("rotate leg exit 2"); return; } fromConnectorItem->rotateLeg(leg, active); } void SketchWidget::changeLeg(long fromID, const QString & fromConnectorID, const QPolygonF & leg, bool relative, const QString & why) { changeLegAux(fromID, fromConnectorID, leg, false, relative, true, why); } void SketchWidget::recalcLeg(long fromID, const QString & fromConnectorID, const QPolygonF & leg, bool relative, bool active, const QString & why) { changeLegAux(fromID, fromConnectorID, leg, true, relative, active, why); } void SketchWidget::changeLegAux(long fromID, const QString & fromConnectorID, const QPolygonF & leg, bool reset, bool relative, bool active, const QString & why) { ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) { DebugDialog::debug("change leg exit 1"); return; } ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, ViewLayer::specFromID(fromItem->viewLayerID())); if (fromConnectorItem == NULL) { DebugDialog::debug("change leg exit 2"); return; } if (reset) { fromConnectorItem->resetLeg(leg, relative, active, why); } else { fromConnectorItem->setLeg(leg, relative, why); } QList already; fromItem->updateConnections(fromConnectorItem, false, already); } void SketchWidget::selectItem(long id, bool state, bool updateInfoView, bool doEmit) { this->clearHoldingSelectItem(); ItemBase * item = findItem(id); if (item != NULL) { item->setSelected(state); if(updateInfoView) { // show something in the info view, even if it's not selected viewItemInfo(item); } if (doEmit) { emit itemSelectedSignal(id, state); } } PaletteItem *pitem = dynamic_cast(item); if(pitem) { setLastPaletteItemSelected(pitem); } } void SketchWidget::selectDeselectAllCommand(bool state) { this->clearHoldingSelectItem(); SelectItemCommand * cmd = stackSelectionState(false, NULL); cmd->setText(state ? tr("Select All") : tr("Deselect")); cmd->setSelectItemType( state ? SelectItemCommand::SelectAll : SelectItemCommand::DeselectAll ); m_undoStack->push(cmd); } void SketchWidget::selectAllItems(bool state, bool doEmit) { foreach (QGraphicsItem * item, this->scene()->items()) { item->setSelected(state); } if (doEmit) { emit selectAllItemsSignal(state, false); } } void SketchWidget::cut() { copy(); cutDeleteAux("Cut", false, NULL); } void SketchWidget::copy() { QList tlBases; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item); if (itemBase == NULL) continue; if (itemBase->getRatsnest()) continue; if (tlBases.contains(itemBase)) continue; QList superSubs = collectSuperSubs(itemBase); if (superSubs.count() > 0) { foreach (ItemBase * supersub, superSubs) { if (!tlBases.contains(supersub)) tlBases.append(supersub); } continue; } tlBases.append(itemBase); } QList bases; sortAnyByZ(tlBases, bases); // sort them in z-order so the copies also appear in the same order copyAux(bases, true); } void SketchWidget::copyAux(QList & bases, bool saveBoundingRects) { for (int i = bases.count() - 1; i >= 0; i--) { Wire * wire = qobject_cast(bases.at(i)); if (wire == NULL) continue; if (!wire->getTrace()) continue; QList ends; QList wires; wire->collectChained(wires, ends); if (ends.count() < 2) { // trace is dangling bases.removeAt(i); continue; } foreach (ConnectorItem * end, ends) { if (bases.contains(end->attachedTo())) continue; if (bases.contains(end->attachedTo()->layerKinChief())) continue; // trace is dangling bases.removeAt(i); break; } } if (bases.count() == 0) { return; } QByteArray itemData; QList modelIndexes; copyHeart(bases, saveBoundingRects, itemData, modelIndexes); // only preserve connections for copied items that connect to each other QByteArray newItemData = removeOutsideConnections(itemData, modelIndexes); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-dnditemsdata", newItemData); mimeData->setData("text/plain", newItemData); QClipboard *clipboard = QApplication::clipboard(); if (clipboard == NULL) { // shouldn't happen delete mimeData; return; } clipboard->setMimeData(mimeData, QClipboard::Clipboard); } void SketchWidget::pasteHeart(QByteArray & itemData, bool seekOutsideConnections) { QList modelParts; QHash boundingRects; if (m_sketchModel->paste(m_referenceModel, itemData, modelParts, boundingRects, true)) { QRectF r; QRectF boundingRect = boundingRects.value(this->viewName(), r); QList newIDs; this->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, true, &r, seekOutsideConnections, newIDs); } } void SketchWidget::copyHeart(QList & bases, bool saveBoundingRects, QByteArray & itemData, QList & modelIndexes) { QXmlStreamWriter streamWriter(&itemData); streamWriter.writeStartElement("module"); streamWriter.writeAttribute("fritzingVersion", Version::versionString()); if (saveBoundingRects) { QRectF itemsBoundingRect; foreach (ItemBase * itemBase, bases) { if (itemBase->getRatsnest()) continue; itemsBoundingRect |= itemBase->sceneBoundingRect(); } QHash boundingRects; boundingRects.insert(m_viewName, itemsBoundingRect); emit copyBoundingRectsSignal(boundingRects); streamWriter.writeStartElement("boundingRects"); foreach (QString key, boundingRects.keys()) { streamWriter.writeStartElement("boundingRect"); streamWriter.writeAttribute("name", key); QRectF r = boundingRects.value(key); streamWriter.writeAttribute("rect", QString("%1 %2 %3 %4") .arg(r.left()) .arg(r.top()) .arg(r.width()) .arg(r.height())); streamWriter.writeEndElement(); } streamWriter.writeEndElement(); } streamWriter.writeStartElement("instances"); foreach (ItemBase * base, bases) { if (base->getRatsnest()) continue; base->modelPart()->saveInstances("", streamWriter, false); modelIndexes.append(base->modelPart()->modelIndex()); } streamWriter.writeEndElement(); streamWriter.writeEndElement(); } QByteArray SketchWidget::removeOutsideConnections(const QByteArray & itemData, QList & modelIndexes) { // now have to remove each connection that points to a part outside of the set of parts being copied QDomDocument domDocument; QString errorStr; int errorLine; int errorColumn; bool result = domDocument.setContent(itemData, &errorStr, &errorLine, &errorColumn); if (!result) return ___emptyByteArray___; QDomElement root = domDocument.documentElement(); if (root.isNull()) { return ___emptyByteArray___; } QDomElement instances = root.firstChildElement("instances"); if (instances.isNull()) return ___emptyByteArray___; QDomElement instance = instances.firstChildElement("instance"); while (!instance.isNull()) { QDomElement views = instance.firstChildElement("views"); if (!views.isNull()) { QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement connectors = view.firstChildElement("connectors"); if (!connectors.isNull()) { QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement connects = connector.firstChildElement("connects"); if (!connects.isNull()) { QDomElement connect = connects.firstChildElement("connect"); QList toDelete; while (!connect.isNull()) { long modelIndex = connect.attribute("modelIndex").toLong(); if (!modelIndexes.contains(modelIndex)) { toDelete.append(connect); } connect = connect.nextSiblingElement("connect"); } foreach (QDomElement connect, toDelete) { QDomNode removed = connects.removeChild(connect); if (removed.isNull()) { DebugDialog::debug("removed is null"); } } } connector = connector.nextSiblingElement("connector"); } } view = view.nextSiblingElement(); } } instance = instance.nextSiblingElement("instance"); } return domDocument.toByteArray(); } void SketchWidget::dragEnterEvent(QDragEnterEvent *event) { if (dragEnterEventAux(event)) { setupAutoscroll(false); event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("application/x-dndsketchdata")) { if (event->source() != this) { m_movingItem = NULL; SketchWidget * other = dynamic_cast(event->source()); if (other == NULL) { throw "drag enter event from unknown source"; } // TODO: this checkunder will probably never work m_checkUnder = other->m_checkUnder; m_movingItem = new QGraphicsSvgItem(); m_movingItem->setSharedRenderer(other->m_movingSVGRenderer); this->scene()->addItem(m_movingItem); m_movingItem->setPos(mapToScene(event->pos()) - other->m_movingSVGOffset); } event->acceptProposedAction(); } else { // subclass seems to call acceptProposedAction so don't invoke it // QGraphicsView::dragEnterEvent(event); event->ignore(); } } bool SketchWidget::dragEnterEventAux(QDragEnterEvent *event) { if (!event->mimeData()->hasFormat("application/x-dnditemdata")) return false; scene()->setSceneRect(scene()->sceneRect()); // prevents inadvertent scrolling when dragging in items from the parts bin m_clearSceneRect = true; m_droppingWire = false; QByteArray itemData = event->mimeData()->data("application/x-dnditemdata"); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString moduleID; QPointF offset; dataStream >> moduleID >> offset; moduleID = checkDroppedModuleID(moduleID); ModelPart * modelPart = m_referenceModel->retrieveModelPart(moduleID); if (modelPart == NULL) return false; if (!canDropModelPart(modelPart)) return false; m_droppingWire = (modelPart->itemType() == ModelPart::Wire); m_droppingOffset = offset; if (ItemDrag::cache().contains(this)) { m_droppingItem->setVisible(true); } else { ViewGeometry viewGeometry; QPointF p = QPointF(this->mapToScene(event->pos())) - offset; viewGeometry.setLoc(p); long fromID = ItemBase::getNextID(); bool doConnectors = true; // create temporary item for dragging m_droppingItem = addItemAuxTemp(modelPart, defaultViewLayerPlacement(modelPart), viewGeometry, fromID, doConnectors, m_viewID, true); QSizeF size = m_droppingItem->sceneBoundingRect().size(); if (size.width() < offset.x() || size.height() < offset.y()) { offset = m_droppingOffset = QPointF(size.width() / 2, size.height() / 2); } QHash savedItems; QHash savedWires; findAlignmentAnchor(m_droppingItem, savedItems, savedWires); ItemDrag::cache().insert(this, m_droppingItem); //m_droppingItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); connect(ItemDrag::singleton(), SIGNAL(dragIsDoneSignal(ItemDrag *)), this, SLOT(dragIsDoneSlot(ItemDrag *))); } //ItemDrag::_setPixmapVisible(false); m_checkUnder.clear(); if (checkUnder()) { m_checkUnder.append(m_droppingItem); } // make sure relevant layer is visible ViewLayer::ViewLayerID viewLayerID; if (m_droppingWire) { viewLayerID = getWireViewLayerID(m_droppingItem->getViewGeometry(), m_droppingItem->viewLayerPlacement()); } else if(modelPart->moduleID().compare(ModuleIDNames::RulerModuleIDName) == 0) { viewLayerID = getRulerViewLayerID(); } else if(modelPart->moduleID().compare(ModuleIDNames::NoteModuleIDName) == 0) { viewLayerID = getNoteViewLayerID(); } else { viewLayerID = getPartViewLayerID(); } ensureLayerVisible(viewLayerID); // TODO: if any layer in the dragged part is visible, then don't bother calling ensureLayerVisible return true; } bool SketchWidget::canDropModelPart(ModelPart * modelPart) { LayerList layerList = modelPart->viewLayers(viewID()); foreach (ViewLayer::ViewLayerID viewLayerID, m_viewLayers.keys()) { if (layerList.contains(viewLayerID)) return true; } return false; } void SketchWidget::dragLeaveEvent(QDragLeaveEvent * event) { Q_UNUSED(event); turnOffAutoscroll(); if (m_droppingItem != NULL) { if (m_clearSceneRect) { m_clearSceneRect = false; scene()->setSceneRect(QRectF()); } m_droppingItem->setVisible(false); //ItemDrag::_setPixmapVisible(true); } else { // dragging sketch items if (m_movingItem) { delete m_movingItem; m_movingItem = NULL; } } //QGraphicsView::dragLeaveEvent(event); // we override QGraphicsView::dragEnterEvent so don't call the subclass dragLeaveEvent here } void SketchWidget::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("application/x-dnditemdata")) { dragMoveHighlightConnector(event->pos()); event->acceptProposedAction(); return; } if (event->mimeData()->hasFormat("application/x-dndsketchdata")) { if (event->source() == this) { m_globalPos = this->mapToGlobal(event->pos()); if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) { QPointF p = GraphicsUtils::calcConstraint(m_mousePressGlobalPos, m_globalPos); m_globalPos.setX(p.x()); m_globalPos.setY(p.y()); } moveItems(m_globalPos, true, m_rubberBandLegWasEnabled); m_moveEventCount++; } else { SketchWidget * other = dynamic_cast(event->source()); if (other == NULL) { throw "drag move event from unknown source"; } m_movingItem->setPos(mapToScene(event->pos()) - other->m_movingSVGOffset); } event->acceptProposedAction(); return; } //QGraphicsView::dragMoveEvent(event); // we override QGraphicsView::dragEnterEvent so don't call the subclass dragMoveEvent here } void SketchWidget::dragMoveHighlightConnector(QPoint eventPos) { if (m_droppingItem == NULL) return; m_globalPos = this->mapToGlobal(eventPos); checkAutoscroll(m_globalPos); QPointF loc = this->mapToScene(eventPos) - m_droppingOffset; if (m_alignToGrid && (m_alignmentItem != NULL)) { QPointF l = m_alignmentItem->getViewGeometry().loc(); alignLoc(loc, m_alignmentStartPoint, loc, l); //QPointF q = m_alignmentItem->pos(); //if (q != l) { // DebugDialog::debug(QString("m alignment %1 %2, %3 %4").arg(q.x()).arg(q.y()).arg(l.x()).arg(l.y())); //} } m_droppingItem->setItemPos(loc); if (m_checkUnder.contains(m_droppingItem)) { m_droppingItem->findConnectorsUnder(); } } void SketchWidget::dropEvent(QDropEvent *event) { m_alignmentItem = NULL; turnOffAutoscroll(); clearHoldingSelectItem(); if (event->mimeData()->hasFormat("application/x-dnditemdata")) { dropItemEvent(event); } else if (event->mimeData()->hasFormat("application/x-dndsketchdata")) { if (m_movingItem) { delete m_movingItem; m_movingItem = NULL; } ConnectorItem::clearEqualPotentialDisplay(); if (event->source() == this) { checkMoved(false); m_savedItems.clear(); m_savedWires.clear(); } else { SketchWidget * other = dynamic_cast(event->source()); if (other == NULL) { throw "drag and drop from unknown source"; } ItemBase * ref = other->m_moveReferenceItem; QPointF originalPos = ref->getViewGeometry().loc(); other->copyDrop(); QPointF startLocal = other->mapFromGlobal(QPoint(other->m_mousePressGlobalPos.x(), other->m_mousePressGlobalPos.y())); QPointF sceneLocal = other->mapToScene(startLocal.x(), startLocal.y()); QPointF offset = sceneLocal - originalPos; m_pasteOffset = this->mapToScene(event->pos()) - offset - originalPos; DebugDialog::debug(QString("other %1 %2, event %3 %4") .arg(startLocal.x()).arg(startLocal.y()) .arg(event->pos().x()).arg(event->pos().y()) ); m_pasteCount = 0; emit dropPasteSignal(this); } event->acceptProposedAction(); } else { QGraphicsView::dropEvent(event); } DebugDialog::debug("after drop event"); } void SketchWidget::dropItemEvent(QDropEvent *event) { if (m_droppingItem == NULL) return; if (m_clearSceneRect) { m_clearSceneRect = false; scene()->setSceneRect(QRectF()); } ModelPart * modelPart = m_droppingItem->modelPart(); if (modelPart == NULL) return; if (modelPart->modelPartShared() == NULL) return; ModelPart::ItemType itemType = modelPart->itemType(); QUndoCommand* parentCommand = new TemporaryCommand(tr("Add %1").arg(m_droppingItem->title())); stackSelectionState(false, parentCommand); CleanUpWiresCommand * cuw = new CleanUpWiresCommand(this, CleanUpWiresCommand::Noop, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); m_droppingItem->saveGeometry(); ViewGeometry viewGeometry = m_droppingItem->getViewGeometry(); long fromID = m_droppingItem->id(); BaseCommand::CrossViewType crossViewType = BaseCommand::CrossView; switch (modelPart->itemType()) { case ModelPart::Ruler: case ModelPart::Note: // rulers and notes are local to a particular view crossViewType = BaseCommand::SingleView; break; default: break; } ViewLayer::ViewLayerPlacement viewLayerPlacement; getDroppedItemViewLayerPlacement(modelPart, viewLayerPlacement); AddItemCommand * addItemCommand = newAddItemCommand(crossViewType, modelPart, modelPart->moduleID(), viewLayerPlacement, viewGeometry, fromID, true, -1, true, parentCommand); addItemCommand->setDropOrigin(this); new SetDropOffsetCommand(this, fromID, m_droppingOffset, parentCommand); new CheckStickyCommand(this, crossViewType, fromID, false, CheckStickyCommand::RemoveOnly, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->addRedo(fromID); new ShowLabelFirstTimeCommand(this, crossViewType, fromID, true, true, parentCommand); if (modelPart->itemType() == ModelPart::Wire && !m_lastColorSelected.isEmpty()) { new WireColorChangeCommand(this, fromID, m_lastColorSelected, m_lastColorSelected, 1.0, 1.0, parentCommand); } bool gotConnector = false; // jrc: 24 aug 2010: don't see why restoring color on dropped item is necessary //QList connectorItems; foreach (ConnectorItem * connectorItem, m_droppingItem->cachedConnectorItems()) { //connectorItem->setMarked(false); //connectorItems.append(connectorItem); ConnectorItem * to = connectorItem->overConnectorItem(); if (to != NULL) { to->connectorHover(to->attachedTo(), false); connectorItem->setOverConnectorItem(NULL); // clean up extendChangeConnectionCommand(BaseCommand::CrossView, connectorItem, to, ViewLayer::specFromID(connectorItem->attachedToViewLayerID()), true, parentCommand); gotConnector = true; } //connectorItem->clearConnectorHover(); } //foreach (ConnectorItem * connectorItem, connectorItems) { //if (!connectorItem->marked()) { //connectorItem->restoreColor(false, 0, true); //} //} //m_droppingItem->clearConnectorHover(); clearTemporaries(); killDroppingItem(); if (gotConnector) { new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); cuw->setDirection(CleanUpWiresCommand::UndoOnly); } if (itemType == ModelPart::CopperFill) { m_undoStack->waitPushTemporary(parentCommand, 10); } else { m_undoStack->waitPush(parentCommand, 10); } event->acceptProposedAction(); emit dropSignal(event->pos()); } SelectItemCommand* SketchWidget::stackSelectionState(bool pushIt, QUndoCommand * parentCommand) { // if pushIt assumes m_undoStack->beginMacro has previously been called //DebugDialog::debug(QString("stacking")); // DebugDialog::debug(QString("stack selection state %1 %2").arg(pushIt).arg((long) parentCommand)); SelectItemCommand* selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); const QList sitems = scene()->selectedItems(); for (int i = 0; i < sitems.size(); ++i) { ItemBase * base = ItemBase::extractTopLevelItemBase(sitems.at(i)); if (base == NULL) continue; selectItemCommand->addUndo(base->id()); //DebugDialog::debug(QString("\tstacking %1").arg(base->id())); } selectItemCommand->setText(tr("Selection")); if (pushIt) { m_undoStack->push(selectItemCommand); } return selectItemCommand; } bool SketchWidget::moveByArrow(double dx, double dy, QKeyEvent * event) { bool rubberBandLegEnabled = false; DebugDialog::debug(QString("move by arrow %1").arg(event == NULL ? false : event->isAutoRepeat())); if (event == NULL || !event->isAutoRepeat()) { m_dragBendpointWire = NULL; clearHoldingSelectItem(); m_savedItems.clear(); m_savedWires.clear(); m_moveEventCount = 0; m_arrowTotalX = m_arrowTotalY = 0; QPoint cp = QCursor::pos(); QPoint wp = this->mapFromGlobal(cp); QPointF sp = this->mapToScene(wp); Wire * wire = dynamic_cast(scene()->itemAt(sp, QTransform())); bool draggingWire = false; if (wire != NULL) { if (canChainWire(wire) && wire->hasConnections()) { if (canDragWire(wire) && ((event->modifiers() & altOrMetaModifier()) != 0)) { prepDragWire(wire); draggingWire = true; } } } if (!draggingWire) { rubberBandLegEnabled = (event != NULL) && ((event->modifiers() & altOrMetaModifier()) != 0); prepMove(NULL, rubberBandLegEnabled, true); } if (m_savedItems.count() == 0) return false; m_mousePressScenePos = this->mapToScene(this->rect().center()); m_movingByArrow = true; } else { //DebugDialog::debug("autorepeat"); } if (event != NULL && (event->modifiers() & Qt::ShiftModifier)) { dx *= 10; dy *= 10; } if (m_alignToGrid) { dx *= gridSizeInches() * GraphicsUtils::SVGDPI; dy *= gridSizeInches() * GraphicsUtils::SVGDPI; } m_arrowTotalX += dx; m_arrowTotalY += dy; QPoint globalPos = mapFromScene(m_mousePressScenePos + QPointF(m_arrowTotalX, m_arrowTotalY)); globalPos = mapToGlobal(globalPos); moveItems(globalPos, false, rubberBandLegEnabled); m_moveEventCount++; return true; } void SketchWidget::mousePressEvent(QMouseEvent *event) { m_originatingItem = NULL; m_draggingBendpoint = false; if (m_movingByArrow) return; m_movingByMouse = true; QMouseEvent * hackEvent = NULL; if (event->button() == Qt::MidButton && !spaceBarIsPressed()) { m_middleMouseIsPressed = true; setDragMode(QGraphicsView::ScrollHandDrag); setCursor(Qt::OpenHandCursor); // make the event look like a left button press to fool the underlying drag mode implementation event = hackEvent = new QMouseEvent(event->type(), event->pos(), event->globalPos(), Qt::LeftButton, event->buttons() | Qt::LeftButton, event->modifiers()); } m_dragBendpointWire = NULL; m_spaceBarWasPressed = spaceBarIsPressed(); if (m_spaceBarWasPressed) { InfoGraphicsView::mousePressEvent(event); if (hackEvent) delete hackEvent; return; } //setRenderHint(QPainter::Antialiasing, false); clearHoldingSelectItem(); m_savedItems.clear(); m_savedWires.clear(); m_moveEventCount = 0; m_holdingSelectItemCommand = stackSelectionState(false, NULL); m_mousePressScenePos = mapToScene(event->pos()); m_mousePressGlobalPos = event->globalPos(); squashShapes(m_mousePressScenePos); QList items = this->items(event->pos()); QGraphicsItem* wasItem = getClickedItem(items); m_anyInRotation = false; // mouse event gets passed through to individual QGraphicsItems QGraphicsView::mousePressEvent(event); if (m_anyInRotation) { m_anyInRotation = false; unsquashShapes(); return; } items = this->items(event->pos()); QGraphicsItem* item = getClickedItem(items); if (item != wasItem) { // if the item was deleted during mousePressEvent // for example, by shift-clicking a connectorItem return; } unsquashShapes(); if (item == NULL) { if (items.length() == 1) { // if we unambiguously click on a partlabel whose owner is unselected, go ahead and activate it PartLabel * partLabel = dynamic_cast(items[0]); if (partLabel != NULL) { partLabel->owner()->setSelected(true); return; } } clickBackground(event); if (m_infoView != NULL) { m_infoView->viewItemInfo(this, NULL, true); } return; } PartLabel * partLabel = dynamic_cast(item); if (partLabel != NULL) { viewItemInfo(partLabel->owner()); setLastPaletteItemSelectedIf(partLabel->owner()); return; } // Note's child items (at the moment) are the resize grip and the text editor Note * note = dynamic_cast(item->parentItem()); if (note != NULL) { return; } Stripbit * stripbit = dynamic_cast(item); if (stripbit) return; ItemBase * itemBase = dynamic_cast(item); if (itemBase) { viewItemInfo(itemBase); setLastPaletteItemSelectedIf(itemBase); } if (resizingBoardPress(itemBase)) { return; } ConnectorItem * connectorItem = dynamic_cast(wasItem); if (connectorItem != NULL && connectorItem->isDraggingLeg()) { return; } Wire * wire = dynamic_cast(item); if ((event->button() == Qt::LeftButton) && (wire != NULL)) { if (canChainWire(wire) && wire->hasConnections()) { if (canDragWire(wire) && ((event->modifiers() & altOrMetaModifier()) != 0)) { prepDragWire(wire); return; } else { m_dragCurve = curvyWiresIndicated(event->modifiers()) && wire->canHaveCurve(); m_dragBendpointWire = wire; m_dragBendpointPos = event->pos(); if (m_connectorDragWire) { // if you happen to drag on a wire which is on top of a connector // drag the bendpoint on the wire rather than the new wire from the connector // maybe a better approach to block mousePressConnectorEvent? delete m_connectorDragWire; m_connectorDragWire = NULL; } return; } } } if (resizingJumperItemPress(itemBase)) { return; } if (event->button() == Qt::LeftButton) { prepMove(itemBase ? itemBase : dynamic_cast(item->parentItem()), (event->modifiers() & altOrMetaModifier()) != 0, true); if (m_alignToGrid && (itemBase == NULL) && (event->modifiers() == Qt::NoModifier)) { Wire * wire = dynamic_cast(item->parentItem()); if (wire != NULL && wire->draggingEnd()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem != NULL) { m_draggingBendpoint = (connectorItem->connectionsCount() > 0); this->m_alignmentStartPoint = mapToScene(event->pos()) - connectorItem->sceneAdjustedTerminalPoint(NULL); } } } m_moveReferenceItem = m_savedItems.count() > 0 ? m_savedItems.values().at(0) : NULL; setupAutoscroll(true); } } void SketchWidget::prepMove(ItemBase * originatingItem, bool rubberBandLegEnabled, bool includeRatsnest) { m_originatingItem = originatingItem; m_rubberBandLegWasEnabled = rubberBandLegEnabled; m_checkUnder.clear(); //DebugDialog::debug("prep move check under = false"); QSet wires; QList items; foreach (QGraphicsItem * gitem, this->scene()->selectedItems()) { ItemBase *itemBase = dynamic_cast(gitem); if (itemBase == NULL) continue; if (itemBase->moveLock()) continue; items.append(itemBase); } //DebugDialog::debug(QString("prep move items %1").arg(items.count())); int originalItemsCount = items.count(); for (int i = 0; i < items.count(); i++) { ItemBase * itemBase = items[i]; if (itemBase->itemType() == ModelPart::Wire) { Wire * wire = qobject_cast(itemBase); if (wire->isTraceType(getTraceFlag())) { wires.insert(wire); // wire->debugInfo("adding wire"); } else if (includeRatsnest && wire->getRatsnest()) { wires.insert(wire); } continue; } ItemBase * chief = itemBase->layerKinChief(); if (chief->moveLock()) continue; m_savedItems.insert(chief->id(), chief); //chief->debugInfo("adding saved"); if (chief->isSticky()) { foreach(ItemBase * sitemBase, chief->stickyList()) { if (sitemBase->isVisible()) { if (sitemBase->itemType() == ModelPart::Wire) { Wire * wire = qobject_cast(sitemBase); if (wire->isTraceType(getTraceFlag())) { wires.insert(wire); //wire->debugInfo("adding wire"); } else if (includeRatsnest && wire->getRatsnest()) { wires.insert(wire); } } else { m_savedItems.insert(sitemBase->layerKinChief()->id(), sitemBase); //sitemBase->debugInfo("adding sitem saved"); if (!items.contains(sitemBase)) { items.append(sitemBase); } } } } } QSet set; if (collectFemaleConnectees(chief, set)) { // for historical reasons returns true if chief has male connectors if (i < originalItemsCount) { m_checkUnder.append(chief); } } foreach (ItemBase * sitemBase, set) { if (!items.contains(sitemBase)) { items.append(sitemBase); } } QSet tempWires; chief->collectWireConnectees(tempWires); foreach (Wire * wire, tempWires) { if (wire->isTraceType(getTraceFlag())) { wires.insert(wire); } else if (includeRatsnest && wire->getRatsnest()) { wires.insert(wire); } } } for (int i = m_checkUnder.count() - 1; i >= 0; i--) { ItemBase * itemBase = m_checkUnder.at(i); foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { bool gotOne = false; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (m_savedItems.value(toConnectorItem->attachedToID(), NULL) != NULL) { m_checkUnder.removeAt(i); gotOne = true; break; } } if (gotOne) break; } } if (wires.count() > 0) { QList freeWires; categorizeDragWires(wires, freeWires); m_checkUnder.append(freeWires); } categorizeDragLegs(rubberBandLegEnabled); foreach (ItemBase * itemBase, m_savedItems.values()) { itemBase->saveGeometry(); } foreach (Wire * w, m_savedWires.keys()) { w->saveGeometry(); } findAlignmentAnchor(originatingItem, m_savedItems, m_savedWires); } void SketchWidget::alignLoc(QPointF & loc, const QPointF startPoint, const QPointF newLoc, const QPointF originalLoc) { // in the standard case, startpoint is the center of the connectorItem, newLoc is the current mouse position, // originalLoc is the original mouse position. newpos is therefore the new position of the center of the connectorItem // and ny and ny make up the nearest grid point. nx, ny - newloc give just the offset from the grid, which is then // applied to loc, which is the location of the item being dragged QPointF newPos = startPoint + newLoc - originalLoc; double ny = GraphicsUtils::getNearestOrdinate(newPos.y(), gridSizeInches() * GraphicsUtils::SVGDPI); double nx = GraphicsUtils::getNearestOrdinate(newPos.x(), gridSizeInches() * GraphicsUtils::SVGDPI); loc.setX(loc.x() + nx - newPos.x()); loc.setY(loc.y() + ny - newPos.y()); } void SketchWidget::findAlignmentAnchor(ItemBase * originatingItem, QHash & savedItems, QHash & savedWires) { m_alignmentItem = NULL; if (!m_alignToGrid) return; if (originatingItem) { foreach (ConnectorItem * connectorItem, originatingItem->cachedConnectorItems()) { m_alignmentStartPoint = connectorItem->sceneAdjustedTerminalPoint(NULL); m_alignmentItem = originatingItem; return; } if (canAlignToTopLeft(originatingItem)) { m_alignmentStartPoint = originatingItem->pos(); m_alignmentItem = originatingItem; return; } if (canAlignToCenter(originatingItem)) { m_alignmentStartPoint = originatingItem->sceneBoundingRect().center(); m_alignmentItem = originatingItem; return; } } foreach (ItemBase * itemBase, savedItems) { foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { m_alignmentStartPoint = connectorItem->sceneAdjustedTerminalPoint(NULL); m_alignmentItem = itemBase; return; } } foreach (Wire * w, savedWires.keys()) { m_alignmentItem = w; m_alignmentStartPoint = w->connector0()->sceneAdjustedTerminalPoint(NULL); return; } foreach (ItemBase * itemBase, savedItems) { if (canAlignToTopLeft(itemBase)) { m_alignmentStartPoint = itemBase->pos(); m_alignmentItem = itemBase; return; } if (canAlignToCenter(itemBase)) { m_alignmentStartPoint = itemBase->sceneBoundingRect().center(); m_alignmentItem = itemBase; return; } } } struct ConnectionThing { Wire * wire; ConnectionStatus status[2]; }; void SketchWidget::categorizeDragLegs(bool rubberBandLegEnabled) { m_stretchingLegs.clear(); if (!rubberBandLegEnabled) return; QSet passives; foreach (ItemBase * itemBase, m_savedItems.values()) { if (itemBase->itemType() == ModelPart::Wire) continue; if (!itemBase->hasRubberBandLeg()) continue; // 1. we are dragging a part with rubberBand legs which are attached to some part not being dragged along (i.e. a breadboard) // so we stretch those attached legs // 2. a part has rubberBand legs attached to multiple parts, and we are only dragging some of the parts foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { if (!connectorItem->hasRubberBandLeg()) continue; if (connectorItem->connectionsCount() == 0) continue; bool treatAsNormal = true; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) continue; if (m_savedItems.value(toConnectorItem->attachedTo()->layerKinChief()->id(), NULL)) continue; treatAsNormal = false; break; } if (treatAsNormal) continue; if (itemBase->isSelected()) { // itemBase is being dragged, but the connector doesn't come along connectorItem->prepareToStretch(true); m_stretchingLegs.insert(itemBase, connectorItem); continue; } // itemBase has connectors stuck into multiple parts, not all of which are being dragged // but we're in a loop of savedItems, so we have to treat it later passives.insert(itemBase); } } foreach (ItemBase * itemBase, passives) { // we're not actually dragging the itemBase // one of its connectors is coming along for the ride m_savedItems.remove(itemBase->id()); foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { if (!connectorItem->hasRubberBandLeg()) continue; if (connectorItem->connectionsCount() == 0) continue; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) continue; ItemBase * chief = toConnectorItem->attachedTo()->layerKinChief(); if (m_savedItems.value(chief->id(), NULL) == NULL) { // connected to another part // treat it as passive as well } // the connector is passively dragged along with the part it is connected to // but the part it is attached to stays put connectorItem->prepareToStretch(false); m_stretchingLegs.insert(chief, connectorItem); break; } } } } void SketchWidget::categorizeDragWires(QSet & wires, QList & freeWires) { foreach (Wire * w, wires) { QList chainedWires; QList ends; w->collectChained(chainedWires, ends); foreach (Wire * ww, chainedWires) { wires.insert(ww); } } QList connectionThings; QHash ctHash; foreach (Wire * w, wires) { ConnectionThing * ct = new ConnectionThing; ct->wire = w; ct->status[0] = ct->status[1] = UNDETERMINED_; connectionThings.append(ct); ctHash.insert(w, ct); } // handle free first foreach (Wire * w, wires) { if (w->getTrace()) continue; QList pairs; pairs << w->connector0() << w->connector1(); for (int i = 0; i < pairs.count(); i++) { ConnectorItem * ci = pairs.at(i); if (ci->connectionsCount() == 0) { ConnectionThing * ct = ctHash.value(ci->attachedTo()); if (ct->status[i] != UNDETERMINED_) continue; // if one end is FREE, treat all connected wires as free (except possibly if the other end connector is attached to something) QList chainedWires; QList ends; ct->wire->collectChained(chainedWires, ends); ends.clear(); foreach (Wire * ww, chainedWires) { ends.append(ww->connector0()); ends.append(ww->connector1()); } foreach (ConnectorItem * end, ends) { if (end->connectionsCount() == 0) { ctHash.value(end->attachedTo())->status[i] = FREE_; } else { bool onlyWires = true; foreach (ConnectorItem * to, end->connectedToItems()) { if (to->attachedToItemType() != ModelPart::Wire) { onlyWires = false; break; } } if (onlyWires) { ctHash.value(end->attachedTo())->status[i] = FREE_; } } } } } } int noChangeCount = 0; QList outWires; while (connectionThings.count() > 0) { ConnectionThing * ct = connectionThings.takeFirst(); bool changed = false; QList from; from.append(ct->wire->connector0()); from.append(ct->wire->connector1()); for (int i = 0; i < 2; i++) { if (ct->status[i] != UNDETERMINED_) continue; foreach (ConnectorItem * toConnectorItem, from.at(i)->connectedToItems()) { if (m_savedItems.keys().contains(toConnectorItem->attachedTo()->layerKinChief()->id())) { changed = true; ct->status[i] = IN_; break; } bool notWire = toConnectorItem->attachedToItemType() != ModelPart::Wire; if (notWire || outWires.contains(toConnectorItem->attachedTo())) { changed = true; ct->status[i] = OUT_; break; } } if (ct->status[i] != UNDETERMINED_) continue; ItemBase * stickingTo = ct->wire->stickingTo(); if (stickingTo != NULL) { QPointF p = from.at(i)->sceneAdjustedTerminalPoint(NULL); if (stickingTo->contains(stickingTo->mapFromScene(p))) { if (m_savedItems.keys().contains(stickingTo->layerKinChief()->id())) { ct->status[i] = IN_; changed = true; } } } if (ct->status[i] != UNDETERMINED_) continue; // it's not connected and not stuck if (ct->wire->getTrace() && from.at(i)->connectionsCount() == 0) { QPointF p = from.at(i)->sceneAdjustedTerminalPoint(NULL); foreach (QGraphicsItem * item, scene()->items(p)) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; ct->status[i] = m_savedItems.keys().contains(itemBase->layerKinChief()->id()) ? IN_ : OUT_; changed = true; break; } } if (ct->status[i] != UNDETERMINED_) continue; if (from.at(i)->connectionsCount() == 0) { DebugDialog::debug("FREE_ wire should not be found at this point"); } } if (ct->status[0] != UNDETERMINED_ && ct->status[1] != UNDETERMINED_) { if (ct->status[0] == IN_) { if (ct->status[1] == IN_ || ct->status[1] == FREE_) { m_savedItems.insert(ct->wire->id(), ct->wire); //ct->wire->debugInfo("adding saved free"); if (ct->status[1] == FREE_) freeWires.append(ct->wire); } else { // attach the connector that stays IN m_savedWires.insert(ct->wire, ct->wire->connector0()); //ct->wire->debugInfo("adding saved in"); } } else if (ct->status[0] == OUT_) { if (ct->status[1] == IN_) { // attach the connector that stays in m_savedWires.insert(ct->wire, ct->wire->connector1()); } else { // don't drag this; both ends are connected OUT outWires.append(ct->wire); } } else /* ct->status[0] == FREE_ */ { if (ct->status[1] == IN_) { // attach wire that stays IN m_savedItems.insert(ct->wire->id(), ct->wire); freeWires.append(ct->wire); } else if (ct->status[1] == FREE_) { // both sides are free, so if the wire is selected, drag it if (ct->wire->isSelected()) { m_savedItems.insert(ct->wire->id(), ct->wire); freeWires.append(ct->wire); //ct->wire->debugInfo("adding saved free 2"); } else { outWires.append(ct->wire); } } else { // don't drag this; both ends are connected OUT outWires.append(ct->wire); } } delete ct; noChangeCount = 0; } else { connectionThings.append(ct); if (changed) { noChangeCount = 0; } else { if (++noChangeCount > connectionThings.count()) { QList cts; foreach (ConnectionThing * ct, connectionThings) { // if one end is OUT and the other end is unaccounted for at this pass, then both ends are OUT if ((ct->status[0] == FREE_ || ct->status[0] == OUT_) || (ct->status[1] == FREE_ || ct->status[1] == OUT_)) { noChangeCount = 0; outWires.append(ct->wire); delete ct; } else { cts.append(ct); } } if (noChangeCount == 0) { // get ready for another pass, we got rid of some connectionThings.clear(); foreach (ConnectionThing * ct, cts) { connectionThings.append(ct); } } else { // we've elimated all OUT items so mark everybody IN foreach (ConnectionThing * ct, connectionThings) { m_savedItems.insert(ct->wire->id(), ct->wire); //ct->wire->debugInfo("adding saved in 2"); delete ct; } connectionThings.clear(); } } } } } } void SketchWidget::clickBackground(QMouseEvent *) { // in here if you clicked on the sketch itself, } void SketchWidget::prepDragWire(Wire * wire) { bool drag = true; foreach (ConnectorItem * toConnectorItem, wire->connector0()->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { m_savedWires.insert(qobject_cast(toConnectorItem->attachedTo()), toConnectorItem); } else { drag = false; break; } } if (drag) { foreach (ConnectorItem * toConnectorItem, wire->connector1()->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { m_savedWires.insert(qobject_cast(toConnectorItem->attachedTo()), toConnectorItem); } else { drag = false; break; } } } if (!drag) { m_savedWires.clear(); return; } m_savedItems.clear(); m_savedItems.insert(wire->id(), wire); //wire->debugInfo("adding saved wire"); wire->saveGeometry(); foreach (Wire * w, m_savedWires.keys()) { w->saveGeometry(); } setupAutoscroll(true); } void SketchWidget::prepDragBendpoint(Wire * wire, QPoint eventPos, bool dragCurve) { m_bendpointWire = wire; wire->saveGeometry(); ViewGeometry vg = m_bendpointVG = wire->getViewGeometry(); QPointF newPos = mapToScene(eventPos); if (dragCurve) { setupAutoscroll(true); wire->initDragCurve(newPos); wire->grabMouse(); unsquashShapes(); return; } QPointF oldPos = wire->pos(); QLineF oldLine = wire->line(); Bezier left, right; bool curved = wire->initNewBendpoint(newPos, left, right); //DebugDialog::debug(QString("oldpos"), oldPos); //DebugDialog::debug(QString("oldline p1"), oldLine.p1()); //DebugDialog::debug(QString("oldline p2"), oldLine.p2()); QLineF newLine(oldLine.p1(), newPos - oldPos); wire->setLine(newLine); if (curved) wire->changeCurve(&left); vg.setLoc(newPos); QLineF newLine2(QPointF(0,0), oldLine.p2() + oldPos - newPos); vg.setLine(newLine2); ConnectorItem * oldConnector1 = wire->connector1(); m_connectorDragWire = this->createTempWireForDragging(wire, wire->modelPart(), oldConnector1, vg, wire->viewLayerPlacement()); if (curved) { right.translateToZero(); m_connectorDragWire->changeCurve(&right); } ConnectorItem * newConnector1 = m_connectorDragWire->connector1(); foreach (ConnectorItem * toConnectorItem, oldConnector1->connectedToItems()) { oldConnector1->tempRemove(toConnectorItem, false); toConnectorItem->tempRemove(oldConnector1, false); newConnector1->tempConnectTo(toConnectorItem, false); toConnectorItem->tempConnectTo(newConnector1, false); } oldConnector1->tempConnectTo(m_connectorDragWire->connector0(), false); m_connectorDragWire->connector0()->tempConnectTo(oldConnector1, false); m_connectorDragConnector = oldConnector1; setupAutoscroll(true); m_connectorDragWire->initDragEnd(m_connectorDragWire->connector0(), newPos); m_connectorDragWire->grabMouse(); unsquashShapes(); //m_connectorDragWire->debugInfo("grabbing mouse"); } bool SketchWidget::collectFemaleConnectees(ItemBase * itemBase, QSet & items) { Q_UNUSED(itemBase); Q_UNUSED(items); return false; } bool SketchWidget::checkUnder() { return false; }; bool SketchWidget::draggingWireEnd() { if (m_connectorDragWire != NULL) return true; QGraphicsItem * mouseGrabberItem = scene()->mouseGrabberItem(); Wire * wire = dynamic_cast(mouseGrabberItem); if (wire == NULL) { ConnectorItem * connectorItem = dynamic_cast(mouseGrabberItem); if (connectorItem == NULL) return false; if (connectorItem->attachedToItemType() != ModelPart::Wire) return false; wire = qobject_cast(connectorItem->attachedTo()); } // wire->debugInfo("mouse grabber"); return wire->draggingEnd(); } void SketchWidget::mouseMoveEvent(QMouseEvent *event) { // if its just dragging a wire end do default // otherwise handle all move action here if (m_movingByArrow) return; QPointF scenePos = mapToScene(event->pos()); double posx = scenePos.x() / GraphicsUtils::SVGDPI; double posy = scenePos.y() / GraphicsUtils::SVGDPI; if ( event->buttons() & (Qt::LeftButton | Qt::RightButton ) ) { QRectF selectionRect = this->scene()->selectionArea().boundingRect(); double width = selectionRect.width() / GraphicsUtils::SVGDPI; double height = selectionRect.height() / GraphicsUtils::SVGDPI; emit cursorLocationSignal(posx, posy, width, height); //DebugDialog::debug(QString("pos= %1,%2 size= %3 %4").arg(posx).arg(posy).arg(width).arg(height)); } else { emit cursorLocationSignal(posx, posy); //DebugDialog::debug(QString("pos= %1,%2").arg(posx).arg(posy)); } if (m_dragBendpointWire != NULL) { Wire * tempWire = m_dragBendpointWire; m_dragBendpointWire = NULL; prepDragBendpoint(tempWire, m_dragBendpointPos, m_dragCurve); m_draggingBendpoint = true; DebugDialog::debug("dragging bendpoint"); this->m_alignmentStartPoint = mapToScene(m_dragBendpointPos); // not sure this will be correct... return; } if (m_spaceBarWasPressed) { InfoGraphicsView::mouseMoveEvent(event); return; } if (m_savedItems.count() > 0) { if ((event->buttons() & Qt::LeftButton) && !draggingWireEnd()) { m_globalPos = event->globalPos(); if ((m_globalPos - m_mousePressGlobalPos).manhattanLength() >= QApplication::startDragDistance()) { QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-dndsketchdata", NULL); QDrag * drag = new QDrag(this); drag->setMimeData(mimeData); //QBitmap bitmap = *CursorMaster::MoveCursor->bitmap(); //drag->setDragCursor(bitmap, Qt::MoveAction); QPointF offset; QString svg = makeMoveSVG(GraphicsUtils::SVGDPI, GraphicsUtils::StandardFritzingDPI, offset); m_movingSVGRenderer = new QSvgRenderer(new QXmlStreamReader(svg)); m_movingSVGOffset = m_mousePressScenePos - offset; m_moveEventCount = 0; // reset m_moveEventCount to make sure that equal potential highlights are cleared m_movingByMouse = false; drag->exec(); delete m_movingSVGRenderer; m_movingSVGRenderer = NULL; return; } } } m_moveEventCount++; if (m_alignToGrid && m_draggingBendpoint) { QPointF sp(scenePos); alignLoc(sp, sp, QPointF(0,0), QPointF(0,0)); QPointF p = mapFromScene(sp); QPoint pp(qRound(p.x()), qRound(p.y())); QPointF q = mapToGlobal(pp); QMouseEvent alignedEvent(event->type(), pp, QPoint(q.x(), q.y()), event->button(), event->buttons(), event->modifiers()); //DebugDialog::debug(QString("sketch move event %1,%2").arg(sp.x()).arg(sp.y())); QGraphicsView::mouseMoveEvent(&alignedEvent); return; } if (draggingWireEnd()) { // DebugDialog::debug("dragging wire end"); checkAutoscroll(event->globalPos()); } QList squashed; if (event->buttons() == Qt::NoButton) { squashShapes(scenePos); } QGraphicsView::mouseMoveEvent(event); unsquashShapes(); } QString SketchWidget::makeMoveSVG(double printerScale, double dpi, QPointF & offset) { QRectF itemsBoundingRect; foreach (ItemBase * itemBase, m_savedItems.values()) { itemsBoundingRect |= itemBase->sceneBoundingRect(); } double width = itemsBoundingRect.width(); double height = itemsBoundingRect.height(); offset = itemsBoundingRect.topLeft(); QString outputSVG = TextUtils::makeSVGHeader(printerScale, dpi, width, height); foreach (ItemBase * itemBase, m_savedItems.values()) { Wire * wire = qobject_cast(itemBase); if (wire != NULL) { outputSVG.append(makeWireSVG(wire, offset, dpi, printerScale, true)); } else { outputSVG.append(TextUtils::makeRectSVG(itemBase->sceneBoundingRect(), offset, dpi, printerScale)); } } //outputSVG.append(makeRectSVG(itemsBoundingRect, offset, dpi, printerScale)); outputSVG += ""; return outputSVG; } void SketchWidget::moveItems(QPoint globalPos, bool checkAutoScrollFlag, bool rubberBandLegEnabled) { if (checkAutoScrollFlag) { bool result = checkAutoscroll(globalPos); if (!result) return; } QPoint q = mapFromGlobal(globalPos); QPointF scenePos = mapToScene(q); if (m_alignToGrid && (m_alignmentItem != NULL)) { QPointF currentParentPos = m_alignmentItem->mapToParent(m_alignmentItem->mapFromScene(scenePos)); QPointF buttonDownParentPos = m_alignmentItem->mapToParent(m_alignmentItem->mapFromScene(m_mousePressScenePos)); alignLoc(scenePos, m_alignmentStartPoint, currentParentPos, buttonDownParentPos); } /* DebugDialog::debug(QString("scroll 1 sx:%1 sy:%2 sbx:%3 sby:%4 qx:%5 qy:%6") .arg(scenePos.x()).arg(scenePos.y()) .arg(m_mousePressScenePos.x()).arg(m_mousePressScenePos.y()) .arg(q.x()).arg(q.y()) ); */ if (m_moveEventCount == 0) { // first time m_moveDisconnectedFromFemale.clear(); foreach (ItemBase * item, m_savedItems) { if (item->itemType() == ModelPart::Wire) continue; //DebugDialog::debug(QString("disconnecting from female %1").arg(item->instanceTitle())); disconnectFromFemale(item, m_savedItems, m_moveDisconnectedFromFemale, false, rubberBandLegEnabled, NULL); } } foreach (ItemBase * itemBase, m_savedItems) { QPointF currentParentPos = itemBase->mapToParent(itemBase->mapFromScene(scenePos)); QPointF buttonDownParentPos = itemBase->mapToParent(itemBase->mapFromScene(m_mousePressScenePos)); itemBase->setPos(itemBase->getViewGeometry().loc() + currentParentPos - buttonDownParentPos); foreach (ConnectorItem * connectorItem, m_stretchingLegs.values(itemBase)) { connectorItem->stretchBy(currentParentPos - buttonDownParentPos); } if (m_checkUnder.contains(itemBase)) { findConnectorsUnder(itemBase); } /* DebugDialog::debug(QString("scroll 2 lx:%1 ly:%2 cpx:%3 cpy:%4 qx:%5 qy:%6 px:%7 py:%8") .arg(item->getViewGeometry().loc().x()).arg(item->getViewGeometry().loc().y()) .arg(currentParentPos.x()).arg(currentParentPos.y()) .arg(buttonDownParentPos.x()).arg(buttonDownParentPos.y()) .arg(item->pos().x()).arg(item->pos().y()) ); */ } foreach (Wire * wire, m_savedWires.keys()) { wire->simpleConnectedMoved(m_savedWires.value(wire)); } //DebugDialog::debug(QString("done move items %1").arg(QTime::currentTime().msec()) ); if (m_infoView) { if (m_originatingItem) { m_infoView->updateLocation(m_originatingItem->layerKinChief()); } else { foreach (ItemBase * itemBase, m_savedItems) { m_infoView->updateLocation(itemBase->layerKinChief()); } } } } void SketchWidget::findConnectorsUnder(ItemBase * item) { Q_UNUSED(item); } void SketchWidget::mouseReleaseEvent(QMouseEvent *event) { //setRenderHint(QPainter::Antialiasing, true); //DebugDialog::debug("sketch mouse release event"); m_draggingBendpoint = false; if (m_movingByArrow) return; m_alignmentItem = NULL; m_movingByMouse = false; m_dragBendpointWire = NULL; ConnectorItem::clearEqualPotentialDisplay(); if (m_spaceBarWasPressed) { QMouseEvent * hackEvent = NULL; if (m_middleMouseIsPressed) { // make the event look like a left button press to fool the underlying drag mode implementation event = hackEvent = new QMouseEvent(event->type(), event->pos(), event->globalPos(), Qt::LeftButton, event->buttons() | Qt::LeftButton, event->modifiers()); } InfoGraphicsView::mouseReleaseEvent(event); m_spaceBarWasPressed = false; if (m_middleMouseIsPressed) { m_middleMouseIsPressed = false; setDragMode(QGraphicsView::RubberBandDrag); setCursor(Qt::ArrowCursor); } //DebugDialog::debug("turning off spacebar was"); if (hackEvent) delete hackEvent; return; } if (resizingBoardRelease()) { InfoGraphicsView::mouseReleaseEvent(event); return; } if (resizingJumperItemRelease()) { InfoGraphicsView::mouseReleaseEvent(event); return; } turnOffAutoscroll(); QGraphicsView::mouseReleaseEvent(event); if (m_connectorDragWire != NULL) { // remove again (may not have been removed earlier) if (m_connectorDragWire->scene() != NULL) { removeDragWire(); //m_infoView->unregisterCurrentItem(); updateInfoView(); } if (m_bendpointWire) { // click on wire but no drag: restore original state of wire foreach (ConnectorItem * toConnectorItem, m_connectorDragWire->connector1()->connectedToItems()) { m_connectorDragWire->connector1()->tempRemove(toConnectorItem, false); toConnectorItem->tempRemove(m_connectorDragWire->connector1(), false); m_bendpointWire->connector1()->tempConnectTo(toConnectorItem, false); toConnectorItem->tempConnectTo(m_bendpointWire->connector1(), false); } m_bendpointWire->connector1()->tempRemove(m_connectorDragWire->connector0(), false); m_connectorDragWire->connector0()->tempRemove(m_bendpointWire->connector1(), false); m_bendpointWire->setLine(m_bendpointVG.line()); } DebugDialog::debug("deleting connector drag wire"); delete m_connectorDragWire; m_bendpointWire = m_connectorDragWire = NULL; m_savedItems.clear(); m_savedWires.clear(); m_connectorDragConnector = NULL; return; } // make sure this is cleared m_bendpointWire = NULL; if (m_moveEventCount == 0) { if (this->m_holdingSelectItemCommand != NULL) { if (m_holdingSelectItemCommand->updated()) { SelectItemCommand* tempCommand = m_holdingSelectItemCommand; m_holdingSelectItemCommand = NULL; //DebugDialog::debug(QString("scene changed push select %1").arg(scene()->selectedItems().count())); m_undoStack->push(tempCommand); } else { clearHoldingSelectItem(); } } } m_savedItems.clear(); m_savedWires.clear(); } bool SketchWidget::checkMoved(bool wait) { if (m_moveEventCount == 0) { return false; } int moveCount = m_savedItems.count(); if (moveCount <= 0) { return false; } ItemBase * saveBase = NULL; foreach (ItemBase * item, m_savedItems) { saveBase = item; break; } clearHoldingSelectItem(); QString moveString; QString viewName = ViewLayer::viewIDName(m_viewID); if (moveCount == 1) { moveString = tr("Move %2 (%1)").arg(viewName).arg(saveBase->title()); } else { moveString = tr("Move %2 items (%1)").arg(viewName).arg(QString::number(moveCount)); } QUndoCommand * parentCommand = new QUndoCommand(moveString); bool hasBoard = false; foreach (ItemBase * item, m_savedItems) { rememberSticky(item, parentCommand); } CleanUpWiresCommand * cuw = new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); moveLegBendpoints(true, parentCommand); bool gotConnection = true; MoveItemsCommand * moveItemsCommand = new MoveItemsCommand(this, true, parentCommand); foreach (ItemBase * item, m_savedItems) { if (item == NULL) continue; ViewGeometry viewGeometry(item->getViewGeometry()); item->saveGeometry(); moveItemsCommand->addItem(item->id(), viewGeometry.loc(), item->getViewGeometry().loc()); if (item->itemType() == ModelPart::Breadboard) { hasBoard = true; continue; } // TODO: boardtypes and breadboard types are always sticky if (Board::isBoard(item)) { hasBoard = true; } } foreach (ItemBase * item, m_savedItems) { new CheckStickyCommand(this, BaseCommand::SingleView, item->id(), false, CheckStickyCommand::RedoOnly, parentCommand); } foreach (ItemBase * item, m_savedWires.keys()) { rememberSticky(item, parentCommand); } foreach (Wire * wire, m_savedWires.keys()) { if (wire == NULL) continue; moveItemsCommand->addWire(wire->id(), m_savedWires.value(wire)->connectorSharedID()); } foreach (ItemBase * item, m_savedWires.keys()) { new CheckStickyCommand(this, BaseCommand::SingleView, item->id(), false, CheckStickyCommand::RedoOnly, parentCommand); } foreach (ConnectorItem * fromConnectorItem, m_moveDisconnectedFromFemale.uniqueKeys()) { foreach (ConnectorItem * toConnectorItem, m_moveDisconnectedFromFemale.values(fromConnectorItem)) { extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(fromConnectorItem->attachedToViewLayerID()), false, parentCommand); gotConnection = true; } } QList restoreConnectorItems; foreach (ItemBase * item, m_savedItems) { foreach (ConnectorItem * fromConnectorItem, item->cachedConnectorItems()) { if (item->itemType() == ModelPart::Wire) { if (fromConnectorItem->connectionsCount() > 0) { continue; } } ConnectorItem * toConnectorItem = fromConnectorItem->overConnectorItem(); if (toConnectorItem != NULL) { toConnectorItem->connectorHover(item, false); fromConnectorItem->setOverConnectorItem(NULL); // clean up gotConnection = true; extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), true, parentCommand); } restoreConnectorItems.append(fromConnectorItem); fromConnectorItem->clearConnectorHover(); } item->clearConnectorHover(); } QList visited; foreach (ConnectorItem * connectorItem, restoreConnectorItems) { connectorItem->restoreColor(visited); } // must restore legs after connections are restored (redo direction) moveLegBendpoints(false, parentCommand); clearTemporaries(); if (gotConnection) { new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); cuw->setDirection(CleanUpWiresCommand::UndoOnly); } if (wait) { m_undoStack->waitPush(parentCommand, PropChangeDelay); } else { m_undoStack->push(parentCommand); } return true; } void SketchWidget::setReferenceModel(ReferenceModel *referenceModel) { m_referenceModel = referenceModel; } ReferenceModel * SketchWidget::referenceModel() { return m_referenceModel; } void SketchWidget::setSketchModel(SketchModel * sketchModel) { m_sketchModel = sketchModel; } void SketchWidget::itemAddedSlot(ModelPart * modelPart, ItemBase *, ViewLayer::ViewLayerPlacement viewLayerPlacement, const ViewGeometry & viewGeometry, long id, SketchWidget * dropOrigin) { if (dropOrigin != NULL && dropOrigin != this) { placePartDroppedInOtherView(modelPart, viewLayerPlacement, viewGeometry, id, dropOrigin); } else { addItemAux(modelPart, viewLayerPlacement, viewGeometry, id, true, m_viewID, false); } } ItemBase * SketchWidget::placePartDroppedInOtherView(ModelPart * modelPart, ViewLayer::ViewLayerPlacement viewLayerPlacement, const ViewGeometry & viewGeometry, long id, SketchWidget * dropOrigin) { // offset the part QPointF from = dropOrigin->mapToScene(QPoint(0, 0)); QPointF to = this->mapToScene(QPoint(0, 0)); QPointF dp = viewGeometry.loc() - from; ViewGeometry vg(viewGeometry); vg.setLoc(to + dp); ItemBase * itemBase = addItemAux(modelPart, viewLayerPlacement, vg, id, true, m_viewID, false); if (m_alignToGrid && (itemBase != NULL)) { alignOneToGrid(itemBase); } return itemBase; } void SketchWidget::itemDeletedSlot(long id) { ItemBase * pitem = findItem(id); if (pitem != NULL) { deleteItem(pitem, false, false, false); } } void SketchWidget::selectionChangedSlot() { if (m_ignoreSelectionChangeEvents > 0) { return; } emit selectionChangedSignal(); if (m_holdingSelectItemCommand != NULL) { //DebugDialog::debug("update holding command"); int selCount = 0; ItemBase* saveBase = NULL; QString selString; m_holdingSelectItemCommand->clearRedo(); const QList sitems = scene()->selectedItems(); foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * base = dynamic_cast(item); if (base == NULL) continue; saveBase = base; m_holdingSelectItemCommand->addRedo(base->layerKinChief()->id()); selCount++; } if (selCount == 1) { selString = tr("Select %1").arg(saveBase->title()); } else { selString = tr("Select %1 items").arg(QString::number(selCount)); } m_holdingSelectItemCommand->setText(selString); m_holdingSelectItemCommand->setUpdated(true); } } void SketchWidget::clearHoldingSelectItem() { // DebugDialog::debug("clear holding"); if (m_holdingSelectItemCommand != NULL) { delete m_holdingSelectItemCommand; m_holdingSelectItemCommand = NULL; } } void SketchWidget::clearSelection() { this->scene()->clearSelection(); emit clearSelectionSignal(); } void SketchWidget::clearSelectionSlot() { this->scene()->clearSelection(); } void SketchWidget::itemSelectedSlot(long id, bool state) { ItemBase * item = findItem(id); //DebugDialog::debug(QString("got item selected signal %1 %2 %3 %4").arg(id).arg(state).arg(item != NULL).arg(m_viewID)); if (item != NULL) { item->setSelected(state); } PaletteItem *pitem = dynamic_cast(item); if(pitem) { setLastPaletteItemSelected(pitem); } } void SketchWidget::prepLegSelection(ItemBase * itemBase) { this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted if (itemBase->isSelected()) return; m_holdingSelectItemCommand = stackSelectionState(false, NULL); itemBase->setSelected(true); } void SketchWidget::prepLegBendpointMove(ConnectorItem * from, int index, QPointF oldPos, QPointF newPos, ConnectorItem * to, bool changeConnections) { this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(); if (m_holdingSelectItemCommand) { SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->copyUndo(m_holdingSelectItemCommand); selectItemCommand->copyRedo(m_holdingSelectItemCommand); clearHoldingSelectItem(); } long fromID = from->attachedToID(); QString fromConnectorID = from->connectorSharedID(); long toID = -1; QString toConnectorID; if (changeConnections && (to != NULL)) { toID = to->attachedToID(); toConnectorID = to->connectorSharedID(); } if (changeConnections) { new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); } MoveLegBendpointCommand * mlbc = new MoveLegBendpointCommand(this, fromID, fromConnectorID, index, oldPos, newPos, parentCommand); mlbc->setUndoOnly(); if (changeConnections) { QList< QPointer > former = from->connectedToItems(); QString prefix; QString suffix; if (to == NULL) { if (former.count() > 0) { prefix = tr("Disconnect"); suffix = tr("from %1").arg(former.at(0)->attachedToInstanceTitle()); } else { prefix = tr("Move leg of"); } } else { prefix = tr("Connect"); suffix = tr("to %1").arg(to->attachedToInstanceTitle()); } parentCommand->setText(QObject::tr("%1 %2,%3 %4") .arg(prefix) .arg(from->attachedTo()->instanceTitle()) .arg(from->connectorSharedName()) .arg(suffix) ); if (former.count() > 0) { QList connectorItems; connectorItems.append(from); ConnectorItem::collectEqualPotential(connectorItems, true, ViewGeometry::RatsnestFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag); foreach (ConnectorItem * formerConnectorItem, former) { ChangeConnectionCommand * ccc = extendChangeConnectionCommand(BaseCommand::CrossView, from, formerConnectorItem, ViewLayer::specFromID(from->attachedToViewLayerID()), false, parentCommand); ccc->setUpdateConnections(false); from->tempRemove(formerConnectorItem, false); formerConnectorItem->tempRemove(from, false); } } if (to != NULL) { ChangeConnectionCommand * ccc = extendChangeConnectionCommand(BaseCommand::CrossView, from, to, ViewLayer::specFromID(from->attachedToViewLayerID()), true, parentCommand); ccc->setUpdateConnections(false); } } else { parentCommand->setText(QObject::tr("Change leg of %1,%2") .arg(from->attachedTo()->instanceTitle()) .arg(from->connectorSharedName()) ); } // change leg after connections have been restored mlbc = new MoveLegBendpointCommand(this, fromID, fromConnectorID, index, oldPos, newPos, parentCommand); mlbc->setRedoOnly(); if (changeConnections) { new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); } m_undoStack->push(parentCommand); } void SketchWidget::prepLegCurveChange(ConnectorItem * from, int index, const class Bezier * oldB, const class Bezier * newB, bool triggerFirstTime) { this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(tr("Change leg curvature for %1.").arg(from->attachedToInstanceTitle())); if (m_holdingSelectItemCommand) { SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->copyUndo(m_holdingSelectItemCommand); selectItemCommand->copyRedo(m_holdingSelectItemCommand); clearHoldingSelectItem(); } long fromID = from->attachedToID(); QString fromConnectorID = from->connectorSharedID(); ChangeLegCurveCommand * clcc = new ChangeLegCurveCommand(this, fromID, fromConnectorID, index, oldB, newB, parentCommand); if (!triggerFirstTime) { clcc->setSkipFirstRedo(); } m_undoStack->push(parentCommand); } void SketchWidget::prepLegBendpointChange(ConnectorItem * from, int oldCount, int newCount, int index, QPointF p, const class Bezier * bezier0, const class Bezier * bezier1, const class Bezier * bezier2, bool triggerFirstTime) { this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(tr("Change leg bendpoint for %1.").arg(from->attachedToInstanceTitle())); if (m_holdingSelectItemCommand) { SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->copyUndo(m_holdingSelectItemCommand); selectItemCommand->copyRedo(m_holdingSelectItemCommand); clearHoldingSelectItem(); } long fromID = from->attachedToID(); QString fromConnectorID = from->connectorSharedID(); ChangeLegBendpointCommand * clbc = new ChangeLegBendpointCommand(this, fromID, fromConnectorID, oldCount, newCount, index, p, bezier0, bezier1, bezier2, parentCommand); if (!triggerFirstTime) { clbc->setSkipFirstRedo(); } m_undoStack->push(parentCommand); } void SketchWidget::wireChangedSlot(Wire* wire, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, ConnectorItem * from, ConnectorItem * to) { this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted // TODO: make sure all these pointers to pointers to pointers aren't null... if (wire == this->m_connectorDragWire) { dragWireChanged(wire, from, to); return; } clearDragWireTempCommand(); if ((to != NULL) && from->connectedToItems().contains(to)) { // there's no change: the wire was dragged back to its original connection QList already; from->attachedTo()->updateConnections(to, false, already); return; } QUndoCommand * parentCommand = new QUndoCommand(); long fromID = wire->id(); QString fromConnectorID; if (from != NULL) { fromConnectorID = from->connectorSharedID(); } long toID = -1; QString toConnectorID; if (to != NULL) { toID = to->attachedToID(); toConnectorID = to->connectorSharedID(); } new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); rememberSticky(wire, parentCommand); bool chained = false; foreach (ConnectorItem * toConnectorItem, from->connectedToItems()) { Wire * toWire = qobject_cast(toConnectorItem->attachedTo()); if (toWire) { chained = true; break; } } new ChangeWireCommand(this, fromID, oldLine, newLine, oldPos, newPos, true, true, parentCommand); new CheckStickyCommand(this, BaseCommand::SingleView, fromID, false, CheckStickyCommand::RedoOnly, parentCommand); foreach (ConnectorItem * toConnectorItem, from->connectedToItems()) { Wire * toWire = qobject_cast(toConnectorItem->attachedTo()); if (toWire == NULL) continue; rememberSticky(toWire, parentCommand); ViewGeometry vg = toWire->getViewGeometry(); QLineF nl = toWire->line(); QPointF np = toWire->pos(); new ChangeWireCommand(this, toWire->id(), vg.line(), nl, vg.loc(), np, true, true, parentCommand); new CheckStickyCommand(this, BaseCommand::SingleView, toWire->id(), false, CheckStickyCommand::RedoOnly, parentCommand); } QList< QPointer > former = from->connectedToItems(); QString prefix; QString suffix; if (to == NULL) { if (former.count() > 0 && !chained) { prefix = tr("Disconnect"); // the suffix is a little tricky to determine // it might be multiple disconnects, or might be disconnecting a virtual wire, in which case, the // title needs to come from the virtual wire's other connection's attachedTo() // suffix = tr("from %1").arg(former->attachedToTitle()); } else { prefix = tr("Change"); } } else { prefix = tr("Connect"); suffix = tr("to %1").arg(to->attachedToInstanceTitle()); } parentCommand->setText(QObject::tr("%1 %2 %3").arg(prefix).arg(wire->title()).arg(suffix) ); if (!chained) { if (former.count() > 0) { foreach (ConnectorItem * formerConnectorItem, former) { extendChangeConnectionCommand(BaseCommand::CrossView, from, formerConnectorItem, ViewLayer::specFromID(wire->viewLayerID()), false, parentCommand); from->tempRemove(formerConnectorItem, false); formerConnectorItem->tempRemove(from, false); } } if (to != NULL) { extendChangeConnectionCommand(BaseCommand::CrossView, from, to, ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); } } clearTemporaries(); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::dragWireChanged(Wire* wire, ConnectorItem * fromOnWire, ConnectorItem * to) { if (m_bendpointWire != NULL && wire->getRatsnest()) { dragRatsnestChanged(); return; } prereleaseTempWireForDragging(m_connectorDragWire); BaseCommand::CrossViewType crossViewType = BaseCommand::CrossView; if (m_bendpointWire) { } else { m_connectorDragConnector->tempRemove(m_connectorDragWire->connector1(), false); m_connectorDragWire->connector1()->tempRemove(m_connectorDragConnector, false); // if to and from are the same connector, you can't draw a wire to yourself // or to == NULL and it's pcb or schematic view, bail out if ((m_connectorDragConnector == to) || !canCreateWire(wire, fromOnWire, to)) { clearDragWireTempCommand(); removeDragWire(); return; } } QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(tr("Create and connect wire")); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); if (m_tempDragWireCommand != NULL) { selectItemCommand->copyUndo(m_tempDragWireCommand); clearDragWireTempCommand(); } new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); m_connectorDragWire->saveGeometry(); bool doEmit = false; long fromID = wire->id(); DebugDialog::debug(QString("m_connectorDragConnector:%1 %4 from:%2 to:%3") .arg(m_connectorDragConnector->connectorSharedID()) .arg(fromOnWire->connectorSharedID()) .arg((to == NULL) ? "null" : to->connectorSharedID()) .arg(m_connectorDragConnector->attachedTo()->title()) ); // create a new wire with the same id as the temporary wire ViewGeometry vg = m_connectorDragWire->getViewGeometry(); vg.setWireFlags(getTraceFlag()); new AddItemCommand(this, crossViewType, m_connectorDragWire->moduleID(), m_connectorDragWire->viewLayerPlacement(), vg, fromID, true, -1, parentCommand); new CheckStickyCommand(this, crossViewType, fromID, false, CheckStickyCommand::RemoveOnly, parentCommand); selectItemCommand->addRedo(fromID); if (m_bendpointWire == NULL) { ConnectorItem * anchor = wire->otherConnector(fromOnWire); if (anchor != NULL) { extendChangeConnectionCommand(BaseCommand::CrossView, anchor, m_connectorDragConnector, ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); doEmit = true; } if (to != NULL) { extendChangeConnectionCommand(BaseCommand::CrossView, fromOnWire, to, ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); doEmit = true; } setUpColor(m_connectorDragConnector, to, wire, parentCommand); } else { new WireColorChangeCommand(this, wire->id(), m_bendpointWire->colorString(), m_bendpointWire->colorString(), m_bendpointWire->opacity(), m_bendpointWire->opacity(), parentCommand); new WireWidthChangeCommand(this, wire->id(), m_bendpointWire->width(), m_bendpointWire->width(), parentCommand); if (m_bendpointWire->banded()) { new SetPropCommand(this, wire->id(), "banded", "Yes", "Yes", true, parentCommand); } } if (m_bendpointWire) { ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, m_bendpointWire->id(), m_bendpointWire->undoCurve(), m_bendpointWire->curve(), m_bendpointWire->getAutoroutable(), parentCommand); cwcc->setUndoOnly(); // puts the wire in position at redo time ChangeWireCommand * cwc = new ChangeWireCommand(this, m_bendpointWire->id(), m_bendpointVG.line(), m_bendpointWire->line(), m_bendpointVG.loc(), m_bendpointWire->pos(), true, false, parentCommand); cwc->setRedoOnly(); foreach (ConnectorItem * toConnectorItem, wire->connector1()->connectedToItems()) { toConnectorItem->tempRemove(wire->connector1(), false); wire->connector1()->tempRemove(toConnectorItem, false); new ChangeConnectionCommand(this, BaseCommand::CrossView, m_bendpointWire->id(), m_connectorDragConnector->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), false, parentCommand); new ChangeConnectionCommand(this, BaseCommand::CrossView, wire->id(), wire->connector1()->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), true, parentCommand); } m_connectorDragConnector->tempRemove(wire->connector0(), false); wire->connector0()->tempRemove(m_connectorDragConnector, false); new ChangeConnectionCommand(this, BaseCommand::CrossView, m_connectorDragConnector->attachedToID(), m_connectorDragConnector->connectorSharedID(), wire->id(), wire->connector0()->connectorSharedID(), ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); new ChangeWireCurveCommand(this, wire->id(), NULL, wire->curve(), wire->getAutoroutable(), parentCommand); cwcc = new ChangeWireCurveCommand(this, m_bendpointWire->id(), m_bendpointWire->undoCurve(), m_bendpointWire->curve(), m_bendpointWire->getAutoroutable(), parentCommand); cwcc->setRedoOnly(); // puts the wire in position at undo time cwc = new ChangeWireCommand(this, m_bendpointWire->id(), m_bendpointVG.line(), m_bendpointWire->line(), m_bendpointVG.loc(), m_bendpointWire->pos(), true, false, parentCommand); cwc->setUndoOnly(); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->addRedo(m_bendpointWire->id()); m_bendpointWire = NULL; // signal that we're done } clearTemporaries(); // remove the temporary wire removeDragWire(); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void SketchWidget::dragRatsnestChanged() { // m_bendpointWire is the original wire // m_connectorDragWire is temporary // wire == m_connectorDragWire // m_connectorDragConnector is from original wire QList wires; QList ends; m_bendpointWire->collectChained(wires, ends); if (ends.count() != 2) { // ratsnest wires should always and only have two ends: we're screwed return; } ViewLayer::ViewLayerPlacement viewLayerPlacement = createWireViewLayerPlacement(ends[0], ends[1]); if (viewLayerPlacement == ViewLayer::UnknownPlacement) { // for now this should not be possible QMessageBox::critical(this, tr("Fritzing"), tr("This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers.")); return; } BaseCommand::CrossViewType crossViewType = BaseCommand::CrossView; QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(tr("Create and connect %1").arg(m_viewID == ViewLayer::BreadboardView ? tr("wire") : tr("trace"))); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); //SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); m_connectorDragWire->saveGeometry(); m_bendpointWire->saveGeometry(); double traceWidth = getTraceWidth(); QString tColor = traceColor(viewLayerPlacement); if (!this->m_lastColorSelected.isEmpty()) { tColor = this->m_lastColorSelected; } long newID1 = ItemBase::getNextID(); ViewGeometry vg1 = m_connectorDragWire->getViewGeometry(); vg1.setWireFlags(getTraceFlag()); new AddItemCommand(this, crossViewType, m_connectorDragWire->moduleID(), viewLayerPlacement, vg1, newID1, true, -1, parentCommand); new CheckStickyCommand(this, crossViewType, newID1, false, CheckStickyCommand::RemoveOnly, parentCommand); new WireColorChangeCommand(this, newID1, tColor, tColor, 1.0, 1.0, parentCommand); new WireWidthChangeCommand(this, newID1, traceWidth, traceWidth, parentCommand); long newID2 = ItemBase::getNextID(); ViewGeometry vg2 = m_bendpointWire->getViewGeometry(); vg2.setWireFlags(getTraceFlag()); new AddItemCommand(this, crossViewType, m_bendpointWire->moduleID(), viewLayerPlacement, vg2, newID2, true, -1, parentCommand); new CheckStickyCommand(this, crossViewType, newID2, false, CheckStickyCommand::RemoveOnly, parentCommand); new WireColorChangeCommand(this, newID2, tColor, tColor, 1.0, 1.0, parentCommand); new WireWidthChangeCommand(this, newID2, traceWidth, traceWidth, parentCommand); new ChangeConnectionCommand(this, BaseCommand::CrossView, newID2, m_connectorDragConnector->connectorSharedID(), newID1, m_connectorDragWire->connector0()->connectorSharedID(), viewLayerPlacement, // ViewLayer::specFromID(wire->viewLayerID()) true, parentCommand); foreach (ConnectorItem * toConnectorItem, m_bendpointWire->connector0()->connectedToItems()) { new ChangeConnectionCommand(this, BaseCommand::CrossView, newID2, m_bendpointWire->connector0()->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), viewLayerPlacement, // ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()) true, parentCommand); } foreach (ConnectorItem * toConnectorItem, m_connectorDragWire->connector1()->connectedToItems()) { new ChangeConnectionCommand(this, BaseCommand::CrossView, newID1, m_connectorDragWire->connector1()->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), viewLayerPlacement, // ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()) true, parentCommand); m_connectorDragWire->connector1()->tempRemove(toConnectorItem, false); toConnectorItem->tempRemove(m_connectorDragWire->connector1(), false); m_bendpointWire->connector1()->tempConnectTo(toConnectorItem, false); toConnectorItem->tempConnectTo(m_bendpointWire->connector1(), false); } m_bendpointWire->setPos(m_bendpointVG.loc()); m_bendpointWire->setLine(m_bendpointVG.line()); m_connectorDragConnector->tempRemove(m_connectorDragWire->connector0(), false); m_connectorDragWire->connector0()->tempRemove(m_connectorDragConnector, false); m_bendpointWire = NULL; // signal that we're done // remove the temporary wire removeDragWire(); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void SketchWidget::setUpColor(ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Wire * wire, QUndoCommand * parentCommand) { Q_UNUSED(fromConnectorItem); Q_UNUSED(toConnectorItem); if (!this->m_lastColorSelected.isEmpty()) { new WireColorChangeCommand(this, wire->id(), m_lastColorSelected, m_lastColorSelected, wire->opacity(), wire->opacity(), parentCommand); } } void SketchWidget::addViewLayer(ViewLayer * viewLayer) { ViewLayer * oldViewLayer = m_viewLayers.value(viewLayer->viewLayerID(), NULL); if (oldViewLayer) { delete oldViewLayer; } m_viewLayers.insert(viewLayer->viewLayerID(), viewLayer); QAction* action = new QAction(QObject::tr("%1 Layer").arg(viewLayer->displayName()), this); action->setData(QVariant::fromValue(viewLayer)); action->setCheckable(true); action->setChecked(viewLayer->visible()); action->setEnabled(true); connect(action, SIGNAL(triggered()), this, SLOT(toggleLayerVisibility())); viewLayer->setAction(action); } void SketchWidget::setAllLayersVisible(bool visible) { LayerList keys = m_viewLayers.keys(); for (int i = 0; i < keys.count(); i++) { ViewLayer * viewLayer = m_viewLayers.value(keys[i]); if (viewLayer != NULL && viewLayer->action()->isEnabled()) { setLayerVisible(viewLayer, visible, true); } } } ItemCount SketchWidget::calcItemCount() { ItemCount itemCount; // TODO: replace scene()->items() QList items = scene()->items(); QList selItems = scene()->selectedItems(); itemCount.visLabelCount = itemCount.hasLabelCount = 0; itemCount.selCount = 0; itemCount.selHFlipable = itemCount.selVFlipable = itemCount.selRotatable = itemCount.sel45Rotatable = 0; itemCount.itemsCount = 0; itemCount.obsoleteCount = 0; itemCount.moveLockCount = 0; itemCount.wireCount = 0; for (int i = 0; i < selItems.count(); i++) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(selItems[i]); if (itemBase != NULL) { itemCount.selCount++; if (itemBase->moveLock()) { itemCount.moveLockCount++; } if (itemBase->hasPartLabel()) { itemCount.hasLabelCount++; if (itemBase->isPartLabelVisible()) { itemCount.visLabelCount++; } } if (itemBase->isObsolete()) { itemCount.obsoleteCount++; } if (itemBase->itemType() == ModelPart::Wire) { itemCount.wireCount++; } else { bool rotatable = itemBase->rotationAllowed(); if (rotatable) { itemCount.selRotatable++; } rotatable = itemBase->rotation45Allowed(); if (rotatable) { itemCount.sel45Rotatable++; } if (itemBase->canFlipHorizontal()) { itemCount.selHFlipable++; } if (itemBase->canFlipVertical()) { itemCount.selVFlipable++; } } } } /* DebugDialog::debug(QString("sc:%1 wc:%2 sr:%3 s45r:%4 sv:%5 sh:%6") .arg(itemCount.selCount) .arg(itemCount.wireCount) .arg(itemCount.selRotatable) .arg(itemCount.sel45Rotatable) .arg(itemCount.selVFlipable) .arg(itemCount.selHFlipable) ); */ if (itemCount.selCount - itemCount.wireCount != itemCount.selRotatable) { // if you can't rotate them all, then you can't rotate any itemCount.selRotatable = 0; } if (itemCount.selCount - itemCount.wireCount != itemCount.sel45Rotatable) { // if you can't rotate them all, then you can't rotate any itemCount.sel45Rotatable = 0; } if (itemCount.selCount - itemCount.wireCount != itemCount.selVFlipable) { itemCount.selVFlipable = 0; } if (itemCount.selCount - itemCount.wireCount != itemCount.selHFlipable) { itemCount.selHFlipable = 0; } if (itemCount.selCount > 0) { for (int i = 0; i < items.count(); i++) { if (ItemBase::extractTopLevelItemBase(items[i]) != NULL) { itemCount.itemsCount++; } } } return itemCount; } bool SketchWidget::layerIsVisible(ViewLayer::ViewLayerID viewLayerID) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer == NULL) return false; return viewLayer->visible(); } bool SketchWidget::layerIsActive(ViewLayer::ViewLayerID viewLayerID) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer == NULL) return false; return viewLayer->isActive(); } void SketchWidget::setLayerVisible(ViewLayer::ViewLayerID viewLayerID, bool vis, bool doChildLayers) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer) { setLayerVisible(viewLayer, vis, doChildLayers); } } void SketchWidget::toggleLayerVisibility() { QAction * action = qobject_cast(sender()); if (action == NULL) return; ViewLayer * viewLayer = action->data().value(); if (viewLayer == NULL) return; setLayerVisible(viewLayer, !viewLayer->visible(), viewLayer->includeChildLayers()); } void SketchWidget::setLayerVisible(ViewLayer * viewLayer, bool visible, bool doChildLayers) { LayerList viewLayerIDs; viewLayerIDs.append(viewLayer->viewLayerID()); viewLayer->setVisible(visible); if (doChildLayers) { foreach (ViewLayer * childLayer, viewLayer->childLayers()) { childLayer->setVisible(visible); viewLayerIDs.append(childLayer->viewLayerID()); } } // TODO: replace scene()->items() foreach (QGraphicsItem * item, scene()->items()) { // want all items, not just topLevel ItemBase * itemBase = dynamic_cast(item); if (itemBase) { if (viewLayerIDs.contains(itemBase->viewLayerID())) { itemBase->setHidden(!visible); //DebugDialog::debug(QString("setting visible %1").arg(viewLayer->visible())); } continue; } PartLabel * partLabel = dynamic_cast(item); if (partLabel && (viewLayerIDs.contains(partLabel->viewLayerID()))) { partLabel->setHidden(!visible); } } } void SketchWidget::setLayerActive(ViewLayer::ViewLayerID viewLayerID, bool active) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer) { setLayerActive(viewLayer, active); } } void SketchWidget::setLayerActive(ViewLayer * viewLayer, bool active) { LayerList viewLayerIDs; viewLayerIDs.append(viewLayer->viewLayerID()); viewLayer->setActive(active); foreach (ViewLayer * childLayer, viewLayer->childLayers()) { childLayer->setActive(active); viewLayerIDs.append(childLayer->viewLayerID()); } // TODO: replace scene()->items() foreach (QGraphicsItem * item, scene()->items()) { // want all items, not just topLevel ItemBase * itemBase = dynamic_cast(item); if (itemBase != NULL) { //itemBase->debugInfo("setActive"); if (viewLayerIDs.contains(itemBase->viewLayerID())) { itemBase->setInactive(!active); //DebugDialog::debug(QString("setting visible %1").arg(viewLayer->visible())); } continue; } PartLabel * partLabel = dynamic_cast(item); if (partLabel != NULL) { if (viewLayerIDs.contains(partLabel->viewLayerID())) { partLabel->setInactive(!active); } continue; } } } void SketchWidget::sendToBack() { QList bases; if (!startZChange(bases)) return; QString text = QObject::tr("Bring forward"); continueZChangeMax(bases, bases.size() - 1, -1, greaterThan, -1, text); } void SketchWidget::sendBackward() { QList bases; if (!startZChange(bases)) return; QString text = QObject::tr("Send backward"); continueZChange(bases, 0, bases.size(), lessThan, 1, text); } void SketchWidget::bringForward() { QList bases; if (!startZChange(bases)) return; QString text = QObject::tr("Bring forward"); continueZChange(bases, bases.size() - 1, -1, greaterThan, -1, text); } void SketchWidget::bringToFront() { QList bases; if (!startZChange(bases)) return; QString text = QObject::tr("Bring to front"); continueZChangeMax(bases, 0, bases.size(), lessThan, 1, text); } double SketchWidget::fitInWindow() { QRectF itemsRect; foreach(QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isEverVisible()) continue; itemsRect |= itemBase->sceneBoundingRect(); } static const double borderFactor = 0.03; itemsRect.adjust(-itemsRect.width() * borderFactor, -itemsRect.height() * borderFactor, itemsRect.width() * borderFactor, itemsRect.height() * borderFactor); QRectF viewRect = rect(); //fitInView(itemsRect.x(), itemsRect.y(), itemsRect.width(), itemsRect.height(), Qt::KeepAspectRatio); double wRelation = (viewRect.width() - this->verticalScrollBar()->width() - 5) / itemsRect.width(); double hRelation = (viewRect.height() - this->horizontalScrollBar()->height() - 5) / itemsRect.height(); //DebugDialog::debug(QString("scen rect: w%1 h%2").arg(itemsRect.width()).arg(itemsRect.height())); //DebugDialog::debug(QString("view rect: w%1 h%2").arg(viewRect.width()).arg(viewRect.height())); //DebugDialog::debug(QString("relations (v/s): w%1 h%2").arg(wRelation).arg(hRelation)); if(wRelation < hRelation) { m_scaleValue = (wRelation * 100); } else { m_scaleValue = (hRelation * 100); } this->centerOn(itemsRect.center()); this->absoluteZoom(m_scaleValue); return m_scaleValue; } bool SketchWidget::startZChange(QList & bases) { int selCount = bases.count(); if (selCount == 0) { selCount = scene()->selectedItems().count(); if (selCount <= 0) return false; } const QList items = scene()->items(); if (items.count() <= selCount) return false; sortAnyByZ(items, bases); return true; } void SketchWidget::continueZChange(QList & bases, int start, int end, bool (*test)(int current, int start), int inc, const QString & text) { bool moved = false; int last = bases.size(); for (int i = start; test(i, end); i += inc) { ItemBase * base = bases[i]; if (!base->getViewGeometry().selected()) continue; int j = i - inc; if (j >= 0 && j < last && bases[j]->viewLayerID() == base->viewLayerID()) { bases.move(i, j); moved = true; } } if (!moved) { return; } continueZChangeAux(bases, text); } void SketchWidget::continueZChangeMax(QList & bases, int start, int end, bool (*test)(int current, int start), int inc, const QString & text) { QHash marked; bool moved = false; int last = bases.size(); for (int i = start; test(i, end); i += inc) { ItemBase * base = bases[i]; if (!base->getViewGeometry().selected()) continue; if (marked[base] != NULL) continue; marked.insert(base, base); int dest = -1; for (int j = i + inc; j >= 0 && j < last && bases[j]->viewLayerID() == base->viewLayerID(); j += inc) { dest = j; } if (dest >= 0) { moved = true; bases.move(i, dest); DebugDialog::debug(QString("moving %1 to %2").arg(i).arg(dest)); i -= inc; // because we just modified the list and would miss the next item } } if (!moved) { return; } continueZChangeAux(bases, text); } void SketchWidget::continueZChangeAux(QList & bases, const QString & text) { ChangeZCommand * changeZCommand = new ChangeZCommand(this, NULL); ViewLayer::ViewLayerID lastViewLayerID = ViewLayer::UnknownLayer; double z = 0; for (int i = 0; i < bases.size(); i++) { double oldZ = bases[i]->getViewGeometry().z(); if (bases[i]->viewLayerID() != lastViewLayerID) { lastViewLayerID = bases[i]->viewLayerID(); z = qFloor(oldZ); } else { z += ViewLayer::getZIncrement(); } if (oldZ == z) continue; // optimize this by only adding z's that must change // rather than changing all of them changeZCommand->addTriplet(bases[i]->id(), oldZ, z); } changeZCommand->setText(text); m_undoStack->push(changeZCommand); } void SketchWidget::sortAnyByZ(const QList & items, QList & bases) { for (int i = 0; i < items.size(); i++) { ItemBase * base = dynamic_cast(items[i]); if (base != NULL) { bases.append(base); base->saveGeometry(); } } // order by z qSort(bases.begin(), bases.end(), ItemBase::zLessThan); } bool SketchWidget::lessThan(int a, int b) { return a < b; } bool SketchWidget::greaterThan(int a, int b) { return a > b; } void SketchWidget::changeZ(QHash triplets, double (*pairAccessor)(RealPair *) ) { // TODO: replace scene->items const QList items = scene()->items(); for (int i = 0; i < items.size(); i++) { // want all items, not just topLevel ItemBase * itemBase = dynamic_cast(items[i]); if (itemBase == NULL) continue; RealPair * pair = triplets[itemBase->id()]; if (pair == NULL) continue; double newZ = pairAccessor(pair); ViewLayer * viewLayer = m_viewLayers.value(itemBase->viewLayerID()); if (viewLayer) { newZ = viewLayer->getZFromBelow(newZ, this->viewFromBelow()); } //DebugDialog::debug(QString("change z %1 %2").arg(itemBase->id()).arg(newZ)); items[i]->setZValue(newZ); } } ViewLayer::ViewLayerID SketchWidget::getDragWireViewLayerID(ConnectorItem *) { return m_wireViewLayerID; } ViewLayer::ViewLayerID SketchWidget::getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement) { if (viewGeometry.getRatsnest()) { return ViewLayer::BreadboardRatsnest; } return m_wireViewLayerID; } ViewLayer::ViewLayerID SketchWidget::getRulerViewLayerID() { return m_rulerViewLayerID; } ViewLayer::ViewLayerID SketchWidget::getPartViewLayerID() { return m_partViewLayerID; } ViewLayer::ViewLayerID SketchWidget::getConnectorViewLayerID() { return m_connectorViewLayerID; } ViewLayer::ViewLayerID SketchWidget::getLabelViewLayerID(ItemBase *) { return ViewLayer::UnknownLayer; } ViewLayer::ViewLayerID SketchWidget::getNoteViewLayerID() { return m_noteViewLayerID; } void SketchWidget::mousePressConnectorEvent(ConnectorItem * connectorItem, QGraphicsSceneMouseEvent * event) { ModelPart * wireModel = m_referenceModel->retrieveModelPart(ModuleIDNames::WireModuleIDName); if (wireModel == NULL) return; m_tempDragWireCommand = m_holdingSelectItemCommand; m_holdingSelectItemCommand = NULL; clearHoldingSelectItem(); // make sure wire layer is visible ViewLayer::ViewLayerID viewLayerID = getDragWireViewLayerID(connectorItem); ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer != NULL && !viewLayer->visible()) { setLayerVisible(viewLayer, true, true); emit updateLayerMenuSignal(); } ViewGeometry viewGeometry; QPointF p = QPointF(connectorItem->mapToScene(event->pos())); viewGeometry.setLoc(p); viewGeometry.setLine(QLineF(0,0,0,0)); m_connectorDragConnector = connectorItem; m_connectorDragWire = createTempWireForDragging(NULL, wireModel, connectorItem, viewGeometry, ViewLayer::UnknownPlacement); if (m_connectorDragWire == NULL) { clearDragWireTempCommand(); return; } m_connectorDragWire->debugInfo("creating connector drag wire"); setupAutoscroll(true); // give connector item the mouse, so wire doesn't get mouse moved events m_connectorDragWire->setVisible(true); m_connectorDragWire->grabMouse(); unsquashShapes(); //m_connectorDragWire->debugInfo("grabbing mouse 2"); m_connectorDragWire->initDragEnd(m_connectorDragWire->connector0(), event->scenePos()); m_connectorDragConnector->tempConnectTo(m_connectorDragWire->connector1(), false); m_connectorDragWire->connector1()->tempConnectTo(m_connectorDragConnector, false); if (!m_lastColorSelected.isEmpty()) { m_connectorDragWire->setColorString(m_lastColorSelected, m_connectorDragWire->opacity(), false); } } void SketchWidget::rotateX(double degrees, bool rubberBandLegEnabled, ItemBase * originatingItem) { if (qAbs(degrees) < 0.01) return; clearHoldingSelectItem(); m_savedItems.clear(); m_savedWires.clear(); prepMove(originatingItem, rubberBandLegEnabled, false); QRectF itemsBoundingRect; // want the bounding rect of the original selected items, not all the items that are secondarily being rotated foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemsBoundingRect |= (item->transform() * QTransform().translate(item->x(), item->y())) .mapRect(itemBase->boundingRectWithoutLegs() /* | item->childrenBoundingRect() */); } QPointF center = itemsBoundingRect.center(); QTransform rotation; rotation.rotate(degrees); QString string = tr("Rotate %2 (%1)") .arg(ViewLayer::viewIDName(m_viewID)) .arg((m_savedItems.count() == 1) ? m_savedItems.values().at(0)->title() : QString::number(m_savedItems.count() + m_savedWires.count()) + " items" ); QUndoCommand * parentCommand = new QUndoCommand(string); //foreach (long id, m_savedItems.keys()) { //m_savedItems.value(id)->debugInfo(QString("save item %1").arg(id)); //} new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); // change legs after connections have been updated (undo direction) moveLegBendpoints(true, parentCommand); rotatePartLabels(degrees, rotation, center, parentCommand); QList wires; foreach (ItemBase * itemBase, m_savedItems.values()) { if (itemBase->itemType() == ModelPart::Wire) { wires << qobject_cast(itemBase); } } foreach (Wire * wire, wires) { rotateWire(wire, rotation, center, true, parentCommand); } foreach (ItemBase * itemBase, m_savedItems.values()) { switch (itemBase->itemType()) { case ModelPart::Via: case ModelPart::Hole: { QPointF p = itemBase->sceneBoundingRect().center(); QPointF d = p - center; QPointF dt = rotation.map(d) + center; ViewGeometry vg1 = itemBase->getViewGeometry(); ViewGeometry vg2(vg1); vg2.setLoc(vg1.loc() + dt - p); new MoveItemCommand(this, itemBase->id(), vg1, vg2, true, parentCommand); } break; case ModelPart::Wire: break; default: { ViewGeometry vg1 = itemBase->getViewGeometry(); ViewGeometry vg2(vg1); itemBase->calcRotation(rotation, center, vg2); ConnectorPairHash connectorHash; disconnectFromFemale(itemBase, m_savedItems, connectorHash, true, rubberBandLegEnabled, parentCommand); new MoveItemCommand(this, itemBase->id(), vg1, vg1, true, parentCommand); new RotateItemCommand(this, itemBase->id(), degrees, parentCommand); new MoveItemCommand(this, itemBase->id(), vg2, vg2, true, parentCommand); } break; } } foreach (Wire * wire, wires) { rotateWire(wire, rotation, center, false, parentCommand); } // change legs after connections have been updated (redo direction) QList connectorItems; foreach (ItemBase * itemBase, m_stretchingLegs.uniqueKeys()) { foreach (ConnectorItem * connectorItem, m_stretchingLegs.values(itemBase)) { connectorItems.append(connectorItem); QPolygonF oldLeg, newLeg; bool active; connectorItem->stretchDone(oldLeg, newLeg, active); new RotateLegCommand(this, connectorItem->attachedToID(), connectorItem->connectorSharedID(), oldLeg, active, parentCommand); } } foreach (Wire * wire, m_savedWires.keys()) { ViewGeometry vg1 = wire->getViewGeometry(); ViewGeometry vg2(vg1); ConnectorItem * rotater = m_savedWires.value(wire); QPointF p0 = rotater->sceneAdjustedTerminalPoint(NULL); QPointF d0 = p0 - center; QPointF d0t = rotation.map(d0); QPointF p1 = wire->otherConnector(rotater)->sceneAdjustedTerminalPoint(NULL); if (rotater == wire->connector0()) { new ChangeWireCommand(this, wire->id(), vg1.line(), QLineF(QPointF(0,0), p1 - (d0t + center)), vg1.loc(), d0t + center, true, true, parentCommand); } else { new ChangeWireCommand(this, wire->id(), vg1.line(), QLineF(QPointF(0,0), d0t + center - p1), vg1.loc(), vg1.loc(), true, true, parentCommand); } } new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void SketchWidget::rotateWire(Wire * wire, QTransform & rotation, QPointF center, bool undoOnly, QUndoCommand * parentCommand) { //wire->debugInfo("rotating wire"); QPointF p0 = wire->connector0()->sceneAdjustedTerminalPoint(NULL); QPointF d0 = p0 - center; QPointF d0t = rotation.map(d0); QPointF p1 = wire->connector1()->sceneAdjustedTerminalPoint(NULL); QPointF d1 = p1 - center; QPointF d1t = rotation.map(d1); ViewGeometry vg1 = wire->getViewGeometry(); ChangeWireCommand * cwc = new ChangeWireCommand(this, wire->id(), vg1.line(), QLineF(QPointF(0,0), d1t - d0t), vg1.loc(), d0t + center, true, true, parentCommand); if (undoOnly) cwc->setUndoOnly(); else cwc->setRedoOnly(); const Bezier * bezier = wire->curve(); if (bezier) { Bezier * newBezier = new Bezier(); newBezier->set_endpoints(QPointF(0,0), d1t - d0t); QPointF c0 = p0 + bezier->cp0(); QPointF dc0 = c0 - center; QPointF dc0t = rotation.map(dc0); newBezier->set_cp0(dc0t - d0t); QPointF c1 = p0 + bezier->cp1(); QPointF dc1 = c1 - center; QPointF dc1t = rotation.map(dc1); newBezier->set_cp1(dc1t - d0t); ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, wire->id(), bezier, newBezier, wire->getAutoroutable(), parentCommand); if (undoOnly) cwcc->setUndoOnly(); else cwcc->setRedoOnly(); } } void SketchWidget::rotatePartLabels(double degrees, QTransform &, QPointF center, QUndoCommand * parentCommand) { Q_UNUSED(center); Q_UNUSED(degrees); Q_UNUSED(parentCommand); } void SketchWidget::flipX(Qt::Orientations orientation, bool rubberBandLegEnabled) { if (!this->isVisible()) return; clearHoldingSelectItem(); m_savedItems.clear(); m_savedWires.clear(); prepMove(NULL, rubberBandLegEnabled, false); QList items = scene()->selectedItems(); QList targets; for (int i = 0; i < items.size(); i++) { // can't flip layerkin (layerkin flipped indirectly) ItemBase *itemBase = ItemBase::extractTopLevelItemBase(items[i]); if (itemBase == NULL) continue; if (Board::isBoard(itemBase)) continue; switch (itemBase->itemType()) { case ModelPart::Wire: case ModelPart::Note: case ModelPart::CopperFill: case ModelPart::Unknown: case ModelPart::Via: case ModelPart::Hole: case ModelPart::Breadboard: continue; default: if (!itemBase->canFlip(orientation)) { continue; } break; } targets.append(itemBase); } if (targets.count() <= 0) { return; } QString string = tr("Flip %2 (%1)") .arg(ViewLayer::viewIDName(m_viewID)) .arg((targets.count() == 1) ? targets[0]->title() : QString::number(targets.count()) + " items" ); QUndoCommand * parentCommand = new QUndoCommand(string); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); // change legs after connections have been updated (undo direction) moveLegBendpoints(true, parentCommand); QHash emptyList; // emptylist is only used for a move command ConnectorPairHash connectorHash; foreach (ItemBase * item, targets) { disconnectFromFemale(item, emptyList, connectorHash, true, rubberBandLegEnabled, parentCommand); if (item->isSticky()) { //TODO: apply transformation to stuck items } // TODO: if item has female connectors, then apply transform to connected items new FlipItemCommand(this, item->id(), orientation, parentCommand); } // change legs after connections have been updated (redo direction) foreach (ItemBase * itemBase, m_stretchingLegs.uniqueKeys()) { foreach (ConnectorItem * connectorItem, m_stretchingLegs.values(itemBase)) { QPolygonF oldLeg, newLeg; bool active; connectorItem->stretchDone(oldLeg, newLeg, active); new RotateLegCommand(this, connectorItem->attachedToID(), connectorItem->connectorSharedID(), oldLeg, active, parentCommand); } } clearTemporaries(); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } ConnectorItem * SketchWidget::findConnectorItem(ConnectorItem * foreignConnectorItem) { ItemBase * itemBase = findItem(foreignConnectorItem->attachedTo()->layerKinChief()->id()); if (itemBase == NULL) { return NULL; } ConnectorItem * result = findConnectorItem(itemBase, foreignConnectorItem->connectorSharedID(), ViewLayer::NewBottom); if (result) return result; return findConnectorItem(itemBase, foreignConnectorItem->connectorSharedID(), ViewLayer::NewTop); } ConnectorItem * SketchWidget::findConnectorItem(ItemBase * itemBase, const QString & connectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement) { ConnectorItem * connectorItem = itemBase->findConnectorItemWithSharedID(connectorID, viewLayerPlacement); if (connectorItem != NULL) return connectorItem; DebugDialog::debug("used to seek layer kin"); /* if (seekLayerKin) { PaletteItem * pitem = qobject_cast(itemBase); if (pitem == NULL) return NULL; foreach (ItemBase * lkpi, pitem->layerKin()) { connectorItem = lkpi->findConnectorItemWithSharedID(connectorID); if (connectorItem != NULL) return connectorItem; } } */ return NULL; } PaletteItem * SketchWidget::getSelectedPart(){ QList items= scene()->selectedItems(); PaletteItem *item = NULL; // dynamic cast returns null in cases where non-PaletteItems (i.e. wires and layerKin palette items) are selected for(int i=0; i < items.count(); i++){ PaletteItem *temp = dynamic_cast(items[i]); if (temp == NULL) continue; if (item != NULL) return NULL; // there are multiple items selected item = temp; } return item; } void SketchWidget::setBackground(QColor color) { /*QBrush brush(color); brush.setTexture(QPixmap("/home/merun/workspace/fritzing_trunk/phoenix/resources/images/schematic_grid_tile.png")); scene()->setBackgroundBrush(brush);*/ scene()->setBackgroundBrush(QBrush(color)); } void SketchWidget::setBackgroundColor(QColor color, bool setPrefs) { if (setPrefs) { QSettings settings; settings.setValue(QString("%1BackgroundColor").arg(getShortName()), color.name()); } setBackground(color); } const QColor& SketchWidget::background() { return scene()->backgroundBrush().color(); } void SketchWidget::setItemMenu(QMenu* itemMenu){ m_itemMenu = itemMenu; } void SketchWidget::setWireMenu(QMenu* wireMenu){ m_wireMenu = wireMenu; } void SketchWidget::wireConnectedSlot(long fromID, QString fromConnectorID, long toID, QString toConnectorID) { ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) return; Wire* wire = qobject_cast(fromItem); if (wire == NULL) return; ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, ViewLayer::specFromID(wire->viewLayerID())); if (fromConnectorItem == NULL) { // shouldn't be here return; } ItemBase * toItem = findItem(toID); if (toItem == NULL) { // this was a disconnect return; } ConnectorItem * toConnectorItem = findConnectorItem(toItem, toConnectorID, ViewLayer::specFromID(wire->viewLayerID())); if (toConnectorItem == NULL) { // shouldn't really be here return; } QPointF p1(0,0), p2, pos; ConnectorItem * other = wire->otherConnector(fromConnectorItem); if (fromConnectorItem == wire->connector0()) { pos = toConnectorItem->sceneAdjustedTerminalPoint(fromConnectorItem); ConnectorItem * toConnector1 = other->firstConnectedToIsh(); if (toConnector1 == NULL) { p2 = other->mapToScene(other->pos()) - pos; } else { p2 = toConnector1->sceneAdjustedTerminalPoint(other); } } else { pos = wire->pos(); ConnectorItem * toConnector0 = other->firstConnectedToIsh(); if (toConnector0 == NULL) { pos = wire->pos(); } else { pos = toConnector0->sceneAdjustedTerminalPoint(other); } p2 = toConnectorItem->sceneAdjustedTerminalPoint(fromConnectorItem) - pos; } wire->setLineAnd(QLineF(p1, p2), pos, true); // here's the connect (model has been previously updated) fromConnectorItem->connectTo(toConnectorItem); toConnectorItem->connectTo(fromConnectorItem); this->update(); } void SketchWidget::wireDisconnectedSlot(long fromID, QString fromConnectorID) { DebugDialog::debug(QString("got wire disconnected")); ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) return; Wire* wire = qobject_cast(fromItem); if (wire == NULL) return; ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, ViewLayer::specFromID(wire->viewLayerID())); if (fromConnectorItem == NULL) { // shouldn't be here return; } ConnectorItem * toConnectorItem = fromConnectorItem->firstConnectedToIsh(); if (toConnectorItem != NULL) { fromConnectorItem->removeConnection(toConnectorItem, true); toConnectorItem->removeConnection(fromConnectorItem, true); } } void SketchWidget::changeConnection(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, bool doEmit, bool updateConnections) { changeConnectionAux(fromID, fromConnectorID, toID, toConnectorID, viewLayerPlacement, connect, updateConnections); if (doEmit) { //TODO: findPartOrWire not necessary for harmonize? //fromID = findPartOrWire(fromID); //toID = findPartOrWire(toID); emit changeConnectionSignal(fromID, fromConnectorID, toID, toConnectorID, viewLayerPlacement, connect, updateConnections); } } void SketchWidget::changeConnectionAux(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, bool updateConnections) { // only called from the above changeConnection() which is invoked only from a command object DebugDialog::debug(QString("changeConnection: from %1 %2; to %3 %4 con:%5 v:%6") .arg(fromID).arg(fromConnectorID) .arg(toID).arg(toConnectorID) .arg(connect).arg(m_viewID) ); ItemBase * fromItem = findItem(fromID); if (fromItem == NULL) { DebugDialog::debug(QString("change connection exit 1 %1").arg(fromID)); return; } ItemBase * toItem = findItem(toID); if (toItem == NULL) { DebugDialog::debug(QString("change connection exit 2 %1").arg(toID)); return; } ConnectorItem * fromConnectorItem = findConnectorItem(fromItem, fromConnectorID, viewLayerPlacement); if (fromConnectorItem == NULL) { // shouldn't be here DebugDialog::debug(QString("change connection exit 3 %1 %2").arg(fromItem->id()).arg(fromConnectorID)); return; } ConnectorItem * toConnectorItem = findConnectorItem(toItem, toConnectorID, viewLayerPlacement); if (toConnectorItem == NULL) { // shouldn't be here DebugDialog::debug(QString("change connection exit 4 %1 %2").arg(toItem->id()).arg(toConnectorID)); return; } //fromConnectorItem->debugInfo(" from"); //toConnectorItem->debugInfo(" to"); ratsnestConnect(fromConnectorItem, toConnectorItem, connect, true); if (connect) { // canConnect checks for when a THT part has been swapped for an SMD part, and the connections are now on different layers // it seems very difficult to test this condition before the part has actually been created if (canConnect(fromItem, toItem)) { fromConnectorItem->connector()->connectTo(toConnectorItem->connector()); fromConnectorItem->connectTo(toConnectorItem); toConnectorItem->connectTo(fromConnectorItem); } } else { fromConnectorItem->connector()->disconnectFrom(toConnectorItem->connector()); fromConnectorItem->removeConnection(toConnectorItem, true); toConnectorItem->removeConnection(fromConnectorItem, true); } if (updateConnections) { if (updateOK(fromConnectorItem, toConnectorItem)) { QList already; fromConnectorItem->attachedTo()->updateConnections(fromConnectorItem, false, already); toConnectorItem->attachedTo()->updateConnections(toConnectorItem, false, already); } } } void SketchWidget::changeConnectionSlot(long fromID, QString fromConnectorID, long toID, QString toConnectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool connect, bool updateConnections) { changeConnection(fromID, fromConnectorID, toID, toConnectorID, viewLayerPlacement, connect, false, updateConnections); } void SketchWidget::keyReleaseEvent(QKeyEvent * event) { //DebugDialog::debug(QString("key release event %1").arg(event->isAutoRepeat())); if (m_movingByArrow) { m_autoScrollTimer.stop(); m_arrowTimer.start(); //DebugDialog::debug("key release event"); } else { QGraphicsView::keyReleaseEvent(event); } } void SketchWidget::arrowTimerTimeout() { m_movingByArrow = false; if (checkMoved(false)) { m_savedItems.clear(); m_savedWires.clear(); } } void SketchWidget::keyPressEvent ( QKeyEvent * event ) { //DebugDialog::debug("key press event"); if ((m_inFocus.length() == 0) && !m_movingByMouse) { int dx = 0, dy = 0; switch (event->key()) { case Qt::Key_Up: dy = -1; break; case Qt::Key_Down: dy = 1; break; case Qt::Key_Left: dx = -1; break; case Qt::Key_Right: dx = 1; break; default: break; } if (dx != 0 || dy != 0) { m_arrowTimer.stop(); DebugDialog::debug("arrow press event"); ConnectorItem::clearEqualPotentialDisplay(); moveByArrow(dx, dy, event); m_arrowTimer.start(); return; } } QGraphicsView::keyPressEvent(event); } void SketchWidget::makeDeleteItemCommand(ItemBase * itemBase, BaseCommand::CrossViewType crossView, QUndoCommand * parentCommand) { if (crossView == BaseCommand::CrossView) { emit makeDeleteItemCommandPrepSignal(itemBase, true, parentCommand); } makeDeleteItemCommandPrepSlot(itemBase, false, parentCommand); if (crossView == BaseCommand::CrossView) { emit makeDeleteItemCommandFinalSignal(itemBase, true, parentCommand); } makeDeleteItemCommandFinalSlot(itemBase, false, parentCommand); } void SketchWidget::makeDeleteItemCommandPrepSlot(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand) { if (foreign) { itemBase = findItem(itemBase->id()); if (itemBase == NULL) return; } if (itemBase->isPartLabelVisible()) { ShowLabelCommand * slc = new ShowLabelCommand(this, parentCommand); slc->add(itemBase->id(), true, true); } Note * note = qobject_cast(itemBase); if (note != NULL) { ChangeNoteTextCommand * cntc = new ChangeNoteTextCommand(this, note->id(), note->text(), note->text(), QSizeF(), QSizeF(), parentCommand); cntc->setSkipFirstRedo(); } else { new ChangeLabelTextCommand(this, itemBase->id(), itemBase->instanceTitle(), itemBase->instanceTitle(), parentCommand); } if (!foreign) { QMap propsMap; prepDeleteProps(itemBase, itemBase->id(), "", propsMap, parentCommand); } rememberSticky(itemBase, parentCommand); Wire * wire = qobject_cast(itemBase); if (wire) { const Bezier * bezier = wire->curve(); if (bezier && !bezier->isEmpty()) { ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, itemBase->id(), bezier, NULL, wire->getAutoroutable(), parentCommand); cwcc->setUndoOnly(); } } if (itemBase->hasRubberBandLeg()) { foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { if (!connectorItem->hasRubberBandLeg()) continue; // backwards order: curves then polys, since these will be trigged by undo QVector beziers = connectorItem->beziers(); for (int i = 0; i < beziers.count() - 1; i++) { Bezier * bezier = beziers.at(i); if (bezier == NULL) continue; if (bezier->isEmpty()) continue; ChangeLegCurveCommand * clcc = new ChangeLegCurveCommand(this, itemBase->id(), connectorItem->connectorSharedID(), i, bezier, bezier, parentCommand); clcc->setUndoOnly(); } QPolygonF poly = connectorItem->leg(); ChangeLegCommand * clc = new ChangeLegCommand(this, itemBase->id(), connectorItem->connectorSharedID(), poly, poly, true, true, "delete", parentCommand); clc->setUndoOnly(); // TODO: beziers here } } } void SketchWidget::makeDeleteItemCommandFinalSlot(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand) { if (foreign) { itemBase = findItem(itemBase->id()); if (itemBase == NULL) return; } ModelPart * mp = itemBase->modelPart(); // single view because this is called for each view new DeleteItemCommand(this, BaseCommand::SingleView, mp->moduleID(), itemBase->viewLayerPlacement(), itemBase->getViewGeometry(), itemBase->id(), mp->modelIndex(), parentCommand); } void SketchWidget::prepDeleteProps(ItemBase * itemBase, long id, const QString & newModuleID, QMap & propsMap, QUndoCommand * parentCommand) { // TODO: does this need to be generalized to the whole set of modelpart props? // TODO: Ruler? // TODO: this all belongs in PartFactory or in a call to the part itself // NOTE: prepDeleteProps is called after a swap and assumes that the new part is closely related to the old part // meaning that the properties of itemBase (which is the old part) apply to the new part (which has not yet been created) // this works most of the time, but does not, for example, when a ResizableBoard is swapped for a custom board shape bool boardToCustomBoard = false; ModelPart * mp = (newModuleID.isEmpty()) ? itemBase->modelPart() : referenceModel()->retrieveModelPart(newModuleID); if (mp->itemType() == ModelPart::Logo && qobject_cast(itemBase) != NULL) { boardToCustomBoard = true; mp = itemBase->modelPart(); } switch (mp->itemType()) { case ModelPart::Wire: { Wire * wire = qobject_cast(itemBase); new WireWidthChangeCommand(this, id, wire->width(), wire->width(), parentCommand); new WireColorChangeCommand(this, id, wire->colorString(), wire->colorString(), wire->opacity(), wire->opacity(), parentCommand); } return; case ModelPart::Board: new ChangeBoardLayersCommand(this, m_boardLayers, m_boardLayers, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); return; case ModelPart::ResizableBoard: { new ChangeBoardLayersCommand(this, m_boardLayers, m_boardLayers, parentCommand); ResizableBoard * brd = qobject_cast(itemBase); if (brd) { brd->saveParams(); QPointF p; QSizeF sz; brd->getParams(p, sz); ResizeBoardCommand * rbc = new ResizeBoardCommand(this, id, sz.width(), sz.height(), sz.width(), sz.height(), parentCommand); if (boardToCustomBoard) { rbc->setUndoOnly(); } } prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } return; case ModelPart::Logo: { LogoItem * logo = qobject_cast(itemBase); logo->saveParams(); QPointF p; QSizeF sz; logo->getParams(p, sz); new ResizeBoardCommand(this, id, sz.width(), sz.height(), sz.width(), sz.height(), parentCommand); QString logoProp = logo->prop("logo"); QString shapeProp = logo->prop("shape"); if (!logoProp.isEmpty()) { new SetPropCommand(this, id, "logo", logoProp, logoProp, true, parentCommand); } else if (!shapeProp.isEmpty()) { QString newName = logo->getNewLayerFileName(propsMap.value("layer")); new LoadLogoImageCommand(this, id, shapeProp, logo->modelPart()->localProp("aspectratio").toSizeF(), logo->prop("lastfilename"), newName, false, parentCommand); } prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } return; case ModelPart::Jumper: { JumperItem * jumper = qobject_cast(itemBase); jumper->saveParams(); QPointF p; QPointF c0, c1; jumper->getParams(p, c0, c1); new ResizeJumperItemCommand(this, id, p, c0, c1, p, c0, c1, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } return; case ModelPart::CopperFill: { GroundPlane * groundPlane = dynamic_cast(itemBase); new SetPropCommand(this, id, "svg", groundPlane->svg(), groundPlane->svg(), true, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } return; case ModelPart::Symbol: { SymbolPaletteItem * sitem = dynamic_cast(itemBase); QString label = sitem->getLabel(); if (!label.isEmpty()) { new SetPropCommand(this, id, "label", label, label, true, parentCommand); } prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } return; default: break; } Pad* pad = qobject_cast(itemBase); if (pad != NULL) { pad->saveParams(); QPointF p; QSizeF sz; pad->getParams(p, sz); new ResizeBoardCommand(this, id, sz.width(), sz.height(), sz.width(), sz.height(), parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); return; } Resistor * resistor = qobject_cast(itemBase); if (resistor != NULL) { new SetResistanceCommand(this, id, resistor->resistance(), resistor->resistance(), resistor->pinSpacing(), resistor->pinSpacing(), parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); return; } MysteryPart * mysteryPart = qobject_cast(itemBase); if (mysteryPart != NULL) { new SetPropCommand(this, id, "chip label", mysteryPart->chipLabel(), mysteryPart->chipLabel(), true, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); return; } /* PinHeader * pinHeader = qobject_cast(itemBase); if (pinHeader != NULL) { // deal with old-style pin headers (pre 0.6.4) new SetPropCommand(this, id, "form", pinHeader->form(), PinHeader::findForm(newModuleID), true, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, parentCommand); return; } */ Hole * hole = qobject_cast(itemBase); if (hole != NULL) { new SetPropCommand(this, id, "hole size", hole->holeSize(), hole->holeSize(), true, parentCommand); prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); return; } prepDeleteOtherProps(itemBase, id, newModuleID, propsMap, parentCommand); } void SketchWidget::prepDeleteOtherProps(ItemBase * itemBase, long id, const QString & newModuleID, QMap & propsMap, QUndoCommand * parentCommand) { Capacitor * capacitor = qobject_cast(itemBase); if (capacitor) { QHash properties; capacitor->getProperties(properties); foreach(QString prop, properties.keys()) { new SetPropCommand(this, id, prop, properties.value(prop), properties.value(prop), true, parentCommand); } } if (itemBase->moduleID().endsWith(ModuleIDNames::StripboardModuleIDName) || itemBase->moduleID().endsWith(ModuleIDNames::Stripboard2ModuleIDName)) { QString buses = itemBase->prop("buses"); QString newBuses = propsMap.value("buses"); if (newBuses.isEmpty()) newBuses = buses; if (!buses.isEmpty()) { new SetPropCommand(this, id, "buses", buses, newBuses, true, parentCommand); } QString layout = itemBase->prop("layout"); QString newLayout = propsMap.value("layout"); if (newLayout.isEmpty()) newLayout = layout; if (!layout.isEmpty()) { new SetPropCommand(this, id, "layout", layout, newLayout, true, parentCommand); } } QString value = itemBase->modelPart()->localProp(ModelPartShared::PartNumberPropertyName).toString(); if (!value.isEmpty()) { QString newValue = value; if (!newModuleID.isEmpty()) { newValue = ""; ModelPart * newModelPart = m_referenceModel->retrieveModelPart(newModuleID); if (newModelPart != NULL) { newValue = newModelPart->properties().value(ModelPartShared::PartNumberPropertyName, ""); } } new SetPropCommand(this, id, ModelPartShared::PartNumberPropertyName, value, newValue, true, parentCommand); } } void SketchWidget::rememberSticky(long id, QUndoCommand * parentCommand) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; rememberSticky(itemBase, parentCommand); } void SketchWidget::rememberSticky(ItemBase * itemBase, QUndoCommand * parentCommand) { QList< QPointer > stickyList = itemBase->stickyList(); if (stickyList.count() <= 0) return; CheckStickyCommand * checkStickyCommand = new CheckStickyCommand(this, BaseCommand::SingleView, itemBase->id(), false, CheckStickyCommand::UndoOnly, parentCommand); if (itemBase->isBaseSticky()) { foreach (ItemBase * sticking, stickyList) { checkStickyCommand->stick(this, itemBase->id(), sticking->id(), true); } } else if (itemBase->stickingTo() != NULL) { checkStickyCommand->stick(this, itemBase->stickingTo()->id(), itemBase->id(), true); } } ViewLayer::ViewID SketchWidget::viewID() { return m_viewID; } void SketchWidget::setViewLayerIDs(ViewLayer::ViewLayerID part, ViewLayer::ViewLayerID wire, ViewLayer::ViewLayerID connector, ViewLayer::ViewLayerID ruler, ViewLayer::ViewLayerID note) { m_partViewLayerID = part; m_wireViewLayerID = wire; m_connectorViewLayerID = connector; m_rulerViewLayerID = ruler; m_noteViewLayerID = note; } void SketchWidget::dragIsDoneSlot(ItemDrag * itemDrag) { disconnect(itemDrag, SIGNAL(dragIsDoneSignal(ItemDrag *)), this, SLOT(dragIsDoneSlot(ItemDrag *))); killDroppingItem(); // drag is done, but nothing dropped here: remove the temporary item } void SketchWidget::clearTemporaries() { for (int i = 0; i < m_temporaries.count(); i++) { QGraphicsItem * item = m_temporaries[i]; scene()->removeItem(item); delete item; } m_temporaries.clear(); } void SketchWidget::killDroppingItem() { m_alignmentItem = NULL; if (m_droppingItem != NULL) { m_droppingItem->removeLayerKin(); this->scene()->removeItem(m_droppingItem); if (m_droppingItem->modelPart()) { delete m_droppingItem->modelPart(); } delete m_droppingItem; m_droppingItem = NULL; } } ViewLayer::ViewLayerID SketchWidget::getViewLayerID(ModelPart * modelPart, ViewLayer::ViewID viewID, ViewLayer::ViewLayerPlacement viewLayerPlacement) { LayerList viewLayers = modelPart->viewLayers(viewID); if (viewLayers.count() == 1) { return viewLayers.at(0); } return multiLayerGetViewLayerID(modelPart, viewID, viewLayerPlacement, viewLayers); } ViewLayer::ViewLayerID SketchWidget::multiLayerGetViewLayerID(ModelPart * modelPart, ViewLayer::ViewID viewID, ViewLayer::ViewLayerPlacement viewLayerPlacement, LayerList & layerList) { Q_UNUSED(modelPart); Q_UNUSED(viewID); Q_UNUSED(viewLayerPlacement); if (layerList.count() == 0) return ViewLayer::UnknownLayer; return layerList.at(0); } ItemBase * SketchWidget::overSticky(ItemBase * itemBase) { if (!itemBase->stickyEnabled()) return NULL; foreach (QGraphicsItem * item, scene()->collidingItems(itemBase)) { ItemBase * s = dynamic_cast(item); if (s == NULL) continue; if (s == itemBase) continue; if (!s->isBaseSticky()) continue; return s->layerKinChief(); } return NULL; } void SketchWidget::stickem(long stickTargetID, long stickSourceID, bool stick) { ItemBase * stickTarget = findItem(stickTargetID); if (stickTarget == NULL) return; ItemBase * stickSource = findItem(stickSourceID); if (stickSource == NULL) return; stickTarget->addSticky(stickSource, stick); stickSource->addSticky(stickTarget, stick); } void SketchWidget::setChainDrag(bool chainDrag) { m_chainDrag = chainDrag; } void SketchWidget::stickyScoop(ItemBase * stickyOne, bool checkCurrent, CheckStickyCommand * checkStickyCommand) { // TODO: use the shape rather than the rect // need to find the best layerkin to use in that case //foreach (QGraphicsItem * item, scene()->collidingItems(stickyOne)) { QList added; QList already; QPolygonF poly = stickyOne->mapToScene(stickyOne->boundingRect()); foreach (QGraphicsItem * item, scene()->items(poly)) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBase = itemBase->layerKinChief(); if (!itemBase->stickyEnabled()) continue; if (added.contains(itemBase)) continue; if (itemBase->isBaseSticky()) continue; if (stickyOne->alreadySticking(itemBase)) { already.append(itemBase); continue; } stickyOne->addSticky(itemBase, true); itemBase->addSticky(stickyOne, true); if (checkStickyCommand) { checkStickyCommand->stick(this, stickyOne->id(), itemBase->id(), true); } added.append(itemBase); } if (checkCurrent) { foreach (ItemBase * itemBase, stickyOne->stickyList()) { if (added.contains(itemBase)) continue; if (already.contains(itemBase)) continue; stickyOne->addSticky(itemBase, false); itemBase->addSticky(stickyOne, false); if (checkStickyCommand) { checkStickyCommand->stick(this, stickyOne->id(), itemBase->id(), false); } } } } void SketchWidget::wireSplitSlot(Wire* wire, QPointF newPos, QPointF oldPos, const QLineF & oldLine) { if (!canChainWire(wire)) return; this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(QObject::tr("Split Wire") ); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); long fromID = wire->id(); QLineF newLine(oldLine.p1(), newPos - oldPos); long newID = ItemBase::getNextID(); ViewGeometry vg(wire->getViewGeometry()); vg.setLoc(newPos); QLineF newLine2(QPointF(0,0), oldLine.p2() + oldPos - newPos); vg.setLine(newLine2); BaseCommand::CrossViewType crossView = wireSplitCrossView(); new AddItemCommand(this, crossView, ModuleIDNames::WireModuleIDName, wire->viewLayerPlacement(), vg, newID, true, -1, parentCommand); new CheckStickyCommand(this, crossView, newID, false, CheckStickyCommand::RemoveOnly, parentCommand); new WireColorChangeCommand(this, newID, wire->colorString(), wire->colorString(), wire->opacity(), wire->opacity(), parentCommand); new WireWidthChangeCommand(this, newID, wire->width(), wire->width(), parentCommand); if (wire->banded()) { new SetPropCommand(this, newID, "banded", "Yes", "Yes", true, parentCommand); } // disconnect from original wire and reconnect to new wire ConnectorItem * connector1 = wire->connector1(); foreach (ConnectorItem * toConnectorItem, connector1->connectedToItems()) { new ChangeConnectionCommand(this, crossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), wire->id(), connector1->connectorSharedID(), ViewLayer::specFromID(wire->viewLayerID()), false, parentCommand); new ChangeConnectionCommand(this, crossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), newID, connector1->connectorSharedID(), ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); } new ChangeWireCommand(this, fromID, oldLine, newLine, oldPos, oldPos, true, false, parentCommand); // connect the two wires new ChangeConnectionCommand(this, crossView, wire->id(), connector1->connectorSharedID(), newID, "connector0", ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); selectItemCommand->addRedo(newID); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void SketchWidget::wireJoinSlot(Wire* wire, ConnectorItem * clickedConnectorItem) { // if (!canChainWire(wire)) return; // can't join a wire in some views (for now) this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted QUndoCommand * parentCommand = new QUndoCommand(); parentCommand->setText(QObject::tr("Join Wire") ); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); // assumes there is one and only one item connected ConnectorItem * toConnectorItem = clickedConnectorItem->connectedToItems()[0]; if (toConnectorItem == NULL) return; Wire * toWire = qobject_cast(toConnectorItem->attachedTo()); if (toWire == NULL) return; if (wire->id() > toWire->id()) { // delete the wire with the higher id // so we can keep the three views in sync // i.e. the original wire has the lowest id in the chain Wire * wtemp = toWire; toWire = wire; wire = wtemp; ConnectorItem * ctemp = toConnectorItem; toConnectorItem = clickedConnectorItem; clickedConnectorItem = ctemp; } ConnectorItem * otherConnector = toWire->otherConnector(toConnectorItem); BaseCommand::CrossViewType crossView = BaseCommand::CrossView; // wireSplitCrossView(); ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, wire->id(), wire->curve(), NULL, wire->getAutoroutable(), parentCommand); cwcc->setUndoOnly(); cwcc = new ChangeWireCurveCommand(this, toWire->id(), toWire->curve(), NULL, toWire->getAutoroutable(),parentCommand); cwcc->setUndoOnly(); // disconnect the wires new ChangeConnectionCommand(this, crossView, wire->id(), clickedConnectorItem->connectorSharedID(), toWire->id(), toConnectorItem->connectorSharedID(), ViewLayer::specFromID(wire->viewLayerID()), false, parentCommand); // disconnect everyone from the other end of the wire being deleted, and reconnect to the remaining wire foreach (ConnectorItem * otherToConnectorItem, otherConnector->connectedToItems()) { new ChangeConnectionCommand(this, crossView, otherToConnectorItem->attachedToID(), otherToConnectorItem->connectorSharedID(), toWire->id(), otherConnector->connectorSharedID(), ViewLayer::specFromID(toWire->viewLayerID()), false, parentCommand); new ChangeConnectionCommand(this, crossView, otherToConnectorItem->attachedToID(), otherToConnectorItem->connectorSharedID(), wire->id(), clickedConnectorItem->connectorSharedID(), ViewLayer::specFromID(wire->viewLayerID()), true, parentCommand); } toWire->saveGeometry(); makeDeleteItemCommand(toWire, crossView, parentCommand); Bezier b0, b1; QLineF newLine; QPointF newPos; if (otherConnector == toWire->connector1()) { newPos = wire->pos(); newLine = QLineF(QPointF(0,0), toWire->pos() - wire->pos() + toWire->line().p2()); b0.copy(wire->curve()); b1.copy(toWire->curve()); b0.set_endpoints(wire->line().p1(), wire->line().p2()); b1.set_endpoints(toWire->line().p1(), toWire->line().p2()); b1.translate(toWire->pos() - wire->pos()); } else { newPos = toWire->pos(); newLine = QLineF(QPointF(0,0), wire->pos() - toWire->pos() + wire->line().p2()); b0.copy(toWire->curve()); b1.copy(wire->curve()); b0.set_endpoints(toWire->line().p1(), toWire->line().p2()); b1.set_endpoints(wire->line().p1(), wire->line().p2()); b1.translate(wire->pos() - toWire->pos()); } new ChangeWireCommand(this, wire->id(), wire->line(), newLine, wire->pos(), newPos, true, false, parentCommand); Bezier joinBezier = b0.join(&b1); if (!joinBezier.isEmpty()) { ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, wire->id(), wire->curve(), &joinBezier, wire->getAutoroutable(), parentCommand); cwcc->setRedoOnly(); } new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } void SketchWidget::hoverEnterItem(QGraphicsSceneHoverEvent * event, ItemBase * item) { if(m_infoViewOnHover || currentlyInfoviewed(item)) { InfoGraphicsView::hoverEnterItem(event, item); } Wire * wire = dynamic_cast(item); if (wire != NULL) { if (canChainWire(wire)) { bool segment = wire->connector0()->chained() && wire->connector1()->chained(); bool disconnected = wire->connector0()->connectionsCount() == 0 && wire->connector1()->connectionsCount() == 0; statusMessage(QString("%1 to add a bendpoint %2") .arg(disconnected ? tr("Double-click") : tr("Drag or double-click")) .arg(segment ? tr("or alt-drag to move the segment") : tr(""))); m_lastHoverEnterItem = item; } } } void SketchWidget::statusMessage(QString message, int timeout) { // TODO: eventually do the connecting from the window not from the sketch QMainWindow * mainWindow = qobject_cast(window()); if (mainWindow == NULL) return; if (m_statusConnectState == StatusConnectNotTried) { bool result = connect(this, SIGNAL(statusMessageSignal(QString, int)), mainWindow, SLOT(statusMessage(QString, int))); m_statusConnectState = (result) ? StatusConnectSucceeded : StatusConnectFailed; } if (m_statusConnectState == StatusConnectFailed) { QStatusBar * sb = mainWindow->statusBar(); if (sb != NULL) { sb->showMessage(message, timeout); } } else { emit statusMessageSignal(message, timeout); } } void SketchWidget::hoverLeaveItem(QGraphicsSceneHoverEvent * event, ItemBase * item){ m_lastHoverEnterItem = NULL; if(m_infoViewOnHover) { InfoGraphicsView::hoverLeaveItem(event, item); } if (canChainWire(qobject_cast(item))) { statusMessage(QString()); } } void SketchWidget::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { if(m_infoViewOnHover || currentlyInfoviewed(item->attachedTo())) { InfoGraphicsView::hoverEnterConnectorItem(event, item); } if (item->attachedToItemType() == ModelPart::Wire) { if (!this->m_chainDrag) return; if (!item->chained()) return; m_lastHoverEnterConnectorItem = item; QString msg = hoverEnterWireConnectorMessage(event, item); statusMessage(msg); } else { QString msg = hoverEnterPartConnectorMessage(event, item); statusMessage(msg); } } const QString & SketchWidget::hoverEnterWireConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { Q_UNUSED(event); Q_UNUSED(item); static QString message = tr("Double-click to delete this bend point"); return message; } const QString & SketchWidget::hoverEnterPartConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { Q_UNUSED(event); Q_UNUSED(item); return ___emptyString___; } void SketchWidget::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item) { m_lastHoverEnterConnectorItem = NULL; ItemBase* attachedTo = item->attachedTo(); if(attachedTo) { if(m_infoViewOnHover || currentlyInfoviewed(attachedTo)) { InfoGraphicsView::hoverLeaveConnectorItem(event, item); if(attachedTo->collidesWithItem(item)) { hoverEnterItem(event,attachedTo); } } attachedTo->hoverLeaveConnectorItem(event, item); } if (attachedTo->itemType() == ModelPart::Wire) { if (!this->m_chainDrag) return; if (!item->chained()) return; statusMessage(QString()); } else { statusMessage(QString()); } } bool SketchWidget::currentlyInfoviewed(ItemBase *item) { if(m_infoView) { ItemBase * currInfoView = m_infoView->currentItem(); return !currInfoView || item == currInfoView;//->cu selItems.size()==1 && selItems[0] == item; } return false; } void SketchWidget::cleanUpWires(bool doEmit, CleanUpWiresCommand * command) { RoutingStatus routingStatus; updateRoutingStatus(command, routingStatus, false); if (doEmit) { emit cleanUpWiresSignal(command); } } void SketchWidget::cleanUpWiresSlot(CleanUpWiresCommand * command) { RoutingStatus routingStatus; updateRoutingStatus(command, routingStatus, false); } void SketchWidget::noteChanged(ItemBase * item, const QString &oldText, const QString & newText, QSizeF oldSize, QSizeF newSize) { ChangeNoteTextCommand * command = new ChangeNoteTextCommand(this, item->id(), oldText, newText, oldSize, newSize, NULL); command->setText(tr("Note text change")); command->setSkipFirstRedo(); m_undoStack->waitPush(command, PropChangeDelay); } void SketchWidget::partLabelChanged(ItemBase * pitem,const QString & oldText, const QString &newText) { // partLabelChanged triggered from inline editing the label if (!m_current) { // all three views get the partLabelChanged call, but only need to act on this once return; } //if (currentlyInfoviewed(pitem)) { // TODO: just change the affected item in the info view //viewItemInfo(pitem); //} partLabelChangedAux(pitem, oldText, newText); } void SketchWidget::partLabelChangedAux(ItemBase * pitem,const QString & oldText, const QString &newText) { if (pitem == NULL) return; ChangeLabelTextCommand * command = new ChangeLabelTextCommand(this, pitem->id(), oldText, newText, NULL); command->setText(tr("Change %1 label to '%2'").arg(pitem->title()).arg(newText)); m_undoStack->waitPush(command, PropChangeDelay); } void SketchWidget::setInfoViewOnHover(bool infoViewOnHover) { m_infoViewOnHover = infoViewOnHover; } void SketchWidget::updateInfoView() { if (m_blockUI) return; QTimer::singleShot(50, this, SLOT(updateInfoViewSlot())); } void SketchWidget::updateInfoViewSlot() { foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; ItemBase * chief = itemBase->layerKinChief(); viewItemInfo(chief); return; } viewItemInfo(m_lastPaletteItemSelected); } long SketchWidget::setUpSwap(SwapThing & swapThing, bool master) { if (swapThing.firstTime) { swapThing.firstTime = false; swapThing.newID = swapStart(swapThing, master); // need to ensure the parts are all created first thing emit swapStartSignal(swapThing, master); } ItemBase * itemBase = swapThing.itemBase; if (itemBase->viewID() != m_viewID) { itemBase = findItem(itemBase->id()); if (itemBase == NULL) return swapThing.newID; } setUpSwapReconnect(swapThing, itemBase, swapThing.newID, master); new CheckStickyCommand(this, BaseCommand::SingleView, swapThing.newID, false, CheckStickyCommand::RemoveOnly, swapThing.parentCommand); if (itemBase->isPartLabelVisible()) { ShowLabelCommand * slc = new ShowLabelCommand(this, swapThing.parentCommand); slc->add(swapThing.newID, true, true); } if (master) { SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, swapThing.parentCommand); selectItemCommand->addRedo(swapThing.newID); selectItemCommand->addUndo(itemBase->id()); new ChangeLabelTextCommand(this, itemBase->id(), itemBase->instanceTitle(), itemBase->instanceTitle(), swapThing.parentCommand); new ChangeLabelTextCommand(this, swapThing.newID, itemBase->instanceTitle(), itemBase->instanceTitle(), swapThing.parentCommand); /* foreach (Wire * wire, swapThing.wiresToDelete) { QList chained; QList ends; wire->collectChained(chained, ends); foreach (Wire * w, chained) { if (!swapThing.wiresToDelete.contains(w)) swapThing.wiresToDelete.append(w); } } makeWiresChangeConnectionCommands(swapThing.wiresToDelete, swapThing.parentCommand); foreach (Wire * wire, swapThing.wiresToDelete) { makeDeleteItemCommand(wire, BaseCommand::CrossView, swapThing.parentCommand); } */ makeDeleteItemCommand(itemBase, BaseCommand::CrossView, swapThing.parentCommand); selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, swapThing.parentCommand); selectItemCommand->addRedo(swapThing.newID); // to make sure new item is selected so it appears in the info view prepDeleteProps(itemBase, swapThing.newID, swapThing.newModuleID, swapThing.propsMap, swapThing.parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, swapThing.parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, swapThing.parentCommand); } return swapThing.newID; } void SketchWidget::setUpSwapReconnect(SwapThing & swapThing, ItemBase * itemBase, long newID, bool master) { ModelPart * newModelPart = m_referenceModel->retrieveModelPart(swapThing.newModuleID); if (newModelPart == NULL) return; QList fromConnectorItems(itemBase->cachedConnectorItems()); newModelPart->initConnectors(); // make sure the connectors are set up QList< QPointer > newConnectors = newModelPart->connectors().values(); bool checkReplacedby = (!itemBase->modelPart()->replacedby().isEmpty() && itemBase->modelPart()->replacedby() == swapThing.newModuleID); QList notFound; QList other; QHash found; QHash m2f; foreach (ConnectorItem * fromConnectorItem, fromConnectorItems) { QList candidates; Connector * newConnector = NULL; if (fromConnectorItem->connectorType() == Connector::Male) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { if (toConnectorItem->connectorType() == Connector::Female) { m2f.insert(fromConnectorItem, toConnectorItem); break; } } } // matching by connectorid can lead to weird results because these all just usually count up from zero // so only match by name and description (the latter is a bit of a hail mary) QString fromName = fromConnectorItem->connectorSharedName(); QString fromDescription = fromConnectorItem->connectorSharedDescription(); QString fromReplacedby = fromConnectorItem->connectorSharedReplacedby(); //itemBase->debugInfo(QString("%1 %2").arg(fromName).arg(fromReplacedby)); foreach (Connector * connector, newConnectors) { QString toName = connector->connectorSharedName(); QString toID = connector->connectorSharedID(); if (checkReplacedby) { if (fromReplacedby.compare(toName, Qt::CaseInsensitive) == 0 || fromReplacedby.compare(toID) == 0) { candidates.clear(); candidates.append(connector); //fromConnectorItem->debugInfo(QString("matched %1 %2").arg(toName).arg(toID)); break; } } bool gotOne = false; QString toDescription = connector->connectorSharedDescription(); if (fromName.compare(toName, Qt::CaseInsensitive) == 0) { gotOne = true; } else if (fromDescription.compare(toDescription, Qt::CaseInsensitive) == 0) { gotOne = true; } else if (fromDescription.compare(toName, Qt::CaseInsensitive) == 0) { gotOne = true; } else if (fromName.compare(toDescription, Qt::CaseInsensitive) == 0) { gotOne = true; } if (gotOne) { candidates.append(connector); } } if (candidates.count() > 0) { newConnector = candidates[0]; if (candidates.count() > 1) { foreach (Connector * connector, candidates) { // this gets an exact match, if there is one if (fromConnectorItem->connectorSharedID().compare(connector->connectorSharedID(), Qt::CaseInsensitive) == 0) { newConnector = connector; break; } } } newConnectors.removeOne(newConnector); found.insert(fromConnectorItem, newConnector); fromConnectorItem = fromConnectorItem->getCrossLayerConnectorItem(); if (fromConnectorItem) { other.append(fromConnectorItem); found.insert(fromConnectorItem, newConnector); } } else { notFound.append(fromConnectorItem); } } QHash legs; QHash formerLegs; if (m2f.count() > 0 && (m_viewID == ViewLayer::BreadboardView)) { checkFit(newModelPart, itemBase, newID, found, notFound, m2f, swapThing.byWire, legs, formerLegs, swapThing.parentCommand); } fromConnectorItems.append(other); foreach (ConnectorItem * fromConnectorItem, fromConnectorItems) { //fromConnectorItem->debugInfo("from"); Connector * newConnector = found.value(fromConnectorItem, NULL); foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { // delete connection to part being swapped out Wire * wire = qobject_cast(toConnectorItem->attachedTo()); if (wire != NULL) { if (wire->getRatsnest()) continue; //if (newConnector == NULL && wire->getTrace() && wire->isTraceType(getTraceFlag())) { // swapThing.wiresToDelete.append(wire); // continue; //} } // disconnect command created for each view individually extendChangeConnectionCommand(BaseCommand::SingleView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), false, swapThing.parentCommand); bool cleanup = false; if (newConnector) { bool byWireFlag = (swapThing.byWire.value(fromConnectorItem, NULL) == newConnector); bool swapped = false; if (byWireFlag) { swapThing.toConnectorItems.insert(fromConnectorItem, toConnectorItem); } else { swapped = swappedGender(fromConnectorItem, newConnector); if (swapped && m_viewID == ViewLayer::BreadboardView) { swapThing.swappedGender.insert(fromConnectorItem, newConnector); swapThing.toConnectorItems.insert(fromConnectorItem, toConnectorItem); } } cleanup = byWireFlag || swapped; } if ((newConnector == NULL) || cleanup) { // clean up after disconnect } else { // reconnect directly without cleaning up; command created for each view // if it's an smd swap, deal with reconnecting the wire at reconnect time ChangeConnectionCommand * ccc = new ChangeConnectionCommand(this, BaseCommand::SingleView, newID, newConnector->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), true, swapThing.parentCommand); swapThing.reconnections.insert(fromConnectorItem, ccc); } } } foreach (ConnectorItem * fromConnectorItem, swapThing.swappedGender.keys()) { makeSwapWire(swapThing.bbView, itemBase, newID, fromConnectorItem, swapThing.toConnectorItems.value(fromConnectorItem), swapThing.swappedGender.value(fromConnectorItem), swapThing.parentCommand); } if (master && swapThing.byWire.count() > 0) { foreach (ConnectorItem * fromConnectorItem, swapThing.byWire.keys()) { makeSwapWire(swapThing.bbView, itemBase, newID, fromConnectorItem, swapThing.toConnectorItems.value(fromConnectorItem), swapThing.byWire.value(fromConnectorItem), swapThing.parentCommand); } foreach (ConnectorItem * fromConnectorItem, swapThing.byWire.keys()) { // if a part, for example a generic DIP, is reconnected by wires after swapping, // then remove any pcb and schematic direct reconnections QList toRemove; foreach (ConnectorItem * foreign, swapThing.reconnections.keys()) { ConnectorItem * candidate = swapThing.bbView->findConnectorItem(foreign); if (candidate == fromConnectorItem) { toRemove << foreign; swapThing.reconnections.value(foreign)->disable(); } } foreach (ConnectorItem * foreign, toRemove) { swapThing.reconnections.remove(foreign); } } } // changeConnection calls PaletteItemBase::connectedMoved which repositions the new part // so slam in the desired position QPointF p = itemBase->getViewGeometry().loc(); new SimpleMoveItemCommand(this, newID, p, p, swapThing.parentCommand); foreach (QString connectorID, legs.keys()) { // must be invoked after all the connections have been dealt with QPolygonF poly = legs.value(connectorID); ConnectorItem * connectorItem = formerLegs.value(connectorID, NULL); if (connectorItem && connectorItem->hasRubberBandLeg()) { poly = connectorItem->leg(); } ChangeLegCommand * clc = new ChangeLegCommand(this, newID, connectorID, poly, poly, true, true, "swap", swapThing.parentCommand); clc->setRedoOnly(); if (connectorItem && connectorItem->hasRubberBandLeg()) { QVector beziers = connectorItem->beziers(); for (int i = 0; i < beziers.count() - 1; i++) { Bezier * bezier = beziers.at(i); if (bezier == NULL) continue; if (bezier->isEmpty()) continue; ChangeLegCurveCommand * clcc = new ChangeLegCurveCommand(this, newID, connectorID, i, bezier, bezier, swapThing.parentCommand); clcc->setRedoOnly(); } } } } void SketchWidget::makeSwapWire(SketchWidget * bbView, ItemBase * itemBase, long newID, ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Connector * newConnector, QUndoCommand * parentCommand) { Q_UNUSED(fromConnectorItem); long wireID = ItemBase::getNextID(); ViewGeometry vg; new AddItemCommand(bbView, BaseCommand::CrossView, ModuleIDNames::WireModuleIDName, itemBase->viewLayerPlacement(), vg, wireID, false, -1, parentCommand); new CheckStickyCommand(bbView, BaseCommand::CrossView, wireID, false, CheckStickyCommand::RemoveOnly, parentCommand); new ChangeConnectionCommand(bbView, BaseCommand::CrossView, newID, newConnector->connectorSharedID(), wireID, "connector0", ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), true, parentCommand); new ChangeConnectionCommand(bbView, BaseCommand::CrossView, toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), wireID, "connector1", ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), bbView, parentCommand); } void SketchWidget::checkFit(ModelPart * newModelPart, ItemBase * itemBase, long newID, QHash & found, QList & notFound, QHash & m2f, QHash & byWire, QHash & legs, QHash & formerLegs, QUndoCommand * parentCommand) { if (found.count() == 0) return; ItemBase * tempItemBase = addItemAuxTemp(newModelPart, itemBase->viewLayerPlacement(), itemBase->getViewGeometry(), newID, true, m_viewID, true); if (tempItemBase == NULL) return; // we're really screwed checkFitAux(tempItemBase, itemBase, newID, found, notFound, m2f, byWire, legs, formerLegs, parentCommand); delete tempItemBase; } void SketchWidget::checkFitAux(ItemBase * tempItemBase, ItemBase * itemBase, long newID, QHash & found, QList & notFound, QHash & m2f, QHash & byWire, QHash & legs, QHash & formerLegs, QUndoCommand * parentCommand) { QPointF foundAnchor(std::numeric_limits::max(), std::numeric_limits::max()); QPointF newAnchor(std::numeric_limits::max(), std::numeric_limits::max()); QHash foundPoints; QHash newPoints; QHash foundNews; QHash newFounds; QList removeFromFound; foreach (ConnectorItem * foundConnectorItem, found.keys()) { if (m2f.value(foundConnectorItem, NULL) == NULL) { // we only care about replacing the female connectors here continue; } Connector * connector = found.value(foundConnectorItem); ConnectorItem * newConnectorItem = NULL; foreach (ConnectorItem * nci, tempItemBase->cachedConnectorItems()) { if (nci->connector()->connectorShared() == connector->connectorShared()) { newConnectorItem = nci; break; } } if (newConnectorItem == NULL) { removeFromFound.append(foundConnectorItem); } else { foundNews.insert(foundConnectorItem, newConnectorItem); newFounds.insert(newConnectorItem, foundConnectorItem); QPointF lastNew = newConnectorItem->sceneAdjustedTerminalPoint(NULL); if (lastNew.x() < newAnchor.x()) newAnchor.setX(lastNew.x()); if (lastNew.y() < newAnchor.y()) newAnchor.setY(lastNew.y()); newPoints.insert(newConnectorItem, lastNew); QPointF lastFound = foundConnectorItem->sceneAdjustedTerminalPoint(NULL); if (lastFound.x() < foundAnchor.x()) foundAnchor.setX(lastFound.x()); if (lastFound.y() < foundAnchor.y()) foundAnchor.setY(lastFound.y()); foundPoints.insert(foundConnectorItem, lastFound); } } foreach (ConnectorItem * connectorItem, removeFromFound) { found.remove(connectorItem); notFound.append(connectorItem); } if (found.count() == 0) { return; } bool allCorrespond = true; foreach (ConnectorItem * foundConnectorItem, foundNews.keys()) { QPointF fp = foundPoints.value(foundConnectorItem) - foundAnchor; ConnectorItem * newConnectorItem = foundNews.value(foundConnectorItem); QPointF np = newPoints.value(newConnectorItem) - newAnchor; if (!newConnectorItem->hasRubberBandLeg() && (qAbs(fp.x() - np.x()) >= CloseEnough || qAbs(fp.y() - np.y()) >= CloseEnough)) { // pins can be off by a little // but if even one connector is out of place, hook everything up by wires allCorrespond = false; break; } } if (allCorrespond) { if (tempItemBase->cachedConnectorItems().count() == found.count()) { if (tempItemBase->hasRubberBandLeg()) { foreach (ConnectorItem * connectorItem, tempItemBase->cachedConnectorItems()) { legs.insert(connectorItem->connectorSharedID(), connectorItem->leg()); formerLegs.insert(connectorItem->connectorSharedID(), newFounds.value(connectorItem, NULL)); } } // it's a clean swap: all connectors line up return; } } // there's a mismatch in terms of connector count between the swaps, // so make sure all target connections are open or to be swapped out // establish the location of the new item's connectors QHash newConnections; if (allCorrespond) { QList alreadyFits = foundNews.values(); foreach (ConnectorItem * nci, tempItemBase->cachedConnectorItems()) { if (alreadyFits.contains(nci)) continue; if (nci->connectorType() != Connector::Male) continue; // TODO: this doesn't handle all scenarios. For example, if another part with a female connector is // on top of the breadboard, and would be in the way QPointF p = nci->sceneAdjustedTerminalPoint(NULL) - newAnchor + foundAnchor; // eventual position of this new connector ConnectorItem * connectorUnder = NULL; foreach (QGraphicsItem * item, scene()->items(p)) { ConnectorItem * cu = dynamic_cast(item); if (cu == NULL || cu == nci || cu->attachedTo() == itemBase || cu->connectorType() != Connector::Female) { continue; } connectorUnder = cu; break; } if (connectorUnder == NULL) { // safe? continue; } foreach (ConnectorItem * uct, connectorUnder->connectedToItems()) { if (uct->attachedTo() == itemBase) { // we're safe, itemBase is swapping out continue; } // some other part is in the way allCorrespond = false; break; } if (!allCorrespond) break; newConnections.insert(nci, connectorUnder); // add a new direct connection } } if (allCorrespond) { // the extra new connectors will also fit foreach (ConnectorItem * nci, newConnections.keys()) { ConnectorItem * toConnectorItem = newConnections.value(nci); new ChangeConnectionCommand(this, BaseCommand::CrossView, newID, nci->connectorSharedID(), toConnectorItem->attachedToID(), toConnectorItem->connectorSharedID(), ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), true, parentCommand); } if (tempItemBase->hasRubberBandLeg()) { foreach (ConnectorItem * connectorItem, newConnections) { legs.insert(connectorItem->connectorSharedID(), connectorItem->leg()); } foreach (ConnectorItem * newConnectorItem, newFounds.keys()) { legs.insert(newConnectorItem->connectorSharedID(), newConnectorItem->leg()); formerLegs.insert(newConnectorItem->connectorSharedID(), newFounds.value(newConnectorItem, NULL)); } } return; } // have to replace each found value with a wire foreach (ConnectorItem * fci, found.keys()) { byWire.insert(fci, found.value(fci)); } } void SketchWidget::changeWireColor(const QString newColor) { m_lastColorSelected = newColor; QList wires; foreach (QGraphicsItem * item, scene()->selectedItems()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; wires.append(wire); } if (wires.count() <= 0) return; QString commandString; if (wires.count() == 1) { commandString = tr("Change %1 color from %2 to %3") .arg(wires[0]->instanceTitle()) .arg(wires[0]->colorString()) .arg(newColor); } else { commandString = tr("Change color of %1 wires to %2") .arg(wires.count()) .arg(newColor); } QUndoCommand* parentCommand = new QUndoCommand(commandString); foreach (Wire * wire, wires) { QList subWires; wire->collectWires(subWires); foreach (Wire * subWire, subWires) { new WireColorChangeCommand( this, subWire->id(), subWire->colorString(), newColor, subWire->opacity(), subWire->opacity(), parentCommand); } } m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::changeWireWidthMils(const QString newWidthStr) { bool ok = false; double newWidth = newWidthStr.toDouble(&ok); if (!ok) return; double trueWidth = GraphicsUtils::SVGDPI * newWidth / 1000.0; QList wires; foreach (QGraphicsItem * item, scene()->selectedItems()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (!wire->getTrace()) continue; wires.append(wire); } if (wires.count() <= 0) return; QString commandString; if (wires.count() == 1) { commandString = tr("Change %1 width from %2 to %3") .arg(wires[0]->instanceTitle()) .arg((int) wires[0]->mils()) .arg(newWidth); } else { commandString = tr("Change width of %1 wires to %2") .arg(wires.count()) .arg(newWidth); } QUndoCommand* parentCommand = new QUndoCommand(commandString); foreach (Wire * wire, wires) { QList subWires; wire->collectWires(subWires); foreach (Wire * subWire, subWires) { new WireWidthChangeCommand( this, subWire->id(), subWire->width(), trueWidth, parentCommand); } } m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::changeWireColor(long wireId, const QString& color, double opacity) { ItemBase *item = findItem(wireId); Wire* wire = qobject_cast(item); if (wire) { wire->setColorString(color, opacity, true); updateInfoView(); } } void SketchWidget::changeWireWidth(long wireId, double width) { ItemBase *item = findItem(wireId); Wire* wire = qobject_cast(item); if (wire) { wire->setWireWidth(width, this, getWireStrokeWidth(wire, width)); updateInfoView(); } } bool SketchWidget::swappingEnabled(ItemBase * itemBase) { if (itemBase == NULL) { return m_referenceModel->swapEnabled(); } return (m_referenceModel->swapEnabled() && itemBase->isSwappable()); } void SketchWidget::resizeEvent(QResizeEvent * event) { InfoGraphicsView::resizeEvent(event); QPoint s(event->size().width(), event->size().height()); QPointF p = this->mapToScene(s); QPointF z = this->mapToScene(QPoint(0,0)); // DebugDialog::debug(QString("resize event %1 %2, %3 %4, %5 %6") /* , %3 %4 %5 %6, %7 %8 %9 %10 */ // .arg(event->size().width()).arg(event->size().height()) // .arg(p.x()).arg(p.y()) // .arg(z.x()).arg(z.y()) // .arg(sr.left()).arg(sr.top()).arg(sr.width()).arg(sr.height()) // .arg(sr.left()).arg(sr.top()).arg(ir.width()).arg(ir.height()) // // ); if (m_sizeItem != NULL) { m_sizeItem->setLine(z.x(), z.y(), p.x(), p.y()); } emit resizeSignal(); } void SketchWidget::addViewLayers() { } void SketchWidget::addViewLayersAux(const LayerList & layers, const LayerList & layersFromBelow, float startZ) { m_z = startZ; foreach(ViewLayer::ViewLayerID vlId, layers) { addViewLayer(new ViewLayer(vlId, true, m_z)); m_z += 1; } double z = startZ; foreach(ViewLayer::ViewLayerID vlId, layersFromBelow) { ViewLayer * viewLayer = m_viewLayers.value(vlId, NULL); if (viewLayer) viewLayer->setInitialZFromBelow(z); z += 1; } } void SketchWidget::setIgnoreSelectionChangeEvents(bool ignore) { if (ignore) { m_ignoreSelectionChangeEvents++; } else { m_ignoreSelectionChangeEvents--; } } void SketchWidget::hideConnectors(bool hide) { foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isVisible()) continue; foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { connectorItem->setVisible(!hide); } } } void SketchWidget::saveLayerVisibility() { m_viewLayerVisibility.clear(); foreach (ViewLayer::ViewLayerID viewLayerID, m_viewLayers.keys()) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID); if (viewLayer == NULL) continue; m_viewLayerVisibility.insert(viewLayerID, viewLayer->visible()); } } void SketchWidget::restoreLayerVisibility() { foreach (ViewLayer::ViewLayerID viewLayerID, m_viewLayerVisibility.keys()) { setLayerVisible(m_viewLayers.value(viewLayerID), m_viewLayerVisibility.value(viewLayerID), false); } } void SketchWidget::changeWireFlags(long wireId, ViewGeometry::WireFlags wireFlags) { ItemBase *item = findItem(wireId); if(Wire* wire = qobject_cast(item)) { wire->setWireFlags(wireFlags); } } bool SketchWidget::disconnectFromFemale(ItemBase * item, QHash & savedItems, ConnectorPairHash & connectorHash, bool doCommand, bool rubberBandLegEnabled, QUndoCommand * parentCommand) { // schematic and pcb view connections are always via wires so this is a no-op. breadboard view has its own version. Q_UNUSED(item); Q_UNUSED(savedItems); Q_UNUSED(parentCommand); Q_UNUSED(connectorHash); Q_UNUSED(doCommand); Q_UNUSED(rubberBandLegEnabled); return false; } void SketchWidget::spaceBarIsPressedSlot(bool isPressed) { if (m_middleMouseIsPressed) return; m_spaceBarIsPressed = isPressed; if (isPressed) { setDragMode(QGraphicsView::ScrollHandDrag); //setInteractive(false); //CursorMaster::instance()->addCursor(this, Qt::OpenHandCursor); //setCursor(Qt::OpenHandCursor); //DebugDialog::debug("setting open hand cursor"); } else { //CursorMaster::instance()->removeCursor(this); setDragMode(QGraphicsView::RubberBandDrag); //setInteractive(true); //setCursor(Qt::ArrowCursor); } } void SketchWidget::updateRoutingStatus(CleanUpWiresCommand* command, RoutingStatus & routingStatus, bool manual) { //DebugDialog::debug("update ratsnest status"); routingStatus.zero(); updateRoutingStatus(routingStatus, manual); if (routingStatus != m_routingStatus) { if (command) { // changing state after the command has already been executed command->addRoutingStatus(this, m_routingStatus, routingStatus); } emit routingStatusSignal(this, routingStatus); m_routingStatus = routingStatus; } } void SketchWidget::updateRoutingStatus(RoutingStatus & routingStatus, bool manual) { //DebugDialog::debug(QString("update routing status %1 %2 %3") // .arg(m_viewID) // .arg(m_ratsnestUpdateConnect.count()) // .arg(m_ratsnestUpdateDisconnect.count()) // ); // TODO: think about ways to optimize this... QList< QPointer > ratsToDelete; QList< QList > ratnestsToUpdate; QList visited; foreach (QGraphicsItem * item, scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (visited.contains(connectorItem)) continue; //if (this->viewID() == ViewLayer::SchematicView) { // connectorItem->debugInfo("testing urs"); //} VirtualWire * vw = qobject_cast(connectorItem->attachedTo()); if (vw != NULL) { if (vw->connector0()->connectionsCount() == 0 || vw->connector1()->connectionsCount() == 0) { ratsToDelete.append(vw); } visited << vw->connector0() << vw->connector1(); continue; } QList connectorItems; connectorItems.append(connectorItem); ConnectorItem::collectEqualPotential(connectorItems, true, ViewGeometry::RatsnestFlag); visited.append(connectorItems); //if (this->viewID() == ViewLayer::SchematicView) { // DebugDialog::debug("________________________"); // foreach (ConnectorItem * ci, connectorItems) ci->debugInfo("cep"); //} bool doRatsnest = manual || checkUpdateRatsnest(connectorItems); if (!doRatsnest && connectorItems.count() <= 1) continue; QList partConnectorItems; ConnectorItem::collectParts(connectorItems, partConnectorItems, includeSymbols(), ViewLayer::NewTopAndBottom); if (partConnectorItems.count() < 1) continue; if (!doRatsnest && partConnectorItems.count() <= 1) continue; //if (this->viewID() == ViewLayer::SchematicView) { // DebugDialog::debug("________________________"); // foreach (ConnectorItem * pci, partConnectorItems) { // pci->debugInfo("pc 1"); // } //} for (int i = partConnectorItems.count() - 1; i >= 0; i--) { ConnectorItem * ci = partConnectorItems[i]; if (!ci->attachedTo()->isEverVisible()) { partConnectorItems.removeAt(i); } } if (partConnectorItems.count() < 1) continue; if (doRatsnest) { ratnestsToUpdate.append(partConnectorItems); } if (partConnectorItems.count() <= 1) continue; //if (this->viewID() == ViewLayer::SchematicView) { // DebugDialog::debug("________________________"); // foreach (ConnectorItem * pci, partConnectorItems) { // pci->debugInfo("pc 2"); // } //} GraphUtils::scoreOneNet(partConnectorItems, this->getTraceFlag(), routingStatus); } routingStatus.m_jumperItemCount /= 4; // since we counted each connector twice on two layers (4 connectors per jumper item) // can't do this in the above loop since VirtualWires and ConnectorItems are added and deleted foreach (QList partConnectorItems, ratnestsToUpdate) { //partConnectorItems.at(0)->debugInfo("display ratsnest"); //if (this->viewID() == ViewLayer::SchematicView) { // DebugDialog::debug("________________________"); // foreach (ConnectorItem * pci, partConnectorItems) { // pci->debugInfo("pc 3"); // } //} partConnectorItems.at(0)->displayRatsnest(partConnectorItems, this->getTraceFlag()); } foreach(QPointer vw, ratsToDelete) { if (vw != NULL) { //vw->debugInfo("removing rat 2"); vw->scene()->removeItem(vw); delete vw; } } m_ratsnestUpdateConnect.clear(); m_ratsnestUpdateDisconnect.clear(); /* // uncomment for live drc CMRouter cmRouter(this); QString message; bool result = cmRouter.drc(message); */ } void SketchWidget::ensureLayerVisible(ViewLayer::ViewLayerID viewLayerID) { ViewLayer * viewLayer = m_viewLayers.value(viewLayerID, NULL); if (viewLayer == NULL) return; if (!viewLayer->visible()) { setLayerVisible(viewLayer, true, true); } } void SketchWidget::clearDragWireTempCommand() { if (m_tempDragWireCommand) { delete m_tempDragWireCommand; m_tempDragWireCommand = NULL; } } void SketchWidget::autoScrollTimeout() { //DebugDialog::debug(QString("scrolling dx:%1 dy:%2").arg(m_autoScrollX).arg(m_autoScrollY) ); if (m_autoScrollX == 0 && m_autoScrollY == 0 ) return; if (m_autoScrollX != 0) { QScrollBar * h = horizontalScrollBar(); h->setValue(m_autoScrollX + h->value()); } if (m_autoScrollY != 0) { QScrollBar * v = verticalScrollBar(); v->setValue(m_autoScrollY + v->value()); } //DebugDialog::debug(QString("autoscrolling %1 %2").arg(m_autoScrollX).arg(m_autoScrollX)); } void SketchWidget::dragAutoScrollTimeout() { autoScrollTimeout(); dragMoveHighlightConnector(mapFromGlobal(m_globalPos)); } void SketchWidget::moveAutoScrollTimeout() { autoScrollTimeout(); moveItems(m_globalPos, true, m_rubberBandLegWasEnabled); } const QString &SketchWidget::selectedModuleID() { if(m_lastPaletteItemSelected) { return m_lastPaletteItemSelected->moduleID(); } foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase) return itemBase->moduleID(); } return ___emptyString___; } BaseCommand::CrossViewType SketchWidget::wireSplitCrossView() { return BaseCommand::CrossView; } bool SketchWidget::canDeleteItem(QGraphicsItem * item, int count) { Q_UNUSED(count); ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) return false; if (itemBase->moveLock()) return false; ItemBase * chief = itemBase->layerKinChief(); if (chief == NULL) return false; if (chief->moveLock()) return false; return true; } bool SketchWidget::canCopyItem(QGraphicsItem * item, int count) { Q_UNUSED(count); ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) return false; ItemBase * chief = itemBase->layerKinChief(); if (chief == NULL) return false; return true; } bool SketchWidget::canChainMultiple() { return false; } bool SketchWidget::canChainWire(Wire * wire) { if (!this->m_chainDrag) return false; if (wire == NULL) return false; return true; } bool SketchWidget::canDragWire(Wire * wire) { if (wire == NULL) return false; return true; } bool SketchWidget::canCreateWire(Wire * dragWire, ConnectorItem * from, ConnectorItem * to) { Q_UNUSED(dragWire); Q_UNUSED(from); Q_UNUSED(to); return true; } /* bool SketchWidget::modifyNewWireConnections(Wire * dragWire, ConnectorItem * fromOnWire, ConnectorItem * from, ConnectorItem * to, QUndoCommand * parentCommand) { Q_UNUSED(dragWire); Q_UNUSED(fromOnWire); Q_UNUSED(from); Q_UNUSED(to); Q_UNUSED(parentCommand); return false; } */ void SketchWidget::setupAutoscroll(bool moving) { m_autoScrollX = m_autoScrollY = 0; m_autoScrollThreshold = (moving) ? MoveAutoScrollThreshold : DragAutoScrollThreshold; m_autoScrollCount = 0; connect(&m_autoScrollTimer, SIGNAL(timeout()), this, moving ? SLOT(moveAutoScrollTimeout()) : SLOT(dragAutoScrollTimeout())); //DebugDialog::debug("set up autoscroll"); } void SketchWidget::turnOffAutoscroll() { m_autoScrollTimer.stop(); disconnect(&m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(moveAutoScrollTimeout())); disconnect(&m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(dragAutoScrollTimeout())); //DebugDialog::debug("turn off autoscroll"); } bool SketchWidget::checkAutoscroll(QPoint globalPos) { QRect r = rect(); QPoint q = mapFromGlobal(globalPos); if (verticalScrollBar()->isVisible()) { r.setWidth(width() - verticalScrollBar()->width()); } if (horizontalScrollBar()->isVisible()) { r.setHeight(height() - horizontalScrollBar()->height()); } if (!r.contains(q)) { m_autoScrollX = m_autoScrollY = 0; if (m_autoScrollCount < m_autoScrollThreshold) { m_autoScrollCount = 0; } return false; } //DebugDialog::debug(QString("check autoscroll %1, %2 %3").arg(QTime::currentTime().msec()).arg(q.x()).arg(q.y()) ); r.adjust(16,16,-16,-16); // these should be set someplace bool autoScroll = !r.contains(q); if (autoScroll) { if (++m_autoScrollCount < m_autoScrollThreshold) { m_autoScrollX = m_autoScrollY = 0; //DebugDialog::debug("in autoscrollThreshold"); return true; } if (m_clearSceneRect) { scene()->setSceneRect(QRectF()); m_clearSceneRect = true; } int dx = 0, dy = 0; if (q.x() > r.right()) { dx = q.x() - r.right(); } else if (q.x() < r.left()) { dx = q.x() - r.left(); } if (q.y() > r.bottom()) { dy = q.y() - r.bottom(); } else if (q.y() < r.top()) { dy = q.y() - r.top(); } int div = 3; if (dx != 0) { m_autoScrollX = (dx + ((dx > 0) ? div : -div)) / (div + 1); // ((m_autoScrollX > 0) ? 1 : -1) } if (dy != 0) { m_autoScrollY = (dy + ((dy > 0) ? div : -div)) / (div + 1); // ((m_autoScrollY > 0) ? 1 : -1) } if (!m_autoScrollTimer.isActive()) { //DebugDialog::debug("starting autoscroll timer"); m_autoScrollTimer.start(10); } } else { m_autoScrollX = m_autoScrollY = 0; if (m_autoScrollCount < m_autoScrollThreshold) { m_autoScrollCount = 0; } } //DebugDialog::debug(QString("autoscroll %1 %2").arg(m_autoScrollX).arg(m_autoScrollY) ); return true; } void SketchWidget::setWireVisible(Wire * wire) { Q_UNUSED(wire); } void SketchWidget::forwardRoutingStatus(const RoutingStatus & routingStatus) { emit routingStatusSignal(this, routingStatus); } bool SketchWidget::matchesLayer(ModelPart * modelPart) { LayerList viewLayers = modelPart->viewLayers(m_viewID); foreach (ViewLayer* viewLayer, m_viewLayers) { if (viewLayers.contains(viewLayer->viewLayerID())) return true; } return false; } const QString & SketchWidget::viewName() { return m_viewName; } void SketchWidget::setNoteText(long itemID, const QString & newText) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; Note * note = qobject_cast(itemBase); if (note == NULL) return; note->setText(newText, false); } void SketchWidget::incInstanceTitle(long itemID) { ItemBase * itemBase = findItem(itemID); if (itemBase) { itemBase->ensureUniqueTitle(itemBase->instanceTitle(), true); } emit updatePartLabelInstanceTitleSignal(itemID); } void SketchWidget::updatePartLabelInstanceTitleSlot(long itemID) { ItemBase * itemBase = findItem(itemID); if (itemBase) { itemBase->updatePartLabelInstanceTitle(); } } void SketchWidget::setInstanceTitle(long itemID, const QString & oldText, const QString & newText, bool isUndoable, bool doEmit) { // isUndoable is true when setInstanceTitle is called from the infoview ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; if (!isUndoable) { itemBase->setInstanceTitle(newText, false); if (doEmit && currentlyInfoviewed(itemBase)) { // TODO: just change the affected item in the info view viewItemInfo(itemBase); } if (doEmit) { emit setInstanceTitleSignal(itemID, oldText, newText, isUndoable, false); } } else { if (oldText.compare(newText) == 0) return; /* // this doesn't work correctly--undo somehow gets messed up LogoItem * logoItem = qobject_cast(itemBase); if (logoItem && logoItem->hasLogo()) { // instead of changing part label, change logo if (logoItem->logo().compare(newText) == 0) return; setProp(logoItem, "logo", tr("logo"), logoItem->logo(), newText, true); return; } */ partLabelChangedAux(itemBase, oldText, newText); } } void SketchWidget::showPartLabel(long itemID, bool showIt) { ItemBase * itemBase = findItem(itemID); if (itemBase != NULL) { itemBase->showPartLabel(showIt, m_viewLayers.value(getLabelViewLayerID(itemBase))); } } void SketchWidget::hidePartLabel(ItemBase * item) { QList itemBases; itemBases.append(item); showPartLabelsAux(false, itemBases); } void SketchWidget::collectParts(QList & partList) { // using PaletteItem instead of ItemBase ensures layerKinChiefs only foreach (QGraphicsItem * item, scene()->items()) { PaletteItem * pitem = dynamic_cast(item); if (pitem == NULL) continue; if (pitem->itemType() == ModelPart::Symbol) continue; partList.append(pitem); } } void SketchWidget::movePartLabel(long itemID, QPointF newPos, QPointF newOffset) { ItemBase * item = findItem(itemID); if (item == NULL) return; item->movePartLabel(newPos, newOffset); } void SketchWidget::setCurrent(bool current) { m_current = current; } void SketchWidget::partLabelMoved(ItemBase * itemBase, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset) { MoveLabelCommand * command = new MoveLabelCommand(this, itemBase->id(), oldPos, oldOffset, newPos, newOffset, NULL); command->setText(tr("Move label '%1'").arg(itemBase->title())); m_undoStack->push(command); } void SketchWidget::rotateFlipPartLabel(ItemBase * itemBase, double degrees, Qt::Orientations flipDirection) { RotateFlipLabelCommand * command = new RotateFlipLabelCommand(this, itemBase->id(), degrees, flipDirection, NULL); command->setText(tr("%1 label '%2'").arg((degrees != 0) ? tr("Rotate") : tr("Flip")).arg(itemBase->title())); m_undoStack->push(command); } void SketchWidget::rotateFlipPartLabel(long itemID, double degrees, Qt::Orientations flipDirection) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; itemBase->doRotateFlipPartLabel(degrees, flipDirection); } void SketchWidget::showPartLabels(bool show) { QList itemBases; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item); if (itemBase == NULL) continue; if (itemBase->hasPartLabel()) { itemBases.append(itemBase); } } if (itemBases.count() <= 0) return; showPartLabelsAux(show, itemBases); } void SketchWidget::showPartLabelsAux(bool show, QList & itemBases) { ShowLabelCommand * showLabelCommand = new ShowLabelCommand(this, NULL); QString text; if (show) { text = tr("show %n part label(s)", "", itemBases.count()); } else { text = tr("hide %n part label(s)", "", itemBases.count()); } showLabelCommand->setText(text); foreach (ItemBase * itemBase, itemBases) { showLabelCommand->add(itemBase->id(), itemBase->isPartLabelVisible(), show); } m_undoStack->push(showLabelCommand); } void SketchWidget::noteSizeChanged(ItemBase * itemBase, const QSizeF & oldSize, const QSizeF & newSize) { ResizeNoteCommand * command = new ResizeNoteCommand(this, itemBase->id(), oldSize, newSize, NULL); command->setText(tr("Resize Note")); m_undoStack->push(command); clearHoldingSelectItem(); } void SketchWidget::resizeNote(long itemID, const QSizeF & size) { Note * note = qobject_cast(findItem(itemID)); if (note == NULL) return; note->setSize(size); } QString SketchWidget::renderToSVG(RenderThing & renderThing, QGraphicsItem * board, const LayerList & layers) { renderThing.board = board; if (board) { renderThing.offsetRect = board->sceneBoundingRect(); } return renderToSVG(renderThing, layers); } QString SketchWidget::renderToSVG(RenderThing & renderThing, const LayerList & layers) { QList itemsAndLabels; QRectF itemsBoundingRect; QList items; if (renderThing.selectedItems) { items = scene()->selectedItems(); } else if (renderThing.board == NULL) { items = scene()->items(); } else { items = scene()->collidingItems(renderThing.board); items << renderThing.board; } foreach (QGraphicsItem * item, items) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->hidden() || itemBase->layerHidden()) continue; if (!renderThing.renderBlocker) { Pad * pad = qobject_cast(itemBase); if (pad != NULL && pad->copperBlocker()) { continue; } } if (itemBase == itemBase->layerKinChief() && itemBase->isPartLabelVisible()) { if (layers.contains(itemBase->partLabelViewLayerID())) { itemsAndLabels.append(itemBase->partLabel()); itemsBoundingRect |= itemBase->partLabelSceneBoundingRect(); } } if (!itemBase->isVisible()) continue; if (!layers.contains(itemBase->viewLayerID())) continue; itemsAndLabels.append(itemBase); itemsBoundingRect |= item->sceneBoundingRect(); } renderThing.itemsBoundingRect = itemsBoundingRect; return renderToSVG(renderThing, itemsAndLabels); } QString translateSVG(QString & svg, QPointF loc, double dpi, double printerScale) { loc.setX(loc.x() * dpi / printerScale); loc.setY(loc.y() * dpi / printerScale); if (loc.x() != 0 || loc.y() != 0) { svg = QString("%3") .arg(loc.x()) .arg(loc.y()) .arg(svg); } return svg; } QString SketchWidget::renderToSVG(RenderThing & renderThing, QList & itemsAndLabels) { renderThing.empty = true; double width = renderThing.itemsBoundingRect.width(); double height = renderThing.itemsBoundingRect.height(); QPointF offset = renderThing.itemsBoundingRect.topLeft(); if (!renderThing.offsetRect.isEmpty()) { offset = renderThing.offsetRect.topLeft(); width = renderThing.offsetRect.width(); height = renderThing.offsetRect.height(); } renderThing.imageRect.setRect(offset.x(), offset.y(), width, height); QString outputSVG = TextUtils::makeSVGHeader(renderThing.printerScale, renderThing.dpi, width, height); QHash svgHash; // put them in z order qSort(itemsAndLabels.begin(), itemsAndLabels.end(), zLessThan); QList gotLabel; foreach (QGraphicsItem * item, itemsAndLabels) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) { PartLabel * partLabel = dynamic_cast(item); if (partLabel == NULL) continue; QString labelSvg = partLabel->owner()->makePartLabelSvg(renderThing.blackOnly, renderThing.dpi, renderThing.printerScale); if (labelSvg.isEmpty()) continue; labelSvg = translateSVG(labelSvg, partLabel->owner()->partLabelScenePos() - offset, renderThing.dpi, renderThing.printerScale); labelSvg = QString("%2").arg(partLabel->owner()->id()).arg(labelSvg); renderThing.empty = false; outputSVG.append(labelSvg); continue; } if (itemBase->itemType() != ModelPart::Wire) { double factor; QString itemSvg = itemBase->retrieveSvg(itemBase->viewLayerID(), svgHash, renderThing.blackOnly, renderThing.dpi, factor); if (itemSvg.isEmpty()) continue; TextUtils::fixMuch(itemSvg, false); QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (doc.setContent(itemSvg, &errorStr, &errorLine, &errorColumn)) { bool changed = false; if (renderThing.renderBlocker) { Pad * pad = qobject_cast(itemBase); if (pad && pad->copperBlocker()) { QDomNodeList nodeList = doc.documentElement().elementsByTagName("rect"); for (int n = 0; n < nodeList.count(); n++) { QDomElement element = nodeList.at(n).toElement(); element.setAttribute("fill-opacity", 1); changed = true; } } } foreach (ConnectorItem * ci, itemBase->cachedConnectorItems()) { SvgIdLayer * svgIdLayer = ci->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); if (renderThing.hideTerminalPoints && !svgIdLayer->m_terminalId.isEmpty()) { // these tend to be degenerate shapes and can cause trouble at gerber export time if (hideTerminalID(doc, svgIdLayer->m_terminalId)) changed = true; } if (ensureStrokeWidth(doc, svgIdLayer->m_svgId, factor)) changed = true; if (!ci->hasRubberBandLeg()) continue; // at the moment, the legs don't get a partID, but since there are no legs in PCB view, we don't care outputSVG.append(ci->makeLegSvg(offset, renderThing.dpi, renderThing.printerScale, renderThing.blackOnly)); } if (changed) { itemSvg = doc.toString(0); } } QTransform t = itemBase->transform(); itemSvg = TextUtils::svgTransform(itemSvg, t, false, QString()); itemSvg = translateSVG(itemSvg, itemBase->scenePos() - offset, renderThing.dpi, renderThing.printerScale); itemSvg = QString("%2").arg(itemBase->id()).arg(itemSvg); outputSVG.append(itemSvg); renderThing.empty = false; /* // TODO: deal with rotations and flips QString shifted = splitter->shift(loc.x(), loc.y(), xmlName); outputSVG.append(shifted); empty = false; splitter->shift(-loc.x(), -loc.y(), xmlName); */ } else { Wire * wire = qobject_cast(itemBase); if (wire == NULL) continue; //if (wire->getTrace()) { // DebugDialog::debug(QString("trace %1 %2,%3 %4,%5") // .arg(wire->id()) // .arg(wire->line().p1().x()) // .arg(wire->line().p1().y()) // .arg(wire->line().p2().x()) // .arg(wire->line().p2().y()) // ); //} QString wireSvg = makeWireSVG(wire, offset, renderThing.dpi, renderThing.printerScale, renderThing.blackOnly); wireSvg = QString("%2").arg(wire->id()).arg(wireSvg); outputSVG.append(wireSvg); renderThing.empty = false; } extraRenderSvgStep(itemBase, offset, renderThing.dpi, renderThing.printerScale, outputSVG); } outputSVG += ""; return outputSVG; } void SketchWidget::extraRenderSvgStep(ItemBase * itemBase, QPointF offset, double dpi, double printerScale, QString & outputSvg) { Q_UNUSED(itemBase); Q_UNUSED(offset); Q_UNUSED(dpi); Q_UNUSED(printerScale); Q_UNUSED(outputSvg); } QString SketchWidget::makeWireSVG(Wire * wire, QPointF offset, double dpi, double printerScale, bool blackOnly) { QString shadow; bool dashed = false; if (wire->hasShadow()) { shadow = makeWireSVGAux(wire, wire->shadowWidth(), wire->shadowHexString(), offset, dpi, printerScale, blackOnly, false); if (wire->banded()) { dashed = true; shadow += makeWireSVGAux(wire, wire->width(), "white", offset, dpi, printerScale, blackOnly, false); } } return shadow + makeWireSVGAux(wire, wire->width(), wire->hexString(), offset, dpi, printerScale, blackOnly, dashed); } QString SketchWidget::makeWireSVGAux(Wire * wire, double width, const QString & color, QPointF offset, double dpi, double printerScale, bool blackOnly, bool dashed) { if (wire->isCurved()) { QPolygonF poly = wire->sceneCurve(offset); return TextUtils::makeCubicBezierSVG(poly, width, color, dpi, printerScale, blackOnly, dashed, Wire::TheDash); } else { QLineF line = wire->getPaintLine(); QPointF p1 = wire->scenePos() + line.p1() - offset; QPointF p2 = wire->scenePos() + line.p2() - offset; return TextUtils::makeLineSVG(p1, p2, width, color, dpi, printerScale, blackOnly, dashed, Wire::TheDash); } } void SketchWidget::drawBackground( QPainter * painter, const QRectF & rect ) { if (!rect.isValid()) { return; } //DebugDialog::debug(QString("draw background %1").arg(viewName())); InfoGraphicsView::drawBackground(painter, rect); // from: http://www.qtcentre.org/threads/27364-Trying-to-draw-a-grid-on-a-QGraphicsScene-View InfoGraphicsView::drawForeground(painter, rect); // always draw the logo in the same place in the window // no matter how the view is zoomed or scrolled static QPixmap * bgPixmap = NULL; if (bgPixmap == NULL) { bgPixmap = new QPixmap(":resources/images/fritzing_logo_background.png"); } if (bgPixmap) { QPointF p = painter->viewport().bottomLeft(); int hOffset = 0; if (horizontalScrollBar()->isVisible()) { hOffset = horizontalScrollBar()->height(); } p += QPointF(25, hOffset - 25 - bgPixmap->height()); painter->save(); painter->setWindow(painter->viewport()); painter->setTransform(QTransform()); painter->drawPixmap(p,*bgPixmap); painter->restore(); } if (m_showGrid) { double gridSize = m_gridSizeInches * GraphicsUtils::SVGDPI; int intGridSize = int(gridSize * 10000); if (intGridSize > 0) { double left = int(rect.left() * 10000) - (int(rect.left() * 10000) % intGridSize); left /= 10000; double top = int(rect.top() * 10000) - (int(rect.top() * 10000) % intGridSize); top /= 10000; QVarLengthArray linesX; for (double x = left; x < rect.right(); x += gridSize) { linesX.append(QLineF(x, rect.top(), x, rect.bottom())); } QVarLengthArray linesY; for (double y = top; y < rect.bottom(); y += gridSize) { linesY.append(QLineF(rect.left(), y, rect.right(), y)); } //DebugDialog::debug(QString("lines %1 %2").arg(linesX.count()).arg(linesY.count())); QPen pen; pen.setColor(m_gridColor); pen.setWidth(0); pen.setCosmetic(true); //pen.setStyle(Qt::DotLine); //QVector dashes; // removed dash pattern at forum suggestion: http://fritzing.org/forum/thread/855 //dashes << 1 << 1; //pen.setDashPattern(dashes); painter->save(); painter->setPen(pen); painter->drawLines(linesX.data(), linesX.size()); painter->drawLines(linesY.data(), linesY.size()); painter->restore(); } } } /* QPoint SketchWidget::calcFixedToCenterItemOffset(const QRect & viewPortRect, const QSizeF & helpSize) { QPoint p((int) ((viewPortRect.width() - helpSize.width()) / 2.0), (int) ((viewPortRect.height() - helpSize.height()) / 2.0)); return p; } */ void SketchWidget::pushCommand(QUndoCommand * command, QObject * thing) { if (m_undoStack) { CommandProgress * commandProgress = BaseCommand::initProgress(); connect(commandProgress, SIGNAL(incRedo()), thing, SLOT(incCommandProgress())); m_undoStack->push(command); BaseCommand::clearProgress(); } } bool SketchWidget::spaceBarIsPressed() { return m_spaceBarIsPressed || m_middleMouseIsPressed; } ViewLayer::ViewLayerID SketchWidget::defaultConnectorLayer(ViewLayer::ViewID viewId) { switch(viewId) { case ViewLayer::IconView: return ViewLayer::Icon; case ViewLayer::BreadboardView: return ViewLayer::Breadboard; case ViewLayer::SchematicView: return ViewLayer::Schematic; case ViewLayer::PCBView: return ViewLayer::Copper0; default: return ViewLayer::UnknownLayer; } } bool SketchWidget::swappedGender(ConnectorItem * connectorItem, Connector * newConnector) { return (connectorItem->connectorType() != newConnector->connectorType()); } void SketchWidget::setLastPaletteItemSelected(PaletteItem * paletteItem) { m_lastPaletteItemSelected = paletteItem; //DebugDialog::debug(QString("m_lastPaletteItemSelected:%1 %2").arg(paletteItem == NULL ? "NULL" : paletteItem->instanceTitle()).arg(m_viewID)); } void SketchWidget::setLastPaletteItemSelectedIf(ItemBase * itemBase) { PaletteItem * paletteItem = qobject_cast(itemBase); if (paletteItem == NULL) return; setLastPaletteItemSelected(paletteItem); } void SketchWidget::setResistance(QString resistance, QString pinSpacing) { PaletteItem * item = getSelectedPart(); if (item == NULL) return; ModelPart * modelPart = item->modelPart(); if (!modelPart->moduleID().endsWith(ModuleIDNames::ResistorModuleIDName)) return; Resistor * resistor = qobject_cast(item); if (resistor == NULL) return; if (resistance.isEmpty()) { resistance = resistor->resistance(); } if (pinSpacing.isEmpty()) { pinSpacing = resistor->pinSpacing(); } SetResistanceCommand * cmd = new SetResistanceCommand(this, item->id(), resistor->resistance(), resistance, resistor->pinSpacing(), pinSpacing, NULL); cmd->setText(tr("Change Resistance from %1 to %2").arg(resistor->resistance()).arg(resistance)); m_undoStack->waitPush(cmd, PropChangeDelay); } void SketchWidget::setResistance(long itemID, QString resistance, QString pinSpacing, bool doEmit) { ItemBase * item = findItem(itemID); if (item == NULL) return; Resistor * ritem = qobject_cast(item); if (ritem == NULL) return; ritem->setResistance(resistance, pinSpacing, false); viewItemInfo(item); if (doEmit) { emit setResistanceSignal(itemID, resistance, pinSpacing, false); } } void SketchWidget::setProp(ItemBase * item, const QString & prop, const QString & trProp, const QString & oldValue, const QString & newValue, bool redraw) { if (oldValue.isEmpty() && newValue.isEmpty()) return; SetPropCommand * cmd = new SetPropCommand(this, item->id(), prop, oldValue, newValue, redraw, NULL); cmd->setText(tr("Change %1 from %2 to %3").arg(trProp).arg(oldValue).arg(newValue)); // unhook triggered action from originating widget event m_undoStack->waitPush(cmd, PropChangeDelay); } void SketchWidget::setHoleSize(ItemBase * item, const QString & prop, const QString & trProp, const QString & oldValue, const QString & newValue, QRectF & oldRect, QRectF & newRect, bool redraw) { if (oldValue.isEmpty() && newValue.isEmpty()) return; QUndoCommand * parentCommand = new QUndoCommand(tr("Change %1 from %2 to %3").arg(trProp).arg(oldValue).arg(newValue)); new SetPropCommand(this, item->id(), prop, oldValue, newValue, redraw, parentCommand); item->saveGeometry(); ViewGeometry vg(item->getViewGeometry()); QPointF p(vg.loc().x() + (oldRect.width() / 2) - (newRect.width() / 2), vg.loc().y() + (oldRect.height() / 2) - (newRect.height() / 2)); vg.setLoc(p); new MoveItemCommand(this, item->id(), item->getViewGeometry(), vg, false, parentCommand); //DebugDialog::debug("set hole", oldRect); //DebugDialog::debug(" ", newRect); //DebugDialog::debug(" ", item->getViewGeometry().loc()); //DebugDialog::debug(" ", p); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::setProp(long itemID, const QString & prop, const QString & value, bool redraw, bool doEmit) { ItemBase * item = findItem(itemID); if (item == NULL) return; item->setProp(prop, value); if (redraw) { viewItemInfo(item); } if (doEmit) { emit setPropSignal(itemID, prop, value, false, false); } } // called from ResizeBoardCommand ItemBase * SketchWidget::resizeBoard(long itemID, double mmW, double mmH) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return NULL; bool resized = false; switch (itemBase->itemType()) { case ModelPart::ResizableBoard: qobject_cast(itemBase)->resizeMM(mmW, mmH, m_viewLayers); resized = true; break; case ModelPart::Logo: qobject_cast(itemBase)->resizeMM(mmW, mmH, m_viewLayers); resized = true; break; case ModelPart::Ruler: qobject_cast(itemBase)->resizeMM(mmW, mmH, m_viewLayers); resized = true; break; } if (!resized) { Pad * pad = qobject_cast(itemBase); if (pad) { pad->resizeMM(mmW, mmH, m_viewLayers); resized = true; } } if (!resized) { SchematicFrame * schematicFrame = qobject_cast(itemBase); if (schematicFrame) { schematicFrame->resizeMM(mmW, mmH, m_viewLayers); resized = true; } } if (resized) { emit resizedSignal(itemBase); } return itemBase; } void SketchWidget::resizeBoard(double mmW, double mmH, bool doEmit) { Q_UNUSED(doEmit); PaletteItem * item = getSelectedPart(); if (item == NULL) { return InfoGraphicsView::resizeBoard(mmW, mmH, doEmit); } switch (item->itemType()) { case ModelPart::Ruler: break; case ModelPart::Logo: resizeWithHandle(item, mmW, mmH); default: return; } QString orig = item->prop("width"); QString temp = orig; temp.chop(2); double origw = temp.toDouble(); double origh = orig.endsWith("cm") ? 0 : 1; QUndoCommand * parentCommand = new QUndoCommand(tr("Resize ruler to %1 %2").arg(mmW).arg((mmH == 0) ? "cm" : "in")); new ResizeBoardCommand(this, item->id(), origw, origh, mmW, mmH, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::resizeWithHandle(ItemBase * itemBase, double mmW, double mmH) { double origw = itemBase->modelPart()->localProp("width").toDouble(); double origh = itemBase->modelPart()->localProp("height").toDouble(); if (mmH == 0 || mmW == 0) { dynamic_cast(itemBase)->setInitialSize(); double w = itemBase->modelPart()->localProp("width").toDouble(); double h = itemBase->modelPart()->localProp("height").toDouble(); if (origw == w && origh == h) { // no change return; } viewItemInfo(itemBase); mmW = w; mmH = h; } QUndoCommand * parentCommand = new QUndoCommand(tr("Resize board to %1 %2").arg(mmW).arg(mmH)); rememberSticky(itemBase, parentCommand); new ResizeBoardCommand(this, itemBase->id(), origw, origh, mmW, mmH, parentCommand); new CheckStickyCommand(this, BaseCommand::SingleView, itemBase->id(), true, CheckStickyCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::addBendpoint(ItemBase * lastHoverEnterItem, ConnectorItem * lastHoverEnterConnectorItem, QPointF lastLocation) { if (lastHoverEnterConnectorItem) { Wire * wire = qobject_cast(lastHoverEnterConnectorItem->attachedTo()); if (wire != NULL) { wireJoinSlot(wire, lastHoverEnterConnectorItem); } } else if (lastHoverEnterItem) { Wire * wire = qobject_cast(lastHoverEnterItem); if (wire != NULL) { wireSplitSlot(wire, lastLocation, wire->pos(), wire->line()); } } } void SketchWidget::flattenCurve(ItemBase * lastHoverEnterItem, ConnectorItem * lastHoverEnterConnectorItem, QPointF lastLocation) { Q_UNUSED(lastLocation); Wire * wire = NULL; if (lastHoverEnterConnectorItem) { wire = qobject_cast(lastHoverEnterConnectorItem->attachedTo()); } if (wire == NULL && lastHoverEnterItem) { wire = qobject_cast(lastHoverEnterItem); } if (wire != NULL) { wireChangedCurveSlot(wire, wire->curve(), NULL, true); } } ConnectorItem * SketchWidget::lastHoverEnterConnectorItem() { return m_lastHoverEnterConnectorItem; } ItemBase * SketchWidget::lastHoverEnterItem() { return m_lastHoverEnterItem; } LayerHash & SketchWidget::viewLayers() { return m_viewLayers; } void SketchWidget::setClipEnds(ClipableWire * vw, bool) { vw->setClipEnds(false); } void SketchWidget::createTrace(Wire * wire, bool useLastWireColor) { QString commandString = tr("Create wire from Ratsnest"); createTrace(wire, commandString, getTraceFlag(), useLastWireColor); } void SketchWidget::createTrace(Wire * fromWire, const QString & commandString, ViewGeometry::WireFlag flag, bool useLastWireColor) { QList done; QUndoCommand * parentCommand = new QUndoCommand(commandString); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); bool gotOne = false; if (fromWire == NULL) { foreach (QGraphicsItem * item, scene()->selectedItems()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (done.contains(wire)) continue; gotOne = createOneTrace(wire, flag, false, done, useLastWireColor, parentCommand); } } else { gotOne = createOneTrace(fromWire, flag, false, done, useLastWireColor, parentCommand); } if (!gotOne) { delete parentCommand; return; } new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->push(parentCommand); } bool SketchWidget::createOneTrace(Wire * wire, ViewGeometry::WireFlag flag, bool allowAny, QList & done, bool useLastWireColor, QUndoCommand * parentCommand) { QList ends; Wire * trace = NULL; if (wire->getRatsnest()) { trace = wire->findTraced(getTraceFlag(), ends); } else if (wire->isTraceType(getTraceFlag())) { trace = wire; } else if (!allowAny) { // not eligible return false; } else { trace = wire->findTraced(getTraceFlag(), ends); } if (trace && trace->hasFlag(flag)) { return false; } if (trace != NULL) { removeWire(trace, ends, done, parentCommand); } QString colorString = traceColor(createWireViewLayerPlacement(ends[0], ends[1])); if (useLastWireColor && !this->m_lastColorSelected.isEmpty()) { colorString = m_lastColorSelected; } long newID = createWire(ends[0], ends[1], flag, false, BaseCommand::CrossView, parentCommand); // TODO: is this opacity constant stored someplace new WireColorChangeCommand(this, newID, colorString, colorString, 1.0, 1.0, parentCommand); new WireWidthChangeCommand(this, newID, getTraceWidth(), getTraceWidth(), parentCommand); return true; } void SketchWidget::selectAllWires(ViewGeometry::WireFlag flag) { QList items = scene()->items(); selectAllWiresFrom(flag, items); } void SketchWidget::selectAllWiresFrom(ViewGeometry::WireFlag flag, QList & items) { QList wires; foreach (QGraphicsItem * item, items) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (wire->hasFlag(flag)) { if (wire->parentItem() != NULL) { // skip module wires continue; } wires.append(wire); } } if (wires.count() <= 0) { // TODO: tell user? } QString wireName; if (flag == getTraceFlag()) { wireName = QObject::tr("Trace wires"); } else if (flag == ViewGeometry::RatsnestFlag) { wireName = QObject::tr("Ratsnest wires"); } QUndoCommand * parentCommand = new QUndoCommand(QObject::tr("Select all %1").arg(wireName)); stackSelectionState(false, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); foreach (Wire * wire, wires) { selectItemCommand->addRedo(wire->id()); } scene()->clearSelection(); m_undoStack->push(parentCommand); } void SketchWidget::tidyWires() { } void SketchWidget::updateConnectors() { // update issue with 4.5.0? QList visited; foreach (QGraphicsItem* item, scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; connectorItem->restoreColor(visited); } } const QString & SketchWidget::getShortName() { return m_shortName; } void SketchWidget::getBendpointWidths(Wire * wire, double width, double & bendpointWidth, double & bendpoint2Width, bool & negativeOffsetRect) { Q_UNUSED(wire); Q_UNUSED(width); bendpoint2Width = bendpointWidth = -1; negativeOffsetRect = true; } QColor SketchWidget::standardBackground() { return RatsnestColors::backgroundColor(m_viewID); } void SketchWidget::initBackgroundColor() { setBackground(standardBackground()); QSettings settings; QString colorName = settings.value(QString("%1BackgroundColor").arg(getShortName())).toString(); if (!colorName.isEmpty()) { QColor color; color.setNamedColor(colorName); setBackground(color); } m_curvyWires = false; QString curvy = settings.value(QString("%1CurvyWires").arg(getShortName())).toString(); if (!curvy.isEmpty()) { m_curvyWires = (curvy.compare("1") == 0); } } bool SketchWidget::includeSymbols() { return false; } void SketchWidget::disconnectAll() { QSet itemBases; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; itemBases.insert(itemBase); } QList connectorItems; foreach (ItemBase * itemBase, itemBases) { ConnectorItem * fromConnectorItem = itemBase->rightClickedConnector(); if (fromConnectorItem == NULL) continue; if (fromConnectorItem->connectedToWires()) { connectorItems.append(fromConnectorItem); } } if (connectorItems.count() <= 0) return; QString string; if (itemBases.count() == 1) { ItemBase * firstItem = *(itemBases.begin()); string = tr("Disconnect all wires from %1").arg(firstItem->title()); } else { string = tr("Disconnect all wires from %1 items").arg(QString::number(itemBases.count())); } QUndoCommand * parentCommand = new QUndoCommand(string); stackSelectionState(false, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); QHash itemsToDelete; disconnectAllSlot(connectorItems, itemsToDelete, parentCommand); emit disconnectAllSignal(connectorItems, itemsToDelete, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); foreach (ItemBase * item, itemsToDelete.keys()) { itemsToDelete.value(item)->makeDeleteItemCommand(item, BaseCommand::CrossView, parentCommand); } m_undoStack->push(parentCommand); } void SketchWidget::disconnectAllSlot(QList connectorItems, QHash & itemsToDelete, QUndoCommand * parentCommand) { // (jc 2011 Aug 16): this code is not hooked up and my last recollection is that it wasn't working return; QList myConnectorItems; foreach (ConnectorItem * ci, connectorItems) { ItemBase * itemBase = findItem(ci->attachedToID()); if (itemBase == NULL) continue; ConnectorItem * fromConnectorItem = findConnectorItem(itemBase, ci->connectorSharedID(), ViewLayer::NewTop); if (fromConnectorItem != NULL) { myConnectorItems.append(fromConnectorItem); } fromConnectorItem = findConnectorItem(itemBase, ci->connectorSharedID(), ViewLayer::NewBottom); if (fromConnectorItem != NULL) { myConnectorItems.append(fromConnectorItem); } } QSet deletedItems; foreach (ConnectorItem * fromConnectorItem, myConnectorItems) { foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { Wire * wire = qobject_cast(toConnectorItem->attachedTo()); if (!wire->getRatsnest()) { QList chained; QList ends; wire->collectChained(chained, ends); foreach (Wire * w, chained) { itemsToDelete.insert(w, this); deletedItems.insert(w); } } } else if (toConnectorItem->connectorType() == Connector::Female) { if (ignoreFemale()) { //fromConnectorItem->tempRemove(toConnectorItem, false); //toConnectorItem->tempRemove(fromConnectorItem, false); //extendChangeConnectionCommand(fromConnectorItem, toConnectorItem, false, true, parentCommand); } else { ItemBase * detachee = fromConnectorItem->attachedTo(); QPointF newPos = calcNewLoc(detachee, toConnectorItem->attachedTo()); // delete connections // add wires and connections for undisconnected connectors detachee->saveGeometry(); ViewGeometry vg = detachee->getViewGeometry(); vg.setLoc(newPos); new MoveItemCommand(this, detachee->id(), detachee->getViewGeometry(), vg, false, parentCommand); QHash emptyList; ConnectorPairHash connectorHash; disconnectFromFemale(detachee, emptyList, connectorHash, true, false, parentCommand); foreach (ConnectorItem * fConnectorItem, connectorHash.uniqueKeys()) { if (myConnectorItems.contains(fConnectorItem)) { // don't need to reconnect continue; } foreach (ConnectorItem * tConnectorItem, connectorHash.values(fConnectorItem)) { createWire(fConnectorItem, tConnectorItem, ViewGeometry::NoFlag, false, BaseCommand::CrossView, parentCommand); } } } } } } deleteMiddle(deletedItems, parentCommand); } bool SketchWidget::canDisconnectAll() { return true; } bool SketchWidget::ignoreFemale() { return true; } QPointF SketchWidget::calcNewLoc(ItemBase * moveBase, ItemBase * detachFrom) { QRectF dr = detachFrom->boundingRect(); dr.moveTopLeft(detachFrom->pos()); QPointF pos = moveBase->pos(); QRectF r = moveBase->boundingRect(); pos.setX(pos.x() + (r.width() / 2.0)); pos.setY(pos.y() + (r.height() / 2.0)); double d[4]; d[0] = qAbs(pos.y() - dr.top()); d[1] = qAbs(pos.y() - dr.bottom()); d[2] = qAbs(pos.x() - dr.left()); d[3] = qAbs(pos.x() - dr.right()); int ix = 0; for (int i = 1; i < 4; i++) { if (d[i] < d[ix]) { ix = i; } } QPointF newPos = moveBase->pos(); switch (ix) { case 0: newPos.setY(dr.top() - r.height()); break; case 1: newPos.setY(dr.bottom()); break; case 2: newPos.setX(dr.left() - r.width()); break; case 3: newPos.setX(dr.right()); break; } return newPos; } long SketchWidget::findPartOrWire(long itemID) { ItemBase * item = findItem(itemID); if (item == NULL) return itemID; if (item->itemType() != ModelPart::Wire) return itemID; QList chained; QList ends; qobject_cast(item)->collectChained(chained, ends); if (chained.length() <= 1) return itemID; foreach (Wire * w, chained) { if (w->id() < itemID) { itemID = w->id(); } } return itemID; } void SketchWidget::resizeJumperItem(long itemID, QPointF pos, QPointF c0, QPointF c1) { ItemBase * item = findItem(itemID); if (item == NULL) return; if (item->itemType() != ModelPart::Jumper) return; qobject_cast(item)->resize(pos, c0, c1); } QList SketchWidget::selectAllObsolete() { QSet itemBases; foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->isObsolete()) continue; itemBases.insert(itemBase->layerKinChief()); } selectAllItems(itemBases, QObject::tr("Select outdated parts")); return itemBases.toList(); } int SketchWidget::selectAllMoveLock() { QSet itemBases; foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (!itemBase->moveLock()) continue; itemBases.insert(itemBase->layerKinChief()); } return selectAllItems(itemBases, QObject::tr("Select locked parts")); } int SketchWidget::selectAllItems(QSet & itemBases, const QString & msg) { if (itemBases.count() <= 0) { // TODO: tell user? return 0; } QUndoCommand * parentCommand = new QUndoCommand(msg); stackSelectionState(false, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); foreach (ItemBase * itemBase, itemBases) { selectItemCommand->addRedo(itemBase->id()); } scene()->clearSelection(); m_undoStack->push(parentCommand); return itemBases.count(); } AddItemCommand * SketchWidget::newAddItemCommand(BaseCommand::CrossViewType crossViewType, ModelPart * newModelPart, QString moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, ViewGeometry & viewGeometry, qint64 id, bool updateInfoView, long modelIndex, bool addSubparts, QUndoCommand *parent) { AddItemCommand * aic = new AddItemCommand(this, crossViewType, moduleID, viewLayerPlacement, viewGeometry, id, updateInfoView, modelIndex, parent); if (newModelPart == NULL) { newModelPart = m_referenceModel->retrieveModelPart(moduleID); } if (!newModelPart->hasSubparts() || !addSubparts) return aic; ModelPartShared * modelPartShared = newModelPart->modelPartShared(); if (modelPartShared == NULL) return aic; foreach (ModelPartShared * mps, modelPartShared->subparts()) { long subID = ItemBase::getNextID(); ViewGeometry vg = viewGeometry; vg.setLoc(vg.loc() + (mps->subpartOffset() * GraphicsUtils::SVGDPI)); new AddItemCommand(this, crossViewType, mps->moduleID(), viewLayerPlacement, vg, subID, updateInfoView, -1, parent); AddSubpartCommand * asc = new AddSubpartCommand(this, crossViewType, id, subID, parent); asc->setRedoOnly(); } return aic; } bool SketchWidget::partLabelsVisible() { foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase->isPartLabelVisible()) return true; } return false; } void SketchWidget::showLabelFirstTime(long itemID, bool show, bool doEmit) { if (doEmit) { emit showLabelFirstTimeSignal(itemID, show, false); } } void SketchWidget::restorePartLabel(long itemID, QDomElement & element) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; itemBase->restorePartLabel(element, getLabelViewLayerID(itemBase)); } void SketchWidget::loadLogoImage(ItemBase * itemBase, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName) { if (oldSvg.isEmpty() && oldFilename.isEmpty()) { // have to swap in a custom shape then load the file emit swapBoardImageSignal(this, itemBase, newFilename, m_boardLayers == 1 ? ModuleIDNames::OneLayerBoardLogoImageModuleIDName : ModuleIDNames::BoardLogoImageModuleIDName, addName); return; } QUndoCommand * cmd = new LoadLogoImageCommand(this, itemBase->id(), oldSvg, oldAspectRatio, oldFilename, newFilename, addName, NULL); cmd->setText(tr("Change image from %1 to %2").arg(oldFilename).arg(newFilename)); m_undoStack->waitPush(cmd, PropChangeDelay); } void SketchWidget::loadLogoImage(long itemID, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; LogoItem * logoItem = qobject_cast(itemBase); if (logoItem == NULL) return; logoItem->reloadImage(oldSvg, oldAspectRatio, oldFilename, false); } void SketchWidget::loadLogoImage(long itemID, const QString & newFilename, bool addName) { ItemBase * itemBase = findItem(itemID); if (itemBase == NULL) return; LogoItem * logoItem = qobject_cast(itemBase); if (logoItem == NULL) return; logoItem->loadImage(newFilename, addName); } void SketchWidget::paintEvent ( QPaintEvent * event ) { //DebugDialog::debug("sketch widget paint event"); if (scene()) { ((FGraphicsScene *) scene())->setDisplayHandles(true); } QGraphicsView::paintEvent(event); } void SketchWidget::setNoteFocus(QGraphicsItem * item, bool inFocus) { if (inFocus) { m_inFocus.append(item); } else { m_inFocus.removeOne(item); } } double SketchWidget::defaultGridSizeInches() { return 0.0; // should never get here } double SketchWidget::gridSizeInches() { return m_gridSizeInches; } void SketchWidget::alignToGrid(bool align) { m_alignToGrid = align; QSettings settings; settings.setValue(QString("%1AlignToGrid").arg(viewName()), align); } void SketchWidget::showGrid(bool show) { m_showGrid = show; QSettings settings; settings.setValue(QString("%1ShowGrid").arg(viewName()), show); update(); } bool SketchWidget::alignedToGrid() { return m_alignToGrid; } bool SketchWidget::showingGrid() { return m_showGrid; } bool SketchWidget::canAlignToTopLeft(ItemBase *) { return false; } bool SketchWidget::canAlignToCenter(ItemBase *) { return false; } void SketchWidget::saveZoom(double zoom) { m_zoom = zoom; } double SketchWidget::retrieveZoom() { return m_zoom; } void SketchWidget::setGridSize(const QString & newSize) { QSettings settings; settings.setValue(QString("%1GridSize").arg(viewName()), newSize); m_gridSizeInches = TextUtils::convertToInches(newSize); m_gridSizeText = newSize; if (m_showGrid) { invalidateScene(); } } QString SketchWidget::gridSizeText() { if (!m_gridSizeText.isEmpty()) return m_gridSizeText; return QString("%1in").arg(m_gridSizeInches); } void SketchWidget::initGrid() { m_showGrid = m_alignToGrid = true; m_gridSizeInches = defaultGridSizeInches(); QSettings settings; QString szString = settings.value(QString("%1GridSize").arg(viewName()), "").toString(); if (!szString.isEmpty()) { bool ok; double temp = TextUtils::convertToInches(szString, &ok, false); if (ok) { m_gridSizeInches = temp; m_gridSizeText = szString; } } m_alignToGrid = settings.value(QString("%1AlignToGrid").arg(viewName()), true).toBool(); m_showGrid = settings.value(QString("%1ShowGrid").arg(viewName()), true).toBool(); } void SketchWidget::copyDrop() { QList itemBases; foreach (ItemBase * itemBase, m_savedItems.values()) { QList superSubs = collectSuperSubs(itemBase); if (superSubs.count() > 0) { foreach (ItemBase * supersub, superSubs) { if (!itemBases.contains(supersub)) itemBases.append(supersub); } continue; } itemBases.append(itemBase); } qSort(itemBases.begin(), itemBases.end(), ItemBase::zLessThan); foreach (ItemBase * itemBase, itemBases) { QPointF loc = itemBase->getViewGeometry().loc(); itemBase->setItemPos(loc); } copyAux(itemBases, false); m_savedItems.clear(); m_savedWires.clear(); } ViewLayer::ViewLayerPlacement SketchWidget::defaultViewLayerPlacement(ModelPart * modelPart) { Q_UNUSED(modelPart); //return (m_boardLayers == 1) ? ViewLayer::NewBottom : ViewLayer::NewTop; return ViewLayer::NewTop; } ViewLayer::ViewLayerPlacement SketchWidget::wireViewLayerPlacement(ConnectorItem *) { return (m_boardLayers == 1) ? ViewLayer::NewBottom : ViewLayer::NewTop; } void SketchWidget::changeBoardLayers(int layers, bool doEmit) { m_boardLayers = layers; if (doEmit) { emit changeBoardLayersSignal(layers, false); } } void SketchWidget::collectAllNets(QHash & indexer, QList< QList* > & allPartConnectorItems, bool includeSingletons, bool bothSides) { // get the set of all connectors in the sketch QList allConnectors; foreach (QGraphicsItem * item, scene()->items()) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!bothSides && connectorItem->attachedToViewLayerID() == ViewLayer::Copper1) continue; allConnectors.append(connectorItem); } // find all the nets and make a list of nodes (i.e. part ConnectorItems) for each net while (allConnectors.count() > 0) { ConnectorItem * connectorItem = allConnectors.takeFirst(); QList connectorItems; connectorItems.append(connectorItem); ConnectorItem::collectEqualPotential(connectorItems, bothSides, ViewGeometry::NoFlag); if (connectorItems.count() <= 0) { continue; } foreach (ConnectorItem * ci, connectorItems) { //if (connectorItems.count(ci) > 1) { //DebugDialog::debug("collect equal potential bug"); //} //DebugDialog::debug(QString("from in equal potential %1 %2").arg(ci->connectorSharedName()).arg(ci->attachedToInstanceTitle())); allConnectors.removeOne(ci); } if (!includeSingletons && (connectorItems.count() <= 1)) { continue; } QList * partConnectorItems = new QList; ConnectorItem::collectParts(connectorItems, *partConnectorItems, includeSymbols(), ViewLayer::NewTopAndBottom); for (int i = partConnectorItems->count() - 1; i >= 0; i--) { if (!partConnectorItems->at(i)->attachedTo()->isEverVisible()) { partConnectorItems->removeAt(i); } } if ((partConnectorItems->count() <= 0) || (!includeSingletons && (partConnectorItems->count() <= 1))) { delete partConnectorItems; continue; } foreach (ConnectorItem * ci, *partConnectorItems) { //if (partConnectorItems->count(ci) > 1) { //DebugDialog::debug("collect Parts bug"); //} if (!connectorItems.contains(ci)) { // crossed layer: toss it //DebugDialog::debug(QString("not in equal potential '%1' '%2' %3") // .arg(ci->connectorSharedName()) // .arg(ci->attachedToInstanceTitle()) // .arg(ci->attachedToViewLayerID())); continue; } //if (indexer.keys().contains(ci)) { //DebugDialog::debug(QString("connector item already indexed %1 %2").arg(ci->connectorSharedName()).arg(ci->attachedToInstanceTitle())); //} //int c = indexer.count(); //DebugDialog::debug(QString("insert indexer %1 '%2' '%3' %4") //.arg(c) //.arg(ci->connectorSharedName()) //.arg(ci->attachedToInstanceTitle()) //.arg(ci->attachedToViewLayerID())); indexer.insert(ci, indexer.count()); } //DebugDialog::debug("________________"); allPartConnectorItems.append(partConnectorItems); } } ViewLayer::ViewLayerPlacement SketchWidget::getViewLayerPlacement(ModelPart * modelPart, QDomElement & instance, QDomElement & view, ViewGeometry & viewGeometry) { Q_UNUSED(instance); ViewLayer::ViewLayerPlacement viewLayerPlacement = defaultViewLayerPlacement(modelPart); if (modelPart->moduleID().compare(ModuleIDNames::GroundPlaneModuleIDName) == 0) { QString layer = view.attribute("layer"); if (layer.isEmpty()) return viewLayerPlacement; ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(layer); if (viewLayerID == ViewLayer::GroundPlane1) { return ViewLayer::NewTop; } return ViewLayer::NewBottom; } if (viewGeometry.getAnyTrace()) { QString layer = view.attribute("layer"); if (layer.isEmpty()) return viewLayerPlacement; ViewLayer::ViewLayerID viewLayerID = ViewLayer::viewLayerIDFromXmlString(layer); switch (viewLayerID) { case ViewLayer::Copper1Trace: case ViewLayer::GroundPlane1: case ViewLayer::Copper1: return ViewLayer::NewTop; case ViewLayer::Copper0Trace: case ViewLayer::GroundPlane0: case ViewLayer::Copper0: return ViewLayer::NewBottom; default: break; } } return viewLayerPlacement; } bool SketchWidget::routeBothSides() { return false; } void SketchWidget::copyBoundingRectsSlot(QHash & boundingRects) { QRectF itemsBoundingRect; QList tlBases; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item); if (itemBase == NULL) continue; if (itemBase->getRatsnest()) continue; itemsBoundingRect |= itemBase->sceneBoundingRect(); } boundingRects.insert(m_viewName, itemsBoundingRect); } void SketchWidget::changeLayer(long id, double z, ViewLayer::ViewLayerID viewLayerID) { Q_UNUSED(id); Q_UNUSED(z); Q_UNUSED(viewLayerID); } bool SketchWidget::resizingJumperItemRelease() { return false; } bool SketchWidget::resizingJumperItemPress(ItemBase *) { return false; } bool SketchWidget::resizingBoardPress(ItemBase * itemBase) { if (itemBase == NULL) return false; // board's child items (at the moment) are the resize grips ResizableBoard * rb = qobject_cast(itemBase->layerKinChief()); if (rb == NULL) return false; if (!rb->inResize()) return false; m_resizingBoard = rb; m_resizingBoard->saveParams(); return true; } bool SketchWidget::resizingBoardRelease() { if (m_resizingBoard == NULL) return false; resizeBoard(); return true; } void SketchWidget::resizeBoard() { QSizeF oldSize; QPointF oldPos; m_resizingBoard->getParams(oldPos, oldSize); QSizeF newSize; QPointF newPos; m_resizingBoard->saveParams(); m_resizingBoard->getParams(newPos, newSize); QUndoCommand * parentCommand = new QUndoCommand(tr("Resize board to %1 %2").arg(newSize.width()).arg(newSize.height())); rememberSticky(m_resizingBoard, parentCommand); new ResizeBoardCommand(this, m_resizingBoard->id(), oldSize.width(), oldSize.height(), newSize.width(), newSize.height(), parentCommand); if (oldPos != newPos) { m_resizingBoard->saveGeometry(); ViewGeometry vg1 = m_resizingBoard->getViewGeometry(); ViewGeometry vg2 = vg1; vg1.setLoc(oldPos); vg2.setLoc(newPos); new MoveItemCommand(this, m_resizingBoard->id(), vg1, vg2, false, parentCommand); } new CheckStickyCommand(this, BaseCommand::SingleView, m_resizingBoard->id(), true, CheckStickyCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, 10); m_resizingBoard = NULL; } bool SketchWidget::hasAnyNets() { return false; } void SketchWidget::ratsnestConnect(ItemBase * itemBase, bool connect) { foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { ratsnestConnect(connectorItem, connect); } } void SketchWidget::ratsnestConnect(long id, const QString & connectorID, bool connect, bool doEmit) { if (doEmit) { emit ratsnestConnectSignal(id, connectorID, connect, false); } ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, itemBase->viewLayerPlacement()); if (connectorItem == NULL) return; ratsnestConnect(connectorItem, connect); } void SketchWidget::ratsnestConnect(ConnectorItem * c1, ConnectorItem * c2, bool connect, bool wait) { if (wait) { if (connect) { m_ratsnestCacheConnect << c1 << c2; } else { m_ratsnestCacheDisconnect << c1 << c2; } return; } QList connectorItems; connectorItems.append(c1); connectorItems.append(c2); ConnectorItem::collectEqualPotential(connectorItems, true, ViewGeometry::RatsnestFlag); foreach (ConnectorItem * connectorItem, connectorItems) { ratsnestConnect(connectorItem, connect); } } void SketchWidget::ratsnestConnect(ConnectorItem * connectorItem, bool connect) { if (connect) { m_ratsnestUpdateConnect << connectorItem; } else { m_ratsnestUpdateDisconnect << connectorItem; } //connectorItem->debugInfo(QString("rat connect %1").arg(connect)); } void SketchWidget::deleteRatsnest(Wire * ratsnest, QUndoCommand * parentCommand) { // deleting a ratsnest really means deleting underlying connections // assume ratsnest has only one connection at each end ConnectorItem * source = ratsnest->connector0()->firstConnectedToIsh(); ConnectorItem * sink = ratsnest->connector1()->firstConnectedToIsh(); QList connectorItems; connectorItems.append(source); connectorItems.append(sink); ConnectorItem::collectEqualPotential(connectorItems, true, ViewGeometry::RatsnestFlag); QList foreignSketchWidgets; emit collectRatsnestSignal(foreignSketchWidgets); // there are multiple possibilities for each pair of connectors: // they are directly connected because they're each inserted into female connectors on the same bus // they are directly connected with a wire // they are "directly" connected through some combination of female connectors and wires (i.e. one part is connected to a wire which is inserted into a female connector) // they are indirectly connected via other parts // what if there are multiple direct connections--treat it as a single connection and delete them all QList cutSet; GraphUtils::minCut(connectorItems, foreignSketchWidgets, source, sink, cutSet); emit removeRatsnestSignal(cutSet, parentCommand); foreach (ConnectorEdge * ce, cutSet) { delete ce; } } void SketchWidget::removeRatsnestSlot(QList & cutSet, QUndoCommand * parentCommand) { QHash detachItems; // key is part to be detached, value is part to detach from QSet deletedItems; QList deletedIDs; foreach (ConnectorEdge * ce, cutSet) { if (ce->c0->attachedToViewID() != viewID()) continue; if (ce->c1->attachedToViewID() != viewID()) continue; if (ce->wire) { QList ends; QList wires; ce->wire->collectChained(wires, ends); foreach (Wire * w, wires) { if (!deletedIDs.contains(w->id())) { deletedItems.insert(w); deletedIDs.append(w->id()); } } } else { // we have to detach the source or sink from a female connector if (ce->c0->connectorType() == Connector::Female) { detachItems.insert(ce->c1, ce->c0); } else { detachItems.insert(ce->c0, ce->c1); } } } foreach (ConnectorItem * detacheeConnector, detachItems.keys()) { ItemBase * detachee = detacheeConnector->attachedTo(); ConnectorItem * detachFromConnector = detachItems.value(detacheeConnector); ItemBase * detachFrom = detachFromConnector->attachedTo(); QPointF newPos = calcNewLoc(detachee, detachFrom); // delete connections // add wires and connections for undisconnected connectors detachee->saveGeometry(); ViewGeometry vg = detachee->getViewGeometry(); vg.setLoc(newPos); new MoveItemCommand(this, detachee->id(), detachee->getViewGeometry(), vg, false, parentCommand); QHash emptyList; ConnectorPairHash connectorHash; disconnectFromFemale(detachee, emptyList, connectorHash, true, false, parentCommand); foreach (ConnectorItem * fromConnectorItem, connectorHash.uniqueKeys()) { if (detachItems.keys().contains(fromConnectorItem)) { // don't need to reconnect continue; } if (detachItems.values().contains(fromConnectorItem)) { // don't need to reconnect continue; } foreach (ConnectorItem * toConnectorItem, connectorHash.values(fromConnectorItem)) { createWire(fromConnectorItem, toConnectorItem, ViewGeometry::NoFlag, false, BaseCommand::CrossView, parentCommand); } } } deleteAux(deletedItems, parentCommand, false); } void SketchWidget::addDefaultParts() { } void SketchWidget::vScrollToZero() { verticalScrollBar()->setValue(verticalScrollBar()->minimum()); } float SketchWidget::getTopZ() { return m_z; } QGraphicsItem * SketchWidget::addWatermark(const QString &filename) { QGraphicsSvgItem * item = new QGraphicsSvgItem(filename); if (item == NULL) return NULL; this->scene()->addItem(item); return item; } bool SketchWidget::acceptsTrace(const ViewGeometry &) { return false; } QPointF SketchWidget::alignOneToGrid(ItemBase * itemBase) { if (m_alignToGrid) { QHash savedItems; QHash savedWires; findAlignmentAnchor(itemBase, savedItems, savedWires); if (m_alignmentItem) { m_alignmentItem = NULL; QPointF loc = itemBase->pos(); alignLoc(loc, m_alignmentStartPoint, QPointF(0,0), QPointF(0, 0)); QPointF result = loc - itemBase->pos(); itemBase->setPos(loc); return result; } } return QPointF(0, 0); } ViewGeometry::WireFlag SketchWidget::getTraceFlag() { return ViewGeometry::NormalFlag; } void SketchWidget::changeBus(ItemBase * itemBase, bool connect, const QString & oldBus, const QString & newBus, QList & connectorItems, const QString & message, const QString & oldLayout, const QString & newLayout) { QUndoCommand * parentCommand = new QUndoCommand(message); CleanUpWiresCommand * cuwc = new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); foreach(ConnectorItem * connectorItem, connectorItems) { cuwc->addRatsnestConnect(connectorItem->attachedToID(), connectorItem->connectorSharedID(), connect); } new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new SetPropCommand(this, itemBase->id(), "buses", oldBus, newBus, true, parentCommand); new SetPropCommand(this, itemBase->id(), "layout", oldLayout, newLayout, true, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); cuwc = new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); foreach(ConnectorItem * connectorItem, connectorItems) { cuwc->addRatsnestConnect(connectorItem->attachedToID(), connectorItem->connectorSharedID(), connect); } m_undoStack->waitPush(parentCommand, PropChangeDelay); } const QString & SketchWidget::filenameIf() { static QString filename; emit filenameIfSignal(filename); return filename; } void SketchWidget::setItemDropOffset(long id, QPointF offset) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; itemBase->setDropOffset(offset); } Wire * SketchWidget::createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement spec) { Q_UNUSED(fromWire); if (spec == ViewLayer::UnknownPlacement) { spec = wireViewLayerPlacement(connectorItem); } return qobject_cast(addItemAuxTemp(wireModel, spec, viewGeometry, ItemBase::getNextID(), true, m_viewID, true)); } void SketchWidget::prereleaseTempWireForDragging(Wire*) { } void SketchWidget::wireChangedCurveSlot(Wire* wire, const Bezier * oldB, const Bezier * newB, bool triggerFirstTime) { this->clearHoldingSelectItem(); this->m_moveEventCount = 0; // clear this so an extra MoveItemCommand isn't posted ChangeWireCurveCommand * cwcc = new ChangeWireCurveCommand(this, wire->id(), oldB, newB, wire->getAutoroutable(), NULL); cwcc->setText("Change wire curvature"); if (!triggerFirstTime) { cwcc->setSkipFirstRedo(); } m_undoStack->push(cwcc); } void SketchWidget::changeWireCurve(long id, const Bezier * bezier, bool autoroutable) { Wire * wire = qobject_cast(findItem(id)); if (wire == NULL) return; wire->changeCurve(bezier); wire->setAutoroutable(autoroutable); } void SketchWidget::changeLegCurve(long id, const QString & connectorID, int index, const Bezier * bezier) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, ViewLayer::specFromID(itemBase->viewLayerID())); if (connectorItem == NULL) return; connectorItem->changeLegCurve(index, bezier); } void SketchWidget::addLegBendpoint(long id, const QString & connectorID, int index, QPointF p, const class Bezier * bezierLeft, const class Bezier * bezierRight) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, ViewLayer::specFromID(itemBase->viewLayerID())); if (connectorItem == NULL) return; connectorItem->addLegBendpoint(index, p, bezierLeft, bezierRight); } void SketchWidget::removeLegBendpoint(long id, const QString & connectorID, int index, const class Bezier * bezierCombined) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, ViewLayer::specFromID(itemBase->viewLayerID())); if (connectorItem == NULL) return; connectorItem->removeLegBendpoint(index, bezierCombined); } void SketchWidget::moveLegBendpoint(long id, const QString & connectorID, int index, QPointF p) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, ViewLayer::specFromID(itemBase->viewLayerID())); if (connectorItem == NULL) return; connectorItem->moveLegBendpoint(index, p); } void SketchWidget::moveLegBendpoints(bool undoOnly, QUndoCommand * parentCommand) { foreach (ItemBase * itemBase, m_stretchingLegs.uniqueKeys()) { foreach (ConnectorItem * connectorItem, m_stretchingLegs.values(itemBase)) { moveLegBendpointsAux(connectorItem, undoOnly, parentCommand); } } } void SketchWidget::moveLegBendpointsAux(ConnectorItem * connectorItem, bool undoOnly, QUndoCommand * parentCommand) { int index0, index1; QPointF oldPos0, newPos0, oldPos1, newPos1; connectorItem->moveDone(index0, oldPos0, newPos0, index1, oldPos1, newPos1); MoveLegBendpointCommand * mlbc = new MoveLegBendpointCommand(this, connectorItem->attachedToID(), connectorItem->connectorSharedID(), index0, oldPos0, newPos0, parentCommand); if (undoOnly) mlbc->setUndoOnly(); else mlbc->setRedoOnly(); if (index0 != index1) { mlbc = new MoveLegBendpointCommand(this, connectorItem->attachedToID(), connectorItem->connectorSharedID(), index1, oldPos1, newPos1, parentCommand); if (undoOnly) mlbc->setUndoOnly(); else mlbc->setRedoOnly(); } } bool SketchWidget::curvyWires() { return m_curvyWires; } void SketchWidget::setCurvyWires(bool curvyWires) { m_curvyWires = curvyWires; } bool SketchWidget::curvyWiresIndicated(Qt::KeyboardModifiers modifiers) { if (m_curvyWires) { return ((modifiers & Qt::ControlModifier) == 0); } return ((modifiers & Qt::ControlModifier) != 0); } void SketchWidget::setMoveLock(long id, bool lock) { ItemBase * itemBase = findItem(id); if (itemBase) itemBase->setMoveLock(lock); } void SketchWidget::triggerRotate(ItemBase * itemBase, double degrees) { QList selectedItems = scene()->selectedItems(); setIgnoreSelectionChangeEvents(true); this->clearSelection(); itemBase->setSelected(true); rotateX(degrees, false, itemBase); foreach (QGraphicsItem * item, selectedItems) { item->setSelected(true); } setIgnoreSelectionChangeEvents(false); } void SketchWidget::makeWiresChangeConnectionCommands(const QList & wires, QUndoCommand * parentCommand) { QStringList alreadyList; foreach (Wire * wire, wires) { QList wireConnectorItems; wireConnectorItems << wire->connector0() << wire->connector1(); foreach (ConnectorItem * fromConnectorItem, wireConnectorItems) { foreach(ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { QString already = ((fromConnectorItem->attachedToID() <= toConnectorItem->attachedToID()) ? QString("%1.%2.%3.%4") : QString("%3.%4.%1.%2")) .arg(fromConnectorItem->attachedToID()).arg(fromConnectorItem->connectorSharedID()) .arg(toConnectorItem->attachedToID()).arg(toConnectorItem->connectorSharedID()); if (alreadyList.contains(already)) continue; alreadyList.append(already); extendChangeConnectionCommand(BaseCommand::CrossView, fromConnectorItem, toConnectorItem, ViewLayer::specFromID(toConnectorItem->attachedToViewLayerID()), false, parentCommand); } } } } void SketchWidget::changePinLabelsSlot(ItemBase * itemBase, bool singleRow) { itemBase = this->findItem(itemBase->id()); if (itemBase == NULL) return; if (itemBase->viewID() != ViewLayer::SchematicView) return; PaletteItem * paletteItem = qobject_cast(itemBase->layerKinChief()); if (paletteItem == NULL) return; if (qobject_cast(itemBase)) { paletteItem->changePinLabels(singleRow, true); } else if (qobject_cast(itemBase)) { paletteItem->changePinLabels(singleRow, false); } else { bool hasLayout, sip; QStringList labels = paletteItem->sipOrDipOrLabels(hasLayout, sip); if (labels.count() == 0) return; QTransform transform = paletteItem->untransform(); QString svg = PartFactory::makeSchematicSipOrDipOr(labels, hasLayout, sip); paletteItem->resetLayerKin(svg); if (!hasLayout && !sip) { paletteItem->resetConnectors(); } paletteItem->retransform(transform); } } void SketchWidget::changePinLabels(ItemBase * itemBase, bool singleRow) { emit changePinLabelsSignal(itemBase, singleRow); changePinLabelsSlot(itemBase, singleRow); } void SketchWidget::renamePins(ItemBase * itemBase, const QStringList & oldLabels, const QStringList & newLabels, bool singleRow) { QUndoCommand * command = new RenamePinsCommand(this, itemBase->id(), oldLabels, newLabels, singleRow, NULL); command->setText(tr("change pin labels")); m_undoStack->waitPush(command, 10); } void SketchWidget::renamePins(long id, const QStringList & labels, bool singleRow) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; PaletteItem * paletteItem = qobject_cast(itemBase->layerKinChief()); if (paletteItem == NULL) return; paletteItem->renamePins(labels, singleRow); } bool SketchWidget::checkUpdateRatsnest(QList & connectorItems) { foreach (ConnectorItem * ci, m_ratsnestUpdateConnect) { if (ci == NULL) continue; if (connectorItems.contains(ci)) return true; } foreach (ConnectorItem * ci, m_ratsnestUpdateDisconnect) { if (ci == NULL) continue; if (connectorItems.contains(ci)) return true; } return false; } void SketchWidget::getRatsnestColor(QColor & color) { //RatsnestColors::reset(m_viewID); color = RatsnestColors::netColor(m_viewID); } VirtualWire * SketchWidget::makeOneRatsnestWire(ConnectorItem * source, ConnectorItem * dest, bool routed, QColor color, bool force) { if (source->attachedTo() == dest->attachedTo()) { if (source == dest) return NULL; if (source->bus() == dest->bus() && dest->bus() != NULL) { if (!force) return NULL; // don't draw a wire within the same part on the same bus } } long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; makeRatsnestViewGeometry(viewGeometry, source, dest); viewGeometry.setRouted(routed); //if (viewID() == ViewLayer::PCBView) { // source->debugInfo("making rat src"); // dest->debugInfo("making rat dst"); //} // ratsnest only added to one view ItemBase * newItemBase = addItem(m_referenceModel->retrieveModelPart(ModuleIDNames::WireModuleIDName), source->attachedTo()->viewLayerPlacement(), BaseCommand::SingleView, viewGeometry, newID, -1, NULL); VirtualWire * wire = qobject_cast(newItemBase); ConnectorItem * connector0 = wire->connector0(); source->tempConnectTo(connector0, false); connector0->tempConnectTo(source, false); ConnectorItem * connector1 = wire->connector1(); dest->tempConnectTo(connector1, false); connector1->tempConnectTo(dest, false); if (!source->attachedTo()->isVisible() || !dest->attachedTo()->isVisible()) { wire->setVisible(false); } wire->setColor(color, ratsnestOpacity()); wire->setWireWidth(ratsnestWidth(), this, VirtualWire::ShapeWidthExtra + ratsnestWidth()); return wire; } double SketchWidget::ratsnestOpacity() { return m_ratsnestOpacity; } void SketchWidget::setRatsnestOpacity(double opacity) { m_ratsnestOpacity = opacity; } double SketchWidget::ratsnestWidth() { return m_ratsnestWidth; } void SketchWidget::setRatsnestWidth(double width) { m_ratsnestWidth = width; } void SketchWidget::makeRatsnestViewGeometry(ViewGeometry & viewGeometry, ConnectorItem * source, ConnectorItem * dest) { QPointF fromPos = source->sceneAdjustedTerminalPoint(NULL); viewGeometry.setLoc(fromPos); QPointF toPos = dest->sceneAdjustedTerminalPoint(NULL); QLineF line(0, 0, toPos.x() - fromPos.x(), toPos.y() - fromPos.y()); viewGeometry.setLine(line); viewGeometry.setWireFlags(ViewGeometry::RatsnestFlag); } const QString & SketchWidget::traceColor(ViewLayer::ViewLayerPlacement) { return ___emptyString___; } double SketchWidget::getTraceWidth() { return 1; } void SketchWidget::setAnyInRotation() { m_anyInRotation = true; } void SketchWidget::removeWire(Wire * w, QList & ends, QList & done, QUndoCommand * parentCommand) { QList chained; w->collectChained(chained, ends); makeWiresChangeConnectionCommands(chained, parentCommand); foreach (Wire * c, chained) { makeDeleteItemCommand(c, BaseCommand::CrossView, parentCommand); done.append(c); } } void SketchWidget::collectRatsnestSlot(QList & foreignSketchWidgets) { foreignSketchWidgets << this; } void SketchWidget::setGroundFillSeed(long id, const QString & connectorID, bool seed) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; ConnectorItem * connectorItem = findConnectorItem(itemBase, connectorID, ViewLayer::specFromID(itemBase->viewLayerID())); if (connectorItem == NULL) return; connectorItem->setGroundFillSeed(seed); } void SketchWidget::resolveTemporary(bool resolve, ItemBase * itemBase) { if (resolve) { m_undoStack->resolveTemporary(); return; } QTimer * timer = new QTimer(); timer->setProperty("temporary", QVariant::fromValue(itemBase)); timer->setSingleShot(true); timer->setInterval(10); connect(timer, SIGNAL(timeout()), this, SLOT(deleteTemporary())); // resolveTemporary is invoked indirectly from the temporary stack item via the itemBase, so defer deletion timer->start(); } void SketchWidget::deleteTemporary() { QObject * s = sender(); if (s == NULL) return; ItemBase * itemBase = s->property("temporary").value(); if (itemBase) { deleteItem(itemBase->id(), true, true, false); } m_undoStack->deleteTemporary(); s->deleteLater(); } QString SketchWidget::checkDroppedModuleID(const QString & moduleID) { return moduleID; } bool SketchWidget::sameElectricalLayer2(ViewLayer::ViewLayerID, ViewLayer::ViewLayerID) { return true; } bool SketchWidget::canConnect(ItemBase * from, ItemBase * to) { if (m_pasting) return true; // no need to check in this case Wire * fromWire = qobject_cast(from); Wire * toWire = qobject_cast(to); if (fromWire != NULL && fromWire->getTrace()) { if (fromWire->isTraceType(getTraceFlag())) { return canConnect(fromWire, to); } else { bool can; emit canConnectSignal(fromWire, to, can); return can; } } if (toWire != NULL && toWire->getTrace()) { if (toWire->isTraceType(getTraceFlag())) { return canConnect(toWire, from); } else { bool can; emit canConnectSignal(toWire, from, can); return can; } } return true; } bool SketchWidget::canConnect(Wire *, ItemBase *) { return true; } void SketchWidget::canConnect(Wire * from, ItemBase * to, bool & connect) { if (!from->isTraceType(getTraceFlag())) return; //from->debugInfo("can connect"); //to->debugInfo("\t"); from = qobject_cast(findItem(from->id())); to = findItem(to->id()); connect = canConnect(from, to); } long SketchWidget::swapStart(SwapThing & swapThing, bool master) { Q_UNUSED(master); long newID = ItemBase::getNextID(swapThing.newModelIndex); ItemBase * itemBase = swapThing.itemBase; if (itemBase->viewID() != m_viewID) { itemBase = findItem(itemBase->id()); if (itemBase == NULL) return newID; } ViewGeometry vg = itemBase->getViewGeometry(); QTransform oldTransform = vg.transform(); bool needsTransform = false; if (!oldTransform.isIdentity()) { // restore identity transform vg.setTransform(QTransform()); needsTransform = true; } new MoveItemCommand(this, itemBase->id(), vg, vg, false, swapThing.parentCommand); // command created for each view newAddItemCommand(BaseCommand::SingleView, NULL, swapThing.newModuleID, swapThing.viewLayerPlacement, vg, newID, true, swapThing.newModelIndex, true, swapThing.parentCommand); if (needsTransform) { QMatrix m; m.setMatrix(oldTransform.m11(), oldTransform.m12(), oldTransform.m21(), oldTransform.m22(), 0, 0); new TransformItemCommand(this, newID, m, m, swapThing.parentCommand); } return newID; } void SketchWidget::setPasting(bool pasting) { m_pasting = pasting; } void SketchWidget::showUnrouted() { // MainWindow::routingStatusLabelMouse uses a different technique for collecting unrouted... // what about multiple boards QList< QList< ConnectorItem *>* > allPartConnectorItems; QHash indexer; collectAllNets(indexer, allPartConnectorItems, false, routeBothSides()); QSet toShow; foreach (QList * connectorItems, allPartConnectorItems) { ConnectorPairHash result; GraphUtils::chooseRatsnestGraph(connectorItems, (ViewGeometry::RatsnestFlag | ViewGeometry::NormalFlag | ViewGeometry::PCBTraceFlag | ViewGeometry::SchematicTraceFlag) ^ getTraceFlag(), result); foreach (ConnectorItem * ck, result.uniqueKeys()) { toShow.insert(ck); foreach (ConnectorItem * cv, result.values(ck)) { toShow.insert(cv); } } } QList visited; foreach (ConnectorItem * connectorItem, toShow) { if (connectorItem->isActive() && connectorItem->isVisible() && !connectorItem->hidden() && !connectorItem->layerHidden()) { connectorItem->showEqualPotential(true, visited); } else { connectorItem = connectorItem->getCrossLayerConnectorItem(); if (connectorItem) connectorItem->showEqualPotential(true, visited); } } QString message = tr("Unrouted connections are highlighted in yellow."); if (toShow.count() == 0) message = tr("There are no unrouted connections"); QMessageBox::information(this, tr("Unrouted connections"), tr("%1\n\n" "Note: you can also trigger this display by mousing down on the routing status text in the status bar.").arg(message)); visited.clear(); foreach (ConnectorItem * connectorItem, toShow) { if (connectorItem->isActive() && connectorItem->isVisible() && !connectorItem->hidden() && !connectorItem->layerHidden()) { connectorItem->showEqualPotential(false, visited); } else { connectorItem = connectorItem->getCrossLayerConnectorItem(); if (connectorItem) connectorItem->showEqualPotential(false, visited); } } } void SketchWidget::showEvent(QShowEvent * event) { InfoGraphicsView::showEvent(event); emit showing(this); } void SketchWidget::removeDragWire() { if (scene()->mouseGrabberItem() == m_connectorDragWire) { // probably already ungrabbed by the wire, but just in case m_connectorDragWire->ungrabMouse(); //m_connectorDragWire->debugInfo("ungrabbing mouse 2"); } this->scene()->removeItem(m_connectorDragWire); } void SketchWidget::selectItem(ItemBase * itemBase) { QList itemBases; itemBases << itemBase; selectItems(itemBases); } void SketchWidget::selectItemsWithModuleID(ModelPart * modelPart) { QSet itemBases; foreach (QGraphicsItem * item, scene()->items()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase && itemBase->moduleID() == modelPart->moduleID()) { itemBases.insert(itemBase->layerKinChief()); } } if (itemBases.count() == 0) { QMessageBox::information(NULL, "Not found", tr("Part '%1' not found in sketch").arg(modelPart->title())); return; } selectItems(itemBases.values()); } void SketchWidget::addToSketch(QList & modelParts) { if (modelParts.count() == 0) { modelParts = this->m_referenceModel->allParts(); } QUndoCommand* parentCommand = new QUndoCommand(tr("Add %1 parts").arg(modelParts.count())); stackSelectionState(false, parentCommand); new CleanUpWiresCommand(this, CleanUpWiresCommand::Noop, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); int ix = 0; QList ids; int columns = 50; foreach (ModelPart * modelPart, modelParts) { ViewGeometry viewGeometry; int x = (ix % columns) * 100; int y = (ix / columns) * 100; ix++; viewGeometry.setLoc(QPointF(x, y)); ViewLayer::ViewLayerPlacement viewLayerPlacement; getDroppedItemViewLayerPlacement(modelPart, viewLayerPlacement); long id = ItemBase::getNextID(); newAddItemCommand(BaseCommand::CrossView, modelPart, modelPart->moduleID(), viewLayerPlacement, viewGeometry, id, true, -1, true, parentCommand); ids.append(id); } new PackItemsCommand(this, columns, ids, parentCommand); m_undoStack->waitPush(parentCommand, 10); } void SketchWidget::selectItems(QList startingItemBases) { QSet itemBases; foreach (ItemBase * itemBase, startingItemBases) { if (itemBase) itemBases.insert(itemBase->layerKinChief()); } QSet already; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase) already.insert(itemBase->layerKinChief()); } bool theSame = (itemBases.count() == already.count()); if (theSame) { foreach(ItemBase * itemBase, itemBases) { if (!already.contains(itemBase)) { theSame = false; break; } } } if (theSame) return; int count = 0; ItemBase * theItemBase = NULL; foreach(ItemBase * itemBase, itemBases) { if (itemBase) { theItemBase = itemBase; count++; } } QString message; if (count == 0) { message = tr("Deselect all"); } else if (count == 1) { message = tr("Select %1").arg(theItemBase->instanceTitle()); } else { message = tr("Select %1 items").arg(count); } QUndoCommand * parentCommand = new QUndoCommand(message); stackSelectionState(false, parentCommand); SelectItemCommand * selectItemCommand = new SelectItemCommand(this, SelectItemCommand::NormalSelect, parentCommand); foreach(ItemBase * itemBase, itemBases) { if (itemBase) { selectItemCommand->addRedo(itemBase->id()); } } scene()->clearSelection(); m_undoStack->push(parentCommand); } QGraphicsItem * SketchWidget::getClickedItem(QList & items) { foreach (QGraphicsItem * gitem, items) { if (gitem->acceptedMouseButtons() != Qt::NoButton) { bool ok = true; emit clickedItemCandidateSignal(gitem, ok); if (ok) { return gitem; } } } return NULL; } void SketchWidget::blockUI(bool block) { m_blockUI = block; } void SketchWidget::viewItemInfo(ItemBase * item) { if (m_blockUI) return; InfoGraphicsView::viewItemInfo(item); } QHash SketchWidget::getAutorouterSettings() { return QHash(); } void SketchWidget::setAutorouterSettings(QHash &) { } void SketchWidget::hidePartLayer(long id, ViewLayer::ViewLayerID viewLayerID, bool hide) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; hidePartLayer(itemBase, viewLayerID, hide); } void SketchWidget::hidePartLayer(ItemBase * itemBase, ViewLayer::ViewLayerID viewLayerID, bool hide) { if (itemBase->viewLayerID() == viewLayerID) { itemBase->setLayerHidden(hide); } else { foreach (ItemBase * lkpi, itemBase->layerKinChief()->layerKin()) { if (lkpi->viewLayerID() == viewLayerID) { lkpi->setLayerHidden(hide); break; } } } } void SketchWidget::cleanupRatsnests(bool doEmit) { cleanupRatsnests(m_ratsnestCacheConnect, true); cleanupRatsnests(m_ratsnestCacheDisconnect, false); if (doEmit) emit cleanupRatsnestsSignal(false); } void SketchWidget::cleanupRatsnests(QList< QPointer > & connectorItems, bool connect) { QList cis; foreach (ConnectorItem * connectorItem, connectorItems) { if (connectorItem) cis << connectorItem; } connectorItems.clear(); QSet set = cis.toSet(); cis.clear(); QList cis2 = set.toList(); ConnectorItem::collectEqualPotential(cis2, true, ViewGeometry::RatsnestFlag); foreach (ConnectorItem * connectorItem, cis2) { ratsnestConnect(connectorItem, connect); } } void SketchWidget::addSubpart(long id, long subpartID, bool doEmit) { ItemBase * super = findItem(id); if (super == NULL) return; ItemBase * sub = findItem(subpartID); if (sub == NULL) return; super->addSubpart(sub); sub->setInstanceTitle("", true); if (doEmit) { emit addSubpartSignal(id, subpartID, false); } } void SketchWidget::getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement & viewLayerPlacement) { emit getDroppedItemViewLayerPlacementSignal(modelPart, viewLayerPlacement); } QList SketchWidget::collectSuperSubs(ItemBase * itemBase) { QList itemBases; if (itemBase->superpart()) { itemBases.append(itemBase->superpart()->layerKinChief()); foreach (ItemBase * subpart, itemBase->superpart()->subparts()) { if (!itemBases.contains(subpart->layerKinChief())) { itemBases.append(subpart->layerKinChief()); } } } else if (itemBase->subparts().count() > 0) { itemBases.append(itemBase->layerKinChief()); foreach (ItemBase * subpart, itemBase->subparts()) { if (!itemBases.contains(subpart->layerKinChief())) { itemBases.append(subpart->layerKinChief()); } } } return itemBases; } void SketchWidget::moveItem(ItemBase * itemBase, double x, double y) { if (itemBase == NULL) return; QPointF p = itemBase->pos(); if (qAbs(x - p.x()) < 0.01 && qAbs(y - p.y()) < 0.01) return; bool alignToGrid = m_alignToGrid; m_alignToGrid = false; moveByArrow(x - p.x(), y - p.y(), NULL); m_movingByArrow = false; checkMoved(false); m_savedItems.clear(); m_savedWires.clear(); m_alignToGrid = alignToGrid; } void SketchWidget::alignItems(Qt::Alignment alignment) { bool rubberBandLegEnabled = false; m_dragBendpointWire = NULL; clearHoldingSelectItem(); m_savedItems.clear(); m_savedWires.clear(); m_moveEventCount = 0; prepMove(NULL, rubberBandLegEnabled, true); QMultiHash unsaved; QSet unsavedSet; foreach (ItemBase * itemBase, m_savedItems) { if (itemBase->itemType() == ModelPart::Wire) { Wire * wire = qobject_cast(itemBase); QList wires; QList ends; wire->collectChained(wires, ends); foreach (Wire * w, wires) { if (!unsavedSet.contains(w)) { QList< QPointer > toList = w->connector0()->connectedToItems(); foreach (ConnectorItem * end, ends) { if (toList.contains(end)) { unsaved.insert(w, end); break; } } unsavedSet.insert(w); } } } } foreach (Wire * w, unsavedSet) m_savedItems.remove(w->id()); int count = 0; double left = std::numeric_limits::max(); double top = std::numeric_limits::max(); double right = std::numeric_limits::min(); double bottom = std::numeric_limits::min(); double hcTotal = 0; double vcTotal = 0; foreach (ItemBase * itemBase, m_savedItems) { QRectF r = itemBase->sceneBoundingRect(); if (r.left() < left) left = r.left(); if (r.right() > right) right = r.right(); if (r.top() < top) top = r.top(); if (r.bottom() > bottom) bottom = r.bottom(); count++; QPointF center = r.center(); hcTotal += center.x(); vcTotal += center.y(); } if (count < 2) return; hcTotal /= count; vcTotal /= count; if (m_moveEventCount == 0) { // first time m_moveDisconnectedFromFemale.clear(); foreach (ItemBase * item, m_savedItems) { if (item->itemType() == ModelPart::Wire) continue; //DebugDialog::debug(QString("disconnecting from female %1").arg(item->instanceTitle())); disconnectFromFemale(item, m_savedItems, m_moveDisconnectedFromFemale, false, rubberBandLegEnabled, NULL); } } foreach (ItemBase * itemBase, m_savedItems) { if (itemBase->itemType() == ModelPart::Wire) continue; QRectF r = itemBase->sceneBoundingRect(); QPointF dp; switch (alignment) { case Qt::AlignLeft: dp.setY(0); dp.setX(left - r.left()); break; case Qt::AlignHCenter: dp.setY(0); dp.setX(hcTotal - r.center().x()); break; case Qt::AlignRight: dp.setY(0); dp.setX(right - r.right()); break; case Qt::AlignTop: dp.setX(0); dp.setY(top - r.top()); break; case Qt::AlignVCenter: dp.setX(0); dp.setY(vcTotal - r.center().y()); break; case Qt::AlignBottom: dp.setX(0); dp.setY(bottom - r.bottom()); break; default: dp.setY(0); dp.setX(left - r.left()); break; } itemBase->setPos(itemBase->getViewGeometry().loc() + dp); foreach (ConnectorItem * connectorItem, m_stretchingLegs.values(itemBase)) { connectorItem->stretchBy(dp); } if (m_checkUnder.contains(itemBase)) { findConnectorsUnder(itemBase); } } foreach (Wire * wire, m_savedWires.keys()) { ConnectorItem * ci = m_savedWires.value(wire); wire->simpleConnectedMoved(ci); } foreach (Wire * w, unsaved.keys()) { foreach (ConnectorItem * end, unsaved.values(w)) { w->simpleConnectedMoved(end); m_savedWires.insert(w, end); } } //DebugDialog::debug(QString("done move items %1").arg(QTime::currentTime().msec()) ); if (m_infoView) { foreach (ItemBase * itemBase, m_savedItems) { m_infoView->updateLocation(itemBase->layerKinChief()); } } m_movingByArrow = false; m_moveEventCount++; checkMoved(false); m_savedItems.clear(); m_savedWires.clear(); } void SketchWidget::squashShapes(QPointF scenePos) { if (viewID() == ViewLayer::BreadboardView) return; unsquashShapes(); // topmost connectoritem // topmost wire // topmost shape // topmost ConnectorItem * connectorItem = NULL; Wire * wire = NULL; QList itms = scene()->items(scenePos); if (itms.count() <= 1) return; int ix = 0; for (; ix < itms.count(); ix++) { QGraphicsItem * item = itms.at(ix); connectorItem = dynamic_cast(item); if (connectorItem && connectorItem->acceptHoverEvents()) { ItemBase * itemBase = connectorItem->attachedTo(); if (itemBase->inactive()) continue; if (itemBase->hidden()) continue; if (itemBase->layerHidden()) continue; break; } wire = dynamic_cast(item); if (wire != NULL && wire->acceptHoverEvents() && !wire->inactive() && !wire->hidden() && !wire->layerHidden()) break; } if (ix == 0) { return; } if (wire == NULL && connectorItem == NULL) { int smallest = 0; double smallestArea = std::numeric_limits::max(); for (ix = 0; ix < itms.count(); ix++) { QGraphicsItem * item = itms.at(ix); ItemBase * itemBase = dynamic_cast(item); if (itemBase != NULL) { if (itemBase->hidden() || itemBase->layerHidden() || itemBase->inactive()) continue; QPainterPath painterPath = itemBase->mapToScene(itemBase->selectionShape()); if (painterPath.contains(scenePos)) { break; } double a = itemBase->boundingRect().width() * itemBase->boundingRect().height(); if (a < smallestArea) { smallest = ix; smallestArea = a; } } } if (ix == 0) return; // use the topmost if (ix >= itms.count()) { ix = smallest; } } if (ix == 0) { return; } bool firstTime = true; for (int i = 0; i < ix; i++) { ItemBase * itemBase = dynamic_cast(itms.at(i)); if (itemBase == NULL) continue; if (connectorItem != NULL && connectorItem->parentItem() == itemBase) { if (firstTime) { // topmost contains connectorItem return; } // itembase lower in the list owns the connectorItem break; } firstTime = false; itemBase->setSquashShape(true); m_squashShapes << itemBase; } } void SketchWidget::unsquashShapes() { foreach (ItemBase * itemBase, m_squashShapes) { if (itemBase) itemBase->setSquashShape(false); } m_squashShapes.clear(); } void SketchWidget::contextMenuEvent(QContextMenuEvent *event) { // this event does not occur within mousePressEvent() so squashshapes is not called twice squashShapes(mapToScene(event->pos())); InfoGraphicsView::contextMenuEvent(event); unsquashShapes(); } void SketchWidget::mouseDoubleClickEvent(QMouseEvent *event) { squashShapes(mapToScene(event->pos())); InfoGraphicsView::mouseDoubleClickEvent(event); unsquashShapes(); } bool SketchWidget::viewportEvent(QEvent *event) { if (event->type() == QEvent::ToolTip) { QHelpEvent * helpEvent = static_cast(event); squashShapes(mapToScene(helpEvent->pos())); } bool result = InfoGraphicsView::viewportEvent(event); if (event->type() == QEvent::ToolTip) { unsquashShapes(); } return result; } void SketchWidget::packItems(int columns, const QList & ids, QUndoCommand *parent, bool doEmit) { if (ids.count() < 2) return; QList itemBases; foreach (long id, ids) { ItemBase * itemBase = findItem(id); if (itemBase == NULL) return; itemBases << itemBase; itemBase->saveGeometry(); } QPointF initial = itemBases.at(0)->pos(); double top = initial.y(); QVector heights((ids.count() + columns - 1) / columns, 0); for (int i = 0; i < itemBases.count(); i++) { ItemBase * itemBase = itemBases.at(i); QRectF r = itemBase->sceneBoundingRect(); if (r.height() > heights.at(i / columns)) { heights[i / columns] = r.height(); } } double offset = 10; double left = 0; for (int i = 0; i < itemBases.count(); i++) { if (i % columns == 0) { left = initial.x(); } ItemBase * itemBase = itemBases.at(i); ViewGeometry vg1 = itemBase->getViewGeometry(); ViewGeometry vg2 = vg1; vg2.setLoc(QPointF(left, top)); new MoveItemCommand(this, itemBase->id(), vg1, vg2, true, parent); itemBase->setPos(left, top); left += itemBase->sceneBoundingRect().width() + offset; if (i % columns == columns - 1) { top += heights.at(i / columns) + offset; } } if (doEmit) { emit packItemsSignal(columns, ids, parent, false); } } QColor SketchWidget::gridColor() const { return m_gridColor; } void SketchWidget::setGridColor(QColor color) { m_gridColor = color; } bool SketchWidget::everZoomed() const { return m_everZoomed; } void SketchWidget::setEverZoomed(bool everZoomed) { m_everZoomed = everZoomed; } bool SketchWidget::updateOK(ConnectorItem *, ConnectorItem *) { return true; } void SketchWidget::testConnectors() { static const QString templateModuleID("generic_female_pin_header_1_100mil"); static QRectF templateBoundingRect; static QPointF templateOffset; QSet already; foreach (QGraphicsItem * item, scene()->selectedItems()) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; already.insert(itemBase->layerKinChief()); } if (already.count() == 0) return; ModelPart * templateModelPart = referenceModel()->genFZP(templateModuleID, referenceModel()); if (templateBoundingRect.isNull()) { long newID = ItemBase::getNextID(); ViewGeometry viewGeometry; ItemBase * templateItem = addItemAuxTemp(templateModelPart, ViewLayer::NewTop, viewGeometry, newID, true, viewID(), true); templateBoundingRect = templateItem->sceneBoundingRect(); QPointF templatePos = templateItem->cachedConnectorItems()[0]->sceneAdjustedTerminalPoint(NULL); templateOffset = templatePos - templateBoundingRect.topLeft(); foreach (ItemBase * kin, templateItem->layerKin()) delete kin; delete templateItem; } QUndoCommand * parentCommand = new QUndoCommand(tr("test connectors")); new CleanUpWiresCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::UndoOnly, parentCommand); foreach (ItemBase * itemBase, already) { QRectF sceneBoundingRect = itemBase->sceneBoundingRect(); QPointF center = sceneBoundingRect.center(); foreach (ConnectorItem * connectorItem, itemBase->cachedConnectorItems()) { QPointF fromPos = connectorItem->sceneAdjustedTerminalPoint(NULL); QPointF toPos = fromPos; double d[4]; d[0] = qAbs(fromPos.x() - sceneBoundingRect.left()); d[1] = qAbs(fromPos.x() - sceneBoundingRect.right()); d[2] = qAbs(fromPos.y() - sceneBoundingRect.top()); d[3] = qAbs(fromPos.y() - sceneBoundingRect.bottom()); int best = 0; for (int i = 1; i < 4; i++) { if (d[i] < d[best]) best = i; } switch (best) { case 0: // left toPos.setX(sceneBoundingRect.left() - (3 * templateBoundingRect.width())); break; case 1: // right toPos.setX(sceneBoundingRect.right() + (3 * templateBoundingRect.width())); break; case 2: // top toPos.setY(sceneBoundingRect.top() - (3 * templateBoundingRect.height())); break; case 3: // bottom toPos.setY(sceneBoundingRect.bottom() + (3 * templateBoundingRect.height())); break; } long newID = ItemBase::getNextID(); ViewGeometry vg; vg.setLoc(toPos - templateOffset); newAddItemCommand(BaseCommand::CrossView, templateModelPart, templateModelPart->moduleID(), itemBase->viewLayerPlacement(), vg, newID, true, -1, true, parentCommand); long wireID = ItemBase::getNextID(); ViewGeometry vgw; vgw.setLoc(fromPos); QLineF line(0, 0, toPos.x() - fromPos.x(), toPos.y() - fromPos.y()); vgw.setLine(line); vgw.setWireFlags(getTraceFlag()); new AddItemCommand(this, BaseCommand::CrossView, ModuleIDNames::WireModuleIDName, itemBase->viewLayerPlacement(), vgw, wireID, false, -1, parentCommand); new ChangeConnectionCommand(this, BaseCommand::CrossView, itemBase->id(), connectorItem->connectorSharedID(), wireID, "connector0", itemBase->viewLayerPlacement(), true, parentCommand); new ChangeConnectionCommand(this, BaseCommand::CrossView, newID, "connector0", wireID, "connector1", itemBase->viewLayerPlacement(), true, parentCommand); } } new CleanUpWiresCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); new CleanUpRatsnestsCommand(this, CleanUpWiresCommand::RedoOnly, parentCommand); m_undoStack->waitPush(parentCommand, PropChangeDelay); } void SketchWidget::updateWires() { QList already; ViewGeometry::WireFlag traceFlag = getTraceFlag(); foreach (QGraphicsItem * item, scene()->items()) { Wire * wire = dynamic_cast(item); if (wire == NULL) continue; if (!wire->isTraceType(traceFlag)) continue; ConnectorItem * from = wire->connector0()->firstConnectedToIsh(); if (from != NULL) wire->connectedMoved(from, wire->connector0(), already); ConnectorItem * to = wire->connector1()->firstConnectedToIsh(); if (to != NULL) wire->connectedMoved(to, wire->connector1(), already); } } void SketchWidget::viewGeometryConversionHack(ViewGeometry &, ModelPart *) { } fritzing-app-0.9.2b/src/sketch/sketchwidget.h000066400000000000000000001156601250202676700212240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6999 $: $Author: irascibl@gmail.com $: $Date: 2013-04-28 14:14:07 +0200 (So, 28. Apr 2013) $ ********************************************************************/ #ifndef SKETCHWIDGET_H #define SKETCHWIDGET_H #include #include #include #include #include #include #include #include #include #include "../items/paletteitem.h" #include "../referencemodel/referencemodel.h" #include "../model/sketchmodel.h" #include "../viewgeometry.h" #include "infographicsview.h" #include "../viewlayer.h" #include "../utils/misc.h" #include "../commands.h" struct ItemCount { int selCount; int hasLabelCount; int visLabelCount; int itemsCount; int selRotatable; int sel45Rotatable; int selHFlipable; int selVFlipable; int obsoleteCount; int moveLockCount; int wireCount; }; struct SwapThing { bool firstTime; long newID; ItemBase * itemBase; long newModelIndex; QString newModuleID; ViewLayer::ViewLayerPlacement viewLayerPlacement; QList wiresToDelete; QUndoCommand * parentCommand; QHash reconnections; QHash byWire; QHash toConnectorItems; QHash swappedGender; SketchWidget * bbView; QMap propsMap; }; struct RenderThing { bool selectedItems; double printerScale; bool blackOnly; QRectF imageRect; QRectF offsetRect; double dpi; bool renderBlocker; QRectF itemsBoundingRect; QGraphicsItem * board; bool empty; bool hideTerminalPoints; }; class SizeItem : public QObject, public QGraphicsLineItem { Q_OBJECT public: SizeItem(); ~SizeItem(); }; class SketchWidget : public InfoGraphicsView { Q_OBJECT Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor DESIGNABLE true) Q_PROPERTY(double ratsnestWidth READ ratsnestWidth WRITE setRatsnestWidth DESIGNABLE true) Q_PROPERTY(double ratsnestOpacity READ ratsnestOpacity WRITE setRatsnestOpacity DESIGNABLE true) public: SketchWidget(ViewLayer::ViewID, QWidget *parent=0, int size=400, int minSize=300); ~SketchWidget(); void pushCommand(QUndoCommand *, QObject * signalTarget); class WaitPushUndoStack * undoStack(); ItemBase * addItem(ModelPart *, ViewLayer::ViewLayerPlacement, BaseCommand::CrossViewType, const ViewGeometry &, long id, long modelIndex, AddDeleteItemCommand * originatingCommand); ItemBase * addItem(const QString & moduleID, ViewLayer::ViewLayerPlacement, BaseCommand::CrossViewType, const ViewGeometry &, long id, long modelIndex, AddDeleteItemCommand * originatingCommand); void deleteItem(long id, bool deleteModelPart, bool doEmit, bool later); virtual void deleteItem(ItemBase *, bool deleteModelPart, bool doEmit, bool later); void simpleMoveItem(long id, QPointF); void moveItem(long id, ViewGeometry &, bool updateRatsnest); void moveItem(long id, const QPointF & p, bool updateRatsnest); void updateWire(long id, const QString & connectorID, bool updateRatsnest); void rotateItem(long id, double degrees); void transformItem(long id, const QMatrix &); void flipItem(long id, Qt::Orientations orientation); void selectItem(long id, bool state, bool updateInfoView, bool doEmit); void selectItem(ItemBase * itemBase); void selectItems(QList); void selectItemsWithModuleID(ModelPart *); void addToSketch(QList &); void selectDeselectAllCommand(bool state); void changeWire(long fromID, QLineF line, QPointF pos, bool updateConnections, bool updateRatsnest); void changeLeg(long fromID, const QString & connectorID, const QPolygonF &, bool relative, const QString & why); void recalcLeg(long fromID, const QString & connectorID, const QPolygonF &, bool relative, bool active, const QString & why); void rotateLeg(long fromID, const QString & connectorID, const QPolygonF &, bool active); void cut(); void copy(); void setReferenceModel(class ReferenceModel *referenceModel); class ReferenceModel * referenceModel(); void setSketchModel(SketchModel *); void setUndoStack(class WaitPushUndoStack *); void clearSelection(); virtual void loadFromModelParts(QList & modelParts, BaseCommand::CrossViewType, QUndoCommand * parentCommand, bool offsetPaste, const QRectF * boundingRect, bool seekOutsideConnections, QList & newIDs); void changeZ(QHash, double (*pairAccessor)(RealPair *) ); void sendToBack(); void sendBackward(); void bringForward(); void bringToFront(); void alignItems(Qt::Alignment); double fitInWindow(); void rotateX(double degrees, bool rubberBandLegEnabled, ItemBase * originatingItem); void flipX(Qt::Orientations orientation, bool rubberBandLegEnabled); void addBendpoint(ItemBase * lastHoverEnterItem, ConnectorItem * lastHoverEnterConnectorItem, QPointF lastLocation); void flattenCurve(ItemBase * lastHoverEnterItem, ConnectorItem * lastHoverEnterConnectorItem, QPointF lastLocation); void deleteSelected(Wire *, bool minus); PaletteItem *getSelectedPart(); void addViewLayer(ViewLayer *); void setAllLayersVisible(bool visible); void setLayerVisible(ViewLayer * viewLayer, bool visible, bool doChildLayers); void setLayerVisible(ViewLayer::ViewLayerID viewLayerID, bool visible, bool doChildLayers); void setLayerActive(ViewLayer * viewLayer, bool active); void setLayerActive(ViewLayer::ViewLayerID viewLayerID, bool active); bool layerIsVisible(ViewLayer::ViewLayerID); bool layerIsActive(ViewLayer::ViewLayerID); void sortAnyByZ(const QList & items, QList & bases); void mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *); void setBackground(QColor); void setBackgroundColor(QColor, bool setPref); const QColor& background(); QColor standardBackground(); void setItemMenu(QMenu*); void setWireMenu(QMenu*); virtual void changeConnection(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, bool doEmit, bool updateConnections); ItemCount calcItemCount(); ViewLayer::ViewID viewID(); void setViewLayerIDs(ViewLayer::ViewLayerID part, ViewLayer::ViewLayerID wire, ViewLayer::ViewLayerID connector, ViewLayer::ViewLayerID ruler, ViewLayer::ViewLayerID note); void stickem(long stickTargetID, long stickSourceID, bool stick); void stickyScoop(ItemBase * stickyOne, bool checkCurrent, CheckStickyCommand *); void setChainDrag(bool); void hoverEnterItem(QGraphicsSceneHoverEvent * event, ItemBase * item); void hoverLeaveItem(QGraphicsSceneHoverEvent * event, ItemBase * item); void hoverEnterConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item); void hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * event, ConnectorItem * item); void cleanUpWires(bool doEmit, class CleanUpWiresCommand *); void partLabelChanged(ItemBase *, const QString & oldText, const QString &newtext); void noteChanged(ItemBase *, const QString & oldText, const QString &newtext, QSizeF oldSize, QSizeF newSize); void setInfoViewOnHover(bool infoViewOnHover); virtual ItemBase * addItemAux(ModelPart *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, bool doConnectors, ViewLayer::ViewID, bool temporary); ItemBase * addItemAuxTemp(ModelPart *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, bool doConnectors, ViewLayer::ViewID, bool temporary); bool swappingEnabled(ItemBase *); virtual void addViewLayers(); void changeWireColor(long wireId, const QString& color, double opacity); void changeWireWidth(long wireId, double width); void changeWireFlags(long wireId, ViewGeometry::WireFlags wireFlags); void setIgnoreSelectionChangeEvents(bool); void hideConnectors(bool hide); void saveLayerVisibility(); void restoreLayerVisibility(); void updateRoutingStatus(CleanUpWiresCommand*, RoutingStatus &, bool manual); void updateRoutingStatus(RoutingStatus &, bool manual); virtual bool hasAnyNets(); void ensureLayerVisible(ViewLayer::ViewLayerID); const QString &selectedModuleID(); virtual bool canDeleteItem(QGraphicsItem * item, int count); virtual bool canCopyItem(QGraphicsItem * item, int count); const QString & viewName(); void makeDeleteItemCommand(ItemBase * itemBase, BaseCommand::CrossViewType, QUndoCommand * parentCommand); virtual void forwardRoutingStatus(const RoutingStatus &); void collectParts(QList & partList); void movePartLabel(long itemID, QPointF newPos, QPointF newOffset); void updateInfoView(); virtual void setCurrent(bool current); void partLabelMoved(ItemBase *, QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset); void rotateFlipPartLabel(ItemBase *, double degrees, Qt::Orientations flipDirection); void rotateFlipPartLabel(long itemID, double degrees, Qt::Orientations flipDirection); void showPartLabels(bool show); void hidePartLabel(ItemBase * item); void noteSizeChanged(ItemBase * itemBase, const QSizeF & oldSize, const QSizeF & newSize); void resizeNote(long itemID, const QSizeF & ); class SelectItemCommand* stackSelectionState(bool pushIt, QUndoCommand * parentCommand); QString renderToSVG(RenderThing &, QGraphicsItem * board, const LayerList &); bool spaceBarIsPressed(); virtual long setUpSwap(SwapThing &, bool master); ConnectorItem * lastHoverEnterConnectorItem(); ItemBase * lastHoverEnterItem(); LayerHash & viewLayers(); virtual void createTrace(Wire*, bool useLastWireColor); virtual void selectAllWires(ViewGeometry::WireFlag); virtual void tidyWires(); const QString & getShortName(); virtual void setClipEnds(class ClipableWire *, bool); void getBendpointWidths(class Wire *, double w, double & w1, double & w2, bool & negativeOffsetRect); virtual bool includeSymbols(); void disconnectAll(); virtual bool canDisconnectAll(); virtual bool ignoreFemale(); virtual ViewLayer::ViewLayerID getWireViewLayerID(const ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); ItemBase * findItem(long id); long createWire(ConnectorItem * from, ConnectorItem * to, ViewGeometry::WireFlags, bool dontUpdate, BaseCommand::CrossViewType, QUndoCommand * parentCommand); QList selectAllObsolete(); int selectAllMoveLock(); void setMoveLock(long id, bool lock); bool partLabelsVisible(); void restorePartLabel(long itemID, QDomElement & element); void loadLogoImage(ItemBase *, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename, const QString & newFilename, bool addName); void loadLogoImage(long itemID, const QString & oldSvg, const QSizeF oldAspectRatio, const QString & oldFilename); void loadLogoImage(long itemID, const QString & newFilename, bool addName); void setNoteFocus(QGraphicsItem *, bool inFocus); void alignToGrid(bool); bool alignedToGrid(); void showGrid(bool); bool showingGrid(); void setGridSize(const QString &); QString gridSizeText(); void saveZoom(double); double retrieveZoom(); void initGrid(); virtual double defaultGridSizeInches(); void clearPasteOffset(); virtual ViewLayer::ViewLayerPlacement defaultViewLayerPlacement(ModelPart *); void collectAllNets(QHash & indexer, QList< QList* > & allPartConnectorItems, bool includeSingletons, bool bothSides); virtual bool routeBothSides(); virtual void changeLayer(long id, double z, ViewLayer::ViewLayerID viewLayerID); void ratsnestConnect(ConnectorItem * connectorItem, bool connect); void ratsnestConnect(ItemBase *, bool connect); void ratsnestConnect(ConnectorItem * c1, ConnectorItem * c2, bool connect, bool wait); virtual void addDefaultParts(); float getTopZ(); QGraphicsItem * addWatermark(const QString & filename); void copyHeart(QList & bases, bool saveBoundingRects, QByteArray & itemData, QList & modelIndexes); void pasteHeart(QByteArray & itemData, bool seekOutsideConnections); ViewGeometry::WireFlag getTraceFlag(); void changeBus(ItemBase *, bool connec, const QString & oldBus, const QString & newBus, QList &, const QString & message, const QString & oldLayout, const QString & newLayout); const QString & filenameIf(); void setItemDropOffset(long id, QPointF offset); void prepLegBendpointMove(ConnectorItem * from, int index, QPointF oldPos, QPointF newPos, ConnectorItem * to, bool changeConnections); void prepLegCurveChange(ConnectorItem * from, int index, const class Bezier * oldB, const class Bezier * newB, bool triggerFirstTime); void prepLegBendpointChange(ConnectorItem * from, int oldCount, int newCount, int index, QPointF pos, const class Bezier *, const class Bezier *, const class Bezier *, bool triggerFirstTime); void prepLegSelection(ItemBase *); void changeWireCurve(long id, const Bezier *, bool autoroutable); void changeLegCurve(long id, const QString & connectorID, int index, const Bezier *); void addLegBendpoint(long id, const QString & connectorID, int index, QPointF, const class Bezier *, const class Bezier *); void removeLegBendpoint(long id, const QString & connectorID, int index, const class Bezier *); void moveLegBendpoint(long id, const QString & connectorID, int index, QPointF); bool curvyWires(); void setCurvyWires(bool); bool curvyWiresIndicated(Qt::KeyboardModifiers); void triggerRotate(ItemBase *, double degrees); void makeWiresChangeConnectionCommands(const QList & wires, QUndoCommand * parentCommand); void renamePins(ItemBase *, const QStringList & oldLabels, const QStringList & newLabels, bool singleRow); void renamePins(long itemID, const QStringList & labels, bool singleRow); void getRatsnestColor(QColor &); VirtualWire * makeOneRatsnestWire(ConnectorItem * source, ConnectorItem * dest, bool routed, QColor color, bool force); double ratsnestOpacity(); void setRatsnestOpacity(double); double ratsnestWidth(); void setRatsnestWidth(double); void setAnyInRotation(); ConnectorItem * findConnectorItem(ConnectorItem * foreignConnectorItem); void setGroundFillSeed(long id, const QString & connectorID, bool seed); void setWireExtras(long id, QDomElement &); void resolveTemporary(bool, ItemBase *); virtual bool sameElectricalLayer2(ViewLayer::ViewLayerID, ViewLayer::ViewLayerID); void deleteMiddle(QSet & deletedItems, QUndoCommand * parentCommand); void setPasting(bool); void showUnrouted(); QPointF alignOneToGrid(ItemBase * itemBase); void showEvent(QShowEvent * event); void blockUI(bool); void viewItemInfo(ItemBase * item); virtual QHash getAutorouterSettings(); virtual void setAutorouterSettings(QHash &); void hidePartLayer(long id, ViewLayer::ViewLayerID, bool hide); void hidePartLayer(ItemBase *, ViewLayer::ViewLayerID, bool hide); void moveItem(ItemBase *, double x, double y); QColor gridColor() const; void setGridColor(QColor); bool everZoomed() const; void setEverZoomed(bool); void testConnectors(); void updateWires(); protected: void dragEnterEvent(QDragEnterEvent *); bool dragEnterEventAux(QDragEnterEvent *); virtual bool canDropModelPart(ModelPart *); void dragLeaveEvent(QDragLeaveEvent *); void dragMoveEvent(QDragMoveEvent *); void dropEvent(QDropEvent *); virtual void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseDoubleClickEvent (QMouseEvent *); void contextMenuEvent(QContextMenuEvent *); bool viewportEvent(QEvent *); void paintEvent(QPaintEvent *); virtual PaletteItem* addPartItem(ModelPart * , ViewLayer::ViewLayerPlacement, PaletteItem *, bool doConnectors, bool & ok, ViewLayer::ViewID, bool temporary); void clearHoldingSelectItem(); bool startZChange(QList & bases); void continueZChange(QList & bases, int start, int end, bool (*test)(int current, int start), int inc, const QString & text); void continueZChangeMax(QList & bases, int start, int end, bool (*test)(int current, int start), int inc, const QString & text); void continueZChangeAux(QList & bases, const QString & text); virtual ViewLayer::ViewLayerID getDragWireViewLayerID(ConnectorItem *); ViewLayer::ViewLayerID getPartViewLayerID(); ViewLayer::ViewLayerID getRulerViewLayerID(); ViewLayer::ViewLayerID getConnectorViewLayerID(); virtual ViewLayer::ViewLayerID getLabelViewLayerID(ItemBase *); ViewLayer::ViewLayerID getNoteViewLayerID(); void dragMoveHighlightConnector(QPoint eventPos); void addToScene(ItemBase * item, ViewLayer::ViewLayerID viewLayerID); ConnectorItem * findConnectorItem(ItemBase * item, const QString & connectorID, ViewLayer::ViewLayerPlacement); bool checkMoved(bool wait); void changeConnectionAux(long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, bool updateConnections); void cutDeleteAux(QString undoStackMessage, bool minus, Wire * wire); void deleteAux(QSet & deletedItems, QUndoCommand * parentCommand, bool doPush); ChangeConnectionCommand * extendChangeConnectionCommand(BaseCommand::CrossViewType, long fromID, const QString & fromConnectorID, long toID, const QString & toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, QUndoCommand * parent); ChangeConnectionCommand * extendChangeConnectionCommand(BaseCommand::CrossViewType, ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, ViewLayer::ViewLayerPlacement, bool connect, QUndoCommand * parentCommand); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); void clearTemporaries(); void dragWireChanged(class Wire* wire, ConnectorItem * from, ConnectorItem * to); void dragRatsnestChanged(); void killDroppingItem(); ViewLayer::ViewLayerID getViewLayerID(ModelPart *, ViewLayer::ViewID, ViewLayer::ViewLayerPlacement); ItemBase * overSticky(ItemBase *); virtual void setNewPartVisible(ItemBase *); virtual bool collectFemaleConnectees(ItemBase *, QSet &); virtual bool checkUnder(); virtual void findConnectorsUnder(ItemBase * item); bool currentlyInfoviewed(ItemBase *item); void resizeEvent(QResizeEvent *); void addViewLayersAux(const LayerList &, const LayerList & layersFromBelow, float startZ = 1.5); virtual bool disconnectFromFemale(ItemBase * item, QHash & savedItems, ConnectorPairHash &, bool doCommand, bool rubberBandLegEnabled, QUndoCommand * parentCommand); void clearDragWireTempCommand(); bool draggingWireEnd(); void moveItems(QPoint globalPos, bool checkAutoScroll, bool rubberBandLegEnabled); virtual ViewLayer::ViewLayerID multiLayerGetViewLayerID(ModelPart * modelPart, ViewLayer::ViewID, ViewLayer::ViewLayerPlacement, LayerList &); virtual BaseCommand::CrossViewType wireSplitCrossView(); virtual bool canChainMultiple(); virtual bool canChainWire(Wire *); virtual bool canDragWire(Wire *); virtual bool canCreateWire(Wire * dragWire, ConnectorItem * from, ConnectorItem * to); //virtual bool modifyNewWireConnections(Wire * dragWire, ConnectorItem * fromOnWire, ConnectorItem * from, ConnectorItem * to, QUndoCommand * parentCommand); virtual void setUpColor(ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Wire * wire, QUndoCommand * parentCommand); void setupAutoscroll(bool moving); void turnOffAutoscroll(); bool checkAutoscroll(QPoint globalPos); virtual void setWireVisible(Wire *); bool matchesLayer(ModelPart * modelPart); QByteArray removeOutsideConnections(const QByteArray & itemData, QList & modelIndexes); void addWireExtras(long newID, QDomElement & view, QUndoCommand * parentCommand); virtual const QString & hoverEnterWireConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item); virtual const QString & hoverEnterPartConnectorMessage(QGraphicsSceneHoverEvent * event, ConnectorItem * item); void partLabelChangedAux(ItemBase * pitem,const QString & oldText, const QString &newText); void drawBackground( QPainter * painter, const QRectF & rect ); void handleConnect(QDomElement & connect, ModelPart *, const QString & fromConnectorID, ViewLayer::ViewLayerID, QStringList & alreadyConnected, QHash & newItems, QUndoCommand * parentCommand, bool seekOutsideConnections); void setUpSwapReconnect(SwapThing &, ItemBase * itemBase, long newID, bool master); void makeSwapWire(SketchWidget *, ItemBase *, long newID, ConnectorItem * fromConnectorItem, ConnectorItem * toConnectorItem, Connector * newConnector, QUndoCommand * parentCommand); bool swappedGender(ConnectorItem * originalConnectorItem, Connector * newConnector); void setLastPaletteItemSelected(PaletteItem * paletteItem); void setLastPaletteItemSelectedIf(ItemBase * itemBase); void prepDragBendpoint(Wire *, QPoint eventPos, bool dragCurve); void prepDragWire(Wire *); void clickBackground(QMouseEvent *); void categorizeDragWires(QSet & wires, QList & freeWires); void categorizeDragLegs(bool rubberBandLegEnabled); void prepMove(ItemBase * originatingItem, bool rubberBandLegEnabled, bool includeRatsnest); void initBackgroundColor(); QPointF calcNewLoc(ItemBase * moveBase, ItemBase * detachFrom); long findPartOrWire(long itemID); AddItemCommand * newAddItemCommand(BaseCommand::CrossViewType crossViewType, ModelPart *, QString moduleID, ViewLayer::ViewLayerPlacement, ViewGeometry & viewGeometry, qint64 id, bool updateInfoView, long modelIndex, bool addSubparts, QUndoCommand *parent); int selectAllItems(QSet & itemBases, const QString & msg); bool moveByArrow(double dx, double dy, QKeyEvent * ); double gridSizeInches(); virtual bool canAlignToTopLeft(ItemBase *); virtual bool canAlignToCenter(ItemBase *); virtual void findAlignmentAnchor(ItemBase * originatingItem, QHash & savedItems, QHash & savedWires); void alignLoc(QPointF & loc, const QPointF startPoint, const QPointF newLoc, const QPointF originalLoc); void copyAux(QList & bases, bool saveBoundingRects); void copyDrop(); void dropItemEvent(QDropEvent *event); virtual QString checkDroppedModuleID(const QString & moduleID); QString makeWireSVG(Wire * wire, QPointF offset, double dpi, double printerscale, bool blackOnly); QString makeWireSVGAux(Wire * wire, double width, const QString & color, QPointF offset, double dpi, double printerScale, bool blackOnly, bool dashed); QString makeMoveSVG(double printerScale, double dpi, QPointF & offset); void prepDeleteProps(ItemBase * itemBase, long id, const QString & newModuleID, QMap & propsMap, QUndoCommand * parentCommand); void prepDeleteOtherProps(ItemBase * itemBase, long id, const QString & newModuleID, QMap & propsMap, QUndoCommand * parentCommand); virtual ViewLayer::ViewLayerPlacement getViewLayerPlacement(ModelPart *, QDomElement & instance, QDomElement & view, ViewGeometry &); virtual ViewLayer::ViewLayerPlacement wireViewLayerPlacement(ConnectorItem *); virtual bool resizingJumperItemPress(ItemBase *); virtual bool resizingJumperItemRelease(); bool resizingBoardPress(ItemBase *); bool resizingBoardRelease(); void resizeBoard(); void resizeWithHandle(ItemBase * itemBase, double mmW, double mmH); virtual bool acceptsTrace(const ViewGeometry &); virtual ItemBase * placePartDroppedInOtherView(ModelPart *, ViewLayer::ViewLayerPlacement, const ViewGeometry & viewGeometry, long id, SketchWidget * dropOrigin); void showPartLabelsAux(bool show, QList & itemBases); virtual void extraRenderSvgStep(ItemBase *, QPointF offset, double dpi, double printerScale, QString & outputSvg); virtual ViewLayer::ViewLayerPlacement createWireViewLayerPlacement(ConnectorItem * from, ConnectorItem * to); virtual Wire * createTempWireForDragging(Wire * fromWire, ModelPart * wireModel, ConnectorItem * connectorItem, ViewGeometry & viewGeometry, ViewLayer::ViewLayerPlacement); virtual void prereleaseTempWireForDragging(Wire*); void checkFit(ModelPart * newModelPart, ItemBase * itemBase, long newID, QHash & found, QList & notFound, QHash & m2f, QHash & byWire, QHash & legs, QHash & formerLegs, QUndoCommand * parentCommand); void checkFitAux(ItemBase * tempItemBase, ItemBase * itemBase, long newID, QHash & found, QList & notFound, QHash & m2f, QHash & byWire, QHash & legs, QHash & formerLegs, QUndoCommand * parentCommand); void changeLegAux(long fromID, const QString & fromConnectorID, const QPolygonF &, bool reset, bool relative, bool active, const QString & why); void moveLegBendpoints(bool undoOnly, QUndoCommand * parentCommand); void moveLegBendpointsAux(ConnectorItem * connectorItem, bool undoOnly, QUndoCommand * parentCommand); virtual void rotatePartLabels(double degrees, QTransform &, QPointF center, QUndoCommand * parentCommand); bool checkUpdateRatsnest(QList & connectorItems); void makeRatsnestViewGeometry(ViewGeometry & viewGeometry, ConnectorItem * source, ConnectorItem * dest); virtual double getTraceWidth(); virtual const QString & traceColor(ViewLayer::ViewLayerPlacement); void createTrace(Wire * fromWire, const QString & commandString, ViewGeometry::WireFlag, bool useLastWireColor); bool createOneTrace(Wire * wire, ViewGeometry::WireFlag flag, bool allowAny, QList & done, bool useLastWireColor, QUndoCommand * parentCommand); void removeWire(Wire * w, QList & ends, QList & done, QUndoCommand * parentCommand); void selectAllWiresFrom(ViewGeometry::WireFlag flag, QList & items); bool canConnect(ItemBase * from, ItemBase * to); virtual bool canConnect(Wire * from, ItemBase * to); void removeDragWire(); QGraphicsItem * getClickedItem(QList & items); void cleanupRatsnests(QList< QPointer > & connectorItems, bool connect); void rotateWire(Wire *, QTransform & rotation, QPointF center, bool undoOnly, QUndoCommand * parentCommand); QString renderToSVG(RenderThing &, const LayerList &); QString renderToSVG(RenderThing &, QList & itemsAndLabels); QList collectSuperSubs(ItemBase *); void squashShapes(QPointF scenePos); void unsquashShapes(); virtual bool updateOK(ConnectorItem *, ConnectorItem *); virtual void viewGeometryConversionHack(ViewGeometry &, ModelPart *); protected: static bool lessThan(int a, int b); static bool greaterThan(int a, int b); signals: void itemAddedSignal(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, SketchWidget * dropOrigin); void itemDeletedSignal(long id); void clearSelectionSignal(); void itemSelectedSignal(long id, bool state); void itemMovedSignal(ItemBase *); void wireDisconnectedSignal(long fromID, QString fromConnectorID); void wireConnectedSignal(long fromID, QString fromConnectorID, long toID, QString toConnectorID); void changeConnectionSignal(long fromID, QString fromConnectorID, long toID, QString toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, bool updateConnections); void copyBoundingRectsSignal(QHash &); void cleanUpWiresSignal(CleanUpWiresCommand *); void selectionChangedSignal(); void resizeSignal(); void dropSignal(const QPoint &pos); void routingStatusSignal(SketchWidget *, const RoutingStatus &); void movingSignal(SketchWidget *, QUndoCommand * parentCommand); void selectAllItemsSignal(bool state, bool doEmit); void checkStickySignal(long id, bool doEmit, bool checkCurrent, CheckStickyCommand *); void disconnectAllSignal(QList, QHash & itemsToDelete, QUndoCommand * parentCommand); void setResistanceSignal(long itemID, QString resistance, QString pinSpacing, bool doEmit); void setPropSignal(long itemID, const QString & prop, const QString & value, bool doRedraw, bool doEmit); void setInstanceTitleSignal(long id, const QString & oldTitle, const QString & newTitle, bool isUndoable, bool doEmit); void statusMessageSignal(QString, int timeout); void showLabelFirstTimeSignal(long itemID, bool show, bool doEmit); void dropPasteSignal(SketchWidget *); void changeBoardLayersSignal(int, bool doEmit); void deleteTracesSignal(QSet & deletedItems, QHash & otherDeletedItems, QList & deletedIDs, bool isForeign, QUndoCommand * parentCommand); void makeDeleteItemCommandPrepSignal(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand); void makeDeleteItemCommandFinalSignal(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand); void cursorLocationSignal(double xinches, double yinches, double width=0.0, double height=0.0); void ratsnestConnectSignal(long id, const QString & connectorID, bool connect, bool doEmit); void updatePartLabelInstanceTitleSignal(long itemID); void filenameIfSignal(QString & filename); void collectRatsnestSignal(QList & foreignSketchWidgets); void removeRatsnestSignal(QList & cutSet, QUndoCommand * parentCommand); void updateLayerMenuSignal(); void swapBoardImageSignal(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName); void canConnectSignal(Wire * from, ItemBase * to, bool & connect); void swapStartSignal(SwapThing & swapThing, bool master); void showing(SketchWidget *); void clickedItemCandidateSignal(QGraphicsItem *, bool & ok); void resizedSignal(ItemBase *); void cleanupRatsnestsSignal(bool doEmit); void addSubpartSignal(long id, long subpartID, bool doEmit); void getDroppedItemViewLayerPlacementSignal(ModelPart * modelPart, ViewLayer::ViewLayerPlacement &); void packItemsSignal(int columns, const QList & ids, QUndoCommand *parent, bool doEmit); protected slots: void itemAddedSlot(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long id, SketchWidget * dropOrigin); void itemDeletedSlot(long id); void clearSelectionSlot(); void itemSelectedSlot(long id, bool state); void selectionChangedSlot(); void wireChangedSlot(class Wire*, const QLineF & oldLine, const QLineF & newLine, QPointF oldPos, QPointF newPos, ConnectorItem * from, ConnectorItem * to); void wireChangedCurveSlot(class Wire*, const Bezier * oldB, const Bezier * newB, bool triggerFirstTime); virtual void wireSplitSlot(class Wire*, QPointF newPos, QPointF oldPos, const QLineF & oldLine); void wireJoinSlot(class Wire*, ConnectorItem * clickedConnectorItem); void toggleLayerVisibility(); void wireConnectedSlot(long fromID, QString fromConnectorID, long toID, QString toConnectorID); void wireDisconnectedSlot(long fromID, QString fromConnectorID); void changeConnectionSlot(long fromID, QString fromConnectorID, long toID, QString toConnectorID, ViewLayer::ViewLayerPlacement, bool connect, bool updateConnections); void restartPasteCount(); void dragIsDoneSlot(class ItemDrag *); void statusMessage(QString message, int timeout = 0); void cleanUpWiresSlot(CleanUpWiresCommand *); void updateInfoViewSlot(); void spaceBarIsPressedSlot(bool); void autoScrollTimeout(); void dragAutoScrollTimeout(); void moveAutoScrollTimeout(); void rememberSticky(long id, QUndoCommand * parentCommand); void rememberSticky(ItemBase *, QUndoCommand * parentCommand); void copyBoundingRectsSlot(QHash &); void deleteRatsnest(Wire *, QUndoCommand * parentCommand); void deleteTracesSlot(QSet & deletedItems, QHash & otherDeletedItems, QList & deletedIDs, bool isForeign, QUndoCommand * parentCommand); void vScrollToZero(); void arrowTimerTimeout(); void makeDeleteItemCommandPrepSlot(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand); void makeDeleteItemCommandFinalSlot(ItemBase * itemBase, bool foreign, QUndoCommand * parentCommand); void updatePartLabelInstanceTitleSlot(long itemID); void changePinLabelsSlot(ItemBase * itemBase, bool singleRow); void changePinLabels(ItemBase *, bool singleRow); void collectRatsnestSlot(QList & foreignSketchWidgets); void removeRatsnestSlot(QList & cutSet, QUndoCommand * parentCommand); void deleteTemporary(); void canConnect(Wire * from, ItemBase * to, bool & connect); long swapStart(SwapThing & swapThing, bool master); virtual void getDroppedItemViewLayerPlacement(ModelPart * modelPart, ViewLayer::ViewLayerPlacement &); public slots: void changeWireColor(const QString newColor); void changeWireWidthMils(const QString newWidth); void selectAllItems(bool state, bool doEmit); void setNoteText(long itemID, const QString & newText); void setInstanceTitle(long id, const QString & oldTitle, const QString & newTitle, bool isUndoable, bool doEmit); void incInstanceTitle(long id); void showPartLabel(long id, bool showIt); void checkSticky(long id, bool doEmit, bool checkCurrent, CheckStickyCommand *); virtual ItemBase * resizeBoard(long id, double w, double h); void resizeJumperItem(long id, QPointF pos, QPointF c0, QPointF c1); void disconnectAllSlot(QList, QHash & itemsToDelete, QUndoCommand * parentCommand); void setResistance(long itemID, QString resistance, QString pinSpacing, bool doEmit); void setResistance(QString resistance, QString pinSpacing); void setProp(long itemID, const QString & prop, const QString & value, bool redraw, bool doEmit); virtual void setProp(ItemBase *, const QString & propName, const QString & translatedPropName, const QString & oldValue, const QString & newValue, bool redraw); void setHoleSize(ItemBase *, const QString & propName, const QString & translatedPropName, const QString & oldValue, const QString & newValue, QRectF & oldRect, QRectF & newRect, bool redraw); virtual void showLabelFirstTime(long itemID, bool show, bool doEmit); void resizeBoard(double w, double h, bool doEmit); virtual void changeBoardLayers(int layers, bool doEmit); void updateConnectors(); void ratsnestConnect(long id, const QString & connectorID, bool connect, bool doEmit); void cleanupRatsnests(bool doEmit); void addSubpart(long id, long subpartid, bool doEmit); void packItems(int columns, const QList & ids, QUndoCommand *parent, bool doEmit); protected: enum StatusConnectStatus { StatusConnectNotTried, StatusConnectSucceeded, StatusConnectFailed }; protected: QPointer m_referenceModel; QPointer m_sketchModel; ViewLayer::ViewID m_viewID; class WaitPushUndoStack * m_undoStack; class SelectItemCommand * m_holdingSelectItemCommand; class SelectItemCommand * m_tempDragWireCommand; LayerHash m_viewLayers; QHash m_viewLayerVisibility; QPointer m_connectorDragWire; QPointer m_bendpointWire; ViewGeometry m_bendpointVG; QPointer m_connectorDragConnector; bool m_droppingWire; QPointF m_droppingOffset; QPointer m_droppingItem; int m_moveEventCount; //QList m_lastSelected; hack for 4.5.something ViewLayer::ViewLayerID m_wireViewLayerID; ViewLayer::ViewLayerID m_partViewLayerID; ViewLayer::ViewLayerID m_rulerViewLayerID; ViewLayer::ViewLayerID m_connectorViewLayerID; ViewLayer::ViewLayerID m_noteViewLayerID; QList m_temporaries; bool m_chainDrag; QPointF m_mousePressScenePos; QPointF m_mousePressGlobalPos; QTimer m_autoScrollTimer; volatile int m_autoScrollX; volatile int m_autoScrollY; volatile int m_autoScrollCount; QPoint m_globalPos; QPointer m_lastPaletteItemSelected; int m_pasteCount; QPointF m_pasteOffset; // Part Menu QMenu *m_itemMenu; QMenu *m_wireMenu; bool m_infoViewOnHover; QHash m_savedItems; QHash m_savedWires; QList m_additionalSavedItems; int m_ignoreSelectionChangeEvents; bool m_current; QString m_lastColorSelected; ConnectorPairHash m_moveDisconnectedFromFemale; bool m_spaceBarIsPressed; bool m_spaceBarWasPressed; QPointer m_lastHoverEnterConnectorItem; QPointer m_lastHoverEnterItem; QString m_shortName; QPointer m_dragBendpointWire; bool m_dragCurve; QPoint m_dragBendpointPos; StatusConnectStatus m_statusConnectState; QList m_inFocus; QString m_viewName; bool m_movingByArrow; double m_arrowTotalX; double m_arrowTotalY; bool m_movingByMouse; bool m_alignToGrid; bool m_showGrid; double m_gridSizeInches; QString m_gridSizeText; QPointer m_alignmentItem; QPointer m_originatingItem; QPointF m_alignmentStartPoint; double m_zoom; bool m_draggingBendpoint; QPointer m_sizeItem; int m_autoScrollThreshold; bool m_clearSceneRect; QPointer m_moveReferenceItem; QPointer m_movingSVGRenderer; QPointF m_movingSVGOffset; QPointer m_movingItem; QList< QPointer > m_ratsnestUpdateDisconnect; QList< QPointer > m_ratsnestUpdateConnect; QList< QPointer > m_ratsnestCacheDisconnect; QList< QPointer > m_ratsnestCacheConnect; QList m_checkUnder; bool m_addDefaultParts; QPointer m_addedDefaultPart; float m_z; QTimer m_arrowTimer; bool m_middleMouseIsPressed; QMultiHash m_stretchingLegs; bool m_curvyWires; bool m_rubberBandLegWasEnabled; RoutingStatus m_routingStatus; bool m_anyInRotation; bool m_pasting; QPointer m_resizingBoard; QList< QPointer > m_squashShapes; QColor m_gridColor; bool m_everZoomed; double m_ratsnestOpacity; double m_ratsnestWidth; public: static ViewLayer::ViewLayerID defaultConnectorLayer(ViewLayer::ViewID viewId); static const int PropChangeDelay; static bool m_blockUI; protected: static const int MoveAutoScrollThreshold; static const int DragAutoScrollThreshold; }; #endif fritzing-app-0.9.2b/src/sketch/welcomeview.cpp000066400000000000000000001115571250202676700214210ustar00rootroot00000000000000/********************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "welcomeview.h" #include "../debugdialog.h" #include "../help/tipsandtricks.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////// static const int TitleRole = Qt::UserRole; static const int IntroRole = Qt::UserRole + 1; static const int DateRole = Qt::UserRole + 2; static const int AuthorRole = Qt::UserRole + 3; static const int IconRole = Qt::UserRole + 4; static const int RefRole = Qt::UserRole + 5; static const int ImageSpace = 65; static const int TopSpace = 5; QString WelcomeView::m_activeHeaderLabelColor = "#333"; QString WelcomeView::m_inactiveHeaderLabelColor = "#b1b1b1"; /////////////////////////////////////////////////////////////////////////////// void zeroMargin(QLayout * layout) { layout->setMargin(0); layout->setSpacing(0); } QString makeUrlText(const QString & url, const QString & urlText, const QString & color) { return QString("%2").arg(url).arg(urlText).arg(color); } QString hackColor(QString oldText, const QString & color) { QRegExp colorFinder("color:(#[^;]*);"); int ix = oldText.indexOf(colorFinder); if (ix >= 0) { oldText.replace(colorFinder.cap(1), color); } return oldText; } int pixelSize(const QString & sizeString) { // assume all sizes are of the form Npx otherwise return -1 QString temp = sizeString; temp.remove(" "); if (temp.contains("px")) { temp.remove("px"); bool ok; int ps = temp.toInt(&ok); if (ok) return ps; } return -1; } QString cleanData(const QString & data) { static QRegExp ListItemMatcher("

  • .*
  • "); ListItemMatcher.setMinimal(true); // equivalent of lazy matcher QDomDocument doc; QStringList listItems; int pos = 0; while (pos < data.count()) { int ix = data.indexOf(ListItemMatcher, pos); if (ix < 0) break; QString listItem = ListItemMatcher.cap(0); //DebugDialog::debug("ListItem " + listItem); if (doc.setContent(listItem)) { listItems << listItem; } pos += listItem.count(); } return listItems.join(""); } //////////////////////////////////////////////////////////////////////////////// BlogListWidget::BlogListWidget(QWidget * parent) : QListWidget(parent) { connect(this, SIGNAL(itemEntered(QListWidgetItem *)), this, SLOT(itemEnteredSlot(QListWidgetItem *))); } BlogListWidget::~BlogListWidget() { } QStringList & BlogListWidget::imageRequestList() { return m_imageRequestList; } /* blogEntry Title text properties color, fontfamily, fontsize*/ QColor BlogListWidget::titleTextColor() const { return m_titleTextColor; } void BlogListWidget::setTitleTextColor(QColor color) { m_titleTextColor = color; } QString BlogListWidget::titleTextFontFamily() const { return m_titleTextFontFamily; } void BlogListWidget::setTitleTextFontFamily(QString family) { m_titleTextFontFamily = family; } QString BlogListWidget::titleTextFontSize() const { return m_titleTextFontSize; } void BlogListWidget::setTitleTextFontSize(QString size) { m_titleTextFontSize = size; } QString BlogListWidget::titleTextExtraLeading() const { return m_titleTextExtraLeading; } void BlogListWidget::setTitleTextExtraLeading(QString leading) { m_titleTextExtraLeading = leading; } /* blogEntry intro text properties color, fontfamily, fontsize*/ QColor BlogListWidget::introTextColor() const { return m_introTextColor; } void BlogListWidget::setIntroTextColor(QColor color) { m_introTextColor = color; } QString BlogListWidget::introTextFontFamily() const { return m_introTextFontFamily; } void BlogListWidget::setIntroTextFontFamily(QString family) { m_introTextFontFamily = family; } QString BlogListWidget::introTextFontSize() const { return m_introTextFontSize; } void BlogListWidget::setIntroTextFontSize(QString size) { m_introTextFontSize = size; } QString BlogListWidget::introTextExtraLeading() const { return m_introTextExtraLeading; } void BlogListWidget::setIntroTextExtraLeading(QString leading) { m_introTextExtraLeading = leading; } /* blogEntry Date text properties color, fontfamily, fontsize*/ QColor BlogListWidget::dateTextColor() const { return m_dateTextColor; } void BlogListWidget::setDateTextColor(QColor color) { m_dateTextColor = color; } QString BlogListWidget::dateTextFontFamily() const { return m_dateTextFontFamily; } void BlogListWidget::setDateTextFontFamily(QString family) { m_dateTextFontFamily = family; } QString BlogListWidget::dateTextFontSize() const { return m_dateTextFontSize; } void BlogListWidget::setDateTextFontSize(QString size) { m_dateTextFontSize = size; } void BlogListWidget::itemEnteredSlot(QListWidgetItem * item) { QString url = item->data(RefRole).toString(); bool arrow = (url.isEmpty()) || (url == "nop"); setCursor(arrow ? Qt::ArrowCursor : Qt::PointingHandCursor); } //////////////////////////////////////////////////////////////////////////////// BlogListDelegate::BlogListDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } BlogListDelegate::~BlogListDelegate() { } void BlogListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { BlogListWidget * listWidget = qobject_cast(this->parent()); if (listWidget == NULL) return; QStyle * style = listWidget->style(); if (style == NULL) return; painter->save(); QFont itemFont(painter->font()); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, listWidget); QPixmap pixmap = qvariant_cast(index.data(IconRole)); QString title = index.data(TitleRole).toString(); QString date = index.data(DateRole).toString(); QString author = index.data(AuthorRole).toString(); QString intro = index.data(IntroRole).toString(); // QRect rect; int imageSpace = ImageSpace + 10; // TITLE painter->setPen(listWidget->titleTextColor()); QFont titleFont(listWidget->titleTextFontFamily()); titleFont.setPixelSize(pixelSize(listWidget->titleTextFontSize())); painter->setFont(titleFont); QRect rect = option.rect.adjusted(imageSpace, TopSpace, 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, title); QFontMetrics titleFontMetrics(titleFont); // INTRO painter->setPen(listWidget->introTextColor()); QFont introFont(listWidget->introTextFontFamily()); introFont.setPixelSize(pixelSize(listWidget->introTextFontSize())); painter->setFont(introFont); rect = option.rect.adjusted(imageSpace, TopSpace + titleFontMetrics.lineSpacing() + pixelSize(listWidget->titleTextExtraLeading()) , 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, intro); QFontMetrics introFontMetrics(introFont); // DATE painter->setPen(listWidget->dateTextColor()); QFont font(listWidget->dateTextFontFamily()); font.setPixelSize(pixelSize(listWidget->dateTextFontSize())); painter->setFont(font); rect = option.rect.adjusted(imageSpace, TopSpace + titleFontMetrics.lineSpacing() + introFontMetrics.lineSpacing() + pixelSize(listWidget->introTextExtraLeading()), 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, date); QFontMetrics dateTextFontMetrics(font); // AUTHOR QRect textRect = style->itemTextRect(dateTextFontMetrics, option.rect, Qt::AlignLeft, true, date); rect = option.rect.adjusted(imageSpace + textRect.width() + 7, TopSpace + titleFontMetrics.lineSpacing() + introFontMetrics.lineSpacing() + pixelSize(listWidget->introTextExtraLeading()), 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, author); if (!pixmap.isNull()) { //ic.paint(painter, option.rect, Qt::AlignVCenter|Qt::AlignLeft); style->drawItemPixmap(painter, option.rect.adjusted(0, TopSpace, 0, -TopSpace), Qt::AlignLeft, pixmap); } painter->restore(); } QSize BlogListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const { return QSize(100, ImageSpace); // very dumb value } ////////////////////////////////////// WelcomeView::WelcomeView(QWidget * parent) : QFrame(parent) { this->setObjectName("welcomeView"); m_tip = NULL; setAcceptDrops(true); initLayout(); connect(this, SIGNAL(newSketch()), this->window(), SLOT(createNewSketch())); connect(this, SIGNAL(openSketch()), this->window(), SLOT(mainLoad())); connect(this, SIGNAL(recentSketch(const QString &, const QString &)), this->window(), SLOT(openRecentOrExampleFile(const QString &, const QString &))); // TODO: blog network calls should only happen once, not for each window? QNetworkAccessManager * manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(gotBlogSnippet(QNetworkReply *))); manager->get(QNetworkRequest(QUrl("http://blog.fritzing.org/recent-posts-app/"))); manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(gotBlogSnippet(QNetworkReply *))); manager->get(QNetworkRequest(QUrl("http://fritzing.org/projects/snippet/"))); TipsAndTricks::initTipSets(); nextTip(); } WelcomeView::~WelcomeView() { } void WelcomeView::initLayout() { QGridLayout * mainLayout = new QGridLayout(); //mainLayout->setSpacing (0); //mainLayout->setContentsMargins (0, 0, 0, 0); mainLayout->setSizeConstraint (QLayout::SetMaximumSize); QWidget * recent = initRecent(); mainLayout->addWidget(recent, 0, 0); QWidget * widget = initBlog(); mainLayout->addWidget(widget, 0, 1); widget = initShop(); mainLayout->addWidget(widget, 1, 1); widget = initTip(); mainLayout->addWidget(widget, 1, 0); this->setLayout(mainLayout); } QWidget * WelcomeView::initRecent() { QFrame * frame = new QFrame; frame->setObjectName("recentFrame"); QVBoxLayout * frameLayout = new QVBoxLayout; zeroMargin(frameLayout); QFrame * titleFrame = new QFrame; titleFrame-> setObjectName("recentTitleFrame"); QHBoxLayout * titleFrameLayout = new QHBoxLayout; zeroMargin(titleFrameLayout); QLabel * label = new QLabel(tr("Recent Sketches")); label->setObjectName("recentTitle"); titleFrameLayout->addWidget(label); titleFrame ->setLayout(titleFrameLayout); frameLayout->addWidget(titleFrame); m_recentListWidget = new QListWidget(); m_recentListWidget->setObjectName("recentList"); m_recentListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); connect(m_recentListWidget, SIGNAL(itemClicked (QListWidgetItem *)), this, SLOT(recentItemClicked(QListWidgetItem *))); frameLayout->addWidget(m_recentListWidget); QStringList names; names << "recentSpace" << "recentNewSketch" << "recentOpenSketch"; foreach (QString name, names) { QWidget * widget = NULL; QLayout * whichLayout = frameLayout; QLabel * icon = NULL; QLabel * text = NULL; if (name == "recentSpace") { widget = new QLabel(); } else if (name == "recentTitleSpace") { widget = new QLabel(); } else if (name == "recentNewSketch") { widget = makeRecentItem(name, QString(""), QString("%1").arg(tr("New Sketch")), icon, text); } else if (name == "recentOpenSketch") { widget = makeRecentItem(name, QString(""), QString("%1").arg(tr("Open Sketch")), icon, text); } if (widget) { widget->setObjectName(name); whichLayout->addWidget(widget); } } // frameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); frame->setLayout(frameLayout); return frame; } QWidget * WelcomeView::makeRecentItem(const QString & objectName, const QString & iconText, const QString & textText, QLabel * & icon, QLabel * & text) { QFrame * rFrame = new QFrame; QHBoxLayout * rFrameLayout = new QHBoxLayout; zeroMargin(rFrameLayout); icon = new QLabel(iconText); icon->setObjectName("recentIcon"); connect(icon, SIGNAL(linkActivated(const QString &)), this, SLOT(clickRecent(const QString &))); rFrameLayout->addWidget(icon); text = new QLabel(textText); text->setObjectName(objectName); text->setObjectName("recentText"); rFrameLayout->addWidget(text); connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(clickRecent(const QString &))); rFrame->setLayout(rFrameLayout); return rFrame; } QWidget * WelcomeView::initShop() { QFrame * frame = new QFrame(); frame->setObjectName("shopFrame"); QVBoxLayout * frameLayout = new QVBoxLayout; zeroMargin(frameLayout); QWidget * headerFrame = createHeaderFrame( tr("Shop"), "Shop", tr("Fab"), "Fab", m_inactiveHeaderLabelColor, m_activeHeaderLabelColor, m_shopLabel, m_fabLabel); frameLayout->addWidget(headerFrame); m_shopUberFrame = createShopContentFrame(":/resources/images/welcome_kit.png", tr("Fritzing CreatorKit"), tr("The Fritzing Creator Kit is out of Stock. For Updates please visit the fritzing.blog"), "http://creatorkit.fritzing.org/", tr(""), tr(""), ":/resources/images/icons/WS-shopLogo.png", "#f5a400" ); frameLayout->addWidget(m_shopUberFrame); m_fabUberFrame = createShopContentFrame(":/resources/images/pcbs_2013.png", tr("Fritzing Fab"), tr("Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches."), "http://fab.fritzing.org/", tr("produce your first pcb now >>"), tr("Order your PCB now."), ":/resources/images/icons/WS-fabLogo.png", "#5f4d4a" ); frameLayout->addWidget(m_fabUberFrame); frame->setLayout(frameLayout); clickBlog("fab"); return frame; } QWidget * WelcomeView::createShopContentFrame(const QString & imagePath, const QString & headline, const QString & description, const QString & url, const QString & urlText, const QString & urlText2, const QString & logoPath, const QString & footerLabelColor ) { QFrame * uberFrame = new QFrame(); uberFrame->setObjectName("shopUberFrame"); QVBoxLayout * shopUberFrameLayout = new QVBoxLayout; zeroMargin(shopUberFrameLayout); QFrame* shopContentFrame = new QFrame(); shopContentFrame->setObjectName("shopContentFrame"); QHBoxLayout * contentFrameLayout = new QHBoxLayout; zeroMargin(contentFrameLayout); QLabel * label = new QLabel(QString("").arg(imagePath)); label->setObjectName("shopContentImage"); contentFrameLayout->addWidget(label); QFrame * contentTextFrame = new QFrame(); contentTextFrame->setObjectName("shopContentTextFrame"); QVBoxLayout * contentTextFrameLayout = new QVBoxLayout; zeroMargin(contentTextFrameLayout); contentTextFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding)); label = new QLabel(headline); label->setObjectName("shopContentTextHeadline"); //label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); contentTextFrameLayout->addWidget(label); label = new QLabel(description); label->setObjectName("shopContentTextDescription"); //label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); contentTextFrameLayout->addWidget(label); label = new QLabel(QString("%2").arg(url).arg(urlText)); label->setObjectName("shopContentTextCaption"); contentTextFrameLayout->addWidget(label); //label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(label, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); contentTextFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding)); contentTextFrame->setLayout(contentTextFrameLayout); contentFrameLayout->addWidget(contentTextFrame); shopContentFrame->setLayout(contentFrameLayout); shopUberFrameLayout->addWidget(shopContentFrame); shopUberFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); QFrame * shopFooterFrame = new QFrame(); shopFooterFrame->setObjectName("shopFooterFrame"); QHBoxLayout * footerFrameLayout = new QHBoxLayout; zeroMargin(footerFrameLayout); footerFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); QLabel * footerLabel = new QLabel(QString("%2").arg(url).arg(urlText2).arg(footerLabelColor)); footerLabel->setObjectName("shopLogoText"); footerFrameLayout->addWidget(footerLabel); connect(footerLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); QLabel * footerLogoLabel = new QLabel(tr("").arg(url).arg(logoPath)); footerLogoLabel->setObjectName("shopLogo"); footerFrameLayout->addWidget(footerLogoLabel); connect(footerLogoLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); shopFooterFrame->setLayout(footerFrameLayout); shopUberFrameLayout->addWidget(shopFooterFrame); uberFrame->setLayout(shopUberFrameLayout); return uberFrame; } QWidget * WelcomeView::initBlog() { QFrame * frame = new QFrame(); frame->setObjectName("blogFrame"); QVBoxLayout * frameLayout = new QVBoxLayout; zeroMargin(frameLayout); QWidget * headerFrame = createHeaderFrame(tr("Projects"), "Projects", tr("Blog"), "Blog", m_inactiveHeaderLabelColor, m_activeHeaderLabelColor, m_projectsLabel, m_blogLabel); frameLayout->addWidget(headerFrame); m_blogListWidget = createBlogContentFrame("http://blog.fritzing.org", tr("Fritzing News."), ":/resources/images/icons/WS-blogLogo.png", "#802742"); m_blogUberFrame = m_blogListWidget; while (m_blogUberFrame->parentWidget()) m_blogUberFrame = m_blogUberFrame->parentWidget(); frameLayout->addWidget(m_blogUberFrame); m_projectListWidget = createBlogContentFrame("http://fritzing.org/projects/", tr("Fritzing Projects."), ":/resources/images/icons/WS-galleryLogo.png", "#00a55b"); m_projectsUberFrame = m_projectListWidget; while (m_projectsUberFrame->parentWidget()) m_projectsUberFrame = m_projectsUberFrame->parentWidget(); frameLayout->addWidget(m_projectsUberFrame); frame->setLayout(frameLayout); //DebugDialog::debug("first click blog"); clickBlog("Blog"); return frame; } QFrame * WelcomeView::createHeaderFrame (const QString & url1, const QString & urlText1, const QString & url2, const QString & urlText2, const QString & inactiveColor, const QString & activeColor, QLabel * & label1, QLabel * & label2){ QFrame * titleFrame = new QFrame(); titleFrame->setObjectName("wsSwitchableFrameHeader"); QHBoxLayout * titleFrameLayout = new QHBoxLayout; zeroMargin(titleFrameLayout); label1 = new QLabel(makeUrlText(url1, urlText1, inactiveColor)); label1->setObjectName("headerTitle1"); titleFrameLayout->addWidget(label1); connect(label1, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); QLabel * titleSpace = new QLabel("|"); titleSpace->setObjectName("headerTitleSpace"); titleFrameLayout->addWidget(titleSpace); label2 = new QLabel(makeUrlText(url2, urlText2, activeColor)); label2->setObjectName("headerTitle2"); titleFrameLayout->addWidget(label2); connect(label2, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); titleFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); titleFrame->setLayout(titleFrameLayout); return titleFrame; } BlogListWidget * WelcomeView::createBlogContentFrame(const QString & url, const QString & urlText, const QString & logoPath, const QString & footerLabelColor) { QFrame * uberFrame = new QFrame; QVBoxLayout * uberFrameLayout = new QVBoxLayout; zeroMargin(uberFrameLayout); BlogListWidget * listWidget = new BlogListWidget; listWidget->setObjectName("blogList"); listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); listWidget->setItemDelegate(new BlogListDelegate(listWidget)); connect(listWidget, SIGNAL(itemClicked (QListWidgetItem *)), this, SLOT(blogItemClicked(QListWidgetItem *))); uberFrameLayout->addWidget(listWidget); QFrame * footerFrame = new QFrame(); footerFrame->setObjectName("blogFooterFrame"); QHBoxLayout * footerFrameLayout = new QHBoxLayout; zeroMargin(footerFrameLayout); footerFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); QLabel * footerLabel = new QLabel(QString("%2").arg(url).arg(urlText).arg(footerLabelColor)); footerLabel->setObjectName("blogLogoText"); footerFrameLayout->addWidget(footerLabel); connect(footerLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); footerLabel = new QLabel(tr("").arg(url).arg(logoPath)); footerLabel->setObjectName("blogLogo"); footerFrameLayout->addWidget(footerLabel); connect(footerLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(clickBlog(const QString &))); footerFrame->setLayout(footerFrameLayout); uberFrameLayout->addWidget(footerFrame); uberFrame->setLayout(uberFrameLayout); return listWidget; } void WelcomeView::showEvent(QShowEvent * event) { QFrame::showEvent(event); updateRecent(); } void WelcomeView::updateRecent() { if (m_recentListWidget == NULL) return; QSettings settings; QStringList files = settings.value("recentFileList").toStringList(); m_recentListWidget->clear(); bool gotOne = false; QIcon icon(":/resources/images/icons/WS-fzz-icon.png"); for (int i = 0; i < files.size(); ++i) { QFileInfo finfo(files[i]); if (!finfo.exists()) continue; gotOne = true; QListWidgetItem * item = new QListWidgetItem(icon, finfo.fileName()); item->setData(Qt::UserRole, finfo.absoluteFilePath()); item->setToolTip(finfo.absoluteFilePath()); m_recentListWidget->addItem(item); } if (!gotOne) { // put in a placeholder if there are no recent files QListWidgetItem * item = new QListWidgetItem(icon, tr("No recent sketches found")); item->setData(Qt::UserRole, ""); m_recentListWidget->addItem(item); } } void WelcomeView::clickRecent(const QString & url) { if (url == "open") { emit openSketch(); return; } if (url == "new") { emit newSketch(); return; } } void WelcomeView::gotBlogSnippet(QNetworkReply * networkReply) { bool blog = networkReply->url().toString().contains("blog"); QString prefix = networkReply->url().scheme() + "://" + networkReply->url().authority(); QNetworkAccessManager * manager = networkReply->manager(); int responseCode = networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); bool goodBlog = false; QDomDocument doc; QString errorStr; int errorLine; int errorColumn; if (responseCode == 200) { QString data(networkReply->readAll()); //DebugDialog::debug("response data " + data); data = "" + cleanData(data) + ""; // make it one tree for xml parsing if (doc.setContent(data, &errorStr, &errorLine, &errorColumn)) { readBlog(doc, true, blog, prefix); goodBlog = true; } } if (!goodBlog) { QString message = (blog) ? tr("Unable to reach blog.fritzing.org") : tr("Unable to reach friting.org/projects") ; QString placeHolder = QString("
  • ").arg(message); if (doc.setContent(placeHolder, &errorStr, &errorLine, &errorColumn)) { readBlog(doc, true, blog, ""); } } manager->deleteLater(); networkReply->deleteLater(); } void WelcomeView::clickBlog(const QString & url) { if (url.toLower() == "fab") { m_shopUberFrame->setVisible(false); m_fabUberFrame->setVisible(true); m_fabLabel->setText(hackColor(m_fabLabel->text(), m_activeHeaderLabelColor)); m_shopLabel->setText(hackColor(m_shopLabel->text(), m_inactiveHeaderLabelColor)); return; } if (url.toLower() == "shop") { m_shopUberFrame->setVisible(true); m_fabUberFrame->setVisible(false); m_fabLabel->setText(hackColor(m_fabLabel->text(), m_inactiveHeaderLabelColor)); m_shopLabel->setText(hackColor(m_shopLabel->text(), m_activeHeaderLabelColor)); return; } if (url.toLower() == "nexttip") { nextTip(); return; } if (url.toLower() == "projects") { m_projectsUberFrame->setVisible(true); m_blogUberFrame->setVisible(false); m_projectsLabel->setText(hackColor(m_projectsLabel->text(), m_activeHeaderLabelColor)); m_blogLabel->setText(hackColor(m_blogLabel->text(), m_inactiveHeaderLabelColor)); return; } if (url.toLower() == "blog") { m_projectsUberFrame->setVisible(false); m_blogUberFrame->setVisible(true); m_projectsLabel->setText(hackColor(m_projectsLabel->text(), m_inactiveHeaderLabelColor)); m_blogLabel->setText(hackColor(m_blogLabel->text(), m_activeHeaderLabelColor)); return; } QDesktopServices::openUrl(url); } /* // sample output from http://blog.fritzing.org/recent-posts-app/ // sample output from http://fritzing.org/projects/snippet/ */ void WelcomeView::readBlog(const QDomDocument & doc, bool doEmit, bool blog, const QString & prefix) { BlogListWidget * listWidget = (blog) ? m_blogListWidget : m_projectListWidget; listWidget->clear(); listWidget->imageRequestList().clear(); QDomNodeList nodeList = doc.elementsByTagName("li"); for (int i = 0; i < nodeList.count(); i++) { QDomElement element = nodeList.at(i).toElement(); QDomElement child = element.firstChildElement(); QHash stuff; while (!child.isNull()) { if (child.tagName() == "img") { stuff.insert("img", child.attribute("src")); } else { QString clss = child.attribute("class"); if (clss == "title") { QString title = child.attribute("title"); QString href = child.attribute("href"); if (!blog) { href.insert(0, prefix); } stuff.insert("title", title); stuff.insert("href", href); } else if (clss == "image") { QDomElement img = child.firstChildElement("img"); QString src = img.attribute("src"); if (!src.isEmpty()) src.insert(0, prefix); stuff.insert("img", src); } else { stuff.insert(clss, child.text()); } } child = child.nextSiblingElement(); } if (stuff.value("title", "").isEmpty()) continue; if (stuff.value("href", "").isEmpty()) continue; QListWidgetItem * item = new QListWidgetItem(); item->setData(TitleRole, stuff.value("title")); item->setData(RefRole, stuff.value("href")); QString text = stuff.value("intro", ""); text.replace("\r", " "); text.replace("\n", " "); text.replace("\t", " "); item->setData(IntroRole, text); listWidget->addItem(item); listWidget->imageRequestList() << stuff.value("img", ""); if (!stuff.value("date", "").isEmpty()) { item->setData(DateRole, stuff.value("date")); } if (!stuff.value("author", "").isEmpty()) { item->setData(AuthorRole, stuff.value("author")); } } if (listWidget->count() > 0) { listWidget->itemEnteredSlot(listWidget->item(0)); } if (doEmit) { getNextBlogImage(0, blog); foreach (QWidget *widget, QApplication::topLevelWidgets()) { WelcomeView * other = widget->findChild(); if (other == NULL) continue; if (other == this) continue; other->readBlog(doc, false, blog, prefix); } } } void WelcomeView::getNextBlogImage(int ix, bool blog) { BlogListWidget * listWidget = (blog) ? m_blogListWidget : m_projectListWidget; for (int i = ix; i < listWidget->imageRequestList().count(); i++) { QString image = listWidget->imageRequestList().at(i); if (image.isEmpty()) continue; QNetworkAccessManager * manager = new QNetworkAccessManager(this); manager->setProperty("index", i); manager->setProperty("blog", blog); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(gotBlogImage(QNetworkReply *))); manager->get(QNetworkRequest(QUrl(image))); } } void WelcomeView::gotBlogImage(QNetworkReply * networkReply) { QNetworkAccessManager * manager = networkReply->manager(); if (manager == NULL) return; int index = manager->property("index").toInt(); bool blog = manager->property("blog").toBool(); int responseCode = networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (responseCode == 200) { QByteArray data(networkReply->readAll()); QPixmap pixmap; if (pixmap.loadFromData(data)) { QPixmap scaled = pixmap.scaled(QSize(ImageSpace, ImageSpace), Qt::KeepAspectRatio); setBlogItemImage(scaled, index, blog); foreach (QWidget *widget, QApplication::topLevelWidgets()) { WelcomeView * other = widget->findChild(); if (other == NULL) continue; if (other == this) continue; other->setBlogItemImage(scaled, index, blog); } } } manager->deleteLater(); networkReply->deleteLater(); getNextBlogImage(index + 1, blog); } QWidget * WelcomeView::initTip() { QFrame * tipFrame = new QFrame(); tipFrame->setObjectName("tipFrame"); QVBoxLayout * tipLayout = new QVBoxLayout(); zeroMargin(tipLayout); QLabel * tipTitle = new QLabel(tr("Tip of the Day:")); tipTitle->setObjectName("tipTitle"); tipLayout->addWidget(tipTitle); QScrollArea * scrollArea = new QScrollArea; scrollArea->setObjectName("tipScrollArea"); scrollArea->setWidgetResizable(true); // scrollArea->setAlignment(Qt::AlignTop | Qt::AlignLeft); // scrollArea->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_tip = new QLabel(); m_tip->setObjectName("tip"); m_tip->setAlignment(Qt::AlignTop | Qt::AlignLeft); //connect(m_tip, SIGNAL(linkActivated(const QString &)), this->window(), SLOT(tipsAndTricks())); scrollArea->setWidget(m_tip); tipLayout->addWidget(scrollArea); tipLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Fixed)); QFrame * footerFrame = new QFrame(); footerFrame->setObjectName("tipFooterFrame"); QHBoxLayout * footerFrameLayout = new QHBoxLayout; zeroMargin(footerFrameLayout); QLabel * footerLabel = new QLabel(QString("%1").arg(tr("All Tips"))); footerLabel->setObjectName("allTips"); footerFrameLayout->addWidget(footerLabel); connect(footerLabel, SIGNAL(linkActivated(const QString &)), this->window(), SLOT(tipsAndTricks())); footerFrameLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding)); footerLabel = new QLabel(QString("%1").arg(tr("Next Tip"))); footerLabel->setObjectName("nextTip"); footerFrameLayout->addWidget(footerLabel); connect(footerLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(nextTip())); footerFrame->setLayout(footerFrameLayout); tipLayout->addWidget(footerFrame); tipFrame->setLayout(tipLayout); return tipFrame; } void WelcomeView::dragEnterEvent(QDragEnterEvent *event) { DebugDialog::debug("ignoring drag enter"); event->ignore(); } void WelcomeView::nextTip() { if (m_tip == NULL) return; m_tip->setText(QString("%1").arg(TipsAndTricks::randomTip())); } void WelcomeView::recentItemClicked(QListWidgetItem * item) { QString data = item->data(Qt::UserRole).toString(); if (data.isEmpty()) return; emit recentSketch(data, data); } void WelcomeView::blogItemClicked(QListWidgetItem * item) { QString url = item->data(RefRole).toString(); if (url.isEmpty()) return; if (url == "nop") return; QDesktopServices::openUrl(url); } void WelcomeView::setBlogItemImage(QPixmap & pixmap, int index, bool blog) { // TODO: this is not totally thread-safe if there are multiple sketch widgets opened within a very short time BlogListWidget * listWidget = (blog) ? m_blogListWidget : m_projectListWidget; QListWidgetItem * item = listWidget->item(index); if (item) { item->setData(IconRole, pixmap); } } fritzing-app-0.9.2b/src/sketch/welcomeview.h000066400000000000000000000147161250202676700210650ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6483 $: $Author: irascibl@gmail.com $: $Date: 2012-09-26 15:45:37 +0200 (Mi, 26. Sep 2012) $ ********************************************************************/ #ifndef WELCOMEVIEW_H #define WELCOMEVIEW_H #include #include #include #include #include #include #include #include #include #include class BlogListWidget : public QListWidget { Q_OBJECT Q_PROPERTY(QColor titleTextColor READ titleTextColor WRITE setTitleTextColor DESIGNABLE true) Q_PROPERTY(QString titleTextFontFamily READ titleTextFontFamily WRITE setTitleTextFontFamily DESIGNABLE true) Q_PROPERTY(QString titleTextFontSize READ titleTextFontSize WRITE setTitleTextFontSize DESIGNABLE true) Q_PROPERTY(QString titleTextExtraLeading READ titleTextExtraLeading WRITE setTitleTextExtraLeading DESIGNABLE true) Q_PROPERTY(QColor introTextColor READ introTextColor WRITE setIntroTextColor DESIGNABLE true) Q_PROPERTY(QString introTextFontFamily READ introTextFontFamily WRITE setIntroTextFontFamily DESIGNABLE true) Q_PROPERTY(QString introTextFontSize READ introTextFontSize WRITE setIntroTextFontSize DESIGNABLE true) Q_PROPERTY(QString introTextExtraLeading READ introTextExtraLeading WRITE setIntroTextExtraLeading DESIGNABLE true) Q_PROPERTY(QColor dateTextColor READ dateTextColor WRITE setDateTextColor DESIGNABLE true) Q_PROPERTY(QString dateTextFontFamily READ dateTextFontFamily WRITE setDateTextFontFamily DESIGNABLE true) Q_PROPERTY(QString dateTextFontSize READ dateTextFontSize WRITE setDateTextFontSize DESIGNABLE true) public: BlogListWidget(QWidget * parent = 0); ~BlogListWidget(); QColor titleTextColor() const; void setTitleTextColor(QColor); QString titleTextFontFamily() const; void setTitleTextFontFamily(QString); QString titleTextFontSize() const; void setTitleTextFontSize(QString); QString titleTextExtraLeading() const; void setTitleTextExtraLeading(QString); QColor introTextColor() const; void setIntroTextColor(QColor); QString introTextFontFamily() const; void setIntroTextFontFamily(QString); QString introTextFontSize() const; void setIntroTextFontSize(QString); QString introTextExtraLeading() const; void setIntroTextExtraLeading(QString); QColor dateTextColor() const; void setDateTextColor(QColor); QString dateTextFontFamily() const; void setDateTextFontFamily(QString); QString dateTextFontSize() const; void setDateTextFontSize(QString); QStringList & imageRequestList(); public slots: void itemEnteredSlot(QListWidgetItem *); protected: QColor m_titleTextColor; QString m_titleTextFontFamily; QString m_titleTextFontSize; QString m_titleTextExtraLeading; QColor m_introTextColor; QString m_introTextFontFamily; QString m_introTextFontSize; QString m_introTextExtraLeading; QColor m_dateTextColor; QString m_dateTextFontFamily; QString m_dateTextFontSize; QStringList m_imageRequestList; }; class WelcomeView : public QFrame { Q_OBJECT public: WelcomeView(QWidget * parent = 0); ~WelcomeView(); void showEvent(QShowEvent * event); void dragEnterEvent(QDragEnterEvent *event); void updateRecent(); protected: void initLayout(); QWidget * initRecent(); QWidget * initBlog(); QWidget * initShop(); QWidget * initTip(); void readBlog(const QDomDocument &, bool doEmit, bool blog, const QString & prefix); QWidget * makeRecentItem(const QString & objectName, const QString & iconText, const QString & textText, QLabel * & icon, QLabel * & text); void getNextBlogImage(int ix, bool blog); void setBlogItemImage(QPixmap &, int index, bool blog) ; QWidget * createShopContentFrame(const QString & imagePath, const QString & headline, const QString & description, const QString & url, const QString & urlText, const QString & urlText2, const QString & logoPath, const QString & footerLabelColor); BlogListWidget * createBlogContentFrame(const QString & url, const QString & urlText, const QString & logoPath, const QString & footerLabelColor); QFrame * createHeaderFrame(const QString & url1, const QString & urlText1, const QString & url2, const QString & urlText2, const QString & inactiveColor, const QString & activeColor, QLabel * & label1, QLabel * & label2); signals: void newSketch(); void openSketch(); void recentSketch(const QString & filename, const QString & actionText); protected slots: void clickRecent(const QString &); void gotBlogSnippet(QNetworkReply *); void gotBlogImage(QNetworkReply *); void clickBlog(const QString &); void recentItemClicked(QListWidgetItem *); void blogItemClicked(QListWidgetItem *); void nextTip(); protected: BlogListWidget * m_blogListWidget; BlogListWidget * m_projectListWidget; QWidget * m_blogUberFrame; QWidget * m_projectsUberFrame; QLabel * m_tip; QListWidget * m_recentListWidget; QWidget * m_fabUberFrame; QWidget * m_shopUberFrame; QLabel * m_projectsLabel; QLabel * m_blogLabel; QLabel * m_fabLabel; QLabel * m_shopLabel; static QString m_activeHeaderLabelColor; static QString m_inactiveHeaderLabelColor; }; class BlogListDelegate : public QAbstractItemDelegate { public: BlogListDelegate(QObject *parent = 0); virtual ~BlogListDelegate(); void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; }; #endif fritzing-app-0.9.2b/src/sketch/zoomablegraphicsview.cpp000066400000000000000000000124761250202676700233170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #include #include #include //#include #include "zoomablegraphicsview.h" #include "../utils/zoomslider.h" #include "../utils/misc.h" const int ZoomableGraphicsView::MaxScaleValue = 3000; ZoomableGraphicsView::WheelMapping ZoomableGraphicsView::m_wheelMapping = #ifdef Q_OS_WIN ZoomPrimary; #else ScrollPrimary; #endif bool FirstTime = true; ZoomableGraphicsView::ZoomableGraphicsView( QWidget * parent ) : QGraphicsView(parent) { m_viewFromBelow = false; m_scaleValue = 100; m_maxScaleValue = MaxScaleValue; m_minScaleValue = 1; m_acceptWheelEvents = true; if (FirstTime) { FirstTime = false; QSettings settings; m_wheelMapping = (WheelMapping) settings.value("wheelMapping", m_wheelMapping).toInt(); if (m_wheelMapping >= WheelMappingCount) { m_wheelMapping = ScrollPrimary; } } //setViewport(new QGLWidget); } void ZoomableGraphicsView::wheelEvent(QWheelEvent* event) { if (!m_acceptWheelEvents) { QGraphicsView::wheelEvent(event); return; } if ((event->modifiers() & Qt::ShiftModifier) != 0) { QGraphicsView::wheelEvent(event); return; } bool doZoom = false; bool doHorizontal = false; bool doVertical = false; bool control = event->modifiers() & Qt::ControlModifier; bool alt = event->modifiers() & altOrMetaModifier(); bool shift = event->modifiers() & Qt::ShiftModifier; switch (m_wheelMapping) { case ScrollPrimary: if (control || alt) doZoom = true; else { if (event->orientation() == Qt::Horizontal) { doHorizontal = true; } else { doVertical = true; } } break; case ZoomPrimary: if (control || alt) { if (event->orientation() == Qt::Horizontal) { doHorizontal = true; } else { doVertical = true; } } else doZoom = true; break; default: // shouldn't happen return; } if (shift && (doVertical || doHorizontal)) { if (doVertical) { doVertical = false; doHorizontal = true; } else { doVertical = true; doHorizontal = false; } } int numSteps = event->delta() / 8; if (doZoom) { double delta = ((double) event->delta() / 120) * ZoomSlider::ZoomStep; if (delta == 0) return; // Scroll zooming relative to the current size relativeZoom(2*delta, true); emit wheelSignal(); } else if (doVertical) { verticalScrollBar()->setValue( verticalScrollBar()->value() - numSteps); } else if (doHorizontal) { horizontalScrollBar()->setValue( horizontalScrollBar()->value() - numSteps); } } void ZoomableGraphicsView::relativeZoom(double step, bool centerOnCursor) { double tempSize = m_scaleValue + step; if (tempSize < m_minScaleValue) { m_scaleValue = m_minScaleValue; emit zoomOutOfRange(m_scaleValue); return; } if (tempSize > m_maxScaleValue) { m_scaleValue = m_maxScaleValue; emit zoomOutOfRange(m_scaleValue); return; } double tempScaleValue = tempSize/100; m_scaleValue = tempSize; //QPoint p = QCursor::pos(); //QPoint q = this->mapFromGlobal(p); //QPointF r = this->mapToScene(q); QMatrix matrix; double multiplier = 1; if (m_viewFromBelow) multiplier = -1; matrix.scale(multiplier * tempScaleValue, tempScaleValue); if (centerOnCursor) { //this->setMatrix(QMatrix().translate(-r.x(), -r.y()) * matrix * QMatrix().translate(r.x(), r.y())); this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); } else { this->setTransformationAnchor(QGraphicsView::AnchorViewCenter); } this->setMatrix(matrix); emit zoomChanged(m_scaleValue); } void ZoomableGraphicsView::absoluteZoom(double percent) { relativeZoom(percent-m_scaleValue, false); } double ZoomableGraphicsView::currentZoom() { return m_scaleValue; } void ZoomableGraphicsView::setAcceptWheelEvents(bool accept) { m_acceptWheelEvents = accept; } void ZoomableGraphicsView::setWheelMapping(WheelMapping wm) { m_wheelMapping = wm; } ZoomableGraphicsView::WheelMapping ZoomableGraphicsView::wheelMapping() { return m_wheelMapping; } bool ZoomableGraphicsView::viewFromBelow() { return m_viewFromBelow; } void ZoomableGraphicsView::setViewFromBelow(bool viewFromBelow) { if (m_viewFromBelow == viewFromBelow) return; m_viewFromBelow = viewFromBelow; this->setTransformationAnchor(QGraphicsView::AnchorViewCenter); QTransform transform; transform.scale(-1, 1); this->setTransform(transform, true); } fritzing-app-0.9.2b/src/sketch/zoomablegraphicsview.h000066400000000000000000000041101250202676700227460ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #ifndef ZOOMABLEGRAPHICSVIEW_H #define ZOOMABLEGRAPHICSVIEW_H #include #include #include #include class ZoomableGraphicsView : public QGraphicsView { Q_OBJECT public: ZoomableGraphicsView(QWidget* parent = 0); void relativeZoom(double step, bool centerToCursor); void absoluteZoom(double percent); double currentZoom(); void setAcceptWheelEvents(bool); virtual void ensureFixedToBottomRightItems() {} bool viewFromBelow(); virtual void setViewFromBelow(bool); static const int MaxScaleValue; public: enum WheelMapping { ScrollPrimary, ZoomPrimary, WheelMappingCount }; static WheelMapping wheelMapping(); static void setWheelMapping(WheelMapping); signals: void zoomChanged(double zoom); void zoomOutOfRange(double zoom); void wheelSignal(); protected: virtual void wheelEvent(QWheelEvent* event); protected: double m_scaleValue; int m_maxScaleValue; int m_minScaleValue; bool m_acceptWheelEvents; bool m_viewFromBelow; protected: static WheelMapping m_wheelMapping; }; #endif fritzing-app-0.9.2b/src/sketchtoolbutton.cpp000066400000000000000000000075141250202676700212220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "sketchtoolbutton.h" #include "debugdialog.h" #include #include #include #include SketchToolButton::SketchToolButton(const QString &imageName, QWidget *parent, QAction* defaultAction) : QToolButton(parent) { m_imageName = imageName; // nice to have for debugging setupIcons(imageName); //DebugDialog::debug(QString("%1 %2 %3 %4 %5 %6 %7").arg(imageName) //.arg(m_enabledImage.width()).arg(m_enabledImage.height()) //.arg(m_disabledImage.width()).arg(m_disabledImage.height()) //.arg(m_pressedImage.width()).arg(m_pressedImage.height())); if(defaultAction) { setDefaultAction(defaultAction); setText(defaultAction->text()); } } SketchToolButton::SketchToolButton(const QString &imageName, QWidget *parent, QList menuActions) : QToolButton(parent) { m_imageName = imageName; // nice to have for debugging setupIcons(imageName); QMenu *menu = new QMenu(this); for(int i=0; i < menuActions.size(); i++) { QAction* act = menuActions[i]; menu->addAction(act); if(i==0) { setDefaultAction(act); } } setMenu(menu); connect(menu,SIGNAL(aboutToHide()),this,SLOT(setEnabledIconAux())); setPopupMode(QToolButton::MenuButtonPopup); } void SketchToolButton::setEnabledIconAux() { setEnabledIcon(); } QString SketchToolButton::imagePrefix() { return ":/resources/images/icons/toolbar"; } void SketchToolButton::setImage(const QPixmap & pixmap) { setIcon(QIcon(pixmap)); } void SketchToolButton::setupIcons(const QString &imageName, bool hasStates) { setIconSize(QSize(37,24)); setToolButtonStyle(Qt::ToolButtonTextUnderIcon); AbstractStatesButton::setupIcons(imageName, hasStates); } void SketchToolButton::updateEnabledState() { bool enabled = false; foreach(QAction *act, actions()) { if(act->isEnabled()) { enabled = true; break; } } setEnabled(enabled); } void SketchToolButton::actionEvent(QActionEvent *event) { switch (event->type()) { case QEvent::ActionChanged: if (event->action() == defaultAction()) { setEnabled(defaultAction()->isEnabled()); // update button state } break; default: QToolButton::actionEvent(event); } } void SketchToolButton::mousePressEvent(QMouseEvent *event) { setPressedIcon(); QToolButton::mousePressEvent(event); } void SketchToolButton::mouseReleaseEvent(QMouseEvent *event) { setEnabledIcon(); QToolButton::mouseReleaseEvent(event); } void SketchToolButton::changeEvent(QEvent *event) { if(event->type() == QEvent::EnabledChange) { if(this->isEnabled()) { setEnabledIcon(); } else { setDisabledIcon(); } } QToolButton::changeEvent(event); } void SketchToolButton::enterEvent(QEvent *event) { QToolButton::enterEvent(event); emit entered(); } void SketchToolButton::leaveEvent(QEvent *event) { QToolButton::leaveEvent(event); emit left(); } fritzing-app-0.9.2b/src/sketchtoolbutton.h000066400000000000000000000037231250202676700206650ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SKETCHTOOLBUTTON_H_ #define SKETCHTOOLBUTTON_H_ #include #include "utils/abstractstatesbutton.h" class SketchToolButton : public QToolButton, public AbstractStatesButton { Q_OBJECT public: SketchToolButton(const QString &imageName, QWidget *parent, QAction* defaultAction); SketchToolButton(const QString &imageName, QWidget *parent, QList menuActions); void updateEnabledState(); protected slots: void setEnabledIconAux(); signals: void entered(); void left(); protected: QString imagePrefix(); void setImage(const QPixmap & pixmap); void setupIcons(const QString &imageName, bool hasStates=true); void actionEvent(QActionEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void enterEvent(QEvent *); void leaveEvent(QEvent *); void changeEvent(QEvent *); protected: QString m_imageName; }; #endif /* SKETCHTOOLBUTTON_H_ */ fritzing-app-0.9.2b/src/svg/000077500000000000000000000000001250202676700156735ustar00rootroot00000000000000fritzing-app-0.9.2b/src/svg/gedaelement.g000066400000000000000000000401671250202676700203250ustar00rootroot00000000000000%parser GedaElementGrammar %decl gedaelementparser.h %impl gedaelementparser.cpp %token ELEMENT %token PAD %token PIN %token MARK %token ELEMENTLINE %token ELEMENTARC %token ATTRIBUTE %token LEFTPAREN %token RIGHTPAREN %token LEFTBRACKET %token RIGHTBRACKET %token NUMBER %token STRING %token HEXNUMBER %start geda_element /: /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 1671 $: $Author: cohen@irascible.com $: $Date: 2008-11-28 12:20:31 +0100 (Fri, 28 Nov 2008) $ ********************************************************************/ #ifndef GEDAELEMENTPARSER_H #define GEDAELEMENTPARSER_H #include #include #include "gedaelementgrammar_p.h" class GedaElementLexer; class GedaElementParser: public $table { public: GedaElementParser(); ~GedaElementParser(); bool parse(GedaElementLexer *lexer); QVector & symStack(); QString errorMessage() const; QVariant result() const; private: void reallocateStack(); int m_tos; QVector m_stateStack; QVector m_symStack; QString m_errorMessage; QVariant m_result; }; #endif // GEDAELEMENTPARSER_H :/ /. /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 1671 $: $Author: cohen@irascible.com $: $Date: 2008-11-28 12:20:31 +0100 (Fri, 28 Nov 2008) $ ********************************************************************/ #include #include "gedaelementparser.h" #include "gedaelementlexer.h" GedaElementParser::GedaElementParser() { } GedaElementParser::~GedaElementParser() { } QVector & GedaElementParser::symStack() { return m_symStack; } void GedaElementParser::reallocateStack() { int size = m_stateStack.size(); if (size == 0) size = 128; else size <<= 1; m_stateStack.resize(size); } QString GedaElementParser::errorMessage() const { return m_errorMessage; } QVariant GedaElementParser::result() const { return m_result; } bool GedaElementParser::parse(GedaElementLexer *lexer) { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); m_tos = 0; m_stateStack[++m_tos] = INITIAL_STATE; while (true) { const int state = m_stateStack.at(m_tos); if (yytoken == -1 && - TERMINAL_COUNT != action_index [state]) yytoken = lexer->lex(); int act = t_action (state, yytoken); if (act == ACCEPT_STATE) return true; else if (act > 0) { if (++m_tos == m_stateStack.size()) reallocateStack(); m_stateStack[m_tos] = act; yytoken = -1; } else if (act < 0) { int r = - act - 1; m_tos -= rhs [r]; act = m_stateStack.at(m_tos++); switch (r) { ./ geda_element ::= element_command element_command_sequence sub_element_sequence ; /. case $rule_number: { qDebug() << "got geda_element "; } break; ./ sub_element_sequence ::= sub_element_sequence_paren | sub_element_sequence_bracket ; /. case $rule_number: { } break; ./ sub_element_sequence_paren ::= LEFTPAREN sub_element_groups RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); } break; ./ sub_element_sequence_bracket ::= LEFTBRACKET sub_element_groups RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); } break; ./ element_command_sequence ::= element_command_sequence_paren | element_command_sequence_bracket ; /. case $rule_number: { qDebug() << " got element_command sequence "; } break; ./ element_command_sequence_paren ::= LEFTPAREN element_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got element_command sequence "; } break; ./ element_command_sequence_bracket ::= LEFTBRACKET element_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got element_command sequence "; } break; ./ element_arguments ::= SFlags description pcb_name value mark_x mark_y text_x text_y text_direction text_scale SFlags ; /. case $rule_number: { qDebug() << " got element_arguments "; } break; ./ sub_element_groups ::= sub_element_group | sub_element_group sub_element_groups ; /. case $rule_number: { qDebug() << " got sub_element_groups "; } break; ./ sub_element_group ::= pin_element | pad_element | element_arc_element | element_line_element | mark_element | attribute_element; /. case $rule_number: { qDebug() << " got sub_element_group "; } break; ./ mark_element ::= mark_command mark_sequence ; /. case $rule_number: { qDebug() << "got mark_element "; } break; ./ mark_sequence ::= mark_paren_sequence | mark_bracket_sequence ; /. case $rule_number: { qDebug() << " got mark_sequence "; } break; ./ mark_paren_sequence ::= LEFTPAREN mark_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got mark_paren_sequence "; } break; ./ mark_bracket_sequence ::= LEFTBRACKET mark_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got mark_bracket_sequence "; } break; ./ mark_arguments ::= x y ; /. case $rule_number: { qDebug() << " got mark_arguments"; } break; ./ pin_element ::= pin_command pin_sequence ; /. case $rule_number: { qDebug() << "got pin_element "; } break; ./ pin_sequence ::= pin_paren_sequence | pin_bracket_sequence ; /. case $rule_number: { qDebug() << " got pin_sequence "; } break; ./ pin_paren_sequence ::= LEFTPAREN pin_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got pin_paren_sequence "; } break; ./ pin_bracket_sequence ::= LEFTBRACKET pin_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got pin_bracket_sequence "; } break; ./ pin_arguments ::= pin_arguments_1 | pin_arguments_2 | pin_arguments_3 | pin_arguments_4; /. case $rule_number: { qDebug() << " got pin_arguments "; } break; ./ pin_arguments_1 ::= x y Thickness Clearance Mask DrillHole Name pin_number SFlags ; /. case $rule_number: { qDebug() << " got pin_arguments 1"; } break; ./ pin_arguments_2 ::= x y Thickness DrillHole Name pin_number NFlags ; /. case $rule_number: { qDebug() << " got pin_arguments 2"; } break; ./ pin_arguments_3 ::= x y Thickness DrillHole Name NFlags ; /. case $rule_number: { qDebug() << " got pin_arguments 3"; } break; ./ pin_arguments_4 ::= x y Thickness Name NFlags ; /. case $rule_number: { qDebug() << " got pin_arguments 4 "; } break; ./ pad_element ::= pad_command pad_sequence ; /. case $rule_number: { qDebug() << "got pad_element "; } break; ./ pad_sequence ::= pad_paren_sequence | pad_bracket_sequence ; /. case $rule_number: { qDebug() << " got pad_sequence "; } break; ./ pad_paren_sequence ::= LEFTPAREN pad_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got pad_paren_sequence "; } break; ./ pad_bracket_sequence ::= LEFTBRACKET pad_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got pad_bracket_sequence "; } break; ./ pad_arguments ::= pad_arguments_1 | pad_arguments_2 | pad_arguments_3 ; /. case $rule_number: { qDebug() << " got pad_arguments "; } break; ./ pad_arguments_1 ::= x1 y1 x2 y2 Thickness Clearance Mask Name pad_number SFlags ; /. case $rule_number: { qDebug() << " got pad_arguments 1"; } break; ./ pad_arguments_2 ::= x1 y1 x2 y2 Thickness Name pad_number NFlags ; /. case $rule_number: { qDebug() << " got pad_arguments 2"; } break; ./ pad_arguments_3 ::= x1 y1 x2 y2 Thickness Name NFlags ; /. case $rule_number: { qDebug() << " got pad_arguments 3"; } break; ./ element_line_element ::= element_line_command element_line_sequence ; /. case $rule_number: { qDebug() << "got element_line_element "; } break; ./ element_line_sequence ::= element_line_paren_sequence | element_line_bracket_sequence ; /. case $rule_number: { qDebug() << " got element_line_sequence "; } break; ./ element_line_paren_sequence ::= LEFTPAREN element_line_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got element_line_paren_sequence "; } break; ./ element_line_bracket_sequence ::= LEFTBRACKET element_line_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got element_line_bracket_sequence "; } break; ./ element_line_arguments ::= x1 y1 x2 y2 Thickness ; /. case $rule_number: { qDebug() << " got element_line_arguments "; } break; ./ element_arc_element ::= element_arc_command element_arc_sequence ; /. case $rule_number: { qDebug() << "got element_arc_element "; } break; ./ element_arc_sequence ::= element_arc_paren_sequence | element_arc_bracket_sequence ; /. case $rule_number: { qDebug() << " got element_arc_sequence "; } break; ./ element_arc_paren_sequence ::= LEFTPAREN element_arc_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got element_arc_paren_sequence "; } break; ./ element_arc_bracket_sequence ::= LEFTBRACKET element_arc_arguments RIGHTBRACKET ; /. case $rule_number: { m_symStack.append(QChar(']')); qDebug() << " got element_arc_bracket_sequence "; } break; ./ element_arc_arguments ::= x y Width Height StartAngle Delta Thickness ; /. case $rule_number: { qDebug() << " got element_arc_arguments "; } break; ./ attribute_element ::= attribute_command attribute_sequence ; /. case $rule_number: { qDebug() << "got attribute_element "; } break; ./ attribute_sequence ::= attribute_paren_sequence ; /. case $rule_number: { qDebug() << " got attribute_sequence "; } break; ./ attribute_paren_sequence ::= LEFTPAREN attribute_arguments RIGHTPAREN ; /. case $rule_number: { m_symStack.append(QChar(')')); qDebug() << " got attribute_paren_sequence "; } break; ./ attribute_arguments ::= Name value ; /. case $rule_number: { qDebug() << " got attribute_arguments "; } break; ./ pad_number ::= string_value ; /. case $rule_number: { } break; ./ x ::= number_value ; /. case $rule_number: { } break; ./ x1 ::= number_value ; /. case $rule_number: { } break; ./ x2 ::= number_value ; /. case $rule_number: { } break; ./ y ::= number_value ; /. case $rule_number: { } break; ./ y1 ::= number_value ; /. case $rule_number: { } break; ./ y2 ::= number_value ; /. case $rule_number: { } break; ./ Thickness ::= number_value ; /. case $rule_number: { } break; ./ Clearance ::= number_value ; /. case $rule_number: { } break; ./ Mask ::= number_value ; /. case $rule_number: { } break; ./ DrillHole ::= number_value ; /. case $rule_number: { } break; ./ Name ::= string_value ; /. case $rule_number: { } break; ./ pin_number ::= string_value ; /. case $rule_number: { } break; ./ Width ::= number_value ; /. case $rule_number: { } break; ./ Height ::= number_value ; /. case $rule_number: { } break; ./ StartAngle ::= number_value ; /. case $rule_number: { } break; ./ Delta ::= number_value ; /. case $rule_number: { } break; ./ SFlags ::= string_value | hex_number_value ; /. case $rule_number: { } break; ./ NFlags ::= hex_number_value ; /. case $rule_number: { } break; ./ description ::= string_value ; /. case $rule_number: { } break; ./ pcb_name ::= string_value ; /. case $rule_number: { } break; ./ value ::= string_value ; /. case $rule_number: { } break; ./ mark_x ::= number_value ; /. case $rule_number: { } break; ./ mark_y ::= number_value ; /. case $rule_number: { } break; ./ text_x ::= number_value ; /. case $rule_number: { } break; ./ text_y ::= number_value ; /. case $rule_number: { } break; ./ text_direction ::= number_value ; /. case $rule_number: { } break; ./ text_scale ::= number_value ; /. case $rule_number: { } break; ./ number_value ::= NUMBER ; /. case $rule_number: { qDebug() << " got NUMBER " << lexer->currentNumber(); m_symStack.append(lexer->currentNumber()); } break; ./ hex_number_value ::= HEXNUMBER ; /. case $rule_number: { qDebug() << " got HEXNUMBER " << lexer->currentNumber(); m_symStack.append(lexer->currentNumber()); } break; ./ string_value ::= STRING ; /. case $rule_number: { qDebug() << " got STRING " << lexer->currentString(); m_symStack.append(lexer->currentString()); } break; ./ element_command ::= ELEMENT ; /. case $rule_number: { qDebug() << "got ELEMENT command "; m_symStack.append(lexer->currentCommand()); } break; ./ pin_command ::= PIN ; /. case $rule_number: { qDebug() << "got PIN command "; m_symStack.append(lexer->currentCommand()); } break; ./ pad_command ::= PAD ; /. case $rule_number: { qDebug() << "got PAD command "; m_symStack.append(lexer->currentCommand()); } break; ./ mark_command::= MARK ; /. case $rule_number: { qDebug() << "got MARK command "; m_symStack.append(lexer->currentCommand()); } break; ./ element_line_command ::= ELEMENTLINE ; /. case $rule_number: { qDebug() << "got ELEMENTLINE command "; m_symStack.append(lexer->currentCommand()); } break; ./ element_arc_command ::= ELEMENTARC ; /. case $rule_number: { qDebug() << "got ELEMENTARC command "; m_symStack.append(lexer->currentCommand()); } break; ./ attribute_command ::= ATTRIBUTE ; /. case $rule_number: { qDebug() << "got ATTRIBUTE command "; m_symStack.append(lexer->currentCommand()); } break; ./ /. } // switch m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT); } else { int ers = state; int shifts = 0; int reduces = 0; int expected_tokens[3]; for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (! k) continue; else if (k < 0) ++reduces; else if (spell[tk]) { if (shifts < 3) expected_tokens[shifts] = tk; ++shifts; } } m_errorMessage.clear(); if (shifts && shifts < 3) { bool first = true; for (int s = 0; s < shifts; ++s) { if (first) m_errorMessage += QLatin1String("Expected "); else m_errorMessage += QLatin1String(", "); first = false; m_errorMessage += QLatin1String("`"); m_errorMessage += QLatin1String(spell[expected_tokens[s]]); m_errorMessage += QLatin1String("'"); } } return false; } } return false; } ./ fritzing-app-0.9.2b/src/svg/gedaelement2svg.cpp000066400000000000000000000350171250202676700214610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "gedaelement2svg.h" #include "gedaelementparser.h" #include "gedaelementlexer.h" #include "../utils/textutils.h" #include "../version/version.h" #include "../items/wire.h" #include "../debugdialog.h" #include "../fsvgrenderer.h" #include #include #include #include #include #include #include #include #include #include GedaElement2Svg::GedaElement2Svg() : X2Svg() { } QString GedaElement2Svg::convert(const QString & filename, bool allowPadsAndPins) { m_nonConnectorNumber = 0; initLimits(); QFile file(filename); if (!file.open(QFile::ReadOnly)) { throw QObject::tr("unable to open %1").arg(filename); } QString text; QTextStream textStream(&file); text = textStream.readAll(); file.close(); GedaElementLexer lexer(text); GedaElementParser parser; if (!parser.parse(&lexer)) { throw QObject::tr("unable to parse %1").arg(filename); } QFileInfo fileInfo(filename); QDateTime now = QDateTime::currentDateTime(); QString dt = now.toString("dd/MM/yyyy hh:mm:ss"); QString title = QString("%1").arg(fileInfo.fileName()); QString description = QString("Geda footprint file '%1' converted by Fritzing") .arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(fileInfo.fileName()))); QString metadata(""); metadata += ""; metadata += ""; metadata += m_attribute.arg("geda filename").arg(fileInfo.fileName()); metadata += m_attribute.arg("fritzing version").arg(Version::versionString()); metadata += m_attribute.arg("conversion date").arg(dt); // TODO: other layers QString silkscreen; QVector stack = parser.symStack(); bool hasAuthor = false; QMultiHash pads; QMultiHash pins; QStringList pinIDs; QStringList padIDs; for (int ix = 0; ix < stack.size(); ) { QVariant var = stack[ix]; if (var.type() == QVariant::String) { QString thing = var.toString(); int argCount = countArgs(stack, ix); bool mils = stack[ix + argCount + 1].toChar() == ')'; if (thing.compare("element", Qt::CaseInsensitive) == 0) { } else if (thing.compare("pad", Qt::CaseInsensitive) == 0) { QString pid; QString s = convertPad(stack, ix, argCount, mils, pid); pads.insert(pid, s); if (!padIDs.contains(pid)) { padIDs.append(pid); } } else if (thing.compare("pin", Qt::CaseInsensitive) == 0) { QString pid; QString s = convertPin(stack, ix, argCount, mils, pid); pins.insert(pid, s); if (!pinIDs.contains(pid)) { pinIDs.append(pid); } } else if (thing.compare("elementline", Qt::CaseInsensitive) == 0) { QString unused; silkscreen += convertPad(stack, ix, argCount, mils, unused); } else if (thing.compare("elementarc", Qt::CaseInsensitive) == 0) { silkscreen += convertArc(stack, ix, argCount, mils); } else if (thing.compare("mark", Qt::CaseInsensitive) == 0) { } else if (thing.compare("attribute", Qt::CaseInsensitive) == 0) { QString aname = TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(unquote(stack[ix + 1].toString()))); metadata += m_attribute.arg(aname, TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(unquote(stack[ix + 2].toString())))); if (aname.compare("author", Qt::CaseInsensitive) == 0) { hasAuthor = true; } } ix += argCount + 2; } else if (var.type() == QVariant::Char) { // will arrive here at the end of the element // TODO: shouldn't happen otherwise ix++; } else { throw QObject::tr("parse failure in %1").arg(filename); } } if (!allowPadsAndPins && pins.count() > 0 && pads.count() > 0) { throw QObject::tr("Sorry, Fritzing can't yet handle both pins and pads together (in %1)").arg(filename); } foreach (QString c, lexer.comments()) { metadata += m_comment.arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(c))); } if (!hasAuthor) { metadata += m_attribute.arg("dist-license").arg("GPL"); metadata += m_attribute.arg("use-license").arg("unlimited"); metadata += m_attribute.arg("author").arg("gEDA project"); metadata += m_attribute.arg("license-url").arg("http://www.gnu.org/licenses/gpl.html"); } metadata += ""; metadata += ""; metadata += ""; QString copper0 = makeCopper(pinIDs, pins, filename); QString copper1 = makeCopper(padIDs, pads, filename); if (!copper0.isEmpty()) { copper0 = offsetMin("\n" + copper0 + "\n"); } if (!copper1.isEmpty()) { copper1 = offsetMin("\n" + copper1 + "\n"); } if (!silkscreen.isEmpty()) { silkscreen = offsetMin("\n" + silkscreen + "\n"); } QString svg = TextUtils::makeSVGHeader(100000, 100000, m_maxX - m_minX, m_maxY - m_minY) + title + description + metadata + copper0 + copper1 + silkscreen + ""; return svg; } int GedaElement2Svg::countArgs(QVector & stack, int ix) { int argCount = 0; for (int i = ix + 1; i < stack.size(); i++) { QVariant var = stack[i]; if (var.type() == QVariant::Char) { QChar ch = var.toChar(); if (ch == ']' || ch == ')') { break; } } argCount++; } return argCount; } QString GedaElement2Svg::convertPin(QVector & stack, int ix, int argCount, bool mils, QString & pinID) { double drill = 0; QString name; QString number; //int flags = stack[ix + argCount].toInt(); //bool useNumber = (flags & 1) != 0; if (argCount == 9) { drill = stack[ix + 6].toInt(); name = stack[ix + 7].toString(); number = stack[ix + 8].toString(); } else if (argCount == 7) { drill = stack[ix + 4].toInt(); name = stack[ix + 5].toString(); number = stack[ix + 6].toString(); } else if (argCount == 6) { drill = stack[ix + 4].toInt(); name = stack[ix + 5].toString(); } else if (argCount == 5) { name = stack[ix + 4].toString(); } else { throw QObject::tr("bad pin argument count"); } pinID = getPinID(number, name, false); int cx = stack[ix + 1].toInt(); int cy = stack[ix + 2].toInt(); double r = stack[ix + 3].toInt() / 2.0; drill /= 2.0; if (mils) { // lo res cx *= 100; cy *= 100; r *= 100; drill *= 100; } checkXLimit(cx - r); checkXLimit(cx + r); checkYLimit(cy - r); checkYLimit(cy + r); double w = r - drill; // TODO: what if multiple pins have the same id--need to clear or increment the other ids. also put the pins on a bus? // TODO: if the pin has a name, post it up to the fz as the connector name QString circle = QString("") .arg(cx) .arg(cy) .arg(r - (w / 2)) .arg(pinID) .arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(name))) .arg(w) .arg(ViewLayer::Copper0Color); return circle; } QString GedaElement2Svg::convertPad(QVector & stack, int ix, int argCount, bool mils, QString & pinID) { QString name; QString number; int flags = (argCount > 5) ? stack[ix + argCount].toInt() : 0; bool square = (flags & 0x0100) != 0; int x1 = stack[ix + 1].toInt(); int y1 = stack[ix + 2].toInt(); int x2 = stack[ix + 3].toInt(); int y2 = stack[ix + 4].toInt(); int thickness = stack[ix + 5].toInt(); bool isPad = true; if (argCount == 10) { name = stack[ix + 8].toString(); number = stack[ix + 9].toString(); QString sflags = stack[ix + argCount].toString(); if (sflags.contains("square", Qt::CaseInsensitive)) { square = true; } } else if (argCount == 8) { name = stack[ix + 6].toString(); number = stack[ix + 7].toString(); } else if (argCount == 7) { name = stack[ix + 6].toString(); } else if (argCount == 5) { // this is an elementline isPad = false; } else { throw QObject::tr("bad pad argument count"); } if (isPad) { pinID = getPinID(number, name, true); } if (mils) { // lo res x1 *= 100; y1 *= 100; x2 *= 100; y2 *= 100; thickness *= 100; } double halft = thickness / 2.0; // don't know which of the coordinates is larger so check them all checkXLimit(x1 - halft); checkXLimit(x2 - halft); checkXLimit(x1 + halft); checkXLimit(x2 + halft); checkYLimit(y1 - halft); checkYLimit(y2 - halft); checkYLimit(y1 + halft); checkYLimit(y2 + halft); QString line = QString(" & stack, int ix, int argCount, bool mils) { Q_UNUSED(argCount); int x = stack[ix + 1].toInt(); int y = stack[ix + 2].toInt(); double w = stack[ix + 3].toInt(); double h = stack[ix + 4].toInt(); // In PCB, an angle of zero points left (negative X direction), and 90 degrees points down (positive Y direction) int startAngle = (stack[ix + 5].toInt()) + 180; // Positive angles sweep counterclockwise int deltaAngle = stack[ix + 6].toInt(); int thickness = stack[ix + 7].toInt(); if (mils) { // lo res x *= 100; y *= 100; w *= 100; h *= 100; thickness *= 100; } double halft = thickness / 2.0; checkXLimit(x - w - halft); checkXLimit(x + w + halft); checkYLimit(y - h - halft); checkYLimit(y + h + halft); if (deltaAngle == 360) { if (w == h) { QString circle = QString("") .arg(x) .arg(y) .arg(w) .arg(thickness); return circle; } QString ellipse = QString("") .arg(x) .arg(y) .arg(w) .arg(h) .arg(thickness); return ellipse; } int quad = 0; int startAngleQ1 = reflectQuad(startAngle, quad); double q = atan(w * tan(2 * M_PI * startAngleQ1 / 360.0) / h); double px = w * cos(q); double py = -h * sin(q); fixQuad(quad, px, py); int endAngleQ1 = reflectQuad(startAngle + deltaAngle, quad); q = atan(w * tan(2 * M_PI * endAngleQ1 / 360.0) / h); double qx = w * cos(q); double qy = -h * sin(q); fixQuad(quad, qx, qy); QString arc = QString("") .arg(thickness) .arg(px + x) .arg(py + y) .arg(w) .arg(h) .arg(qAbs(deltaAngle) >= 180 ? 1 : 0) .arg(deltaAngle > 0 ? 0 : 1) .arg(qx - px) .arg(qy - py); return arc; } void GedaElement2Svg::fixQuad(int quad, double & px, double & py) { switch (quad) { case 0: break; case 1: px = -px; break; case 2: px = -px; py = -py; break; case 3: py = -py; break; } } int GedaElement2Svg::reflectQuad(int angle, int & quad) { angle = angle %360; if (angle < 0) angle += 360; quad = angle / 90; switch (quad) { case 0: return angle; case 1: return 180 - angle; case 2: return angle - 180; case 3: return 360 - angle; } // never gets here, but keeps compiler happy return angle; } QString GedaElement2Svg::getPinID(QString & number, QString & name, bool isPad) { if (!number.isEmpty()) { number = unquote(number); } if (!name.isEmpty()) { name = unquote(name); } QString suffix = isPad ? "pad" : "pin"; if (!number.isEmpty()) { bool ok; int n = number.toInt(&ok); return ok ? QString("connector%1%2").arg(n - 1).arg(suffix) : QString("connector%1%2").arg(number).arg(suffix); } if (!name.isEmpty()) { if (number.isEmpty()) { bool ok; int n = name.toInt(&ok); if (ok) { return QString("connector%1%2").arg(n - 1).arg(suffix); } } } return QString("%1%2").arg(FSvgRenderer::NonConnectorName).arg(m_nonConnectorNumber++); } QString GedaElement2Svg::makeCopper(QStringList ids, QHash & strings, const QString & filename) { QString copper; foreach (QString id, ids) { QStringList values = strings.values(id); if (id.isEmpty()) { DebugDialog::debug(QString("geda empty id %1").arg(filename)); foreach(QString string, values) { copper.append(string); } continue; } if (values.count() == 1) { copper.append(values.at(0)); continue; } if (values.count() == 0) { // shouldn't happen continue; } DebugDialog::debug(QString("geda multiple id %1").arg(filename)); QString xml = ""; foreach (QString string, values) { xml.append(string); } xml.append(""); QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(xml, &errorStr, &errorLine, &errorColumn)) { throw QObject::tr("Unable to parse copper: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn); } QDomElement root = doc.documentElement(); QDomElement child = root.firstChildElement(); while (!child.isNull()) { QString id = child.attribute("id"); root.setAttribute("id", id); child.removeAttribute("id"); QString name = child.attribute("connectorname"); child.removeAttribute("connectorname"); if (!name.isEmpty()) { root.setAttribute("connectorname", name); } child = child.nextSiblingElement(); } copper += doc.toString(); } return copper; } fritzing-app-0.9.2b/src/svg/gedaelement2svg.h000066400000000000000000000036621250202676700211270ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef GEDAELEMENT2SVG_H #define GEDAELEMENT2SVG_H #include #include #include #include "x2svg.h" class GedaElement2Svg : public X2Svg { public: GedaElement2Svg(); QString convert(const QString & filename, bool allowPadsAndPins); protected: int countArgs(QVector & stack, int ix); QString convertPin(QVector & stack, int ix, int argCount, bool mils, QString & pinID); QString convertPad(QVector & stack, int ix, int argCount, bool mils, QString & pinID); QString convertArc(QVector & stack, int ix, int argCount, bool mils); void fixQuad(int quad, double & px, double & py); int reflectQuad(int angle, int & quad); QString getPinID(QString & number, QString & name, bool isPad); QString makeCopper(QStringList ids, QHash &, const QString & filename); protected: int m_nonConnectorNumber; }; #endif // GEDAELEMENT2SVG_H fritzing-app-0.9.2b/src/svg/gedaelementgrammar.cpp000066400000000000000000000237251250202676700222310ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! #include "gedaelementgrammar_p.h" const char *const GedaElementGrammar::spell [] = { "end of file", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #ifndef QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO "geda_element", "element_command", "element_command_sequence", "sub_element_sequence", "sub_element_sequence_paren", "sub_element_sequence_bracket", "sub_element_groups", "element_command_sequence_paren", "element_command_sequence_bracket", "element_arguments", "SFlags", "description", "pcb_name", "value", "mark_x", "mark_y", "text_x", "text_y", "text_direction", "text_scale", "sub_element_group", "pin_element", "pad_element", "element_arc_element", "element_line_element", "mark_element", "attribute_element", "mark_command", "mark_sequence", "mark_paren_sequence", "mark_bracket_sequence", "mark_arguments", "x", "y", "pin_command", "pin_sequence", "pin_paren_sequence", "pin_bracket_sequence", "pin_arguments", "pin_arguments_1", "pin_arguments_2", "pin_arguments_3", "pin_arguments_4", "Thickness", "Clearance", "Mask", "DrillHole", "Name", "pin_number", "NFlags", "pad_command", "pad_sequence", "pad_paren_sequence", "pad_bracket_sequence", "pad_arguments", "pad_arguments_1", "pad_arguments_2", "pad_arguments_3", "x1", "y1", "x2", "y2", "pad_number", "element_line_command", "element_line_sequence", "element_line_paren_sequence", "element_line_bracket_sequence", "element_line_arguments", "element_arc_command", "element_arc_sequence", "element_arc_paren_sequence", "element_arc_bracket_sequence", "element_arc_arguments", "Width", "Height", "StartAngle", "Delta", "attribute_command", "attribute_sequence", "attribute_paren_sequence", "attribute_arguments", "string_value", "number_value", "hex_number_value", "$accept" #endif // QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO }; const int GedaElementGrammar::lhs [] = { 15, 18, 18, 19, 20, 17, 17, 22, 23, 24, 21, 21, 35, 35, 35, 35, 35, 35, 40, 43, 43, 44, 45, 46, 36, 50, 50, 51, 52, 53, 53, 53, 53, 54, 55, 56, 57, 37, 66, 66, 67, 68, 69, 69, 69, 70, 71, 72, 39, 79, 79, 80, 81, 82, 38, 84, 84, 85, 86, 87, 41, 93, 94, 95, 77, 47, 73, 75, 48, 74, 76, 58, 59, 60, 61, 62, 63, 88, 89, 90, 91, 25, 25, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 97, 98, 96, 16, 49, 65, 42, 78, 83, 92, 99}; const int GedaElementGrammar:: rhs[] = { 3, 1, 1, 3, 3, 1, 1, 3, 3, 11, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 1, 1, 1, 1, 9, 7, 6, 5, 2, 1, 1, 3, 3, 1, 1, 1, 10, 8, 7, 2, 1, 1, 3, 3, 5, 2, 1, 1, 3, 3, 7, 2, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; #ifndef QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO const int GedaElementGrammar::rule_info [] = { 15, 16, 17, 18 , 18, 19 , 18, 20 , 19, 8, 21, 9 , 20, 10, 21, 11 , 17, 22 , 17, 23 , 22, 8, 24, 9 , 23, 10, 24, 11 , 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 25 , 21, 35 , 21, 35, 21 , 35, 36 , 35, 37 , 35, 38 , 35, 39 , 35, 40 , 35, 41 , 40, 42, 43 , 43, 44 , 43, 45 , 44, 8, 46, 9 , 45, 10, 46, 11 , 46, 47, 48 , 36, 49, 50 , 50, 51 , 50, 52 , 51, 8, 53, 9 , 52, 10, 53, 11 , 53, 54 , 53, 55 , 53, 56 , 53, 57 , 54, 47, 48, 58, 59, 60, 61, 62, 63, 25 , 55, 47, 48, 58, 61, 62, 63, 64 , 56, 47, 48, 58, 61, 62, 64 , 57, 47, 48, 58, 62, 64 , 37, 65, 66 , 66, 67 , 66, 68 , 67, 8, 69, 9 , 68, 10, 69, 11 , 69, 70 , 69, 71 , 69, 72 , 70, 73, 74, 75, 76, 58, 59, 60, 62, 77, 25 , 71, 73, 74, 75, 76, 58, 62, 77, 64 , 72, 73, 74, 75, 76, 58, 62, 64 , 39, 78, 79 , 79, 80 , 79, 81 , 80, 8, 82, 9 , 81, 10, 82, 11 , 82, 73, 74, 75, 76, 58 , 38, 83, 84 , 84, 85 , 84, 86 , 85, 8, 87, 9 , 86, 10, 87, 11 , 87, 47, 48, 88, 89, 90, 91, 58 , 41, 92, 93 , 93, 94 , 94, 8, 95, 9 , 95, 62, 28 , 77, 96 , 47, 97 , 73, 97 , 75, 97 , 48, 97 , 74, 97 , 76, 97 , 58, 97 , 59, 97 , 60, 97 , 61, 97 , 62, 96 , 63, 96 , 88, 97 , 89, 97 , 90, 97 , 91, 97 , 25, 96 , 25, 98 , 64, 98 , 26, 96 , 27, 96 , 28, 96 , 29, 97 , 30, 97 , 31, 97 , 32, 97 , 33, 97 , 34, 97 , 97, 12 , 98, 14 , 96, 13 , 16, 1 , 49, 3 , 65, 2 , 42, 4 , 78, 5 , 83, 6 , 92, 7 , 99, 15, 0}; const int GedaElementGrammar::rule_index [] = { 0, 4, 6, 8, 12, 16, 18, 20, 24, 28, 40, 42, 45, 47, 49, 51, 53, 55, 57, 60, 62, 64, 68, 72, 75, 78, 80, 82, 86, 90, 92, 94, 96, 98, 108, 116, 123, 129, 132, 134, 136, 140, 144, 146, 148, 150, 161, 170, 178, 181, 183, 185, 189, 193, 199, 202, 204, 206, 210, 214, 222, 225, 227, 231, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312}; #endif // QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO const int GedaElementGrammar::action_default [] = { 0, 97, 0, 0, 0, 0, 0, 7, 6, 95, 0, 96, 0, 83, 82, 0, 85, 0, 86, 87, 0, 94, 0, 88, 0, 89, 90, 0, 91, 0, 92, 0, 93, 0, 10, 9, 0, 8, 0, 0, 1, 3, 2, 103, 102, 101, 100, 99, 98, 0, 18, 0, 15, 0, 16, 0, 17, 0, 14, 0, 13, 11, 0, 0, 62, 61, 0, 0, 76, 64, 63, 0, 0, 57, 56, 55, 0, 66, 0, 59, 69, 0, 0, 78, 0, 79, 0, 80, 0, 81, 60, 72, 0, 58, 0, 0, 51, 50, 49, 0, 67, 0, 53, 70, 0, 68, 0, 71, 0, 54, 0, 52, 0, 0, 21, 20, 19, 0, 0, 23, 24, 0, 22, 0, 0, 40, 39, 38, 0, 43, 44, 45, 0, 42, 0, 0, 0, 0, 0, 0, 73, 0, 74, 0, 0, 65, 46, 48, 84, 0, 47, 0, 41, 0, 0, 27, 26, 25, 0, 30, 31, 32, 33, 0, 29, 0, 0, 0, 0, 0, 75, 0, 0, 75, 0, 0, 77, 34, 0, 36, 0, 35, 37, 0, 28, 12, 5, 0, 4, 104}; const int GedaElementGrammar::goto_default [] = { 3, 2, 6, 40, 42, 41, 62, 8, 7, 12, 10, 15, 17, 20, 22, 24, 27, 29, 31, 33, 61, 60, 58, 52, 54, 56, 50, 55, 116, 115, 114, 117, 78, 81, 59, 157, 156, 155, 158, 159, 160, 161, 162, 90, 138, 141, 168, 66, 175, 147, 57, 127, 126, 125, 128, 129, 130, 131, 101, 104, 106, 108, 149, 53, 98, 97, 96, 99, 51, 75, 74, 73, 76, 82, 84, 86, 88, 49, 65, 64, 67, 68, 77, 13, 0}; const int GedaElementGrammar::action_index [] = { 38, -15, 27, 24, 20, 20, 22, -15, -15, -15, 3, -15, 4, -15, -15, 3, -15, 3, -15, -15, 7, -15, 7, -15, 7, -15, -15, 7, -15, 7, -15, 0, -15, 20, -15, -15, 5, -15, 58, 58, -15, -15, -15, -15, -15, -15, -15, -15, -15, 2, -15, 36, -15, 28, -15, 45, -15, 33, -15, 32, -15, 58, 6, 3, -15, -15, 3, 9, -15, -15, -15, 1, 1, -15, -15, -15, -4, -15, 1, -15, -15, 1, 16, -15, 19, -15, 19, -15, 19, -15, -15, -15, 14, -15, 19, 1, -15, -15, -15, 18, -15, 10, -15, -15, 13, -15, 13, -15, 13, -15, 11, -15, 13, 13, -15, -15, -15, 15, 16, -15, -15, 12, -15, 13, 1, -15, -15, -15, -2, -15, -15, -15, -8, -15, -12, 1, 1, 35, 1, 20, -15, 3, -15, -5, 20, -15, -15, -15, -15, -9, -15, -3, -15, 1, 1, -15, -15, -15, -10, -15, -15, -15, -15, 1, -15, -8, 35, -12, 3, -9, -1, 1, 3, -15, 3, 20, -15, -15, 20, -15, -9, -15, -15, -6, -15, -15, -15, -7, -15, -15, -85, -85, -85, -85, -74, 22, -85, -85, -85, -85, -75, -85, -85, -85, -85, -80, -85, -71, -85, -85, -73, -85, -77, -85, -82, -85, -85, -78, -85, -59, -85, -68, -85, 44, -85, -85, -85, -85, -85, 10, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, 73, -85, -85, -85, -85, 19, -85, -85, -85, -85, -85, -61, -85, -85, -85, -85, -85, -60, -85, -85, -58, -57, -85, -56, -85, -70, -85, -69, -85, -85, -85, -85, -85, -67, -34, -85, -85, -85, -85, -85, -64, -85, -85, -63, -85, -65, -85, -14, -85, -85, -85, -12, 21, -85, -85, -85, -85, 25, -85, -85, -85, -85, 2, 8, -85, -85, -85, -85, -85, -85, -85, -8, -85, -25, -23, -1, -7, -55, -36, -85, -26, -85, -16, 39, -85, -85, -85, -85, -5, -85, -85, -85, -24, 5, -85, -85, -85, -85, -85, -85, -85, -85, 23, -85, 7, 33, -11, -6, -10, -85, -18, -44, -85, -79, 20, -85, -85, 38, -85, -13, -85, -85, -85, -85, -85, -85, -85, -85, -85}; const int GedaElementGrammar::action_info [] = { 21, 164, 188, 184, 21, 9, 152, 79, 11, 133, 63, -73, 21, 21, 37, 35, 11, 186, 70, 21, 111, 122, 21, 93, 189, 21, 119, 0, 21, 102, 39, 21, 38, 11, 9, 5, 95, 4, 94, 1, 154, 124, 153, 123, 72, 0, 71, 21, 11, 0, 0, 0, 0, 113, 0, 112, 0, 0, 0, 0, 47, 48, 46, 45, 44, 43, 0, 0, 0, 0, 0, 0, 0, 26, 18, 176, 174, 28, 25, 16, 14, 163, 23, 19, 92, 89, 91, 32, 100, 187, 107, 103, 105, 118, 143, 80, 30, 83, 85, 87, 142, 172, 109, 177, 36, 69, 110, 171, 135, 181, 163, 136, 182, 139, 178, 137, 183, 150, 145, 144, 148, 100, 146, 166, 134, 121, 118, 34, 0, 165, 105, 120, 107, 132, 0, 151, 0, 173, 145, 132, 0, 91, 0, 148, 142, 0, 148, 103, 140, 0, 167, 148, 185, 169, 91, 0, 0, 100, 0, 180, 179, 0, 91, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 14, 0, 14, 0, 80, 0, 80, 0, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 176, 14, 148, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const int GedaElementGrammar::action_check [] = { 12, 11, 9, 9, 12, 14, 9, 11, 13, 11, 8, 12, 12, 12, 9, 11, 13, 11, 9, 12, 9, 9, 12, 9, 0, 12, 11, -1, 12, 11, 8, 12, 10, 13, 14, 8, 8, 10, 10, 1, 8, 8, 10, 10, 8, -1, 10, 12, 13, -1, -1, -1, -1, 8, -1, 10, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, -1, -1, -1, -1, -1, -1, -1, 82, 81, 81, 47, 82, 82, 81, 81, 32, 82, 81, 72, 82, 82, 82, 82, 6, 82, 82, 82, 32, 47, 82, 82, 82, 82, 82, 82, 46, 43, 10, 9, 13, 67, 45, 60, 49, 32, 61, 49, 47, 47, 43, 38, 49, 81, 62, 83, 82, 10, 43, 59, 31, 32, 10, -1, 33, 82, 33, 82, 58, -1, 54, -1, 82, 81, 58, -1, 82, -1, 83, 82, -1, 83, 82, 82, -1, 44, 83, 6, 47, 82, -1, -1, 82, -1, 48, 49, -1, 82, 82, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 81, -1, 81, -1, 82, -1, 82, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, 81, 81, 83, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; fritzing-app-0.9.2b/src/svg/gedaelementgrammar_p.h000066400000000000000000000034201250202676700222030ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! #ifndef GEDAELEMENTGRAMMAR_P_H #define GEDAELEMENTGRAMMAR_P_H class GedaElementGrammar { public: enum { EOF_SYMBOL = 0, ATTRIBUTE = 7, ELEMENT = 1, ELEMENTARC = 6, ELEMENTLINE = 5, HEXNUMBER = 14, LEFTBRACKET = 10, LEFTPAREN = 8, MARK = 4, NUMBER = 12, PAD = 2, PIN = 3, RIGHTBRACKET = 11, RIGHTPAREN = 9, STRING = 13, ACCEPT_STATE = 189, RULE_COUNT = 104, STATE_COUNT = 190, TERMINAL_COUNT = 15, NON_TERMINAL_COUNT = 85, GOTO_INDEX_OFFSET = 190, GOTO_INFO_OFFSET = 73, GOTO_CHECK_OFFSET = 73 }; static const char *const spell []; static const int lhs []; static const int rhs []; #ifndef QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO static const int rule_index []; static const int rule_info []; #endif // QLALR_NO_GEDAELEMENTGRAMMAR_DEBUG_INFO static const int goto_default []; static const int action_default []; static const int action_index []; static const int action_info []; static const int action_check []; static inline int nt_action (int state, int nt) { const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; const int yyn = goto_index [state] + nt; if (yyn < 0 || goto_check [yyn] != nt) return goto_default [nt]; const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; return goto_info [yyn]; } static inline int t_action (int state, int token) { const int yyn = action_index [state] + token; if (yyn < 0 || action_check [yyn] != token) return - action_default [state]; return action_info [yyn]; } }; #endif // GEDAELEMENTGRAMMAR_P_H fritzing-app-0.9.2b/src/svg/gedaelementlexer.cpp000066400000000000000000000163171250202676700217210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 4067 $: $Author: cohen@irascible.com $: $Date: 2010-03-27 00:21:20 +0100 (Sa, 27. Mrz 2010) $ ********************************************************************/ #include "gedaelementlexer.h" #include "gedaelementgrammar_p.h" #include #include static QRegExp findWhitespace("[\\s]+"); GedaElementLexer::GedaElementLexer(const QString &source) { m_nonWhitespaceMatcher.setPattern("[^\\s]"); m_commentMatcher.setPattern("(^\\s*\\#)"); m_elementMatcher.setPattern("Element\\s*([\\(\\[])"); //m_stringMatcher.setPattern("\"([^\"]*)\""); m_stringMatcher.setPattern("\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\""); m_integerMatcher.setPattern("[-+]?\\d+"); m_hexMatcher.setPattern("0[xX][0-9a-fA-F]+"); m_source = clean(source); m_chars = m_source.unicode(); m_size = m_source.size(); //qDebug() << m_source; m_pos = 0; m_current = next(); } GedaElementLexer::~GedaElementLexer() { } QString GedaElementLexer::clean(const QString & source) { // clean it up to make it easier to parse QStringList s = source.split("\n"); for (int i = s.length() - 1; i >= 0; i--) { QString str = s[i]; if (m_commentMatcher.indexIn(str) == 0) { s.removeAt(i); str = str.remove(0, m_commentMatcher.matchedLength()); if (m_nonWhitespaceMatcher.indexIn(str) >= 0) { m_comments.push_front(str.trimmed()); } } } QString s1 = s.join("\n"); QString s2 = s1.replace(findWhitespace, " "); int ix = m_elementMatcher.indexIn(s2); if (ix < 0) { return s2; } // now figure out how many params the Element has and fill in the missing ones // this is because Element grammar requires a longer lookahead than provided by an LALR(1) parser QStringList params; GedaElementLexer lexer(s2.right(s2.length() - m_elementMatcher.matchedLength() - ix)); int nix = ix; bool done = false; while (!done) { int result = lexer.lex(); if (result <= 0) break; switch (result) { case GedaElementGrammar::HEXNUMBER: case GedaElementGrammar::NUMBER: case GedaElementGrammar::STRING: params.append(lexer.m_currentString); break; case GedaElementGrammar::RIGHTBRACKET: nix = lexer.m_pos - 2; done = true; break; case GedaElementGrammar::RIGHTPAREN: nix = lexer.m_pos - 2; done = true; break; default: return s2; } } if (params.count() == 11) { // no changes required return s2; } bool swap = false; if (params.count() == 9) { // insert MX and MY params.insert(4, "0"); params.insert(4, "0"); swap = true; } if (params.count() == 8) { // insert value params.insert(3, "\"\""); // insert MX and MY params.insert(4, "0"); params.insert(4, "0"); swap = true; } if (params.count() == 7) { // insert SFlags params.insert(0, "\"\""); // insert value params.insert(3, "\"\""); // insert MX and MY params.insert(4, "0"); params.insert(4, "0"); swap = true; } if (!swap) { return s2; } QString j = params.join(" "); return s2.replace(ix + m_elementMatcher.matchedLength(), nix, j); } int GedaElementLexer::lex() { while (true) { if (m_hexMatcher.indexIn(m_source, m_pos - 1) == m_pos - 1) { bool ok; m_currentString = m_hexMatcher.cap(0); m_currentNumber = m_currentString.toLong(&ok, 16); m_pos += m_hexMatcher.matchedLength() - 1; if (m_source.at(m_pos).isSpace()) { m_pos++; } next(); return GedaElementGrammar::HEXNUMBER; } else if (m_integerMatcher.indexIn(m_source, m_pos - 1) == m_pos - 1) { m_currentString = m_integerMatcher.cap(0); m_currentNumber = m_currentString.toLong(); m_pos += m_integerMatcher.matchedLength() - 1; if (m_source.at(m_pos).isSpace()) { m_pos++; } next(); return GedaElementGrammar::NUMBER; } else if (m_stringMatcher.indexIn(m_source, m_pos - 1) == m_pos - 1) { m_currentString = m_stringMatcher.cap(0); m_pos += m_stringMatcher.matchedLength() - 1; next(); return GedaElementGrammar::STRING; } else if (m_current.isSpace()) { next(); continue; } else if (m_current.isNull()) { return GedaElementGrammar::EOF_SYMBOL; } else if (m_current == QLatin1Char('(')) { next(); return GedaElementGrammar::LEFTPAREN; } else if (m_current == QLatin1Char(')')) { next(); return GedaElementGrammar::RIGHTPAREN; } else if (m_current == QLatin1Char('[')) { next(); return GedaElementGrammar::LEFTBRACKET; } else if (m_current == QLatin1Char(']')) { next(); return GedaElementGrammar::RIGHTBRACKET; } else if (m_source.indexOf("elementline", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "elementline"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::ELEMENTLINE; } else if (m_source.indexOf("elementarc", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "elementarc"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::ELEMENTARC; } else if (m_source.indexOf("attribute", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "attribute"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::ATTRIBUTE; } else if (m_source.indexOf("element", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "element"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::ELEMENT; } else if (m_source.indexOf("pad", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "pad"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::PAD; } else if (m_source.indexOf("pin", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "pin"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::PIN; } else if (m_source.indexOf("mark", m_pos - 1, Qt::CaseInsensitive) == m_pos - 1) { m_currentCommand = "mark"; m_pos += m_currentCommand.length() - 1; next(); return GedaElementGrammar::MARK; } return -1; } } QChar GedaElementLexer::next() { if (m_pos < m_size) m_current = m_chars[m_pos++]; else m_current = QChar(); return m_current; } QString GedaElementLexer::currentCommand() { return m_currentCommand; } double GedaElementLexer::currentNumber() { return m_currentNumber; } QString GedaElementLexer::currentString() { return m_currentString; } const QStringList & GedaElementLexer::comments() { return m_comments; } fritzing-app-0.9.2b/src/svg/gedaelementlexer.h000066400000000000000000000035341250202676700213630ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 4067 $: $Author: cohen@irascible.com $: $Date: 2010-03-27 00:21:20 +0100 (Sa, 27. Mrz 2010) $ ********************************************************************/ #ifndef GEDAELEMENTLEXER_H #define GEDAELEMENTLEXER_H #include #include #include #include class GedaElementLexer { public: GedaElementLexer(const QString &source); ~GedaElementLexer(); int lex(); QString currentCommand(); double currentNumber(); QString currentString(); const QStringList & comments(); protected: QChar next(); QString clean(const QString & source); protected: QString m_source; const QChar *m_chars; int m_size; int m_pos; QChar m_current; QString m_currentCommand; long m_currentNumber; long m_currentHexString; QString m_currentString; QRegExp m_integerMatcher; QRegExp m_hexMatcher; QRegExp m_stringMatcher; QRegExp m_elementMatcher; QRegExp m_commentMatcher; QRegExp m_nonWhitespaceMatcher; QStringList m_comments; }; #endif fritzing-app-0.9.2b/src/svg/gedaelementparser.cpp000066400000000000000000000214421250202676700220710ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 4224 $: $Author: cohen@irascible.com $: $Date: 2010-06-07 14:51:32 +0200 (Mo, 07. Jun 2010) $ ********************************************************************/ #include #include "gedaelementparser.h" #include "gedaelementlexer.h" GedaElementParser::GedaElementParser() { } GedaElementParser::~GedaElementParser() { } QVector & GedaElementParser::symStack() { return m_symStack; } void GedaElementParser::reallocateStack() { int size = m_stateStack.size(); if (size == 0) size = 128; else size <<= 1; m_stateStack.resize(size); } QString GedaElementParser::errorMessage() const { return m_errorMessage; } QVariant GedaElementParser::result() const { return m_result; } bool GedaElementParser::parse(GedaElementLexer *lexer) { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); m_tos = 0; m_stateStack[++m_tos] = INITIAL_STATE; while (true) { const int state = m_stateStack.at(m_tos); if (yytoken == -1 && - TERMINAL_COUNT != action_index [state]) yytoken = lexer->lex(); int act = t_action (state, yytoken); if (act == ACCEPT_STATE) return true; else if (act > 0) { if (++m_tos == m_stateStack.size()) reallocateStack(); m_stateStack[m_tos] = act; yytoken = -1; } else if (act < 0) { int r = - act - 1; m_tos -= rhs [r]; act = m_stateStack.at(m_tos++); switch (r) { case 0: { //qDebug() << "got geda_element "; } break; case 2: { } break; case 3: { m_symStack.append(QChar(')')); } break; case 4: { m_symStack.append(QChar(']')); } break; case 6: { //qDebug() << " got element_command sequence "; } break; case 7: { m_symStack.append(QChar(')')); //qDebug() << " got element_command sequence "; } break; case 8: { m_symStack.append(QChar(']')); //qDebug() << " got element_command sequence "; } break; case 9: { //qDebug() << " got element_arguments "; } break; case 11: { //qDebug() << " got sub_element_groups "; } break; case 17: { //qDebug() << " got sub_element_group "; } break; case 18: { //qDebug() << "got mark_element "; } break; case 20: { //qDebug() << " got mark_sequence "; } break; case 21: { m_symStack.append(QChar(')')); //qDebug() << " got mark_paren_sequence "; } break; case 22: { m_symStack.append(QChar(']')); //qDebug() << " got mark_bracket_sequence "; } break; case 23: { //qDebug() << " got mark_arguments"; } break; case 24: { //qDebug() << "got pin_element "; } break; case 26: { //qDebug() << " got pin_sequence "; } break; case 27: { m_symStack.append(QChar(')')); //qDebug() << " got pin_paren_sequence "; } break; case 28: { m_symStack.append(QChar(']')); //qDebug() << " got pin_bracket_sequence "; } break; case 32: { //qDebug() << " got pin_arguments "; } break; case 33: { //qDebug() << " got pin_arguments 1"; } break; case 34: { //qDebug() << " got pin_arguments 2"; } break; case 35: { //qDebug() << " got pin_arguments 3"; } break; case 36: { //qDebug() << " got pin_arguments 4 "; } break; case 37: { //qDebug() << "got pad_element "; } break; case 39: { //qDebug() << " got pad_sequence "; } break; case 40: { m_symStack.append(QChar(')')); //qDebug() << " got pad_paren_sequence "; } break; case 41: { m_symStack.append(QChar(']')); //qDebug() << " got pad_bracket_sequence "; } break; case 44: { //qDebug() << " got pad_arguments "; } break; case 45: { //qDebug() << " got pad_arguments 1"; } break; case 46: { //qDebug() << " got pad_arguments 2"; } break; case 47: { //qDebug() << " got pad_arguments 3"; } break; case 48: { //qDebug() << "got element_line_element "; } break; case 50: { //qDebug() << " got element_line_sequence "; } break; case 51: { m_symStack.append(QChar(')')); //qDebug() << " got element_line_paren_sequence "; } break; case 52: { m_symStack.append(QChar(']')); //qDebug() << " got element_line_bracket_sequence "; } break; case 53: { //qDebug() << " got element_line_arguments "; } break; case 54: { //qDebug() << "got element_arc_element "; } break; case 56: { //qDebug() << " got element_arc_sequence "; } break; case 57: { m_symStack.append(QChar(')')); //qDebug() << " got element_arc_paren_sequence "; } break; case 58: { m_symStack.append(QChar(']')); //qDebug() << " got element_arc_bracket_sequence "; } break; case 59: { //qDebug() << " got element_arc_arguments "; } break; case 60: { //qDebug() << "got attribute_element "; } break; case 61: { //qDebug() << " got attribute_sequence "; } break; case 62: { m_symStack.append(QChar(')')); //qDebug() << " got attribute_paren_sequence "; } break; case 63: { //qDebug() << " got attribute_arguments "; } break; case 64: { } break; case 65: { } break; case 66: { } break; case 67: { } break; case 68: { } break; case 69: { } break; case 70: { } break; case 71: { } break; case 72: { } break; case 73: { } break; case 74: { } break; case 75: { } break; case 76: { } break; case 77: { } break; case 78: { } break; case 79: { } break; case 80: { } break; case 82: { } break; case 83: { } break; case 84: { } break; case 85: { } break; case 86: { } break; case 87: { } break; case 88: { } break; case 89: { } break; case 90: { } break; case 91: { } break; case 92: { } break; case 93: { //qDebug() << " got NUMBER " << lexer->currentNumber(); m_symStack.append(lexer->currentNumber()); } break; case 94: { //qDebug() << " got HEXNUMBER " << lexer->currentNumber(); m_symStack.append(lexer->currentNumber()); } break; case 95: { //qDebug() << " got STRING " << lexer->currentString(); m_symStack.append(lexer->currentString()); } break; case 96: { //qDebug() << "got ELEMENT command "; m_symStack.append(lexer->currentCommand()); } break; case 97: { //qDebug() << "got PIN command "; m_symStack.append(lexer->currentCommand()); } break; case 98: { //qDebug() << "got PAD command "; m_symStack.append(lexer->currentCommand()); } break; case 99: { //qDebug() << "got MARK command "; m_symStack.append(lexer->currentCommand()); } break; case 100: { //qDebug() << "got ELEMENTLINE command "; m_symStack.append(lexer->currentCommand()); } break; case 101: { //qDebug() << "got ELEMENTARC command "; m_symStack.append(lexer->currentCommand()); } break; case 102: { //qDebug() << "got ATTRIBUTE command "; m_symStack.append(lexer->currentCommand()); } break; } // switch m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT); } else { int ers = state; int shifts = 0; int reduces = 0; int expected_tokens[3]; for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (! k) continue; else if (k < 0) ++reduces; else if (spell[tk]) { if (shifts < 3) expected_tokens[shifts] = tk; ++shifts; } } m_errorMessage.clear(); if (shifts && shifts < 3) { bool first = true; for (int s = 0; s < shifts; ++s) { if (first) m_errorMessage += QLatin1String("Expected "); else m_errorMessage += QLatin1String(", "); first = false; m_errorMessage += QLatin1String("`"); m_errorMessage += QLatin1String(spell[expected_tokens[s]]); m_errorMessage += QLatin1String("'"); } } return false; } } return false; } fritzing-app-0.9.2b/src/svg/gedaelementparser.h000066400000000000000000000032461250202676700215400ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 3848 $: $Author: cohen@irascible.com $: $Date: 2009-12-10 12:48:23 +0100 (Do, 10. Dez 2009) $ ********************************************************************/ #ifndef GEDAELEMENTPARSER_H #define GEDAELEMENTPARSER_H #include #include #include "gedaelementgrammar_p.h" class GedaElementLexer; class GedaElementParser: public GedaElementGrammar { public: GedaElementParser(); ~GedaElementParser(); bool parse(GedaElementLexer *lexer); QVector & symStack(); QString errorMessage() const; QVariant result() const; private: void reallocateStack(); int m_tos; QVector m_stateStack; QVector m_symStack; QString m_errorMessage; QVariant m_result; }; #endif // GEDAELEMENTPARSER_H fritzing-app-0.9.2b/src/svg/gerbergenerator.cpp000066400000000000000000001215441250202676700215630ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #include #include #include #include #include "gerbergenerator.h" #include "../debugdialog.h" #include "../fsvgrenderer.h" #include "../sketch/pcbsketchwidget.h" #include "../connectors/connectoritem.h" #include "../connectors/svgidlayer.h" #include "svgfilesplitter.h" #include "groundplanegenerator.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../utils/folderutils.h" #include "../version/version.h" static const QRegExp AaCc("[aAcCqQtTsS]"); static const QRegExp MFinder("([mM])\\s*([0-9.]*)[\\s,]*([0-9.]*)"); const QRegExp GerberGenerator::MultipleZs("z\\s*[^\\s]"); const QString GerberGenerator::SilkTopSuffix = "_silkTop.gto"; const QString GerberGenerator::SilkBottomSuffix = "_silkBottom.gbo"; const QString GerberGenerator::CopperTopSuffix = "_copperTop.gtl"; const QString GerberGenerator::CopperBottomSuffix = "_copperBottom.gbl"; const QString GerberGenerator::MaskTopSuffix = "_maskTop.gts"; const QString GerberGenerator::MaskBottomSuffix = "_maskBottom.gbs"; const QString GerberGenerator::PasteMaskTopSuffix = "_pasteMaskTop.gtp"; const QString GerberGenerator::PasteMaskBottomSuffix = "_pasteMaskBottom.gbp"; const QString GerberGenerator::DrillSuffix = "_drill.txt"; const QString GerberGenerator::OutlineSuffix = "_contour.gm1"; const QString GerberGenerator::MagicBoardOutlineID = "boardoutline"; const double GerberGenerator::MaskClearanceMils = 5; //////////////////////////////////////////// bool pixelsCollide(QImage * image1, QImage * image2, int x1, int y1, int x2, int y2) { for (int y = y1; y < y2; y++) { for (int x = x1; x < x2; x++) { QRgb p1 = image1->pixel(x, y); if (p1 == 0xffffffff) continue; QRgb p2 = image2->pixel(x, y); if (p2 == 0xffffffff) continue; //DebugDialog::debug(QString("p1:%1 p2:%2").arg(p1, 0, 16).arg(p2, 0, 16)); return true; } } return false; } //////////////////////////////////////////// void GerberGenerator::exportToGerber(const QString & prefix, const QString & exportDir, ItemBase * board, PCBSketchWidget * sketchWidget, bool displayMessageBoxes) { if (board == NULL) { int boardCount; board = sketchWidget->findSelectedBoard(boardCount); if (boardCount == 0) { DebugDialog::debug("board not found"); return; } if (board == NULL) { DebugDialog::debug("multiple boards found"); return; } } exportPickAndPlace(prefix, exportDir, board, sketchWidget, displayMessageBoxes); LayerList viewLayerIDs = ViewLayer::copperLayers(ViewLayer::NewBottom); int copperInvalidCount = doCopper(board, sketchWidget, viewLayerIDs, "Copper0", CopperBottomSuffix, prefix, exportDir, displayMessageBoxes); if (sketchWidget->boardLayers() == 2) { viewLayerIDs = ViewLayer::copperLayers(ViewLayer::NewTop); copperInvalidCount += doCopper(board, sketchWidget, viewLayerIDs, "Copper1", CopperTopSuffix, prefix, exportDir, displayMessageBoxes); } LayerList maskLayerIDs = ViewLayer::maskLayers(ViewLayer::NewBottom); QString maskBottom, maskTop; int maskInvalidCount = doMask(maskLayerIDs, "Mask0", MaskBottomSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes, maskBottom); if (sketchWidget->boardLayers() == 2) { maskLayerIDs = ViewLayer::maskLayers(ViewLayer::NewTop); maskInvalidCount += doMask(maskLayerIDs, "Mask1", MaskTopSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes, maskTop); } maskLayerIDs = ViewLayer::maskLayers(ViewLayer::NewBottom); int pasteMaskInvalidCount = doPasteMask(maskLayerIDs, "PasteMask0", PasteMaskBottomSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes); if (sketchWidget->boardLayers() == 2) { maskLayerIDs = ViewLayer::maskLayers(ViewLayer::NewTop); pasteMaskInvalidCount += doPasteMask(maskLayerIDs, "PasteMask1", PasteMaskTopSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes); } LayerList silkLayerIDs = ViewLayer::silkLayers(ViewLayer::NewTop); int silkInvalidCount = doSilk(silkLayerIDs, "Silk1", SilkTopSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes, maskTop); silkLayerIDs = ViewLayer::silkLayers(ViewLayer::NewBottom); silkInvalidCount += doSilk(silkLayerIDs, "Silk0", SilkBottomSuffix, board, sketchWidget, prefix, exportDir, displayMessageBoxes, maskBottom); // now do it for the outline/contour LayerList outlineLayerIDs = ViewLayer::outlineLayers(); bool empty; QString svgOutline = renderTo(outlineLayerIDs, board, sketchWidget, empty); if (empty || svgOutline.isEmpty()) { displayMessage(QObject::tr("outline is empty"), displayMessageBoxes); return; } svgOutline = cleanOutline(svgOutline); // at this point svgOutline must be a single element; a path element may contain cutouts QMultiHash treatAsCircle; svgOutline = clipToBoard(svgOutline, board, "board", SVG2gerber::ForOutline, "", displayMessageBoxes, treatAsCircle); QSizeF svgSize = TextUtils::parseForWidthAndHeight(svgOutline); // create outline gerber from svg SVG2gerber outlineGerber; int outlineInvalidCount = outlineGerber.convert(svgOutline, sketchWidget->boardLayers() == 2, "contour", SVG2gerber::ForOutline, svgSize * GraphicsUtils::StandardFritzingDPI); //DebugDialog::debug(QString("outline output: %1").arg(outlineGerber.getGerber())); saveEnd("contour", exportDir, prefix, OutlineSuffix, displayMessageBoxes, outlineGerber); doDrill(board, sketchWidget, prefix, exportDir, displayMessageBoxes); if (outlineInvalidCount > 0 || silkInvalidCount > 0 || copperInvalidCount > 0 || maskInvalidCount || pasteMaskInvalidCount) { QString s; if (outlineInvalidCount > 0) s += QObject::tr("the board outline layer, "); if (silkInvalidCount > 0) s += QObject::tr("silkscreen layer(s), "); if (copperInvalidCount > 0) s += QObject::tr("copper layer(s), "); if (maskInvalidCount > 0) s += QObject::tr("mask layer(s), "); if (pasteMaskInvalidCount > 0) s += QObject::tr("paste mask layer(s), "); s.chop(2); displayMessage(QObject::tr("Unable to translate svg curves in %1").arg(s), displayMessageBoxes); } } int GerberGenerator::doCopper(ItemBase * board, PCBSketchWidget * sketchWidget, LayerList & viewLayerIDs, const QString & copperName, const QString & copperSuffix, const QString & filename, const QString & exportDir, bool displayMessageBoxes) { bool empty; QString svg = renderTo(viewLayerIDs, board, sketchWidget, empty); if (empty || svg.isEmpty()) { displayMessage(QObject::tr("%1 layer export is empty.").arg(copperName), displayMessageBoxes); return 0; } QMultiHash treatAsCircle; foreach (QGraphicsItem * item, sketchWidget->scene()->collidingItems(board)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->isPath()) continue; if (connectorItem->radius() == 0) continue; treatAsCircle.insert(connectorItem->attachedToID(), connectorItem); } QSizeF svgSize = TextUtils::parseForWidthAndHeight(svg); svg = clipToBoard(svg, board, copperName, SVG2gerber::ForCopper, "", displayMessageBoxes, treatAsCircle); if (svg.isEmpty()) { displayMessage(QObject::tr("%1 layer export is empty (case 2).").arg(copperName), displayMessageBoxes); return 0; } return doEnd(svg, sketchWidget->boardLayers(), copperName, SVG2gerber::ForCopper, svgSize * GraphicsUtils::StandardFritzingDPI, exportDir, filename, copperSuffix, displayMessageBoxes); } int GerberGenerator::doSilk(LayerList silkLayerIDs, const QString & silkName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes, const QString & clipString) { bool empty; QString svgSilk = renderTo(silkLayerIDs, board, sketchWidget, empty); if (empty || svgSilk.isEmpty()) { if (silkLayerIDs.contains(ViewLayer::Silkscreen1)) { displayMessage(QObject::tr("silk layer %1 export is empty").arg(silkName), displayMessageBoxes); } return 0; } //QFile f(silkName + "original.svg"); //f.open(QFile::WriteOnly); //QTextStream fs(&f); //fs << svgSilk; //f.close(); QSizeF svgSize = TextUtils::parseForWidthAndHeight(svgSilk); QMultiHash treatAsCircle; svgSilk = clipToBoard(svgSilk, board, silkName, SVG2gerber::ForSilk, clipString, displayMessageBoxes, treatAsCircle); if (svgSilk.isEmpty()) { displayMessage(QObject::tr("silk export failure"), displayMessageBoxes); return 0; } //QFile f2(silkName + "clipped.svg"); //f2.open(QFile::WriteOnly); //QTextStream fs2(&f2); //fs2 << svgSilk; //f2.close(); return doEnd(svgSilk, sketchWidget->boardLayers(), silkName, SVG2gerber::ForSilk, svgSize * GraphicsUtils::StandardFritzingDPI, exportDir, filename, gerberSuffix, displayMessageBoxes); } int GerberGenerator::doDrill(ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes) { LayerList drillLayerIDs; drillLayerIDs << ViewLayer::drillLayers(); bool empty; QString svgDrill = renderTo(drillLayerIDs, board, sketchWidget, empty); if (empty || svgDrill.isEmpty()) { displayMessage(QObject::tr("exported drill file is empty"), displayMessageBoxes); return 0; } QSizeF svgSize = TextUtils::parseForWidthAndHeight(svgDrill); QMultiHash treatAsCircle; foreach (QGraphicsItem * item, sketchWidget->scene()->collidingItems(board)) { ConnectorItem * connectorItem = dynamic_cast(item); if (connectorItem == NULL) continue; if (!connectorItem->isPath()) continue; if (connectorItem->radius() == 0) continue; treatAsCircle.insert(connectorItem->attachedToID(), connectorItem); } svgDrill = clipToBoard(svgDrill, board, "Copper0", SVG2gerber::ForDrill, "", displayMessageBoxes, treatAsCircle); if (svgDrill.isEmpty()) { displayMessage(QObject::tr("drill export failure"), displayMessageBoxes); return 0; } return doEnd(svgDrill, sketchWidget->boardLayers(), "drill", SVG2gerber::ForDrill, svgSize * GraphicsUtils::StandardFritzingDPI, exportDir, filename, DrillSuffix, displayMessageBoxes); } int GerberGenerator::doMask(LayerList maskLayerIDs, const QString &maskName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes, QString & clipString) { // don't want these in the mask laqyer QList copperLogoItems; sketchWidget->hideCopperLogoItems(copperLogoItems); bool empty; QString svgMask = renderTo(maskLayerIDs, board, sketchWidget, empty); sketchWidget->restoreCopperLogoItems(copperLogoItems); if (empty || svgMask.isEmpty()) { displayMessage(QObject::tr("exported mask layer %1 is empty").arg(maskName), displayMessageBoxes); return 0; } svgMask = TextUtils::expandAndFill(svgMask, "black", MaskClearanceMils * 2); if (svgMask.isEmpty()) { displayMessage(QObject::tr("%1 mask export failure (2)").arg(maskName), displayMessageBoxes); return 0; } QSizeF svgSize = TextUtils::parseForWidthAndHeight(svgMask); QMultiHash treatAsCircle; svgMask = clipToBoard(svgMask, board, maskName, SVG2gerber::ForCopper, "", displayMessageBoxes, treatAsCircle); if (svgMask.isEmpty()) { displayMessage(QObject::tr("mask export failure"), displayMessageBoxes); return 0; } clipString = svgMask; return doEnd(svgMask, sketchWidget->boardLayers(), maskName, SVG2gerber::ForCopper, svgSize * GraphicsUtils::StandardFritzingDPI, exportDir, filename, gerberSuffix, displayMessageBoxes); } int GerberGenerator::doPasteMask(LayerList maskLayerIDs, const QString &maskName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes) { // don't want these in the mask laqyer QList copperLogoItems; sketchWidget->hideCopperLogoItems(copperLogoItems); QList holes; sketchWidget->hideHoles(holes); bool empty; QString svgMask = renderTo(maskLayerIDs, board, sketchWidget, empty); sketchWidget->restoreCopperLogoItems(copperLogoItems); sketchWidget->restoreCopperLogoItems(holes); if (empty || svgMask.isEmpty()) { displayMessage(QObject::tr("exported paste mask layer is empty"), displayMessageBoxes); return 0; } svgMask = sketchWidget->makePasteMask(svgMask, board, GraphicsUtils::StandardFritzingDPI, maskLayerIDs); if (svgMask.isEmpty()) return 0; QSizeF svgSize = TextUtils::parseForWidthAndHeight(svgMask); QMultiHash treatAsCircle; svgMask = clipToBoard(svgMask, board, maskName, SVG2gerber::ForCopper, "", displayMessageBoxes, treatAsCircle); if (svgMask.isEmpty()) { displayMessage(QObject::tr("mask export failure"), displayMessageBoxes); return 0; } return doEnd(svgMask, sketchWidget->boardLayers(), maskName, SVG2gerber::ForCopper, svgSize * GraphicsUtils::StandardFritzingDPI, exportDir, filename, gerberSuffix, displayMessageBoxes); } int GerberGenerator::doEnd(const QString & svg, int boardLayers, const QString & layerName, SVG2gerber::ForWhy forWhy, QSizeF svgSize, const QString & exportDir, const QString & prefix, const QString & suffix, bool displayMessageBoxes) { // create mask gerber from svg SVG2gerber gerber; int invalidCount = gerber.convert(svg, boardLayers == 2, layerName, forWhy, svgSize); saveEnd(layerName, exportDir, prefix, suffix, displayMessageBoxes, gerber); return invalidCount; } bool GerberGenerator::saveEnd(const QString & layerName, const QString & exportDir, const QString & prefix, const QString & suffix, bool displayMessageBoxes, SVG2gerber & gerber) { QString outname = exportDir + "/" + prefix + suffix; QFile out(outname); if (!out.open(QIODevice::WriteOnly | QIODevice::Text)) { displayMessage(QObject::tr("%1 layer: unable to save to '%2'").arg(layerName).arg(outname), displayMessageBoxes); return false; } QTextStream stream(&out); stream << gerber.getGerber(); stream.flush(); out.close(); return true; } void GerberGenerator::displayMessage(const QString & message, bool displayMessageBoxes) { // don't use QMessageBox if running conversion as a service if (displayMessageBoxes) { QMessageBox::warning(NULL, QObject::tr("Fritzing"), message); return; } DebugDialog::debug(message); } QString GerberGenerator::clipToBoard(QString svgString, ItemBase * board, const QString & layerName, SVG2gerber::ForWhy forWhy, const QString & clipString, bool displayMessageBoxes, QMultiHash & treatAsCircle) { QRectF source = board->sceneBoundingRect(); source.moveTo(0, 0); return clipToBoard(svgString, source, layerName, forWhy, clipString, displayMessageBoxes, treatAsCircle); } QString GerberGenerator::clipToBoard(QString svgString, QRectF & boardRect, const QString & layerName, SVG2gerber::ForWhy forWhy, const QString & clipString, bool displayMessageBoxes, QMultiHash & treatAsCircle) { // document 1 will contain svg that is easy to convert to gerber QDomDocument domDocument1; QString errorStr; int errorLine; int errorColumn; bool result = domDocument1.setContent(svgString, &errorStr, &errorLine, &errorColumn); if (!result) { return ""; } QDomElement root1 = domDocument1.documentElement(); if (root1.firstChildElement().isNull()) { return ""; } if (forWhy != SVG2gerber::ForDrill) { QDomNodeList nodeList = root1.elementsByTagName("circle"); QList justHoles; for (int i = 0; i < nodeList.count(); i++) { QDomElement circle = nodeList.at(i).toElement(); if (circle.attribute("id").contains(FSvgRenderer::NonConnectorName)) { double sw = circle.attribute("stroke-width").toDouble(); if (sw == 0) { justHoles << circle; } } } foreach (QDomElement circle, justHoles) { circle.setTagName("g"); } } handleDonuts(root1, treatAsCircle); bool multipleContours = false; if (forWhy == SVG2gerber::ForOutline) { multipleContours = dealWithMultipleContours(root1, displayMessageBoxes); } // document 2 will contain svg that must be rasterized for gerber conversion QDomDocument domDocument2 = domDocument1.cloneNode(true).toDocument(); bool anyConverted = false; if (TextUtils::squashElement(domDocument1, "text", "", QRegExp())) { anyConverted = true; } // gerber can't handle ellipses that are rotated, so cull them all if (TextUtils::squashElement(domDocument1, "ellipse", "", QRegExp())) { anyConverted = true; } if (TextUtils::squashElement(domDocument1, "rect", "rx", QRegExp())) { anyConverted = true; } if (TextUtils::squashElement(domDocument1, "rect", "ry", QRegExp())) { anyConverted = true; } // gerber can't handle paths with curves if (TextUtils::squashElement(domDocument1, "path", "d", AaCc)) { anyConverted = true; } // gerber can't handle multiple subpaths if there are intersections if (TextUtils::squashElement(domDocument1, "path", "d", MultipleZs)) { anyConverted = true; } if (TextUtils::squashElement(domDocument1, "image", "", QRegExp())) { anyConverted = true; } // can't handle scaled paths very well. There is probably a deeper bug that needs to be chased down. // is this only necessary for contour view? QDomNodeList nodeList = root1.elementsByTagName("path"); for (int i = 0; i < nodeList.count(); i++) { QDomNode parent = nodeList.at(i); while (!parent.isNull()) { QString transformString = parent.toElement().attribute("transform"); if (!transformString.isNull()) { QMatrix matrix = TextUtils::transformStringToMatrix(transformString); QTransform transform(matrix); if (transform.isScaling()) { nodeList.at(i).toElement().setTagName("g"); anyConverted = true; break; } } parent = parent.parentNode(); } } QVector leaves1; int transformCount1 = 0; QDomElement e1 = domDocument1.documentElement(); TextUtils::collectLeaves(e1, transformCount1, leaves1); QVector leaves2; int transformCount2 = 0; QDomElement e2 = domDocument2.documentElement(); TextUtils::collectLeaves(e2, transformCount2, leaves2); double res = GraphicsUtils::StandardFritzingDPI; // convert from pixel dpi to StandardFritzingDPI QRectF sourceRes(boardRect.left() * res / GraphicsUtils::SVGDPI, boardRect.top() * res / GraphicsUtils::SVGDPI, boardRect.width() * res / GraphicsUtils::SVGDPI, boardRect.height() * res / GraphicsUtils::SVGDPI); int twidth = sourceRes.width(); int theight = sourceRes.height(); QSize imgSize(twidth + 2, theight + 2); QRectF target(0, 0, twidth, theight); QImage * clipImage = NULL; if (!clipString.isEmpty()) { clipImage = new QImage(imgSize, QImage::Format_Mono); clipImage->fill(0xffffffff); clipImage->setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); clipImage->setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); QXmlStreamReader reader(clipString); QSvgRenderer renderer(&reader); QPainter painter; painter.begin(clipImage); renderer.render(&painter, target); painter.end(); #ifndef QT_NO_DEBUG clipImage->save(FolderUtils::getUserDataStorePath("") + "/clip.png"); #endif } svgString = TextUtils::removeXMLEntities(domDocument1.toString()); QList possibleHoles; QXmlStreamReader reader(svgString); QSvgRenderer renderer(&reader); bool anyClipped = false; if (forWhy != SVG2gerber::ForOutline) { for (int i = 0; i < transformCount1; i++) { QString n = QString::number(i); QRectF bounds = renderer.boundsOnElement(n); QMatrix m = renderer.matrixForElement(n); QDomElement element = leaves1.at(i); QRectF mBounds = m.mapRect(bounds); if (mBounds.left() < sourceRes.left() - 0.1|| mBounds.top() < sourceRes.top() - 0.1 || mBounds.right() > sourceRes.right() + 0.1 || mBounds.bottom() > sourceRes.bottom() + 0.1) { if (element.tagName() == "circle") { possibleHoles.append(element); } // element is outside of bounds--squash it so it will be clipped // we don't care if the board shape is irregular // since anything printed between the shape and the bounding rectangle // will be physically clipped when the board is cut out element.setTagName("g"); anyClipped = anyConverted = true; } } } if (possibleHoles.count() > 0) { QList newHoles; int ix = 0; foreach (QDomElement element, possibleHoles) { QDomElement newElement = element.cloneNode(false).toElement(); double radius = element.attribute("r").toDouble(); double sw = element.attribute("stroke-width").toDouble(); element.parentNode().insertAfter(newElement, element); newElement.setAttribute("id", QString("__%1__").arg(ix++)); newElement.setAttribute("stroke-width", 0); newElement.setAttribute("r", QString::number(radius - (sw / 2))); newElement.setTagName("circle"); newHoles.append(newElement); } QSvgRenderer renderer(domDocument1.toByteArray()); for (int i = newHoles.count() - 1; i >= 0; i--) { QString id = QString("__%1__").arg(i); QRectF bounds = renderer.boundsOnElement(id); QMatrix m = renderer.matrixForElement(id); QDomElement newElement = newHoles.at(i); QRectF mBounds = m.mapRect(bounds); if (mBounds.left() < sourceRes.left() - 0.1 || mBounds.top() < sourceRes.top() - 0.1 || mBounds.right() > sourceRes.right() + 0.1 || mBounds.bottom() > sourceRes.bottom() + 0.1) { // hole is still clipped newHoles.removeAt(i); newElement.parentNode().removeChild(newElement); } else { // enlarge it a little due to aliasing when the clipped portion is converted to raster and back double radius = newElement.attribute("r").toDouble(); radius += 4; newElement.setAttribute("r", QString::number(radius)); newElement.setAttribute("stroke-width", 2); } } } if (clipImage) { QImage another(imgSize, QImage::Format_Mono); another.fill(0xffffffff); another.setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); another.setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); svgString = TextUtils::removeXMLEntities(domDocument1.toString()); QXmlStreamReader reader(svgString); QSvgRenderer renderer(&reader); QPainter painter; painter.begin(&another); renderer.render(&painter, target); painter.end(); for (int i = 0; i < transformCount1; i++) { QDomElement element = leaves1.at(i); if (element.tagName().compare("g") == 0) { // element is already converted to raster space, we'll clip it later continue; } QString n = QString::number(i); QRectF bounds = renderer.boundsOnElement(n); QMatrix m = renderer.matrixForElement(n); QRectF mBounds = m.mapRect(bounds); int x1 = qFloor(qMax(0.0, mBounds.left() - sourceRes.left())); // atmel compiler fails without cast int x2 = qCeil(qMin(sourceRes.width(), mBounds.right() - sourceRes.left())); int y1 = qFloor(qMax(0.0, mBounds.top() - sourceRes.top())); // atmel compiler fails without cast int y2 = qCeil(qMin(sourceRes.height(), mBounds.bottom() - sourceRes.top())); if (pixelsCollide(&another, clipImage, x1, y1, x2, y2)) { element.setTagName("g"); anyClipped = anyConverted = true; } } } if (anyClipped) { // svg has been changed by clipping process so get the string again svgString = TextUtils::removeXMLEntities(domDocument1.toString()); } if (anyConverted) { for (int i = 0; i < transformCount1; i++) { QDomElement element1 = leaves1.at(i); if (element1.tagName().compare("g") != 0) { // document 1 element svg can be directly converted to gerber // so remove it from document 2 QDomElement element2 = leaves2.at(i); element2.setTagName("g"); } } // expand the svg to fill the space of the image QDomElement root2 = domDocument2.documentElement(); root2.setAttribute("width", QString("%1px").arg(twidth)); root2.setAttribute("height", QString("%1px").arg(theight)); if (boardRect.x() != 0 || boardRect.y() != 0) { QString viewBox = root2.attribute("viewBox"); QStringList coords = viewBox.split(" ", QString::SkipEmptyParts); coords[0] = QString::number(sourceRes.left()); coords[1] = QString::number(sourceRes.top()); root2.setAttribute("viewBox", coords.join(" ")); } QStringList exceptions; exceptions << "none" << ""; QString toColor("#000000"); SvgFileSplitter::changeColors(root2, toColor, exceptions); QImage image(imgSize, QImage::Format_Mono); image.setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); image.setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); if (forWhy == SVG2gerber::ForOutline) { QDomNodeList paths = root2.elementsByTagName("path"); if (paths.count() == 0) { // some non-path element makes up the outline mergeOutlineElement(image, target, res, domDocument2, svgString, 0, layerName); } else { for (int p = 0; p < paths.count(); p++) { QDomElement path = paths.at(p).toElement(); path.setTagName("g"); } for (int p = 0; p < paths.count(); p++) { QDomElement path = paths.at(p).toElement(); path.setTagName("path"); if (p > 0) { paths.at(p - 1).toElement().setTagName("g"); } mergeOutlineElement(image, target, res, domDocument2, svgString, p, layerName); } } } else { image.fill(0xffffffff); QByteArray svg = TextUtils::removeXMLEntities(domDocument2.toString()).toUtf8(); QSvgRenderer renderer(svg); QPainter painter; painter.begin(&image); renderer.render(&painter, target); painter.end(); image.invertPixels(); // need white pixels on a black background for GroundPlaneGenerator #ifndef QT_NO_DEBUG image.save(FolderUtils::getUserDataStorePath("") + "/preclip_output.png"); #endif if (clipImage != NULL) { // can this be done with a single blt using composition mode // if not, grab a scanline instead of testing every pixel for (int y = 0; y < theight; y++) { for (int x = 0; x < twidth; x++) { if (clipImage->pixel(x, y) != 0xffffffff) { image.setPixel(x, y, 0); } } } } #ifndef QT_NO_DEBUG image.save(FolderUtils::getUserDataStorePath("") + "/output.png"); #endif QString path = makePath(image, res / GraphicsUtils::StandardFritzingDPI, "#000000"); svgString.replace("", path + ""); /* GroundPlaneGenerator gpg; gpg.setLayerName(layerName); gpg.setMinRunSize(1, 1); gpg.scanImage(image, image.width(), image.height(), GraphicsUtils::StandardFritzingDPI / res, GraphicsUtils::StandardFritzingDPI, "#000000", false, false, QSizeF(0, 0), 0, sourceRes.topLeft()); if (gpg.newSVGs().count() > 0) { svgString = gpg.mergeSVGs(svgString, ""); } */ } } if (clipImage) delete clipImage; return QString(svgString); } QString GerberGenerator::cleanOutline(const QString & outlineSvg) { QDomDocument doc; doc.setContent(outlineSvg); QList leaves; QDomElement root = doc.documentElement(); TextUtils::collectLeaves(root, leaves); QDomNodeList textNodes = root.elementsByTagName("text"); for (int t = 0; t < textNodes.count(); t++) { leaves << textNodes.at(t).toElement(); } if (leaves.count() == 0) return ""; if (leaves.count() == 1) return outlineSvg; if (leaves.count() > 1) { for (int i = 0; i < leaves.count(); i++) { QDomElement leaf = leaves.at(i); if (leaf.attribute("id", "").compare(MagicBoardOutlineID) == 0) { for (int j = 0; j < leaves.count(); j++) { if (i != j) { QDomElement jleaf = leaves.at(j); jleaf.parentNode().removeChild(jleaf); } } return doc.toString(); } } } if (leaves.count() == 0) return ""; return outlineSvg; } void GerberGenerator::mergeOutlineElement(QImage & image, QRectF & target, double res, QDomDocument & document, QString & svgString, int ix, const QString & layerName) { image.fill(0xffffffff); QByteArray svg = TextUtils::removeXMLEntities(document.toString()).toUtf8(); QSvgRenderer renderer(svg); QPainter painter; painter.begin(&image); renderer.render(&painter, target); painter.end(); image.invertPixels(); // need white pixels on a black background for GroundPlaneGenerator #ifndef QT_NO_DEBUG image.save(QString("%2/output%1.png").arg(ix).arg(FolderUtils::getUserDataStorePath(""))); #else Q_UNUSED(ix); #endif GroundPlaneGenerator gpg; gpg.setLayerName(layerName); gpg.setMinRunSize(1, 1); gpg.scanOutline(image, image.width(), image.height(), GraphicsUtils::StandardFritzingDPI / res, GraphicsUtils::StandardFritzingDPI, "#000000", false, false, QSizeF(0, 0), 0); if (gpg.newSVGs().count() > 0) { svgString = gpg.mergeSVGs(svgString, ""); } } QString GerberGenerator::makePath(QImage & image, double unit, const QString & colorString) { double halfUnit = unit / 2; QString paths; int lineCount = 0; for (int y = 0; y < image.height(); y++) { bool inWhite = false; int whiteStart = 0; for (int x = 0; x < image.width(); x++) { QRgb current = image.pixel(x, y); if (inWhite) { if (current == 0xffffffff) { // another white pixel, keep moving continue; } // got black: close up this segment; inWhite = false; paths += QString("M%1,%2L%3,%2 ").arg(whiteStart + halfUnit).arg(y + halfUnit).arg(x - 1 + halfUnit); if (++lineCount == 10) { lineCount = 0; paths += "\n"; } } else { if (current != 0xffffffff) { // another black pixel, keep moving continue; } inWhite = true; whiteStart = x; } } } QString path = QString("\n"; } bool GerberGenerator::dealWithMultipleContours(QDomElement & root, bool displayMessageBoxes) { bool multipleContours = false; bool contoursOK = true; // split path into multiple contours QDomNodeList paths = root.elementsByTagName("path"); // should only be one for (int p = 0; p < paths.count() && contoursOK; p++) { QDomElement path = paths.at(p).toElement(); QString originalPath = path.attribute("d", "").trimmed(); if (MultipleZs.indexIn(originalPath) < 0) continue; multipleContours = true; QStringList subpaths = path.attribute("d").split("z", QString::SkipEmptyParts); foreach (QString subpath, subpaths) { if (!subpath.trimmed().startsWith("m", Qt::CaseInsensitive)) { contoursOK = false; break; } } } if (!multipleContours) return false; if (!contoursOK) { QString msg = QObject::tr("Fritzing is unable to process the cutouts in this custom PCB shape. ") + QObject::tr("You may need to reload the shape SVG. ") + QObject::tr("Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor."); displayMessage(msg, displayMessageBoxes); return false; } for (int p = 0; p < paths.count(); p++) { QDomElement path = paths.at(p).toElement(); QString originalPath = path.attribute("d", "").trimmed(); if (MultipleZs.indexIn(originalPath) >= 0) { QStringList subpaths = path.attribute("d").split("z", QString::SkipEmptyParts); QString priorM; MFinder.indexIn(subpaths.at(0).trimmed()); priorM += MFinder.cap(1) + MFinder.cap(2) + "," + MFinder.cap(3) + " "; for (int i = 1; i < subpaths.count(); i++) { QDomElement newPath = path.cloneNode(true).toElement(); QString z = ((i < subpaths.count() - 1) || originalPath.endsWith("z", Qt::CaseInsensitive)) ? "z" : ""; QString d = subpaths.at(i).trimmed() + z; MFinder.indexIn(d); if (d.startsWith("m", Qt::CaseSensitive)) { d = priorM + d; } priorM += MFinder.cap(1) + MFinder.cap(2) + "," + MFinder.cap(3) + " "; newPath.setAttribute("d", d); path.parentNode().appendChild(newPath); } path.setAttribute("d", subpaths.at(0) + "z"); } } return true; } void GerberGenerator::exportPickAndPlace(const QString & prefix, const QString & exportDir, ItemBase * board, PCBSketchWidget * sketchWidget, bool displayMessageBoxes) { QPointF bottomLeft = board->sceneBoundingRect().bottomLeft(); QSet itemBases; foreach (QGraphicsItem * item, sketchWidget->scene()->collidingItems(board)) { ItemBase * itemBase = dynamic_cast(item); if (itemBase == NULL) continue; if (itemBase == board) continue; if (itemBase->itemType() == ModelPart::Wire) continue; itemBase = itemBase->layerKinChief(); if (!itemBase->isEverVisible()) continue; if (itemBase == board) continue; itemBases.insert(itemBase->layerKinChief()); } QString outname = exportDir + "/" + prefix + "_pnp.txt"; QFile out(outname); if (!out.open(QIODevice::WriteOnly | QIODevice::Text)) { displayMessage(QObject::tr("Unable to save pick and place file: %2").arg(outname), displayMessageBoxes); return; } QTextStream stream(&out); stream << "*Pick And Place List\n" << "*Company=\n" << "*Author=\n" //*Tel= //*Fax= << "*eMail=\n" << "*\n" << QString("*Project=%1\n").arg(prefix) // *Variant= << QString("*Date=%1\n").arg(QTime::currentTime().toString()) << QString("*CreatedBy=Fritzing %1\n").arg(Version::versionString()) << "*\n" << "*\n*Coordinates in mm, always center of component\n" << "*Origin 0/0=Lower left corner of PCB\n" << "*Rotation in degree (0-360, math. pos.)\n" << "*\n" << "*No;Value;Package;X;Y;Rotation;Side;Name\n" ; QStringList valueKeys; valueKeys << "resistance" << "capacitance" << "inductance" << "voltage" << "current" << "power"; int ix = 1; foreach (ItemBase * itemBase, itemBases) { QString value; foreach (QString valueKey, valueKeys) { value = itemBase->modelPart()->localProp(valueKey).toString(); if (!value.isEmpty()) break; value = itemBase->modelPart()->properties().value(valueKey); if (!value.isEmpty()) break; } QPointF loc = itemBase->sceneBoundingRect().center(); QTransform transform = itemBase->transform(); // doesn't account for scaling double angle = atan2(transform.m12(), transform.m11()) * 180 / M_PI; // No;Value;Package;X;Y;Rotation;Side;Name QString string = QString("%1;%2;%3;%4;%5;%6;%7;%8\n") .arg(ix++) .arg(value) .arg(itemBase->modelPart()->properties().value("package")) .arg(GraphicsUtils::pixels2mm(loc.x() - bottomLeft.x(), GraphicsUtils::SVGDPI)) .arg(GraphicsUtils::pixels2mm(loc.y() - bottomLeft.y(), GraphicsUtils::SVGDPI)) .arg(angle) .arg(itemBase->viewLayerID() == ViewLayer::Copper1 ? "Top" : "Bottom") .arg(itemBase->instanceTitle()) ; stream << string; stream.flush(); } out.close(); } void GerberGenerator::handleDonuts(QDomElement & root1, QMultiHash & treatAsCircle) { // most of this would not be necessary if we cached cleaned SVGs static const QString unique("%%%%%%%%%%%%%%%%%%%%%%%%_________________________________%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); QDomNodeList nodeList = root1.elementsByTagName("path"); if (treatAsCircle.count() > 0) { QStringList ids; foreach (ConnectorItem * connectorItem, treatAsCircle.values()) { ItemBase * itemBase = connectorItem->attachedTo(); SvgIdLayer * svgIdLayer = connectorItem->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); DebugDialog::debug(QString("treat as circle %1").arg(svgIdLayer->m_svgId)); ids << svgIdLayer->m_svgId; } for (int n = 0; n < nodeList.count(); n++) { QDomElement path = nodeList.at(n).toElement(); QString id = path.attribute("id"); if (id.isEmpty()) continue; DebugDialog::debug(QString("checking for %1").arg(id)); if (!ids.contains(id)) continue; QString pid; ConnectorItem * connectorItem = NULL; for (QDomElement parent = path.parentNode().toElement(); !parent.isNull(); parent = parent.parentNode().toElement()) { pid = parent.attribute("partID"); if (pid.isEmpty()) continue; QList connectorItems = treatAsCircle.values(pid.toLong()); if (connectorItems.count() == 0) break; foreach (ConnectorItem * candidate, connectorItems) { ItemBase * itemBase = candidate->attachedTo(); SvgIdLayer * svgIdLayer = candidate->connector()->fullPinInfo(itemBase->viewID(), itemBase->viewLayerID()); if (svgIdLayer->m_svgId == id) { connectorItem = candidate; break; } } if (connectorItem) break; } if (connectorItem == NULL) continue; //QString string; //QTextStream stream(&string); //path.save(stream, 0); //DebugDialog::debug("path " + string); connectorItem->debugInfo("make path"); path.setAttribute("id", unique); QSvgRenderer renderer; renderer.load(root1.ownerDocument().toByteArray()); QRectF bounds = renderer.boundsOnElement(unique); path.removeAttribute("id"); QDomElement circle = root1.ownerDocument().createElement("circle"); path.parentNode().insertBefore(circle, path); circle.setAttribute("id", id); QPointF p = bounds.center(); circle.setAttribute("cx", QString::number(p.x())); circle.setAttribute("cy", QString::number(p.y())); circle.setAttribute("r", QString::number(connectorItem->radius() * GraphicsUtils::StandardFritzingDPI / GraphicsUtils::SVGDPI)); circle.setAttribute("stroke-width", QString::number(connectorItem->strokeWidth() * GraphicsUtils::StandardFritzingDPI / GraphicsUtils::SVGDPI)); } } } QString GerberGenerator::renderTo(const LayerList & layers, ItemBase * board, PCBSketchWidget * sketchWidget, bool & empty) { RenderThing renderThing; renderThing.printerScale = GraphicsUtils::SVGDPI; renderThing.blackOnly = true; renderThing.dpi = GraphicsUtils::StandardFritzingDPI; renderThing.hideTerminalPoints = true; renderThing.selectedItems = renderThing.renderBlocker = false; QString svg = sketchWidget->renderToSVG(renderThing, board, layers); empty = renderThing.empty; return svg; } fritzing-app-0.9.2b/src/svg/gerbergenerator.h000066400000000000000000000112261250202676700212230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6955 $: $Author: irascibl@gmail.com $: $Date: 2013-04-06 23:14:37 +0200 (Sa, 06. Apr 2013) $ ********************************************************************/ #ifndef GERBERGENERATOR_H #define GERBERGENERATOR_H #include #include "../viewlayer.h" #include "svg2gerber.h" class GerberGenerator { public: static void exportToGerber(const QString & prefix, const QString & exportDir, class ItemBase * board, class PCBSketchWidget *, bool displayMessageBoxes); static QString clipToBoard(QString svgString, QRectF & boardRect, const QString & layerName, SVG2gerber::ForWhy, const QString & clipString, bool displayMessageBoxes, QMultiHash & treatAsCircle); static QString clipToBoard(QString svgString, ItemBase * board, const QString & layerName, SVG2gerber::ForWhy, const QString & clipString, bool displayMessageBoxes, QMultiHash & treatAsCircle); static int doEnd(const QString & svg, int boardLayers, const QString & layerName, SVG2gerber::ForWhy forWhy, QSizeF svgSize, const QString & exportDir, const QString & prefix, const QString & suffix, bool displayMessageBoxes); static QString cleanOutline(const QString & svgOutline); public: static const QString SilkTopSuffix; static const QString SilkBottomSuffix; static const QString CopperTopSuffix; static const QString CopperBottomSuffix; static const QString MaskTopSuffix; static const QString MaskBottomSuffix; static const QString PasteMaskTopSuffix; static const QString PasteMaskBottomSuffix; static const QString DrillSuffix; static const QString OutlineSuffix; static const QString MagicBoardOutlineID; static const double MaskClearanceMils; static const QRegExp MultipleZs; protected: static int doSilk(LayerList silkLayerIDs, const QString & silkName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes, const QString & clipString); static int doMask(LayerList maskLayerIDs, const QString & maskName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes, QString & clipString); static int doPasteMask(LayerList maskLayerIDs, const QString & maskName, const QString & gerberSuffix, ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes); static int doCopper(ItemBase * board, PCBSketchWidget * sketchWidget, LayerList & viewLayerIDs, const QString & copperName, const QString & copperSuffix, const QString & filename, const QString & exportDir, bool displayMessageBoxes); static int doDrill(ItemBase * board, PCBSketchWidget * sketchWidget, const QString & filename, const QString & exportDir, bool displayMessageBoxes); static void displayMessage(const QString & message, bool displayMessageBoxes); static bool saveEnd(const QString & layerName, const QString & exportDir, const QString & prefix, const QString & suffix, bool displayMessageBoxes, SVG2gerber & gerber); static void mergeOutlineElement(QImage & image, QRectF & target, double res, QDomDocument & document, QString & svgString, int ix, const QString & layerName); static QString makePath(QImage & image, double unit, const QString & colorString); static bool dealWithMultipleContours(QDomElement & root, bool displayMessageBoxes); static void exportPickAndPlace(const QString & prefix, const QString & exportDir, ItemBase * board, PCBSketchWidget * sketchWidget, bool displayMessageBoxes); static void handleDonuts(QDomElement & root1, QMultiHash & treatAsCircle); static QString renderTo(const LayerList &, ItemBase * board, PCBSketchWidget * sketchWidget, bool & empty); }; #endif // GERBERGENERATOR_H fritzing-app-0.9.2b/src/svg/groundplanegenerator.cpp000066400000000000000000001070221250202676700226260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, orF (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6941 $: $Author: irascibl@gmail.com $: $Date: 2013-03-26 15:03:18 +0100 (Di, 26. Mrz 2013) $ ********************************************************************/ #include "groundplanegenerator.h" #include "svgfilesplitter.h" #include "../fsvgrenderer.h" #include "../debugdialog.h" #include "../version/version.h" #include "../utils/folderutils.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../items/wire.h" #include "../processeventblocker.h" #include "../autoroute/drc.h" #include #include #include #include #include #include #include #include static const double BORDERINCHES = 0.04; const QString GroundPlaneGenerator::KeepoutSettingName("GPG_Keepout"); const double GroundPlaneGenerator::KeepoutDefaultMils = 10; inline int OFFSET(int x, int y, QImage * image) { return (y * image->width()) + x; } QString GroundPlaneGenerator::ConnectorName = "connector0pad"; // !!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!! IMPORTANT NOTE: QRect::right() and QRect::bottom() are off by one--this is a known Qt problem // !!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!! one workaround might be to switch to QRectF // !!!!!!!!!!!!!!!!!!! GroundPlaneGenerator::GroundPlaneGenerator() { m_strokeWidthIncrement = 0; m_minRiseSize = m_minRunSize = 1; } GroundPlaneGenerator::~GroundPlaneGenerator() { } bool GroundPlaneGenerator::getBoardRects(const QByteArray & boardByteArray, QGraphicsItem * board, double res, double keepoutSpace, QList & rects) { QRectF br = board->sceneBoundingRect(); double bWidth = res * br.width() / GraphicsUtils::SVGDPI; double bHeight = res * br.height() / GraphicsUtils::SVGDPI; QImage image(bWidth, bHeight, QImage::Format_Mono); image.setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); image.setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); image.fill(0xffffffff); QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(&image); painter.setRenderHint(QPainter::Antialiasing, false); renderer.render(&painter); painter.end(); #ifndef QT_NO_DEBUG image.save(FolderUtils::getUserDataStorePath("") + "/getBoardRects.png"); #endif QColor keepaway(255,255,255); // now add keepout area to the border QImage image2 = image.copy(); painter.begin(&image2); painter.setRenderHint(QPainter::Antialiasing, false); painter.fillRect(0, 0, image2.width(), keepoutSpace, keepaway); painter.fillRect(0, image2.height() - keepoutSpace, image2.width(), keepoutSpace, keepaway); painter.fillRect(0, 0, keepoutSpace, image2.height(), keepaway); painter.fillRect(image2.width() - keepoutSpace, 0, keepoutSpace, image2.height(), keepaway); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { QRgb current = image.pixel(x, y); if (current != 0xffffffff) { continue; } painter.fillRect(x - keepoutSpace, y - keepoutSpace, keepoutSpace + keepoutSpace, keepoutSpace + keepoutSpace, keepaway); } } painter.end(); #ifndef QT_NO_DEBUG image2.save(FolderUtils::getUserDataStorePath("") + "/getBoardRects2.png"); #endif scanLines(image2, bWidth, bHeight, rects); // combine parallel equal-sized rects int ix = 0; while (ix < rects.count()) { QRect r = rects.at(ix++); for (int j = ix; j < rects.count(); j++) { QRect s = rects.at(j); if (s.bottom() == r.bottom()) { // on same row; keep going continue; } if (s.top() > r.bottom() + 1) { // skipped row, can't join break; } if (s.left() == r.left() && s.right() == r.right()) { // join these r.setBottom(s.bottom()); rects.removeAt(j); ix--; rects.replace(ix, r); break; } } } return true; } bool GroundPlaneGenerator::generateGroundPlaneUnit(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, const QString & color, QPointF whereToStart, double keepoutMils) { GPGParams params; params.boardSvg = boardSvg; params.boardImageSize = boardImageSize; params.svg = svg; params.copperImageSize = copperImageSize; params.exceptions = exceptions; params.board = board; params.res = res; params.color = color; params.keepoutMils = keepoutMils; double bWidth, bHeight; QList rects; QImage * image = generateGroundPlaneAux(params, bWidth, bHeight, rects); if (image == NULL) return false; QRectF bsbr = board->sceneBoundingRect(); QPoint s(qRound(res * (whereToStart.x() - bsbr.topLeft().x()) / GraphicsUtils::SVGDPI), qRound(res * (whereToStart.y() - bsbr.topLeft().y()) / GraphicsUtils::SVGDPI)); QBitArray redMarker(image->height() * image->width(), false); QRgb pixel = image->pixel(s); //DebugDialog::debug(QString("unit %1").arg(pixel, 0, 16)); if (pixel != 0xffffffff) { // starting off in bad territory delete image; return false; } // step 1 flood fill white to "red" (keep max locations) int minY = image->height(); int maxY = 0; int minX = image->width(); int maxX = 0; QList stack; stack << s; while (stack.count() > 0) { QPoint p = stack.takeFirst(); if (p.x() < 0) continue; if (p.y() < 0) continue; if (p.x() >= image->width()) continue; if (p.y() >= image->height()) continue; if (redMarker.testBit(OFFSET(p.x(), p.y(), image))) continue; // already been here QRgb pixel = image->pixel(p); if (pixel != 0xffffffff) continue; // black; bail redMarker.setBit(OFFSET(p.x(), p.y(), image), true); if (p.x() > maxX) maxX = p.x(); if (p.x() < minX) minX = p.x(); if (p.y() > maxY) maxY = p.y(); if (p.y() < minY) minY = p.y(); stack.append(QPoint(p.x() - 1, p.y())); stack.append(QPoint(p.x() + 1, p.y())); stack.append(QPoint(p.x(), p.y() - 1)); stack.append(QPoint(p.x(), p.y() + 1)); } //image->save("testPoly1.png"); // step 2 replace white with black image->fill(0); // step 3 replace "red" with white for (int y = 0; y < image->height(); y++) { for (int x = 0; x < image->width(); x++) { if (redMarker.testBit(OFFSET(x, y, image))) { image->setPixel(x, y, 1); } } } #ifndef QT_NO_DEBUG image->save(FolderUtils::getUserDataStorePath("") + "/testGroundPlaneUnit3.png"); #endif scanImage(*image, bWidth, bHeight, GraphicsUtils::StandardFritzingDPI / res, res, color, true, true, QSizeF(.05, .05), 1 / GraphicsUtils::SVGDPI, QPointF(0,0)); delete image; return true; } bool GroundPlaneGenerator::generateGroundPlane(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, const QString & color, double keepoutMils) { GPGParams params; params.boardSvg = boardSvg; params.keepoutMils = keepoutMils; params.boardImageSize = boardImageSize; params.svg = svg; params.copperImageSize = copperImageSize; params.exceptions = exceptions; params.board = board; params.res = res; params.color = color; QFuture future = QtConcurrent::run(this, &GroundPlaneGenerator::generateGroundPlaneFn, params); while (!future.isFinished()) { ProcessEventBlocker::processEvents(200); } return future.result(); } bool GroundPlaneGenerator::generateGroundPlaneFn(GPGParams & params) { double bWidth, bHeight; QList rects; QImage * image = generateGroundPlaneAux(params, bWidth, bHeight, rects); if (image == NULL) return false; double pixelFactor = GraphicsUtils::StandardFritzingDPI / params.res; scanImage(*image, bWidth, bHeight, pixelFactor, params.res, params.color, true, true, QSizeF(.05, .05), 1 / GraphicsUtils::SVGDPI, QPointF(0,0)); if (rects.count() > 0) { foreach (QRectF r, rects) { // add the rects separately as tiny SVGs which don't get clipped (since they are connected) QList polygons; QPolygon polygon; polygon << QPoint(r.left() * pixelFactor, r.top() * pixelFactor) << QPoint(r.right() * pixelFactor, r.top() * pixelFactor) << QPoint(r.right() * pixelFactor, r.bottom() * pixelFactor) << QPoint(r.left() * pixelFactor, r.bottom() * pixelFactor); polygons.append(polygon); makePolySvg(polygons, params.res, bWidth, bHeight, pixelFactor, params.color, false, true, QSizeF(0, 0), 0, QPointF(0, 0)); } } delete image; return true; } QImage * GroundPlaneGenerator::generateGroundPlaneAux(GPGParams & params, double & bWidth, double & bHeight, QList & rects) { QByteArray boardByteArray; QString tempColor("#ffffff"); if (!SvgFileSplitter::changeColors(params.boardSvg, tempColor, params.exceptions, boardByteArray)) { return NULL; } //QFile file0("testGroundFillBoard.svg"); //file0.open(QIODevice::WriteOnly); //QTextStream out0(&file0); //out0 << boardByteArray; //file0.close(); /* QByteArray copperByteArray; if (!SvgFileSplitter::changeStrokeWidth(params.svg, m_strokeWidthIncrement, false, true, copperByteArray)) { return NULL; } */ QString errorStr; int errorLine; int errorColumn; QDomDocument doc; doc.setContent(params.svg, &errorStr, &errorLine, &errorColumn); QDomElement root = doc.documentElement(); SvgFileSplitter::forceStrokeWidth(root, 2 * params.keepoutMils, "#000000", true, true); QByteArray copperByteArray = doc.toByteArray(0); //QFile file1("testGroundFillCopper.svg"); //file1.open(QIODevice::WriteOnly); //QTextStream out1(&file1); //out1 << copperByteArray; //file1.close(); double svgWidth = params.res * qMax(params.boardImageSize.width(), params.copperImageSize.width()) / GraphicsUtils::SVGDPI; double svgHeight = params.res * qMax(params.boardImageSize.height(), params.copperImageSize.height()) / GraphicsUtils::SVGDPI; QRectF br = params.board->sceneBoundingRect(); bWidth = params.res * br.width() / GraphicsUtils::SVGDPI; bHeight = params.res * br.height() / GraphicsUtils::SVGDPI; QImage * image = new QImage(qMax(svgWidth, bWidth), qMax(svgHeight, bHeight), QImage::Format_Mono); // image->setDotsPerMeterX(params.res * GraphicsUtils::InchesPerMeter); image->setDotsPerMeterY(params.res * GraphicsUtils::InchesPerMeter); image->fill(0x0); QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); QRectF boardBounds(0, 0, params.res * params.boardImageSize.width() / GraphicsUtils::SVGDPI, params.res * params.boardImageSize.height() / GraphicsUtils::SVGDPI); DebugDialog::debug("boardbounds", boardBounds); renderer.render(&painter, boardBounds); painter.end(); #ifndef QT_NO_DEBUG image->save(FolderUtils::getUserDataStorePath("") + "/testGroundFillBoard.png"); #endif DRC::extendBorder(BORDERINCHES * params.res, image); GraphicsUtils::drawBorder(image, BORDERINCHES * params.res); QImage boardImage = image->copy(); /* for (double m = 0; m < BORDERINCHES; m += (1.0 / params.res)) { // 1 mm QList points; collectBorderPoints(*image, points); #ifndef QT_NO_DEBUG // for debugging //double pixelFactor = GraphicsUtils::StandardFritzingDPI / res; //QPolygon polygon; //foreach(QPoint p, points) { // polygon.append(QPoint(p.x() * pixelFactor, p.y() * pixelFactor)); //} //QList polygons; //polygons.append(polygon); //QPointF offset; //this //QString pSvg = makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, "#ffffff", false, NULL, QSizeF(0,0), 0, QPointF(0, 0)); #endif foreach (QPoint p, points) image->setPixel(p, 0); } */ #ifndef QT_NO_DEBUG image->save(FolderUtils::getUserDataStorePath("") + "/testGroundFillBoardBorder.png"); #endif QSvgRenderer renderer2(copperByteArray); painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); QRectF bounds(0, 0, params.res * params.copperImageSize.width() / GraphicsUtils::SVGDPI, params.res * params.copperImageSize.height() / GraphicsUtils::SVGDPI); DebugDialog::debug("copperbounds", bounds); renderer2.render(&painter, bounds); painter.end(); #ifndef QT_NO_DEBUG image->save(FolderUtils::getUserDataStorePath("") + "/testGroundFillCopper.png"); #endif emit postImageSignal(this, image, &boardImage, params.board, &rects); return image; } void GroundPlaneGenerator::scanImage(QImage & image, double bWidth, double bHeight, double pixelFactor, double res, const QString & colorString, bool makeConnectorFlag, bool makeOffset, QSizeF minAreaInches, double minDimensionInches, QPointF polygonOffset) { QList rects; scanLines(image, bWidth, bHeight, rects); QList< QList * > pieces; splitScanLines(rects, pieces); foreach (QList * piece, pieces) { QList polygons; QList newRects; foreach (int i, *piece) { QRect r = rects.at(i); newRects.append(QRect(r.x() * pixelFactor, r.y() * pixelFactor, (r.width() * pixelFactor) + 1, pixelFactor + 1)); // + 1 is for off-by-one converting rects to polys } // note: there is always one joinScanLines(newRects, polygons); makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, colorString, makeConnectorFlag, makeOffset, minAreaInches, minDimensionInches, polygonOffset); } /* QString newSvg = QString("\n") .arg(bWidth / res) .arg(bHeight / res) .arg(bWidth * MILS) .arg(bHeight * MILS); newSvg += "\n"; // ?split each line into two lines (l1, l2) and add a terminal point at the left of l1 and the right of l2? ix = 0; foreach (QRectF r, rects) { newSvg += QString("\n") .arg(r.left() * MILS) .arg(r.top() * MILS) .arg(r.width() * MILS) .arg(MILS) .arg(ix++). .arg(ViewLayer::Copper0Color); } newSvg += "\n\n"; */ } void GroundPlaneGenerator::scanLines(QImage & image, int bWidth, int bHeight, QList & rects) { if (m_minRiseSize > 1) { for (int x = 0; x < bWidth; x++) { bool inWhite = false; int whiteStart = 0; for (int y = 0; y < bHeight; y++) { QRgb current = image.pixel(x, y); if (inWhite) { if (current == 0xffffffff) { // qBlue(current) == 0xff gray > 128 // another white pixel, keep moving continue; } // got black: close up this segment; inWhite = false; if (y - whiteStart < m_minRiseSize) { for (int j = whiteStart; j <= y; j++) { image.setPixel(x, j, 0); } continue; } } else { if (current != 0xffffffff) { // qBlue(current) != 0xff // another black pixel, keep moving continue; } inWhite = true; whiteStart = y; } } if (inWhite) { // close up the last segment if (bHeight - whiteStart < m_minRiseSize) { for (int j = whiteStart; j <= bHeight; j++) { image.setPixel(x, j, 0); } } } } } // threshold should be between 0 and 255 exclusive; smaller will include more of the svg for (int y = 0; y < bHeight; y++) { bool inWhite = false; int whiteStart = 0; for (int x = 0; x < bWidth; x++) { QRgb current = image.pixel(x, y); //if (current != 0xff000000 && current != 0xffffffff) { //DebugDialog::debug(QString("current %1").arg(current,0,16)); //} //DebugDialog::debug(QString("current %1 %2").arg(current,0,16).arg(gray, 0, 16)); if (inWhite) { if (current == 0xffffffff) { // qBlue(current) == 0xff gray > 128 // another white pixel, keep moving continue; } // got black: close up this segment; inWhite = false; if (x - whiteStart < m_minRunSize) { // not a big enough section continue; } rects.append(QRect(whiteStart, y, x - whiteStart, 1)); } else { if (current != 0xffffffff) { // qBlue(current) != 0xff // another black pixel, keep moving continue; } inWhite = true; whiteStart = x; } } if (inWhite) { // close up the last segment if (bWidth - whiteStart >= m_minRunSize) { rects.append(QRect(whiteStart, y, bWidth - whiteStart, 1)); } } } } void GroundPlaneGenerator::splitScanLines(QList & rects, QList< QList * > & pieces) { // combines vertically adjacent scanlines into "pieces" int ix = 0; int prevFirst = -1; int prevLast = -1; while (ix < rects.count()) { int first = ix; QRectF firstR = rects.at(ix); while (++ix < rects.count()) { QRectF nextR = rects.at(ix); if (nextR.y() != firstR.y()) { break; } } int last = ix - 1; // this was a lookahead so step back one if (prevFirst >= 0) { for (int i = first; i <= last; i++) { QRectF candidate = rects.at(i); int gotCount = 0; for (int j = prevFirst; j <= prevLast; j++) { QRectF prev = rects.at(j); if (prev.y() + 1 != candidate.y()) { // skipped a line; no intersection possible break; } if ((prev.x() + prev.width() <= candidate.x()) || (candidate.x() + candidate.width() <= prev.x())) { // candidate and prev didn't intersect continue; } if (++gotCount > 1) { QList * piecei = NULL; QList * piecej = NULL; foreach (QList * piece, pieces) { if (piece->contains(j)) { piecej = piece; break; } } foreach (QList * piece, pieces) { if (piece->contains(i)) { piecei = piece; break; } } if (piecei != NULL && piecej != NULL) { if (piecei != piecej) { foreach (int b, *piecej) { piecei->append(b); } piecej->clear(); pieces.removeOne(piecej); delete piecej; } piecei->append(i); } else { DebugDialog::debug("we are really screwed here, what should we do about it?"); } } else { // put the candidate (i) in j's piece foreach (QList * piece, pieces) { if (piece->contains(j)) { piece->append(i); break; } } } } if (gotCount == 0) { // candidate is an orphan line at this point QList * piece = new QList; piece->append(i); pieces.append(piece); } } } else { for (int i = first; i <= last; i++) { QList * piece = new QList; piece->append(i); pieces.append(piece); } } prevFirst = first; prevLast = last; } foreach (QList * piece, pieces) { qSort(*piece); } } void GroundPlaneGenerator::joinScanLines(QList & rects, QList & polygons) { QList< QList * > pieces; int ix = 0; int prevFirst = -1; int prevLast = -1; while (ix < rects.count()) { int first = ix; QRectF firstR = rects.at(ix); while (++ix < rects.count()) { QRectF nextR = rects.at(ix); if (nextR.y() != firstR.y()) { break; } } int last = ix - 1; if (prevFirst >= 0) { QVector holdPrevs(last - first + 1); QVector gotCounts(last - first + 1); for (int i = first; i <= last; i++) { int index = i - first; holdPrevs[index] = 0; gotCounts[index] = 0; QRectF candidate = rects.at(i); for (int j = prevFirst; j <= prevLast; j++) { QRectF prev = rects.at(j); if ((prev.x() + prev.width() <= candidate.x()) || (candidate.x() + candidate.width() <= prev.x())) { // candidate and prev didn't intersect continue; } holdPrevs[index] = j; gotCounts[index]++; } if (gotCounts[index] > 1) { holdPrevs[index] = -1; // clear this to allow one of the others in this scanline to capture a previous } } for (int i = first; i <= last; i++) { int index = i - first; bool gotOne = false; if (gotCounts[index] == 1) { bool unique = true; for (int j = first; j <= last; j++) { if (j - first == index) continue; // don't compare against yourself if (holdPrevs[index] == holdPrevs[j - first]) { unique = false; break; } } if (unique) { // add this to the previous chunk gotOne = true; foreach (QList * piece, pieces) { if (piece->contains(holdPrevs[index])) { piece->append(i); break; } } } } if (!gotOne) { // start a new chunk holdPrevs[index] = -1; // allow others to capture the prev QList * piece = new QList; piece->append(i); pieces.append(piece); } } } else { for (int i = first; i <= last; i++) { QList * piece = new QList; piece->append(i); pieces.append(piece); } } prevFirst = first; prevLast = last; } foreach (QList * piece, pieces) { //QPolygon poly(rects.at(piece->at(0)), true); //for (int i = 1; i < piece->length(); i++) { //QPolygon temp(rects.at(piece->at(i)), true); //poly = poly.united(temp); //} // no need to close polygon; SVG automatically closes path QPolygon poly; // left side for (int i = 0; i < piece->length(); i++) { QRect r = rects.at(piece->at(i)); if ((poly.count() > 0) && (poly.last().x() == r.left())) { poly.pop_back(); } else { poly.append(QPoint(r.left(), r.top())); } poly.append(QPoint(r.left(), r.bottom())); } // right side for (int i = piece->length() - 1; i >= 0; i--) { QRect r = rects.at(piece->at(i)); if ((poly.count() > 0) && (poly.last().x() == r.right())) { poly.pop_back(); } else { poly.append(QPoint(r.right(), r.bottom())); } poly.append(QPoint(r.right(), r.top())); } polygons.append(poly); delete piece; } } void GroundPlaneGenerator::makePolySvg(QList & polygons, double res, double bWidth, double bHeight, double pixelFactor, const QString & colorString, bool makeConnectorFlag, bool makeOffset, QSizeF minAreaInches, double minDimensionInches, QPointF polygonOffset) { QPointF offset; QString pSvg = makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, colorString, makeConnectorFlag, makeOffset ? &offset : NULL, minAreaInches, minDimensionInches, polygonOffset); if (pSvg.isEmpty()) return; m_newSVGs.append(pSvg); if (makeOffset) { offset *= GraphicsUtils::SVGDPI; m_newOffsets.append(offset); // offset now in pixels } /* QFile file4("testPoly.svg"); file4.open(QIODevice::WriteOnly); QTextStream out4(&file4); out4 << pSvg; file4.close(); */ } QString GroundPlaneGenerator::makePolySvg(QList & polygons, double res, double bWidth, double bHeight, double pixelFactor, const QString & colorString, bool makeConnectorFlag, QPointF * offset, QSizeF minAreaInches, double minDimensionInches, QPointF polygonOffset) { int minX = 0; int minY = 0; if (offset != NULL) { minY = std::numeric_limits::max(); int maxY = std::numeric_limits::min(); minX = minY; int maxX = maxY; foreach (QPolygon polygon, polygons) { foreach (QPoint p, polygon) { if (p.x() > maxX) maxX = p.x(); if (p.x() < minX) minX = p.x(); if (p.y() > maxY) maxY = p.y(); if (p.y() < minY) minY = p.y(); } } bWidth = (maxX - minX) / pixelFactor; bHeight = (maxY - minY) / pixelFactor; offset->setX(minX / (res * pixelFactor)); // inches offset->setY(minY / (res * pixelFactor)); // inches } if ((bWidth / res < minAreaInches.width()) && (bHeight / res < minAreaInches.height())) { return ""; } if ((bWidth / res < minDimensionInches) || (bHeight / res < minDimensionInches)) { return ""; } QString pSvg = QString("\n") .arg(bWidth / res) .arg(bHeight / res) .arg(bWidth * pixelFactor) .arg(bHeight * pixelFactor); QString transform; if (polygonOffset.x() != 0 || polygonOffset.y() != 0) { transform = QString("transform='translate(%1, %2)'").arg(polygonOffset.x()).arg(polygonOffset.y()); } pSvg += QString("\n").arg(m_layerName).arg(transform); if (makeConnectorFlag) { makeConnector(polygons, res, pixelFactor, colorString, minX, minY, pSvg); } else { foreach (QPolygon poly, polygons) { pSvg += makeOnePoly(poly, colorString, "", minX, minY); } } pSvg += "\n\n"; return pSvg; } void GroundPlaneGenerator::makeConnector(QList & polygons, double res, double pixelFactor, const QString & colorString, int minX, int minY, QString & pSvg) { // see whether the standard circular connector will fit somewhere inside a polygon: // http://stackoverflow.com/questions/4279478/maximum-circle-inside-a-non-convex-polygon // or maybe this is useful, e.g. treating the circle as a square: // http://stackoverflow.com/questions/4833802/check-if-polygon-is-inside-a-polygon // code presently uses a version of the Poles of Inaccessibility algorithm: static const double standardConnectorWidth = .075; // inches double targetDiameter = res * pixelFactor * standardConnectorWidth; double targetDiameterAnd = targetDiameter * 1.25; double targetRadius = targetDiameter / 2; double targetRadiusAnd = targetDiameterAnd / 2; double targetRadiusAndSquared = targetRadiusAnd * targetRadiusAnd; foreach (QPolygon poly, polygons) { QRect boundingRect = poly.boundingRect(); if (boundingRect.width() < targetDiameterAnd) continue; if (boundingRect.height() < targetDiameterAnd) continue; QList polyLines; int count = poly.count(); for (int i = 0; i < count; i++) { QLineF lp(poly[i], poly[(i + 1) % count]); polyLines.append(lp); } int xDivisor = qRound(boundingRect.width() / targetRadius); int yDivisor = qRound(boundingRect.height() / targetRadius); double dx = (boundingRect.width() - targetDiameterAnd) / xDivisor; double dy = (boundingRect.height() - targetDiameterAnd) / yDivisor; double x; double y = boundingRect.top() + targetRadiusAnd - dy; for (int iy = 0; iy <= yDivisor; iy++) { y += dy; x = boundingRect.left() + targetRadiusAnd - dx; for (int ix = 0; ix <= xDivisor; ix++) { x += dx; if (!poly.containsPoint(QPoint(qRound(x), qRound(y)), Qt::OddEvenFill)) continue; bool gotOne = true; foreach (QLineF line, polyLines) { double distance, dx, dy; bool atEndpoint; GraphicsUtils::distanceFromLine(x, y, line.p1().x(), line.p1().y(), line.p2().x(), line.p2().y(), dx, dy, distance, atEndpoint); if (distance <= targetRadiusAndSquared) { gotOne = false; break; } } if (!gotOne) continue; foreach (QPolygon poly, polygons) { pSvg += makeOnePoly(poly, colorString, "", minX, minY); } pSvg += QString("\n") .arg(ConnectorName) .arg(x - minX) .arg(y - minY) .arg(targetRadius) .arg(colorString); return; } } } // couldn't find anything big enough above, so // try to find a poly with an area that's big enough to click, but not so big as to get in the way int useIndex = -1; QList areas; double divisor = res * pixelFactor * res * pixelFactor; foreach (QPolygon poly, polygons) { areas.append(calcArea(poly) / divisor); } for (int i = 0; i < areas.count(); i++) { if (areas.at(i) > 0.1 && areas.at(i) < 0.25) { useIndex = i; break; } } if (useIndex < 0) { for (int i = 0; i < areas.count(); i++) { if (areas.at(i) > 0.1) { useIndex = i; break; } } } if (useIndex < 0) { pSvg += QString("\n").arg(ConnectorName); foreach (QPolygon poly, polygons) { pSvg += makeOnePoly(poly, colorString, "", minX, minY); } pSvg += ""; } else { int ix = 0; for (int i = 0; i < polygons.count(); i++) { if (i == useIndex) { // has to appear inside a g element pSvg += QString("\n").arg(ConnectorName); pSvg += makeOnePoly(polygons.at(i), colorString, "", minX, minY); pSvg += ""; } else { pSvg += makeOnePoly(polygons.at(i), colorString, FSvgRenderer::NonConnectorName + QString::number(ix++), minX, minY); } } } } double GroundPlaneGenerator::calcArea(QPolygon & poly) { double total = 0; for (int ix = 0; ix < poly.count(); ix++) { QPoint p0 = poly.at(ix); QPoint p1 = poly.at((ix + 1) % poly.count()); total += (p0.x() * p1.y() - p1.x() * p0.y()); } return qAbs(total / 2.0); } QString GroundPlaneGenerator::makeOnePoly(const QPolygon & poly, const QString & colorString, const QString & id, int minX, int minY) { QString idString; if (!id.isEmpty()) { idString = QString("id='%1'").arg(id); } QString polyString = QString("\n"; return polyString; } const QStringList & GroundPlaneGenerator::newSVGs() { return m_newSVGs; } const QList & GroundPlaneGenerator::newOffsets() { return m_newOffsets; } void removeRedundant(QList & points) { QPoint current = points.last(); int ix = points.count() - 2; int soFar = 1; while (ix > 0) { if (points.at(ix).x() != current.x()) { current = points.at(ix--); soFar = 1; continue; } if (++soFar > 2) { points.removeAt(ix + 1); } ix--; } } bool GroundPlaneGenerator::collectBorderPoints(QImage & image, QList & points) { // background is black int currentX = 0, currentY = 0; bool gotSomething = false; for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { QRgb current = image.pixel(x, y); if (current != 0xffffffff) { // another black pixel, keep moving continue; } currentX = x; currentY = y; //DebugDialog::debug(QString("first point %1 %2").arg(currentX).arg(currentY)); points.append(QPoint(currentX, currentY)); gotSomething = true; break; } if (gotSomething) break; } if (!gotSomething) { DebugDialog::debug("first border point not found"); return false; } bool done = false; long maxPoints = image.height() * image.width() / 2; for (long inc = 0; inc < maxPoints; inc++) { if (try8(currentX, currentY, image, points)) ; else { QPoint p = points.first(); if (qAbs(p.x() - currentX) < 4 && qAbs(p.y() - currentY) < 4) { // we're near the beginning again done = true; break; } bool keepGoing = false; for (int ix = points.count() - 2; ix >= 0; ix--) { QPoint p = points.at(ix); if (try8(p.x(), p.y(), image, points)) { keepGoing = true; break; } } if (!keepGoing) break; } QPoint p = points.last(); currentX = p.x(); currentY = p.y(); //DebugDialog::debug(QString("next point %1 %2").arg(currentX).arg(currentY)); //if (inc % 100 == 0) { //DebugDialog::debug("\n"); //} } return done; } void GroundPlaneGenerator::scanOutline(QImage & image, double bWidth, double bHeight, double pixelFactor, double res, const QString & colorString, bool makeConnectorFlag, bool makeOffset, QSizeF minAreaInches, double minDimensionInches) { QList points; bool result = collectBorderPoints(image, points); if (points.count() == 0 || !result) { DebugDialog::debug("no border points"); return; } removeRedundant(points); QPolygon polygon; foreach(QPoint p, points) { polygon.append(QPoint(p.x() * pixelFactor, p.y() * pixelFactor)); } QList polygons; polygons.append(polygon); makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, colorString, makeConnectorFlag, makeOffset, minAreaInches, minDimensionInches, QPointF(0,0)); /* QFile file4("testPoly.svg"); file4.open(QIODevice::WriteOnly); QTextStream out4(&file4); out4 << pSvg; file4.close(); */ } bool GroundPlaneGenerator::try8(int x, int y, QImage & image, QList & points) { if (tryNextPoint(x, y + 1, image, points)) return true; else if (tryNextPoint(x + 1, y, image, points)) return true; else if (tryNextPoint(x, y - 1, image, points)) return true; else if (tryNextPoint(x - 1, y, image, points)) return true; else if (tryNextPoint(x + 1, y + 1, image, points)) return true; else if (tryNextPoint(x - 1, y + 1, image, points)) return true; else if (tryNextPoint(x + 1, y - 1, image, points)) return true; else if (tryNextPoint(x - 1, y - 1, image, points)) return true; return false; } bool GroundPlaneGenerator::tryNextPoint(int x, int y, QImage & image, QList & points) { if (x < 0) return false; if (y < 0) return false; if (x >= image.width()) return false; if (y >= image.height()) return false; foreach (QPoint p, points) { if (p.x() == x && p.y() == y) { // already visited return false; } if (qAbs(p.x() - x) > 3 && qAbs(p.y() - y) > 3) { // too far away from the start of the polygon break; } } for (int i = points.count() - 1; i >= 0; i--) { QPoint p = points.at(i); if (p.x() == x && p.y() == y) { // already visited return false; } if (qAbs(p.x() - x) > 3 && qAbs(p.y() - y) > 3) { // too far away from from the current point break; } } QRgb pixel = image.pixel(x, y); //DebugDialog::debug(QString("pixel %1,%2 %3").arg(x).arg(y).arg(pixel, 0, 16)); if (pixel != 0xffffffff) { // empty pixel, not on the border return false; } if (x + 1 == image.width()) { points.append(QPoint(x, y)); return true; } pixel = image.pixel(x + 1, y); if (pixel != 0xffffffff) { points.append(QPoint(x, y)); return true; } if (y + 1 == image.height()) { points.append(QPoint(x, y)); return true; } pixel = image.pixel(x, y + 1); if (pixel != 0xffffffff) { points.append(QPoint(x, y)); return true; } if (x - 1 < 0) { points.append(QPoint(x, y)); return true; } pixel = image.pixel(x - 1, y); if (pixel != 0xffffffff) { points.append(QPoint(x, y)); return true; } if (y - 1 < 0) { points.append(QPoint(x, y)); return true; } pixel = image.pixel(x, y - 1); if (pixel != 0xffffffff) { points.append(QPoint(x, y)); return true; } return false; } void GroundPlaneGenerator::setStrokeWidthIncrement(double swi) { m_strokeWidthIncrement = swi; } void GroundPlaneGenerator::setLayerName(const QString & layerName) { m_layerName = layerName; } const QString & GroundPlaneGenerator::layerName() { return m_layerName; } void GroundPlaneGenerator::setMinRunSize(int mrus, int mris) { m_minRunSize = mrus; m_minRiseSize = mris; } QString GroundPlaneGenerator::mergeSVGs(const QString & initialSVG, const QString & layerName) { QDomDocument doc; if (!initialSVG.isEmpty()) { TextUtils::mergeSvg(doc, initialSVG, layerName); } foreach (QString newSvg, m_newSVGs) { TextUtils::mergeSvg(doc, newSvg, layerName); } return TextUtils::mergeSvgFinish(doc); } fritzing-app-0.9.2b/src/svg/groundplanegenerator.h000066400000000000000000000114371250202676700222770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6941 $: $Author: irascibl@gmail.com $: $Date: 2013-03-26 15:03:18 +0100 (Di, 26. Mrz 2013) $ ********************************************************************/ #ifndef GROUNDPLANEGENERATOR_H #define GROUNDPLANEGENERATOR_H #include #include #include #include #include #include #include struct GPGParams { QString boardSvg; QSizeF boardImageSize; QString svg; QSizeF copperImageSize; QStringList exceptions; QGraphicsItem * board; double res; QString color; double keepoutMils; }; class GroundPlaneGenerator : public QObject { Q_OBJECT public: GroundPlaneGenerator(); ~GroundPlaneGenerator(); bool generateGroundPlane(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, const QString & color, double keepoutMils); bool generateGroundPlaneUnit(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, const QString & color, QPointF whereToStart, double keepoutMils); void scanImage(QImage & image, double bWidth, double bHeight, double pixelFactor, double res, const QString & colorString, bool makeConnector, bool makeOffset, QSizeF minAreaInches, double minDimensionInches, QPointF offsetPolygons); void scanOutline(QImage & image, double bWidth, double bHeight, double pixelFactor, double res, const QString & colorString, bool makeConnector, bool makeOffset, QSizeF minAreaInches, double minDimensionInches); void scanLines(QImage & image, int bWidth, int bHeight, QList & rects); bool getBoardRects(const QByteArray & boardByteArray, QGraphicsItem * board, double res, double keepoutSpace, QList & rects); const QStringList & newSVGs(); const QList & newOffsets(); void setStrokeWidthIncrement(double); void setLayerName(const QString &); const QString & layerName(); void setMinRunSize(int minRunSize, int minRiseSize); QString mergeSVGs(const QString & initialSVG, const QString & layerName); public: static QString ConnectorName; signals: void postImageSignal(GroundPlaneGenerator *, QImage * copperImage, QImage * boardImage, QGraphicsItem * board, QList *); protected: void splitScanLines(QList & rects, QList< QList * > & pieces); void joinScanLines(QList & rects, QList & polygons); QString makePolySvg(QList & polygons, double res, double bWidth, double bHeight, double pixelFactor, const QString & colorString, bool makeConnectorFlag, QPointF * offset, QSizeF minAreaInches, double minDimensionInches, QPointF polygonOffset); void makePolySvg(QList & polygons, double res, double bWidth, double bHeight, double pixelFactor, const QString & colorString, bool makeConnectorFlag, bool makeOffset, QSizeF minAreaInches, double minDimensionInches, QPointF polygonOffset); QString makeOnePoly(const QPolygon & poly, const QString & colorString, const QString & id, int minX, int minY); double calcArea(QPolygon & poly); QImage * generateGroundPlaneAux(GPGParams &, double & bWidth, double & bHeight, QList &); void makeConnector(QList & polygons, double res, double pixelFactor, const QString & colorString, int minX, int minY, QString & svg); bool tryNextPoint(int x, int y, QImage & image, QList & points); bool collectBorderPoints(QImage & image, QList & points); bool try8(int x, int y, QImage & image, QList & points); bool generateGroundPlaneFn(GPGParams &); protected: QStringList m_newSVGs; QList m_newOffsets; double m_blurBy; QString m_layerName; double m_strokeWidthIncrement; int m_minRunSize; int m_minRiseSize; public: static const QString KeepoutSettingName; static const double KeepoutDefaultMils; }; #endif fritzing-app-0.9.2b/src/svg/kicad2svg.cpp000066400000000000000000000053761250202676700202670ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "kicad2svg.h" #include "../utils/textutils.h" #include "../version/version.h" #include #include #include Kicad2Svg::Kicad2Svg() { } QString Kicad2Svg::makeMetadata(const QString & filename, const QString & type, const QString & name) { QFileInfo fileInfo(filename); QDateTime now = QDateTime::currentDateTime(); QString dt = now.toString("dd/MM/yyyy hh:mm:ss"); m_title = QString("%1\n").arg(fileInfo.fileName()); m_description = QString("Kicad %3 '%2' from file '%1' converted by Fritzing\n") .arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(fileInfo.fileName()))) .arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(name))) .arg(type); QString metadata("\n"); metadata += ""; metadata += "\n"; metadata += m_attribute.arg("kicad filename").arg(fileInfo.fileName()); metadata += m_attribute.arg(QString("kicad %1").arg(type)) .arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(name))); metadata += m_attribute.arg("fritzing version").arg(Version::versionString()); metadata += m_attribute.arg("conversion date").arg(dt); metadata += m_attribute.arg("dist-license").arg("GPL"); metadata += m_attribute.arg("use-license").arg("unlimited"); metadata += m_attribute.arg("author").arg("KICAD project"); metadata += m_attribute.arg("license-url").arg("http://www.gnu.org/licenses/gpl.html"); return metadata; } QString Kicad2Svg::endMetadata() { QString metadata = ""; metadata += ""; metadata += ""; return metadata; } fritzing-app-0.9.2b/src/svg/kicad2svg.h000066400000000000000000000025121250202676700177210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef KICAD2SVG_H #define KICAD2SVG_H #include "x2svg.h" class Kicad2Svg : public X2Svg { public: Kicad2Svg(); QString makeMetadata(const QString & filename, const QString & type, const QString & name); QString endMetadata(); protected: QString m_title; QString m_description; }; #endif // KICAD2SVG_H fritzing-app-0.9.2b/src/svg/kicadmodule2svg.cpp000066400000000000000000000670101250202676700214660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "kicadmodule2svg.h" #include "../utils/textutils.h" #include "../debugdialog.h" #include "../viewlayer.h" #include "../fsvgrenderer.h" #include #include #include #include #include #include #include #include #include #define KicadSilkscreenTop 21 #define KicadSilkscreenBottom 20 // TODO: // non-centered drill holes? // trapezoidal pads (shape delta may or may not be a separate issue)? // non-copper holes? // find true bounding box of arcs instead of using the whole circle double checkStrokeWidth(double w) { if (w >= 0) return w; DebugDialog::debug("stroke width < 0"); return 0; } KicadModule2Svg::KicadModule2Svg() : Kicad2Svg() { } QStringList KicadModule2Svg::listModules(const QString & filename) { QStringList modules; QFile file(filename); if (!file.open(QFile::ReadOnly)) return modules; QTextStream textStream(&file); bool gotIndex = false; while (true) { QString line = textStream.readLine(); if (line.isNull()) break; if (line.compare("$INDEX") == 0) { gotIndex = true; break; } } if (!gotIndex) return modules; while (true) { QString line = textStream.readLine(); if (line.isNull()) break; if (line.compare("$EndINDEX") == 0) { return modules; } modules.append(line); } modules.clear(); return modules; } QString KicadModule2Svg::convert(const QString & filename, const QString & moduleName, bool allowPadsAndPins) { m_nonConnectorNumber = 0; initLimits(); QFile file(filename); if (!file.open(QFile::ReadOnly)) { throw QObject::tr("unable to open %1").arg(filename); } QString text; QTextStream textStream(&file); QString metadata = makeMetadata(filename, "module", moduleName); bool gotModule = false; while (true) { QString line = textStream.readLine(); if (line.isNull()) { break; } if (line.contains("$MODULE") && line.contains(moduleName, Qt::CaseInsensitive)) { gotModule = true; break; } } if (!gotModule) { throw QObject::tr("footprint %1 not found in %2").arg(moduleName).arg(filename); } bool gotT0; QString line; while (true) { line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("unexpected end of file in footprint %1 in file %2").arg(moduleName).arg(filename); } if (line.startsWith("T0") || line.startsWith("DS") || line.startsWith("DA") || line.startsWith("DC")) { gotT0 = true; break; } else if (line.startsWith("Cd")) { metadata += m_comment.arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(line.remove(0,3)))); } else if (line.startsWith("Kw")) { QStringList keywords = line.split(" "); for (int i = 1; i < keywords.count(); i++) { metadata += m_attribute.arg("keyword").arg(TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(keywords[i]))); } } } metadata += endMetadata(); if (!gotT0) { throw QObject::tr("unexpected format (1) in %1 from %2").arg(moduleName).arg(filename); } while (line.startsWith("T")) { line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("unexpected end of file in footprint %1 in file %2").arg(moduleName).arg(filename); } } bool done = false; QString copper0; QString copper1; QString silkscreen0; QString silkscreen1; while (true) { if (line.startsWith("$PAD")) break; if (line.startsWith("$EndMODULE")) { done = true; break; } int layer = 0; QString svgElement; if (line.startsWith("DS")) { layer = drawDSegment(line, svgElement); } else if (line.startsWith("DA")) { layer = drawDArc(line, svgElement); } else if (line.startsWith("DC")) { layer = drawDCircle(line, svgElement); } switch (layer) { case KicadSilkscreenTop: silkscreen1 += svgElement; break; case KicadSilkscreenBottom: silkscreen0 += svgElement; break; default: break; } line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("unexpected end of file in footprint %1 in file %2").arg(moduleName).arg(filename); } } if (!done) { QList numbers; for (int i = 0; i < 512; i++) { numbers << i; } int pads = 0; int pins = 0; while (!done) { try { QString pad; PadLayer padLayer = convertPad(textStream, pad, numbers); switch (padLayer) { case ToCopper0: copper0 += pad; pins++; break; case ToCopper1: copper1 += pad; pads++; break; default: break; } } catch (const QString & msg) { DebugDialog::debug(QString("kicad pad %1 conversion failed in %2: %3").arg(moduleName).arg(filename).arg(msg)); } while (true) { line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("unexpected end of file in footprint %1 in file %2").arg(moduleName).arg(filename); } if (line.contains("$SHAPE3D")) { done = true; break; } if (line.contains("$EndMODULE")) { done = true; break; } if (line.contains("$PAD")) { break; } } } if (!allowPadsAndPins && pins > 0 && pads > 0) { throw QObject::tr("Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)").arg(moduleName).arg(filename); } } if (!copper0.isEmpty()) { copper0 = offsetMin("\n" + copper0 + "\n"); } if (!copper1.isEmpty()) { copper1 = offsetMin("\n" + copper1 + "\n"); } if (!silkscreen1.isEmpty()) { silkscreen1 = offsetMin("\n" + silkscreen1 + "\n"); } if (!silkscreen0.isEmpty()) { silkscreen0 = offsetMin("\n" + silkscreen0 + "\n"); } QString svg = TextUtils::makeSVGHeader(10000, 10000, m_maxX - m_minX, m_maxY - m_minY) + m_title + m_description + metadata + copper0 + copper1 + silkscreen0 + silkscreen1 + ""; return svg; } int KicadModule2Svg::drawDCircle(const QString & ds, QString & circle) { // DC Xcentre Ycentre Xend Yend width layer QStringList params = ds.split(" "); if (params.count() < 7) return -1; int cx = params.at(1).toInt(); int cy = params.at(2).toInt(); int x2 = params.at(3).toInt(); int y2 = params.at(4).toInt(); double radius = qSqrt((cx - x2) * (cx - x2) + (cy - y2) * (cy - y2)); int w = params.at(5).toInt(); double halfWidth = w / 2.0; checkXLimit(cx + radius + halfWidth); checkXLimit(cx - radius - halfWidth); checkYLimit(cy + radius + halfWidth); checkYLimit(cy - radius - halfWidth); int layer = params.at(6).toInt(); circle = QString("") .arg(cx) .arg(cy) .arg(radius) .arg(checkStrokeWidth(w)); return layer; } int KicadModule2Svg::drawDSegment(const QString & ds, QString & line) { // DS Xstart Ystart Xend Yend Width Layer QStringList params = ds.split(" "); if (params.count() < 7) return -1; int x1 = params.at(1).toInt(); int y1 = params.at(2).toInt(); int x2 = params.at(3).toInt(); int y2 = params.at(4).toInt(); checkXLimit(x1); checkXLimit(x2); checkYLimit(y1); checkYLimit(y2); int layer = params.at(6).toInt(); line = QString("") .arg(x1) .arg(y1) .arg(x2) .arg(y2) .arg(checkStrokeWidth(params.at(5).toDouble())); return layer; } int KicadModule2Svg::drawDArc(const QString & ds, QString & arc) { //DA x0 y0 x1 y1 angle width layer QStringList params = ds.split(" "); if (params.count() < 8) return -1; int cx = params.at(1).toInt(); int cy = params.at(2).toInt(); int x2 = params.at(3).toInt(); int y2 = params.at(4).toInt(); int width = params.at(6).toInt(); double diffAngle = (params.at(5).toInt() % 3600) / 10.0; double radius = qSqrt((cx - x2) * (cx - x2) + (cy - y2) * (cy - y2)); double endAngle = asin((y2 - cy) / radius); if (x2 < cx) { endAngle += M_PI; } double startAngle = endAngle + (diffAngle * M_PI / 180.0); double x1 = (radius * cos(startAngle)) + cx; double y1 = (radius * sin(startAngle)) + cy; // TODO: figure out bounding box for circular arc and set min and max accordingly /* You have radius R, start angle S, end angle T, and I'll assume that the arc is swept counterclockwise from S to T. start.x = R * cos(S) start.y = R * sin(S) end.x = R * cos(T) end.y = R * sin(T) Determine the axis crossings by analyzing the start and end angles. For discussion sake, I'll describe angles using degrees. Provide a function, wrap(angle), that returns an angle in the range [0 to 360). cross0 = wrap(S) > wrap(T) cross90 = wrap(S-90) > wrap(T-90) cross180 = wrap(S-180) > wrap(T-180) cross270 = wrap(S-270) > wrap(T-270) Now the axis aligned bounding box is defined by: right = cross0 ? +R : max(start.x, end.x) top = cross90 ? +R : max(start.y, end.y) left = cross180 ? -R : min(start.x, end.x) bottom = cross270 ? -R : min(start.y, end.y) */ checkXLimit(cx + radius); checkXLimit(cx - radius); checkYLimit(cy + radius); checkYLimit(cy - radius); int layer = params.at(7).toInt(); arc = QString("") .arg(checkStrokeWidth(width / 2.0)) .arg(x1) .arg(y1) .arg(radius) .arg(radius) .arg(qAbs(diffAngle) >= 180 ? 1 : 0) .arg(diffAngle > 0 ? 0 : 1) .arg(x2 - x1) .arg(y2 - y1); return layer; } KicadModule2Svg::PadLayer KicadModule2Svg::convertPad(QTextStream & stream, QString & pad, QList & numbers) { PadLayer padLayer = UnableToTranslate; QStringList padStrings; while (true) { QString line = stream.readLine(); if (line.isNull()) { throw QObject::tr("unexpected end of file"); } if (line.contains("$EndPAD")) { break; } padStrings.append(line); } QString shape; QString drill; QString attributes; QString position; foreach (QString string, padStrings) { if (string.startsWith("Sh")) { shape = string; } else if (string.startsWith("Po")) { position = string; } else if (string.startsWith("At")) { attributes = string; } else if (string.startsWith("Dr")) { drill = string; } } if (drill.isEmpty()) { throw QObject::tr("pad missing drill"); } if (attributes.isEmpty()) { throw QObject::tr("pad missing attributes"); } if (position.isEmpty()) { throw QObject::tr("pad missing position"); } if (shape.isEmpty()) { throw QObject::tr("pad missing shape"); } QStringList positionStrings = position.split(" "); if (positionStrings.count() < 3) { throw QObject::tr("position missing params"); } int posX = positionStrings.at(1).toInt(); int posY = positionStrings.at(2).toInt(); QStringList drillStrings = drill.split(" "); if (drillStrings.count() < 4) { throw QObject::tr("drill missing params"); } int drillX = drillStrings.at(1).toInt(); int drillXOffset = drillStrings.at(2).toInt(); int drillYOffset = drillStrings.at(3).toInt(); int drillY = drillX; if (drillXOffset != 0 || drillYOffset != 0) { throw QObject::tr("drill offset not implemented"); } if (drillStrings.count() > 4) { if (drillStrings.at(4) == "O") { if (drillStrings.count() < 7) { throw QObject::tr("drill missing ellipse params"); } drillY = drillStrings.at(6).toInt(); } } QStringList attributeStrings = attributes.split(" "); if (attributeStrings.count() < 4) { throw QObject::tr("attributes missing params"); } bool ok; int layerMask = attributeStrings.at(3).toInt(&ok, 16); if (!ok) { throw QObject::tr("bad layer mask parameter"); } QString padType = attributeStrings.at(1); if (padType == "MECA") { // seems to be the same thing padType = "STD"; } if (padType == "STD") { padLayer = ToCopper0; } else if (padType == "SMD") { padLayer = ToCopper1; } else if (padType == "CONN") { if (layerMask & 1) { padLayer = ToCopper0; } else { padLayer = ToCopper1; } } else if (padType == "HOLE") { padLayer = ToCopper0; } else { throw QObject::tr("Sorry, can't handle pad type %1").arg(padType); } QStringList shapeStrings = shape.split(" "); if (shapeStrings.count() < 8) { throw QObject::tr("pad shape missing params"); } QString padName = unquote(shapeStrings.at(1)); int padNumber = padName.toInt(&ok) - 1; if (!ok) { padNumber = padName.isEmpty() ? -1 : numbers.takeFirst(); //DebugDialog::debug(QString("name:%1 padnumber %2").arg(padName).arg(padNumber)); } else { numbers.removeOne(padNumber); } QString shapeIdentifier = shapeStrings.at(2); int xSize = shapeStrings.at(3).toInt(); int ySize = shapeStrings.at(4).toInt(); if (ySize <= 0) { DebugDialog::debug(QString("ySize is zero %1").arg(padName)); ySize = xSize; } if (xSize <= 0) { throw QObject::tr("pad shape size is invalid"); } int xDelta = shapeStrings.at(5).toInt(); int yDelta = shapeStrings.at(6).toInt(); int orientation = shapeStrings.at(7).toInt(); if (shapeIdentifier == "T") { throw QObject::tr("trapezoidal pads not implemented"); // eventually polygon? } if (xDelta != 0 || yDelta != 0) { // note: so far, all cases of non-zero delta go with shape "T" throw QObject::tr("shape delta not implemented"); } if (padType == "HOLE") { if (shapeIdentifier != "C") { throw QObject::tr("non-circular holes not implemented"); } if (drillX == xSize) { throw QObject::tr("non-copper holes not implemented"); } } if (shapeIdentifier == "C") { checkLimits(posX, xSize, posY, ySize); pad += drawCPad(posX, posY, xSize, ySize, drillX, drillY, padName, padNumber, padType, padLayer); } else if (shapeIdentifier == "R") { checkLimits(posX, xSize, posY, ySize); pad += drawRPad(posX, posY, xSize, ySize, drillX, drillY, padName, padNumber, padType, padLayer); } else if (shapeIdentifier == "O") { checkLimits(posX, xSize, posY, ySize); QString id = getID(padNumber, padLayer); pad += QString("") .arg(id).arg(padName) + drawOblong(posX, posY, xSize, ySize, drillX, drillY, padType, padLayer) + ""; } else { throw QObject::tr("unable to handle pad shape %1").arg(shapeIdentifier); } if (orientation != 0) { if (orientation < 0) { orientation = (orientation % 3600) + 3600; } orientation = 3600 - (orientation % 3600); QTransform t = QTransform().translate(-posX, -posY) * QTransform().rotate(orientation / 10.0) * QTransform().translate(posX, posY); pad = TextUtils::svgTransform(pad, t, true, QString("_x='%1' _y='%2' _r='%3'").arg(posX).arg(posY).arg(orientation / 10.0)); } return padLayer; } QString KicadModule2Svg::drawVerticalOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer padLayer) { QString color = getColor(padLayer); double rad = xSize / 4.0; QString bot; if (drillX == drillY) { bot = QString("") .arg(posX - rad - rad) .arg(posY - (ySize / 2.0) + (xSize / 2.0)) .arg(rad * 2) .arg(rad * 4) .arg(color); bot += QString("") .arg(posX + rad + rad) .arg(posY + (ySize / 2.0) - (xSize / 2.0)) .arg(rad * 2) .arg(-rad * 4) .arg(color); } else { double w = (ySize - drillY) / 2.0; double newrad = rad - w / 4; bot = QString("").arg(checkStrokeWidth(drillX)); bot += QString("") .arg(posX - rad - rad + (w / 2)) .arg(posY - (ySize / 2.0) + (xSize / 2.0)) .arg(newrad * 2) .arg(newrad * 4) .arg(color) .arg(checkStrokeWidth(w)); bot += QString("") .arg(posX + rad + rad - (w / 2)) .arg(posY + (ySize / 2.0) - (xSize / 2.0)) .arg(newrad * 2) .arg(-newrad * 4) .arg(color) .arg(checkStrokeWidth(w)); bot += QString("") .arg(posX).arg(posY - (ySize / 2.0) + (xSize / 2.0)).arg(posX).arg(posY + (ySize / 2.0) - (xSize / 2.0)); bot += ""; } QString middle; if (padType == "SMD") { middle = QString("") .arg(posX - (xSize / 2.0)) .arg(posY - (ySize / 2.0) + (xSize / 2.0)) .arg(xSize) .arg(ySize - xSize) .arg(color); } else { if (drillX == drillY) { middle = QString("") .arg(posX) .arg(posY) .arg((qMin(xSize, ySize) / 2.0) - (drillX / 4.0)) .arg(checkStrokeWidth(drillX / 2.0)) .arg(color); } middle += QString("") .arg(posX - (xSize / 2.0) + (drillX / 4.0)) .arg(posY - (ySize / 2.0) + (xSize / 2.0)) .arg(posY + (ySize / 2.0) - (xSize / 2.0)) .arg(checkStrokeWidth(drillX / 2.0)) .arg(color); middle += QString("") .arg(posX + (xSize / 2.0) - (drillX / 4.0)) .arg(posY - (ySize / 2.0) + (xSize / 2.0)) .arg(posY + (ySize / 2.0) - (xSize / 2.0)) .arg(checkStrokeWidth(drillX / 2.0)) .arg(color); } return middle + bot; } QString KicadModule2Svg::drawHorizontalOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer padLayer) { QString color = getColor(padLayer); double rad = ySize / 4.0; QString bot; if (drillX == drillY) { bot = QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)) .arg(posY - rad - rad) .arg(rad * 2) .arg(rad * 4) .arg(color); bot += QString("") .arg(posX + (xSize / 2.0) - (ySize / 2.0)) .arg(posY + rad + rad) .arg(rad * 2) .arg(-rad * 4) .arg(color); } else { double w = (xSize - drillX) / 2.0; double newrad = rad - w / 4; bot = QString("").arg(checkStrokeWidth(drillY)); bot += QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)) .arg(posY - rad - rad + (w / 2)) .arg(newrad * 2) .arg(newrad * 4) .arg(color) .arg(checkStrokeWidth(w)); bot += QString("") .arg(posX + (xSize / 2.0) - (ySize / 2.0)) .arg(posY + rad + rad - (w / 2)) .arg(newrad * 2) .arg(-newrad * 4) .arg(color) .arg(checkStrokeWidth(w)); bot += QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)).arg(posY).arg(posX + (xSize / 2.0) - (ySize / 2.0)).arg(posY); bot += ""; } QString middle; bool gotID = false; if (padType == "SMD") { middle = QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)) .arg(posY - (ySize / 2.0)) .arg(xSize - ySize) .arg(ySize) .arg(color); } else { if (drillX == drillY) { gotID = true; middle = QString("") .arg(posX) .arg(posY) .arg((qMin(xSize, ySize) / 2.0) - (drillY / 4.0)) .arg(checkStrokeWidth(drillY / 2.0)) .arg(color); } middle += QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)) .arg(posY - (ySize / 2.0) + (drillY / 4.0)) .arg(posX + (xSize / 2.0) - (ySize / 2.0)) .arg(checkStrokeWidth(drillY / 2.0)) .arg(color); middle += QString("") .arg(posX - (xSize / 2.0) + (ySize / 2.0)) .arg(posY + (ySize / 2.0) - (drillY / 4.0)) .arg(posX + (xSize / 2.0) - (ySize / 2.0)) .arg(checkStrokeWidth(drillY / 2.0)) .arg(color); } return middle + bot; } void KicadModule2Svg::checkLimits(int posX, int xSize, int posY, int ySize) { checkXLimit(posX - (xSize / 2.0)); checkXLimit(posX + (xSize / 2.0)); checkYLimit(posY - (ySize / 2.0)); checkYLimit(posY + (ySize / 2.0)); } QString KicadModule2Svg::drawCPad(int posX, int posY, int xSize, int ySize, int drillX, int drillY, const QString & padName, int padNumber, const QString & padType, KicadModule2Svg::PadLayer padLayer) { QString color = getColor(padLayer); QString id = getID(padNumber, padLayer); Q_UNUSED(ySize); if (padType == "SMD") { return QString("") .arg(posX) .arg(posY) .arg(xSize / 2.0) .arg(id) .arg(color) .arg(padName); } if (drillX == drillY) { double w = (xSize - drillX) / 2.0; QString pad = QString("").arg(id).arg(padName); pad += QString("") .arg(posX) .arg(posY) .arg((drillX / 2.0) + (w / 2)) .arg(checkStrokeWidth(w)) .arg(color); if (drillX > 500) { pad += QString("") .arg(posX) .arg(posY) .arg(drillX / 2.0); } pad += ""; return pad; } QString pad = QString("").arg(id); double w = (xSize - qMax(drillX, drillY)) / 2.0; pad += QString("") .arg(posX) .arg(posY) .arg((xSize / 2.0) - (w / 2)) .arg(checkStrokeWidth(w)) .arg(color); pad += drawOblong(posX, posY, drillX + w, drillY + w, drillX, drillY, "", padLayer); // now fill the gaps between the oblong and the circle if (drillX >= drillY) { double angle = asin(((drillY + w) / 2) / (ySize / 2.0)); double opp = (ySize / 2.0) * cos(angle); pad += QString("") .arg(color) .arg(posX) .arg(posY - (ySize / 2.0)) .arg(posX - opp) .arg(posY - (drillY / 2.0)) .arg(posX + opp) .arg(posY - (drillY / 2.0)); pad += QString("") .arg(color) .arg(posX) .arg(posY + (ySize / 2.0)) .arg(posX - opp) .arg(posY + (drillY / 2.0)) .arg(posX + opp) .arg(posY + (drillY / 2.0)); } else { double angle = acos(((drillX + w) / 2) / (xSize / 2.0)); double adj = (xSize / 2.0) * sin(angle); pad += QString("") .arg(color) .arg(posX - (xSize / 2.0)) .arg(posY) .arg(posX - (drillX / 2.0)) .arg(posY - adj) .arg(posX - (drillX / 2.0)) .arg(posY + adj); pad += QString("") .arg(color) .arg(posX + (xSize / 2.0)) .arg(posY) .arg(posX + (drillX / 2.0)) .arg(posY - adj) .arg(posX + (drillX / 2.0)) .arg(posY + adj); } pad += ""; return pad; } QString KicadModule2Svg::drawRPad(int posX, int posY, int xSize, int ySize, int drillX, int drillY, const QString & padName, int padNumber, const QString & padType, KicadModule2Svg::PadLayer padLayer) { QString color = getColor(padLayer); QString id = getID(padNumber, padLayer); if (padType == "SMD") { return QString("") .arg(posX - (xSize / 2.0)) .arg(posY - (ySize / 2.0)) .arg(xSize) .arg(ySize) .arg(id) .arg(color) .arg(padName); } QString pad = QString("").arg(id).arg(padName); if (drillX == drillY) { double w = (qMin(xSize, ySize) - drillX) / 2.0; pad += QString("") .arg(posX) .arg(posY) .arg((w / 2) + (drillX / 2.0)) .arg(checkStrokeWidth(w)) .arg(color); } else { double w = (drillX >= drillY) ? (xSize - drillX) / 2.0 : (ySize - drillY) / 2.0 ; pad += QString("") .arg(posX) .arg(posY) .arg((w / 2) + (qMax(drillX, drillY) / 2.0)) .arg(checkStrokeWidth(w)) .arg(color); pad += drawOblong(posX, posY, drillX + w, drillY + w, drillX, drillY, "", padLayer); } // draw 4 lines otherwise there may be gaps if one pair of sides is much longer than the other pair of sides double w = (ySize - drillY) / 2.0; double tlx = posX - xSize / 2.0; double tly = posY - ySize / 2.0; pad += QString("") .arg(tlx) .arg(tly + w / 2) .arg(tlx + xSize) .arg(checkStrokeWidth(w)) .arg(color); pad += QString("") .arg(tlx) .arg(tly + ySize - w / 2) .arg(tlx + xSize) .arg(checkStrokeWidth(w)) .arg(color); w = (xSize - drillX) / 2.0; pad += QString("") .arg(tlx + w / 2) .arg(tly) .arg(tly + ySize) .arg(checkStrokeWidth(w)) .arg(color); pad += QString("") .arg(tlx + xSize - w / 2) .arg(tly) .arg(tly + ySize) .arg(checkStrokeWidth(w)) .arg(color); pad += ""; return pad; } QString KicadModule2Svg::drawOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer padLayer) { if (xSize <= ySize) { return drawVerticalOblong(posX, posY, xSize, ySize, drillX, drillY, padType, padLayer); } else { return drawHorizontalOblong(posX, posY, xSize, ySize, drillX, drillY, padType, padLayer); } } QString KicadModule2Svg::getID(int padNumber, KicadModule2Svg::PadLayer padLayer) { if (padNumber < 0) { return QString("id='%1%2'").arg(FSvgRenderer::NonConnectorName).arg(m_nonConnectorNumber++); } return QString("id='connector%1%2'").arg(padNumber).arg((padLayer == ToCopper1) ? "pad" : "pin"); } QString KicadModule2Svg::getColor(KicadModule2Svg::PadLayer padLayer) { switch (padLayer) { case ToCopper0: return ViewLayer::Copper0Color; break; case ToCopper1: return ViewLayer::Copper1Color; break; default: DebugDialog::debug("kicad getcolor with unknown layer"); return "#FF0000"; } } fritzing-app-0.9.2b/src/svg/kicadmodule2svg.h000066400000000000000000000054071250202676700211350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef KICADMODULE2SVG_H #define KICADMODULE2SVG_H #include #include #include #include "kicad2svg.h" class KicadModule2Svg : public Kicad2Svg { public: KicadModule2Svg(); QString convert(const QString & filename, const QString & moduleName, bool allowPadsAndPins); public: static QStringList listModules(const QString & filename); public: enum PadLayer { ToCopper0, ToCopper1, UnableToTranslate }; protected: KicadModule2Svg::PadLayer convertPad(QTextStream & stream, QString & pad, QList & numbers); int drawDSegment(const QString & ds, QString & line); int drawDArc(const QString & ds, QString & arc); int drawDCircle(const QString & ds, QString & arc); QString drawOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer); QString drawVerticalOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer); QString drawHorizontalOblong(int posX, int posY, double xSize, double ySize, int drillX, int drillY, const QString & padType, KicadModule2Svg::PadLayer); void checkLimits(int posX, int xSize, int posY, int ySize); QString drawRPad(int posX, int posY, int xSize, int ySize, int drillX, int drillY, const QString & padName, int padNumber, const QString & padType, KicadModule2Svg::PadLayer); QString drawCPad(int posX, int posY, int xSize, int ySize, int drillX, int drillY, const QString & padName, int padNumber, const QString & padType, KicadModule2Svg::PadLayer); QString getColor(KicadModule2Svg::PadLayer padLayer); QString getID(int padNumber, KicadModule2Svg::PadLayer padLayer); protected: int m_nonConnectorNumber; }; #endif // KICADMODULE2SVG_H fritzing-app-0.9.2b/src/svg/kicadschematic2svg.cpp000066400000000000000000000410511250202676700221360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "kicadschematic2svg.h" #include "../utils/textutils.h" #include "../utils/graphicsutils.h" #include "../version/version.h" #include "../debugdialog.h" #include "../viewlayer.h" #include "../fsvgrenderer.h" #include "../utils/misc.h" #include #include #include #include #include #include #include // TODO: // pin shape: invert, etc. KicadSchematic2Svg::KicadSchematic2Svg() : Kicad2Svg() { } QStringList KicadSchematic2Svg::listDefs(const QString & filename) { QStringList defs; QFile file(filename); if (!file.open(QFile::ReadOnly)) return defs; QTextStream textStream(&file); while (true) { QString line = textStream.readLine(); if (line.isNull()) break; if (line.startsWith("DEF")) { QStringList linedefs = line.split(" ", QString::SkipEmptyParts); if (linedefs.count() > 1) { defs.append(linedefs[1]); } } } return defs; } QString KicadSchematic2Svg::convert(const QString & filename, const QString & defName) { initLimits(); QFile file(filename); if (!file.open(QFile::ReadOnly)) { throw QObject::tr("unable to open %1").arg(filename); } QTextStream textStream(&file); QString metadata = makeMetadata(filename, "schematic part", defName); metadata += endMetadata(); QString reference; int textOffset = 0; bool drawPinNumber = true; bool drawPinName = true; bool gotDef = false; while (true) { QString line = textStream.readLine(); if (line.isNull()) { break; } if (line.startsWith("DEF") && line.contains(defName, Qt::CaseInsensitive)) { QStringList defs = splitLine(line); if (defs.count() < 8) { throw QObject::tr("bad schematic definition %1").arg(filename); } reference = defs[2]; textOffset = defs[4].toInt(); drawPinName = defs[6] == "Y"; drawPinNumber = defs[5] == "Y"; gotDef = true; break; } } if (!gotDef) { throw QObject::tr("schematic part %1 not found in %2").arg(defName).arg(filename); } QString contents = "\n"; bool inFPLIST = false; while (true) { QString fline = textStream.readLine(); if (fline.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (1) in %2").arg(defName).arg(filename); } if (fline.contains("ENDDEF")) { throw QObject::tr("schematic %1 unexpectedly ends (2) in %2").arg(defName).arg(filename); } if (fline.startsWith("DRAW")) { break; } if (fline.startsWith("ALIAS")) continue; if (fline.startsWith("F")) { contents += convertField(fline); continue; } if (fline.startsWith("$FPLIST")) { inFPLIST = true; break; } } while (inFPLIST) { QString fline = textStream.readLine(); if (fline.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (1) in %2").arg(defName).arg(filename); } if (fline.startsWith("$ENDFPLIST")) { inFPLIST = false; break; } if (fline.contains("ENDDEF")) { throw QObject::tr("schematic %1 unexpectedly ends (2) in %2").arg(defName).arg(filename); } } int pinIndex = 0; while (true) { QString line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (3) in %2").arg(defName).arg(filename); } if (line.startsWith("DRAW")) { continue; } if (line.contains("ENDDEF")) { break; } if (line.contains("ENDDRAW")) { break; } if (line.startsWith("S")) { contents += convertRect(line); } else if (line.startsWith("X")) { // need to look at them all before formatting (I think) contents += convertPin(line, textOffset, drawPinName, drawPinNumber, pinIndex++); } else if (line.startsWith("C")) { contents += convertCircle(line); } else if (line.startsWith("P")) { contents += convertPoly(line); } else if (line.startsWith("A")) { contents += convertArc(line); } else if (line.startsWith("T")) { contents += convertText(line); } else { DebugDialog::debug("Unknown line " + line); } } contents += "\n"; QString svg = TextUtils::makeSVGHeader(GraphicsUtils::StandardFritzingDPI, GraphicsUtils::StandardFritzingDPI, m_maxX - m_minX, m_maxY - m_minY) + m_title + m_description + metadata + offsetMin(contents) + ""; return svg; } QString KicadSchematic2Svg::convertText(const QString & line) { QStringList fs = splitLine(line); if (fs.count() < 8) { DebugDialog::debug("bad text " + line); return ""; } return convertField(fs[2], fs[3], fs[4], fs[1], "C", "C", fs[8]); } QString KicadSchematic2Svg::convertField(const QString & line) { QStringList fs = splitLine(line); if (fs.count() < 7) { DebugDialog::debug("bad field " + line); return ""; } if (fs[6] == "I") { // invisible return ""; } while (fs.count() < 9) { fs.append(""); } return convertField(fs[2], fs[3], fs[4], fs[5], fs[7], fs[8], fs[1]); } QString KicadSchematic2Svg::convertField(const QString & xString, const QString & yString, const QString & fontSizeString, const QString &orientation, const QString & hjustify, const QString & vjustify, const QString & t) { QString text = t; bool notName = false; if (text.startsWith("~")) { notName = true; text.remove(0, 1); } int x = xString.toInt(); int y = -yString.toInt(); // KiCad flips y-axis w.r.t. svg int fontSize = fontSizeString.toInt(); bool rotate = (orientation == "V"); QString rotation; QMatrix m; if (rotate) { m = QMatrix().translate(-x, -y) * QMatrix().rotate(-90) * QMatrix().translate(x, y); // store x, y, and r so they can be shifted correctly later rotation = QString("transform='%1' _x='%2' _y='%3' _r='-90'").arg(TextUtils::svgMatrix(m)).arg(x).arg(y); } QFont font; font.setFamily(OCRAFontName); font.setWeight(QFont::Normal); font.setPointSizeF(72.0 * fontSize / GraphicsUtils::StandardFritzingDPI); QString style; if (vjustify.contains("I")) { style += "font-style='italic' "; font.setStyle(QFont::StyleItalic); } if (vjustify.endsWith("B")) { style += "font-weight='bold' "; font.setWeight(QFont::Bold); } QString anchor = "middle"; if (vjustify.startsWith("T")) { anchor = "end"; } else if (vjustify.startsWith("B")) { anchor = "start"; } if (hjustify.contains("L")) { anchor = "start"; } else if (hjustify.contains("R")) { anchor = "end"; } QFontMetricsF metrics(font); QRectF bri = metrics.boundingRect(text); // convert back to 1000 dpi QRectF brf(0, 0, bri.width() * GraphicsUtils::StandardFritzingDPI / GraphicsUtils::SVGDPI, bri.height() * GraphicsUtils::StandardFritzingDPI / GraphicsUtils::SVGDPI); if (anchor == "start") { brf.translate(x, y - (brf.height() / 2)); } else if (anchor == "end") { brf.translate(x - brf.width(), y - (brf.height() / 2)); } else if (anchor == "middle") { brf.translate(x - (brf.width() / 2), y - (brf.height() / 2)); } if (rotate) { brf = m.map(QPolygonF(brf)).boundingRect(); } checkXLimit(brf.left()); checkXLimit(brf.right()); checkYLimit(brf.top()); checkYLimit(brf.bottom()); QString s = QString("%7\n") .arg(x) .arg(y + (fontSize / 3)) .arg(fontSize) .arg(anchor) .arg(style) .arg(rotation) .arg(TextUtils::escapeAnd(unquote(text))) .arg(OCRAFontName) ; if (notName) { s += QString("\n") .arg(brf.left()) .arg(brf.top()) .arg(rotate ? brf.left() : brf.right()) .arg(rotate ? brf.bottom() : brf.top()); } return s; } QString KicadSchematic2Svg::convertRect(const QString & line) { QStringList s = splitLine(line); if (s.count() < 8) { DebugDialog::debug(QString("bad rectangle %1").arg(line)); return ""; } if (s.count() < 9) { s.append("N"); // assume it's unfilled } int x = s[1].toInt(); int y = -s[2].toInt(); // KiCad flips y-axis w.r.t. svg int x2 = s[3].toInt(); int y2 = -s[4].toInt(); // KiCad flips y-axis w.r.t. svg checkXLimit(x); checkXLimit(x2); checkYLimit(y); checkYLimit(y2); QString rect = QString(" 12 && l[12] == "N") { // don't draw this return ""; } int unit = l[9].toInt(); if (unit > 1) { // don't draw this return ""; } QChar orientation = l[6].at(0); QString name = l[1]; if (name == "~") { name = ""; } bool pinNumberOK; int pinNumber = l[2].toInt(&pinNumberOK); if (!pinNumberOK) { pinNumber = pinIndex; } int nFontSize = l[7].toInt(); int x1 = l[3].toInt(); int y1 = -l[4].toInt(); // KiCad flips y-axis w.r.t. svg int length = l[5].toInt(); int x2 = x1; int y2 = y1; int x3 = x1; int y3 = y1; int x4 = x1; int y4 = y1; QString justify = "C"; bool rotate = false; switch (orientation.toLatin1()) { case 'D': y2 = y1 + length; y3 = y1 + (length / 2); if (textOffset == 0) { x3 += nFontSize / 2; x4 -= nFontSize / 2; y4 = y3; justify = "C"; } else { x3 -= nFontSize / 2; y4 = y2; justify = "R"; } rotate = true; break; case 'U': y2 = y1 - length; y3 = y1 - (length / 2); if (textOffset == 0) { x3 += nFontSize / 2; x4 -= nFontSize / 2; y4 = y3; justify = "C"; } else { x3 -= nFontSize / 2; y4 = y2; justify = "L"; } rotate = true; break; case 'L': x2 = x1 - length; x3 = x1 - (length / 2); if (textOffset == 0) { y3 += nFontSize / 2; y4 -= nFontSize / 2; x4 = x3; justify = "C"; } else { y3 -= nFontSize / 2; x4 = x2; justify = "R"; } break; case 'R': x2 = x1 + length; x3 = x1 + (length / 2); if (textOffset == 0) { y3 += nFontSize / 2; y4 -= nFontSize / 2; x4 = x3; justify = "C"; } else { y3 -= nFontSize / 2; x4 = x2; justify = "L"; } break; default: DebugDialog::debug(QString("bad orientation %1").arg(line)); break; } checkXLimit(x1); checkXLimit(x2); checkYLimit(y1); checkYLimit(y2); int thickness = 1; QString pin = QString("\n") .arg(x1) .arg(y1) .arg(x2) .arg(y2) .arg(thickness) .arg(pinNumber) .arg(TextUtils::escapeAnd(name)); pin += QString("\n") .arg(x1) .arg(y1) .arg(pinNumber); if (drawPinNumber) { pin += convertField(QString::number(x3), QString::number(-y3), l[7], rotate ? "V" : "H", "C", "C", l[2]); } if (drawPinName && !name.isEmpty()) { pin += convertField(QString::number(x4), QString::number(-y4), l[8], rotate ? "V" : "H", justify, "C", name); } return pin; } QString KicadSchematic2Svg::convertCircle(const QString & line) { QStringList s = splitLine(line); if (s.count() < 8) { DebugDialog::debug(QString("bad circle %1").arg(line)); return ""; } int x = s[1].toInt(); int y = -s[2].toInt(); // KiCad flips y-axis w.r.t. svg int r = s[3].toInt(); checkXLimit(x + r); checkXLimit(x - r); checkYLimit(y + r); checkYLimit(y - r); QString circle = QString(" 180 sweeps double diffAngle = endAngle - startAngle; if (diffAngle > 180) diffAngle -= 360; else if (diffAngle < -180) diffAngle += 360; // TODO: use actual bounding box of arc for clipping checkXLimit(x + r); checkXLimit(x - r); checkYLimit(y + r); checkYLimit(y - r); QString arc = QString("= 180 ? 1 : 0) .arg(diffAngle > 0 ? 0 : 1) .arg(x2 - x1) .arg(y2 - y1); arc += addFill(line, s[9], s[8]); arc += " />\n"; return arc; } QString KicadSchematic2Svg::convertPoly(const QString & line) { QStringList s = splitLine(line); if (s.count() < 6) { DebugDialog::debug(QString("bad poly %1").arg(line)); return ""; } int np = s[1].toInt(); if (np < 2) { DebugDialog::debug(QString("degenerate poly %1").arg(line)); return ""; } if (s.count() < (np * 2) + 5) { DebugDialog::debug(QString("bad poly (2) %1").arg(line)); return ""; } if (s.count() < (np * 2) + 6) { s.append("N"); // assume unfilled } int ix = 5; if (np == 2) { int x1 = s[ix++].toInt(); int y1 = -s[ix++].toInt(); // KiCad flips y-axis w.r.t. svg int x2 = s[ix++].toInt(); int y2 = -s[ix++].toInt(); // KiCad flips y-axis w.r.t. svg checkXLimit(x1); checkYLimit(y1); checkXLimit(x2); checkYLimit(y2); QString line = QString(" 0; i--) { QString s = strs[i]; if (s[s.length() - 1] != '"') continue; if (s[0] == '"' && s.length() > 1) continue; // space in a quoted string: combine strs[i - 1] += strs[i]; strs.removeAt(i); } return strs; } fritzing-app-0.9.2b/src/svg/kicadschematic2svg.h000066400000000000000000000042201250202676700216000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef KICADSCHEMATIC2SVG_H #define KICADSCHEMATIC2SVG_H #include #include #include #include #include "kicad2svg.h" class KicadSchematic2Svg : public Kicad2Svg { public: KicadSchematic2Svg(); QString convert(const QString & filename, const QString &defName); public: static QStringList listDefs(const QString & filename); protected: QString convertField(const QString & line); QString convertText(const QString & line); QString convertField(const QString & xString, const QString & yString, const QString & fontSizeString, const QString & orientation, const QString & hjustify, const QString & vjustify, const QString & text); QString convertRect(const QString & line); QString convertCircle(const QString & line); QString convertPin(const QString & line, int textOffset, bool drawPinName, bool drawPinNumber, int pinIndex); QString convertArc(const QString & line); QString convertPoly(const QString & line); QString addFill(const QString & line, const QString & NF, const QString & strokeString); QStringList splitLine(const QString & line); }; #endif // KICADSCHEMATIC2SVG_H fritzing-app-0.9.2b/src/svg/svg2gerber.cpp000066400000000000000000000746521250202676700204650ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "svg2gerber.h" #include "../debugdialog.h" #include "svgflattener.h" #include #include #include static const double MaskClearance = 0.005; // 5 mils clearance bool fillNotStroke(QDomElement & element, SVG2gerber::ForWhy forWhy) { if (forWhy == SVG2gerber::ForOutline) return false; if (forWhy == SVG2gerber::ForMask) return true; QString fill = element.attribute("fill"); if (fill.isEmpty()) return false; if (fill.compare("none") == 0) return false; QString stroke = element.attribute("stroke"); if (stroke.isEmpty()) return true; if (stroke.compare("none") == 0) return true; // both fill and stroke // note: this originally returned 'false' which suggests there may be some parts that will surprise us next time they are exported to gerber return true; } //TODO: currently only supports one board per sketch (i.e. multiple board outlines will mess you up) SVG2gerber::SVG2gerber() { } int SVG2gerber::convert(const QString & svgStr, bool doubleSided, const QString & mainLayerName, ForWhy forWhy, QSizeF boardSize) { m_boardSize = boardSize; m_SVGDom = QDomDocument("svg"); QString errorStr; int errorLine; int errorColumn; bool result = m_SVGDom.setContent(svgStr, &errorStr, &errorLine, &errorColumn); if (!result) { DebugDialog::debug(QString("gerber svg failed %2 %3 %4 %1").arg(svgStr).arg(errorStr).arg(errorLine).arg(errorColumn)); } #ifndef QT_NO_DEBUG QString temp = m_SVGDom.toString(); #endif normalizeSVG(); #ifndef QT_NO_DEBUG temp = m_SVGDom.toString(); #endif return renderGerber(doubleSided, mainLayerName, forWhy); } QString SVG2gerber::getGerber(){ return m_gerber_header + m_gerber_paths; } int SVG2gerber::renderGerber(bool doubleSided, const QString & mainLayerName, ForWhy forWhy) { if (forWhy != ForDrill) { // human readable description comments m_gerber_header = "G04 MADE WITH FRITZING*\n"; m_gerber_header += "G04 WWW.FRITZING.ORG*\n"; m_gerber_header += QString("G04 %1 SIDED*\n").arg(doubleSided ? "DOUBLE" : "SINGLE"); m_gerber_header += QString("G04 HOLES%1PLATED*\n").arg(doubleSided ? " " : " NOT "); m_gerber_header += "G04 CONTOUR ON CENTER OF CONTOUR VECTOR*\n"; // initialize axes m_gerber_header += "%ASAXBY*%\n"; // NOTE: this currently forces a 1 mil grid // format coordinates to drop leading zeros with 2,3 digits m_gerber_header += "%FSLAX23Y23*%\n"; // set units to inches m_gerber_header += "%MOIN*%\n"; // no offset m_gerber_header += "%OFA0B0*%\n"; // scale factor 1x1 m_gerber_header += "%SFA1.0B1.0*%\n"; } else { // deal with header at the end } // define apertures and draw them int invalidCount = allPaths2gerber(forWhy); if (forWhy == ForDrill) { static const int initialHoleIndex = 1; static const int offset = 100; int initialPlatedIndex = (((m_holeApertures.uniqueKeys().count() + initialHoleIndex - 1) / offset) + 1) * offset; m_gerber_header = ""; m_gerber_header += QString("; NON-PLATED HOLES START AT T%1\n").arg(initialHoleIndex); m_gerber_header += QString("; THROUGH (PLATED) HOLES START AT T%1\n").arg(initialPlatedIndex); // setup drill file header m_gerber_header += "M48\n"; // set to english (inches) units, with trailing zeros m_gerber_header += "INCH\n"; int ix = initialHoleIndex; foreach (QString aperture, m_holeApertures.uniqueKeys()) { m_gerber_header += QString("T%1%2\n").arg(ix).arg(aperture); m_gerber_paths += QString("T%1\n").arg(ix); foreach (QString loc, m_holeApertures.values(aperture).toSet()) { m_gerber_paths += loc + "\n"; } ix++; } ix = initialPlatedIndex; foreach (QString aperture, m_platedApertures.uniqueKeys()) { m_gerber_header += QString("T%1%2\n").arg(ix).arg(aperture); m_gerber_paths += QString("T%1\n").arg(ix); foreach (QString loc, m_platedApertures.values(aperture).toSet()) { m_gerber_paths += loc + "\n"; } ix++; } m_gerber_header += "%\n"; // closes the header //m_gerber_paths += m_drill_slots; // from handleOblong, not up to date // drill file unload tool and end of program m_gerber_paths += "T00\n"; m_gerber_paths += "M30\n"; } else { // label our layers m_gerber_header += QString("%LN%1*%\n").arg(mainLayerName.toUpper()); //just to be safe: G90 (absolute coords) and G70 (inches) m_gerber_header += "G90*\nG70*\n"; // now write the footer // comment to indicate end-of-sketch m_gerber_paths += QString("G04 End of %1*\n").arg(mainLayerName); // write gerber end-of-program m_gerber_paths += "M02*"; } return invalidCount; } void SVG2gerber::normalizeSVG(){ QDomElement root = m_SVGDom.documentElement(); // convert to paths convertShapes2paths(root); // get rid of transforms SvgFlattener flattener; flattener.flattenChildren(root); } void SVG2gerber::convertShapes2paths(QDomNode node){ // I'm a leaf node. make me a path //TODO: this should strip svg: namspaces if(!node.hasChildNodes()) { QString tag = node.nodeName().toLower(); QDomElement element = node.toElement(); QDomElement path; //DebugDialog::debug("converting child to path: " + tag); if(tag=="polygon"){ path = element; } else if(tag=="polyline"){ path = element; } else if(tag=="rect"){ path = element; } else if(tag=="circle"){ path = element; } else if(tag=="line"){ path = element; } else if(tag=="ellipse"){ path = ellipse2path(element); } else if((tag=="path") || (tag=="svg:path")){ path = element; } else if (tag == "g") { // no op } else if (tag == "#comment") { // no op } else if (tag == "#text") { // no op } else { DebugDialog::debug("svg2gerber ignoring SVG element: " + tag); } copyStyles(element, path); // add the path and delete the primitive element (is this ok for paths?) QDomNode parent = node.parentNode(); parent.replaceChild(path, node); return; } // recurse the children QDomNodeList tagList = node.childNodes(); //DebugDialog::debug("child nodes: " + QString::number(tagList.length())); for(int i = 0; i < tagList.length(); i++){ convertShapes2paths(tagList.item(i)); } } void SVG2gerber::copyStyles(QDomElement source, QDomElement dest){ QStringList attrList; attrList << "stroke" << "fill" << "stroke-width" << "style"; for (int i = 0; i < attrList.size(); ++i) { if (source.hasAttribute(attrList.at(i))) dest.setAttribute(attrList.at(i), source.attribute(attrList.at(i))); } } QMatrix SVG2gerber::parseTransform(QDomElement element){ QMatrix transform = QMatrix(); QString svgTransform = element.attribute("transform"); return transform; } int SVG2gerber::allPaths2gerber(ForWhy forWhy) { int invalidPathsCount = 0; QHash apertureMap; QString current_dcode; int dcode_index = 10; bool light_on = false; int currentx = -1; int currenty = -1; m_holeApertures.clear(); m_platedApertures.clear(); // iterates through all circles, rects, lines and paths // 1. check if we already have an aperture // if aperture does not exist, add it to the header // 2. switch to this aperture // 3. draw it at the correct path/location QDomNodeList circleList = m_SVGDom.elementsByTagName("circle"); //DebugDialog::debug("circles to gerber: " + QString::number(circleList.length())); QDomNodeList rectList = m_SVGDom.elementsByTagName("rect"); //DebugDialog::debug("rects to gerber: " + QString::number(rectList.length())); QDomNodeList polyList = m_SVGDom.elementsByTagName("polygon"); //DebugDialog::debug("polygons to gerber: " + QString::number(polyList.length())); QDomNodeList polyLineList = m_SVGDom.elementsByTagName("polyline"); //DebugDialog::debug("polylines to gerber: " + QString::number(polyLineList.length())); QDomNodeList lineList = m_SVGDom.elementsByTagName("line"); //DebugDialog::debug("lines to gerber: " + QString::number(lineList.length())); QDomNodeList pathList = m_SVGDom.elementsByTagName("path"); //DebugDialog::debug("paths to gerber: " + QString::number(pathList.length())); // if this is the board outline, use it as the contour if (forWhy == ForOutline) { //DebugDialog::debug("drawing board outline"); // switch aperture to the only one used for contour: note this is the last one on the list: the aperture is added at the end of this function m_gerber_paths += "G54D10*\n"; } // circles for(int i = 0; i < circleList.length(); i++){ QDomElement circle = circleList.item(i).toElement(); double centerx = circle.attribute("cx").toDouble(); double centery = circle.attribute("cy").toDouble(); double r = circle.attribute("r").toDouble(); if (r == 0) continue; QString drillAttribute = circle.attribute("drill", ""); bool noDrill = (drillAttribute.compare("0") == 0 || drillAttribute.compare("no", Qt::CaseInsensitive) == 0 || drillAttribute.compare("false", Qt::CaseInsensitive) == 0); double stroke_width = circle.attribute("stroke-width").toDouble(); double hole = ((2*r) - stroke_width) / 1000; // convert mils (standard fritzing resolution) to inches if (forWhy == ForDrill) { if (noDrill) continue; QString drill_cx = QString("%1").arg((int) (flipxNoRound(centerx) * 10), 6, 10, QChar('0')); // drill file is in inches 00.0000, converting mils to 10000ths QString drill_cy = QString("%1").arg((int) (flipyNoRound(centery) * 10), 6, 10, QChar('0')); // drill file is in inches 00.0000, converting mils to 10000ths QString aperture = QString("C%1").arg(hole, 0, 'f'); QString loc = "X" + drill_cx + "Y" + drill_cy; if (stroke_width == 0) m_holeApertures.insert(aperture, loc); else m_platedApertures.insert(aperture, loc); continue; } QString aperture; QString cx = QString::number(flipx(centerx)); QString cy = QString::number(flipy(centery)); QString fill = circle.attribute("fill"); double diam = ((2*r) + stroke_width)/1000; if (forWhy == ForMask) { diam += 2 * MaskClearance; } if ((forWhy != ForCopper && fill=="none" && forWhy != ForMask) || (forWhy == ForCopper && noDrill)) { aperture = QString("C,%1X%2").arg(diam, 0, 'f').arg(hole); } else { aperture = QString("C,%1").arg(diam, 0, 'f'); } // add aperture to defs if we don't have it yet if(!apertureMap.contains(aperture)){ apertureMap[aperture] = QString::number(dcode_index); m_gerber_header += "%ADD" + QString::number(dcode_index) + aperture + "*%\n"; dcode_index++; } if (forWhy != ForOutline) { QString dcode = apertureMap[aperture]; if(current_dcode != dcode){ //switch to correct aperture m_gerber_paths += "G54D" + dcode + "*\n"; current_dcode = dcode; } //flash m_gerber_paths += "X" + cx + "Y" + cy + "D03*\n"; } else { standardAperture(circle, apertureMap, current_dcode, dcode_index, 0); // create circle outline m_gerber_paths += QString("G01X%1Y%2D02*\n" "G75*\n" "G03X%1Y%2I%3J0D01*\n") .arg(QString::number(flipx(centerx + r))) .arg(QString::number(flipy(centery))) .arg(QString::number(qRound(-r))); m_gerber_paths += "G01*\n"; } } if (forWhy != ForDrill) { // rects for(int j = 0; j < rectList.length(); j++){ QDomElement rect = rectList.item(j).toElement(); QString aperture; double width = rect.attribute("width").toDouble(); double height = rect.attribute("height").toDouble(); double rx = rect.attribute("rx", "0").toDouble(); double ry = rect.attribute("ry", "0").toDouble(); if (rx != 0 || ry != 0) { // not sure how to do rounded rects in gerber invalidPathsCount++; continue; } if (width == 0) continue; if (height == 0) continue; double x = rect.attribute("x").toDouble(); double y = rect.attribute("y").toDouble(); double centerx = x + (width/2); double centery = y + (height/2); QString cx = QString::number(flipx(centerx)); QString cy = QString::number(flipy(centery)); QString fill = rect.attribute("fill"); double stroke_width = rect.attribute("stroke-width").toDouble(); double totalx = (width + stroke_width)/1000; double totaly = (height + stroke_width)/1000; double holex = (width - stroke_width)/1000; double holey = (height - stroke_width)/1000; if (forWhy == ForMask) { totalx += 2 * MaskClearance; totaly += 2 * MaskClearance; } if(forWhy != ForCopper && fill=="none" && forWhy != ForMask) { aperture = QString("R,%1X%2X%3X%4").arg(totalx, 0, 'f').arg(totaly, 0, 'f').arg(holex, 0, 'f').arg(holey, 0, 'f'); } else { aperture = QString("R,%1X%2").arg(totalx, 0, 'f').arg(totaly, 0, 'f'); } // add aperture to defs if we don't have it yet if(!apertureMap.contains(aperture)){ apertureMap[aperture] = QString::number(dcode_index); m_gerber_header += "%ADD" + QString::number(dcode_index) + aperture + "*%\n"; dcode_index++; } bool doLines = false; if (forWhy == ForOutline) doLines = true; else if (forWhy == ForSilk && fill == "none") doLines = true; if (!doLines) { QString dcode = apertureMap[aperture]; if(current_dcode != dcode){ //switch to correct aperture m_gerber_paths += "G54D" + dcode + "*\n"; current_dcode = dcode; } //flash m_gerber_paths += "X" + cx + "Y" + cy + "D03*\n"; } else { // draw 4 lines standardAperture(rect, apertureMap, current_dcode, dcode_index, 0); m_gerber_paths += "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y)) + "D02*\n"; m_gerber_paths += "X" + QString::number(flipx(x+width)) + "Y" + QString::number(flipy(y)) + "D01*\n"; m_gerber_paths += "X" + QString::number(flipx(x+width)) + "Y" + QString::number(flipy(y+height)) + "D01*\n"; m_gerber_paths += "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y+height)) + "D01*\n"; m_gerber_paths += "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y)) + "D01*\n"; m_gerber_paths += "D02*\n"; } } // lines - NOTE: this assumes a circular aperture for(int k = 0; k < lineList.length(); k++){ QDomElement line = lineList.item(k).toElement(); // Note: should be no forWhy == ForMask cases double x1 = line.attribute("x1").toDouble(); double y1 = line.attribute("y1").toDouble(); double x2 = line.attribute("x2").toDouble(); double y2 = line.attribute("y2").toDouble(); standardAperture(line, apertureMap, current_dcode, dcode_index, 0); // turn off light if we are not continuing along a path if ((y1 != currenty) || (x1 != currentx)) { if (light_on) { m_gerber_paths += "D02*\n"; light_on = false; } } //go to start - light off m_gerber_paths += "X" + QString::number(flipx(x1)) + "Y" + QString::number(flipy(y1)) + "D02*\n"; //go to end point - light on m_gerber_paths += "X" + QString::number(flipx(x2)) + "Y" + QString::number(flipy(y2)) + "D01*\n"; light_on = true; currentx = x2; currenty = y2; } // polys - NOTE: assumes comma- or space- separated formatting for(int p = 0; p < polyList.length(); p++) { QDomElement polygon = polyList.item(p).toElement(); doPoly(polygon, forWhy, true, apertureMap, current_dcode, dcode_index); } for(int p = 0; p < polyLineList.length(); p++) { QDomElement polygon = polyLineList.item(p).toElement(); doPoly(polygon, forWhy, false, apertureMap, current_dcode, dcode_index); } } // paths - NOTE: this assumes circular aperture for(int n = 0; n < pathList.length(); n++){ QDomElement path = pathList.item(n).toElement(); if (forWhy == ForDrill) { handleOblongPath(path, dcode_index); // this is currently a no-op continue; } QString data = path.attribute("d").trimmed(); const char * slot = SLOT(path2gerbCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.x = 0; pathUserData.y = 0; pathUserData.pathStarting = true; pathUserData.string = ""; SvgFlattener flattener; bool invalid = false; try { flattener.parsePath(data, slot, pathUserData, this, true); } catch (const QString & msg) { DebugDialog::debug("flattener.parsePath failed " + msg); invalid = true; } catch (char const *str) { DebugDialog::debug("flattener.parsePath failed " + QString(str)); invalid = true; } catch (...) { DebugDialog::debug("flattener.parsePath failed"); invalid = true; } // only add paths if they contained gerber-izable path commands (NO CURVES!) // TODO: display some informative error for the user if (invalid || pathUserData.string.contains("INVALID")) { invalidPathsCount++; continue; } if (path.attribute("stroke-linecap") == "square") { double stroke_width = path.attribute("stroke-width").toDouble(); if (stroke_width != 0) { QString aperture = QString("R,%1X%1").arg(stroke_width/1000, 0, 'f'); // add aperture to defs if we don't have it yet if (!apertureMap.contains(aperture)) { apertureMap[aperture] = QString::number(dcode_index); m_gerber_header += "%ADD" + QString::number(dcode_index) + aperture + "*%\n"; dcode_index++; } QString dcode = apertureMap[aperture]; if (current_dcode != dcode) { //switch to correct aperture m_gerber_paths += "G54D" + dcode + "*\n"; current_dcode = dcode; } } } else { standardAperture(path, apertureMap, current_dcode, dcode_index, 0); } // set poly fill if this is actually a filled in shape bool polyFill = fillNotStroke(path, forWhy); if(polyFill) { // start poly fill m_gerber_paths += "G36*\n"; } m_gerber_paths += pathUserData.string; //DebugDialog::debug("path id: " + path.attribute("id")); // stop poly fill if this is actually a filled in shape if(polyFill){ // stop poly fill m_gerber_paths += "G37*\n"; } if (forWhy == ForMask) { // draw the outline, G36 only does the fill standardAperture(path, apertureMap, current_dcode, dcode_index, path.attribute("stroke-width").toDouble() + (MaskClearance * 2 * 1000)); m_gerber_paths += pathUserData.string; } // light off m_gerber_paths += "D02*\n"; } if (forWhy == ForOutline) { // add circular aperture with 0 width m_gerber_header += "%ADD10C,0.008*%\n"; } return invalidPathsCount; } void SVG2gerber::doPoly(QDomElement & polygon, ForWhy forWhy, bool closedCurve, QHash & apertureMap, QString & current_dcode, int & dcode_index) { //QString temp; //QTextStream tempStream(&temp); //polygon.save(tempStream, 1); QString points = polygon.attribute("points"); QStringList pointList = points.split(QRegExp("\\s+|,"), QString::SkipEmptyParts); QString aperture; QString pointString; double startx = pointList.at(0).toDouble(); double starty = pointList.at(1).toDouble(); // move to start - light off pointString += "X" + QString::number(flipx(startx)) + "Y" + QString::number(flipy(starty)) + "D02*\n"; // iterate through all other points - light on for(int pt = 2; pt < pointList.length(); pt +=2){ double ptx = pointList.at(pt).toDouble(); double pty = pointList.at(pt+1).toDouble(); pointString += "X" + QString::number(flipx(ptx)) + "Y" + QString::number(flipy(pty)) + "D01*\n"; } if (closedCurve) { // move back to start point pointString += "X" + QString::number(flipx(startx)) + "Y" + QString::number(flipy(starty)) + "D01*\n"; } standardAperture(polygon, apertureMap, current_dcode, dcode_index, 0); bool polyFill = fillNotStroke(polygon, forWhy); // set poly fill if this is actually a filled in shape if (polyFill) { // start poly fill m_gerber_paths += "G36*\n"; } m_gerber_paths += pointString; // stop poly fill if this is actually a filled in shape if(polyFill){ // stop poly fill m_gerber_paths += "G37*\n"; } if (forWhy == ForMask) { // draw the outline, G36 only does the fill standardAperture(polygon, apertureMap, current_dcode, dcode_index, polygon.attribute("stroke-width").toDouble() + (MaskClearance * 2 * 1000)); m_gerber_paths += pointString; } // light off m_gerber_paths += "D02*\n"; } QString SVG2gerber::standardAperture(QDomElement & element, QHash & apertureMap, QString & current_dcode, int & dcode_index, double stroke_width) { if (stroke_width == 0) { stroke_width = element.attribute("stroke-width").toDouble(); } if (stroke_width == 0) return ""; QString aperture = QString("C,%1").arg(stroke_width/1000, 0, 'f'); // add aperture to defs if we don't have it yet if (!apertureMap.contains(aperture)){ apertureMap[aperture] = QString::number(dcode_index); m_gerber_header += "%ADD" + QString::number(dcode_index) + aperture + "*%\n"; dcode_index++; } QString dcode = apertureMap[aperture]; if (current_dcode != dcode) { //switch to correct aperture m_gerber_paths += "G54D" + dcode + "*\n"; current_dcode = dcode; } return aperture; } void SVG2gerber::handleOblongPath(QDomElement & path, int & dcode_index) { // this code has not been tested in a long time and is probably obsolete return; // look for oblong paths QDomElement parent = path.parentNode().toElement(); if (parent.attribute("id").compare("oblong") != 0) return; QDomElement nextPath = path.nextSiblingElement("path"); if (nextPath.isNull()) return; QDomElement nextLine = nextPath.nextSiblingElement("line"); if (nextLine.isNull()) return; double diameter = parent.attribute("stroke-width").toDouble(); double cx1 = nextLine.attribute("x1").toDouble(); double cy1 = nextLine.attribute("y1").toDouble(); double cx2 = nextLine.attribute("x2").toDouble(); double cy2 = nextLine.attribute("y2").toDouble(); QString drill_aperture = QString("C%1").arg(diameter / 1000, 0, 'f') + "\n"; // convert mils to inches if (!m_gerber_header.contains(drill_aperture)) { m_gerber_header += "T" + QString::number(dcode_index++) + drill_aperture; } int ix = m_gerber_header.indexOf(drill_aperture); int it = m_gerber_header.lastIndexOf("T", ix); m_drill_slots += QString("%1\nX%2Y%3G85X%4Y%5\nG05\n") .arg(m_gerber_header.mid(it, ix - it), 0, 'f') .arg((int) (flipxNoRound(cx1) * 10), 6, 10, QChar('0')) .arg((int) (flipyNoRound(cy1) * 10), 6, 10, QChar('0')) .arg((int) (flipxNoRound(cx2) * 10), 6, 10, QChar('0')) .arg((int) (flipyNoRound(cy2) * 10), 6, 10, QChar('0')); } QDomElement SVG2gerber::ellipse2path(QDomElement ellipseElement){ // TODO return ellipseElement; } QString SVG2gerber::path2gerber(QDomElement pathElement){ Q_UNUSED(pathElement); QString d; return d; } void SVG2gerber::path2gerbCommandSlot(QChar command, bool relative, QList & args, void * userData) { QString gerb_path; int x, y; PathUserData * pathUserData = (PathUserData *) userData; int argIndex = 0; while (argIndex < args.count()) { switch(command.toLatin1()) { case 'a': case 'A': case 'c': case 'C': case 'q': case 'Q': case 's': case 'S': case 't': case 'T': // TODO: implement elliptical arc, etc. pathUserData->string.append("INVALID"); argIndex = args.count(); break; case 'm': case 'M': x = args[argIndex]; y = args[argIndex + 1]; if (relative && !pathUserData->pathStarting) { x += pathUserData->x; y += pathUserData->y; } if (argIndex == 0) { // treat first 'm' arg pair as a move to gerb_path = "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y)) + "D02*\n"; m_pathstart_x = x; m_pathstart_y = y; } else { // treat subsequent 'm' arg pair as line to gerb_path = "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y)) + "D01*\n"; } pathUserData->x = x; pathUserData->y = y; pathUserData->pathStarting = false; pathUserData->string.append(gerb_path); argIndex += 2; break; case 'v': case 'V': DebugDialog::debug("'v' and 'V' are now removed by preprocessing; shouldn't be here"); break; case 'h': case 'H': DebugDialog::debug("'h' and 'H' are now removed by preprocessing; shouldn't be here"); break; case 'l': case 'L': x = args[argIndex]; y = args[argIndex + 1]; if (relative) { x += pathUserData->x; y += pathUserData->y; } gerb_path = "X" + QString::number(flipx(x)) + "Y" + QString::number(flipy(y)) + "D01*\n"; pathUserData->x = x; pathUserData->y = y; pathUserData->string.append(gerb_path); argIndex += 2; break; case 'z': case 'Z': gerb_path = "X" + QString::number(flipx(m_pathstart_x)) + "Y" + QString::number(flipy(m_pathstart_y)) + "D01*\n"; gerb_path += "D02*\n"; pathUserData->string.append(gerb_path); pathUserData->pathStarting = true; break; default: argIndex = args.count(); pathUserData->string.append("INVALID"); break; } } } int SVG2gerber::flipx(double x) { return qRound(x); } int SVG2gerber::flipy(double y) { return qRound(m_boardSize.height() - y); } double SVG2gerber::flipxNoRound(double x) { return x; } double SVG2gerber::flipyNoRound(double y) { return m_boardSize.height() - y; } fritzing-app-0.9.2b/src/svg/svg2gerber.h000066400000000000000000000054221250202676700201170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVG2GERBER_H #define SVG2GERBER_H #include #include #include #include #include class SVG2gerber : public QObject { Q_OBJECT public: SVG2gerber(); public: enum ForWhy { ForCopper, ForSilk, ForOutline, ForMask, ForDrill, ForPasteMask }; int convert(const QString & svgStr, bool doubleSided, const QString & mainLayerName, ForWhy, QSizeF boardSize); QString getGerber(); protected: QDomDocument m_SVGDom; QString m_gerber_header; QString m_gerber_paths; QString m_drill_slots; QSizeF m_boardSize; QMultiHash m_platedApertures; QMultiHash m_holeApertures; double m_pathstart_x; double m_pathstart_y; protected: void normalizeSVG(); void convertShapes2paths(QDomNode); void flattenSVG(QDomNode); QMatrix parseTransform(QDomElement); QDomElement ellipse2path(QDomElement); void copyStyles(QDomElement, QDomElement); int renderGerber(bool doubleSided, const QString & mainLayerName, ForWhy); int allPaths2gerber(ForWhy); QString path2gerber(QDomElement); void handleOblongPath(QDomElement & path, int & dcode_index); QString standardAperture(QDomElement & element, QHash & apertureMap, QString & current_dcode, int & dcode_index, double stroke_width); int flipx(double x); int flipy(double y); double flipxNoRound(double x); double flipyNoRound(double y); void doPoly(QDomElement & polygon, ForWhy forWhy, bool closedCurve, QHash & apertureMap, QString & current_dcode, int & dcode_index); protected slots: void path2gerbCommandSlot(QChar command, bool relative, QList & args, void * userData); }; #endif // SVG2GERBER_H fritzing-app-0.9.2b/src/svg/svgfilesplitter.cpp000066400000000000000000001231561250202676700216350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #include "svgfilesplitter.h" #include "../utils/misc.h" #include "../utils/textutils.h" //#include "../debugdialog.h" #include "svgpathparser.h" #include "svgpathlexer.h" #include "svgpathrunner.h" #include #include #include #include struct HVConvertData { double x; double y; double subX; double subY; QString path; }; void appendPair(QString & path, double a1, double a2) { path.append(QString::number(a1)); path.append(','); path.append(QString::number(a2)); path.append(','); } ////////////////////////////////////////////////// SvgFileSplitter::SvgFileSplitter() { } bool SvgFileSplitter::split(const QString & filename, const QString & elementID) { m_byteArray.clear(); QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { return false; } QString contents = file.readAll(); file.close(); return splitString(contents, elementID); } bool SvgFileSplitter::splitString(QString & contents, const QString & elementID) { m_byteArray.clear(); // gets rid of some crap inserted by illustrator which can screw up polygons and paths contents.replace('\t', ' '); contents.replace('\n', ' '); contents.replace('\r', ' '); // get rid of inkscape stuff too TextUtils::cleanSodipodi(contents); QString errorStr; int errorLine; int errorColumn; if (!m_domDocument.setContent(contents, true, &errorStr, &errorLine, &errorColumn)) { //DebugDialog::debug(QString("parse error: %1 l:%2 c:%3\n\n%4").arg(errorStr).arg(errorLine).arg(errorColumn).arg(contents)); return false; } QDomElement root = m_domDocument.documentElement(); if (root.isNull()) { return false; } if (root.tagName() != "svg") { return false; } root.removeAttribute("space"); QDomElement element = TextUtils::findElementWithAttribute(root, "id", elementID); if (element.isNull()) { return false; } QStringList superTransforms; QDomNode parent = element.parentNode(); while (!parent.isNull()) { QDomElement e = parent.toElement(); if (!e.isNull()) { QString transform = e.attribute("transform"); if (!transform.isEmpty()) { superTransforms.append(transform); } } parent = parent.parentNode(); } if (!superTransforms.isEmpty()) { element.removeAttribute("id"); } QDomDocument document; QDomNode node = document.importNode(element, true); document.appendChild(node); QString elementText = document.toString(); if (!superTransforms.isEmpty()) { for (int i = 0; i < superTransforms.count() - 1; i++) { elementText = QString("%2").arg(superTransforms[i]).arg(elementText); } elementText = QString("%3") .arg(elementID) .arg(superTransforms[superTransforms.count() - 1]) .arg(elementText); } while (!root.firstChild().isNull()) { root.removeChild(root.firstChild()); } // at this point the document should contain only the element and possibly svg info strings QString svgOnly = m_domDocument.toString(); int ix = svgOnly.lastIndexOf("/>"); if (ix < 0) return false; svgOnly[ix] = ' '; svgOnly += elementText; svgOnly += ""; if (!m_domDocument.setContent(svgOnly, true, &errorStr, &errorLine, &errorColumn)) { return false; } m_byteArray = m_domDocument.toByteArray(); //QString s = m_domDocument.toString(); //DebugDialog::debug(s); return true; } const QByteArray & SvgFileSplitter::byteArray() { return m_byteArray; } const QDomDocument & SvgFileSplitter::domDocument() { return m_domDocument; } QString SvgFileSplitter::elementString(const QString & elementID) { QDomElement root = m_domDocument.documentElement(); QDomElement mainElement = TextUtils::findElementWithAttribute(root, "id", elementID); if (mainElement.isNull()) return ___emptyString___; QDomDocument document; QDomNode node = document.importNode(mainElement, true); document.appendChild(node); return document.toString(); } bool SvgFileSplitter::normalize(double dpi, const QString & elementID, bool blackOnly, double & factor) { // get the viewbox and the width and height // then normalize them // then normalize all the internal stuff // if there are translations, we're probably ok factor = 1; QDomElement root = m_domDocument.documentElement(); if (root.isNull()) return false; double sWidth, sHeight, vbWidth, vbHeight; if (!TextUtils::getSvgSizes(m_domDocument, sWidth, sHeight, vbWidth, vbHeight)) return false; root.setAttribute("width", QString("%1in").arg(sWidth)); root.setAttribute("height", QString("%1in").arg(sHeight)); root.setAttribute("viewBox", QString("%1 %2 %3 %4").arg(0).arg(0).arg(sWidth * dpi).arg(sHeight * dpi) ); QDomElement mainElement = root; if (!elementID.isEmpty()) { mainElement = TextUtils::findElementWithAttribute(root, "id", elementID); if (mainElement.isNull()) return false; } normalizeChild(mainElement, sWidth * dpi, sHeight * dpi, vbWidth, vbHeight, blackOnly); factor = sWidth * dpi / vbWidth; return true; } QPainterPath SvgFileSplitter::painterPath(double dpi, const QString & elementID) { // only partially implemented because so far we only use this for polygons generated for the groundplane QPainterPath ppath; double factor; bool result = normalize(dpi, elementID, false, factor); if (!result) return ppath; QDomElement root = m_domDocument.documentElement(); if (root.isNull()) return ppath; QDomElement mainElement = TextUtils::findElementWithAttribute(root, "id", elementID); if (mainElement.isNull()) return ppath; QDomElement childElement = mainElement.firstChildElement(); while (!childElement.isNull()) { painterPathChild(childElement, ppath); childElement = childElement.nextSiblingElement(); } return ppath; } void SvgFileSplitter::painterPathChild(QDomElement & element, QPainterPath & ppath) { // only partially implemented if (element.nodeName().compare("circle") == 0) { double cx = element.attribute("cx").toDouble(); double cy = element.attribute("cy").toDouble(); double r = element.attribute("r").toDouble(); double stroke = element.attribute("stroke-width").toDouble(); ppath.addEllipse(QRectF(cx - r - (stroke / 2), cy - r - (stroke / 2), (r * 2) + stroke, (r * 2) + stroke)); } else if (element.nodeName().compare("line") == 0) { /* double x1 = element.attribute("x1").toDouble(); double y1 = element.attribute("y1").toDouble(); double x2 = element.attribute("x2").toDouble(); double y2 = element.attribute("y2").toDouble(); double stroke = element.attribute("stroke-width").toDouble(); // treat as parallel lines stroke width apart? */ } else if (element.nodeName().compare("rect") == 0) { double width = element.attribute("width").toDouble(); double height = element.attribute("height").toDouble(); double x = element.attribute("x").toDouble(); double y = element.attribute("y").toDouble(); double stroke = element.attribute("stroke-width").toDouble(); double rx = element.attribute("rx").toDouble(); double ry = element.attribute("ry").toDouble(); if (rx != 0 || ry != 0) { ppath.addRoundedRect(x - (stroke / 2), y - (stroke / 2), width + stroke, height + stroke, rx, ry); } else { ppath.addRect(x - (stroke / 2), y - (stroke / 2), width + stroke, height + stroke); } } else if (element.nodeName().compare("ellipse") == 0) { double cx = element.attribute("cx").toDouble(); double cy = element.attribute("cy").toDouble(); double rx = element.attribute("rx").toDouble(); double ry = element.attribute("ry").toDouble(); double stroke = element.attribute("stroke-width").toDouble(); ppath.addEllipse(QRectF(cx - rx - (stroke / 2), cy - ry - (stroke / 2), (rx * 2) + stroke, (ry * 2) + stroke)); } else if (element.nodeName().compare("polygon") == 0 || element.nodeName().compare("polyline") == 0) { QString data = element.attribute("points"); if (!data.isEmpty()) { const char * slot = SLOT(painterPathCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.painterPath = &ppath; if (parsePath(data, slot, pathUserData, this, false)) { } } } else if (element.nodeName().compare("path") == 0) { /* QString data = element.attribute("d").trimmed(); if (!data.isEmpty()) { const char * slot = SLOT(normalizeCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.sNewHeight = sNewHeight; pathUserData.sNewWidth = sNewWidth; pathUserData.vbHeight = vbHeight; pathUserData.vbWidth = vbWidth; if (parsePath(data, slot, pathUserData, this, true)) { element.setAttribute("d", pathUserData.string); } } */ } else { QDomElement childElement = element.firstChildElement(); while (!childElement.isNull()) { painterPathChild(childElement, ppath); childElement = childElement.nextSiblingElement(); } } } void SvgFileSplitter::normalizeTranslation(QDomElement & element, double sNewWidth, double sNewHeight, double vbWidth, double vbHeight) { QString attr = element.attribute("transform"); if (attr.isEmpty()) return; QMatrix matrix = TextUtils::elementToMatrix(element); if (matrix.dx() == 0 && matrix.dy() == 0) return; double dx = matrix.dx() * sNewWidth / vbWidth; double dy = matrix.dy() * sNewHeight / vbHeight; if (dx == 0 && dy == 0) return; matrix.setMatrix(matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), dx, dy); TextUtils::setSVGTransform(element, matrix); } void SvgFileSplitter::normalizeChild(QDomElement & element, double sNewWidth, double sNewHeight, double vbWidth, double vbHeight, bool blackOnly) { normalizeTranslation(element, sNewWidth, sNewHeight, vbWidth, vbHeight); bool doChildren = false; QString nodeName = element.nodeName(); if (nodeName.compare("g") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); normalizeAttribute(element, "font-size", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); doChildren = true; } else if (nodeName.compare("circle") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "cx", sNewWidth, vbWidth); normalizeAttribute(element, "cy", sNewHeight, vbHeight); normalizeAttribute(element, "r", sNewWidth, vbWidth); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("line") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "x1", sNewWidth, vbWidth); normalizeAttribute(element, "y1", sNewHeight, vbHeight); normalizeAttribute(element, "x2", sNewWidth, vbWidth); normalizeAttribute(element, "y2", sNewHeight, vbHeight); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("rect") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "width", sNewWidth, vbWidth); normalizeAttribute(element, "height", sNewHeight, vbHeight); normalizeAttribute(element, "x", sNewWidth, vbWidth); normalizeAttribute(element, "y", sNewHeight, vbHeight); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); // rx, ry for rounded rects if (!element.attribute("rx").isEmpty()) { normalizeAttribute(element, "rx", sNewWidth, vbWidth); } if (!element.attribute("ry").isEmpty()) { normalizeAttribute(element, "ry", sNewHeight, vbHeight); } setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("ellipse") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "cx", sNewWidth, vbWidth); normalizeAttribute(element, "cy", sNewHeight, vbHeight); normalizeAttribute(element, "rx", sNewWidth, vbWidth); normalizeAttribute(element, "ry", sNewHeight, vbHeight); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("polygon") == 0 || nodeName.compare("polyline") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); QString data = element.attribute("points"); if (!data.isEmpty()) { const char * slot = SLOT(normalizeCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.sNewHeight = sNewHeight; pathUserData.sNewWidth = sNewWidth; pathUserData.vbHeight = vbHeight; pathUserData.vbWidth = vbWidth; if (parsePath(data, slot, pathUserData, this, false)) { pathUserData.string.remove(0, 1); // get rid of the "M" element.setAttribute("points", pathUserData.string); } } setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("path") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); QString data = element.attribute("d").trimmed(); if (!data.isEmpty()) { const char * slot = SLOT(normalizeCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.sNewHeight = sNewHeight; pathUserData.sNewWidth = sNewWidth; pathUserData.vbHeight = vbHeight; pathUserData.vbWidth = vbWidth; if (parsePath(data, slot, pathUserData, this, true)) { element.setAttribute("d", pathUserData.string); } } } else if (nodeName.compare("text") == 0) { TextUtils::fixStyleAttribute(element); normalizeAttribute(element, "x", sNewWidth, vbWidth); normalizeAttribute(element, "y", sNewHeight, vbHeight); normalizeAttribute(element, "stroke-width", sNewWidth, vbWidth); normalizeAttribute(element, "font-size", sNewWidth, vbWidth); setStrokeOrFill(element, blackOnly, "black", false); } else if (nodeName.compare("linearGradient") == 0) { if (element.attribute("gradientUnits").compare("userSpaceOnUse") == 0) { normalizeAttribute(element, "x1", sNewWidth, vbWidth); normalizeAttribute(element, "y1", sNewWidth, vbWidth); normalizeAttribute(element, "x2", sNewWidth, vbWidth); normalizeAttribute(element, "y2", sNewWidth, vbWidth); } else { //DebugDialog::debug(QString("unable to handle linearGradient with gradientUnits=%1").arg(element.attribute("gradientUnits"))); } } else if (nodeName.compare("radialGradient") == 0) { if (element.attribute("gradientUnits").compare("userSpaceOnUse") == 0) { normalizeAttribute(element, "cx", sNewWidth, vbWidth); normalizeAttribute(element, "cy", sNewWidth, vbWidth); normalizeAttribute(element, "fx", sNewWidth, vbWidth); normalizeAttribute(element, "fy", sNewWidth, vbWidth); normalizeAttribute(element, "r", sNewWidth, vbWidth); } else { //DebugDialog::debug(QString("unable to handle radialGradient with gradientUnits=%1").arg(element.attribute("gradientUnits"))); } } else { doChildren = true; } if (doChildren) { QDomElement childElement = element.firstChildElement(); while (!childElement.isNull()) { normalizeChild(childElement, sNewWidth, sNewHeight, vbWidth, vbHeight, blackOnly); childElement = childElement.nextSiblingElement(); } } } bool SvgFileSplitter::normalizeAttribute(QDomElement & element, const char * attributeName, double num, double denom) { QString attributeValue = element.attribute(attributeName); if (attributeValue.isEmpty()) return true; bool ok; double n = attributeValue.toDouble(&ok) * num / denom; if (!ok) { QString string; QTextStream stream(&string); element.save(stream, 0); //DebugDialog::debug("bad attribute " + string); } element.setAttribute(attributeName, QString::number(n)); return ok; } QString SvgFileSplitter::shift(double x, double y, const QString & elementID, bool shiftTransforms) { QDomElement root = m_domDocument.documentElement(); QDomElement mainElement = TextUtils::findElementWithAttribute(root, "id", elementID); if (mainElement.isNull()) return ""; QDomElement childElement = mainElement.firstChildElement(); while (!childElement.isNull()) { shiftChild(childElement, x, y, shiftTransforms); childElement = childElement.nextSiblingElement(); } QDomDocument document; QDomNode node = document.importNode(mainElement, true); document.appendChild(node); return document.toString(); } bool SvgFileSplitter::shiftTranslation(QDomElement & element, double x, double y) { QString attr = element.attribute("transform"); if (attr.isEmpty()) return false; QMatrix m0 = TextUtils::elementToMatrix(element); bool ok1, ok2, ok3; double _x = element.attribute("_x").toDouble(&ok1); double _y = element.attribute("_y").toDouble(&ok2); double _r = element.attribute("_r").toDouble(&ok3); if (ok1 && ok2 && ok3) { QMatrix mx = QMatrix().translate(-_x - x, -_y - y) * QMatrix().rotate(_r) * QMatrix().translate(_x + x, _y + y); TextUtils::setSVGTransform(element, mx); element.removeAttribute("_x"); element.removeAttribute("_y"); element.removeAttribute("_r"); return false; } // calculate the original cx and cy and retranslate (there must be an easier way) // and this doesn't seem to work... double sinTheta = m0.m21(); double cosTheta = m0.m11(); double cosThetaMinusOne = cosTheta - 1; double cx = (m0.dx() + (sinTheta * m0.dy() / cosThetaMinusOne)) / (cosThetaMinusOne + (sinTheta * sinTheta / cosThetaMinusOne)); double cy = (m0.dy() - (sinTheta * cx)) / cosThetaMinusOne; cx += x; cy += y; QMatrix m1(m0.m11(), m0.m12(), m0.m21(), m0.m22(), 0, 0); QMatrix mx = QMatrix().translate(-cx, -cy) * m1 * QMatrix().translate(cx, cy); TextUtils::setSVGTransform(element, mx); return false; } void SvgFileSplitter::shiftChild(QDomElement & element, double x, double y, bool shiftTransforms) { if (shiftTransforms) { shiftTranslation(element, x, y); } QString nodeName = element.nodeName(); if (nodeName.compare("circle") == 0 || nodeName.compare("ellipse") == 0) { shiftAttribute(element, "cx", x); shiftAttribute(element, "cy", y); } else if (nodeName.compare("line") == 0) { shiftAttribute(element, "x1", x); shiftAttribute(element, "y1", y); shiftAttribute(element, "x2", x); shiftAttribute(element, "y2", y); } else if (nodeName.compare("rect") == 0) { shiftAttribute(element, "x", x); shiftAttribute(element, "y", y); } else if (nodeName.compare("text") == 0) { shiftAttribute(element, "x", x); shiftAttribute(element, "y", y); } else if (nodeName.compare("polygon") == 0 || nodeName.compare("polyline") == 0) { QString data = element.attribute("points"); if (!data.isEmpty()) { const char * slot = SLOT(shiftCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.x = x; pathUserData.y = y; if (parsePath(data, slot, pathUserData, this, false)) { pathUserData.string.remove(0, 1); // get rid of the "M" element.setAttribute("points", pathUserData.string); } } } else if (nodeName.compare("path") == 0) { QString data = element.attribute("d").trimmed(); if (!data.isEmpty()) { const char * slot = SLOT(shiftCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.pathStarting = true; pathUserData.x = x; pathUserData.y = y; if (parsePath(data, slot, pathUserData, this, true)) { element.setAttribute("d", pathUserData.string); } } } else { QDomElement childElement = element.firstChildElement(); while (!childElement.isNull()) { shiftChild(childElement, x, y, shiftTransforms); childElement = childElement.nextSiblingElement(); } } } void SvgFileSplitter::normalizeCommandSlot(QChar command, bool relative, QList & args, void * userData) { Q_UNUSED(relative); // just normalizing here, so relative is not used PathUserData * pathUserData = (PathUserData *) userData; double d; pathUserData->string.append(command); switch(command.toLatin1()) { case 'v': case 'V': //DebugDialog::debug("'v' and 'V' are now removed by preprocessing; shouldn't be here"); /* for (int i = 0; i < args.count(); i++) { d = args[i] * pathUserData->sNewHeight / pathUserData->vbHeight; pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } */ break; case 'h': case 'H': //DebugDialog::debug("'h' and 'H' are now removed by preprocessing; shouldn't be here"); /* for (int i = 0; i < args.count(); i++) { d = args[i] * pathUserData->sNewWidth / pathUserData->vbWidth; pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } */ break; case 'a': case 'A': for (int i = 0; i < args.count(); i++) { switch (i % 7) { case 0: case 5: d = args[i] * pathUserData->sNewWidth / pathUserData->vbWidth; break; case 1: case 6: d = args[i] * pathUserData->sNewHeight / pathUserData->vbHeight; break; default: d = args[i]; break; } pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } break; case SVGPathLexer::FakeClosePathChar: break; default: for (int i = 0; i < args.count(); i++) { if (i % 2 == 0) { d = args[i] * pathUserData->sNewWidth / pathUserData->vbWidth; } else { d = args[i] * pathUserData->sNewHeight / pathUserData->vbHeight; } pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } break; } } void SvgFileSplitter::painterPathCommandSlot(QChar command, bool relative, QList & args, void * userData) { Q_UNUSED(relative); // just normalizing here, so relative is not used Q_UNUSED(command) // note: painterPathCommandSlot is only partially implemented PathUserData * pathUserData = (PathUserData *) userData; double dx, dy; for (int i = 0; i < args.count(); i += 2) { dx = args[i]; dy = args[i + 1]; if (i == 0) { pathUserData->painterPath->moveTo(dx, dy); } else { pathUserData->painterPath->lineTo(dx, dy); } } pathUserData->painterPath->closeSubpath(); } void SvgFileSplitter::shiftCommandSlot(QChar command, bool relative, QList & args, void * userData) { Q_UNUSED(relative); // just normalizing here, so relative is not used PathUserData * pathUserData = (PathUserData *) userData; double d; pathUserData->string.append(command); switch(command.toLatin1()) { case 'v': case 'V': //DebugDialog::debug("'v' and 'V' are now removed by preprocessing; shouldn't be here"); /* d = args[0]; if (!relative) { d += pathUserData->y; } pathUserData->string.append(QString::number(d)); */ break; case 'h': case 'H': //DebugDialog::debug("'h' and 'H' are now removed by preprocessing; shouldn't be here"); /* d = args[0]; if (!relative) { d += pathUserData->x; } pathUserData->string.append(QString::number(d)); */ break; case 'z': case 'Z': pathUserData->pathStarting = true; break; case SVGPathLexer::FakeClosePathChar: pathUserData->pathStarting = true; break; case 'a': case 'A': for (int i = 0; i < args.count(); i++) { d = args[i]; if (i % 7 == 5) { if (!relative) { d += pathUserData->x; } } else if (i % 7 == 6) { if (!relative) { d += pathUserData->y; } } pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } break; case 'm': case'M': standardArgs(relative, pathUserData->pathStarting, args, pathUserData); pathUserData->pathStarting = false; break; default: standardArgs(relative, false, args, pathUserData); break; } } void SvgFileSplitter::standardArgs(bool relative, bool starting, QList & args, PathUserData * pathUserData) { for (int i = 0; i < args.count(); i++) { double d = args[i]; if (i % 2 == 0) { if (!relative || (starting && i == 0)) { d += pathUserData->x; } } else { if (!relative || (starting && i == 1)) { d += pathUserData->y; } } pathUserData->string.append(QString::number(d)); if (i < args.count() - 1) { pathUserData->string.append(','); } } } QVector SvgFileSplitter::simpleParsePath(const QString & data) { static QVector emptyStack; QString dataCopy(data); if (!dataCopy.startsWith('M', Qt::CaseInsensitive)) { dataCopy.prepend('M'); } while (dataCopy.at(dataCopy.length() - 1).isSpace()) { dataCopy.remove(dataCopy.length() - 1, 1); } QChar last = dataCopy.at(dataCopy.length() - 1); if (last != 'z' && last != 'Z' && last != SVGPathLexer::FakeClosePathChar) { dataCopy.append(SVGPathLexer::FakeClosePathChar); } SVGPathLexer lexer(dataCopy); SVGPathParser parser; bool result = parser.parse(&lexer); if (!result) { //DebugDialog::debug(QString("svg path parse failed %1").arg(dataCopy)); return emptyStack; } return parser.symStack(); } bool SvgFileSplitter::parsePath(const QString & dataString, const char * slot, PathUserData & pathUserData, QObject * slotTarget, bool convertHV) { QVector symStack = simpleParsePath(dataString); if (convertHV && (dataString.contains("h", Qt::CaseInsensitive) || dataString.contains("v", Qt::CaseInsensitive))) { SVGPathRunner svgPathRunner; HVConvertData data; data.x = data.y = data.subX = data.subY = 0; data.path = ""; connect(&svgPathRunner, SIGNAL(commandSignal(QChar, bool, QList &, void *)), this, SLOT(convertHVSlot(QChar, bool, QList &, void *)), Qt::DirectConnection); svgPathRunner.runPath(symStack, &data); return parsePath(data.path, slot, pathUserData, slotTarget, false); } SVGPathRunner svgPathRunner; connect(&svgPathRunner, SIGNAL(commandSignal(QChar, bool, QList &, void *)), slotTarget, slot, Qt::DirectConnection); return svgPathRunner.runPath(symStack, &pathUserData); } void SvgFileSplitter::convertHVSlot(QChar command, bool relative, QList & args, void * userData) { Q_UNUSED(relative); HVConvertData * data = (HVConvertData *) userData; double x, y; switch(command.toLatin1()) { case 'M': data->path.append(command); for (int i = 0; i < args.count(); i += 2) { data->x = data->subX = args[i]; data->y = data->subY = args[i + 1]; appendPair(data->path, args[i], args[i + 1]); } data->path.chop(1); break; case 'm': data->path.append(command); x = data->x; y = data->y; for (int i = 0; i < args.count(); i += 2) { data->subX = data->x = (x + args[i]); data->subY = data->y = (y + args[i + 1]); appendPair(data->path, args[i], args[i + 1]); } data->path.chop(1); break; case 'L': case 'T': data->path.append(command); for (int i = 0; i < args.count(); i += 2) { data->x = args[i]; data->y = args[i + 1]; appendPair(data->path, args[i], args[i + 1]); } data->path.chop(1); break; case 'l': case 't': data->path.append(command); x = data->x; y = data->y; for (int i = 0; i < args.count(); i += 2) { data->x = x + args[i]; data->y = y + args[i + 1]; appendPair(data->path, args[i], args[i + 1]); } data->path.chop(1); break; case 'C': data->path.append(command); for (int i = 0; i < args.count(); i += 6) { data->x = args[i + 4]; data->y = args[i + 5]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); appendPair(data->path, args[i + 4], args[i + 5]); } data->path.chop(1); break; case 'c': data->path.append(command); x = data->x; y = data->y; for (int i = 0; i < args.count(); i += 6) { data->x = x + args[i + 4]; data->y = y + args[i + 5]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); appendPair(data->path, args[i + 4], args[i + 5]); } data->path.chop(1); break; case 'S': case 'Q': data->path.append(command); for (int i = 0; i < args.count(); i += 4) { data->x = args[i + 2]; data->y = args[i + 3]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); } data->path.chop(1); break; case 's': case 'q': data->path.append(command); x = data->x; y = data->y; for (int i = 0; i < args.count(); i += 4) { data->x = x + args[i + 2]; data->y = y + args[i + 3]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); } data->path.chop(1); break; case 'Z': case 'z': data->path.append(command); data->x = data->subX; data->y = data->subY; break; case SVGPathLexer::FakeClosePathChar: data->path.append(command); break; case 'A': data->path.append(command); for (int i = 0; i < args.count(); i += 7) { data->x = args[i + 5]; data->y = args[i + 6]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); appendPair(data->path, args[i + 4], args[i + 5]); data->path.append(QString::number(args[i + 6])); data->path.append(','); } data->path.chop(1); break; case 'a': data->path.append(command); x = data->x; y = data->y; for (int i = 0; i < args.count(); i += 7) { data->x = x + args[i + 5]; data->y = y + args[i + 6]; appendPair(data->path, args[i], args[i + 1]); appendPair(data->path, args[i + 2], args[i + 3]); appendPair(data->path, args[i + 4], args[i + 5]); data->path.append(QString::number(args[i + 6])); data->path.append(','); } data->path.chop(1); break; case 'v': data->path.append('l'); y = data->y; for (int i = 0; i < args.count(); i++) { data->y = y + args[i]; appendPair(data->path, 0, args[i]); } data->path.chop(1); break; case 'h': data->path.append('l'); x = data->x; for (int i = 0; i < args.count(); i++) { data->x = x + args[i]; appendPair(data->path, args[i], 0); } data->path.chop(1); break; case 'H': data->path.append('L'); for (int i = 0; i < args.count(); i++) { data->x = args[i]; appendPair(data->path, args[i], data->y); } data->path.chop(1); break; case 'V': data->path.append('L'); for (int i = 0; i < args.count(); i++) { data->y = args[i]; appendPair(data->path, data->x, args[i]); } data->path.chop(1); break; default: //DebugDialog::debug(QString("unknown path command %1").arg(command)); data->path.append(command); for (int i = 0; i < args.count(); i++) { data->path.append(QString::number(args[i])); data->path.append(','); } data->path.chop(1); break; } } void SvgFileSplitter::setStrokeOrFill(QDomElement & element, bool blackOnly, const QString & color, bool force) { if (!blackOnly) return; // if stroke attribute is not empty make it black // if fill attribute is not empty and not "none" make it black QString stroke = element.attribute("stroke"); if (!stroke.isEmpty() || force) { if (stroke.compare("none") != 0) { element.setAttribute("stroke", color); } } QString fill = element.attribute("fill"); if (!fill.isEmpty()) { if (fill.compare("none") != 0) { element.setAttribute("fill", color); } } } void SvgFileSplitter::fixStyleAttributeRecurse(QDomElement & element) { TextUtils::fixStyleAttribute(element); QDomElement childElement = element.firstChildElement(); while (!childElement.isNull()) { fixStyleAttributeRecurse(childElement); childElement = childElement.nextSiblingElement(); } } void SvgFileSplitter::fixColorRecurse(QDomElement & element, const QString & newColor, const QStringList & exceptions) { TextUtils::fixStyleAttribute(element); bool gotException = false; QString s = element.attribute("stroke"); QString f = element.attribute("fill"); QString id = element.attribute("id"); foreach (QString e, exceptions) { if (s.isEmpty()) { if (f.isEmpty()) { } else { if (exceptions.contains(f)) { gotException = true; break; } } } else { if (f.isEmpty()) { if (exceptions.contains(s)) { gotException = true; break; } } else { if (exceptions.contains(s) && exceptions.contains(f)) { gotException = true; break; } } } } if (!gotException) { setStrokeOrFill(element, true, newColor, !id.isEmpty()); } QDomElement childElement = element.firstChildElement(); while (!childElement.isNull()) { fixColorRecurse(childElement, newColor, exceptions); childElement = childElement.nextSiblingElement(); } } bool SvgFileSplitter::getSvgSizeAttributes(const QString & svg, QString & width, QString & height, QString & viewBox) { QXmlStreamReader xml(svg); xml.setNamespaceProcessing(false); while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: if (xml.name().toString().compare("svg") == 0) { width = xml.attributes().value("width").toString(); height = xml.attributes().value("height").toString(); viewBox = xml.attributes().value("viewBox").toString(); return true; } default: break; } } return false; } bool SvgFileSplitter::changeStrokeWidth(const QString & svg, double delta, bool absolute, bool changeOpacity, QByteArray & byteArray) { QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, true, &errorStr, &errorLine, &errorColumn)) { return false; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { return false; } if (root.tagName() != "svg") { return false; } changeStrokeWidth(root, delta, absolute, changeOpacity); byteArray = domDocument.toByteArray(); return true; } void SvgFileSplitter::changeStrokeWidth(QDomElement & element, double delta, bool absolute, bool changeOpacity) { bool ok; double sw = element.attribute("stroke-width").toDouble(&ok); if (ok) { element.setAttribute("stroke-width", QString::number((absolute) ? delta : sw + delta)); } if (changeOpacity) { QString fillo = element.attribute("fill-opacity"); if (!fillo.isEmpty()) { element.setAttribute("fill-opacity", "1.0"); } QString sillo = element.attribute("stroke-opacity"); if (!sillo.isEmpty()) { element.setAttribute("stroke-opacity", "1.0"); } } QDomElement child = element.firstChildElement(); while (!child.isNull()) { changeStrokeWidth(child, delta, absolute, changeOpacity); child = child.nextSiblingElement(); } } void SvgFileSplitter::forceStrokeWidth(QDomElement & element, double delta, const QString & stroke, bool recurse, bool fill) { bool ok; double sw = element.attribute("stroke-width").toDouble(&ok); if (!ok) sw = 0; element.setAttribute("stroke-width", QString::number(qMax(0, sw + delta))); element.setAttribute("stroke", stroke); if (fill) element.setAttribute("fill", stroke); if (recurse) { QDomElement child = element.firstChildElement(); while (!child.isNull()) { forceStrokeWidth(child, delta, stroke, recurse, fill); child = child.nextSiblingElement(); } } } bool SvgFileSplitter::changeColors(const QString & svg, QString & toColor, QStringList & exceptions, QByteArray & byteArray) { QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, true, &errorStr, &errorLine, &errorColumn)) { return false; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { return false; } if (root.tagName() != "svg") { return false; } changeColors(root, toColor, exceptions); byteArray = domDocument.toByteArray(); return true; } void SvgFileSplitter::changeColors(QDomElement & element, QString & toColor, QStringList & exceptions) { QString c = element.attribute("stroke"); if (!exceptions.contains(c)) { element.setAttribute("stroke", toColor); } c = element.attribute("fill"); if (!exceptions.contains(c)) { element.setAttribute("fill", toColor); } QString fillo = element.attribute("fill-opacity"); if (!fillo.isEmpty()) { element.setAttribute("fill-opacity", "1.0"); } QString sillo = element.attribute("stroke-opacity"); if (!sillo.isEmpty()) { element.setAttribute("stroke-opacity", "1.0"); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { changeColors(child, toColor, exceptions); child = child.nextSiblingElement(); } } bool SvgFileSplitter::shiftAttribute(QDomElement & element, const char * attributeName, double d) { double n = element.attribute(attributeName).toDouble() + d; element.setAttribute(attributeName, QString::number(n)); return true; } bool SvgFileSplitter::load(const QString string) { QString errorStr; int errorLine; int errorColumn; return m_domDocument.setContent(string, true, &errorStr, &errorLine, &errorColumn); } bool SvgFileSplitter::load(const QString * filename) { QFile file(*filename); return load(&file); } bool SvgFileSplitter::load(QFile * file) { QString errorStr; int errorLine; int errorColumn; return m_domDocument.setContent(file, true, &errorStr, &errorLine, &errorColumn); } QString SvgFileSplitter::toString() { return TextUtils::removeXMLEntities(m_domDocument.toString()); } void SvgFileSplitter::gWrap(const QHash & attributes) { TextUtils::gWrap(m_domDocument, attributes); } void SvgFileSplitter::gReplace(const QString & id) { QDomElement element = TextUtils::findElementWithAttribute(m_domDocument.documentElement(), "id", id); if (element.isNull()) return; element.setTagName("g"); } QByteArray SvgFileSplitter::hideText(const QString & filename) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; QFile file(filename); if (!doc.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { return QByteArray(); } QDomElement root = doc.documentElement(); hideTextAux(root, false); return TextUtils::removeXMLEntities(doc.toString()).toUtf8(); } QByteArray SvgFileSplitter::hideText2(const QByteArray & svg) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { return QByteArray(); } QDomElement root = doc.documentElement(); hideTextAux(root, false); return TextUtils::removeXMLEntities(doc.toString()).toUtf8(); } QString SvgFileSplitter::hideText3(const QString & svg) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { return ""; } QDomElement root = doc.documentElement(); hideTextAux(root, false); return TextUtils::removeXMLEntities(doc.toString()); } void SvgFileSplitter::hideTextAux(QDomElement & parent, bool hideChildren) { if (hideChildren || parent.tagName() == "text") { parent.setTagName("g"); hideChildren = true; } QDomElement child = parent.firstChildElement(); while (!child.isNull()) { hideTextAux(child, hideChildren); child = child.nextSiblingElement(); } } QByteArray SvgFileSplitter::showText(const QString & filename, bool & hasText) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; QFile file(filename); if (!doc.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { return QByteArray(); } QDomElement root = doc.documentElement(); showTextAux(root, hasText, true); if (!hasText) { return QByteArray(); } return TextUtils::removeXMLEntities(doc.toString()).toUtf8(); } QByteArray SvgFileSplitter::showText2(const QByteArray & svg, bool & hasText) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { return QByteArray(); } QDomElement root = doc.documentElement(); showTextAux(root, hasText, true); if (!hasText) { return QByteArray(); } return TextUtils::removeXMLEntities(doc.toString()).toUtf8(); } QString SvgFileSplitter::showText3(const QString & svg, bool & hasText) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) { return ""; } QDomElement root = doc.documentElement(); showTextAux(root, hasText, true); if (!hasText) { return ""; } return TextUtils::removeXMLEntities(doc.toString()); } void SvgFileSplitter::showTextAux(QDomElement & parent, bool & hasText, bool root) { if (parent.tagName() == "text") { hasText = true; return; } if (!root) { parent.setTagName("g"); } QDomElement child = parent.firstChildElement(); while (!child.isNull()) { showTextAux(child, hasText, false); child = child.nextSiblingElement(); } } fritzing-app-0.9.2b/src/svg/svgfilesplitter.h000066400000000000000000000123311250202676700212720ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6980 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 01:45:43 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef SVGFILESPLITTER_H_ #define SVGFILESPLITTER_H_ #include #include #include #include #include #include #include #include struct PathUserData { QString string; QMatrix transform; double sNewWidth; double sNewHeight; double vbWidth; double vbHeight; double x; double y; bool pathStarting; QPainterPath * painterPath; }; class SvgFileSplitter : public QObject { Q_OBJECT public: SvgFileSplitter(); bool split(const QString & filename, const QString & elementID); bool splitString(QString & contents, const QString & elementID); const QByteArray & byteArray(); const QDomDocument & domDocument(); bool normalize(double dpi, const QString & elementID, bool blackOnly, double & factor); QString shift(double x, double y, const QString & elementID, bool shiftTransforms); QString elementString(const QString & elementID); virtual bool parsePath(const QString & data, const char * slot, PathUserData &, QObject * slotTarget, bool convertHV); QVector simpleParsePath(const QString & data); QPainterPath painterPath(double dpi, const QString & elementID); // note: only partially implemented void shiftChild(QDomElement & element, double x, double y, bool shiftTransforms); bool load(const QString * filename); bool load(QFile *); bool load(const QString string); QString toString(); void gWrap(const QHash & attributes); void gReplace(const QString & id); public: static bool getSvgSizeAttributes(const QString & svg, QString & width, QString & height, QString & viewBox); static bool changeStrokeWidth(const QString & svg, double delta, bool absolute, bool changeOpacity, QByteArray &); static void changeStrokeWidth(QDomElement & element, double delta, bool absolute, bool changeOpacity); static void forceStrokeWidth(QDomElement & element, double delta, const QString & stroke, bool recurse, bool fill); static bool changeColors(const QString & svg, QString & toColor, QStringList & exceptions, QByteArray &); static void changeColors(QDomElement & element, QString & toColor, QStringList & exceptions); static void fixStyleAttributeRecurse(QDomElement & element); static void fixColorRecurse(QDomElement & element, const QString & newColor, const QStringList & exceptions); static QByteArray hideText(const QString & filename); static QByteArray showText(const QString & filename, bool & hasText); static QByteArray hideText2(const QByteArray & svg); static QByteArray showText2(const QByteArray & svg, bool & hasText); static QString hideText3(const QString & svg); static QString showText3(const QString & svg, bool & hasText); protected: void normalizeChild(QDomElement & childElement, double sNewWidth, double sNewHeight, double vbWidth, double vbHeight, bool blackOnly); bool normalizeAttribute(QDomElement & element, const char * attributeName, double num, double denom); void painterPathChild(QDomElement & element, QPainterPath & ppath); // note: only partially implemented void normalizeTranslation(QDomElement & element, double sNewWidth, double sNewHeight, double vbWidth, double vbHeight); bool shiftTranslation(QDomElement & element, double x, double y); void standardArgs(bool relative, bool starting, QList & args, PathUserData * pathUserData); protected: static bool shiftAttribute(QDomElement & element, const char * attributeName, double d); static void setStrokeOrFill(QDomElement & element, bool doIt, const QString & color, bool force); static void hideTextAux(QDomElement & parent, bool hideChildren); static void showTextAux(QDomElement & parent, bool & hasText, bool root); protected slots: void normalizeCommandSlot(QChar command, bool relative, QList & args, void * userData); void shiftCommandSlot(QChar command, bool relative, QList & args, void * userData); virtual void rotateCommandSlot(QChar, bool, QList &, void *){} void painterPathCommandSlot(QChar command, bool relative, QList & args, void * userData); void convertHVSlot(QChar command, bool relative, QList & args, void * userData); protected: QByteArray m_byteArray; QDomDocument m_domDocument; }; #endif fritzing-app-0.9.2b/src/svg/svgflattener.cpp000066400000000000000000000316461250202676700211150ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6435 $: $Author: cohen@irascible.com $: $Date: 2012-09-16 23:31:00 +0200 (So, 16. Sep 2012) $ ********************************************************************/ #include "svgflattener.h" #include "svgpathlexer.h" #include "../utils/graphicsutils.h" #include "../utils/textutils.h" #include "../debugdialog.h" #include #include #include #include SvgFlattener::SvgFlattener() : SvgFileSplitter() { } void SvgFlattener::flattenChildren(QDomElement &element){ // recurse the children QDomNodeList childList = element.childNodes(); for(int i = 0; i < childList.length(); i++){ QDomElement child = childList.item(i).toElement(); flattenChildren(child); } //do translate if(hasTranslate(element)){ QList params = TextUtils::getTransformFloats(element); if (params.size() == 2) { shiftChild(element, params.at(0), params.at(1), false); //DebugDialog::debug(QString("translating %1 %2").arg(params.at(0)).arg(params.at(1))); } else if (params.size() == 6) { shiftChild(element, params.at(4), params.at(5), false); } else if (params.size() == 1) { shiftChild(element, params.at(0), 0, false); //DebugDialog::debug(QString("translating %1").arg(params.at(0))); } else { DebugDialog::debug("weird transform found"); } } else if(hasOtherTransform(element)) { QMatrix transform = TextUtils::transformStringToMatrix(element.attribute("transform")); //DebugDialog::debug(QString("rotating %1 %2 %3 %4 %5 %6").arg(params.at(0)).arg(params.at(1)).arg(params.at(2)).arg(params.at(3)).arg(params.at(4)).arg(params.at(5))); unRotateChild(element, transform); } // remove transform element.removeAttribute("transform"); } void SvgFlattener::unRotateChild(QDomElement & element, QMatrix transform) { // TODO: missing ellipse element if(!element.hasChildNodes()) { QString sw = element.attribute("stroke-width"); if (!sw.isEmpty()) { bool ok; double strokeWidth = sw.toDouble(&ok); if (ok) { QLineF line(0, 0, strokeWidth, 0); QLineF newLine = transform.map(line); element.setAttribute("stroke-width", QString::number(newLine.length())); } } // I'm a leaf node. QString tag = element.nodeName().toLower(); if(tag == "path"){ QString data = element.attribute("d").trimmed(); if (!data.isEmpty()) { const char * slot = SLOT(rotateCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.transform = transform; if (parsePath(data, slot, pathUserData, this, true)) { element.setAttribute("d", pathUserData.string); } } } else if ((tag == "polygon") || (tag == "polyline")) { QString data = element.attribute("points"); if (!data.isEmpty()) { const char * slot = SLOT(rotateCommandSlot(QChar, bool, QList &, void *)); PathUserData pathUserData; pathUserData.transform = transform; if (parsePath(data, slot, pathUserData, this, false)) { pathUserData.string.remove(0, 1); // get rid of the "M" element.setAttribute("points", pathUserData.string); } } } else if(tag == "rect"){ float x = element.attribute("x").toFloat(); float y = element.attribute("y").toFloat(); float width = element.attribute("width").toFloat(); float height = element.attribute("height").toFloat(); QRectF r(x, y, width, height); QPolygonF poly = transform.map(r); if (GraphicsUtils::isRect(poly)) { QRectF rect = GraphicsUtils::getRect(poly); element.setAttribute("x", QString::number(rect.left())); element.setAttribute("y", QString::number(rect.top())); element.setAttribute("width", QString::number(rect.width())); element.setAttribute("height", QString::number(rect.height())); } else { element.setTagName("polygon"); QString pts; for (int i = 1; i < poly.count(); i++) { QPointF p = poly.at(i); pts += QString("%1,%2 ").arg(p.x()).arg(p.y()); } pts.chop(1); element.setAttribute("points", pts); } } else if(tag == "circle"){ float cx = element.attribute("cx").toFloat(); float cy = element.attribute("cy").toFloat(); float r = element.attribute("r").toFloat(); QPointF point = transform.map(QPointF(cx,cy)); element.setAttribute("cx", QString::number(point.x())); element.setAttribute("cy", QString::number(point.y())); QLineF line(0, 0, r, 0); QLineF newLine = transform.map(line); element.setAttribute("r", QString::number(newLine.length())); } else if(tag == "line") { float x1 = element.attribute("x1").toFloat(); float y1 = element.attribute("y1").toFloat(); QPointF p1 = transform.map(QPointF(x1,y1)); element.setAttribute("x1", QString::number(p1.x())); element.setAttribute("y1", QString::number(p1.y())); float x2 = element.attribute("x2").toFloat(); float y2 = element.attribute("y2").toFloat(); QPointF p2 = transform.map(QPointF(x2,y2)); element.setAttribute("x2", QString::number(p2.x())); element.setAttribute("y2", QString::number(p2.y())); } else if (tag == "g") { // no op } else if (tag.isEmpty()) { } else { DebugDialog::debug("Warning! Can't rotate element: " + tag); } return; } // recurse the children QDomNodeList childList = element.childNodes(); for(int i = 0; i < childList.length(); i++){ QDomElement child = childList.item(i).toElement(); unRotateChild(child, transform); } } bool SvgFlattener::hasTranslate(QDomElement & element) { QString transform = element.attribute("transform"); if (transform.isEmpty()) return false; if (transform.startsWith("translate")) return true; if (transform.startsWith("matrix")) { QMatrix matrix = TextUtils::transformStringToMatrix(transform); matrix.translate(-matrix.dx(), -matrix.dy()); if (matrix.isIdentity()) return true; } return false; } bool SvgFlattener::hasOtherTransform(QDomElement & element) { QString transform = element.attribute("transform"); if (transform.isEmpty()) return false; // NOTE: doesn't handle multiple transform attributes... return (!transform.contains("translate")); } void SvgFlattener::rotateCommandSlot(QChar command, bool relative, QList & args, void * userData) { Q_UNUSED(relative); // just normalizing here, so relative is not used PathUserData * pathUserData = (PathUserData *) userData; pathUserData->string.append(command); double x; double y; QPointF point; for (int i = 0; i < args.count(); ) { switch(command.toLatin1()) { case 'v': case 'V': DebugDialog::debug("'v' and 'V' are now removed by preprocessing; shouldn't be here"); /* y = args[i]; x = 0; // what is x, really? DebugDialog::debug("Warning! Can't rotate path with V"); */ i++; break; case 'h': case 'H': DebugDialog::debug("'h' and 'H' are now removed by preprocessing; shouldn't be here"); /* x = args[i]; y = 0; // what is y, really? DebugDialog::debug("Warning! Can't rotate path with H"); */ i++; break; case SVGPathLexer::FakeClosePathChar: break; case 'a': case 'A': // TODO: test whether this is correct for (int j = 0; j < 5; j++) { pathUserData->string.append(QString::number(args[j])); pathUserData->string.append(','); } x = args[5]; y = args[6]; i += 7; point = pathUserData->transform.map(QPointF(x,y)); pathUserData->string.append(QString::number(point.x())); pathUserData->string.append(','); pathUserData->string.append(QString::number(point.y())); if (i < args.count()) { pathUserData->string.append(','); } break; default: x = args[i]; y = args[i+1]; i += 2; point = pathUserData->transform.map(QPointF(x,y)); pathUserData->string.append(QString::number(point.x())); pathUserData->string.append(','); pathUserData->string.append(QString::number(point.y())); if (i < args.count()) { pathUserData->string.append(','); } } } } void SvgFlattener::replaceElementID(const QString & filename, const QString & svg, QDomDocument & domDocument, const QString & elementID, const QString & altElementID) { if (!loadDocIf(filename, svg, domDocument)) return; QDomElement root = domDocument.documentElement(); QDomElement element = TextUtils::findElementWithAttribute(root, "id", elementID); if (!element.isNull()) { element.setAttribute("id", altElementID); } } void SvgFlattener::flipSMDSvg(const QString & filename, const QString & svg, QDomDocument & flipDoc, const QString & elementID, const QString & altElementID, double printerScale, Qt::Orientations orientation) { QDomDocument domDocument; if (!loadDocIf(filename, svg, domDocument)) return; QDomElement root = domDocument.documentElement(); QDomElement element = TextUtils::findElementWithAttribute(root, "id", elementID); if (!element.isNull()) { QDomElement altElement = TextUtils::findElementWithAttribute(root, "id", altElementID); QString svg = flipSMDElement(domDocument, element, elementID, altElement, altElementID, printerScale, orientation); if (svg.length() > 0) { flipDoc.setContent(svg); } } } QString SvgFlattener::flipSMDElement(QDomDocument & domDocument, QDomElement & element, const QString & att, QDomElement altElement, const QString & altAtt, double printerScale, Qt::Orientations orientation) { Q_UNUSED(printerScale); Q_UNUSED(att); QMatrix m; //QRectF bounds = renderer.boundsOnElement(att); QRectF bounds; // want part bounds, not layer bounds double w, h; TextUtils::ensureViewBox(domDocument, 1, bounds, false, w, h, false); m.translate(bounds.center().x(), bounds.center().y()); QMatrix mMinus = m.inverted(); QMatrix cm = mMinus * ((orientation & Qt::Vertical) ? QMatrix().scale(-1, 1) : QMatrix().scale(1, -1)) * m; QDomElement newElement = element.cloneNode(true).toElement(); #ifndef QT_NODEBUG QString string; QTextStream textStream(&string); newElement.save(textStream, 1); #endif newElement.removeAttribute("id"); QDomElement pElement = domDocument.createElement("g"); pElement.setAttribute("id", altAtt); pElement.setAttribute("flipped", true); QDomElement mElement = domDocument.createElement("g"); TextUtils::setSVGTransform(mElement, cm); pElement.appendChild(mElement); QDomElement tElementChild = domDocument.createElement("g"); QDomElement tElementParent = tElementChild; QDomElement parent = element.parentNode().toElement(); while (!parent.isNull()) { QString transform = parent.attribute("transform"); if (!transform.isEmpty()) { QDomElement t = domDocument.createElement("g"); t.setAttribute("transform", transform); t.appendChild(tElementParent); tElementParent = t; } parent = parent.parentNode().toElement(); } mElement.appendChild(tElementParent); tElementChild.appendChild(newElement); if (!altElement.isNull()) { tElementChild.appendChild(altElement); altElement.removeAttribute("id"); } domDocument.documentElement().appendChild(pElement); return domDocument.toString(); } bool SvgFlattener::loadDocIf(const QString & filename, const QString & svg, QDomDocument & domDocument) { if (domDocument.isNull()) { QString errorStr; int errorLine; int errorColumn; bool result; if (filename.isEmpty()) { result = domDocument.setContent(svg, &errorStr, &errorLine, &errorColumn); } else { QFile file(filename); result = domDocument.setContent(&file, &errorStr, &errorLine, &errorColumn); } if (!result) { domDocument.clear(); // probably redundant return false; } } return true; } fritzing-app-0.9.2b/src/svg/svgflattener.h000066400000000000000000000043401250202676700205510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVGFLATTENER_H #define SVGFLATTENER_H #include "svgfilesplitter.h" #include #include class SvgFlattener : public SvgFileSplitter { public: SvgFlattener(); void flattenChildren(QDomElement & element); void unRotateChild(QDomElement & element,QMatrix transform); public: static void flipSMDSvg(const QString & filename, const QString & svg, QDomDocument & flipDoc, const QString & elementID, const QString & altElementID, double printerScale, Qt::Orientations); static void replaceElementID(const QString & filename, const QString & svg, QDomDocument & flipDoc, const QString & elementID, const QString & altElementID); protected: static QString flipSMDElement(QDomDocument & domDocument, QDomElement & element, const QString & att, QDomElement altAtt, const QString & altElementID, double printerScale, Qt::Orientations); static bool hasOtherTransform(QDomElement & element); static bool hasTranslate(QDomElement & element); static bool loadDocIf(const QString & filename, const QString & svg, QDomDocument & domDocument); protected slots: void rotateCommandSlot(QChar command, bool relative, QList & args, void * userData); }; #endif // SVGFLATTENER_H fritzing-app-0.9.2b/src/svg/svgpath.g000066400000000000000000000342711250202676700175260ustar00rootroot00000000000000%parser SVGPathGrammar %decl svgpathparser.h %impl svgpathparser.cpp %token EM %token ZEE %token EKS %token EL %token AITCH %token VEE %token CEE %token ESS %token KYU %token TEE %token AE %token COMMA %token NUMBER %token WHITESPACE %start path_data /: /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 3454 $: $Author: cohen@irascible.com $: $Date: 2009-09-11 19:39:43 +0200 (Fr, 11. Sep 2009) $ ********************************************************************/ #ifndef SVGPATHPARSER_H #define SVGPATHPARSER_H #include #include #include "svgpathgrammar_p.h" class SVGPathLexer; class SVGPathParser: public $table { public: SVGPathParser(); ~SVGPathParser(); bool parse(SVGPathLexer *lexer); QVector & symStack(); QString errorMessage() const; QVariant result() const; private: void reallocateStack(); int m_tos; QVector m_stateStack; QVector m_symStack; QString m_errorMessage; QVariant m_result; }; #endif // SVGPATHPARSER_H :/ /. /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 3454 $: $Author: cohen@irascible.com $: $Date: 2009-09-11 19:39:43 +0200 (Fr, 11. Sep 2009) $ ********************************************************************/ #include #include "svgpathparser.h" #include "svgpathlexer.h" SVGPathParser::SVGPathParser() { } SVGPathParser::~SVGPathParser() { } QVector & SVGPathParser::symStack() { return m_symStack; } void SVGPathParser::reallocateStack() { int size = m_stateStack.size(); if (size == 0) size = 128; else size <<= 1; m_stateStack.resize(size); } QString SVGPathParser::errorMessage() const { return m_errorMessage; } QVariant SVGPathParser::result() const { return m_result; } bool SVGPathParser::parse(SVGPathLexer *lexer) { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); m_tos = 0; m_stateStack[++m_tos] = INITIAL_STATE; while (true) { const int state = m_stateStack.at(m_tos); if (yytoken == -1 && - TERMINAL_COUNT != action_index [state]) yytoken = lexer->lex(); int act = t_action (state, yytoken); if (act == ACCEPT_STATE) return true; else if (act > 0) { if (++m_tos == m_stateStack.size()) reallocateStack(); m_stateStack[m_tos] = act; yytoken = -1; } else if (act < 0) { int r = - act - 1; m_tos -= rhs [r]; act = m_stateStack.at(m_tos++); switch (r) { ./ path_data ::= moveto_drawto_command_groups ; /. case $rule_number: { qDebug() << " got path_data "; } break; ./ moveto_drawto_command_groups ::= moveto_drawto_command_group | moveto_drawto_command_group moveto_drawto_command_groups ; /. case $rule_number: { //qDebug() << " got moveto_drawto_command_groups "; } break; ./ moveto_drawto_command_group ::= moveto drawto_commands | moveto; /. case $rule_number: { //qDebug() << " got moveto_drawto_command_group "; } break; ./ drawto_commands ::= drawto_command | drawto_command drawto_commands ; /. case $rule_number: { //qDebug() << " got drawto_commands "; } break; ./ drawto_command ::= fakeclosepath | closepath | lineto | horizontal_lineto | vertical_lineto | curveto | smooth_curveto | quadratic_bezier_curveto | smooth_quadratic_bezier_curveto | elliptical_arc; /. case $rule_number: { //qDebug() << " got drawto_command "; } break; ./ moveto ::= moveto_command moveto_argument_sequence ; /. case $rule_number: { qDebug() << " got moveto "; } break; ./ moveto_argument_sequence ::= coordinate_pair | coordinate_pair comma_wsp moveto_argument_sequence | coordinate_pair moveto_argument_sequence ; /. case $rule_number: { //qDebug() << " got moveto_argument_sequence "; } break; ./ lineto ::= lineto_command lineto_argument_sequence ; /. case $rule_number: { qDebug() << " got lineto "; } break; ./ lineto_argument_sequence ::= coordinate_pair | coordinate_pair comma_wsp lineto_argument_sequence | coordinate_pair lineto_argument_sequence ; /. case $rule_number: { //qDebug() << " got lineto_argument_sequence "; } break; ./ horizontal_lineto ::= horizontal_lineto_command horizontal_lineto_argument_sequence ; /. case $rule_number: { qDebug() << " got horizontal_lineto "; } break; ./ horizontal_lineto_argument_sequence ::= coordinate | coordinate comma_wsp horizontal_lineto_argument_sequence | coordinate horizontal_lineto_argument_sequence ; /. case $rule_number: { //qDebug() << " got horizontal_lineto_argument_sequence "; } break; ./ vertical_lineto ::= vertical_lineto_command vertical_lineto_argument_sequence ; /. case $rule_number: { qDebug() << " got vertical_lineto "; } break; ./ vertical_lineto_argument_sequence ::= coordinate | coordinate comma_wsp vertical_lineto_argument_sequence | coordinate vertical_lineto_argument_sequence ; /. case $rule_number: { //qDebug() << " got vertical_lineto_argument_sequence "; } break; ./ curveto ::= curveto_command curveto_argument_sequence ; /. case $rule_number: { qDebug() << " got curveto "; } break; ./ curveto_argument_sequence ::= curveto_argument | curveto_argument curveto_argument_sequence | curveto_argument comma_wsp curveto_argument_sequence ; /. case $rule_number: { //qDebug() << " got curveto_argument_sequence 3 "; } break; ./ curveto_argument ::= coordinate_pair comma_wsp coordinate_pair comma_wsp coordinate_pair | coordinate_pair comma_wsp coordinate_pair coordinate_pair | coordinate_pair coordinate_pair comma_wsp coordinate_pair | coordinate_pair coordinate_pair coordinate_pair ; /. case $rule_number: { //qDebug() << " got curveto_argument "; } break; ./ smooth_curveto ::= smooth_curveto_command smooth_curveto_argument_sequence ; /. case $rule_number: { qDebug() << " got smooth_curveto "; } break; ./ smooth_curveto_argument_sequence ::= smooth_curveto_argument | smooth_curveto_argument smooth_curveto_argument_sequence | smooth_curveto_argument comma_wsp smooth_curveto_argument_sequence ; /. case $rule_number: { //qDebug() << " got smooth_curveto_argument_sequence 3 "; } break; ./ smooth_curveto_argument ::= coordinate_pair coordinate_pair | coordinate_pair comma_wsp coordinate_pair ; /. case $rule_number: { //qDebug() << " got smooth_curveto_argument "; } break; ./ quadratic_bezier_curveto ::= quadratic_bezier_curveto_command quadratic_bezier_curveto_argument_sequence ; /. case $rule_number: { qDebug() << " got quadratic_bezier_curveto "; } break; ./ quadratic_bezier_curveto_argument_sequence ::= quadratic_bezier_curveto_argument | quadratic_bezier_curveto_argument quadratic_bezier_curveto_argument_sequence | quadratic_bezier_curveto_argument comma_wsp quadratic_bezier_curveto_argument_sequence ; /. case $rule_number: { //qDebug() << " got quadratic_bezier_curveto_argument "; } break; ./ quadratic_bezier_curveto_argument ::= coordinate_pair comma_wsp coordinate_pair | coordinate_pair coordinate_pair ; /. case $rule_number: { //qDebug() << " got quadratic_bezier_curveto_argument "; } break; ./ elliptical_arc ::= elliptical_arc_command elliptical_arc_argument_sequence ; /. case $rule_number: { qDebug() << " got elliptical_arc "; } break; ./ elliptical_arc_argument_sequence ::= elliptical_arc_argument | elliptical_arc_argument elliptical_arc_argument_sequence | elliptical_arc_argument comma_wsp elliptical_arc_argument_sequence ; /. case $rule_number: { //qDebug() << " got elliptical_arc_argument_sequence "; } break; ./ elliptical_arc_argument ::= nonnegative_number comma_wsp nonnegative_number comma_wsp number comma_wsp flag comma_wsp flag comma_wsp coordinate_pair ; /. case $rule_number: { //qDebug() << " got elliptical_arc_argument "; } break; ./ smooth_quadratic_bezier_curveto ::= smooth_quadratic_bezier_curveto_command smooth_quadratic_bezier_curveto_argument_sequence ; /. case $rule_number: { qDebug() << " got smooth_quadratic_bezier_curveto "; } break; ./ smooth_quadratic_bezier_curveto_argument_sequence ::= coordinate_pair | coordinate_pair comma_wsp smooth_quadratic_bezier_curveto_argument_sequence | coordinate_pair smooth_quadratic_bezier_curveto_argument_sequence ; /. case $rule_number: { //qDebug() << " got smooth_quadratic_bezier_curveto_argument_sequence 3 "; } break; ./ coordinate_pair ::= x_coordinate comma_wsp y_coordinate | x_coordinate y_coordinate ; /. case $rule_number: { //qDebug() << " got coordinate_pair "; } break; ./ x_coordinate ::= coordinate; /. case $rule_number: { //qDebug() << " got x coordinate "; } break; ./ y_coordinate ::= coordinate; /. case $rule_number: { //qDebug() << " got y coordinate "; } break; ./ comma_wsp ::= wspplus | COMMA ; /. case $rule_number: { //qDebug() << " got comma_wsp 3 "; } break; ./ wspplus ::= WHITESPACE ; /. case $rule_number: { //qDebug() << " got wspplus "; } break; ./ coordinate ::= NUMBER ; /. case $rule_number: { //qDebug() << " got coordinate "; m_symStack.append(lexer->currentNumber()); } break; ./ nonnegative_number ::= NUMBER ; /. case $rule_number: { //qDebug() << " got nonnegative_number "; //not presently checking this is non-negative m_symStack.append(lexer->currentNumber()); } break; ./ number ::= NUMBER ; /. case $rule_number: { //qDebug() << " got number "; m_symStack.append(lexer->currentNumber()); } break; ./ flag ::= NUMBER ; /. case $rule_number: { //qDebug() << " got flag "; //not presently checking this is only 0 or 1 m_symStack.append(lexer->currentNumber()); } break; ./ moveto_command ::= EM ; /. case $rule_number: { //qDebug() << " got moveto command "; m_symStack.append(lexer->currentCommand()); } break; ./ lineto_command ::= EL ; /. case $rule_number: { //qDebug() << " got lineto command "; m_symStack.append(lexer->currentCommand()); } break; ./ horizontal_lineto_command ::= AITCH ; /. case $rule_number: { //qDebug() << " got horizontal_lineto command "; m_symStack.append(lexer->currentCommand()); } break; ./ vertical_lineto_command ::= VEE ; /. case $rule_number: { //qDebug() << " got vertical_lineto command "; m_symStack.append(lexer->currentCommand()); } break; ./ curveto_command ::= CEE ; /. case $rule_number: { //qDebug() << " got curveto command "; m_symStack.append(lexer->currentCommand()); } break; ./ smooth_curveto_command ::= ESS ; /. case $rule_number: { //qDebug() << " got smooth curveto command "; m_symStack.append(lexer->currentCommand()); } break; ./ quadratic_bezier_curveto_command ::= KYU ; /. case $rule_number: { //qDebug() << " got quadratic_bezier_curveto_command command "; m_symStack.append(lexer->currentCommand()); } break; ./ smooth_quadratic_bezier_curveto_command ::= TEE ; /. case $rule_number: { //qDebug() << " got smooth_quadratic_bezier_curveto_command command "; m_symStack.append(lexer->currentCommand()); } break; ./ elliptical_arc_command ::= AE ; /. case $rule_number: { //qDebug() << " got elliptical_arc_command "; m_symStack.append(lexer->currentCommand()); } break; ./ closepath ::= ZEE ; /. case $rule_number: { qDebug() << " got closepath "; m_symStack.append(lexer->currentCommand()); } break; ./ fakeclosepath ::= EKS ; /. case $rule_number: { qDebug() << " got fakeclosepath "; } break; ./ /. } // switch m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT); } else { int ers = state; int shifts = 0; int reduces = 0; int expected_tokens[3]; for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (! k) continue; else if (k < 0) ++reduces; else if (spell[tk]) { if (shifts < 3) expected_tokens[shifts] = tk; ++shifts; } } m_errorMessage.clear(); if (shifts && shifts < 3) { bool first = true; for (int s = 0; s < shifts; ++s) { if (first) m_errorMessage += QLatin1String("Expected "); else m_errorMessage += QLatin1String(", "); first = false; m_errorMessage += QLatin1String("`"); m_errorMessage += QLatin1String(spell[expected_tokens[s]]); m_errorMessage += QLatin1String("'"); } } return false; } } return false; } ./ fritzing-app-0.9.2b/src/svg/svgpathgrammar.cpp000066400000000000000000000165501250202676700214310ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! #include "svgpathgrammar_p.h" const char *const SVGPathGrammar::spell [] = { "end of file", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #ifndef QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO "path_data", "moveto_drawto_command_groups", "moveto_drawto_command_group", "moveto", "drawto_commands", "drawto_command", "fakeclosepath", "closepath", "lineto", "horizontal_lineto", "vertical_lineto", "curveto", "smooth_curveto", "quadratic_bezier_curveto", "smooth_quadratic_bezier_curveto", "elliptical_arc", "moveto_command", "moveto_argument_sequence", "coordinate_pair", "comma_wsp", "lineto_command", "lineto_argument_sequence", "horizontal_lineto_command", "horizontal_lineto_argument_sequence", "coordinate", "vertical_lineto_command", "vertical_lineto_argument_sequence", "curveto_command", "curveto_argument_sequence", "curveto_argument", "smooth_curveto_command", "smooth_curveto_argument_sequence", "smooth_curveto_argument", "quadratic_bezier_curveto_command", "quadratic_bezier_curveto_argument_sequence", "quadratic_bezier_curveto_argument", "elliptical_arc_command", "elliptical_arc_argument_sequence", "elliptical_arc_argument", "nonnegative_number", "number", "flag", "smooth_quadratic_bezier_curveto_command", "smooth_quadratic_bezier_curveto_argument_sequence", "x_coordinate", "y_coordinate", "wspplus", "$accept" #endif // QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO }; const int SVGPathGrammar::lhs [] = { 15, 16, 16, 17, 17, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 18, 32, 32, 32, 23, 36, 36, 36, 24, 38, 38, 38, 25, 41, 41, 41, 26, 43, 43, 43, 44, 44, 44, 44, 27, 46, 46, 46, 47, 47, 28, 49, 49, 49, 50, 50, 30, 52, 52, 52, 53, 29, 58, 58, 58, 33, 33, 59, 60, 34, 34, 61, 39, 54, 55, 56, 31, 35, 37, 40, 42, 45, 48, 57, 51, 22, 21, 62}; const int SVGPathGrammar:: rhs[] = { 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 2, 2, 1, 3, 2, 2, 1, 3, 2, 2, 1, 3, 2, 2, 1, 2, 3, 5, 4, 4, 3, 2, 1, 2, 3, 2, 3, 2, 1, 2, 3, 3, 2, 2, 1, 2, 3, 11, 2, 1, 3, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; #ifndef QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO const int SVGPathGrammar::rule_info [] = { 15, 16 , 16, 17 , 16, 17, 16 , 17, 18, 19 , 17, 18 , 19, 20 , 19, 20, 19 , 20, 21 , 20, 22 , 20, 23 , 20, 24 , 20, 25 , 20, 26 , 20, 27 , 20, 28 , 20, 29 , 20, 30 , 18, 31, 32 , 32, 33 , 32, 33, 34, 32 , 32, 33, 32 , 23, 35, 36 , 36, 33 , 36, 33, 34, 36 , 36, 33, 36 , 24, 37, 38 , 38, 39 , 38, 39, 34, 38 , 38, 39, 38 , 25, 40, 41 , 41, 39 , 41, 39, 34, 41 , 41, 39, 41 , 26, 42, 43 , 43, 44 , 43, 44, 43 , 43, 44, 34, 43 , 44, 33, 34, 33, 34, 33 , 44, 33, 34, 33, 33 , 44, 33, 33, 34, 33 , 44, 33, 33, 33 , 27, 45, 46 , 46, 47 , 46, 47, 46 , 46, 47, 34, 46 , 47, 33, 33 , 47, 33, 34, 33 , 28, 48, 49 , 49, 50 , 49, 50, 49 , 49, 50, 34, 49 , 50, 33, 34, 33 , 50, 33, 33 , 30, 51, 52 , 52, 53 , 52, 53, 52 , 52, 53, 34, 52 , 53, 54, 34, 54, 34, 55, 34, 56, 34, 56, 34, 33 , 29, 57, 58 , 58, 33 , 58, 33, 34, 58 , 58, 33, 58 , 33, 59, 34, 60 , 33, 59, 60 , 59, 39 , 60, 39 , 34, 61 , 34, 12 , 61, 14 , 39, 13 , 54, 13 , 55, 13 , 56, 13 , 31, 1 , 35, 4 , 37, 5 , 40, 6 , 42, 7 , 45, 8 , 48, 9 , 57, 10 , 51, 11 , 22, 2 , 21, 3 , 62, 15, 0}; const int SVGPathGrammar::rule_index [] = { 0, 2, 4, 7, 10, 12, 14, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 40, 42, 46, 49, 52, 54, 58, 61, 64, 66, 70, 73, 76, 78, 82, 85, 88, 90, 93, 97, 103, 108, 113, 117, 120, 122, 125, 129, 132, 136, 139, 141, 144, 148, 152, 155, 158, 160, 163, 167, 179, 182, 184, 188, 191, 195, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238}; #endif // QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO const int SVGPathGrammar::action_default [] = { 0, 74, 5, 0, 2, 1, 0, 82, 76, 78, 84, 75, 79, 80, 81, 77, 83, 9, 13, 0, 6, 4, 17, 0, 8, 11, 0, 10, 0, 15, 0, 14, 0, 16, 0, 12, 0, 70, 65, 0, 35, 34, 0, 68, 69, 0, 0, 67, 0, 0, 39, 38, 0, 41, 40, 0, 36, 37, 0, 66, 64, 63, 7, 71, 55, 54, 0, 0, 56, 57, 0, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0, 58, 27, 26, 0, 29, 28, 23, 22, 0, 25, 24, 0, 49, 48, 0, 53, 52, 0, 50, 51, 0, 43, 42, 0, 46, 47, 0, 44, 45, 60, 59, 0, 62, 61, 31, 30, 0, 33, 32, 19, 18, 0, 21, 20, 3, 85}; const int SVGPathGrammar::goto_default [] = { 6, 5, 4, 2, 21, 20, 24, 17, 27, 25, 35, 18, 31, 29, 33, 22, 3, 121, 39, 45, 28, 88, 26, 83, 38, 36, 116, 19, 41, 40, 32, 103, 102, 30, 94, 93, 23, 65, 64, 66, 74, 77, 34, 111, 42, 60, 47, 0}; const int SVGPathGrammar::action_index [] = { 16, -15, 29, -13, 0, -15, 2, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -13, 29, -15, -15, -9, -15, -15, -1, -15, -5, -15, -3, -15, -7, -15, -1, -15, -1, -15, -15, 10, 10, -15, 10, -15, -15, -13, 10, -15, 10, -1, -15, -15, -1, -15, -15, -1, -15, -15, -1, -15, -15, -15, -15, -15, 13, -15, 4, -2, -15, -15, -6, 7, -4, -15, 7, -8, -15, 7, 1, 7, -1, -15, 10, -15, -1, -15, -15, 10, -15, -13, -15, -15, 10, 10, -15, -13, -15, -15, -13, -15, -15, 10, 10, -15, -13, -15, -15, -13, -15, -15, 10, -15, -10, -15, -15, 10, -15, -13, -15, -15, 10, -15, -13, -15, -15, -15, -15, -48, -48, -48, -12, 43, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, -4, -48, -48, -48, -48, -48, -5, -48, 6, -48, 3, -48, -13, -48, -9, -48, -21, -48, -48, -6, 20, -48, 16, -48, -48, -3, 13, -48, 19, -8, -48, -48, -7, -48, -48, -14, -48, -48, 10, -48, -48, -48, -48, -48, 8, -48, -11, -30, -48, -48, -26, 1, -48, -48, 4, -48, -48, -15, -25, -2, 0, -48, 50, -48, 18, -48, -48, 42, -48, 15, -48, -48, 33, 38, -48, -16, -48, -48, 25, -48, -48, 28, 46, -48, -17, -48, -48, 31, -48, -48, 35, -48, 7, -48, -48, 72, -48, 2, -48, -48, 49, -48, 12, -48, -48, -48, -48}; const int SVGPathGrammar::action_info [] = { 37, 1, 126, 37, 63, 76, 37, 63, 37, 73, 37, 63, 37, 0, 76, 0, 43, 1, 44, 43, 0, 44, 43, 37, 44, 43, 63, 44, 0, 0, 0, 16, 10, 11, 8, 15, 9, 12, 13, 14, 7, 0, 0, 0, 62, 106, 97, 115, 78, 101, 120, 69, 70, 110, 51, 54, 46, 71, 57, 48, 79, 80, 81, 82, 72, 92, 0, 75, 87, 110, 115, 67, 119, 124, 120, 53, 52, 87, 59, 58, 91, 50, 49, 55, 59, 86, 82, 92, 125, 68, 105, 104, 56, 101, 114, 96, 95, 110, 112, 61, 92, 98, 0, 100, 87, 89, 109, 90, 101, 107, 123, 120, 122, 84, 0, 0, 99, 85, 82, 0, 0, 108, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 0, 115, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const int SVGPathGrammar::action_check [] = { 13, 1, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -1, 13, -1, 12, 1, 14, 12, -1, 14, 12, 13, 14, 12, 13, 14, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1, -1, -1, 4, 18, 18, 24, 19, 18, 18, 37, 19, 18, 18, 18, 18, 39, 28, 18, 41, 19, 18, 24, 19, 18, -1, 19, 18, 18, 24, 19, 26, 17, 18, 18, 19, 18, 24, 19, 21, 18, 19, 19, 24, 23, 24, 18, 1, 37, 18, 19, 28, 18, 43, 18, 19, 18, 19, 45, 18, 19, -1, 34, 18, 19, 31, 21, 18, 19, 17, 18, 19, 19, -1, -1, 34, 23, 24, -1, -1, 31, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, 24, -1, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; fritzing-app-0.9.2b/src/svg/svgpathgrammar_p.h000066400000000000000000000032761250202676700214160ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! #ifndef SVGPATHGRAMMAR_P_H #define SVGPATHGRAMMAR_P_H class SVGPathGrammar { public: enum { EOF_SYMBOL = 0, AE = 11, AITCH = 5, CEE = 7, COMMA = 12, EKS = 3, EL = 4, EM = 1, ESS = 8, KYU = 9, NUMBER = 13, TEE = 10, VEE = 6, WHITESPACE = 14, ZEE = 2, ACCEPT_STATE = 126, RULE_COUNT = 85, STATE_COUNT = 127, TERMINAL_COUNT = 15, NON_TERMINAL_COUNT = 48, GOTO_INDEX_OFFSET = 127, GOTO_INFO_OFFSET = 44, GOTO_CHECK_OFFSET = 44 }; static const char *const spell []; static const int lhs []; static const int rhs []; #ifndef QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO static const int rule_index []; static const int rule_info []; #endif // QLALR_NO_SVGPATHGRAMMAR_DEBUG_INFO static const int goto_default []; static const int action_default []; static const int action_index []; static const int action_info []; static const int action_check []; static inline int nt_action (int state, int nt) { const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; const int yyn = goto_index [state] + nt; if (yyn < 0 || goto_check [yyn] != nt) return goto_default [nt]; const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; return goto_info [yyn]; } static inline int t_action (int state, int token) { const int yyn = action_index [state] + token; if (yyn < 0 || action_check [yyn] != token) return - action_default [state]; return action_info [yyn]; } }; #endif // SVGPATHGRAMMAR_P_H fritzing-app-0.9.2b/src/svg/svgpathlexer.cpp000066400000000000000000000134151250202676700211170ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "svgpathlexer.h" #include "svgpathgrammar_p.h" #include "../utils/textutils.h" #include static const QRegExp findWhitespaceBefore(" ([AaCcMmVvTtQqSsLlVvHhZz,])"); static const QRegExp findWhitespaceAfter("([AaCcMmVvTtQqSsLlVvHhZz,]) "); static const QRegExp findWhitespaceAtEnd(" $"); SVGPathLexer::SVGPathLexer(const QString &source) { m_source = clean(source); m_chars = m_source.unicode(); m_size = m_source.size(); //qDebug() << m_source; m_pos = 0; m_current = next(); } SVGPathLexer::~SVGPathLexer() { } QString SVGPathLexer::clean(const QString & source) { // SVG path grammar is ambiguous, so clean it up to make it easier to parse // the rules are WSP* , WSP* ==> , // WSP* command WSP* ==> command // WSP+ ==> WSP // where WSP is whitespace, command is one of the path commands such as M C V ... QString s1 = source; s1.replace(TextUtils::FindWhitespace, " "); s1.replace(findWhitespaceBefore, "\\1"); // replace with the captured character s1.replace(findWhitespaceAfter, "\\1"); // replace with the captured character s1.replace(findWhitespaceAtEnd, ""); return s1; } int SVGPathLexer::lex() { if (TextUtils::floatingPointMatcher.indexIn(m_source, m_pos - 1) == m_pos - 1) { m_currentNumber = m_source.mid(m_pos - 1, TextUtils::floatingPointMatcher.matchedLength()).toDouble(); m_pos += TextUtils::floatingPointMatcher.matchedLength() - 1; next(); return SVGPathGrammar::NUMBER; } if (m_current.isSpace()) { next(); return SVGPathGrammar::WHITESPACE; } else if (m_current.isNull()) { return SVGPathGrammar::EOF_SYMBOL; } else if (m_current == QLatin1Char('V')) { m_currentCommand = m_current; next(); return SVGPathGrammar::VEE; } else if (m_current == QLatin1Char('v')) { m_currentCommand = m_current; next(); return SVGPathGrammar::VEE; } else if (m_current == QLatin1Char('T')) { m_currentCommand = m_current; next(); return SVGPathGrammar::TEE; } else if (m_current == QLatin1Char('t')) { m_currentCommand = m_current; next(); return SVGPathGrammar::TEE; } else if (m_current == QLatin1Char(FakeClosePathChar)) { m_currentCommand = m_current; next(); return SVGPathGrammar::EKS; } else if (m_current == QLatin1Char('C')) { m_currentCommand = m_current; next(); return SVGPathGrammar::CEE; } else if (m_current == QLatin1Char('c')) { m_currentCommand = m_current; next(); return SVGPathGrammar::CEE; } else if (m_current == QLatin1Char('Q')) { m_currentCommand = m_current; next(); return SVGPathGrammar::KYU; } else if (m_current == QLatin1Char('q')) { m_currentCommand = m_current; next(); return SVGPathGrammar::KYU; } else if (m_current == QLatin1Char('S')) { m_currentCommand = m_current; next(); return SVGPathGrammar::ESS; } else if (m_current == QLatin1Char('s')) { m_currentCommand = m_current; next(); return SVGPathGrammar::ESS; } else if (m_current == QLatin1Char('H')) { m_currentCommand = m_current; next(); return SVGPathGrammar::AITCH; } else if (m_current == QLatin1Char('h')) { m_currentCommand = m_current; next(); return SVGPathGrammar::AITCH; } else if (m_current == QLatin1Char('L')) { m_currentCommand = m_current; next(); return SVGPathGrammar::EL; } else if (m_current == QLatin1Char('l')) { m_currentCommand = m_current; next(); return SVGPathGrammar::EL; } else if (m_current == QLatin1Char('M')) { m_currentCommand = m_current; next(); return SVGPathGrammar::EM; } else if (m_current == QLatin1Char('m')) { m_currentCommand = m_current; next(); return SVGPathGrammar::EM; } else if (m_current == QLatin1Char('A')) { m_currentCommand = m_current; next(); return SVGPathGrammar::AE; } else if (m_current == QLatin1Char('a')) { m_currentCommand = m_current; next(); return SVGPathGrammar::AE; } else if (m_current == QLatin1Char('Z')) { m_currentCommand = m_current; next(); return SVGPathGrammar::ZEE; } else if (m_current == QLatin1Char('z')) { m_currentCommand = m_current; next(); return SVGPathGrammar::ZEE; } else if (m_current == QLatin1Char(',')) { next(); return SVGPathGrammar::COMMA; } return -1; } QChar SVGPathLexer::next() { if (m_pos < m_size) m_current = m_chars[m_pos++]; else m_current = QChar(); return m_current; } QChar SVGPathLexer::currentCommand() { return m_currentCommand; } double SVGPathLexer::currentNumber() { return m_currentNumber; } fritzing-app-0.9.2b/src/svg/svgpathlexer.h000066400000000000000000000031621250202676700205620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVGPATHLEXER_H #define SVGPATHLEXER_H #include #include #include #include #include class SVGPathLexer { public: SVGPathLexer(const QString &source); ~SVGPathLexer(); int lex(); QChar currentCommand(); double currentNumber(); public: static const char FakeClosePathChar = 'x'; protected: QChar next(); QString clean(const QString & source); protected: QString m_source; const QChar *m_chars; int m_size; int m_pos; QChar m_current; QChar m_currentCommand; double m_currentNumber; }; #endif fritzing-app-0.9.2b/src/svg/svgpathparser.cpp000066400000000000000000000171751250202676700213030ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 4147 $: $Author: cohen@irascible.com $: $Date: 2010-04-25 19:00:40 +0200 (So, 25. Apr 2010) $ ********************************************************************/ #include #include "svgpathparser.h" #include "svgpathlexer.h" SVGPathParser::SVGPathParser() { } SVGPathParser::~SVGPathParser() { } QVector & SVGPathParser::symStack() { return m_symStack; } void SVGPathParser::reallocateStack() { int size = m_stateStack.size(); if (size == 0) size = 128; else size <<= 1; m_stateStack.resize(size); } QString SVGPathParser::errorMessage() const { return m_errorMessage; } QVariant SVGPathParser::result() const { return m_result; } bool SVGPathParser::parse(SVGPathLexer *lexer) { const int INITIAL_STATE = 0; int yytoken = -1; reallocateStack(); m_tos = 0; m_stateStack[++m_tos] = INITIAL_STATE; while (true) { const int state = m_stateStack.at(m_tos); if (yytoken == -1 && - TERMINAL_COUNT != action_index [state]) yytoken = lexer->lex(); int act = t_action (state, yytoken); if (act == ACCEPT_STATE) return true; else if (act > 0) { if (++m_tos == m_stateStack.size()) reallocateStack(); m_stateStack[m_tos] = act; yytoken = -1; } else if (act < 0) { int r = - act - 1; m_tos -= rhs [r]; act = m_stateStack.at(m_tos++); switch (r) { case 0: { //qDebug() << " got path_data "; } break; case 2: { //qDebug() << " got moveto_drawto_command_groups "; } break; case 4: { //qDebug() << " got moveto_drawto_command_group "; } break; case 6: { //qDebug() << " got drawto_commands "; } break; case 16: { //qDebug() << " got drawto_command "; } break; case 17: { //qDebug() << " got moveto "; } break; case 20: { //qDebug() << " got moveto_argument_sequence "; } break; case 21: { //qDebug() << " got lineto "; } break; case 24: { //qDebug() << " got lineto_argument_sequence "; } break; case 25: { //qDebug() << " got horizontal_lineto "; } break; case 28: { //qDebug() << " got horizontal_lineto_argument_sequence "; } break; case 29: { //qDebug() << " got vertical_lineto "; } break; case 32: { //qDebug() << " got vertical_lineto_argument_sequence "; } break; case 33: { //qDebug() << " got curveto "; } break; case 36: { //qDebug() << " got curveto_argument_sequence 3 "; } break; case 40: { //qDebug() << " got curveto_argument "; } break; case 41: { //qDebug() << " got smooth_curveto "; } break; case 44: { //qDebug() << " got smooth_curveto_argument_sequence 3 "; } break; case 46: { //qDebug() << " got smooth_curveto_argument "; } break; case 47: { //qDebug() << " got quadratic_bezier_curveto "; } break; case 50: { //qDebug() << " got quadratic_bezier_curveto_argument "; } break; case 52: { //qDebug() << " got quadratic_bezier_curveto_argument "; } break; case 53: { //qDebug() << " got elliptical_arc "; } break; case 56: { //qDebug() << " got elliptical_arc_argument_sequence "; } break; case 57: { //qDebug() << " got elliptical_arc_argument "; } break; case 58: { //qDebug() << " got smooth_quadratic_bezier_curveto "; } break; case 61: { //qDebug() << " got smooth_quadratic_bezier_curveto_argument_sequence 3 "; } break; case 63: { //qDebug() << " got coordinate_pair "; } break; case 64: { //qDebug() << " got x coordinate "; } break; case 65: { //qDebug() << " got y coordinate "; } break; case 67: { //qDebug() << " got comma_wsp 3 "; } break; case 68: { //qDebug() << " got wspplus "; } break; case 69: { //qDebug() << " got coordinate "; m_symStack.append(lexer->currentNumber()); } break; case 70: { //qDebug() << " got nonnegative_number "; //not presently checking this is non-negative m_symStack.append(lexer->currentNumber()); } break; case 71: { //qDebug() << " got number "; m_symStack.append(lexer->currentNumber()); } break; case 72: { //qDebug() << " got flag "; //not presently checking this is only 0 or 1 m_symStack.append(lexer->currentNumber()); } break; case 73: { //qDebug() << " got moveto command "; m_symStack.append(lexer->currentCommand()); } break; case 74: { //qDebug() << " got lineto command "; m_symStack.append(lexer->currentCommand()); } break; case 75: { //qDebug() << " got horizontal_lineto command "; m_symStack.append(lexer->currentCommand()); } break; case 76: { //qDebug() << " got vertical_lineto command "; m_symStack.append(lexer->currentCommand()); } break; case 77: { //qDebug() << " got curveto command "; m_symStack.append(lexer->currentCommand()); } break; case 78: { //qDebug() << " got smooth curveto command "; m_symStack.append(lexer->currentCommand()); } break; case 79: { //qDebug() << " got quadratic_bezier_curveto_command command "; m_symStack.append(lexer->currentCommand()); } break; case 80: { //qDebug() << " got smooth_quadratic_bezier_curveto_command command "; m_symStack.append(lexer->currentCommand()); } break; case 81: { //qDebug() << " got elliptical_arc_command "; m_symStack.append(lexer->currentCommand()); } break; case 82: { //qDebug() << " got closepath "; m_symStack.append(lexer->currentCommand()); } break; case 83: { //qDebug() << " got fakeclosepath "; } break; } // switch m_stateStack[m_tos] = nt_action(act, lhs[r] - TERMINAL_COUNT); } else { int ers = state; int shifts = 0; int reduces = 0; int expected_tokens[3]; for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (! k) continue; else if (k < 0) ++reduces; else if (spell[tk]) { if (shifts < 3) expected_tokens[shifts] = tk; ++shifts; } } m_errorMessage.clear(); if (shifts && shifts < 3) { bool first = true; for (int s = 0; s < shifts; ++s) { if (first) m_errorMessage += QLatin1String("Expected "); else m_errorMessage += QLatin1String(", "); first = false; m_errorMessage += QLatin1String("`"); m_errorMessage += QLatin1String(spell[expected_tokens[s]]); m_errorMessage += QLatin1String("'"); } } return false; } } return false; } fritzing-app-0.9.2b/src/svg/svgpathparser.h000066400000000000000000000031761250202676700207440ustar00rootroot00000000000000// This file was generated by qlalr - DO NOT EDIT! /******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-08 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 3442 $: $Author: cohen@irascible.com $: $Date: 2009-09-10 04:49:21 +0200 (Do, 10. Sep 2009) $ ********************************************************************/ #ifndef SVGPATHPARSER_H #define SVGPATHPARSER_H #include #include #include "svgpathgrammar_p.h" class SVGPathLexer; class SVGPathParser: public SVGPathGrammar { public: SVGPathParser(); ~SVGPathParser(); bool parse(SVGPathLexer *lexer); QVector & symStack(); QString errorMessage() const; QVariant result() const; private: void reallocateStack(); int m_tos; QVector m_stateStack; QVector m_symStack; QString m_errorMessage; QVariant m_result; }; #endif // SVGPATHPARSER_H fritzing-app-0.9.2b/src/svg/svgpathrunner.cpp000066400000000000000000000136141250202676700213120ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include "svgpathrunner.h" QHash SVGPathRunner::pathCommands; SVGPathRunner::SVGPathRunner() { if (pathCommands.size() == 0) { initStates(); } } SVGPathRunner::~SVGPathRunner() { } bool SVGPathRunner::runPath(QVector & pathData, void * userData) { PathCommand * currentCommand = NULL; QList args; foreach (QVariant variant, pathData) { if (variant.type() == QVariant::Char) { PathCommand * newCommand = pathCommands.value(variant.toChar(), NULL); if (newCommand == NULL) return false; if (currentCommand != NULL) { if (currentCommand->argCount == 0) { if (args.count() != 0) return false; } else if (args.count() % currentCommand->argCount != 0) return false; emit commandSignal(currentCommand->command, currentCommand->relative, args, userData); } args.clear(); currentCommand = newCommand; } else if (variant.type() == QVariant::Double) { if (currentCommand == NULL) return false; args.append(variant.toDouble()); } } if (currentCommand != NULL) { if (currentCommand->argCount == 0) { if (args.count() != 0) return false; } else if (args.count() % currentCommand->argCount != 0) return false; emit commandSignal(currentCommand->command, currentCommand->relative, args, userData); } return true; } void SVGPathRunner::initStates() { pathCommands.clear(); PathCommand * pathCommand = new PathCommand; pathCommand->command = 'M'; pathCommand->relative = false; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'm'; pathCommand->relative = true; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'A'; pathCommand->relative = false; pathCommand->argCount = 7; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'a'; pathCommand->relative = true; pathCommand->argCount = 7; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'Z'; pathCommand->relative = false; pathCommand->argCount = 0; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'z'; pathCommand->relative = true; pathCommand->argCount = 0; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'L'; pathCommand->relative = false; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'l'; pathCommand->relative = true; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'H'; pathCommand->relative = false; pathCommand->argCount = 1; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'h'; pathCommand->relative = true; pathCommand->argCount = 1; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'V'; pathCommand->relative = false; pathCommand->argCount = 1; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'v'; pathCommand->relative = true; pathCommand->argCount = 1; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'C'; pathCommand->relative = false; pathCommand->argCount = 6; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'c'; pathCommand->relative = true; pathCommand->argCount = 6; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'S'; pathCommand->relative = false; pathCommand->argCount = 4; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 's'; pathCommand->relative = true; pathCommand->argCount = 4; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'Q'; pathCommand->relative = false; pathCommand->argCount = 4; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'q'; pathCommand->relative = true; pathCommand->argCount = 4; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 'T'; pathCommand->relative = false; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); pathCommand = new PathCommand; pathCommand->command = 't'; pathCommand->relative = true; pathCommand->argCount = 2; pathCommands.insert(pathCommand->command, pathCommand); } fritzing-app-0.9.2b/src/svg/svgpathrunner.h000066400000000000000000000032671250202676700207620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SVGPATHRUNNER_H #define SVGPATHRUNNER_H #include #include struct PathCommand { bool relative; int argCount; QChar command; }; class SVGPathRunner : public QObject { Q_OBJECT public: SVGPathRunner(); ~SVGPathRunner(); public: bool runPath(QVector & pathData, void * userData); signals: // note: must connect to this signal via Qt::DirectConnection since args is modified immediately after the signal void commandSignal(QChar command, bool relative, QList & args, void * userData); protected: static void initStates(); protected: static QHash pathCommands; }; #endif // SVGPATHRUNNER_H fritzing-app-0.9.2b/src/svg/x2svg.cpp000066400000000000000000000052341250202676700174540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "x2svg.h" #include "../utils/textutils.h" #include "svgfilesplitter.h" #include #include #include #include #include #include #include #include #include static const int MAX_INT = std::numeric_limits::max(); static const int MIN_INT = std::numeric_limits::min(); X2Svg::X2Svg() { m_attribute = "%2\n"; m_comment = "%2\n"; } void X2Svg::initLimits() { m_maxX = MIN_INT; m_maxY = MIN_INT; m_minX = MAX_INT; m_minY = MAX_INT; } void X2Svg::checkXLimit(double x) { if (x < m_minX) m_minX = x; if (x > m_maxX) m_maxX = x; } void X2Svg::checkYLimit(double y) { if (y < m_minY) m_minY = y; if (y > m_maxY) m_maxY = y; } QString X2Svg::offsetMin(const QString & svg) { if (m_minX == 0 && m_minY == 0) return svg; QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(svg, true, &errorStr, &errorLine, &errorColumn)) { throw QObject::tr("failure in svg conversion 1: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn); } QDomElement root = domDocument.documentElement(); if (root.isNull()) { throw QObject::tr("failure in svg conversion 2: %1 %2 %3").arg(errorStr).arg(errorLine).arg(errorColumn); } SvgFileSplitter splitter; splitter.shiftChild(root, -m_minX, -m_minY, true); return TextUtils::removeXMLEntities(domDocument.toString()); } QString X2Svg::unquote(const QString & string) { QString s = string; if (s.endsWith('"')) { s.chop(1); } if (s.startsWith('"')) { s = s.remove(0, 1); } return s; } fritzing-app-0.9.2b/src/svg/x2svg.h000066400000000000000000000026301250202676700171160ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef X2SVG_H #define X2SVG_H #include class X2Svg { public: X2Svg(); void checkXLimit(double x); void checkYLimit(double y); protected: QString offsetMin(const QString & svg); void initLimits(); QString unquote(const QString &); protected: double m_maxX; double m_maxY; double m_minX; double m_minY; QString m_attribute; QString m_comment; }; #endif // X2SVG_H fritzing-app-0.9.2b/src/utils/000077500000000000000000000000001250202676700162345ustar00rootroot00000000000000fritzing-app-0.9.2b/src/utils/abstractstatesbutton.h000066400000000000000000000042601250202676700226720ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ABSTRACTSTATESBUTTON_H_ #define ABSTRACTSTATESBUTTON_H_ #include #include #include "../debugdialog.h" class AbstractStatesButton { public: virtual ~AbstractStatesButton() {} // clears compiler warning void setEnabledIcon() { setImage(m_enabledImage); } void setDisabledIcon() { setImage(m_disabledImage); } void setPressedIcon() { setImage(m_pressedImage); } protected: virtual QString imagePrefix() = 0; virtual QString imageSubfix() { return "_icon.png"; } virtual void setImage(const QPixmap & pixmap) = 0; virtual void setupIcons(const QString &imageName, bool hasStates=true) { if(hasStates) { m_enabledImage = QPixmap(imagePrefix()+imageName+"Enabled"+imageSubfix()); m_disabledImage = QPixmap(imagePrefix()+imageName+"Disabled"+imageSubfix()); m_pressedImage = QPixmap(imagePrefix()+imageName+"Pressed"+imageSubfix()); } else { m_enabledImage = QPixmap(imagePrefix()+imageName+imageSubfix()); m_disabledImage = m_enabledImage; m_pressedImage = m_enabledImage; } } protected: QPixmap m_enabledImage; QPixmap m_disabledImage; QPixmap m_pressedImage; }; #endif /* ABSTRACTSTATESBUTTON_H_ */ fritzing-app-0.9.2b/src/utils/autoclosemessagebox.cpp000066400000000000000000000104361250202676700230200ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "autoclosemessagebox.h" #include "../debugdialog.h" #include "../mainwindow/mainwindow.h" static const int Interval = 30; static const int Steps = 7; static const int Wait = 100; AutoCloseMessageBox::AutoCloseMessageBox( QWidget * parent ) : QLabel(parent) { setWordWrap(true); } void AutoCloseMessageBox::setStartPos(int x, int y) { m_startX = x; m_startY = y; QRect r = this->geometry(); r.moveTo(x, y); setGeometry(r); } void AutoCloseMessageBox::setEndPos(int x, int y) { m_endX = x; m_endY = y; } void AutoCloseMessageBox::start() { m_counter = Steps; m_animationTimer.setInterval(Interval); m_animationTimer.setSingleShot(false); connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(moveOut())); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) m_animationTimer.setTimerType(Qt::PreciseTimer); #endif m_movingState = MovingOut; m_animationTimer.start(); show(); } void AutoCloseMessageBox::mousePressEvent(QMouseEvent * event) { Q_UNUSED(event); if (m_movingState != MovingBack) { m_animationTimer.stop(); if (m_movingState == MovingOut) { disconnect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(moveOut())); } else if (m_movingState == Waiting) { disconnect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(wait())); } prepMoveBack(); } } void AutoCloseMessageBox::moveOut() { if (--m_counter == 0) { m_animationTimer.stop(); disconnect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(moveOut())); m_movingState = Waiting; QRect r = geometry(); r.moveTo(m_endX, m_endY); setGeometry(r); m_counter = Wait; connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(wait())); m_animationTimer.start(); return; } QRect r = geometry(); int dx = (m_endX - r.x()) / m_counter; int dy = (m_endY - r.y()) / m_counter; r.translate(dx, dy); setGeometry(r); } void AutoCloseMessageBox::moveBack() { if (--m_counter == 0) { m_animationTimer.stop(); disconnect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(moveOut())); QRect r = geometry(); r.moveTo(m_startX, m_startY); setGeometry(r); this->deleteLater(); return; } QRect r = geometry(); int dx = (m_startX - r.x()) / m_counter; int dy = (m_startY - r.y()) / m_counter; r.translate(dx, dy); setGeometry(r); } void AutoCloseMessageBox::wait() { if (--m_counter == 0) { m_animationTimer.stop(); disconnect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(wait())); prepMoveBack(); } } void AutoCloseMessageBox::prepMoveBack() { m_counter = Steps; m_movingState = MovingBack; connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(moveBack())); m_animationTimer.start(); } void AutoCloseMessageBox::showMessage(QWidget *window, const QString &message) { MainWindow * mainWindow = qobject_cast(window); if (mainWindow == NULL) return; QStatusBar * statusBar = mainWindow->realStatusBar(); if (statusBar == NULL) return; AutoCloseMessageBox * acmb = new AutoCloseMessageBox(mainWindow); acmb->setText(message); QRect dest = statusBar->geometry(); // toolbar->geometry(); QRect r = mainWindow->geometry(); acmb->setFixedSize(QSize(dest.width(), dest.height())); QPoint p(dest.x(), dest.y()); p = statusBar->parentWidget()->mapTo(mainWindow, p); acmb->setStartPos(p.x(), r.height()); acmb->setEndPos(p.x(), p.y()); acmb->start(); } fritzing-app-0.9.2b/src/utils/autoclosemessagebox.h000066400000000000000000000033231250202676700224620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef AUTOCLOSEMESSAGEBOX_H #define AUTOCLOSEMESSAGEBOX_H #include #include class AutoCloseMessageBox : public QLabel { Q_OBJECT public: AutoCloseMessageBox(QWidget * parent); void setStartPos(int x, int y); void setEndPos(int x, int y); void start(); static void showMessage(QWidget * window, const QString & message); protected: void mousePressEvent(QMouseEvent *); void prepMoveBack(); protected slots: void moveOut(); void moveBack(); void wait(); protected: enum MovingState { MovingOut, Waiting, MovingBack }; volatile MovingState m_movingState; int m_endX; int m_endY; int m_startX; int m_startY; QTimer m_animationTimer; int m_counter; }; #endif fritzing-app-0.9.2b/src/utils/bendpointaction.cpp000066400000000000000000000035421250202676700221240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "bendpointaction.h" #include "../items/itembase.h" #include "../connectors/connectoritem.h" BendpointAction::BendpointAction(const QString & text, QObject * parent) : QAction(text, parent) { m_lastHoverEnterConnectorItem = NULL; m_lastHoverEnterItem = NULL; } void BendpointAction::setLastHoverEnterConnectorItem(ConnectorItem * connectorItem) { m_lastHoverEnterConnectorItem = connectorItem; } void BendpointAction::setLastHoverEnterItem(ItemBase * itemBase) { m_lastHoverEnterItem = itemBase; } void BendpointAction::setLastLocation(QPointF p) { m_lastLocation = p; } ConnectorItem * BendpointAction::lastHoverEnterConnectorItem() { return m_lastHoverEnterConnectorItem; } ItemBase * BendpointAction::lastHoverEnterItem() { return m_lastHoverEnterItem; } QPointF BendpointAction::lastLocation() { return m_lastLocation; } fritzing-app-0.9.2b/src/utils/bendpointaction.h000066400000000000000000000032051250202676700215650ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef BENDPOINTACTION_H #define BENDPOINTACTION_H #include #include #include class BendpointAction : public QAction { Q_OBJECT public: BendpointAction(const QString & text, QObject * parent); void setLastHoverEnterConnectorItem(class ConnectorItem *); void setLastHoverEnterItem(class ItemBase *); void setLastLocation(QPointF); class ConnectorItem * lastHoverEnterConnectorItem(); class ItemBase * lastHoverEnterItem(); QPointF lastLocation(); protected: class ConnectorItem * m_lastHoverEnterConnectorItem; class ItemBase * m_lastHoverEnterItem; QPointF m_lastLocation; }; #endif fritzing-app-0.9.2b/src/utils/bezier.cpp000066400000000000000000001064211250202676700202240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "bezier.h" #include "graphicsutils.h" #include "../debugdialog.h" #include #include ///////////////////////////////////////////// // borrowed liberally from the following sources: // // http://processingjs.nihongoresources.com/bezierinfo/ // http://www.tinaja.com/text/bezmath.html, // http://www.lemoda.net/maths/bezier-length/index.html, // http://www.flong.com/texts/code/shapers_bez/ // http://steve.hollasch.net/cgindex/curves/cbezarclen.html ///////////////////////////////////////////// // utilities from http://www.flong.com/texts/code/shapers_bez/ double B0 (double t){ return (1-t)*(1-t)*(1-t); } double B1 (double t){ return 3*t* (1-t)*(1-t); } double B2 (double t){ return 3*t*t* (1-t); } double B3 (double t){ return t*t*t; } ///////////////////////////////////////////// // utilities from http://processingjs.nihongoresources.com/bezierinfo/sketchsource.php?sketch=cubicGaussQuadrature double base3(double t, double p1, double p2, double p3, double p4) { double t1 = -3*p1 + 9*p2 - 9*p3 + 3*p4; double t2 = t*t1 + 6*p1 - 12*p2 + 6*p3; return t*t2 - 3*p1 + 3*p2; } // Legendre-Gauss abscissae (xi values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x)) double Tvalues[25][24] = { {}, {}, {-0.5773502691896257310588680411456152796745,0.5773502691896257310588680411456152796745}, {0.0000000000000000000000000000000000000000,-0.7745966692414834042779148148838430643082,0.7745966692414834042779148148838430643082}, {-0.3399810435848562573113440521410666406155,0.3399810435848562573113440521410666406155,-0.8611363115940525725378051902225706726313,0.8611363115940525725378051902225706726313}, {0.0000000000000000000000000000000000000000,-0.5384693101056831077144693153968546539545,0.5384693101056831077144693153968546539545,-0.9061798459386639637003213465504813939333,0.9061798459386639637003213465504813939333}, {0.6612093864662644815410885712481103837490,-0.6612093864662644815410885712481103837490,-0.2386191860831969047129774708082550205290,0.2386191860831969047129774708082550205290,-0.9324695142031520500580654697841964662075,0.9324695142031520500580654697841964662075}, {0.0000000000000000000000000000000000000000,0.4058451513773971841558818596240598708391,-0.4058451513773971841558818596240598708391,-0.7415311855993944600839995473506860435009,0.7415311855993944600839995473506860435009,-0.9491079123427584862682238053821492940187,0.9491079123427584862682238053821492940187}, {-0.1834346424956498078362443493460887111723,0.1834346424956498078362443493460887111723,-0.5255324099163289908176466269651427865028,0.5255324099163289908176466269651427865028,-0.7966664774136267279658341067261062562466,0.7966664774136267279658341067261062562466,-0.9602898564975362871720676594122778624296,0.9602898564975362871720676594122778624296}, {0.0000000000000000000000000000000000000000,-0.8360311073266357695388251158874481916428,0.8360311073266357695388251158874481916428,-0.9681602395076260858530758923734538257122,0.9681602395076260858530758923734538257122,-0.3242534234038089158147499801998492330313,0.3242534234038089158147499801998492330313,-0.6133714327005903577116896485676988959312,0.6133714327005903577116896485676988959312}, {-0.1488743389816312157059030596428783610463,0.1488743389816312157059030596428783610463,-0.4333953941292472133994806426926515996456,0.4333953941292472133994806426926515996456,-0.6794095682990244355892173189204186201096,0.6794095682990244355892173189204186201096,-0.8650633666889845363456856830453034490347,0.8650633666889845363456856830453034490347,-0.9739065285171717434309357486199587583542,0.9739065285171717434309357486199587583542}, {0.0000000000000000000000000000000000000000,-0.2695431559523449593918087430211016908288,0.2695431559523449593918087430211016908288,-0.5190961292068118071441062966187018901110,0.5190961292068118071441062966187018901110,-0.7301520055740493564400139803183265030384,0.7301520055740493564400139803183265030384,-0.8870625997680953167545681026240345090628,0.8870625997680953167545681026240345090628,-0.9782286581460569729884468870295677334070,0.9782286581460569729884468870295677334070}, {-0.1252334085114689132822718420356977730989,0.1252334085114689132822718420356977730989,-0.3678314989981801841345543380157323554158,0.3678314989981801841345543380157323554158,-0.5873179542866174829285341729701030999422,0.5873179542866174829285341729701030999422,-0.7699026741943046925342741815256886184216,0.7699026741943046925342741815256886184216,-0.9041172563704749087776235683122649788857,0.9041172563704749087776235683122649788857,-0.9815606342467192435563561048184055835009,0.9815606342467192435563561048184055835009}, {0.0000000000000000000000000000000000000000,-0.2304583159551348015003924274424207396805,0.2304583159551348015003924274424207396805,-0.4484927510364468683512484403763664886355,0.4484927510364468683512484403763664886355,-0.6423493394403402279024817289609927684069,0.6423493394403402279024817289609927684069,-0.8015780907333098781464286730624735355377,0.8015780907333098781464286730624735355377,-0.9175983992229779229177211163914762437344,0.9175983992229779229177211163914762437344,-0.9841830547185881350458203087328001856804,0.9841830547185881350458203087328001856804}, {-0.1080549487073436676354276642086915671825,0.1080549487073436676354276642086915671825,-0.3191123689278897446186533670697826892138,0.3191123689278897446186533670697826892138,-0.5152486363581540995681962158414535224438,0.5152486363581540995681962158414535224438,-0.6872929048116854788830210054584313184023,0.6872929048116854788830210054584313184023,-0.8272013150697650196718768711434677243233,0.8272013150697650196718768711434677243233,-0.9284348836635735180422557277779560536146,0.9284348836635735180422557277779560536146,-0.9862838086968123141318187663273420184851,0.9862838086968123141318187663273420184851}, {0.0000000000000000000000000000000000000000,-0.2011940939974345143870237961891689337790,0.2011940939974345143870237961891689337790,-0.3941513470775633853904196257644798606634,0.3941513470775633853904196257644798606634,-0.5709721726085388304738899023504927754402,0.5709721726085388304738899023504927754402,-0.7244177313601700696210627938853576779366,0.7244177313601700696210627938853576779366,-0.8482065834104272061821916395274456590414,0.8482065834104272061821916395274456590414,-0.9372733924007059513883177714888006448746,0.9372733924007059513883177714888006448746,-0.9879925180204853774057482951320707798004,0.9879925180204853774057482951320707798004}, {-0.0950125098376374405129141109682677779347,0.0950125098376374405129141109682677779347,-0.2816035507792589154263396267197094857693,0.2816035507792589154263396267197094857693,-0.4580167776572273696800152720243204385042,0.4580167776572273696800152720243204385042,-0.6178762444026437705701937375124543905258,0.6178762444026437705701937375124543905258,-0.7554044083550029986540153004170861095190,0.7554044083550029986540153004170861095190,-0.8656312023878317551961458775622304528952,0.8656312023878317551961458775622304528952,-0.9445750230732326002680565579794347286224,0.9445750230732326002680565579794347286224,-0.9894009349916499385102497399202547967434,0.9894009349916499385102497399202547967434}, {0.0000000000000000000000000000000000000000,-0.1784841814958478545261044700964703224599,0.1784841814958478545261044700964703224599,-0.3512317634538763000406902392569463700056,0.3512317634538763000406902392569463700056,-0.5126905370864769384553483178024180233479,0.5126905370864769384553483178024180233479,-0.6576711592166907260903485621383879333735,0.6576711592166907260903485621383879333735,-0.7815140038968013680431567991035990417004,0.7815140038968013680431567991035990417004,-0.8802391537269859123071569229068700224161,0.8802391537269859123071569229068700224161,-0.9506755217687677950166857954172883182764,0.9506755217687677950166857954172883182764,-0.9905754753144173641032921295845881104469,0.9905754753144173641032921295845881104469}, {-0.0847750130417353059408824833553808275610,0.0847750130417353059408824833553808275610,-0.2518862256915054831374334298743633553386,0.2518862256915054831374334298743633553386,-0.4117511614628426297457508553634397685528,0.4117511614628426297457508553634397685528,-0.5597708310739475390249708652845583856106,0.5597708310739475390249708652845583856106,-0.6916870430603532238222896921797655522823,0.6916870430603532238222896921797655522823,-0.8037049589725231424353069087374024093151,0.8037049589725231424353069087374024093151,-0.8926024664975557021406871172075625509024,0.8926024664975557021406871172075625509024,-0.9558239495713977129653926567698363214731,0.9558239495713977129653926567698363214731,-0.9915651684209308980300079383596312254667,0.9915651684209308980300079383596312254667}, {0.0000000000000000000000000000000000000000,-0.1603586456402253668240831530056311748922,0.1603586456402253668240831530056311748922,-0.3165640999636298302810644145210972055793,0.3165640999636298302810644145210972055793,-0.4645707413759609383241411251219687983394,0.4645707413759609383241411251219687983394,-0.6005453046616809897884081692609470337629,0.6005453046616809897884081692609470337629,-0.7209661773352293856476080691209062933922,0.7209661773352293856476080691209062933922,-0.8227146565371428188484514976153150200844,0.8227146565371428188484514976153150200844,-0.9031559036148179009373393455462064594030,0.9031559036148179009373393455462064594030,-0.9602081521348300174878431789693422615528,0.9602081521348300174878431789693422615528,-0.9924068438435843519940249279898125678301,0.9924068438435843519940249279898125678301}, {-0.0765265211334973383117130651953630149364,0.0765265211334973383117130651953630149364,-0.2277858511416450681963397073559463024139,0.2277858511416450681963397073559463024139,-0.3737060887154195487624974703066982328892,0.3737060887154195487624974703066982328892,-0.5108670019508271264996324134699534624815,0.5108670019508271264996324134699534624815,-0.6360536807265150249790508496516849845648,0.6360536807265150249790508496516849845648,-0.7463319064601507957235071444301865994930,0.7463319064601507957235071444301865994930,-0.8391169718222187823286617458506952971220,0.8391169718222187823286617458506952971220,-0.9122344282513259461353527512983419001102,0.9122344282513259461353527512983419001102,-0.9639719272779138092843709273438435047865,0.9639719272779138092843709273438435047865,-0.9931285991850948846604296704754233360291,0.9931285991850948846604296704754233360291}, {0.0000000000000000000000000000000000000000,-0.1455618541608950933241573011400760151446,0.1455618541608950933241573011400760151446,-0.2880213168024011172185794293909566476941,0.2880213168024011172185794293909566476941,-0.4243421202074387776903563462838064879179,0.4243421202074387776903563462838064879179,-0.5516188358872198271853903861483559012413,0.5516188358872198271853903861483559012413,-0.6671388041974123384036943207320291548967,0.6671388041974123384036943207320291548967,-0.7684399634756778896260698275000322610140,0.7684399634756778896260698275000322610140,-0.8533633645833172964856316866644192487001,0.8533633645833172964856316866644192487001,-0.9200993341504007938524978271743748337030,0.9200993341504007938524978271743748337030,-0.9672268385663063128276917268522083759308,0.9672268385663063128276917268522083759308,-0.9937521706203894522602126926358323544264,0.9937521706203894522602126926358323544264}, {-0.0697392733197222253194169638845778536052,0.0697392733197222253194169638845778536052,-0.2078604266882212725509049278116435743868,0.2078604266882212725509049278116435743868,-0.3419358208920842412403828802780481055379,0.3419358208920842412403828802780481055379,-0.4693558379867570073962212973128771409392,0.4693558379867570073962212973128771409392,-0.5876404035069116016387624767958186566830,0.5876404035069116016387624767958186566830,-0.6944872631866827461522007070016115903854,0.6944872631866827461522007070016115903854,-0.7878168059792081123759999172762036323547,0.7878168059792081123759999172762036323547,-0.8658125777203001804949167308222968131304,0.8658125777203001804949167308222968131304,-0.9269567721871739829353487039043102413416,0.9269567721871739829353487039043102413416,-0.9700604978354286922481719557254109531641,0.9700604978354286922481719557254109531641,-0.9942945854823992402060639506089501082897,0.9942945854823992402060639506089501082897}, {0.0000000000000000000000000000000000000000,-0.1332568242984661088801345840693102218211,0.1332568242984661088801345840693102218211,-0.2641356809703449548543119362875586375594,0.2641356809703449548543119362875586375594,-0.3903010380302908144400930723350029438734,0.3903010380302908144400930723350029438734,-0.5095014778460075222099590064317453652620,0.5095014778460075222099590064317453652620,-0.6196098757636461229481028567533940076828,0.6196098757636461229481028567533940076828,-0.7186613631319501704908248029823880642653,0.7186613631319501704908248029823880642653,-0.8048884016188398993207897547108586877584,0.8048884016188398993207897547108586877584,-0.8767523582704416229560706597112584859133,0.8767523582704416229560706597112584859133,-0.9329710868260161493736859483760781586170,0.9329710868260161493736859483760781586170,-0.9725424712181152120393790028174407780170,0.9725424712181152120393790028174407780170,-0.9947693349975521570627279288601130247116,0.9947693349975521570627279288601130247116}, {-0.0640568928626056299791002857091370970011,0.0640568928626056299791002857091370970011,-0.1911188674736163106704367464772076345980,0.1911188674736163106704367464772076345980,-0.3150426796961633968408023065421730279922,0.3150426796961633968408023065421730279922,-0.4337935076260451272567308933503227308393,0.4337935076260451272567308933503227308393,-0.5454214713888395626995020393223967403173,0.5454214713888395626995020393223967403173,-0.6480936519369755455244330732966773211956,0.6480936519369755455244330732966773211956,-0.7401241915785543579175964623573236167431,0.7401241915785543579175964623573236167431,-0.8200019859739029470802051946520805358887,0.8200019859739029470802051946520805358887,-0.8864155270044010714869386902137193828821,0.8864155270044010714869386902137193828821,-0.9382745520027327978951348086411599069834,0.9382745520027327978951348086411599069834,-0.9747285559713094738043537290650419890881,0.9747285559713094738043537290650419890881,-0.9951872199970213106468008845695294439793,0.9951872199970213106468008845695294439793}}; // Legendre-Gauss weights (wi values, defined by a function linked to in the Bezier primer article) double Cvalues[25][24] = { {}, {}, {1.0000000000000000000000000000000000000000,1.0000000000000000000000000000000000000000}, {0.8888888888888888395456433499930426478386,0.5555555555555555802271783250034786760807,0.5555555555555555802271783250034786760807}, {0.6521451548625460947761212082696147263050,0.6521451548625460947761212082696147263050,0.3478548451374538497127275604725582525134,0.3478548451374538497127275604725582525134}, {0.5688888888888888883954564334999304264784,0.4786286704993664709029133064177585765719,0.4786286704993664709029133064177585765719,0.2369268850561890848993584768322762101889,0.2369268850561890848993584768322762101889}, {0.3607615730481386062677984227775596082211,0.3607615730481386062677984227775596082211,0.4679139345726910370615314604947343468666,0.4679139345726910370615314604947343468666,0.1713244923791703566706701167277060449123,0.1713244923791703566706701167277060449123}, {0.4179591836734694032529091600736137479544,0.3818300505051189230876218516641529276967,0.3818300505051189230876218516641529276967,0.2797053914892766446342875497066415846348,0.2797053914892766446342875497066415846348,0.1294849661688697028960604029634851031005,0.1294849661688697028960604029634851031005}, {0.3626837833783619902128236844873754307628,0.3626837833783619902128236844873754307628,0.3137066458778872690693617641954915598035,0.3137066458778872690693617641954915598035,0.2223810344533744820516574236535234376788,0.2223810344533744820516574236535234376788,0.1012285362903762586661571276636095717549,0.1012285362903762586661571276636095717549}, {0.3302393550012597822629345500899944454432,0.1806481606948573959137149813614087179303,0.1806481606948573959137149813614087179303,0.0812743883615744122650426106702070683241,0.0812743883615744122650426106702070683241,0.3123470770400028628799304897256661206484,0.3123470770400028628799304897256661206484,0.2606106964029354378098446431977208703756,0.2606106964029354378098446431977208703756}, {0.2955242247147528700246255084493895992637,0.2955242247147528700246255084493895992637,0.2692667193099963496294435572053771466017,0.2692667193099963496294435572053771466017,0.2190863625159820415877476307286997325718,0.2190863625159820415877476307286997325718,0.1494513491505805868886369580650352872908,0.1494513491505805868886369580650352872908,0.0666713443086881379917585377370414789766,0.0666713443086881379917585377370414789766}, {0.2729250867779006162194832540990319103003,0.2628045445102466515230332788632949814200,0.2628045445102466515230332788632949814200,0.2331937645919904822378043718344997614622,0.2331937645919904822378043718344997614622,0.1862902109277342621584949711177614517510,0.1862902109277342621584949711177614517510,0.1255803694649046120535018644659430719912,0.1255803694649046120535018644659430719912,0.0556685671161736631007421749472996452823,0.0556685671161736631007421749472996452823}, {0.2491470458134027732288728884668671526015,0.2491470458134027732288728884668671526015,0.2334925365383548057085505433860816992819,0.2334925365383548057085505433860816992819,0.2031674267230659247651658461109036579728,0.2031674267230659247651658461109036579728,0.1600783285433462210800570346691529266536,0.1600783285433462210800570346691529266536,0.1069393259953184266430881166343169752508,0.1069393259953184266430881166343169752508,0.0471753363865118277575838590109924552962,0.0471753363865118277575838590109924552962}, {0.2325515532308738975153517003491288051009,0.2262831802628972321933531475224299356341,0.2262831802628972321933531475224299356341,0.2078160475368885096170146198346628807485,0.2078160475368885096170146198346628807485,0.1781459807619457380578609217991470359266,0.1781459807619457380578609217991470359266,0.1388735102197872495199959530509659089148,0.1388735102197872495199959530509659089148,0.0921214998377284516317686779984796885401,0.0921214998377284516317686779984796885401,0.0404840047653158771612247335269785253331,0.0404840047653158771612247335269785253331}, {0.2152638534631577948985636794532183557749,0.2152638534631577948985636794532183557749,0.2051984637212956041896205761076998896897,0.2051984637212956041896205761076998896897,0.1855383974779378219999159682629397138953,0.1855383974779378219999159682629397138953,0.1572031671581935463599677404999965801835,0.1572031671581935463599677404999965801835,0.1215185706879031851679329179205524269491,0.1215185706879031851679329179205524269491,0.0801580871597602079292599341897584963590,0.0801580871597602079292599341897584963590,0.0351194603317518602714208952875196700916,0.0351194603317518602714208952875196700916}, {0.2025782419255612865072180284187197685242,0.1984314853271115786093048427574103698134,0.1984314853271115786093048427574103698134,0.1861610000155622113293674146916600875556,0.1861610000155622113293674146916600875556,0.1662692058169939202105780395868350751698,0.1662692058169939202105780395868350751698,0.1395706779261543240000520427201990969479,0.1395706779261543240000520427201990969479,0.1071592204671719394948325998484506271780,0.1071592204671719394948325998484506271780,0.0703660474881081243747615872052847407758,0.0703660474881081243747615872052847407758,0.0307532419961172691358353148416426847689,0.0307532419961172691358353148416426847689}, {0.1894506104550685021692402187909465283155,0.1894506104550685021692402187909465283155,0.1826034150449235837765371570640127174556,0.1826034150449235837765371570640127174556,0.1691565193950025358660127494658809155226,0.1691565193950025358660127494658809155226,0.1495959888165767359691216142891789786518,0.1495959888165767359691216142891789786518,0.1246289712555338768940060845125117339194,0.1246289712555338768940060845125117339194,0.0951585116824927856882254673109855502844,0.0951585116824927856882254673109855502844,0.0622535239386478936318702892549481475726,0.0622535239386478936318702892549481475726,0.0271524594117540964133272751723779947497,0.0271524594117540964133272751723779947497}, {0.1794464703562065333031227964966092258692,0.1765627053669926449508409405098063871264,0.1765627053669926449508409405098063871264,0.1680041021564500358653759803928551264107,0.1680041021564500358653759803928551264107,0.1540457610768102836296122859494062140584,0.1540457610768102836296122859494062140584,0.1351363684685254751283167706787935458124,0.1351363684685254751283167706787935458124,0.1118838471934039680011352402289048768580,0.1118838471934039680011352402289048768580,0.0850361483171791776580761279547004960477,0.0850361483171791776580761279547004960477,0.0554595293739872027827253475606994470581,0.0554595293739872027827253475606994470581,0.0241483028685479314545681006620725383982,0.0241483028685479314545681006620725383982}, {0.1691423829631436004383715498988749459386,0.1691423829631436004383715498988749459386,0.1642764837458327298325144738555536605418,0.1642764837458327298325144738555536605418,0.1546846751262652419622867228099494241178,0.1546846751262652419622867228099494241178,0.1406429146706506538855308008351130411029,0.1406429146706506538855308008351130411029,0.1225552067114784593471199514169711619616,0.1225552067114784593471199514169711619616,0.1009420441062871681703327908508072141558,0.1009420441062871681703327908508072141558,0.0764257302548890515847546112127020023763,0.0764257302548890515847546112127020023763,0.0497145488949697969549568199454370187595,0.0497145488949697969549568199454370187595,0.0216160135264833117019200869890482863411,0.0216160135264833117019200869890482863411}, {0.1610544498487836984068621859478298574686,0.1589688433939543399375793342187535017729,0.1589688433939543399375793342187535017729,0.1527660420658596696075193221986410208046,0.1527660420658596696075193221986410208046,0.1426067021736066031678547005867585539818,0.1426067021736066031678547005867585539818,0.1287539625393362141547726196222356520593,0.1287539625393362141547726196222356520593,0.1115666455473339896409257221421285066754,0.1115666455473339896409257221421285066754,0.0914900216224499990280705219447554554790,0.0914900216224499990280705219447554554790,0.0690445427376412262931992813719261903316,0.0690445427376412262931992813719261903316,0.0448142267656995996194524423117400147021,0.0448142267656995996194524423117400147021,0.0194617882297264781221723950466184760444,0.0194617882297264781221723950466184760444}, {0.1527533871307258372951309866039082407951,0.1527533871307258372951309866039082407951,0.1491729864726037413369397199858212843537,0.1491729864726037413369397199858212843537,0.1420961093183820411756101975697674788535,0.1420961093183820411756101975697674788535,0.1316886384491766370796739238357986323535,0.1316886384491766370796739238357986323535,0.1181945319615184120110029653005767613649,0.1181945319615184120110029653005767613649,0.1019301198172404415709380032240005675703,0.1019301198172404415709380032240005675703,0.0832767415767047547436874310733401216567,0.0832767415767047547436874310733401216567,0.0626720483341090678353069165495980996639,0.0626720483341090678353069165495980996639,0.0406014298003869386621822457072994438931,0.0406014298003869386621822457072994438931,0.0176140071391521178811867542890468030237,0.0176140071391521178811867542890468030237}, {0.1460811336496904144777175815761438570917,0.1445244039899700461138110085812513716519,0.1445244039899700461138110085812513716519,0.1398873947910731496691028041823301464319,0.1398873947910731496691028041823301464319,0.1322689386333374683690777828815043903887,0.1322689386333374683690777828815043903887,0.1218314160537285334440227302366110961884,0.1218314160537285334440227302366110961884,0.1087972991671483785625085261017375160009,0.1087972991671483785625085261017375160009,0.0934444234560338621298214434318651910871,0.0934444234560338621298214434318651910871,0.0761001136283793039316591944043466355652,0.0761001136283793039316591944043466355652,0.0571344254268572049326735395879950374365,0.0571344254268572049326735395879950374365,0.0369537897708524937234741969405149575323,0.0369537897708524937234741969405149575323,0.0160172282577743345377552230957007850520,0.0160172282577743345377552230957007850520}, {0.1392518728556319806966001806358690373600,0.1392518728556319806966001806358690373600,0.1365414983460151721050834794368711300194,0.1365414983460151721050834794368711300194,0.1311735047870623838139891859100316651165,0.1311735047870623838139891859100316651165,0.1232523768105124178928733158500108402222,0.1232523768105124178928733158500108402222,0.1129322960805392156435900119504367467016,0.1129322960805392156435900119504367467016,0.1004141444428809648581335522976587526500,0.1004141444428809648581335522976587526500,0.0859416062170677286236042391465161927044,0.0859416062170677286236042391465161927044,0.0697964684245204886048341563764552120119,0.0697964684245204886048341563764552120119,0.0522933351526832859712534684604179346934,0.0522933351526832859712534684604179346934,0.0337749015848141515006020085820637177676,0.0337749015848141515006020085820637177676,0.0146279952982721998810955454928262042813,0.0146279952982721998810955454928262042813}, {0.1336545721861061852830943053049850277603,0.1324620394046966131984532921705977059901,0.1324620394046966131984532921705977059901,0.1289057221880821613169132433540653437376,0.1289057221880821613169132433540653437376,0.1230490843067295336776822978208656422794,0.1230490843067295336776822978208656422794,0.1149966402224113642960290349037677515298,0.1149966402224113642960290349037677515298,0.1048920914645414120824895576333801727742,0.1048920914645414120824895576333801727742,0.0929157660600351542612429511791560798883,0.0929157660600351542612429511791560798883,0.0792814117767189491248203125906002242118,0.0792814117767189491248203125906002242118,0.0642324214085258499151720457120973151177,0.0642324214085258499151720457120973151177,0.0480376717310846690356385124687221832573,0.0480376717310846690356385124687221832573,0.0309880058569794447631551292943186126649,0.0309880058569794447631551292943186126649,0.0134118594871417712993677540112003043760,0.0134118594871417712993677540112003043760}, {0.1279381953467521593204025975865079089999,0.1279381953467521593204025975865079089999,0.1258374563468283025002847352880053222179,0.1258374563468283025002847352880053222179,0.1216704729278033914052770114722079597414,0.1216704729278033914052770114722079597414,0.1155056680537255991980671865348995197564,0.1155056680537255991980671865348995197564,0.1074442701159656343712356374453520402312,0.1074442701159656343712356374453520402312,0.0976186521041138843823858906034729443491,0.0976186521041138843823858906034729443491,0.0861901615319532743431096832864568568766,0.0861901615319532743431096832864568568766,0.0733464814110802998392557583429152145982,0.0733464814110802998392557583429152145982,0.0592985849154367833380163688161701429635,0.0592985849154367833380163688161701429635,0.0442774388174198077483545432642131345347,0.0442774388174198077483545432642131345347,0.0285313886289336633705904233693217975087,0.0285313886289336633705904233693217975087,0.0123412297999872001830201639904771582223,0.0123412297999872001830201639904771582223}}; ///////////////////////////////////////////// Bezier::Bezier(QPointF cp0, QPointF cp1) { m_cp0 = cp0; m_cp1 = cp1; m_isEmpty = false; } Bezier::Bezier() { m_isEmpty = true; } bool Bezier::isEmpty() const { return m_isEmpty; } void Bezier::clear() { m_isEmpty = true; } QPointF Bezier::cp0() const { return m_cp0; } QPointF Bezier::cp1() const { return m_cp1; } QPointF Bezier::endpoint0() const { return m_endpoint0; } QPointF Bezier::endpoint1() const { return m_endpoint1; } void Bezier::set_cp0(QPointF cp0) { m_cp0 = cp0; m_isEmpty = false; } void Bezier::set_cp1(QPointF cp1) { m_cp1 = cp1; m_isEmpty = false; } void Bezier::set_endpoints(QPointF ep0, QPointF ep1) { m_endpoint0 = ep0; m_endpoint1 = ep1; } Bezier Bezier::fromElement(QDomElement & element) { Bezier bezier; if (element.tagName().compare("bezier") != 0) return bezier; QDomElement point = element.firstChildElement("cp0"); if (point.isNull()) return bezier; double x = point.attribute("x").toDouble(); double y = point.attribute("y").toDouble(); bezier.set_cp0(QPointF(x, y)); point = element.firstChildElement("cp1"); x = point.attribute("x").toDouble(); y = point.attribute("y").toDouble(); bezier.set_cp1(QPointF(x, y)); return bezier; } void Bezier::write(QXmlStreamWriter & streamWriter) { if (isEmpty()) return; streamWriter.writeStartElement("bezier"); streamWriter.writeStartElement("cp0"); streamWriter.writeAttribute("x", QString::number(m_cp0.x())); streamWriter.writeAttribute("y", QString::number(m_cp0.y())); streamWriter.writeEndElement(); streamWriter.writeStartElement("cp1"); streamWriter.writeAttribute("x", QString::number(m_cp1.x())); streamWriter.writeAttribute("y", QString::number(m_cp1.y())); streamWriter.writeEndElement(); streamWriter.writeEndElement(); } bool Bezier::operator==(const Bezier & other) const { if (m_isEmpty != other.isEmpty()) return false; if (m_cp0 != other.cp0()) return false; if (m_cp1 != other.cp1()) return false; return true; } bool Bezier::operator!=(const Bezier & other) const { if (m_isEmpty != other.isEmpty()) return true; if (m_cp0 != other.cp0()) return true; if (m_cp1 != other.cp1()) return true; return false; } void Bezier::recalc(QPointF p) { // http://www.flong.com/texts/code/shapers_bez/ // http://www.lemoda.net/maths/bezier-length/index.html, // arbitrary but reasonable t-values for interior control points double t0 = 0.3; double t1 = 0.7; if (m_drag_cp0) { double x = (p.x() - m_endpoint0.x() * B0(t0) - m_cp1.x() * B2(t0) - m_endpoint1.x() * B3(t0)) / B1(t0); double y = (p.y() - m_endpoint0.y() * B0(t0) - m_cp1.y() * B2(t0) - m_endpoint1.y() * B3(t0)) / B1(t0); m_cp0 = QPointF(x, y); } else { double x = (p.x() - m_endpoint0.x() * B0(t1) - m_cp0.x() * B1(t1) - m_endpoint1.x() * B3(t1)) / B2(t1); double y = (p.y() - m_endpoint0.y() * B0(t1) - m_cp0.y() * B1(t1) - m_endpoint1.y() * B3(t1)) / B2(t1); m_cp1 = QPointF(x, y); } /* DebugDialog::debug(QString("ix:%1 p0x:%2,p0y:%3 p1x:%4,p1y:%5 px:%6,py:%7") .arg(m_drag_cp0) .arg(m_endpoint0.x()) .arg(m_endpoint0.y()) .arg(m_endpoint1.x()) .arg(m_endpoint1.y()) .arg(p.x()) .arg(p.y()) ); */ m_isEmpty = false; } void Bezier::initToEnds(QPointF cp0, QPointF cp1) { m_endpoint0 = m_cp0 = cp0; m_endpoint1 = m_cp1 = cp1; m_isEmpty = false; } double Bezier::xFromT(double t) const { // http://www.lemoda.net/maths/bezier-length/index.html return m_endpoint0.x() * B0(t) + m_cp0.x() * B1(t) + m_cp1.x() * B2(t) + m_endpoint1.x() * B3(t); } double Bezier::xFromTPrime(double t) const { return base3(t, m_endpoint0.x(), m_cp0.x(), m_cp1.x(), m_endpoint1.x()); } double Bezier::yFromT(double t) const { // http://www.lemoda.net/maths/bezier-length/index.html return m_endpoint0.y() * B0(t) + m_cp0.y() * B1(t) + m_cp1.y() * B2(t) + m_endpoint1.y() * B3(t); } void Bezier::split(double t, Bezier & left, Bezier & right) const { // http://processingjs.nihongoresources.com/bezierinfo/sketchsource.php?sketch=CubicDeCasteljau // interpolate from 4 to 3 points QPointF p5((1-t)*m_endpoint0.x() + t*m_cp0.x(), (1-t)*m_endpoint0.y() + t*m_cp0.y()); QPointF p6((1-t)*m_cp0.x() + t*m_cp1.x(), (1-t)*m_cp0.y() + t*m_cp1.y()); QPointF p7((1-t)*m_cp1.x() + t*m_endpoint1.x(), (1-t)*m_cp1.y() + t*m_endpoint1.y()); // interpolate from 3 to 2 points QPointF p8((1-t)*p5.x() + t*p6.x(), (1-t)*p5.y() + t*p6.y()); QPointF p9((1-t)*p6.x() + t*p7.x(), (1-t)*p6.y() + t*p7.y()); // interpolate from 2 points to 1 point QPointF p10((1-t)*p8.x() + t*p9.x(), (1-t)*p8.y() + t*p9.y()); // we now have all the values we need to build the subcurves left.m_endpoint0 = m_endpoint0; left.m_cp0 = p5; left.m_cp1 = p8; right.m_endpoint0 = left.m_endpoint1 = p10; right.m_cp0 = p9; right.m_cp1 = p7; right.m_endpoint1 = m_endpoint1; left.m_isEmpty = right.m_isEmpty = false; } void Bezier::initControlIndex(QPointF p, double width) { double t = findSplit(p, width); double totalLen = computeCubicCurveLength(1, 24); double len = computeCubicCurveLength(t, 24); //double d0 = GraphicsUtils::distanceSqd(p, m_cp0); //double d1 = GraphicsUtils::distanceSqd(p, m_cp1); m_drag_cp0 = (len <= totalLen / 2); } /** * Gauss quadrature for cubic Bezier curves */ double Bezier::computeCubicCurveLength(double z, int n) const { // http://processingjs.nihongoresources.com/bezierinfo/sketchsource.php?sketch=cubicGaussQuadrature double z2 = z/2.0; double sum = 0; for (int i = 0; i < n; i++) { double corrected_t = z2 * Tvalues[n][i] + z2; sum += Cvalues[n][i] * cubicF(corrected_t); } return z2 * sum; } double Bezier::cubicF(double t) const { double xbase = base3(t, m_endpoint0.x(), m_cp0.x(), m_cp1.x(), m_endpoint1.x()); double ybase = base3(t, m_endpoint0.y(), m_cp0.y(), m_cp1.y(), m_endpoint1.y()); double combined = xbase*xbase + ybase*ybase; return qSqrt(combined); } void Bezier::copy(const Bezier * other) { if (other == NULL) { m_isEmpty = true; return; } m_cp0 = other->m_cp0; m_cp1 = other->m_cp1; m_endpoint0 = other->m_endpoint0; m_endpoint1 = other->m_endpoint1; m_isEmpty = other->m_isEmpty; m_drag_cp0 = other->m_drag_cp0; } double Bezier::findSplit(QPointF p, double minDistance) const { double bestT = 0; double lastDistance = std::numeric_limits::max(); double blen = computeCubicCurveLength(1.0, 24); double increment = 1.0 / blen; double minDSqd = minDistance * minDistance; for (double t = 0; t <= 1; t += increment) { double x = xFromT(t); double y = yFromT(t); double d = GraphicsUtils::distanceSqd(p, QPointF(x, y)); if (d >= lastDistance) { if (d > minDSqd) continue; break; } bestT = t; lastDistance = d; } return bestT; } void Bezier::translateToZero() { m_cp0 -= m_endpoint0; m_cp1 -= m_endpoint0; m_endpoint1 -= m_endpoint0; m_endpoint0 -= m_endpoint0; } void Bezier::translate(QPointF p) { m_cp0 += p; m_cp1 += p; m_endpoint1 += p; m_endpoint0 += p; } Bezier Bezier::join(const Bezier * other) const { Bezier bezier; bool otherIsEmpty = (other == NULL || other->isEmpty()); if (isEmpty() && otherIsEmpty) { return bezier; } else { if (isEmpty()) { bezier.set_cp0(m_endpoint0); bezier.set_cp1(other->cp1()); } else if (other->isEmpty()) { bezier.set_cp1(other->m_endpoint1); bezier.set_cp0(cp0()); } else { bezier.set_cp0(cp0()); bezier.set_cp1(other->cp1()); } } return bezier; } bool Bezier::drag0() { return m_drag_cp0; } fritzing-app-0.9.2b/src/utils/bezier.h000066400000000000000000000045021250202676700176660ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef BEZIER_H #define BEZIER_H #include #include #include // cubic bezier auxiliary implementation class Bezier { public: Bezier(QPointF cp1, QPointF cp2); Bezier(); QPointF cp0() const; QPointF cp1() const; QPointF endpoint0() const; QPointF endpoint1() const; void set_cp0(QPointF); void set_cp1(QPointF); void set_endpoints(QPointF, QPointF); bool isEmpty() const; void clear(); void write(QXmlStreamWriter &); bool operator==(const Bezier &) const; bool operator!=(const Bezier &) const; void recalc(QPointF p); void initToEnds(QPointF cp0, QPointF cp1); double xFromT(double t) const; double xFromTPrime(double t) const; double yFromT(double t) const; void split(double t, Bezier & left, Bezier & right) const; void initControlIndex(QPointF fromPoint, double width); double computeCubicCurveLength(double z, int n) const; void copy(const Bezier *); double findSplit(QPointF p, double minDistance) const; void translateToZero(); void translate(QPointF); Bezier join(const Bezier * other) const; bool drag0(); protected: double cubicF(double t) const; public: static Bezier fromElement(QDomElement & element); protected: QPointF m_endpoint0; QPointF m_endpoint1; QPointF m_cp0; QPointF m_cp1; bool m_isEmpty; bool m_drag_cp0; }; #endif fritzing-app-0.9.2b/src/utils/bezierdisplay.cpp000066400000000000000000000113561250202676700216140ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "bezierdisplay.h" #include "../viewlayer.h" #include "../debugdialog.h" #include "../processeventblocker.h" #include "graphicsutils.h" #include #include #include BezierDisplay::BezierDisplay() { m_itemL0 = m_itemL1 = NULL; m_itemE0 = m_itemE1 = NULL; } BezierDisplay::~BezierDisplay() { //DebugDialog::debug("removing bezier display"); if (m_itemL0) { m_itemL0->scene()->removeItem(m_itemL0); delete m_itemL0; } if (m_itemL1) { m_itemL1->scene()->removeItem(m_itemL1); delete m_itemL1; } //if (m_itemE0) { // m_itemE0->scene()->removeItem(m_itemE0); // delete m_itemE0; //} //if (m_itemE1) { // m_itemE1->scene()->removeItem(m_itemE1); // delete m_itemE1; //} } void BezierDisplay::initDisplay(QGraphicsItem * master, Bezier *bezier) { //DebugDialog::debug("adding bezier display"); static int activeColor = 0xffffff; static int inactiveColor = 0xb0b0b0; QPen pen; pen.setWidth(0); QGraphicsItem * parent = master; while (parent->parentItem()) { parent = master->parentItem(); } // put the feeback on top double z = parent->zValue() + 100; // (ViewLayer::getZIncrement() / 2) m_itemL0 = new QGraphicsLineItem(); pen.setColor(QColor(bezier->drag0() ? activeColor : inactiveColor)); m_itemL0->setPen(pen); m_itemL0->setPos(0, 0); m_itemL0->setZValue(z); master->scene()->addItem(m_itemL0); //m_itemE0 = new QGraphicsEllipseItem(); //m_itemE0->setPen(pen); //m_itemE0->setPos(0, 0); //m_itemE0->setZValue(z); //master->scene()->addItem(m_itemE0); m_itemL1 = new QGraphicsLineItem(); pen.setColor(QColor(bezier->drag0() == false ? activeColor : inactiveColor)); m_itemL1->setPen(pen); m_itemL1->setPos(0, 0); m_itemL1->setZValue(z); master->scene()->addItem(m_itemL1); //m_itemE1 = new QGraphicsEllipseItem(); //m_itemE1->setPen(pen); //m_itemE1->setPos(0, 0); //m_itemE1->setZValue(z); //master->scene()->addItem(m_itemE1); updateDisplay(master, bezier); ProcessEventBlocker::processEvents(); } void BezierDisplay::updateDisplay(QGraphicsItem * master, Bezier *bezier) { if (m_itemL0 == NULL) return; if (m_itemL1 == NULL) return; //if (m_itemE0 == NULL) return; //if (m_itemE1 == NULL) return; if (bezier == NULL || bezier->isEmpty()) { m_itemL0->setVisible(false); m_itemL1->setVisible(false); //m_itemE0->setVisible(false); //m_itemE1->setVisible(false); return; } //static double minD = 5; //static double radius = 6; //static double minDSqd = minD * minD; QRectF sr = master->scene()->sceneRect(); double x1, y1, x2, y2; QPointF p0 = master->mapToScene(bezier->endpoint0()); QPointF p1 = master->mapToScene(bezier->cp0()); GraphicsUtils::liangBarskyLineClip(p0.x(), p0.y(), p1.x(), p1.y(), sr.left(), sr.right(), sr.top(), sr.bottom(), x1, y1, x2, y2); m_itemL0->setLine(x1, y1, x2, y2); //if (GraphicsUtils::distanceSqd(bezier->endpoint0(), bezier->cp0()) > minDSqd) { //m_itemE0->setVisible(false); //} //else { //QRectF r(master->mapToScene(bezier->endpoint0()), QSizeF(0,0)); //r.adjust(-radius, -radius, radius, radius); //m_itemE0->setRect(r); //m_itemE0->setVisible(true); //} p0 = master->mapToScene(bezier->endpoint1()); p1 = master->mapToScene(bezier->cp1()); GraphicsUtils::liangBarskyLineClip(p0.x(), p0.y(), p1.x(), p1.y(), sr.left(), sr.right(), sr.top(), sr.bottom(), x1, y1, x2, y2); m_itemL1->setLine(x1, y1, x2, y2); //if (GraphicsUtils::distanceSqd(bezier->endpoint1(), bezier->cp1()) > minDSqd) { // m_itemE1->setVisible(false); //} //else { // QRectF r(master->mapToScene(bezier->endpoint1()), QSizeF(0,0)); // r.adjust(-radius, -radius, radius, radius); // m_itemE1->setRect(r); // m_itemE1->setVisible(true); //} m_itemL0->setVisible(true); m_itemL1->setVisible(true); } fritzing-app-0.9.2b/src/utils/bezierdisplay.h000066400000000000000000000027341250202676700212610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef BEZIERDISPLAY_H #define BEZIERDISPLAY_H #include #include #include "bezier.h" class BezierDisplay { public: BezierDisplay(); ~BezierDisplay(); void initDisplay(QGraphicsItem * master, Bezier *); void updateDisplay(QGraphicsItem * master, Bezier *); protected: QGraphicsLineItem * m_itemL0; QGraphicsLineItem * m_itemL1; QGraphicsEllipseItem * m_itemE0; QGraphicsEllipseItem * m_itemE1; }; #endif fritzing-app-0.9.2b/src/utils/boundedregexpvalidator.h000066400000000000000000000043541250202676700231540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef BOUNDEDREGEXPVALIDATOR_H #define BOUNDEDREGEXPVALIDATOR_H #include #include typedef double (*Converter)(const QString &, const QString & symbol); class BoundedRegExpValidator : public QRegExpValidator { public: BoundedRegExpValidator(QObject * parent) : QRegExpValidator(parent) { m_max = std::numeric_limits::max(); m_min = std::numeric_limits::min(); m_converter = NULL; m_symbol = ""; } void setBounds(double min, double max) { m_min = min; m_max = max; } void setConverter(Converter converter) { m_converter = converter; } void setSymbol(const QString & symbol) { m_symbol = symbol; } QValidator::State validate ( QString & input, int & pos ) const { QValidator::State state = QRegExpValidator::validate(input, pos); if (state == QValidator::Invalid) return state; if (state == QValidator::Intermediate) return state; if (m_converter == NULL) return state; double converted = m_converter(input, m_symbol); if (converted < m_min) return QValidator::Invalid; if (converted > m_max) return QValidator::Invalid; return QValidator::Acceptable; } protected: double m_min; double m_max; QString m_symbol; Converter m_converter; }; #endif fritzing-app-0.9.2b/src/utils/bundler.h000066400000000000000000000006101250202676700200350ustar00rootroot00000000000000 #ifndef BUNDLER_H_ #define BUNDLER_H_ class Bundler { public: virtual ~Bundler() {} virtual bool saveAsAux(const QString &filename) = 0; virtual bool loadBundledAux(QDir &dir, QList mps) {Q_UNUSED(dir); Q_UNUSED(mps); return true;}; virtual bool preloadBundledAux(QDir &dir, bool dontAsk) {Q_UNUSED(dir); Q_UNUSED(dontAsk); return true;}; }; #endif /* BUNDLER_H_ */ fritzing-app-0.9.2b/src/utils/clickablelabel.cpp000066400000000000000000000023671250202676700216610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "clickablelabel.h" ClickableLabel::ClickableLabel(const QString & text, QWidget * parent) : QLabel(text, parent) { } void ClickableLabel::mousePressEvent(QMouseEvent * e) { QLabel::mousePressEvent(e); emit clicked(); } fritzing-app-0.9.2b/src/utils/clickablelabel.h000066400000000000000000000024571250202676700213260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef CLICKABLELABEL_H #define CLICKABLELABEL_H #include class ClickableLabel : public QLabel { Q_OBJECT public: ClickableLabel(const QString & text = "", QWidget * parent = NULL); protected: void mousePressEvent(QMouseEvent * e); signals: void clicked(); }; #endif fritzing-app-0.9.2b/src/utils/cursormaster.cpp000066400000000000000000000174571250202676700215070ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6141 $: $Author: cohen@irascible.com $: $Date: 2012-07-04 21:20:05 +0200 (Mi, 04. Jul 2012) $ ********************************************************************/ #include "cursormaster.h" #include "../debugdialog.h" #include #include #include #include #include #include #include #include #include #include #include QCursor * CursorMaster::BendpointCursor = NULL; QCursor * CursorMaster::NewBendpointCursor = NULL; QCursor * CursorMaster::MakeWireCursor = NULL; QCursor * CursorMaster::MakeCurveCursor = NULL; QCursor * CursorMaster::RubberbandCursor = NULL; QCursor * CursorMaster::MoveCursor = NULL; QCursor * CursorMaster::BendlegCursor = NULL; QCursor * CursorMaster::RotateCursor = NULL; QCursor * CursorMaster::ScaleCursor = NULL; //static QTimer timer; CursorMaster CursorMaster::TheCursorMaster; static QList Listeners; static QHash CursorItems; static QList Cursors; CursorMaster::CursorMaster() : QObject() { m_blocked = false; } void CursorMaster::cleanup() { foreach (QCursor ** cursor, Cursors) { delete *cursor; } Cursors.clear(); } void CursorMaster::initCursors() { if (BendpointCursor == NULL) { //timer.setSingleShot(true); //timer.setInterval(0); //connect(&timer, SIGNAL(timeout()), &TheCursorMaster, SLOT(moveCursor())); QStringList names; QStringList masks; names << ":resources/images/cursor/bendpoint.bmp" << ":resources/images/cursor/new_bendpoint.bmp" << ":resources/images/cursor/make_wire.bmp" << ":resources/images/cursor/curve.bmp" << ":resources/images/cursor/rubberband_move.bmp" << ":resources/images/cursor/part_move.bmp" << ":resources/images/cursor/bendleg.bmp" << ":resources/images/cursor/rotate.bmp" << ":resources/images/cursor/scale.bmp"; masks << ":resources/images/cursor/bendpoint_mask.bmp" << ":resources/images/cursor/new_bendpoint_mask.bmp" << ":resources/images/cursor/make_wire_mask.bmp" << ":resources/images/cursor/curve_mask.bmp" << ":resources/images/cursor/rubberband_move_mask.bmp" << ":resources/images/cursor/part_move_mask.bmp" << ":resources/images/cursor/bendleg_mask.bmp" << ":resources/images/cursor/rotate_mask.bmp" << ":resources/images/cursor/scale_mask.bmp"; Cursors << &BendpointCursor << &NewBendpointCursor << &MakeWireCursor << &MakeCurveCursor << &RubberbandCursor << &MoveCursor << &BendlegCursor << &RotateCursor << &ScaleCursor; for (int i = 0; i < Cursors.count(); i++) { QBitmap bitmap1(names.at(i)); QBitmap bitmap1m(masks.at(i)); *Cursors.at(i) = new QCursor(bitmap1, bitmap1m, 0, 0); } QApplication::instance()->installEventFilter(instance()); } } CursorMaster * CursorMaster::instance() { return &TheCursorMaster; } void CursorMaster::addCursor(QObject * object, const QCursor & cursor) { if (m_blocked) return; if (object == NULL) return; /* QGraphicsItem * item = dynamic_cast(object); if (item == NULL) return; QGraphicsScene * scene = item->scene(); if (scene == NULL) return; QGraphicsView * view = dynamic_cast(scene->parent()); if (view == NULL) return; QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL); if (pixmapItem == NULL) { pixmapItem = new QGraphicsPixmapItem(); pixmapItem->setZValue(10000); // always on top pixmapItem->setVisible(true); pixmapItem->setAcceptedMouseButtons(0); pixmapItem->setAcceptDrops(false); pixmapItem->setAcceptTouchEvents(false); pixmapItem->setAcceptHoverEvents(false); pixmapItem->setEnabled(false); pixmapItem->setFlags(QGraphicsItem::ItemIgnoresTransformations); CursorItems.insert(scene, pixmapItem); scene->addItem(pixmapItem); scene->installEventFilter(this); } pixmapItem->setPixmap(*cursor.mask()); pixmapItem->setPos(view->mapToScene(view->mapFromGlobal(QCursor::pos())) + cursor.hotSpot()); */ if (Listeners.contains(object)) { if (Listeners.first() != object) { Listeners.removeOne(object); Listeners.push_front(object); } //DebugDialog::debug(QString("changing cursor %1").arg((long) object)); QApplication::changeOverrideCursor(cursor); return; } Listeners.push_front(object); connect(object, SIGNAL(destroyed(QObject *)), this, SLOT(deleteCursor(QObject *))); QApplication::setOverrideCursor(cursor); //DebugDialog::debug(QString("addding cursor %1").arg((long) object)); } void CursorMaster::removeCursor(QObject * object) { if (object == NULL) return; if (Listeners.contains(object)) { disconnect(object, SIGNAL(destroyed(QObject *)), this, SLOT(deleteCursor(QObject *))); Listeners.removeOne(object); QApplication::restoreOverrideCursor(); //DebugDialog::debug(QString("removing cursor %1").arg((long) object)); } /* QGraphicsItem * item = dynamic_cast(object); if (item == NULL) return; QGraphicsScene * scene = item->scene(); if (scene == NULL) return; QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL); if (pixmapItem == NULL) return; pixmapItem->hide(); */ } void CursorMaster::deleteCursor(QObject * object) { removeCursor(object); } bool CursorMaster::eventFilter(QObject * object, QEvent * event) { Q_UNUSED(object); //QGraphicsScene * scene = NULL; switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: //scene = dynamic_cast(object); //DebugDialog::debug(QString("event filter %1").arg(object->metaObject()->className())); //if (scene) { QKeyEvent *keyEvent = static_cast(event); foreach (QObject * listener, Listeners) { if (listener) { dynamic_cast(listener)->cursorKeyEvent(keyEvent->modifiers()); break; } } } break; /* case QEvent::GraphicsSceneMouseMove: scene = dynamic_cast(object); if (scene) { QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL); if (pixmapItem) { timer.setProperty("loc", ((QGraphicsSceneMouseEvent *) event)->scenePos()); timer.setUserData(1, (QObjectUserData *) pixmapItem); } } break; case QEvent::Leave: scene = dynamic_cast(object); if (scene) { QGraphicsPixmapItem * pixmapItem = CursorItems.value(scene, NULL); if (pixmapItem) { //DebugDialog::debug("pos", ((QGraphicsSceneMouseEvent *) event)->scenePos()); pixmapItem->hide(); } } break; */ default: break; } return false; } void CursorMaster::moveCursor() { //QObject * t = sender(); //if (t == NULL) return; //QPointF p = t->property("loc").toPointF(); //QGraphicsPixmapItem * item = (QGraphicsPixmapItem *) t->userData(1); //DebugDialog::debug("move", p); //item->setPos(p); // + cursor->hotspot //item->show(); } void CursorMaster::block() { m_blocked = true; } void CursorMaster::unblock() { m_blocked = false; } fritzing-app-0.9.2b/src/utils/cursormaster.h000066400000000000000000000040361250202676700211410ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6141 $: $Author: cohen@irascible.com $: $Date: 2012-07-04 21:20:05 +0200 (Mi, 04. Jul 2012) $ ********************************************************************/ #ifndef CURSORMASTER_H #define CURSORMASTER_H #include #include class CursorKeyListener { public: virtual void cursorKeyEvent(Qt::KeyboardModifiers) = 0; }; class CursorMaster : public QObject { Q_OBJECT protected: CursorMaster(); public: static CursorMaster * instance(); static void initCursors(); void addCursor(QObject * listener, const QCursor & cursor); void removeCursor(QObject * listener); void block(); void unblock(); protected: bool eventFilter(QObject *obj, QEvent *event); protected slots: void deleteCursor(QObject *); void moveCursor(); public: static void cleanup(); public: static QCursor * BendpointCursor; static QCursor * NewBendpointCursor; static QCursor * MakeWireCursor; static QCursor * MakeCurveCursor; static QCursor * RubberbandCursor; static QCursor * MoveCursor; static QCursor * BendlegCursor; static QCursor * RotateCursor; static QCursor * ScaleCursor; protected: static CursorMaster TheCursorMaster; bool m_blocked; }; #endif fritzing-app-0.9.2b/src/utils/expandinglabel.cpp000066400000000000000000000041371250202676700217220ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "expandinglabel.h" ExpandingLabel::ExpandingLabel(QWidget *parent, int minSize) : QTextEdit(parent) { setMinimumWidth(minSize); setReadOnly(true); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } void ExpandingLabel::setLabelText(const QString& theText) { document()->setHtml(theText); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setAlignment(Qt::AlignCenter); setContextMenuPolicy(Qt::NoContextMenu); } void ExpandingLabel::allTextVisible() { QTextDocument *doc = document(); doc->setTextWidth(width()); int height = doc->documentLayout()->documentSize().toSize().height(); setFixedHeight(height); } void ExpandingLabel::mouseMoveEvent(QMouseEvent * event) { QAbstractScrollArea::mouseMoveEvent(event); } void ExpandingLabel::mousePressEvent(QMouseEvent *event) { emit mousePressSignal(event); QAbstractScrollArea::mousePressEvent(event); } void ExpandingLabel::mouseReleaseEvent(QMouseEvent *event) { emit mouseReleaseSignal(event); QAbstractScrollArea::mouseReleaseEvent(event); } fritzing-app-0.9.2b/src/utils/expandinglabel.h000066400000000000000000000032141250202676700213620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef EXPANDINGLABEL_H_ #define EXPANDINGLABEL_H_ #include #include #include #include "../debugdialog.h" class ExpandingLabel : public QTextEdit { Q_OBJECT public: ExpandingLabel(QWidget *parent, int minSize=100); void setLabelText(const QString& theText); public slots: void allTextVisible(); signals: void mousePressSignal(QMouseEvent *event); void mouseReleaseSignal(QMouseEvent *event); protected: void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); }; #endif /* EXPANDINGLABEL_H_ */ fritzing-app-0.9.2b/src/utils/familypropertycombobox.h000066400000000000000000000034021250202676700232230ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FAMILYPROPERTYCOMBOBOX_H #define FAMILYPROPERTYCOMBOBOX_H #include #include "../debugdialog.h" #include "focusoutcombobox.h" class FamilyPropertyComboBox : public FocusOutComboBox { Q_OBJECT public: FamilyPropertyComboBox(const QString & family, const QString & prop, QWidget * parent = 0) : FocusOutComboBox(parent) { m_family = family; m_prop = prop; setEditable(false); } ~FamilyPropertyComboBox() { } void hidePopup() { //DebugDialog::debug(QString("hide popup %1").arg((long) this, 0, 16)); QComboBox::hidePopup(); } const QString & prop() { return m_prop; } const QString & family() { return m_family; } protected: QString m_family; QString m_prop; }; #endif fritzing-app-0.9.2b/src/utils/fileprogressdialog.cpp000066400000000000000000000143441250202676700226320ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "fileprogressdialog.h" #include "../debugdialog.h" #include "../processeventblocker.h" #include #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////// FileProgressDialog::FileProgressDialog(const QString & title, int initialMaximum, QWidget * parent) : QDialog(parent) { m_incValueMod = 2; QSplashScreen *splash = NULL; foreach (QWidget *widget, QApplication::topLevelWidgets()) { splash = qobject_cast(widget); if (splash) { break; } } init(title, initialMaximum); setModal(splash == NULL); // OS X Lion doesn't seem to like modal dialogs during splash time show(); if (splash) { QRect sr = splash->geometry(); QRect r = this->geometry(); QRect fr = this->frameGeometry(); int offset = sr.bottom() - r.top() + (fr.height() - r.height()); r.adjust(0, offset, 0, offset); this->setGeometry(r); } ProcessEventBlocker::processEvents(); } FileProgressDialog::FileProgressDialog(QWidget *parent) : QDialog(parent) { init(QObject::tr("File Progress..."), 0); } FileProgressDialog::~FileProgressDialog() { m_timer.stop(); } void FileProgressDialog::init(const QString & title, int initialMaximum) { Qt::WindowFlags flags = windowFlags(); flags |= Qt::CustomizeWindowHint; flags ^= Qt::WindowCloseButtonHint; flags ^= Qt::WindowSystemMenuHint; flags ^= Qt::WindowContextHelpButtonHint; //flags ^= Qt::WindowTitleHint; setWindowFlags(flags); this->setWindowTitle(title); QVBoxLayout * vLayout = new QVBoxLayout(this); m_message = new QLabel(this); m_message->setMinimumWidth(300); vLayout->addWidget(m_message); m_progressBar = new QProgressBar(this); m_progressBar->setMinimum(0); m_progressBar->setMaximum(initialMaximum); vLayout->addWidget(m_progressBar); //QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel); //buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); //buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); //connect(buttonBox, SIGNAL(rejected()), this, SLOT(sendCancel())); //vLayout->addWidget(buttonBox); this->setLayout(vLayout); } void FileProgressDialog::setMinimum(int minimum) { m_progressBar->setMinimum(minimum); } void FileProgressDialog::setMaximum(int maximum) { m_progressBar->setMaximum(maximum); //DebugDialog::debug(QString("set maximum:%1").arg(maximum)); } void FileProgressDialog::addMaximum(int maximum) { if (maximum != 0) { m_progressBar->setMaximum(m_progressBar->maximum() + maximum); //DebugDialog::debug(QString("set maximum:%1").arg(maximum)); } } void FileProgressDialog::setValue(int value) { m_progressBar->setValue(value); ProcessEventBlocker::processEvents(); } void FileProgressDialog::incValue() { m_progressBar->setValue(m_progressBar->value() + 1); if (m_progressBar->value() % m_incValueMod == 0) { ProcessEventBlocker::processEvents(); } } int FileProgressDialog::value() { return m_progressBar->value(); } void FileProgressDialog::sendCancel() { emit cancel(); } void FileProgressDialog::closeEvent(QCloseEvent *event) { event->ignore(); } void FileProgressDialog::setMessage(const QString & message) { m_message->setText(message); ProcessEventBlocker::processEvents(); } void FileProgressDialog::setBinLoadingCount(int count) { m_binLoadingCount = count; m_binLoadingIndex = -1; m_binLoadingStart = value(); } void FileProgressDialog::setBinLoadingChunk(int chunk) { m_binLoadingChunk = chunk; } void FileProgressDialog::loadingInstancesSlot(class ModelBase *, QDomElement & instances) { m_binLoadingValue = m_binLoadingStart + (++m_binLoadingIndex * m_binLoadingChunk / (double) m_binLoadingCount); setValue(m_binLoadingValue); int count = instances.childNodes().count(); // * 3 comes from: once for model part load, once for list view, once for icon view m_binLoadingInc = m_binLoadingChunk / (double) (m_binLoadingCount * 3 * count); } void FileProgressDialog::loadingInstanceSlot(class ModelBase *, QDomElement & instance) { Q_UNUSED(instance); //QString text; //QTextStream textStream(&text); //instance.save(textStream, 0); //DebugDialog::debug(QString("loading %1").arg(text)); //DebugDialog::debug(QString("loading %1").arg(instance.attribute("path"))); settingItemSlot(); } void FileProgressDialog::settingItemSlot() { m_binLoadingValue += m_binLoadingInc; if ((int) m_binLoadingValue > value()) { setValue(m_binLoadingValue); } } void FileProgressDialog::resizeEvent(QResizeEvent * event) { QDialog::resizeEvent(event); QRect scr = QApplication::desktop()->screenGeometry(); move( scr.center() - rect().center() ); } void FileProgressDialog::setIncValueMod(int mod) { m_incValueMod = mod; } void FileProgressDialog::setIndeterminate() { m_progressBar->setRange(0, 0); m_timer.setSingleShot(false); m_timer.setInterval(1000); connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateIndeterminate())); m_timer.start(); } void FileProgressDialog::updateIndeterminate() { if (m_progressBar) { m_progressBar->setValue(0); } } fritzing-app-0.9.2b/src/utils/fileprogressdialog.h000066400000000000000000000045441250202676700223000ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FILEPROGRESSDIALOG_H #define FILEPROGRESSDIALOG_H #include #include #include #include #include class FileProgressDialog : public QDialog { Q_OBJECT public: FileProgressDialog(QWidget *parent = 0); FileProgressDialog(const QString & title, int initialMaximum, QWidget *parent); ~FileProgressDialog(); int value(); void setBinLoadingCount(int); void setBinLoadingChunk(int); void setIncValueMod(int); void setIndeterminate(); protected: void closeEvent(QCloseEvent *); void resizeEvent(QResizeEvent *); public slots: void setMinimum(int); void setMaximum(int); void addMaximum(int); void setValue(int); void incValue(); void setMessage(const QString & message); void sendCancel(); void loadingInstancesSlot(class ModelBase *, QDomElement & instances); void loadingInstanceSlot(class ModelBase *, QDomElement & instance); void settingItemSlot(); protected slots: void updateIndeterminate(); signals: void cancel(); protected: void init(const QString & title, int initialMaximum); protected: QProgressBar * m_progressBar; QLabel * m_message; int m_binLoadingCount; int m_binLoadingIndex; int m_binLoadingStart; int m_binLoadingChunk; int m_incValueMod; double m_binLoadingInc; double m_binLoadingValue; QTimer m_timer; }; #endif fritzing-app-0.9.2b/src/utils/flineedit.cpp000066400000000000000000000033661250202676700207130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "flineedit.h" FLineEdit::FLineEdit(QWidget * parent) : QLineEdit(parent) { editingFinishedSlot(); connect(this, SIGNAL(editingFinished()), this, SLOT(editingFinishedSlot())); } FLineEdit::~FLineEdit() { } void FLineEdit::editingFinishedSlot() { m_readOnly = true; emit editable(false); setCursor(Qt::IBeamCursor); } void FLineEdit::mousePressEvent ( QMouseEvent * event ) { if (m_readOnly) { m_readOnly = false; emit editable(true); } QLineEdit::mousePressEvent(event); } void FLineEdit::enterEvent(QEvent * event) { QLineEdit::enterEvent(event); if (m_readOnly) { emit mouseEnter(); } } void FLineEdit::leaveEvent(QEvent * event) { QLineEdit::leaveEvent(event); if (m_readOnly) { emit mouseLeave(); } } fritzing-app-0.9.2b/src/utils/flineedit.h000066400000000000000000000030331250202676700203470ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FLINEEDIT_H #define FLINEEDIT_H #include #include class FLineEdit : public QLineEdit { Q_OBJECT public: FLineEdit(QWidget * parent = NULL); ~FLineEdit(); protected: void mousePressEvent( QMouseEvent * event ); void enterEvent( QEvent *); void leaveEvent( QEvent *); signals: void mouseEnter(); void mouseLeave(); void editable(bool); protected slots: void editingFinishedSlot(); protected: bool m_readOnly; // was using readOnly() but mac didn't like it }; #endif fritzing-app-0.9.2b/src/utils/fmessagebox.cpp000066400000000000000000000055771250202676700212610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "fmessagebox.h" #include "../debugdialog.h" bool FMessageBox::BlockMessages = false; FMessageBox::FMessageBox(QWidget * parent) : QMessageBox(parent) { } int FMessageBox::exec() { if (BlockMessages) return QMessageBox::Cancel; return QMessageBox::exec(); } QMessageBox::StandardButton FMessageBox::critical( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons, StandardButton defaultButton) { if (BlockMessages) { DebugDialog::debug("critcal " + title); DebugDialog::debug(text); return QMessageBox::Cancel; } return QMessageBox::critical(parent, title, text, buttons, defaultButton); } QMessageBox::StandardButton FMessageBox::information( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons, StandardButton defaultButton) { if (BlockMessages) { DebugDialog::debug("information " + title); DebugDialog::debug(text); return QMessageBox::Cancel; } return QMessageBox::information(parent, title, text, buttons, defaultButton); } QMessageBox::StandardButton FMessageBox::question( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons, StandardButton defaultButton) { if (BlockMessages) { DebugDialog::debug("question " + title); DebugDialog::debug(text); return QMessageBox::Cancel; } return QMessageBox::question(parent, title, text, buttons, defaultButton); } QMessageBox::StandardButton FMessageBox::warning( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons, StandardButton defaultButton) { if (BlockMessages) { DebugDialog::debug("warning " + title); DebugDialog::debug(text); return QMessageBox::Cancel; } return QMessageBox::warning(parent, title, text, buttons, defaultButton); } fritzing-app-0.9.2b/src/utils/fmessagebox.h000066400000000000000000000037631250202676700207210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FMESSAGEBOX_H #define FMESSAGEBOX_H #include class FMessageBox : public QMessageBox { Q_OBJECT public: FMessageBox ( QWidget * parent = 0 ); int exec (); public: static QMessageBox::StandardButton critical ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ); static QMessageBox::StandardButton information ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ); static QMessageBox::StandardButton question ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ); static QMessageBox::StandardButton warning ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ); public: static bool BlockMessages; }; #endif fritzing-app-0.9.2b/src/utils/focusoutcombobox.cpp000066400000000000000000000047101250202676700223420ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "focusoutcombobox.h" #include "../debugdialog.h" FocusOutComboBox::FocusOutComboBox(QWidget * parent) : QComboBox(parent) { setEditable(true); m_wasOut = true; lineEdit()->installEventFilter( this ); } FocusOutComboBox::~FocusOutComboBox() { } void FocusOutComboBox::focusInEvent(QFocusEvent * e) { //DebugDialog::debug("focus in"); QComboBox::focusInEvent(e); checkSelectAll(); } void FocusOutComboBox::focusOutEvent(QFocusEvent * e) { //DebugDialog::debug("focus out"); m_wasOut = true; QComboBox::focusOutEvent(e); QString t = this->currentText(); QString it = this->itemText(this->currentIndex()); if (t.compare(it) != 0) { int ix = findText(t); if (ix == -1) { addItem(t); ix = count() - 1; } setCurrentIndex(ix); } } bool FocusOutComboBox::eventFilter( QObject *target, QEvent *event ) { // subclassing mouseReleaseEvent doesn't seem to work so use eventfilter instead if( target == lineEdit() && event->type() == QEvent::MouseButtonRelease ) { if (m_wasOut) { // only select all the first time the focused lineEdit is clicked, not every time, // otherwise you can't move the selection point with the mouse checkSelectAll(); m_wasOut = false; } } return false; } void FocusOutComboBox::checkSelectAll() { if(lineEdit() && !lineEdit()->hasSelectedText() && isEnabled()) { lineEdit()->selectAll(); } } fritzing-app-0.9.2b/src/utils/focusoutcombobox.h000066400000000000000000000027671250202676700220210ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FOCUSOUTCOMBOBOX_H #define FOCUSOUTCOMBOBOX_H #include #include #include #include class FocusOutComboBox : public QComboBox { Q_OBJECT public: FocusOutComboBox(QWidget * parent = NULL); ~FocusOutComboBox(); protected: void focusInEvent(QFocusEvent *); void focusOutEvent(QFocusEvent *); bool eventFilter( QObject *target, QEvent *event ); void checkSelectAll(); protected: bool m_wasOut; }; #endif fritzing-app-0.9.2b/src/utils/folderutils.cpp000066400000000000000000000453351250202676700213060ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 7004 $: $Author: irascibl@gmail.com $: $Date: 2013-04-29 13:10:59 +0200 (Mo, 29. Apr 2013) $ ********************************************************************/ #include "folderutils.h" #include "lockmanager.h" #include "textutils.h" #include #include #include #include #include #include #include #include #include #include #include "../debugdialog.h" #ifdef QUAZIP_INSTALLED #include #include #else #include "../lib/quazip/quazip.h" #include "../lib/quazip/quazipfile.h" #endif #include "../lib/qtsysteminfo/QtSystemInfo.h" FolderUtils* FolderUtils::singleton = NULL; QString FolderUtils::m_openSaveFolder = ""; FolderUtils::FolderUtils() { m_openSaveFolder = ___emptyString___; m_folders << "/bins" << "/partfactory" << "/parts/user" << "/parts/contrib" << "/parts/svg/user/icon" << "/parts/svg/user/breadboard" << "/parts/svg/user/schematic" << "/parts/svg/user/pcb" << "/parts/svg/contrib/icon" << "/parts/svg/contrib/breadboard" << "/parts/svg/contrib/schematic" << "/parts/svg/contrib/pcb" << "/backup" << "/fzz"; } FolderUtils::~FolderUtils() { } // finds a subfolder of the application directory searching backward up the tree QDir * FolderUtils::getApplicationSubFolder(QString search) { if (singleton == NULL) { singleton = new FolderUtils(); } QString path = singleton->applicationDirPath(); path += "/" + search; //DebugDialog::debug(QString("path %1").arg(path) ); QDir* dir= new QDir(path); while (!dir->exists()) { // if we're running from the debug or release folder, go up one to find things dir->cdUp(); dir->cdUp(); if (dir->isRoot()) return NULL; // didn't find the search folder dir->setPath(dir->absolutePath() + "/" + search); } return dir; } QString FolderUtils::getApplicationSubFolderPath(QString search) { if (singleton == NULL) { singleton = new FolderUtils(); } QDir * dir = getApplicationSubFolder(search); if (dir == NULL) return ""; QString result = dir->path(); delete dir; return result; } QString FolderUtils::getUserDataStorePath(QString folder) { QString settingsFile = QSettings(QSettings::IniFormat,QSettings::UserScope,"Fritzing","Fritzing").fileName(); return QFileInfo(settingsFile).dir() .absolutePath()+(folder.isEmpty()?"":QString("/")+folder); } const QStringList & FolderUtils::getUserDataStoreFolders() { if (singleton == NULL) { singleton = new FolderUtils(); } return singleton->userDataStoreFolders(); } bool FolderUtils::createFolderAnCdIntoIt(QDir &dir, QString newFolder) { if(!dir.mkdir(newFolder)) return false; if(!dir.cd(newFolder)) return false; return true; } bool FolderUtils::setApplicationPath(const QString & path) { if (singleton == NULL) { singleton = new FolderUtils(); } return singleton->setApplicationPath2(path); } void FolderUtils::cleanup() { if (singleton) { delete singleton; singleton = NULL; } } const QString FolderUtils::getLibraryPath() { if (singleton == NULL) { singleton = new FolderUtils(); } return singleton->libraryPath(); } const QString FolderUtils::libraryPath() { #ifdef Q_OS_MAC // mac plugins are always in the bundle return QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../lib"); #endif return QDir::cleanPath(applicationDirPath() + "/lib"); } const QString FolderUtils::applicationDirPath() { if (m_appPath.isEmpty()) { #ifdef Q_OS_WIN return QCoreApplication::applicationDirPath(); #else // look in standard Fritzing location (applicationDirPath and parent folders) then in standard linux locations QStringList candidates; candidates.append(QCoreApplication::applicationDirPath()); QDir dir(QCoreApplication::applicationDirPath()); if (dir.cdUp()) { candidates.append(dir.absolutePath()); if (dir.cdUp()) { candidates.append(dir.absolutePath()); if (dir.cdUp()) { candidates.append(dir.absolutePath()); } } } #ifdef PKGDATADIR candidates.append(QLatin1String(PKGDATADIR)); #else candidates.append("/usr/share/fritzing"); candidates.append("/usr/local/share/fritzing"); #endif candidates.append(QDir::homePath() + "/.local/share/fritzing"); foreach (QString candidate, candidates) { //DebugDialog::debug(QString("candidate:%1").arg(candidate)); QDir dir(candidate); if (!dir.exists("parts")) continue; if (dir.exists("bins")) { m_appPath = candidate; return m_appPath; } } m_appPath = QCoreApplication::applicationDirPath(); DebugDialog::debug("data folders not found"); #endif } return m_appPath; } bool FolderUtils::setApplicationPath2(const QString & path) { QDir dir(path); if (!dir.exists()) return false; m_appPath = path; return true; } const QStringList & FolderUtils::userDataStoreFolders() { return m_folders; } void FolderUtils::setOpenSaveFolder(const QString& path) { setOpenSaveFolderAux(path); QSettings settings; settings.setValue("openSaveFolder", m_openSaveFolder); } void FolderUtils::setOpenSaveFolderAux(const QString& path) { QFileInfo fileInfo(path); if(fileInfo.isDir()) { m_openSaveFolder = path; } else { m_openSaveFolder = fileInfo.path().remove(fileInfo.fileName()); } } const QString FolderUtils::openSaveFolder() { if(m_openSaveFolder.isEmpty()) { QSettings settings; QString tempFolder = settings.value("openSaveFolder").toString(); if (!tempFolder.isEmpty()) { QFileInfo fileInfo(tempFolder); if (fileInfo.exists()) { m_openSaveFolder = tempFolder; return m_openSaveFolder; } else { settings.remove("openSaveFolder"); } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) DebugDialog::debug(QString("default save location: %1").arg(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation))); return QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); #else DebugDialog::debug(QString("default save location: %1").arg(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation))); return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); #endif } else { return m_openSaveFolder; } } QString FolderUtils::getOpenFileName( QWidget * parent, const QString & caption, const QString & dir, const QString & filter, QString * selectedFilter, QFileDialog::Options options ) { QString result = QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options); if (!result.isNull()) { setOpenSaveFolder(result); } return result; } QStringList FolderUtils::getOpenFileNames( QWidget * parent, const QString & caption, const QString & dir, const QString & filter, QString * selectedFilter, QFileDialog::Options options ) { QStringList result = QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options); if (result.count() > 0) { setOpenSaveFolder(result.at(0)); } return result; } QString FolderUtils::getSaveFileName( QWidget * parent, const QString & caption, const QString & dir, const QString & filter, QString * selectedFilter, QFileDialog::Options options ) { //DebugDialog::debug(QString("getopenfilename %1 %2 %3 %4").arg(caption).arg(dir).arg(filter).arg(*selectedFilter)); QString result = QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options); if (!result.isNull()) { setOpenSaveFolder(result); } return result; } bool FolderUtils::isEmptyFileName(const QString &fileName, const QString &untitledFileName) { return (fileName.isEmpty() || fileName.isNull() || fileName.startsWith(untitledFileName)); } void FolderUtils::replicateDir(QDir srcDir, QDir targDir) { // copy all files from srcDir source to tagDir QStringList files = srcDir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot); for(int i=0; i < files.size(); i++) { QFile tempFile(srcDir.path() + "/" +files.at(i)); DebugDialog::debug(QObject::tr("Copying file %1").arg(tempFile.fileName())); QFileInfo fi(files.at(i)); QString newFilePath = targDir.path() + "/" + fi.fileName(); if(QFileInfo(tempFile.fileName()).isDir()) { QDir newTargDir = QDir(newFilePath); newTargDir.mkpath(newTargDir.absolutePath()); newTargDir.cd(files.at(i)); replicateDir(QDir(tempFile.fileName()),newTargDir); } else { if(!tempFile.copy(newFilePath)) { DebugDialog::debug(QObject::tr("File %1 already exists: it won't be overwritten").arg(newFilePath)); } } } } // NOTE: This function cannot remove directories that have non-empty name filters set on it. void FolderUtils::rmdir(const QString &dirPath) { QDir dir = QDir(dirPath); rmdir(dir); } void FolderUtils::rmdir(QDir & dir) { //DebugDialog::debug(QString("removing folder: %1").arg(dir.path())); QStringList files = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot); for(int i=0; i < files.size(); i++) { QFile tempFile(dir.path() + "/" +files.at(i)); //DebugDialog::debug(QString("removing from original folder: %1").arg(tempFile.fileName())); if(QFileInfo(tempFile.fileName()).isDir()) { QDir dir = QDir(tempFile.fileName()); rmdir(dir); } else { tempFile.remove(tempFile.fileName()); } } dir.rmdir(dir.path()); } bool FolderUtils::createZipAndSaveTo(const QDir &dirToCompress, const QString &filepath, const QStringList & skipSuffixes) { DebugDialog::debug("zipping "+dirToCompress.path()+" into "+filepath); QString tempZipFile = QDir::temp().path()+"/"+TextUtils::getRandText()+".zip"; DebugDialog::debug("temp file: "+tempZipFile); QuaZip zip(tempZipFile); if(!zip.open(QuaZip::mdCreate)) { qWarning("zip.open(): %d", zip.getZipError()); return false; } QFileInfoList files=dirToCompress.entryInfoList(); QFile inFile; QuaZipFile outFile(&zip); char c; QString currFolderBU = QDir::currentPath(); QDir::setCurrent(dirToCompress.path()); foreach(QFileInfo file, files) { if(!file.isFile()||file.fileName()==filepath) continue; if (file.fileName().contains(LockManager::LockedFileName)) continue; bool skip = false; foreach (QString suffix, skipSuffixes) { if (file.fileName().endsWith(suffix)) { skip = true; break; } } if (skip) continue; //#pragma message("remove fzz check") //if (file.fileName().endsWith(".fzz")) continue; inFile.setFileName(file.fileName()); if(!inFile.open(QIODevice::ReadOnly)) { qWarning("inFile.open(): %s", inFile.errorString().toLocal8Bit().constData()); return false; } if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(inFile.fileName(), inFile.fileName()))) { qWarning("outFile.open(): %d", outFile.getZipError()); return false; } while(inFile.getChar(&c)&&outFile.putChar(c)){} if(outFile.getZipError()!=UNZ_OK) { qWarning("outFile.putChar(): %d", outFile.getZipError()); return false; } outFile.close(); if(outFile.getZipError()!=UNZ_OK) { qWarning("outFile.close(): %d", outFile.getZipError()); return false; } inFile.close(); } zip.close(); QDir::setCurrent(currFolderBU); if(QFileInfo(filepath).exists()) { // if we're here the usr has already accepted to overwrite QFile::remove(filepath); } QFile file(tempZipFile); FolderUtils::slamCopy(file, filepath); file.remove(); if(zip.getZipError()!=0) { qWarning("zip.close(): %d", zip.getZipError()); return false; } return true; } bool FolderUtils::unzipTo(const QString &filepath, const QString &dirToDecompress, QString & error) { static QChar badCharacters[] = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }; static QChar underscore('_'); QuaZip zip(filepath); if(!zip.open(QuaZip::mdUnzip)) { error = QString("zip.open(): %d").arg(zip.getZipError()); DebugDialog::debug(error); return false; } zip.setFileNameCodec("IBM866"); DebugDialog::debug(QString("unzipping %1 entries from %2").arg(zip.getEntriesCount()).arg(filepath)); QuaZipFileInfo info; QuaZipFile file(&zip); QFile out; QString name; char c; for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { if(!zip.getCurrentFileInfo(&info)) { error = QString("getCurrentFileInfo(): %d\n").arg(zip.getZipError()); DebugDialog::debug(error); return false; } if(!file.open(QIODevice::ReadOnly)) { error = QString("file.open(): %d").arg(file.getZipError()); DebugDialog::debug(error); return false; } name=file.getActualFileName(); if(file.getZipError()!=UNZ_OK) { error = QString("file.getFileName(): %d").arg(file.getZipError()); DebugDialog::debug(error); return false; } out.setFileName(dirToDecompress+"/"+name); // this will fail if "name" contains subdirectories, but we don't mind that if(!out.open(QIODevice::WriteOnly)) { for (int i = 0; i < name.length(); i++) { if (name[i].unicode() < 32) { name.replace(i, 1, &underscore, 1); } else for (unsigned int j = 0; j < (sizeof(badCharacters) / sizeof(QChar)); j++) { if (name[i] == badCharacters[j]) { name.replace(i, 1, &underscore, 1); break; } } } out.setFileName(dirToDecompress+"/"+name); if(!out.open(QIODevice::WriteOnly)) { error = QString("out.open(): %s").arg(out.errorString().toLocal8Bit().constData()); DebugDialog::debug(error); return false; } } // Slow like hell (on GNU/Linux at least), but it is not my fault. // Not ZIP/UNZIP package's fault either. // The slowest thing here is out.putChar(c). // TODO: now that out.putChar has been replaced with a buffered write, is it still slow under Linux? #define BUFFERSIZE 1024 char buffer[BUFFERSIZE]; int ix = 0; while(file.getChar(&c)) { buffer[ix++] = c; if (ix == BUFFERSIZE) { out.write(buffer, ix); ix = 0; } } if (ix > 0) { out.write(buffer, ix); } out.close(); if(file.getZipError()!=UNZ_OK) { error = QString("file.getFileName(): %d").arg(file.getZipError()); DebugDialog::debug(error); return false; } if(!file.atEnd()) { error = "read all but not EOF"; DebugDialog::debug(error); return false; } file.close(); if(file.getZipError()!=UNZ_OK) { error = QString("file.close(): %d").arg(file.getZipError()); DebugDialog::debug(error); return false; } } zip.close(); if(zip.getZipError()!=UNZ_OK) { error = QString("zip.close(): %d").arg(zip.getZipError()); DebugDialog::debug(error); return false; } return true; } void FolderUtils::collectFiles(const QDir & parent, QStringList & filters, QStringList & files, bool recursive) { QFileInfoList fileInfoList = parent.entryInfoList(filters, QDir::Files | QDir::Hidden | QDir::NoSymLinks); foreach (QFileInfo fileInfo, fileInfoList) { files.append(fileInfo.absoluteFilePath()); } if (recursive) { QFileInfoList dirList = parent.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks); foreach (QFileInfo dirInfo, dirList) { QDir dir(dirInfo.filePath()); //DebugDialog::debug(QString("looking in backup dir %1").arg(dir.absolutePath())); collectFiles(dir, filters, files, recursive); } } } void FolderUtils::makePartFolderHierarchy(const QString & prefixFolder, const QString & destFolder) { QDir dir(prefixFolder); dir.mkdir(destFolder); dir.mkdir("svg"); dir.cd("svg"); dir.mkdir(destFolder); dir.cd(destFolder); dir.mkdir("icon"); dir.mkdir("breadboard"); dir.mkdir("schematic"); dir.mkdir("pcb"); } void FolderUtils::copyBin(const QString & dest, const QString & source) { if(QFileInfo(dest).exists()) return; // this copy action, is not working on windows, because is a resources file if(!QFile(source).copy(dest)) { #ifdef Q_OS_WIN // may not be needed from qt 4.5.2 on DebugDialog::debug("Failed to copy a file from the resources"); QDir binsFolder = QFileInfo(dest).dir().absolutePath(); QStringList binFiles = binsFolder.entryList(QDir::AllEntries | QDir::NoDotAndDotDot); foreach(QString binName, binFiles) { if(binName.startsWith("qt_temp.")) { QString filePath = binsFolder.absoluteFilePath(binName); bool success = QFile(filePath).rename(dest); Q_UNUSED(success); break; } } #endif } QFlags ps = QFile::permissions(dest); QFile::setPermissions( dest, QFile::WriteOwner | QFile::WriteUser | ps #ifdef Q_OS_WIN | QFile::WriteOther | QFile::WriteGroup #endif ); } bool FolderUtils::slamCopy(QFile & file, const QString & dest) { QFileInfo info(file); if (info.absoluteFilePath() == dest) { // source = dest return true; } bool result = file.copy(dest); if (result) return result; file.remove(dest); return file.copy(dest); } void FolderUtils::showInFolder(const QString & path) { // http://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt // http://stackoverflow.com/questions/9581330/change-selection-in-explorer-window // Mac, Windows support folder or file. #if defined(Q_OS_WIN) const QString explorer = "explorer.exe"; QString param = QLatin1String("/e,/select,"); param += QDir::toNativeSeparators(path); QProcess::startDetached(explorer, QStringList(param)); #elif defined(Q_OS_MAC) QStringList scriptArgs; scriptArgs << QLatin1String("-e") << QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"") .arg(path); QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs); scriptArgs.clear(); scriptArgs << QLatin1String("-e") << QLatin1String("tell application \"Finder\" to activate"); QProcess::execute("/usr/bin/osascript", scriptArgs); #else QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo(path).absolutePath() ) ); #endif } fritzing-app-0.9.2b/src/utils/folderutils.h000066400000000000000000000070661250202676700207520ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef FOLDERUTILS_H #define FOLDERUTILS_H #include #include #include #include #include "misc.h" class FolderUtils { public: static QDir *getApplicationSubFolder(QString); static QString getApplicationSubFolderPath(QString); static QString getUserDataStorePath(QString folder = ___emptyString___); static const QStringList & getUserDataStoreFolders(); static bool createFolderAnCdIntoIt(QDir &dir, QString newFolder); static bool setApplicationPath(const QString & path); static const QString getLibraryPath(); static QString getOpenFileName( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, QFileDialog::Options options = 0 ); static QStringList getOpenFileNames( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, QFileDialog::Options options = 0 ); static QString getSaveFileName( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, QFileDialog::Options options = 0 ); static void setOpenSaveFolder(const QString& path); static void setOpenSaveFolderAux(const QString& path); static const QString openSaveFolder(); static bool isEmptyFileName(const QString &filename, const QString &unsavedFilename); static void rmdir(const QString &dirPath); static void rmdir(QDir & dir); static bool createZipAndSaveTo(const QDir &dirToCompress, const QString &filename, const QStringList & skipSuffixes); static bool unzipTo(const QString &filepath, const QString &dirToDecompress, QString & error); static void replicateDir(QDir srcDir, QDir targDir); static void cleanup(); static void collectFiles(const QDir & parent, QStringList & filters, QStringList & files, bool recursive); static void makePartFolderHierarchy(const QString & prefixFolder, const QString & destFolder); static void copyBin(const QString & source, const QString & dest); static bool slamCopy(QFile &, const QString & dest); static void showInFolder(const QString & path); protected: FolderUtils(); ~FolderUtils(); const QStringList & userDataStoreFolders(); bool setApplicationPath2(const QString & path); const QString applicationDirPath(); const QString libraryPath(); protected: static FolderUtils* singleton; static QString m_openSaveFolder; protected: QStringList m_folders; QString m_appPath; }; #endif fritzing-app-0.9.2b/src/utils/fsizegrip.cpp000066400000000000000000000025141250202676700207440ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "fsizegrip.h" #include "misc.h" FSizeGrip::FSizeGrip(QMainWindow *parent) : QSizeGrip(parent) { m_mainWindow = parent; resize(sizeHint()); rearrange(); } void FSizeGrip::rearrange() { int x = m_mainWindow->width()-this->width(); int y = m_mainWindow->height()-this->height(); move(x,y); raise(); } fritzing-app-0.9.2b/src/utils/fsizegrip.h000066400000000000000000000024201250202676700204050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef FSIZEGRIP_H_ #define FSIZEGRIP_H_ #include #include class FSizeGrip : public QSizeGrip { public: FSizeGrip(QMainWindow *parent); void rearrange(); protected: QMainWindow *m_mainWindow; }; #endif /* FSIZEGRIP_H_ */ fritzing-app-0.9.2b/src/utils/graphicsutils.cpp000066400000000000000000000366141250202676700216330ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6926 $: $Author: irascibl@gmail.com $: $Date: 2013-03-10 21:27:34 +0100 (So, 10. Mrz 2013) $ ********************************************************************/ #include "graphicsutils.h" #include #include #include #include #include const double GraphicsUtils::IllustratorDPI = 72; const double GraphicsUtils::StandardFritzingDPI = 1000; const double GraphicsUtils::SVGDPI = 90; const double GraphicsUtils::InchesPerMeter = 39.370078; const double GraphicsUtils::StandardSchematicSeparationMils = 295.275591; // 7.5mm const double GraphicsUtils::StandardSchematicSeparation10thinMils = 100; // 0.1 inches void GraphicsUtils::distanceFromLine(double cx, double cy, double ax, double ay, double bx, double by, double & dx, double & dy, double &distanceSegment, bool & atEndpoint) { // http://www.codeguru.com/forum/showthread.php?t=194400 // // find the distance from the point (cx,cy) to the line // determined by the points (ax,ay) and (bx,by) // double r_numerator = (cx-ax)*(bx-ax) + (cy-ay)*(by-ay); double r_denomenator = (bx-ax)*(bx-ax) + (by-ay)*(by-ay); double r = r_numerator / r_denomenator; if ( (r >= 0) && (r <= 1) ) { dx = ax + r*(bx-ax); dy = ay + r*(by-ay); distanceSegment = (cx-dx)*(cx-dx) + (cy-dy)*(cy-dy); atEndpoint = false; } else { atEndpoint = true; double dist1 = (cx-ax)*(cx-ax) + (cy-ay)*(cy-ay); double dist2 = (cx-bx)*(cx-bx) + (cy-by)*(cy-by); if (dist1 < dist2) { dx = ax; dy = ay; distanceSegment = dist1; } else { dx = bx; dy = by; distanceSegment = dist2; } } return; } struct PD { QPointF p; double d; }; bool pdLessThan(PD* pd1, PD* pd2) { return pd1->d < pd2->d; } QPointF GraphicsUtils::calcConstraint(QPointF initial, QPointF current) { QList pds; PD * pd = new PD; pd->p.setX(current.x()); pd->p.setY(initial.y()); pd->d = (current.y() - initial.y()) * (current.y() - initial.y()); pds.append(pd); pd = new PD; pd->p.setX(initial.x()); pd->p.setY(current.y()); pd->d = (current.x() - initial.x()) * (current.x() - initial.x()); pds.append(pd); double dx, dy, d; bool atEndpoint; QLineF plus45(initial.x() - 10000, initial.y() - 10000, initial.x() + 10000, initial.y() + 10000); distanceFromLine(current.x(), current.y(), plus45.p1().x(), plus45.p1().y(), plus45.p2().x(), plus45.p2().y(), dx, dy, d, atEndpoint); pd = new PD; pd->p.setX(dx); pd->p.setY(dy); pd->d = d; pds.append(pd); QLineF minus45(initial.x() + 10000, initial.y() - 10000, initial.x() - 10000, initial.y() + 10000); distanceFromLine(current.x(), current.y(), minus45.p1().x(), minus45.p1().y(), minus45.p2().x(), minus45.p2().y(), dx, dy, d, atEndpoint); pd = new PD; pd->p.setX(dx); pd->p.setY(dy); pd->d = d; pds.append(pd); qSort(pds.begin(), pds.end(), pdLessThan); QPointF result = pds[0]->p; foreach (PD* pd, pds) { delete pd; } return result; } double GraphicsUtils::pixels2mils(double p, double dpi) { return p * 1000.0 / dpi; } double GraphicsUtils::pixels2ins(double p, double dpi) { return p / dpi; } double GraphicsUtils::distanceSqd(QPointF p1, QPointF p2) { return ((p1.x() - p2.x()) * (p1.x() - p2.x())) + ((p1.y() - p2.y()) * (p1.y() - p2.y())); } double GraphicsUtils::distanceSqd(QPoint p1, QPoint p2) { double dpx = p1.x() - p2.x(); double dpy = p1.y() - p2.y(); return (dpx * dpx) + (dpy * dpy); } double GraphicsUtils::mm2mils(double mm) { return (mm / 25.4 * 1000); } double GraphicsUtils::mm2pixels(double mm) { return (90 * mm / 25.4); } double GraphicsUtils::pixels2mm(double p, double dpi) { return (p / dpi * 25.4); } double GraphicsUtils::mils2pixels(double m, double dpi) { return (dpi * m / 1000); } void GraphicsUtils::saveTransform(QXmlStreamWriter & streamWriter, const QTransform & transform) { if (transform.isIdentity()) return; streamWriter.writeStartElement("transform"); streamWriter.writeAttribute("m11", QString::number(transform.m11())); streamWriter.writeAttribute("m12", QString::number(transform.m12())); streamWriter.writeAttribute("m13", QString::number(transform.m13())); streamWriter.writeAttribute("m21", QString::number(transform.m21())); streamWriter.writeAttribute("m22", QString::number(transform.m22())); streamWriter.writeAttribute("m23", QString::number(transform.m23())); streamWriter.writeAttribute("m31", QString::number(transform.m31())); streamWriter.writeAttribute("m32", QString::number(transform.m32())); streamWriter.writeAttribute("m33", QString::number(transform.m33())); streamWriter.writeEndElement(); } bool GraphicsUtils::loadTransform(const QDomElement & transformElement, QTransform & transform) { if (transformElement.isNull()) return false; double m11 = transform.m11(); double m12 = transform.m12(); double m13 = transform.m13(); double m21 = transform.m21(); double m22 = transform.m22(); double m23 = transform.m23(); double m31 = transform.m31(); double m32 = transform.m32(); double m33 = transform.m33(); bool ok; double temp; temp = transformElement.attribute("m11").toDouble(&ok); if (ok) m11 = temp; temp = transformElement.attribute("m12").toDouble(&ok); if (ok) m12 = temp; temp = transformElement.attribute("m13").toDouble(&ok); if (ok) m13 = temp; temp = transformElement.attribute("m21").toDouble(&ok); if (ok) m21 = temp; temp = transformElement.attribute("m22").toDouble(&ok); if (ok) m22 = temp; temp = transformElement.attribute("m23").toDouble(&ok); if (ok) m23 = temp; temp = transformElement.attribute("m31").toDouble(&ok); if (ok) m31 = temp; temp = transformElement.attribute("m32").toDouble(&ok); if (ok) m32 = temp; temp = transformElement.attribute("m33").toDouble(&ok); if (ok) m33 = temp; transform.setMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33); return true; } double GraphicsUtils::getNearestOrdinate(double ordinate, double units) { double lo = qFloor(ordinate / units) * units; double hi = qCeil(ordinate / units) * units; return (qAbs(lo - ordinate) <= qAbs(hi - ordinate)) ? lo : hi; } void GraphicsUtils::shortenLine(QPointF & p1, QPointF & p2, double d1, double d2) { double angle1 = atan2(p2.y() - p1.y(), p2.x() - p1.x()); double angle2 = angle1 - M_PI; double dx1 = d1 * cos(angle1); double dy1 = d1 * sin(angle1); double dx2 = d2 * cos(angle2); double dy2 = d2 * sin(angle2); p1.setX(p1.x() + dx1); p1.setY(p1.y() + dy1); p2.setX(p2.x() + dx2); p2.setY(p2.y() + dy2); } bool GraphicsUtils::isRect(const QPolygonF & poly) { if (poly.count() != 5) return false; if (poly.at(0) != poly.at(4)) return false; // either we start running across top or running along side if (poly.at(0).x() == poly.at(1).x() && poly.at(1).y() == poly.at(2).y() && poly.at(2).x() == poly.at(3).x() && poly.at(3).y() == poly.at(4).y()) return true; if (poly.at(0).y() == poly.at(1).y() && poly.at(1).x() == poly.at(2).x() && poly.at(2).y() == poly.at(3).y() && poly.at(3).x() == poly.at(4).x()) return true; return false; } QRectF GraphicsUtils::getRect(const QPolygonF & poly) { // assumes poly is known to be a rect double minX, maxX, minY, maxY; minX = maxX = poly.at(0).x(); minY = maxY = poly.at(0).y(); for (int i = 1; i < 4; i++) { QPointF p = poly.at(i); if (p.x() > maxX) maxX = p.x(); if (p.x() < minX) minX = p.x(); if (p.y() > maxY) maxY = p.y(); if (p.y() < minY) minY = p.y(); } return QRectF(minX, minY, maxX - minX, maxY - minY); } // based on code from http://code-heaven.blogspot.com/2009/05/c-program-for-liang-barsky-line.html bool GraphicsUtils::liangBarskyLineClip(double x1, double y1, double x2, double y2, double wxmin, double wxmax, double wymin, double wymax, double & x11, double & y11, double & x22, double & y22) { double p1 = -(x2 - x1 ); double q1 = x1 - wxmin; double p2 = ( x2 - x1 ); double q2 = wxmax - x1; double p3 = - ( y2 - y1 ); double q3 = y1 - wymin; double p4 = ( y2 - y1 ); double q4 = wymax - y1; x11 = x1; y11 = y1; x22 = x2; y22 = y2; if( ( ( p1 == 0.0 ) && ( q1 < 0.0 ) ) || ( ( p2 == 0.0 ) && ( q2 < 0.0 ) ) || ( ( p3 == 0.0 ) && ( q3 < 0.0 ) ) || ( ( p4 == 0.0 ) && ( q4 < 0.0 ) ) ) { return false; } double u1 = 0.0, u2 = 1.0; if( p1 != 0.0 ) { double r1 = q1 /p1 ; if( p1 < 0 ) u1 = qMax(r1, u1 ); else u2 = qMin(r1, u2 ); } if( p2 != 0.0 ) { double r2 = q2 /p2 ; if( p2 < 0 ) u1 = qMax(r2, u1 ); else u2 = qMin(r2, u2 ); } if( p3 != 0.0 ) { double r3 = q3 /p3 ; if( p3 < 0 ) u1 = qMax(r3, u1 ); else u2 = qMin(r3, u2 ); } if( p4 != 0.0 ) { double r4 = q4 /p4 ; if( p4 < 0 ) u1 = qMax(r4, u1 ); else u2 = qMin(r4, u2 ); } if( u1 > u2 ) { return false; } x11 = x1 + u1 * ( x2 - x1 ) ; y11 = y1 + u1 * ( y2 - y1 ) ; x22 = x1 + u2 * ( x2 - x1 ); y22 = y1 + u2 * ( y2 - y1 ); return true; } QString GraphicsUtils::toHtmlImage(QPixmap *pixmap, const char* format) { QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap->save(&buffer, format); // writes pixmap into bytes in PNG format return QString("data:image/%1;base64,%2").arg(QString(format).toLower()).arg(QString(bytes.toBase64())); } QPainterPath GraphicsUtils::shapeFromPath(const QPainterPath &path, const QPen &pen, double shapeStrokeWidth, bool includeOriginalPath) { // this function mostly copied from QGraphicsItem::qt_graphicsItem_shapeFromPath // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 // if we pass a value of 0.0 to QPainterPathStroker::setWidth() static const double penWidthZero = double(0.00000001); if (path == QPainterPath()) return path; QPainterPathStroker ps; ps.setCapStyle(pen.capStyle()); //ps.setCapStyle(Qt::FlatCap); if (shapeStrokeWidth <= 0.0) ps.setWidth(penWidthZero); else ps.setWidth(shapeStrokeWidth); ps.setJoinStyle(pen.joinStyle()); ps.setMiterLimit(pen.miterLimit()); QPainterPath p = ps.createStroke(path); if (includeOriginalPath) { p.addPath(path); } return p; } void GraphicsUtils::qt_graphicsItem_highlightSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF & boundingRect, const QPainterPath & path) { const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1)); if (qFuzzyCompare(qMax(murect.width(), murect.height()) + 1, 1)) return; const QRectF mbrect = painter->transform().mapRect(boundingRect); if (qMin(mbrect.width(), mbrect.height()) < double(1.0)) return; double itemPenWidth = 1.0; const double pad = itemPenWidth / 2; const double penWidth = 0; // cosmetic pen const QColor fgcolor = option->palette.windowText().color(); const QColor bgcolor( // ensure good contrast against fgcolor fgcolor.red() > 127 ? 0 : 255, fgcolor.green() > 127 ? 0 : 255, fgcolor.blue() > 127 ? 0 : 255); painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine)); painter->setBrush(Qt::NoBrush); if (path.isEmpty()) { painter->drawRect(boundingRect.adjusted(pad, pad, -pad, -pad)); } else { painter->drawPath(path); } painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine)); painter->setBrush(Qt::NoBrush); if (path.isEmpty()) { painter->drawRect(boundingRect.adjusted(pad, pad, -pad, -pad)); } else { painter->drawPath(path); } } QPointF GraphicsUtils::calcRotation(QTransform & rotation, QPointF rCenter, QPointF p, QPointF pCenter) { QPointF dp = rCenter - p; QTransform tp = QTransform().translate(-dp.x(), -dp.y()) * rotation * QTransform().translate(dp.x(), dp.y()); QTransform tc = QTransform().translate(-pCenter.x(), -pCenter.y()) * rotation * QTransform().translate(pCenter.x(), pCenter.y()); QPointF mp = tp.map(QPointF(0,0)); QPointF mc = tc.map(QPointF(0,0)); return (p + mp - mc); } void GraphicsUtils::drawBorder(QImage * image, int border) { int halfBorder = border / 2; QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); QPen pen = painter.pen(); pen.setWidth(border); pen.setColor(0xff000000); painter.setPen(pen); painter.drawLine(0, halfBorder, image->width() - 1, halfBorder); painter.drawLine(0, image->height() - halfBorder, image->width() - 1, image->height() - halfBorder); painter.drawLine(halfBorder, 0, halfBorder, image->height() - 1); painter.drawLine(image->width() - halfBorder, 0, image->width() - halfBorder, image->height() - 1); painter.end(); } bool almostEqual(qreal a, qreal b) { static qreal nearly = 0.001; return (qAbs(a - b) < nearly); } bool GraphicsUtils::isFlipped(const QMatrix & matrix, double & rotation) { static qreal halfSqrt2 = 0.7071; // flipped means flipped horizontally (around the vertical axis) // rotation values are ccw and upright is zero if (almostEqual(matrix.m11(), 1.0)) { if (almostEqual(matrix.m22(), 1.0)) { rotation = 0; return false; } rotation = 180; return true; } if (almostEqual(matrix.m11(), -1.0)) { if (almostEqual(matrix.m22(), -1.0)) { rotation = 180; return false; } rotation = 0; return true; } if (almostEqual(matrix.m12(), 1.0)) { if (almostEqual(matrix.m21(), -1.0)) { rotation = 90; return false; } rotation = 270; return true; } if (almostEqual(matrix.m12(), -1.0)) { if (almostEqual(matrix.m21(), 1)) { rotation = 270; return false; } rotation = 90; return true; } if (almostEqual(matrix.m11(), halfSqrt2)) { if (almostEqual(matrix.m22(), halfSqrt2)) { if (almostEqual(matrix.m12(), -halfSqrt2)) { rotation = 315; return false; } rotation = 45; return false; } if (almostEqual(matrix.m12(), halfSqrt2)) { rotation = 225; return true; } rotation = 135; return true; } if (almostEqual(matrix.m11(), -halfSqrt2)) { if (almostEqual(matrix.m22(), -halfSqrt2)) { if (almostEqual(matrix.m12(), -halfSqrt2)) { rotation = 225; return false; } rotation = 135; return false; } if (almostEqual(matrix.m12(), -halfSqrt2)) { rotation = 45; return true; } rotation = 315; return true; } qWarning() << QString("unknown matrix %1 %2 %3 %4").arg(matrix.m11()).arg(matrix.m12()).arg(matrix.m21()).arg(matrix.m22()); rotation = 0; return false; } fritzing-app-0.9.2b/src/utils/graphicsutils.h000066400000000000000000000066271250202676700213010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef GRAPHICSUTILS_H #define GRAPHICSUTILS_H #include #include #include #include #include #include #include #include #include #include #include class GraphicsUtils { public: static void distanceFromLine(double cx, double cy, double ax, double ay, double bx, double by, double & dx, double & dy, double &distanceSegment, bool & atEndpoint); static QPointF calcConstraint(QPointF initial, QPointF current); static double pixels2mils(double p, double dpi); static double pixels2ins(double p, double dpi); static double distanceSqd(QPointF p1, QPointF p2); static double distanceSqd(QPoint p1, QPoint p2); static double getNearestOrdinate(double ordinate, double units); static double mm2mils(double mm); static double pixels2mm(double p, double dpi); static double mm2pixels(double mm); static double mils2pixels(double m, double dpi); static void saveTransform(QXmlStreamWriter & streamWriter, const QTransform & transform); static bool loadTransform(const QDomElement & transformElement, QTransform & transform); static bool isRect(const QPolygonF & poly); static QRectF getRect(const QPolygonF & poly); static void shortenLine(QPointF & p1, QPointF & p2, double d1, double d2); static bool liangBarskyLineClip(double x1, double y1, double x2, double y2, double wxmin, double wxmax, double wymin, double wymax, double & x11, double & y11, double & x22, double & y22); static QString toHtmlImage(QPixmap *pixmap, const char* format = "PNG"); static QPainterPath shapeFromPath(const QPainterPath &path, const QPen &pen, double shapeStrokeWidth, bool includeOriginalPath); static void qt_graphicsItem_highlightSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF & boundingRect, const QPainterPath & path); static QPointF calcRotation(QTransform & rotation, QPointF rCenter, QPointF p, QPointF pCenter); static void drawBorder(QImage * image, int border); static bool isFlipped(const QMatrix & matrix, double & rotation); public: static const double IllustratorDPI; static const double StandardFritzingDPI; static const double SVGDPI; static const double InchesPerMeter; static const double StandardSchematicSeparationMils; static const double StandardSchematicSeparation10thinMils; }; #endif fritzing-app-0.9.2b/src/utils/graphutils.cpp000066400000000000000000000473501250202676700211330ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6954 $: $Author: irascibl@gmail.com $: $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $ ********************************************************************/ #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4503) #pragma warning(disable:4100) // disable scary-looking compiler warnings in Boost library #pragma warning(disable:4181) #endif #include #include #include // #include // kolmogorov_max_flow is probably more efficient, but it doesn't compile #include #include #ifdef _MSC_VER #pragma warning(pop) // restore warning state #endif #include "graphutils.h" #include "../fsvgrenderer.h" #include "../items/wire.h" #include "../items/jumperitem.h" #include "../sketch/sketchwidget.h" #include "../debugdialog.h" void ConnectorEdge::setHeadTail(int h, int t) { head = h; tail = t; } ConnectorEdge * makeConnectorEdge(QList & edges, ConnectorItem * ci, ConnectorItem * cj, int weight, Wire * wire) { ConnectorEdge * connectorEdge = new ConnectorEdge; connectorEdge->c0 = ci; connectorEdge->c1 = cj; connectorEdge->weight = weight; connectorEdge->wire = wire; connectorEdge->visible = true; edges.append(connectorEdge); return connectorEdge; } static int LastVertex = 0; #define appendVertIf(ci, vertices, verts) { \ int ix = vertices.value(ci, -1); \ if (ix == -1) { \ ix = vertices.count(); \ vertices.insert(ci, ix); \ verts.append(add_vertex(g)); \ } \ LastVertex = ix; \ } void GraphUtils::minCut(QList & connectorItems, QList & foreignSketchWidgets, ConnectorItem * source, ConnectorItem * sink, QList & minCut) { // this helped: http://boost.2283326.n4.nabble.com/graph-edmund-karp-max-flow-vs-kolmogorov-max-flow-color-map-td2565611.html using namespace boost; typedef adjacency_list_traits < vecS, vecS, directedS > Traits; typedef property < vertex_color_t, boost::default_color_type > COLOR; typedef property < vertex_index_t, long, COLOR > VERTEX; typedef property < edge_reverse_t, Traits::edge_descriptor > REVERSE; typedef property < edge_residual_capacity_t, long, REVERSE > RESIDUAL; typedef property < edge_capacity_t, long, RESIDUAL > EDGE; typedef adjacency_list < listS, vecS, directedS, VERTEX, EDGE > Graph; Graph g; property_map < Graph, edge_capacity_t >::type capacity = get(edge_capacity, g); property_map < Graph, edge_residual_capacity_t >::type residual_capacity = get(edge_residual_capacity, g); property_map < Graph, edge_reverse_t >::type reverse = get(edge_reverse, g); property_map < Graph, vertex_color_t >::type color = get(vertex_color, g); property_map < Graph, vertex_index_t >::type index = get(vertex_index, g); Traits::vertex_descriptor s, t; QList visitedWires; QList indexes; QHash vertices; QList edges; QVector verts; vertices.insert(source, 0); vertices.insert(sink, 1); verts.append(s = add_vertex(g)); verts.append(t = add_vertex(g)); foreach (ConnectorItem * connectorItem, connectorItems) { //connectorItem->debugInfo("input"); if (connectorItem->attachedToItemType() == ModelPart::Wire) { Wire * wire = qobject_cast(connectorItem->attachedTo()); if (visitedWires.contains(wire)) continue; QList wires; QList ends; wire->collectChained(wires, ends); visitedWires.append(wires); if (ends.count() < 2) continue; foreach (ConnectorItem * end, ends) { appendVertIf(end, vertices, verts); } for (int i = 0; i < ends.count(); i++) { ConnectorItem * end = ends[i]; for (int j = i + 1; j < ends.count(); j++) { ConnectorEdge * connectorEdge = makeConnectorEdge(edges, end, ends[j], 1000, wire); connectorEdge->setHeadTail(vertices.value(connectorEdge->c0), vertices.value(connectorEdge->c1)); } } continue; } if (connectorItem->connectorType() == Connector::Female) { appendVertIf(connectorItem, vertices, verts); int ix = LastVertex; foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) { if (toConnectorItem->attachedToItemType() == ModelPart::Wire) { // deal with the wire continue; } appendVertIf(toConnectorItem, vertices, verts); int jx = LastVertex; ConnectorEdge * connectorEdge = makeConnectorEdge(edges, connectorItem, toConnectorItem, 1000, NULL); connectorEdge->setHeadTail(ix, jx); } } } // don't forget to add edges from bus connections QList originalKeys = vertices.keys(); // make cross-view connections QList foreignEdges; foreach (ConnectorEdge * ce, edges) { if (ce->wire && !ce->wire->isEverVisible()) { ce->visible = false; foreach (SketchWidget * foreignSketchWidget, foreignSketchWidgets) { ItemBase * foreignItemBase = foreignSketchWidget->findItem(ce->wire->id()); if (foreignItemBase && foreignItemBase->isEverVisible()) { ConnectorItem * fc0 = foreignSketchWidget->findConnectorItem(ce->c0); ConnectorItem * fc1 = foreignSketchWidget->findConnectorItem(ce->c1); if (fc0 && fc1) { appendVertIf(fc0, vertices, verts); int ix = LastVertex; appendVertIf(fc1, vertices, verts); int jx = LastVertex; ConnectorEdge * fce = makeConnectorEdge(foreignEdges, fc0, fc1, 1, qobject_cast(foreignItemBase)); fce->setHeadTail(ix, jx); fce = makeConnectorEdge(foreignEdges, ce->c0, fc0, 1000, NULL); fce->setHeadTail(ce->head, ix); fce = makeConnectorEdge(foreignEdges, ce->c1, fc1, 1000, NULL); fce->setHeadTail(ce->tail, jx); } else { ce->c0->debugInfo("missing foreign connector"); } break; } } } if (ce->wire) continue; if (!ce->c0->attachedTo()->isEverVisible()) { ce->visible = false; foreach (SketchWidget * foreignSketchWidget, foreignSketchWidgets) { ConnectorItem * fc0 = foreignSketchWidget->findConnectorItem(ce->c0); if (fc0 == NULL) { ce->c0->debugInfo("missing foreign connector"); continue; } if (!fc0->attachedTo()->isEverVisible()) continue; ConnectorItem * fc1 = foreignSketchWidget->findConnectorItem(ce->c1); if (fc0 && fc1) { appendVertIf(fc0, vertices, verts); int ix = LastVertex; appendVertIf(fc1, vertices, verts); int jx = LastVertex; ConnectorEdge * fce = makeConnectorEdge(foreignEdges, fc0, fc1, 1, NULL); fce->setHeadTail(ix, jx); fce = makeConnectorEdge(foreignEdges, ce->c0, fc0, 1000, NULL); fce->setHeadTail(ce->head, ix); fce = makeConnectorEdge(foreignEdges, ce->c1, fc1, 1000, NULL); fce->setHeadTail(ce->tail, jx); } else { ce->c0->debugInfo("missing foreign connector"); } } } } while (originalKeys.count() > 0) { ConnectorItem * key = originalKeys.takeFirst(); if (key->attachedToItemType() == ModelPart::Wire) continue; if (key->bus() == NULL) continue; int ix = vertices.value(key); QList bcis; key->attachedTo()->busConnectorItems(key->bus(), key, bcis); foreach (ConnectorItem * bci, bcis) { if (bci == key) continue; originalKeys.removeOne(bci); appendVertIf(bci, vertices, verts); int jx = LastVertex; ConnectorEdge * connectorEdge = makeConnectorEdge(edges, key, bci, 1000, NULL); connectorEdge->setHeadTail(ix, jx); } } edges.append(foreignEdges); // add cross-layer edges QList crossVisited; foreach (ConnectorEdge * ce, edges) { QList from; from << ce->c0; from << ce->c1; foreach (ConnectorItem * ci, from) { if (!crossVisited.contains(ci)) { ConnectorItem * cross = ci->getCrossLayerConnectorItem(); if (cross == NULL) continue; appendVertIf(cross, vertices, verts); int jx = LastVertex; ConnectorEdge * connectorEdge = makeConnectorEdge(edges, ci, cross, 1000, NULL); connectorEdge->setHeadTail(vertices.value(ci), jx); } } } //foreach(ConnectorItem * connectorItem, vertices.keys()) { // connectorItem->debugInfo(QString("vertex %1").arg(vertices.value(connectorItem))); //} foreach(ConnectorEdge * ce, edges) { if (!ce->visible) continue; Traits::edge_descriptor e1, e2; bool in1, in2; tie(e1, in1) = add_edge(verts[ce->head], verts[ce->tail], g); tie(e2, in2) = add_edge(verts[ce->tail], verts[ce->head], g); capacity[e2] = capacity[e1] = ce->weight; reverse[e1] = e2; reverse[e2] = e1; //ce->c0->debugInfo(QString("head %1").arg(ce->weight)); //ce->c1->debugInfo("\ttail"); } /* foreach(ConnectorEdge * ce, edges) { connectorItems.at(ce->head)->debugInfo(QString("%1").arg(ce->weight)); } DebugDialog::debug(""); DebugDialog::debug(""); foreach(ConnectorEdge * ce, edges) { partConnectorItems.at(ce->tail)->debugInfo(QString("%1").arg(ce->weight)); } */ // if color_map parameter not specified, colors are not set long flow = edmonds_karp_max_flow(g, s, t, color_map(color)); Q_UNUSED(flow); //DebugDialog::debug(QString("flow %1, s%2, t%3").arg(flow).arg(index(s)).arg(index(t))); //for (int i = 0; i < verts.count(); ++i) { // DebugDialog::debug(QString("index %1 %2").arg(index(verts[i])).arg(color(verts[i]))); //} typedef property_traits::type>::value_type tColorValue; typedef boost::color_traits tColorTraits; foreach (ConnectorEdge * ce, edges) { bool addIt = false; if (ce->visible) { if (color(verts[ce->head]) == tColorTraits::white() && color(verts[ce->tail]) != tColorTraits::white()) { addIt = true; } else if (color(verts[ce->head]) != tColorTraits::white() && color(verts[ce->tail]) == tColorTraits::white()) { addIt = true; } if (addIt) { minCut << ce; //DebugDialog::debug(QString("edge %1 %2 w:%3").arg(ce->head).arg(ce->tail).arg(ce->weight)); } } else { delete ce; } } } bool GraphUtils::chooseRatsnestGraph(const QList * partConnectorItems, ViewGeometry::WireFlags flags, ConnectorPairHash & result) { using namespace boost; typedef adjacency_list < vecS, vecS, undirectedS, property, property < edge_weight_t, double > > Graph; typedef std::pair < int, int >E; if (partConnectorItems->count() < 2) return false; QList temp(*partConnectorItems); //DebugDialog::debug("__________________"); int tix = 0; while (tix < temp.count()) { ConnectorItem * connectorItem = temp[tix++]; //connectorItem->debugInfo("check cross"); ConnectorItem * crossConnectorItem = connectorItem->getCrossLayerConnectorItem(); if (crossConnectorItem) { // it doesn't matter which one on which layer we remove // when we check equal potential both of them will be returned //crossConnectorItem->debugInfo("\tremove cross"); temp.removeOne(crossConnectorItem); } } QList locs; foreach (ConnectorItem * connectorItem, temp) { locs << connectorItem->sceneAdjustedTerminalPoint(NULL); } QList < QList > wiredTo; int num_nodes = temp.count(); int num_edges = num_nodes * (num_nodes - 1) / 2; E * edges = new E[num_edges]; double * weights = new double[num_edges]; int ix = 0; QVector< QVector > reverseWeights(num_nodes, QVector(num_nodes, 0)); for (int i = 0; i < num_nodes; i++) { ConnectorItem * c1 = temp.at(i); //c1->debugInfo("c1"); for (int j = i + 1; j < num_nodes; j++) { edges[ix].first = i; edges[ix].second = j; ConnectorItem * c2 = temp.at(j); if ((c1->attachedTo() == c2->attachedTo()) && (c1->bus() != NULL) && (c1->bus() == c2->bus())) { weights[ix++] = 0; continue; } bool already = false; bool checkWiredTo = true; foreach (QList list, wiredTo) { if (list.contains(c1)) { checkWiredTo = false; if (list.contains(c2)) { weights[ix++] = 0; already = true; } break; } } if (already) continue; //c2->debugInfo("\tc2"); if (checkWiredTo) { QList cwConnectorItems; cwConnectorItems.append(c1); ConnectorItem::collectEqualPotential(cwConnectorItems, true, flags); wiredTo.append(cwConnectorItems); //foreach (ConnectorItem * cx, cwConnectorItems) { //cx->debugInfo("\t\tcx"); //} if (cwConnectorItems.contains(c2)) { weights[ix++] = 0; continue; } } //DebugDialog::debug("c2 not eliminated"); double dx = locs[i].x() - locs[j].x(); double dy = locs[i].y() - locs[j].y(); weights[ix++] = reverseWeights[i][j] = reverseWeights[j][i] = (dx * dx) + (dy * dy); } } bool retval = false; try { Graph g(edges, edges + num_edges, weights, num_nodes); property_map::type weightmap = get(edge_weight, g); std::vector < graph_traits < Graph >::vertex_descriptor > p(num_vertices(g)); prim_minimum_spanning_tree(g, &p[0]); for (std::size_t i = 0; i != p.size(); ++i) { if (i == p[i]) continue; if (reverseWeights[i][p[i]] == 0) continue; result.insert(temp[i], temp[p[i]]); } retval = true; } catch ( const std::exception& e ) { // catch an error in boost 1.54 DebugDialog::debug(QString("boost spanning tree failure: %1").arg(e.what())); } catch(...) { DebugDialog::debug("boost spanning tree failure"); } delete edges; delete weights; return retval; } #define add_edge_d(i, j, g) \ add_edge(verts[i], verts[j], g); \ //partConnectorItems[i]->debugInfo(QString("edge from %1").arg(i)); //partConnectorItems[j]->debugInfo(QString("\tto %1").arg(j)); bool GraphUtils::scoreOneNet(QList & partConnectorItems, ViewGeometry::WireFlags myTrace, RoutingStatus & routingStatus) { using namespace boost; int num_nodes = partConnectorItems.count(); typedef property < vertex_index_t, std::size_t > Index; typedef adjacency_list < listS, listS, directedS, Index > graph_t; typedef graph_traits < graph_t >::vertex_descriptor vertex_t; typedef graph_traits < graph_t >::edge_descriptor edge_t; graph_t G; std::vector < vertex_t > verts(num_nodes); for (int i = 0; i < num_nodes; ++i) { verts[i] = add_vertex(Index(i), G); } //std::pair pair; bool gotUserConnection = false; for (int i = 0; i < num_nodes; i++) { add_edge_d(i, i, G); ConnectorItem * from = partConnectorItems[i]; for (int j = i + 1; j < num_nodes; j++) { ConnectorItem * to = partConnectorItems[j]; if (from->isCrossLayerConnectorItem(to)) { add_edge_d(i, j, G); add_edge_d(j, i, G); continue; } if (from->attachedToItemType() == ModelPart::Symbol && to->attachedToItemType() == ModelPart::Symbol && from->attachedTo()->isEverVisible() && to->attachedTo()->isEverVisible()) { // equipotential symbols are treated as if they were connected by wires add_edge_d(i, j, G); add_edge_d(j, i, G); gotUserConnection = true; continue; } if (to->attachedTo() != from->attachedTo()) { gotUserConnection = true; continue; } if ((to->bus() != NULL) && (to->bus() == from->bus())) { add_edge_d(i, j, G); add_edge_d(j, i, G); continue; } gotUserConnection = true; } } if (!gotUserConnection) { return false; } routingStatus.m_netCount++; for (int i = 0; i < num_nodes; i++) { ConnectorItem * fromConnectorItem = partConnectorItems[i]; if (fromConnectorItem->attachedToItemType() == ModelPart::Jumper) { routingStatus.m_jumperItemCount++; } foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) { switch (toConnectorItem->attachedToItemType()) { case ModelPart::Wire: break; case ModelPart::Breadboard: if (toConnectorItem->attachedTo()->isEverVisible()) { QList ends; collectBreadboard(toConnectorItem, partConnectorItems, ends); foreach (ConnectorItem * end, ends) { if (end == fromConnectorItem) continue; int j = partConnectorItems.indexOf(end); if (j >= 0) { add_edge_d(i, j, G); add_edge_d(j, i, G); } } } continue; } Wire * wire = qobject_cast(toConnectorItem->attachedTo()); if (wire == NULL) continue; if (!(wire->getViewGeometry().wireFlags() & myTrace)) { // don't add edge if the connection isn't traced with my kind of trace continue; } QList wires; QList ends; wire->collectChained(wires, ends); foreach (ConnectorItem * end, ends) { if (end == fromConnectorItem) continue; int j = partConnectorItems.indexOf(end); if (j >= 0) { add_edge_d(i, j, G); add_edge_d(j, i, G); } } } } adjacency_list <> TC; transitive_closure(G, TC); QVector check(num_nodes, true); bool anyMissing = false; for (int i = 0; i < num_nodes - 1; i++) { if (!check[i]) continue; check[i] = false; bool missingOne = false; for (int j = i + 1; j < num_nodes; j++) { if (!check[j]) continue; if (edge(i, j, TC).second) { check[j] = false; } else { // we can minimally span the set with n-1 wires, so even if multiple connections are missing from a given connector, count it as one anyMissing = missingOne = true; //ConnectorItem * ci = partConnectorItems.at(i); //ConnectorItem * cj = partConnectorItems.at(j); //ci->debugInfo("missing one ci"); //cj->debugInfo("\t\tcj"); } } if (missingOne) { routingStatus.m_connectorsLeftToRoute++; } } if (!anyMissing) { routingStatus.m_netRoutedCount++; } return true; } void GraphUtils::collectBreadboard(ConnectorItem * connectorItem, QList & partConnectorItems, QList & ends) { QList itemsToGo; itemsToGo.append(connectorItem); for (int i = 0; i < itemsToGo.count(); i++) { ConnectorItem * candidate = itemsToGo.at(i); if (partConnectorItems.contains(candidate)) { if (!ends.contains(candidate)) { ends.append(candidate); } continue; } Bus * bus = candidate->bus(); if (bus) { QList busConnectorItems; candidate->attachedTo()->busConnectorItems(bus, candidate, busConnectorItems); foreach (ConnectorItem * bci, busConnectorItems) { if (!itemsToGo.contains(bci)) { itemsToGo.append(bci); } } } foreach (ConnectorItem * to, candidate->connectedToItems()) { if (!itemsToGo.contains(to)) { itemsToGo.append(to); } } } } fritzing-app-0.9.2b/src/utils/graphutils.h000066400000000000000000000036771250202676700206040ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6145 $: $Author: cohen@irascible.com $: $Date: 2012-07-05 19:17:11 +0200 (Do, 05. Jul 2012) $ ********************************************************************/ #ifndef GRAPHUTILS_H #define GRAPHUTILS_H #include "../connectors/connectoritem.h" #include "../routingstatus.h" struct ConnectorEdge { int head; int tail; int weight; ConnectorItem * c0; ConnectorItem * c1; class Wire * wire; bool visible; void setHeadTail(int head, int tail); }; class GraphUtils { public: static bool chooseRatsnestGraph(const QList * equipotentials, ViewGeometry::WireFlags, ConnectorPairHash & result); static bool scoreOneNet(QList & partConnectorItems, ViewGeometry::WireFlags, RoutingStatus & routingStatus); static void minCut(QList & connectorItems, QList & foreighSketchWidgets, ConnectorItem * source, ConnectorItem * sink, QList & cutSet); protected: static void collectBreadboard(ConnectorItem * connectorItem, QList & partConnectorItems, QList & ends); }; #endif fritzing-app-0.9.2b/src/utils/lockmanager.cpp000066400000000000000000000147621250202676700212350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "lockmanager.h" #include "folderutils.h" #include "textutils.h" #include #include #include #include #include const QString LockManager::LockedFileName = "___lockfile___.txt"; const long LockManager::FastTime = 2000; const long LockManager::SlowTime = 240000; static LockManager TheLockManager; static QHash > TheTimers; static QMultiHash TheLockedFiles; static QMutex TheMutex; LockedFile::LockedFile(const QString & filename, long freq) { file.setFileName(filename); frequency = freq; } bool LockedFile::touch() { if (file.open(QFile::WriteOnly)) { file.write("a"); file.close(); return true; } return false; } ///////////////////////////////////////////////// LockManager::LockManager() : QObject() { } LockManager::~LockManager() { foreach (QTimer * timer, TheTimers) { if (timer) timer->stop(); } TheTimers.clear(); } void LockManager::cleanup() { foreach (QTimer * timer, TheTimers) { if (timer) { timer->stop(); delete timer; } } TheTimers.clear(); } void LockManager::touchFiles() { QTimer * timer = qobject_cast(sender()); if (timer == NULL) return; QMutexLocker locker(&TheMutex); foreach (LockedFile * lockedFile, TheLockedFiles.values(timer->interval())) { lockedFile->touch(); } } void LockManager::initLockedFiles(const QString & prefix, QString & folder, QHash & lockedFiles, long touchFrequency) { // first create our own unique folder and lock it QDir backupDir(FolderUtils::getUserDataStorePath(prefix)); QString lockedSubfolder = TextUtils::getRandText(); backupDir.mkdir(lockedSubfolder); folder = backupDir.absoluteFilePath(lockedSubfolder); if (touchFrequency > 0) { LockedFile * lockedFile = makeLockedFile(folder + "/" + LockedFileName, touchFrequency); lockedFiles.insert(lockedSubfolder, lockedFile); } } LockedFile * LockManager::makeLockedFile(const QString & path, long touchFrequency) { LockedFile * lockedFile = new LockedFile(path, touchFrequency); lockedFile->touch(); TheMutex.lock(); TheLockedFiles.insert(touchFrequency, lockedFile); TheMutex.unlock(); QTimer * timer = TheTimers.value(touchFrequency, NULL); if (timer == NULL) { timer = new QTimer(); timer->setInterval(touchFrequency); timer->setSingleShot(false); QObject::connect(timer, SIGNAL(timeout()), &TheLockManager, SLOT(touchFiles())); timer->start(); TheTimers.insert(touchFrequency, timer); } return lockedFile; } void LockManager::releaseLockedFiles(const QString & folder, QHash & lockedFiles) { // remove backup files; this is a clean exit releaseLockedFiles(folder, lockedFiles, true); } void LockManager::releaseLockedFiles(const QString & folder, QHash & lockedFiles, bool remove) { QDir backupDir(folder); backupDir.cdUp(); foreach (QString sub, lockedFiles.keys()) { LockedFile * lockedFile = lockedFiles.value(sub); TheMutex.lock(); TheLockedFiles.remove(lockedFile->frequency, lockedFile); TheMutex.unlock(); if (remove) { FolderUtils::rmdir(backupDir.absoluteFilePath(sub)); } delete lockedFile; } lockedFiles.clear(); } void LockManager::checkLockedFiles(const QString & prefix, QFileInfoList & backupList, QHash & lockedFiles, bool recurse, long touchFrequency) { QDir backupDir(FolderUtils::getUserDataStorePath(prefix)); QFileInfoList dirList = backupDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks); foreach (QFileInfo dirInfo, dirList) { QDir dir(dirInfo.filePath()); QStringList filters; //DebugDialog::debug(QString("looking in backup dir %1").arg(dir.absolutePath())); QFileInfoList fileInfoList = dir.entryInfoList(filters, QDir::Files | QDir::Hidden | QDir::NoSymLinks); bool gotRecurse = false; if (recurse && fileInfoList.isEmpty()) { gotRecurse = checkLockedFilesAux(dir, filters); } if (fileInfoList.isEmpty() && !gotRecurse) { // could mean this backup folder is just being created by another process // could also mean it's leftover crap. // check the date and only delete if it's old QDateTime lastModified = dirInfo.lastModified(); if (lastModified < QDateTime::currentDateTime().addMSecs(-2000 - touchFrequency)) { FolderUtils::rmdir(dirInfo.filePath()); } continue; } QFileInfo lockInfo(dir.absoluteFilePath(LockedFileName)); if (lockInfo.exists()) { QDateTime lastModified = lockInfo.lastModified(); if (lastModified >= QDateTime::currentDateTime().addMSecs(-2000 - touchFrequency)) { // somebody else owns the file continue; } } // we own the file QString folder; LockedFile * lockedFile = makeLockedFile(dir.absoluteFilePath(LockedFileName), touchFrequency); lockedFiles.insert(dirInfo.fileName(), lockedFile); foreach (QFileInfo fileInfo, fileInfoList) { backupList << fileInfo; } } } bool LockManager::checkLockedFilesAux(const QDir & parent, QStringList & filters) { QFileInfoList dirList = parent.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::NoSymLinks); foreach (QFileInfo dirInfo, dirList) { QDir dir(dirInfo.filePath()); //DebugDialog::debug(QString("looking in backup dir %1").arg(dir.absolutePath())); QFileInfoList fileInfoList = dir.entryInfoList(filters, QDir::Files | QDir::Hidden | QDir::NoSymLinks); if (!fileInfoList.isEmpty()) return true; if (checkLockedFilesAux(dir, filters)) return true; } return false; }fritzing-app-0.9.2b/src/utils/lockmanager.h000066400000000000000000000042651250202676700206770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6141 $: $Author: cohen@irascible.com $: $Date: 2012-07-04 21:20:05 +0200 (Mi, 04. Jul 2012) $ ********************************************************************/ #ifndef LOCKMANAGER_H #define LOCKMANAGER_H #include #include #include struct LockedFile { QFile file; long frequency; LockedFile(const QString & filename, long freq); bool touch(); }; class LockManager : public QObject { Q_OBJECT public: LockManager(); ~LockManager(); public: static void initLockedFiles(const QString & prefix, QString & folder, QHash & lockedFiles, long touchFrequency); static void releaseLockedFiles(const QString & folder, QHash & lockedFiles); static void checkLockedFiles(const QString & prefix, QFileInfoList & backupList, QHash & lockedFiles, bool recurse, long touchFrequency); static void cleanup(); public: static const QString LockedFileName; static const long FastTime; static const long SlowTime; public slots: void touchFiles(); protected: static bool checkLockedFilesAux(const QDir & parent, QStringList & filters); static void releaseLockedFiles(const QString & folder, QHash & lockedFiles, bool remove); static LockedFile * makeLockedFile(const QString & folder, long touchFrequency); }; #endif fritzing-app-0.9.2b/src/utils/misc.cpp000066400000000000000000000037271250202676700177040ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6181 $: $Author: cohen@irascible.com $: $Date: 2012-07-18 15:52:11 +0200 (Mi, 18. Jul 2012) $ ********************************************************************/ // misc Fritzing utility functions #include "misc.h" #include #include #include #include #include #include static QStringList ___fritzingExtensions___; const QStringList & fritzingExtensions() { if (___fritzingExtensions___.count() == 0) { ___fritzingExtensions___ << FritzingSketchExtension << FritzingBinExtension << FritzingPartExtension << FritzingBundleExtension << FritzingBundledPartExtension << FritzingBundledBinExtension; } return ___fritzingExtensions___; } bool isParent(QObject * candidateParent, QObject * candidateChild) { QObject * parent = candidateChild->parent(); while (parent) { if (parent == candidateParent) return true; parent = parent->parent(); } return false; } Qt::KeyboardModifier altOrMetaModifier() { #ifdef LINUX_32 return Qt::MetaModifier; #endif #ifdef LINUX_64 return Qt::MetaModifier; #endif return Qt::AltModifier; } fritzing-app-0.9.2b/src/utils/misc.h000066400000000000000000000067051250202676700173500ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef MISC_H #define MISC_H #include #include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) // TODO: this debugging hack seems to break in Qt 5; needs investigation #ifdef Q_OS_WIN #ifndef QT_NO_DEBUG #ifdef _MSC_VER // just for the MS compiler // windows hack for finding memory leaks // the 'new' redefinition breaks QHash and QVector so they are included beforehand. #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif #endif #endif #endif #ifdef Q_OS_WIN #define getenvUser() getenv("USERNAME") #else #define getenvUser() getenv("USER") #endif #include #include #include #include #include #include #include #define ALLMOUSEBUTTONS (Qt::LeftButton | Qt::MidButton | Qt::RightButton | Qt::XButton1 | Qt::XButton2) typedef QPair RealPair; static QString ___emptyString___; static QDomElement ___emptyElement___; static QStringList ___emptyStringList___; static QHash ___emptyStringHash___; static QDir ___emptyDir___; static QByteArray ___emptyByteArray___; static const QString OCRAFontName("OCRA"); static const QString ResourcePath(":/resources/"); bool isParent(QObject * candidateParent, QObject * candidateChild); static const QString FritzingSketchExtension(".fz"); static const QString FritzingBinExtension(".fzb"); static const QString FritzingBundledBinExtension(".fzbz"); static const QString FritzingPartExtension(".fzp"); static const QString FritzingBundledPartExtension(".fzpz"); static const QString FritzingBundleExtension(".fzz"); inline double qMin(float f, double d) { return qMin((double) f, d); } inline double qMin(double d, float f) { return qMin((double) f, d); } inline double qMax(float f, double d) { return qMax((double) f, d); } inline double qMax(double d, float f) { return qMax((double) f, d); } const QStringList & fritzingExtensions(); static const QString FemaleSymbolString = QString("%1").arg(QChar(0x2640)); static const QString MaleSymbolString = QString("%1").arg(QChar(0x2642)); Qt::KeyboardModifier altOrMetaModifier(); static QRegExp IntegerFinder("\\d+"); static const int PartsBinHeightDefault = 240; static const int InfoViewHeightDefault = 220; static const int InfoViewMinHeight = 50; static const int DockWidthDefault = 300; static const int DockHeightDefault = 50; #endif fritzing-app-0.9.2b/src/utils/ratsnestcolors.cpp000066400000000000000000000171021250202676700220260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #include "ratsnestcolors.h" #include "../debugdialog.h" #include QHash RatsnestColors::m_viewList; QHash RatsnestColors::m_allNames; QColor ErrorColor(0, 0, 0); ////////////////////////////////////////////////////// class RatsnestColor { RatsnestColor(const QDomElement &); ~RatsnestColor(); bool matchColor(const QString &); friend class RatsnestColors; protected: QString m_name; QString m_wire; QColor m_ratsnest; QString m_shadow; QStringList m_connectorNames; QList m_obsoleteList; }; ////////////////////////////////////////////////////// RatsnestColor::RatsnestColor(const QDomElement & color) { m_name = color.attribute("name"); //DebugDialog::debug("color name " + m_name); m_ratsnest.setNamedColor(color.attribute("ratsnest")); m_wire = color.attribute("wire"); m_shadow = color.attribute("shadow"); QDomElement connector = color.firstChildElement("connector"); while (!connector.isNull()) { m_connectorNames.append(connector.attribute("name")); connector = connector.nextSiblingElement("connector"); } QDomElement obsolete = color.firstChildElement("obsolete"); while (!obsolete.isNull()) { m_obsoleteList << new RatsnestColor(obsolete); obsolete = obsolete.nextSiblingElement("obsolete"); } } RatsnestColor::~RatsnestColor() { foreach (RatsnestColor * ratsnestColor, m_obsoleteList) { delete ratsnestColor; } m_obsoleteList.clear(); } bool RatsnestColor::matchColor(const QString & string) { if (m_wire.compare(string, Qt::CaseInsensitive) == 0) return true; foreach (RatsnestColor * obsolete, m_obsoleteList) { if (obsolete->m_wire.compare(string, Qt::CaseInsensitive) == 0) return true; } return false; } ////////////////////////////////////////////////////// RatsnestColors::RatsnestColors(const QDomElement & view) { m_viewID = ViewLayer::idFromXmlName(view.attribute("name")); m_backgroundColor.setNamedColor(view.attribute("background")); m_index = 0; QDomElement color = view.firstChildElement("color"); while (!color.isNull()) { RatsnestColor * ratsnestColor = new RatsnestColor(color); m_ratsnestColorHash.insert(ratsnestColor->m_name, ratsnestColor); m_ratsnestColorList.append(ratsnestColor); foreach (QString name, ratsnestColor->m_connectorNames) { m_allNames.insert(name.toLower(), ratsnestColor); } color = color.nextSiblingElement("color"); } } RatsnestColors::~RatsnestColors() { foreach (RatsnestColor * ratsnestColor, m_ratsnestColorHash.values()) { delete ratsnestColor; } m_ratsnestColorHash.clear(); m_ratsnestColorList.clear(); } void RatsnestColors::initNames() { QFile file(":/resources/ratsnestcolors.xml"); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { return; } if (root.tagName() != "colors") { return; } QDomElement view = root.firstChildElement("view"); while (!view.isNull()) { RatsnestColors * ratsnestColors = new RatsnestColors(view); m_viewList.insert(ratsnestColors->m_viewID, ratsnestColors); view = view.nextSiblingElement("view"); } } void RatsnestColors::cleanup() { foreach (RatsnestColors * ratsnestColors, m_viewList.values()) { delete ratsnestColors; } m_viewList.clear(); } const QColor & RatsnestColors::netColor(ViewLayer::ViewID viewID) { RatsnestColors * ratsnestColors = m_viewList.value(viewID, NULL); if (ratsnestColors == NULL) return ErrorColor; return ratsnestColors->getNextColor(); } const QColor & RatsnestColors::getNextColor() { if (m_ratsnestColorList.count() <= 0) return ErrorColor; int resetCount = 0; while (true) { if (m_index < 0 || m_index >= m_ratsnestColorList.count()) { m_index = 0; if (++resetCount > 2) { // prevent infinite loops if all the colors in the list are for particular connectors return ErrorColor; } } RatsnestColor * ratsnestColor = m_ratsnestColorList[m_index++]; if (ratsnestColor->m_connectorNames.length() > 0) { // don't use colors designated for particular connectors m_index++; continue; } if (!ratsnestColor->m_ratsnest.isValid()){ m_index++; continue; } return ratsnestColor->m_ratsnest; } } bool RatsnestColors::findConnectorColor(const QStringList & names, QColor & color) { foreach (QString name, names) { RatsnestColor * ratsnestColor = m_allNames.value(name.toLower(), NULL); if (ratsnestColor == NULL) continue; color = ratsnestColor->m_ratsnest; return true; } return false; } bool RatsnestColors::isConnectorColor(ViewLayer::ViewID m_viewID, const QColor & color) { RatsnestColors * ratsnestColors = m_viewList.value(m_viewID, NULL); if (ratsnestColors == NULL) return false; foreach (RatsnestColor * ratsnestColor, ratsnestColors->m_ratsnestColorList) { if (ratsnestColor->m_ratsnest == color) { return (ratsnestColor->m_connectorNames.length() > 0); } } return false; } void RatsnestColors::reset(ViewLayer::ViewID m_viewID) { RatsnestColors * ratsnestColors = m_viewList.value(m_viewID, NULL); if (ratsnestColors == NULL) return; ratsnestColors->m_index = 0; } QColor RatsnestColors::backgroundColor(ViewLayer::ViewID viewID) { RatsnestColors * ratsnestColors = m_viewList.value(viewID, NULL); if (ratsnestColors == NULL) return QColor(); return ratsnestColors->m_backgroundColor; } const QString & RatsnestColors::shadowColor(ViewLayer::ViewID viewID, const QString & name) { RatsnestColors * ratsnestColors = m_viewList.value(viewID, NULL); if (ratsnestColors == NULL) return ___emptyString___; RatsnestColor * ratsnestColor = ratsnestColors->m_ratsnestColorHash.value(name.toLower(), NULL); if (ratsnestColor == NULL) return ___emptyString___; return ratsnestColor->m_shadow; } QString RatsnestColors::wireColor(ViewLayer::ViewID viewID, QString & string) { RatsnestColors * ratsnestColors = m_viewList.value(viewID, NULL); if (ratsnestColors == NULL) return ___emptyString___; RatsnestColor * ratsnestColor = ratsnestColors->m_ratsnestColorHash.value(string.toLower(), NULL); if (ratsnestColor != NULL) { QString w = ratsnestColor->m_wire; if (!w.isEmpty()) return w; } // reverse lookup foreach (QString cname, ratsnestColors->m_ratsnestColorHash.keys()) { RatsnestColor * candidate = ratsnestColors->m_ratsnestColorHash.value(cname); if (candidate->matchColor(string)) { string = cname; return candidate->m_wire; } } return ___emptyString___; } fritzing-app-0.9.2b/src/utils/ratsnestcolors.h000066400000000000000000000041571250202676700215010ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6912 $: $Author: irascibl@gmail.com $: $Date: 2013-03-09 08:18:59 +0100 (Sa, 09. Mrz 2013) $ ********************************************************************/ #ifndef RATSNESTCOLORS_H #define RATSNESTCOLORS_H #include #include #include #include #include "../viewlayer.h" class RatsnestColors { public: RatsnestColors(const QDomElement &); ~RatsnestColors(); static void initNames(); static void cleanup(); static const QColor & netColor(ViewLayer::ViewID m_viewID); static bool findConnectorColor(const QStringList & names, QColor & color); static bool isConnectorColor(ViewLayer::ViewID m_viewID, const QColor &); static void reset(ViewLayer::ViewID m_viewID); static QColor backgroundColor(ViewLayer::ViewID); static const QString & shadowColor(ViewLayer::ViewID, const QString& name); static QString wireColor(ViewLayer::ViewID, QString& name); protected: const QColor & getNextColor(); protected: ViewLayer::ViewID m_viewID; QColor m_backgroundColor; int m_index; QHash m_ratsnestColorHash; QList m_ratsnestColorList; static QHash m_viewList; static QHash m_allNames; }; #endif fritzing-app-0.9.2b/src/utils/resizehandle.cpp000066400000000000000000000062541250202676700214240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "resizehandle.h" #include "../sketch/zoomablegraphicsview.h" #include "../debugdialog.h" #include "../sketch/fgraphicsscene.h" #include ResizeHandle::ResizeHandle(const QPixmap &pixmap, const QCursor & cursor, bool ignoresTransforms, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent) { setCursor(cursor); setVisible(true); setFlag(QGraphicsItem::ItemIgnoresTransformations, ignoresTransforms); } ResizeHandle::~ResizeHandle() { } void ResizeHandle::mousePressEvent(QGraphicsSceneMouseEvent * event) { event->accept(); emit mousePressSignal(event, this); } void ResizeHandle::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { event->accept(); emit mouseMoveSignal(event, this); } void ResizeHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) { event->accept(); emit mouseReleaseSignal(event, this); } void ResizeHandle::setResizeOffset(QPointF p) { m_resizeOffset = p; } QPointF ResizeHandle::resizeOffset() { return m_resizeOffset; } QVariant ResizeHandle::itemChange(GraphicsItemChange change, const QVariant &value) { switch (change) { case QGraphicsItem::ItemSceneHasChanged: if (scaling()) { ZoomableGraphicsView *sw = dynamic_cast(scene()->parent()); if (sw) { connect(sw, SIGNAL(zoomChanged(double)), this, SLOT(zoomChangedSlot(double))); } } break; default: break; } return QGraphicsPixmapItem::itemChange(change, value); } void ResizeHandle::zoomChangedSlot(double scale) { emit zoomChangedSignal(scale); } double ResizeHandle::currentScale() { if (scaling()) { ZoomableGraphicsView *sw = dynamic_cast(scene()->parent()); if(sw) { return sw->currentZoom()/100; } } return 1; } void ResizeHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if(scene()) { FGraphicsScene * fscene = qobject_cast(scene()); if (fscene != NULL && fscene->displayHandles()) { QGraphicsPixmapItem::paint(painter, option, widget); } } } bool ResizeHandle::scaling() { return (this->flags() & QGraphicsItem::ItemIgnoresTransformations) && (scene() != NULL); } fritzing-app-0.9.2b/src/utils/resizehandle.h000066400000000000000000000042651250202676700210710ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef RESIZEHANDLE_H #define RESIZEHANDLE_H #include #include // currently used by Note.cpp class ResizeHandle : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: ResizeHandle(const QPixmap & pixmap, const QCursor &, bool ignoresTransforms, QGraphicsItem * parent = 0); ~ResizeHandle(); QPointF resizeOffset(); void setResizeOffset(QPointF); double currentScale(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); public slots: void zoomChangedSlot(double scale); protected: void mousePressEvent ( QGraphicsSceneMouseEvent * event ); void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ); void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ); QVariant itemChange(GraphicsItemChange change, const QVariant &value); bool scaling(); signals: void mousePressSignal(QGraphicsSceneMouseEvent * event, ResizeHandle *); void mouseMoveSignal(QGraphicsSceneMouseEvent * event, ResizeHandle *); void mouseReleaseSignal(QGraphicsSceneMouseEvent * event, ResizeHandle *); void zoomChangedSignal(double scale); protected: QPointF m_resizeOffset; }; #endif fritzing-app-0.9.2b/src/utils/s2s.cpp000066400000000000000000001014701250202676700174520ustar00rootroot00000000000000#include "s2s.h" #include "stdio.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../src/utils/textutils.h" #include "../../src/utils/schematicrectconstants.h" #include ///////////////////////////////// bool xLessThan(ConnectorLocation * cl1, ConnectorLocation * cl2) { return cl1->terminalPoint.x() < cl2->terminalPoint.x(); } bool yLessThan(ConnectorLocation * cl1, ConnectorLocation * cl2) { return cl1->terminalPoint.y() < cl2->terminalPoint.y(); } double getY(const QPointF & p) { return p.y(); } double getX(const QPointF & p) { return p.x(); } void setHiddenAux(QList & allConnectorLocations, QList & sideConnectorLocations, double (*get)(const QPointF &), double fudge) { int i = 0; while (i < sideConnectorLocations.count() - 1) { QList same; ConnectorLocation * basis = sideConnectorLocations.at(i); same << basis; for (int j = i + 1; j < sideConnectorLocations.count(); j++) { i = j; ConnectorLocation * next = sideConnectorLocations.at(j); if (qAbs(get(basis->terminalPoint )- get(next->terminalPoint)) < fudge) { same << next; } else { break; } } if (same.count() > 1) { foreach (ConnectorLocation * connectorLocation, same) { connectorLocation->hidden = true; } for (int ix = allConnectorLocations.count() - 1; ix >= 0; ix--) { ConnectorLocation * that = allConnectorLocations.at(ix); if (same.contains(that)) { // assume the topmost is the one at the end of allConnectorLocations // the rest are hidden that->hidden = false; sideConnectorLocations.removeOne(that); int maxIndex = -1; foreach (ConnectorLocation * s, same) { int ix = sideConnectorLocations.indexOf(s); if (ix > maxIndex) maxIndex = ix; } // visible one should be the topmost of the set sideConnectorLocations.insert(maxIndex + 1, that); break; } } } } } ///////////////////////////////// static QRegExp IntegerFinder("\\d+"); static const double ImageFactor = 5; static const double FudgeDivisor = 300; static const QRegExp VersionRegexp("[ -_][vV][\\d]+"); /////////////////////////////////////////////////////// QString makePinNumber(const ConnectorLocation * connectorLocation, double x1, double y1, double x2, double y2) { if (connectorLocation->id < 0) return ""; if (connectorLocation->hidden) return ""; if (!connectorLocation->displayPinNumber) return ""; QString text; double tx = 0; double ty = 0; if (x1 == x2) { text += QString("\n") .arg(x2 - SchematicRectConstants::PinWidth + SchematicRectConstants::PinSmallTextVert) .arg((y2 + y1) / 2) .arg(270) ; } else { tx = (x2 + x1) / 2; ty = y2 - SchematicRectConstants::PinWidth + SchematicRectConstants::PinSmallTextVert; } text += QString("%5\n") .arg(SchematicRectConstants::PinSmallTextHeight) .arg(tx) .arg(ty) .arg("middle") .arg(connectorLocation->id) .arg(0) // SW(width) .arg(SchematicRectConstants::PinTextColor) .arg(SchematicRectConstants::FontFamily) ; if (x1 == x2) { text += "\n"; } return text; } QString makePinText(const ConnectorLocation * connectorLocation, double x1, double y1, double x2, double y2, bool anchorAtStart) { if (connectorLocation->hidden) return ""; QString text; bool rotate = false; double xOffset = 0, yOffset = 0; if (x1 == x2) { rotate = true; yOffset = (anchorAtStart ? -SchematicRectConstants::PinTextIndent : SchematicRectConstants::PinTextIndent); xOffset = SchematicRectConstants::PinTextVert; } else if (y1 == y2) { // horizontal pin xOffset = (anchorAtStart ? SchematicRectConstants::PinTextIndent : -SchematicRectConstants::PinTextIndent); yOffset = SchematicRectConstants::PinTextVert; } else { return ""; } if (rotate) { text += QString("\n") .arg(x2 + xOffset) .arg(y2 + yOffset) .arg(270); x2 = 0; y2 = 0; xOffset = yOffset = 0; } text += QString("%5\n") .arg(SchematicRectConstants::PinBigTextHeight) .arg(x2 + xOffset) .arg(y2 + yOffset) .arg(anchorAtStart ? "start" : "end") .arg(TextUtils::escapeAnd(connectorLocation->name)) .arg(0) // SW(width) .arg(SchematicRectConstants::PinTextColor) .arg(SchematicRectConstants::FontFamily) ; if (rotate) { text += "\n"; } return text; } QString makePin(const ConnectorLocation * connectorLocation, double x1, double y1, double x2, double y2) { return QString("\n") .arg(x1) .arg(y1) .arg(x2) .arg(y2) .arg(connectorLocation->hidden ? "none" : SchematicRectConstants::PinColor) .arg(connectorLocation->hidden ? 0 : SchematicRectConstants::PinWidth) .arg(connectorLocation->svgID) ; } QString makeTerminal(const ConnectorLocation * connectorLocation, double x, double y) { return QString("\n") .arg(x - (SchematicRectConstants::PinWidth / 2)) .arg(y - (SchematicRectConstants::PinWidth / 2)) .arg(SchematicRectConstants::PinWidth) .arg(SchematicRectConstants::PinWidth) .arg(connectorLocation->terminalID) ; } /////////////////////////////////////////////////////// S2S::S2S(bool fzpzStyle) : QObject() { m_image = new QImage(50 * ImageFactor, 5 * ImageFactor, QImage::Format_Mono); m_fzpzStyle = fzpzStyle; } void S2S::message(const QString & msg) { // QTextStream cout(stdout); // cout << msg; // cout.flush(); qDebug() << msg; emit messageSignal(msg); } void S2S::saveFile(const QString & content, const QString & path) { QFile file(path); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out.setCodec("UTF-8"); out << content; file.close(); } } bool S2S::onefzp(QString & fzpFilePath, QString & schematicFilePath) { if (!fzpFilePath.endsWith(".fzp")) { return false; } bool createSchematicFile = schematicFilePath.isEmpty(); QString newSchematicFilePath = schematicFilePath; m_lefts.clear(); m_rights.clear(); m_tops.clear(); m_bottoms.clear(); QFile file(fzpFilePath); QString errorStr; int errorLine; int errorColumn; QDomDocument dom; if (!dom.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { message(tr("Failed loading '%1', %2 line:%3 col:%4").arg(fzpFilePath).arg(errorStr).arg(errorLine).arg(errorColumn)); return false; } QDomElement root = dom.documentElement(); QDomElement titleElement = root.firstChildElement("title"); QString title; TextUtils::findText(titleElement, title); //int ix = VersionRegexp.lastIndexIn(title); //if (ix > 0 && ix + VersionRegexp.cap(0).count() == title.count()) { // title.chop(VersionRegexp.cap(0).count()); //} QStringList titles; titles << title; TextUtils::resplit(titles, " "); TextUtils::resplit(titles, "_"); TextUtils::resplit(titles, "-"); if (createSchematicFile) { QString schematicFileName; QDomNodeList nodeList = root.elementsByTagName("schematicView"); for (int i = 0; i < nodeList.count(); i++) { QDomElement schematicView = nodeList.at(i).toElement(); QDomElement layers = schematicView.firstChildElement("layers"); schematicFileName = layers.attribute("image"); if (!schematicFileName.isEmpty()) break; } if (schematicFileName.isEmpty()) { message(tr("Schematic not found for '%1'").arg(fzpFilePath)); return false; } if (m_fzpzStyle) { schematicFileName.replace("/", "."); schematicFileName = "svg." + schematicFileName; } schematicFilePath = m_oldSvgDir.absoluteFilePath(schematicFileName); newSchematicFilePath = m_newSvgDir.absoluteFilePath(schematicFileName); } if (!ensureTerminalPoints(fzpFilePath, schematicFilePath, root)) { return false; } qDebug() << schematicFilePath; QSvgRenderer renderer; bool loaded = renderer.load(schematicFilePath); if (!loaded) { message(tr("Unable to load schematic '%1' for '%2'").arg(schematicFilePath).arg(fzpFilePath)); return false; } QList connectorLocations = initConnectors(root, renderer, fzpFilePath, schematicFilePath); QRectF viewBox = renderer.viewBoxF(); if (viewBox.isEmpty()) { qDebug() << "\tempty viewbox"; } double oldUnit = lrtb(connectorLocations, viewBox); if (qAbs(oldUnit - SchematicRectConstants::NewUnit) < (SchematicRectConstants::NewUnit / 25)) { message(tr("Schematic '%1' is already using the 0.1inch standard.").arg(schematicFilePath)); return false; } setHidden(connectorLocations); double minPinV = 0; double maxPinV = 0; if (m_lefts.count() && m_rights.count()) { minPinV = qMin(m_lefts.first()->terminalPoint.y(), m_rights.first()->terminalPoint.y()); maxPinV = qMax(m_lefts.last()->terminalPoint.y(), m_rights.last()->terminalPoint.y()); } else if (m_rights.count()) { minPinV = m_rights.first()->terminalPoint.y(); maxPinV = m_rights.last()->terminalPoint.y(); } else if (m_lefts.count()) { minPinV = m_lefts.first()->terminalPoint.y(); maxPinV = m_lefts.last()->terminalPoint.y(); } int vPinUnits = qRound((maxPinV - minPinV) / oldUnit) + 2; int vUnits = vPinUnits; double minPinH = 0; double maxPinH = 0; if (m_bottoms.count() && m_tops.count()) { minPinH = qMin(m_bottoms.first()->terminalPoint.x(), m_tops.first()->terminalPoint.x()); maxPinH = qMax(m_bottoms.last()->terminalPoint.x(), m_tops.last()->terminalPoint.x()); } else if (m_bottoms.count()) { minPinH = m_bottoms.first()->terminalPoint.x(); maxPinH = m_bottoms.last()->terminalPoint.x(); } else if (m_tops.count()) { minPinH = m_tops.first()->terminalPoint.x(); maxPinH = m_tops.last()->terminalPoint.x(); } int hPinUnits = qRound((maxPinH - minPinH) / oldUnit) + 2; int hUnits = hPinUnits; double hPinTextMax = 0; for (int i = 0; i < m_lefts.count(); i++) { double w = stringWidthMM(SchematicRectConstants::PinBigTextHeight, m_lefts.at(i)->name); if (w > hPinTextMax) hPinTextMax = w; } for (int i = 0; i < m_rights.count(); i++) { double w = stringWidthMM(SchematicRectConstants::PinBigTextHeight, m_rights.at(i)->name); if (w > hPinTextMax) hPinTextMax = w; } int leftTextUnits = qCeil(hPinTextMax / SchematicRectConstants::NewUnit); int rightTextUnits = leftTextUnits; double vTopPinTextMax = 0; for (int i = 0; i < m_tops.count(); i++) { double w = stringWidthMM(SchematicRectConstants::PinBigTextHeight, m_tops.at(i)->name); if (w > vTopPinTextMax) vTopPinTextMax = w; } int topTextUnits = qCeil(vTopPinTextMax / SchematicRectConstants::NewUnit); double vBottomPinTextMax = 0; for (int i = 0; i < m_bottoms.count(); i++) { double w = stringWidthMM(SchematicRectConstants::PinBigTextHeight, m_bottoms.at(i)->name); if (w > vBottomPinTextMax) vBottomPinTextMax = w; } int bottomTextUnits = qCeil(vBottomPinTextMax / SchematicRectConstants::NewUnit); double labelTextMax = spaceTitle(titles, hUnits - leftTextUnits - rightTextUnits - 2); double textWidth = hPinTextMax + hPinTextMax + labelTextMax + (6 * SchematicRectConstants::PinTextIndent); // PTI text PTI PTI title PTI PTI text PTI double hTextUnits = qCeil(textWidth / SchematicRectConstants::NewUnit); if (hTextUnits > hUnits) hUnits = hTextUnits; textWidth = titles.count() * (SchematicRectConstants::LabelTextHeight + SchematicRectConstants::LabelTextSpace); double vTextUnits = qCeil((textWidth / SchematicRectConstants::NewUnit) + (2 * SchematicRectConstants::PinTextIndent)); if (vTextUnits > vUnits) vUnits = vTextUnits; vUnits += topTextUnits; vUnits += bottomTextUnits; double fullWidth = hUnits; if (m_lefts.count()) fullWidth += 2; if (m_rights.count()) fullWidth += 2; double fullHeight = vUnits; if (m_tops.count()) fullHeight += 2; if (m_bottoms.count()) fullHeight += 2; // construct svg QString svg = TextUtils::makeSVGHeader(25.4, 25.4, fullWidth * SchematicRectConstants::NewUnit, fullHeight * SchematicRectConstants::NewUnit); double rectL = SchematicRectConstants::RectStrokeWidth / 2; double rectT = rectL; if (m_lefts.count()) rectL += 2 * SchematicRectConstants::NewUnit; if (m_tops.count()) rectT += 2 * SchematicRectConstants::NewUnit; svg += "\n"; svg += QString("\n") .arg(rectL) .arg(rectT) .arg((hUnits * SchematicRectConstants::NewUnit) - SchematicRectConstants::RectStrokeWidth) .arg((vUnits * SchematicRectConstants::NewUnit) - SchematicRectConstants::RectStrokeWidth) .arg(SchematicRectConstants::RectFillColor) .arg(SchematicRectConstants::RectStrokeColor) .arg(SchematicRectConstants::RectStrokeWidth) ; double vPinOffset = 0; if (m_tops.count()) vPinOffset = 2 * SchematicRectConstants::NewUnit; vPinOffset += topTextUnits * SchematicRectConstants::NewUnit; int space = vUnits - vPinUnits - topTextUnits - bottomTextUnits; if (space > 1) { vPinOffset += (space / 2) * SchematicRectConstants::NewUnit; } foreach (ConnectorLocation * connectorLocation, m_rights) { int units = qRound((connectorLocation->terminalPoint.y() - minPinV) / oldUnit) + 1; double y = units * SchematicRectConstants::NewUnit + vPinOffset; double x1 = ((fullWidth - 2) * SchematicRectConstants::NewUnit) - (SchematicRectConstants::PinWidth / 2); double x2 = (fullWidth * SchematicRectConstants::NewUnit) - (SchematicRectConstants::PinWidth / 2); svg += makePin(connectorLocation, x1, y, x2, y); svg += makePinNumber(connectorLocation, x1, y, x2, y); svg += makePinText(connectorLocation, x2, y, x1, y, false); svg += makeTerminal(connectorLocation, fullWidth * SchematicRectConstants::NewUnit, y); } foreach (ConnectorLocation * connectorLocation, m_lefts) { int units = qRound((connectorLocation->terminalPoint.y() - minPinV) / oldUnit) + 1; double y = units * SchematicRectConstants::NewUnit + vPinOffset; double x1 = SchematicRectConstants::PinWidth / 2; double x2 = (2 * SchematicRectConstants::NewUnit) + (SchematicRectConstants::PinWidth / 2); svg += makePin(connectorLocation, x1, y, x2, y); svg += makePinNumber(connectorLocation, x1, y, x2, y); svg += makePinText(connectorLocation, x1, y, x2, y, true); svg += makeTerminal(connectorLocation, 0, y); } double hPinOffset = 0; if (m_lefts.count()) hPinOffset = 2 * SchematicRectConstants::NewUnit; space = hUnits - hPinUnits; if (space > 1) { hPinOffset += (space / 2) * SchematicRectConstants::NewUnit; } foreach (ConnectorLocation * connectorLocation, m_bottoms) { int units = qRound((connectorLocation->terminalPoint.x() - minPinH) / oldUnit) + 1; double x = units * SchematicRectConstants::NewUnit + hPinOffset; double y1 = ((fullHeight - 2) * SchematicRectConstants::NewUnit) - (SchematicRectConstants::PinWidth / 2); double y2 = (fullHeight * SchematicRectConstants::NewUnit) - (SchematicRectConstants::PinWidth / 2); svg += makePin(connectorLocation, x, y1, x, y2); svg += makePinNumber(connectorLocation, x, y1, x, y2); svg += makePinText(connectorLocation, x, y2, x, y1, true); svg += makeTerminal(connectorLocation, x, fullHeight * SchematicRectConstants::NewUnit); } foreach (ConnectorLocation * connectorLocation, m_tops) { int units = qRound((connectorLocation->terminalPoint.x() - minPinH) / oldUnit) + 1; double x = units * SchematicRectConstants::NewUnit + hPinOffset; double y1 = SchematicRectConstants::PinWidth / 2; double y2 = (2 * SchematicRectConstants::NewUnit) + (SchematicRectConstants::PinWidth / 2); svg += makePin(connectorLocation, x, y1, x, y2); svg += makePinNumber(connectorLocation, x, y1, x, y2); svg += makePinText(connectorLocation, x, y1, x, y2, false); svg += makeTerminal(connectorLocation, x, 0); } double y = vUnits * SchematicRectConstants::NewUnit / 2; y -= titles.count() * (SchematicRectConstants::LabelTextHeight + SchematicRectConstants::LabelTextSpace) / 2; y += rectT; y = qMax(y, rectT + (topTextUnits * SchematicRectConstants::NewUnit) + SchematicRectConstants::LabelTextHeight + SchematicRectConstants::LabelTextSpace + SchematicRectConstants::PinTextIndent); // y seems to be the location of the baseline so add a line foreach (QString subTitle, titles) { svg += QString("%6\n") .arg(SchematicRectConstants::LabelTextHeight) .arg(((hUnits * SchematicRectConstants::NewUnit) / 2) + rectL) .arg(y) .arg(0) // SW(width) .arg(SchematicRectConstants::TitleColor) .arg(TextUtils::escapeAnd(subTitle)) .arg(SchematicRectConstants::FontFamily) ; y += (SchematicRectConstants::LabelTextHeight + SchematicRectConstants::LabelTextSpace); } svg +="\n"; svg +="\n"; TextUtils::writeUtf8(newSchematicFilePath, svg); qDebug() << newSchematicFilePath; qDebug() << ""; return true; } double S2S::stringWidthMM(double fontSize, const QString & string) { /* // tried using FontMetrics but the result is always too short QFont font("Droid Sans"); font.setPointSizeF(fontSize * 72 / 25.4); QFontMetricsF fontMetrics(font); double pixels = fontMetrics.width(string); double mm = 25.4 * pixels / 90; */ QString svg = TextUtils::makeSVGHeader(25.4, 25.4, 50, 5); svg += QString("%3") .arg(SchematicRectConstants::FontFamily).arg(fontSize).arg(TextUtils::escapeAnd(string)).arg(2.5); svg += ""; QSvgRenderer renderer(svg.toUtf8()); m_image->fill(0xffffffff); QPainter painter; painter.begin(m_image); painter.setRenderHint(QPainter::Antialiasing, false); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); renderer.render(&painter); painter.end(); //QDir dir(QCoreApplication::applicationDirPath()); //dir.cdUp(); //image.save(dir.absoluteFilePath("bloody_font.png")); int bestX = 0; for (int y = 0; y < m_image->height(); y++) { for (int x = bestX; x < m_image->width(); x++) { if (m_image->pixel(x, y) == 0xff000000) { bestX = x; } } } //if (mm < bestX / ImageFactor) { // qDebug() << "string width" << mm << (bestX / ImageFactor) << string; //} return bestX / ImageFactor; } QList S2S::initConnectors(const QDomElement & root, const QSvgRenderer & renderer, const QString & fzpFilename, const QString & svgFilename) { QList connectorLocations; m_minLeft = std::numeric_limits::max(); m_minTop = std::numeric_limits::max(); m_maxRight = std::numeric_limits::min(); m_maxBottom = std::numeric_limits::min(); QDomElement connectors = root.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); QBitArray idlist; int noIDCount = 0; while (!connector.isNull()) { QDomElement schematicView = connector.firstChildElement("views").firstChildElement("schematicView"); QString svgID = schematicView.firstChildElement("p").attribute("svgId"); if (svgID.isEmpty()) { message(tr("Missing connector %1 in '%2' schematic of '%3'").arg(connector.attribute("id")).arg(svgFilename).arg(fzpFilename)); } else { ConnectorLocation * connectorLocation = new ConnectorLocation; connectorLocation->id = -1; connectorLocation->hidden = false; connectorLocation->displayPinNumber = false; QString id = connector.attribute("id"); int ix = IntegerFinder.indexIn(id); if (ix > 0) { connectorLocation->id = IntegerFinder.cap(0).toInt(); if (idlist.size() < connectorLocation->id + 1) { int oldsize = idlist.size(); idlist.resize(connectorLocation->id + 1); for (int i = oldsize; i < idlist.size(); i++) idlist.setBit(i, false); } idlist.setBit(connectorLocation->id, true); } else { noIDCount++; } connectorLocation->name = connector.attribute("name"); connectorLocation->terminalID = schematicView.firstChildElement("p").attribute("terminalId"); connectorLocation->svgID = svgID; QRectF bounds = renderer.boundsOnElement(svgID); QMatrix m = renderer.matrixForElement(svgID); connectorLocation->bounds = m.mapRect(bounds); connectorLocation->terminalPoint = connectorLocation->bounds.center(); if (!connectorLocation->terminalID.isEmpty()) { bounds = renderer.boundsOnElement(connectorLocation->terminalID); m = renderer.matrixForElement(connectorLocation->terminalID); connectorLocation->terminalPoint = m.mapRect(bounds).center(); } connectorLocations.append(connectorLocation); if (connectorLocation->terminalPoint.x() < m_minLeft) { m_minLeft = connectorLocation->terminalPoint.x(); } if (connectorLocation->terminalPoint.x() > m_maxRight) { m_maxRight = connectorLocation->terminalPoint.x(); } if (connectorLocation->terminalPoint.y() < m_minTop) { m_minTop = connectorLocation->terminalPoint.y(); } if (connectorLocation->terminalPoint.y() > m_maxBottom) { m_maxBottom = connectorLocation->terminalPoint.y(); } } connector = connector.nextSiblingElement("connector"); } if (noIDCount > 0) { qDebug() << "no id count" << noIDCount; } bool display = true; if (!idlist.at(0) && !idlist.at(1)) { display = false; } else { int present = 0; for (int i = 0; i < idlist.size(); i++) { if (idlist.at(i)) present++; } display = (present >= .66 * idlist.size()); } foreach (ConnectorLocation * connectorLocation, connectorLocations) { connectorLocation->displayPinNumber = display; } if (display && idlist.at(0)) { foreach (ConnectorLocation * connectorLocation, connectorLocations) { connectorLocation->id++; } } return connectorLocations; } double S2S::lrtb(QList & connectorLocations, const QRectF & viewBox) { m_fudge = qMax(m_maxRight - m_minLeft, m_maxBottom - m_minTop) / FudgeDivisor; foreach (ConnectorLocation * connectorLocation, connectorLocations) { double d[4]; d[0] = connectorLocation->terminalPoint.x() - viewBox.left(); d[1] = connectorLocation->terminalPoint.y() - viewBox.top(); d[2] = viewBox.right() - connectorLocation->terminalPoint.x(); d[3] = viewBox.bottom() - connectorLocation->terminalPoint.y(); int ix = 0; int dx = d[0]; for (int i = 1; i < 4; i++) { if (d[i] < dx) { dx = d[i]; ix = i; } } switch (ix) { case 0: m_lefts << connectorLocation; break; case 1: m_tops << connectorLocation; break; case 2: m_rights << connectorLocation; break; case 3: m_bottoms << connectorLocation; break; default: qDebug() << "shouldn't happen" << ix; } } qSort(m_lefts.begin(), m_lefts.end(), yLessThan); qSort(m_rights.begin(), m_rights.end(), yLessThan); qSort(m_tops.begin(), m_tops.end(), xLessThan); qSort(m_bottoms.begin(), m_bottoms.end(), xLessThan); QList distances; for (int i = 1; i < m_lefts.count(); i++) { ConnectorLocation * l1 = m_lefts.at(i - 1); ConnectorLocation * l2 = m_lefts.at(i); distances << l2->terminalPoint.y() - l1->terminalPoint.y(); } for (int i = 1; i < m_rights.count(); i++) { ConnectorLocation * l1 = m_rights.at(i - 1); ConnectorLocation * l2 = m_rights.at(i); distances << l2->terminalPoint.y() - l1->terminalPoint.y(); } for (int i = 1; i < m_tops.count(); i++) { ConnectorLocation * l1 = m_tops.at(i - 1); ConnectorLocation * l2 = m_tops.at(i); distances << l2->terminalPoint.x() - l1->terminalPoint.x(); } for (int i = 1; i < m_bottoms.count(); i++) { ConnectorLocation * l1 = m_bottoms.at(i - 1); ConnectorLocation * l2 = m_bottoms.at(i); distances << l2->terminalPoint.x() - l1->terminalPoint.x(); } qSort(distances.begin(), distances.end()); int totalPins = m_lefts.count() + m_rights.count() + m_bottoms.count() + m_tops.count(); int most = 0; foreach (double distance, distances) { int d = qRound(distance / m_fudge); if (d > most) most = d; } QVector dbins(most + 2, 0); foreach (double distance, distances) { int d = qRound(distance / m_fudge); dbins[d] += 1; } int biggest = dbins[1]; int biggestIndex = 1; for (int i = 2; i < dbins.count(); i++) { if (dbins[i] > biggest) { biggest = dbins[i]; biggestIndex = i; } } if (biggest == 0) { qDebug() << "\tbiggest 0" << totalPins; } double oldUnit = biggestIndex * m_fudge; qDebug() << QString("\tunit is roughly %1mm, bin:%2 pins:%3 fudge:%4").arg(oldUnit).arg(biggest).arg(totalPins).arg(m_fudge); qDebug() << QString("\tl:%1 t:%2 r:%3 b:%4").arg(m_lefts.count()).arg(m_tops.count()).arg(m_rights.count()).arg(m_bottoms.count()); return oldUnit; } void S2S::setHidden(QList & connectorLocations) { setHiddenAux(connectorLocations, m_lefts, getY, m_fudge); setHiddenAux(connectorLocations, m_rights, getY, m_fudge); setHiddenAux(connectorLocations, m_tops, getX, m_fudge); setHiddenAux(connectorLocations, m_bottoms, getX, m_fudge); } bool S2S::ensureTerminalPoints(const QString & fzpFilePath, const QString & svgFilePath, QDomElement & fzpRoot) { QList missing; QDomElement connectors = fzpRoot.firstChildElement("connectors"); QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement views = connector.firstChildElement("views"); QDomElement schematicView = views.firstChildElement("schematicView"); QDomElement p = schematicView.firstChildElement("p"); QString terminalID = p.attribute("terminalId"); if (terminalID.isEmpty()) { missing << p; } connector = connector.nextSiblingElement("connector"); } if (missing.count() == 0) return true; QSvgRenderer renderer; bool loaded = renderer.load(svgFilePath); if (!loaded) { message(tr("Uunable to load schematic '%1' for '%2'").arg(svgFilePath).arg(fzpFilePath)); return false; } QString errorStr; int errorLine; int errorColumn; QFile file(svgFilePath); QDomDocument dom; if (!dom.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { message(tr("Failed loading schematic '%1', %2 line:%3 col:%4").arg(svgFilePath).arg(errorStr).arg(errorLine).arg(errorColumn)); return false; } QDomElement svgRoot = dom.documentElement(); bool fzpChanged = false; bool svgChanged = false; foreach (QDomElement p, missing) { QDomElement connector = p.parentNode().parentNode().parentNode().toElement(); QString name = connector.attribute("id"); if (name.isEmpty()) { qDebug() << "empty name in connector"; } else { // assumes the file is well behaved, and the terminalID isn't already in use QString terminalName = name + "terminal"; p.setAttribute("terminalId", terminalName); fzpChanged = true; QDomElement terminalElement = TextUtils::findElementWithAttribute(svgRoot, "id", terminalName); if (terminalElement.isNull()) { QString svgID = p.attribute("svgId"); QDomElement connectorElement = TextUtils::findElementWithAttribute(svgRoot, "id", svgID); QRectF bounds = renderer.boundsOnElement(svgID); QDomElement rect = svgRoot.ownerDocument().createElement("rect"); connectorElement.parentNode().insertAfter(rect, connectorElement); rect.setAttribute("x", QString::number(bounds.left())); rect.setAttribute("y", QString::number(bounds.top())); rect.setAttribute("width", QString::number(bounds.width())); rect.setAttribute("height", QString::number(bounds.height())); rect.setAttribute("fill", "none"); rect.setAttribute("stroke", "none"); rect.setAttribute("stroke-width", 0); rect.setAttribute("id", terminalName); svgChanged = true; } } } if (svgChanged) { TextUtils::writeUtf8(svgFilePath, TextUtils::removeXMLEntities(dom.toString(4))); } if (fzpChanged) { TextUtils::writeUtf8(fzpFilePath, TextUtils::removeXMLEntities(fzpRoot.ownerDocument().toString(4))); } return true; } double S2S::spaceTitle(QStringList & titles, int openUnits) { double labelTextMax = 0; foreach (QString title, titles) { double w = stringWidthMM(SchematicRectConstants::LabelTextHeight, title); if (w > labelTextMax) labelTextMax = w; } double useMax = qMax(openUnits * SchematicRectConstants::NewUnit, labelTextMax); bool changed = false; int ix = 0; while (ix < titles.count() - 1) { QString combined = titles.at(ix); if (!(combined.endsWith("_") || combined.endsWith("-"))) { combined.append(" "); } combined.append(titles.at(ix + 1)); double w = stringWidthMM(SchematicRectConstants::LabelTextHeight, combined); if (w <= useMax) { titles[ix] = combined; titles.removeAt(ix + 1); changed = true; continue; } ix++; } if (!changed) return labelTextMax; labelTextMax = 0; foreach (QString title, titles) { double w = stringWidthMM(SchematicRectConstants::LabelTextHeight, title); if (w > labelTextMax) labelTextMax = w; } return labelTextMax; } void S2S::setSvgDirs(QDir & oldDir, QDir & newDir) { m_oldSvgDir = oldDir; m_newSvgDir = newDir; } fritzing-app-0.9.2b/src/utils/s2s.h000066400000000000000000000033271250202676700171210ustar00rootroot00000000000000#ifndef S2S_H #define S2S_H #include #include #include #include #include #include struct ConnectorLocation { QString svgID; QString terminalID; QString name; int id; QRectF bounds; QPointF terminalPoint; bool hidden; bool displayPinNumber; enum Side { Unknown, Left, Top, Right, Bottom }; }; class S2S : public QObject { Q_OBJECT public: S2S(bool fzpzStyle); bool onefzp(QString & fzpFilePath, QString & schematicFilePath); void setSvgDirs(QDir & oldDir, QDir & newDir); signals: void messageSignal(const QString & message); protected: void message(const QString &); void saveFile(const QString & content, const QString & path); double stringWidthMM(double fontSize, const QString & string); QList initConnectors(const QDomElement & root, const QSvgRenderer &, const QString & fzpFilename, const QString & svgFilename); double lrtb(QList &, const QRectF & viewBox); void setHidden(QList &); bool ensureTerminalPoints(const QString & fzpFilename, const QString & svgFilename, QDomElement & fzpRoot); double spaceTitle(QStringList & titles, int openUnits); protected: bool m_fzpzStyle; QString m_andPath; double m_minLeft; double m_minTop; double m_maxRight; double m_maxBottom; QList m_lefts; QList m_tops; QList m_rights; QList m_bottoms; double m_fudge; QDir m_oldSvgDir; QDir m_newSvgDir; QImage * m_image; }; #endif // S2S_H fritzing-app-0.9.2b/src/utils/schematicrectconstants.cpp000066400000000000000000000465731250202676700235320ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "schematicrectconstants.h" #include "textutils.h" // all measurements in millimeters const double SchematicRectConstants::PinWidth = 0.246944; // millimeters const double SchematicRectConstants::PinSmallTextHeight = 0.881944444; const double SchematicRectConstants::PinBigTextHeight = 1.23472222; const double SchematicRectConstants::PinTextIndent = PinWidth * 2; // was PinWidth * 3; const double SchematicRectConstants::PinTextVert = PinWidth * 1; const double SchematicRectConstants::PinSmallTextVert = -PinWidth / 2; const double SchematicRectConstants::LabelTextHeight = 1.49930556; const double SchematicRectConstants::LabelTextSpace = 0.1; const double SchematicRectConstants::RectStrokeWidth = 0.3175; const double SchematicRectConstants::NewUnit = 0.1 * 25.4; // .1in in mm const QString SchematicRectConstants::PinColor("#787878"); const QString SchematicRectConstants::PinTextColor("#8c8c8c"); const QString SchematicRectConstants::TitleColor("#000000"); const QString SchematicRectConstants::RectStrokeColor("#000000"); const QString SchematicRectConstants::RectFillColor("#FFFFFF"); const QString SchematicRectConstants::FontFamily("'Droid Sans'"); /////////////////////////////////////////// #include #include #include #include /////////////////////////////////////////// inline QString SW(qreal strokeWidth) { return QString("%1").arg(strokeWidth); } QString schematicPinNumber(qreal x, qreal y, qreal pinSmallTextHeight, const QString & cid, bool rotate, bool gotZero, bool gotOne) { if (!gotZero && !gotOne) return ""; QString id = cid; if (gotZero) { id = QString::number(cid.toInt() + 1); } QString text; qreal useX = x; qreal offset = 1000 * (SchematicRectConstants::PinWidth - SchematicRectConstants::PinSmallTextVert) / 25.4; qreal useY = y - offset; if (rotate) { text += QString("\n") .arg(useX - offset) .arg(useY + offset) .arg(270); useX = 0; useY = 0; } text += QString("%5\n") .arg(pinSmallTextHeight) .arg(useX) .arg(useY) .arg("middle") .arg(id) .arg(0) // SW(width) .arg(SchematicRectConstants::PinTextColor) .arg(SchematicRectConstants::FontFamily) ; if (rotate) { text += "\n"; } return text; } QString schematicPinText(const QString & id, const QString & signal, qreal x, qreal y, qreal bigPinFontSize, const QString & anchor, bool rotate) { QString text; if (rotate) { qreal yOffset = SchematicRectConstants::PinTextIndent + SchematicRectConstants::RectStrokeWidth; if (anchor == "start") yOffset = -yOffset; qreal xOffset = SchematicRectConstants::PinTextVert + SchematicRectConstants::PinWidth; xOffset = 1000 * xOffset / 25.4; yOffset = 1000 * yOffset / 25.4; text += QString("\n") .arg(x + xOffset) .arg(y + yOffset) .arg(270); x = 0; y = 0; //xOffset = yOffset = 0; } text += QString("%3\n") .arg(id) .arg(y) .arg(TextUtils::escapeAnd(signal)) .arg(bigPinFontSize) .arg(x) .arg(SchematicRectConstants::PinTextColor) .arg(SchematicRectConstants::FontFamily) .arg(anchor) ; if (rotate) { text += "\n"; } return text; } QString SchematicRectConstants::simpleGetConnectorName(const QDomElement & element) { return TextUtils::escapeAnd(element.attribute("name")); } QString SchematicRectConstants::genSchematicDIP(QList & powers, QList & grounds, QList & lefts, QList & rights, QList & vias, QStringList & busNames, QString & boardName, bool usingParam, bool genericSMD, QString (*getConnectorName)(const QDomElement &)) { int powersBuses = 0, groundsBuses = 0, leftsBuses = 0, rightsBuses = 0; QList busContacts; QList all = powers; all.append(lefts); all.append(rights); all.append(grounds); bool gotZero = false; bool gotOne = false; foreach (QDomElement contact, all) { bool ok; if (contact.attribute("connectorIndex").toInt() == 1) gotOne = true; if (contact.attribute("connectorIndex").toInt(&ok) == 0 && ok) gotZero = true; } foreach (QDomElement contact, powers) { contact.setAttribute("ltrb", "power"); if (contact.attribute("bus", 0).compare("1") == 0) { busContacts.append(contact); powersBuses++; } } foreach (QDomElement contact, grounds) { contact.setAttribute("ltrb", "ground"); if (contact.attribute("bus", 0).compare("1") == 0) { busContacts.append(contact); groundsBuses++; } } foreach (QDomElement contact, lefts) { contact.setAttribute("ltrb", "left"); if (contact.attribute("bus", 0).compare("1") == 0) { busContacts.append(contact); leftsBuses++; } } foreach (QDomElement contact, rights) { contact.setAttribute("ltrb", "right"); if (contact.attribute("bus", 0).compare("1") == 0) { busContacts.append(contact); rightsBuses++; } } //foreach(QDomElement contact, busContacts) { //qDebug() << "sch bus" << contact.attribute("signal") << contact.attribute("name") << contact.attribute("connectorIndex"); //} qreal bigFontSize = 1000 * SchematicRectConstants::PinBigTextHeight / 25.4; qreal bigPinFontSize = 1000 * SchematicRectConstants::PinBigTextHeight / 25.4; qreal smallPinFontSize = 1000 * SchematicRectConstants::PinSmallTextHeight / 25.4; qreal pinThickness = 1000 * SchematicRectConstants::PinWidth / 25.4; qreal halfPinThickness = pinThickness / 2; qreal unitLength = 1000 * SchematicRectConstants::NewUnit / 25.4; qreal pinLength = 2 * unitLength; qreal pinTextIndent = 1000 * SchematicRectConstants::PinTextIndent / 25.4; qreal pinTextVert = 1000 * SchematicRectConstants::PinTextVert / 25.4; qreal rectThickness = 1000 * SchematicRectConstants::RectStrokeWidth / 25.4; QStringList titles; if (genericSMD) { titles.append(boardName); } else { boardName.replace(" - ", " "); boardName.replace("_", " "); titles = boardName.split(" "); if (!usingParam) { QRegExp version("^[vV][\\d]+"); if (titles.last().contains(version)) { titles.takeLast(); } } } qreal titleWidth = 0; qreal leftWidth = 0; qreal rightWidth = 0; qreal topWidth = 0; qreal bottomWidth = 0; QFont bigFont("DroidSans"); bigFont.setPointSizeF(bigFontSize * 72 / 1000.0); QFontMetricsF bigFontMetrics(bigFont); foreach (QString title, titles) { qreal w = bigFontMetrics.width(title); if (w > titleWidth) titleWidth = w; } QFont pinTextFont("DroidSans"); pinTextFont.setPointSizeF(bigPinFontSize * 72 / 1000.0); QFontMetricsF smallFontMetrics(pinTextFont); foreach (QDomElement element, lefts) { qreal w = smallFontMetrics.width(getConnectorName(element)); if (w > leftWidth) leftWidth = w; } foreach (QDomElement element, rights) { qreal w = smallFontMetrics.width(getConnectorName(element)); if (w > rightWidth) rightWidth = w; } foreach (QDomElement element, powers) { qreal w = smallFontMetrics.width(getConnectorName(element)); if (w > topWidth) topWidth = w; } foreach (QDomElement element, grounds) { qreal w = smallFontMetrics.width(getConnectorName(element)); if (w > bottomWidth) bottomWidth = w; } // title is symmetric so leave max room on both sides if (leftWidth > rightWidth && rightWidth > 0) rightWidth = leftWidth; if (rightWidth > leftWidth && leftWidth > 0) leftWidth = rightWidth; // convert from pixels (which seem to be points) back to mils leftWidth = 1000 * leftWidth / 72.0; rightWidth = 1000 * rightWidth / 72.0; titleWidth = 1000 * titleWidth / 72.0; topWidth = 1000 * topWidth / 72.0; bottomWidth = 1000 * bottomWidth / 72.0; qreal textWidth = (leftWidth + rightWidth + titleWidth + (rightWidth > 0 ? pinTextIndent : 0) + (leftWidth > 0 ? pinTextIndent : 0)); qreal width = (qCeil(textWidth / unitLength) * unitLength); if (lefts.count() > 0) width += pinLength; if (rights.count() > 0) width += pinLength; int room = qFloor(width / unitLength) - 4; if (powers.count() - powersBuses > room) width += (pinLength * (powers.count() - powersBuses - room)); if (grounds.count() - groundsBuses > room) width += (pinLength * (grounds.count() - groundsBuses - room)); qreal rectTop = rectThickness / 2; qreal height = 0; qreal startTitle = 0; if (powers.count() > 0) { startTitle = pinLength + qCeil(topWidth / unitLength) * unitLength; height += startTitle; rectTop += pinLength - rectThickness / 2; } else { height += unitLength; startTitle = unitLength; } qreal rectBottom = rectThickness / 2; if (grounds.count() > 0) { qreal dh = pinLength + qCeil(bottomWidth / unitLength) * unitLength; rectBottom += pinLength - (rectThickness / 2); height += dh; } else height += unitLength; int l1 = qMax(0, lefts.count() - leftsBuses - 1); l1 = qMax(l1, rights.count() - rightsBuses - 1); l1 = qMax(l1, qCeil(titles.count() * bigFontSize / unitLength)); height += l1 * unitLength; QString svg = TextUtils::makeSVGHeader(1000, 1000, width, height); svg += "Fritzing schematic generated by brd2svg\n"; svg += "\n"; qreal rectLeft = rectThickness / 2; qreal rectMinus = 0; if (lefts.count()) { rectLeft = pinLength; rectMinus += pinLength; } if (rights.count()) { rectMinus += pinLength; } svg += QString("\n") .arg(width - rectMinus - (rectThickness / 2)) .arg(height - rectBottom - rectTop) .arg(rectTop) .arg(rectLeft) .arg(SW(rectThickness)); qreal y = qFloor((height / 2) / unitLength) * unitLength; y -= bigFontSize * qCeil(titles.count() / 2.0); if (y < startTitle) y = startTitle; foreach (QString title, titles) { svg += QString("%2\n") .arg(rectLeft + (width - rectMinus) / 2) .arg(TextUtils::escapeAnd(title)) .arg(y) .arg(bigFontSize) .arg(SchematicRectConstants::FontFamily) ; y += bigFontSize; } QHash busMids; // do vias first, so they are hidden beneath other connectors qreal viaX = 0; qreal viaY = 0; foreach (QDomElement contact, vias) { QString signal = getConnectorName(contact); svg += QString("\n") .arg(contact.attribute("connectorIndex")).arg(signal); svg += QString("\n") .arg(contact.attribute("connectorIndex")); } qreal ly = startTitle; foreach (QDomElement contact, lefts) { bool bus = contact.attribute("bus", 0).compare("1") == 0; if (!contact.isNull() && !bus) { QString signal = getConnectorName(contact); svg += QString("\n") .arg(ly).arg(SW(pinThickness)).arg(pinLength).arg(halfPinThickness).arg(SchematicRectConstants::PinColor); viaY = ly; viaX = halfPinThickness; QString mid = QString("\n") .arg(ly - halfPinThickness).arg(contact.attribute("connectorIndex")).arg(pinLength).arg(pinThickness).arg(signal); mid += QString("\n") .arg(ly - halfPinThickness).arg(contact.attribute("connectorIndex")).arg(pinThickness); svg += mid; if (busNames.contains(contact.attribute("signal"), Qt::CaseInsensitive)) { busMids.insert(contact.attribute("signal").toLower(), mid); } svg += schematicPinText(contact.attribute("connectorIndex"), signal, pinLength + pinTextIndent, ly + pinTextVert, bigPinFontSize, "start", false); svg += schematicPinNumber(pinLength / 2, ly, smallPinFontSize, contact.attribute("connectorIndex"), false, gotZero, gotOne); } if (!bus) ly += unitLength; } ly = startTitle; foreach (QDomElement contact, rights) { bool bus = contact.attribute("bus", 0).compare("1") == 0; if (!contact.isNull() && !bus) { QString signal = getConnectorName(contact); svg += QString("\n") .arg(width - pinLength - halfPinThickness) .arg(ly) .arg(width - halfPinThickness) .arg(SW(pinThickness)) .arg(SchematicRectConstants::PinColor) ; viaY = ly; viaX = width - pinLength - halfPinThickness; QString mid = QString("\n") .arg(width - pinLength) .arg(ly - halfPinThickness) .arg(contact.attribute("connectorIndex")) .arg(pinLength) .arg(pinThickness) .arg(signal); mid += QString("\n") .arg(width) .arg(ly - halfPinThickness) .arg(contact.attribute("connectorIndex")) .arg(pinThickness); svg += mid; if (busNames.contains(contact.attribute("signal"), Qt::CaseInsensitive)) { busMids.insert(contact.attribute("signal").toLower(), mid); } svg += schematicPinText(contact.attribute("connectorIndex"), signal, width - pinLength - pinTextIndent, ly + pinTextVert, bigPinFontSize, "end", false); svg += schematicPinNumber(width - (pinLength / 2) , ly, smallPinFontSize, contact.attribute("connectorIndex"), false, gotZero, gotOne); } if (!bus) ly += unitLength; } qreal lx = width / 2; if (powers.count() - powersBuses > 2) { lx -= (unitLength * (powers.count() - powersBuses) / 2); } lx = qFloor(lx / unitLength) * unitLength; foreach (QDomElement contact, powers) { bool bus = contact.attribute("bus", 0).compare("1") == 0; if (!contact.isNull() && !bus) { QString signal = getConnectorName(contact); svg += QString("\n") .arg(lx).arg(halfPinThickness).arg(pinLength).arg(SW(pinThickness)).arg(SchematicRectConstants::PinColor); viaY = halfPinThickness; viaX = lx; QString mid = QString("\n") .arg(lx - halfPinThickness).arg(0).arg(contact.attribute("connectorIndex")).arg(pinThickness).arg(pinLength).arg(signal); mid += QString("\n") .arg(lx - halfPinThickness).arg(0).arg(contact.attribute("connectorIndex")).arg(pinThickness); svg += mid; if (busNames.contains(contact.attribute("signal"), Qt::CaseInsensitive)) { busMids.insert(contact.attribute("signal").toLower(), mid); } svg += schematicPinText(contact.attribute("connectorIndex"), signal, lx, pinLength - pinTextVert, bigPinFontSize, "end", true); svg += schematicPinNumber(lx, pinLength / 2, smallPinFontSize, contact.attribute("connectorIndex"), true, gotZero, gotOne); } if (!bus) lx += unitLength; } lx = width / 2; if (grounds.count() - groundsBuses > 2) { lx -= (unitLength * (grounds.count() - groundsBuses) / 2); } lx = qFloor(lx / unitLength) * unitLength; foreach (QDomElement contact, grounds) { bool bus = contact.attribute("bus", 0).compare("1") == 0; if (!contact.isNull() && !bus) { QString signal = getConnectorName(contact); svg += QString("\n") .arg(lx).arg(height - pinLength).arg(height - halfPinThickness).arg(SW(pinThickness)).arg(SchematicRectConstants::PinColor); viaY = height - pinLength; viaX = lx; QString mid = QString("\n") .arg(lx - halfPinThickness).arg(height - pinLength).arg(contact.attribute("connectorIndex")).arg(pinThickness).arg(pinLength).arg(signal); mid += QString("\n") .arg(lx - halfPinThickness).arg(height).arg(contact.attribute("connectorIndex")).arg(pinThickness); svg += mid; if (busNames.contains(contact.attribute("signal"), Qt::CaseInsensitive)) { busMids.insert(contact.attribute("signal").toLower(), mid); } svg += schematicPinText(contact.attribute("connectorIndex"), signal, lx, height - (pinLength - pinTextVert), bigPinFontSize, "start", true); svg += schematicPinNumber(lx, height - (pinLength / 2), smallPinFontSize, contact.attribute("connectorIndex"), true, gotZero, gotOne); } if (!bus) lx += unitLength; } svg.replace("viax=''", QString("x='%1'").arg(viaX)); svg.replace("viay=''", QString("y='%1'").arg(viaY)); QRegExp pin("connector[\\d]+pin"); QRegExp terminal("connector[\\d]+terminal"); foreach (QDomElement contact, busContacts) { QString mid = busMids.value(contact.attribute("signal").toLower(), ""); if (mid.isEmpty()) continue; QString index = contact.attribute("connectorIndex"); mid.replace(pin, QString("connector%1pin").arg(index)); mid.replace(terminal, QString("connector%1terminal").arg(index)); //qDebug() << "got bus connector" << index << contact.attribute("signal") << contact.attribute("connectorIndex"); svg += mid; } svg += "\n"; svg += "\n"; return svg; } fritzing-app-0.9.2b/src/utils/schematicrectconstants.h000066400000000000000000000044041250202676700231620ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef SCHEMATICRECTCONTANTS_H #define SCHEMATICRECTCONTANTS_H #include #include #include // all measurements in millimeters class SchematicRectConstants { public: static const double PinWidth; static const double PinSmallTextHeight; static const double PinBigTextHeight; static const double PinTextIndent; static const double PinTextVert; static const double PinSmallTextVert; static const double LabelTextHeight; static const double LabelTextSpace; static const double RectStrokeWidth; static const QString PinColor; static const QString PinTextColor; static const QString TitleColor; static const QString RectStrokeColor; static const QString RectFillColor; static const double NewUnit; static const QString FontFamily; public: static QString genSchematicDIP(QList & powers, QList & grounds, QList & lefts, QList & rights, QList & vias, QStringList & busNames, QString & boardName, bool usingParam, bool genericSMD, QString (*getConnectorName)(const QDomElement &)); static QString simpleGetConnectorName(const QDomElement & element); }; #endif fritzing-app-0.9.2b/src/utils/textutils.cpp000066400000000000000000001527221250202676700210160ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ //#include #include #include #include "textutils.h" #include "misc.h" #include "../installedfonts.h" //#include "../debugdialog.h" #include #include #include #include #include #include #include #include #include QSet InstalledFonts::InstalledFontsList; QMultiHash InstalledFonts::InstalledFontsNameMapper; // family name to filename; SVG files seem to have to use filename const QString TextUtils::CreatedWithFritzingString("Created with Fritzing (http://www.fritzing.org/)"); const QString TextUtils::CreatedWithFritzingXmlComment("\n"); const QRegExp TextUtils::FindWhitespace("[\\s]+"); static const QRegExp SodipodiAttributeDetector("(inkscape|sodipodi):[^=\\s]+=\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\""); static const QRegExp SodipodiElementDetector("]+>"); const QString TextUtils::SMDFlipSuffix("___"); const QString TextUtils::RegexFloatDetector = "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"; const QRegExp TextUtils::floatingPointMatcher(RegexFloatDetector); static const QRegExp HexExpr("&#x[0-9a-fA-F];"); // static const QRegExp Xmlns("xmlns=([\"|'])[^\"']*\\1"); const ushort TextUtils::MicroSymbolCode = 181; const QString TextUtils::MicroSymbol = QString::fromUtf16(&MicroSymbolCode, 1); const QString TextUtils::AdobeIllustratorIdentifier = "Generator: Adobe Illustrator"; QList PowerPrefixes; QList PowerPrefixValues; const QString TextUtils::PowerPrefixesString = QString("pnmkMGTu\\x%1").arg(MicroSymbolCode, 4, 16, QChar('0')); typedef QHash FixedFontsHash; ////////////////////////////////////////////// QSet getAttrFontFamilies(const QString &fileContent) { /* * font-family defined as attr example: A0 */ static QString pattern = "font-family\\s*=\\s*\"([^\"]*)\""; return TextUtils::getRegexpCaptures(pattern,fileContent); } QSet getFontFamiliesInsideStyleTag(const QString &fileContent) { /* * regexp: font-family\s*:\s*(.|[^;"]*).*" * font-family defined in a style attr example: style="font-size:9;-inkscape-font-specification:Droid Sans;font-family:Droid Sans;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal" style="font-size:144px;font-style:normal;font-weight:normal;line-height:100%;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" x="18.000002" */ static QString pattern = "font-family\\s*:\\s*([^;\"]*)"; return TextUtils::getRegexpCaptures(pattern,fileContent); } FixedFontsHash fixFontsMapping(const QSet fontsTofix, const QString & destFont) { FixedFontsHash retval; QSet tempFontsToFix; tempFontsToFix = fontsTofix - InstalledFonts::InstalledFontsList; foreach (QString fontFileName, InstalledFonts::InstalledFontsNameMapper.values()) { // SVG uses filename which may not match family name (e.g. "Droid Sans" and "Droid Sans") tempFontsToFix.remove(fontFileName); } foreach (QString broken, tempFontsToFix) { retval.insert(broken, destFont); } return retval; } bool removeFontFamilySingleQuotes(QString &fileContent) { static QString pattern = "font-family=\"('[^']*')\""; QSet wrongFontFamilies = TextUtils::getRegexpCaptures(pattern, fileContent); foreach(QString ff, wrongFontFamilies) { QString wrongFF = ff; QString fixedFF = ff.remove('\''); fileContent.replace(wrongFF,fixedFF); } return wrongFontFamilies.size() > 0; } bool fixUnavailableFontFamilies(QString &fileContent, const QString & destFont) { QSet definedFFs; definedFFs.unite(getAttrFontFamilies(fileContent)); definedFFs.unite(getFontFamiliesInsideStyleTag(fileContent)); FixedFontsHash fixedFonts = fixFontsMapping(definedFFs, destFont); foreach(QString oldF, fixedFonts.keys()) { QString newF = fixedFonts[oldF]; fileContent.replace(oldF,newF); } return fixedFonts.size() > 0; } QString makeDashString(bool dashed, const QVector & pattern, double dpi, double printerScale) { QString dash; if (dashed && pattern.count() > 0) { dash = "stroke-dasharray='"; foreach (qreal p, pattern) { dash += QString::number(p * dpi / printerScale); dash += ","; } dash.chop(1); dash.append("'"); } return dash; } /////////////////////////////////////// void TextUtils::findElementsWithAttribute(QDomElement & element, const QString & att, QList & elements) { if (!element.attribute(att).isEmpty()) { elements.append(element); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { findElementsWithAttribute(child, att, elements); child = child.nextSiblingElement(); } } QDomElement TextUtils::findElementWithAttribute(QDomElement element, const QString & attributeName, const QString & attributeValue) { if (element.hasAttribute(attributeName)) { if (element.attribute(attributeName).compare(attributeValue) == 0) return element; } for(QDomElement e = element.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { QDomElement result = findElementWithAttribute(e, attributeName, attributeValue); if (!result.isNull()) return result; } return ___emptyElement___; } QSet TextUtils::getRegexpCaptures(const QString &pattern, const QString &textToSearchIn) { QRegExp re(pattern); QSet captures; int pos = 0; while ((pos = re.indexIn(textToSearchIn, pos)) != -1) { captures << re.cap(1); pos += re.matchedLength(); } return captures; } double TextUtils::convertToInches(const QString & s, bool * ok, bool isIllustrator) { QString string = s; double divisor = 1.0; int chop = 2; if (string.endsWith("cm", Qt::CaseInsensitive)) { divisor = 2.54; } else if (string.endsWith("mm", Qt::CaseInsensitive)) { divisor = 25.4; } else if (string.endsWith("in", Qt::CaseInsensitive)) { divisor = 1.0; } else if (string.endsWith("px", Qt::CaseInsensitive)) { divisor = isIllustrator? 72.0: 90.0; } else if (string.endsWith("mil", Qt::CaseInsensitive)) { divisor = 1000.0; chop = 3; } else if (string.endsWith("pt", Qt::CaseInsensitive)) { divisor = 72.0; } else if (string.endsWith("pc", Qt::CaseInsensitive)) { divisor = 6.0; } else { chopNotDigits(string); divisor = 90.0; // default to Qt's standard internal units if all else fails chop = 0; } if (chop) string.chop(chop); bool fine; double result = string.toDouble(&fine); if (!fine) { if (ok) *ok = false; return 0; } if (ok) *ok = true; return result / divisor; } void TextUtils::chopNotDigits(QString & string) { for (int ix = string.count() - 1; ix >= 0; ix--) { QChar ch = string.at(ix); if (ch.isDigit()) return; if (ch == '.') return; string.chop(1); } } bool TextUtils::squashElement(QDomDocument & doc, const QString & elementName, const QString &attName, const QRegExp &matchContent) { bool result = false; QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName(elementName); for (int i = 0; i < domNodeList.count(); i++) { QDomElement node = domNodeList.item(i).toElement(); if (node.isNull()) continue; if (!attName.isEmpty()) { QString att = node.attribute(attName); if (att.isEmpty()) continue; if (!matchContent.isEmpty()) { if (matchContent.indexIn(att) < 0) continue; } } node.setTagName("g"); result = true; } return result; } QString TextUtils::replaceTextElement(const QString & svg, const QString & id, const QString & newValue) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) return svg; QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName("text"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement node = domNodeList.item(i).toElement(); if (node.isNull()) continue; if (node.attribute("id").compare(id) != 0) continue; replaceChildText(node, newValue); return doc.toString(); } return svg; } QByteArray TextUtils::replaceTextElement(const QByteArray & svg, const QString & id, const QString & newValue) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) return svg; QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName("text"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement node = domNodeList.item(i).toElement(); if (node.isNull()) continue; if (node.attribute("id").compare(id) != 0) continue; replaceChildText(node, newValue); return doc.toByteArray(); } return svg; } QString TextUtils::replaceTextElements(const QString & svg, const QHash & hash) { QString errorStr; int errorLine; int errorColumn; QDomDocument doc; if (!doc.setContent(svg, &errorStr, &errorLine, &errorColumn)) return svg; bool changed = false; QDomElement root = doc.documentElement(); QDomNodeList domNodeList = root.elementsByTagName("text"); for (int i = 0; i < domNodeList.count(); i++) { QDomElement node = domNodeList.item(i).toElement(); if (node.isNull()) continue; foreach (QString id, hash.keys()) { if (node.attribute("id").compare(id) != 0) continue; replaceChildText(node, hash.value(id)); changed = true; break; } } if (!changed) return svg; return doc.toString(); } void TextUtils::replaceElementChildText(QDomElement & root, const QString & elementName, const QString & text) { QDomElement element = root.firstChildElement(elementName); if (element.isNull()) { element = root.ownerDocument().createElement(elementName); root.appendChild(element); } replaceChildText(element, text); } void TextUtils::replaceChildText(QDomNode & node, const QString & text) { node.normalize(); QDomNodeList childList = node.childNodes(); for (int j = 0; j < childList.count(); j++) { QDomNode child = childList.item(j); if (child.isText()) { child.setNodeValue(text); return; } } QDomText t = node.ownerDocument().createTextNode(text); node.appendChild(t); } bool TextUtils::mergeSvg(QDomDocument & doc1, const QString & svg, const QString & id) { QString errorStr; int errorLine; int errorColumn; if (doc1.isNull()) { return doc1.setContent(svg, &errorStr, &errorLine, &errorColumn); } QDomDocument doc2; if (!doc2.setContent(svg, &errorStr, &errorLine, &errorColumn)) return false; QDomElement root1 = doc1.documentElement(); if (root1.tagName() != "svg") return false; QDomElement root2 = doc2.documentElement(); if (root2.tagName() != "svg") return false; QDomElement id1; if (!id.isEmpty()) { id1 = findElementWithAttribute(root1, "id", id); } if (id1.isNull()) id1 = root1; QDomElement id2; if (!id.isEmpty()) { id2 = findElementWithAttribute(root2, "id", id); } if (id2.isNull()) id2 = root2; QDomNode node = id2.firstChild(); while (!node.isNull()) { QDomNode nextNode = node.nextSibling(); id1.appendChild(node); node = nextNode; } return true; } QString TextUtils::mergeSvgFinish(QDomDocument & doc) { return removeXMLEntities(doc.toString()); } QString TextUtils::mergeSvg(const QString & svg1, const QString & svg2, const QString & id, bool flip) { QDomDocument doc1; if (!svg1.isEmpty()) { if (!TextUtils::mergeSvg(doc1, svg1, id)) return ___emptyString___; } if (!TextUtils::mergeSvg(doc1, svg2, id)) return ___emptyString___; if (flip) { QDomElement svg = doc1.documentElement(); QString viewBox = svg.attribute("viewBox"); QStringList coords = viewBox.split(" ", QString::SkipEmptyParts); double width = coords[2].toDouble(); QMatrix matrix; matrix.translate(width / 2, 0); matrix.scale(-1, 1); matrix.translate(-width / 2, 0); QHash attributes; attributes.insert("transform", svgMatrix(matrix)); gWrap(doc1, attributes); } return mergeSvgFinish(doc1); } QString TextUtils::makeSVGHeader(double printerScale, double dpi, double width, double height) { double trueWidth = width / printerScale; double trueHeight = height / printerScale; return QString("\n%5" "\n" ) .arg(trueWidth) .arg(trueHeight) .arg(trueWidth * dpi) .arg(trueHeight * dpi) .arg(TextUtils::CreatedWithFritzingXmlComment); } bool TextUtils::isIllustratorFile(const QString &fileContent) { return fileContent.contains(AdobeIllustratorIdentifier, Qt::CaseInsensitive); } bool TextUtils::isIllustratorFile(const QByteArray & fileContent) { return fileContent.contains(AdobeIllustratorIdentifier.toUtf8()); } bool TextUtils::isIllustratorDoc(const QDomDocument & doc) { QDomNodeList children = doc.childNodes(); for ( int i=0; i < children.count(); ++i ) { QDomNode child = children.at(i); if (child.nodeType() == QDomNode::CommentNode) { if (isIllustratorFile(child.nodeValue())) { return true; } } } return false; } QString TextUtils::removeXMLEntities(QString svgContent) { return svgNSOnly(svgContent.remove(HexExpr)); } QString TextUtils::killXMLNS(QString svgContent) { // TODO: this is a bug in Qt, it would be nice to fix it there svgContent.remove(Xmlns); return svgContent; } QString TextUtils::svgNSOnly(QString svgContent) { svgContent.remove(Xmlns); int ix = svgContent.indexOf("= 0) { svgContent.insert(ix + 5, "xmlns=\"http://www.w3.org/2000/svg\" "); } return svgContent; } bool TextUtils::cleanSodipodi(QString &content) { // clean out sodipodi stuff // TODO: don't bother with the core parts int l1 = content.length(); content.remove(SodipodiAttributeDetector); // remove attributes first content.remove(SodipodiElementDetector); if (content.length() != l1) { return true; } return false; /* QString errorStr; int errorLine; int errorColumn; QDomDocument doc; bool result = doc.setContent(bytes, &errorStr, &errorLine, &errorColumn); m_svgXml.clear(); if (!result) { return false; } SvgFlattener flattener; QDomElement root = doc.documentElement(); flattener.flattenChildren(root); SvgFileSplitter::fixStyleAttributeRecurse(root); return doc.toByteArray(); */ } bool TextUtils::fixPixelDimensionsIn(QString &fileContent) { bool isIllustrator = isIllustratorFile(fileContent); if (!isIllustrator) return false; QDomDocument svgDom; QString errorMsg; int errorLine; int errorCol; if(!svgDom.setContent(fileContent, true, &errorMsg, &errorLine, &errorCol)) { return false; } bool fileHasChanged = false; if(isIllustrator) { QDomElement elem = svgDom.firstChildElement("svg"); fileHasChanged = pxToInches(elem,"width",isIllustrator); fileHasChanged |= pxToInches(elem,"height",isIllustrator); } if (fileHasChanged) { fileContent = removeXMLEntities(svgDom.toString()); } return fileHasChanged; } bool TextUtils::pxToInches(QDomElement &elem, const QString &attrName, bool isIllustrator) { if (!isIllustrator) return false; QString attrValue = elem.attribute(attrName); if(attrValue.endsWith("px")) { bool ok; double value = TextUtils::convertToInches(attrValue, &ok, isIllustrator); if(ok) { QString newValue = QString("%1in").arg(value); elem.setAttribute(attrName,newValue); return true; } } return false; } QString TextUtils::svgMatrix(const QMatrix & matrix) { return QString("matrix(%1, %2, %3, %4, %5, %6)").arg(matrix.m11()).arg(matrix.m12()).arg(matrix.m21()).arg(matrix.m22()).arg(matrix.dx()).arg(matrix.dy()); } QString TextUtils::svgMatrix(const QTransform & matrix) { return QString("matrix(%1, %2, %3, %4, %5, %6)").arg(matrix.m11()).arg(matrix.m12()).arg(matrix.m21()).arg(matrix.m22()).arg(matrix.dx()).arg(matrix.dy()); } void TextUtils::setSVGTransform(QDomElement & element, QMatrix & matrix) { element.setAttribute("transform", svgMatrix(matrix)); } QString TextUtils::svgTransform(const QString & svg, QTransform & transform, bool translate, const QString extras) { if (transform.isIdentity()) return svg; return QString("%7") .arg(transform.m11()) .arg(transform.m12()) .arg(transform.m21()) .arg(transform.m22()) .arg(translate ? transform.dx() : 0.0) .arg(translate ? transform.dy() : 0.0) .arg(svg) .arg(extras); } bool TextUtils::getSvgSizes(QDomDocument & doc, double & sWidth, double & sHeight, double & vbWidth, double & vbHeight) { bool isIllustrator = isIllustratorDoc(doc); QDomElement root = doc.documentElement(); QString swidthStr = root.attribute("width"); if (swidthStr.isEmpty()) return false; QString sheightStr = root.attribute("height"); if (sheightStr.isEmpty()) return false; bool ok; sWidth = TextUtils::convertToInches(swidthStr, &ok, isIllustrator); if (!ok) return false; sHeight = TextUtils::convertToInches(sheightStr, &ok, isIllustrator); if (!ok) return false; bool vbWidthOK = false; bool vbHeightOK = false; QString sviewboxStr = root.attribute("viewBox"); if (!sviewboxStr.isEmpty()) { QStringList strings = sviewboxStr.split(" "); if (strings.size() == 4) { double tempWidth = strings[2].toDouble(&vbWidthOK); if (vbWidthOK) { vbWidth = tempWidth; } double tempHeight= strings[3].toDouble(&vbHeightOK); if (vbHeightOK) { vbHeight = tempHeight; } } } if (vbWidthOK && vbHeightOK) return true; // assume that if there's no viewBox, the viewbox is at the right dpi? // or should the assumption be 90 or 100? Illustrator would be 72... int multiplier = 90; if (isIllustratorFile(doc.toString())) { multiplier = 72; } vbWidth = sWidth * multiplier; vbHeight = sHeight * multiplier; return true; } bool TextUtils::findText(const QDomNode & node, QString & text) { if (node.isText()) { text = node.nodeValue(); return true; } QDomNode cnode = node.firstChild(); while (!cnode.isNull()) { if (findText(cnode, text)) return true; cnode = cnode.nextSibling(); } return false; } double TextUtils::convertToInches(const QString & string) { bool ok; double retval = TextUtils::convertToInches(string, &ok, false); if (!ok) return 0; return retval; } QString TextUtils::escapeAnd(const QString & string) { #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QString s = Qt::escape(string); #else QString s = string.toHtmlEscaped(); #endif s.replace('\'', "'"); return s; } QString TextUtils::convertExtendedChars(const QString & str) { QString result; foreach (QChar c, str) { if (c < 128) { result.append(c); } else { result.append(QString("&#x%1;").arg(c.unicode(), 0, 16)); } } return result; } QString TextUtils::stripNonValidXMLCharacters(const QString & str) { QString result; QChar hs; bool in_hs = false; foreach (QChar c, str) { if (c.isHighSurrogate()) { hs = c; in_hs = true; continue; } if ((c == 0x9) || (c == 0xA) || (c == 0xD) || ((c >= 0x20) && (c <= 0xD7FF)) || ((c >= 0xE000) && (c <= 0xFFFD))) { if (in_hs) { result.append(hs); in_hs = false; } if (c > 255) { result.append(QString("&#%1").arg(c, 0, 16)); } else { result.append(c); } } else { in_hs = false; } } return result; } bool TextUtils::addCopper1(const QString & filename, QDomDocument & domDocument, const QString & srcAtt, const QString & destAtt) { QString errorStr; int errorLine; int errorColumn; QFile file(filename); bool result = domDocument.setContent(&file, &errorStr, &errorLine, &errorColumn); if (!result) { domDocument.clear(); // probably redundant return false; } QDomElement root = domDocument.documentElement(); QList elements; findElementsWithAttribute(root, "id", elements); for (int i = 0; i < elements.count(); i++) { QDomElement node = elements.at(i); if (node.isNull()) continue; QString att = node.attribute("id"); if (att == destAtt) { // already have copper1 domDocument.clear(); return false; } } result = false; for (int i = 0; i < elements.count(); i++) { QDomElement node = elements.at(i); if (node.isNull()) continue; QString att = node.attribute("id"); if (att == srcAtt) { QDomElement g = domDocument.createElement("g"); g.setAttribute("id", destAtt); node.parentNode().insertAfter(g, node); g.appendChild(node); result = true; } } if (!result) { domDocument.clear(); } //else { //QString test = domDocument.toString(); //DebugDialog::debug("test " + test); //} return result; } QString TextUtils::convertToPowerPrefix(double q) { initPowerPrefixes(); for (int i = 0; i < PowerPrefixes.count(); i++) { if (q < 100 * PowerPrefixValues[i]) { q /= PowerPrefixValues[i]; return QString::number(q) + PowerPrefixes[i]; } } return QString::number(q); } double TextUtils::convertFromPowerPrefixU(QString & val, const QString & symbol) { val.replace('u', MicroSymbol); return convertFromPowerPrefix(val, symbol); } double TextUtils::convertFromPowerPrefix(const QString & val, const QString & symbol) { initPowerPrefixes(); double multiplier = 1; QString temp = val; if (temp.endsWith(symbol)) { temp.chop(symbol.length()); } for (int i = 0; i < PowerPrefixes.count(); i++) { if (PowerPrefixes[i].isEmpty()) continue; if (temp.endsWith(PowerPrefixes[i], Qt::CaseSensitive)) { multiplier = PowerPrefixValues[i]; temp.chop(PowerPrefixes[i].length()); break; } } temp = temp.trimmed(); return temp.toDouble() * multiplier; } void TextUtils::initPowerPrefixes() { if (PowerPrefixes.count() == 0) { PowerPrefixes << "p" << "n" << MicroSymbol << "u" << "m" << "" << "k" << "M" << "G" << "T"; PowerPrefixValues << 0.000000000001 << 0.000000001 << 0.000001 << 0.000001 << 0.001 << 1 << 1000 << 1000000 << 1000000000. << 1000000000000.; } } void TextUtils::collectLeaves(QDomElement & element, int & index, QVector & leaves) { if (element.hasChildNodes()) { element.removeAttribute("id"); QDomElement c = element.firstChildElement(); while (!c.isNull()) { collectLeaves(c, index, leaves); c = c.nextSiblingElement(); } } else { leaves.insert(index, element); element.setAttribute("id", QString::number(index++)); } } void TextUtils::collectLeaves(QDomElement & element, QList & leaves) { if (element.hasChildNodes()) { QDomElement c = element.firstChildElement(); while (!c.isNull()) { collectLeaves(c, leaves); c = c.nextSiblingElement(); } } else { leaves.append(element); } } QMatrix TextUtils::elementToMatrix(QDomElement & element) { QString transform = element.attribute("transform"); if (transform.isEmpty()) return QMatrix(); return transformStringToMatrix(transform); } QMatrix TextUtils::transformStringToMatrix(const QString & transform) { // doesn't handle multiple transform attributes QList floats = getTransformFloats(transform); if (transform.startsWith("translate")) { return QMatrix().translate(floats[0], (floats.length() > 1) ? floats[1] : 0); } else if (transform.startsWith("rotate")) { if (floats.length() == 1) { return QMatrix().rotate(floats[0]); } else if (floats.length() == 3) { return QMatrix().translate(-floats[1], -floats[2]) * QMatrix().rotate(floats[0]) * QMatrix().translate(floats[1], floats[2]); } } else if (transform.startsWith("matrix")) { return QMatrix(floats[0], floats[1], floats[2], floats[3], floats[4], floats[5]); } else if (transform.startsWith("scale")) { return QMatrix().scale(floats[0], floats[1]); } else if (transform.startsWith("skewX")) { return QMatrix().shear(floats[0], 0); } else if (transform.startsWith("skewY")) { return QMatrix().shear(0, floats[0]); } return QMatrix(); } QList TextUtils::getTransformFloats(QDomElement & element){ return getTransformFloats(element.attribute("transform")); } QList TextUtils::getTransformFloats(const QString & transform){ QList list; int pos = 0; while ((pos = TextUtils::floatingPointMatcher.indexIn(transform, pos)) != -1) { list << transform.mid(pos, TextUtils::floatingPointMatcher.matchedLength()).toDouble(); pos += TextUtils::floatingPointMatcher.matchedLength(); } #ifndef QT_NO_DEBUG // QString dbg = "got transform params: \n"; //dbg += transform + "\n"; //for(int i=0; i < list.size(); i++){ //dbg += QString::number(list.at(i)) + " "; // } //DebugDialog::debug(dbg); #endif return list; } void TextUtils::gWrap(QDomDocument & domDocument, const QHash & attributes) { QDomElement g = domDocument.createElement("g"); foreach (QString key, attributes.keys()) { g.setAttribute(key, attributes.value(key, "")); } QDomNodeList nodeList = domDocument.documentElement().childNodes(); QList nodes; for (int i = 0; i < nodeList.count(); i++) { nodes.append(nodeList.item(i)); } domDocument.documentElement().appendChild(g); foreach (QDomNode node, nodes) { g.appendChild(node); } } bool TextUtils::fixInternalUnits(QString & svg) { // float detector is a little weak static QRegExp findInternalUnits("[\"']([\\d,\\.]+)(px|mm|cm|in|pt|pc)[\"']"); static QRegExp findStrokeWidth("stroke-width:([\\d,\\.]+)(px|mm|cm|in|pt|pc)"); int sw = 0; int iu = 0; int jx = svg.indexOf("= 0) { sw = iu = svg.indexOf(">", jx + 4); } bool firstTime = true; QSizeF size; QRectF viewBox; bool result = false; while (true) { iu = findInternalUnits.indexIn(svg, iu); if (iu < 0) break; result = true; if (firstTime) { // assumes width dpi = height dpi size = parseForWidthAndHeight(svg, viewBox, true); if (size.width() == 0) { // svg is messed up return false; } firstTime = false; } QString old = findInternalUnits.cap(1) + findInternalUnits.cap(2); double in = convertToInches(old); double replacement = in * viewBox.width() / size.width(); svg.replace(iu + 1, old.length(), QString::number(replacement)); } while (true) { sw = findStrokeWidth.indexIn(svg, sw); if (sw < 0) break; result = true; if (firstTime) { // assumes width dpi = height dpi size = parseForWidthAndHeight(svg, viewBox, true); if (size.width() == 0) { // svg is messed up return false; } } QString old = findStrokeWidth.cap(1) + findStrokeWidth.cap(2); double in = convertToInches(old); double replacement = in * viewBox.width() / size.width(); svg.replace(sw + 13, old.length(), QString::number(replacement)); } return result; } bool TextUtils::fixMuch(QString &svg, bool fixStrokeWidthFlag) { bool result = cleanSodipodi(svg); result |= fixInternalUnits(svg); QDomDocument svgDom; QString errorMsg; int errorLine; int errorCol; if(!svgDom.setContent(svg, true, &errorMsg, &errorLine, &errorCol)) { return result; } QDomElement root = svgDom.documentElement(); result |= fixViewBox(root); QStringList strings; strings << "pattern" << "marker" << "clipPath"; foreach (QString string, strings) { if (svg.contains("<" + string)) { result |= noPatternAux(svgDom, string); } } if (svg.contains(" todo; todo << svgDoc.documentElement(); while (todo.count() > 0) { QDomElement element = todo.takeFirst(); QDomElement child = element.firstChildElement(); while (!child.isNull()) { todo.append(child); child = child.nextSiblingElement(); } QString stroke, strokeWidth; stroke = element.attribute("stroke"); if (stroke.isEmpty()) { QString style = element.attribute("style"); if (style.contains("stroke")) { fixStyleAttribute(element); stroke = element.attribute("stroke"); } } strokeWidth = element.attribute("stroke-width"); if (stroke.isEmpty()) continue; if (stroke == "none") continue; if (!strokeWidth.isEmpty()) continue; getStrokeWidth(element, 1); result = true; } return result; } bool TextUtils::noPatternAux(QDomDocument & svgDom, const QString & tag) { bool result = false; QDomNodeList nodeList = svgDom.elementsByTagName(tag); for (int i = 0; i < nodeList.count(); i++) { QDomNode pattern = nodeList.at(i); pattern.parentNode().removeChild(pattern); result = true; } return result; } bool TextUtils::tspanRemoveAux(QDomDocument & svgDom) { QList texts; QDomNodeList textNodeList = svgDom.elementsByTagName("text"); for (int i = 0; i < textNodeList.count(); i++) { QDomElement text = textNodeList.item(i).toElement(); QDomElement tspan = text.firstChildElement("tspan"); if (tspan.isNull()) continue; texts.append(text); } if (texts.count() == 0) return false; foreach (QDomElement text, texts) { QDomElement g = svgDom.createElement("g"); text.parentNode().replaceChild(g, text); QDomNamedNodeMap attributes = text.attributes(); for (int i = 0; i < attributes.count(); i++) { QDomNode attribute = attributes.item(i); g.setAttribute(attribute.nodeName(), attribute.nodeValue()); } QString defaultX = g.attribute("x"); QString defaultY = g.attribute("y"); g.removeAttribute("x"); g.removeAttribute("y"); copyText(svgDom, g, text, defaultX, defaultY, false); QDomElement tspan = text.firstChildElement("tspan"); while (!tspan.isNull()) { copyText(svgDom, g, tspan, defaultX, defaultY, true); tspan = tspan.nextSiblingElement("tspan"); } } return true; } bool TextUtils::noUseAux(QDomDocument & svgDom) { QDomElement root = svgDom.documentElement(); if (root.isNull()) return false; QList uses; QDomNodeList useNodeList = svgDom.elementsByTagName("use"); for (int i = 0; i < useNodeList.count(); i++) { QDomElement use = useNodeList.item(i).toElement(); QString refid = use.attribute("href"); if (refid.isEmpty()) continue; QString id = use.attribute("id"); if (id.isEmpty()) continue; uses.append(use); } if (uses.count() == 0) return false; foreach (QDomElement use, uses) { QString transform = use.attribute("transform"); QString refid = use.attribute("href"); QString id = use.attribute("id"); QDomElement g = svgDom.createElement("g"); use.parentNode().replaceChild(g, use); g.setAttribute("transform", transform); if (refid.startsWith("#")) { refid.remove(0, 1); if (refid.isEmpty()) continue; } QDomElement toCopy = findElementWithAttribute(root, "id", refid); if (toCopy.isNull()) continue; QDomElement copy = toCopy.cloneNode(true).toElement(); g.appendChild(copy); copy.setAttribute("id", id); } return true; } QDomElement TextUtils::copyText(QDomDocument & svgDom, QDomElement & parent, QDomElement & text, const QString & defaultX, const QString & defaultY, bool copyAttributes) { QDomNode cnode = text.firstChild(); while (!cnode.isNull()) { if (cnode.isText()) { QDomElement newText = svgDom.createElement("text"); parent.appendChild(newText); newText.setAttribute("x", defaultX); newText.setAttribute("y", defaultY); QDomNode textValue = svgDom.createTextNode(cnode.nodeValue()); newText.appendChild(textValue); if (copyAttributes) { QDomNamedNodeMap attributes = text.attributes(); for (int i = 0; i < attributes.count(); i++) { QDomNode attribute = attributes.item(i); newText.setAttribute(attribute.nodeName(), attribute.nodeValue()); } } // normalize means there's only one text child node, so we can return now return newText; } cnode = cnode.nextSibling(); } return ___emptyElement___; } QString TextUtils::slamStrokeAndFill(const QString & svg, const QString & stroke, const QString & strokeWidth, const QString & fill) { QDomDocument doc; if (doc.setContent(svg)) { QDomElement root = doc.documentElement(); slamStrokeAndFill(root, stroke, strokeWidth, fill); return doc.toString(); } return svg; } void TextUtils::slamStrokeAndFill(QDomElement & element, const QString & stroke, const QString & strokeWidth, const QString & fill) { // assumes style elements have been normalized already QString strokeAtt = element.attribute("stroke"); QString fillAtt = element.attribute("fill"); QString strokeWidthAtt = element.attribute("stroke-width"); if (!strokeAtt.isEmpty() || !fillAtt.isEmpty() || !strokeWidthAtt.isEmpty()) { element.setAttribute("stroke", stroke); element.setAttribute("fill", fill); element.setAttribute("stroke-width", strokeWidth); } QDomElement child = element.firstChildElement(); while (!child.isNull()) { slamStrokeAndFill(child, stroke, strokeWidth, fill); child = child.nextSiblingElement(); } } struct MatchThing { int pos; int len; double val; }; QString TextUtils::incrementTemplate(const QString & filename, int pins, double increment, MultiplyPinFunction multiFun, CopyPinFunction copyFun, void * userData) { QFile file(filename); file.open(QFile::ReadOnly); QString templateString = file.readAll(); file.close(); return incrementTemplateString(templateString, pins, increment, multiFun, copyFun, userData); } QString TextUtils::incrementTemplateString(const QString & templateString, int pins, double increment, MultiplyPinFunction multiFun, CopyPinFunction copyFun, void * userData) { QString string; QRegExp uMatcher("\\[([\\.\\d]+)\\]"); MatchThing matchThings[32]; int pos = 0; unsigned int matchThingIndex = 0; while ((pos = uMatcher.indexIn(templateString, pos)) != -1) { MatchThing * mt = &matchThings[matchThingIndex++]; mt->pos = pos; mt->len = uMatcher.matchedLength(); mt->val = uMatcher.cap(1).toDouble(); pos += uMatcher.matchedLength(); if (matchThingIndex >= sizeof(matchThings) / sizeof(MatchThing)) break; } for (int i = 0; i < pins; i++) { QString argCopy(templateString); for (int j = matchThingIndex - 1; j >= 0; j--) { MatchThing * mt = &matchThings[j]; argCopy.replace(mt->pos, mt->len, (*multiFun)(i, increment, mt->val)); } string += (*copyFun)(i, argCopy, userData); } return string; } QString TextUtils::standardCopyPinFunction(int pin, const QString & argString, void *) { return argString.arg(pin); } QString TextUtils::standardMultiplyPinFunction(int pin, double increment, double value) { return QString::number(value + (pin * increment)); } QString TextUtils::incMultiplyPinFunction(int pin, double increment, double value) { return QString::number(value + ((pin + 1) * increment)); } QString TextUtils::incCopyPinFunction(int pin, const QString & argString, void *) { return argString.arg(pin + 1); } QString TextUtils::noCopyPinFunction(int, const QString & argString, void *) { return argString; } QString TextUtils::negIncCopyPinFunction(int pin, const QString & argString, void * userData) { int pins = *((int *) userData); int offset = *(((int *) userData) + 1); return argString.arg(pins - (pin + offset)); } double TextUtils::getViewBoxCoord(const QString & svg, int coord) { QRegExp re("viewBox=['\\\"]([^'\\\"]+)['\\\"]"); int ix = re.indexIn(svg); if (ix < 0) return 0; QString vb = re.cap(1); QStringList coords = vb.split(" "); QString c = coords.at(coord); return c.toDouble(); } QString TextUtils::makeLineSVG(QPointF p1, QPointF p2, double width, QString colorString, double dpi, double printerScale, bool blackOnly, bool dashed, const QVector & pattern) { p1.setX(p1.x() * dpi / printerScale); p1.setY(p1.y() * dpi / printerScale); p2.setX(p2.x() * dpi / printerScale); p2.setY(p2.y() * dpi / printerScale); QString dash = makeDashString(dashed, pattern, dpi, printerScale); QString stroke = (blackOnly) ? "black" : colorString; return QString("") .arg(p1.x()) .arg(p1.y()) .arg(p2.x()) .arg(p2.y()) .arg(width * dpi / printerScale) .arg(stroke) .arg(dash) ; } QString TextUtils::makeCubicBezierSVG(const QPolygonF & poly, double width, QString colorString, double dpi, double printerScale, bool blackOnly, bool dashed, const QVector & pattern) { QString dash = makeDashString(dashed, pattern, dpi, printerScale); QString stroke = (blackOnly) ? "black" : colorString; return QString("") .arg(width * dpi / printerScale) .arg(stroke) .arg(poly.at(0).x() * dpi / printerScale) .arg(poly.at(0).y() * dpi / printerScale) .arg(poly.at(1).x() * dpi / printerScale) .arg(poly.at(1).y() * dpi / printerScale) .arg(poly.at(2).x() * dpi / printerScale) .arg(poly.at(2).y() * dpi / printerScale) .arg(poly.at(3).x() * dpi / printerScale) .arg(poly.at(3).y() * dpi / printerScale) .arg(dash) ; } QString TextUtils::makeRectSVG(QRectF r, QPointF offset, double dpi, double printerScale) { r.translate(-offset.x(), -offset.y()); double l = r.left() * dpi / printerScale; double t = r.top() * dpi / printerScale; double w = r.width() * dpi / printerScale; double h = r.height() * dpi / printerScale; QString stroke = "black"; return QString("") .arg(l) .arg(t) .arg(w) .arg(h) .arg(1 * dpi / printerScale) .arg(stroke); } QString TextUtils::makePolySVG(const QPolygonF & poly, QPointF offset, double width, QString colorString, double dpi, double printerScale, bool blackOnly) { QString polyString = QString("\n"; return polyString; } QPolygonF TextUtils::polygonFromElement(QDomElement & element) { QPolygonF poly; QDomElement point = element.firstChildElement("point"); while (!point.isNull()) { double x = point.attribute("x").toDouble(); double y = point.attribute("y").toDouble(); poly.append(QPointF(x, y)); point = point.nextSiblingElement("point"); } return poly; } QString TextUtils::pointToSvgString(QPointF p, QPointF offset, double dpi, double printerScale) { QString point; point += QString::number((p.x() - offset.x()) * dpi / printerScale); point += ","; point += QString::number((p.y() - offset.y()) * dpi / printerScale); return point; } QString TextUtils::removeSVGHeader(QString & string) { int ix = string.indexOf("", ix); if (ix < 0) return string; int jx = string.indexOf(""); if (jx < 0) return string; string.remove(jx, 6); string.remove(0, ix + 1); return string; } /* QString TextUtils::getMacAddress() { // http://stackoverflow.com/questions/7609953/obtaining-mac-address-on-windows-in-qt foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) { // Return only the first non-loopback MAC Address if (!(interface.flags() & QNetworkInterface::IsLoopBack)) return interface.hardwareAddress(); } return QString(); } */ QString TextUtils::expandAndFill(const QString & svg, const QString & color, double expandBy) { QDomDocument domDocument; QString errorStr; int errorLine; int errorColumn; bool result = domDocument.setContent(svg, &errorStr, &errorLine, &errorColumn); if (!result) { return ""; } QDomElement root = domDocument.documentElement(); expandAndFillAux(root, color, expandBy); return domDocument.toString(); } void TextUtils::expandAndFillAux(QDomElement & element, const QString & color, double expandBy) { bool gotChildren = false; QDomElement child = element.firstChildElement(); while (!child.isNull()) { gotChildren = true; expandAndFillAux(child, color, expandBy); child = child.nextSiblingElement(); } if (gotChildren) return; QString fill = element.attribute("fill"); QString stroke = element.attribute("stroke"); QString strokeWidth = element.attribute("stroke-width"); if (stroke.isEmpty() && fill.isEmpty()) { return; } element.setAttribute("fill", color); element.setAttribute("stroke", color); if (strokeWidth.isEmpty()) { strokeWidth = "0"; } double sw = strokeWidth.toDouble(); sw += expandBy; element.setAttribute("stroke-width", QString::number(sw)); } bool TextUtils::writeUtf8(const QString & fileName, const QString & text) { QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream out(&file); out.setCodec("UTF-8"); out << text; file.close(); return true; } return false; } int TextUtils::getPinsAndSpacing(const QString & expectedFileName, QString & spacingString) { QStringList pieces = expectedFileName.split("_"); int pix = 0; foreach (QString piece, pieces) { bool ok; piece.toInt(&ok); if (ok) break; pix++; } if (pix >= pieces.count()) return 0; int pins = pieces.at(pix).toInt(); spacingString = "100mil"; for (++pix; pix < pieces.count(); pix++) { if (QRegExp("\\d").indexIn(pieces.at(pix)) == 0) { spacingString = pieces.at(pix); return pins; } } return pins; } QSizeF TextUtils::parseForWidthAndHeight(const QString & svg) { QRectF viewBox; return parseForWidthAndHeight(svg, viewBox, false); } QString TextUtils::parseForModuleID(const QString & fzp) { QXmlStreamReader streamReader(fzp); streamReader.setNamespaceProcessing(false); while (!streamReader.atEnd()) { switch (streamReader.readNext()) { case QXmlStreamReader::StartElement: if (streamReader.name().toString().compare("module") == 0) { return streamReader.attributes().value("moduleId").toString(); } break; default: break; } } return ""; } QSizeF TextUtils::parseForWidthAndHeight(const QString & svg, QRectF & viewBox, bool getViewBox) { QXmlStreamReader streamReader(svg); return parseForWidthAndHeight(streamReader, viewBox, getViewBox); } QSizeF TextUtils::parseForWidthAndHeight(QXmlStreamReader & svg) { QRectF viewBox; return parseForWidthAndHeight(svg, viewBox, false); } QSizeF TextUtils::parseForWidthAndHeight(QXmlStreamReader & svg, QRectF & viewBox, bool getViewBox) { svg.setNamespaceProcessing(false); QSizeF size(0, 0); viewBox.setRect(0, 0, 0, 0); bool isIllustrator = false; bool bad = false; while (!svg.atEnd() && !bad) { switch (svg.readNext()) { case QXmlStreamReader::Comment: if (!isIllustrator) { isIllustrator = TextUtils::isIllustratorFile(svg.text().toString()); } break; case QXmlStreamReader::StartElement: if (svg.name().toString().compare("svg") == 0) { QString ws = svg.attributes().value("width").toString(); QString hs = svg.attributes().value("height").toString(); bool okw, okh; double w = TextUtils::convertToInches(ws, &okw, isIllustrator); double h = TextUtils::convertToInches(hs, &okh, isIllustrator); if (!okw || qIsNaN(w) || qIsInf(w) || !okh || qIsNaN(h) || qIsInf(h)) { bad = true; break; } size.setWidth(w); size.setHeight(h); if (getViewBox) { bool gotViewBox = false; QString vb = svg.attributes().value("viewBox").toString(); QStringList vbs = vb.split(QRegExp(",| ")); if (vbs.count() == 4) { bool ok = false; double d[4]; for (int i = 0; i < 4; i++) { d[i] = vbs.at(i).toDouble(&ok); if (!ok) break; } if (ok) { gotViewBox = true; viewBox.setRect(d[0], d[1], d[2], d[3]); } } if (!gotViewBox) { chopNotDigits(hs); chopNotDigits(ws); viewBox.setRect(0, 0, ws.toDouble(), hs.toDouble()); } } return size; } break; default: break; } } return size; } void TextUtils::gornTree(QDomDocument & doc) { QDomElement root = doc.documentElement(); QString oldid = root.attribute("id"); root.setAttribute("id", "0"); root.setAttribute("gorn", "0"); root.setAttribute("oldid", oldid); gornTreeAux(root); } void TextUtils::gornTreeAux(QDomElement & root) { QString prefix = root.attribute("id"); QDomElement child = root.firstChildElement(); int index = 0; while (!child.isNull()) { QString oldid = child.attribute("id"); QString newid = QString("%1.%2").arg(prefix).arg(index++); child.setAttribute("id", newid); child.setAttribute("gorn", newid); child.setAttribute("oldid", oldid); gornTreeAux(child); child = child.nextSiblingElement(); } } bool TextUtils::elevateTransform(QDomElement & root) { QList transforms; collectTransforms(root, transforms); if (transforms.length() == 0) return false; foreach (QDomElement element, transforms) { QString transform = element.attribute("transform"); element.removeAttribute("transform"); QDomElement g = element.ownerDocument().createElement("g"); g.setAttribute("transform", transform); element.parentNode().insertBefore(g, element); g.appendChild(element); } return true; } void TextUtils::collectTransforms(QDomElement & root, QList & transforms) { QString transform = root.attribute("transform"); if (!transform.isEmpty()) { transforms.append(root); } QDomElement child = root.firstChildElement(); while (!child.isNull()) { collectTransforms(child, transforms); child = child.nextSiblingElement(); } } bool TextUtils::fixFonts(QString & svg, const QString & destFont, bool & reallyFixed) { bool changed = removeFontFamilySingleQuotes(svg); reallyFixed = fixUnavailableFontFamilies(svg, destFont); changed |= reallyFixed; return changed; } void TextUtils::fixStyleAttribute(QDomElement & element) { QString style = element.attribute("style"); if (style.isEmpty()) return; fixStyleAttribute(element, style, "stroke-width"); fixStyleAttribute(element, style, "stroke"); fixStyleAttribute(element, style, "fill"); fixStyleAttribute(element, style, "fill-opacity"); fixStyleAttribute(element, style, "stroke-opacity"); fixStyleAttribute(element, style, "font-size"); if (style.trimmed().isEmpty()) { element.removeAttribute("style"); } else { element.setAttribute("style", style); } //QString deleteMe; //QTextStream stream(&deleteMe); //stream << element; //DebugDialog::debug(deleteMe); } void TextUtils::fixStyleAttribute(QDomElement & element, QString & style, const QString & attributeName) { static const QString findStyle("%1[\\s]*:[\\s]*([^;]*)[;]?"); QString str = findStyle.arg(attributeName); QRegExp sw(str); if (sw.indexIn(style) >= 0) { QString value = sw.cap(1); style.remove(sw); element.setAttribute(attributeName, value); } } QString TextUtils::getRandText() { QString rand = QUuid::createUuid().toString(); QString randext = QCryptographicHash::hash(rand.toLatin1(),QCryptographicHash::Md4).toHex(); return randext; } /*QString TextUtils::getBase64RandText() { QString rand = QUuid::createUuid().toString(); QString randext = QCryptographicHash::hash(rand.toLatin1(),QCryptographicHash::Md4).toHex(); return randext; }*/ bool TextUtils::ensureViewBox(QDomDocument doc, double dpi, QRectF & rect, bool convert, double & w, double & h, bool getwh) { bool isIllustrator = TextUtils::isIllustratorDoc(doc); QDomElement root = doc.documentElement(); QString viewBox = root.attribute("viewBox"); if (viewBox.isEmpty() || getwh) { bool ok1, ok2; if (convert) { w = TextUtils::convertToInches(root.attribute("width"), &ok1, isIllustrator) * dpi; h = TextUtils::convertToInches(root.attribute("height"), &ok2, isIllustrator) * dpi; } else { w = root.attribute("width").toDouble(&ok1); h = root.attribute("height").toDouble(&ok2); } if (!ok1 || !ok2) { return false; } } if (viewBox.isEmpty()) { root.setAttribute("viewBox", QString("0 0 %1 %2").arg(w).arg(h)); rect.setRect(0, 0, w, h); return true; } QStringList coords = viewBox.split(QRegExp(" |,")); if (coords.count() != 4) return false; rect.setRect(coords.at(0).toDouble(), coords.at(1).toDouble(), coords.at(2).toDouble(), coords.at(3).toDouble()); return true; } QString TextUtils::findAnchor(const QDomElement & text) { if (text.isNull()) return "start"; QString anchor = text.attribute("text-anchor"); if (!anchor.isEmpty()) return anchor; return findAnchor(text.parentNode().toElement()); } void TextUtils::resplit(QStringList & names, const QString & split) { QStringList result; QString appender = split; if (appender == " ") appender = ""; foreach (QString name, names) { QStringList sub = name.split(split, QString::SkipEmptyParts); for (int i = 0; i < sub.count(); i++) { QString s = sub.at(i); if (i < sub.count() - 1) s.append(appender); result.append(s); } } names.clear(); names.append(result); } fritzing-app-0.9.2b/src/utils/textutils.h000066400000000000000000000226101250202676700204530ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6984 $: $Author: irascibl@gmail.com $: $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $ ********************************************************************/ #ifndef TEXTUTILS_H #define TEXTUTILS_H #include #include #include #include #include #include typedef QString (*CopyPinFunction)(int pin, const QString & argString, void * userData); typedef QString (*MultiplyPinFunction)(int pin, double increment, double value); class TextUtils { public: static QSet getRegexpCaptures(const QString &pattern, const QString &textToSearchIn); static QDomElement findElementWithAttribute(QDomElement element, const QString & attributeName, const QString & attributeValue); static void findElementsWithAttribute(QDomElement & element, const QString & att, QList & elements); static double convertToInches(const QString & string, bool * ok, bool isIllustrator); static double convertToInches(const QString & string); static QString convertToPowerPrefix(double); static double convertFromPowerPrefix(const QString & val, const QString & symbol); static double convertFromPowerPrefixU(QString & val, const QString & symbol); static QString replaceTextElement(const QString & svg, const QString & id, const QString & newValue); static QByteArray replaceTextElement(const QByteArray & svg, const QString & id, const QString & newValue); static QString replaceTextElements(const QString & svg, const QHash &); static bool squashElement(QDomDocument &, const QString & elementName, const QString & attName, const QRegExp & matchContent); static QString mergeSvg(const QString & svg1, const QString & svg2, const QString & id, bool flip); static QString mergeSvgFinish(QDomDocument & doc); static bool mergeSvg(QDomDocument & doc1, const QString & svg, const QString & id); static QString makeSVGHeader(double printerscale, double dpi, double width, double height); static bool isIllustratorFile(const QString &fileContent); static bool isIllustratorFile(const QByteArray &fileContent); static bool isIllustratorDoc(const QDomDocument & doc); static QString removeXMLEntities(QString svgContent); static bool cleanSodipodi(QString &bytes); static bool fixPixelDimensionsIn(QString &fileContent); static bool addCopper1(const QString & filename, QDomDocument & doc, const QString & srcAtt, const QString & destAtt); static void setSVGTransform(QDomElement &, QMatrix &); static QString svgMatrix(const QMatrix &); static QString svgMatrix(const QTransform &); static QString svgTransform(const QString & svg, QTransform & transform, bool translate, const QString extra); static bool getSvgSizes(QDomDocument & doc, double & sWidth, double & sHeight, double & vbWidth, double & vbHeight); static bool findText(const QDomNode & node, QString & text); static QString stripNonValidXMLCharacters(const QString & str); static QString convertExtendedChars(const QString & str); static QString escapeAnd(const QString &); static QMatrix elementToMatrix(QDomElement & element); static QMatrix transformStringToMatrix(const QString & transform); static QList getTransformFloats(QDomElement & element); static QList getTransformFloats(const QString & transform); static QString svgNSOnly(QString svgContent); static QString killXMLNS(QString svgContent); static void gWrap(QDomDocument & domDocument, const QHash & attributes); static void slamStrokeAndFill(QDomElement &, const QString & stroke, const QString & strokeWidth, const QString & fill); static QString slamStrokeAndFill(const QString & svg, const QString & stroke, const QString & strokeWidth, const QString & fill); static QString incrementTemplate(const QString & filename, int pins, double unitIncrement, MultiplyPinFunction, CopyPinFunction, void * userData); static QString incrementTemplateString(const QString & templateString, int pins, double increment, MultiplyPinFunction, CopyPinFunction, void * userData); static QString standardCopyPinFunction(int pin, const QString & argString, void * userData); static QString standardMultiplyPinFunction(int pin, double increment, double value); static QString noCopyPinFunction(int pin, const QString & argString, void * userData); static QString incMultiplyPinFunction(int pin, double increment, double value); static QString incCopyPinFunction(int pin, const QString & argString, void * userData); static QString negIncCopyPinFunction(int pin, const QString & argString, void * userData); static double getViewBoxCoord(const QString & svg, int coord); static QString makeLineSVG(QPointF p1, QPointF p2, double width, QString colorString, double dpi, double printerScale, bool blackOnly, bool dashed, const QVector &); static QString makeCubicBezierSVG(const QPolygonF & controlPoints, double width, QString colorString, double dpi, double printerScale, bool blackOnly, bool dashed, const QVector &); static QString makeRectSVG(QRectF r, QPointF offset, double dpi, double printerscale); static QString makePolySVG(const QPolygonF & poly, QPointF offset, double width, QString colorString, double dpi, double printerScale, bool blackOnly); static QPolygonF polygonFromElement(QDomElement & element); static QString pointToSvgString(QPointF p, QPointF offset, double dpi, double printerScale); static void replaceChildText(QDomNode & node, const QString & text); static void replaceElementChildText(QDomElement & root, const QString & elementName, const QString & text); static QString removeSVGHeader(QString & string); //static QString getMacAddress(); static QString expandAndFill(const QString & svg, const QString & color, double expandBy); static void expandAndFillAux(QDomElement &, const QString & color, double expandBy); static bool writeUtf8(const QString & fileName, const QString & text); static int getPinsAndSpacing(const QString & expectedFileName, QString & spacingString); static QSizeF parseForWidthAndHeight(QXmlStreamReader &, QRectF & viewBox, bool getViewBox); static QSizeF parseForWidthAndHeight(QXmlStreamReader &); static QSizeF parseForWidthAndHeight(const QString & svg, QRectF & viewBox, bool getViewBox); static QSizeF parseForWidthAndHeight(const QString & svg); static void gornTree(QDomDocument &); static bool elevateTransform(QDomElement &); static bool fixMuch(QString &svg, bool fixStrokeWidth); static bool fixInternalUnits(QString & svg); static bool fixFonts(QString & svg, const QString & destFont, bool & reallyFixed); static void fixStyleAttribute(QDomElement & element); static QString parseForModuleID(const QString & fzp); static QString getRandText(); static bool ensureViewBox(QDomDocument doc, double dpi, QRectF & rect, bool toInches, double & w, double & h, bool getwh); static QString findAnchor(const QDomElement & text); static double getStrokeWidth(QDomElement &, double defaultValue); static void resplit(QStringList & names, const QString & split); public: static const QRegExp FindWhitespace; static const QString SMDFlipSuffix; static const QString MicroSymbol; static const ushort MicroSymbolCode; static const QString PowerPrefixesString; static const QString CreatedWithFritzingString; static const QString CreatedWithFritzingXmlComment; static void collectLeaves(QDomElement & element, int & index, QVector & leaves); static void collectLeaves(QDomElement & element, QList & leaves); static const QRegExp floatingPointMatcher; static const QString RegexFloatDetector; static const QString AdobeIllustratorIdentifier; protected: static bool pxToInches(QDomElement &elem, const QString &attrName, bool isIllustrator); static void squashNotElement(QDomElement & element, const QString & elementName, const QString & attName, const QRegExp & matchContent, bool & result); static void initPowerPrefixes(); static QDomElement copyText(QDomDocument & svgDom, QDomElement & parent, QDomElement & text, const QString & defaultX, const QString & defaultY, bool copyAttributes); static void gornTreeAux(QDomElement &); static bool noPatternAux(QDomDocument & svgDom, const QString & tag); static bool noUseAux(QDomDocument & svgDom); static bool tspanRemoveAux(QDomDocument & svgDom); static void fixStyleAttribute(QDomElement & element, QString & style, const QString & attributeName); static bool fixStrokeWidth(QDomDocument & svgDoc); static bool fixViewBox(QDomElement & root); static void chopNotDigits(QString &); static void collectTransforms(QDomElement & root, QList & transforms); }; #endif fritzing-app-0.9.2b/src/utils/zoomslider.cpp000066400000000000000000000200521250202676700211260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include #include #include #include #include #include #include #include #include #include "zoomslider.h" #include "../debugdialog.h" double ZoomSlider::ZoomStep; QList ZoomSlider::ZoomFactors; static const int MIN_VALUE = 10; static const int STARTING_VALUE = 100; static const int HEIGHT = 16; static const int STEP = 100; static int AutoRepeatDelay = 0; static int AutoRepeatInterval = 0; /////////////////////////////////////////////// ZoomLabel::ZoomLabel(QWidget * parent) : QLabel(parent) { if (AutoRepeatDelay == 0) { QPushButton button; AutoRepeatInterval = button.autoRepeatInterval(); AutoRepeatDelay = button.autoRepeatDelay(); } m_autoRepeat = m_mouseIsDown = m_mouseIsIn = m_repeated = false; m_timer.setSingleShot(false); m_timer.setInterval(AutoRepeatInterval); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) m_timer.setTimerType(Qt::PreciseTimer); #endif connect(&m_timer, SIGNAL(timeout()), this, SLOT(repeat())); } ZoomLabel::~ZoomLabel() { } void ZoomLabel::setAutoRepeat(bool autoRepeat) { m_autoRepeat = autoRepeat; } void ZoomLabel::setImages(const QString & normal, const QString & pressed) { m_normal.load(normal); m_pressed.load(pressed); setPixmap(m_normal); } void ZoomLabel::repeat() { if (m_mouseIsIn && m_mouseIsDown) { m_repeated = true; emit clicked(); } } void ZoomLabel::mousePressEvent(QMouseEvent * event) { m_timer.stop(); this->setMouseTracking(true); this->setPixmap(m_pressed); QLabel::mousePressEvent(event); m_mouseIsDown = m_mouseIsIn = true; m_repeated = false; if (m_autoRepeat) { m_timer.start(AutoRepeatDelay); } } void ZoomLabel::mouseMoveEvent(QMouseEvent * event) { QLabel::mouseMoveEvent(event); if (m_mouseIsDown) { QPoint p = event->pos(); bool mouseIsIn = p.x() >= 0 && p.y() >= 0 && p.x() <= width() && p.y() <= height(); if (m_mouseIsIn && !mouseIsIn) { m_timer.stop(); this->setPixmap(m_normal); m_mouseIsIn = false; } else if (!m_mouseIsIn && mouseIsIn) { this->setPixmap(m_pressed); m_mouseIsIn = true; m_timer.start(AutoRepeatDelay); } } } void ZoomLabel::mouseReleaseEvent(QMouseEvent * event) { m_timer.stop(); this->setMouseTracking(false); m_mouseIsDown = false; this->setPixmap(m_normal); QLabel::mouseReleaseEvent(event); if (!m_repeated && m_mouseIsIn) { emit clicked(); } } ///////////////////////////////////////////// ZoomSlider::ZoomSlider(int maxValue, QWidget * parent) : QFrame(parent) { // layout doesn't seem to work: the slider appears too far down in the status bar // because the status bar layout is privileged for the message text m_firstTime = true; if (ZoomFactors.size() == 0) { loadFactors(); } this->setObjectName("ZoomSliderFrame"); m_lineEdit = new QLineEdit(this); m_lineEdit->setObjectName("ZoomSliderValue"); m_lineEdit->setText(QString("%1").arg(STARTING_VALUE)); m_lineEdit->setValidator(new QIntValidator(MIN_VALUE, maxValue + MIN_VALUE, this)); m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, 0); m_lineEdit->setAlignment(Qt::AlignRight | Qt::AlignVCenter); m_suffix = new QLabel(tr("%"), this); m_suffix->setObjectName("ZoomSliderLabel"); m_minusButton = new ZoomLabel(this); m_minusButton->setImages(":/resources/images/icons/zoomSliderMinus.png", ":/resources/images/icons/zoomSliderMinusPressed.png"); m_minusButton->setAutoRepeat(true); m_minusButton->setObjectName("ZoomSliderButton"); connect(m_minusButton, SIGNAL(clicked()), this, SLOT(minusClicked())); m_slider = new QSlider(this); m_slider->setObjectName("ZoomSliderSlider"); m_slider->setOrientation(Qt::Horizontal); m_slider->setRange(MIN_VALUE, maxValue + MIN_VALUE); m_slider->setValue(STARTING_VALUE); m_slider->setTickPosition(QSlider::TicksBelow); m_slider->setTickInterval(500); m_plusButton = new ZoomLabel(this); m_plusButton->setImages(":/resources/images/icons/zoomSliderPlus.png", ":/resources/images/icons/zoomSliderPlusPressed.png"); m_plusButton->setAutoRepeat(true); m_plusButton->setObjectName("ZoomSliderButton"); connect(m_plusButton, SIGNAL(clicked()), this, SLOT(plusClicked())); connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); connect(m_lineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(sliderTextEdited(const QString &))); //m_userStillWriting = false; //m_valueBackup = editText(); //m_indexBackup = itemIndex(m_valueBackup); } void ZoomSlider::loadFactors() { QFile file(":/resources/zoomfactors.txt"); file.open(QFile::ReadOnly); QTextStream stream( &file ); int lineNumber = 0; while(!stream.atEnd()) { QString line = stream.readLine(); if(lineNumber != 0) { ZoomFactors << line.toDouble(); } else { ZoomStep = line.toDouble(); } lineNumber++; } file.close(); } void ZoomSlider::setValue(double value) { QString newText = QString("%1").arg(qRound(value)); m_lineEdit->setText(newText); sliderTextEdited(newText, false); } double ZoomSlider::value() { return m_lineEdit->text().toDouble(); } void ZoomSlider::minusClicked() { step(-1); } void ZoomSlider::plusClicked() { step(1); } void ZoomSlider::step(int direction) { int minIndex = 0; double minDiff = std::numeric_limits::max(); double v = value(); for (int i = 0; i < ZoomFactors.count(); i++) { double f = ZoomFactors[i]; if (qAbs(f - v) < minDiff) { minDiff = qAbs(f - v); minIndex = i; } } minIndex += direction; if (minIndex < 0) { minIndex = 0; } else if (minIndex >= ZoomFactors.count()) { minIndex = ZoomFactors.count() - 1; } setValue(ZoomFactors[minIndex]); emit zoomChanged(ZoomFactors[minIndex]); } void ZoomSlider::sliderValueChanged(int newValue) { newValue = (newValue / 10) * 10; // make it so moving the slider outputs nice rounded values QString newText = QString("%1").arg(newValue); if (newText.compare(m_lineEdit->text()) != 0) { m_lineEdit->setText(newText); emit zoomChanged(newValue); } } void ZoomSlider::sliderTextEdited(const QString & newText) { sliderTextEdited(newText, true); } void ZoomSlider::sliderTextEdited(const QString & newText, bool doEmit) { int value = newText.toInt(); if (m_slider->value() != value) { disconnect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); m_slider->setValue(value); connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); if (doEmit) emit zoomChanged(value); } } void ZoomSlider::zoomIn () { plusClicked(); } void ZoomSlider::zoomOut () { minusClicked(); } void ZoomSlider::showEvent(QShowEvent * event) { // can't get QHLayout to work, so shoving widgets into place here // because widths aren't set at constructor time QFrame::showEvent(event); if (m_firstTime) { m_firstTime = false; int soFar = 0; m_lineEdit->move(soFar, -2); soFar += m_lineEdit->width(); m_suffix->move(soFar, 0); soFar += m_suffix->width(); m_minusButton->move(soFar, 0); soFar += m_minusButton->width(); m_slider->move(soFar, 0); soFar += m_slider->width(); m_plusButton->move(soFar, 0); } } fritzing-app-0.9.2b/src/utils/zoomslider.h000066400000000000000000000054221250202676700205770ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef ZOOMSLIDER_H_ #define ZOOMSLIDER_H_ #include #include #include #include #include #include #include #include class ZoomLabel : public QLabel { Q_OBJECT public: ZoomLabel(QWidget * parent); ~ZoomLabel(); void setImages(const QString & normal, const QString & pressed); void setAutoRepeat(bool); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); signals: void clicked(); protected slots: void repeat(); protected: QTimer m_timer; QPixmap m_pressed; QPixmap m_normal; bool m_autoRepeat; bool m_mouseIsDown; bool m_mouseIsIn; bool m_repeated; }; class ZoomSlider: public QFrame { Q_OBJECT public: ZoomSlider(int maxValue, QWidget * parent=0); void setValue(double); double value(); void zoomOut(); void zoomIn(); protected slots: //void emitZoomChanged(); //void updateBackupFieldsIfOptionSelected(int index); void sliderValueChanged(int newValue); void sliderTextEdited(const QString & newText); void minusClicked(); void plusClicked(); protected: void step(int direction); void sliderTextEdited(const QString & newValue, bool doEmit); void showEvent(QShowEvent * event); static void loadFactors(); protected: //int itemIndex(QString value); //void updateBackupFields(); static QList ZoomFactors; //bool m_userStillWriting; //QString m_valueBackup; //int m_indexBackup; QSlider * m_slider; QLineEdit * m_lineEdit; ZoomLabel * m_plusButton; ZoomLabel * m_minusButton; QLabel * m_suffix; bool m_firstTime; public: static double ZoomStep; signals: void zoomChanged(double newZoom); }; #endif /* ZOOMSLIDER_H_ */ fritzing-app-0.9.2b/src/version/000077500000000000000000000000001250202676700165615ustar00rootroot00000000000000fritzing-app-0.9.2b/src/version/updatedialog.cpp000066400000000000000000000127521250202676700217360ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ // much code borrowed from Qt's rsslisting example #include "updatedialog.h" #include "version.h" #include "versionchecker.h" #include "../debugdialog.h" #include #include #include #include UpdateDialog::UpdateDialog(QWidget *parent) : QDialog(parent) { m_versionChecker = NULL; this->setWindowTitle(QObject::tr("Check for updates")); QVBoxLayout * vLayout = new QVBoxLayout(this); m_feedbackLabel = new QLabel(); m_feedbackLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard); m_feedbackLabel->setOpenExternalLinks(true); vLayout->addWidget(m_feedbackLabel); QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Close")); connect(buttonBox, SIGNAL(accepted()), this, SLOT(stopClose())); vLayout->addWidget(buttonBox); this->setLayout(vLayout); } UpdateDialog::~UpdateDialog() { if (m_versionChecker) { delete m_versionChecker; } } void UpdateDialog::setAvailableReleases(const QList & availableReleases) { AvailableRelease * interimRelease = NULL; AvailableRelease * mainRelease = NULL; foreach (AvailableRelease * availableRelease, availableReleases) { if (availableRelease->interim && (interimRelease == NULL)) { interimRelease = availableRelease; continue; } if (!availableRelease->interim && (mainRelease == NULL)) { mainRelease = availableRelease; continue; } if (mainRelease != NULL && interimRelease != NULL) break; } if (mainRelease == NULL && interimRelease == NULL) { if (m_atUserRequest) { m_feedbackLabel->setText(tr("No new versions found.")); } return; } QSettings settings; QString style; QFile css(":/resources/styles/updatedialog.css"); if (css.open(QIODevice::ReadOnly)) { style = css.readAll(); css.close(); } QString text = QString("").arg(style); if (mainRelease) { text += genTable(tr("A new main release is available for downloading:"), mainRelease); settings.setValue("lastMainVersionChecked", mainRelease->versionString); } if (interimRelease) { text += genTable(tr("A new interim release is available for downloading:"), interimRelease); settings.setValue("lastInterimVersionChecked", interimRelease->versionString); } text += ""; m_feedbackLabel->setText(text); this->show(); } void UpdateDialog::setVersionChecker(VersionChecker * versionChecker) { if (m_versionChecker != NULL) { m_versionChecker->stop(); delete m_versionChecker; } m_feedbackLabel->setText(tr("Checking...")); m_versionChecker = versionChecker; connect(m_versionChecker, SIGNAL(releasesAvailable()), this, SLOT(releasesAvailableSlot())); connect(m_versionChecker, SIGNAL(xmlError(QXmlStreamReader::Error)), this, SLOT(xmlErrorSlot(QXmlStreamReader::Error))); connect(m_versionChecker, SIGNAL(httpError(QNetworkReply::NetworkError)), this, SLOT(httpErrorSlot(QNetworkReply::NetworkError))); m_versionChecker->fetch(); } void UpdateDialog::httpErrorSlot(QNetworkReply::NetworkError) { handleError(); } void UpdateDialog::releasesAvailableSlot() { setAvailableReleases(m_versionChecker->availableReleases()); emit enableAgainSignal(true); } void UpdateDialog::xmlErrorSlot(QXmlStreamReader::Error errorCode) { Q_UNUSED(errorCode); handleError(); } void UpdateDialog::handleError() { DebugDialog::debug("handle error"); if (m_atUserRequest) { m_feedbackLabel->setText(tr("Sorry, unable to retrieve update info")); } else { // automatic update check: don't bother the user } emit enableAgainSignal(true); DebugDialog::debug("handle error done"); } void UpdateDialog::setAtUserRequest(bool atUserRequest) { m_atUserRequest = atUserRequest; } void UpdateDialog::stopClose() { m_versionChecker->stop(); this->close(); } QString UpdateDialog::genTable(const QString & title, AvailableRelease * release) { return QString( "

    " "

    %1

    " "
    " "" "" "" "" "
    Version %2(%3)" "
    " "
    %5
    " "
    " "

    " ) .arg(title) .arg(release->versionString) .arg(release->dateTime.toString(Qt::DefaultLocaleShortDate)) .arg(release->link) .arg(release->summary.replace("changelog:", "", Qt::CaseInsensitive)); } fritzing-app-0.9.2b/src/version/updatedialog.h000066400000000000000000000035561250202676700214050ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef UPDATEDIALOG_H #define UPDATEDIALOG_H #include #include #include #include class UpdateDialog : public QDialog { Q_OBJECT public: UpdateDialog(QWidget *parent = 0); ~UpdateDialog(); void setVersionChecker(class VersionChecker *); void setAtUserRequest(bool); signals: void enableAgainSignal(bool enable); protected slots: void releasesAvailableSlot(); void xmlErrorSlot(QXmlStreamReader::Error errorCode); void httpErrorSlot(QNetworkReply::NetworkError); void stopClose(); protected: void setAvailableReleases(const QList & availableReleases); void handleError(); QString genTable(const QString & title, struct AvailableRelease *); protected: class VersionChecker * m_versionChecker; bool m_atUserRequest; QLabel * m_feedbackLabel; }; #endif fritzing-app-0.9.2b/src/version/version.cpp000066400000000000000000000151231250202676700207540ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty ofswap 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 Fritzing. If not, see . ********************************************************************* $Revision: 9268 $: $Author: irascibl@gmail.com $: $Date: 2014-06-11 17:47:21 +0200 (We, 11. Jun 2013) $ ********************************************************************/ #include "version.h" #include #include #include #include #include "../debugdialog.h" #include "../utils/textutils.h" #include "../lib/qtsysteminfo/QtSystemInfo.h" QString Version::m_majorVersion("0"); QString Version::m_minorVersion("9"); QString Version::m_minorSubVersion("2"); QString Version::m_modifier("b"); QString Version::m_gitCommit("8d2d5970658f0bed09c661c9ea9a515b5f40f44c"); QString Version::m_gitDate("2014-11-19 13:13:28"); QString Version::m_revision; QString Version::m_date; QString Version::m_shortDate; QString Version::m_versionString; QString Version::m_year; QStringList Version::m_modifiers; Version * Version::m_singleton = new Version(); QString Version::FirstVersionWithDetachedUserData = "0.3.1b.05.26.3016"; Version::Version() { if (m_modifiers.count() == 0) { m_modifiers << "a" << "b" << "rc" << ""; } m_revision = m_gitCommit; QStringList strings; strings = m_gitDate.split(" ", QString::SkipEmptyParts); if (strings.size() >= 2) { m_date = strings[0]; strings = m_date.split("-", QString::SkipEmptyParts); if (strings.size() >= 3) { m_shortDate = strings[1] + "." + strings[2]; m_year = strings[0]; } } m_versionString = QString("%1.%2.%3%4.%5.%6").arg(m_majorVersion).arg(m_minorVersion).arg(m_minorSubVersion).arg(m_modifier).arg(m_shortDate).arg(m_revision); } const QString & Version::majorVersion() { return m_majorVersion; } const QString & Version::minorVersion() { return m_minorVersion; } const QString & Version::minorSubVersion() { return m_minorSubVersion; } const QString & Version::revision() { return m_revision; } const QString & Version::modifier() { return m_modifier; } const QString & Version::versionString() { return m_versionString; } const QString & Version::date() { return m_date; } const QString & Version::shortDate() { return m_shortDate; } const QString & Version::year() { return m_year; } bool Version::candidateGreaterThanCurrent(const VersionThing & candidateVersionThing) { VersionThing myVersionThing; myVersionThing.majorVersion = majorVersion().toInt(); myVersionThing.minorVersion = minorVersion().toInt(); myVersionThing.minorSubVersion = minorSubVersion().toInt(); myVersionThing.releaseModifier = modifier(); return greaterThan(myVersionThing, candidateVersionThing); } bool Version::greaterThan(const QString & myVersionStr, const QString & yourVersionStr) { VersionThing myVersionThing; Version::toVersionThing(myVersionStr,myVersionThing); VersionThing yourVersionThing; Version::toVersionThing(yourVersionStr,yourVersionThing); return greaterThan(myVersionThing,yourVersionThing); } bool Version::greaterThan(const VersionThing & myVersionThing, const VersionThing & yourVersionThing) { // yourVersionThing > myVersionThing bool newOne = false; if (yourVersionThing.majorVersion > myVersionThing.majorVersion) { newOne = true; } else if (yourVersionThing.majorVersion == myVersionThing.majorVersion) { if (yourVersionThing.minorVersion > myVersionThing.minorVersion) { newOne = true; } else if (yourVersionThing.minorVersion == myVersionThing.minorVersion) { if (yourVersionThing.minorSubVersion > myVersionThing.minorSubVersion) { newOne = true; } else if (yourVersionThing.minorSubVersion == myVersionThing.minorSubVersion) { newOne = modifierGreaterThan(myVersionThing.releaseModifier, yourVersionThing.releaseModifier); } } } return newOne; } bool Version::modifierGreaterThan(const QString & myReleaseModifier, const QString & yourReleaseModifier) { int yourIndex = m_modifiers.indexOf(yourReleaseModifier); int myIndex = m_modifiers.indexOf(myReleaseModifier); return yourIndex > myIndex; } void Version::toVersionThing(const QString & candidate, VersionThing & versionThing) { versionThing.ok = false; QString modString; foreach (QString s, m_modifiers) { modString += s + "|"; } modString.chop(1); QRegExp sw(QString("([\\d]+)\\.([\\d]+)\\.([\\d]+)[\\.]{0,1}(%1)").arg(modString)); if (sw.indexIn(candidate) != 0) { return; } versionThing.majorVersion = sw.cap(1).toInt(&versionThing.ok); if (!versionThing.ok) return; versionThing.minorVersion = sw.cap(2).toInt(&versionThing.ok); if (!versionThing.ok) return; versionThing.minorSubVersion = sw.cap(3).toInt(&versionThing.ok); if (!versionThing.ok) return; versionThing.releaseModifier = sw.cap(4); } void Version::cleanup() { if (m_singleton) { delete m_singleton; m_singleton = NULL; } } QString Version::makeRequestParamsString(bool withID) { QSettings settings; if (settings.value("pid").isNull()) { settings.setValue("pid", TextUtils::getRandText()); } QString id; if (withID) id = QString("&pid=%1").arg(settings.value("pid").toString()); QtSystemInfo systemInfo(NULL); QString siVersion(QUrl::toPercentEncoding(Version::versionString())); QString siSystemName(QUrl::toPercentEncoding(systemInfo.systemName())); QString siSystemVersion(QUrl::toPercentEncoding(systemInfo.systemVersion())); QString siKernelName(QUrl::toPercentEncoding(systemInfo.kernelName())); QString siKernelVersion(QUrl::toPercentEncoding(systemInfo.kernelVersion())); QString siArchitecture(QUrl::toPercentEncoding(systemInfo.architectureName())); QString string = QString("?version=%2&sysname=%3&kernname=%4&kernversion=%5&arch=%6&sysversion=%7%8") .arg(siVersion) .arg(siSystemName) .arg(siKernelName) .arg(siKernelVersion) .arg(siArchitecture) .arg(siSystemVersion) .arg(id) ; return string; } fritzing-app-0.9.2b/src/version/version.h000066400000000000000000000050551250202676700204240ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2015 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef VERSION_H #define VERSION_H #include struct VersionThing { int majorVersion; int minorVersion; int minorSubVersion; QString releaseModifier; bool ok; }; class Version { public: static const QString & majorVersion(); static const QString & minorVersion(); static const QString & minorSubVersion(); static const QString & modifier(); static const QString & revision(); static const QString & versionString(); static const QString & date(); static const QString & shortDate(); static const QString & year(); static bool candidateGreaterThanCurrent(const VersionThing &); static bool greaterThan(const VersionThing & myVersionThing, const VersionThing & yourVersionThing); static bool greaterThan(const QString & myVersionStr, const QString & yourVersionStr); static bool modifierGreaterThan(const QString & myReleaseModifier, const QString & yourReleaseModifier); static void toVersionThing(const QString & candidate, VersionThing & versionThing); static void cleanup(); static QString makeRequestParamsString(bool withID); public: static QString FirstVersionWithDetachedUserData; protected: Version(); protected: static QString m_majorVersion; static QString m_minorVersion; static QString m_minorSubVersion; static QString m_gitCommit; static QString m_revision; static QString m_modifier; static QString m_versionString; static QString m_gitDate; static QString m_date; static QString m_shortDate; static QString m_year; static Version * m_singleton; static QStringList m_modifiers; }; #endif fritzing-app-0.9.2b/src/version/versionchecker.cpp000066400000000000000000000171411250202676700223030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ // much code borrowed from Qt's rsslisting example #include "versionchecker.h" #include "version.h" #include "../debugdialog.h" #include #include #include VersionChecker::VersionChecker() : QObject() { m_networkReply = NULL; m_depth = 0; m_inSummary = m_inUpdated = m_inTitle = m_inEntry = false; m_ignoreInterimVersion.ok = m_ignoreMainVersion.ok = false; } VersionChecker::~VersionChecker() { foreach (AvailableRelease * availableRelease, m_availableReleases) { delete availableRelease; } m_availableReleases.clear(); } void VersionChecker::fetch() { DebugDialog::debug("http check new version"); m_xml.clear(); QUrl url(m_urlString); QNetworkAccessManager * manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(finished(QNetworkReply *))); QNetworkReply * reply = manager->get(QNetworkRequest(url)); QMutexLocker locker(&m_networkReplyLock); m_networkReply = reply; } void VersionChecker::finished(QNetworkReply * networkReply) { int responseCode = networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (responseCode == 200) { m_xml.addData(networkReply->readAll()); parseXml(); DebugDialog::debug("http check new version no error"); emit releasesAvailable(); } else { DebugDialog::debug(QString("http check new version error %1").arg(networkReply->errorString())); emit httpError(networkReply->error()); } QMutexLocker locker(&m_networkReplyLock); if (networkReply == m_networkReply) { m_networkReply = NULL; } networkReply->manager()->deleteLater(); networkReply->deleteLater(); } void VersionChecker::parseXml() { //DebugDialog::debug("parsing xml"); while (!m_xml.atEnd()) { m_xml.readNext(); if (m_xml.isStartElement()) { QString elementName = m_xml.name().toString(); if (elementName.compare("entry") == 0) { m_inEntry = true; m_inSummary = m_inTitle = m_inUpdated = false; m_currentLinkHref = ""; m_currentCategoryTerm = ""; m_currentTitle = ""; m_currentUpdated = ""; } else if (m_inEntry && elementName.compare("title") == 0) { m_inTitle = true; } else if (m_inEntry && elementName.compare("link") == 0) { if (m_xml.attributes().value("rel").toString().compare("enclosure") == 0) { m_currentLinkHref = m_xml.attributes().value("href").toString(); } } else if (m_inEntry && elementName.compare("category") == 0) { m_currentCategoryTerm = m_xml.attributes().value("term").toString(); } else if (m_inEntry && elementName.compare("updated") == 0) { m_inUpdated = true; } else if (m_inEntry && elementName.compare("summary") == 0) { m_inSummary = true; } //DebugDialog::debug(QString("%1<%2>").arg(QString(m_depth * 4, ' ')).arg(elementName)); m_depth++; //foreach (QXmlStreamAttribute attribute, m_xml.attributes()) { //DebugDialog::debug(QString("%1%2: %3").arg(QString((m_depth + 1) * 4, ' ')).arg(attribute.name().toString()).arg(attribute.value().toString())); //} } else if (m_xml.isEndElement()) { QString elementName = m_xml.name().toString(); if (m_inEntry && elementName.compare("entry") == 0) { m_inEntry = false; parseEntry(); } else if (m_inTitle && elementName.compare("title") == 0) { m_inTitle = false; } else if (m_inUpdated && elementName.compare("updated") == 0) { m_inUpdated = false; } else if (m_inSummary && elementName.compare("summary") == 0) { m_inSummary = false; } m_depth--; //DebugDialog::debug(QString("%1").arg(QString(m_depth * 4, ' ')).arg(elementName)); } else if (m_xml.isCharacters() && !m_xml.isWhitespace()) { QString t = m_xml.text().toString(); t.replace(QRegExp("[\\s]+"), " "); //DebugDialog::debug(QString("%1%2").arg(QString((m_depth + 1) * 4, ' ')).arg(t)); if (m_inTitle) { m_currentTitle = m_xml.text().toString(); } else if (m_inUpdated) { m_currentUpdated = m_xml.text().toString(); } else if (m_inSummary) { m_currentSummary = m_xml.text().toString(); } } } if (m_xml.error() && m_xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) { emit xmlError(m_xml.error()); return; } } void VersionChecker::setUrl(const QString & url) { m_urlString = url; } void VersionChecker::parseEntry() { if (m_currentLinkHref.isEmpty()) return; if (m_currentCategoryTerm.isEmpty()) return; if (m_currentUpdated.isEmpty()) return; #ifndef QT_NO_DEBUG // hack for testing if (m_currentCategoryTerm.compare("main") == 0) { if (m_currentTitle.compare("0.11b") == 0) { m_currentTitle = "0.1.11b"; } else if (m_currentTitle.compare("0.1b") == 0) { m_currentTitle = "0.1.1b"; } } #endif VersionThing entryVersionThing; Version::toVersionThing(m_currentTitle, entryVersionThing); if (!entryVersionThing.ok) { // older versions that don't conform, bail return; } if (!Version::candidateGreaterThanCurrent(entryVersionThing)) { return; } bool interim = (m_currentCategoryTerm.compare("interim") == 0); if (interim) { if (m_ignoreInterimVersion.ok) { if (!Version::greaterThan(m_ignoreInterimVersion, entryVersionThing)) { return; // candidate version is earlier or the same as interim version already in prefs } } } else { if (m_ignoreMainVersion.ok) { if (!Version::greaterThan(m_ignoreMainVersion, entryVersionThing)) { return; // candidate version is earlier or the same as main version already in prefs } } } AvailableRelease * availableRelease = new AvailableRelease(); availableRelease->versionString = m_currentTitle; availableRelease->link = m_currentLinkHref; availableRelease->interim = interim; availableRelease->summary = m_currentSummary; QStringList temp = m_currentUpdated.split('+'); // conversion is confused by the +timezone suffix from the site xml availableRelease->dateTime = QDateTime::fromString(temp[0], "yyyy-MM-ddThh:mm:ss"); m_availableReleases.append(availableRelease); } const QList & VersionChecker::availableReleases() { return m_availableReleases; } void VersionChecker::stop() { if (m_networkReplyLock.tryLock(1)) { if (m_networkReply) { m_networkReply = NULL; } m_networkReplyLock.unlock(); } } void VersionChecker::ignore(const QString & version, bool interim) { if (interim) { Version::toVersionThing(version, m_ignoreInterimVersion); } else { Version::toVersionThing(version, m_ignoreMainVersion); } } fritzing-app-0.9.2b/src/version/versionchecker.h000066400000000000000000000045661250202676700217570ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #ifndef VERSIONCHECKER_H #define VERSIONCHECKER_H #include #include #include #include #include #include "version.h" // much code borrowed from Qt's rsslisting example struct AvailableRelease { bool interim; QString versionString; QString link; QString summary; QDateTime dateTime; }; class VersionChecker : public QObject { Q_OBJECT public: VersionChecker(); ~VersionChecker(); void setUrl(const QString & url); const QList & availableReleases(); void stop(); void ignore(const QString & version, bool interim); signals: void httpError(QNetworkReply::NetworkError); void xmlError(QXmlStreamReader::Error errorCode); void releasesAvailable(); public slots: void fetch(); void finished(QNetworkReply *); protected: void parseXml(); void parseEntry(); protected: QString m_urlString; QXmlStreamReader m_xml; QString m_version; int m_depth; bool m_inEntry; bool m_inTitle; bool m_inUpdated; bool m_inSummary; QList m_availableReleases; QString m_currentLinkHref; QString m_currentCategoryTerm; QString m_currentTitle; QString m_currentUpdated; QString m_currentSummary; VersionThing m_ignoreMainVersion; VersionThing m_ignoreInterimVersion; QNetworkReply * m_networkReply; QMutex m_networkReplyLock; }; #endif fritzing-app-0.9.2b/src/viewgeometry.cpp000066400000000000000000000120431250202676700203260ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #include "viewgeometry.h" #include "utils/graphicsutils.h" ViewGeometry::ViewGeometry( ) { m_z = -1; m_loc.setX(-1); m_loc.setY(-1); m_line.setLine(-1,-1,-1,-1); m_wireFlags = NoFlag; } ViewGeometry::ViewGeometry(const ViewGeometry & that ) { set(that); } ViewGeometry::ViewGeometry(QDomElement & geometry) { m_wireFlags = (WireFlags) geometry.attribute("wireFlags").toInt(); m_z = geometry.attribute("z").toDouble(); m_loc.setX(geometry.attribute("x").toDouble()); m_loc.setY(geometry.attribute("y").toDouble()); QString x1 = geometry.attribute("x1"); if (!x1.isEmpty()) { m_line.setLine( geometry.attribute("x1").toDouble(), geometry.attribute("y1").toDouble(), geometry.attribute("x2").toDouble(), geometry.attribute("y2").toDouble() ); } QString w = geometry.attribute("width"); if (!w.isEmpty()) { m_rect.setX(geometry.attribute("x").toDouble()); m_rect.setY(geometry.attribute("y").toDouble()); m_rect.setWidth(geometry.attribute("width").toDouble()); m_rect.setHeight(geometry.attribute("height").toDouble()); } GraphicsUtils::loadTransform(geometry.firstChildElement("transform"), m_transform); } void ViewGeometry::setZ(double z) { m_z = z; } double ViewGeometry::z() const { return m_z ; } void ViewGeometry::setLoc(QPointF loc) { m_loc = loc; } QPointF ViewGeometry::loc() const { return m_loc ; } void ViewGeometry::setLine(QLineF loc) { m_line = loc; } QLineF ViewGeometry::line() const { return m_line; } void ViewGeometry::offset(double x, double y) { m_loc.setX(x + m_loc.x()); m_loc.setY(y + m_loc.y()); } bool ViewGeometry::selected() { return m_selected; } void ViewGeometry::setSelected(bool selected) { m_selected = selected; } QRectF ViewGeometry::rect() const { return m_rect; } void ViewGeometry::setRect(double x, double y, double width, double height) { m_rect.setRect(x, y, width, height); } void ViewGeometry::setRect(const QRectF & r) { setRect(r.x(), r.y(), r.width(), r.height()); } void ViewGeometry::setTransform(QTransform transform) { m_transform = transform; } QTransform ViewGeometry::transform() const { return m_transform; } void ViewGeometry::set(const ViewGeometry & that) { m_z = that.m_z; m_line = that.m_line; m_loc = that.m_loc; m_transform = that.m_transform; m_wireFlags = that.m_wireFlags; m_rect = that.m_rect; } void ViewGeometry::setRouted(bool routed) { setWireFlag(routed, RoutedFlag); } void ViewGeometry::setPCBTrace(bool trace) { setWireFlag(trace, PCBTraceFlag); } void ViewGeometry::setSchematicTrace(bool trace) { setWireFlag(trace, SchematicTraceFlag); } void ViewGeometry::setRatsnest(bool ratsnest) { setWireFlag(ratsnest, RatsnestFlag); } void ViewGeometry::setNormal(bool normal) { setWireFlag(normal, NormalFlag); } void ViewGeometry::setAutoroutable(bool autoroutable) { setWireFlag(autoroutable, AutoroutableFlag); } bool ViewGeometry::getRouted() const { return m_wireFlags.testFlag(RoutedFlag); } bool ViewGeometry::getNormal() const { return m_wireFlags.testFlag(NormalFlag); } bool ViewGeometry::getPCBTrace() const { return m_wireFlags.testFlag(PCBTraceFlag); } bool ViewGeometry::getAnyTrace() const { return getPCBTrace() || getSchematicTrace(); } bool ViewGeometry::getSchematicTrace() const { return m_wireFlags.testFlag(SchematicTraceFlag); } bool ViewGeometry::getRatsnest() const { return m_wireFlags.testFlag(RatsnestFlag); } bool ViewGeometry::getAutoroutable() const { return m_wireFlags.testFlag(AutoroutableFlag); } void ViewGeometry::setWireFlag(bool setting, WireFlag flag) { if (setting) { m_wireFlags |= flag; } else { m_wireFlags &= ~flag; } } int ViewGeometry::flagsAsInt() const { return (int) m_wireFlags; } void ViewGeometry::setWireFlags(WireFlags wireFlags) { m_wireFlags = wireFlags; } bool ViewGeometry::hasFlag(ViewGeometry::WireFlag flag) { return (m_wireFlags & flag) ? true : false; } bool ViewGeometry::hasAnyFlag(ViewGeometry::WireFlags flags) { return (m_wireFlags & flags) ? true : false; } ViewGeometry::WireFlags ViewGeometry::wireFlags() const { return m_wireFlags; } fritzing-app-0.9.2b/src/viewgeometry.h000066400000000000000000000053641250202676700200030ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6112 $: $Author: cohen@irascible.com $: $Date: 2012-06-28 00:18:10 +0200 (Do, 28. Jun 2012) $ ********************************************************************/ #ifndef VIEWGEOMETRY_H #define VIEWGEOMETRY_H #include #include #include #include #include class ViewGeometry { public: ViewGeometry(); ViewGeometry(QDomElement &); ViewGeometry(const ViewGeometry &); ~ViewGeometry() {} public: enum WireFlag { NoFlag = 0, RoutedFlag = 2, PCBTraceFlag = 4, ObsoleteJumperFlag = 8, RatsnestFlag = 16, AutoroutableFlag = 32, NormalFlag = 64, SchematicTraceFlag = 128 }; Q_DECLARE_FLAGS(WireFlags, WireFlag) protected: void setWireFlag(bool setting, WireFlag flag); public: void setZ(double); double z() const; void setLoc(QPointF); QPointF loc() const; void setLine(QLineF); QLineF line() const; void offset(double x, double y); bool selected(); void setSelected(bool); QRectF rect() const; void setRect(double x, double y, double width, double height); void setRect(const QRectF &); void setTransform(QTransform); QTransform transform() const; void set(const ViewGeometry &); void setRouted(bool); bool getRouted() const; void setPCBTrace(bool); bool getPCBTrace() const; bool getAnyTrace() const; void setSchematicTrace(bool); bool getSchematicTrace() const; void setRatsnest(bool); bool getRatsnest() const; void setAutoroutable(bool); bool getAutoroutable() const; void setNormal(bool); bool getNormal() const; void setWireFlags(WireFlags); bool hasFlag(WireFlag); bool hasAnyFlag(WireFlags); int flagsAsInt() const; ViewGeometry::WireFlags wireFlags() const; protected: double m_z; QPointF m_loc; QLineF m_line; QRectF m_rect; bool m_selected; WireFlags m_wireFlags; QTransform m_transform; }; Q_DECLARE_OPERATORS_FOR_FLAGS(ViewGeometry::WireFlags) //Q_DECLARE_METATYPE(ViewGeometry *); #endif fritzing-app-0.9.2b/src/viewlayer.cpp000066400000000000000000000435021250202676700176130ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #include "viewlayer.h" #include "debugdialog.h" #include double ViewLayer::zIncrement = 0.00001; // 0.000000001; QHash ViewLayer::names; QMultiHash ViewLayer::alternatives; QMultiHash ViewLayer::unconnectables; QHash ViewLayer::xmlHash; const QString ViewLayer::Copper0Color = "#f9a435"; // "#FFCB33"; //Bottom const QString ViewLayer::Copper1Color = "#fdde68"; // "#F28A00"; //Top const QString ViewLayer::Copper0WireColor = "#f28a00"; const QString ViewLayer::Copper1WireColor = "#f2c600"; const QString ViewLayer::Silkscreen0Color = "#444444"; const QString ViewLayer::Silkscreen1Color = "#000000"; const QString ViewLayer::BoardColor = "#ffffff"; static LayerList CopperBottomLayers; static LayerList CopperTopLayers; static LayerList NonCopperLayers; // just NonCopperLayers in pcb view static LayerList IconViewLayerList; static LayerList BreadboardViewLayerList; static LayerList SchematicViewLayerList; static LayerList PCBViewLayerList; static LayerList EmptyLayerList; static LayerList PCBViewFromBelowLayerList; NamePair::NamePair(QString xml, QString display) { xmlName = xml; displayName = display; } ////////////////////////////////////////////// class NameTriple { public: NameTriple(const QString & _xmlName, const QString & _viewName, const QString & _naturalName) { m_xmlName = _xmlName; m_viewName = _viewName; m_naturalName = _naturalName; } QString & xmlName() { return m_xmlName; } QString & viewName() { return m_viewName; } QString & naturalName() { return m_naturalName; } protected: QString m_xmlName; QString m_naturalName; QString m_viewName; }; ////////////////////////////////////////////// ViewLayer::ViewLayer(ViewLayerID viewLayerID, bool visible, double initialZ) { m_fromBelow = false; m_viewLayerID = viewLayerID; m_visible = visible; m_action = NULL; m_initialZFromBelow = m_initialZ = initialZ; m_nextZ = 0; m_parentLayer = NULL; m_active = true; m_includeChildLayers = true; } ViewLayer::~ViewLayer() { } void ViewLayer::initNames() { if (CopperBottomLayers.isEmpty()) { CopperBottomLayers << ViewLayer::GroundPlane0 << ViewLayer::Copper0 << ViewLayer::Copper0Trace; } if (CopperTopLayers.isEmpty()) { CopperTopLayers << ViewLayer::GroundPlane1 << ViewLayer::Copper1 << ViewLayer::Copper1Trace; } if (NonCopperLayers.isEmpty()) { NonCopperLayers << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label << ViewLayer::PartImage; } if (names.count() == 0) { // xmlname, displayname names.insert(ViewLayer::Icon, new NamePair("icon", QObject::tr("Icon"))); names.insert(ViewLayer::BreadboardBreadboard, new NamePair("breadboardbreadboard", QObject::tr("Breadboard"))); names.insert(ViewLayer::Breadboard, new NamePair("breadboard", QObject::tr("Parts"))); names.insert(ViewLayer::BreadboardWire, new NamePair("breadboardWire", QObject::tr("Wires"))); names.insert(ViewLayer::BreadboardLabel, new NamePair("breadboardLabel", QObject::tr("Part Labels"))); names.insert(ViewLayer::BreadboardRatsnest, new NamePair("breadboardRatsnest", QObject::tr("Ratsnest"))); names.insert(ViewLayer::BreadboardNote, new NamePair("breadboardNote", QObject::tr("Notes"))); names.insert(ViewLayer::BreadboardRuler, new NamePair("breadboardRuler", QObject::tr("Rulers"))); names.insert(ViewLayer::SchematicFrame, new NamePair("schematicframe", QObject::tr("Frame"))); names.insert(ViewLayer::Schematic, new NamePair("schematic", QObject::tr("Parts"))); names.insert(ViewLayer::SchematicText, new NamePair("schematicText", QObject::tr("Text"))); names.insert(ViewLayer::SchematicWire, new NamePair("schematicWire",QObject::tr("Ratsnest"))); names.insert(ViewLayer::SchematicTrace, new NamePair("schematicTrace",QObject::tr("Wires"))); names.insert(ViewLayer::SchematicLabel, new NamePair("schematicLabel", QObject::tr("Part Labels"))); names.insert(ViewLayer::SchematicNote, new NamePair("schematicNote", QObject::tr("Notes"))); names.insert(ViewLayer::SchematicRuler, new NamePair("schematicRuler", QObject::tr("Rulers"))); names.insert(ViewLayer::Board, new NamePair("board", QObject::tr("Board"))); names.insert(ViewLayer::Silkscreen1, new NamePair("silkscreen", QObject::tr("Silkscreen Top"))); // really should be silkscreen1 names.insert(ViewLayer::Silkscreen1Label, new NamePair("silkscreenLabel", QObject::tr("Silkscreen Top (Part Labels)"))); names.insert(ViewLayer::GroundPlane0, new NamePair("groundplane", QObject::tr("Copper Fill Bottom"))); names.insert(ViewLayer::Copper0, new NamePair("copper0", QObject::tr("Copper Bottom"))); names.insert(ViewLayer::Copper0Trace, new NamePair("copper0trace", QObject::tr("Copper Bottom Trace"))); names.insert(ViewLayer::GroundPlane1, new NamePair("groundplane1", QObject::tr("Copper Fill Top"))); names.insert(ViewLayer::Copper1, new NamePair("copper1", QObject::tr("Copper Top"))); names.insert(ViewLayer::Copper1Trace, new NamePair("copper1trace", QObject::tr("Copper Top Trace"))); names.insert(ViewLayer::PcbRatsnest, new NamePair("ratsnest", QObject::tr("Ratsnest"))); names.insert(ViewLayer::Silkscreen0, new NamePair("silkscreen0", QObject::tr("Silkscreen Bottom"))); names.insert(ViewLayer::Silkscreen0Label, new NamePair("silkscreen0Label", QObject::tr("Silkscreen Bottom (Part Labels)"))); //names.insert(ViewLayer::Soldermask, new NamePair("soldermask", QObject::tr("Solder mask"))); //names.insert(ViewLayer::Outline, new NamePair("outline", QObject::tr("Outline"))); //names.insert(ViewLayer::Keepout, new NamePair("keepout", QObject::tr("Keep out"))); names.insert(ViewLayer::PartImage, new NamePair("partimage", QObject::tr("Part Image"))); names.insert(ViewLayer::PcbNote, new NamePair("pcbNote", QObject::tr("Notes"))); names.insert(ViewLayer::PcbRuler, new NamePair("pcbRuler", QObject::tr("Rulers"))); foreach (ViewLayerID key, names.keys()) { xmlHash.insert(names.value(key)->xmlName, key); } names.insert(ViewLayer::UnknownLayer, new NamePair("unknown", QObject::tr("Unknown Layer"))); alternatives.insert(ViewLayer::Copper0, ViewLayer::Copper1); alternatives.insert(ViewLayer::Copper1, ViewLayer::Copper0); LayerList l0, l1; l0 << ViewLayer::Copper0 << ViewLayer::Copper0Trace << ViewLayer::GroundPlane0; l1 << ViewLayer::Copper1 << ViewLayer::Copper1Trace << ViewLayer::GroundPlane1; foreach (ViewLayer::ViewLayerID viewLayerID0, l0) { foreach (ViewLayer::ViewLayerID viewLayerID1, l1) { unconnectables.insert(viewLayerID0, viewLayerID1); unconnectables.insert(viewLayerID1, viewLayerID0); } } } if (ViewIDNames.count() == 0) { ViewIDNames.insert(ViewLayer::IconView, new NameTriple("iconView", QObject::tr("icon view"), "icon")); ViewIDNames.insert(ViewLayer::BreadboardView, new NameTriple("breadboardView", QObject::tr("breadboard view"), "breadboard")); ViewIDNames.insert(ViewLayer::SchematicView, new NameTriple("schematicView", QObject::tr("schematic view"), "schematic")); ViewIDNames.insert(ViewLayer::PCBView, new NameTriple("pcbView", QObject::tr("pcb view"), "pcb")); } if (BreadboardViewLayerList.count() == 0) { IconViewLayerList << ViewLayer::Icon; BreadboardViewLayerList << ViewLayer::BreadboardBreadboard << ViewLayer::Breadboard << ViewLayer::BreadboardWire << ViewLayer::BreadboardLabel << ViewLayer::BreadboardRatsnest << ViewLayer::BreadboardNote << ViewLayer::BreadboardRuler; SchematicViewLayerList << ViewLayer::SchematicFrame << ViewLayer::Schematic << ViewLayer::SchematicText << ViewLayer::SchematicWire << ViewLayer::SchematicTrace << ViewLayer::SchematicLabel << ViewLayer::SchematicNote << ViewLayer::SchematicRuler; PCBViewLayerList << ViewLayer::Board << ViewLayer::GroundPlane0 << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label << ViewLayer::Copper0 << ViewLayer::Copper0Trace << ViewLayer::GroundPlane1 << ViewLayer::Copper1 << ViewLayer::Copper1Trace << ViewLayer::PcbRatsnest << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label << ViewLayer::PartImage << ViewLayer::PcbNote << ViewLayer::PcbRuler; PCBViewFromBelowLayerList << ViewLayer::Board << ViewLayer::GroundPlane1 << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label << ViewLayer::Copper1 << ViewLayer::Copper1Trace << ViewLayer::GroundPlane0 << ViewLayer::Copper0 << ViewLayer::Copper0Trace << ViewLayer::PcbRatsnest << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label << ViewLayer::PartImage << ViewLayer::PcbNote << ViewLayer::PcbRuler; } } QString & ViewLayer::displayName() { return names[m_viewLayerID]->displayName; } void ViewLayer::setAction(QAction * action) { m_action = action; } QAction* ViewLayer::action() { return m_action; } bool ViewLayer::visible() { return m_visible; } void ViewLayer::setVisible(bool visible) { m_visible = visible; if (m_action) { m_action->setChecked(visible); } } double ViewLayer::nextZ() { double temp = m_nextZ + (m_fromBelow ? m_initialZFromBelow : m_initialZ); m_nextZ += zIncrement; return temp; } ViewLayer::ViewLayerID ViewLayer::viewLayerIDFromXmlString(const QString & viewLayerName) { return xmlHash.value(viewLayerName, ViewLayer::UnknownLayer); } ViewLayer::ViewLayerID ViewLayer::viewLayerID() { return m_viewLayerID; } double ViewLayer::incrementZ(double z) { return (z + zIncrement); } double ViewLayer::getZIncrement() { return zIncrement; } const QString & ViewLayer::viewLayerNameFromID(ViewLayerID viewLayerID) { NamePair * sp = names.value(viewLayerID); if (sp == NULL) return ___emptyString___; return sp->displayName; } const QString & ViewLayer::viewLayerXmlNameFromID(ViewLayerID viewLayerID) { NamePair * sp = names.value(viewLayerID); if (sp == NULL) return ___emptyString___; return sp->xmlName; } ViewLayer * ViewLayer::parentLayer() { return m_parentLayer; } void ViewLayer::setParentLayer(ViewLayer * parent) { m_parentLayer = parent; if (parent) { parent->m_childLayers.append(this); } } const QList & ViewLayer::childLayers() { return m_childLayers; } bool ViewLayer::alreadyInLayer(double z) { if (m_fromBelow) { return (z >= m_initialZFromBelow && z <= m_initialZFromBelow + m_nextZ); } return (z >= m_initialZ && z <= m_initialZ + m_nextZ); } void ViewLayer::cleanup() { foreach (NamePair * sp, names.values()) { delete sp; } names.clear(); foreach (NameTriple * nameTriple, ViewIDNames) { delete nameTriple; } ViewIDNames.clear(); } void ViewLayer::resetNextZ(double z) { m_nextZ = z - floor(z); } LayerList ViewLayer::findAlternativeLayers(ViewLayer::ViewLayerID id) { LayerList alts = alternatives.values(id); return alts; } bool ViewLayer::canConnect(ViewLayer::ViewLayerID v1, ViewLayer::ViewLayerID v2) { if (v1 == v2) return true; LayerList uncs = unconnectables.values(v1); return (!uncs.contains(v2)); } bool ViewLayer::isActive() { return m_active; } void ViewLayer::setActive(bool a) { m_active = a; } ViewLayer::ViewLayerPlacement ViewLayer::specFromID(ViewLayer::ViewLayerID viewLayerID) { switch (viewLayerID) { case Copper1: case Copper1Trace: case GroundPlane1: return ViewLayer::NewTop; default: return ViewLayer::NewBottom; } } bool ViewLayer::isCopperLayer(ViewLayer::ViewLayerID viewLayerID) { if (CopperTopLayers.contains(viewLayerID)) return true; if (CopperBottomLayers.contains(viewLayerID)) return true; return false; } const LayerList & ViewLayer::copperLayers(ViewLayer::ViewLayerPlacement viewLayerPlacement) { if (viewLayerPlacement == ViewLayer::NewTop) return CopperTopLayers; return CopperBottomLayers; } const LayerList & ViewLayer::maskLayers(ViewLayer::ViewLayerPlacement viewLayerPlacement) { static LayerList bottom; static LayerList top; if (bottom.isEmpty()) { bottom << ViewLayer::Copper0; } if (top.isEmpty()) { top << ViewLayer::Copper1; } if (viewLayerPlacement == ViewLayer::NewTop) return top; return bottom; } const LayerList & ViewLayer::silkLayers(ViewLayer::ViewLayerPlacement viewLayerPlacement) { static LayerList bottom; static LayerList top; if (bottom.isEmpty()) { bottom << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label; } if (top.isEmpty()) { top << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label; } if (viewLayerPlacement == ViewLayer::NewTop) return top; return bottom; } const LayerList & ViewLayer::outlineLayers() { static LayerList layerList; if (layerList.isEmpty()) { layerList << ViewLayer::Board; } return layerList; } const LayerList & ViewLayer::drillLayers() { static LayerList layerList; if (layerList.isEmpty()) { layerList << ViewLayer::Copper0 << ViewLayer::Copper1; } return layerList; } const LayerList & ViewLayer::silkLayers() { static LayerList layerList; if (layerList.isEmpty()) { layerList << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen1; } return layerList; } const LayerList & ViewLayer::topLayers() { static LayerList layerList; if (layerList.isEmpty()) { layerList << ViewLayer::Copper1 << ViewLayer::Copper1Trace << ViewLayer::Silkscreen1 << ViewLayer::Silkscreen1Label << ViewLayer::GroundPlane1; } return layerList; } const LayerList & ViewLayer::bottomLayers() { static LayerList layerList; if (layerList.isEmpty()) { layerList << ViewLayer::Copper0 << ViewLayer::Copper0Trace << ViewLayer::Silkscreen0 << ViewLayer::Silkscreen0Label << ViewLayer::GroundPlane0; } return layerList; } bool ViewLayer::isNonCopperLayer(ViewLayer::ViewLayerID viewLayerID) { // for pcb view layers only return NonCopperLayers.contains(viewLayerID); } bool ViewLayer::includeChildLayers() { return m_includeChildLayers; } void ViewLayer::setIncludeChildLayers(bool incl) { m_includeChildLayers = incl; } ///////////////////////////////// QHash ViewLayer::ViewIDNames; QString & ViewLayer::viewIDName(ViewLayer::ViewID viewID) { if (viewID < 0 || viewID >= ViewLayer::ViewCount) { throw "ViewLayer::viewIDName bad identifier"; } return ViewIDNames[viewID]->viewName(); } QString & ViewLayer::viewIDXmlName(ViewLayer::ViewID viewID) { if (viewID < 0 || viewID >= ViewLayer::ViewCount) { throw "ViewLayer::viewIDXmlName bad identifier"; } return ViewIDNames[viewID]->xmlName(); } QString & ViewLayer::viewIDNaturalName(ViewLayer::ViewID viewID) { if (viewID < 0 || viewID >= ViewLayer::ViewCount) { throw "ViewLayer::viewIDNaturalName bad identifier"; } return ViewIDNames[viewID]->naturalName(); } ViewLayer::ViewID ViewLayer::idFromXmlName(const QString & name) { foreach (ViewID id, ViewIDNames.keys()) { NameTriple * nameTriple = ViewIDNames.value(id); if (name.compare(nameTriple->xmlName()) == 0) return id; } return UnknownView; } const LayerList & ViewLayer::layersForView(ViewLayer::ViewID viewID) { switch(viewID) { case IconView: return IconViewLayerList; case BreadboardView: return BreadboardViewLayerList; case SchematicView: return SchematicViewLayerList; case PCBView: return PCBViewLayerList; default: return EmptyLayerList; } } const LayerList & ViewLayer::layersForViewFromBelow(ViewLayer::ViewID viewID) { switch(viewID) { case IconView: return IconViewLayerList; case BreadboardView: return BreadboardViewLayerList; case SchematicView: return SchematicViewLayerList; case PCBView: return PCBViewFromBelowLayerList; default: return EmptyLayerList; } } bool ViewLayer::viewHasLayer(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) { return layersForView(viewID).contains(viewLayerID); } QDomElement ViewLayer::getConnectorPElement(const QDomElement & element, ViewLayer::ViewID viewID) { QString viewName = ViewLayer::viewIDXmlName(viewID); QDomElement views = element.firstChildElement("views"); QDomElement view = views.firstChildElement(viewName); return view.firstChildElement("p"); } bool ViewLayer::getConnectorSvgIDs(QDomElement & element, ViewLayer::ViewID viewID, QString & id, QString & terminalID) { QDomElement p = getConnectorPElement(element, viewID); if (p.isNull()) { return false; } id = p.attribute("svgId"); if (id.isEmpty()) { return false; } terminalID = p.attribute("terminalId"); return true; } bool ViewLayer::fromBelow() { return m_fromBelow; } void ViewLayer::setFromBelow(bool fromBelow) { m_fromBelow = fromBelow; } void ViewLayer::setInitialZFromBelow(double initialZ) { m_initialZFromBelow = initialZ; } double ViewLayer::getZFromBelow(double currentZ, bool fromBelow) { double frac = currentZ - m_initialZ; if (qAbs(frac) > 1) { frac = currentZ - m_initialZFromBelow; } return frac + (fromBelow ? m_initialZFromBelow : m_initialZ); } fritzing-app-0.9.2b/src/viewlayer.h000066400000000000000000000131461250202676700172610ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6976 $: $Author: irascibl@gmail.com $: $Date: 2013-04-21 09:50:09 +0200 (So, 21. Apr 2013) $ ********************************************************************/ #ifndef VIEWLAYER_H #define VIEWLAYER_H #include #include #include #include #include struct NamePair { QString xmlName; QString displayName; NamePair(QString xml, QString display); }; class ViewLayer : public QObject { Q_OBJECT public: enum ViewLayerID { Icon, BreadboardBreadboard, Breadboard, BreadboardWire, BreadboardLabel, BreadboardRatsnest, BreadboardNote, BreadboardRuler, SchematicFrame, Schematic, SchematicText, SchematicWire, SchematicTrace, SchematicLabel, SchematicNote, SchematicRuler, Board, GroundPlane0, Silkscreen0, Silkscreen0Label, Copper0, Copper0Trace, GroundPlane1, Copper1, Copper1Trace, Silkscreen1, Silkscreen1Label, PartImage, PcbRatsnest, PcbNote, PcbRuler, UnknownLayer, ViewLayerCount }; enum ViewLayerPlacement { NewTop, NewBottom, NewTopAndBottom, UnknownPlacement }; enum ViewID { IconView, BreadboardView, SchematicView, PCBView, AllViews, UnknownView, ViewCount }; public: static const QString HolesColor; static const QString Copper0Color; static const QString Copper1Color; static const QString Copper0WireColor; static const QString Copper1WireColor; static const QString Silkscreen1Color; static const QString Silkscreen0Color; static const QString BoardColor; protected: static double zIncrement; static QHash names; static QMultiHash alternatives; static QMultiHash unconnectables; static QHash xmlHash; public: ViewLayer(ViewLayerID, bool visible, double initialZ); ~ViewLayer(); void setAction(QAction *); QAction* action(); QString & displayName(); bool visible(); void setVisible(bool); double nextZ(); ViewLayerID viewLayerID(); double incrementZ(double); ViewLayer * parentLayer(); void setParentLayer(ViewLayer *); const QList & childLayers(); bool alreadyInLayer(double z); void resetNextZ(double z); void setActive(bool); bool isActive(); bool includeChildLayers(); void setIncludeChildLayers(bool); void setFromBelow(bool); bool fromBelow(); void setInitialZFromBelow(double); double getZFromBelow(double currentZ, bool fromBelow); public: static ViewLayerID viewLayerIDFromXmlString(const QString &); static const QString & viewLayerNameFromID(ViewLayerID); static const QString & viewLayerXmlNameFromID(ViewLayerID); static void initNames(); static double getZIncrement(); static void cleanup(); static QList findAlternativeLayers(ViewLayerID); static bool canConnect(ViewLayerID, ViewLayerID); static ViewLayer::ViewLayerPlacement specFromID(ViewLayer::ViewLayerID); static const QList & copperLayers(ViewLayer::ViewLayerPlacement); static const QList & maskLayers(ViewLayer::ViewLayerPlacement); static const QList & silkLayers(ViewLayer::ViewLayerPlacement); static const QList & outlineLayers(); static const QList & drillLayers(); static const QList & topLayers(); static const QList & bottomLayers(); static const QList & silkLayers(); static bool isCopperLayer(ViewLayer::ViewLayerID); static bool isNonCopperLayer(ViewLayer::ViewLayerID viewLayerID); // for pcb view layers only static QString & viewIDName(ViewLayer::ViewID); static QString & viewIDXmlName(ViewLayer::ViewID); static QString & viewIDNaturalName(ViewLayer::ViewID); static ViewID idFromXmlName(const QString & name); static const QList & layersForView(ViewLayer::ViewID); static const QList & layersForViewFromBelow(ViewLayer::ViewID); static bool viewHasLayer(ViewID, ViewLayer::ViewLayerID); static bool getConnectorSvgIDs(QDomElement & connector, ViewLayer::ViewID, QString & id, QString & terminalID); static QDomElement getConnectorPElement(const QDomElement & connector, ViewLayer::ViewID); protected: bool m_visible; ViewLayerID m_viewLayerID; QAction* m_action; double m_nextZ; double m_initialZ; double m_initialZFromBelow; QList m_childLayers; ViewLayer * m_parentLayer; bool m_active; bool m_includeChildLayers; bool m_fromBelow; static QHash ViewIDNames; }; typedef QHash LayerHash; typedef QList LayerList; Q_DECLARE_METATYPE( ViewLayer* ); #endif fritzing-app-0.9.2b/src/waitpushundostack.cpp000066400000000000000000000110101250202676700213510ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6904 $: $Author: irascibl@gmail.com $: $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $ ********************************************************************/ #include "waitpushundostack.h" #include "utils/misc.h" #include "utils/folderutils.h" #include "commands.h" #include #include CommandTimer::CommandTimer(QUndoCommand * command, int delayMS, WaitPushUndoStack * undoStack) : QTimer() { m_undoStack = undoStack; m_command = command; m_undoStack->addTimer(this); setSingleShot(true); setInterval(delayMS); connect(this, SIGNAL(timeout()), this, SLOT(timedout())); start(); } void CommandTimer::timedout() { if (m_undoStack) { m_undoStack->push(m_command); m_undoStack->deleteTimer(this); } } ///////////////////////////////// WaitPushUndoStack::WaitPushUndoStack(QObject * parent) : QUndoStack(parent) { m_temporary = NULL; #ifndef QT_NO_DEBUG QString path = FolderUtils::getUserDataStorePath(""); path += "/undostack.txt"; m_file.setFileName(path); m_file.remove(); #endif } WaitPushUndoStack::~WaitPushUndoStack() { clearLiveTimers(); clearDeadTimers(); } void WaitPushUndoStack::push(QUndoCommand * cmd) { #ifndef QT_NO_DEBUG writeUndo(cmd, 0, NULL); #endif if (m_temporary == cmd) { m_temporary->redo(); return; } QUndoStack::push(cmd); } void WaitPushUndoStack::waitPush(QUndoCommand * command, int delayMS) { clearDeadTimers(); if (delayMS <= 0) { push(command); return; } new CommandTimer(command, delayMS, this); } void WaitPushUndoStack::waitPushTemporary(QUndoCommand * command, int delayMS) { m_temporary = command; waitPush(command, delayMS); } void WaitPushUndoStack::clearDeadTimers() { clearTimers(m_deadTimers); } void WaitPushUndoStack::clearLiveTimers() { clearTimers(m_liveTimers); } void WaitPushUndoStack::clearTimers(QList & timers) { QMutexLocker locker(&m_mutex); foreach (QTimer * timer, timers) { delete timer; } timers.clear(); } void WaitPushUndoStack::deleteTimer(QTimer * timer) { QMutexLocker locker(&m_mutex); m_deadTimers.append(timer); m_liveTimers.removeOne(timer); } void WaitPushUndoStack::addTimer(QTimer * timer) { QMutexLocker locker(&m_mutex); m_liveTimers.append(timer); } bool WaitPushUndoStack::hasTimers() { QMutexLocker locker(&m_mutex); return m_liveTimers.count() > 0; } void WaitPushUndoStack::resolveTemporary() { TemporaryCommand * tc = dynamic_cast(m_temporary); m_temporary = NULL; if (tc) { tc->setEnabled(false); push(tc); tc->setEnabled(true); } } void WaitPushUndoStack::deleteTemporary() { if (m_temporary != NULL) { delete m_temporary; m_temporary = NULL; } } #ifndef QT_NO_DEBUG void WaitPushUndoStack::writeUndo(const QUndoCommand * cmd, int indent, const BaseCommand * parent) { const BaseCommand * bcmd = dynamic_cast(cmd); QString cmdString; QString indexString; if (bcmd == NULL) { cmdString = cmd->text(); } else { cmdString = bcmd->getDebugString(); indexString = QString::number(bcmd->index()) + " "; } if (m_file.open(QIODevice::Append | QIODevice::Text)) { QTextStream out(&m_file); QString indentString(indent, QChar(' ')); if (parent) { indentString += QString("(%1) ").arg(parent->index()); } indentString += indexString; out << indentString << cmdString << "\n"; m_file.close(); } for (int i = 0; i < cmd->childCount(); i++) { writeUndo(cmd->child(i), indent + 4, NULL); } if (bcmd) { for (int i = 0; i < bcmd->subCommandCount(); i++) { writeUndo(bcmd->subCommand(i), indent + 4, bcmd); } } } #endif fritzing-app-0.9.2b/src/waitpushundostack.h000066400000000000000000000042751250202676700210350ustar00rootroot00000000000000/******************************************************************* Part of the Fritzing project - http://fritzing.org Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de Fritzing is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fritzing 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 Fritzing. If not, see . ******************************************************************** $Revision: 6469 $: $Author: irascibl@gmail.com $: $Date: 2012-09-23 00:54:30 +0200 (So, 23. Sep 2012) $ ********************************************************************/ #ifndef WAITPUSHUNDOSTACK_H #define WAITPUSHUNDOSTACK_H #include #include #include #include #include class WaitPushUndoStack : public QUndoStack { Q_OBJECT public: WaitPushUndoStack(QObject * parent = 0); ~WaitPushUndoStack(); void waitPush(QUndoCommand *, int delayMS); void waitPushTemporary(QUndoCommand *, int delayMS); void resolveTemporary(); void deleteTemporary(); void deleteTimer(QTimer *); void addTimer(QTimer *); void push(QUndoCommand *); bool hasTimers(); #ifndef QT_NO_DEBUG public: void writeUndo(const QUndoCommand *, int indent, const class BaseCommand * parent); protected: QFile m_file; #endif protected: void clearDeadTimers(); void clearLiveTimers(); void clearTimers(QList &); protected: QList m_deadTimers; QList m_liveTimers; QMutex m_mutex; QUndoCommand * m_temporary; }; class CommandTimer : public QTimer { Q_OBJECT public: CommandTimer(QUndoCommand * command, int delayMS, WaitPushUndoStack * undoStack); protected slots: void timedout(); protected: QUndoCommand * m_command; QPointer m_undoStack; }; #endif fritzing-app-0.9.2b/tools/000077500000000000000000000000001250202676700154455ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/Fritzing.dmgCanvas/000077500000000000000000000000001250202676700211435ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/Fritzing.dmgCanvas/Disk Image000066400000000000000000075567421250202676700230150ustar00rootroot00000000000000bplist00T$topX$objectsX$versionY$archiverTroot5 TYfghipxyz{>U$null ZNS.objectsV$classWNS.keys4YdiskImage!  !"#$%&'()*+,-./0123456785:;<5>?@AB>CDEF5HIJ>KHMNOP5RF_internetEnabled[buildTargetXiconSize^toolbarVisible^windowContentsXlicenses_backgroundColor_statusBarVisibleZbackground_windowContentWidth_suggestedDiskImageFilePath_backgroundObject\nameFontSizeZviewLayout_backgroundImageZvolumeName_volumeSizeOption_defaultLicenseLanguage_iconPreviewVisibleZencryptionXautoopen_windowContentHeight]labelPositionVformatXpassword_suggestedDiskImageNameZvolumeIcon[finalFormatYwindowTop_itemInfoVisibleZwindowLeftZvolumeSize%3&2 *0( ,'(1+)xȀ UVWX  Z[\]^_`5bcd5Yinvisible_relativeFilePathXfilePathXlocationYisAnAliasd _../../../deploy/Fritzing.app_C/Users/andre/Documents/FritzingOrg/dev/fritzing/deploy/Fritzing.app_{100, 174.05469}jkloX$classesZ$classnamemn_DBDiskContentItemXNSObject_DBDiskContentItem Z[\]^q`5tuvId  _'../../../../../../../../../Applications]/Applications_{372, 176.83203}jk|}}~n^NSMutableArrayWNSArray ><C_compositedBackgroundImageTtypeUcolor]gradientAngle[endingColorUimageWobjects$"C jk~~n VNSRepsWNSColor\NSImageFlags U  _NSTIFFRepresentationOMM* ,*@[0SPs HV HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Kmjkn_NSBitmapImageRepZNSImageRep_NSBitmapImageRep \NSColorSpaceWNSWhiteD0 0jknWNSColorjknWNSImage UNSRGBO'0.9571161866 0.9571161866 0.9571161866 D0.5 VNSSize  Z{544, 364} Ù̀! ЀҀ" Հ#O MM*  l  < RS s "  appl mntrRGB XYZ   acspAPPLappl-appl descodscmxlcprt8wtptrXYZ0gXYZDbXYZXrTRClchad|,bTRClgTRCldescGeneric RGB ProfileGeneric RGB Profilemluc skSK(xhrHR(caES$ptBR&ukUA*frFU(Vaeobecn RGB profilGeneri ki RGB profilPerfil RGB genricPerfil RGB Genrico030;L=89 ?@>D09; RGBProfil gnrique RVBu( RGB r_icϏProfilo RGB genericoGenerisk RGB-profil| RGB \ |Obecn RGB profil RGB Allgemeines RGB-Profilltalnos RGB profilfn RGB cϏeNN, RGB 000000Profil RGB generic  RGBPerfil RGB genricoAlgemeen RGB-profielB#D%L RGB 1H'DGenel RGB ProfiliYleinen RGB-profiiliUniwersalny profil RGB1I89 ?@>D8;L RGBEDA *91JA RGB 'D9'EGeneric RGB ProfileGenerel RGB-beskrivelsetextCopyright 2007 Apple Inc., all rights reserved.XYZ RXYZ tM=XYZ Zus4XYZ (6curvsf32 B&ljkڢn_DBDiskImageBackground_DBDiskImageBackground UހTHFS+PTUDBZXFritzing , U- . /O 6MM* 2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>eYeYeYeY뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑范eYeY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>eY뙑뙑XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>rgrg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYrg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XKL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"uXK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"ueY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rgu2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rgXK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK范L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑뙑范eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑ueYeYeY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XKXK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"urg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0eY范뙑뙑eYL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0rguL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg范?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0范L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0뙑L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0uL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XKrg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>u范XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYeYrg뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑뙑ueYeY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK߰j`xM@b/ KV xM@xM@ǵ2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"ﰗb/ KKKKKKKKKKKKj`Ŀ?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"賂V KKKKKKKKKKKKKKKKxM@Ŀu2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XKb/ KKKKKKKKKKKKKKKKKKKKyp2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"KKKKKKKKKKKKKKKKKKKKKKKm>0?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"j`KKKKKKKKKKKKKKKKKKKKKKKKKV rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0KKKKKKKKKKKKKKKKKKKKKKKKKKKV 2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rgKKKKKKKKKKKKKKKKKKKKKKKKKKKKKm>02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑V KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKyp2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"xM@KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKĿeY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"ĿKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKm>0u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"xM@KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKĿ뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK[P2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYypKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范m>0KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKyp2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑ĿKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKxM@2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKV 2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑ĿKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKb/ 2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKxM@2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"뙑KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg[PKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKĿ2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKV 2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKyp2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"j`KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKj`rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKV L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范m>0KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKǵ2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eYV KKKKKKKKKKKKKKKKKKKKKKKKKKKKyp2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"V KKKKKKKKKKKKKKKKKKKKKKKKKKj`뙑2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"V KKKKKKKKKKKKKKKKKKKKKKKKj`XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范m>0KKKKKKKKKKKKKKKKKKKKKK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>KKKKKKKKKKKKKKKKKKKm>02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"ߏj`KKKKKKKKKKKKKKKb/ rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范߰m>0KKKKKKKKKV j`ǵ2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0Ŀǵ2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XK2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"范L>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"u?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>范2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"?0eY2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"uL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"uL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY뙑?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>范rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"L>范rg2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"eY뙑uL>2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"XKeY范뙑뙑뙑뙑뙑뙑rgeY?02"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"2"--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  U S s H     HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmYAutomatic_Fritzing0.9.0b.dmg_'/Users/andre/Desktop/Fritzing0.9.0b.dmgjkn[DBDiskImage[DBDiskImagejkn\NSDictionary_NSKeyedArchiver'0:?DF}-@MXju".8JU`adfhikmopruwy{}   0v/=PY`ow #*2?ACEJSUXZcejlnw6?FYdw #8?ACEGLW`begprwy{4=BZrt}ˀ˅ˆˋ˔˥˧˩˫˰˹˻˾'<fotـٌٕٚ٧٬پfritzing-app-0.9.2b/tools/Fritzing.dmgCanvas/QuickLook/000077500000000000000000000000001250202676700230445ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/Fritzing.dmgCanvas/QuickLook/Preview.jpg000066400000000000000000000511131250202676700251700ustar00rootroot00000000000000JFIF XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmLExifMM*i,C      C  ," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?x+<0((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((/O<}(д}#h݄5H3ƥȸ 3{ !io8߈2j?U%~}i'ܚv?y%)fxxՌa>k\{W'&{W'&]+[s ? iϨ_ ?_ v?|!_ ж ;I ;Ihm?*_? iϨ_ ?_ v?|!_ ж ;I ;Ihm?*_? iϨ_ ?_ v?|!_ ж ;I ;Ihm?*_? iϨ_ ?_ v?|!_ ж ;I?} YrOTP9>9\>xJ"|:оxZDqU!/R{{گ0PP^޼_g>N_>W5v~÷~:5qe߈׃5 (&'2Tbk޳Y]?Yi 6d6 jxup~ʴ^|쑖}y\ܤnnZN2{x9މ#*+>%m3U"aER(+|c&Q]'4*2_+=n+IgQ_ՇQEQEQEQEQEQEQExKn#^UKmҴnY,pv'&k!i;0g';ךa!mŌ<:\ wK 3HkɋFxU'oGѭv؋$|;||/|< պ=03x%l}2kڌ?يd/&XaQ\nɷv߱CM]\4\ҊJ*.M?K?7=_ oѾ ^ BMFWQ+  *`v:kj++qm^h(s<\'W]4%4i''$Osh(iwG\Mv߳Oo?dӿ:ީ?^~.R9Gy&IH&۝ƪqץ[ݨbh У'F $}#isɪh ӌs?H_+v:rW =}#K|ᚚg>5N}i򋜸k 1 n$'Ҽľ2^F13-НAʐGnGTn, E=rxᎋ$iEo.h-תF$oú kv+$wS80s } ]gt_||sgc?4J`E9Ӟ?)X&(n1jqi*V}AgَHM>V.kZn>nǜXBǯ1 ǭ5s1(c.I~sGn2y땶jgo+S<((+|c&Q]'4*2_+=n+IgQ_ՇQEk;մ+1o4pE(UZ稩pբIgC W^G-]{Msu zGb9T# ?} KFVOv{O|F1+޹j7W:V'oROqʱDX!}|uR4{)=?gx~-uħSYU ̫bM#QErpӬQ?һ> v$ºpƉˍ =[8 }~bE޺GQE҅Q@Q@~Bq?dJz_[N7I___?QE~QE|(|Aŭj2EdC1~♼ =#[ӆ )kJN*qsRTf~޶?+K4k-&$%acEU@W3 L]X,Iwծ;fYeFڛ*ar'߆tϊK넹H-S8>rA{Fkuo?t j^+]k^k,\H_ HaL7gk#ژ<>k5W]wߩowWP>/5 Huh-\yXYQu%@ N} /~ዋmNB>do5bpJ$gB[| md+;sW?ՄPA$ICIbN8e?e&L68s x]eLzecOeG%W hX5m=ӛEe'neQ_aEPEP]'4*f8ɧTuٗR4yYq_K?^?((/Wl5A|)5uagsMsO,B'?J WV^TzjEE:QZҫQEQEWD/:o]y(v7-5GĨڮwok,2'9⩥ncrY.[f eΈk76̔$&:&#-.5ɛyA ·#p]:ml\ya@w=xVX+`_6Aԣxz9tGI7uӂK1<|*PyZ˪}U.P Qb?85OCҹ_l#ɴ"9% xUބIj[o߾8ZrNh5o CDH } `Cingrz=?2lwLތqZIU?{Inڨ $+[=ϥrsW9;r2:g{3໷=Wjܤ8_@xbZO.lGɞEWTQEQE K@Qҩ+!io8߈2j?U%~_O?~3׸GEWQEQE/ a~{Ɩ -̦_F\{r'  M>xJF̻Sg4gЬ~zC(vSIPVW4_xC^%eJ''Ŧ~gO,/Z,rxY|]1Ap"~Y?jo7~*p]LRlpr=>Ҷ?L[LkrzŒ^܋zdO)YE$=:%I'ުv{"ax-`wt=?JwK7֨:zp)(VR͞pqrh?^;<-|#UreOX\~ ^Nr^=b_F+可 ( ( /x%A@J޿_ZM_l.O?~˳ loxG6oWhѶ_,zQ_/3g}Mm?6Əo5{/0YShͿ_F~m|F?w>6oWhѶ_,zQGϯ7?m8`zQg}Mm?6Əo5{/0YShͿ_F~m|F?w>6oWhѶ_,zQGϯ7f{w'ĺpH ?QXh Gk/K_fsĮy~&>xO_ENaEPEPEPEPEPEP\8_]yǠZY/iPKZ_3_V1ky7Z]$K!Om=݉Qӏ2ҕ5V\cixWxm?Jl^[MbCh" f"cr$>:|Wⱟ0C,2,CNԷ)L:> Gk éGCBHiA li 32n6_|@hڏ-FV-nxEn ́͞ZNQ^*)+}cX1 _=K ?xLj1b_PϤ~fa2z!;VxW23ױ?0GVs?§RڧOKǫ֊>_Oχ_hkmS-mխFܟ3u߇֚n%q$n,ʼnɮ՗-I)ahP|Ԡ (7 ( ( {m/<_?9k]5BĚޣ/?o Örs+gGhvf$$I&WzҧNy[z} Eaf몱TQE~=Q@Q@Q@Q@Q@Q@q|k{BQ)޽şɴ1Ӳ׎6ΊR*3pwCbaR PvE ( ( ( ( ( ( ( ( ( ( ( ( ( ( +v({?Y_-~374Y$Ic thF$!IQ__ L|rNq⏋WFg >߷Ia'2%a,QQs#K95rܩ]?EI*Omc+|RR$ vhz}Y[i6sh˺m`l1@N7>N~0ԵMjJ-̫bD &0+ή"4iJWӥҵ΢m}ͫ6>+<_Czo=O_+Y4 P[bB-X]oļEUkҿj/S/P:$]zEԁa"HZ-G6B&t**o{k/'|km>g#]WĚ?}OU}3uƟ&^faKxMV~`0~m↗>-|9oǡY–ךqkcBۖ# n͔'΢V[N<+Iշ>?j:>xi?|}?]xB= iֶ?w9,):-y8h['\%Z (((((((((((( ?n+ciB]=/M(aqw VFڧ?߈0xhg^1:E{ ڥdv[Ȓʣ ڃ4=G>$q5= SB3_H,E,/ 3_gnH'wjM;o =+H -K]GVg.yBWZSJuJ^.N(ejz^WKK6}/?t _V_Ky6זl.$be^Hr?ړᗏ|/.oִX,5KXg1­*HTPO&f|Wg|k|: h ZiaCa[jmo5rT]Ѣ 77/B!i*6W~>E |q|㏏R'jρ9xS]Э |;cg.yy ؾRml;.gS?=Ke x}^_|#eɯߦ{":%H*H?1?gO4 +<z\7VVzvmkoi rGE-WeEO$mki|ҽrtSt7Z'OMmVEeP[y2,hF1&`1^E<7Q|U ~x+/Oj({i'|?i-l rbhb(ILimg7ׯ_ sKRuVZj^K^GbVƪI'd&k;6`_t?|/I尿LEzItMw (*($F %s^EIY(I7' (Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ Ἅ%U*\TZfkY%moimvb4\*jQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEuJt|A>&K?QKOo[ɊO:T&>M5%t&]QEQEV;oѕ൴&dm{UczdQҬr\Ђҡ'b6r( (dO%ns뜚ɤciŠ( (~l觍_vGugh)|n9+amQLAEhxfVHIq%RK\U;Ď;V͋®B1˞JvtQE1Vǥid_@epړvvM̺(l/#(<7b"OxwIѯR[ӯXU=*QBy j:auZMn$V|)1.;Ğ ZmEka {Vq~4D/- C\17}s}}5ޝ$`=lWV`0EggĖvz]ƝKygġ I22pxuix~]7V1tp{m9q֛ۯ%%˿O}R ѮMIɕ7$Th޲D˘v0>ƒAiXimV'tcx|LWg`Xi T:+NNJ\&s+kzf[ϦTN, $pB)i:mͭaj1`*tCV^+[9=EXi%v(fݕ#9Ih`y-%|=^#Q7?4CڳI .tMc }w" Mj ݷ\v1w_2%$FMQZQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@-DOZ\2 BQE$op)(((((((((((((((((((((((((((((((((((((((((((fritzing-app-0.9.2b/tools/deploy_fritzing_mac.sh000077500000000000000000000033721250202676700220410ustar00rootroot00000000000000#!/bin/bash QTBIN=/Users/andre/Qt5.2.1/5.2.1/clang_64/bin tdir=`dirname $BASH_SOURCE` cd $tdir cd .. workingdir=$(pwd) echo "current working directory" echo $workingdir echo "building fritzing from working directory" $QTBIN/qmake -o Makefile phoenix.pro make release # release is the type of build builddir=$workingdir/../release64 echo "build directory" echo $builddir deploysrcdir=$workingdir/../deploy-src echo "deploy src directory" echo $deploysrcdir rm -rf $deploysrcdir mkdir $deploysrcdir git clone --recursive https://github.com/fritzing/fritzing-app/ $deploysrcdir deployappdir=$workingdir/../deploy-app echo "deploy app directory" echo $deployappdir rm -rf $deployappdir mkdir $deployappdir echo "moving parts to pdb - TEMPORARY WORKAROUND" mv $deploysrcdir/parts/contrib/* $deploysrcdir/pdb/contrib/ mv $deploysrcdir/parts/core/* $deploysrcdir/pdb/core/ mv $deploysrcdir/parts/obsolete/* $deploysrcdir/pdb/obsolete/ mv $deploysrcdir/parts/user/* $deploysrcdir/pdb/user/ echo "removing translations" rm $deploysrcdir/translations/*.ts find $deploysrcdir/translations -name "*.qm" -size -128c -delete echo "still more cleaning" rm $deploysrcdir/control rm -rf $deploysrcdir/deploy* rm -rf $deploysrcdir/fritzing.* rm $deploysrcdir/Fritzing.1 rm $deploysrcdir/Fritzing.sh rm -rf $deploysrcdir/Fritzing*.plist rm -rf $deploysrcdir/linguist* rm -rf $deploysrcdir/phoenix* rm -rf $deploysrcdir/pri/* rmdir $deploysrcdir/pri rm -rf $deploysrcdir/resources/* rmdir $deploysrcdir/resources rm -rf $deploysrcdir/src/* rmdir $deploysrcdir/src rm -rf $deploysrcdir/tools/* rmdir $deploysrcdir/tools echo "mac deploy qt" cp -r $builddir/Fritzing.app $deployappdir $QTBIN/macdeployqt $deployappdir/Fritzing.app cp -r $deploysrcdir/* $deployappdir/Fritzing.app/Contents/MacOS fritzing-app-0.9.2b/tools/fixfz/000077500000000000000000000000001250202676700165735ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/fixfz/fixfz.cpp000066400000000000000000000104141250202676700204250ustar00rootroot00000000000000#include "fixfz.h" #include #include #include #include #include #include #include #include QDir globalDir; void usage() { std::cout << "update fz files:" << std::endl << std::endl; std::cout << "usage: fixfz partsfolder" << std::endl << std::endl; std::cout << std::endl; } bool findFile(QDir & dir, QFile & resultFile, QString filename) { if (!dir.exists()) return false; QFileInfoList files = dir.entryInfoList(); foreach(QFileInfo fileInfo, files) { if (fileInfo.isFile()) { if (fileInfo.absoluteFilePath().endsWith(filename)) { resultFile.setFileName(fileInfo.absoluteFilePath()); return true; } continue; } if (fileInfo.fileName().compare(".") == 0) continue; if (fileInfo.fileName().compare("..") == 0) continue; if (fileInfo.isDir()) { QDir temp(fileInfo.absoluteFilePath()); if (findFile(temp, resultFile, filename)) { return true; } } } return false; } void handleFile(const QString & filename) { std::cout << "\t" << filename.toStdString() << std::endl; QFile file(filename); QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { std::cout << "file isn't fritzing file (1)" << std::endl; return; } QDomElement root = domDocument.documentElement(); if (root.isNull()) { std::cout << "file isn't fritzing file (2)" << std::endl; return; } if (root.tagName() != "module") { std::cout << "can't find module tag" << std::endl; return; } QDomElement views = root.firstChildElement("views"); if (views.isNull()) { std::cout << "can't find views element" << std::endl; return; } QHash viewImages; QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement layers = view.firstChildElement("layers"); if (!layers.isNull()) { QDomElement layer = layers.firstChildElement("layer"); while (!layer.isNull()) { QString image = layer.attribute("image"); if (!image.isEmpty()) { layers.setAttribute("image", image); layer.removeAttribute("image"); } layer = layer.nextSiblingElement("layer"); } } viewImages.insert(view.tagName(), layers.attribute("image")); view = view.nextSiblingElement(); } QDomElement connectors = root.firstChildElement("connectors"); if (views.isNull()) { std::cout << "can't find connectors element" << std::endl; return; } QDomElement connector = connectors.firstChildElement("connector"); while (!connector.isNull()) { QDomElement views = connector.firstChildElement("views"); if (views.isNull()) { std::cout << "can't find views element" << std::endl; } QDomElement view = views.firstChildElement(); while (!view.isNull()) { QDomElement pin = view.firstChildElement("pin"); if (!pin.isNull()) { pin.setTagName("p"); QString id = pin.attribute("svgId"); QString image = viewImages.value(view.tagName()); QFile imageFile; if (findFile(globalDir, imageFile, image)) { if (imageFile.open(QIODevice::ReadOnly)) { QString temp = imageFile.readAll(); imageFile.close(); if (!temp.contains(id)) { std::cout << "--- missing " << id.toStdString() << " in " << view.tagName().toStdString() << " in " << imageFile.fileName().toStdString() << " ---" << std::endl; } } } } view = view.nextSiblingElement(); } connector = connector.nextSiblingElement("connector"); } QFile data(filename); if (data.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream out(&data); out << domDocument.toString(); data.close(); } } void runDir(QDir & dir) { if (!dir.exists()) return; QFileInfoList files = dir.entryInfoList(); foreach(QFileInfo file, files) { if (file.isFile()) { if (file.fileName().endsWith(".fz")) { handleFile(file.absoluteFilePath()); } continue; } if (file.fileName().compare(".") == 0) continue; if (file.fileName().compare("..") == 0) continue; if (file.isDir()) { QDir temp(file.absoluteFilePath()); runDir(temp); } } } int main(int argc, char * argv[]) { if ((argc < 2)) { usage(); return 0; } globalDir.setPath(argv[1]); runDir(globalDir); } fritzing-app-0.9.2b/tools/fixfz/fixfz.h000066400000000000000000000000641250202676700200720ustar00rootroot00000000000000#ifndef FIXFZ_H #define FIXFZ_H #endif // FIXFZ_H fritzing-app-0.9.2b/tools/fixfz/fixfz.pro000066400000000000000000000001511250202676700204400ustar00rootroot00000000000000TEMPLATE = app TARGET = fxfz HEADERS = fixfz.h SOURCES = fixfz.cpp CONFIG += console QT += core gui xml fritzing-app-0.9.2b/tools/linguist_release.bat000066400000000000000000000001441250202676700214720ustar00rootroot00000000000000cd %~dp0 cd .. C:\Qt\Qt5.2.1-64bit\5.2.1\msvc2012_64\bin\lrelease -removeidentical phoenix.pro fritzing-app-0.9.2b/tools/linguist_translate.bat000066400000000000000000000001361250202676700220500ustar00rootroot00000000000000cd %~dp0 cd .. C:\Qt\Qt5.2.1-64bit\5.2.1\msvc2012_64\bin\lupdate -noobsolete phoenix.pro fritzing-app-0.9.2b/tools/linux_release_script/000077500000000000000000000000001250202676700216705ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/linux_release_script/obsolete/000077500000000000000000000000001250202676700235045ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/linux_release_script/obsolete/release.all.sh000066400000000000000000000004101250202676700262220ustar00rootroot00000000000000#!/bin/bash schroot -c hardy_i386 -u root cd /home/mariano/release ./release.sh exit schroot -c hardy_amd64 -u root cd /home/mariano/release ./release.sh exit cd /home/mariano/workspace/fritzing/release sudo chown mariano fritzing* sudo chgrp mariano fritzing* fritzing-app-0.9.2b/tools/linux_release_script/release.sh000077500000000000000000000077551250202676700236650ustar00rootroot00000000000000#!/bin/bash arch_aux=`uname -m` current_dir=$(pwd) echo "" echo "NOTE: Don't forget to set this script's QT_HOME variable" echo "NOTE: Execute this script from outside the fritzing-app folder" echo "" QT_HOME="/home/ubuntu/Qt5.2.1/5.2.1/gcc" #QT_HOME="/home/vuser/Qt5.2.1/5.2.1/gcc_64" # 64bit version #QT_HOME="~/Qt5.2.1/5.2.1/gcc" # doesn't work for some reason if [ "$1" = "" ] then echo "Usage: $0 " exit fi PKG_OK=$(dpkg-query -W --showformat='${Status}\n' libboost-dev) if [ "`expr index "$PKG_OK" installed`" -gt 0 ] then echo "using installed boost library" else echo "please install libboost-dev" exit fi PKG_OK=$(dpkg-query -W --showformat='${Status}\n' libquazip-dev) quazip='QUAZIP_LIB' if [ "`expr index "$PKG_OK" installed`" -gt 0 ] then quazip='QUAZIP_INSTALLED' echo "using installed quazip" else echo "using src/lib/quazip" fi compile_folder="build-$arch_aux" #svn export http://fritzing.googlecode.com/svn/trunk/fritzing $compile_folder git clone --recursive https://github.com/fritzing/fritzing-app $compile_folder cd $compile_folder/parts git submodule update --init --recursive git checkout master cd .. cd src/lib rm -rf boost* # depend on linux boost installation if [ "$quazip" == 'QUAZIP_INSTALLED' ] then rm -rf quazip* fi cd $current_dir #let's define some variables that we'll need to in the future relname=$1 #`date +%Y.%m.%d` if [ "$arch_aux" == 'x86_64' ] ; then arch='AMD64' # only creates the source tarball, when running on the 64 platform tarball_folder="fritzing-$relname.source" echo "making source tarball: $tarball_folder" cp -rf $compile_folder $tarball_folder rm -rf $tarball_folder/FritzingInfo.plist rm -rf $tarball_folder/tools/fixfz tar -cjf ./$tarball_folder.tar.bz2 $tarball_folder rm -rf $tarball_folder echo "done with source tarball: $tarball_folder" else arch='i386' fi cd $compile_folder echo "compliling... if this is not taking a long time, something is probably wrong" $QT_HOME/bin/qmake CONFIG+=release DEFINES+=$quazip make release_folder="fritzing-$relname.linux.$arch" echo "making release folder: $release_folder" mkdir ../$release_folder echo "copying release files" cp -rf bins/ parts/ sketches/ help/ pdb/ Fritzing Fritzing.sh Fritzing.1 fritzing.desktop fritzing.rc fritzing.appdata.xml readme.md LICENSE.CC-BY-SA LICENSE.GPL2 LICENSE.GPL3 ../$release_folder/ cd ../$release_folder echo "move parts into pdb folder - TEMPORARY WORKAROUND" mv parts/contrib/* pdb/contrib/ mv parts/core/* pdb/core/ mv parts/obsolete/* pdb/obsolete/ mv parts/user/* pdb/user/ echo "making library folders" mkdir lib mkdir lib/imageformats mkdir lib/sqldrivers mkdir translations mkdir lib/platforms cd lib echo "copying libraries" cp $QT_HOME/lib/libicudata.so.51 $QT_HOME/lib/libicui18n.so.51 $QT_HOME/lib/libicuuc.so.51 $QT_HOME/lib/libicudata.so.5 $QT_HOME/lib/libQt5Concurrent.so.5 $QT_HOME/lib/libQt5Core.so.5 $QT_HOME/lib/libQt5DBus.so.5 $QT_HOME/lib/libQt5Gui.so.5 $QT_HOME/lib/libQt5Network.so.5 $QT_HOME/lib/libQt5SerialPort.so.5 $QT_HOME/lib/libQt5PrintSupport.so.5 $QT_HOME/lib/libQt5Sql.so.5 $QT_HOME/lib/libQt5Svg.so.5 $QT_HOME/lib/libQt5Xml.so.5 $QT_HOME/lib/libQt5Widgets.so.5 $QT_HOME/lib/libQt5XmlPatterns.so.5 . mv ../Fritzing . # hide the executable in the lib folder mv ../Fritzing.sh ../Fritzing # rename Fritzing.sh to Fritzing chmod +x ../Fritzing echo "copying plugins" cp $QT_HOME/plugins/imageformats/libqjpeg.so imageformats cp $QT_HOME/plugins/sqldrivers/libqsqlite.so sqldrivers cp $QT_HOME/plugins/platforms/libqxcb.so platforms echo "copying translations" cp ../../$compile_folder/translations/ -r ../ rm ../translations/*.ts # remove translation xml files, since we only need the binaries in the release find ../translations -name "*.qm" -size -128c -delete # delete empty translation binaries cd ../../ echo "compressing...." tar -cjf ./$release_folder.tar.bz2 $release_folder echo "cleaning up" rm -rf $release_folder rm -rf $compile_folder echo "done!" fritzing-app-0.9.2b/tools/make.bat000066400000000000000000000006251250202676700170550ustar00rootroot00000000000000cd /d %~dp0 cd .. rem C:\Qt\qt-everywhere-opensource-src-4.8.5\bin\qmake.exe -t vcapp -spec win32-msvc2012 phoenix.pro C:\Qt\qt-everywhere-opensource-src-5.2.1-32\qtbase\bin\qmake.exe -t vcapp -spec win32-msvc2012 phoenix.pro -o Fritzing32.vcxproj C:\Qt\qt-everywhere-opensource-src-5.2.1-64\qtbase\bin\qmake.exe "QMAKE_TARGET.arch=x86_64" -t vcapp -spec win32-msvc2012 phoenix.pro -o Fritzing64.vcxproj fritzing-app-0.9.2b/tools/release_fritzing.bat000066400000000000000000000131451250202676700214750ustar00rootroot00000000000000echo off echo you must start this script from the Visual Studio Command Line Window echo find this under the start menu at: echo All Programs / Microsoft Visual Studio 2012 / Visual Studio Tools / Developer Command Prompt echo for the 64-bit build, use the 64-bit prompt: echo All Programs / Microsoft Visual Studio 2012 / Visual Studio Tools / VS2012 x64 Cross Tools Command Prompt echo. echo the script also assumes you have cloned the Fritzing git repository and are launching this script from within that repository echo. echo for a full release, run the script twice, once for a 64-built build, once for a 32-bit build echo you may need to change QTBIN to point to your Qt folder (once for 64-bit, once for 32-bit) echo. IF .%1 == . ( echo first parameter--release version--is missing, should be something like 0.8.6b EXIT /B ) IF .%2 == . ( echo second parameter--target architecture--is missing, should be either "32" for a 32-bit build or "64" for a 64-bit build EXIT /B ) echo set the path to the qt sdk bin folder IF %2==64 ( set QTBIN=C:\Qt\Qt5.2.1-64bit\5.2.1\msvc2012_64\bin set arch=""QMAKE_TARGET.arch=x86_64"" ) ELSE ( IF %2==32 ( set QTBIN=C:\Qt\Qt5.2.1\5.2.1\msvc2012\bin set arch=. ) ELSE ( echo second parameter--target architecture--should be either "32" for a 32-bit build or "64" for a 64-bit build EXIT /B ) ) set QMAKE=%QTBIN%\qmake.exe if not exist %QMAKE% echo '%QMAKE%' not found--please change the path to Qt\bin if not exist %QMAKE% EXIT /B n echo found qmake.exe echo. cd /d %~dp0 cd .. rem set environment variable for qmake phoenix.pro set RELEASE_SCRIPT="release_script" %QMAKE% -o Makefile phoenix.pro %arch% echo building fritzing nmake release set DESTDIR=..\release%2 set RELEASE_NAME=%DESTDIR%\forzip\fritzing.%1.%2.pc echo setting up deploy folder. ignore any "The system cannot find ..." messages rmdir %DESTDIR%\deploy /s /q rmdir %DESTDIR%\forzip /s /q if exist %RELEASE_NAME%.zip ( del %RELEASE_NAME%.zip ) mkdir %DESTDIR%\deploy mkdir %DESTDIR%\forzip mkdir %DESTDIR%\deploy\platforms mkdir %DESTDIR%\deploy\lib mkdir %DESTDIR%\deploy\lib\imageformats mkdir %DESTDIR%\deploy\lib\sqldrivers mkdir %DESTDIR%\deploy\lib\printsupport echo deploy folder ready. any further "The system cannot find ..." messages represent significant problems with the script echo. echo copy qt libraries copy %QTBIN%\libEGL.dll %DESTDIR%\deploy\libEGL.dll copy %QTBIN%\libGLESv2.dll %DESTDIR%\deploy\libGLESv2.dll copy %QTBIN%\Qt5Core.dll %DESTDIR%\deploy\Qt5Core.dll copy %QTBIN%\Qt5Gui.dll %DESTDIR%\deploy\Qt5Gui.dll copy %QTBIN%\Qt5Network.dll %DESTDIR%\deploy\Qt5Network.dll copy %QTBIN%\Qt5PrintSupport.dll %DESTDIR%\deploy\Qt5PrintSupport.dll copy %QTBIN%\Qt5Sql.dll %DESTDIR%\deploy\Qt5Sql.dll copy %QTBIN%\Qt5Svg.dll %DESTDIR%\deploy\Qt5Svg.dll copy %QTBIN%\Qt5Widgets.dll %DESTDIR%\deploy\Qt5Widgets.dll copy %QTBIN%\Qt5Xml.dll %DESTDIR%\deploy\Qt5Xml.dll copy %QTBIN%\Qt5SerialPort.dll %DESTDIR%\deploy\Qt5SerialPort.dll copy %QTBIN%\icudt51.dll %DESTDIR%\deploy\icudt51.dll copy %QTBIN%\icuin51.dll %DESTDIR%\deploy\icuin51.dll copy %QTBIN%\icuuc51.dll %DESTDIR%\deploy\icuuc51.dll copy %QTBIN%\..\plugins\imageformats\qjpeg.dll %DESTDIR%\deploy\lib\imageformats\qjpeg.dll copy %QTBIN%\..\plugins\sqldrivers\qsqlite.dll %DESTDIR%\deploy\lib\sqldrivers\qsqlite.dll copy %QTBIN%\..\plugins\platforms\qwindows.dll %DESTDIR%\deploy\platforms\qwindows.dll copy %QTBIN%\..\plugins\printsupport\windowsprintersupport.dll %DESTDIR%\deploy\lib\printsupport\windowsprintersupport.dll copy %QTBIN%\..\plugins\platforms\qwindows.dll %DESTDIR%\deploy\platforms\qwindows.dll echo copying bins, parts, sketches, translations, pdb, help echo. copy %DESTDIR%\Fritzing.exe %DESTDIR%\deploy\Fritzing.exe xcopy /q .\translations %DESTDIR%\deploy\translations /E /I xcopy /q .\bins %DESTDIR%\deploy\bins /E /I xcopy /q .\sketches %DESTDIR%\deploy\sketches /E /I move .\parts\core\*.* .\pdb\core\ move .\parts\obsolete\*.* .\pdb\obsolete\ move .\parts\contrib\*.* .\pdb\contrib\ move .\parts\user\*.* .\pdb\user\ xcopy /q .\parts %DESTDIR%\deploy\parts /E /I xcopy /q .\pdb %DESTDIR%\deploy\pdb /E /I move .\pdb\core\*.* .\parts\core\ move .\pdb\obsolete\*.* .\parts\obsolete\ move .\pdb\user\*.* .\parts\user\ move .\pdb\contrib\*.* .\parts\contrib\ xcopy /q .\parts\core\placeholder.txt .\pdb\core\ xcopy /q .\parts\core\placeholder.txt .\pdb\obsolete\ xcopy /q .\parts\core\placeholder.txt .\pdb\user\ xcopy /q .\parts\core\placeholder.txt .\pdb\contrib\ xcopy /q .\help %DESTDIR%\deploy\help /E /I copy .\README.txt %DESTDIR%\deploy\README.txt copy .\LICENSE.GPL2 %DESTDIR%\deploy\LICENSE.GPL2 copy .\LICENSE.GPL3 %DESTDIR%\deploy\LICENSE.GPL3 copy .\LICENSE.CC-BY-SA %DESTDIR%\deploy\LICENSE.CC-BY-SA echo removing empty translation files echo. del %DESTDIR%\deploy\translations\*.ts set CURRENTDIR=%cd% cd %DESTDIR% cd deploy del/s placeholder.txt cd translations for /f "usebackq delims=;" %%A in (`dir /b *.qm`) do If %%~zA LSS 1024 del "%%A" cd %CURRENTDIR% IF %2==32 ( echo make the executable compatible with windows xp "%VCINSTALLDIR%bin\editbin.exe" %DESTDIR%\deploy\Fritzing.exe /SUBSYSTEM:WINDOWS,5.01 /OSVERSION:5.1 ) echo copying vc redist files IF %2==32 ( set XFOLDER=x86 ) ELSE ( set XFOLDER=x64 ) copy "%VCINSTALLDIR%redist\%XFOLDER%\Microsoft.VC110.CRT\msvcp110.dll" %DESTDIR%\deploy\msvcp110.dll copy "%VCINSTALLDIR%redist\%XFOLDER%\Microsoft.VC110.CRT\msvcr110.dll" %DESTDIR%\deploy\msvcr110.dll move %DESTDIR%\deploy %RELEASE_NAME% echo create zip file FOR /F %%i IN ("%DESTDIR%\forzip") DO SET SRC=%%~fi FOR /F %%i IN ("%DESTDIR%\fritzing.%1.%2.pc.zip") DO SET DEST=%%~fi CScript .\tools\zip.vbs %SRC% %DEST% fritzing-app-0.9.2b/tools/schem2schem/000077500000000000000000000000001250202676700176465ustar00rootroot00000000000000fritzing-app-0.9.2b/tools/schem2schem/.gitignore000066400000000000000000000013471250202676700216430ustar00rootroot00000000000000# Visual Studio folders and files # ##################### debug/ release/ *.opensdf *.user *.sln *.sdf *.suo *.vcx* *.pdb ipch/ # testing # ##################### working/ obsolete/ new_schematics/ *.txt # Compiled source # ################### *.pyc *.com *.class *.dll *.exe *.o *.so # Temporary files # ############### *.py~ *.xml~ # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods #*.7z #*.dmg #*.gz #*.iso #*.jar #*.rar #*.tar #*.zip # Logs and databases # ###################### #*.log #*.sql #*.sqlite # OS generated files # ###################### .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db .bash_history saved_state fritzing-app-0.9.2b/tools/schem2schem/main.cpp000066400000000000000000000001661250202676700213010ustar00rootroot00000000000000 #include "s2sapplication.h" int main(int argc, char *argv[]) { S2SApplication a(argc, argv); a.start(); } fritzing-app-0.9.2b/tools/schem2schem/make.bat000066400000000000000000000001461250202676700212540ustar00rootroot00000000000000cd %~dp0 C:\Qt\qt-everywhere-opensource-src-4.8.5\bin\qmake.exe -t vcapp -spec win32-msvc2012 s2s.pro fritzing-app-0.9.2b/tools/schem2schem/readme.md000066400000000000000000000002051250202676700214220ustar00rootroot00000000000000Fritzing tool for converting old-style to new-style (0.1" grid) schematics See http://blog.fritzing.org/2014/01/23/0-8-6-schematics/fritzing-app-0.9.2b/tools/schem2schem/s2s.pro000066400000000000000000000012161250202676700210770ustar00rootroot00000000000000# ------------------------------------------------- # Project created by QtCreator 2011-02-16T09:56:30 # ------------------------------------------------- QT += xml \ gui \ svg \ TARGET = s2s CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp \ s2sapplication.cpp \ ../../src/utils/s2s.cpp \ ../../src/utils/textutils.cpp \ ../../src/utils/schematicrectconstants.cpp \ HEADERS += s2sapplication.h \ ../../src/utils/s2s.h \ ../../src/utils/textutils.h \ ../../src/utils/schematicrectconstants.h \ RESOURCES += ../../phoenixresources.qrc win32 { DEFINES += _CRT_SECURE_NO_DEPRECATE } fritzing-app-0.9.2b/tools/schem2schem/s2sapplication.cpp000066400000000000000000000117171250202676700233140ustar00rootroot00000000000000#include "s2sapplication.h" #include "stdio.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../src/utils/textutils.h" #include "../../src/utils/schematicrectconstants.h" #include "../../src/utils/s2s.h" #include ///////////////////////////////// // // TODO: // // pin numbers in brd2svg--something to add to params files? // // copy old schematics to obsolete (with prefix) // readonly old style vs. read/write new style // // update wire thickness in fritzing schematic view // update part label size (and font?) in fritzing // // controller_wiringmini a0 pin is fucked // // update internal schematics generators // update brd2svg schematics generator // /////////////////////////////////////////////////////// S2SApplication::S2SApplication(int argc, char *argv[]) : QCoreApplication(argc, argv) { m_fzpzStyle = false; } void S2SApplication::start() { if (!initArguments()) { usage(); return; } int ix = QFontDatabase::addApplicationFont(":/resources/fonts/DroidSans.ttf"); if (ix < 0) return; ix = QFontDatabase::addApplicationFont(":/resources/fonts/DroidSans-Bold.ttf"); if (ix < 0) return; ix = QFontDatabase::addApplicationFont(":/resources/fonts/DroidSansMono.ttf"); if (ix < 0) return; ix = QFontDatabase::addApplicationFont(":/resources/fonts/OCRA.ttf"); if (ix < 0) return; m_fzpDir.setPath(m_fzpPath); m_oldSvgDir.setPath(m_oldSvgPath); m_newSvgDir.setPath(m_newSvgPath); QFile file(m_filePath); if (!file.open(QFile::ReadOnly)) { message(QString("unable to open %1").arg(m_filePath)); return; } S2S s2s(m_fzpzStyle); s2s.setSvgDirs(m_oldSvgDir, m_newSvgDir); QTextStream in(&file); while ( !in.atEnd() ) { QString line = in.readLine().trimmed(); QString schematicFileName; s2s.onefzp(m_fzpDir.absoluteFilePath(line), schematicFileName); } } void S2SApplication::usage() { message("\nusage: s2s " "-ff " "-f " "-os " "-ns " "[-fzpz (translate to fzpz style filenames)] " "\n" ); } bool S2SApplication::initArguments() { QStringList args = QCoreApplication::arguments(); for (int i = 0; i < args.length(); i++) { if ((args[i].compare("-h", Qt::CaseInsensitive) == 0) || (args[i].compare("-help", Qt::CaseInsensitive) == 0) || (args[i].compare("--help", Qt::CaseInsensitive) == 0)) { return false; } if (args[i].compare("-fzpz", Qt::CaseInsensitive) == 0) { m_fzpzStyle = true; continue; } if (i + 1 < args.length()) { if ((args[i].compare("-ff", Qt::CaseInsensitive) == 0) || (args[i].compare("--ff", Qt::CaseInsensitive) == 0)) { m_fzpPath = args[++i]; } else if ((args[i].compare("-os", Qt::CaseInsensitive) == 0) || (args[i].compare("--os", Qt::CaseInsensitive) == 0)) { m_oldSvgPath = args[++i]; } else if ((args[i].compare("-ns", Qt::CaseInsensitive) == 0) || (args[i].compare("--ns", Qt::CaseInsensitive) == 0)) { m_newSvgPath = args[++i]; } else if ((args[i].compare("-f", Qt::CaseInsensitive) == 0) || (args[i].compare("--f", Qt::CaseInsensitive) == 0)) { m_filePath = args[++i]; } } } if (m_fzpPath.isEmpty()) { message("-ff fzp path parameter missing"); usage(); return false; } if (m_oldSvgPath.isEmpty()) { message("-os old svg path parameter missing"); usage(); return false; } if (m_newSvgPath.isEmpty()) { message("-ns new svg path parameter missing"); usage(); return false; } if (m_filePath.isEmpty()) { message("-f fzp list file parameter missing"); usage(); return false; } QStringList paths; paths << m_fzpPath << m_oldSvgPath << m_newSvgPath; foreach (QString path, paths) { QDir directory(path); if (!directory.exists()) { message(QString("path '%1' not found").arg(path)); return false; } } QFile file(m_filePath); if (!file.exists()) { message(QString("file path '%1' not found").arg(m_filePath)); return false; } return true; } void S2SApplication::message(const QString & msg) { // QTextStream cout(stdout); // cout << msg; // cout.flush(); qDebug() << msg; } fritzing-app-0.9.2b/tools/schem2schem/s2sapplication.h000066400000000000000000000012611250202676700227520ustar00rootroot00000000000000#ifndef APPLICATION_H #define APPLICATION_H #include #include #include #include #include #include class S2SApplication : public QCoreApplication { Q_OBJECT public: S2SApplication(int argc, char *argv[]); void start(); protected: void usage(); void message(const QString &); bool initArguments(); void saveFile(const QString & content, const QString & path); protected: QString m_fzpPath; QDir m_fzpDir; QString m_oldSvgPath; QDir m_oldSvgDir; QString m_newSvgPath; QDir m_newSvgDir; QString m_filePath; bool m_fzpzStyle; }; #endif // APPLICATION_H fritzing-app-0.9.2b/tools/zip.vbs000066400000000000000000000016041250202676700167640ustar00rootroot00000000000000'http://superuser.com/questions/110991/can-you-zip-a-file-from-the-command-prompt-using-only-windows-built-in-capabili 'Get command-line arguments. Set objArgs = WScript.Arguments InputFolder = objArgs(0) ZipFile = objArgs(1) 'Create empty ZIP file. CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar) Set objShell = CreateObject("Shell.Application") Set source = objShell.NameSpace(InputFolder).Items objShell.NameSpace(ZipFile).CopyHere(source) ' Wait for compression window to open set scriptShell = CreateObject("Wscript.Shell") Do While scriptShell.AppActivate("Compressing...") = FALSE WScript.Sleep 500 ' Arbitrary polling delay Loop ' Wait for compression to complete before exiting script Do While scriptShell.AppActivate("Compressing...") = TRUE WScript.Sleep 500 ' Arbitrary polling delay Loop fritzing-app-0.9.2b/translations/000077500000000000000000000000001250202676700170265ustar00rootroot00000000000000fritzing-app-0.9.2b/translations/fritzing_ar.qm000066400000000000000000000000441250202676700217010ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. Save... Save Don't Save Cancel Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Placement pcb layer Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Ready Save %1 Unable to open '%1': %2 Specify a file name Fritzing (*%1) Fritzing Unable to export %1 as shareable Fritzing Part (*%1) Unable to export %1 to shareable sketch Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Select a Fritzing File to Open Cannot find file %1. Cannot read file 1 %1: %2. File '%1' not found directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber BoM Text File (*.html) Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (SVG)... &Print... Ctrl+P Print the current view Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box &Edit &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Show part label Ctrl+Shift+V Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Parts Editor Help Display Parts Editor help in a browser Align &Routing Move to bottom layer Move to top layer top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Show unrouted Highlight all unrouted connectors Select All Wires Select all wires Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Check Loaded Traces Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. jumpers copperfill vias The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. &Show Breadboard Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show/hide the label for the selected parts Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Show Code Show the code (programming) view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation &File &Export as Image for Production &Part Raise and Lower &View &Window Ground Fill &Help Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Autoroute connections... Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+1 Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Select All CopperFill Select all copper fill items Select all jumper item parts Select All Vias Select all via parts Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Delete Page Setup Sorry, "%1" has not been implemented yet This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Select All Traces Select all trace wires Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select all trace wires excluded from autorouting Select All Jumpers Tidy Wires Tidy selected wires Copper Fill Remove Copper Fill Remove the copper fill Copper Top and Copper Bottom layers are both active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Copper Top layer is active Copper Bottom layer is active Autorouting... Autorouting Progress... Remove Bendpoint Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts Remove copper fill &Wire Color Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Do you want to update now? Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Metadata Connectors Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Save Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Cancel OK Mouse Wheel Behavior Command Control Change Wheel Behavior Code View Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Edit link Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb Breadboard View PCB View pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem Schematic View Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select all %1 Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates icon view breadboard view schematic view pcb view Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Note text change Rotate Flip Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 test connectors Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_bg.qm000066400000000000000000006154111250202676700217010ustar00rootroot00000000000000:t;@CFdIH/PHYIXHQIXNIXY2J6KQL4ciMMeM5dOP,EHPWi\RURxRUjkVgQl$V/#VoVlOWmrAWXYHYZ8,*)[ %m[f3V([f3\]4Sx^+_C68`bpQcgebi'eijcbSjcb@jcbjejɢNk7mn nrxrxtZtiuiui wm)yyeRyeyeye2yeyeKy>y}zl0zlYzz{ %v{{9}}}ܑ|UW]AVZP55:LMNR0_^\@~T8$J'f! FOc-\&z[uvT3>AB=ILRW;>$ V#JN[:\3E G#"bj2&a8)t){T**/SJ24*6E9?y JvgOL#\L4wO.TZ]0e>!e}Uqr2{(y«E:Np[Y:5E'`J,(p$WCpb IpNP`Z0rN2KCF2MS]v,NZ.kRl˓O0͌Ӓ2fԲNolجN .wԲSKD_d4#9U)Pa\`[33 1_&Ws.SS44Y?..BɢC>DJĮQʨQ˯(RԢfdTIWYXnYYYZx^4lfjdlTṚlpt.ztdPtluT!au5uTTxezAxexxic5y9|D2 'ұRA/.`sS9TDU'şI^XLI7M.Qb;As;AgP5u(u#/±("±"AĵS2:"Ea&a Sc֙nnq[bhr\P u~RIHeC8`bQpq2 & 5$T87TT[kU6JY;3Y.m*4 @;=U>HcFJC FtF.H0NKNaBRBTV|>wXMYhWwnkqjp>rxsum#|}nR1$oMBњ~a\r?[qFӝ%^2@ڮjy~T 4'ܡ ǒeo2տlֺPHo|fdQ"_Qd̵c )eolSI(#Hpc7Du~oʳE.XnIkK߭n9DZ"Bà'eT(Ï*Z-5r;NC= EG$Ke.ArPѧ[TDMX$Ze}ZeaUcOZc.UqjNTlzrRxtrzb{eD6|/}`|ouƮ} `"nQD,́J4ׅ ].bfLf!hɱ"I*IIlBIoIzIBIIjI*I3I9<I<;IzaZe<d 06=Lov)LRĩ !,ȥebEYN0#Y ^L~~O@9ax3{nٶcۘMlDEBfw F0*XPi;3qb@}Dvip^{  ~,.s^%<U|g((2,]P5~8[;$@E K_EnOfnQ0eQMKRNU\TX$/^z[^t_p}_zh`rGi\ l/pI{qW6 r |t/tz |%@t_z?CuCJSۧJ UIN -]]}"u4} I>`ZZ%Zvv~:ۉ09V]]D'kD!L%L sMW?a@9֣*֣j\~eh(mޛne}c8-f9lDrwZyr'p  q] 39-H!>"S&|8\'S((-3e. I.X51,p;!0//ԆU[ʫ  T 0mtLX 44Y_S]a.F*I-?>)OWߺ Γ>x{^;p$dgAX0:63g7p(lw {%`|&)w,ι-B8q21{AwHPCE3E:`NF?H4Ht:HI'N>O;_P1W;YQY´2:^Vb]A~fC?SfCuf|IfgIphТi'ZMiHvywJwnx>Kyz.)|Ԃ#|^]|^O`EAo' 2Z"Q.~2s1%*', XN=xR>]SSg{%[KoI$rnr*y؊G @"3%XMn20ʗ/% К1л%SX"E:Ֆ\'ܼ;evT5 O \~ + E6 XC   / dz ɾ |U .߼ w1 )^  (s  !y $)~1 .5~@ 01) 0!S 5Gu 6TIO ;=" BUa/ Exւ Gȧ MgX QcR SeD \u aB4: cϥDn d`V lOp l{ t7 ui޿ u |@pT ~ . ~S5j N8 M r/) ^n 8 ;. D p +) B1ޖ N! . : & ~ h sg Ŧvf HU 8 , 3 ; ՛Kp {u+ 7  ~ x D7 v  i    ) RS ^@f J  S4 `O 7 i76 2(  !q% !q #$h )r ?"EɆ CD D)* M 4 N=B P U [>@ ^5! a4ƨ c36 c3م d eKL eR e fjF g7> k2% k2 qw1 sum tqŤ v w: NI Ȑ D y˼ Pm ~f Y #Q , ^ 7 . +j  "n[ 9C 9v NJ Ɍ4 v v ώ. Ϯ  Ҍj 0k 0$ ˺fm K & ;' c2 k i UE B TU >D ? V ~ ~0>  gy3 R% !_gN #eȧ %4 ( ) = )^p ); * * 9 -# -mnz 8) ? 8 HK Jg K2g\ K2g N>. VĀ YE^: YseL bRh g1 gy` i$e l?I pf* qt )4} 7 1 ~ + z! V N" b 4 @y @ L Ί -n} ,._ ak ^ ^ q % + Nt ARq } p6 ZZ ƽ~ +EI / %V 1 R< KG ~`  tb 4 & >r ,  , y w- Cq" LH I{  ei8 h . ` M R # %^! %^ ,\ -0' /~_ 9s5 ;z ;> =4 AiT6 F^C( L.1% M&`{ O~ Q  Wj` XM"R `l af+a eu2 eZNU hȾb o rnK r֔ t z n+ z n[ {7i "- ]DO @j% N'  $ )  @˃ u ^A G ,. ,+$ j + /: /  'h $ $ P F4 m ǚ 1z m4H E; . 9/ T7\ YVe ɠ. ?-X  'm  oG K rv ~7 }j . /a o Up ˞ JL (1* %  j< f /Q O ?څ AB; A= DA DD% G0 LRz R/ Tp.و X4  Zgn [ Ud _k cB c f* fk1 iEa kc m[aE qUMU u; vL v vCq }& #8/ }x / 15'M   ǫ ~ z; ]F Bp ~Xs &X @ Rt <> ՞| ^ cYy Nw !  d e _" ^   e '$=<]I7S  ]e@1P3n-{W rc(,#/93;KBa.ma./He~ fT?fTvt#@v8%w=)yt~2Pi*o#=! n4n7Q>$) ""KSRx̔lxXãCc1iuŅŅ_ HArqth=H!4=tS ͫuCACnW]`b^$Yz~+>A9C~C E}iyRj2 pY~uc{"TN"$E/`i01_=3 w=V7=_u^@@ݱCYO(7TWVx]t^<av!d}hfgEhtiji0pHnsV<#vgULw|>zLz |`q}$7k@) 5}oGD pFcd^gJz9)ajcmjc8~"DQXsTwpqk,@(\WJNij<b>2007-%1 #=825@A8B5B 70 ?@8;>6=8 =0C:8 >AB40<</b>%2007-%1 Fachhochschule PotsdamAboutBox<b>GNU GPL v3 ?@020 =04 :>40 8 CreativeCommons:BY-SA =04 2A8G:> >AB0=0;>?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBox4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxp5?0@B0<5=B0 ?> !B@>8B5;AB2> :J< #=825@A8B5B0 2J2 Weimar)Department of Bauhaus-University Weimar, AboutBox3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBox6?@>1=> :@J3G5 =0 "Fritzing"Fritzing a test spin. AboutBox0Fritzing 5 AJ74045= >B: Fritzing is made by: AboutBoxt!J74020=5B> =0 "Fritzing" 5 >AJI5AB25=> A D8=0=A8@0=5 >B: 0Fritzing is made possible with funding from the AboutBox*Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxlIxDS, 0=>=8<5= 40@8B5; , Parallax, Picaxe, Sparkfun, 6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBox%Jan Sieber, Yaniv Steiner, Olaf Val, AboutBox-Jonathan Cohen, Marcus Paeschke, Omer Yosha, AboutBox6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxTMWFK Brandenburg, A?>=A>@AB2>B> 70 48709=00MWFK Brandenburg, the sponsorship of the Design AboutBox%Mariano Crowe, Johannes Landstorfer, AboutBox!Michaela Vieser and Julia Werner.AboutBox@>D5A>@. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, @Prof. Reto Wettach, André Knörig, Myriel Milicevic, AboutBox`!JA A?5F80;=8 1;03>40@=>AB8 :J< 2A8G:8 ABC45=B8 4Special thanks goes out as well to all the students AboutBox@!JA A?5F80;=8 1;03>40@=>AB8 :J<:Special thanks goes out to: AboutBox! 1;03>40@=>AB8 :J< Kurt Badelt 8 Miguel Solis 70 A?0=A:8O ?@52>4,DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBox,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBox2Travis Robertson, Stefan Hermann, Brendan Howell, AboutBoxz8 2A8G:8 0;D0 B5AB5@8 :>8B> 1OE0 4>AB0BJG=> A<5;8 40 =0?@02OB0and alpha testers who were brave enough to give AboutBox8 >B 2AO:0 ?>:C?:0 =0 =0H8O :><?;5:B 70 =0G8=05I8 8;8 =0 ?5G0B=0 ?;0B:0 >B D01@8:0B0 =0 Fritzing.Land from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab.AboutBox8 =0 Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira 70 >@BC30;A:8O (@078;A:8)?@52>4. |and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. AboutBoxt=0 &#313;ubom&iacute;r Ducho&#328; 70 ?@52>40 >B !;>20H:8?to Ĺubomír Duchoň for the Slovak translation, AboutBoxb=0 Alexander Kaltsas 70 ?@52>40 >B @J4A:8 578:, 0to Alexander Kaltsas for the Greek translation, AboutBoxl=0 Cihan Mete Bahad&#x0131;r 70 ?@52>40 >B "C@A:8 578::to Cihan Mete Bahadır for the Turkish translation, AboutBoxP=0 Gianluca Urgese 70 B0;80=A:8O ?@52>40to Gianluca Urgese for the Italian translation, AboutBoxJ=0 Hiroshi Suzuk 70 /?>=A:8O ?@52>4, 0to Hiroshi Suzuki for the Japanese translation, AboutBoxT=0 Jinbuhm Kim 70 ?@52>40 >B >@59A:8 578:+to Jinbuhm Kim for the Korean translation, AboutBoxV=0 Josef Dustira 70 ?@52>40 >B '5H:8 578:, ,to Josef Dustira for the Czech translation, AboutBoxN=0 8:>;09 !B0=:>2 70 J;30@A:8O ?@52>42to Nikolay Stankov for the Bulgarian translation, AboutBoxz=0 Nuno Pessanha Santos 70 >@BC30;A:8O (2@>?59A:8) ?@52>4, Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxr=0 Robert Lee 70 ?@52>40 >B 8B09A:8 ("@048F8>=5=) 578:, 9to Robert Lee for the Chinese (Traditional) translation, AboutBox=0 Steven Noppe 8 Davy Uittenbogerd 70 ?@52>40 >B %>;0=4A:8 578:, Ato Steven Noppe and Davy Uittenbogerd for the Dutch translation, AboutBoxX=0 ;048<8@ !028=>2 70 ?@52>40 >B  CA:8 578:1to Vladimir Savinov for the Russian translation, AboutBoxr=0 Yuelin and Ninjia 70 ?@52>40 >B 8B09A:8 (?@>AB5=) , @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBox009 - 4>1@>B> 4> <><5=B0 Best So FarAutorouteProgressDialog B<5=8CancelAutorouteProgressDialog!?@8 A530Stop NowAutorouteProgressDialog@:>=B@>;8 =0 <0I018@0=5 8 873;540zoom and pan controlsAutorouteProgressDialogxB<5=5=> 02B><0B8G=> ?@5:0@20=5 =0 ?8AB8. !530 @07G8AB20<...$Routing canceled! Now cleaning up... Autorouter<b>BAB>O=85</b> 5 <8=8<0;=>B> @07AB>O=85 <564C <54=8B5 5;5<5=B8 =0 ?;0B:0B0QKeepout is the minimum distance between copper elements on different nets.AutorouterSettingsDialogBAB>O=85 >B 0.01 inch 8;8 (0.254 mm) 5 4>1@0 =0AB@>9:0 :0B> 70 =0G0;>4A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialog B<5=8CancelAutorouterSettingsDialogBAB>O=85KeepoutAutorouterSettingsDialog=8<0=85: >;:>B> ?> <0;:> 5 >AB>O=85B> B>;:>20 ?> 102=> I5 AB020 02B><0B8G=0B0 ?>4@5410 =0 ?8AB8B5 8 DRC.JNote: the smaller the keepout, the slower the DRC and Autorouter will run.AutorouterSettingsDialog>B2J@48OKAutorouterSettingsDialog$84 =0 ?@>4C:F8OB0Production typeAutorouterSettingsDialog((8@>G8=0 =0 ?8AB8B5  Trace widthAutorouterSettingsDialog.04045=0 >B ?>B@518B5;OcustomAutorouterSettingsDialog=BCA80ABhomebrewAutorouterSettingsDialog@>D5A8>=0;=0 professionalAutorouterSettingsDialog 01>@Bin BinManager5=846J@JB =0 18=0@=8 D09;>25::setDirtyTab: 5 CA?O 40 704045 '%1' :0B> "<@JA5=";BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager5=8465@JB =0 18=0@=8 D09;>25::@><5=8 8<5B> : 5 CA?O 40 704045 bin. '%1' :0B> "<@JA5=";BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagern5 <>65B5 40 704045B5 =520;845= 18=0@5= D09; :0B> B5:CI(Cannot set a NULL bin as the current one BinManager0B2>@5B5 D09;0 Close Bin BinManager.0B2>@5B5 D09;0 A G0AB8Close parts bin BinManagerd>?8@09 2A8G:8 G0AB8 2 =01>@0 >B G0AB8 :J< AE5<0B0)Copy all the parts in the bin to a sketch BinManager&>?8@09 :J< !E5<0B0Copy to Sketch BinManager4!J7409B5 =>2 =01>@ A G0AB8Create a new parts bin BinManager7B@89B5 Bin-a Delete Bin BinManager&7B@89 18=0@5= D09; Delete bin BinManager<7B@89B5 18=0@=8O D09; A G0AB8Delete parts bin BinManager67:0@09 G0AB8B5 :0B> A?8AJ:Display parts as a list BinManager2>:068 G0AB8B5 :0B> 8:>=8Display parts as icons BinManager!83C@=8 ;8 AB5 ,G5 18EB5 8A:0;8 40 87B@85B5 18=0@=8O D09;'%1'? "078 >?5@0F8O =5 <>65 40 1J45 2J@=0B0 =0704.EDo you really want to delete bin '%1'? This action cannot be undone. BinManager!83C@=8 ;8 AB5 G5 8A:0B5 40 ?@5<0E<5B5 '%1' >B A?8AJ:0 ? "078 >?5@0F8O =5 <>65 40 1J45 >B=5<5=0 8;8 2J@=0B0 >1@0B=>.PDo you really want to remove '%1' from the bin? This operation cannot be undone. BinManager@@><5=8 G0AB (@540:B>@ =0 G0AB8)Edit Part (new parts editor)... BinManagerB7=5A5B5 (:A?>@B8@09B5) D09;0... Export Bin... BinManager27=5A8 (:A?>@B8@09) G0ABExport Part... BinManager*0<5@8 G0AB 2 AE5<0B0Find Part in Sketch BinManagerFritzing 18=0@=8 D09;>25(*%1 *%2);;Fritzing 18=0@5= (*%1);;Fritzing A?>45;O5< 18=0@5= (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagerFritzing D09;>25 (*%1 *%2 *%3);; Fritzing '0AB8G5=(*%1);;Fritzing 18=0@5=(*%2);;Fritzing A?>45;O5< 18=0@5=(*%3)cFritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) BinManager"=5A8(<?>@B8@09) Import... BinManager0@548 G0AB =0 Fritzing(.fzpz) 8;8 18=0@5= D09; A G0AB8 =0 Fritzing (.fzb, .fzbz)CLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManager >2 18=0@5= D09; New Bin... BinManager*>2-18=0@5= D09; (%1) New bin (%1) BinManager '0AB8Parts BinManager4>;O 8715@5B5 8<5 70 D09;0!Please choose a name for the bin: BinManager6$09; A ?@020 A0<> 70 G5B5=5 Read-only bin BinManager@5<0E=8 G0AB Remove Part BinManager6@5<0E=5B5 >B 18=0@=8O D09;Remove from Bin BinManager(@5<0E=8 >B A?8AJ:0 Remove from bin BinManager*@58<5=C209B5 D09;... Rename Bin... BinManager @58<5=C209 $09; Rename bin BinManager:@58<5=C209B5 D09; A G0AB8...Rename parts bin... BinManager0?075B5 D09;0Save Bin BinManager<0?075B5 18=0@=8O D09; :0B>...Save Bin As... BinManager<0?075B5 18=0@=8O D09; A G0AB8Save parts bin BinManagerL0?075B5 18=0@=8O D09; A G0AB8 :0B>...Save parts bin as... BinManagert0?075B5 =01>@0 >B D09;>25 A G0AB8 2 :><?@5A8@0= D>@<0B...&Save parts bin in compressed format... BinManager"J@AO... Searching... BinManagerl715@5B5 Fritzing D09;0 :>9B> 18EB5 8A:0;8 40 >B2>@8B5Select a Fritzing File to Open BinManagerx715@5B5 18=0@5= D09; A G0AB8 =0 Fritzing 70 40 1J45 >B2>@5=(Select a Fritzing Parts Bin file to open BinManagerF>:068 18=0@=8B5 D09;>25 :0B> 8:>=8Show Bin in Icon View BinManagerD>:068 D09;>25B5 2 A?8AJG5= 873;54Show Bin in List View BinManagerL">78 D09; =5 <>65 40 1J45 ?@58<5=C20=.This bin cannot be renamed. BinManager5 5 2J7<>6=> ?@5<0E20=5B> =0 G0ABB0 '%1'--2 <><5=B0 A5 ?>;720 2 AE5<0B04Unable to remove part '%1'--it is in use in a sketch BinManager >B@518B5;A:8 704045=0 ?;0B:0 2 svg D>@<0B >18:=>25=> 8<0 548= 8;8 420 A;>O A8B>?5G0B 8 548= A;>9 A D>@<0B0 =0 A0<0B0 ?;0B:0 U A custom board svg typically has one or two silkscreen layers and one board layer. Board<b>>B@518B5;A:8 704045=0B0 D>@<0 8<0 %n :>=BC@0 70 87@O720=5 </b>'The custom shape has %n cutouts.Board<b>>B@518B5;A:8 704045=0B0 D>@<0 15 70@545=0 8 285 I5 2848B5 =>20B0 ?;0B:0 AJ2A5< A:>@>.</b><br/><br/>ZThe custom shape has been loaded, and you will see the new board shortly.

    Board<b>>B@518B5;A:8 704045=0B0 D>@<0 =O<0 :>=BC@8 70 87@O720=5.</b>'The custom shape has no cutouts.Board<br/><br/>0:> AB5 8<0;8 =0<5@5=85 20H0B0 ?>B@518B5;A:8 704045=0 D>@<0 =0 ?;0B:0 40 8<0 8 :>=BC@8 70 87@O720=5 8 =5 A5 5 ?>;CG8;> B0:0 , e

    If you intended your custom shape to have cutouts and you did not get the expected result, Board<br/>J?@5:8 B>20 , :>=BC@8B5 <>65 40 =5 A0 D>@<0B8@0=8 :>@5:B=>.9
    However, the cutouts may not be formatted correctly.BoardV@548 @50;=0 87@01>B:0 =0 ?;0B:0B0 8 ?@5?>@JG20<5 40 B5AB20B5 20H0B0 ?>B@518B5;A:8 704045=0 D>@<0 :0B> 87?>;720B5 <5=NB> '$09;>:A?>@B8@09 70 87@01>B:0> Extended Gerber. Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Board25 <>65 40 A5 70@548 , => Can load, butBoard$@>25@5B5 :>=BC@0 =0 ?;0B:0B0 A;54 AJ74020=5B> <C A ?@>3@0<0 70 ?@53;54 =0 Gerber D09;>25 70 40 AB5 A83C@=8 ,G5 5 AB0=0; :0:B> >G0:20B5 <br/><br/>xCheck the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.

    Board>3;54=5B5 D09;0 A 8<5 circle_pcb.svg 2J2 8=AB0;0F8>==0B0 ?0?:0 =0 20HaB0 Fritzing A8AB5<0 2J2 parts/svg/core/pcb . eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Board !=8<:8ImagesBoardX715@5B5 D09; A A=8<:0 :>9B> 40 1J45 70@545=Select an image file to loadBoard!=8<:0B0 >B %1 <>65 40 1J45 70@545=0 => %2 A:0B5 ;8 40 87?>;720B5 B>78 D09;?5The image from %1 can be loaded, but %2 Use the file?BoardfAB0=0;0B0 G0AB >B B>20 AJ>1I5=85 :JA05 87@57:8B5'-The rest of this message concerns 'cutouts'. Board">20 A0 :@J3;8 8;8 >B2>@8 A =5?@028;=0 D>@<0. 8EB5 <>3;8 40 38 2:;NG8B5 2J2 ?>B@518B5;A:8 704045=0B0 D>@<0 70 ?;0B:0<br/><br/>uThese are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.

    Board45 5 2J7<>6=> 40 A5 70@548Unable to loadBoardL5 <>65 40 A5 70@548 A=8<:0B0 >B %1 %2Unable to load image from %1 %2Boardl70I>B> , xml D09;0 =5 5 ?@0D8;=> D>@<0B8@0= (?>4@545=)*because the xml is not correctly formattedBoard@70I>B> 8<0 =O:>;:> A;>O A<?8AB8>)because there are multiple layersBoardJ70I>B> 8<0 =O:>;:> <silkscreen0> A;>O/because there are multiple layersBoardF70I>B> 8<0 =O:>;:> A;>O <A8B>?5G0B>.because there are multiple layersBoard870I>B> =O<0 A;>525 A <?8AB8>!because there is no layerBoardd=> ?5G0B=0B0 ?;0B:0 =O<0 40 8<0 A;>9 AJA A8B>?5G0B0but the pcb itself will have no silkscreen layerBoardL>@048 xml.?@>1;5< %1 @54:%2 :>;>=0:%3+due to an xml problem: %1 line:%2 column:%3BoardD09; A A=8<:0 image fileBoardB> B>20 A5 5 ?>;CG8;> B0:0 70I>B> Fritzing 878A:20 40 704045B5 :>=BC@8B5 70 87@O720=5 87?>;7209:8 DC=:F88B5 'substraction' 8;8 'difference' 2J2 20H0B0 ?@>3@0<0 70 @01>B0 A 25:B>@=8 87>1@065=8O.it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.Board(70@548 D09; A A=8<:0load image fileBoard054=>A;>9=0 (54=>AB@0==0)one layer (single-sided)BoardV5;5<5=B0 <?8AB8>=5 AJ4J@60 5;5<5=B8 A D>@<8.the element contains no shape elementsBoardFsvg. D09;0 =5 AJ4J@60 =8:0:28 D>@<8"the svg contains no shape elementsBoardjsvg. D09;0 =5 AJ2?040 A ?@><5=5=8O D>@<0B =0 ?;0B:0B0+the svg doesn't fit the custom board formatBoard,42CA;>9=0 (42CAB@0==0)two layers (double-sided)Board D>@<0shape BoardLogoItem0715@5B5 F2OB =0 B5:AB0 Select text colorBreadboardLogoItem,0409B5 F2OB =0 B5:AB0Set text colorBreadboardLogoItemF2OBcolorBreadboardLogoItemp715@5B5 >B ?040I>B> <5=N , 8;8 =0?8H5B5 AB>9=>AB 2J2 %1/Select from the dropdown, or type in a %1 value Capacitor8>1025B5 B>G:0 70 45D>@<0F8O Add bendpoint ConnectorItem<@5<0E=5B5 B>G:0 70 45D>@<0F8ORemove bendpoint ConnectorItem7?@025B5 :@820Straighten curve ConnectorItem$B=>A=> ?@>3@0<0B0&About ConsoleWindow 7E>4&Quit ConsoleWindow=AB@C<5=B8Tools ConsoleWindow4%1 A5 70ABJ?20 A (%2 A;>9)%1 is overlapping (%2 layer)DRCO:>9 >B >B2>@8B5 2J2 %1 <>65 40 A5 =0<8@0 872J= 3@0=8F0B0 =0 ?;0B:0B0 8 5 25@>OB=> 40 1J45 >B@O70=.JA hole in %1 may lie outside the border of the board and would be clipped.DRC"DRC 15H5 >B<5=5=.DRC was cancelled.DRCFriztingFritzingDRC@>1;5< 2 Fritzing :=5 5 2J7<>6=> 40 1J45 87@01>B5=0 ?;0B:0B0 svg.+Fritzing error: unable to render board svg.DRCbO<0 ?8AB8 8;8 :>=5:B>@8 :>8B> 40 1J40B ?@>25@5=8 No traces or connectors to checkDRC0<5AB5B5 38 =0=>2> 8 AB0@B8@09B5 >B=>2> DRC 70 40 2848B5 40;8 8<0 >I5 ?@>1;5<8;Reposition them and run the DRC again to find more problemsDRC>=8B5 =0 20H0B0 ?;0B:0 >B15;O70=8 A G5@25=> A0 :>=5:B>@8 8;8 ?8AB8 :>8B> A5 70ABJ?20B 8;8 A0 ?@5:0;5=> 1;87:> 54=8 4> 4@C38qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRCL"2J@45 1;87> 4> 3@0=8F0B0 A (%1 -A;>9) Too close to a border (%1 layer)DRC5>G0:20= ?@>1;5< ?@8 87@01>B20=5B> AJA SVG --->;O A2J@65B5 A5 A-- fritzing.org6Unexpected SVG rendering failure--contact fritzing.orgDRC0H8OB ?@>5:B 5 3>B>2 70 87@01>B:0: =O<0 2@J7:8 8;8 ?8AB8 :>8B> 40 A5 70ABJ?20B 8;8 40 A5 ?@5:0;5=> 1;87:> 54=0 4> 4@C30nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRC0B8A=5B5 2J@EC >15:B >B A?8AJ:0 70 40 28 1J45 <0@:8@0=> 70ABJ?20=5B> A :>5B> 5 A2J@70=.BClick on an item in the list to highlight of overlap it refers to.DRCResultsDialog  57C;B0B8 >B DRC DRC ResultsDRCResultsDialog=8<0=85: !?8AJ:0 A :>=D;8:B8 8 G5@25=>B> <0@:8@0=5 =O<0 40 A5 >1=>2O20 02B><0B8G=> 4>:0B> ?@><5=OB5 20H0B0 AE5<0--B@O120 40 AB0@B8@0B5 >B=>2> DRC ?@>25@:0B0.'5@25=>B> <0@:8@0=5 I5 87G57=5 :>30B> 70B2>@8B5 B>78 ?@>7>@5F.Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialog270 >BAB@0=O20=5 =0 3@5H:8 for debugging DebugDialog$!JI> 87B@89 D09;JBAlso delete the file DeleteDialog5 ?@5<0E209 Don't remove DeleteDialog@5<0E=8Remove DeleteDialogB8:5B =0 G8?0 chip labelDip=8<0=85 ! 8EB5 <>3;8 40 38 4>1028B5 8 ?> :JA=> 87?>;7209:8 >?F8OB0 "><>I">"=5A8 G0AB8 8 18=0@=8 D09;>25 >B ?> AB0@0 25@A8O..."l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication5 2=0AO9 A530Do not import now FApplication8EB5 ;8 8A:0;8 40 2=5A5B5 G0AB8 8;8 18=0@=8 D09;>25 :>8B> AB5 AJ74020;8 A ?@548H=8 25@A88 =0 Fritzing?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationdFritzing 70A5G5 87:;NG5=85 %1 >B %2 2J2 AJ18B85 %33Fritzing caught an exception %1 from %2 in event %3 FApplicationZFritzing 70A5G5 87:;NG5=85 %1 2J2 AJ18B85 %2 0Fritzing caught an exception from %1 in event %2 FApplication"@5H:0 2 FritzingFritzing failure FApplication =5A8Import FApplication@=5A8 D09;>25 >B ?@548H=0 25@A8O#Import files from previous version? FApplication>;O CB>G=5B5 8<5B> =0 .ffc D09;0 2 :>9B> 18EB5 8A:0;8 40 70?8A20B5 (?@8 >B<O=0 =0 >?5@0F8OB0 I5 87B@85B5 @575@2=>B> :>?85)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplication0><>I ?@8 ?J@20 C?>B@510First Time HelpFirstTimeHelpDialog"0B2>@8 @>7>@5F0 &Close WindowFritzingWindow B<5=8CancelFritzingWindow,0B2>@8 B5:CI0B0 AE5<0Close the current sketchFritzingWindow8EB5 ;8 8A:0;8 40 70?078B5 ?@><5=8B5 :>8B> AB5 =0?@028;8 2 4>:C<5=B0 "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindow5 70?07209 Don't SaveFritzingWindow 0?078SaveFritzingWindow0?8H8 "%1" Save "%1"FritzingWindow0?078...Save...FritzingWindow(0409B5 8<5 =0 D09;0Specify a file nameFritzingWindowh0H8B5 ?@><5=8 I5 1J40B 703C15=8 0:> =5 38 70?078B5.1Your changes will be lost if you don't save them.FritzingWindow B<5=8CancelGroundFillSeedDialog>B2J@48OKGroundFillSeedDialogD>B2J@48 8 70?J;=8 AJA A;>9 >B <54OK and copper fillGroundFillSeedDialogJ>B2J@48 8 70?J;=8 A 7075<O20=5 (GND)OK and ground fillGroundFillSeedDialog 07;8:0B0 <564C 70?J;20=5B> A "7075<O20=5" 8 B>20 A "?@>AB> <54" 5 2 B>20 ,G5 ?@8 70?J;20=5B> A 7075<O20=5 B> A2J@720 2A8G:8 :>=5:B>@8 8 ?8AB8 ?@5420@8B5;=> 704045=8 :0B> "GND" 8;8 "7075<O20=5". >=O:>30 <>65 40 8<0B5 =O:>;:> @07;8G=8 <@568 A 7075<O20I8 2@J7:8 8 18EB5 <>3;8 40 8A:0B5 A0<> 54=0 >B BOE 40 1J45 70?J;=5=0. ">78 480;>3>2 ?@>7>@5F A2J@720 A0<> 2@J7:8 ?@5420@8B5;=> >1>7=0G5=8 :0B> "GND" 8;8 75<O(7075<O20=5) ,:0:B> 8 2@J7:8 25G5 >B15;O70=8 :0B> A5<5=0 70 @07@0AB20=5 =0 70?J;20=5B>. 0B8A=5B5 2J@EC >15:B 70 40 2848B5 =53>28B5 2@J7:8 =0 AE5<0B0 !JI> 5 2J7<>6=> 40 8715@5B5 :>=5:B>@ :0B> A5<5 70 @07@0AB20=5 =0 70?J;20=5B> A 7075<O20I0 ?8AB0 :0B> =0B8A=5B5 45A5= 1CB>= 2J@EC :>=5:B>@0 8 8718@09:8 '0409 :0B> A5<5 70 70?J;20=5 A 7075<O20=5'.The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialog @07<5@ =0 >B2>@0 hole sizeHole2(02B><0GB8=> - >?@>2>48<)(autoroutable) HtmlInfoView<@><5=5B5 ;5?:02>B>-AJAB>O=85 =0 B078 G0AB 2 B>78 873;54. >30B> ;5?:020 G0AB 1J45 ?@5<5AB5=0 >15:B8B5 :>8B> A5 =0<8@0B 2J@EC =5O AJI> A5 <5ABOB 7054=> A =5O.pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoView@><5=5B5 70:;NG5=>B> AJAB>O=85 =0 B078 G0AB 2 B>78 873;54. 0:;NG5=0 G0AB =5 <>65 40 1J45 <5AB5=0.OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoView>@><5=5B5 5B8:5B0 =0 G0ABB0 BC:Change the part label here HtmlInfoView!2@J7:8 Connections HtmlInfoView0:;NG5=Locked HtmlInfoViewN0@B8=:0 =0 G0ABB0 70 @>B>B8?5= 873;54Part breadboard view image HtmlInfoViewb0@B8=:0 =0 G0ABB0 70 873;540 =0 ?5G0B=0B0 ?;0B:0Part pcb view image HtmlInfoViewP0@B8=:0 =0 G0ABB0 70 !E5<0B8G=8O 873;54Part schematic view image HtmlInfoView6><5@ =0 25@A8OB0 =0 G0ABB0Part version number HtmlInfoView5AB>?>;>65=85 Placement HtmlInfoView!2>9AB20 Properties HtmlInfoView*!2J@720I0 "<8H0" 68F0 Ratsnest wire HtmlInfoView5?:020Sticky HtmlInfoViewB15;O720=8OTags HtmlInfoView*@>A;548 ?@>2>4=8: %1 Trace wire %1 HtmlInfoView@>2>4=8:Wire HtmlInfoView>=5:B>@conn. HtmlInfoView(A2J@70= A %n ?@54<5B*A2J@70= A %n ?@54<5B8connected to %n item(s) HtmlInfoView3@04CA8degrees HtmlInfoView<5AB>?>;>65=85location HtmlInfoView<5name HtmlInfoView&87;O7J; >B C?>B@510obsolete HtmlInfoView&A;>9 ?5G0B=0 ?;0B:0 pcb layer HtmlInfoView702J@B0=5rotation HtmlInfoView"8?type HtmlInfoView25@.%1 %2v. %1 %2 HtmlInfoView'0ABPartItemBase>1548=O20=5bandedItemBase>;=0 AB@0=0bottomItemBase:0?0F8B5B capacitanceItemBaseF2OBcolorItemBase 4>;5= <545= A;>9 copper bottomItemBase 3>@5= <545= A;>9 copper topItemBaseB>:currentItemBase40B0dateItemBase>?8A0=85descrItemBaseA5<59AB2>familyItemBase4D09; 70 %1 %2 =5 5 =0<5@5=file for %1 %2 not foundItemBase<5 =0 D09;0filenameItemBase284 :>@?CAformItemBaseG5AB>B0 frequencyItemBase8=4C:B82=>AB inductanceItemBase A;>525layersItemBase0<0:A8<0;=> AJ?@>B82;5=85maximum resistanceItemBase <>45;modelItemBase4?@>1;5< A <>45;0 =0 G0ABB0model part problemItemBaseB8? :>@?CApackageItemBase?0@B845= =><5@0 part numberItemBase4@07AB>O=85 <564C :@0G5B0B0 pin spacingItemBase:@0G5B0pinsItemBase<>I=>ABpowerItemBase?@>F5A>@ processorItemBase ?@>5:BprojectItemBase>1>7=0G5= B>: rated currentItemBase$>1>7=0G5=0 <>I=>AB rated powerItemBase*>1>7=0G5=> =0?@565=85 rated voltageItemBaseAJ?@>B82;5=85 resistanceItemBase@52878OrevItemBase D>@<0shapeItemBase;8ABsheetItemBase(A8B>?5G0B 4>;5= A;>9silkscreen bottomItemBase(A8B>?5G0B 3>@5= A;>9silkscreen topItemBase @07<5@sizeItemBase@07AB>O=85spacingItemBase703;0285titleItemBaseB>;5@0=A toleranceItemBase>@=0 AB@0=0topItemBaseB8?typeItemBaseb=5 5 2J7<>6=> 40 1J45 AJ74045= C:070B5; 70 svg %1$unable to create renderer for svg %1ItemBase20@80=BvariantItemBase 25@A8OversionItemBase=0?@565=85voltageItemBase B<5=8CancelKicadModuleDialog>B2J@48OKKicadModuleDialog(?>:068 2A8G:8 A;>525show all layers LayerPalette B<5=8Cancel LinkDialog>B2J@48OK LinkDialog "5:AB:text: LinkDialogWeb 04@5A:url: LinkDialog:5 5 2J7<>6=> 40 1J45 ?>:070=Unable to displayLogoItem\5 5 2J7<>6=> 40 1J45 ?>:070=0 :0@B8=0B0 >B %1Unable to display image from %1LogoItem>70I>B> D09;0 =O<0 <svg> 5;5<5=B%because the file has no element���LogoItem���T70I>B>� D09;0� =O<0� >A=>25=�(:>@5=5=�)� 5;5<5=B�������$because the file has no root element���LogoItem���&70I>B>� �s�v�g� 5� ?@075=�������because the svg is empty���LogoItem��0I>B>� 873;5640� �,G5� B>20� 5� �S�V�G� D09;� :>5B>� 873;5640� �,G5� 5� 5:A?>@B8@0=� >B� �C�o�r�e�l�D�R�A�W� 157� 40� 1J45� 871@0=0� =0AB@>9:0B0� 70� �'�p�r�e�s�e�n�t�a�t�i�o�n� �a�t�t�r�i�b�u�t�e�s�'�������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem���>?>@048� 3@5H:0� ?@8� 87G5@B020=5B>�������due to a rendering error���LogoItem���L>@048� �x�m�l�.?@>1;5<� �%�1� @54�:�%�2� :>;>=0�:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem���l70@048� =5OA=8� ?@8G8=8� �-�-� =09�-25@>OB=>� D09;0� 5� ?>2@545=�������9for unknown reasons--possibly the image file is corrupted���LogoItem��� $>@<0�������shape���LogoItem���z�%�1� >B� �%�2� <@568� A2J@70=8� �-� �%�n� 2@J7:8� >AB020B� 40� 1J40B� A2J@70=8�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow���8� �%�1� �%�2�������&%1 %2��� MainWindow���$B=>A=>� ?@>3@0<0B0�������&About��� MainWindow����OB=>A=>� �Q�t������� &About Qt��� MainWindow��� 50;5=� @07<5@������� &Actual Size��� MainWindow���6>1028� :J<� =870� >B� G0AB8�.�.�.�������&Add to bin...��� MainWindow���8� >?8@09�������&Copy��� MainWindow���:!J7409� ?8AB0� >B� �"<8H0�"� 2@J7:0�������&Create trace from ratsnest��� MainWindow���F!J7409� ?@>2>4=8:� >B� �"<8H8B5� 2@J7:8�"�������&Create wire from ratsnest��� MainWindow��� 7@568�������&Cut��� MainWindow��� 7B@89�������&Delete��� MainWindow���"7B@889� ?@>2>4=8:������� &Delete Wire��� MainWindow���6B<5=8� A5;5:F8OB0�(�d�e�s�e�l�e�c�t�)������� &Deselect��� MainWindow���C1;8@09������� &Duplicate��� MainWindow���@><5=8� �(�e�d�i�t�)�������&Edit��� MainWindow���(7=5A8� �(5:A?>@B8@09�)�������&Export��� MainWindow���:A?>@B8@09�.�.�.������� &Export...��� MainWindow���$09;�������&File��� MainWindow���<!J15@8� 4>� @07<5@0� =0� ?@>7>@5F0�������&Fit in Window��� MainWindow���F3;540;=>� >1@JI0=5� ?>� %>@87>=B0;0B0�������&Flip Horizontal��� MainWindow���B3;540;=>� >1@JI0=5� ?>� 5@B8:0;0B0�������&Flip Vertical��� MainWindow��� ><>I�������&Help��� MainWindow���&!:@89� 2A8G:8� A;>525�������&Hide All Layers��� MainWindow���n=5A5B5� G0AB8� 8� 18=0@=8� D09;>25� A� G0AB8� >B� AB0@0� 25@A8O�������*&Import parts and bins from old version...��� MainWindow���8=8<878@09������� &Minimize��� MainWindow���B2>@8� @8<5@������� &Open Example��� MainWindow���2B2>@8� ?>A;54=8B5� D09;>25�������&Open Recent Files��� MainWindow���B20@O=5�.�.�.�������&Open...��� MainWindow��� '0ABB0�������&Part��� MainWindow���8� >AB028�������&Paste��� MainWindow���0AB@>9:8�������&Preferences...��� MainWindow���B?5G0B09������� &Print...��� MainWindow��� 7E>4�������&Quit��� MainWindow���>2B><0B8G=>� ?>4@5640=5� =0� ?8AB8�������&Routing��� MainWindow��� 0?078�������&Save��� MainWindow���0?078� :0B>�.�.�.������� &Save As...��� MainWindow���4!5;5:B8@09� 2A8G:>� �(�s�e�l�e�c�t�)������� &Select All��� MainWindow���(>:068� 2A8G:8� A;>525�������&Show All Layers��� MainWindow���0>:068� @>B>B8?=0� ?;0B:0�������&Show Breadboard��� MainWindow���4>:068� ?5G0B=0� ?;0B:0�(�P�C�B�)������� &Show PCB��� MainWindow���>:068� !E5<0B0�������&Show Schematic��� MainWindow���.>:068� 5B8:5B� =0� G0ABB0�������&Show part label��� MainWindow��� 73;54�������&View��� MainWindow���@>7>@5F�������&Window��� MainWindow���$&2OB� =0� ?@>2>4=8:0������� &Wire Color��� MainWindow��� >1;868�(C25;8G8�)�������&Zoom In��� MainWindow���&B40;5G8� �(�z�o�o�m� �o�u�t�)������� &Zoom Out��� MainWindow���,�1�0�0�%� �(?8:A5;5=�)@07<5@� �������100% (pixel) size��� MainWindow����1�0�0�0�% 07<5@������� 100% Size��� MainWindow���dAB8=A:8� @07<5@� �(:0:B>� I5� 873;5640� @50;=>� =0� 682>�)�������!Actual (real world physical) size��� MainWindow��� 50;5=� @07<5@������� Actual Size��� MainWindow���4>1028� B>G:0� =0� 45D>@<0F8O������� Add Bendpoint��� MainWindow���>1028� 15;56:0�������Add Note��� MainWindow���`>1028� B>G:0� =0� 45D>@<0F8O� =0� 871@0=8O� ?@>2>4=8:�������$Add a bendpoint to the selected wire��� MainWindow��� >1025B5� 15;56:0������� Add a note��� MainWindow���R>1028� <0@:8@0=0B0� G0AB� :J<� =870� >B� G0AB8�������Add selected part to bin��� MainWindow���>4@02=8�������Align��� MainWindow���>4@02=8� 4>;C������� Align Bottom��� MainWindow���>>4@02=8� E>@87>=B0;=>� 2� F5=BJ@0�������Align Horizontal Center��� MainWindow��� >4@02=8� 2� ;O2=>������� Align Left��� MainWindow��� >4@02=8� 2� 4OA=>������� Align Right��� MainWindow���>4@02=8� 3>@5������� Align Top��� MainWindow���:>4@02=8� 2� 25@B8:0;=8O� F5=BJ@�������Align Vertical Center��� MainWindow���f>4@02=8� =5I0B0� :J<� @5H5B:0B0� :>30B>� 38� ?@82;0G20B5�������!Align items to grid when dragging��� MainWindow���@>4@02=8� 871@0=8B5� 5;5<5=B8� 4>;C�������"Align selected items at the bottom��� MainWindow���d>4@02=8� 871@0=8B5� 5;5<5=B8� 2� E>@87>=B0;=8O� F5=BJ@�������-Align selected items at the horizontal center��� MainWindow���D>4@02=8� 871@0=8B5� 5;5<5=B8� 2� ;O2>������� Align selected items at the left��� MainWindow���F>4@02=8� 871@0=8B5� 5;5<5=B8� 2� 4OA=>�������!Align selected items at the right��� MainWindow���B>4@02=8� 871@0=8B5� 5;5<5=B8� 3>@5� �������Align selected items at the top��� MainWindow���d>4@02=8� 871@0=8B5� 5;5<5=B8� 2J2� 25@B8:0;=8O� F5=BJ@�������+Align selected items at the vertical center��� MainWindow���D>4@02=8� A?@O<>� @560B0�(@5H5B:0B0�)������� Align to Grid��� MainWindow��� A8G:8�������All��� MainWindow���^5� 2A8G:8� ?8AB8� A0� ?@5:0@0=8� 8� A2J@70=8� 2A5� >I5�������$All traces have not yet been routed.��� MainWindow���(2B><0B8G=>� >?@>2>48������� Autoroute��� MainWindow���8@5:0@09� 02B><0B8G=>� ?8AB8B5�������Autoroute connections...��� MainWindow���2B><0B8G=>� ?>4@5640=5� =0� ?8AB8�/@>25@:0� 70� :>=D;8:B8� ?@8� @07@01>B:0B0� �-� =0AB@>9:8�.�.�.�������Autorouter/DRC settings...��� MainWindow���Z2B><0B8G=>� ?>4@5640=5� =0� ?8AB8B5� 2� ?@>F5A�.�.�.�������Autorouting Progress...��� MainWindow���H2B><0B8G=>� ?>4@5640=5� =0� ?8AB8B5�.�.�.�������Autorouting...��� MainWindow���>!J74020<� @575@2=>� :>?85� =0� �'�%�1�'�������Backing up '%1'��� MainWindow���2�B�o�M� B5:AB>2� D09;� �(�*�.�h�t�m�l�)�������BoM Text File (*.html)��� MainWindow���20B0� A;>O������� Both Layers��� MainWindow���>;5=� A;>9������� Bottom Layer��� MainWindow���"@>B>B8?=0� ?;0B:0������� Breadboard��� MainWindow���09� 0?@54������� Bring Forward��� MainWindow���X09� 871@0=8B5� >15:B8� ?>�-=0?@54� 2� B5E=8O� A;>9�������/Bring selected object(s) forward in their layer��� MainWindow���p7:0@09� A5;5:B8@0=8B5� >15:B8� =09� �-� >B?@54� =0� B5E=8O� A;>9�������0Bring selected object(s) to front of their layer��� MainWindow���7:0@09� >B?@54�������Bring to Front��� MainWindow��� B<5=8�������Cancel��� MainWindow���D$09;JB� �%�1� =5� <>65� 40� 1J45� =0<5@5=�.�������Cannot find file %1.��� MainWindow���:5� <>65� 40� A5� >B?5G0B0� :J<� �%�1�������Cannot print to %1��� MainWindow���Z5� <>65� 40� A5� >B2>@8�(?@>G5B5�)� D09;� �1� �%�1�:� �%�2�.� �������Cannot read file 1 %1: %2.��� MainWindow���D5� <>65� 40� A5� 70?8H5� D09;� �%�1�:� �%�2�.� �������Cannot write file %1: %2.��� MainWindow���*!<5=8� A=8<:0B0� =0� � �%�2�������Change image to %2��� MainWindow���P@5<8=5B5� =0� 54=>A;>5=� @568<� =0� ?;0B:0B0�������Change to single layer pcb��� MainWindow���N@5<8=5B5� =0� 42CA;>5=� @568<� =0� ?;0B:0B0�������Change to two layer pcb��� MainWindow���0@>25@8� 0@545=8B5� 8AB8�������Check Loaded Traces��� MainWindow���,@>25@8� 70� >1=>2O20=8O�������Check for updates...��� MainWindow���r@>25@8� 40;8� =O<0� ?>� �-� =>20� 25@A8O� =0� �F�r�i�t�z�i�n�g� 70� A20;O=5�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���`715@8� 74@J=F0B0� 70� 70?J;20=5� A� 7075<O20=5� �(�G�N�D�)�������Choose Ground Fill Seed(s)...��� MainWindow���>715@5B5� D09;� 70� 5:A?>@B8@0=5B>�������Choose a folder for exporting��� MainWindow���d@5<0E=8� A5<5=F0B0� 70� 70?J;20=5� A� 7075<O20=5� �(�G�N�D�)�������Clear Ground Fill Seeds��� MainWindow���@5<0E=8� A5<5=F0B0� 70� 70?J;20=5� A� 7075<O20=5� �(�G�N�D�)�-�-?>72>;8� 70?J;20=5� A0<>� A� <54=0� ?8AB0�.�������1Clear ground fill seeds--enable copper fill only.��� MainWindow���>4�������Code��� MainWindow���>=25@B8@09B5�������Convert��� MainWindow���`>=25@B8@09� B>G:0� =0� 45D>@<0F8O� 2� ?@>E>45=� >B2>@�������Convert Bendpoint to Via��� MainWindow���x>=25@B8@09� ?@>E>45=� >B2>@� 2J2� B>G:0� =0� 45D>@<0F8O� �(>3J20=5�)�������Convert Via to Bendpoint��� MainWindow���d>=25@B8@09� B>G:0B0� =0� 45D>@<0F8O� 2� ?@>E>45=� >B2>@�������Convert the bendpoint to a via��� MainWindow���t>=25@B8@09� ?@>E>4=8O� >B2>@� 2� B>G:0� =0� 45D>@<0F8O�(>3J20=5�)�������Convert the via to a bendpoint��� MainWindow���<>;=8O� A;>9� A� ?8AB8� 5� 0:B82=8O�������Copper Bottom layer is active��� MainWindow���.0?J;20=5� A� <54=0� ?8AB0������� Copper Fill��� MainWindow���60?J;20=5� A� <54=0� ?8AB0�(�%�1�)�������Copper Fill (%1)��� MainWindow���R� 3>@=8O� 8� 4>;=8O� A;>9� A� ?8AB8� A0� 0:B82=8�������3Copper Top and Copper Bottom layers are both active��� MainWindow���<>@=8O� A;>9� A� ?8AB8� 5� 0:B82=8O�������Copper Top layer is active��� MainWindow���,>?8@0=5� =0� A5;5:F8OB0�������Copy selection��� MainWindow���B5� <>30� 40� =0<5@O� �d�o�c�k� ?@8BC@:0B0�������Couldn't get the dock widget��� MainWindow���0!J74020=5� =0� =>20� AE5<0� �������Create a new sketch��� MainWindow���:!J7409� ?8AB0� >B� �"<8H0�"� 2@J7:0�������%Create a trace from the ratsnest line��� MainWindow���F!J7409� ?@>2>4=8:� >B� �"<8H8B5� 2@J7:8�"�������$Create a wire from the ratsnest line��� MainWindow���"B@568� A5;5:F8OB0������� Cut selection��� MainWindow���d@>3@5A� =0� ?@>25@:0B0� 70� ?@028;0B0� ?@8� 48709=0� �.�.�.�������DRC Progress...��� MainWindow���:7E>45=� :>4� =0� �"�D�e�b�u�g�g�e�r�"� �-�a� �������Debugger Output��� MainWindow��� 7B@89�������Delete��� MainWindow���7B@89� <8=CA0������� Delete Minus��� MainWindow���87B@89� !2J@720I0� �"<8H0�"� 68F0�������Delete Ratsnest Line��� MainWindow��� 7B@89� @>2>4=8:������� Delete Wire��� MainWindow���L7B@89� 68F0B0� 4>� B>G:8B5� =0� 45D>@<0F8O�������Delete Wire up to bendpoints��� MainWindow���"7B@89� A5;5:F8OB0�������Delete selection��� MainWindow���L7B@89� A5;5:F8OB0� 157� ?@8:0G5=8B5� 68F8�������'Delete selection without attached wires��� MainWindow���"B<5=8� A5;5:F8OB0�������Deselect��� MainWindow���n@>25@:0� 70� A?0720=5� =0� ?@028;0B0� ?@8� ?@>5:B8@0=5� �(�D�R�C�)�������Design Rules Check (DRC)��� MainWindow���HB:0G8� 2A8G:8� 2@J7:8� =0� ?@>2>4=8F8B5�������Disconnect All Wires��� MainWindow���RB:0G8� 2A8G:8� ?@>2>4=8F8� >B� B>78� :>=5:B>@�������0Disconnect all wires connected to this connector��� MainWindow���b>:068� ?><>I� >B=>A=>� :>@5:B>@0� 70� G0AB8� 2� @0C75@�������&Display Parts Editor help in a browser��� MainWindow���^>:068� =O:>9� ?>;57=8� AJ25B8� 8� =><5@0� 2� �F�r�i�t�z�i�n�g�������+Display some handy Fritzing tips and tricks��� MainWindow���\>:068� ?@>7>@5F0� A� G0AB8B5� 2J2� A?8AJG5=� 873;54�������$Display the parts bin in a list view��� MainWindow���V>:07209� ?@>7>@5F0� A� G0AB8B5� 2� 284� =0� 8:>=8�������%Display the parts bin in an icon view��� MainWindow���05� ?@5:0@209� 02B><0B8G=>�������Do not autoroute��� MainWindow���X8EB5� ;8� 8A:0;8� 40� 70?078B5� 2=5A5=8B5� G0AB8�?�������'Do you want to keep the imported parts?��� MainWindow���V8EB5� ;8� 8A:0;8� 40� ?@>4J;68B5� 2J?@5:8� B>20�?�������Do you want to proceed anyway?��� MainWindow���D>4?><>3=5B5� D8=0=A>2>� =0� �F�r�i�t�z�i�n�g�������Donate to Fritzing��� MainWindow���&C1;8@09� A5;5:F8OB0�������Duplicate selection��� MainWindow���R@><5=8� �(?@><O=0� 2� 548B>@0� =0� =>28� G0AB8�)�������Edit (new parts editor)��� MainWindow���R 07@5H5B5� @538AB@8@0=5B>� =0� 3@5H:8� 2� D09;�������Enable debugging log��� MainWindow���J2548� "5:AB������� Enter Text��� MainWindow���F205<� �(�P�D�F�)�.�.�.�������Etchable (PDF)...��� MainWindow���F205<�(�S�V�G�)�.�.�.�������Etchable (SVG)...��� MainWindow���:A?>@B0� 70� 5F20=5� <>65� 40� ?>5<0� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6� �-�-� <>;O� >1>7=0G5B5� :>O� 8A:0B5� 40� 5:A?>@B8@0B5�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow���:A?>@B8@09� �S�V�G� D09;� =0� B078� G0AB� A� A;5B8� 2A8:8� A;>525� 2� B>78� 873;54� A� @57>;NF8O� �1�0�0�0� B>G:8� =0� 8=G�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���:A?>@B8@09� �S�V�G� D09;� =0� B078� G0AB� 2� B>78� 873;54� A� @57>;NF8O� �1�0�0�0� B>G:8� =0� 8=G�������-Export 1000 dpi SVG of this part in this view��� MainWindow���P:A?>@B8@09� A?8AJ:0� A� <0B5@80;8� �(�B�o�m�)�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���>:A?>@B8@09� :J<� �N�e�t�l�i�s�t� D09;�.�.�.�������Export Netlist...��� MainWindow���n:A?>@B8@09� >@<0;878@0=� A� 2A8G:8� A;OB8� A;>525� �S�V�G� D09;�������Export Normalized Flattened SVG��� MainWindow���B:A?>@B8@09� >@<0;878@0=� �S�V�G� D09;�������Export Normalized SVG��� MainWindow���J:A?>@B8@09� :J<� �S�P�I�C�E� �N�e�t�l�i�s�t� D09;�.�.�.�������Export SPICE Netlist...��� MainWindow���::A?>@B8@09B5� :J<� �S�V�G� D09;�.�.�.������� Export SVG...��� MainWindow���J7=5A8�(5:A?>@B8@09�)� 70� ?5G0B=0� ?;0B:0�������Export for PCB��� MainWindow���4:A?>@B8@09� 871@0=0B0� G0AB�������Export selected part��� MainWindow���R:A?>@B8@09� B5:CI0B0� AE5<0� :J<� � �S�V�G� �i�m�a�g�e�������)Export the current sketch as an SVG image��� MainWindow���R:A?>@B8@09� B5:CI0B0� AE5<0� :J<� � �E�a�g�l�e� �C�A�D�������&Export the current sketch to Eagle CAD��� MainWindow���:A?>@B8@09� B5:CI0B0� AE5<0� :J<� �E�x�t�e�n�d�e�d� �G�e�r�b�e�r� �f�o�r�m�a�t� �(�R�S�-�2�7�4�X�)� 70� ?@>D5A8>=0;=0� 87@01>B:0� =0� ?5G0B=8� ?;0B:8�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow���A:?>@B8@09� B5:CI0B0� AE5<0� :J<� �P�D�F� 70� 4><0H=0� 87@01>B:0� ?>� D>B>� <5B>4�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow���:A?>@B8@09� B5:CI0B0� AE5<0� :J<� �S�V�G� 70� 4><0H=0� 87@01>B:0� ?>� D>B>� <5B>4�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���t:A?>@B8@09� 2848<0B0� G0AB� =0� B5:CI0B0� AE5<0� :J<� � �J�P�G� �i�m�a�g�e�������@B8@09� 2848<0B0� G0AB� =0� B5:CI0B0� AE5<0� :J<� � �P�D�F� �i�m�a�g�e�������@B8@09� 2848<0B0� G0AB� =0� B5:CI0B0� AE5<0� :J<� � �P�N�G� �i�m�a�g�e�������@B8@09� 2848<0B0� G0AB� =0� B5:CI0B0� AE5<0� :J<� � �P�o�s�t�S�c�r�i�p�t� �i�m�a�g�e�������CExport the visible area of the current sketch as a PostScript image��� MainWindow���:A?>@B8@09�.�.�.������� Export...��� MainWindow���:A?>@B8@0<�.�.�.������� Exporting...��� MainWindow���0$09;JB� �'�%�1�'� =5� 5� =0<5@5=�������File '%1' not found��� MainWindow���0?J;=8� ?@07=8B5� @538>=8� 2� A;>O� A� ?8AB8B5� �-�-� B>20� 2:;NG20� 8� 2A8G:8� ?8AB8� A2J@70=8� A� /� �(�G�N�D�)�������ZFill empty regions of the copper layer--fill will include all traces connected to a GROUND��� MainWindow���0?J;=8� ?@07=8B5� @538>=8� A� <54=0� ?8AB0� �-�-B>20� 2:;NG20� 2A8G:8� ?8AB8� A2J@70=8� :J<� 704045=8B5� A5<5=0� 70� @07@0AB20=5� =0� <54=8O� A;>9�������[Fill empty regions of the copper layer--fill will include all traces connected to the seeds��� MainWindow���0?J;=8� ?@07=8B5� @538>=8� 2� A;>O� A� ?8AB8B5� �-�-� B>20� 2:;NG20� 8� 2A8G:8� ?8AB8� A2J@70=8� A� /� �(�G�N�D�)�������RFill empty regions of the copper layer--not including traces connected to a GROUND��� MainWindow���*0<5@8� G0AB� 2� AE5<0B0�������Find part in sketch...��� MainWindow���0><>I� ?@8� ?J@20� C?>B@510�������First Time Help��� MainWindow���<!J15@8� 4>� @07<5@0� =0� ?@>7>@5F0������� Fit in window��� MainWindow��� 1J@=8� >3;540;=>�������Flip��� MainWindow���x1J@=8� B5:CI0B0� A5;5:F8O� >3;540;=>� ?>� E>@87>=B0;=0B0� @02=8=0�������#Flip current selection horizontally��� MainWindow���t1J@=8� B5:CI0B0� A5;5:F8O� >3;540;=>� ?>� 25@B8:0;=0B0� @02=8=0�������!Flip current selection vertically��� MainWindow���0A8;AB25=>� >1=>2O20=5� =0� AB0BCA0� =0� 02B><0B8G=>� ?@5:0@20=5� 8� �"<8H8B5�"� A2@J7:8�������)Force Update Routing Status and Ratsnests��� MainWindow����F�r�i�z�t�i�n�g�������Fritzing��� MainWindow���Z0?8B20=5� 70� 87@01>B:0� =0� ?;0B:0� :J<� �F�r�i�t�z�i�n�g�������Fritzing Fab Quote...��� MainWindow��8�F�r�i�t�z�i�n�g� D09;>25B5� �(�*�%�1� �*�%�2� �*�%�3� �*�%�4� �*�%�5�)�;�;�F�r�i�t�z�i�n�g� �(�*�%�1�)�;�;�F�r�i�t�z�i�n�g� !?>45;O5<� �(�*�%�2�)�;�;�F�r�i�t�z�i�n�g� '0AB� �(�*�%�3�)�;�;�F�r�i�t�z�i�n�g� 18=0@5=�(�*�%�4�)�;�;�F�r�i�t�z�i�n�g� A?>45;O5<� �B�i�n� �(�*�%�5�)�������Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5)��� MainWindow���,'0AB� =0� �F�r�i�t�z�i�n�g� �(�*�%�1�)�������Fritzing Part (*%1)��� MainWindow���25=5@8@0<� 70?J;20=5B>� � �%�1�������Generating %1 fill...��� MainWindow���:A?>@B0� :J<� �G�e�r�b�e�r� A8AB5<0� <>65� 40� ?>5<0� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6� �-�-� <>;O� >1>7=0G5B5� :>O� 8A:0B5� 40� 5:A?>@B8@0B5�������^Gerber export can only handle one board at a time--please select the board you want to export.��� MainWindow���< 07<5@� =0� @5H5B:0B0� �(<@560B0�)�:������� Grid Size:��� MainWindow���80?J;20=5� A� 7075<O20I0� ?8AB0������� Ground Fill��� MainWindow���@0?J;20=5� A� 7075<O20I0� ?8AB0�(�%�1�)�������Ground Fill (%1)��� MainWindow���J!:@89� 2A8G:8� A;>525� =0� B5:CI8O� 873;54�������'Hide all the layers of the current view��� MainWindow���.!:@89� 5B8:5B0� =0� G0ABB0�������Hide part label��� MainWindow���4!:@89� A8B>?5G0B0� =0� G0ABB0�������Hide part silkscreen��� MainWindow���`!:@88�/?>:068� A;>O� A� A8B>?5G0B0� A0<>� 70� B078� G0AB�������1Hide/show the silkscreen layer for only this part��� MainWindow���PB:@>8� 2A8G:8� =5A2J@70=8� 2@J7:8�(8� ?8AB8�)�������!Highlight all unrouted connectors��� MainWindow���B:@>8� G0AB8B5� �,:>8B>� A0� B2J@45� 1;87:>� 54=0� 4>� 4@C30� 70� 40� <>65� 40� 1J45� 87@01>B5=>� 157>?0A=>�������JHighlights any parts that are too close together for safe board production��� MainWindow���>;:>� I5� AB@C20� 40� A5� ?@>872545� 5G0B=0� ?;0B:0� >B� B078� AE5<0� 2� D01@8:0B0� =0� �F�r�i�t�z�i�n�g�������KHow much would it could to produce a PCB from this sketch with Fritzing Fab��� MainWindow���:>� �";5?:020� �"� G0AB� 1J45� ?@5<5AB5=0� �,� B>� 8� G0AB8B5� 2J@EC� =5O� 1820B� ?@5<5AB5=8� A� =5O�������>If a "sticky" part is moved, parts on top of it are also moved��� MainWindow���|=5A5B5� G0AB8� 8� 18=0@=8� D09;>25� A� G0AB8� >B� ?@548H=0� 8=AB0;0F8O�������0Import parts and bins from previous installation��� MainWindow���=A?5:B>@������� Inspector��� MainWindow��73;5640� =5� <>65� 40� 1J45� 02B><0B8G=>� D878G5A:8O� @07<5@� =0� 20H8O� <>=8B>@� 70� B>20� � �' 50;5=�  07<5@�'� :0:B>� 873;5640� 2� <><5=B0� 5� A0<>� ?@54?>;>65=85� �.@5?>@JG8B5;=>� 5� 40� 87?>;720B5� G0ABB0� ;8=89:0� �,� 40� O� 87B53;8B5� =0� 5:@0=0� 8� ?>A;5� 278<09:8� 8AB8=A:0� ;8=88:0� 40� 4>1;86020B5� 4>:0B>� AJ2?04=0B� 425B5� ;8=89:8� =0;>65=8� 54=0� =04� 4@C30�.">3020� ?;0B:0B0� I5� 5� 2� @50;5=� @07<5@�.������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow���&�J�P�E�G� A=8<:0� �(�*�.�j�p�g�)�������JPEG Image (*.jpg)��� MainWindow���!B0@B8@09� �%�1�.�.�.������� Launch %1...��� MainWindow��� !;>525�������Layers��� MainWindow���Z!?8AJ:� A� G0AB8B5� �(8� A<5B:0� 70� 0B5@80;8B5�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow���0@5640<�.�.�.������� Loading...��� MainWindow���0:;NG8� G0ABB0������� Lock Part��� MainWindow���A=>25=@>7>@5F�:�:?@5<5AB8J<0?:0B0!JA$09;>25�-� >A=>2=8O� ?@>7>@5F� ;8?A20�������0MainWindow::moveToPartsFolder mainwindow missing��� MainWindow���A=>25=� ?@>7>@5F� �:�:�p�o�p�u�l�a�t�e�M�e�n�u�W�i�t�h�I�n�d�e�x�:� =5� <>65� 40� A5� 70@548� ?@8<5@=0� AE5<0� A� 84� �=� �'�%�1�'�������EMainWindow::populateMenuWithIndex: couldn't load example with id='%1'��� MainWindow���88=8<878@09� B5:CI8O� ?@>7>@5F�������Minimize current window��� MainWindow��@5<5AB8� 871@0=8B5� ?8AB8� >B� 4@C30B0� AB@0=0� =0� ?;0B:0B0� �(7015;56:0�:� ?J@20B0� ?8AB0� I5� 1J45� ?@5<5AB5=0� 8� ?>A;5� >AB0=0;8B5� A;54� =5O� �)�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���,@5<5AB8� 2� 4>;=8O� A;>9�������Move to bottom layer��� MainWindow���D@5<5AB8� 2� 4@C38O� A;>9� =0� ?;0B:0B0�������Move to other side of the board��� MainWindow���,@5<5AB8� 2� 3>@=8O� A;>9�������Move to top layer��� MainWindow���>2�������New��� MainWindow���85� 5� =0<5@5=0� AE5<0� 2J2� �'�%�1�'�������No Sketch found in '%1'��� MainWindow���@O<0� 2@J7:8� :J<� :>@5==0B0� 2@J7:0�������No connections to route��� MainWindow���.O<0� 3>@5=� A;>9� A� ?8AB8�������No copper top layer��� MainWindow���O<0� B>G=>� AJ2?040I0� G0AB�;� �F�r�i�t�z�i�n�g� 871@0� =09� �-� 1;87:>B>� AJ2?045=85�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow���O<0� =0<5@5=8� >AB0@5;8� G0AB8� A8G:8� G0AB8� A0� ?>A;54=0B0� @52878O�.�������7No outdated parts found. All your parts are up-to-date.��� MainWindow��.O<0� G0AB� A� B0:820� ?0@0<5B@8�  01>B8<� =04� B>20� 40� 87153=5<� B>20� AJ>1I5=85� 8� 40� 28� 4045<� 2J7<>6=>AB� 40� 8718@0B5� <564C� A2>9AB20� :>8B>� =08AB8=0� AJI5AB2C20B�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���h8:0:28� G0AB8� =5� AJ2?040B� A� 4C<0B0� 70� BJ@A5=5� � �'�%�1�'�.�������"No parts matched search term '%1'.��� MainWindow���>B2J@48�������OK��� MainWindow���.=;09=� A?@02:0� =0� G0AB8�������Online Parts Reference��� MainWindow���80;5@8O� A� ?@>5:B8� 2� 8=B5@=5B�������Online Projects Gallery��� MainWindow���:=B5@5A=8� ?@8<5@8� >B� 8=B5@=5B�������Online Tutorials��� MainWindow���hB2>@8� AB@0=8F0B0� 70� 40@5=8O� =0� �F�r�i�t�z�i�n�g� 2� 8=B5@=5B�.�������Open Fritzing donation web page��� MainWindow���FB2>@8� ?@8<5@=8� ?@>5:B8� =0� �F�r�i�t�z�i�n�g�������Open Fritzing examples��� MainWindow���@B2>@8� ?><>I=8O� D09;� =0� �F�r�i�t�z�i�n�g�������Open Fritzing help��� MainWindow���,B2>@8� A?@02:0� A� G0AB8�������Open Parts Reference��� MainWindow���B2>@8� �F�r�i�t�z�i�n�g� AE5<0� �(�f�z�z�,� �.�f�z�)�,� 8;8� 70@548� �F�r�i�z�t�i�n�g� G0AB� �(�.� �f�p�z�)� �,� 8;8� :0B0;>3� A� G0AB8� =0� �F�r�i�t�z�i�n�g� �(�,�f�b�z� �.�f�z�b�z�)�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���dB2>@8� ?@>7>@5F� 70� ?@>3@0<8@0=5� =0� <8:@>:>=B@>;5@0�������'Open microcontroller programming window��� MainWindow���>B2>@8� ?@>7>@5F� 70� ?@>3@0<8@0=5�������Open programming window��� MainWindow���pB2>@8� ?@><5=8B5;O� =0� =>28� G0AB8� 2J@EC� AJI5AB2C20I0� G0AB�������-Open the new parts editor on an existing part��� MainWindow���>@JG09� 5G0B=0� ?;0B:0� AJ74045=0� >B� B2>OB0� AE5<0� >B� 8725AB=0B0� �"�F�r�i�t�z�i�n�g�"� D01@8:0�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow���,>@JG09� 5G0B=0� ?;0B:0�������Order a PCB...��� MainWindow���AB0@5;8� G0AB8�������Outdated parts��� MainWindow���5G0B=0� ;0B:0�������PCB��� MainWindow���.0AB@>9:8� =0� AB@0=8F0B0������� Page Setup��� MainWindow���R><>I� 70� C?>B@510B0� =0� :>@5:B>@0� =0� G0AB8�������Parts Editor Help��� MainWindow���B>AB028� AJ4J@60=85B>� =0� ;8?1>@40�������Paste clipboard contents��� MainWindow���l>AB025B5� AJ4J@60=85B>� =0� :;8?1>@40� 2� 704045=>B>� <OAB>�������!Paste clipboard contents in place��� MainWindow���2>AB028� =0� 4045=>B>� <OAB>�������Paste in Place��� MainWindow���Z>;O� 8715@5B5� ?@548H=0B0� ?0?:0� =0� �F�r�i�t�z�i�n�g�.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow���>;O� 8715@5B5� ;0B:0� �-�-� 70?J;20=5B>� A� <54=0� ?8AB0� <>65� 40� >1@01>B20� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow���>;O� 8715@5B5� ;0B:0� �-�-� 70?J;20=5B>� A� 7075<O20I0� ?8AB0� <>65� 40� >1@01>B20� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow���>;O� 8715@5B5� ;0B:0� �-�-� 70?J;20=5B>� A� <54=0� ?8AB0� <>65� 40� >1@01>B20� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow���>;O� 8715@5B5� ?5G0B=0� ?;0B:0�.� @>25@:0B0� 70� ?@028;0B0� ?@8� ?@>5:B8@0=5� �(�D�R�C�)� <>65� 40� >1@01>B20� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6�.�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow�� >;O� 8715@5B5� ?;0B:0B0� G88B>� ?8AB8� 8A:0B5� 40� 1J40B� ?>4@545=8� 02B><0B8G=>� �.">78� ?@>F5A� <>65� 40� >1@01>B20� A0<>� ?>� 54=0� ?;0B:0� =0� 254=J6�.�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow���>;O� 8715@5B5� 8<5� =0� � �.�f�z�z� D09;0� A� :>5B>� 18EB5� 8A:0;8� 40� AJE@0=8B5� �'�%�1�'�������0Please specify an .fzz file name to save '%1' to��� MainWindow���JC1;8:C209� ?@>5:B� 2� A09B0� =0� �F�r�i�t�z�i�n�g�������&Post a project to the Fritzing website��� MainWindow���^0:;NG20� 2J7<>6=>ABB0� 70� <5AB5=5� =0� 4045=0� G0AB�������Prevent a part from being moved��� MainWindow���0B?5G0B09� B5:CI8O� 873;54�������Print the current view��� MainWindow���@8=B8@0<�.�.�.������� Printing...��� MainWindow���@>4J;68�������Proceed��� MainWindow���&7;57� >B� ?@>3@0<0B0�������Quit the application��� MainWindow���*>24830=5� 8� !=86020=5�������Raise and Lower��� MainWindow���!0<>�-G5B5=5������� Read-only��� MainWindow��� >B>2�������Ready��� MainWindow��@5A<5B=8� =0=>2>� AB0BCA0� =0� 02B><0B8G=>� ?@5:0@20=5� =0� ?8AB8B5� 8� �"<8H8B5�"� 2@J7:8� �(2� A;CG09� G5� 02B><0B8G=>B>� >1=>2O20=5� =5� @01>B8� :>@5:B=>�)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow���0J@=8� >1@0B=>� >B<5=5=>B>�������Redo��� MainWindow���$@570@548� AE5<0B0� �������Reload the sketch��� MainWindow���J@5<0E=8� B>G:0� =0� 45D>@<0F8O�(>3J20=5�)�������Remove Bendpoint��� MainWindow���@@5<0E=8� 70?J;20=5� A� <54=0� ?8AB0�������Remove Copper Fill��� MainWindow���D?@5<0E=8� 70?J;20=5B>� A� <54=0� ?8AB0�������Remove copper fill��� MainWindow���D@5<0E=8� 70?J;20=5B>� A� <54=0� ?8AB0�������Remove the copper fill��� MainWindow���&>:;04209B5� ?@>1;5<�������Report a bug...��� MainWindow���b>:;04209B5� ?@>1;5<� :>9B>� AB5� =0<5@8;8� 2� �F�r�i�t�z�i�n�g�������%Report a but you've found in Fritzing��� MainWindow���LJ7AB0=>28� =0AB@>9:8B5� ?>� ?>4@0718@0=5�������Restore Default��� MainWindow���8@JI0=5� >1@0B=>� =0� ?@><5=8B5�������Revert��� MainWindow���@0� 2J@=0� ;8� >1@0B=>� 459AB285B>� �?�������Revert?��� MainWindow���02J@B8�������Rotate��� MainWindow���.02J@B8� =0� �1�8�0�� �{�1�8�0�?�}������� Rotate 180���� MainWindow���02J@B8� =0� �1�3�5�� 3@04CA0� ?>� ?>A>:0� =0� G0A>2=8:>20B0� AB@5;:0� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���z02J@B8� =0� �4�5� 3@04CA0� >1@0B=>� =0� G0A>2=8:>20B0� AB@5;:0� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow���02J@B8� =0� �1�3�5�� 3@04CA0� ?>� ?>A>:0� =0� G0A>2=8:>20B0� AB@5;:0� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���z02J@B8� =0� �4�5� 3@04CA0� >1@0B=>� =0� G0A>2=8:>20B0� AB@5;:0� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���|02J@B8� 871@0=8B5� G0AB8� =0� �4�5� 3@04CA0� ?>� G0A>2=8:>20B0� AB@5;:0�������-Rotate current selection 45 degrees clockwise��� MainWindow���02J@B8� 871@0=8B5� G0AB8� =0� �4�5� 3@04CA0� >1@0B=>� =0� G0A>2=8:>20B0� AB@5;:0�������5Rotate current selection 45 degrees counter clockwise��� MainWindow���02J@B8� 871@0=8B5� G0AB8� =0� �9�0� 3@04CA0� >1@0B=>� =0� G0A>2=8:>20B0� AB@5;:0�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���L02J@B8� 871@0=8B5� G0AB8� =0� �1�8�0� 3@04CA0�������(Rotate the selected parts by 180 degrees��� MainWindow���02J@B8� 871@0=8B5� G0AB8� =0� �9�0� 3@04CA0� ?>� ?>A>:0� =0� G0A>2=8:>20B0� AB@5;:0�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow���D2B><0B8G=>B>� A2J@720=5� ?@8:;NG5=>�������Routing completed��� MainWindow���2B><0B8G=>B>�-A2J@720=5� ?@8:;NG5=>� 87?>;7209:8� �%�n� ?@>E>4=8� >B2>@8� <564C� A;>525B5���2B><0B8G=>B>�-A2J@720=5� ?@8:;NG5=>� 87?>;7209:8� �%�n� ?@>E>4=8� >B2>@8� <564C� A;>525B5�������)Routing completed using %n jumper part(s)��� MainWindow���$�S�V�G� A=8<:0� �(�*�.�s�v�g�)�������SVG Image (*.svg)��� MainWindow���0?8H8� �%�1�������Save %1��� MainWindow���v0?075B5� A?8AJ:� A� <0B5@80;8B5� �/A?8AJ:� 70� ?>:C?:8� :0B>� B5:AB�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���B0?075B5� <@56>2� ;8AB� �S�P�I�C�E� �f�o�r�m�a�t�������Save a netlist in SPICE format��� MainWindow���F0?075B5� <@56>2� ;8AB� 2J2� �X�M�L� �f�o�r�m�a�t�������Save a netlist in XML format��� MainWindow���.0?075B5� B5:CI0B0� AE5<0�������Save the current sketch��� MainWindow���0?8A0=� �'�%�1�'������� Saved '%1'��� MainWindow���!E5<0B8G5=������� Schematic��� MainWindow��� "J@A8�������Search��� MainWindow���`"J@A8� G0AB8� 2� AE5<0B0� :0B>� 38� AJ?>AB028H� A� B5:AB�������-Search for parts in a sketch by matching text��� MainWindow���!5;5:B8@09� 2A8G:8� ?8AB8� 2� @568<� �"5� ?>4@56409� 02B><0B8G=>� ?@8� 02B><0B8G=>� ?>4@5640=5�"�������#Select All "Don't Autoroute" Traces��� MainWindow���n!5;5:B8@09� 2A8G:8� ?8AB8� 2� @568<� 02B><0B8G=>� ?>4@5640=5� �������Select All Autoroutable Traces��� MainWindow���T!5;5:B8@09� 2A8G:8� 70?J;20=8O� A� <54=0� ?8AB0�������Select All CopperFill��� MainWindow���4!5;5:B8@09� 2A8G:8� <>ABG5B0�������Select All Jumpers��� MainWindow���:715@8� 2A8G:8� 70:;NG5=8� G0AB8�������Select All Locked Parts��� MainWindow���.!5;5:B8@09� 2A8G:8� ?8AB8�������Select All Traces��� MainWindow���B!5;5:B8@09� 2A8G:8� ?@>E>4=8� >B2>@8�������Select All Vias��� MainWindow���8!5;5:B8@09� 2A8G:8� @>2>4=8F8�������Select All Wires��� MainWindow���T715@5B5� :>9� �F�r�i�t�z�i�n�g� D09;� 40� 1J45� >B2>@5=�������Select a Fritzing File to Open��� MainWindow���T!5;5:B8@09� 2A8G:8� 70?J;20=8O� A� <54=0� ?8AB0�������Select all copper fill items��� MainWindow���2!5;5:B8@0� 2A8G:8� 5;5<5=B8�������Select all elements��� MainWindow���H!5;5:B8@09� 2A8G:8� <>ABG5B0� 8� A2@J7:8�������Select all jumper item parts��� MainWindow���f715@8� 2A8G:8� G0AB8� :>8B>� =5� <>30B� 40� 1J40B� <5AB5=8�������$Select all parts that can't be moved��� MainWindow���B!5;5:B8@09� 2A8G:8� ?@>2>48<8� ?8AB8�������Select all trace wires��� MainWindow���!5;5:B8@09� 2A8G:8� 68F8� 87:;NG5=8� >B� 02B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8�������0Select all trace wires excluded from autorouting��� MainWindow���!5;5:B8@09� 2A8G:8� ?8AB8� :>8B>� <>30B� 40� 1J40B� ?@><5=O=8� ?@8� 02B><0B8G=>� ?>4@5640=5� =0� ?8AB8B5�������=Select all trace wires that can be changed during autorouting��� MainWindow���J715@8� 2A8G:8� ?@>E>4=8� >B2>@8� 8� G0AB8�������Select all via parts��� MainWindow���8!5;5:B8@09� 2A8G:8� ?@>2>4=8F8�������Select all wires��� MainWindow��!5;5:B8@09� 2A8G:8� ?8AB8� ?@8� :>8B>� 5:@0==>B>� <5AB>?>;>65=85� =5� AJ2?040� A� @50;=>B>� <5AB>?>;>65=85�.� 5>1E>48<>� A0<>� 70� AE5<8� ?@8� :>8B>� A5� 87?>;720� 02B><0B8G=>� ?>4@5640=5� =0� ?8AB8B5� A� 25@A8O� �0�.�7�.�1�0� 8;8� ?>� AB0@0�������Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier��� MainWindow���6!5;5:B8@09� >AB0@5;8B5� G0AB8�������Select outdated parts��� MainWindow���7?@0B8� 0704������� Send Backward��� MainWindow���X7?@0B8� 871@0=8B5� >15:B8� =0704� 2� B5E=8O� A;>9�������+Send selected object(s) back in their layer��� MainWindow���`7?@0B8� 871@0=8B5� >15:B8� =09� >B704� 2� B5E=8O� A;>9�������2Send selected object(s) to the back of their layer��� MainWindow���7?@0B8� >B704������� Send to Back��� MainWindow���$0409� F2OB� =0� D>=0�������Set Background Color...��� MainWindow���L0409� @07<5@� =0� @5H5B:0B0� �(<@560B0�)�.�.�.�������Set Grid Size...��� MainWindow���^0409� >BAB>O=85B>� ?@8� 70?J;20=5� A� 7075<O20=5�.�.�.�������Set Ground Fill Keepout...��� MainWindow���P0409� 7@J=F0B0� 70� 70?J;20=5� A� 7075<O20=5�������Set Ground Fill Seed��� MainWindow���0409� ?0@0<5B@8� 70� 02B><0B8G=>� =0@5640=5� =0� ?8AB8B5� 2:;NG8B5;=>� 8� >BAB>O=85�������/Set autorouting parameters including keepout...��� MainWindow���l0409� 8� 420B0� A;>O� A� ?8AB8� :0B>� ?>72>;5=8� 70� =0B8A:0=5������� Set both copper layers clickable��� MainWindow���N0409� 4>;=8O� A;>9� ?>72>;5=� 70� =0B8A:0=5�������!Set copper bottom layer clickable��� MainWindow���N0409� 3>@=8O� A;>9� ?>72>;5=� 70� =0B8A:0=5�������Set copper top layer clickable��� MainWindow���B0409� F2OB� =0� D>=0� 70� B>78� 873;54�������%Set the background color of this view��� MainWindow���T0409� @07<5@� =0� @5H5B:0B0� �(<@560B0�)� 70� �%�1�.�������Set the grid size for %1.��� MainWindow���0409� <8=8<0;=>B>� >AB>O=85� <564C� 70?J;20=5B>� A� 7075<O20=5� 8� ?8AB8B5� 8;8� :>=5:B>@8B5� �������ESet the minimum distance between ground fill and traces or connectors��� MainWindow���R0409� @07<5@0� =0� @5H5B:0B0� 70� B>78� 873;54�������%Set the size of the grid in this view��� MainWindow���!?>45;8�������Share��� MainWindow���*!?>45;8� 2� 8=B5@=5B�.�.�.�������Share online...��� MainWindow���.0@5640=5� =0� :>=7>;0� �%�1�������Shell launch %1��� MainWindow���>:068� :>40������� Show Code��� MainWindow���>:068� @5H5B:0������� Show Grid��� MainWindow���R>:068� ?@>7>@5F0� A� G0AB8B5� 2� 284� =0� 8:>=8�������Show Parts Bin Icon View��� MainWindow���b>:07209� ?@>7>@5F0� A� G0AB8B5� :0B>� A?8AJG5=� 873;54�������Show Parts Bin List View��� MainWindow���8>:068� 8=D>@<0F8O� >B=>A=>� �Q�t�������Show Qt's about box��� MainWindow���\>:068� 2A8G:8� =0;8G=8� A;>525� 70� B5:CI8O� 873;54�������2Show all the available layers for the current view��� MainWindow���0>:068� 5B8:5B0� =0� G0ABB0�������Show part label��� MainWindow���6>:068� A8B>?5G0B0� =0� G0ABB0�������Show part silkscreen��� MainWindow���8>:068� 873;54� 5G0B=0� ?;0B:0�������Show the PCB view��� MainWindow���`>:068� B5:AB>20B0� :CB8O� �">B=>A=>�"� =0� 0?;8:0F8OB0������� Show the application's about box��� MainWindow���0>:068� @>B>B8?5=� 873;54�������Show the breadboard view��� MainWindow���B>:068� :>40� �(?@>3@0<8AB:8�)� 873;54������� Show the code (programming) view��� MainWindow��� >:068� @5H5B:0B0������� Show the grid��� MainWindow���2>:068� AE5<0B8G=8O� 873;54�������Show the schematic view��� MainWindow���L>:068� =5?@5:0@0=8B5� 02B><0B8G=>� ?8AB8������� Show unrouted��� MainWindow���V>:068�/!:@89� =04?8A0� =0� A5;5:B8@0=8B5� G0AB8�������*Show/hide the label for the selected parts��� MainWindow���,!E5<0B0� 5� 5:A?>@B8@0=0�������Sketch exported��� MainWindow���R!E5<0B0� 5� 5:A?>@B8@0=0� :J<� �G�e�r�b�e�r� A8AB5<0�������Sketch exported to Gerber��� MainWindow���!J65;O20<�!�������Sorry!��� MainWindow���b!J65;O20<5�,� �"�%�1�"� >I5� =5� 5� 23@045=>� :0B>� ?>44@J6:0�������(Sorry, "%1" has not been implemented yet��� MainWindow���*715@5B5� 8<5� =0� D09;0�������Specify a file name��� MainWindow���5?:020�������Sticky��� MainWindow���7?@028� :@820�������Straighten Curve��� MainWindow���J7?@028� :@820B0� =0� 871@0=8O� ?@>2>4=8:�������)Straighten the curve of the selected wire��� MainWindow���#A?5H=>� A0� >1=>25=8� �%�1� G0AB�(8�)� >;O� ?@>25@5B5� 2A8G:8� 873;548� 70� ?>B5=F80;=8� AB@0=8G=8� 5D5:B8�.�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow��@J2� �S�v�g� D09;0� �%�1� ;8?A20� � �'�%�2�'� A;>9�.� 0� ?>25G5� 8=D>@<0F8O� >B=>A=>� :0:� 40� AJ4045B5� ?;0B:0� A� A?5F80;=0� D>@<0� <>;O� 286B5� >1OA=5=85B>� =0� �<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�<�/�a�>�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���40<5=5=� 5� � �%�1� AJA� <>4C;� �%�2�������Swapped %1 with module %2��� MainWindow���"5:ABJB� I5� 1J45� AJ?>AB025=� A� 5B8:5B0� =0� G0ABB0� �,>?8A0=85B>�,703;0285B>� 8� 8� B=�.� J2545B5� B5:AB� :>9B>� 40� A5� 87?>;720� 70� :@8B5@88� �:�������NText will match part label, description, title, etc. Enter text to search for:��� MainWindow��`$09;>28O� D>@<0B� � �.�f�z� 25G5� =5� A5� 87?>;720� � � 8EB5� ;8� 8A:0B5� 40� :>=25@B8@0B5� D09;JB� �'�%�1�'� � 2J2� =>28O� D>@<0B� �.� �f�z�z� 8;8� 8A:0B5� 40� 3>� >B2>@8B5� 2� AB0@8O� D>@<0B� A0<>� A� ?@020� 70� G5B5=5�?�������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow���`@>F5A0� ?>� :>=25@B8@0=5� =O<0� 40� <>45D8F8@0� �'�%�1�'�.�������,The conversion process will not modify '%1'.��� MainWindow��>@=8OB� �(�c�o�p�p�e�r� �1�)� A;>9� =5� 5� =0;8G5=� =0� 54=>A;>9=0� ?;0B:0�.� >;O� ?@52:;NG5B5� ?;0B:0B0� =0� @568<� A� 420� A;>O� 8;8� 8715@5B5� 4>;=8O� �(�c�o�p�p�e�r� �0�)� A;>9�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���`0?:0B0� �"�%�1�"� =5� 5� 8AB0;0F8>==0� ?0?:0� =0� �F�r�i�t�z�i�n�g�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���xO<0� =5A2J@70=8� :><?>=5=B8� 8� ?@5:0@0=8� A2@J7:8� 2� B>78� 873;54�������/There are no unrouted connections in this view.��� MainWindow���p5G5� 8<0� G0AB� A� 845=B8D8:0B>@� �'�%�1�'� 70@545=0� 2J2� �F�r�i�t�z�i�n�g�������:There is already a part with id '%1' loaded into Fritzing.��� MainWindow�� "078� >?5@0F8O� =5� <>65� 40� 1J45� >B<5=5=0� 2� ?>A;54AB285� �-�-� I5� 703C18B5� 2A8G:8B5� A8� ?@><5=8� � � 0� 4020<� =0?@54� 8� 40� 2J@=0� ?@><5=8B5� ;8� � �?� �������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow��">20� A:>@>� I5� 28� ?>72>;8� 40� 8<0B5� 5:A?>@B� =0� 20H0B0� �F�r�i�t�z�i�n�g� AE5<0� :J<� A>DBC5@� =0� �E�A�G�L�E�.� :>� 18EB5� 8A:0;8� 40� 8<0� ?>25G5� 5:A?>@B8� :J<� 4@C38� A8AB5<8� �,<>;O� 409B5� =8� 845O� 8;8� ?>4?><>3=5B5� =59=>B>� 87?J;=5=85�.�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow���>4@548� 8F8B5������� Tidy Wires��� MainWindow���,>4@548� 871@0=8B5� 68F8�������Tidy selected wires��� MainWindow���<!J25B8� �,� ><5@0� 8� J@78� 1CB>=8�������Tips, Tricks and Shortcuts��� MainWindow���>@5=� A;>9������� Top Layer��� MainWindow���"@5B8@09� B>78� A2J@720I� 5;5<5=B� 8� =53>28B5� 2@J7:8� :0B>� �"75<O�"� ?@8� 70?J;20=5� A� 7075<O20=5� �(�G�N�D�)�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���5� 5� 2J7<>6=>� 40� 1J45� 5:A?>@B8@0=�(87=5A5=�)� �%�1� :0B>� B8?� A?>45;O5<� ������� Unable to export %1 as shareable��� MainWindow���l5� <>65� 40� 5:A?>@B8@0� �(87=5A5�)� �%�1� :J<� A?>45;O5<0� AE5<0�������'Unable to export %1 to shareable sketch��� MainWindow���D5� <>65� 40� A5� 70@548� G0ABB0� >B� �%�1�'�������Unable to load part from '%1'��� MainWindow���D5� <>30B� 40� 1J40B� >B2>@5=8� �%�1�'�:� �%�2�������Unable to open '%1': %2��� MainWindow���`5� <>30B� 40� 1J40B� >B2>@5=8� A?>45;O5<8B5� �'�%�1�'�:� �%�2�������!Unable to open shareable '%1': %2��� MainWindow���l5� <>30B� 40� 1J40B� >B2>@5=8� A?>45;O5<0B0� G0AB� � �'�%�1�'�:� �%�2�������&Unable to open shareable part '%1': %2��� MainWindow���@5� 5� 2J7<>6=>� 40� 1J45� 70?8A0=� �%�1�������Unable to save %1��� MainWindow���!?8AJ:0� A� G0AB8B5� =5� <>60� 40� 1J45� AJE@0=5=� �,=>� B5:AB0� 2A5� >I5� 5� 2� ;8?1>@40�.�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow��� B<5=8�������Undo��� MainWindow���DAB>@8O� A� 2@JI0=8B5� =0704� >?5@0F88������� Undo History��� MainWindow���&5?@5:0@0=8� A2@J7:8�������Unrouted connections��� MainWindow���"1=>28� �%�1� G0AB�(8�)�������Update %1 part(s)��� MainWindow���F1=>28� 8=D>@<0F8OB0� ?@8� ?@5<8=020=5�������Update InfoView on hover��� MainWindow���T1=>28� A5;5:B8@0=8B5� G0AB8� A� =>28B5� 25@A88�������Update selected parts��� MainWindow���73;54� >B� 3>@5�������View from Above��� MainWindow���73;54� >B� 4>;C�������View from Below��� MainWindow��� >3;54=8� >B� 3>@5�������View from above��� MainWindow��� >3;54=8� >B� 4>;C�������View from below��� MainWindow���v>3;54=8� ?5G0B=0B0� ?;0B:0� 3;5409:8� >B� 4>;=8B5� A;>525� =03>@5�������+View the PCB from the bottom layers upwards��� MainWindow���d>3;54=8� ?5G0B=0B0� ?;0B:0� >B� 3>@=8B5� A;>525� =04>;C�������*View the PCB from the top layers downwards��� MainWindow���>30B>� ?@5:0@20H� ?8AB8B5� 02B><0B8G=>� =5� ?@5:JA209� B078� �,?8AB0�,?@>E>45=� >B2>@� 8;8� 46J<?5@�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow���)5� A5� =0;>68� 40� @5AB0@B8@0B5� �F�r�i�t�z�i�n�g� 70� 40� <>65B5� 40� 87?>;720B5� 2=5A5=8B5�(8<?>@B8@0=8B5�)� G0AB8�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 40� O� =0?@028B5� 5:A?>@B8@C5<0� :J<� �G�e�r�b�e�r� A8AB5<8�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow���0H0B0� AE5<0� 2A5� >I5� =O<0� ?;0B:0� �!� >;O� 4>1025B5� B0:020� 70� 40� ?@5<0E<5B5� 70?J;20=5B>� A� <54=0� ?8AB0�.�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 70� 40� 87?>;20B5� 70?J;20=5B>� A� 7075<O20=5� 8;8� A� <54=0� ?8AB0�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 70� 40� 87?>;20B5� 02B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!@>25@:0B0� 70� ?@028;0B0� ?@8� ?@>5:B8@0=5� �(�D�R�C�)� @01>B8� A0<>� :>30B>� B0:020� 5� =0;8G=0�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 40� O� =0?@028B5� 5:A?>@B8@C5<0� 70� 5F20=5�.�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 70� 40� 87?>;20B5� 70?J;20=5B>� A� <54=0� ?8AB0�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow���>1;868�������Zoom in��� MainWindow���B40;5G8�������Zoom out��� MainWindow���:0B>� !=8<:0�������as Image��� MainWindow���>;=0� AB@0=0�������bottom��� MainWindow���<54�������copper��� MainWindow���.70?J;20=5� A� <54=0� ?8AB0������� copperfill��� MainWindow���648@5:B=>� 70@5640=5� =0� G0AB8�������directly loading parts��� MainWindow���70� @>872>4AB2>�������for Production��� MainWindow���7075<O20=5�������ground��� MainWindow���8=G0�������in��� MainWindow���<>ABG5B0�������jumpers��� MainWindow���70@545=8� �%�1������� loading %1��� MainWindow���070@5640<� �%�1�(?@>B>?;0B:0�)�������loading %1 (breadboard)��� MainWindow���&70@5640<� �%�1� �(<>45;�)�������loading %1 (model)��� MainWindow���670@5640<� �%�1�(?5G0B=0� ?;0B:0�)�������loading %1 (pcb)��� MainWindow���$70@5640<� �%�1�(AE5<0�)�������loading %1 (schematic)��� MainWindow���<<�.�������mm��� MainWindow���=>20� AE5<0������� new sketch��� MainWindow���>D09;>28O� D>@<0B� � �.�f�z� 5� >AB0@O;� �������the .fz file format is obsolete��� MainWindow���hA;>68� D0;H82>� 87:;NG5=85� 70� 40� 2848B5� :0:2>� I5� AB0=5�������*throw a fake exception to see what happens��� MainWindow���6?>AB028� 87:;NG5=85� 2� B5:AB0�������throw test exception��� MainWindow���>@=0� AB@0=0�������top��� MainWindow���$3>@5=� 8� 4>;5=� A;>9�������top and bottom��� MainWindow���J=5� <>65� 40� A5� =0<5@8� 70<5=:0� 70� � �%�1�.� �������#unable to find replacement for %1. ��� MainWindow���?@>E>4=8� >B2>@8�������vias��� MainWindow���.AJA� �%�n� � ?@>E>4=8� >B2>@8������� with %n vias��� MazeRouter���\2B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8� 15� >B<5=5=>�.�������Autorouter was cancelled.��� MazeRouter���,?B8<878@0<� ?8AB8B5�.�.�.�������Optimizing traces...��� MazeRouter���p>43>B2O<� >?5@0F8OB0� ?>� 2@JI0=5� :J<� ?@548H=8B5� =0AB@>9:8�������Preparing undo...��� MazeRouter���^2B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8B5� ?@8:;NG5=>�!�������Routing complete!��� MazeRouter���2B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8� 4>AB83=0� <0:A8<C<� 70?J;20=5� >:>;>� �%�1�.�������!Routing reached maximum round %1.��� MazeRouter���R2B><0B8G=>B>� ?>4@5640=5� =0� ?8AB8� A?@O=>�!�������Routing stopped!��� MazeRouter���~5CA?5H=>� 02B><0B8G=>� ?>4@5640=5� =0� ?8AB8B5� �;� A?@O� ?@8� >?8B� �%�1�.�������+Routing unsuccessful; stopping at round %1.��� MazeRouter���5>G0:20=� :@09� ?@8� 87G5@B020=5B>� =0� �S�V�G� D09;�.� !2J@65B5� A5� A� �w�w�w�.�f�r�i�t�z�i�n�g�.�o�r�g�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���F7?>;7209� =09�-4>1@>B>� 70� <><5=B0�.�.�.�������Use best so far...��� MazeRouter���`=09�-4>1@>B>� 4>� <><5=B0� �:� �%�1� >B� � �%�2� A0� >?@>2>45=8�������best so far: %1 of %2 routed��� MazeRouter���>:>;>� �%�1� >B�:������� round %1 of:��� MazeRouter���5� CA?OE� 40� ?@570?8H0� D09;� �'�%�1�'�.� @8G8=0�:�%�2� � �(:>4� 70� 3@5H:0� � �%�3�)�������5Couldn't overwrite file '%1'. Reason: %2 (errcode %3)��� ModelBase���\?5@0F8OB0� ?>� AJE@0=O20=5� =0� D09;0� A5� ?@>20;8�!�������File save failed!��� ModelBase���R5� <>65� 40� 1J45� >B:@8B0� A;54=0B0� �%�n� � G0AB���V5� <>30B� 40� 1J40B� >B:@8B8� A;54=8B5� �%�n� G0AB8�������(Unable to find the following %n part(s):��� ModelBase��� 2J2�/=0�������at��� ModelBase���5B8:5B� =0� G8?0������� chip label��� MysteryPart��� 5B8:5B�������label��� MysteryPart���"5B8:5B� =0� <@560B0������� net label���NetLabel���:�[=0?8H5B5� 20H0B0� 15;56:0� BC:�]�������[write your note here]���Note����%�10?J;20=5� �:� >;O� 8715@5B5� ?;0B:0B0� =0� :>OB>� 8A:0B5� 40� ?@8;>68B5� 70?J;20=5�.�������;%1 Fill: please select the board you want to apply fill to.���PCBSketchWidget���P�1�0� �m�i�l�s� 5� 4>1J@� 871>@� ?>� ?>4@0718@0=5� � � �������#10 mils is a good default choice. ���PCBSketchWidget���.@><5=8� A;>O� =0� ?8AB0B0�������Change trace layer���PCBSketchWidget���~7G8AB8� 70@>48H8B5� �(A5<5=F0B0�)� 70� 70?J;20=5� A� 7075<O20I0� ?8AB0�.�������Clear ground fill seeds���PCBSketchWidget���b0B8A=8� B>78� :>=5:B>@� 70� 40� ?@>2;0G8H� =>20� ?8AB0�.�������-Click this connector to drag out a new trace.���PCBSketchWidget���54=0� ?8AB0�������Copper���PCBSketchWidget���0?J;20=5� A� <54=0� ?8AB0� �:� <>;O� 8715@5B5� A0<>� ?;0B:0B0� :>OB>� 8A:0B5� 40� 70?J;=8B5�������;Copper fill: please select only the board you want to fill.���PCBSketchWidget���L!J7409� ?8AB0� 87?>;7209:8� �"<8H0�"� 2@J7:0�������Create Trace from Ratsnest���PCBSketchWidget���$J2545B5� >BAB>O=85������� Enter Keepout���PCBSketchWidget���>0409B5� AB>9=>AB� =0� >BAB>O=85B>�������Enter keepout value:���PCBSketchWidget����F�r�i�z�t�i�n�g�������Fritzing���PCBSketchWidget���B2>B0� 70� ?@>8725640=5� =0� �F�r�i�t�z�i�n�g�������Fritzing Fab Quote���PCBSketchWidget���Z@5H:0� =5� <>65� 40� A5� 87G5@B05� ?;0B:0� �s�v�g� �(�1�)�.�������/Fritzing error: unable to render board svg (1).���PCBSketchWidget���d@5H:0� =5� <>65� 40� A5� 87G5@B05� A;>O� A� ?8AB8� �s�v�g� �(�1�)�������0Fritzing error: unable to render copper svg (1).���PCBSketchWidget���@5H:0� =5� <>65� 40� A5� 87G5@B05� 70?J;20=5B>� A� <54=0� ?8AB0� �s�v�g� �(�1�)�.�������0Fritzing error: unable to write copper fill (1).���PCBSketchWidget���@5H:0� =5� <>65� 40� A5� 87G5@B05� 70?J;20=5B>� A� <54=0� ?8AB0� �s�v�g� �(�2�)�.�������0Fritzing error: unable to write copper fill (2).���PCBSketchWidget���075<O20=5�������Ground���PCBSketchWidget���4!:@89� A8B>?5G0B0� =0� G0ABB0�������Hide part silkscreen���PCBSketchWidget���JBAB>O=85B>� 5� 2� �m�i�l�s� �(�.�0�0�1� �i�n�c�h�e�s�)�.� � �������#Keepout is in mils (.001 inches). ���PCBSketchWidget���<09B5� 2?@54284� �,G5� 70@048� A8=>=8<8:0B0� �,@07AB>O=8OB0� <>65� 40� A0� ?>� :JA8� A� 4>� � �2� �m�i�l�s� �������FNote that due to aliasing, distances may be too short by up to 2 mils ���PCBSketchWidget���>;O� 8715@5B5� ;0B:0� ?J@2>� �-�-� >?5@0F8OB0� ?>� A5;5:B8@0=5B>� @01>B8� A0<>� A� 54=0� ?;0B:0� =0� 254=J6�������YPlease click on a PCB first--this selection operation only works for one board at a time.���PCBSketchWidget���>;O� =07=0G5B5� 54=>� 8;8� ?>25G5� A5<5=0� 70� 70?J;20=5� A� 7075<O20=5� ?@548� 40� AB0@B8@0B5� 70?J;20=5� A� 7075<O20I0� ?8AB0� � �������LPlease designate one or more ground fill seeds before doing a ground fill. ���PCBSketchWidget���6>:068� A8B>?5G0B0� =0� G0ABB0�������Show part silkscreen���PCBSketchWidget�� !J65;O20<5�,� � �h�t�t�p�:�/�/�f�a�b�.�f�r�i�t�z�i�n�g�.�o�r�g� =5� >B3>20@O� =0� 20H5B>� 70?8B20=5� �.>;O� ?@>25@5B5� A8� 2@J7:0B0� A� 8=B5@=5B� 8� >?8B09B5� >B=>2>� A530� 8;8� ?>� :JA=>�.�������Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later.���PCBSketchWidget��>5� <>65B5� 40� :>=25@B8@0B5� B>78� ?@>E>45=� >B2>@� 2� B>G:0� =0� 45D>@<0F8O� 70� ?8AB0� �,70I>B>� 5� A2J@70=� :J<� G0AB� :>OB>� 5� A0<>� =0� 4>;=8O� A;>9� 8� B0:020� :>OB>� 5� =0� 3>@=8O�.�������Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer.���PCBSketchWidget���5� <>65� 40� A5� AJ74045� 70?J;20=5B>� A� <54=0� ?8AB0�-�-� =09�-25@>OB=>� G0ABB0� 5� 18;0� ?>AB025=0� 2J@EC� 4@C30� G0AB� 2<5AB>� 2J@EC� ?;0B:0B0�.�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget���5� <>65� 40� A5� AJ74045� 70?J;20=5B>� A� <54=0� ?8AB0�-�-� =09�-25@>OB=>� G0ABB0� =5� 5� 18;0� ?>AB025=0� 2J@EC� ?;0B:0B0�.�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget���0H0B0� AE5<0� 2A5� >I5� =O<0� ?;0B:0� �!� >;O� 4>1025B5� B0:020� 70� 40� 87?>;720B5� 70?J;20=5� A� <54=0� ?8AB0�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 70� 40� 87?>;20B5� B078� A5;5:B8@0I0� >?5@0F8O�.�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0� �!>;O� 4>1025B5� B0:020� 70� 40� <>65B5� 70� 40� 87?>;20B5� B078� A5;5:B8@0I0� >?5@0F8O�.�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget���0H0B0� AE5<0� >I5� A8� =O<0� ?;0B:0�.� 5� 18EB5� <>3;8� 40� O� ?@>872545B5� 157� 40� 8<0� 704045=0� ?;0B:0�.�������[Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.���PCBSketchWidget���70� B>20� <>65� 40� A5� =0;>68� 40� C25;8G8B5� AB>9=>ABB0� =0� >BAB>O=85B>� A� B>;:>20� � � �������=so you may want to increase the keepout value by that much. ���PCBSketchWidget���2>2J@E=>AB5=� <>=B06� �(�S�M�D�)�������SMD���PEConnectorsView���x"C:� <>65B5� 40� ?@><5=8B5� ?0@0<5B@8B5� =0� :>=5:B>@8B5� =0� G0ABB0�������:This is where you edit the connector metadata for the part���PEConnectorsView���@>E>45=� >B2>@������� Through-hole���PEConnectorsView���1@>9� :>=5:B>@8�:�������number of connectors:���PEConnectorsView���H� � 0� ?@>4J;60� =0?@54� 8� � 40� AJE@0=O� �?������� Go ahead and save?��� PEMainWindow���8�  540:B8@09�������&Edit��� PEMainWindow���8� 7=5A8�������&Export��� PEMainWindow��� 8� $09;�������&File��� PEMainWindow����<�b�r�/�>�<�b�r�/�>">20� =O<0� 40� 1J45� ?@>1;5<� 2� A;5420I>B>� 8740=85� =0�  540:B>@0� 70� G0AB8�������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowj5 <>65 40 A5 4C1;8@0 'family' A2>9AB2>B> =0 5;5<5=B0,A duplicate 'family' property is not allowed PEMainWindowfC1;8@0=5B> =0 'variant' A2>9AB2>B> =5 5 ?>72>;5=>-A duplicate 'variant' property is not allowed PEMainWindow&>1028 %1 :>=5:B>@8Add %1 connectors PEMainWindow>1028 :>=5:B>@ Add connector PEMainWindowL>1028 2J@B5H=8 2@J7:8 >B '%1' 4> '%2')Add internal connection from '%1' to '%2' PEMainWindow:5 5 ?>72>;5=> 157 AJ4J@60=85Blank not allowed PEMainWindow B<5=8Cancel PEMainWindow$@><5=8 %1 2J2 %2Change %1 to %2 PEMainWindow&@><5=8 %1 :J< '%2'Change %1 to '%2' PEMainWindow<@><5=8 2A8G:8 :>=5:B>@8 =0 %1Change all connectors to %1 PEMainWindow&@><5=8 :>=5:B>@ %1Change connector %1 PEMainWindow$@><5=8 >?8A0=85B>Change description PEMainWindow$@><5=8 A2>9AB20B0Change properties PEMainWindow@><5=8 5B8:5B0 Change tags PEMainWindow@><5=8 =0 %1 Change to %1 PEMainWindow<0B2>@8 157 70?0720=5 =0 D09;0Close without saving PEMainWindowJ0 70B2>@O ;8 157 70?0720=5 =0 D09;0?Close without saving? PEMainWindow>=5:B>@8 Connectors PEMainWindow 73;54 >=5:B>@8Connectors View PEMainWindow4@>1;5< ?@8 :>=25@B8@0=5B>Conversion problem PEMainWindow >?8@09 ?@>1;5<0 Copy problem PEMainWindow8EB5 ;8 8A:0;8 40 ?@>4J;68B5 40 @01>B8B5 8;8 40 70B2>@8B5 157 70?0720=5?4Do you want to keep working or close without saving? PEMainWindow8EB5 ;8 8A:0;8 40 70?078B5 ?@><5=8B5 :>8B> AB5 =0?@028;8 2 G0ABB0 "%1"?:Do you want to save the changes you made in the part "%1"? PEMainWindowdC1;8@0=5B> =0 'family' A2>9AB2>B> =5 5 ?>72>;5=>'Duplicate 'family' property not allowed PEMainWindowfC1;8@0=5B> =0 'variant' A2>9AB2>B> =5 5 ?>72>;5=>(Duplicate 'variant' property not allowed PEMainWindow"C1;8@0= ?@>1;5< Duplicate problem PEMainWindow!?>:>9=> <>65B5 40 87;575B5 >B >@5:B>@0 =0 G0AB8 A530 ,A0<> =5 701@02O9B5 40 4>2J@H8B5 7040G0B0 ?> :JA=>.^Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMainWindow8@54AB02:0 =0 8<5B> =0 D09;0Filename prefix PEMainWindow(@8DB>25Fonts PEMainWindowB 540:B>@ (>28) G0AB8 =0 FritzingFritzing (New) Parts Editor PEMainWindow B5:CI8O <><5=B Fritzing ?>44J@60 A0<> OCRA 8 Droid H@8DB>25 -- B5 1OE0 70<5=5=8 A H@8DB>25B5 2 '%1'kFritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' PEMainWindow :>=0Icon PEMainWindow"73;54 :0B> 8:>=8 Icon View PEMainWindow:> =0?@028B5 ?@><5=8 2 873;540 5:A?5@8<5=B0;=0 ?;0B:0 , 8;8 ?@><5=8B5 A2>9AB20B0 =0 A2@J7:8B5 =0 5;5<5=B0 B> :@0G5B0B0 <>65 40 =5 @01>BOB.cIf you make changes to breadboard view, or change connector metadata, the legs may no longer work.  PEMainWindow<$09;>25 A >1@07 8;8 >B?5G0BJ: (%1 %2 %3 %4 %5);;SVG $09;>25 (%1);;JPEG $09;>25 (%2);;PNG $09;>25 (%3);;gEDA B?5G0BJG5= $09; (%4);;Kicad >4C;=8 $09;>25 (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindow$09;>25 A 87>1@065=8O (%1 %2 %3);;SVG $09;>25 (%1);;JPEG $09;>25 (%2);;PNG $09;>25 (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindow=A?5:B>@ Inspector PEMainWindowHJB@5H=8B5 2@J7:8 A0 <=>3> >1J@:0=8.(Internal connections are very messed up. PEMainWindowD@>4J;60209 40 87?J;=O20H(@01>B8H) Keep working PEMainWindow !;>525Layers PEMainWindowF0@568 87>1@065=85B> 70 ?@53;5640=5Load image for view... PEMainWindowr0?@028 :>?85 =0 G0ABB0 8 3> 70?078 2 =01>@0 A >8 G0AB8'9Make a copy of the part and save it in the 'My Parts' Bin PEMainWindow:0?@028 A0<> 873;54 %1 2848<Make only %1 view visible PEMainWindow<0?@028 2848< A0<> B>78 873;54Make only this view visible PEMainWindow,=D>@<0F8O 70 5;5<5=B0Metadata PEMainWindow673;54 A2>9AB20 =0 5;5<5=B0 Metadata View PEMainWindow @5<5AB8 :;5<0B0Move terminal point PEMainWindow."@O120 40 1J45 C=8:0;=>Must be unique PEMainWindow|B2>@5B5 ?0?:0B0 =0 @01>B=8O ?;>B AJ4J@60I0 B5:CI8O svg D09;.@On the desktop, open the folder containing the current svg file. PEMainWindow$B2>@8 7>1@065=85 Open Image PEMainWindowzB2>@8 D09; :>9B> 40 1J45 87?>;720= 70 B>78 873;54 =0 G0ABB0.:Open a file to use as the image for this view of the part. PEMainWindowPNG 8 JPEG 87>1@065=8OB0 70?0720B A2>OB0 ?@8@>40 :0B> 18B<0? 87>1@065=85 8 =5 873;5640B 4>1@5 :>30B> 1J40B C3>;5<5=8--TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindow"K>@5:B>@ =0 G0AB8 Parts Editor PEMainWindow>;O 2J2545B5 ?@54AB02:0 70 40 <>65B5 ?> ;5A=> 40 845=B8D8F8@0B5 D09;>25B5 A G0AB8B5. <5=0B0 I5 1J40B 2 A;54=8O 284 ' !"_%1'(=5 5 =C6=> 40 ?@><5=OB5 ?@54AB02:0B0 ,70I>B> C=8:0;=0 =0AB02:0 A5 ?>AB02O 28=038 02B><0B8G=>.)Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) PEMainWindow>;O ?@570?8H5B5 SVG D09;0 87?>;7209:8 B578 =0AB@>9:8 8 A5 >?8B09B5 40 3> 70@548B5 >B=>2>.HPlease re-export the SVG file using that setting, and try loading again. PEMainWindow(@5<5AB8 :>=5:B>@ %1Relocate connector %1 PEMainWindow,@5<0E=8 %1 :>=5:B>@8Remove %1 connectors PEMainWindow0@5<0E=8 2JB@5H=0 2@J7:0Remove Internal Connection PEMainWindow"@5<0E=8 :>=5:B>@Remove connector PEMainWindowD@5<0E=8 2J@B5H=0B0 2@J7:0 >B '%1'$Remove internal connection from '%1' PEMainWindowR7?>;7209 >B=>2> :0@B8=0B0 ?5G0B=0 ?;0B:0Reuse PCB image PEMainWindowP7?>;7209B5 >B=>2=> breadboard :0@B8=0B0Reuse breadboard image PEMainWindowN7?>;7209B5 >B=>2> AE5<0B8G=0B0 :0@B8=0Reuse schematic image PEMainWindown7?>;7209 >B=>2> :0@B8=0B0 ?5G0B=0 ?;0B:0 2 B>78 873;54 Reuse the PCB image in this view PEMainWindowp7?>;7209B5 >B=>2=> breadboard :0@B8=0B0 2J2 B>78 873;54'Reuse the breadboard image in this view PEMainWindowj7?>;7209B5 >B=>2> AE5<0B8G=0B0 :0@B8=0 2 B>78 873;54&Reuse the schematic image in this view PEMainWindow@>1;5< A SVG SVG problem PEMainWindow!JE@0=8Save PEMainWindow!JE@0=8 "%1" Save "%1" PEMainWindow*0?078 :0B> =>20 G0ABSave as new part PEMainWindow!JE@0=O20=B> =0 ?@><5=8B5 ?> B078 G0AB I5 =0?@028 ?@><5=8 ?> AE5<0B0 :>8B> =5 <>30B 40 1J40B 2J@=0B8 >1@0B=>.HSaving this part will make a change to the sketch that cannot be undone. PEMainWindow!JE@0=O20=B> =0 ?@><5=8B5 ?> B078 G0AB I5 =0?@028 ?@><5=8 ?> B578 AE5<8 :>8B> =5 <>30B 40 1J40B 2J@=0B8 >1@0B=>.LSaving this part will make a change to these sketches that cannot be undone. PEMainWindow86B5 2 <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">B>20 >1OA=5=85 </a>.ySee this explanation. PEMainWindow$>:068 >=5:B>@8B5Show Connectors PEMainWindow>:068 8:>=0B0 Show Icon PEMainWindowV>:068 >?8A0=85B> =0 ?>:070B5;8B5 =0 G0ABB0 Show Metadata PEMainWindow>:068 2 ?0?:0Show in Folder PEMainWindowx>:068 >?8A0=85B> =0 :>=5:B>@8B5 =0 G0ABB0 2 A?8AJG5= 873;54*Show the connector metadata in a list view PEMainWindow">:068 :0B> 8:>=8Show the icon view PEMainWindow:>:068 873;540 AJA A2>9AB20B0Show the metadata view PEMainWindowH@54C?@565=85 ?@8 ?@><O=0 =0 G5@B560Sketch Change Warning PEMainWindow0 B>20 @540:B8@0=5B> <>65 40 4>2545 4> =520;845=0 :0@B8=0 ?@8 873;54 ?5G0B=0 ?;0B:00So editing may produce an invalid PCB view image PEMainWindow!2>9AB2>B> 'family'(D0<8;8O) =0 5;5<5=B0 =5 <>65 40 1J45 ?@07=>.'The 'family' property can not be blank. PEMainWindow73;5640 G5 SVG D09;0 5 18; 87=5A5= >B CorelDraw 157 40 1J40B =03;0A5=8 "presentation attributes" =0AB@>9:8B5nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindownB2>@5=0B0 AE5<0 '%1' 87?>;720 G0ABB0 :>OB> ?@><5=OB5. 4The open sketch '%1' uses the part you are editing.  PEMainWindow B2>@5=8B5 AE5<8The open sketches  PEMainWindow|'0ABB0 I5 1J45 2848<0 A0<> 2 B>78 873;54 8 2 873;54 :0B> 8:>=08The part will only be visible in this view and icon view PEMainWindowT!B>9=>ABB0 =0 '%1' =5 <>65 40 1J45 ?@07=0.#The value of '%1' can not be blank. PEMainWindowXO<0 A;>525 A <54=0 ?8AB0 45D8=8@0=8 2 %1. +There are no copper layers defined in: %1.  PEMainWindow`<0 54=0 ?>A;54=0 :>@5:F8O 2A5 >I5 =0 87G0:20=5.%There is one last edit still pending. PEMainWindowX'0ABB0 =5 <>65 40 1J45 70?075=0 :0:20B> 5: #This part can not be saved as-is:  PEMainWindowP"078 G0AB8 8<0 %n =5=07=0G5=8 :>=5:B>@0.'This part has %n unassigned connectors  PEMainWindow@"078 G0AB8 8<0 >3J205<8 :@0G5B0.This part has bendable legs.  PEMainWindowl"078 25@A8O =0 @540:B>@0 =0 G0AB8 2A5 >I5 =5 ?>44J@60 @540:B8@0=5 =0 >3J205<8 :@0G5B0 , 70@048 :>5B> :@0G5B0B0 <>65 40 =5 1J40B 87>1@075=85 :>@5:B=> 2 873;540 5:A?5@8<5=B0;=0 ?;0B:0.This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindow"078 25@A8O =0  540:B>@0 70 =>28 G0AB8 =5 18 <>3J; 40 A5 A?@028 A >B45;=8 ( <545=) copper0 8 (<545=) copper1 layers in '%1'. dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindow">20 ?@54C?@5645=85 =O<0 40 1J45 ?>2B0@O=> 2 B078 A5A8O =0 Fritzing=This warning will not be repeated in this session of Fritzing PEMainWindow5 <>65 40 1J45 AJ74045= =>2 :>=5:B>@--<>65 40 A5 =0;>68 40 70?>G=5B5 =0=>2>.;Unable to create new connector--you may have to start over. PEMainWindow85 <>65 40 1J45 70@545= '%1'Unable to load '%1' PEMainWindow5 <>65 40 1J45 70@545=> '%1'.>;O 70B2>@5B5 @540:B>@0 =0 G0AB8 157 40 AJE@0=O20B5 8 >?8B09B5 >B=>2>.PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindow>5 <>65 40 A5 70@548 fzp >B %1Unable to load fzp from %1 PEMainWindowX5 <>65 40 A5 70@548 D09; A 87>1@065=85 '%1'Unable to load image file '%1' PEMainWindowl5 <>65 40 A5 70@548 D09;0 A 87>1@065=85 >B %1: %2 $Unable to load image file '%1': %2 PEMainWindowZ5 <>65 40 A5 AJ74045 ;>:0;=> :>?85 =0 : '%1'$Unable to make a local copy of: '%1' PEMainWindow45 <>65 40 A5 0=0;878@0 %1Unable to parse '%1' PEMainWindowd5 <>65 40 A5 >1@01>B8 '%1': %2 @54 :%3 :>;>=0:%4*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindowH5 <>65 40 A5 0=0;878@0 fzp D09;0 %1Unable to parse fzp file %1 PEMainWindowL5 5 2J7<>6=> 40 A5 70?8H5 svg 2J2 %1Unable to write svg to %1 PEMainWindow>:0B> 2A8G:8 2@J7:8 =5 A0 =07=0G5=8 :J< svg 5;5<5=B8 , G0ABB0 =O<0 40 @01>B8 :>@5:B=>. UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindowT#?>B@510B0 =0 PNG 8 JPG 5 =5?@5?>@JG8B5;=0Use of PNG and JPG discouraged PEMainWindow0@80=B '%1' 25G5 A5 87?>;720. <5B> =0 20@80=B0 B@O120 40 1J45 C=8:0;=>.8Variant '%1' is in use. The variant name must be unique. PEMainWindow57>?0A=> 18EB5 <>3;8 40 ?@028B5 ?@><5=8 2 !E5<0B8G=8O 8;8 873;540 5G0B=0 ?;0B:0. 7You can safely make changes to Schematic or PCB view.  PEMainWindow>65 40 87?>;720B5 PNG 8;8 JPEG 87>1@065=85 70 40 AJ74045B5 A2>OB0 G0AB ,=> 5 ?> 4>1@5 40 87?>;720B5 SVG D09;.WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindowh0H8B5 ?@><5=8 I5 1J40B 703C15=8 0:> =5 38 70?078B5.1Your changes will be lost if you don't save them. PEMainWindow"?@57 %n 873;540. across %n views.  PEMainWindow8 '%1'  and '%1'  PEMainWindow,=> 70 A530 <>;O <>45D8F8@09B5 D09;0 A?>@54 8=AB@C:F88B5 2 ;8=:0.Mbut for now please modify the file according to the instructions in the link. PEMainWindowT=5 A0 =0<5@5=8 >B?5G0BJG=8 >G5@B0=8O 2 %1no footprints found in %1 PEMainWindow2=5 A0 =0<5@5=8 AE5<8 2 %1no schematics found in %1 PEMainWindowAE5<0B8G=0 G0ABschematic part PEMainWindow70 B>20 70 Fritzing G0AB8 5 ?> - 4>1@5 40 87?>;720B5 PNG 8 JPG A0<> :0B> <5AB>?>:070B5;8.Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindow =58<5=C20=0 G0AB untitled part PEMainWindow 2B>@AuthorPEMetadataView0B0DatePEMetadataView?8A0=85 DescriptionPEMetadataView!5<59AB2>FamilyPEMetadataView B8:5BLabelPEMetadataView!2>9AB20 PropertiesPEMetadataView0409B5 ?@54AB02:0 :>OB> 40 A5 ?>AB02O 28=038 ?@54 5B8:5B0 =0 G0ABB0.!Set the default part label prefixPEMetadataView.0409B5 02B>@ =0 G0ABB0Set the part's authorPEMetadataView,0409B5 40B0 =0 G0ABB0Set the part's datePEMetadataView0409B5 >?8A0=85 70 G0ABB0 -- >65 40 87?>;720B5 >18:=>25= html (:0:B> 5 45D8=8@0= 2 Qt's Rich Text)RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataView0409B5 'D0<8;8O' =0 G0ABB0 -- A :>8 4@C38 G0AB8 5 ?>4>1=0 8;8 5 2 ?@O:0 2@J7:0?Set the part's family--what other parts is this part related toPEMetadataView80409B5 A2>9AB20B0 =0 G0ABB0Set the part's propertiesPEMetadataView40409B5 5B8:5BG5 =0 G0ABB0Set the part's tagsPEMetadataView*0409B5 8<5 =0 G0ABB0Set the part's titlePEMetadataView0409B5 8=B5@=5B 04@5A0 (url) =0 G0ABB0 0:> 5 45D8=8@0=0 2 8=B5@=5B AB@0=8F03Set the part's url if it is described on a web pagePEMetadataView0409B5 20@80=B0 =0 G0ABB0 -- B>20 O ?@028 C=8:0;=0 A?@O<> 4@C38B5 G0AB8 2 AJI0B0 D0<8;8OTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewB8:5BG5TagsPEMetadataViewt"C: A5 ?@><5=O 8=D>@<0F8OB0 70 =0AB@>9:8B5 =0 5;5<5=B0...4This is where you edit the metadata for the part ...PEMetadataView<5TitlePEMetadataView0@80=BVariantPEMetadataView28A>G8=0:height: PESvgViewH8@>G8=0:width: PESvgViewZ<font color='black'>;0G5=5B> 2:;NG5=></font>+Dragging enabled PEToolView\<font color='black'>;0G5=5B> 87:;NG5=></font>+Dragging disabled PEToolView &5=BJ@Center PEToolView>=5:B>@ %1 Connector %1 PEToolView!?8AJ: =0 :>=5:B>@8B5 (>B<5B:0B0 >7=0G020 ,G5 3@0D8:0B0 5 A5;5:B8@0=0);Connector List (a checkmark means the graphic was selected) PEToolViewh>=B@>;8 70 704020=5 B5@<8=0;=0B0 B>G:0 =0 :>=5:B>@. "5@<8=0;=0 B>G:0 5 <OAB>B> =0 :>5B> 68F0(?@>2>4=8:0) A5 A2J@720 A :>=5:B>@0. !JI> <>65B5 40 2;0G8B5 <5@=8:0 =0 B5:CI8O :>=5:B>@Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector PEToolView&;0G5=5B> 87:;NG5=>Dragging disabled PEToolViewE PEToolView^>45D8F8@0 E :>>@48=0B0B0 =0 B5@<8=0;=0B0 B>G:0/Modifies the x-coordinate of the terminal point PEToolView^>45D8F8@0 y :>>@48=0B0B0 =0 B5@<8=0;=0B0 B>G:0/Modifies the y-coordinate of the terminal point PEToolView!N PEToolView.S PEToolView715@8 3@0D8:0Select graphic PEToolView*0409 JB@5H=8 2@J7:8Set Internal Connections PEToolViewB15;565B5 B078 :CB89:0 70 40 ?@><5=OB5 2J@B5H=8B5 2@J7:8 G5@B059:8 68F8?Set this checkbox to edit internal connections by drawing wires PEToolView\03;0AO B5@<8=0;=0B0 B>G:0 =0 :>=5:B>@0 =0 %1.*Sets the connector's terminal point to %1. PEToolViewf7?>;7209 <5AB>?>;>65=85B> =0 :C@A>@0 8 :>;5;F5B> =0 <8H:0B0 70 40 =02838@0H SVG 5;5<5=B0 ,:>9B> 8A:0B5 40 =07=0G8B5 =0 B5:CI8O :>=5:B>@, B>3020 =04>;C A <8H:0B0 70 40 A5;5:B8@0B5Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. PEToolViewW PEToolView F5=BJ@center PEToolView 87B>:east PEToolViewN3north PEToolViewN3south PEToolView 70?04west PEToolView F5=BJ@centerPadA2J@68 :J< connect toPad 87B>:eastPad A525@northPad D>@<0shapePadN3southPad 70?04westPad<@><5=8 5B8:5B8B5 =0 :@0G5B0B0Edit Pin Labels PaletteItem$80<5BJ@ =0 >B2>@0 Hole Diameter PaletteItem^ 07<8=020=5 2 5B8:5B8B5. 8I> =5 15 AJE@0=5=>.#Label mismatch. Nothing was saved. PaletteItem*515;8=0 =0 @JAB5=0 Ring Thickness PaletteItem5 <>30 40 ?@>4J;60; :>=5:B>@8B5 =0 G0AB8B5 =O<0B AB0=40@B=8 845=B8D8:0B>@8 (ID-B0).;Unable to proceed; part connectors do no have standard IDs. PaletteItemr5 <>30 40 ?@>4J;60; =5 5 5 =0<5@5= 873;54 2 3>@=8O A;>9.1Unable to proceed; unable to find top level view. PaletteItem,4>?J;=8B5;=8 =0AB@>9:8advanced settings PaletteItem"@07<5@ =0 4C?:0B0 hole size PaletteItem8=Gin PaletteItem<<mm PaletteItem$>:068 AB>9=>AB8B5Display Values PartLabel0>:068 B5:AB0 =0 5B8:5B0Display the text of the label PartLabelD>:068 AB>9=>ABB0 =0 A2>9AB2>B> %1 Display the value of property %1 PartLabel@><5=8Edit PartLabel2@><5=8 B5:AB0 =0 5B8:5B0Edit label text PartLabel&1J@=8 E>@87>=B0;=>Flip Horizontal PartLabel"1J@=8 25@B8:0;=> Flip Vertical PartLabel61J@=8 5B8:5B0 E>@87>=B0;=>Flip label horizontally PartLabel21J@=8 5B8:5B0 25@B8:0;=>Flip label vertically PartLabel1J@=8/02J@B8 Flip/Rotate PartLabel  07<5@ =0 H@8DB0 Font Size PartLabel !:@89Hide PartLabel0!:@889 5B8:5B0 =0 G0ABB0Hide part label PartLabel "5:AB =0 5B8:5B0 Label text PartLabel$"5:AB =0 5B8:5B0 : Label text: PartLabel >;O<Large PartLabel !@545=Medium PartLabel02J@B8 =0 135 3@04CA0 ?> ?>A>:0 =0 G0A>2=8:>20B0 AB@5;:0 {135?}Rotate 135� Clockwise PartLabel|02J@B8 =0 45 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:0 {135?}Rotate 135� Counter Clockwise PartLabel.02J@B8 =0 180 {180?} Rotate 180� PartLabel02J@B8 =0 135 3@04CA0 ?> ?>A>:0 =0 G0A>2=8:>20B0 AB@5;:0 {45?}Rotate 45� Clockwise PartLabelz02J@B8 =0 45 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:0 {45?}Rotate 45� Counter Clockwise PartLabel02J@B8 =0 135 3@04CA0 ?> ?>A>:0 =0 G0A>2=8:>20B0 AB@5;:0 {90?}Rotate 90� Clockwise PartLabelz02J@B8 =0 45 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:0 {90?}Rotate 90� Counter Clockwise PartLabel02J@B8 871@0=8B5 G0AB8 =0 90 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:05Rotate current selection 90 degrees counter clockwise PartLabeln02J@B8 =04?8A0 =0 135 3@04CA0 ?> G0A>2=8:>20B0 AB@5;:0)Rotate the label by 135 degrees clockwise PartLabel~02J@B8 =04?8A0 =0 135 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:01Rotate the label by 135 degrees counter clockwise PartLabel<02J@B8 =04?8A0 =0 180 3@04CA0Rotate the label by 180 degrees PartLabell02J@B8 =04?8A0 =0 45 3@04CA0 ?> G0A>2=8:>20B0 AB@5;:0(Rotate the label by 45 degrees clockwise PartLabel|02J@B8 =04?8A0 =0 45 3@04CA0 >1@0B=> =0 G0A>2=8:>20B0 AB@5;:00Rotate the label by 45 degrees counter clockwise PartLabell02J@B8 =04?8A0 =0 90 3@04CA0 ?> G0A>2=8:>20B0 AB@5;:0(Rotate the label by 90 degrees clockwise PartLabel@0409 @07<5@0 =0 H@8DB0 =0 3>;O<Set font size to large PartLabelB0409 @07<5@0 =0 H@8DB0 =0 A@545=Set font size to medium PartLabel@0409 @07<5@0 =0 H@8DB0 =0 <0;J:Set font size to small PartLabelB0409 @07<5@0 =0 H@8DB0 =0 4@515=Set font size to tiny PartLabel(0409 5B8:5B 70 %1Set label for %1 PartLabel 0;J:Small PartLabel @515=Tiny PartLabel0>1028 :J< =870 >B G0AB8 Add to binPartsBinPaletteWidget B<5=8CancelPartsBinPaletteWidgetD5 <>65 40 1J45 =0<5@5= D09;0 %1.Cannot find file %1.PartsBinPaletteWidgetF5 <>65 40 A5 ?@>G5B5 D09;0 %1: %2.Cannot read file %1: %2.PartsBinPaletteWidget2!<5=O F25B0 =0 8:>=0B0...Change icon color...PartsBinPaletteWidgetf!<5=8 F25B0 =0 8:>=0B0 70 B>78 =01>@ >B G0AB8 (Bin)*Change the color of the icon for this bin.PartsBinPaletteWidget08AB8=0 ;8 18EB5 8A:0;8 40 4>1028B5 B5:CI0B0 G0AB :J< B>78 =01>@(bin)?7Do you really want to add the selected part to the bin?PartsBinPaletteWidget8EB5 ;8 8A:0;8 40 70?078B5 ?@><5=8B5 :>8B> AB5 =0?@028;8 2 18=0@=8O D09; "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidget5 70?07209 Don't SavePartsBinPaletteWidgetFriztingFritzingPartsBinPaletteWidget.Fritzing bin D09; (*%1)Fritzing Bin (*%1)PartsBinPaletteWidget0@5640<... Loading...PartsBinPaletteWidget 0?8H8SavePartsBinPaletteWidget00?078 18=0@5= D09; "%1" Save bin "%1"PartsBinPaletteWidget2715@8 F2OB 70 B078 8:>=0Select a color for this iconPartsBinPaletteWidget$0409 8<5 =0 D09;0Specify a file namePartsBinPaletteWidget"5>703;025= 01>@ Untitled BinPartsBinPaletteWidgeth0H8B5 ?@><5=8 I5 1J40B 703C15=8 0:> =5 38 70?078B5.1Your changes will be lost if you don't save them.PartsBinPaletteWidget40@5640< 18=0@5= D09; '%1'loading bin '%1'PartsBinPaletteWidget B<5=8Cancel PerfboardN@54C?@5645=85 >B=>A=> E0@0:B5@8AB8:8B5Performance Warning Perfboard7?J;=5=85B> =0 5:A?5@8<5=B0;=8 ?;0B:8 A ?>25G5 >B ?@81;878B5;=> 2000 4C?:8 <>65 40 1J45 102=>. !83C@=8 ;8 AB5? 015;56:0 : B>20 AJ>1I5=85 =O<0 40 1J45 ?>2B0@O=> ?>25G5 ?@57 B5:CI0B0 ?>B@518B5;A:0 A5A8O.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard 0409 =>2 @07<5@ Set new size Perfboard :>;>=8columns Perfboard @54>25rows Perfboard28715@8 @07<5@ =0 ?;0B:0B0set board size Perfboard @07<5@size Perfboard^<p><h2> 540:B>@ =0 8<5=0B0 =0 ?8=>25B5</h2></p>

    Pin Label Editor

    PinLabelDialogl<p>0B8A=5B5 =0 5B8:5B0 4> ?8=0 70 40 3> ?@58<5=C20B5.<

    Click on a label next to a pin number to rename that pin.PinLabelDialog B<5=8CancelPinLabelDialog0J@=8 >1@0B=> >B<5=5=>B>RedoPinLabelDialog 0?078SavePinLabelDialog B<5=8UndoPinLabelDialog>65B5 40 87?>;720B5 tab 70 40 A5 42868B5 ?> 5B8:5B8B5 ?>A;54>20B5;=></p>@You can use the tab key to move through the labels in order.

    PinLabelDialog<%1 (=0B8A=8 70 40 ?@><5=8H...)%1 (click to change...) PrefsDialog2B>AJE@0=O20=5Autosave PrefsDialog02B>AJE@0=O209 =0 2A5:8:Autosave every: PrefsDialog B<5=8Cancel PrefsDialogV@><5=8 ?>2545=85B> =0 :>;5;F5B> =0 <8H:0B0Change Wheel Behavior PrefsDialog&7G8AB8 =0AB@>9:8B5Clear Settings PrefsDialog&25B>25Colors PrefsDialog*!2J@70=0 2@JE=0 B>G:0Connected Highlight PrefsDialog6@82>;8G5I8 8;8 ?@028 ;8=88Curvy vs. straight wires PrefsDialog4@82>;8G5I8 68F8 8 :@0G5B0Curvy wires and legs PrefsDialog1I8General PrefsDialog78:Language PrefsDialogB>2545=85 =0 :>;5;F5B> =0 <8H:0B0Mouse Wheel Behavior PrefsDialogOK PrefsDialogN715@5B5 87?J;=8< (?@>3@0<8@C5< ) 70 %1'Select a programmer (executable) for %1 PrefsDialog>"078 :CB889:0 704020 ?>2545=85B> ?> ?>4@0718@0=5. 8EB5 <>3;8 40 ?@52:;NG8B5 >1@0B=> :J< 4@C3>B> ?>2545=85 704J@609:8 Control (Command ?@8 Mac )4>:0B> 2;0G8B5.This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialog05A2J@L70=0 2@JE=0 B>G:0Unconnected Highlight PrefsDialog>30B> =0B8A=5B5 A <8H:0B0 8 2;0G8B5 68F0 8;8 :@0G5 =0 G0AB (:J< :>=5:B>@ 8;8 B>G:0 =0 45D>@<0F8O) 18EB5 ;8 8A:0;8 40 ?@><5=OB5 :@828=0B0 =0 B078 68F0 (8;8 :@0G5) 8;8 18EB5 8A:0;8 40 A5 ?>O28 =>20 B>G:0 =0 45D>@<0F8O?When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialog <8=CB8minutes PrefsDialog0:> =O<0 =0B8A=0B8 :>?G5B0 = scroll shift @07<5=O >AB0 70 scroll Alt 8;8 %1 = 4>1;868Fno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialog0:> =O<0 =0B8A=0B8 :>?G5B0 = zoom Alt 8;8 %1 = scroll shift @07<5=O >AB0 70 scrollFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialog~!83C@=8 ;8 AB5 ,G5 18EB5 8A:0;8 40 ?@5<0E=5B5 "%1" >B AE5<0B0 ?5Are you sure you want to remove "%1" from the sketch? ProgramTab ;0B:0Board ProgramTab>4 (*.%1) Code (*.%1) ProgramTabbFritzing =5 CA?O 40 =0<5@8 '%1', <>;O ?>A>G5B5 3>1Fritzing is unable to find '%1', please locate it ProgramTab>2New ProgramTab@5<0E=8 "%1"? Remove "%1"? ProgramTab 0?078Save ProgramTabX715@8 D09; A ?@>3@0<0 :>9B> 40 1J45 70@545=Select a program file to load ProgramTabfJ?@5:8 G5 5 2J7<>6=> 40 G5B5B5 8 ?@><5=OB5 %1 D09;>25B5 A ?@>3@0<8B5 =0 :>=B@>;5@8B5 ,:J< <><5=B0 =5 <>65B5 40 87?>;720B5 Fritzing 70 40 38 :><?8;8@0B5 8;8 70?8H5B5 2 :>=B@>;5@0.While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. ProgramTab 8 >40&Code ProgramWindow8 >?8@09&Copy ProgramWindow8 7@568&Cut ProgramWindow8  540:B8@09&Edit ProgramWindow8 >AB028&Paste ProgramWindow0AB@>9:8&Preferences... ProgramWindow&8 !5;5:B8@09 2A8G:> &Select All ProgramWindow8 @53;5409&View ProgramWindow ;0B:0Board ProgramWindow@>7>@5F A :>40 Code Window ProgramWindow&@>7>@5F A :>40 %1Code Window - %1 ProgramWindow,>?8@0=5 =0 A5;5:F8OB0Copy selection ProgramWindow"B@568 A5;5:F8OB0 Cut selection ProgramWindow$09;JB '%1' 15 2J7AB0=>25= >B .fzz D09;0; AJE@0=5B5 ;>:0;=> :>?85 70 40 @01>B8B5 A 2J=H=0 @540:F8>==0 ?@>3@0<0.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindow$09;JB '%1' 15 2J7AB0=>25= >B .fzz D09;0; ;>:0;=>B> :>?85 =5 <>65 40 1J45 =0<5@5=>.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindowB>AB028 AJ4J@60=85B> =0 ;8?1>@40Paste clipboard contents ProgramWindow0J@=8 >1@0B=> >B<5=5=>B>Redo ProgramWindow,!5;5:B8@09 F5;8O B5:ABSelect all text ProgramWindow`>:068 B5:AB>20B0 :CB8O ">B=>A=>" =0 0?;8:0F8OB0 Show the application's about box ProgramWindow B<5=8Undo ProgramWindow%1 !;>9%1 LayerQObjectX%15:A?>@B0 >B B>78 A;>9 5 ?@075=.(A;CG09 2)."%1 layer export is empty (case 2).QObjectB%15:A?>@B0 >B B>78 A;>9 5 ?@075=.%1 layer export is empty.QObjectT%1 A;>9 : =5 <>65 40 1J45 70?075= 2J2 '%2' %1 layer: unable to save to '%2'QObjectR%1 3@5H:0 ?@8 5:A?>@B8@0=5 =0 <0A:0B0 (2)%1 mask export failure (2)QObjectt%1 68F8 A0 ?@5<5AB5=8 >B BOE=0B0 AJE@0=5=0 ?>78F8O 2J2 %2./%1 wires moved from their saved position in %2.QObject <b>?8A0=85:</b>Description:QObject<b><5:</b> Name:QObject<b>B8?:</b> type:QObjectJ0AB@>9:8 =0 02B><0B8G=>B> ?>4@5640=5Autorouter SettingsQObjectA=>25=BasicQObject ;0B:0BoardQObject:A?5@8<5=B0;=0 BreadboardQObject:73;54 5:A?5@8<5=B0;=0 ?;0B:0Breadboard ViewQObject7:0@09 =0?@54 Bring forwardQObject(7:0@09 =09 - >B?@54Bring to frontQObject5 <>65 40 ?>4@548 02B><0B8G=> ?8AB8B5 : =O<0 =0<5@5=0 ?;0B:0 (8;8 ?;0B:8) 5Cannot autoroute: no board (or multiple boards) foundQObjectB5 <>30 40 ?@>G5B0 D09;JB %1: %2.Cannot read file %1: %2.QObjectZ5 <>65 40 A5 70?8H5 2@5<5==8O D09; %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject0@><5=8 :@0G5B> =0 %1,%2Change leg of %1,%2QObject*@>25@8 70 >1=>2;5=8OCheck for updatesQObject&7G8AB8 =0AB@>9:8B5Clear SettingsQObject7B@89 2A8G:8 70?075=8 =0AB@>9:8 8 70B2>@8 ?@>7>@5F0 <><5=B0;=>.;Clear all saved settings and close this dialog immediately.QObject0!2J@70= ?>4G5@B020I F2OBConnected highlight colorQObject @J7:0 ConnectionQObjectt>=25@B8@09 ?@>E>4=8O >B2>@ 2 B>G:0 =0 45D>@<0F8O(>3J20=5)Convert Via to BendpointQObject8>=25@B8@09 2 ?@>E>45= >B2>@Convert to ViaQObject >;5= <545= A;>9 Copper BottomQObject,>;5= A;>9 <54=0 ?8AB0Copper Bottom TraceQObjectL0?J;20=5 A <54=0 ?8AB0 =0 4>;=8O A;>9Copper Fill BottomQObjectL0?J;20=5 A <54=0 ?8AB0 =0 3>@=8O A;>9Copper Fill TopQObject>@5= A;>9 <54 Copper TopQObject,>@5= A;>9 <54=0 ?8AB0Copper Top TraceQObject$>?8@0 A5 D09; %1Copying file %1QObject  540:B8@09 ;8=:0 Edit linkQObjectH@5H:0 ?@8 G5B5=5B> =0 D09;0 %1: %2.Error reading file %1: %2.QObject`$09; %125G5 AJI5AB2C20 : =O<0 40 1J45 ?@570?8A0=/File %1 already exists: it won't be overwrittenQObject&@>3@5A =0 D09;0...File Progress...QObject 04J@FrameQObjectFriztingFritzingQObjectTFritzing =5 <>65 40 70@548 =01>@0 >B G0AB8"Fritzing cannot load the parts binQObjectFritzing =5 <>65 40 >1@01>B8 >G5@B0=8OB0 70 87@O720=5 2 B078 ?>B@518B5;A:8 704045=0 D>@<0 =0 ?;0B:0B0. DFritzing is unable to process the cutouts in this custom PCB shape. QObject6Fritzing 878A:20 40 AJ74020B5 >G5@B0=8OB0 70 87@O720=5 87?>;7209:8 shape 'substraction' 8;8 'difference' >?5@0F8O 2 20H8O @540:B>@ =0 25:B>@=8 87>1@065=8O.}Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.QObjectZ 540:B>@ =0 A5<5=0B0 A 70?J;20=5 A 7075<O20=5Ground Fill Seed EditorQObject '8?>25ICsQObject :>=0IconQObject73;54 :>=8 Icon ViewQObjectE>4InputQObjectJB@5H=8 2@J7:8Internal ConnectionsQObject:@8AJ548=8 8F0B0(?@>2>4=8:0) Join WireQObject8:@>:>=B@>;5@MicrocontrollerQObjectrO<0 2@J7:8 (=0 ?5G0B=0B0 ?;0B:0 ) :>8B> 40 A5 ?>4@5640B.%No connections (on the PCB) to route.QObject@O<0 2@J7:8 :>8B> 40 A5 ?>4@54OBNo connections to route.QObject*5 A0 =0<5@5=8 G0AB8 No parts found.QObject5;56:8NotesQObject ?00!Oops!QObject @C38OtherQObject 7E>4OutputQObject*73;54 5G0B=0 ?;0B:0PCB ViewQObject>4;>6:0PadQObjectt@5H:0 ?@8 87G5@B020=5B> (1) ?@8 @54 %1, :>;>=0 %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObjectp@5H:0 ?@8 87G5@B020=5B> (2) =0 @54 %1, :>;>=0 %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObject'0ABPartQObject'0AB %1 '%2' Part %1 '%2'QObject$0@B8=:0 =0 G0ABB0 Part ImageQObject$B8:5B8 =0 G0AB8B5 Part LabelsQObject,'0ABB0 5 25G5 2 =01>@0Part already in binQObject '0AB8PartsQObject60?:0 A G0AB8 =5 5 =0<5@5=0Parts folder not found.QObjectB 540:B>@ =0 5B8:5B8B5 =0 ?8=>25B5Pin Label EditorQObject>;O 8<09B5 2?@54284 ,G5 =>20 =0AB@>9:0 70 578:0 =O<0 40 2;575 2 A8;0 4> A;5420I> AB0@B8@0=5 =0 Fritzing.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObject0E@0=20=5PowerQObject0AB@>9:8 PreferencesQObject8H8 68F8RatsnestQObject8H8 68F8Ratsnest wiresQObject 8=88RulersQObject"!E5<0B8G5= 873;54Schematic ViewQObject715@8 %1 Select %1QObject 715@8 2A8G:8 %1 Select all %1QObject\715@8 2A8G:8 ?8AB8 >B B8?0 "5 02B>?>4@56409"#Select all 'Don't autoroute' tracesQObjectT715@8 2A8G:8 02><0B8G=> ?>4@56405<8 ?8AB8Select all autorouteable tracesQObject0715@8 70:;NG5=8B5 G0AB8Select locked partsQObject>715@8 >AB0@5;8B5 <>@0;=> G0AB8Select outdated partsQObject,@0B8 =0704 2 A;>525B5 Send backwardQObject!5=7>@8SensorsQObject40409 @07<5@0 =0 @5H5B:0B0 Set Grid SizeQObjectJ0409 A5<5 70 70?J;20=5 A 7075<O20=5 Set Ground Fill SeedQObject(03;0A8 2A8G:8 =0 :  Set all to:QObject:0409B5 >?8A0=85 =0 :>=5:B>@0 Set the connectors's descriptionQObject:0409B5 703;0285 =0 :>=5:B>@0Set the connectors's titleQObject"(8;4>25 (Shields)ShieldsQObject!8B>?5G0B >;5=Silkscreen BottomQObjectH!8B>?5G0B >;5= (5B8:5B8 =0 G0AB8B5)Silkscreen Bottom (Part Labels)QObject!8B>?5G0B >@5=Silkscreen TopQObjectH!8B>?5G0B >@5= (5B8:5B8 =0 G0AB8B5)Silkscreen Top (Part Labels)QObject!J65;O20<5, Fritzing >I5 =5 <>65 40 ?>5<0 4C?:8 8 ?>4;>6:8 70 smd 5;5<5=B8 54=>2@5<5==> (2J2 %1>B %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObject!J65;O20<5, Fritzing >I5 =5 <>65 40 ?>5<0 4C?:8 8 ?>4;>6:8 70 smd 5;5<5=B8 54=>2@5<5==> (2J2 %1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectd!J60;O20<,=5 <>65 40 A5 87?J;=8 ?>4;>6:0 >B B8? %1Sorry, can't handle pad type %1QObject728=5B5 8<0<5 ?@>1;5< A ?>4<5=OI8O <5E0=87J<. Fritzing 2A5 >I5 @01>B8 ,=> =O<0 40 <>65B5 40 A<5=OB5 =0AB@>9:8B5 =0 G0AB8B5.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObject 0745;8 ?8AB0B0 Split WireQObject "5:ABTextQObjectB$09;JB %1 =5 5 Fritzing D09; (2).'The file %1 is not a Fritzing file (2).QObjectB$09;JB %1 =5 5 Fritzing D09; (3).'The file %1 is not a Fritzing file (3).QObjectB$09;JB %1 =5 5 Fritzing D09; (4).'The file %1 is not a Fritzing file (4).QObject$09;JB '%1'5 A0<> 70 G5B5=5 ; <>;O 87?>;7209B5 4@C3> 8<5 70 D09;0.@ =0 <>4C;0 '%3'.OB> 4>1028EB5 5 25G5 B0< ,=O<0 40 O 4>102O<5 >B=>2=> =0;8 ? RThe part that you have just added, is already there, we won't add it again, right?QObjectO<0 >1@0B=> 2@JI0=5 >B B078 >?5@0F8O :0:B> 8 =8:0:28 4>?J;=8B5;=8 ?@54C?@5645=8O!!!!20 459AB285 =5 87B@820 D09;>25; B> 2J7AB0=>2O20 =0AB@>9:8B5 4> B5E=8B5 AB>9=>AB8 ?> ?>4@0718@0=5.TThis action does not delete any files; it restores settings to their default values.QObject=AB@C<5=B8ToolsQObject 8AB8 Trace wiresQObjectZ5 <>65 40 A5 87G5@B05 <54=0B0 ?8AB0 %1 %2 %3 Unable to parse copper: %1 %2 %3QObjectr5 <>65 40 1J45 AJE@0=5= D09;0 >B B8?0 275<8 8 ?>AB028 %2&Unable to save pick and place file: %2QObjecth5 <>30B 40 A5 ?@5@8AC20B A;>525B5 A :@828B5 2J2 %1$Unable to translate svg curves in %1QObject45A2J@70= ?>4G5@B020I F2OBUnconnected highlight colorQObject58725AB5= A;>9 Unknown LayerQObject8F0(?@>2>4=8:)WireQObject8F8WiresQObjectX>65 40 A5 =0;>68 40 ?@570@548B5 SVG D>@<0B0&You may need to reload the shape SVG. QObject 5B8:5Ba labelQObjectAB>9=>ABa valueQObject@;8?A20B ?0@0<5B@8 =0 ?@8AB02:8B5attributes missing paramsQObject>;>H ?0@0<5BJ@ =0 A;>O A <0A:0B0bad layer mask parameterQObjecth3@5H5= 0@3C<5=B ?@8 ?@51@>O20=5 =0 ?>4;>6:8B5 70 smdbad pad argument countQObjectV3@5H5= 0@3C<5=B ?@8 ?@51@>O20=5 =0 ?8=>25B5bad pin argument countQObject:;>H0 AE5<0B8G=0 45D8=8F8O %1bad schematic definition %1QObject11bbQObject:873;54 5:A?5@8<5=B0;=0 ?;0B:0breadboard viewQObject&<54=5= A;>9(A;>525)copper layer(s), QObjectR3@5H:0 ?@8 5:A?>@B8@0=5B> =0 ?@>1820=5B> drill export failureQObjectN;8?A20B 5;8?B8G=8 ?0@0<5B@8 =0 5;8?A0B0drill missing ellipse paramsQObject@;8?A20B ?0@0<5B@8 70 ?@>1820=5B>drill missing paramsQObjectN=5 5 704045=> >B<5AB20=5 =0 ?@>1820=5B>drill offset not implementedQObjectP5:A?>@B8@0=8O D09; 70 ?@>1820=5 5 ?@075=exported drill file is emptyQObjectX5:A?>@B0 =0 A;>O A A>;45@<0A:0B0 %1 5 ?@075=exported mask layer %1 is emptyQObjectl5:A?>@B8@0=85 8 ?>AB025= A;>9 A A>;45@<0A:0B0 5 ?@075="exported paste mask layer is emptyQObjectj3@5H:0 ?@8 :>=25@B8@0=5B> =0 SVG G5@B560 1: %1 %2 %3%failure in svg conversion 1: %1 %2 %3QObjectj3@5H:0 ?@8 :>=25@B8@0=5B> =0 SVG G5@B560 2: %1 %2 %3%failure in svg conversion 2: %1 %2 %3QObjectD09;>25filesQObjectB>B?5G0BJ: %1 =5 5 =0<5@5= 2J2 %2footprint %1 not found in %2QObject873;54 =0 8:>=8 icon viewQObject88iiQObject8=GinQObjectD3@5H:0 ?@8 5:A?>@B8@0=5 =0 <0A:0B0mask export failureQObject.A;>9 A <0A:0B0(<0A:8B5)mask layer(s), QObjectP=5 :@J3;8 4C?:8 >I5 =5 A0 8<?;5<5=B8@0=8"non-circular holes not implementedQObjectF=5 <54=8 4C?:8 =5 A0 8<?;5<5=B8@0=8 non-copper holes not implementedQObject(>G5@B0=85B> 5 ?@07=>outline is emptyQObjectJ;8?A20B A2>9AB20 =0 ?>4;>6:0B0 70 smdpad missing attributesQObject@;8?A20I8 drill =0 smd ?>4;>6:8B5pad missing drillQObject8;8?A20 ?>78F8O =0 ?>4;>6:0B0pad missing positionQObject4;8?A20 D>@<0 =0 ?>4;>6:0B0pad missing shapeQObjectT;8?A20B ?0@0<5B@8 70 D>@<0B0 =0 ?>4;>6:0B0pad shape missing paramsQObject<=520;845= @07<5@ =0 ?>4;>6:0B0pad shape size is invalidQObject>3@5H:0 ?@8 87G5@B020=5B> 2J2 %1parse failure in %1QObject6?>AB028 A;>525B5 A <0A:0B0,paste mask layer(s), QObject ?;0B:0pcbQObject*873;54 ?5G0B=0 ?;0B:0pcb viewQObject>;8?A20I8 ?0@0<5B@8 =0 ?>78F8OB0position missing paramsQObject AE5<0schemQObjectRAE5<0B0 %1 =5>G0:20=> 702J@H20 (1) 2J2 %2(schematic %1 unexpectedly ends (1) in %2QObjectRAE5<0B0 %1 =5>G0:20=> 702J@H20 (2) 2J2 %2(schematic %1 unexpectedly ends (2) in %2QObjectRAE5<0B0 %1 =5>G0:20=> 702J@H20 (3) 2J2 %2(schematic %1 unexpectedly ends (3) in %2QObjectVAE5<0B8G=0B0 G0AB %1 =5 5 =0<5@5=0 2J2 %2!schematic part %1 not found in %2QObject"AE5<0B8G5= 873;54schematic viewQObjectR45;B>84=8B5 ?>4;>6:8 =5 A0 8<?;5<5=B8@0=8shape delta not implementedQObjectB3@5H:0 ?@8 5:A?>@B0 =0 A8B>?5G0B0silk export failureQObjectR5:A?>@B0 =0 A;>O A A8B>?5G0B0 %1 5 ?@075=silk layer %1 export is emptyQObject,A;>9(A;>525) A8B>?5G0Bsilkscreen layer(s), QObject<A;>9 A >G5@B0=85B> =0 ?;0B:0B0the board outline layer, QObjectZB@0?5F>84=8 ?>4;>6:8 >I5 =5 A0 8<?;5<5=B8@0=8 trapezoidal pads not implementedQObjectP=5 <>65 40 A5 :>?8@0 D09; '%1' 2J2 '%2'.!unable to copy file '%1' to '%2'.QObjectR=5 <>65 40 87?J;=8 D>@<0 =0 ?>4;>6:0B0 %1unable to handle pad shape %1QObject0=5 <>65 40 A5 >B2>@8 %1unable to open %1QObject4=5 <>65 40 A5 87G5@B05 %1unable to parse %1QObject.=5>G0:20= :@09 =0 D09;0unexpected end of fileQObjecth=5>G0:20= :@09 =0 @540 ?@8 >B?5G0BJ: %1 2J2 D09; %21unexpected end of file in footprint %1 in file %2QObjectF=5>G0:20= D>@<0B (1) 2J2 %1 >B %2#unexpected format (1) in %1 from %2QObject0%1 cm%3 (%2 in%3).<br /> %1 cm%3 (%2 in%3).
     QuoteDialog >?8OCopies QuoteDialog0 ?>25G5 8=D>@<0F8O >B=>A=> F5=8B5 286B5 <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>.rFor more information on pricing see http://fab.fritzing.org/pricing. QuoteDialogDD5@B8 70 ?@>8725640=5 >B FritzingFritzing Fab Quote QuoteDialogT>@JG09 5G0B=0 ?;0B:0 "Fritzing" D01@8:0 Order your PCB from Fritzing Fab QuoteDialog>;O 8<09B5 2?@54284 ,G5 F5=8B5 =5 2:;NG20B @07E>48B5 ?> B@0=A?>@B0,<br />6Please note that prices do not include shipping,
     QuoteDialog&5=0Price QuoteDialog&5=0 =0 ?;0B:0Price per board QuoteDialogbJ7?>;7209B5 A5 >B =0H0B0 >BABJ?:0 70 :>;8G5AB20:(Take advantage of our quantity discount: QuoteDialogb1I0B0 ?;>I =0 %n ?5B0G=0 ?;0B:0 2 B078 AE5<0 5 1The total area of the %n PCB(s) in this sketch is QuoteDialog7?>;7209B5 D01@8:0B0 =0 Fritzing 70 40 AJ74045B5 ?5G0B=0 ?;0B:0 >B 20H0B0 AE5<0 . <br />9Use Fritzing Fab to produce a PCB from your sketch.
     QuoteDialog*>A5B5B5 Fritzing FabVisit Fritzing Fab QuoteDialog4>?J;=8B5;=8 B0:A8 , 8;8 B0:A0B0 70 ?@>25@O20=5 =0 ?;0B:0B0 <br />5possible additional taxes, or the checking fee.
     QuoteDialog&3=>@8@09&IgnoreRecoveryDialog&J7AB0=>28&RecoverRecoveryDialogV<p><b> Fritzing <>65 40 5 A@5I=0; =5>G0:20= ?@>1;5< ,=> =O:>9 >B ?@><5=8B5 ?> A;54=8B5 D09;>25 <>30B 40 1J40B 2J7AB0=>25=8. </b></p><p>@5<5B> 8 40B0B0 ?> :>5B> D09;0 5 18; AJE@0=5= ?>A;54=> 5 87>1@075=.:> D09;0 5 18; AJE@0=5= B> B>3020 A5 87?8A20 8 40B0B0 8 G0A0 70 A@02=5=85.</p><p>@838=0;=8B5 D09;>25 A0 2A5 >I5 =0 20H8O 48A: 0:> =O:>30 A0 18;8 AJE@0=5=8.8EB5 <>3;8 40 8715@5B5 40;8 40 ?@570?8H5B5 >@838=0;=8O D09; A;54 :0B> 70@548B5 =53>28O D09; 70 2J7AB0=>2O20=5</p><p><b>715@5B5 D09;>25B5 :>8B> 8A:0B5 40 2J7AB0=>28B5 >B A?8AJ:0 ?> 4>;C.</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialog$09;FileRecoveryDialog>A;545= 15:J? Last backupRecoveryDialog">A;54=> AJE@0=5= Last savedRecoveryDialog(D09;0 =5 5 AJE@0=5= file not savedRecoveryDialog 578AB>@ResistorResistor8EB5 <>3;8 8;8 40 2J2545B5 AB>9=>AB =0 AJ?@>B82;5=85B> , 8;8 40 8715@5B5 B0:020 >B ?040I>B> <5=N. $>@<0B nnn.dP :J45B> P 5 548= >B umkMG'tYou can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'ResistorAJ?@>B82;5=85 resistanceResistor@02=> (8.5x14)Legal (8.5x14)ResizableBoard8A<> (8.5x11)Letter (8.5x11)ResizableBoardJ@=8 ?@><5=8B5RevertResizableBoard?>B@518B5;A:8customResizableBoard28A>G8=0(<<) height(mm)ResizableBoard28A>G8=0 %1mm height: %1mmResizableBoard(70?078 AJ>B=>H5=85B>keep aspect ratioResizableBoard D>@<0shapeResizableBoard @07<5@sizeResizableBoardH8@>G8=0(<<) width(mm)ResizableBoardH8@>G8=0 %1mm width: %1mmResizableBoardH8@>G8=0widthRuler0B0DateSchematicFrame<5 =0 D09;0FilenameSchematicFrame @>5:BProjectSchematicFrame8ABSheetSchematicFrame40B0dateSchematicFrame>BofSchematicFrame D>@<0shapeSchematicFrame;8ABsheetSchematicFrame2!<5=8 5B8:5B0 >B %1 =0 %2Change label from %1 to %2SchematicSketchWidget6@><5=8 2>;B060 >B %1 =0 %2Change voltage from %1 to %2SchematicSketchWidget B<5=8CancelSetColorDialogJ0?@028 B>20 %1 F25B0 ?> ?>4@0718@0=5Make this the default %1 colorSetColorDialogOKSetColorDialog%1 015;56:0 : 18EB5 <>3;8 AJI> 40 87:0@0B5 B>78 48A?;59 :0B> >B845B5 A <8H:0B0 2J@EC AB0BCA0 =0 @CB8@0=5 =0 ?8AB8B5 2 ;5=B0B0 A AB0BCA0i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2 ?@54<5B8 %1 %2 items SketchWidget%1 5B8:5B '%2' %1 label '%2' SketchWidget>1028 %1Add %1 SketchWidget>1028 %1 G0AB8 Add %1 parts SketchWidget@><5=8Change SketchWidget4!<5=8 %1 F25B0 >B %2 =0 %3Change %1 color from %2 to %3 SketchWidget0@><5=8 %1 >B %2 =0 %3Change %1 from %2 to %3 SketchWidget2!<5=8 %1 5B8:5B0 =0 '%2'Change %1 label to '%2' SketchWidget>!<5=8 %1 I8@>G8=0B0 >B %2 =0 %3Change %1 width from %2 to %3 SketchWidgetF@><5=8 AJ?@>B82;5=85B> >B %1 =0 %2Change Resistance from %1 to %2 SketchWidget>!<5=8 F25B0 =0 %1 68F8B5 =0 %2Change color of %1 wires to %2 SketchWidget<@><5=8 :0@B8=:0B0 >B %1 =0 %2Change image from %1 to %2 SketchWidget^@><5=8 B>G:0B0 =0 45D>@<0F8O >B :@0G5B> =0 %1.Change leg bendpoint for %1. SketchWidgetF@><5=8 :@828=0B0 =0 :@0G5B> =0 %1.Change leg curvature for %1. SketchWidgetD!<5=8 H8@>G8=0B0 >B %1 68F8 =0 %2Change width of %1 wires to %2 SketchWidget !2J@68Connect SketchWidget$!J7409 8 A2J@68 %1Create and connect %1 SketchWidget(!J7409 8 A2J@68 68F0Create and connect wire SketchWidget0!J7409 68F0 >B <8H0 68F0Create wire from Ratsnest SketchWidget&7B@889 <8H8B5 68F8Delete ratsnest SketchWidget"B<5=8 A5;5:F8OB0Deselect SketchWidget6B<5=8 A5;5:F8OB0 >B 2A8G:> Deselect all SketchWidget B:0G8 Disconnect SketchWidget0B:0G8 2A8G:8 68F8 >B %1Disconnect all wires from %1 SketchWidgetDB:0G8 2A8G:8 68F8 >B %1 ?@54<5B8 "Disconnect all wires from %1 items SketchWidget2>9=> :;8:20=5 Double-click SketchWidgett0B8A=8 420 ?JB8 70 40 ?@5<0E=5B5 B078 B>G:0 =0 45D>@<0F8O&Double-click to delete this bend point SketchWidget602;5G8 8;8 :;8:=8 420 ?JB8Drag or double-click SketchWidget 1J@=8Flip SketchWidget1J@=8 %2 (%1) Flip %2 (%1) SketchWidgetFriztingFritzing SketchWidget @5<5AB8 %2 (%1) Move %2 (%1) SketchWidget4@5<5AB8 %2 ?@54<5B0 (%1)Move %2 items (%1) SketchWidget*@5<5AB8 5B8:5B0 '%1'Move label '%1' SketchWidget"@5<5AB8 :@0:0 =0 Move leg of SketchWidget8!<O=0 =0 B5:AB0 =0 15;56:0B0Note text change SketchWidgetD'0ABB0 '%1'=5 5 =0<5@5=0 2 AE5<0B0Part '%1' not found in sketch SketchWidget*@5>@07<5@8 15;56:0B0 Resize Note SketchWidget:@5>@07<5@8 ?;0B:0B0 =0 %1 %2Resize board to %1 %2 SketchWidget<@5>@07<5@8 ;8=88:0B0 =0 %1 %2Resize ruler to %1 %2 SketchWidget02J@B8Rotate SketchWidget02J@B8 %2 (%1)Rotate %2 (%1) SketchWidget715@8 %1 Select %1 SketchWidget&715@8 %1 ?@54<5B8 Select %1 items SketchWidget715@8 2A8G:8 Select All SketchWidget!5;5:F8O Selection SketchWidget,<0 =5?@5:0@0=8 2@J7:8!There are no unrouted connections SketchWidget"">20 873;5640 :0B> >?8B 40 A5 AJ74045 ?8AB0 <564C A;>525B5. "0:>20 >1AB>OB5;AB2> =5 18 A;5420;> 40 A5 ?>;CG020.>;O A2J@65B5 A5 A @07@01>BG8F8B5.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget$5?@5:0@0=8 2@J7:8Unrouted connections SketchWidgetT5?@5:0@0=8B5 2@J7:8 A0 >B15;O70=8 2 6J;B>/Unrouted connections are highlighted in yellow. SketchWidget<?@><5=8 5B8:5B8B5 =0 ?8=>25B5 change pin labels SketchWidget(?@8:;NG5=> 70@5640=5 done loading SketchWidget >B %1from %1 SketchWidget8A:@889 %n 5B8:5B0 =0 G0ABB0 hide %n part label(s) SketchWidget70@5640< G0AB loading part SketchWidgetb8;8 =0B8A:09:8 alt 2;0G8 70 40 ?@5<5AB8H A53<5=B0or alt-drag to move the segment SketchWidgetF?>:068 %n 5B8:5B =0 G0ABB0(G0AB8B5)show %n part label(s) SketchWidget =0 %1to %1 SketchWidget ?8AB0trace SketchWidget68F0wire SketchWidgetR5E0=87J<0 ?> ?>4<O=0B0 5 87:;NG5= 70 : )The swapping mechanism is disabled for: SqliteReferenceModel$8 %1 4@C38 G0AB8and %1 other partsSqliteReferenceModel*8 %1 4@C38 A2>9AB20and %1 other propertiesSqliteReferenceModel|G0AB '%1' AJA id '%2'; 25@>OB=> 70I>B> =O<0 A2>9AB2> 'D0<8;8OEpart '%1' with id '%2'; possibly because it has no 'family' property.SqliteReferenceModelLA2>9AB2> '%1' 2 G0AB '%2' AJA id '%3'.(property '%1' in part '%2' with id '%3'.SqliteReferenceModel%1 %n ;5=B0(8)%1 %n strip(s) Stripboard%1 >D>@<;5=85 %1 layout Stripboard B@568Cut StripboardJ7AB0=>25=Restored Stripboard :>;>=8columns Stripboard @54>25rows Stripboard@56>28 5B8:5B8 Net labelsSymbolPaletteItemT@56>28B5 5B8:5B8 =5 <>30B 40 1J40B ?@07=8Net labels cannot be blankSymbolPaletteItem 5B8:5BlabelSymbolPaletteItem 2>;B06voltageSymbolPaletteItem !J25B8 8 B@8:>25Tips and Tricks TipsAndTricks702J@B0=5rotation TipsAndTricksr715@8 >B ?040I>B> <5=N ,8;8 =0?8H8 AB>9=>AB >B %1 4> %2 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>কোড এর মধ্যে GNU GPL v3এবং বাকি টুকুর মধ্যে CreativeCommons:BY-SA <b>2007-%1 Fachhochschule Potsdam</b> <b> 2007-%1Fachhochschule 'potsdam করুন </b> Fritzing is made by: ফ্রিটজিংগ যারা বানিয়েছেনঃ Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto wettach,Andr&eacute;Kn &ouml;rig;Myriet Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: বিশেষ ভাবে ধন্যবাদ দিচ্ছিঃ Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, kutrt badelt এবং Miguel solis কে ধন্নবাদ স্প্যানিশ আনুবাদের জন্য, to Gianluca Urgese for the Italian translation, Gianuca Urgese কে ইতালিয়ান ভাষায় আনুবাদের জন্য, to Nuno Pessanha Santos for the Portuguese (European) translation, ধন্যবাদ Nuno Pessanha Sontos কে portuguese(ইউরপিয়ান) আনুবাদের জন্য, to Yuelin and Ninjia for the Chinese (Simplified) translation, ধন্য বাদ Yuelin এবংNinjia কেন চাইনিস(simplied)আনুবাদের জন্য, to Hiroshi Suzuki for the Japanese translation, ধন্যবাদ hiroshi suziki কে জাপানিস ভাষার আনুবাদের জন্য, to Robert Lee for the Chinese (Traditional) translation, ধন্যবাদ Robert Leeচাইনিজ(ট্র্যাডিশনাল)আনুবাদের জন্য, to Vladimir Savinov for the Russian translation, ধন্যবাদ Vladimir Savinov রাশিয়ান ভাষায় আনুবাদের জন্য, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, ধন্যবাদ Josef Dustira কে czeck ভাষায় আনুবাদের জন্য, to Jinbuhm Kim for the Korean translation, ধন্যবাদ Jinbuhm Kim কোরিয়ান ভাষায় আনুবাদের জন্য, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, এবং#313;ubom & jacute;r ducho&#328;for the slovak আনুবােদর জন্য, to Alexander Kaltsas for the Greek translation, ধন্যবাদ Alxeander Kaltsas কে গ্রীক ভাষায় আনুবাদের জন্য, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the Fritzing থেকে অর্থায়ন সঙ্গে তৈরি সম্ভব ফ্রিটজিংগ এর আনুদানে ইহা সম্ভব MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg,এর উদ্যোক্তা বা ডিজাইনার Department of Bauhaus-University Weimar, Buhaus বিশ্ববিদ্যাল এর weimer ডিপার্টমেন্ট,>বিভাগ Buhaus বিশ্ববিদ্যালয় weimer ডিপার্টমেন্ট, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, লম্বন IxDS, বেনামী দাতা,parallax,Picaxe, Sperkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students সকল ছাত্র ছাত্রিদের বিশেষ ধন্যবাদ দেয়াহল and alpha testers who were brave enough to give এবং পরীক্ষক গনকে যারা পর্যাপ্ত অভিমত প্রদান করেছেন Fritzing a test spin. Fritzing পর্যবেক্ষণ ফ্রিটজিংগ পরীক্ষন <br /><br /><br /><br /><br /><br /><br /><br /> <br/><br/><br/><br/><br/><br/><br/><br/> AutorouteProgressDialog zoom and pan controls জুম এবং প্যান নিয়ন্ত্রণ zoom এবং pan নিয়ন্ত্রণ Stop Now থামাতে বন্ধ কর বন্ধ করুন Best So Far Cancel বন্ধ করা বাতিল করুন বাতিল Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type কর্মক্ষেত্রের ধরন বা তইয়ার করার ধরন কাজ করার ধরন homebrew নিজের professional পেশাদারি পেশাগত custom প্রথা বিধি Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width প্রসস্ত চওড়া পথচিহ্ন Cancel বাতিল করা বাতিল OK আচ্ছা ঠিক BinManager Parts অংশ গুণাবলী পার্টস BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty Bin ম্যানেজারঃঃসেট অপরিচ্ছন্ন ট্যাবঃ বিন সেট করা %1 BinManager::updateTitle: Couldn't set the bin '%1' as dirty Bin ম্যানেজারঃঃসেট শিরোনাম: ট্যাবঃ বিন সেট করা %1 New bin (%1) নতুন বিন বক্স(%1) Select a Fritzing Parts Bin file to open Fritzing নির্বাচিত ফাইল খুলতে একটি' Fritzing'​​ফাইল খোলতে নির্বাচন করুন Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing নেওয়ার যোগ্য বক্স Fritzing ফাইল বক্স(*%1'*%2);;Fritzing বক্স (*%1);;Fritzing সেয়ারেবল বক্স Cannot set a NULL bin as the current one বর্তমান বক্সে NULLএর মত বক্স তৈয়ার কর Searching... খোজ করার জন্য খোঁজ কর Bin বক্স বিন Import... সংগ্রহ করা... আমদানি করতে... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) একটি Fritzing অংশ (. fzpz),বা একটি Fritzing partsবিন লোড (.fzb,'. fzbz) New Bin... নতুন বক্স.বিন.... নতুন বিন বক্স Create a new parts bin নুতন পার্টস বক্স তইরিকরন বক্স নতুন পার্টস বিন তৈরি Close Bin বন্ধ বিন বক্স Close parts bin পার্টস বিন বক্স বন্দ কর Delete Bin বিন বক্স মুছেফেলা Delete parts bin পার্টস মুছে ফেলার জন্য বক্স পার্টস বিন বক্স মুছে ফেলা Save Bin সঞ্চিত করন বক্স সঞ্চয় বিন বক্স Save parts bin পার্টস সঞ্চিত করন বক্স পার্টস সঞ্চয় বিন বক্স Save Bin As... সঞ্চয় বক্স ঐ রকম করে বিন হিসাবে সংরক্ষণ করুন... Save parts bin as... সঞ্চয় বক্স ঐ রকম পার্টস বিন হিসাবে সংরক্ষণ করুন... Export Bin... বিন বক্স রপ্তানি করুন... Save parts bin in compressed format... compressedপার্টস বক্স সঞ্চয় ফর্মেট... Rename Bin... বিন বক্সের নামকরন... নামকরন বিন বক্স... Rename parts bin... পার্টস বিন বক্স নামকরন... পার্টস বক্স নামকরন... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View তালিকা বিন বক্স দেখার জন্য তালিকা আকারে বিন দেখার জন্য Display parts as a list পার্টস তালিকা প্রদর্শন দৃশ্যমান পার্টস তালিকা Show Bin in Icon View দৃশ্যমান বিন বক্স চিত্র বিন প্রদর্শন আইকন Display parts as icons পার্টস চিত্র সামুহ প্রদর্শন Edit Part (new parts editor)... পার্টস সোগযগ করন.. সং যুক্ত (নতুন পার্টস এডিটর) Export Part... পার্টস সংযোগ করতে পার্ট রপ্তানি Remove Part পার্ট সরিয়ে ফেলতে পার্ট সরিয়ে ফেলা Find Part in Sketch Delete bin বক্স মুছে ফেলতে মুছে ফেলার বক্স Do you really want to delete bin '%1'? This action cannot be undone. আপনি কি বিন বক্স মুছতে চান '%1'?..যে কাজ টি অসমাপ্ত Read-only bin বক্স টি পরতে বক্স টি পড়ার জন্য মাত্র This bin cannot be renamed. এই বক্সটি নামকর হচ্ছেনা এই বিন নাম বদলানো যাবে না Rename bin বক্সের নামকরন বক্স নামকরন Please choose a name for the bin: দিন আনুগ্রহ করে বক্সের নাম ধার্য করুনঃ Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin বক্স হতে স্তানান্তর জন্য বক্স হতে সরাতে Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open frtzing ফাইল খোলা জন্য নির্বাচন frtzing ফাইল খোলা জন্য Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing ফাইল'স(*%1'*%2' *%3);;Fritzing পার্ট (*%1)Fritzing বক্স (*%2);: Fritzing বিনিময় করা(*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. আপনার firtzing ইনস্টলেশন ফোল্ডারে একটি করে parts/svg/core/pcb.'আর বর্ণনা আছে। one layer (single-sided) এক 'স্তর' (একক পার্শ্বযুক্ত) এক স্তর অর্ধেক পাস two layers (double-sided) দু 'স্তর' (দুই পাশে) দুই স্তর (দুই পাস) image file চিত্র 'ফাইল ইমেজ ফাইল load image file লোড 'চিত্র' ফাইল লোড ইমেজ ফাইল Images 'চিত্র' ইমেজ Select an image file to load নির্বাচন 'একটি' চিত্র 'ফাইল'. লোডের জন্য একটি' চিত্র 'ফাইল লোডের জন্য নির্বাচন due to an xml problem: %1 line:%2 column:%3 সমাধানের জন্যঃ %1 লাইনঃ %2 কলামঃ%3 উদাহারন because the xml is not correctly formatted উদাহরন ঠিক না থাকলে মুছাফেলা কোন কারনে xml সটীক বিন্যাস না হলে the <board> element contains no shape elements <bord> 'উপাদান' দি<bord> 'উপাদান' because there are multiple <board> layers সেখানে'একাধিক <bord> দেয়া আছে এখানে একাধিক<bord> লেয়ার আছে because there are multiple <silkscreen> layers সেখানে <silkscreen>লেয়ার আছে এখানে একাধিক<silkscreen>লেয়ার because there are multiple <silkscreen0> layers because there is no <board> layer 'সেখানে' কোন '<board>লেয়ার নাই এখানে কোন <board>লেয়ার নাই the svg contains no shape elements svg আকার নিরধারনের 'উপাদান' নেই SVG 'উপাদান' উপস্থিত নেই but the pcb itself will have no silkscreen layer পি সি বি লেয়ারে কোন ছাপ পড়ে নাই কিন্তু PCB তে নিজস্ব কোন silkscreen'স্তর নেই the svg doesn't fit the custom board format svg বোর্ড পরিবর্তন ফিট হচ্ছে না SVG কাস্টম bord বিন্যাসে ফিট হচ্ছে না <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load গ্রহন করার জন্য অপ্রস্তুত লোড করতে অক্ষম Unable to load image from %1 %2 এবং চিত্র পুনঃধারন %১ %২ করতে অক্ষম এবং% 1%2 থেকে চিত্র লোড করতে অক্ষম Can load, but ধারন সস্মব কিন্তু 'লোড করতে পারে, কিন্তু The image from %1 can be loaded, but %2 Use the file? % 1 থেকে চিত্র %2'লোড' করতে পারেন, কিন্ত এই ফাইল ব্যবহার করে ইমেজ %1 ধারন সম্ভব,কিন্তু%2 এইফাইল ব্যবহাের? BoardLogoItem shape আকার BreadboardLogoItem color রং Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint বিন পয়েন্ট যোগ করুন Straighten curve প্রাথমিক পর্যবেক্ষণ বক্র সোজা Remove bendpoint বিন পয়েন্ট সরিয়ে ফেলুন ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools সরঞ্জাম &About এই সম্পর্কে About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit সব বন্ধ Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. আপনার স্কেস উৎপাদনের জন্য তইয়ারঃ এখানে আর কোন সংযোগ অথবা ছাপ নাই আবৃত অংস একসাথে বন্ধ করতে । The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing ফ্রিটজিং Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging ডিবাগ করার জন্য DeleteDialog Also delete the file এ ছাড়াওফাইলটি মুছে দিতে এই ফাইল টি মুছতে Remove অপসারণ সরিয়ে ফেলুন Don't remove অপসরণ না করা কক্ষনো সরবেনা Dip chip label চিপ স্তর FApplication Fritzing failure ফ্রিটজিং ব্যর্থ Fritzing caught an exception %1 from %2 in event %3 ফ্রিটজিং গ্রহন %1হইতে %2 নির্ধারণ %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 %1 থেকে ইভেন্ট %2 এর মধ্যে একটি ঘটনা পছন্দের ফ্রিটজিং গ্রহন%1 নির্ধারণ%2 Import files from previous version? আগের সংস্করন থেকে ফাইল আমদানি পূর্বের মত ফাইল সগ্রহ Do you want to import parts and bins that you have created with earlier versions of Fritzing? আপনি কি পার্টস এবং বিন্স আমদানি করতে চান যা আপনি ফ্রিতযিং earlier version থেকে পাবেন আপনি কি পার্টস এবং বক্স গ্রহন করতে চান ? তাহলে ফ্রিনটজিং ইয়ারলেয়ারের সাহাজ্য নিন Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. ' নোটঃ পরবর্তী ব্যবহারের জন্য"Help" > "পুরাতন পার্টস বিন পেতে "menu'action"। নোটঃ পরবর্তী ব্যবহারের জন্য"হেল্প" > "পুরাতন পার্টস বিন পেতে "মেনু অ্যাকশন"। Import আমদানি সংগ্রহ Do not import now এখন সগ্রহন করা যাবেনা Please specify an .fzz file name to save to (cancel will delete the backup) আনুগ্রহ করে নির্ধারিত.fzz সঞ্চয় ফাইলে (বাতিল মুছুন ফিরেযান) Fritzing (*%1) ফ্রিটজিং (*%1) FirstTimeHelpDialog First Time Help প্রাথমিক সহায়তা <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window উইন্ডো বন্ধ Ctrl+W Ctrl+W Close the current sketch বর্তমান স্কেস বন্ধ %1 - %2 %1 - %2 Specify a file name একটি ফাইলের নাম উল্লেখ Save... সঞ্চয়... Save সঞ্চয় Don't Save সঞ্চয় প্রয়োজন নাই Cancel বাতিল Ctrl+D Ctrl+D Save "%1" সঞ্চয় "%1" Do you want to save the changes you made in the document "%1"? আপনি কি পরিবর্তিত আবস্তায় সঞ্চয় করতে চান"%1"? Your changes will be lost if you don't save them. আপনার পরিবর্তিত অংশ মুছে গেছে সঞ্চয় সম্ভব নয় GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. 'গ্রাউন্ড ফিল' এবং 'কপার ফিল' এর মধ্যে পার্থক্য হলো, গ্রাউন্ড ফিল এর মধ্যে সব জায়গায় ট্রেস এবং কানেক্টর থাকে (এই কানেক্টর গুলো 'গ্রাউন্ড' এর সাথে সংযুক্ত), গ্রাউন্ড কানেক্টর গুলো সাধারণত 'GND' অথবা 'ground' লেবেল দেওয়া থাকে, কিন্তু সবসময় না। কোনো কোনো সময় একাধিক 'নেট' গ্রাউন্ড কানেক্টর সহ থাকতে পারে এবং এসব ক্ষেত্রে আপনার শুধু একটা 'নেট' ভরাট করা দরকার। এই ডায়লগ শুধু 'GND' অথবা 'ground' লেবেল করা কানেক্টর গুলো এবং যেসব কানেক্টর 'seed' হিসাবে চিহ্নিত হয়েছে সেগুলো সংগ্রহ করে। স্কেচ এর মধ্যে কানেকশন গুলো দেখার জন্য যেকোনো আইটেম এর উপর ক্লিক করুন। যেকোনো কানেক্টর এ ডান-ক্লিক করে এবং কনটেক্সট মেনু থেকে 'Set Ground Fill Seed' সিলেক্ট করেও যেকোনো কানেক্টর কে 'Ground Fill Seed' বানানো সম্ভব। Cancel বাতিল করা বাতিল OK আচ্ছা ঠিক OK and ground fill সঠিক নিচের ফিল OK and copper fill সঠিক কপার ফিল Hole hole size ছিেদ্রর সাইজ HtmlInfoView Change the part label here পার্ট লেভেল পরিবর্তন /পরিবর্তন অংশ লেবেল এখানে অংশ বিশেষ পরিবর্তন এখানে Part breadboard view image breadboard দর্শন চিত্রাঅংশ ব্রেডবোর্ড দেখার অংশ চিত্র Part schematic view image schmatic দর্শন চিত্রাঅংশ স্কেমেটিক দেখার অংশ চিত্র Part pcb view image pcb দেখার চিত্রআংশ পি সি বি দেখার চিত্র আংশ Part version number স্তরের অংশ নং যন্ত্র সংষ্করণ সংখ্যা Locked আটকানো লক করতে Change the locked state of the part in this view. A locked part can't be moved. একটি বন্ধ অংশ চলা যাবে না।এই বিনের সুরুতে ধারন কৃত যন্ত্র পরিবর্তন দেখতে' ধারন কৃত যন্ত্রাংশ স্তানান্তর করতে Sticky স্টীকি Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. পরিবর্তন " স্টিকি " এই দর্শনে part' এইটির ওপর ও বিষয়ে চলে সরাসরি " স্টিকি" দর্শনের অংশ চিত্র। যার উপর" স্টিকি"চলা চল করে। Properties বৈশিষ্ট্যাবলী জায়গা Placement pcb layer Tags ট্যাগস নির্ধারণ Connections সংযোগ conn. নির্ধারণ name নাম type ধরন connected to %n item(s) এই বিষয় সংযোগে %n (s) (autoroutable) (স্বয়ংক্রিয় ভাবে রুট) Wire তার Ratsnest wire Ratsnest তার Trace wire %1 ট্রেস তার %1 ট্র্যাক তার %1 v. %1 %2 v. %1 %2 obsolete পুরাতন অপ্রচলিত location rotation degrees ItemBase family এর ধরন type রকম ধরন model আকৃতি size আকার color রং resistance রেজিস টেন্স capacitance ক্যাপা সিটর inductance ইনডাকটেনস voltage ভোল্টেজ current কারেন্ট power পাওয়ার pin spacing মূল জায়গায় rated power পাওয়ার রেট rated voltage ভোল্টেজ রেট rated current কারেন্ট রেট version সংস্করণ package প্যাকেজ shape আকৃতি form হইতে part number পার্ট নাম্বার maximum resistance অধিক রেজিসটেন্স pins পিন গুলি spacing পার্থক্য ব্যবধান frequency ফ্রিকুইন্সি processor কারিগর প্রস্তুত কারক variant ভিন্ন layers স্তর tolerance মানের পার্থক্য সহনশীলতা descr descr উল্লেখ্য filename ফাইলের নাম title শিরোনাম date তারিখ rev ফিরতি দেখা আগের sheet শীট project প্রোজেক্ট banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part পার্টস model part problem সমস্যার অংস গুলি পার্ট নমুনায় সমস্যা file for %1 %2 not found ফাইল খুজে না পেলে%1%2 unable to create renderer for svg %1 svg %1এর জন্য renderer তৈরি করতে অক্ষম KicadModuleDialog Cancel বাতিল OK ঠিক LayerPalette show all layers সকল স্তর প্রদর্শন LinkDialog url: ইউ আর এলঃ text: টেক্সটঃ Cancel বাতিল OK আচ্ছা ঠিক LogoItem text shape রুপদান আকার due to a rendering error কারন একটি অনুবাদ সঙ্কারান্ত ত্রুটি আনুবাদ সংক্রান্ত সমস্যা because the svg is empty svg খালি কারন এস ভি জি ফাঁকা because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 বাকি উদাহারন%1লাইনঃ%2কলামঃ%3 এক্সাপ্লল বাকিঃ%1লাইনঃ %2কলামঃ%3 because the file has no root element কারন ফাইল এ কোন মুল উপদান নাই because the file has no <svg> element কারন ফাইল এ কোন এস ভি জি উপাদান নাই for unknown reasons--possibly the image file is corrupted অজানা কারনে ছবির ফাইল নষ্ট হওয়ার সম্ভাবনা অজানা কারণের জন্য-- ছবি ফাইল সম্ভবত নষ্ট Unable to display প্রদর্শন করতে অক্ষম দেখানো অসম্ভব Unable to display image from %1 %1হইতে চিত্র প্রদর্শন করতে অক্ষম ইমেজ %1 হইতেপ্রদর্শন করা অসম্ভব MainWindow Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Meta+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Rotate ঘুরােনা Share ভাগাভাগি বিনিময় Flip উল্টানো Autoroute স্বয়ংক্রিয় রুট Both Layers উভই স্তর সম্ভাব্য স্তর সমুহ Bottom Layer নিচের স্তর Top Layer উপরের স্তর Add a note চিহ্ন যুক্ত নোট সংযুক্তী Export for PCB পি সি বি তে পাঠানোর জন্য Ready প্রস্তুত Save %1 সঞ্চয় %1 Fritzing ফ্রিটজিং No Sketch found in '%1' ভিতরে নকশা নাই %1 কোন স্কেচ পায়নাই %1 Unable to open '%1': %2 Click to highlight unconnected parts Fabricate View from Above View from Below Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name একটি নিদৃষ্ট ফাইলের নাম নির্দেশিত একটি ফাইলের নাম Fritzing Part (*%1) ফ্রিটজিং অংশ t(*%1) Unable to export %1 to shareable sketch নকশারঅংশ বিশেষ রপ্তানিতে করতেঅপারগ %1বিনিময় স্কেচপাটাতে অক্ষম MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? তুমি কি চাও আমদানি করা যন্ত্রাংশ রাখতে? সংগ্রিিহত অংশ ধরে রাখতে চান? No connections to route ঘুরিয়ে সংযোগ নেই/ রাস্তার সাথে কোন সংযুক্তি নাই সংযোগ রাস্তা নেই Routing completed রাস্তা তৈরি সম্পন্ন রাউটিং সমপণ্য Routing completed using %n jumper part(s) সম্পূর্ণ রাউটিং ব্যবহারে %n জাম্পার অংস(S) %1 of %2 nets routed - %n connector(s) still to be routed %1এবং%2নিপিষ্ট জাল সংযোগ%n(s)কে স্থাপন %1 - [%2] %1 - [%2] No copper top layer উপরের স্তর এ কোন তামা নাই উপরে লেয়ারে কোণ কপার নাই The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. উপলুব্ধ একতরফা তামা (copper1)বোর্ড টি হয়নি অনুগ্রহ করে দুই পাস তামার বোর্ড আনতে(copper0)নির্বাচন করুন। Sorry! দুঃখিত? No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist ঐসব কোনো পার্টসে নাই। আমরা এই বার্তা বাদ দেবার চেষ্টা করছি এবং শুধু যেসব ধর্ম যোগ করা আছে সেইগুলাই পছন্দ করতে দিব। No exactly matching part found; Fritzing chose the closest match. যথাযথভাবে কোন অংশ মেলানোর জন্য পাওয়া যায় নি; কাছাকাছি মিল fritzing. Change to single layer pcb একক স্তর পি সি বি পরিবর্তন এক স্তর পি সি বি পরিবর্তন Change to two layer pcb দুই স্তর পি সি বি বদল দুই স্তরপি সি বি পরিবর্তন Swapped %1 with module %2 %1 সঙ্গে %2মডিউল বদল করতে মডিউল আনতে%1 পাঠাতে%2 Change image to %2 ইমেজ বদল করতে%2 ইমেজ বদলে%2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 বোঝাই করতে%1 লোডিং %1 Loading... বোঝাই... লোডিং... new sketch নতুন চাকতি নতুন স্কেচ Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' ফিরে আসতে %1 Fritzing (*%1) ফ্রিটজিং(*%1) Unrouted connections অসংযুক্ত রাস্তা অসংযুক্ত সংযোগ There are no unrouted connections in this view. এখানে অসংযুক্ত রাস্তার চিত্র দেখা অসংযুক্ত রাস্তার চিত্র দেখতে (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector পরিদর্শক Undo History পূর্বের ইতিহাস Breadboard ব্রেডবোর্ড Schematic স্কেমেটিক PCB PCB পি সি বি Layers স্তর সমূহ Couldn't get the dock widget ডক কোন উইজেট পাইনি PDF (*.pdf) পি ডি এফ(*.pdf) PostScript (*.ps) পোস্ট স্ক্রিপ্ট(*.ps) PNG Image (*.png) পি এন জি ইমেজ(*png) পি এন জি চিত্র(*.png) JPEG Image (*.jpg) জে পি ই জি ইমেজ(*.jpg) SVG Image (*.svg) এস ভি জি ইমেজ(*.svg) BoM Text File (*.html) শেষ টেক্সট ফাইল(*htm) টেক্সট ফাইল BoM (*.html) Printing... মুদ্রণ... প্রিন্টিং... Your sketch does not have a board yet! Please add a PCB in order to export etchable. আপনার তৈরি নকশা করা বোর্ডটিএখনো হয়নি? দয়া করে পাঠানোর জন্য একটিPCB যোগ করতে পারেন Etchable export can only handle one board at a time--please select the board you want to export. সংযোগিত নির্বাচন করা বোর্ডটি একই সাথে পরিচালনার জন্য পাঠান All traces have not yet been routed. সব ট্রেস এখনো রাউট হয়নি Do you want to proceed anyway? যেকোন রাস্তায় অগ্রসর হতে চান? Proceed অনুমোদন/অগ্রসর অনুমোদন Cancel বাতিল Choose a folder for exporting রপ্তানির জন্য একটি ফোল্ডার নির্বাচন করুন পরীক্ষণের জন্য একটি ফোল্ডার নির্বাচন করুন Sketch exported নকশা রপ্তানি নকশা পাটাতে Export... পাটাতে... রপ্তানি... Exporting... রপ্তানি হচ্ছে... Unable to save %1 সঞ্চয় সম্ভব নয় %1 Cannot print to %1 মদ্রনে করতেঅক্ষম %1 প্রিন্ট করতে অক্ষম %1 Cannot write file %1: %2. ফাইলটি লিখা অসম্ভব%1: %2. Saved '%1' সঞ্চয় %1 সংরক্ষণ%1 Unable to export %1 as shareable বিনিময় করে%1পাঠানো সম্ভব নয় &Save সংরক্ষণ Ctrl+S Ctrl+S Save the current sketch বর্তমান নকশা সঞ্চয় এই নকশা সংরক্ষন &Save As... এবং সেমতে সঞ্চয়... সেমতে সংরক্ষণ... Shift+Ctrl+S Shift+Ctrl+S Share online... অন লাইনে শেয়ার করুন... Post a project to the Fritzing website ফ্রিটজিংওয়েব সাইটে এই প্রোজেক্ট পোষ্ট করা ফ্রিটজিং ওয়েব সাইটে উক্ত প্রোজেক্ট পাঠান JPG... জে পি জি... JPG... Export the visible area of the current sketch as a JPG image JPG ইমেজ হিসাবে বর্তমান নকশায় দৃশ্যমান এরিয়া সাথে এক্সপোর্ট PNG... পিএনজি... PNG... Export the visible area of the current sketch as a PNG image PNG ইমেজ হিসাবে বর্তমান নকশায় দৃশ্যমান এরিয়া সাথেএক্সপোর্ট PostScript... স্ক্রিপ্ট পোষ্ট... Export the visible area of the current sketch as a PostScript image স্ক্রিপ্ট পোষ্ট ইমেজ হিসাবে বর্তমান নকশায় দৃশ্যমান এরিয়া সাথেএক্সপোর্ট PDF... পি ডি এফ... Export the visible area of the current sketch as a PDF image PDFইমেজ হিসাবে বর্তমান নকশায় দৃশ্যমান এরিয়ার সাথে এক্সপোর্ট SVG... SVG... Export the current sketch as an SVG image SVG চিত্র হিসাবে বর্তমান নকশা এক্সপোর্ট List of parts (&Bill of Materials)... তালিকার অংশ (এবং উপকরন বিল)... Save a Bill of Materials (BoM)/Shopping List as text সপিং তালিকায় একটি উপাদান বিল টেক্সট হিসাবে সংরক্ষণ XML Netlist... XML Netlist... Save a netlist in XML format XML ফর্মেটে একটি netlistসংরক্ষণ করুন SPICE Netlist... Save a netlist in SPICE format Eagle... ঈগল... Eagle... Export the current sketch to Eagle CAD বর্তমানস্কেচ ঈগলCADএ রপ্তানি করুন Extended Gerber (RS-274X)... Gerber সম্প্রসারণ (RS-247x)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Etchable (PDF)... একত্রিত(PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) পিডিএফ DIY PCB উত্পাদনের (photoresist) জন্য বর্তমান স্কেচ রপ্তানি করুন Etchable (SVG)... একত্রিত (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) SVG তে DIY PCB উত্পাদনের (photoresist) জন্য বর্তমান স্কেচ রপ্তানি করুন &Print... প্রিন্ট... Ctrl+P Ctrl+P Print the current view প্রিন্ট বর্তমান ভিউ This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. এই শীঘ্রই EAGLE লেআউট সফ্টওয়্যার আপনার Fritzing স্কেচ টি রপ্তানি করবে. যদি আপনার প্রিয় EDA টুল আমাদের আরো রপ্তানি করে,যা অবদান রাখতেপারে। Export SVG... SVG রপ্তানি... Export Bill of Materials (BoM)... উপাদােনর বিল রপ্তানি (BoM)... Unable to save BOM file, but the text is on the clipboard. BOM ফাইলটি সংরক্ষণ করতে ব্যর্থ কিন্তু টেক্সট ক্লিপবোের্ড হবে. Export SPICE Netlist... Export Netlist... সর্বশেষ লিস্ট রপ্তানি Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. আপনার স্কেচ এখনো এর কোন বোর্ডটি হইনি! PCB যুক্তএকটি GERBER এক্সপোর্ট করুন. Gerber export can only handle one board at a time--please select the board you want to export. GERBER রপ্তানি শুধুমাত্র একটি সময়ে এক বোর্ডের ব্যাবহার করতে পারে - আপনি বোর্ডের নির্বাচন করতে এবং রপ্তানি করতে চান. Sketch exported to Gerber GERBER এবং স্কেচ এক্সপোর্ট Select a Fritzing File to Open একটি Fritzing ফাইল খুলুন এবং নির্বাচন করুন Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) ফ্রিটজিং ফাইল (*%1 *%2 *%3 *%4 *%5);;ফ্রিটজিং (*%1);;ফ্রিটজিং বিনিময় (*%2);;ফ্রিটজিং অংশ(*%3);; ফ্রিটজিং বিন (*%4);;ফ্রিটজিং বিনিময় বিন (*%5) Cannot find file %1. ফাইল খুজে পাচ্ছে না %1. Cannot read file 1 %1: %2. 1 ফাইলটি পড়তে পারচ্ছে না %1: %2 Revert? প্রত্যাবর্তন? প্রত্যাবর্তন ? This operation can not be undone--you will lose all of your changes. Go ahead and revert? অপারেশন পূর্বাবস্থায় ফেরানো যায় না - আপনার করা সমস্ত পরিবর্তন হারিয়ে যাবে. এগিয়ে যান এবং প্রত্যাবর্তন? File '%1' not found ফাইল %1 খুজে পায়না the .fz file format is obsolete fz ফাইল ফরম্যাট অচল The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? Fz ফাইল ফরম্যাট অসমর্থিত হয়েছে। আপনি Fzz ফরম্যাট রূপান্তরিত করতে চান'% 1' অথবা এটিকে শুধুমাত্র পাঠযোগ্য করে খুলতে চান? The conversion process will not modify '%1'. রূপান্তর করতে পদ্ধতি '% 1' সংশোধন করা হইনি. Convert পরিবর্তন Read-only শুধু-পড়তে Please specify an .fzz file name to save '%1' to অনুগ্রহ করে নির্ধারিত নামে fzz ফাইল সেভ করুন '%1' directly loading parts সরাসরি পার্টস লোডিং loading %1 (model) মডেল %1 লোড loading %1 (breadboard) ব্রেডবোর্ড %1 লোড loading %1 (pcb) পি সি বি %1 লোড loading %1 (schematic) লোড %1 (স্কেমেটিক) New নতুন টি Ctrl+N Ctrl+N Create a new sketch একটি নাতুন স্কেচ বানান একটি নাতুন স্কেচ নিন &Open... খুলতে Ctrl+O Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) একটি ফ্রিটজিং স্কেজ (.fzz, .fz),এবং একটি ফ্রিটজিং পার্ট লোড (.fzpz),,এবংএকটি ফ্রিটজিং পার্ট বক্স (.fzb, .fzbz) খুলতে Revert প্রত্যাবর্তন Reload the sketch স্কেচটি পুনরায় লোড Shell launch %1 শেল প্রবর্তন 1% throw test exception ব্যতিক্রমটি পরীক্ষা করতে throw a fake exception to see what happens ব্যতিক্রম কি হবে দেখতে একটি জাল নিক্ষেপ &Quit সব বন্ধ Ctrl+Q Ctrl+Q Quit the application এই অ্যাপ্লিকেসন বন্ধ &Open Example উদাহরন খুলুন All সকল MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow :: populateMenuWithIndex: আইডি = '% 1' উদাহরণ টি লোড করতে পারেনি &Open Recent Files বর্তমান ফাইল খুলতে &%1 %2 %1 %2 Undo আগেরমত করুন Redo আবার করুন &Cut কাটতে Cut selection কাটতে নির্বাচন &Copy কপি Copy selection কপি নির্বাচন &Paste পেস্ট Paste clipboard contents ক্লিপবোর্ডে বিষয়বস্তু আটকান Paste in Place এখান থেকে বাহির Paste clipboard contents in place একটি স্থানে ক্লিপবোর্ডের বিষয়বস্তু আটকান &Duplicate ডুপ্লিকেট Ctrl+D Ctrl+B Duplicate selection প্রতিলিপি নির্বাচন &Delete মুছতে Delete selection মুছতে নির্বাচন &Delete Wire &Select All সব নির্বাচন Select all elements সকল যন্ত্রাংশ নির্বাচন &Deselect বাদ দিতে Deselect বাদ দাও Add Note নোট সংযুক্ত &Preferences... ও পছন্দসমূহ ... Show the application's about box আবেদন এর সম্পর্কে বক্স দেখান Edit (new parts editor) এডিট (নিউ পার্টস এডিটর) Open the new parts editor on an existing part বর্তমান অংশ নতুন অংশগুলির একটাএডিটর খুলুন &Add to bin... বিন যুক্ত করুন ... Add selected part to bin নির্বাচিত অংশে বিন যোগ করুন Disconnect All Wires সমস্ত তারের সংযোগ বিচ্ছিন্ন Ctrl+Shift+V Disconnect all wires connected to this connector সব সংযোগ এই সংযোগকারী এবং তারের সংযোগ বিচ্ছিন্ন Update InfoView on hover আপডেট InfoView উপর কার্সার রেখে দেখুন Export Normalized SVG সাধারণ SVG রপ্তানি করুন Export 1000 dpi SVG of this part in this view 1000 DPI SVG এই অংশের রপ্তানি এর ফলে ভিউ Export Normalized Flattened SVG সাধারণত একরকমের SVG রপ্তানি করুন Export 1000 dpi Flattened SVG of this part in this view 1000 DPI এই ভিউ রপ্তানি এর ফলে অংশের SVG একরকমের Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise 45 ডিগ্রি ক্লক ওয়াইজ ঘুরা নির্বাচন Rotate the selected parts by 90 degrees clockwise 90 ডিগ্রি ক্লক ওয়াইজ নির্বািচত পার্টস ঘুরান Rotate the selected parts by 180 degrees 180 ডিগ্রি নির্বািচত পার্টস ঘুরান Rotate current selection 90 degrees counter clockwise 90 ডিগ্রি ক্লক ওয়াইজ বিপরিতে বর্তমান নির্বাচন ঘুরান Rotate current selection 45 degrees counter clockwise 45 ডিগ্রি ক্লক ওয়াইজ বিপরিতে বর্তমান নির্বাচন ঘুরান &Flip Horizontal পাশা পাশি উল্টান Flip current selection horizontally বর্তমান নির্বাচন পাশা পাি শ দিকে উল্টান &Flip Vertical খাড়া ভাবে উল্টান Flip current selection vertically বর্তমান নির্বাচন খাড়া দিকে উল্টান Bring to Front সম্মুখে আনুন Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer নিজেদের লেয়ারটিতে নির্বাচিত বস্তু (গুলি) সামনে আনতে Bring Forward এক ধাপ সামনে আনতে Ctrl+] Ctrl+] Bring selected object(s) forward in their layer নিজেদের লেয়ারটির মধ্যে নির্বাচিত বস্তু (গুলি) পেছিয়ে আনতে Send Backward পিছনে ফিরতে Ctrl+[ Ctrl+[ Send selected object(s) back in their layer পুনরায় লেয়ারের মধ্যে নির্বাচিত বস্তু (গুলি) পাঠান Send to Back পুনরায় পাঠান Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer পুনরায় লেয়ারের মধ্যে নির্বাচিত বস্তু (গুলি) পাঠান লেয়ারে আবার নির্বাচিত বস্তু (গুলি) পাঠান Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part অংশিক লক Prevent a part from being moved একটি করে অংশ আটকাতে পাঠানো হচ্ছে Sticky আঠালো If a "sticky" part is moved, parts on top of it are also moved আপনি যদি একটি "স্টিকি" অংশ স্থানান্তর করেন , এটা উপরে অংশের ও সরানো হয় Select All Locked Parts সব লক অংশ নির্বাচন Select all parts that can't be moved সকল পার্টস সরানো যাবে না নির্বাচন করুন Show/hide the label for the selected parts Find part in sketch... Search for parts in a sketch by matching text Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Show Code Ctrl+4 Ctrl+4 Show the code (programming) view &Show All Layers সকল স্তর প্রদর্শন Show all the available layers for the current view দৃশ্যমান প্রাপ্তিসাধ্য সব স্তর প্রদর্শন জন্য বর্তমান ভিউ &Hide All Layers সকল স্তর হাইড Hide all the layers of the current view সব লুকান স্তর দেখুন বর্তমান ভিউ Align Move to bottom layer Move to top layer top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards The folder "%1" isn't a Fritzing installation folder There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. &Show part label পার্ট লেভেল দেখুন Delete Minus Delete selection without attached wires Delete Wire up to bendpoints &Export... এবং রপ্তানি... Export selected part পার্ট রপ্তানির জন্য Add Bendpoint Bendpoint যোগ করুন Add a bendpoint to the selected wire সমস্ত নির্বাচিত তারের একটি bendpoint যোগ করুন Convert Bendpoint to Via Bendpoint মাধ্যমে রূপান্তরিত করুন Convert the bendpoint to a via বিন পয়েন্ট এর মধ্যেই রূপান্তর Convert Via to Bendpoint Bendpoint এর মাধ্যমে রূপান্তর করুন Convert the via to a bendpoint bendpoint মাধ্যমে একটাকে রূপান্তর করুন Straighten Curve বক্র সোজা Straighten the curve of the selected wire Select outdated parts মেয়াদোত্তীর্ণ যন্ত্রাংশ নির্বাচন Update selected parts নির্বাচিত যন্ত্রাংশ আপডেট Open programming window প্রোগ্রামিং উইনডো খুলুন Open microcontroller programming window মাইক্রো কন্ট্রোলার প্রোগ্রামিং উইনডো খুলুন &Zoom In এবং জুম ইন Ctrl++ Ctrl++ Zoom in জুম ইন Ctrl+= Ctrl+= &Zoom Out এবং জুম আউট Ctrl+- Ctrl+- Zoom out জুম আউট &Fit in Window এবং উইনডো তে স্তাপন Ctrl+0 Ctrl+0 Fit in window উইনডো তে স্তাপন &Actual Size এবং প্রকৃত মাপ Actual (real world physical) size প্রকৃত (বাস্তব বিশ্বের আসল) মাপ 100% Size মাপ 100% Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size 100% (পিক্সেল)মাপ Align to Grid গ্রিড অনুযায়ী সাজান Align items to grid when dragging গ্রিড অনুযায়ী আইটেম হলে টেনে নিয়ে সাজান Show Grid গ্রিডের প্রদর্শন Show the grid এই গ্রিডের প্রদর্শন Set Grid Size... গ্রিডের আকার ... Set the size of the grid in this view এই ভিউ গ্রিডের আকার সেট করতে Set Background Color... ব্যাকগ্রাউন্ড রং সেট Set the background color of this view এই ভিউ ব্যাকগ্রাউন্ড রং সেট করতে &Show Breadboard এবং ব্যাকগ্রাউন্ড প্রদর্শন. Ctrl+1 Ctrl+1 Show the breadboard view ব্রেডবোর্ড ভিউ দেখুন &Show Schematic এবং স্কেমেটিক প্রদর্শন Ctrl+2 Ctrl+2 Show the schematic view স্কেমেটিক ভিউ দেখুন &Show PCB এবং পি সি বি প্রদর্শন করুন Ctrl+3 Ctrl+3 Show the PCB view পি সি বি ভিউ দেখুন Show Parts Bin Icon View পার্টস বিন প্রদর্শন আইকন Display the parts bin in an icon view পার্টস চিেএর মত ভিউ প্রদর্শন Show Parts Bin List View তালিকা প্রদর্শন পার্টস বিন ভিউ Display the parts bin in a list view পার্টস বিন ভিউ তালিকায় প্রদর্শন &Minimize এবং মিনিমাইজ Ctrl+M Ctrl+M Minimize current window এই উইনডো মিনিমাইজ Debugger Output ডিবাগার আউটপুট Online Tutorials অনলাইন টিউটোরিয়াল Ctrl+? Ctrl+? Open Fritzing help ফ্রিটজিং সহায়তা ওপেন Donate to Fritzing Fritzing এ প্রদান করুন Open Fritzing donation web page Fritzing প্রদান এ ওয়েবপেইজ খুলুন Online Projects Gallery অনলাইন প্রজেক্টস গ্যালারী Open Fritzing examples Fritzing উদাহরণ খুলুন Online Parts Reference অনলাইন রেফারেন্স অংশগুলি Open Parts Reference পার্টস রেফারেন্স খুলুন First Time Help প্রাথমিক সহায়তা Check for updates... আপডেটের জন্য চেক করুন ... Check whether a newer version of Fritzing is available for download Fritzing থেকে ডাউন লোডের জন্য যা নেওয়া হয়েছে একটি নতুন সংস্করণ কিনা তা চেক &About এই সম্পর্কে Tips, Tricks and Shortcuts টিপস, ট্রিকস এবং শর্টকাট Display some handy Fritzing tips and tricks কিছু সহজ টিপস এবং ট্রিকস Fritzing প্রদর্শন &About Qt Qt সম্পর্কে Show Qt's about box Qt এর প্রদর্শন বক্স সম্পর্কে Report a bug... একটি বাগ রিপোর্ট করুন ... Report a but you've found in Fritzing যে রিপোর্ট করেছেন তা আপনি Fritzing এ খুঁজে পাবেন Enable debugging log ডিবাগিং লগ সক্রিয় করুন &Import parts and bins from old version... পুরোনো সংস্করণ থেকে যন্ত্রাংশ এবং বিন গুলি আমদানি করুন ... Import parts and bins from previous installation যন্ত্রাংশ এবং বিন ইনস্টলেশনের পূর্বে আমদানি করুন Parts Editor Help Display Parts Editor help in a browser &File ফাইল &Export রপ্তানি করুন as Image ইমেজ হিসাবে for Production জন্য উত্পাদন &Edit সম্পাদনা &Part যন্ত্রাংশ Raise and Lower বারিয়ে এবং কমিয়ে &View দেখতে প্রদর্শন &Window উইনডো &Routing রাউটিং Ground Fill গ্রাউনড ফিল &Help সহায়তা Delete Ratsnest Line Ratsnest লাইন মুছে দিন Delete Wire তার মুছেফেলা Hide part label হাইড পার্ট লেভেল Show part label Show part silkscreen Delete মুছুন Actual Size আসল সাইজ It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. মনিটর এর প্রকৃত মাপ সয়ংক্রিয় ভাবে বের করা মনে হয় সম্ভব না এই জন্য প্রকৃত মাপ আনুমানিক ধরে নেওয়া হয়েছে। ভালো বুদ্ধি হচ্ছে একটা রুলার ধরে বসান এবং তারপর একটা আসল রুলার এর সাথে মিলাতে থাকুন (লম্বায় টেনে টেনে) যতক্ষণ পর্যন্ত না মিলে। Page Setup পৃষ্ঠা সেটআপ Sorry, "%1" has not been implemented yet দুঃখিত, "% 1" এখনো বাস্তবায়িত হয়নি Shift+Ctrl+A Shift+Ctrl+A Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Set both copper layers clickable ক্লিকযোগ্য উভয় তামার স্তর নির্ধারণ করুন Shift+Ctrl+3 Shift+Ctrl+A Set copper top layer clickable উপরের স্তরে তামার ক্লিকযোগ্য নির্ধারণ Shift+Ctrl+2 Shift+Ctrl+2 Set copper bottom layer clickable নিচের স্তরে তামার ক্লিকযোগ্য নির্ধারণ Shift+Ctrl+1 Shift+Ctrl+1 &Create trace from ratsnest & Ratsnest থেকে ট্রেস তৈরি করুন Rotate 45� Clockwise 135° ক্লক ওয়াইজ ঘুরান {45�?} Rotate 90� Clockwise 135° ক্লক ওয়াইজ ঘুরান {90�?} Rotate 180� 180° ঘুরান {180�?} Rotate 90� Counter Clockwise 45° ক্লক ওয়াইজ বিপরিতে ঘুরান {90�?} Rotate 45� Counter Clockwise 45° ক্লক ওয়াইজ বিপরিতে ঘুরান {45�?} Display First Time Help Autoroute connections... Create a trace from the ratsnest line Ratsnest লাইন থেকে একটি ট্রেস তৈরি করুন &Create wire from ratsnest Ratsnest থেকে তার তৈরি করুন Create a wire from the ratsnest line Ratsnest লাইন থেকে একটি তার তৈরি করুন Do not autoroute স্বয়ংক্রিয় রুট হবে না When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board বোর্ডেটি অন্য দিকে সরান Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted আন রাউটেড প্রদর্শন Highlight all unrouted connectors সব আন রাউটেড সংযোগ গুলিকে হাইলাইট Select All Traces সব ট্রেস নির্বাচন করুন Select all trace wires সব তারের চিহ্ন নির্বাচন করুন Select All Wires সমস্ত তার নির্বাচন করুন Select all wires সব তারের নির্বাচন করুন Select All CopperFill সমস্ত কপার ফিল নির্বাচন করুন Select all copper fill items সব তামা ভরাট করা আইটেম নির্বাচন করুন Force Update Routing Status and Ratsnests ফোর্স আপডেট রাউটিং অবস্থা এবং Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces সমস্ত " Autoroute করবেন না" ট্রেস নির্বাচন করুন Select all trace wires excluded from autorouting সব ট্রেস থেকে autorouting বাদ তারগুলিকে নির্বাচন করুন Select All Autoroutable Traces সমস্ত Autoroutable ট্রেস নির্বাচন করুন Select all trace wires that can be changed during autorouting সব ট্রেস নির্বাচন তারগুলিকে যে autoroutingএর সময় পরিবর্তন করা যেতে পারে Select All Jumpers সমস্ত Jumpers নির্বাচন করুন Select all jumper item parts সমস্ত Jumpers আইটেম যন্ত্রাংশ নির্বাচন করুন Select All Vias সমস্ত Vias নির্বাচন করুন Select all via parts সমস্ত ভায়া যন্ত্রাংশ নির্বাচন করুন Tidy Wires পরিপাটি তারগুলি Tidy selected wires পরিপাটি নির্বাচিত তারগুলি Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill কপার ফিল Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill কপার ফিল সরাতে Remove the copper fill এই কপার ফিল সরাতে Choose Ground Fill Seed(s)... গ্রাউনড ফিল সীড গুলো পছন্দ করুন Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed গ্রাউন্ড ফিল সীড সেট করুন Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds গ্রাউন্ড ফিল সীড গুলো পরিষ্কার Clear ground fill seeds--enable copper fill only. সাফ ভূমি ভরাট বীজ - পূরণ করুন.সক্ষম গ্রাউন্ড ফিল সীড গুলো পরিষ্কার--শুধু তামার ফিল সক্রিয় Shift+Ctrl+D Shift+Ctrl+D Check Loaded Traces লোড ট্রেস চেক করুন Copper Top and Copper Bottom layers are both active উপরের তামা এবং নীচের তামাস্তর উভয় সক্রিয় Copper Top layer is active উপরের তামার স্তর সক্রিয় Copper Bottom layer is active নিচের তামার লেয়ার সক্রিয় Order a PCB... একটি PCB অর্ডার ... Order a PCB created from your sketch--from fabulous Fritzing Fab আপনার স্কেচ তৈরির একটি PCB অর্ডার করুন -- কল্পিত Fritzing Fab থেকে Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. আপনার স্কেচ এখনো এর কোন বোর্ড হইনি! অটোরুট ব্যাবহার করতে একটি পি সি বি সংযুক্ত করুন Please select the board you want to autoroute. The autorouter can only handle one board at a time. আনুগ্রহ করে অটোরুট করতে বোর্ড নির্বাচন করুন অটোরুট একই সময়ে একটি বোর্ড পরিচালনা করতে পারবে Autorouting... স্বয়ংক্রিয় রাউটিং ... Autorouting Progress... Autorouting অগ্রগতি... jumpers জাম্পারস copperfill কপার ফিল vias vias Remove Bendpoint বিন পয়েন্ট সরিয়ে ফেলুন Please choose the previous Fritzing folder... আগে ফ্রিটজিং ফোল্ডার বাছাই করুন ... You will have to restart Fritzing in order to use the imported parts আপনি Fritzing করার জন্য আমদানিকৃত পার্টস ব্যবহার করে পুনরায় আরম্ভ করুন Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. তমার বরদে কন স্কেছ নাই প সি বি করার অন্ন দয়া করে আক্তি তামা জুক্ত গ্রুন্দ ফিল্ল বেবহার ক্রুরুন আপনার বোর্ডে কোনো স্কেচ নাই !পি সি বি করার জন্য দয়া করে একটি তামার যুক্ত গ্রাউনড ফিল ব্যবহার করুন Please select a PCB--copper fill only works for one board at a time. নির্বাচিত পি সি বি -- একটি বোর্ডের জন্য কপার ফিল একই সাথে কাজ করবে Generating %1 fill... ফিল জেনারেট করুন %1... ground গ্রাউন্ড copper কপার Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. আপনার তৈরি নকশা করা বোর্ডটিএখনো হয়নি? দয়া করে কপার ফাইলে নতুন একটি পি সি বি স্তাপন করুন Please select a PCB--ground fill operations only work on a one board at a time. দয়া করে একটা PCB নির্বাচন করুন -- ground fil কাজকর্ম শুধু এক বোর্ডে একই সাথে. কাজ করবে . Remove copper fill কপার ফিল সরাতে &Wire Color এবং তারের রং Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Launch %1... আরম্ভ করুন %1... No outdated parts found. All your parts are up-to-date. কোন মেয়াদোত্তীর্ণ পার্টস খুঁজে পাওয়া যায়নি. আপনার সমস্ত পার্টস আপ টু ডেট. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Outdated parts মেয়াদ উত্তীর্ণ যন্ত্রাংশ Do you want to update now? unable to find replacement for %1. খুঁজে পেতে অসমর্থ হলে বদল করার জন্য খোজ করুন Update %1 part(s) যন্ত্রাংশ (গুলি) আপডেট%1 Successfully updated %1 part(s). Please check all views for potential side-effects. যন্ত্রাংশ (গুলি)সফলভাবে আপডেট %1. সম্ভাব্য পার্শ্ব প্রতিক্রিয়া জন্য সব মতামত দয়া করে চেক করুন. OK ঠিক Set the grid size for %1. % 1 গ্রিডের মাপ নির্ধারণ করার জন্য Grid Size: গ্রিডের আকারঃ in প্রবেশ ইন mm মি মি Restore Default ডিফল্ট পুনঃ স্থাপন Your sketch does not have a board yet! DRC only works with a PCB. আপনার তৈরি নকশা করা বোর্ডটিএখনো হয়নি? দয়া করে পাথানর জন্য একটিPCB যোগ করতে পারেন Please select a PCB. DRC only works on one board at a time. কাজের করতে একটি পি সি বি ও কপার ফাইল নির্বাচন করুনএই বোর্ডের জন্য DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. আপনার তৈরি নকশা করা বোর্ডটিএখনো হয়নি? দয়া করে পাথানর জন্য একটিPCB যোগ করতে পারেন Please select a PCB. Copper fill operations only work on one board at a time. একটি পি সি বি করুন।তামা ভরাট অপারেশান কেবল একটি বোর্ড এ একটি সমায় এর কাজ এই বোর্ডে কাজ করতে একটি পি সি বি ও কপার ফাইল নির্বাচন করুন MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: রাউন্ড %1অফঃ Routing stopped! Use best so far... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org Optimizing traces... ModelBase Unable to find the following %n part(s): নিম্নলিখিত%n পার্টস গুলিকে খুঁজে পাওয়া যায়নি: at এতে File save failed! ফাইল সংরক্ষনে বার্থ Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ফাইল মুছে ফেলা জা MysteryPart label স্তর chip label চিপ স্তর NetLabel net label Note [write your note here] আপনার লেখাটা এই খানে লিখুন [এখানে আপনার নোট লিখুন] PCBSketchWidget Create Trace from Ratsnest Ratsnest থেকে ট্রেস তৈরি Fritzing Fritzing ফ্রিটজিং Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. আপনার তৈরি নকশা করা বোর্ডটিএখনো হয়নি? দয়া করে পাথানর জন্য একটিPCB যোগ করতে পারেন Please click on a PCB first--this selection operation only works for one board at a time. কাজের করতে একটি পি সি বি ও কপার ফাইল নির্বাচন করুনএই বোর্ডের জন্য Click this connector to drag out a new trace. Change trace layer ট্রেস স্তর পি সি বি পরিবর্তন Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground গ্রাউন্ড Copper কপার Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part এই হল যেখানে আপনি সংযোগকারী মেটাডাটা সম্পাদনকরুন অংশ এর জন্য আপনার সংযুক্ত তার ও পার্ট সমুহ সম্পাদন number of connectors: সংযোগকারি নম্বর সনযুক্ত নাম্বার Through-hole SMD PEMainWindow SVG SVG Connectors কানেক্টরস Show in Folder ফোল্ডার দেখতে On the desktop, open the folder containing the current svg file. ডেক্সটপ অন করুন,বর্তমান ফোল্ডার svgফাইল সংযোগ করুন Parts Editor পার্টস এডিটর Unable to write svg to %1 svg হতে লেখা বন্ধ %1 Unable to parse fzp file %1 fzpফাইল হতে প্রিন্ট বন্ধ %1 Icon View আইকন ভিউ Metadata View মেটাডেটা ভিউ Connectors View কানেক্টরস ভিউ Show Icon আইকন দেখুন Ctrl+4 Ctrl+4 Show the icon view আইকন ভিউ দেখুন Ctrl+5 Ctrl+5 Show the metadata view মেটাডেটা ভিউ দেখুন Show Connectors কানেক্টরস দেখুন Ctrl+6 Ctrl+6 Change description বর্ণনা পরিবর্তন%1 Change %1 to '%2' পরিবর্তন করতে %1to%2 Change tags ট্যাগ পরিবর্তন Change properties জায়গা পরিবর্তন Change connector %1 কানেক্টরস পরিবর্তন করতে%1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) ইমেজ এবং ফটোপ্রিন্ট ফাইল (%1 %2 %3 %4 %5);;SVG ফাইল (%1);;JPEG ফাইল (%2);;PNG ফাইল (%3);;gEDA ফটোপ্রিন্ট ফাইল (%4);;Kicad মডিউল ফাইল (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 ইমেজ ফাইল (%1 %2 %3);;SVG ফাইল(%1);;JPEG ফাইল (%2);;PNG ফাইল (%3)%4%5 Open Image ইমেজ খুলুন Copy problem কপিতে সমস্যা Unable to make a local copy of: '%1' লোকাল কপি করা অসম্ভব '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- JPGএবং PNG বিটম্যাপ ইমেজ চরিত্র বজায় রাখে,যখন কমে আসবে তখন ভাল দেখাবে না -- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Fritzing পার্টস স্থানধারক হিসাবে আমাদের জন্য শ্রেষ্ঠ শুধুমাত্র JPGএবং PNG ব্যবহার. Use of PNG and JPG discouraged JPG, PNG এবং ব্যবহার বাঞ্ছনীয় Conversion problem সমস্যার পরিবর্তন SVG problem SVG সমস্যা Unable to parse '%1': %2 line:%3 column:%4 প্রেস করা অসম্ভবঃ'%1': %2 লাইনঃ%3 কলামঃ%4 There are no copper layers defined in: %1. এতে কোন কপার লেয়ার পাওয়া যায়নাই %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. এখানে দেখুন <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">বিস্তারিত আছে </a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>এতে সমস্যা নাই পরবর্তী রিলিজে এডিটর সমস্যার সৃষ্টি হতে পারে,' but for now please modify the file according to the instructions in the link. no schematics found in %1 এতে স্কেমেটিক'স পাচ্ছে না %1 schematic part স্কেমেটিক অংশ no footprints found in %1 এতে ফটোপ্রিন্ট পাচ্ছে না %1 Relocate connector %1 সংযোগ পুনরায় দেখতে %1 &File ফাইল There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon আইকন Metadata Inspector পরিদর্শক Layers স্তর সমূহ Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export রপ্তানি করুন &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning স্কেচ পরিবর্তন সংকেত The open sketch '%1' uses the part you are editing. খুলুন স্কেচ '% 1' অংশ হয় তাহলে সম্পাদিত ব্যবহার করা. ' সম্পাদিত যন্ত্রাংশ ব্যবহার করে একটি স্কেচ খুলুন '%1' Saving this part will make a change to the sketch that cannot be undone. The open sketches এই নকশাগুলি খুলতে '%1', '%1', and '%1' এবং '%1' Saving this part will make a change to these sketches that cannot be undone. এই অংশ সংরক্ষণ করুন স্কেস পরিবর্তনের পর তা পূর্বাবস্তায় আনা যাবে না Go ahead and save? এগিয়ে জান সঞ্চয় Save সঞ্চয় Cancel বাতিল Move terminal point মুল পয়েন্ট সরাতে Remove connector কানেক্টরস সরিয়ে ফেলা Remove %1 connectors কানেক্টরস সরিয়ে ফেলতে %1 Save "%1" সঞ্চয় %1 Do you want to save the changes you made in the part "%1"? আপনি কি পরিবর্তিত আবস্তায় তৈরি অংশ সঞ্চয় করতে চান"%1"? Your changes will be lost if you don't save them. আপনার পরিবর্তিত অংশ মুছে গেছে সঞ্চয় সম্ভব নয় untitled part বেনামী যন্ত্র Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector কানেক্টর যুক্ত Add %1 connectors কানেক্টরস যুক্ত করতে%1 Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... পার্টসটি কোথায় সংযোগ করতে চান Set the part's title পার্টসের ধরন নির্ণয় Title ধরন Set the part's date পার্টসের তারিখ নির্ণয় Date তারিখ Set the part's author আনুমদিত পার্টস নির্ণয় Author আনুমদন Set the part's description--you can use simple html (as defined by Qt's Rich Text) সাধারন html ব্যবহার করে পার্টসের ব্যখা নির্ণয় (খোজ করুন qt's Rich Text) Description বর্ণনা Set the default part label prefix ত্রুটি জুক্ত স্তর অংশ পুনঃ নির্ধারণ Label স্তর Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to একই ধরনের কি পার্টস নির্ণয় Family ধরন Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties পার্টসের জায়গা নির্ধারণ Properties জায়গা Set the part's tags পার্টস একত্রিত করা Tags নির্ধারণ PESvgView width: প্রস্ত height: উচ্চতা PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center কেন্দ্র N N E E S S W W center কেন্দ্র west পশ্চিম north উত্তর south দক্ষিন east পূর্ব Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 সংযোগকারী %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape রুপদানকারি আকৃতি center কেন্দ্র north উত্তর east পূর্ব south দক্ষিন west পশ্চিম connect to সংযোগ করতে সংযোগ করা PaletteItem Edit Pin Labels পিন লেবেল সপ্পাদনা করুন পিন লেভেল নির্ধারণ Fritzing Fritzing ফ্রিটজিং Unable to proceed; unable to find top level view. এগিেয় যেতে অক্ষম,উপরে স্তর দৃশ্য খুজে পেতে অসমর্থ Unable to proceed; part connectors do no have standard IDs. এগিেয় যেতে অক্ষম ,সংযোগকারী অংশ কোন আই ডি এস Label mismatch. Nothing was saved. লেবেল মিলেনি কিছু সঞ্চিত ছিল না hole size গর্ত আকার ছিদ্র আকার advanced settings উচ্চ পরজায়ার সেটিংস্‌ আগ্রিম সংযুক্তি in মধ্যে ইন mm এম এম মি মি Hole Diameter গর্ত ব্যাস Ring Thickness রিং এর ঘনত্ব PartLabel Edit এডিট Edit label text এডিট টেক্সট লেভেল Hide হাইড Hide part label হাইড পার্ট লেভেল Display Values মানের প্রদর্শন Flip/Rotate সরানো/ঘুরানো Font Size ফন্ট সাইজ Rotate the label by 45 degrees clockwise 45 ডিগ্রি ক্লক ওয়াইজ লেভেল ঘুরান Rotate the label by 90 degrees clockwise 90 ডিগ্রি ক্লক ওয়াইজ লেভেেল ঘুরান Rotate the label by 135 degrees clockwise 135 ডিগ্রি ক্লক ওয়াইজ লেভেেল ঘুরান Rotate the label by 180 degrees 180 ডিগ্রি লেভেলে ঘুরান Rotate the label by 135 degrees counter clockwise 135° ক্লক ওয়াইজ বিপরিতে লেভেল ঘুরান Rotate current selection 90 degrees counter clockwise 90 ডিগ্রি ক্লক ওয়াইজ বিপরিতে ঘুরা নির্বাচন Rotate 45� Clockwise 135° ক্লক ওয়াইজ ঘুরান {45�?} Rotate 90� Clockwise 135° ক্লক ওয়াইজ ঘুরান {90�?} Rotate 135� Clockwise 135° ক্লক ওয়াইজ ঘুরান {135�?} Rotate 180� 180° ঘুরান {180�?} Rotate 135� Counter Clockwise 45° ক্লক ওয়াইজ বিপরিতে ঘুরান {135�?} Rotate 90� Counter Clockwise 45° ক্লক ওয়াইজ বিপরিতে ঘুরান {90�?} Rotate 45� Counter Clockwise 45° ক্লক ওয়াইজ বিপরিতে ঘুরান {45�?} Rotate the label by 45 degrees counter clockwise 45 ডিগ্রি ক্লক ওয়াইজ বিপরিতে লেভেল ঘুরান Flip Horizontal Flip label horizontally পাশা পাি শ দিকে সরানো Flip Vertical খাড়া দিকে সরাতে Flip label vertically খাড়া দিকে লেভেল সরাতে Tiny টাইনী Set font size to tiny টাইনীতে ফ্রন্ট সাইজ সেট Small ছোট Set font size to small সেট ছোট সাইজ ফ্রন্ট Medium মধ্যম Set font size to medium সেট বড় সাইজ ফ্রন্ট Large বড় Set font size to large সেট সব থেকে বর সাইজ ফ্রন্ট Label text টেক্সট লেভেল Display the text of the label টেক্সট লেভেল প্রদর্শন Display the value of property %1 জায়গার মান প্রদর্শন %1 Set label for %1 লেভেল সেটের জন্য %1 Label text: টেক্সট লেভেল PartsBinPaletteWidget Untitled Bin বেনামী বিন Specify a file name একটি ফাইলের নাম উল্লেখ Fritzing Bin (*%1) ফ্রিটজিং বিন t(*%1) Fritzing ফ্রিটজিং Cannot find file %1. ফাইল খুজে পাচ্ছে না %1. Cannot read file %1: %2. ফাইলটি পড়তে পারচ্ছে না %1:%2 Loading... লোডিং... loading bin '%1' লোডিং বিন %1 Save bin "%1" সঞ্চয় বিন বক্স Do you want to save the changes you made in the bin "%1"? আপনি কি পরিবর্তন বিন তৈরি "% 1" সংরক্ষণ করতে চান? Your changes will be lost if you don't save them. আপনার পরিবর্তনগুলি হারিয়ে যাবে যদি তাদের সংরক্ষণ না করেন Save সঞ্চয় Don't Save সঞ্চয় প্রয়োজন নাই Ctrl+D Ctrl+D Cancel বাতিল Add to bin বিন যুক্ত করুন Do you really want to add the selected part to the bin? আপনি কি সত্যিই বিনে নির্বাচিত অংশ যোগ করতে চান? Change icon color... আইকন রঙ পরিবর্তন করুন... Change the color of the icon for this bin. এই বিন জন্য আইকনের রঙ পরিবর্তন করুন. Select a color for this icon এই আইকনের জন্য একটি রং নির্বাচন করুন Perfboard size আকার set board size বোর্ড আকার সেট Performance Warning কর্মক্ষমতা সতর্কতা কর্মক্ষম সতর্কতা Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. perfboards এবং stripboardsএর কার্যকারিতা ধীর। তুমিকি নিশ্চিত? 2000 গর্তের বেশি আরও আছে। নোট: এই অধিবেশনের সাবধান বাণীটি সময় উপযোগী। Set new size নতুন আকার সেট Cancel বাতিল rows সারি columns কলাম PinLabelDialog <p><h2>Pin Label Editor</h2></p> <P><H2>পিন লাবেল সম্পাদক </h2></p> <p>Click on a label next to a pin number to rename that pin. <P>একটি লাবেল এর ওপর ক্লিক করুন পরবর্তী একটি পিনযে পিন নতুন নামকরন করা You can use the tab key to move through the labels in order.</p> আপনি লাবেল মাধ্যম সরাতে ট্যাব কী ব্যবহার করতেপারেন </P> Cancel বাতিল Save রক্ষা সঞ্চয় Undo আগেরমত করুন Redo পুনরায় করা আবার করুন PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel বাতিল OK ঠিক Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings সেটিংস পরিষ্কার Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New নতুন টি Save সঞ্চয় Open Platform Board বোর্ড Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit এডিট Undo আগের মত করুন Redo আবার করুন &Cut কাট Cut selection কাটতে নির্বাচন &Copy কপি Copy selection কপি নির্বাচন &Paste পেস্ট Paste clipboard contents পেস্ট ক্লিপ বোর্ড উদৃিত &Select All সব নির্বাচন Select all text সকল টেক্সট নির্বাচন &Preferences... ও পছন্দসমূহ ... Show the application's about box আবেদন এর সম্পর্কে বক্স দেখান &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board বোর্ড Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 %1%2 {1%2?} &View প্রদর্শন File '%1' was restored from the .fzz file; the local copy was not found. ফাইল '% 1' fzz ফাইল থেকে পুনরুদ্ধার করা হয়েছিল;লোকাল কপি পাওয়া যায়নি File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ফাইল '% 1' fzz ফাইল থেকে পুনরুদ্ধার করা হয়েছিল; কোন বহিস্থিত এডিটার দিয়ে কাজ করতে লোকাল কপি করে সেভ করুন. QObject Fritzing ফ্রিটজিং Cannot autoroute: no board (or multiple boards) found Autoroute করতে পারে না: কোন বোর্ড ( বা একাধিকবোর্ড) পাওয়া যায়নি No connections (on the PCB) to route. সংযোগ রাস্তা.নেই পি সি বি তে No connections to route. সংযোগ রাস্তা নেই. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. % 1% 2 তারগুলিকে তাদের মধ্যে সংরক্ষিত স্থান থেকে সরানো হয়েছে. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Set Ground Fill Seed গ্রাউনড ফিল সীড সেট করুন Ground Fill Seed Editor গ্রাউনড ফিল সীড এডিটর Pin Label Editor পিন লেবেল এডিটর Preferences পছন্দ Please note that a new language setting will not take effect until the next time you run Fritzing. যে একটি নতুন ভাষা সেটিং পরবর্তী সময় আপনি Fritzing করেন পর্যন্ত প্রভাব গ্রহণ করব না দয়া করে নোট করুন. Connected highlight color সংযুক্ত রং হাইলাইট করতে Unconnected highlight color অসম্পৃক্ত রং হাইলাইট করাতে Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! এই পদক্ষেপ এর জন্য কোন পূর্বাবস্থায় ফেরাতে, এবং আরও সতর্কীকরণ! Clear Settings সেটিংস পরিষ্কার <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> Edit link লিংক সম্পাদন mm মিমি in ইন The file '%1' is read-only; please use a different filename. ফাইল '% 1' হল শুধুমাত্র পাঠযোগ্য; একটি ভিন্ন ফাইলের ব্যবহার করুন. Part যন্ত্র Wire তার Set Grid Size গ্রিডের আকার সেট Cannot read file %1: %2. ফাইলটি পড়তে পারচ্ছে না %1: %2 Parse error (1) at line %1, column %2: %3 %4 ত্রুটি বিশ্লেষণ করতে (1) লাইন %1, কলাম% 2: % 3 4% The file %1 is not a Fritzing file (2). ফাইল %1 এটি Fritzing ফাইল নয় (2)। The file %1 is not a Fritzing file (4). ফাইল %1 এটি Fritzing ফাইল নয় (4)। The file %1 is not a Fritzing file (3). ফাইল %1 এটি Fritzing ফাইল নয় (3)। Cannot write file temp: %1 %2 %3. Temp ফাইলটি লিখতে পারে না: % 1 % 2 % 3. Parts folder not found. পার্টস ফোল্ডার পাওয়া যায়নি No parts found. কোন পোর্ট পাওয়া যায়নি Parse error (2) at line %1, column %2: %3 %4 এ ত্রুটির বিশ্লেষণ করতে (2) লাইন %1, কলাম %2 2: % 3 4% The part '%1' at '%2' does not have a unique module id '%3'. এ অংশে '% 1' '% 2' একটি অনন্য মডিউল আইডি '% 3' নেই. Basic প্রাথমিক Input ইনপুট Output আউটপুট ICs IC Power Pawer Connection সংযোগ Microcontroller মাইক্রো কন্ট্রোলার Breadboard View ব্রেডবোর্ড ভিউ Schematic View স্কেমেটিক ভিউ দেখুন PCB View পি সি বি ভিউ দেখুন Tools সরঞ্জাম Shields সিলডস্ LilyPad লিলি প্যাড Other অন্যান্য Sensors সংবেদনশীল Part already in bin এই বিনে যন্ত্র The part that you have just added, is already there, we won't add it again, right? আবার যুক্ত করাই সঠিক? শুধু আপনি ঐ অংশ যোগ করুন a label একটি স্তর a value একটি মান Select %1 নির্বাচন করুন %1 ii ii Icon View আইকন ভিউ Internal Connections <b>id:</b> <b>আইডিঃ</b> <b>Name:</b> <b>নামঃ</b> Set the connectors's title পার্টসের ধরন নির্ণয় <b>type:</b> <b>Description:</b> <b>বর্ণনাঃ</b> Set the connectors's description সংযোগকারী এর বিবরণ সেট files ফাইল গুলি Oops! হায়! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. আমরা দুঃখিত, সোয়াপিং ব্যবস্থায় একটা সমস্যা আছে. Fritzing এখনও কাজ করছে, কিন্তু আপনি যন্ত্রাংশ বৈশিষ্ট্য পরিবর্তন করতে পারবেন না. bb ব্রেড বোর্ড pcb পি সি বি Select all 'Don't autoroute' traces 'অটো রাওউট হবে না' সকল ট্রেস নির্বাচন করুন Select all autorouteable traces সকল 'autoroute' ট্রেস নির্বাচন করুন Select all %1 সব নির্বাচন করুন Convert to Via এর মাধ্যমে রূপান্তর Convert Via to Bendpoint বিন পয়েন্ট এর মধইয় রূপান্তর schem স্কেম Error reading file %1: %2. ত্রুটি ফাইলটি পড়া %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 লোগো পরিবর্তনে %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer %1 স্তর Bring forward এক ধাপ সামনে Send backward পিছনে ফিরতে Bring to front সম্মুখে আনুন Split Wire বিভক্ত তার Join Wire সংযোগ তার Trace wires তারের ট্রেস Ratsnest wires Ratsnest তার গুলি Select outdated parts মেয়াদোত্তীর্ণ যন্ত্রাংশ নির্বাচন Select locked parts লক যন্ত্রাংশ নির্বাচন করুন unable to open %1 খুলতে অক্ষম %1 unable to parse %1 প্রিন্ট হতে অক্ষম %1 parse failure in %1 এই প্রিন্ট ব্যার্থ %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) দুঃখিত, এখনো Fritzing উভয় পিনের এবং প্যাড হ্যান্ডেল (এর মধ্যে% 1) করতে পারছে না bad pin argument count উল্লেখ্য পিন সংখ্যা ত্রুটিযুক্ত bad pad argument count উল্লেখ্য প্যাড সংখ্যা ত্রুটিযুক্ত Unable to parse copper: %1 %2 %3 % 1% 2% 3: তামা বিশ্লেষণ করতে অক্ষম outline is empty সীমারেখা খালি আছে the board outline layer, বোর্ড স্তর সীমারেখা,' silkscreen layer(s), silkscreen লেয়ার গুলি copper layer(s), তামার স্তর গুলি mask layer(s), মাস্ক লেয়ার গুলি paste mask layer(s), পেস্ট মাস্ক লেয়ার গুলি Unable to translate svg curves in %1 %1 SVG রেখাচিত্র অনুবাদ করতে অক্ষম %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure সিল্ক রপ্তানি ব্যর্থ %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure ড্রিল রপ্তানি ব্যর্থ %1 mask export failure (2) %1 মাস্ক রপ্তানি ব্যর্থ (2) mask export failure মাস্ক রপ্তানি ব্যর্থ Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. footprint %1 not found in %2 পদচিহ্ন%1 পাওয়া যায়নি %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... ফাইলের অগ্রগতি... Copying file %1 ফাইল কপি হচ্ছে File %1 already exists: it won't be overwritten Check for updates আপডেটের জন্য চেক করুন Icon আইকন Breadboard ব্রেডবোর্ড Parts যন্ত্রাংশ Wires তার সমূহ Part Labels পার্ট স্তর Ratsnest Notes নোটস্ Rulers রুলারস Frame ফার্ম Text Board বোর্ড Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image ইমেজ অংশ Unknown Layer নামহিন লেয়ার icon view আইকন ভিউ breadboard view ব্রেডবোর্ড ভিউ schematic view স্কেমেটিক ভিউ দেখুন pcb view পি সি বি ভিউ দেখুন Autorouter Settings Part %1 '%2' Fritzing cannot load the parts bin Set all to: Pad N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File ফাইল Last backup সর্বশেষ ব্যাকআপ Last saved সর্বশেষ সংরক্ষণ file not saved ফাইল সংরক্ষণ হয় নি <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover ও পুন্নরুদ্ধার &Ignore ও উপেক্ষা করা Resistor Resistor রোধ resistance প্রতি রোধক You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape আকৃতি width: %1mm প্রস্থঃ%১ মিলি মিটার height: %1mm উচ্চতাঃ%১মিলি মিটার width(mm) প্রস্ত(মিলিমিটার) height(mm) উচ্চতা (মিলিমিটার) keep aspect ratio Revert পিছনে ফিরে প্রত্যাবর্তন size custom বিধি A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width প্রস্থ প্রশস্ততা S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project প্রোজেক্ট Filename ফাইলের নাম Date তারিখ Sheet পাতা সিট Rev আবার shape of অফ এর date তারিখ টি sheet পাতা সিট SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 ভোল্টেজ পরিবর্তন আন্তে %1 টু %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color %1এটা ডিফল্ট করা রং Cancel বাতিল OK ঠিক Pick custom %1 color Current color (%1) SketchWidget loading part যন্ত্র লোডিং done loading লোড শেষ লোড সম্পন্ন Delete ratsnest ratsnest মুছেফেলা ratsnestমুছতে %1 %2 %1%2 %1 %2 items items%1%2 আইটেম %1%2 Select All সব নির্বাচন সব নির্বাচন করুন Deselect অনির্বাচন Add %1 যুক্ত%1 যোগ করুন %1 Selection নির্বাচন বাছাই Move %2 (%1) স্থানান্তর করা %2(%1) Move %2 items (%1) স্থানান্তর করা%2 items(%1) Select %1 নির্বাচন করুন %1 Select %1 items নির্বাচন করুন%1 items Disconnect সংযোগ বিচসিন্ন করা from %1 হইতে%1 হতে%1 Move leg of লেগ সরাতে Connect যুক্ত করা সংযোগ to %1 to%1 কর %1 Change leg curvature for %1. লেগ বক্রতা পরিবর্তনের জন্য%1 Change leg bendpoint for %1. লেগ পরিবর্তন জন্য বিন পয়েন্ট%1 Change পরিবর্তন Create and connect wire এবং তারের সাথেসংযোগ তৈরি করতে Fritzing ফ্রিটজিং This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. মনে হয় layeerজুড়ে ট্রেসতৈরি করতে এই circulamstanceআবশ্যক।কোন developper সাথে যোগাযোগ করুন. Create and connect %1 সাথেসংযোগ তৈরি করতে এবং সংযোগ তৈরি করতে %1 wire তার wire trace গমনপথ ট্রেস Rotate %2 (%1) আবর্তিত%2 (%1) Flip %2 (%1) Flip%2(%1) Double-click দুইবার ক্লিক করুন Drag or double-click টানুন বা দুইবার ক্লিক করুন or alt-drag to move the segment বা বিকল্প সেগমেন্ট টি সরানোর জন্য Double-click to delete this bend point এই বিন পয়েন্ট মুছতে দুইবার ক্লিক করুন Note text change টেক্সট পরিবর্তনতি নোট করুন Change %1 label to '%2' লেভেল পরিবর্তন করতে%1%2 Change %1 color from %2 to %3 %1 রঙ পরিবর্তনের জন্য %2 থেকে %3 Change color of %1 wires to %2 %1 তারের রঙ পরিবর্তনের জন্য%2 Change %1 width from %2 to %3 %1 প্রস্থ পরিবর্তনের জন্য %2 থেকে %3 Change width of %1 wires to %2 তারের প্রস্থ পরিবর্তনের জন্য %1থেকে%2 Move label '%1' লেভেলটি সরাতে %1 %1 label '%2' %1লেভেলটি%2 Rotate চক্রাকার Flip ফ্লীপ টোকা show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 এবং মাপকাঠি পুনরায় আকার দিন %1 %2 Resize board to %1 %2 বোর্ড পুনরায় আকার দিন %1%2 Part '%1' not found in sketch Add %1 parts Deselect all test connectors Resize Note নোট পুনঃমাপ Change Resistance from %1 to %2 রেজিস্টেনস পরিবর্তন করতে %1থেকে%2 Change %1 from %2 to %3 %1পরিবর্তনের জন্য %2 থেকে %3 Create wire from Ratsnest তারের Ratsnest তৈরি করতে Disconnect all wires from %1 সকল তারের সংযোগ বিচসিন্ন করতে%1 Disconnect all wires from %1 items সকল তারের সংযোগ বিচসিন্ন করতে%1 আইটেম Change image from %1 to %2 ইমেজ পরিবর্তনের জন্য%1থেকে%2 change pin labels পিন লেবেল পরিবর্তন Unrouted connections are highlighted in yellow. Unrouted connections are highlighted in yellow. Unrouted সংযোগটি উজ্জল হলুদ করা থাকে। There are no unrouted connections এখানে কোন unrouted সংযোগ নাই Unrouted connections Unrouted সংযোগটি %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. % নোটঃএছাড়া এই ডিসপ্লে দ্বারা mousingঅবস্থায় বারের নিচে আপনি ststus বারে রাউটিং ststus লেখা আরম্ভ করতে পারেন SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored পুনঃ স্থাপন Cut কাটা %1 %n strip(s) %১%n কাঠী (s) rows সারি columns কলাম %1 layout SymbolPaletteItem voltage ভোল্টেজ label স্তর Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks টিপস এবং ট্রিকস Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 নিচে নামান এবং যে কোন মান টাইপের জন্য %1 to %2 width প্রস্ত TranslatorListModel English - %1 ইংলিশ - %1 French - %1 ফ্রান্স - %1 German - %1 জার্মান - %1 Spanish - %1 স্পেনিশ - %1 Japanese - %1 জাপানিস - %1 Portuguese (European)- %1 পরতুগিস(ইউরপিয়ান) - %1 Portuguese (Brazilian) - %1 পরতুগিস(ব্রাজিলিয়ান) - %1 Hungarian - %1 হাঙ্গেরিয়ান - %1 Estonian - %1 ইস্তনিয়ান - %1 Dutch - %1 ডাচ্ - %1 Danish - %1 Russian - %1 রাশিয়ান - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 ইতালিয়ান - %1 Hebrew - %1 হিব্রুই - %1 Arabic - %1 এ্যরাবিক - %1 Hindi - %1 হিন্দি - %1 Chinese (Simplified) - %1 চাইনিজ (সিমপ্লিফাইড) - %1 Chinese (Traditional) - %1 চাইনিজ (ট্রেডীসনাল) - %1 Polish - %1 পলিস - %1 Czech - %1 চেেজছ - %1 Turkish - %1 তুর্কিস - %1 Swedish - %1 সুইডিস - %1 Romanian - %1 রোমানিয়ান - % Thai - %1 থাই - % Greek - %1 গ্রীক - % Bulgarian - %1 বুলগেরিয়ান - %1 Galician - %1 জেলিশিয়ান - %1 Korean - %1 কোরিয়ান - %1 Indonesian - %1 ইন্দোনিসিয়ান - %1 Slovak - %1 স্লোভক %1 Bengali - %1 বেঙ্গলী - %1 UpdateDialog Close বন্ধ কর No new versions found. কোন নতুন সংস্করন পাওয়া যায়নি A new main release is available for downloading: খুজে পাওয়া উপযুক্ত নতুন টি ডাউন লোডঃ A new interim release is available for downloading: খুজে পাওয়া উপযুক্ত নতুন টি অন্তর্বর্তী কালীন ডাউনলোডঃ Checking... পরীক্ষণ... Sorry, unable to retrieve update info সাম্প্রতিকীকরন তথ্য আহরন করতে দুঃখিত, অক্ষম দুঃখিত ,সাম্প্রতিক তথ্য আহরন করতে অক্ষম WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) সুপার ফাইন (৮মি) সুপারফাইন(8mil) extra thin (12 mil) অতিরিক্ত পাতলা (১২মিলি) অতিরিক্তপাতলা(12mil) thin (16 mil) পাতলা (১৬মিলি) পাতলা(16mil) standard (24 mil) মান(৩২মিলি) মান(24mil) thick (32 mil) পুরু (৩২মিিল) পুরু(32mil) extra thick (48 mil) অতিরিক্ত পুরু (৪৮) অতিরিক্তপুরু(48mil) blue নীল red লাল black কালো yellow হলুদ green সবুজ grey ধুসর white সাদা orange কমলা ochre cyan brown বাদামী purple রক্তবর্ণ রক্তবর্ণ pink color রঙ্গিন রং Banded ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_cs.qm000066400000000000000000003245511250202676700217200ustar00rootroot0000000000000023m"BxY 1įį8į)/CwHEf֍FH5DpSHu|JdeDeKzܤaܤz U# es5Ln.U!"*yQ~*y#H*S*H*#*%TH*%*0Uo+hW+'+X+Y7+[+$,BFW,Df-txFdQ7H*IX!LIX$IX*2J6PKQ}M51P,EVPW2RUgRxR Uj3VgQ3V+V7V3Wm90XYsYfZ8, [f3(#[f3G]4(n^I_C{`BbpL cQge0Ai'ijcb&jcbEqjcbjeCjɢEk-mNnrx?rx|Jt/ui uiwmHye&RyeJyeN9ye;yedyeg"yJygRzl7zl`{ %KJ{zv{z}}e}}|UP 35Jd5cLR0 _^G@~W$"',Fd-̛>g.[?$q V#R[:\ G"b3)t){d}*Q#*k2"4T69)?yZPJvg,L#-L4wyTZae>\TeچqW?r{(ylN85E` ,_7P.juU rk(]N\.3LLR͌Ӓ2o2.uW_+LvpZ1U &WM44SBɢC>DIQ˯RԢmYXBYYCmYZClTRqBt+tuTu5]uT'xe??xexicLy9C|Dz 'usST#'Pgş"RX#.;A:;Av4g%wuuw±A±aca"n.n[b/\%u@BC|}Qpq 5T^57T&[uD3K*.mT;`>H*FyH0URB)]V|>vXMhWw=p>HrxI9su4|Ij4(z$oFa\r[qyV'Yܡ~PտhֺIfdÒcHlSGu~6ʳzVIݴ%nf9D+'e*Z5ؔ;NG$XhaZ"jNl?zbi:|/}.Dׅ^]beqgɱfcIII29I5ILIMLIeI<I I^IIRIgz/is6Rl{ {,o}є#j -o~l~% -ٶ)ۘBfw5M;q/}#~ s޸D^UgiK(#(J,]]a5@;M?%BLPBOyP1U_cgava3c b/peel4,nqYpgqS6f}"Xe. AF*ouP`,:ILT  1KBOB2qvׯ fََ' q%՞I7y J7bVgOrIX$k"V8$k2U$kBU,%b)!+Tnj-ڎ3L_I;7@E9K_E6Q0QMjv^z^cX_pں_z\`r i\ QlWqW"ItKtQzH |c zC; ?u ZZ%A;v.|]]dDDLL:PWWO/d@9F(֣Bq֣7(bm`ޛnne?c-9.lDwc*'p S 69&|8>'SGP(G2-3eST.H?51,62;!dE&Eʇ4Z\c\ cYihi@khkTrVםs$M}sNt|%&t2EV>C-'^s IT f<WL]4c4*]ńa c-G?t>[r{^EYӺA0-3gp(2n ?&Zo,ιc-B25CREF?HtoHR,I'eNO;P15YQ^mb]ARfCfC;f|ܞgi'+?i!zvyyz.|Ԃg|^n|^%l4C.~;1l*),qSNzSM[aI$9nr\*y{ GX"3Mnʗ>КkRл%Tz-QT5 \~X +}e E |UX wT  9  V !yM} $)~ 0 0!Sj 5GV BU/ Exw GȧT Mg Q0 Sesy \uA aB cϥW lOP lX ui~E u ~ .z ~S N r ^4N B1~ N! .D  9 s.h Ŧ ^5U a4p& c3B c3{ dE3 d8 eKn eR^ e ej fjm# g7K k2 k2 su5D tqo vU N ~ҭ ,R ^  q O "n, 9 9<| NJ Ɍ4E vS v~ Ϯ 01 0 ˺-- KrE j ;' c  0& Up Ti  V\S ~ ~# _ g=1 ă %4Nc (R ) K * * ? 8m N> VnG YsI bR gm i$ea 1Z r Y $q 49 @= L v -n|3 ,.* a e) qD %F t }eg pX Z2 1 % KG[ @U F t 4cI a  wj Lk I v `[ XH $& RH #x %^ %^B ,\ -1 /~} 9sx =l; L. M&`I O~ Wj `l$ af euGa eZm hȾ0 r4 rD t\ z n e z n,b "R @0 $L$ )F Z r ,f , S /p /o c P  T 1 m4{ E .P 9 T7u ɠ.LX ? ' KF 9a ~## os0 US Jp ( % fRa a  #Ѯ 3F 7n$ A AR DD G0 LRB R/T [ Ǎ cL c| f^ fk1; iB m[a2 qU$ vCi }L #< }<  { 15j yc T< ~z z & &J @z R[# <N ^j# cY>  _ ^  d>  (Zִ{p] rcSY(/y9i;)Ka.3a.sfTfT<w=)~sPijo#n!n6w$ qS RJxtxãCM!ciuoA9qtY2$!4o/ uuCqk].-^6$Y>#}i$ 5u}2*3"TN6$]/`i=3 8@}TmW)^Uav!iZi0p$CsVvgU{ w|>vZ}$71#AmF1p_PX:Tm=7IN\Wi,l<b>GNU GPL v3 na kd a CreativeCommons:BY-SA na zbytek?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxdBryant Mairs, Uleshka Asher, a Daniel Tzschentke. 4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxHOddlen Bauhaus univerzity Weimar, )Department of Bauhaus-University Weimar, AboutBox~Durrelul Bishopovi, Davidu Cuartiellesovi, Fabianu Hemmertovi, 3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBox>pustit do kola testo Fritzingu.Fritzing a test spin. AboutBox(Fritzing vytvoYili: Fritzing is made by: AboutBoxXFritzing bylo mo~n vytvoYit s financovnm 0Fritzing is made possible with funding from the AboutBoxjGero Herkenrathovi, Jeffu Hoefsovi, Tomu Hulbertovi, *Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxdIxDS, anonymn drce, Parallax, Picaxe, Sparkfun, 6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBoxbJanu Sieberovi, Yaniv Steinerovi, Olafu Vaolovi, %Jan Sieber, Yaniv Steiner, Olaf Val, AboutBoxvJussi &Auml;ngeslev&auml;, Massimo Banzimu, Ayah Bdeirovi, 6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxDMWFK Brandenburg, sponzor Designu 0MWFK Brandenburg, the sponsorship of the Design AboutBoxJMichaele Vieserov a Julii Wernerov.!Michaela Vieser and Julia Werner.AboutBox\Zvlatn podkovn patY tak vaem studentom 4Special thanks goes out as well to all the students AboutBox6Zvlatn podkovn patY: Special thanks goes out to: AboutBoxDkujeme Kurtu Badeltovi a Miguelu Solisovi za `panlsk pYeklad, DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBoxnTomu Igoevi, Hans-Peteru Kadelovi, Tillu Savelkoulovi, ,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBoxLa alfa testerom, kteY mli odvahu se 0and alpha testers who were brave enough to give AboutBoxHGianluca Urgese za Italsk pYeklad, 0to Gianluca Urgese for the Italian translation, AboutBoxLHiroshi Suzukimu za Japonsk pYeklad, 0to Hiroshi Suzuki for the Japanese translation, AboutBoxHJinbuhm Kimovi za Korejsk pYeklad, +to Jinbuhm Kim for the Korean translation, AboutBoxFJosefu Duatrovi za  esk pYeklad, ,to Josef Dustira for the Czech translation, AboutBoxvNuno Pessanha Santosovi za Portugalsk (Evropsk) pYeklad, Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxTRobertu Lee za  nsk (tradi n) pYeklad, 9to Robert Lee for the Chinese (Traditional) translation, AboutBoxJVladimiru Savinovi za Rusk pYeklad, 1to Vladimir Savinov for the Russian translation, AboutBoxr Yuelinovi a Ninjiovi za  nsk (zjednoduaen) pYeklad, @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBox ZruaitCancelAutorouteProgressDialogZastavitStop NowAutorouteProgressDialog0Yzen zvtaen a posunuzoom and pan controlsAutorouteProgressDialog ZruaitCancelAutorouterSettingsDialogTyp vrobyProduction typeAutorouterSettingsDialog`Yka spoje Trace widthAutorouterSettingsDialogvlastncustomAutorouterSettingsDialogdomc vrobahomebrewAutorouterSettingsDialogprofesionln professionalAutorouterSettingsDialogZsobnkBin BinManagerBinManager::setDirtyTab: Nelze nastavit zsobnk '%1' jako dirty;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerBinManager::updateTitle: Nelze nastavit zsobnk '%1' jako dirty;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerTNelze nastavit NULL zsobnk jako aktuln(Cannot set a NULL bin as the current one BinManagerZavYt zsobnk Close Bin BinManager0ZavYe zsobnk sou stekClose parts bin BinManager>VytvoY nov zsobnk sou stekCreate a new parts bin BinManager Vymazat zsobnk Delete Bin BinManager Vymazat zsobnk Delete bin BinManager2Vyma~e zsobnk sou stekDelete parts bin BinManager:Zobraz sou stky jako seznamDisplay parts as a list BinManager8Zobraz sou stky jako ikonyDisplay parts as icons BinManager|Opravdu chcete vymazat zsobnk '%1'? Tuto akci nelze vrtit.EDo you really want to delete bin '%1'? This action cannot be undone. BinManager,Exportovat zsobnk... Export Bin... BinManager.Exportovat sou stku...Export Part... BinManagerFritzing soubory zsobnku (*%1 *%2);;Fritzing zsobnk (*%1);;Fritzing sdlen zsobnk (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManager Nov zsobnk... New Bin... BinManager$Nov zsobnk (%1) New bin (%1) BinManagerSou stkyParts BinManager4Zvolte nzev pro zsobnk:!Please choose a name for the bin: BinManager0Zsobnk pouze pro  ten Read-only bin BinManager&Odstranit sou stku Remove Part BinManager,Odstranit ze zsobnkuRemove from bin BinManager.PYejmenovat zsobnk... Rename Bin... BinManager&PYejmenuje zsobnk Rename bin BinManager@PYejmenuje zsobnk sou stek...Rename parts bin... BinManagerUlo~it zsobnkSave Bin BinManager.Ulo~it zsobnk jako...Save Bin As... BinManager0Ulo~ zsobnk sou stekSave parts bin BinManager@Ulo~ zsobnk sou stek jako...Save parts bin as... BinManagerfUlo~ zsobnk sou stek v komprimovanm formtu...&Save parts bin in compressed format... BinManagerFVybrat soubor Fritzing pro otevYenSelect a Fritzing File to Open BinManagernVybrat Fritzing soubor zsobnku sou stek pro otevYen(Select a Fritzing Parts Bin file to open BinManager8Zobrazit zsobnk jako ikonyShow Bin in Icon View BinManager:Zobrazit zsobnk jako seznamShow Bin in List View BinManagerBTento zsobnk nelze pYejmenovat.This bin cannot be renamed. BinManagerObrzkyImagesBoard@Preferencesyberte soubor obrzkuSelect an image file to loadBoardNelze na stUnable to loadBoard8Nelze na st obrzek z %1 %2Unable to load image from %1 %2Boardsoubor obrzku image fileBoard*na st soubor obrzkuload image fileBoard6jedna vrstva (jednostrann)one layer (single-sided)Board0dv vrstvy (oboustrann)two layers (double-sided)Boardtvarshape BoardLogoItem barvacolorBreadboardLogoItem PYidat bod zlomu Add bendpoint ConnectorItem&Odstranit bod zlomuRemove bendpoint ConnectorItemVyrovnat kYivkuStraighten curve ConnectorItem&O programu&About ConsoleWindow&Ukon it&Quit ConsoleWindowNstrojeTools ConsoleWindow Va nvrh je pYipraven pro vrobu: nebyly nalezeny ~dn pYekrvajc se propojky,ani spoje a sou asn tak nejsou pYlia blzko sebe.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRCpro debugging for debugging DebugDialog*Odstranit tak souborAlso delete the file DeleteDialogNeodstraHovat Don't remove DeleteDialogOdstranitRemove DeleteDialogpopisek  ipu chip labelDip Pozn.: Mo~ete importovat pozdji, s pou~itm polo~ky "Npovda" > "Import sou stek a zsobnko z dYvja verze..." z nabdky.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication"Nyn neimportovatDo not import now FApplicationPYejete si importovat sou stky a zsobnky, kter jste vytvoYili v pYedchoz verzi Fritzingu?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplication^Fritzing zachytil vyjmku %1 z %2 v udlosti %33Fritzing caught an exception %1 from %2 in event %3 FApplicationXFritzing zachytil vyjmku z %1 v udlosti %20Fritzing caught an exception from %1 in event %2 FApplication2Aplikace Fritzing selhalaFritzing failure FApplicationJImportovat soubory z pYedchoz verze?#Import files from previous version? FApplication~Zadejte nzev souboru .fzz pro ulo~en (Zruait odstran zlohu)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplicationPrvn npovdaFirst Time HelpFirstTimeHelpDialog&ZavYt okno &Close WindowFritzingWindow ZruaitCancelFritzingWindow*UzavYe aktuln nvrhClose the current sketchFritzingWindowfPYejete si ulo~it zmny proveden v dokumentu "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindowNeukldat Don't SaveFritzingWindow Ulo~itSaveFritzingWindowUlo~it "%1" Save "%1"FritzingWindowUlo~it...Save...FritzingWindow*Zadejte nzev souboruSpecify a file nameFritzingWindow\Vaae zmny budou ztraceny, pokud je neulo~te.1Your changes will be lost if you don't save them.FritzingWindow ZruaitCancelGroundFillSeedDialog"OK a vyplnit mdOK and copper fillGroundFillSeedDialog"OK a vyplnit zemOK and ground fillGroundFillSeedDialogRozdl mezi 'vpln zem' a prostou 'vpln m' je ten, ~e ve vplni zem, obsahuje vyplnn plocha spoje a konektory, kter jsou pYipojeny na 'zemnc' konektory. Zemnc konektory jsou obvykle ozna eny jako "GND", nebo "zem", ale nkdy to vaak nemus bt tento pYpad. Dala mo~nost tak mo~e bt, ~e na desce jsou rozn st se zemnm konektorem, a vy budete chtt vyplnit pouze jednu z tchto st. Tento dialog shroma~uje pouze konektory s ozna enm "GND" nebo "zem", stejn tak jako konektory ji~ vybran jako zemnc. Poklepnm na polo~ku zvraznte v nvrhu jej propoje. Je tak mo~n zvolit konektory jako vplH zem kliknutm pravm tla tkem myai na konektor a z kontextov nabdky vybrat 'Nastavit vplH zem".The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialogvelikost otvoru hole sizeHole4(automaticky routovateln)(autoroutable) HtmlInfoView8Zde zmnit popisek sou stkyChange the part label here HtmlInfoViewPiny Connections HtmlInfoViewUzam enoLocked HtmlInfoView@Obrzek sou stky mont~n deskyPart breadboard view image HtmlInfoView6Obrzek sou stky desky PCBPart pcb view image HtmlInfoView4Obrzek sou stky schmatuPart schematic view image HtmlInfoView* slo verze sou stkyPart version number HtmlInfoViewVlastnosti Properties HtmlInfoViewPropojovac se Ratsnest wire HtmlInfoView Zna kyTags HtmlInfoViewPloan spoj %1 Trace wire %1 HtmlInfoViewPropojkaWire HtmlInfoViewkon.conn. HtmlInfoView,pYipojeno k %n polo~ce0pYipojeno ke %n polo~km.pYipojeno k %n polo~kmconnected to %n item(s) HtmlInfoView nzevname HtmlInfoViewtyptype HtmlInfoViewSou stkaPartItemBasekondenztor capacitanceItemBase barvacolorItemBaseaktulncurrentItemBase datumdateItemBase popisdescrItemBase rodinafamilyItemBasenzev souborufilenameItemBase formaformItemBasekmito et frequencyItemBaseinduk nost inductanceItemBase vrstvylayersItemBasemaximln odpormaximum resistanceItemBase0problm modelu sou stkymodel part problemItemBasepouzdropackageItemBase slo sou stky part numberItemBaseodstup pino pin spacingItemBasepinypinsItemBasenapjenpowerItemBaseprocesor processorItemBaseprojektprojectItemBasejmenovit proud rated currentItemBase$jmenovit napjen rated powerItemBase jmenovit napt rated voltageItemBase odpor resistanceItemBasetvarshapeItemBaselistsheetItemBasevelikostsizeItemBase odstupspacingItemBasetitulektitleItemBasetyptypeItemBaseBnelze vytvoYit renderovn svg %1$unable to create renderer for svg %1ItemBasevariantavariantItemBase verzeversionItemBase naptvoltageItemBase ZruaitCancelKicadModuleDialog.zobrazit vaechny vrstvyshow all layers LayerPalette ZruaitCancel LinkDialogNelze zobrazitUnable to displayLogoItem6Nelze zobrazit obrzek z %1Unable to display image from %1LogoItemtvarshapeLogoItem%1 z %2 routovanch propojo - %n propojka, kter bude jeat routovna%1 z %2 routovanch propojo - %n propojky, kter budou jeat routovny%1 z %2 routovanch propojo - %n propojek, kter budou jeat routovny9%1 of %2 nets routed - %n connector(s) still to be routed MainWindow&O programu&About MainWindow &O Qt &About Qt MainWindow$&Aktuln velikost &Actual Size MainWindow.&PYidat do zsobnku...&Add to bin... MainWindow&Koprovat&Copy MainWindow<&VytvoYit spoj ze st propojo&Create trace from ratsnest MainWindowD&VytvoYit propojku ze st propojo&Create wire from ratsnest MainWindowV&yjmout&Cut MainWindow&Vymazat&Delete MainWindow&Zruait vbr &Deselect MainWindow&Duplikovat &Duplicate MainWindow&Upravit&Edit MainWindow&Exportovat&Export MainWindow&Exportovat... &Export... MainWindow&Soubor&File MainWindow"&PYizposobit oknu&Fit in Window MainWindow(&PYeklopit vodorovn&Flip Horizontal MainWindow"&PYeklopit svisle&Flip Vertical MainWindow&Npovda&Help MainWindow*&Skrt vaechny vrstvy&Hide All Layers MainWindowh&Import sou stek a zsobnko z pYedchozch verz...*&Import parts and bins from old version... MainWindow&Minimalizovat &Minimize MainWindow &OtevYt pYklad &Open Example MainWindow0&OtevYt nedvn soubory&Open Recent Files MainWindow&OtevYt...&Open... MainWindow&Sou stka&Part MainWindow&Vlo~it&Paste MainWindow&PYedvolby...&Preferences... MainWindow&Tisk... &Print... MainWindow&Ukon it&Quit MainWindow&Routovn&Routing MainWindow&Ulo~it&Save MainWindow&Ulo~it jako... &Save As... MainWindow&Vybrat vae &Select All MainWindow0&Zobrazit vaechny vrstvy&Show All Layers MainWindow0&Zobrazit mont~n desku&Show Breadboard MainWindow&Zobrazit PCB &Show PCB MainWindow &Zobrazit schma&Show Schematic MainWindow6&Zobrazit popisku sou stky&Show part label MainWindow&Zobrazen&View MainWindow &Okno&Window MainWindow&Barva propojky &Wire Color MainWindow&Zvtait&Zoom In MainWindow&Zmenait &Zoom Out MainWindow,100% (pixelo) velikost100% (pixel) size MainWindow100% Velikost 100% Size MainWindowHAktuln (skute n fyzick) velikost!Actual (real world physical) size MainWindow"Aktuln velikost Actual Size MainWindow PYidat bod zlomu Add Bendpoint MainWindowPYidat poznmkuAdd Note MainWindow@PYid bod zlomu vybran propojce$Add a bendpoint to the selected wire MainWindowPYid poznmku Add a note MainWindowJPYid vybranou sou stku do zsobnkuAdd selected part to bin MainWindowNPYi pYeta~en pYichyt polo~ky k mY~ce!Align items to grid when dragging MainWindow$PYichytit k mY~ce Align to Grid MainWindowVaeAll MainWindowLNebyly zroutovny jeat vaechny spoje.$All traces have not yet been routed. MainWindow(Automaticky routovat Autoroute MainWindow,Probh autorouting...Autorouting Progress... MainWindowZlohovat '%1'Backing up '%1' MainWindow6Textov soubor BoM (*.html)BoM Text File (*.html) MainWindowOb vrstvy Both Layers MainWindowSpodn vrstva Bottom Layer MainWindowMont~n deska Breadboard MainWindowPosunout vpYed Bring Forward MainWindowbPosune vybran() objekt(y) vpYed v jejich vrstv/Bring selected object(s) forward in their layer MainWindowhPYenese vybran() objekt(y) dopYedu v jejich vrstv0Bring selected object(s) to front of their layer MainWindow"PYesunout dopYeduBring to Front MainWindow ZruaitCancel MainWindow.Nelze nalzt soubor %1.Cannot find file %1. MainWindow(Nelze tisknout na %1Cannot print to %1 MainWindow8Nelze  st soubor 1 %1: %2.Cannot read file 1 %1: %2. MainWindow6Nelze zapsat soubor %1: %2.Cannot write file %1: %2. MainWindow.Kontrola aktualizace...Check for updates... MainWindowpZkontroluje, zda nen ke sta~en novja verze FritzinguCCheck whether a newer version of Fritzing is available for download MainWindow@Vybrat plochu(y) zemn vpln...Choose Ground Fill Seed(s)... MainWindow0Vybrat slo~ku pro exportChoose a folder for exporting MainWindow6Vymazat plochy zemn vplnClear Ground Fill Seeds MainWindowhVyma~e plochy zemn vpln--povol pouze vplH md.1Clear ground fill seeds--enable copper fill only. MainWindowPYevstConvert MainWindow>Spodn mdn vrstva je aktivnCopper Bottom layer is active MainWindowMdn vplH Copper Fill MainWindow^Ob mdn vrstvy, horn i spodn, jsou aktivn3Copper Top and Copper Bottom layers are both active MainWindow<Horn mdn vrstva je aktivnCopper Top layer is active MainWindow Kopruje vybranCopy selection MainWindow,Nelze zadokovat widgetCouldn't get the dock widget MainWindow$VytvoY nov nvrhCreate a new sketch MainWindow,VytvoY spoj z propoje%Create a trace from the ratsnest line MainWindow@VytvoY prost propoj z propojky$Create a wire from the ratsnest line MainWindowVyjme vbr Cut selection MainWindow Vstup debuggeruDebugger Output MainWindowVymazatDelete MainWindow0Vymazat propojovac  ruDelete Ratsnest Line MainWindow Vymazat propojku Delete Wire MainWindowVyma~e vbrDelete selection MainWindowZrua vbrDeselect MainWindow.Odpoj vaechny propojkyDisconnect All Wires MainWindowLOdpoj vaechny propojky od tto api ky0Disconnect all wires connected to this connector MainWindow^Zobraz nkter u~ite n tipy a triky Fritzingu+Display some handy Fritzing tips and tricks MainWindowLZobraz zsobnk sou stek jako seznam$Display the parts bin in a list view MainWindowJZobraz zsobnk sou stek jako ikony%Display the parts bin in an icon view MainWindow0Neprovdt autoroutovnDo not autoroute MainWindowNPYejete zachovat importovan sou stky?'Do you want to keep the imported parts? MainWindow2PYesto chcete pokra ovat?Do you want to proceed anyway? MainWindow"PodpoYte FritzingDonate to Fritzing MainWindowDuplikuje vbrDuplicate selection MainWindow*Povolit debugging logEnable debugging log MainWindow&Leptateln (PDF)...Etchable (PDF)... MainWindow&Leptateln (SVG)...Etchable (SVG)... MainWindowExportuje 1000 dpi slou en SVG tto sou stky v tomto zobrazen7Export 1000 dpi Flattened SVG of this part in this view MainWindownExportuje 1000 dpi SVG tto sou stky v tomto zobrazen-Export 1000 dpi SVG of this part in this view MainWindowDExport soupisky materilu (BoM)...!Export Bill of Materials (BoM)... MainWindow$Export netlistu...Export Netlist... MainWindowHExportuje normalizovan slou en SVGExport Normalized Flattened SVG MainWindow6Exportuje normalizovan SVGExport Normalized SVG MainWindow"Exportovat SVG... Export SVG... MainWindowExport pro PCBExport for PCB MainWindow8Exportuje vybranou sou stkuExport selected part MainWindowRExportuje aktuln nvrh jako SVG obrzek)Export the current sketch as an SVG image MainWindowJExportuje aktuln nvrh do Eagle CAD&Export the current sketch to Eagle CAD MainWindowExportuje aktuln nvrh do Extended Gerber formtu (RS-274X) pro professionln vrobu PCB]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production MainWindow|Exportuje aktuln nvrh do PDF pro DIY vrobu PCB (fotocesta)EExport the current sketch to PDF for DIY PCB production (photoresist) MainWindow|Exportuje aktuln nvrh do SVG pro DIY vrobu PCB (fotocesta)EExport the current sketch to SVG for DIY PCB production (photoresist) MainWindow|Exportuje viditelnou oblast aktulnho nvrhu jako JPG obrzekNastav velikost mY~ky pro %1.Set the grid size for %1. MainWindow SdletShare MainWindow Sdlet online...Share online... MainWindow Shell spustil %1Shell launch %1 MainWindowZobrazit mY~ku Show Grid MainWindowNZobrazit sou stky zsobnku jako ikonyShow Parts Bin Icon View MainWindowPZobrazit sou stky zsobnku jako seznamShow Parts Bin List View MainWindow&Zobraz okno o Qt'sShow Qt's about box MainWindowlZobraz vaechny dostupn vrstvy pro aktuln zobrazen2Show all the available layers for the current view MainWindow*Zobraz pohled na PCBShow the PCB view MainWindow.Zobraz okno O programu Show the application's about box MainWindow@Zobraz pohled na mont~n deskuShow the breadboard view MainWindowZobraz mY~ku Show the grid MainWindow0Zobraz pohled na schmaShow the schematic view MainWindow Nvrh exportovnSketch exported MainWindow4Nvrh exportovn do GerberSketch exported to Gerber MainWindowPromiHte!Sorry! MainWindow^PromiHte, funkce %1 nebyla dosud implementovna(Sorry, "%1" has not been implemented yet MainWindow*Zadejte nzev souboruSpecify a file name MainWindowVyrovnat kYivkuStraighten Curve MainWindow>Vyrovn kYivku vybran propojky)Straighten the curve of the selected wire MainWindowspan aktualizovno %1 sou stek. Zkontrolujte, vaechny pohledy pro potenciln vedleja  inky.SSuccessfully updated %1 part(s). Please check all views for potential side-effects. MainWindowSVG %1 neobsahuje vrstvu '%2'. Dala informace o tom, jak vytvoYit vlastn obrazec desky naleznete v kurzu na <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/. MainWindow.PYepnut %1 s modulem %2Swapped %1 with module %2 MainWindowfz formt se ji~ nepou~v. Chtli byste zmnit '%1' do formtu fzz nyn, nebo otevYt pouze pro  ten? vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only?  MainWindow@Procesem pYevodu se '%1' nemn.,The conversion process will not modify '%1'. MainWindowNa jednostrann desce nen horn mdn vrstva (m 1) k dispozici. PYepnte desku na oboustrannou, nebo zvolte spodn mdnou vrstvu (m 0).The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. MainWindowrTato funkce brzy poskytne export nvrhu Fritzing do EAGLE PCB software. Pokud byste chtli mt vce exporto do svch oblbench nstrojo EDA, prosm dejte nm vdt, nebo nm pYispjte.This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. MainWindow"UspoYdat propoje Tidy Wires MainWindow0UspoYd vybran propojeTidy selected wires MainWindow>Tipy, triky a klvesov zkratkyTips, Tricks and Shortcuts MainWindowHorn vrstva Top Layer MainWindowBhem vytvYen zemn vpln pova~ovat tento konektor a jeho pYipojen jako "zem".JTreat this connector and its connections as a 'ground' during ground fill. MainWindow@Nelze exportovat %1 jako sdlen Unable to export %1 as shareable MainWindowNNelze exportovat %1 do sdlenho nvrhu'Unable to export %1 to shareable sketch MainWindowNelze ulo~it %1Unable to save %1 MainWindowpNelze ulo~it soubor BOM, ale text je ulo~en ve schrnce.:Unable to save BOM file, but the text is on the clipboard. MainWindowZptUndo MainWindowHistorie Zpt Undo History MainWindow0Aktualizace %1 sou stekUpdate %1 part(s) MainWindowBAktualizuje InfoView pYi pYechoduUpdate InfoView on hover MainWindow<Aktualizovat vybran sou stkyUpdate selected parts MainWindowPYi autoroutingu se nezni tento propojovac spoj, prochod, nebo propojkuDWhen autorouting, do not rip up this trace wire, via, or jumper item MainWindowPro pou~it importovanch sou stek mus bt Fritzing restartovnDYou will have to restart Fritzing in order to use the imported parts MainWindowVa nvrh dosud neobsahuje desku! Pro span export do Gerber pYidejte PCB.VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber. MainWindowZvtaitZoom in MainWindowZmenaitZoom out MainWindowjako obrzekas Image MainWindowmdnoucopper MainWindow.pYm na ten sou stekdirectly loading parts MainWindowpro vrobufor Production MainWindow zemnground MainWindow palcein MainWindowna tn %1 loading %1 MainWindow8na tn %1 (mont~n deska)loading %1 (breadboard) MainWindow&na tn %1 (model)loading %1 (model) MainWindow"na tn %1 (pcb)loading %1 (pcb) MainWindow(na tn %1 (schma)loading %1 (schematic) MainWindownov nvrh new sketch MainWindow,fz formt je zastaralthe .fz file format is obsolete MainWindowhVlo~ faleanou vjimku , aby bylo vidt, co se stane*throw a fake exception to see what happens MainWindow,vlo~ testovac vyjmkuthrow test exception MainWindow:nelze nalzt nhradu pro %1. #unable to find replacement for %1.  MainWindowkolo %1 z: round %1 of: MazeRouternNen mo~n pYepsat soubor '%1'. Dovod: %2 (chyb.kd %3)5Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ModelBase0Ulo~en souboru selhalo!File save failed! ModelBaseLNelze nalzt nsledujc %n sou stku:LNelze nalzt nsledujc %n sou stky:PNelze nalzt nsledujcch %n sou stek:(Unable to find the following %n part(s): ModelBasevat ModelBasepopisek  ipu chip label MysteryPartpopiseklabel MysteryPart,[zde napiate poznmku][write your note here]Note&Zmnit vrstvu spojeChange trace layerPCBSketchWidget6Vymazat plochy zemn vplnClear ground fill seedsPCBSketchWidget`Kliknte na tento pin pro vyta~en novho spoje.-Click this connector to drag out a new trace.PCBSketchWidget:VytvoYit spoj ze st propojoCreate Trace from RatsnestPCBSketchWidgetdChyba Fritzingu: Nelze renderovat desku v SVG (1)./Fritzing error: unable to render board svg (1).PCBSketchWidget`Chyba Fritzingu: Nelze renderovat m v SVG (1).0Fritzing error: unable to render copper svg (1).PCBSketchWidget`Chyba Fritzingu: Nelze zapsat mdnou vplH (1).0Fritzing error: unable to write copper fill (1).PCBSketchWidget`Chyba Fritzingu: Nelze zapsat mdnou vplH (2).0Fritzing error: unable to write copper fill (2).PCBSketchWidgetPYed vytvoYenm zemn vpln ur ete jednu nebo vce zemnch ploch vpln. LPlease designate one or more ground fill seeds before doing a ground fill. PCBSketchWidgetNelze vytvoYit mdnou vplH - sou stka byla pravdpodobn vlo~ena na jinou  st nebo propoj, spae ne~ aktuln PCB.qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.PCBSketchWidgetNelze vytvoYit mdnou vplH - pravdpodobn sou stka nebyla vlo~enal na PCB.LUnable to create copper fill--probably the part wasn't dropped onto the PCB.PCBSketchWidgetVa nvrh jeat neobsahuje desku! PYidejte PCB Aby bylo mo~n pou~t mdnou vplH.UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.PCBSketchWidget&Upravit&Edit PEMainWindow&Exportovat&Export PEMainWindow&Soubor&File PEMainWindowPYidat konektor Add connector PEMainWindow ZruaitCancel PEMainWindowPiny Connectors PEMainWindow Problm konverzeConversion problem PEMainWindow IkonaIcon PEMainWindow&Soubory obrzko & patic (%1 %2 %3 %4 %5);;SVG soubory (%1);;JPEG soubory (%2);;PNG soubory (%3);;soubory gEDA patic (%4);;soubory Kicad modulo (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowSoubory obrzko (%1 %2 %3);;SVG soubory (%1);;JPEG soubory (%2);;PNG soubory (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowInspektor Inspector PEMainWindow VrstvyLayers PEMainWindowOtevYt obrzek Open Image PEMainWindow Editor sou stek Parts Editor PEMainWindow Ulo~itSave PEMainWindowUlo~it "%1" Save "%1" PEMainWindow\Vaae zmny budou ztraceny, pokud je neulo~te.1Your changes will be lost if you don't save them. PEMainWindow8v %1 nenalezena ~dn paticeno footprints found in %1 PEMainWindow8v %1 nenalezeno ~dn schmano schematics found in %1 PEMainWindow schma sou stkyschematic part PEMainWindow AutorAuthorPEMetadataView DatumDatePEMetadataView Popis DescriptionPEMetadataViewPopisekLabelPEMetadataViewVlastnosti PropertiesPEMetadataView Zna kyTagsPEMetadataView stYedcenter PEToolView vchodeast PEToolView severnorth PEToolViewjihsouth PEToolView zpadwest PEToolView stYedcenterPadpropojit s connect toPad vchodeastPad severnorthPadtvarshapePadjihsouthPad zpadwestPad(Upravit popisku pinuEdit Pin Labels PaletteItemPromr otvoru Hole Diameter PaletteItemPPopisek nesoulhlas. Nic nebylo ulo~eno.#Label mismatch. Nothing was saved. PaletteItemTlouaeka kruhuRing Thickness PaletteItemlNelze pokra ovat, piny sou stky nemaj standardn ID.;Unable to proceed; part connectors do no have standard IDs. PaletteItempNelze pokra ovat, nelze najt nejvyaa roveH zobrazen.1Unable to proceed; unable to find top level view. PaletteItem&rozaYen nastavenadvanced settings PaletteItemvelikost otvoru hole size PaletteItem palcein PaletteItem Zobrazit hodnotyDisplay Values PartLabel(Zobraz text popiskuDisplay the text of the label PartLabel:Zobraz hodnotu vlastnosti %1 Display the value of property %1 PartLabelUpravitEdit PartLabel(Upravit text popiskuEdit label text PartLabel&PYeklopit vodorovnFlip Horizontal PartLabel PYeklopit svisle Flip Vertical PartLabel4PYeklop popisek vodorovnFlip label horizontally PartLabel.PYeklop popisek svisleFlip label vertically PartLabel PYeklopit/Oto it Flip/Rotate PartLabelVelikost psma Font Size PartLabel SkrtHide PartLabel.Skrt popisek sou stkyHide part label PartLabelText popisku Label text PartLabelText popisku: Label text: PartLabel VelkLarge PartLabelStYednMedium PartLabel:Oto it o 135 doprava {135?}Rotate 135� Clockwise PartLabel6Oto it o 45 doleva {135?}Rotate 135� Counter Clockwise PartLabel*Oto it o 180 {180?} Rotate 180� PartLabel8Oto it o 135 doprava {45?}Rotate 45� Clockwise PartLabel4Oto it o 45 doleva {45?}Rotate 45� Counter Clockwise PartLabel8Oto it o 135 doprava {90?}Rotate 90� Clockwise PartLabel4Oto it o 45 doleva {90?}Rotate 90� Counter Clockwise PartLabelBOto aktuln vbr o 90 doleva5Rotate current selection 90 degrees counter clockwise PartLabel8Oto popisek o 135 doprava)Rotate the label by 135 degrees clockwise PartLabel6Oto popisek o 135 doleva1Rotate the label by 135 degrees counter clockwise PartLabel(Oto popisek o 180Rotate the label by 180 degrees PartLabel6Oto popisek o 45 doprava(Rotate the label by 45 degrees clockwise PartLabel4Oto popisek o 45 doleva0Rotate the label by 45 degrees counter clockwise PartLabel6Oto popisek o 90 doprava(Rotate the label by 90 degrees clockwise PartLabel<Nastav velkou velikost psmaSet font size to large PartLabel@Nastav stYedn velikost psmaSet font size to medium PartLabel:Nastav malou velikost psmaSet font size to small PartLabel@Nastav nejmena velikost psmaSet font size to tiny PartLabel,Nastav popisek pro %1Set label for %1 PartLabelMalSmall PartLabelNejmenaTiny PartLabel&PYidat do zsobnku Add to binPartsBinPaletteWidget ZruaitCancelPartsBinPaletteWidget.Nelze nalzt soubor %1.Cannot find file %1.PartsBinPaletteWidget2Nelze  st soubor %1: %2.Cannot read file %1: %2.PartsBinPaletteWidget*Zmnit barvu ikony...Change icon color...PartsBinPaletteWidgetHZmnit barvu ikony tohoto zsobnku.*Change the color of the icon for this bin.PartsBinPaletteWidgetlOpravdu chcete pYidat vybranou sou stku do zsobnku?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetfPYejete si ulo~it zmny proveden v zsobnku "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetNeukldat Don't SavePartsBinPaletteWidget.Fritzing zsobnk (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetNa tn... Loading...PartsBinPaletteWidget Ulo~itSavePartsBinPaletteWidget(Ulo~it zsobnk "%1" Save bin "%1"PartsBinPaletteWidget.Vybere barvu tto ikonySelect a color for this iconPartsBinPaletteWidget*Zadejte nzev souboruSpecify a file namePartsBinPaletteWidget,Nepojmenovan zsobnk Untitled BinPartsBinPaletteWidget\Vaae zmny budou ztraceny, pokud je neulo~te.1Your changes will be lost if you don't save them.PartsBinPaletteWidget*na tn zsobnku %1loading bin '%1'PartsBinPaletteWidget ZruaitCancel Perfboard"Upozornn vkonuPerformance Warning Perfboard@Provdn perfboards a stripboards s vce ne~ cca 2000 otvory mo~e bt pomal. Jste si jisti? Poznmka: Bhem tto relace se ji~ toto varovn nebude opakovat.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard.Nastavit novou velikost Set new size Perfboardsloupcocolumns Perfboard Ydkorows Perfboard.nastavit velikost deskyset board size Perfboardvelikostsize PerfboardF<p><h2>Editor popisku pinu</h2></p>

    Pin Label Editor

    PinLabelDialog<p>Kliknte na popisek vedle  sla pinu pro pYejmenovn tohoto pinu.<

    Click on a label next to a pin number to rename that pin.PinLabelDialog ZruaitCancelPinLabelDialog VpYedRedoPinLabelDialog Ulo~itSavePinLabelDialogZptUndoPinLabelDialoghMo~ete pou~t klvesu Tab k posunu pYes popisky.</p>@You can use the tab key to move through the labels in order.

    PinLabelDialog4%1 (kliknout pro zmnu...)%1 (click to change...) PrefsDialog(Automatick ukldnAutosave PrefsDialog6Automaticky ulo~it ka~dch:Autosave every: PrefsDialog ZruaitCancel PrefsDialog6Zmnit chovn kole ka myaiChange Wheel Behavior PrefsDialog BarvyColors PrefsDialog PYkazCommand PrefsDialog,Zvraznn propojenchConnected Highlight PrefsDialog XzenControl PrefsDialog2KYivky vs. rovn propojkyCurvy vs. straight wires PrefsDialogVaeobecnGeneral PrefsDialog JazykLanguage PrefsDialog(Chovn kole ka myaiMouse Wheel Behavior PrefsDialogPVyberte programtor (spustiteln) pro %1'Select a programmer (executable) for %1 PrefsDialog0Zvraznn nepropojenchUnconnected Highlight PrefsDialog minutminutes PrefsDialog~dn klvesa stla en = posunout klvesa SHIFT pYepne posun osy Klvesa Alt nebo klvesa %1 = zvtaenFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialog~dn klvesa stla en = zvtaen klvesa SHIFT pYepne posun osy Klvesa Alt nebo klvesa %1 = posunoutFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialogNOpravdu chcete odstranit "%1" z nvrhu?5Are you sure you want to remove "%1" from the sketch? ProgramTab DeskaBoard ProgramTab^Fritzing nebyl schopen nalzt '%1', najdte jej1Fritzing is unable to find '%1', please locate it ProgramTabNovNew ProgramTabOdstranit "%1"? Remove "%1"? ProgramTab Ulo~itSave ProgramTabBVyberte soubor programu k na tenSelect a program file to load ProgramTab&Koprovat&Copy ProgramWindowV&yjmout&Cut ProgramWindow&Upravit&Edit ProgramWindow&Vlo~it&Paste ProgramWindow&PYedvolby...&Preferences... ProgramWindow&Vybrat vae &Select All ProgramWindow&Zobrazen&View ProgramWindow DeskaBoard ProgramWindowKopruje vbrCopy selection ProgramWindowVyjme vbr Cut selection ProgramWindowSoubor '%1' byl obnoven ze souboru .fzz; Ulo~te mstn kopii pro prci s externm editorem.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindowSoubor '%1' byl obnoven ze souboru .fzz; mstn kopie nebyla nalezena.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindow(Vlo~ obsah schrnkyPaste clipboard contents ProgramWindow VpYedRedo ProgramWindow Vybere cel textSelect all text ProgramWindow.Zobraz okno O programu Show the application's about box ProgramWindowZptUndo ProgramWindowVrstva %1%1 LayerQObject8%1 maska exportu selhala (2)%1 mask export failure (2)QObjectZkladnBasicQObject DeskaBoardQObjectMont~n deska BreadboardQObject0Zobrazen mont~n deskyBreadboard ViewQObjectPosunout vpYed Bring forwardQObject"PYesunout dopYeduBring to frontQObjectNelze spustit Autorouting: ~dn deska (nebo vce desek) nenalezena5Cannot autoroute: no board (or multiple boards) foundQObject2Nelze  st soubor %1: %2.Cannot read file %1: %2.QObjectLNelze zapsat do asn soubor: %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject Zmna pinu %1,%2Change leg of %1,%2QObject(Kontrola aktualizaceCheck for updatesQObjectPYipojen ConnectionQObjectSpodn m Copper BottomQObject&Spodn mdn spojeCopper Bottom TraceQObject&Spodn mdn vplHCopper Fill BottomQObject&Horn mdn vplHCopper Fill TopQObjectHorn m Copper TopQObject$Horn mdn spojeCopper Top TraceQObject*Koprovn souboru %1Copying file %1QObjectUpravit odkaz Edit linkQObject6Chyba  ten souboru %1: %2.Error reading file %1: %2.QObjectLSoubor %1 ji~ existuje: nebude pYepsn/File %1 already exists: it won't be overwrittenQObject.Zpracovvn souboru...File Progress...QObject RmecFrameQObject4Editor plochy zemn vplnGround Fill Seed EditorQObject IkonaIconQObject VstupInputQObjectSpojit propojku Join WireQObjectMikroprocesorMicrocontrollerQObject*Sou stky nenalezeny.No parts found.QObjectPoznmkyNotesQObject Ouha!Oops!QObjectOstatnOtherQObject VstupOutputQObjectZobrazen PCBPCB ViewQObjectdChyba parsovn (1) na Ydce %1, sloupec %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObject`Chyba analzy (2) na Ydce %1, sloupec %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectSou stkaPartQObject"Obrzek sou stky Part ImageQObject"Popisky sou stek Part LabelsQObject8Sou stka je ji~ v zsobnkuPart already in binQObjectSou stkyPartsQObject8Slo~ka sou stek nenalezena.Parts folder not found.QObject&Editor popisku pinuPin Label EditorQObjectMjte na pamti, ~e nov nastaven jazyka se projev a~ pYi dalam spuatn Fritzingu.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectNapjenPowerQObjectPYedvolby PreferencesQObjectSe propojoRatsnestQObject VytvoY se spojoRatsnest wiresQObjectPravtkoRulersQObject$Zobrazen schmatuSchematic ViewQObjectVybrat %1 Select %1QObject"Vybrat vaechny %1 Select all %1QObjectBVybrat vaechny uzam en sou stkySelect locked partsQObjectFVybrat vaechny neaktuln sou stkySelect outdated partsQObjectPosunout vzad Send backwardQObjectSenzorySensorsQObject6Nastav plochu zemn vplnSet Ground Fill SeedQObject"Spodn silkscreenSilkscreen BottomQObjectJSpodn silkscreen (Popisky sou stek)Silkscreen Bottom (Part Labels)QObject Horn silkscreenSilkscreen TopQObjectHHorn silkscreen (Popisky sou stek)Silkscreen Top (Part Labels)QObjectJe nm lto, Fritzing zatm nezvldne piny a ploaky sou asn spolu (v %1 v %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectJe nm lto, ale Fritzing prozatm nezvldne piny a ploaky sou asn spolu. (in %1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectTJe nm lto, typ ploaky %1 nen podporovnSorry, can't handle pad type %1QObjectPromiHte, mme problm s pYepnacm mechanismem. Fritzing stle funguje, ale nebudete moci zmnit vlastnosti Sou stek.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObject"Rozdlit propojku Split WireQObjectFSoubor %1 nen soubor Fritzing (2).'The file %1 is not a Fritzing file (2).QObjectFSoubor %1 nen soubor Fritzing (3).'The file %1 is not a Fritzing file (3).QObjectFSoubor %1 nen soubor Fritzing (4).'The file %1 is not a Fritzing file (4).QObjectSoubor '%1' je jen pro  ten; Pou~ijte prosm jin nzev souboru.<b>Fritzing mo~n havaroval, ale nkter ze zmn v nsledujcch souborech mohou bt obnoveny.</b></p><p>Datum a  as ka~dho souboru kter byl zlohovn, je zobrazen. Pokud byl soubor ulo~en, jeho datum a  as je tak pro srovnn uveden.</p><p>Povodn soubory jsou stle na Vaaem disku, pokud byly vobec ulo~eny. Mo~ete vybrat, zda chcete pYepsat povodn soubor po na ten jeho obnovenho souboru.</p><p><b>Vyberte soubory, kter chcete obnovit z n~e uvedenho seznamu.</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialog SouborFileRecoveryDialogPosledn zloha Last backupRecoveryDialog"Naposledy ulo~eno Last savedRecoveryDialogsoubor neulo~enfile not savedRecoveryDialog OdporResistorResistor odpor resistanceResistorvlastncustomResizableBoardvaka(mm) height(mm)ResizableBoardvaka: %1mm height: %1mmResizableBoardtvarshapeResizableBoardvelikostsizeResizableBoardaYka(mm) width(mm)ResizableBoardaYka: %1mm width: %1mmResizableBoard aYkawidthRuler DatumDateSchematicFrame SouborFilenameSchematicFrameProjektProjectSchematicFrameRevSchematicFrameListSheetSchematicFrame datumdateSchematicFramezofSchematicFrametvarshapeSchematicFramelistsheetSchematicFrame.Zmna napt z %1 na %2Change voltage from %1 to %2SchematicSketchWidget ZruaitCancelSetColorDialog<Nastavit jako vchoz barvu %1Make this the default %1 colorSetColorDialog%1 %2 polo~ky %1 %2 items SketchWidgetpopiska %1 '%2' %1 label '%2' SketchWidgetPYidat %1Add %1 SketchWidget ZmnitChange SketchWidget4Zmnit barvu %1 z %2 na %3Change %1 color from %2 to %3 SketchWidget&Zmna %1 z %2 na %3Change %1 from %2 to %3 SketchWidget2Zmnit %1 popisku na '%2'Change %1 label to '%2' SketchWidget4Zmnit aYku %1 z %2 na %3Change %1 width from %2 to %3 SketchWidget.Zmna odporu z %1 na %2Change Resistance from %1 to %2 SketchWidget<Zmnit barvu propojky %1 na %2Change color of %1 wires to %2 SketchWidget2Zmnit obrzek z %1 na %2Change image from %1 to %2 SketchWidget>Zmnit zlomov bod pinu pro %1.Change leg bendpoint for %1. SketchWidget4Zmnit kYivku pinu pro %1.Change leg curvature for %1. SketchWidget<Zmnit aYku propojky %1 na %2Change width of %1 wires to %2 SketchWidgetPYipojitConnect SketchWidget(VytvoYte propojku %1Create and connect %1 SketchWidget8VytvoYit a pYipojit propojkuCreate and connect wire SketchWidgetBVytvoYit propojku ze st propojoCreate wire from Ratsnest SketchWidget&Vymazat se propojoDelete ratsnest SketchWidgetZrua vbrDeselect SketchWidgetOdpojit Disconnect SketchWidget<Odpojit vaechny propojky od %1Disconnect all wires from %1 SketchWidgetLOdpojit vaechny propojky od %1 polo~ek"Disconnect all wires from %1 items SketchWidgetDvojklik Double-click SketchWidgetZDvojklik pro odstrann tohoto zlomovho bodu&Double-click to delete this bend point SketchWidget0PYethnout nebo dvojklikDrag or double-click SketchWidgetPYeklopitFlip SketchWidget"PYeklopit %2 (%1) Flip %2 (%1) SketchWidgetPYesun %2 (%1) Move %2 (%1) SketchWidget,PYesun %2 polo~ky (%1)Move %2 items (%1) SketchWidget*Posunout popisku '%1'Move label '%1' SketchWidgetPYesunout pin Move leg of SketchWidget.Zmnit velikost popisku Resize Note SketchWidget<Zmnit velikost desky na %1 %2Resize board to %1 %2 SketchWidget<Zmnit velikost pravtka %1 %2Resize ruler to %1 %2 SketchWidget Oto itRotate SketchWidgetOto it %2 (%1)Rotate %2 (%1) SketchWidgetVybrat %1 Select %1 SketchWidget"Vybrat %1 polo~ekSelect %1 items SketchWidgetVybrat vae Select All SketchWidget Vbr Selection SketchWidgetTo se jev jako pokus o vytvoYen spoje napY vrstvami. Tato skute nost by nemla vzniknout: kontaktujte vvojYe.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget&zmnit popisky pinochange pin labels SketchWidget$na tn sokon eno done loading SketchWidgetz %1from %1 SketchWidget$na tn sou stky loading part SketchWidgetRnebo Alt-pYeta~en pro pYeta~en segmentuor alt-drag to move the segment SketchWidget do %1to %1 SketchWidgetspojtrace SketchWidgetpropojkawire SketchWidget%1 %n pska%1 %n psky%1 %n psek%1 %n strip(s) StripboardVyjmoutCut StripboardObnovenoRestored Stripboardsloupcocolumns Stripboard Ydkorows StripboardpopiseklabelSymbolPaletteItem naptvoltageSymbolPaletteItemTipy a TrikyTips and Tricks TipsAndTricks aYkawidth TraceWireArabatina - %1 Arabic - %1TranslatorListModel Bulharatina - %1Bulgarian - %1TranslatorListModel8 natina (zjednoduaen) - %1Chinese (Simplified) - %1TranslatorListModel0 natina (tradi n) - %1Chinese (Traditional) - %1TranslatorListModel eatina - %1 Czech - %1TranslatorListModel Holandatina - %1 Dutch - %1TranslatorListModelAngli tina - %1 English - %1TranslatorListModelEstonatina - %1 Estonian - %1TranslatorListModel$Francouzatina - %1 French - %1TranslatorListModel"Galicijatina - %1 Galician - %1TranslatorListModelNm ina - %1 German - %1TranslatorListModelXe tina - %1 Greek - %1TranslatorListModel Hebrejatina - %1 Hebrew - %1TranslatorListModelHindatina - %1 Hindi - %1TranslatorListModelMaaratina - %1Hungarian - %1TranslatorListModel Indonatina - %1Indonesian - %1TranslatorListModelItalatina - %1 Italian - %1TranslatorListModelJaponatina - %1 Japanese - %1TranslatorListModelKorejatina - %1 Korean - %1TranslatorListModelPolatina - %1 Polish - %1TranslatorListModel<Portugalatina (Brazilsk) - %1Portuguese (Brazilian) - %1TranslatorListModel8Portugalatina (Evropsk)- %1Portuguese (European)- %1TranslatorListModelRumunatina - %1 Romanian - %1TranslatorListModelRuatina - %1 Russian - %1TranslatorListModel `panlatina - %1 Spanish - %1TranslatorListModel`vdatina - %1 Swedish - %1TranslatorListModelThajatina - %1 Thai - %1TranslatorListModelTure tina - %1 Turkish - %1TranslatorListModelbNov prozatmn vydn je k dispozici ke sta~en:3A new interim release is available for downloading: UpdateDialog\Nov hlavn vydn je k dispozici pro sta~en:0A new main release is available for downloading: UpdateDialogKontrola... Checking... UpdateDialog ZavYtClose UpdateDialog8}dn nov verze nenalezena.No new versions found. UpdateDialogXLituji, nelze na st informace o aktualizaci%Sorry, unable to retrieve update info UpdateDialog  ernblackWire modrblueWire hndbrownWire barvacolorWire(extra siln (48 mil)extra thick (48 mil)Wire zelengreenWireaedgreyWireoran~ovorangeWirefialovpurpleWire ervenredWiresiln (32 mil)thick (32 mil)Wiretenk (16 mil) thin (16 mil)WireblwhiteWire ~lutyellowWirefritzing-app-0.9.2b/translations/fritzing_cs.ts000066400000000000000000014671751250202676700217440ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 na kód a CreativeCommons:BY-SA na zbytek <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Fritzing vytvořili: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, a Daniel Tzschentke. Special thanks goes out to: Zvláštní poděkování patří: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzimu, Ayah Bdeirovi, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrelul Bishopovi, Davidu Cuartiellesovi, Fabianu Hemmertovi, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrathovi, Jeffu Hoefsovi, Tomu Hulbertovi, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tomu Igoevi, Hans-Peteru Kadelovi, Tillu Savelkoulovi, Jan Sieber, Yaniv Steiner, Olaf Val, Janu Sieberovi, Yaniv Steinerovi, Olafu Vaolovi, Michaela Vieser and Julia Werner. Michaele Vieserové a Julii Wernerové. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Děkujeme Kurtu Badeltovi a Miguelu Solisovi za Španělský překlad, to Gianluca Urgese for the Italian translation, Gianluca Urgese za Italský překlad, to Nuno Pessanha Santos for the Portuguese (European) translation, Nuno Pessanha Santosovi za Portugalský (Evropský) překlad, to Yuelin and Ninjia for the Chinese (Simplified) translation, Yuelinovi a Ninjiovi za Čínský (zjednodušený) překlad, to Hiroshi Suzuki for the Japanese translation, Hiroshi Suzukimu za Japonský překlad, to Robert Lee for the Chinese (Traditional) translation, Robertu Lee za Čínský (tradiční) překlad, to Vladimir Savinov for the Russian translation, Vladimiru Savinovi za Ruský překlad, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, Josefu Duštírovi za Český překlad, to Jinbuhm Kim for the Korean translation, Jinbuhm Kimovi za Korejský překlad, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the Fritzing bylo možné vytvořit s financováním MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, sponzor Designu Department of Bauhaus-University Weimar, Oddělení Bauhaus univerzity Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, anonymní dárce, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students Zvláštní poděkování patří také všem studentům and alpha testers who were brave enough to give a alfa testerům, kteří měli odvahu se Fritzing a test spin. pustit do kola testů Fritzingu. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls řízení zvětšení a posunu Stop Now Zastavit Best So Far Cancel Zrušit Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type Typ výroby homebrew domácí výroba professional profesionální custom vlastní Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Šířka spoje Cancel Zrušit OK OK BinManager Parts Součástky BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Nelze nastavit zásobník '%1' jako dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Nelze nastavit zásobník '%1' jako dirty New bin (%1) Nový zásobník (%1) Select a Fritzing Parts Bin file to open Vybrat Fritzing soubor zásobníku součástek pro otevření Searching... Bin Zásobník Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Nový zásobník... Create a new parts bin Vytvoří nový zásobník součástek Close Bin Zavřít zásobník Close parts bin Zavře zásobník součástek Delete Bin Vymazat zásobník Delete parts bin Vymaže zásobník součástek Save Bin Uložit zásobník Save parts bin Uloží zásobník součástek Save Bin As... Uložit zásobník jako... Save parts bin as... Uloží zásobník součástek jako... Export Bin... Exportovat zásobník... Save parts bin in compressed format... Uloží zásobník součástek v komprimovaném formátu... Rename Bin... Přejmenovat zásobník... Rename parts bin... Přejmenuje zásobník součástek... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Zobrazit zásobník jako seznam Display parts as a list Zobrazí součástky jako seznam Show Bin in Icon View Zobrazit zásobník jako ikony Display parts as icons Zobrazí součástky jako ikony Edit Part (new parts editor)... Export Part... Exportovat součástku... Remove Part Odstranit součástku Find Part in Sketch Delete bin Vymazat zásobník Do you really want to delete bin '%1'? This action cannot be undone. Opravdu chcete vymazat zásobník '%1'? Tuto akci nelze vrátit. Read-only bin Zásobník pouze pro čtení This bin cannot be renamed. Tento zásobník nelze přejmenovat. Rename bin Přejmenuje zásobník Please choose a name for the bin: Zvolte název pro zásobník: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Odstranit ze zásobníku Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Vybrat soubor Fritzing pro otevření Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing soubory zásobníku (*%1 *%2);;Fritzing zásobník (*%1);;Fritzing sdílený zásobník (*%2) Cannot set a NULL bin as the current one Nelze nastavit NULL zásobník jako aktuální Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) jedna vrstva (jednostranný) two layers (double-sided) dvě vrstvy (oboustranný) image file soubor obrázku load image file načíst soubor obrázku Images Obrázky Select an image file to load Preferencesyberte soubor obrázku due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Nelze načíst Unable to load image from %1 %2 Nelze načíst obrázek z %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape tvar BreadboardLogoItem color barva Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Přidat bod zlomu Straighten curve Vyrovnat křivku Remove bendpoint Odstranit bod zlomu ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools Nástroje &About &O programu About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit &Ukončit Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Váš návrh je připraven pro výrobu: nebyly nalezeny žádné překrývající se propojky,ani spoje a současně také nejsou příliš blízko sebe. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging pro debugging DeleteDialog Also delete the file Odstranit také soubor Remove Odstranit Don't remove Neodstraňovat Dip chip label popisek čipu FApplication Fritzing failure Aplikace Fritzing selhala Fritzing caught an exception %1 from %2 in event %3 Fritzing zachytil vyjímku %1 z %2 v události %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Fritzing zachytil vyjímku z %1 v události %2 Import files from previous version? Importovat soubory z předchozí verze? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Přejete si importovat součástky a zásobníky, které jste vytvořili v předchozí verzi Fritzingu? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Pozn.: Můžete importovat později, s použitím položky "Nápověda" > "Import součástek a zásobníků z dřívější verze..." z nabídky. Import Import Do not import now Nyní neimportovat Please specify an .fzz file name to save to (cancel will delete the backup) Zadejte název souboru .fzz pro uložení (Zrušit odstraní zálohu) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help První nápověda <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Zavřít okno Ctrl+W Ctrl+W Close the current sketch Uzavře aktuální návrh %1 - %2 %1 - %2 Specify a file name Zadejte název souboru Save "%1" Uložit "%1" Do you want to save the changes you made in the document "%1"? Přejete si uložit změny provedené v dokumentu "%1"? Your changes will be lost if you don't save them. Vaše změny budou ztraceny, pokud je neuložíte. Save... Uložit... Save Uložit Don't Save Neukládat Cancel Zrušit Ctrl+D Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Rozdíl mezi 'výplní země' a prostou 'výplní měďí' je ten, že ve výplni země, obsahuje vyplněná plocha spoje a konektory, které jsou připojeny na 'zemnící' konektory. Zemnící konektory jsou obvykle označeny jako "GND", nebo "zem", ale někdy to však nemusí být tento případ. Další možností také může být, že na desce jsou různé sítě se zemním konektorem, a vy budete chtít vyplnit pouze jednu z těchto sítí. Tento dialog shromažďuje pouze konektory s označením "GND" nebo "zem", stejně tak jako konektory již vybrané jako zemnící. Poklepáním na položku zvýrazníte v návrhu její propoje. Je také možné zvolit konektory jako výplň země kliknutím pravým tlačítkem myši na konektor a z kontextové nabídky vybrat 'Nastavit výplň země". Cancel Zrušit OK OK OK and ground fill OK a vyplnit zemí OK and copper fill OK a vyplnit mědí Hole hole size velikost otvoru HtmlInfoView Change the part label here Zde změnit popisek součástky Part breadboard view image Obrázek součástky montážní desky Part schematic view image Obrázek součástky schématu Part pcb view image Obrázek součástky desky PCB Part version number Číslo verze součástky Locked Uzamčeno Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Vlastnosti Placement pcb layer Tags Značky Connections Piny conn. kon. name název type typ connected to %n item(s) připojeno k %n položce připojeno ke %n položkám připojeno k %n položkám (autoroutable) (automaticky routovatelné) Wire Propojka Ratsnest wire Propojovací síť Trace wire %1 Plošný spoj %1 v. %1 %2 v. %1 %2 obsolete location rotation degrees ItemBase family rodina type typ model model size velikost color barva resistance odpor capacitance kondenzátor inductance indukčnost voltage napětí current aktuální power napájení pin spacing odstup pinů rated power jmenovité napájení rated voltage jmenovité napětí rated current jmenovitý proud version verze package pouzdro shape tvar form forma part number číslo součástky maximum resistance maximální odpor pins piny spacing odstup frequency kmitočet processor procesor variant varianta layers vrstvy tolerance tolerance descr popis filename název souboru title titulek date datum rev rev sheet list project projekt banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part Součástka model part problem problém modelu součástky file for %1 %2 not found unable to create renderer for svg %1 nelze vytvořit renderování svg %1 KicadModuleDialog Cancel Zrušit OK OK LayerPalette show all layers zobrazit všechny vrstvy LinkDialog url: url: text: text: Cancel Zrušit OK OK LogoItem text shape tvar due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Nelze zobrazit Unable to display image from %1 Nelze zobrazit obrázek z %1 MainWindow Rotate Otočit Share Sdílet Flip Překlopit Autoroute Automaticky routovat Both Layers Obě vrstvy Bottom Layer Spodní vrstva Top Layer Horní vrstva Add a note Přidá poznámku Ready Připraven Save %1 Uložit %1 Unable to open '%1': %2 Specify a file name Zadejte název souboru Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Nelze exportovat %1 jako sdílený Fritzing Part (*%1) Fritzing součástka (*%1) Unable to export %1 to shareable sketch Nelze exportovat %1 do sdíleného návrhu Do you want to keep the imported parts? Přejete zachovat importované součástky? No connections to route Žádné propojky k routování Routing completed Routing dokončen Routing completed using %n jumper part(s) Routing dokončen s použitím %n propojky Routing dokončen s použitím %n propojek Routing dokončen s použitím %n propojek Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed %1 z %2 routovaných propojů - %n propojka, která bude ještě routována %1 z %2 routovaných propojů - %n propojky, které budou ještě routovány %1 z %2 routovaných propojů - %n propojek, které budou ještě routovány Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB Export pro PCB No Sketch found in '%1' V '%1' žádný návrh nenalezen Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] %1 - [%2] No copper top layer Žádná měděná horní vrstva The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Na jednostranné desce není horní měděná vrstva (měď 1) k dispozici. Přepněte desku na oboustrannou, nebo zvolte spodní měděnou vrstvu (měď 0). Sorry! Promiňte! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Součástka s touto charakteristikou neexistuje. Pracujeme na potlačení této zprávy a nyní Vám nezbývá, než zvolit mezi vlastnostmi, které existují No exactly matching part found; Fritzing chose the closest match. Nebyla nalezena přesně shodná součástka; Fritzing vybral součástku s nejbližšími vlastnostmi. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Přepnut %1 s modulem %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. SVG %1 neobsahuje vrstvu '%2'. Další informace o tom, jak vytvořit vlastní obrazec desky naleznete v kurzu na <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 načítání %1 Loading... Načítání... new sketch nový návrh Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Zálohovat '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Váš návrh dosud neobsahuje desku! Pro úspěšný export do Gerber přidejte PCB. Choose a folder for exporting Vybrat složku pro export PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG obrázek (*.png) JPEG Image (*.jpg) JPEG obrázek (*.jpg) SVG Image (*.svg) SVG obrázky (*.svg) Printing... Tisk... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Nebyly zroutovány ještě všechny spoje. Do you want to proceed anyway? Přesto chcete pokračovat? Proceed Provést Cancel Zrušit Sketch exported Návrh exportován Export... Export... Exporting... Exportování... Unable to save %1 Nelze uložit %1 Cannot print to %1 Nelze tisknout na %1 Cannot write file %1: %2. Nelze zapsat soubor %1: %2. Saved '%1' Uložit '%1' Select a Fritzing File to Open Vybrat soubor Fritzing pro otevření Cannot find file %1. Nelze nalézt soubor %1. Cannot read file 1 %1: %2. Nelze číst soubor 1 %1: %2. File '%1' not found Soubor '%1' nenalezen directly loading parts přímé načtení součástek loading %1 (model) načítání %1 (model) loading %1 (breadboard) načítání %1 (montážní deska) loading %1 (pcb) načítání %1 (pcb) loading %1 (schematic) načítání %1 (schéma) New Nový Ctrl+N Ctrl+N Create a new sketch Vytvoří nový návrh &Open... &Otevřít... Ctrl+O Ctrl+O &Save &Uložit Ctrl+S Ctrl+S Save the current sketch Uloží aktuální návrh &Save As... &Uložit jako... Shift+Ctrl+S Shift+Ctrl+S Share online... Sdílet online... Post a project to the Fritzing website Pošle projekt na webové stránky Fritzing JPG... JPG... Export the visible area of the current sketch as a JPG image Exportuje viditelnou oblast aktuálního návrhu jako JPG obrázek PNG... PNG... Export the visible area of the current sketch as a PNG image Exportuje viditelnou oblast aktuálního návrhu jako PNG obrázek PostScript... PostScript... Export the visible area of the current sketch as a PostScript image Exportuje viditelnou oblast aktuálního návrhu jako PostScript obrázek PDF... PDF... Export the visible area of the current sketch as a PDF image Exportuje viditelnou oblast aktuálního návrhu jako PDF obrázek SVG... SVG... Export the current sketch as an SVG image Exportuje aktuální návrh jako SVG obrázek List of parts (&Bill of Materials)... Seznam součástek (&Soupiska materiálu)... Save a Bill of Materials (BoM)/Shopping List as text Uloží soupisku materiálu (BoM)/Nákupní seznam jako text XML Netlist... XML Netlist... Save a netlist in XML format Uloží netlist v XML formátu SPICE Netlist... Save a netlist in SPICE format Eagle... Eagle... Export the current sketch to Eagle CAD Exportuje aktuální návrh do Eagle CAD Etchable (PDF)... Leptatelné (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Exportuje aktuální návrh do PDF pro DIY výrobu PCB (fotocesta) Export the current sketch to SVG for DIY PCB production (photoresist) Exportuje aktuální návrh do SVG pro DIY výrobu PCB (fotocesta) Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Návrh exportován do Gerber BoM Text File (*.html) Textový soubor BoM (*.html) Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Exportuje aktuální návrh do Extended Gerber formátu (RS-274X) pro professionální výrobu PCB Etchable (SVG)... Leptatelné (SVG)... &Print... &Tisk... Ctrl+P Ctrl+P Print the current view Vytiskne aktuální pohled Shell launch %1 Shell spustil %1 throw test exception vlož testovací vyjímku throw a fake exception to see what happens Vloží falešnou výjimku , aby bylo vidět, co se stane &Quit &Ukončit Ctrl+Q Ctrl+Q Quit the application Ukončí aplikaci &Open Example &Otevřít příklad All Vše MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: nelze načíst příklad s id='%1' &Open Recent Files &Otevřít nedávné soubory &%1 %2 &%1 %2 Undo Zpět Redo Vpřed &Cut V&yjmout Cut selection Vyjme výběr &Copy &Kopírovat Copy selection Kopíruje vybrané &Paste &Vložit Paste clipboard contents Vloží obsah schránky Paste in Place Vložit na místo Paste clipboard contents in place Vloží obsah schránky na místo &Duplicate &Duplikovat Ctrl+D Ctrl+D Duplicate selection Duplikuje výběr &Delete &Vymazat Delete selection Vymaže výběr &Select All &Vybrat vše Select all elements Vybere všechny prvky &Deselect &Zrušit výběr Deselect Zruší výběr Add Note Přidat poznámku &Preferences... &Předvolby... Show the application's about box Zobrazí okno O programu &Edit &Upravit &Add to bin... &Přidat do zásobníku... Add selected part to bin Přidá vybranou součástku do zásobníku Disconnect All Wires Odpojí všechny propojky Disconnect all wires connected to this connector Odpojí všechny propojky od této špičky Update InfoView on hover Aktualizuje InfoView při přechodu Export Normalized SVG Exportuje normalizované SVG Export 1000 dpi SVG of this part in this view Exportuje 1000 dpi SVG této součástky v tomto zobrazení Export Normalized Flattened SVG Exportuje normalizované sloučené SVG Export 1000 dpi Flattened SVG of this part in this view Exportuje 1000 dpi sloučený SVG této součástky v tomto zobrazení Rotate the selected parts by 90 degrees clockwise Otočí vybrané součástkyr o 90 stupňů vpravo Rotate the selected parts by 180 degrees Otočí vybrané součástkyr o 180 stupňů Rotate current selection 90 degrees counter clockwise Otočí aktuální výběr o 90 stupňů vlevo Rotate current selection 45 degrees counter clockwise Otočí aktuální výběr o 45 stupňů vlevo Rotate current selection 45 degrees clockwise Otočí aktuální výběr o 45 stupňů vpravo Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? the .fz file format is obsolete fz formát je zastaralý The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? fz formát se již nepoužívá. Chtěli byste změnit '%1' do formátu fzz nyní, nebo otevřít pouze pro čtení? The conversion process will not modify '%1'. Procesem převodu se '%1' nemění. Convert Převést Read-only Pouze pro čtení Please specify an .fzz file name to save '%1' to Zadejte název souboru .fzz pro oložení '%1' do Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal &Překlopit vodorovně Flip current selection horizontally Překlopí aktuální výběr vodorovně &Flip Vertical &Překlopit svisle Flip current selection vertically Překlopí aktuální výběr svisle Bring to Front Přesunout dopředu Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Přenese vybraný(é) objekt(y) dopředu v jejich vrstvě Bring Forward Posunout vpřed Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Posune vybraný(é) objekt(y) vpřed v jejich vrstvě Send Backward Posunout vzad Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Posune vybraný objekt(y) vzad ve své vrstvě Send to Back Přesunout dozadu Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Přesune vybraný objekt(y) dozadu ve své vrstvě Lock Part Uzamknout součástku Prevent a part from being moved Zabrání přesunu součástky Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Vybrat všechny uzamčené součástky Select all parts that can't be moved Vybere všechny součástky, které nemohou být přesunuty &Show All Layers &Zobrazit všechny vrstvy Show all the available layers for the current view Zobrazí všechny dostupné vrstvy pro aktuální zobrazení &Hide All Layers &Skrýt všechny vrstvy Hide all the layers of the current view Skryje všechny vrstvy aktuálního zobrazení &Show part label &Zobrazit popisku součástky Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Otočit o 135° doprava {45�?} Rotate 90� Clockwise Otočit o 135° doprava {90�?} Rotate 180� Otočit o 180° {180�?} Rotate 90� Counter Clockwise Otočit o 45° doleva {90�?} Rotate 45� Counter Clockwise Otočit o 45° doleva {45�?} Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom &Export... &Exportovat... Export selected part Exportuje vybranou součástku Add Bendpoint Přidat bod zlomu Add a bendpoint to the selected wire Přidá bod zlomu vybrané propojce Straighten Curve Vyrovnat křivku Straighten the curve of the selected wire Vyrovná křivku vybrané propojky Select outdated parts Vybrat neaktuální součástky Update selected parts Aktualizovat vybrané součástky Find part in sketch... Search for parts in a sketch by matching text Open programming window Otevřít programátorské okno Open microcontroller programming window Otevře programátorské okno mikroprocesoru &Zoom In &Zvětšit Ctrl++ Ctrl++ Zoom in Zvětšit Ctrl+= Ctrl+= &Zoom Out &Zmenšit Ctrl+- Ctrl+- Zoom out Zmenšit &Fit in Window &Přizpůsobit oknu Ctrl+0 Ctrl+0 Fit in window Přizpůsobí oknu &Actual Size &Aktuální velikost Actual (real world physical) size Aktuální (skutečná fyzická) velikost 100% Size 100% Velikost Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size 100% (pixelů) velikost Align to Grid Přichytit k mřížce Align items to grid when dragging Při přetažení přichytí položky k mřížce Show Grid Zobrazit mřížku Show the grid Zobrazí mřížku Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+4 Ctrl+4 Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Parts Editor Help Display Parts Editor help in a browser Align &Routing &Routování Move to bottom layer Move to top layer top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size Aktuální velikost It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Zdá se, že není možné automaticky určit skutečnou, fyzickou velikost monitoru, takže současně implementovaná 'aktuální velikost' je pouhý odhad. Nejlepší by bylo použít funkci pravítka, poté přes něj umístit skutečné pravítko (fyzické) a měnit velikost, dokud se neshodují. &Create trace from ratsnest &Vytvořit spoj ze sítě propojů Create a trace from the ratsnest line Vytvoří spoj z propoje &Create wire from ratsnest &Vytvořit propojku ze sítě propojů Create a wire from the ratsnest line Vytvoří prostý propoj z propojky Show unrouted Highlight all unrouted connectors Select All Wires Vybrat všechny propojky Select all wires Vybere všechny propojky Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Choose Ground Fill Seed(s)... Vybrat plochu(y) zemní výplně... Set Ground Fill Seed Nastaví plochu zemní výplně Treat this connector and its connections as a 'ground' during ground fill. Během vytváření zemní výplně považovat tento konektor a jeho připojení jako "zem". Clear Ground Fill Seeds Vymazat plochy zemní výplně Clear ground fill seeds--enable copper fill only. Vymaže plochy zemní výplně--povolí pouze výplň mědí. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Check Loaded Traces Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. jumpers copperfill vias The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... Vytváření %1 výplňl... ground zemní copper měděnou Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. nelze nalézt náhradu pro %1. OK OK Set the grid size for %1. Nastaví velikost mřížky pro %1. Grid Size: Velikost mřížky: in palce mm mm Restore Default Obnovit výchozí Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. &Show Breadboard &Zobrazit montážní desku Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show/hide the label for the selected parts Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+1 Ctrl+1 Show the breadboard view Zobrazí pohled na montážní desku &Show Schematic &Zobrazit schéma Ctrl+2 Ctrl+2 Show the schematic view Zobrazí pohled na schéma &Show PCB &Zobrazit PCB Ctrl+3 Ctrl+3 Ctrl+Shift+V Show the PCB view Zobrazí pohled na PCB Show Code Show the code (programming) view Show Parts Bin Icon View Zobrazit součástky zásobníku jako ikony Display the parts bin in an icon view Zobrazí zásobník součástek jako ikony Show Parts Bin List View Zobrazit součástky zásobníku jako seznam Display the parts bin in a list view Zobrazí zásobník součástek jako seznam &Minimize &Minimalizovat Ctrl+M Ctrl+M Minimize current window Minimalizuje aktuální okno Debugger Output Výstup debuggeru Online Tutorials Online výuka Ctrl+? Ctrl+? Open Fritzing help Otevře nápovědu Fritzingu Donate to Fritzing Podpořte Fritzing Open Fritzing donation web page Otevře web stránku daru pro Fritzing Online Projects Gallery Online galerie projektů Open Fritzing examples Otevře Fritzing příklady Online Parts Reference Online reference součástek Open Parts Reference Otevře reference součástek First Time Help První nápověda Check for updates... Kontrola aktualizace... Check whether a newer version of Fritzing is available for download Zkontroluje, zda není ke stažení novější verze Fritzingu &About &O programu Tips, Tricks and Shortcuts Tipy, triky a klávesové zkratky Display some handy Fritzing tips and tricks Zobrazí některé užitečné tipy a triky Fritzingu &About Qt &O Qt Show Qt's about box Zobrazí okno o Qt's Report a bug... Nahlásit chybu... Report a but you've found in Fritzing Nahlásí chybu, kterou jste nalezli ve Fritzingu Enable debugging log Povolit debugging log &Import parts and bins from old version... &Import součástek a zásobníků z předchozích verzí... Import parts and bins from previous installation Importuje součástky a zásobníky z předchozích instalací &File &Soubor &Export &Exportovat as Image jako obrázek for Production pro výrobu &Part &Součástka Raise and Lower Řazení &View &Zobrazení &Window &Okno Ground Fill Zemnící výplň &Help &Nápověda Delete Ratsnest Line Vymazat propojovací čáru Delete Wire Vymazat propojku Hide part label Skrýt popisek součástky Show part label Show part silkscreen Autoroute connections... Shift+Ctrl+A Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Do not autoroute Neprovádět autoroutování When autorouting, do not rip up this trace wire, via, or jumper item Při autoroutingu se nezničí tento propojovací spoj, průchod, nebo propojku Move to other side of the board Přesunout na druhou stranu desky Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Přesunoue vybrané spoje na druhou stranu desky (Pozn.: "první" stopa bude přesunuta a ostatní budou následovat na stejnou stranu) Select All CopperFill Vybrat všechny měděné výplně Select all copper fill items Vybere všechny položky měděné výplně Select all jumper item parts Vybrat všechny položky propojek součástek Select All Vias Vybrat všechny průchodky Select all via parts Vybere všechny průchodky součástek Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Vyplní prázdné oblasti měděné vrstvy--včetně všech spojů připojených k ZEMI Fill empty regions of the copper layer--not including traces connected to a GROUND Vyplní prázdné oblasti měděné vrstvy--s vyjímkou všech spojů připojených k ZEMI Fill empty regions of the copper layer--fill will include all traces connected to the seeds Vyplní prázdné oblasti měděné vrstvy--výplň bude obsahovat všechny spoje připojené k plochám Shift+Ctrl+D Shift+Ctrl+D Delete Vymazat Page Setup Nastavení stránky Sorry, "%1" has not been implemented yet Promiňte, funkce %1 nebyla dosud implementována This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Tato funkce brzy poskytne export návrhu Fritzing do EAGLE PCB software. Pokud byste chtěli mít více exportů do svých oblíbených nástrojů EDA, prosím dejte nám vědět, nebo nám přispějte. Export SVG... Exportovat SVG... Export Bill of Materials (BoM)... Export soupisky materiálu (BoM)... Unable to save BOM file, but the text is on the clipboard. Nelze uložit soubor BOM, ale text je uložen ve schránce. Export Netlist... Export netlistu... Set both copper layers clickable Nastaví obě měděné vrstvy klikatelné Set copper top layer clickable Nastaví horní měděnou vrstvu klikatelnou Set copper bottom layer clickable Nastaví spodní měděnou vrstvu klikatelnou Select All Traces Vybere všechny spoje Select all trace wires Vybere všechny spoje Force Update Routing Status and Ratsnests Provedení aktualizace routingu a propojení Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Přepočítat stav routingu a propojení propojek (v případě, že autoaktualizace nepracuje správně) Select all trace wires excluded from autorouting Vybere všechny spoje vyjmuté z autoroutingu Select All Jumpers Vybrat všechny propojky Tidy Wires Uspořádat propoje Tidy selected wires Uspořádá vybrané propoje Copper Fill Měděná výplň Remove Copper Fill Odstranit měděnou výplň Remove the copper fill Odstraní měděnou výplň Copper Top and Copper Bottom layers are both active Obě měděné vrstvy, horní i spodní, jsou aktivní Order a PCB... Objednat PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Objedná PCB, vytvořené z Vašeho návrhu - v báječném Fritzing Fab Copper Top layer is active Horní měděná vrstva je aktivní Copper Bottom layer is active Spodní měděná vrstva je aktivní Autorouting... Autorouting... Autorouting Progress... Probíhá autorouting... Remove Bendpoint Odstranit bod zlomu Please choose the previous Fritzing folder... Vyberte předchozí složku Fritzingu... You will have to restart Fritzing in order to use the imported parts Pro použití importovaných součástek musí být Fritzing restartován Remove copper fill Odstranit měděnou výplň &Wire Color &Barva propojky Launch %1... Spustit %1... No outdated parts found. All your parts are up-to-date. Nebyly nalezeny žádné neaktuální součástky. Všechny Vaše součástky jsou aktuální. Outdated parts Neaktuální součástky Do you want to update now? Successfully updated %1 part(s). Please check all views for potential side-effects. Úspěšně aktualizováno %1 součástek. Zkontrolujte, všechny pohledy pro potenciální vedlejší účinky. Update %1 part(s) Aktualizace %1 součástek Inspector Inspektor Undo History Historie Zpět Breadboard Montážní deska Schematic Schéma PCB PCB Layers Vrstvy Couldn't get the dock widget Nelze zadokovat widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: kolo %1 z: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): Nelze nalézt následující %n součástku: Nelze nalézt následující %n součástky: Nelze nalézt následujících %n součástek: at v File save failed! Uložení souboru selhalo! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Není možné přepsat soubor '%1'. Důvod: %2 (chyb.kód %3) MysteryPart label popisek chip label popisek čipu NetLabel net label Note [write your note here] [zde napište poznámku] PCBSketchWidget Create Trace from Ratsnest Vytvořit spoj ze sítě propojů Click this connector to drag out a new trace. Klikněte na tento pin pro vytažení nového spoje. Change trace layer Změnit vrstvu spoje Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Váš návrh ještě neobsahuje desku! Přidejte PCB Aby bylo možné použít měděnou výplň. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Před vytvořením zemní výplně určete jednu nebo více zemních ploch výplně. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Chyba Fritzingu: Nelze renderovat desku v SVG (1). Fritzing error: unable to render copper svg (1). Chyba Fritzingu: Nelze renderovat měď v SVG (1). Fritzing error: unable to write copper fill (1). Chyba Fritzingu: Nelze zapsat měděnou výplň (1). Fritzing error: unable to write copper fill (2). Chyba Fritzingu: Nelze zapsat měděnou výplň (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Nelze vytvořit měděnou výplň - pravděpodobně součástka nebyla vloženal na PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Nelze vytvořit měděnou výplň - součástka byla pravděpodobně vložena na jinou část nebo propoj, spíše než aktuální PCB. Clear ground fill seeds Vymazat plochy zemní výplně Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor Editor součástek SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Ikona Metadata Connectors Piny Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Ctrl+4 Show the icon view Ctrl+5 Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Soubory obrázků & patic (%1 %2 %3 %4 %5);;SVG soubory (%1);;JPEG soubory (%2);;PNG soubory (%3);;soubory gEDA patic (%4);;soubory Kicad modulů (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Soubory obrázků (%1 %2 %3);;SVG soubory (%1);;JPEG soubory (%2);;PNG soubory (%3)%4%5 Open Image Otevřít obrázek Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Problém konverze Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Vrstvy Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 v %1 nenalezeno žádné schéma schematic part schéma součástky no footprints found in %1 v %1 nenalezena žádná patice Relocate connector %1 &File &Soubor Inspector Inspektor Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Exportovat &Edit &Upravit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Uložit Cancel Zrušit Move terminal point Remove connector Remove %1 connectors Save "%1" Uložit "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. Vaše změny budou ztraceny, pokud je neuložíte. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Přidat konektor Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Datum Set the part's author Author Autor Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Popis Set the default part label prefix Label Popisek Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Vlastnosti Set the part's tags Tags Značky PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center střed west západ north sever south jih east východ Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape tvar center střed north sever east východ south jih west západ connect to propojit s PaletteItem Edit Pin Labels Upravit popisku pinu Fritzing Fritzing Unable to proceed; unable to find top level view. Nelze pokračovat, nelze najít nejvyšší úroveň zobrazení. Unable to proceed; part connectors do no have standard IDs. Nelze pokračovat, piny součástky nemají standardní ID. Label mismatch. Nothing was saved. Popisek nesoulhlasí. Nic nebylo uloženo. hole size velikost otvoru advanced settings rozšířené nastavení in palce mm mm Hole Diameter Průměr otvoru Ring Thickness Tloušťka kruhu PartLabel Edit Upravit Edit label text Upravit text popisku Hide Skrýt Hide part label Skrýt popisek součástky Display Values Zobrazit hodnoty Flip/Rotate Překlopit/Otočit Font Size Velikost písma Rotate the label by 45 degrees clockwise Otočí popisek o 45° doprava Rotate the label by 90 degrees clockwise Otočí popisek o 90° doprava Rotate the label by 135 degrees clockwise Otočí popisek o 135° doprava Rotate the label by 180 degrees Otočí popisek o 180° Rotate the label by 135 degrees counter clockwise Otočí popisek o 135° doleva Rotate current selection 90 degrees counter clockwise Otočí aktuální výběr o 90° doleva Rotate 45� Clockwise Otočit o 135° doprava {45�?} Rotate 90� Clockwise Otočit o 135° doprava {90�?} Rotate 135� Clockwise Otočit o 135° doprava {135�?} Rotate 180� Otočit o 180° {180�?} Rotate 135� Counter Clockwise Otočit o 45° doleva {135�?} Rotate 90� Counter Clockwise Otočit o 45° doleva {90�?} Rotate 45� Counter Clockwise Otočit o 45° doleva {45�?} Rotate the label by 45 degrees counter clockwise Otočí popisek o 45° doleva Flip Horizontal Překlopit vodorovně Flip label horizontally Překlopí popisek vodorovně Flip Vertical Překlopit svisle Flip label vertically Překlopí popisek svisle Tiny Nejmenší Set font size to tiny Nastaví nejmenší velikost písma Small Malé Set font size to small Nastaví malou velikost písma Medium Střední Set font size to medium Nastaví středníí velikost písma Large Velké Set font size to large Nastaví velkou velikost písma Label text Text popisku Display the text of the label Zobrazí text popisku Display the value of property %1 Zobrazí hodnotu vlastnosti %1 Set label for %1 Nastaví popisek pro %1 Label text: Text popisku: PartsBinPaletteWidget Untitled Bin Nepojmenovaný zásobník Save Uložit Specify a file name Zadejte název souboru Fritzing Bin (*%1) Fritzing zásobník (*%1) Fritzing Fritzing Cannot find file %1. Nelze nalézt soubor %1. Cannot read file %1: %2. Nelze číst soubor %1: %2. Loading... Načítání... loading bin '%1' načítání zásobníku %1 Save bin "%1" Uložit zásobník "%1" Do you want to save the changes you made in the bin "%1"? Přejete si uložit změny provedené v zásobníku "%1"? Your changes will be lost if you don't save them. Vaše změny budou ztraceny, pokud je neuložíte. Don't Save Neukládat Ctrl+D Ctrl+D Cancel Zrušit Add to bin Přidat do zásobníku Do you really want to add the selected part to the bin? Opravdu chcete přidat vybranou součástku do zásobníku? Change icon color... Změnit barvu ikony... Change the color of the icon for this bin. Změnit barvu ikony tohoto zásobníku. Select a color for this icon Vybere barvu této ikony Perfboard size velikost Performance Warning Upozornění výkonu Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Provádění perfboards a stripboards s více než cca 2000 otvory může být pomalé. Jste si jisti? Poznámka: Během této relace se již toto varování nebude opakovat. Set new size Nastavit novou velikost Cancel Zrušit rows řádků columns sloupců set board size nastavit velikost desky PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Editor popisku pinu</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Klikněte na popisek vedle čísla pinu pro přejmenování tohoto pinu. You can use the tab key to move through the labels in order.</p> Můžete použít klávesu Tab k posunu přes popisky.</p> Cancel Zrušit Save Uložit Undo Zpět Redo Vpřed PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Všeobecné Cancel Zrušit OK OK Mouse Wheel Behavior Chování kolečka myši Command Příkaz Control Řízení Change Wheel Behavior Změnit chování kolečka myši Code View Autosave Automatické ukládání Autosave every: Automaticky uložit každých: minutes minut Language Jazyk Colors Barvy %1 (click to change...) %1 (kliknout pro změnu...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Vyberte programátor (spustitelný) pro %1 Connected Highlight Zvýraznění propojených Unconnected Highlight Zvýraznění nepropojených no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom žádné klávesa stlačená = posunout klávesa SHIFT přepne posun osy Klávesa Alt nebo klávesa %1 = zvětšení no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis žádné klávesa stlačená = zvětšení klávesa SHIFT přepne posun osy Klávesa Alt nebo klávesa %1 = posunout Curvy vs. straight wires Křivky vs. rovné propojky When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Nový Open Save Uložit Platform Board Deska Port Serial Monitor Upload Select a program file to load Vyberte soubor programu k načtení Fritzing is unable to find '%1', please locate it Fritzing nebyl schopen nalézt '%1', najděte jej Code (*.%1) Remove "%1"? Odstranit "%1"? Are you sure you want to remove "%1" from the sketch? Opravdu chcete odstranit "%1" z návrhu? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit &Upravit Undo Zpět Redo Vpřed &Cut V&yjmout Cut selection Vyjme výběr &Copy &Kopírovat Copy selection Kopíruje výběr &Paste &Vložit Paste clipboard contents Vloží obsah schránky &Select All &Vybrat vše Select all text Vybere celý text &Preferences... &Předvolby... Show the application's about box Zobrazí okno O programu &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Deska Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 %1%2 &View &Zobrazení File '%1' was restored from the .fzz file; the local copy was not found. Soubor '%1' byl obnoven ze souboru .fzz; místní kopie nebyla nalezena. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Soubor '%1' byl obnoven ze souboru .fzz; Uložte místní kopii pro práci s externím editorem. QObject Preferences Předvolby Please note that a new language setting will not take effect until the next time you run Fritzing. Mějte na paměti, že nové nastavení jazyka se projeví až při dalším spuštění Fritzingu. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found Nelze spustit Autorouting: žádná deska (nebo více desek) nenalezena No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Soubor '%1' je jen pro čtení; Použijte prosím jiný název souboru. Edit link Upravit odkaz Part Součástka Wire Propojka Set Grid Size Cannot read file %1: %2. Nelze číst soubor %1: %2. Parse error (1) at line %1, column %2: %3 %4 Chyba parsování (1) na řádce %1, sloupec %2: %3 %4 The file %1 is not a Fritzing file (2). Soubor %1 není soubor Fritzing (2). The file %1 is not a Fritzing file (4). Soubor %1 není soubor Fritzing (4). The file %1 is not a Fritzing file (3). Soubor %1 není soubor Fritzing (3). Cannot write file temp: %1 %2 %3. Nelze zapsat dočasný soubor: %1 %2 %3. Parts folder not found. Složka součástek nenalezena. No parts found. Součástky nenalezeny. Parse error (2) at line %1, column %2: %3 %4 Chyba analýzy (2) na řádce %1, sloupec %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Součástka '%1' na '%2' nemá jedinečné id modulu '%3'. Basic Základní Input Vstup Output Výstup ICs ICs Power Napájení Connection Připojení Microcontroller Mikroprocesor Tools Nástroje Shields Shields LilyPad LilyPad Other Ostatní Sensors Senzory Part already in bin Součástka je již v zásobníku The part that you have just added, is already there, we won't add it again, right? Součástka kterou hodláte přidat je již v zásobníku. Chcete ji přidat znovu? a label popiska a value hodnota files soubory Oops! Ouha! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Promiňte, máme problém s přepínacím mechanismem. Fritzing stále funguje, ale nebudete moci změnit vlastnosti Součástek. bb bb Breadboard View Zobrazení montážní desky PCB View Zobrazení PCB pcb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem schem Schematic View Zobrazení schématu Error reading file %1: %2. Chyba čtení souboru %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Změna pinu %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer Vrstva %1 Bring forward Posunout vpřed Send backward Posunout vzad Bring to front Přesunout dopředu Split Wire Rozdělit propojku Join Wire Spojit propojku Trace wires Vytvoř spoj z propoje Ratsnest wires Vytvoř síť spojů Select all %1 Vybrat všechny %1 Select outdated parts Vybrat všechny neaktuální součástky Select locked parts Vybrat všechny uzamčené součástky unable to open %1 Nelze otevřít %1 unable to parse %1 Nelze parsovat %1 parse failure in %1 parse selhala v %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Je nám líto, ale Fritzing prozatím nezvládne piny a plošky současně spolu. (in %1) bad pin argument count špatný počet argumentů pinu bad pad argument count špatný počet argumentů plošky Unable to parse copper: %1 %2 %3 Nelze analyzovat měď: %1 %2 %3 footprint %1 not found in %2 patice %1 v %2 nenalezena unexpected end of file in footprint %1 in file %2 neočekávaný konec souboru v patici %1 v souboru %2 unexpected format (1) in %1 from %2 neočekávaný formát (1) v %1 z %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Je nám líto, Fritzing zatím nezvládne piny a plošky současně spolu (v %1 v %2) unexpected end of file neočekávaný konec souboru pad missing drill plošce chybí vrtání pad missing attributes plošce chybí atributy pad missing position plošce chybí pozice pad missing shape plošce chybí tvar position missing params poloze chybí parametry drill missing params vrtání chybí parametry drill offset not implemented offset vrtání není implementován drill missing ellipse params vrtání chybí parametry elipsy attributes missing params atributům chybí parametry bad layer mask parameter špatný parametr masky vrstvy Sorry, can't handle pad type %1 Je nám líto, typ plošky %1 není podporován pad shape missing params tvaru plošky chybí parametry pad shape size is invalid velikost tvaru plošky je neplatná trapezoidal pads not implemented lichoběžníkové plošky nejsou implementovány shape delta not implemented tvar delty není implementován non-circular holes not implemented nekruhové otvory nejsou implementovány non-copper holes not implemented díry bez mědi nejsou implementovány unable to handle pad shape %1 tvar plošky %1 není podporován failure in svg conversion 1: %1 %2 %3 selhání v SVG konverzi 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 selhání v SVG konverzi 2: %1 %2 %3 File Progress... Zpracovávání souboru... Copying file %1 Kopírování souboru %1 File %1 already exists: it won't be overwritten Soubor %1 již existuje: nebude přepsán Check for updates Kontrola aktualizace icon view zobrazit jako ikony breadboard view zobrazení montážní desky schematic view sobrazení shématu pcb view zobrazení pcb Icon Ikona Breadboard Montážní deska Parts Součástky Wires Propojky Part Labels Popisky součástek Ratsnest Síť propojů Notes Poznámky Rulers Pravítko Frame Rámec Text Board Deska Silkscreen Top Horní silkscreen Silkscreen Top (Part Labels) Horní silkscreen (Popisky součástek) Copper Fill Bottom Spodní měděná výplň Copper Fill Top Horníí měděná výplň Copper Bottom Spodní měď Copper Bottom Trace Spodní měděné spoje Copper Top Horní měď Copper Top Trace Horní měděné spoje Silkscreen Bottom Spodní silkscreen Silkscreen Bottom (Part Labels) Spodní silkscreen (Popisky součástek) Part Image Obrázek součástky Unknown Layer Neznámá vrstva Select %1 Vybrat %1 bad schematic definition %1 špatná definice schématu %1 schematic part %1 not found in %2 součástka schématu %1 nebyla v %2 nalezena schematic %1 unexpectedly ends (1) in %2 schéma %1 v %2 nečekaně končí (1) schematic %1 unexpectedly ends (2) in %2 schéma %1 v %2 nečekaně končí (2) schematic %1 unexpectedly ends (3) in %2 schéma %1 v %2 nečekaně končí (3) outline is empty obrys je prázdný the board outline layer, vrstva obrysu desky, silkscreen layer(s), vrstva(y) potisku, copper layer(s), vrstva(y) mědi, mask layer(s), vrstva(y) masky, paste mask layer(s), Unable to translate svg curves in %1 Nelze převést SVG křivky v %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure export potisku selhal %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure export vrtání selhal %1 mask export failure (2) %1 maska exportu selhala (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure export masky selhal Pin Label Editor Editor popisku pinu mm mm in palce Set Ground Fill Seed Nastaví plochu zemní výplně Ground Fill Seed Editor Editor plochy zemní výplně unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Soubor Last backup Poslední záloha Last saved Naposledy uloženo file not saved soubor neuložen <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Fritzing možná havaroval, ale některé ze změn v následujících souborech mohou být obnoveny.</b></p><p>Datum a čas každého souboru který byl zálohován, je zobrazen. Pokud byl soubor uložen, jeho datum a čas je také pro srovnání uveden.</p><p>Původní soubory jsou stále na Vašem disku, pokud byly vůbec uloženy. Můžete vybrat, zda chcete přepsat původní soubor po načtení jeho obnoveného souboru.</p><p><b>Vyberte soubory, které chcete obnovit z níže uvedeného seznamu.</b></p> &Recover &Obnovit &Ignore &Ignorovat Resistor Resistor Odpor resistance odpor You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape tvar width: %1mm šířka: %1mm height: %1mm výška: %1mm width(mm) šířka(mm) height(mm) výška(mm) keep aspect ratio Revert size velikost custom vlastní A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width šířka S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Projekt Filename Soubor Date Datum Sheet List Rev shape tvar of z date datum sheet list SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 Změna napětí z %1 na %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Nastavit jako výchozí barvu %1 Cancel Zrušit OK OK Pick custom %1 color Current color (%1) SketchWidget loading part načítání součástky done loading načítání sokončeno %1 %2 %1 %2 %1 %2 items %1 %2 položky Select All Vybrat vše Deselect Zruší výběr Add %1 Přidat %1 Selection Výběr Move %2 (%1) Přesun %2 (%1) Move %2 items (%1) Přesun %2 položky (%1) Select %1 Vybrat %1 Select %1 items Vybrat %1 položek Disconnect Odpojit Change Změnit Connect Připojit to %1 do %1 Create and connect wire Vytvořit a připojit propojku Rotate %2 (%1) Otočit %2 (%1) Note text change Rotate Otočit Flip Překlopit Double-click Dvojklik Delete ratsnest Vymazat síť propojů from %1 z %1 Move leg of Přesunout pin Change leg curvature for %1. Změnit křivku pinu pro %1. Change leg bendpoint for %1. Změnit zlomový bod pinu pro %1. Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. To se jeví jako pokus o vytvoření spoje napříč vrstvami. Tato skutečnost by neměla vzniknout: kontaktujte vývojáře. Create and connect %1 Vytvořte propojku %1 wire propojka trace spoj Flip %2 (%1) Překlopit %2 (%1) Drag or double-click Přetáhnout nebo dvojklik or alt-drag to move the segment nebo Alt-přetažení pro přetažení segmentu Double-click to delete this bend point Dvojklik pro odstranění tohoto zlomového bodu Change %1 label to '%2' Změnit %1 popisku na '%2' Change %1 color from %2 to %3 Změnit barvu %1 z %2 na %3 Change color of %1 wires to %2 Změnit barvu propojky %1 na %2 Change %1 width from %2 to %3 Změnit šířku %1 z %2 na %3 Change width of %1 wires to %2 Změnit šířku propojky %1 na %2 Move label '%1' Posunout popisku '%1' %1 label '%2' popiska %1 '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 Změnit velikost pravítka %1 %2 test connectors Resize Note Změnit velikost popisku Change Resistance from %1 to %2 Změna odporu z %1 na %2 Change %1 from %2 to %3 Změna %1 z %2 na %3 Resize board to %1 %2 Změnit velikost desky na %1 %2 Create wire from Ratsnest Vytvořit propojku ze sítě propojů Disconnect all wires from %1 Odpojit všechny propojky od %1 Disconnect all wires from %1 items Odpojit všechny propojky od %1 položek Change image from %1 to %2 Změnit obrázek z %1 na %2 change pin labels změnit popisky pinů Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Obnoveno Cut Vyjmout %1 %n strip(s) %1 %n páska %1 %n pásky %1 %n pásek rows řádků columns sloupců %1 layout SymbolPaletteItem voltage napětí label popisek Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Tipy a Triky Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width šířka TranslatorListModel English - %1 Angličtina - %1 French - %1 Francouzština - %1 German - %1 Němčina - %1 Spanish - %1 Španělština - %1 Japanese - %1 Japonština - %1 Portuguese (European)- %1 Portugalština (Evropská)- %1 Portuguese (Brazilian) - %1 Portugalština (Brazilská) - %1 Hungarian - %1 Maďarština - %1 Estonian - %1 Estonština - %1 Dutch - %1 Holandština - %1 Danish - %1 Russian - %1 Ruština - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Italština - %1 Hebrew - %1 Hebrejština - %1 Arabic - %1 Arabština - %1 Hindi - %1 Hindština - %1 Chinese (Simplified) - %1 Čínština (zjednodušená) - %1 Chinese (Traditional) - %1 Čínština (tradiční) - %1 Polish - %1 Polština - %1 Czech - %1 Čeština - %1 Turkish - %1 Turečtina - %1 Swedish - %1 Švédština - %1 Romanian - %1 Rumunština - %1 Thai - %1 Thajština - %1 Greek - %1 Řečtina - %1 Bulgarian - %1 Bulharština - %1 Galician - %1 Galicijština - %1 Korean - %1 Korejština - %1 Indonesian - %1 Indonéština - %1 Slovak - %1 Bengali - %1 UpdateDialog Close Zavřít No new versions found. Žádná nová verze nenalezena. A new main release is available for downloading: Nové hlavní vydání je k dispozici pro stažení: A new interim release is available for downloading: Nové prozatímní vydání je k dispozici ke stažení: Checking... Kontrola... Sorry, unable to retrieve update info Lituji, nelze načíst informace o aktualizaci WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) tenká (16 mil) standard (24 mil) standard (24 mil) thick (32 mil) silná (32 mil) extra thick (48 mil) extra silná (48 mil) blue modrá red červená black černá yellow žlutá green zelená grey šedá white bílá orange oranžová ochre cyan brown hnědá purple fialová pink color barva Banded ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_da.qm000066400000000000000000000000201250202676700216550ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Cancel OK Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save... Save Don't Save Cancel Ctrl+D Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Properties Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Breadboard Schematic PCB Click to highlight unconnected parts Rotate Share Flip Autoroute Fabricate Both Layers Bottom Layer Top Layer View from Above View from Below Add a note Export for PCB Ready Save %1 Fritzing Unable to open '%1': %2 No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Fritzing (*%1) Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector Undo History Layers Couldn't get the dock widget PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Choose a folder for exporting Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Unable to export %1 as shareable &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Etchable (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export SPICE Netlist... Export Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Cannot find file %1. Cannot read file 1 %1: %2. Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? File '%1' not found the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection Delete Minus Delete selection without attached wires &Delete Wire Delete Wire up to bendpoints &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box Edit (new parts editor) Open the new parts editor on an existing part &Add to bin... Add selected part to bin Disconnect All Wires Ctrl+Shift+V Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show part label Show/hide the label for the selected parts &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+1 Ctrl+2 Ctrl+3 Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard Show the breadboard view &Show Schematic Show the schematic view &Show PCB Show the PCB view Show Code Show the code (programming) view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks First Time Help Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser &File &Export as Image for Production &Edit &Part Raise and Lower Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align &View &Window &Routing Ground Fill &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Traces Select all trace wires Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select all trace wires excluded from autorouting Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Shift+Ctrl+D Check Loaded Traces Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting Progress... jumpers copperfill vias Remove Bendpoint Please choose the previous Fritzing folder... The folder "%1" isn't a Fritzing installation folder You will have to restart Fritzing in order to use the imported parts Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill &Wire Color Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Launch %1... No outdated parts found. All your parts are up-to-date. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Outdated parts There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. Do you want to update now? unable to find replacement for %1. Update %1 part(s) Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org Optimizing traces... ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Change trace layer Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon Metadata Connectors SVG Inspector Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Show in Folder On the desktop, open the folder containing the current svg file. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection &File Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit Parts Editor This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to write svg to %1 Unable to parse fzp file %1 Fritzing (New) Parts Editor Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Show Metadata Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Change description Change %1 to '%2' Change tags Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Change properties Change connector %1 SVG problem This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Conversion problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Unable to load image file '%1': %2 Unable to load image file '%1' Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. Copy problem Unable to make a local copy of: '%1' no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center W N S E center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Save Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel OK Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Code No boards available &Preferences... Show the application's about box &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Code Window Code Window - %1 %1%2 QObject Autorouter Settings Part %1 '%2' Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position Set Ground Fill Seed Ground Fill Seed Editor Pin Label Editor Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings %1 wires moved from their saved position in %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Edit link mm in The file '%1' is read-only; please use a different filename. Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Fritzing cannot load the parts bin Basic Input Output ICs Power Connection Microcontroller Breadboard View Schematic View PCB View Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 Set all to: Pad ii Icon View Internal Connections <b>Name:</b> Set the connectors's title <b>Description:</b> Set the connectors's description <b>id:</b> <b>type:</b> files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Select all %1 Convert to Via Convert Via to Bendpoint schem Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. %1 layer export is empty (case 2). silk layer %1 export is empty silk export failure exported drill file is empty drill export failure exported mask layer %1 is empty %1 mask export failure (2) mask export failure exported paste mask layer is empty %1 layer: unable to save to '%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to save pick and place file: %2 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer icon view breadboard view schematic view pcb view N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Fritzing Fab Quote Order your PCB from Fritzing Fab Copies Price per board Price Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading Delete ratsnest %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect from %1 Move leg of Connect to %1 Change leg curvature for %1. Change leg bendpoint for %1. Change Create and connect wire Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Rotate %2 (%1) Flip %2 (%1) Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Rotate Flip show %n part label(s) hide %n part label(s) Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize ruler to %1 %2 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. parts editor Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Italian - %1 Polish - %1 Turkish - %1 Swedish - %1 Galician - %1 Indonesian - %1 Danish - %1 Japanese - %1 Russian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Czech - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Korean - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_de.qm000066400000000000000000006433601250202676700217050ustar00rootroot00000000000000ȫrcrMr_\b;ib;ABHP#IZRWGQ->P$1 V#JNd\53 G0p"bw&a^)t~){)%*9*/SK24l6P9.?yJvg]L#k7L4w2O.TZX]0e>0eLqr4{(y ԸEtN~~[j95E(`Y,R)^~$CU %p>PnslrN2LMCQ'$[_]EvN.xlR\l|˓VM͌\Ӓ2Ӓ2Բuq\orجN ./Ew݋AK_v>0"U*7PsO0c'N[֨F3@ 1m: |d`&W.Sh0nd44-4#R:'^>@^?..BɢC>DJĮQQ˯(RԢwTIYXYYYZ2\ϰjfjlTRޒl4n \?pt.tl$DtutuT.u5uTUxexe"xicAy9z@O|DZ 'L\RÖpra .qsSFTE!]4yşL^fW~S._;A;AgXu4u$±4±#VĵS@^:Ea2a"cInn[bz\Pu!4C`^bQ`0nfQY[pq & 5%yT7TUR[kb6Jg3g.m,4 ;>Hu;FJCFF.H0PKNaD RBa}V|>7XM1YEhWwmW)nkqp>krxsuz$|}Ka 1$oMBڡ\r@_P6[q zqWG%^Lڮw|~ '{b^!ܡǒ7e!տ-ֺ$Hofd_|"n"Q:c%elS5(&H c7Bu~}ʳFpI=n9Dh Z"B'e (Ï *Z{-5;NH=fEG$Ke.BhPѧQ`/TDlXZeZe{]+_sacOlhc.b3jNblrRt2zbЁ{eD|/}n|ouR} uc"nPD8́!JpׅxI]07bf[f'ɱnjGI>II~\II.IIII+`I3I9NI<IJzoZed2;o<6>ov)LR "$UՆշ2JeŘ{֬b-W[?b8pסbl4W= ج !,ڶwbYN#Y[ mDZ~n~V@9XSF]fa&րWkٶtۘlDGB4:f+F;X^;3qp+}Dv{^  ~,s1^'vUgV( (Ѵ,]=58[; d]cX 1"B1$k"$k2$kBw%]))7 +T\-ڎQ.#s $3L7ʒ^ 9;7 J> E@EaK_E|nOtQ0wyQM0RN¤U\aX$3^z:^_p_zm`s`rIi\  lApIɠqW7r |Jrdttx9fz:|Q@tuzACJ YXZUXN /G]]#BUuA7 >r ZZZ3%s$v)C*]]]D3D#L2jL"Wo@9a֣֣j\Zh(mޛ޷necD-+9BlDMwy|g#['p A  398s!>"S0&|8'S(=-3e. Js.h/51,);!;i[o1/V+V  Ȗ 0mtL\Ռe4;4gZaa.G;*IA-?~^P˸`>O`ߺ[XW> {^;͜pry5Af0Fz3gDW ]p(~H Lx2Tm%`n&r)w,ι-B8=23aAwSGB _CE43FF?H4HtMHTI'ƁN?O;7P1oS W;HYQY´?n^Ӽb]A9fCK9fC!f|fgThТi'hTiJIsqOWvycwJcx?Qyz.+|Ԃʄ|^|^W}֥ZqA2"QM.~4m1&*, .XNxR>kS,S{%[Z:I$ nr*yGa"3&.Mn4 qTʗ/1К0л% Sf"E<:jrY';eۇT5 Oʙ \~7 + E6 |U . w )  (  !yT $)~3 .5~ 01k 0!SҴ 5G 6TI 90zY ;=" BUo8 Ex$ Gȧ LZ[X MgA P_J Qq5 S; Se \u ` aB4 cϥO d`= lO la^ m#X t7k ui u |@p ~ . ~SB NB z JX J@, r: ^ 8 ;.K an D [ + B1 N! . :f '= ~ y syg Ŧ H 8 ,E 3 ; ՛Y {u7W  wS i ~ D v e i   V) ԁ + RF ^@% J"  T `P 7 i78@ 2+  !q2 !q! #$ )r) 5sT 5sU8 5sU 5sU 5sV 5sV\ 5tbV 5tcV 5tkW 5tmW ?"Eۓ CD! DLV[ D)z IRZ M  N= o PK U̒ [>L ^5" a5[ a4ؽ c36 c3 d2 d8>D eK9 eR1 e> e& fj7 g7 k2 k2Ќ qw s'>>l su{ tq u= v w NT1 Ȑw yݖ 4] Q)  \ ~x* k5 #Q , ^+  9 . +|>  "nj) Ća" NJ Ɍ4 vT v ώ.f Ϯ  Ҍ9 0} 0 ˺x K (E ;'@ c! }i { UP S C T ?D  VI ~ j ~0  gc g `X !_g\ #e7 %4@ (c ) )l ) *G * -#4 -mn/ 8) ? 8\ HK Jg K2gn[ K2g N>0 Vq YE^  ߗ  yv tj wJ C LЮ I ez L .× `= T R #^ %^ %^Y ,\~ -2 /~ 9s ;z ;>{ =I @M AiT F^C L.3 M&`l O~! Q Wj XM"S `lt af6 eul eZ\g hȾp o r rQ t yU> z n,4 z ni {7{ " ]D^ @| N)  $ )  @ t ^M G , ,+   /݃ /  ' '+ & P F~ C F 1D m4 E<5 .[ 90 s[ T7 Yf ɠ. ?.  '~  o K  ~8 } .5 `@ m :G o Up ˞B Je (< %  j> f 1 = np #ѮS )%.Ŧ 3F2 3f2O 7n < [ >O ?څ AC A>q DA DD' DZe G0 LR_ R/ Tp. X4) Zg|( [ c _k c cY eO_ f fk1s iF kc m[a qUNk u; vM v vCN } #D } 1 15' R  b  p ~ z< k N ~i &= @ RF ¦e <? ՞ cY N    ew _/ ^    Z$=ok7T  o+s!1PL33{܆ rc(,NSI,#_/KVX a.=a./e~LfTKfTt$v8% w=)y~C~Pi,o#>.t-n6nC)Q>h$*=)U /RSSRxޘ\x,ãCc>0iu8ŅŅm~A@qtAIB!4htݶVg6pZ3a ߯uCbACnen2]n2t^! $Y>+>NK E^C~OVA[ h}i͈yR{ ~!ugt"TN$$ o/`i1o1=3 8=V=_@X@CO(9NTLWc<]t^Dav!d}Bfg0f" hƘi/i0pHsVHMvgU6w|>yfzRz |`h}$7~@+ BR; ymհFrd^'VgP2>Sz9aj<jc~jc~8bbU"DRSX5Tһ}qx'ϳ@\WXE2 i/<b>GNU GPL v3 auf den Quellcode und CreativeCommons:BY-SA auf den Rest?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBox0







    AboutBoxhBryant Mairs, Uleshka Asher, und Daniel Tzschentke. 4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxTAbteilung der Bauhaus-Universitt Weimar, )Department of Bauhaus-University Weimar, AboutBox3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBox2Fritzing auszuprobieren. Fritzing a test spin. AboutBoxNFritzing ist die gemeinsame Arbeit von:Fritzing is made by: AboutBoxbFritzing wird ermglicht durch die Frderung von 0Fritzing is made possible with funding from the AboutBox*Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxjIxDS, Parallax, Picaxe, Sparkfun, zahlreiche Spender,6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBox%Jan Sieber, Yaniv Steiner, Olaf Val, AboutBox-Jonathan Cohen, Marcus Paeschke, Omer Yosha, AboutBox6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxjMWFK Brandenburg, die Untersttzung durch die Design 0MWFK Brandenburg, the sponsorship of the Design AboutBox%Mariano Crowe, Johannes Landstorfer, AboutBoxBMichaela Vieser und Julia Werner.!Michaela Vieser and Julia Werner.AboutBox@Prof. Reto Wettach, André Knörig, Myriel Milicevic, AboutBox`Besonderer Dank geht auerdem an alle Studenten 4Special thanks goes out as well to all the students AboutBox2Besonderer Dank geht an: Special thanks goes out to: AboutBoxVielen Dank an Kurt Badelt und Miguel Solis fr die Spanische bersetzung, DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBox,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBox2Travis Robertson, Stefan Hermann, Brendan Howell, AboutBox$Zach Eveland, Dirk van Oosterbosch, AboutBoxXund Alpha-Testern, die mutig genug waren, um0and alpha testers who were brave enough to give AboutBoxund von jedem Kauf eines Fritzing Starter Kit oder einer Leiterplatte von Fritzing Fab.Land from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab.AboutBoxund an Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, und Gabriel Ferreira fr die Portugiesische (Brasilianisch) bersetzung. |and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. AboutBoxan &#313;ubom&iacute;r Ducho&#328; fr die Slowakische bersetzung, ?to Ĺubomír Duchoň for the Slovak translation, AboutBoxlan Alexander Kaltsas fr die Griechische bersetzung, 0to Alexander Kaltsas for the Greek translation, AboutBoxxan Cihan Mete Bahad&#x0131;r fr die Trkische bersetzung, :to Cihan Mete Bahadır for the Turkish translation, AboutBoxjan Gianluca Urgese fr die Italienische bersetzung, 0to Gianluca Urgese for the Italian translation, AboutBoxdan Hiroshi Suzuki fr die Japanische bersetzung, 0to Hiroshi Suzuki for the Japanese translation, AboutBox`an Jinbuhm Kim fr die Koreanische bersetzung, +to Jinbuhm Kim for the Korean translation, AboutBoxfan Josef Dustira fr die Tschechische bersetzung, ,to Josef Dustira for the Czech translation, AboutBoxan Lionel Michel, Yvan Kloster, Alexandre Dussart, und Roald Baudoux fr die Franzsische bersetzung,ato Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, AboutBoxfan Nikolay Stankov fr die Bulgarische bersetzung,2to Nikolay Stankov for the Bulgarian translation, AboutBoxan Nuno Pessanha Santos fr die Portugiesische (Europisch) bersetzung, Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBox|an Robert Lee fr die Chinesische (traditionell) bersetzung, 9to Robert Lee for the Chinese (Traditional) translation, AboutBoxan Steven Noppe und Davy Uittenbogerd fr die Niederlndische bersetzung, Ato Steven Noppe and Davy Uittenbogerd for the Dutch translation, AboutBoxfan Wladimir Savinov fr die Russische bersetzung, 1to Vladimir Savinov for the Russian translation, AboutBoxan Yuelin und Ninjia fr die Chinesische (vereinfacht) bersetzung, @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBoxBestes Ergebnis Best So FarAutorouteProgressDialogAbbrechenCancelAutorouteProgressDialogAnhaltenStop NowAutorouteProgressDialog,Zoomen und verschiebenzoom and pan controlsAutorouteProgressDialogDRouting abgebrochen! Rume auf... $Routing canceled! Now cleaning up... AutorouterDer minimale <b>Abstand</b> zwischen Kupferelementen verschiedener Netze.QKeepout is the minimum distance between copper elements on different nets.AutorouterSettingsDialogEin Abstand von 0,01 Zoll (0,254 mm) ist ein guter Standardwert.4A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialogAbbrechenCancelAutorouterSettingsDialogAbstandKeepoutAutorouterSettingsDialogBeachte: Je kleiner der Abstand, desto mehr Zeit bentigen Autorouter und DRC.JNote: the smaller the keepout, the slower the DRC and Autorouter will run.AutorouterSettingsDialogProduktionsartProduction typeAutorouterSettingsDialog Leiterbahnbreite Trace widthAutorouterSettingsDialog"benutzerdefiniertcustomAutorouterSettingsDialogManuellhomebrewAutorouterSettingsDialogProfessionell professionalAutorouterSettingsDialogSortimentBin BinManagerBinManager::setDirtyTab: Konnte das Sortiment '%1' nicht als verndert setzen;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerBinManager::updateTitle: Konnte das Sortiment '%1' nicht als verndert setzen;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerpEin NULL Sortiment kann nicht als aktuell gesetzt werden(Cannot set a NULL bin as the current one BinManager&Sortiment schlieen Close Bin BinManager4Bauteilsortiment schlieenClose parts bin BinManagerZAlle geladenen Bauteile im Entwurf platzieren#Copy all loaded parts to the sketch BinManagerbPlatziere alle Bauteile des Sortiments im Entwurf)Copy all the parts in the bin to a sketch BinManager6Alles im Entwurf platzierenCopy all to Sketch BinManager&In Entwurf kopierenCopy to Sketch BinManagerHEin neues Bauteilsortiment erstellenCreate a new parts bin BinManager"Sortiment lschen Delete Bin BinManager"Sortiment lschen Delete bin BinManager0Bauteilsortiment lschenDelete parts bin BinManager:Bauteile als Liste darstellenDisplay parts as a list BinManager>Bauteile als Symbole darstellenDisplay parts as icons BinManagerWillst Du das Sortiment '%1' wirklich lschen? Diese Aktion kann nicht rckgngig gemacht werden.EDo you really want to delete bin '%1'? This action cannot be undone. BinManagerWillst Du '%1' wirklich aus dem Sortiment entfernen? Dies kann nicht rckgngig gemacht werden.PDo you really want to remove '%1' from the bin? This operation cannot be undone. BinManagerZBauteil bearbeiten (neuer Bauteile-Editor)...Edit Part (new parts editor)... BinManager0Sortiment exportieren... Export Bin... BinManager,Bauteil exportieren...Export Part... BinManager0Finde Bauteil im EntwurfFind Part in Sketch BinManagerFritzing-Sortimente (*%1 *%2);;Fritzing-Sortiment (*%1);;Fritzing-Sortiment-Paket (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagerFritzing-Dateien (*%1 *%2 *%3);;Fritzing-Bauteile (*%1);;Fritzing-Sortimente (*%2 *%3)cFritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) BinManagerImportieren... Import... BinManagerffne ein Fritzing-Bauteil (.fzpz) oder -Bauteilsortiment (.fzb, .fzbz)CLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManager$Neues Sortiment... New Bin... BinManager(Neues Sortiment (%1) New bin (%1) BinManagerBauteileParts BinManagerTBitte whle einen Namen fr das Sortiment:!Please choose a name for the bin: BinManager8Schreibgeschtztes Sortiment Read-only bin BinManager"Bauteil entfernen Remove Part BinManager.Aus Sortiment entfernenRemove from Bin BinManager.Von Sortiment entfernenRemove from bin BinManager.Sortiment umbenennen... Rename Bin... BinManager(Sortiment umbenennen Rename bin BinManager<Bauteilsortiment umbenennen...Rename parts bin... BinManager&Sortiment speichernSave Bin BinManager8Sortiment speichern unter...Save Bin As... BinManager4Bauteilsortiment speichernSave parts bin BinManagerFBauteilsortiment speichern unter...Save parts bin as... BinManagervBauteilsortiment in einem komprimierten Format speichern...&Save parts bin in compressed format... BinManagerSuche... Searching... BinManager.Fritzing-Entwurf ffnenSelect a Fritzing File to Open BinManagerrWhle eine Fritzing-Bauteilsortiment-Datei zum ffnen aus(Select a Fritzing Parts Bin file to open BinManagerFSortiment in Symbolansicht anzeigenShow Bin in Icon View BinManagerFSortiment in Listenansicht anzeigenShow Bin in List View BinManagerZDieses Sortiment kann nicht umbenannt werden.This bin cannot be renamed. BinManagerDas Bauteil '%1' konnte nicht entfernt werden - es wird in einem Entwurf verwendet4Unable to remove part '%1'--it is in use in a sketch BinManager Ein eigenes Platinen-SVG hat blicherweise eine oder zwei Siebdruckebenen ("silkscreen") und eine Platinenebene ("board").U A custom board svg typically has one or two silkscreen layers and one board layer. Board^<b>Die Platinenform enthlt %n Ausschnitte.</b>'The custom shape has %n cutouts.Board<b>Deine eigene Platinenform wurde geladen und wird in Krze sichtbar</b><br/><br/>ZThe custom shape has been loaded, and you will see the new board shortly.

    Boardh<b>Diese Platinenform enthlt keine Ausschnitte.</b>'The custom shape has no cutouts.Board<br/><br/>Falls die von Dir eingesetzten Ausschnitte nicht wie erwartet angezeigt werden,e

    If you intended your custom shape to have cutouts and you did not get the expected result, Board<br/>Einige dieser Ausschnitte knnten nicht korrekt formatiert sein.9
    However, the cutouts may not be formatted correctly.Board,Vor der Platinenherstellung empfehlen wir, die eigene Platinenform im Gerberformat zu berprfen (Datei > Exportieren > Produktion > Extended Gerber).Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. BoardJDie Datei konnte geladen werden, aber Can load, butBoardberprfe die Konturdatei mit einem Gerber-Anzeigeprogramm<br/><br/>xCheck the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.

    BoardSchau Dir die Beispieldatei circle_pcb.svg in Deinem Fritzing-Installationsordner unter Fritzing/parts/svg/core/pcb/ an. eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Board BilderImagesBoard:Bilddatei zum Laden auswhlenSelect an image file to loadBoardDie Forma aus %1 konnte geladen werden, aber %2. Trotzdem diese Datei benutzen?5The image from %1 can be loaded, but %2 Use the file?BoardvDer folgende Hinweis betrifft "Ausschnitte" in der Platine.-The rest of this message concerns 'cutouts'. BoardAusschnitte sind kreisfrmige oder anders geformte Lcher, die Du optional in Deiner eigenen Platinenform nutzen kannst.<br/><br/> uThese are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.

    BoardJDie Datei konnte nicht geladen werdenUnable to loadBoardfAus der Datei %1 %2 konnte kein Bild geladen werdenUnable to load image from %1 %2BoardNda das XML nicht korrekt formatiert ist*because the xml is not correctly formattedBoardPda mehrere <board>-Ebenen enthalten sind)because there are multiple layersBoard\da mehrere <silkscreen0>-Ebenen enthalten sind/because there are multiple layersBoardZda mehrere <silkscreen>-Ebenen enthalten sind.because there are multiple layersBoardZda keine <board>-Ebene gefunden werden konnte!because there is no layerBoardaber diese Leiterplatte wird keine Siebdruck-Ebene ('silkscreen') enthalten0but the pcb itself will have no silkscreen layerBoarddaufgrund eines XML-Problems: %1 Zeile:%2 Spalte:%3+due to an xml problem: %1 line:%2 column:%3BoardBilddatei image fileBoard>liegt das vermutlich daran, dass Fritzing diese nur korrekt erkennen kann, wenn sie als "Subtraktion" der Grundform in Deinem Zeichenprogramm erstellt wurden. it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.BoardBilddatei ladenload image fileBoard,eine Ebene (einseitig)one layer (single-sided)BoardZdie <board>-Ebene enthlt keine Form-Elemente.the element contains no shape elementsBoardLdieses SVG keine Form-Elemente enthlt"the svg contains no shape elementsBoarddieses SVG enstpricht nicht dem Format fr benutzderefinierte Leiterplatten+the svg doesn't fit the custom board formatBoard0zwei Ebenen (zweiseitig)two layers (double-sided)BoardFormshape BoardLogoItem&Textfarbe auswhlenSelect text colorBreadboardLogoItem&Textfarbe festlegenSet text colorBreadboardLogoItem FarbecolorBreadboardLogoItemVAus der Liste whlen oder %1-Wert eintippen/Select from the dropdown, or type in a %1 value Capacitor*Biegepunkt hinzufgen Add bendpoint ConnectorItem(Biegepunkt entfernenRemove bendpoint ConnectorItem$Biegung begradigenStraighten curve ConnectorItem Weitere OptionenAdditional optionsConsoleSettingsAnwendenApplyConsoleSettingsBaudrate: BaudRate:ConsoleSettingsDatenbits: Data bits:ConsoleSettingsBeschreibung: Description:ConsoleSettings Beschreibung: %1Description: %1ConsoleSettingsFlusskontrolle: Flow control:ConsoleSettingsLokales Echo Local echoConsoleSettings Pfad: Location:ConsoleSettingsPfad: %1 Location: %1ConsoleSettingsHersteller: Manufacturer:ConsoleSettingsHersteller: %1Manufacturer: %1ConsoleSettingsParitt:Parity:ConsoleSettingsProduktkennung: Product ID:ConsoleSettings*Produktbezeichner: %1Product Identifier: %1ConsoleSettings&Parameter auswhlenSelect ParametersConsoleSettings0Seriellen Port auswhlenSelect Serial PortConsoleSettingsSeriennummer:Serial number:ConsoleSettings Seriennummer: %1Serial number: %1ConsoleSettingsEinstellungenSettingsConsoleSettingsStoppbits: Stop bits:ConsoleSettings Anbieterkennung: Vendor ID:ConsoleSettings,Anbieterbezeichner: %1Vendor Identifier: %1ConsoleSettings &ber&About ConsoleWindow&Optionen &Configure ConsoleWindow&Trennen &Disconnect ConsoleWindow&Beenden&Quit ConsoleWindowber QtAbout Qt ConsoleWindow4ber den Seriellen MonitorAbout Serial Monitor ConsoleWindow(ber dieses Programm About program ConsoleWindow Alt+Alt+A ConsoleWindow Alt+OAlt+C ConsoleWindow&LeerenC&lear ConsoleWindow&VerbindenC&onnect ConsoleWindowAusgabe leeren Clear data ConsoleWindowDKonfiguration des seriellen Ports Configure serial port ConsoleWindow@Mit dem seriellen Port verbindenConnect to serial port ConsoleWindowJVerbunden mit %1 : %2, %3, %4, %5, %6$Connected to %1 : %2, %3, %4, %5, %6 ConsoleWindow"Kritischer FehlerCritical Error ConsoleWindow Strg+DCtrl+D ConsoleWindow Strg+OCtrl+O ConsoleWindow Strg+BCtrl+Q ConsoleWindowJVerbindung zum seriellen Port trennenDisconnect from serial port ConsoleWindow&Verbindung getrennt Disconnected ConsoleWindow FehlerError ConsoleWindow"Serieller MonitorSerial Monitor ConsoleWindowLFehler beim ffnen des seriellen PortsSerial port open error ConsoleWindow8Dieses Terminal zeigt die serielle Kommunikation auf dem ausgewhlten Port an, die zwischen Deinem Computer und dem verbundenen Mikrocontroller stattfindet.This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. ConsoleWindowWerkzeugeTools ConsoleWindow.%1 berlappt (%2-Ebene)%1 is overlapping (%2 layer)DRCEin Loch in %1 knnte auerhalb der Platine liegen und wrde abgeschnitten werden.JA hole in %1 may lie outside the border of the board and would be clipped.DRCVerbinder %1 auf %2 sollte sowohl oben als auch unten eine Kupferebene haben, aber das SVG bestimmt nur eine Ebene.gConnector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer.DRCNEntwurfsregelprfung wurde abgebrochen.DRC was cancelled.DRCxFehler: Das Leiterplatten-SVG konnte nicht gerendert werden.+Fritzing error: unable to render board svg.DRC`Keine Leiterbahnen oder Verbinder zum berprfen No traces or connectors to checkDRCPositioniere sie neu und fhre dann die Entwurfsregelprfung erneut aus, um weitere Probleme ausfindig zu machen;Reposition them and run the DRC again to find more problemsDRCDie rot hervorgehobenen Bereiche sind problematisch, da sich hier Leiterbahnen berlappen oder zu nah beieinander liegen.qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRC@Zu nah an einer Kante (%1-Ebene) Too close to a border (%1 layer)DRCUnerwarteter SVG-Rendering-Fehler--bitte kontaktiere fritzing.org6Unexpected SVG rendering failure--contact fritzing.orgDRCDein Entwurf ist bereit fr die Produktion! Es konnten keine Verbinder oder Leiterbahnen gefunden werden, die zu nah sind oder sich berlappen.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRC`Whle ein Element, um das Problem hervorzuheben.BClick on an item in the list to highlight of overlap it refers to.DRCResultsDialogFErgebnisse der Entwurfsregelprfung DRC ResultsDRCResultsDialogBeachte: Die Listenelemente und die rote Hervorhebung werden nicht aktualisiert, wenn Du deinen Entwurf bearbeitest - Du musst den DRC erneut ausfhren. Die Hervorhebung wird verschwinden, wenn Du diesen Dialog schliet.Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialogfrs Debuggen for debugging DebugDialog,Auch die Datei lschenAlso delete the file DeleteDialogNicht entfernen Don't remove DeleteDialogEntfernenRemove DeleteDialog"Chip-Beschriftung chip labelDip Hinweis: Du kannst sie nachtrglich importieren, indem Du "Hilfe" > "Bauteile und Sortimente aus einer alten Version importieren..." aufrufst.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication.Jetzt nicht importierenDo not import now FApplicationMchtest Du die Bauteile und Sortimente importieren, die Du in einer frheren Fritzing-Version erstellt hast?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationTFritzing-Ausnahme %1 aus %2 im Ereignis %33Fritzing caught an exception %1 from %2 in event %3 FApplicationNFritzing-Ausnahme aus %1 in Ereignis %20Fritzing caught an exception from %1 in event %2 FApplicationVFritzing-Ausnahme aus %1 in Ereignis %2: %34Fritzing caught an exception from %1 in event %2: %3 FApplication$Fehler in FritzingFritzing failure FApplicationImportierenImport FApplicationRDateien aus frherer Version importieren?#Import files from previous version? FApplicationBitte gib einen Dateinamen (.fzz) zum Speichern des Backups an. (Abbrechen fhrt zum Lschen des Backups)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplication"ErstbenutzerhilfeFirst Time HelpFirstTimeHelpDialog&Schlieen &Close WindowFritzingWindowAbbrechenCancelFritzingWindow6Aktuellen Entwurf schlieenClose the current sketchFritzingWindow Strg+DCtrl+DFritzingWindow Strg+WCtrl+WFritzingWindowjMchtest Du die nderungen am Entwurf "%1" speichern?>Do you want to save the changes you made in the document "%1"?FritzingWindowNicht speichern Don't SaveFritzingWindowSpeichernSaveFritzingWindow"%1" speichern Save "%1"FritzingWindowSpeichern...Save...FritzingWindow(Dateinamen auswhlenSpecify a file nameFritzingWindowDeine nderungen gehen verloren, falls sie nicht gespeichert werden.1Your changes will be lost if you don't save them.FritzingWindowAbbrechenCancelGroundFillSeedDialog(OK und KupferfllungOK and copper fillGroundFillSeedDialog&OK und MassefllungOK and ground fillGroundFillSeedDialog.Der Unterschied zwischen einer "Massefllung" und einer einfachen "Kupferfllung" besteht darin, dass bei einer Massefllung die gefllte Flche Leiterbahnen und Verbinder beinhaltet, welche mit dem "Masse"-Verbinder verbunden sind. Masseverbinder sind in der Regel mit "GND" oder "ground" gekennzeichnet, aber manchmal ist dies nicht der Fall. Es kann auch sein, dass es mehrere Netze mit einem Masseverbinder gibt und Du nur eines der Netze gefllt haben willst. Dieser Dialog sammelt nur Verbinder mit der Bezeichnung "GND" oder "ground", sowie bereits als Saat ausgewhlte Verbinder. Klicke auf ein Element, um seine Verbindungen im Entwurf hervorzuheben. The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialogLochgre hole sizeHole(autoroutbar)(autoroutable) HtmlInfoView "Haftung" fr dieses Bauteil ndern. Wenn ein "haftendes" Bauteil bewegt wird, werden auch alle Bauteile die darauf liegen mitbewegt.pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoViewSperrung fr dieses Bauteil in dieser Ansicht ndern. Ein gesperrtes Bauteil kann nicht bewegt werden.OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoView:Bauteilbezeichnung hier ndenChange the part label here HtmlInfoViewVerbindungen Connections HtmlInfoViewGesperrtLocked HtmlInfoViewBSteckplatinenansicht des BauteilsPart breadboard view image HtmlInfoViewBLeiterplattenansicht des BauteilsPart pcb view image HtmlInfoView<Schaltplanansicht des BauteilsPart schematic view image HtmlInfoViewVersionsnummerPart version number HtmlInfoViewPlatzierung Placement HtmlInfoViewEigenschaften Properties HtmlInfoViewLuftlinie Ratsnest wire HtmlInfoViewHaftendSticky HtmlInfoViewSchlagwrterTags HtmlInfoViewLeiterbahn %1 Trace wire %1 HtmlInfoView DrahtWire HtmlInfoView Verb.conn. HtmlInfoView0Verbunden mit %n Element4Verbunden mit %n Elementenconnected to %n item(s) HtmlInfoViewGraddegrees HtmlInfoViewPositionlocation HtmlInfoViewNamename HtmlInfoViewveraltetobsolete HtmlInfoViewPlatinen-Ebene pcb layer HtmlInfoViewDrehungrotation HtmlInfoViewTyptype HtmlInfoViewBauteilPartItemBaseberingtbandedItemBase untenbottomItemBaseKapazitt capacitanceItemBase FarbecolorItemBaseKupfer unten copper bottomItemBaseKupfer oben copper topItemBase StromcurrentItemBase DatumdateItemBaseBeschreibungdescrItemBaseFamiliefamilyItemBaseXDatei fr %1 %2 konnte nicht gefunden werdenfile for %1 %2 not foundItemBaseDateinamefilenameItemBaseFormformItemBaseFrequenz frequencyItemBaseInduktivitt inductanceItemBase EbenenlayersItemBaseMax. Widerstandmaximum resistanceItemBase ModellmodelItemBase$Model Part Problemmodel part problemItemBase PaketpackageItemBaseBauteilnummer part numberItemBaseBeinchenabstand pin spacingItemBaseBeinchenpinsItemBaseLeistungpowerItemBaseProzessor processorItemBaseProjektprojectItemBaseMax. Strom rated currentItemBaseMax. Leistung rated powerItemBaseMax. Spannung rated voltageItemBaseWiderstand resistanceItemBaseRevisionrevItemBaseFormshapeItemBase BlattsheetItemBaseSiebdruck untensilkscreen bottomItemBaseSiebdruck obensilkscreen topItemBase GresizeItemBaseAbstandspacingItemBase TiteltitleItemBaseToleranz toleranceItemBaseobentopItemBaseTyptypeItemBasepDer Renderer fr das SVG %1 konnte nicht erstellt werden$unable to create renderer for svg %1ItemBaseVariantevariantItemBaseVersionversionItemBaseSpannungvoltageItemBaseAbbrechenCancelKicadModuleDialog(Alle Ebenen anzeigenshow all layers LayerPaletteAbbrechenCancel LinkDialog Text:text: LinkDialogURL:url: LinkDialogNicht anzeigbarUnable to displayLogoItemVDas Bild aus %1 kann nicht angezeigt werdenUnable to display image from %1LogoItemRda diese Datei kein <svg>-Element enthlt%because the file has no element���LogoItem���T�d�a� �d�i�e�s�e� �D�a�t�e�i� �k�e�i�n� �W�u�r�z�e�l�-�E�l�e�m�e�n�t� �e�n�t�h��l�t�������$because the file has no root element���LogoItem���2�d�a� �d�i�e� �S�V�G�-�D�a�t�e�i� �l�e�e�r� �i�s�t�������because the svg is empty���LogoItem����d�a� �d�i�e�s�e� �S�V�G�-�D�a�t�e�i� �v�e�r�m�u�t�l�i�c�h� �a�u�s� �C�o�r�e�l�D�R�A�W� �o�h�n�e� �d�i�e� �E�i�n�s�t�e�l�l�u�n�g� �"�p�r�e�s�e�n�t�a�t�i�o�n� �a�t�t�r�i�b�u�t�e�s�"� �e�x�p�o�r�t�i�e�r�t� �w�u�r�d�e� �������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem���@�a�u�f�g�r�u�n�d� �e�i�n�e�s� �R�e�n�d�e�r�i�n�g�-�F�e�h�l�e�r�s�������due to a rendering error���LogoItem���d�a�u�f�g�r�u�n�d� �e�i�n�e�s� �X�M�L�-�P�r�o�b�l�e�m�s�:� �%�1� �Z�e�i�l�e�:�%�2� �S�p�a�l�t�e�:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem����a�u�s� �u�n�b�e�k�a�n�n�t�e�n� �G�r��n�d�e�n�-�-�m��g�l�i�c�h�e�r�w�e�i�s�e� �i�s�t� �d�i�e� �B�i�l�d�d�a�t�e�i� �b�e�s�c�h��d�i�g�t�������9for unknown reasons--possibly the image file is corrupted���LogoItem����F�o�r�m�������shape���LogoItem����T�e�x�t�������text���LogoItem���@� � �W�i�l�l�s�t� �D�u� �j�e�t�z�t� �a�k�t�u�a�l�i�s�i�e�r�e�n�?������� Do you want to update now?��� MainWindow����%�1� �H�i�n�t�e�r�g�r�u�n�d������� %1 background��� MainWindow���n�%�1� �v�o�n� �%�2� �N�e�t�z�e�n� �g�e�r�o�u�t�e�t� �-� �%�n� �V�e�r�b�i�n�d�e�r� �n�o�c�h� �z�u� �r�o�u�t�e�n���n�%�1� �v�o�n� �%�2� �N�e�t�z�e�n� �g�e�r�o�u�t�e�t� �-� �%�n� �V�e�r�b�i�n�d�e�r� �n�o�c�h� �z�u� �r�o�u�t�e�n�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow����&��b�e�r� �F�r�i�t�z�i�n�g�������&About��� MainWindow����&��b�e�r� �Q�t������� &About Qt��� MainWindow����&�O�r�i�g�i�n�a�l�g�r���e������� &Actual Size��� MainWindow���8�Z�u�m� �S�o�r�t�i�m�e�n�t� �&�h�i�n�z�u�f��g�e�n�.�.�.�������&Add to bin...��� MainWindow����&�K�o�p�i�e�r�e�n�������&Copy��� MainWindow���F�&�L�e�i�t�e�r�b�a�h�n� �a�u�s� �L�u�f�t�l�i�n�i�e� �e�r�s�t�e�l�l�e�n�������&Create trace from ratsnest��� MainWindow���<�&�D�r�a�h�t� �a�u�s� �L�u�f�t�l�i�n�i�e� �e�r�s�t�e�l�l�e�n�������&Create wire from ratsnest��� MainWindow����&�A�u�s�s�c�h�n�e�i�d�e�n�������&Cut��� MainWindow����&�L��s�c�h�e�n�������&Delete��� MainWindow��� �D�r�a�h�t� �&�e�n�t�f�e�r�n�e�n������� &Delete Wire��� MainWindow���*�A�u�s�w�a�h�l� �&�z�u�r��c�k�s�e�t�z�e�n������� &Deselect��� MainWindow����&�D�u�p�l�i�z�i�e�r�e�n������� &Duplicate��� MainWindow����&�B�e�a�r�b�e�i�t�e�n�������&Edit��� MainWindow����&�E�x�p�o�r�t�i�e�r�e�n�������&Export��� MainWindow����&�E�x�p�o�r�t�i�e�r�e�n�.�.�.������� &Export...��� MainWindow��� �&�D�a�t�e�i�������&File��� MainWindow���6�A�l�l�e�s� �i�n� �&�F�e�n�s�t�e�r� �e�i�n�p�a�s�s�e�n�������&Fit in Window��� MainWindow���(�&�H�o�r�i�z�o�n�t�a�l� �u�m�d�r�e�h�e�n�������&Flip Horizontal��� MainWindow���$�&�V�e�r�t�i�k�a�l� �u�m�d�r�e�h�e�n�������&Flip Vertical��� MainWindow��� �&�H�i�l�f�e�������&Help��� MainWindow���.�A�l�l�e� �E�b�e�n�e�n� �a�&�u�s�b�l�e�n�d�e�n�������&Hide All Layers��� MainWindow���r�B�a�u�t�e�i�l�e� �u�n�d� �S�o�r�t�i�m�e�n�t�e� �a�u�s� �a�l�t�e�r� �V�e�r�s�i�o�n� �&�i�m�p�o�r�t�i�e�r�e�n�.�.�.�������*&Import parts and bins from old version...��� MainWindow����&�M�i�n�i�m�i�e�r�e�n������� &Minimize��� MainWindow����&�B�e�i�s�p�i�e�l�e������� &Open Example��� MainWindow���6�&�Z�u�l�e�t�z�t� �g�e��f�f�n�e�t�e� �E�n�t�w��r�f�e�������&Open Recent Files��� MainWindow����&��f�f�n�e�n�.�.�.�������&Open...��� MainWindow����B�a�u�&�t�e�i�l�������&Part��� MainWindow����&�E�i�n�f��g�e�n�������&Paste��� MainWindow���"�&�E�i�n�s�t�e�l�l�u�n�g�e�n�.�.�.�������&Preferences...��� MainWindow����&�D�r�u�c�k�e�n�.�.�.������� &Print...��� MainWindow����&�B�e�e�n�d�e�n�������&Quit��� MainWindow����&�S�p�e�i�c�h�e�r�n�������&Save��� MainWindow���&�S�p�e�i�c�h�e�r�n� �&�u�n�t�e�r�.�.�.������� &Save As...��� MainWindow��� �&�A�l�l�e�s� �a�u�s�w��h�l�e�n������� &Select All��� MainWindow���*�A�l�l�e� �E�b�e�n�e�n� �&�a�n�z�e�i�g�e�n�������&Show All Layers��� MainWindow���,�&�S�t�e�c�k�p�l�a�t�i�n�e� �a�n�z�e�i�g�e�n�������&Show Breadboard��� MainWindow���,�&�L�e�i�t�e�r�p�l�a�t�t�e� �a�n�z�e�i�g�e�n������� &Show PCB��� MainWindow���(�&�S�c�h�a�l�t�p�l�a�n� �a�n�z�e�i�g�e�n�������&Show Schematic��� MainWindow���(�W�i�l�l�k�o�m�m�e�n� �a�n�&�z�e�i�g�e�n������� &Show Welcome��� MainWindow���*�&�B�e�z�e�i�c�h�n�u�n�g� �a�n�z�e�i�g�e�n�������&Show part label��� MainWindow����&�A�n�s�i�c�h�t�������&View��� MainWindow����&�F�e�n�s�t�e�r�������&Window��� MainWindow����&�D�r�a�h�t�f�a�r�b�e������� &Wire Color��� MainWindow����&�V�e�r�g�r���e�r�n�������&Zoom In��� MainWindow����&�V�e�r�k�l�e�i�n�e�r�n������� &Zoom Out��� MainWindow���$�1�0�0�%� �(�P�i�x�e�l�-�)�G�r���e�������100% (pixel) size��� MainWindow����1�0�0�%� �G�r���e������� 100% Size��� MainWindow����O�r�i�g�i�n�a�l�g�r���e�������!Actual (real world physical) size��� MainWindow����O�r�i�g�i�n�a�l�g�r���e������� Actual Size��� MainWindow���*�B�i�e�g�e�p�u�n�k�t� �h�i�n�z�u�f��g�e�n������� Add Bendpoint��� MainWindow��� �N�o�t�i�z� �h�i�n�z�u�f��g�e�n�������Add Note��� MainWindow���d�E�i�n�e�n� �B�i�e�g�e�p�u�n�k�t� �z�u�m� �a�u�s�g�e�w��h�l�t�e�n� �D�r�a�h�t� �h�i�n�z�u�f��g�e�n�������$Add a bendpoint to the selected wire��� MainWindow��� �N�o�t�i�z������� Add a note��� MainWindow���Z�A�u�s�g�e�w��h�l�t�e�s� �B�a�u�t�e�i�l� �z�u�m� �S�o�r�t�i�m�e�n�t� �h�i�n�z�u�f��g�e�n�������Add selected part to bin��� MainWindow����A�u�s�r�i�c�h�t�e�n�������Align��� MainWindow��� �U�n�t�e�n������� Align Bottom��� MainWindow���*�H�o�r�i�z�o�n�t�a�l� �z�e�n�t�r�i�e�r�e�n�������Align Horizontal Center��� MainWindow��� �L�i�n�k�s������� Align Left��� MainWindow��� �R�e�c�h�t�s������� Align Right��� MainWindow����O�b�e�n������� Align Top��� MainWindow���&�V�e�r�t�i�k�a�l� �z�e�n�t�r�i�e�r�e�n�������Align Vertical Center��� MainWindow���R�E�l�e�m�e�n�t�e� �b�e�i�m� �Z�i�e�h�e�n� �a�m� �R�a�s�t�e�r� �a�u�s�r�i�c�h�t�e�n�������!Align items to grid when dragging��� MainWindow���J�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �u�n�t�e�n� �a�u�s�r�i�c�h�t�e�n�������"Align selected items at the bottom��� MainWindow���T�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �h�o�r�i�z�o�n�t�a�l� �z�e�n�t�r�i�e�r�e�n�������-Align selected items at the horizontal center��� MainWindow���J�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �l�i�n�k�s� �a�u�s�r�i�c�h�t�e�n������� Align selected items at the left��� MainWindow���L�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �r�e�c�h�t�s� �a�u�s�r�i�c�h�t�e�n�������!Align selected items at the right��� MainWindow���H�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �o�b�e�n� �a�u�s�r�i�c�h�t�e�n�������Align selected items at the top��� MainWindow���P�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �v�e�r�t�i�k�a�l� �z�e�n�t�r�i�e�r�e�n�������+Align selected items at the vertical center��� MainWindow���(�A�m� �R�a�s�t�e�r� �a�u�s�r�i�c�h�t�e�n������� Align to Grid��� MainWindow����A�l�l�e�������All��� MainWindow���`�E�s� �w�u�r�d�e�n� �n�o�c�h� �n�i�c�h�t� �a�l�l�e� �L�e�i�t�e�r�b�a�h�n�e�n� �g�e�r�o�u�t�e�d�.�������$All traces have not yet been routed.��� MainWindow����A�l�t�+�S�t�r�g�+�R������� Alt+Ctrl+R��� MainWindow���&�A�l�t�+�U�m�s�c�h�a�l�t�+�S�t�r�g�+�R�������Alt+Shift+Ctrl+R��� MainWindow���D�V�e�r�b�i�n�d�u�n�g�e�n� �a�u�t�o�m�a�t�i�s�c�h� �r�o�u�t�e�n�.�.�.�������Autoroute connections...��� MainWindow���>�A�u�t�o�r�o�u�t�e�r�/�D�R�C�-�E�i�n�s�t�e�l�l�u�n�g�e�n�.�.�.�������Autorouter/DRC settings...��� MainWindow���4�A�u�t�o�r�o�u�t�i�n�g�-�F�o�r�t�s�c�h�r�i�t�t�.�.�.�������Autorouting Progress...��� MainWindow���8�A�u�t�o�r�o�u�t�i�n�g�,� �b�i�t�t�e� �w�a�r�t�e�n�.�.�.�������Autorouting...��� MainWindow���&�'�%�1�'� �w�i�r�d� �g�e�s�i�c�h�e�r�t�������Backing up '%1'��� MainWindow���$�B�o�M�-�L�i�s�t�e� �(�*�.�h�t�m�l�)�������BoM Text File (*.html)��� MainWindow����B�e�i�d�e� �S�e�i�t�e�n������� Both Layers��� MainWindow����U�n�t�e�r�e� �S�e�i�t�e������� Bottom Layer��� MainWindow����S�t�e�c�k�p�l�a�t�i�n�e������� Breadboard��� MainWindow���>�S�c�h�r�i�t�t�w�e�i�s�e� �n�a�c�h� �v�o�r�n�e� �b�r�i�n�g�e�n������� Bring Forward��� MainWindow����A�u�s�w�a�h�l� �i�n�n�e�r�h�a�l�b� �d�e�i�n�e�r� �E�b�e�n�e� �s�c�h�r�i�t�t�w�e�i�s�e� �i�n� �d�e�n� �V�o�r�d�e�r�g�r�u�n�d� �b�r�i�n�g�e�n�������/Bring selected object(s) forward in their layer��� MainWindow���r�A�u�s�w�a�h�l� �i�n�n�e�r�h�a�l�b� �d�e�i�n�e�r� �E�b�e�n�e� �i�n� �d�e�n� �V�o�r�d�e�r�g�r�u�n�d� �b�r�i�n�g�e�n�������0Bring selected object(s) to front of their layer��� MainWindow���$�N�a�c�h� �v�o�r�n�e� �b�r�i�n�g�e�n�������Bring to Front��� MainWindow����A�b�b�r�e�c�h�e�n�������Cancel��� MainWindow���P�E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�f�u�n�d�e�n� �w�e�r�d�e�n�.�������Cannot find file %1.��� MainWindow���V�D�e�r� �E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�d�r�u�c�k�t� �w�e�r�d�e�n�������Cannot print to %1��� MainWindow���^�D�e�r� �E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�l�e�s�e�n� �w�e�r�d�e�n�:� �%�2�.�������Cannot read file 1 %1: %2.��� MainWindow���f�D�e�r� �E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�s�c�h�r�i�e�b�e�n� �w�e�r�d�e�n�:� �%�2�.�������Cannot write file %1: %2.��� MainWindow���&�B�i�l�d� ��n�d�e�r�n� �n�a�c�h� �%�2�������Change image to %2��� MainWindow���D�Z�u� �e�i�n�s�e�i�t�i�g�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� ��n�d�e�r�n�������Change to single layer pcb��� MainWindow���F�Z�u� �b�e�i�d�s�e�i�t�i�g�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� ��n�d�e�r�n�������Change to two layer pcb��� MainWindow���@�G�e�l�a�d�e�n�e� �L�e�i�t�e�r�b�a�h�n�e�n� ��b�e�r�p�r��f�e�n�������Check Loaded Traces��� MainWindow���,�N�a�c�h� �U�p�d�a�t�e�s� �s�u�c�h�e�n�.�.�.�������Check for updates...��� MainWindow�����b�e�r�p�r��f�e�n�,� �o�b� �e�i�n�e� �n�e�u�e�r�e� �F�r�i�t�z�i�n�g�-�V�e�r�s�i�o�n� �z�u�m� �D�o�w�n�l�o�a�d� �b�e�r�e�i�t� �s�t�e�h�t�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���B�W��h�l�e� �e�i�n�e�n� �O�r�d�n�e�r� �f��r� �d�e�n� �E�x�p�o�r�t�������Choose a folder for exporting��� MainWindow���\�K�l�i�c�k�e�,� �u�m� �u�n�v�e�r�b�u�n�d�e�n�e� �B�a�u�t�e�i�l�e� �h�e�r�v�o�r�z�u�h�e�b�e�n�������$Click to highlight unconnected parts��� MainWindow���h�A�l�l�e� �V�e�r�b�i�n�d�e�r� �m�i�t� �e�i�n�e�m� �e�i�n�z�i�g�e�n� �T�e�s�t�t�e�i�l� �v�e�r�b�i�n�d�e�n�������,Connect all connectors to a single test part��� MainWindow����U�m�w�a�n�d�e�l�n�������Convert��� MainWindow���6�B�i�e�g�e�p�u�n�k�t� �i�n� �V�i�a� �u�m�w�a�n�d�e�l�n�������Convert Bendpoint to Via��� MainWindow���6�V�i�a� �i�n� �B�i�e�g�e�p�u�n�k�t� �u�m�w�a�n�d�e�l�n�������Convert Via to Bendpoint��� MainWindow���>�B�i�e�g�e�p�u�n�k�t� �i�n� �e�i�n� �V�i�a� �u�m�w�a�n�d�e�l�n�������Convert the bendpoint to a via��� MainWindow���B�V�i�a� �i�n� �e�i�n�e�n� �B�i�e�g�e�p�u�n�k�t� �u�m�w�a�n�d�e�l�n�������Convert the via to a bendpoint��� MainWindow���@�U�n�t�e�r�e� �K�u�p�f�e�r�s�e�i�t�e� �i�s�t� �a�k�t�i�v�i�e�r�t�������Copper Bottom layer is active��� MainWindow����K�u�p�f�e�r�f��l�l�u�n�g������� Copper Fill��� MainWindow���$�K�u�p�f�e�r�f��l�l�u�n�g� �(�%�1�)�������Copper Fill (%1)��� MainWindow���b�O�b�e�r�e� �u�n�d� �u�n�t�e�r�e� �K�u�p�f�e�r�s�e�i�t�e� �s�i�n�d� �b�e�i�d�e� �a�k�t�i�v�i�e�r�t�������3Copper Top and Copper Bottom layers are both active��� MainWindow���<�O�b�e�r� �K�u�p�f�e�r�s�e�i�t�e� �i�s�t� �a�k�t�i�v�i�e�r�t�������Copper Top layer is active��� MainWindow��� �A�u�s�w�a�h�l� �k�o�p�i�e�r�e�n�������Copy selection��� MainWindow���f�D�a�s� �D�o�c�k�-�S�t�e�u�e�r�e�l�e�m�e�n�t� �k�o�n�n�t�e� �n�i�c�h�t� �e�r�r�e�i�c�h�t� �w�e�r�d�e�n�������Couldn't get the dock widget��� MainWindow���.�N�e�u�e�n� �E�n�t�w�u�r�f� �e�r�s�t�e�l�l�e�n�������Create a new sketch��� MainWindow���\�A�u�s� �d�i�e�s�e�r� �L�u�f�t�l�i�n�i�e� �e�i�n�e� �L�e�i�t�e�r�b�a�h�n� �e�r�s�t�e�l�l�e�n�������%Create a trace from the ratsnest line��� MainWindow���T�A�u�s� �d�i�e�s�e�r� �L�u�f�t�l�i�n�i�e� �e�i�n�e�n� �D�r�a�h�t� �e�r�s�t�e�l�l�e�n�������$Create a wire from the ratsnest line��� MainWindow��� �S�t�r�g�+�+�������Ctrl++��� MainWindow��� �S�t�r�g�+�-�������Ctrl+-��� MainWindow��� �S�t�r�g�+�0�������Ctrl+0��� MainWindow��� �S�t�r�g�+�1�������Ctrl+1��� MainWindow��� �S�t�r�g�+�2�������Ctrl+2��� MainWindow��� �S�t�r�g�+�3�������Ctrl+3��� MainWindow��� �S�t�r�g�+�4�������Ctrl+4��� MainWindow��� �S�t�r�g�+�5�������Ctrl+5��� MainWindow��� �S�t�r�g�+�=�������Ctrl+=��� MainWindow��� �S�t�r�g�+�?�������Ctrl+?��� MainWindow��� �S�t�r�g�+�D�������Ctrl+D��� MainWindow��� �S�t�r�g�+�M�������Ctrl+M��� MainWindow��� �S�t�r�g�+�N�������Ctrl+N��� MainWindow��� �S�t�r�g�+�O�������Ctrl+O��� MainWindow��� �S�t�r�g�+�P�������Ctrl+P��� MainWindow��� �S�t�r�g�+�Q�������Ctrl+Q��� MainWindow��� �S�t�r�g�+�R�������Ctrl+R��� MainWindow��� �S�t�r�g�+�S�������Ctrl+S��� MainWindow����S�t�r�+�U�m�s�c�h�a�l�t�+�V������� Ctrl+Shift+V��� MainWindow��� �S�t�r�g�+�[�������Ctrl+[��� MainWindow��� �S�t�r�g�+�]�������Ctrl+]��� MainWindow���(�A�u�s�w�a�h�l� �a�u�s�s�c�h�n�e�i�d�e�n������� Cut selection��� MainWindow���4�F�o�r�t�s�c�h�r�i�t�t� �d�e�r� �P�r��f�u�n�g�.�.�.�������DRC Progress...��� MainWindow���d�A�l�l�e� �B�a�u�t�e�i�l�e� �w�e�g�w�e�r�f�e�n� �i�n� �d�i�e�s�e�r� �A�n�s�i�c�h�t� �d�e�b�u�g�g�e�n�������!Debug dump all parts in this view��� MainWindow��� �D�e�b�u�g�g�e�r�-�A�u�s�g�a�b�e�������Debugger Output��� MainWindow����E�n�t�f�e�r�n�e�n�������Delete��� MainWindow��� �E�n�t�f�e�r�n�e�n� �(�o�h�n�e�)������� Delete Minus��� MainWindow���(�V�e�r�b�i�n�d�u�n�g� �e�n�t�f�e�r�n�e�n�������Delete Ratsnest Line��� MainWindow���(�L�e�i�t�e�r�b�a�h�n� �e�n�t�f�e�r�n�e�n������� Delete Wire��� MainWindow���f�V�e�r�b�i�n�d�u�n�g�e�n� �b�i�s� �z�u�m� �n��c�h�s�t�e�n� �K�n�o�t�e�n�p�u�n�k�t� �e�n�t�f�e�r�n�e�n�������Delete Wire up to bendpoints��� MainWindow����A�u�s�w�a�h�l� �l��s�c�h�e�n�������Delete selection��� MainWindow���j�A�u�s�g�e�w��h�l�t�e� �E�l�e�m�e�n�t�e� �o�h�n�e� �v�e�r�b�u�n�d�e�n�e� �D�r��h�t�e� �e�n�t�f�e�r�n�e�n�������'Delete selection without attached wires��� MainWindow���(�A�u�s�w�a�h�l� �z�u�r��c�k�s�e�t�z�e�n�������Deselect��� MainWindow���4�E�n�t�w�u�r�f�s�r�e�g�e�l�p�r��f�u�n�g� �(�D�R�C�)�������Design Rules Check (DRC)��� MainWindow���"�A�l�l�e� �D�r��h�t�e� �l��s�e�n�������Disconnect All Wires��� MainWindow���|�A�l�l�e� �D�r��h�t�e�,� �w�e�l�c�h�e� �m�i�t� �d�i�e�s�e�m� �V�e�r�b�i�n�d�e�r� �v�e�r�b�u�n�d�e�n� �s�i�n�d�,� �l��s�e�n�������0Disconnect all wires connected to this connector��� MainWindow���4�E�r�s�t�b�e�n�u�t�z�e�r�h�i�l�f�e� �a�n�z�e�i�g�e�n�������Display First Time Help��� MainWindow���V�H�i�l�f�e� �z�u�m� �B�a�u�t�e�i�l�e�-�E�d�i�t�o�r� �i�m� �B�r�o�w�s�e�r� ��f�f�n�e�n�������&Display Parts Editor help in a browser��� MainWindow���T�H�i�l�f�r�e�i�c�h�e� �T�a�s�t�a�t�u�r�k��r�z�e�l� �u�n�d� �w�e�i�t�e�r�e� �T�i�p�s�������+Display some handy Fritzing tips and tricks��� MainWindow���v�D�i�e� �B�a�u�t�e�i�l�e� �d�e�s� �S�o�r�t�i�m�e�n�t�s� �i�n� �e�i�n�e�r� �L�i�s�t�e�n�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������$Display the parts bin in a list view��� MainWindow���v�D�i�e� �B�a�u�t�e�i�l�e� �d�e�s� �S�o�r�t�i�m�e�n�t�s� �i�n� �e�i�n�e�r� �S�y�m�b�o�l�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������%Display the parts bin in an icon view��� MainWindow���8�V�o�n� �A�u�t�o�r�o�u�t�i�n�g� �a�u�s�s�c�h�l�i�e��e�n�������Do not autoroute��� MainWindow���^�M��c�h�t�e�s�t� �D�u� �d�i�e� �i�m�p�o�r�t�i�e�r�t�e�n� �B�a�u�t�e�i�l�e� �b�e�h�a�l�t�e�n�?�������'Do you want to keep the imported parts?��� MainWindow���@�M��c�h�t�e�s�t� �D�u� �t�r�o�t�z�d�e�m� �f�o�r�t�f�a�h�r�e�n�?�������Do you want to proceed anyway?��� MainWindow���&�S�p�e�n�d�e�n� �a�n� �F�r�i�t�z�i�n�g�������Donate to Fritzing��� MainWindow���.�A�l�l�e� �B�a�u�t�e�i�l�e� �w�e�g�w�e�r�f�e�n�������Dump all parts��� MainWindow���&�A�u�s�w�a�h�l� �d�u�p�l�i�z�i�e�r�e�n�������Duplicate selection��� MainWindow���D�B�e�a�r�b�e�i�t�e�n� �(�n�e�u�e�r� �B�a�u�t�e�i�l�e�-�E�d�i�t�o�r�)�������Edit (new parts editor)��� MainWindow���B�D�e�b�u�g�g�i�n�g�-�A�u�f�z�e�i�c�h�n�u�n�g� �a�k�t�i�v�i�e�r�e�n�������Enable debugging log��� MainWindow����T�e�x�t� �e�i�n�g�e�b�e�n������� Enter Text��� MainWindow�����t�z�b�a�r� �(�P�D�F�)�.�.�.�������Etchable (PDF)...��� MainWindow�����t�z�b�a�r� �(�S�V�G�)�.�.�.�������Etchable (SVG)...��� MainWindow����E�s� �k�a�n�n� �n�u�r� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �e�x�p�o�r�t�i�e�r�t� �w�e�r�d�e�n� �-� �b�i�t�t�e� �w��h�l�e� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�,� �d�i�e� �D�u� �e�x�p�o�r�t�i�e�r�e�n� �m��c�h�t�e�s�t�.�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow����A�k�t�u�e�l�l�e�n� �A�u�s�s�c�h�n�i�t�t� �a�l�s� �r�e�d�u�z�i�e�r�t�e�s� �S�V�G� �m�i�t� �1�0�0�0� �d�p�i� �e�x�p�o�r�t�i�e�r�e�n�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���j�A�k�t�u�e�l�l�e�n� �A�u�s�s�c�h�n�i�t�t� �a�l�s� �S�V�G� �m�i�t� �1�0�0�0� �d�p�i� �e�x�p�o�r�t�i�e�r�e�n�������-Export 1000 dpi SVG of this part in this view��� MainWindow���D�M�a�t�e�r�i�a�l�l�i�s�t�e� �(�B�o�M�)� �e�x�p�o�r�t�i�e�r�e�n�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���0�N�e�t�z�l�i�s�t�e� �e�x�p�o�r�t�i�e�r�e�n�.�.�.�������Export Netlist...��� MainWindow���6�R�e�d�u�z�i�e�r�t�e�s� �S�V�G� �e�x�p�o�r�t�i�e�r�e�n�������Export Normalized Flattened SVG��� MainWindow���<�N�o�r�m�a�l�i�s�i�e�r�t�e�s� �S�V�G� �e�x�p�o�r�t�i�e�r�e�n�������Export Normalized SVG��� MainWindow���<�S�P�I�C�E�-�N�e�t�z�l�i�s�t�e� �e�x�p�o�r�t�i�e�r�e�n�.�.�.�������Export SPICE Netlist...��� MainWindow���0�S�V�G�-�D�a�t�e�i� �e�x�p�o�r�t�i�e�r�e�n�.�.�.������� Export SVG...��� MainWindow���&�P�l�a�t�i�n�e� �e�x�p�o�r�t�i�e�r�e�n�������Export for PCB��� MainWindow���@�A�u�s�g�e�w��h�l�t�e�s� �B�a�u�t�e�i�l� �e�x�p�o�r�t�i�e�r�e�n�������Export selected part��� MainWindow���T�A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �a�l�s� �S�V�G�-�G�r�a�f�i�k� �s�p�e�i�c�h�e�r�n�������)Export the current sketch as an SVG image��� MainWindow���X�A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �n�a�c�h� �E�A�G�L�E� �C�A�D� �e�x�p�o�r�t�i�e�r�e�n�������&Export the current sketch to Eagle CAD��� MainWindow����A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �i�m� �E�x�t�e�n�d�e�d� �G�e�r�b�e�r�-�F�o�r�m�a�t� �(�R�S�-�2�7�4�X�)� �f��r� �p�r�o�f�e�s�s�i�o�n�e�l�l�e� �P�l�a�t�i�n�e�n�p�r�o�d�u�k�t�i�o�n� �e�x�p�o�r�t�i�e�r�e�n�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow����A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �a�l�s� �P�D�F� �f��r� �S�e�l�b�s�t�b�a�u�-�L�e�i�t�e�r�p�l�a�t�t�e�n� �e�x�p�o�r�t�i�e�r�e�n� �(�F�o�t�o�r�e�s�i�s�t�-�M�e�t�h�o�d�e�)�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow����A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �a�l�s� �S�V�G� �f��r� �S�e�l�b�s�t�b�a�u�-�L�e�i�t�e�r�p�l�a�t�t�e�n� �e�x�p�o�r�t�i�e�r�e�n� �(�F�o�t�o�r�e�s�i�s�t�-�M�e�t�h�o�d�e�)�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���T�S�i�c�h�t�b�a�r�e�n� �B�e�r�e�i�c�h� �a�l�s� �J�P�E�G�-�B�i�l�d� �s�p�e�i�c�h�e�r�n�������If a "sticky" part is moved, parts on top of it are also moved��� MainWindow����S�e�l�b�s�t� �e�r�s�t�e�l�l�t�e� �B�a�u�t�e�i�l�e� �u�n�d� �S�o�r�t�i�m�e�n�t�e� �a�u�s� �e�i�n�e�r� �f�r��h�e�r�e�n� �I�n�s�t�a�l�l�a�t�i�o�n� �i�m�p�o�r�t�i�e�r�e�n�������0Import parts and bins from previous installation��� MainWindow����I�n�s�p�e�k�t�o�r������� Inspector��� MainWindow���E�s� �i�s�t� �l�e�i�d�e�r� �n�i�c�h�t� �m��g�l�i�c�h�,� �d�i�e� �t�a�t�s��c�h�l�i�c�h�e� �p�h�y�s�i�s�c�h�e� �G�r���e� �d�i�e�s�e�s� �D�i�s�p�l�a�y�s� �z�u� �b�e�r�e�c�h�n�e�n�,� �s�o�d�a�s�s� �d�i�e� �"�O�r�i�g�i�n�a�l�g�r���e�"� �n�u�r� �e�i�n�e� �A�n�n��h�e�r�u�n�g� �i�s�t�.������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow���"�J�P�E�G�-�B�i�l�d� �(�*�.�j�p�g�)�������JPEG Image (*.jpg)��� MainWindow����%�1� �a�u�s�f��h�r�e�n�.�.�.������� Launch %1...��� MainWindow��� �E�b�e�n�e�n�������Layers��� MainWindow���(�S�t��c�k�l�i�s�t�e� �(�&�B�o�M�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow����L�a�d�e�.�.�.������� Loading...��� MainWindow����S�p�e�r�r�e�n������� Lock Part��� MainWindow����M�e�t�a�+�S�t�r�g�+�R������� Meta+Ctrl+R��� MainWindow���(�M�e�t�a�+�U�m�s�c�h�a�l�t�+�S�t�r�g�+�R�������Meta+Shift+Ctrl+R��� MainWindow���&�F�e�n�s�t�e�r� �m�i�n�i�m�i�e�r�e�n� �������Minimize current window��� MainWindow���r�A�u�s�g�e�w��h�l�t�e� �L�e�i�t�e�r�b�a�h�n�e�n� �a�u�f� �d�i�e� �a�n�d�e�r�e� �S�e�i�t�e� �v�e�r�s�c�h�i�e�b�e�n�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���8�A�u�f� �u�n�t�e�r�e� �E�b�e�n�e� �v�e�r�s�c�h�i�e�b�e�n�������Move to bottom layer��� MainWindow���H�A�u�f� �a�n�d�e�r�e� �P�l�a�t�i�n�e�n�s�e�i�t�e� �v�e�r�s�c�h�i�e�b�e�n�������Move to other side of the board��� MainWindow���6�A�u�f� �o�b�e�r�e� �E�b�e�n�e� �v�e�r�s�c�h�i�e�b�e�n�������Move to top layer��� MainWindow����N�e�u�������New��� MainWindow���V�I�n� �'�%�1�'� �k�o�n�n�t�e� �k�e�i�n� �E�n�t�w�u�r�f� �g�e�f�u�n�d�e�n� �w�e�r�d�e�n�������No Sketch found in '%1'��� MainWindow���:�K�e�i�n�e� �V�e�r�b�i�n�d�u�n�g�e�n� �z�u�m� �R�o�u�t�e�n�������No connections to route��� MainWindow���4�F�e�h�l�e�n�d�e� �o�b�e�r�e� �K�u�p�f�e�r�e�b�e�n�e�������No copper top layer��� MainWindow����K�e�i�n� �p�a�s�s�e�n�d�e�s� �B�a�u�t�e�i�l� �g�e�f�u�n�d�e�n�;� �d�a�s� ��h�n�l�i�c�h�s�t�e� �w�u�r�d�e� �a�u�t�o�m�a�t�i�s�c�h�e� �a�u�s�g�e�w��h�l�t�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow����K�e�i�n�e� �v�e�r�a�l�t�e�t�e�n� �B�a�u�t�e�i�l�e� �g�e�f�u�n�d�e�n�.� �A�l�l�e� �v�e�w�e�n�d�e�t�e�n� �B�a�u�t�e�i�l� �s�i�n�d� �a�u�f� �d�e�m� �a�k�t�u�e�l�l�e�n� �S�t�a�n�d�.�������7No outdated parts found. All your parts are up-to-date.��� MainWindow��@�E�s� �g�i�b�t� �l�e�i�d�e�r� �k�e�i�n�e� �B�a�u�t�e�i�l�e� �m�i�t� �d�i�e�s�e�n� �E�i�g�e�n�s�c�h�a�f�t�e�n�.� �(�W�i�r� �a�r�b�e�i�t�e�n� �d�a�r�a�n�,� �d�i�e�s�e�n� �H�i�n�w�e�i�s� �z�u� �v�e�r�m�e�i�d�e�n�,� �u�n�d� �n�u�r� �s�o�l�c�h�e� �E�i�g�e�n�s�c�h�a�f�t�e�n� �a�n�z�u�b�i�e�t�e�n�,� �d�i�e� �e�s� �g�i�b�t�.�)�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���f�E�s� �k�o�n�n�t�e�n� �k�e�i�n�e� �B�a�u�t�e�i�l�e� �f��r� �'�%�1�'� �g�e�f�u�n�d�e�n� �w�e�r�d�e�n�.�������"No parts matched search term '%1'.��� MainWindow���,�O�n�l�i�n�e�-�B�a�u�t�e�i�l�r�e�f�e�r�e�n�z�������Online Parts Reference��� MainWindow���*�O�n�l�i�n�e�-�P�r�o�j�e�k�t�g�a�l�e�r�i�e�������Online Projects Gallery��� MainWindow���$�O�n�l�i�n�e�-�A�n�l�e�i�t�u�n�g�e�n�������Online Tutorials��� MainWindow���F��f�f�n�e�t� �d�i�e� �F�r�i�t�z�i�n�g� �S�p�e�n�d�e�n�-�W�e�b�s�i�t�e�������Open Fritzing donation web page��� MainWindow���Z�F�r�i�t�z�i�n�g�-�B�e�i�s�p�i�e�l�p�r�o�j�e�k�t�e� ��f�f�n�e�n� �(�i�m� �B�r�o�w�s�e�r�)�������Open Fritzing examples��� MainWindow���D�F�r�i�t�z�i�n�g�-�H�i�l�f�e� ��f�f�n�e�n� �(�i�m� �B�r�o�w�s�e�r�)�������Open Fritzing help��� MainWindow���J�B�a�u�t�e�i�l�e�-�R�e�f�e�r�e�n�z� ��f�f�n�e�n� �(�i�m� �B�r�o�w�s�e�r�)�������Open Parts Reference��� MainWindow�����f�f�n�e� �e�i�n�e�n� �F�r�i�t�z�i�n�g�-�E�n�t�w�u�r�f� �(�.�f�z�z�,� �.�f�z�)�,� �e�i�n� �F�r�i�t�z�i�n�g�-�B�a�u�t�e�i�l� �(�.�f�z�p�z�)� �o�d�e�r� �-�B�a�u�t�e�i�l�s�o�r�t�i�m�e�n�t� �(�.�f�z�b�,� �.�f�z�b�z�)�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���n�F�e�n�s�t�e�r� �z�u�r� �P�r�o�g�r�a�m�m�i�e�r�e�u�n�g� �v�o�n� �M�i�k�r�o�c�o�n�t�r�o�l�l�e�r�n� ��f�f�n�e�n�������'Open microcontroller programming window��� MainWindow���$�P�r�o�g�r�a�m�m�i�e�r�f�e�n�s�t�e�r�������Open programming window��� MainWindow���v��f�f�n�e� �d�e�n� �n�e�u�e�n� �B�a�u�t�e�i�l�e�-�E�d�i�t�o�r� �f��r� �e�i�n� �v�o�r�h�a�n�d�e�n�e�s� �B�a�u�t�e�i�l�������-Open the new parts editor on an existing part��� MainWindow����E�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �b�e�s�t�e�l�l�e�n�,� �w�e�l�c�h�e� �a�u�s� �d�e�i�n�e�m� �E�n�t�w�u�r�f� �e�r�s�t�e�l�l�t� �w�u�r�d�e�-�-�v�o�n� �d�e�m� �f�a�b�e�l�h�a�f�t�e�n� �F�r�i�t�z�i�n�g� �F�a�b�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow���2�L�e�i�t�e�r�p�l�a�t�t�e� �b�e�s�t�e�l�l�e�n�.�.�.�������Order a PCB...��� MainWindow���$�V�e�r�a�l�t�e�t�e� �B�a�u�t�e�i�l�e�������Outdated parts��� MainWindow����L�e�i�t�e�r�p�l�a�t�t�e�������PCB��� MainWindow��� �P�N�G�-�B�i�l�d� �(�*�.�p�n�g�)�������PNG Image (*.png)��� MainWindow��� �S�e�i�t�e� �e�i�n�r�i�c�h�t�e�n������� Page Setup��� MainWindow���2�H�i�l�f�e� �z�u�m� �B�a�u�t�e�i�l�e�-�E�d�i�t�o�r�������Parts Editor Help��� MainWindow���P� �I�n�h�a�l�t�e� �a�u�s� �d�e�r� �Z�w�i�s�c�h�e�n�a�b�l�a�g�e� �e�i�n�f��g�e�n�������Paste clipboard contents��� MainWindow���V�Z�w�i�s�c�h�e�n�a�b�l�a�g�e� �a�n� �d�e�r� �M�a�u�s�p�o�s�i�t�i�o�n� �e�i�n�f��g�e�n�������!Paste clipboard contents in place��� MainWindow����H�i�e�r� �e�i�n�f��g�e�n�������Paste in Place��� MainWindow���r�B�i�t�t�e� �w��h�l�e� �d�e�n� �O�r�t� �d�e�r� �f�r��h�e�r�e�n� �F�r�i�t�z�i�n�g�-�I�n�s�t�a�l�l�a�t�i�o�n�.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow����B�i�t�t�e� �w��h�l�e� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.� �D�i�e� �K�u�p�f�e�r�f��l�l�u�n�g� �k�a�n�n� �n�u�r� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �a�u�s�g�e�f��h�r�t� �w�e�r�d�e�n�.�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow���B�i�t�t�e� �w��h�l�e� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.� ��n�d�e�r�u�n�g�e�n� �a�n� �d�e�r� �K�u�p�f�e�r�f��l�l�u�n�g� �k��n�n�e�n� �n�u�r� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �a�u�s�g�e�f��h�r�t� �w�e�r�d�e�n�.�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow����B�i�t�t�e� �w��h�l�e� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.� �D�i�e� �K�u�p�f�e�r�f��l�l�u�n�g� �k�a�n�n� �n�u�r� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �a�u�s�g�e�f��h�r�t� �w�e�r�d�e�n�.�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow����B�i�t�t�e� �w��h�l�e� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.� �D�i�e� �E�n�t�w�u�r�f�s�r�e�g�e�l�p�r��f�u�n�g� �k�a�n�n� �n�u�r� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �a�u�s�g�e�f��h�r�t� �w�e�r�d�e�n�.�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow����E�s� �k�a�n�n� �n�u�r� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �g�e�r�o�u�t�e�t� �w�e�r�d�e�n�.� �B�i�t�t�e� �w��h�l�e� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�,� �d�i�e� �D�u� �a�u�t�o�r�o�u�t�e�n� �m��c�h�t�e�s�t�.�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow���r�B�i�t�t�e� �g�i�b� �e�i�n�e�n� �n�e�u�e�n� �D�a�t�e�i�n�a�m�e�n� �(�.�f�z�z�)� �z�u�m� �S�p�e�i�c�h�e�r�n� �a�n�.�������0Please specify an .fzz file name to save '%1' to��� MainWindow���n�D�i�e�s�e�s� �P�r�o�j�e�k�t� �a�u�f� �d�e�r� �F�r�i�t�z�i�n�g� �W�e�b�s�i�t�e� �v�e�r��f�f�e�n�t�l�i�c�h�e�n�������&Post a project to the Fritzing website��� MainWindow���:�P�o�s�i�t�i�o�n� �d�e�s� �B�a�u�t�e�i�l�s� �s�p�e�r�r�e�n�������Prevent a part from being moved��� MainWindow���0�A�k�t�u�e�l�l�e� �A�n�s�i�c�h�t� �d�r�u�c�k�e�n�������Print the current view��� MainWindow����D�r�u�c�k�e�.�.�.������� Printing...��� MainWindow����F�o�r�t�s�e�t�z�e�n�������Proceed��� MainWindow��� �P�r�o�g�r�a�m�m� �b�e�e�n�d�e�n�������Quit the application��� MainWindow����R�e�i�h�e�n�f�o�l�g�e�������Raise and Lower��� MainWindow����N�u�r� �L�e�s�e�n������� Read-only��� MainWindow��� �F�e�r�t�i�g�������Ready��� MainWindow����N�e�u�b�e�r�e�c�h�n�u�n�g� �d�e�s� �R�o�u�t�i�n�g�-�S�t�a�t�u�s� �u�n�d� �a�l�l�e�r� �L�u�f�t�l�i�n�i�e�n� �(�f�a�l�l�s� �d�i�e� �a�u�t�o�m�a�t�i�s�c�h�e� �A�k�t�u�a�l�i�s�i�e�r�u�n�g� �n�i�c�h�t� �r�i�c�h�t�i�g� �f�u�n�k�t�i�o�n�i�e�r�t�)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow���"�&�W�i�e�d�e�r�h�e�r�s�t�e�l�l�e�n�������Redo��� MainWindow���(�E�n�t�w�u�r�f� �e�r�n�e�u�t� �l�a�d�e�n�������Reload the sketch��� MainWindow���(�B�i�e�g�e�p�u�n�k�t� �e�n�t�f�e�r�n�e�n�������Remove Bendpoint��� MainWindow���.�K�u�p�f�e�r�f��l�l�u�n�g� �e�n�t�f�e�r�n�e�n�������Remove Copper Fill��� MainWindow���.�K�u�p�f�e�r�f��l�l�u�n�g� �e�n�t�f�e�r�n�e�n�������Remove copper fill��� MainWindow���<�K�u�p�f�e�r�f��l�l�u�n�g� �w�i�e�d�e�r� �e�n�t�f�e�r�n�e�n�������Remove the copper fill��� MainWindow��� �F�e�h�l�e�r� �m�e�l�d�e�n�.�.�.�������Report a bug...��� MainWindow���j�M�e�l�d�e� �u�n�s� �e�i�n�e�n� �B�u�g�,� �d�e�n� �D�u� �i�n� �F�r�i�t�z�i�n�g� �e�n�t�d�e�c�k�t� �h�a�s�t�������%Report a but you've found in Fritzing��� MainWindow����Z�u�r��c�k�s�e�t�z�e�n�������Restore Default��� MainWindow����Z�u�r��c�k�s�e�t�z�e�n�������Revert��� MainWindow����Z�u�r��c�k�s�e�t�z�e�n�?�������Revert?��� MainWindow��� �D�r�e�h�e�n�������Rotate��� MainWindow���,�U�m� �1�8�0�� �d�r�e�h�e�n� �{�1�8�0�?�}������� Rotate 180���� MainWindow���L�U�m� �1�3�5�� �i�m� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���X�U�m� �4�5�� �g�e�g�e�n� �d�e�n� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow���L�U�m� �1�3�5�� �i�m� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���X�U�m� �4�5�� �g�e�g�e�n� �d�e�n� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���^�A�k�t�u�e�l�l�e� �A�u�s�w�a�h�l� �u�m� �4�5�� �i�m� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n�������-Rotate current selection 45 degrees clockwise��� MainWindow���l�A�k�t�u�e�l�l�e� �A�u�s�w�a�h�l� �u�m� �4�5�� �g�e�g�e�n� �d�e�n� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n�������5Rotate current selection 45 degrees counter clockwise��� MainWindow���l�A�k�t�u�e�l�l�e� �A�u�s�w�a�h�l� �u�m� �9�0�� �g�e�g�e�n� �d�e�n� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���P�D�i�e� �a�u�s�g�e�w��h�l�t�e�n� �B�a�u�t�e�i�l�e� �u�m� �1�8�0�� �d�r�e�h�e�n�������(Rotate the selected parts by 180 degrees��� MainWindow���p�D�i�e� �a�u�s�g�e�w��h�l�t�e�n� �B�a�u�t�e�i�l�e� �u�m� �9�0�� �i�m� �U�h�r�z�e�i�g�e�r�s�i�n�n� �d�r�e�h�e�n�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow���,�R�o�u�t�i�n�g� �f�e�r�t�i�g�g�e�s�t�e�l�l�t�������Routing completed��� MainWindow���R�R�o�u�t�i�n�g� �f�e�r�t�i�g�g�e�s�t�e�l�l�t� �m�i�t� �%�n� �D�r�a�h�t�b�r��c�k�e���T�R�o�u�t�i�n�g� �f�e�r�t�i�g�g�e�s�t�e�l�l�t� �m�i�t� �%�n� �D�r�a�h�t�b�r��c�k�e�n�������)Routing completed using %n jumper part(s)��� MainWindow���$�S�P�I�C�E� �N�e�t�z�l�i�s�t�e�.�.�.�������SPICE Netlist...��� MainWindow��� �S�V�G�-�B�i�l�d� �(�*�.�s�v�g�)�������SVG Image (*.svg)��� MainWindow����%�1� �s�p�e�i�c�h�e�r�n�������Save %1��� MainWindow���n�E�i�n�k�a�u�f�s�-� �b�z�w�.� �S�t��c�k�l�i�s�t�e� �(�B�o�M�)� �a�l�s� �T�e�x�t�d�a�t�e�i� �s�p�e�i�c�h�e�r�n�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���F�N�e�t�z�l�i�s�t�e� �i�m� �S�P�I�C�E�-�F�o�r�m�a�t� �s�p�e�i�c�h�e�r�n�������Save a netlist in SPICE format��� MainWindow���B�N�e�t�z�l�i�s�t�e� �i�m� �X�M�L�-�F�o�r�m�a�t� �s�p�e�i�c�h�e�r�n�������Save a netlist in XML format��� MainWindow���6�A�k�t�u�e�l�l�e�n� �E�n�t�w�u�r�f� �s�p�e�i�c�h�e�r�n�������Save the current sketch��� MainWindow��� �'�%�1�'� �g�e�s�p�e�i�c�h�e�r�t������� Saved '%1'��� MainWindow����B�e�i�m� �S�p�e�i�c�h�e�r�n� �d�i�e�s�e�s� �E�n�t�w�u�r�f�s� �w�i�r�d� �e�r� �i�n� �d�e�n� �n�e�u�e�n� �s�c�h�e�m�a�t�i�s�c�h�e�n� �G�r�a�f�i�k�s�t�a�n�d�a�r�d� �k�o�n�v�e�r�t�i�e�r�t�.� �F�o�r�t�f�a�h�r�e�n� �u�n�d� �k�o�n�v�e�r�t�i�e�r�e�n�?�������`Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert?��� MainWindow����S�c�h�a�l�t�p�l�a�n������� Schematic��� MainWindow���.�S�c�h�a�l�t�p�l�a�n�k�o�n�v�e�r�t�i�e�r�u�n�g�������Schematic conversion��� MainWindow���>�S�c�h�a�l�t�p�l�a�n�a�n�s�i�c�h�t� �a�k�t�u�a�l�i�s�i�e�r�e�n�������Schematic view update��� MainWindow��� �S�u�c�h�e�������Search��� MainWindow���H�B�a�u�t�e�i�l� �m�i�t� �e�i�n�e�m� �S�u�c�h�b�e�g�r�i�f�f� �f�i�n�d�e�n�������-Search for parts in a sketch by matching text��� MainWindow���\�A�l�l�e� �"�N�i�c�h�t� �A�u�t�o�r�o�u�t�e�n�"�-�L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�������#Select All "Don't Autoroute" Traces��� MainWindow���Z�A�l�l�e� �"�A�u�t�o�r�o�u�t�e�-�b�a�r�e�n�"�-�L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�������Select All Autoroutable Traces��� MainWindow���<�A�l�l�e� �K�u�p�f�e�r�f��l�l�u�n�g�e�n� �a�u�s�w��h�l�e�n�������Select All CopperFill��� MainWindow���6�A�l�l�e� �D�r�a�h�t�b�r��c�k�e�n� �a�u�s�w��h�l�e�n�������Select All Jumpers��� MainWindow���D�A�l�l�e� �g�e�s�p�e�r�r�t�e�n� �B�a�u�t�e�i�l�e� �a�u�s�w��h�l�e�n�������Select All Locked Parts��� MainWindow���6�A�l�l�e� �L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�������Select All Traces��� MainWindow���&�A�l�l�e� �V�i�a�s� �a�u�s�w��h�l�e�n�������Select All Vias��� MainWindow���*�A�l�l�e� �D�r��h�t�e� �a�u�s�w��h�l�e�n�������Select All Wires��� MainWindow���.�F�r�i�t�z�i�n�g�-�E�n�t�w�u�r�f� ��f�f�n�e�n�������Select a Fritzing File to Open��� MainWindow���R�A�l�l�e� �E�l�e�m�e�n�t�e� �m�i�t� �K�u�p�f�e�r�f��l�l�u�n�g� �a�u�s�w��h�l�e�n�������Select all copper fill items��� MainWindow���(�A�l�l�e� �T�e�i�l�e� �a�u�s�w��h�l�e�n�������Select all elements��� MainWindow���6�A�l�l�e� �D�r�a�h�t�b�r��c�k�e�n� �a�u�s�w��h�l�e�n�������Select all jumper item parts��� MainWindow���n�A�l�l�e� �B�a�u�t�e�i�l�e� �a�u�s�w��h�l�e�n�,� �d�i�e� �n�i�c�h�t� �b�e�w�e�g�t� �w�e�r�d�e�n� �k��n�n�e�n�������$Select all parts that can't be moved��� MainWindow���6�A�l�l�e� �L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�������Select all trace wires��� MainWindow����A�l�l�e� �L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�,� �d�i�e� �v�o�m� �A�u�t�o�r�o�u�t�i�n�g� �a�u�s�g�e�s�c�h�l�o�s�s�e�n� �s�i�n�d�������0Select all trace wires excluded from autorouting��� MainWindow����A�l�l�e� �L�e�i�t�e�r�b�a�h�n�e�n� �a�u�s�w��h�l�e�n�,� �d�i�e� �w��h�r�e�n�d� �d�e�s� �A�u�t�o�r�o�u�t�i�n�g� �g�e��n�d�e�r�t� �w�e�r�d�e�n� �k��n�n�t�e�n�������=Select all trace wires that can be changed during autorouting��� MainWindow���&�A�l�l�e� �V�i�a�s� �a�u�s�w��h�l�e�n�������Select all via parts��� MainWindow���*�A�l�l�e� �D�r��h�t�e� �a�u�s�w��h�l�e�n�������Select all wires��� MainWindow���W��h�l�e� �e�i�n�e� �L�e�i�t�e�r�b�a�h�n� �a�u�s�,� �d�e�s�s�e�n� �P�o�s�i�t�i�o�n� �a�u�f� �d�e�m� �B�i�l�d�s�c�h�i�r�m� �n�i�c�h�t� �d�e�r� �r�i�c�h�t�i�g�e�n� �P�o�s�i�t�i�o�n� �e�n�t�s�p�r�i�c�h�t�.� �(�N�u�r� �n��t�i�g� �f��r� �E�n�t�w��r�f�e� �d�i�e� �i�n� �V�e�r�s�i�o�n� �0�.�7�.�1�0� �o�d�e�r� �f�r��h�e�r� �m�i�t� �d�e�m� �A�u�t�o�r�o�u�t�e�r� �g�e�r�o�u�t�e�t� �w�u�r�d�e�n�.�)�������Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier��� MainWindow���8�V�e�r�a�l�t�e�t�e� �B�a�u�t�e�i�l�e� �a�u�s�w��h�l�e�n�������Select outdated parts��� MainWindow���>�S�c�h�r�i�t�t�w�e�i�s�e� �n�a�c�h� �h�i�n�t�e�n� �s�e�n�d�e�n������� Send Backward��� MainWindow����A�u�s�w�a�h�l� �i�n�n�e�r�h�a�l�b� �i�h�r�e�r� �E�b�e�n�e� �s�c�h�r�i�t�t�w�e�i�s�e� �i�n� �d�e�n� �H�i�n�t�e�r�g�r�u�n�d� �s�e�n�d�e�n�������+Send selected object(s) back in their layer��� MainWindow���n�A�u�s�w�a�h�l� �i�n�n�e�r�h�a�l�b� �i�h�r�e�r� �E�b�e�n�e� �i�n� �d�e�n� �H�i�n�t�e�r�g�r�u�n�d� �s�e�n�d�e�n�������2Send selected object(s) to the back of their layer��� MainWindow���$�N�a�c�h� �h�i�n�t�e�n� �s�e�n�d�e�n������� Send to Back��� MainWindow���&�H�i�n�t�e�r�g�r�u�n�d�f�a�r�b�e�.�.�.�������Set Background Color...��� MainWindow����R�a�s�t�e�r�g�r���e�.�.�.�������Set Grid Size...��� MainWindow���L�A�b�s�t�a�n�d� �d�e�r� �M�a�s�s�e�f��l�l�u�n�g� �e�i�n�s�t�e�l�l�e�n�.�.�.�������Set Ground Fill Keepout...��� MainWindow���P�A�u�t�o�r�o�u�t�e�r� �u�n�d� �E�n�t�w�u�r�f�s�r�e�g�e�l�n� �e�i�n�s�t�e�l�l�e�n�������/Set autorouting parameters including keepout...��� MainWindow���$�B�e�i�d�e� �K�u�p�f�e�r�s�e�i�t�e�n������� Set both copper layers clickable��� MainWindow���H�U�n�t�e�r�e� �K�u�p�f�e�r�e�b�e�n�e� �a�n�k�l�i�c�k�b�a�r� �m�a�c�h�e�n�������!Set copper bottom layer clickable��� MainWindow���F�O�b�e�r�e� �K�u�p�f�e�r�e�b�e�n�e� �a�n�k�l�i�c�k�b�a�r� �m�a�c�h�e�n�������Set copper top layer clickable��� MainWindow���^�D�i�e� �H�i�n�t�e�r�g�r�u�n�d�f�a�r�b�e� �f��r� �d�i�e�s�e� �A�n�s�i�c�h�t� �a�n�p�a�s�s�e�n�������%Set the background color of this view��� MainWindow���:�R�a�s�t�e�r�w�e�i�t�e� �f�e�s�t�l�e�g�e�n� �f��r� �%�1�.�������Set the grid size for %1.��� MainWindow����M�i�n�i�m�a�l�e�r� �A�b�s�t�a�n�d� �z�w�i�s�c�h�e�n� �M�a�s�s�e�f��l�l�u�n�g� �u�n�d� �b�e�n�a�c�h�b�a�r�t�e�n� �L�e�i�t�e�r�b�a�h�n�e�n� �u�n�d� �V�e�r�b�i�n�d�e�r�n�������ESet the minimum distance between ground fill and traces or connectors��� MainWindow���d�D�i�e� �W�e�i�t�e� �d�e�r� �R�a�s�t�e�r�u�n�g� �f��r� �d�i�e�s�e� �A�n�s�i�c�h�t� �a�n�p�a�s�s�e�n�������%Set the size of the grid in this view��� MainWindow����V�e�r��f�f�e�n�t�l�i�c�h�e�n�������Share��� MainWindow���2�O�n�l�i�n�e� �v�e�r��f�f�e�n�t�l�i�c�h�e�n�.�.�.�������Share online...��� MainWindow���0�%�1� �i�m� �T�e�r�m�i�n�a�l� �a�u�s�f��h�r�e�n�������Shell launch %1��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�0������� Shift+Ctrl+0��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�1������� Shift+Ctrl+1��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�2������� Shift+Ctrl+2��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�3������� Shift+Ctrl+3��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�A������� Shift+Ctrl+A��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�D������� Shift+Ctrl+D��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�R������� Shift+Ctrl+R��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�S������� Shift+Ctrl+S��� MainWindow���"�U�m�s�c�h�a�l�t�+�S�t�r�g�+�T�a�b�������Shift+Ctrl+Tab��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�[������� Shift+Ctrl+[��� MainWindow����U�m�s�c�h�a�l�t�+�S�t�r�g�+�]������� Shift+Ctrl+]��� MainWindow����C�o�d�e� �a�n�z�e�i�g�e�n������� Show Code��� MainWindow����R�a�s�t�e�r� �a�n�z�e�i�g�e�n������� Show Grid��� MainWindow���<�S�o�r�t�i�m�e�n�t� �a�l�s� �S�y�m�b�o�l�e� �a�n�z�e�i�g�e�n�������Show Parts Bin Icon View��� MainWindow���X�B�a�u�t�e�i�l�e�-�S�o�r�t�i�m�e�n�t� �i�n� �L�i�s�t�e�n�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������Show Parts Bin List View��� MainWindow���<�I�n�f�o�r�m�a�t�i�o�n�e�n� ��b�e�r� �Q�t� �a�n�z�e�i�g�e�n�������Show Qt's about box��� MainWindow���T�A�l�l�e� �E�b�e�n�e�n� �d�e�r� �a�k�t�u�e�l�l�e�n� �A�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������2Show all the available layers for the current view��� MainWindow���8�B�a�u�t�e�i�l�b�e�s�c�h�r�i�f�t�u�n�g� �a�n�z�e�i�g�e�n�������Show part label��� MainWindow���(�S�i�e�b�d�r�u�c�k� �e�i�n�b�l�e�n�d�e�n�������Show part silkscreen��� MainWindow���:�L�e�i�t�e�r�p�l�a�t�t�e�n�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������Show the PCB view��� MainWindow���H�Z�e�i�g�e� �I�n�f�o�r�m�a�t�i�o�n�e�n� ��b�e�r� �F�r�i�t�z�i�n�g� �a�n������� Show the application's about box��� MainWindow���:�S�t�e�c�k�p�l�a�t�i�n�e�n�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������Show the breadboard view��� MainWindow���F�(�P�r�o�g�r�a�m�m�i�e�r�-�)�C�o�d�e�-�A�n�s�i�c�h�t� �a�n�z�e�i�g�e�n������� Show the code (programming) view��� MainWindow���*�D�a�s� �R�a�s�t�e�r� �e�i�n�b�l�e�n�d�e�n������� Show the grid��� MainWindow���4�S�c�h�a�l�t�p�l�a�n�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������Show the schematic view��� MainWindow���>�D�i�e� �W�i�l�l�k�o�m�m�e�n�s�a�n�s�i�c�h�t� �a�n�z�e�i�g�e�n�������Show the welcome view��� MainWindow���(�U�n�g�e�r�o�u�t�e�t�e� �a�n�z�e�i�g�e�n������� Show unrouted��� MainWindow���P�B�e�z�e�i�c�h�n�u�n�g� �d�e�s� �B�a�u�t�e�i�l�s� �e�i�n�-�/�a�u�s�b�l�e�n�d�e�n�������*Show/hide the label for the selected parts��� MainWindow���0�E�n�t�w�u�r�f� �w�u�r�d�e� �e�x�p�o�r�t�i�e�r�t�������Sketch exported��� MainWindow���F�E�n�t�w�u�r�f� �w�u�r�d�e� �a�l�s� �G�e�r�b�e�r� �e�x�p�o�r�t�i�e�r�t�������Sketch exported to Gerber��� MainWindow���l�E�n�t�s�c�h�u�l�d�i�g�e� �b�i�t�t�e�,� �"�%�1�"� �h�a�b�e�n� �w�i�r� �n�o�c�h� �n�i�c�h�t� �f�e�r�t�i�g�.�.�������(Sorry, "%1" has not been implemented yet��� MainWindow���(�D�a�t�e�i�n�a�m�e�n� �a�u�s�w��h�l�e�n�������Specify a file name��� MainWindow����H�a�f�t�e�n�d�������Sticky��� MainWindow���$�B�i�e�g�u�n�g� �b�e�g�r�a�d�i�g�e�n�������Straighten Curve��� MainWindow���V�B�i�e�g�u�n�g� �d�e�s� �a�u�s�g�e�w��h�l�t�e�n� �D�r�a�h�t�e�s� �b�e�g�r�a�d�i�g�e�n�������)Straighten the curve of the selected wire��� MainWindow����%�1� �B�a�u�t�e�i�l�(�e�)� �e�r�f�o�l�g�r�e�i�c�h� �a�k�t�u�a�l�i�s�i�e�r�t�.� �B�i�t�t�e� ��b�e�r�p�r��f�e� �a�l�l�e� �A�n�s�i�c�h�t�e�n� �a�u�f� �e�v�e�n�t�u�e�l�l�e� �N�e�b�e�n�w�i�r�k�u�n�g�e�n�.�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow���D�e�r� �S�V�G�-�D�a�t�e�i� �%�1� �f�e�h�l�t� �e�i�n�e� �'�%�2�'�-�E�b�e�n�e�.� �U�m� �m�e�h�r� �d�a�r��b�e�r� �z�u� �l�e�r�n�e�n�,� �w�i�e� �m�a�n� �e�i�n�e� �e�i�g�e�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�n�f�o�r�m� �e�r�s�t�e�l�l�t�,� �s�c�h�a�u� �D�i�r� �d�i�e� �<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�A�n�l�e�i�t�u�n�g�<�/�a�>� �a�n�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���H�%�1� �w�u�r�d�e� �a�u�s�g�e�t�a�u�s�c�h�t� �d�u�r�c�h� �M�o�d�u�l� �%�2�������Swapped %1 with module %2��� MainWindow��� �V�e�r�b�i�n�d�e�r� �p�r��f�e�n�������Test Connectors��� MainWindow����D�e�r� �S�u�c�h�t�e�x�t� �w�i�r�d� �m�i�t� �d�e�n� �B�a�u�t�e�i�l�b�e�s�c�h�r�e�i�b�u�n�g�e�n� �v�e�r�g�l�i�c�h�e�n�.� �G�i�b� �e�i�n�e�n� �T�e�x�t� �z�u�r� �S�u�c�h�e� �e�i�n�:�������NText will match part label, description, title, etc. Enter text to search for:��� MainWindow���D�a�s� �.�f�z�-�F�o�r�m�a�t� �w�i�r�d� �n�i�c�h�t� �l��n�g�e�r� �v�e�r�w�e�n�d�e�t�.� � �M��c�h�t�e�s�t� �D�u� �'�%�1�'� �i�n� �d�a�s� �n�e�u�e� �.�f�z�z�-�F�o�r�m�a�t� �u�m�w�a�n�d�e�l�,� �o�d�e�r� �s�i�e� �n�u�r� �i�m� �L�e�s�e�m�o�d�u�s� ��f�f�n�e�n�?� �������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow����D�e�r� �K�o�n�v�e�r�t�i�e�r�u�n�g�s�p�r�o�z�e�s�s� �w�i�r�d� �'�%�1�'� �n�i�c�h�t� �v�e�r��n�d�e�r�n�,� �b�i�s� �D�u� �d�i�e� �D�a�t�e�i� �s�p�e�i�c�h�e�r�s�t�.� �������FThe conversion process will not modify '%1', until you save the file. ��� MainWindow���b�D�e�r� �U�m�w�a�n�d�l�u�n�g�s�v�o�r�g�a�n�g� �w�i�r�d� �'�%�1�'� �n�i�c�h�t� �v�e�r��n�d�e�r�n�.�������,The conversion process will not modify '%1'.��� MainWindow��t�D�i�e� �o�b�e�r�e� �K�u�p�f�e�r�e�b�e�n�e� �(�c�o�p�p�e�r� �1�)� �i�s�t� �a�u�f� �e�i�n�e�r� �e�i�n�s�e�i�t�i�g�e�n� �L�e�i�t�e�r�p�l�a�t�t�e� �n�i�c�h�t� �v�e�r�f��g�b�a�r�.� �B�i�t�t�e� ��n�d�e�r�e� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�f� �e�i�n�e� �b�e�i�d�s�e�i�t�i�g�e�,� �o�d�e�r� �w��h�l�e� �d�i�e� �u�n�t�e�r�e� �K�u�p�f�e�r�e�b�e�n�e� �(�c�o�p�p�e�r� �0�)�.�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���j�D�e�r� �O�r�d�n�e�r� �"�%�1�"� �i�s�t� �k�e�i�n� �F�r�i�t�z�i�n�g�-�I�n�s�t�a�l�l�a�t�i�o�n�s�o�r�d�n�e�r�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���b�E�s� �s�i�n�d� �%�n� �v�e�r�a�l�t�e�t�e� �B�a�u�t�e�i�l�e� �i�n� �d�i�e�s�e�m� �E�n�t�w�u�r�f�.� �������.There are %n outdated part(s) in this sketch. ��� MainWindow���t�E�s� �g�i�b�t� �k�e�i�n�e� �u�n�g�e�r�o�u�t�e�t�e�n� �V�e�r�b�i�n�d�u�n�g�e�n� �i�n� �d�i�e�s�e�r� �A�n�s�i�c�h�t�.�������/There are no unrouted connections in this view.��� MainWindow����E�s� �g�i�b�t� �e�i�n�e�n� �n�e�u�e�n� �G�r�a�f�i�k�s�t�a�n�d�a�r�d� �f��r� �d�i�e� �B�a�u�t�e�i�l�b�i�l�d�e�r� �d�e�r� �S�c�h�a�l�t�p�l�a�n�a�n�s�i�c�h�t�,� �b�e�g�i�n�n�e�n�d� �m�i�t� �V�e�r�s�i�o�n� �0�.�8�.�6�.� � �������`There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. ��� MainWindow���X�E�s� �g�i�b�t� �b�e�r�e�i�t�s� �e�i�n� �B�a�u�t�e�i�l� �m�i�t� �d�e�r� �I�D� �'�%�1�'�.�������:There is already a part with id '%1' loaded into Fritzing.��� MainWindow����D�i�e�s� �k�a�n�n� �z�u� ��n�d�e�r�u�n�g�e�n� �a�m� �E�n�t�w�u�r�f� �f��h�r�e�n�,� �B�a�u�t�e�i�l�e� �o�d�e�r� �V�e�r�b�i�n�d�e�r� �k��n�n�e�n� �v�e�r�s�c�h�o�b�e�n� �s�e�i�n�.� �������RThis may result in changes to your sketch, as parts or connectors may be shifted. ��� MainWindow����D�i�e�s�e�r� �B�e�f�e�h�l� �k�a�n�n� �n�i�c�h�t� �r��c�k�g��n�g�i�g� �g�e�m�a�c�h�t� �w�e�r�d�e�n�.� �D�u� �w�i�r�s�t� �a�l�l�e� ��n�d�e�r�u�n�g�e�n� �v�e�r�l�i�e�r�e�n�.� � �Z�u�r��c�k�s�e�t�z�e�n�?�������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow��"�A�n� �d�i�e�s�e�r� �S�t�e�l�l�e� �g�i�b�t� �e�s� �b�a�l�d� �e�i�n�e�n� �E�x�p�o�r�t� �z�u�r� �E�A�G�L�E� �L�a�y�o�u�t� �S�o�f�t�w�a�r�e�.� �W�e�n�n� �D�u� �m�e�h�r� �E�x�p�o�r�t�m��g�l�i�c�h�k�e�i�t�e�n� �w��n�s�c�h�s�t�,� �s�a�g� �u�n�s� �B�e�s�c�h�e�i�d�,� �o�d�e�r� �h�i�l�f� �m�i�t�.�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow��� �D�r��h�t�e� �a�u�f�r��u�m�e�n������� Tidy Wires��� MainWindow���8�A�u�s�g�e�w��h�l�t�e� �D�r��h�t�e� �a�u�f�r��u�m�e�n�������Tidy selected wires��� MainWindow���:�T�i�p�p�s�,� �T�r�i�c�k�s�,� �u�n�d� �K�u�r�z�t�a�s�t�e�n�������Tips, Tricks and Shortcuts��� MainWindow����O�b�e�r�e� �S�e�i�t�e������� Top Layer��� MainWindow����D�i�e�s�e�n� �V�e�r�b�i�n�d�e�r� �u�n�d� �s�e�i�n�e� �V�e�r�b�i�n�d�u�n�g�e�n� �a�l�s� �"�M�a�s�s�e�"� �b�e�i� �d�e�r� �M�a�s�s�e�f��l�l�u�n�g� �b�e�l�e�g�e�n�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���`�%�1� �k�o�n�n�t�e� �n�i�c�h�t� �a�l�s� �v�e�r�t�e�i�l�b�a�r� �e�x�p�o�r�t�i�e�r�t� �w�e�r�d�e�n������� Unable to export %1 as shareable��� MainWindow���n�D�e�r� �E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �a�l�s� �P�a�k�e�t� �e�x�p�o�r�t�i�e�r�t� �w�e�r�d�e�n�������'Unable to export %1 to shareable sketch��� MainWindow���X�B�a�u�t�e�i�l� �a�u�s� �"�%�1�"� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�l�a�d�e�n� �w�e�r�d�e�n�������Unable to load part from '%1'��� MainWindow���J�"�%�1�"� �k�o�n�n�t�e� �n�i�c�h�t� �g�e��f�f�n�e�t� �w�e�r�d�e�n�:� �%�2�������Unable to open '%1': %2��� MainWindow���b�"�%�1�"� �(�s�h�a�r�e�a�b�l�e�)� �k�o�n�n�t�e� �n�i�c�h�t� �g�e��f�f�n�e�t� �w�e�r�d�e�n�:� �%�2�������!Unable to open shareable '%1': %2��� MainWindow���Z�B�a�u�t�e�i�l� �"�%�1�"� �k�o�n�n�t�e� �n�i�c�h�t� �g�e��f�f�n�e�t� �w�e�r�d�e�n�:� �%�2�������&Unable to open shareable part '%1': %2��� MainWindow���\�D�e�r� �E�n�t�w�u�r�f� �%�1� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�s�p�e�i�c�h�e�r�t� �w�e�r�d�e�n�������Unable to save %1��� MainWindow����D�i�e� �B�o�M�-�D�a�t�e�i� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�s�p�e�i�c�h�e�r� �w�e�r�d�e�n�,� �a�b�e�r� �d�e�r� �T�e�x�t� �l�i�e�g�t� �i�m� �Z�w�i�s�c�h�e�n�s�p�e�i�c�h�e�r�.�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow����&�R��c�k�g��n�g�i�g�������Undo��� MainWindow����V�e�r�l�a�u�f������� Undo History��� MainWindow���0�U�n�g�e�r�o�u�t�e�t�e� �V�e�r�b�i�n�d�u�n�g�e�n�������Unrouted connections��� MainWindow���6�%�1� �B�a�u�t�e�i�l�(�e�)� �a�k�t�u�a�l�i�s�i�e�r�e�n�������Update %1 part(s)��� MainWindow���D�A�u�s�g�e�w��h�l�t�e� �B�a�u�t�e�i�l�e� �a�k�t�u�a�l�i�s�i�e�r�e�n�������Update selected parts��� MainWindow��� �A�n�s�i�c�h�t� �v�o�n� �o�b�e�n�������View from Above��� MainWindow���"�A�n�s�i�c�h�t� �v�o�n� �u�n�t�e�n�������View from Below��� MainWindow����S�i�c�h�t� �v�o�n� �o�b�e�n�������View from above��� MainWindow����S�i�c�h�t� �v�o�n� �u�n�t�e�n�������View from below��� MainWindow���B�L�e�i�t�e�r�p�l�a�t�t�e� �v�o�n� �u�n�t�e�n� �b�e�t�r�a�c�h�t�e�n�������+View the PCB from the bottom layers upwards��� MainWindow���@�L�e�i�t�e�r�p�l�a�t�t�e� �v�o�n� �o�b�e�n� �b�e�t�r�a�c�h�t�e�n�������*View the PCB from the top layers downwards��� MainWindow����W�i�r� �e�m�p�f�e�h�l�e�n� �D�i�r� �e�i�n�d�r�i�n�g�l�i�c�h�,� �d�i�e�s�e� �%�n� �B�a�u�t�e�i�l�e� �a�u�f� �d�i�e� �n�e�u�e�s�t�e� �V�e�r�s�i�o�n� �z�u� �a�k�t�u�a�l�i�s�i�e�r�e�n�.� �������MWe strongly recommend that you update these %n parts to the latest version. ��� MainWindow����W�i�l�l�k�o�m�m�e�n�������Welcome��� MainWindow���R�B�e�i�m� �A�u�t�o�r�o�u�t�e�n� �d�i�e�s�e�s� �E�l�e�m�e�n�t� �i�g�n�o�r�i�e�r�e�n�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow����M��c�h�t�e�s�t� �D�u� �'�%�1�'� �j�e�t�z�t� �i�n� �d�e�n� �n�e�u�e�n� �S�t�a�n�d�a�r�d� �k�o�n�v�e�r�t�i�e�r�e�n� �o�d�e�r� �d�i�e� �D�a�t�e�i� �s�c�h�r�e�i�b�g�e�s�c�h��t�z�t� ��f�f�n�e�n�?�������SWould you like to convert '%1' to the new standard now or open the file read-only? ��� MainWindow��� �X�M�L�-�N�e�t�z�l�i�s�t�e�.�.�.�������XML Netlist...��� MainWindow����D�u� �m�u�s�s�t� �F�r�i�t�z�i�n�g� �n�e�u�s�t�a�r�t�e�n�,� �u�m� �d�i�e� �i�m�p�o�r�t�i�e�r�t�e�n� �B�a�u�t�e�i�l�e� �n�u�t�z�e�n� �z�u� �k��n�n�e�n�.�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow���D�e�i�n�e�m� �E�n�t�w�u�r�f� �f�e�h�l�t� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �U�m� �n�a�c�h� �G�e�r�b�e�r� �z�u� �e�x�p�o�r�t�i�e�r�e�n�,� �m��s�s�e�n� �d�i�e� �B�a�u�t�e�i�l�e� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �(�P�C�B�)� �a�n�g�e�o�r�d�n�e�t� �s�e�i�n�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �d�i�e� �K�u�p�f�e�r�f��l�l�u�n�g� �e�n�t�f�e�r�n�e�n� �z�u� �k��n�n�e�n�.�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �e�i�n�e� �K�u�p�f�e�r�f��l�l�u�n�g� �z�u� �e�r�z�e�u�g�e�n�.�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �d�e�n� �A�u�t�o�r�o�u�t�e�r� �z�u� �s�t�a�r�t�e�n�.�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �d�e�n� �d�i�e� �E�n�t�w�u�r�f�s�r�e�g�e�l�p�r��f�u�n�g� �z�u� �s�t�a�r�t�e�n�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �h�i�n�z�u�,� �u�m� �d�e�n� �E�x�p�o�r�t� �z�u� �e�r�m��g�l�i�c�h�e�n�.�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow����D�e�i�n�e�m� �E�n�t�w�u�r�f� �f�e�h�l�t� �n�o�c�h� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �F��r� �d�i�e� �K�u�p�f�e�r�f��l�l�u�n�g� �m�u�s�s�t� �D�u� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �(�P�C�B�)� �e�i�n�f��g�e�n�.�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow����V�e�r�g�r���e�r�n�������Zoom in��� MainWindow����V�e�r�k�l�e�i�n�e�r�n�������Zoom out��� MainWindow����a�l�s� �B�i�l�d�������as Image��� MainWindow��� �U�n�t�e�n�������bottom��� MainWindow��� �K�u�p�f�e�r�������copper��� MainWindow����K�u�p�f�e�r�f��l�l�i�n�g������� copperfill��� MainWindow���*�B�a�u�t�e�i�l�e� �d�i�r�e�k�t� �l�a�d�e�n�������directly loading parts��� MainWindow���$�f��r� �d�i�e� �P�r�o�d�u�k�t�i�o�n�������for Production��� MainWindow��� �M�a�s�s�e�������ground��� MainWindow����D�r�a�h�t�b�r��c�k�e�n�������jumpers��� MainWindow����L�a�d�e� �%�1������� loading %1��� MainWindow���,�L�a�d�e� �%�1� �(�S�t�e�c�k�p�l�a�t�i�n�e�)�������loading %1 (breadboard)��� MainWindow��� �L�a�d�e� �%�1� �(�M�o�d�e�l�l�)�������loading %1 (model)��� MainWindow���,�L�a�d�e� �%�1� �(�L�e�i�t�e�r�p�l�a�t�t�e�)�������loading %1 (pcb)��� MainWindow���(�L�a�d�e� �%�1� �(�S�c�h�a�l�t�p�l�a�n�)�������loading %1 (schematic)��� MainWindow����N�e�u�e�r� �E�n�t�w�u�r�f������� new sketch��� MainWindow���T�d�a�s� �.�f�z�-�F�o�r�m�a�t� �w�i�r�d� �n�i�c�h�t� �l��n�g�e�r� �v�e�r�w�e�n�d�e�t�������the .fz file format is obsolete��� MainWindow���v�T�e�s�t�w�e�i�s�e� �e�i�n�e� �A�u�s�n�a�h�m�e� �e�r�z�w�i�n�g�e�n�,� �u�m� �z�u� �s�e�h�e�n� �w�a�s� �p�a�s�s�i�e�r�t�������*throw a fake exception to see what happens��� MainWindow���,�T�e�s�t�-�A�u�s�n�a�h�m�e� �e�r�z�e�u�g�e�n�������throw test exception��� MainWindow����O�b�e�n�������top��� MainWindow����O�b�e�n� �u�n�d� �u�n�t�e�n�������top and bottom��� MainWindow���H�K�o�n�n�t�e� �k�e�i�n�e�n� �E�r�s�a�t�z� �f��r� �%�1� �f�i�n�d�e�n�.� �������#unable to find replacement for %1. ��� MainWindow����V�i�a�s�������vias��� MainWindow����m�i�t� �%�n� �V�i�a����m�i�t� �%�n� �V�i�a�s������� with %n vias��� MazeRouter���B�D�e�r� �A�u�t�o�r�o�u�t�e�r� �w�u�r�d�e� �a�b�g�e�b�r�o�c�h�e�n�.�������Autorouter was cancelled.��� MazeRouter���2�O�p�t�i�m�i�e�r�e� �L�e�i�t�e�r�b�a�h�n�e�n�.�.�.�������Optimizing traces...��� MazeRouter���@�Z�u�r��c�k�s�e�t�z�e�n� �w�i�r�d� �v�o�r�b�e�r�e�i�t�e�t�.�.�.�������Preparing undo...��� MazeRouter���.�R�o�u�t�i�n�g� �f�e�r�t�i�g�g�e�s�t�e�l�l�t�!�������Routing complete!��� MazeRouter���R�R�o�u�t�i�n�g� �h�a�t� �d�i�e� �l�e�t�z�t�e� �R�u�n�d�e� �%�1� �e�r�r�e�i�c�h�t�.�������!Routing reached maximum round %1.��� MazeRouter���&�R�o�u�t�i�n�g� �a�n�g�e�h�a�l�t�e�n�!�������Routing stopped!��� MazeRouter���^�R�o�u�t�i�n�g� �n�i�c�h�t� �e�r�f�o�l�g�r�e�i�c�h�;� �b�e�e�n�d�e�t� �i�n� �R�u�n�d�e� �%�1�.�������+Routing unsuccessful; stopping at round %1.��� MazeRouter����U�n�e�r�w�a�r�t�e�t�e�r� �S�V�G�-�R�e�n�d�e�r�i�n�g�-�F�e�h�l�e�r�-�-�b�i�t�t�e� �k�o�n�t�a�k�t�i�e�r�e� �f�r�i�t�z�i�n�g�.�o�r�g�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���6�B�e�s�t�e�s� �R�e�s�u�l�t�a�t� �a�n�w�e�n�d�e�n�.�.�.�������Use best so far...��� MazeRouter���T�B�i�s�h�e�r� �b�e�s�t�e�s� �R�e�s�u�l�t�a�t�:� �%�1� �v�o�n� �%�2� �g�e�r�o�u�t�e�t�������best so far: %1 of %2 routed��� MazeRouter����R�u�n�d�e� �%�1� �v�o�n�:������� round %1 of:��� MazeRouter����K�o�n�n�t�e� �d�i�e� �D�a�t�e�i� �'�%�1�'� �n�i�c�h�t� ��b�e�r�s�c�h�r�e�i�b�e�n�.� �U�r�s�a�c�h�e�:� �%�2� �(�F�e�h�l�e�r�c�o�d�e� �%�3�)�������5Couldn't overwrite file '%1'. Reason: %2 (errcode %3)��� ModelBase���L�D�a�t�e�i� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�s�p�e�i�c�h�e�r�t� �w�e�r�d�e�n�!�������File save failed!��� ModelBase���f�D�a�s� �f�o�l�g�e�n�d�e� �B�a�u�t�e�i�l� �k�o�n�n�t�e�n� �n�i�c�h�t� �g�e�f�u�n�d�e�n� �w�e�r�d�e�n�:���p�D�i�e� �f�o�l�g�e�n�d�e�n� �%�n� �B�a�u�t�e�i�l�e� �k�o�n�n�t�e�n� �n�i�c�h�t� �g�e�f�u�n�d�e�n� �w�e�r�d�e�n�:�������(Unable to find the following %n part(s):��� ModelBase����b�e�i�������at��� ModelBase���"�C�h�i�p�-�B�e�s�c�h�r�i�f�t�u�n�g������� chip label��� MysteryPart����B�e�s�c�h�r�i�f�t�u�n�g�������label��� MysteryPart����N�e�t�z�b�e�z�e�i�c�h�n�u�n�g������� net label���NetLabel���$�[�D�e�i�n�e� �N�o�t�i�z� �h�i�e�r�]�������[write your note here]���Note���\�%�1�-�F��l�l�u�n�g�:� �B�i�t�t�e� �w��h�l�e� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.�������;%1 Fill: please select the board you want to apply fill to.���PCBSketchWidget���d�1�0� �t�a�u�s�e�n�d�s�t�e�l� �Z�o�l�l� �s�i�n�d� �e�i�n� �g�u�t�e�r� �S�t�a�n�d�a�r�d�w�e�r�t�.� � �������#10 mils is a good default choice. ���PCBSketchWidget���8�A�u�f� �a�n�d�e�r�e� �S�e�i�t�e� �v�e�r�s�c�h�i�e�b�e�n�������Change trace layer���PCBSketchWidget����D�i�e�s�e�n� �V�e�r�b�i�n�d�e�r� �a�n�k�l�i�c�k�e�n� �u�n�d� �z�i�e�h�e�n�,� �u�m� �e�i�n�e� �n�e�u�e� �L�e�i�t�e�r�b�a�h�n� �z�u� �e�r�z�e�u�g�e�n�.�������-Click this connector to drag out a new trace.���PCBSketchWidget��� �K�u�p�f�e�r�������Copper���PCBSketchWidget���b�K�u�p�f�e�r�f��l�l�u�n�g�:� �B�i�t�t�e� �w��h�l�e� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.�������;Copper fill: please select only the board you want to fill.���PCBSketchWidget���D�L�e�i�t�e�r�b�a�h�n� �a�u�s� �L�u�f�t�l�i�n�i�e� �e�r�s�t�e�l�l�e�n�������Create Trace from Ratsnest���PCBSketchWidget��� �A�b�s�t�a�n�d� �e�i�n�g�e�b�e�n������� Enter Keepout���PCBSketchWidget���2�G�i�b� �d�e�n� �A�b�s�t�a�n�d�s�w�e�r�t� �e�i�n�:�������Enter keepout value:���PCBSketchWidget���<�F�r�i�t�z�i�n�g� �F�a�b� �H�e�r�s�t�e�l�l�u�n�g�s�p�r�e�i�s�������Fritzing Fab Quote���PCBSketchWidget����F�e�h�l�e�r�:� �D�a�s� �L�e�i�t�e�r�p�l�a�t�t�e�n�-�S�V�G� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�r�e�n�d�e�r�t� �w�e�r�d�e�n� �(�1�)�.�������/Fritzing error: unable to render board svg (1).���PCBSketchWidget���r�F�e�h�l�e�r�:� �D�a�s� �K�u�p�f�e�r�-�S�V�G� �k�o�n�n�t�e� �n�i�c�h�t� �g�e�r�e�n�d�e�r�t� �w�e�r�d�e�n� �(�1�)�.�������0Fritzing error: unable to render copper svg (1).���PCBSketchWidget���b�F�e�h�l�e�r�:� �K�o�n�n�t�e� �K�u�p�f�e�r�f��l�l�u�n�g� �n�i�c�h�t� �e�r�s�t�e�l�l�e�n� �(�1�)�.�������0Fritzing error: unable to write copper fill (1).���PCBSketchWidget���b�F�e�h�l�e�r�:� �K�o�n�n�t�e� �K�u�p�f�e�r�f��l�l�u�n�g� �n�i�c�h�t� �e�r�s�t�e�l�l�e�n� �(�2�)�.�������0Fritzing error: unable to write copper fill (2).���PCBSketchWidget��� �M�a�s�s�e�������Ground���PCBSketchWidget���8�B�a�u�t�e�i�l�-�S�i�e�b�d�r�u�c�k� �a�u�s�b�l�e�n�d�e�n�������Hide part silkscreen���PCBSketchWidget���V�A�b�s�t�a�n�d� �i�n� �t�a�u�s�e�n�d�s�t�e�l� �Z�o�l�l� �(�0�.�0�0�1� �Z�o�l�l�)�.� � �������#Keepout is in mils (.001 inches). ���PCBSketchWidget����B�e�a�c�h�t�e�n� �S�i�e�,� �d�a�s�s� �d�u�r�c�h� �d�i�e� �K�a�n�t�e�n�g�l��t�t�u�n�g� �d�e�r� �A�b�s�t�a�n�d� �u�m� �c�a�.� �2� �t�a�u�s�e�n�d�s�t�e�l� �Z�o�l�l� �k�l�e�i�n�e�r� �w�e�r�d�e�n� �k�a�n�n� �������FNote that due to aliasing, distances may be too short by up to 2 mils ���PCBSketchWidget����B�i�t�t�e� �w��h�l�e� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �a�u�s�.� �D�i�e�s�e� �F�u�n�k�t�i�o�n� �k�a�n�n� �n�u�r� �a�u�f� �e�i�n�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �g�l�e�i�c�h�z�e�i�t�i�g� �a�u�s�g�e�f��h�r�t� �w�e�r�d�e�n�.�������YPlease click on a PCB first--this selection operation only works for one board at a time.���PCBSketchWidget���8�B�a�u�t�e�i�l�-�S�i�e�b�d�r�u�c�k� �e�i�n�b�l�e�n�d�e�n�������Show part silkscreen���PCBSketchWidget��$�L�e�i�d�e�r� �a�n�t�w�o�r�t�e�t� �h�t�t�p�:�/�/�f�a�b�.�f�r�i�t�z�i�n�g�.�o�r�g� �n�i�c�h�t� �a�u�f� �d�i�e� �P�r�e�i�s�a�n�f�r�a�g�e�.� �B�i�t�t�e� ��b�e�r�p�r��f�e� �D�e�i�n�e� �I�n�t�e�r�n�e�t�v�e�r�b�i�n�d�u�n�g� �o�d�e�r� �v�e�r�s�u�c�h�e� �e�s� �s�p��t�e�r� �n�o�c�h� �e�i�n�m�a�l�.�������Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later.���PCBSketchWidget��\�K�u�p�f�e�r�f��l�l�u�n�g� �k�o�n�n�t�e� �n�i�c�h�t� �e�r�z�e�u�g�t� �w�e�r�d�e�n�-�-�m��g�l�i�c�h�e�r�w�e�i�s�e� �w�u�r�d�e� �d�a�s� �B�a�u�t�e�i�l� �n�i�c�h�t� �a�u�f� �d�i�e� �e�i�g�e�n�t�l�i�c�h�e� �L�e�i�t�e�r�p�l�a�t�t�e�,� �s�o�n�d�e�r�n� �a�u�f� �e�i�n� �a�n�d�e�r�e�s� �B�a�u�t�e�i�l� �o�d�e�r� �e�i�n�e�n� �D�r�a�h�t� �a�b�g�e�l�e�g�t�.�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget����K�u�p�f�e�r�f��l�l�u�n�g� �k�o�n�n�t�e� �n�i�c�h�t� �e�r�z�e�u�g�t� �w�e�r�d�e�n�-�-�w�a�h�r�s�c�h�e�i�n�l�i�c�h� �w�u�r�d�e� �d�a�s� �B�a�u�t�e�i�l� �n�i�c�h�t� �a�u�f� �d�e�r� �L�e�i�t�e�r�p�l�a�t�t�e� �a�b�g�e�l�e�g�t�.�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget����D�e�i�n�e�m� �E�n�t�w�u�r�f� �f�e�h�l�t� �n�o�c�h� �d�i�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �F��r� �d�i�e� �K�u�p�f�e�r�f��l�l�u�n�g� �m�u�s�s�t� �D�u� �e�r�s�t� �e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e� �(�P�C�B�)� �e�i�n�f��g�e�n�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �d�i�e�s�e� �F�u�n�k�t�i�o�n� �a�u�s�z�u�f��h�r�e�n�.�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �n�o�c�h� �k�e�i�n�e� �L�e�i�t�e�r�p�l�a�t�t�e�!� �B�i�t�t�e� �f��g�e� �e�i�n�e� �h�i�n�z�u�,� �u�m� �d�i�e�s�e� �F�u�n�k�t�i�o�n� �a�u�s�z�u�f��h�r�e�n�.�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget����D�e�i�n� �E�n�t�w�u�r�f� �e�n�t�h��l�t� �b�i�s�h�e�r� �k�e�i�n�e� �P�l�a�t�i�n�e�.� �O�h�n�e� �d�i�e�s�e� �k�a�n�n� �D�e�i�n� �E�n�t�w�u�r�f� �n�i�c�h�t� �p�r�o�d�u�z�i�e�r�t� �w�e�r�d�e�n�.�������[Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.���PCBSketchWidget���d�s�o� �d�a�s�s� �D�u� �d�i�e�s�e� �e�n�t�s�p�r�e�c�h�e�n�d� �a�u�f�r�e�c�h�n�e�n� �s�o�l�l�t�e�s�t�.�������=so you may want to increase the keepout value by that much. ���PCBSketchWidget����H�i�e�r� �k�a�n�n�s�t� �D�u� �d�i�e� �V�e�r�b�i�n�d�e�r�m�e�t�a�d�a�t�e�n� �f��r� �d�a�s� �B�a�u�t�e�i�l� �b�e�a�r�b�e�i�t�e�n�������:This is where you edit the connector metadata for the part���PEConnectorsView����D�u�r�c�h�s�t�e�c�k�e�n������� Through-hole���PEConnectorsView���*�A�n�z�a�h�l� �d�e�r� �V�e�r�b�i�n�d�e�r�:�������number of connectors:���PEConnectorsView���6� � �F�o�r�t�s�e�t�z�e�n� �u�n�d� �s�p�e�i�c�h�e�r�n�?������� Go ahead and save?��� PEMainWindow����&�B�e�a�r�b�e�i�t�e�n�������&Edit��� PEMainWindow����&�E�x�p�o�r�t�i�e�r�e�n�������&Export��� PEMainWindow��� �&�D�a�t�e�i�������&File��� PEMainWindow����<�b�r�/�>�<�b�r�/�>�I�n� �d�e�r� �n��c�h�s�t�e�n� �V�e�r�s�i�o�n� �d�e�s� �B�a�u�t�e�i�l�e�-�E�d�i�t�o�r�s� �w�i�r�d� �d�i�e�s� �k�e�i�n� �P�r�o�b�l�e�m� �m�e�h�r� �s�e�i�n�,� �������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowlEine doppelte "Familien"-Eigenschaft ist nicht erlaubt,A duplicate 'family' property is not allowed PEMainWindownEine doppelte "Varianten"-Eigenschaft ist nicht erlaubt-A duplicate 'variant' property is not allowed PEMainWindow.%1 Verbinder hinzufgenAdd %1 connectors PEMainWindow(Verbinder hinzufgen Add connector PEMainWindow`Interne Verbindung von '%1' nach '%2' hinzufgen)Add internal connection from '%1' to '%2' PEMainWindow$Leer nicht erlaubtBlank not allowed PEMainWindowAbbrechenCancel PEMainWindow"%1 nach %2 ndernChange %1 to %2 PEMainWindow"ndere %1 zu '%2'Change %1 to '%2' PEMainWindow6Alle Verbinder zu %1 ndernChange all connectors to %1 PEMainWindow&Verbinder %1 ndernChange connector %1 PEMainWindow&Beschreibung ndernChange description PEMainWindow(Eigenschaften ndernChange properties PEMainWindow&Schlagwrter ndern Change tags PEMainWindowndern auf %1 Change to %1 PEMainWindow6Schlieen ohne zu speichernClose without saving PEMainWindow8Schlieen ohne zu speichern?Close without saving? PEMainWindowVerbinder Connectors PEMainWindow VerbinderansichtConnectors View PEMainWindow*KonvertierungsproblemConversion problem PEMainWindow`Schaltplan in den 0,1-Zoll-Standard konvertieren&Convert schematic to 0.1 inch standard PEMainWindowKopierproblem Copy problem PEMainWindow Strg+4Ctrl+4 PEMainWindow Strg+5Ctrl+5 PEMainWindow Strg+6Ctrl+6 PEMainWindowxMchtest Du Weiterarbeiten oder Schlieen ohne zu speichern?4Do you want to keep working or close without saving? PEMainWindowWillst du die vorgenommenen nderungen im Bauteil "%1" speichern?:Do you want to save the changes you made in the part "%1"? PEMainWindowpDuplizieren der "Familien"-Eigenschaft ist nicht erlaubt'Duplicate 'family' property not allowed PEMainWindowrDuplizieren der "Varianten"-Eigenschaft ist nicht erlaubt(Duplicate 'variant' property not allowed PEMainWindow(DuplizierungsproblemDuplicate problem PEMainWindowDas Beenden das Bauteile-Editors ist jetzt in Ordnung, solange Du daran denkst, die Belegung spter fertigzustellen.^Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMainWindow DateinamenprfixFilename prefix PEMainWindowSchriftartenFonts PEMainWindow@Fritzing (Neuer) Bauteile-EditorFritzing (New) Parts Editor PEMainWindowFritzing untersttzt derzeit nur OCRA und Droid-Schriftarten--diese haben die Schriftarten in '%1' ersetztkFritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' PEMainWindow SymbolIcon PEMainWindowSymbolansicht Icon View PEMainWindowHBild- & Anschlussflchen-Dateien (%1 %2 %3 %4 %5);;SVG-Dateien (%1);;JPEG-Dateien (%2);;PNG-Dateien (%3);;gEDA-Anschlussflchendateien (%4);;Kicad-Moduldateien (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowBilddateien (%1 %2 %3);;SVG-Dateien (%1);;JPEG-Dateien (%2);;PNG-Dateien (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowInspektor Inspector PEMainWindowZInterne Verbindungen sind sehr durcheinander.(Internal connections are very messed up. PEMainWindowWeiterarbeiten Keep working PEMainWindow EbenenLayers PEMainWindow2Bild zur Ansicht laden...Load image for view... PEMainWindowMachen Sie eine Kopie des Bauteils und speichern sie es im 'Mein Bauteile'-Sortiment9Make a copy of the part and save it in the 'My Parts' Bin PEMainWindow<Nur %1-Ansicht sichtbar machenMake only %1 view visible PEMainWindowBNur diese Ansicht sichtbar machenMake only this view visible PEMainWindowMetadatenMetadata PEMainWindow Metadatenansicht Metadata View PEMainWindow4Anschlusspunkt verschiebenMove terminal point PEMainWindow&Muss eindeutig seinMust be unique PEMainWindowzffne auf dem Desktop den Ordner mit der aktuellen SVG-Datei.@On the desktop, open the folder containing the current svg file. PEMainWindowBild ffnen Open Image PEMainWindowPNG und JPG-Bilder behalten ihre Beschaffenheit als Rastergrafik und werden beim Skalieren nicht gut aussehen--TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindowBauteile-Editor Parts Editor PEMainWindowBitte exportiere die SVG-Datei mit dieser Einstellung erneut und versuche sie nochmal zu laden.HPlease re-export the SVG file using that setting, and try loading again. PEMainWindow*Verbinder %1 umsetzenRelocate connector %1 PEMainWindow,%1 Verbinder entfernenRemove %1 connectors PEMainWindow8Interne Verbindung entfernenRemove Internal Connection PEMainWindow&Verbinder entfernenRemove connector PEMainWindowJInterne Verbindung aus '%1' entfernen$Remove internal connection from '%1' PEMainWindowBLeiterplattenbild wiederverwendenReuse PCB image PEMainWindowBSteckplatinenbild wiederverwendenReuse breadboard image PEMainWindow4Schaltplan wiederverwendenReuse schematic image PEMainWindownDas Leiterplattenbild in dieser Ansicht wiederverwenden Reuse the PCB image in this view PEMainWindowfSteckplatinenbild in dieser Ansicht wiederverwenden'Reuse the breadboard image in this view PEMainWindowXSchaltplan in dieser Ansicht wiederverwenden&Reuse the schematic image in this view PEMainWindowSVG-Problem SVG problem PEMainWindowSpeichernSave PEMainWindow"%1" speichern Save "%1" PEMainWindow6Als neues Bauteil speichernSave as new part PEMainWindowBeim Speichern dieses Bauteils wird im Entwurf eine nderung vorgenommen werden, welche nicht rckgngig gemacht werden kann.HSaving this part will make a change to the sketch that cannot be undone. PEMainWindow Beim Speichern dieses Bauteils wird in diesen Entwrfen eine nderung vorgenommen werden, welche nicht rckgngig gemacht werden kann.LSaving this part will make a change to these sketches that cannot be undone. PEMainWindowSiehe <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">diese Erklrung</a>.ySee this explanation. PEMainWindow$Verbinder anzeigenShow Connectors PEMainWindowSymbol anzeigen Show Icon PEMainWindow$Metadaten anzeigen Show Metadata PEMainWindow$Im Ordner anzeigenShow in Folder PEMainWindowdVerbindermetadaten in einer Listenansicht anzeigen*Show the connector metadata in a list view PEMainWindow4Die Symbolansicht anzeigenShow the icon view PEMainWindow:Die Metadatenansicht anzeigenShow the metadata view PEMainWindow0EntwurfsnderungswarnungSketch Change Warning PEMainWindowSo knnte die Bearbeitung ein ungltiges Bild von der Leiterplattenansicht erzeugen0So editing may produce an invalid PCB view image PEMainWindow`Die "Familien"-Eigenschaft darf nicht leer sein.'The 'family' property can not be blank. PEMainWindowDie SVG-Datei '%1' wurde anscheinend aus CorelDRAW ohne die 'Prsentationsattribute'-Einstellung exportiert. nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindowDer geffnete Entworf '%1' verwendet das Teil, das Sie bearbeiten. 4The open sketch '%1' uses the part you are editing.  PEMainWindow*Die offenen Entwrfe The open sketches  PEMainWindowDas Bauteil wird nur in dieser Ansicht und in der Symbolansicht sichtbar sein8The part will only be visible in this view and icon view PEMainWindowNDer Wert von '%1' darf nicht leer sein.#The value of '%1' can not be blank. PEMainWindowXEs sind keine Kupferebenen bestimmt in: %1. +There are no copper layers defined in: %1.  PEMainWindowNEine letzte Bearbeitung steht noch aus.%There is one last edit still pending. PEMainWindowfDieses Bauteil kann nicht gespeichert werden als: #This part can not be saved as-is:  PEMainWindowTDieses Bauteil hat %n unbelegte Verbinder 'This part has %n unassigned connectors  PEMainWindowLDieses Bauteil hat biegbare Beinchen. This part has bendable legs.  PEMainWindowtDiese Version des Bauteile-Editors untersttzt noch keine Bearbeitung von biegbaren Beinchen und die Beinchen werden in der Steckplatinenansicht mglicherweise nicht richtig angezeigt . This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindowDiese Version des neuen Bauteile-Editors kann mit separaten Kupfer0 und Kupfer1-Ebenen in '%1' nicht umgehen. dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindowDiese Warnung wird in dieser Sitzung von Fritzing nicht wiederholt werden=This warning will not be repeated in this session of Fritzing PEMainWindowNeuer Verbinder konnte nicht erstellt werden--mglicherweise mssen Sie von vorne beginnen.;Unable to create new connector--you may have to start over. PEMainWindow.Konnte '%1' nicht ladenUnable to load '%1' PEMainWindow'%1' kann nicht geladen werden. Bitte schlieen Sie den Bauteile-Editor ohne zu speichern und versuchen Sie es erneut.PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindowLFZP aus %1 konnte nicht geladen werdenUnable to load fzp from %1 PEMainWindowTBilddatei '%1' konnte nicht geladen werdenUnable to load image file '%1' PEMainWindow`Bilddatei '%1' konnte nicht geladen werden: %2$Unable to load image file '%1': %2 PEMainWindownEine lokale Kopie von '%1' konnte nicht erstellt werden$Unable to make a local copy of: '%1' PEMainWindow@'%1' konnte nicht geparst werdenUnable to parse '%1' PEMainWindown'%1': %2 Zeile:%3 Spalte:%4 konnte nicht geparst werden*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindowZFZP-Datei von %1 konnte nicht geparst werdenUnable to parse fzp file %1 PEMainWindowXSVG konnte nicht nach %1 geschrieben werdenUnable to write svg to %1 PEMainWindowBis alle Verbinder SVG-Elementen zugeordnet sind, wird das Bauteil nicht korrekt funktionieren.UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindow\Verwendung von PNG und JPG ist nicht empfohlenUse of PNG and JPG discouraged PEMainWindowVariante '%1' ist in Gebrauch. Der Variantenname muss eindeutig sein.8Variant '%1' is in use. The variant name must be unique. PEMainWindowDu kannst ein PNG- oder JPG-Bild zum Erstellen Deines Bauteils verwenden, aber es ist besser, eine SVG zu verwenden.WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindowDeine nderungen gehen verloren, wenn sie nicht gespeichert werden.1Your changes will be lost if you don't save them. PEMainWindow&ber %n Ansichten. across %n views.  PEMainWindowund '%1'  and '%1'  PEMainWindowJkeine Anschlussflchen gefunden in %1no footprints found in %1 PEMainWindow@Keine Schaltplne gefunden in %1no schematics found in %1 PEMainWindow$Schematischer Teilschematic part PEMainWindowdeshalb ist es fr Fritzing-Bauteile am besten, wenn PNG und JPG nur als Platzhalter verwendet werden.Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindow&unbenannte Beuteile untitled part PEMainWindowErstellerAuthorPEMetadataView DatumDatePEMetadataViewBeschreibung DescriptionPEMetadataViewFamilieFamilyPEMetadataViewBezeichnungLabelPEMetadataViewEigenschaften PropertiesPEMetadataView`Den Standard-Bauteilbezeichnungsprfix festlegen!Set the default part label prefixPEMetadataView<Den Bauteilersteller festlegenSet the part's authorPEMetadataView4Das Bauteildatum festlegenSet the part's datePEMetadataViewDie Bauteilbeschreibung festlegen--Du kannst einfaches HTML verwenden (wie von Qt Rich Text definiert)RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataViewDie Bauteilfamilie festlegen--mit welchen anderen Bauteilen steht dieses Bauteil in Verbindung?Set the part's family--what other parts is this part related toPEMetadataViewDDie Bauteileigenschaften festlegenSet the part's propertiesPEMetadataViewBDie Bauteilschlagwrter festlegenSet the part's tagsPEMetadataView<Die Bauteilbenennung festlegenSet the part's titlePEMetadataViewDie Bauteil-URL festlegen, wenn es auf einer Webseite beschrieben ist3Set the part's url if it is described on a web pagePEMetadataViewDie Bauteilvariante festlegen--dies macht es einzigartig von allen anderen Bauteilen in der gleichen FamilieTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewSchlagwrterTagsPEMetadataViewdHier bearbeitest Du die Metadaten des Bauteils ...4This is where you edit the metadata for the part ...PEMetadataViewBenennungTitlePEMetadataViewVarianteVariantPEMetadataView Hhe:height: PESvgViewBreite:width: PESvgViewV<font color='black'>Ziehen aktiviert</font>+Dragging enabled PEToolViewX<font color='gray'>Ziehen deaktiviert</font>+Dragging disabled PEToolView MitteCenter PEToolViewVerbinder %1 Connector %1 PEToolViewVerbinderliste (ein Hkchen bedeutet, dass die Grafik ausgewhlt wurde);Connector List (a checkmark means the graphic was selected) PEToolView$Ziehen deaktiviertDragging disabled PEToolViewOE PEToolViewXndert die X-Koordinate des Anschlusspunktes/Modifies the x-coordinate of the terminal point PEToolViewXndert die Y-Koordinate des Anschlusspunktes/Modifies the y-coordinate of the terminal point PEToolView Grafik auswhlenSelect graphic PEToolView<Interne Verbindungen festlegenSet Internal Connections PEToolViewfLegt den Anschlusspunkt des Verbinders auf %1 fest.*Sets the connector's terminal point to %1. PEToolView Mittecenter PEToolViewOsteast PEToolViewNordnorth PEToolViewSdsouth PEToolViewWestwest PEToolView MittecenterPadverbinden mit connect toPadOsteastPadNordnorthPadFormshapePadSdsouthPadWestwestPad&Kontakte bearbeitenEdit Pin Labels PaletteItemLochdurchmesser Hole Diameter PaletteItemNicht bereinstimmende Bezeichnungen. Es wurde nichts gespeichert.#Label mismatch. Nothing was saved. PaletteItemRingdickeRing Thickness PaletteItemFortfahren nicht mglich; Bauteilverbinder haben keine Standardkennungen.;Unable to proceed; part connectors do no have standard IDs. PaletteItemFortfahren nicht mglich; Oberkantenansicht konnte nicht gefunden werden.1Unable to proceed; unable to find top level view. PaletteItem0Erweiterte Einstellungenadvanced settings PaletteItemLochgre hole size PaletteItemWerte anzeigenDisplay Values PartLabel*Beschriftung anzeigenDisplay the text of the label PartLabel@Wert der Eigenschaft %1 anzeigen Display the value of property %1 PartLabelBearbeitenEdit PartLabel.Beschriftung bearbeitenEdit label text PartLabel&Horizontal umdrehenFlip Horizontal PartLabel"Vertikal umdrehen Flip Vertical PartLabel@Beschriftung horizontal umdrehenFlip label horizontally PartLabel<Beschriftung vertikal umdrehenFlip label vertically PartLabelUmdrehen/Drehen Flip/Rotate PartLabelSchriftgre Font Size PartLabelAusblendenHide PartLabel0Beschriftung ausblendenHide part label PartLabelBeschriftung Label text PartLabelBeschriftung: Label text: PartLabelGroLarge PartLabel MittelMedium PartLabelNUm 135 im Uhrzeigersinn drehen {135?}Rotate 135� Clockwise PartLabelZUm 45 gegen den Uhrzeigersinn drehen {135?}Rotate 135� Counter Clockwise PartLabel,Um 180 drehen {180?} Rotate 180� PartLabelLUm 135 im Uhrzeigersinn drehen {45?}Rotate 45� Clockwise PartLabelXUm 45 gegen den Uhrzeigersinn drehen {45?}Rotate 45� Counter Clockwise PartLabelLUm 135 im Uhrzeigersinn drehen {90?}Rotate 90� Clockwise PartLabelXUm 45 gegen den Uhrzeigersinn drehen {90?}Rotate 90� Counter Clockwise PartLabelZAuswahl um 90 gegen den Uhrzeigersinn drehen5Rotate current selection 90 degrees counter clockwise PartLabelXBeschriftung um 135 im Uhrzeigersinn drehen)Rotate the label by 135 degrees clockwise PartLabelfBeschriftung um 135 gegen den Uhrzeigersinn drehen1Rotate the label by 135 degrees counter clockwise PartLabel6Beschriftung um 180 drehenRotate the label by 180 degrees PartLabelVBeschriftung um 45 im Uhrzeigersinn drehen(Rotate the label by 45 degrees clockwise PartLabeldBeschriftung um 45 gegen den Uhrzeigersinn drehen0Rotate the label by 45 degrees counter clockwise PartLabelVBeschriftung um 90 im Uhrzeigersinn drehen(Rotate the label by 90 degrees clockwise PartLabel2Groe Schriftgre whlenSet font size to large PartLabel8Mittlere Schriftgre whlenSet font size to medium PartLabel4Kleine Schriftgre whlenSet font size to small PartLabel>Sehr kleine Schriftgre whlenSet font size to tiny PartLabel4Beschriftung fr %1 ndernSet label for %1 PartLabel KleinSmall PartLabelSehr kleinTiny PartLabel0Zum Sortiment hinzufgen Add to binPartsBinPaletteWidgetAbbrechenCancelPartsBinPaletteWidgetTDie Datei %1 konnte nicht gefunden werden.Cannot find file %1.PartsBinPaletteWidgetZDie Datei %1 konnte nicht gelesen werden: %2.Cannot read file %1: %2.PartsBinPaletteWidget*Symbolfarbe ndern...Change icon color...PartsBinPaletteWidgetPSymbolfarbe fr dieses Sortiment ndern.*Change the color of the icon for this bin.PartsBinPaletteWidget Strg+DCtrl+DPartsBinPaletteWidgetzMchtest Du das ausgewhlte Bauteil zum Sortiment hinzufgen?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetnMchtest Du die nderungen am Sortiment "%1" speichern?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetNicht speichern Don't SavePartsBinPaletteWidget0Fritzing-Sortiment (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetLade... Loading...PartsBinPaletteWidgetSpeichernSavePartsBinPaletteWidget0Sortiment "%1" speichern Save bin "%1"PartsBinPaletteWidgetDWhle eine Farbe fr dieses SymbolSelect a color for this iconPartsBinPaletteWidget(Dateinamen auswhlenSpecify a file namePartsBinPaletteWidget*Unbenanntes Sortiment Untitled BinPartsBinPaletteWidgetDeine nderungen gehen verloren, falls sie nicht gespeichert werden.1Your changes will be lost if you don't save them.PartsBinPaletteWidget&Lade Sortiment '%1'loading bin '%1'PartsBinPaletteWidgetAbbrechenCancel Perfboard4Warnung zur SystemleistungPerformance Warning PerfboardBBei Lochrasterplatinen mit mehr als 2000 Lchern kann die Systemleistung stark leiden. Mchtest Du fortfahren? Hinweis: Diese Warnung wird nur einmal angezeigt.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. PerfboardFortfahren Set new size PerfboardSpaltencolumns Perfboard Zeilenrows Perfboard$Leiterplattengreset board size Perfboard Gresize Perfboard<<p><h2>Kontakt-Editor</h2></p>

    Pin Label Editor

    PinLabelDialog<p>Klicke auf eine Bezeichnung neben einer Kontaktnummer, um diesen Kontakt umzubenennen.<

    Click on a label next to a pin number to rename that pin.PinLabelDialogAbbrechenCancelPinLabelDialog WiederherstellenRedoPinLabelDialogSpeichernSavePinLabelDialogRckgngigUndoPinLabelDialogDu kannst die Tab-Taste verwenden, um Dich der Reihe nach durch die Bezeichnungen zu bewegen.</p>@You can use the tab key to move through the labels in order.

    PinLabelDialogStarte %1 %2 Running %1 %2PlatformArduinoStarte %1 %2 Running %1 %2PlatformPicaxe%1%1 (click to change...) PrefsDialog,Automatische SicherungAutosave PrefsDialogSichern alle:Autosave every: PrefsDialogAbbrechenCancel PrefsDialog0Mausrad-Verhalten ndernChange Wheel Behavior PrefsDialog4Einstellungen zurcksetzenClear Settings PrefsDialogCode-Ansicht Code View PrefsDialog FarbenColors PrefsDialogCmdCommand PrefsDialogVerbundenConnected Highlight PrefsDialogStrgControl PrefsDialog4Gebogene vs. gerade DrhteCurvy vs. straight wires PrefsDialog8Gebogene Drhte und BeinchenCurvy wires and legs PrefsDialogAllgemeinGeneral PrefsDialogSpracheLanguage PrefsDialog Pfad: Location: PrefsDialog,Verhalten des MausradsMouse Wheel Behavior PrefsDialog.Plattform-UntersttzungPlatform Support PrefsDialoghWhle einen Programmierer (ausfhrbare Datei) fr %1'Select a programmer (executable) for %1 PrefsDialog4Dies ist die Standardeinstellung. Du kannst immer das jeweils andere Verhalten erzielen, wenn Du beim Ziehen die "Strg"-Taste (Mac: Cmd) gedrckt hltst. This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialogNicht verbundenUnconnected Highlight PrefsDialogWenn Du mit der Maus an einem Draht oder Bauteilbeinchen ziehst, mchtest Du die Biegung ndern oder einen Knick hinzufgen?When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialogrDu bentigst <a href='%1'>%2</a> (Version %3 oder neuer).EYou need to have %2 (version %3 or newer) installed. PrefsDialogMinutenminutes PrefsDialogMausrad = vertikaler Bildlauf Mausrad + Umschalt-Taste = horizontaler Bildlauf Mausrad + Alt- oder %1-Taste = ZoomFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialogMausrad = Zoom Mausrad + Alt- oder %1-Taste = vertikaler Bildlauf Mausrad + Alt + Umschalt-Taste = horizontaler BildlaufFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialoghMchtest Du wirklich "%1" aus dem Entwurf entfernen?5Are you sure you want to remove "%1" from the sketch? ProgramTabrFritzing kann '%1' nicht finden, bitte mache es ausfindig1Fritzing is unable to find '%1', please locate it ProgramTabNeuNew ProgramTabEs wurde noch kein Programmierer fr %1 angegeben. Gehen Sie zu Einstellungen > Code-Ansicht, um diesen zu konfigurieren.LNo uploader for %1 specified. Go to Preferences > Code View to configure it. ProgramTab ffnenOpen ProgramTabPlattformPlatform ProgramTab"%1" entfernen? Remove "%1"? ProgramTabSpeichernSave ProgramTab.Programmdatei auswhlenSelect a program file to load ProgramTab"Serieller MonitorSerial Monitor ProgramTabHochladenUpload ProgramTab\Hochladen fehlgeschlagen mit Fehlercode %1, %2#Upload failed with exit code %1, %2 ProgramTab$Hochladen beendet.Upload finished. ProgramTabProgrammierer ist konfiguriert, aber konnte hier nicht gefunden werden: %1(Uploader configured, but not found at %1 ProgramTabWhrend das Einlesen und Bearbeiten von %1-Programmierdateien mglich ist, ist es momentan leider noch nicht mglich, dieses Programm direkt in Fritzing zu kompilieren oder auf einen Mikrocontroller hochzuladen.While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. ProgramTab&Kopieren&Copy ProgramWindow&Ausschneiden&Cut ProgramWindow&Bearbeiten&Edit ProgramWindow(Code &importieren...&Import Code... ProgramWindow&Neuer Tab&New Tab ProgramWindow&Einfgen&Paste ProgramWindow"&Einstellungen...&Preferences... ProgramWindowTab um&benennen &Rename Tab ProgramWindowTab &speichern &Save Tab ProgramWindow &Alles auswhlen &Select All ProgramWindow&Ansicht&View ProgramWindowAlt+Strg+B Alt+Ctrl+R ProgramWindowTab schlieen Close Tab ProgramWindowProgrammcode Code Window ProgramWindow"Programmcode - %1Code Window - %1 ProgramWindow Auswahl kopierenCopy selection ProgramWindow0Neues Code-Tab erstellenCreate a new program tab ProgramWindow Strg+MCtrl+M ProgramWindow Strg+UCtrl+U ProgramWindow(Auswahl ausschneiden Cut selection ProgramWindow Die Datei '%1' wurde aus der .fzz-Datei wiederhergestellt. Speicher eine lokale Kopie, um sie mit einem externen Editor zu bearbeiten.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindowDie Datei '%1' wurde aus der .fzz-Datei wiederhergestellt. Die lokale Kopie konnte nicht gefunden werden.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindowPImportiere Code aus einer externen DateiImport a program from a file ProgramWindowBSerielle Kommunikation berwachen%Monitor the serial port communication ProgramWindow,Keine Boards verfgbarNo boards available ProgramWindowNInhalte aus der Zwischenablage einfgenPaste clipboard contents ProgramWindowPlattformPlatform ProgramWindow WiederherstellenRedo ProgramWindowZEntfernt den aktuelle Code von diesem Entwurf.Remove the current program tab from the sketch ProgramWindow:Aktuellen Code-Tab umbenennenRename the current program tab ProgramWindow8Aktuellen Code-Tab speichernSave the current program tab ProgramWindow.Gesamten Text auswhlenSelect all text ProgramWindow"Serieller MonitorSerial Monitor ProgramWindowHZeige Informationen ber Fritzing an Show the application's about box ProgramWindowRckgngigUndo ProgramWindowHochladenUpload ProgramWindow~Ldt den aktuellen Code auf einen angeschlossen Mikrocontroller1Upload the current program onto a microcontroller ProgramWindow%1-Ebene%1 LayerQObjectD%1-Ebenenexport ist leer (Fall 2)."%1 layer export is empty (case 2).QObject2%1-Ebenenexport ist leer.%1 layer export is empty.QObjectf%1-Ebene: Konnte nicht nach '%2' gespeichert werden %1 layer: unable to save to '%2'QObjectn%1 Fehler beim Exportieren der Ltstoppmasken-Datei (2)%1 mask export failure (2)QObject%1 Drhte wurden von ihrer ursprnglichen Position in %2 bewegt./%1 wires moved from their saved position in %2.QObjectx%2 ... %1 Drhte von ihrer gespeicherten Position verschoben/%2 ... %1 wires moved from their saved positionQObject(<b>Beschreibung:</b>Description:QObject&<b>Bezeichnung:</b> Name:QObject<b>Kennung:</b> id:QObject<b>Typ:</b> type:QObject0Autorouter-EinstellungenAutorouter SettingsQObject BasisBasicQObjectLeiterplattenBoardQObjectSteckplatinen BreadboardQObject(SteckplatinenansichtBreadboard ViewQObject>Schrittweise nach vorne bringen Bring forwardQObject$Nach vorne bringenBring to frontQObjectAutorouten kann nicht durchgefhrt werden: Keine oder mehrere Leiterplatten gefunden5Cannot autoroute: no board (or multiple boards) foundQObjectZDie Datei %1 konnte nicht gelesen werden: %2.Cannot read file %1: %2.QObjectpTemporre Datei kann nicht geschrieben werden: %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject2ndere Beinchen von %1,%2Change leg of %1,%2QObject8Nach Aktualisierungen suchenCheck for updatesQObject4Einstellungen zurcksetzenClear SettingsQObjectzAlle Einstellungen zurcksetzen und dieses Fenster schlieen.;Clear all saved settings and close this dialog immediately.QObjectDHervorhebungsfarbe fr "Verbunden"Connected highlight colorQObjectVerbindung ConnectionQObject6Via in Biegepunkt umwandelnConvert Via to BendpointQObject In Via umwandelnConvert to ViaQObjectKupfer unten Copper BottomQObject8Kupfern unten (Leiterbahnen)Copper Bottom TraceQObject0Kupferfllung UnterseiteCopper Fill BottomQObject,Kuperfllung OberseiteCopper Fill TopQObjectKupfer oben Copper TopQObject4Kupfer oben (Leiterbahnen)Copper Top TraceQObject Kopiere Datei %1Copying file %1QObjectLink bearbeiten Edit linkQObjectFFehler beim lesen der Datei %1: %2.Error reading file %1: %2.QObjectDatei %1 ist bereits vorhanden: Sie kann nicht berschrieben werden/File %1 already exists: it won't be overwrittenQObject&Dateifortschritt...File Progress...QObject RahmenFrameQObject^Fritzing kann das Bauteilsortiment nicht ffnen"Fritzing cannot load the parts binQObjectFritzing kann die Ausschnitte in dieser Platine nicht verarbeiten. DFritzing is unable to process the cutouts in this custom PCB shape. QObjectFritzing kann Ausschnitte nur korrekt erkennen, wenn sie als "Subtraktion" der Grundform in Deinem Zeichenprogramm erstellt wurden.}Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.QObjectHalbleiterICsQObject SymbolIconQObjectSymbolansicht Icon ViewQObjectEingabeInputQObject(Interne VerbindungenInternal ConnectionsQObjectDraht verbinden Join WireQObjectMikrocontrollerMicrocontrollerQObjectN/VN/AQObjectjKeine Verbindungen (auf der Leiterplatte) zum Routen.%No connections (on the PCB) to route.QObject<Keine Verbindungen zum Routen.No connections to route.QObject0Keine Bauteile gefunden.No parts found.QObjectNotizenNotesQObjectUps!Oops!QObject AndereOtherQObjectAusgabeOutputQObject(LeiterplattenansichtPCB ViewQObjectLtflchePadQObjectDer XML-Code fr der Bauteil (1) %4 enthlt einen Fehler bei Zeile %1, Spalte %2:%3,Parse error (1) at line %1, column %2: %3 %4QObjectDer XML-Code fr der Teil (2) %4 enthlt einen Fehler bei Zeile %1, Spalte %2:%3,Parse error (2) at line %1, column %2: %3 %4QObjectBauteilPartQObjectBauteil %1 '%2' Part %1 '%2'QObjectBauteil-Abbild Part ImageQObject*Bauteilbeschriftungen Part LabelsQObjectLBauteil bereits im Sortiment vorhandenPart already in binQObjectBauteilePartsQObject>Bauteile-Ordner nicht gefunden.Parts folder not found.QObject4Kontaktbezeichnungs-EditorPin Label EditorQObjectEine neue Spracheinstellung wird erst nach einem Neustart von Fritzing wirksam.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectEnergiePowerQObjectEinstellungen PreferencesQObjectLuftlinieRatsnestQObjectLuftlinienRatsnest wiresQObject LinealRulersQObject"SchaltplanansichtSchematic ViewQObject%1 auswhlen Select %1QObject$Alles auswhlen %1 Select all %1QObject\Alle "Nicht Autorouten"-Leiterbahnen auswhlen#Select all 'Don't autoroute' tracesQObjectVAlle "Autorutebaren" Leiterbahnen auswhlenSelect all autorouteable tracesQObjectDAlle gesperrten Bauteile auswhlenSelect locked partsQObject8Veraltete Bauteile auswhlenSelect outdated partsQObject>Schrittweise nach hinten senden Send backwardQObjectSensorenSensorsQObjectRastergre Set Grid SizeQObject(Alles festlegen auf: Set all to:QObject8Beschreibung des Anschlusses Set the connectors's descriptionQObjectHBezeichnung des Verbinders festlegenSet the connectors's titleQObjectSiebdruck untenSilkscreen BottomQObjectLSiebdruck unten (Bauteilbezeichnungen)Silkscreen Bottom (Part Labels)QObjectSiebdruck obenSilkscreen TopQObjectJSiebdruck oben (Beuteilbezeichnungen)Silkscreen Top (Part Labels)QObjectSorry, Fritzing kann noch nicht Pins und Pads in einer Datei handhaben (in %1 in %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectSorry, Fritzing kann noch nicht Pins und Pads in einer Datei handhaben (in %1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectZSorry, kann mit Pad-Typ %1 noch nicht umgehenSorry, can't handle pad type %1QObjectJSorry, wir habben noch ein kleines Problem mit dem ndern von Eigenschaften. Versuche, Fritzing neu zu starten. Falls das Problem bestehen bleibt, wende Dich an uns.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectDraht aufteilen Split WireQObjectTDie Datei %1 ist keine Fritzing Datei (2).'The file %1 is not a Fritzing file (2).QObjectTDie Datei %1 ist keine Fritzing Datei (3).'The file %1 is not a Fritzing file (3).QObjectTDie Datei %1 ist keine Fritzing-Datei (4).'The file %1 is not a Fritzing file (4).QObjectDie Datei '%1' ist schreibgeschtzt; bitte benutze einen anderen Dateinamen.Falscher Ebenenmasken-Parameterbad layer mask parameterQObject2Anzahl Pads nicht korrektbad pad argument countQObject2Anzahl Pins nicht korrektbad pin argument countQObjectFFehlerhafte Schaltplandefinition %1bad schematic definition %1QObjectSteckplatinebbQObject(Steckplatinenansichtbreadboard viewQObject"Kupfer-Ebene(n), copper layer(s), QObjectFFehler beim Exportieren des Bohrensdrill export failureQObjectHBohrung: Fehlende Ellipsen-Parameterdrill missing ellipse paramsQObject6Bohrung: Fehlende Parameterdrill missing paramsQObjectHBohrung: Abstand nicht implementiertdrill offset not implementedQObjectDdie exportierte Bohrdatei ist leerexported drill file is emptyQObjectPdie exportierte Masken-Ebene %1 ist leerexported mask layer %1 is emptyQObjectZdie exportierte Ltstoppmasken-Ebene ist leer"exported paste mask layer is emptyQObjectNFehler in SVG-Konvertierung 1: %1 %2 %3%failure in svg conversion 1: %1 %2 %3QObjectNFehler in SVG-Konvertierung 2: %1 %2 %3%failure in svg conversion 2: %1 %2 %3QObjectDateienfilesQObject^Footprint %1 konnte nicht gefunden werden in %2footprint %1 not found in %2QObjectSymbolansicht icon viewQObject`Fehler beim Exportieren der Ltstoppmasken-Dateimask export failureQObject2Ltstoppmasken-Ebene(n), mask layer(s), QObjectpSorry, kann noch nicht mit nicht-runden Lchern umgehen."non-circular holes not implementedQObjectvSorry, kann noch nicht mit nicht-kupfernen Lchern umgehen. non-copper holes not implementedQObject,Umriss/Kontur ist leeroutline is emptyQObject.Pad: Fehlende Attributepad missing attributesQObject$Pad: Bohrung fehltpad missing drillQObject,Pad: Fehlende Positionpad missing positionQObject$Pad: Fehlende Formpad missing shapeQObject8Pad-Form: Fehlende Parameterpad shape missing paramsQObject8Pad-Form: Gre ist ungltigpad shape size is invalidQObject(Parsing-Fehler in %1parse failure in %1QObject2Ltstoppmasken-Ebene(n), paste mask layer(s), QObjectLeiterplattepcbQObject(Leiterplattenansichtpcb viewQObject8Position: Fehlende Parameterposition missing paramsQObjectSchaltplanschemQObjectHSymbol %1 endet unerwartet (1) in %2(schematic %1 unexpectedly ends (1) in %2QObjectHSymbol %1 endet unerwartet (2) in %2(schematic %1 unexpectedly ends (2) in %2QObjectHSymbol %1 endet unerwartet (3) in %2(schematic %1 unexpectedly ends (3) in %2QObjectXSymbol %1 konnte nicht in %2 gefunden werden!schematic part %1 not found in %2QObject"Schaltplanansichtschematic viewQObject`Form: Sorry, kann noch nicht mit "Delta" umgehenshape delta not implementedQObjectLFehler beim Exportieren des Siebdruckssilk export failureQObjectBSiebdruckebene-Export %1 ist leersilk layer %1 export is emptyQObject(Siebdruck-Ebene(n), silkscreen layer(s), QObject*Umriss/Kontur-Ebene, the board outline layer, QObjectbForm: Sorry, kann noch nicht mit "Trapez" umgehen trapezoidal pads not implementedQObjectT'%1 konnte nicht nach '%2' kopiert werden.!unable to copy file '%1' to '%2'.QObject^Sorry, kann noch nicht mit Pad-Form %1 umgehen.unable to handle pad shape %1QObject>%1 konnte nicht geffnet werdenunable to open %1QObjectH%1 konnte nicht interpretiert werdenunable to parse %1QObject,Unerwartetes Dateiendeunexpected end of fileQObjectdUnerwartetes Dateiende in Footprint %1 in Datei %21unexpected end of file in footprint %1 in file %2QObjectHUnerwartetes Format (1) in %1 aus %2#unexpected format (1) in %1 from %2QObjectStrgCtrl QShortcutUmschaltShift QShortcut KopienCopies QuoteDialogFr weitere Informationen ber Preise siehe <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>.rFor more information on pricing see http://fab.fritzing.org/pricing. QuoteDialog<Fritzing Fab HerstellungspreisFritzing Fab Quote QuoteDialogXBestelle Deine Leiterplatte bei Fritzing Fab Order your PCB from Fritzing Fab QuoteDialogXBeachte dass dieser Preis exklusive Versand,6Please note that prices do not include shipping,
     QuoteDialog PreisPrice QuoteDialog"Preis pro PlatinePrice per board QuoteDialogPNutze den Vorteil unseres Mengenrabatts:(Take advantage of our quantity discount: QuoteDialogTDie Gesamtgre Deiner %n Leiterplatte istVDie Gesamtgre Deiner %n Leiterplatten ist1The total area of the %n PCB(s) in this sketch is QuoteDialogProduziere eine Leiterplatte aus Deinem Entwurf mit Hilfe von Fritzing Fab.<br/>9Use Fritzing Fab to produce a PCB from your sketch.
     QuoteDialog(Besuche Fritzing FabVisit Fritzing Fab QuoteDialogBSteuern, und Prfgebhr ist.<br/>5possible additional taxes, or the checking fee.
     QuoteDialog&Ignorieren&IgnoreRecoveryDialog"&Wiederherstellen&RecoverRecoveryDialog<p><b>Fritzing ist abgestrzt, aber einige Deiner letzten nderungen an den folgenden Entwrfen knnten wiederhergestellt werden.</b></p><p> Das Datum und die Uhrzeit der letzten automatischen Sicherung werden hier angezeigt. Falls die Datei einmal gespeichert wurde, wird auch dieses Datum zum Vergleich angezeigt. Du kannst nach der Wiederherstellung noch whlen, ob Du die letzte gespeicherte Datei berschreiben willst.</p><p><b>Whle alle Dateien, die Du von der Sicherung wiederherstellen mchtest:</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialog DateiFileRecoveryDialog Letzte Sicherung Last backupRecoveryDialog&Zuletzt gespeichert Last savedRecoveryDialog,Datei nicht gespeicherfile not savedRecoveryDialogWiderstandResistorResistorDu kannst entweder einen Widerstandswert eingeben oder einen aus der Dropdown-Liste auswhlen. Format nnn.dP, wobei P einer von 'umkMG' isttYou can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'ResistorWiderstand resistanceResistorZurcksetzenRevertResizableBoard"benutzerdefiniertcustomResizableBoardHhe (mm) height(mm)ResizableBoardHhe: %1 mm height: %1mmResizableBoard Seitenverhltniskeep aspect ratioResizableBoardFormshapeResizableBoard GresizeResizableBoardBreite (mm) width(mm)ResizableBoardBreite: %1 mm width: %1mmResizableBoard BreitewidthRulerbLaden von '%1', %2 Zeile:%3 Sp.:%4 fehlgeschlagen&Failed loading '%1', %2 line:%3 col:%4S2S~Schaltplan '%1', %2 Zeile:%3 Sp.:%4 konnte nicht geladen werden0Failed loading schematic '%1', %2 line:%3 col:%4S2SdFehlender Verbinder %1 in '%2' Schaltplan von '%3'.Missing connector %1 in '%2' schematic of '%3'S2SpSchaltplan '%1' verwendet bereits den 0,1-Zoll-Standard.5Schematic '%1' is already using the 0.1inch standard.S2SDSchaltplan fr '%1' nicht gefundenSchematic not found for '%1'S2ShSchaltplan '%1' fr '%2' konnte nicht geladen werden&Unable to load schematic '%1' for '%2'S2ShSchaltplan '%1' fr '%2' konnte nicht geladen werden'Uunable to load schematic '%1' for '%2'S2S DatumDateSchematicFrameDateinameFilenameSchematicFrameProjektProjectSchematicFrameRevisionRevSchematicFrame BlattSheetSchematicFrame DatumdateSchematicFramevonofSchematicFrameFormshapeSchematicFrame BlattsheetSchematicFrameLBeschriftung von '%1' nach '%2' ndernChange label from %1 to %2SchematicSketchWidget<Spannung von %1 nach %2 ndernChange voltage from %1 to %2SchematicSketchWidget%1-Farbe... %1 Color...SetColorDialogAbbrechenCancelSetColorDialog&%1-Farbe auswhlen:Choose %1 color:SetColorDialog&Aktuelle Farbe (%1)Current color (%1)SetColorDialog$Standard-Fabe (%1)Default color (%1)SetColorDialog^Diese Farbe als Standard-Farbe fr %1 verwendenMake this the default %1 colorSetColorDialog4Eigene %1 -Farbe auswhlenPick custom %1 colorSetColorDialog,Eigene Farbe whlen...Pick custom color ...SetColorDialogZurcksetzenReset to defaultSetColorDialog%1 Beachte: Du kannst diese Anzeige auch aufrufen, indem Du den Routing-Status in der Statusleiste unten anklickst und gedrckt hltst.i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2 Elemente %1 %2 items SketchWidget&%1 Bezeichnung '%2' %1 label '%2' SketchWidget%1 hinzufgenAdd %1 SketchWidget,%1 Bauteile hinzufgen Add %1 parts SketchWidget ndereChange SketchWidget<Farbe %1 von %2 nach %3 ndernChange %1 color from %2 to %3 SketchWidget0%1 von %2 nach %3 ndernChange %1 from %2 to %3 SketchWidgetLBeschriftung von '%1' nach '%2' ndernChange %1 label to '%2' SketchWidget>Breite %1 von %2 nach %3 ndernChange %1 width from %2 to %3 SketchWidgetTWert des Widerstands von %1 nach %2 ndernChange Resistance from %1 to %2 SketchWidgetFFarbe von %1 Drhten nach %2 ndernChange color of %1 wires to %2 SketchWidget4Bild von %1 nach %2 ndernChange image from %1 to %2 SketchWidgetBBeinchenbiegepunkt fr %1 ndern.Change leg bendpoint for %1. SketchWidget<Beinchenbiegung fr %1 ndern.Change leg curvature for %1. SketchWidgetJBreite von %1 Bahn(en) nach %2 ndernChange width of %1 wires to %2 SketchWidgetVerbindeConnect SketchWidget4%1 erstellen und verbindenCreate and connect %1 SketchWidget:Draht erstellen und verbindenCreate and connect wire SketchWidget:Draht aus Luftlinie erstellenCreate wire from Ratsnest SketchWidget&Luftlinie entfernenDelete ratsnest SketchWidget(Auswahl zurcksetzenDeselect SketchWidget(Auswahl zurcksetzen Deselect all SketchWidgetTrennen Disconnect SketchWidget2Alle Drhte zu %1 trennenDisconnect all wires from %1 SketchWidgetBAlle Drhte zu %1 Elementen lsen"Disconnect all wires from %1 items SketchWidgetDoppelklicken Double-click SketchWidget`Doppelklicken, um diesen Biegepunkt zu entfernen&Double-click to delete this bend point SketchWidget2Ziehen oder doppelklickenDrag or double-click SketchWidgetUmdrehenFlip SketchWidget Umdrehen %2 (%1) Flip %2 (%1) SketchWidget&%2 verschieben (%1) Move %2 (%1) SketchWidget8%2 Elemente verschieben (%1)Move %2 items (%1) SketchWidget8Bezeichnung '%1' verschiebenMove label '%1' SketchWidget.Verschiebe Beinchen von Move leg of SketchWidget$nderung der NotizNote text change SketchWidgetvBauteil '%1' konnte in diesem Entwurf nicht gefunden werdenPart '%1' not found in sketch SketchWidget"Notizgre ndern Resize Note SketchWidget0Gre anpassen auf %1 %2Resize board to %1 %2 SketchWidgetHGres des Lineals nach %1 %2 ndernResize ruler to %1 %2 SketchWidget DrehenRotate SketchWidgetDrehen %2 (%1)Rotate %2 (%1) SketchWidget %1 auswhlen Select %1 SketchWidget*%1 Elemente auswhlenSelect %1 items SketchWidgetAlles auswhlen Select All SketchWidgetAuswahl Selection SketchWidgetNEs gibt keine ungerouteten Verbindungen!There are no unrouted connections SketchWidget6Dies scheint ein Versuch zur Erzeugung einer Leiterbahn quer durch Ebenen zu sein. Dieser Umstand sollte nicht eintreten: Bitte kontaktiere die Entwickler.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget0Ungeroutete VerbindungenUnrouted connections SketchWidgetlUngeroutete Verbindungen werden in gelb hervorgehoben./Unrouted connections are highlighted in yellow. SketchWidget6Kontaktbezeichnungen ndernchange pin labels SketchWidgetBauteil geladen done loading SketchWidget von %1from %1 SketchWidget>Blende Bauteil-Beschriftung ausHBlende %n Bauteil-Beschriftungen aushide %n part label(s) SketchWidgetLade Bauteil loading part SketchWidgetRoder Alt+Ziehen um ein Segment zu bewegenor alt-drag to move the segment SketchWidget>Blende Bauteil-Beschriftung einHBlende %n Bauteil-Beschriftungen einshow %n part label(s) SketchWidget Verbinder prfentest connectors SketchWidget mit %1to %1 SketchWidgetLeiterbahntrace SketchWidget Drahtwire SketchWidgetXDer Wechsel-Mechanismus ist deaktiviert fr:)The swapping mechanism is disabled for: SqliteReferenceModel.und %1 weitere Bauteileand %1 other partsSqliteReferenceModel8und %1 weitere Eigenschaftenand %1 other propertiesSqliteReferenceModelBauteil '%1' mit ID '%2'; vermutlich da es keine Eigenschaft 'Familie' hat.Epart '%1' with id '%2'; possibly because it has no 'family' property.SqliteReferenceModelZEigenschaft '%1' in Bauteil '%2' mit ID '%3'.(property '%1' in part '%2' with id '%3'.SqliteReferenceModel%1 %n-Streifen%1 %n strip(s) StripboardSchneideCut Stripboard"WiederhergestelltRestored StripboardSpaltencolumns Stripboard Zeilenrows Stripboard"Netzbezeichnungen Net labelsSymbolPaletteItemVNetzbezeichnungen knnen nicht leer bleibenNet labels cannot be blankSymbolPaletteItemBezeichnunglabelSymbolPaletteItemSpannungvoltageSymbolPaletteItem2Fritzing Tipps und TricksFritzing Tips and Tricks TipsAndTricksKleinere Leiterplatten sind erschwinglicher als grere. Spare Platz und Geld.HSmaller PCBs are more affortable than larger ones. Save space and money. TipsAndTricks Tipps und TricksTips and Tricks TipsAndTricksImportieren Sie eine SVG-Datei, um eine eigene Form fr Ihre Leiterplatte zu erstellen.:To create a custom shape for your PCB, import an SVG file. TipsAndTricksUm einen Biegepunkt aus einem Draht zu lschen, doppelklicken Sie darauf.3To delete a bendpoint from a wire, double-click it. TipsAndTricksUm ein elegantes Arduino Shield im Nullkommanichts zu erstellen, schalte die Form der Leiterplatte von einem Rechteck auf den Arduino umhTo make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino TipsAndTricksVerbindungen connections TipsAndTricks8Kurven und biegbare Beinchencurves and bendable legs TipsAndTricksBeispieleexamples TipsAndTricks(Ebenen und Ansichtenlayers and views TipsAndTricks.lokale Datenspeicherunglocal file storage TipsAndTricks(Bewegung und Auswahlmoving and selection TipsAndTricksAnmerkungennotes TipsAndTricks(Bauteilbezeichnungen part labels TipsAndTricksBauteileparts TipsAndTricksBauteile-Editor parts editor TipsAndTricks4Leiterplattenbelegungsplan pcb layout TipsAndTricks.Leiterplattenproduktionpcb production TipsAndTricksDrehungrotation TipsAndTricks,Drhte und Biegepunktewires and bendpoints TipsAndTricksAus der Liste whlen oder einen Wert zwischen %1 und %2 eingeben AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 στον κώδικα και CreativeCommons:BY-SA στα υπόλοιπα <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Το Fritzing κατασκευάστηκε από τους: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Ιδιαίτερες ευχαριστίες στους: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Ευχαριστίες στους Kurt Badelt και Miguel Solis για την μετάφραση στα Ισπανικά, to Gianluca Urgese for the Italian translation, Gianluca Urgese για την μετάφραση στα Ιταλικά, to Nuno Pessanha Santos for the Portuguese (European) translation, Nuno Pessanha Santos για την μετάφραση στα Πορτογαλικά, to Yuelin and Ninjia for the Chinese (Simplified) translation, Yuelin και Ninjia για την μετάφραση στα Κινέζικα (απλοποιημένα), to Hiroshi Suzuki for the Japanese translation, Hiroshi Suzuki για την μετάφραση στα Ιαπωνικά, to Robert Lee for the Chinese (Traditional) translation, Robert Lee για την μετάφραση στα Κινέζικα (παραδοσιακά), to Vladimir Savinov for the Russian translation, Vladimir Savinov fγια την μετάφραση στα Ρώσικα, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, Steven Noppe και Davy Uittenbogerd για την μετάφραση στα Ολλανδικά, to Josef Dustira for the Czech translation, Josef Dustira για την μετάφραση στα τσέχικα, to Jinbuhm Kim for the Korean translation, Jinbuhm Kim για την μετάφραση στα Κορεάτικα, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, &#313;ubom&iacute;r Ducho&#328; για την μετάφραση στα Σλοβάκικα to Alexander Kaltsas for the Greek translation, Καλτσά Αλέξανδρο για την μετάφραση στα Ελληνικά, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the Το Fritzing είναι πραγματικότητα με χρηματοδότηση από τους MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, για την χορηγία του Σχεδίου Department of Bauhaus-University Weimar, Τμήμα του πανεπιστημίου Bauhaus Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, έναν ανώνυμο χορηγό, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students Ειδικές ευχαριστίες σε όλους τους σπουδαστές and alpha testers who were brave enough to give και στους δοκιμαστές των alpha εκδόσεων που ήταν αρκετά γενναίοι Fritzing a test spin. να δοκιμάσουν το Fritzing. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Χειριστήρια μεγέθυνσης και μετακίνησης Stop Now Σταμάτημα Τώρα Best So Far Καλύτερα μέχρι στιγμής Cancel Ακύρωση Autorouter Routing canceled! Now cleaning up... Η δρομολόγησή ακυρώθηκε! Εκτελείτε καθαρισμός... AutorouterSettingsDialog Production type Τύπος παραγωγής homebrew σπιτική professional επαγγελματική custom προσαρμοσμένη Keepout Όριο ασφαλείας <b>Keepout</b> is the minimum distance between copper elements on different nets. <b>Όριο ασφαλείας</b> είναι η ελάχιστη απόσταση μεταξύ στοιχείων χαλκού σε διαφορετικά δίκτυα. A keepout of 0.01 inch (0.254 mm) is a good default. Ένα όριο ασφαλείας 0,01 in (0.254 mm) είναι καλή προεπιλογή. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Σημείωση. Όσο μικρότερο το όριο ασφαλείας, τοσο ποιο αργά θα εκτελούνται ο DRC και η Αυτοδρομολογητής. Trace width Πλάτος διαδρομής Cancel Ακύρωση OK Εντάξει BinManager Parts Εξαρτήματα BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Δεν μπόρεσε να γίνει επισήμανση του δοχείου '%1' ως "βρώμικο" BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Δεν μπόρεσε να γίνει επισήμανση του δοχείου '%1' ως "βρώμικο" New bin (%1) Νέο δοχείο (%1) Select a Fritzing Parts Bin file to open Επιλέξτε για άνοιγμα ένα Δοχείο Εξαρτημάτων του Fritzing Searching... Αναζήτηση... Bin Δοχείο Import... Εισαγωγή... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Φόρτωση ενός εξαρτήματος Fritzing (.fzpz), ή ενός δοδείου εξαρτημάτων Fritzing (.fzb, .fzbz) New Bin... Νέο δοχείο... Create a new parts bin Δημιουργεί ένα νέο δοχείο εξαρτημάτων Close Bin Κλείσιμο Δοχείου Close parts bin Κλείνει ένα δοχείο εξαρτημάτων Delete Bin Διαγραφή Δοχείου Delete parts bin Διαγράφει ένα δοχείο εξαρτημάτων Save Bin Αποθήκευση Δοχείου Save parts bin Αποθηκεύει ένα δοχείο εξαρτημάτων Save Bin As... Αποθήκευση δοχείου ως... Save parts bin as... Αποθηκεύει ένα δοχείο ως... Export Bin... Εξαγωγή Δοχείου... Save parts bin in compressed format... Αποθηκεύει τον δοχείο εξαρτημάτων σε συμπιεσμένη μορφή... Rename Bin... Μετονομασία Δοχείου... Rename parts bin... Μετονομάζει το δοχείο εξαρτημάτων... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Προβολή του Δοχείου σε Λίστα Display parts as a list Προβάλει τα εξαρτήματα σαν λίστα Show Bin in Icon View Προβολή του Δοχείου σε Εικονίδια Display parts as icons Προβάλει τα εξαρτήματα σαν εικονίδια Edit Part (new parts editor)... Επεξεργασία εξαρτήματος (νέος επεξεργαστής εξαρτημάτων)... Export Part... Εξαγωγή Εξαρτήματος... Remove Part Αφαίρεση Εξαρτήματος Find Part in Sketch Εύρεση Εξαρτήματος στο Σχέδιο Delete bin Διαγραφή Δοχείου Do you really want to delete bin '%1'? This action cannot be undone. Θέλετε πραγματικά να διαγράψετε το δοχείο '%1'; Αυτή η ενέργεια δεν αναιρείται. Read-only bin Δοχείο μόνο για ανάγνωση This bin cannot be renamed. Αυτό το δοχείο δεν μπορεί να μετονομαστεί. Rename bin Μετονομασία δοχείου Please choose a name for the bin: Παρακαλώ επιλέξτε ένα όνομα για το δοχείο: Remove from Bin Αφαίρεση από το Δοχείο Unable to remove part '%1'--it is in use in a sketch Αδυναμία αφαίρεσης του εξαρτήματος '%1' --είναι σε χρήση σε κάποιο σχέδιο Remove from bin Αφαίρεση από το δοχείο Do you really want to remove '%1' from the bin? This operation cannot be undone. Θέλετε πραγματικά να αφαιρέσετε το '%1' από το δοχείο; Η ενέργεια αυτή δεν μπορεί να αναιρεθεί. Select a Fritzing File to Open Επιλέξτε για Άνοιγμα ένα αρχείο Fritzing Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Αρχεία Fritzing (*%1 *%2 *%3);;Εξαρτήματα Fritzing (*%1);;Δοχείο Fritzing (*%2);;Διαμοιραζόμενο Δοχείο Fritzing (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Αρχεία Δοχείων του Fritzing (*%1 *%2);;Δοχείο του Fritzing (*%1);;Κοινό Δοχείο του Fritzing (*%2) Cannot set a NULL bin as the current one Τώρα το NULL πως να το πεις... ΚΕΝΟ; Θα δείξει... Δεν μπορείτε να επιλέξετε ένα NULL δοχείο ως τρέχον Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Ρίξτε μία ματιά στο αρχείο circle_pcb.svg στον κατάλογο εγκατάστασης του Fritzing, parts/svg/core/pcb/. one layer (single-sided) ένα επίπεδο (μονής όψεως) two layers (double-sided) δύο επίπεδα (διπλής όψεως) image file αρχείο εικόνας load image file φόρτωση αρχείου εικόνας Images Εικόνες Select an image file to load Επιλέξτε για φόρτωση ένα αρχείο εικόνας due to an xml problem: %1 line:%2 column:%3 λόγο ενός xml προβλήματος: %1 γραμμή: %2 στήλη: %3 because the xml is not correctly formatted επειδή η xml δεν είναι σωστά διαμορφωμένη the <board> element contains no shape elements το στοιχείο <πλακέτα> δεν περιέχει στοιχεία σχήματος because there are multiple <board> layers επειδή υπάρχουν πολλαπλά επίπεδα <πλακέτας> because there are multiple <silkscreen> layers επειδή υπάρχουν πολλαπλά επίπεδα <μεταξοτυπίας> because there are multiple <silkscreen0> layers because there is no <board> layer επειδή δεν υπάρχει επίπεδο <πλακέτας> the svg contains no shape elements το svg δεν περιέχει στοιχεία σχήματος but the pcb itself will have no silkscreen layer αλλά το τυπωμένο δεν θα έχει επίπεδο μεταξοτυπίας the svg doesn't fit the custom board format το svg δεν χωρά στην μορφή της προσαρμοσμένης πλακέτας <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Αδυναμία φόρτωσης Unable to load image from %1 %2 Αδυναμία φόρτωσης εικόνας από %1 %2 Can load, but Μπορεί να φορτωθεί, αλλά The image from %1 can be loaded, but %2 Use the file? Η εικόνα από %1 μπορεί να φορτωθεί, αλλά %2 Χρήση του αρχείου; BoardLogoItem shape σχήμα BreadboardLogoItem color χρώμα Set text color Ορισμός χρώματος κειμένου Select text color Επιλέξτε χρώμα κειμένου Capacitor Select from the dropdown, or type in a %1 value Επιλέξτε από την λίστα, ή πληκτρολογίστε μία %1 τιμή ConnectorItem Add bendpoint Εισαγωγή καμπής Straighten curve Ευθυγράμμιση καμπύλης Remove bendpoint Αφαίρεση καμπής ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools Εργαλεία &About &Περί About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit &Έξοδος Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Το DRC ακυρώθηκε. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Το σχέδιο σας είναι έτοιμο για παραγωγή: Δεν υπάρχουν συνδετήρες ή διάδρομοι που επικαλύπτονται ή είναι πολύ κοντά. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Οι περιοχές στην πλακέτα σας που είναι τονισμένα με κόκκινο είναι συνδετήρες ή χαλκοδιάδρομοι που μπορεί να είναι πολύ κοντά ή να πέφτει το ένα πάνω στο άλλο. Reposition them and run the DRC again to find more problems Επανατοποθετήστε και εκτελέστε το DRC για να βρείτε άλλα προβλήματα Fritzing Fritzing Fritzing error: unable to render board svg. Σφάλμα Fritzing: αδυναμία απόδοσης του svg της πλακέτας. No traces or connectors to check Δεν υπάρχουν ίχνη (χαλκο-διάδρομοι) ή συνδετήρες προς έλεγχο Unexpected SVG rendering failure--contact fritzing.org Απροσδόκητη αποτυχία απόδοσης SVG--ενημερώστε στο fritzing.org %1 is overlapping (%2 layer) το %1 συμπίπτει (επίπεδο %2) A hole in %1 may lie outside the border of the board and would be clipped. Μία οπή στο %1 μπορεί να βρίσκεται εκτός ορίου της πλακέτας και θα κοπεί. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) Πολύ κοντά στο όριο (επίπεδο %1) DRCResultsDialog DRC Results Αποτελέσματα του DRC Click on an item in the list to highlight of overlap it refers to. Κάντε κλικ σε έναν αντικείμενο στην λίστα για να τονιστεί η επικάλυψη. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Σημείωση: τα αντικείμενα της λίστας και η κόκκινη επισήμανση δεν ανανεώνονται καθώς τροποποιείτε το σχέδιο σας--πρέπει να εκτελέσετε πάλι τον DRC. Η επισήμανση θα χαθεί όταν κλείσετε αυτόν τον διάλογο. DebugDialog for debugging για αποσφαλμάτωση DeleteDialog Also delete the file Επίσης διέγραψε το αρχείο Remove Αφαίρεση Don't remove Μην αφαιρείς Dip chip label ετικέτα chip FApplication Fritzing failure Αποτυχία του Fritzing Fritzing caught an exception %1 from %2 in event %3 Το Fritzing εντόπισε μία εξαίρεση %1 από %2 στο γεγονός %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Το Fritzing εντόπισε μία εξαίρεση από το %1 στο γεγονός %2 Import files from previous version? Εισαγωγή αρχείων από προηγούμενη έκδοση; Do you want to import parts and bins that you have created with earlier versions of Fritzing? Θέλετε να εισάγεται εξαρτήματα και δοχεία που έχετε δημιουργήσει με μια νεώτερη έκδοση του Fritzing; Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Σημείωση: Μπορείτε να τα εισάγετε αργότερα χρησιμοποιώντας το μενού "Βοήθεια" > "Εισαγωγή εξαρτημάτων και δοχεία από παλιά έκδοση...". Import Εισαγωγή Do not import now Μην γίνει εισαγωγή τώρα Please specify an .fzz file name to save to (cancel will delete the backup) Παρακαλώ προσδιορίστε ένα όνομα αρχείου .fzz για αποθήκευση (ακύρωση θα διαγράψει το αντίγραφο) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help Βοήθεια Πρώτης Φοράς <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Κλείσιμο Παραθύρου Ctrl+W Ctrl+W Close the current sketch Κλείσιμο του τρέχοντος σχεδίου %1 - %2 %1 - %2 Specify a file name Προσδιορίστε ένα όνομα αρχείου Save "%1" Αποθήκευση "%1" Do you want to save the changes you made in the document "%1"? Θέλετε να αποθηκεύσετε τις αλλαγές που πραγματοποιήσατε στο έγγραφο"%1"; Your changes will be lost if you don't save them. Οι αλλαγές σας θα χαθούν αν δεν τις αποθηκεύσετε. Save... Αποθήκευση... Save Αποθήκευση Don't Save Όχι Αποθήκευση Cancel Ακύρωση Ctrl+D Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Η διαφορά μεταξύ σε "γέμισμα γειώσεις" και "γέμισμα χαλκού" είναι πως στο γέμισμα γείωσης η προς γέμισμα περιοχή περιλαμβάνει διαδρόμους και συνδετήρες που είναι συνδεδεμένοι στον συνδετήρα γείωσης. Οι συνδετήρες της γείωσης έχουν συνήθως την ετικέτα 'GND' ή 'ground' αλλά όχι πάντα. Αυτός ο διάλογος συλλέγει μόνο συνδετήρες με την ετικέτα 'GND' ή 'ground', καθώς και συνδετήρες που έχουν ήδη επιλεγεί. Κάντε "κλικ" σε ένα αντικείμενο για να το επισημάνετε στο σχέδιο. Είναι επίσης εθικτό να επιλέξετε έναν συνδετήρα σαν γέμισμα γείωσης κάνοντας δεξί "κλικ" πάνω του και επιλέγοντας 'Επιλογή Γέμισμα Γείωσης' από το πλαίσιο του μενού. Cancel Ακύρωση OK Εντάξει OK and ground fill Εντάξει και γέμισμα γείωσης OK and copper fill Εντάξει και γέμισμα χαλκού Hole hole size μέγεθος οπής HtmlInfoView Change the part label here Αλλαγή της ετικέτας εξαρτήματος εδώ Part breadboard view image Εικόνα εξαρτήματος προβολής breadboard Part schematic view image Εικόνα εξαρτήματος προβολής σχεδίου Part pcb view image Εικόνα εξαρτήματος προβολής τυπωμένου (PCB) Part version number Αριθμός έκδοσης του εξαρτήματος Locked Κλειδωμένο Change the locked state of the part in this view. A locked part can't be moved. Αλλαγή της κατάσταση κλειδώματος του εξαρτήματος σε αυτή την προβολή. ένα κλειδωμένο εξάρτημα δεν μπορεί να μετακινηθεί. Sticky Υπόμνημα (Sticky) Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Αλλαγή της κατάστασης "υπομνήματος (sticky)" σε αυτή την προβολή. Όταν ένα εξάρτημα-υπόμνημα μετακινείτε, τα από πάνω αντικείμενα μετακινούνται επίσης. Properties Ιδιότητες Placement pcb layer Tags Ετικέτες Connections Συνδέσεις conn. συνδ. name όνομα type τύπος connected to %n item(s) συνδεδεμένο σε %n εξαρτήματα συνδεδεμένο σε %n εξαρτήματα (autoroutable) (αυτο-δρομολογήσιμο) Wire Καλώδιο Ratsnest wire Ratsnest ??? Ratsnest καλώδιο Trace wire %1 Ίχνος καλωδίου %1 v. %1 %2 εκ. %1 %2 obsolete παρωχημένο location rotation degrees ItemBase family οικογένεια type τύπος model μοντέλο size μέγεθος color χρώμα resistance αντίσταση capacitance χωρητικότητα inductance αυτεπαγωγή voltage τάση current ρεύμα power ισχύς pin spacing κενό ακίδων rated power ονομαστική ισχύς rated voltage ονομαστική τάση rated current ονομαστικό ρεύμα version έκδοση package πακέτο shape σχήμα form μορφή part number αριθμός εξαρτήματος maximum resistance μέγιστη αντίσταση pins ακίδες spacing κενό frequency συχνότητα processor επεξεργαστής variant παραλλαγή layers επίπεδα tolerance ανοχή descr ?? περιγρ filename όνομα αρχείου title τίτλος date ημερομηνία rev rev sheet φύλλο project έργο banded top πάνω μέρος bottom κάτω μέρος copper bottom copper top silkscreen bottom silkscreen top Part Εξάρτημα model part problem πρόβλημα μοντέλου εξαρτήματος file for %1 %2 not found το αρχείο για το %1 %2 δεν βρέθηκε unable to create renderer for svg %1 αδυναμία δημιουργίας απόδοσης για το svg %1 KicadModuleDialog Cancel Ακύρωση OK Εντάξει LayerPalette show all layers εμφάνιση όλων των επιπέδων LinkDialog url: url: text: κείμενο: Cancel Ακύρωση OK Εντάξει LogoItem text shape σχήμα due to a rendering error λόγο ενός σφάλματος στην απόδοση because the svg is empty επειδή το svg είναι άδειο because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting επειδή το αυτό μοιάζει να είναι ένα SVG αρχείο από το CorelDRAW χωρίς να έχει επιλεγεί η ρύθμιση 'presentation attributes' due to an xml problem: %1 line:%2 column:%3 λόγο ενός xml προβλήματος: %1 γραμμή: %2 στήλη: %3 because the file has no root element επειδή το αρχείο δεν έχει στοιχείο ρίζας (root) because the file has no <svg> element επειδή το αρχείο δεν έχει <svg> στοιχείο for unknown reasons--possibly the image file is corrupted για άγνωστο λόγο--πιθανότατα η εικόνα είναι κατεστραμένη Unable to display Αδυναμία προβολής Unable to display image from %1 Αδυναμία προβολής εικόνας από %1 MainWindow Rotate Περιστροφή Share Διαμοιρασμός Flip Αναστροφή Autoroute Αυτο-Δρομολόγιση Both Layers Τα δύο Επίπεδα Bottom Layer Κάτω Επίπεδο Top Layer Πάνω Επίπεδο Add a note Προσθήκη Σημείωσης Export for PCB Εξαγωγή σε PCB Ready Έτοιμο Ctrl+R Rotate Clockwise Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Toggle Active Layer Shift+Ctrl+Tab Click to highlight unconnected parts Fabricate View from Above View from Below Save %1 Αποθήκευση %1 Unable to open '%1': %2 Αδυναμία ανοίγματος του '%1': %2 Unable to open shareable '%1': %2 Αδυναμία ανοίγματος του κοινόχρηστου '%1': %2 Unable to open shareable part '%1': %2 Αδυναμία ανοίγματος του κοινόχρηστου εξαρτήματος '%1': %2 Unable to load part from '%1' Αδυναμία φόρτωσης του εξαρτήματος '%1' Specify a file name Προσδιορίστε ένα όνομα αρχείου Change image to %2 Αλλαγή εικόνας σε %2 Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Αδυναμία εξαγωγής του %1 ως κοινόχρηστο No Sketch found in '%1' Δεν βρέθηκε κανένα σχέδιο στο '%1' Fritzing Part (*%1) Εξάρτημα Fritzing (*%1) Unable to export %1 to shareable sketch Αδυναμία εξαγωγής του %1 σε κοινόχρηστο σχέδιο MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Υπάρχει ήδη ένα εξάρτημα με ταυτότητα '%1' που έχει φορτωθεί στο Fritzing. Do you want to keep the imported parts? Θέλετε να διατηρήσετε τα εισαγμένα εξαρτήματα; No connections to route Δεν υπάρχουν συνδέσεις για δρομολόγιση Routing completed Η δρομολόγιση ολοκληρώθηκε Routing completed using %n jumper part(s) Η δρομολόγιση ολοκληρώθηκε χρησιμοποιώντας %n βραχυκυκλωτήρες Η δρομολόγιση ολοκληρώθηκε χρησιμοποιώντας %n βραχυκυκλωτήρες %1 of %2 nets routed - %n connector(s) still to be routed %1 από %2 δίκτυα δρομολογήθηκαν - %n συνδετήρες προς δρομολόγηση %1 από %2 δίκτυα δρομολογήθηκαν - %n συνδετήρες προς δρομολόγηση %1 - [%2] %1 - [%2] No copper top layer Δεν υπάρχει πάνω επίπεδο χαλκού The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Το πανω επίπεδο χαλκού (copper 1) δεν είναι διαθέσιμο σε μία μονής όψης πλακέτα. Παρακαλώ αλλάξτε την πλακέτα σε διπλής όψης ή επιλέξτε το κάτω επίπεδο (copper 0) χαλκού. Sorry! Συγνώμη! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Δεν υπάρχει εξάρτημα με αυτά τα χαρακτηριστικά. Προσπαθούμε να αποφύγουμε το μήνυμα αυτό, και σας επιτρέπουμε να επιλέξετε μεταξύ ιδιοτήτων που υπάρχουν No exactly matching part found; Fritzing chose the closest match. Δεν βρέθηκε ακριβώς το εξάρτημα, το Fritzing επέλεξε το πιο ταιριαστό. Change to single layer pcb Αλλαγή σε τυπωμένο μονής όψης Change to two layer pcb Αλλαγή σε τυπωμένο διπλής όψης Swapped %1 with module %2 Ανταλλάχτηκε το το άρθρωμα %1 με το %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Το Svg %1 στερείται ενός '%2' επιπέδου. Για περισσότερες πληροφορίες για την δημιουργία προσαρμοσμένου σχήματος πλακετών δείτε το βοήθημα στο <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 φόρτωση %1 Loading... Φόρτωση... new sketch νέο σχέδιο Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Αντιγραφή ασφαλείας '%1' Unrouted connections Μη δρομολογημένες συνδέσεις There are no unrouted connections in this view. Δεν υπάρχουν μη δρομολογημένες συνδέσεις σε αυτή την προβολή. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Κώδικας Welcome Ctrl+D Ctrl+D PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG Εικόνα (*.png) JPEG Image (*.jpg) JPEG Εικόνα (*.jpg) SVG Image (*.svg) SVG Εικόνα (*.svg) BoM Text File (*.html) BoM Αρχείο Κειμένου (*.html) Printing... Εκτύπωση... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Το σχέδιο σας δεν περιέχει κάποια πλακέτα! Παρακαλώ προσθαίστε ένα PCB για να εξάγετε σε οξυγραφία. Etchable export can only handle one board at a time--please select the board you want to export. Η εξαγωγή σε οξυγραφία μπορεί να διαχειριστεί μόνο μία πλακέτα την φορά--παρακαλώ επιλέξτε την πλακέτα που θέλετε να εξάγετε. All traces have not yet been routed. Δεν έχουν δρομολογηθεί όλα τα ίχνη. Do you want to proceed anyway? Θέλετε να συνεχίσετε παρόλο αυτά; Proceed Συνέχεια Cancel Ακύρωση Choose a folder for exporting Επιλογή φακέλου για την εξαγωγή Sketch exported Έγινε εξαγωγή του σχεδίου Export... Εξαγωγή... Exporting... Εξαγωγή... Unable to save %1 Αδυναμία αποθήκευσης του %1 Cannot print to %1 Αδυναμία εκτύπωσης του %1 Cannot write file %1: %2. Αδυναμία εγγραφής του αρχείου %1: %2. Saved '%1' Αποθηκευμένο '%1' &Save &Αποθήκευση Ctrl+S Ctrl+S Save the current sketch Αποθήκευση τρέχοντος σχεδίου &Save As... &Αποθήκευση Ως... Shift+Ctrl+S Shift+Ctrl+S Share online... Διαμοιρασμός στο Ιντερνετ... Post a project to the Fritzing website Τοποθετήστε ένα έργο σας στην σελίδα του Fritzing JPG... JPG... Export the visible area of the current sketch as a JPG image Εξαγωγή της ορατής περιοχής του τρέχοντος σχεδίου ως JPG εικόνας PNG... PNG... Export the visible area of the current sketch as a PNG image Εξαγωγή της ορατής περιοχής του τρέχοντος σχεδίου ως PNG εικόνας PostScript... PostScript... Export the visible area of the current sketch as a PostScript image Εξαγωγή της ορατής περιοχής του τρέχοντος σχεδίου ως PostScrip εικόνας PDF... PDF... Export the visible area of the current sketch as a PDF image Εξαγωγή της ορατής περιοχής του τρέχοντος σχεδίου ως PDF εικόνας SVG... SVG... Export the current sketch as an SVG image Εξαγωγή του τρέχοντος σχεδίου ως SVG εικόνας List of parts (&Bill of Materials)... Λίστα των εξαρτημάτων (Κόστος Υλικών, &BoM)... Save a Bill of Materials (BoM)/Shopping List as text Αποθήκευση του Κόστους Υλικών (BoM) ως κείμενο XML Netlist... XML Netlist... Save a netlist in XML format Αποθήκευση netlist σε XML μορφή SPICE Netlist... SPICE Netlist... Save a netlist in SPICE format Αποθήκευση μίας netlist σε μορφή SPICE Eagle... Eagle... Export the current sketch to Eagle CAD Εξαγωγή του τρέχοντος σχεδίου σε Eagle CAD Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Εξαγωγή του τρέχοντος σχεδίου σε μορφή Extended Gerber (RS-274X) για επαγγελματική παραγωγή τυπωμένου (PCB) Etchable (PDF)... Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Εξαγωγή του τρέχοντος σχεδίου σε PDF για την κατασκευή "σπιτικού" φωτοευαίσθητου τυπωμένου (photoresist PCB) Etchable (SVG)... Οξυγραφία (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) Εξαγωγή του τρέχοντος σχεδίου σε SVG για την κατασκευή "σπιτικού" φωτοευαίσθητου τυπωμένου (photoresist PCB) &Print... &Εκτύπωση... Ctrl+P Ctrl+P Print the current view Εκτύπωση της τρέχουσας προβολής This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Αυτό σύντομα θα προσφαίρει εξαγωγή του Fritzing σχεδίου σας για το λογισμικό σχεδίασης EAGLE. Αν θέλετε να έχετε περισσότερες επιλογές εξαγωγής στο αγαπημένο σας EDA εργαλείο, ενημερώστε μας, ή συνεισφέρετε οι ίδιοι. Export SVG... Εξαγωγή SVG... Export Bill of Materials (BoM)... Εξαγωγή κόστους υλικών (BoM)... Unable to save BOM file, but the text is on the clipboard. Αδυναμία αποθήκευσης του αρχείου BoM, αλλά το κείμενο υπάρχει στο πρόχειρο. Export SPICE Netlist... Εξαγωγή SPICE Netlist... Export Netlist... Εξαγωγή Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Το σχέδιο σας δεν έχει ακόμη πλακέτα! Παρακαλώ προσθέστε ένα τυπωμένο (PCB) για να εξάγετε σε Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Η εξαγωγή Gerber μπορεί μόνο να διαχειριστεί μόνο μία πλακέτα την φορά--παρακαλώ επιλέξτε την πλακέτα που θέλετε να εξάγετε. Sketch exported to Gerber Το σχέδιο εξάχθηκε σε Gerber Select a Fritzing File to Open Επιλέξτε για Άνοιγμα ένα αρχείο Fritzing Cannot find file %1. Αδυναμία εύρεσης του αρχείου %1. Cannot read file 1 %1: %2. Αδυναμία ανάγνωσης του αρχείου 1 %1: %2. File '%1' not found Το αρχείο '%1' δεν βρέθηκε the .fz file format is obsolete η μορφή αρχείων .fz είναι ξεπερασμένη The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? Η μορφή αρχείων .fz έχει ξεπεραστεί. Θα θέλατε να μετατρέψετε το '%1' στην μορφή .fzz τώρα ή να το ανοίξετε μόνο για αναγνωση; The conversion process will not modify '%1'. Η διαδικασία μετατροπής δεν θα τροποποιήσει το '%1'. Convert Μετατροπή Read-only Μόνο Ανάγνωση Please specify an .fzz file name to save '%1' to Παρακαλώ επιλέξτε ένα όνομα αρχείου .fzz για την αποθήκευση του '%1' directly loading parts απευθείας φόρτωση εξαρτημάτων loading %1 (model) φόρτωση %1 (μοντέλου) loading %1 (breadboard) φόρτωση %1 (breadboard) loading %1 (pcb) φόρτωση %1 (pcb) loading %1 (schematic) φόρτωση %1 (σχέδιο) New Νέο Ctrl+N Ctrl+N Create a new sketch Δημιουργεί ένα νέο σχέδιο &Open... &Άνοιγμα... Ctrl+O Ctrl+O Shell launch %1 Εκκίνηση κελύφους %1 throw test exception εισαγωγή εξαίρεσης δοκιμής throw a fake exception to see what happens Εισάγει μία ψεύτικη εξαίρεση για να δει τι συμβαίνει &Quit &Έξοδος Ctrl+Q Ctrl+Q Quit the application Εγκαταλείπει την εφαρμογή &Open Example &Άνοιγμα Παραδείγματος All Όλα MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: αδυναμία φόρτωσης παραδείγματος με διακριτικό='%1' &Open Recent Files &Άνοιγμα Πρόσφατων Αρχείων &%1 %2 &%1 %2 Undo Αναίρεση Redo Επανάληψη &Cut &Αποκοπή Cut selection Αποκοπή επιλογής &Copy Copy selection Αντιγράφει το επιλεγμένο &Paste &Επικόλληση Paste clipboard contents Επικόλληση των περιεχομένων του πρόχειρου Paste in Place Επικόλληση Εδώ Paste clipboard contents in place Επικόλληση των περιεχομένων του πρόχειρου στην ίδια θέση &Duplicate &Διπλότυπο Duplicate selection Δημιουργεί ένα αντίγραφο της επιλογής &Delete &Διαγραφή Delete selection Διαγράφει την επιλογή &Select All &Επιλογή Όλων Select all elements Επιλέγει όλα τα στοιχεία &Deselect &Αποεπιλογή Deselect Αποεπιλέγει Add Note Προσθήκη Σημείωσης &Preferences... &Επιλογές... Show the application's about box Εμφανίζει πληροφορίες για την εφαρμογή &Edit &Επεξεργασία &Add to bin... &Προσθήκη σε δοχείο... Add selected part to bin Προσθέτει το εξάρτημα σε δοχείο Disconnect All Wires Αποσύνδεση Όλων των Καλωδίων Disconnect all wires connected to this connector Αποσυνδέει όλα τα καλώδια που συνδέονται σε αυτόν τον συνδετήρα Update InfoView on hover Ενημέρωση InfoView στο πέρασμα από πάνω Export Normalized SVG Εξαγωγή Κανονικοποιημένου SVG Export 1000 dpi SVG of this part in this view Εξάγει ένα SVG 1000 dpi του εξαρτήματος σε αυτή την προβολή Export Normalized Flattened SVG Εξαγωγή Κανονικοποιημένου Πεπλατυσμένου SVG Export 1000 dpi Flattened SVG of this part in this view Εξάγει ένα Πεπλατυσμένο SVG του εξαρτήματος σε αυτή την προβολή Rotate the selected parts by 90 degrees clockwise Περιστρέφει το επιλεγμένο εξάρτημα κατά 90 μοίρες δεξιόστροφα Rotate the selected parts by 180 degrees Περιστρέφει το επιλεγμένο εξάρτημα κατά 180 μοίρες Rotate current selection 90 degrees counter clockwise Περιστρέφει την τρέχουσα επιλογή 90 μοίρες αριστερόστροφα Rotate current selection 45 degrees counter clockwise Περιστρέφει την τρέχουσα επιλογή 45 μοίρες αριστερόστροφα Rotate current selection 45 degrees clockwise Περιστρέφει την τρέχουσα επιλογή 45 μοίρες δεξιόστροφα &Flip Horizontal &Οριζόντια Αναστροφή Flip current selection horizontally Αναστρέφει την τρέχουσα επιλογή οριζόντια &Flip Vertical &Κατακόρυφη Αναστροφή Flip current selection vertically Αναστρέφει την τρέχουσα επιλογή κατακόρυφα Bring to Front Μεταφορά Εμπρός Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Μεταφέρει τα επιλεγμένα αντικείμενα εμπρός στο επίπεδό τους Bring Forward Μεταφορά προς τα Εμπρός Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Μεταφέρει τα επιλεγμένα αντικείμενα προς τα εμπρός στο επίπεδό τους Send Backward Μεταφορά προς τα Πίσω Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Μεταφέρει τα επιλεγμένα αντικείμενα πίσω στο επίπεδό τους Send to Back Μεταφορά Πίσω Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Μεταφέρει τα επιλεγμένα αντικείμενα προς τα πίσω στο επίπεδό τους Lock Part Κλείδωμα Εξαρτήματος Prevent a part from being moved Αποτρέπει την μετακίνηση ενός εξαρτήματος Select All Locked Parts Επιλογή Όλων των Κλειδωμένων Εξαρτημάτων Select all parts that can't be moved Επιλέγει όλα τα εξαρτήματα που δεν μπορούν να μετακινηθούν &Show All Layers &Εμφάνιση Όλων των Επιπέδων Show all the available layers for the current view Εμφανίζει όλα τα διαθέσιμα επίπεδα για την τρέχουσα προβολή &Hide All Layers &Απόκρυψη Όλων των Επιπέδων Hide all the layers of the current view Αποκρύπτει όλα τα επίπεδα της τρέχουσας προβολής &Show part label &Εμφάνιση ετικέτας εξαρτήματος Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Περιστροφή 135° Δεξιόστροφα {45�?} Rotate 90� Clockwise Περιστροφή 135° Δεξιόστροφα {90�?} Rotate 180� Περιστροφή 180° {180�?} Rotate 90� Counter Clockwise Περιστροφή 45° Αριστερόστροφα {90�?} Rotate 45� Counter Clockwise Περιστροφή 45° Αριστερόστροφα {45�?} &Export... &Εξαγωγή... Export selected part Εξάγει το επιλεγμένο εξάρτημα Add Bendpoint Εισαγωγή Καμπής Add a bendpoint to the selected wire Εισάγει ένα σημείο καμπής στο επιλεγμένο καλώδιο Convert Bendpoint to Via Μετατροπή σημείου καμπής σε Οπή Convert the bendpoint to a via Μετατρέπει το σημείο καμπής σε οπή Convert Via to Bendpoint Μετατροπή Οπής σε Σημείο καμπής Convert the via to a bendpoint Μετατρέπει την οπή σε σημείο καμπής Straighten Curve Ευθυγράμμιση Καμπύλης Straighten the curve of the selected wire Ευθυγραμμίζει την καμπύλη του επιλεγμένου καλωδίου Select outdated parts Επιλογή ξεπερασμένων εξαρτημάτων Update selected parts Ενημέρωση επιλεγμένων εξαρτημάτων Open programming window Άνοιγμα παραθύρου προγραμματισμού Open microcontroller programming window Ανοίγει το παράθυρο προγραμματισμού του μικροελεγκτή &Zoom In &Μεγέθυνση Ctrl++ Ctrl++ Zoom in Εκτελεί μεγέθυνση Ctrl+= Ctrl+= &Zoom Out &Σμίκρυνση Ctrl+- Ctrl+- Zoom out Εκτελεί σμίκρυνση &Fit in Window &Ταίριασμα στο Παράθυρο Ctrl+0 Ctrl+0 Fit in window Προσαρμόζει το μέγεθος σε αυτό του παραθύρου &Actual Size &Πραγματικό Μέγεθος Actual (real world physical) size Πραγματικό φυσικό μέγεθος 100% Size 100% Μέγεθος Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size 100% μέγεθος (εικονοστοιχεία) Align to Grid Ευθυγράμμιση στο Πλέγμα Align items to grid when dragging Ευθυγραμμίζει τα αντικείμενα στο πλέγμα κατά το σύρσιμο Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Show Code Εμφάνιση Κώδικα Show the code (programming) view Εμφάνιση προβολής κώδικα (προγραμματισμού) Display First Time Help &Routing &Δρομολόγηση Autoroute connections... Συνδέσεις Αυτοδρομολόγησης... &Create trace from ratsnest &Δημιουργία ίχνους από το rastnet Create a trace from the ratsnest line Δημιουργεί έναν διάδρομο από την γραμμή του rastnet &Create wire from ratsnest &Δημιουργία καλωδίου από το rastnet Create a wire from the ratsnest line Δημιουργεί ένα καλώδιο από την γραμμή του rastnet Select All Wires Επιλογή Όλων των Καλωδίων Select all wires Επιλέγει όλα τα καλώδια Select All "Don't Autoroute" Traces Επιλογή Όλων "Μην Αυτοδρομολογείς" τα Ίχνη Select All Autoroutable Traces Επιλογή Όλων των Αυτοδρομολογούμενων Ιχνών Select all trace wires that can be changed during autorouting Επιλέγει όλα ίχνη καλωδίων που μπορεί να αλλαχτούν κατά την αυτοδρομολόγηση Fill empty regions of the copper layer--not including traces connected to a GROUND Γεμίζει τις άδειες περιοχές του επιπέδου του χαλκού χωρίς να περιλαμβάνει τα ίχνη που συνδέονται σε κάποια Γείωση (GROUND) Choose Ground Fill Seed(s)... Επιλέξτε Φύτρες Γεμίσματος Γείωσης... Set Ground Fill Seed Καθορίστε Φύτρες Γεμίσματος Γείωσης Treat this connector and its connections as a 'ground' during ground fill. Αντιμετωπίζει τους συνδετήρες και τις συνδέσεις τους ως 'γείωση' κατά το γέμισμα γείωσης. Clear Ground Fill Seeds Καθάρισμα των Φυτρών Γεμίσματος Γείωσης Clear ground fill seeds--enable copper fill only. Καθαρίζει τις φύτρες γεμίσματος γείωσης. Ενεργοποιεί γέμισμα χαλκού μόνο. Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Επιλέξτε τα ίχνη που η θέση στην οθόνη δεν ταιριάζει την πραγματική θέση. Μόνο για σχέδια αυτοδρομολογημένα με έκδοση 0.7.10 ή νεότερη Autorouter/DRC settings... Ρυθμίσεις Αυτοδρομολογητή/DRC... Set autorouting parameters including keepout... Ρύθμιση παραμέτρων αυτοδρομολόγησης και ορίου ασφαλείας... jumpers βραχυκυκλωτήρες copperfill γέμισμα χαλκού vias οπές Generating %1 fill... Παραγωγή %1 γεμίσματος... ground γείωση copper χαλκός Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Do you want to update now? unable to find replacement for %1. Αδυναμία εύρεσης αντικατάστασης για το %1. &Show Breadboard &Εμφάνιση Breadboard Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Αρχεία Fritzing (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Διαμοιραζόμενα Fritzing (*%2);;Εξαρτήματα Fritzing (*%3);;Δοχεία Fritzing (*%4);;Διαμοιραζόμενα Δοχεία Fritzing (*%5) Revert? Αναίρεση; This operation can not be undone--you will lose all of your changes. Go ahead and revert? Αυτή η ενέργεια δεν μπορεί να αναιρεθεί--θα χάσετε όλες τις αλλαγές. Συνέχεια στην αναίρεση; Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Άνοιγμα ενός σχεδίου Fritzing (.fzz, .fz), ή φόρτωση ενός εξαρτήματος Fritzing (.fzpz), ή ένός δοχείου εξαρτηματων Fritzing (.fzb, .fzbz) Revert Αναίρεση Reload the sketch Επαναφόρτωση του σχεδίου &Delete Wire &Διαγραφή Καλωδίου Edit (new parts editor) Επεξεργασία (επεξεργαστής νέων εξαρτημάτων) Open the new parts editor on an existing part Άνοιγμα του επεξεργαστή νέων εξαρτημάτων σε ένα υπάρχον εξάρτημα Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Sticky Υπόμνημα (Sticky) If a "sticky" part is moved, parts on top of it are also moved Όταν ένα εξάρτημα-υπόμνημα μετακινείτε, τα από πάνω αντικείμενα μετακινούνται επίσης Show/hide the label for the selected parts Εμφάνιση/Απόκρυψη της ετικέτας για το επιλεγμένο εξάρτημα Find part in sketch... Εύρεση εξαρτήματος στο σχέδιο... Search for parts in a sketch by matching text Αναζήτηση για εξαρτήματα σε ένα σχέδιο βάση κειμένου Hide part silkscreen Απόκρυψη μεταξοτυπίας εξαρτήματος Hide/show the silkscreen layer for only this part Αποκρύψη/Εμφάνιση του επιπέδου μεταξοτυπίας για αυτό το εξάρτημα Show Grid Εμφάνιση Πλέγματος Show the grid Εμφανίζει το πλέγμα Set Grid Size... Ρύθμιση μεγέθους πλέγματος... Set the size of the grid in this view Ρυθμίζει το μέγεθος πλέγματος σε αυτή την προβολή Set Background Color... Ρύθμιση Χρώματος Φόντου... Set the background color of this view Ρυθμίζει το χρώμα φόντου σε αυτή την προβολή Ctrl+1 Ctrl+1 Show the breadboard view Εμφανίζει την προβολή breadboard &Show Schematic &Εμφάνιση Schematic Ctrl+2 Ctrl+2 Show the schematic view Εμφανίζει την προβολή σε σχηματικό &Show PCB &Εμφάνιση Τυπωμ.ένου (PCB) Ctrl+3 Ctrl+3 Show the PCB view Εμφανίζει την προβολή σε τυπωμένο (PCB) Ctrl+4 Ctrl+4 Show Parts Bin Icon View Εμφάνιση Δοχείου Εξαρτημάτων ως Εικονίδια Display the parts bin in an icon view Εμφανίζει τα εξαρτήματα στο δοχείο σαν εικονίδια Show Parts Bin List View Εμφάνιση Δοχείου Εξαρτημάτων ως Λίστα Display the parts bin in a list view Εμφανίζει τα εξαρτήματα στο δοχείο σαν λίστα &Minimize &Ελαχιστοποίηση Ctrl+M Ctrl+M Minimize current window Ελαχιστοποιεί το τρέχον παράθυρο Debugger Output Έξοδος Αποσφαλματωτή Online Tutorials Βοηθήματα στο Διαδίκτυο Ctrl+? Ctrl+? Open Fritzing help Άνοιγμα βοήθειας του Fritzing Donate to Fritzing Δωρεά προς το Fritzing Open Fritzing donation web page Ανοίγει την σελίδα δωρεών του Fritzing Online Projects Gallery Συλλογή Έργων στο Διαδίκτυο Open Fritzing examples Άνοιγμα παραδειγμάτων του Fritzing Online Parts Reference Αναφορά Εξαρτημάτων στο Διαδίκτυο Open Parts Reference Άνοιγμα Αναφοράς Εξαρτημάτων First Time Help Βοήθεια Πρώτης Φοράς Check for updates... Έλεγχος για ενημερώσεις... Check whether a newer version of Fritzing is available for download Ελέγχει αν υπάρχει κάποια νέα έκδοση του Fritzing για μεταφόρτωση &About &Περί Tips, Tricks and Shortcuts Συμβουλές, Κόλπα και Συντομεύσεις Display some handy Fritzing tips and tricks Εμφανίζει μερικές χρήσιμες συμβουλές και κόλπα &About Qt &Περί του Qt Show Qt's about box Εμφανίζει πληροφορίες για το Qt Report a bug... Αναφορά προβλήματος... Report a but you've found in Fritzing Αναφέρει κάποιο πρόβλημα που εντοπίσατε στο Fritzing Enable debugging log Ενεργοποίηση καταγραφής αποσφαλμάτωσης &Import parts and bins from old version... &εισαγωγή εξαρτημάτων και δοχείων από παλιότερη έκδοση... Import parts and bins from previous installation Εισάγει εξαρτήματα και δοχεία από μία προηγούμενη εγκατάσταση Parts Editor Help Βοήθεια Επεξεργαστή Εξαρτημάτων Display Parts Editor help in a browser Εμφανίζει την βοήθεια του Επεξεργαστή Εξαρτημάτων σε έναν φυλλομετρητή &File &Αρχείο &Export &Εξαγωγή as Image ως Εικόνα for Production για Παραγωγή &Part &Εξάρτημα Raise and Lower Ανύψωση και Κατέβασμα Ctrl+Shift+V Align &View &Προβολή &Window &Παράθυρο Ground Fill Γέμισμα Γείωσης &Help &Βοήθεια Move to bottom layer Move to top layer Delete Ratsnest Line Διαγραφή Γραμμής Rastnest Delete Wire Διαγραφή Καλωδίου Hide part label Απόκρυψη ετικέτας εξαρτήματος Show part label Εμφάνιση ετικέτας εξαρτήματος Show part silkscreen Εμφάνιση μεταξοτυπίας εξαρτήματος Delete Διαγραφή top and bottom bottom κάτω μέρος top πάνω μέρος Ground Fill (%1) Copper Fill (%1) Actual Size Φυσικό Μέγεθος It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Δεν μοιάζει να είναι εφικτό να καθοριστεί αυτόματα το φυσικό μέγεθος της οθόνης, έτσι το 'Φυσικό Μέγεθος' είναι απλά μια εκτίμηση. Η καλύτερη λύση θα ήταν να τοποθετήσετε έναν κανόνα και μετά έναν πραγματικό κανόνα από πάνω να μεγεθύνεται μέχρι να υπάρξει ταύτιση. Page Setup Ρύθμιση Σελίδας Sorry, "%1" has not been implemented yet Συγνώμη. Το "%1" δεν έχει υλοποιηθεί ακόμη Shift+Ctrl+A Shift+Ctrl+A Set Ground Fill Keepout... Ορισμός Ορίου Ασφαλείας στο Γέμισμα Χαλκού... Set the minimum distance between ground fill and traces or connectors Ορισμός ελάχιστης απόστασης μεταξύ γεμίσματος χαλκού και ιχνών ή συνδετήρων Design Rules Check (DRC) Έλεγχος Σχεδιαστικών Κανόνων (DRC) Highlights any parts that are too close together for safe board production Επισήμανση όποιων εξαρτημάτων βρίσκονται πολύ κοντά το ένα στο άλλο, για ασφαλή παραγωγή πλακέτας Fritzing Fab Quote... Ερώτηση Fritzing Fab... How much would it could to produce a PCB from this sketch with Fritzing Fab Πόσο θα στοίχιζε η παραγωγή ενός τυπωμένου (PCB) από αυτό το σχέδιο με το Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Set both copper layers clickable Ενεργοποίηση του "κλικ" στα δύο επίπεδα Shift+Ctrl+3 Shift+Ctrl+3 Set copper top layer clickable Ενεργοποίηση του "κλικ" στο πάνω επίπεδο Shift+Ctrl+2 Shift+Ctrl+2 Set copper bottom layer clickable Ενεργοποίηση του "κλικ" στο κάτω επίπεδο Shift+Ctrl+1 Shift+Ctrl+1 Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text QInputDialog::getText() Text will match part label, description, title, etc. Enter text to search for: Το κείμενο θα ταιριάξει με την ετικέτα του εξαρτήματος, περιγραφή, τίτλο, κτλ. Εισάγετε κείμενο προς αναζήτηση: Search Αναζήτηση No parts matched search term '%1'. Κανένα εξάρτημα δεν ταιριάζει με τον όρο '%1'. Do not autoroute Όχι αυτοδομολόγηση When autorouting, do not rip up this trace wire, via, or jumper item Κατά την αυτοδρομολόγηση, μην πειράζεις αυτό το ίχνος, καλώδιο, τυφλή οπή ή βραχυκυκλωτήρα Move to other side of the board Μετακίνηση στην άλλη πλευρά της πλακέτας Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Μετακινεί τα επιλεγμένα ίχνη στην άλλη πλευρά της πλακέτας (θα μετακινηθεί το πρώτο και τα υπόλοιπα θα ακολουθήσουν) Show unrouted Εμφάνιση μη δρομολογημένων Highlight all unrouted connectors Επισήμανση όλων των μη δρομολογημένων συνδετήρων Select All Traces Επιλογή Όλων των Ιχνών Select all trace wires Επιλέγει όλα τα ίχνη καλωδίων Select All CopperFill Επιλογή Όλου του Γεμίσματος Χαλκού Select all copper fill items Επιλέγει όλα τα αντικείμενα γεμίσματος χαλκού Force Update Routing Status and Ratsnests Εξαναγκασμένη Ενημέρωση Κατάστασης Δρομολόγησης και Rastnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Υπολογίζει πάλι την κατάσταση δρομολόγησης και τα καλώδια rastnests (σε περίπτωση που η αυτοδρομολόγηση δεν δουλεύει σωστά) Select all trace wires excluded from autorouting Επιλογή όλων των ιχνών καλωδίων που εξαιρούνται από την αυτοδρομολόγηση Select All Jumpers Επιλογή Όλων των Βαχυκυκλωτήρων Select all jumper item parts Επιλέγει όλους τους βραχυκυκλωτήρες Select All Vias Επιλογή Όλων των τυφλών Οπών Select all via parts Επιλέγει όλες τις τυφλές οπές Tidy Wires Τακτοποίηση Καλωδίων Tidy selected wires Τακτοποιεί τα επιλεγμένα καλώδια Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Γεμίζει τις άδειες περιοχές του επιπέδου χαλκού. Το γέμισμα θα περιλάβει όλα τα ίχνη που συνδέονται σε μία γείωση (GROUND) Copper Fill Γέμισμα Χαλκού Remove Copper Fill Αφαίρεση Γέμισμα Χαλκού Remove the copper fill Αφαιρεί το γέμισμα χαλκού Fill empty regions of the copper layer--fill will include all traces connected to the seeds Γεμίζει τις άδειες περιοχές του επιπέδου χαλκού. Το γέμισμα θα περιλάβει όλα τα ίχνη που συνδέονται σε φύτρες Shift+Ctrl+D Shift+Ctrl+D Check Loaded Traces Έλεγχος Φορτωμένων Ιχνών Copper Top and Copper Bottom layers are both active Το Πάνω και Κάτω στρώμα χαλκού είναι ενεργά Order a PCB... Παραγγελία Τυπωμένου (PCB)... Order a PCB created from your sketch--from fabulous Fritzing Fab Παραγγελία ενός PCB που δημιουργήθηκε από κάποιο σχέδιο σας. Από το εργαστήριο του Fritzing Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε μια πλακέτα (PCB) για να κάνετε χρήση του αυτόματου δρομολογητή. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Παρακαλώ επιλέξτε την πλακέτα που θέλετε για τον αυτόματο δρομολογητή. Ο αυτόματος δρομολογητής μπορεί να χειριστεί μία πλακέτα την φορά. The folder "%1" isn't a Fritzing installation folder Ο φάκελος "%1" δεν είναι ένας φάκελος εγκατάστασης του Fritzing Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποιο PCB για να χρησιμοποιήσετε γέμισμα χαλκού. Please select a PCB--copper fill only works for one board at a time. Παρακαλώ επιλέξτε μία πλακέτα (PCB)--το γέμισμα χαλκού μπορεί να χειριστεί μία πλακέτα την φορά. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποιο PCB για να αφαιρέσετε το γέμισμα χαλκού. Please select a PCB--ground fill operations only work on a one board at a time. Παρακαλώ επιλέξτε μία πλακέτα (PCB)--το γέμισμα γείωσεις μπορεί να χειριστεί μία πλακέτα την φορά. OK Εντάξει Set the grid size for %1. Ρύθμιση μεγέθους πλέγματος για %1. Grid Size: Μέγεθος Πλέγματος: in in mm mm Restore Default Αποκατάσταση Προεπιλογών Your sketch does not have a board yet! DRC only works with a PCB. Το σχέδιο σας δεν περιέχει κάποια πλακέτα! Ο DRC λειτουργεί μόνο με μία πλακέτα (PCB). Please select a PCB. DRC only works on one board at a time. Παρακαλώ επιλέξτε μία πλακέτα (PCB)--ο DRC μπορεί να χειριστεί μία πλακέτα την φορά. DRC Progress... Πρόοδος DRC... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποια πλακέτα (PCB) για να χρησιμοποιήσετε τις λειτουργίες γεμίσματος χαλκού. Please select a PCB. Copper fill operations only work on one board at a time. Παρακαλώ επιλέξτε μία πλακέτα (PCB). Το γέμισμα χαλκού μπορεί να χειριστεί μία πλακέτα την φορά. Copper Top layer is active Το πάνω στρώμα Χαλκού είναι ενεργό Copper Bottom layer is active Το κάτω στρώμα Χαλκού είναι ενεργό Autorouting... Αυτοδρομολόγηση... Autorouting Progress... Πρόοδος Αυτοδρομολόγησης... Remove Bendpoint Αφαίρεση Καμπής Please choose the previous Fritzing folder... Παρακαλώ επιλέξτε τον προηγούμενο φάκελο του Fritzing... You will have to restart Fritzing in order to use the imported parts Θα πρέπει να επανεκκινήσετε το fritzing για να χρησιμοποιήσετε τα εισηγμένα εξαρτήματα Remove copper fill Αφαίρεση γεμίσματος χαλκού &Wire Color &Χρώμα Καλωδίου Launch %1... Εκκίνηση %1... No outdated parts found. All your parts are up-to-date. Δεν βρέθηκαν ξεπερασμένα εξαρτήματα. Όλα τα εξαρτηματά σας είναι ενημερωμένα. Outdated parts Ξεπερασμένα εξαρτήματα Update %1 part(s) Ενημέρωση %1 εξαρτημάτων Successfully updated %1 part(s). Please check all views for potential side-effects. Επιτυχής ενημέρωση %1 εξαρτημάτων. Παρακαλώ ελέξτε όλες τις προβολές για τυχόν λάθη. Inspector Ελεγκτής Undo History Ιστορία Αναίρεσης Breadboard Breadboard Schematic Σχέδιο PCB Τυπωμένο (PCB) Layers Επίπεδα Couldn't get the dock widget Δεν μπόρεσε να γίνει λήψη του widget απόθεσης MazeRouter Autorouter was cancelled. Ο Αυτο-δρομολογητής ακυρώθηκε. best so far: %1 of %2 routed καλύτερο μέχρι τώρα: %1 από %2 δρομολογήθηκε with %n vias με %n οπές με %n οπές round %1 of: γύρος %1 από: Routing stopped! Η δρομολόγηση σταμάτησε! Use best so far... Χρήση καλύτερου μέχρι τώρα... Preparing undo... Προετοιμασία αναίρεσης... Optimizing traces... Βελτιστοποίηση ιχνών... Routing complete! Η δρομολόγηση ολοκληρώθηκε! Routing unsuccessful; stopping at round %1. Ανεπιτυχής δρομολόγηση, στάση στον γύρο %1. Routing reached maximum round %1. Η δρομολόγηση έφτασε στον μέγιστo γύρο %1. Unexpected SVG rendering failure--contact fritzing.org Απροσδόκητη αποτυχία απόδοσης SVG--ενημερώστε στο fritzing.org ModelBase Unable to find the following %n part(s): Αδυναμία εύρεσης των ακόλουθων %n εξαρτημάτων: Αδυναμία εύρεσης των ακόλουθων %n εξαρτημάτων: at στο File save failed! Η αποθήκευση αρχείου απέτυχε! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Αδυναμία αντικατάστασης του αρχείου '%1' Αιτία: %2 (κωδ. σφαλμ. %3) MysteryPart label ετικέτα chip label ετικέτα chip NetLabel net label ετικέτα δικτύου Note [write your note here] [γράψτε την σημείωση σας εδώ] PCBSketchWidget Create Trace from Ratsnest Δημιουργία Ίχνους από Ratsnest Click this connector to drag out a new trace. Κλικ σε αυτόν τον συνδετήρα για να εξάγετε έναν νέο ίχνος. Change trace layer Αλλαγή επιπέδου ίχνους Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποια πλακέτα (PCB) για να χρησιμοποιήσετε αυτή την λειτουργία επιλογής. Please click on a PCB first--this selection operation only works for one board at a time. Παρακαλώ κάντε "κλικ" σε μία πλακέτα (PCB) πρώτα--αυτή η λειτουργία επιλογής λειτουργεί με μία πλακέτα την φορά. Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποιο PCB για να χρησιμοποιήσετε γέμισμα χαλκού. %1 Fill: please select the board you want to apply fill to. %1 Γέμισμα: παρακαλώ επιλέξτε την πλακέτα που θέλετε να εφαρμόσετε το γέμισμα. Ground Γείωση Copper Χαλκός Please designate one or more ground fill seeds before doing a ground fill. Παρακαλώ προσδιορίστε μία ή περισσότερες φύτρες γεμίσματος χαλκού πριν το γέμισμα. Fritzing error: unable to render board svg (1). Σφάλμα Fritzing: Αδυναμία απόδοσης του board.svg(1). Fritzing error: unable to render copper svg (1). Σφάλμα Fritzing: Αδυναμία απόδοσης του copper.svg(1). Fritzing error: unable to write copper fill (1). Σφάλμα Fritzing: Αδυναμία εγγραφής του γεμίσματος χαλκού(1). Fritzing error: unable to write copper fill (2). Σφάλμα Fritzing: Αδυναμία εγγραφής του γεμίσματος χαλκού(2). Copper fill: please select only the board you want to fill. Γέμισμα χαλκού: παρακαλώ επιλέξτε μόνο την πλακέτα που θέλετε να γεμίσετε. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Αδυναμία γεμίσματος χαλκού. Πιθανότατα το εξάρτημα δεν τοποθετήθηκε πάνω στο τυπωμένο (PCB). Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Αδυναμία γεμίσματος χαλκού. Πιθανότατα το εξάρτημα τοποθετήθηκε πάνω κάποιο άλλο εξάρτημα, καλώδιο και όχι στο τυπωμένο (PCB). Clear ground fill seeds Καθαρισμός φυτρών γεμίσματος χαλκού Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Το σχέδιο σας δεν έχει κάποια πλακέτα ακόμη! Παρακαλώ προσθέστε κάποια πλακέτα (PCB) για να χρησιμοποιήσετε αυτή την λειτουργία επιλογής. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Αδυναμία μετατροπής της οπής σε σημείο καμπής διότι είναι συνδεδεμένη σε κάποιο εξάρτημα που είναι μόνο στο κάτω επίπεδο και σε ένα άλλο που είναι μόνο στο πάνω επίπεδο. Show part silkscreen Εμφάνιση μεταξοτυπίας εξαρτήματος Hide part silkscreen Απόκρυψη μεταξοτυπίας εξαρτήματος Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Το σχέδιο σας δεν έχει πλακέτα ακόμη. Δεν μπορείτε να κατασκευάσετε αυτό το σχέδιο χωρίς τυπωμένο (PCB). Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Εισαγωγή Ορίου Ασφαλείας Keepout is in mils (.001 inches). Όριο Ασφαλείας σε mil (.0001 ίντσες). Note that due to aliasing, distances may be too short by up to 2 mils Σημείωστε πως λόγο της ομαλοποίησης (aliasing), οι αποστάσεις μπορεί να είναι μικρότερες μέχρι και 2 mils so you may want to increase the keepout value by that much. οπότε ίσως θέλετε να αυξήσετε το όριο ασφαλείας κατά αυτό το ποσό. 10 mils is a good default choice. 10 mils είναι μία καλή προεπιλογή. Enter keepout value: Εισάγετε την τιμή του ορίου ασφαλείας: PEConnectorsView This is where you edit the connector metadata for the part Εδώ τροποποιείτε τα μετα-δεδομένα του συνδετήρα για το εξάρτημα number of connectors: Αριθμός συνδετήρων: Through-hole Μέσω-οπής (Through-hole) SMD SMD PEMainWindow Parts Editor Επεξεργαστής Εξαρτημάτων SVG SVG There is one last edit still pending. Εκκρεμεί μία τελευταία επεξεργασία. Duplicate 'family' property not allowed Δεν επιτρέπεται διπλότυπη ιδιότητα 'οικογένειας' Duplicate 'variant' property not allowed Δεν επιτρέπεται διπλότυπη ιδιότητα 'παραλλαγή' Close without saving? Κλείσιμο χωρίς αποθήκευση; Close without saving Κλείσιμο χωρίς αποθήκευση Keep working Συνέχιση εργασίας Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Η έξοδος από τον επεξεργαστή Εξαρτημάτων είναι εντάξει, αρκεί να θυμηθείτε να τελειώσετε την εργασία αργότερα. Icon Εικονίδιο Metadata Μεταδεδομένα Connectors Συνδετήρες Show in Folder Εμφάνιση σε Φάκελο On the desktop, open the folder containing the current svg file. Στην επιφάνεια εργασίας, ανοίξτε τον φάκελο που περιέχει το τρέχον svg αρχείο. Remove Internal Connection Αφαίρεση Εσωτερικής Σύνδεσης Unable to write svg to %1 Αδυναμία εγγραφής svg στο %1 Unable to parse fzp file %1 Αδυναμία ανάλυσης του fzp αρχείου %1 Icon View Προβολή εικονιδίων Metadata View Προβολή μεταδεδομένων Connectors View Προβολή συνδετήρων Show Icon Εμφάνιση Εικονιδίου Ctrl+4 Ctrl+4 Show the icon view Εμφανίζει την προβολή σε εικονίδια Ctrl+5 Ctrl+5 Show the metadata view Εμφάνιση της προβολής μεταδεδομένων Show Connectors Εμφάνιση Συνδετήρων Ctrl+6 Ctrl+6 Change %1 to '%2' Αλλαγή %1 σε '%2' Change description Αλλαγή περιγραφής Change tags Αλλαγή ετικετών Change properties Αλλαγή ιδιοτήτων Change connector %1 Αλλαγή συνδετήρα %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Αρχεία Εικόνας & Footprint (%1 %2 %3 %4 %5);;Αρχεία SVG (%1);;Αρχεία JPEG (%2);;Αρχεία PNG (%3);;Αρχεία gEDA Footprint (%4);;Αρχεία Αρθρωμάτων Kicad(%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Αρχεία Εικόνας (%1 %2 %3);;Αρχεία SVG (%1);;Αρχεία JPEG (%2);;Αρχεία PNG (%3)%4%5 Open Image Άνοιγμα Εικόνας Copy problem Πρόβλημα αντιγραφής Unable to make a local copy of: '%1' Αδυναμία δημιουργίας τοπικού αντιγράφου του '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. Μπορείτε να χρησιμοποιήσετε ένα αρχείο PNG ή JPG για να κατασκευάσετε το εξάρτημά σας, αλλά είναι καλύτερα να χρησιμοποιήσετε ένα SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- Οι PNG και JPG εικόνες δεν εμφανίζονται όμορφα όταν αλλάζουν διαστάσεις-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. έτσι για εξαρτήματα του Fritzing είναι καλύτερα να χρησιμοποιείτε PNG και JPG μόνο ως δείκτες τοποθέτησης. Use of PNG and JPG discouraged Η χρήση PNG και JPG δεν ενδείκνυται Conversion problem Πρόβλημα Μετατροπής Fritzing (New) Parts Editor Επεξεργαστής Εξαρτημάτων (Νέος) του Fritzing Show Metadata Εμφάνιση Μεταδεδομένων Show the connector metadata in a list view Εμφάνιση μεταδεδομένων του συνδετήρα σε μορφή λίστας Blank not allowed Δεν επιτρέπονται τα κενά The value of '%1' can not be blank. Η τιμή του '%1' δεν μπορεί να είναι κενή. Change %1 to %2 Αλλαγή του %1 σε %2 Must be unique Πρέπει να είναι μοναδικό Variant '%1' is in use. The variant name must be unique. Η παραλλαγή '%1' είναι σε χρήση. Το όνομα πρέπει να είναι μοναδικό. Duplicate problem Πρόβλημα διπλότυπου Unable to load '%1' Αδυναμία φόρτωσης του '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Το SVG αρχείο '%1' μοίαζει να έχει εξαχθεί από το CorelDRAW χωρίς να έχει επιλεγεί η ρύθμιση 'presentation attributes'. Please re-export the SVG file using that setting, and try loading again. Παρακαλώ ξανα εξάγετε το SVG αρχείο χρησιμοποιώντας την ρύθμιση αυτή. Fonts Γραμματοσειρά Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Το Fritzing αυτή την στιγμή υποστηρίζει μόνο OCRA και Droid γραμματοσειρές--αυτέςέχουν υποκαθίσταθεί για τις γραμματοσειρές στο '%1' Unable to load image file '%1': %2 Αδυναμία φόρτωσης του αρχείου εικόνας '%1': %2 SVG problem Πρόβλημα SVG The 'family' property can not be blank. Η ιδιότητα 'οικογένεια' δεν μπορεί να είναι κενή. A duplicate 'family' property is not allowed Μία διπλότυπη ιδιότητα 'οικογένεια' δεν επιτρέπεται A duplicate 'variant' property is not allowed Μία διπλότυπη ιδιότητα 'παραλλαγή' δεν επιτρέπεται This part can not be saved as-is: Αυτό το εξάρτημα δεν μπορεί να σωθεί ως είναι: Do you want to keep working or close without saving? Θέλετε να συνεχίσετε να εργάζεστε ή κλείσιμο χωρίς αποθήκευση; This part has %n unassigned connectors Αυτό το εξάρτημα έχει %n ασύνδετους συνδετήρες Αυτό το εξάρτημα έχει %n ασύνδετους συνδετήρες across %n views. διά μέσου %n προβολών. διά μέσου %n προβολών. Until all connectors are assigned to SVG elements, the part will not work correctly. Μέχρι όλοι οι συνδετήρες να ανατεθούν σε SVG στοιχεία, το εξάρτημα δεν θα λειτουργεί σωστά. Layers Επίπεδα Reuse breadboard image Επαναχρησιμοποίηση εικόνας breadboard Reuse the breadboard image in this view Επαναχρησιμοποίηση εικόνας breadboard σε αυτή την προβολή Reuse schematic image Επαναχρησιμοποίηση εικόνας σχεδίου Reuse the schematic image in this view Επαναχρησιμοποίηση εικόνας σχεδίου σε αυτή την προβολή Reuse PCB image Επαναχρησιμοποίηση εικόνας PCB Reuse the PCB image in this view Επαναχρησιμοποίηση εικόνας PCB σε αυτή την προβολή Make only this view visible Κάνε μόνο αυτή την προβολή ορατή The part will only be visible in this view and icon view Το εξάρτημα θα είναι ορατό μόνο σε αυτή την προβολή και προβολή εικονιδίων This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. Αυτή η έκδοση του νέου επεξεργαστή εξαρτημάτων δεν μπορεί να αντιμετωπίσει ξεχωριστά επίπεδα copper0 και copper1 στο '%1'. So editing may produce an invalid PCB view image Έτσι η επεξεργασία ίσως παράξει μία μη έγκυρη προβολή εικόνας PCB Unable to parse '%1': %2 line:%3 column:%4 Αδυναμία ανάλυσης '%1': %2 γραμμή:%3 στήλη:%4 There are no copper layers defined in: %1. Δεν υπάρχουν καθορισμένα επίπεδα χαλκού στο: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. Δείτε <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">αυτή την εξήγηση</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>Αυτό δεν θα είναι πρόβλημα στην επόμενη έκδοση του Επεξεργαστή Εξαρτημάτων, but for now please modify the file according to the instructions in the link. αλλά για τώρα παρακαλώ τροποποιήστε το αρχείο σύμφωνα με τις οδηγίες στον σύνδεσμο. no schematics found in %1 δεν βρέθηκε σχηματικό στο %1 schematic part σχηματικό εξαρτήματος no footprints found in %1 δεν βρέθηκε footprint στο %1 Relocate connector %1 Επανεντοπισμός συνδετήρα %1 &File &Αρχείο Inspector Ελεγκτής Load image for view... Φόρτωση εικόνας για προβολή... Open a file to use as the image for this view of the part. Άνοιγμα αρχείου για χρήση ως εικόνα για αυτή την προβολή του εξαρτήματος. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Αποθήκευση ως νέου εξαρτήματος Make a copy of the part and save it in the 'My Parts' Bin Πραγματοποίηση αντιγράφου από το εξάρτημα και αποθήκευση στο Δοχείο 'Εξαρτήματά μου' &Export &Εξαγωγή &Edit &Επεξεργασία This part has bendable legs. Αυτό το εξάρτημα έχει εύκαμπτα πόδια. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . Αυτή η έκδοση του Επεξεργαστή Εξαρτημάτων δεν υποστηρίζει ακόμη επεξεργασία εύκαμπτων ποδιών, και τα πόδια ίσως να μην προβάλλονται σωστά στην προβολή breadboard . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. Αν πραγματοποιήσετε αλλαγές στην προβολή breadboard, ή αλλάξετε τα μεταδεδομένα, τα πόδια ίσως πλέον δεν λειτουργούν. You can safely make changes to Schematic or PCB view. Μπορείτε με ασφάλεια να πραγματοποιήσετε αλλαγές στην προβολή Σχηματικού ή PCB. This warning will not be repeated in this session of Fritzing Αυτή η προειδοποίηση δεν θα επαναληφθεί σε αυτή την συνεδρία του Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Αδυναμία φόρτωσης '%1'. Παρακαλώ κλείστε τον επεξεργαστή εξαρτημάτων χωρίς αποθήκευση και προσπαθήστε πάλι. Unable to load image file '%1' Αδυναμία φόρτωσης του αρχείου εικόνας %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning Προειδοποίηση Αλλαγής Σχεδίου The open sketch '%1' uses the part you are editing. Το ανοικτό σχέδιο '%1' χρησιμοποιεί τα εξαρτήματα που επεξεργάζεστε. Saving this part will make a change to the sketch that cannot be undone. Η αποθήκευση αυτού του εξαρτήματος θα δημιουργήσει αλλαγές στο σχέδιο που δεν μπορούν να αναιρεθούν. The open sketches Τα ανοικτά σχέδια '%1', '%1', and '%1' και '%1' Saving this part will make a change to these sketches that cannot be undone. Η αποθήκευση αυτού του εξαρτήματος θα δημιουργήσει αλλαγές σε αυτλα τα σχέδια που δεν μπορούν να αναιρεθούν. Go ahead and save? Συνέχιση και αποθήκευση; Save Αποθήκευση Cancel Ακύρωση Move terminal point Μετακίνηση τερματικού σημείου Remove connector Αφαίρεση συνδετήρα Remove %1 connectors Αφαίρεση %1 συνδετήρων Save "%1" Αποθήκευση "%1" Do you want to save the changes you made in the part "%1"? Θέλετε να αποθηκεύσετε τις αλλαγές που κάνατε στο εξάρτημα "%1"; Your changes will be lost if you don't save them. Οι αλλαγές σας θα χαθούν αν δεν τις αποθηκεύσετε. untitled part εξάρτημα χωρίς τίτλο Unable to load fzp from %1 Αδυναμία φόρτωσης του fzp από %1 Unable to create new connector--you may have to start over. Αδυναμία δημιουργίας νέου συνδετήρα--ίσως χρειαστεί να ξαναρχίσετε. Add connector Προσθήκη συνδετήρα Add %1 connectors Προσθήκη %1 συνδετήρων Remove internal connection from '%1' Αφαίρεση εσωτερικών συνδέσεων από '%1' Change all connectors to %1 Αλλαγή όλλων των συνδετήρων σε %1 Unable to parse '%1' Αδυναμία ανάλυσης του '%1' Change to %1 Αλλαγή σε %1 Make only %1 view visible Κάνε μόνο την προβολή %1 ορατή Internal connections are very messed up. Οι εσωτερικές συνδέσεις είναι πολύ μπερδεμένες. Add internal connection from '%1' to '%2' Προσθήκη εσωτερικής σύνδεσης από '%1' σε '%2' PEMetadataView This is where you edit the metadata for the part ... Εδώ τροποποιείτε τα μετα-δεδομένα για το εξάρτημα ... Set the part's title Επιλέξτε τον τίτλο του εξαρτήματος Title Τίτλος Set the part's date Επιλέξτε την ημερομηνία του εξαρτήματος Date Ημερομηνία Set the part's author Επιλέξτε τον δημιουργό του εξαρτήματος Author Συγγραφέας Set the part's description--you can use simple html (as defined by Qt's Rich Text) Επιλέξτε την περιγραφή του εξαρτήματος--μπορείτε να χρησιμοποιήσετε απλή html (όπως καθορίζεται από το Qt's Rich Text) Description Περιγραφή Set the default part label prefix Επιλέξτε το προκαθορισμένο πρόθεμα για την ετικέτα Label Ετικέτα Set the part's url if it is described on a web page Επιλέξτε τον σύνδεσμο για το εξάρτημα αν αυτό περιγράφεται σε κάποια ιστοσελίδα URL URL Set the part's family--what other parts is this part related to Επιλέξτε την οικογένεια του εξαρτήματος--με τι άλλα εξαρτήματα σχετίζεται Family Οικογένεια Set the part's variant--this makes it unique from all other parts in the same family Επιλέξτε την παραλλαγή του εξαρτήματος--αυτό το καθιστά μοναδικό από όλα τα άλλα εξαρτήματα στην ίδια οικογένεια Variant Παραλλαγή Set the part's properties Επιλέξτε τις ιδιότητες του εξαρτήματος Properties Ιδιότητες Set the part's tags Επιλέξτε τις ετικέτες του εξαρτήματος Tags Ετικέτες PESvgView width: πλάτος: height: ύψος: PEToolView Set Internal Connections Επιλογή Εσωτερικών Συνδέσεων Set this checkbox to edit internal connections by drawing wires Επιλέξτε αυτό το κουτί για να επεξεργαστείτε εσωτερικές συνδέσεις σχεδιάζοντας καλώδια Connector List (a checkmark means the graphic was selected) Λίστα Συνδετήρων (ένα σημάδι ελέγχου σημαίνει πως το γραφικό έχει επιλεχθεί) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Χειριστήρια για την ρύθμιση των τερματικών σημείων των συνδετήρων. Τερματικά σημεία είναι τα σημεία που τα καλώδια ενώνονται με τον συνδετήρα Center Κέντρο N Β E Α S Ν W Δ center κέντρο west δύση north βοράς south νότος east ανατολή Sets the connector's terminal point to %1. Ρυθμίζει το τερματικό σημείο του συνδετήρα σε %1. Modifies the x-coordinate of the terminal point Τροποποιεί την x-συντενταγμένη του τερματικού σημείου Modifies the y-coordinate of the terminal point Τροποποιεί την y-συντενταγμένη του τερματικού σημείου Dragging disabled Το σύρσιμο είναι απενεργοποιημένο <font color='black'>Dragging enabled</font> <font color='black'>Το σύρσιμο είναι ενεργοποιημένο</font> <font color='gray'>Dragging disabled</font> <font color='black'>Το σύρσιμο είναι απενεργοποιημένο</font> Connector %1 Συνδετήρας %1 Select graphic Επιλογή γραφικού Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Χρησιμοποιείστε την τοποθεσία του κέρσορα και τον τροχό του ποντικιού για να περιηγηθείτε στο SVG στοιχείο που θέλετε να αναθέσετε στον τρέχοντα συνδετήρα, και μετά με κλικ το επιλέγετε. Pad shape σχήμα center κέντρο north βοράς east ανατολή south νότος west δύση connect to σύνδεση σε PaletteItem Edit Pin Labels Επεξεργασία Ετικέτας Ακίδων Fritzing Fritzing Unable to proceed; unable to find top level view. Αδυναμία να συνεχιστεί, αδυναμία εύρεσης προβολής πάνω επιπέδου. Unable to proceed; part connectors do no have standard IDs. Αδυναμία να συνεχιστεί, οι συνδετήρες των εξαρτημάτων δεν έχουν πρότυπα IDs. Label mismatch. Nothing was saved. Αναντιστοιχία ετικέτας. Δεν αποθηκεύτηκε τίποτε. hole size μέγεθος οπής advanced settings προχωρημένες ρυθμίσεις in in mm mm Hole Diameter Διάμετρος Οπής Ring Thickness Πάχος Δακτυλίου PartLabel Edit Επεξεργασία Edit label text Επεξεργασία ετικέτας κειμένου Hide Απόκρυψη Hide part label Απόκρυψη ετικέτας εξαρτήματος Display Values Προβολή Τιμών Flip/Rotate Αναστροφή/Περιστροφή Font Size Μέγεθος Γραμματοσειράς Rotate the label by 45 degrees clockwise Περιστρέφει την ετικέτα 45 μοίρες δεξιόστροφα Rotate the label by 90 degrees clockwise Περιστρέφει την ετικέτα 90 μοίρες δεξιόστροφα Rotate the label by 135 degrees clockwise Περιστρέφει την ετικέτα 135 μοίρες δεξιόστροφα Rotate the label by 180 degrees Περιστρέφει την ετικέτα 135 μοίρες Rotate the label by 135 degrees counter clockwise Περιστρέφει την ετικέτα 135 μοίρες αριστερόστροφα Rotate current selection 90 degrees counter clockwise Περιστρέφει την ετικέτα 90 μοίρες αριστερόστροφα Rotate 45� Clockwise Περιστροφή 135° Δεξιόστροφα {45�?} Rotate 90� Clockwise Περιστροφή 135° Δεξιόστροφα {90�?} Rotate 135� Clockwise Περιστροφή 135° Δεξιόστροφα {135�?} Rotate 180� Περιστροφή 180° {180�?} Rotate 135� Counter Clockwise Περιστροφή 45° Αριστερόστροφα {135�?} Rotate 90� Counter Clockwise Περιστροφή 45° Αριστερόστροφα {90�?} Rotate 45� Counter Clockwise Περιστροφή 45° Αριστερόστροφα {45�?} Rotate the label by 45 degrees counter clockwise Περιστρέφει την ετικέτα 45 μοίρες αριστερόστροφα Flip Horizontal Οριζόντια Ανατροπή Flip label horizontally Ανατρέπει την ετικέτα οριζόντια Flip Vertical Κάθετη Ανατροπή Flip label vertically Ανατρέπει την ετικέτα κάθετα Tiny Πολύ Μικρό Set font size to tiny Ρύθμιση γραμματοσειράς σε πολύ μικρό μέγεθος Small Μικρό Set font size to small Ρύθμιση γραμματοσειράς σε μικρό μέγεθος Medium Μεσαίο Set font size to medium Ρύθμιση γραμματοσειράς σε μεσαίο μέγεθος Large Μεγάλο Set font size to large Ρύθμιση γραμματοσειράς σε μεγάλο μέγεθος Label text Κείμενο ετικέτας Display the text of the label Εμφανίζει το κείμενο της ετικέτας Display the value of property %1 Εμφανίζει την τιμή της ιδιότητας %1 Set label for %1 Ρύθμιση τιμής για %1 Label text: Κείμενο ετικέτας: PartsBinPaletteWidget Untitled Bin Ανώνυμο Δοχείο Save Αποθήκευση Specify a file name Προσδιορίστε ένα όνομα αρχείου Fritzing Bin (*%1) Δοχείο Fritzing (*%1) Fritzing Fritzing Cannot find file %1. Αδυναμία εύρεσης του αρχείου %1. Cannot read file %1: %2. Αδυναμία ανάγνωσης του αρχείου:%1: %2. Loading... Φόρτωση... loading bin '%1' φόρτωση δοχείου '%1' Save bin "%1" Αποθήκευση δοχείου "%1" Do you want to save the changes you made in the bin "%1"? Θέλετε να αποθηκεύσετε τις αλλαγές που κάνατε στο δοχείο "%1"; Your changes will be lost if you don't save them. Οι αλλαγές σας θα χαθούν αν δεν τις αποθηκεύσετε. Don't Save Όχι Αποθήκευση Ctrl+D Ctrl+D Cancel Ακύρωση Add to bin Προσθήκη στο δοχείο Do you really want to add the selected part to the bin? Θέλετε πραγματικά να προσθέσετε το επιλεγμένο εξάρτημα στο δοχείο; Change icon color... Αλλαγή χρώματος εικονιδίου... Change the color of the icon for this bin. Αλλάζει το χρώμα του εικονιδίου για αυτό το δοχείο. Select a color for this icon Επιλέξτε ένα χρώμα για αυτό το εικονίδιο Perfboard size μέγεθος set board size ρύθμιση μεγέθους της πλακέτας Performance Warning Προειδοποίηση Επίδοσης Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Η επίδοση για perfboards και striboard (διάτρητες πλακέτες) με περισσότερες από 2000 οπές μπορεί να είναι αργή. Είστε σίγουρος; Σημείωση: Αυτή η προειδοποίηση δεν θα επαναληφθεί κατά την διάρκεια της συνεδρίας. Set new size Ρύθμιση νέου μεγέθους Cancel Ακύρωση rows σειρές columns στήλες PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Επεξεργαστής Ετικετών Ακίδων</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Κάντε "κλικ" σε μία ετικέτα δίπλα στον αριθμό κάποιας ακίδα για να μετονομάσετε την ακίδα. You can use the tab key to move through the labels in order.</p> Μπορείτε να χρησιμοποιήσετε το πλήκτρο tab για να αλλάζετε μεταξύ των ετικετών με σειρά.</p> Cancel Ακύρωση Save Αποθήκευση Undo Αναίρεση Redo Επανάληψη PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Γενικά Cancel Ακύρωση OK Εντάξει Mouse Wheel Behavior Συμπεριφορά Ροδέλας Ποντικιού Command Εντολή Control Έλεγχος Change Wheel Behavior Αλλαγή Συμπεριφοράς Ροδέλας Code View Autosave Αυτόματη Αποθήκευση Autosave every: Αυτόματη Αποθήκευση κάθε: minutes λεπτά Language Γλώσσα Colors Χρώματα %1 (click to change...) %1 ("κλικ" για αλλαγή...) Clear Settings Καθαρισμός Ρυθμίσεων Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Επιλέξτε έναν προγραμματιστή (εκτελέσιμο) για το %1 Connected Highlight Επισήμανση Συνδεδεμένου Unconnected Highlight Επισήμανση μη Συνδεδεμένου no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom κανένα πάτημα πλήκτρου = κύλιση Το Shift ανταλλάσσει τους άξονες κύλισης Το Alt ή το %1 = μεγέθυνση no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis κανένα πάτημα πλήκτρου = μεγέθυνση Το Alt ή το %1 = κύλιση Το Shift ανταλλάσσει τους άξονες κύλισης Curvy vs. straight wires Καμπυλωτά ή ευθύγραμμα καλώδια When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? Όταν πατάτε το ποντίκι και σύρετε πάνω σε ένα καλώδιο ή στο πόδι ενός εξαρτήματος (σε αντίθεση με έναν συνδετήρα ή σημείο καμπής) θέλετε να αλλάζει η καμπύλη ή να δημιουργείται ένα νέο σημείο καμπής; This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Το κουτί επιλογής θέτει την προκαθορισμένη συμπεριφορά. Μπορείτε να επιστρέψετε στην μη προκαθορισμένη συμπεριφορά κρατώντας το πλήκτρο Control (πλήκτρο Command για Mac) όταν σύρετε. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Νέο Save Αποθήκευση Open Platform Board Πλακέτα Port Serial Monitor Upload Select a program file to load Επιλογή προγράμματος προς φόρτωση Fritzing is unable to find '%1', please locate it Το Fritzing δεν μπόρεσε να βρει το '%1', παρακαλώ εντοπίστε το Code (*.%1) Κώδικας (*.%1) Remove "%1"? Αφαίρεση του "%1"; Are you sure you want to remove "%1" from the sketch? Είστε σίγουρος πως θέλετε να αφαιρέσετε το "%1" από το σχέδιο; No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit &Επεξεργασία Undo Αναίρεση Redo Επανάληψη &Cut &Αποκοπή Cut selection Αποκοπή επιλογής &Copy &Αντιγραφή Copy selection Αντιγράφει το επιλεγμένο &Paste &Επικόλληση Paste clipboard contents Επικόλληση των περιεχομένων του πρόχειρου &Select All &Επιλογή Όλων Select all text Επιλέγει όλο το κείμενο &Preferences... &Επιλογές... Show the application's about box Εμφανίζει πληροφορίες για την εφαρμογή &Code &Κώδικας &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Πλακέτα Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Παράθυρο Κώδικα Code Window - %1 Παράθυρο Κώδικα - %1 %1%2 %1%2 &View &Προβολή File '%1' was restored from the .fzz file; the local copy was not found. Το αρχείο '%1' αποκαταστάθηκε από το .fzz αρχείο, το τοπικό αρχείο δεν βρέθηκε. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Το αρχείο '%1' αποκαταστάθηκε από το .fzz αρχείο, αποθηκεύστε ένα τοπικό αρχείο για να εργαστείτε με έναν εξωτερικό επεξεργαστή κειμένου. QObject Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found Αδυναμία αυτοδρομολόγησης: δεν βρέθηκε πλακέτα (ή πλακέτες) No connections (on the PCB) to route. Δεν υπάρχουν συνδέσεις (στο PCB) για δρομολόγιση. No connections to route. Δεν υπάρχουν συνδέσεις για δρομολόγιση. Preferences Επιλογές Please note that a new language setting will not take effect until the next time you run Fritzing. Μία νέα ρύθμιση της γλώσσας θα ενεργοποιηθεί την επόμενη φορά που θα εκτελέσετε το Fritzing. Connected highlight color Χρώμα επισήμανσης συνδεδεμένων Unconnected highlight color Χρώμα επισήμανσης ασύνδετων Clear all saved settings and close this dialog immediately. Καθαρισμός όλων των αποθηκευμένων ρυθμίσεων και κλείσιμο αυτού του διαλόγου. This action does not delete any files; it restores settings to their default values. Αυτή η ενέργεια δεν διαγράφει αρχεία, επαναφέρει τις ρυθμίσεις στις προεπιλεγμένες τιμές. There is no undo for this action, and no further warning!!!! Δεν υπάρχει αναίρεση για αυτή την ενέργεια, και καμιά περαιτέρω προειδοποίηση!!! Clear Settings Καθαρισμός Ρυθμίσεων <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Το αρχείο '%1' είναι μόνο για ανάγνωση, παρακαλώ χρησιμοποιήστε ένα άλλο όνομα αρχείου. Edit link Επεξεργασία συνδέσμου Part Εξάρτημα Wire Καλώδιο Set Grid Size Ρύθμιση Μεγέθους Πλέγματος Cannot read file %1: %2. Αδυναμία ανάγνωσης του αρχείου:%1: %2. Parse error (1) at line %1, column %2: %3 %4 Σφάλμα συντακτικής ανάλυσης (1) στην γραμμή %1, στήλη %2: %3 %4 The file %1 is not a Fritzing file (2). Το αρχείο %1 δεν είναι ένα αρχείο Fritzing (2). The file %1 is not a Fritzing file (4). Το αρχείο %1 δεν είναι ένα αρχείο Fritzing (4). The file %1 is not a Fritzing file (3). Το αρχείο %1 δεν είναι ένα αρχείο Fritzing (3). Cannot write file temp: %1 %2 %3. Αδυναμία εγγραφής προσωρινού αρχείου: %1 %2 %3. Parts folder not found. Δεν βρέθηκε ο φάκελος των εξαρτημάτων. No parts found. Δεν βρέθηκαν εξαρτήματα. Parse error (2) at line %1, column %2: %3 %4 Σφάλμα συντακτικής ανάλυσης (1) στην γραμμή %1, στήλη %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Το εξάρτημα '%1' στο '%2' δεν έχει μία μοναδική ταυτότητα αρθρώματος '%3'. Basic Βασικά Input Είσοδος Output Έξοδος ICs ICs Power Πηγές Connection Συνδέσεις Microcontroller Μικροελεγκτές Breadboard View Προβολή Breadboar Schematic View Προβολή Σχηματικού PCB View Προβολή Τυπωμένου (PCB) Tools Εργαλεία Shields Ασπίδες LilyPad LilyPad Other Άλλα Sensors Αισθητήρες Part already in bin Εξάτημα ήδη στο δοχείο The part that you have just added, is already there, we won't add it again, right? Το εξάρτημα που μόλις προσθέσατε, υπάρχει, δεν θα το προσθέσουμε πάλι, εντάξει; a label μία ετικέτα a value μία τιμή Select %1 Επιλογή %1 files αρχεία Oops! Όοπα! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Συγνώμη, έχουμε κάποιο πρόβλημα με τον μηχανισμό ανταλλαγής. Το Fritzing λειτουργεί ακόμη, αλλά δεν θα μπορείτε να αλλάξετε τις ιδιότητες εξαρτημάτων. bb bb pcb pcb Select all 'Don't autoroute' traces Επιλογή Όλων "Μην Αυτοδρομολογείς" τα Ίχνη Select all autorouteable traces Επιλογή Όλων των Αυτοδρομολογούμενων Ιχνών Convert to Via Μετατροπή σε Οπή Convert Via to Bendpoint Μετατροπή Οπής σε Σημείο Καμπής schem schem Error reading file %1: %2. Σφάλμα ανάγνωσης αρχείου %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Αλλαγή στο πόδι του %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer %1 Επίπεδο Bring forward Μεταφορά προς τα Εμπρός Send backward Μεταφορά προς τα Πίσω Bring to front Μεταφορά Εμπρός Split Wire Διαχωρισμός Καλωδίου Join Wire Ένωση Καλωδίου Trace wires Ιχνηλάτηση καλωδίων Ratsnest wires Καλώδια Ratsnest Select all %1 Επιλογή Όλων των %1 Select outdated parts Επιλογή ξεπερασμένων εξαρτημάτων Select locked parts Επιλογή κλειδωμένων εξαρτημάτων unable to open %1 αδυναμία ανοίγματος του '%1' unable to parse %1 αδυναμία συντακτικής ανάλυσης του %1 parse failure in %1 σφάλμα συντακτικής ανάλυσης στο %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Συγνώμη, το Fritzing δεν μπορεί ακόμη να χειριστεί μαζί ακίδες (pins) και επιθέματα (pads) (στο %1) bad pin argument count λάθος όρισμα στην αρίθμηση ακίδας (pin) bad pad argument count λάθος όρισμα στην αρίθμηση επιθέματος (pad) Unable to parse copper: %1 %2 %3 Αδυναμία ανάλυσης χαλκού: %1 %2 %3 footprint %1 not found in %2 δεν βρέθηκε το footprint %1 στο %2 unexpected end of file in footprint %1 in file %2 απροσδόκητο τέλος αρχείου του footprint %1 στο αρχείο %2 unexpected format (1) in %1 from %2 απροσδόκητη μορφή (1) στο %1 από το %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Συγνώμη, το Fritzing δεν μπορεί ακόμη να χειριστεί μαζί ακίδες (pins) και επιθέματα (pads) (στο %1 στο %2) unexpected end of file απροσδόκητο τέλος αρχείου pad missing drill απών τρυπάνι (drill) από το επίθεμα (pad) pad missing attributes απόντα χαρακτηριστικά από το επίθεμα (pad) pad missing position απούσα θέση από το επίθεμα (pad) pad missing shape απών σχήμα από το επίθεμα (pad) position missing params απούσα παράμετρος από την θέση drill missing params απούσα παράμετρος από το τρυπάνι (drill) drill offset not implemented δεν έχει γίνει αντιστάθμιση (offset) τρυπανιού drill missing ellipse params απούσα παράμετρος έλλειψης από το τρυπάνι (drill) attributes missing params απόντες παράμετροι από τα χαρακτηριστικά bad layer mask parameter λάθος παράμετρος μάσκας επιπέδου Sorry, can't handle pad type %1 Συγνώμη, δεν μπορεί να γίνει χειρισμός του τύπου επιθέματος (pad) %1 pad shape missing params απόντες παράμετροι από το σχήμα επιθέματος (pad) pad shape size is invalid λάθος μέγεθος στο σχήμα επιθέματος (pad) trapezoidal pads not implemented δεν υποστηρίζονται τραπεζοειδή επιθέματα (pads) shape delta not implemented δεν υποστηρίζονται σχήματα δέλτα non-circular holes not implemented δεν υποστηρίζονται μη κυκλικές οπές non-copper holes not implemented δεν υποστηρίζονται μη χάλκινες οπές unable to handle pad shape %1 αδυναμία χειρισμού σχήματος επιθέματος (pad) %1 bad schematic definition %1 λάθος προσδιορισμός σχηματικού %1 schematic part %1 not found in %2 το εξάρτημα σχηματικού %1 δεν βρέθηκε στο %2 schematic %1 unexpectedly ends (1) in %2 αναπάντεχο τέλος (1) σχηματικού %1 στο %2 schematic %1 unexpectedly ends (2) in %2 αναπάντεχο τέλος (2) σχηματικού %1 στο %2 schematic %1 unexpectedly ends (3) in %2 αναπάντεχο τέλος (3) σχηματικού %1 στο %2 failure in svg conversion 1: %1 %2 %3 σφάλμα στην svg μετατροπή 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 σφάλμα στην svg μετατροπή 2: %1 %2 %3 File Progress... Πρόοδος Αρχείου... Copying file %1 Αντιγραφή αρχείου %1 File %1 already exists: it won't be overwritten Το αρχείο %1 υπάρχει: δεν θα αντικατασταθεί Check for updates Έλεγχος για ενημερώσεις icon view προβολή εικονιδίων breadboard view προβολή breadboar schematic view προβολή σχηματικού pcb view προβολή τυπωμένου (PCB) Icon Εικονίδιο Breadboard Breadboard Parts Εξαρτήματα Wires Καλώδια Part Labels Ετικέτες Εξαρτήματος Ratsnest Ratsnest Notes Σημειώσεις Rulers Κανόνες Frame Πλαίσιο Text Κείμενο Board Πλακέτα Silkscreen Top Πάνω Μεταξοτυπία Silkscreen Top (Part Labels) Copper Fill Bottom Κάτω Γέμισμα Χαλκού Copper Fill Top Πάνω Γέμισμα Χαλκού Copper Bottom Κάτω Χαλκός Copper Bottom Trace Ίχνος Κάτω Χαλκού Copper Top Πάνω Χαλκός Copper Top Trace Ίχνος Πάνω Χαλκού Silkscreen Bottom Κάτω Μεταξοτυπία Silkscreen Bottom (Part Labels) Κάτω Μεταξοτυπία (Ετικέτες Εξαρτήματος) Part Image Εικόνα Εξαρτήματος Unknown Layer Άγνωστο Επίπεδο outline is empty η διαγράμμιση είναι κενή the board outline layer, επίπεδο της διαγράμμισης της πλακέτας silkscreen layer(s), στρώμα(τα) μεταξοτυπίας, copper layer(s), στρώμα(τα) χαλκού, mask layer(s), στρώμα(τα) μάσκας, paste mask layer(s), επικόληση επιπέδου(ων) μάσκας Unable to translate svg curves in %1 Αδυναμία ,μετάφρασης των καμπύλων svg σε %1 %1 layer export is empty. Το %1 επίπεδο εξαγωγής είναι άδειο. exported drill file is empty το εξαγόμενο αρχείο διάτρησης είναι άδειο exported mask layer %1 is empty η εξαγόμενη μάσκα επιπέδου %1 είναι άδεια exported paste mask layer is empty η εξαγώμενη μάσκα πάστας είναι άδεια %1 layer: unable to save to '%2' Επίπεδο %1: αδυναμία αποθήκευσης σε '%2' Unable to save pick and place file: %2 Αδυναμία αποθήκευσης του αρχείου 'pick and place': %2 silk export failure αποτυχία εξαγωγής μεταξοτυπίας %1 layer export is empty (case 2). Το %1 επίπεδο εξαγωγής είναι άδειο (case 2). silk layer %1 export is empty drill export failure αποτυχία εξαγωγής τρυπανιού %1 mask export failure (2) %1 αποτυχία εξαγωγής μάσκας (2) Fritzing is unable to process the cutouts in this custom PCB shape. Το Fritzing αδυνατεί να επεξεργαστεί τις εκτομές σε αυτό το PCB. You may need to reload the shape SVG. Ίσως χριαστεί να ξανα-φορτώσετε το SVG του σχήματος. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Το Fritzing απαιτεί να κάνετε τις εκτομές χρησιμοποιώντας μία διαδικασία 'αφαίρεσης' ή 'διαφοράς' ενός σχήματος στον επεξεργαστή γραφικών ανυσμάτων. mask export failure αποτυχία εξαγωγής μάσκας Pin Label Editor Επεξεργαστής Ετικέτας Ακίδας (pin) mm mm in σε Set Ground Fill Seed Καθορίστε Φύτρες Γεμίσματος Γείωσης Ground Fill Seed Editor Επεξεργαστής φυτρών Γεμίσματος Γείωσης unable to copy file '%1' to '%2'. αδυναμία αντιγραφής αρχείου '%1' στο '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. %1 καλώδια μετακινήθηκαν από την αποθηκευμένη θέση τους στη %2. ii ii Icon View προβολή εικονιδίων Internal Connections Εσωτερικές Συνδέσεις <b>id:</b> <b>id:</b> <b>Name:</b> <b>Όνομα:</b> Set the connectors's title Επιλέξτε τον τίτλο των συνδετήρων <b>type:</b> <b>τύπος:</b> <b>Description:</b> <b>Περιγραφή:</b> Set the connectors's description Επιλέξτε την περιγραφή των συνδετήρων Fritzing cannot load the parts bin Το Fritzing αδυνατεί να φορτώσει το δοχείο εξαρτημάτων Set all to: Ρύθμιση όλων σε: Pad Επίθεμα (Pad) Part %1 '%2' Εξάρτημα %1 '%2' Autorouter Settings Ρυθμίσεις Αυτοδρομολογητή N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Για περισσότερες πληροφορίες για την κοστολόγηση δείτε στο <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Αρχείο Last backup Τελευταίο αντίγραφο Last saved Τελευταία αποθήκευση file not saved το αρχείο δεν αποθηκεύτηκε <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Το Fritzing μπορεί να αντιμετώπισε σφάλμα αλλά μερικές από τις αλλαγές στα ακόλουθα αρχεία ίσως ανακτηθούν.</b></p><p>Προβάλλεται η ημερομηνία και η ώρα αντιγράφου του κάθε αρχείου. Αν το αρχείο είχε αποθηκευτεί, προβάλλεται και αυτή η ημερομηνία και ώρα.</p><p>Τα αρχικά αρχεία θα υπάρχουν ακόμη στον δίσκο αν είχαν αποθηκευτεί. Μπορείτε να επιλέξετε αν θα αντικαταστήσετε αφού φορτώσετε το αντίγραφο ασφαλείας του.</p><p><b>Επιλέξτε όποιο αρχείο θέλετε να ανακτήσετε από την παρακάτω λίστα.</b></p> &Recover &Ανάκτηση &Ignore &Αγνόηση Resistor Resistor Αντίσταση resistance αντίσταση You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' Μπορείτε να να πληκτρολογήσετε μία τιμή αντίστασης, ή να επιλέξετε από την λίστα. Μορφή nnn.dP όπου P ένα από τα 'umkMG' ResizableBoard shape σχήμα width: %1mm πλάτος: %1mm height: %1mm ύψος: %1mm width(mm) πλάτος(mm) height(mm) ύψος(mm) keep aspect ratio διατήρηση αναλογιών Revert Αναίρεση size μέγεθος custom προσαρμοσμένη A0 (1030x1456) A0 (1030x1456) A1 (728x1030) A1 (728x1030) A2 (515x728) A2 (515x728) A3 (364x515) A3 (364x515) A4 (257x364) A4 (257x364) A5 (182x257) A5 (182x257) A6 (128x182) A6 (128x182) Letter (8.5x11) Letter (8.5x11) Legal (8.5x14) Legal (8.5x14) Ledger (17x11) Ledger (17x11) Tabloid (11x17) Tabloid (11x17)) {11x?} Ruler width πλάτος S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Έργο Filename Όνομα αρχείου Date Ημερομηνία Sheet Φύλλο Rev Εκδ shape σχήμα of από date ημερομηνία sheet φύλλο SchematicSketchWidget Change label from %1 to %2 Αλλαγή ετικέτας από %1 σε %2 Change voltage from %1 to %2 Αλλαγή τάσης από %1 σε %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Κάντε αυτό το προκαθορισμένο %1 χρώμα Cancel Ακύρωση OK Εντάξει Pick custom %1 color Current color (%1) SketchWidget loading part φόρτωση εξαρτήματος done loading ολοκλήρωση φόρτωσης Delete ratsnest Διαγραφή ratsnest %1 %2 %1 %2 %1 %2 items %1 %2 αντικείμενα Select All Επιλογή Όλων Deselect Αποεπιλογή Add %1 Προσθήκη %1 Selection Επιλογή Move %2 (%1) Μετακίνηση %2 (%1) Move %2 items (%1) Μετακίνηση %2 αντικειμένων (%1) Select %1 Επιλογή %1 Select %1 items Επιλογή %1 αντικειμένων Disconnect Αποσύνδεση from %1 από %1 Move leg of Μετακίνηση από το Connect Σύνδεση to %1 στο %1 Change leg curvature for %1. Αλλαγή καμπύλης ποδιού για το %1. Change leg bendpoint for %1. Αλλαγή σημείου καμπής ποδιού για το %1. Change Αλλαγή Create and connect wire Δημιουργία και σύνδεση καλωδίου Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Αυτό μοιάζει με προσπάθεια για την δημιουργία ενός ίχνους διαμέσου επιπέδων. Αυτό δεν έπρεπε να συμβεί: παρακαλώ ειδοποιείστε τους προγραμματιστές. Create and connect %1 Δημιουργία και σύνδεση %1 wire καλωδίου trace ίχνους Rotate %2 (%1) Περιστροφή %2 (%1) Flip %2 (%1) Αναστροφή %2 (%1) Double-click Διπλό-κλικ Drag or double-click Σύρσιμο ή διπλό-κλικ or alt-drag to move the segment ή alt-σύρσιμο για να μετακινηθεί στο κομμάτι Double-click to delete this bend point Διπλό-κλικ για την διαγραφή αυτού του σημείου καμπής Note text change Αλλαγή κειμένου σημείωσης Change %1 label to '%2' Αλλαγή ετικέτας %1 σε '%2' Change %1 color from %2 to %3 Αλλαγή χρώματος %1 από %2 σε %3 Change color of %1 wires to %2 Αλλαγή χρώματος %1 καλωδίων σε %2 Change %1 width from %2 to %3 Αλλαγή μεγέθους %1 από %2 σε %3 Change width of %1 wires to %2 Αλλαγή πλάτους %1 καλωδίων σε %2 Move label '%1' Μετακίνηση ετικέτας '%1' %1 label '%2' %1 ετικέτα %2 Rotate Περιστροφή Flip Αναστροφή show %n part label(s) εμφάνιση ετικέτας(ων) %n εξαρτημάτων εμφάνιση ετικέτας(ων) %n εξαρτημάτων hide %n part label(s) απόκρυψη ετικέτας(ων) %n εξαρτημάτων απόκρυψη ετικέτας(ων) %n εξαρτημάτων Resize ruler to %1 %2 Αλλαγή μεγέθους κανόνα σε %1 %2 test connectors Resize Note Αλλαγή μεγέθους Σημείωσης Change Resistance from %1 to %2 Αλλαγή Αντίστασης από %1 σε %2 Change %1 from %2 to %3 Αλλαγή %1 από %2 σε %3 Resize board to %1 %2 Μέγεθος πλακέτας σε %1 %2 Create wire from Ratsnest Δημιουργία καλωδίου από Ratsnes Disconnect all wires from %1 Αποσύνδεση όλων των καλωδίων από το %1 Disconnect all wires from %1 items Αποσύνδεση όλων των καλωδίων από %1 αντικείμενα Change image from %1 to %2 Αλλαγή εικόνας από %1 σε %2 change pin labels αλλαγή ετικετών ακίδας (pin) Unrouted connections are highlighted in yellow. Μη δρομολογημένες συνδέσεις είναι επισημασμένες με κίτρινο. There are no unrouted connections Δεν υπάρχουν μη δρομολογημένες συνδέσεις Unrouted connections Μη δρομολογημένς συνδέσεις %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. %1 Σημείωση: μπορείτε να προκαλέσετε την οθόνη αυτή πατώντας το ποντίκι στο κείμενο κατάστασης της δρομολόγησης στην μπάρα κατάστασης. Part '%1' not found in sketch Το εξάρτημα '%1' δεν βρέθηκε στο σχέδιο Add %1 parts Deselect all Αποεπιλογή όλων SqliteReferenceModel The swapping mechanism is disabled for: Ο μηχανισμός εναλλαγής είναι απενεργοποιημένος για: and %1 other parts και %1 άλλα εξαρτήματα and %1 other properties και %1 άλλες ιδιότητες property '%1' in part '%2' with id '%3'. η ιδιότητα '%1' στο εξάρτημα '%2' με id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. το εξάρτημα '%1' με id '%2', πιθανότατα επιδεί δεν έχει ιδιότητα 'οικογένεια'. Stripboard Restored Αποκαταστημένο Cut Αποκοπή %1 %n strip(s) %1 %n διάδρομος %1 %n διάδρομοι rows σειρές columns στήλες %1 layout SymbolPaletteItem voltage τάση label ετικέτα Net labels Ετικέτες Δικτύων Net labels cannot be blank Οι ετικέτες δικτύων δεν μπορεί να είναι κενές TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Πληροφορίες και Κόλπα Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 Επιλέξτε από την λίστα, ή πληκτρολογήστε μία τιμή από %1 έως %2 width πλάτος TranslatorListModel English - %1 Αγγλικά - %1 French - %1 Γαλλικά - %1 German - %1 Γερμανικά - %1 Spanish - %1 Ισπανικά - %1 Japanese - %1 Ιαπωνικά - %1 Portuguese (European)- %1 Πορτογαλικά (Ευρώπη)- %1 Portuguese (Brazilian) - %1 Πορτογαλικά (Βραζιλία)- %1 Hungarian - %1 Ουγγρικά - %1 Estonian - %1 Εσθονικά - %1 Dutch - %1 Ολλανδικά - %1 Danish - %1 Russian - %1 Ρώσικα - %1 Persian - %1 Περσικά - %1 Slovenian - %1 Σλοβενικά - %1 Marathi - %1 Μαράθι - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Ιταλικά - %1 Hebrew - %1 Εβραϊκά - %1 Arabic - %1 Αραβικά - %1 Hindi - %1 Χέντι - %1 Chinese (Simplified) - %1 Κινέζικα (Απλά) - %1 Chinese (Traditional) - %1 Κινέζικα (Παραδοσιακά) - %1 Polish - %1 Πολωνικά - %1 Czech - %1 Τσέχικα - %1 Turkish - %1 Τούρκικα - %1 Swedish - %1 Σουηδικά - %1 Romanian - %1 Ρουμάνικα - %1 Thai - %1 Ταϊλανδέζικα - %1 Greek - %1 Ελληνικά - %1 Bulgarian - %1 Βουλγάρικα - %1 Galician - %1 Γαλικιακά - %1 Korean - %1 Κορεάτικα - %1 Indonesian - %1 Ινδονησιακά - %1 Slovak - %1 Σλοβάκικα - %1 Bengali - %1 Βεγγαλική - %1 UpdateDialog Close Κλείσιμο No new versions found. Δεν βρέθηκαν νέες εκδόσεις. A new main release is available for downloading: Μία κύρια έκδοση είναι διαθέσιμη για μεταφόρτωση: A new interim release is available for downloading: Μία ενδιάμεση έκδοση είναι διαθέσιμη για μεταφόρτωση: Checking... Έλεγχος... Sorry, unable to retrieve update info Συγνώμη, αδυναμία λήψης στοιχείων ενημερώσεων WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) υπέρ λεπτό (8 mil) extra thin (12 mil) πολύ λεπτό (12 mil) thin (16 mil) λεπτό (16 mil) standard (24 mil) σύνηθες (24 mil) thick (32 mil) χοντρό (32 mil) extra thick (48 mil) πολύ χοντρό (48 mil) blue μπλε red κόκκινο black μαύρο yellow κίτρινο green πράσινο grey γκρι white άσπρο orange πορτοκαλί ochre cyan brown καφέ purple μοβ pink color χρώμα Banded ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_en.qm000066400000000000000000000057411250202676700217120ustar00rootroot00000000000000The custom shape has %n cutout.</b>N<b>The custom shape has %n cutouts.</b>'The custom shape has %n cutouts.Board(connected to %n item*connected to %n itemsconnected to %n item(s) HtmlInfoView part # part numberItemBasen%1 of %2 nets routed - %n connection still to be routedp%1 of %2 nets routed - %n connections still to be routed9%1 of %2 nets routed - %n connector(s) still to be routed MainWindowLRouting completed using %n jumper partNRouting completed using %n jumper parts)Routing completed using %n jumper part(s) MainWindowRThere is %n outdated part in this sketch.VThere are %n outdated parts in this sketch..There are %n outdated part(s) in this sketch.  MainWindowWe strongly recommend that you update this part to the latest version. We strongly recommend that you update these parts to the latest version. MWe strongly recommend that you update these %n parts to the latest version.  MainWindow with %n via with %n vias with %n vias MazeRouterFUnable to find the following part:LUnable to find the following %n parts:(Unable to find the following %n part(s): ModelBaseLThis part has %n unassigned connector NThis part has %n unassigned connectors 'This part has %n unassigned connectors  PEMainWindowin %n view. "across %n views. across %n views.  PEMainWindowVThe total area of the PCB in this sketch is^The total area of the %n PCBs in this sketch is1The total area of the %n PCB(s) in this sketch is QuoteDialoghide part label"hide parts labelshide %n part label(s) SketchWidgetshow part label"show parts labelsshow %n part label(s) SketchWidget%1 %n strip%1 %n strips%1 %n strip(s) Stripboardfritzing-app-0.9.2b/translations/fritzing_en.ts000066400000000000000000014373541250202676700217350ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Best So Far Cancel Stop Now Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <b>The custom shape has %n cutout.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Import files from previous version? Import Do not import now Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Save... Save Don't Save Ctrl+D Your changes will be lost if you don't save them. Cancel GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView conn. name type (autoroutable) Wire Trace wire %1 Connections Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Locked location rotation degrees connected to %n item(s) connected to %n item connected to %n items Ratsnest wire v. %1 %2 obsolete Properties Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Tags ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number part # maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow %1 of %2 nets routed - %n connector(s) still to be routed %1 of %2 nets routed - %n connection still to be routed %1 of %2 nets routed - %n connections still to be routed Rotate Flip Autoroute Ready Save %1 Unable to export %1 as shareable Specify a file name Fritzing (*%1) Fritzing Unable to export %1 to shareable sketch Fritzing Part (*%1) Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Share Fabricate Both Layers Bottom Layer Top Layer View from Above View from Below Export for PCB Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 No connections to route Routing completed Routing completed using %n jumper part(s) Routing completed using %n jumper part Routing completed using %n jumper parts Change to single layer pcb Change to two layer pcb Change image to %2 Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome %1 - [%2] No Sketch found in '%1' Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. No exactly matching part found; Fritzing chose the closest match. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Backing up '%1' PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Cannot find file %1. Cannot read file 1 %1: %2. loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) Create a new sketch &Open... Ctrl+O Export the visible area of the current sketch as a JPG image Export the visible area of the current sketch as a PNG image Export the visible area of the current sketch as a PostScript image Export the visible area of the current sketch as a PDF image Export the current sketch as an SVG image Save a Bill of Materials (BoM)/Shopping List as text &Open Recent Files &Open Example Proceed Cancel File '%1' not found New Ctrl+N &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website List of parts (&Bill of Materials)... XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &%1 %2 &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect &Preferences... Show the application's about box &Add to bin... Add selected part to bin Disconnect All Wires Ctrl+Shift+V Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Show/hide the label for the selected parts Straighten Curve Straighten the curve of the selected wire Find part in sketch... Search for parts in a sketch by matching text Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page Display First Time Help Align Move to bottom layer Move to top layer Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards jumpers copperfill vias Generating %1 fill... ground copper Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. There is %n outdated part in this sketch. There are %n outdated parts in this sketch. We strongly recommend that you update these %n parts to the latest version. We strongly recommend that you update this part to the latest version. We strongly recommend that you update these parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Sticky If a "sticky" part is moved, parts on top of it are also moved &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Actual (real world physical) size 100% Size 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Tips, Tricks and Shortcuts Parts Editor Help Display Parts Editor help in a browser as Image for Production &Routing Ground Fill Delete Ratsnest Line Delete Wire Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 &Create trace from ratsnest Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show Code Show the code (programming) view Autoroute connections... Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Check Loaded Traces Copper Top and Copper Bottom layers are both active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Do you want to update now? OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Copper Top layer is active Copper Bottom layer is active Autorouting Progress... Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) &Zoom In Shell launch %1 Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Open programming window Open microcontroller programming window Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Shift+Ctrl+0 &Show Breadboard Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view &Minimize Ctrl+M Minimize current window Debugger Output Ctrl+? Open Fritzing help Open Fritzing examples Open Parts Reference First Time Help &About Display some handy Fritzing tips and tricks Report a bug... Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation &File &Export Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting Export SVG... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Tidy Wires Tidy selected wires Remove copper fill Remove Bendpoint Select all jumper item parts Select All Vias Select all via parts Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts &Wire Color &Edit JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... Select outdated parts Update selected parts Online Tutorials Online Projects Gallery Online Parts Reference &Part &View &Window &Help Sorry, "%1" has not been implemented yet Copper Fill Remove Copper Fill Remove the copper fill Autorouting... directly loading parts Page Setup Undo Redo Select a Fritzing File to Open &Show part label Export Bill of Materials (BoM)... Add a note Add Note Check for updates... Check whether a newer version of Fritzing is available for download Select All Traces Select all trace wires Select all trace wires excluded from autorouting Do you want to keep the imported parts? &About Qt Show Qt's about box Report a but you've found in Fritzing This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Swapped %1 with module %2 All traces have not yet been routed. Do you want to proceed anyway? Raise and Lower Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias with %n via with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): Unable to find the following part: Unable to find the following %n parts: at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Metadata Connectors Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors This part has %n unassigned connector This part has %n unassigned connectors across %n views. in %n view. across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Specify a file name Fritzing Cannot find file %1. Cannot read file %1: %2. loading bin '%1' Save Fritzing Bin (*%1) Loading... Save bin "%1" Do you want to save the changes you made in the bin "%1"? Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Your changes will be lost if you don't save them. Untitled Bin Perfboard size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Mouse Wheel Behavior Command Control Change Wheel Behavior Cancel General Code View OK Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab Select a program file to load While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Open Save Platform Board Port Serial Monitor Upload Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint bb Breadboard View Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> icon view breadboard view schematic view pcb view Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. a label a value PCB View Preferences Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. schem Schematic View Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Select locked parts Icon Breadboard Parts Wires Ratsnest Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer Please note that a new language setting will not take effect until the next time you run Fritzing. Part Labels Notes Trace wires Ratsnest wires Select all %1 Check for updates The file '%1' is read-only; please use a different filename. Edit link The file %1 is not a Fritzing file (4). Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? File Progress... Select outdated parts files unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid shape delta not implemented trapezoidal pads not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 Copying file %1 File %1 already exists: it won't be overwritten Select %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is The total area of the PCB in this sketch is The total area of the %n PCBs in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Rotate Flip Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Note text change Change %1 color from %2 to %3 Change color of %1 wires to %2 Resize ruler to %1 %2 test connectors Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all Change %1 label to '%2' Double-click to delete this bend point Move label '%1' %1 label '%2' Selection show %n part label(s) show part label show parts labels hide %n part label(s) hide part label hide parts labels Resize Note Change %1 width from %2 to %3 Change width of %1 wires to %2 SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) %1 %n strip %1 %n strips rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 Japanese - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_es.qm000066400000000000000000002007451250202676700217200ustar00rootroot000000000000006Aį|`įvįni֍H5,ee U[5_V`". !"*y^*y*t***%*%-*0 f+h"+ +#+#+&+'-FdIXIXZIXJ6:KQ8P,E!RU2Rx,R`UjVVXXYlZ8,^ȓ`cMRgei'ijcb jcb8jcb mxnrxrxt y~yeyezz{}}}jI559LnQ@~q$' F.>22&U G[)t){׳**NX246kg9?y% JvgoL#L4w?TZ-e>'teq"<N5E,*P] rܫn.^͌Ӓ2{o*.;I&ZU&WfC>DRԢzYXYYñYZdlTR9_t thuTY3u5(7xexeXxice`y9 '<5sSg4T =#S;A,;Au^KB±^±a]a[b C^pqTT)3 ;;+FRBhWwHrxsu"|qu$o\r[qqi S '$.ܡտ{ֺ.fdpUu~ʳICAn1'e5~amlzbDbCׅ)bɱ1UIIpIIII|I0IIzIqIIIيzc6\R6y~6~}ٶ 8ۘ7Bc:~GXqj}v sUBg4(J}(,](u;?Q BLO?aa3-b/8ee|nqp3qS}*F }\,pTOOBَU~َ* q7&77-grXI3L*AQ0z2QM۹RN->^zH5_p_z'l"zW>D]DL\Lҭ@9d֣\֣dm+ޛ-X~9HwT".'S-3e9;!/Eʇ\U3c'*c$+hi=EOidksNh|%E!>rWߠ4.X4 ?;`>={^zAv0g3gp( j&Ծ,ιl2CII'0dNO;.YQDab]AdfChXfCf|i' ivyGI|Ԃ |^7|^s*SS^[m,nrGSxh"3%S \~# wJ !y 0!S+ Ex=p Gȧ Mg Q SeG cϥj lOp u ~ .? N rb ^ N! . {d s J 8O2 ,5] ՛m {ua}  ʕ ~ v Q~ ͩ ` @ 7E !q\F !q #$>" CD> U [>i ^5" a4ފ d8 eKݫ eR)a su Nl , ^W  T b v v Ϯ ' 0 0E ;'F( cT  E Uk T D V g p %4 (ϊ * *Q ? 87h N>B Ysy bR" gd i$e, > $u @Z Ll a| _ q : }؝ KG&  t 4. , L w L5 < #9 R #> O~ Wja `lR af` eu eZoh rs r t' z n6 z nQ "F  ,0 ,  /8 /G | 1 E 9 ɠ.H ? '| Kw  c! o UХ (d} f   3F R/ [ s1 cz c# fL m[a= vC9 }Z #f }z AC 15f p ~ zV @@4 Rz cY _ZZ  v}D{8d rc(KEa.a.tfThfT-w=)PiYn.nf3VYSRɥxTãCce*RCA\qtd!48uC:4]w^U$Y^J:}iu$LD/`iG@^ i%pyvgU@}$76e(FΈXkT6iL<b>GNU GPL v3 para el cdigo y CreativeCommons:BY-SA para el resto?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxCancelarCancelAutorouteProgressDialogDetener ahoraStop NowAutorouteProgressDialogCancelarCancelAutorouterSettingsDialogAceptarOKAutorouterSettingsDialogcompartimientoBin BinManagerBinManager::setdirtyTab: No se pude colocar el compartimiento '%1' como sucio;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerlNo se puede colocar un compartimiento NULO como actual(Cannot set a NULL bin as the current one BinManagerArchivos de compartimientos de Fritzing (*%1 *%2);;Compartimiento de fritzing (*%1);;Compartimiento compartido de Fritzing (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManager2Compartimiento nuevo (%1) New bin (%1) BinManager PartesParts BinManagerpPor favor selecciona un nombre para este compartimiento:!Please choose a name for the bin: BinManager&Quitar del catlogoRemove from bin BinManager2Re nombrar compartimiento Rename bin BinManagerTSeleccionar un archivo Fritzing para abrirSelect a Fritzing File to Open BinManagerImgenesImagesBoardTSeleciona un archivo de imgen para cargarSelect an image file to loadBoard Imposible cargarUnable to loadBoardFImposible cargar la imagen de %1 %2Unable to load image from %1 %2Board0cargar archivo de imagenload image fileBoard ColorcolorBreadboardLogoItem&Acerca&About ConsoleWindow &Salir&Quit ConsoleWindowPara Depurar for debugging DebugDialogRemoverRemove DeleteDialog"Etiqueta del chip chip labelDip"No importar ahoraDo not import now FApplicationlFritzing obtuvo una excepcin %1 de %2 en el evento %33Fritzing caught an exception %1 from %2 in event %3 FApplicationfFritzing obtuvo una excepcin de %1 en el evento %20Fritzing caught an exception from %1 in event %2 FApplicationFritzinf falloFritzing failure FApplicationImportarImport FApplicationNImportar archivos de la versi previa?#Import files from previous version? FApplication(Ayuda de primera vezFirst Time HelpFirstTimeHelpDialog&Cerrar Ventana &Close WindowFritzingWindowCancelarCancelFritzingWindow2Cerrar el bosquejo actualClose the current sketchFritzingWindowrDeseas guardar los cambios realizados al documento "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindowNo Guardar Don't SaveFritzingWindowGuardarSaveFritzingWindowGuardar "%1" Save "%1"FritzingWindowGuardar...Save...FritzingWindowHEspecifica un nombre para el archivoSpecify a file nameFritzingWindowRLos cambios se perderan si no se guardan.1Your changes will be lost if you don't save them.FritzingWindowCancelarCancelGroundFillSeedDialogAceptarOKGroundFillSeedDialogTamao del hoyo hole sizeHole(autoruteable)(autoroutable) HtmlInfoViewConexiones Connections HtmlInfoViewPropiedades Properties HtmlInfoView Trazar Cable %1  Trace wire %1 HtmlInfoView CableWire HtmlInfoView,Conectado a %n item(s),Conectado a %n item(s)connected to %n item(s) HtmlInfoView Nombrename HtmlInfoViewTipotype HtmlInfoView PartePartItemBase ColorcolorItemBaseFamiliafamilyItemBase formaformItemBase$mxima resistenciamaximum resistanceItemBasepaquetepackageItemBase&espacio entre pines pin spacingItemBase*corriente clasificada rated currentItemBase(potencia clasificada rated powerItemBase&voltaje clasificado rated voltageItemBaseResistencia resistanceItemBase figurashapeItemBase tamaosizeItemBaseTipotypeItemBaseversinversionItemBaseVoltajevoltageItemBaseCancelarCancelKicadModuleDialogAceptarOKKicadModuleDialog.mostrar todas las capasshow all layers LayerPaletteCancelarCancel LinkDialogAceptarOK LinkDialog texto:text: LinkDialog(Imposible de mostrarUnable to displayLogoItemBImposible mostrar la imagen de %1Unable to display image from %1LogoItem~%1 to %2 redes ruteadas -%n conector(es) pendiente(s) de rutear~%1 to %2 redes ruteadas -%n conector(es) pendiente(s) de rutear9%1 of %2 nets routed - %n connector(s) still to be routed MainWindow&Acerca&About MainWindow&Acerca de Qt &About Qt MainWindow&Tamao Actual &Actual Size MainWindow8&Aadir al compartimiento...&Add to bin... MainWindow&Copiar&Copy MainWindow&Cortar&Cut MainWindow&Borrar&Delete MainWindow&Deseleccionar &Deselect MainWindow&Duplicar &Duplicate MainWindow&Editar&Edit MainWindow&Exportar&Export MainWindow&Exportar... &Export... MainWindow&Archivo&File MainWindow*&Ajustar a la ventana&Fit in Window MainWindow2&Invertir Horizontalmente&Flip Horizontal MainWindow.&Invertir Verticalmente&Flip Vertical MainWindow &Ayuda&Help MainWindow0&Ocultar todas las capas&Hide All Layers MainWindowz&Importat partes y compartimientos de una versin anterior...*&Import parts and bins from old version... MainWindow&Minimizar &Minimize MainWindow&Abrir ejemplo &Open Example MainWindow2&Abrir Archivos recientes&Open Recent Files MainWindow&Abrir...&Open... MainWindow &Parte&Part MainWindow &Pegar&Paste MainWindow &Preferencias...&Preferences... MainWindow&Imprimir... &Print... MainWindow &Salir&Quit MainWindow&Guardar&Save MainWindow &Guardar como... &Save As... MainWindow"&Seleccionar todo &Select All MainWindow0&Mostrar todas las capas&Show All Layers MainWindowR&Mostrar Protoboard (placa de Prototipos)&Show Breadboard MainWindow>&Mostrar PCB (Circuito Impreso) &Show PCB MainWindow &Mostrar Esquema&Show Schematic MainWindow@&Mostrar la etiqueta de la parte&Show part label MainWindow &Vista&View MainWindow&Ventana&Window MainWindow &Color del Cable &Wire Color MainWindow&Acercar&Zoom In MainWindow&Alejar &Zoom Out MainWindow&100% (pixel) tamao100% (pixel) size MainWindow100% Tamao 100% Size MainWindowNTamao actual (fsico en el mundo real)!Actual (real world physical) size MainWindow2Aadir un punto de doblez Add Bendpoint MainWindowAgregar NotaAdd Note MainWindow^aadir un punto de doblez al cable seleccionado$Add a bendpoint to the selected wire MainWindowAgregar nota Add a note MainWindowZAadir la parte selecionada al compartimientoAdd selected part to bin MainWindowLAlienar partes a la malla al arrastrar!Align items to grid when dragging MainWindow$Alinear a la Malla Align to Grid MainWindowTodoAll MainWindow>No se ha ruteado ninguna traza.$All traces have not yet been routed. MainWindowAutorutear Autoroute MainWindow2Progreso del Autoruteo...Autorouting Progress... MainWindowAutoruteando...Autorouting... MainWindow Respaldando '%1'Backing up '%1' MainWindowAmbas Capas Both Layers MainWindowltima Capa Bottom Layer MainWindowProtoboard Breadboard MainWindowTraer al frente Bring Forward MainWindowtEnviar el o los objetos seleccionados al frente de la capa/Bring selected object(s) forward in their layer MainWindowtEnviar el o los objetos seleccionados al frente de la capa0Bring selected object(s) to front of their layer MainWindowTraer al frenteBring to Front MainWindowCancelarCancel MainWindow>Imposible encontrar archivo %1.Cannot find file %1. MainWindow6No es posible imprimir a %1Cannot print to %1 MainWindow<Imposible leer archivo %1: %2.Cannot read file 1 %1: %2. MainWindowPNo es posible escribir el Archivo %1:%2.Cannot write file %1: %2. MainWindow2Buscar actualizaciones...Check for updates... MainWindowComprobar si hay una nueva versin de Fritzing disponible para descargarCCheck whether a newer version of Fritzing is available for download MainWindowDSelecciona un folder para exportarChoose a folder for exporting MainWindowFLa ltima capa de cobre esta activaCopper Bottom layer is active MainWindow Relleno de Cobre Copper Fill MainWindowdLa Primera y la ltima capa de cobre estan activas3Copper Top and Copper Bottom layers are both active MainWindowHLa primera Capa de Cobre esta activaCopper Top layer is active MainWindow Copiar seleccinCopy selection MainWindowLNo se puede obtener el widget del dockCouldn't get the dock widget MainWindow(Crear bosquejo nuevoCreate a new sketch MainWindow Cortar seleccin Cut selection MainWindow(Salida del depuradorDebugger Output MainWindow Borrar seleccinDelete selection MainWindowDeseleccionarDeselect MainWindow8Desconectar Todos los CablesDisconnect All Wires MainWindownDesconectar todos los cables conectados a ste conector0Disconnect all wires connected to this connector MainWindow`Mostrar algunos tips y trucos utiles de Fritzing+Display some handy Fritzing tips and tricks MainWindowTDesea quedarse con las partes importadas?'Do you want to keep the imported parts? MainWindowBDesea Proceder con la Operacin?Do you want to proceed anyway? MainWindow$Duplicar seleccinDuplicate selection MainWindowBPermitir el archivo de depuracinEnable debugging log MainWindowpExportar a 1000 dpi SVG plano de esta parte a esta vista7Export 1000 dpi Flattened SVG of this part in this view MainWindowfExportar a 1000 dpi SVG de esta parte en esta vista-Export 1000 dpi SVG of this part in this view MainWindowHExportar Lista de Materiales(BoM)...!Export Bill of Materials (BoM)... MainWindow4Exporta la Lista de Red...Export Netlist... MainWindow<Exportar SVG Plano NormalizadoExport Normalized Flattened SVG MainWindow0Exportar SVG NormalizadoExport Normalized SVG MainWindowExporta SVG... Export SVG... MainWindow6Exportar parte seleccionadaExport selected part MainWindow^Exportar el bosquejo actual como una imagen SVG)Export the current sketch as an SVG image MainWindowJExport el bosquejo actual a Eagle CAD&Export the current sketch to Eagle CAD MainWindowExportar el rea visible del bosquejo actual como una imagen JPGReferencia para partes en lneaOnline Parts Reference MainWindow:Galeria de proyectos en lneaOnline Projects Gallery MainWindow&Tutoriales en lneaOnline Tutorials MainWindow4Abrir Ejemplos de FritzingOpen Fritzing examples MainWindow.Abrir ayuda de FritzingOpen Fritzing help MainWindow:Abrir la referencia de partesOpen Parts Reference MainWindowdAbrir ventana de programacin del microcontrolador'Open microcontroller programming window MainWindow:Abrir ventana de programacinOpen programming window MainWindow partes AtrasadasOutdated parts MainWindow$Imagen PNG (*.png)PNG Image (*.png) MainWindow"Configurar Pgina Page Setup MainWindow@Pegar contenido del portapapelesPaste clipboard contents MainWindow`Porfavor elije el folder de Fritzing anterior...-Please choose the previous Fritzing folder... MainWindowXPostear un proyecto al sitio web de Fritzing&Post a project to the Fritzing website MainWindow0Imprimir la vista actualPrint the current view MainWindowImprimiendo... Printing... MainWindowProcederProceed MainWindow,Salir de la aplicacinQuit the application MainWindow(Aumentar y disminuirRaise and Lower MainWindow ListoReady MainWindowRehacerRedo MainWindow,Quitar Punto de DoblesRemove Bendpoint MainWindow4Quitar el Relleno de CobreRemove Copper Fill MainWindow6Remover las pistas de cobreRemove copper fill MainWindow6Remover el relleno de cobreRemove the copper fill MainWindow$Reportar un bug...Report a bug... MainWindow^Reporta un error que haz encontrado en Fritzing%Report a but you've found in Fritzing MainWindow0Restauracin predefinidaRestore Default MainWindow GirarRotate MainWindow$Girar 180 {180?} Rotate 180� MainWindowFGirar 90 en sentido horario {45?}Rotate 45� Clockwise MainWindowNGirar 90 en sentido antihorario {45?}Rotate 45� Counter Clockwise MainWindowFGirar 90 en sentido horario {90?}Rotate 90� Clockwise MainWindowNGirar 90 en sentido antihorario {90?}Rotate 90� Counter Clockwise MainWindowhRotar la seccin actual 45 grados en sentido horario-Rotate current selection 45 degrees clockwise MainWindowpRotar la seccin actual 45 grados en sentido antihorario5Rotate current selection 45 degrees counter clockwise MainWindowtGirar la seleccion actual 90 grados en sentido antihorario5Rotate current selection 90 degrees counter clockwise MainWindowTGirar las partes seleccionadas 180 grados (Rotate the selected parts by 180 degrees MainWindowvGirar las partes seleccionadas 90 grados en sentido horario1Rotate the selected parts by 90 degrees clockwise MainWindow Ruteado completoRouting completed MainWindow$Imagen SVG (*.svg)SVG Image (*.svg) MainWindowGuardar %1Save %1 MainWindowGuardar una Lista de Materiales(BoM)/Lista de Compras como texto4Save a Bill of Materials (BoM)/Shopping List as text MainWindowNGuardar una lista de red en formato XMLSave a netlist in XML format MainWindow4Guardar el bosquejo actualSave the current sketch MainWindowGuardado '%1' Saved '%1' MainWindowEsquema Schematic MainWindow:Seleccionar Todos los JumpersSelect All Jumpers MainWindow8Seleccionar Todas las TrazasSelect All Traces MainWindowTSeleccionar un archivo Fritzing para abrirSelect a Fritzing File to Open MainWindow>Seleccionar todos los elementosSelect all elements MainWindow8Seleccionar Todas las TrazasSelect all trace wires MainWindowhSeleccionar todas las trazas excluidas del autoruteo0Select all trace wires excluded from autorouting MainWindow6Selecciona partes obsoletasSelect outdated parts MainWindowEnviar al fondo Send Backward MainWindowrEnviar el o los objetos seleccionados al fondo de la capa+Send selected object(s) back in their layer MainWindowrEnviar el o los objetos seleccionados al fondo de la capa2Send selected object(s) to the back of their layer MainWindowEnviar al fondo Send to Back MainWindowTElegir ambas capas de cobre al hacer click Set both copper layers clickable MainWindowVelegir la ltima capa de cobre con un click!Set copper bottom layer clickable MainWindowXElegir la primera capa de cobre con un clickSet copper top layer clickable MainWindowCompartirShare MainWindow*Compartir en lnea...Share online... MainWindow>Mostrar el dialogo acerca de QTShow Qt's about box MainWindowpOcultar todas las capas disponibles para la vista actual2Show all the available layers for the current view MainWindowTMostrar la vista de PCB (Circuito Impreso)Show the PCB view MainWindowTMostrar el dialogo acerca de la aplicacin Show the application's about box MainWindowPMostrar Protoboard (placa de Prototipos)Show the breadboard view MainWindow0Mostrar Vista de EsquemaShow the schematic view MainWindow$Bosquejo ExportadoSketch exported MainWindowDisculpa!Sorry! MainWindowPDisculpa, "%1" no se ha implementado aun(Sorry, "%1" has not been implemented yet MainWindowHEspecifica un nombre para el archivoSpecify a file name MainWindow%1 parte(s) actualizadas con xito. Porfavor verifica todas tus vistas por posibles efectos secundarios.SSuccessfully updated %1 part(s). Please check all views for potential side-effects. MainWindow0Al archivo Svg %1 le faltan '%2' capas. Para mayor informacin sobre como crear una placa personalizada, vea el tutorial en <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/. MainWindow>Se intercambi %1 por mdulo %2Swapped %1 with module %2 MainWindowAqu encontraras pronto una opcion para exportar tu archivo de Fritzing a al Software EAGLE. Si deseas tener ms opciones para exportar a tu herramienta favorita avisanos mediante el foro o contribuye con nosotros.This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. MainWindowOrdenar Cables Tidy Wires MainWindow6Ordenar cables selecionadosTidy selected wires MainWindow*Tips, Trucos y AtajosTips, Tricks and Shortcuts MainWindowPrimera Capa Top Layer MainWindowPImposible de exportar %1 como compartido Unable to export %1 as shareable MainWindow^Imposible exportar %1 como un bosquejo portable'Unable to export %1 to shareable sketch MainWindow(Imposible guardar %1Unable to save %1 MainWindowDeshacerUndo MainWindow"Historia Deshacer Undo History MainWindow4%1 parte(s) actualizada(s)Update %1 part(s) MainWindow\Actualizar informacin de la vista en el hoverUpdate InfoView on hover MainWindow<Actualizar partes selecionadasUpdate selected parts MainWindow&Lista de Red XML...XML Netlist... MainWindowTendrs que reiniciar Fritzing para poder usar las partes importadasDYou will have to restart Fritzing in order to use the imported parts MainWindowTu bosquejo no tiene an una placa! Porfavor aade un PCB para poder exportar a Gerber.VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber. MainWindowAcercarZoom in MainWindow AlejarZoom out MainWindow8Cargando partes directamentedirectly loading parts MainWindow dentroin MainWindow0Cargando %1 (Protoboard)loading %1 (breadboard) MainWindow(Cargando %1 (modelo)loading %1 (model) MainWindow"Cargando %1 (PCB)loading %1 (pcb) MainWindow*Cargando %1 (Esquema)loading %1 (schematic) MainWindowXhacer una excepcion falsa para ver que pasa*throw a fake exception to see what happens MainWindow:hacer una excepcin de pruebathrow test exception MainWindowNo se puede sobre escribir el archivo '%1'. Razon%2 (errcode %3)5Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ModelBase:Error! archivo No guardado!File save failed! ModelBase"etiqueta del chip chip label MysteryPartetiquetalabel MysteryPart,[escribe tu nota aqu][write your note here]NotexDa click sobre este conector para arrastrar una nueva traza.-Click this connector to drag out a new trace.PCBSketchWidgethError de Fritzing: imposible hacer la placa svg (1)./Fritzing error: unable to render board svg (1).PCBSketchWidgethError de Fritzing: Imposible hacer svg de cobre (1).0Fritzing error: unable to render copper svg (1).PCBSketchWidgetTu bosquejo no tiene una placa an! Porfavor aade un PCB para poder crear las pistas de cobre.UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.PCBSketchWidget&Editar&Edit PEMainWindow&Exportar&Export PEMainWindow&Archivo&File PEMainWindow Agregar conector Add connector PEMainWindowCancelarCancel PEMainWindowConectores Connectors PEMainWindow,Problema de conversinConversion problem PEMainWindow IconoIcon PEMainWindowDArchivos de Imagen y Huellas (%1 %2 %3 %4 %5);;Archivo SVG (%1);;Archivo JPEG (%2);;Archivo PNG (%3);; Archivo de Huellas gEDA (%4);;Archivo de Modulos Kicad (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowArchivos de Imgenes (%1 %2 %3);;Archivo SVG (%1);; Archivo JPEG (%2);; Archivo PNG (%3) {1 %2 %3)?} {1)?} {2)?} {3)%4%5?}KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindow CapasLayers PEMainWindowAbrir Imagen Open Image PEMainWindow Editor de Partes Parts Editor PEMainWindowGuardarSave PEMainWindowGuardar "%1" Save "%1" PEMainWindow>no se encontraron huellas en %1no footprints found in %1 PEMainWindow AutorAuthorPEMetadataViewDescripcin DescriptionPEMetadataViewEtiquetaLabelPEMetadataViewPropiedades PropertiesPEMetadataView4Diametro de la perforacin Hole Diameter PaletteItem"Grosor del anilloRing Thickness PaletteItemTamao del hoyo hole size PaletteItem dentroin PaletteItemMostrar ValoresDisplay Values PartLabel>Muestra el texto de la etiquetaDisplay the text of the label PartLabelBMuestra la propiedad del valor %1 Display the value of property %1 PartLabel EditarEdit PartLabel0Editar Etiqueta de TextoEdit label text PartLabel0Invertir HorizontalmenteFlip Horizontal PartLabel,Invertir Verticalmente Flip Vertical PartLabelBInvertir etiqueta horizontalmenteFlip label horizontally PartLabel>Invertir Etiqueta VerticalmenteFlip label vertically PartLabelInvertir/Rotar Flip/Rotate PartLabel&Tamao de la Fuente Font Size PartLabel"Etiqueta de texto Label text PartLabel$Etiqueta de texto: Label text: PartLabel GrandeLarge PartLabelMedianaMedium PartLabelHGirar 90 en sentido horario {135?}Rotate 135� Clockwise PartLabelPGirar 90 en sentido antihorario {135?}Rotate 135� Counter Clockwise PartLabel$Girar 180 {180?} Rotate 180� PartLabelFGirar 90 en sentido horario {45?}Rotate 45� Clockwise PartLabelNGirar 90 en sentido antihorario {45?}Rotate 45� Counter Clockwise PartLabelFGirar 90 en sentido horario {90?}Rotate 90� Clockwise PartLabelNGirar 90 en sentido antihorario {90?}Rotate 90� Counter Clockwise PartLabeltGirar la seleccin actual 90 grados en sentido antihorario5Rotate current selection 90 degrees counter clockwise PartLabel@Girar la etiqueta en 180 grados Rotate the label by 180 degrees PartLabel\Girar la etiqueta 90 grados en sentido horario(Rotate the label by 90 degrees clockwise PartLabelPSeleccionar el tamao de fuente a grandeSet font size to large PartLabelRSeleccionar el tamao de fuente a medianaSet font size to medium PartLabelRSeleccionar el tamao de fuente a pequeaSet font size to small PartLabel(Pon la etiqueta a %1Set label for %1 PartLabelPequeoSmall PartLabel&Agregar al catlogo Add to binPartsBinPaletteWidgetCancelarCancelPartsBinPaletteWidget>Imposible encontrar archivo %1.Cannot find file %1.PartsBinPaletteWidget:Imposible leer archivo %1:%2.Cannot read file %1: %2.PartsBinPaletteWidgetzRealmente quieres agregar la parte seleccionada al catlogo?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetQuieres guardar los cambios que hiciste en el compartimento "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetNo Guardar Don't SavePartsBinPaletteWidget>Compartimiento de Fritzing(*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetGuardarSavePartsBinPaletteWidget:Guarda el compartimiento "%1" Save bin "%1"PartsBinPaletteWidgetHEspecifica un nombre para el archivoSpecify a file namePartsBinPaletteWidget&Catalogo Sin Nombre Untitled BinPartsBinPaletteWidgetRLos cambios se perdern si no se guardan.1Your changes will be lost if you don't save them.PartsBinPaletteWidgetCancelarCancel Perfboard tamaosize PerfboardCancelarCancelPinLabelDialogRehacerRedoPinLabelDialogGuardarSavePinLabelDialogDeshacerUndoPinLabelDialog4%1 (click para cambiar...)%1 (click to change...) PrefsDialogAutoguardarAutosave PrefsDialog"Autoguardar cada:Autosave every: PrefsDialogCancelarCancel PrefsDialogJCambiar el Comportamiento de la RuedaChange Wheel Behavior PrefsDialogColoresColors PrefsDialogComandoCommand PrefsDialog IdiomaLanguage PrefsDialogHComportamiento de la Rueda del RatnMouse Wheel Behavior PrefsDialogAceptarOK PrefsDialogminutosminutes PrefsDialog PlacaBoard ProgramTabjFritzing no puede encontrar '%1', porfavor localizalo1Fritzing is unable to find '%1', please locate it ProgramTab NuevoNew ProgramTabGuardarSave ProgramTabZSelecciona un archivo de programa para cargarSelect a program file to load ProgramTab&Copiar&Copy ProgramWindow&Cortar&Cut ProgramWindow&Editar&Edit ProgramWindow &Pegar&Paste ProgramWindow &Preferencias...&Preferences... ProgramWindow"&Seleccionar todo &Select All ProgramWindow &Vista&View ProgramWindow PlacaBoard ProgramWindow Copiar seleccinCopy selection ProgramWindow Cortar seleccin Cut selection ProgramWindow@Pegar contenido del portapapelesPaste clipboard contents ProgramWindowRehacerRedo ProgramWindowTMostrar el dialogo acerca de la aplicacin Show the application's about box ProgramWindowDeshacerUndo ProgramWindow%1 Capa%1 LayerQObject PlacaBoardQObjectProtoboard BreadboardQObjectRVista de Protoboard (placa de Prototipos)Breadboard ViewQObject(Traer hacia adelante Bring forwardQObjectTraer al frenteBring to frontQObject:Imposible leer archivo %1:%2.Cannot read file %1: %2.QObject,Buscar actualizacionesCheck for updatesQObjectFondo de Cobre Copper BottomQObject.Fondo de Trazo de CobreCopper Bottom TraceQObject&Superficie de Cobre Copper TopQObject8Superficie de trazo de CobreCopper Top TraceQObject&Copiando archivo %1Copying file %1QObjectEditar Vinculo Edit linkQObject\El Archivo %1 ya existe: no ser sobre escrito/File %1 already exists: it won't be overwrittenQObject,Archivo en Progreso...File Progress...QObject IconoIconQObjectUnir Cable Join WireQObject2No se encontraron Partes.No parts found.QObject NotasNotesQObjectVista de PCBPCB ViewQObjectjError de Parseo (1) en la lnea %1, columna %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObjectjError de Parseo (2) en la lnea %1, columna %2 :%3 %4,Parse error (2) at line %1, column %2: %3 %4QObject PartePartQObject&Etiquetas de partes Part LabelsQObjectVEsta parte ya se encuentra en el contenedorPart already in binQObject PartesPartsQObjectRecuerda que los cambios de en la configuracin del idioma no surtirn efecto hasta la prxima vez que inicies Fritzing.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectPreferencias PreferencesQObject0Cables del Nido de RatasRatsnest wiresQObject ReglaRulersQObject Vista de EsquemaSchematic ViewQObjectSelecionar %1 Select %1QObject0Seleccionar todos los %1 Select all %1QObject8Seleccionar partes obsoletasSelect outdated partsQObject$Enviar hacia atrs Send backwardQObject&Fondo de serigrafaSilkscreen BottomQObjectRFondo de serigrafa (Etiquetas de partes)Silkscreen Bottom (Part Labels)QObject<Primera pantalla de serigrafaSilkscreen TopQObjectfPrimera pantalla de serigrafa (Etiqueta de Partes)Silkscreen Top (Part Labels)QObjectUna disculpa, Fritzing an no puede manejar ambos pines y pads juntos (en %1 en %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectUna disculpa, Fritzing an no puede manejar ambos pines y pads juntos (en %1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObject\Lo siento, no puedo manejar ese tipo de pad %1Sorry, can't handle pad type %1QObject,Disculpa, pero tenemos un problema con el mecanismos de intercambio Fritzing segir funcionando, pero no podrs cambiar las propiedades de las partes.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectSeparar Cable Split WireQObjectnEste Archivo %1 no es un archivo valido de Fritzing(2).'The file %1 is not a Fritzing file (2).QObjectpEste Archivo %1 no es un archivo valido de Fritzing (3).'The file %1 is not a Fritzing file (3).QObject`El archivo %1 no es un archivo de Fritzing (4).'The file %1 is not a Fritzing file (4).QObjectEl archivo '%1' es de slo lectura; por favor, selecciona otro nombre.Cambiar color de %1 cables a %2Change color of %1 wires to %2 SketchWidgetDCambiar el ancho de %1 cables a %2Change width of %1 wires to %2 SketchWidgetConectarConnect SketchWidget,Crear y conectar CableCreate and connect wire SketchWidgetDeseleccionarDeselect SketchWidgetDesconectar Disconnect SketchWidgetInvertirFlip SketchWidgetMover %2 (%1) Move %2 (%1) SketchWidget&Mover %2 items (%1)Move %2 items (%1) SketchWidget&Mover etiqueta '%1'Move label '%1' SketchWidget2Cambiar tamao de la Nota Resize Note SketchWidgetJCambiar el tamao de la placa a %1 %2Resize board to %1 %2 SketchWidget GirarRotate SketchWidgetSelecionar %1 Select %1 SketchWidget&Selecionar %1 itemsSelect %1 items SketchWidget Seleccionar Todo Select All SketchWidgetSeleccin Selection SketchWidgetcarga terminada done loading SketchWidgetcargando parte loading part SketchWidgeta %1to %1 SketchWidgetetiquetalabelSymbolPaletteItemvoltajevoltageSymbolPaletteItemTips y TrucosTips and Tricks TipsAndTricks Anchowidth TraceWirerabe - %1 Arabic - %1TranslatorListModel2Chino (Simplificado) - %1Chinese (Simplified) - %1TranslatorListModel0Chino (Tradicional) - %1Chinese (Traditional) - %1TranslatorListModelHolands- %1 Dutch - %1TranslatorListModelIngls - %1 English - %1TranslatorListModelEstonio - %1 Estonian - %1TranslatorListModelFrancs - %1 French - %1TranslatorListModelAlemn - %1 German - %1TranslatorListModelHebreo - %1 Hebrew - %1TranslatorListModelHind - %1 Hindi - %1TranslatorListModelHungaro - %1Hungarian - %1TranslatorListModelItaliano- %1 Italian - %1TranslatorListModelJapons - %1 Japanese - %1TranslatorListModel4Portugues (Brasileo) - %1Portuguese (Brazilian) - %1TranslatorListModel.Portugues (Europeo)- %1Portuguese (European)- %1TranslatorListModelRuso- %1 Russian - %1TranslatorListModelEspaol- %1 Spanish - %1TranslatorListModelxHay una nueva versin provisional disponible para descargar:3A new interim release is available for downloading: UpdateDialogtHay una nueva versin principal disponible para descargar:0A new main release is available for downloading: UpdateDialogComprobando... Checking... UpdateDialog CerrarClose UpdateDialogFNo se encontraron versiones nuevas.No new versions found. UpdateDialog~Perdn, no se puedo recuperar la informacin de actualizaciones%Sorry, unable to retrieve update info UpdateDialog negroblackWireazulblueWirecafbrownWire ColorcolorWire*extra grueso (48 mil)extra thick (48 mil)Wire verdegreenWiregrisgreyWirenaranjaorangeWire moradopurpleWirerojoredWiregrueso (32 mil)thick (32 mil)Wire delgado (16 mil) thin (16 mil)Wire blancowhiteWireamarilloyellowWirefritzing-app-0.9.2b/translations/fritzing_es.ts000066400000000000000000014624131250202676700217340ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 para el código y CreativeCommons:BY-SA para el resto <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Best So Far Cancel Cancelar Stop Now Detener ahora Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel Cancelar OK Aceptar BinManager Parts Partes BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setdirtyTab: No se pude colocar el compartimiento '%1' como sucio BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Compartimiento nuevo (%1) Select a Fritzing Parts Bin file to open Searching... Bin compartimiento Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Re nombrar compartimiento Please choose a name for the bin: Por favor selecciona un nombre para este compartimiento: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Quitar del catálogo Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Seleccionar un archivo Fritzing para abrir Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Archivos de compartimientos de Fritzing (*%1 *%2);;Compartimiento de fritzing (*%1);;Compartimiento compartido de Fritzing (*%2) Cannot set a NULL bin as the current one current one (actual)?? No se puede colocar un compartimiento NULO como actual Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file cargar archivo de imagen Images Imágenes Select an image file to load Seleciona un archivo de imágen para cargar due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Imposible cargar Unable to load image from %1 %2 Imposible cargar la imagen de %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About &Acerca About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit &Salir Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging Para Depurar DeleteDialog Also delete the file Remove Remover Don't remove Dip chip label Etiqueta del chip FApplication Import files from previous version? ¿Importar archivos de la versió previa? Import Importar Do not import now No importar ahora Fritzing failure Fritzinf fallo Fritzing caught an exception %1 from %2 in event %3 Fritzing obtuvo una excepción %1 de %2 en el evento %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Fritzing obtuvo una excepción de %1 en el evento %2 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help Ayuda de primera vez <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Cerrar Ventana Ctrl+W Ctrl+W Close the current sketch Cerrar el bosquejo actual %1 - %2 %1 - %2 Specify a file name Especifica un nombre para el archivo Save "%1" Guardar "%1" Do you want to save the changes you made in the document "%1"? ¿Deseas guardar los cambios realizados al documento "%1"? Save... Guardar... Save Guardar Don't Save No Guardar Ctrl+D Ctrl+D Your changes will be lost if you don't save them. Los cambios se perderan si no se guardan. Cancel Cancelar GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel Cancelar OK Aceptar OK and ground fill OK and copper fill Hole hole size Tamaño del hoyo HtmlInfoView conn. conn. name Nombre type Tipo (autoroutable) (autoruteable) Wire Cable Trace wire %1 Trazar Cable %1 Connections Conexiones Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Locked location rotation degrees connected to %n item(s) Conectado a %n item(s) Conectado a %n item(s) Ratsnest wire v. %1 %2 obsolete Properties Propiedades Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Tags Tags ItemBase family Familia type Tipo model size tamaño color Color resistance Resistencia capacitance inductance voltage Voltaje current power pin spacing espacio entre pines rated power potencia clasificada rated voltage voltaje clasificado rated current corriente clasificada version versión package paquete shape figura form forma part number maximum resistance máxima resistencia pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part Parte model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel Cancelar OK Aceptar LayerPalette show all layers mostrar todas las capas LinkDialog url: url: text: texto: Cancel Cancelar OK Aceptar LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Imposible de mostrar Unable to display image from %1 Imposible mostrar la imagen de %1 MainWindow Rotate Girar Flip Invertir Autoroute Autorutear Ready Listo Save %1 Guardar %1 Unable to export %1 as shareable Imposible de exportar %1 como compartido Specify a file name Especifica un nombre para el archivo Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 to shareable sketch Imposible exportar %1 como un bosquejo portable Fritzing Part (*%1) Parte Fritzing(*%1) Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Share Compartir Fabricate Both Layers Ambas Capas Bottom Layer Última Capa Top Layer Primera Capa View from Above View from Below Export for PCB Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 No connections to route No existen conexiones que rutear Routing completed Ruteado completo Routing completed using %n jumper part(s) Change to single layer pcb Change to two layer pcb Change image to %2 Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome %1 of %2 nets routed - %n connector(s) still to be routed %1 to %2 redes ruteadas -%n conector(es) pendiente(s) de rutear %1 to %2 redes ruteadas -%n conector(es) pendiente(s) de rutear No Sketch found in '%1' Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. No exactly matching part found; Fritzing chose the closest match. Ninguna parte corresponde exactamente; Fritzing escojerá la que más se corresponda. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Al archivo Svg %1 le faltan '%2' capas. Para mayor información sobre como crear una placa personalizada, vea el tutorial en <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Backing up '%1' Respaldando '%1' PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) Imagen PNG (*.png) JPEG Image (*.jpg) Imagen JPEG (*.jpg) SVG Image (*.svg) Imagen SVG (*.svg) BoM Text File (*.html) Printing... Imprimiendo... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. Sketch exported Bosquejo Exportado Export... Exportar... Exporting... Exportando... Unable to save %1 Imposible guardar %1 Cannot print to %1 No es posible imprimir a %1 Cannot write file %1: %2. No es posible escribir el Archivo %1:%2. Saved '%1' Guardado '%1' Cannot find file %1. Imposible encontrar archivo %1. Cannot read file 1 %1: %2. Imposible leer archivo %1: %2. directly loading parts Cargando partes directamente loading %1 (model) Cargando %1 (modelo) loading %1 (breadboard) Cargando %1 (Protoboard) loading %1 (pcb) Cargando %1 (PCB) loading %1 (schematic) Cargando %1 (Esquema) Create a new sketch Crear bosquejo nuevo &Open... &Abrir... Ctrl+O Ctrl+O Export the visible area of the current sketch as a JPG image Exportar el área visible del bosquejo actual como una imagen JPG Export the visible area of the current sketch as a PNG image Exportar el área visible del bosquejo actual como una imagen PNG Export the visible area of the current sketch as a PostScript image Exportar el área visble del bosquejo actual como una imagen PostScript Export the visible area of the current sketch as a PDF image Exportar el área visble del bosquejo actual como una imagen PDF Export the current sketch as an SVG image Exportar el bosquejo actual como una imagen SVG Save a Bill of Materials (BoM)/Shopping List as text Guardar una Lista de Materiales(BoM)/Lista de Compras como texto &Open Recent Files &Abrir Archivos recientes &Open Example &Abrir ejemplo Proceed Proceder Cancel Cancelar File '%1' not found New Nuevo Ctrl+N Ctrl+N &Save &Guardar Ctrl+S Ctrl+S Save the current sketch Guardar el bosquejo actual &Save As... &Guardar como... Shift+Ctrl+S Shift+Ctrl+S Share online... Compartir en línea... Post a project to the Fritzing website Postear un proyecto al sitio web de Fritzing List of parts (&Bill of Materials)... Lista de Partes (&Lista de Materiales)... XML Netlist... Lista de Red XML... Save a netlist in XML format Guardar una lista de red en formato XML SPICE Netlist... Save a netlist in SPICE format Export the current sketch to Eagle CAD Export el bosquejo actual a Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) &Print... &Imprimir... Ctrl+P Ctrl+P Print the current view Imprimir la vista actual Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber throw test exception hacer una excepción de prueba throw a fake exception to see what happens hacer una excepcióon falsa para ver que pasa &Quit &Salir Ctrl+Q Ctrl+Q Quit the application Salir de la aplicación All Todo MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: no se puede cargar el ejemplo con el id='%1' &%1 %2 &%1 %2 &Cut &Cortar Cut selection Cortar selección &Copy &Copiar Copy selection Copiar selección &Paste &Pegar Paste clipboard contents Pegar contenido del portapapeles Paste in Place Paste clipboard contents in place &Duplicate &Duplicar Ctrl+D Ctrl+D Duplicate selection Duplicar selección &Delete &Borrar Delete selection Borrar selección &Select All &Seleccionar todo Select all elements Seleccionar todos los elementos &Deselect &Deseleccionar Deselect Deseleccionar &Preferences... &Preferencias... Show the application's about box Mostrar el dialogo acerca de la aplicación &Add to bin... &Añadir al compartimiento... Add selected part to bin Añadir la parte selecionada al compartimiento Disconnect All Wires Desconectar Todos los Cables Disconnect all wires connected to this connector Desconectar todos los cables conectados a éste conector Update InfoView on hover Actualizar información de la vista en el hover Export Normalized SVG Exportar SVG Normalizado Export 1000 dpi SVG of this part in this view Exportar a 1000 dpi SVG de esta parte en esta vista Export Normalized Flattened SVG Exportar SVG Plano Normalizado Export 1000 dpi Flattened SVG of this part in this view Exportar a 1000 dpi SVG plano de esta parte a esta vista Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Girar 90° en sentido horario {45�?} Rotate 90� Clockwise Girar 90° en sentido horario {90�?} Rotate 180� Girar 180° {180�?} Rotate 90� Counter Clockwise Girar 90° en sentido antihorario {90�?} Rotate 45� Counter Clockwise Girar 90° en sentido antihorario {45�?} Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Show/hide the label for the selected parts Straighten Curve Straighten the curve of the selected wire Find part in sketch... Search for parts in a sketch by matching text Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+4 Ctrl+4 Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page Display First Time Help Align Move to bottom layer Move to top layer Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards jumpers copperfill vias Generating %1 fill... ground copper Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Rotate the selected parts by 90 degrees clockwise Girar las partes seleccionadas 90 grados en sentido horario Rotate the selected parts by 180 degrees Girar las partes seleccionadas 180 grados Rotate current selection 90 degrees counter clockwise Girar la seleccion actual 90 grados en sentido antihorario Rotate current selection 45 degrees counter clockwise Rotar la sección actual 45 grados en sentido antihorario Rotate current selection 45 degrees clockwise Rotar la sección actual 45 grados en sentido horario Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal &Invertir Horizontalmente Flip current selection horizontally Invertir la selección actual horizontalmente &Flip Vertical &Invertir Verticalmente Flip current selection vertically Invertir la selección actual verticalmente Bring to Front Traer al frente Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Enviar el o los objetos seleccionados al frente de la capa Bring Forward Traer al frente Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Enviar el o los objetos seleccionados al frente de la capa Send Backward Enviar al fondo Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Enviar el o los objetos seleccionados al fondo de la capa Send to Back Enviar al fondo Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Enviar el o los objetos seleccionados al fondo de la capa Sticky If a "sticky" part is moved, parts on top of it are also moved &Show All Layers &Mostrar todas las capas Show all the available layers for the current view Ocultar todas las capas disponibles para la vista actual &Hide All Layers &Ocultar todas las capas Hide all the layers of the current view Ocultar todas las capas de la vista actual &Export... &Exportar... Export selected part Exportar parte seleccionada Add Bendpoint Añadir un punto de doblez Add a bendpoint to the selected wire añadir un punto de doblez al cable seleccionado Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Actual (real world physical) size Tamaño actual (físico en el mundo real) 100% Size 100% Tamaño 100% (pixel) size 100% (pixel) tamaño Align to Grid Alinear a la Malla Align items to grid when dragging Alienar partes a la malla al arrastrar Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Tips, Tricks and Shortcuts Tips, Trucos y Atajos Parts Editor Help Display Parts Editor help in a browser as Image for Production &Routing Ground Fill Delete Ratsnest Line Delete Wire Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Set both copper layers clickable Elegir ambas capas de cobre al hacer click Shift+Ctrl+3 Shift+Ctrl+3 Set copper top layer clickable Elegir la primera capa de cobre con un click Shift+Ctrl+2 Shift+Ctrl+2 Set copper bottom layer clickable elegir la última capa de cobre con un click Shift+Ctrl+1 Shift+Ctrl+1 &Create trace from ratsnest Ctrl+Shift+V Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show Code Show the code (programming) view Autoroute connections... Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Seleccionar Todos los Jumpers Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Check Loaded Traces Copper Top and Copper Bottom layers are both active La Primera y la Última capa de cobre estan activas Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Do you want to update now? OK Aceptar Set the grid size for %1. Grid Size: Tamaño de la Malla: in dentro mm mm Restore Default Restauración predefinida Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Copper Top layer is active La primera Capa de Cobre esta activa Copper Bottom layer is active La Última capa de cobre esta activa Autorouting Progress... Progreso del Autoruteo... Launch %1... Lanzar %1... No outdated parts found. All your parts are up-to-date. No se encontraron partes atrasadas. Todas tus partes estan al día. Outdated parts partes Atrasadas Successfully updated %1 part(s). Please check all views for potential side-effects. %1 parte(s) actualizadas con éxito. Porfavor verifica todas tus vistas por posibles efectos secundarios. Update %1 part(s) %1 parte(s) actualizada(s) &Zoom In &Acercar Shell launch %1 Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Open programming window Abrir ventana de programación Open microcontroller programming window Abrir ventana de programación del microcontrolador Ctrl++ Ctrl++ Zoom in Acercar Ctrl+= Ctrl+= &Zoom Out &Alejar Ctrl+- Ctrl+- Zoom out Alejar &Fit in Window &Ajustar a la ventana Ctrl+0 Ctrl+0 Fit in window Ajustar a la ventana &Actual Size &Tamaño Actual Shift+Ctrl+0 Shift+Ctrl+0 &Show Breadboard &Mostrar Protoboard (placa de Prototipos) Ctrl+1 Ctrl+1 Show the breadboard view Mostrar Protoboard (placa de Prototipos) &Show Schematic &Mostrar Esquema Ctrl+2 Ctrl+2 Show the schematic view Mostrar Vista de Esquema &Show PCB &Mostrar PCB (Circuito Impreso) Ctrl+3 Ctrl+3 Show the PCB view Mostrar la vista de PCB (Circuito Impreso) &Minimize &Minimizar Ctrl+M Ctrl+M Minimize current window Minimizar la ventana actual Debugger Output Salida del depurador Ctrl+? Ctrl+? Open Fritzing help Abrir ayuda de Fritzing Open Fritzing examples Abrir Ejemplos de Fritzing Open Parts Reference Abrir la referencia de partes First Time Help Ayuda de primera vez &About &Acerca Display some handy Fritzing tips and tricks Mostrar algunos tips y trucos utiles de Fritzing Report a bug... Reportar un bug... Enable debugging log Permitir el archivo de depuración &Import parts and bins from old version... &Importat partes y compartimientos de una versión anterior... Import parts and bins from previous installation Importar partes y compartimientos de una instalación previa &File &Archivo &Export &Exportar Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. ¡Tu bosquejo no tiene aún una placa! Porfavor añade un PCB para poder exportar a Gerber. Choose a folder for exporting Selecciona un folder para exportar Export SVG... Exporta SVG... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Exporta la Lista de Red... Tidy Wires Ordenar Cables Tidy selected wires Ordenar cables selecionados Remove copper fill Remover las pistas de cobre Remove Bendpoint Quitar Punto de Dobles Select all jumper item parts Select All Vias Select all via parts Please choose the previous Fritzing folder... Porfavor elije el folder de Fritzing anterior... You will have to restart Fritzing in order to use the imported parts Tendrás que reiniciar Fritzing para poder usar las partes importadas &Wire Color &Color del Cable &Edit &Editar JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... Select outdated parts Selecciona partes obsoletas Update selected parts Actualizar partes selecionadas Online Tutorials Tutoriales en línea Online Projects Gallery Galeria de proyectos en línea Online Parts Reference Referencia para partes en línea &Part &Parte &View &Vista &Window &Ventana &Help &Ayuda Page Setup Configurar Página Sorry, "%1" has not been implemented yet Disculpa, "%1" no se ha implementado aun Copper Fill Relleno de Cobre Remove Copper Fill Quitar el Relleno de Cobre Remove the copper fill Remover el relleno de cobre Autorouting... Autoruteando... Undo Deshacer Redo Rehacer Select a Fritzing File to Open Seleccionar un archivo Fritzing para abrir &Show part label &Mostrar la etiqueta de la parte Export Bill of Materials (BoM)... Exportar Lista de Materiales(BoM)... Add a note Agregar nota Add Note Agregar Nota Check for updates... Buscar actualizaciones... Check whether a newer version of Fritzing is available for download Comprobar si hay una nueva versión de Fritzing disponible para descargar Select All Traces Seleccionar Todas las Trazas Select all trace wires Seleccionar Todas las Trazas Select all trace wires excluded from autorouting Seleccionar todas las trazas excluidas del autoruteo Do you want to keep the imported parts? ¿Desea quedarse con las partes importadas? &About Qt &Acerca de Qt Show Qt's about box Mostrar el dialogo acerca de QT Report a but you've found in Fritzing Reporta un error que haz encontrado en Fritzing This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Aquí encontraras pronto una opcion para exportar tu archivo de Fritzing a al Software EAGLE. Si deseas tener más opciones para exportar a tu herramienta favorita avisanos mediante el foro o contribuye con nosotros. Sorry! Disculpa! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No hay una parte con esas caracteristicas Estamos trabajando para evitar este mesaje y permitirte seleccionar propiedades que existan Swapped %1 with module %2 Se intercambió %1 por módulo %2 All traces have not yet been routed. No se ha ruteado ninguna traza. Do you want to proceed anyway? ¿Desea Proceder con la Operación? Raise and Lower Aumentar y disminuir Inspector Inspector Undo History Historia Deshacer Breadboard Protoboard Schematic Esquema PCB PCB Layers Capas Couldn't get the dock widget No se puede obtener el widget del dock MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! ¡Error! archivo ¡No guardado! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) No se puede sobre escribir el archivo '%1'. Razóon%2 (errcode %3) MysteryPart label etiqueta chip label etiqueta del chip NetLabel net label Note [write your note here] [escribe tu nota aquí] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Da click sobre este conector para arrastrar una nueva traza. Change trace layer Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. ¡Tu bosquejo no tiene una placa aún! Porfavor añade un PCB para poder crear las pistas de cobre. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Error de Fritzing: imposible hacer la placa svg (1). Fritzing error: unable to render copper svg (1). Error de Fritzing: Imposible hacer svg de cobre (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor Editor de Partes SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Icono Metadata Connectors Conectores Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Ctrl+4 Show the icon view Ctrl+5 Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Archivos de Imagen y Huellas (%1 %2 %3 %4 %5);;Archivo SVG (%1);;Archivo JPEG (%2);;Archivo PNG (%3);; Archivo de Huellas gEDA (%4);;Archivo de Modulos Kicad (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Archivos de Imágenes (%1 %2 %3);;Archivo SVG (%1);; Archivo JPEG (%2);; Archivo PNG (%3) {1 %2 %3)?} {1)?} {2)?} {3)%4%5?} Open Image Abrir Imagen Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Problema de conversión Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Capas Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 no se encontraron huellas en %1 Relocate connector %1 &File &Archivo Inspector Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Exportar &Edit &Editar This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Guardar Cancel Cancelar Move terminal point Remove connector Remove %1 connectors Save "%1" Guardar "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Agregar conector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Autor Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Descripción Set the default part label prefix Label Etiqueta Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Propiedades Set the part's tags Tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size Tamaño del hoyo advanced settings in dentro mm mm Hole Diameter Diametro de la perforación Ring Thickness Grosor del anillo PartLabel Edit Editar Edit label text Editar Etiqueta de Texto Hide Hide part label Display Values Mostrar Valores Flip/Rotate Invertir/Rotar Font Size Tamaño de la Fuente Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Girar la etiqueta 90 grados en sentido horario Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Girar la etiqueta en 180 grados Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Girar la selección actual 90 grados en sentido antihorario Rotate 45� Clockwise Girar 90° en sentido horario {45�?} Rotate 90� Clockwise Girar 90° en sentido horario {90�?} Rotate 135� Clockwise Girar 90° en sentido horario {135�?} Rotate 180� Girar 180° {180�?} Rotate 135� Counter Clockwise Girar 90° en sentido antihorario {135�?} Rotate 90� Counter Clockwise Girar 90° en sentido antihorario {90�?} Rotate 45� Counter Clockwise Girar 90° en sentido antihorario {45�?} Rotate the label by 45 degrees counter clockwise Flip Horizontal Invertir Horizontalmente Flip label horizontally Invertir etiqueta horizontalmente Flip Vertical Invertir Verticalmente Flip label vertically Invertir Etiqueta Verticalmente Tiny Set font size to tiny Small Pequeño Set font size to small Seleccionar el tamaño de fuente a pequeña Medium Mediana Set font size to medium Seleccionar el tamaño de fuente a mediana Large Grande Set font size to large Seleccionar el tamaño de fuente a grande Label text Etiqueta de texto Display the text of the label Muestra el texto de la etiqueta Display the value of property %1 Muestra la propiedad del valor %1 Set label for %1 Pon la etiqueta a %1 Label text: Etiqueta de texto: PartsBinPaletteWidget Specify a file name Especifica un nombre para el archivo Fritzing Fritzing Cannot find file %1. Imposible encontrar archivo %1. Cannot read file %1: %2. Imposible leer archivo %1:%2. loading bin '%1' Save Guardar Fritzing Bin (*%1) Compartimiento de Fritzing(*%1) Loading... Save bin "%1" Guarda el compartimiento "%1" Do you want to save the changes you made in the bin "%1"? ¿Quieres guardar los cambios que hiciste en el compartimento "%1"? Don't Save No Guardar Ctrl+D Ctrl+D Cancel Cancelar Add to bin Agregar al catálogo Do you really want to add the selected part to the bin? ¿Realmente quieres agregar la parte seleccionada al catálogo? Change icon color... Change the color of the icon for this bin. Select a color for this icon Your changes will be lost if you don't save them. Los cambios se perderán si no se guardan. Untitled Bin Catalogo Sin Nombre Perfboard size tamaño Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel Cancelar rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Cancelar Save Guardar Undo Deshacer Redo Rehacer PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Mouse Wheel Behavior Comportamiento de la Rueda del Ratón Command Comando Control Control Change Wheel Behavior Cambiar el Comportamiento de la Rueda Cancel Cancelar General Code View OK Aceptar Autosave Autoguardar Autosave every: Autoguardar cada: minutes minutos Language Idioma Colors Colores %1 (click to change...) %1 (click para cambiar...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab Select a program file to load Selecciona un archivo de programa para cargar While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Nuevo Open Save Guardar Platform Board Placa Port Serial Monitor Upload Fritzing is unable to find '%1', please locate it Fritzing no puede encontrar '%1', porfavor localizalo Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit &Editar Undo Deshacer Redo Rehacer &Cut &Cortar Cut selection Cortar selección &Copy &Copiar Copy selection Copiar selección &Paste &Pegar Paste clipboard contents Pegar contenido del portapapeles &Select All &Seleccionar todo Select all text &Preferences... &Preferencias... Show the application's about box Mostrar el dialogo acerca de la aplicación &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Placa Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 %1%2 &View &Vista File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings pcb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint bb bb Breadboard View Vista de Protoboard (placa de Prototipos) Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> icon view Vista de Iconos breadboard view Vista de Protoboard schematic view Vista de Esquema pcb view Vista de PCB Part Parte Wire Cable Set Grid Size Cannot read file %1: %2. Imposible leer archivo %1:%2. Parse error (1) at line %1, column %2: %3 %4 Error de Parseo (1) en la línea %1, columna %2: %3 %4 The file %1 is not a Fritzing file (2). Este Archivo %1 no es un archivo valido de Fritzing(2). The file %1 is not a Fritzing file (3). Este Archivo %1 no es un archivo valido de Fritzing (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. No se encontraron Partes. Parse error (2) at line %1, column %2: %3 %4 Error de Parseo (2) en la línea %1, columna %2 :%3 %4 The part '%1' at '%2' does not have a unique module id '%3'. La parte '%1' en '%2' no tiene un identificador único de módulo '%3'. a label Una Etiqueta a value Un valor PCB View Vista de PCB Preferences Preferencias Oops! Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Disculpa, pero tenemos un problema con el mecanismos de intercambio Fritzing segirá funcionando, pero no podrás cambiar las propiedades de las partes. schem esquema Schematic View Vista de Esquema Error reading file %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer %1 Capa Bring forward Traer hacia adelante Send backward Enviar hacia atrás Bring to front Traer al frente Split Wire Separar Cable Join Wire Unir Cable Select locked parts Icon Icono Breadboard Protoboard Parts Partes Wires Cables Ratsnest Rulers Regla Frame Text Board Placa Silkscreen Top Primera pantalla de serigrafía Silkscreen Top (Part Labels) Primera pantalla de serigrafía (Etiqueta de Partes) Copper Fill Bottom Copper Fill Top Copper Bottom Fondo de Cobre Copper Bottom Trace Fondo de Trazo de Cobre Copper Top Superficie de Cobre Copper Top Trace Superficie de trazo de Cobre Silkscreen Bottom Fondo de serigrafía Silkscreen Bottom (Part Labels) Fondo de serigrafía (Etiquetas de partes) Part Image Unknown Layer Capa Desconocida Please note that a new language setting will not take effect until the next time you run Fritzing. Recuerda que los cambios de en la configuración del idioma no surtirán efecto hasta la próxima vez que inicies Fritzing. Part Labels Etiquetas de partes Notes Notas Trace wires Trazas Ratsnest wires Cables del Nido de Ratas Select all %1 Seleccionar todos los %1 Check for updates Buscar actualizaciones The file '%1' is read-only; please use a different filename. El archivo '%1' es de sólo lectura; por favor, selecciona otro nombre. Edit link Editar Vinculo The file %1 is not a Fritzing file (4). El archivo %1 no es un archivo de Fritzing (4). Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin Esta parte ya se encuentra en el contenedor The part that you have just added, is already there, we won't add it again, right? La parte que acabas de agregar ya se encuentra ahí, no la vamos a agregar de nuevo ¿o si? File Progress... Archivo en Progreso... Select outdated parts Seleccionar partes obsoletas files archivos unable to open %1 Imposible abrir %1 unable to parse %1 Imposible analizar %1 parse failure in %1 fallo el analisis en %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Una disculpa, Fritzing aún no puede manejar ambos pines y pads juntos (en %1) bad pin argument count Mal conteo de argumentos en pines bad pad argument count Mal conteo de argumentos en el pad Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 huella %1 no encontrada en %2 unexpected end of file in footprint %1 in file %2 Inesperado fin del archivo en la huella %1 en el archivo %2 unexpected format (1) in %1 from %2 formato inesperado (1) en %1 de %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Una disculpa, Fritzing aún no puede manejar ambos pines y pads juntos (en %1 en %2) unexpected end of file Inesperado fin de archivo pad missing drill falta el pad del barreno pad missing attributes faltan atributos del pad pad missing position falta posición del pad pad missing shape falta forma del pad position missing params parametros de posicióon faltantes drill missing params parametros del barreno faltantes drill offset not implemented drill missing ellipse params faltan parametros para los barrenos circulares attributes missing params parametros de atributos faltantes bad layer mask parameter Mal parametro de la capa de máscara Sorry, can't handle pad type %1 Lo siento, no puedo manejar ese tipo de pad %1 pad shape missing params faltan parametros de forma del pad pad shape size is invalid shape delta not implemented forma delta no implementada trapezoidal pads not implemented pad trapezoidales no implementados non-circular holes not implemented hoyos no circulares no implementados non-copper holes not implemented hoyos sin cobre no implementados unable to handle pad shape %1 Imposible de manejar la forma del pad %1 failure in svg conversion 1: %1 %2 %3 fallo en la conversión svg 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 fallo en la conversión svg 2: %1 %2 %3 Copying file %1 Copiando archivo %1 File %1 already exists: it won't be overwritten El Archivo %1 ya existe: no será sobre escrito Select %1 Selecionar %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm mm in dentro Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Recuperar &Ignore &Ignorar Resistor Resistor resistance Resistencia You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape forma width: %1mm ancho: %1mm height: %1mm altura: %1mm width(mm) ancho(mm) height(mm) alto(mm) keep aspect ratio Revert size tamaño custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width Ancho S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 Cambiar el voltaje de %1 a %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Hacer este el color determinado %1 Cancel Cancelar OK Aceptar Pick custom %1 color Current color (%1) SketchWidget loading part cargando parte done loading carga terminada %1 %2 %1 %2 %1 %2 items %1 %2 items Select All Seleccionar Todo Deselect Deseleccionar Add %1 Agregar %1 Move %2 (%1) Mover %2 (%1) Move %2 items (%1) Mover %2 items (%1) Select %1 Selecionar %1 Select %1 items Selecionar %1 items Disconnect Desconectar Change Cambiar Connect Conectar to %1 a %1 Create and connect wire Crear y conectar Cable Rotate %2 (%1) Rotate Girar Flip Invertir Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Note text change Change %1 color from %2 to %3 Cambiar el color de %1 de %2 a %3 Change color of %1 wires to %2 Cambiar color de %1 cables a %2 Resize ruler to %1 %2 test connectors Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Cambiar el tamaño de la placa a %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all Change %1 label to '%2' Cambiar la etiqueta %1 a '%2' Double-click to delete this bend point Move label '%1' Mover etiqueta '%1' %1 label '%2' %1 etiqueta '%2' Selection Selección show %n part label(s) hide %n part label(s) Resize Note Cambiar tamaño de la Nota Change %1 width from %2 to %3 Cambiar el ancho de %1 de %2 a %3 Change width of %1 wires to %2 Cambiar el ancho de %1 cables a %2 SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage voltaje label etiqueta Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Tips y Trucos Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width Ancho TranslatorListModel English - %1 Inglés - %1 French - %1 Francés - %1 German - %1 Alemán - %1 Spanish - %1 Español- %1 Hungarian - %1 Hungaro - %1 Estonian - %1 Estonio - %1 Dutch - %1 Holandés- %1 Danish - %1 Russian - %1 Ruso- %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Italiano- %1 Chinese (Simplified) - %1 Chino (Simplificado) - %1 Chinese (Traditional) - %1 Chino (Tradicional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 Japanese - %1 Japonés - %1 Hebrew - %1 Hebreo - %1 Arabic - %1 Árabe - %1 Hindi - %1 Hindú - %1 Portuguese (European)- %1 Portugues (Europeo)- %1 Portuguese (Brazilian) - %1 Portugues (Brasileño) - %1 UpdateDialog Close Cerrar No new versions found. No se encontraron versiones nuevas. A new main release is available for downloading: Hay una nueva versión principal disponible para descargar: A new interim release is available for downloading: Hay una nueva versión provisional disponible para descargar: Checking... Comprobando... Sorry, unable to retrieve update info Perdón, no se puedo recuperar la información de actualizaciones WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) delgado (16 mil) standard (24 mil) standard (24 mil) thick (32 mil) grueso (32 mil) extra thick (48 mil) extra grueso (48 mil) blue azul red rojo black negro yellow amarillo green verde grey gris white blanco orange naranja ochre cyan brown café purple morado pink color Color Banded ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_et.qm000066400000000000000000000000271250202676700217100ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Best So Far Cancel Stop Now Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Import files from previous version? Import Do not import now Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Save... Save Don't Save Ctrl+D Your changes will be lost if you don't save them. Cancel GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Connections conn. connected to %n item(s) name Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Locked location rotation degrees type (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete Properties Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Tags ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Ready Save %1 Unable to open '%1': %2 Specify a file name Fritzing (*%1) Fritzing Unable to export %1 as shareable Fritzing Part (*%1) Unable to export %1 to shareable sketch Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) Printing... All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Select a Fritzing File to Open Cannot find file %1. Cannot read file 1 %1: %2. directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... New File '%1' not found Ctrl+N Create a new sketch &Open... Ctrl+O BoM Text File (*.html) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website Export the visible area of the current sketch as a JPG image Export the visible area of the current sketch as a PNG image Export the visible area of the current sketch as a PostScript image Export the visible area of the current sketch as a PDF image Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box &Edit &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Straighten Curve Straighten the curve of the selected wire Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page Delete Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Sticky If a "sticky" part is moved, parts on top of it are also moved &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Show part label &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Select outdated parts Update selected parts Actual (real world physical) size 100% Size 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Tips, Tricks and Shortcuts Report a bug... Enable debugging log Parts Editor Help Display Parts Editor help in a browser as Image for Production &Routing Ground Fill Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 &Create trace from ratsnest Ctrl+Shift+V Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Ctrl+5 &Show Welcome Show the welcome view Show Code Show the code (programming) view Display First Time Help Autoroute connections... Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Wires Select all wires Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Check Loaded Traces Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting Progress... jumpers copperfill vias The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. No outdated parts found. All your parts are up-to-date. Outdated parts Do you want to update now? Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Update %1 part(s) &Zoom In Shell launch %1 Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Show/hide the label for the selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Shift+Ctrl+0 &Show Breadboard Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Ctrl+4 &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Display some handy Fritzing tips and tricks &About Qt Show Qt's about box Report a but you've found in Fritzing &Import parts and bins from old version... Import parts and bins from previous installation &File &Export &Part Raise and Lower Align &View &Window &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Page Setup Sorry, "%1" has not been implemented yet Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Generating %1 fill... ground copper Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Select All Traces Select all trace wires Select All CopperFill Select all copper fill items Select all trace wires excluded from autorouting Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Copper Fill Remove Copper Fill Remove the copper fill Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Autorouting... Remove Bendpoint Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts Remove copper fill &Wire Color Launch %1... Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Metadata Connectors Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Save Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Change icon color... Change the color of the icon for this bin. Select a color for this icon Do you want to save the changes you made in the bin "%1"? Don't Save Ctrl+D Your changes will be lost if you don't save them. Save bin "%1" Cancel Add to bin Do you really want to add the selected part to the bin? Perfboard size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Mouse Wheel Behavior Command Control Change Wheel Behavior Cancel General Code View OK Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab Select a program file to load While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Open Save Platform Board Port Serial Monitor Upload Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject bb Breadboard View Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Edit link Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value PCB View pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. schem Schematic View Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select all %1 Select locked parts File Progress... Check for updates icon view breadboard view schematic view pcb view Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer Select outdated parts files unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid shape delta not implemented trapezoidal pads not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 Copying file %1 File %1 already exists: it won't be overwritten Select %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Rotate Flip Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all test connectors Disconnect all wires from %1 show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 Disconnect all wires from %1 items SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_fa.qm000066400000000000000000000001771250202676700216740ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: با تشکر فراوان از: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save... Save Don't Save Cancel Ctrl+D Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Placement pcb layer Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Breadboard Schematic PCB Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Export for PCB Ready Save %1 Fritzing No Sketch found in '%1' Unable to open '%1': %2 Click to highlight unconnected parts Fabricate View from Above View from Below Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Fritzing (*%1) Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector Undo History Layers Couldn't get the dock widget PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Choose a folder for exporting Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Unable to export %1 as shareable &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Etchable (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export SPICE Netlist... Export Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Cannot find file %1. Cannot read file 1 %1: %2. Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? File '%1' not found the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Delete Wire &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box Edit (new parts editor) Open the new parts editor on an existing part &Add to bin... Add selected part to bin Disconnect All Wires Ctrl+Shift+V Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show part label Show/hide the label for the selected parts &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Ctrl+4 Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser &File &Export as Image for Production &Edit &Part Raise and Lower Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align &View &Window &Routing Ground Fill &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Traces Select all trace wires Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select all trace wires excluded from autorouting Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Shift+Ctrl+D Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Check Loaded Traces Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show Code Show the code (programming) view Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting Progress... jumpers copperfill vias Remove Bendpoint Please choose the previous Fritzing folder... The folder "%1" isn't a Fritzing installation folder You will have to restart Fritzing in order to use the imported parts Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill &Wire Color Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Do you want to update now? unable to find replacement for %1. Update %1 part(s) Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Change trace layer Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon Metadata Connectors SVG Inspector Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Show in Folder On the desktop, open the folder containing the current svg file. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection &File Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit Parts Editor This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to write svg to %1 Unable to parse fzp file %1 Fritzing (New) Parts Editor Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Show Metadata Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Change description Change %1 to '%2' Change tags Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Change properties Change connector %1 SVG problem This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Conversion problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Unable to load image file '%1': %2 Unable to load image file '%1' Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. Copy problem Unable to make a local copy of: '%1' no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center W N S E center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Save Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel OK Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Part %1 '%2' Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Set Ground Fill Seed Ground Fill Seed Editor Pin Label Editor Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> Edit link mm in The file '%1' is read-only; please use a different filename. Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Fritzing cannot load the parts bin Basic Input Output ICs Power Connection Microcontroller Breadboard View Schematic View PCB View Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 Set all to: Pad ii Icon View Internal Connections <b>Name:</b> Set the connectors's title <b>id:</b> <b>type:</b> <b>Description:</b> Set the connectors's description files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Select all %1 Convert to Via Convert Via to Bendpoint schem Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) mask export failure Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer icon view breadboard view schematic view pcb view Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading Delete ratsnest %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect from %1 Move leg of Connect to %1 Change leg curvature for %1. Change leg bendpoint for %1. Change Create and connect wire Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Rotate %2 (%1) Flip %2 (%1) Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Rotate Flip show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 test connectors Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_fr.qm000066400000000000000000007557031250202676700217310ustar00rootroot00000000000000;}FdH/UH9IXIXIXhJ6oKQL4cM6MeM5P,E{PWRU Rx:R[VgQV2VVCWmBWXR=XY{1YIZ8,f[ %C[f3[[f34\]4w^̆_Cg1`MbpРc7lgei'i jcbX=jcbjcb/jɢkt{mծn nrxrx!tZtouiPsuiQujvwmny5yeWEye[yeyeQye~yeyyzlPzlQzzQ{ %{{}}s}|UW]r(P55:1L_R0_^R@~$5'kT"Fc --u9[u<T3?>%DABnFP#ItRWlZ>b$  V#JN[:V\7} GV"by&aH)tP){))**8/SN2XT4e6v9Y?yHJvgvL#4L4wpMEO.MTZ>X]0e>eAqr7{(y2EN[]5Ed`},Դe$'C  KpPhXrN2PCxJ`]#v!mN.R6l˓͌Ӓ2HӒ2ԲI{oجNK.;6wK _iVRUfdP[13d 1&W.SA0n444#h:';XN@^?..BɢBUC>DJĮȡN̮jQQ˯N[RԢSBNTIYXYY¦YZ]\ϰ^4MfjlTRl*pt.XtibtsuTTzu5uTYxexeUxicey9|D} 'R9SpK2.zsSk"TIZ2şq^In~WL.;A;Ag$uZu`1±ZM±_bĵSd:E.aY1a^HS!c~7nЬnр[bn@\Tu!.mC[`ebQ60npq & 5 5afT7TY>[k~T6J3C.mRo4 6;c=5>HhFJCF[F.H0AK'NaRBRVOV|>SXMYE'hWw"nkqp>rxYsu|͢} nF$oŸMB V\r|[qX*%^-q"ڮ~@>g'$ܡǒeտֺHDfds"QdcgelSɠ(*Hcsu~eI6Pr Iun,9D"B:'e\;(Ï=*Z!-.5j;N 5=>E G$G_>_Ke.EPѧgTD,;XfZe#Ze҈avcO_Gc.8jNKrRrt!zb{eD0f|/}|oud} b"n)D^́!JׅӲ<]1b:6 gffpɱAIAI!,ILI;IIII.IgIpRIv;IyHIz,ZEeda6zeov)PRG %;!*d,Zb&YN#MYQ" 4~~y@9:ka zٶhۘZlDTBО]:fQLF`X;oqvp1^  ~hsĵ^+}UgC(.(,]58[;\ ?) )Tk 1xiOY Bx.?(TcKqצׯ8َEَ qW+#՞*^m7;Hn\)g7 ӕgNgDgUrZ_X-,$k"޼$k2$kBb%r)5)9+T-ڎy .#s?3Ls9;7$> Eu@E= K_EOQ0QMRNU\X$Z^z!k^f_p{_z5`r5i\ شllpIqW:tr |ttĕzi| @t[;z}QCn.qQ>/J|U|iN 0].]'ueB >euZPZP%v>PY9٭]#]E#}DYD^LXL]bW8=9@95T֣x֣:j\oh (m׹ޛ Fne!ci-Q9[lDwA6H*'p  \ 399^!>"S #&|8#t'Sa((P-3e. NG./S51,;!QSaY#<\u\D`%i`cЬcEi=hiAN0ikkkrVs$҉sNntQ|%p~'&&Eʳ~A>mYy/ZKQ   W 0mt8Lҙ  E4l4a.Kg)IFW-?>\OߺDCA.R@>{^;p%YA0k3ghCSp(c %`&)w,ι4-Bu$25AwzCEpE:`FUF?UH4Ht H+I'N|O;3P1MSW;EYQdY´cC^ai-:b]AfCpjfCf|cfg{hТi'mivy8wJx|yz./|Ԃ|^`|^eA Li4o"Q-.~61b*x,FXNRxR+>S-SԤ{% {>t[~sI$nr*yG@a "3bMn6dΝʗ/WК{л%AS"E+:cra';e T5F O \~^ +  Es$ |U . w. e  e  !y $)~5 .5~Dy 0m 0!S 5Gj 6TM ;=" BUc ExZ Gȧr P_t Q S;{ Se \u: ` aBp a^! cϥvO d`! lOi l t7S uia u+ |@p̳ ~ . \ ~Sf7 N 2 @ r_ ^ d 8ɶ ;. a D  +9 B1\ N! . : cJ ~  smZ Ŧ H-7  89r , 3$ ;/ ՛~W .1 {u] Y  P ~  D% v  i< .  ?"Ew CD\ D)Ӆ M  { N=AW P8 UG [>q ^5& a4  c3s c3 do d8z eK eR] e{a e fj g7 k2) k2p qw7 su tq & v) w5b N{e Ȑ/ y; T ' ~: ^Z #U , ^P Dv +8  "n 9t 93 NJ Ɍ4 v3 v= ώ.T Ϯ  ҌR 0{d 0 ˺k K [ ,v ;' cC S Y pn Uw S ; T B 2 VQ ~/m ~l  g n !_g #em %4 ( ) )* )z * *< -# -mn 8)c ? 8 HOo Jgۗ K2gaN K2g N>2Z V YE^?* Ys \i bR gb} go gy`` i$e l? m7EH pfY qt )8 7k 1 W @ ͗ !  4 @Y @+ L y -n ,.) a Nz  ^E) qŹ 5 Nf ARQ }' pM  ZS Y~ ƽ~ +I %[ 1 V KGv  5 t[; k 4 m >^  6 y tj w; C L I G e  .u `   R # %^#+ %^Z ,\7 -4 /~% 9sd ;z" ;> = @MX AiT C~vU F^G L.5? M&`+ O~ Qb Wj` XM"Wz _| `l> af]* eu eZ( hȾ" o ro rn tw z nhY z n {7( " ]DJ @q N. C $ ) - @ ! ^sB G( ,B ,g  j2 | /g /  ' +, * P Jp W f 1D m4 >F Ex . 9lM T7 Y[G ?j L ̚O '  o- K } ~;x } . `@J ` on U% ˞ J (b %z jA fh 2 y| nc !>x7 #Ѯ( /.N 3F4 3f4k 7nS < >O ?څ A8 Az DA DD+ G07 LR R/ Tp. X4I Zgv [  _k cP c!R f fk1] i kc m[a75 qUQ u;B vQD v vC }} #iR }7 3   15c # s O ~ zx  t k ~] & @  R ¦e <|d ՞ ^W cY N " ͤ $f em _U ^Cv   a)  9$^y7Xw  bD1FP3${j rc~([,#/9;ʱKVX a.a.kb ce~RfTpfTft(v8%@w=)Oyy^e~C5~o#{Utn9nh O:Q>q$O) " UpSRNʅxOUxTD ãCcbiuŅ Ņ=AqtM!4t+ xuCECnAX]^F$Yy+>s.Mj]C~u]  yR x~Guhk"TN'$]^$$2A/`i 11݄=3 =V=_@*@sC4eO(;T4WK]t1^Sav! d}fg7hXiίi0tpLsVmNvgU vw|>zz :|`#}$7@/fFy}  BFO Yd^Lg:Z>S'z9-aßjcjca~^L"DV'XT)qW@S|W\W|i<b>2007-%1 Universit des sciences appliques de Potsdam (FH Potsdam)</b>%2007-%1 Fachhochschule PotsdamAboutBox<b>GNU GPL v3 pour le code et CreativeCommons:BY-SA pour le reste?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxbBryant Mairs, Uleshka Asher et Daniel Tzschentke.4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxF de l'Universit Bauhaus de Weimar,)Department of Bauhaus-University Weimar, AboutBoxf Durrell Bishop, David Cuartielles, Fabian Hemmert,3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBox4 Fritzing un tour d'essai.Fritzing a test spin. AboutBox4Fritzing est ralis par :Fritzing is made by: AboutBoxjFritzing a t rendu possible grce au financement de0Fritzing is made possible with funding from the AboutBoxT Gero Herkenrath, Jeff Hoefs, Tom Hulbert,*Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxjIxDS, un donneur anonyme, Parallax, Picaxe, Sparkfun,6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBox\ Jonathan Cohen, Marcus Paeschke, Omer Yosha, -Jonathan Cohen, Marcus Paeschke, Omer Yosha, AboutBoxl Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir,6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxr MWFK Brandenburg, le parrainage du Dpartement du Design0MWFK Brandenburg, the sponsorship of the Design AboutBoxL Mariano Crowe, Johannes Landstorfer, %Mariano Crowe, Johannes Landstorfer, AboutBoxB Michaela Vieser et Julia Werner.!Michaela Vieser and Julia Werner.AboutBox Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, @Prof. Reto Wettach, André Knörig, Myriel Milicevic, AboutBox`Un merci tout spcial aussi tous les tudiants4Special thanks goes out as well to all the students AboutBox4Remerciements spciaux :Special thanks goes out to: AboutBoxMerci Kurt Badelt et Miguel Solis pour la traduction en espagnol,DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBoxX Tom Igoe, Hans-Peter Kadel, Till Savelkoul,,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBoxf Travis Robertson, Stefan Hermann, Brendan Howell, 2Travis Robertson, Stefan Hermann, Brendan Howell, AboutBoxJ Zach Eveland, Dirk van Oosterbosch, $Zach Eveland, Dirk van Oosterbosch, AboutBox et aux testeurs alpha qui taient assez courageux pour faire avec0and alpha testers who were brave enough to give AboutBoxet grce chaque achat d'un Starter Kit Fritzing ou d'un circuit imprim Fritzing Fab.Land from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab.AboutBoxet Arthur Zanona, Nuno Santos Pessanha, Leandro Nunes, et Gabriel Ferreira pour la traduction en portugais (Brsil).|and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. AboutBox A &#313;ubom&iacute;r Ducho&#328; pour la traduction en slovaque,?to Ĺubomír Duchoň for the Slovak translation, AboutBox` Kaltsas Alexander pour la traduction en grec,0to Alexander Kaltsas for the Greek translation, AboutBoxp Cihan Mete Bahad&#x0131;r pour la traduction en turc,:to Cihan Mete Bahadır for the Turkish translation, AboutBoxb Gianluca Urgese pour la traduction en italien,0to Gianluca Urgese for the Italian translation, AboutBoxb Hiroshi Suzuki pour la traduction en japonais,0to Hiroshi Suzuki for the Japanese translation, AboutBoxX Jinbuhm Kim pour la traduction en coren,+to Jinbuhm Kim for the Korean translation, AboutBoxX Josef Dustira pour la traduction tchque,,to Josef Dustira for the Czech translation, AboutBox Lionel Michel, Yvan Kloster, Alexandre Dussart et Roald Baudoux pour la traduction franaise, ato Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, AboutBoxZ Nikolay Stankov pour la traduction bulgare2to Nikolay Stankov for the Bulgarian translation, AboutBox Nuno Santos Pessanha pour la traduction en portugais (europen),Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxZ Robert Lee pour le chinois (traditionnel),9to Robert Lee for the Chinese (Traditional) translation, AboutBox Steven Noppe et Davy Uittenbogerd pour la traduction en nerlandais,Ato Steven Noppe and Davy Uittenbogerd for the Dutch translation, AboutBox` Vladimir Savinov pour la traduction en russe,1to Vladimir Savinov for the Russian translation, AboutBox| Yuelin et Ninjia pour la traduction en Chinois (simplifi),@to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBoxBMeilleur rsultat jusqu' prsent Best So FarAutorouteProgressDialogAnnulerCancelAutorouteProgressDialog$Arrter maintenantStop NowAutorouteProgressDialog@Commandes de zoom et panoramiquezoom and pan controlsAutorouteProgressDialogJRoutage annul. Nettoyage en cours...$Routing canceled! Now cleaning up... AutorouterLa <b>Marge de scurit</b> est la distance minimale entre les lments en cuivre des difrentes pistes.QKeepout is the minimum distance between copper elements on different nets.AutorouterSettingsDialogUne marge de scurit de 0,01 pouce (0,254 mm) est un bon choix par dfaut.4A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialogAnnulerCancelAutorouterSettingsDialog"Marge de scuritKeepoutAutorouterSettingsDialogNote : au plus la marge de scurit est petite, au plus l'excution de la RDC et de l'autoroutage sera lente.JNote: the smaller the keepout, the slower the DRC and Autorouter will run.AutorouterSettingsDialog$Type de productionProduction typeAutorouterSettingsDialog$Largeur des pistes Trace widthAutorouterSettingsDialogpersonnaliscustomAutorouterSettingsDialogfait maisonhomebrewAutorouterSettingsDialogprofessionnel professionalAutorouterSettingsDialog"Jeu de composantsBin BinManagerBinManager :: setDirtyTab: Impossible de configurer bin '%1' comme sale;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerBinManager :: updateTitle: Impossible de configurer bin '%1' comme sale;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagertImpossible de dfinir un magasin NULL comme celui en cours(Cannot set a NULL bin as the current one BinManager"Fermer le magasin Close Bin BinManager>Fermer le magasin de composantsClose parts bin BinManagerdCopier tous les composants chargs vers l'esquisse#Copy all loaded parts to the sketch BinManagernCopier tous les composants du magasin vers une esquisse)Copy all the parts in the bin to a sketch BinManager6Copier tout vers l'esquisseCopy all to Sketch BinManager0Copier vers une esquisseCopy to Sketch BinManagerDCrer un nouveau jeu de composantsCreate a new parts bin BinManager,Supprimer le composant Delete Bin BinManager(Supprimer le magasin Delete bin BinManager<Supprimer le jeu de composantsDelete parts bin BinManagerXAffficher les composants sous forme de listeDisplay parts as a list BinManagerjAfficher le magasin de composants sous forme d'icnesDisplay parts as icons BinManagerVoullez-vous vraiment supprimer le jeu "%1" ? Cette action est irrversible.EDo you really want to delete bin '%1'? This action cannot be undone. BinManagerVoullez-vous vraiment supprimer'%1'? Cette action est irverssible!.PDo you really want to remove '%1' from the bin? This operation cannot be undone. BinManager:Crer un nouveau composant...Edit Part (new parts editor)... BinManager$Exporter le jeu... Export Bin... BinManager0Exporter le composant...Export Part... BinManagerRRechercher un composant dans une esquisseFind Part in Sketch BinManagerImporter... Import... BinManagerCharger un composant Fritzing (.Fzpz), ou un jeu de composants Fritzing (.Fzb, Fzbz)CLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManager8Nouveau jeu de composants... New Bin... BinManager<Nouveau jeu de composants (%1) New bin (%1) BinManagerComposantsParts BinManagerfVeuillez choisir un nom pour le jeu de composants :!Please choose a name for the bin: BinManagerJMagasin de composant en lecture seule Read-only bin BinManager,Supprimer le composant Remove Part BinManager<Supprimer du jeu de composantsRemove from Bin BinManager<Supprimer du jeu de composantsRemove from bin BinManager$Renommer le jeu... Rename Bin... BinManager:Renommer le jeu de composants Rename bin BinManager@Renommer le jeu de composants...Rename parts bin... BinManager$Enregistrer le jeuSave Bin BinManager4Enregistrer le jeu sous...Save Bin As... BinManager@Enregistrer le jeu de composantsSave parts bin BinManagerPEnregistrer le jeu de composants sous...Save parts bin as... BinManagerxEnregistrer le jeu de composants sous un format compress...&Save parts bin in compressed format... BinManager*Recherche en cours... Searching... BinManagerpSlectionner le fichier Fritzing que vous dsirez ouvrirSelect a Fritzing File to Open BinManagernSlectionnez un fichier de composants Fritzing ouvrir(Select a Fritzing Parts Bin file to open BinManagerNAfficher le magasin sous forme d'icnesShow Bin in Icon View BinManagerNAfficher le magasin sous forme de listeShow Bin in List View BinManagerHCe magasin ne peut pas tre renomm.This bin cannot be renamed. BinManagerImpossible de supprimer le composant "%1"-- il est utilis dans une esquisse4Unable to remove part '%1'--it is in use in a sketch BinManager Une carte svg personnalise a gnralement un ou deux calques de srigraphie et un calque carte. U A custom board svg typically has one or two silkscreen layers and one board layer. Boardd<b>La forme personnalise comporte %n dcoupe.</b>f<b>La forme personnalise comporte %n dcoupes.</b>'The custom shape has %n cutouts.Board<b>La forme personnalise a t charge et vous verrez la nouvelle plaque dans un bref dlai.</b><br/><br/>ZThe custom shape has been loaded, and you will see the new board shortly.

    BoardjLa forme personnalise ne comporte pas de dcoupe</b>'The custom shape has no cutouts.Board <br/><br/>Si vous aviez l'intention d'inclure des dcoupes dans votre forme personnalise et n'avez pas obtenu le rsultat escompt, e

    If you intended your custom shape to have cutouts and you did not get the expected result, BoardCependant, les dcoupes peuvent ne pas tre formes correctement.9
    However, the cutouts may not be formatted correctly.BoardhAvant la production d'un vritable circuit imprim nous vous recommandons de tester votre forme personnalise en utilisant l'option "Exporter > pour la production > Gerber tendu".Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Board,Peut tre charg, mais Can load, butBoard<Vrifier le fichier de contour rsultant avec un logiciel de visualisation de fichiers Gerber pour s'assurer que la forme est conforme aux attentes.<br/><br/>xCheck the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.

    BoardJetez un Sil sur le fichier circle_pcb.svg dans votre dossier d'installation Fritzing composants/svg/core/pcb/. eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. BoardNSlectionnez un fichier image chargerSelect an image file to loadBoardL'image peut tre charge partir de %1, mais %2 Utiliser le fichier ?5The image from %1 can be loaded, but %2 Use the file?BoardZLe reste de ce message concerne les dcoupes.-The rest of this message concerns 'cutouts'. BoardCe sont des trous circulaires ou de forme irrgulire que vous pouvez inclure en option dans une forme sur mesure de circuit imprim<br/><br/>uThese are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.

    Board*Chargement impossibleUnable to loadBoard^Impossible de charger l'image partir de %1 %2Unable to load image from %1 %2Board^parce que le xml n'est pas correctement format*because the xml is not correctly formattedBoardHcar il y a plusieurs calques <board>)because there are multiple layersBoardTcar il y a plusieurs calques <silkscreen0>/because there are multiple layersBoardPcar il y a plusieur calques <silkscreen>.because there are multiple layersBoardDcar il n'y a pas de calque <board>!because there is no layerBoardtmais le circuit imprim lui-mme n'aura aucune srigraphie0but the pcb itself will have no silkscreen layerBoardlsuite un problme XML :%1 la ligne :%2 colonne :%3+due to an xml problem: %1 line:%2 column:%3Boardfichier image image fileBoardXc'est parce que Fritzing demande que vous ralisiez des dcoupes via une opration de "soustraction" ou de "diffrence" dans votre logiciel d'dition graphique vectorielle.it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.Board0charger un fichier imageload image fileBoard.un calque (simple face)one layer (single-sided)Boardhl'lment <board> ne contient aucun lment de forme.the element contains no shape elementsBoardRce svg ne contient aucun lment de forme"the svg contains no shape elementsBoardrle svg ne correspond pas au format de plaque personnalis+the svg doesn't fit the custom board formatBoard4deux calques (double face)two layers (double-sided)Boardmodelershape BoardLogoItem Couleur du texteSelect text colorBreadboardLogoItem6Dfinir la couleur du texteSet text colorBreadboardLogoItemcouleurcolorBreadboardLogoItemzSlectionnez dans la liste droulante, ou entrez une valeur%1/Select from the dropdown, or type in a %1 value CapacitorTAjouter un point de connexion/articulation Add bendpoint ConnectorItemXSupprimer le point de connexion/articulationRemove bendpoint ConnectorItem&Redresser la courbeStraighten curve ConnectorItem& propos&About ConsoleWindow&Quitter&Quit ConsoleWindow OutilsTools ConsoleWindowF%1 est en chevauchement (calque %2)%1 is overlapping (%2 layer)DRCUn trou dans %1 peut se situer au-del des limites de la carte et sera tronqu.JA hole in %1 may lie outside the border of the board and would be clipped.DRC2Vrification RDC annule.DRC was cancelled.DRCxErreur Fritzing : le rendu de la carte en svg et impossible.+Fritzing error: unable to render board svg.DRCJAucune piste ou connecteur vrifier No traces or connectors to checkDRCRepositionnez-les et lancez la RDC nouveau pour dtecter d'autres problmes;Reposition them and run the DRC again to find more problemsDRCLes zones sur votre carte surlignes en rouge sont des connecteurs ou des pistes qui peuvent se chevaucher ou tre trop rapproches.qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRC>Trop prs d'un bord (calque %1) Too close to a border (%1 layer)DRCUne erreur inattendue s'est produite lors du rendu de la SVG--contactez fritzing.org6Unexpected SVG rendering failure--contact fritzing.orgDRC Votre esquisse est prte pour la production : il n'existe pas de connecteurs ou de traces qui se chevauchent ou sont trop rapprochs.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRCCliquez sur un lment dans la liste pour mettre en vidence les chevauchements auxquels il se rfre.BClick on an item in the list to highlight of overlap it refers to.DRCResultsDialog>Rsultat de la vrification RDC DRC ResultsDRCResultsDialogRemarque : les lments de liste et la mise en vidence rouges ne seront pas mise jour lorsque vous modifierez votre croquis - vous devez rexcuter la RDC. La mise en vidence disparatra lorsque vous fermerez cette bote de dialogue.Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialog pour le dbogage for debugging DebugDialog<Supprimer galement le fichierAlso delete the file DeleteDialog Ne pas supprimer Don't remove DeleteDialogSupprimerRemove DeleteDialog(Etiquette de la puce chip labelDip^ Remarque : vous pouvez les importer ultrieurement en utilisant la rubrique "Aide"> "Importer composants et magasins partir d'une ancienne version ..." dans le menu Action.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication4Ne pas importer maintenantDo not import now FApplicationVoulez-vous importer des composants et magasins que vous avez crs avec des versions antrieures de Fritzing? ^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationFritzing a intercept une exception %1 partir de %2 dans l'vnement %33Fritzing caught an exception %1 from %2 in event %3 FApplicationtFritzing a intercept une exception %1 dans l'vnement %20Fritzing caught an exception from %1 in event %2 FApplication~Fritzing a attrap une exception de %1 dans l'vnement %2 : %34Fritzing caught an exception from %1 in event %2: %3 FApplication(Erreur dans FritzingFritzing failure FApplicationImportationImport FApplication`Importer un fichier depuis une ancienne version?#Import files from previous version? FApplicationVeuillez spcifier un nom de fichier .Fzz pour l'enregistrement (annuler supprimera la sauvegarde)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplicationv<br/>La <b>vue de la platine d'essai</b> est destine ressembler un <i>vritable</i> prototype sur platine d'exprimentation.<br/><br/>Dmarrez en faisant glisser un composant depuis le Magasin de Composants, qui se trouve en haut droite. Ensuite insrez d'autres composants et connectez-les en les plaant sur la platine ou en cliquant sur les connecteurs et en tirant des cbles. Le procd est semblable la manire dont vous disposeriez les lments dans le monde physique. <br/><br/>Une fois que vous avez termin votre esquisse dans la vue de la platine d'essai, essayez les autres vues. Vous pouvez basculer entre les vues en cliquant sur les Onglets situs en haut de la fentre. Comme les diffrentes vues correspondent des buts diffrents, les composants auront une apparence diffrente dans les autres vues.
    The Breadboard View is meant to look like a real-life breadboard prototype.

    Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world.

    After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views.FirstTimeHelpDialog.Aide pour les dbutantsFirst Time HelpFirstTimeHelpDialog La vue du <b>Circuit imprim</b> est l'endroit o vous placez les composants sur un circuit imprim physique.<br/><br/>Les circuits imprims peuvent tre raliss chez soi ou dans un petit labo en employant des procds amateurs. Ils peuvent aussi tre envoys des services professionnels de ralisation de circuits imprims en vue d'une fabrication plus prcise.<br/><table><tr><td>La premire chose dont vous aurez besoin est une plaque sur laquelle placer vos composants. Il devrait toujours y en avoir une dans votre esquisse, sinon faites glisser l'icne correspondante depuis le magasin de composants. L'icne correspond cette image droite : </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/> Pour laborer votre circuit imprim, disposez les composants de telle sorte qu'ils tiennent bien dans l'espace de la plaque. Ensuite essayez de les dplacer afin de rduire les longueurs des connexions et d'liminer toute possibilit de confusion. Vous pouvez aussi redimensionner les plaques rectangulaires. <br/><table><tr><td>Une fois les composants tris, vous les reliez par des pistes en cuivre. Vous pouvez tracer des pistes partir de connexions individuelles ou bien utiliser l'autoroutage pour les crer automatiquement. Le bouton Autoroutage est en bas de la fentre. L'apparence du bouton est semblable celle de l'image situe droite : </td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table>The PCB View is where you layout the components will on a physical PCB (Printed Circuit Board).

    PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication.
    The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right:


    To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards.
    Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:
    FirstTimeHelpDialog"Bienvenue dans la <b>vue schmatique.</b><br/><br/>Il s'agit d'une manire plus abstraite de considrer les composants et les connexions que dans la vue de la platine d'essai. Vous disposez des mmes lments que ceux de la platine d'essai, ils ont simplement un aspect diffrent. Cette reprsentation est plus proche des diagrammes habituellement employs par les ingnieurs.<br/><br/> Aprs avoir dessin des cbles entre les composants, vous pouvez utiliser la commande &lt;Majuscule&gt;-clic avec la souris pour crer des points de connexion/basculement et mettre de l'ordre dans vos connexions. La vue schmatique peut vous aider vrifier que vous avez tabli les bonnes connexions entre composants. Il vous est galement possible d'imprimer votre schma fin de documentation._Welcome to the Schematic View

    This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.

    After you have drawn wires between parts, you can press <Shift>-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation.FirstTimeHelpDialog$&Fermer la fentre &Close WindowFritzingWindowAnnulerCancelFritzingWindow4Fermer l'esquisse actuelleClose the current sketchFritzingWindowVoulez-vous enregistrer les modifications faites dans le document "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindow$Ne pas enregistrer Don't SaveFritzingWindowEnregistrerSaveFritzingWindowEnregistrer %1 Save "%1"FritzingWindowEnregistrer...Save...FritzingWindow6Spcifier un nom de fichierSpecify a file nameFritzingWindow~Les modifications seront perdus si vous ne les enregistrez pas.1Your changes will be lost if you don't save them.FritzingWindowAnnulerCancelGroundFillSeedDialog6OK et remplissage en cuivreOK and copper fillGroundFillSeedDialog8OK et remplissage des massesOK and ground fillGroundFillSeedDialogdLa diffrence entre un 'remplissage de masse' et un simple 'remplissage en cuivre' est que dans un 'remplissage de masse' la zone remplie comprend des pistes et des connecteurs qui sont connects des connecteurs dits de 'masse'. Les connecteurs de masse sont gnralement tiquets "GND" ou 'masse', mais parfois ce n'est pas le cas. Il se peut aussi qu'il y ait des rseaux multiples avec un seul connecteur de masse, et vous pourriez vouloir ne pourvoir qu'un seul rseau d'un remplissage. Cette bote de dialogue ne recueille que des connecteurs tiquets "GND" ou 'masse', ainsi que des connecteurs dj choisi comme semences. Cliquez sur un lment pour mettre en vidence ses liens dans l'esquisse. Il est galement possible de choisir un connecteur comme une graine de remplissage de masse en effectuant un clic-droite sur un connecteur et en choisissant l'option "Dfinir semences des masses lors du remplissage " du menu contextuel.The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialogTaille du trou hole sizeHoleLModifier l'tat "Aimant" de ce composant dans cette vue. Quand un composant aimant est dplac, les objets se trouvant au dessus de celui-ci se dplacent galement.pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoViewModifier l'tat de verrouillage du composant dans cette vue. Un composant verrouill ne peut pas tre dplac.OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoViewJModifier l'tiquette du composant iciChange the part label here HtmlInfoViewConnexions Connections HtmlInfoViewVerrouillLocked HtmlInfoViewhImage du composant pour la vue de la platine d'essaiPart breadboard view image HtmlInfoViewBImage du composant pour la vue CIPart pcb view image HtmlInfoViewTImage du composant pour la vue schmatiquePart schematic view image HtmlInfoView<Numro de version du composantPart version number HtmlInfoViewEmplacement Placement HtmlInfoViewProprits Properties HtmlInfoView(Fil d'enchevtrement Ratsnest wire HtmlInfoViewAimantSticky HtmlInfoViewMots-clsTags HtmlInfoView.Relier le fil volant %1 Trace wire %1 HtmlInfoView CbleWire HtmlInfoView*connect %n lment0connect %n lment(s)connected to %n item(s) HtmlInfoView degrsdegrees HtmlInfoViewemplacementlocation HtmlInfoViewnomname HtmlInfoViewobsolteobsolete HtmlInfoView2couche du circuit imprim pcb layer HtmlInfoViewComposantPartItemBase bagubandedItemBaseface infrieurebottomItemBasecapacit capacitanceItemBasecouleurcolorItemBase8Cuivre de la face infrieure copper bottomItemBase8cuivre de la face suprieure copper topItemBase actuelcurrentItemBasedescriptiondescrItemBasefamillefamilyItemBaseFLe fichier de %1 %2 est introuvablefile for %1 %2 not foundItemBasenom du fichierfilenameItemBase formeformItemBasefrquence frequencyItemBasecalqueslayersItemBase&rsistance maximalemaximum resistanceItemBase modlemodelItemBase6problme de modle de picemodel part problemItemBasebotierpackageItemBase(numro du composant  part numberItemBase,espacement des broches pin spacingItemBasebrochespinsItemBasealimentationpowerItemBaseprocesseur processorItemBase projetprojectItemBasecourant nominal rated currentItemBase$puissance nominale rated powerItemBase tension nominale rated voltageItemBasersistance resistanceItemBaseinverserrevItemBasereprsentationshapeItemBasefeuille/docsheetItemBase,srigraphie infrieuresilkscreen bottomItemBase,srigraphie suprieuresilkscreen topItemBase taillesizeItemBaseespacementspacingItemBase titretitleItemBasetolrance toleranceItemBaseFace suprieuretopItemBaseRimpossible de crer le rendu de %1 en svg$unable to create renderer for svg %1ItemBasevariantevariantItemBasetensionvoltageItemBaseAnnulerCancelKicadModuleDialog2Afficher tous les calquesshow all layers LayerPaletteAnnulerCancel LinkDialogtexte :text: LinkDialog url :url: LinkDialog(Affichage impossibleUnable to displayLogoItemFImpossible d'afficher l'image de %1Unable to display image from %1LogoItemLcar le fichier n'a pas d'lment <svg>%because the file has no element���LogoItem���Z�p�a�r�c�e� �q�u�e� �l�e� �f�i�c�h�i�e�r� �n�'�a� �p�a�s� �d�'��l��m�e�n�t� �r�a�c�i�n�e�������$because the file has no root element���LogoItem���&�c�a�r� �l�e� �s�v�g� �e�s�t� �v�i�d�e�������because the svg is empty���LogoItem���p�a�r�c�e� �q�u�e� �c�e�l�a� �s�e�m�b�l�e� ��t�r�e� �u�n� �f�i�c�h�i�e�r� �S�V�G� �e�x�p�o�r�t�� �� �p�a�r�t�i�r� �d�e� �C�o�r�e�l�D�R�A�W� �s�a�n�s� �a�v�o�i�r� �c�h�o�i�s�i� �l�e� �p�a�r�a�m��t�r�e� �"�a�t�t�r�i�b�u�t�s� �d�e� �p�r��s�e�n�t�a�t�i�o�n�"�������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem���>�e�n� �r�a�i�s�o�n� �d�'�u�n�e� �e�r�r�e�u�r� �d�e� �r�e�n�d�u�������due to a rendering error���LogoItem���l�e�n� �r�a�i�s�o�n� �d�'�u�n� �p�r�o�b�l��m�e� �:�%�1� �� �l�a� �l�i�g�n�e� �:�%�2� �c�o�l�o�n�n�e� �:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem����p�o�u�r� �d�e�s� �r�a�i�s�o�n�s� �i�n�c�o�n�n�u�e�s� �-� �l�e� �f�i�c�h�i�e�r� �i�m�a�g�e� �e�s�t� �p�e�u�t�-��t�r�e� �c�o�r�r�o�m�p�u�������9for unknown reasons--possibly the image file is corrupted���LogoItem��� �f�o�r�m�e�������shape���LogoItem���L�V�o�u�l�e�z�-�v�o�u�s� �m�e�t�t�r�e� �� �j�o�u�r� �m�a�i�n�t�e�n�a�n�t� �?������� Do you want to update now?��� MainWindow���8�d�e� �l�'�a�r�r�i��r�e�-�p�l�a�n� �p�o�u�r� �l�a� �%�1������� %1 background��� MainWindow����%�1� �d�e�s� �%�2� �r��s�e�a�u�x� �a� ��t�� �r�o�u�t�� �-� �%�n� �c�o�n�n�e�c�t�e�u�r�(�s�)� �d�o�i�v�e�n�t� ��t�r�e�s� �r�e�l�i��s����%�1� �d�e�s� �%�2� �r��s�e�a�u�x� �o�n�t� ��t�� �r�o�u�t�� �-� �%�n� �c�o�n�n�e�c�t�e�u�r�(�s�)� �d�o�i�v�e�n�t� ��t�r�e�s� �r�e�l�i��s�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow����&�� �p�r�o�p�o�s�������&About��� MainWindow����&�� �p�r�o�p�o�s� �d�e� �Q�t������� &About Qt��� MainWindow����&�T�a�i�l�l�e� �r��e�l�l�e������� &Actual Size��� MainWindow���@�&�A�j�o�u�t�e�r� �a�u� �j�e�u� �d�e� �c�o�m�p�o�s�a�n�t�s�.�.�.�������&Add to bin...��� MainWindow����&�C�o�p�i�e�r�������&Copy��� MainWindow���\�&�C�r��e�r� �u�n�e� �p�i�s�t�e� �e�n� �r�e�m�p�l�a�c�e�m�e�n�t� �d�u� �f�i�l� �v�a�l�a�n�t�������&Create trace from ratsnest��� MainWindow���\�&�C�r��e�r� �u�n�e� �p�i�s�t�e� �c�u�i�v�r�e� �� �p�a�r�t�i�r� �d�u� �f�i�l� �v�a�l�a�n�t�������&Create wire from ratsnest��� MainWindow����&�C�o�u�p�e�r�������&Cut��� MainWindow����&�S�u�p�p�r�i�m�e�r�������&Delete��� MainWindow���&�&�S�u�p�p�r�i�m�e�r� �l�e� �c��b�l�e������� &Delete Wire��� MainWindow����&�D��s��l�e�c�t�i�o�n�n�e�r������� &Deselect��� MainWindow����&�D�u�p�l�i�q�u�e�r������� &Duplicate��� MainWindow����&��d�i�t�i�o�n�������&Edit��� MainWindow����&�E�x�p�o�r�t�e�r�������&Export��� MainWindow����&�E�x�p�o�r�t�e�r�.�.�.������� &Export...��� MainWindow����&�F�i�c�h�i�e�r�������&File��� MainWindow���X�&�A�d�a�p�t�e�r� �l�'��c�h�e�l�l�e� �� �l�a� �t�a�i�l�l�e� �d�e� �l�a� �f�e�n��t�r�e�������&Fit in Window��� MainWindow���4�&�R�e�t�o�u�r�n�e�r� �h�o�r�i�z�o�n�t�a�l�e�m�e�n�t�������&Flip Horizontal��� MainWindow���0�&�R�e�t�o�u�r�n�e�r� �v�e�r�t�i�c�a�l�e�m�e�n�t�������&Flip Vertical��� MainWindow��� �&�A�i�d�e�������&Help��� MainWindow���2�&�M�a�s�q�u�e�r� �t�o�u�s� �l�e�s� �c�a�l�q�u�e�s�������&Hide All Layers��� MainWindow���~�&�I�m�p�o�r�t�e�r� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �e�t� �j�e�u�x� �d�e�p�u�i�s� �u�n�e� �a�n�c�i�e�n�n�e� �v�e�r�s�i�o�n�.�.�.�������*&Import parts and bins from old version...��� MainWindow����&�R��d�u�i�r�e������� &Minimize��� MainWindow���$�&�O�u�v�r�i�r� �u�n� �e�x�e�m�p�l�e������� &Open Example��� MainWindow���8�&�O�u�v�r�i�r� �l�e�s� �f�i�c�h�i�e�r�s� �r��c�e�n�t�s�������&Open Recent Files��� MainWindow����&�O�u�v�r�i�r�.�.�.�������&Open...��� MainWindow����&�C�o�m�p�o�s�a�n�t�������&Part��� MainWindow����&�C�o�l�l�e�r�������&Paste��� MainWindow����&�P�r��f��r�e�n�c�e�s�.�.�.�������&Preferences...��� MainWindow����&�I�m�p�r�i�m�e�r�.�.�.������� &Print...��� MainWindow����&�Q�u�i�t�t�e�r�������&Quit��� MainWindow����&�R�o�u�t�a�g�e�������&Routing��� MainWindow����&�E�n�r�e�g�i�s�t�r�e�r�������&Save��� MainWindow���(�&�E�n�r�e�g�i�s�t�r�e�r� �s�o�u�s�.�.�.������� &Save As...��� MainWindow���$�&�T�o�u�t� �s��l�e�c�t�i�o�n�n�e�r������� &Select All��� MainWindow���4�&�A�f�f�i�c�h�e�r� �t�o�u�s� �l�e�s� �c�a�l�q�u�e�s�������&Show All Layers��� MainWindow���8�&�A�f�f�i�c�h�e�r� �l�a� �p�l�a�t�i�n�e� �d�'�e�s�s�a�i�������&Show Breadboard��� MainWindow���8�&�A�f�f�i�c�h�e�r� �l�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m�������� &Show PCB��� MainWindow���8�&�A�f�f�i�c�h�e�r� �l�a� �v�u�e� �s�c�h��m�a�t�i�q�u�e�������&Show Schematic��� MainWindow���6�&�A�f�f�i�c�h�e�r� �l�a� �p�a�g�e� �d�'�a�c�c�u�e�i�l������� &Show Welcome��� MainWindow���D�&�A�f�f�i�c�h�e�r� �l�'��t�i�q�u�e�t�t�e� �d�u� �c�o�m�p�o�s�a�n�t�������&Show part label��� MainWindow����&�V�u�e�������&View��� MainWindow����&�F�e�n��t�r�e�������&Window��� MainWindow���"�&�C�o�u�l�e�u�r� �d�u� �c�a�b�l�e������� &Wire Color��� MainWindow����&�Z�o�o�m� �a�v�a�n�t�������&Zoom In��� MainWindow����&�Z�o�o�m� �a�r�r�i��r�e������� &Zoom Out��� MainWindow���.�T�a�i�l�l�e� �1�0�0�%� �(�e�n� �p�i�x�e�l�s�)�������100% (pixel) size��� MainWindow����T�a�i�l�l�e� �1�0�0�%������� 100% Size��� MainWindow���F�T�a�i�l�l�e� �r��e�l�l�e� �(�m�o�n�d�e� �p�h�y�s�i�q�u�e� �r��e�l�)�������!Actual (real world physical) size��� MainWindow����T�a�i�l�l�e� �r��e�l�l�e������� Actual Size��� MainWindow���T�A�j�o�u�t�e�r� �u�n� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n������� Add Bendpoint��� MainWindow���.�A�j�o�u�t�e�r� �u�n� �a�i�d�e�-�m��m�o�i�r�e�������Add Note��� MainWindow���~�A�j�o�u�t�e�r� �u�n� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n� �a�u� �c��b�l�e� �s��l�e�c�t�i�o�n�n��������$Add a bendpoint to the selected wire��� MainWindow����A�i�d�e�-�m��m�o�i�r�e������� Add a note��� MainWindow���j�A�j�o�u�t�e�r� �l�e� �c�o�m�p�o�s�a�n�t� �s��l�e�c�t�i�o�n�n�� �a�u� �j�e�u� �d�e� �c�o�m�p�o�s�a�n�t�s�������Add selected part to bin��� MainWindow����A�l�i�g�n�e�r�������Align��� MainWindow���$�A�l�i�g�n�e�r� �p�a�r� �l�e� �b�a�s������� Align Bottom��� MainWindow���R�A�l�i�g�n�e�r� �s�u�r� �l�e� �c�e�n�t�r�e� �d�e� �l�'�a�x�e� �h�o�r�i�z�o�n�t�a�l�������Align Horizontal Center��� MainWindow��� �A�l�i�g�n�e�r� �� �g�a�u�c�h�e������� Align Left��� MainWindow��� �A�l�i�g�n�e�r� �� �d�r�o�i�t�e������� Align Right��� MainWindow����A�l�i�g�n�e�r� �l�e� �h�a�u�t������� Align Top��� MainWindow���N�A�l�i�g�n�e�r� �s�u�r� �l�e� �c�e�n�t�r�e� �d�e� �l�'�a�x�e� �v�e�r�t�i�c�a�l�������Align Vertical Center��� MainWindow���t�A�l�i�g�n�e�r� �l�e�s� �o�b�j�e�t�s� �s�u�r� �l�a� �g�r�i�l�l�e� �l�o�r�s�q�u�e� �l�'�o�n� �f�a�i�t� �g�l�i�s�s�e�r�������!Align items to grid when dragging��� MainWindow���X�A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �p�a�r� �l�e� �b�a�s�������"Align selected items at the bottom��� MainWindow����A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �s�u�r� �l�e� �c�e�n�t�r�e� �d�e� �l�'�a�x�e� �h�o�r�i�z�o�n�t�a�l�������-Align selected items at the horizontal center��� MainWindow���T�A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �� �g�a�u�c�h�e������� Align selected items at the left��� MainWindow���T�A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �� �d�r�o�i�t�e�������!Align selected items at the right��� MainWindow���Z�A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �s�u�r� �l�e� �h�a�u�t�������Align selected items at the top��� MainWindow����A�l�i�g�n�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �s�u�r� �l�e� �c�e�n�t�r�e� �d�e� �l�'�a�x�e� �v�e�r�t�i�c�a�l�������+Align selected items at the vertical center��� MainWindow���*�A�l�i�g�n�e�r� �s�u�r� �l�a� �g�r�i�l�l�e������� Align to Grid��� MainWindow����T�o�u�s�������All��� MainWindow���^�T�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s� �n�'�o�n�t� �p�a�s� �e�n�c�o�r�e� ��t�� �r�o�u�t��e�s�.�������$All traces have not yet been routed.��� MainWindow���T�F�a�i�r�e� �t�o�u�r�n�e�r� �d�a�n�s� �l�e� �s�e�n�s� �a�n�t�i�-�h�o�r�l�o�g�i�q�u�e�������Alt+Shift+Ctrl+R��� MainWindow����A�u�t�o�r�o�u�t�a�g�e������� Autoroute��� MainWindow���T�C�o�n�n�e�x�i�o�n�s� �a�u�t�o�m�a�t�i�q�u�e�s� �p�a�r� �a�u�t�o�r�o�u�t�a�g�e�.�.�.�������Autoroute connections...��� MainWindow���j�P�a�r�a�m��t�r�e�s� �d�e� �l�'�A�u�t�o�r�o�u�t�a�g�e� �e�t� �d�e� �v��r�i�f�i�c�a�t�i�o�n� �R�D�C�.�.�.�������Autorouter/DRC settings...��� MainWindow���.�A�u�t�o�r�o�u�t�a�g�e� �e�n� �c�o�u�r�s�.�.�.�������Autorouting Progress...��� MainWindow����A�u�t�o�r�o�u�t�a�g�e�.�.�.�������Autorouting...��� MainWindow���$�S�a�u�v�e�g�a�r�d�e� �d�e� �'�%�1�'�������Backing up '%1'��� MainWindow���4�F�i�c�h�i�e�r� �t�e�x�t�e� �B�o�M� �(�*�.�h�t�m�l�)�������BoM Text File (*.html)��� MainWindow����D�o�u�b�l�e� �c�o�u�c�h�e������� Both Layers��� MainWindow���"�C�o�u�c�h�e� �i�n�f��r�i�e�u�r�e������� Bottom Layer��� MainWindow����P�l�a�t�i�n�e� �d�'�e�s�s�a�i������� Breadboard��� MainWindow����A�v�a�n�c�e�r������� Bring Forward��� MainWindow����M�e�t�t�r�e� �t�o�u�t� �l�e�s� ��l��m�e�n�t� �s��l�e�c�t�i�o�n�n�e�z� �e�n� �s�u�r�b�r�i�l�l�a�n�c�e� �d�a�n�s� �l�e� �c�a�l�q�u�e�������/Bring selected object(s) forward in their layer��� MainWindow����A�v�a�n�c�e�r� �a�u� �p�r�e�m�i�e�r� �p�l�a�n� �l�e�(�s�)� �o�b�j�e�t�(�s�)� �s��l�e�c�t�i�o�n�n��(�s�)� �� �l�'�i�n�t��r�i�e�u�r� �d�e� �l�e�u�r� �c�a�l�q�u�e�������0Bring selected object(s) to front of their layer��� MainWindow���.�A�v�a�n�c�e�r� �a�u� �p�r�e�m�i�e�r� �p�l�a�n�������Bring to Front��� MainWindow����A�n�n�u�l�e�r�������Cancel��� MainWindow���H�I�m�p�o�s�s�i�b�l�e� �d�e� �t�r�o�u�v�e�r� �l�e� �f�i�c�h�i�e�r� �%�1�.�������Cannot find file %1.��� MainWindow���>�I�m�p�o�s�s�i�b�l�e� �d�'�i�m�p�r�i�m�e�r� �l�e� �P�D�F� �%�1�������Cannot print to %1��� MainWindow���P�I�m�p�o�s�s�i�b�l�e� �d�e� �l�i�r�e� �l�e� �f�i�c�h�i�e�r� � �1� �%�1�:� �%�2�.�������Cannot read file 1 %1: %2.��� MainWindow���N�I�m�p�o�s�s�i�b�l�e� �d�'��c�r�i�r�e� �l�e� �f�i�c�h�i�e�r� �%�1� �:� �%�2�.�������Cannot write file %1: %2.��� MainWindow���,�M�o�d�i�f�i�e�r� �l�'�i�m�a�g�e� �e�n� �%�2�������Change image to %2��� MainWindow���N�M�o�d�i�f�i�e�r� �e�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �s�i�m�p�l�e� �f�a�c�e�������Change to single layer pcb��� MainWindow���N�M�o�d�i�f�i�e�r� �e�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �d�o�u�b�l�e� �f�a�c�e�������Change to two layer pcb��� MainWindow���6�V��r�i�f�i�e�r� �l�e�s� �p�i�s�t�e� �c�h�a�r�g��e�s�������Check Loaded Traces��� MainWindow���\�V��r�i�f�i�e�r� �l�a� �d�i�s�p�o�n�i�b�i�l�i�t�� �d�'�u�n�e� �m�i�s�e� �� �j�o�u�r�.�.�.�������Check for updates...��� MainWindow����V��r�i�f�i�e�r� �s�i� �u�n�e� �v�e�r�s�i�o�n� �p�l�u�s� �r��c�e�n�t�e� �d�e� �F�r�i�t�z�i�n�g� �e�s�t� �d�i�s�p�o�n�i�b�l�e� �e�n� �t��l��c�h�a�r�g�e�m�e�n�t�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���h�S��l�e�c�t�i�o�n� �d�e� �l�a� �m��t�h�o�d�e� �d�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�.�.�.�������Choose Ground Fill Seed(s)...��� MainWindow���T�S��l�e�c�t�i�o�n�n�e�r� �u�n� �d�o�s�s�i�e�r� �p�o�u�r� �l�'�e�x�p�o�r�t�a�t�i�o�n�������Choose a folder for exporting��� MainWindow���N�R��i�n�i�t�i�a�l�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�������Clear Ground Fill Seeds��� MainWindow����R��i�n�i�t�i�a�l�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�-�-�a�u�t�o�r�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �e�n� �c�u�i�v�r�e� �u�n�i�q�u�e�m�e�n�t�.�������1Clear ground fill seeds--enable copper fill only.��� MainWindow���x�C�l�i�q�u�e�r� �p�o�u�r� �m�e�t�t�r�e� �e�n� ��v�i�d�e�n�c�e� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �n�o�n� �c�o�n�n�e�c�t��s�������$Click to highlight unconnected parts��� MainWindow����C�o�n�v�e�r�t�i�r�������Convert��� MainWindow����C�o�n�v�e�r�t�i�r� �l�e� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n� �e�n� �c�o�n�n�e�x�i�o�n� �t�r�a�v�e�r�s�a�n�t�e�������Convert Bendpoint to Via��� MainWindow����C�o�n�v�e�r�t�i�r� �l�a� �c�o�n�n�e�x�i�o�n� �t�r�a�v�e�r�s�a�n�t�e� �e�n� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n�������Convert Via to Bendpoint��� MainWindow����C�o�n�v�e�r�t�i�r� �l�e� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n� �e�n� �c�o�n�n�e�x�i�o�n� �t�r�a�v�e�r�s�a�n�t�e�������Convert the bendpoint to a via��� MainWindow����C�o�n�v�e�r�t�i�r� �l�a� �c�o�n�n�e�x�i�o�n� �t�r�a�v�e�r�s�a�n�t�e� �e�n� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n�������Convert the via to a bendpoint��� MainWindow���R�L�a� �c�o�u�c�h�e� �d�e� �c�u�i�v�r�e� �i�n�f��r�i�e�u�r�e� �e�s�t� �a�c�t�i�v�e�������Copper Bottom layer is active��� MainWindow���*�R�e�m�p�l�i�s�s�a�g�e� �e�n� �c�u�i�v�r�e������� Copper Fill��� MainWindow���B�C�r��a�t�i�o�n� �d�'�u�n� �p�l�a�n� �e�n� �c�u�i�v�r�e� �(�%�1�)�������Copper Fill (%1)��� MainWindow���J�L�e�s� �d�e�u�x� �f�a�c�e�s� �e�n� �c�u�i�v�r�e� �s�o�n�t� �a�c�t�i�v�e�s�������3Copper Top and Copper Bottom layers are both active��� MainWindow���L�L�a� �c�o�u�c�h�e� �c�u�i�v�r�e� �s�u�p��r�i�e�u�r�e� �e�s�t� �a�c�t�i�v�e�������Copper Top layer is active��� MainWindow���&�C�o�p�i�e�r� �l�a� �s��l�e�c�t�i�o�n�������Copy selection��� MainWindow���X�I�m�p�o�s�s�i�b�l�e� �d�'�o�b�t�e�n�i�r� �l�e� �s�t�o�c�k�a�g�e� �d�e�s� �w�i�d�g�e�t�s�������Couldn't get the dock widget��� MainWindow���6�C�r��e�r� �u�n�e� �n�o�u�v�e�l�l�e� �e�s�q�u�i�s�s�e�������Create a new sketch��� MainWindow���L�C�r��e�r� �u�n�e� �p�i�s�t�e� �� �p�a�r�t�i�r� �d�u� �f�i�l� �v�o�l�a�n�t�������%Create a trace from the ratsnest line��� MainWindow���N�R�e�m�p�l�a�c�e�r� �l�e� �c��b�l�e� �p�a�r� �u�n�e� �p�i�s�t�e� �c�u�i�v�r��������$Create a wire from the ratsnest line��� MainWindow�������Ctrl+N��� MainWindow���&�C�o�u�p�e�r� �l�a� �s��l�e�c�t�i�o�n������� Cut selection��� MainWindow���x�A�v�a�n�c��e� �d�e� �l�a� �v��r�i�f�i�c�a�t�i�o�n� �d�e�s� �r��g�l�e�s� �d�e� �c�o�n�c�e�p�t�i�o�n� �(�R�D�C�)�.�.�.�������DRC Progress...��� MainWindow���n�D��b�o�g�u�e�r� �"�S�u�p�p�r�i�m�e�r� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s�"� �d�a�n�s� �c�e�t�t�e� �v�u�e�������!Debug dump all parts in this view��� MainWindow���&�S�o�r�t�i�e� �d�u� �d��b�o�g�u�e�u�r�������Debugger Output��� MainWindow����E�f�f�a�c�e�r�������Delete��� MainWindow���^�S�u�p�p�r�i�m�e�r� �l�'��l��m�e�n�t� �e�t� �c�o�n�s�e�r�v�e�r� �l�e�s� �c�o�n�n�e�x�i�o�n�s������� Delete Minus��� MainWindow���.�S�u�p�p�r�i�m�e�r� �l�e� �f�i�l� �v�o�l�a�n�t�������Delete Ratsnest Line��� MainWindow���$�S�u�p�p�r�i�m�e�r� �l�e� �c��b�l�e������� Delete Wire��� MainWindow���j�S�u�p�p�r�i�m�e�r� �l�e� �c��b�l�e� �j�u�s�q�u�'�� �l�'�a�n�g�l�e�/�p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�������Delete Wire up to bendpoints��� MainWindow���,�S�u�p�p�r�i�m�e�r� �l�a� �s��l�e�c�t�i�o�n�������Delete selection��� MainWindow���\�S�u�p�p�r�i�m�e�r� �l�a� �s��l�e�c�t�i�o�n� �s�a�n�s� �l�e�s� �f�i�l�s� �c�o�n�n�e�c�t��s�������'Delete selection without attached wires��� MainWindow����D��s��l�e�c�t�i�o�n�n�e�r�������Deselect��� MainWindow���V�V��r�i�f�i�c�a�t�i�o�n� �d�e�s� �r��g�l�e�s� �d�e� �c�o�n�c�e�p�t�i�o�n� �(�R�D�C�)�������Design Rules Check (DRC)��� MainWindow���6�D��c�o�n�n�e�c�t�e�r� �t�o�u�s� �l�e�s� �c��b�l�e�s�������Disconnect All Wires��� MainWindow���d�D��c�o�n�n�e�c�t�e�r� �t�o�u�s� �l�e�s� �c��b�l�e�s� �r�e�l�i��s� �� �c�e� �c�o�n�n�e�c�t�e�u�r�������0Disconnect all wires connected to this connector��� MainWindow���:�A�f�f�i�c�h�e�r� �l�'�a�i�d�e� �d�e�s� �d��b�u�t�a�n�t�s�������Display First Time Help��� MainWindow���~�A�f�f�i�c�h�e�r� �l�'�a�i�d�e� �p�o�u�r� �l�'��d�i�t�e�u�r� �d�e� �c�o�m�p�o�s�a�n�t�s� �d�a�n�s� �l�e� �n�a�v�i�g�a�t�e�u�r�������&Display Parts Editor help in a browser��� MainWindow���p�A�f�f�i�c�h�e�r� �q�u�e�l�q�u�e�s� �a�s�t�u�c�e�s� �e�t� �c�o�n�s�e�i�l�s� �p�r�a�t�i�q�u�e�s� �F�r�i�t�z�i�n�g�������+Display some handy Fritzing tips and tricks��� MainWindow���j�A�f�f�i�c�h�e�r� �l�e� �m�a�g�a�s�i�n� �d�e� �c�o�m�p�o�s�a�n�t�s� �s�o�u�s� �f�o�r�m�e� �d�e� �l�i�s�t�e�������$Display the parts bin in a list view��� MainWindow���j�A�f�f�i�c�h�e�r� �l�e� �m�a�g�a�s�i�n� �d�e� �c�o�m�p�o�s�a�n�t�s� �s�o�u�s� �f�o�r�m�e� �d�'�i�c��n�e�s�������%Display the parts bin in an icon view��� MainWindow���"�N�e� �p�a�s� �a�u�t�o�r�o�u�t�e�r�������Do not autoroute��� MainWindow���V�V�o�u�l�e�z�-�v�o�u�s� �g�a�r�d�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �i�m�p�o�r�t��s�?�������'Do you want to keep the imported parts?��� MainWindow���D�V�o�u�l�e�z�-�v�o�u�s� �q�u�a�n�d� �m��m�e� �c�o�n�t�i�n�u�e�r� �?�������Do you want to proceed anyway?��� MainWindow���.�F�a�i�r�e� �u�n� �d�o�n� �� �F�r�i�t�z�i�n�g�������Donate to Fritzing��� MainWindow���:�S�u�p�p�r�i�m�e�r� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s�������Dump all parts��� MainWindow���,�D�u�p�l�i�q�u�e�r� �l�a� �s��l�e�c�t�i�o�n�������Duplicate selection��� MainWindow���:�E�d�i�t�e�r� �(�u�n� �n�o�u�v�e�a�u� �c�o�m�p�o�s�a�n�t�)�������Edit (new parts editor)��� MainWindow���<�A�c�t�i�v�e�r� �l�e� �j�o�u�r�n�a�l� �d�e� �d��b�o�g�a�g�e�������Enable debugging log��� MainWindow����E�n�t�r�e�z� �l�e� �t�e�x�t�e������� Enter Text��� MainWindow���"�C�r��e�r� �e�n� �(�P�D�F�)�.�.�.�������Etchable (PDF)...��� MainWindow���"�C�r��e�r� �e�n� �(�S�V�G�)�.�.�.�������Etchable (SVG)...��� MainWindow�� �L�'�e�x�p�o�r�t�a�t�i�o�n� �p�o�u�r� �l�a� �g�r�a�v�u�r�e� �n�e� �p�e�u�t� �g��r�e�r� �q�u�'�u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s� �-� �v�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �l�a� �c�a�r�t�e� �q�u�e� �v�o�u�s� �s�o�u�h�a�i�t�e�z� �e�x�p�o�r�t�e�r�.�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow����E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�V�G� �1�0�0�0� �d�p�i� �a�p�l�a�t�i� �d�e� �c�e� �c�o�m�p�o�s�a�n�t� �d�a�n�s� �c�e�t�t�e� �v�u�e�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���t�E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�V�G� �1�0�0�0� �d�p�i� �d�e� �c�e� �c�o�m�p�o�s�a�n�t� �d�a�n�s� �c�e�t�t�e� �v�u�e�������-Export 1000 dpi SVG of this part in this view��� MainWindow���6�E�x�p�o�r�t�e�r� �l�a� �n�o�m�e�n�c�l�a�t�u�r�e�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���,�E�x�p�o�r�t�e�r� �l�a� �N�e�t�l�i�s�t�.�.�.�������Export Netlist...��� MainWindow���F�E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�V�G� �a�p�l�a�t�i� �n�o�r�m�a�l�i�s��������Export Normalized Flattened SVG��� MainWindow���8�E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�V�G� �n�o�r�m�a�l�i�s��������Export Normalized SVG��� MainWindow���J�E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�P�I�C�E� �d�e� �l�a� �N�e�t�L�i�s�t�.�.�.�������Export SPICE Netlist...��� MainWindow���*�E�x�p�o�r�t�a�t�i�o�n� �e�n� �S�V�G�.�.�.������� Export SVG...��� MainWindow���"�E�x�p�o�r�t� �c�i�r�c�.�i�m�p�r�.�������Export for PCB��� MainWindow���B�E�x�p�o�r�t�e�r� �l�e� �c�o�m�p�o�s�a�n�t� �s��l�e�c�t�i�o�n�n��������Export selected part��� MainWindow���X�E�x�p�o�r�t�e�r� �l�'�e�s�q�u�i�s�s�e� �a�c�t�u�e�l�l�e� �c�o�m�m�e� �i�m�a�g�e� �S�V�G�������)Export the current sketch as an SVG image��� MainWindow���P�E�x�p�o�r�t�e�r� �l�e� �s�c�h��m�a� �a�c�t�u�e�l� �v�e�r�s� �E�a�g�l�e� �C�A�D�������&Export the current sketch to Eagle CAD��� MainWindow����E�x�p�o�r�t�e�r� �l�'�e�s�q�u�i�s�s�e� �a�c�t�u�e�l�l�e� �a�u� �f�o�r�m�a�t� �G�e�r�b�e�r� ��t�e�n�d�u� �(�R�S�-�2�7�4�X�)� �p�o�u�r� �l�a� �p�r�o�d�u�c�t�i�o�n� �p�r�o�f�e�s�s�i�o�n�n�e�l�l�e� �d�e� �c�i�r�c�u�i�t�s� �i�m�p�r�i�m��s�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow����E�x�p�o�r�t�e�r� �l�'�e�s�q�u�i�s�s�e� �c�o�u�r�a�n�t�e� �a�u� �f�o�r�m�a�t� �P�D�F� �p�o�u�r� �l�a� �r��a�l�i�s�a�t�i�o�n� �d�'�u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �e�n� �a�m�a�t�e�u�r� �(�r��s�i�n�e� �p�h�o�t�o�s�e�n�s�i�b�l�e�)�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow����E�x�p�o�r�t�e�r� �l�'�e�s�q�u�i�s�s�e� �c�o�u�r�a�n�t�e� �a�u� �f�o�r�m�a�t� �S�V�G� �p�o�u�r� �l�a� �p�r�o�d�u�c�t�i�o�n� �d�'�u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �e�n� �a�m�a�t�e�u�r� �(�r��s�i�n�e� �p�h�o�t�o�s�e�n�s�i�b�l�e�)�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���~�E�x�p�o�r�t�e�r� �l�a� �z�o�n�e� �v�i�s�i�b�l�e� �d�e� �l�'�e�s�q�u�i�s�s�e� �a�c�t�u�e�l�l�e� �c�o�m�m�e� �i�m�a�g�e� �J�P�G��������G��n��r�a�t�i�o�n� �d�e� �%�1� �r�e�m�p�l�i�s�s�a�g�e�.�.�.�������Generating %1 fill...��� MainWindow����L�'�e�x�p�o�r�t�a�t�i�o�n� �G�e�r�b�e�r� �n�e� �p�e�u�t� �g��r�e�r� �q�u�'�u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s� �-� �v�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �l�a� �c�a�r�t�e� �q�u�e� �v�o�u�s� �s�o�u�h�a�i�t�e�z� �e�x�p�o�r�t�e�r�.�������^Gerber export can only handle one board at a time--please select the board you want to export.��� MainWindow���*�T�a�i�l�l�e� �d�e� �l�a� �g�r�i�l�l�e� �:������� Grid Size:��� MainWindow���8�R�e�m�p�l�i�s�s�a�g�e� �d�u� �p�l�a�n� �d�e� �m�a�s�s�e������� Ground Fill��� MainWindow���@�C�r��a�t�i�o�n� �d�'�u�n� �p�l�a�n� �d�e� �m�a�s�s�e� �(�%�1�)�������Ground Fill (%1)��� MainWindow���V�M�a�s�q�u�e�r� �t�o�u�s� �l�e�s� �c�a�l�q�u�e�s� �d�e� �l�a� �v�u�e� �a�c�t�u�e�l�l�e�������'Hide all the layers of the current view��� MainWindow���@�M�a�s�q�u�e�r� �l�'��t�i�q�u�e�t�t�e� �d�u� �c�o�m�p�o�s�a�n�t�������Hide part label��� MainWindow���F�M�a�s�q�u�e�r� �l�a� �s��r�i�g�r�a�p�h�i�e� �d�u� �c�o�m�p�o�s�a�n�t�������Hide part silkscreen��� MainWindow���x�M�a�s�q�u�e�r�/�a�f�f�i�c�h�e�r� �l�a� �s��r�i�g�r�a�p�h�i�e� �p�o�u�r� �c�e� �c�o�m�p�o�s�a�n�t� �u�n�i�q�u�e�m�e�n�t�������1Hide/show the silkscreen layer for only this part��� MainWindow���l�M�e�t�t�r�e� �e�n� �s�u�r�b�r�i�l�l�a�n�c�e� �t�o�u�s� �l�e�s� �c�o�n�n�e�c�t�e�u�r�s� �n�o�n� �r�o�u�t��s�������!Highlight all unrouted connectors��� MainWindow����M�e�t� �e�n� ��v�i�d�e�n�c�e� �l�e�s� �p�a�r�t�i�e�s� �q�u�i� �s�o�n�t� �t�r�o�p� �r�a�p�p�r�o�c�h��e�s� �p�o�u�r� �c�r��e�r� �u�n� �C�I� �s��r�������JHighlights any parts that are too close together for safe board production��� MainWindow����C�o�m�b�i�e�n� �c�e�l�a� �p�o�u�r�r�a�i�t� �c�o��t�e�r� �d�e� �p�r�o�d�u�i�r�e� �u�n� �C�I� �� �p�a�r�t�i�r� �d�e� �c�e�t�t�e� �e�s�q�u�i�s�s�e� �a�v�e�c� �F�r�i�t�z�i�n�g� �F�a�b�������KHow much would it could to produce a PCB from this sketch with Fritzing Fab��� MainWindow����S�i� �u�n� �c�o�m�p�o�s�a�n�t� �"�c�o�l�l�a�n�t�"� �e�s�t� �d��p�l�a�c��,� �l�e�s� �p�i��c�e�s� �a�u� �d�e�s�s�u�s� �d�e� �c�e�l�u�i�-�c�i� �s�e�r�o�n�t� ��g�a�l�e�m�e�n�t� �d��p�l�a�c��e�s�������>If a "sticky" part is moved, parts on top of it are also moved��� MainWindow���r�I�m�p�o�r�t�e�r� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �e�t� �j�e�u�x� �d�'�u�n�e� �p�r��c��d�e�n�t�e� �v�e�r�s�i�o�n� �������0Import parts and bins from previous installation��� MainWindow����I�n�s�p�e�c�t�e�u�r������� Inspector��� MainWindow���I�l� �n�e� �s�e�m�b�l�e� �p�a�s� �p�o�s�s�i�b�l�e� �d�e� �d��t�e�r�m�i�n�e�r� �a�u�t�o�m�a�t�i�q�u�e�m�e�n�t� �l�a� �t�a�i�l�l�e� �p�h�y�s�i�q�u�e� �d�e� �l�'��c�r�a�n�,� �d�o�n�c� �l�a� �"�t�a�i�l�l�e� �r��e�l�l�e�"� �t�e�l�l�e� �q�u�'�a�f�f�i�c�h��e� �a�c�t�u�e�l�l�e�m�e�n�t� �n�'�e�s�t� �q�u�'�u�n�e� �s�u�p�p�o�s�i�t�i�o�n�.� �C�e� �q�u�'�i�l� �y� �a�u�r�a�i�t� �d�e� �m�i�e�u�x� �� �f�a�i�r�e� �s�e�r�a�i�t� �d�'�i�n�s��r�e�r� �u�n� �c�o�m�p�o�s�a�n�t� �d�e� �t�y�p�e� �r��g�l�e�,� �p�u�i�s� �d�e� �p�l�a�c�e�r� �u�n�e� �r��g�l�e� �r��e�l�l�e� �(�p�h�y�s�i�q�u�e�)� �s�u�r� �l�'��c�r�a�n� �e�t� �d�e� �z�o�o�m�e�r� �j�u�s�q�u�'�� �c�e� �q�u�e� �l�a� �r��g�l�e� �d�e� �F�r�i�t�z�i�n�g� �e�t� �l�a� �r��g�l�e� �r��e�l�l�e� �c�o�r�r�e�s�p�o�n�d�e�n�t�.������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow���$�i�m�a�g�e� �J�P�E�G� �(�*�.�j�p�g�)�������JPEG Image (*.jpg)��� MainWindow����L�a�n�c�e�r� �%�1�.�.�.������� Launch %1...��� MainWindow����C�a�l�q�u�e�s�������Layers��� MainWindow���f�L�i�s�t�e� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �(�&�N�o�m�e�n�c�l�a�t�u�r�e� �e�t� �m�a�t��r�i�e�l�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow����C�h�a�r�g�e�m�e�n�t�.�.�.������� Loading...��� MainWindow���0�V�e�r�r�o�u�i�l�l�e�r� �l�e� �c�o�m�p�o�s�a�n�t������� Lock Part��� MainWindow����M�a�i�n�W�i�n�d�o�w� �:�:� �L�e� �d�o�s�s�i�e�r� �p�r�i�n�c�i�p�a�l� �d�e� �l�a� �f�e�n��t�r�e� �p�o�u�r� �l�e� �d��p�l�a�c�e�m�e�n�t� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �e�s�t� �m�a�n�q�u�a�n�t�������0MainWindow::moveToPartsFolder mainwindow missing��� MainWindow����M�a�i�n�W�i�n�d�o�w� �:�:� �L�e� �r�e�m�p�l�i�s�s�a�g�e� �d�u� �m�e�n�u� �g�r��c�e� �� �l�'�i�n�d�e�x�:� �n�'�a� �p�a�s� �p�u� �c�h�a�r�g�e�r� �l�'�e�x�e�m�p�l�e� �a�v�e�c� �l�'�i�d� �=� �'�%�1�'�������EMainWindow::populateMenuWithIndex: couldn't load example with id='%1'��� MainWindow���:�M�i�n�i�m�i�z�e�r� �l�a� �f�e�n��t�r�e� �a�c�t�u�e�l�l�e�������Minimize current window��� MainWindow���D��p�l�a�c�e�r� �l�e�s� �p�i�s�t�e�s� �s��l�e�c�t�i�o�n�n��e�s� �d�e� �l�'�a�u�t�r�e� �c��t�� �d�e� �l�a� �c�a�r�t�e� �(�n�o�t�e� �:� �l�a� �"�p�r�e�m�i��r�e�"� �p�i�s�t�e� �s�e�r�a� �d��p�l�a�c��e� �e�t� �l�e� �r�e�s�t�e� �s�u�i�v�r�a� �d�u� �m��m�e� �c��t��)�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���@�D��p�l�a�c�e�r� �v�e�r�s� �l�a� �f�a�c�e� �i�n�f��r�i�e�u�r�e�������Move to bottom layer��� MainWindow���L�D��p�l�a�c�e�r� �v�e�r�s� �l�'�a�u�t�r�e� �c��t�� �d�e� �l�a� �c�a�r�t�e�������Move to other side of the board��� MainWindow���@�D��p�l�a�c�e�r� �v�e�r�s� �l�a� �f�a�c�e� �s�u�p��r�i�e�u�r�e�������Move to top layer��� MainWindow����N�o�u�v�e�a�u�������New��� MainWindow���R�A�u�c�u�n�e� �e�s�q�u�i�s�s�e� �n�'�a� ��t�� �t�r�o�u�v��e� �d�a�n�s� �'�%�1�'�������No Sketch found in '%1'��� MainWindow���2�P�a�s� �d�e� �c�o�n�n�e�x�i�o�n� �� �r�e�l�i�e�r�������No connections to route��� MainWindow���H�P�a�s� �d�e� �c�u�i�v�r�e� �s�u�r� �l�a� �f�a�c�e� �s�u�p��r�i�e�u�r�e�������No copper top layer��� MainWindow����A�u�c�u�n� �c�o�m�p�o�s�a�n�t� �c�o�r�r�e�s�p�o�n�d�a�n�t� �e�x�a�c�t�e�m�e�n�t� �n�'�a� ��t�� �t�r�o�u�v��;� �F�r�i�t�z�i�n�g� �v�a� �c�h�o�i�s�i�r� �l�e� �p�l�u�s� �p�r�o�c�h�e�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow����A�u�c�u�n� �c�o�m�p�o�s�a�n�t� �o�b�s�o�l��t�e�s� �n�'�a� ��t�� �t�r�o�u�v��.� �T�o�u�t�e�s� �v�o�s� �c�o�m�p�o�s�a�n�t�s� �s�o�n�t� �� �j�o�u�r�.�������7No outdated parts found. All your parts are up-to-date.��� MainWindow��6�A�u�c�u�n� �c�o�m�p�o�s�a�n�t� �a�y�a�n�t� �c�e�s� �c�a�r�a�c�t��r�i�s�t�i�q�u�e�s� �n�'�e�x�i�s�t�e�.� �N�o�u�s� �t�r�a�v�a�i�l�l�o�n�s� �� ��l�i�m�i�n�e�r� �c�e� �m�e�s�s�a�g�e� �a�f�i�n� �d�e� �n�e� �v�o�u�s� �l�a�i�s�s�e�r� �c�h�o�i�s�i�r� �q�u�e� �d�e�s� �p�r�o�p�r�i��t��s� �q�u�i� �e�x�i�s�t�e�n�t�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���J�A�u�c�u�n� �c�o�m�p�o�s�a�n�t� �c�o�r�r�e�s�p�o�n�d�a�n�t� �� �'�%�1�'�.�������"No parts matched search term '%1'.��� MainWindow���B�C�a�t�a�l�o�g�u�e� �e�n� �l�i�g�n�e� �d�e�s� �c�o�m�p�o�s�a�n�t�s�������Online Parts Reference��� MainWindow���8�G�a�l�e�r�i�e� �d�e�s� �p�r�o�j�e�t�s� �e�n� �l�i�g�n�e�������Online Projects Gallery��� MainWindow���$�T�u�t�o�r�i�e�l�s� �e�n� �l�i�g�n�e�������Online Tutorials��� MainWindow���N�O�u�v�r�i�r� �l�a� �p�a�g�e� �W�e�b� �d�e� �d�o�n�a�t�i�o�n� �F�r�i�t�z�i�n�g�������Open Fritzing donation web page��� MainWindow���8�O�u�v�r�i�r� �l�e�s� �e�x�e�m�p�l�e�s� �F�r�i�t�z�i�n�g�������Open Fritzing examples��� MainWindow���2�O�u�v�r�i�r� �l�'�a�i�d�e� �d�e� �F�r�i�t�z�i�n�g�������Open Fritzing help��� MainWindow���L�O�u�v�r�i�r� �l�a� �d�o�c�u�m�e�n�t�a�t�i�o�n� �d�e�s� �c�o�m�p�o�s�a�n�t�s�������Open Parts Reference��� MainWindow����O�u�v�r�i�r� �u�n�e� �e�s�q�u�i�s�s�e� �F�r�i�t�z�i�n�g� �(�.�f�z�z� �.�f�z�)�,� �c�h�a�r�g�e�r� �u�n� �c�o�m�p�o�s�a�n�t� �F�r�i�t�z�i�n�g� �(�.�f�z�p�z�)�,� �o�u� �u�n� �m�a�g�a�s�i�n� �d�e� �c�o�m�p�o�s�a�n�t�s� �(�.�f�z�b�,� �.�f�z�b�z�)�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���j�O�u�v�r�i�r� �l�a� �f�e�n��t�r�e� �d�e� �p�r�o�g�r�a�m�m�a�t�i�o�n� �d�e� �m�i�c�r�o�c�o�n�t�r��l�e�u�r�������'Open microcontroller programming window��� MainWindow���D�O�u�v�r�i�r� �l�a� �f�e�n��t�r�e� �d�e� �p�r�o�g�r�a�m�m�a�t�i�o�n�������Open programming window��� MainWindow���~�O�u�v�r�i�r� �l�'��d�i�t�e�u�r� �d�e� �n�o�u�v�e�a�u� �c�o�m�p�o�s�a�n�t� �s�u�r� �u�n� �c�o�m�p�o�s�a�n�t� �e�x�i�s�t�a�n�t�������-Open the new parts editor on an existing part��� MainWindow����C�o�m�m�a�n�d�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �c�r��� �� �p�a�r�t�i�r� �d�e� �v�o�t�r�e� �e�s�q�u�i�s�s�e�-�-�a�u�p�r��s� �d�e� �l�a� �f�a�b�u�l�e�u�s�e� �F�r�i�t�z�i�n�g� �F�a�b�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow���>�C�o�m�m�a�n�d�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.�.�.�������Order a PCB...��� MainWindow���(�C�o�m�p�o�s�a�n�t�s� �o�b�s�o�l��t�e�s�������Outdated parts��� MainWindow����C�i�r�c�u�i�t� �i�m�p�r�i�m��������PCB��� MainWindow���"�I�m�a�g�e� �P�N�G� �(�*�.�p�n�g�)�������PNG Image (*.png)��� MainWindow���6�P�r��f��r�e�n�c�e�s� �d�e� �m�i�s�e� �e�n� �p�a�g�e������� Page Setup��� MainWindow���F�A�i�d�e� �p�o�u�r� �l�a� �c�r��a�t�i�o�n� �d�e� �c�o�m�p�o�s�a�n�t�s�������Parts Editor Help��� MainWindow���D�C�o�p�i�e�r� �l�e� �c�o�n�t�e�n�u� �d�u� �p�r�e�s�s�e�-�p�a�p�i�e�r�������Paste clipboard contents��� MainWindow���Z�C�o�l�l�e�r�-�r�e�m�p�l�a�c�e�r� �l�e� �c�o�n�t�e�n�u� �d�u� �p�r�e�s�s�e�-�p�a�p�i�e�r�s�������!Paste clipboard contents in place��� MainWindow��� �C�o�l�l�e�r�-�r�e�m�p�l�a�c�e�r�������Paste in Place��� MainWindow���d�V�e�u�i�l�l�e�z� �c�h�o�i�s�i�r� �l�e� �d�o�s�s�i�e�r� �F�r�i�t�z�i�n�g� �p�r��c��d�e�n�t� �.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow����V�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.� �L�e� �r�e�m�p�l�i�s�s�a�g�e� �e�n� �c�u�i�v�r�e� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �p�o�u�r� �u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow����V�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�n�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.� �L�e�s� �o�p��r�a�t�i�o�n�s� �d�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e� �m�a�s�s�e� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �s�u�r� �u�n�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow���V�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.� �L�e�s� �o�p��r�a�t�i�o�n�s� �d�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e� �c�u�i�v�r�e� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �s�u�r� �u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow����V�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �q�u�'�u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.� �L�a� �R�D�C� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �s�u�r� �u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow����V�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �l�a� �c�a�r�t�e� �q�u�e� �v�o�u�s� �s�o�u�h�a�i�t�e�z� �a�u�t�o�r�o�u�t�e�r�.� �L�e� �r�o�u�t�e�u�r� �n�e� �p�e�u�t� �g��r�e�r� �q�u�'�u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow����S�'�i�l� �v�o�u�s� �p�l�a��t� �s�p��c�i�f�i�e�r� �u�n� �n�o�m� �d�e� �f�i�c�h�i�e�r� �(�.�F�z�z�)� �p�o�u�r� �e�n�r�e�g�i�s�t�r�e�r� �'�%�1�'�������0Please specify an .fzz file name to save '%1' to��� MainWindow���R�P�o�s�t�e�r� �u�n� �p�r�o�j�e�t� �s�u�r� �l�e� �s�i�t�e� �W�e�b� �F�r�i�t�z�i�n�g�������&Post a project to the Fritzing website��� MainWindow���J�E�m�p��c�h�e� �l�e� �d��p�l�a�c�e�m�e�n�t� �d�'�u�n� �c�o�m�p�o�s�a�n�t�������Prevent a part from being moved��� MainWindow���0�I�m�p�r�i�m�e�r� �l�a� �v�u�e� �a�c�t�u�e�l�l�e�������Print the current view��� MainWindow���,�I�m�p�r�e�s�s�i�o�n� �e�n� �c�o�u�r�s�.�.�.������� Printing...��� MainWindow����C�o�n�t�i�n�u�e�r�������Proceed��� MainWindow���(�Q�u�i�t�t�e�r� �l�e� �p�r�o�g�r�a�m�m�e�������Quit the application��� MainWindow��� �M�o�d�i�f�i�e�r� �l�'�o�r�d�r�e�������Raise and Lower��� MainWindow��� �E�n� �l�e�c�t�u�r�e� �s�e�u�l�e������� Read-only��� MainWindow����T�e�r�m�i�n��������Ready��� MainWindow���R�e�c�a�l�c�u�l�e�r� �l�'��t�a�t� �d�u� �r�o�u�t�a�g�e� �d�e�s� �p�i�s�t�e�s� �e�t� �d�e�s� �f�i�l�s� �v�o�l�a�n�t�s� �(�a�u� �c�a�s� �o�� �l�a� �m�i�s�e� �� �j�o�u�r� �a�u�t�o�m�a�t�i�q�u�e� �n�e� �f�o�n�c�t�i�o�n�n�e� �p�a�s� �c�o�r�r�e�c�t�e�m�e�n�t�)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow����R��t�a�b�l�i�r�������Redo��� MainWindow���(�R�e�c�h�a�r�g�e�r� �l�'�e�s�q�u�i�s�s�e�������Reload the sketch��� MainWindow���X�S�u�p�p�r�i�m�e�r� �l�e� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n�������Remove Bendpoint��� MainWindow���>�S�u�p�p�r�i�m�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e�������Remove Copper Fill��� MainWindow���>�S�u�p�p�r�i�m�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e�������Remove copper fill��� MainWindow���>�S�u�p�p�r�i�m�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e�������Remove the copper fill��� MainWindow���(�S�i�g�n�a�l�e�r� �u�n� �b�o�g�u�e�.�.�.�������Report a bug...��� MainWindow���:�S�i�g�n�a�l�e�r� �u�n� �b�u�g� �d�a�n�s� �F�r�i�t�z�i�n�g�������%Report a but you've found in Fritzing��� MainWindow���J�R�e�s�t�a�u�r�e�r� �l�a� �c�o�n�f�i�g�u�r�a�t�i�o�n� �p�a�r� �d��f�a�u�t�������Restore Default��� MainWindow����R��t�a�b�l�i�r�������Revert��� MainWindow����R��t�a�b�l�i�r� �?�������Revert?��� MainWindow����R�o�t�a�t�i�o�n�������Rotate��� MainWindow���:�F�a�i�r�e� �p�i�v�o�t�e�r� �d�e� �1�8�0�� �{�1�8�0�?�}������� Rotate 180���� MainWindow���T�F�a�i�r�e� �p�i�v�o�t�e�r� �d�e� �9�0�� �v�e�r�s� �l�a� �d�r�o�i�t�e� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���V�F�a�i�r�e� �p�i�v�o�t�e�r� �d�e� �1�3�5�� �v�e�r�s� �l�a� �g�a�u�c�h�e� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow���T�F�a�i�r�e� �p�i�v�o�t�e�r� �d�e� �9�0�� �v�e�r�s� �l�a� �d�r�o�i�t�e� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���V�F�a�i�r�e� �p�i�v�o�t�e�r� �d�e� �1�3�5�� �v�e�r�s� �l�a� �g�a�u�c�h�e� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���r�T�o�u�r�n�e�r� �l�a� �s��l�e�c�t�i�o�n� �a�c�t�u�e�l�l�e� �d�e� �4�5� �d�e�g�r��s� �v�e�r�s� �l�a� �d�r�o�i�t�e�������-Rotate current selection 45 degrees clockwise��� MainWindow���r�T�o�u�r�n�e�r� �l�a� �s��l�e�c�t�i�o�n� �a�c�t�u�e�l�l�e� �d�e� �4�5� �d�e�g�r��s� �v�e�r�s� �l�a� �g�a�u�c�h�e�������5Rotate current selection 45 degrees counter clockwise��� MainWindow���r�T�o�u�r�n�e�r� �l�a� �s��l�e�c�t�i�o�n� �a�c�t�u�e�l�l�e� �d�e� �9�0� �d�e�g�r��s� �v�e�r�s� �l�a� �g�a�u�c�h�e�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���^�P�i�v�o�t�e�r� �d�e� �1�8�0� �d�e�g�r��s� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s�������(Rotate the selected parts by 180 degrees��� MainWindow���z�P�i�v�o�t�e�r� �l�e�s� ��l��m�e�n�t�s� �s��l�e�c�t�i�o�n�n��s� �d�e� �9�0� �d�e�g�r��s� �v�e�r�s� �l�a� �d�r�o�i�t�e�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow����R�o�u�t�a�g�e� �t�e�r�m�i�n��������Routing completed��� MainWindow���R�R�o�u�t�a�g�e� �c�o�m�p�l��t�� �e�n� �u�t�i�l�i�s�a�n�t� �%�n� �c�a�v�a�l�i�e�r���T�R�o�u�t�a�g�e� �c�o�m�p�l��t�� �e�n� �u�t�i�l�i�s�a�n�t� �%�n� �c�a�v�a�l�i�e�r�s�������)Routing completed using %n jumper part(s)��� MainWindow����E�n�r�e�g�i�s�t�r�e�r� �%�1�������Save %1��� MainWindow����E�n�r�e�g�i�s�t�r�e�r� �u�n�e� �n�o�m�e�n�c�l�a�t�u�r�e� �(�B�o�M�)�/�l�i�s�t�e� �d�'�a�c�h�a�t�s� �s�o�u�s� �f�o�r�m�e� �d�e� �t�e�x�t�e�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���N�E�n�r�e�g�i�s�t�r�e�r� �u�n�e� �n�e�t�l�i�s�t� �a�u� �f�o�r�m�a�t� �S�P�I�C�E�������Save a netlist in SPICE format��� MainWindow���J�E�n�r�e�g�i�s�t�r�e�r� �u�n�e� �n�e�t�l�i�s�t� �a�u� �f�o�r�m�a�t� �X�M�L�������Save a netlist in XML format��� MainWindow���>�E�n�r�e�g�i�s�t�r�e�r� �l�'�e�s�q�u�i�s�s�e� �a�c�t�u�e�l�l�e�������Save the current sketch��� MainWindow����'�%�1�'� �e�n�r�e�g�i�s�t�r�������� Saved '%1'��� MainWindow����V�u�e� �s�c�h��m�a�t�i�q�u�e������� Schematic��� MainWindow����R�e�c�h�e�r�c�h�e�r�������Search��� MainWindow����R�e�c�h�e�r�c�h�e� �d�e� �p�i��c�e�s� �d�a�n�s� �u�n�e� �e�s�q�u�i�s�s�e� �p�a�r� �l�e� �t�e�x�t�e� �c�o�r�r�e�s�p�o�n�d�a�n�t�������-Search for parts in a sketch by matching text��� MainWindow���`�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s� �"�n�o�n� �a�u�t�o�r�o�u�t��e�s�"�������#Select All "Don't Autoroute" Traces��� MainWindow���T�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s� �a�u�t�o�r�o�u�t��e�s�������Select All Autoroutable Traces��� MainWindow���R�s��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �r�e�m�p�l�i�s�s�a�g�e�s� �c�u�i�v�r�e�������Select All CopperFill��� MainWindow���>�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c�a�v�a�l�i�e�r�s�������Select All Jumpers��� MainWindow���X�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �v�e�r�r�o�u�i�l�l��s�������Select All Locked Parts��� MainWindow���<�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s�������Select All Traces��� MainWindow���D�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�t�e�s� �l�e�s� �t�r�a�v�e�r�s��e�s�������Select All Vias��� MainWindow���8�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �C��b�l�e�s�������Select All Wires��� MainWindow���p�S��l�e�c�t�i�o�n�n�e�r� �l�e� �f�i�c�h�i�e�r� �F�r�i�t�z�i�n�g� �q�u�e� �v�o�u�s� �d��s�i�r�e�z� �o�u�v�r�i�r�������Select a Fritzing File to Open��� MainWindow���`�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� ��l��m�e�n�t�s� �r�e�m�p�l�i�s� �e�n� �c�u�i�v�r�e�������Select all copper fill items��� MainWindow���<�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� ��l��m�e�n�t�s�������Select all elements��� MainWindow���b�S��l�e�c�t�i�o�n�n�e�r� �l�e�s� �c�a�v�a�l�i�e�r�s� �d�e� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s�������Select all jumper item parts��� MainWindow����S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �q�u�i� �n�e� �p�e�u�v�e�n�t� �p�a�s� ��t�r�e� �d��p�l�a�c��s�������$Select all parts that can't be moved��� MainWindow���F�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c��b�l�e�s� �p�i�s�t��s�������Select all trace wires��� MainWindow���n�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s� �e�x�c�l�u�e�s� �d�e� �l�'�a�u�t�o�r�o�u�t�a�g�e�������0Select all trace wires excluded from autorouting��� MainWindow����S��l�e�c�t�i�o�n�n�e�z� �t�o�u�s� �l�e�s� �p�i�s�t�e� �q�u�i� �p�e�u�v�e�n�t� ��t�r�e� �m�o�d�i�f�i��s� �e�n� �c�o�u�r�s� �d�'�a�u�t�o�r�o�u�t�a�g�e�������=Select all trace wires that can be changed during autorouting��� MainWindow���^�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �i�n�t�e�r�m��d�i�a�i�r�e�s�������Select all via parts��� MainWindow���8�S��l�e�c�t�i�o�n�n�e�r� �t�o�u�s� �l�e�s� �c��b�l�e�s�������Select all wires��� MainWindow��t�S��l�e�c�t�i�o�n�n�e�z� �t�o�u�t�e�s� �l�e�s� �p�i�s�t�e�s� �d�o�n�t� �l�'�e�m�p�l�a�c�e�m�e�n�t� �� �l�'��c�r�a�n� �n�e� �c�o�r�r�e�s�p�o�n�d� �p�a�s� �� �l�a� �p�o�s�i�t�i�o�n� �r��e�l�l�e�.� �U�n�i�q�u�e�m�e�n�t� �n��c�e�s�s�a�i�r�e� �p�o�u�r� �l�e�s� �e�s�q�u�i�s�s�e�s� �a�u�t�o�r�o�u�t��e�s� �a�v�e�c� �v�e�r�s�i�o�n� �0�.�7�.�1�0� �o�u� �a�n�t��r�i�e�u�r�e�������Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier��� MainWindow���J�S��l�e�c�t�i�o�n�n�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �o�b�s�o�l��t�e�s�������Select outdated parts��� MainWindow����R�e�c�u�l�e�r������� Send Backward��� MainWindow����R�e�c�u�l�e�r� �l�e�(�s�)� �o�b�j�e�t�(�s�)� �s��l�e�c�t�i�o�n�n��(�s�)� �� �l�'�i�n�t��r�i�e�u�r� �d�e� �l�e�u�r� �c�a�l�q�u�e�������+Send selected object(s) back in their layer��� MainWindow����R�e�c�u�l�e�r� �� �l�'�a�r�r�i��r�e�-�p�l�a�n� �l�e�(�s�)� �o�b�j�e�t�(�s�)� �s��l�e�c�t�i�o�n�n��(�s�)� �� �l�'�i�n�t��r�i�e�u�r� �d�e� �l�e�u�r� �c�a�l�q�u�e�������2Send selected object(s) to the back of their layer��� MainWindow���0�R�e�c�u�l�e�r� �� �l�'�a�r�r�i��r�e�-�p�l�a�n������� Send to Back��� MainWindow���2�C�o�u�l�e�u�r� �d�'�a�r�r�i��r�e�-�p�l�a�n�.�.�.�������Set Background Color...��� MainWindow���B�D��f�i�n�i�r� �l�a� �t�a�i�l�l�e� �d�e� �l�a� �g�r�i�l�l�e�.�.�.�������Set Grid Size...��� MainWindow����D��f�i�n�i�r� �l�e�s� �m�a�r�g�e�s� �d�e� �s��c�u�r�i�t�� �l�o�r�s� �d�u� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�.�.�.�������Set Ground Fill Keepout...��� MainWindow���V�D��f�i�n�i�r� �l�a� �g�r�a�i�n�e� �d�u� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�������Set Ground Fill Seed��� MainWindow����D��f�i�n�i�r� �l�e�s� �p�a�r�a�m��t�r�e�s� �d�e� �r�o�u�t�a�g�e� �a�u�t�o�m�a�t�i�q�u�e�,� �y� �c�o�m�p�r�i�s� �l�e�s� �m�a�r�g�e�s� �d�e� �s��c�u�r�i�t��.�.�.�������/Set autorouting parameters including keepout...��� MainWindow���V�R�e�n�d�r�e� �c�l�i�q�u�a�b�l�e� �l�e�s� �d�e�u�x� �c�o�u�c�h�e�s� �d�e� �c�u�i�v�r�e������� Set both copper layers clickable��� MainWindow����R�e�n�d�r�e� �u�n�i�q�u�e�m�e�n�t� �s��l�e�c�t�i�o�n�n�a�b�l�e� �l�a� �c�o�u�c�h�e� �d�e� �c�u�i�v�r�e� �i�n�f��r�i�e�u�r�e� �d�e� �l�a� �c�a�r�t�e�������!Set copper bottom layer clickable��� MainWindow����R�e�n�d�r�e� �c�l�i�q�u�a�b�l�e� �u�n�i�q�u�e�m�e�n�t� �l�a� �c�o�u�c�h�e� �d�e� �c�u�i�v�r�e� �s�u�p��r�i�e�u�r�e� �d�e� �l�a� �c�a�r�t�e�������Set copper top layer clickable��� MainWindow���F�C�o�u�l�e�u�r� �d�'�a�r�r�i��r�e�-�p�l�a�n� �d�e� �c�e�t�t�e� �v�u�e�������%Set the background color of this view��� MainWindow���8�T�a�i�l�l�e� �d�e� �l�a� �g�r�i�l�l�e� �p�o�u�r� �%�1�.�������Set the grid size for %1.��� MainWindow����D��f�i�n�i�t� �l�a� �d�i�s�t�a�n�c�e� �m�i�n�i�m�a�l�e� �e�n�t�r�e� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s� �e�t� �d�e�s� �p�i�s�t�e�s� �o�u� �c�o�n�n�e�c�t�e�u�r�s�������ESet the minimum distance between ground fill and traces or connectors��� MainWindow���Z�D��f�i�n�i�r� �l�a� �t�a�i�l�l�e� �d�e� �l�a� �g�r�i�l�l�e� �d�a�n�s� �c�e�t�t�e� �v�u�e�������%Set the size of the grid in this view��� MainWindow����P�a�r�t�a�g�e�r�������Share��� MainWindow���(�P�a�r�t�a�g�e�r� �e�n� �l�i�g�n�e�.�.�.�������Share online...��� MainWindow���*�L�a�n�c�e�m�e�n�t� �S�h�e�l�l� �d�e� �%�1�������Shell launch %1��� MainWindow������� Shift+Ctrl+A��� MainWindow������� Shift+Ctrl+D��� MainWindow��� �A�f�f�i�c�h�e�r� �l�e� �c�o�d�e������� Show Code��� MainWindow���$�A�f�f�i�c�h�e�r� �l�a� �g�r�i�l�l�e������� Show Grid��� MainWindow���v�A�f�f�i�c�h�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �d�a�n�s� �l�e� �m�a�g�a�s�i�n� �s�o�u�s� �f�o�r�m�e� �d�'�i�c��n�e�s�������Show Parts Bin Icon View��� MainWindow���v�A�f�f�i�c�h�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �d�a�n�s� �l�e� �m�a�g�a�s�i�n� �s�o�u�s� �f�o�r�m�e� �d�e� �l�i�s�t�e�������Show Parts Bin List View��� MainWindow���&�M�o�n�t�r�e�r� �"�� �p�r�o�p�o�s�"� �������Show Qt's about box��� MainWindow���t�A�f�f�i�c�h�e�r� �t�o�u�s� �l�e�s� �c�a�l�q�u�e�s� �d�i�s�p�o�n�i�b�l�e�s� �p�o�u�r� �l�a� �v�u�e� �a�c�t�u�e�l�l�e�������2Show all the available layers for the current view��� MainWindow���B�A�f�f�i�c�h�e�r� �l�'��t�i�q�u�e�t�t�e� �d�u� �c�o�m�p�o�s�a�n�t�������Show part label��� MainWindow���H�A�f�f�i�c�h�e�r� �l�a� �s��r�i�g�r�a�p�h�i�e� �d�u� �c�o�m�p�o�s�a�n�t�������Show part silkscreen��� MainWindow���6�A�f�f�i�c�h�e�r� �l�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m��������Show the PCB view��� MainWindow���$�M�o�n�t�r�e�r� �"�� �p�r�o�p�o�s�"������� Show the application's about box��� MainWindow���6�A�f�f�i�c�h�e�r� �l�a� �p�l�a�t�i�n�e� �d�'�e�s�s�a�i�������Show the breadboard view��� MainWindow���R�A�f�f�i�c�h�e�r� �l�a� �v�u�e� �d�e� �c�o�d�a�g�e� �(�p�r�o�g�r�a�m�m�a�t�i�o�n�)������� Show the code (programming) view��� MainWindow���$�A�f�f�i�c�h�e�r� �l�a� �g�r�i�l�l�e������� Show the grid��� MainWindow���6�A�f�f�i�c�h�e�r� �l�a� �v�u�e� �s�c�h��m�a�t�i�q�u�e�������Show the schematic view��� MainWindow���4�A�f�f�i�c�h�e�r� �l�a� �p�a�g�e� �d�'�a�c�c�u�e�i�l�������Show the welcome view��� MainWindow���D�A�f�f�i�c�h�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �n�o�n� �r�o�u�t��s������� Show unrouted��� MainWindow���p�A�f�f�i�c�h�e�r�/�M�a�s�q�u�e�r� �l�'��t�i�q�u�e�t�t�e� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �s��l�e�c�t�i�o�n�n��s�������*Show/hide the label for the selected parts��� MainWindow���"�E�s�q�u�i�s�s�e� �e�x�p�o�r�t��e�������Sketch exported��� MainWindow���D�E�s�q�u�i�s�s�e� �e�x�p�o�r�t��e� �a�u� �f�o�r�m�a�t� �G�e�r�b�e�r�������Sketch exported to Gerber��� MainWindow��� �O�u�p�s�!�������Sorry!��� MainWindow���T�D��s�o�l��,� �"�%�1�"� �n�'�a� �p�a�s� ��t�� �e�n�c�o�r�e� �i�m�p�l��m�e�n�t��������(Sorry, "%1" has not been implemented yet��� MainWindow���H�V�e�u�i�l�l�e�z� �s�p��c�i�f�i�e�r� �u�n� �n�o�m� �d�e� �f�i�c�h�i�e�r�������Specify a file name��� MainWindow���*�A�i�m�a�n�t�e�r� �l�e� �c�o�m�p�o�s�a�n�t�������Sticky��� MainWindow���*�R�e�d�r�e�s�s�e�r� �u�n�e� �c�o�u�r�b�e� �������Straighten Curve��� MainWindow���P�R�e�d�r�e�s�s�e�r� �l�a� �c�o�u�r�b�u�r�e� �d�u� �f�i�l� �s��l�e�c�t�i�o�n�n��������)Straighten the curve of the selected wire��� MainWindow����M�i�s�e� �� �j�o�u�r� �r��u�s�s�i�e� �d�e� �%�1� �c�o�m�p�o�s�a�n�t� �(�s�)�.� �V�e�u�i�l�l�e�z� �v��r�i�f�i�e�r� �t�o�u�t�e�s� �l�e�s� �v�u�e�s� �p�o�u�r� �l�e�s� �e�f�f�e�t�s� �s�e�c�o�n�d�a�i�r�e�s� �p�o�s�s�i�b�l�e�s�.�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow��T�L�e� �%�1� �S�v�g� �p�o�u�r� �l�a� �c�a�r�t�e� �'�%�2�'� �e�s�t� �m�a�n�q�u�a�n�t�.� �P�o�u�r� �p�l�u�s� �d�'�i�n�f�o�r�m�a�t�i�o�n�s� �s�u�r� �l�a� �c�r��a�t�i�o�n� �d�e� �c�a�r�t�e�s� �a�u�x� �f�o�r�m�e�s� �p�e�r�s�o�n�a�l�i�s��e�s�,� �c�o�n�s�u�l�t�e�z� �l�e� �t�u�t�o�r�i�e�l� �<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�<�/�a�>�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���8�E�c�h�a�n�g�� �%�1� �a�v�e�c� �l�e� �m�o�d�u�l�e� �%�2�������Swapped %1 with module %2��� MainWindow����T�e�x�t�e� �c�o�r�r�e�s�p�o�n�d�a�n�t� �� �l�'��t�i�q�u�e�t�t�e� �d�u� �c�o�m�p�o�s�a�n�t�,� �s�a� �d�e�s�c�r�i�p�t�i�o�n�,� �l�e� �t�i�t�r�e�,� �e�t�c�.� �S�a�i�s�i�s�s�e�z� �l�e� �t�e�x�t�e� �� �r�e�c�h�e�r�c�h�e�r� �:�������NText will match part label, description, title, etc. Enter text to search for:��� MainWindow���L�e� �f�o�r�m�a�t� �d�e� �f�i�c�h�i�e�r� �.�F�z� �a� ��t�� �r�e�n�d�u� �o�b�s�o�l��t�e�.� � �V�o�u�l�e�z�-�v�o�u�s� �c�o�n�v�e�r�t�i�r� �'�%�1�'� �a�u� �f�o�r�m�a�t� �.� �F�z�z� �m�a�i�n�t�e�n�a�n�t� �o�u� �l�'�o�u�v�r�i�r� �e�n� �l�e�c�t�u�r�e� �s�e�u�l�e�?� �������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow���f�L�e� �p�r�o�c�e�s�s�u�s� �d�e� �c�o�n�v�e�r�s�i�o�n� �n�e� �v�a� �p�a�s� �m�o�d�i�f�i�e�r� �'�%�1�'�.�������,The conversion process will not modify '%1'.��� MainWindow���L�e� �c�u�i�v�r�e� �d�e� �l�a� �f�a�c�e� �s�u�p��r�i�e�u�r�e� �(�c�u�i�v�r�e� �1�)� �n�'�e�s�t� �p�a�s� �d�i�s�p�o�n�i�b�l�e� �s�u�r� �u�n�e� �c�a�r�t�e� �� �u�n�e� �s�e�u�l�e� �f�a�c�e�.� �V�e�u�i�l�l�e�z� �t�r�a�s�n�f�o�r�m�e�r� �l�a� �c�a�r�t�e� �e�n� �d�o�u�b�l�e� �f�a�c�e� �o�u� �s��l�e�c�t�i�o�n�n�e�r� �l�e� �c�u�i�v�r�e� �d�e� �l�a� �f�a�c�e� �i�n�f��r�i�e�u�r�e� �(�c�u�i�v�r�e� �0�)� �.�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���x�L�e� �d�o�s�s�i�e�r� �"�%�1�"�,�n�'�e�s�t� �p�a�s� �u�n� �d�o�s�s�i�e�r� �d�'�i�n�s�t�a�l�l�a�t�i�o�n� �F�r�i�t�z�i�n�g�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���Z�I�l� �y� �a� �%�n� �c�o�m�p�o�s�a�n�t� �d�a�t�� �d�a�n�s� �c�e�t�t�e� �e�s�q�u�i�s�s�e�.���^�I�l� �y� �a� �%�n� �c�o�m�p�o�s�a�n�t�s� �d�a�t��s� �d�a�n�s� �c�e�t�t�e� �e�s�q�u�i�s�s�e�.�������.There are %n outdated part(s) in this sketch. ��� MainWindow���h�I�l� �n�'�y� �a� �p�a�s� �d�e� �c�o�n�n�e�x�i�o�n� �n�o�n� �r�o�u�t��e� �d�a�n�s� �c�e�t�t�e� �v�u�e�.�������/There are no unrouted connections in this view.��� MainWindow����I�l� �e�x�i�s�t�e� �d��j�� �u�n� �c�o�m�p�o�s�a�n�t� �a�v�e�c� �l�'�i�d� �"�%�1�"� �c�h�a�r�g�� �d�a�n�s� �F�r�i�t�z�i�n�g�.�������:There is already a part with id '%1' loaded into Fritzing.��� MainWindow����C�e�c�i� �p�e�u�t� �p�r�o�d�u�i�r�e� �d�e�s� �c�h�a�n�g�e�m�e�n�t�s� �d�a�n�s� �v�o�t�r�e� �e�s�q�u�i�s�s�e�,� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �t�o�u�t� �c�o�m�m�e� �d�e�s� �c�o�n�n�e�c�t�e�u�r�s� �p�o�u�v�a�n�t� ��t�r�e� �d��c�a�l��s�.�������RThis may result in changes to your sketch, as parts or connectors may be shifted. ��� MainWindow����C�e�t�t�e� �o�p��r�a�t�i�o�n� �n�e� �p�e�u�t� ��t�r�e� �a�n�n�u�l��e� �-� �v�o�u�s� �p�e�r�d�r�e�z� �t�o�u�t�e�s� �v�o�s� �m�o�d�i�f�i�c�a�t�i�o�n�s�.� � �C�o�n�t�i�n�u�e�r� �o�u� �a�n�n�u�l�e�r�?�������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow���V�o�u�s� �t�r�o�u�v�e�r�e�z� �i�c�i� �p�r�o�c�h�a�i�n�e�m�e�n�t� �u�n� �m�o�d�u�l�e� �d�e� �d�'�e�x�p�o�r�t� �d�e� �s�c�h��m�a� �F�r�i�t�z�i�n�g� �v�e�r�s� �l�o�g�i�c�i�e�l� �d�e� �C�A�D� �E�A�G�L�E�.� �S�i� �v�o�u�s� �s�o�u�h�a�i�t�e�z� �d�'�a�u�t�r�e�s� �m�o�d�u�l�e�s� �d�'�e�x�p�o�r�t� �v�e�r�s� �v�o�t�r�e� �l�o�g�i�c�i�e�l� �d�e� �C�A�D� �d�'��l�e�c�t�r�o�n�i�q�u�e� �f�a�v�o�r�i�,� �f�a�i�t�e�s�-�l�e� �n�o�u�s� �s�a�v�o�i�r� �o�u� �p�a�r�t�i�c�i�p�e�z� �d�i�r�e�c�t�e�m�e�n�t� �� �s�a� �c�o�n�c�e�p�t�i�o�n�.�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow����R�a�n�g�e�r� �l�e�s� �f�i�l�s������� Tidy Wires��� MainWindow���8�R�a�n�g�e�r� �l�e�s� �f�i�l�s� �s��l�e�c�t�i�o�n�n��s�������Tidy selected wires��� MainWindow���8�T�r�u�c�s�,� �a�s�t�u�c�e�s� �e�t� �r�a�c�c�o�u�r�c�i�s�������Tips, Tricks and Shortcuts��� MainWindow����F�a�c�e� �s�u�p��r�i�e�u�r�e������� Top Layer��� MainWindow����T�r�a�i�t�e�r� �c�e� �c�o�n�n�e�c�t�e�u�r� �e�t� �s�e�s� �c�o�n�n�e�x�i�o�n�s� �e�n� �t�a�n�t� �q�u�e� �"�m�a�s�s�e�"� �l�o�r�s� �d�u� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���T�I�m�p�o�s�s�i�b�l�e� �d�'�e�x�p�o�r�t�e�r� �%�1� �p�o�u�r� ��t�r�e� �p�a�r�t�a�g�������� Unable to export %1 as shareable��� MainWindow���b�I�m�p�o�s�s�i�b�l�e� �d�'�e�x�p�o�r�t�e�r� �%�1� �v�e�r�s� �l�'�e�s�q�u�i�s�s�e� �p�a�r�t�a�g��e�������'Unable to export %1 to shareable sketch��� MainWindow���X�I�m�p�o�s�s�i�b�l�e� �d�e� �c�h�a�r�g�e�r� �l�e� �c�o�m�p�o�s�a�n�t� �p�o�u�r� �"�%�1�"�������Unable to load part from '%1'��� MainWindow���:�I�m�p�o�s�s�i�b�l�e� �d�'�o�u�v�r�i�r� �"�%�1�"� �:� �%�2�������Unable to open '%1': %2��� MainWindow���`�I�m�p�o�s�s�i�b�l�e� �d�'�o�u�v�r�i�r� �"�%�1�"� �p�o�u�r� �l�e� �p�a�r�t�a�g�e� �d�e� �:� �%�2�������!Unable to open shareable '%1': %2��� MainWindow���t�I�m�p�o�s�s�i�b�l�e� �d�'�o�u�v�r�i�r� �"�%�1�"� �p�o�u�r� �l�e� �p�a�r�t�a�g�e� �d�u� �c�o�m�p�o�s�a�n�t� �:� �%�2�������&Unable to open shareable part '%1': %2��� MainWindow���8�I�m�p�o�s�s�i�b�l�e� �d�e� �s�a�u�v�e�g�a�r�d�e�r� �%�1�������Unable to save %1��� MainWindow����I�m�p�o�s�s�i�b�l�e� �d�'�e�n�r�e�g�i�s�t�r�e�r� �l�e� �f�i�c�h�i�e�r� �d�e� �n�o�m�e�n�c�l�a�t�u�r�e�,� �m�a�i�s� �l�e� �t�e�x�t�e� �e�s�t� �d�a�n�s� �l�e� �p�r�e�s�s�e�-�p�a�p�i�e�r�s�.�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow����A�n�n�u�l�e�r�������Undo��� MainWindow���.�H�i�s�t�o�r�i�q�u�e� �d�'�a�n�n�u�l�a�t�i�o�n������� Undo History��� MainWindow���,�C�o�n�n�e�x�i�o�n�s� �n�o�n� �r�o�u�t��e�s�������Unrouted connections��� MainWindow���@�M�i�s�e� �� �j�o�u�r� �d�e� �"�%�1�"� �c�o�m�p�o�s�a�n�t�(�s�)�������Update %1 part(s)��� MainWindow���|�M�e�t�t�r�e� �� �j�o�u�r� �l�'�I�n�f�o�V�i�e�w� �l�o�r�s�q�u�'�i�l� �e�s�t� �s�u�r�v�o�l�� �p�a�r� �l�e� �p�o�i�n�t�e�u�r�������Update InfoView on hover��� MainWindow���N�M�i�s�e� �� �j�o�u�r� �d�e�s� �c�o�m�p�o�s�a�n�t�s� �s��l�e�c�t�i�o�n�n��s�������Update selected parts��� MainWindow����V�u�e� �d�u� �D�e�s�s�u�s�������View from Above��� MainWindow����V�u�e� �d�u� �D�e�s�s�o�u�s�������View from Below��� MainWindow����V�u�e� �d�u� �d�e�s�s�u�s�������View from above��� MainWindow����V�u�e� �d�u� �d�e�s�s�o�u�s�������View from below��� MainWindow����A�f�f�i�c�h�e�r� �l�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �v�u� �d�e� �l�a� �f�a�c�e� �i�n�f��r�i�e�u�r�e� �e�t� �o�r�i�e�n�t�� �v�e�r�s� �l�e� �h�a�u�t�������+View the PCB from the bottom layers upwards��� MainWindow����A�f�f�i�c�h�e�r� �l�a� �f�a�c�e� �s�u�p��r�i�e�u�r�e� �d�u� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �e�t� �o�r�i�e�n�t��e� �v�e�r�s� �l�e� �b�a�s�������*View the PCB from the top layers downwards��� MainWindow����N�o�u�s� �v�o�u�s� �r�e�c�o�m�m�a�n�d�o�n�s� �f�o�r�t�e�m�e�n�t� �d�e� �m�e�t�t�r�e� �� �j�o�u�r� �c�e� �c�o�m�p�o�s�a�n�t� �%�n� �a�v�e�c� �l�a� �v�e�r�s�i�o�n� �l�a� �p�l�u�s� �r��c�e�n�t�e�.����N�o�u�s� �v�o�u�s� �r�e�c�o�m�m�a�n�d�o�n�s� �f�o�r�t�e�m�e�n�t� �d�e� �m�e�t�t�r�e� �� �j�o�u�r� �c�e�s� �c�o�m�p�o�s�a�n�t�s� �%�n� �a�v�e�c� �l�e�u�r� �v�e�r�s�i�o�n� �l�a� �p�l�u�s� �r��c�e�n�t�e�.�������MWe strongly recommend that you update these %n parts to the latest version. ��� MainWindow����P�a�g�e� �d�'�a�c�c�u�e�i�l�������Welcome��� MainWindow����L�o�r�s� �d�e� �l�'�a�u�t�o�r�o�u�t�a�g�e�,� �n�e� �p�a�s� �c�o�u�p�e�r� �c�e�t�t�e� �p�i�s�t�e�,� �t�r�a�v�e�r�s��e� �d�e� �p�i�s�t�e�,� �o�u� �c�a�v�a�l�i�e�r�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow����X�M�L� �N�e�t�l�i�s�s�t�.�.�.�������XML Netlist...��� MainWindow����V�o�u�s� �d�e�v�r�e�z� �r�e�d��m�a�r�r�e�r� �F�r�i�t�z�i�n�g� �a�f�i�n� �d�'�u�t�i�l�i�s�e�r� �l�e�s� �c�o�m�p�o�s�a�n�t�s� �i�m�p�o�r�t��s�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow����V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �a�f�i�n� �d�e� �p�o�u�v�o�i�r� �l�'�e�x�p�o�r�t�e�r� �v�e�r�s� �G�e�r�b�e�r�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow����V�o�t�r�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �a�f�i�n� �d�'��l�i�m�i�n�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e� �c�u�i�v�r�e�.�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow���V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �a�f�i�n� �d�'�u�t�i�l�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e� �m�a�s�s�e� �o�u� �e�n� �c�u�i�v�r�e�.�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow����V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� � �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �p�o�u�r� �u�t�i�l�i�s�e�r� �l�'�a�u�t�o�r�o�u�t�a�g�e�.�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow����V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �L�a� �R�D�C� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �s�i� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �e�x�i�s�t�e�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow����V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �p�l�a�q�u�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �a�f�i�n� �d�e� �p�o�u�v�o�i�r� �l�'�e�x�p�o�r�t�e�r�.�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow���V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �p�o�u�r� �u�t�i�l�i�s�e�r� �l�e�s� �o�p��r�a�t�i�o�n�s� �d�e� �r�e�m�p�l�i�s�s�a�g�e� �e�n� �c�u�i�v�r�e�.�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow����Z�o�o�m� �a�v�a�n�t�������Zoom in��� MainWindow����Z�o�o�m� �a�r�r�i��r�e�������Zoom out��� MainWindow����c�o�m�m�e� �I�m�a�g�e�������as Image��� MainWindow���"�c�o�u�c�h�e� �i�n�f��r�i�e�u�r�e�������bottom��� MainWindow��� �c�u�i�v�r�e�������copper��� MainWindow���$�r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e������� copperfill��� MainWindow���H�C�o�m�p�o�s�a�n�t�s� ��t�a�n�t� �c�h�a�r�g��s� �d�i�r�e�c�t�e�m�e�n�t�������directly loading parts��� MainWindow���$�p�o�u�r� �l�a� �P�r�o�d�u�c�t�i�o�n�������for Production��� MainWindow��� �m�a�s�s�e�������ground��� MainWindow����d�a�n�s�������in��� MainWindow����C�a�v�a�l�i�e�r�s�������jumpers��� MainWindow��� �C�h�a�r�g�e�m�e�n�t� �d�e� �%�1������� loading %1��� MainWindow���>�c�h�a�r�g�e�m�e�n�t� �%�1� �(�p�l�a�t�i�n�e� �d�'�e�s�s�a�i�)�������loading %1 (breadboard)��� MainWindow���,�c�h�a�r�g�e�m�e�n�t� �%�1� �(�m�o�d��l�e�)�������loading %1 (model)��� MainWindow���>�c�h�a�r�g�e�m�e�n�t� �%�1� �(�c�i�r�c�u�i�t� �i�m�p�r�i�m��)�������loading %1 (pcb)��� MainWindow���6�c�h�a�r�g�e�m�e�n�t� �%�1� �(�s�c�h��m�a�t�i�q�u�e�)�������loading %1 (schematic)��� MainWindow���"�N�o�u�v�e�l�l�e� �e�s�q�u�i�s�s�e������� new sketch��� MainWindow���J�L�e� �f�o�r�m�a�t� �d�e� �f�i�c�h�i�e�r� �.�f�z� �e�s�t� �o�b�s�o�l��t�e�������the .fz file format is obsolete��� MainWindow���j�l�a�n�c�e�r� �u�n�e� �f�a�u�s�s�e� �e�x�c�e�p�t�i�o�n� �p�o�u�r� �v�o�i�r� �c�e� �q�u�i� �s�e� �p�a�s�s�e�������*throw a fake exception to see what happens��� MainWindow���8�l�a�n�c�e�r� �u�n�e� �e�x�c�e�p�t�i�o�n� �d�e� �t�e�s�t�������throw test exception��� MainWindow����s�u�p��r�i�e�u�r�������top��� MainWindow���8�s�u�p��r�i�e�u�r�(�e�)� �e�t� �i�n�f��r�i�e�u�r�(�e�)�������top and bottom��� MainWindow���^�I�m�p�o�s�s�i�b�l�e� �d�e� �t�r�o�u�v�e�r� �u�n� �r�e�m�p�l�a�c�e�m�e�n�t� �p�o�u�r� �%�1�.� �������#unable to find replacement for %1. ��� MainWindow����t�r�a�v�e�r�s��e�s�������vias��� MainWindow���"�a�v�e�c� �%�n� �t�r�a�v�e�r�s��e���$�a�v�e�c� �%�n� �t�r�a�v�e�r�s��e�s������� with %n vias��� MazeRouter���6�L�'�a�u�t�o�r�o�u�t�a�g�e� �� ��t�� �a�n�n�u�l��.�������Autorouter was cancelled.��� MazeRouter���4�O�p�t�i�m�i�s�a�t�i�o�n� �d�e�s� �p�i�s�t�e�s�.�.�.�������Optimizing traces...��� MazeRouter���8�A�n�n�u�l�a�t�i�o�n� �e�n� �p�r��p�a�r�a�t�i�o�n�.�.�.�������Preparing undo...��� MazeRouter��� �R�o�u�t�a�g�e� �t�e�r�m�i�n��!�������Routing complete!��� MazeRouter���V�L�e� �r�o�u�t�a�g�e� �a� �a�t�t�e�i�n�t� �%�1� �c�o�m�m�e� �t�o�u�r� �m�a�x�i�m�a�l�.�������!Routing reached maximum round %1.��� MazeRouter����R�o�u�t�a�g�e� �a�r�r��t��!�������Routing stopped!��� MazeRouter���D�R�o�u�t�a�g�e� ��c�h�o�u��;� �a�r�r��t�� �a�u� �t�o�u�r� �%�1�.�������+Routing unsuccessful; stopping at round %1.��� MazeRouter���h��c�h�e�c� �d�e� �r�e�n�d�u� �S�V�G� �I�n�a�t�t�e�n�d�u�.� �C�o�n�t�a�c�t�e�r� �f�r�i�t�z�i�n�g�.�o�r�g�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���B�U�t�i�l�i�s�e�z� �l�e� �m�e�i�l�l�e�u�r� �� �c�e� �j�o�u�r�.�.�.�������Use best so far...��� MazeRouter���h�m�e�i�l�l�e�u�r� �r��s�u�l�t�a�t� �j�u�s�q�u�'�� �p�r��s�e�n�t� �:�%�1� �d�e�%�2� �a�c�h�e�m�i�n��s�������best so far: %1 of %2 routed��� MazeRouter����%�1� �t�o�u�r� �d�a�n�s� �:������� round %1 of:��� MazeRouter���j�I�m�p�o�s�s�i�b�l�e� �d�e� �r�e�m�p�l�a�c�e�r� �"�%�1�"�.� �R�a�i�s�o�n� �:�%�2� �(� �e�r�r�c�o�d�e�%�3�)�������5Couldn't overwrite file '%1'. Reason: %2 (errcode %3)��� ModelBase���J�L�'�e�n�r�e�g�i�s�t�r�e�m�e�n�t� �d�u� �f�i�c�h�i�e�r� �� ��c�h�o�u��!�������File save failed!��� ModelBase���^�I�m�p�o�s�s�i�b�l�e� �d�e� �t�r�o�u�v�e�r� �l�e� �%�n� �c�o�m�p�o�s�a�n�t� �s�u�i�v�a�n�t� �:���p�I�m�p�o�s�s�i�b�l�e� �d�e� �t�r�o�u�v�e�r� �l�e�(�s�)� �%�n� �c�o�m�p�o�s�a�n�t�(�s�)� �s�u�i�v�a�n�t�(�s�)� �:�������(Unable to find the following %n part(s):��� ModelBase����d�a�n�s�������at��� ModelBase���(��t�i�q�u�e�t�t�e� �d�e� �l�a� �p�u�c�e������� chip label��� MysteryPart�����t�i�q�u�e�t�t�e�������label��� MysteryPart����l�a�b�e�l� �d�e� �r��s�e�a�u������� net label���NetLabel���2�[��c�r�i�v�e�z� �v�o�t�r�e� �t�e�x�t�e� �i�c�i�]�������[write your note here]���Note����%�1� �R�e�m�p�l�i�s�s�a�g�e� �:� �v�e�u�i�l�l�e�z� �s��l�e�c�t�i�o�n�n�e�r� �l�a� �c�a�r�t�e� �o�� �v�o�u�s� �s�o�u�h�a�i�t�e�z� �a�p�p�l�i�q�u�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e�.�������;%1 Fill: please select the board you want to apply fill to.���PCBSketchWidget���D�1�0� �m�m� �e�s�t� �u�n� �b�o�n� �c�h�o�i�x� �p�a�r� �d��f�a�u�t�.�������#10 mils is a good default choice. ���PCBSketchWidget���:�M�o�d�i�f�i�e�r� �l�e� �c�a�l�q�u�e� �d�e�s� �p�i�s�t�e�s�������Change trace layer���PCBSketchWidget���F�R��i�n�i�t�i�a�l�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e�������Clear ground fill seeds���PCBSketchWidget���t�C�l�i�q�u�e�r� �s�u�r� �c�e� �c�o�n�n�e�c�t�e�u�r� �p�o�u�r� ��t�a�b�l�i�r� �u�n�e� �n�o�u�v�e�l�l�e� �p�i�s�t�e�.�������-Click this connector to drag out a new trace.���PCBSketchWidget��� �C�u�i�v�r�e�������Copper���PCBSketchWidget����R�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e� �:� �v�e�u�i�l�l�e�z� �n�e� �s��l�e�c�t�i�o�n�n�e�r� �q�u�e� �l�a� �c�a�r�t�e� �� �r�e�m�p�l�i�r�.�������;Copper fill: please select only the board you want to fill.���PCBSketchWidget���P�C�r��e�r� �u�n�e� �p�i�s�t�e� �� �p�a�r�t�i�r� �d�'�u�n� �f�i�l� �v�o�l�a�n�t�������Create Trace from Ratsnest���PCBSketchWidget���<�S�a�i�s�i�s�s�e�z� �l�a� �m�a�r�g�e� �d�e� �s��c�u�r�i�t�������� Enter Keepout���PCBSketchWidget���T�E�n�t�r�e�z� �l�a� �v�a�l�e�u�r� �d�e� �l�a� �m�a�r�g�e� �d�e� �s��c�u�r�i�t�� �:�������Enter keepout value:���PCBSketchWidget���B�E�s�t�i�m�a�t�i�o�n� �d�e�s� �c�o��t�s� �F�r�i�t�z�i�n�g� �F�a�b�������Fritzing Fab Quote���PCBSketchWidget���n�E�r�r�e�u�r� �F�r�i�t�z�i�n�g� �:� �r�e�n�d�u� �d�e� �l�a� �c�a�r�t�e� �(�1�)� �s�v�g� �i�m�p�o�s�s�i�b�l�e�.�������/Fritzing error: unable to render board svg (1).���PCBSketchWidget����E�r�r�e�u�r� �F�r�i�t�z�i�n�g� �:� �i�m�p�o�s�s�i�b�l�e� �d�'�e�f�f�e�c�t�u�e�r� �l�e� �r�e�n�d�u� �c�u�i�v�r�e� �s�v�g� �(�1�)�.�������0Fritzing error: unable to render copper svg (1).���PCBSketchWidget����E�r�r�e�u�r� �F�r�i�t�z�i�n�g� �:� �E�c�r�i�t�u�r�e� �d�u� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e� �(�1�)� �i�m�p�o�s�s�i�b�l�e�.�������0Fritzing error: unable to write copper fill (1).���PCBSketchWidget����E�r�r�e�u�r� �F�r�i�t�z�i�n�g� �:� �E�c�r�i�t�u�r�e� �d�u� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e� �(�2�)� �i�m�p�o�s�s�i�b�l�e�.�������0Fritzing error: unable to write copper fill (2).���PCBSketchWidget��� �M�a�s�s�e�������Ground���PCBSketchWidget���F�M�a�s�q�u�e�r� �l�a� �s��r�i�g�r�a�p�h�i�e� �d�u� �c�o�m�p�o�s�a�n�t�������Hide part silkscreen���PCBSketchWidget���H�P�o�s�i�t�i�o�n�s� �i�n�t�e�r�d�i�t�e�s� �>� �(�0�.�0�2�5�4� �m�m�)�.� �������#Keepout is in mils (.001 inches). ���PCBSketchWidget����N�o�t�e�z� �q�u�'�e�n� �r�a�i�s�o�n� �d�e� �l�'�a�l�i�a�s�i�n�g�,� �l�e�s� �d�i�s�t�a�n�c�e�s� �p�e�u�v�e�n�t� ��t�r�e� �t�r�o�p� �c�o�u�r�t�e�s� �d�'�u�n�e� �d�i�s�t�a�n�c�e� �a�l�l�a�n�t� �j�u�s�q�u�� �2� �m�i�l�s� �������FNote that due to aliasing, distances may be too short by up to 2 mils ���PCBSketchWidget����V�e�u�i�l�l�e�z� �c�l�i�q�u�e�r� �s�u�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �d�'�a�b�o�r�d�.� �C�e�t�t�e� �o�p��r�a�t�i�o�n� �d�e� �s��l�e�c�t�i�o�n� �n�e� �f�o�n�c�t�i�o�n�n�e� �q�u�e� �p�o�u�r� �u�n�e� �s�e�u�l�e� �c�a�r�t�e� �� �l�a� �f�o�i�s�.�������YPlease click on a PCB first--this selection operation only works for one board at a time.���PCBSketchWidget����V�e�u�i�l�l�e�z� �d��s�i�g�n�e�r� �u�n� �o�u� �p�l�u�s�i�e�u�r�s� �m�a�s�s�e�s� �a�v�a�n�t� �d�'�e�f�f�e�c�t�u�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e�s� �m�a�s�s�e�s�.�������LPlease designate one or more ground fill seeds before doing a ground fill. ���PCBSketchWidget���H�A�f�f�i�c�h�e�r� �l�a� �s��r�i�g�r�a�p�h�i�e� �d�u� �c�o�m�p�o�s�a�n�t�������Show part silkscreen���PCBSketchWidget���D��s�o�l��,� �h�t�t�p�:�/�/�f�a�b�.�f�r�i�t�z�i�n�g�.�o�r�g� �n�e� �r��p�o�n�d� �p�a�s� �p�o�u�r� �l�a� �d�e�m�a�n�d�e� �d�e� �d�e�v�i�s�.� �V�e�u�i�l�l�e�z� �v��r�i�f�i�e�r� �v�o�t�r�e� �c�o�n�n�e�x�i�o�n� �r��s�e�a�u� �e�t�/�o�u� �r��e�s�s�a�y�e�r� �p�l�u�s� �t�a�r�d�.�������Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later.���PCBSketchWidget���I�m�p�o�s�s�i�b�l�e� �d�e� �c�o�n�v�e�r�t�i�r� �c�e� �p�o�i�n�t� �d�e� �c�o�n�n�e�x�i�o�n�/�a�r�t�i�c�u�l�a�t�i�o�n� �e�n� �c�o�n�n�e�x�i�o�n� �t�r�a�v�e�r�s�a�n�t�e� �c�a�r� �e�l�l�e� �e�s�t� �r�e�l�i��e� �� �u�n� �c�o�m�p�o�s�a�n�t� �q�u�i� �e�s�t� �u�n�i�q�u�e�m�e�n�t� �s�u�r� �l�a� �c�o�u�c�h�e� �d�e� �c�u�i�v�r�e� �i�n�f��r�i�e�u�r�e� �e�t� �u�n� �a�u�t�r�e� �c�o�m�p�o�s�a�n�t� �q�u�i� �e�s�t� �u�n�i�q�u�e�m�e�n�t� �s�u�r� �l�a� �c�o�u�c�h�e� �s�u�p��r�i�e�u�r�e�.�������Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer.���PCBSketchWidget��H�I�m�p�o�s�s�i�b�l�e� �d�e� �c�r��e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e� �-� �i�l� �e�s�t� �p�o�s�s�i�b�l�e� �q�u�e� �l�e� �c�o�m�p�o�s�a�n�t� �a�i�t� ��t�� �a�j�o�u�t�� �s�u�r� �u�n�e� �a�u�t�r�e� �c�o�m�p�o�s�a�n�t� �o�u� �c��b�l�e� �p�l�u�t��t� �q�u�e� �s�u�r� �l�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �r��e�l�.�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget����I�m�p�o�s�s�i�b�l�e� �d�e� �c�r��e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �c�u�i�v�r�e� �-� �L�e� �c�o�m�p�o�s�a�n�t� �n�'�a� �p�r�o�b�a�b�l�e�m�e�n�t� �p�a�s� ��t�� �a�j�o�u�t�� �s�u�r� �l�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget�� �V�o�t�r�e� �c�r�o�q�u�i�s� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �a�f�i�n� �d�e� �p�o�u�v�o�i�r� �u�t�i�l�i�s�e�r� �l�e� �r�e�m�p�l�i�s�s�a�g�e� �d�e� �c�u�i�v�r�e�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget���V�o�t�r�e� �c�r�o�q�u�i�s� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e� �!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �p�o�u�r� �p�o�u�v�o�i�r� �u�t�i�l�i�s�e�r� �c�e�t�t�e� �o�p��r�a�t�i�o�n� �d�e� �s��l�e�c�t�i�o�n�.�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget�� �V�o�t�r�e� �c�r�o�q�u�i�s� �n�e� �c�o�m�p�o�r�t�e� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e�!� �V�e�u�i�l�l�e�z� �a�j�o�u�t�e�r� �u�n� �c�i�r�c�u�i�t� �i�m�p�r�i�m�� �p�o�u�r� �p�o�u�v�o�i�r� �u�t�i�l�i�s�e�r� �c�e�t�t�e� �o�p��r�a�t�i�o�n� �d�e� �s��l�e�c�t�i�o�n�.�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget����V�o�t�r�e� �e�s�q�u�i�s�s�e� �n�'�a� �p�a�s� �e�n�c�o�r�e� �d�e� �c�a�r�t�e�.� �V�o�u�s� �n�e� �p�o�u�v�e�z� �p�a�s� �f�a�b�r�i�q�u�e�r� �c�e�t�t�e� �e�s�q�u�i�s�s�e� �s�a�n�s� �u�n�e� �p�a�r�t�i�e� �c�i�r�c�u�i�t� �i�m�p�r�i�m��.�������[Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.���PCBSketchWidget����d�e� �s�o�r�t�e� �q�u�e� �v�o�u�s� �p�o�u�r�r�i�e�z� �v�o�u�l�o�i�r� �a�u�g�m�e�n�t�e�r� �l�a� �v�a�l�e�u�r� �d�e� �l�a� �m�a�r�g�e� �d�e� �s��c�u�r�i�t�� �d�'�a�u�t�a�n�t�.� � �������=so you may want to increase the keepout value by that much. ���PCBSketchWidget���(�C�o�m�p�o�s�a�n�t� �d�e� �s�u�r�f�a�c�e�������SMD���PEConnectorsView����C�'�e�s�t� �i�c�i� �q�u�e� �v�o�u�s� �m�o�d�i�f�i�e�z� �l�e�s� �m��t�a�d�o�n�n��e�s� �d�e�s� �c�o�n�n�e�c�t�e�u�r�s� �d�u� �c�o�m�p�o�s�a�n�t�������:This is where you edit the connector metadata for the part���PEConnectorsView���(�C�o�m�p�o�s�a�n�t� �t�r�a�v�e�r�s�a�n�t������� Through-hole���PEConnectorsView���.�n�o�m�b�r�e� �d�e� �c�o�n�n�e�c�t�e�u�r�s� �:�������number of connectors:���PEConnectorsView���4�P�o�u�r�s�u�i�v�r�e� �e�t� �s�a�u�v�e�g�a�r�d�e�r�?������� Go ahead and save?��� PEMainWindow����&��d�i�t�i�o�n�������&Edit��� PEMainWindow����&�E�x�p�o�r�t�e�r�������&Export��� PEMainWindow����&�F�i�c�h�i�e�r�������&File��� PEMainWindow����'�%�1�'�������'%1', ��� PEMainWindow����<�b�r�/�>�<�b�r�/�>�c�e� �n�e� �s�e�r�a� �p�l�u�s� �u�n� �p�r�o�b�l��m�e� �d�a�n�s� �l�a� �p�r�o�c�h�a�i�n�e� �v�e�r�s�i�o�n� �d�e� �l�'��d�i�t�e�u�r� �d�e� �c�o�m�p�o�s�a�n�t�s�,� �������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowVUne seule proprit "famille" est autorise,A duplicate 'family' property is not allowed PEMainWindowXUne seule proprit "Variante" est autorise-A duplicate 'variant' property is not allowed PEMainWindow,Ajouter %1 connecteursAdd %1 connectors PEMainWindow*Ajouter un connecteur Add connector PEMainWindowpAjouter une connexion interne dans '%1' partir de '%2')Add internal connection from '%1' to '%2' PEMainWindow@Les vides ne sont pas autorisssBlank not allowed PEMainWindowAnnulerCancel PEMainWindow*Modifier '%1' en '%2'Change %1 to %2 PEMainWindow"Modifier %1 en %2Change %1 to '%2' PEMainWindowJModifier tous les connecteurs dans %1Change all connectors to %1 PEMainWindow2Modifier le connecteur %1Change connector %1 PEMainWindow.Modifier la descriptionChange description PEMainWindow0Modifier les propritesChange properties PEMainWindow.Modifier les tiquettes Change tags PEMainWindow Modifier dans %1 Change to %1 PEMainWindow0Quitter sans enregistrerClose without saving PEMainWindow2Quitter sans enregistrer?Close without saving? PEMainWindowConnecteurs Connectors PEMainWindow2Affichage des connecteursConnectors View PEMainWindow,Problme de conversionConversion problem PEMainWindow"Problme de copie Copy problem PEMainWindow~Voulez-vous continuer travailler ou quitter sans sauvegarder?4Do you want to keep working or close without saving? PEMainWindowVoulez-vous enregistrer les modifications que vous avez apportes au composant "%1"?:Do you want to save the changes you made in the part "%1"? PEMainWindowVUne seule proprit "famille" est autorise'Duplicate 'family' property not allowed PEMainWindowVUne seule proprit "famille" est autorise(Duplicate 'variant' property not allowed PEMainWindow&Problme de doublonDuplicate problem PEMainWindowQuitter l'diteur de composant maintenant, c'est bien, pour autant que vous vous souveniez de terminer les travaux plus tard.^Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMainWindow2Prfixe du nom de fichierFilename prefix PEMainWindowPolicesFonts PEMainWindowREditeur de (Nouveaux) composants FritzingFritzing (New) Parts Editor PEMainWindowFritzing ne supporte actuellement que les polices OCRA et Droid - celles-ci ont t substitues aux polices de caractres dans '%1'kFritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' PEMainWindow IcneIcon PEMainWindow(Affichage des icnes Icon View PEMainWindow, Si vous apportez des modifications la vue de la platine d'essai ou modifiez les mtadonnes des connexions, les pattes peuvent ne plus fonctionner.cIf you make changes to breadboard view, or change connector metadata, the legs may no longer work.  PEMainWindowFichiers d'images (%1 %2 %3);;Fichiers SVG (%1);;Fichiers JPEG (%2);;Fichiers PNG (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowInspecteur Inspector PEMainWindow\Les connexions internes sont trs en dsordre.(Internal connections are very messed up. PEMainWindow(Ignorer la procdure Keep working PEMainWindowCalquesLayers PEMainWindowNChargement de l'image pour cette vue...Load image for view... PEMainWindowEffectuer un copie de ce composant et l'enregistrer dans "Mes composants" (My Parts)9Make a copy of the part and save it in the 'My Parts' Bin PEMainWindowFRendre visible uniquement la vue %1Make only %1 view visible PEMainWindowFRendre visible uniquement cette vueMake only this view visible PEMainWindowMtadonnesMetadata PEMainWindow2Affichage des mtadonnes Metadata View PEMainWindow4Dplacer le point terminalMove terminal point PEMainWindow Doit tre uniqueMust be unique PEMainWindowSur le bureau, ouvrez le dossier contenant le fichier svg actuel.@On the desktop, open the folder containing the current svg file. PEMainWindow Ouvrir une image Open Image PEMainWindowOuvrir le fichier utiliser comme image pour cette vue du composant.:Open a file to use as the image for this view of the part. PEMainWindowLes images PNG et JPG conservent leur nature en tant que bitmaps n'ont pas une bonne apparence lorsqu'elles sont redimensionnes--TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindow*diteur de composants Parts Editor PEMainWindowVeuillez entrer un prfixe pour vous aider identifier les fichiers de composants. Les noms auront la forme 'PREFIX_%1'. (Il n'est pas ncessaire de changer le prfixe puisqu'un suffixe unique est toujours ajout.)Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) PEMainWindowVeuillez r-exporter le fichier SVG en utilisant ce rglage, puis ressayez de le charger.HPlease re-export the SVG file using that setting, and try loading again. PEMainWindow8Relocaliser le connecteur %1Relocate connector %1 PEMainWindow4Supprimer '%1' connecteursRemove %1 connectors PEMainWindow<Supprimer la connexion interneRemove Internal Connection PEMainWindow.Supprimer le connecteurRemove connector PEMainWindowPSupprimer la connexion interne dans '%1'$Remove internal connection from '%1' PEMainWindowJRutiliser l'image du circuit imprimReuse PCB image PEMainWindowPRutiliser l'image de la platine d'essaiReuse breadboard image PEMainWindow8Rutiliser l'image du schmaReuse schematic image PEMainWindowhRutiliser l'image du circuit imprim dans cette vue Reuse the PCB image in this view PEMainWindownRutiliser l'image de la platine d'essai dans cette vue'Reuse the breadboard image in this view PEMainWindowVRutiliser l'image du schma dans cette vue&Reuse the schematic image in this view PEMainWindowProblme SVG SVG problem PEMainWindowEnregistrerSave PEMainWindowEnregistrer %1 Save "%1" PEMainWindowREnregistrer en tant que nouveau composantSave as new part PEMainWindowSauvegarder cette partie apporteras une modification l'esquisse qui ne pourras plus tre annule.HSaving this part will make a change to the sketch that cannot be undone. PEMainWindowSauvegarder cette partie apporteras une modification ces esquisses qui ne pourront plus tre annules.LSaving this part will make a change to these sketches that cannot be undone. PEMainWindowConsultez cette explication :<a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/"></a>.ySee this explanation. PEMainWindow0Afficher les connecteursShow Connectors PEMainWindow(Affficher les icnes Show Icon PEMainWindow0Afficher les mtadonnes Show Metadata PEMainWindow(Voir dans le dossierShow in Folder PEMainWindowxAfficher les mtadonnes des connecteurs sous forme de liste*Show the connector metadata in a list view PEMainWindow2Afficher en tant qu'icneShow the icon view PEMainWindow0Afficher les mtadonnesShow the metadata view PEMainWindowBAvertissement - esquisse modifieSketch Change Warning PEMainWindowPar consquent, l'dition peut produire un affichage incorrect de l'image du circuit imprim0So editing may produce an invalid PCB view image PEMainWindow`La proprit "famille" ne peut pas rester vide.'The 'family' property can not be blank. PEMainWindowLe fichier SVG '%1' semble avoir t export partir de CorelDRAW sans rglage des 'attributs de prsentation'.nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindowL'esquisse '%1' actuellement ouverte utilise le composant que vous modifiez.4The open sketch '%1' uses the part you are editing.  PEMainWindow,Les esquisses ouvertesThe open sketches  PEMainWindowCe composant est uniquement visible dans cette vue ainsi qu'en icne8The part will only be visible in this view and icon view PEMainWindowXLa valeur dans '%1' ne peut pas rester vide.#The value of '%1' can not be blank. PEMainWindowhIl n'y a pas de couches de cuivre dfinies dans :%1.+There are no copper layers defined in: %1.  PEMainWindowZIl ya une dernire dition encore en suspens.%There is one last edit still pending. PEMainWindowjCe composant ne peut pas tre sauvegard tel quel : #This part can not be saved as-is:  PEMainWindowVCe composant a %n connecteurs non assigns ^Ces composants ont %n connecteurs non assigns 'This part has %n unassigned connectors  PEMainWindowFCe composant a des pattes pliables.This part has bendable legs.  PEMainWindowv Cette version de l'diteur de composant ne prend pas encore en charge l'dition de pattes pliables et les pattes peuvent ne pas s'afficher correctement dans la vue de la platine d'essai.This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindow Cette version de l'diteur de nouveau composants ne peut pas traiter sparment les calques copper0 et copper1 dans '%1'.dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindowCet avertissement ne sera pas rpt durant cette session de Fritzing=This warning will not be repeated in this session of Fritzing PEMainWindowImpossible de crer de nouveau connecteur - vous pourriez avoir tout recommencer.;Unable to create new connector--you may have to start over. PEMainWindow4Impossible de charger '%1'Unable to load '%1' PEMainWindowImpossible de charger '%1'. Fermez l'diteur de nouveau composants sans sauvegarder pralablement, puis ressayez.PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindowXImpossible de charger le fichier fzp dans %1Unable to load fzp from %1 PEMainWindow\Impossible de charger le fichier d'images '%1'Unable to load image file '%1' PEMainWindowdImpossible de charger le fichier d'images '%1' %2$Unable to load image file '%1': %2 PEMainWindowNImpossible de faire une copie de : '%1'$Unable to make a local copy of: '%1' PEMainWindow4Impossible d'analyser '%1'Unable to parse '%1' PEMainWindowxImpossible d'analyser '%1' : %2 la ligne : %3 colonne : %4*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindowNImpossible d'analyser le fichier fzp %1Unable to parse fzp file %1 PEMainWindowDImpossible d'crire en svg dans %1Unable to write svg to %1 PEMainWindowJusqu' ce que tous les connecteurs soient affects des lments SVG, le composant ne fonctionnera pas correctement.UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindow^L'utilisation de PNG et de JPG est dconseilleUse of PNG and JPG discouraged PEMainWindowLa variante '%1' est en cours d'utilisation. Le nom de la variante doit tre unique.8Variant '%1' is in use. The variant name must be unique. PEMainWindow Vous pouvez faire en toute scurit les modifications au schma ou de la vue du circuit imprim. 7You can safely make changes to Schematic or PCB view.  PEMainWindowVous pouvez utiliser une image PNG ou JPG pour construire votre composant, mais il est prfrable d'utiliser un SVG.WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindowVos modifications seront perdues si vous ne les enregistrez pas.1Your changes will be lost if you don't save them. PEMainWindowdans %n' vue. dans %n' vues. across %n views.  PEMainWindowet '%1' and '%1'  PEMainWindowmais pour l'instant veuillez modifier le fichier en suivant les instructions accessibles via le lien.Mbut for now please modify the file according to the instructions in the link. PEMainWindowNAucune empreinte n'a t trouve dans%1no footprints found in %1 PEMainWindowFAucun schma n'a t trouv dans %1no schematics found in %1 PEMainWindow&Schma du composantschematic part PEMainWindowAlors pour les composants Fritzing, il est prfrable d'utiliser des PNG et JPG uniquement comme espaces rservs.Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindow(composant sans titre untitled part PEMainWindow AuteurAuthorPEMetadataViewFamilleFamilyPEMetadataViewEtiquetteLabelPEMetadataViewProprits PropertiesPEMetadataViewfDfinir le prfixe du label par dfaut du composant!Set the default part label prefixPEMetadataView Dfinir l'auteurSet the part's authorPEMetadataView6Dfinir la date de crationSet the part's datePEMetadataViewDfinir la description du composant - vous pouvez utiliser du code HTML simple ( tel que dfini dans le format Rich Text de Qt)RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataViewDfinir la famille du composant - lier ce composant d'autres composants de la mme famille?Set the part's family--what other parts is this part related toPEMetadataViewHDfinir les proprites du composantSet the part's propertiesPEMetadataViewDDfinir les mots-cls du composantSet the part's tagsPEMetadataView:Dfinir le titre du composantSet the part's titlePEMetadataViewzDfinir l'URL du composant si il est dcrit dans une page Web3Set the part's url if it is described on a web pagePEMetadataViewDfinir la variante de la pice -La rendre unique par rapport aux autres composants de la mme familleTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewMots-clsTagsPEMetadataViewvC'est ici que vous modifiez les mtadonnes du composant...4This is where you edit the metadata for the part ...PEMetadataView TitreTitlePEMetadataViewVarianteVariantPEMetadataViewhauteur :height: PESvgViewlargeur :width: PESvgViewf<font color='black'>Activer le faire glisser</font>+Dragging enabled PEToolViewl<font color='black'>Dsactiver le faire glisser</font>+Dragging disabled PEToolViewCentrerCenter PEToolViewConnecteur %1 Connector %1 PEToolView`Connexions (case coche = graphique slectionn);Connector List (a checkmark means the graphic was selected) PEToolViewCommandes de rglage du point terminal pour un connecteur. Le point terminal est l'endroit o un fil se fixe sur le connecteur. Vous pouvez galement faire glisser le pointeur en forme de croix sur le connecteur actuelControls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector PEToolView(Glissement dsactivDragging disabled PEToolViewTModifier la coordonne x du point terminal/Modifies the x-coordinate of the terminal point PEToolViewTModifier la coordonne y du point terminal/Modifies the y-coordinate of the terminal point PEToolView,Slection du graphiqueSelect graphic PEToolView>Dfinir les connexions internesSet Internal Connections PEToolViewDfinir cette option pour modifier les connexions internes lors du tirage des fils?Set this checkbox to edit internal connections by drawing wires PEToolView`Dfinit le point terminal du connecteur pour %1.*Sets the connector's terminal point to %1. PEToolViewUtilisez l'emplacement du curseur et la molette de la souris pour naviguer dans l'lment SVG auquel vous voulez attribuer le connecteur actuel, puis dplacez la souris vers le bas pour le slectionner.Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. PEToolViewOW PEToolViewcentrercenter PEToolViewEsteast PEToolViewNordnorth PEToolViewSudsouth PEToolView Ouestwest PEToolViewcentrercenterPadconnecter  connect toPad ouesteastPadnorthPadcontourshapePadsudsouthPadestwestPadFModifier les tiquettes des brochesEdit Pin Labels PaletteItem Diamtre du trou Hole Diameter PaletteItemjInadquation de l'tiquette. Rien n'a t enregistr.#Label mismatch. Nothing was saved. PaletteItem*Epaisseur de l'anneauRing Thickness PaletteItemImpossible de procder; les connecteurs du composant n'ont pas d'IDs standard.;Unable to proceed; part connectors do no have standard IDs. PaletteItem|Impossible de procder, incapable de trouver la vue du dessus.1Unable to proceed; unable to find top level view. PaletteItem$Paramtres avancsadvanced settings PaletteItemTaille du trou hole size PaletteItemdansin PaletteItem(Afficher les valeursDisplay Values PartLabel@Afficher le texte de l'tiquetteDisplay the text of the label PartLabelPAfficher les valeurs de la proprits %1 Display the value of property %1 PartLabel EditerEdit PartLabel@Modifier le texte de l'tiquetteEdit label text PartLabel2Retourner horizontalementFlip Horizontal PartLabel.Retourner verticalement Flip Vertical PartLabelJRetourner l'tiquette horizontalementFlip label horizontally PartLabelFRetourner l'tiquette verticalementFlip label vertically PartLabel$Retourner/Rotation Flip/Rotate PartLabel&Taille de la police Font Size PartLabelMasquerHide PartLabel@Masquer l'tiquette du composantHide part label PartLabel(Texte de l'tiquette Label text PartLabel,Texte de l'tiquette : Label text: PartLabel GrandLarge PartLabel MoyenMedium PartLabelVFaire pivoter de 90 vers la droite {135?}Rotate 135� Clockwise PartLabelXFaire pivoter de 135 vers la gauche {135?}Rotate 135� Counter Clockwise PartLabel:Faire pivoter de 180 {180?} Rotate 180� PartLabelTFaire pivoter de 90 vers la droite {45?}Rotate 45� Clockwise PartLabelVFaire pivoter de 135 vers la gauche {45?}Rotate 45� Counter Clockwise PartLabelTFaire pivoter de 90 vers la droite {90?}Rotate 90� Clockwise PartLabelVFaire pivoter de 135 vers la gauche {90?}Rotate 90� Counter Clockwise PartLabelrPivoter la slection actuelle de 90 degrs vers la droite5Rotate current selection 90 degrees counter clockwise PartLabelfFaire pivoter le label de 135 degrs vers la droite)Rotate the label by 135 degrees clockwise PartLabelfFaire pivoter le label de 135 degrs vers la gauche1Rotate the label by 135 degrees counter clockwise PartLabelHFaire pivoter le label de 180 degrsRotate the label by 180 degrees PartLabeldFaire pivoter le label de 45 degrs vers la droite(Rotate the label by 45 degrees clockwise PartLabeldFaire pivoter le label de 45 degrs vers la gauche0Rotate the label by 45 degrees counter clockwise PartLabeljFaire pivoter l'tiquette de 90 degrs vers la droite(Rotate the label by 90 degrees clockwise PartLabel8Taille de la police en grandSet font size to large PartLabel8Taille de la police en moyenSet font size to medium PartLabel8Taille de la police en petitSet font size to small PartLabel@Taille de la police en minusculeSet font size to tiny PartLabel6Dfinir l'tiquette pour %1Set label for %1 PartLabel PetitSmall PartLabelMinusculeTiny PartLabel8Ajouter au jeu de composants Add to binPartsBinPaletteWidgetAnnulerCancelPartsBinPaletteWidgetHImpossible de trouver le fichier %1.Cannot find file %1.PartsBinPaletteWidgetLImpossible de lire le fichier %1 : %2.Cannot read file %1: %2.PartsBinPaletteWidgetBModifier la couleur de l'icne...Change icon color...PartsBinPaletteWidget^Modifier la couleur de l'icne pour ce magasin.*Change the color of the icon for this bin.PartsBinPaletteWidgetVoulez-vous vraiment ajouter le composant slectionn au jeu de composants ?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetVoullez-vous sauvegarder les modifications effectues dans "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidget$Ne pas enregistrer Don't SavePartsBinPaletteWidget>Jeu de composant Fritzing (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetChargement... Loading...PartsBinPaletteWidgetEnregistrerSavePartsBinPaletteWidget Sauvegarder "%1" Save bin "%1"PartsBinPaletteWidgetPSlectionner la couleur pour cette icneSelect a color for this iconPartsBinPaletteWidget2Veuillez spcifier un nomSpecify a file namePartsBinPaletteWidget4Jeu de composants sans nom Untitled BinPartsBinPaletteWidgetzVos changements seront perdus si vous ne les enregistrez pas.1Your changes will be lost if you don't save them.PartsBinPaletteWidget$Chargement de '%1'loading bin '%1'PartsBinPaletteWidgetAnnulerCancel Perfboard*Alerte de performancePerformance Warning Perfboard|Les performances du logiciel avec des Cartes bandes de plus de 2000 trous peuvent tres rduites. Etes-vous sr? Remarque : cet avertissement ne sera pas rpt au cours de cette session.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard6Dfinir une nouvelle taille Set new size Perfboardcolonnescolumns Perfboard lignesrows Perfboard:Dfinir la taille de la carteset board size Perfboard taillesize Perfboardf<p><h2>Modification d'tiquettes de broche</h2></p>

    Pin Label Editor

    PinLabelDialog<p>Cliquez sur une tiquette ct d'un numro d'identification pour renommer cette broche.<

    Click on a label next to a pin number to rename that pin.PinLabelDialogAnnulerCancelPinLabelDialogRefaireRedoPinLabelDialogEnregistrerSavePinLabelDialogAnnulerUndoPinLabelDialogVous pouvez utiliser la touche de tabulation pour vous dplacer parmi les tiquettes.<p/>@You can use the tab key to move through the labels in order.

    PinLabelDialog%1 (Modifier)%1 (click to change...) PrefsDialog,Sauvegarde automatiqueAutosave PrefsDialogFSauvegarde automatique toutes les :Autosave every: PrefsDialogAnnulerCancel PrefsDialogNModifier le comportement de la rouletteChange Wheel Behavior PrefsDialog8Rinitialiser les paramtresClear Settings PrefsDialogCouleursColors PrefsDialogCommandesCommand PrefsDialogZMettre en surbrillance les lments connectsConnected Highlight PrefsDialogControl PrefsDialog@Cbles courbes plutt que droitsCurvy vs. straight wires PrefsDialog0Cbles et pattes courbesCurvy wires and legs PrefsDialogGnralGeneral PrefsDialog LangueLanguage PrefsDialogPComportement de la roulette de la sourisMouse Wheel Behavior PrefsDialog`Slectionnez un programmeur (excutable) pour %1'Select a programmer (executable) for %1 PrefsDialogCette case dfinit le comportement par dfaut. Vous pouvez revenir au comportement non dfini par dfaut en maintenant enfonce la touche Ctrl (Mac : touche Commande) lorsque vous faites glisser.This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialogbMettre en surbrillance les lments non connectsUnconnected Highlight PrefsDialog:Lorsque le bouton de la souris est enfonc et que vous faites glisser un cble ou la patte d'un composant (par opposition un connecteur ou un point de connexion/articulation) voulez-vous modifier la courbure du fil (ou de la patte) ou faire apparatre un nouveau point de connexion ?When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialogaucune touche enfonce = dfilement Majuscule permute l'axe de dfilement Alt ou la touche %1 = zoomFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialogtouche vers le bas = zoom Alt ou la touche %1=dfilement Majuscule permute l'axe de dfilementFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialog5Are you sure you want to remove "%1" from the sketch? ProgramTab PlaqueBoard ProgramTabzFritzing est incapable de trouver "%1", veuillez le localiser1Fritzing is unable to find '%1', please locate it ProgramTabNouveauNew ProgramTabSupprimer "%1"? Remove "%1"? ProgramTabEnregistrerSave ProgramTab\Slectionnez un fichier de programme chargerSelect a program file to load ProgramTabtBien qu'il soit possible de lire et de modifier les fichiers de programmation %1, Fritzing n'est pas encore utilisable pour compiler ou tlverser ces programmes vers un microcontrleur.While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. ProgramTab&Copier&Copy ProgramWindow&Couper&Cut ProgramWindow&dition&Edit ProgramWindow&Coller&Paste ProgramWindow&Prfrences...&Preferences... ProgramWindow$&Tout slectionner &Select All ProgramWindow&Vue&View ProgramWindow PlaqueBoard ProgramWindowFentre de code Code Window ProgramWindow(Fentre de code - %1Code Window - %1 ProgramWindow&Copier la slectionCopy selection ProgramWindow&Couper la slection Cut selection ProgramWindowLe fichier "%1" a t restaur partir du fichier fzz;. Enregistrer une copie locale pour travailler avec un diteur externe.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindowLe fichier "%1" a t restaure partir du fichier fzz;. La copie locale n'a pas t trouv.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindowDCopier le contenu du presse-papierPaste clipboard contents ProgramWindowRtablirRedo ProgramWindow@Slectionner l'ensemble du texteSelect all text ProgramWindow$Montrer " propos" Show the application's about box ProgramWindowAnnulerUndo ProgramWindow%1%1 LayerQObjectPLe calque exporter %1 (case2) est vide."%1 layer export is empty (case 2).QObjectBLe calque exporter %1 est vide.%1 layer export is empty.QObject`Le calque %1 : n'est pas sauvegardable dans "%2" %1 layer: unable to save to '%2'QObjectNEchec de l'exportation du masque %1 (2)%1 mask export failure (2)QObjectl%1 fils dplacs de leur position enregistre dans %2./%1 wires moved from their saved position in %2.QObjectp%2 ... %1 cbles dplacs de leur position de sauvegarde/%2 ... %1 wires moved from their saved positionQObject(<b>Description :</b>Description:QObject<b>Nom :</b> Name:QObject<b>type :</b> type:QObject0<font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Universit des sciences appliques de Potsdam (FH Potsdam)</font>t© 2007-%1 Fachhochschule PotsdamQObject0Paramtres d'autoroutageAutorouter SettingsQObjectBasiqueBasicQObject PlaqueBoardQObjectPlatine d'essai BreadboardQObject2Vue de la platine d'essaiBreadboard ViewQObjectAvancer Bring forwardQObject0Disposer au premier planBring to frontQObjectAutoroutage impossible : aucune carte (ou carte multiples) trouve5Cannot autoroute: no board (or multiple boards) foundQObjectLImpossible de lire le fichier %1 : %2.Cannot read file %1: %2.QObjecttImpossible d'crire dans le fichier temporaire : %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject8Modifier les pattes de %1,%2Change leg of %1,%2QObjectTVrifier la disponibilit d'un mise jourCheck for updatesQObject8Rinitialiser les paramtresClear SettingsQObjectRinitialiser tous les paramtres sauvegarder et fermer cette boite de dialogue immdiatement.;Clear all saved settings and close this dialog immediately.QObjectLCouleur de surbrillance des connexionsConnected highlight colorQObjectConnexion ConnectionQObjectConvertir la connexion traversante en point de connexion/articulationConvert Via to BendpointQObjectDConvertir en connexion traversanteConvert to ViaQObject0Cuivre - face Infrieure Copper BottomQObjectPCuivrer les pistes de la face infrieureCopper Bottom TraceQObjectNRemplissage en cuivre (face infrieure)Copper Fill BottomQObjectHRemplissage cuivre (face suprieure)Copper Fill TopQObject0Cuivre - face suprieure Copper TopQObject4Cuivrer la face suprieureCopper Top TraceQObject&Copie du fichier %1Copying file %1QObject Modifier le lien Edit linkQObjectHEchec de lecture du fichier %1 : %2.Error reading file %1: %2.QObjectdLe fichier%1 existe dj : il ne sera pas remplac/File %1 already exists: it won't be overwrittenQObject0Chargement du fichier...File Progress...QObject GrilleFrameQObjectvFritzing ne parvient pas charger le magasin de composants"Fritzing cannot load the parts binQObjectFritzing est incapable de traiter les dcoupes dans cette forme de circuit imprim personnalise.DFritzing is unable to process the cutouts in this custom PCB shape. QObject8Fritzing ncessite que vous faire les dcoupes l'aide d'une forme de 'soustraction' ou par 'diffrentes' opration de graphiques vectoriels votre diteur.}Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.QObjecthditeur de remplissage des points (graines) de masseGround Fill Seed EditorQObject IcneIconQObject(Affichage des icnes Icon ViewQObject EntreInputQObject$Connexions interneInternal ConnectionsQObjectBSupprimer un point d'articulation Join WireQObjectMicrocontrleurMicrocontrollerQObjectTAucune connexion (sur le circuit imprim).%No connections (on the PCB) to route.QObject4Aucune connexion router.No connections to route.QObject.Aucun composant trouv.No parts found.QObject Oups!Oops!QObject AutresOtherQObject SortieOutputQObject,Vue du circuit imprimPCB ViewQObjectbErreur de syntaxe (1) ligne %1, colonne %2 :%3 %4,Parse error (1) at line %1, column %2: %3 %4QObjectdErreur de syntaxe (2) ligne %1, colonne %2 : %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectComposantPartQObject"Composant %1 "%2" Part %1 '%2'QObject*Images des composants Part ImageQObject.tiquettes de composant Part LabelsQObject`Composant dj prsent dans le jeu de composantsPart already in binQObjectComposantsPartsQObjectBDossier de composants non trouv.Parts folder not found.QObjectFEditeur d'tiquette des connecteursPin Label EditorQObjectVeuillez noter que le changement de langue ne prendra effet qu'au redmarrage de Fritzing.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectAllimentationPowerQObjectPrfrences PreferencesQObjectfil volantRatsnestQObjectCable volantRatsnest wiresQObject RglesRulersQObjectVue schmatiqueSchematic ViewQObjectSlectionner %1 Select %1QObject(Tout slectionner %1 Select all %1QObject^Slectionner toutes les pistes non autoroutes #Select all 'Don't autoroute' tracesQObjectXSlectionner toutes les pistes autoroutablesSelect all autorouteable tracesQObjectNSlectionner les composants verrouillsSelect locked partsQObjectJSlectionner les composants obsoltesSelect outdated partsQObjectReculer Send backwardQObjectCapteursSensorsQObject:Dfinir la taile de la grille Set Grid SizeQObjectRChoisir la graine de remplissage de masseSet Ground Fill SeedQObject.Positionner tout dans : Set all to:QObjectHDfinir la description du connecteur Set the connectors's descriptionQObjectDParamtre du titre des connecteursSet the connectors's titleQObject CartesShieldsQObjectBSrigraphie de la face infrieureSilkscreen BottomQObjectxSrigraphie de la face infrieure (tiquettes de composants)Silkscreen Bottom (Part Labels)QObjectBSrigraphie de la face suprieureSilkscreen TopQObject|Srigraphie de la face suprieure (Etiquettess des composants)Silkscreen Top (Part Labels)QObjectDsol, Fritzing ne peut pas (encore) grer simultanment des broches et des pads (dans%1 dans%2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectDsol, Fritzing ne peut pas (encore) grer simultanment des broches et des pads (dans%1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectVDsol, ne peut pas grer le pad de type %1Sorry, can't handle pad type %1QObjectnDsol, nous avons un problme dans la mise jour des proprits. Fritzing va continuer fonctionner, mais vous n'aurez pas la possibilit de changer les proprits des composants. }Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectRAjouter un point d'articulation/connexion Split WireQObject TexteTextQObjecttLe fichier %1 n'est pas un fichier venant de Fritzing (2).'The file %1 is not a Fritzing file (2).QObjecttLe fichier %1 n'est pas un fichier venant de Fritzing (3).'The file %1 is not a Fritzing file (3).QObject`Le fichier %1 n'est pas un fichier Fritzing (4).'The file %1 is not a Fritzing file (4).QObjectLe fichier "%1" ne peut pas tre modifi; Veuillez utiliser un autre nom.paramtres de perage manquantsdrill missing paramsQObjectPL'offset du perage n'est pas implmentdrill offset not implementedQObject<Le fichier de percage est videexported drill file is emptyQObjectRLe calque de masquage export %1 est videexported mask layer %1 is emptyQObjectTle calque de masquage de l'export est vide"exported paste mask layer is emptyQObjectHEchec de convertion svg 1 : %1 %2 %3%failure in svg conversion 1: %1 %2 %3QObject@Echec de convertion 2 : %1 %2 %3%failure in svg conversion 2: %1 %2 %3QObjectfichiersfilesQObject>Empreinte %1 introuvable dans%2footprint %1 not found in %2QObject"Vue en mode icne icon viewQObjectdansinQObject:Echec d'exportation du masquemask export failureQObject(calque(s) de masque,mask layer(s), QObjectbLes trous non circulaires ne sont pas implments"non-circular holes not implementedQObjectZLes trous non cuivrs ne sont pas implments non-copper holes not implementedQObject"L'aperu est videoutline is emptyQObject4attributs de Pad manquantspad missing attributesQObject.perage de pad manquantpad missing drillQObject2position de pad manquantepad missing positionQObject,forme de pad manquantepad missing shapeQObject6paramtres de pad manquantspad shape missing paramsQObjectVla taille de la forme du pad est incorrectepad shape size is invalidQObject&analyse chec en %1parse failure in %1QObject<calque(s) du masque de soudurepaste mask layer(s), QObjectcircuit imprimpcbQObject,vue du circuit imprimpcb viewQObject@Paramtres de position manquantsposition missing paramsQObject schmaschemQObjectjLe schma %1 se termine de faon inattendue (1) en %2(schematic %1 unexpectedly ends (1) in %2QObjecthLe schma %1 se termine de faon inattendue (2) en%2(schematic %1 unexpectedly ends (2) in %2QObjectjLe schma %1 se termine de faon inattendue (3) en %2(schematic %1 unexpectedly ends (3) in %2QObjecthLe schma du composant %1 n'a pas t trouv dans %2!schematic part %1 not found in %2QObjectvue schmatiqueschematic viewQObject<forme en delta pas implmenteshape delta not implementedQObjectPchec de l'exportation de la srigraphiesilk export failureQObjectdL'exportation du calque de srigraphie %1 est videsilk layer %1 export is emptyQObject6Calque(s) de la srigraphiesilkscreen layer(s), QObject:le calque de contour de cartethe board outline layer, QObjectZles pads trapzodaux ne sont pas implments trapezoidal pads not implementedQObject^Impossible de copier le fichier "%1" dans "%2".!unable to copy file '%1' to '%2'.QObjectPincapables de traiter la forme de pad %1unable to handle pad shape %1QObject,impossible d'ouvrir %1unable to open %1QObject0impossible d'analyser %1unable to parse %1QObject2Fin de fichier inattendueunexpected end of fileQObject~Fin de fichier inattendue dans l'empreinte %1 dans le fichier%21unexpected end of file in footprint %1 in file %2QObjectVFormat inattendu (1) dans %1 partir de %2#unexpected format (1) in %1 from %2QObjectExemplairesCopies QuoteDialogPour plus d'informations sur la tarification voir <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>.rFor more information on pricing see http://fab.fritzing.org/pricing. QuoteDialog$Devis Fritzing FabFritzing Fab Quote QuoteDialog`Commandez votre circuit imprim sur Fritzing Fab Order your PCB from Fritzing Fab QuoteDialogVeuillez noter que les tarifs ne comprennent pas les frais de transport, <br />6Please note that prices do not include shipping,
     QuoteDialogPrixPrice QuoteDialog Prix par cartePrice per board QuoteDialogNProfitez de notre remise quantitative :(Take advantage of our quantity discount: QuoteDialogLa surface totale du circuit imprim %n dans cette esquisse est deLa surface totale des circuits imprims %n dans cette esquisse est de1The total area of the %n PCB(s) in this sketch is QuoteDialogUtilisez Fritzing Fab pour produire un circuit imprim partir de votre esquisse. <br />9Use Fritzing Fab to produce a PCB from your sketch.
     QuoteDialog(Visitez Fritzing FabVisit Fritzing Fab QuoteDialogxde possibles taxes ou frais de douane supplmentaires.<br />5possible additional taxes, or the checking fee.
     QuoteDialog&Ignorer&IgnoreRecoveryDialog&restaurer&RecoverRecoveryDialog<p><b>Fritzing peut-tre cras, mais quelques-unes des modifications apportes aux fichiers suivants peuvent tre rcuprs.</b></p><p> La date et l'heure auxquelles chaque fichier a t sauvegard est affich. Si le fichier a t enregistr, cette date heure est galement inscrite pour la comparaison.</p><p> Les fichiers originaux sont toujours sur votre disque, s'ils ont dj t enregistres. Vous pouvez choisir si vous souhaitez remplacer le fichier d'origine aprs avoir charger son fichier de rcupration; Slectionnez les fichiers que vous souhaitez rcuprer dans la liste ci-dessous.</b><b>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialogFichierFileRecoveryDialog&Dernire sauvegarde Last backupRecoveryDialog,Dernier enregistrement Last savedRecoveryDialog,fichier non sauvegardfile not savedRecoveryDialogRsistanceResistorResistorVous pouvez soit entrer une valeur de rsistance, ou la slectionner dans la liste droulante. Format nnn.dP o P est l'un des 'umkMG 'tYou can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'Resistorrsistance resistanceResistorLivre (17x11)Ledger (17x11)ResizableBoardLgal (8.5x14)Legal (8.5x14)ResizableBoardLettre (8.5x11)Letter (8.5x11)ResizableBoardRevenirRevertResizableBoardTablod (11x17)Tabloid (11x17)ResizableBoardPersonnaliscustomResizableBoardHauteur (mm) height(mm)ResizableBoardHauteur : %1 mm height: %1mmResizableBoard2Conserver les proportionskeep aspect ratioResizableBoard DessinshapeResizableBoard TaillesizeResizableBoardLargeur(mm) width(mm)ResizableBoardLargeur : %1 mm width: %1mmResizableBoardlargeurwidthRulerNom du fichierFilenameSchematicFrame ProjetProjectSchematicFrameRvRevSchematicFrameFeuilleSheetSchematicFramedeofSchematicFrame formeshapeSchematicFramefeuillesheetSchematicFrame:Modifier l'tiquette %1 en %2Change label from %1 to %2SchematicSketchWidget<Modifier la tension de %1 %2Change voltage from %1 to %2SchematicSketchWidgetAnnulerCancelSetColorDialog<Faire %1 la couleur par dfautMake this the default %1 colorSetColorDialog%1 Remarque : vous pouvez galement dclencher cet affichage en positionnant la souris sur le texte d'tat de routage dans la barre d'tat.i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2 lments %1 %2 items SketchWidget"%1 tiquette '%2' %1 label '%2' SketchWidgetAjouter %1Add %1 SketchWidget.Ajouter %1 composant(s) Add %1 parts SketchWidgetChangerChange SketchWidgetFPasser la couleur de %1 du %2 au %3Change %1 color from %2 to %3 SketchWidgetChange %1 from %2 to %3 SketchWidget<Changer l'tiquette %1 en '%2'Change %1 label to '%2' SketchWidgetDChanger la largeur %1 de %2 en %3 Change %1 width from %2 to %3 SketchWidget@Modifier la rsistance %1 par %2Change Resistance from %1 to %2 SketchWidgetJChanger la couleur de %1 cbles en %2Change color of %1 wires to %2 SketchWidget6Modifier l'image de%1 en %2Change image from %1 to %2 SketchWidgetfModifier le point d'articulation de la patte en %1.Change leg bendpoint for %1. SketchWidgetJModifier la valeur de la patte de %1.Change leg curvature for %1. SketchWidgetNAppliquer une largeur %1 cbles de %2Change width of %1 wires to %2 SketchWidgetConnecterConnect SketchWidget*Crer et connecter %1Create and connect %1 SketchWidget6Crer et connecter un cbleCreate and connect wire SketchWidget8Crer les fils dans RatsnestCreate wire from Ratsnest SketchWidget*Supprimer le ratsnestDelete ratsnest SketchWidgetDslectionnerDeselect SketchWidget&Tous dselectionner Deselect all SketchWidgetDconnecter Disconnect SketchWidget>Dconncter tous les fils de %1Disconnect all wires from %1 SketchWidgetPDconncter tous les fils de %1 lments"Disconnect all wires from %1 items SketchWidgetDouble-clique Double-click SketchWidgetfDouble cliquez pour supprimer ce point de connexion&Double-click to delete this bend point SketchWidgetBFaites glisser ou double-cliquez Drag or double-click SketchWidget*Transformation miroirFlip SketchWidget Inverser %2 (%1) Flip %2 (%1) SketchWidget Dplacer %2 (%1) Move %2 (%1) SketchWidget2Dplacer %2 lements (%1)Move %2 items (%1) SketchWidget2Dplacer l'tiquette '%1'Move label '%1' SketchWidget"Dplacer patte de Move leg of SketchWidget:Modifier le texte de la note Note text change SketchWidgetpLe composant '%1' n'a pas t trouv dans cette esquissePart '%1' not found in sketch SketchWidget:Redimensionner l'aide-mmoire Resize Note SketchWidget>Redimensionner la platine %1 %2Resize board to %1 %2 SketchWidgetHRedimentionner les rgles pour %1 %2Resize ruler to %1 %2 SketchWidgetRotationRotate SketchWidget*Faire pivoter %2 (%1)Rotate %2 (%1) SketchWidgetSlectionner %1 Select %1 SketchWidget0Slectionner %1 lementsSelect %1 items SketchWidget"Tout slectionner Select All SketchWidgetSlection Selection SketchWidgetHIl n'y a aucune connexion non route!There are no unrouted connections SketchWidget6Cela ressemble une tentative pour crer une piste travers plusieurs calques. Cela ne devrait pas se produire : veuillez contacter les dveloppeurs svp.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget,Connexions non routesUnrouted connections SketchWidgetRLes connexions non routes sont en jaune./Unrouted connections are highlighted in yellow. SketchWidget<modifier le label de la brochechange pin labels SketchWidget$chargement termin done loading SketchWidgetdans %1from %1 SketchWidgetFMasquer l'tiquette du composant %nPMasquer les tiquettes des composants %nhide %n part label(s) SketchWidget.composant en chargement loading part SketchWidgetNou alt-glisser pour dplacer le segmentor alt-drag to move the segment SketchWidgetJAfficher les %n label(s) du composantBAfficher le %n label du composantshow %n part label(s) SketchWidget %1to %1 SketchWidget pistetrace SketchWidgetfilwire SketchWidget`Le mcanisme de permutation est dsactiv pour :)The swapping mechanism is disabled for: SqliteReferenceModel.et %1 autres composantsand %1 other partsSqliteReferenceModel.et %1 autres propritsand %1 other propertiesSqliteReferenceModelcomposant '%1' avec id '%2'; peut-tre parce qu'll n'a pas de proprit "famille".Epart '%1' with id '%2'; possibly because it has no 'family' property.SqliteReferenceModelfproprit '%1' dans le composant '%2' avec id '%3'.(property '%1' in part '%2' with id '%3'.SqliteReferenceModel%1 %n bande%1 %n bandes%1 %n strip(s) Stripboardarrangement %1 %1 layout Stripboard CouperCut StripboardRestaurRestored Stripboardcolonnescolumns Stripboard lignesrows Stripboard(Etiquettes de rseau Net labelsSymbolPaletteItemZUne tiquette de rseau ne peut pas tre videNet labels cannot be blankSymbolPaletteItemtiquettelabelSymbolPaletteItemtensionvoltageSymbolPaletteItemHLa prsence d'un fil volant ("fil" trs fin) entre connexions dans une vue signifie que ces connexions sont d'une manire ou d'une autre relies dans une autre vue.A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. TipsAndTricksCrez toujours une piste en partant directement d'un connecteur, cela vous aidera viter les courts-circuits.PAlways lead a trace straight out of a pin. This helps to prevent short circuits. TipsAndTricksBUne icne dans le magasin de composants peut en ralit reprsenter de multiples composants relatifs. Ds lors, lorsque vous faites glisser une icne dans une esquisse, assurez-vous de regarder l'Inspecteur. L'Inspecteur affichera les choix accessibles pour modifier un composant ou le remplacer par un autre. Le jeu de composants sera aussi reprsent sous forme d'une petite "pile" et pas juste par une icne plate.gAn icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. TipsAndTricksAvant d'employer l'Editeur de Composants pour crer un nouveau composant, voyez si un circuit intgr gnrique, un composant-mystre ou une barrette de connecteurs ne peut convenir. Une fois que vous avez plac un de ces lments dans votre esquisse, vous pouvez modifier le nombre de broches, l'cart entre broches et d'autres proprits.Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. TipsAndTricks(Vous ne trouvez pas un composant ? Recherchez-le en cliquant sur l'icne en forme de loupe dans le Magasin de Composants et tapez quelques mots-clsmCan't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords TipsAndTricksJetez un coup d'Sil l'Aide de l'Editeur de Composants dans le menu <b>Aide</b>.7Check out Parts Editor Help under the Help Menu. TipsAndTricks0Cliquer sur l'indicateur de position de la souris dans la barre de statut (au bas de l'cran) pour faire basculer l'affichage des units en mm ou en px.pClick on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. TipsAndTricksNe sauvegardez pas vos fichiers de composants personnaliss dans le dossier d'installation Fritzing. Si vous mettez Fritzing jour, ces fichiers seront probablement supprims. De mme, les fichiers se trouvant dans le dossier d'installation de Fritzing ne seront pas sauvs dans les fichiers d'esquisse (.fzz), ce qui vous empchera de les partager.Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. TipsAndTricks2Trucs et astuces FritzingFritzing Tips and Tricks TipsAndTricksFritzing mmorise des fichiers pour les composants personnaliss, les composants gnrs, temporairement ou long terme dans un "dossier de stockage local". Sous Mac et Linux, il s'agit habituellement de ~/.config/Fritzing/. Sous Windows Vista et dans les versions ultrieures, il s'agit de quelque chose comme C:\Users\[user name]\AppData\Roaming\Fritzing\; sous Windows XP cela ressemble C:\Documents and Settings\[user name]\Application Data\Fritzing\.Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. TipsAndTricksLancez-vous en jetant un coup d'Sil aux exemples de circuits partir de Fichier > Ouvrir un Exemple.JGet a jump start by looking at the example circuits under File > Examples. TipsAndTricksxFaites raliser rapidement et facilement votre circuit imprim avec Fritzing Fab. Placez le pointeur de souris au dessus du bouton "Faire Fabriquer" pour afficher une estimation des cots.nHave your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. TipsAndTricksS'il manque dans Fritzing un composant spcifique et que vous ne voulez pas le crer par vous-mme, alors employez des barrettes (pinheaders) comme connecteurs et employez la grille pour les aligner.If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. TipsAndTricksSi vous ne pouvez trouver un composant dans le Magasin de Composants, le circuit intgr gnrique (Generic IC) est votre ami. Faites-le glisser dans votre esquisse, ensuite utilisez les widgets de l'Inspecteur pour choisir parmi 25 formats diffrents en montage traversant ou de surface ; modifiez les noms des broches ; et - pour les botiers DIL/DIP ou SIP - modifiez le nombre de broches. Vous pouvez aussi changer les noms des broches avec l'diteur de noms de broches (Pin Label editor)RIf you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor TipsAndTricks6Si vous avez des difficults slectionner un composant ou un (segment de) cble, essayez de slectionner le composant qui obstrue le passage et envoyez-le dans le fond : employez les fonctions Avancer et Reculer du menu Composants ou du menu contextuel (affich par un clic droit).If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). TipsAndTricksDans les vues de la platine d'essai et du circuit imprim, pour ajouter une courbe un cble ou une patte pliable, faites glisser tout en enfonant la touche Control (Mac : Command). Vous pouvez dcider si les cbles sont courbes par dfaut via les Prfrences.In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. TipsAndTricksDans la vue de la platine d'essai, pour faire glisser un composant dot de pattes pliables tout en prservant sa connexion la platine, maintenez la touche Alt (Linux : Meta) enfonce lorsque vous commencez le glissement.In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. TipsAndTricksFDans la vue de la platine d'essai, pour tirer un cble depuis l'extrmit d'une patte, effectuez le glissement en maintenant la touche Alt (Linux : Meta) enfonce.pIn Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. TipsAndTricksDans les vues schmatique ou du circuit imprim, si vous effectuez un glissement d'un point de connexion/articulation avec la touche Alt (Linux : Meta) enfonce, vous allez faire surgir un nouveau cble depuis ce point.In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. TipsAndTrickshDans l'Editeur de Composants, pour slectionner un lment graphique qui se trouve sous un autre, employez la roulette de la sousis tout en maintenant enfonce la touche majuscule.zIn the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. TipsAndTricksTracer les pistes horizontales d'un ct du circuit imprim et les pistes verticales de l'autre vous facilite la vie.hIt makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. TipsAndTricksCrez des pistes avec des angles ne dpassant pas 45 degrs afin de rduire le bruit.1Route traces in 45-degree angles to reduce noise. TipsAndTricksLes circuits imprims plus petits sont moins coteux que les plus grands. Economisez de l'espace et de l'argent.HSmaller PCBs are more affortable than larger ones. Save space and money. TipsAndTricksLa fentre Inspecteur - qui vous permet de modifier les proprits des composants - n'est active que pour les composants se trouvant dans une esquisse (pas pour les composants encore en magasin).The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). TipsAndTricksLes composants traversants peuvent tre placs de chaque ct du circuit imprim.;Through-hole parts can be traced from either side of a PCB. TipsAndTricks Trucs et astucesTips and Tricks TipsAndTricksPour ajouter un point de connexion/articulation dans un cble, faites un double-clic l'endroit souhait.sur le cble.HTo add a bendpoint to a wire, double-click where you want the bendpoint. TipsAndTricksPour modifier la largeur d'une piste, slectionnez une piste puis employez la combo-box <b>largeur</b> dans l'inspecteur. Vous pouvez utiliser le menu droulant ou simplement frapper un nombre au clavier (entre 8 et 128).To change trace width, select a trace then use the width combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). TipsAndTricks8Pour contraindre le dplacement d'un composant sur la verticale ou l'horizontale, maintenez enfonce la touche majuscule pendant que vous le faites glisser.dTo constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. TipsAndTricksPour crer une forme personnalise pour votre circuit imprim, importez un fichier SVG.:To create a custom shape for your PCB, import an SVG file. TipsAndTricksPour supprimer un point de connexion/articulation d'un cble, faites un double-clic dessus.3To delete a bendpoint from a wire, double-click it. TipsAndTricks*Pour afficher diffrentes proprits dans l'tiquette d'un composant, pour la faire tourner, ou changer sa typographie, faites un double-clic dessus.qTo display different properties in a part label, as well as rotate it, or change the font, right-click the label. TipsAndTricksxPour dplacer un segment de cble (une section de cble situe entre deux points de connexion/articulation), effectuez le dplacement avec la touche Alt (Linux : Meta) enfonce. Si vous maintenez aussi la touche majuscule enfonce, le segment de cble sera contraint sur un axe de dplacement horizontal ou vertical.To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. TipsAndTricksPour dplacer le canevas, maintenez la barre d'espacement enfonce et dplacez la souris.DTo drag the canvas, hold down the space bar and drag with the mouse. TipsAndTricksPour modifier l'tiquette d'un composant, faites un double-clic dessus, ou utilisez le widget d'encodage texte dans la fentre Inspecteur.\To edit a part label, double-click it, or use the text input widget in the inspector window. TipsAndTricksPour faire tourner librement un logo textuel ou un lment image dans la vue du circuit imprim maintenez la touche Alt (Linux : Meta) enfonce et effectuez la rotation libre de manire habituelle.rTo free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. TipsAndTricksPour faire tourner librement un composant dans les vues de la platine d'essai ou du circuit imprim, slectionnnez-le, ensuite faites passer le pointeur de la souris prs d'un de ses coins jusqu' ce que le curseur de rotation apparaisse. Enfoncez le bouton de la souris et ce coin suivra en tournant les dplacements de la souris.To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. TipsAndTricksZPour insrer une url cliquable dans un aide-mmoire, slectionnez du texte dans la note et tapez ctrl-l (Mac : command-l). (Il s'agit bien de la lettre "l" comme la premire lettre du mot "lien"). Pour modifier un lien existant, slectionnnez le texte du lien et employez ctrl-l (command-l) nouveau.To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. TipsAndTricksPour raliser un shield Arduino en deux temps trois mouvements, basculez de la forme de circuit imprim Rectangle la forme Arduino ShieldhTo make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino TipsAndTricks`Pour dplacer avec plus de prcision une slection de composants, employez les touches avec flches. En les combinant avec la touche majuscule, le dplacement est de 10 units.`To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. TipsAndTricksPour dplacer l'tiquette d'un composant sparment du composant lui-mme, slectionnez d'abord le composant - tant la composant que son tiquette seront mis en vidence. Une fois l'tiquette slectionne vous pouvez la dplacer sparment.To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. TipsAndTricksfPour voir tous les connecteurs branchs sur un connecteur donn, maintenez le bouton de souris enfonc au-dessus de ce connecteur - toutes les connexions seront mises en vidence.To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. TipsAndTricksPour faire apparatre ou disparatre un calque dans une vue, allez dans le menu Vue et choisissez un des calques. Vous pouvez aussi ouvrir la palette <b>Calques</b> depuis le menu <b> Fentre</b>.To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the Layers palette from the Window menu. TipsAndTricksUtilisez des composants Bloqueurs de Cuivre (Copper Fill Blocker) pour masquer les zones que vous voulez exclure du remplissage cuivre.MUse copper-blocker parts to mask out areas that you want free of copper fill. TipsAndTricksUtiliser majuscule + dplacement sur l'extrmit d'un cble ou sur un point de connexion/articulation pour contraindre son segment de cble un angle de 45 degrs (ou correspondant un multiple de 45). Si le segment de cble est connect d'autres segments de cble, le segment que vous dplacez va s'aligner de manire former des angles de 90 degrs avec les segments voisins.Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. TipsAndTricksLorsque vous exportez des images depuis Fritzing, vous pouvez choisir quels calques sont exports. Avant de choisir "Exporter...", allez dans le menu "Vue" et cachez les calques que vous ne voulez pas voir dans l'image.When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. TipsAndTricksVous pouvez inclure votre propre logo dans srigraphie du circuit imprim. Employez le composant "Logo" de la bibliothque de base et slectionnez votre propre fichier. Le format SVG est le meilleur.You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. TipsAndTricksTVous pouvez employer l'Editeur de Composants afin de trouver le fichier SVG correspondant l'image d'un composant pour une vue donne. Dans l'Editeur de Composants, cliquez sur l'onglet correspondant cette vue, ensuite employez la commande <b>Voir dans le dossier</b> dans le menu <b>Fichier</b>You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use Show in Folder under the File Menu TipsAndTricksconnexions connections TipsAndTricks4courbes et pattes pliablescurves and bendable legs TipsAndTricksexemplesexamples TipsAndTrickscalques et vueslayers and views TipsAndTricks<sauvegarde locale des fichierslocal file storage TipsAndTricks0dplacer et slectionnermoving and selection TipsAndTricksaides-mmoiresnotes TipsAndTricks2tiquettes des composants part labels TipsAndTrickscomposantsparts TipsAndTricks*diteur de composants parts editor TipsAndTricks<laboration du circuit imprim pcb layout TipsAndTricks<ralisation de circuit imprimpcb production TipsAndTricksTcbles et points de connexion/articulationwires and bendpoints TipsAndTricksSlectionnez dans le menu droulant, ou entrez une valeur comprise entre %1 et %2 AboutBox <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 -on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Fritzing is gemaakt door: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, André Knörig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Met speciale dank aan: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Dank aan Kurt Badelt en Miguel Solis voor de Spaanse vertaling, to Gianluca Urgese for the Italian translation, aan, Gianluca Urgese voor de Italiaanse vertaling, to Nuno Pessanha Santos for the Portuguese (European) translation, aan Nuno Pessanha Santos voor de Portugeese (Europese) vertaling, to Yuelin and Ninjia for the Chinese (Simplified) translation, aan Yuelin and Ninjia voor de Chinese (versimpelde) vertaling, to Hiroshi Suzuki for the Japanese translation, aan Hiroshi Suzuki voor de Japanse vertaling, to Robert Lee for the Chinese (Traditional) translation, aan Robert Lee voor de Chinese (traditionele) vertaling, to Vladimir Savinov for the Russian translation, aan Vladimir Savinov voor de Russische vertaling, Fritzing is made possible with funding from the Fritzing is mogelijk gemaakt door financiering van de MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, sponsoring van de Design Department of Bauhaus-University Weimar, afdeling van de Bauhaus Universiteit Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, een anonieme gever, Parallax, Picaxe, Sparkfun, Special thanks goes out as well to all the students Speciale dank gaat ook uit naar alle studenten and alpha testers who were brave enough to give en alpha testers, welke moedig genoeg waren om Fritzing a test spin. Fritzing te testen. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> to Josef Dustira for the Czech translation, aan Josef Dustira voor de Tsjechische vertaling, to Jinbuhm Kim for the Korean translation, aan, Jinbuhm Kim voor de Koreaanse vertaling, to Alexander Kaltsas for the Greek translation, aan Alexander Kaltsas voor de Griekse vertaling, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, aan Ĺubomír Duchoň voor de Slowaakse vertaling to Steven Noppe and Davy Uittenbogerd for the Dutch translation, aan Steven Noppe en Davy Uittenbogerd voor de Nederlandse vertaling, to Cihan Mete Bahad&#x0131;r for the Turkish translation, aan Cihan Mete Bahadır voor de Turkse vertaling, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. en aan Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira voor de Portugeese (Braziliaanse) vertaling. to Nikolay Stankov for the Bulgarian translation, aan Nikolay Stankov voor de Bulgaarse vertaling, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. en van elke aankoop van een Fritzing Starter Kit of een PCB van Fritzing Fab. to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, AutorouteProgressDialog Cancel Annuleren Stop Now Stop nu zoom and pan controls Zoomen en pannen Best So Far Beste tot nu toe Autorouter Routing canceled! Now cleaning up... Routing geannuleerd! Ruimt nu op... AutorouterSettingsDialog Production type Productietype homebrew Hobbyist professional Professioneel custom Aangepast Trace width Spoor breedte Cancel Annuleren OK OK Keepout Veiligheids afstand <b>Keepout</b> is the minimum distance between copper elements on different nets. <b>Veiligheids afstand</b> is de minimale afstand tussen banen verschillende koper netten. A keepout of 0.01 inch (0.254 mm) is a good default. Een veiligheids afstand van 0.01 inch (0.254 mm) is een goede standaard. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Noot: Hoe kleiner de veiligheidsafstand, hoe langzamer de DRC en Autorouter zullen zijn. BinManager Parts Onderdelen BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Kon de koffer '%1' niet als vuil zetten New bin (%1) Nieuwe koffer (%1) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing Koffer Bestanden (*%1 *%2);;Fritzing Koffer (*%1);;Fritzing Uitwisselbare Koffer (*%2) Cannot set a NULL bin as the current one Kan geen NULL koffer instellen als de huidige BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Kon de koffer '%1' niet als vuil zetten Select a Fritzing Parts Bin file to open Selecteer een Fritzing Onderdeel Koffer bestand om te openen Bin Koffer New Bin... Nieuwe Koffer... Create a new parts bin Maak een nieuwe onderdeel koffer aan Close Bin Sluit Koffer Close parts bin Sluit onderdeel koffer Delete Bin Verwijder Koffer Delete parts bin Verwijder onderdeel koffer Save Bin Bewaar Koffer Save parts bin Bewaar onderdeel koffer Save Bin As... Bewaar Koffer Als... Save parts bin as... Bewaar onderdeel koffer als... Export Bin... Exporteer Koffer... Save parts bin in compressed format... Bewaar onderdeel koffer in gecomprimeerd formaat... Rename Bin... Hernoem Koffer... Rename parts bin... Hernoem onderdeel koffer... Show Bin in List View Geef Koffer weer als Lijst Weergave Display parts as a list Onderdelen weergeven als een lijst Show Bin in Icon View Toon Koffer als Icoon Weergave Display parts as icons Onderdelen weergeven als Iconen Export Part... Exporteer Onderdeel... Remove Part Verwijder Onderdeel Delete bin Verwijder koffer Do you really want to delete bin '%1'? This action cannot be undone. Weet u zeker dat u koffer '%1' wilt verwijderen? Dit kan niet ongedaan worden gemaakt. Read-only bin Alleen-Lezen koffer This bin cannot be renamed. Deze koffer kan niet hernoemd worden. Rename bin Hernoem koffer Please choose a name for the bin: Kies a.u.b. een naam voor de koffer: Remove from bin Verwijder uit de koffer Searching... Zoeken... Import... Importeer... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Laad een Fritzing onderdeel (.fzpz) of een Fritzing onderdeel koffer (.fzb, .fzbz) Select a Fritzing File to Open Selecteer een Fritzing Bestand om te Openen Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bestanden (*%1 *%2 *%3);;Fritzing Onderdeel (*%1);;Fritzing Koffer (*%2);;Fritzing Deelbare Koffer (*%3) Edit Part (new parts editor)... Wijzig Onderdeel (Nieuwe Onderdeel Bewerker)... Find Part in Sketch Vind Onderdeel in Sketch Remove from Bin Verwijder uit de koffer Unable to remove part '%1'--it is in use in a sketch Niet mogelijk om onderdeel '%1' te verwijderen--het is momenteel in gebruik in een sketch Do you really want to remove '%1' from the bin? This operation cannot be undone. Weet u zeker dat u '%1' wilt verwijderen uit de koffer? Dit kan niet ongedaan worden gemaakt. Copy to Sketch Kopieer naar Sketch Copy all the parts in the bin to a sketch Kopieer alle onderdelen in de koffer naar een sketch Copy all to Sketch Kopieer alles naar Sketch Copy all loaded parts to the sketch Kopieer alle geladen onderdelen naar de sketch Board one layer (single-sided) Eén laags (Enkel zijdig) two layers (double-sided) Twee lagen (Dubbel zijdig) Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Kijk even naar het circle_pcb.svg bestand in je Fritzing installatiefolder onder parts/svg/core/pcb/. image file afbeeldings bestand load image file Laad afbeelding Images Afbeeldingen Select an image file to load Selecteer een afbeelding om te laden due to an xml problem: %1 line:%2 column:%3 veroorzaakt door een xml probleem: %1 regel:%2 kolom:%3 because the xml is not correctly formatted omdat de xml niet juist geformatteerd is the <board> element contains no shape elements het <board> element bevat geen vorm elementen because there are multiple <board> layers omdat er meerdere <board> lagen zijn because there are multiple <silkscreen> layers omdat er meerdere <silkscreen> lagen zijn because there is no <board> layer omdat er geen <board> laag is the svg contains no shape elements de SVG bevat geen vorm elementen but the pcb itself will have no silkscreen layer maar de pcb zelf zal geen silkscreen laag hebben the svg doesn't fit the custom board format de SVG past niet op het standaard bord formaat Unable to load Niet mogelijk om te laden Unable to load image from %1 %2 Niet mogelijk om de afbeelding te laden van %1 %2 Can load, but Kan laden, maar The image from %1 can be loaded, but %2 Use the file? De afbeelding van %1 kan geladen worden, maar %2 Wil je het bestand gebruiken? A custom board svg typically has one or two silkscreen layers and one board layer. Een aangepast bord svg heeft normaal gesproken een of twee silkscreen lagen en een bordlaag. because there are multiple <silkscreen0> layers omdat er meerdere <silkscreen0> lagen zijn <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> <b>De aangepaste vorm is geladen en zal snel in beeld komen.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Voordat je de PCB gaat produceren, raden we je aan om de aangepaste vorm van het bord te testen. Ga naar Bestand > Exporteer >voor Productie > Extended Gerber. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> Controleer het contour bestand met een Gerber-Viewer programma om er zeker van te zijn dat de vorm van de PCB juist is <br/><br/> The rest of this message concerns 'cutouts'. De rest van deze melding gaat over 'uitsnedes'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> Dit zijn cirkelvormige of onregelmatig gevormde gaten, welke optioneel toegevoegd kunnen worden aan een aangepaste bord vorm. <br/><br/> <b>The custom shape has no cutouts.</b> <b>De aangepaste vorm bevat geen uitsnedes.</b> <b>The custom shape has %n cutouts.</b> <b>De aangepaste vorm heeft %n uitsnede.</b> <b>De aangepaste vorm heeft %n uitsnedes.</b> <br/>However, the cutouts may not be formatted correctly. <br/>Het kan zijn dat de uitsnedes niet het juiste formaat hebben. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, <br/><br/>Als je aangepaste vorm uitsnedes zou moeten hebben en je krijgt niet het gewenste resultaat, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. is dat omdat Fritzing verlangt dat je de uitsnedes maakt door middel van een vorm via de 'substractie' of 'verschil' uitvoer binnen je vector programma. BoardLogoItem shape vorm BreadboardLogoItem color kleur Set text color Stel tekst kleur in Select text color Selecteer tekst kleur Capacitor Select from the dropdown, or type in a %1 value Selecteer uit het dropdown menu of typ een %1 waarde ConnectorItem Add bendpoint Voeg buigpunt toe Remove bendpoint Verwijder buigpunt Straighten curve Maak curve recht ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools Gereedschappen &About &Over Fritzing About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit &Afsluiten Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected Critical Error About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. DRC DRC was cancelled. DRC is geannuleerd. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Je sketch is klaar voor productie: Er zijn geen banen of connectoren die elkaar overlappen of te dicht bij elkaar liggen. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. De met rood gemarkeerde gebieden op het bord, zijn banen en/of aansluitingen die te dicht bij elkaar liggen, of elkaar overlappen. Reposition them and run the DRC again to find more problems Herpositioneer ze en start de DRC nogmaals om andere problemen te vinden Fritzing error: unable to render board svg. Fritzing fout: Kan bord SVG niet renderen. No traces or connectors to check Geen banen of connectors om te controleren Unexpected SVG rendering failure--contact fritzing.org Onverwachtte SVG render fout--Neem contact op met Fritzing.org Fritzing Fritzing %1 is overlapping (%2 layer) %1 overlapt (%2 laag) Too close to a border (%1 layer) Te dicht bij een rand (%1 layer) A hole in %1 may lie outside the border of the board and would be clipped. Een gat in %1 ligt waarschijnlijk te dicht aan de rand van het bord en zal worden afgeknipt. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results DRC Resultaten Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Noot: de items in de lijst en de rood gemarkeerde gebieden zullen niet updaten als je je sketch bewerkt--Je moet de DRC opnieuw uitvoeren. De gemarkeerde gebieden verdwijnen als je dit venster sluit. Click on an item in the list to highlight of overlap it refers to. Klik op een item in de lijst om te zien welk gemarkeerd gebied bedoeld wordt. DebugDialog for debugging Voor foutopsporing DeleteDialog Also delete the file Verwijder ook het bestand Remove Verwijder Don't remove Verwijder niet Dip chip label IC label FApplication Import files from previous version? Bestanden importeren van vorige versie? Import Importeer Do not import now Nu niet importeren Fritzing failure Fritzing fout Fritzing caught an exception from %1 in event %2 Fritzing heeft een uitzondering van %1 gevonden in event %2 Fritzing caught an exception %1 from %2 in event %3 Fritzing heeft een uitzondering van %1 gevonden %2 in event %3 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Wil je onderdelen en koffers importeren die je hebt gemaakt in eerdere versies van Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Noot: Je kunt ze ook later importeren via "Help" >"Importeer onderdelen en koffers van oudere versie". Please specify an .fzz file name to save to (cancel will delete the backup) Specificeer een .fzz bestandsnaam om naar op te slaan. (Annuleren zal de backup verwijderen) Fritzing (*%1) Fritzing (*%1) Fritzing caught an exception from %1 in event %2: %3 FirstTimeHelpDialog First Time Help Eerste keer - help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Sluit venster Ctrl+W Ctrl+W Close the current sketch Sluit huidige sketch %1 - %2 %1 - %2 Specify a file name Specificeer een bestandsnaam Save "%1" "%1" Opslaan Do you want to save the changes you made in the document "%1"? Wilt u de wijzigingen opslaan in document "%1"? Save... Opslaan... Save Opslaan Don't Save Niet opslaan Ctrl+D Ctrl+D Your changes will be lost if you don't save them. De aangebrachte wijzigingen zullen verloren gaan, indien u niet opslaat. Cancel Annuleren GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Het verschil tussen ground vulling en koper vulling, is dat een koper vulling de ruimte tussen de connectors en banen zal opvullen. De ground vulling doet dit ook, maar zal ook verbinding maken met alle connectoren die het label 'GND' of 'Ground' hebben. Maar, het kan zijn dat je, van verschillende netten, maar één net gevuld wilt hebben. Dit venster vindt alleen de connectors gemarkeerd als 'GND' of 'Ground' en connectors die je zelf gemarkeerd hebt als 'Seed'. Klik op een item om de verbindingen te markeren in je sketch. Het is ook mogelijk om op een connector rechts te klikken en kies 'Maak ground vulling seed' uit het context menu. Cancel Annuleren OK OK OK and ground fill OK en ground vulling OK and copper fill OK en koper vulling Hole hole size gat diameter HtmlInfoView Connections Aansluitingen conn. aansl. connected to %n item(s) Aangesloten op %n item Aangesloten op %n items name Naam type Type (autoroutable) (autoroutable) Wire Draad Trace wire %1 Baan draad %1 Properties Eigenschappen Tags Tags Change the part label here Wijzig het onderdeel label hier Part breadboard view image Onderdeel breadboard weergave afbeelding Part schematic view image Onderdeel schema weergave afbeelding Part pcb view image Onderdeel PCB weergave afbeelding Part version number Onderdeel versie nummer Locked Vastgezet Ratsnest wire Rattennest draad Change the locked state of the part in this view. A locked part can't be moved. Wijzig de status van het vastgezette onderdeel. Een onderdeel welke is vastgezet kan niet verplaatst worden. Sticky Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Wijzig de status van het "sticky" onderdeel. Als een "sticky" onderdeel wordt verplaatst, bewegen onderdelen er boven ook mee. v. %1 %2 v. %1 %2 obsolete verouderd Placement Plaatsing pcb layer pcb laag location locatie rotation rotatie degrees graden ItemBase family familie size grootte color kleur resistance weerstand voltage spanning pin spacing pin afstanden rated power nominaal vermogen rated voltage nominale spanning rated current nominale stroomsterkte version versie package pakket shape vorm form formulier maximum resistance maximume weerstand Part Onderdeel model part problem model onderdeel probleem capacitance capaciteit inductance inductiviteit current stroom power spanning part number onderdeel nummer type type model model pins pins spacing afstand frequency frequentie processor processor variant variant layers lagen tolerance tolerantie descr beschr filename bestandsnaam title titel date datum rev rev sheet blad project project unable to create renderer for svg %1 niet mogelijk renderer te maken voor SVG %1 file for %1 %2 not found bestand voor %1 %2 niet gevonden banded gestreept top boven bottom onder copper bottom koper onderkant copper top koper bovenkant silkscreen bottom silkscreen onderkant silkscreen top silkscreen bovenkant KicadModuleDialog Cancel Annuleren OK OK LayerPalette show all layers toon alle lagen LinkDialog Cancel Annuleren OK OK url: url: text: tekst: LogoItem Unable to display Niet mogelijk om te tonen Unable to display image from %1 Niet mogelijk om de afbeeldeing te tonen van %1 shape vorm due to a rendering error door een renderings fout because the svg is empty omdat de SVG leeg is due to an xml problem: %1 line:%2 column:%3 door een xml probleem: %1 regel:%2 kolom:%3 because the file has no root element omdat het bestand geen root element heeft because the file has no <svg> element omdat het bestand geen <svg> element heeft for unknown reasons--possibly the image file is corrupted voor een onbekende reden--misschien is het afbeeldingsbestand beschadigd because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting omdat dit een SVG bestand lijkt te zijn, geëxporteerde vanuit CorelDRAW zonder te kiezen voor de 'presentation attributes' instelling text MainWindow Rotate Roteer Share Delen Flip Spiegel Autoroute Autoroute Add a note Notitie toevoegen Ready Klaar Save %1 Opslaan %1 Specify a file name Specificeer een bestandsnaam Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Niet mogelijk om %1 te exporteren als een uitwisselbare Fritzing Part (*%1) Fritzing Onderdeel (*%1) Unable to export %1 to shareable sketch Niet mogelijk om %1 te exporteren als uitwisselbare sketch Do you want to keep the imported parts? Wilt u de geïmporteerde onderdelen behouden? No connections to route Geen aansluitingen om te routen Routing completed Routing klaar %1 of %2 nets routed - %n connector(s) still to be routed %1 van de %2 nets gerout - %n aansluiting te gaan %1 van de %2 nets gerout - %n aansluitingen te gaan %1 - [%2] %1 - [%2] Sorry! Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Geen onderdeeel met deze karakteristiek. Wij werken er momenteel aan om dit bericht te vermijden en je te laten kiezen tussen eigenschappen die wel bestaan No exactly matching part found; Fritzing chose the closest match. Geen exact passend onderdeel gevonden; Fritzing koos voor de meest passende. Swapped %1 with module %2 %1 werd omgewisseld met module %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. De SVG %1 mist een '%2' laag. Voor meer informatie over hoe je een eigen bord kunt maken, zie de tutorial op <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG afbeelding (*.png) JPEG Image (*.jpg) JPEG afbeelding (*.jpg) SVG Image (*.svg) SVG afbeelding (*.svg) Printing... Bezig met afdrukken... All traces have not yet been routed. Niet alle banen werden gerout. Do you want to proceed anyway? Wilt u toch verder gaan? Proceed Doorgaan Cancel Annuleren Sketch exported Sketch geëxporteerd Export... Exporteer... Exporting... Exporteren... Unable to save %1 Fout bij opslaan van %1 Cannot print to %1 Fout bij printen van %1 Cannot write file %1: %2. Kan niet schrijven naar bestand %1: %2. Saved '%1' Opgeslagen %1 Select a Fritzing File to Open Selecteer een Fritzing bestand om te openen Cannot find file %1. Kan bestand niet vinden %1?. Cannot read file 1 %1: %2. Kan bestand niet lezen %1: %2. directly loading parts Direct inladen van onderdelen loading %1 (model) laden %1 (model) loading %1 (breadboard) laden %1 (breadboard) loading %1 (pcb) laden %1 (pcb) loading %1 (schematic) laden %1 (schema) Ctrl+N Ctrl+N Create a new sketch Creëer een nieuwe sketch &Open... &Openen... Ctrl+O Ctrl+O &Save &Opslaan Ctrl+S Ctrl+S Save the current sketch Sla huidige sketch op &Save As... &Opslaan als... Shift+Ctrl+S Shift+Ctrl+S Share online... Online delen... Post a project to the Fritzing website Vertuur een project naar de Fritzing website Export the visible area of the current sketch as a JPG image Exporteer het zichtbare gedeelte van de huidige sketch als een JPG afbeelding Export the visible area of the current sketch as a PNG image Exporteer het zichtbare gedeelte van de huidige sketch als een PNG afbeelding Export the visible area of the current sketch as a PostScript image Exporteer het zichtbare gedeelte van de huidige sketch als een PostScript afbeelding Export the visible area of the current sketch as a PDF image Exporteer het zichtbare gedeelte van de huidige sketch als een PDF afbeelding Export the current sketch as an SVG image Exporteer de huidige sketch als een SVG afbeelding List of parts (&Bill of Materials)... Lijst met onderdelen (&Winkellijstje)... Save a Bill of Materials (BoM)/Shopping List as text Sla een Bill of Materials (BoM)/Winkellijst op als een tekst bestand XML Netlist... XML Netlist... Save a netlist in XML format Sla een netlist op in XML formaat Export the current sketch to Eagle CAD Exporteer de huidige sketch naar Eagle CAD &Print... &Afdrukken... Ctrl+P Ctrl+P Print the current view Druk de huidige weergave af Shell launch %1 Shell lanceren %1 &Quit &Afsluiten Ctrl+Q Ctrl+Q Quit the application Applicatie afsluiten &Open Example &Open voorbeeld All Alles MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex:'kon voorbeeld niet laden met id='%1' &Open Recent Files &Open recente bestanden &%1 %2 &%1 %2 Undo Ongedaan maken Redo Opnieuw &Cut &Knippen Cut selection Knip selectie &Copy &Kopiëren Copy selection Kopieer selectie &Paste &Plakken Paste clipboard contents Plak klembord inhoud &Duplicate &Dupliceer Ctrl+D Ctrl+D Duplicate selection Dupliceer selectie &Delete &Verwijderen Delete selection Verwijder selectie &Select All &Alles selecteren Select all elements Selecteer alle elementen &Deselect &Deselecteer Deselect Deselecteren Add Note Notitie toevoegen &Preferences... &Eigenschappen... Show the application's about box Toon de applicatie about venster &Edit &Wijzig &Add to bin... &Toevoegen aan koffer... Add selected part to bin Voeg de geselecteerde onderdelen toe aan de koffer Disconnect All Wires Disconecteer alle draden Disconnect all wires connected to this connector Disconecteer alle draden die met deze aansluiting aangesloten zijn Update InfoView on hover Update de InfoWeergave bij overbewegen van de muis Export Normalized SVG Exporteer genormaliseerde SVG Export 1000 dpi SVG of this part in this view Exporteer 1000 dpi SVG van dit onderdeel in deze weergave Export Normalized Flattened SVG Exporteer Genormaliseerde Platte SVG Export 1000 dpi Flattened SVG of this part in this view Exporteer 1000 dpi Platte SVG van dit onderdeel in deze weergave Rotate the selected parts by 90 degrees clockwise Roteer de geselecteerde onderdelen 90° rechtsom Rotate the selected parts by 180 degrees Roteer de geselecteerde onderdelen 180° Rotate current selection 90 degrees counter clockwise Roteer de huidige selectie 90° linksom &Flip Horizontal &Flip horizontaal Flip current selection horizontally Flip huidige selectie horizontaal &Flip Vertical &Flip verticaal Flip current selection vertically Flip huidige selectie verticaal Bring to Front Breng volledig vooruit Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Breng de geselecteerde objecten vooruit in hun laag Bring Forward Breng vooruit Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Breng de geselecteerde objecten vooruit in hun laag Send Backward Breng achteruit Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Zend de geselecteerde objecten terug naar achter in deze laag Send to Back Breng volledig naar achter Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Zend de geselecteerde objecten naar achter in deze laag &Show All Layers &Toon alle lagen Show all the available layers for the current view Toon alle beschikbare lagen voor de huidige weergave &Hide All Layers &Verberg alle lagen Hide all the layers of the current view Verberg alle lagen van de huidige weergave &Show part label &Toon onderdeel label &Export... &Exporteer... Export selected part Exporteer geselecteerd onderdeel Add Bendpoint Voeg buigpunt toe Add a bendpoint to the selected wire Voeg een buigpunt toe aan de geselecteerde draad Select outdated parts Selecteer oude onderdelen Update selected parts Update de geselecteerde onderdelen &Zoom In &Zoom in Ctrl++ Ctrl++ Zoom in Inzoomen Ctrl+= Ctrl++ &Zoom Out &Zoom uit Ctrl+- Ctrl+- Zoom out Uitzoomen &Fit in Window &Pas aan in het venster Ctrl+0 Ctrl+0 Fit in window Pas aan in het venster &Actual Size &Actuele grootte Shift+Ctrl+0 Shift+Ctrl+0 &Show Breadboard &Toon breadboard Ctrl+1 Ctrl+1 Show the breadboard view Toon de breadboard weergave &Show Schematic &Toon Schema Ctrl+2 Ctrl+2 Show the schematic view Toon de schema weergave &Show PCB &Toon PCB Ctrl+3 Ctrl+3 Show the PCB view Toon de PCB weergave &Minimize &Minimaliseren Ctrl+M Ctrl+M Minimize current window Minimaliseer huidig venster Debugger Output Debugger output Online Tutorials Online tutorials Ctrl+? Ctrl+? Open Fritzing help Open Fritzing help Online Projects Gallery Online projecten gallerij Open Fritzing examples Open Fritzing voorbeelden Online Parts Reference Online Onderdelen Referentie Open Parts Reference Open Onderdelen Referentie First Time Help Eerste keer - help Check for updates... Controleer op updates... Check whether a newer version of Fritzing is available for download Controleer indie er een nieuwere versie van Fritzing beschikbaar is om te downloaden &About &Over Fritzing Display some handy Fritzing tips and tricks Toon handige Fritzing tips en trucks &About Qt &Over Qt Show Qt's about box Toon QT's about venster Report a but you've found in Fritzing &Import parts and bins from old version... &Importeer onderdelen en koffers van een oudere versie... Import parts and bins from previous installation Importeer onderdelen en koffers van een oudere installatie &File &Bestand &Export &Exporteer &Part &Onderdeel Raise and Lower Heffen en dalen &View &Weergave &Window &Venster &Help &Help Page Setup Pagina-instelling Sorry, "%1" has not been implemented yet Sorry,"%1" is nog niet geïmplementeerd Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Uw sketch heeft nog geen bord! Voeg a.u.b. een PCB toe om te kunnen exporteren naar Gerber. Choose a folder for exporting Kies een map om te exporteren This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Er zal gauw een export mogelijk zijn van uw Fritzing sketch naar de EAGLE layout software. Als je graag nog andere exports wilt zien naar uw favoriete EDA tool, laat het ons dan weten of help ons mee. Export SVG... Exporteer SVG... Export Bill of Materials (BoM)... Exporteer Winkellijst... Export Netlist... Exporteer NetList... Select All Traces Selecteer alle banen Select all trace wires Selecteer alle baan draden Select all trace wires excluded from autorouting Selecteer alle baan draden die uitgesloten waren van autoroute Tidy Wires Ruim draden op Tidy selected wires Ruim geselecteerde draden op Copper Fill Koper vulling Remove Copper Fill Verwijder de koper vulling Remove the copper fill Verwijder de koper vulling Autorouting... Autorouting... Remove Bendpoint Verwijder buigpunt Please choose the previous Fritzing folder... Kies a.u.b. de vorige Fritzing map... You will have to restart Fritzing in order to use the imported parts U moet Fritzing herstarten om de geïmporteerde onderdelen te kunnen gebruiken Remove copper fill Verwijder de koper vullingen &Wire Color &Draad kleur Launch %1... Start %1... No outdated parts found. All your parts are up-to-date. Geen oude onderdelen gevonden. Al uw onderdelen zijn up-to-date. Outdated parts Oude onderdelen Successfully updated %1 part(s). Please check all views for potential side-effects. Successvol %1 onderdeel/onderdelen ge-update. Controleer a.u.b. alle weergaves voor potentiële fouten. Update %1 part(s) Update %1 onderdeel throw test exception Gooi een test-exception throw a fake exception to see what happens Gooi een nep exception om te zien wat er gebeurd Select All Jumpers Selecteer alle jumpers New Nieuw Align to Grid Uitlijnen op raster Align items to grid when dragging Uitlijnen op raster tijdens slepen Tips, Tricks and Shortcuts Tips, Tricks and Shortcuts Open programming window Open programmeer venster Open microcontroller programming window Open Microcontroller programmeer venster Report a bug... Rapporteer een fout... Enable debugging log Zet logbestand voor foutmelding aan Both Layers Beide lagen Bottom Layer Onderste laag Top Layer Bovenste laag Backing up '%1' Backing up '%1' Rotate current selection 45 degrees counter clockwise Roteer de huidige selectie 45° linksom Rotate current selection 45 degrees clockwise Roteer de huidige selectie 45° rechtsom Actual (real world physical) size Werkelijke grootte 100% Size 100% grootte 100% (pixel) size 100% (pixel) grootte Set both copper layers clickable Maak beide koperlagen aanklikbaar Set copper top layer clickable Maak bovenste koperlaag aanklikbaar Set copper bottom layer clickable Maak onderste koperlaag aanklikbaar Copper Top and Copper Bottom layers are both active Bovenste en onderste koperlagen zijn beide actief Copper Top layer is active Bovenste koperlaag is actief Copper Bottom layer is active Onderste koperlaag is actief Autorouting Progress... Autorouting voortgang... File '%1' not found Bestand %1 niet gevonden Paste in Place Plak op plaats Paste clipboard contents in place Plak klembord inhoud op plaats Delete Verwijderen Routing completed using %n jumper part(s) Routing gereed door gebruik van %n jumper Routing gereed door gebruik van %n jumpers Delete Ratsnest Line Verwijder rattennest lijn Delete Wire Verwijder draad Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Verplaats de geselecteerde banen naar de andere kant van het bord. (Noot: de 'eerste' baan zal verplaatst worden en de rest volgt naar de zelfde kant.) Force Update Routing Status and Ratsnests Forceer Update Routing Status en Rattennest Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Herbereken Routing Status en Rattennest lijnen (In het geval de auto-update niet correct werkt) Lock Part Zet onderdeel vast Prevent a part from being moved Voorkom dat een onderdeel verplaatst wordt Select All Locked Parts Selecteer alle vastgezette onderdelen Select all parts that can't be moved Selecteer alle onderdelen die niet verplaatst kunnen worden Show Parts Bin Icon View Toon Onderdeel Koffer als Icoon Weergave Display the parts bin in an icon view Laat onderdelen in de onderdelen koffer zien als Iconen Show Parts Bin List View Toon Onderdelen Koffer als Lijst Weergave Display the parts bin in a list view Laat onderdelen in de onderdelen koffer zien als een lijst Donate to Fritzing Doneer aan Fritzing Open Fritzing donation web page Open de Fritzing donatie website Export for PCB Exporteer voor PCB Export the current sketch to PDF for DIY PCB production (photoresist) Exporteer de huigege sketch naar PDF voor DHZ PCB productie (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) Exporteer de huigege sketch naar SVG voor DHZ PCB productie (photoresist) JPG... JPG... PNG... PNG... PostScript... PostScript... PDF... PDF... SVG... SVG... Eagle... Eagle... Etchable (PDF)... Etsbaar (PDF)... Etchable (SVG)... Etsbaar (SVG)... as Image als Afbeelding for Production voor Productie loading %1 laad %1 Loading... Laden... new sketch nieuwe sketch BoM Text File (*.html) Winkellijst Tekst bestand (*.html) Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Exporteer de huige sketch naar Extended Gerber format (RS-274X) voor professionele PCB productie Unable to save BOM file, but the text is on the clipboard. Niet mogelijk om de winkellijst als bestand op te slaan, maar de tekst is opgeslagen naar het klembord. Do not autoroute Gebruik geen autoroute When autorouting, do not rip up this trace wire, via, or jumper item Deze baan, via of jumper niet aanpassen als de autorouter wordt gebruikt Move to other side of the board Verplaats naar de ander kant van het bord Select all jumper item parts Selecteer alle jumpers Select All Vias Selecteer alle via's Select all via parts Selecteer alle via onderdelen Shift+Ctrl+D Shift+Ctrl+D Order a PCB... Bestel een PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Bestel een PCB van jouw sketch--van Fabulous Fritzing Fab Straighten Curve Maak curve recht Straighten the curve of the selected wire Maak de curve van de geselecteerde draad recht Select All CopperFill Selecteer alle kopervullingen Select all copper fill items Selecteer alle kopervulling onderdelen unable to find replacement for %1. Niet mogelijk een vervanging te vinden voor %1. Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Sketch exported to Gerber Sketch geëexporteerd naar Gerber Shift+Ctrl+A Shift+Ctrl+A Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Ground Fill Ground vulling Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Vul lege gebieden van de koperlaag--Vulling zal alle banen verbonden met GROUND omvatten Fill empty regions of the copper layer--not including traces connected to a GROUND Vul lege gebieden van de koperlaag--Vulling zal alle banen verbonden met GROUND uitsluiten No copper top layer Geen bovenste koperlaag The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. De bovenste koperlaag (Koper 1) is niet aanwezig op een enkelzijdig bord. Wijzig naar dubbelzijdig bord of selecteer de onderste koperlaag. (Koper 0). No Sketch found in '%1' Geen sketch gevonden in '%1' the .fz file format is obsolete het .fz bestandsformaat is verouderd The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? Het .fz bestandsformaat wordt niet langer gebruikt. Wilt u '%1' converteren naar het .fzz bestandsfomaat of wilt u het als 'Alleen-Lezen' openen? The conversion process will not modify '%1'. Het conversie proces zal '%1' niet aanpassen. Convert Converteren Read-only Alleen-Lezen Please specify an .fzz file name to save '%1' to Kies a.u.b. een .fzz bestandsnaam om '%1' op te slaan &Routing &Routing &Create trace from ratsnest &Creëer baan van rattennest Create a trace from the ratsnest line &Creëer een baan van rattennest lijn &Create wire from ratsnest &Creëer draad van rattennest Create a wire from the ratsnest line &Creëer een draad van rattennest lijn Select All Wires Selcteer Alle Draden Select all wires Selecteer alle draden Fill empty regions of the copper layer--fill will include all traces connected to the seeds Vul lege gebieden van de koperlaag--Vulling zal alle banen verbonden met seeds omvatten Choose Ground Fill Seed(s)... Kies Ground vulling seed(s)... Set Ground Fill Seed Maak Ground Vulling Seed Treat this connector and its connections as a 'ground' during ground fill. Behandel deze connector en aansluitingen als 'Ground' tijdens de ground vulling. Clear Ground Fill Seeds Verwijder Ground Vulling Seeds Clear ground fill seeds--enable copper fill only. Verwijder de ground vulling seeds--sta alleen koper vulling toe. Generating %1 fill... Genereer %1 vulling... ground ground copper koper Show Grid Toon Raster Show the grid Toon het raster Actual Size Werkelijke grootte It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Het blijkt niet mogelijk te zijn om automatisch te detecteren, wat de werkelijke grootte van de monitor is, Dus 'ware grootte' is momenteel een gokje. Je kunt het best een lineaal toevoegen aan je sketch en vervolgens een echte lineaal er naast leggen. Zoom tot dat de maatvoering overeen komt. Select All "Don't Autoroute" Traces Selecteer Alle "Geen Autoroute" Banen Select All Autoroutable Traces Selecteer Alle Autorouteerbare Banen Select all trace wires that can be changed during autorouting Selcteer alle banen welke kunnen wijzigen tijdens autorouting Change to single layer pcb Wijzig naar enkellaags PCB Change to two layer pcb Wijzig naar dubbellaags PCB Change image to %2 Wijzig afbeelding naar %2 Gerber export can only handle one board at a time--please select the board you want to export. Gerber export kan maar één bord per keer aan--selecteer a.u.b. het bord dat je wilt expoteren. Sticky Sticky If a "sticky" part is moved, parts on top of it are also moved Als een "sticky" onderdeel wordt verplaatst, bewegen de onderdelen erboven ook mee Set Grid Size... Stel Rastergrootte In... Set the size of the grid in this view Stel hier de grootte van het raster in Set Background Color... Stel Achtergrondkleur In... Set the background color of this view Stel hier de achtergrondkleur in jumpers jumpers copperfill kopervulling vias vias OK OK Set the grid size for %1. Stel de rastergrootte in voor %1. Grid Size: Rastergrootte: in in mm mm Restore Default Standaard waarden Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Fritzing bestanden (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Uitwisselbaar (*%2);;Fritzing Onderdeel (*%3);;Fritzing Koffer (*%4);;Fritzing Uitwisselbare Koffer (*%5) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om een etsbaar export bestand te maken. Etchable export can only handle one board at a time--please select the board you want to export. Etsbaar export kan maar één bord per keer aan. --selecteer a.u.b. het bord welke je wilt exporteren. Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om de autorouter te kunnen gebruiken. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Selecteer a.u.b. het bord waarvoor je autoroute wilt. De autorouter kan maar één bord per keer aan. Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om een ground- of kopervulling te maken. Please select a PCB--copper fill only works for one board at a time. Selecteer a.u.b. het bord waarvoor je kopervulling wilt. Kopervulling werkt maar voor één bord tegelijk. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om de kopervulling te verwijderen. Please select a PCB--ground fill operations only work on a one board at a time. Selecteer a.u.b. het bord waarvoor je groundvulling wilt. Groundvulling werkt maar voor één bord tegelijk. Your sketch does not have a board yet! DRC only works with a PCB. Je sketch heeft nog geen bord! DRC werkt alleen met een PCB. Please select a PCB. DRC only works on one board at a time. Selecteer een bord! DRC werkt alleen met één bordt tegelijk. Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om gebruik te kunnen maken van kopervullingen. Please select a PCB. Copper fill operations only work on one board at a time. Selecteer a.u.b. het bord waarvoor je kopervulling wilt. Kopervulling werkt maar voor één bord tegelijk. Convert Bendpoint to Via Converteer buigpunt naar Via Convert the bendpoint to a via Converteert het buigpunt naar een Via Convert Via to Bendpoint Converteer Via naar Buigpunt Convert the via to a bendpoint Converteert een via naar een buigpunt Revert? Terug naar vorige versie? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Deze handeling kan niet ongedaan worden gemaakt--je zult alle aanpassingen verliezen. Doorgaan en terug naar vorige versie? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Open een Fritzing sketch (.fzz, fz) of laadt een Fritzing onderdeel(.fzpz), of een Fritzing onderdelen koffer (.fzb, fzbz) Revert Terug naar vorige versie Reload the sketch Herlaad de sketch Check Loaded Traces Controleerd geladen Banen Unrouted connections Ongeroute aansluitingen There are no unrouted connections in this view. Er zijn geen ongeroute aansluitingen in deze weergave. Edit (new parts editor) Wijzig (nieuwe onderdelen bewerker) Open the new parts editor on an existing part Open de nieuwe onderdelen bewerker voor een bestaand onderdeel Show unrouted Toon Ongeroute Highlight all unrouted connectors Markeer alle ongeroute aansluitingen Inspector Inspector Undo History Ongedaan maken geschiedenis Breadboard Breadboard Schematic Schema PCB PCB Layers Lagen Couldn't get the dock widget Fout bij ophalen dock widget &Delete Wire Verwijder &Draad Parts Editor Help Onderdelen Bewerker Help Display Parts Editor help in a browser Toon Onderdelen Bewerker help in een browser The folder "%1" isn't a Fritzing installation folder De folder "%1" is geen Fritzing installatiefolder Design Rules Check (DRC) Design Rules Check (DRC) DRC Progress... DRC Voortgang... Highlights any parts that are too close together for safe board production Markeer alle onderdelen die te dicht bij elkaar liggen voor een veilige bord productie Autoroute connections... Autoroute aansluitingen... Show/hide the label for the selected parts Toon/verberg het label voor de geselecteerde onderdelen Hide part silkscreen Verberg onderdeel silkscreen Hide/show the silkscreen layer for only this part Verberg/toon de silksrceen laag voor alleen dit onderdeel Hide part label Verberg onderdeel label Show part label Toon onderdeel label Show part silkscreen Toon onderdeel silkscreen Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Selecteer banen waar de scherm locatie niet overeen komt met de werkelijke locatie. Alleen nodig sketches autorouted met versie 0.7.10 of eerder Autorouter/DRC settings... Autorouter/DRC instellingen... Set autorouting parameters including keepout... Stel autorouting parameter in, inclusief veiligheidsafstand... Ctrl+4 Ctrl+4 Code Code Show Code Toon code Show the code (programming) view Toon de code (programmeer) weergave Fritzing Fab Quote... Fritzing Fab Offerte... How much would it could to produce a PCB from this sketch with Fritzing Fab Wat zullen de kosten zijn om een PCB te laten produceren van deze sketch met Fritzing Fab Find part in sketch... Vind onderdeel in de sketch... Search for parts in a sketch by matching text Zoek naar onderdelen met overeenkomstige tekst in een sketch Text will match part label, description, title, etc. Enter text to search for: Tekst zal gelijk zijn aan het onderdeellabel, beschrijving, titel, etc. Voer tekst in om te zoeken: Search Zoeken No parts matched search term '%1'. Geen onderdelen gevonden met de zoekterm '%1'. Unable to load part from '%1' Niet mogelijk om onderdeel te laden van '%1' MainWindow::moveToPartsFolder mainwindow missing MainWindow::verplaatsNaarOnderdeelMap Hoofdscherm mist There is already a part with id '%1' loaded into Fritzing. Er is al een onderdeel met id '%1' geladen in Fritzing. SPICE Netlist... SPICE Netlist... Save a netlist in SPICE format Sla een netlist op in SPICE formaat Unable to open '%1': %2 Niet mogelijk om %1 te openen:%2 Unable to open shareable '%1': %2 Niet mogelijk om '%1' te openen als uitwisselbare:%2 Unable to open shareable part '%1': %2 Niet mogelijk om '%1' te openen als uitwisselbaar onderdeel:%2 Export SPICE Netlist... Exporteer SPICE NetList... Set Ground Fill Keepout... Stel Ground Vulling Veiligheidsafstand In... Set the minimum distance between ground fill and traces or connectors Stel de minimale veiligheidsafstand in tussen een ground vulling en banen of aansluitingen Enter Text Voer Text in View from Above Bekijk van Boven View from Below Bekijk van Onder View from below Bekijk van onder View the PCB from the bottom layers upwards Bekijk de PCB vanaf de onderste laag omhoog View from above Bekijk van boven View the PCB from the top layers downwards Bekijk de PCB vanaf de bovenste laag naar onder Delete Minus Verwijder Minimaal Delete selection without attached wires Verwijder de selectie zonder gekoppelde draden Delete Wire up to bendpoints Verwijder de draad tot een buigpunt Move to bottom layer Verplaats naar onderste laag Move to top layer Verplaats naar de bovenste laag Align Left Links Uitlijnen Align selected items at the left Lijn de geselecteerde onderdelen links uit Align Horizontal Center Horizontaal Gecentreerd Uitlijnen Align selected items at the horizontal center Lijn de geselecteerde onderdelen Horizontaal gecentreerd uit Align Right Rechts Uitlijnen Align selected items at the right Lijn de geselecteerde onderdelen rechts uit Align Top Boven Uitlijnen Align selected items at the top Lijn de geselecteerde onderdelen boven uit Align Vertical Center Vertikaal Gecentreerd Uitlijnen Align selected items at the vertical center Lijn de geselecteerde onderdelen vertikaal gecentreerd uit Align Bottom Onder Uitlijnen Align selected items at the bottom Lijn de geselecteerde onderdelen onder uit Align Uitlijnen top and bottom boven en onder bottom onder top boven Ground Fill (%1) Ground vulling (%1) Copper Fill (%1) Koper Vulling (%1) Do you want to update now? Wil je nu updaten? There are %n outdated part(s) in this sketch. Er is %n onderdeel niet up to date in deze sketch. Er zijn %n onderdelen niet up to date in deze sketch. Click to highlight unconnected parts Fabricate Welcome Dump all parts Debug dump all parts in this view Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Test Connectors Connect all connectors to a single test part Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Rotate 45� Clockwise Roteer 135° Rechtsom {45�?} Rotate 90� Clockwise Roteer 135° Rechtsom {90�?} Rotate 180� Roteer 180° {180�?} Rotate 90� Counter Clockwise Roteer 45° Linksom {90�?} Rotate 45� Counter Clockwise Roteer 45° Linksom {45�?} Ctrl+Shift+V (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 MazeRouter Autorouter was cancelled. De autorouter werd geannuleerd. round %1 of: Poging %1 van: Unexpected SVG rendering failure--contact fritzing.org Onverwachte SVG renderings fout--contact Fritzing.org best so far: %1 of %2 routed Beste tot nu: %1 van %2 routed with %n vias met %n via met %n via's Routing reached maximum round %1. Routing heeft maximum ronde %1 bereikt. Routing stopped! Routing gestopt! Routing complete! Routing compleet! Routing unsuccessful; stopping at round %1. Routing niet gelukt; stopt bij ronde %1. Use best so far... Gebruik beste tot nu toe... Preparing undo... Voorbereiden op ongedaan maken... Optimizing traces... Banen optimaliseren... ModelBase File save failed! Fout bij opslaan! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Kon bestand niet overschrijven '%1'. Reden : %2 (errcode %3) Unable to find the following %n part(s): Kan het volgende %n onderdeel niet vinden: Kan de volgende %n onderdelen niet vinden: at in MysteryPart label label chip label IC label NetLabel net label net label Note [write your note here] [Typ hier uw notitie] PCBSketchWidget Click this connector to drag out a new trace. Klik op de aansluiting om een nieuwe baan te creëren. Change trace layer Wijzig spoor laag Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Uw sketch heeft nog geen bord! Voeg a.u.b. een PCB toe om koper vullingen te gebruiken. Fritzing error: unable to render board svg (1). Fritzing fout : Niet mogelijk om het SVG bord te renderen (1). Fritzing error: unable to render copper svg (1). Fritzing fout : Niet mogelijk om de koper SVG te renderen (1). Fritzing error: unable to write copper fill (1). Fritzing fout : Niet mogelijk om de kopervulling te schrijven (1). Fritzing error: unable to write copper fill (2). Fritzing fout : Niet mogelijk om de kopervulling te schrijven (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Niet mogelijk om de kopervulling te maken--misschien is het onderdeel niet goed op het bord geplaatst. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Niet mogelijk om de kopervulling te maken--misschien is het onderdeel op een ander onderdeel of op een draad geplaatst in plaats van het bord zelf. Create Trace from Ratsnest Creëer Spoor van Rattennest Please designate one or more ground fill seeds before doing a ground fill. Wijs één of meer ground vulling seeds aan, alvorens een ground vulling te doen. Clear ground fill seeds Verwijder ground vulling seeds %1 Fill: please select the board you want to apply fill to. %1 Vulling: Selecteer a.u.b. het bord wele gevuld moet worden. Ground Ground Copper Koper Copper fill: please select only the board you want to fill. Koper vulling: Selecteer a.u.b. het bord welke gevuld moet worden. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om te kunnen selecteren. Please click on a PCB first--this selection operation only works for one board at a time. Klik eerst op een bord--deze bewerking kan slechts voor één bord tegelijk worden uitgevoerd. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Je sketch heeft nog geen bord! Voeg a.u.b. een bord toe om te kunnen selecteren. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Niet mogelijk om deze via te converteren naar een buigpunt. Het is bevestigd aan een onderdeel wat alleen op de onderlaag aanwezig is en aan een ander onderdeel wat alleen op de bovenlaag aanwezig is. Show part silkscreen Toon onderdeel silkscreen Hide part silkscreen Verberg onderdeel silkscreen Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Je sketch heeft nog geen bord! Je kunt je sketch niet fabriceren zonder een PCB onderdeel. Enter Keepout Voer veiligheids afstand in Keepout is in mils (.001 inches). Veiligheidsafstand is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils Houd er rekening mee dat door kartelvorming afstanden tot 2 mils te kort kunnen zijn so you may want to increase the keepout value by that much. dus je zult de veiligheidsafstand met die waarde moeten vergroten. 10 mils is a good default choice. 10 mils is een goede standaard keuze. Enter keepout value: Voer veiligheids afstand in: Fritzing Fab Quote Fritzing Fab Offerte Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Sorry, http://fab.fritzing.org reageert niet op je offerte verzoek. Controleer je netwerkinstellingen en/of probeer later opnieuw. PEConnectorsView This is where you edit the connector metadata for the part Hier pas je de metadata voor de aansluiting aan voor het onderdeel number of connectors: aantal aansluitingen: Through-hole Through-hole SMD SMD PEMainWindow Parts Editor Onderdeel Bewerker Show Icon Toon Icoon Ctrl+4 Ctrl+4 Show the icon view Toon de Icoon weergave Ctrl+5 Ctrl+5 Show the metadata view Toon de metadata weergave Show Connectors Toon aansluitingen Ctrl+6 Ctrl+6 Change %1 to '%2' wijzig %1 naar '%2' Change tags Wijzig labels Change properties Wijzig eigenschappen Change description Wijzig beschrijving Change connector %1 Wijzig aansluiting %1 SVG SVG Connectors Aansluitingen Show in Folder Toon in Map On the desktop, open the folder containing the current svg file. Open op het bureaublad de map die het huidige SVG bestand bevat. Unable to write svg to %1 Niet mogelijk om de SVG naar %1 te schrijven Unable to parse fzp file %1 Niet mogelijk om fzp bestand %1 te analyseren Icon View Icoon weergave Metadata View Metadata weergave Connectors View Aansluitingen weergave Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Afbeeldings- & Footprint Bestanden (%1 %2 %3 %4 %5);;SVG Bestanden (%1);;JPEG Bestanden (%2);;PNG Bestanden (%3);;gEDA Footprint Bestanden (%4);;Kicad Module Bestanden (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Afbeeldingsbestanden (%1 %2 %3);;SVG Bestanden (%1);;JPEG Bestanden (%2);;PNG Bestanden (%3)%4%5 Open Image Open Afbeelding Copy problem Kopieer probleem Unable to make a local copy of: '%1' Niet mogelijk een lokale kopie te maken van :'%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. Je kunt een PNG of JPG gebuiken om je onderdeel te maken, maar het is beter om een SVG te gebruiken. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PNG en JPG afbeeldingen behouden hun bitmap eigenschappen en zullen er niet goed uit zien als ze vergroten-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. dus voor Fritzing onderdelen is het het beste om PNG en JPG te gebruiken als placeholders. Use of PNG and JPG discouraged Gebruik van PNG en JPG afgeraden Conversion problem Conversie probleem SVG problem SVG probleem Unable to parse '%1': %2 line:%3 column:%4 Niet mogelijk om '%1' te analyseren: %2 lijn:%3 kolom:%4 There are no copper layers defined in: %1. Er zijn geen koperlagen gedefineerd in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. Zie <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">deze uitleg</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>Dit zal geen probeelm zijn in de volgende release van de onderdeel bewerker, but for now please modify the file according to the instructions in the link. maar voor nu, pas het bestand aan zoals beschreven in de link. no schematics found in %1 geen schema's gevonden in %1 schematic part schematisch onderdeel no footprints found in %1 geen footprint gevonden in %1 Relocate connector %1 Herplaats aansluiting %1 &File &Bestand Sketch Change Warning Sketch Aanpassing Waarschuwing The open sketch '%1' uses the part you are editing. De geopende sketch '%1' maakt gebruik van het onderdeel dat u aanpast. Saving this part will make a change to the sketch that cannot be undone. Het opslaan van het onderdeel resulteerd in een wijziging in de sketch, welke niet ongedaan gemaakt kan worden. The open sketches De geopende sketches '%1', '%1', and '%1' en '%1' Saving this part will make a change to these sketches that cannot be undone. Het opslaan van het onderdeel resulteerd in een wijziging in de sketches, welke niet ongedaan gemaakt kan worden. Go ahead and save? Doorgaan en opslaan? Save Opslaan Cancel Annuleren Move terminal point Verplaats terminal punt Remove connector Verwijder aansluiting Remove %1 connectors Verwijder %1 aansluitingen Save "%1" "%1" opslaan Do you want to save the changes you made in the part "%1"? Wilt u de gemaakte wijzigingen opslaan voor onderdeel "%1"? Your changes will be lost if you don't save them. Je wijzigingen zullen verloren gaan, indien je niet opslaat. untitled part Onderdeel zonder naam Add connector Aansluiting toevoegen Add %1 connectors Voeg %1 aansluitingen toe There is one last edit still pending. Er is nog een laatste bewerking bezig. Duplicate 'family' property not allowed Dupliceren van 'familie' eigenschap niet toegestaan Duplicate 'variant' property not allowed Dupliceren van 'variant' eigenschap niet toegestaan Close without saving? Sluiten zonder opslaan? Close without saving Sluiten zonder opslaan Keep working Blijven werken Icon Icoon Metadata Metadata Remove Internal Connection Verwijder interne aansluitingen Fritzing (New) Parts Editor Fritzing (Nieuwe) Onderdeel Bewerker Show Metadata Toon Metadata Show the connector metadata in a list view Toon de metadata van aansluitingen in lijstweergave Blank not allowed Leeg niet toegestaan The value of '%1' can not be blank. De waarde van '%1' kan niet leeg zijn. Change %1 to %2 Wijzig %1 naar %2 Must be unique Moet uniek zijn Variant '%1' is in use. The variant name must be unique. Variant '%1' is in gebruik. De variantnaam moet uniek zijn. Duplicate problem Probleem met dupliceren Unable to load '%1' Niet mogelijk om '%1' te laden The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Het SVG bestand'%1' lijkt te zijn geëxporteerd van uit CorelDRAW zonder de 'presentation attributes' instelling. Please re-export the SVG file using that setting, and try loading again. Exporteer het SVG bestand nogmaals met de juiste instelling en probeer opnieuw. Fonts Lettertypen Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Fritzing ondersteunt momenteel alleen OCRA en Droid lettertypen--de lettertypen in '%1' zijn hierdoor vervangen Unable to load image file '%1': %2 Niet mogelijk om afbeeldingsbestand '%1' te laden: %2 Remove internal connection from '%1' Verwijder interne aansluiting van '%1' Internal connections are very messed up. De interne aansluitingen zijn erg warrig. Add internal connection from '%1' to '%2' Voeg interne verbinding toe van '%1' naar '%2' The 'family' property can not be blank. De 'familie' eigenschap kan niet leeg zijn. A duplicate 'family' property is not allowed Een gedupliceerde 'familie' eigenschap is niet toegestaan A duplicate 'variant' property is not allowed Een gedupliceerde 'variant' eigenschap is niet toegestaan This part can not be saved as-is: 'Opslaan Als' kan niet voor dit onderdeel: Do you want to keep working or close without saving? Wil je doorwerken of sluiten zonder opslaan? This part has %n unassigned connectors Dit onderdeel heeft %n niet toegewezen aansluiting Dit onderdeel heeft %n niet toegewezen aansluitingen across %n views. binnen %n weergave. binnen %n weergaven. Until all connectors are assigned to SVG elements, the part will not work correctly. Dit anderdeel zal niet goed werken tot dat alle aansluitingen juist zijn toegewezen aan de SVG elementen. Layers Lagen Reuse breadboard image Gebruik de breadboard afbeelding Reuse the breadboard image in this view Gebruik de breadboard afbeelding voor deze weergave Reuse schematic image Gebruik de schema afbeelding Reuse the schematic image in this view Gebruik de schema afbeelding voor deze weergave Reuse PCB image Gebruik de PCB afbeelding Reuse the PCB image in this view Gebruik de PCB afbeelding voor deze weergave Make only this view visible Maak alleen deze weergave zichtbaar The part will only be visible in this view and icon view Dit onderdeel zal alleen zichtbaar zijn in deze weergave en de icoon weergave This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. Deze versie van de Nieuwe Onderdeel Bewerker kan niet overweg met aparte koper0 en koper1 lagen in '%1'. So editing may produce an invalid PCB view image Dus bewerken kan resulteren in een onjuise afbeelding in de PCB weergave &Export &Exporteer Change all connectors to %1 Wijzig alle aansluitingen naar %1 Unable to parse '%1' Niet mogelijk om '%1' te analyseren Change to %1 Wijzig naar %1 Make only %1 view visible Maak alleen %1 weergave zichtbaar Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. De Onderdeel Bewerker nu verlaten is geen probleem, vergeet niet om later de toewijzingen af te maken. Load image for view... Laad afbeelding voor weergave... Open a file to use as the image for this view of the part. Open een bestand om te gebruiken voor de weergave van dit onderdeel. Save as new part Sla op als nieuw onderdeel Make a copy of the part and save it in the 'My Parts' Bin Maak een kopie van het onderdeel en sla het op in de 'Mijn Onderdelen' koffer &Edit &Wijzig This part has bendable legs. Dit onderdeel heeft buigbare pootjes. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . Deze versie van de Onderdeel Bewerker ondersteunt momenteel nog geen buigbare pootjes. De pootjes kunnen mogelijk verkeerd worden weergegeven in de breadboard weergave. If you make changes to breadboard view, or change connector metadata, the legs may no longer work. Als je wijzigingen maakt aan de breadboard weergave of de metadat voor de aansluitingen aanpast, is het mogelijk dat de pootjes niet meer (goed) werken. You can safely make changes to Schematic or PCB view. Je kunt nu veilig wijzigingen maken aan de schema of PCB of weergave. This warning will not be repeated in this session of Fritzing Deze waarschuling zal de rest van deze sessie van Fritzing niet meer getoond worden Unable to load '%1'. Please close the parts editor without saving and try again. Niet mogelijk om '%1' te laden. Sluit de Onderdeel Bewerker zonder opslaan en probeer opnieuw. Unable to load image file '%1' Niet mogelijk om afbeeldingsbestand '%1' te laden Inspector Inspector Unable to load fzp from %1 Niet mogelijk om fzp te laden van %1 Unable to create new connector--you may have to start over. Niet mogelijk om een nieuwe aansluiting te maken--Misschien moet je opnieuw beginnen. Filename prefix Bestandsnaam voorvoegsel Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Voer een voorvoegsel in om je onderdeelbestanden te herkennen. De namen zullen er als volgt uitzien 'VOORVOEGSEL_%1' (Het is niet noodzakelijk om het voorvoegsel te veranderen, omdat altijd een uniek achtervoegsel gemaakt wordt.) Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard PEMetadataView This is where you edit the metadata for the part ... Hier kun je de metadata wijzigen voor het onderdeel... Set the part's title Vul de onderdeeltitel in Title Titel Set the part's date Vul de onderdeel datum in Date Datum Set the part's author Vul de ontwikkelaar in Author Ontwikkelaar Set the part's description--you can use simple html (as defined by Qt's Rich Text) Vul een omschrijving in--Je kunt simpele html gebruiken (Qt's Rich Text) Description Omschrijving Set the default part label prefix Vul een standaard onderdeel-label kengetal in Label Label Set the part's family--what other parts is this part related to Vul de familienaam in van het onderdeel.--aan welke onderdelen is het gerelateerd Family Familie Set the part's properties Vul de onderdeel eigenschappen in Properties Eigenschappen Set the part's tags Vul Tags in voor het onderdeel Tags Tags Set the part's variant--this makes it unique from all other parts in the same family Vul de variant in--deze maakt een onderdeel binnen een familie uniek Variant Variant Set the part's url if it is described on a web page url naar datasheet op internet URL URL PESvgView width: breedte: height: hoogte: PEToolView Center Midden N N E O S Z W W Connector %1 Aansluiting %1 Set Internal Connections Stel Interne Aansluitingen in Set this checkbox to edit internal connections by drawing wires Vink aan om de interne aansluitingen te wijzigen door draden te trekken Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Instellingen voor de aansluitpunten van de aansluitingen. Het aansluitpunt is het deel waar de draad of baan verbinding maakt met de aansluiting. Je kunt ook het draadkruis verslepen van de huidige aansluiting center midden west west north noord south zuid east oost Sets the connector's terminal point to %1. Stelt het aansluitpunt als %1 in voor de aansluiting. Modifies the x-coordinate of the terminal point Wijzigt het x-coördinaat van het aansluitpunt Modifies the y-coordinate of the terminal point Wijzigt het y-coördinaat van het aansluitpunt Dragging disabled Slepen uitgeschakeld <font color='black'>Dragging enabled</font> <font color='black'>Slepen ingeschakeld</font> <font color='gray'>Dragging disabled</font> <font color='gray'>Slepen uitgeschakeld</font> Connector List (a checkmark means the graphic was selected) Lijst met aansluitingen (een vinkje betekent dat de afdeelding is geselecteerd) Select graphic Selecteer afbeelding Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Scroll met je muiswiel op de plaats on naar het SVG element te navigeren, waar je de aansluitingen voor wilt toewijzen, dan klikken om te selecteren. Pad shape vorm center midden north noord east oost south zuid west west connect to verbind naar PaletteItem Edit Pin Labels Wijzig Pin Labels Fritzing Fritzing Unable to proceed; unable to find top level view. Niet mogelijk om door te gaan; kon geen bovenste laag weergave vinden. Unable to proceed; part connectors do no have standard IDs. Niet mogelijk om door te gaan; onderdeel aansluitingen hebben geen standaard ID's. Label mismatch. Nothing was saved. Verkeerde label combinatie. Er is niets opgeslagen. hole size afmeting gat advanced settings geavanceerde instellingen in in mm mm Hole Diameter Gat Diameter Ring Thickness Ring Dikte PartLabel Edit Wijzig Edit label text Wijzig label tekst Display Values Toon waardes Flip/Rotate Flip/Roteer Font Size Tekengrootte Rotate the label by 90 degrees clockwise Roteer het label 90° rechtsom Rotate the label by 180 degrees Roteer de label 180° Rotate current selection 90 degrees counter clockwise Roteer de huidige selectie 90° linksom Flip Horizontal Flip horizontaal Flip label horizontally Flip label horizontaal Flip Vertical Flip verticaal Flip label vertically Flip label verticaal Small Klein Set font size to small Zet lettertype naar klein Medium Medium Set font size to medium Zet lettertype naar medium Large Groot Set font size to large Zet lettertype naar groot Label text Label tekst Display the text of the label Toon de tekst van de label Display the value of property %1 Toon de waarde van de eigenschap %1 Set label for %1 Zet label voor %1 Label text: Label tekst : Hide Verberg Hide part label Verberg onderdeel label Rotate the label by 45 degrees clockwise Roteer het label 45° rechtsom Rotate the label by 135 degrees clockwise Roteer het label 135° rechtsom Rotate the label by 135 degrees counter clockwise Roteer het label 135° linksom Rotate the label by 45 degrees counter clockwise Roteer het label 45° linksom Tiny Klein Set font size to tiny Stel een klein lettertype in Rotate 45� Clockwise Roteer 135° Rechtsom {45�?} Rotate 90� Clockwise Roteer 135° Rechtsom {90�?} Rotate 135� Clockwise Roteer 135° Rechtsom {135�?} Rotate 180� Roteer 180° {180�?} Rotate 135� Counter Clockwise Roteer 45° Linksom {135�?} Rotate 90� Counter Clockwise Roteer 45° Linksom {90�?} Rotate 45� Counter Clockwise Roteer 45° Linksom {45�?} PartsBinPaletteWidget Untitled Bin Koffer zonder naam Save Opslaan Specify a file name Specifiëer een bestandsnaam Fritzing Bin (*%1) Fritzing koffer (*%1) Fritzing Fritzing Cannot find file %1. Kan bestand %1 niet vinden. Cannot read file %1: %2. Kan bestand %1 niet lezen : %2. Do you want to save the changes you made in the bin "%1"? Wilt u de wijzigingen opslaan die u gemaakt heeft in de koffer "%1"? Don't Save Niet opslaan Ctrl+D Ctrl+D Your changes will be lost if you don't save them. Uw wijzigingen zullen verloren gaan indien u niet opslaat. Add to bin Voeg toe aan koffer Do you really want to add the selected part to the bin? Weet u zeker dat u het geselecteerde onderdeel wilt toevoegen aan de koffer? Save bin "%1" Sla koffer "%1% op Cancel Annuleren Loading... Laden... loading bin '%1' Koffer '%1' laden Change icon color... Wijzig icoon kleur... Change the color of the icon for this bin. Wijzig de kleur van het icoon voor de ze koffer. Select a color for this icon Selecteer een kleur voor dit icoon Perfboard size grootte set board size Stel grootte in voor het bord rows rijen columns kolommen Performance Warning Prestatie Waarschuwing Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Bij gebruik van gaatjes- of stripbord met meer dan circa 2000 gaatjes kan de prestatie van het programma vertragen. Weet je het zeker? Noot: Deze waarschuling zal de rest van deze sessie van Fritzing niet meer getoond worden. Set new size Stel nieuwe grootte in Cancel Annuleren PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Pin Label Bewerker</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Klik op een label naast een pin nummer om deze te hernoemen. You can use the tab key to move through the labels in order.</p> Je kunt de <Tab> toets gebruiken om naar het volgende label te gaan.</p> Cancel Annuleren Undo Ongedaan maken Redo Opnieuw Save Opslaan PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Cancel Annuleren OK OK Language Taal Colors Kleuren %1 (click to change...) %1 (klik om te wijzigen...) Connected Highlight Geconecteerde highlight Unconnected Highlight Niet geconecteerde highlight Mouse Wheel Behavior Gedrag scrollwiel Command Command Control Control Change Wheel Behavior Wijzig scrol wiel gedrag Autosave Automatisch Opslaan Autosave every: Sla automatisch op, iedere: minutes minuten no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom Geen toets ingedrukt = scroll De shift toets wisselt de as Alt of %1 toets = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Geen toets ingedrukt = zoom Alt of %1 toets = scroll De shift toets wisselt de as General Algemeen Curvy vs. straight wires Gebogen of rechte draden Clear Settings Standaard instelling When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? Wil je bij het verslepen van een draad of poot van een onderdeel (dus geen buigpunt of aansluiting) de draad (of poot) in een curve laten buigen of wil je een nieuw buigpunt laten maken? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Dit selectievakje stelt het standaard gedrag in. Je kunt het niet-standaard gedrag gebruiken door de Control toets (Mac: Command toets ⌘ ) ingedrukt te houden tijdens het slepen. Curvy wires and legs Gebogen draden en poten Code View Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Selecteer een programmer (uitvoerbaar) voor %1 ProgramTab Select a program file to load Selecteer een bestand om te laden Fritzing is unable to find '%1', please locate it Fritzing is niet in staat '%1' te vinden New Nieuw Save Opslaan Remove "%1"? "%1" verwijderen? Are you sure you want to remove "%1" from the sketch? Weet je zeker dat je "%1" uit de sketch wilt verwijderen? Code (*.%1) Code (*.%1) While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Hoewel het mogelijk is om %1 programmeer bestanden te openen en aan te passen, is het nog niet mogelijk om met Fritzing deze bestanden te compileren of te uploaden op een microcontroller. Open Platform Board Bord Port Serial Monitor Upload No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit &Wijzig Undo Ongedaan maken Redo Opnieuw &Cut &Knippen Cut selection Knip selectie &Copy &Kopiëren Copy selection Kopieer selectie &Paste &Plakken Paste clipboard contents Plak klembord inhoud &Select All &Alles selecteren Select all text Selecteer alle tekst File '%1' was restored from the .fzz file; the local copy was not found. Bestand '%1' is hersteld vanuit het .fzz bestand; de lokale kopie werd niet gevonden. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Bestand '%1' is hersteld vanuit het .fzz bestand; sla een lokale kopie op om met een externe bewerker te werken. &Code &Code &View &Weergave Code Window Code Venster Code Window - %1 Code Venster - %1 No boards available &Preferences... &Eigenschappen... Show the application's about box Toon de applicatie about venster &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Bord Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller %1%2 %1%2 QObject Preferences eigenschappen Please note that a new language setting will not take effect until the next time you run Fritzing. De wijziging van taal zal pas werken bij de volgende start van het programma. Fritzing Fritzing <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> The file '%1' is read-only; please use a different filename. Het bestand '%1' is alleen-lezen; Specifiëer a.u.b. een andere bestandsnaam. Edit link Wijzig link Part onderdeel Wire Draad Cannot read file %1: %2. Kan bestand niet lezen %1 : %2. Parse error (1) at line %1, column %2: %3 %4 Analyse fout (1) op lijn %1, kolom %2: %3 %4 The file %1 is not a Fritzing file (2). Het bestand %1 is geen Fritzing bestand (2). The file %1 is not a Fritzing file (4). Het bestand %1 is geen Fritzing bestand (4). The file %1 is not a Fritzing file (3). Het bestand %1 is geen Fritzing bestand (3). No parts found. Geen onderdelen gevonden. Parse error (2) at line %1, column %2: %3 %4 Analyse fout (2) op lijn %1, kolom %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Het onderdeel '%1' op '%2' heeft geen uniek module id '%3'. Part already in bin Onderdeel reeds in de koffer The part that you have just added, is already there, we won't add it again, right? Het onderdeel dat u juist heeft toegevoegd, bestaat al, we willen het niet nogmaals toevoegen, juist? a label een label a value een waarde Oops! Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Sorry, we hebben een probleem met het omwissel mechanisme. Fritzing werkt nog steeds, maar je kunt geen eigenschappen van de onderdelen wijzigen. bb bb Breadboard View Breadboard Weergave PCB View PCB weergave pcb pcb schem schema Schematic View Schema Weergave %1 %2 %3 %1 %2 %3 %1 Layer %1 Laag Bring forward Breng vooruit Send backward Breng achteruit Bring to front Breng naar voren Split Wire Draad splitsen Join Wire Draad samenvoegen Trace wires Baan draden Ratsnest wires Rattennest draden Select all %1 Selecteer alle %1 Select outdated parts Selecteer oude onderdelen File Progress... Bestand voortgang... Check for updates Controleer op updates icon view icoon weergave breadboard view breadboard weergave schematic view schema weergave pcb view PCB weergave Icon Icoon Breadboard Breadboard Parts Onderdelen Wires Draden Part Labels Onderdeel labels Notes Notities Rulers Meetlatten Board Bord Unknown Layer Onbekende laag files bestanden unable to open %1 niet mogelijk om %1 te openen unable to parse %1 Niet mogelijk om %1 te analyseren parse failure in %1 Analyse fout in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Sorry, Fritzing kan nog niet onderling omgaan met zowel pins en pads (in %1) bad pin argument count verkeerde pin variabelen bad pad argument count verkeerde pad variabelen footprint %1 not found in %2 footprint %1 niet gevonden in %2 unexpected end of file in footprint %1 in file %2 onverwacht eind van bestand in footprint %1 in bestand %2 unexpected format (1) in %1 from %2 onverwacht formaat (1) in %1 van %2 unexpected end of file onverwacht eind van bestand pad missing drill pad mist boorgat pad missing attributes pad mist attributen pad missing position pad mist postitie pad missing shape pad mist vorm position missing params positie mist parameters drill missing params boorgat mist parameters drill offset not implemented boorgat offset niet geïmplementeerd drill missing ellipse params boorgat mist elips parameters attributes missing params attributen missen parameters Sorry, can't handle pad type %1 Sorry, kan niet overweg met pad type %1 pad shape missing params pad vorm mist parameters shape delta not implemented vorm delta niet geïmplementeerd trapezoidal pads not implemented trapeziumvormige pads niet geïmplementeerd unable to handle pad shape %1 kan niet overweg met pad vorm %1 failure in svg conversion 1: %1 %2 %3 fout in SVG conversie 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 fout in SVG conversie 2: %1 %2 %3 Copying file %1 Kopieert bestand %1 File %1 already exists: it won't be overwritten Bestand %1 bestaat al: zal niet overgeschreven worden Silkscreen Top Silkscreen Bovenkant Silkscreen Top (Part Labels) Silkscreen Bovenkant (Onderdeel Labels) Copper Bottom Koper Onderkant Copper Bottom Trace Koper Baan Onderkant Copper Top Koper Bovenkant Copper Top Trace Koper Baan Bovenkant Silkscreen Bottom Silkscreen Onderkant Silkscreen Bottom (Part Labels) Silkscreen Onderkant (Onderdeel Labels) Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Sorry, Fritzing kan nog niet onderling omgaan met zowel pins en pads (in %1 in %2) bad layer mask parameter Foute maskerlaag parameter non-circular holes not implemented niet-ronde gaten niet geïmplementeerd non-copper holes not implemented gaten zonder koper niet geïmplementeerd Unable to parse copper: %1 %2 %3 Niet mogelijk om koper %1 %2 %3 te analyseren Parts folder not found. Onderdelen folder niet gevonden. Select %1 Selecteer %1 pad shape size is invalid pad grootte is onjuist bad schematic definition %1 foute schematische defenitie %1 schematic part %1 not found in %2 schematisch onderdeel %1 niet gevonden in %2 schematic %1 unexpectedly ends (1) in %2 schema %1 eindigt onverwacht (1) in %2 schematic %1 unexpectedly ends (2) in %2 schema %1 eindigt onverwacht (2) in %2 schematic %1 unexpectedly ends (3) in %2 schema %1 eindigt onverwacht (3) in %2 Part Image Onderdeel afbeelding Error reading file %1: %2. Fout bij lezen bestand %1: %2. Select locked parts Selecteer vastgezette onderdelen Basic Standaard Input Input Output Output ICs ICs Power Spanning Connection Aansluiting Microcontroller Microcontroller Tools Gereedschappen Frame Frame %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Wijzig poot van %1, %2 outline is empty outline is leeg the board outline layer, de bord outline laag silkscreen layer(s), silkscreen laag/lagen, copper layer(s), Koper laag/lagen, mask layer(s), masker laag/lagen, Unable to translate svg curves in %1 Niet mogelijk om SVG curves te vertalen in %1 silk export failure silk export fout drill export failure boor export fout mask export failure masker export fout Copper Fill Bottom Kopervulling Onderkant Copper Fill Top Kopervulling Bovenkant Shields Shields LilyPad LilyPad Other Anders Sensors Sensoren Pin Label Editor Pin Label Bewerker Ratsnest Rattennest mm mm in in Cannot write file temp: %1 %2 %3. Kan geen tijdelijk bestand aanmaken: %1 %2 %3. Cannot autoroute: no board (or multiple boards) found Kan autoroute niet uitvoeren: Geen bord/borden gevonden Set Ground Fill Seed Stel Ground Vulling Seeds in Ground Fill Seed Editor Ground Vulling Seed Bewerker %1 mask export failure (2) %1 masker export fout (2) Select all 'Don't autoroute' traces Selecteer aan 'Geen autoroute' banen Select all autorouteable traces Selecteer Alle Autorouteerbare Banen Set Grid Size Stel Rastegrootte In There is no undo for this action, and no further warning!!!! Je kunt deze actie niet ongedan maken en er komen geen verdere waarschuwingen!!! Clear Settings Standaard instelling No connections (on the PCB) to route. Geen aansluitingen (op de PCB) om te routen. No connections to route. Geen aansluitingen om te routen. Connected highlight color Verbonden markeerkleur Unconnected highlight color Niet verbonden markeerkleur Clear all saved settings and close this dialog immediately. Zet alles terug naar standaardinstellingen en sluit dit venster direct. This action does not delete any files; it restores settings to their default values. Deze actie verwijdert geen bestanden; de instellingen worden teruggezet naar de standaard waarden. Convert to Via Converteer naar Via Convert Via to Bendpoint Converteer Via naar Buigpunt %1 wires moved from their saved position in %2. %1 draden zijn verschoven vanaf hun opgeslagen positie in %2. paste mask layer(s), plak masker laag/lagen, ii ii Icon View Icoon Weergave <b>id:</b> <b>id:</b> <b>Name:</b> <b>Naam:</b> Set the connectors's title Stel de titel in voor de aansluiting <b>Description:</b> <b>Beschrijving:</b> Set the connectors's description Stel de beschrijving voor de aansluiting in Fritzing cannot load the parts bin Fritzing kan de onderdeelkoffer niet laden Internal Connections Interne Verbindingen Set all to: Maak alles: Pad Pad <b>type:</b> <b>type:</b> Part %1 '%2' Onderdeel %1 '%2' Fritzing is unable to process the cutouts in this custom PCB shape. Fritzing is niet in staat om de uitsnedes in de aangepast PCB vorm te verwerken. You may need to reload the shape SVG. Mogelijk moet je de SVG vorm opnieuw inladen. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Fritzing verlangt dat je de uitsnedes maakt door middel van een vorm via de 'substractie' of 'verschil' uitvoer binnen je vector programma. unable to copy file '%1' to '%2'. Niet mogelijk bestand '%1' naar '%2' te kopieren. Autorouter Settings Autorouter Instellingen %1 layer export is empty. %1 laag export is leeg. exported drill file is empty het geëxporteerde boorbestand is leeg exported mask layer %1 is empty de geëxporteerde masker laag %1 is leeg exported paste mask layer is empty de geëxporteerde soldeerpasta masker laag is leeg %1 layer: unable to save to '%2' %1 laag: niet mogelijk om naar '%2' op te slaan Unable to save pick and place file: %2 Niet mogelijk om pick and place bestand op te slaan:%2 Text Tekst %1 layer export is empty (case 2). %1 laag export is leeg (case 2). silk layer %1 export is empty silkscreen laag %1 export is leeg %2 ... %1 wires moved from their saved position %2 ...%1 draden verplaatst van hun opgeslagen positie <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Voor meer informatie over beprijzing ga je naar <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Order your PCB from Fritzing Fab Bestel je PCB van Fritzing Fab Price per board Prijs per bord Price Prijs Copies Aantal Visit Fritzing Fab Bezoek Fritzing Fab Fritzing Fab Quote Fritzing Fab Offerte The total area of the %n PCB(s) in this sketch is De totale oppervlakte van deze %n PCB in deze sketch is De totale oppervlakte van de %n PCB's in deze sketch is Please note that prices do not include shipping,<br /> Houd er rekening mee dat de prijzen exclusief verzendkosten,<br /> possible additional taxes, or the checking fee.<br /> btw en eventuele bankkosten zijn.<br /> %1 cm%3 (%2 in%3).<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Maak gebruik van Fritzing Fab om een PCB te laten produceren van je sketch<br /> Take advantage of our quantity discount: Maak gebruik van onze kwantumkoring: RecoveryDialog &Recover &Herstel &Ignore &Negeer File Bestand Last backup Laatste Backup Last saved Laast bewaard file not saved Bestand niet bewaard <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Fritzing is vastgelopen, maar sommige wijzigingen voor de volgende bestanden kunnen herstelt worden.</b></p><p>De datum en tijd van elk gebackupt bestand is weergegeven. Als het bestand is opgeslagen staat daarvan ook de datum en tijd vermeldt ter vergelijking.</p><p>De originele bestanden staan nog op je schijf als je ze ooit opgeslagen hebt. Je kunt er voor kiezen om die bestanden te overschrijven nadat je het herstelbestand geladen hebt.</p><p><b>Selcteer de bestanden die je wilt herstellen uit de lijst hier onder.</b></p> Resistor resistance weerstand Resistor Weestand You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' Je kunt een weerstandwaarde invoeren of selecteren uit het dropdown menu. Formaat nnn.dP waar P staat voor een 'umkMG' ResizableBoard shape vorm width: %1mm breedte : %1 mm height: %1mm hoogte : %1 mm width(mm) breedte (mm) height(mm) hoogte (mm) keep aspect ratio blijf in verhouding Revert Omkeren size grootte custom aangepast A0 (1030x1456) A0 (1030x1456) A1 (728x1030) A1 (728x1030) A2 (515x728) A2 (515x728) A3 (364x515) A3 (364x515) A4 (257x364) A4 (257x364) A5 (182x257) A5 (182x257) A6 (128x182) A6 (128x182) Letter (8.5x11) Letter (8.5x11) Legal (8.5x14) Legal (8.5x14) Ledger (17x11) Ledger (17x11) Tabloid (11x17) Tabloid (11x17) Ruler width breedte S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Project Filename Bestandsnaam Date Datum Sheet Pagina Rev of van date datum sheet pagina shape vorm SchematicSketchWidget Change voltage from %1 to %2 Wijzig spanning van %1 naar %2 Change label from %1 to %2 Wijzig label van %1 naar %2 SetColorDialog Make this the default %1 color Maak van deze de standaard %1 kleur Cancel Annuleren OK OK %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Pick custom %1 color Current color (%1) SketchWidget loading part Onderdeel laden done loading Klaar met laden %1 %2 %1 %2 %1 %2 items %1 %2 items Select All Alles selecteren Deselect Deselecteer Add %1 Toevoegen %1 Selection Selectie Move %2 (%1) Verplaats %2 (%1) Move %2 items (%1) Verplaats %2 items (%1) Select %1 Selecteer %1 Select %1 items Selecteer %1 items Disconnect Afsluiten Change Wijzig Connect Connecteer to %1 naar %1 Create and connect wire Creëer en connecteer een draad Rotate %2 (%1) Roteer %2 (%1) Rotate Roteer Flip Flip Double-click Dubbelklikken Drag or double-click Verslepen of dubbel klikken or alt-drag to move the segment of alt-versleep om een segment te verplaatsen Double-click to delete this bend point Dubbel klik om dit plooi punt te verwijderen Change %1 label to '%2' Wijzig %1 label naar %2 Change %1 color from %2 to %3 Wijzig %1 kleur van %2 naar %3 Change color of %1 wires to %2 Wijzig de kleur van %1 draad naar %2 Change %1 width from %2 to %3 Wijzig de %1 breedte van %2 naar %3 Change width of %1 wires to %2 Wijzig de breedte van %1 draden naar %2 Move label '%1' Verplaats label '%1' %1 label '%2' %1 label '%2' Resize Note Wijzig grootte van notitie Change Resistance from %1 to %2 Wijzig weerstand van %1 naar %2 Disconnect all wires from %1 Sluit alle draden af van %1 Disconnect all wires from %1 items Sluit alle draden af van %1 items Change image from %1 to %2 Wijzig afbeelding van %1 naar %2 Change %1 from %2 to %3 Wijzig %1 van %2 naar %3 from %1 van %1 Move leg of Verplaats poot van Flip %2 (%1) Flip %2 (%1) Change leg curvature for %1. Wijzig poot curve voor %1. Change leg bendpoint for %1. Wijzig poot buigpunt voor %1. change pin labels Wijzig pin labels Delete ratsnest Vewijder ratsnest Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Dit lijkt op een poging om een baan te maken tussen verschillende lagen. Van deze omstandigheid mag geen sprakezijn: neem contact op met de ontwikkelaars. Create and connect %1 Maak en verbind %1 wire draad trace baan Create wire from Ratsnest Maak draad van Rattennest Note text change Notitie tekst wijziging Unrouted connections are highlighted in yellow. Ongeroute aansluitingen zijn mer geel gemarkeerd. There are no unrouted connections Er zijn geen ongeroute aansluitingen Unrouted connections Niet geroute aansluitingen %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. %1 Noot:Je kunt dit venster ook oproepen door op de tekst van de routing status te klikken in de statusbalk. Deselect all Deselecteer alles Part '%1' not found in sketch Onderdeel '%1' niet gevonden in de sketch Resize board to %1 %2 Wijzig de grootte van het bord naar %1 %2 show %n part label(s) toon %n onderdeel label toom %n onderdeel labels hide %n part label(s) verberg %n onderdeel label verberg %n onderdeel labels Resize ruler to %1 %2 Wijzig grootte van meetlat naar %1 %2 Add %1 parts Voeg %1 onderdelen toe test connectors SqliteReferenceModel The swapping mechanism is disabled for: Het wissel mechanisme is uitgeschakeld voor: and %1 other parts en %1 andere onderdelen and %1 other properties en %1 andere eigenschappen property '%1' in part '%2' with id '%3'. eigenschap '%1' in onderdeel '%2' met id'%3'. part '%1' with id '%2'; possibly because it has no 'family' property. onderdeel '%1' met '%2'; waarschijnlijk omdat het geen 'familie' eigenschap heeft. Stripboard Restored Hersteld Cut Knip %1 %n strip(s) %1 %n strip %1 %n strips rows rijen columns kolommen %1 layout %1 layout SymbolPaletteItem voltage spanning label label Net labels Net labels Net labels cannot be blank Net labels kunnen niet leeg zijn TipsAndTricks Tips and Tricks Tips en Trucs Fritzing Tips and Tricks parts If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation rotatie To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor examples Get a jump start by looking at the example circuits under File > Examples. Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. TraceWire width breedte Select from the dropdown, or type in any value from %1 to %2 Selecteer uit het dropdown menu of typ een waarde tussen %1 en %2 TranslatorListModel English - %1 Engels - %1 French - %1 Frans - %1 German - %1 Duits - %1 Spanish - %1 Spaans - %1 Japanese - %1 Japans - %1 Portuguese (European)- %1 Portugees (Europees) - %1 Portuguese (Brazilian) - %1 Portugees (braziliaans) - %1 Hungarian - %1 Hongaars - %1 Estonian - %1 Estoniaans - %1 Dutch - %1 Nederlands - %1 Russian - %1 Russisch - %1 Italian - %1 Italiaans - %1 Hebrew - %1 Hebreeuws - %1 Arabic - %1 Arabisch -%1 Hindi - %1 Hindisch - %1 Chinese (Simplified) - %1 Chinees (simpel) - %1 Chinese (Traditional) - %1 chinees (traditioneel) - %1 Polish - %1 Pools - %1 Czech - %1 Tsjechisch - %1 Turkish - %1 Turks - %1 Swedish - %1 Zweeds - %1 Romanian - %1 Romeens - %1 Thai - %1 Thais - %1 Greek - %1 Grieks - %1 Bulgarian - %1 Bulgaars - %1 Galician - %1 Galicisch - %1 Korean - %1 Koreaans - %1 Indonesian - %1 Indonesisch - %1 Slovak - %1 Slowaaks - %1 Bengali - %1 Bengaals - %1 Persian - %1 Persisch - %1 Slovenian - %1 Sloveens - %1 Marathi - %1 Marathi - %1 Ukrainian - %1 Danish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close Sluiten No new versions found. Geen nieuwe versie gevonden. A new main release is available for downloading: Een nieuwe algemene release is beschikbaar om te downloaden : A new interim release is available for downloading: een nieuwe test release is beschikbaar om te downloaden : Checking... Controleren... Sorry, unable to retrieve update info Excuseer, niet mogelijk om de update info af te halen WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Fritzing Fab Wire thin (16 mil) dun (16mil) standard (24 mil) standaard (24 mil) thick (32 mil) dik (32 mil) extra thick (48 mil) extra dik (48 mil) blue blauw red rood black zwart yellow geel green groen grey grijs white wit orange oranje color kleur brown bruin purple paars super fine (8 mil) super fijn (8 mil) extra thin (12 mil) extra dun (12 mil) Banded Gestreept pink roze ochre cyan ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_pl.qm000066400000000000000000000000371250202676700217140ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. Save... Save Don't Save Cancel Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Placement pcb layer Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Ready Save %1 Unable to open '%1': %2 Specify a file name Fritzing (*%1) Fritzing Unable to export %1 as shareable Fritzing Part (*%1) Unable to export %1 to shareable sketch Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Select a Fritzing File to Open Cannot find file %1. Cannot read file 1 %1: %2. File '%1' not found directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber BoM Text File (*.html) Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (SVG)... &Print... Ctrl+P Print the current view Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box &Edit &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Show part label Ctrl+Shift+V Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Parts Editor Help Display Parts Editor help in a browser Align &Routing Move to bottom layer Move to top layer top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Show unrouted Highlight all unrouted connectors Select All Wires Select all wires Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Check Loaded Traces Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. jumpers copperfill vias The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. unable to find replacement for %1. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. &Show Breadboard Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show/hide the label for the selected parts Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Hide part silkscreen Hide/show the silkscreen layer for only this part Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Show Code Show the code (programming) view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation &File &Export as Image for Production &Part Raise and Lower &View &Window Ground Fill &Help Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Autoroute connections... Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+1 Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Select All CopperFill Select all copper fill items Select all jumper item parts Select All Vias Select all via parts Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Delete Page Setup Sorry, "%1" has not been implemented yet This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Select All Traces Select all trace wires Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select all trace wires excluded from autorouting Select All Jumpers Tidy Wires Tidy selected wires Copper Fill Remove Copper Fill Remove the copper fill Copper Top and Copper Bottom layers are both active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Copper Top layer is active Copper Bottom layer is active Autorouting... Autorouting Progress... Remove Bendpoint Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts Remove copper fill &Wire Color Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Do you want to update now? Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Metadata Connectors Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Save Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Cancel OK Mouse Wheel Behavior Command Control Change Wheel Behavior Code View Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Open Save Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Edit link Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb Breadboard View PCB View pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem Schematic View Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select all %1 Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates icon view breadboard view schematic view pcb view Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer Select %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Note text change Rotate Flip Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 test connectors Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_pt_br.qm000066400000000000000000005542271250202676700224260ustar00rootroot00000000000000V'7V2V/iWm5WhXYpYzZ8,[ %u[f3@[f3Hy\v]4^K_C F`AbpOcge'(i'aijcb>-jcblPjcbjej kmTSn 1nrx^BrxtZoutQuiފuiߙwmq y[?ye=9yerye}CyeyexHyezysyzzl޸zlzzw{ %tL{{I}}y9}|UUkW]wϞ5r5uQL! R0 c_^@~'$'NF*cZ-/u9u[u\T3y>ABI /RW>$ V#uJNj[:k\+K G"b-&a)t){w*l*/S62C4C69f?yJvg#/L#!L4w`O.ۏTZ]0e>eOqr*{(yIfERN3[C(5E`m,R3$ΥCCz p|P% rvN28 C!`]vNl..vR`˓͌SӒ2&Բ_oU~.wKŃ_MzUP5[3 1$xs&Ww.S44Ye?..]BɢC>DqJĮ_Q.Q˯%RԢ9TISYXBYYBYZCJ^4.fjXnlTRlpt.LtM<t]uTu5uT?mxebxe xicy9j;|D}v 'Rf B.43sS T3f@~şA^UIv>.$;A6;A^gAuu8±Q±ĵS*tz:,EaGaSucnfng[bQ<\:ufRI#hCx`b{Qfpq & 5T7T? [nk6J- 3OR (@.m4 ~;c=G>HLFJC{FFF.H04KNa TRBXMuYUhWwCnkqp>JrxL\su/|L}GwW;&6$oEMB"P\r[qm%^bڮ-~Z'tFܡǒeBRտ~`ֺLHBfd$"2Qd}c${eBlSHHC0cJu~2eʳ >y&IR=n9D~'e(Ï*Z-Im5E;N)=EsG$PѧTD!X~ZeEZehabcODc.jNq0lbtvzb~{eDV|/}%h|ou"nDḰWJ.ׅd/]&bf fmW&ɱ`IIITIXgIvHIvIIIIIII|z&}ZԘeQ~dx-6odvbT)8R `!H,W8b;YNP#Yb9 #~ ~@9ɖa;*yAٶLۘlDhgB:ENfFhX#;q&}38vR<^M m 2~*sT$[^Ung(Զ(<,]5f8[M;IZ,Z%gS9vO9oB]e]wDDYLLQ64W]^ &;l@9m^Ď֣h֣j\P,hn(rmޛneec -W9lDQAwK'p Y9!>g|"S&|8 'SH(n-3e. 6F.pB51,Y;!i/T?  qu y^ULS_p44V&a;tI -o?>d ߺ>J{^D;p(:A,0@3g p(U >`{%`&by)w{,ιR-BQ2)AwCX6EE:`TF?H4z#HtH{I'NO;P1mW;YQ Y´~^0b]AfCfC8f|Qfgi',iWvywJ:gx/yz.!|Ԃ{|^a|^;IAW"Q.~*1*s,2XNaxRl>"SSSSI{%H[pI$5nrlT*yG#2"3xMn*Jdfʗ/Кл%;S"E[:!';eT5 Ok \~ + E |U^ . w 8  7 k_ !ywI $)~) .5~J 0m 0!Sv 5G]h 6T5 ;=" BU% ExP GȧZ MgV Q' Se \ug aBx cϥ d` lO~ l t7 ui u |@pK ~ .@ ~S X Ne \ rc ^V 8` ;.| D < +k B1L N! .C :dZ } ~m{ ; sP Ŧ9s H5 8 , 3˸ ; ՛ {u M NE ~{ Dh v J i T  ! R ^@ JO  = `:: 7p i7.n 2{6  !qz !q #$ )r” ?"E$ CDs D)R$ M n N=D PǸ U|9 [>I ^5P a4Y c3 c3 dl d8 eK eR! e e fj g7t k2_ k2 qw su0 tqo w N Ȑ v y : ~9 C #; ,' ^   +=  "n 9 99 Ɍ4m vE v|L ώ.X Ϯ ! Ҍ: 0T3 0X ˺OS K } ;'° cW ? Rs UE J TT a Vl ~Շ ~ Q g; % !_g"X #e %4}o (W{ ) u )#] )J *P *d -# -mnc 8)- ? 8 H7~ K2gFz K2gYq N>& V5 Ys8 bRV g gy`* i$en l? pf ),y 7s 1  ^ z! ?  u> 4 @ x ^ q\J %n { N AR }x p` Z.N ƽ~j" +3 |W %A/ 1X < KGv f[  t 4P >   yhE w CC L I  e = AiT( F^1 L.); O~1 Wj XM"=j `l af euo" eZ! hȾ'k ox rV rL tg z n z n a {7< "/ ]D# @S N ҩ $u )n| b @  ^I G ,) , j  / / ' [  P @  1* m4~ E( . 9( T7 Y@ ɠ.u ?2 > '@? oe. K 5M ~. }lx .  ok UX ˞ J (t % fW 'q  nH #Ѯr 3F( 3f( 7n < yX >OJ ?څ A AC DA DD G0 LRhE R/Z Tp. X4+ Zg1| [ )\ _k cv c? f fk1 i s kc~ m[aI qU9 u;Ѯ v9M v{ vC$ }PL # ) }; ' 15# v Y ~e z| 0  ~Bq & @ RcC < ՞d ^ cY< N: w c  eU _3 ^  wZ q P">7>_ R GB)t1PZ3̈dAO{ rcX(J,#i*/9F;a,K0a.VIa.e~VfTOfT9*v8%w=)wy7~tPi"o#un,n Q>W$)+SRJRM?xNxãCPciuŅŅ$AA5qt`+5!4ti'& uC'1Cn]$6=^$Y=V+>q &C~4 }iyR=Z X~uLa"TN3$/`iǓ13=VZ5=_G@k@cCO(/^TZW]tm^'av!ud}sBfg=hi?i0p4sVvgU<z |`}$7T@  ? vxF(zd^z9=aZFjc@jcV'"D<X6T]3q.cS\Wip<b>GNU GPL v3 no cdigo e CreativeCommons:BY-SA no resto?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxdBryant Mairs, Uleshka Asher, e Daniel Tzschentke. 4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxXDepartamento da Bauhaus-University Weimar, )Department of Bauhaus-University Weimar, AboutBox@os testes iniciais no Fritzing. Fritzing a test spin. AboutBox<Fritzing foi desenvolvido por:Fritzing is made by: AboutBoxrFritzing foi possvel com o financiamento proveniente da 0Fritzing is made possible with funding from the AboutBoxtIxDS,um patrocinador annimo, Parallax, Picaxe, Sparkfun, 6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBoxVMWFK Brandenburg, o patrocinador do Design 0MWFK Brandenburg, the sponsorship of the Design AboutBox>Michaela Vieser e Julia Werner.!Michaela Vieser and Julia Werner.AboutBoxzAgradecimentos especiais vo tambm para todos os estudantes 4Special thanks goes out as well to all the students AboutBox<Agradecimentos especiais para:Special thanks goes out to: AboutBoxAgradecimentos para Kurt Badelt e Miguel Solis pela traduo para Espanhol, DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBoxe todos os alpha testers que foram corajosos o suficiente para fazer 0and alpha testers who were brave enough to give AboutBoxao &#313;ubom&iacute;r Ducho&#328; pela traduo para o Slovaco, ?to Ĺubomír Duchoň for the Slovak translation, AboutBoxbao Alexander Kaltsas pela traduo para o Grego, 0to Alexander Kaltsas for the Greek translation, AboutBoxrao Cihan Mete Bahad&#x0131;r pela traduo para o Turco, :to Cihan Mete Bahadır for the Turkish translation, AboutBoxbao Gianluca Urgese pela traduo para Italiano, 0to Gianluca Urgese for the Italian translation, AboutBox\ao Hiroshi Suzuki pela traduo para Japons, 0to Hiroshi Suzuki for the Japanese translation, AboutBoxZao Jinbuhm Kim pela traduo para o Coreano, +to Jinbuhm Kim for the Korean translation, AboutBox\ao Josef Dustira pela traduo para o Tcheco, ,to Josef Dustira for the Czech translation, AboutBoxao Nuno Pessanha Santos pela traduo para Portugus (Europeu), Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxnao Robert Lee pela traduo para chins (Tradicional), 9to Robert Lee for the Chinese (Traditional) translation, AboutBoxao Steven Noppe e Davy Uittenbogerd pela traduao para o Holands, Ato Steven Noppe and Davy Uittenbogerd for the Dutch translation, AboutBox\ao Vladimir Savinov pela traduo para Russo, 1to Vladimir Savinov for the Russian translation, AboutBoxzao Yuelin e Ninjia pela traduo para Chins (Simplificado), @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBox(ltimo verso vlida Best So FarAutorouteProgressDialogCancelarCancelAutorouteProgressDialogParar agoraStop NowAutorouteProgressDialog8zoom e comandos de movimentozoom and pan controlsAutorouteProgressDialog`Roteamento cancelado! Limpando trabalho feito...$Routing canceled! Now cleaning up... Autorouter<b>Margem de Distncia</b> a distncia mnima entre elementos de cobre em redes diferentes.QKeepout is the minimum distance between copper elements on different nets.AutorouterSettingsDialogA margem de distncia de 0.01 polegada (0.254 mm) um bom padro.4A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialogCancelarCancelAutorouterSettingsDialog&Margem de distnciaKeepoutAutorouterSettingsDialogNota: quanto menor a margem de distancia, maior o tempo para DRC e autoroteador serem executados.JNote: the smaller the keepout, the slower the DRC and Autorouter will run.AutorouterSettingsDialog Tipo de produoProduction typeAutorouterSettingsDialog Largura do trao Trace widthAutorouterSettingsDialogpersonalizadocustomAutorouterSettingsDialogcaseirohomebrewAutorouterSettingsDialogprofissional professionalAutorouterSettingsDialog PacoteBin BinManagerBinManager::setDirtyTab: No foi possvel definir o pacote '%1' como suja;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerGestorPacote::TtuloAtualizado: No se pode definir o pacote '%1' como sujo;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerZNo possvel definir NULL como pacote atual(Cannot set a NULL bin as the current one BinManagerFechar Pacote Close Bin BinManager8Fechar pacote de componentesClose parts bin BinManagerJCriar um novo pacote para componentesCreate a new parts bin BinManagerApagar Pacote Delete Bin BinManagerApagar pacote Delete bin BinManager8Apagar componentes do pacoteDelete parts bin BinManagerBMostrar os componentes numa listaDisplay parts as a list BinManagerDMostrar os componentes como conesDisplay parts as icons BinManagerDeseja realmente apagar o pacote '%1'? Esta ao no pode ser desfeita.EDo you really want to delete bin '%1'? This action cannot be undone. BinManagerVoc realmente deseja remover '%1' do pacote? Esta operao no pode ser desfeita.PDo you really want to remove '%1' from the bin? This operation cannot be undone. BinManagerdEditar Componente (editor de novos componentes)...Edit Part (new parts editor)... BinManager$Exportar pacote... Export Bin... BinManager,Exportar Componente...Export Part... BinManager>Achar Componente no EsquemticoFind Part in Sketch BinManagerArquivos de pacote Fritzing (*%1 *%2);; Pacote Fritzing(*%1);; Pacote Fritzing compartilhvel (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagerArquivos Fritzing (*%1 *%2 *%3);;Componentes Fritzing (*%1);;Pacotes Fritzing (*%2);;Pacotes Compartilhveis Fritzing (*%3)cFritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) BinManagerImportar... Import... BinManagerCarregar uma parte Fritzing (.fzpz), ou um pacote Fritzing de partes (.fzb, .fzbz)CLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManagerNovo Pacote... New Bin... BinManager Novo pacote (%1) New bin (%1) BinManagerComponentesParts BinManager@Selecione um nome para o pacote:!Please choose a name for the bin: BinManager0Pacote-apenas de leitura Read-only bin BinManager$Remover Componente Remove Part BinManager"Remover do PacoteRemove from Bin BinManager"Remover do pacoteRemove from bin BinManager$Renomear pacote... Rename Bin... BinManagerRenomear pacote Rename bin BinManagerFRenomear o pacote de componentes...Rename parts bin... BinManagerSalvar PacoteSave Bin BinManager*Salvar pacote como...Save Bin As... BinManager<Salvar o pacote de componentesSave parts bin BinManagerLSalvar o pacote de componentes como...Save parts bin as... BinManagerjSalvar pacote de componentes em formato compactado...&Save parts bin in compressed format... BinManagerProcurando... Searching... BinManagerPSelecione um arquivo Fritzing para abrirSelect a Fritzing File to Open BinManagerlSelecione um pacote Fritzing de componentes para abrir(Select a Fritzing Parts Bin file to open BinManager<Mostrar o pacote no modo coneShow Bin in Icon View BinManager<Mostrar o pacote no modo listaShow Bin in List View BinManagerFEste pacote no pode ser renomeado.This bin cannot be renamed. BinManagerNo foi possvel remover componente '%1'--ele est em uso em um esquemtico4Unable to remove part '%1'--it is in use in a sketch BinManager Um svg de placa personalizada tipicamente tem uma ou mais camadas de impresso e um camada de placa.U A custom board svg typically has one or two silkscreen layers and one board layer. Board*Posso carregar, porm Can load, butBoardD uma olhada no arquivo circle_pcb.svg na sua pasta de instalao do Fritzing no diretorio parts/svg/core/pcb/. eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. BoardImagensImagesBoardXSelecione um arquivo de imagem para carregarSelect an image file to loadBoardzA imagem de %1 pode ser carregada, porm %2 Usar assim mesmo?5The image from %1 can be loaded, but %2 Use the file?Board2No foi possvel carregarUnable to loadBoardVNo foi possvel carregar a imagem de %1 %2Unable to load image from %1 %2Board\porque o xml no estava corretamente formatado*because the xml is not correctly formattedBoardPporque existem mltiplas camadas <board>)because there are multiple layersBoard\porque existem mltiplas camadas <silkscreen0>/because there are multiple layersBoardZporque existem mltiplas camadas <silkscreen>.because there are multiple layersBoardDporque no existe a camada <board>!because there is no layerBoarddmas a pcb ,por si s, no ter camada de impresso0but the pcb itself will have no silkscreen layerBoardbdevido a um problema de xml: %1 line:%2 column:%3+due to an xml problem: %1 line:%2 column:%3Board"arquivo de imagem image fileBoard4Carregar arquivo de imagemload image fileBoard2uma camada (face simples)one layer (single-sided)BoardZo elemento <board> contm elementos sem forma.the element contains no shape elementsBoard@o svg contm elementos sem forma"the svg contains no shape elementsBoardvo svg no compatvel com o formato personalizado da placa+the svg doesn't fit the custom board formatBoard2duas camadas (face dupla)two layers (double-sided)Board formashape BoardLogoItem.Selecionar cor do textoSelect text colorBreadboardLogoItem(Definir cor do textoSet text colorBreadboardLogoItemcorcolorBreadboardLogoItem`Selecione do menu cascata, ou digite um valor %1/Select from the dropdown, or type in a %1 value Capacitor2Adicionar ponto de flexo Add bendpoint ConnectorItem.Remover ponto de flexoRemove bendpoint ConnectorItem Endireitar curvaStraighten curve ConnectorItem &Sobre&About ConsoleWindow &Sair&Quit ConsoleWindowFerramentasTools ConsoleWindow:%1 est sobrepondo (%2 layer)%1 is overlapping (%2 layer)DRCUm buraco em %1 pode cair fora da borda do curcuito e poder ser cortado.JA hole in %1 may lie outside the border of the board and would be clipped.DRC$DRC foi cancelado.DRC was cancelled.DRCterro Fritzing: no foi possvel renderizar o svg da placa.+Fritzing error: unable to render board svg.DRCPNenhuma trilha ou conectores para checar No traces or connectors to checkDRCReposicione eles e rode o DRC novamente para encontrar mais problemas;Reposition them and run the DRC again to find more problemsDRCAs reas destacadas em vermelho na sua placa so trilhas ou ligaes que podem se sobrepor ou estarem muito prximas. qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRC@Muito prximo a borda (%1 layer) Too close to a border (%1 layer)DRCzFalha de renderizao de SVG inesperada--contate fritzing.org6Unexpected SVG rendering failure--contact fritzing.orgDRCSeu esquemtico est pronto para produo: no existem trilhas ou ligaes incorretas ou muito prximas.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRCClique em um item da lista para destacar a qual sobreposio ele se refere.BClick on an item in the list to highlight of overlap it refers to.DRCResultsDialog"Resultados do DRC DRC ResultsDRCResultsDialogbNota: os itens da lista e o destaque vermelho no sero atualizados conforme edita o esquemtico--rode novamente o DRC. O destaque ir desaparecer quando voc fechar este aviso.Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialogpara depurao for debugging DebugDialog.Tambm apague o arquivoAlso delete the file DeleteDialogNo remover Don't remove DeleteDialogRemoverRemove DeleteDialogRtulo do chip chip labelDip Nota: Voc pode importa-los posteriormente usando o menu de ao "Ajuda" -> "Importar peas e bins de verses antigas...".l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication$No importar agoraDo not import now FApplicationGostaria de importar peas e pacotes que voc criou com verses anteriores do Fritzing?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationhFritzing capturou uma excesso %1 de %2 no evento %33Fritzing caught an exception %1 from %2 in event %3 FApplicationbFritzing capturou uma excesso de %1 no evento %20Fritzing caught an exception from %1 in event %2 FApplicationFalha FritzingFritzing failure FApplicationImportarImport FApplicationRImportar arquivos de uma verso anterior?#Import files from previous version? FApplicationFavor especificar um nome para o arquivo .fzz para salv-lo para (cancelar ir apagar o backup)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplication*Ajuda na primeira vezFirst Time HelpFirstTimeHelpDialog&Fechar Janela &Close WindowFritzingWindowCancelarCancelFritzingWindow*Fechar o sketch atualClose the current sketchFritzingWindowjDeseja salvar as alteraes feitas no documento "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindowNo salvar Don't SaveFritzingWindow SalvarSaveFritzingWindowSalvar "%1" Save "%1"FritzingWindowSalvar...Save...FritzingWindow<Especifique um nome de arquivoSpecify a file nameFritzingWindowfSuas mudanas sero perdidas se voc no salva-las.1Your changes will be lost if you don't save them.FritzingWindowCancelarCancelGroundFillSeedDialog.OK e preencha com cobreOK and copper fillGroundFillSeedDialog:OK e preencha com aterramentoOK and ground fillGroundFillSeedDialog A diferena entre o preenchimento aterrado e o preenchimento em cobre que no preenchimento aterrado so includos traos que ligam o preencimento a conectores para aterramento. Conectores de aterramento usualmente so nomeados como 'GND',ou 'ground''. Tambm possvel que vrias malhas tenham conector de aterramento, e voc pode desejar que apenas uma dessas malhas seja ligada ao aterramento. Esse dilogo coleta apenas conectores nomeados como 'GND' ou 'ground', assim como conectores j escolhidos como pontos de aterramento. Clique em um item para destacar suas conexes no esquemtico. Tambm possvel escolher um conector como ponto de aterramento clicando com o boto direito num conector e selecionando a opo 'Escolher Como Ponto de Aterramento' no menu.The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialogtamanho do furo hole sizeHole(autorotevel)(autoroutable) HtmlInfoViewMude o estado de "grudento" deste componente nesta visao. Quando um componente grudento movido, objetos acima dele so movidos juntos.pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoViewMude o estado de bloqueio do componente nesta viso. Uma parte bloqueada no pode ser movida.OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoView>Mudar o nome do componente aquiChange the part label here HtmlInfoViewConexes Connections HtmlInfoViewBloqueadoLocked HtmlInfoViewHImagem dos componentes na protoboardPart breadboard view image HtmlInfoView:Imagem dos componentes da PCBPart pcb view image HtmlInfoViewJImagem dos componentes do esquemticoPart schematic view image HtmlInfoView(Verso do componentePart version number HtmlInfoViewPropriedades Properties HtmlInfoViewFiao de n Ratsnest wire HtmlInfoViewGrudentoSticky HtmlInfoViewMarcadoresTags HtmlInfoViewTraar fio %1 Trace wire %1 HtmlInfoViewFioWire HtmlInfoViewcon.conn. HtmlInfoView2conectado a %n componente4conectado a %n componentesconnected to %n item(s) HtmlInfoViewnomename HtmlInfoViewobsoletoobsolete HtmlInfoViewtipotype HtmlInfoViewComponentePartItemBasecom faixasbandedItemBaseinferiorbottomItemBasecapacitncia capacitanceItemBasecorcolorItemBasecobre inferior copper bottomItemBasecobre superior copper topItemBasecorrentecurrentItemBasedatadateItemBasefamliafamilyItemBaseJarquivo para %1 %2 no foi encontradofile for %1 %2 not foundItemBasenome do arquivofilenameItemBase formaformItemBasefrequncia frequencyItemBaseindutncia inductanceItemBasecamadaslayersItemBase$resistncia mximamaximum resistanceItemBase modelomodelItemBase@problema no modelo do componentemodel part problemItemBase pacotepackageItemBase(nmero do componente part numberItemBase$Espao entre pinos pin spacingItemBase pinospinsItemBaseenergiapowerItemBaseprocessador processorItemBaseprojetoprojectItemBase corrente nominal rated currentItemBase potncia nominal rated powerItemBasetenso nominal rated voltageItemBaseresistncia resistanceItemBaserevisorevItemBase formashapeItemBase folhasheetItemBase$impresso inferiorsilkscreen bottomItemBase$impresso superiorsilkscreen topItemBasetamanhosizeItemBaseespaamentospacingItemBase ttulotitleItemBasetolerncia toleranceItemBasesuperiortopItemBasetipotypeItemBasefNo foi possvel criar a renderizao para o svg %1$unable to create renderer for svg %1ItemBasevariantevariantItemBase versoversionItemBase tensovoltageItemBaseCancelarCancelKicadModuleDialog0Mostrar todas as camadasshow all layers LayerPaletteCancelarCancel LinkDialog texto:text: LinkDialog.No foi possvel exibirUnable to displayLogoItemLNo foi possvel exibir a imagem do %1Unable to display image from %1LogoItemXporque o arquivo no continha elemento <svg>%because the file has no element���LogoItem���P�p�o�r�q�u�e� �o� �a�r�q�u�i�v�o� �n��o� �t�i�n�h�a� �e�l�e�m�e�n�t�o� �r�a�i�z�������$because the file has no root element���LogoItem���.�p�o�r�q�u�e� �o� �s�v�g� �e�s�t�� �v�a�z�i�o�������because the svg is empty���LogoItem����p�o�r�q�u�e� �i�s�s�o� �p�a�r�e�c�e� �s�e�r� �u�m� �a�r�q�u�i�v�o� �S�V�G� �e�x�p�o�r�t�a�d�o� �d�o� �C�o�r�e�l�D�R�A�W� �s�e�m� �e�s�c�o�l�h�e�r� �a� �c�o�n�f�i�g�u�r�a���o� �'�a�t�r�i�b�u�t�o�s� �d�e� �a�p�r�e�s�e�n�t�a���o�'� �������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem���@�d�e�v�i�d�o� �a� �u�m� �e�r�r�o� �d�e� �r�e�n�d�e�r�i�z�a���o�������due to a rendering error���LogoItem���d�d�e�v�i�d�o� �a� �u�m� �p�r�o�b�l�e�m�a� �n�o� �x�m�l�:� �%�1� �l�i�n�h�a�:�%�2� �c�o�l�u�n�a�:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem����p�o�r� �r�a�z��e�s� �d�e�s�c�o�n�h�e�c�i�d�a�s�-�-�p�o�s�s��v�e�l�m�e�n�t�e� �o� �a�r�q�u�i�v�o� �d�e� �i�m�a�g�e�m� �e�s�t�� �c�o�r�r�o�m�p�i�d�o�������9for unknown reasons--possibly the image file is corrupted���LogoItem��� �f�o�r�m�a�������shape���LogoItem���x�%�1� �d�e� �%�2� �r�e�d�e�s� �r�o�t�e�a�d�a�s� �-� �%�n� �c�o�n�e�c�t�o�r�(�e�s�)� �a� �s�e�r�e�m� �r�o�t�e�a�d�o�(�s�)���x�%�1� �d�e� �%�2� �r�e�d�e�s� �r�o�t�e�a�d�a�s� �-� �%�n� �c�o�n�e�c�t�o�r�(�e�s�)� �a� �s�e�r�e�m� �r�o�t�e�a�d�o�(�s�)�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow��� �&�S�o�b�r�e�������&About��� MainWindow����&�S�o�b�r�e� �Q�T������� &About Qt��� MainWindow����&�T�a�m�a�n�h�o� �R�e�a�l������� &Actual Size��� MainWindow���.�&�A�d�i�c�i�o�n�a�r� �a�o� �p�a�c�o�t�e�.�.�.�������&Add to bin...��� MainWindow����&�C�o�p�i�a�r�������&Copy��� MainWindow���H�&�C�r�i�a�r� �t�r�i�l�h�a� �a� �p�a�r�t�i�r� �d�e� �e�m�a�r�a�n�h�a�d�o�������&Create trace from ratsnest��� MainWindow���B�&�C�r�i�a�r� �f�i�o� �a� �p�a�r�t�i�r� �d�e� �e�m�a�r�a�n�h�a�d�o�������&Create wire from ratsnest��� MainWindow����&�C�o�r�t�a�r�������&Cut��� MainWindow����&�A�p�a�g�a�r�������&Delete��� MainWindow����&�A�p�a�g�a�r� �F�i�o������� &Delete Wire��� MainWindow����&�D�e�s�m�a�r�c�a�r������� &Deselect��� MainWindow����&�D�u�p�l�i�c�a�r������� &Duplicate��� MainWindow����&�E�d�i�t�a�r�������&Edit��� MainWindow����&�E�x�p�o�r�t�a�r�������&Export��� MainWindow����&�E�x�p�o�r�t�a�r�.�.�.�.������� &Export...��� MainWindow����&�A�r�q�u�i�v�o�������&File��� MainWindow���"�&�A�j�u�s�t�a�r� �� �j�a�n�e�l�a�������&Fit in Window��� MainWindow���.�&�I�n�v�e�r�t�e�r� �n�a� �H�o�r�i�z�o�n�t�a�l�������&Flip Horizontal��� MainWindow���*�&�I�n�v�e�r�t�e�r� �n�a� �V�e�r�t�i�c�a�l�������&Flip Vertical��� MainWindow��� �&�A�j�u�d�a�������&Help��� MainWindow���2�&�O�c�u�l�t�a�r� �t�o�d�a�s� �a�s� �c�a�m�a�d�a�s�������&Hide All Layers��� MainWindow���r�&�I�m�p�o�r�t�a�r� �c�o�m�p�o�n�e�n�t�e�s� �e� �p�a�c�o�t�e�s� �d�e� �u�m�a� �v�e�r�s��o� �a�n�t�e�r�i�o�r�.�.�.�������*&Import parts and bins from old version...��� MainWindow����&�M�i�n�i�m�i�z�a�r������� &Minimize��� MainWindow����&�A�b�r�i�r� �E�x�e�m�p�l�o������� &Open Example��� MainWindow���0�&�A�b�r�i�r� �A�r�q�u�i�v�o�s� �R�e�c�e�n�t�e�s�������&Open Recent Files��� MainWindow����&�A�b�r�i�r�.�.�.�������&Open...��� MainWindow����&�C�o�m�p�o�n�e�n�t�e�������&Part��� MainWindow��� �&�C�o�l�a�r�������&Paste��� MainWindow��� �&�P�r�e�f�e�r��n�c�i�a�s�.�.�.�������&Preferences...��� MainWindow����&�I�m�p�r�i�m�i�r�.�.�.������� &Print...��� MainWindow��� �&�S�a�i�r�������&Quit��� MainWindow����&�R�o�t�e�a�m�e�n�t�o�������&Routing��� MainWindow����&�S�a�l�v�a�r�������&Save��� MainWindow����&�S�a�l�v�a�r� �C�o�m�o�.�.�.������� &Save As...��� MainWindow��� �&�S�e�l�e�c�i�o�n�a�r� �t�u�d�o������� &Select All��� MainWindow���2�&�M�o�s�t�r�a�r� �t�o�d�a�s� �a�s� �c�a�m�a�d�a�s�������&Show All Layers��� MainWindow���&�&�M�o�s�t�r�a�r� �P�r�o�t�o�b�o�a�r�d�������&Show Breadboard��� MainWindow����&�M�o�s�t�r�a�r� �P�C�B������� &Show PCB��� MainWindow���(�&�M�o�s�t�r�a�r� �E�s�q�u�e�m��t�i�c�o�������&Show Schematic��� MainWindow���B�&�M�o�s�t�r�a�r� �a� �e�t�i�q�u�e�t�a� �d�o� �c�o�m�p�o�n�e�n�t�e�������&Show part label��� MainWindow��� �&�V�i�s��o�������&View��� MainWindow����&�J�a�n�e�l�a�������&Window��� MainWindow����&�C�o�r� �d�o�s� �f�i�o�s������� &Wire Color��� MainWindow����&�M�a�i�s� �Z�o�o�m�������&Zoom In��� MainWindow����&�M�e�n�o�s� �Z�o�o�m������� &Zoom Out��� MainWindow���(�T�a�m�a�n�h�o� �1�0�0�%� �(�p�i�x�e�l�)�������100% (pixel) size��� MainWindow����T�a�m�a�n�h�o� �1�0�0�%������� 100% Size��� MainWindow���@�T�a�m�a�n�h�o� �r�e�a�l� �(�m�u�n�d�o� �f��s�i�c�o� �r�e�a�l�)�������!Actual (real world physical) size��� MainWindow����T�a�m�a�n�h�o� �A�t�u�a�l������� Actual Size��� MainWindow���2�A�d�i�c�i�o�n�a�r� �p�o�n�t�o� �d�e� �f�l�e�x��o������� Add Bendpoint��� MainWindow����A�d�i�c�i�o�n�a�r� �N�o�t�a�������Add Note��� MainWindow���^�A�d�i�c�i�o�n�a�r� �u�m� �p�o�n�t�o� �d�e� �f�l�e�x��o� �a�o� �f�i�o� �s�e�l�e�c�i�o�n�a�d�o�������$Add a bendpoint to the selected wire��� MainWindow���$�A�d�i�c�i�o�n�a�r� �u�m�a� �n�o�t�a������� Add a note��� MainWindow���X�A�d�i�c�i�o�n�a�r� �o� �c�o�m�p�o�n�e�n�t�e� �s�e�l�e�c�i�o�n�a�d�o� �a�o� �p�a�c�o�t�e�������Add selected part to bin��� MainWindow���B�A�l�i�n�h�a�r� �i�t�e�n�s� �� �g�r�a�d�e� �a�o� �a�r�r�a�s�t�a�r�������!Align items to grid when dragging��� MainWindow����A�l�i�n�h�a�r� �a� �g�r�a�d�e������� Align to Grid��� MainWindow��� �T�o�d�o�s�������All��� MainWindow���R�T�o�d�o�s� �o�s� �t�r�a��o�s� �a�i�n�d�a� �n��o� �f�o�r�a�m� �r�o�t�e�a�d�o�s�.�������$All traces have not yet been routed.��� MainWindow����A�u�t�o�r�o�t�e�a�m�e�n�t�o������� Autoroute��� MainWindow���,�A�u�t�o�r�o�t�e�i�e� �c�o�n�e�x��e�s�.�.�.�������Autoroute connections...��� MainWindow���H�C�o�n�f�i�g�u�r�a���e�s� �d�o� �a�u�t�o�r�o�t�e�a�d�o�r�/�D�R�C�.�.�.�������Autorouter/DRC settings...��� MainWindow���<�P�r�o�g�r�e�s�s�o� �d�e� �a�u�t�o�r�o�t�e�a�m�e�n�t�o�.�.�.�������Autorouting Progress...��� MainWindow����A�u�t�o�r�o�t�e�a�n�d�o�.�.�.�������Autorouting...��� MainWindow����V�o�l�t�a�n�d�o� �a� �'�%�1�'�������Backing up '%1'��� MainWindow���8�B�o�M� �a�r�q�u�i�v�o� �d�e� �T�e�x�t�o� �(�*�h�t�m�l�)�������BoM Text File (*.html)��� MainWindow����A�m�b�a�s� �C�a�m�a�d�a�s������� Both Layers��� MainWindow����C�a�m�a�d�a� �I�n�f�e�r�i�o�r������� Bottom Layer��� MainWindow����P�r�o�t�o�b�o�a�r�d������� Breadboard��� MainWindow���(�T�r�a�z�e�r� �p�a�r�a� �a� �f�r�e�n�t�e������� Bring Forward��� MainWindow���l�T�r�a�z�e�r� �o�s� �o�b�j�e�t�o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �p�a�r�a� �a� �f�r�e�n�t�e� �d�a� �c�a�m�a�d�a�������/Bring selected object(s) forward in their layer��� MainWindow���l�T�r�a�z�e�r� �o�s� �o�b�j�e�t�o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �p�a�r�a� �a� �f�r�e�n�t�e� �d�a� �c�a�m�a�d�a�������0Bring selected object(s) to front of their layer��� MainWindow���(�T�r�a�z�e�r� �p�a�r�a� �a� �f�r�e�n�t�e�������Bring to Front��� MainWindow����C�a�n�c�e�l�a�r�������Cancel��� MainWindow���P�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�n�c�o�n�t�r�a�r� �o� �a�r�q�u�i�v�o� �%�1�.�������Cannot find file %1.��� MainWindow���8�N��o� �f�o�i� �p�o�s�s��v�e�l� �i�m�p�r�i�m�i�r� �%�1�������Cannot print to %1��� MainWindow���P�N��o� �f�o�i� �p�o�s�s��v�e�l� �l�e�r� �o� �a�r�q�u�i�v�o� �1� �%�1�:� �%�2�.�������Cannot read file 1 %1: %2.��� MainWindow���X�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�s�c�r�e�v�e�r� �n�o� �a�r�q�u�i�v�o� �%�1�:� �%�2�.�������Cannot write file %1: %2.��� MainWindow���(�M�u�d�a�r� �i�m�a�g�e�m� �p�a�r�a� �%�2�������Change image to %2��� MainWindow���8�M�u�d�a�r� �p�a�r�a� �p�c�b� �d�e� �u�m�a� �c�a�m�a�d�a�������Change to single layer pcb��� MainWindow���<�M�u�d�a�r� �p�a�r�a� �p�c�b� �d�e� �d�u�a�s� �c�a�m�a�d�a�s�������Change to two layer pcb��� MainWindow���2�C�h�e�c�a�r� �T�r�i�l�h�a�s� �C�a�r�r�e�g�a�d�a�s�������Check Loaded Traces��� MainWindow���2�V�e�r�i�f�i�c�a�r� �a�t�u�a�l�i�z�a���e�s�.�.�.�������Check for updates...��� MainWindow����V�e�r� �s�e� �u�m�a� �n�o�v�a� �v�e�r�s��o� �d�o� �F�r�i�t�z�i�n�g� �e�n�c�o�n�t�r�a�-�s�e� �d�i�s�p�o�n��v�e�l� �p�a�r�a� �d�o�w�n�l�o�a�d�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���l�E�s�c�o�l�h�e�r� �p�o�n�t�o�(�s�)� �d�e� �a�t�e�r�r�a�m�e�n�t�o� �p�a�r�a� �p�r�e�e�n�c�h�i�m�e�n�t�o�.�.�.�������Choose Ground Fill Seed(s)...��� MainWindow���>�E�s�c�o�l�h�a� �u�m�a� �p�a�s�t�a� �p�a�r�a� �e�x�p�o�r�t�a�r�������Choose a folder for exporting��� MainWindow���8�L�i�m�p�a�r� �P�o�n�t�o�s� �d�e� �A�t�e�r�r�a�m�e�n�t�o�������Clear Ground Fill Seeds��� MainWindow����L�i�m�p�a�r� �t�o�d�a�s� �o�s� �p�o�n�t�o�s� �d�e� �a�t�e�r�r�a�m�e�n�t�o�-�-�p�e�r�m�i�t�i�r� �p�r�e�e�n�c�h�i�m�e�n�t�o� �c�o�m�u�m� �d�e� �c�o�b�r�e�.�������1Clear ground fill seeds--enable copper fill only.��� MainWindow��� �C��d�i�g�o�������Code��� MainWindow����C�o�n�v�e�r�t�e�r�������Convert��� MainWindow���D�C�o�n�v�e�r�t�e�r� �P�o�n�t�o� �d�e� �F�l�e�x��o� �p�a�r�a� �V�i�a�������Convert Bendpoint to Via��� MainWindow���D�C�o�n�v�e�r�t�e�r� �V�i�a� �p�a�r�a� �P�o�n�t�o� �d�e� �F�l�e�x��o�������Convert Via to Bendpoint��� MainWindow���H�C�o�n�v�e�r�t�e�r� �o� �p�o�n�t�o� �d�e� �f�l�e�x��o� �p�a�r�a� �v�i�a�������Convert the bendpoint to a via��� MainWindow���D�C�o�n�v�e�r�t�e�r� �v�i�a� �p�a�r�a� �p�o�n�t�o� �d�e� �f�l�e�x��o�������Convert the via to a bendpoint��� MainWindow���F�C�a�m�a�d�a� �i�n�f�e�r�i�o�r� �d�e� �c�o�b�r�e� �e�s�t�� �a�t�i�v�a�������Copper Bottom layer is active��� MainWindow���,�P�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e������� Copper Fill��� MainWindow���b�C�a�m�a�d�a�s� �d�e� �C�o�b�r�e� �s�u�p�e�r�i�o�r� �e� �i�n�f�e�r�i�o�r� �e�s�t��o� �a�t�i�v�o�s�������3Copper Top and Copper Bottom layers are both active��� MainWindow���F�C�a�m�a�d�a� �s�u�p�e�r�i�o�r� �d�e� �c�o�b�r�e� �e�s�t�� �a�t�i�v�a�������Copper Top layer is active��� MainWindow���$�C�o�p�i�a�r� �s�e�l�e�c�i�o�n�a�d�o�������Copy selection��� MainWindow���>�N��o� �f�o�i� �p�o�s�s��v�e�l� �o�b�t�e�r� �o� �w�i�d�g�e�t�������Couldn't get the dock widget��� MainWindow���(�C�r�i�a�r� �u�m� �n�o�v�o� �s�k�e�t�c�h�������Create a new sketch��� MainWindow���X�C�r�i�a�r� �t�r�i�l�h�a� �a� �p�a�r�t�i�r� �d�e� �l�i�n�h�a� �d�e� �e�m�a�r�a�n�h�a�d�o�������%Create a trace from the ratsnest line��� MainWindow���R�C�r�i�a�r� �f�i�o� �a� �p�a�r�t�i�r� �d�e� �l�i�n�h�a� �d�e� �e�m�a�r�a�n�h�a�d�o�������$Create a wire from the ratsnest line��� MainWindow���$�C�o�r�t�a�r� �s�e�l�e�c�i�o�n�a�d�o������� Cut selection��� MainWindow���&�P�r�o�g�r�e�s�s�o� �d�a� �D�R�C�.�.�.�������DRC Progress...��� MainWindow���$�S�a��d�a� �d�o� �d�e�p�u�r�a�d�o�r�������Debugger Output��� MainWindow��� �A�p�a�g�a�r�������Delete��� MainWindow����A�p�a�g�a�r� �M�e�n�o�s������� Delete Minus��� MainWindow���&�A�p�a�g�a�r� �F�i�a���o� �d�e� �N��������Delete Ratsnest Line��� MainWindow����A�p�a�g�a�r� �f�i�o������� Delete Wire��� MainWindow���>�A�p�a�g�a�r� �F�i�o� �a�t�� �p�o�n�t�o�s� �d�e� �f�l�e�x��o�������Delete Wire up to bendpoints��� MainWindow���$�A�p�a�g�a�r� �s�e�l�e�c�i�o�n�a�d�o�������Delete selection��� MainWindow���D�A�p�a�g�a�r� �s�e�l�e���o� �s�e�m� �f�i�o�s� �c�o�n�e�c�t�a�d�o�s�������'Delete selection without attached wires��� MainWindow����D�e�s�m�a�r�c�a�r�������Deselect��� MainWindow���D�C�h�e�c�a�g�e�m� �d�e� �R�e�g�r�a�s� �d�e� �D�e�s�i�g�n� �(�D�R�C�)�������Design Rules Check (DRC)��� MainWindow���,�D�e�s�l�i�g�a�r� �t�o�d�o�s� �o�s� �f�i�o�s�������Disconnect All Wires��� MainWindow���\�D�e�s�l�i�g�a�r� �t�o�d�o�s� �o�s� �f�i�o�s� �l�i�g�a�d�o�s� �a� �e�s�t�e� �c�o�n�e�c�t�o�r�������0Disconnect all wires connected to this connector��� MainWindow���l�M�o�s�t�r�a�r� �a�j�u�d�a� �d�o� �E�d�i�t�o�r� �d�e� �C�o�m�p�o�n�e�n�t�e�s� �e�m� �u�m� �n�a�v�e�g�a�d�o�r�������&Display Parts Editor help in a browser��� MainWindow���\�M�o�s�t�r�a�r� �a�l�g�u�m�a�s� �d�i�c�a�s� �e� �t�r�u�q�u�e�s� ��t�e�i�s� �F�r�i�t�z�i�n�g�������+Display some handy Fritzing tips and tricks��� MainWindow���d�M�o�s�t�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�o� �p�a�c�o�t�e� �n�a� �v�i�s�t�a� �d�e� �l�i�s�t�a�������$Display the parts bin in a list view��� MainWindow���d�M�o�s�t�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�o� �p�a�c�o�t�e� �n�a� �v�i�s�t�a� �d�e� ��c�o�n�e�������%Display the parts bin in an icon view��� MainWindow���0�N��o� �f�a�z�e�r� �e�n�c�a�m�i�n�h�a�m�e�n�t�o�������Do not autoroute��� MainWindow���V�V�o�c�� �q�u�e�r� �m�a�n�t�e�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �i�m�p�o�r�t�a�d�o�s�?�������'Do you want to keep the imported parts?��� MainWindow���6�Q�u�e�r� �c�o�n�t�i�n�u�a�r� �m�e�s�m�o� �a�s�s�i�m�?�������Do you want to proceed anyway?��� MainWindow���(�D�o�a�r� �p�a�r�a� �o� �F�r�i�t�z�i�n�g�������Donate to Fritzing��� MainWindow���(�D�u�p�l�i�c�a�r� �s�e�l�e�c�i�o�n�a�d�o�������Duplicate selection��� MainWindow���J�E�d�i�t�a�r� �(�c�r�i�a�d�o�r� �d�e� �n�o�v�o�s� �c�o�m�p�o�n�e�n�t�e�s�)�������Edit (new parts editor)��� MainWindow���8�A�t�i�v�a�r� �r�e�g�i�s�t�r�o� �d�e� �d�e�p�u�r�a���o�������Enable debugging log��� MainWindow����D�i�g�i�t�e� �o� �T�e�x�t�o������� Enter Text��� MainWindow����S�� �p�o�d�e�m�o�s� �e�x�p�o�r�t�a�r� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�-�-�s�e�l�e�c�i�o�n�e� �a� �p�l�a�c�a� �q�u�e� �d�e�s�e�j�a� �e�x�p�o�r�t�a�r�.�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow���t�E�x�p�o�r�t�a�r� �o� �c�o�m�p�o�n�e�n�t�e� �n�e�s�t�a� �v�i�s��o� �e�m� �1�0�0�0� �d�p�i� �S�V�G� �A�c�h�a�t�a�d�o�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���d�E�x�p�o�r�t�a�r� �o� �c�o�m�p�o�n�e�n�t�e� �n�e�s�t�a� �v�i�s��o� �e�m� �1�0�0�0� �d�p�i� �S�V�G� �������-Export 1000 dpi SVG of this part in this view��� MainWindow���F�E�x�p�o�r�t�a�r� �l�i�s�t�a� �d�e� �m�a�t�e�r�i�a�l� �(�B�o�M�)�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���*�E�x�p�o�r�t�a�r� �a� �N�e�t�l�i�s�t�.�.�.�������Export Netlist...��� MainWindow���B�E�x�p�o�r�t�a�r� �S�V�G� �A�c�h�a�t�a�d�o� �N�o�r�m�a�l�i�z�a�d�o�������Export Normalized Flattened SVG��� MainWindow���0�E�x�p�o�r�t�a�r� �S�V�G� �N�o�r�m�a�l�i�z�a�d�o�������Export Normalized SVG��� MainWindow���F�E�x�p�o�r�t�a�r� �l�i�s�t�a� �d�e� �c�o�n�e�x��e�s� �S�P�I�C�E�.�.�.�������Export SPICE Netlist...��� MainWindow��� �E�x�p�o�r�t�a�r� �S�V�G�.�.�.�.������� Export SVG...��� MainWindow����E�x�p�o�r�t�a�r� �P�C�B�������Export for PCB��� MainWindow���8�E�x�p�o�r�t�a�r� �a� �p�a�r�t�e� �s�e�l�e�c�i�o�n�a�d�a�������Export selected part��� MainWindow���V�E�x�p�o�r�t�a�r� �o� �s�k�e�t�c�h� �a�t�u�a�l� �c�o�m�o� �u�m�a� �i�m�a�g�e�m� �S�V�G�������)Export the current sketch as an SVG image��� MainWindow���L�E�x�p�o�r�t�a�r� �o� �s�k�e�t�c�h� �a�t�u�a�l� �p�a�r�a� �E�a�g�l�e� �C�A�D�������&Export the current sketch to Eagle CAD��� MainWindow����E�x�p�o�r�t�a�r� �o� �d�e�s�e�n�h�o� �a�c�t�u�a�l� �p�a�r�a� �o� �f�o�r�m�a�t�o� �E�x�t�e�n�d�e�d� �G�e�r�b�e�r� �(�R�S�-�2�7�4�X�)� �p�a�r�a� �p�r�o�d�u���o� �p�r�o�f�i�s�s�i�o�n�a�l� �d�e� �P�C�B�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow����E�x�p�o�r�t�a�r� �o� �d�e�s�e�n�h�o� �a�t�u�a�l� �p�a�r�a� �P�D�F� �p�a�r�a� �D�I�Y� �p�r�o�d�u���o� �d�e� �P�C�B� �(�f�o�t�o�r�e�s�i�s�t�i�v�o�)�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow����E�x�p�o�r�t�a�r� �o� �d�e�s�e�n�h�o� �a�t�u�a�l� �p�a�r�a� �S�V�G� �p�a�r�a� �D�I�Y� �p�r�o�d�u���o� �d�e� �P�C�B� �(�f�o�t�o�r�e�s�i�s�t�i�v�o�)�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���t�E�x�p�o�r�t�e� �a� ��r�e�a� �v�i�s��v�e�l� �d�o� �s�k�e�t�c�h� �a�t�u�a�l� �c�o�m�o� �u�m�a� �i�m�a�g�e�m� �J�P�G��������E�s�c�o�n�d�e�r� �e�t�i�q�u�e�t�a� �d�o� �c�o�m�p�o�n�e�n�t�e�������Hide part label��� MainWindow���@�E�s�c�o�n�d�e�r� �i�m�p�r�e�s�s��o� �d�e� �c�o�m�p�o�n�e�n�t�e�������Hide part silkscreen��� MainWindow����E�s�c�o�n�d�e�r�/�m�o�s�t�r�a�r� �c�a�m�a�d�a� �d�e� �i�m�p�r�e�s�s��o� �a�p�e�n�a�s� �p�a�r�a� �e�s�t�e� �c�o�m�p�o�n�e�n�t�e�������1Hide/show the silkscreen layer for only this part��� MainWindow���R�D�e�s�t�a�c�a�r� �t�o�d�o�s� �o�s� �c�o�n�e�c�t�o�r�e�s� �n��o� �r�o�t�e�a�d�o�s�������!Highlight all unrouted connectors��� MainWindow����D�e�s�t�a�c�a�r� �q�u�a�i�s�q�u�e�r� �c�o�m�p�o�n�e�n�t�e�s� �q�u�e� �e�s�t�e�j�a�m� �p�r��x�i�m�o�s� �d�e�m�a�i�s� �p�a�r�a� �u�m�a� �p�r�o�d�u���o� �s�e�g�u�r�a� �d�a� �p�l�a�c�a�������JHighlights any parts that are too close together for safe board production��� MainWindow�������KHow much would it could to produce a PCB from this sketch with Fritzing Fab��� MainWindow����S�e� �u�m� �c�o�m�p�o�n�e�n�t�e� �"�g�r�u�d�e�n�t�o�"� �f�o�r� �m�o�v�i�d�o�,� �c�o�m�p�o�n�e�n�c�e�s� �e�m� �c�i�m�a� �d�e�l�e�s� �t�a�m�b��m� �s�e�r��o�������>If a "sticky" part is moved, parts on top of it are also moved��� MainWindow���r�I�m�p�o�r�t�a�r� �c�o�m�p�o�n�e�n�t�e�s� �e� �p�a�c�o�t�e�s� �d�e� �u�m�a� �i�n�s�t�a�l�a���o� �a�n�t�e�r�i�o�r�������0Import parts and bins from previous installation��� MainWindow����P�r�o�p�r�i�e�d�a�d�e�s������� Inspector��� MainWindow��F�N��o� �p�a�r�e�c�e� �p�o�s�s��v�e�l� �d�e�t�e�r�m�i�n�a�l� �o� �a�t�u�a�l� �t�a�m�a�n�h�o� �d�o� �m�o�n�i�t�o�r� �a�u�t�o�m�a�t�i�c�a�m�e�n�t�e�,� �e�n�t��o� �o� �'�t�a�m�a�n�h�o� �a�t�u�a�l�'� �c�o�m�o� �e�s�t�� �i�m�p�l�e�m�e�n�t�a�d�o� �� �a�p�e�n�a�s� �u�m� �c�h�u�t�e�.� �S�u�a� �m�e�l�h�o�r� �a�p�o�s�t�a� �d�e�v�e� �s�e�r� �u�t�i�l�i�z�a�r� �a� �c�o�m�p�o�n�e�n�t�e� �d�e� �r�e�g�u�a�,� �d�e�p�o�i�s� �c�o�l�o�c�a�r� �u�m�a� �r��g�u�a� �r�e�a�l� �p�o�r� �c�i�m�a� �d�e�l�a�,� �e� �d�a�r� �z�o�o�m� �a�t�� �q�u�e� �s�e�u�s� �t�a�m�a�n�h�o�s� �s�e�j�a�m� �i�g�u�a�i�s�.������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow���&�I�m�a�g�e�m� �J�P�E�G� �(�*�.�j�p�g�)�������JPEG Image (*.jpg)��� MainWindow����I�n�i�c�i�a�r� �%�1�.�.�.������� Launch %1...��� MainWindow����C�a�m�a�d�a�s�������Layers��� MainWindow���Z�L�i�s�t�a� �d�e� �c�o�m�p�o�n�e�n�t�e�s� �(�&�L�i�s�t�a� �d�e� �M�a�t�e�r�i�a�i�s�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow����c�a�r�r�e�g�a�n�d�o�.�.�.������� Loading...��� MainWindow���&�B�l�o�q�u�e�a�r� �c�o�m�p�o�n�e�n�t�e������� Lock Part��� MainWindow���n�M�a�i�n�W�i�n�d�o�w�:�:�m�o�v�e�T�o�P�a�r�t�s�F�o�l�d�e�r� �j�a�n�e�l�a� �p�r�i�n�c�i�p�a�l� �f�a�l�t�a�n�d�o�������0MainWindow::moveToPartsFolder mainwindow missing��� MainWindow����M�a�i�n�W�i�n�d�o�w�:�:�p�o�p�u�l�a�t�e�M�e�n�u�W�i�t�h�I�n�d�e�x�:� �N��o� �f�o�i� �p�o�s�s��v�e�l� �c�a�r�r�e�a�g�a�r� �o� �e�x�e�m�p�l�o� �c�o�m� �a� �i�d�=�'�%�1�'�������EMainWindow::populateMenuWithIndex: couldn't load example with id='%1'��� MainWindow���0�M�i�n�i�m�i�z�a�r� �a� �j�a�n�e�l�a� �a�t�u�a�l�������Minimize current window��� MainWindow���M�o�v�e�r� �o�s� �t�r�a��o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �p�a�r�a� �o�u�t�r�o� �l�a�d�o� �d�a� �p�l�a�c�a� �(�n�o�t�a�:� �o� �'�p�r�i�m�e�i�r�o�'� �t�r�a��o� �s�e�r�� �m�o�v�i�d�o� �e� �o� �r�e�s�t�a�n�t�e� �s�e�g�u�i�r�� �p�a�r�a� �o� �m�e�s�m�o� �l�a�d�o�)�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���4�M�o�v�e�r� �p�a�r�a� �c�a�m�a�d�a� �i�n�f�e�r�i�o�r�������Move to bottom layer��� MainWindow���@�M�o�v�e�r� �p�a�r�a� �o� �o�u�t�r�o� �l�a�d�o� �d�a� �p�l�a�c�a�������Move to other side of the board��� MainWindow���4�M�o�v�e�r� �p�a�r�a� �c�a�m�a�d�a� �s�u�p�e�r�i�o�r�������Move to top layer��� MainWindow����N�o�v�o�������New��� MainWindow���N�N��o� �f�o�i� �e�n�c�o�n�t�r�a�d�o� �E�s�q�u�e�m��a�t�i�c�o� �e�m� �'�%�1�'�������No Sketch found in '%1'��� MainWindow���@�N��o� �e�x�i�s�t�e�m� �l�i�g�a���e�s� �p�a�r�a� �r�o�t�e�a�r�������No connections to route��� MainWindow���>�S�e�m� �c�a�m�a�d�a� �s�u�p�e�r�f�i�c�i�a�l� �d�e� �c�o�b�r�e�������No copper top layer��� MainWindow����N��o� �f�o�i� �e�n�c�o�n�t�r�a�d�a� �u�m�a� �c�o�r�r�e�s�p�o�n�d��n�c�i�a� �a� �u�m� �c�o�m�p�o�n�e�n�t�e�;� �o� �F�r�i�t�z�i�n�g� �v�a�i� �e�s�c�o�l�h�e�r� �o� �m�a�i�s� �a�d�e�q�u�a�d�o�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow����N��o� �f�o�r�a�m� �e�n�c�o�n�t�r�a�d�o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�e�s�a�t�u�a�l�i�z�a�d�o�s�.� �T�o�d�o�s� �o�s� �s�e�u�s� �c�o�m�p�o�n�e�n�t�e�s� �e�s�t��o� �a�t�u�a�l�i�z�a�d�o�s�.�������7No outdated parts found. All your parts are up-to-date.��� MainWindow��>�N��o� �e�x�i�s�t�e� �u�m� �c�o�m�p�o�n�e�n�t�e� �c�o�m� �e�s�s�a�s� �c�a�r�a�c�t�e�r��s�t�i�c�a�s�.� �E�s�t�a�m�o�s� �t�r�a�b�a�l�h�a�n�d�o� �p�a�r�a� �e�v�i�t�a�r� �e�s�t�a� �m�e�n�s�a�g�e�m�,� �e� �a�p�e�n�a�s� �d�e�i�x�a�r� �v�o�c�� �e�s�c�o�l�h�e�r� �e�n�t�r�e� �p�r�o�p�r�i�e�d�a�d�e�s� �q�u�e� �e�x�i�s�t�e�m�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���d�N�e�n�h�u�m� �c�o�m�p�o�n�e�n�t�e� �f�o�i� �e�n�c�o�n�t�r�a�d�o� �c�o�m� �o� �t�e�r�m�o� �'�%�1�'�.�������"No parts matched search term '%1'.��� MainWindow���@�R�e�f�e�r��n�c�i�a� �d�e� �C�o�m�p�o�n�e�n�t�e�s� �O�n�l�i�n�e�������Online Parts Reference��� MainWindow���4�G�a�l�e�r�i�a� �d�e� �P�r�o�j�e�t�o�s� �O�n�l�i�n�e�������Online Projects Gallery��� MainWindow��� �T�u�t�o�r�i�a�i�s� �O�n�l�i�n�e�������Online Tutorials��� MainWindow���P�A�b�r�i�r� �a� �p��g�i�n�a� �w�e�b� �d�e� �d�o�n�a�t�i�v�o�s� �F�r�i�t�z�i�n�g�������Open Fritzing donation web page��� MainWindow���:�A�b�r�i�r� �o�s� �e�x�e�m�p�l�o�s� �d�o� �F�r�i�t�z�i�n�g�������Open Fritzing examples��� MainWindow���2�A�b�r�i�r� �a� �a�j�u�d�a� �d�o� �F�r�i�t�z�i�n�g�������Open Fritzing help��� MainWindow���D�A�b�r�i�r� �a� �r�e�f�e�r��n�c�i�a� �d�o�s� �c�o�m�p�o�n�e�n�t�e�s�������Open Parts Reference��� MainWindow���A�b�r�a� �u�m� �e�s�q�u�e�m��t�i�c�o� �F�r�i�t�z�i�n�g� �(�.�f�z�z�,� �.�f�z�)�,� �o�u� �c�a�r�r�e�g�a�r� �u�m� �c�o�m�p�o�n�e�n�t�e� �F�r�i�t�z�i�n�g� �(�.�f�z�p�z�)�,� �o�u� �u�m� �p�a�c�o�t�e� �F�r�i�t�z�i�n�g� �d�e� �c�o�m�p�o�n�e�n�t�e�s� �(�.�f�z�b�,� �.�f�z�b�z�)�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���f�A�b�r�i�r� �a� �j�a�n�e�l�a� �d�e� �p�r�o�g�r�a�m�a���o� �d�e� �m�i�c�r�o�c�o�n�t�r�o�l�a�d�o�r�e�s�������'Open microcontroller programming window��� MainWindow���6�A�b�r�i�r� �j�a�n�e�l�a� �d�e� �p�r�o�g�r�a�m�a���o�������Open programming window��� MainWindow���v�A�b�r�i�r� �e�d�i�t�o�r� �d�e� �n�o�v�o�s� �c�o�m�p�o�n�e�n�t�e�s� �p�a�r�a� �c�o�m�p�o�n�e�n�t�e� �e�x�i�s�t�e�n�t�e�������-Open the new parts editor on an existing part��� MainWindow����E�n�c�o�m�e�n�d�a�r� �o� �P�C�B� �c�r�i�a�d�o� �a� �p�a�r�t�i�r� �d�o� �s�e�u� �e�s�q�u�e�m��t�i�c�o�-�-�p�r�o�d�u�z�i�d�o� �p�e�l�o� �f�a�b�u�l�o�s�o� �F�r�i�t�z�i�n�g� �F�a�b�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow����C�o�m�p�r�a�r� �P�C�B�.�.�.�������Order a PCB...��� MainWindow���4�C�o�m�p�o�n�e�n�t�e�s� �d�e�s�a�t�u�a�l�i�z�a�d�o�s�������Outdated parts��� MainWindow���$�I�m�a�g�e�m� �P�N�G� �(�*�.�p�n�g�)�������PNG Image (*.png)��� MainWindow��� �O�p���e�s� �d�a� �P��g�i�n�a������� Page Setup��� MainWindow���<�A�j�u�d�a� �d�o� �E�d�i�t�o�r� �d�e� �C�o�m�p�o�n�e�n�t�e�s�������Parts Editor Help��� MainWindow���:�C�o�l�a�r� �o� �c�o�n�t�e��d�o� �d�o� �c�l�i�p�b�o�a�r�d�������Paste clipboard contents��� MainWindow���L�C�o�l�a�r� �o� �c�o�n�t�e��d�o� �d�o� �c�l�i�p�b�o�a�r�d� �n�o� �l�o�c�a�l�������!Paste clipboard contents in place��� MainWindow����C�o�l�a�r� �n�o� �L�o�c�a�l�������Paste in Place��� MainWindow���f�P�o�r� �f�a�v�o�r� �s�e�l�e�c�i�o�n�e� �a� �p�a�s�t�a� �d�o� �F�r�t�i�z�i�n�g� �a�n�t�e�r�i�o�r�.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow����F�a�v�o�r� �s�e�l�e�c�i�o�n�a�r� �u�m�a� �P�C�B�-�-�p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e� �f�u�n�c�i�o�n�a� �a�p�e�n�a�s� �e�m� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow����F�a�v�o�r� �s�e�l�e�c�i�o�n�a�r� �u�m�a� �P�C�B�-�-�o�p�e�r�a���e�s� �d�e� �p�r�e�e�n�c�h�i�m�e�n�t�o� �a�t�e�r�r�a�d�o� �f�u�n�c�i�o�n�a�m� �a�p�e�n�a�s� �e�m� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow����S�e�l�e�c�i�o�n�e� �u�m�a� �P�C�B�.� �O�p�e�r�a���e�s� �d�e� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e� �f�u�n�c�i�o�n�a�m� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow���~�F�a�v�o�r� �s�e�l�e�c�i�o�n�a�r� �u�m�a� �P�C�B�.� �O� �D�R�C� �f�u�n�c�i�o�n�a� �c�o�m� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow����F�a�v�o�r� �s�e�l�e�c�i�o�n�a�r� �p�l�a�c�a� �q�u�e� �d�e�s�e�j�a� �a�u�t�o�r�e�t�e�a�r�.� �O� �a�u�t�o�r�o�t�e�a�d�o�r� �s�u�p�o�r�t�a� �a�p�e�n�a�s� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow����F�a�v�o�r� �e�s�p�e�c�i�f�i�c�a�r� �u�m� �n�o�m�e� �p�a�r�a� �a�r�q�u�i�v�o� �.�f�z�z� �p�a�r�a� �s�a�l�v�a�r� �'�%�1�'� �p�a�r�a�������0Please specify an .fzz file name to save '%1' to��� MainWindow���N�P�u�b�l�i�c�a�r� �u�m� �p�r�o�j�e�t�o� �n�o� �w�e�b�s�i�t�e� �F�r�i�t�z�i�n�g�������&Post a project to the Fritzing website��� MainWindow���P�I�m�p�e�d�i�r� �q�u�e� �a�l�g�u�m� �c�o�m�p�o�n�e�n�t�e� �s�e�j�a� �m�o�v�i�d�o�������Prevent a part from being moved��� MainWindow���:�I�m�p�r�i�m�i�r� �a� �v�i�s�u�a�l�i�z�a���o� �a�t�u�a�l�������Print the current view��� MainWindow����I�m�p�r�i�m�i�n�d�o�.�.�.������� Printing...��� MainWindow����C�o�n�t�i�n�u�a�r�������Proceed��� MainWindow���"�S�a�i�r� �d�a� �a�p�l�i�c�a���o�������Quit the application��� MainWindow���"�L�e�v�a�n�t�a�r� �e� �B�a�i�x�a�r�������Raise and Lower��� MainWindow����M�o�d�o� �d�e� �L�e�i�t�u�r�a������� Read-only��� MainWindow��� �P�r�o�n�t�o�������Ready��� MainWindow����R�e�c�a�l�c�u�l�a�r� �s�t�a�t�u�s� �d�e� �r�o�t�e�a�m�e�n�t�o� �e� �f�i�o�s� �d�o� �e�m�a�r�a�n�h�a�d�o� �(�n�o� �c�a�s�o� �d�a� �a�t�u�a�l�i�z�a���o� �a�u�t�o�m��t�i�c�a� �n��o� �f�u�n�c�i�o�n�a�r� �c�o�r�r�e�t�a�m�e�n�t�e�)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow����R�e�t�r�o�c�e�d�e�r�������Redo��� MainWindow���0�R�e�c�a�r�r�e�g�a�r� �o� �e�s�q�u�e�m��t�i�c�o�������Reload the sketch��� MainWindow���.�R�e�m�o�v�e�r� �p�o�n�t�o� �d�e� �f�l�e�x��o�������Remove Bendpoint��� MainWindow���.�R�e�m�o�v�e�r� �C�a�m�a�d�a� �d�e� �c�o�b�r�e�������Remove Copper Fill��� MainWindow���.�R�e�m�o�v�e�r� �c�a�m�a�d�a� �d�e� �c�o�b�r�e�������Remove copper fill��� MainWindow���2�R�e�m�o�v�e�r� �a� �c�a�m�a�d�a� �d�e� �c�o�b�r�e�������Remove the copper fill��� MainWindow���&�R�e�p�o�r�t�a�r� �u�m� �e�r�r�o�.�.�.�������Report a bug...��� MainWindow���^�R�e�p�o�r�t�a�r� �u�m� �e�r�r�o� �q�u�e� �v�o�c�� �e�n�c�o�n�t�r�o�u� �n�o� �F�r�i�t�z�i�n�g�������%Report a but you've found in Fritzing��� MainWindow��� �R�e�s�t�a�u�r�a�r� �p�a�d�r��o�������Restore Default��� MainWindow����D�e�s�f�a�z�e�r�������Revert��� MainWindow����D�e�s�f�a�z�e�r�?�������Revert?��� MainWindow��� �G�i�r�a�r�������Rotate��� MainWindow���$�R�o�d�a�r� �1�8�0�� �{�1�8�0�?�}������� Rotate 180���� MainWindow���H�R�o�d�a�r� �1�3�5�� �n�o� �s�e�n�t�i�d�o� �H�o�r��r�i�o� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���P�R�o�d�a�r� �4�5�� �n�o� �s�e�n�t�i�d�o� �A�n�t�i�-�H�o�r��r�i�o� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow���H�R�o�d�a�r� �1�3�5�� �n�o� �s�e�n�t�i�d�o� �H�o�r��r�i�o� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���P�R�o�d�a�r� �4�5�� �n�o� �s�e�n�t�i�d�o� �A�n�t�i�-�H�o�r��r�i�o� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���X�G�i�r�a�r� �s�e�l�e���o� �a�t�u�a�l� �4�5� �g�r�a�u�s� �s�e�n�t�i�d�o� �h�o�r��r�i�o�������-Rotate current selection 45 degrees clockwise��� MainWindow���b�G�i�r�a�r� �s�e�l�e���o� �a�t�u�a�l� �4�5� �g�r�a�u�s� �s�e�n�t�i�d�o� �a�n�t�i�-�h�o�r��r�i�o�������5Rotate current selection 45 degrees counter clockwise��� MainWindow���b�G�i�r�a�r� �s�e�l�e���o� �a�t�u�a�l� �9�0� �g�r�a�u�s� �s�e�n�t�i�d�o� �a�n�t�i�-�h�o�r��r�i�o�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���V�G�i�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �s�e�l�e�c�i�o�n�a�d�o�s� �1�8�0� �g�r�a�u�s�������(Rotate the selected parts by 180 degrees��� MainWindow���p�G�i�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �s�e�l�e�c�i�o�n�a�d�o�s� �9�0�� �n�o� �s�e�n�t�i�d�o� �H�o�r��r�i�o�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow���&�R�o�t�e�a�m�e�n�t�o� �c�o�m�p�l�e�t�o�������Routing completed��� MainWindow���\�R�o�t�e�a�m�e�n�t�o� �c�o�m�p�l�e�t�o� �u�s�a�n�d�o� �%�n� �e�l�e�m�e�n�t�o�s� �j�u�m�p�e�r���b�R�o�t�e�a�m�e�n�t�o� �c�o�m�p�l�e�t�o� �u�s�a�n�d�o� �%�n� �e�l�e�m�e�n�t�o�s� �j�u�m�p�e�r�(�s�)�������)Routing completed using %n jumper part(s)��� MainWindow���4�L�i�s�t�a� �d�e� �c�o�n�e�x��e�s� �S�P�I�C�E�.�.�.�������SPICE Netlist...��� MainWindow���$�I�m�a�g�e�m� �S�V�G� �(�*�.�s�v�g�)�������SVG Image (*.svg)��� MainWindow����S�a�l�v�a�r� �%�1�������Save %1��� MainWindow���z�S�a�l�v�a�r� �a� �L�i�s�t�a� �d�e� �M�a�t�e�r�i�a�i�s� �(�B�o�M�)�/�L�i�s�t�a� �d�e� �C�o�m�p�r�a�s� �c�o�m�o� �t�e�x�t�o�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���R�S�a�l�v�a�r� �l�i�s�t�a� �d�e� �c�o�n�e�x��e�s� �e�m� �f�o�r�m�a�t�o� �S�P�I�C�E�������Save a netlist in SPICE format��� MainWindow���B�S�a�l�v�a�r� �u�m�a� �n�e�t�l�i�s�t� �n�o� �f�o�r�m�a�t�o� �X�M�L�������Save a netlist in XML format��� MainWindow���*�S�a�l�v�a�r� �o� �s�k�e�t�c�h� �a�t�u�a�l�������Save the current sketch��� MainWindow����S�a�l�v�o� �'�%�1�'������� Saved '%1'��� MainWindow����E�s�q�u�e�m��t�i�c�o������� Schematic��� MainWindow��� �B�u�s�c�a�������Search��� MainWindow���`�E�n�c�o�n�t�r�a�r� �c�o�m�p�o�n�e�n�t�e�s� �n�o� �e�s�q�u�e�m��t�i�c�o� �c�o�m� �o� �t�e�x�t�o�������-Search for parts in a sketch by matching text��� MainWindow���r�S�e�l�e�c�i�o�n�a�r� �T�o�d�a�s� �a�s� �t�r�i�l�h�a�s� �m�a�r�c�a�d�a�s� �c�o�m� �"�N��o� �A�u�t�o�r�o�t�e�i�e�"�������#Select All "Don't Autoroute" Traces��� MainWindow���R�S�e�l�e�c�i�o�n�a�r� �T�o�d�a�s� �a�s� �T�r�i�l�h�a�s� �A�u�t�o�r�o�t�e��v�e�i�s�������Select All Autoroutable Traces��� MainWindow���P�S�e�l�e�c�i�o�n�a�r� �t�o�d�o� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e�������Select All CopperFill��� MainWindow���6�S�e�l�e�c�i�o�n�a�r� �T�o�d�o�s� �o�s� �J�u�m�p�e�r�s�������Select All Jumpers��� MainWindow���T�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �b�l�o�q�u�e�a�d�o�s�������Select All Locked Parts��� MainWindow���4�S�e�l�e�c�i�o�n�a�r� �T�o�d�o�s� �o�s� �T�r�a��o�s�������Select All Traces��� MainWindow���0�S�e�l�e�c�i�o�n�a�r� �t�o�d�a�s� �a�s� �V�i�a�s�������Select All Vias��� MainWindow���0�S�e�l�e�c�i�o�n�a�r� �T�o�d�o�s� �o�s� �F�i�o�s�������Select All Wires��� MainWindow���P�S�e�l�e�c�i�o�n�e� �u�m� �a�r�q�u�i�v�o� �F�r�i�t�z�i�n�g� �p�a�r�a� �a�b�r�i�r�������Select a Fritzing File to Open��� MainWindow���^�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �i�t�e�m�s� �p�r�e�e�n�c�h�i�d�o�s� �c�o�m� �c�o�b�r�e�������Select all copper fill items��� MainWindow���:�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �e�l�e�m�e�n�t�o�s�������Select all elements��� MainWindow���V�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �j�u�m�p�e�r�s� �d�o�s� �c�o�m�p�o�n�e�n�t�e�s�������Select all jumper item parts��� MainWindow���r�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �q�u�e� �n��o� �p�o�d�e�m� �s�e�r� �m�o�v�i�d�o�s�������$Select all parts that can't be moved��� MainWindow���0�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �f�i�o�s�������Select all trace wires��� MainWindow���p�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �t�r�a��o�s� �e�x�c�l�u��d�o�s� �p�e�l�o� �a�u�t�o�r�o�t�e�a�m�e�n�t�o�������0Select all trace wires excluded from autorouting��� MainWindow����S�e�l�e�c�i�o�n�e� �t�o�d�a�s� �o�f� �f�i�o�s� �d�e� �t�r�i�l�h�a� �q�u�e� �p�o�d�e�m� �s�e�r� �m�o�d�i�f�i�c�a�d�o�s� �d�u�r�a�n�t�e� �o� �a�u�t�o�r�o�t�e�a�m�e�n�t�o�������=Select all trace wires that can be changed during autorouting��� MainWindow���H�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �V�i�a�s�������Select all via parts��� MainWindow���0�S�e�l�e�c�i�o�n�a�r� �t�o�d�o�s� �o�s� �f�i�o�s�������Select all wires��� MainWindow��@�S�e�l�e�c�i�o�n�a�r� �f�i�o�s� �o�n�d�e� �a� �l�o�c�a�l�i�z�a���o� �d�a� �t�e�l�a� �n��o� �b�a�t�e�m� �c�o�m� �a� �l�o�c�a�l�i�z�a���o� �a�t�u�a�l�.� �A�p�e�n�a�s� �n�e�c�e�s�s��r�i�o� �p�a�r�a� �e�s�q�u�e�m��t�i�c�o�s� �a�u�t�o�r�o�t�e�a�d�o�s� �c�o�m� �a� �v�e�r�s��o� �0�.�7�.�1�0� �o�u� �a�n�t�e�r�i�o�r�e�s�������Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier��� MainWindow���N�S�e�l�e�c�i�o�n�e� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�e�s�a�t�u�a�l�i�z�a�d�o�s�������Select outdated parts��� MainWindow��� �E�n�v�i�a�r� �p�a�r�a� �t�r��s������� Send Backward��� MainWindow���d�T�r�a�z�e�r� �o�s� �o�b�j�e�t�o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �p�a�r�a� �t�r��s� �d�a� �c�a�m�a�d�a�������+Send selected object(s) back in their layer��� MainWindow���d�T�r�a�z�e�r� �o�s� �o�b�j�e�t�o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �p�a�r�a� �t�r��s� �d�a� �c�a�m�a�d�a�������2Send selected object(s) to the back of their layer��� MainWindow��� �E�n�v�i�a�r� �p�a�r�a� �t�r��s������� Send to Back��� MainWindow���,�D�e�f�i�n�a� �c�o�r� �d�e� �f�u�n�d�o�.�.�.�������Set Background Color...��� MainWindow���8�D�e�f�i�n�a� �o� �T�a�m�a�n�h�o� �d�a� �G�r�a�d�e�.�.�.�������Set Grid Size...��� MainWindow���r�D�e�f�i�n�a� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a� �p�a�r�a� �p�r�e�e�n�c�h�i�m�e�n�t�o� �a�t�e�r�r�a�d�o�.�.�.�������Set Ground Fill Keepout...��� MainWindow���D�E�s�c�o�l�h�e�r� �C�o�m�o� �P�o�n�t�o� �d�e� �A�t�e�r�r�a�m�e�n�t�o�������Set Ground Fill Seed��� MainWindow����D�e�f�i�n�a� �p�a�r�a�m�e�t�r�o�s� �d�e� �a�u�t�o�r�o�t�e�a�m�e�n�t�o� �i�n�c�l�u�i�n�d�o� �a� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a�.�.�.�������/Set autorouting parameters including keepout...��� MainWindow���Z�H�a�b�i�l�i�t�a�r� �a�m�b�a�s� �c�a�m�a�d�a�s� �d�e� �c�o�b�r�e� �p�a�r�a� �c�l�i�q�u�e�s������� Set both copper layers clickable��� MainWindow���^�H�a�b�i�l�i�t�a�r� �c�a�m�a�d�a� �i�n�f�e�r�i�o�r� �d�e� �c�o�b�r�e� �p�a�r�a� �c�l�i�q�u�e�s�������!Set copper bottom layer clickable��� MainWindow���^�H�a�b�i�l�i�t�a�r� �c�a�m�a�d�a� �s�u�p�e�r�i�o�r� �d�e� �c�o�b�r�e� �p�a�r�a� �c�l�i�q�u�e�s�������Set copper top layer clickable��� MainWindow���B�D�e�f�i�n�a� �a� �c�o�r� �d�e� �f�u�n�d�o� �d�e�s�t�a� �v�i�s��o�������%Set the background color of this view��� MainWindow���F�D�e�f�i�n�i�r� �o� �t�a�m�a�n�h�o� �d�a� �g�r�a�d�e� �p�a�r�a� �%�1�.�������Set the grid size for %1.��� MainWindow����D�e�f�i�n�a� �a� �d�i�s�t��n�c�i�a� �m��n�i�m�a� �e�n�t�r�e� �p�r�e�e�n�c�h�i�m�e�n�t�o� �a�t�e�r�r�a�d�o� �e� �t�r�i�l�h�a�s� �e� �c�o�n�e�c�t�o�r�e�s�������ESet the minimum distance between ground fill and traces or connectors��� MainWindow���J�D�e�f�i�n�a� �o� �t�a�m�a�n�h�o� �d�a� �g�r�a�d�e� �n�e�s�t�a� �v�i�s��o�������%Set the size of the grid in this view��� MainWindow����C�o�m�p�a�r�t�i�l�h�a�r�������Share��� MainWindow���,�C�o�m�p�a�r�t�i�l�h�a�r� �o�n�l�i�n�e�.�.�.�������Share online...��� MainWindow��� �I�n�i�c�i�a�r� �S�h�e�l�l� �%�1�������Shell launch %1��� MainWindow����M�o�s�t�r�a�r� �C��d�i�g�o������� Show Code��� MainWindow����M�o�s�t�r�a�r� �G�r�a�d�e������� Show Grid��� MainWindow���\�M�o�s�t�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�o� �p�a�c�o�t�e� �n�o� �m�o�d�o� ��c�o�n�e�������Show Parts Bin Icon View��� MainWindow���\�M�o�s�t�r�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �d�o� �p�a�c�o�t�e� �n�o� �m�o�d�o� �l�i�s�t�a�������Show Parts Bin List View��� MainWindow���>�M�o�s�t�r�a�r� �a� �c�a�i�x�a� �"�s�o�b�r�e�"� �d�o� �Q�t��s�������Show Qt's about box��� MainWindow���n�M�o�s�t�r�a�r� �t�o�d�a�s� �a�s� �c�a�m�a�d�a�s� �d�i�s�p�o�n��v�e�i�s� �p�a�r�a� �a� �v�i�s��o� �a�t�u�a�l�������2Show all the available layers for the current view��� MainWindow���<�M�o�s�t�r�a�r� �e�t�i�q�u�e�t�a� �d�e� �c�o�m�p�o�n�e�n�t�e�������Show part label��� MainWindow���>�M�o�s�t�r�a�r� �i�m�p�r�e�s�s��o� �d�e� �c�o�m�p�o�n�e�n�t�e�������Show part silkscreen��� MainWindow���&�M�o�s�t�r�a�r� �a� �v�i�s��o� �P�C�B�������Show the PCB view��� MainWindow���H�M�o�s�t�r�a�r� �a� �c�a�i�x�a� �"�s�o�b�r�e�"� �d�a� �a�p�l�i�c�a���o������� Show the application's about box��� MainWindow���:�M�o�s�t�r�a�r� �a� �v�i�s��o� �d�a� �p�r�o�t�o�b�o�a�r�d�������Show the breadboard view��� MainWindow���N�M�o�s�t�r�a�r� �a� �v�i�s��o� �d�e� �c��d�i�g�o� �(�p�r�o�g�r�a�m�a���o�)������� Show the code (programming) view��� MainWindow����M�o�s�t�r�a�r� �a� �g�r�a�d�e������� Show the grid��� MainWindow���6�M�o�s�t�r�a�r� �a� �v�i�s��o� �e�s�q�u�e�m��t�i�c�o�������Show the schematic view��� MainWindow���(�M�o�s�t�r�a�r� �n��o� �r�o�t�e�a�d�o�s������� Show unrouted��� MainWindow���n�M�o�s�t�r�a�r�/�e�s�c�o�n�d�e�r� �e�t�i�q�u�e�t�a� �p�a�r�a� �c�o�m�p�o�n�e�n�t�e�s� �s�e�l�e�c�i�o�n�a�d�o�s�������*Show/hide the label for the selected parts��� MainWindow��� �S�k�e�t�c�h� �e�x�p�o�r�t�a�d�o�������Sketch exported��� MainWindow���:�D�e�s�e�n�h�o� �e�x�p�o�r�t�a�d�o� �p�a�r�a� �G�e�r�b�e�r�������Sketch exported to Gerber��� MainWindow����D�e�s�c�u�l�p�e�!�������Sorry!��� MainWindow���R�D�e�s�c�u�l�p�e�,� �a�i�n�d�a� �n��o� �f�o�i� �i�m�p�l�e�m�e�n�t�a�d�o� �"�%�1�"�������(Sorry, "%1" has not been implemented yet��� MainWindow���:�E�s�p�e�c�i�f�i�q�u�e� �o� �n�o�m�e� �d�o� �a�r�q�u�i�v�o�������Specify a file name��� MainWindow����G�r�u�d�e�n�t�o�������Sticky��� MainWindow��� �E�n�d�i�r�e�i�t�a�r� �C�u�r�v�a�������Straighten Curve��� MainWindow���F�E�n�d�i�r�e�i�t�a�r� �C�u�r�v�a� �d�o� �f�i�o� �s�e�l�e�c�i�o�n�a�d�o�������)Straighten the curve of the selected wire��� MainWindow��6�F�o�r�a�m� �a�t�u�a�l�i�z�a�d�a�s� �c�o�m� �s�u�c�e�s�s�o� �%�1� �c�o�m�p�o�n�e�n�t�e�(�s�)�.� �P�o�r� �f�a�v�o�r� �v�e�r�i�f�i�q�u�e� �e�m� �t�o�d�o�s� �o�s� �m�o�d�o�s� �d�e� �v�i�s�u�a�l�i�z�a���o� �p�a�r�a� �v�e�r�i�f�i�c�a�r� �a�l�g�u�m�a� �m�o�d�i�f�i�c�a���o� �n�a�s� �s�u�a�s� �d�i�m�e�n�s��e�s�.�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow���S�v�g� �%�1� �e�s�t�� �a� �p�r�o�c�u�r�a�n�d�o� �a� �'�%�2�'� �c�a�m�a�d�a�.� �P�a�r�a� �m�a�i�s� �i�n�f�o�r�m�a���e�s� �d�e� �c�o�m�o� �c�r�i�a�r� �u�m�a� �f�o�r�m�a� �d�e� �p�l�a�c�a�,� �v�e�j�a� �o� �t�u�t�o�r�i�a�l� �e�m� �<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�<�/�a�>�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���0�T�r�o�c�a�d�o� �%�1� �c�o�m� �m��d�u�l�o� �%�2�������Swapped %1 with module %2��� MainWindow����T�e�x�t�o� �i�r�� �s�e�r� �b�u�s�c�a�d�o� �n�a� �e�t�i�q�u�e�t�a�,� �d�e�s�c�r�i���o�,� �n�o�m�e� �e� �e�t�c� �d�o� �c�o�m�p�o�n�e�n�t�e�.� �E�n�t�r�e� �c�o�m� �o� �t�e�x�t�o� �a� �s�e�r� �p�r�o�c�u�r�a�d�o�:�������NText will match part label, description, title, etc. Enter text to search for:��� MainWindow���O� �f�o�r�m�a�t�o� �d�e� �a�r�q�u�i�v�o� �.�f�z� �n��o� �� �m�a�i�s� �u�t�i�l�i�z�a�d�o�.� � �V�o�c�� �g�o�s�t�a�r�i�a� �d�e� �c�o�n�v�e�r�t�e�r� �'�%�1�'� �p�a�r�a� �o� �f�o�r�m�a�t�o� �.�f�z�z� �a�g�o�r�a� �o�u� �a�b�r��-�l�o� �e�m� �m�o�d�o� �d�e� �l�e�i�t�u�r�a�?� �������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow���b�O� �p�r�o�c�e�s�s�o� �d�e� �c�o�n�v�e�r�s��o� �n��a�o� �i�r��a� �m�o�d�i�f�i�c�a�r� �'�%�1�'�.�������,The conversion process will not modify '%1'.��� MainWindow��l�A� �c�a�m�a�d�a� �s�u�p�e�r�i�o�r� �d�e� �c�o�b�r�e� �(�c�o�b�r�e� �1�)� �n��o� �e�s�t�� �d�i�s�p�o�n��v�e�l� �e�m� �u�m�a� �p�l�a�c�a� �d�e� �l�a�d�o� ��n�i�c�o�.� � �P�o�r� �f�a�v�o�r� �t�r�o�q�u�e� �p�a�r�a� �u�m�a� �p�l�a�c�a� �d�e� �l�a�d�o� �d�u�p�l�o� �o�u� �s�e�l�e�c�i�o�n�e� �a� �c�a�m�a�d�a� �i�n�f�e�r�i�o�r� �d�e� �c�o�b�r�e� �(�c�o�b�r�e� �0�)�.�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���l�A� �p�a�s�t�a� �"�%�1�"� �n��o� �� �u�m�a� �p�a�s�t�a� �d�e� �i�n�s�t�a�l�a���o� �d�o� �F�r�i�t�z�i�n�g�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���\�N��o� �e�x�i�s�t�e�m� �c�o�n�e�x��e�s� �n��o� �r�o�t�e�a�d�a�s� �n�e�s�t�a� �v�i�s��o�.�������/There are no unrouted connections in this view.��� MainWindow���t�J�� �e�x�i�s�t�e� �u�m� �c�o�m�p�o�n�e�n�t�e� �c�o�m� �i�d� �'�%�1�'� �c�a�r�r�e�g�a�d�o� �n�o� �F�r�i�t�z�i�n�g�.�������:There is already a part with id '%1' loaded into Fritzing.��� MainWindow����E�s�t�a� �o�p�e�r�a���o� �n��o� �p�o�d�e� �s�e�r� �d�e�s�f�e�i�t�a�-�-�v�o�c�� �i�r�� �p�e�r�d�e�r� �t�o�d�a�s� �m�o�d�i�f�i�c�a���e�s�.� � �I�r� �e�m� �f�r�e�n�t�e� �e� �d�e�s�f�a�z�e�r�?�������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow��v�V�a�i� �s�e�r� �p�r�o�v�i�d�e�n�c�i�a�d�a� �a� �e�x�p�o�r�t�a���o� �d�o� �s�k�e�t�c�h� �c�r�i�a�d�o� �p�e�l�o� �F�r�i�t�z�i�n�g� �p�a�r�a� �o� �s�o�f�t�w�a�r�e� �E�A�G�L�E�.� �S�e� �d�e�s�e�j�a� �t�e�r� �a� �e�x�p�o�r�t�a���o� �p�a�r�a� �o�u�t�r�o� �t�i�p�o� �d�e� �s�o�f�t�w�a�r�e� �d�e� �d�e�s�e�n�v�o�l�v�i�m�e�n�t�o�,� �d�i�g�a�-�n�o�s�,� �o�u� �c�o�n�t�r�i�b�u�a�.�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow��� �F�i�o�s� �o�r�g�a�n�i�z�a�d�o�s������� Tidy Wires��� MainWindow���:�F�i�o�s� �s�e�l�e�c�i�o�n�a�d�o�s� �o�r�g�a�n�i�z�a�d�o�s�������Tidy selected wires��� MainWindow���0�D�i�c�a�s�,� �T�r�u�q�u�e�s� �e� �A�t�a�l�h�o�s�������Tips, Tricks and Shortcuts��� MainWindow����C�a�m�a�d�a� �S�u�p�e�r�i�o�r������� Top Layer��� MainWindow����T�r�a�t�e� �c�o�n�e�c�t�o�r� �e� �s�u�a�s� �c�o�n�e�x��e�s� �c�o�m�o� �'�t�e�r�r�a�'� �d�u�r�a�n�t�e� �p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �a�t�e�r�r�a�m�e�n�t�o�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���`�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�x�p�o�r�t�a�r� �%�1� �c�o�m�o� �c�o�m�p�a�r�t�i�l�h��v�e�l������� Unable to export %1 as shareable��� MainWindow���t�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�x�p�o�r�t�a�r� �%�1� �c�o�m�o� �u�m� �s�k�e�t�c�h� �c�o�m�p�a�r�t�i�l�h��v�e�l�������'Unable to export %1 to shareable sketch��� MainWindow���X�N��o� �f�o�i� �p�o�s�s��v�e�l� �c�a�r�r�e�g�a�r� �c�o�m�p�o�n�e�n�t�e� �d�e� �'�%�1�'�������Unable to load part from '%1'��� MainWindow���>�N��o� �f�o�i� �p�o�s�s��v�e�l� �a�b�r�i�r� �'�%�1�'�:� �%�2�������Unable to open '%1': %2��� MainWindow���\�N��o� �f�o�i� �p�o�s�s��v�e�l� �a�b�r�i�r� �c�o�m�p�a�r�t�i�l�h��v�e�l� �'�%�1�'�:� �%�2�������!Unable to open shareable '%1': %2��� MainWindow���r�N��o� �f�o�i� �p�o�s�s��v�e�l� �a�b�r�i�r� �c�o�m�p�o�n�e�n�t�e� �c�o�m�p�a�r�t�i�l�h��v�e�l� �'�%�1�'�:� �%�2�������&Unable to open shareable part '%1': %2��� MainWindow���4�N��o� �f�o�i� �p�o�s�s��v�e�l� �g�r�a�v�a�r� �%�1�������Unable to save %1��� MainWindow����N��o� �f�o�i� �p�o�s�s��v�e�l� �g�r�a�v�a�r� �o� �a�r�q�u�i�v�o� �B�O�M�,� �m�a�s� �o� �t�e�x�t�o� �e�s�t�� �n�o� ��r�e�a� �d�e� �t�r�a�n�s�f�e�r��n�c�i�a�.�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow����D�e�s�f�a�z�e�r�������Undo��� MainWindow���$�D�e�s�f�a�z�e�r� �H�i�s�t��r�i�c�o������� Undo History��� MainWindow���*�C�o�n�e�x��e�s� �n��o� �r�o�t�e�a�d�a�s�������Unrouted connections��� MainWindow���4�A�t�u�a�l�i�z�a�r� �%�1� �c�o�m�p�o�n�e�n�t�e�(�s�)�������Update %1 part(s)��� MainWindow���N�A�c�t�u�a�l�i�z�a�r� �a� �i�n�f�o�r�m�a���o� �d�e� �v�i�s�u�a�l�i�z�a���o�������Update InfoView on hover��� MainWindow���J�A�t�u�a�l�i�z�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �s�e�l�e�c�i�o�n�a�d�o�s�������Update selected parts��� MainWindow����V�i�s��o� �S�u�p�e�r�i�o�r�������View from Above��� MainWindow����V�i�s��o� �I�n�f�e�r�i�o�r�������View from Below��� MainWindow����V�i�s��o� �s�u�p�e�r�i�o�r�������View from above��� MainWindow����V�i�s��o� �i�n�f�e�r�i�o�r�������View from below��� MainWindow���4�V�e�r� �P�C�B� �d�e� �b�a�i�x�o� �p�a�r�a� �c�i�m�a�������+View the PCB from the bottom layers upwards��� MainWindow���4�V�e�r� �P�C�B� �d�e� �c�i�m�a� �p�a�r�a� �b�a�i�x�o�������*View the PCB from the top layers downwards��� MainWindow���v�D�u�r�a�n�t�e� �o� �r�o�t�e�a�m�e�n�t�o� �a�u�t�o�m�a�t�i�c�o�,� �n��o� �a�p�a�g�a�r� �f�i�o�s� �o�u� �j�u�m�p�e�r�s�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow����N�e�t�l�i�s�t� �X�M�L�.�.�.�������XML Netlist...��� MainWindow����V�a�i�s� �t�e�r� �d�e� �r�e�i�n�i�c�i�a�r� �o� �F�r�i�t�z�i�n�g� �p�a�r�a� �u�t�i�l�i�z�a�r� �o�s� �c�o�m�p�o�n�e�n�t�e�s� �i�m�p�o�r�t�a�d�o�s�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow����O� �s�e�u� �s�k�e�t�c�h� �a�i�n�d�a� �n��o� �t�e�m� �u�m�a� �p�l�a�c�a�!� �P�o�r� �f�a�v�o�r� �a�d�i�c�i�o�n�e� �u�m�a� �P�C�B� �(�P�l�a�c�a� �d�e� �C�i�r�c�u�i�t�o� �I�m�p�r�e�s�s�o�)� �p�a�r�a� �e�x�p�o�r�t�a�r� �p�a�r�a� �o� �"�G�e�r�b�e�r�"�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �p�l�a�c�a�!� � �F�a�v�o�r� �a�d�i�c�i�o�n�a�r� �u�m�a� �P�C�B� �p�a�r�a� �r�e�m�o�v�e�r� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e�.�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �p�l�a�c�a�!� � �F�a�v�o�r� �a�d�i�c�i�o�n�a�r� �u�m�a� �P�C�B� �p�a�r�a� �u�t�i�l�i�z�a�r� �p�r�e�e�n�c�h�i�m�e�n�t�o� �c�o�m� �a�t�e�r�r�a�m�e�n�t�o� �o�u� �c�o�b�r�e�.�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �p�l�a�c�a�!� �F�a�v�o�r� �a�d�i�c�i�o�n�a�r� �u�m�a� �P�C�B� �p�a�r�a� �p�o�d�e�r� �a�u�t�o�r�o�t�e�a�r�.�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �p�l�a�c�a�!� �O� �D�R�C� �s�� �f�u�n�c�i�o�n�a� �c�o�m� �u�m�a� �P�C�B�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �u�m�a� �p�l�a�c�a�!� �F�a�v�o�r� �c�o�l�o�c�a�r� �u�m�a� �P�C�B� �p�a�r�a� �p�o�d�e�r� �e�x�p�o�r�t��-�l�a�.�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �c�o�n�t��m� �u�m�a� �p�l�a�c�a�!� �A�d�i�c�i�o�n�e� �u�m�a� �P�C�B� �p�a�r�a� �u�t�i�l�i�z�a�r� �o�p�e�r�a���e�s� �d�e� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e�.�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow����M�a�i�s� �Z�o�o�m�������Zoom in��� MainWindow����M�e�n�o�s� �Z�o�o�m�������Zoom out��� MainWindow����c�o�m�o� �I�m�a�g�e�m�������as Image��� MainWindow����i�n�f�e�r�i�o�r�������bottom��� MainWindow����e�m� �c�o�b�r�e�������copper��� MainWindow���,�p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e������� copperfill��� MainWindow���D�C�a�r�r�e�g�a�n�d�o� �c�o�m�p�o�n�e�n�t�e�s� �d�i�r�e�t�a�m�e�n�t�e�������directly loading parts��� MainWindow����p�a�r�a� �P�r�o�d�u���o�������for Production��� MainWindow����a�t�e�r�r�a�d�o�������ground��� MainWindow����p�o�l�������in��� MainWindow����c�a�r�r�e�g�a�n�d�o� �%�1������� loading %1��� MainWindow���4�c�a�r�r�e�g�a�n�d�o� �%�1� �(�p�r�o�t�o�b�o�a�r�d�)�������loading %1 (breadboard)��� MainWindow���,�c�a�r�r�e�g�a�n�d�o� �%�1� �(�m�o�d�e�l�o�)�������loading %1 (model)��� MainWindow���&�c�a�r�r�e�g�a�n�d�o� �%�1� �(�p�c�b�)�������loading %1 (pcb)��� MainWindow���.�c�a�r�r�e�g�a�n�d�o� �%�1� �(�e�s�q�u�e�m�a�)�������loading %1 (schematic)��� MainWindow����n�o�v�o� �d�e�s�e�n�h�o������� new sketch��� MainWindow���F�o� �f�o�r�m�a�t�o� �d�e� �a�r�q�u�i�v�o� �.�f�z� �� �o�b�s�o�l�e�t�o�������the .fz file format is obsolete��� MainWindow���b�l�a�n��a�r� �u�m�a� �f�a�l�s�a� �e�x�c�e���o� �p�a�r�a� �v�e�r� �o� �q�u�e� �a�c�o�n�t�e�c�e�u�������*throw a fake exception to see what happens��� MainWindow���*�l�a�n��a�r� �e�x�e�c�e���o� �t�e�s�t�e�������throw test exception��� MainWindow����s�u�p�e�r�i�o�r�������top��� MainWindow���\�I�m�p�o�s�s��v�e�l� �d�e� �e�n�c�o�n�t�r�a�r� �s�u�b�s�t�i�t�u�i���o� �p�a�r�a� �%�1�.� �������#unable to find replacement for %1. ��� MainWindow���� �c�o�m� �%�n� �v�i�a���� �c�o�m� �%�n� �v�i�a�s������� with %n vias��� MazeRouter���6�A�u�t�o�r�o�t�e�a�d�o�r� �f�o�i� �c�a�n�c�e�l�a�d�o�.�������Autorouter was cancelled.��� MazeRouter���*�O�t�i�m�i�z�a�n�d�o� �t�r�i�l�h�a�s�.�.�.�������Optimizing traces...��� MazeRouter���6�P�r�e�p�a�r�a�n�d�o� �p�a�r�a� �d�e�s�f�a�z�e�r�.�.�.�������Preparing undo...��� MazeRouter���(�R�o�t�e�a�m�e�n�t�o� �c�o�m�p�l�e�t�o�!�������Routing complete!��� MazeRouter���J�R�o�t�e�a�m�e�n�t�o� �c�h�e�g�o�u� �� ��l�t�i�m�a� �r�o�d�a�d�a� �%�1�.�������!Routing reached maximum round %1.��� MazeRouter���"�R�o�t�e�a�m�e�n�t�o� �p�a�r�o�u�!�������Routing stopped!��� MazeRouter���h�R�o�t�e�a�m�e�n�t�o� �m�a�l� �s�u�c�e�d�i�d�o�;� �p�a�r�o�u� �d�u�r�a�n�t�e� �a� �%�1�� �r�o�d�a�d�a�.�������+Routing unsuccessful; stopping at round %1.��� MazeRouter����F�a�l�h�a� �i�n�e�x�p�e�r�a�d�a� �d�e� �r�e�n�d�e�r�i�z�a���o� �d�o� �S�V�G�-�-�c�o�n�t�a�t�a�n�d�o� �f�r�i�t�z�i�n�g�.�o�r�g�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���(�U�t�i�l�i�z�a�r� �o� �m�e�l�h�o�r�.�.�.�������Use best so far...��� MazeRouter���B�f�e�i�t�o� �a�t�� �a�g�o�r�a�:�%�1� �d�e� �%�2� �r�o�t�e�a�d�o�s�������best so far: %1 of %2 routed��� MazeRouter����r�o�d�a�d�a� �%�1� �d�e�:������� round %1 of:��� MazeRouter����N��o� �f�o�i� �p�o�s�s��v�e�l� �s�o�b�r�e�s�c�r�e�v�e�r� �o� �a�r�q�u�i�v�o� �'�%�1�'�.� �R�a�z��o�:� �%�2� �(�c��d�i�g�o� �d�o� �e�r�r�o� �%�3�)�������5Couldn't overwrite file '%1'. Reason: %2 (errcode %3)��� ModelBase���:�A� �g�r�a�v�a���o� �d�o� �a�r�q�u�i�v�o� �f�a�l�h�o�u�!�������File save failed!��� ModelBase���h�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�n�c�o�n�t�r�a�r� �o� �s�e�g�u�i�n�t�e� �c�o�m�p�o�n�e�n�t�e� �%�n�:���n�N��o� �f�o�i� �p�o�s�s��v�e�l� �e�n�c�o�n�t�r�a�r� �o�s� �s�e�g�u�i�n�t�e�s� �c�o�m�p�o�n�e�n�t�e�s� �%�n�:�������(Unable to find the following %n part(s):��� ModelBase����e�m�������at��� ModelBase��� �e�t�i�q�u�e�t�a� �d�o� �c�h�i�p������� chip label��� MysteryPart����e�t�i�q�u�e�t�a�������label��� MysteryPart��� �e�t�i�q�u�e�t�a� �d�e� �r�e�d�e������� net label���NetLabel���0�[�E�s�c�r�e�v�a� �s�e�u� �t�e�x�t�o� �a�q�u�i�]�������[write your note here]���Note����P�r�e�e�n�c�h�i�m�e�n�t�o� �%�1�:� �s�e�l�e�c�i�o�n�e� �a� �p�l�a�c�a� �q�u�e� �v�o�c�� �d�e�s�e�j�a� �a�p�l�i�c�a�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o�.�������;%1 Fill: please select the board you want to apply fill to.���PCBSketchWidget���r�1�0�m�i�l�s� �� �u�m�a� �b�o�a� �e�s�c�o�l�h�a� �p�a�r�a� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a� �p�a�d�r��o�.�������#10 mils is a good default choice. ���PCBSketchWidget���*�M�u�d�a�r� �c�a�m�a�d�a� �d�e� �t�r�a��o�������Change trace layer���PCBSketchWidget���8�L�i�m�p�a�r� �p�o�n�t�o�s� �d�e� �a�t�e�r�r�a�m�e�n�t�o�������Clear ground fill seeds���PCBSketchWidget���d�C�l�i�q�u�e� �n�e�s�t�e� �c�o�n�e�c�t�o�r� �p�a�r�a� �a�r�r�a�s�t�a�r� �u�m� �n�o�v�o� �t�r�a��o�.�������-Click this connector to drag out a new trace.���PCBSketchWidget��� �C�o�b�r�e�������Copper���PCBSketchWidget����P�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e�:�s�e�l�e�c�i�o�n�e� �a�p�e�n�a�s� �a� �p�l�a�c�a� �q�u�e� �d�e�s�e�j�a� �p�r�e�e�n�c�h�e�r�.�������;Copper fill: please select only the board you want to fill.���PCBSketchWidget���H�C�r�i�a�r� �T�r�a��o� �a� �p�a�r�t�i�r� �d�e� �f�i�a���o� �d�e� �n��������Create Trace from Ratsnest���PCBSketchWidget���2�E�n�t�r�e� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a������� Enter Keepout���PCBSketchWidget���8�E�n�t�r�e� �a� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a�:�������Enter keepout value:���PCBSketchWidget����F�r�i�t�z�i�n�g� �F�a�b�������Fritzing Fab Quote���PCBSketchWidget���z�E�r�r�o� �n�o� �F�r�i�t�z�i�n�g�:� �n��o� �f�o�i� �p�o�s�s��v�e�l� �r�e�n�d�e�r�i�z�a�r� �a� �p�l�a�c�a� �s�v�g�(�1�)�.�������/Fritzing error: unable to render board svg (1).���PCBSketchWidget���z�E�r�r�o� �n�o� �F�r�i�t�z�i�n�g�:� �n��o� �f�o�i� �p�o�s�s��v�e�l� �r�e�n�d�e�r�i�z�a�r� �o� �c�o�b�r�e� �s�v�g�(�1�)�.�������0Fritzing error: unable to render copper svg (1).���PCBSketchWidget����E�r�r�o� �n�o� �F�r�i�t�z�i�n�g�:� �n��o� �f�o�i� �p�o�s�s��v�e�l� �f�a�z�e�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e� �(�1�)�.�������0Fritzing error: unable to write copper fill (1).���PCBSketchWidget����E�r�r�o� �n�o� �F�r�i�t�z�i�n�g�:� �I�n�c�a�p�a�z� �d�e� �f�a�z�e�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e� �(�2�)�.�������0Fritzing error: unable to write copper fill (2).���PCBSketchWidget��� �T�e�r�r�a�������Ground���PCBSketchWidget���@�E�s�c�o�n�d�e�r� �i�m�p�r�e�s�s��o� �d�o� �c�o�m�p�o�n�e�n�t�e�������Hide part silkscreen���PCBSketchWidget���P�M�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a� �e�m� �m�i�l�s�(�.�0�0�1� �p�o�l�)�.� � �������#Keepout is in mils (.001 inches). ���PCBSketchWidget����D�e�v�i�d�o� �a�o� �a�l�i�a�s�i�n�g�,� �d�i�s�t��n�c�i�a�s� �p�o�d�e�m� �s�e�r� �m�u�i�t�o� �p�r��x�i�m�a�s� �a� �p�a�r�t�i�r� �d�e� �2� �m�i�l�s� �������FNote that due to aliasing, distances may be too short by up to 2 mils ���PCBSketchWidget����C�l�i�q�u�e� �n�u�m�a� �P�C�B� �p�r�i�m�e�i�r�o� �-�-�e�s�t�a� �o�p�e�r�a���o� �d�e� �s�e�l�e���o� �f�u�n�c�i�o�n�a� �a�p�e�n�a�s� �p�a�r�a� �u�m�a� �p�l�a�c�a� �p�o�r� �v�e�z�.�������YPlease click on a PCB first--this selection operation only works for one board at a time.���PCBSketchWidget����P�o�r� �f�a�v�o�r�,� �e�s�c�o�l�h�a� �u�m� �o�u� �m�a�i�s� �p�o�n�t�o�s� �d�e� �a�t�e�r�r�a�m�e�n�t�o� �a�n�t�e�s� �d�e� �f�a�z�e�r� �p�r�e�e�n�c�h�i�m�e�n�t�o� �a�t�e�r�r�a�d�o�.� � �������LPlease designate one or more ground fill seeds before doing a ground fill. ���PCBSketchWidget���>�M�o�s�t�r�a�r� �i�m�p�r�e�s�s��o� �d�o� �c�o�m�p�o�n�e�n�t�e�������Show part silkscreen���PCBSketchWidget�� �D�e�s�c�u�l�p�e�,� �h�t�t�p�:�/�/�g�a�b�.�f�r�i�t�z�i�n�g�.�o�r�g� �n��o� �e�s�t�� �r�e�s�p�o�n�d�e�n�d�o� �a�o� �s�e�u� �r�e�q�u�e�r�i�m�e�n�t�o�.� �F�a�v�o�r� �c�h�e�c�a�r� �s�u�a� �c�o�n�e�x��o� �c�o�m� �a� �r�e�d�e� �e�/�o�u� �t�e�n�t�e� �n�o�v�a�m�e�n�t�e� �m�a�i�s� �t�a�r�d�e�.�������Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later.���PCBSketchWidget��.�N��o� �f�o�i� �p�o�s�s�i�v�e�l� �c�o�n�v�e�r�t�e�r� �e�s�t�a� �v�i�a� �p�a�r�a� �u�m� �p�o�n�t�o� �d�e� �f�l�e�x��o� �p�o�r�q�u�e� �e�s�t�e� �e�s�t�� �c�o�n�e�c�t�a�d�o� �a� �u�m� �c�o�m�p�o�n�e�n�t�e� �d�a� �c�a�m�a�d�a� �i�n�f�e�r�i�o�r� �e� �o�u�t�r�o� �n�a� �c�a�m�a�d�a�d�a� �s�u�p�e�r�i�o�r�.�������Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer.���PCBSketchWidget����I�m�p�o�s�s��v�e�l� �c�r�i�a�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e�-�-�p�r�o�v�a�v�e�l�m�e�n�t�e� �o� �c�o�m�p�o�n�e�n�t�e� �f�o�i� �l�a�r�g�a�d�o� �n�o�u�t�r�o� �s��t�i�o� �q�u�e� �n��o� �e�s�t�a� �P�C�B�.�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget����I�m�p�o�s�s��v�e�l� �c�r�i�a�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �d�e� �c�o�b�r�e�-�-�p�r�o�v�a�v�e�l�m�e�n�t�e� �o� �c�o�m�p�o�n�e�n�t�e� �n��o� �f�o�i� �c�o�l�o�c�a�d�o� �n�a� �P�C�B�.�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget����S�e�u� �e�s�q�u�e�m��t�i�c�o� �a�i�n�d�a� �n��o� �t�e�m� �u�m�a� �p�l�a�c�a�!� �A�d�i�c�i�o�n�e� �u�m�a� �P�C�B� �(�P�l�a�c�a� �d�e� �C�i�r�c�u�i�t�o� �I�m�p�r�e�s�s�o�)� �p�a�r�a� �u�s�a�r� �o� �p�r�e�e�n�c�h�i�m�e�n�t�o� �e�m� �c�o�b�r�e�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget����S�e�u� �e�s�q�u�e�m��t�i�c�o� �n��o� �t�e�m� �u�m�a� �p�l�a�c�a� �a�i�n�d�a�!� � �A�d�i�c�i�o�n�e� �u�m�a� �P�C�B� �p�a�r�a� �u�t�i�l�i�z�a�r� �e�s�t�a� �o�p�e�r�a���o� �d�e� �s�e�l�e���o�.�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget����S�e�u� �e�s�q�u�e�m��t�i�c�o� �n��o� �p�o�s�s�u�i� �u�m�a� �p�l�a�c�a� �a�i�n�d�a�!� �A�d�i�c�i�o�n�e� �u�m�a� �P�C�B� �p�a�r�a� �u�i�t�i�l�i�z�a�r� �e�s�t�a� �o�p�e�r�a���o� �d�e� �s�e�l�e���o�.�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget����S�e�u� �e�s�q�u�e�m��t�i�c�o� �n��o� �t�e�m� �u�m�a� �p�l�a�c�a� �a�i�n�d�a�.� �V�o�c�� �n��o� �p�o�d�e� �f�a�b�r�i�c�a�r� �e�s�t�e� �e�s�q�u�e�m��t�i�c�o� �s�e�m� �u�m�a� �c�o�m�p�o�n�e�n�t�e� �P�C�B�.�������[Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.���PCBSketchWidget����e�n�t��o� �v�o�c�� �p�o�d�e� �d�e�s�e�j�a�r� �a�u�m�e�n�t�a�r� �a� �m�a�r�g�e�m� �d�e� �d�i�s�t��n�c�i�a� �p�a�r�a� �p�e�l�o� �m�e�n�o�s� �i�s�t�o�.� � �������=so you may want to increase the keepout value by that much. ���PCBSketchWidget����A�q�u�i� �� �o�n�d�e� �v�o�c�� �e�d�i�t�a� �m�e�t�a�d�a�d�o�s� �d�o� �c�o�n�e�c�t�o�r� �p�a�r�a� �e�s�t�e� �c�o�m�p�o�n�e�n�t�e�������:This is where you edit the connector metadata for the part���PEConnectorsView����B�u�r�a�c�o� �a�t�r�a�v��s������� Through-hole���PEConnectorsView���*�n��m�e�r�o� �d�e� �c�o�n�e�c�t�o�r�e�s�:�������number of connectors:���PEConnectorsView���.� � �V�� �e�m� �f�r�e�n�t�e� �e� �s�a�l�v�e�?������� Go ahead and save?��� PEMainWindow����&�E�d�i�t�a�r�������&Edit��� PEMainWindow����&�E�x�p�o�r�t�a�r�������&Export��� PEMainWindow����&�A�r�q�u�i�v�o�������&File��� PEMainWindow����<�b�r�/�>�<�b�r�/�>�E�s�t�e� �n��o� �s�e�r�a� �m�a�i�s� �u�m� �p�r�o�b�l�e�m�a� �n�a� �p�r��x�i�m�o� �e�d�i���o� �d�o� �E�d�i�t�o�r� �d�e� �C�o�m�p�o�n�e�n�t�e�s�,� �������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowfNo permitida duplicatas da propriedade 'famlia',A duplicate 'family' property is not allowed PEMainWindowhNo permitida duplicadas da propriedade 'variante'-A duplicate 'variant' property is not allowed PEMainWindow.Adicionar %1 conectoresAdd %1 connectors PEMainWindow*Adicionar um conector Add connector PEMainWindowXAdicionar conexo interna de ''%1' para '%2')Add internal connection from '%1' to '%2' PEMainWindow,Branco no permitidoBlank not allowed PEMainWindowCancelarCancel PEMainWindowMude %1 para %2Change %1 to %2 PEMainWindow"Mude %1 para '%2'Change %1 to '%2' PEMainWindowBMudar todos os conectores para %1Change all connectors to %1 PEMainWindow"Mudar conector %1Change connector %1 PEMainWindowMudar descrioChange description PEMainWindow$Mudar propriedadesChange properties PEMainWindowMudar etiquetas Change tags PEMainWindowMudar para %1 Change to %1 PEMainWindow"Fechar sem salvarClose without saving PEMainWindow$Fechar sem salvar?Close without saving? PEMainWindowConectores Connectors PEMainWindow&Viso de ConectoresConnectors View PEMainWindow*Problema na conversoConversion problem PEMainWindow"Problema na cpia Copy problem PEMainWindownVoc deseja continuar trabalhando ou fechar sem salvar?4Do you want to keep working or close without saving? PEMainWindowVoc deseja salvar as modificaes que voc fez no componente "%1"?:Do you want to save the changes you made in the part "%1"? PEMainWindowfNo permitida duplicatas da propriedade 'famlia''Duplicate 'family' property not allowed PEMainWindow\Propriedade duplicada 'variante' no permitida(Duplicate 'variant' property not allowed PEMainWindow*Problema de duplicataDuplicate problem PEMainWindowEditor de Componentes existente est bem, desde que voc se lembre de acabar de fazer conexes depois.^Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMainWindow4Prefixo do nome do arquivoFilename prefix PEMainWindow FontesFonts PEMainWindowJ(Novo) Editor de Componentes FritzingFritzing (New) Parts Editor PEMainWindowFritzing atualmente suporta apenas as fontes OCRA e Droid--estas foram substituidas pelas fontes '%1'kFritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' PEMainWindow coneIcon PEMainWindowViso de cones Icon View PEMainWindowSe fizer modificaes na viso do protoboard, ou modificar metadados de conectores, as pernas podem no funcionar mais. cIf you make changes to breadboard view, or change connector metadata, the legs may no longer work.  PEMainWindowvImagem & Arquivos <i>Footprint</i> (%1 %2 %3 %4 %5);;Arquivos SVG (%1);;Arquivos JPEG (%2);;Arquivos PNG (%3);;Arquivos <i>Footprint</i> EDA Footprint (%4);;Arquivos de Mdulo Kicad (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowArquivos de Imagem (%1 %2 %3);;Arquivos SVG (%1);;Arquivos JPEG (%2);;Arquivos PNG (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowPropriedades Inspector PEMainWindowRConexes internas esto muito bagunadas.(Internal connections are very messed up. PEMainWindow$Manter trabalhando Keep working PEMainWindowCamadasLayers PEMainWindow:Carregar imagem para viso...Load image for view... PEMainWindowxfFazer cpia do componente e salvar ela no pacote 'My Parts'9Make a copy of the part and save it in the 'My Parts' Bin PEMainWindow>Fazer apenas a visao %1 visvelMake only %1 view visible PEMainWindow>Fazer apenas esta viso visvelMake only this view visible PEMainWindowMetadadoMetadata PEMainWindow$Viso de Metadados Metadata View PEMainWindow(Mover ponto terminalMove terminal point PEMainWindowDeve ser nicoMust be unique PEMainWindow~Na rea de trabalho, abra a pasta contendo o arquivo svg atual.@On the desktop, open the folder containing the current svg file. PEMainWindowAbrir Imagem Open Image PEMainWindowAbra um arquivo para usar como imagem para esta viso do componente.:Open a file to use as the image for this view of the part. PEMainWindowImagens PNG e JPG mantm a sua natureza de imagens bitmap, e no ficam agradveis quando sofrem reescala--TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindow*Editor de Componentes Parts Editor PEMainWindowEntre com um prefixo para ajudar a indentificar os arquivos de componentes. Os nomes devem estar no formato 'PREFIXO_%1'. (No necessrio mudar o prefixo, j que um sufixo nico sempre adicionado.)Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) PEMainWindowFavor reexportar o arquivo SVG usando esta configurao, e tente carregar novamente.HPlease re-export the SVG file using that setting, and try loading again. PEMainWindow,Realoque o conector %1Relocate connector %1 PEMainWindow*remover %1 conectoresRemove %1 connectors PEMainWindow.Remover Conexo InternaRemove Internal Connection PEMainWindow Remover conectorRemove connector PEMainWindow>Remover conexo interna de '%1'$Remove internal connection from '%1' PEMainWindow"Reusar imagem PCBReuse PCB image PEMainWindow6Reusar imagem do protoboardReuse breadboard image PEMainWindow8Reusar imagem do esquemticoReuse schematic image PEMainWindow@Reusar imagem do PCB nessa viso Reuse the PCB image in this view PEMainWindowNReusar imagem do protoboard nessa viso'Reuse the breadboard image in this view PEMainWindowPReusar imagem do esquemtico nessa viso&Reuse the schematic image in this view PEMainWindowProblema no SVG SVG problem PEMainWindow SalvarSave PEMainWindowSalvar "%1" Save "%1" PEMainWindow6Salvar como novo componenteSave as new part PEMainWindowSalvar este componente modificar o esquemtico, e no poder ser desfeito.HSaving this part will make a change to the sketch that cannot be undone. PEMainWindowSalvar este componente modificar estes esquemticos, e est no poder ser desfeita.LSaving this part will make a change to these sketches that cannot be undone. PEMainWindowVeja <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">esta explicao</a>.ySee this explanation. PEMainWindow$Mostrar ConectoresShow Connectors PEMainWindowMostrar cone Show Icon PEMainWindow"Mostrar Metadados Show Metadata PEMainWindowMostar na PastaShow in Folder PEMainWindow\Mostrar metadados de conector em modo de lista*Show the connector metadata in a list view PEMainWindow.Mostrar viso de conesShow the icon view PEMainWindow2Mostar viso de metadadosShow the metadata view PEMainWindowHAlerta de Modificao no EsquemticoSketch Change Warning PEMainWindowEnto modificando pode produzir uma imagem de viso PCV invlida0So editing may produce an invalid PCB view image PEMainWindowVA propriedade 'famlia' no pode ser vazia.'The 'family' property can not be blank. PEMainWindowO arquivo SVG '%1' parece ter sido exportado pelo CorelDRAW sem a configurao de 'atributos de apresentao'.nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindowO esquemtico aberto '%1' usa o componente que voc est modificando. 4The open sketch '%1' uses the part you are editing.  PEMainWindow.Os esquemticos abertosThe open sketches  PEMainWindowO componente ser visvel apenas nessa viso e na viso de cones8The part will only be visible in this view and icon view PEMainWindowFO valor de '%1' no pode ser vazio.#The value of '%1' can not be blank. PEMainWindow^No existem camadas de cobres definidas em: %1.+There are no copper layers defined in: %1.  PEMainWindowBExiste uma edio ainda pendente.%There is one last edit still pending. PEMainWindow^Este componente no pode ser salvo como est: #This part can not be saved as-is:  PEMainWindowZEste componente tem %n conector no conectadobEste componentes tem %n conectores no conectados'This part has %n unassigned connectors  PEMainWindowPEsse componente tem pernas entortveis. This part has bendable legs.  PEMainWindowNEsta verso do Editor de Componentes ainda no tem suporte para edio de pernas entortveis, e as pernas podem no ser exibidas corretamente na viso de breadboard . This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindowEsta verso do novo Editor de Componentes no lida com camadas separadas cobre0 e cobre1 em '%1'. dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindowfEsse aviso no se repetir nessa sesso do Fritzing=This warning will not be repeated in this session of Fritzing PEMainWindowNo foi possvel criar novo conector--voc pode ter que tentar novamente.;Unable to create new connector--you may have to start over. PEMainWindow<No foi possivel carregar '%1'Unable to load '%1' PEMainWindowNo foi possvell carregar '%1'. Favor fechar o editor de componentes sem salvar e tentar novamente.PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindowFNo foi possvel carregar fzp de %1Unable to load fzp from %1 PEMainWindowdNo foi possvel carregar o arquivo de imagem '%1'Unable to load image file '%1' PEMainWindowpNo foi possivel carregar o arquivo de imagem '%1': %2$Unable to load image file '%1': %2 PEMainWindow\No foi possvel criar uma copia local de:'%1'$Unable to make a local copy of: '%1' PEMainWindow>No foi possvel processar '%1'Unable to parse '%1' PEMainWindowlNo foi possivel processar '%1': %2 linha:%3 coluna:%4*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindowVNo foi possvel processar o arquivo fzp %1Unable to parse fzp file %1 PEMainWindowPNo foi possivel escrever o svg para %1Unable to write svg to %1 PEMainWindowAt que todos os conectores estejam conectados aos elementos SVG, o componente no funcionar corretamente.UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindow@Uso de PNG e JPG desencorajadoUse of PNG and JPG discouraged PEMainWindowzVarivelt '%1' est em uso. Nome da varivelt deve ser nica.8Variant '%1' is in use. The variant name must be unique. PEMainWindowVoc pode fazer mudanas com segurana nas vises de Esquemtico ou PCB. 7You can safely make changes to Schematic or PCB view.  PEMainWindowVoc deve usar uma imagem PNG ou JPG para construir seu componente, porm melhor que use uma SVG. WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindowhSuas modificaes sero perdidas se no salvar elas.1Your changes will be lost if you don't save them. PEMainWindow$atravs %n viso. &atravs %n vises. across %n views.  PEMainWindowe '%1'  and '%1'  PEMainWindowmas por enquanto, modifique o arquivo de acordo com as instrues no link.Mbut for now please modify the file according to the instructions in the link. PEMainWindowPnenhum <i>footprint</i> encontrado em %1no footprints found in %1 PEMainWindowPesquemticos noforam encontrados em %1no schematics found in %1 PEMainWindow,componente esquemticoschematic part PEMainWindowzpara componentes do Fritzing melhor usar imagens PNG e JPG.Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindow*componente sem ttulo untitled part PEMainWindow AutorAuthorPEMetadataViewDataDatePEMetadataViewDescrio DescriptionPEMetadataViewFamliaFamilyPEMetadataViewEtiquetaLabelPEMetadataViewPropriedades PropertiesPEMetadataView`Definir prefixo de etiqueta padro do componente!Set the default part label prefixPEMetadataView6Definir autor do componenteSet the part's authorPEMetadataView4Definir data do componenteSet the part's datePEMetadataViewDefinir descrio do componente--voc pode usar html simples (como definido pelo Rich Text Qt)RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataViewDefinir famlia do componente--como outros componentes e este esto relacionados?Set the part's family--what other parts is this part related toPEMetadataViewDDefinir propriedades do componenteSet the part's propertiesPEMetadataView@Definir marcadores do componenteSet the part's tagsPEMetadataView4Definir nome do componenteSet the part's titlePEMetadataViewDefinir url deste componente se esta estiver descrita em uma pgina da web3Set the part's url if it is described on a web pagePEMetadataViewDefinir variante do componente--iso o que faz nico de outros componentes da mesma famliaTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewMarcadoresTagsPEMetadataViewpAqui onde voc modifica metadados para o componente...4This is where you edit the metadata for the part ...PEMetadataView TtuloTitlePEMetadataViewVarianteVariantPEMetadataViewaltura:height: PESvgViewlargura:width: PESvgView\<font color='black'>Arrastar habilitado</font>+Dragging enabled PEToolView^<font color='gray'>Arrastar desabilidato</font>+Dragging disabled PEToolView CentroCenter PEToolViewConector %1 Connector %1 PEToolViewLista de Conectores (marca de OK significa que o grfico foi selecionado);Connector List (a checkmark means the graphic was selected) PEToolViewdControles de configuraes de ponto terminal para um conector. O ponto terminal onde um fio ser ligado a um conector.Voc tambem pode arrastar a caixa tracejada nos conectoresControls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector PEToolView0Arrastar est desabitadoDragging disabled PEToolViewLE PEToolViewTModificar a coordenada x do ponto terminal/Modifies the x-coordinate of the terminal point PEToolViewPModificar coordenada y do ponto terminal/Modifies the y-coordinate of the terminal point PEToolView"Selecionar imagemSelect graphic PEToolView2Definir Conexes InternasSet Internal Connections PEToolViewDefinir esta checkbox para modificar conexes internas desenhando fios?Set this checkbox to edit internal connections by drawing wires PEToolViewVDefinir ponto terminal do conector para %1.*Sets the connector's terminal point to %1. PEToolView&Usar a localizao do cursor e roda do mouse para navegar at o elemento SVG que voc deseja associar ao conector atual, com o mouse selecione ele.Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. PEToolViewOW PEToolView centrocenter PEToolView lesteeast PEToolView nortenorth PEToolViewsulsouth PEToolView oestewest PEToolView centrocenterPadconecte para connect toPad lesteeastPad nortenorthPad formashapePadsulsouthPad oestewestPad6Modificar Etiquetas de PinoEdit Pin Labels PaletteItem Dimetro do Furo Hole Diameter PaletteItem^Incompatibilidade de etiqueta. Nada foi salvo.#Label mismatch. Nothing was saved. PaletteItem"Espessura do AnelRing Thickness PaletteItemNo foi possvel continuar; conectores do componente no tem IDs padro.;Unable to proceed; part connectors do no have standard IDs. PaletteItemNo foi possvel continuar, no foi possvel encontrar viso do nvel de topo.1Unable to proceed; unable to find top level view. PaletteItem.configuraes avanadasadvanced settings PaletteItemtamanho do furo hole size PaletteItempolin PaletteItemMostrar valoresDisplay Values PartLabel6Mostrar o texto da etiquetaDisplay the text of the label PartLabelBMostrar o valor da propriedade %1 Display the value of property %1 PartLabel EditarEdit PartLabel4Editar a etiqueta de textoEdit label text PartLabel,Inverter na HorizontalFlip Horizontal PartLabel(Inverter na Vertical Flip Vertical PartLabelBInverter a etiqueta na horizontalFlip label horizontally PartLabel>Inverter a etiqueta na verticalFlip label vertically PartLabelInverter/Rodar Flip/Rotate PartLabel Tamanho da letra Font Size PartLabelEsconderHide PartLabel>Esconder etiqueta do componenteHide part label PartLabel"Texto da etiqueta Label text PartLabel$Texto da etiqueta: Label text: PartLabel GrandeLarge PartLabel MdioMedium PartLabelJRodar 135 no sentido Horrio {135?}Rotate 135� Clockwise PartLabelRRodar 45 no sentido Anti-Horrio {135?}Rotate 135� Counter Clockwise PartLabel$Rodar 180 {180?} Rotate 180� PartLabelHRodar 135 no sentido Horrio {45?}Rotate 45� Clockwise PartLabelPRodar 45 no sentido Anti-Horrio {45?}Rotate 45� Counter Clockwise PartLabelHRodar 135 no sentido Horrio {90?}Rotate 90� Clockwise PartLabelPRodar 45 no sentido Anti-Horrio {90?}Rotate 90� Counter Clockwise PartLabelRodar os componentes selecionados 90 graus no sentido Anti-Horrio5Rotate current selection 90 degrees counter clockwise PartLabelPRodar a etiqueta 135 no sentido Horrio)Rotate the label by 135 degrees clockwise PartLabelZRodar a etiqueta 135 no sentido Anti-Horrio1Rotate the label by 135 degrees counter clockwise PartLabel4Rodar a etiqueta 180 grausRotate the label by 180 degrees PartLabelNRodar a etiqueta 45 no sentido Horrio(Rotate the label by 45 degrees clockwise PartLabelXRodar a etiqueta 45 no sentido Anti-Horrio0Rotate the label by 45 degrees counter clockwise PartLabelNRodar a etiqueta 90 no sentido Horrio(Rotate the label by 90 degrees clockwise PartLabelLDefinir o tamanho da letra para grandeSet font size to large PartLabelJDefinir o tamanho da letra para mdioSet font size to medium PartLabelNDefinir o tamanho da letra para pequenoSet font size to small PartLabelJDefinir o tamanho de letra em pequenoSet font size to tiny PartLabel0Definir etiqueta para %1Set label for %1 PartLabelPequenoSmall PartLabelpequenoTiny PartLabel&Adicionar ao pacote Add to binPartsBinPaletteWidgetCancelarCancelPartsBinPaletteWidgetPNo foi possvel encontrar o arquivo %1.Cannot find file %1.PartsBinPaletteWidgetLNo foi possvel ler o arquivo %1: %2.Cannot read file %1: %2.PartsBinPaletteWidget*Mudar cor do cone...Change icon color...PartsBinPaletteWidgetLMudar a cor do cone para este pacote.*Change the color of the icon for this bin.PartsBinPaletteWidgetVoc realmente deseja adicionar o componente selecionado ao pacote?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetdDeseja salvar as alteraes feitas no pacote "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetNo salvar Don't SavePartsBinPaletteWidget*Pacote Fritzing (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetCarregar... Loading...PartsBinPaletteWidget SalvarSavePartsBinPaletteWidget$Salvar pacote "%1" Save bin "%1"PartsBinPaletteWidgetDSelecionar uma cor para este coneSelect a color for this iconPartsBinPaletteWidget<Especifique um nome de arquivoSpecify a file namePartsBinPaletteWidgetPacote sem nome Untitled BinPartsBinPaletteWidgetdAs modificaes sero perdidas se voc no salvar.1Your changes will be lost if you don't save them.PartsBinPaletteWidget,Carregando pacote '%1'loading bin '%1'PartsBinPaletteWidgetCancelarCancel Perfboard*Alerta de PerformancePerformance Warning PerfboardVPerformance de placas e placas com furos com mais de aproximadamente 2000 furos podem ser devagares. Tem certeza ? Nota: este aviso no ser repetido durante essa sesso.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard(Definir novo tamanho Set new size Perfboardcolunascolumns Perfboard linhasrows Perfboard0definir tamanho da placaset board size Perfboardtamanhosize Perfboard8Editor de etiquetas de pinos

    Pin Label Editor

    PinLabelDialogfClique na etiqueta prxima ao pino para renome-lo.<

    Click on a label next to a pin number to rename that pin.PinLabelDialogCancelarCancelPinLabelDialogRefazerRedoPinLabelDialog SalvarSavePinLabelDialogDesfazerUndoPinLabelDialognVoc pode usar a tecla tab para se mover entre os pinos@You can use the tab key to move through the labels in order.

    PinLabelDialog2%1 (Clique para mudar...)%1 (click to change...) PrefsDialog,Salvar AutomaticamenteAutosave PrefsDialog<Salvar Automaticamente a cada:Autosave every: PrefsDialogCancelarCancel PrefsDialog6Mudar Comportamento da RodaChange Wheel Behavior PrefsDialog(Limpar ConfiguraesClear Settings PrefsDialog CoresColors PrefsDialogComandoCommand PrefsDialog$Destaque ConectadoConnected Highlight PrefsDialogControleControl PrefsDialog&Fios curvos e retosCurvy vs. straight wires PrefsDialog(Fios e pernas curvasCurvy wires and legs PrefsDialog GeralGeneral PrefsDialogLinguagemLanguage PrefsDialog<Comportamento da Roda do MouseMouse Wheel Behavior PrefsDialogZSelecione um programador (executavel) para %1'Select a programmer (executable) for %1 PrefsDialog2Esse checkbox define o comportamento padro. Voc pode mud-lo para o comportamento no padro apertando o boto Control (Mac: Command) enquanto arrasta.This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialog,Destaque No ConectadoUnconnected Highlight PrefsDialogQuando arrastar um fio ou perna de um componente, deseja que a curvatura do fio (ou perna) mude ou seja criado um novo ponto de flexo?When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialogminutosminutes PrefsDialog~sem teclas = scroll shift troca eixo de scroll Alt ou %1 = zoomFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialog|sem teclas= zoom Alt ou %1 = scroll shift troca eixo de scrollFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialogXTem certeza que deseja remover %1 do sketch?5Are you sure you want to remove "%1" from the sketch? ProgramTab PlacaBoard ProgramTabCdigo (*.%1) Code (*.%1) ProgramTabpFritzing no consegue encontrar %1, por favor localize-o1Fritzing is unable to find '%1', please locate it ProgramTabNovoNew ProgramTabRemover "%1"? Remove "%1"? ProgramTab SalvarSave ProgramTabHSelecione um arquivo a ser carregadoSelect a program file to load ProgramTab&Cdigo&Code ProgramWindow&Copiar&Copy ProgramWindow&Recortar&Cut ProgramWindow&Editar&Edit ProgramWindow &Colar&Paste ProgramWindow &Preferncias...&Preferences... ProgramWindow &Selecionar tudo &Select All ProgramWindow &Viso&View ProgramWindow PlacaBoard ProgramWindow Janela de Cdigo Code Window ProgramWindow*Janela de Cdigo - %1Code Window - %1 ProgramWindowCopiar seleoCopy selection ProgramWindowCortar seleo Cut selection ProgramWindowArquivo '%1' foi restaurado do arquivo .fzz; salve uma cpia local para trabalhar com um editor externo.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindowArquivo '%1' foi restaurado do arquivo .fzz; uma cpia local no foi encontrada.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindow:Colar o contedo do clipboardPaste clipboard contents ProgramWindowRefazerRedo ProgramWindow*Selecionar todo textoSelect all text ProgramWindowHMostrar a caixa "sobre" da aplicao Show the application's about box ProgramWindowDesfazerUndo ProgramWindow%1 %2 %3QObjectCamada %1%1 LayerQObjectZexportao da camada %1 est vazia (2 caso)."%1 layer export is empty (case 2).QObjectF%1 exportao de camada est vazia.%1 layer export is empty.QObjectX%1 camada: no foi possvel salvar para '%2' %1 layer: unable to save to '%2'QObjectJfalha de exportao de mscara %1 (2)%1 mask export failure (2)QObjectV%1 fios movidos de sua posio salva em %2./%1 wires moved from their saved position in %2.QObject"<b>Descrio:</b>Description:QObject<b>Nome:</b> Name:QObject<b>tipo:</b> type:QObject:Configuraes do AutoroteadorAutorouter SettingsQObject BsicoBasicQObject PlacaBoardQObjectProtoboard BreadboardQObject Viso ProtoboardBreadboard ViewQObject(Trazer para a frente Bring forwardQObject(Trazer para a frenteBring to frontQObjectNo possvel autorotear: no foi encontrada nem uma (ou mais) placa(s) 5Cannot autoroute: no board (or multiple boards) foundQObjectLNo foi possvel ler o arquivo %1: %2.Cannot read file %1: %2.QObjectnNo possvel escrever o arquivo temporrio: %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject*Mudar "pata" de %1,%2Change leg of %1,%2QObject,Verificar atualizaesCheck for updatesQObject(Limpar ConfiguraesClear SettingsQObjectvLimpar as configuraes salvas e fechar este dilogo agora.;Clear all saved settings and close this dialog immediately.QObject:Cor de componentes conectadosConnected highlight colorQObjectLigao ConnectionQObjectDConverter Via para Ponto de FlexoConvert Via to BendpointQObject$Converter para ViaConvert to ViaQObjectCobre Inferior Copper BottomQObject.Trao Inferior de CobreCopper Bottom TraceQObject>Preenchimento inferior de cobreCopper Fill BottomQObject<Preenchimento de cobre em cimaCopper Fill TopQObjectCobre Superior Copper TopQObject.Trao Superior de CobreCopper Top TraceQObject&Copiando arquivo %1Copying file %1QObjectEditar endereo Edit linkQObject:Erro ao ler o arquivo %1: %2.Error reading file %1: %2.QObjectTArquivo %1 j existe: no ser substitudo/File %1 already exists: it won't be overwrittenQObject.Arquivo em progresso...File Progress...QObjectbFritzing no pode carregar o pacote de coponentes"Fritzing cannot load the parts binQObjectFritzing no pode processar os cortes nessa forma de PCB personalizada. DFritzing is unable to process the cutouts in this custom PCB shape. QObjectFritzing requer que voc faa cortes utilizando operaes de 'subtrao' ou 'diferena' de forma no seu editor de grficos.}Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.QObject<Editor de Ponto de AterramentoGround Fill Seed EditorQObject coneIconQObjectViso de cones Icon ViewQObjectEntradaInputQObject"Conexes InternasInternal ConnectionsQObjectJuntar o fio Join WireQObject MicrocontroladorMicrocontrollerQObjectJNenhuma conexo (na PCB) para rotear.%No connections (on the PCB) to route.QObject8Nenhuma conexo para rotear.No connections to route.QObjectDNo foram encontrados componentes.No parts found.QObject NotasNotesQObject OutroOtherQObject SadaOutputQObjectViso PCBPCB ViewQObject`Erro de anlise(1) na linha %1, coluna %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObjectbErro de anlise (2) na linha %1, coluna %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectComponentePartQObject$Componente %1 '%2' Part %1 '%2'QObject(Imagem do Componente Part ImageQObject(Rtulo do componente Part LabelsQObjectFComponente j se encontra no pacotePart already in binQObjectComponentesPartsQObjectJPasta de componentes no encontrados.Parts folder not found.QObject4Editor de Etiqueta de PinoPin Label EditorQObjectNote que a definio de uma nova linguagem no ter efeito at voc reiniciar o Fritzing.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectEnergiaPowerQObjectPreferncias PreferencesQObjectFiao de nRatsnestQObjectFios de nRatsnest wiresQObject RguasRulersQObject"Viso EsquemticoSchematic ViewQObjectSelecionar %1 Select %1QObject$Selecionar Tudo %1 Select all %1QObject`Selecionar todas as trilhas com 'No autoroteie'#Select all 'Don't autoroute' tracesQObjectRSelecionar todas as trilhas autoroteveisSelect all autorouteable tracesQObjectBSelecionar componentes bloqueadosSelect locked partsQObjectPSelecione os componentes desactualizadosSelect outdated partsQObject Enviar para trs Send backwardQObjectSensoresSensorsQObject0Definir Tamanho da Grade Set Grid SizeQObject8Definir Ponto de AterramentoSet Ground Fill SeedQObject&Definit todos para: Set all to:QObject:Definir descrio do conector Set the connectors's descriptionQObject0Definir nome de conectorSet the connectors's titleQObject&Silkscreen InferiorSilkscreen BottomQObjectXSilkscreen Inferior (Rtulo dos Componentes)Silkscreen Bottom (Part Labels)QObject&Silkscreen SuperiorSilkscreen TopQObjectXSilkscreen Superior (Rtulo dos Componentes)Silkscreen Top (Part Labels)QObjectDesculpe, Fritzing ainda no pode lidar com pinos e pads em conjunto (em %1 em %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectDesculpe, Fritzing ainda no pode lidar com pinos e pads em conjunto (%1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectRDesculpe, no posso manipular pad tipo %1Sorry, can't handle pad type %1QObject6Estamos tendo problemas com o mecanismo de mudana. O Fritzing tentando resolver o problema, mas no ser possvel modificar as propriedas dos componentes.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectDividir o fio Split WireQObject TextoTextQObjectVO arquivo %1 no um arquivo Fritzing (2).'The file %1 is not a Fritzing file (2).QObjectVO arquivo %1 no um arquivo Fritzing (3).'The file %1 is not a Fritzing file (3).QObjectVO arquivo %1 no um arquivo Fritzing (4).'The file %1 is not a Fritzing file (4).QObjectO arquivo '%1' somente leitura; por favor especifique um arquivo diferente.footprint</i> %1 no encontrado em %2footprint %1 not found in %2QObjectViso cone icon viewQObjectpolinQObject6falha ao exportar a mscaramask export failureQObject,camada(s) de mscara, mask layer(s), QObjectJfuros no circulares no implementado"non-circular holes not implementedQObject@furos sem cobre no implementado non-copper holes not implementedQObject$rebordo est vaziooutline is emptyQObject2faltando atributos do padpad missing attributesQObject*faltando drill do padpad missing drillQObject.faltando posio do padpad missing positionQObject*faltando forma do padpad missing shapeQObjectFfaltando parametros da forma do padpad shape missing paramsQObject@tamanho da forma do pad invlidopad shape size is invalidQObject,falha na anlise em %1parse failure in %1QObject4colar camada(s) de mscarapaste mask layer(s), QObjectviso PCBpcb viewQObject<faltando parametros de posioposition missing paramsQObjectEsquemticoschemQObjectbesquemtico %1 terminou inesperadamente (1) em %2(schematic %1 unexpectedly ends (1) in %2QObjectbesquemtico %1 terminou inesperadamente (2) em %2(schematic %1 unexpectedly ends (2) in %2QObjectbesquemtico %1 terminou inesperadamente (3) em %2(schematic %1 unexpectedly ends (3) in %2QObjectdcomponente esquemtico %1 no foi encontrado em %2!schematic part %1 not found in %2QObject"viso esquemticoschematic viewQObject8shape delta no implementadoshape delta not implementedQObject,falha ao exportar silksilk export failureQObject^exportao da camada de impresso %1 est vaziasilk layer %1 export is emptyQObject,camada(s) silkscreen, silkscreen layer(s), QObject8Camada do rebordo da placa, the board outline layer, QObjectDpads trapezoidais no implementado trapezoidal pads not implementedQObjectbno foi possvel copiar o arquivo '%1' para '%2'.!unable to copy file '%1' to '%2'.QObjectBimpossvel manipular forma pad %1unable to handle pad shape %1QObject2no foi possvel abrir %1unable to open %1QObject8no foi possvel analisar %1unable to parse %1QObject2fim do arquivo inesperadounexpected end of fileQObject|fim do arquivo inesperado no <i>footprint</i> %1 no arquivo %21unexpected end of file in footprint %1 in file %2QObjectDformato inesperado (1) em %1 de %2#unexpected format (1) in %1 from %2QObject4 %1 cm%3 (%2 pol%3).<br /> %1 cm%3 (%2 in%3).
     QuoteDialog CpiasCopies QuoteDialogPara mais informaes sobre preos acesse <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>.rFor more information on pricing see http://fab.fritzing.org/pricing. QuoteDialogFritzing FabFritzing Fab Quote QuoteDialogBEncomende sua PCB da Fritzing Fab Order your PCB from Fritzing Fab QuoteDialogDPreos no incluem o frete, <br />6Please note that prices do not include shipping,
     QuoteDialog PreoPrice QuoteDialogPreo por placaPrice per board QuoteDialogPAproveite nosso desconto por quantidade:(Take advantage of our quantity discount: QuoteDialogPrea total da %n PCB nesse esquemtico Rrea total de %n PCBs nesse esquemtico 1The total area of the %n PCB(s) in this sketch is QuoteDialogUtilize a Fritzing Fab para produzir a PCB do seu esquemtico. <br />9Use Fritzing Fab to produce a PCB from your sketch.
     QuoteDialog(Visitar Fritzing FabVisit Fritzing Fab QuoteDialogfpodem incidir taxas adicionais e/ou impostos.<br />5possible additional taxes, or the checking fee.
     QuoteDialog&Ignorar&IgnoreRecoveryDialog&Recuperar&RecoverRecoveryDialog <p><b>Fritzing talvez tenha falhado, mas algumas das alteraes nos seguintes arquivos talvez sejam recuperadas.</b></p><p>A data e hora de cada arquivo recuperado mostrado. Se o arquivo foi salvo, a data e hora tambm est listado para comparao.</p><p>Os arquivos originais ainda esto no disco, caso eles no tenham sido salvos. Voc pode escolher se deseja substituir o arquivo original depois de carregar o seu arquivo de recuperao.</p><p><b>Selecione os arquivos que deseja recuperar a partir da lista abaixo.</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialogArquivoFileRecoveryDialog2ltima cpia de segurana Last backupRecoveryDialogltima gravao Last savedRecoveryDialog"arquivo no salvofile not savedRecoveryDialogVoc pode ou digitar o valor da resistncia, ou selecionar uma no menu. Formato nnn.dP onde P um de 'umkMG'tYou can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'Resistorresistncia resistanceResistor0Tablide deitado (17x11)Ledger (17x11)ResizableBoardOfcio (8.5x14)Legal (8.5x14)ResizableBoardCarta (8.5x11)Letter (8.5x11)ResizableBoardDesfazerRevertResizableBoard Tablide (11x17)Tabloid (11x17)ResizableBoardpersonalizadocustomResizableBoardaltura(mm) height(mm)ResizableBoardaltura: %1mm height: %1mmResizableBoard2manter aspector de escalakeep aspect ratioResizableBoard formashapeResizableBoardtamanhosizeResizableBoardlargura(mm) width(mm)ResizableBoardlargura: %1mm width: %1mmResizableBoardlargurawidthRulerDataDateSchematicFrameNome do arquivoFilenameSchematicFrameProjectoProjectSchematicFrame FolhaSheetSchematicFramedatadateSchematicFramedeofSchematicFrame formashapeSchematicFrame folhasheetSchematicFrame8Mudar etiqueta de %1 para %2Change label from %1 to %2SchematicSketchWidget8Mudar a tenso de %1 para %2Change voltage from %1 to %2SchematicSketchWidgetCancelarCancelSetColorDialog.Fazer esta cor padro%1Make this the default %1 colorSetColorDialog%1 Nota: voc pode tambm acionar este aviso passando o mouse pelo texto de estado de roteamento na barra de estados.i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2 itens %1 %2 items SketchWidget %1 etiqueta '%2' %1 label '%2' SketchWidgetAcrescentar %1Add %1 SketchWidget TrocarChange SketchWidget8Mudar a cor %1 de %2 para %3Change %1 color from %2 to %3 SketchWidget,Mudar %1 de %2 para %3Change %1 from %2 to %3 SketchWidget@Mudar a etiqueta de %1 para '%2'Change %1 label to '%2' SketchWidget@Mudar a largura %1 de %2 para %3Change %1 width from %2 to %3 SketchWidgetBMudar a resistncia de %1 para %2Change Resistance from %1 to %2 SketchWidget>Mudar a cor %1 dos fios para %2Change color of %1 wires to %2 SketchWidget8Mudar a imagem de %1 para %2Change image from %1 to %2 SketchWidgetRMudar o ponto de flexo da perna para %1.Change leg bendpoint for %1. SketchWidgetFMudar a curvatura da perna para %1.Change leg curvature for %1. SketchWidgetFMudar a largura %1 dos fios para %2Change width of %1 wires to %2 SketchWidgetconectarConnect SketchWidget&Criar e conectar %1Create and connect %1 SketchWidget(Criar e conectar fioCreate and connect wire SketchWidgetDCriar fio a partir de fiao de nCreate wire from Ratsnest SketchWidget&Apagar fiao de nDelete ratsnest SketchWidgetDescelecionarDeselect SketchWidget$Desselecionar tudo Deselect all SketchWidgetDesconectar Disconnect SketchWidget8Desligar todos os fios de %1Disconnect all wires from %1 SketchWidgetHDesligar todos os fios de %1 Artigos"Disconnect all wires from %1 items SketchWidgetDuplo clique Double-click SketchWidget`Duplo clique para selecionar este ponto de dobra&Double-click to delete this bend point SketchWidget.Arrastar ou Duplo-clickDrag or double-click SketchWidgetInverterFlip SketchWidget Inverter %2 (%1) Flip %2 (%1) SketchWidgetMover %2 (%1) Move %2 (%1) SketchWidget&Mover %2 itens (%1)Move %2 items (%1) SketchWidget&Mover etiqueta '%1'Move label '%1' SketchWidgetMover "pata" de Move leg of SketchWidget0Houve alterao no textoNote text change SketchWidgetbComponente '%1' no foi encontrado no esquemticoPart '%1' not found in sketch SketchWidget$Redimensionar Nota Resize Note SketchWidget<Redimensionar placa para %1 %2Resize board to %1 %2 SketchWidget@Redimensionar a rgua para %1 %2Resize ruler to %1 %2 SketchWidget RodarRotate SketchWidgetRodar %2 (%1)Rotate %2 (%1) SketchWidgetSelecionar %1 Select %1 SketchWidget&Selecionar %1 itensSelect %1 items SketchWidgetSelecionar Tudo Select All SketchWidgetSeleco Selection SketchWidgetBNo existem conexes no roteadas!There are no unrouted connections SketchWidgetIsto parece uma tentativa de criar uma trilha entre camadas. Esta circunstncia no deveria ocorrer: favor contatar os desenvolvedores.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget*Conexes no roteadasUnrouted connections SketchWidgetdConexes no roteadas esto destacadas em amarelo./Unrouted connections are highlighted in yellow. SketchWidget.mudar etiquetas de pinochange pin labels SketchWidget*carregamento efetuado done loading SketchWidget de %1from %1 SketchWidgetDesconder %n etiqueta de componenteFesconder %n etiquetas de componentehide %n part label(s) SketchWidget0Carregando um componente loading part SketchWidgetJou alt-arrastar para mover o segmentoor alt-drag to move the segment SketchWidgetBmostrar %n etiqueta de componenteDmostrar %n etiquetas de componenteshow %n part label(s) SketchWidgetpara %1to %1 SketchWidget trilhatrace SketchWidgetfiowire SketchWidgetZO mecnismo de troca est desabilitado para: )The swapping mechanism is disabled for: SqliteReferenceModel.e %1 outros componentesand %1 other partsSqliteReferenceModel0e %1 outras propriedadesand %1 other propertiesSqliteReferenceModelcomponente '%1' com id '%2'; possivelmente porque no tem a propriedade de famlia.Epart '%1' with id '%2'; possibly because it has no 'family' property.SqliteReferenceModel`propriedade '%1' no componente '%2' com id '%3'.(property '%1' in part '%2' with id '%3'.SqliteReferenceModel%1 %n tira%1 %n tiras%1 %n strip(s) StripboardRecortarCut StripboardRestauradoRestored Stripboardcolunascolumns Stripboard linhasrows Stripboard"Etiquetas de rede Net labelsSymbolPaletteItemVEtiquetas de rede no podem estar em brancoNet labels cannot be blankSymbolPaletteItemetiquetalabelSymbolPaletteItem tensovoltageSymbolPaletteItemDicas e TruquesTips and Tricks TipsAndTricks|Selecione do menu cascata, ou digite qualquer valor de %1 a %2> order now >> WelcomeViewTproducei acum primul dumneavoastr pcb >>produce your first pcb now >> WelcomeViewMarcat cu benziBandedWire negrublackWirealbastrublueWiremarobrownWireculoarecolorWireciancyanWire(foarte gros (48 mil)extra thick (48 mil)Wire"subirel (12 mil)extra thin (12 mil)Wire verdegreenWiregrigreyWireocruochreWireportocaliuorangeWirerozpinkWire violetpurpleWirerouredWire$foarte fin (8 mil)super fine (8 mil)Wiregros (32 mil)thick (32 mil)Wire subire (16 mil) thin (16 mil)WirealbwhiteWire galbenyellowWire $fritzing-app-0.9.2b/translations/fritzing_ro.ts000066400000000000000000015674501250202676700217540ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> Versiunea %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 pentru cod și CreativeCommons:BY-SA pentru restul <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Fritzing este creat de: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, și Daniel Tzschentke. Special thanks goes out to: Mulțumiri speciale pentru: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Michaela Vieser și Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Mulțumiri lui Kurt Badelt și Miguel Solis pentru traducerea în spaniolă, to Gianluca Urgese for the Italian translation, lui Gianluca Urgese pentru traducerea în italiană, to Nuno Pessanha Santos for the Portuguese (European) translation, lui Nuno Pessanha Santos pentru traducerea în portugheză (europeană), to Yuelin and Ninjia for the Chinese (Simplified) translation, lui Yuelin și Ninjia pentru traducerea în chineză (simplificată), to Hiroshi Suzuki for the Japanese translation, lui Hiroshi Suzuki pentru traducerea în japoneză, to Robert Lee for the Chinese (Traditional) translation, lui Robert Lee pentru traducerea în chineză (tradițională), to Vladimir Savinov for the Russian translation, lui Vladimir Savinov pentru traducerea în rusă, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, lui Steven Noppe și Davy Uittenbogerd pentru traducerea în olandeză, to Josef Dustira for the Czech translation, lui Josef Dustira pentru traducerea în cehă, to Jinbuhm Kim for the Korean translation, lui Jinbuhm Kim pentru traducerea în koreeană, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, lui &#313;ubom&iacute;r Ducho&#328; pentru traducerea în slovacă, to Alexander Kaltsas for the Greek translation, lui Alexander Kaltsas pentru traducerea ăn greacă, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, lui Lionel Michel, Yvan Kloster, Alexandre Dussart, și Roald Baudoux pentru traducerea în franceză, to Cihan Mete Bahad&#x0131;r for the Turkish translation, lui Cihan Mete Bahad&#x0131;r pentru traducerea în turcă, to Nikolay Stankov for the Bulgarian translation, lui Nikolay Stankov pentru traducerea în bulgară, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. și lui Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira pentru traducerea în portugheză (braziliană). Fritzing is made possible with funding from the Fritzing este făcut posibil cu finanțare de la MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, sponsorul pentru Design Department of Bauhaus-University Weimar, Departamentul universității Weimar din Bauhaus, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, un donator anonim, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. și pentru toate achizițiile a Kitului de Pornire Fritzing sau a unei PCB de la Fabrica Fritzing. Special thanks goes out as well to all the students Mulțumiri speciale adresate tuturor studenților and alpha testers who were brave enough to give și testerilor care au avut curajul să testeze Fritzing a test spin. Fritzing. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls controale pentru zoom și panoramare Stop Now Oprește acum Best So Far Cel mai bun până acum Cancel Anulare Autorouter Routing canceled! Now cleaning up... Rutarea anulată! Acum se curăță... AutorouterSettingsDialog Production type Tip producție homebrew homebrew professional profesional custom personalizat Keepout Keepouts - zonă restricționare nu trebuie confundată cu stratul de restricționare. (restrict layer) vedeți: http://dangerousprototypes.com/2012/08/08/how-to-eagle-keepout-and-restrict-layers/ Zonă restricționare <b>Keepout</b> is the minimum distance between copper elements on different nets. <b>Zonă restricționare</b> este distanța minimă dintre elementele de cupru pe rețele diferite. A keepout of 0.01 inch (0.254 mm) is a good default. O zonă de restricționare de 0,01 inch (0.254 mm) este bună ca implicită. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Notificare: cu cât este mai mică zona de restricționare, cu atât DRC și Autotrasarea va rula mai lent. Trace width Lățime traseu Cancel Anulare OK OK BinManager Parts Componente BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Nu se poate configura cutia '%1' ca murdară BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Nu se poate configura cutia '%1' ca murdară New bin (%1) Cutie nouă (%1) Select a Fritzing Parts Bin file to open Selectați un fișier cutie componente Fritzing de deschis Searching... Se caută... Bin Cutie Import... Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Încarcă o componentă Fritzing (.fzpz), sau o cutie componente Fritzing (.fzb, .fzbz) New Bin... Cutie nouă... Create a new parts bin Crează o cutie componente nouă Close Bin Închide cutia Close parts bin Închide cutia componentelor Delete Bin Șterge cutia Delete parts bin Șterge cutia componentelor Save Bin Salvează cutia Save parts bin Salvează cutia componentelor Save Bin As... Salvează cutia ca... Save parts bin as... Salvează cutia componentelor ca... Export Bin... Exportă cutia... Save parts bin in compressed format... Salvează cutia componentelor în format comprimat... Rename Bin... Redenumește cutia... Rename parts bin... Redenumește cutia componentelor... Copy to Sketch Copiază în schiță Copy all the parts in the bin to a sketch Copiază toate componentele din cutie într-o schiță Copy all to Sketch Copiază tot în schiță Copy all loaded parts to the sketch Copiază toate componentele încărcate în schiță Show Bin in List View Arată cutia în vizualizare listă Display parts as a list Afișează componentele ca o listă Show Bin in Icon View Arată cutia în vizualizare pictogramă Display parts as icons Afișează componentele ca pictograme Edit Part (new parts editor)... Editare componentă (editor componente noi)... Export Part... Exportă parte... Remove Part Eliminare parte Find Part in Sketch Găsește parte în schiță Delete bin Șterge cutia Do you really want to delete bin '%1'? This action cannot be undone. Sigur doriți să ștergeți cutia '%1'? Această acțiune nu poate fi refăcută. Read-only bin Cutie doar-citire This bin cannot be renamed. Această cutie nu poate fi redenumită. Rename bin Redenumire cutie Please choose a name for the bin: Alegeți un nume pentru cutie: Remove from Bin Elimină din cutie Unable to remove part '%1'--it is in use in a sketch Nu se poate elimina partea '%1'--este utilizată într-o schiță Remove from bin Elimină din cutie Do you really want to remove '%1' from the bin? This operation cannot be undone. Sigur doriți să eliminați '%1' din cutie? Această operație nu poate fi refăcută. Select a Fritzing File to Open Selectați un fișier Fritzing de deschis Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fișiere Fritzing (*%1 *%2 *%3);;Părți Fritzing (*%1);;Cutie Fritzing (*%2);;Cutie partajabilă Fritzing (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fișiere cutie Fritzing (*%1 *%2);;Cutie Fritzing (*%1);;Cutie partajabilă Fritzing (*%2) Cannot set a NULL bin as the current one Nu se poate configura o cutie NULĂ ca una curentă Board A custom board svg typically has one or two silkscreen layers and one board layer. O placă personalizată tipic svg are unul sau două straturi serigrafice și un strat placă. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Consultați fișierul circle_pcb.svg în dosarul de instalare Fritzing la componente/svg/core/pcb/. one layer (single-sided) un strat (o singură parte) two layers (double-sided) două straturi (pe ambele părți) image file fișier imagine load image file încarcă fișier imagine Images Imagini Select an image file to load Selectați un fișier imagine de încărcat due to an xml problem: %1 line:%2 column:%3 datorită unei probleme xml: %1 line:%2 column:%3 because the xml is not correctly formatted fiindcă xml-ul nu este formatat corect the <board> element contains no shape elements elementul <placă> nu conține forma elementelor because there are multiple <board> layers fiindcă acolo sunt mai multe straturi <placă> because there are multiple <silkscreen> layers fiindcă acolo sunt mai multe straturi <silkscreen> because there are multiple <silkscreen0> layers fiindcă acolo sunt mai multe straturi <silkscreen0> because there is no <board> layer fiindcă acolo nu este stratul <placă> the svg contains no shape elements Fișierul svg nu conține forma elementelor but the pcb itself will have no silkscreen layer dar însuși pcb nu va avea stratul serigrafic the svg doesn't fit the custom board format fișierul svg nu se potrivește cu formatul personalizat al plăcii <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> <b>Forma personalizată a fost încărcată, iar dumneavoastră veți vedea în curând noua placă.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Înaintea producerii actualei PCB vă recomandăm să testați forma dumneavoastră personalizată utilizând opțiunea 'Fișier > Exportă pentru producție > Gerber extins'. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> Verificați fișierul contur rezultat cu o aplicație vizualizator Gerber ca să fiți sigur că forma a ieșit cum vă așteptați.<br/><br/> The rest of this message concerns 'cutouts'. Restul acestui mesaj se referă la 'decupaje'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> Acestea sunt găuri formate circular sau neregulat pe care le puteți incorpora facultativ într-o formă PCB personalizată.<br/><br/> <b>The custom shape has no cutouts.</b> <b>Forma personalizată nu are decupaje.</b> <b>The custom shape has %n cutouts.</b> <b>Forma personalizată are %n decupaj.</b> <b>Forma personalizată are %n decupaje.</b> <b>Forma personalizată are %n de decupaje.</b> <br/>However, the cutouts may not be formatted correctly. <br/>Oricum, decupajele pot fi neformatate corect. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, <br/><br/>Dacă intenționați ca forma dumneavoastră personalizată să aibe decupaje și nu ați obținut rezultatul așteptat, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. este fiindcă Fritzing are nevoie să faceți decupajele utilizând o formă operație 'scădere' sau 'diferență' în editorul dumneavoastră de grafică vectorială. Unable to load Nu se poate încărca Unable to load image from %1 %2 Nu se poate ăncărca imaginea de la %1 %2 Can load, but Se poate încărca, dar The image from %1 can be loaded, but %2 Use the file? Imaginea de la %1 poate fi încărcată, dar %2 Se utilizează fișierul? BoardLogoItem shape formă BreadboardLogoItem color culoare Set text color Configurați culoarea textului Select text color Selectați culoarea textului Capacitor Select from the dropdown, or type in a %1 value Selectați din meniul desfășurător, sau tastați o %1 valoare ConnectorItem Add bendpoint Adaugă bendpoint Straighten curve Îndreaptă curba Remove bendpoint Elimină bendpoint ConsoleSettings Settings Configurări Select Parameters Selectare parametrii BaudRate: Rată Baud: Data bits: Octeți date: Parity: Paritate: Stop bits: Octeți opriți: Flow control: Control flux: Select Serial Port Selectați portul serial Description: Descriere: Manufacturer: Fabricant: Serial number: Număr serial: Location: Locație: Vendor ID: ID vânzător: Product ID: ID produs: Apply Aplică Additional options Opțiuni suplimentare Local echo Ecou local Description: %1 Descriere: %1 Manufacturer: %1 Fabricant: %1 Serial number: %1 Număr serial: %1 Location: %1 Locație: %1 Vendor Identifier: %1 Identificator vânzător: %1 Product Identifier: %1 Identificator produs: %1 ConsoleWindow Serial Monitor Monitor serial Monitor Monitor Tools Unelte &About &Despre About program Despre program Alt+A Alt+A About Qt Despre Qt C&onnect C&onectare Connect to serial port Conectare la portul serial Ctrl+O Ctrl+O &Disconnect &Deconectare Disconnect from serial port Deconectare de la portul serial Ctrl+D Ctrl+D &Configure &Configurare Configure serial port Configurare port serial Alt+C Alt+C C&lear C&urăță Clear data Curăță datele Alt+L Alt+L &Quit &Termină Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Conectat la %1 : %2, %3, %4, %5, %6 Error Eroare Serial port open error Eroare deschidere port serial Disconnected Deconectat About Serial Monitor Despre monitorul serial This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Acest terminal afișează comunicația serială pe portul selectat, de obicei între computerul dumneavoastră și controlerul oglindă conectat. Critical Error Eroare critică DRC DRC was cancelled. DRC a fost anulat. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Schița este gata pentru producție: nu sunt conectori sau trasee care se suprapun sau sunt prea apropiate unul de celălalt. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Zona de pe placă evidențiată în roșu sunt conectori și trasee care se pot suprapune sau pot fi prea apropiate unul de celălalt. Reposition them and run the DRC again to find more problems Repoziționațile și rulați DRC din nou pentru a descoperii mai multe probleme Fritzing Fritzing Fritzing error: unable to render board svg. Eroare Fritzing: nu se poate randa placa în format svg. No traces or connectors to check Nu sunt trasee sau conectori de verificat Unexpected SVG rendering failure--contact fritzing.org Eșuare neașteptată randare svg--contactați fritzing.org %1 is overlapping (%2 layer) %1 suprapune(%2 strat) A hole in %1 may lie outside the border of the board and would be clipped. O gaură în %1 se poate afla în afara limitei și va fi tăiată. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Conectorul %1 pe %2 trebuie să aibă straturi de cupru atât sus cât și dedesubt, dar fișierul svg specifică numai un strat. Too close to a border (%1 layer) Prea aproape de o margine (%1 strat) DRCResultsDialog DRC Results Rezultate DRC Click on an item in the list to highlight of overlap it refers to. Apăsați pe un element în listă pentru a fi evidențiat dacă suprapunerea se referă la el. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Notificare: lista elementelor și evidențierea roșie nu se va actualiza în timp ce editați schița--trebuie să rulați din nou DRC. Evidențierea va dispare după ce veți închide acest dialog. DebugDialog for debugging pentru depanare DeleteDialog Also delete the file Șterge totodată și fișierul Remove Elimină Don't remove Nu elimina Dip chip label etichetă chip FApplication Fritzing failure Eșuare Fritzing Fritzing caught an exception %1 from %2 in event %3 Fritzing a prins o excepție %1 de la %2 în evenimentul %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing a prins o excepție de la %1 în evenimentul %2: %3 Fritzing caught an exception from %1 in event %2 Fritzing a prins o excepție de la %1 în evenimentul %2 Import files from previous version? Se importă fișiere din versiunea anterioară? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Doriți să importați componente și cuti pe care le-ați creat cu versiunile anterioare de Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Notă: Le puteți importa mai târziu utilizând acțiunea meniu "Ajutor" > "Importare componente și cuti din versiunile vechi...". Import Import Do not import now Nu importa acum Please specify an .fzz file name to save to (cancel will delete the backup) Specificați un nume fișier .fzz pentru salvare (anularea va șterge copia de rezervă) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help Ajutor prima utilizare <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. <br/> <b>Vizualizare placă testare</b> este destinată să arate ca o placă prototip din <i>viața reală</i>.<br/><br/>Începeți prin tragerea unei componente din coșul componentelor, care este pe partea dreaptă sus. Apoi trageți în mai multe părți, conectându-le prin plasarea lor pe placa de testare sau apăsând pe conectori și trăgând fire. Procesul este asemănător cu modul în care ați aranja lucrurile în lumea fizică. <br/><br/>După ce ați terminat cu crearea schiței în vizualizare placă de testare, încercați alte vizualizări. Puteți comuta vizualizările apăsând filele din partea de sus a ferestrei. Fiindcă diferite vizualizări au diferite întrebuințări, componentele vor arăta diferit în alte vizualizări. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. Bine ați venit la <b>Vizualizare schemă</b><br/><br/>Aceasta este o cale mai abstractă de a vedea componentele și conectorii decât Vizualizare placă testare. Aveți aceleași elemente pe care le aveți pe placa de testare, doar că arată diferit. Această reprezentare este mai aproape de schemele tradiționale utilizate de ingineri.<br/><br/>După ce ați desenat fire între părți, puteți apăsa &lt;Shift&gt;-clic cu mausul pentru a crea bend-points și a pune în ordine conexiunile. Vizualizare schemă vă poate ajuta să verificați dacă ați făcut conexiuni corecte între componente. Puteți și tipări schema pentru documentare. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> <b>Vizualizare PCB</b> este unde amplasați componentele pe o PCB fizică (Placă Circuit Imprimat-PCB).<br/><br/>PCB-urile pot fi făcute acasă sau într-un mic laborator utilizând procese de gravare DIY. De asemenea pot fi trimise unui serviciu profesional de fabricare PCB pentru o fabricare mai precisă. <br/><table><tr><td>Primul lucru de care aveți nevoie este o placă pe care să plasați componentele. Ar trebui să fie deja una în schița dumneavoastră, dar dacă nu este, trageți pictograma plăcii din cutia componentelor. Pictograma se aseamănă cu această imagine din dreapta: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/> Pentru amplasarea PCB, aranjați toate componentele astfel încât acestea să se potrivească bine pe placă. Apoi încercați să le deplasați împrejur pentru micșorarea lungimii și confuziei conectorilor. Puteți deasemenea să redimensionați plăcile dreptunghiulare. <br/><table><tr><td>Odată ce componentele sunt sortate, le conectați cu trasee de cupru. Puteți trasa un traseu de la conexiunile individuale sau utilizați autotrasarea pentru a le genera. Butonul de autotrasare este în partea de sus a ferestrei. Butonul se potrivește cu imaginea din dreapta:</td><td><img src=":resurse/imagini/miniaturi/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Închide fereastra Ctrl+W Ctrl+W Close the current sketch Închide schița curentă %1 - %2 %1 - %2 Specify a file name Specificați un nume fișier Save "%1" Salvează "%1" Do you want to save the changes you made in the document "%1"? Doriți să salvați modificările efectuate documentului "%1"? Your changes will be lost if you don't save them. Modificările vor fi pierdute dacă nu le salvați. Save... Salvează... Save Salvează Don't Save Nu salva Cancel Anulare Ctrl+D Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Diferența dintre o 'umple plan de masă' și doar 'umple cu cupru' este că într-o umplere cu plan de masă, zona inundată include trasee și conectori care sunt conectați la conectorii de 'masă'. Conectorii de împământare sunt de obicei marcați 'GND' sau 'ground' dar uneori nu este cazul. De asemenea, ar putea ca să fie mai multe rețele cu un conector de masă, și ați putea dori ca doar una dintre plase să fie completată Acest dialog colectează numai conectorii etichetați 'GND' sau 'ground', precum și conectoriideja aleți ca semințe. Apăsați un element pentru a evidenția conexiunile sale în schiță. Este deasemeni posibil să alegeți un conector ca sămânță umplere împământare cu click dreapta pe un conector și alegând opțiunea 'Set Ground Fill Seed' din meniul contextual. Cancel Anulare OK OK OK and ground fill OK și umple planul de masă OK and copper fill OK și umple cu cupru Hole hole size dimensiunea întreagă HtmlInfoView Change the part label here Schimbați aici eticheta părții Part breadboard view image Vizualizare imagine parte placă testare Part schematic view image Vizualizare imagine parte schemă Part pcb view image Vizualizare imagine parte pcb Part version number Număr versiune parte Locked Blocat Change the locked state of the part in this view. A locked part can't be moved. Schimbă starea blocat a părții în această vizualizare. O parte blocată nu poate fi mutată. Sticky Lipicios Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Schimbă starea "lipicios" a părții în această vizualizare. Când o parte lipicioasă este mutată, sunt mutate și obiectele de deasupra ei. Properties Proprietăți Placement Amplasare pcb layer strat pcb Tags Etichete Connections Conexiuni conn. conex. name nume type tip connected to %n item(s) conectat la %n element conectat la %n elemente conectat la %n de elemente (autoroutable) (autotrasabil) Wire Fir Ratsnest wire ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Fir ratsnest Trace wire %1 Traseu cablat %1 v. %1 %2 v. %1 %2 obsolete învechit location locație rotation rotație degrees grade ItemBase family familie type tip model model size dimensiune color culoare resistance rezistență capacitance capacitate inductance inductanță voltage tensiune current curent power putere pin spacing distanță pini rated power putere nominală rated voltage tensiune nominală rated current curent nominal version versiune package pachet shape formă form tabel part number număr parte maximum resistance rezistența maximă pins pini spacing distanțare frequency frecvență processor procesor variant variantă layers straturi tolerance toleranță descr descr filename nume fișier title titlu date dată rev rev sheet foaie project proiect banded marcat cu benzi top sus bottom jos copper bottom cupru dedesubt copper top cupru sus silkscreen bottom serigrafia dedesubt silkscreen top serigrafia sus Part Parte model part problem problemă model parte file for %1 %2 not found fișierul pentru %1 %2 nu a fost găsit unable to create renderer for svg %1 nu se poate crea randarea pentru fișierul svg %1 KicadModuleDialog Cancel Anulare OK OK LayerPalette show all layers arată toate straturile LinkDialog url: url: text: text: Cancel Anulare OK OK LogoItem text text shape formă due to a rendering error datorită unei erori de randare because the svg is empty fiindcă fișierul svg este gol because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting fiindcă acesta apare că este un fișier SVG exportat din CorelDRAW fără alegerea configurării 'atribute prezentare' due to an xml problem: %1 line:%2 column:%3 datorită unei probleme xml: %1 linie:%2 coloană:%3 because the file has no root element fiindcă fișierul nu are nici un element root because the file has no <svg> element fiindcă fișierul nu are nici un element <svg> for unknown reasons--possibly the image file is corrupted din motive necunoscute--posibil fișierul imagine este corupt Unable to display Nu se poate afișa Unable to display image from %1 Nu se poate afișa imaginea de la %1 MainWindow Rotate Rotire Share Partajare Flip Întoarce Autoroute Autotrasare Both Layers Ambele straturi Bottom Layer Stratul de jos Top Layer Stratul de sus Add a note Adaugă o notificare Export for PCB Exportă pentru PCB Ready Gata Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Click to highlight unconnected parts Apăsați pentru a evidenția componentele neconectate Fabricate Fabricat View from Above Vizualizare de deasupra View from Below Vizualizare de dedesubt Save %1 Salvează %1 Unable to open '%1': %2 Nu se poate deschide '%1': %2 Unable to open shareable '%1': %2 Nu se poate deschide partajabila '%1': %2 Unable to open shareable part '%1': %2 Nu se poate deschide partea partajabilă '%1': %2 Unable to load part from '%1' Nu se poate încărca partea din '%1' Specify a file name Specificați un nume fișier Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Nu se poate exporta %1 ca partajabil No Sketch found in '%1' Nu s-a găsit nici o schiță în '%1' Fritzing Part (*%1) Parte Fritzing (*%1) Unable to export %1 to shareable sketch Nu se poate exporta %1 la schița partajabilă MainWindow::moveToPartsFolder mainwindow missing Fereastraprincipală::mutăladosarulcomponentelor lipsește fereastra principală There is already a part with id '%1' loaded into Fritzing. Este deja o parte cu id '%1' încărcată în Fritzing. Do you want to keep the imported parts? Doriți să păstrați componentele importate? No connections to route Nu sunt conexiuni de trasat Routing completed Trasare finalizată Routing completed using %n jumper part(s) Trasarea s-a finalizat utilizând %n componenta jumper Trasarea s-a finalizat utilizând %n componente jumper Trasarea s-a finalizat utilizând %n de componente jumper %1 of %2 nets routed - %n connector(s) still to be routed %1 din %2 rețele trasate - %n conector urmează să fie trasat %1 din %2 rețele trasate - %n conectori urmează să fie trasați %1 din %2 rețele trasate - %n de conectori urmează să fie trasați %1 - [%2] %1 - [%2] No copper top layer Nu este strat de cupru superior The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Stratul de cupru superior (cupru 1) nu este disponibil pe o placă monoplacată. Comutați placa la dubluplacată sau alegeți stratul de cupru dedesubt (cupru 0). Sorry! Regretăm! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Nici o componentă cu aceste caracteristici. Lucrăm pentru a evita acest mesaj și permisiunea de a alege între proprietăți care nu există No exactly matching part found; Fritzing chose the closest match. Nu s-a găsit componenta potrivită perfect; Fritzing alege cea mai apropiată potrivire. Change to single layer pcb Schimbă la pcb cu un singur strat Change to two layer pcb Schimbă la pcb cu două straturi Swapped %1 with module %2 S-a schimbat %1 cu modulul %2 Change image to %2 Schimbă imaginea la %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 are lipsă un '%2' strat. Pentru mai multe informații despre cum să creeați o formă placă personalizată, consultați ghidul la<a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 se încarcă %1 Loading... Se încarcă... new sketch schița nouă Schematic conversion Conversie schemă Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Salvând această schiță va fi convertită la noul standard grafic pentru schemă. Se continuă și se convertește? Backing up '%1' Backing up '%1' Unrouted connections Conexiuni netrasate There are no unrouted connections in this view. Nu sunt conexiuni netrasate în această vizualizare. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Cod Welcome Bine ați venit Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Schița dumneavoastră nu are încă o placă! Adăugați un PCB în scopul de a o exporta la Gerber. Choose a folder for exporting Alegeți un dosar pentru export PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG Imagine (*.png) JPEG Image (*.jpg) JPEG Imagine (*.jpg) SVG Image (*.svg) SVG Imagine (*.svg) Printing... Se tipărește... All traces have not yet been routed. Toate traseele nu au fost încă trasate. Do you want to proceed anyway? Doriți să se continue oricum? Proceed Continuă Cancel Anulare Sketch exported Schița s-a exportat Export... Export... Exporting... Se exportă... Unable to save %1 Nu se poate salva %1 Cannot print to %1 Nu se poate tipări la %1 Cannot write file %1: %2. Nu se poate scrie fișierul %1: %2. Saved '%1' Salvat '%1' Select a Fritzing File to Open Selectați un fișier Fritzing de deschis Cannot find file %1. Nu se poate găsi fișierul %1. Cannot read file 1 %1: %2. Nu se poate citi fișierul 1 %1: %2. File '%1' not found Fișierul '%1' nu a fost găsit directly loading parts încărcare directă componente loading %1 (model) se încarcă %1 (model) loading %1 (breadboard) se încarcă %1 (placă testare) loading %1 (pcb) se încarcă %1 (pcb) loading %1 (schematic) se încarcă %1 (schemă) New Nou Ctrl+N Ctrl+N Create a new sketch Creați o schiță nouă &Open... &Deschide... Ctrl+O Ctrl+O BoM Text File (*.html) Fișier text BoM (*.html) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Schița nu are încă o placă! Adăugați un PCB pentru a o exporta gravabil. Etchable export can only handle one board at a time--please select the board you want to export. Exportul gravabil poate manipula numai o placă odată--selectați placa pe care doriți să o exportați. &Save &Salvează Ctrl+S Ctrl+S Save the current sketch Salvează schița curentă &Save As... &Salvează ca... Shift+Ctrl+S Shift+Ctrl+S Share online... Partajare online... Post a project to the Fritzing website Postează un proiect pe site-ul web Fritzing JPG... JPG... Export the visible area of the current sketch as a JPG image Exportă zona vizibilă a schiței curente ca o imagine JPG PNG... PNG... Export the visible area of the current sketch as a PNG image Exportă zona vizibilă a schiței curente ca o imagine PNG PostScript... PostScript... Export the visible area of the current sketch as a PostScript image Exportă zona vizibilă a schiței curente ca o imagine PostScript PDF... PDF... Export the visible area of the current sketch as a PDF image Exportă zona vizibilă a schiței curente ca un fișier PDF SVG... SVG... Export the current sketch as an SVG image Exportă schița curentă ca o imagine SVG List of parts (&Bill of Materials)... Lista componentelor (&Factura de materiale)... Save a Bill of Materials (BoM)/Shopping List as text Salvează o listă de materiale (BoM)/listă cumpărături ca text XML Netlist... netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist XML Netlist... Save a netlist in XML format netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist Salvează netlist în format XML SPICE Netlist... netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist SPICE Netlist... Save a netlist in SPICE format netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist Salvează netlist în format SPICE Eagle... Eagle... Export the current sketch to Eagle CAD Exportă schița curentă la Eagle CAD Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Exportă schița curentă în format Gerber extins (RS-274X) pentru producția profesională de PCB Export SPICE Netlist... netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist Exportă netlist SPICE... Gerber export can only handle one board at a time--please select the board you want to export. Exportul către Gerber poate manipula o singură placă odată selectați placa pe care doriți să o exportați. Sketch exported to Gerber Schița exportată la Gerber Export the current sketch to PDF for DIY PCB production (photoresist) Exportați schița curentă ca PDF pentru DIY producție PCB (fotorezistent) Export the current sketch to SVG for DIY PCB production (photoresist) Exportați schița curentă ca SVG pentru DIY producție PCB (fotorezistent) Etchable (PDF)... Gravabil (PDF)... Etchable (SVG)... Gravabil (SVG)... &Print... &Tipărește... Ctrl+P Ctrl+P Print the current view Tipărește vizualizarea curentă Shell launch %1 Lansare shell %1 throw test exception aruncă excepție test throw a fake exception to see what happens aruncă o excepție falsă pentru a vedea ce se întâmplă &Quit &Termină Ctrl+Q Ctrl+Q Quit the application Termină aplicația &Open Example &Deschide exemplu All Tot MainWindow::populateMenuWithIndex: couldn't load example with id='%1' Fereastraprincipală::populeazămeniucuindex: nu se pot încărca exemplul cu id='%1' &Open Recent Files &Deschide fișierele recente &%1 %2 &%1 %2 Undo Anulează Redo Refă &Cut &Taie Cut selection Taie selecția &Copy &Copiază Copy selection Copiază selecția &Paste &Lipește Paste clipboard contents Lipește conținutul memoriei temporare Paste in Place Lipește în Loc Paste clipboard contents in place Lipește conținutul memoriei temporare în loc &Duplicate &Duplicare Ctrl+D Ctrl+D Duplicate selection Duplică selecția &Delete &Șterge Delete selection Șterge selecția &Select All &Selectare tot Select all elements Selectare toate elementele &Deselect &Deselectare Deselect Deselectare Add Note Adaugă notificare &Preferences... &Preferințe... Show the application's about box Arată căsuța despre a aplicației &Edit &Editare &Add to bin... &Adaugă la cutie... Add selected part to bin Adaugă componenta selectată la cutie Disconnect All Wires Deconectează toate firele Disconnect all wires connected to this connector Deconectează toate firele conectate la acest conector Update InfoView on hover Actualizează informația vizualizare la planare Export Normalized SVG Exportă SVG normalizat Export 1000 dpi SVG of this part in this view Exportă SVG 1000 dpi a acestei componente în această vizualizare Export Normalized Flattened SVG Exportă SVG aplatizat normalizat Export 1000 dpi Flattened SVG of this part in this view Exportă 1000dpi SVG aplatizat a acestei componente în această vizualizare Rotate the selected parts by 90 degrees clockwise Rotește componentele selectate cu 90 de grade în sens orar Rotate the selected parts by 180 degrees Rotește componentele selectate cu 180 de grade Rotate current selection 90 degrees counter clockwise Rotește secțiunea curentă 90 de grade în sens antiorar Rotate current selection 45 degrees counter clockwise Rotește selecția curentă 45 de grade în sens antiorar Rotate current selection 45 degrees clockwise Rotește selecția curentă 45 de grade în sens orar the .fz file format is obsolete formatul fișier .fz este învechit The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? Formatul fișier .fz a fost învechit. Doriți să convertiți '%1' la formatul .fzz acum sau îl deschideți doar-citire? The conversion process will not modify '%1'. Procesul de conversie nu va modifica '%1'. Convert Convertește Read-only Doar-citire Please specify an .fzz file name to save '%1' to Specificați un nume fișier .fzz pentru a salva '%1' &Flip Horizontal &Întoarce orizontal Flip current selection horizontally Întoarce orizontal selecția curentă &Flip Vertical &Întoarce vertical Flip current selection vertically Întoarce vertical selecția curentă Bring to Front Adu în față Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Adu obiectul selectat(e) în fața stratului său Bring Forward Adu înainte Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Adu obiectul(ele) selectate înainte în stratul lor Send Backward Trimite înapoi Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Trimite obiectul(ele) selectat înapoi în stratul său Send to Back Trimite înapoi Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Trimite obiectul(ele) pe spatele stratului său Lock Part Blochează componentă Prevent a part from being moved Previne o componentă să fie mutată Select All Locked Parts Selectați toate componentele blocate Select all parts that can't be moved Selectați toate componentele care nu pot fi mutate &Show All Layers &Arată toate straturile Show all the available layers for the current view Arată toate straturile disponibile pentru vizualizarea curentă &Hide All Layers &Ascunde toate straturile Hide all the layers of the current view Ascunde toate straturile vizualizării curente &Show part label &Arată eticheta componentei Ctrl+Shift+V Ctrl+Shift+V Delete Minus Șterge minus Delete selection without attached wires Șterge selecția fără firele atașate Delete Wire up to bendpoints Șterge firul până la bendpoint-uri Dump all parts Depozitează toate componentele Debug dump all parts in this view Depanează depozitarea tuturor componentelor în această fereastră &Export... &Export... Export selected part Exportă componenta selectată Add Bendpoint Adaugă bendpoint Add a bendpoint to the selected wire Adaugă un bendpoint la firul selectat Convert Bendpoint to Via Convertește Bendpoint la Via Convert the bendpoint to a via Convertește bendpoint-ul la o via Convert Via to Bendpoint Convertește Via la Bendpoint Convert the via to a bendpoint Convertește via la un bendpoint Straighten Curve Îndreaptă curba Straighten the curve of the selected wire Îndreaptă curba firului selectat Select outdated parts Selectează componentele expirate Update selected parts Actualizează componentele selectate Open programming window Deschide fereastra de programare Open microcontroller programming window Deschide fereastra de programare a microcontrollerului &Zoom In &Mărește Ctrl++ Ctrl++ Zoom in Mărește Ctrl+= Ctrl+= &Zoom Out &Micșorează Ctrl+- Ctrl+- Zoom out Micșorează &Fit in Window &Potrivește în fereastră Ctrl+0 Ctrl+0 Fit in window Potrivește în fereastră &Actual Size &Dimensiune actuală Actual (real world physical) size Dimensiune (fizic lumea reală) actuală 100% Size Dimensiune 100% Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size dimensiune 100% (pixel) Align to Grid Aliniază la grilă Align items to grid when dragging Aliniază elementele la grilă când se trag Ctrl+5 Ctrl+5 &Show Welcome &Arată Bine ați venit Show the welcome view Arată vizualizarea de bun venit Show Code Arată codul Show the code (programming) view Arată vizualizarea codului (programare) &Routing &Trasare &Create trace from ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG &Crează traseu de la ratsnest Create a trace from the ratsnest line ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Crează un traseu de la linia ratsnest &Create wire from ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG &Creează fire de la ratsnest Create a wire from the ratsnest line ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Crează un fir de la linia ratsnest Select All Wires Selectați toate firele Select all wires Selectați toate firele Fill empty regions of the copper layer--not including traces connected to a GROUND Umple regiunile goale ale stratului de cupru--nu includ traseele conectate la o ÎMPĂMÂNTARE Fill empty regions of the copper layer--fill will include all traces connected to the seeds Umple regiunile goale ale stratului de cupru--umplerea va include toate pistele conectate la semințe Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Selectați orice piste unde poziția ecranului nu se potrivește cu poziția actuală. Este necesar numai pentru schițele trasate automat cu versiunea 0.7.10 sau anterioară Autorouter/DRC settings... Configurări autotrasor/DRC... Set autorouting parameters including keepout... Configurează parametri de autotrasare inclusiv zona de restricționare... jumpers jumpere copperfill umple cupru vias vias Do you want to update now? Doriți să actualizați acum? unable to find replacement for %1. nu se poate găsi înlocuitor pentru %1. &Show Breadboard &Arată placă testare Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Fișiere Fritzing (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Partajabile Fritzing (*%2);;Componentă Fritzing (*%3);;Cutie Fritzing (*%4);;Cutie partajabilă Fritzing (*%5) Revert? Inversați? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Această operație nu poate fi refăcută--veți pierde toate modificările. Continuați și inversați? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Deschide o schiță Fritzing (.fzz, .fz), sau încarcă o componentă Fritzing (.fzpz), sau o cutie componente Fritzing (.fzb, .fzbz) Revert Inversare Reload the sketch Reâncarcă schița &Delete Wire &Șterge fir Edit (new parts editor) Editare (editor componente noi) Open the new parts editor on an existing part Deschide editorul componente noi pe o componentă existentă Align Left Aliniază la stânga Align selected items at the left Aliniază elementele selectate la stânga Align Horizontal Center Aliniază centrul orizontal Align selected items at the horizontal center Aliniază elementele selectate la centrul orizontal Align Right Aliniază la dreapta Align selected items at the right Aliniază elementele selectate la dreapta Align Top Aliniază sus Align selected items at the top Aliniază sus elementele selectate Align Vertical Center Aliniază centrul vertical Align selected items at the vertical center Aliniază elementele selectate la centrul vertical Align Bottom Aliniază jos Align selected items at the bottom Aliniază jos elementele selectate Sticky Lipicios If a "sticky" part is moved, parts on top of it are also moved Dacă o componentă "lipicioasă" este mutată, sunt mutate și componentele de deasupra acesteia Show/hide the label for the selected parts Arată/ascunde eticheta pentru componentele selectate Find part in sketch... Găsește componentă în schiță... Search for parts in a sketch by matching text Caută componente într-o schiță potrivind textul Hide part silkscreen Ascunde partea serigrafică Hide/show the silkscreen layer for only this part Ascunde/arată stratul serigrafic numai pentru această parte Show Grid Arată grila Show the grid Arată grila Set Grid Size... Configurare dimensiune grilă... Set the size of the grid in this view Configurați dimensiunea grilei în această vizualizare Set Background Color... Configurează culoarea de fundal... Set the background color of this view Configurați culoarea de fundal a acestei vizualizări Ctrl+1 Ctrl+1 Show the breadboard view Arată vizualizarea placă testare &Show Schematic &Arată schema Ctrl+2 Ctrl+2 Show the schematic view Arată vizualizarea schemei &Show PCB &Arată PCB Ctrl+3 Ctrl+3 Show the PCB view Arată vizualizarea PCB Ctrl+4 Ctrl+4 Show Parts Bin Icon View Arată vizualizare pictogramă cutie componente Display the parts bin in an icon view Afișează cutia componentelor într-o vizualizare pictogramă Show Parts Bin List View Arată vizualizare listă cutie componente Display the parts bin in a list view Afișează cutia componentelor într-o vizualizare listă &Minimize &Minimizează Ctrl+M Ctrl+M Minimize current window Minimizează fereastra curentă Debugger Output Ieșire depanare Online Tutorials Tutoriale online Ctrl+? Ctrl+? Open Fritzing help Deschide ajutor Fritzing Donate to Fritzing Donați pentru Fritzing Open Fritzing donation web page Deschide pagina web Fritzing pentru donații Online Projects Gallery Galeria de proiecte online Open Fritzing examples Deschide exemple Fritzing Online Parts Reference Referință componente online Open Parts Reference Deschide referința componentelor First Time Help Ajutor prima pornire Check for updates... Verifică pentru actualizări... Test Connectors Conectori test Connect all connectors to a single test part Conectează toți conectorii la o singură componentă test Check whether a newer version of Fritzing is available for download Verifică dacă este disponiobilă o versiune Fritzing mai nouă pentru descărcare &About &Despre Tips, Tricks and Shortcuts Sfaturi, trucuri și scurtături Display some handy Fritzing tips and tricks Afișează unele sfaturi și trucuri Fritzing utile Display First Time Help Afișează ajutor prima pornire &About Qt &Despre Qt Show Qt's about box Arată căsuța despre Qt Report a bug... Raportați un defect de programare... Report a but you've found in Fritzing Raportați un defect pe care l-ați găsit în Fritzing Enable debugging log Activare jurnal depanare &Import parts and bins from old version... &Importă componente și cuti din versiunea veche... Import parts and bins from previous installation Importă componente și cuti din instalarea anterioară Parts Editor Help Ajutor editor componente Display Parts Editor help in a browser Afișează ajutorul pentru editorul componentelor într-un navigator &File &Fișier &Export &Export as Image ca imagine for Production pentru producție &Part &Componentă Raise and Lower Ridică și micșorează Rotate 45� Clockwise Rotește 135° în sens orar {45�?} Rotate 90� Clockwise Rotește 135° în sens orar {90�?} Rotate 180� Rotire 180° {180�?} Rotate 90� Counter Clockwise Rotește 45° în sens antiorar {90�?} Rotate 45� Counter Clockwise Rotește 45° în sens antiorar {45�?} Align Aliniază &View &Vizualizare &Window &Fereastră Ground Fill Umple cu plan de masă &Help &Ajutor Move to bottom layer Mută în stratul inferior Move to top layer Mută în stratul superior Delete Ratsnest Line ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Șterge linia ratsnest Delete Wire Șterge fir Hide part label Ascunde eticheta componentei Show part label Arată eticheta componentei Show part silkscreen Arată partea serigrafică Delete Șterge top and bottom sus și jos bottom jos top sus Ground Fill (%1) Umple cu plan de masă (%1) Copper Fill (%1) Umple cu cupru (%1) Actual Size Dimensiune actuală It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Se pare că nu este posibil să fie determinată automat dimensiunea fizică actuală a monitorului, astfel 'dimensiunea actuală' ca implementată curent este doar o aproximare. ,Cea mai bună alegere va fi să trageți o componentă riglă, apoi plasați o riglă reală (fizică) deasupra și acționați zoom-ul până ce acestea se potrivesc. Page Setup Configurare pagină Sorry, "%1" has not been implemented yet Regretăm, "%1" nu a fost implementat încă Autoroute connections... Autotrasare conexiuni... Shift+Ctrl+A Shift+Ctrl+A Set Ground Fill Keepout... Configurați zona de restricționare a planului de masă... Set the minimum distance between ground fill and traces or connectors Configurați distanța minimă dintre planul de masă și trasee sau conectori Design Rules Check (DRC) Verificare Reguli Design (DRC) Highlights any parts that are too close together for safe board production Evidențiază orice componente care sunt prea apropiate una de cealaltă pentru producția plăcii în siguranță Fritzing Fab Quote... Citat Fritzing Fab... How much would it could to produce a PCB from this sketch with Fritzing Fab Cât de mult ar putea să producă o PCB după această schiță cu Fritzing Fab View from below Vizualizare de dedesubt View the PCB from the bottom layers upwards Vizualizați PCB din straturile de jos în sus View from above Vizualizare de deasupra View the PCB from the top layers downwards Vizualizați PCB din straturile superioare în jos Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Schematic view update Actualizare vizualizare schemă There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Este un nou standard grafic pentru vizualizare schemă imagini componentă, începând cu versiunea 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? Doriți să convertiți acum '%1' la noul standard sau deschideți fișierul doar citire? The conversion process will not modify '%1', until you save the file. Procesul de conversie nu va modifica '%1', până veți salva fișierul. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Va trebui să rearanjați componentele și conexiunile în vizualizarea schemă, ca dimensiunea celor mai multe imagini componente vor avea modificări. Luați în considerare utilizarea trasării automate pentru a curăța traseele. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Rețineți că unele componente personalizate nu vor fi convertite. O unealtă pentru convertire 'dreptunghiulară' a imaginilor schemelor este disponibilă în Editorul componentelor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Notificare:dacă doriți să actualizați mai târziu, sunt opțiuni sub meniul 'Componente' pentru lucrul cu componente învechite individual. There are %n outdated part(s) in this sketch. Este %n componentă învechită în această schiță. Sunt %n componente învechite în această schiță. Sunt %n de componente învechite în această schiță. We strongly recommend that you update these %n parts to the latest version. Vă recomandăm să actualizați această %n componentă la ultima versiune. Vă recomandăm să actualizați aceste %n componente la ultima versiune. Vă recomandăm să actualizați aceste %n de componente la ultima versiune. This may result in changes to your sketch, as parts or connectors may be shifted. Aceasta poate rezulta în modificări aduse schiței, componente sau conectori pot fi mutați. %1 background %1 fundal Enter Text Introduceți text Text will match part label, description, title, etc. Enter text to search for: Textul se va potrivi cu eticheta componentei, descrierea, titlul, etc. Introduceți textul de căutat: Search Căutare No parts matched search term '%1'. Nici o componentă nu se potrivește cu termenul căutat '%1'. Do not autoroute Nu autotrasa When autorouting, do not rip up this trace wire, via, or jumper item Când se trasează automat, nu rupe acest traseu fir, via, sau elementul jumper Move to other side of the board Mută la altă parte a plăcii Show unrouted Arată netrasatele Highlight all unrouted connectors Evidențiază toți conectorii netrasați Select All CopperFill Selectează toate umplerile cu cupru Select all copper fill items Selectează toate elementele umplute cu cupru Select All "Don't Autoroute" Traces Selectează toate traseele "Nu trasa automat" Select All Autoroutable Traces Selectează toate traseele autotrasabile Select all trace wires that can be changed during autorouting Selectează toate traseele cablate care pot fi modificate în timpul autotrasării Select all jumper item parts Selectați toate componentele element jumper Select All Vias Selectați toate Vias Select all via parts Selectează toate componentele via Check Loaded Traces Verifică traseele încărcate Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Schița dumneavoastră nu are încă o placă! Adăugați o PCB în scopul utilizării trasatorului automat. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Selectați placa pe care doriți să o trasați automat. Trasatorul automat nu poate manipula decât o placă la un moment dat. The folder "%1" isn't a Fritzing installation folder Dosarul "%1" nu este un dosar instalare Fritzing Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Schița dumneavoastră nu are încă o placă! Adăugați o PCB în scopul de a utiliza împământarea sau umplerea cu cupru. Please select a PCB--copper fill only works for one board at a time. Selectați o PCB--umplerea cu cupru funcționează numai cu o singură placă la un moment dat. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Schița dumneavoastră nu are încă o placă! Adăugați o PCB în scopul de a elimina umplerea cu cupru. Please select a PCB--ground fill operations only work on a one board at a time. Selectați o PCB--operațiile de umplere împământare funcționează cu o singură placă la un moment dat. OK OK Set the grid size for %1. Configurează dimensiunea grilei pentru %1. Grid Size: Dimensiune grilă: in in mm mm Restore Default Restaurează implicite Your sketch does not have a board yet! DRC only works with a PCB. Schița dumneavoastră nu are încă o placă! DRC funcționează numai cu o PCB. Please select a PCB. DRC only works on one board at a time. Selectați o PCB. DRC funcționează numai cu o singură placă odată. DRC Progress... Progres DRC... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Schița dumneavoastră nu are încă o PCB! Adăugați o PCB cu scopul de a utiliza operațiile de umplere cu cupru. Please select a PCB. Copper fill operations only work on one board at a time. Selectați o PCB. Operațiile de umplere cu cupru funcționează numai cu o singură PCB la un moment dat. This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Aceasta va asigura în curând un export al schiței Fritzing la aplicația cu aspect EAGLE. Dacă doriți să aveți mai multe exporturi către unealta EDA favorită, anunțați-ne, sau contribuiți. Export SVG... Exportă SVG... Export Bill of Materials (BoM)... Exportă lista de materiale (BoM)... Unable to save BOM file, but the text is on the clipboard. Nu se poate salva fișierul BOM, dar textul este în memoria temporară a PC. Export Netlist... netlist is not curently translatable in romanian. see: http://en.wikipedia.org/wiki/Netlist Exportă netlist... Set both copper layers clickable Configurați ambele straturi de cupru să interacționeze cu mausul Set copper top layer clickable Configurați stratul de cupru de deasupra să interacționeze cu mausul Set copper bottom layer clickable Configurați stratul de cupru de dedesubt să interacționeze cu mausul Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Mută traseele selectate pe cealaltă parte a plăcii (notificare: 'primul' traseu va fi mutat iar restul îl va urma pe aceiași pistă) Select All Traces Selectează toate traseele Select all trace wires Selectează toate traseele cablate Force Update Routing Status and Ratsnests ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Forțează actualizarea stării trasării și ratsnest-uri Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Recalculează starea trasării și fire ratsnest (în caz de actualizare automată nu funcționează corect) Select all trace wires excluded from autorouting Selectează toate traseele cablate excluse de la autotrasare Select All Jumpers Selectează toți jumperii Tidy Wires Aranjează firele Tidy selected wires Aranjează firele selectate Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Umple regiunile goale ale stratului de cupru--umplerea va include toate traseele conectate la o ÎMPĂMÂNTARE Copper Fill Umplere cupru Remove Copper Fill Elimină umplere cupru Remove the copper fill Elimină umplerea cu cupru Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Tratează acest conector și conexiunile sale ca o 'împământare' în timpul umplerii cu plan de masă. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Shift+Ctrl+D Shift+Ctrl+D Copper Top and Copper Bottom layers are both active Straturile de cupru de deasupra și de dedesubt sunt ambele active Order a PCB... Comandați o PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Comandați o PCB creată după schița dumneavoastră--de la fabuloasa Fritzing Fab Copper Top layer is active Stratul superior de cupru este activ Copper Bottom layer is active Stratul inferior de cupru este activ Autorouting... Se autotrasează... Autorouting Progress... Progres autotrasare... Remove Bendpoint Elimină bendpoint Please choose the previous Fritzing folder... Alegeți dosarul Fritzing anterior... You will have to restart Fritzing in order to use the imported parts Trebuie să reporniți Fritzing pentru a utiliza componentele importate Generating %1 fill... Se generează %1 umplere... ground împământare copper cupru Remove copper fill Elimină umplerea cu cupru &Wire Color &Culoare fir Launch %1... Lansează %1... No outdated parts found. All your parts are up-to-date. Nu s-au găsit componente învechite. Toate componentele sunt actualizate. Outdated parts Componente învechite Successfully updated %1 part(s). Please check all views for potential side-effects. S-au actualizat cu succes %1 componentă(e). Verificați toate vizualizările pentru potențiale efecte secundare. Update %1 part(s) Actualizează %1 componentă(e) Inspector Inspector Undo History Anulează istoric Breadboard Placă testare Schematic Schemă PCB PCB Layers Straturi Couldn't get the dock widget Nu se poate obține controlul andocat MazeRouter Autorouter was cancelled. Autotrasarea a fost anulată. best so far: %1 of %2 routed cel mai bun de până acum: %1 din %2 trasat with %n vias cu %n vias cu %n de vias cu %n vias round %1 of: în jur de %1 din: Routing stopped! Trasarea este oprită! Use best so far... Utilizează cel mai bun de până acum... Optimizing traces... Se optimizează traseele... Routing complete! Trasare finalizată! Routing unsuccessful; stopping at round %1. Trasarea a eșuat; oprită la runda %1. Routing reached maximum round %1. Trasarea a tins runda maximă %1. Preparing undo... Se pregătește anularea... Unexpected SVG rendering failure--contact fritzing.org Eșuare randare SVG neașteptată--contactați fritzing.org ModelBase Unable to find the following %n part(s): Nu se poate găsi următoarea %n componentă: Nu se pot găsi următoarele %n componente: Nu se pot găsi următoarele %n de componente: at la File save failed! A eșuat salvarea fișierului! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Nu se poate suprascrie fișierul '%1'. Motivul: %2 (cod eroare %3) MysteryPart label etichetă chip label etichetă cip NetLabel net label etichetă net Note [write your note here] [scrieți notificarea aici] PCBSketchWidget Create Trace from Ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Crează traseu de la ratsnest Click this connector to drag out a new trace. Apăsați acest conector pentru a scoate afară un nou traseu. Change trace layer Schimbă stratul traseului Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Schița dumneavoastră nu are încă o placă! Adăugați un PCB în scopul de a utiliza umplerea cu cupru. %1 Fill: please select the board you want to apply fill to. %1 Umplut: selectați placa pe care doriți să aplicați umplerea. Ground Împământare Copper Cupru Copper fill: please select only the board you want to fill. Umplere cu cupru: selectați numai placa pe care doriți să o umpleți. Please designate one or more ground fill seeds before doing a ground fill. Desemnați una sau mai multe sămânțe plan de masă înaintea efectuării a unei umpleri cu masă. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Schița dumneavoastră nu are încă o placă! Adăugați o PCB în scopul de a utiliza această operație selectată. Please click on a PCB first--this selection operation only works for one board at a time. Apăsați întâi pe o PCB--această operație de selecție funcționează numai pe o singură placă la un moment dat. Fritzing error: unable to render board svg (1). Eroare Fritzing: nu se poate randa placa svg (1). Fritzing error: unable to render copper svg (1). Eroare Fritzing: nu se poate randa cuprul svg (1). Fritzing error: unable to write copper fill (1). Eroare Fritzing: nu se poate scrie umplerea cu cupru (1). Fritzing error: unable to write copper fill (2). Eroare Fritzing: nu se poate scrie umplerea cu cupru (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Nu se poate crea umplerea cu cupru--posibil că piesa nu a fost trasă pe PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Nu se poate crea umplerea cu cupru--posibil că piesa a fost trasă pe o altă parte sau fir mai degrabă decât pe actuala PCB. Clear ground fill seeds Curăță semințe umplere masă Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Schița dumneavoastră nu are încă o placă! Adăugați o PCB în scopul de a utiliza această operație selectată. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Nu se poate converti acest via la un bendpoint fiindcă este conectat la o componentă care este numai pe stratul de dedesubt și o altă componentă care este numai pe stratul de deasupra. Show part silkscreen Arată partea serigrafiată Hide part silkscreen Ascunde partea serigrafiată Fritzing Fab Quote Citat Fritzing Fab Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Schița dumneavoastră nu are încă o placă. Nu puteți fabrica această schiță fără o parte PCB. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Regretăm, http://fab.fritzing.org nu răspunde la citatul solicitat. Verificați conexiunea la rețea și/sau încercați mai târziu. Enter Keepout Introduceți zona de restricționare Keepout is in mils (.001 inches). Zona de restricționare este în mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils Rețineți că din cauza amestecării, distanțele pot fi prea scurte până la 2 miimi de inch so you may want to increase the keepout value by that much. astfel poate doriți să măriți valoarea zonei de restricționare cu atât de mult. 10 mils is a good default choice. 10 mils este o alegere implicită bună. Enter keepout value: Introduceți valoarea zonei de restricționare: PEConnectorsView This is where you edit the connector metadata for the part Aici este locul unde editați metadata conectorului pentru componentă number of connectors: număr de conectori: Through-hole Prin gaură SMD SMD PEMainWindow Parts Editor Editor componente SVG SVG There is one last edit still pending. Există o ultimă editare încă în așteptare. Duplicate 'family' property not allowed Nu este permisă duplicarea proprietății 'familie' Duplicate 'variant' property not allowed Nu este permisă duplicarea proprietății 'variantă' Close without saving? Se închide fără salvare? Close without saving Închide fără salvare Keep working Păstrați lucrul Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Este în regulă să ieșiți din editorul componentelor acum, cât timp vă reamintiți să terminați sarcinile mai târziu. Icon Pictogramă Metadata Metadată Connectors Conectori Show in Folder Arată în dosar On the desktop, open the folder containing the current svg file. Pe birou, deschideți dosarul conținând fișierul svg curent. Remove Internal Connection Elimină conexiunea internă Unable to write svg to %1 Nu se poate scrie svg la %1 Unable to parse fzp file %1 Nu se poate analiza fișierul fzp %1 Icon View Vizualizare pictogramă Metadata View Vizualizare metadată Connectors View Vizualizare conectori Show Icon Arată pictogramă Ctrl+4 Ctrl+4 Show the icon view Arată vizualizarea pictogramei Ctrl+5 Ctrl+5 Show the metadata view Arată vizualizarea metadatei Show Connectors Arată conectorii Ctrl+6 Ctrl+6 Change %1 to '%2' Modifică %1 la '%2' Change description Modifică descrierea Change tags Schimbă etichete Change properties Modifică proprietățile Change connector %1 Schimbă conectorul %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Fișiere imagine și amprentă (%1 %2 %3 %4 %5);;Fișiere SVG (%1);;Fișiere JPEG (%2);;Fișiere PNG (%3);;Fișiere amprentă gEDA (%4);;Fișiere modul Kicad (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Fișiere imagine (%1 %2 %3);;Fișiere SVG (%1);;Fișiere JPEG (%2);;Fișiere PNG (%3)%4%5 Open Image Deschide imaginea Copy problem Problemă la copiere Unable to make a local copy of: '%1' Nu se poate face o copie locală a: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. Puteți utiliza o imagine PNG sau JPG pentru a construi componenta, dar este cel mai bine să utilizați un SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- Imaginile PNG și JPG păstrează natura lor ca bitmap și nu arată bine când se scalează-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. astfel pentru componentele Fritzing este cel mai bine să utilizați PNG și JPG numai ca înlocuitori. Use of PNG and JPG discouraged Utilizarea PNG și JPG este descurajată Conversion problem Problemă la convertire Fritzing (New) Parts Editor Editor componente (nou) Fritzing Show Metadata Arată metadata Show the connector metadata in a list view Arată metadatele conectorului într-o vizualizare listă Blank not allowed Gol nu este permis The value of '%1' can not be blank. Valoarea a '%1' nu poate fi goală. Change %1 to %2 Modificați %1 la %2 Must be unique Trebuie să fie unic Variant '%1' is in use. The variant name must be unique. Varianta '%1' este în utilizare. Numele variantei trebuie să fie unic. Duplicate problem Problemă duplicare Unable to load '%1' Nu se poate încărca '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Fișierul SVG '%1' apare că a fost exportat din CorelDRAW fără configurarea 'patributele prezentării'. Please re-export the SVG file using that setting, and try loading again. Exportați din nou fișierul SVG utilizând acele configurări și încercați să-l încărcați din nou. Fonts Fonturi Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Fritzing actualmente suportă numai fonturile OCRA și Droid fonts--cu acestea au fost înlocuite fonturile din '%1' Unable to load image file '%1': %2 Nu se poate încărca fișierul imagine '%1': %2 SVG problem Problemă SVG The 'family' property can not be blank. Proprietatea 'familie' nu poate fi goală. A duplicate 'family' property is not allowed O duplicare a proprietății 'familie' nu este permisă A duplicate 'variant' property is not allowed O duplicare a proprietății 'variantă' nu este permisă This part can not be saved as-is: Această componentă nu poate fi salvată cum este: Do you want to keep working or close without saving? Doriți să continuați lucrul sau închideți fără salvare? This part has %n unassigned connectors Această componentă are %n conector neatribuit Această componentă are %n conectoare neatribuite Această componentă are %n de conectoare neatribuite across %n views. peste %n vizualizare. peste %n de vizualizări. peste %n vizualizări. Until all connectors are assigned to SVG elements, the part will not work correctly. Până ce toți conectorii nu sunt atribuiți elementelor SVG, componenta nu va funcționa corect. Layers Straturi Reuse breadboard image Reutilizează imagine placă testare Reuse the breadboard image in this view Reutilizează imaginea placă testare în această vizualizare Reuse schematic image Reutilizează imagine schemă Reuse the schematic image in this view Reutilizează imaginea schemei în această vizualizare Reuse PCB image Reutilizare imagine PCB Reuse the PCB image in this view Reutilizează imaginea PCB în această vizualizare Make only this view visible Fă numai această vizualizare vizibilă The part will only be visible in this view and icon view Componenta va fi vizibilă numai în această vizualizare și vizualizare pictogramă This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. Această versiune a noului Editor Componente nu poate lucra cu straturile cupru0 și cupru1 în '%1'. So editing may produce an invalid PCB view image Astfel editarea poate produce o imagine vizualizare PCB nevalidă Unable to parse '%1': %2 line:%3 column:%4 Nu se poate analiza '%1': %2 linia:%3 coloana:%4 There are no copper layers defined in: %1. Nu sunt straturi de cupru definite în: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. Consultați <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>Aceasta nu va mai fi o problemă în următoarea versiune a editorului componentelor, but for now please modify the file according to the instructions in the link. dar pentru moment modificați fișierul conform instrucțiunilor din link. no schematics found in %1 nu s-au găsit scheme în %1 schematic part parte schemă no footprints found in %1 Nu s-au găsit amprente în %1 Relocate connector %1 Realocare conector %1 &File &Fișier Inspector Inspector Load image for view... Încarcă imaginea pentru vizualizare... Open a file to use as the image for this view of the part. Deschide un fișier de utilizat ca imagine pentru această vizualizare a componentei. Convert schematic to 0.1 inch standard Convertește schema la 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Convertește imaginea schemei ante-0.8.6 la noul standard 0.1 inch Save as new part Salvează ca o componentă nouă Make a copy of the part and save it in the 'My Parts' Bin Fă o copie a componentei și salveaz-o în cutia 'Componentele mele' &Export &Export &Edit &Editare This part has bendable legs. Această componentă are picioare flexibile. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . Această versiune a editorului componente nu suportă încă editarea picioarelor flexibile, iar picioarele pot să nu fie afișate corect în vizualizare placă testare . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. Dacă faceți modificări vizualizării placă testare, sau modificați metadatele conectorilor, picioarele nu vor mai funcționa. You can safely make changes to Schematic or PCB view. Puteți efectua modificări în siguranță vizualizărilor Schemă sau PCB. This warning will not be repeated in this session of Fritzing Această avertizare nu se va mai repeta în această sesiune Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Nu se poate încărca '%1'. Închideți editorul componentelor fără să salvați și încercați din nou. Unable to load image file '%1' Nu se poate încărca fișierul imagine '%1' Filename prefix Prefix nume fișier Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Introduceți un prefix care să vă ajute să identificați fișierele componente. Numele va avea forma 'PREFIX_%1'. (nu este necesar să modificați prefixul, întrucât este adăugat întotdeauna un suffix unic.) Sketch Change Warning Atenționare modificare schiță The open sketch '%1' uses the part you are editing. Schița deschisă '%1' utilizează componenta pe care-ați editat-o. Saving this part will make a change to the sketch that cannot be undone. Salvând această componentă se va efectua o modificare schiței care nu mai poate fi anulată. The open sketches Schițele deschise '%1', '%1', and '%1' și '%1' Saving this part will make a change to these sketches that cannot be undone. Salvând această componentă se va efectua o modificare acestei schițe care nu poate fi anulată. Go ahead and save? Continuați și salvați? Save Salvează Cancel Anulare Move terminal point Mută punctul terminal Remove connector Elimină conector Remove %1 connectors Elimină %1 conectori Save "%1" Salvează "%1" Do you want to save the changes you made in the part "%1"? Doriți să salvați modificările pe care le-ați efectual în componenta "%1"? Your changes will be lost if you don't save them. Modificările vor fi pierdute dacă nu le salvați. untitled part componentă fără titlu Unable to load fzp from %1 Nu se poate încărca fzp de la %1 Unable to create new connector--you may have to start over. Nu se poate creea noul conector--va trebui să-l începeți peste. Add connector Adaugă conector Add %1 connectors Adaugă %1 conectori Remove internal connection from '%1' Elimină conexiunea internă de la '%1' Change all connectors to %1 Schimbă toți conectorii la %1 Unable to parse '%1' Nu se poate analiza '%1' Change to %1 Schimbă la %1 Make only %1 view visible Fă numai vizualizarea %1 vizibilă Internal connections are very messed up. Conexiunile interne sunt foarte încurcate. Add internal connection from '%1' to '%2' Adaugă conexiune internă de la '%1' la '%2' PEMetadataView This is where you edit the metadata for the part ... Aici este unde editați metadata pentru componenta ... Set the part's title Configurați titlul componentei Title Titlu Set the part's date Configurați data componentei Date Dată Set the part's author Configurați autorul componentei Author Autor Set the part's description--you can use simple html (as defined by Qt's Rich Text) Configurați descrierea componentei--puteți utiliza html simplu (cum este definit de textul formatat Qt) Description Descriere Set the default part label prefix Configurați prefixul implicit pentru eticheta componentei Label Etichetă Set the part's url if it is described on a web page Configurați URL-ul componentei dacă este descrisă pe o pagină web URL URL Set the part's family--what other parts is this part related to Configurați familia componentelor--cu ce alte componente este această componentă în legătură Family Familie Set the part's variant--this makes it unique from all other parts in the same family Configurați varianta componentei--aceasta o face unică față de alte componente în aceiași familie Variant Variantă Set the part's properties Configurați proprietățile componentei Properties Proprietăți Set the part's tags Configurați eticheta componentei Tags Etichete PESvgView width: lățime: height: înălțime: PEToolView Set Internal Connections Configurare conexiuni interne Set this checkbox to edit internal connections by drawing wires Configurați această casetă pentru editarea conexiunilor interne prin trasarea firelor Connector List (a checkmark means the graphic was selected) Listă conector (o bifare înseamnă că graficul a fost selectat) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Controale pentru configurarea punctului terminal. Punctul terminal este unde un fir va fi atașat conectorului. Puteți de asemenea să trageți firul conectorului curent Center Centru N N E E S S W W center centru west vest north nord south sud east est Sets the connector's terminal point to %1. Configurați punctul terminal al conectorului la %1. Modifies the x-coordinate of the terminal point Schimbă coordonatele-x ale punctului terminal Modifies the y-coordinate of the terminal point Schimbă coordonatele-y ale punctului terminal Dragging disabled Tragerea este dezactivată <font color='black'>Dragging enabled</font> <font color='black'>Tragerea activată</font> <font color='gray'>Dragging disabled</font> <font color='gray'>Tragerea dezactivată</font> Connector %1 Conector %1 Select graphic Selectare grafic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Utilizați locația curentă și rotița mausului pentru a naviga la elementul SVG pe care doriți să-l atribuiți conectorului curent, apoi coborâți mausul pentru a-l selecta. Pad shape formă center centru north nord east est south sud west vest connect to conectare la PaletteItem Edit Pin Labels Editare etichete pini Fritzing Fritzing Unable to proceed; unable to find top level view. Nu se poate proceda; nu se poate găsi vizualizarea părții de sus. Unable to proceed; part connectors do no have standard IDs. Nu se poate proceda; conectorii componentei nu au ID-uri standard. Label mismatch. Nothing was saved. Eticheta nu se potrivește. Nimic nu a fost salvat. hole size dimensiune gaură advanced settings configurări avansate in in mm mm Hole Diameter Diametru gaură Ring Thickness Cotele inelului PartLabel Edit Editare Edit label text Editare text etichetă Hide Ascunde Hide part label Ascunde eticheta componentei Display Values Afișează valorile Flip/Rotate Întoarce/Rotește Font Size Dimensiune font Rotate the label by 45 degrees clockwise Rotește eticheta cu 45 de grade în sens orar Rotate the label by 90 degrees clockwise Rotește eticheta cu 90 de grade în sens orar Rotate the label by 135 degrees clockwise Rotește eticheta cu 135 de grade în sens orar Rotate the label by 180 degrees Rotește eticheta cu 180 de grade Rotate the label by 135 degrees counter clockwise Rotește eticheta cu 135 de grade în sens antiorar Rotate current selection 90 degrees counter clockwise Rotește selecția curentă 90 de grade în sens antiorar Rotate 45� Clockwise Rotește 135° în sens orar {45�?} Rotate 90� Clockwise Rotește 135° în sens orar {90�?} Rotate 135� Clockwise Rotește 135° în sens orar {135�?} Rotate 180� Rotire 180° {180�?} Rotate 135� Counter Clockwise Rotește 45° în sens antiorar {135�?} Rotate 90� Counter Clockwise Rotește 45° în sens antiorar {90�?} Rotate 45� Counter Clockwise Rotește 45° în sens antiorar {45�?} Rotate the label by 45 degrees counter clockwise Rotește eticheta cu 45 de grade în sens antiorar Flip Horizontal Întoarce orizontal Flip label horizontally Întoarce eticheta orizontal Flip Vertical Întoarce vertical Flip label vertically Întoarce eticheta vertical Tiny Minuscul Set font size to tiny Configurează dimensiunea fontului ca minusculă Small Mic Set font size to small Configurează dimensiunea fontului ca mică Medium Mediu Set font size to medium Configurează dimensiunea fontului ca medie Large Larg Set font size to large Configurează dimensiunea fontului ca mare Label text Text etichetă Display the text of the label Afișează textul etichetei Display the value of property %1 Afișează valoarea proprietății %1 Set label for %1 Configurează eticheta pentru %1 Label text: Text etichetă: PartsBinPaletteWidget Untitled Bin Cutie fără titlu Save Salvează Specify a file name Specificați un nume fișier Fritzing Bin (*%1) Cutie Fritzing (*%1) Fritzing Fritzing Cannot find file %1. Nu se poate găsi fișierul %1. Cannot read file %1: %2. Nu se poate citi fișierul %1: %2. Loading... Se încarcă... loading bin '%1' se încarcă cutia '%1' Save bin "%1" Salvează cutia "%1" Do you want to save the changes you made in the bin "%1"? Doriți să salvați modificările efectuate în cutia "%1"? Your changes will be lost if you don't save them. Modificările vor fi pierdute dacă nu le salvați. Don't Save Nu salva Ctrl+D Ctrl+D Cancel Anulare Add to bin Adaugă la cutie Do you really want to add the selected part to the bin? Sigur doriți să adăugați componenta selectată la cutie? Change icon color... Schimbă culoarea pictogramei... Change the color of the icon for this bin. Schimbă culoarea pictogramei pentru această cutie. Select a color for this icon Selectați o culoare pentru această pictogramă Perfboard size dimensiune Performance Warning Atenționare performanță Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Performanța plăcilor perforate și a plăcilor cu benzi cu mai mult decât aproximativ 2000 de găuri poate fi lentă. Sunteți sigur? Notificare: această atenționare nu se va repeta în timpul acestei sesiuni. Set new size Configurați noua dimensiune Cancel Anulare rows rânduri columns coloane set board size configurați dimensiuinea plăcii PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Editor etichetă pin</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Apăsați pe o etichetă lângă un număr pin pentru a redenumi acel pin. You can use the tab key to move through the labels in order.</p> Puteți utiliza tasta tab pentru a muta printre etichete în ordine.</p> Cancel Anulare Save Salvează Undo Anulează Redo Refă PlatformArduino Running %1 %2 Rulează %1 %2 PlatformPicaxe Running %1 %2 Rulează %1 %2 PrefsDialog General General Cancel Anulare OK OK Mouse Wheel Behavior Comportament rotiță maus Command Comandă Control Control Change Wheel Behavior Schimbă comportamentul rotiței Code View Vizualizare cod Autosave Salvare automată Autosave every: Salvare automată la fiecare: minutes minute Language Limbă Colors Culori %1 (click to change...) %1 (apăsați să modificați...) Clear Settings Curăță configurările Platform Support Platformă suport <b>%1</b> <b>%1</b> Location: Locație: ... ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Trebuie să aveți instalată <a href='%1'>%2</a> (versiune %3 sau mai nouă). Select a programmer (executable) for %1 Selectați un programator (executabil) pentru %1 Connected Highlight Evidențiere conectat Unconnected Highlight Evidențiere neconectat no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom nici o tastă apăsată = derulare tasta shift schimbată derulare axială Alt sau tasta %1 = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis nici o tastă apăsată = zoom Alt sau tasta %1 = derulare tasta shift schimbată derulare axială Curvy vs. straight wires fire curbate vs. drepte When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? Când mausul coboară și trage de un fir sau de un pin al unei componente (spre deosebire de un conector sau bendpoint) doriți să modificați curbura firului (sau a pinului) sau să trasați un nou bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Această casetă configurează comportamentul implicit. Puteți comuta înapoi la comportamentul ne implicit ținând apăsată tasta Control (Mac: Command key) când trageți. Curvy wires and legs Fire și picioare curbate ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Deși este posibil să citiți și să editați fișiere program %1, nu este încă posibil să utilizați Fritzing să compilați sau să încărcați aceste programe într-un microcontroller. New Nou Save Salvează Open Deschide Platform Platformă Board Placă Port Port Serial Monitor Monitor serial Upload Încărcat Select a program file to load Selectați un fișier program de încărcat Fritzing is unable to find '%1', please locate it Fritzing nu poate găsi '%1', găsiți-o manual Code (*.%1) Cod (*.%1) Remove "%1"? Se elimină "%1"? Are you sure you want to remove "%1" from the sketch? Sigur doriți să eliminați "%1" din schiță? No uploader for %1 specified. Go to Preferences > Code View to configure it. Nu este specificat nici un încărcător pentru %1. Mergeți la Preferințe > Vizualizare cod pentru a-l configura. Uploader configured, but not found at %1 Încărcătorul este configurat, dar nu s-a găsit la %1 Upload finished. Încărcare finalizată. Upload failed with exit code %1, %2 Încărcarea a eșuat cu codul %1, %2 ProgramWindow No boards available Nu sunt plăci disponibile &Edit &Editare Undo Anulează Redo Refă &Cut &Taie Cut selection Taie selecția &Copy &Copiază Copy selection Copiază selecția &Paste &Lipește Paste clipboard contents Lipește conținutul memoriei temporare &Select All &Selectează tot Select all text Selectează tot textul &Preferences... &Preferințe... Show the application's about box Arată căsuța despre a aplicației &Code &Cod &New Tab &Filă nouă Create a new program tab Crează o nouă filă program &Import Code... &Importare cod... Alt+Ctrl+I Alt+Ctrl+I Import a program from a file Importă un program dintr-un fișier &Save Tab &Salvează fila Alt+Ctrl+S Alt+Ctrl+S Save the current program tab Salvează fila program curentă &Rename Tab &Redenumește fila Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Redenumește fila program curentă Close Tab Închide fila Alt+Ctrl+W Alt+Ctrl+W Remove the current program tab from the sketch Elimină fila program curentă din schiță Platform Platformă Board Placă Port Port Serial Monitor Monitor serial Ctrl+M Ctrl+M Monitor the serial port communication Monitorizează comunicația portului serial Upload Încarcă Ctrl+U Ctrl+U Upload the current program onto a microcontroller Încarcă programul curent într-un microcontroller Code Window Cod fereastră Code Window - %1 Cod fereastră - %1 %1%2 %1%2 &View &Vizualizare File '%1' was restored from the .fzz file; the local copy was not found. Fișierul '%1' a fost restaurat din fișierul .fzz; copia locală nu a fost găsită. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Fișierul '%1' a fost restaurat din fișierul .fzz; salvați o copie locală pentru a lucra cu un editor extern. QObject Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found Nu se poate autotrasa: nu s-a găsit placa (sau plăci multiple) No connections (on the PCB) to route. Nu sunt conexiuni (pe PCB) de trasat. No connections to route. Nu sunt conexiuni de trasat. Preferences Preferințe Please note that a new language setting will not take effect until the next time you run Fritzing. Rețineți că o nouă configurare a limbii nu va avea efect până ce nu reporniți Fritzing. Connected highlight color Culoare evidențiere conectat Unconnected highlight color Culoare evidențiere neconectat Clear all saved settings and close this dialog immediately. Curăță toate configurările salvate și închide imediat acest dialog. This action does not delete any files; it restores settings to their default values. Această acțiune nu șterge nici un fișier; restaurează configurările la valorile lor implicite. There is no undo for this action, and no further warning!!!! Nu este nici o refacere pentru această acțiune și nici viitoare atenționări!!!! Clear Settings Curăță configurările <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Fișierul '%1' este doar citire; utilizați un nume diferit. Edit link Editare legătură Part Componentă Wire Fir Set Grid Size Configurați dimensiunea grilei Cannot read file %1: %2. Nu se poate citi fișierul %1: %2. Parse error (1) at line %1, column %2: %3 %4 Eroare analiză (1) la linia %1, coloana %2: %3 %4 The file %1 is not a Fritzing file (2). Fișierul %1 nu este un fișier Fritzing (2). The file %1 is not a Fritzing file (4). Fișierul %1 nu este un fișier Fritzing (4). The file %1 is not a Fritzing file (3). Fișierul %1 nu este un fișier Fritzing (3). Cannot write file temp: %1 %2 %3. Nu se poate scrie fișierul temporar: %1 %2 %3. Parts folder not found. Dosarul componentelor nu s-a găsit. No parts found. Nu s-au găsit componente. Parse error (2) at line %1, column %2: %3 %4 Eroare analiză (2) la linia %1, coloana %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Componenta '%1' la '%2' nu are un id modul unic '%3'. Basic De bază Input Intrare Output Ieșire ICs CI-uri Power Alimentare Connection Conexiune Microcontroller Microcontroller Tools Unelte Shields Plăci de extensie LilyPad LilyPad Other Altul Sensors Senzori Part already in bin Componenta este deja în cutie The part that you have just added, is already there, we won't add it again, right? Componenta pe care tocmai ați adăugat-o, este deja acolo, nu dorim să o adăugăm iară, corect? a label o etichetă a value o valoare Select %1 Selectați %1 files fișiere Oops! Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Regretăm, avem o problemă cu mecanismul de schimbare. Fritzing continuă să funcționeze, dar nu veți putea să modificați proprietățile componentelor. bb bb Breadboard View Vizualizare placă testare PCB View Vizualizare PCB pcb pcb Select all 'Don't autoroute' traces Selectează toate pistele 'Nu autotrasa' Select all autorouteable traces Selectează toate traseele autotrasabile Convert to Via Convertește la Via Convert Via to Bendpoint Convertește Via la Bendpoint schem schemă Schematic View Vizualizare schemă Error reading file %1: %2. Eroare la citirea fișierului %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Schimbă piciorul al %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer %1 strat Bring forward Adu înainte Send backward Trimite înapoi Bring to front Adu în față Split Wire Desparte fir Join Wire Alătură fir Trace wires Traseu cablat Ratsnest wires ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Fire ratsnest Select all %1 Selectează tot %1 Select outdated parts Selectați componentele învechite Select locked parts Selectați componentele blocate unable to open %1 nu se poate deschide %1 unable to parse %1 nu se poate analiza %1 parse failure in %1 eșuare analiză în %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Regretăm, Fritzing nu poate încă manipula pini și pad-uri împreună (în %1) bad pin argument count număr argument pin greșit bad pad argument count pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. număr de argumente pad incorecte Unable to parse copper: %1 %2 %3 Nu se poate analiza cupru: %1 %2 %3 footprint %1 not found in %2 amprenta %1 nu s-a găsit în %2 unexpected end of file in footprint %1 in file %2 sfârșit de fișier neașteptat în amprenta %1 în fișierul %2 unexpected format (1) in %1 from %2 format neașteptat (1) în %1 de la %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Regretăm, Fritzing nu poate încă manipula pini și pad-uri împreună (în %1 în %2) unexpected end of file sfârșit neașteptat al fișierului pad missing drill pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. lipsesc găurile pad-ului pad missing attributes pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. lipsesc atributele pad-ului pad missing position pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. lipsește poziția pad-ului pad missing shape pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. lipsește forma pad-ului position missing params lipsă parametri poziție drill missing params lipsesc parametrii găurilor drill offset not implemented nu este implementată compensarea găurilor drill missing ellipse params lipsesc parametrii eliptici ai găurilor attributes missing params lipsă parametri atribute bad layer mask parameter parametru mască strat eronat Sorry, can't handle pad type %1 Regretăm, nu se poate manipula pad-ul de tip %1 pad shape missing params lipsesc parametrii formei pad-ului pad shape size is invalid dimensiunea formei pad-ului nu este validă trapezoidal pads not implemented nu este implementat pad-ul trapezoidal shape delta not implemented forma delta nu este implementată non-circular holes not implemented găuri ne-circulare nu sunt implementate non-copper holes not implemented găurile fără cupru nu sunt implementate unable to handle pad shape %1 nu se poate manipula forma pad-ului %1 bad schematic definition %1 definiție schemă eronată %1 schematic part %1 not found in %2 componenta schemei %1 nu s-a găsit în %2 schematic %1 unexpectedly ends (1) in %2 schema %1 s-a terminat neașteptat (1) în %2 schematic %1 unexpectedly ends (2) in %2 schema %1 s-a terminat neașteptat (2) în %2 schematic %1 unexpectedly ends (3) in %2 schema %1 s-a terminat neașteptat (3) în %2 failure in svg conversion 1: %1 %2 %3 a eșuat conversia în svg 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 a eșuat conversia în svg 2: %1 %2 %3 File Progress... Progres fișier... Copying file %1 Se copiază fișierul %1 File %1 already exists: it won't be overwritten Fișierul %1 deja există: nu va fi suprascris Check for updates Verifică pentru actualizări icon view vizualizare pictogramă breadboard view vizualizare placă testare schematic view vizualizare schemă pcb view vizualizare pcb Icon Pictogramă Breadboard Placă testare Parts Componente Wires Fire Part Labels Etichete componentă Ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Ratsnest Notes Notificări Rulers Rigle Frame Cadru Text Text Board Placă Silkscreen Top Serigrafia sus Silkscreen Top (Part Labels) Serigrafia sus (etichete componentă) Copper Fill Bottom Umple cupru dedesubt Copper Fill Top Umple cupru deasupra Copper Bottom Cupru de dedesubt Copper Bottom Trace Traseu cupru dedesubt Copper Top Cupru de deasupra Copper Top Trace Traseu cupru deasupra Silkscreen Bottom Serigrafia jos Silkscreen Bottom (Part Labels) Serigrafia jos (etichete componentă) Part Image Imagine componentă Unknown Layer Strat necunoscut outline is empty conturul este gol the board outline layer, stratul conturului plăcii, silkscreen layer(s), strat(e) serigrafic, copper layer(s), strat(uri) cupru, mask layer(s), mască strat(uri), paste mask layer(s), lipește masca strat(uri) Unable to translate svg curves in %1 Nu se pot interpreta curbele svg în %1 %1 layer export is empty. stratul %1 exportat este gol. exported drill file is empty fișierul găurilor exportat este gol exported mask layer %1 is empty masca strat %1 exportată este goală exported paste mask layer is empty masca strat lipită exportată este goală %1 layer: unable to save to '%2' stratul %1: nu se poate salva la '%2' Unable to save pick and place file: %2 Nu se poate salva alegerea și locul fișierului: %2 silk export failure a eșuat exportul stratului serigrafic %1 layer export is empty (case 2). stratul %1 exportat este gol (caz 2). silk layer %1 export is empty stratul serigrafic %1 exportat este gol drill export failure a eșuat exportul găurilor %1 mask export failure (2) a eșuat exportul măștii %1 (2) Fritzing is unable to process the cutouts in this custom PCB shape. Fritzing nu poate procesa decupajele în această formă PCB personalizată. You may need to reload the shape SVG. Este posibil să fie nevoie să reâncărcați forma SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Fritzing are nevoie să efectuați decupaje utilizând o formă 'scădere' sau 'diferență' operație în editorul dumneavoastră de grafică vectorială. mask export failure a eșuat exportul măștii Pin Label Editor Editor etichetă pin mm mm in in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. nu se poate copia fișierul '%1' la '%2'. %2 ... %1 wires moved from their saved position %2 ... %1 fire sunt mutate de la poziția lor salvată %1 wires moved from their saved position in %2. %1 fire sunt mutate de la poziția lor salvată în %2. ii ii Icon View Vizualizare pictogramă Internal Connections Conexiuni interne <b>id:</b> <b>id:</b> <b>Name:</b> <b>Nume:</b> Set the connectors's title Configurați titlul conectorilor <b>type:</b> <b>tip:</b> <b>Description:</b> <b>Descriere:</b> Set the connectors's description Configurați descrierea conectorilor Fritzing cannot load the parts bin Fritzing nu poate încărca cutia componentelor Set all to: Configurați totul la: Pad Pad : A flat area on a track of a printed circuit or on the edge of an integrated circuit to which wires or component leads can be attached to make an electrical connection. Pad Part %1 '%2' Componenta %1 '%2' Autorouter Settings Configurări autotrasare N/A N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Comandați PCB-ul dumneavoastră de la Fritzing Fab Copies Copii Please note that prices do not include shipping,<br /> Vă rugăm să rețineți că prețurile nu includ taxa de transport,<br /> possible additional taxes, or the checking fee.<br /> sunt posibile taxe suplimentare, sau taxa de verificare.<br /> %1 cm%3 (%2 in%3).<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Utilizați Fritzing Fab pentru a produce un PCB pentru schița dumneavoastră.<br /> Take advantage of our quantity discount: Profitați de avantajul discountul-ui nostru pentru cantitate: Visit Fritzing Fab Vizitați Fritzing Fab The total area of the %n PCB(s) in this sketch is Zona totală a %n PCB în această schiță este Zona totală a %n PCB-uri în această schiță este Zona totală a %n PCB-uri în această schiță este For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Pentru mai multe informații despre prețuri consultați <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Citat Fritzing Fab Price per board Preț pe tablă Price Preț RecoveryDialog File Fișier Last backup Ultima copie de rezervă Last saved Ultimul salvat file not saved fișierul nu este salvat <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Fritzing poate avea disfuncțiuni, dar unele dintre modificări ale următoarelor fișiere se pot recupera.</b></p><p>Este afișată data și ora la care fiecare fișier are creată o copie de siguranță. dacă fișierul a fost salvat, acea dată și oră este listată pentru comparare.</p><p>Fișierele originale sunt încă pe hard-disc, dacă acestea au fost salvate. Puteți alege dacă suprascrieți fișierul original după ce ați încărcat fișierul său de recuperare.</p><p><b>Selectați orice fișier pe care doriți să-l recuperați din lista de mai jos.</b></p> &Recover &Recuperează &Ignore &Ignoră Resistor Resistor Rezistor resistance rezistență You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' Puteți fie să tastați o valoare rezistență, sau să selectați una din meniul desfășurător. Forma nnn.dP unde P este unul dintre 'umkMG' ResizableBoard shape formă width: %1mm lățime: %1mm height: %1mm înălțime: %1mm width(mm) lățime(mm) height(mm) înălțime(mm) keep aspect ratio păstrează raportul aspectului Revert Inversat size dimensiune custom personalizat A0 (1030x1456) A0 (1030x1456) A1 (728x1030) A1 (728x1030) A2 (515x728) A2 (515x728) A3 (364x515) A3 (364x515) A4 (257x364) A4 (257x364) A5 (182x257) A5 (182x257) A6 (128x182) A6 (128x182) Letter (8.5x11) Scrisoare (8.5x11) Legal (8.5x14) Legal (8.5x14) Ledger (17x11) Ledger (17x11) Tabloid (11x17) Tabloid (11x17) Ruler width lățime S2S Failed loading '%1', %2 line:%3 col:%4 A eșuat încărcarea '%1', %2 linia:%3 col:%4 Schematic not found for '%1' Nu s-a găsit schema pentru '%1' Unable to load schematic '%1' for '%2' Nu se poate încărca schema '%1' pentru '%2' Schematic '%1' is already using the 0.1inch standard. Schema '%1' deja utilizează standardul de 0,1inch. Missing connector %1 in '%2' schematic of '%3' Conector lipsă %1 în '%2' schema a '%3' Uunable to load schematic '%1' for '%2' Nu se poate încărca schema '%1' pentru '%2' Failed loading schematic '%1', %2 line:%3 col:%4 A eșuat încărcarea schemei '%1', %2 linia:%3 col:%4 SchematicFrame Project Proiect Filename Nume fișier Date Dată Sheet Foaie Rev Rev shape formă of de date dată sheet foaie SchematicSketchWidget Change label from %1 to %2 Schimbă eticheta de la %1 la %2 Change voltage from %1 to %2 Schimbă tensiunea de la %1 la %2 SetColorDialog %1 Color... %1 Culoare... Choose %1 color: Alegeți culoare %1: Reset to default Resetare la implicite Default color (%1) Culoare implicită (%1) Pick custom color ... Alegeți culoarea personalizată ... Make this the default %1 color Fă asta culoarea implicită %1 Cancel Anulare OK OK Pick custom %1 color Alegeți culoarea personalizată %1 Current color (%1) Culoarea curentă (%1) SketchWidget loading part se încarcă componentă done loading s-a finalizat încărcarea %1 %2 %1 %2 %1 %2 items %1 %2 elemente Select All Selectează tot Deselect Deselectează Add %1 Adaugă %1 Selection Selecție Move %2 (%1) Mută %2 (%1) Move %2 items (%1) Mută %2 elemente (%1) Select %1 Selectați %1 Select %1 items Selectați %1 elemente Disconnect Deconectare Change Schimbă Connect Conectează to %1 la %1 Create and connect wire Creați și conectați fir Rotate %2 (%1) Rotește %2 (%1) Note text change Notă modificare text Rotate Rotește Flip Întoarce Double-click Dublu-click Delete ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Șterge ratsnest from %1 de la %1 Move leg of Mută piciorul de Change leg curvature for %1. Modifică curbura piciorului pentru %1. Change leg bendpoint for %1. Schimbă piciorul bendpoint pentru %1. Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Aceasta pare o încercarea de a creea un traseu peste straturi. Această împrejurare nu ar trebui să apară: contactați dezvoltatorii. Create and connect %1 Creați și conectați %1 wire fir trace traseu Flip %2 (%1) Întoarce %2 (%1) Drag or double-click Trage sau dublu-click or alt-drag to move the segment sau alt+trage pentru a muta segmentul Double-click to delete this bend point Click dublu pentru a șterge acest bendpoint Change %1 label to '%2' Schimbă eticheta %1 la '%2' Change %1 color from %2 to %3 Modifică culoarea %1 de la %2 la %3 Change color of %1 wires to %2 Schimbă culoarea a %1 fire la %2 Change %1 width from %2 to %3 Schimbă lățimea %1 de la %2 la %3 Change width of %1 wires to %2 Schimbă lățimea a %1 fire la %2 Move label '%1' Mută eticheta '%1' %1 label '%2' %1 etichetă '%2' show %n part label(s) arată %n eticheta componentei arată %n etichete componentă arată %n de etichete componentă hide %n part label(s) ascunde %n eticheta componentei ascunde %n etichete componentă ascunde %n de etichete componentă Resize ruler to %1 %2 Redimensionează rigla la %1 %2 test connectors testare conectori Resize Note Redimensionează notificarea Change Resistance from %1 to %2 Schimbă rezistența de la %1 la %2 Change %1 from %2 to %3 Schimbă %1 de la %2 la %3 Resize board to %1 %2 Redimensionează tabla la %1 %2 Create wire from Ratsnest ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG Creează fire de la ratsnest Disconnect all wires from %1 Deconectează toate firele de la %1 Disconnect all wires from %1 items Deconectează toate firele de la %1 elemente Change image from %1 to %2 Schimbă imaginea de la %1 la %2 change pin labels modifică etichetele pinilor Unrouted connections are highlighted in yellow. Conexiunile netrasate sunt evidențiate în galben. There are no unrouted connections Nu sunt conexiuni netrasate Unrouted connections Conexiuni netrasate %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. %1 Notificare: puteți deasemenea să declanșați acest afișaj prin trecerea mausului peste textul stare trasare în bara de stare. Part '%1' not found in sketch Componenta '%1' nu a fost găsită în schiță Add %1 parts Adaugă %1 componente Deselect all Deselectează tot SqliteReferenceModel The swapping mechanism is disabled for: Mecanismul de schimbare este dezactivat pentru: and %1 other parts și %1 alte componente and %1 other properties și %1 alte proprietăți property '%1' in part '%2' with id '%3'. proprietatea '%1' în componenta '%2' cu id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. componenta '%1' cu id '%2'; este posibil fiindcă nu are 'familie' proprietăți. Stripboard Restored Restaurat Cut Taie %1 %n strip(s) %1 %n bandă %1 %n benzi %1 %n de benzi rows rânduri columns coloane %1 layout %1 aspect SymbolPaletteItem voltage tensiune label etichetă Net labels Etichete rețea Net labels cannot be blank Etichetele rețea nu pot fi goale TipsAndTricks Fritzing Tips and Tricks Sfaturi și trucuri Fritzing Tips and Tricks Sfaturi și trucuri Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Fritzing depozitează fișierele pentru componentele personalizate, componentele generate și pentru alte întrebuințări temporare și de durată într-un 'dosar depozitare locală'. Pe Mac și Linux acesta este de obicei ~/.config/Fritzing/. Sub Windows Vista și următoarele este ceva gen C:\Users\[user name]\AppData\Roaming\Fritzing\; sub Windows XP este ceva gen C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples exemple Get a jump start by looking at the example circuits under File > Examples. Luați un start rapid consultând circuitele exemplu sub Fișier > Exemple. parts componente Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords Nu puteți găsi componenta? Căutați-o apăsând pictograma lupă în cutia componentelor și tastați unele cuvinte cheie If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor Dacă nu puteți găsi o componentă în Cutia componentelor, Generic IC vă este de ajutor. Trageți-l pe schiță, apoi utilizați controalele în inspector pentru: alegeți dintre 25 de găuri diferite și pachete SMD; modificarea etichetei pinului; și--pentru DIP-uri și SIP-uri--modificați numărul pinilor. Puteți de asemenea schimba numele pinilor cu editorul Etichetă Pin An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. O pictogramă în cutia componentelor poate reprezenta actual mai multe componente asociate. Astfel când trageți o pictogramă într-o schiță, asigurați-vă că ați consultat inspectorul. Inspectorul va afișa limitele alegerilor disponibile pentru modificarea unei componente, sau schimbați la o componentă asociată. Pictograma cutiei componentelor va fi de asemenea un pic 'îngrămădită' nu doar ca o pictogramă plată. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). Fereastra inspector--care vă permite să modificați proprietățile componentelor--este activată numai pentru componentele care sunt într-o schiță (nu pentru componentele aflate într-o cutie componente). moving and selection mutare și selecție To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. Pentru a constrânge mișcarea unei componente orizontal sau vertical, țineți apăsat tasta shift în timp ce trageți. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). Dacă aveți probleme la selectarea unei componente sau a unui fir (segment), încercați selectarea componentei care este în cale și trimiteți-o înapoi:utilizați funcțiile Ridică și Micșorează în meniul componentelor sau meniul contextual (click dreapta). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Pentru a muta cu mai mare precizie o selecție de componente, utilizați tastele săgeți. Shift-săgeată mută cu 10 unități. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. Apăsați pe indicatorul de poziție al mausului în bara de stare (dedesubt) pentru a comuta unitățile de la in la mm sau px. rotation rotire To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. Pentru a roti liber o componentă în vizualizare Placă testare sau PCB, selectați-o, apoi planați mausul lângă unul dintre colțuri până ce vedeți că se rotește cursorul. Coborâți mausul iar acel colț va urma mausul după cum trageți. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. Pentru a roti liber un text logo sau element imagine în vizualizarea PCB țineți apăsată tasta Alt (meta în Linux) și rotiți liber ca de obicei. layers and views straturi și vizualizări To drag the canvas, hold down the space bar and drag with the mouse. Pentru a trage canavaua, țineți apăsată bara de spațiu și trageți cu mausul. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. Pentru a declanșa vizibilitatea unui strat într-o vizualizare, mergeți la meniul vizualizării și alegeți unul dintre elementele vizualizării stratului. Sau deschideți paleta <b>Straturi</b> din meniul <b>Fereastră</b>. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. Când exportați imagini din Fritzing, puteți alege care straturi sunt exportate. Înainte să alegeți 'Export...', mergeți la meniul 'Vizualizare' și ascundeți straturile care nu doriți să fie vizibile. part labels etichete componentă To edit a part label, double-click it, or use the text input widget in the inspector window. Pentru a edita etichetă unei componente, dați dublu-click pe ea, sau utilizați controlul intrare text în fereastra inspector. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. Pentru a afișa proprietăți diferite în eticheta unei componente, precum și rotirea acesteia, sau schimbarea fontului, dați click-dreapta pe etichetă. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. Pentru a muta eticheta componentei independent de partea sa, selectați întâi componenta--atât componenta cât și eticheta vor fi evidențiate. Odată ce eticheta este selectată o puteți trage. wires and bendpoints fire și bendpoint-uri To add a bendpoint to a wire, double-click where you want the bendpoint. Pentru a adăuga un bendpoint la un fir, dublu-click unde doriți să adăugați bendpoint-ul. To delete a bendpoint from a wire, double-click it. Pentru a șterge un bendpoint de la un fir, dați dublu-click pe el. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. În vizualizarea Schemă sau PCB, dacă trageți de la un bendpoint cu tasta Alt apăsată (Linux: Meta), veți trasa un nou fir de la acel bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Pentru a trage un segment de fir (o secțiune a unui fir între două bendpoint-uri), trăgeți-le cu tasta Alt (Linux: Meta) apăsată. Dacă veți apăsa tasta Shift, segmentul de fir va fi limitat doar la mișcare orizontală sau verticală. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections conexiuni To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Pentru a vedea toți conectorii conectați la un conector dat, țineți mausul jos pe conector--toate conexiunile vor fi evidențiate. Check out Parts Editor Help under the <b>Help</b> Menu. Consultați ajutor editor componente din <b>Ajutor</b> Meniu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. Înainte să utilizați editorul componentelor, vedeți dacă Generic IC, Mystery Part, sau Pin Header va face sarcina. Odată ce trageți unele dintre acestea în schiță, puteți modifica numărul pinilor, distanța între pini și alte proprietăți. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. În editorul componentelor, pentru a selecta un grafic sub un alt grafic, utilizați rotița mausului în timp ce țineți apăsată tasta Shift. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Puteți utiliza Editorul componentelor pentru a găsi fișierul SVG pentru imaginea unei componente pentru o vizualizare dată. În editorul componentelor, apăsați pe fila pentru acea vizualizare, apoi utilizați <b>Arată în dosar</b> din meniul <b>Fișier</b> Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Nu depozitați fișierele parte personalizate în dosarul de instalare Fritzing. Dacă veți actualiza Fritzing, aceste fișiere probabil vor fi șterse. De asemenea, fișierele din dosarul de instalare Fritzing nu vor fi salvate în fișiere schiță (.fzz), astfel nu veți putea să le partajați. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. A fost produs PCB-ul dumneavoastră repede și ușor cu Fritzing Fab. Treceți peste butonul 'Fabricate' pentru a obține un citat. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. Când utilizați serviciul Fritzing Fab, Dacă sunt zone goale pe PCB pe care nu doriți să le umpleți cu cupru, utilizați componenta blocare cupru. Această componentă redimensionabilă va masca umplerea cu cupru în dreptunghiul care acoperă. notes notificări To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. Pentru a introduce un URL adresabil într-o notificare, selectați un text în notificare și tastați ctrl-l (Mac: command-l). (Acest 'l' ca în prima literă din 'link'.) Pentru a modifica un link existent selectați textul aferent link-ului și utilizați ctrl-l (command-l) din nou. local file storage depozit fișier local pcb layout aspect pcb curves and bendable legs curbe și picioare flexibile In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. În vizualizare Placă testare, pentru a trage o componentă cu picioare flexibile păstrând-o conectată la placa de testare, țineți tasta Alt apăsată (Linux: Meta) când începeți tragerea. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. În vizualizare Placă testare, pentru a trasa un fir de la terminația unui picior flexibil, trageți cu tasta Alt apăsată(Linux: Meta). In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. Prin gaură, componentele pot fi trase de pe o altă față a unui PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Vă ușurează viața trasarea traseelor orizontal pe o parte a unui PCB și vertical pe cealaltă parte. Route traces in 45-degree angles to reduce noise. Trasează traseele în unghi de 45 de grade pentru reducerea zgomotului. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Puteți pune propriul Logo pe serigrafia unei PCB a dumneavoastră. Doar utilizați partea Logo din biblioteca core și selectați propriul fișier. SVG este cel mai bun format. To create a custom shape for your PCB, import an SVG file. Pentru a creea o formă personalizată pentru PCB-ul dumneavoastră, importați un fișier SVG. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino Pentru a face o placă de extensie Arduino stilată ca niciodată, comutați forma PCB de la dreptunghiular la Arduino pcb production producție pcb Smaller PCBs are more affortable than larger ones. Save space and money. PCB-urile mici sunt mai accesibile decât cele mari. Salvați spațiu și bani. Use copper-blocker parts to mask out areas that you want free of copper fill. Utilizați componente blocare-cupru pentru a masca zona pe care doriți să nu fie umplută cu cupru. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. ratsnest is not translatable yet. see: http://commons.wikimedia.org/wiki/File:Rats_nest_diagram.JPG O linie ratsnest ('fir' foarte subțire) între conexiuni într-o vizualizare înseamnă că acele conexiunisunt cumva conectate în altă vizualizare. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). Pentru a schimba lățimea traseului, selectați un traseu apoi utilizați căsuța derulantă <b>lățime</b> din inspector. Puteți utiliza meniul derulant sau doar tastați un număr (de la 8 la 128) în căsuță. parts editor editor componente TraceWire Select from the dropdown, or type in any value from %1 to %2 Selectați din meniul derulant, sau tastați orice valoare de la %1 la %2 width lățime TranslatorListModel English - %1 Engleză - %1 French - %1 Franceză - %1 German - %1 Germană - %1 Spanish - %1 Spaniolă - %1 Japanese - %1 Japoneză - %1 Portuguese (European)- %1 Portugheză (europeană) - %1 Portuguese (Brazilian) - %1 Portugheză (braziliană) - %1 Hungarian - %1 Ungară - %1 Estonian - %1 Estoniană - %1 Dutch - %1 Olandeză - %1 Danish - %1 Daneză - %1 Russian - %1 Rusă - %1 Persian - %1 Persană - %1 Slovenian - %1 Slovenă - %1 Marathi - %1 Marathi - %1 Ukrainian - %1 Ucraineană - %1 Macedonian - %1 Macedoniană - %1 Serbian - %1 Sârbă - %1 Urdu - %1 Urdu - %1 Italian - %1 Italiană - %1 Hebrew - %1 Ebraică - %1 Arabic - %1 Arabă - %1 Hindi - %1 Hindi - %1 Chinese (Simplified) - %1 Chineză (simplificată) - %1 Chinese (Traditional) - %1 Chineză (tradițională) - %1 Polish - %1 Poloneză - %1 Czech - %1 Cehă - %1 Turkish - %1 Turcă - %1 Swedish - %1 Suedeză - %1 Romanian - %1 Română - %1 Thai - %1 Tailandeză - %1 Greek - %1 Greacă - %1 Bulgarian - %1 Bulgară - %1 Galician - %1 Galician - %1 Korean - %1 Koreană - %1 Indonesian - %1 Indoneziană - %1 Slovak - %1 Slovacă - %1 Bengali - %1 Bengali - %1 UpdateDialog Close Închide No new versions found. Nu s-au găsit versiuni noi. A new main release is available for downloading: O nouă versiune principală este disponibilă pentru descărcare: A new interim release is available for downloading: O nouă versiune interimară este disponibilă pentru descărcare: Checking... Se verifică... Sorry, unable to retrieve update info Regretăm, nu s-a putut obține informația de actualizare WelcomeView Recent Sketches Schițele curente New Sketch Schiță nouă Open Sketch Deschide schiță Fab Fabrică Shop Magazin Fritzing CreatorKit Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. Fritzing Creator Kit asigură o introducere rapidă, ușoară și distractivă în lumea electronicii interactive. order now >> comandați acum >> Get your Creator Kit now. Obțineți Creator Kit acum. Fritzing Fab Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. Fritzing Fab este un serviciu ușor și la prețuri accesibile pentru producerea de PCB-uri profesionale după schițele Fritzing ale dumneavoastră. produce your first pcb now >> produceți acum primul dumneavoastră pcb >> Order your PCB now. Comandați acum PCB-ul dumneavoastră. <a href='%1'><img src='%2'/></a> <a href='%1'><img src='%2'/></a> Projects Proiecte Blog Blog Fritzing News. Știri Fritzing. Fritzing Projects. Proiecte Fritzing. <a href='%1'><img src='%2' /></a> <a href='%1'><img src='%2' /></a> No recent sketches found Nu s-au găsit schițe curente Unable to reach blog.fritzing.org Nu se poate accesa blog.fritzing.org Unable to reach friting.org/projects Nu se poate accesa friting.org/projects Tip of the Day: Sfatul zilei: All Tips Toate sfaturile Next Tip Sfatul următor Wire super fine (8 mil) foarte fin (8 mil) extra thin (12 mil) subțirel (12 mil) thin (16 mil) subțire (16 mil) standard (24 mil) standard (24 mil) thick (32 mil) gros (32 mil) extra thick (48 mil) foarte gros (48 mil) blue albastru red roșu black negru yellow galben green verde grey gri white alb orange portocaliu ochre ocru cyan cian brown maro purple violet pink roz color culoare Banded Marcat cu benzi ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_ru.qm000066400000000000000000001431601250202676700217340ustar00rootroot00000000000000;;TrAvIxj$.r6^n^]hh/Ek( o!q(įbįZįF@H5ee5JKaz .*y*y*0*m2*l*%*%m*0H+h+s++++-HIXIXIXJ6KQo)P,ERU(iRxpRuUj#VgQXV1VXE;YTZ8,^B`gei'jcbjcbjcbgjewny{}q}}8T9&5u5ALV'$F$>'m$ GG *2s49tF?y4JvgWL#sTZe> ee}q5E}a,"~JszrrV^.͌Ӓ2ozo ./uU~SBN@YXYYtYZlTR-'uTEy9sSQ+;A1;Akuz;±I±yaHaxTCpqT!3%FdVRBhWw8rxqsu| [YS$o^eq[q|Sb@'zտ^fdX3u~Ig4+2n']'ev'5cSXl zbDMׅ!bpHɱ&IbII I yIIOI&fInFII}III/OM68`8n}~*X~ٶۘtBm:c DvU3^g);u?>BL.aqYb/,eeup(qS]}h$FG,XTOsBَBَ qr7gX:3L"QQMRN#_pe_z lCDIQDxLHLw@9@֣֣pޛ-D9$zl'S-3e;!%pEʇ\Ac Bc9h9i=5ksN^EDX4$54S?/{^~`A]*0Ra3gp( ,ιg82+I'&NO;YQ4b]Af|fei'vy7|Ԃ|^+|^W 1|*k[U"3{%1 \~ w:z } 0!S Gȧ Mgp{ Se lO u| ~ .0 Nj rNV ^  N! . a# 8< ՛U {uL ~X v- ?> !qG !qw_ #$/ CDv Uh [>T ^5V a4_ eKp eR!k k29 k2n suy NU* ,_ ^D ? A\ M vv vmz 0 G 06e K ;'6  i X %4 *\ *? ? 8+, N> Ys_ bR gP0 i$e# r iJ  F L ( aa qh .v KG B tuE # <` w L* 3 R #0Y O~ Wj `l@Z afL/ eZW^ r rp z nM z n "7( ,& ,  /, / ? 'bN K $ N o0 J (O _ 3F A# Ah [ Y f vC #Q 2 15| ~kA @1 _Fb{,.(u/GK6a. Sa.sfTSfTw=)-PiEnvnQC8FPSfxcPs?A]!4+ CuC-]^Bug$</`i8J^ivgU1l}$7 PF XjT*iJ<b>2007-%1 Fachhochschule >BA40<</b>%2007-%1 Fachhochschule PotsdamAboutBoxz<b>GNU GPL v3 =0 :>4 8 CreativeCommons:BY-SA =0 2AQ >AB0;L=>5?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxB<5=8BLCancelAutorouteProgressDialog"AB0=>28BL A59G0AStop NowAutorouteProgressDialogB<5=8BLCancelAutorouterSettingsDialog@8=OBLOKAutorouterSettingsDialogBinManager::setDirtyTab: 5 <>3C CAB0=>28BL bin '%1' :0: G5@=>28:;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerL5 <>3C CAB0=>28BL =C;52>9 bin B5:CI8<(Cannot set a NULL bin as the current one BinManagerFritzing Bin D09;K (*%1 *%2);;Fritzing Bin (*%1);;Fritzing 1I89 Bin (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManager>2K9 bin (%1) New bin (%1) BinManager '0AB8Parts BinManagerB>60;C9AB0, 2K15@8B5 8<O 4;O bin:!Please choose a name for the bin: BinManager#40;8BL 87 binRemove from bin BinManager"5@58<5=>20BL bin Rename bin BinManagerDK1@0BL D09; Fritzing 4;O >B:@KB8OSelect a Fritzing File to Open BinManagerF25BcolorBreadboardLogoItem  ?@>3@0<<5 (&A)&About ConsoleWindowKE>4(&Q)&Quit ConsoleWindow4;O >B;04:8 for debugging DebugDialog#40;8BLRemove DeleteDialog.5 8<?>@B8@>20BL A59G0ADo not import now FApplication <?>@BImport FApplicationL<?>@B8@>20BL D09;K ?@54K4CI59 25@A88?#Import files from previous version? FApplication>4A:07:8First Time HelpFirstTimeHelpDialog"0:@KBL :=> (&C) &Close WindowFritzingWindowB<5=8BLCancelFritzingWindow*0:@KBL B5:CI89 MA:87Close the current sketchFritzingWindowrK E>B8B5 A>E@0=8BL A45;0==K5 87<5=5=8O 2 4>:C<5=B5 "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindow5 A>E@0=OBL Don't SaveFritzingWindow!>E@0=8BLSaveFritzingWindow!>E@0=8BL "%1" Save "%1"FritzingWindow!>E@0=8BL...Save...FritzingWindow(#AB0=>28BL 8<O D09;0Specify a file nameFritzingWindowl0H8 87<5=5=8O 1C4CB CB5@O=K, 5A;8 2K 8E =5 A>E@0=8B5.1Your changes will be lost if you don't save them.FritzingWindowB<5=8BLCancelGroundFillSeedDialog@8=OBLOKGroundFillSeedDialog"(02B>B@0AA8@C5<>)(autoroutable) HtmlInfoView!>548=5=8O Connections HtmlInfoView!2>9AB20 Properties HtmlInfoView 5B:8Tags HtmlInfoView,"@0AA8@>20BL ?@>2>4 %1 Trace wire %1 HtmlInfoView @>2>4Wire HtmlInfoView?>4:;NG.conn. HtmlInfoView:?>4:;NG5=> : %n M;5<5=BC(-0<)0?>4:;NG5=> : %n M;5<5=BC2?>4:;NG5=> : %n M;5<5=B0<connected to %n item(s) HtmlInfoView=0720=85name HtmlInfoViewB8?type HtmlInfoView '0ABLPartItemBaseF25BcolorItemBaseA5<59AB2>familyItemBaseA>?@>B82;5=85 resistanceItemBaseB8?typeItemBaseB<5=8BLCancelKicadModuleDialog@8=OBLOKKicadModuleDialogB<5=8BLCancel LinkDialog@8=OBLOK LinkDialog%1 87 %2 ;8=89 @072545=K - %n @07JQ<>2 5IQ =C640NBAO 2 @072545=88%1 87 %2 ;8=89 @072545=K - %n @07JQ<>2 5IQ =C640NBAO 2 @072545=88%1 87 %2 ;8=89 @072545=K - %n @07JQ<>2 5IQ =C640NBAO 2 @072545=889%1 of %2 nets routed - %n connector(s) still to be routed MainWindow  ?@>3@0<<5 (&A)&About MainWindow& ?@>3@0<<5 Qt (&A) &About Qt MainWindow.$0:B8G5A:89 @07<5@ (&A) &Actual Size MainWindow.>1028BL 2 bin (&A)...&Add to bin... MainWindow!:>?8@>20BL(&C)&Copy MainWindowK@570BL(&C)&Cut MainWindow#40;8BL(&D)&Delete MainWindow&!=OBL 2K45;5=85(&D) &Deselect MainWindowC1;8@>20BL(&D) &Duplicate MainWindow" 540:B8@>20BL(&E)&Edit MainWindow-:A?>@B (&E)&Export MainWindow-:A?>@B (&E)... &Export... MainWindow$09; (&F)&File MainWindow&>4>3=OBL >:=> (&F)&Fit in Window MainWindow6B@078BL ?>-3>@87>=B0;8(&F)&Flip Horizontal MainWindow2B@078BL ?>-25@B8:0;8(&F)&Flip Vertical MainWindow><>IL (&H)&Help MainWindow&!:@KBL 2A5 A;>8(&H)&Hide All Layers MainWindowt<?>@B8@>20BL M;5<5=BK 8 bins 87 ?@54K4CI59 25@A88 (&I)...*&Import parts and bins from old version... MainWindow!25@=CBL(&) &Minimize MainWindow&B:@KBL ?@8<5@ &Open Example MainWindow0&B:@KBL ?>A;54=85 D09;K&Open Recent Files MainWindow&B:@KBL...&Open... MainWindow-;5<5=B(&P)&Part MainWindowAB028BL(&P)&Paste MainWindow 0AB@>9:8(&P)...&Preferences... MainWindow5G0BL(&P)... &Print... MainWindowKE>4(&Q)&Quit MainWindow!>E@0=8BL (&S)&Save MainWindow*!>E@0=8BL :0: (&S)... &Save As... MainWindow"K45;8BL 2AQ (&S) &Select All MainWindow,>:070BL 2A5 A;>8 (&S)&Show All Layers MainWindow8>:070BL <0:5B=CN ?;0BC (&S)&Show Breadboard MainWindow8>:070BL ?5G0B=CN ?;0BC (&S) &Show PCB MainWindowD>:070BL ?@8=F8?80;L=CN AE5<C (&S)&Show Schematic MainWindow:>:070BL <5B:8 M;5<5=B>2 (&S)&Show part label MainWindow84 (&V)&View MainWindow:=> (&W)&Window MainWindow"&25B ?@>2>40 (&W) &Wire Color MainWindow#25;8G8BL (&Z)&Zoom In MainWindow#<5=LH8BL (&Z) &Zoom Out MainWindow*>1028BL B>G:C 873810 Add Bendpoint MainWindow&>1028BL ?@8<5G0=85Add Note MainWindowV>1028BL B>G:C 873810 =0 2K45;5==>< ?@>2>45$Add a bendpoint to the selected wire MainWindow&>1028BL ?@8<5G0=85 Add a note MainWindowD>1028BL 2K45;5==K5 M;5<5=BK 2 binAdd selected part to bin MainWindow@5 2A5 A>548=5=8O 1K;8 @072545=K$All traces have not yet been routed. MainWindow2B>B@0AA8@>2:0 Autoroute MainWindow$2B>B@0AA8@>2:0...Autorouting... MainWindow0:5B=0O ?;0B0 Breadboard MainWindow$5@5<5AB8BL 2?5@Q4 Bring Forward MainWindowX5@5=5AB8 2K1@0==K5 >1J5:BK 2?5@Q4 2 8E A;>5/Bring selected object(s) forward in their layer MainWindowZ5@5<5AB8BL 2K1@0==K5 >1J5:BK =0704 2 8E A;>50Bring selected object(s) to front of their layer MainWindow 0 ?5@54=89 ?;0=Bring to Front MainWindowB<5=8BLCancel MainWindow,5 <>3C =09B8 D09; %1.Cannot find file %1. MainWindow25 <>3C @0A?5G0B0BL =0 %1Cannot print to %1 MainWindowZ5 C405BAO ?@>8725AB8 GB5=85 D09;0 1 %1: %2.Cannot read file 1 %1: %2. MainWindow@5 C405BAO 70?8A0BL D09; %1: %2.Cannot write file %1: %2. MainWindow.@>25@8BL >1=>2;5=8O...Check for updates... MainWindowp@>25@8BL 4>ABC?=>ABL =>2>9 25@A88 Fritzing 4;O 703@C7:8CCheck whether a newer version of Fritzing is available for download MainWindow6K15@8B5 ?0?:C 4;O M:A?>@B0Choose a folder for exporting MainWindow 0?>;=5=85 <54LN Copper Fill MainWindow*>?8@>20BL 2K45;5==>5Copy selection MainWindowB5 <>3C ?>;CG8BL 28465B 4>:C<5=B0Couldn't get the dock widget MainWindow&!>740BL =>2K9 MA:87Create a new sketch MainWindow&K@570BL 2K45;5==>5 Cut selection MainWindow*B;04>G=0O 8=D>@<0F8ODebugger Output MainWindow$#40;8BL 2K45;5==>5Delete selection MainWindow!=OBL 2K45;5=85Deselect MainWindow.BA>548=8BL 2A5 ?@>2>40Disconnect All Wires MainWindowtBA>548=8BL 2A5 ?@>2>40, ?>4:;NGQ==K5 : 40==><C A>548=5=8N0Disconnect all wires connected to this connector MainWindowB>:070BL ?>;57=K5 A>25BK Fritzing+Display some handy Fritzing tips and tricks MainWindowF!>E@0=8BL 8<?>@B8@>20==K5 M;5<5=BK?'Do you want to keep the imported parts? MainWindow6K 2AQ @02=> E>B8B5 =0G0BL?Do you want to proceed anyway? MainWindow,C1;8@>20BL 2K45;5==>5Duplicate selection MainWindowF-:A?>@B8@>20BL A?8A>: <0B5@80;>2...!Export Bill of Materials (BoM)... MainWindow0-A?>@B8@>20BL Netlist...Export Netlist... MainWindow-:A?>@B SVG... Export SVG... MainWindow8-:A?>@B 2K45;5==KE M;5<5=B>2Export selected part MainWindowR-:A?>@B B5:CI53> MA:870 2 87>1@065=85 SVG)Export the current sketch as an SVG image MainWindowF-:A?>@B B5:CI53> MA:870 2 Eagle CAD&Export the current sketch to Eagle CAD MainWindowr-:A?>@B 2848<>9 >1;0AB8 B5:CI53> MA:870 2 87>1@065=85 JPG@B 2848<>9 >1;0AB8 B5:CI53> MA:870 2 87>1@065=85 PDF@B 2848<>9 >1;0AB8 B5:CI53> MA:870 2 87>1@065=85 PNG@B 2848<>9 >1;0AB8 B5:CI53> MA:870 2 87>1@065=85 PostScriptCExport the visible area of the current sketch as a PostScript image MainWindow-:A?>@B... Export... MainWindow$-:A?>@B8@>20=85... Exporting... MainWindow>4A:07:8First Time Help MainWindow >4>3=0BL 2 >:=5 Fit in window MainWindowB>1@078BLFlip MainWindowRB@078BL B5:CI55 2K45;5=85 ?>-3>@87>=B0;8#Flip current selection horizontally MainWindowNB@078BL B5:CI55 2K45;5=85 ?>-25@B8:0;8!Flip current selection vertically MainWindow,-;5<5=B Fritzing (*%1)Fritzing Part (*%1) MainWindow8!:@KBL 2A5 A;>8 B5:CI53> 284'Hide all the layers of the current view MainWindowj<?>@B8@>20BL M;5<5=BK 8 bins 87 ?@54K4CI59 CAB0=>2:80Import parts and bins from previous installation MainWindow=A?5:B>@ Inspector MainWindow087>1@065=85 JPEG (*.jpg)JPEG Image (*.jpg) MainWindowTC?8A>: <0B5@80;>2 4;O 873>B>2;5=8O (&B)...%List of parts (&Bill of Materials)... MainWindowMainWindow::populateMenuWithIndex: =5 <>3C 703@C78BL ?@8<5@ A id='%1'EMainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow*!25@=CBL B5:CI55 >:=>Minimize current window MainWindow45B A>548=5=8O A <0@H@CB><No connections to route MainWindowB5B M;5<5=B>2 A B0:8<8 E0@0:B5@8AB8:0<8. K @01>B05< =04 B5<, GB>1K 871560BL MB>3> A>>1I5=8O, 8 2K <>3;8 @01>B0BL A ?0@0<5B@0<8, :>B>@K5 459AB28B5;L=> ACI5AB2CNBNo part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist MainWindow@8=OBLOK MainWindow.=;09= AAK;:8 M;5<5=B>2Online Parts Reference MainWindow.=;09=-30;5@5O ?@>5:B>2Online Projects Gallery MainWindow$=;09=-@C:>2>4AB2>Online Tutorials MainWindow0B:@KBL ?@8<5@K FritzingOpen Fritzing examples MainWindow0B:@KBL A?@02:C FritzingOpen Fritzing help MainWindow0B:@KBL AAK;:C M;5<5=B>2Open Parts Reference MainWindow5G0B=0O ?;0B0PCB MainWindow.87>1@065=85 PNG (*.png)PNG Image (*.png) MainWindow$#AB0=>2:8 AB@0=8FK Page Setup MainWindowBAB028BL A>45@68<>5 1CD5@0 >1<5=0Paste clipboard contents MainWindowl>60;C9AB0, 2K15@8B5 ?@54K4CICN 48@5:B>@8N Fritzing...-Please choose the previous Fritzing folder... MainWindowB03@C78BL ?@>5:B =0 A09B Fritzing&Post a project to the Fritzing website MainWindow(5G0BL B5:CI53> 2840Print the current view MainWindow5G0BL... Printing... MainWindow@>4>;68BLProceed MainWindow$KE>4 87 ?@>3@0<<KQuit the application MainWindow$>4=OBL 8 >?CAB8BLRaise and Lower MainWindow >B>2>Ready MainWindowB<5=8BLRedo MainWindow(#40;8BL B>G:C 873810Remove Bendpoint MainWindow*#40;8BL 70;82:C <54LNRemove Copper Fill MainWindow*#40;8BL 70;82:C <54LNRemove copper fill MainWindow*#40;8BL 70;82:C <54LNRemove the copper fill MainWindow:!>>1I8BL :0 2K =0H;8 Fritzing%Report a but you've found in Fritzing MainWindow>25@=CBLRotate MainWindow2>25@=CBL =0 180 {180?} Rotate 180� MainWindowd>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5 {135?} {45?}Rotate 45� Clockwise MainWindow^>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8 {45?}Rotate 45� Counter Clockwise MainWindowd>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5 {135?} {90?}Rotate 90� Clockwise MainWindow^>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8 {90?}Rotate 90� Counter Clockwise MainWindow>25@=CBL B5:CI89 2K1>@ =0 90 3@04CA>2 ?@>B82 G0A>2>9 AB@5;:8 {45 ?}5Rotate current selection 45 degrees counter clockwise MainWindowz>25@=CBL B5:CI89 2K1>@ =0 90 3@04CA>2 ?@>B82 G0A>2>9 AB@5;:85Rotate current selection 90 degrees counter clockwise MainWindowZ>25@=CBL2K45;5==K5 M;5<5=BK =0 180 3@04CA>2(Rotate the selected parts by 180 degrees MainWindow~>25@=CBL 2K45;5==K5 M;5<5=BK =0 90 3@04CA>2 ?> G0A>2>9 AB@5;:51Rotate the selected parts by 90 degrees clockwise MainWindow*"@0AA8@>2:0 7025@H5=0Routing completed MainWindow.SVG 87>1@065=85 (*.svg)SVG Image (*.svg) MainWindow!>E@0=8BL %1Save %1 MainWindowf!>E@0=8BL A?8A>: M;5<5=B>2/!?8A>: ?>:C?>: :0: B5:AB4Save a Bill of Materials (BoM)/Shopping List as text MainWindowD!>E@0=8BL :0: A?8A>: 2 XML D>@<0B5Save a netlist in XML format MainWindow.!>E@0=8BL B5:CI89 MA:87Save the current sketch MainWindow!>E@0=Q= '%1' Saved '%1' MainWindow(@8=F8?80;L=0O AE5<0 Schematic MainWindow$K1@0BL 2A5 B@0AAKSelect All Traces MainWindowDK1@0BL D09; Fritzing 4;O >B:@KB8OSelect a Fritzing File to Open MainWindow*K45;8BL 2A5 M;5<5=BKSelect all elements MainWindow8K45;8BL 2A5 B@0AAK ?@>2>4>2Select all trace wires MainWindowdK1@0BL 2A5 B@0AAK, 8A:;NGQ==K5 87 02B>B@0AA8@>2:80Select all trace wires excluded from autorouting MainWindow"B?@028BL >1@0B=> Send Backward MainWindowTB?@028BL 2K1@0==K9 >1J5:B(K) =0704 2 A;>9+Send selected object(s) back in their layer MainWindowTB?@028BL 2K1@0==K9 >1J5:B(K) 2 :>=5F A;>O2Send selected object(s) to the back of their layer MainWindowB?@028BL =0704 Send to Back MainWindow?C1;8:>20BLShare MainWindow,?C1;8:>20BL >=;09=...Share online... MainWindow$>:070BL >:=> > QtShow Qt's about box MainWindow^>:070BL 2A5 8<5NI85AO A;>8 4;O B5:CI53> @568<02Show all the available layers for the current view MainWindow.>:070BL ?5G0B=CN ?;0BCShow the PCB view MainWindow8>:070BL 8=D>@<0F8>==>5 >:=> Show the application's about box MainWindow.>:070BL <0:5B=CN ?;0BCShow the breadboard view MainWindow:>:070BL ?@8=F8?80;L=CN AE5<CShow the schematic view MainWindow&-A:87 M:A?>@B8@>20=Sketch exported MainWindow728=8B5!Sorry! MainWindowN A>60;5=8N, "%1" 5IQ =5 1K; @50;87>20=(Sorry, "%1" has not been implemented yet MainWindow"#:068B5 8<O D09;0Specify a file name MainWindowXSvg %1 >BACBAB2C5B A;>9 '%2'.;O ?>;CG5=8O 4>?>;=8B5;L=>9 8=D>@<0F88 > B><, :0: A>74020BL ?>;L7>20B5;LA:85 D>@<K ?;0B, A<. 8=AB@C:F88 ?> 04@5AC <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/. MainWindow0><5=OBL %1 A <>4C;5< %2Swapped %1 with module %2 MainWindow-B> ?>72>;8B M:A?>@B8@>20BL 0H Fritzing-MA:87 2 <0:5B EAGLE. A;8 K E>B8B5 2>7<>6=>ABL M:A?>@B0 2 4@C385 ?@>3@0<<K :><?LNB5@=>3> <>45;8@>20=8O, ?>60;C9AB0, 409B5 =0< 7=0BL, 8;8 2=5AB8 A2>9 2:;04.This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. MainWindow#1@0BL ?@>2>40 Tidy Wires MainWindow2#1@0BL 2K45;5==K5 ?@>2>40Tidy selected wires MainWindowH52>7<>6=> M:A?>@B8@>20BL %1 2 >1I89 Unable to export %1 as shareable MainWindowT52>7<>6=> M:A?>@B8@>20BL %1 2 >1I89 MA:87'Unable to export %1 to shareable sketch MainWindow.52>7<>6=> A>E@0=8BL %1Unable to save %1 MainWindowB<5=8BLUndo MainWindowAB>@8O >B<5= Undo History MainWindowB1=>28BL 8=D>@<0F8N ?@8 =02545=88Update InfoView on hover MainWindowXML A?8A>:...XML Netlist... MainWindow;O 8A?>;L7>20=8O 8<?>@B8@>20==KE M;5<5=B>2, 0< ?@845BAO ?5@570?CAB8BL FritzingDYou will have to restart Fritzing in order to use the imported parts MainWindow0H MA:87 5IQ =5 8<55B ?;0BK! >60;C9AB0, 4>102LB5 ?5G0B=CN ?;0BC 4;O M:A?>@B0 2 Gerber.VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber. MainWindow#25;8G8BLZoom in MainWindow#<5=LH8BLZoom out MainWindowB=5?>A@54AB25==> 703@C65==K5 G0AB8directly loading parts MainWindow>703@C605BAO %1 (<0:5B=0O ?;0B0)loading %1 (breadboard) MainWindow.703@C605BAO %1 (<>45;L)loading %1 (model) MainWindow>703@C605BAO %1 (?5G0B=0O ?;0B0)loading %1 (pcb) MainWindowJ703@C605BAO %1 (?@8=F8?80;L=0O AE5<0)loading %1 (schematic) MainWindowv5 <>3C ?5@570?8A0BL D09; '%1'. ?@8G8=0: %2 (:>4 >H81:8 %3)5Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ModelBase.H81:0 A>E@0=58O D09;0!File save failed! ModelBase@[=0?8H8B5 0H5 ?@8<5G0=85 745AL][write your note here]Note)Q;:=8B5 =0 40==>< A>548=5=88 4;O ?@>:;04K20=8O =>2>3> <0@H@CB0.-Click this connector to drag out a new trace.PCBSketchWidgetdH81:0 Fritzing : =5 <>3C 70:@0A8BL ?;0BC svg (1)./Fritzing error: unable to render board svg (1).PCBSketchWidgetbH81:0 Fritzing : =5 <>3C 70:@0A8BL <54L svg (1).0Fritzing error: unable to render copper svg (1).PCBSketchWidget0H MA:87 5IQ =5 8<55B ?;0BK! >60;C9AB0, 4>102LB5 ?5G0B=CN ?;0BC 4;O ?@>:;04:8 <54=KE 4>@>65:..UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.PCBSketchWidget" 540:B8@>20BL(&E)&Edit PEMainWindow-:A?>@B (&E)&Export PEMainWindow$09; (&F)&File PEMainWindow&>1028BL A>548=5=85 Add connector PEMainWindowB<5=8BLCancel PEMainWindow!>548=5=8O Connectors PEMainWindow :>=:0Icon PEMainWindow=A?5:B>@ Inspector PEMainWindow&B:@KBL 87>1@065=85 Open Image PEMainWindow$ 540:B>@ M;5<5=B>2 Parts Editor PEMainWindow!>E@0=8BLSave PEMainWindow!>E@0=8BL "%1" Save "%1" PEMainWindow 2B>@AuthorPEMetadataView?8A0=85 DescriptionPEMetadataView 5B:0LabelPEMetadataView!2>9AB20 PropertiesPEMetadataView 5B:8TagsPEMetadataView&B>1@078BL 25;8G8=KDisplay Values PartLabel,B>1@078BL B5:AB <5B:8Display the text of the label PartLabel>B>1@078BL 25;8G8=C A2>9AB20 %1 Display the value of property %1 PartLabel @02:0Edit PartLabel2 540:B8@>20BL B5:AB <5B:8Edit label text PartLabel2B>1@078BL ?>-3>@87>=B0;8Flip Horizontal PartLabel.B>1@078BL ?>-25@B8:0;8 Flip Vertical PartLabel>B>1@078BL <5B:C ?>-3>@87>=B0;8Flip label horizontally PartLabel:B>1@078BL <5B:C ?>-25@B8:0;8Flip label vertically PartLabel(B>1@078BL/>25@=CBL Flip/Rotate PartLabel 07<5@ H@8DB0 Font Size PartLabel"5:AB <5B:8 Label text PartLabel"5:AB <5B:8: Label text: PartLabel>;LH>9Large PartLabel!@54=89Medium PartLabelf>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5 {135?} {135?}Rotate 135� Clockwise PartLabel`>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8 {135?}Rotate 135� Counter Clockwise PartLabel2>25@=CBL =0 180 {180?} Rotate 180� PartLabeld>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5 {135?} {45?}Rotate 45� Clockwise PartLabel^>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8 {45?}Rotate 45� Counter Clockwise PartLabeld>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5 {135?} {90?}Rotate 90� Clockwise PartLabel^>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8 {90?}Rotate 90� Counter Clockwise PartLabelt>25@=CBL 2K45;5==>5 =0 90 3@04CA>2 ?@>B82 G0A>2>9 AB@5;:85Rotate current selection 90 degrees counter clockwise PartLabelj>25@=CBL <5B:C =0 90 ?@>B82 G0A>2>9 AB@5;:8 {135 ?})Rotate the label by 135 degrees clockwise PartLabel>>25@=CBL <5B:C =0 180 3@04CA>2Rotate the label by 180 degrees PartLabelh>25@=CBL <5B:C =0 90 ?@>B82 G0A>2>9 AB@5;:8 {45 ?}(Rotate the label by 45 degrees clockwise PartLabelZ>25@=CBL <5B:C =0 90 ?@>B82 G0A>2>9 AB@5;:8(Rotate the label by 90 degrees clockwise PartLabel@#AB0=>28BL 1>;LH>9 @07<5@ H@8DB0Set font size to large PartLabel@#AB0=>28BL A@54=89 @07<5@ H@8DB0Set font size to medium PartLabelD#AB0=>28BL <0;5=L:89 @07<5@ H@8DB0Set font size to small PartLabel.#AB0=>28BL <5B:C 4;O %1Set label for %1 PartLabel0;5=L:89Small PartLabel>1028BL 2 bin Add to binPartsBinPaletteWidgetB<5=8BLCancelPartsBinPaletteWidget,5 <>3C =09B8 D09; %1.Cannot find file %1.PartsBinPaletteWidgetB5 C40QBAO ?@>G8B0BL D09; %1: %2.Cannot read file %1: %2.PartsBinPaletteWidgetvK 459AB28B5;L=> E>B8B5, 4>1028BL 2K1@0==K9 'M;5<5=B 2 bin?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgethK E>B8B5 A>E@0=8BL 87<5=5=8O, 2=5AQ==K5 2 bin "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidget5 A>E@0=OBL Don't SavePartsBinPaletteWidget!>E@0=8BLSavePartsBinPaletteWidget"#:068B5 8<O D09;0Specify a file namePartsBinPaletteWidget&5>703;02;5==K9 Bin Untitled BinPartsBinPaletteWidgeth0H8 87<5=5=8O 1C4CB ?>B5@O=K, 5A;8 8E =5 A>E@0=8BL.1Your changes will be lost if you don't save them.PartsBinPaletteWidgetB<5=8BLCancel PerfboardB<5=8BLCancelPinLabelDialogB<5=8BLRedoPinLabelDialog!>E@0=8BLSavePinLabelDialogB<5=8BLUndoPinLabelDialog:%1 (06<8B5 4;O 87<5=5=8O...)%1 (click to change...) PrefsDialogB<5=8BLCancel PrefsDialog &25B0Colors PrefsDialog(K45;5=85 A>548=5=89Connected Highlight PrefsDialog/7K:Language PrefsDialog@8=OBLOK PrefsDialog.K45;5=85 =5A>548=Q==KEUnconnected Highlight PrefsDialog ;0B0Board ProgramTab!>E@0=8BLSave ProgramTab!:>?8@>20BL(&C)&Copy ProgramWindowK@570BL(&C)&Cut ProgramWindow" 540:B8@>20BL(&E)&Edit ProgramWindowAB028BL(&P)&Paste ProgramWindow 0AB@>9:8(&P)...&Preferences... ProgramWindow"K45;8BL 2AQ (&S) &Select All ProgramWindow84 (&V)&View ProgramWindow ;0B0Board ProgramWindow*>?8@>20BL 2K45;5==>5Copy selection ProgramWindow&K@570BL 2K45;5==>5 Cut selection ProgramWindowBAB028BL A>45@68<>5 1CD5@0 >1<5=0Paste clipboard contents ProgramWindowB<5=8BLRedo ProgramWindow8>:070BL 8=D>@<0F8>==>5 >:=> Show the application's about box ProgramWindowB<5=8BLUndo ProgramWindow%1 A;>9%1 LayerQObject<font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule >BA40<</font>t© 2007-%1 Fachhochschule PotsdamQObject ;0B0BoardQObject0:5B=0O ?;0B0 BreadboardQObject0:5B=0O ?;0B0Breadboard ViewQObject$5@5<5AB8BL 2?5@Q4 Bring forwardQObject 0 ?5@54=89 ?;0=Bring to frontQObject<5 <>3C ?@>G8B0BL D09; %1: %2.Cannot read file %1: %2.QObject(@>25@8BL >1=>2;5=8OCheck for updatesQObject7<5=8BL AAK;:C Edit linkQObject&K?>;=5=85 D09;0...File Progress...QObject :>=:0IconQObject !>548=8BL ?@>2>4 Join WireQObject*-;5<5=B>2 =5 =0945=>.No parts found.QObject@8<5G0=8ONotesQObject>9!Oops!QObject5G0B=0O ?;0B0PCB ViewQObjectp!8=B0:A8G5A:0O >H81:0 (1) 2 AB@>:5 %1, AB>;15F %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObjectn!8=B0:A8G5A:0O >H81:0(2) 2 AB@>:5 %1, AB>;15F %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObject-;5<5=BPartQObject5B:8 M;5<5=B>2 Part LabelsQObject"-;5<5=B C65 2 binPart already in binQObject-;5<5=BKPartsQObject0AB@>9:0 PreferencesQObject(8=88 4;O A>548=5=8ORatsnest wiresQObject@028;0RulersQObject(@8=F8?80;L=0O AE5<0Schematic ViewQObjectK1@0BL %1 Select %1QObjectK1@0BL 2A5 %1 Select all %1QObject"5@5<5AB8BL =0704 Send backwardQObject A>60;5=8N, C =0A 5ABL ?@>1;5<0 A <5E0=87<>< 70<5=K. Fritzing ?>-?@56=5<C @01>B05B, => 2K =5 A<>65B5 87<5=8BL A2>9AB20 M;5<5=BK.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObject$ 07J548=8BL ?@>2>4 Split WireQObjectP$09; %1 =5 O2;O5BAO D09;>< Fritzing (2).'The file %1 is not a Fritzing file (2).QObjectP$09; %1 =5 O2;O5BAO D09;>< Fritzing (3).'The file %1 is not a Fritzing file (3).QObjectP$09; %1 =5 O2;O5BAO D09;>< Fritzing (4).'The file %1 is not a Fritzing file (4).QObject$09; '%1' B>;L:> 4;O GB5=8O; ?>60;C9AB0, 8A?>;L7C9B5 4@C3>5 8<O D09;0.3> 845=B8D8:0B>@0 <>4C;O '%3'.B>@K9 K B>;L:> GB> 4>1028;8, C65 B0< 5ABL, <K =5 <>65< 4>1028BL 53> A=>20, 25@=>?RThe part that you have just added, is already there, we won't add it again, right?QObject"@0AAK ?@>2>4>2 Trace wiresQObject 58725AB=K9 A;>9 Unknown LayerQObject @>2>4WireQObject@>2>40WiresQObject O@;K:a labelQObject25;8G8=0a valueQObject<0:5B=0O ?;0B0breadboard viewQObject 7=0G:8 icon viewQObject?5G0B=0O ?;0B0pcbQObject?5G0B=0O ?;0B0pcb viewQObject AE5<0schemQObject(?@8=F8?80;L=0O AE5<0schematic viewQObjectA>?@>B82;5=85 resistanceResistor H8@8=0widthRuler<7<5=8BL =0?@O65=85 A %1 =0 %2Change voltage from %1 to %2SchematicSketchWidgetB<5=8BLCancelSetColorDialog<!45;0BL %1 F25B>< ?>-C<>;G0=8NMake this the default %1 colorSetColorDialog@8=OBLOKSetColorDialog%1 %2 M;5<5=B %1 %2 items SketchWidget%1 <5B:0 '%2' %1 label '%2' SketchWidget>1028BL %1Add %1 SketchWidget7<5=8BLChange SketchWidget67<5=8BL %1 F25B A %2 =0 %3Change %1 color from %2 to %3 SketchWidget47<5=8BL %1 <5B:C 4;O '%2'Change %1 label to '%2' SketchWidget:7<5=8BL %1 H8@8=C A %2 =0 %3Change %1 width from %2 to %3 SketchWidget>7<5=8BL F25B %1 ?@>2>4>2 =0 %2Change color of %1 wires to %2 SketchWidgetB7<5=8BL H8@8=C %1 ?@>2>4>2 =0 %2Change width of %1 wires to %2 SketchWidget!>548=8BLConnect SketchWidget6!>740BL 8 ?>4:;NG8BL ?@>2>4Create and connect wire SketchWidget!=OBL 2K45;5=85Deselect SketchWidgetB:;NG8BL Disconnect SketchWidget6B:;NG8BL 2A5 ?@>2>40 >B %1Disconnect all wires from %1 SketchWidgetJB:;NG8BL 2A5 ?@>2>40 >B %1 M;5<5=B>2"Disconnect all wires from %1 items SketchWidget2>9=>9 I5;GQ: Double-click SketchWidget^2064K I5;:=8B5, GB>1K C40;8BL MBC B>G:C 873810&Double-click to delete this bend point SketchWidget:5@5B0I8BL 8;8 42>9=>9-I5;GQ:Drag or double-click SketchWidget>25@=CBLFlip SketchWidget&5@5<5AB8BL %2 (%1) Move %2 (%1) SketchWidget65@5<5AB8BL %2 M;5<5=B (%1)Move %2 items (%1) SketchWidget,5@5<5AB8BL <5B:C '%1'Move label '%1' SketchWidget47<5=8BL @07<5@ ?@8<5G0=8O Resize Note SketchWidget07<5=8BL @07<5@ =0 %1 %2Resize board to %1 %2 SketchWidget@0I0BLRotate SketchWidget">25@=CBL %2 (%1)Rotate %2 (%1) SketchWidgetK1@0BL %1 Select %1 SketchWidget&K1@0BL %1 M;5<5=BKSelect %1 items SketchWidgetK45;8BL 2AQ Select All SketchWidgetK45;5=85 Selection SketchWidget$703@C7:0 7025@H5=0 done loading SketchWidget"703@C7:0 M;5<5=B0 loading part SketchWidget48;8 Alt-?5@5B0I8BL A53<5=Bor alt-drag to move the segment SketchWidget: %1to %1 SketchWidget>;57=K5 A>25BKTips and Tricks TipsAndTricks H8@8=0width TraceWire@01A:89 - %1 Arabic - %1TranslatorListModel >;;0=4A:89 - %1 Dutch - %1TranslatorListModel=3;89A:89 - %1 English - %1TranslatorListModel $@0=FC7A:89 - %1 French - %1TranslatorListModel5<5F:89 - %1 German - %1TranslatorListModel2@8B - %1 Hebrew - %1TranslatorListModel%8=48 - %1 Hindi - %1TranslatorListModel5=35@A:89 - %1Hungarian - %1TranslatorListModel B0;LO=A:89 - %1 Italian - %1TranslatorListModel/?>=A:89 - %1 Japanese - %1TranslatorListModel>>@BC30;LA:89 (@078;LA:89)- %1Portuguese (Brazilian) - %1TranslatorListModel>>@BC30;LA:89 (2@>?59A:89)- %1Portuguese (European)- %1TranslatorListModel CAA:89 - %1 Russian - %1TranslatorListModelA?0=A:89 - %1 Spanish - %1TranslatorListModelf>2K9 ?@><56CB>G=K9 @5;87 4>ABC?5= 4;O A:0G820=8O: 3A new interim release is available for downloading: UpdateDialog\>2K9 >A=>2=>9 @5;87 4>ABC?5= 4;O A:0G820=8O:0A new main release is available for downloading: UpdateDialog@>25@:0... Checking... UpdateDialog0:@KBLClose UpdateDialog0>20O 25@A8O =5 =0945=0.No new versions found. UpdateDialogt A>60;5=8N, =5 C40;>AL 703@C78BL 8D>@<0F8N >1 >1=>2;5=8OE%Sorry, unable to retrieve update info UpdateDialog GQ@=K9blackWire A8=89blueWireF25BcolorWire,>G5=L B>;ABK9 (1.2 <<)extra thick (48 mil)Wire75;Q=K9greenWire A5@K9greyWire>@0=652K9orangeWire:@0A=K9redWire(AB0=40@B=K9 (0.6 <<)standard (24 mil)Wire B>;ABK9 (0.8 <<)thick (32 mil)WireB>=:89 (0.4 <<) thin (16 mil)Wire 15;K9whiteWire 6Q;BK9yellowWire ) , fritzing-app-0.9.2b/translations/fritzing_ru.ts000066400000000000000000010306461250202676700217520ustar00rootroot00000000000000 AboutBox <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 на код и CreativeCommons:BY-SA на всё остальное <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Потсдам</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to Alexander Kaltsas for the Greek translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. to Nikolay Stankov for the Bulgarian translation, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, AutorouteProgressDialog Cancel Отменить Stop Now Остановить сейчас zoom and pan controls Best So Far Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Trace width Cancel Отменить OK Принять Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. BinManager Parts Части BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Не могу установить bin '%1' как черновик New bin (%1) Новый bin (%1) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing Bin файлы (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Общий Bin (*%2) Cannot set a NULL bin as the current one Не могу установить нулевой bin текущим BinManager::updateTitle: Couldn't set the bin '%1' as dirty Select a Fritzing Parts Bin file to open Bin Bin New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Export Part... Remove Part Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Переименовать bin Please choose a name for the bin: Пожалуйста, выберите имя для bin: Remove from bin Удалить из bin Searching... Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Select a Fritzing File to Open Выбрать файл Fritzing для открытия Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Edit Part (new parts editor)... Find Part in Sketch Remove from Bin Unable to remove part '%1'--it is in use in a sketch Do you really want to remove '%1' from the bin? This operation cannot be undone. Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Board one layer (single-sided) two layers (double-sided) Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? A custom board svg typically has one or two silkscreen layers and one board layer. because there are multiple <silkscreen0> layers <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. BoardLogoItem shape BreadboardLogoItem color цвет Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Remove bendpoint Straighten curve ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About О программе (&A) About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Выход(&Q) Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected Critical Error About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Fritzing Fritzing %1 is overlapping (%2 layer) Too close to a border (%1 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Click on an item in the list to highlight of overlap it refers to. DebugDialog for debugging для отладки DeleteDialog Also delete the file Remove Удалить Don't remove Dip chip label FApplication Import files from previous version? Импортировать файлы предыдущей версии? Import Импорт Do not import now Не импортировать сейчас Fritzing failure Fritzing caught an exception from %1 in event %2 Fritzing caught an exception %1 from %2 in event %3 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) Fritzing (*%1) Fritzing caught an exception from %1 in event %2: %3 FirstTimeHelpDialog First Time Help Подсказки <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Закрыть Окно (&C) Ctrl+W Ctrl+W Close the current sketch Закрыть текущий эскиз %1 - %2 %1 - %2 Specify a file name Установить имя файла Save "%1" Сохранить "%1" Do you want to save the changes you made in the document "%1"? Вы хотите сохранить сделанные изменения в документе "%1"? Save... Сохранить... Save Сохранить Don't Save Не сохранять Ctrl+D Ctrl+D Your changes will be lost if you don't save them. Ваши изменения будут утеряны, если вы их не сохраните. Cancel Отменить GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel Отменить OK Принять OK and ground fill OK and copper fill Hole hole size HtmlInfoView Connections Соединения conn. подключ. connected to %n item(s) подключено к %n элементу(-ам) подключено к %n элементу подключено к %n элементам name название type тип (autoroutable) (автотрассируемо) Wire Провод Trace wire %1 Трассировать провод %1 Properties Свойства Tags Метки Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Ratsnest wire Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. v. %1 %2 obsolete Placement pcb layer location rotation degrees ItemBase Part Часть family семейство color цвет resistance сопротивление voltage pin spacing rated power rated voltage rated current version package shape maximum resistance size form model part problem capacitance inductance current power part number type тип model pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project unable to create renderer for svg %1 file for %1 %2 not found banded top bottom copper bottom copper top silkscreen bottom silkscreen top KicadModuleDialog Cancel Отменить OK Принять LayerPalette show all layers LinkDialog Cancel Отменить OK Принять url: text: LogoItem Unable to display Unable to display image from %1 shape due to a rendering error because the svg is empty due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting text MainWindow Rotate Повернуть Share Опубликовать Flip Отобразить Autoroute Автотрассировка Add a note Добавить примечание Ready Готово Save %1 Сохранить %1 Specify a file name Укажите имя файла Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Невозможно экспортировать %1 в общий Fritzing Part (*%1) Элемент Fritzing (*%1) Unable to export %1 to shareable sketch Невозможно экспортировать %1 в общий эскиз Do you want to keep the imported parts? Сохранить импортированные элементы? No connections to route Нет соединения с маршрутом Routing completed Трассировка завершена %1 of %2 nets routed - %n connector(s) still to be routed %1 из %2 линий разведены - %n разъёмов ещё нуждаются в разведении %1 из %2 линий разведены - %n разъёмов ещё нуждаются в разведении %1 из %2 линий разведены - %n разъёмов ещё нуждаются в разведении %1 - [%2] %1 - [%2] Sorry! Извините! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Нет элементов с такими характеристиками. Мы работаем над тем, чтобы избежать этого сообщения, и вы могли работать с параметрами, которые действительно существуют Swapped %1 with module %2 Поменять %1 с модулем %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 отсутствует слой '%2'.Для получения дополнительной информации о том, как создавать пользовательские формы плат, см. инструкции по адресу <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) изображение PNG (*.png) JPEG Image (*.jpg) изображение JPEG (*.jpg) SVG Image (*.svg) SVG изображение (*.svg) Printing... Печать... All traces have not yet been routed. Не все соединения были разведены Do you want to proceed anyway? Вы всё равно хотите начать? Proceed Продолжить Cancel Отменить Sketch exported Эскиз экспортирован Export... Экспорт... Exporting... Экспортирование... Unable to save %1 Невозможно сохранить %1 Cannot print to %1 Не могу распечатать на %1 Cannot write file %1: %2. Не удается записать файл %1: %2. Saved '%1' Сохранён '%1' Select a Fritzing File to Open Выбрать файл Fritzing для открытия Cannot find file %1. Не могу найти файл %1. Cannot read file 1 %1: %2. Не удается произвести чтение файла 1 %1: %2. directly loading parts непосредственно загруженные части loading %1 (model) загружается %1 (модель) loading %1 (breadboard) загружается %1 (макетная плата) loading %1 (pcb) загружается %1 (печатная плата) loading %1 (schematic) загружается %1 (принципиальная схема) Create a new sketch Создать новый эскиз &Open... &Открыть... Ctrl+O Ctrl+O &Save Сохранить (&S) Ctrl+S Ctrl+S Save the current sketch Сохранить текущий эскиз &Save As... Сохранить как (&S)... Shift+Ctrl+S Shift+Ctrl+S Share online... Опубликовать онлайн... Post a project to the Fritzing website Загрузить проект на сайт Fritzing Export the visible area of the current sketch as a JPG image Экспорт видимой области текущего эскиза в изображение JPG Export the visible area of the current sketch as a PNG image Экспорт видимой области текущего эскиза в изображение PNG Export the visible area of the current sketch as a PostScript image Экспорт видимой области текущего эскиза в изображение PostScript Export the visible area of the current sketch as a PDF image Экспорт видимой области текущего эскиза в изображение PDF Export the current sketch as an SVG image Экспорт текущего эскиза в изображение SVG List of parts (&Bill of Materials)... Cписок материалов для изготовления (&B)... Save a Bill of Materials (BoM)/Shopping List as text Сохранить список элементов/Список покупок как текст XML Netlist... XML список... Save a netlist in XML format Сохранить как список в XML формате Export the current sketch to Eagle CAD Экспорт текущего эскиза в Eagle CAD &Print... Печать(&P)... Ctrl+P Ctrl+P Print the current view Печать текущего вида &Quit Выход(&Q) Ctrl+Q Ctrl+Q Quit the application Выход из программы &Open Example &Открыть пример MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: не могу загрузить пример с id='%1' &Open Recent Files &Открыть последние файлы &%1 %2 &%1 %2 Undo Отменить Redo Отменить &Cut Вырезать(&C) Cut selection Вырезать выделенное &Copy Скопировать(&C) Copy selection Копировать выделенное &Paste Вставить(&P) Paste clipboard contents Вставить содержимое буфера обмена &Duplicate Дублировать(&D) Ctrl+D Ctrl+D Duplicate selection Дублировать выделенное &Delete Удалить(&D) Delete selection Удалить выделенное &Select All Выделить всё (&S) Select all elements Выделить все элементы &Deselect Снять выделение(&D) Deselect Снять выделение Add Note Добавить примечание &Preferences... Настройки(&P)... Show the application's about box Показать информационное окно &Edit Редактировать(&E) &Add to bin... Добавить в bin (&A)... Add selected part to bin Добавить выделенные элементы в bin Disconnect All Wires Отсоединить все провода Disconnect all wires connected to this connector Отсоединить все провода, подключённые к данному соединению Update InfoView on hover Обновить информацию при наведении Rotate the selected parts by 90 degrees clockwise Повернуть выделенные элементы на 90 градусов по часовой стрелке Rotate the selected parts by 180 degrees Повернутьвыделенные элементы на 180 градусов Rotate current selection 90 degrees counter clockwise Повернуть текущий выбор на 90 градусов против часовой стрелки &Flip Horizontal Отразить по-горизонтали(&F) Flip current selection horizontally Отразить текущее выделение по-горизонтали &Flip Vertical Отразить по-вертикали(&F) Flip current selection vertically Отразить текущее выделение по-вертикали Bring to Front На передний план Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Переместить выбранные объекты назад в их слое Bring Forward Переместить вперёд Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Перенести выбранные объекты вперёд в их слое Send Backward Отправить обратно Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Отправить выбранный объект(ы) назад в слой Send to Back Отправить назад Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Отправить выбранный объект(ы) в конец слоя &Show All Layers Показать все слои (&S) Show all the available layers for the current view Показать все имеющиеся слои для текущего режима &Hide All Layers Скрыть все слои(&H) Hide all the layers of the current view Скрыть все слои текущего вид &Show part label Показать метки элементов (&S) &Export... Экспорт (&E)... Export selected part Экспорт выделенных элементов Add Bendpoint Добавить точку изгиба Add a bendpoint to the selected wire Добавить точку изгиба на выделенном проводе &Zoom In Увеличить (&Z) Ctrl++ Ctrl++ Zoom in Увеличить Ctrl+= Ctrl+= &Zoom Out Уменьшить (&Z) Ctrl+- Ctrl+- Zoom out Уменьшить &Fit in Window Подогнять окно (&F) Ctrl+0 Ctrl+0 Fit in window Подогнать в окне &Actual Size Фактический размер (&A) Shift+Ctrl+0 Shift+Ctrl+0 &Show Breadboard Показать макетную плату (&S) Ctrl+1 Ctrl+1 Show the breadboard view Показать макетную плату &Show Schematic Показать принципиальную схему (&S) Ctrl+2 Ctrl+2 Show the schematic view Показать принципиальную схему &Show PCB Показать печатную плату (&S) Ctrl+3 Ctrl+3 Show the PCB view Показать печатную плату &Minimize Свернуть(&М) Ctrl+M Ctrl+M Minimize current window Свернуть текущее окно Debugger Output Отладочная информация Online Tutorials Онлайн-руководство Ctrl+? Ctrl+? Open Fritzing help Открыть справку Fritzing Online Projects Gallery Онлайн-галерея проектов Open Fritzing examples Открыть примеры Fritzing Online Parts Reference Онлайн ссылки элементов Open Parts Reference Открыть ссылку элементов First Time Help Подсказки Check for updates... Проверить обновления... Check whether a newer version of Fritzing is available for download Проверить доступность новой версии Fritzing для загрузки &About О программе (&A) Display some handy Fritzing tips and tricks Показать полезные советы Fritzing &About Qt О программе Qt (&A) Show Qt's about box Показать окно о Qt Report a but you've found in Fritzing Сообщить ка вы нашли Fritzing &Import parts and bins from old version... Импортировать элементы и bins из предыдущей версии (&I)... Import parts and bins from previous installation Импортировать элементы и bins из предыдущей установки &File Файл (&F) &Export Экспорт (&E) &Part Элемент(&P) Raise and Lower Поднять и опустить &View Вид (&V) &Window Окно (&W) &Help Помощь (&H) Page Setup Установки страницы Sorry, "%1" has not been implemented yet К сожалению, "%1" ещё не был реализован Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Ваш эскиз ещё не имеет платы! Пожалуйста, добавьте печатную плату для экспорта в Gerber. Choose a folder for exporting Выберите папку для экспорта This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Это позволит экспортировать Ваш Fritzing-эскиз в макет EAGLE. Если Вы хотите возможность экспорта в другие программы компьютерного моделирования, пожалуйста, дайте нам знать, или внести свой вклад. Export SVG... Экспорт SVG... Export Bill of Materials (BoM)... Экспортировать список материалов... Export Netlist... Эспортировать Netlist... Select All Traces Выбрать все трассы Select all trace wires Выделить все трассы проводов Select all trace wires excluded from autorouting Выбрать все трассы, исключённые из автотрассировки Tidy Wires Убрать провода Tidy selected wires Убрать выделенные провода Copper Fill Заполнение медью Remove Copper Fill Удалить заливку медью Remove the copper fill Удалить заливку медью Autorouting... Автотрассировка... Remove Bendpoint Удалить точку изгиба Please choose the previous Fritzing folder... Пожалуйста, выберите предыдущую директорию Fritzing... You will have to restart Fritzing in order to use the imported parts Для использования импортированных элементов, Вам придется перезапустить Fritzing Remove copper fill Удалить заливку медью &Wire Color Цвет провода (&W) Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Select outdated parts Update selected parts No outdated parts found. All your parts are up-to-date. Outdated parts Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) No exactly matching part found; Fritzing chose the closest match. Shell launch %1 Launch %1... All throw test exception throw a fake exception to see what happens Select All Jumpers New Ctrl+N Tips, Tricks and Shortcuts Align to Grid Align items to grid when dragging Open programming window Open microcontroller programming window Report a bug... Enable debugging log Both Layers Bottom Layer Top Layer Backing up '%1' Rotate current selection 45 degrees counter clockwise Повернуть текущий выбор на 90 градусов против часовой стрелки {45 ?} Rotate current selection 45 degrees clockwise Actual (real world physical) size 100% Size 100% (pixel) size Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Autorouting Progress... File '%1' not found Paste in Place Paste clipboard contents in place Delete Routing completed using %n jumper part(s) Delete Ratsnest Line Delete Wire Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page Export for PCB Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... as Image for Production loading %1 Loading... new sketch BoM Text File (*.html) Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Unable to save BOM file, but the text is on the clipboard. Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Select all jumper item parts Select All Vias Select all via parts Shift+Ctrl+D Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Straighten Curve Straighten the curve of the selected wire Select All CopperFill Select all copper fill items unable to find replacement for %1. Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Sketch exported to Gerber Shift+Ctrl+A Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Ground Fill Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. No Sketch found in '%1' the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to &Routing &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Select All Wires Select all wires Fill empty regions of the copper layer--fill will include all traces connected to the seeds Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Generating %1 fill... ground copper Show Grid Show the grid Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Change to single layer pcb Change to two layer pcb Change image to %2 Gerber export can only handle one board at a time--please select the board you want to export. Sticky If a "sticky" part is moved, parts on top of it are also moved Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view jumpers copperfill vias OK Принять Set the grid size for %1. Grid Size: in mm Restore Default Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Check Loaded Traces Unrouted connections There are no unrouted connections in this view. Edit (new parts editor) Open the new parts editor on an existing part Show unrouted Highlight all unrouted connectors Inspector Инспектор Undo History История отмен Breadboard Макетная плата Schematic Принципиальная схема PCB Печатная плата Layers Couldn't get the dock widget Не могу получить виджет документа &Delete Wire Parts Editor Help Display Parts Editor help in a browser The folder "%1" isn't a Fritzing installation folder Design Rules Check (DRC) DRC Progress... Highlights any parts that are too close together for safe board production Autoroute connections... Show/hide the label for the selected parts Hide part silkscreen Hide/show the silkscreen layer for only this part Hide part label Show part label Show part silkscreen Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Ctrl+4 Ctrl+4 Code Show Code Show the code (programming) view Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab Find part in sketch... Search for parts in a sketch by matching text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. SPICE Netlist... Save a netlist in SPICE format Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Export SPICE Netlist... Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Enter Text View from Above View from Below View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Move to bottom layer Move to top layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Align top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Do you want to update now? There are %n outdated part(s) in this sketch. Click to highlight unconnected parts Fabricate Welcome Dump all parts Debug dump all parts in this view Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Test Connectors Connect all connectors to a single test part Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Rotate 45� Clockwise Повернуть на 90° по часовой стрелке {135°?} {45�?} Rotate 90� Clockwise Повернуть на 90° по часовой стрелке {135°?} {90�?} Rotate 180� Повернуть на 180° {180�?} Rotate 90� Counter Clockwise Повернуть на 90 ° против часовой стрелки {90�?} Rotate 45� Counter Clockwise Повернуть на 90 ° против часовой стрелки {45�?} Ctrl+Shift+V (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 MazeRouter Autorouter was cancelled. round %1 of: Unexpected SVG rendering failure--contact fritzing.org best so far: %1 of %2 routed with %n vias Routing reached maximum round %1. Routing stopped! Routing complete! Routing unsuccessful; stopping at round %1. Use best so far... Preparing undo... Optimizing traces... ModelBase File save failed! Ошибка сохранеия файла! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Не могу перезаписать файл '%1'. причина: %2 (код ошибки %3) Unable to find the following %n part(s): at MysteryPart label chip label NetLabel net label Note [write your note here] [напишите Ваше примечание здесь] PCBSketchWidget Click this connector to drag out a new trace. Щёлкните на данном соединении для прокладывания нового маршрута. Change trace layer Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Ваш эскиз ещё не имеет платы! Пожалуйста, добавьте печатную плату для прокладки медных дорожек.. Fritzing error: unable to render board svg (1). Ошибка Fritzing : не могу закрасить плату svg (1). Fritzing error: unable to render copper svg (1). Ошибка Fritzing : не могу закрасить медь svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Create Trace from Ratsnest Please designate one or more ground fill seeds before doing a ground fill. Clear ground fill seeds %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: Fritzing Fab Quote Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor Редактор элементов Show Icon Ctrl+4 Ctrl+4 Show the icon view Ctrl+5 Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Ctrl+6 Change %1 to '%2' Change tags Change properties Change description Change connector %1 SVG Connectors Соединения Show in Folder On the desktop, open the folder containing the current svg file. Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Открыть изображение Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem SVG problem Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Файл (&F) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Сохранить Cancel Отменить Move terminal point Remove connector Remove %1 connectors Save "%1" Сохранить "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Add connector Добавить соединение Add %1 connectors There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Icon Иконка Metadata Remove Internal Connection Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 Remove internal connection from '%1' Internal connections are very messed up. Add internal connection from '%1' to '%2' The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image &Export Экспорт (&E) Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Load image for view... Open a file to use as the image for this view of the part. Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Edit Редактировать(&E) This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Inspector Инспектор Unable to load fzp from %1 Unable to create new connector--you may have to start over. Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Автор Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Описание Set the default part label prefix Label Метка Set the part's family--what other parts is this part related to Family Set the part's properties Properties Свойства Set the part's tags Tags Метки Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's url if it is described on a web page URL PESvgView width: height: PEToolView Center N E S W Connector %1 Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector List (a checkmark means the graphic was selected) Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Правка Edit label text Редактировать текст метки Display Values Отобразить величины Flip/Rotate Отобразить/Повернуть Font Size Размер шрифта Rotate the label by 90 degrees clockwise Повернуть метку на 90° против часовой стрелки Rotate the label by 180 degrees Повернуть метку на 180 градусов Rotate current selection 90 degrees counter clockwise Повернуть выделенное на 90 градусов против часовой стрелки Flip Horizontal Отобразить по-горизонтали Flip label horizontally Отобразить метку по-горизонтали Flip Vertical Отобразить по-вертикали Flip label vertically Отобразить метку по-вертикали Small Маленький Set font size to small Установить маленький размер шрифта Medium Средний Set font size to medium Установить средний размер шрифта Large Большой Set font size to large Установить большой размер шрифта Label text Текст метки Display the text of the label Отобразить текст метки Display the value of property %1 Отобразить величину свойства %1 Set label for %1 Установить метку для %1 Label text: Текст метки: Hide Hide part label Rotate the label by 45 degrees clockwise Повернуть метку на 90° против часовой стрелки {45 ?} Rotate the label by 135 degrees clockwise Повернуть метку на 90° против часовой стрелки {135 ?} Rotate the label by 135 degrees counter clockwise Rotate the label by 45 degrees counter clockwise Tiny Set font size to tiny Rotate 45� Clockwise Повернуть на 90° по часовой стрелке {135°?} {45�?} Rotate 90� Clockwise Повернуть на 90° по часовой стрелке {135°?} {90�?} Rotate 135� Clockwise Повернуть на 90° по часовой стрелке {135°?} {135�?} Rotate 180� Повернуть на 180° {180�?} Rotate 135� Counter Clockwise Повернуть на 90 ° против часовой стрелки {135�?} Rotate 90� Counter Clockwise Повернуть на 90 ° против часовой стрелки {90�?} Rotate 45� Counter Clockwise Повернуть на 90 ° против часовой стрелки {45�?} PartsBinPaletteWidget Untitled Bin Неозаглавленный Bin Save Сохранить Specify a file name Укажите имя файла Fritzing Bin (*%1) Fritzing Bin (*%1) Fritzing Fritzing Cannot find file %1. Не могу найти файл %1. Cannot read file %1: %2. Не удаётся прочитать файл %1: %2. Do you want to save the changes you made in the bin "%1"? Вы хотите сохранить изменения, внесённые в bin "%1"? Don't Save Не сохранять Ctrl+D Ctrl+D Your changes will be lost if you don't save them. Ваши изменения будут потеряны, если их не сохранить. Add to bin Добавить в bin Do you really want to add the selected part to the bin? Вы действительно хотите, добавить выбранный 'элемент в bin? Save bin "%1" Cancel Отменить Loading... loading bin '%1' Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size rows columns Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel Отменить PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Отменить Undo Отменить Redo Отменить Save Сохранить PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Cancel Отменить OK Принять Language Язык Colors Цвета %1 (click to change...) %1 (Нажмите для изменения...) Connected Highlight Выделение соединений Unconnected Highlight Выделение несоединённых Mouse Wheel Behavior Command Control Change Wheel Behavior Autosave Autosave every: minutes no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis General Curvy vs. straight wires Clear Settings When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs Code View Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 ProgramTab Select a program file to load Fritzing is unable to find '%1', please locate it New Save Сохранить Remove "%1"? Are you sure you want to remove "%1" from the sketch? Code (*.%1) While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Open Platform Board Плата Port Serial Monitor Upload No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit Редактировать(&E) Undo Отменить Redo Отменить &Cut Вырезать(&C) Cut selection Вырезать выделенное &Copy Скопировать(&C) Copy selection Копировать выделенное &Paste Вставить(&P) Paste clipboard contents Вставить содержимое буфера обмена &Select All Выделить всё (&S) Select all text File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. &Code &View Вид (&V) Code Window Code Window - %1 No boards available &Preferences... Настройки(&P)... Show the application's about box Показать информационное окно &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Плата Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller %1%2 %1%2 QObject bb bb Breadboard View Макетная плата Preferences Настройка Please note that a new language setting will not take effect until the next time you run Fritzing. Обратите внимание, что новые настройки языка, вступят в силу только после перезапуска Fritzing. Please note that a new language setting will not take effect until the next time you run Fritzing. Fritzing Fritzing <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Потсдам</font> The file '%1' is read-only; please use a different filename. Файл '%1' только для чтения; пожалуйста, используйте другое имя файла. Edit link Изменить ссылку Part Элемент Wire Провод Cannot read file %1: %2. Не могу прочитать файл %1: %2. Parse error (1) at line %1, column %2: %3 %4 Синтаксическая ошибка (1) в строке %1, столбец %2: %3 %4 The file %1 is not a Fritzing file (2). Файл %1 не является файлом Fritzing (2). The file %1 is not a Fritzing file (4). Файл %1 не является файлом Fritzing (4). The file %1 is not a Fritzing file (3). Файл %1 не является файлом Fritzing (3). No parts found. Элементов не найдено. Parse error (2) at line %1, column %2: %3 %4 Синтаксическая ошибка(2) в строке %1, столбец %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Элемент '%1' в '%2' не имеет уникального идентификатора модуля '%3'. Part already in bin Элемент уже в bin The part that you have just added, is already there, we won't add it again, right? Элемент, который Вы только что добавили, уже там есть, мы не можем добавить его снова, верно? a label ярлык a value величина PCB View Печатная плата pcb печатная плата Oops! Оой! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. К сожалению, у нас есть проблема с механизмом замены. Fritzing по-прежнему работает, но вы не сможете изменить свойства элементы. schem схема Schematic View Принципиальная схема %1 %2 %3 %1 %2 %3 %1 Layer %1 слой Bring forward Переместить вперёд Send backward Переместить назад Bring to front На передний план Split Wire Разъединить провод Join Wire Соединить провод Trace wires Трассы проводов Ratsnest wires Линии для соединения Select all %1 Выбрать все %1 File Progress... Выполнение файла... Check for updates Проверить обновления icon view значки breadboard view макетная плата schematic view принципиальная схема pcb view печатная плата Icon Иконка Breadboard Макетная плата Parts Элементы Wires Провода Part Labels Метки элементов Notes Примечания Rulers Правила Board Плата Unknown Layer Неизвестный слой Select outdated parts files unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params Sorry, can't handle pad type %1 pad shape missing params shape delta not implemented trapezoidal pads not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 Copying file %1 File %1 already exists: it won't be overwritten Silkscreen Top Silkscreen Top (Part Labels) Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) bad layer mask parameter non-circular holes not implemented non-copper holes not implemented Unable to parse copper: %1 %2 %3 Parts folder not found. Select %1 Выбрать %1 pad shape size is invalid bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 Part Image Error reading file %1: %2. Select locked parts Basic Input Output ICs Power Connection Microcontroller Tools Frame %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), Unable to translate svg curves in %1 silk export failure drill export failure mask export failure Copper Fill Bottom Copper Fill Top Shields LilyPad Other Sensors Pin Label Editor Ratsnest mm in Cannot write file temp: %1 %2 %3. Cannot autoroute: no board (or multiple boards) found Set Ground Fill Seed Ground Fill Seed Editor %1 mask export failure (2) Select all 'Don't autoroute' traces Select all autorouteable traces Set Grid Size There is no undo for this action, and no further warning!!!! Clear Settings No connections (on the PCB) to route. No connections to route. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. Convert to Via Convert Via to Bendpoint %1 wires moved from their saved position in %2. paste mask layer(s), ii Icon View <b>id:</b> <b>Name:</b> Set the connectors's title <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Internal Connections Set all to: Pad <b>type:</b> Part %1 '%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. unable to copy file '%1' to '%2'. Autorouter Settings %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 Text %1 layer export is empty (case 2). silk layer %1 export is empty %2 ... %1 wires moved from their saved position <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Order your PCB from Fritzing Fab Price per board Price Copies Visit Fritzing Fab Fritzing Fab Quote The total area of the %n PCB(s) in this sketch is Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog &Recover &Ignore File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> Resistor resistance сопротивление Resistor You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width ширина S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev of date sheet shape SchematicSketchWidget Change voltage from %1 to %2 Изменить напряжение с %1 на %2 Change label from %1 to %2 SetColorDialog Make this the default %1 color Сделать %1 цветом по-умолчанию Cancel Отменить OK Принять %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Pick custom %1 color Current color (%1) SketchWidget loading part загрузка элемента done loading загрузка завершена %1 %2 %1 %2 %1 %2 items %1 %2 элемент Select All Выделить всё Deselect Снять выделение Add %1 Добавить %1 Selection Выделение Move %2 (%1) Переместить %2 (%1) Move %2 items (%1) Переместить %2 элемент (%1) Select %1 Выбрать %1 Select %1 items Выбрать %1 элементы Disconnect Отключить Change Изменить Connect Соединить to %1 к %1 Create and connect wire Создать и подключить провод Rotate %2 (%1) Повернуть %2 (%1) Rotate Вращать Flip Повернуть Double-click Двойной щелчёк Drag or double-click Перетащить или двойной-щелчёк or alt-drag to move the segment или Alt-перетащить сегмент Double-click to delete this bend point Дважды щелкните, чтобы удалить эту точку изгиба Change %1 label to '%2' Изменить %1 метку для '%2' Change %1 color from %2 to %3 Изменить %1 цвет с %2 на %3 Change color of %1 wires to %2 Изменить цвет %1 проводов на %2 Change %1 width from %2 to %3 Изменить %1 ширину с %2 на %3 Change width of %1 wires to %2 Изменить ширину %1 проводов на %2 Move label '%1' Переместить метку '%1' %1 label '%2' %1 метка '%2' Resize Note Изменить размер примечания Disconnect all wires from %1 Отключить все провода от %1 Disconnect all wires from %1 items Отключить все провода от %1 элементов Change Resistance from %1 to %2 Change image from %1 to %2 Change %1 from %2 to %3 from %1 Move leg of Flip %2 (%1) Change leg curvature for %1. Change leg bendpoint for %1. change pin labels Delete ratsnest Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Create wire from Ratsnest Note text change Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Deselect all Part '%1' not found in sketch Resize board to %1 %2 Изменить размер на %1 %2 show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 Add %1 parts test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Tips and Tricks Полезные советы Fritzing Tips and Tricks parts If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor examples Get a jump start by looking at the example circuits under File > Examples. Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. TraceWire width ширина Select from the dropdown, or type in any value from %1 to %2 TranslatorListModel English - %1 Английский - %1 French - %1 Французский - %1 German - %1 Немецкий - %1 Spanish - %1 Испанский - %1 Japanese - %1 Японский - %1 Portuguese (European)- %1 Португальский (Европейский)- %1 Portuguese (Brazilian) - %1 Португальский (Бразильский)- %1 Hungarian - %1 Венгерский - %1 Dutch - %1 Голландский - %1 Russian - %1 Русский - %1 Italian - %1 Итальянский - %1 Hebrew - %1 Иврит - %1 Arabic - %1 Арабский - %1 Hindi - %1 Хинди - %1 Chinese (Simplified) - %1 Estonian - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Danish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close Закрыть No new versions found. Новая версия не найдена. A new main release is available for downloading: Новый основной релиз доступен для скачивания: A new interim release is available for downloading: Новый промежуточный релиз доступен для скачивания: Checking... Проверка... Sorry, unable to retrieve update info К сожалению, не удалось загрузить иформацию об обновлениях WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Fritzing Fab Wire thin (16 mil) тонкий (0.4 мм) standard (24 mil) стандартный (0.6 мм) thick (32 mil) толстый (0.8 мм) extra thick (48 mil) очень толстый (1.2 мм) blue синий red красный black чёрный yellow жёлтый green зелёный grey серый white белый orange оранжевый color цвет brown purple super fine (8 mil) extra thin (12 mil) Banded pink ochre cyan ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_sk.qm000066400000000000000000003012111250202676700217140ustar00rootroot00000000000000xvM^r^h;hy j3؂95YįEįį: $dS<_B֍="eIH5;<pS?OSWAs@Ee;keB<U U ef512.K!"*yH<*y<*IZ***%J*%l*0K4+hM+'+N+N+Q6+,B<,DAV-OOFd,HfIX@IXIXJ6bKQM5 P,ELPW?RU\RxRUjEVgQvVVVWmXY7YAZ8,[f3'[f3"a]4A^$L_C^`bp'pcge Li'd)idzjcb&[jcb<jcbdje:Bjɢ<k m*nerxrxW3t/wm?xye&,yeAyeDyehye@yeBqyAIyB{ %A{U_{U}f}@}W|U+|.5@5?)L$_^)@~$',FYk>\hP$L{ V#y\ Gh"b)tm){?*G*24J69?yOJvgbL# L4wl+TZae>QeqMrv{(ysGN5E`,TkTP wKJrG~]N8h.CR͌bӒ25o2.g_+ Q?PUD@&WD44/QBɢC>D@RԢYX&YYYZ8lTRct*tʨuTu5RuT&xe5xexic3y9:p|Dv 'h6sSTT#'G'şDM.;AJ;AQQuu!±$±BaFannΦ[b/\%au7R9BCW}Qpq] 5BTSw7T&[P3'.m9;U>H*jFH0!RB0V|>hXMuVhWw{<p>#[rx$}su<|$4j $o![×ߜ\r[q_Tl{C'OuܡY9տDAֺ$fdlS"u~SʳlIsRqn['eC*Zz5;NG$sXCa5jNZl6zbD|/} DׅT]yb&L>ɱ[tIII2?I5IC|IDI[IQIIyI,ICGz D6R_ M,a#Eg  ~`Z~ٶ)ۘXBӞfR p;q }#~isc^oUrg^(}(׹,]R57;?BLGBۍOkP1UZ_cEaPa3XYb/c\eelnq5Ep]9qS }0"3.F*RP+,?T6 1&OB qhׯ Hََ q՞h7S q@7Wg+r@XX}1$k"1$k21L$kB0%W)!x-ڎ3LT;7@EK_EQ0dQME^zz^>_p%_zR`ri\ -9lMoqW"-z>|>zCu q%7]`]?ZDDVLLzW2 o@9<֣9֣(>?mUSޛIne6zc-9dwFY!c'p 9&|8'S"(=-3eI.>;!ZEʇ\cQcNhenikIrVs$(sNq|%e&O EL>59'8<N ? A3-& 4X4a`->:?g>7pe{^ A03gf?p(2t &6 ,ιt-B2C.:F?ކI'ZNmO;[P1]YQt%b]A^fCfC;f|ĭgi'invyy/yz.|ԂB|^ad|^d4.~1$*,3S)S)q[gWBI$@nr8-*yUGf@"3Mnʗ КFл%J? ZT5 \~N_ +o |U3 w~   !yDA $)~f 0 0!SF/ 5G2X BU Exj Gȧ0# Mgڊ Q SeNX \u89 cϥ! lOGb uip u^] ~ .l ~S Ṅ T r ^4T B1Y N!Y . s.` Ŧ 8 ,_9 ;~ ՛ {u % &. ~Z v]n ^ D *  ^@] J' `% 7? i7" !q !q% #$j ?"Eb CD UC| [># ^5% a4J c3 c3V d; d8 eKI^ eRS e fjHr g7A k2| k2} su tqJd vw Ni ,H ^ \| 1 > NJ Ɍ4<3 vI v. Ϯ  01 0w ˺- KM B ;'x, c ~ 0 U6 T  V7 ~~ ~ l gu  %4E' (- ) Bc *cu * ? 8a N> VI Ys bR gV i$eV 1[?  OC a 4u @ Lc Q -nn a0 @z q %= f~ }@ p4T 1[ % KGQp 6 te 4X Vg % w_ L^ I`D i? `` N  R# #kS %^{ %^ ,\e - /~Xl 9sS =G L. M&`] O~\ Wja/ `l afu eu= eZ hȾ r4 rس tRW z n z n "x @0 $B )=M 6] M ,[D , H /c /J &  1Z m4V Eu 9E T7g ɠ.C ?m 'p K\+  ~# oN U. JK ( % ; f- G ^ #Ѯ 3Fe 7n A A2 DD G0 LR8 R/0c [ cCJ cWl fZG i0 m[a qU$ vCD }( # }&  n- 15 T< / ~> z v &^ @m, R6 <4 cYD  _ ^  ?  (4{b rc.(/TKu a.3a.fT7fTw=)f~ePiPo#n n$1\SR%FxOxãC(ciub'yA~qt4$Y!4a PuCdV^}] :T^$Y}}iԡuX* "TN$ /`izK=3 x@XT^Kjav!_QiPEi0p$sVTvgUmw|>h}$71WeHF K8,+XT`ܴ\Wigl<b>GNU GPL v3 na kd a CreativeCommons:BY-SA na zvyaok?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxdBryant Mairs, Uleshka Asher, a Daniel Tzschentke. 4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBoxJOddelenie Bauhaus univerzity Weimar, )Department of Bauhaus-University Weimar, AboutBoxDurrelul Bishopovi, Davidovi Cuartiellesovi, Fabianovi Hemmertovi, 3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBoxHpustie do koloto a testov Fritzingu.Fritzing a test spin. AboutBox(Fritzing vytvorili: Fritzing is made by: AboutBoxXFritzing bolo mo~n vytvorie s financovanm 0Fritzing is made possible with funding from the AboutBoxjGero Herkenrathovi, Jeffu Hoefsovi, Tomu Hulbertovi, *Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxdIxDS, anonymn darca, Parallax, Picaxe, Sparkfun, 6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBoxpJanovi Sieberovi, Yanivovi Steinerovi, Olafovi Vaolovi, %Jan Sieber, Yaniv Steiner, Olaf Val, AboutBoxvJussi &Auml;ngeslev&auml;, Massimo Banzimu, Ayah Bdeirovi, 6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxDMWFK Brandenburg, sponzor Designu 0MWFK Brandenburg, the sponsorship of the Design AboutBoxNMichaele Vieserovej a Julii Wernerovej.!Michaela Vieser and Julia Werner.AboutBoxjZvlatne poakovanie patr taktie~ vaetkm atudentom 4Special thanks goes out as well to all the students AboutBox8Zvlatne poakovanie patr: Special thanks goes out to: AboutBoxakujeme Kurtovi Badeltovi a Miguelovi Solisovi za `panielsk preklad, DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBoxzTomovi Igoevi, Hans-Peterovi Kadelovi, Tillovi Savelkoulovi, ,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBoxLa alfa testerom, ktor mali odvahu sa 0and alpha testers who were brave enough to give AboutBoxPGianluca Urgesovi za Taliansky preklad, 0to Gianluca Urgese for the Italian translation, AboutBoxLHiroshi Suzukimu za Japonsk preklad, 0to Hiroshi Suzuki for the Japanese translation, AboutBoxJJosefovi Duatrovi za  esk preklad, ,to Josef Dustira for the Czech translation, AboutBoxvNuno Pessanha Santosovi za Portugalsky (Europsky) preklad, Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxXRobertovi Lee za  nsky (tradi n) preklad, 9to Robert Lee for the Chinese (Traditional) translation, AboutBoxNVladimirovi Savinovi za Rusk preklad, 1to Vladimir Savinov for the Russian translation, AboutBoxp Yuelinovi a Ninjiovi za  nsky (zjednoduaen) preklad, @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBox ZruaieCancelAutorouteProgressDialogZastavieStop NowAutorouteProgressDialog6riadenie zv aenia a posunuzoom and pan controlsAutorouteProgressDialog ZruaieCancelAutorouterSettingsDialogTyp vrobyProduction typeAutorouterSettingsDialog`rka spoja Trace widthAutorouterSettingsDialogvlastncustomAutorouterSettingsDialogdomca vrobahomebrewAutorouterSettingsDialogprofesionlna professionalAutorouterSettingsDialogZsobnkBin BinManager~BinManager::setDirtyTab: Nejde nastavie zsobnk '%1' ako dirty;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager~BinManager::updateTitle: Nejde nastavit zsobnk '%1' ako dirty;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerRNejde nastavie NULL zsobnk ako aktulny(Cannot set a NULL bin as the current one BinManager Zavriee zsobnk Close Bin BinManager4Zavriee zsobnk s iastokClose parts bin BinManager@Vytvorie nov zsobnk s iastokCreate a new parts bin BinManager Vymazae zsobnk Delete Bin BinManager Vymazae zsobnk Delete bin BinManager4Vymazae zsobnk s iastokDelete parts bin BinManager:Zobrazie s iastky ako zoznamDisplay parts as a list BinManager8Zobrazie s iastky ako ikonyDisplay parts as icons BinManagerNaozaj chcete vymazae zsobnk '%1'? Tto akciu nebude mo~n vrtie.EDo you really want to delete bin '%1'? This action cannot be undone. BinManager,Exportovae zsobnk... Export Bin... BinManager.Exportovae s iastku...Export Part... BinManagerFritzing sbory zsobnku (*%1 *%2);;Fritzing zsobnk (*%1);;Fritzing zdie>an zsobnk (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManager Nov zsobnk... New Bin... BinManager$Nov zsobnk (%1) New bin (%1) BinManagerS iastkyParts BinManager4Zvo>te nzov pre zsobnk:!Please choose a name for the bin: BinManager.Zsobnk iba na  tanie Read-only bin BinManager&Odstrnie s iastku Remove Part BinManager,Odstrnie zo zsobnkuRemove from bin BinManager,Premenovae zsobnk... Rename Bin... BinManager&Prejmenuje zsobnk Rename bin BinManager@Premenovae zsobnk s iastok...Rename parts bin... BinManagerUlo~ie zsobnkSave Bin BinManager,Ulo~ie zsobnk ako...Save Bin As... BinManager2Ulo~ie zsobnk s iastokSave parts bin BinManager@Ulo~ie zsobnk s iastok ako...Save parts bin as... BinManagerhUlo~ie zsobnk s iastok v komprimovanom formte...&Save parts bin in compressed format... BinManagerFVybrae sbor Fritzing pre otvorenieSelect a Fritzing File to Open BinManagernVybrae Fritzing sbor zsobnku s iastok pre otvorenie(Select a Fritzing Parts Bin file to open BinManager6Zobrazie zsobnk ako ikonyShow Bin in Icon View BinManager8Zobrazie zsobnk ako zoznamShow Bin in List View BinManagerDTento zsobnk sa ned premenovae.This bin cannot be renamed. BinManagerObrzkyImagesBoard2Vyberte si sbor obrzkovSelect an image file to loadBoardNejde na taeUnable to loadBoard:Nejde na tae obrzok z %1 %2Unable to load image from %1 %2Boardsbor obrzkov image fileBoard,na tae sbor obrzkovload image fileBoard6jedna vrstva (jednostrann)one layer (single-sided)Board0dve vrstvy (obojstrann)two layers (double-sided)Boardtvarshape BoardLogoItem farbacolorBreadboardLogoItem Pridae bod zlomu Add bendpoint ConnectorItem&Odstrnie bod zlomuRemove bendpoint ConnectorItemVyrovnae krivkuStraighten curve ConnectorItem&O programe&About ConsoleWindow&Ukon ie&Quit ConsoleWindowNstrojeTools ConsoleWindow Va nvrh je pripraven pre vrobu: neboli njden ~iadne prekrvajce sa prpojky ani spoje a s asne tie~ nie s prlia blzko seba.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRCpre debugging for debugging DebugDialog(Odstrnie tie~ sborAlso delete the file DeleteDialogNeodstraHovae Don't remove DeleteDialogOdstrnieRemove DeleteDialogpopis  ipu chip labelDip Pozn.: M~ete importovae neskr s pou~itm polo~ky "Pomocnk" > "Import s iastok a zsobnikov z predchdzajcej verzie..." z ponuky.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication.Momentlne neimportovaeDo not import now FApplicationPrajete si importovae s iastky a zsobniky, ktor ste vytvorili v predchdzajcej verzii Fritzingu?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplication^Fritzing zachytil vnimku %1 z %2 v udalosti %33Fritzing caught an exception %1 from %2 in event %3 FApplicationXFritzing zachytil vnimku z %1 v udalosti %20Fritzing caught an exception from %1 in event %2 FApplication4Aplikcia Fritzing zlyhalaFritzing failure FApplicationVImportovae sbory z predchdzajcej verzie?#Import files from previous version? FApplication~Zadajte nzov sboru .fzz pre ulo~enie (Zruaie odstrni zlohu)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplicationPrv npovedaFirst Time HelpFirstTimeHelpDialog&Zavriee okno &Close WindowFritzingWindow ZruaieCancelFritzingWindow,Uzavrie aktulny nvrhClose the current sketchFritzingWindowdPrajete si ulo~ie zmeny vykonan v dokumente "%1"?>Do you want to save the changes you made in the document "%1"?FritzingWindowNeukladae Don't SaveFritzingWindow Ulo~ieSaveFritzingWindowUlo~ie "%1" Save "%1"FritzingWindowUlo~ie...Save...FritzingWindow(Zadajte nzov sboruSpecify a file nameFritzingWindow\Vaae zmeny bud straten, pokia> ch neulo~te.1Your changes will be lost if you don't save them.FritzingWindow ZruaieCancelGroundFillSeedDialogve>kose otvoru hole sizeHole4(automaticky routovateln)(autoroutable) HtmlInfoView2Tu zmente popis s iastkyChange the part label here HtmlInfoViewPiny Connections HtmlInfoViewZamknutLocked HtmlInfoViewBObrzok s iastky mont~nej doskyPart breadboard view image HtmlInfoView6Obrzok s iastky dosky PCBPart pcb view image HtmlInfoView0Obrzok s iastky schmyPart schematic view image HtmlInfoView, slo verzie s iastkyPart version number HtmlInfoViewVlastnosti Properties HtmlInfoView"Prepojovacia siee Ratsnest wire HtmlInfoView Zna kyTags HtmlInfoViewPloan spoj %1 Trace wire %1 HtmlInfoViewPrepojkaWire HtmlInfoViewkon.conn. HtmlInfoView,pripojen k %n polo~ke0pripojen ke %n polo~km.pripojen k %n polo~kmconnected to %n item(s) HtmlInfoView nzovname HtmlInfoViewtyptype HtmlInfoViewS iastkaPartItemBasekondenztor capacitanceItemBase farbacolorItemBaseprdcurrentItemBase dtumdateItemBase popisdescrItemBase rodinafamilyItemBasenzov sborufilenameItemBase formaformItemBasekmito et frequencyItemBaseinduk nose inductanceItemBase vrstvylayersItemBasemaximlny odpormaximum resistanceItemBase0problm modelu s iastkymodel part problemItemBase pzdropackageItemBase slo s iastky part numberItemBaseodstup pinov pin spacingItemBasepinypinsItemBasenapjaniepowerItemBaseprocesor processorItemBaseprojektprojectItemBasemenovit prd rated currentItemBase$menovit napjanie rated powerItemBase menovit naptie rated voltageItemBase odpor resistanceItemBasetvarshapeItemBaselistsheetItemBaseve>kosesizeItemBase odstupspacingItemBasetituloktitleItemBasetolerancia toleranceItemBasetyptypeItemBaseBnejde vytvorie renderovan svg %1$unable to create renderer for svg %1ItemBasevariantavariantItemBase verziaversionItemBasenaptievoltageItemBase ZruaieCancelKicadModuleDialog,zobrazie vaetky vrstvyshow all layers LayerPalette ZruaieCancel LinkDialogNejde zobrazieUnable to displayLogoItem6Nejde zobrazie obrzok z %1Unable to display image from %1LogoItemtvarshapeLogoItem%1 z %2 routovanch prepojov - %n prepojka, ktor bude eate routovan%1 z %2 routovanch prepojov - %n prepojky, ktor bude eate routovan%1 z %2 routovanch prepojov - %n prepojok, ktor bud eate routovn9%1 of %2 nets routed - %n connector(s) still to be routed MainWindow&O programe&About MainWindow &O Qt &About Qt MainWindow"&Aktulna ve>kose &Actual Size MainWindow.&Pridae do zsobniku...&Add to bin... MainWindow&Koprovae&Copy MainWindow &VyHae&Cut MainWindow&Vymazae&Delete MainWindow&Zruaie vber &Deselect MainWindow&Duplikovae &Duplicate MainWindow&Upravie&Edit MainWindow&Exportovae&Export MainWindow&Exportovae... &Export... MainWindow &Sbor&File MainWindow"&Prispsobie oknu&Fit in Window MainWindow(&Preklopie vodorovne&Flip Horizontal MainWindow"&Preklopie zvisle&Flip Vertical MainWindow&Npoveda&Help MainWindow(&Skrye vaetky vrstvy&Hide All Layers MainWindowv&Import s iastok a zsobnikov z predchdzajcich verzi...*&Import parts and bins from old version... MainWindow&Minimalizovae &Minimize MainWindow &Otvorie prklad &Open Example MainWindow.&Otvorie nedvne sbory&Open Recent Files MainWindow&Otvorie...&Open... MainWindow&S iastka&Part MainWindow&Vlo~ie&Paste MainWindow&Predvo>by...&Preferences... MainWindow&Tla ... &Print... MainWindow&Ukon ie&Quit MainWindow&Ulo~ie&Save MainWindow&Ulo~ie ako... &Save As... MainWindow&Vybrae vaetko &Select All MainWindow.&Zobrazie vaetky vrstvy&Show All Layers MainWindow0&Zobrazie mont~nu dosku&Show Breadboard MainWindow&Zobrazie PCB &Show PCB MainWindow &Zobrazie schmu&Show Schematic MainWindow2&Zobrazie popis s iastky&Show part label MainWindow&Zobrazenie&View MainWindow &Okno&Window MainWindow&Farba prepojky &Wire Color MainWindow&Zv aie&Zoom In MainWindow&Zmenaie &Zoom Out MainWindow*100% (pixlov) ve>kose100% (pixel) size MainWindow100% Ve>kose 100% Size MainWindowFAktulna (skuto n fyzick) ve>kose!Actual (real world physical) size MainWindow Pridae bod zlomu Add Bendpoint MainWindowPridae poznmkuAdd Note MainWindowBPrid bod zlomu vybranej propojky$Add a bendpoint to the selected wire MainWindowPridae poznmku Add a note MainWindowHPrid vybran s iastku do zsobnikuAdd selected part to bin MainWindowTPri pretiahnut prichyt polo~ky k mrie~ke!Align items to grid when dragging MainWindow&Prichytie k mrie~ke Align to Grid MainWindow VaetkoAll MainWindowHNeboli zroutovan eate vaetky spoje.$All traces have not yet been routed. MainWindow(Automaticky routovae Autoroute MainWindow.Prebieha autorouting...Autorouting Progress... MainWindowZlohovae '%1'Backing up '%1' MainWindow4Textov sbor BoM (*.html)BoM Text File (*.html) MainWindowObe vrstvy Both Layers MainWindowSpodn vrstva Bottom Layer MainWindowMont~na doska Breadboard MainWindowPosune dopredu Bring Forward MainWindow^Posunie vybran() objekt(y) vpred v ich vrstve/Bring selected object(s) forward in their layer MainWindow`Prenesie vybran() objekt(y) vpred v ich vrstve0Bring selected object(s) to front of their layer MainWindow Presune dopreduBring to Front MainWindow ZruaieCancel MainWindow*Nejde njse sbor %1.Cannot find file %1. MainWindow$Nejde tla ie na %1Cannot print to %1 MainWindow8Nejde  tae sbor 1 %1: %2.Cannot read file 1 %1: %2. MainWindow6Nejde zapsae sbor %1: %2.Cannot write file %1: %2. MainWindow0Kontrola aktualizcie...Check for updates... MainWindowvSkontroluje,  i nie je k stiahnutiu novaia verzia FritzinguCCheck whether a newer version of Fritzing is available for download MainWindow0Vybrae zlo~ku pre exportChoose a folder for exporting MainWindow>Spodn meden vrstva je aktvnaCopper Bottom layer is active MainWindowMeden vplH Copper Fill MainWindowZObe meden vrstvy, horn a spodn, s aktivne3Copper Top and Copper Bottom layers are both active MainWindow<Horn meden vrstva je aktvnaCopper Top layer is active MainWindow Kopruje vybranCopy selection MainWindow,Nejde zadokovae widgetCouldn't get the dock widget MainWindow$VytvoY nov nvrhCreate a new sketch MainWindowVyjme vber Cut selection MainWindow Vstup debuggeruDebugger Output MainWindowVymazaeDelete MainWindow4Vymazae prepojovaciu  iaruDelete Ratsnest Line MainWindow Vymazae prepojku Delete Wire MainWindowVyma~e vberDelete selection MainWindowZrua vberDeselect MainWindow,Odpoj vaetky prepojkyDisconnect All Wires MainWindowLOdpoj vaetky prepojky od tejto api ky0Disconnect all wires connected to this connector MainWindow`Zobraz niektor u~ito n tipy a triky Fritzingu+Display some handy Fritzing tips and tricks MainWindowJZobraz zsobnik s iastok ako zoznam$Display the parts bin in a list view MainWindowHZobraz zsobnik s iastok ako ikony%Display the parts bin in an icon view MainWindow6Nepredvdzae autoroutovanieDo not autoroute MainWindowTPrajete si zachovae importovan s iastky?'Do you want to keep the imported parts? MainWindow>Napriek tomu chcete pokra ovae?Do you want to proceed anyway? MainWindow"Podporte FritzingDonate to Fritzing MainWindowDuplikuje vberDuplicate selection MainWindow*Povolie debugging logEnable debugging log MainWindow&Leptate>n (PDF)...Etchable (PDF)... MainWindow&Leptate>n (SVG)...Etchable (SVG)... MainWindowExportuje 1000 dpi zlu en SVG tejto s iastky v tomto zobrazen7Export 1000 dpi Flattened SVG of this part in this view MainWindowpExportuje 1000 dpi SVG tejto s iastky v tomto zobrazen-Export 1000 dpi SVG of this part in this view MainWindowBExport spisky materilu (BoM)...!Export Bill of Materials (BoM)... MainWindow$Export netlistu...Export Netlist... MainWindowFExportuje normalizovan zl en SVGExport Normalized Flattened SVG MainWindow6Exportuje normalizovan SVGExport Normalized SVG MainWindow"Exportovae SVG... Export SVG... MainWindowExport pre PCBExport for PCB MainWindow6Exportuje vybran s iastkuExport selected part MainWindowPExportuje aktulny nvrh ako SVG obrzok)Export the current sketch as an SVG image MainWindowJExportuje aktulny nvrh do Eagle CAD&Export the current sketch to Eagle CAD MainWindowExportuje aktulny nvrh do Extended Gerber formtu (RS-274X) pre profesionln vrobu PCB]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production MainWindow|Exportuje aktulny nvrh do PDF pre DIY vrobu PCB (fotocesta)EExport the current sketch to PDF for DIY PCB production (photoresist) MainWindow|Exportuje aktulny nvrh do SVG pre DIY vrobu PCB (fotocesta)EExport the current sketch to SVG for DIY PCB production (photoresist) MainWindowxExportuje vidite>n oblase aktulneho nvrhu ako JPG obrzokn oblase aktulneho nvrhu ako PDF obrzokn oblase aktulneho nvrhu ako PNG obrzokn oblase aktulneho nvrhu ako PostScript obrzokCExport the visible area of the current sketch as a PostScript image MainWindowExportovanie... Exporting... MainWindow(Sbor '%1' nenjdenFile '%1' not found MainWindowVypln przdne oblasti medenej vrstvy--vrtane vaetkch spojov pripojench k ZEMIZFill empty regions of the copper layer--fill will include all traces connected to a GROUND MainWindowVypln przdn oblasti medenej vrstvy--s vnimkou vaetkch spojov pripojench k ZEMIRFill empty regions of the copper layer--not including traces connected to a GROUND MainWindowPrv npovedaFirst Time Help MainWindowPrispsob oknu Fit in window MainWindowPreklopieFlip MainWindowBPreklop aktulny vber vodorovne#Flip current selection horizontally MainWindow<Preklop aktulny vber zvisle!Flip current selection vertically MainWindowXPrevedenie aktualizcie routingu a prepojen)Force Update Routing Status and Ratsnests MainWindow0Fritzing sou stka (*%1)Fritzing Part (*%1) MainWindow Ve>kost mrie~ky: Grid Size: MainWindowZemniaca vplH Ground Fill MainWindowTSkryje vaetky vrstvy aktulneho zobrazenia'Hide all the layers of the current view MainWindow*Skrye popis s iastkyHide part label MainWindowzImportuje s iastky a zsobnky z predchdzajcich inatalci0Import parts and bins from previous installation MainWindowInapektor Inspector MainWindow(JPEG obrzok (*.jpg)JPEG Image (*.jpg) MainWindowSpustie %1... Launch %1... MainWindow VrstvyLayers MainWindowPZoznam s iastok (&Spiska materilu)...%List of parts (&Bill of Materials)... MainWindowNa tanie... Loading... MainWindow$Uzamkne s iastku Lock Part MainWindowMainWindow::populateMenuWithIndex: nejde na tae prklad s id='%1'EMainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow4Minimalizuje aktulne oknoMinimize current window MainWindowPresune vybran spoje na druh stranu dosky (Pozn.: "prv" stopa bude presunut a ostatn bud nasledovae na rovnak stranu)Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) MainWindow<Presunt na druh stranu doskyMove to other side of the board MainWindowNovNew MainWindow:V '%1' ~iadny nvrh nenjdenNo Sketch found in '%1' MainWindow8}iadne prepojky k routovaniuNo connections to route MainWindow4}iadna meden horn vrstvaNo copper top layer MainWindowNebola njden presn zhodn s iastka; Fritzing vybral s iastku s najbli~ami vlastnoseami.ANo exactly matching part found; Fritzing chose the closest match. MainWindowNeboli njden ~iadne neaktulne s iastky. Vaetky Vaae s iastky s aktulne.7No outdated parts found. All your parts are up-to-date. MainWindow4S iastka s touto charakteristikou neexistuje. Pracujeme na vyhnut sa tejto sprve a prve Vm neostva in ne~ zvolie medzi vlastnoseami, ktor existujNo part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist MainWindow6Online referencie s iastokOnline Parts Reference MainWindow0Online galria projektovOnline Projects Gallery MainWindowOnline vukaOnline Tutorials MainWindowJOtvorte web strnku daru pre FritzingOpen Fritzing donation web page MainWindow2Otvorte Fritzing prkladyOpen Fritzing examples MainWindow2Otvor npovedu FritzinguOpen Fritzing help MainWindow8Otvorte referencie s iastokOpen Parts Reference MainWindowROtvor programtorsk okno mikroprocesoru'Open microcontroller programming window MainWindow6Otvorie programtorske oknoOpen programming window MainWindowObjednae PCB vytvoren z Vaho nvrhu - vo vbornom Fritzing Fab@Order a PCB created from your sketch--from fabulous Fritzing Fab MainWindowObjednae PCB...Order a PCB... MainWindow(Neaktulne s iastkyOutdated parts MainWindow&PNG obrzok (*.png)PNG Image (*.png) MainWindow$Nastavenie strnky Page Setup MainWindow(Vlo~ obsah schrnkyPaste clipboard contents MainWindow<Vlo~ obsah schrnky na miesto!Paste clipboard contents in place MainWindow Vlo~ie na miestoPaste in Place MainWindowTVyberte predchdzajcu zlo~ku Fritzingu...-Please choose the previous Fritzing folder... MainWindowPPoale projekt na webov strnky Fritzing&Post a project to the Fritzing website MainWindow2Zabrni presunu s iastkyPrevent a part from being moved MainWindow.Vytla aktulny poh>adPrint the current view MainWindowTla ... Printing... MainWindowVykonaeProceed MainWindow Ukon aplikciuQuit the application MainWindowRiadenieRaise and Lower MainWindowPripravenReady MainWindowPrepo tae stav routingu a prepojenia prepojok (v prpade, ~e autoaktualizcia nepracuje sprvne)_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) MainWindowDopreduRedo MainWindow&Odstrnie bod zlomuRemove Bendpoint MainWindow,Odstrnie meden vplHRemove Copper Fill MainWindow,Odstrnie meden vplHRemove copper fill MainWindow*Odstrni meden vplHRemove the copper fill MainWindow"Nahlsie chybu...Report a bug... MainWindowVNahlsi chybu, ktor ste naali vo Fritzingu%Report a but you've found in Fritzing MainWindow"Obnovie vchodzieRestore Default MainWindow Oto ieRotate MainWindow*Oto ie o 180 {180?} Rotate 180� MainWindow8Oto ie o 135 doprava {45?}Rotate 45� Clockwise MainWindow4Oto ie o 45 do>ava {45?}Rotate 45� Counter Clockwise MainWindow8Oto ie o 135 doprava {90?}Rotate 90� Clockwise MainWindow4Oto ie o 45 do>ava {90?}Rotate 90� Counter Clockwise MainWindowPOto aktulny vber o 45 stupHov vpravo-Rotate current selection 45 degrees clockwise MainWindowNOto aktulny vber o 45 stupHov v>avo5Rotate current selection 45 degrees counter clockwise MainWindowNOto aktulny vber o 90 stupHov v>avo5Rotate current selection 90 degrees counter clockwise MainWindowHOto vybran s stky o 180 stupHov(Rotate the selected parts by 180 degrees MainWindowVOto vybran s iastky o 90 stupHov vpravo1Rotate the selected parts by 90 degrees clockwise MainWindow"Routing dokon enRouting completed MainWindowPRouting dokon en s pou~itm %n prepojkyPRouting dokon en s pou~itm %n prepojokPRouting dokon en s pou~itm %n prepojok)Routing completed using %n jumper part(s) MainWindow&SVG obrzky (*.svg)SVG Image (*.svg) MainWindowUlo~ie %1Save %1 MainWindowhUlo~ spis materilov (BoM)/Nkupn zoznam ako text4Save a Bill of Materials (BoM)/Shopping List as text MainWindow6Ulo~ netlist v XML formteSave a netlist in XML format MainWindow(Ulo~ aktulny nvrhSave the current sketch MainWindowUlo~ie '%1' Saved '%1' MainWindow Schma Schematic MainWindow6Vybrae vaetky meden vplneSelect All CopperFill MainWindow,Vybrae vaetky prepojkySelect All Jumpers MainWindowBVybrae vaetky uzamknut s iastkySelect All Locked Parts MainWindow&Vybrae vaetky spojeSelect All Traces MainWindow0Vybrae vaetky priechodkySelect All Vias MainWindowFVybrae sbor Fritzing pre otvorenieSelect a Fritzing File to Open MainWindowJVyberie vaetky polo~ky medenej vplneSelect all copper fill items MainWindow(Vyberie vaetky prvkySelect all elements MainWindowPVybrae vaetky polo~ky prepojok s iastokSelect all jumper item parts MainWindowhVyberie vaetky s iastky, ktor nem~u bye presunut$Select all parts that can't be moved MainWindow(Vyberie vaetky spojeSelect all trace wires MainWindowTVyberie vaetky spoje vyHat z autoroutingu0Select all trace wires excluded from autorouting MainWindowFVyberie vaetky priechodky s iastokSelect all via parts MainWindow6Vybrae neaktulne s iastkySelect outdated parts MainWindowPosune vzad Send Backward MainWindow^Posunie vybran objekt(y) vzad vo svojej vrstve+Send selected object(s) back in their layer MainWindowdPresunie vybran objekt(y) dozadu vo svojej vrstve2Send selected object(s) to the back of their layer MainWindowPresune dozadu Send to Back MainWindowHNastav obe meden vrstvy klikate>n Set both copper layers clickable MainWindowNNastav spodn meden vrstvu klikate>n!Set copper bottom layer clickable MainWindowLNastav horn meden vrstvu klikate>nSet copper top layer clickable MainWindow@Nastavie ve>kose mrie~ky pre %1.Set the grid size for %1. MainWindowZdie>aeShare MainWindow"Zdie>ae online...Share online... MainWindow Shell spustil %1Shell launch %1 MainWindowLZobrazie s iastky zsobniku ako ikonyShow Parts Bin Icon View MainWindowNZobrazie s iastky zsobniku ako zoznamShow Parts Bin List View MainWindow&Zobraz okno o Qt'sShow Qt's about box MainWindowlZobraz vaetky dostupn vrstvy pre aktulne zobrazenie2Show all the available layers for the current view MainWindow*Zobraz poh>ad na PCBShow the PCB view MainWindow.Zobraz okno O programu Show the application's about box MainWindow@Zobraz poh>ad na mont~nu doskuShow the breadboard view MainWindow0Zobraz poh>ad na schmuShow the schematic view MainWindow"Nvrh exportovanSketch exported MainWindow6Nvrh exportovan do GerberSketch exported to Gerber MainWindowPrep te!Sorry! MainWindowfPrep te, funkcia %1 nebola doposia> implementovan(Sorry, "%1" has not been implemented yet MainWindow(Zadajte nzov sboruSpecify a file name MainWindowVyrovnae krivkuStraighten Curve MainWindow@Vyrovn krivku vybranej prepojky)Straighten the curve of the selected wire MainWindowspeane aktualizovanch %1 s iastok. Skontrolujte vaetky poh>ady pre potencilne ved>ajaie  inky.SSuccessfully updated %1 part(s). Please check all views for potential side-effects. MainWindowSVG %1 neobsahuje vrstvu '%2'. alaie informcie o tom, ako vytvorie vlastn obrazec dosky njdete v kurze na <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/. MainWindow.Prepne %1 s modulom %2Swapped %1 with module %2 MainWindow"Na jednostrannej doske nie je horn meden vrstva (me 1) k dispozcii. Prepnite dosku na obojstrann alebo zvo>te spodn meden vrstvu (me 0).The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. MainWindowTto funkcia  oskoro poskytne export nvrhu Fritzing do EAGLE PCB software. Pokia> by ste chceli mae viac exportov do svojich ob>bench nstrojov EDA, prosm dajte nm vediee alebo nm prispejte.This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. MainWindow$Usporiadae prepoje Tidy Wires MainWindow2Usporiada vybran prepojeTidy selected wires MainWindow>Tipy, triky a klvesov skratkyTips, Tricks and Shortcuts MainWindowHorn vrstva Top Layer MainWindow@Nejde exportovae %1 ako zdie>an Unable to export %1 as shareable MainWindowPNejde exportovae %1 do zdielanho nvrhu'Unable to export %1 to shareable sketch MainWindowNejde ulo~ie %1Unable to save %1 MainWindownNejde ulo~ie sbor BOM, ale text je ulo~en v schrnke.:Unable to save BOM file, but the text is on the clipboard. MainWindowSpeUndo MainWindowHistria Spt Undo History MainWindow2Aktualizcia %1 s iastokUpdate %1 part(s) MainWindowBAktualizuje InfoView pri prechodeUpdate InfoView on hover MainWindow<Aktualizovae vybran s iastkyUpdate selected parts MainWindowPri autoroutingu sa nezna tento prepojovac spoj, priechod alebo prepojkuDWhen autorouting, do not rip up this trace wire, via, or jumper item MainWindowPre pou~itie importovanch s iastok mus bye Fritzing reatartovanDYou will have to restart Fritzing in order to use the imported parts MainWindowVa nvrh dosia> neobsahuje dosku! Pre spean export do Gerber pridajte PCB.VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber. MainWindowZv aieZoom in MainWindowZmenaieZoom out MainWindowako obrzokas Image MainWindow4priame na tanie s iastokdirectly loading parts MainWindowpre vrobufor Production MainWindow palcein MainWindowna tanie %1 loading %1 MainWindow8na tn %1 (mont~n deska)loading %1 (breadboard) MainWindow(na tanie %1 (model)loading %1 (model) MainWindow$na tanie %1 (pcb)loading %1 (pcb) MainWindow*na tanie %1 (schma)loading %1 (schematic) MainWindownov nvrh new sketch MainWindowdVlo~ faloan vnimku, aby bylo vidiee  o sa stane*throw a fake exception to see what happens MainWindow.vlo~ testovaciu vnimkuthrow test exception MainWindow8nejde njse nhradu pre %1. #unable to find replacement for %1.  MainWindowokrhle %1 z: round %1 of: MazeRouterrNie je mo~n prepsae sbor '%1'. Dvod: %2 (chyb.kd %3)5Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ModelBase0Ulo~enie sboru zlyhalo!File save failed! ModelBaseJNejde njse nsledujcu %n s iastku:JNejde njse nsledujce %n s iastky:NNejde njse nsledujcch %n s iastok:(Unable to find the following %n part(s): ModelBasevat ModelBasepopisok  ipu chip label MysteryPartpopisoklabel MysteryPart(tu napate poznmku][write your note here]Note&Zmenie vrstvu spojaChange trace layerPCBSketchWidgetfKliknite na tento pin pre vytiahnutie novho spoja.-Click this connector to drag out a new trace.PCBSketchWidgetdChyba Fritzingu: Nejde renderovae dosku v SVG (1)./Fritzing error: unable to render board svg (1).PCBSketchWidget`Chyba Fritzingu: Nejde renderovae me v SVG (1).0Fritzing error: unable to render copper svg (1).PCBSketchWidget`Chyba Fritzingu: Nejde zapsae meden vplH (1).0Fritzing error: unable to write copper fill (1).PCBSketchWidget`Chyba Fritzingu: Nejde zapsae meden vplH (2).0Fritzing error: unable to write copper fill (2).PCBSketchWidgetNejde vytvorie meden vplH - s iastka bola pravdepodobne vlo~en na in  ase alebo prepoj skr ne~ aktulny PCB.qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.PCBSketchWidgetNejde vytvorie meden vplH - pravdepodobne s iastka nebola vlo~en na PCB.LUnable to create copper fill--probably the part wasn't dropped onto the PCB.PCBSketchWidgetVa nvrh eate neobsahuje dosku! Pridajte PCB, aby bolo mo~n pou~ie meden vplH.UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.PCBSketchWidget&Upravie&Edit PEMainWindow&Exportovae&Export PEMainWindow &Sbor&File PEMainWindowPridae konektor Add connector PEMainWindowPiny Connectors PEMainWindow"Problm konverzieConversion problem PEMainWindow IkonaIcon PEMainWindowSbory obrzkov & patic (%1 %2 %3 %4 %5);;SVG sbory (%1);;JPEG sbory (%2);;PNG sbory (%3);;sbory gEDA patic (%4);;sbory Kicad modulov (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowSbory obrzkov (%1 %2 %3);;SVG sbory (%1);;JPEG sbory (%2);;PNG sbory (%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowInapektor Inspector PEMainWindow VrstvyLayers PEMainWindowOtvorie obrzok Open Image PEMainWindow Editor s iastok Parts Editor PEMainWindow Ulo~ieSave PEMainWindowUlo~ie "%1" Save "%1" PEMainWindow8v %1 nenjden ~iadna pticano footprints found in %1 PEMainWindow8v %1 nenjden ~iadna schmano schematics found in %1 PEMainWindow schma s iastkyschematic part PEMainWindow AutorAuthorPEMetadataView DtumDatePEMetadataView Popis DescriptionPEMetadataView PopisLabelPEMetadataViewVlastnosti PropertiesPEMetadataView Zna kyTagsPEMetadataViewtvarshapePad$Upravie popis pinuEdit Pin Labels PaletteItemPriemer otvoru Hole Diameter PaletteItemHPopis neshlas. Ni nebolo ulo~en.#Label mismatch. Nothing was saved. PaletteItemTu nota kruhuRing Thickness PaletteItemlNjdze pokra ovae, piny s iastky nemaj atandardn ID.;Unable to proceed; part connectors do no have standard IDs. PaletteItemrNejde pokra ovae, nejde njse najvyaaiu roveH zobrazen.1Unable to proceed; unable to find top level view. PaletteItem(rozaren nastaveniaadvanced settings PaletteItemve>kose otvoru hole size PaletteItem palcein PaletteItem Zobrazie hodnotyDisplay Values PartLabel&Zobraz text popisuDisplay the text of the label PartLabel:Zobraz hodnotu vlastnosti %1 Display the value of property %1 PartLabelUpravieEdit PartLabel&Upravie text popisuEdit label text PartLabel&Preklopie vodorovneFlip Horizontal PartLabel Preklopie zvisle Flip Vertical PartLabel0Preklop popis vodorovneFlip label horizontally PartLabel*Preklop popis zvisleFlip label vertically PartLabel Preklopie/Oto ie Flip/Rotate PartLabelVe>kose psma Font Size PartLabel SkryeHide PartLabel*Skrye popis s iastkyHide part label PartLabelText popisu Label text PartLabelText popisu: Label text: PartLabel Ve>kLarge PartLabelStrednMedium PartLabel:Oto ie o 135 doprava {135?}Rotate 135� Clockwise PartLabel6Oto ie o 45 do>ava {135?}Rotate 135� Counter Clockwise PartLabel*Oto ie o 180 {180?} Rotate 180� PartLabel8Oto ie o 135 doprava {45?}Rotate 45� Clockwise PartLabel4Oto ie o 45 do>ava {45?}Rotate 45� Counter Clockwise PartLabel8Oto ie o 135 doprava {90?}Rotate 90� Clockwise PartLabel4Oto ie o 45 do>ava {90?}Rotate 90� Counter Clockwise PartLabelBOto aktulny vber o 90 do>ava5Rotate current selection 90 degrees counter clockwise PartLabel4Oto popis o 135 doprava)Rotate the label by 135 degrees clockwise PartLabel2Oto popis o 135 do>ava1Rotate the label by 135 degrees counter clockwise PartLabel$Oto popis o 180Rotate the label by 180 degrees PartLabel2Oto popis o 45 doprava(Rotate the label by 45 degrees clockwise PartLabel0Oto popis o 45 do>ava0Rotate the label by 45 degrees counter clockwise PartLabel2Oto popis o 90 doprava(Rotate the label by 90 degrees clockwise PartLabel6Nastav ve>k ve>kose psmaSet font size to large PartLabel:Nastav stredn ve>kose psmaSet font size to medium PartLabel4Nastav mal ve>kose psmaSet font size to small PartLabel>Nastav najmenaiu ve>kose psmaSet font size to tiny PartLabel(Nastav popis pre %1Set label for %1 PartLabelMalSmall PartLabelNajmenaTiny PartLabel&Pridae do zsobniku Add to binPartsBinPaletteWidget ZruaieCancelPartsBinPaletteWidget*Nejde njse sbor %1.Cannot find file %1.PartsBinPaletteWidget2Nejde  tae sbor %1: %2.Cannot read file %1: %2.PartsBinPaletteWidget*Zmenie farbu ikony...Change icon color...PartsBinPaletteWidgetHZmenie farbu ikony tohoto zsobnku.*Change the color of the icon for this bin.PartsBinPaletteWidgethNaozaj chcete pridae vybran s iastku do zsobnku?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetfPrajete si ulo~ie zmeny preveden v zsobnku "%1"?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetNeukladae Don't SavePartsBinPaletteWidget.Fritzing zsobnk (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetNa tnie... Loading...PartsBinPaletteWidget Ulo~ieSavePartsBinPaletteWidget(Ulo~ie zsobnk "%1" Save bin "%1"PartsBinPaletteWidget2Vyberte farbu tejto ikonySelect a color for this iconPartsBinPaletteWidget(Zadajte nzov sboruSpecify a file namePartsBinPaletteWidget*Nepomenovan zsobnk Untitled BinPartsBinPaletteWidget^Vaae zmeny bud straten, pokia> ich neulo~te.1Your changes will be lost if you don't save them.PartsBinPaletteWidget,na tnie zsobnku %1loading bin '%1'PartsBinPaletteWidget ZruaitCancel Perfboardst:pcovcolumns Perfboardriadkovrows Perfboard,nastavie ve>kose doskyset board size Perfboardve>kosesize PerfboardH<p><h2>Editor popisov pinov</h2></p>

    Pin Label Editor

    PinLabelDialog<p>Kliknite na popis ved>a  sla pinu pre premenovanie tohto pinu.<

    Click on a label next to a pin number to rename that pin.PinLabelDialog ZruaieCancelPinLabelDialogDopreduRedoPinLabelDialog Ulo~ieSavePinLabelDialogSpeUndoPinLabelDialogdM~ete pou~ie klvesu Tab k posunu cez popisy.</p>@You can use the tab key to move through the labels in order.

    PinLabelDialog2%1 (klikne pre zmenu...)%1 (click to change...) PrefsDialog*Automatick ukladanieAutosave PrefsDialog6Automaticky ulo~ie ka~dch:Autosave every: PrefsDialog ZruaieCancel PrefsDialog<Zmenie sprvanie kolieska myaiChange Wheel Behavior PrefsDialog FarbyColors PrefsDialog PrkazCommand PrefsDialog.Zvraznenie prepojenchConnected Highlight PrefsDialogRiadenieControl PrefsDialog2Krivky vs. rovn prepojkyCurvy vs. straight wires PrefsDialogVaeobecnGeneral PrefsDialog JazykLanguage PrefsDialog.Sprvanie kolieska myaiMouse Wheel Behavior PrefsDialogPVyberte programtor (spustite>n) pre %1'Select a programmer (executable) for %1 PrefsDialog2Zvraznenie neprepojenchUnconnected Highlight PrefsDialog mintminutes PrefsDialog~iadna klvesa stla en = posune klvesa SHIFT prepne posun osy Klvesa Alt alebo klvesa %1 = zv aenieFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialog~iadna klvesa stla en = zv aenie klvesa SHIFT pYepne posun osy Klvesa Alt alebo klvesa %1 = posuneFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialogLNaozaj chcete odstrnie "%1" z nvrhu?5Are you sure you want to remove "%1" from the sketch? ProgramTab DoskaBoard ProgramTab\Fritzing nebol schopn njse '%1', najdite ich1Fritzing is unable to find '%1', please locate it ProgramTabNovNew ProgramTabOdstrnie "%1"? Remove "%1"? ProgramTab Ulo~ieSave ProgramTabDVyberte sbor programu k na taniuSelect a program file to load ProgramTab&Koprovae&Copy ProgramWindow &VyHae&Cut ProgramWindow&Upravie&Edit ProgramWindow&Vlo~ie&Paste ProgramWindow&Predvo>by...&Preferences... ProgramWindow&Vybrae vaetko &Select All ProgramWindow&Zobrazenie&View ProgramWindow DoskaBoard ProgramWindowKopruje vberCopy selection ProgramWindowVyHae vber Cut selection ProgramWindow*Vlo~ie obsah schrnkyPaste clipboard contents ProgramWindowDopreduRedo ProgramWindow Vybrae cel textSelect all text ProgramWindow.Zobraz okno O programu Show the application's about box ProgramWindowSpeUndo ProgramWindowVrstva %1%1 LayerQObjectZkladnBasicQObject DoskaBoardQObjectMont~na doska BreadboardQObject4Zobrazenie mont~nej doskyBreadboard ViewQObjectPosune dopredu Bring forwardQObject Presune dopreduBring to frontQObject2Nejde  tae sbor %1: %2.Cannot read file %1: %2.QObject Zmena pinu %1,%2Change leg of %1,%2QObject*Kontrola aktualizcieCheck for updatesQObjectPripojenie ConnectionQObjectSpodn me Copper BottomQObject&Spodn meden spojeCopper Bottom TraceQObject&Spodn meden vplHCopper Fill BottomQObject$Horn meden vplHCopper Fill TopQObjectHorn me Copper TopQObject$Horn meden spojeCopper Top TraceQObject*Koprovanie sboru %1Copying file %1QObjectUpravie odkaz Edit linkQObject8Chyba  tania sboru %1: %2.Error reading file %1: %2.QObjectLSbor %1 u~ existuje: nebude prepsan/File %1 already exists: it won't be overwrittenQObject.Spracovvanie sboru...File Progress...QObject RmecFrameQObject IkonaIconQObject VstupInputQObjectSpojie prepojku Join WireQObjectMikroprocesorMicrocontrollerQObject(S iastky nenjden.No parts found.QObjectPoznmkyNotesQObjectUps!Oops!QObjectOstatnOtherQObject VstupOutputQObjectZobrazenie PCBPCB ViewQObjectfChyba parsovania (1) na riadku %1, st:pec %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObject`Chyba analzy (2) na riadku %1, st:pec %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectS iastkaPartQObject"Obrzok s iastok Part ImageQObject Popisy s iastok Part LabelsQObject6S iastka je u~ v zsobnikuPart already in binQObjectS iastkyPartsQObject6Zlo~ka s iastok nenjden.Parts folder not found.QObject(Editor popisov pinovPin Label EditorQObjectMajte na pamti, ~e nov nastavenie jazyka sa prejav a~ pri alaom spusten Fritzingu.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectNapjaniePowerQObjectPredvo>by PreferencesQObjectSiee prepojovRatsnestQObject$Vytvor siee spojovRatsnest wiresQObjectPravtkoRulersQObject"Zobrazenie schmySchematic ViewQObjectVybrae %1 Select %1QObject Vybrae vaetky %1 Select all %1QObjectBVybrae vaetky uzamknut s iastkySelect locked partsQObjectDVybrae vaetky neaktulne s iastkySelect outdated partsQObjectPosune dozadu Send backwardQObjectSenzorySensorsQObject"Spodn silkscreenSilkscreen BottomQObjectJSpodn silkscreen (Popisky s iastok)Silkscreen Bottom (Part Labels)QObject Horn silkscreenSilkscreen TopQObjectFHorn silkscreen (Popisy s iastok)Silkscreen Top (Part Labels)QObjectJe nm >to, Fritzing zatia> nezvldne piny a plaky s asne spolu (v %1 v %2)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectJe nm >to, ale Fritzing zatia> nezvldne piny a plaky s asne spolu. (in %1)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectZJe nm >to, typ plaky %1 nie je podporovanSorry, can't handle pad type %1QObjectPrep te, mme problm s prepnacm mechanizmom. Fritzing stle funguje, ale nebudete mce zmenie vlastnosti s iastok.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObject"Rozdelie prepojku Split WireQObjectFSbor %1 nie je sbor Fritzing (2).'The file %1 is not a Fritzing file (2).QObjectFSbor %1 nie je sbor Fritzing (3).'The file %1 is not a Fritzing file (3).QObjectFSbor %1 nie je sbor Fritzing (4).'The file %1 is not a Fritzing file (4).QObjectSoubor '%1' je len pre  tanie; Pou~ite prosm in nzov sboru.kose tvaru plaky je neplatnpad shape size is invalidQObject.parsovanie zlyhalo v %1parse failure in %1QObjectzobrazenie pcbpcb viewQObject0polohe chbaj parametreposition missing paramsQObjectBschma %1 v %2 ne akane kon (1)(schematic %1 unexpectedly ends (1) in %2QObjectBschma %1 v %2 ne akane kon (2)(schematic %1 unexpectedly ends (2) in %2QObjectBschma %1 v %2 ne akane kon (3)(schematic %1 unexpectedly ends (3) in %2QObjectNs iastka schmy %1 nebola v %2 njden!schematic part %1 not found in %2QObject zobrazenie shmyschematic viewQObject@tvar delty nie je implementovanshape delta not implementedQObject*export potla e zlyhalsilk export failureQObject&vrstva(y) potla e, silkscreen layer(s), QObject*vrstva obrysu dosky, the board outline layer, QObjectVlichobe~nikov plaky nie s implementovan trapezoidal pads not implementedQObjectBtvar ploaky %1 nie je podporovanunable to handle pad shape %1QObject Nejde otvorie %1unable to open %1QObject"Nejde parsovae %1unable to parse %1QObject2neo akvan koniec sboruunexpected end of fileQObjectbneo akvan koniec sboru v ptici %1 v sbore %21unexpected end of file in footprint %1 in file %2QObject@neo akvan formt (1) v %1 z %2#unexpected format (1) in %1 from %2QObject&Ignorovae&IgnoreRecoveryDialog&Obnovie&RecoverRecoveryDialog<p><b>Fritzing mo~no havaroval, ale niektor zo zmien v nsledujcich sboroch m~u bye obnoven.</b></p><p>Dtum a  as ka~dho sboru, ktor bol zalohovan, je zobrazen. Pokia> bol sbor ulo~en, jeho dtum a  as je tie~ uveden.</p><p>Pvodn sbory s stle na Vaaom disku, pokia> boli vbec ulo~en. M~ete vybrae  i chcete prepsae pvodn sbor po na tani jeho obnovenho sboru.</p><p><b>Vyberte sbory, ktor chcete obnovie z ni~aie uvedenho zoznamu.</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialog SborFileRecoveryDialogPosledn zloha Last backupRecoveryDialog"Naposledy ulo~en Last savedRecoveryDialogsbor neulo~enfile not savedRecoveryDialog odpor resistanceResistorvlastncustomResizableBoardvaka(mm) height(mm)ResizableBoardvaka: %1mm height: %1mmResizableBoardtvarshapeResizableBoardve>kosesizeResizableBoardarka(mm) width(mm)ResizableBoardarka: %1mm width: %1mmResizableBoard arkawidthRuler DtumDateSchematicFrame SborFilenameSchematicFrameProjektProjectSchematicFrameRevSchematicFrameListSheetSchematicFrame dtumdateSchematicFramezofSchematicFrametvarshapeSchematicFramelistsheetSchematicFrame0Zmena naptia z %1 na %2Change voltage from %1 to %2SchematicSketchWidget ZruaieCancelSetColorDialog>Nastavie ako vchodziu farbu %1Make this the default %1 colorSetColorDialog%1 %2 polo~ky %1 %2 items SketchWidgetpopis %1 '%2' %1 label '%2' SketchWidgetPridae %1Add %1 SketchWidget ZmenieChange SketchWidget4Zmenie farbu %1 z %2 na %3Change %1 color from %2 to %3 SketchWidget&Zmena %1 z %2 na %3Change %1 from %2 to %3 SketchWidget2Zmenie %1 popisku na '%2'Change %1 label to '%2' SketchWidget4Zmenie arku %1 z %2 na %3Change %1 width from %2 to %3 SketchWidget.Zmena odporu z %1 na %2Change Resistance from %1 to %2 SketchWidget<Zmenie farbu prepojky %1 na %2Change color of %1 wires to %2 SketchWidget2Zmenie obrzok z %1 na %2Change image from %1 to %2 SketchWidget>Zmenie zlomov bod pinu pre %1.Change leg bendpoint for %1. SketchWidget4Zmenie krivku pinu pre %1.Change leg curvature for %1. SketchWidget<Zmenie arku prepojky %1 na %2Change width of %1 wires to %2 SketchWidgetPripojieConnect SketchWidget(Vytvorte prepojku %1Create and connect %1 SketchWidget8Vytvorie a pripojie prepojkuCreate and connect wire SketchWidget*Vymazae siee prepojovDelete ratsnest SketchWidgetZruaie vberDeselect SketchWidgetOdpojie Disconnect SketchWidget:Odpojie vaetky prepojky od %1Disconnect all wires from %1 SketchWidgetLOdpojie vaetky prepojky od %1 polo~iek"Disconnect all wires from %1 items SketchWidgetDvojklik Double-click SketchWidgetZDvojklik pre odstrnenie tohto zlomovho bodu&Double-click to delete this bend point SketchWidget4Pretiahni alebo dvojklikniDrag or double-click SketchWidgetPreklopieFlip SketchWidget"Preklopie %2 (%1) Flip %2 (%1) SketchWidget Presune %2 (%1) Move %2 (%1) SketchWidget,PresuH %2 polo~ky (%1)Move %2 items (%1) SketchWidget$Posune popis '%1'Move label '%1' SketchWidgetPresune pin Move leg of SketchWidget*Zmenie ve>kose popisu Resize Note SketchWidget:Zmenie ve>kose dosky na %1 %2Resize board to %1 %2 SketchWidget:Zmenie ve>kose pravtka %1 %2Resize ruler to %1 %2 SketchWidget Oto ieRotate SketchWidgetOto ie %2 (%1)Rotate %2 (%1) SketchWidgetVybrae %1 Select %1 SketchWidget$Vybrae %1 polo~iekSelect %1 items SketchWidgetVybrae vaetko Select All SketchWidget Vber Selection SketchWidgetJav sa to ako pokus o vytvorenie spoja naprie vrstvami. Tto skuto nose by nemala vznikne: kontaktujte vvojrov.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget&zmenie popisy pinovchange pin labels SketchWidget$na tanie ukon en done loading SketchWidgetz %1from %1 SketchWidget&na tanie s iastky loading part SketchWidget`alebo Alt-pretiahnutie pre pretiahnutie segmentuor alt-drag to move the segment SketchWidget do %1to %1 SketchWidgetspojtrace SketchWidgetprepojkawire SketchWidget%1 %n pska%1 %n psky%1 %n psok%1 %n strip(s) Stripboard VyHaeCut StripboardObnovenRestored Stripboardst:pcovcolumns Stripboardriadkovrows StripboardpopisoklabelSymbolPaletteItemnaptievoltageSymbolPaletteItemTipy a TrikyTips and Tricks TipsAndTricks arkawidth TraceWireArabatina - %1 Arabic - %1TranslatorListModelBulhar ina - %1Bulgarian - %1TranslatorListModel8 natina (zjednoduaen) - %1Chinese (Simplified) - %1TranslatorListModel0 natina (tradi n) - %1Chinese (Traditional) - %1TranslatorListModel eatina - %1 Czech - %1TranslatorListModel Holandatina - %1 Dutch - %1TranslatorListModelAngli tina - %1 English - %1TranslatorListModelEston ina - %1 Estonian - %1TranslatorListModel"Franczatina - %1 French - %1TranslatorListModel Galicij ina - %1 Galician - %1TranslatorListModelNem ina - %1 German - %1TranslatorListModelGrt ina - %1 Greek - %1TranslatorListModelHebrej ina - %1 Hebrew - %1TranslatorListModelHindatina - %1 Hindi - %1TranslatorListModelMaar ina - %1Hungarian - %1TranslatorListModelTalian ina - %1 Italian - %1TranslatorListModelJapon ina - %1 Japanese - %1TranslatorListModelKrejatina - %1 Korean - %1TranslatorListModelPolatina - %1 Polish - %1TranslatorListModel:Portugal ina (Brazlska) - %1Portuguese (Brazilian) - %1TranslatorListModel6Portugal ina (Eurpska)- %1Portuguese (European)- %1TranslatorListModelRumunatina - %1 Romanian - %1TranslatorListModelRuatina - %1 Russian - %1TranslatorListModel `paniel ina - %1 Spanish - %1TranslatorListModel`vdatina - %1 Swedish - %1TranslatorListModelThaj ina - %1 Thai - %1TranslatorListModelTure tina - %1 Turkish - %1TranslatorListModelTNov vydanie je k dispozcii k stiahnutiu:3A new interim release is available for downloading: UpdateDialogfNov hlavn vydanie je k dispozcii pre stiahnutie:0A new main release is available for downloading: UpdateDialogKontrola... Checking... UpdateDialogZavrieeClose UpdateDialog:}iadna nov verzia nenjden.No new versions found. UpdateDialogn=utujeme, nieje mo~n na tae informcie o aktualizcii%Sorry, unable to retrieve update info UpdateDialog  iernablackWire modrblueWire hnedbrownWire farbacolorWire(extra siln (48 mil)extra thick (48 mil)Wire zelengreenWireaedgreyWireoran~ovorangeWirefialovpurpleWire ervenredWire"atandard (24 mil)standard (24 mil)Wiresiln (32 mil)thick (32 mil)Wiretenk (16 mil) thin (16 mil)Wire bielawhiteWire~ltyellowWirefritzing-app-0.9.2b/translations/fritzing_sk.ts000066400000000000000000014633021250202676700217400ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 na kód a CreativeCommons:BY-SA na zvyšok <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Fritzing vytvorili: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, a Daniel Tzschentke. Special thanks goes out to: Zvláštne poďakovanie patrí: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzimu, Ayah Bdeirovi, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrelul Bishopovi, Davidovi Cuartiellesovi, Fabianovi Hemmertovi, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrathovi, Jeffu Hoefsovi, Tomu Hulbertovi, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tomovi Igoevi, Hans-Peterovi Kadelovi, Tillovi Savelkoulovi, Jan Sieber, Yaniv Steiner, Olaf Val, Janovi Sieberovi, Yanivovi Steinerovi, Olafovi Vaolovi, Michaela Vieser and Julia Werner. Michaele Vieserovej a Julii Wernerovej. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Ďakujeme Kurtovi Badeltovi a Miguelovi Solisovi za Španielský preklad, to Gianluca Urgese for the Italian translation, Gianluca Urgesovi za Taliansky preklad, to Nuno Pessanha Santos for the Portuguese (European) translation, Nuno Pessanha Santosovi za Portugalsky (Europsky) preklad, to Yuelin and Ninjia for the Chinese (Simplified) translation, Yuelinovi a Ninjiovi za Čínsky (zjednodušený) preklad, to Hiroshi Suzuki for the Japanese translation, Hiroshi Suzukimu za Japonský preklad, to Robert Lee for the Chinese (Traditional) translation, Robertovi Lee za Čínsky (tradičný) preklad, to Vladimir Savinov for the Russian translation, Vladimirovi Savinovi za Ruský preklad, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, Josefovi Duštírovi za Český preklad, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the Fritzing bolo možné vytvoriť s financovaním MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, sponzor Designu Department of Bauhaus-University Weimar, Oddelenie Bauhaus univerzity Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, anonymný darca, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students Zvláštne poďakovanie patrí taktiež všetkým študentom and alpha testers who were brave enough to give a alfa testerom, ktorí mali odvahu sa Fritzing a test spin. pustiť do kolotoča testov Fritzingu. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls riadenie zväčšenia a posunu Stop Now Zastaviť Best So Far Cancel Zrušiť Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type Typ výroby homebrew domáca výroba professional profesionálna custom vlastná Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Šírka spoja Cancel Zrušiť OK OK BinManager Parts Súčiastky BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::setDirtyTab: Nejde nastaviť zásobník '%1' ako dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Nejde nastavit zásobník '%1' ako dirty New bin (%1) Nový zásobník (%1) Select a Fritzing Parts Bin file to open Vybrať Fritzing súbor zásobníku súčiastok pre otvorenie Searching... Bin Zásobník Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Nový zásobník... Create a new parts bin Vytvoriť nový zásobník súčiastok Close Bin Zavrieť zásobník Close parts bin Zavrieť zásobník súčiastok Delete Bin Vymazať zásobník Delete parts bin Vymazať zásobník súčiastok Save Bin Uložiť zásobník Save parts bin Uložiť zásobník súčiastok Save Bin As... Uložiť zásobník ako... Save parts bin as... Uložiť zásobník súčiastok ako... Export Bin... Exportovať zásobník... Save parts bin in compressed format... Uložiť zásobník súčiastok v komprimovanom formáte... Rename Bin... Premenovať zásobník... Rename parts bin... Premenovať zásobník súčiastok... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Zobraziť zásobník ako zoznam Display parts as a list Zobraziť súčiastky ako zoznam Show Bin in Icon View Zobraziť zásobník ako ikony Display parts as icons Zobraziť súčiastky ako ikony Edit Part (new parts editor)... Export Part... Exportovať súčiastku... Remove Part Odstrániť súčiastku Find Part in Sketch Delete bin Vymazať zásobník Do you really want to delete bin '%1'? This action cannot be undone. Naozaj chcete vymazať zásobník '%1'? Túto akciu nebude možné vrátiť. Read-only bin Zásobník iba na čítanie This bin cannot be renamed. Tento zásobník sa nedá premenovať. Rename bin Prejmenuje zásobník Please choose a name for the bin: Zvoľte názov pre zásobník: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Odstrániť zo zásobníku Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Vybrať súbor Fritzing pre otvorenie Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing súbory zásobníku (*%1 *%2);;Fritzing zásobník (*%1);;Fritzing zdieľaný zásobník (*%2) Cannot set a NULL bin as the current one Nejde nastaviť NULL zásobník ako aktuálny Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) jedna vrstva (jednostranný) two layers (double-sided) dve vrstvy (obojstranný) image file súbor obrázkov load image file načítať súbor obrázkov Images Obrázky Select an image file to load Vyberte si súbor obrázkov due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Nejde načítať Unable to load image from %1 %2 Nejde načítať obrázok z %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape tvar BreadboardLogoItem color farba Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Pridať bod zlomu Straighten curve Vyrovnať krivku Remove bendpoint Odstrániť bod zlomu ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools Nástroje &About &O programe About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit &Ukončiť Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Váš návrh je pripravený pre výrobu: neboli nájdené žiadne prekrývajúce sa prípojky ani spoje a súčasne tiež nie sú príliš blízko seba. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging pre debugging DeleteDialog Also delete the file Odstrániť tiež súbor Remove Odstrániť Don't remove Neodstraňovať Dip chip label popis čipu FApplication Fritzing failure Aplikácia Fritzing zlyhala Fritzing caught an exception %1 from %2 in event %3 Fritzing zachytil výnimku %1 z %2 v udalosti %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Fritzing zachytil výnimku z %1 v udalosti %2 Import files from previous version? Importovať súbory z predchádzajúcej verzie? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Prajete si importovať súčiastky a zásobniky, ktoré ste vytvorili v predchádzajúcej verzii Fritzingu? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Pozn.: Môžete importovať neskôr s použitím položky "Pomocník" > "Import súčiastok a zásobnikov z predchádzajúcej verzie..." z ponuky. Import Import Do not import now Momentálne neimportovať Please specify an .fzz file name to save to (cancel will delete the backup) Zadajte názov súboru .fzz pre uloženie (Zrušiť odstráni zálohu) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help Prvá nápoveda <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window &Zavrieť okno Ctrl+W Ctrl+W Close the current sketch Uzavrie aktuálny návrh %1 - %2 %1 - %2 Specify a file name Zadajte názov súboru Save "%1" Uložiť "%1" Do you want to save the changes you made in the document "%1"? Prajete si uložiť zmeny vykonané v dokumente "%1"? Your changes will be lost if you don't save them. Vaše zmeny budú stratené, pokiaľ ch neuložíte. Save... Uložiť... Save Uložiť Don't Save Neukladať Cancel Zrušiť Ctrl+D Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel Zrušiť OK OK OK and ground fill OK and copper fill Hole hole size veľkosť otvoru HtmlInfoView Change the part label here Tu zmente popis súčiastky Part breadboard view image Obrázok súčiastky montážnej dosky Part schematic view image Obrázok súčiastky schémy Part pcb view image Obrázok súčiastky dosky PCB Part version number Číslo verzie súčiastky Locked Zamknuté Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Vlastnosti Placement pcb layer Tags Značky Connections Piny conn. kon. name názov type typ connected to %n item(s) pripojené k %n položke pripojené ke %n položkám pripojené k %n položkám (autoroutable) (automaticky routovatelné) Wire Prepojka Ratsnest wire Prepojovacia sieť Trace wire %1 Plošný spoj %1 v. %1 %2 v. %1 %2 obsolete location rotation degrees ItemBase family rodina type typ model model size veľkosť color farba resistance odpor capacitance kondenzátor inductance indukčnosť voltage napätie current prúd power napájanie pin spacing odstup pinov rated power menovité napájanie rated voltage menovité napätie rated current menovitý prúd version verzia package púzdro shape tvar form forma part number číslo súčiastky maximum resistance maximálny odpor pins piny spacing odstup frequency kmitočet processor procesor variant varianta layers vrstvy tolerance tolerancia descr popis filename názov súboru title titulok date dátum rev rev sheet list project projekt banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part Súčiastka model part problem problém modelu súčiastky file for %1 %2 not found unable to create renderer for svg %1 nejde vytvoriť renderovaný svg %1 KicadModuleDialog Cancel Zrušiť OK OK LayerPalette show all layers zobraziť všetky vrstvy LinkDialog url: url: text: text: Cancel Zrušiť OK OK LogoItem text shape tvar due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Nejde zobraziť Unable to display image from %1 Nejde zobraziť obrázok z %1 MainWindow Rotate Otočiť Share Zdieľať Flip Preklopiť Autoroute Automaticky routovať Both Layers Obe vrstvy Bottom Layer Spodná vrstva Top Layer Horná vrstva Add a note Pridať poznámku Ready Pripravený Save %1 Uložiť %1 Unable to open '%1': %2 Specify a file name Zadajte názov súboru Change image to %2 Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable Nejde exportovať %1 ako zdieľaný Fritzing Part (*%1) Fritzing součástka (*%1) Unable to export %1 to shareable sketch Nejde exportovať %1 do zdielaného návrhu Do you want to keep the imported parts? Prajete si zachovať importované súčiastky? No connections to route Žiadne prepojky k routovaniu Routing completed Routing dokončený Routing completed using %n jumper part(s) Routing dokončený s použitím %n prepojky Routing dokončený s použitím %n prepojok Routing dokončený s použitím %n prepojok Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed %1 z %2 routovaných prepojov - %n prepojka, ktorá bude ešte routovaná %1 z %2 routovaných prepojov - %n prepojky, ktoré bude ešte routované %1 z %2 routovaných prepojov - %n prepojok, ktoré budú ešte routováné Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB Export pre PCB No Sketch found in '%1' V '%1' žiadny návrh nenájdený Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] %1 - [%2] No copper top layer Žiadna medená horná vrstva The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Na jednostrannej doske nie je horná medená vrstva (meď 1) k dispozícii. Prepnite dosku na obojstrannú alebo zvoľte spodnú medenú vrstvu (meď 0). Sorry! Prepáčte! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Súčiastka s touto charakteristikou neexistuje. Pracujeme na vyhnutí sa tejto správe a práve Vám neostáva iné než zvoliť medzi vlastnosťami, ktoré existujú No exactly matching part found; Fritzing chose the closest match. Nebola nájdená presná zhodná súčiastka; Fritzing vybral súčiastku s najbližšími vlastnosťami. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Prepnúť %1 s modulom %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. SVG %1 neobsahuje vrstvu '%2'. Ďalšie informácie o tom, ako vytvoriť vlastný obrazec dosky nájdete v kurze na <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 načítanie %1 Loading... Načítanie... new sketch nový návrh Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Zálohovať '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Váš návrh dosiaľ neobsahuje dosku! Pre úspešný export do Gerber pridajte PCB. Choose a folder for exporting Vybrať zložku pre export PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG obrázok (*.png) JPEG Image (*.jpg) JPEG obrázok (*.jpg) SVG Image (*.svg) SVG obrázky (*.svg) Printing... Tlač... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Neboli zroutované ešte všetky spoje. Do you want to proceed anyway? Napriek tomu chcete pokračovať? Proceed Vykonať Cancel Zrušiť Sketch exported Návrh exportovaný Export... Export... Exporting... Exportovanie... Unable to save %1 Nejde uložiť %1 Cannot print to %1 Nejde tlačiť na %1 Cannot write file %1: %2. Nejde zapísať súbor %1: %2. Saved '%1' Uložiť '%1' Select a Fritzing File to Open Vybrať súbor Fritzing pre otvorenie Cannot find file %1. Nejde nájsť súbor %1. Cannot read file 1 %1: %2. Nejde čítať súbor 1 %1: %2. File '%1' not found Súbor '%1' nenájdený directly loading parts priame načítanie súčiastok loading %1 (model) načítanie %1 (model) loading %1 (breadboard) načítání %1 (montážní deska) loading %1 (pcb) načítanie %1 (pcb) loading %1 (schematic) načítanie %1 (schéma) New Nový Ctrl+N Ctrl+N Create a new sketch Vytvoří nový návrh &Open... &Otvoriť... Ctrl+O Ctrl+O &Save &Uložiť Ctrl+S Ctrl+S Save the current sketch Uloží aktuálny návrh &Save As... &Uložiť ako... Shift+Ctrl+S Shift+Ctrl+S Share online... Zdieľať online... Post a project to the Fritzing website Pošle projekt na webové stránky Fritzing JPG... JPG... Export the visible area of the current sketch as a JPG image Exportuje viditeľnú oblasť aktuálneho návrhu ako JPG obrázok PNG... PNG... Export the visible area of the current sketch as a PNG image Exportuje viditeľnú oblasť aktuálneho návrhu ako PNG obrázok PostScript... PostScript... Export the visible area of the current sketch as a PostScript image Exportuje viditeľnú oblasť aktuálneho návrhu ako PostScript obrázok PDF... PDF... Export the visible area of the current sketch as a PDF image Exportuje viditeľnú oblasť aktuálneho návrhu ako PDF obrázok SVG... SVG... Export the current sketch as an SVG image Exportuje aktuálny návrh ako SVG obrázok List of parts (&Bill of Materials)... Zoznam súčiastok (&Súpiska materiálu)... Save a Bill of Materials (BoM)/Shopping List as text Uloží súpis materiálov (BoM)/Nákupný zoznam ako text XML Netlist... XML Netlist... Save a netlist in XML format Uloží netlist v XML formáte SPICE Netlist... Save a netlist in SPICE format Eagle... Eagle... Export the current sketch to Eagle CAD Exportuje aktuálny návrh do Eagle CAD Etchable (PDF)... Leptateľné (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Exportuje aktuálny návrh do PDF pre DIY výrobu PCB (fotocesta) Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Export the current sketch to SVG for DIY PCB production (photoresist) Exportuje aktuálny návrh do SVG pre DIY výrobu PCB (fotocesta) Sketch exported to Gerber Návrh exportovaný do Gerber BoM Text File (*.html) Textový súbor BoM (*.html) Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Exportuje aktuálny návrh do Extended Gerber formátu (RS-274X) pre profesionálnú výrobu PCB Etchable (SVG)... Leptateľné (SVG)... &Print... &Tlač... Ctrl+P Ctrl+P Print the current view Vytlačí aktuálny pohľad Shell launch %1 Shell spustil %1 throw test exception vlož testovaciu výnimku throw a fake exception to see what happens Vloží falošnú výnimku, aby bylo vidieť čo sa stane &Quit &Ukončiť Ctrl+Q Ctrl+Q Quit the application Ukončí aplikáciu &Open Example &Otvoriť príklad All Všetko MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: nejde načítať príklad s id='%1' &Open Recent Files &Otvoriť nedávne súbory &%1 %2 &%1 %2 Undo Späť Redo Dopredu &Cut &Vyňať Cut selection Vyjme výber &Copy &Kopírovať Copy selection Kopíruje vybrané &Paste &Vložiť Paste clipboard contents Vloží obsah schránky Paste in Place Vložiť na miesto Paste clipboard contents in place Vloží obsah schránky na miesto &Duplicate &Duplikovať Ctrl+D Ctrl+D Duplicate selection Duplikuje výber &Delete &Vymazať Delete selection Vymaže výber &Select All &Vybrať všetko Select all elements Vyberie všetky prvky &Deselect &Zrušiť výber Deselect Zruší výber Add Note Pridať poznámku &Preferences... &Predvoľby... Show the application's about box Zobrazí okno O programu &Edit &Upraviť &Add to bin... &Pridať do zásobniku... Add selected part to bin Pridá vybranú súčiastku do zásobniku Disconnect All Wires Odpojí všetky prepojky Disconnect all wires connected to this connector Odpojí všetky prepojky od tejto špičky Update InfoView on hover Aktualizuje InfoView pri prechode Export Normalized SVG Exportuje normalizované SVG Export 1000 dpi SVG of this part in this view Exportuje 1000 dpi SVG tejto súčiastky v tomto zobrazení Export Normalized Flattened SVG Exportuje normalizované zlúčené SVG Export 1000 dpi Flattened SVG of this part in this view Exportuje 1000 dpi zlučený SVG tejto súčiastky v tomto zobrazení Rotate the selected parts by 90 degrees clockwise Otočí vybrané súčiastky o 90 stupňov vpravo Rotate the selected parts by 180 degrees Otočí vybrané súčástky o 180 stupňov Rotate current selection 90 degrees counter clockwise Otočí aktuálny výber o 90 stupňov vľavo Rotate current selection 45 degrees counter clockwise Otočí aktuálny výber o 45 stupňov vľavo Rotate current selection 45 degrees clockwise Otočí aktuálny výber o 45 stupňov vpravo the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to &Flip Horizontal &Preklopiť vodorovne Flip current selection horizontally Preklopí aktuálny výber vodorovne &Flip Vertical &Preklopiť zvisle Flip current selection vertically Preklopí aktuálny výber zvisle Bring to Front Presunúť dopredu Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Prenesie vybraný(é) objekt(y) vpred v ich vrstve Bring Forward Posunúť dopredu Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Posunie vybraný(é) objekt(y) vpred v ich vrstve Send Backward Posunúť vzad Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Posunie vybraný objekt(y) vzad vo svojej vrstve Send to Back Presunúť dozadu Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Presunie vybraný objekt(y) dozadu vo svojej vrstve Lock Part Uzamknúť súčiastku Prevent a part from being moved Zabráni presunu súčiastky Select All Locked Parts Vybrať všetky uzamknuté súčiastky Select all parts that can't be moved Vyberie všetky súčiastky, ktoré nemôžu byť presunuté &Show All Layers &Zobraziť všetky vrstvy Show all the available layers for the current view Zobrazí všetky dostupné vrstvy pre aktuálne zobrazenie &Hide All Layers &Skryť všetky vrstvy Hide all the layers of the current view Skryje všetky vrstvy aktuálneho zobrazenia &Show part label &Zobraziť popis súčiastky Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise Otočiť o 135° doprava {45�?} Rotate 90� Clockwise Otočiť o 135° doprava {90�?} Rotate 180� Otočiť o 180° {180�?} Rotate 90� Counter Clockwise Otočiť o 45° doľava {90�?} Rotate 45� Counter Clockwise Otočiť o 45° doľava {45�?} &Export... &Exportovať... Export selected part Exportuje vybranú súčiastku Add Bendpoint Pridať bod zlomu Add a bendpoint to the selected wire Pridá bod zlomu vybranej propojky Straighten Curve Vyrovnať krivku Straighten the curve of the selected wire Vyrovná krivku vybranej prepojky Select outdated parts Vybrať neaktuálne súčiastky Update selected parts Aktualizovať vybrané súčiastky Open programming window Otvoriť programátorske okno Open microcontroller programming window Otvorí programátorské okno mikroprocesoru &Zoom In &Zväčšiť Ctrl++ Ctrl++ Zoom in Zväčšiť Ctrl+= Ctrl+= &Zoom Out &Zmenšiť Ctrl+- Ctrl+- Zoom out Zmenšiť &Fit in Window &Prispôsobiť oknu Ctrl+0 Ctrl+0 Fit in window Prispôsobí oknu &Actual Size &Aktuálna veľkosť Actual (real world physical) size Aktuálna (skutočná fyzická) veľkosť 100% Size 100% Veľkosť Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size 100% (pixlov) veľkosť Align to Grid Prichytiť k mriežke Align items to grid when dragging Pri pretiahnutí prichytí položky k mriežke Show Grid Show the grid Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Show Code Show the code (programming) view Display First Time Help &Routing Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Select All Wires Select all wires Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Generating %1 fill... ground copper Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Do you want to update now? unable to find replacement for %1. nejde nájsť náhradu pre %1. &Show Breadboard &Zobraziť montážnu dosku Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Sticky If a "sticky" part is moved, parts on top of it are also moved Show/hide the label for the selected parts Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Find part in sketch... Search for parts in a sketch by matching text Hide part silkscreen Hide/show the silkscreen layer for only this part Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+1 Ctrl+1 Show the breadboard view Zobrazí pohľad na montážnu dosku &Show Schematic &Zobraziť schému Ctrl+2 Ctrl+2 Show the schematic view Zobrazí pohľad na schému &Show PCB &Zobraziť PCB Ctrl+3 Ctrl+3 Show the PCB view Zobrazí pohľad na PCB Ctrl+4 Ctrl+4 Show Parts Bin Icon View Zobraziť súčiastky zásobniku ako ikony Display the parts bin in an icon view Zobrazí zásobnik súčiastok ako ikony Show Parts Bin List View Zobraziť súčiastky zásobniku ako zoznam Display the parts bin in a list view Zobrazí zásobnik súčiastok ako zoznam &Minimize &Minimalizovať Ctrl+M Ctrl+M Minimize current window Minimalizuje aktuálne okno Debugger Output Výstup debuggeru Online Tutorials Online výuka Ctrl+? Ctrl+? Open Fritzing help Otvorí nápovedu Fritzingu Donate to Fritzing Podporte Fritzing Open Fritzing donation web page Otvorte web stránku daru pre Fritzing Online Projects Gallery Online galéria projektov Open Fritzing examples Otvorte Fritzing príklady Online Parts Reference Online referencie súčiastok Open Parts Reference Otvorte referencie súčiastok First Time Help Prvá nápoveda Check for updates... Kontrola aktualizácie... Check whether a newer version of Fritzing is available for download Skontroluje, či nie je k stiahnutiu novšia verzia Fritzingu &About &O programe Tips, Tricks and Shortcuts Tipy, triky a klávesové skratky Display some handy Fritzing tips and tricks Zobrazí niektoré užitočné tipy a triky Fritzingu &About Qt &O Qt Show Qt's about box Zobrazí okno o Qt's Report a bug... Nahlásiť chybu... Report a but you've found in Fritzing Nahlási chybu, ktorú ste našli vo Fritzingu Enable debugging log Povoliť debugging log &Import parts and bins from old version... &Import súčiastok a zásobnikov z predchádzajúcich verzií... Import parts and bins from previous installation Importuje súčiastky a zásobníky z predchádzajúcich inštalácií Parts Editor Help Display Parts Editor help in a browser &File &Súbor &Export &Exportovať as Image ako obrázok for Production pre výrobu &Part &Súčiastka Raise and Lower Riadenie Ctrl+Shift+V Align &View &Zobrazenie &Window &Okno Ground Fill Zemniaca výplň &Help &Nápoveda Move to bottom layer Move to top layer Delete Ratsnest Line Vymazať prepojovaciu čiaru Delete Wire Vymazať prepojku Hide part label Skryť popis súčiastky Show part label Show part silkscreen top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Autoroute connections... Shift+Ctrl+A Shift+Ctrl+A Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Do not autoroute Nepredvádzať autoroutovanie When autorouting, do not rip up this trace wire, via, or jumper item Pri autoroutingu sa neznačí tento prepojovací spoj, priechod alebo prepojku Move to other side of the board Presunút na druhú stranu dosky Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Presunúť vybrané spoje na druhú stranu dosky (Pozn.: "prvá" stopa bude presunutá a ostatné budú nasledovať na rovnakú stranu) Show unrouted Highlight all unrouted connectors Select All CopperFill Vybrať všetky medené výplne Select all copper fill items Vyberie všetky položky medenej výplne Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select all jumper item parts Vybrať všetky položky prepojok súčiastok Select All Vias Vybrať všetky priechodky Select all via parts Vyberie všetky priechodky súčiastok Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Vyplní prázdne oblasti medenej vrstvy--vrátane všetkých spojov pripojených k ZEMI Fill empty regions of the copper layer--not including traces connected to a GROUND Vyplní prázdné oblasti medenej vrstvy--s výnimkou všetkých spojov pripojených k ZEMI Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D Shift+Ctrl+D Check Loaded Traces The folder "%1" isn't a Fritzing installation folder OK OK Set the grid size for %1. Nastaviť veľkosť mriežky pre %1. Grid Size: Veľkost mriežky: in palce mm mm Restore Default Obnoviť východzie Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Delete Vymazať Page Setup Nastavenie stránky Sorry, "%1" has not been implemented yet Prepáčte, funkcia %1 nebola doposiaľ implementovaná This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Táto funkcia čoskoro poskytne export návrhu Fritzing do EAGLE PCB software. Pokiaľ by ste chceli mať viac exportov do svojich obľúbených nástrojov EDA, prosím dajte nám vedieť alebo nám prispejte. Export SVG... Exportovať SVG... Export Bill of Materials (BoM)... Export súpisky materiálu (BoM)... Unable to save BOM file, but the text is on the clipboard. Nejde uložiť súbor BOM, ale text je uložený v schránke. Export Netlist... Export netlistu... Set both copper layers clickable Nastaví obe medené vrstvy klikateľné Set copper top layer clickable Nastaví hornú medenú vrstvu klikateľnú Set copper bottom layer clickable Nastaví spodnú medenú vrstvu klikateľnú Select All Traces Vybrať všetky spoje Select all trace wires Vyberie všetky spoje Force Update Routing Status and Ratsnests Prevedenie aktualizácie routingu a prepojení Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Prepočítať stav routingu a prepojenia prepojok (v prípade, že autoaktualizácia nepracuje správne) Select all trace wires excluded from autorouting Vyberie všetky spoje vyňaté z autoroutingu Select All Jumpers Vybrať všetky prepojky Tidy Wires Usporiadať prepoje Tidy selected wires Usporiada vybrané prepoje Copper Fill Medená výplň Remove Copper Fill Odstrániť medenú výplň Remove the copper fill Odstráni medenú výplň Copper Top and Copper Bottom layers are both active Obe medené vrstvy, horná a spodná, sú aktivne Order a PCB... Objednať PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Objednať PCB vytvorené z Vášho návrhu - vo výbornom Fritzing Fab Copper Top layer is active Horná medená vrstva je aktívna Copper Bottom layer is active Spodná medená vrstva je aktívna Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting... Autorouting Progress... Prebieha autorouting... jumpers copperfill vias Remove Bendpoint Odstrániť bod zlomu Please choose the previous Fritzing folder... Vyberte predchádzajúcu zložku Fritzingu... You will have to restart Fritzing in order to use the imported parts Pre použitie importovaných súčiastok musí byť Fritzing reštartovaný Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill Odstrániť medenú výplň &Wire Color &Farba prepojky Launch %1... Spustiť %1... No outdated parts found. All your parts are up-to-date. Neboli nájdené žiadne neaktuálne súčiastky. Všetky Vaše súčiastky sú aktuálne. Outdated parts Neaktuálne súčiastky Successfully updated %1 part(s). Please check all views for potential side-effects. Úspešne aktualizovaných %1 súčiastok. Skontrolujte všetky pohľady pre potenciálne vedľajšie účinky. Update %1 part(s) Aktualizácia %1 súčiastok Inspector Inšpektor Undo History História Spät Breadboard Montážna doska Schematic Schéma PCB PCB Layers Vrstvy Couldn't get the dock widget Nejde zadokovať widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: okrúhle %1 z: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): Nejde nájsť následujúcu %n súčiastku: Nejde nájsť následujúce %n súčiastky: Nejde nájsť následujúcích %n súčiastok: at v File save failed! Uloženie súboru zlyhalo! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Nie je možné prepísať súbor '%1'. Dôvod: %2 (chyb.kód %3) MysteryPart label popisok chip label popisok čipu NetLabel net label Note [write your note here] tu napíšte poznámku] PCBSketchWidget Create Trace from Ratsnest Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Kliknite na tento pin pre vytiahnutie nového spoja. Change trace layer Zmeniť vrstvu spoja Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Váš návrh ešte neobsahuje dosku! Pridajte PCB, aby bolo možné použiť medenú výplň. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Chyba Fritzingu: Nejde renderovať dosku v SVG (1). Fritzing error: unable to render copper svg (1). Chyba Fritzingu: Nejde renderovať meď v SVG (1). Fritzing error: unable to write copper fill (1). Chyba Fritzingu: Nejde zapísať medenú výplň (1). Fritzing error: unable to write copper fill (2). Chyba Fritzingu: Nejde zapísať medenú výplň (2). Copper fill: please select only the board you want to fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: Unable to create copper fill--probably the part wasn't dropped onto the PCB. Nejde vytvoriť medenú výplň - pravdepodobne súčiastka nebola vložená na PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Nejde vytvoriť medenú výplň - súčiastka bola pravdepodobne vložená na inú časť alebo prepoj skôr než aktuálny PCB. Clear ground fill seeds PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor Editor súčiastok SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Ikona Metadata Connectors Piny Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Ctrl+4 Show the icon view Ctrl+5 Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Súbory obrázkov & patic (%1 %2 %3 %4 %5);;SVG súbory (%1);;JPEG súbory (%2);;PNG súbory (%3);;súbory gEDA patic (%4);;súbory Kicad modulov (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Súbory obrázkov (%1 %2 %3);;SVG súbory (%1);;JPEG súbory (%2);;PNG súbory (%3)%4%5 Open Image Otvoriť obrázok Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Problém konverzie Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Vrstvy Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 v %1 nenájdená žiadna schéma schematic part schéma súčiastky no footprints found in %1 v %1 nenájdená žiadna pätica Relocate connector %1 &File &Súbor Inspector Inšpektor Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Exportovať &Edit &Upraviť This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Uložiť Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Uložiť "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Pridať konektor Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Dátum Set the part's author Author Autor Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Popis Set the default part label prefix Label Popis Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Vlastnosti Set the part's tags Tags Značky PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape tvar center north east south west connect to PaletteItem Edit Pin Labels Upraviť popis pinu Fritzing Fritzing Unable to proceed; unable to find top level view. Nejde pokračovať, nejde nájsť najvyššiu úroveň zobrazení. Unable to proceed; part connectors do no have standard IDs. Njdze pokračovať, piny súčiastky nemajú štandardné ID. Label mismatch. Nothing was saved. Popis nesúhlasí. Nič nebolo uložené. hole size veľkosť otvoru advanced settings rozšírené nastavenia in palce mm mm Hole Diameter Priemer otvoru Ring Thickness Tučnota kruhu PartLabel Edit Upraviť Edit label text Upraviť text popisu Hide Skryť Hide part label Skryť popis súčiastky Display Values Zobraziť hodnoty Flip/Rotate Preklopiť/Otočiť Font Size Veľkosť písma Rotate the label by 45 degrees clockwise Otočí popis o 45° doprava Rotate the label by 90 degrees clockwise Otočí popis o 90° doprava Rotate the label by 135 degrees clockwise Otočí popis o 135° doprava Rotate the label by 180 degrees Otočí popis o 180° Rotate the label by 135 degrees counter clockwise Otočí popis o 135° doľava Rotate current selection 90 degrees counter clockwise Otočí aktuálny výber o 90° doľava Rotate 45� Clockwise Otočiť o 135° doprava {45�?} Rotate 90� Clockwise Otočiť o 135° doprava {90�?} Rotate 135� Clockwise Otočiť o 135° doprava {135�?} Rotate 180� Otočiť o 180° {180�?} Rotate 135� Counter Clockwise Otočiť o 45° doľava {135�?} Rotate 90� Counter Clockwise Otočiť o 45° doľava {90�?} Rotate 45� Counter Clockwise Otočiť o 45° doľava {45�?} Rotate the label by 45 degrees counter clockwise Otočí popis o 45° doľava Flip Horizontal Preklopiť vodorovne Flip label horizontally Preklopí popis vodorovne Flip Vertical Preklopiť zvisle Flip label vertically Preklopí popis zvisle Tiny Najmenší Set font size to tiny Nastaví najmenšiu veľkosť písma Small Malé Set font size to small Nastaví malú veľkosť písma Medium Stredná Set font size to medium Nastaví strednú veľkosť písma Large Veľké Set font size to large Nastaví veľkú veľkosť písma Label text Text popisu Display the text of the label Zobrazí text popisu Display the value of property %1 Zobrazí hodnotu vlastnosti %1 Set label for %1 Nastaví popis pre %1 Label text: Text popisu: PartsBinPaletteWidget Untitled Bin Nepomenovaný zásobník Save Uložiť Specify a file name Zadajte názov súboru Fritzing Bin (*%1) Fritzing zásobník (*%1) Fritzing Fritzing Cannot find file %1. Nejde nájsť súbor %1. Cannot read file %1: %2. Nejde čítať súbor %1: %2. Loading... Načítánie... loading bin '%1' načítánie zásobníku %1 Save bin "%1" Uložiť zásobník "%1" Do you want to save the changes you made in the bin "%1"? Prajete si uložiť zmeny prevedené v zásobníku "%1"? Your changes will be lost if you don't save them. Vaše zmeny budú stratené, pokiaľ ich neuložíte. Don't Save Neukladať Ctrl+D Ctrl+D Cancel Zrušiť Add to bin Pridať do zásobniku Do you really want to add the selected part to the bin? Naozaj chcete pridať vybranú súčiastku do zásobníku? Change icon color... Zmeniť farbu ikony... Change the color of the icon for this bin. Zmeniť farbu ikony tohoto zásobníku. Select a color for this icon Vyberte farbu tejto ikony Perfboard size veľkosť Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel Zrušit rows riadkov columns stĺpcov set board size nastaviť veľkosť dosky PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Editor popisov pinov</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Kliknite na popis vedľa čísla pinu pre premenovanie tohto pinu. You can use the tab key to move through the labels in order.</p> Môžete použiť klávesu Tab k posunu cez popisy.</p> Cancel Zrušiť Save Uložiť Undo Späť Redo Dopredu PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Všeobecné Cancel Zrušiť OK OK Mouse Wheel Behavior Správanie kolieska myši Clear Settings Command Príkaz Control Riadenie When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Change Wheel Behavior Zmeniť správanie kolieska myši Code View Autosave Automatické ukladanie Autosave every: Automaticky uložiť každých: minutes minút Language Jazyk Colors Farby %1 (click to change...) %1 (kliknúť pre zmenu...) Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Vyberte programátor (spustiteľný) pre %1 Connected Highlight Zvýraznenie prepojených Unconnected Highlight Zvýraznenie neprepojených no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom žiadna klávesa stlačená = posunúť klávesa SHIFT prepne posun osy Klávesa Alt alebo klávesa %1 = zväčšenie no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis žiadna klávesa stlačená = zväčšenie klávesa SHIFT přepne posun osy Klávesa Alt alebo klávesa %1 = posunúť Curvy vs. straight wires Krivky vs. rovné prepojky Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Nový Open Save Uložiť Platform Board Doska Port Serial Monitor Upload Select a program file to load Vyberte súbor programu k načítaniu Fritzing is unable to find '%1', please locate it Fritzing nebol schopný nájsť '%1', najdite ich Code (*.%1) Remove "%1"? Odstrániť "%1"? Are you sure you want to remove "%1" from the sketch? Naozaj chcete odstrániť "%1" z návrhu? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit &Upraviť Undo Späť Redo Dopredu &Cut &Vyňať Cut selection Vyňať výber &Copy &Kopírovať Copy selection Kopíruje výber &Paste &Vložiť Paste clipboard contents Vložiť obsah schránky &Select All &Vybrať všetko Select all text Vybrať celý text &Preferences... &Predvoľby... Show the application's about box Zobrazí okno O programu &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Doska Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 %1%2 &View &Zobrazenie File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Preferences Predvoľby Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Please note that a new language setting will not take effect until the next time you run Fritzing. Majte na pamäti, že nové nastavenie jazyka sa prejaví až pri ďalšom spustení Fritzingu. Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Soubor '%1' je len pre čítanie; Použite prosím iný názov súboru. Edit link Upraviť odkaz Part Súčiastka Wire Prepojka Set Grid Size Cannot read file %1: %2. Nejde čítať súbor %1: %2. Parse error (1) at line %1, column %2: %3 %4 Chyba parsovania (1) na riadku %1, stĺpec %2: %3 %4 The file %1 is not a Fritzing file (2). Súbor %1 nie je súbor Fritzing (2). The file %1 is not a Fritzing file (4). Súbor %1 nie je súbor Fritzing (4). The file %1 is not a Fritzing file (3). Súbor %1 nie je súbor Fritzing (3). Cannot write file temp: %1 %2 %3. Parts folder not found. Zložka súčiastok nenájdená. No parts found. Súčiastky nenájdené. Parse error (2) at line %1, column %2: %3 %4 Chyba analýzy (2) na riadku %1, stĺpec %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Súčiastka '%1' na '%2' nemá jedinečné id modulu '%3'. Basic Základný Input Vstup Output Výstup ICs ICs Power Napájanie Connection Pripojenie Microcontroller Mikroprocesor Tools Nástroje Shields Shields LilyPad LilyPad Other Ostatné Sensors Senzory Part already in bin Súčiastka je už v zásobniku The part that you have just added, is already there, we won't add it again, right? Súčiastka, ktorú plánujete pridať je už v zásobniku. Chcete ju pridať znova? a label popis a value hodnota files súbory Oops! Ups! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Prepáčte, máme problém s prepínacím mechanizmom. Fritzing stále funguje, ale nebudete môcť zmeniť vlastnosti súčiastok. bb bb Breadboard View Zobrazenie montážnej dosky PCB View Zobrazenie PCB pcb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem schem Schematic View Zobrazenie schémy Error reading file %1: %2. Chyba čítania súboru %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Zmena pinu %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer Vrstva %1 Bring forward Posunúť dopredu Send backward Posunúť dozadu Bring to front Presunúť dopredu Split Wire Rozdeliť prepojku Join Wire Spojiť prepojku Trace wires Vytvor spoj z prepoja Ratsnest wires Vytvor sieť spojov Select all %1 Vybrať všetky %1 Select outdated parts Vybrať všetky neaktuálne súčiastky Select locked parts Vybrať všetky uzamknuté súčiastky unable to open %1 Nejde otvoriť %1 unable to parse %1 Nejde parsovať %1 parse failure in %1 parsovanie zlyhalo v %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Je nám ľúto, ale Fritzing zatiaľ nezvládne piny a plôšky súčasne spolu. (in %1) bad pin argument count nesprávny počet argumentov pinov bad pad argument count nesprávny počet argumentov plôšky Unable to parse copper: %1 %2 %3 Nejde analyzovať meď: %1 %2 %3 footprint %1 not found in %2 pätica %1 v %2 nenájdená unexpected end of file in footprint %1 in file %2 neočakávaný koniec súboru v pätici %1 v súbore %2 unexpected format (1) in %1 from %2 neočakávaný formát (1) v %1 z %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) Je nám ľúto, Fritzing zatiaľ nezvládne piny a plôšky súčasne spolu (v %1 v %2) unexpected end of file neočakávaný koniec súboru pad missing drill ploške chýba vŕtanie pad missing attributes ploške chýbajú atribúty pad missing position plôške chýba pozícia pad missing shape plôške chýba tvar position missing params polohe chýbajú parametre drill missing params vŕtaniu chýbajú parametre drill offset not implemented offset vŕtania nie je implementovaný drill missing ellipse params vŕtaniu chýbajú parametre elipsy attributes missing params atribútom chýbajú parametre bad layer mask parameter nesprávny parameter masky vrstvy Sorry, can't handle pad type %1 Je nám ľúto, typ plôšky %1 nie je podporovaný pad shape missing params tvaru plošky chýbajú parametre pad shape size is invalid veľkosť tvaru plôšky je neplatná trapezoidal pads not implemented lichobežnikové plôšky nie sú implementované shape delta not implemented tvar delty nie je implementovaný non-circular holes not implemented nekruhové otvory nie sú implementované non-copper holes not implemented diery bez medi nie sú implementované unable to handle pad shape %1 tvar plošky %1 nie je podporovaný failure in svg conversion 1: %1 %2 %3 zlyhanie v SVG konverzii 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 zlyhanie v SVG konverzii 2: %1 %2 %3 File Progress... Spracovávanie súboru... Copying file %1 Kopírovanie súboru %1 File %1 already exists: it won't be overwritten Súbor %1 už existuje: nebude prepísaný Check for updates Kontrola aktualizácie icon view zobraziť ako ikony breadboard view zobrazenie montážnej dosky schematic view zobrazenie shémy pcb view zobrazenie pcb Icon Ikona Breadboard Montážna doska Parts Súčiastky Wires Prepojky Part Labels Popisy súčiastok Ratsnest Sieť prepojov Notes Poznámky Rulers Pravítko Frame Rámec Text Board Doska Silkscreen Top Horná silkscreen Silkscreen Top (Part Labels) Horná silkscreen (Popisy súčiastok) Copper Fill Bottom Spodná medená výplň Copper Fill Top Horná medená výplň Copper Bottom Spodná meď Copper Bottom Trace Spodné medené spoje Copper Top Horná meď Copper Top Trace Horné medené spoje Silkscreen Bottom Spodná silkscreen Silkscreen Bottom (Part Labels) Spodná silkscreen (Popisky súčiastok) Part Image Obrázok súčiastok Unknown Layer Neznáma vrstva Select %1 Vybrať %1 bad schematic definition %1 nesprávna definícia schémy %1 schematic part %1 not found in %2 súčiastka schémy %1 nebola v %2 nájdená schematic %1 unexpectedly ends (1) in %2 schéma %1 v %2 nečakane končí (1) schematic %1 unexpectedly ends (2) in %2 schéma %1 v %2 nečakane končí (2) schematic %1 unexpectedly ends (3) in %2 schéma %1 v %2 nečakane končí (3) outline is empty obrys je prázdny the board outline layer, vrstva obrysu dosky, silkscreen layer(s), vrstva(y) potlače, copper layer(s), vrstva(y) medi, mask layer(s), vrstva(y) masky, paste mask layer(s), Unable to translate svg curves in %1 Nejde previesť SVG krivky v %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure export potlače zlyhal %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure export vŕtania zlyhal %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure export masky zlyhal Pin Label Editor Editor popisov pinov mm mm in palce Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Súbor Last backup Posledná záloha Last saved Naposledy uložené file not saved súbor neuložený <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Fritzing možno havaroval, ale niektoré zo zmien v následujúcich súboroch môžu byť obnovené.</b></p><p>Dátum a čas každého súboru, ktorý bol zalohovaný, je zobrazený. Pokiaľ bol súbor uložený, jeho dátum a čas je tiež uvedený.</p><p>Pôvodné súbory sú stále na Vašom disku, pokiaľ boli vôbec uložené. Môžete vybrať či chcete prepísať pôvodný súbor po načítani jeho obnoveného súboru.</p><p><b>Vyberte súbory, ktoré chcete obnoviť z nižšie uvedeného zoznamu.</b></p> &Recover &Obnoviť &Ignore &Ignorovať Resistor Resistor resistance odpor You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape tvar width: %1mm šírka: %1mm height: %1mm výška: %1mm width(mm) šírka(mm) height(mm) výška(mm) keep aspect ratio Revert size veľkosť custom vlastná A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width šírka S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Projekt Filename Súbor Date Dátum Sheet List Rev shape tvar of z date dátum sheet list SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 Zmena napätia z %1 na %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Nastaviť ako východziu farbu %1 Cancel Zrušiť OK OK Pick custom %1 color Current color (%1) SketchWidget loading part načítanie súčiastky done loading načítanie ukončené %1 %2 %1 %2 %1 %2 items %1 %2 položky Select All Vybrať všetko Deselect Zrušiť výber Add %1 Pridať %1 Selection Výber Move %2 (%1) Presunúť %2 (%1) Move %2 items (%1) Presuň %2 položky (%1) Select %1 Vybrať %1 Select %1 items Vybrať %1 položiek Disconnect Odpojiť Change Zmeniť Connect Pripojiť to %1 do %1 Create and connect wire Vytvoriť a pripojiť prepojku Rotate %2 (%1) Otočiť %2 (%1) Note text change Rotate Otočiť Flip Preklopiť Double-click Dvojklik Delete ratsnest Vymazať sieť prepojov from %1 z %1 Move leg of Presunúť pin Change leg curvature for %1. Zmeniť krivku pinu pre %1. Change leg bendpoint for %1. Zmeniť zlomový bod pinu pre %1. Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Javí sa to ako pokus o vytvorenie spoja naprieč vrstvami. Táto skutočnosť by nemala vzniknúť: kontaktujte vývojárov. Create and connect %1 Vytvorte prepojku %1 wire prepojka trace spoj Flip %2 (%1) Preklopiť %2 (%1) Drag or double-click Pretiahni alebo dvojklikni or alt-drag to move the segment alebo Alt-pretiahnutie pre pretiahnutie segmentu Double-click to delete this bend point Dvojklik pre odstránenie tohto zlomového bodu Change %1 label to '%2' Zmeniť %1 popisku na '%2' Change %1 color from %2 to %3 Zmeniť farbu %1 z %2 na %3 Change color of %1 wires to %2 Zmeniť farbu prepojky %1 na %2 Change %1 width from %2 to %3 Zmeniť šírku %1 z %2 na %3 Change width of %1 wires to %2 Zmeniť šírku prepojky %1 na %2 Move label '%1' Posunúť popis '%1' %1 label '%2' popis %1 '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 Zmeniť veľkosť pravítka %1 %2 test connectors Resize Note Zmeniť veľkosť popisu Change Resistance from %1 to %2 Zmena odporu z %1 na %2 Change %1 from %2 to %3 Zmena %1 z %2 na %3 Resize board to %1 %2 Zmeniť veľkosť dosky na %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Odpojiť všetky prepojky od %1 Disconnect all wires from %1 items Odpojiť všetky prepojky od %1 položiek Change image from %1 to %2 Zmeniť obrázok z %1 na %2 change pin labels zmeniť popisy pinov Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Obnovené Cut Vyňať %1 %n strip(s) %1 %n páska %1 %n pásky %1 %n pások rows riadkov columns stĺpcov %1 layout SymbolPaletteItem voltage napätie label popisok Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Tipy a Triky Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width šírka TranslatorListModel English - %1 Angličtina - %1 French - %1 Francúzština - %1 German - %1 Nemčina - %1 Spanish - %1 Španielčina - %1 Japanese - %1 Japončina - %1 Portuguese (European)- %1 Portugalčina (Európska)- %1 Portuguese (Brazilian) - %1 Portugalčina (Brazílska) - %1 Hungarian - %1 Maďarčina - %1 Estonian - %1 Estončina - %1 Dutch - %1 Holandština - %1 Danish - %1 Russian - %1 Ruština - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Taliančina - %1 Hebrew - %1 Hebrejčina - %1 Arabic - %1 Arabština - %1 Hindi - %1 Hindština - %1 Chinese (Simplified) - %1 Čínština (zjednodušená) - %1 Chinese (Traditional) - %1 Čínština (tradičná) - %1 Polish - %1 Polština - %1 Czech - %1 Čeština - %1 Turkish - %1 Turečtina - %1 Swedish - %1 Švédština - %1 Romanian - %1 Rumunština - %1 Thai - %1 Thajčina - %1 Greek - %1 Grétčina - %1 Bulgarian - %1 Bulharčina - %1 Galician - %1 Galicijčina - %1 Korean - %1 Kórejština - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close Zavrieť No new versions found. Žiadna nová verzia nenájdená. A new main release is available for downloading: Nové hlavné vydanie je k dispozícii pre stiahnutie: A new interim release is available for downloading: Nové vydanie je k dispozícii k stiahnutiu: Checking... Kontrola... Sorry, unable to retrieve update info Ľutujeme, nieje možné načítať informácie o aktualizácii WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) tenká (16 mil) standard (24 mil) štandard (24 mil) thick (32 mil) silná (32 mil) extra thick (48 mil) extra silná (48 mil) blue modrá red červená black čierna yellow žltá green zelená grey šedá white biela orange oranžová ochre cyan brown hnedá purple fialová pink color farba Banded ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_sl.qm000066400000000000000000000000361250202676700217160ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Cancel OK Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save... Save Don't Save Cancel Ctrl+D Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Placement pcb layer Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Breadboard Schematic PCB Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Export for PCB Ready Save %1 Fritzing No Sketch found in '%1' Unable to open '%1': %2 Click to highlight unconnected parts Fabricate View from Above View from Below Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Fritzing (*%1) Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector Undo History Layers Couldn't get the dock widget PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Choose a folder for exporting Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Unable to export %1 as shareable &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Etchable (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export SPICE Netlist... Export Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Cannot find file %1. Cannot read file 1 %1: %2. Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? File '%1' not found the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Delete Wire &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box Edit (new parts editor) Open the new parts editor on an existing part &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show part label Show/hide the label for the selected parts &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Show Code Show the code (programming) view Align Move to bottom layer Move to top layer top and bottom bottom top Ground Fill (%1) Copper Fill (%1) View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Ctrl+4 Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser &File &Export as Image for Production &Edit &Part Raise and Lower Ctrl+Shift+V Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise &View &Window &Routing Ground Fill &Help Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Traces Select all trace wires Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select all trace wires excluded from autorouting Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Shift+Ctrl+D Check Loaded Traces Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting Progress... jumpers copperfill vias Remove Bendpoint Please choose the previous Fritzing folder... The folder "%1" isn't a Fritzing installation folder You will have to restart Fritzing in order to use the imported parts Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill &Wire Color Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Launch %1... No outdated parts found. All your parts are up-to-date. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Outdated parts Do you want to update now? unable to find replacement for %1. Update %1 part(s) Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Preparing undo... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Change trace layer Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon Metadata Connectors SVG Inspector Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Show in Folder On the desktop, open the folder containing the current svg file. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection &File Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit Parts Editor This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to write svg to %1 Unable to parse fzp file %1 Fritzing (New) Parts Editor Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Show Metadata Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Change description Change %1 to '%2' Change tags Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Change properties Change connector %1 SVG problem This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Conversion problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Unable to load image file '%1': %2 Unable to load image file '%1' Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. Copy problem Unable to make a local copy of: '%1' no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center W N S E center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Save Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel OK Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Autorouter Settings Part %1 '%2' Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Set Ground Fill Seed Ground Fill Seed Editor Pin Label Editor Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> Edit link mm in The file '%1' is read-only; please use a different filename. Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Fritzing cannot load the parts bin Basic Input Output ICs Power Connection Microcontroller Breadboard View Schematic View PCB View Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 Set all to: Pad ii Icon View Internal Connections <b>Name:</b> Set the connectors's title <b>id:</b> <b>type:</b> <b>Description:</b> Set the connectors's description files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Select all %1 Convert to Via Convert Via to Bendpoint schem Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) mask export failure Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer icon view breadboard view schematic view pcb view N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading Delete ratsnest %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect from %1 Move leg of Connect to %1 Change leg curvature for %1. Change leg bendpoint for %1. Change Create and connect wire Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Rotate %2 (%1) Flip %2 (%1) Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Rotate Flip show %n part label(s) hide %n part label(s) Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize ruler to %1 %2 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Italian - %1 Polish - %1 Turkish - %1 Swedish - %1 Galician - %1 Indonesian - %1 Danish - %1 Japanese - %1 Russian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Czech - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Korean - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_sr.qm000066400000000000000000000000421250202676700217210ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Cancel OK Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save... Save Don't Save Cancel Ctrl+D Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Properties Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Breadboard Schematic PCB Click to highlight unconnected parts Rotate Share Flip Autoroute Fabricate Both Layers Bottom Layer Top Layer View from Above View from Below Add a note Export for PCB Ready Save %1 Fritzing Unable to open '%1': %2 No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Fritzing (*%1) Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector Undo History Layers Couldn't get the dock widget PDF (*.pdf) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) PostScript (*.ps) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Choose a folder for exporting Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Unable to export %1 as shareable &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Etchable (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export SPICE Netlist... Export Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Cannot find file %1. Cannot read file 1 %1: %2. Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? File '%1' not found the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection Delete Minus Delete selection without attached wires &Delete Wire Delete Wire up to bendpoints &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box Edit (new parts editor) Open the new parts editor on an existing part &Add to bin... Add selected part to bin Disconnect All Wires Ctrl+Shift+V Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show part label Show/hide the label for the selected parts &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+1 Ctrl+2 Ctrl+3 Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard Show the breadboard view &Show Schematic Show the schematic view &Show PCB Show the PCB view Show Code Show the code (programming) view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks First Time Help Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser &File &Export as Image for Production &Edit &Part Raise and Lower Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align &View &Window &Routing Ground Fill &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Traces Select all trace wires Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select all trace wires excluded from autorouting Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Shift+Ctrl+D Check Loaded Traces Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting Progress... jumpers copperfill vias Remove Bendpoint Please choose the previous Fritzing folder... The folder "%1" isn't a Fritzing installation folder You will have to restart Fritzing in order to use the imported parts Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill &Wire Color Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Launch %1... No outdated parts found. All your parts are up-to-date. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Outdated parts There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. Do you want to update now? unable to find replacement for %1. Update %1 part(s) Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org Optimizing traces... ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Change trace layer Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon Metadata Connectors SVG Inspector Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Show in Folder On the desktop, open the folder containing the current svg file. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection &File Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit Parts Editor This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to write svg to %1 Unable to parse fzp file %1 Fritzing (New) Parts Editor Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Show Metadata Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Change description Change %1 to '%2' Change tags Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Change properties Change connector %1 SVG problem This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Conversion problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Unable to load image file '%1': %2 Unable to load image file '%1' Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. Copy problem Unable to make a local copy of: '%1' no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center W N S E center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Save Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel OK Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Code No boards available &Preferences... Show the application's about box &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Code Window Code Window - %1 %1%2 QObject Autorouter Settings Part %1 '%2' Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position Set Ground Fill Seed Ground Fill Seed Editor Pin Label Editor Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings %1 wires moved from their saved position in %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Edit link mm in The file '%1' is read-only; please use a different filename. Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Fritzing cannot load the parts bin Basic Input Output ICs Power Connection Microcontroller Breadboard View Schematic View PCB View Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 Set all to: Pad ii Icon View Internal Connections <b>Name:</b> Set the connectors's title <b>Description:</b> Set the connectors's description <b>id:</b> <b>type:</b> files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Select all %1 Convert to Via Convert Via to Bendpoint schem Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. %1 layer export is empty (case 2). silk layer %1 export is empty silk export failure exported drill file is empty drill export failure exported mask layer %1 is empty %1 mask export failure (2) mask export failure exported paste mask layer is empty %1 layer: unable to save to '%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to save pick and place file: %2 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer icon view breadboard view schematic view pcb view N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Fritzing Fab Quote Order your PCB from Fritzing Fab Copies Price per board Price Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading Delete ratsnest %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect from %1 Move leg of Connect to %1 Change leg curvature for %1. Change leg bendpoint for %1. Change Create and connect wire Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Rotate %2 (%1) Flip %2 (%1) Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Rotate Flip show %n part label(s) hide %n part label(s) Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize ruler to %1 %2 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. parts editor Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 German - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Italian - %1 Polish - %1 Swedish - %1 Galician - %1 Indonesian - %1 Danish - %1 Japanese - %1 Russian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Czech - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Korean - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 French - %1 Spanish - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Turkish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_sv.qm000066400000000000000000000000271250202676700217300ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel OK BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. Save... Save Don't Save Cancel Ctrl+D GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Properties Placement pcb layer Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Rotate Share Flip Autoroute Both Layers Bottom Layer Top Layer Add a note Export for PCB Ready Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Fabricate View from Above View from Below Save %1 Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing (*%1) Fritzing Unable to export %1 as shareable No Sketch found in '%1' Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) Printing... All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Select a Fritzing File to Open Cannot find file %1. Cannot read file 1 %1: %2. File '%1' not found directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O BoM Text File (*.html) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) Etchable (PDF)... Etchable (SVG)... &Print... Ctrl+P Print the current view Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box &Edit &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Show part label Ctrl+Shift+V Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Dump all parts Debug dump all parts in this view &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Open programming window Open microcontroller programming window &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Ctrl+5 &Show Welcome Show the welcome view Show Code Show the code (programming) view &Routing &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Select All Wires Select all wires Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... jumpers copperfill vias Do you want to update now? unable to find replacement for %1. &Show Breadboard Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Sticky If a "sticky" part is moved, parts on top of it are also moved Show/hide the label for the selected parts Find part in sketch... Search for parts in a sketch by matching text Hide part silkscreen Hide/show the silkscreen layer for only this part Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view Ctrl+4 Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Test Connectors Connect all connectors to a single test part Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser &File &Export as Image for Production &Part Raise and Lower Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Align &View &Window Ground Fill &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+1 Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Show unrouted Highlight all unrouted connectors Select All CopperFill Select all copper fill items Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select all jumper item parts Select All Vias Select all via parts Check Loaded Traces Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export Netlist... Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Select All Traces Select all trace wires Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select all trace wires excluded from autorouting Select All Jumpers Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Shift+Ctrl+D Copper Top and Copper Bottom layers are both active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Copper Top layer is active Copper Bottom layer is active Autorouting... Autorouting Progress... Remove Bendpoint Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts Generating %1 fill... ground copper Remove copper fill &Wire Color Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon Metadata Connectors Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Inspector Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Save Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Cancel OK Mouse Wheel Behavior Command Control Change Wheel Behavior Code View Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Save Open Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. Edit link Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb Breadboard View PCB View pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem Schematic View Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select all %1 Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates icon view breadboard view schematic view pcb view Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Note text change Rotate Flip Double-click Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 test connectors Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Danish - %1 Russian - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_th.qm000066400000000000000000000000201250202676700217040ustar00rootroot00000000000000 AboutBox <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to Alexander Kaltsas for the Greek translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. to Nikolay Stankov for the Bulgarian translation, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, AutorouteProgressDialog Cancel Stop Now zoom and pan controls Best So Far Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Trace width Cancel OK Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty New bin (%1) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one BinManager::updateTitle: Couldn't set the bin '%1' as dirty Select a Fritzing Parts Bin file to open Bin New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Export Part... Remove Part Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from bin Searching... Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Edit Part (new parts editor)... Find Part in Sketch Remove from Bin Unable to remove part '%1'--it is in use in a sketch Do you really want to remove '%1' from the bin? This operation cannot be undone. Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Board one layer (single-sided) two layers (double-sided) Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? A custom board svg typically has one or two silkscreen layers and one board layer. because there are multiple <silkscreen0> layers <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Remove bendpoint Straighten curve ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected Critical Error About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Fritzing %1 is overlapping (%2 layer) Too close to a border (%1 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Click on an item in the list to highlight of overlap it refers to. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Import files from previous version? Import Do not import now Fritzing failure Fritzing caught an exception from %1 in event %2 Fritzing caught an exception %1 from %2 in event %3 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) Fritzing caught an exception from %1 in event %2: %3 FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save "%1" Do you want to save the changes you made in the document "%1"? Save... Save Don't Save Ctrl+D Your changes will be lost if you don't save them. Cancel GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Connections conn. connected to %n item(s) name type (autoroutable) Wire Trace wire %1 Properties Tags Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Locked Ratsnest wire Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. v. %1 %2 obsolete Placement pcb layer location rotation degrees ItemBase family size color resistance voltage pin spacing rated power rated voltage rated current version package shape form maximum resistance Part model part problem capacitance inductance current power part number type model pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project unable to create renderer for svg %1 file for %1 %2 not found banded top bottom copper bottom copper top silkscreen bottom silkscreen top KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog Cancel OK url: text: LogoItem Unable to display Unable to display image from %1 shape due to a rendering error because the svg is empty due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting text MainWindow Rotate Share Flip Autoroute Add a note Ready Save %1 Specify a file name Fritzing (*%1) Fritzing Unable to export %1 as shareable Fritzing Part (*%1) Unable to export %1 to shareable sketch Do you want to keep the imported parts? No connections to route Routing completed %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Swapped %1 with module %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. PDF (*.pdf) PostScript (*.ps) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) Printing... All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Select a Fritzing File to Open Cannot find file %1. Cannot read file 1 %1: %2. directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) Create a new sketch &Open... Ctrl+O &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website Export the visible area of the current sketch as a JPG image Export the visible area of the current sketch as a PNG image Export the visible area of the current sketch as a PostScript image Export the visible area of the current sketch as a PDF image Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format Export the current sketch to Eagle CAD &Print... Ctrl+P Print the current view Shell launch %1 &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Duplicate Ctrl+D Duplicate selection &Delete Delete selection &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box &Edit &Add to bin... Add selected part to bin Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Show part label &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Select outdated parts Update selected parts &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Shift+Ctrl+0 &Show Breadboard Ctrl+1 Show the breadboard view &Show Schematic Ctrl+2 Show the schematic view &Show PCB Ctrl+3 Show the PCB view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference First Time Help Check for updates... Check whether a newer version of Fritzing is available for download &About Display some handy Fritzing tips and tricks &About Qt Show Qt's about box Report a but you've found in Fritzing &Import parts and bins from old version... Import parts and bins from previous installation &File &Export &Part Raise and Lower &View &Window &Help Page Setup Sorry, "%1" has not been implemented yet Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Choose a folder for exporting This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Export Netlist... Select All Traces Select all trace wires Select all trace wires excluded from autorouting Tidy Wires Tidy selected wires Copper Fill Remove Copper Fill Remove the copper fill Autorouting... Remove Bendpoint Please choose the previous Fritzing folder... You will have to restart Fritzing in order to use the imported parts Remove copper fill &Wire Color Launch %1... No outdated parts found. All your parts are up-to-date. Outdated parts Successfully updated %1 part(s). Please check all views for potential side-effects. Update %1 part(s) throw test exception throw a fake exception to see what happens Select All Jumpers New Ctrl+N Tips, Tricks and Shortcuts Align to Grid Align items to grid when dragging Open programming window Open microcontroller programming window Report a bug... Enable debugging log Both Layers Bottom Layer Top Layer Backing up '%1' Rotate current selection 45 degrees counter clockwise Rotate current selection 45 degrees clockwise Actual (real world physical) size 100% Size 100% (pixel) size Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Autorouting Progress... File '%1' not found Paste in Place Paste clipboard contents in place Delete Routing completed using %n jumper part(s) Delete Ratsnest Line Delete Wire Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page Export for PCB Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... as Image for Production loading %1 Loading... new sketch BoM Text File (*.html) Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Unable to save BOM file, but the text is on the clipboard. Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Select all jumper item parts Select All Vias Select all via parts Shift+Ctrl+D Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Straighten Curve Straighten the curve of the selected wire Select All CopperFill Select all copper fill items unable to find replacement for %1. Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Sketch exported to Gerber Shift+Ctrl+A Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+1 Ground Fill Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. No Sketch found in '%1' the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to &Routing &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Select All Wires Select all wires Fill empty regions of the copper layer--fill will include all traces connected to the seeds Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Generating %1 fill... ground copper Show Grid Show the grid Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Change to single layer pcb Change to two layer pcb Change image to %2 Gerber export can only handle one board at a time--please select the board you want to export. Sticky If a "sticky" part is moved, parts on top of it are also moved Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view jumpers copperfill vias OK Set the grid size for %1. Grid Size: in mm Restore Default Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Check Loaded Traces Unrouted connections There are no unrouted connections in this view. Edit (new parts editor) Open the new parts editor on an existing part Show unrouted Highlight all unrouted connectors Inspector Undo History Breadboard Schematic PCB Layers Couldn't get the dock widget &Delete Wire Parts Editor Help Display Parts Editor help in a browser The folder "%1" isn't a Fritzing installation folder Design Rules Check (DRC) DRC Progress... Highlights any parts that are too close together for safe board production Autoroute connections... Show/hide the label for the selected parts Hide part silkscreen Hide/show the silkscreen layer for only this part Hide part label Show part label Show part silkscreen Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Ctrl+4 Code Show Code Show the code (programming) view Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab Find part in sketch... Search for parts in a sketch by matching text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. SPICE Netlist... Save a netlist in SPICE format Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Export SPICE Netlist... Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Enter Text View from Above View from Below View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Move to bottom layer Move to top layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Align top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Do you want to update now? There are %n outdated part(s) in this sketch. Click to highlight unconnected parts Fabricate Welcome Dump all parts Debug dump all parts in this view Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Test Connectors Connect all connectors to a single test part Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Ctrl+Shift+V (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise MazeRouter Autorouter was cancelled. round %1 of: Unexpected SVG rendering failure--contact fritzing.org best so far: %1 of %2 routed with %n vias Routing reached maximum round %1. Routing stopped! Routing complete! Routing unsuccessful; stopping at round %1. Use best so far... Preparing undo... Optimizing traces... ModelBase File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Unable to find the following %n part(s): at MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Click this connector to drag out a new trace. Change trace layer Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Create Trace from Ratsnest Please designate one or more ground fill seeds before doing a ground fill. Clear ground fill seeds %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: Fritzing Fab Quote Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor Show Icon Ctrl+4 Show the icon view Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Change %1 to '%2' Change tags Change properties Change description Change connector %1 SVG Connectors Show in Folder On the desktop, open the folder containing the current svg file. Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem SVG problem Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Add connector Add %1 connectors There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Icon Metadata Remove Internal Connection Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 Remove internal connection from '%1' Internal connections are very messed up. Add internal connection from '%1' to '%2' The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image &Export Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Load image for view... Open a file to use as the image for this view of the part. Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Edit This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Inspector Unable to load fzp from %1 Unable to create new connector--you may have to start over. Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's family--what other parts is this part related to Family Set the part's properties Properties Set the part's tags Tags Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's url if it is described on a web page URL PESvgView width: height: PEToolView Center N E S W Connector %1 Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector List (a checkmark means the graphic was selected) Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Display Values Flip/Rotate Font Size Rotate the label by 90 degrees clockwise Rotate the label by 180 degrees Rotate current selection 90 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: Hide Hide part label Rotate the label by 45 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 135 degrees counter clockwise Rotate the label by 45 degrees counter clockwise Tiny Set font size to tiny Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise PartsBinPaletteWidget Untitled Bin Save Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Do you want to save the changes you made in the bin "%1"? Don't Save Ctrl+D Your changes will be lost if you don't save them. Add to bin Do you really want to add the selected part to the bin? Save bin "%1" Cancel Loading... loading bin '%1' Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size rows columns Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Undo Redo Save PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Cancel OK Language Colors %1 (click to change...) Connected Highlight Unconnected Highlight Mouse Wheel Behavior Command Control Change Wheel Behavior Autosave Autosave every: minutes no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis General Curvy vs. straight wires Clear Settings When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs Code View Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 ProgramTab Select a program file to load Fritzing is unable to find '%1', please locate it New Save Remove "%1"? Are you sure you want to remove "%1" from the sketch? Code (*.%1) While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Open Platform Board Port Serial Monitor Upload No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. &Code &View Code Window Code Window - %1 No boards available &Preferences... Show the application's about box &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller %1%2 QObject Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Fritzing <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> The file '%1' is read-only; please use a different filename. Edit link Part Wire Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb Breadboard View PCB View pcb schem Schematic View %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select all %1 Select outdated parts File Progress... Check for updates icon view breadboard view schematic view pcb view Icon Breadboard Parts Wires Part Labels Notes Rulers Board Unknown Layer files unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params Sorry, can't handle pad type %1 pad shape missing params shape delta not implemented trapezoidal pads not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 Copying file %1 File %1 already exists: it won't be overwritten Silkscreen Top Silkscreen Top (Part Labels) Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) bad layer mask parameter non-circular holes not implemented non-copper holes not implemented Unable to parse copper: %1 %2 %3 Parts folder not found. Select %1 pad shape size is invalid bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 Part Image Error reading file %1: %2. Select locked parts Basic Input Output ICs Power Connection Microcontroller Tools Frame %1 %2,%3 %4 Change leg of %1,%2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), Unable to translate svg curves in %1 silk export failure drill export failure mask export failure Copper Fill Bottom Copper Fill Top Shields LilyPad Other Sensors Pin Label Editor Ratsnest mm in Cannot write file temp: %1 %2 %3. Cannot autoroute: no board (or multiple boards) found Set Ground Fill Seed Ground Fill Seed Editor %1 mask export failure (2) Select all 'Don't autoroute' traces Select all autorouteable traces Set Grid Size There is no undo for this action, and no further warning!!!! Clear Settings No connections (on the PCB) to route. No connections to route. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. Convert to Via Convert Via to Bendpoint %1 wires moved from their saved position in %2. paste mask layer(s), ii Icon View <b>id:</b> <b>Name:</b> Set the connectors's title <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Internal Connections Set all to: Pad <b>type:</b> Part %1 '%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. unable to copy file '%1' to '%2'. Autorouter Settings %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 Text %1 layer export is empty (case 2). silk layer %1 export is empty %2 ... %1 wires moved from their saved position <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Order your PCB from Fritzing Fab Price per board Price Copies Visit Fritzing Fab Fritzing Fab Quote The total area of the %n PCB(s) in this sketch is Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog &Recover &Ignore File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> Resistor resistance Resistor You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev of date sheet shape SchematicSketchWidget Change voltage from %1 to %2 Change label from %1 to %2 SetColorDialog Make this the default %1 color Cancel OK %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Pick custom %1 color Current color (%1) SketchWidget loading part done loading %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect Change Connect to %1 Create and connect wire Rotate %2 (%1) Rotate Flip Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Resize Note Change Resistance from %1 to %2 Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 Change %1 from %2 to %3 from %1 Move leg of Flip %2 (%1) Change leg curvature for %1. Change leg bendpoint for %1. change pin labels Delete ratsnest Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Create wire from Ratsnest Note text change Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Deselect all Part '%1' not found in sketch Resize board to %1 %2 show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 Add %1 parts test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Tips and Tricks Fritzing Tips and Tricks parts If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor examples Get a jump start by looking at the example circuits under File > Examples. Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. TraceWire width Select from the dropdown, or type in any value from %1 to %2 TranslatorListModel English - %1 French - %1 German - %1 Spanish - %1 Japanese - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Russian - %1 Italian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Danish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Fritzing Fab Wire thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange color brown purple super fine (8 mil) extra thin (12 mil) Banded pink ochre cyan ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_tr.qm000066400000000000000000005347661250202676700217530ustar00rootroot00000000000000`V]qH,J{lMcTrT?TVt{Xk]X\vCxxq{`s%{`I~Y\6Ϥ%UNl^}^hkh=pV~i]+YZį68įįj.52Bl]@֍mH5jpSp|rV\[HekcesKσJDܤxܤʒw 'Ҍ U e|5$.5!"&ĩP(5k**y}*y**m*M*%*%n*0+h+?)++8++^,Bm,D\g-n:!:;+Fd?H J6KQKL4c$MlMe{#M5P,EPWRURxRUjVgQV(VBVWmtX[YY]Z8,-[ %O[f3?X[f32l\g]4^5\_CN`+bp8cرgeLi'igjcb=jcblajcbjej]jɢlkm=n VnrrxR rx|tRFuiuiwmpIyDye< yeqye{gyeDye[ye]yr*y]zlJzlk{ %r{w^{w}m}\}~|U>W]Z 3P5q5XLR0^_^V@~$/'N Fcv-& u9X\[uhT3m>)ABIRWMH>j$k V#JN][:^\- G"b&a)tz){Zo*}C*٧2-46!9 ?yQJvgL# L4wO.=TZ]0'e>UeCrqTr,{(yGeExN:[A5E`?,a$ TpnBPpUrdN27xC& ]vNOd.%tRWlE˓͌Ӓ2ԲH[oU.[wBmK_MbpUP+N[g3J 1,V&Wu.SG44Bf?..ĀBɢC>DpJĮRQ˯RԢ0SBNTIYX,YY,YZ-?^4fjLlTR1lpt.@tM*tQuTbu5(uT>Axebxe xic-y9j|Dy}Y '3ġ.*sS7T3>|ş^xIX.n;A ;Apigq2u*uנ=±±SĵSr:EaaASXcxnYnZ8[bQ\9ug"RIi0C}j`}Yb^QipqZ & 53T7T=[omk6J$+38 .m4 v;j=I>HLFJCqfF:rF."H0;K*NaRBV|>XMYChWwxnkqp>3rx6-su|6\}1JW$o/xMBDο\r[qNv %^VC Yڮ~@Y'0ܡLǒ{mտaֺ6fd")\Qtc?m=lS2u~ʳLj\IGv-n9D t'eN(Ï*Z2-3R59e;N=ߺEG$PѧtTDXaKZefZe[aKcOCc.jNbXlbt;zba{eD]|/}|ouf"nbD{́LׅM](-b&jff_Kɱ,TmIIIU'IXItIuQIIr III I)I^zZfe:bdvs{64vV)7R_ !u, /bYN#b u~~0ö^@9a$w7ٶLۘelDZBpfqzFXw;Gq}3ovR^B   uP~sH~O^FUg(*(,]d5f8[sM;", Hpq)iv)T 18.OбBTcqׯ-ََ q*#o[՞57u qS)7\;g}gg>rqw$k"F$k2E`$kBD%))/+T`-ڎ.#s3L(;7x>3@EK_E^OsQ00%QMc)RN?U\X$(^z^V_pC_z`ri\ @<lpIqW/r |R<tW$t}zo^|U@txzC"NzU<N ']k]D(u I>IZZɣ%g#|vDS9`h];]YDDLL |WYG?@9m֣h֣-j\Dh(Umޛgnef0cE-9lDEyw ?'p  Y9"S|4&|8'S2(n-3e. 6-.o51,Y;!i/v>Dm( p \G 0ELG/aݎI-o?>LߺI>>R{^.;{p1A#03gvp(U` (Ol%` _&K_)wr,ιG-B2+Aw.CA?EE:`~F?͹H4kHthH~0I'_NO;P1W;YQY´^b]AfC fC"f|FZfyg\i' 8ivy&wJ$=yz.#O|Ԃ^z|^|^|IA4W|"Qk.~,A1M*e_,XNJxR[> VS<S<~{%[I$nrO+*y{GC"3Mn+ʗ/5Кdл%CS &"E~:w H';ePT5 O \~ + ES |UG .h wa ^  { !yu $)~+l .5~& 0I 0!Sc 5GF 6T5 ;=" BU> ExX GȧC Mg Q Sel \uh aB* cϥ d`V lO| l t7s ui u |@p5 ~ . ~S NX7 Q+ r ^WV 8S ;._ D  +k B1 N! .- :W  2 sP Ŧ#G H 1 8ڋ , 3 ;F ՛ {u 7d 7 ~ %j v  i R =  # R ^@" J9;  < `9x 7o i70. 2yh h !q !qf #$ )r 5s 5s ?"E CD D);i M |~ N=$ P U_) [>  ^5 a4i` c3 c3{ dl d8h eKg, eRh e e fjf g7r k2 k2 qw suJ tqh v3 N ȐK yn :) ~0 B #: ,~ ^ q +4x  "n 9q 9# NJ Ɍ4l v vm ώ.MA Ϯ vC Ҍ 0T~ 0 ˺OM Kk  ! ;'9 ck 5a R U n TI' UL VN ~ ~h F g%  !_g #e; %4{ (@~ ) sr )' )4 * *ݸ -#q -mnc; 8)r= ? 8 H6 K2gE K2gM N>(| Vg^ Ys/ bRW gV gy` i$eo l?r pfu qt ).A 7/ 1>  Rv z!@  f 4 @&c L p -n ,.& a5 [y ^ qP %nJ N AR; }[ pIE Z%@ +4 z %@ 1 ; KG f  tr 4 >t 4  w3 L_ I  e3$ t .u ` I  R4 # %^ %^ ,\ -) /~ 9st ;z ;> =e" AiT F^2B L.* M&` O~ Wj` XM"Otd ?څm A7 A DA" DD G0 LRh R/D Tp. X4 Zg [  . _k[ ct] c}/ fR fk1 i kco m[aI qU9: u; v8 vy vCbI }9 # }% )u 6 15څ ue B  ~X z 'r  ~Ak &t @C RL < ՞e ^ cY& N$ i3 W  eJw _o ^  Z(  E6 7=M ; F1PO-3ȁ7{ rcA(Ҳ/vX9Z;TKVX a.Va.e~K)fT fT#v8%w=))y!~Pi$`o#y!n.~nQ>Lf$3)y`SFR6xnQxãC:ciu6ŅtŅޝA qtIS5!4t[~ puC1Cn]n,^$Y'!+> sC~ i }iyR3 Y,~u~La"TN$/`iø1* =3 =VC.=_;@O(1&TW|]tm?^av!fgf"}hwii0p4sV'vgUw|>my6z Az L|`l}$7T@"*2  >=fFid^\z9aNjc6jcs?4"D;#X T uqvH\WE2-i6www.fritzing.orgAboutBoxF<b>2007-%1 Potsdam Yksek Okulu</b>%2007-%1 Fachhochschule PotsdamAboutBox<b>Kod iin GNU GPL v3 ve geri kalanlar iin CreativeCommons:BY-SA?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBox0







    AboutBox4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBox*Weimar niversitesi, )Department of Bauhaus-University Weimar, AboutBox3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBox(ayr1ca te_ekkrler. Fritzing a test spin. AboutBox2Fritzing'i olu_turanlar: Fritzing is made by: AboutBox|Fritzing a_a1daki finansmanlar sayesinde hayat bulabilmi_tir 0Fritzing is made possible with funding from the AboutBox*Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBoxlIxDS, bir anonim ba1_1, Parallax, Picaxe, Sparkfun, 6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBox%Jan Sieber, Yaniv Steiner, Olaf Val, AboutBox-Jonathan Cohen, Marcus Paeschke, Omer Yosha, AboutBox6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBoxrMWFK Brandenburg, Bauhaus Tasar1m Departman1 sponsorluu 0MWFK Brandenburg, the sponsorship of the Design AboutBox%Mariano Crowe, Johannes Landstorfer, AboutBox!Michaela Vieser and Julia Werner.AboutBox@Prof. Reto Wettach, André Knörig, Myriel Milicevic, AboutBoxtFritznig'e test turu atma imkan1 salayan tm rencilere 4Special thanks goes out as well to all the students AboutBoxSpecial thanks goes out to: AboutBoxKurt Badelt ve Miguel Solis'e 0spanyolca tercme katk1lar1 iin, DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBox,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBox2Travis Robertson, Stefan Hermann, Brendan Howell, AboutBox$Zach Eveland, Dirk van Oosterbosch, AboutBox6ve cesur alfa testilerine 0and alpha testers who were brave enough to give AboutBox&#313;ubom&iacute;r Ducho&#328;'e Slovaka tercme katk1lar1 iin, ?to Ĺubomír Duchoň for the Slovak translation, AboutBoxhAlexander Kaltsas'a Yunanca tercme katk1lar1 iin, 0to Alexander Kaltsas for the Greek translation, AboutBoxjGianluca Urgese'ye 0talyanca tercme katk1lar1 iin, 0to Gianluca Urgese for the Italian translation, AboutBoxdHiroshi Suzuki'ye Japonca tercme katk1lar1 iin, 0to Hiroshi Suzuki for the Japanese translation, AboutBoxZJinbuhm Kim'e Korece tercme katk1lar1 iin, +to Jinbuhm Kim for the Korean translation, AboutBox^Josef Dustira'ya ekce tercme katk1lar1 iin, ,to Josef Dustira for the Czech translation, AboutBoxNuno Pessanha Santos'a Portekizce(Avrupa) tercme katk1lar1 iin, Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBoxpRobert Lee'ye ince(Geleneksel) tercme katk1lar1 iin, 9to Robert Lee for the Chinese (Traditional) translation, AboutBoxSteven Noppe ve Davy Uittenbogerd'e Flemenke.tercme katk1lar1 iin, Ato Steven Noppe and Davy Uittenbogerd for the Dutch translation, AboutBoxbVladimir Savinov'a Rusca tercme katk1lar1 iin, 1to Vladimir Savinov for the Russian translation, AboutBoxdYuelin ve Ninjia'ya ince tercme katk1lar1 iin, @to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBox8^u ana kadarkilerin en iyisi Best So FarAutorouteProgressDialog 0ptalCancelAutorouteProgressDialog^imdi DurdurStop NowAutorouteProgressDialogDyak1nla_t1rma ve ayarl1 kontrollerzoom and pan controlsAutorouteProgressDialog^Ynlendirme iptal edildi! ^imdi temizleniyor...$Routing canceled! Now cleaning up... Autorouter<b>Aral1k</b> farkl1 alar zerindeki bak1r elemanlar aras1ndaki en k1sa mesafedir.QKeepout is the minimum distance between copper elements on different nets.AutorouterSettingsDialogp0.01 inlik(0.254mm) bir uzak tutma ihmal edilebilirdir.4A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialog 0ptalCancelAutorouterSettingsDialog Aral1kKeepoutAutorouterSettingsDialogNot: Ne kadar kk aral1k b1rak1l1rsa DRC ve Oto-Ynlendirici o kadar yava_ al1_1r.JNote: the smaller the keepout, the slower the DRC and Autorouter will run.AutorouterSettingsDialog TamamOKAutorouterSettingsDialogretim _ekliProduction typeAutorouterSettingsDialogHat geni_lii Trace widthAutorouterSettingsDialog zgncustomAutorouterSettingsDialogev yap1m1homebrewAutorouterSettingsDialogprofesyonel professionalAutorouterSettingsDialogBinYneticisi::KirliSekmeayarla: bin '%1''i kirli sekme olarak ayarlanamad1;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagerBinYneticisi::Ba_l11Gncelle: bin '%1''i kirli sekme olarak ayarlanamad1;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerPBo_ bir bin geerli olarak ayarlanam1yor(Cannot set a NULL bin as the current one BinManager&Bin dosyas1n1 kapat Close Bin BinManager6Eleman1n bin doyas1n1 kapatClose parts bin BinManagerFYeni bir eleman bin dosyas1 olu_turCreate a new parts bin BinManager"Bin dosyas1n1 sil Delete Bin BinManager"Bin dosyas1n1 sil Delete bin BinManager4Eleman1n bin dosyas1n1 silDelete parts bin BinManagerBElemanlar1 liste biiminde gsterDisplay parts as a list BinManagerNElemanlar1 kk simgeler olarak gsterDisplay parts as icons BinManagerBin '%1''i silmek istediinize emin misiniz? Bu geri dn_sz bir karard1r.EDo you really want to delete bin '%1'? This action cannot be undone. BinManager'%1%''i bin'den kald1rmak istediinize emin misiniz? Bu geri dn_sz bir karard1r.PDo you really want to remove '%1' from the bin? This operation cannot be undone. BinManager\Eleman1 dzenle (yeni eleman dzenleyicisi)...Edit Part (new parts editor)... BinManager6Bin dosyas1n1 d1_a aktar... Export Bin... BinManager*Elaman1 D1_a Aktar...Export Part... BinManager&Eleman1 izimde bulFind Part in Sketch BinManagerFritzing Bin Dosyalar1 (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Payla_1labilir Bin (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagerFritzing Dosyalar1 (*%1 *%2 *%3);;Fritzing Eleman (*%1);;Fritzing Bin (*%2);;Fritzing Payla_1labilir Bin (*%3)cFritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) BinManager0eri Aktar... Import... BinManagerBir Fritzing Eleman1 (.fzpz) ya da bir Fritzing Eleman1 bin dosyas1 (.fzb, .fznz) ykleCLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManager&Yeni Bin dosyas1... New Bin... BinManagerYeni bin (%1) New bin (%1) BinManagerElemanlarParts BinManager>Ltfen bin iin bir ad seiniz:!Please choose a name for the bin: BinManagerSalt okunur bin Read-only bin BinManagerEleman1 kald1r Remove Part BinManager,Bin dosyas1ndan kald1rRemove from Bin BinManagerbin'den kald1rRemove from bin BinManagerBBin dosyas1n1 yeniden adland1r... Rename Bin... BinManager,Bin'i yeniden adland1r Rename bin BinManagerTEleman1n bin dosyas1n1 yeniden adland1r...Rename parts bin... BinManager(Bin dosyas1n1 kaydetSave Bin BinManager<Bin dosyas1n1 Farkl1 Kaydet...Save Bin As... BinManager:Eleman1n bin dosyas1n1 kaydetSave parts bin BinManagerNEleman1n bin dosyas1n1 Farkl1 Kaydet...Save parts bin as... BinManagerjEleman1n bin dosyas1n1 s1k1_1t1rlm1_ olarak kaydet...&Save parts bin in compressed format... BinManagerAr1yor... Searching... BinManagerFAmak iin bir Fritzing Dosyas1 seSelect a Fritzing File to Open BinManagerdAmak iin bir Fritzing Elemanlar1 Bin dosyas1 se(Select a Fritzing Parts Bin file to open BinManagerNBin dosyas1n1 Kk Simge olarak GsterShow Bin in Icon View BinManagerNBin dosyas1n1 liste biiminde grntleShow Bin in List View BinManager<Bu bin yeniden adland1r1lamaz.This bin cannot be renamed. BinManagerzEleman '%1' kald1r1lam1yor--_u anda bir izimde kullan1lmakta4Unable to remove part '%1'--it is in use in a sketch BinManager(Ykelenebilir, ancak Can load, butBoardFritzing ykleme klasr parts/svg/core/pcb alt1ndaki circle_pcb.svg dosyas1na bak1n. eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. BoardResimlerImagesBoardDYklemek iin bir resim doyas1 seSelect an image file to loadBoardpResim %1'den yklenebilir, ancak%2 Dosya kullan1ls1n m1?5The image from %1 can be loaded, but %2 Use the file?BoardYklenemiyorUnable to loadBoard:Resim %1 %2'den ykelenemiyorUnable to load image from %1 %2Board^xml doru olarak biimlendirilmediinden dolay1*because the xml is not correctly formattedBoard\birden fazla <board> katman1 olduundan dolay1)because there are multiple layersBoarddbirden fazla <serigrafi> katman1 olduundan dolay1.because there are multiple layersBoardF<board> katman1 olmad11ndan dolay1!because there is no layerBoardVancak bask1 devre'nin serigrafisi olmayacak0but the pcb itself will have no silkscreen layerBoard\bir xml hatas1ndan dolay1:%1 sat1r:%2 stun:%3+due to an xml problem: %1 line:%2 column:%3Boardresim dosyas1 image fileBoard&resim dosyas1 ykleload image fileBoard0bir katman (tek-tarafl1)one layer (single-sided)Board><board> tasar1m esi iermiyor.the element contains no shape elementsBoard8svg tasar1m resi iermiyor"the svg contains no shape elementsBoard@svg zgn board biimine uymuyor+the svg doesn't fit the custom board formatBoard2iki katman (ift-tarafl1)two layers (double-sided)BoardTasar1mshape BoardLogoItem2Yaz1 karakter rengini seSelect text colorBreadboardLogoItem8Yaz1 karakter rengini ayarlaSet text colorBreadboardLogoItemRenkcolorBreadboardLogoItemPT1kla ve d_rden se ya da bir %1'e yaz/Select from the dropdown, or type in a %1 value Capacitor(Esnetme noktas1 ekle Add bendpoint ConnectorItem0Esnetme noktas1n1 kald1rRemove bendpoint ConnectorItemEriyi dzeltStraighten curve ConnectorItem&Hakk1nda&About ConsoleWindow&1k&Quit ConsoleWindowAralarTools ConsoleWindowF%1 (%2 katman1yla) stste gelmekte%1 is overlapping (%2 layer)DRC%1'deki bir delik board s1n1r1n1n d1_1na 1kabilir ve k1rp1labilir.JA hole in %1 may lie outside the border of the board and would be clipped.DRCRDRC(Tasar1m Kural Kontrol) iptal edildi.DRC was cancelled.DRCPFritzing hata: board svg modellenemiyor.+Fritzing error: unable to render board svg.DRCnKontrol etmek iin herhangi bir hat ya da konnektr yok No traces or connectors to checkDRCOnlar1 tekrar konumland1r1n ve DRC'i ba_ka problemler bulabilmesi iin tekrar al1_t1r1n;Reposition them and run the DRC again to find more problemsDRCBoardunuz zerindeki k1rm1z1yla vurgulanm1_ alanlar stste gelme olas1l11 olan ve birbirine ok yak1n konnektr ve hatlar1 gstermektedir. qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRC6S1n1ra ok yak1n (%1 layer) Too close to a border (%1 layer)DRCBeklenmedik SVG modelleme hatas1--fritzing.org ile ileti_ime gein6Unexpected SVG rendering failure--contact fritzing.orgDRCizminiz retim iin haz1r stste gelen herhangi bir hat ya da konnektr stste gelmemi_ ve aralar1ndaki mesafe uygun.nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRCBir nesnenin iligli olduu stste gelmeyi grmek iin listedeki nesnenin zerine t1klay1n.BClick on an item in the list to highlight of overlap it refers to.DRCResultsDialogHDRC(Tasar1m Kural Kontrol) Sonular1 DRC ResultsDRCResultsDialogNot:liste nesneleri ve k1rm1z1 vurgular iziminizi tekrar dzenlediinizde gncellenmez--gncelleme iin DRC(Tasar1m Kural Kontrol) tekrar al1_t1r1lmal1d1r. Vurgulama bu diyalou kapatt11n1z zaman kaybolacakt1r.Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialog&hata ay1klamak iin for debugging DebugDialog$Ayr1ca dosyay1 silAlso delete the file DeleteDialogKald1rma Don't remove DeleteDialog Kald1rRemove DeleteDialogip etiketi chip labelDip Not:Onlar1 daha sonra mendeki "Yard1m" > "Eski srmdeki elemanlar1 ve bin dosyalar1n1 ie aktar..."'1 kullanarak aktarabilirsiniz.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication"^imdi ie aktarmaDo not import now FApplicationFritizing'in daha nceki srmlerinde olu_turduunuz elemanlar1 ve bin dosyalar1n1 ier aktarmak ister misiniz?^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationFritzing(*%1)Fritzing (*%1) FApplicationZFritzing %3'de %2'den %1 bir istisna yakalad13Fritzing caught an exception %1 from %2 in event %3 FApplicationTFritzing %2'de %1'den bir istisna yakalad10Fritzing caught an exception from %1 in event %2 FApplicationFritzing hatas1Fritzing failure FApplication0e aktarImport FApplicationPDosyalar1 bir nceki srmden ie aktar?#Import files from previous version? FApplicationLtfen kaydetmek iin bir .fzz dosyas1 belirtin (iptal etmek yedeklen veriyi silecektir)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplication"Ba_lang1 Yard1m1First Time HelpFirstTimeHelpDialog &Pencereyi Kapat &Close WindowFritzingWindow0ptal EtCancelFritzingWindow,A1k olan izimi kapatClose the current sketchFritzingWindow|%1 dosyas1nda yapt11n1z dei_ikleri kaydetmek ister misiniz ?>Do you want to save the changes you made in the document "%1"?FritzingWindowKaydetme Don't SaveFritzingWindow KaydetSaveFritzingWindowKaydet "%1" Save "%1"FritzingWindowKaydet...Save...FritzingWindow,Bir dosya ad1 belirtinSpecify a file nameFritzingWindowpEer dei_ikliklerinizi kaydetmezseniz kaybolacaklard1r.1Your changes will be lost if you don't save them.FritzingWindow0ptal etCancelGroundFillSeedDialog TamamOKGroundFillSeedDialog&Tamam bak1r dolgusuOK and copper fillGroundFillSeedDialog(Tamam toprak dolgusuOK and ground fillGroundFillSeedDialog'Toprak dolgusu' ve 'bak1r dolgusu' aras1ndaki fark dolgulanm1_ alan1n 'toprak' konnektrlerine bal1 hat ve konnektrler'i iinde bulundurmas1d1r. Toprak konnektrleri genellikle 'GND' olarak adland1r1l1r ancak bazen bu durum geerli deildir.Ayr1ca bazen toprak konnektrleri birden fazla aa bal1 olabilir ve bu alardan yaln1z bir tanesinin dolgulanmas1n1 isteyebilirsiniz. Bu dialog sadece hali haz1rda tanecik olarak seilmi_ bir konnektr iin ve 'GND'ya da 'ground' olarak etiketlenmi_ konnektrleri toparlar. izimdeki bir nesnenin balant1lar1n1 vurgulamak iin zerine t1klay1n1z. Ayr1ca konnektr zerine sa t1klanarak 'Ayarla Toprak Dolgu Tanecik' men seeneinden tek bir toprak dolgu tanecii olarak seilebilir.The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialogdelik boyutu hole sizeHole.(Oto-Ynlendirilebilir)(autoroutable) HtmlInfoView<Eleman1n "yap1_kanl1k" durumunu bu grnm iin dei_tir. Ya1_kan bir eleman1n yeri dei_tirildiinde onun zerine bal1 dier nesnelerin de yerleri dei_ir.pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoViewEleman1n bu grnmdeki kilit durumunu dei_tirin. Kilitli bir eleman1n yeri dei_tirilemez.OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoView@Eleman etiketini burdan dei_tirChange the part label here HtmlInfoViewBalant1lar Connections HtmlInfoViewKilitliLocked HtmlInfoViewBEleman1n breadboard grnm resmiPart breadboard view image HtmlInfoViewDEleman1n Bask1 Devre grnm resmiPart pcb view image HtmlInfoView<Eleman1n _ematik grnm resmiPart schematic view image HtmlInfoView0Eleman versiyon numaras1Part version number HtmlInfoViewzellikler Properties HtmlInfoViewKablo Yuma1 Ratsnest wire HtmlInfoViewYap1_kanSticky HtmlInfoViewEtiketlerTags HtmlInfoViewHat kablosu %1 Trace wire %1 HtmlInfoView KabloWire HtmlInfoView konn.conn. HtmlInfoView2%n adet nesne(ler)e bal1connected to %n item(s) HtmlInfoViewAdname HtmlInfoViewkullan1lmayanobsolete HtmlInfoViewTiptype HtmlInfoViewv.%1 %2v. %1 %2 HtmlInfoView ElemanPartItemBasealtbottomItemBaseKapasite Deeri capacitanceItemBaserenkcolorItemBaseak1mcurrentItemBase tarihdateItemBaseA1klamadescrItemBaseailefamilyItemBase@%1 %2 iin olan dosya bulunamad1file for %1 %2 not foundItemBasedosya ad1filenameItemBase biimformItemBasefrekans frequencyItemBase0ndktans inductanceItemBasekatmanlarlayersItemBasemaksimum direnmaximum resistanceItemBase*model eleman problemimodel part problemItemBase paketpackageItemBasepara numaras1 part numberItemBase$pin aral1kland1rma pin spacingItemBase pinlerpinsItemBasegpowerItemBasei_lemci processorItemBase projeprojectItemBasenominal ak1m rated currentItemBasenominal g rated powerItemBasenominal gerilim rated voltageItemBase diren resistanceItemBaserevizyonrevItemBase _ekilshapeItemBase sayfasheetItemBase boyutsizeItemBasebo_luk b1rakmaspacingItemBase ba_l1ktitleItemBasetolerans toleranceItemBasesttopItemBasetiptypeItemBaseNsvg %1 iin modelleyici olu_turulam1yor$unable to create renderer for svg %1ItemBase trevvariantItemBase srmversionItemBasegerilimvoltageItemBase 0ptalCancelKicadModuleDialog TamamOKKicadModuleDialog*tm katmanlar1 gstershow all layers LayerPalette 0ptalCancel LinkDialog TamamOK LinkDialog"GrntlenemeiyorUnable to displayLogoItem<%1'deki resim grntlenemiyorUnable to display image from %1LogoItem<nk dosyan1n <svg> k1sm1 yok%because the file has no element���LogoItem���>���n�k�� �d�o�s�y�a�n1�n� �k�a�y�n�a�k� �k1�s�m1� �y�o�k�������$because the file has no root element���LogoItem���2�s�v�g� �b�o_� �o�l�d�u�u�n�d�a�n� �d�o�l�a�y1�������because the svg is empty���LogoItem����b�u� �i�l�g�i�l�i� �S�V�G� �d�o�s�y�a�s1�n1�n� �C�o�r�e�l�D�R�A�W�'�d�a�n� �d1_�a� �a�k�t�a�r1�l1�r�k�e�n� �h�e�r�h�a�n�g�i� �b�i�r� �'�s�u�n�u�m� ��z�e�l�l�i�i�'�a�y�a�r1� �y�a�p1�l�m�a�d11�n�d�a�n� �d�o�l�a�y1� �g��r��l�m�e�k�t�e�d�i�r�������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem���D�b�i�r� �m�o�d�e�l� �i_�l�e�m�e� �h�a�t�a�s1�n�d�a�n� �d�o�l�a�y1�������due to a rendering error���LogoItem���b�b�i�r� �x�m�l� �p�r�o�b�l�e�m�i�n�d�e�n� �d�o�l�a�y1�:�%�1� �s�a�t1�r� �:�%�2� �s��t�u�n�:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem����b�i�l�i�n�m�e�y�e�n� �n�e�d�e�n�l�e�r� �i��i�n�-�-�b��y��k� �o�l�a�s1�l1�k�l�a� �r�e�s�i�m�(�i�m�g�)� �d�o�s�y�a�s1� �b�o�z�u�k�������9for unknown reasons--possibly the image file is corrupted���LogoItem��� ^�e�k�i�l�������shape���LogoItem����%�1� �b�a�l�a�n�t1�d�a�n� �%�2�'�s�i� �y��n�l�e�n�d�i�r�i�l�d�i� �%�n� �k�o�n�n�e�k�t��r� �h�a�l�e�n� �y��n�l�e�n�d�i�r�i�l�m�e�y�i� �b�e�k�l�i�y�o�r�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow����&�H�a�k�k1�n�d�a�������&About��� MainWindow����&�Q�t� �H�a�k�k1�n�d�a������� &About Qt��� MainWindow����&�G�e�r��e�k� �B�o�y�u�t������� &Actual Size��� MainWindow���(�&�B�i�n� �k1�s�m1�n�a� �e�k�l�e�.�.�.�������&Add to bin...��� MainWindow����&�K�o�p�y�a�l�a�������&Copy��� MainWindow���*�&�Y�u�m�a�k�t�a�n� �h�a�t� �o�l�u_�t�u�r�������&Create trace from ratsnest��� MainWindow���.�&�Y�u�m�a�k�t�a�n� �k�a�b�l�o� �o�l�u_�t�u�r�������&Create wire from ratsnest��� MainWindow����&�K�e�s�������&Cut��� MainWindow����&�S�i�l�������&Delete��� MainWindow����&�K�a�b�l�o�y�u� �S�i�l������� &Delete Wire��� MainWindow���*�&�S�e��i�m�i� �s�e�r�b�e�s�t� �b1�r�a�k������� &Deselect��� MainWindow����&0�k�i�z� �O�l�u_�t�u�r������� &Duplicate��� MainWindow���"�&�D��z�e�n�l�e�/�D�e�i_�t�i�r�������&Edit��� MainWindow����&�D1_�a� �A�k�t�a�r�������&Export��� MainWindow����&�D1_�a� �a�k�t�a�r�.�.�.������� &Export...��� MainWindow��� �&�D�o�s�y�a�������&File��� MainWindow���"�&�P�e�n�c�e�r�e�y�e� �S1�d1�r�������&Fit in Window��� MainWindow����&�Y�a�t�a�y� ��e�v�i�r�������&Flip Horizontal��� MainWindow���(�&�D�i�k�e�y� �o�l�a�r�a�k� �k�a�y�d1�r�������&Flip Vertical��� MainWindow����&�Y�a�r�d1�m�������&Help��� MainWindow���*�&�T��m� �k�a�t�m�a�n�l�a�r1� �g�i�z�l�e�������&Hide All Layers��� MainWindow���Z�&�E�s�k�i� �s��r��m�d�e�n� �e�l�e�m�a�n� �v�e� �b�i�n�l�e�r�i� �i��e� �a�k�t�a�r�.�.�.�������*&Import parts and bins from old version...��� MainWindow����&�K����l�t������� &Minimize��� MainWindow����&�B�i�r� ��r�n�e�k� �A�������� &Open Example��� MainWindow���(�&�M�e�v�c�u�t� �D�o�s�y�a�l�a�r1� �A��������&Open Recent Files��� MainWindow��� �&�A��.�.�.�������&Open...��� MainWindow����&�E�l�e�m�a�n�������&Part��� MainWindow����&�Y�a�p1_�t1�r�������&Paste��� MainWindow����&�T�e�r�c�i�h�l�e�r�.�.�.�������&Preferences...��� MainWindow����&�Y�a�z�d1�r�.�.�.������� &Print...��� MainWindow����&�1�k�������&Quit��� MainWindow����&�Y��n�l�e�n�d�i�r�m�e�������&Routing��� MainWindow����&�K�a�y�d�e�t�������&Save��� MainWindow���"�&�F�a�r�k�l1� �K�a�y�d�e�t�.�.�.������� &Save As...��� MainWindow����&�T��m��n�� �S�e�������� &Select All��� MainWindow���,�&�T��m� �k�a�t�m�a�n�l�a�r1� �g��s�t�e�r�������&Show All Layers��� MainWindow���(�&�B�r�e�a�d�b�o�a�r�d�'�u� �G��s�t�e�r�������&Show Breadboard��� MainWindow���*�&�B�a�s�k1� �D�e�v�r�e�y�i� �G��s�t�e�r������� &Show PCB��� MainWindow��� �&^�e�m�a�t�i�i� �G��s�t�e�r�������&Show Schematic��� MainWindow���4�&�E�l�e�m�a�n1�n� �e�t�i�k�e�t�i�n�i� �g��s�t�e�r�������&Show part label��� MainWindow����&�G��s�t�e�r�������&View��� MainWindow����&�P�e�n�c�e�r�e�������&Window��� MainWindow����&�K�a�b�l�o� �R�e�n�g�i������� &Wire Color��� MainWindow����&�Y�a�k1�n�l�a_�t1�r�������&Zoom In��� MainWindow����&�U�z�a�k�l�a_�t1�r������� &Zoom Out��� MainWindow���&�1�0�0�%�(�p�i�k�s�e�l�)� �b�o�y�u�t�u�������100% (pixel) size��� MainWindow����1�0�0�%� �B�o�y�u�t������� 100% Size��� MainWindow���.�G�e�r��e�k� �(�f�i�z�i�k�s�e�l�)� �b�o�y�u�t�������!Actual (real world physical) size��� MainWindow����G�e�r��e�k� �B�o�y�u�t������� Actual Size��� MainWindow���(�E�s�n�e�t�m�e� �n�o�k�t�a�s1� �e�k�l�e������� Add Bendpoint��� MainWindow����N�o�t� �E�k�l�e�������Add Note��� MainWindow���F�S�e��i�l�i� �k�a�b�l�o�y�a� �e�s�n�e�t�m�e� �n�o�k�t�a�s1� �e�k�l�e�������$Add a bendpoint to the selected wire��� MainWindow����N�o�t� �e�k�l�e������� Add a note��� MainWindow���B�S�e��i�l�m�i_� �e�l�e�m�a�n1� �b�i�n� �k1�s�m1�n�a� �e�k�l�e�������Add selected part to bin��� MainWindow���P�N�e�s�n�e�r�i� �s��r��k�l�e�r�k�e�n� 1�z�g�a�r�a�y�a� �g��r�e� �h�i�z�a�l�a�������!Align items to grid when dragging��� MainWindow���(�I�z�g�a�r�a�y�a� �g��r�e� �H�i�z�a�l�a������� Align to Grid��� MainWindow��� �H�e�p�s�i�������All��� MainWindow���B�H�e�n��z� �t��m� �h�a�t�l�a�r� �y��n�l�e�n�d�i�r�i�l�m�e�d�i�.�������$All traces have not yet been routed.��� MainWindow����O�t�o�-�Y��n�l�e�n�d�i�r������� Autoroute��� MainWindow���:�B�a�l�a�n�t1�l�a�r1� �O�t�o�-�Y��n�l�e�n�d�i�r�.�.�.�������Autoroute connections...��� MainWindow���v�O�t�o�-�Y��n�l�e�n�d�i�r�m�e�/�D�R�C�(�T�a�s�a�r1�m� �K�u�r�a�l�l�a�r1� �k�o�n�t�r�o�l��)� �a�y�a�r�l�a�r1�.�.�.�������Autorouter/DRC settings...��� MainWindow���8�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� 0�l�e�r�l�i�y�o�r�.�.�.�������Autorouting Progress...��� MainWindow���,�O�t�o�-�Y��n�l�e�n�d�i�r�i�l�i�y�o�r�.�.�.�������Autorouting...��� MainWindow���"�'�%�1�'� �y�e�d�e�k�l�e�n�i�y�o�r�������Backing up '%1'��� MainWindow���2�B�o�M� �T�e�x�t� �D�o�s�y�a�s1� �(�*�.�h�t�m�l�)�������BoM Text File (*.html)��� MainWindow����H�e�r� 0�k�i� �K�a�t�m�a�n������� Both Layers��� MainWindow����A�l�t� �K�a�t�m�a�n������� Bottom Layer��� MainWindow���0�l�e�r�l�e�t������� Bring Forward��� MainWindow���\�S�e��i�l�i� �n�e�s�n�e�(�l�e�r�)�i� �k�e�n�d�i� �k�a�t�m�a�n�l�a�r1�n�d�a� �i�l�e�r�l�e�t�������/Bring selected object(s) forward in their layer��� MainWindow���X�S�e��i�l�i� �n�e�s�n�e�(�l�e�r�)�i� �k�a�t�m�a�n�l�a�r1�n1�n� ��n��n�e� �1�k�a�r�������0Bring selected object(s) to front of their layer��� MainWindow�����n�e� �1�k�a�r�������Bring to Front��� MainWindow��� 0�p�t�a�l�������Cancel��� MainWindow���,�%�1� �d�o�s�y�a�s1� �b�u�l�u�n�a�m�a�d1�.�������Cannot find file %1.��� MainWindow���$�%�1� �y�a�z1�d1�r1�l�a�m1�y�o�r�������Cannot print to %1��� MainWindow���4�D�o�s�y�a� �o�k�u�n�a�m�a�d1� � �1� �%�1�:� �%�2�.�������Cannot read file 1 %1: %2.��� MainWindow���&�%�1� �y�a�z1�l�a�m1�y�o�r�:� �%�2�.�������Cannot write file %1: %2.��� MainWindow���"�R�e�s�m�i� �%�2�'�y�e� ��e�v�i�r�������Change image to %2��� MainWindow���D�T�e�k� �k�a�t�m�a�n�l11� �b�a�s�k1� �d�e�v�r�e�'�y�e� ��e�v�i�r�������Change to single layer pcb��� MainWindow���B��i�f�t� �k�a�t�m�a�n�l1� �b�a�s�k1� �d�e�v�r�e�y�e� ��e�v�i�r�������Change to two layer pcb��� MainWindow���8�Y��k�l�e�n�m�i_� �H�a�t�l�a�r1� �K�o�n�t�r�o�l� �E�t�������Check Loaded Traces��� MainWindow���4�G��n�c�e�l�l�e�m�e�l�e�r�i� �T�a�k�i�p� �E�t�.�.�.�������Check for updates...��� MainWindow����F�r�i�t�z�i�n�g�'�i�n� �y�e�n�i� �b�i�r� �s��r��m��n��n� �i�n�d�i�r�m�e�k� �i��i�n� �u�y�g�u�n� �o�l�u�p� �o�l�m�a�d11�n1� �k�o�n�t�r�o�l� �e�t�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���<�T�o�p�r�a�k� �D�o�l�g�u� �T�a�n�e�l�e�r�i�n�i� �S�e��.�.�.�������Choose Ground Fill Seed(s)...��� MainWindow���D�D1_�a� �a�k�t�a�r�m�a�k� �i��i�n� �b�i�r� �d�o�s�y�a� �s�e��i�n�������Choose a folder for exporting��� MainWindow���>�T�o�p�r�a�k� �D�o�l�g�u� �T�a�n�e�l�e�r�i�n�i� �T�e�m�i�z�l�e�������Clear Ground Fill Seeds��� MainWindow����T�o�p�r�a�k� �d�o�l�g�u� �t�a�n�e�l�e�r�i�n�i� �t�e�m�i�z�l�e�-�-�s�a�d�e�c�e� �b�a�k1�r� �d�o�l�g�u�y�u� �e�t�k�i�n�l�e_�t�i�r�.�������1Clear ground fill seeds--enable copper fill only.��� MainWindow����K�o�d�������Code��� MainWindow����D��n�_�t��r�������Convert��� MainWindow���<�E�s�n�e�t�m�e� �n�o�k�t�a�s1�n1� �G�e��i�t�e� ��e�v�i�r�������Convert Bendpoint to Via��� MainWindow���L�"�G�e��i�t�l�"�'�i� �b�i�r� �E�s�n�e�t�m�e� �N�o�k�t�a�s1�n�a� ��e�v�i�r�������Convert Via to Bendpoint��� MainWindow���B�B�u� �e�s�n�e�t�m�e� �n�o�k�t�a�s1�n1� �g�e��i�t�e� ��e�v�i�r�������Convert the bendpoint to a via��� MainWindow���D�G�e��i�t�i� �b�i�r� �e�s�n�e�t�m�e� �n�o�k�t�a�s1�n�a� ��e�v�i�r�������Convert the via to a bendpoint��� MainWindow���,�B�a�k1�r� �A�l�t� �k�a�t�m�a�n� �a�k�t�i�f�������Copper Bottom layer is active��� MainWindow����B�a�k1�r� �D�o�l�g�u������� Copper Fill��� MainWindow���n�B�a�k1�r� ��s�t� �v�e� �B�a�k1�r� �A�l�t� �k�a�t�m�a�n�l�a�r1�n1�n� �h�e�r� �i�k�i�s�i� �d�e� �a�k�t�i�f�������3Copper Top and Copper Bottom layers are both active��� MainWindow���,�B�a�k1�r� ��s�t� �k�a�t�m�a�n� �a�k�t�i�f�������Copper Top layer is active��� MainWindow����S�e��i�m�i� �k�o�p�y�a�l�a�������Copy selection��� MainWindow���8�R1�h�t1�m� �W�i�d�g�e�t�'�l�a�r1� �a�l1�n�a�m�a�d1�������Couldn't get the dock widget��� MainWindow���,�Y�e�n�i� �b�i�r� ��i�z�i�m� �o�l�u_�t�u�r�������Create a new sketch��� MainWindow���>��i�z�g�i� �y�u�m�a�k�l�a�r1�n�d�a�n� �h�a�t� �o�l�u_�t�u�r�������%Create a trace from the ratsnest line��� MainWindow���<��i�z�g�i� �y�u�m�a1�n�d�a�n� �k�a�b�l�o� �o�l�u_�t�u�r�������$Create a wire from the ratsnest line��� MainWindow����S�e��i�m�i� �k�e�s������� Cut selection��� MainWindow���P�T�a�s�a�r1�m� �K�u�r�a�l� �K�o�n�t�r�o�l��(�D�R�C�)� 0�l�e�r�l�i�y�o�r�.�.�.�������DRC Progress...��� MainWindow���@�A�y1�k�l�a�y1�c1� �1�k1_1� �(�D�e�b�u�g�g�e�r� �O�u�t�)�������Debugger Output��� MainWindow����S�i�l�������Delete��� MainWindow���*�Y�u�m�a�k�l�a�n�m1_� �H�a�t�t1� �S�i�l�������Delete Ratsnest Line��� MainWindow����K�a�b�l�o�y�u� �S�i�l������� Delete Wire��� MainWindow����S�e��i�m�i� �s�i�l�������Delete selection��� MainWindow���(�S�e��i�m�i� �s�e�r�b�e�s�t� �b1�r�a�k�������Deselect��� MainWindow���@�T�a�s�a�r1�m� �K�u�r�a�l�l�a�r1� �K�o�n�t�r�o�l�� �(�D�R�C�)�������Design Rules Check (DRC)��� MainWindow���"�T��m� �k�a�b�l�o�l�a�r1� �s��k�������Disconnect All Wires��� MainWindow���J�B�u� �k�o�n�n�e�k�t��r�e� �b�a�l1� �t��m� �k�a�b�l�o�l�a�r1� �s��k�������0Disconnect all wires connected to this connector��� MainWindow���t�E�l�e�m�a�n� �D��z�e�n�l�e�y�i�c�i� �y�a�r�d1�m1�n1� �y�e�n�i� �b�i�r� �t�a�r�a�y1�c1�d�a� �g��r��n�t��l�e�������&Display Parts Editor help in a browser��� MainWindow���|�K�u�l�l�a�n1_�l1� �b�i�r�k�a�� �F�r�i�t�z�i�n�g� �t�a�v�s�i�y�e�s�i�n�i� �v�e� �n�u�m�a�r�a�s1�n1� �g��r��n�t�_�e�������+Display some handy Fritzing tips and tricks��� MainWindow���N�E�l�e�m�a�n�l�a�r1� �l�i�s�t�e�l�e�n�m�i_� �o�l�a�r�a�k� �g��r��n�t��l�e�������$Display the parts bin in a list view��� MainWindow���^�E�l�e�m�a�n�l�a�r� �k1�s�m1�n1� �k����k� �r�e�s�i�m� �h�a�l�i�n�d�e� �g��r��n�t��l�e�������%Display the parts bin in an icon view��� MainWindow���*�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �Y�a�p�m�a�������Do not autoroute��� MainWindow���f0��e� �a�k�t�a�r1�l�m1_� �e�l�e�m�a�n�l�a�r1� �s�a�k�l�a�m�a�k� �i�s�t�i�y�o�r� �m�u�s�u�n�u�z�?�������'Do you want to keep the imported parts?��� MainWindow���D�Y�i�n�e� �d�e� �d�e�v�a�m� �e�t�m�e�k� �i�s�t�e�r� �m�i�s�i�n�i�z�?�������Do you want to proceed anyway?��� MainWindow���(�F�r�i�t�z�i�n�g�'�e� �B�a1_� �Y�a�p�������Donate to Fritzing��� MainWindow���.�S�e��i�m�i�n� �i�k�i�z�i�n�i� �o�l�u_�t�u�r�������Duplicate selection��� MainWindow���B�D��z�e�n�l�e� �(�Y�e�n�i� �e�l�e�m�a�n� �d��z�e�n�l�e�y�i�c�i�)�������Edit (new parts editor)��� MainWindow���L�A�y1�k�l�a�m�a�(�D�e�b�u�g�g�i�n�g�)� �l�o�g�u�n�u� �e�t�k�i�n�l�e_�t�i�r�������Enable debugging log��� MainWindow����Y�a�z1� �y�a�z������� Enter Text��� MainWindow���R�A�s�i�t�l�e� �O�l�u�k�l�a�n�a�b�i�l�i�r� �B�a�s�k1� �D�e�v�r�e� �(�P�D�F�)�.�.�.�������Etchable (PDF)...��� MainWindow���R�A�s�i�t�l�e� �O�l�u�k�l�a�n�a�b�i�l�i�r� �B�a�s�k1� �D�e�v�r�e� �(�S�V�G�)�.�.�.�������Etchable (SVG)...��� MainWindow���A�s�i�t�l�i� �o�y�m�a� �i_�l�e�m�i� �i��i�n� �d1_�a� �a�k�t�a�r� �a�y�n1� �a�n�d�a� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d�'�u� �d1_�a� �a�k�t�a�r�a�b�i�l�i�r�-�-�L��t�f�e�n� �d1_�a� �a�k�t�a�r�m�a�k� �i�s�t�e�d�i�i�n�i�z� �b�o�a�r�d�'�u� �s�e��i�n�.�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow����B�u� �e�l�e�m�a�n1� �b�u� �g��r��n��m�d�e� �b�a�s1�k�l�a_�t1�r1�l�m1_� �1�0�0�0� �d�p�i� �S�V�G� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���l�B�u� �e�l�e�m�a�n1� �b�u� �g��r��n��m�d�e� �1�0�0�0� �d�p�i� �S�V�G� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�������-Export 1000 dpi SVG of this part in this view��� MainWindow���P�M�a�l�z�e�m�e� �M�a�l�i�y�e�t�l�e�r�i�n�i�(�B�o�M�)� �D1_�a� �A�k�t�a�r�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���.�N�e�t�l�i�s�t�'�i� �D1_�a� �A�k�t�a�r�.�.�.�������Export Netlist...��� MainWindow���`�N�o�r�m�a�l�i�z�e� �B�a�s1�k�l�a_�t1�r1�l�m1_� �S�V�G� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�������Export Normalized Flattened SVG��� MainWindow���B�N�o�r�m�a�l�i�z�e� �e�d�i�l�m�i_� �S�V�G�'�y�i� �g��n�c�e�l�l�e�������Export Normalized SVG��� MainWindow���D�S�P�I�C�E� �N�e�t�l�i�s�t� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�.�.�.�������Export SPICE Netlist...��� MainWindow���(�S�V�G�'�y�i� �D1_�a� �A�k�t�a�r�.�.�.������� Export SVG...��� MainWindow���6�B�a�s�k1� �D�e�v�r�e� �i��i�n� �d1_�a� �a�k�t�a�r�������Export for PCB��� MainWindow���2�S�e��i�l�i� �e�l�e�m�a�n1� �d1_�a� �a�k�t�a�r�������Export selected part��� MainWindow���F�M�e�v�c�u�t� ��i�z�i�m�i� �S�V�G� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�������)Export the current sketch as an SVG image��� MainWindow���>�M�e�v�c�u�t� ��i�z�i�m�i� �E�a�g�l�e� �C�A�D�'�e� �a�k�t�a�r�������&Export the current sketch to Eagle CAD��� MainWindow����M�e�v�c�u�t�r� ��i�z�i�m�i� �p�r�o�f�e�s�y�o�n�e�l� �B�a�s�k1� �D�e�v�r�e� ��r�e�t�i�m�i� �i��i�n� �G�e�n�i_�l�e�t�i�l�m�i_� �G�e�r�b�e�r� �(�R�S�-�2�7�4�X�)� �b�i��i�m�i�n�e� �a�k�t�a�r�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow����M�e�v�c�u�t� ��i�z�i�m�i� �K�e�n�d�i�n� �Y�a�p� �y��n�t�e�m�i� �i�l�e� �B�a�s�k1� �D�e�v�r�e� ��r�e�t�i�m�i� �(�f�o�t�o�r�e�z�i�s�t��r�)� �i��i�n� �P�D�F� �b�i��i�m�i�n�e� �a�k�t�a�r�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow����M�e�v�c�u�t� ��i�z�i�m�i� �K�e�n�d�i�n� �Y�a�p� �B�a�s�k1� �D�e�v�r�e� �Y��n�t�e�m�i�(�f�o�t�o�r�e�z�i�s�t��r�)� �i��i�n� �S�V�G� �b�i��i�m�i�n�d�e� �d1_�a� �a�k�t�a�r�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���|�M�e�v�c�u�t� ��i�z�i�m�i�n� �g��r��n�e�n� �k1�s1�m�l�a�r1�n1� �J�P�G� �r�e�s�m�i� �o�l�a�r�a�k� �d1_�a� �a�k�t�a�r�������If a "sticky" part is moved, parts on top of it are also moved��� MainWindow���f�B�i�r� ��n�c�e�k�i� �y��k�l�e�m�e�d�e�k�i� �e�l�e�m�a�n� � �v�e� �b�i�n�l�e�r�i� �i��e� �a�k�t�a�r�������0Import parts and bins from previous installation��� MainWindow����D�e�n�e�t�l�e�y�i�c�i������� Inspector��� MainWindow���M�o�n�i�t�o�r�'�u�n� �f�i�z�i�k�s�e�l� �b�o�y�u�t�u�n�u� �o�t�o�m�a�t�i�k� �o�l�a�r�a�k� �b�e�l�i�r�l�e�m�e�k� �o�l�a�s1� �g��r��n�m��y�o�r� �b�u� �n�e�d�e�n�l�e� �h�a�l�i� �h�a�z1�r�d�a� �u�y�g�u�l�a�n�m1_� �o�l�a�n� �'�g�e�r��e�k� �b�o�y�u�t�'� �g��r��n��m�� �s�a�d�e�c�e� �b�i�r� �t�a�h�m�i�n�.�Y�a�p�a�b�i�l�e�c�e�i�n�i�z� �e�n� �i�y�i� �e�y�l�e�m� �c�e�t�v�e�l� �k1�s�m1�n�d�a�n� �b�i�r� �c�e�t�v�e�l� �s�e��i�p� �s��r��k�l�e�m�e�k� �v�e� �g�e�r��e�k� �(�f�i�z�i�k�s�e�l�)� �b�i�r� �c�e�t�v�e�l�i�n�i�z�i� �b�u� �c�e�t�v�e�l�l�e� �t�a�m� �o�l�a�r�a�k� �e_�l�e_�i�n�c�e�y�e� �k�a�d�a�r� �y�a�k1�n�l�a_�t1�r�m�a�k�.������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow��� �%�1�'�i� ��a�l1_�t1�r�.�.�.������� Launch %1...��� MainWindow����K�a�t�m�a�n�l�a�r�������Layers��� MainWindow���^�E�l�e�m�a�n�l�a�r1�n� �L�i�s�t�e�s�i� �(�&�M�a�l�z�e�m�e�l�e�r�i�n� �M�a�l�i�y�e�t�i�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow����Y��k�l�e�n�i�y�o�r�.�.�.������� Loading...��� MainWindow����E�l�e�m�a�n1� �K�i�l�i�t�l�e������� Lock Part��� MainWindow���b�A�n�a�P�e�n�c�e�r�e�:�:�E�l�e�m�a�n�l�a�r�D�o�s�y�a�s1�n�a�t�a_1� �a�n�a�p�e�n�c�e�r�e� �y�o�k�������0MainWindow::moveToPartsFolder mainwindow missing��� MainWindow����A�n�a�P�e�n�c�e�r�e�:�:�M�e�n��y�0�n�d�e�k�s�l�e�d�o�l�d�u�r�:�'�%�1�'� �i�s�i�m�l�i� ��r�n�e�i� �y��k�e�l�e�m�e� �b�a_�a�r1�s1�z�������EMainWindow::populateMenuWithIndex: couldn't load example with id='%1'��� MainWindow���&�S�a�a�t� �Y��n��n�d�e� �D��n�d��r������� Meta+Ctrl+R��� MainWindow���6�S�a�a�t� �Y��n��n��n� �T�e�r�s�i�n�e� �D��n�d��r�������Meta+Shift+Ctrl+R��� MainWindow���.�M�e�v�c�u�t� �p�e�n�c�e�r�e�y�i� �k����l�t�������Minimize current window��� MainWindow����S�e��i�l�i� �h�a�t�l�a�r1� �b�o�a�r�d�'�u�n� �d�i�e�r� �t�a�r�a�f1�n�a� �a�k�t�a�r� �(�n�o�t�:� �'�i�l�k�'� �h�a�t� �a�k�t�a�r1�l�a�c�a�k� �g�e�r�i�y�e� �k�a�l�a�n�l�a�r�i� �a�y�n1� �t�a�r�a�f1� �t�a�k�i�p� �e�d�e�c�e�k�)�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���0�B�o�a�r�d� �d�i�e�r� �t�a�r�a�f1�n�a� �g�e��������Move to other side of the board��� MainWindow����Y�e�n�i�������New��� MainWindow���H�'�%�1�'� �h�e�r�h�a�n�g�i� �b�i�r� ��i�z�i�m�e� �r�a�s�t�l�a�n�m�a�d1�������No Sketch found in '%1'��� MainWindow���:�Y��n�l�e�n�d�i�r�m�e� �i��i�n� �b�a�l�a�n�t1� �y�o�k�������No connections to route��� MainWindow���(�B�a�k1�r� ��s�t� �k�a�t�m�a�n� �y�o�k�������No copper top layer��� MainWindow����T�a�m� �o�l�a�r�a�k� �e_�l�e_�e�n� �b�i�r� �e�l�e�m�a�n� �b�u�l�u�n�a�m�a�d1�;�F�r�i�t�z�i�n�g� �e�n� �y�a�k1�n� �e_�l�e_�m�e�y�i� �s�e��t�i�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow����S��r�e�s�i� �g�e��m�i_� �h�e�r�h�a�n�g�i� �b�i�r� �e�l�e�m�a�n� �b�u�l�u�n�a�m�a�d1�.� �T��m� �e�l�e�m�a�n�l�a�r1�n1�z� �g��n�c�e�l�.�������7No outdated parts found. All your parts are up-to-date.��� MainWindow����B�u� ��z�e�l�l�i�k�t�e� �b�i�r� �e�l�e�m�a�n� �y�o�k�.� � �B�u� �m�e�s�a�j1� �e�n�g�e�l�l�e�m�e�k� �i��i�n� ��a�l1_1�y�o�r�u�z� �v�e� �s�i�z�e� �v�a�r�o�l�a�n� ��z�e�l�l�i�k�l�e�r�d�e�n� �b�i�r�i�n�i� �s�e��m�e� �i�m�k�a�n1� �s�u�n�u�y�o�r�u�z�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���P�'�%�1�'� �i�l�e� �i�l�g�i�l�i� �h�i��b�i�r� �s�o�n�u�� �b�u�l�u�n�a�m�a�d1�.�������"No parts matched search term '%1'.��� MainWindow��� �T�A�M�A�M�������OK��� MainWindow���8��e�v�r�i�m�i��i� �E�l�e�m�a�n� ��z�e�l�l�i�k�l�e�r�i�������Online Parts Reference��� MainWindow���0��e�v�r�i�m�i��i� �P�r�o�j�e� �G�a�l�e�r�i�s�i�������Online Projects Gallery��� MainWindow���,�O�n�l�i�n�e� ��r�e�t�i�c�i� �N�o�t�l�a�r�������Online Tutorials��� MainWindow���L�F�r�i�t�z�i�n�g� �b�a1_� �w�e�b� �s�i�t�e�s�i�n�i� �z�i�y�a�r�e�t� �e�t�������Open Fritzing donation web page��� MainWindow���0�F�r�i�t�z�i�n�g� ��r�n�e�k�l�e�r�'�i�n�i� �A��������Open Fritzing examples��� MainWindow���&�F�r�i�t�z�i�n�g� �Y�a�r�d1�m1� �A��������Open Fritzing help��� MainWindow���.�E�l�e�m�a�n� ��z�e�l�l�i�k�l�e�r�i�n�i� �A��������Open Parts Reference��� MainWindow�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���P�M�i�k�r�o�i�i_�l�e�m�c�i� �p�r�o�g�r�a�m�l�a�m�a� �p�e�n�c�e�r�e�s�i�n�i� �a��������'Open microcontroller programming window��� MainWindow���4�P�r�o�g�r�a�m�l�a�m�a� �p�e�n�c�e�r�e�s�i�n�i� �a��������Open programming window��� MainWindow���t�V�a�r�o�l�a�n� �b�i�r� �e�l�e�m�a�n� ��z�e�r�i�n�d�e�n� �Y�e�n�i� �E�l�e�m�a�n� �D��z�e�n�l�e�y�i�c�i�'�y�i� �a��������-Open the new parts editor on an existing part��� MainWindow�����i�z�i�m�i�n�i�z�d�e�n� �o�l�u_�t�u�r�u�l�m�u_� �b�i�r� �B�a�s�k1� �D�e�v�r�e�'�y�i� �-�-�m��t�h�i_� �F�r�i�t�z�i�n�g� �F�a�b�'�t�e�n� �s�i�p�r�a�i_� �e�t�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow���:�B�i�r� �B�a�s�k1� �D�e�v�r�e� �S�i�p�a�r�i_� �E�t�.�.�.�������Order a PCB...��� MainWindow���.�S��r�e�s�i� �G�e��m�i_� �e�l�e�m�a�n�l�a�r�������Outdated parts��� MainWindow����B�a�s�k1� �D�e�v�r�e�������PCB��� MainWindow����S�a�y�f�a� �A�y�a�r�l�a�r1������� Page Setup��� MainWindow���4�E�l�e�m�a�n� �D��z�e�n�l�e�y�i�c�i� �Y�a�r�d1�m1�������Parts Editor Help��� MainWindow���2�P�a�n�o�d�a�k�i� ��g�e�l�e�r�i� �y�a�p1_�t1�r�������Paste clipboard contents��� MainWindow���T�P�a�n�o�d�a�k�i� ��g�e�l�e�r�i� �b�e�l�i�r�l�i� �b�i�r� �Y�e�r�e� �y�a�p1_�t1�r�������!Paste clipboard contents in place��� MainWindow���2�B�e�l�i�r�l�i� �b�i�r� �y�e�r�e� �Y�a�p1_�t1�r�������Paste in Place��� MainWindow���Z�L��t�f�e�n� �b�i�r� ��n�c�e�k�i� �F�r�i�t�z�i�n�g� �k�l�a�s��r��n�� �s�e��i�n�.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow����L��t�f�e�n� �t�e�k� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �s�e��i�n�i�z�-�-�b�a�k1�r� �d�o�l�g�u�l�a�m�a� �a�y�n1� �a�n�d�a� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d� �i��i�n� �y�a�p1�l�a�b�i�l�m�e�k�t�e�.�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow����L��t�f�e�n� �t�e�k� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �s�e��i�n�-�-�t�o�p�r�a�k� �d�o�l�g�u�l�a�m�a� �i_�l�e�m�i� �t�e�k� �s�e�f�e�r�d�e� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d� �i��i�n� �y�a�p1�l�a�b�i�l�i�r�.�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow����L��t�f�e�n� �t�e�k� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �s�e��i�n�.� �B�a�k1�r� �d�o�l�g�u� �i_�l�e�m�l�e�r�i� �t�e�k� �s�e�f�e�r�d�e� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d� �i��i�n� �y�a�p1�l�a�b�i�l�i�r�.�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow����L��t�f�e�n� �t�e�k� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �s�e��i�n�.� �D�R�C� �t�e�k� �e�f�e�r�d�e� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d� �i�l�e� ��a�l1_�a�b�i�l�m�e�k�t�e�.�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow����L��t�f�e�n� �O�t�o�-�Y��n�l�e�n�d�i�r�m�e�k� �i�s�t�e�d�i�i�n�i�z� �b�o�a�r�d�'�u� �s�e��i�n�i�z�.� �O�t�o�-�Y��n�l�e�n�d�i�r�i�c�i� �a�y�n1� �a�n�d�a� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�'�u� �y��n�l�e�n�d�i�r�e�b�i�l�i�r�.�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow���~�'�%�1�'�i� �k�a�y�d�e�t�m�e�k� �i��i�n� �l��t�f�e�n� �b�i�r� �.�f�z�z� �b�i��i�m�l�i� �d�o�s�y�a� �a�d1� �b�e�l�i�r�t�i�n�������0Please specify an .fzz file name to save '%1' to��� MainWindow���\�P�r�o�j�e�n�i� �F�r�i�t�z�i�n�g�'�i�n� �i�n�t�e�r�n�e�t� �s�i�t�e�s�i�n�d�e� �y�a�y1�n�l�a�������&Post a project to the Fritzing website��� MainWindow���.�E�l�e�m�a�n1�n� �y�e�r�i�n�i� �s�a�b�i�t�l�e�������Prevent a part from being moved��� MainWindow���,�M�e�v�c�u�t� �g��r��n��m�� �y�a�z�d1�r�������Print the current view��� MainWindow����Y�a�z�d1�r1�y�o�r�.�.�.������� Printing...��� MainWindow����D�e�v�a�m� �E�t�������Proceed��� MainWindow��� �U�y�g�u�l�a�m�a�'�d�a�n� �1�k�������Quit the application��� MainWindow���"�Y��k�s�e�l�t� �v�e� �A�l��a�l�t�������Raise and Lower��� MainWindow����S�a�l�t�-�o�k�u�n�u�r������� Read-only��� MainWindow��� �H�a�z1�r�������Ready��� MainWindow����Y��n�l�e�n�d�i�r�m�e� �d�u�r�u�m�u�n�u� �v�e� �y�u�m�a�k� �k�a�b�l�o�l�a�r1� �t�e�k�r�a�r� �h�e�s�a�p�l�a� �(�o�t�o�-�g��n�c�e�l�l�e�m�e� �d�o�r�u� ��a�l1_�m�a�d11� �d�u�r�u�m�l�a�r�d�a�)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow����T�e�k�r�a�r�d�a�n� �Y�a�p�������Redo��� MainWindow���&��i�z�i�m�i� �t�e�k�r�a�r� �y��k�l�e�������Reload the sketch��� MainWindow���.�E�s�n�e�t�m�e� �N�o�k�t�a�s1�n1� �1�k�a�r�������Remove Bendpoint��� MainWindow���(�B�a�k1�r� �D�o�l�g�u�y�u� �1�k�a�r�t�������Remove Copper Fill��� MainWindow���&�B�a�k1�t� �d�o�l�g�u�y�u� �1�k�a�r�������Remove copper fill��� MainWindow���&�B�a�k1�r� �d�o�l�g�u�y�u� �1�k�a�r�������Remove the copper fill��� MainWindow���&�B�i�r� �b�u�g� �r�a�p�o�r�l�a�.�.�.�.�������Report a bug...��� MainWindow���L�F�r�i�t�z�i�n�g�'�t�e� �b�u�l�d�u�u�n� �b�i�r� �b�u�g�'1� �r�a�p�o�r�l�a�������%Report a but you've found in Fritzing��� MainWindow����V�a�r�s�a�y1�l�a�n�a� �D��n�������Restore Default��� MainWindow����G�e�r�i� �D��n�d��r�������Revert��� MainWindow����G�e�r�i� �D��n�d��r�?�������Revert?��� MainWindow��� �D��n�d��r�������Rotate��� MainWindow���2�1�8�0� �d�e�r�e�c�e� �d��n�d��r� �{�1�8�0�?�}������� Rotate 180���� MainWindow���J�S�a�a�t� �y��n��n�d�e� �1�3�5� �d�e�r�e�c�e� �d��n�d��r� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���X�S�a�a�t� �y��n��n��n� �t�e�r�s�i�n�e� �4�5� �d�e�r�e�c�e� �d��n�d��r� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow���J�S�a�a�t� �y��n��n�d�e� �1�3�5� �d�e�r�e�c�e� �d��n�d��r� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���X�S�a�a�t� �y��n��n��n� �t�e�r�s�i�n�e� �4�5� �d�e�r�e�c�e� �d��n�d��r� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���V�M�e�v�c�u�t� �s�e��i�m�i� �s�a�a�t� �y��n��n�d�e� �4�5� �d�e�r�e�c�e� �d��n�d��r�������-Rotate current selection 45 degrees clockwise��� MainWindow���f�M�e�v�c�u�t� �s�e��i�m�i� �s�a�a�t� �y��n��n��n� �t�e�r�s�i�n�e� �4�5� �d�e�r�e�c�e� �d��n�d��r�������5Rotate current selection 45 degrees counter clockwise��� MainWindow���f�M�e�v�c�u�t� �s�e��i�m�i� �s�a�a�t� �y��n��n��n� �t�e�r�s�i�n�e� �9�0� �d�e�r�e�c�e� �d��n�d��r�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���F�S�e��i�l�i� �e�l�e�m�a�n�l�a�r1� �1�8�0� �d�e�r�e�c�e� �d��n�d��r�������(Rotate the selected parts by 180 degrees��� MainWindow���^�S�e��i�l�i� �e�l�e�m�a�n�l�a�r1� �s�a�a�t� �y��n��n�d�e� �9�0� �d�e�r�e�c�e� �d��n�d��r�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow���,�Y��n�l�e�n�d�i�r�m�e� �t�a�m�a�m�l�a�n�d1�������Routing completed��� MainWindow���t�Y��n�l�e�n�d�i�r�m�e� �%�n� �j�u�m�p�e�r� �e�l�e�m�a�n�(�l�a�r�)1� �k�u�l�l�a�n1�l�a�r�a�k� �t�a�m�a�m�l�a�n�d1�������)Routing completed using %n jumper part(s)��� MainWindow��� �S�V�G� �I�m�a�g�e�(�*�.�s�v�g�)�������SVG Image (*.svg)��� MainWindow����%�1�'�i� �K�a�y�d�e�t�������Save %1��� MainWindow����M�a�l�z�e�m�e�l�e�r�i�n� �M�a�l�i�y�e�t�i� �n�i� �(�B�o�M�)�/�A�l1_�v�e�r�i_� �L�i�s�t�e�s�i� �t�e�x�t� �o�l�a�r�a�k� �k�a�y�d�e�t�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���F�B�i�r� �n�e�t�l�i�s�t�'�i� �S�I�C�E� �b�i��i�m�i�n�d�e� �k�a�y�d�e�t�������Save a netlist in SPICE format��� MainWindow���B�B�i�r� �n�e�t�l�i�s�t�i� �X�M�L� �b�i��i�m�i�n�d�e� �k�a�y�d�e�t�������Save a netlist in XML format��� MainWindow���(�M�e�v�c�u�t� ��i�z�i�m�i� �k�a�y�d�e�t�������Save the current sketch��� MainWindow����'�%�1�'� �k�a�y�d�e�d�i�l�d�i������� Saved '%1'��� MainWindow���^�e�m�a�t�i�k������� Schematic��� MainWindow����A�r�a�������Search��� MainWindow���l�Y�a�z1�m� �e_�l�e_�t�i�r�m�e�y�i� �k�u�l�l�a�n�a�r�a�k� ��i�z�i�m�d�e�k�i� �e�l�e�m�a�n�l�a�r1� �a�r�a�������-Search for parts in a sketch by matching text��� MainWindow���R�T��m� �"�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �Y�a�p�m�a�"� �H�a�t�l�a�r1�n1� �S�e��������#Select All "Don't Autoroute" Traces��� MainWindow���H�T��m� �O�t�o�-�Y��n�l�e�d�i�r�i�l�e�b�i�l�i�r� �H�a�t�l�a�r1� �S�e��������Select All Autoroutable Traces��� MainWindow���*�T��m� �B�a�k1�r� �D�o�l�g�u�y�u� �S�e��������Select All CopperFill��� MainWindow���8�T��m� �A�t�l�a�y1�c1�l�a�r1�(�J�u�m�p�e�r�)� �S�e��������Select All Jumpers��� MainWindow���4�T��m� �k�i�l�i�t�l�i� �e�l�e�m�a�n�l�a�r1� �s�e��������Select All Locked Parts��� MainWindow����T��m� �H�a�t�l�a�r1� �S�e��������Select All Traces��� MainWindow���"�T��m� �G�e��i�t�l�e�r�i� �S�e��������Select All Vias��� MainWindow���"�T��m� �K�a�b�l�o�l�a�r1� �S�e��������Select All Wires��� MainWindow���J�A��m�a�k� �i��i�n� �b�i�r� �F�r�i�t�z�i�n�g� �D�o�s�y�a�s1� �S�e��i�n�������Select a Fritzing File to Open��� MainWindow���>�T��m� �b�a�k1�r� �d�o�l�g�u� �n�e�s�n�e�l�e�r�i�n�i� �s�e��������Select all copper fill items��� MainWindow���$�T��m� �e�l�e�m�a�n�l�a�r1� �s�e��������Select all elements��� MainWindow���D�T��m� �a�t�l�a�y1�c1�(�j�u�m�p�e�r�)� �n�e�s�n�e�l�e�r�i� �s�e��������Select all jumper item parts��� MainWindow���0�T��m� �s�a�b�i�t� �e�l�e�m�a�n�l�a�r1� �s�e��������$Select all parts that can't be moved��� MainWindow���.�T��m� �h�a�t� �k�a�b�l�o�l�a�r1�n1� �s�e��������Select all trace wires��� MainWindow���d�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �y�a�p1�l�m�a�m1_� �t��m� �h�a�t� �k�a�b�l�o�l�a�r1�n1� �s�e��������0Select all trace wires excluded from autorouting��� MainWindow���~�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �s1�r�a�s1�n�d�a� �d�e�i_�e�b�i�l�e�c�e�k� �t��m� �h�a�t� �k�a�b�l�o�l�a�r1�n1� �s�e��������=Select all trace wires that can be changed during autorouting��� MainWindow���4�T��m� �g�e��i�t� �e�l�e�m�a�n�l�a�r1�n1� �s�e��������Select all via parts��� MainWindow���"�T��m� �k�a�b�l�o�l�a�r1� �s�e��������Select all wires��� MainWindow���E�k�r�a�n� �k�o�n�u�m�u� �g�e�r��e�k� �k�o�n�u�m�u�y�l�a� �e_�l�e_�m�e�y�e�n� �t��m� �h�a�t�l�a�r1� �s�e�� �.�S�a�d�e�c�e� �s��r��m� �0�.�7�.�1�0� �v�e� �d�a�h�a� ��n�c�e�s�i�n�d�e� �O�t�o�-�Y��n�l�e�n�d�i�r�i�l�i�m�i_� ��i�z�i�m�l�e�r� �i��i�n� �g�e�r�e�k�l�i�d�i�r�������Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier��� MainWindow���8�Z�a�m�a�n1� �g�e��m�i_� �e�l�e�m�a�n�l�a�r1� �s�e��������Select outdated parts��� MainWindow����G�e�r�i�y�e� �g��n�d�e�r������� Send Backward��� MainWindow���d�S�e��i�l�i� �n�e�s�n�e�l�e�r�i� �k�e�n�d�i� �k�a�t�m�a�n�l�a�r1�n�d�a� �a�r�k�a�y�a� �g��n�d�e�r�������+Send selected object(s) back in their layer��� MainWindow���j�S�e��i�l�i� �n�e�s�n�e�(�l�e�r�)�i� �k�e�n�d�i� �k�a�t�m�a�n�l�a�r1�n�d�a� �a�r�a�k�a�y�a� �g��n�d�e�r�������2Send selected object(s) to the back of their layer��� MainWindow����A�r�k�a�y�a� �G��n�d�e�r������� Send to Back��� MainWindow���6�A�r�k�a� �P�l�a�n� �R�e�n�g�i�n�i� �A�y�a�r�l�a�.�.�.�������Set Background Color...��� MainWindow���:�I�z�g�a�r�a�n1�n� �S1�k�l11�n1� �A�y�a�r�l�a�.�.�.�������Set Grid Size...��� MainWindow���\�T�o�p�r�a�k� �D�o�l�g�u�s�u� �U�z�a�k� �T�u�t�m�a� �M�e�s�a�f�e�s�i�n�i� �A�y�a�r�l�a�.�.�.�������Set Ground Fill Keepout...��� MainWindow���4�T�o�p�r�a�k� �D�o�l�g�u� �T�a�n�e�s�i� �A�y�a�r�l�a�������Set Ground Fill Seed��� MainWindow���j�U�z�a�k� �t�u�t�m�a� �d�a�h�i�l� �O�t�o�-�Y��n�l�e�n�d�i�r� �a�y�a�r�l�a�r1�n1� �d�e�i_�t�i�r�.�.�.�������/Set autorouting parameters including keepout...��� MainWindow���R�H�e�r� �i�k�i� �b�a�k1�r� �k�a�t�m�a�n1� �d�a� �t1�k�l�a�n�a�b�i�l�i�r� �y�a�p������� Set both copper layers clickable��� MainWindow���D�A�l�t� �b�a�k1�r� �k�a�t�m�a�n1� �t1�k�l�a�n�a�b�i�l�i�r� �y�a�p�������!Set copper bottom layer clickable��� MainWindow���D��s�t� �b�a�k1�r� �k�a�t�m�a�n1� �t1�k�l�a�n�a�b�i�l�i�r� �y�a�p�������Set copper top layer clickable��� MainWindow���J�B�u� �g��r��n��m� �i��i�n� �a�r�k�a� �p�l�a�n� �r�e�n�g�i�n�i� �s�e��������%Set the background color of this view��� MainWindow���F�I�z�a�g�a�r�a� �a�r�a�l11�n1� �%�1�'�e� �g��r�e� �a�y�a�r�l�a�.�������Set the grid size for %1.��� MainWindow����T�o�p�r�a�k� �d�o�l�g�u�s�u� �v�e� �h�a�t�l�a�r� �y�a� �d�a� �k�o�n�n�e�k�t��r�l�e�r� �a�r�a�s1�n�d�a� �e�n� �k1�s�a� �m�e�s�a�f�e�y�i� �a�y�a�r�l�a�������ESet the minimum distance between ground fill and traces or connectors��� MainWindow���T�B�U� �g��r��n��m� �i��i�n� 1�z�g�a�r�a�n1�n� �s1�k�l11�n1� �a�y�a�r�l�a�������%Set the size of the grid in this view��� MainWindow��� �P�a�y�l�a_�������Share��� MainWindow���80�n�t�e�r�n�e�t� ��z�e�r�i�n�d�e�n� �p�a�y�l�a_�.�.�.�������Share online...��� MainWindow���,�K�a�b�u�k� �k�o�d�u� ��a�l1_�t1�r� �%�1�������Shell launch %1��� MainWindow����S�h�i�f�t� �C�t�r�l�+�0������� Shift+Ctrl+0��� MainWindow����S�h�i�f�t� �C�t�r�l�+�1������� Shift+Ctrl+1��� MainWindow����K�o�d�u� �G��s�t�e�r������� Show Code��� MainWindow����I�z�g�a�r�a�y1� �G��s�t�e�r������� Show Grid��� MainWindow���H�E�l�e�m�a�n�l�a�r1� �K����k� �R�e�s�i�m� �O�l�a�r�a�k� �G��s�t�e�r�������Show Parts Bin Icon View��� MainWindow���$�E�l�e�m�a�n�l�a�r1� �L�i�s�t�e�l�e�������Show Parts Bin List View��� MainWindow���B�Q�t�'�n�i�n� �"�H�a�k�k1�n�d�a�"� �k�u�t�u�s�u�n�u� �g��s�t�e�r�������Show Qt's about box��� MainWindow���^�M�e�v�c�u�t� �g��r��n��m� �i��i�n� �u�y�g�u�n� �t��m� �k�a�t�m�a�n�l�a�r1� �g��s�t�e�r�������2Show all the available layers for the current view��� MainWindow���.�E�l�e�m�a�n� �e�t�i�k�e�t�i�n�i� �G��s�t�e�r�������Show part label��� MainWindow���:�E�l�e�m�a�n1�n� �s�e�r�i�g�r�a�f�i�s�i�n�i� �g��s�t�e�r�������Show part silkscreen��� MainWindow���:�B�a�s�k1� �D�e�v�r�e� �g��r��n��m��n�� �g��s�t�e�r�������Show the PCB view��� MainWindow���B�U�y�g�u�l�a�m�a� �i�l�e� �i�l�g�i�l�i� �k�u�t�u�y�u� �g��s�t�e�r������� Show the application's about box��� MainWindow���8�B�r�e�a�d�b�o�a�r�d� �g��r��n��m��n�� �g��s�t�e�r�������Show the breadboard view��� MainWindow���F�K�o�d�u� �p�r�o�g�r�a�m�l�a�m�a� �g��r��n��m��n�d�e� �g��s�t�e�r������� Show the code (programming) view��� MainWindow��� �I�z�a�g�a�r�a�y1� �g��s�t�e�r������� Show the grid��� MainWindow���.^�e�m�a�t�i�k� �g��r��n��m�� �g��s�t�e�r�������Show the schematic view��� MainWindow���6�Y��n�l�e�n�d�i�r�i�l�m�e�m�i_�l�e�r�i� �G��s�t�e�r������� Show unrouted��� MainWindow���X�S�e��i�l�i� �e�l�e�m�a�n�l�a�r1�n� �e�t�i�k�e�t�l�e�r�i�n�i� �G��s�t�e�r�/�G�i�z�l�e�������*Show/hide the label for the selected parts��� MainWindow���(��i�z�i�m� �d1_�a� �a�k�t�a�r1�l�d1�������Sketch exported��� MainWindow���0��i�z�i�m� �G�e�r�b�e�r�'�e� �a�k�t�a�r1�l�d1�������Sketch exported to Gerber��� MainWindow�����z��r� �D�i�l�e�r�i�z�!�������Sorry!��� MainWindow���@��z�g��n��z�,� �'�%�1�'� �h�e�n��z� �u�y�g�u�l�a�n�m�a�m1_�������(Sorry, "%1" has not been implemented yet��� MainWindow���,�B�i�r� �d�o�s�y�a� �a�d1� �b�e�l�i�r�t�i�n�������Specify a file name��� MainWindow����Y�a�p1_�k�a�n�������Sticky��� MainWindow��� �E�r�i�y�i� �D��z�l�e_�t�i�r�������Straighten Curve��� MainWindow���H�S�e��i�l�i� �k�a�b�l�o�n�u�n� �e�r�i�l�i�i�n�i� �d��z�l�e_�t�i�r�������)Straighten the curve of the selected wire��� MainWindow����%�1� �e�l�e�m�a�n1�n� �g��n�c�e�l�l�e�m�e�s�i� �b�a_�a�r1�l1�.� �T��m� �g��r��n��m�l�e�r�i� �o�l�a�s1� �y�a�n� �e�t�k�i�l�e�r� �i��i�n� �k�o�n�t�r�o�l� �e�d�i�n�.�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow��\�S�v�g� �%�1�'�d�e� �b�i�r� �%�2� �k�a�t�m�a�n1� �b�u�l�u�n�m�u�y�o�r�.��z�e�l� �b�i�r� �b�o�a�r�d� �o�l�u_�t�u�r�m�a�n1�n� �n�a�s1�l� �y�a�p1�l�a�c�a1�n�a� �d�a�i�r� �b�i�l�g�i� �i��i�n� �l�i�n�k�t�e� �b�u�l�u�n�a�n� ��r�e�t�i�c�i� �n�o�t�l�a�r�a� �b�a�k�a�b�i�l�i�r�s�i�n�i�z� �<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�<�/�a�>�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���>�%�2� �%�1� �m�o�d��l�� �i�l�e� �y�e�r� �d�e�i_�t�i�r�d�i�������Swapped %1 with module %2��� MainWindow����Y�a�z1� �e�l�e�m�a�n� �e�t�i�k�e�t�i�,� �a�1�k�l�a�m�a�s1�,� �b�a_�l11�,� �v�b�.� �e_�l�e_�t�i�r�e�c�e�k� �A�r�a�m�a�k� �i��i�n� �b�i�r_�e�y� �y�a�z1�n�:�������NText will match part label, description, title, etc. Enter text to search for:��� MainWindow����.�f�z� �d�o�s�y�a� �b�i��i�m�i� ��n�e�r�i�l�m�i�y�o�r� � �'�%�1�'�'�i� �.�f�z�z� �b�i��i�m�i�n�e� �d��n�_�t��r�m�e�k� �i�s�t�e�r� �m�i�s�i�n�i�z� �y�o�k�s�a� �y�o�k�s�a� �s�a�l�t�-�o�k�u�n�u�r� �o�l�a�r�a�k� �m� �a��m�a�k� �i�s�t�e�r�s�i�n�i�z�?� �������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow���R�D��n�_�t��r�m�e� �i_�l�e�m�i� �'�%�1�'�i� �d�e�i_�t�i�r�e�m�e�y�e�c�e�k�.�������,The conversion process will not modify '%1'.��� MainWindow��.�B�a�k1�r� ��s�t� �(�b�a�k1�r� �1�)� �k�a�t�m�a�n1� �t�e�k� �t�a�r�a�f�l1� �b�o�a�r�d�'�d�a� �m�e�v�c�u�t� �d�e�i�l�.� �L��t�f�e�n� �b�o�a�r�d�'�u� ��i�f�t� �t�a�r�a�f�l1� �o�l�a�r�a�k� �d�e�i_�t�i�r�i�n� �y�a� �d�a� �b�a�k1�r� �a�l�t� �(�b�a�k1�r� �0�)� �k�a�t�m�a�n1�n1� �s�e��i�n�.�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���^�"�%�1�"� �k�l�a�s��r�� �b�i�r� �F�r�i�t�z�i�n�g� �y��k�l�e�m�e� �k�l�a�s��r�� �d�e�i�l�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���^�B�u� �g��r��n��m�d�e� �y��n�l�e�n�d�i�r�i�l�m�e�m�i_� �b�i�r� �b�a�l�a�n�t1� �y�o�k�.�������/There are no unrouted connections in this view.��� MainWindow���z�H�a�l�i� �h�a�z1�r�d�a� �'�%�1�'� �i�s�i�m�l�i� �e�l�e�m�a�n� �F�r�i�t�z�i�n�g�'�e� �y��k�l�e�n�m�i_� �d�u�r�u�m�d�a�.�������:There is already a part with id '%1' loaded into Fritzing.��� MainWindow����B�u� �i_�l�e�m� �g�e�r�i� �d��n��l�e�m�e�z�-�-�t��m� �d�e�i_�i�k�l�e�r�i�n�i�z�i� �k�a�y�b�e�d�e�c�e�k�s�i�n�i�z�.� � �D�e�v�a�m� �e�t� �v�e� �g�e�r�i� �d��n�d��r�?�������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow���B�u� �y�a�k1�n� �b�i�r� �z�a�m�a�n�d�a� �F�r�i�t�z�i�n�g� ��i�z�m�i�n�i�z�i�n� �E�A�G�L�E� �d��z�e�n�l�e�m�e� �y�a�z1�l1�m1�n�a� �a�k�t�a�r1�l�m�a�s1�n1� �s�a�l�a�y�a�c�a�k�.� �E�e�r� �f�a�v�o�r�i� �E�D�A�(�E�l�e�k�t�r�o�n�i�k� �T�a�s�a�r1�m� �O�t�o�m�a�s�y�o�n�u�)�'�l�a�r1�n1�z1� �i��e�r�e�n� �d�a�h�a� �f�a�z�l�a� �d1_�a� �a�k�t�a�r�m�a� �s�e��e�n�e�i� �i�s�t�i�y�o�r�s�a�n1�z� �b�i�z�i� �b�i�l�g�i�l�e�n�d�i�r�i�n� �y�a� �d�a� �k�a�t�k1�l�a�r1�n1�z1� �p�a�y�l�a_1�n�.�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow����K�a�b�l�o�l�a�r1� �D��z�l�e������� Tidy Wires��� MainWindow���,�S�e��i�l�i� �k�a�b�l�o�l�a�r1� �d��z�l�e�������Tidy selected wires��� MainWindow���H��n�e�r�i�l�e�r�,� �K�u�r�n�a�z�l1�k�l�a�r� �v�e� �K1�s�a�y�o�l�l�a�r�������Tips, Tricks and Shortcuts��� MainWindow�����s�t� �K�a�t�m�a�n������� Top Layer��� MainWindow����B�u� �k�o�n�n�e�k�t��r�� �v�e� �b�a�l�a�n�t1�l�a�r1� �t�o�p�r�a�k� �d�o�l�g�u�l�a�m�a� �i_�l�e�m�i� �s1�r�a�s1�n�d�a� �'�t�o�p�r�a�k�'� �o�l�a�r�a�k� �a�l�g1�l�a�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���V�%�1� �d1_�a� �p�a�y�l�a_1�l�a�b�i�l�i�r� �o�l�a�r�a�k� �a�k�t�a�r1�l�a�m1�y�o�r������� Unable to export %1 as shareable��� MainWindow���P�'�%�1�'� �p�a�y�l�a_1�l�a�b�i�l�i�r� ��i�z�i�m�e� �a�k�t�a�r1�l�a�m1�y�o�r�������'Unable to export %1 to shareable sketch��� MainWindow���8�E�L�e�m�a�n� �'�%�1�'�'�d�e�n� �y��k�l�e�n�e�m�i�y�o�r�������Unable to load part from '%1'��� MainWindow���&�'�%�1�'� �a�1�l�a�m1�y�o�r�:� �%�2�������Unable to open '%1': %2��� MainWindow���D�P�a�y�l�a_1�l�a�b�i�l�i�r� �'�%�1�'� �a�1�l�a�m1�y�o�r�:� �%�2�������!Unable to open shareable '%1': %2��� MainWindow���R�P�a�y�l�a_1�l�a�b�i�l�i�r� �e�l�e�m�a�n� �'�%�1�'� �a�1�l�a�m1�y�o�r�:� �%�2�������&Unable to open shareable part '%1': %2��� MainWindow���"�%�1� �k�a�y�d�e�d�i�l�e�m�i�y�o�r�������Unable to save %1��� MainWindow���~�B�O�M� �d�o�s�y�a�s1� �k�a�y�d�e�d�i�l�e�m�i�y�o�r�,� �a�n�c�a�k� �i�l�g�i�l�i� �y�a�z1� �p�a�n�o�y�a� �a�k�t�a�r1�l�d1�.�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow����G�e�r�i� ��e�v�i�r�������Undo��� MainWindow���.�G�e�r�i�y�e� �A�l1�n�m1_� 0_�l�e�m�l�e�r������� Undo History��� MainWindow���8�Y��n�l�e�n�d�i�r�i�l�m�e�m�i_� �b�a�l�a�n�t1�l�a�r�������Unrouted connections��� MainWindow���&�%�1� �e�l�e�m�a�n1� �g��n�c�e�l�l�e�������Update %1 part(s)��� MainWindow���4�B�i�l�g�i� �P�e�n�c�e�r�e�s�i�n�i� �g��n�c�e�l�l�e�������Update InfoView on hover��� MainWindow���4�S�e��i�l�i� �e�l�e�m�a�n�l�a�r1� �g��n�c�e�l�l�e�������Update selected parts��� MainWindow����O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �y�a�p�a�r�k�e�n�,� �b�u� �h�a�t� �k�a�b�l�o�s�u�n�u�,� �g�e��i�t�i�,� �y�a� �d�a� �a�t�l�a�y1�c1�y1�(�j�u�m�p�e�r�)� �y1�r�t�m�a�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow���0��e� �a�k�t�a�r1�l�m1_� �e�l�e�m�a�n�l�a�r1� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �F�r�i�t�z�i�n�g�'�i� �y�e�n�i�d�e�n� �b�a_�l�a�t�m�a�n1�z� �g�e�r�e�k�e�c�e�k�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow�����i�z�i�m�i�n�i�z�i�n� �h�e�n��z� �b�i�r� �b�o�a�r�d�'�u� �y�o�k�!� �L��t�f�e�n� �G�e�r�b�e�r�'�e� �a�k�t�a�r�m�a�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow�����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�m�i�y�o�r�!� � �L��t�f�e�n� �b�a�k1�r� �d�o�l�g�u�y�u� �1�k�a�r�m�a�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�m�i�y�o�r�!� � �L��t�f�e�n� �t�o�p�r�a�k� �d�o�l�g�u�l�a�m�a� �y�a� �d�a� �b�a�k1�r� �d�o�l�g�u�l�a�m�a�y1� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow�����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�m�i�y�o�r�!� � �L��t�f�e�n� �O�t�o�-�Y��n�l�e�n�d�i�r�i�c�i�y�i� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow�����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�m�i�y�o�r�!� � �T�a�s�a�r1�m� �k�u�r�a�l�l�a�r1� �k�o�n�t�r�o�l��(�D�R�C�)� �s�a�d�e�c�e� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �i�l�e� �y�a�p1�l�a�b�i�l�i�r�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow�����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�e�m�e�m�e�k�t�e�!� �A�s�i�t�l�i� �o�y�m�a� ��r�e�t�i�m� �i_�l�e�m�i� �i��i�n� ��i�z�i�m�i�n�i�z�e� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow�����i�z�i�m�i�n�i�z� �h�e�n��z� �b�i�r� �b�o�a�r�d� �i��e�r�m�i�y�o�r�!� �L��t�f�e�n� �b�a�k1�r� �d�o�l�g�u� �i_�l�e�m�l�e�r�i� �y�a�p�a�b�i�l�m�e�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow����Y�a�k1�n�l�a_�t1�r�������Zoom in��� MainWindow����U�z�a�k�l�a_�t1�r�������Zoom out��� MainWindow����R�e�s�i�m� �o�l�a�r�a�k�������as Image��� MainWindow����a�l�t�������bottom��� MainWindow��� �b�a�k1�r�������copper��� MainWindow����b�a�k1�r� �d�o�l�g�u������� copperfill��� MainWindow���@�e�l�e�m�a�n�l�a�r1� �d�i�r�e�k� �o�l�a�r�a�k� �y��k�l��y�o�r�������directly loading parts��� MainWindow�����r�e�t�i�m� �i��i�n�������for Production��� MainWindow��� �t�o�p�r�a�k�������ground��� MainWindow����i�n��������in��� MainWindow��� �A�t�l�a�y1�c1�(�J�u�m�p�e�r�)�������jumpers��� MainWindow����%�1� �y��k�l�e�n�i�y�o�r������� loading %1��� MainWindow���4�%�1� �(�b�r�e�a�d�b�o�a�r�d�)�'�u� �y��k�l��y�o�r�������loading %1 (breadboard)��� MainWindow���*�%�1� �(�m�o�d�e�l�)�'�i� �y��k�l��y�o�r�������loading %1 (model)��� MainWindow���(�%�1� �(�p�c�b�)�'�y�i� �y��k�l��y�o�r�������loading %1 (pcb)��� MainWindow���.�%�1� �(_�e�m�a�t�i�k�)�'�i� �y��k�l��y�o�r�������loading %1 (schematic)��� MainWindow����y�e�n�i� ��i�z�i�m������� new sketch��� MainWindow���*�.�f�z� �d�o�s�y�a� �b�i��i�m�i� �e�s�k�i�������the .fz file format is obsolete��� MainWindow���`�N�e� �o�l�d�u�u�n�u� �g��r�m�e�k� �i��i�n� �s�a�h�t�e� �b�i�r� �i�s�t�i�s�n�a� �b�a_�l�a�t�������*throw a fake exception to see what happens��� MainWindow���&0�s�t�i�s�n�a� �t�e�s�t� �b�a_�l�a�t�������throw test exception��� MainWindow�����s�t�������top��� MainWindow���Z�%�1�'�i�n� �y�e�r�i�n�e� �g�e��e�b�i�l�e�c�e�k� �b�i�r_�e�y� �b�u�l�u�n�a�m1�y�o�r�.� �������#unable to find replacement for %1. ��� MainWindow����g�e��i�t�l�e�r�������vias��� MainWindow����%�n� �g�e��i�t�l�e������� with %n vias��� MazeRouter���:�O�t�o�-�Y��n�l�e�n�d�i�r�m�e� �i�p�t�a�l� �e�d�i�l�d�i�.�������Autorouter was cancelled.��� MazeRouter���J�H�a�t�l�a�r� �e�n� �u�y�g�u�n� �d�u�r�u�m�a� �g�e�t�i�r�i�l�i�y�o�r�.�.�.�������Optimizing traces...��� MazeRouter���2�G�e�r�i� �a�l�m�a� �h�a�z1�r�l�a�n1�y�o�r�.�.�.�������Preparing undo...��� MazeRouter���.�Y��n�l�e�n�d�i�r�m�e� �t�a�m�a�m�l�a�n�d1�!�������Routing complete!��� MazeRouter���H�Y��n�l�e�n�d�i�r�m�e� �m�a�k�s�i�m�u�m� �t�u�r�a� �e�r�i_�t�i� �%�1�.�������!Routing reached maximum round %1.��� MazeRouter���$�Y��n�l�e�n�d�i�r�m�e� �d�u�r�d�u�!�������Routing stopped!��� MazeRouter���R�Y��n�l�e�n�d�i�r�m�e� �b�a_�a�r1�s1�z�;� �%�1�.� �t�u�r�d�a� �d�u�r�u�y�o�r�.�������+Routing unsuccessful; stopping at round %1.��� MazeRouter���~�B�e�k�l�e�n�m�e�d�i�k� �S�V�G� �i_�l�e�m�e� �h�a�t�a�s1�-�-�f�r�i�t�z�i�n�g�.�o�r�g� �i�l�e� �i�l�e�t�i_�i�m�e� �g�e��i�n�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���L^�u� �a�n�a� �k�a�d�a�r�k�i�n�i�n� �e�n� �i�y�i�s�i�n�i� �k�u�l�l�a�n�.�.�.�������Use best so far...��� MazeRouter���j^�u� �a�n�a� �k�a�d�a�r�k�i�n�i�n� �e�n� �i�y�i�s�i�:� �%�2�'�n�i�n� �%�1�'�i� �y��n�l�e�n�d�i�r�i�l�d�i�������best so far: %1 of %2 routed��� MazeRouter����%�1�.� �t�u�r�:������� round %1 of:��� MazeRouter���v�'�%�1�'� �d�o�s�y�a�s1� ��z�e�r�i�n�e� �y�a�z1�l�a�m1�y�o�r�.� �N�e�d�e�n�:� �'�%�2�'� �(�h�a�t�a�k�o�d�u� �%�3�)�������5Couldn't overwrite file '%1'. Reason: %2 (errcode %3)��� ModelBase���&�D�o�s�y�a� �k�a�y1�t� �h�a�t�a�s1�!�������File save failed!��� ModelBase���:0�l�g�i�l�i� �%�n� �e�l�e�m�a�n� �b�u�l�u�n�a�m1�y�o�r�:�������(Unable to find the following %n part(s):��� ModelBase�������at��� ModelBase�����i�p� �e�t�i�k�e�t�i������� chip label��� MysteryPart��� �e�t�i�k�e�t�������label��� MysteryPart����a� �e�t�i�k�e�t�i������� net label���NetLabel���.�[�n�o�t�u�n�u�z�u� �b�u�r�a�y�a� �y�a�z1�n�]�������[write your note here]���Note���x�%�1� �D�o�l�g�u�:�L��t�f�e�n� �d�o�l�g�u�y�u� �u�y�g�u�l�a�m�a�k� �i�s�t�e�d�i�i�n�i�z� �b�o�a�r�d�'�u� �s�e��i�n�.�������;%1 Fill: please select the board you want to apply fill to.���PCBSketchWidget���|�1�0� �m�i�l�s� �(�0�.�2�5�4� �m�m�)� �u�y�g�u�n� �b�i�r� �v�a�r�s�a�y1�l�a�n� �b�a_�l�a�n�g1�� �d�e�e�r�i�d�i�r�.� � �������#10 mils is a good default choice. ���PCBSketchWidget���0�H�a�t� �k�a�t�m�a�n1�n1� �d�e�i_�t�i�r�i�n�������Change trace layer���PCBSketchWidget���>�T�o�p�r�a�k� �d�o�l�g�u� �t�a�n�e�l�e�r�i�n�i� �t�e�m�i�z�l�e�������Clear ground fill seeds���PCBSketchWidget���r�K�o�n�n�e�k�t��r�d�e�n� �y�e�n�i� �b�i�r� �h�a�t� �1�k�a�r�m�a�k� �i��i�n� ��z�e�r�i�n�e� �t1�k�l�a�y1�n�.�������-Click this connector to drag out a new trace.���PCBSketchWidget��� �B�a�k1�r�������Copper���PCBSketchWidget����B�a�k1�r� �d�o�l�g�u�:�l��t�f�e�n� �y�a�l�n1�z�c�a� �d�o�l�g�u�l�a�m�a�k� �i�s�t�e�d�i�i�n�i�z� �b�o�a�r�d�'�u� �s�e��i�n�.�������;Copper fill: please select only the board you want to fill.���PCBSketchWidget���(�Y�u�m�a�k�t�a�n� �H�a�t� �O�l�u_�t�u�r�������Create Trace from Ratsnest���PCBSketchWidget����A�r�a�l1�k� �T�a�n1�m�l�a������� Enter Keepout���PCBSketchWidget���(�A�r�a�l1�k� �d�e�e�r�i� �g�i�r�i�n�:�������Enter keepout value:���PCBSketchWidget���V�F�r�i�t�z�i�n�g� �h�a�t�a�s1�:� �b�o�a�r�d� �s�v�g� �i_�l�e�n�e�m�i�y�o�r� �(�1�)�.�������/Fritzing error: unable to render board svg (1).���PCBSketchWidget���V�F�r�i�t�z�i�n�g� �h�a�t�a�s1�:� �b�a�k1�r� �s�v�g� �i_�l�e�n�e�m�i�y�o�r� �(�1�)�.�������0Fritzing error: unable to render copper svg (1).���PCBSketchWidget���Z�F�r�i�t�z�i�n�g� �h�a�t�a�s1�:� �b�a�k1�r� �d�o�l�g�u� �y�a�z1�l�a�m1�y�o�r� �(�1�)�.�������0Fritzing error: unable to write copper fill (1).���PCBSketchWidget���Z�F�r�i�t�z�i�n�g� �h�a�t�a�s1�:� �b�a�k1�r� �d�o�l�g�u� �y�a�z1�l�a�m1�y�o�r� �(�2�)�.�������0Fritzing error: unable to write copper fill (2).���PCBSketchWidget��� �T�o�p�r�a�k�������Ground���PCBSketchWidget���:�P�a�r��a�y�a� �a�i�t� �s�e�r�i�g�r�a�f�i�y�i� �g�i�z�l�e�������Hide part silkscreen���PCBSketchWidget���f�A�r�a�l1�k� �m�i�l�s�(�.�0�0�1� �i�n�� �=� �2�5�.�4� �m�i�k�r�o�n�)� �b�i�r�i�m�i�n�d�e�d�i�r�.� � �������#Keepout is in mils (.001 inches). ���PCBSketchWidget�����s�t��s�t�e� �g�e�l�m�e� �p�r�o�b�l�e�m�i�n�d�e�n� �d�o�l�a�y1� �,� �2� �m�i�l�s�'�e� �(�y�a�k�l�a_1�k� �5�0� �m�i�k�r�o�n�)� �k�a�d�a�r� �o�l�a�n� �m�e�s�a�f�e�l�e�r� ��o�k� �y�a�k1�n� �o�l�a�r�a�k� �t�a�n1�m�l�a�n1�r� �������FNote that due to aliasing, distances may be too short by up to 2 mils ���PCBSketchWidget�����n�c�e� �l��t�f�e�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e�n�i�n� ��z�e�r�i�n�e� �t1�k�l�a�y1�n�-�-�b�u� �i_�l�e�m� �a�y�n1� �a�n�d�a� �y�a�l�n1�z�c�a� �b�i�r� �b�o�a�r�d� �i��i�n� �u�y�g�u�l�a�n�a�b�i�l�i�r�.�������YPlease click on a PCB first--this selection operation only works for one board at a time.���PCBSketchWidget����T�o�p�r�a�k� �d�o�l�g�u�s�u� �y�a�p�m�a�d�a�n� ��n�c�e� �l��t�f�e�n� �b�i�r� �y�a� �d�a� �d�a�h�a� �f�a�z�l�a� �t�o�p�r�a�k� �t�a�n�e�s�i� �b�e�l�i�r�l�e�y�i�n�.� � �������LPlease designate one or more ground fill seeds before doing a ground fill. ���PCBSketchWidget���<�E�l�e�m�a�n�a� �a�i�t� �s�e�r�i�g�r�a�f�i�y�i� �g��s�t�e�r�������Show part silkscreen���PCBSketchWidget��0�B�u� �g�e��i�t� �b�i�r� �e�s�n�e�t�m�e� �n�o�k�t�a�s1�n�a� ��e�v�r�i�l�e�m�e�d�i� ���n�k�� �b�i�r� �u�c�u� �s�a�d�e�c�e� ��s�t� �k�a�t�m�a�n�d�a�k�i� �b�i�r� �e�l�e�m�a�n�a� �b�a�l1� �i�k�e�n� �d�i�e�r� �u�c�u� �s�a�d�e�c�e� �a�l�t� �k�a�t�m�a�n�d�a�k�i� �b�i�r� �e�l�e�m�a�n�a� �b�a�l1�.�������Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer.���PCBSketchWidget��F�B�a�k1�r� �d�o�l�g�u� �o�l�u_�t�u�r�u�l�a�m1�y�o�r�-�-�b��y��k� �b�i�r� �o�l�a�s�l1�k�l�a� �e�l�e�m�a�n� �B�a�s�k1� �D�e�v�r�e�n�i�n� ��z�e�r�i�n�e� �y�e�r�l�e_�t�i�r�i�l�m�e�s�i� �g�e�r�e�k�i�r�k�e�n� �b�a_�k�a� �b�i�r� �e�l�e�m�a�n1�n� �y�a� �d�a� �k�a�b�l�o�n�u�n� ��z�e�r�i�n�e� �y�e�r�l�e_�t�i�r�i�l�m�i_�.�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget����B�a�k1�r� �d�o�l�g�u� �o�l�u_�t�u�r�u�l�a�m1�y�o�r�-�-�b��y��k� �b�i�r� �o�l�a�s1�l1�k�l�a� �e�l�e�m�a�n� �B�a�s�k1� �D�e�v�r�e� ��z�e�r�i�n�e� �y�e�r�l�e_�t�i�r�i�l�m�e�m�i_�.�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget�����i�z�i�m�i�n�i�z�i�n� �h�e�n��z� �b�i�r� �b�o�a�r�d�'�u� �y�o�k�!� � �L��t�f�e�n� �b�a�k1�r� �d�o�l�g�u�y�u� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget�����i�z�i�m�i�n�i�z�i�n� �h�e�n��z� �b�i�r� �b�o�r�a�d�'�u� �y�o�k�!� � �S�e��i�m�i� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �l��t�f�e�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget�����i�z�i�m�i�n�i�z�i�n� �h�e�n��z� �b�i�r� �b�o�r�a�d�'�u� �y�o�k�!� �L��t�f�e�n� �s�e��i�l�e�n� �b�u� �i_�l�e�m�i� �k�u�l�l�a�n�a�b�i�l�m�e�k� �i��i�n� �b�i�r� �B�a�s�k1� �D�e�v�r�e� �e�k�l�e�y�i�n�.�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget�����i�z�i�m�i�n�i�z�i�n� �h�e�n��z� �b�i�r� �b�o�a�r�d�'�u� �y�o�k�.� �B�u� ��i�z�i�m�i� �B�a�s�k1� �D�e�v�r�e� �k1�s�m1� �o�l�m�a�d�a�n� ��r�e�t�e�m�e�z�s�i�n�i�z�.�������[Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part.���PCBSketchWidget����b�u� �n�e�d�e�n�l�e� �a�r�a�l1�k� �d�e�e�r�i�n�i� �2� �m�i�l�s� �(�5�0� �m�i�k�r�o�n�)� �k�a�d�a�r� �a�r�t1�r�m�a�k� �i�s�t�e�y�e�b�i�l�i�r�s�i�n�i�z�.� � �������=so you may want to increase the keepout value by that much. ���PCBSketchWidget���@�S�M�D�(�Y��z�e�y�e� �M�o�n�t�e� �E�d�i�l�m�i_� �E�l�e�m�a�n�)�������SMD���PEConnectorsView���~�B�u�r�a�s1� �e�l�e�m�a�n1�n� �k�o�n�n�e�k�t��r� ��s�t� �v�e�r�i�s�i�n�i� �d��z�e�n�l�e�y�e�b�i�l�e�c�e�i�n�i�z� �y�e�r�������:This is where you edit the connector metadata for the part���PEConnectorsView����D�e�l�i�k�l�i������� Through-hole���PEConnectorsView���"�k�o�n�n�e�k�t��r� �s�a�y1�s1�:�������number of connectors:���PEConnectorsView���*� � �D�e�v�a�m� �e�t� �v�e� �k�a�y�d�e�t�?������� Go ahead and save?��� PEMainWindow����&�D��z�e�n�l�e�������&Edit��� PEMainWindow����&�D1_�a� �A�k�t�a�r�������&Export��� PEMainWindow��� �&�D�o�s�y�a�������&File��� PEMainWindow����<�b�r�/�>�<�b�r�/�>�B�u�,� �e�l�e�m�a�n� �d��z�e�n�l�e�y�i�c�i�n�i�n� �d�i�e�r� �s��r��m��n�d�e� �b�i�r� �p�r�o�b�l�e�m�e� �n�e�d�e�n� �o�l�m�a�y�a�c�a�k�t1�r�,� �������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowF'Aile'yi oalt zelliine izin yok,A duplicate 'family' property is not allowed PEMainWindowH'Trev''i oalt zelliine izin yok-A duplicate 'variant' property is not allowed PEMainWindow"%1 konnektr ekleAdd %1 connectors PEMainWindowKonnektr ekle Add connector PEMainWindowJ'%1''den '%2''ye bir i balant1 ekle)Add internal connection from '%1' to '%2' PEMainWindow$Bo_luk b1rak1lamazBlank not allowed PEMainWindow 0ptalCancel PEMainWindow %1'i %2'ye evirChange %1 to %2 PEMainWindow"%1 %2'ye dei_tirChange %1 to '%2' PEMainWindow0Tm konnektr %1'e evirChange all connectors to %1 PEMainWindow0%1 konnektrn dei_tirChange connector %1 PEMainWindow&A1klamay1 dei_tirChange description PEMainWindow(zellikleri dei_tirChange properties PEMainWindow&Etiketleri dei_tir Change tags PEMainWindow%1'e dei_tir Change to %1 PEMainWindowKaydetmeden 1kClose without saving PEMainWindow Kaydetmeden 1k?Close without saving? PEMainWindowKonnektrler Connectors PEMainWindow*Konnektrler GrnmConnectors View PEMainWindow&Dn_trme problemiConversion problem PEMainWindow$Kopyalama problemi Copy problem PEMainWindowal1_maya devam etmek istiyor musunuz yoksa kaydetmeden 1kacak m1s1n1z?4Do you want to keep working or close without saving? PEMainWindowx"%1"'de yapt11n1z dei_iklikleri kaydetmek istiyor musunuz?:Do you want to save the changes you made in the part "%1"? PEMainWindow4'Aile'yi oaltma izni yok'Duplicate 'family' property not allowed PEMainWindow2'Trev' oaltma izni yok(Duplicate 'variant' property not allowed PEMainWindow"oaltma problemiDuplicate problem PEMainWindowAtamalar1 daha sonra bitirmeye hat1rlarsan1z, _imdi Eleman Dzenleyici'den 1kabilirsiniz.^Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMainWindow$Yaz1m KarakterleriFonts PEMainWindowBFritzin (Yeni) Eleman DzenleyiciFritzing (New) Parts Editor PEMainWindow Fritzing _u anda yaln1zca OCRA ve Droid yaz1 karakterlerini destekliyor--'%1'.iindeki yaz1 karakterleri yerine bunlar kullan1lm1_t1rkFritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' PEMainWindowKk ResimIcon PEMainWindow(Kr Resim Grnm Icon View PEMainWindowEer breadboard grnmnde ya da konnektr stverisinde herhangi bir dei_iklik yaparsan1z, ayaklar bir daha al1_mayabilir. cIf you make changes to breadboard view, or change connector metadata, the legs may no longer work.  PEMainWindow>Resim & Ayakizi Dosyalar1 (%1 %2 %3 %4 %5);;SVG Dosyalar1 (%1);;JPEG Dosyalar1 (%2);;PNG Dosyalar1(%3);;gEDA Ayakizi Dosyalar1 (%4);;Kicad Modl Dosyalar1 (%5)Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) PEMainWindowResim Dosyalar1 (%1 %2 %3);;SVG Dosyalar1 (%1);;JPEG Dosyalar1 (%2);;PNG Dosyalar1(%3)%4%5KImage Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 PEMainWindowDenetleyici Inspector PEMainWindowP0 balant1lar olduka berbat (kar1_1k).(Internal connections are very messed up. PEMainWindow$al1_maya devam et Keep working PEMainWindowKatmanlarLayers PEMainWindow6Grnm iin resmi ykle...Load image for view... PEMainWindowEleman1n bir kopyas1n1 yap ve onu 'Benim Elemanlar1m' bin dosyas1n1n iine kaydet9Make a copy of the part and save it in the 'My Parts' Bin PEMainWindow.Sadece %1'i grnr yapMake only %1 view visible PEMainWindowDSadece bu grnm grnebilir yapMake only this view visible PEMainWindowstveriMetadata PEMainWindow stveri Grnm Metadata View PEMainWindow4U noktas1n1 hareket ettirMove terminal point PEMainWindowzgn olmal1Must be unique PEMainWindowhMasastnde, mevcut svg dosyas1n1 ieren klasr a.@On the desktop, open the folder containing the current svg file. PEMainWindowResmi A Open Image PEMainWindowEleman1n bu grnmdeki resmi olarak kullanmak iin bir dosya a1n.:Open a file to use as the image for this view of the part. PEMainWindowPNG ve JPG dosyalar1 bitmap olan doalar1n1 kaybetmiyorlar ve leklendirildiklerinde gzel grnmyorlar--TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindow$Eleman Dzenleyici Parts Editor PEMainWindowLtfen SVG dosyas1n1 ilgili ayar1 kullanarak tekrar d1_a aktar1n ve daha sonra tekrar yklemeyi deneyin.HPlease re-export the SVG file using that setting, and try loading again. PEMainWindow@%1 konnektrn tekrar yerle_tirRelocate connector %1 PEMainWindow0%1 konnektrlerini 1karRemove %1 connectors PEMainWindow,0 Balant1y1 0ptal EtRemove Internal Connection PEMainWindow"Konnektr 1kartRemove connector PEMainWindow8'%1' den i balant1y1 1kar$Remove internal connection from '%1' PEMainWindowBBask1 Devre resmini tekrar kullanReuse PCB image PEMainWindow@Breadboard resmini tekrar kullanReuse breadboard image PEMainWindow6^ematik resmi tekrar kullanReuse schematic image PEMainWindow\Bask1 Devre resmini bu grnmde tekrar kullan Reuse the PCB image in this view PEMainWindowZBreadboard resmini bu grnmde tekrar kullan'Reuse the breadboard image in this view PEMainWindowP^ematik resmi bu grnmde tekrar kullan&Reuse the schematic image in this view PEMainWindowSVG problemi SVG problem PEMainWindow KaydetSave PEMainWindow'%1''i Kaydet Save "%1" PEMainWindow2Yeni eleman olarak kaydetSave as new part PEMainWindowBu eleman1 kaydetmek izimde telafi edilemeyecek bir dei_iklie yol aacakt1r.HSaving this part will make a change to the sketch that cannot be undone. PEMainWindowBu eleman1 kaydetmek bu izimlerde telafisi olmayan dei_ikliklere yol aacakt1r.LSaving this part will make a change to these sketches that cannot be undone. PEMainWindowySee this explanation. PEMainWindow(Konnektrleri GsterShow Connectors PEMainWindow$Kk Resmi Gster Show Icon PEMainWindow stveriyi Gster Show Metadata PEMainWindowKlasrde GsterShow in Folder PEMainWindow\Konnektr stverisini liste grnmnde gster*Show the connector metadata in a list view PEMainWindow:Kk resim grnmn gsterShow the icon view PEMainWindow2stveri grnmn gsterShow the metadata view PEMainWindow2izim Dei_iklii Uyar1s1Sketch Change Warning PEMainWindowBu nedenle dzenleme uygun olmayan bir Bask1 Devre resminin olu_mas1na neden olabilir0So editing may produce an invalid PCB view image PEMainWindow@'Aile' zellii bo_ b1rak1lamaz.'The 'family' property can not be blank. PEMainWindow'%1' SVG dosyas1 CorelDRAW'dan 'tan1t1m ayarlar1' ayarlanmadan aktar1lm1_ grnyor.nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindowA1k olan izim '%1' _u an da dzenlemekte olduunuz eleman1 iermekte. 4The open sketch '%1' uses the part you are editing.  PEMainWindowA1k izimler The open sketches  PEMainWindownEleman yaln1zca bu grnmde simge olarak grlebilecek8The part will only be visible in this view and icon view PEMainWindow:%1'in deeri bo_ b1rak1lamaz.#The value of '%1' can not be blank. PEMainWindowH%1'de tan1ml1 bir bak1r katman yok. +There are no copper layers defined in: %1.  PEMainWindowNHala ask1da olan son bir dzenleme var.%There is one last edit still pending. PEMainWindowJBu eleman olduu gibi kaydedilemez: #This part can not be saved as-is:  PEMainWindowPBu eleman1n %n atanmam1_ konnektr var 'This part has %n unassigned connectors  PEMainWindow@Bu eleman1n esnek ayaklar1 var. This part has bendable legs.  PEMainWindowEleman Dzenleyecinin bu srm henz esnek ayaklar1 desteklemiyor ve ayaklar breadboard grnmnde doru olarak gsterilemeyebilir . This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindowEleman Dzenleyicinin bu srm '%1''deki ayr1k bak1r0 ve bak1r1 katmanlar1n1 desteklemiyor. dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindowdBu uyar1 Fritzing'in bu blmnde tekrarlanmayacak=This warning will not be repeated in this session of Fritzing PEMainWindowYeni bir konnektr olu_turulam1yor--yeniden ba_laman1z gerekebilir.;Unable to create new connector--you may have to start over. PEMainWindow"'%1' yklenemiyorUnable to load '%1' PEMainWindow'%1' yklenemiyor.Ltfen eleman dzenleyiciyi kaydetmeden kapat1p tekrar deneyin.PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindow.fzp %1'den yklenemiyorUnable to load fzp from %1 PEMainWindow>Resim dosyas1 '%1' yklenemiyorUnable to load image file '%1' PEMainWindowH'%1' resim doyas1 yklenemiyor:, %2$Unable to load image file '%1': %2 PEMainWindowJ'%1''in yerel bir kopyas1 yap1lam1yor$Unable to make a local copy of: '%1' PEMainWindow&'%1' zmlenemiyorUnable to parse '%1' PEMainWindowN'%1'zmlenemiyor:%2 sat1r:%3 stun:%4*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindow>%1 fzp dosyas1 ayr1_t1r1lam1yorUnable to parse fzp file %1 PEMainWindow*Svg %1'e yaz1lam1yorUnable to write svg to %1 PEMainWindowTm balant1lar SVG nesnesine atanana kadar eleman doru olarak al1_mayacak. UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindow<PNG ve JPG kullan1m1 nerilmezUse of PNG and JPG discouraged PEMainWindowdTrev '%1' kullan1mda. Trev'in ismi zgn olmal1.8Variant '%1' is in use. The variant name must be unique. PEMainWindowSorunsuz bir _ekilde ^ematik ya da Bask1 Devre grnm iin dei_iklik yapabilirsiniz. 7You can safely make changes to Schematic or PCB view.  PEMainWindowEleman1n1z1 in_a etmek iin PNG ve JPG resimlerini kullanabilirsiniz ancak bir SVG kullanmak daha iyi olacakt1r. WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindowfDei_iklikleriniz onlar1 kaydetmezseniz kaybolacak.1Your changes will be lost if you don't save them. PEMainWindow,%n grnm genelinde. across %n views.  PEMainWindowve '%1'  and '%1'  PEMainWindowancak _imdi ltfen dosyay1 linkteki ynergeleri kullanarak modifiye edin.Mbut for now please modify the file according to the instructions in the link. PEMainWindowR%1'de bir herhangi bir ayakizi bulunamad1no footprints found in %1 PEMainWindowJ%1'de bir herhangi _ematik bulunamad1no schematics found in %1 PEMainWindow_ematik eleman1schematic part PEMainWindowbu nedenle Fritzing elemanlar1 iin PNG ve JPG'yi yaln1zca tutucu olarak kullanmak en iyisi olacakt1r.Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindowisimsiz eleman untitled part PEMainWindow YazarAuthorPEMetadataView TarihDatePEMetadataViewA1klama DescriptionPEMetadataViewAileFamilyPEMetadataView EtiketLabelPEMetadataViewzellikler PropertiesPEMetadataViewNVarsay1lan eleman etiket nekini ayarla!Set the default part label prefixPEMetadataView0Eleman1n yazar1n1 ayarlaSet the part's authorPEMetadataView0Eleman1n tarihini ayarlaSet the part's datePEMetadataViewElemanla igili a1klamay1 dzenle--basit html kullanabilirsiniz.(Qt'nin Rich Text'inde tan1mland11 gibi)RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataView~Elaman1n ailesini belirle--hangi elemanlar1n bu elemanla ilgili?Set the part's family--what other parts is this part related toPEMetadataView<Eleman1n zelliklerini belirleSet the part's propertiesPEMetadataView2Eleman1n knyesini ayarlaSet the part's tagsPEMetadataView4Eleman1n ba_l11n1 dzenleSet the part's titlePEMetadataViewEer eleman bir web sitesi zerinden tan1mland1ysa onun url'sini ayarla3Set the part's url if it is described on a web pagePEMetadataViewEleman1n trevlerini belirle--bu eleman ayn1 ailedeki dier elemanlara gre daha zgn k1lacakt1rTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewKnyelerTagsPEMetadataViewdBuras1 eleman iin stveriyi dzenlediiniz yer...4This is where you edit the metadata for the part ...PEMetadataView Ba_l1kTitlePEMetadataView TrevVariantPEMetadataViewykseklik:height: PESvgViewgeni_lik:width: PESvgViewT<font renk='siyah'>Srkleme a1ld1</font>+Dragging enabled PEToolViewX<font renk='gri'>Srkleme engellendi</font>+Dragging disabled PEToolView MerkezCenter PEToolViewKonnektr %1 Connector %1 PEToolViewKonnektr Listesi (tik at1lm1_ k1s1mlar grafiin seili olduunu belirtiyor);Connector List (a checkmark means the graphic was selected) PEToolViewhKonnektrn u noktalar1n1 ayarlamak iin gereken kontroller. U noktas1 bir kablonun konnektre balanaca1 noktad1r. Ayr1ca mevcut konnektrn hedef i_aretini srkleyebilirsinizControls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector PEToolView(Srekleme engellendiDragging disabled PEToolViewTU noktas1n1n x-koordinat1n1 modifiye eder/Modifies the x-coordinate of the terminal point PEToolViewTU noktas1n1n y-koordinat1n1 modifiye eder/Modifies the y-coordinate of the terminal point PEToolViewGrafii seSelect graphic PEToolView,0 Balant1lar1 AyarlaSet Internal Connections PEToolViewBu kontrol kutusunu i balant1lar1 kablolar izerek dzenlemek iin belirle?Set this checkbox to edit internal connections by drawing wires PEToolViewLKonnektrn u noktas1n1 %1'e ayarlar.*Sets the connector's terminal point to %1. PEToolView8Mevcut konnektre atamak istediiniz SVG nesnesini gezdirebilmek iin imle konumunu ve fare tekerleiini kullan1n ,sonra onu semek iin fareyi a_a1 itin.Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. PEToolView merkezcenter PEToolViewdoueast PEToolView kuzeynorth PEToolView gneysouth PEToolViewbat1west PEToolView merkezcenterPad bala connect toPaddoueastPad kuzeynorthPad _ekilshapePad gneysouthPadbat1westPad0Pin Etiketlerini DzenleEdit Pin Labels PaletteItemDelik ap1 Hole Diameter PaletteItem^Etiket uyumsuzluu. Kaydedilen hibir _ey yok.#Label mismatch. Nothing was saved. PaletteItemYzk Kal1nl11Ring Thickness PaletteItempDevam edilemiyor;konnektrlerin standard kimlikleri yok.;Unable to proceed; part connectors do no have standard IDs. PaletteItemZDevam edilemiyor; stten grnm bulunam1yor.1Unable to proceed; unable to find top level view. PaletteItem geli_mi_ ayarlaradvanced settings PaletteItemdelik boyutu hole size PaletteIteminin PaletteItem Deerleri GsterDisplay Values PartLabel0Etiket metnini grntleDisplay the text of the label PartLabel<%1 zelliinin deerini gster Display the value of property %1 PartLabelDzenleEdit PartLabel,Etiket metnini dzenleEdit label text PartLabelYatay evirFlip Horizontal PartLabelDikey evir Flip Vertical PartLabel&Etiketi yatay evirFlip label horizontally PartLabel&Etiketi dikey evirFlip label vertically PartLabelKayd1r/Dndr Flip/Rotate PartLabelKarakter boyutu Font Size PartLabel GizleHide PartLabel,Eleman etiketini gizleHide part label PartLabelEtiket metni Label text PartLabelEtiket metni: Label text: PartLabel BykLarge PartLabelOrtaMedium PartLabelLSaat ynnde 135 derece dndr {135?}Rotate 135� Clockwise PartLabelZSaat ynnn tersine 45 derece dndr {135?}Rotate 135� Counter Clockwise PartLabel2180 derece dndr {180?} Rotate 180� PartLabelJSaat ynnde 135 derece dndr {45?}Rotate 45� Clockwise PartLabelXSaat ynnn tersine 45 derece dndr {45?}Rotate 45� Counter Clockwise PartLabelJSaat ynnde 135 derece dndr {90?}Rotate 90� Clockwise PartLabelXSaat ynnn tersine 45 derece dndr {90?}Rotate 90� Counter Clockwise PartLabelfMevcut seimi saat ynnn tersine 90 derece dndr5Rotate current selection 90 degrees counter clockwise PartLabelLEtiketi saat ynnde 135 derece dndr)Rotate the label by 135 degrees clockwise PartLabel\Etiketi saat ynnn tersine 135 derece dndr1Rotate the label by 135 degrees counter clockwise PartLabel2Etiketi 180 derece dndrRotate the label by 180 degrees PartLabelJEtiketi saat ynnde 45 derece dndr(Rotate the label by 45 degrees clockwise PartLabelZEtiketi saat ynnn tersine 45 derece dndr0Rotate the label by 45 degrees counter clockwise PartLabelJEtiketi saat ynnde 90 derece dndr(Rotate the label by 90 degrees clockwise PartLabel2Karakterleri byk ayarlaSet font size to large PartLabel>Karakter bykln orta yarlaSet font size to medium PartLabel<Karakter boyutunu kk ayarlaSet font size to small PartLabelDKarakter boyutunu ok kk ayarlaSet font size to tiny PartLabel*%1 iin etiket ayarlaSet label for %1 PartLabel KkSmall PartLabelok kkTiny PartLabel Bin k1sm1na ekle Add to binPartsBinPaletteWidget 0ptalCancelPartsBinPaletteWidget.%1 dosyas1 bulunam1yor.Cannot find file %1.PartsBinPaletteWidget$%1 okunam1yor: %2.Cannot read file %1: %2.PartsBinPaletteWidget2Simge rengini dei_tir...Change icon color...PartsBinPaletteWidgetLBu bin iin simgenin rengini dei_tir.*Change the color of the icon for this bin.PartsBinPaletteWidgetrGerekten seili eleman1 bin'e kaydetmek istiyor musunuz?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetBin "%1"'de yapt11n1z dei_iklikleri kaydetmek istiyor musunuz?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetKaydetme Don't SavePartsBinPaletteWidget4Fritzing Bin Dosyas1 (*%1)Fritzing Bin (*%1)PartsBinPaletteWidgetYkleniyor... Loading...PartsBinPaletteWidget KaydetSavePartsBinPaletteWidget"Bin "%1"'i kaydet Save bin "%1"PartsBinPaletteWidget4Bu simge iin bir renk seSelect a color for this iconPartsBinPaletteWidget,Bir dosya ad1 belirtinSpecify a file namePartsBinPaletteWidgetBa_l1ks1z Bin Untitled BinPartsBinPaletteWidgetpEer dei_ikliklerinizi kaydetmezseniz kaybolacaklard1r.1Your changes will be lost if you don't save them.PartsBinPaletteWidget&bin '%1' ykleniyorloading bin '%1'PartsBinPaletteWidget 0ptalCancel Perfboard$Performans Uyar1s1Performance Warning Perfboard`Yakla_1k 2000'den fazla delie sahip performans board'u ya da delikli plaket'in performans1 yava_ olabilir. Emin misiniz ? Not:Bu uyar1 bu blm boyunca tekrar edilmeyecektir.Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard"Yeni boyut ayarla Set new size Perfboardstunlarcolumns Perfboardsat1rlarrows Perfboard*board boyutunu ayarlaset board size Perfboard boyutsize PerfboardL<p><h2>Pin Etiket Dzenleyici</h2></p>

    Pin Label Editor

    PinLabelDialog<p>Pini yeniden adland1rmak iin pin numaras1n1n yan1ndaki metne t1klay1n.<

    Click on a label next to a pin number to rename that pin.PinLabelDialog 0ptalCancelPinLabelDialogTekrardan YapRedoPinLabelDialog KaydetSavePinLabelDialogGeri evirUndoPinLabelDialogEtiketler aras1nda s1ral1 olarak ilerlemek iin tab tu_unu kullanabilirsiniz.</p>@You can use the tab key to move through the labels in order.

    PinLabelDialog<%1 (Dei_tirmek iin t1kla...)%1 (click to change...) PrefsDialog,Otomatik olarak kaydetAutosave PrefsDialogBOtomatik olarak kaydetme s1kl11:Autosave every: PrefsDialog 0ptalCancel PrefsDialogXFare Tekerleinin Nas1l Davranaca1n1 AyarlaChange Wheel Behavior PrefsDialog Ayarlar1 TemizleClear Settings PrefsDialogRenklerColors PrefsDialog KomutCommand PrefsDialogBalanm1_ VurguConnected Highlight PrefsDialogKontrolControl PrefsDialogBEri kablolar dz kablolara kar_1Curvy vs. straight wires PrefsDialog GenelGeneral PrefsDialogDilLanguage PrefsDialog0Fare Tekerlei Davran1_1Mouse Wheel Behavior PrefsDialog TamamOK PrefsDialog\%1 iin bir programc1 (yrtlebilir/.exe) se'Select a programmer (executable) for %1 PrefsDialogRBu kontrol kutusu varsay1lan davran1_1 ayarlar. Srklerken kontrol(Ctrl) tu_una bas1l1 tutarak (Maclerde:Kommut tu_u(Command)) normal ayarlar1n1za dn_ yapabilirsiniz.This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialog"Balanmam1_ VurguUnconnected Highlight PrefsDialogFareyi a_a1ya doru itip bir kablo ya da bir eleman1n aya1 zerinde srklediinizde (bir konnektr ya da bir esnetme noktas1na kar_1n) kablonun (ya da aya1n) eriliini dei_tirmek ya da yeni bir esnetme noktas1 srklemek ister misiniz?When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialog dakikaminutes PrefsDialogsay1 tu_lar1ndan a_a1 = ilerle shift tu_u ilerleme eksenini dei_tirir Alt ya da %1 tu_u = yak1nla_t1rFno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialogsay1 tu_lar1ndan a_a1 = yak1nla_t1r Alt ya da %1 tu_u = ilerle shift tu_u ilerleme eksenini dei_tirirFno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialogf"%1"'i izimden 1karmak istediinize emin misiniz?5Are you sure you want to remove "%1" from the sketch? ProgramTabKod (* %1) Code (*.%1) ProgramTabbFritzing '%1''i bulam1yor, ltfen onu yerle_tirin1Fritzing is unable to find '%1', please locate it ProgramTabYeniNew ProgramTab"%1"'i 1kar? Remove "%1"? ProgramTab KaydetSave ProgramTabNYklemek iin bir program dosyas1 seinSelect a program file to load ProgramTab&Kod&Code ProgramWindow&Kopyala&Copy ProgramWindow&Kes&Cut ProgramWindow"&Dzenle/Dei_tir&Edit ProgramWindow&Yap1_t1r&Paste ProgramWindow&Tercihler...&Preferences... ProgramWindow&Tmn Se &Select All ProgramWindow&Gster&View ProgramWindowKod Penceresi Code Window ProgramWindow$Kod Penceresi - %1Code Window - %1 ProgramWindowSeimi kopyalaCopy selection ProgramWindowSeimi kes Cut selection ProgramWindow'%1' dosyas1 .fzz dosyas1ndan restore edilmi_; harici bir dzenleyici ile al1_mak iin yerel bir kopya kaydedin.]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindow'%1' dosyas1 .fzz dosyas1ndan restore edilmi_; yerel kopya bulunamad1.HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindow2Panodaki geleri yap1_t1rPaste clipboard contents ProgramWindowTekrardan YapRedo ProgramWindowTm metni seSelect all text ProgramWindowBUygulama ile ilgili kutuyu gster Show the application's about box ProgramWindowGeri evirUndo ProgramWindow%1 Katman1%1 LayerQObjectN%1 katman1 d1_a aktar1m1 bo_ (durum 2)."%1 layer export is empty (case 2).QObject8%1 katman d1_a aktar1m1 bo_.%1 layer export is empty.QObjectD%1 katman1: '%2''ye kaydedilemiyor %1 layer: unable to save to '%2'QObject>%1 mask d1_a aktar1m hatas1 (2)%1 mask export failure (2)QObjectl%1 kablo kaydedilmi_ %2 yerlerinden hareket ettirildi./%1 wires moved from their saved position in %2.QObject <b>A1klama:</b>Description:QObject<b>0sim:</b> Name:QObject<b>kimlik:</b> id:QObject<b>tip:</b> type:QObject<font yz='Lucida Grande, Tahoma, Sans Serif' boyut='2' renk='#eaf4ed'>&#169; 2007-%1 Potsdam Yksekokulu</font>t© 2007-%1 Fachhochschule PotsdamQObject0Oto-Ynlendirme Ayarlar1Autorouter SettingsQObject TemelBasicQObject&Breadboard GrnmBreadboard ViewQObject0lerlet Bring forwardQObjectne 1karBring to frontQObjectOto-ynlendirilemiyor: herhangi bir board bulunamad1 (ya da birden fazla var)5Cannot autoroute: no board (or multiple boards) foundQObject$%1 okunam1yor: %2.Cannot read file %1: %2.QObjectTDosya geici olarak yaz1lam1yor: %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObject:%1,%2'nin ayaklar1n1 dei_tirChange leg of %1,%2QObject.Gncellemeri kontrol etCheck for updatesQObject Ayarlar1 TemizleClear SettingsQObjectzKaydetilmi_ tm ayarlar1 temizle ve bu diyalou acilen kapat.;Clear all saved settings and close this dialog immediately.QObject*Balanm1_ vurgu rengiConnected highlight colorQObjectBalant1 ConnectionQObject<Geiti Esnetme Noktas1na evirConvert Via to BendpointQObjectGeite evirConvert to ViaQObjectBak1r Alt Copper BottomQObjectAlt Bak1r HatCopper Bottom TraceQObjectAlt Bak1r DolguCopper Fill BottomQObjectst Bak1r DolguCopper Fill TopQObjectBak1r st Copper TopQObjectst Bak1r HatCopper Top TraceQObject%1'i KopyalamaCopying file %1QObjectLink'i dzenle Edit linkQObject<%1: %2 dosyas1n1 okuma hatas1.Error reading file %1: %2.QObjectJ%1 zaten mevcut: stne yaz1lamayacak/File %1 already exists: it won't be overwrittenQObject$Dosya 0lerliyor...File Progress...QObjectereveFrameQObjectHFritzing eleman bin'ini ykleyemiyor"Fritzing cannot load the parts binQObjectzFritzing bu zel Bask1 Devre _eklindeki kesikleri i_leyemez. DFritzing is unable to process the cutouts in this custom PCB shape. QObjectFritzing kesikleri vektr grafik dzenleyicinizdeki _ekil '1karma' ya da 'fark' i_lemleriyle yapman1z1 gerektiriyor.}Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor.QObject:Toprak Dolgu Tane DzenleyiciGround Fill Seed EditorQObject IC'lerICsQObject SimgeIconQObjectSimge Grnm Icon ViewQObject Giri_InputQObject0 Balant1larInternal ConnectionsQObject&Kablolar1 Birle_tir Join WireQObjectMikroi_lemciMicrocontrollerQObjecttYnlendirmek iin bir balant1 (Bask1 Devre zerinde) yok.%No connections (on the PCB) to route.QObject>Ynlendirmek iin balant1 yok.No connections to route.QObject2Hibir eleman bulunamad1.No parts found.QObject NotlarNotesQObjectHop!Oops!QObject DierOtherQObject 1k1_OutputQObject(Bask1 Devre GrnmPCB ViewQObject Altl1kPadQObject\zmleme hatas1 (1) sat1r %1, stun %2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObject\zmleme hatas1 (2) sat1r %1, stun %2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObject ElemanPartQObjectEleman %1 '%2' Part %1 '%2'QObjectEleman Resmi Part ImageQObject"Eleman Etiketleri Part LabelsQObject.Eleman zaten bin'de varPart already in binQObjectElemanlarPartsQObject:Elemanlar klasr bulunamad1.Parts folder not found.QObject,Pin Etiket DzenleyiciPin Label EditorQObjectDil seiminizin Fritzing'i bir dahaki a1_1n1za kadar etkili olmayaca1n1 hat1rlatmak isteriz.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectGPowerQObjectTercihler PreferencesQObject YumakRatsnestQObjectYumak kablolarRatsnest wiresQObjectCetvellerRulersQObject^ematik GrnmSchematic ViewQObject%1'i se Select %1QObjectTm %1'i se Select all %1QObjectRTm "Oto-Ynlendirme Yapma" Hatlar1n1 Se#Select all 'Don't autoroute' tracesQObjectHTm Oto-Ynledirilebilir Hatlar1 SeSelect all autorouteable tracesQObject*Kilitli paralar1 seSelect locked partsQObject8Zaman1 gemi_ elemanlar1 seSelect outdated partsQObjectGerilet Send backwardQObjectSensrlerSensorsQObject4Izgaran1n S1kl11n1 Ayarla Set Grid SizeQObject4Toprak Dolgu Tanesi AyarlaSet Ground Fill SeedQObjectTmn ayarla: Set all to:QObject@Konnektr'n a1klamas1n1 ayarla Set the connectors's descriptionQObject8Konnektrn ba_l11n1 ayarlaSet the connectors's titleQObjectKalkanlarShieldsQObjectSerigrafi AltSilkscreen BottomQObjectBSerigrafi Alt (Eleman Etiketleri)Silkscreen Bottom (Part Labels)QObjectst SerigrafiSilkscreen TopQObjectBst Serigrafi (Eleman Etiketleri)Silkscreen Top (Part Labels)QObjectzr dileriz, Fritzing henz ayn1 anda hem pin hem de altl1klar1n stesinden gelemiyor (%1'de %2'de)JSorry, Fritzing can't yet handle both pins and pads together (in %1 in %2)QObjectzr dileriz, Fritzing henz ayn1 anda hem pin hem de altl1klar1n stesinden gelemiyor (%1'de)DSorry, Fritzing can't yet handle both pins and pads together (in %1)QObjectpzr dileriz, %1 trnde altl11n stesinden gelinemiyorSorry, can't handle pad type %1QObjectzr dileriz takas mekanizmam1zda bir problem var. Fritzing hala al1_1yor ancak eleman1n zelliklerini dei_tiremeyeceksiniz.}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectKabloyu Bl Split WireQObject MetinTextQObjectT%1 dosyas1 bir Fritzing dosyas1 (2) deil.'The file %1 is not a Fritzing file (2).QObjectT%1 dosyas1 bir Fritzing dosyas1 (3) deil.'The file %1 is not a Fritzing file (3).QObjectT%1 dosyas1 bir Fritzing dosyas1 (4) deil.'The file %1 is not a Fritzing file (4).QObject|'%1' dosyas1 salt okunur; ltfen ba_ka bir dosya ad1 kullan1n.altl1k _ekil dei_kenleri eksikpad shape missing paramsQObject8altl1k _ekil boyutu geersizpad shape size is invalidQObject,%1 de zmleme hatas1parse failure in %1QObject<mask katman(lar)1n1 yap1_t1r, paste mask layer(s), QObjectbask1 devrepcbQObject(bask1 devre grnmpcb viewQObject:pozisyonun dei_kenleri eksikposition missing paramsQObject_emaschemQObjectj%1 _ematii %2'de beklenmedik _ekilde (1) sonlan1yor (schematic %1 unexpectedly ends (1) in %2QObjectj%1 _ematii %2'de beklenmedik _ekilde (2) sonlan1yor (schematic %1 unexpectedly ends (2) in %2QObjectj%1 _ematii %2'de beklenmedik _ekilde (3) sonlan1yor (schematic %1 unexpectedly ends (3) in %2QObjectF%1 _ematik eleman1 %2'de bulunamad1!schematic part %1 not found in %2QObject _ematik grnmschematic viewQObject4_eklin deltas1 uygulanmad1shape delta not implementedQObject8serigraf d1_a aktar1m hatas1silk export failureQObjectRserigraf katman1 %1 'in d1_a aktar1m1 bo_silk layer %1 export is emptyQObject.serigrafi katman(lar), silkscreen layer(s), QObject$board d1_ katman, the board outline layer, QObject6yamuk altl1klar uygulanmad1 trapezoidal pads not implementedQObject8'%1' '%2''ye kopyalanam1yor.!unable to copy file '%1' to '%2'.QObjectZ%1 _eklindeki altl11n stesinden gelinemiyorunable to handle pad shape %1QObject%1 a1lam1yorunable to open %1QObject"%1 zmlenemiyorunable to parse %1QObject,beklenmedik dosya sonuunexpected end of fileQObjecth%2 dosyas1ndaki %1 ayakizinde beklenmedik dosya sonu1unexpected end of file in footprint %1 in file %2QObjectD%2 den %1 de beklenmedik biim (1)#unexpected format (1) in %1 from %2QObjectcretlendirme ile ilgili daha fazla bilgi iin <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a> 'i ziyaret edin.rFor more information on pricing see http://fab.fritzing.org/pricing. QuoteDialog&Engelle&IgnoreRecoveryDialog&Kurtar&RecoverRecoveryDialog<p><b>Fritzing km_ olabilir ancak ilgili dosyalardaki baz1 dei_iklikler kurtar1labilir.</b></p><p>Yedeklenen her dosyan1n tarih ve saati grntlenir.Dosya kaydedildiyse tarih ve saat'de kar_1la_t1rma iin listelenir.</p><p>Eer dosyay1 bir kere bile kaydettiyseniz o orijinal dosyalar halen diskinizde bulunmaktad1r.Ve orijinal dosyan1z1n kurtarma dosyas1n1 yklediyseniz onu zerine yazmak zere seebilirsiniz.</p><p><b>A_a1daki listeden kurtarmak istediiniz herhangi bir dosyay1 sein.</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialog DosyaFileRecoveryDialogSon yedekleme Last backupRecoveryDialogSon kaydedilen Last savedRecoveryDialog&dosya kaydedilmemi_file not savedRecoveryDialog DirenResistorResistorBir diren deeri yazabilirsiniz ya da t1kla ve d_r penceresinden seebilirsiniz. Biim P'nin bir 'umkMG' olduu nnn.dPtYou can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG'Resistordiren deeri resistanceResistor$Ana Defter (17x11)Ledger (17x11)ResizableBoardYasal (8.5x14)Legal (8.5x14)ResizableBoardMektup (8.5x11)Letter (8.5x11)ResizableBoard$Eski haline dndrRevertResizableBoard*S1k1_t1r1lm1_ (11x17)Tabloid (11x17)ResizableBoardzelcustomResizableBoardykseklik(mm) height(mm)ResizableBoardykseklik: %1mm height: %1mmResizableBoard&grnm oran1n1 tutkeep aspect ratioResizableBoard _ekilshapeResizableBoard boyutsizeResizableBoardgeni_lik(mm) width(mm)ResizableBoardgeni_lik: %1mm width: %1mmResizableBoardgeni_likwidthRuler TarihDateSchematicFrameDosya Ad1FilenameSchematicFrame ProjeProjectSchematicFrameRevizyonRevSchematicFrame SayfaSheetSchematicFrame tarihdateSchematicFrame'ninofSchematicFrame _ekilshapeSchematicFrame sayfasheetSchematicFrame4Etiketi %1'den %2'ye evirChange label from %1 to %2SchematicSketchWidget6Gerilimi %1'den %2'ye evirChange voltage from %1 to %2SchematicSketchWidget 0ptalCancelSetColorDialog8Bunu varsay1lan %1 rengi yapMake this the default %1 colorSetColorDialog TAMAMOKSetColorDialog%1 Not:Bu grnty fareyi durum ubuundaki ynlendirme durumu metni zerinde a_a1 kayd1rarak da tetikleyebilirsiniz.i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2 eleri %1 %2 items SketchWidget%1 etiketi '%2' %1 label '%2' SketchWidget%1 EkleAdd %1 SketchWidgetDei_tirChange SketchWidget8%1 rengini %2'den %3'e evirChange %1 color from %2 to %3 SketchWidget2%1'i %2'den %3'e dei_tirChange %1 from %2 to %3 SketchWidget4%1 etiketini '%2''ye evirChange %1 label to '%2' SketchWidget@%1 geni_liini %2'den %3'e evirChange %1 width from %2 to %3 SketchWidgetJDiren deerini %1'den %2'ye dei_tirChange Resistance from %1 to %2 SketchWidgetF%1 kablolar1n1n rengini %2'ye evirChange color of %1 wires to %2 SketchWidget6Resmi %1'den %2'ye dei_tirChange image from %1 to %2 SketchWidgetP%1 iin ayak esnetme noktas1n1 dei_tir.Change leg bendpoint for %1. SketchWidgetB%1 iin ayak eikliini dei_tir.Change leg curvature for %1. SketchWidgetN%1 kablolar1n1n geni_liini %2'ye evirChange width of %1 wires to %2 SketchWidget BalaConnect SketchWidget&%1 olu_tur ve balaCreate and connect %1 SketchWidget,Kablo olu_tur ve balaCreate and connect wire SketchWidget,Yumaktan kablo olu_turCreate wire from Ratsnest SketchWidgetYuma1 silDelete ratsnest SketchWidgetSemeyi B1rakDeselect SketchWidget(Tmn semeyi b1rak Deselect all SketchWidgetBalant1y1 Kes Disconnect SketchWidgetF%1'den tm kablo balant1lar1n1 kesDisconnect all wires from %1 SketchWidgetV%1 elerinden tm kablo balant1lar1n1 kes"Disconnect all wires from %1 items SketchWidgetift-t1k Double-click SketchWidgetVBu esnetme noktas1n1 silmek iin ift t1kla&Double-click to delete this bend point SketchWidget0Srkle ya da ift-t1klaDrag or double-click SketchWidget evirFlip SketchWidget %2'yi evir (%1) Flip %2 (%1) SketchWidget%2'yi ta_1 (%1) Move %2 (%1) SketchWidget,%2 elerini ta_1 (%1)Move %2 items (%1) SketchWidget&'%1' etiketini ta_1Move label '%1' SketchWidgetAya1n1 ta_1 Move leg of SketchWidget$Not metni dei_imiNote text change SketchWidget>'%1' eleman1 izimde bulunamad1Part '%1' not found in sketch SketchWidget.Notu Tekrar leklendir Resize Note SketchWidgetJBoard'u %1'e %2 tekrardan leklendirResize board to %1 %2 SketchWidgetDCetveli %1'e %2 tekrar leklendirResize ruler to %1 %2 SketchWidget DdrRotate SketchWidget"%2'yi Dndr (%1)Rotate %2 (%1) SketchWidget%1'i se Select %1 SketchWidget %1 elerini seSelect %1 items SketchWidgetTmn Se Select All SketchWidget Seim Selection SketchWidget:Ynlendirilmemi_ balant1 yok!There are no unrouted connections SketchWidgetBu katmanlar aras1 bir hat olu_turma giri_imi gibi grnyor. Bu durumlar ortaya 1kmamal1: ltfen geli_tiricilerle ileti_ime gein.~This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. SketchWidget8Ynlendirilmemi_ balant1larUnrouted connections SketchWidgetjYnlendirilmemi_ balant1lar sar1 ile vurgulanm1_t1r./Unrouted connections are highlighted in yellow. SketchWidget2pin etiketlerini dei_tirchange pin labels SketchWidget$ykleme tamamland1 done loading SketchWidget %1'denfrom %1 SketchWidget<%n eleman etiket(ler)ini gizlehide %n part label(s) SketchWidget eleman1 yklyor loading part SketchWidgetRya da paray1 srklemek iin alt-srkleor alt-drag to move the segment SketchWidget>%n eleman etiket(ler)ini gstershow %n part label(s) SketchWidget%1'eto %1 SketchWidgethattrace SketchWidget kablowire SketchWidgetb0lgili k1s1m iin takas mekanizmas1 devre d1_1: )The swapping mechanism is disabled for: SqliteReferenceModel$ve %1 dier elemanand %1 other partsSqliteReferenceModel&ve %1 dier zellikand %1 other propertiesSqliteReferenceModel'%2' kimlikli '%1' eleman1; muhtemelen harhangi bir 'aile' zellii olmad11 iin.Epart '%1' with id '%2'; possibly because it has no 'family' property.SqliteReferenceModel\'%3' kimlikli '%2' eleman1ndaki '%1' zellii.(property '%1' in part '%2' with id '%3'.SqliteReferenceModel %1 %n _erit(ler)%1 %n strip(s) StripboardKesCut StripboardOnar1ld1Restored Stripboardstunlarcolumns Stripboardsat1rlarrows StripboardA etiketleri Net labelsSymbolPaletteItem:A etiketleri bo_ b1rak1lamazNet labels cannot be blankSymbolPaletteItem etiketlabelSymbolPaletteItemgerilimvoltageSymbolPaletteItem0neriler ve Kurnazl1klarTips and Tricks TipsAndTricksT1kla a_a1 d_r'den se ya da %1 ile %2 aras1nda herhangi bir deer yaz;30@AL:0  %1Bulgarian - %1TranslatorListModel28B09AL:0 (A?@>I5=0)  %1Chinese (Simplified) - %1TranslatorListModel68B09AL:0 (B@048FV9=0)  %1Chinese (Traditional) - %1TranslatorListModel'5AL:0  %1 Czech - %1TranslatorListModel$V45@;0=4AL:0  %1 Dutch - %1TranslatorListModel=3;V9AL:0  %1 English - %1TranslatorListModelAB>=AL:0  %1 Estonian - %1TranslatorListModel$@0=FC7L:0  %1 French - %1TranslatorListModel 0;VAV9AL:0  %1 Galician - %1TranslatorListModelV<5FL:0  %1 German - %1TranslatorListModel@5FL:0  %1 Greek - %1TranslatorListModel2@8B  %1 Hebrew - %1TranslatorListModelV=4V  %1 Hindi - %1TranslatorListModel#3>@AL:0  %1Hungarian - %1TranslatorListModel$=4>=57V9AL:0  %1Indonesian - %1TranslatorListModelB0;V9AL:0  %1 Italian - %1TranslatorListModel/?>=AL:0  %1 Japanese - %1TranslatorListModel>@59AL:0  %1 Korean - %1TranslatorListModel0@0BEV  %1 Marathi - %1TranslatorListModel5@AL:0  %1 Persian - %1TranslatorListModel>;LAL:0  %1 Polish - %1TranslatorListModel@>@BC30;LAL:0 (1@078;LAL:0)  %1Portuguese (Brazilian) - %1TranslatorListModel@>@BC30;LAL:0 (T2@>?59AL:0)  %1Portuguese (European)- %1TranslatorListModel CC<=AL:0  %1 Romanian - %1TranslatorListModel >AV9AL:0  %1 Russian - %1TranslatorListModel!;>20FL:0  %1 Slovak - %1TranslatorListModel!;>25=AL:0  %1Slovenian - %1TranslatorListModelA?0=AL:0  %1 Spanish - %1TranslatorListModel(254AL:0  %1 Swedish - %1TranslatorListModel"09AL:0  %1 Thai - %1TranslatorListModel"C@5FL:0  %1 Turkish - %1TranslatorListModel#:@0W=AL:0  %1Ukrainian - %1TranslatorListModelb>289 ?@><V6=89 @5;V7 4>ABC?=89 4;O 7020=B065==O:3A new interim release is available for downloading: UpdateDialog`>289 >A=>2=89 @5;V7 4>ABC?=89 4;O 7020=B065==O:0A new main release is available for downloading: UpdateDialog5@52V@:0... Checking... UpdateDialog >B>2>Close UpdateDialog*5<0T =>2VH>W 25@AVW.No new versions found. UpdateDialogj0 60;L, =5 240;>AL >B@8<0B8 V=D>@<0FVN ?@> >=>2;5==O%Sorry, unable to retrieve update info UpdateDialogAV ?>@048All Tips WelcomeViewFritzing Fab  F5 ?@>AB0 B0 7@CG=0 ?>A;C30 7V AB2>@5==O ?@>D5AV9=8E 4@C:>20=8E ?;0B V7 20H8E =0@8AV2 Fritzing.kFritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. WelcomeView >28=8 Fritzing.Fritzing News. WelcomeView"@>5:B8 Fritzing.Fritzing Projects. WelcomeViewBB@8<09 A2V9 Creator Kit =5309=>.Get your Creator Kit now. WelcomeView>289 =0@8A New Sketch WelcomeView0ABC?=0 ?>@040Next Tip WelcomeView,5<0T >AB0==VE =0@8AV2No recent sketches found WelcomeViewV4:@8B8 =0@8A Open Sketch WelcomeView20<>28B8 4@C:>20=C ?;0BC.Order your PCB now. WelcomeViewAB0==V =0@8A8Recent Sketches WelcomeViewFritzing CreatorKit 4>72>;OT H284:>, ;53:> B0 @>72060NG8AL C2V9B8 4> A2VBC V=B5@0:B82=>W 5;5:B@>=V:8.uThe Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. WelcomeView>@040 4=O:Tip of the Day: WelcomeViewD5<0T 4>ABC?C 4> blog.fritzing.org!Unable to reach blog.fritzing.org WelcomeViewJ5<0T 4>ABC?C 4> friting.org/projects$Unable to reach friting.org/projects WelcomeView70<>28B8 >> order now >> WelcomeViewP283>B>28B8 20HC ?5@HC 4@C:>20=C ?;0BC >>produce your first pcb now >> WelcomeView!<C60AB89BandedWire G>@=89blackWire A8=V9blueWire1@C=0B=89brownWire :>;V@colorWire1;0:8B=89cyanWire*4C65 B>2AB89 (1,2 <<)extra thick (48 mil)Wire(4C65 B>=:89 (0,3 <<)extra thin (12 mil)Wire75;5=89greenWire AV@89greyWire1@C=0B=>-6>2B89ochreWire6>2B>30@OG89orangeWire@>65289pinkWireDV0;:>289purpleWireG5@2>=89redWire B8?>289 (0,6 <<)standard (24 mil)Wire$=04B>=:89 (0,2 <<)super fine (8 mil)Wire B>2AB89 (0,8 <<)thick (32 mil)WireB>=:89 (0,4 <<) thin (16 mil)Wire 1V;89whiteWire 6>2B89yellowWire ) , fritzing-app-0.9.2b/translations/fritzing_uk.ts000066400000000000000000017654701250202676700217550ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>GNU GPL v3 на код та CreativeCommons:BY-SA на решту <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Постдам</b> Fritzing is made by: Fritzing створено: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, професором Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Особлива подяка: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Michaela Vieser та Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, Дякуємо Kurt Badelt та Miguel Solis за переклад іспанською, to Gianluca Urgese for the Italian translation, Gianluca Urgese за переклад італійською, to Nuno Pessanha Santos for the Portuguese (European) translation, Nuno Pessanha Santos за переклад португальскою (європейською), to Yuelin and Ninjia for the Chinese (Simplified) translation, Yuelin and Ninjia за переклад китайською (спрощеною) to Hiroshi Suzuki for the Japanese translation, Hiroshi Suzuki за переклад японською, to Robert Lee for the Chinese (Traditional) translation, Robert Lee за переклад китайською (традиційною), to Vladimir Savinov for the Russian translation, Владіміру Савінову за переклад російською, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, Steven Noppe та Davy Uittenbogerd за переклад нідерландською, to Josef Dustira for the Czech translation, Josef Dustira за переклад чеською, to Jinbuhm Kim for the Korean translation, Jinbuhm Kim за переклад корейською, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, &#313;ubom&iacute;r Ducho&#328; за переклад словацькою, to Alexander Kaltsas for the Greek translation, Alexander Kaltsas за переклад грецькою, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, Lionel Michel, Yvan Kloster, Alexandre Dussart та Roald Baudoux за переклад французькою, to Cihan Mete Bahad&#x0131;r for the Turkish translation, Cihan Mete Bahad&#x0131;r за переклад турецькою, to Nikolay Stankov for the Bulgarian translation, Ніколаю Станкову за переклад болгарською, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. та Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes і Gabriel Ferreira за переклад португальською (бразильською). Fritzing is made possible with funding from the Створення Fritzing стало можливим завдяки фінансуванню MWFK Brandenburg, the sponsorship of the Design MWFK Brandenburg, підтримці дизайнерського Department of Bauhaus-University Weimar, факультету веймарського університету Баухаус, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, IxDS, безіменним дарувальникам, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. і завдяки кожній купівлі набору Fritzing Starter та друкованих плат Fritzing Fab. Special thanks goes out as well to all the students Окрема подяка всім студентам and alpha testers who were brave enough to give та альфа тестерам, які були досить хоробрими, щоб провести Fritzing a test spin. тестовий прогін Fritzing. <br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls керування збільшенням та видом Stop Now Зупинити негайно Best So Far Найкраще Cancel Скасувати Autorouter Routing canceled! Now cleaning up... Розведення скасовано! Прибирання... AutorouterSettingsDialog Production type Вид продукції homebrew саморобка professional фахова custom заданий Cancel Скасувати OK Гаразд Keepout Проміжок <b>Keepout</b> is the minimum distance between copper elements on different nets. <b>Проміжок</b> — це найменша відстань між мідними елементами ланцюжків. A keepout of 0.01 inch (0.254 mm) is a good default. Проміжок 0,254 мм (0,01 дюйм) є гарним по замовчанню. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Увага: маленький проміжок сповільнює виконання розведення та перевірку проектних норм. Trace width Ширина доріжки BinManager Parts Набір деталей BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty Керування набором::setDirtyTab: Неможливо задати набір '%1' як чорнетку BinManager::updateTitle: Couldn't set the bin '%1' as dirty Керування набором::updateTitle::Неможливо задати набір '%1' як чорнетку New bin (%1) Новий набір (%1) Select a Fritzing Parts Bin file to open Виберіть набір деталей Fritzing для відкривання Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Файл набору Fritzing (*%1 *%2);;Набір Fritzing (*%1);;Спільний набір Fritzing (*%2) Cannot set a NULL bin as the current one Неможливо задати пустий набір поточним Searching... Пошук... Bin Набір Import... Імпорт... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Завантажити деталь Fritzing (.fzpz), або набір деталей Fritzing (.fzb, .fzbz) New Bin... Новий набір... Create a new parts bin Створити новий набір деталей Close Bin Закрити набір Close parts bin Закрити набір деталей Delete Bin Видалити набір Delete parts bin Видалити набір деталей Save Bin Зберегти набір Save parts bin Зберегти набір деталей Save Bin As... Зберегти набір як... Save parts bin as... Зберегти набір деталей як... Export Bin... Експортувати набір... Save parts bin in compressed format... Зберегти набір деталей у стисненому вигляді... Rename Bin... Перейменувати набір... Rename parts bin... Перейменувати набір деталей... Copy to Sketch Перенести на схему Copy all the parts in the bin to a sketch Перенести всі деталі з набору на схему Copy all to Sketch Перенести все на схему Copy all loaded parts to the sketch Перенести всі завантажені деталі на схему Show Bin in List View У вигляді переліку Display parts as a list Показати набір деталей у вигляді переліку Show Bin in Icon View У вигляді значків Display parts as icons Показати набір деталей у вигляді значків Edit Part (new parts editor)... Змінити деталь (редактор деталей)... Export Part... Експортувати деталь... Remove Part Видалити деталь Find Part in Sketch Знайти деталь на схемі Delete bin Видалити набір Do you really want to delete bin '%1'? This action cannot be undone. Ви справді бажаєте видалити набір '%1'? Це неможливо відмінити. Read-only bin Набір лише для читання This bin cannot be renamed. Цей набір неможливо перейменувати. Rename bin Перейменувати набір Please choose a name for the bin: Будь ласка, введіть назву набору: Remove from Bin Видалити з набору Unable to remove part '%1'--it is in use in a sketch Не вдалось видалити деталь '%1' — вона використовується у схемі Remove from bin Видалити з набору Do you really want to remove '%1' from the bin? This operation cannot be undone. Ви справді бажаєте видалити '%1' з набору? Це неможливо віднмінити. Select a Fritzing File to Open Оберіть файл Fritzing для відкривання Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Файли Fritzing (*%1 *%2 *%3);; Деталь Fritzing (*%1);;Набір Fritzing (*%2);;Спільний набір Fritzing (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Користувацька плата у форматі SVG зазвичай містить один або два шари позначок, та один шар плати. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. Подивіться файл circle_pcb.svg у теці, де знаходиться Fritzing: parts/svg/core/pcb . one layer (single-sided) одношарова (одностороння) two layers (double-sided) двошарова (двостороння) image file файл зображення load image file завантажити файл зображення Images Зображення Select an image file to load Оберіть файл зображення для завантаження due to an xml problem: %1 line:%2 column:%3 через проблему з XML: %1 рядок: %2 колонка: %3 because the xml is not correctly formatted тому що xml сформовано неправильно the <board> element contains no shape elements елемент <плата> не містить обрису елементів because there are multiple <board> layers тому що є декілька шарів <плати> because there are multiple <silkscreen> layers тому що є декілька шарів <позначок> because there are multiple <silkscreen0> layers тому що є декілька шарів <позначок0> because there is no <board> layer тому що відсутній шар з <платою> the svg contains no shape elements SVG не містить обрисів елементів but the pcb itself will have no silkscreen layer але друкована плата не містить шару позначок the svg doesn't fit the custom board format SVG не відповідає формату користувацької плати <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> <b>Користувацький обрис було завантажено, і ви скоро побачите нову плату.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Перед виготовленням друкованої плати ми рекомендуємо перевірити створений обрис за допомогою опції 'Файл > Експорт для виготовлення > Extended Gerber'. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> Перевірте отриманий обрис плати за допомогою Gerber-переглядача, і переконайтесь, що все вийшло як очікувалось.<br/><br/> The rest of this message concerns 'cutouts'. Решта цього повідомлення стосується 'вирізів'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> Це кгруглі, або неправильної форми, отвори, які, за необхідності, можна додавати до розробленої друкованої плати.<br/><br/> <b>The custom shape has no cutouts.</b> <b>Розроблений обрис не містить вирізів.<b> <b>The custom shape has %n cutouts.</b> </b>Розроблений обрис містить %n виріз</b> </b>Розроблений обрис містить %n вирізи</b> </b>Розроблений обрис містить %n вирізів</b> <br/>However, the cutouts may not be formatted correctly. <br/>Проте, вирізи неможливо правильно сформувати. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, <br/><br/>Якщо ви хотіли додати вирізи до зробленого обрису, і не отримали бажаного результату, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. то це через те, що Fritzing для створення вирізів вимагає використовувати операції 'віднімання' або 'вирізання' у вашому редакторі векторної графіки. Unable to load Не вдалось завантажити Unable to load image from %1 %2 Не вдалось завантажити зображення з %1 %2 Can load, but Можна завантажити, але The image from %1 can be loaded, but %2 Use the file? Це зображення з %1 можна завантажити, але %2 Використовувати цей файл? BoardLogoItem shape обрис BreadboardLogoItem color колір Set text color Задати колір тексту Select text color Виберіть колір тексту Capacitor Select from the dropdown, or type in a %1 value Оберіть з випадного переліку, або введіть значення %1 ConnectorItem Add bendpoint Додати опорну точку Straighten curve Випрямити криву Remove bendpoint Видалити опорну точку ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools Знаряддя &About Про програму (&A) About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Вихід (&Q) Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. ППМ завершено. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. Ваш нарис готовий до виробництва: немає доріжок та отворів що перекриваються, або знаходяться надто близько одне до одного. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Червоним на платі підсвічено з’єднувачі та доріжки що можуть перекриватись, або знаходяться надто близько одне до одного. Reposition them and run the DRC again to find more problems Виправте це, та запустіть ППМ ще раз, щоб знайти інші проблеми Fritzing Fritzing Fritzing error: unable to render board svg. Помилка Fritzing: не вдалось відобразити плату SVG. No traces or connectors to check Немає доріжок та роз’ємів для перевірки Unexpected SVG rendering failure--contact fritzing.org Несподівана помилка відображення SVG — зв’яжіться з fritzing.org Too close to a border (%1 layer) Занадто близько до краю (шар %1) %1 is overlapping (%2 layer) %1 є суміщення (шар %2) A hole in %1 may lie outside the border of the board and would be clipped. Отвір у %1 може знаходитись поза платою і буде обрізаний. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. З’єднувач %1 на %2 повинен мати мідь як зверху так і знизу, але SVG визначає лише один шар. DRCResultsDialog DRC Results КПМ - контроль проектних норм Результати КПМ Click on an item in the list to highlight of overlap it refers to. Оберіть пункт у переліку, щоб виділити перетин, до якого це відноситься Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. Увага: перелік помилок та червона підсвітка не будуть оновлюватись при редагуванні нарису, доки ви ще раз не запустите КПМ. Виділення зникне, коли ви закриєте цей діалог. DebugDialog for debugging для зневадження DeleteDialog Also delete the file Також видаліть файл Remove Видалити Don't remove Не видаляти Dip chip label позначка мікросхеми FApplication Fritzing failure Помилка Fritzing Fritzing caught an exception %1 from %2 in event %3 Fritzing отримав виключення %1 з %2 у події %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing отримав виключення з %1 у події %2: %3 Fritzing caught an exception from %1 in event %2 Fritzing отримав виключення з %1 у події %2 Import files from previous version? Імпортувати файли з попередньої версії? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Ви бажаєте імпортувати деталі та елементи, що були створені у попередніх версіях Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Увага: ви можете імпортувати їх пізніше, використовуючи меню "Довідка" > "Імпорт деталей та елементів з попередніх версій...". Import Імпорт Do not import now Не імпортувати зараз Please specify an .fzz file name to save to (cancel will delete the backup) Будь ласка, вкажіть ім’я файлу .fzz для зберігання (скасування видалить резервну копію) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help Перша допомога <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. <br/>Вид <b>Макетна плата</b> показує, як виглядає <i>справжня</i> макетна плата.<br/><br/>Перетягніть сюди деталі з розділу Набір деталей у верхньому правому куті. Сполучайте їх, розмістивши на макетній платі, або потягнувши затиснений контакт. Все відбувається так само, як у житті.<br/><br/>Після створення нарису у вікні Макетної плати, перегляньте інші види. Ви можете змінити вид, обравши потрібну вкладку у верхній частині вікна. Оскільки ці види мають різне призначення, деталі в них виглядають по різному. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. Вид <b>Схема</b><br/><br/>Тут деталі та з’єднання мають абстрактніший вигляд, ніж у виді Макетної плати. Ви маєте ті самі складові, але виглядають вони по іншому. Такий вигляд ближчий до традиційних схем, що використовуються інженерами.<br/><br/>Після того як ви з’єднаєте всі деталі доріжками, створіть нові опорні точки, щоб привести схему до ладу. Це можна зробити просто клацнувши по доріжц з &lt;Shift&gt;, і протягнувши вказівник. Вікно Схеми допоможе переконатись, що ви правильно з’єднали всі деталі. Також ви можете роздрукувати свою схему для документації. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> Вид <b>Друкована плата</b> показує, як виглядають складові на справжній ДП (друкованій платі).<br/><br/>Друковану плату можна виготовити вдома, або у невеликій лабораторії, використовуючи травлення. Також можна зврнутись на професійне виробництво, для більш якісного виготовлення ДП.<br/><table><tr><td>Перш за все, вам потрібна сама плата для розміщення деталей. Вона вже має бути у вашому нарисі, але якщо це не так — перетягніть її з Набору деталей. Значок плати ви можете побачити праворуч:</td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>Для створення ДП розмістіть всі складові так, щоб вони були добре розташовані на платі. Спробуйте розставити їх таким чином, щоб зменшити довжину та заплутаність доріжок. Також можна змінити розмір плати.<br/><table><tr><td>Після розміщення деталей з’єднайте їх мідними доріжками. Ви можете протягнути їх вручну, а можете розвести самодійно. Кнопка Розведення знаходиться в нижній частині вікна. Її значок ви бачите праворуч:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Закрити вікно (&C) Ctrl+W Ctrl+W Close the current sketch Закрити поточний нарис %1 - %2 %1 — %2 Specify a file name Вкажіть ім’я файл Save... Збереження... Save Зберегти Don't Save Не зберігати Cancel Скасувати Ctrl+D Ctrl+D Save "%1" Зберегти "%1" Do you want to save the changes you made in the document "%1"? Ви бажаєте зберегти зроблені зміни у документі "%1"? Your changes will be lost if you don't save them. Всі зміни буде втрачено, якщо ви не збережете їх. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Різниця між заповненням зі спільним заземленням та звичайним мідним заповненням полягає у тому, що, в першому випадку, всі доріжки та роз’єми, які під’єднані до заземлення, сполучаються між собою. Роз’єми заземлення позначаються, здебільшого, як 'GND' або 'ground'. Також буває, що є декілька ланцюжків з роз’ємами заземлення, і ви бажаєте об’єднати лише одне з них. Цей діалог збирає лише ті з’єднувачі, що позначені як 'GND' або 'ground', а також роз’єми, позначені як затравка. Клацніть по елементу, щоб показати його зв’язки у нарисі. Крім того, можна відмітити роз’єм як затравку заземлення, клацнувши правою кнопкою на з’єднанні, та обравши опцію меню 'Позначити як затравку спільного заземлення'. Cancel Скасувати OK Гаразд OK and ground fill Гаразд, заповнення зі спільним заземленням OK and copper fill Гаразд, заповнення міддю Hole hole size розмір отвору HtmlInfoView Change the part label here Змінити позначку деталі Part breadboard view image Зображення деталі на Макетній платі Part schematic view image Зображення деталі на Схемі Part pcb view image Зображення деталі на ДП Part version number Номер версії деталі Placement Розміщення pcb layer шар друкованої плати Properties Властивості Tags Ключові слова Connections З’єднання conn. з’єдн. name назва type тип connected to %n item(s) підключено до %n деталі підключено до %n деталей підключено до %n деталей (autoroutable) (саморозведення) Wire Провідник Ratsnest wire Навісний монтаж Trace wire %1 Розведення доріжки %1 v. %1 %2 версія %1 %2 obsolete застаріле Locked Заблокувати Change the locked state of the part in this view. A locked part can't be moved. Розблокуйте деталь на цьому виді. Заблоковану деталь не можна переміщувати. Sticky Прилипати Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Вимкніть "прилипання" деталі у цьому виді. Коли липка деталь переміщується, прилиплі об’єкти також переміщуються. location положення rotation обертання degrees градуси ItemBase family сімейство type тип model модель size розмір color колір resistance опір capacitance ємність inductance індуктивність voltage напруга current струм power потужність pin spacing відстань між штирками rated power номінальна потужність rated voltage номінальна напруга rated current номінальний струм version версія package корпус shape обрис form вид корпусу part number номер деталі maximum resistance найбільший опір pins штирки spacing відстань frequency частота processor процесор variant варіант layers шари tolerance припустиме відхилення descr опис filename ім’я файлу title назва date дата rev ревізія sheet аркуш project проект banded смужастий top верх bottom низ copper bottom мідний низ copper top мідний верх silkscreen bottom шар позначок знизу silkscreen top шар позначок зверху Part Деталь model part problem проблема з моделю деталі file for %1 %2 not found файл %1 %2 не знайдено unable to create renderer for svg %1 не вдалось відобразити SVG %1 KicadModuleDialog Cancel Скасувати OK Гаразд LayerPalette show all layers показати всі шари LinkDialog url: адреса в мережі: text: текст: Cancel Скасувати OK Гаразд LogoItem text текст shape обрис due to a rendering error через помилку в поданні because the svg is empty тому що SVG порожній because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting можливо тому, що при експорті до SVG з CorelDRAW не було обрано опцію 'presentation attributes' due to an xml problem: %1 line:%2 column:%3 через проблему з XML: %1 рядок:%2 стовпчик:%3 because the file has no root element тому що файл не має основного елементу because the file has no <svg> element тому що файл не має <svg> елементу for unknown reasons--possibly the image file is corrupted з невідомих причин — можливо файл зображення пошкоджений Unable to display Не вдалось відобразити Unable to display image from %1 Не вдалось показати зображення з %1 MainWindow Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer Shift+Ctrl+Tab Breadboard Монтажна плата Schematic Схема PCB Друкована плата Click to highlight unconnected parts Натисніть для виділення роз’єднаних деталей Rotate Обернути Share Поширити Flip Віддзеркалити Autoroute Розведення Fabricate Виготовити Both Layers Обидва шари Bottom Layer Нижній шар Top Layer Верхній шар View from Above Вигляд зверху View from Below Вигляд знизу Add a note Примітка Export for PCB Експорт ДП Ready Готовий Save %1 Зберегти %1 Fritzing Frizting Unable to open '%1': %2 Не вдалось відкрити '%1': %2 No Sketch found in '%1' Не знайдено нарис у '%1' Unable to open shareable '%1': %2 Не вдалось відкрити спільне '%1': %2 Unable to open shareable part '%1': %2 Не вдалось відкрити спільну деталь '%1': %2 Unable to load part from '%1' Не вдалось завантажити деталь з '%1' Specify a file name Вкажіть ім’я файлу Fritzing Part (*%1) Деталь Fritzing (*%1) Unable to export %1 to shareable sketch Не вдалось експортувати %1 до спільного нарису MainWindow::moveToPartsFolder mainwindow missing ГоловнеВікно::переміститиДоТекиДеталей головневікно відсутнє There is already a part with id '%1' loaded into Fritzing. Деталь з ідентифікатором '%1' вже було завантажено до Fritzing. Do you want to keep the imported parts? Бажаєте зберегти імпортовані деталі? No connections to route Відсутнє з’єднання з доріжкою Routing completed Розведення завершено Routing completed using %n jumper part(s) Розведення завершено завдяки %n перемичці Розведення завершено завдяки %n перемичкам Розведення завершено завдяки %n перемичкам %1 of %2 nets routed - %n connector(s) still to be routed %1 з %2 ланцюжок розведено — ще %n контакт потребує розведення %1 з %2 ланцюжки розведено - ще %n контакти потребують розведення %1 з %2 ланцюжків розведено - ще %n контактів потребують розведення %1 - [%2] %1 — [%2] No copper top layer Верхній шар не мідний The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Верхній мідний шар (copper 1) неможливий на односторонній платі. Будь ласка, зробіть плату двосторонньою, або оберіть нижній мідний шар (copper 0). Sorry! Вибачте! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist Немає деталей з такими озаками. Ми працюємо над тим, щоб уникнути цього повідомлення, і дозволити обирати лише ті властивості, що справді існують No exactly matching part found; Fritzing chose the closest match. Немає повністю відповідних деталей; Fritzing обрав найближчий відповідник. Change to single layer pcb Змінити на односторонню плату Change to two layer pcb Змінити на двосторонню плату Swapped %1 with module %2 Поміняти %1 з вузлом %2 Change image to %2 Змінити зображення на %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. У SVG %1 відсутній шар '%2'. Для отримання додаткової інформації про створення власних обрисів плат, дивіться підручник <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 завантажується %1 Loading... Завантаження... new sketch новий нарис Schematic conversion Схема перетворення Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Збереження цього нарису потребує його перетворення у новий графічний стандарт схем. Продовжити перетворення? Backing up '%1' Резервне копіювання '%1' Fritzing (*%1) Fritzing (*%1) Unrouted connections Нерозведені з’єднання There are no unrouted connections in this view. На цьому виді немає нерозведених з’єднань. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Код Welcome Ласкаво просимо Inspector Інспектор Undo History Історія Layers Шари Couldn't get the dock widget Не вдалось отримати пристосунок PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) зображення PNG (*.png) JPEG Image (*.jpg) зображення JPEG (*.jpg) SVG Image (*.svg) зображення SVG (*.svg) BoM Text File (*.html) Текстовий файл BoM (*.html) Printing... Друк... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Ваш нарис досі не містить плати! Будь ласка, додайте ДП для експорту витравки. Etchable export can only handle one board at a time--please select the board you want to export. Експорт витравки може працювати лише з однією платою в один момент часу — будь ласка, оберіть плату яку ви бажаєте експортувати. All traces have not yet been routed. Всі доріжки ще не розведені. Do you want to proceed anyway? Все одно бажаєте продовжити? Proceed Продовжити Cancel Скасувати Choose a folder for exporting Обрати теку для експорту Sketch exported Нарис експортується Export... Експорт... Exporting... Експорт... Unable to save %1 Не вдалось зберегти %1 Cannot print to %1 Неможливо надрукувати %1 Cannot write file %1: %2. Неможливо записати файл %1: %2. Saved '%1' Збереження '%1' Unable to export %1 as shareable Не вдалось експортувати %1 як спільне &Save Зберегти (&S) Ctrl+S Ctrl+S Save the current sketch Зберегти поточний нарис &Save As... Зберегти як (&S)... Shift+Ctrl+S Shift+Ctrl+S Share online... Поширити в мережі... Post a project to the Fritzing website Опублікувати проект на сторінці Fritzing JPG... JPG... Export the visible area of the current sketch as a JPG image Експортувати видиму частину поточного нарису як зображення JPG PNG... PNG... Export the visible area of the current sketch as a PNG image Експортувати видиму частину поточного нарису як зображення PNG PostScript... PostScript... Export the visible area of the current sketch as a PostScript image Експортувати видиму частину поточного нарису як зображення PostScript PDF... PDF... Export the visible area of the current sketch as a PDF image Експортувати видиму частину поточного нарису як зображення PDF SVG... SVG... Export the current sketch as an SVG image Експортувати поточний нарис як зображення SVG List of parts (&Bill of Materials)... перелік деталей (опис матеріалів) (&B)... Save a Bill of Materials (BoM)/Shopping List as text Зберегти опис матеріалів/перелік покупок у вигляді тексту XML Netlist... таблицю з’єднань XML... Save a netlist in XML format Зберегти таблицю з’єднань у форматі XML SPICE Netlist... таблицю з’єднань SPICE... Save a netlist in SPICE format Зберегти таблицю з’єднань у форматі SPICE Eagle... Export the current sketch to Eagle CAD Експортувати поточний нарис до Eagle CAD Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Експортувати поточний нарис до Extended Gerber (RS-274X), для професійного виготовлення ДП Etchable (PDF)... Витравка (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Експортувати поточний нарис до PDF, для саморобного виробництва ДП (фоторезист) Etchable (SVG)... Витравка (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) Експортувати поточний нарис до SVG, для саморобного виробництва ДП (фоторезист) &Print... Друкувати (&P)... Ctrl+P Ctrl+P Print the current view Надрукувати поточний вид This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Це скоро дозволить експортувати ваші нариси Fritzing до EAGLE. Якщо ви бажаєте отримати більше варіантів експорту до ваших улюблених АПЕВ — будь ласка, сповістіть нас, або зробіть свій внесок. Export SVG... Експорт SVG... Export Bill of Materials (BoM)... Експорт опису матеріалів... Unable to save BOM file, but the text is on the clipboard. Не вдалось зберегти файл опису матеріалів, але текст у буфері обміну. Export SPICE Netlist... Експорт SPICE Netlist... Export Netlist... Експорт Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Ваш нарис не містить плати! Будь ласка, додайте ДП для експорту у Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Експорт у Gerber можливий лише для однієї плати в один момент часу — будь ласка, оберіть плату для експорту. Sketch exported to Gerber Нарис експортується у Gerber Select a Fritzing File to Open Виберіть файл Fritzing для відкривання Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Файли Fritzing (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Спільне (*%2);;Fritzing Деталь (*%3);;Fritzing Набір (*%4);;Fritzing Спільний набір (*%5) Cannot find file %1. Неможливо знайти файл %1. Cannot read file 1 %1: %2. Неможливо прочитати файл 1 %1: %2. Revert? Повернути? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Цю дію неможливо відмінити — ви втратите всі ваші зміни. Продовжити і розвернути? File '%1' not found Файл '%1 не знайдено the .fz file format is obsolete формат .fz застарів The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? Формат .fz застарілий. Бажаєте перетворити '%1' у формат .fzz зараз, чи відкрити файл лише для читання? The conversion process will not modify '%1'. Процес перетворення не змінить '%1'. Convert Перетворити Read-only Лише для читання Please specify an .fzz file name to save '%1' to Будь ласка, вкажіть ім’я файлу .fzz для збереження '%1' directly loading parts безпосередньо завантажені деталі loading %1 (model) завантажується %1 (макет) loading %1 (breadboard) завантажується %1 (монтажна плата) loading %1 (pcb) завантажується %1 (друкована плата) loading %1 (schematic) завантажується %1 (схема) New Створити Ctrl+N Ctrl+N Create a new sketch Створити новий нарис &Open... Відкрити (&O)... Ctrl+O Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Відкрити нарис Fritzing (.fzz, .fz), або завантажити деталь Fritzing (.fzpz), або набір деталей Fritzing (.fzb, .fzbz) Revert Перевідкрити Reload the sketch Перезавантажити нарис Shell launch %1 Запуск оболонки %1 throw test exception створити тест винятків throw a fake exception to see what happens створити підробний виняток, щоб побачити що відбувається &Quit Вихід (&Q) Ctrl+Q Ctrl+Q Quit the application Вихід із застосунка &Open Example Приклади (&O) All Різне MainWindow::populateMenuWithIndex: couldn't load example with id='%1' ГоловнеВікно::заповнитиМенюЗІнексом::неможливо завантажити приклад з ідентифікатором='%1' &Open Recent Files Останні файли (&O) &%1 %2 &%1 %2 Undo Відмінити Redo Повернути &Cut Вирізати (&C) Cut selection Вирізати вибране &Copy Копіювати (&C) Copy selection Копіювати вибране &Paste Вставити (&P) Paste clipboard contents Вставити вміст буфера обміну Paste in Place Вставити на місце Paste clipboard contents in place Вставити вміст буфера обміну на місце &Duplicate Дублювати (&D) Ctrl+D Ctrl+D Duplicate selection Дублювати вибране &Delete Видалити (&D) Delete selection Видалити вибране Delete Minus Видалити деталь без провідника Delete selection without attached wires Видалити вибране без підключених провідників &Delete Wire Видалити провідник (&D) Delete Wire up to bendpoints Видалити провідник до опорних точок &Select All Вибрати все (&S) Select all elements Вибрати всі складові &Deselect Зняти виділення (&D) Deselect Зняти виділення Add Note Додати примітку &Preferences... Уподобання (&P)... Show the application's about box Показати вікно Про програму Edit (new parts editor) Редагувати (новий Редактор деталей) Open the new parts editor on an existing part Відкрити новий Редактор деталей на існуючій деталі &Add to bin... Додати до набору (&A)... Add selected part to bin Додати виділену деталь до набору Disconnect All Wires Відключити всі провідники Disconnect all wires connected to this connector Відключити всі сполучення до цього роз’єму Update InfoView on hover Оновити Вид інформації при наведенні Export Normalized SVG Експортувати упорядкований SVG Export 1000 dpi SVG of this part in this view Експорт 1000 т/дюйм SVG деталі у цьому виді Export Normalized Flattened SVG Експорт упорядкованого злитого SVG Export 1000 dpi Flattened SVG of this part in this view Експорт 1000 т/дюйм злитого SVG у цій деталі у цьому виді Dump all parts Скинути всі деталі Debug dump all parts in this view Налагодити скидання всіх деталей у цьому виді Test Connectors Перевірити роз’єми Connect all connectors to a single test part Підключити всі роз’єми до випробуваної деталі Rotate current selection 45 degrees clockwise Обернути вибране на 45 градусів за годинником Rotate the selected parts by 90 degrees clockwise Обернути вибране на 90 градусів проти годинника Rotate the selected parts by 180 degrees Обернути вибране на 180 градусів Rotate current selection 90 degrees counter clockwise Обернути вибране на 90 градусів проти годинника Rotate 45� Clockwise Повернути на 135° за годинником {45�?} Rotate 90� Clockwise Повернути на 135° за годинником {90�?} Rotate 180� Повернути на 180° {180�?} Rotate 90� Counter Clockwise Повернути на 45° проти годинника {90�?} Rotate 45� Counter Clockwise Повернути на 45° проти годинника {45�?} Rotate current selection 45 degrees counter clockwise Обернути вибране на 45 градусів проти годинника &Flip Horizontal Віддзеркалити горизонтально (&F) Flip current selection horizontally Віддзеркалити вибране по горизонталі &Flip Vertical Віддзеркалити вертикально (&F) Flip current selection vertically Віддзеркалити вибране по вертикалі Bring to Front Підняти наверх Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer Перемістити вибраний об’єкт(и) наверх цього шару Bring Forward Підняти вище Ctrl+] Ctrl+] Bring selected object(s) forward in their layer Посунути вибраний об’єкт(и) вище у цьому шарі Send Backward Опустити нижче Ctrl+[ Ctrl+[ Send selected object(s) back in their layer Посунути вибраний об’єкт(и) нижче у цьому шарі Send to Back Опустити наниз Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer Перемістити вибраний об’єкт(и) наниз цього шару Align Left Вирівняти по лівому краю Align selected items at the left Вирівняти вибрані об’єкти по лівому краю Align Horizontal Center Вирівняти горизонтально по центру Align selected items at the horizontal center Вирівняти вибрані об’єкти горизонтально по центру Align Right Вирівняти по правому краю Align selected items at the right Вирівняти вибрані об’єкти по правому краю Align Top Вирівняти по верхньому краю Align selected items at the top Вирівняти вибрані об’єкти по верхньому краю Align Vertical Center Вирівняти вертикально по центру Align selected items at the vertical center Вирівняти вибрані об’єкти вертикально по центру Align Bottom Вирівняти по нижньому краю Align selected items at the bottom Вирівняти вибрані об’єкти по нижньому краю Lock Part Заблокувати деталь Prevent a part from being moved Запобігти переміщенню деталі Sticky Приліпити If a "sticky" part is moved, parts on top of it are also moved Якщо "липку" деталь посунути, пов’язані з нею деталі також перемістяться Select All Locked Parts Вибрати всі заблоковані деталі Select all parts that can't be moved Вибрати всі деталі, що не можуть бути переміщеними &Show part label Показати позначку деталі (&S) Show/hide the label for the selected parts Показати/приховати позначку вибраних деталей &Export... Експортувати (&E)... Export selected part Експортувати виділену деталь Add Bendpoint Додати опорну точку Add a bendpoint to the selected wire Додати опорну точку до вибраного провідника Convert Bendpoint to Via Перетворити опорну точку на отвір Convert the bendpoint to a via Перетворити опорну точку на отвір Convert Via to Bendpoint Перетворити отвір на опорну точку Convert the via to a bendpoint Перетворити отвір на опорну точку Straighten Curve Вирівняти вигин Straighten the curve of the selected wire Вирівняти вигин виділеного провідника Select outdated parts Вибрати застаріли деталі Update selected parts Оновити вибрані деталі Find part in sketch... Знайти деталь у нарисі... Search for parts in a sketch by matching text Шукати деталі у нарисі за текстом Open programming window Відкрити вікно програмування Open microcontroller programming window Відкрити вікно програмування мікроконтролера Hide part silkscreen Приховати деталь шару позначок Hide/show the silkscreen layer for only this part Приховати/показати шар позначок лише для цієї деталі &Zoom In Наблизити (&Z) Ctrl++ Ctrl++ Zoom in Наблизити Ctrl+= Ctrl+= &Zoom Out Віддалити (&Z) Ctrl+- Ctrl+- Zoom out Віддалити &Fit in Window Припасувати до вікна (&F) Ctrl+0 Ctrl+0 Fit in window Припасувати до вікна &Actual Size Дійсний розмір (&A) Actual (real world physical) size Дійсний (справжній) розмір 100% Size 100% розмір Shift+Ctrl+0 Shift+Ctrl+0 100% (pixel) size 100% (піксельний) розмір Align to Grid Вирівняти за сіткою Align items to grid when dragging Вирівнювати деталі за сіткою при перетягуванні Show Grid Показати сітку Show the grid Показати сітку Set Grid Size... Задати розмір сітки... Set the size of the grid in this view Задати розмір сітки у цьому виді Set Background Color... Задати колір тла... Set the background color of this view Задати колір тла у цьому виді Ctrl+1 Ctrl+1 Ctrl+2 Ctrl+2 Ctrl+3 Ctrl+3 Ctrl+4 Ctrl+4 Ctrl+5 Ctrl+5 &Show Welcome Показати вікно вітання (&S) Show the welcome view Показати вікно вітання &Show Breadboard Показати МП (&S) Show the breadboard view Показати вид монтажної плати &Show Schematic Показати Схему (&S) Show the schematic view Показати вид схеми &Show PCB Показати ДП (&S) Show the PCB view Показати вид друкованої плати Show Code Показати Код Show the code (programming) view Показати вид коду (програмування) Show Parts Bin Icon View У вигляді значків Display the parts bin in an icon view Показати набір деталей у вигляді значків Show Parts Bin List View У вигляді переліку Display the parts bin in a list view Показати набір деталей у вигляді переліку &Show All Layers Показати всі шари (&S) Show all the available layers for the current view Показати всі наявні шари поточного виду &Hide All Layers Приховати всі шари (&H) Hide all the layers of the current view Приховати всі шари поточного виду &Minimize Згорнути (&M) Ctrl+M Ctrl+M Minimize current window Згорнути поточне вікно Debugger Output Зневаджувальна інформація Online Tutorials Поради в мережі Ctrl+? Ctrl+? Open Fritzing help Відкрити довідку Fritzing Donate to Fritzing Віддячити Fritzing Open Fritzing donation web page Відкрити сторінку віддячення Fritzing Online Projects Gallery Галерея проектів у мережі Open Fritzing examples Відкрити приклади Fritzing Online Parts Reference Деталі в мережі Open Parts Reference Відкрити посилання на деталі Check for updates... Перевірити оновлення... Check whether a newer version of Fritzing is available for download Перевірити наявність нових версій Fritzing &About Про програму (&A) Tips, Tricks and Shortcuts Поради, рекомендації та швидкі клавіші Display some handy Fritzing tips and tricks Показати деякі поради та рекомендації Fritzing First Time Help Перша допомога Display First Time Help Показати швидку довідку &About Qt Про Qt (&A) Show Qt's about box Показати вікно Про Qt Report a bug... Повідомити про помилку... Report a but you've found in Fritzing Повідомити про знайдену помилку у Fritzing Enable debugging log Увімкнути журнал зневадження &Import parts and bins from old version... Імпортувати деталі та набори зі старої версії (&I)... Import parts and bins from previous installation Імпортувати деталі та набори з попереднього встановлення Parts Editor Help Довідка Редактора деталей Display Parts Editor help in a browser Показати довідку Редактора деталей у переглядачі &File Файл (&F) &Export Експортувати (&E) as Image як зображення for Production для виготовлення &Edit Редагування (&E) &Part Деталь (&P) Raise and Lower Підняти та опустити Ctrl+Shift+V Align Вирівняти &View Вид (&V) &Window Вікно (&W) &Routing Розведення (&R) Ground Fill Заповнення &Help Довідка (&H) Move to bottom layer Перемістити на нижній шар Move to top layer Перемістити на верхній шар Delete Ratsnest Line Видалити лінію навісного монтажу Delete Wire Видалити провідник Hide part label Приховати позначку деталі Show part label Показати позначку деталі Show part silkscreen Показати шар позначкок деталі Delete Видалити top and bottom верх та низ bottom верх top низ Ground Fill (%1) Заповнення зі спільним заземлення (%1) Copper Fill (%1) Мідне заповнення (%1) Actual Size Дійсний розмір It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Немає можливості автоматично визначити дійсний розмір монітора, тому 'дійсний розмір' є лише припущенням. Але ви можете розмістити справжню лінійку поверх віртуальної, і скорегувати розмір останньої. Page Setup Установки сторінки Sorry, "%1" has not been implemented yet На жаль, "%1" ще не реалізовано Autoroute connections... Розвести з’єднання... Shift+Ctrl+A Shift+Ctrl+A &Create trace from ratsnest Створити доріжку з навісного монтажу (&C) Create a trace from the ratsnest line Створити доріжку з лінії навісного монтажу &Create wire from ratsnest Створити провідник з навісного монтажу (&C) Create a wire from the ratsnest line Створити провідник з лінії навісного монтажу Do not autoroute Не розводити When autorouting, do not rip up this trace wire, via, or jumper item При саморозведенні не розривати цю доріжку, отвір чи перемичку Move to other side of the board Перемістити на інший бік плати Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Перемістити вибрані доріжки на другий бік плати (увага: коли 'перша' доріжка переміститься, решта перейдуть за нею) Show unrouted Показати нерозведене Highlight all unrouted connectors Підсвітити всі нерозведені роз’єми Select All Traces Вибрати всі доріжки Select all trace wires Вибрати всі провідні доріжки Select All Wires Вибрати всі провідники Select all wires Вибрати всі провідники Select All CopperFill Вибрати все мідне заповнення Select all copper fill items Вибрати всі елементи мідного заповнення Force Update Routing Status and Ratsnests Примусово оновити стан розведення та навісний монтаж Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Перерахувати стан розведення та провідників навісного монтажу (у разі, якщо самооновлення не працює належним чином) Select All "Don't Autoroute" Traces Вибрати всі "не саморозвідні" доріжки Select all trace wires excluded from autorouting Вибрати всі провідні доріжки, виключені з саморозведення Select All Autoroutable Traces Вибрати всі саморозвідні доріжки Select all trace wires that can be changed during autorouting Вибрати всі провідні доріжки, які можна змінити саморозведенням Select All Jumpers Вибрати всі перемички Select all jumper item parts Вибрати всі перемички деталей Select All Vias Вибрати всі отвори Select all via parts Вибрати всі отвори деталей Tidy Wires Прибрати провідники Tidy selected wires Прибрати вибрані провідники Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Заповнити порожню площу мідного шару — разом із доріжками, сполученими з заземленням Copper Fill Мідне заповнення Fill empty regions of the copper layer--not including traces connected to a GROUND Заповнити порожню площю мідного шару — за виключенням доріжок, що сполучені із заземленням Remove Copper Fill Видалити мідне заповнення Remove the copper fill Видалити мідне заповнення Choose Ground Fill Seed(s)... Вибрати затравку(ки) спільного заземлення... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Заповнити порожню площу мідного шару — разом із доріжками, сполученими з затравками Set Ground Fill Seed Задати затравки спільного заземлення Treat this connector and its connections as a 'ground' during ground fill. Розглядати цей роз’єм та ці з’єднання як 'землю' під час заповнення зі спільним заземленням. Clear Ground Fill Seeds Очистити затравки спільного заземлення Clear ground fill seeds--enable copper fill only. Очистити затравки спільного заземлення — дозволити лише заповнення міддю. Set Ground Fill Keepout... Задати проміжок для спільного заземлення... Set the minimum distance between ground fill and traces or connectors Задати найменшу відстань між заповненням зі спільним заземленням та доріжками або роз’ємами Design Rules Check (DRC) Перевірка проектних норм (ППН) Highlights any parts that are too close together for safe board production Підсвітити деталі, що знаходяться надто близько одна до одної для надійного виробництва плати Shift+Ctrl+D Shift+Ctrl+D Check Loaded Traces Перевірити завантажені доріжки Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Вибрати доріжки, розташування яких на екрані не відповідає дійсному розташуванню. Необхідне лише для версії 0.7.10, та більш давніх Autorouter/DRC settings... Налаштування саморозведення та ППН... Set autorouting parameters including keepout... Задати параметри саморозведення, включно з проміжками... Fritzing Fab Quote... Цитати Fritzing Fab... How much would it could to produce a PCB from this sketch with Fritzing Fab Скільки буде коштувати виготовлення друкованої плати з цього нарису на виробництві Fritzing View from below Вид знизу View the PCB from the bottom layers upwards Вигляд друкованої плати знизу View from above Вид зверху View the PCB from the top layers downwards Вигляд друкованої плати зверху Set both copper layers clickable Зробити обидва мідні шари натискними Shift+Ctrl+3 Shift+Ctrl+3 Set copper top layer clickable Зробити верхній мідний шар натискним Shift+Ctrl+2 Shift+Ctrl+2 Set copper bottom layer clickable Зробити нижній мідний шар натискним Shift+Ctrl+1 Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Зробити верхній та нижній мідні шари активними Copper Top layer is active Верхній мідний шар активний Copper Bottom layer is active Нижній мідний шар активний Order a PCB... Замовити друковану плату... Order a PCB created from your sketch--from fabulous Fritzing Fab Замовити друковану плату, створену з вашого нарису — від неймовірної Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Ваш нарис не містить плати! Будь ласка, додайте ДП для використання саморозведення. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Будь ласка, виберіть плату для саморозведення. Саморозведення можливе лише для однієї плати за раз. Autorouting... Саморозведення... Autorouting Progress... Здійснюється саморозведення... jumpers перемички copperfill мідне заповнення vias отвори Remove Bendpoint Видалити опорні точки Please choose the previous Fritzing folder... Будь ласка, виберіть теку попереднього Fritzing... The folder "%1" isn't a Fritzing installation folder Тека "%1" не є текою встановлення Fritzing You will have to restart Fritzing in order to use the imported parts Потрібно перезапустити Fritzing для використання імпортованих деталей Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Ваш нарис не містить плати! Будь ласка, додайте ДП для використання заповнення із заземленям, або мідного заповнення. Please select a PCB--copper fill only works for one board at a time. Будь ласка, оберіть ДП — обробка мідного заповнення можлива лише для однієї плати в один момент часу. Generating %1 fill... Створення %1 заповнення... ground заземленого copper мідного Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Ваш Нарис не містить плати! Будь ласка, додайте ДП для видалення мідного заповнення. Please select a PCB--ground fill operations only work on a one board at a time. Будь ласка, оберіть ДП — обробка заповнення зі спільним заземленням можлива лише для однієї плати в один момент часу. Remove copper fill Видалити мідне заповнення &Wire Color Колір провідника (&W) Schematic view update Оновити вид схеми There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Існує новий графічний стандарт для зображень деталей виду схеми, введений у версії 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? Ви бажаєте перетворити '%1' у новий стандарт зараз, чи відкрити файл лише для читання? The conversion process will not modify '%1', until you save the file. Перетворення не змінить '%1', доки ви не збережете файл. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Вам доведеться переставити деталі та з’єднання у виді схеми, коли розміри зображень деяких деталей беду змінено. Розгляньте можливість використання саморозведення для очищення доріжок. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Зверніть увагу, що жодну саморобну деталь не буде перетворено. Інструмент для перетворення 'прямокутних' зображень схем доступний у редакторі деталей. Launch %1... Запуск %1... No outdated parts found. All your parts are up-to-date. Не знайдено застарілих деталей. Всі ваші деталі сучасні. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Увага: якщо ви бажаєте оновити пізніше, є опція у меню 'Деталь' для роботи з застарілими відособлено. Outdated parts Застарілі деталі There are %n outdated part(s) in this sketch. У нарисі є %n застаріла деталь. У нарисі є %n застарілі деталі. У нарисі є %n застарілих деталей. We strongly recommend that you update these %n parts to the latest version. Ми наполегливо радимо вам оновити цю %n деталь до останньої версії. Ми наполегливо радимо вам оновити ці %n деталі до останньої версії. Ми наполегливо радимо вам оновити ці %n деталей до останньої версії. This may result in changes to your sketch, as parts or connectors may be shifted. Це може призвести до змін у нарисі, оскільки деталі чи роз’єми можуть бути посунуті. Do you want to update now? Ви бажаєте оновити зараз? unable to find replacement for %1. не вдалось знайти заміну для %1. Update %1 part(s) Оновлення %1 деталі(-ей) Successfully updated %1 part(s). Please check all views for potential side-effects. Завершено оновлення %1 деталі(ей). Будь ласка, перевірте всі види для виявлення можливих побічних наслідків. OK Гаразд Set the grid size for %1. Задати розмір сітки %1. Grid Size: Розмір сітки: in дюйм mm мм Restore Default По замовчанню Your sketch does not have a board yet! DRC only works with a PCB. Ваш нарис не містить плати! Перевірка проектних норм працює лише з ДП. Please select a PCB. DRC only works on one board at a time. Будь ласка, оберіть ДП. ППН працює лише з однією ДП в один момент часу. DRC Progress... Здійснюється ППН... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Ваш нарис не містить плати! Будь ласка, додайте ДП для використання мідного заповнення. Please select a PCB. Copper fill operations only work on one board at a time. Будь ласка, оберіть ДП. Мідне заповнення працює лише з однією платою в один момент часу. %1 background %1, тло Enter Text Введіть текст Text will match part label, description, title, etc. Enter text to search for: Текст має відповідати позначці деталі, опису, назві тощо. Введіть текст для пошуку за: Search Пошук No parts matched search term '%1'. Жодна деталь не відповідає умовам пошуку '%1'. MazeRouter Autorouter was cancelled. Розведення скасовано. best so far: %1 of %2 routed найкраще: %1 %2 підключення with %n vias з %n отвору з %n отворів з %n отворів round %1 of: близько %1 з: Routing stopped! Розведення зупинено! Use best so far... Використовуйте найкращий... Routing complete! Розведення завершено! Routing unsuccessful; stopping at round %1. Розведення не було успішним; зупинено близько %1. Routing reached maximum round %1. Розведення досягло максимума приблизно %1. Preparing undo... Підготовка скасування... Unexpected SVG rendering failure--contact fritzing.org Невідома помилка відображення SVG — зверніться на fritzing.org Optimizing traces... Оптимізація доріжок... ModelBase Unable to find the following %n part(s): Не вдалося знайти наступну %n деталь: Не вдалося знайти наступні %n деталі: Не вдалося знайти наступних %n деталей: at в File save failed! Помилка збереження файлу! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) Не вдається перезаписати файл '%1'. Причина: %2 (код помилки %3) MysteryPart label позначка chip label позначка мікросхеми NetLabel net label позначка ланцюжка Note [write your note here] [введіть примітку] PCBSketchWidget Create Trace from Ratsnest Створити доріжки за допомогою підвісного монтажу Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Ваш нарис не містить плати! Будь ласка, додайте ДП для використовування обраної операції. Please click on a PCB first--this selection operation only works for one board at a time. Будь ласка, оберіть спочатку ДП — ця опція працює лише з однією платою одночасно. Click this connector to drag out a new trace. Натисніть на цей з’єднувач, для того щоб витягнути нову доріжку. Change trace layer Змініть шар доріжки Your sketch does not have a board yet! Please add a PCB in order to use copper fill. Ваш нарис не містить плати! Будь ласка, додайте ДП для створення мідного заповнення. %1 Fill: please select the board you want to apply fill to. %1 Заповнення: будь ласка, оберіть платну, яку ви бажаєте заповнити. Ground Заземлення Copper Мідь Please designate one or more ground fill seeds before doing a ground fill. Будь ласка, призначте одну або декілька затравок спільного заземлення, перш ніж створювати заповнення зі спільним заземленням. Fritzing error: unable to render board svg (1). Помилка Fritzing: не вдалось відобразити плату SVG (1). Fritzing error: unable to render copper svg (1). Помилка Fritzing: не вдалось відобразити мідне заповнення SVG (1). Fritzing error: unable to write copper fill (1). Помилка Fritzing: не вдалось відрисувати мідне заповнення (1). Fritzing error: unable to write copper fill (2). Помилка Fritzing: не вдалось відрисувати мідне заповнення (2). Copper fill: please select only the board you want to fill. Мідне заповнення: будь ласка, оберіть плату яку ви бажаєте заповнити. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Не вдалось створити мідне заповнення — імовірно деталь не знаходиться на ДП. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Не вдалось створити мідне заповнення — можливо, деталь було скинуто на іншу деталь або провідник, а не до ДП. Clear ground fill seeds Очистити затравки спільного заземлення Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Ваш нарис не містить плати! Будь ласка, додайте ДП для використовування обраної операції. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Не вдалось перетворити цю опорну точку, оскільки сполучення до деталі є лише на нижньому шарі, а інша деталь є лише на верхньому шарі. Show part silkscreen Показати деталі на шарі позначок Hide part silkscreen Приховати деталі на шарі позначок Fritzing Fab Quote Поради Fritzing Fab Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Ваш нарис не містить плати! Ви не можете створити цей нарис без ДП. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. На жаль, http://fab.fritzing.org не відповідає на запит. Будь ласка, перевірте ваше підключення до мережі, та спробуйте ще раз. Enter Keepout Введіть проміжок Keepout is in mils (.001 inches). Проміжок у мілах (0,0254 мм, .001 дюйма). Note that due to aliasing, distances may be too short by up to 2 mils Зверніть увагу на те, що відстані до 2 мілів (0,05 мм) можуть призвести до накладання, so you may want to increase the keepout value by that much. так що краще збільшити значення проміжку. 10 mils is a good default choice. 10 мілів (0,254 мм) є гарним значенням по замовчанню. Enter keepout value: Введіть значення проміжку: PEConnectorsView This is where you edit the connector metadata for the part Тут ви можете змінювати властивості роз’ємів деталей number of connectors: кількість роз’ємів: Through-hole Наскрізний отвір SMD SMD - поверхневий монтаж Поверхневий монтаж PEMainWindow There is one last edit still pending. Останню правку ще не прийнято. The 'family' property can not be blank. Властивість 'сімейство' не може бути пустою. A duplicate 'family' property is not allowed Не допускається дублювання властивості 'сімейство' A duplicate 'variant' property is not allowed Не допускається дублювання властивості 'варіант' Close without saving? Закрити без збереження? This part can not be saved as-is: Деталь не може бути збережена як є: Do you want to keep working or close without saving? Бажаєте продовжити роботу, чи закрити без збереження? Close without saving Закрити без збереження Keep working Продовжити роботу Icon Значок Metadata Метадата Connectors Роз’єми SVG SVG Inspector Інспектор Layers Шари Reuse breadboard image Повторно використати зображення МП Reuse the breadboard image in this view Повторно використати зображення монтажної плати у цьому виді Reuse schematic image Повторно використати зображення схеми Reuse the schematic image in this view Повторно використати зображення схеми у цьому виді Reuse PCB image Повторно використати зображення ДП Reuse the PCB image in this view Повторно використати зображення друкованої плати у цьому виді Load image for view... Завантажити зображення для відораження... Open a file to use as the image for this view of the part. Відкрийте файл зображення вигляду цієї деталі. Show in Folder Показати у теці On the desktop, open the folder containing the current svg file. Відкрийте теку, що містить поточний файл SVG. Convert schematic to 0.1 inch standard Перетворити схему на стандарт 0.1 дюйм Convert pre-0.8.6 schematic image to new 0.1 inch standard Перетворити старе схематичне зображення до 0.8.6 у нове, стандарту 0.1 дюйм Remove Internal Connection Видалити внутрішнє з’єднання &File Файл (&F) Save as new part Зберегти як нову деталь Make a copy of the part and save it in the 'My Parts' Bin Створити копію деталі, та зберегти її у набір 'Мої деталі' &Export Експортувати (&E) &Edit Редагування (&E) Parts Editor Редактор деталей This part has bendable legs. Деталь має гнучкі ніжки. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . Ця версія Редактору деталей поки що не підтримує редагування гнучких ніжок, тому ніжки можуть відображатись неправильно у виді Монтажної плати. If you make changes to breadboard view, or change connector metadata, the legs may no longer work. Якщо ви вносите зміни у виді Макетної плати, або змінюєте метадані з’єднувачів — ніжки можуть перестати працювати. You can safely make changes to Schematic or PCB view. Ви можете спокійно вносити зміни у видах Схема або Друкована плата. This warning will not be repeated in this session of Fritzing Це попередження не буде повторюватись до перезапуску Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Не вдалось завантажити '%1'. Будь ласка, закрийте редактор деталей без збереження, і спробуйте ще раз. Unable to write svg to %1 Не вдалось записати SVG до %1 Unable to parse fzp file %1 Не вдалось розібрати файл FZP %1 Fritzing (New) Parts Editor Редактор деталей Fritzing (новий) Icon View Вигляд Значок Metadata View Вид Метадата Connectors View Вид З’єднувачів Show Icon Показати значки Ctrl+4 Ctrl+4 Show the icon view Показати у вигляді значка Show Metadata Показати метадані Ctrl+5 Ctrl+5 Show the metadata view Показати у вигляді метадати Show Connectors Показати з’єднувачі Ctrl+6 Ctrl+6 Show the connector metadata in a list view Показати метадату з’єднувача у вигляді переліку Make only this view visible Зробити видимим лише цей вид The part will only be visible in this view and icon view Деталь буде видно лише в цьому виді і у виді значків Blank not allowed Пустота не допускається The value of '%1' can not be blank. Значення '%1' не може бути порожнім. Change %1 to %2 Змінити %1 на %2 Must be unique Має бути унікальним Variant '%1' is in use. The variant name must be unique. Варіант '%1' вже використовується. Назва варіанту має бути унікальною. Change description Змінити опис Change %1 to '%2' Змінити %1 на '%2' Change tags Змінити ключові слова Duplicate problem Проблема дублювання Duplicate 'family' property not allowed Не допускається дублювання властивості 'сімейство' Duplicate 'variant' property not allowed Не допускається дублювання властивості 'варіант' Change properties Змінити властивості Change connector %1 Змінити з’єднувач %1 SVG problem Проблема з SVG This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. Це версія нового Редактора деталей не працює з окремими шарами мідь0 та мідь1 у '%1'. So editing may produce an invalid PCB view image Таким чином, редагування може призвести до неприпустимого вигляду ДП Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Файли зображень та опорних поверхонь (%1 %2 %3 %4 %5);;файли SVG (%1);;файли JPEG (%2);;файли PNG (%3);;файли опорної поверхні gEDA (%4);;файли Kicad Module (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Файли зображень (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Відкрити зображення Conversion problem Проблема перетворення Unable to load '%1' Не вдалось завантажити '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Схоже що SVG файл '%1' був експортований з CorelDRAW без встановлення опції 'presentation attributes'. Please re-export the SVG file using that setting, and try loading again. Будь ласка, ще раз експортуйте SVG файл, використовуючи це налаштування, і спробуйте завантажити його знову. Fonts Шрифти Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' На даний момент Fritzing підтримує лише OCRA та Droid шрифти — вони були замінені в '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. Ви можете використовувати PNG або JPG зображення для побудови своєї деталі, але краще використовувати SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PNG та JPG є растровими зображеннями, і будуть не дуже добре виглядають при зміні розміру — so for Fritzing parts it is best to use PNG and JPG only as placeholders. тому для деталей Fritzing краще використовувати PNG та JPG лише як заповнювачі. Use of PNG and JPG discouraged Використання PNG та JPG бентежить Unable to load image file '%1': %2 Не вдалось завантажити файл зображення '%1': %2 Unable to load image file '%1' Не вдалось завантажити файл зображення '%1' Unable to parse '%1': %2 line:%3 column:%4 Не вдалось розібрати '%1': %2 рядок:%3 стовпчик:%4 There are no copper layers defined in: %1. Немає мідних шарів у: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. Дивіться <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">це пояснення</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>Це не буде проблемою в наступному випуску Редактора деталей, but for now please modify the file according to the instructions in the link. але зараз, будь ласка, змініть файл відповідно до інструкції за посиланням. Copy problem Проблема копіювання Unable to make a local copy of: '%1' Не вдалось створити локальну копію: '%1' no schematics found in %1 не знайдено схеми у %1 schematic part схема деталі no footprints found in %1 не знайдено опорних поверхонь у %1 Relocate connector %1 Перемістити з’єднувач %1 Filename prefix Приросток імені файлу Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Будь ласка, введіть приросток для допомоги з визначенням файлу деталі. Ім’я буде мати вигляд 'PREFIX_%1'. (Не обов’язково змінювати приросток, оскільки завжди додається унікальний наросток.) Sketch Change Warning Попередження зміни нариса The open sketch '%1' uses the part you are editing. Відкритий нарис '%1' використовує редаговану деталь. Saving this part will make a change to the sketch that cannot be undone. Збереження цієї деталі внесе у нарис зміни, які неможливо буде скасувати. The open sketches Відкритий нарис '%1', '%1', and '%1' та '%1' Saving this part will make a change to these sketches that cannot be undone. Збереження цієї деталі внесе у нариси зміни, які неможливо буде скасувати. Go ahead and save? Продовжити і зберегти? Save Зберегти Cancel Скасувати Move terminal point Перемістити кінцеву точку Remove connector Видалити з’єднувач Remove %1 connectors Видалити %1 з’єднувачів Save "%1" Зберегти "%1" Do you want to save the changes you made in the part "%1"? Бажаєте зберегти внесені зміни у деталі "%1"? Your changes will be lost if you don't save them. Зміни буде втрачено, якщо ви не збережете їх. untitled part деталь без назви Unable to load fzp from %1 Не вдалось завантажити FZP з %1 Unable to create new connector--you may have to start over. Не вдалось створити новий з’єднувач — можливо вам доведеться почати спочатку. Add connector Додати з’єднувач Add %1 connectors Додати %1 з’єднувачів Internal connections are very messed up. Внутрішні з’єднання надто заплутані. Remove internal connection from '%1' Видалити внутрішнє з’єднання з '%1' Add internal connection from '%1' to '%2' Додати внутрішнє з’єднання з '%1' до '%2' Change all connectors to %1 Змінити всі з’єднувачі на %1 Unable to parse '%1' Не вдалось розібрати '%1' Change to %1 Змінити на %1 Make only %1 view visible Зробити видимим лише вид %1 This part has %n unassigned connectors Деталь має %n непризначений з’єднувач Деталь має %n непризначених з’єднувачі Деталь має %n непризначених з’єднувачів across %n views. через %n вид. через %n види. через %n видів. Until all connectors are assigned to SVG elements, the part will not work correctly. Доки всі з’єднувачі не призначені до елементів SVG, деталь не буде працювати правильно. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Можете спокійно вийти з Редактора деталей, просто не забудьте закінчити роботу пізніше. PEMetadataView This is where you edit the metadata for the part ... Тут можна редагувати метадані деталі... Set the part's title Задати назву деталі Title Назва Set the part's date Задати дату створення деталі Date Дата Set the part's author Задати автора деталі Author Автор Set the part's description--you can use simple html (as defined by Qt's Rich Text) Задати опис деталі — можна користуватись простим HTML (як визначено в Qt's Rich Text) Description Опис Set the default part label prefix Задати слово, що буде завжди розміщуватись перед позначкою деталі Label Позначка Set the part's url if it is described on a web page Задати мережеву адресу деталі, якщо її описано на якійсь сторінці URL Посилання Set the part's family--what other parts is this part related to Задати сімейство деталі — те, що пов’язує деталь з іншими деталями Family Сімейство Set the part's variant--this makes it unique from all other parts in the same family Задати варіації деталі — це відрізнить її від решти деталей одного сімейства Variant Варіація Set the part's properties Задати властивості деталі Properties Властивості Set the part's tags Задати ключові слова деталі Tags Ключові слова PESvgView width: ширина: height: висота: PEToolView Connector List (a checkmark means the graphic was selected) Перелік роз’ємів (галочкою відмічено обрані зображення) Set Internal Connections Задати внутрішні з’єднання Set this checkbox to edit internal connections by drawing wires Встановіть прапорець, щоб редагувати внутрішні з’єднання малюючи доріжки Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Управління встановленням кінцевої точки з’єднувача. У кінцевій точці провідник під’єднується до роз’єму. Ви можете також перетягнути перехрестя поточного роз’єму Center Середина W Зх N Пн S Пд E Сх center середина west захід north північ south південь east схід Sets the connector's terminal point to %1. Задати кінцеві точки з’єднувачів для %1. Modifies the x-coordinate of the terminal point Змінити X-координату кінцевої точки Modifies the y-coordinate of the terminal point Змінити Y-координату кінцевої точки Dragging disabled Вимкнути перетягування <font color='black'>Dragging enabled</font> <font color='black'>Перетягування ввімкнено</font> <font color='gray'>Dragging disabled</font> <font color='gray'>Перетягування вимкнено</font> Connector %1 З’єднувач %1 Select graphic Вибір зображення Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Використовуйте положення вказівника та коліщатко миші для переходу до елементу SVG, який потрібно призначити для поточного з’єднувача, і клацніть мишкою для його вибору. Pad shape обрис center середина north північ east схід south південь west захід connect to під’єднати до PaletteItem Edit Pin Labels Редагувати позначки штирка Fritzing Fritzing Unable to proceed; unable to find top level view. Не вдалось продовжити; не вдалось знайти вид верхнього рівня. Unable to proceed; part connectors do no have standard IDs. Не вдалось продовжити; з’єднувачі деталей не мають стандартних ідентифікаторів. Label mismatch. Nothing was saved. Невідповідність позначки. Не буде збережено. hole size розмір отвору advanced settings розширені налаштування in дюйм mm мм Hole Diameter Діаметр отвору Ring Thickness Товщина кільця PartLabel Edit Редагувати Edit label text Редагувати позначку Hide Приховати Hide part label Приховати позначку деталі Display Values Показати значення Flip/Rotate Розвернути/Повернути Font Size Розмір шрифта Rotate the label by 45 degrees clockwise Повернути позначку на 45° за годинником Rotate the label by 90 degrees clockwise Повернути позначку на 90° за годинником Rotate the label by 135 degrees clockwise Повернути позначку на 135° за годинником Rotate the label by 180 degrees Повернути позначку на 180° Rotate the label by 135 degrees counter clockwise Повернути позначку на 135° проти годинника Rotate current selection 90 degrees counter clockwise Повернути виділене на 90° проти годинника Rotate 45� Clockwise Повернути на 135° за годинником {45�?} Rotate 90� Clockwise Повернути на 135° за годинником {90�?} Rotate 135� Clockwise Повернути на 135° за годинником {135�?} Rotate 180� Повернути на 180° {180�?} Rotate 135� Counter Clockwise Повернути на 45° проти годинника {135�?} Rotate 90� Counter Clockwise Повернути на 45° проти годинника {90�?} Rotate 45� Counter Clockwise Повернути на 45° проти годинника {45�?} Rotate the label by 45 degrees counter clockwise Повернути позначку на 45° проти годинника Flip Horizontal Розвернути по горизонталі Flip label horizontally Розвернути позначку по горизонталі Flip Vertical Розвернути по вертикалі Flip label vertically Розвернути позначку по вертикалі Tiny Крихітний Set font size to tiny Крихітний розмір шрифта Small Маленький Set font size to small Маленький розмір шрифта Medium Середній Set font size to medium Середній розмір шрифта Large Великий Set font size to large Великий розмір шрифта Label text Текст позначки Display the text of the label Показати текст на позначці Display the value of property %1 Показати значення властивості %1 Set label for %1 Задати позначку для %1 Label text: Текст позначки: PartsBinPaletteWidget Untitled Bin Набір без назви Specify a file name Вкажіть ім’я файлу Fritzing Bin (*%1) Набір Fritzing (*%1) Fritzing Fritzing Cannot find file %1. Не вдається знайти файл %1. Cannot read file %1: %2. Не вдається прочитати файл %1: %2. Loading... Завантаження... loading bin '%1' завантажується набір '%1' Save bin "%1" Зберегти набір "%1" Do you want to save the changes you made in the bin "%1"? Ви бажаєте зберегти внесені зміни у наборі "%1"? Your changes will be lost if you don't save them. Всі зміни буде втрачено, якщо їх не зберегти. Save Збереження Don't Save Не зберігати Ctrl+D Ctrl+D Cancel Скасувати Add to bin Додати до набору Do you really want to add the selected part to the bin? Ви справді бажаєте додати обрану деталь до цього набору? Change icon color... Змінити колір значка... Change the color of the icon for this bin. Змінити колір значка цього набору. Select a color for this icon Оберіть колір цього значка Perfboard size розмір set board size задати розмір плати Performance Warning Попередження щодо продуктивності Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Продуктивність роботи із монтажними платами що мають більш ніж 2000 отворів може бути низькою. Ви справді бажаєте продвожити? Увага: це попередження показується лише один раз за сесію. Set new size Задати новий розмір Cancel Скасувати rows рядок columns стовпчик PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>Редактор позначок штирків</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>Натисніть на позначці штирка для його перейменування. You can use the tab key to move through the labels in order.</p> Ви можете використовувати клавіш табуляції для переміщення по позначках.</p> Cancel Скасувати Save Зберегти Undo Відмінити Redo Повернути PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Загальні Code View Cancel Скасувати OK Гаразд Mouse Wheel Behavior Поведінка коліщатка миші Change Wheel Behavior Змінити поведінку коліщатка Autosave Самозбереження Autosave every: Самозбереження кожні: minutes хвилини Language Мова Colors Кольори %1 (click to change...) %1 (натисніть для зміни...) Clear Settings Скинути налаштування Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Оберіть програматор (виконуваний файл) для %1 Connected Highlight Підсвітити з’єднані Unconnected Highlight Підсвітити роз’єднані Command Команди Control Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom без клавішів = прокручування Shift = змінити вісь прокручування Alt або %1 = збільшення no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis без клавішів = збільшення Alt або %1 = прокручування Shift = змінити вісь прокручування Curvy vs. straight wires Звивисті або прямі лінії When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? При натисканні кнопки миші і перетягуванні доріжки або ніжки деталі (роз’єму або опорної точки) ви бажаєте змінити кривизну доріжки (ніжки), чи створити нову опорну точку? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Цей прапорець задає поведінку за замовчуванням. Поведінку можна змінити, натиснувши Ctrl (у MacOS: Command) під час перетягування. Curvy wires and legs Звивисті лінії та ніжки ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Хоча на даний момент є змога читати та редагувати програмні файли %1, поки що неможливо використовувати Fritzing для компіляції та завантаження програм на мікроконтролер. New Створити Save Зберегти Open Platform Board Плата Port Serial Monitor Upload Select a program file to load Оберіть програмний файл для завантаження Fritzing is unable to find '%1', please locate it Fritzing не вдалось знайти '%1'. Будь ласка, вкажіть це Code (*.%1) Код (*.%1) Remove "%1"? Видалити "%1"? Are you sure you want to remove "%1" from the sketch? Ви справді бажаєте видалити "%1" з нарису? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit Редагування (&E) Undo Відмінити Redo Повернути &Cut Вирізати (&C) Cut selection Вирізати виділене &Copy Копіювати (&C) Copy selection Скопіювати виділене &Paste Вставити (&P) Paste clipboard contents Вставити вміст буфера обміну &Select All Вибрати все (&S) Select all text Вибрати весь текст &Code Код (&C) No boards available &Preferences... Уподобання (&P)... Show the application's about box Показати вікно Про програму &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Плата Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller &View Вид (&V) File '%1' was restored from the .fzz file; the local copy was not found. Файл '%1' відновлено з файлу .fzz; локальну копію не знайдено. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Файл '%1' відновлено з файлу .fzz; збережіть локальну копію для роботи у зовнішньому редакторі. Code Window Вікно коду Code Window - %1 Вікно коду — %1 %1%2 %1%2 QObject Autorouter Settings Налаштування саморозведення Part %1 '%2' Деталь %1 '%2' Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found Саморозведення неможливе: відсутня плата (або декілька плат) No connections (on the PCB) to route. На ДП немає з’єднань для розведення. No connections to route. Немає з’єднань для розведення. unable to copy file '%1' to '%2'. Не вдалось скопіювати файл '%1' до '%2'. %2 ... %1 wires moved from their saved position %2 ... %1 провідників переміщено зі збереженого місцеположення Set Ground Fill Seed Задати затравки спільного заземлення Ground Fill Seed Editor Редактор затравок спільного заземлення Pin Label Editor Редактор позначок штирків Preferences Уподобання Please note that a new language setting will not take effect until the next time you run Fritzing. Зверніть увагу, що нові мовні налаштування не запрацюють до перезапуску Fritzing. Connected highlight color Підсвітити сполучення Unconnected highlight color Підсвітити не сполучені деталі Clear all saved settings and close this dialog immediately. Очистити всі збережені налаштування і негайно закрити цей діалог. This action does not delete any files; it restores settings to their default values. Ця дія не видаляє файли — вона відновлює значення вподобань по замовчанню. There is no undo for this action, and no further warning!!!! Цю дію неможливо скасувати, і більше попереджень не буде!!!! Clear Settings Очистити налаштування %1 wires moved from their saved position in %2. %1 провідників переміщено зі збереженого місцеположення до %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Edit link Редагувати посилання mm мм in дюйм The file '%1' is read-only; please use a different filename. Файл '%1' лише для читання; будь ласка, оберіть іншу назву. Part Деталь Wire Провідник Set Grid Size Задати розмір сітки Cannot read file %1: %2. Неможливо прочитати файл %1: %2. Parse error (1) at line %1, column %2: %3 %4 Помилка аналізу (1) в рядку %1, стовпчику %2: %3 %4 The file %1 is not a Fritzing file (2). Файл %1 не є файлом Fritzing (2). The file %1 is not a Fritzing file (4). Файл %1 не є файлом Fritzing (4). The file %1 is not a Fritzing file (3). Файл %1 не є файлом Fritzing (3). Cannot write file temp: %1 %2 %3. Неможливо записати тимчасовий файл: %1 %2 %3. Parts folder not found. Теку деталей не знайдено. No parts found. Деталі не знайдено. Parse error (2) at line %1, column %2: %3 %4 Помилка аналізу (2) у рядку %1, стовпчику %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Деталь '%1' у %2 не має власного унікального ідентифікатора '%3'. Fritzing cannot load the parts bin Fritzing не може завантажити набір деталей Basic Основні Input Введення Output Виведення ICs Мікросхеми Power Живлення Connection З’єднання Microcontroller Мікроконтролери Breadboard View Монтажна плата Schematic View Схема PCB View Друкована плата Tools Знаряддя Shields Накладки LilyPad LilyPad Other Інше Sensors Давачі Part already in bin Деталь вже є у наборі The part that you have just added, is already there, we won't add it again, right? Деталь, яку ви щойно додали, вже існує. Ми не станемо додавати її ще раз, добре? a label позначка a value значення Select %1 Обрати %1 Set all to: Встановити все до: Pad Площинка ii Icon View Вид Значків Internal Connections Внутрішні з’єднання <b>Name:</b> <b>Назва:</b> Set the connectors's title Задати назву роз’ємів <b>Description:</b> <b>Опис:</b> Set the connectors's description Встановити опис роз’ємів <b>id:</b> <b>ідентифікатор:</b> <b>type:</b> <b>тип:</b> files файли Oops! Йой! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. Вибачте, ми маємо проблему з механізмом заміни. Fritzing продовжує роботу, але ви не зможете змінити властивості деталі. bb МП pcb ДП Select all 'Don't autoroute' traces Вибрати всі не саморозведені доріжки Select all autorouteable traces Вибрати всі доріжки, що можна саморозвести Select all %1 Вибрати все %1 Convert to Via Перетворити на отвір Convert Via to Bendpoint Перетворити отвір на опорну точку schem схема Error reading file %1: %2. Помилка читання файлу %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 Змінити ніжку %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer Шар %1 Bring forward Підняти вище Send backward Опустити нижче Bring to front Підняти наверх Split Wire Розгалузити провідник Join Wire Сполучити провідник Trace wires Розвести провідники Ratsnest wires Провідники навісного монтажу Select outdated parts Вибрати застарілі деталі Select locked parts Вибрати заблоковані деталі unable to open %1 Не вдалось відкрити %1 unable to parse %1 не вдалось проаналізувати %1 parse failure in %1 збій аналізц у %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) Вибачте, Fritzing не може обробити штирки та площинки одночасно (у %1) bad pin argument count хибний аргумент кількості штирків bad pad argument count хибний аргумент кількості площинок Unable to parse copper: %1 %2 %3 Не вдалось проаналізувати мідь: %1 %2 %3 outline is empty контур порожній the board outline layer, шар контура плати, silkscreen layer(s), шар(и) позначок, copper layer(s), шар(и) міді, mask layer(s), шар(и) маски, paste mask layer(s), шар(и) припою, Unable to translate svg curves in %1 Не вдалось перекласти криві SVG у %1 %1 layer export is empty. %1 шар експорту порожній. %1 layer export is empty (case 2). %1 шар експорту порожній (випадок 2). silk layer %1 export is empty шар позначок %1 експортовано порожнім silk export failure збій експорту шару позначок exported drill file is empty експортований файл свердла порожній drill export failure помилка експорту свердла exported mask layer %1 is empty експортований шар маски %1 порожній %1 mask export failure (2) %1 відмова експорту маски (2) mask export failure збій експорту маски exported paste mask layer is empty експортований клеєний шар маски порожній %1 layer: unable to save to '%2' %1 шар: не вдалось записати до '%2' Fritzing is unable to process the cutouts in this custom PCB shape. Fritzing не вдалось обробити вирізи у цій саморобній ДП. You may need to reload the shape SVG. Можливо, вам доведеться перезавантажити SVG обрис. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Fritzing вимагає, щоб вирізи було зроблено за допомогою інструментів 'віднімання' або 'вирізання' вашого графічного редактора. Unable to save pick and place file: %2 Не вдалось зберегти файл поверхневого монтажу: %2 footprint %1 not found in %2 опорну поверхню %1 не знайдено у %2 unexpected end of file in footprint %1 in file %2 неочікуваний кінець файлу опорної поверхні %1 у файлі %2 unexpected format (1) in %1 from %2 неочікуваний формат (1) у %1 з %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) На жаль, Fritzing ще не може одночасно обробляти штирки та площинки (у %1 у %2) unexpected end of file неочікуваний кінець файлу pad missing drill площинка не містить свердлінь pad missing attributes площинка не містить властивостей pad missing position площинка не містить положення pad missing shape площинка не містить обрису position missing params відсутні характеристики положення drill missing params відсутні характеристики свердлінь drill offset not implemented не вказано зміщення свердлінь drill missing ellipse params відсутні характеристики еліпсу свердлінь attributes missing params відсутні властивості характеристик bad layer mask parameter хибна характеристика шару маски Sorry, can't handle pad type %1 На жаль, неможливо обробити тип площинки %1 pad shape missing params обрис площинки не містить значень pad shape size is invalid розмір обрису площинки хибинй trapezoidal pads not implemented не дотримано трапецієподібність площинок shape delta not implemented дельтовидний обрис не дотримано non-circular holes not implemented некруглі отвори не реалізовані non-copper holes not implemented немідні отвори не реалізовані unable to handle pad shape %1 не вдалось впоратись із обрисом площинки %1 bad schematic definition %1 хибне визначення схеми %1 schematic part %1 not found in %2 схема деталі %1 не знайдено у %2 schematic %1 unexpectedly ends (1) in %2 схема %1 має неочікуваний кінець (1) у %2 schematic %1 unexpectedly ends (2) in %2 схема %1 має неочікуваний кінець (2) у %2 schematic %1 unexpectedly ends (3) in %2 схема %1 має неочікуваний кінець (3) у %2 failure in svg conversion 1: %1 %2 %3 збій перетворення SVG 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 збій перетворення SVG 2: %1 %2 %3 File Progress... Обробка файлу... Copying file %1 Копіювання файлу %1 File %1 already exists: it won't be overwritten Файл %1 вже існує: його не можна перезаписати Check for updates Перевірка оновлень Icon Значок Breadboard Монтажна плата Parts Деталі Wires Провідники Part Labels Позначки деталей Ratsnest Навісний монтаж Notes Примітки Rulers Лінійки Frame Рамка Text Текс Board Плата Silkscreen Top Верхній шар позначок Silkscreen Top (Part Labels) Верхній шар позначок (позначки деталей) Copper Fill Bottom Мідне заповнення знизу Copper Bottom Мідь знизу Copper Bottom Trace Мідна доріжка знизу Copper Fill Top Мідне заповнення зверху Copper Top Мідь зверху Copper Top Trace Мідна доріжка зверху Silkscreen Bottom Нижній шар позначок Silkscreen Bottom (Part Labels) Нжиній шар позначок (позначки деталей) Part Image Зображення деталі Unknown Layer Невідомий шар icon view вид значка breadboard view вид монтажної плати schematic view вид схеми pcb view вид ДП N/A QShortcut Ctrl for naming shortcut keys on menu items для йменування швидких клавіш на пунктах меню Ctrl Alt for naming shortcut keys on menu items для йменування швидких клавіш на пунктах меню Alt Shift for naming shortcut keys on menu items для йменування швидких клавіш на пунктах меню Shift Meta for naming shortcut keys on menu items для йменування швидких клавіш на пунктах меню Meta QuoteDialog Fritzing Fab Quote Пропозиції виробництва Fritzing Order your PCB from Fritzing Fab Замовте вашу друковану плату на виробництві Fritzing Copies Копія Price per board Вартість плати Price Вартість Please note that prices do not include shipping,<br /> Зверніть увагу на те, що ціни не включають доставку,<br /> possible additional taxes, or the checking fee.<br /> можливі додаткові податки та збори.<br /> For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Більш докладну інформацію про ціни можна отримати тут <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Visit Fritzing Fab Відвідайте виробництво Fritzing The total area of the %n PCB(s) in this sketch is Загальна площа %n друкованої плати у цьому нарисі складає Загальна площа %n друкованих плат у цьому нарисі складає Загальна площа %n друкованих плат у цьому нарисі складає %1 cm%3 (%2 in%3).<br /> %1 см%3 (%2 дюймів%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Замовляйте друковані плати з ваших нарисів на виробництві Fritzing.<br /> Take advantage of our quantity discount: Скористайтесь нашою знижкою на кількість: RecoveryDialog File Файл Last backup Остання резервна копія Last saved Останнє збереження file not saved файл не збережено <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Схоже що Fritzing несподівано упав, але дещо можна відновити</b></p><p>Відображається дата та час останнього резервування файлу. Якщо файл було збережено, дата та час буде показано для порівняння.</p><p>Початковий файл досі зберігається на диску, якщо його колись було збережено. Ви можете обрати, чи потрібно перезаписати файл вихідний файл після завантаження його відновленої копії.</p><p><b>Оберіть файли для відновлення з переліку знизу.</b></p> &Recover Відновити (&R) &Ignore Відхилити (&I) Resistor Resistor Резистор resistance опір You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' Ви можете ввести значення опору, або обрати його з випадного переліку. Формат nnn.dP, де P є одним з 'umkMG' ResizableBoard shape обрис width: %1mm ширина: %1мм height: %1mm висота: %1мм width(mm) ширина(мм) height(mm) висота(мм) keep aspect ratio зберегти пропорції Revert Повернути size розмір custom заданий A0 (1030x1456) A0 (1030x1456) A1 (728x1030) A1 (728x1030) A2 (515x728) A2 (515x728) A3 (364x515) A3 (364x515) A4 (257x364) A4 (257x364) A5 (182x257) A5 (182x257) A6 (128x182) A6 (128x182) Letter (8.5x11) Letter (8.5x11) Legal (8.5x14) Legal (8.5x14) Ledger (17x11) Ledger (17x11) Tabloid (11x17) Tabloid (11x17) Ruler width ширина S2S Failed loading '%1', %2 line:%3 col:%4 Не вдалось завантажити '%1', %2 рядок:%3 стовпчик:%4 Schematic not found for '%1' Не знайдено схему для '%1' Unable to load schematic '%1' for '%2' Не вдалось завантажити схему '%1' для '%2' Schematic '%1' is already using the 0.1inch standard. Схема '%1' використовує 0,1 дюймовий стандарт. Missing connector %1 in '%2' schematic of '%3' Відсутній роз’єм %1 у '%2' схеми '%3' Uunable to load schematic '%1' for '%2' Не вдалось завантажити схему '%1' для '%2' Failed loading schematic '%1', %2 line:%3 col:%4 Помилка завантаження схеми '%1', %2 рядок:%3 стовпчик:%4 SchematicFrame Project Проект Filename Назва файлу Date Дата Sheet Аркуш Rev Ревізія shape обрис of від date дата sheet аркуш SchematicSketchWidget Change label from %1 to %2 Змінити позначку з %1 на %2 Change voltage from %1 to %2 Змінити напругу з %1 на %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Зробити кольором по замовчанню: %1 Cancel Скасувати OK Гаразд Pick custom %1 color Current color (%1) SketchWidget loading part завантаження деталі done loading завантаження завершено Delete ratsnest Видалити навісний монтаж %1 %2 %1 %2 %1 %2 items %1 %2 предмети Select All Виділити все Deselect Зняти виділення Add %1 Додати %1 Selection Вибір Move %2 (%1) Перемістити %2 (%1) Move %2 items (%1) Перемістити %2 предмети (%1) Select %1 Вибрати %1 Select %1 items Вибрати %1 предмети Disconnect Відключити from %1 від %1 Move leg of Перемістити ніжку Connect Підключити to %1 до %1 Change leg curvature for %1. Змінити кривизну ніжки для %1. Change leg bendpoint for %1. Змінити опорну точку ніжки для %1. Change Змінити Create and connect wire Створити та під’єднати дріт Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Це схоже на спробу провести доріжку між шарами. Так не має бути: будь ласка, зв’яжіться із розробниками. Create and connect %1 Створити та під’єднати %1 wire провідник trace доріжка Rotate %2 (%1) Повернути %2 (%1) Flip %2 (%1) Розвернути %2 (%1) Double-click Двічі клацніть Drag or double-click Перетягніть або двічі клацніть or alt-drag to move the segment або потягніть з Alt'ом для переміщення відрізка Double-click to delete this bend point Двічі клацніть для видалення опорної точки Note text change Змінити примітку Change %1 label to '%2' Змінити %1 позначку на '%2' Change %1 color from %2 to %3 Змінити %1 колір з %2 на %3 Change color of %1 wires to %2 Змінити колір %1 дротів на %2 Change %1 width from %2 to %3 Змінити %1 ширину з %2 на %3 Change width of %1 wires to %2 Змінити ширину %1 дротів на %2 Move label '%1' Перемістити позначку '%1' %1 label '%2' %1 позначка '%2' Rotate Обернути Flip Віддзеркалити show %n part label(s) показати %n позначку деталі показати %n позначки деталей показати %n позначок деталей hide %n part label(s) приховати %n позначку деталі приховати %n позначки деталей приховати %n позначок деталей Resize Note Змінити розмір примітки Change Resistance from %1 to %2 Змінити Опір з %1 на %2 Change %1 from %2 to %3 Змінити %1 з %2 на %3 Resize ruler to %1 %2 Змінити розмір керувача на %1 %2 Resize board to %1 %2 Змінити розмір плати на %1 %2 Create wire from Ratsnest Створити дріт з наівсного монтажу Disconnect all wires from %1 Від’єднати всі дроти від %1 Disconnect all wires from %1 items Від’єднати всі дроти з %1 предметів Change image from %1 to %2 Змінити зображення з %1 на %2 change pin labels змінити позначки штирка Unrouted connections are highlighted in yellow. Нерозведені з’єднання буде виділено жовтим кольором. There are no unrouted connections Тут немає нерозведених з’єднань Unrouted connections Нерозведені з’єднання %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. %1 Увага: ви можете викликати це повідомлення, клацнувши мишею на стані розведення у рядку стану. Part '%1' not found in sketch Деталь '%1' не знайдено у нарисі Add %1 parts Додати %1 деталі Deselect all Зняти виділення з усього test connectors перевірити з’єднання SqliteReferenceModel The swapping mechanism is disabled for: Механізм обміну відключено для: and %1 other parts та %1 інших деталей and %1 other properties та %1 інших властивостей property '%1' in part '%2' with id '%3'. властивість '%1' у деталі '%2' з ідентифікатором '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. деталь '%1' з ідентифікатором '%2'; можливо немає 'родинних' властивостей. Stripboard Restored Відновити Cut Вирізати %1 %n strip(s) %1 %n стрічка %1 %n стрічки %1 %n стрічок rows рядок columns стовпчик %1 layout %1 схема SymbolPaletteItem voltage напруга label позначка Net labels Позначка ланцюжка Net labels cannot be blank Позначки ланцюжка не можуть бути пустими TipsAndTricks Fritzing Tips and Tricks Поради та хитрощі Fritzing Tips and Tricks Поради та хитрощі Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Fritzing зберігає файли створених і згенерованих деталей, та файли для інших тимчасових та довгострокових цілей, у локальній теці. У Mac OS та Linux це зазвичай ~/.config/Fritzing/. У Windows Vista та новіших — щось на кшталт C:\Users\[ім’я користувача]\AppData\Roaming\Fritzing\, а у Windows XP — C:\Documents and Settings\[ім’я користувача]\Application Data\Fritzing\. examples приклади Get a jump start by looking at the example circuits under File > Examples. Для початку, перегляньте приклади схем у меню Файл > Приклади. parts деталі Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords Не можете знайти свою деталь? Натисніть на значок лупи у Наборі деталей, і введіть кілька ключових слів If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor Якщо ви не можете знайти деталь у Наборі деталей, вам допоможе Узагальнена IC (Generic IC). Перетягніть її до свого нарису, а потім використайте віджет у Інспекторі для того щоб: обрати з 25 отворів та плат поверхневого монтажу; змінити позначку штирка; для DIP та SIP корпусів — змінити номери штирків. Також ви можете змінити назви штирків у Редакторі позначок штирків An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. Значки набору деталей можуть представляти декілька пов’язаних деталей. Тому, коли ви перетягуєте значок з набору деталей у нарис, переконайтесь, що ви подивились до Інспектора. Інспектор покаже всі доступні для заміни деталі, і дозволить замінити деталь на потрібну. Також, значок набору деталей буде у вигляді невеликої стопки, а не плоским, як звичайно. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). Вікно Інспектора (яке дозволяє змінити властивості деталей) доступне лише для деталей нарису, і недоступне для деталей з Набору деталей. moving and selection перемістити та вибрати To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. Для переміщення строго по горизонталі або вертикалі, затисніть клавіш Shift при перетягуванні. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). Якщо ви маєте проблеми з вибиранням деталі або частини дроту, спробуйте вибрати деталь що заважає, і перемістити її на задній план: використовуйте функції піднімання та опускання з меню 'Деталь', або контекстного меню (меню правої кнопки миші). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Для більш точного переміщення вибраних деталей використовуйте курсорні клавіші. Якщо при цьому затиснути Shift — переміщення відбудеться відразу на 10 одиниць. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. Клацніть на показнику положення миші у рядку стану (це знизу) для перемикання між міліметрами, пікселями та дюймами. curves and bendable legs кривизна та гнучкість ніжок In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. У виді Монтажної плати, для перетягування та згинання ніжок зі збереженням підключення їх до плати, натисніть Alt (у Linux: Meta), коли почнете перетягування. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. У виді Монтажної плати, для того щоб тягнути дріт з кінця гнучкої ніжки, потягніть його з клавішем Alt (у Linux: Meta). In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. У виді Монтажної плати або Друкованої плати, для викривлення дроту або ніжки, затисніть Ctrl (Mac: Command). Ви можете обрати будь-яке викривлення за замовчуванням у Вподобаннях. rotation обертання To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. Для вільного обертання деталі у виді Монтажної або Друкованї плат, оберіть її, а потім підведіть вказівник до будь-якого її кута, аж доки не побачите значок повороту. Затисніть кнопку миші, і кут буде слідувати за вказівником при перетягуванні. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. Для вільного обертання тексту або зображення у виді Друкованої Плати, утримуйте Alt (у Linux: meta) і обертайте як завжди. layers and views шари та види To drag the canvas, hold down the space bar and drag with the mouse. Для переміщення поля затисніть пробіл, і перетягніть його за допомогою миші. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. Щоб перемкнути видимість шару у видах, перейдіть у меню 'Вид', та виберіть один з пунктів видимості шарів. Або відкрийте палітру <b>Шари</b> з меню <b>Вікно</b>. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. При експорті зображень з Fritzing є можливість обрати шари, які ви бажаєте експортувати. Перед експортування перейдіть до меню 'Вид', і приховайте непотрібні шари. part labels позначки деталей To edit a part label, double-click it, or use the text input widget in the inspector window. Для редагування позначки двічі клацніть по ній, або використовуйте текстовий пристосунок у вікні Інспектора. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. Для відображення різних властивостей на позначках, а також для їх обертання або зміни шрифта, клацніть по позначці правою кнопкою. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. Для переміщення позначки незалежно від деталі, оберіть спочатку деталь — підсвітяться і деталь, і позначка. Після цього можна вибрати позначку і перетягнути її. wires and bendpoints дроти та опорні точки To add a bendpoint to a wire, double-click where you want the bendpoint. Для додавання опорної точки до дроту, двічі клацніть там, де має бути опорна точка. To delete a bendpoint from a wire, double-click it. Для видалення опорної точки з дроту, двічі клацніть по ній. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. У виді Схеми або Друкарської Плати, якщо ви потягнете опорну точку з Alt'ом (Linux: Meta), ви витягнете новий дріт з опорної точки. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Для переміщення ділянки дроту (відрізку між двома опорними точками), потягніть його з Alt'ом (Linux: Meta). Якщо утримувати Shift — ділянку буде переміщено строго горизонтально або вертикально. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. Переміщуйте кінець дрота або опорну точку з Shift'ом — це дозволить переміщення під кутом, кратним 45 градусам. Якщо ділянку дроту під’єднано до іншої ділянки, то ділянка яку ви тягнете, стане під кутом у 90 градусів до сусідньої ділянки. connections з’єднання To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Щоб побачити всі роз’єми, під’єднані до даного роз’єма, тримайте мишу на цьому роз’ємі — всі з’єднання буде виділено. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. Навісний монтаж (дуже тонкі дроти) між з’єднаннями в одному виді означає, що в іншому виді ці з’єднання так чи інакше поєднані. parts editor редактор деталей Check out Parts Editor Help under the <b>Help</b> Menu. Дивіться довідку по Редактору деталей у меню <b>Довідка</b>. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. Generic IC - Узагальнена ІС (інтегральна схема, мікросхема), Mystery Part - Таїнство Детал Перед використанням Редактора деталей, подивіться на можливості Узагальненої ІС (Generic IC), Таємниці деталі (Mystery Part) та Штиркового з’єднувача (Pin Header). Перемістіть щось із цього до нарису, і ви зможете змінити кількість штирків, відстань між штирками та інші властивості. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. Щоб вибрати зображення під іншим зображенням у Редакторі деталей, використовуйте коліщатко миші з клавішем Shift. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Ви можете використовувати Редактор деталей для пошуку файлів SVG із зображенням деталей для даного виду. У Редакторі деталей клацніть по закладці цього виду, потім натисніть <b>Показати у теці</b> у меню <b>Файл</b> Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Не зберігайте зроблені вами деталі у каталозі встановлення Fritzing. Якщо ви оновите Fritzing, ці файли можуть бути видалені. Крім того, файли у каталозі встановлення Fritzing не можуть бути збережені у нарисі (.fzz), отже ви не зможете ними поділитись. pcb layout шар ДП Always lead a trace straight out of a pin. This helps to prevent short circuits. Завжди проводьте доріжку безпосередньо зі штирка. Це допоможе запобігти короткому замиканню. Through-hole parts can be traced from either side of a PCB. Деталі, що кріпляться через монтажні отвори, можуть бути розведені з будь-якого боку ДП. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Якщо з одного боку ДП розвести доріжки горизонтально, а з другого вертикально — це може полегшити життя. Route traces in 45-degree angles to reduce noise. Для зменшення шуму розводьте доріжки під кутом 45 градусів. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. Якщо у Fritzing відсутня потрібна вам деталь, і ви не хочете робити її самостійно — використовуйте штирковий з’єднувач як з’єднувачі, і сітку для вирівнювання. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Ви можете поставити своє лоґо на шарі позначок вашої друкованої плати. Просто використайте розділ Лоґо основної бібліотеки, та оберіть ваш файл. Найкраще підходить SVG формат. Use copper-blocker parts to mask out areas that you want free of copper fill. Використовуйте блокатори міді для маскування ділянок, які ви бажаєте очистити від мідного заповнення. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). Для зміни ширини доріжок оберіть доріжку, і використайте поле випадного переліку Інсперктора <b>ширина</b>. Ви можете знайти значення у переліку, або ввести власне значення від 8 до 128. To create a custom shape for your PCB, import an SVG file. Для створення обрису вашої ДП імпортуйте SVG файл. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino Щоб миттєво створити накладку (shield) у стилі Arduiono, замініть обрис друкованої плати на прямокутник Arduino pcb production вигодовлення ДП Smaller PCBs are more affortable than larger ones. Save space and money. Маленькі друковані плати доступніші за великі. Заощаджуйте місце та гроші. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. Отримайте вашу ДП швидко та просто з Fritzing Fab. Наведіть мишу на кнопку 'Виготовити' для докладнішої інформації. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. При використанні послуги Fab Service: використовуйте блокатори міді, якщо ви бажаєте залишити певні ділянки ДП без мідного заповнення. Це прямокутні деталі змінного розміру, що приховують мідне заповнення яке вони прикривають. notes примітки To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. Для вставлення посилання до примітки виділіть текст у примітці, та натисніть Ctrl-l (Mac: Command-l). Для зміни вихідного посилання виділіть пов’язаний текст, і знову натисніть Ctrl-l (Mac: Command-l). local file storage локальне сховище файлів TraceWire Select from the dropdown, or type in any value from %1 to %2 Оберіть з випадного переліку, або введіть будь-яке значення від %1 до %2 width ширина TranslatorListModel English - %1 Англійська — %1 French - %1 Французька — %1 German - %1 Німецька — %1 Spanish - %1 Іспанська — %1 Portuguese (European)- %1 Португальська (європейська) — %1 Portuguese (Brazilian) - %1 Португальська (бразильська) — %1 Hungarian - %1 Угорська — %1 Estonian - %1 Естонська — %1 Dutch - %1 Нідерландська — %1 Italian - %1 Італійська — %1 Polish - %1 Польська — %1 Turkish - %1 Турецька — %1 Swedish - %1 Шведська — %1 Galician - %1 Галісійська — %1 Indonesian - %1 Індонезійська — %1 Danish - %1 Japanese - %1 Японська — %1 Russian - %1 Російська — %1 Hebrew - %1 Іврит — %1 Arabic - %1 Арабська — %1 Hindi - %1 Гінді — %1 Chinese (Simplified) - %1 Китайська (спрощена) — %1 Chinese (Traditional) - %1 Китайська (традиційна) — %1 Czech - %1 Чеська — %1 Romanian - %1 Руумнська — %1 Thai - %1 Тайська — %1 Greek - %1 Грецька — %1 Bulgarian - %1 Болгарська — %1 Korean - %1 Корейська — %1 Slovak - %1 Словацька — %1 Bengali - %1 Бенгальська — %1 Persian - %1 Перська — %1 Slovenian - %1 Словенська — %1 Marathi - %1 Маратхі — %1 Ukrainian - %1 Українська — %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close Готово No new versions found. Немає новішої версії. A new main release is available for downloading: Новий основний реліз доступний для завантаження: A new interim release is available for downloading: Новий проміжний реліз доступний для завантаження: Checking... Перевірка... Sorry, unable to retrieve update info На жаль, не вдалось отримати інформацію про оновлення WelcomeView Recent Sketches Останні нариси New Sketch Новий нарис Open Sketch Відкрити нарис Fab Shop Fritzing CreatorKit Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. Fritzing CreatorKit дозволяє швидко, легко та розважаючись увійти до світу інтерактивної електроніки. order now >> замовити >> Get your Creator Kit now. Отримай свій Creator Kit негайно. Fritzing Fab Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. Fritzing Fab — це проста та зручна послуга зі створення професійних друкованих плат із ваших нарисів Fritzing. produce your first pcb now >> виготовити вашу першу друковану плату >> Order your PCB now. Замовити друковану плату. <a href='%1'><img src='%2'/></a> <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Новини Fritzing. Fritzing Projects. Проекти Fritzing. <a href='%1'><img src='%2' /></a> <a href='%1'><img src='%2' /></a> No recent sketches found Немає останніх нарисів Unable to reach blog.fritzing.org Немає доступу до blog.fritzing.org Unable to reach friting.org/projects Немає доступу до friting.org/projects Tip of the Day: Порада дня: All Tips Всі поради Next Tip Наступна порада Wire super fine (8 mil) надтонкий (0,2 мм) extra thin (12 mil) дуже тонкий (0,3 мм) thin (16 mil) тонкий (0,4 мм) standard (24 mil) типовий (0,6 мм) thick (32 mil) товстий (0,8 мм) extra thick (48 mil) дуже товстий (1,2 мм) blue синій red червоний black чорний yellow жовтий green зелений grey сірий white білий orange жовтогарячий ochre брунатно-жовтий cyan блакитний brown брунатний purple фіалковий pink рожевий color колір Banded Смужастий ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_ur.qm000066400000000000000000000000271250202676700217260ustar00rootroot00000000000000 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Stop Now Best So Far Cancel Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Cancel OK Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width BinManager Parts BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) Select a Fritzing Parts Bin file to open Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Cannot set a NULL bin as the current one Searching... Bin Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin Please choose a name for the bin: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file Images Select an image file to load due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load Unable to load image from %1 %2 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape BreadboardLogoItem color Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O &Disconnect Disconnect from serial port Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org Too close to a border (%1 layer) %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging DeleteDialog Also delete the file Remove Don't remove Dip chip label FApplication Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Import files from previous version? Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Import Do not import now Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) FirstTimeHelpDialog First Time Help <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window Ctrl+W Close the current sketch %1 - %2 Specify a file name Save... Save Don't Save Cancel Ctrl+D Save "%1" Do you want to save the changes you made in the document "%1"? Your changes will be lost if you don't save them. GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel OK OK and ground fill OK and copper fill Hole hole size HtmlInfoView Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Properties Tags Connections conn. name type connected to %n item(s) (autoroutable) Wire Ratsnest wire Trace wire %1 v. %1 %2 obsolete Locked Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. location rotation degrees ItemBase family type model size color resistance capacitance inductance voltage current power pin spacing rated power rated voltage rated current version package shape form part number maximum resistance pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel OK LayerPalette show all layers LinkDialog url: text: Cancel OK LogoItem text shape due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display Unable to display image from %1 MainWindow Ctrl+R Rotate Clockwise Alt+Ctrl+R Rotate Clockwise Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Breadboard Schematic PCB Click to highlight unconnected parts Rotate Share Flip Autoroute Fabricate Both Layers Bottom Layer Top Layer View from Above View from Below Add a note Export for PCB Ready Save %1 Fritzing Unable to open '%1': %2 No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' Specify a file name Fritzing Part (*%1) Unable to export %1 to shareable sketch MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. Do you want to keep the imported parts? No connections to route Routing completed Routing completed using %n jumper part(s) %1 of %2 nets routed - %n connector(s) still to be routed %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist No exactly matching part found; Fritzing chose the closest match. Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' Fritzing (*%1) Unrouted connections There are no unrouted connections in this view. (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome Inspector Undo History Layers Couldn't get the dock widget PDF (*.pdf) PNG Image (*.png) JPEG Image (*.jpg) SVG Image (*.svg) BoM Text File (*.html) PostScript (*.ps) Printing... Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. All traces have not yet been routed. Do you want to proceed anyway? Proceed Cancel Choose a folder for exporting Sketch exported Export... Exporting... Unable to save %1 Cannot print to %1 Cannot write file %1: %2. Saved '%1' Unable to export %1 as shareable &Save Ctrl+S Save the current sketch &Save As... Shift+Ctrl+S Share online... Post a project to the Fritzing website JPG... Export the visible area of the current sketch as a JPG image PNG... Export the visible area of the current sketch as a PNG image PostScript... Export the visible area of the current sketch as a PostScript image PDF... Export the visible area of the current sketch as a PDF image SVG... Export the current sketch as an SVG image List of parts (&Bill of Materials)... Save a Bill of Materials (BoM)/Shopping List as text XML Netlist... Save a netlist in XML format SPICE Netlist... Save a netlist in SPICE format Eagle... Export the current sketch to Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Etchable (PDF)... Export the current sketch to PDF for DIY PCB production (photoresist) Etchable (SVG)... Export the current sketch to SVG for DIY PCB production (photoresist) &Print... Ctrl+P Print the current view This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. Export SVG... Export Bill of Materials (BoM)... Unable to save BOM file, but the text is on the clipboard. Export SPICE Netlist... Export Netlist... Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Select a Fritzing File to Open Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Cannot find file %1. Cannot read file 1 %1: %2. Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? File '%1' not found the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to directly loading parts loading %1 (model) loading %1 (breadboard) loading %1 (pcb) loading %1 (schematic) New Ctrl+N Create a new sketch &Open... Ctrl+O Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch Shell launch %1 throw test exception throw a fake exception to see what happens &Quit Ctrl+Q Quit the application &Open Example All MainWindow::populateMenuWithIndex: couldn't load example with id='%1' &Open Recent Files &%1 %2 Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents Paste in Place Ctrl+Shift+V Paste clipboard contents in place &Duplicate Ctrl+D Duplicate selection &Delete Delete selection Delete Minus Delete selection without attached wires &Delete Wire Delete Wire up to bendpoints &Select All Select all elements &Deselect Deselect Add Note &Preferences... Show the application's about box Edit (new parts editor) Open the new parts editor on an existing part Disconnect All Wires Disconnect all wires connected to this connector Update InfoView on hover Export Normalized SVG Export 1000 dpi SVG of this part in this view Export Normalized Flattened SVG Export 1000 dpi Flattened SVG of this part in this view Dump all parts Debug dump all parts in this view Test Connectors Connect all connectors to a single test part Rotate current selection 45 degrees clockwise Rotate the selected parts by 90 degrees clockwise Rotate the selected parts by 180 degrees Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 180� Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate current selection 45 degrees counter clockwise &Flip Horizontal Flip current selection horizontally &Flip Vertical Flip current selection vertically Bring to Front Shift+Ctrl+] Bring selected object(s) to front of their layer Bring Forward Ctrl+] Bring selected object(s) forward in their layer Send Backward Ctrl+[ Send selected object(s) back in their layer Send to Back Shift+Ctrl+[ Send selected object(s) to the back of their layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Lock Part Prevent a part from being moved Sticky If a "sticky" part is moved, parts on top of it are also moved Select All Locked Parts Select all parts that can't be moved &Show part label Show/hide the label for the selected parts &Export... Export selected part Add Bendpoint Add a bendpoint to the selected wire Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Straighten Curve Straighten the curve of the selected wire Select outdated parts Update selected parts Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In Ctrl++ Zoom in Ctrl+= &Zoom Out Ctrl+- Zoom out &Fit in Window Ctrl+0 Fit in window &Actual Size Actual (real world physical) size 100% Size Shift+Ctrl+0 100% (pixel) size Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+1 Ctrl+2 Ctrl+3 Ctrl+4 Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard Show the breadboard view &Show Schematic Show the schematic view &Show PCB Show the PCB view Show Code Show the code (programming) view Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view &Show All Layers Show all the available layers for the current view &Hide All Layers Hide all the layers of the current view &Minimize Ctrl+M Minimize current window Debugger Output Online Tutorials Ctrl+? Open Fritzing help Donate to Fritzing Open Fritzing donation web page Online Projects Gallery Open Fritzing examples Online Parts Reference Open Parts Reference Check for updates... Check whether a newer version of Fritzing is available for download &About Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks First Time Help Display First Time Help &About Qt Show Qt's about box Report a bug... Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... Import parts and bins from previous installation Parts Editor Help Display Parts Editor help in a browser Raise and Lower Align &Add to bin... Add selected part to bin &File &Export as Image for Production &Edit &Part &View &Window &Routing Ground Fill &Help Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen Delete top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup Sorry, "%1" has not been implemented yet Autoroute connections... Shift+Ctrl+A &Create trace from ratsnest Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Show unrouted Highlight all unrouted connectors Select All Traces Select all trace wires Select All Wires Select all wires Select All CopperFill Select all copper fill items Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select All "Don't Autoroute" Traces Select all trace wires excluded from autorouting Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select All Jumpers Select all jumper item parts Select All Vias Select all via parts Tidy Wires Tidy selected wires Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Copper Fill Fill empty regions of the copper layer--not including traces connected to a GROUND Remove Copper Fill Remove the copper fill Choose Ground Fill Seed(s)... Fill empty regions of the copper layer--fill will include all traces connected to the seeds Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Shift+Ctrl+D Check Loaded Traces Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Set both copper layers clickable Shift+Ctrl+3 Set copper top layer clickable Shift+Ctrl+2 Set copper bottom layer clickable Shift+Ctrl+1 Copper Top and Copper Bottom layers are both active Copper Top layer is active Copper Bottom layer is active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. Autorouting... Autorouting Progress... jumpers copperfill vias Remove Bendpoint Please choose the previous Fritzing folder... The folder "%1" isn't a Fritzing installation folder You will have to restart Fritzing in order to use the imported parts Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Generating %1 fill... ground copper Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Remove copper fill &Wire Color Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Launch %1... No outdated parts found. All your parts are up-to-date. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. Outdated parts There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. Do you want to update now? unable to find replacement for %1. Update %1 part(s) Successfully updated %1 part(s). Please check all views for potential side-effects. OK Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org Optimizing traces... ModelBase Unable to find the following %n part(s): at File save failed! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) MysteryPart label chip label NetLabel net label Note [write your note here] PCBSketchWidget Create Trace from Ratsnest Fritzing Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Click this connector to drag out a new trace. Change trace layer Your sketch does not have a board yet! Please add a PCB in order to use copper fill. %1 Fill: please select the board you want to apply fill to. Ground Copper Please designate one or more ground fill seeds before doing a ground fill. Fritzing error: unable to render board svg (1). Fritzing error: unable to render copper svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Copper fill: please select only the board you want to fill. Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow There is one last edit still pending. The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed Close without saving? This part can not be saved as-is: Do you want to keep working or close without saving? Close without saving Keep working Icon Metadata Connectors SVG Inspector Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Load image for view... Open a file to use as the image for this view of the part. Show in Folder On the desktop, open the folder containing the current svg file. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Remove Internal Connection &File Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export &Edit Parts Editor This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to write svg to %1 Unable to parse fzp file %1 Fritzing (New) Parts Editor Icon View Metadata View Connectors View Show Icon Ctrl+4 Show the icon view Show Metadata Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Show the connector metadata in a list view Make only this view visible The part will only be visible in this view and icon view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Change description Change %1 to '%2' Change tags Duplicate problem Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Change properties Change connector %1 SVG problem This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image Conversion problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Unable to load image file '%1': %2 Unable to load image file '%1' Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. Copy problem Unable to make a local copy of: '%1' no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save Cancel Move terminal point Remove connector Remove %1 connectors Save "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector Add %1 connectors Internal connections are very messed up. Remove internal connection from '%1' Add internal connection from '%1' to '%2' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description Set the default part label prefix Label Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties Set the part's tags Tags PESvgView width: height: PEToolView Connector List (a checkmark means the graphic was selected) Set Internal Connections Set this checkbox to edit internal connections by drawing wires Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center W N S E center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape center north east south west connect to PaletteItem Edit Pin Labels Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit Edit label text Hide Hide part label Display Values Flip/Rotate Font Size Rotate the label by 45 degrees clockwise Rotate the label by 90 degrees clockwise Rotate the label by 135 degrees clockwise Rotate the label by 180 degrees Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise Rotate 45� Clockwise Rotate 90� Clockwise Rotate 135� Clockwise Rotate 180� Rotate 135� Counter Clockwise Rotate 90� Counter Clockwise Rotate 45� Counter Clockwise Rotate the label by 45 degrees counter clockwise Flip Horizontal Flip label horizontally Flip Vertical Flip label vertically Tiny Set font size to tiny Small Set font size to small Medium Set font size to medium Large Set font size to large Label text Display the text of the label Display the value of property %1 Set label for %1 Label text: PartsBinPaletteWidget Untitled Bin Specify a file name Fritzing Bin (*%1) Fritzing Cannot find file %1. Cannot read file %1: %2. Loading... loading bin '%1' Save bin "%1" Do you want to save the changes you made in the bin "%1"? Your changes will be lost if you don't save them. Save Don't Save Ctrl+D Cancel Add to bin Do you really want to add the selected part to the bin? Change icon color... Change the color of the icon for this bin. Select a color for this icon Perfboard size set board size Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel rows columns PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel Save Undo Redo PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog General Code View Cancel OK Mouse Wheel Behavior Change Wheel Behavior Autosave Autosave every: minutes Language Colors %1 (click to change...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight Unconnected Highlight Command Control no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Open Save Platform Board Port Serial Monitor Upload Select a program file to load Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit Undo Redo &Cut Cut selection &Copy Copy selection &Paste Paste clipboard contents &Select All Select all text &Preferences... Show the application's about box &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller &View File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. Code Window Code Window - %1 %1%2 QObject Autorouter Settings Part %1 '%2' Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position Set Ground Fill Seed Ground Fill Seed Editor Pin Label Editor Preferences Please note that a new language setting will not take effect until the next time you run Fritzing. Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings %1 wires moved from their saved position in %2. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> Edit link mm in The file '%1' is read-only; please use a different filename. Part Wire Set Grid Size Cannot read file %1: %2. Parse error (1) at line %1, column %2: %3 %4 The file %1 is not a Fritzing file (2). The file %1 is not a Fritzing file (4). The file %1 is not a Fritzing file (3). Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. Parse error (2) at line %1, column %2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. Fritzing cannot load the parts bin Basic Input Output ICs Power Connection Microcontroller Breadboard View Schematic View PCB View Tools Shields LilyPad Other Sensors Part already in bin The part that you have just added, is already there, we won't add it again, right? a label a value Select %1 Set all to: Pad ii Icon View Internal Connections <b>Name:</b> Set the connectors's title <b>Description:</b> Set the connectors's description <b>id:</b> <b>type:</b> N/A files Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. bb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Select all %1 Convert to Via Convert Via to Bendpoint schem Error reading file %1: %2. %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 Layer Bring forward Send backward Bring to front Split Wire Join Wire Trace wires Ratsnest wires Select outdated parts Select locked parts unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. %1 layer export is empty (case 2). silk layer %1 export is empty silk export failure exported drill file is empty drill export failure exported mask layer %1 is empty %1 mask export failure (2) mask export failure exported paste mask layer is empty %1 layer: unable to save to '%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to save pick and place file: %2 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid trapezoidal pads not implemented shape delta not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 File Progress... Copying file %1 File %1 already exists: it won't be overwritten Check for updates Icon Breadboard Parts Wires Part Labels Ratsnest Notes Rulers Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Bottom Copper Bottom Trace Copper Fill Top Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer icon view breadboard view schematic view pcb view QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Fritzing Fab Quote Order your PCB from Fritzing Fab Copies Price per board Price Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape width: %1mm height: %1mm width(mm) height(mm) keep aspect ratio Revert size custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color Cancel OK Pick custom %1 color Current color (%1) SketchWidget loading part done loading Delete ratsnest %1 %2 %1 %2 items Select All Deselect Add %1 Selection Move %2 (%1) Move %2 items (%1) Select %1 Select %1 items Disconnect from %1 Move leg of Connect to %1 Change leg curvature for %1. Change leg bendpoint for %1. Change Create and connect wire Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Rotate %2 (%1) Flip %2 (%1) Double-click Drag or double-click or alt-drag to move the segment Double-click to delete this bend point Note text change Change %1 label to '%2' Change %1 color from %2 to %3 Change color of %1 wires to %2 Change %1 width from %2 to %3 Change width of %1 wires to %2 Move label '%1' %1 label '%2' Rotate Flip show %n part label(s) hide %n part label(s) Resize Note Change Resistance from %1 to %2 Change %1 from %2 to %3 Resize ruler to %1 %2 Resize board to %1 %2 Create wire from Ratsnest Disconnect all wires from %1 Disconnect all wires from %1 items Change image from %1 to %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all test connectors SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage label Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. parts editor Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 German - %1 Hungarian - %1 Estonian - %1 Dutch - %1 Italian - %1 Polish - %1 Swedish - %1 Galician - %1 Indonesian - %1 Danish - %1 Japanese - %1 Russian - %1 Hebrew - %1 Arabic - %1 Hindi - %1 Chinese (Simplified) - %1 Chinese (Traditional) - %1 Czech - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Korean - %1 Slovak - %1 Bengali - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 French - %1 Spanish - %1 Portuguese (European)- %1 Portuguese (Brazilian) - %1 Turkish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close No new versions found. A new main release is available for downloading: A new interim release is available for downloading: Checking... Sorry, unable to retrieve update info WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) standard (24 mil) thick (32 mil) extra thick (48 mil) blue red black yellow green grey white orange ochre cyan brown purple pink color Banded ZoomSlider % fritzing-app-0.9.2b/translations/fritzing_zh_cn.qm000066400000000000000000003310121250202676700224020ustar00rootroot00000000000000ng  ֍?V,H5='pSA"o{B"ee=eCσܤ Kܤ7x UV ef5x.N!"*yJ*y.*L**/*%M<*%)*0N%+hO+$+P+Q9+S+0,B?+,Df-sW:D;(FdUH5IX-FIX09IX5,J6=KQL4c=6M8MeGM5;P,EOPW=RU\|RxRUj>VgQ>VVAKV>WmBXYYgRZ8,V[ %[f3$[f3N\]42^P_C`JbpRscge:i' iIjcb#zjcb> jcbkje<jɢ>k"mTtn rx3rx|ntZ@,t-ui ui wmA6yXye#OyeByeI(ye yeeyegyBygzl %zlzzEz{ %C,{xd{x}}f{}}|UUW^]ep{|)cP 5BD5bLR0 S_^@~$.j'+FYcZث-.u9d[uT3J>[ RWR>\$q  V#uJNt[:+\ G"b=&a^)tD){e1*J~*,24M6F9q?yRJvg L#7xL4wkO. HTZ]0e>Se:qOyr{(ydmEyMNA[%5E`,V A$z pҊP9lMrlN2 :C` cJ<2]1N^+.>oDRXl͌Ӓ2Lo07.hwsKv_*tRUP3N[3 19&WE.S44W?..xTBɢC>DAJĮQ˯!RԢfTIYXJYYK'YZK^4 lTRdl]pt.t*tuTu5TcuT#xe7xesxic9y9<|Ds 'h9[T LsST$UIş. ^4IdjP'/R.;AC;Atg0u0uuh±[±ĵSLCR:.EaapSd9cynFn[b-G\!u:tA;C|`} Vbh,Qpqp & ( 5DTU!7T#[s3R>o5{.m4 v;V=>H*OFJCu^FpF.H0 ZNa* RB3gV|>hXMrEYhWwyrp>OrxPsu?m|P}N?1$oMMB=\r'[q~w%^r%ڮ=~g'QMܡ~ǒqտjֺPfd"Qcs2~lSO1"u~Aʳ+GlrIponZ9D6'e(Ïz*Zy@5;N=EG$ PѧITDXjaa\)cO&WjNl8zbj{eD|/}9|ou"nDׅU[p].bpɱZHI iI I/I28IDIE,IZI,II dI#I%Ihz:@ZYkdF(R6&vD) R`  b,ctYNV#k  8~a~0b@9]aFG ٶ)ۘlDFBN:fu; q:z}v.!^ iK ׎~s^ Up^g](~x(,]T5:I8[';}@EwK_E@Q0QMkRNW^zy ^b-_pd_zS`r,i\ V lOpI[qWr |\ttJz@|a@t?z(ECDN n]=]u ¡>(Z Z p%:EvC9]]dDDLVLCWZf:@9>֣;֣j\h(amVWޛnne9cY-!9lDwGX5E'p 3(9"S{&|8u'SO(?-3eLf. q.@51,2;!Y{}]Wߺ!f@>{^L;ipz`;3A0F3gp(/ H%`$&\b)w՗,ι-B#`2AwCVE E:`F?:H4ІHto,HKEI'YN'O;P1YQqX^ab]AfCfCDf|7fRgKi'5i-lvyujwJFyz.|Ԃh|^b|^0(`A1"Q0.~1*X,xR>7STSS{%[WI$Bnr]*y{ G&"3Mneʗ /Кl}л%Ml"EK:x75';ezT5j O\> \~P +n E" |UZ .Z w~   P !yE $)~! .5~K 0 0!Sl% 5GZ 6T ;="[ BU9 Exj GȧXC Mg+ Q;0 Ser[ \u; aB cϥ d`X lOJ lQ t7 uio9 u} ~ .l6 ~Sv N=  r ^1P ;.i D : +=P B18 N!z .L R s, ŦEd H 8 ,`_ ;8 ՛I {uY Qw Q ~G F v : i T   R ^@ JR `! 7@ i7 2H  !q !q #$k )r ?"Ec CDv M | N=K P Ui [> ^5 a4p c3"H c3{ d= d8& eKnv eRUU e' e^ fjm g7C k2{ k2& qw= su? tqor v N Ȑ ek ! ~ % #"c ,K ^   a  "n6 9 9E NJ Ɍ4>F vL v Ϯ ; Ҍ 0/@ 0t ˺+ Kqs  ;'t c & .L U  T<  V] ~ ~  gG# 7 #e! %4IN (VX ) C )8X )O * *@ -# -mn8U 8)W ? 8a H K2g' K2g& N>e Vn Ys bR g gy` i$eW` l? ) 7 1  9b Ŋ Q /  4r @Gr Lg u -nm ,.| a f ^ qB %? g, N AR }f= p[Q Z7 + H 1 # KGSL : tq 4X >֤ W   w L`1 IQ 5 j . ` PX / RP, #k^ %^y %^8 ,\j -L /~~? 9sw4 ;z =m, F^ L. M&` O~ Wj `l af eu? eZ hȾ: oF r1 r tT z na z n6 "u ]DP @.  $D )?{ \ @dr q ^) Gr ,ZB , j` L. /dC /o bh 'Ԇ   B z 1 m4{n B9c{ E%y .x 9 T7g ɠ.DF ?w  ' 6 KT B ~- .i or UW ˞ڌ Jp ( % fV  & #Ѯͺ 3F~ 7nP < F >O ?څ A) A& DDC G0Y LR;S R/Xq X4 X Zg@y [ : _kg cDn c| f fk1# i+r kcӠ m[a qU!X u;% v vHB vCk3 }R # }F  mN 15 w W b ~ z% ~% & @l R\ <' ՞9* ^^% cYG NF5 ' _q ^  d  cL ~&Q7 '13z {d  rcWD(/x 9];ƊKra.0a.wfTfTE7v8%w=)_yDn~fPi-o#'Fnnq$)y8SRQ3xsxãCS,ciucŅ_Ņ8AC#qt[q~? o}i 2~u}*"TN3$ /`iw16=3?=VX=_%@~TVW3]t>^NUav!5fghiR_i0mpsV3vgUlw|>izz|`}$7/@^I *nF;pCd^lz9hbjcjcv_MU"D"XCTa;Apq>+sc_w\Wi\<b>Nxu[GNU GPL v3 QvNQ[u[ CreativeCommons:BY-SA?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBox0







    AboutBox4Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. AboutBox)Department of Bauhaus-University Weimar, AboutBox3Durrell Bishop, David Cuartielles, Fabian Hemmert, AboutBoxFritzing a test spin. AboutBoxFritzing vO\f/:Fritzing is made by: AboutBox0Fritzing is made possible with funding from the AboutBox*Gero Herkenrath, Jeff Hoefs, Tom Hulbert, AboutBox6IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, AboutBox%Jan Sieber, Yaniv Steiner, Olaf Val, AboutBox-Jonathan Cohen, Marcus Paeschke, Omer Yosha, AboutBox6Jussi Ängeslevä, Massimo Banzi, Ayah Bdeir, AboutBox0MWFK Brandenburg, the sponsorship of the Design AboutBox%Mariano Crowe, Johannes Landstorfer, AboutBox!Michaela Vieser and Julia Werner.AboutBox4Special thanks goes out as well to all the students AboutBox ryR+a":Special thanks goes out to: AboutBoxJa" Kurt BadeltTMiguel Solis [srYv,DThanks to Kurt Badelt and Miguel Solis for the Spanish translation, AboutBox,Tom Igoe, Hans-Peter Kadel, Till Savelkoul, AboutBox2Travis Robertson, Stefan Hermann, Brendan Howell, AboutBox0and alpha testers who were brave enough to give AboutBoxX &#313;ubom&iacute;r Ducho&#328; [emOQKv, ?to Ĺubomír Duchoň for the Slovak translation, AboutBox4Alexander Kaltsas[^ Jv, 0to Alexander Kaltsas for the Greek translation, AboutBox2Gianluca Urgese [aY'R)rHv,0to Gianluca Urgese for the Italian translation, AboutBox.Hiroshi Suzuki [eerHv,0to Hiroshi Suzuki for the Japanese translation, AboutBox&Jinbuhm Kim[v, +to Jinbuhm Kim for the Korean translation, AboutBox,Josef Dustira[cwQKv, ,to Josef Dustira for the Czech translation, AboutBoxDNuno Pessanha Santos [arY(k'm2)rHv,Cto Nuno Pessanha Santos for the Portuguese (European) translation, AboutBox*Robert Lee [~AOSN-erHv,9to Robert Lee for the Chinese (Traditional) translation, AboutBox4Vladimir Savinov [OWerHv,1to Vladimir Savinov for the Russian translation, AboutBox0YuelinTNinjia [{OSN-erHv,@to Yuelin and Ninjia for the Chinese (Simplified) translation, AboutBoxSmCancelAutorouteProgressDialogsW(P\kbStop NowAutorouteProgressDialog )e>eˏlcR6zoom and pan controlsAutorouteProgressDialog>0.01inch0.254mm vg\yf/NN*Y}v؋P<04A keepout of 0.01 inch (0.254 mm) is a good default.AutorouterSettingsDialogSmCancelAutorouterSettingsDialogxn[OKAutorouterSettingsDialogNTWSProduction typeAutorouterSettingsDialog~[^ Trace widthAutorouterSettingsDialog[NIcustomAutorouterSettingsDialogR6homebrewAutorouterSettingsDialogNN professionalAutorouterSettingsDialogQCN^Bin BinManager8^{tVh::n^h{~:N n^'%1'O\N:dirty;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManager4^{tVh::feh:N b^'%1'ndirty;BinManager::updateTitle: Couldn't set the bin '%1' as dirty BinManagerN n_SRM^N:zz(Cannot set a NULL bin as the current one BinManagerQs^ Close Bin BinManager QsQCN^Close parts bin BinManager R^eQCN^Create a new parts bin BinManagerR d^ Delete Bin BinManagerR d^ Delete bin BinManager R dQCN^Delete parts bin BinManagerNRhf>y:QCNDisplay parts as a list BinManagerNVhv_b_f>y:^Display parts as icons BinManager,O`xn[R d^'%1'?N*dO\N `bY 0EDo you really want to delete bin '%1'? This action cannot be undone. BinManagerQCNeQCNVh ...Edit Part (new parts editor)... BinManager [Q^... Export Bin... BinManager[QQCN...Export Part... BinManagerFritzing BineN(*%1 *%2);;Fritzing Bin (*%1);;FritzingSRNBin (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagerFritzingeN (*%1 *%2 *%3);;FritzingQCN(*%1);;FritzingQCN^(*%2);;FritzingRNQCN^(*%3)cFritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) BinManager [Qe... Import... BinManager^}QeFritzingSN.fzpz ,b FritzingQCN^.fzb, .fzbz CLoad a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) BinManagereQCN^... New Bin... BinManagere^^(%1) New bin (%1) BinManagerQCNParts BinManagerN:^ bNN*T [W:!Please choose a name for the bin: BinManagerS^ Read-only bin BinManagerydQCN Remove Part BinManager N^N-ydRemove from bin BinManagerT}T ^... Rename Bin... BinManagerT}T ^ Rename bin BinManagerT}T QCN^...Rename parts bin... BinManagerO[X^Save Bin BinManagerS[X^N:...Save Bin As... BinManager O[XQCN^Save parts bin BinManagerS[XQCN^N:...Save parts bin as... BinManagerNS)h<_O[XQCN^...&Save parts bin in compressed format... BinManager gb~N-... Searching... BinManager b鉁bS_vFritzingeNSelect a Fritzing File to Open BinManager& b鉁bS_vFritzingQCN^eN(Select a Fritzing Parts Bin file to open BinManagerVhVf>y:^Show Bin in Icon View BinManagerRhVf>y:^Show Bin in List View BinManagerN*^N T}T 0This bin cannot be renamed. BinManagerN }Qe OFf/ Can load, butBoardvgw NN O`vFritziing[eNY9parts/svg/core/pcb/N-Circle_pcb.svgeN0 eHave a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. BoardVPImagesBoard bNN*}QevVPeNSelect an image file to loadBoard.%1vVPSN别}Qe OFf/%2 Ou(N*eN5The image from %1 can be loaded, but %2 Use the file?BoardN }QeUnable to loadBoardN N%1 %2N-}QeVPUnable to load image from %1 %2BoardVN:xmlN f/kcxnvh<_*because the xml is not correctly formattedBoardVN:g YN*<board>\B)because there are multiple layersBoard$VN:g YN*<silkscreen>\B.because there are multiple layersBoardVN:lg <board>\B!because there is no layerBoardVN:PCBg,N ST+NSp\B0but the pcb itself will have no silkscreen layerBoard"u1Nxml%1c%2R%3+due to an xml problem: %1 line:%2 column:%3BoardVPeN image fileBoard }QeVPeNload image fileBoard N\B(SUb)one layer (single-sided)Board$<board>QC} ST+lg _brvQC} .the element contains no shape elementsBoardsvgN ST+_brQC} "the svg contains no shape elementsBoardsvgN T[NIgh<_+the svg doesn't fit the custom board formatBoard N$\B(S̗b)two layers (double-sided)Board_brshape BoardLogoItemrcolorBreadboardLogoItemXRfp Add bendpoint ConnectorItemydfpRemove bendpoint ConnectorItembvf~Straighten curve ConnectorItem QsN(&A)&About ConsoleWindow Q(&Q)&Quit ConsoleWindow]QwTools ConsoleWindowDRCSmN.DRC was cancelled.DRC,FritzingN n2gg[Pvsvg0+Fritzing error: unable to render board svg.DRClg ~bccNhg No traces or connectors to checkDRC(c^NN ^vQk!ЈLDRCb~QfY;Reposition them and run the DRC again to find more problemsDRC:O`gN ~rNvS:Wf/ccNTc~SSb`NwN0qThe areas on your board highlighted in red are connectors and traces which may overlap or be too close together. DRC8N SevSVGn2gӕ--T|fritzing.org6Unexpected SVG rendering failure--contact fritzing.orgDRC:O`vh7g]~QYY}uNlg ccNb^~Y bY*`N0nYour sketch is ready for production: there are no connectors or traces that overlap or are too close together.DRC DRC~g DRC ResultsDRCResultsDialogrlaRhN-vyvT~rNvyvW(O`vePN Ofe--O`_Ř{VDRC0NW(O`Qs[hFvePOmY10Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog.DRCResultsDialogmKu( for debugging DebugDialog T eR deNAlso delete the file DeleteDialogN yd Don't remove DeleteDialogydRemove DeleteDialogrGh{~ chip labelDipP cy:O`SNW(z TOu("^.R">"NegrHg,N-[QeQCNTQCN^"SU[QeNN.l Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. FApplication sW([QeNHDo not import now FApplication@O``[QeOu(egrHg,vFritzingR^vQCNTQCN^NH? ^Do you want to import parts and bins that you have created with earlier versions of Fritzing?  FApplicationBFritzing W(event %3 N-_NNN* %2v%1aY3Fritzing caught an exception %1 from %2 in event %3 FApplication@Fritzing W(event %2 N-_NNN* %1vaY0Fritzing caught an exception from %1 in event %2 FApplicationFritzing QNFritzing failure FApplication[QeImport FApplicationNegrHg,[Qe?#Import files from previous version? FApplication4c[NN*.fzzeNT geNOO[X(Sm\R dYN)KPlease specify an .fzz file name to save to (cancel will delete the backup) FApplication k!Ou(^.RFirst Time HelpFirstTimeHelpDialogQszS(&C) &Close WindowFritzingWindowSmCancelFritzingWindow Qs_SRMz ^Close the current sketchFritzingWindow O[XW(ehc"%1"b@PZvOe9NH?>Do you want to save the changes you made in the document "%1"?FritzingWindowN O[X Don't SaveFritzingWindowO[XSaveFritzingWindowO[X "%1" Save "%1"FritzingWindow O[X...Save...FritzingWindow c[eNT Specify a file nameFritzingWindow YgN O[X b@PZvOe9\ON"Y1.1Your changes will be lost if you don't save them.FritzingWindowSmCancelGroundFillSeedDialogxn[OKGroundFillSeedDialog xn^vOK and copper fillGroundFillSeedDialogxn[^v[W0OK and ground fillGroundFillSeedDialog^bXkQETXkQEvS:R+W(N W(^bXkQEe XkQES:WST+~TcR0W0vccN0cW0vY^8^8hy:N:'GND'b'ground' OFg eN f/Qs.0[N_Sf/g YQ~hScR0NN*ccNN O`^f/S`QvN-vNN*TWXkQE0 N*[hFe6NST+Shg 'GND'b'ground'h{~U/NccN NNccN]~ψ N:y[P0 bNN*NONNW(Iz?N vc0 N_SNOu(S. bNN*O\N:cW0XkQEy[PvccN q6T b鋾nN:cW0XkQEy[PvSU y0The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option.GroundFillSeedDialog[T_ hole sizeHole(SR^~)(autoroutable) HtmlInfoViewDe9S؉VN-"|T"vr`0_S|TvQCNyRe [N bvQCNN_OyR0pChange the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. HtmlInfoView2e9SkdVN-vQCN[r`0[vQCNN yR0OChange the locked state of the part in this view. A locked part can't be moved. HtmlInfoViewّOe9QCNh{~Change the part label here HtmlInfoViewcep Connections HtmlInfoView[Locked HtmlInfoViewQCNbSgVVrGPart breadboard view image HtmlInfoViewQCNpcbVVrGPart pcb view image HtmlInfoViewQCNStVVVrGPart schematic view image HtmlInfoView QCNrHg,SPart version number HtmlInfoView\^`' Properties HtmlInfoView~~ Ratsnest wire HtmlInfoView|TSticky HtmlInfoViewQs.Tags HtmlInfoView _[~%1 Trace wire %1 HtmlInfoView[~Wire HtmlInfoViewcS.conn. HtmlInfoViewcR0N %n N*QCNconnected to %n item(s) HtmlInfoViewT [Wname HtmlInfoView^_vobsolete HtmlInfoView|{Wtype HtmlInfoViewQCNPartItemBase^bottomItemBaseu5[ capacitanceItemBasercolorItemBaseu5mAcurrentItemBaseegdateItemBasecϏdescrItemBase|{efamilyItemBase%1 %2veNg*b~R0file for %1 %2 not foundItemBaseeNT filenameItemBase~bformItemBases frequencyItemBaseu5a inductanceItemBase\BlayersItemBasegY'u5;maximum resistanceItemBaseWSmodelItemBase j!WQCNmodel part problemItemBaseSpackageItemBaseQCNS part numberItemBasey pin spacingItemBasepinsItemBaseu5npowerItemBaseYtVh processorItemBaseyvprojectItemBase[u5mA rated currentItemBase[Rs rated powerItemBase[u5S rated voltageItemBaseu5; resistanceItemBaserHg,revItemBase_brshapeItemBasehSUsheetItemBaseY'\sizeItemBasezzspacingItemBasehtitleItemBaseQl] toleranceItemBasevtopItemBase|{WtypeItemBaseN N:svg%1R^n2g$unable to create renderer for svg %1ItemBaseS_bvariantItemBaserHg,versionItemBaseu5SvoltageItemBaseSmCancelKicadModuleDialogxn[OKKicadModuleDialog f>y:b@g \Bshow all layers LayerPaletteSmCancel LinkDialogxn[OK LinkDialogeg,:text: LinkDialogN f>y:Unable to displayLogoItemN N%1f>y:VPUnable to display image from %1LogoItemVN:eNlg <svg>QC} %because the file has no element���LogoItem���VN:eNlg �r�o�o�tQC} �������$because the file has no root element���LogoItem���VN:�s�v�gN:zz�������because the svg is empty���LogoItem���PQsN*Sf/VN:N�C�o�r�e�l�D�R�A�WN-[Qv�S�V�GeNlg b�'cy:\^`'�'n�������tbecause this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting���LogoItem��� u1Nn2gӕ�������due to a rendering error���LogoItem���&u1N�x�m�l�%�1� ~�:�%�2R�:�%�3�������+due to an xml problem: %1 line:%2 column:%3���LogoItem���"VN:g*wSV�-�-SVPeNN kcxn�������9for unknown reasons--possibly the image file is corrupted���LogoItem���_br�������shape���LogoItem���2�%�2N-v�%�1Q~^~[b�-�%�nN*ccNNq6�^~�������9%1 of %2 nets routed - %n connector(s) still to be routed��� MainWindow��� QsN�(�&�A�)�������&About��� MainWindow���QsN� �Q�t�(�&�A�)������� &About Qt��� MainWindow���[EY'\�(�&�A�)������� &Actual Size��� MainWindow���RQeQCN^�(�&�A�)�.�.�.�������&Add to bin...��� MainWindow��� Y R6�(�&�C�)�������&Copy��� MainWindow���NQ[TN-R^[~�(�&�C�)�������&Create trace from ratsnest��� MainWindow���NQ[TN-R^~�(�&�C�)�������&Create wire from ratsnest��� MainWindow��� RjR�(�&�C�)�������&Cut��� MainWindow��� R d�(�&�D�)�������&Delete��� MainWindow���R d~�&�D ������� &Delete Wire��� MainWindow���Sm b�(�&�D�)������� &Deselect��� MainWindow���R6O\Rog,�(�&�D�)������� &Duplicate��� MainWindow��� �(�&�E�)�������&Edit��� MainWindow��� [Q�(�&�E�)�������&Export��� MainWindow���[Q�(�&�E�)�.�.�.������� &Export...��� MainWindow��� eN�(�&�F�)�������&File��� MainWindow���TzS�(�&�F�)�������&Fit in Window��� MainWindow���l4^sl�(�&�F�)�������&Flip Horizontal��� MainWindow���Wvl�(�&�F�)�������&Flip Vertical��� MainWindow��� ^.R�(�&�H�)�������&Help��� MainWindow���b@g \B�(�&�H�)�������&Hide All Layers��� MainWindow���(NerHg,N-[QeQCNTQCN^�(�&�I�)�.�.�.�������*&Import parts and bins from old version...��� MainWindow���g�\S�(�&�M�)������� &Minimize��� MainWindow���bS_�O[P�(�&�O�)������� &Open Example��� MainWindow���bS_�g�eN�(�&�O�)�������&Open Recent Files��� MainWindow���bS_��(�&�O�)�.�.�.�������&Open...��� MainWindow��� QCN�(�&�P�)�������&Part��� MainWindow��� |4�(�&�P�)�������&Paste��� MainWindow���Sepn�(�&�P�)�.�.�.�������&Preferences...��� MainWindow���bSSp�(�&�P�)�.�.�.������� &Print...��� MainWindow��� �Q�(�&�Q�)�������&Quit��� MainWindow��� ^~�(�&�R�)�������&Routing��� MainWindow��� O[X�(�&�S�)�������&Save��� MainWindow���S[XN:�(�&�S�)�.�.�.������� &Save As...��� MainWindow��� Qh �(�&�S�)������� &Select All��� MainWindow���f>y:b@g \B�(�&�S�)�������&Show All Layers��� MainWindow���f>y:bSg�(�&�S�)�������&Show Breadboard��� MainWindow���f>y:�P�C�B�(�&�S�)������� &Show PCB��� MainWindow���f>y:StV�(�&�S�)�������&Show Schematic��� MainWindow���f>y:QCNh{~�(�&�S�)�������&Show part label��� MainWindow��� V�(�&�V�)�������&View��� MainWindow��� zS�(�&�W�)�������&Window��� MainWindow���~r�(�&�W�)������� &Wire Color��� MainWindow��� e>Y'�(�&�Z�)�������&Zoom In��� MainWindow��� )\�(�&�Z�)������� &Zoom Out��� MainWindow����1�0�0�%�(P} �)Y'\�������100% (pixel) size��� MainWindow��� �1�0�0�%Y'\������� 100% Size��� MainWindow���[E\:[�(w[rit\:[�)�������!Actual (real world physical) size��� MainWindow���[E\:[������� Actual Size��� MainWindow���mRbp������� Add Bendpoint��� MainWindow���mRl�������Add Note��� MainWindow���N: bv[~XRbp�������$Add a bendpoint to the selected wire��� MainWindow���mRl������� Add a note��� MainWindow���\ bQCNRQeQCN^�������Add selected part to bin��� MainWindow���bRe[PQh<�������!Align items to grid when dragging��� MainWindow��� [PQh<������� Align to Grid��� MainWindow���b@g �������All��� MainWindow���N f/b@g v_[~c^0�������$All traces have not yet been routed.��� MainWindow���R^~������� Autoroute��� MainWindow���R^~Yt�.�.�.�������Autorouting Progress...��� MainWindow���R^~N-�.�.�.�������Autorouting...��� MainWindow���YN�'�%�1�'N-�������Backing up '%1'��� MainWindow���S\B������� Both Layers��� MainWindow���^\B������� Bottom Layer��� MainWindow���bSg������� Breadboard��� MainWindow���SGR0N \B������� Bring Forward��� MainWindow���\ bv[a^&R0b@W(\BvN b�������/Bring selected object(s) forward in their layer��� MainWindow���\ b[ayb@W(\Bvkcb�������0Bring selected object(s) to front of their layer��� MainWindow���cR0N \B�������Bring to Front��� MainWindow���Sm�������Cancel��� MainWindow���b~N R0eN�%�1�.�������Cannot find file %1.��� MainWindow���N bSSpN:�%�1�������Cannot print to %1��� MainWindow��� N SeN� �1� �%�1�:� �%�2�.�������Cannot read file 1 %1: %2.��� MainWindow���N QQeeN�%�1�:� �%�2�.�������Cannot write file %1: %2.��� MainWindow���lcbVPN:�%�2�������Change image to %2��� MainWindow���lcbN:SU\B�P�C�B�������Change to single layer pcb��� MainWindow���lcbN:S\B�P�C�B�������Change to two layer pcb��� MainWindow��� hg}Qev~�������Check Loaded Traces��� MainWindow���hgfe�.�.�.�������Check for updates...��� MainWindow���$hgf/T&g erH�F�r�i�t�z�i�n�gON }�������CCheck whether a newer version of Fritzing is available for download��� MainWindow���e9ScW0XkQEy[P�.�.�.�������Choose Ground Fill Seed(s)...��� MainWindow��� b[QeNY9�������Choose a folder for exporting��� MainWindow���ndcW0XkQEy[P�������Clear Ground Fill Seeds��� MainWindow���$ndcW0XkQEy[P�-�-SQAXkQE0�������1Clear ground fill seeds--enable copper fill only.��� MainWindow���lcb�������Convert��� MainWindow���\fpSN:~�������Convert Bendpoint to Via��� MainWindow���lcb~N:fp�������Convert Via to Bendpoint��� MainWindow���lcbN�N*fpN:~�������Convert the bendpoint to a via��� MainWindow���lcb~N:fp�������Convert the via to a bendpoint��� MainWindow���^\B\Bom;�������Copper Bottom layer is active��� MainWindow���������� Copper Fill��� MainWindow���om;N N \B�������3Copper Top and Copper Bottom layers are both active��� MainWindow���v\B\Bom;�������Copper Top layer is active��� MainWindow���Y R6 b�������Copy selection��� MainWindow���N _SP\`cN�������Couldn't get the dock widget��� MainWindow��� R^e�������Create a new sketch��� MainWindow���"N�r�a�t�s�n�e�s�t~N-R^N�h9[~�������%Create a trace from the ratsnest line��� MainWindow��� N�r�a�t�s�n�e�s�t~N-R^N�h9~�������$Create a wire from the ratsnest line��� MainWindow��� �C�t�r�l�+�}�������Ctrl+]��� MainWindow���RjR b������� Cut selection��� MainWindow����D�R�CۈLN-�.�.�.�������DRC Progress...��� MainWindow����D�e�b�u�g�g�e�rQ�������Debugger Output��� MainWindow���R d�������Delete��� MainWindow��� R d~�������Delete Ratsnest Line��� MainWindow���R d[~������� Delete Wire��� MainWindow���R d b�������Delete selection��� MainWindow���Sm b�������Deselect��� MainWindow���Rhg�D�R�C �������Design Rules Check (DRC)��� MainWindow��� e_�b@g ~�������Disconnect All Wires��� MainWindow���e_�b@g cR0N*ccNv~�������0Disconnect all wires connected to this connector��� MainWindow���W(mOVhN-f>y:QCNVh^.R�������&Display Parts Editor help in a browser��� MainWindow���*f>y:�F�r�i�t�z�i�n�gvN�N{SUvb]Tcy:�������+Display some handy Fritzing tips and tricks��� MainWindow���W(RhVN-f>y:QCN^�������$Display the parts bin in a list view��� MainWindow���W(VhVN-f>y:QCN^�������%Display the parts bin in an icon view��� MainWindow��� N R^~�������Do not autoroute��� MainWindow���O[X]~[QevQCNNH�?�������'Do you want to keep the imported parts?��� MainWindow���eYOU~~NH�?�������Do you want to proceed anyway?��� MainWindow���cP`�F�r�i�t�z�i�n�g�������Donate to Fritzing��� MainWindow���N:_SRM bR6O\Rog,�������Duplicate selection��� MainWindow���eQCNVh �������Edit (new parts editor)��� MainWindow��� T/u(Ջ_U�������Enable debugging log��� MainWindow�������Etchable (PDF)...��� MainWindow�������Etchable (SVG)...��� MainWindow���8SR;v[Qkk!SYtN�WWg�-�- bO``[Qvg[P0�������`Etchable export can only handle one board at a time--please select the board you want to export.��� MainWindow���0[QN:�1�0�0�0� �d�p�iW(kdVN-QCNv�S�V�GVP�������7Export 1000 dpi Flattened SVG of this part in this view��� MainWindow���0[QN:�1�0�0�0� �d�p�iW(kdVN-QCNv�S�V�GVP�������-Export 1000 dpi SVG of this part in this view��� MainWindow���[QgPeSU�(�B�o�M�)�.�.�.�������!Export Bill of Materials (BoM)...��� MainWindow���[QQ~܈h�.�.�.�������Export Netlist...��� MainWindow���[QhQv�S�V�GVP�������Export Normalized Flattened SVG��� MainWindow���[QN:hQv�S�V�G�������Export Normalized SVG��� MainWindow���[Q�S�V�G�.�.�.������� Export SVG...��� MainWindow��� [QN:�P�C�B�������Export for PCB��� MainWindow���[Q bvQCN�������Export selected part��� MainWindow���[Q_SRMz ^vN:�S�V�GVP�������)Export the current sketch as an SVG image��� MainWindow��� [Q_SRM�E�a�g�l�e� �C�A�D�������&Export the current sketch to Eagle CAD��� MainWindow���b[Q_SRMIz?�E�x�t�e�n�d�e�d� �G�e�r�b�e�r� �f�o�r�m�a�t� �(�R�S�-�2�7�4�X�)NONNv�P�C�BuN�������]Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production��� MainWindow���D[Q_SRMyv�P�D�FۈL�D�I�Yv�P�C�BuN�(�p�h�o�t�o�r�e�s�i�s�t�)�������EExport the current sketch to PDF for DIY PCB production (photoresist)��� MainWindow���D[Q_SRMyv�S�V�GۈL�D�I�Yv�P�C�BuN�(�p�h�o�t�o�r�e�s�i�s�t�)�������EExport the current sketch to SVG for DIY PCB production (photoresist)��� MainWindow���"[Q_SRMz ^vSS:WN:�J�P�GVP�������If a "sticky" part is moved, parts on top of it are also moved��� MainWindow���$NNKRM[vrHg,N-N-[QeQCNTQCN^�������0Import parts and bins from previous installation��� MainWindow���cy:h������� Inspector��� MainWindow���w wgeN SRQ[f>y:Vhv[Erit\:[ b@N_SRM�'[E\:[�'v[sSf/N�N*s`0O`g�Y}Ou(N�N*\:[PQCN q6Te>N�N*ritN v \:[PW(N b )e>vNN\:[S9M0������It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up.��� MainWindow����J�P�E�GVP�(�*�.�j�p�g�)�������JPEG Image (*.jpg)��� MainWindow���T/R�%�1�.�.�.������� Launch %1...��� MainWindow���\B�������Layers��� MainWindow��� QCNRh�(gPeSU�)�(�&�B�)�.�.�.�������%List of parts (&Bill of Materials)...��� MainWindow��� }QeN-�.�.�.������� Loading...��� MainWindow���[QCN������� Lock Part��� MainWindow���TN;zS�:�:�p�o�p�u�l�a�t�e�M�e�n�u�W�i�t�h�I�n�d�e�x�:� N }Qe�i�dN:�'�%�1�'vO[P�������EMainWindow::populateMenuWithIndex: couldn't load example with id='%1'��� MainWindow���g�\S_SRMzS�������Minimize current window��� MainWindow���N\ bv_[~ygvSN�b�(lN�ga_[~yRNTQvvQsvN_\yR0SN�b�)�������Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)��� MainWindow���lR0gvSN�b�������Move to other side of the board��� MainWindow���e^�������New��� MainWindow���g*b~R0Iz?�'�%�1�'�������No Sketch found in '%1'��� MainWindow���lg �^~vc�������No connections to route��� MainWindow��� v\Blg �������No copper top layer��� MainWindow���6lg b~R0|xnvN�F�r�i�t�z�i�n�g bNN�N*vv�.�������ANo exactly matching part found; Fritzing chose the closest match.��� MainWindow���*g*b~R0gQCN0� `b@g vQCNf/g�ev0�������7No outdated parts found. All your parts are up-to-date.��� MainWindow���Nlg NSepvSN�.� bNRRQMN*O`o NO`SNN]g v\^`'vSNN- b�������No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist��� MainWindow���xn[�������OK��� MainWindow��� W(~QCNS€�������Online Parts Reference��� MainWindow��� W(~yv^�������Online Projects Gallery��� MainWindow���W(~c[�������Online Tutorials��� MainWindow���bS_��F�r�i�t�z�i�n�gcP`QW@�������Open Fritzing donation web page��� MainWindow���bS_��F�r�i�t�z�i�n�gy:O�������Open Fritzing examples��� MainWindow���bS_��F�r�i�t�z�i�n�g^.R�������Open Fritzing help��� MainWindow��� bS_�QCNS€�������Open Parts Reference��� MainWindow���bS_�N�N*�F�r�i�t�z�i�n�g�(�.�f�z�z�,� �.�f�z�)�,� b}Qe�F�r�i�t�z�i�n�gQCN�o�r� �l�o�a�d� �a� �F�r�i�t�z�i�n�g� �p�a�r�t�(�.�f�z�p�z�)�,b�F�r�i�t�z�i�n�gQCN^�(�.�f�z�b�,� �.�f�z�b�z�)�������jOpen a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)��� MainWindow���bS_�SUrGg:z zS�������'Open microcontroller programming window��� MainWindow��� bS_�z zS�������Open programming window��� MainWindow���$W(N�N*][XW(vQCNN bS_�eQCNVh�������-Open the new parts editor on an existing part��� MainWindow���H_N�WWNO`vIz?N-R^v�P�C�B�-�-geO N-v�F�r�i�t�z�i�n�g� �F�a�b�������@Order a PCB created from your sketch--from fabulous Fritzing Fab��� MainWindow���_N�WW�P�C�B�.�.�.�������Order a PCB...��� MainWindow��� ]gQCN�������Outdated parts��� MainWindow����P�N�GVP�(�*�.�p�n�g�)�������PNG Image (*.png)��� MainWindow���ubn������� Page Setup��� MainWindow���QCNVh^.R�������Parts Editor Help��� MainWindow���|4RjRgQ[�������Paste clipboard contents��� MainWindow���\Rj4gQ[|4R0ّ�������!Paste clipboard contents in place��� MainWindow��� |4R0ّ�������Paste in Place��� MainWindow���& bN \B�F�r�i�t�z�i�n�geNY9�.�.�.�������-Please choose the previous Fritzing folder...��� MainWindow���0 bN�WW�P�C�B�-�-XkQEN�k!SN:N�WWg]O\0�������DPlease select a PCB--copper fill only works for one board at a time.��� MainWindow���6 bO``R^~vg0W0XkQEdO\kk!SYtN�WWg0�������OPlease select a PCB--ground fill operations only work on a one board at a time.��� MainWindow���0 bN�WW�P�C�B�-�-XkQEN�k!SN:N�WWg]O\0�������MPlease select a PCB. Copper fill operations only work on one board at a time.��� MainWindow���, bN�WW�P�C�B0�D�R�CN�k!SYtN�WWg0�������;Please select a PCB. DRC only works on one board at a time.��� MainWindow���4 bO``R^~vg0R^~kk!SYtN�WWg0�������bPlease select the board you want to autoroute. The autorouter can only handle one board at a time.��� MainWindow���$N:�'�%�1�'c[N�N*�.�f�z�zveNT �������0Please specify an .fzz file name to save '%1' to��� MainWindow���T�F�r�i�t�z�i�n�gQW@S^]z �������&Post a project to the Fritzing website��� MainWindow���2kbQCNyR�������Prevent a part from being moved��� MainWindow��� bSSp_SRMV�������Print the current view��� MainWindow��� bSSpN-�.�.�.������� Printing...��� MainWindow���ۈLN-�������Proceed��� MainWindow����Qz ^�������Quit the application��� MainWindow���SGMQCN�������Raise and Lower��� MainWindow���S������� Read-only��� MainWindow���QYY}�������Ready��� MainWindow���:e{^~r`T~�(W(RfeN kcxn]O\v`QN �)�������_Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)��� MainWindow���`bY �������Redo��� MainWindow��� e}Qe�������Reload the sketch��� MainWindow���ydbp�������Remove Bendpoint��� MainWindow���yd�������Remove Copper Fill��� MainWindow���yd�������Remove copper fill��� MainWindow��� yd\B�������Remove the copper fill��� MainWindow���bTJ�b�u�g�.�.�.�������Report a bug...��� MainWindow���$bTJW(�F�r�i�t�z�i�n�gN-Ssv�b�u�g�������%Report a but you've found in Fritzing��� MainWindow��� `bY ؋P<�������Restore Default��� MainWindow���`bY �������Revert��� MainWindow���`bY �������Revert?��� MainWindow���eˏl�������Rotate��� MainWindow���eˏl� �1�8�0�� �{�1�8�0�?�}������� Rotate 180���� MainWindow��� zeeˏl�1�3�5�� �{�4�5�?�}�������Rotate 45� Clockwise��� MainWindow���eeˏl�4�5�� �{�4�5�?�}�������Rotate 45� Counter Clockwise��� MainWindow��� zeeˏl�1�3�5�� �{�9�0�?�}�������Rotate 90� Clockwise��� MainWindow���eeˏl�4�5�� �{�9�0�?�}�������Rotate 90� Counter Clockwise��� MainWindow���zeeˏl_SRM b�4�5^�������-Rotate current selection 45 degrees clockwise��� MainWindow���eeˏl_SRM b�4�5^�������5Rotate current selection 45 degrees counter clockwise��� MainWindow��� \_SRM bvQCNeeˏl�9�0^�������5Rotate current selection 90 degrees counter clockwise��� MainWindow���\ bvQCNeˏl�1�8�0^�������(Rotate the selected parts by 180 degrees��� MainWindow���\ bvQCNzeeˏl�9�0^�������1Rotate the selected parts by 90 degrees clockwise��� MainWindow���^~[b�������Routing completed��� MainWindow���Ou(�%�nN*~QCN[bN^~�������)Routing completed using %n jumper part(s)��� MainWindow����S�V�GVP�(�*�.�s�v�g�)�������SVG Image (*.svg)��� MainWindow��� O[X� �%�1�������Save %1��� MainWindow���&�bO[XgPeSU�(�B�o�M�)�/Ǎ-RhN:eg,�������4Save a Bill of Materials (BoM)/Shopping List as text��� MainWindow���O[XQ~܈hN:�X�M�Lh<_�������Save a netlist in XML format��� MainWindow��� O[X_SRM�������Save the current sketch��� MainWindow���O[XN� �'�%�1�'������� Saved '%1'��� MainWindow���StV������� Schematic��� MainWindow��� bb@g �'N R^~�'v~�������#Select All "Don't Autoroute" Traces��� MainWindow��� bb@g R^~v~�������Select All Autoroutable Traces��� MainWindow��� bb@g �������Select All CopperFill��� MainWindow��� bb@g ~�������Select All Jumpers��� MainWindow��� bb@g [QCN�������Select All Locked Parts��� MainWindow��� bb@g _[~�������Select All Traces��� MainWindow��� bb@g �V�i�a�s�������Select All Vias��� MainWindow��� bb@g ~�������Select All Wires��� MainWindow��� b鉁bS_�v�F�r�i�t�z�i�n�geN�������Select a Fritzing File to Open��� MainWindow��� bb@g vyv�������Select all copper fill items��� MainWindow��� bb@g QC} �������Select all elements��� MainWindow��� bb@g ~yvQCN�������Select all jumper item parts��� MainWindow��� bb@g N yRQCN�������$Select all parts that can't be moved��� MainWindow��� bb@g _[~[~�������Select all trace wires��� MainWindow���" bb@g cdW(R^~Yv_[~�������0Select all trace wires excluded from autorouting��� MainWindow��� bb@g W(R^~eSNe9Sv~�������=Select all trace wires that can be changed during autorouting��� MainWindow��� bb@g �v�i�aQCN�������Select all via parts��� MainWindow��� bb@g ~�������Select all wires��� MainWindow��� bgQCN�������Select outdated parts��� MainWindow���MR0N \B������� Send Backward��� MainWindow���\ b[ayb@W(\BvN b�������+Send selected object(s) back in their layer��� MainWindow���\ b[ayb@W(\BvN b�������2Send selected object(s) to the back of their layer��� MainWindow��� SѐN b������� Send to Back��� MainWindow���nfor�.�.�.�������Set Background Color...��� MainWindow���nQh<\:[�.�.�.�������Set Grid Size...��� MainWindow���ncW0XkQEy[P�������Set Ground Fill Seed��� MainWindow���nS̗b\BSpQ������� Set both copper layers clickable��� MainWindow���n^\B\BSpQ�������!Set copper bottom layer clickable��� MainWindow���nv\B\BSpQ�������Set copper top layer clickable��� MainWindow���nkdVN-vfor�������%Set the background color of this view��� MainWindow���nQhy:Qh<������� Show Grid��� MainWindow���f>y:QCN^VhV�������Show Parts Bin Icon View��� MainWindow���NRhVf>y:QCN^�������Show Parts Bin List View��� MainWindow���f>y:� �Q�t� vQsN[hF�������Show Qt's about box��� MainWindow���W(_SRMVN-f>y:b@g S\B�������2Show all the available layers for the current view��� MainWindow���f>y:�P�C�BV�������Show the PCB view��� MainWindow���f>y:z ^QsN[hF������� Show the application's about box��� MainWindow���f>y:bSgV�������Show the breadboard view��� MainWindow���f>y:c[vQh<������� Show the grid��� MainWindow���f>y:StVV�������Show the schematic view��� MainWindow��� f>y:g*^~������� Show unrouted��� MainWindow��� ][Q�������Sketch exported��� MainWindow���[QIz?R0�G�e�r�b�e�r�������Sketch exported to Gerber��� MainWindow���bkI�!�������Sorry!��� MainWindow���bkI �"�%�1�"lg [s�������(Sorry, "%1" has not been implemented yet��� MainWindow��� c[eNT �������Specify a file name��� MainWindow���|T�������Sticky��� MainWindow���bvf~�������Straighten Curve��� MainWindow���bv bvf~�������)Straighten the curve of the selected wire��� MainWindow���@bRfeN� �%�1� N*QCN�.� hgb@g vVNO݋g kcxnveHg0�������SSuccessfully updated %1 part(s). Please check all views for potential side-effects.��� MainWindow���S�v�g� �%�1� N"Y1N� �'�%�2�'\B�.� YOUR^[NIgWvfYO`o gw W(�<�a� �h�r�e�f�=�'�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�'�>�h�t�t�p�:�/�/�f�r�i�t�z�i�n�g�.�o�r�g�/�l�e�a�r�n�i�n�g�/�t�u�t�o�r�i�a�l�s�/�d�e�s�i�g�n�i�n�g�-�p�c�b�/�p�c�b�-�c�u�s�t�o�m�-�s�h�a�p�e�/�<�/�a�>vT[�.������ Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/.��� MainWindow���u(j!WW�%�2fN�%�1�������Swapped %1 with module %2��� MainWindow���b�.�f�zeNh<_]~N W(^Ou(N0� � O`sW(`lcb�'�%�1�'N:�.�f�z�zh<_bNSh<_bS_�[NH�?� �������vThe .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? ��� MainWindow���lcbYtz N Oe9S�'�%�1�'0�������,The conversion process will not modify '%1'.��� MainWindow���dv\B�(�c�o�p�p�e�r� �1�)\BN e/cSUbg0\glcbN:S̗bb b^\B�(�c�o�p�p�e�r� �0�)\B0�������The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer.��� MainWindow���,eNY9�"�%�1�"N f/�F�r�i�t�z�i�n�g[eNY9�������4The folder "%1" isn't a Fritzing installation folder��� MainWindow���N*VN-lg g*^~vc0�������/There are no unrouted connections in this view.��� MainWindow���:N*dO\N PZ�-�-\OY1Sb@g vOe90� � ~~^v`bY �������ZThis operation can not be undone--you will lose all of your changes. Go ahead and revert?��� MainWindow���N NET\cO\�F�r�i�t�z�i�n�g[Q�E�A�G�E�L^\@voN�.YgO``[QfYO`Uk"v�E�D�A]QwN- bNwS bcON�N!s.0�������This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute.��� MainWindow���ett~������� Tidy Wires��� MainWindow��� ett b[~�������Tidy selected wires��� MainWindow���b]�,zT_cw.�������Tips, Tricks and Shortcuts��� MainWindow���v\B������� Top Layer��� MainWindow���8W(ۈLcW0XkQEebN*ccNTN[g QsvcO\N:�'W0�'�.�������JTreat this connector and its connections as a 'ground' during ground fill.��� MainWindow���N \�%�1[QN:SRNv������� Unable to export %1 as shareable��� MainWindow���N b�%�1[QN:SRN�������'Unable to export %1 to shareable sketch��� MainWindow��� N O[X�%�1�������Unable to save %1��� MainWindow���*N O[XN:�B�O�MeN SUeg,NW(RjRgN-0�������:Unable to save BOM file, but the text is on the clipboard.��� MainWindow���d��������Undo��� MainWindow���d�SS������� Undo History��� MainWindow��� g*^~vc�������Unrouted connections��� MainWindow���feN� �%�1� N*QCN�������Update %1 part(s)��� MainWindow��� h`P\efeO`oV�������Update InfoView on hover��� MainWindow���fe bvQCN�������Update selected parts��� MainWindow���,_SR^~e N R_�N~ ~T~QCN�������DWhen autorouting, do not rip up this trace wire, via, or jumper item��� MainWindow����X�M�LQ~܈h�.�.�.�������XML Netlist...��� MainWindow���*Ou([QevQCN_Ř{eT/R�F�r�i�t�z�i�n�g�������DYou will have to restart Fritzing in order to use the imported parts��� MainWindow���@O`vN-lg ST+gmRN�WW�P�C�BNO[Q�G�e�r�b�e�r�.�������VYour sketch does not have a board yet! Please add a PCB in order to export to Gerber.��� MainWindow���:O`vN-lg g[PmRN�WW�P�C�BNOSNydXkQE0�������XYour sketch does not have a board yet! Please add a PCB in order to remove copper fill.��� MainWindow���@O`vN-lg g[PmRN�WW�P�C�BNOSNOu(W0b\BXkQE0�������_Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill.��� MainWindow���:O`vlg g[PmRN�WW�P�C�BNOSNOu(R^~0�������XYour sketch does not have a board yet! Please add a PCB in order to use the autorouter.��� MainWindow���4O`vN-lg ST+g�D�R�CSW(g �P�C�Be]O\�.�������AYour sketch does not have a board yet! DRC only works with a PCB.��� MainWindow���6O`vlg g[PmRN�WW�P�C�BNO[QSR;v0�������TYour sketch does not have a board yet! Please add a PCB in order to export etchable.��� MainWindow���:O`vN-lg ST+gmRN�WW�P�C�BNOOu(R�.�������_Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations.��� MainWindow���e>Y'�������Zoom in��� MainWindow���)\�������Zoom out��� MainWindow���O\N:VP�������as Image��� MainWindow���^�������bottom��� MainWindow����������copper��� MainWindow���������� copperfill��� MainWindow��� vc}QeQCN�������directly loading parts��� MainWindow���N:NuN�������for Production��� MainWindow���W0�������ground��� MainWindow���~�������jumpers��� MainWindow��� �%�1}QeN-������� loading %1��� MainWindow���}Qe�%�1�(bSg�)�������loading %1 (breadboard)��� MainWindow���}Qe�%�1�(j!WW�)�������loading %1 (model)��� MainWindow���}Qe�%�1�(�p�c�b�)�������loading %1 (pcb)��� MainWindow���}Qe�%�1�(StV�)�������loading %1 (schematic)��� MainWindow���eIz?������� new sketch��� MainWindow����.�f�zeNh<_]~ψP\kbOu(N�������the .fz file format is obsolete��� MainWindow��� bQN�N*O*aY gw SuNNNHN�������*throw a fake exception to see what happens��� MainWindow��� bQmKaY�������throw test exception��� MainWindow���v�������top��� MainWindow���N�%�1N-b~N R0SNfcbv�.� �������#unable to find replacement for %1. ��� MainWindow���~�������vias��� MainWindow���8N Sev�S�V�Gn2gӕ�-�-T|�f�r�i�t�z�i�n�g�.�o�r�g�������6Unexpected SVG rendering failure--contact fritzing.org��� MazeRouter���nR0SYN�N*QCNb~N lg e>W([E�P�C�BN 0�������qUnable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB.���PCBSketchWidget���.N R^\B�-�-QCNSlg e>nR0�P�C�BN 0�������LUnable to create copper fill--probably the part wasn't dropped onto the PCB.���PCBSketchWidget���:O`vN-lg ST+gmRN�WW�P�C�BNOOu(R�.�������UYour sketch does not have a board yet! Please add a PCB in order to use copper fill.���PCBSketchWidget���8O`vN-lg g[PXRN�WW�P�C�BNOOu( bdO\0�������bYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget���8O`vN-lg g[PXRN�WW�P�C�BNOOu( bdO\0�������aYour sketch does not have a board yet! Please add a PCB in order to use this selection operation.���PCBSketchWidget���ّu(geccNQCNvQCepcn�������:This is where you edit the connector metadata for the part���PEConnectorsView���[T������� Through-hole���PEConnectorsView��� ccNep�������number of connectors:���PEConnectorsView���� � ~~^vO[X������� Go ahead and save?��� PEMainWindow��� �(�&�E�)�������&Edit��� PEMainWindow��� [Q�(�&�E�)�������&Export��� PEMainWindow��� eN�(�&�F�)�������&File��� PEMainWindow����'�%�1�'�������'%1', ��� PEMainWindow���<�<�b�r�/�>�<�b�r�/�>W(N N�rHvQCNVhN-\N Qf/�,� �������N

    This will not be a problem in the next release of the Parts Editor,  PEMainWindowN QAY R6'family'\^`',A duplicate 'family' property is not allowed PEMainWindow N QAY R6'variant'\^`'-A duplicate 'variant' property is not allowed PEMainWindowXR%1ccNAdd %1 connectors PEMainWindow mRccN Add connector PEMainWindow XRQcN'%1'R0'%2')Add internal connection from '%1' to '%2' PEMainWindow N QAN:zzBlank not allowed PEMainWindowSmCancel PEMainWindowb%1lSN:%2Change %1 to %2 PEMainWindowlcb%1%2Change %1 to '%2' PEMainWindowlSb@g ccN%1Change all connectors to %1 PEMainWindowlcbccN%1Change connector %1 PEMainWindowlcbcϏChange description PEMainWindowlcb\^`'Change properties PEMainWindowlcbh{~ Change tags PEMainWindow lS؁%1 Change to %1 PEMainWindowQsz ^NN O[XClose without saving PEMainWindow N O[XQsClose without saving? PEMainWindowccN Connectors PEMainWindow ccNVConnectors View PEMainWindowlcbConversion problem PEMainWindowY R6 Copy problem PEMainWindow4Do you want to keep working or close without saving? PEMainWindow$O``O[XW(QCN"%1"N-O\ve9SNH?:Do you want to save the changes you made in the part "%1"? PEMainWindow N QAY R6'family'v\^`''Duplicate 'family' property not allowed PEMainWindow"N QAY R6'variant'v\^`'(Duplicate 'variant' property not allowed PEMainWindowY R6Duplicate problem PEMainWindowPNGTJPGVPOcNNOMVv\^`' _S)e>ew wgeN Y}-- TPNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PEMainWindow QCNVh Parts Editor PEMainWindow*Ou(ne[QSVGeN ^vW(kd[Qe0HPlease re-export the SVG file using that setting, and try loading again. PEMainWindownccN%1Relocate connector %1 PEMainWindowyd%1ccNRemove %1 connectors PEMainWindow ydQcRemove Internal Connection PEMainWindow ydccNRemove connector PEMainWindowydQcN'%1'$Remove internal connection from '%1' PEMainWindowu(PCBVPReuse PCB image PEMainWindowu(bSgVPReuse breadboard image PEMainWindoweOu(StVReuse schematic image PEMainWindowW(N*VN-eOu(PCBVP Reuse the PCB image in this view PEMainWindowW(N*VN-eOu(bSgVP'Reuse the breadboard image in this view PEMainWindowW(N*VN-eOu(StVP&Reuse the schematic image in this view PEMainWindow SVG SVG problem PEMainWindowO[XSave PEMainWindowO[X "%1" Save "%1" PEMainWindow S[XN:eQCNSave as new part PEMainWindow*O[XN*QCN\O[NuN `bY ve9S0HSaving this part will make a change to the sketch that cannot be undone. PEMainWindow2O[XN*QCN\O[N be9S ONN PZ0LSaving this part will make a change to these sketches that cannot be undone. PEMainWindowgw <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">N*</a>0ySee this explanation. PEMainWindow f>y:ccNShow Connectors PEMainWindowf>y:Vh Show Icon PEMainWindow f>y:QCepcn Show Metadata PEMainWindow eNN-f>y:Show in Folder PEMainWindowW(RhVN-f>y:QCepcn*Show the connector metadata in a list view PEMainWindow f>y:VhVShow the icon view PEMainWindowf>y:QCepcnVShow the metadata view PEMainWindow e9S؋fTJSketch Change Warning PEMainWindow$b@]S[eeHvPCBVVP0So editing may produce an invalid PCB view image PEMainWindow'family'\^`'N N:zz0'The 'family' property can not be blank. PEMainWindow\QsN*Sf/VN:NCorelDRAWN-[QvSVGeN'%1'lg b'cy:\^`''n. nThe SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting.  PEMainWindow*bS_v'%1'Ou(NO`kcW(vQCN04The open sketch '%1' uses the part you are editing.  PEMainWindow bS_vThe open sketches  PEMainWindow QCNـW(kdVTVhVN-S8The part will only be visible in this view and icon view PEMainWindow'%1'vPy:0This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view .  PEMainWindowRN*rHg,vevQCNVhN Yt'%1'N-Ryvcopper0Tcopper1\B0dThis version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'.  PEMainWindow0N*fTJN W(FritzingN*6kY vQs=This warning will not be repeated in this session of Fritzing PEMainWindowN }Qe'%1'Unable to load '%1' PEMainWindow6N }Qe'%1'0QsQCNVhN-g*O[XR^v͋0PUnable to load '%1'. Please close the parts editor without saving and try again. PEMainWindowN }QeVPeN'%1'Unable to load image file '%1' PEMainWindow"N }QeVPeN'%1': %2$Unable to load image file '%1': %2 PEMainWindowN ^zg,W0Rog,'%1'$Unable to make a local copy of: '%1' PEMainWindowN g'%1'Unable to parse '%1' PEMainWindow&N g'%1':%2~:%3R:%4*Unable to parse '%1': %2 line:%3 column:%4 PEMainWindowN gfzpeN%1Unable to parse fzp file %1 PEMainWindowN QQesvg%1Unable to write svg to %1 PEMainWindow8vR0b@g vccNRM~SVGQC} N*QCNbMkcxn]O\0UUntil all connectors are assigned to SVG elements, the part will not work correctly.  PEMainWindowOu(PNGTJPGf/N ^vUse of PNG and JPG discouraged PEMainWindow*Sؑ'%1'W(Ou(N-0SؑT _Ř{f/U/Nv08Variant '%1' is in use. The variant name must be unique. PEMainWindow.O`SN[Qhv[StVbPCBVۈLOe90 7You can safely make changes to Schematic or PCB view.  PEMainWindowBO`SNOu(PNGbJPGVP^zO`vQCN OFgY}Ou(SVG^z0 WYou may use a PNG or JPG image to construct your part, but it is better to use an SVG.  PEMainWindow YgN O[X b@PZvOe9\ON"Y1.1Your changes will be lost if you don't save them. PEMainWindowNS%nV0across %n views.  PEMainWindow T'%1'  and '%1'  PEMainWindow$OFf/sW(h9cnN bvcgeOe9eN.Mbut for now please modify the file according to the instructions in the link. PEMainWindowW(%1N-g*b~R0VhN\no footprints found in %1 PEMainWindowW(%1N-g*b~R0StVno schematics found in %1 PEMainWindow StVQCNschematic part PEMainWindow@b@N[NFritzingQCNgY}SOu(PNGTJPGO\N:S`OM{&0Iso for Fritzing parts it is best to use PNG and JPG only as placeholders. PEMainWindow ehQCN untitled part PEMainWindowO\AuthorPEMetadataViewegDatePEMetadataViewcϏ DescriptionPEMetadataView[eFamilyPEMetadataViewh{~LabelPEMetadataView\^`' PropertiesPEMetadataViewn؋QCNh{~RM!Set the default part label prefixPEMetadataView nQCNO\Set the part's authorPEMetadataView nQCNegSet the part's datePEMetadataView@nQCNcϏ--O`SNOu({SUvhtmlQt[eg,[NIvQ[ RSet the part's description--you can use simple html (as defined by Qt's Rich Text)PEMetadataView&nQCN[e--N*QCNg QsvQvNQCN?Set the part's family--what other parts is this part related toPEMetadataView nQCN\^`'Set the part's propertiesPEMetadataViewnQCNQs.Set the part's tagsPEMetadataView nQCNhSet the part's titlePEMetadataView$nQCNvurlYg[W(QuN g cϏ3Set the part's url if it is described on a web pagePEMetadataView6nQCNvSؑ--O[NT N[eQvNQCNvkf/`NvTSet the part's variant--this makes it unique from all other parts in the same familyPEMetadataViewQs.TagsPEMetadataView ّf/QCNQCepcnvW0e...4This is where you edit the metadata for the part ...PEMetadataViewhTitlePEMetadataViewSؑVariantPEMetadataView^:height: PESvgView[^:width: PESvgView><font color='black'>QAbb</font>+Dragging enabled PEToolView<<font color='gray'>ykbbb</font>+Dragging disabled PEToolViewN-_Center PEToolView ccN%1 Connector %1 PEToolView$ccNRh[Sva`f/VPψ N- ;Connector List (a checkmark means the graphic was selected) PEToolViewRcR6ccNzpvn0zpf/~TccNcvW0e0O`N_SNbR_SRMccNvSA[WQ~Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector PEToolViewykbbbDragging disabled PEToolViewOe9zpvxWPh/Modifies the x-coordinate of the terminal point PEToolViewOe9zpvyWPh/Modifies the y-coordinate of the terminal point PEToolView bVPSelect graphic PEToolView nQcSet Internal Connections PEToolView& [N*Y hFu;~geOcwQvc?Set this checkbox to edit internal connections by drawing wires PEToolViewnccNvzp%10*Sets the connector's terminal point to %1. PEToolViewTOu(QIh[OM hnڏngec[`~_SRMccNRMvSVGQC} q6Tc N hge b[0Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. PEToolViewN-_center PEToolViewNeast PEToolViewSnorth PEToolViewSWsouth PEToolViewwest PEToolViewN-_centerPadc connect toPadNeastPadSnorthPad_brshapePadSWsouthPadwestPad h{~Edit Pin Labels PaletteItemQ_ Hole Diameter PaletteItemh{~N S9M0NNHlO[X0#Label mismatch. Nothing was saved. PaletteItemY_Ring Thickness PaletteItem$N Yt:QCNccNlg hQvID0;Unable to proceed; part connectors do no have standard IDs. PaletteItemN Yt:b~N R0v\BV01Unable to proceed; unable to find top level view. PaletteItem~nadvanced settings PaletteItem[T_ hole size PaletteItemf>y:P<Display Values PartLabelf>y:h{~ve[WDisplay the text of the label PartLabelf>y:\^`'%1vP< Display the value of property %1 PartLabelEdit PartLabel h{~e[WEdit label text PartLabell4^slFlip Horizontal PartLabelWvl Flip Vertical PartLabel l4^slh{~Flip label horizontally PartLabel Wvlh{~Flip label vertically PartLabel l/eˏl Flip/Rotate PartLabel[WOSY'\ Font Size PartLabelHide PartLabel QCNh_Hide part label PartLabelh{~e[W Label text PartLabel h{~e[W: Label text: PartLabelY'Large PartLabelN-Medium PartLabel"zeeˏl135 {135?}Rotate 135� Clockwise PartLabel eeˏl45 {135?}Rotate 135� Counter Clockwise PartLabeleˏl 180 {180?} Rotate 180� PartLabel zeeˏl135 {45?}Rotate 45� Clockwise PartLabeleeˏl45 {45?}Rotate 45� Counter Clockwise PartLabel zeeˏl135 {90?}Rotate 90� Clockwise PartLabeleeˏl45 {90?}Rotate 90� Counter Clockwise PartLabel\_SRM beeˏl90^5Rotate current selection 90 degrees counter clockwise PartLabel\h{~zeeˏl135^)Rotate the label by 135 degrees clockwise PartLabeleeˏlh{~135^1Rotate the label by 135 degrees counter clockwise PartLabelh{~eˏl180^Rotate the label by 180 degrees PartLabel\h{~zeeˏl45^(Rotate the label by 45 degrees clockwise PartLabeleeˏlh{~45^0Rotate the label by 45 degrees counter clockwise PartLabel\h{~zeeˏl90^(Rotate the label by 90 degrees clockwise PartLabel [WOSnN:Y'Set font size to large PartLabel [WOSnN:N-Set font size to medium PartLabel [WOSnN:\Set font size to small PartLabeln[WOSY'\N:tinySet font size to tiny PartLabelN:%1nh{~Set label for %1 PartLabel\Small PartLabelg\Tiny PartLabel mRR0QCN Add to binPartsBinPaletteWidgetSmCancelPartsBinPaletteWidgetb~N R0eN%1.Cannot find file %1.PartsBinPaletteWidgetN SeN %1: %2.Cannot read file %1: %2.PartsBinPaletteWidgete9SVhr...Change icon color...PartsBinPaletteWidgete9Skd^Vhvr.*Change the color of the icon for this bin.PartsBinPaletteWidget xn[\b@ QCNRQeR0QCN^N-NH?7Do you really want to add the selected part to the bin?PartsBinPaletteWidgetO[X[QCN"%1"vfe9NH?9Do you want to save the changes you made in the bin "%1"?PartsBinPaletteWidgetN O[X Don't SavePartsBinPaletteWidgetFritzingQCN(*%1)Fritzing Bin (*%1)PartsBinPaletteWidget }QeN-... Loading...PartsBinPaletteWidgetO[XSavePartsBinPaletteWidgetO[XQCN^"%1" Save bin "%1"PartsBinPaletteWidgetN:Vh b阜rSelect a color for this iconPartsBinPaletteWidget c[eNT Specify a file namePartsBinPaletteWidget g*T}T QCN Untitled BinPartsBinPaletteWidget YgN O[X b@PZvOe9\ON"Y1.1Your changes will be lost if you don't save them.PartsBinPaletteWidget}Qe^'%1'loading bin '%1'PartsBinPaletteWidgetSmCancel Perfboard`'fTJPerformance Warning PerfboardbgLQwg YN2000N*[Tvperfboards and stripboardvOab0O`xn[NH laN*fTJW(kd~z N-N OY 0Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Perfboard neY'\ Set new size PerfboardRcolumns PerfboardLrows Perfboard ngY'\set board size PerfboardY'\size Perfboard.<p><h2>h{~Vh</h2></p>

    Pin Label Editor

    PinLabelDialog,<p>W(h{~N pQq6T bT}T v.<

    Click on a label next to a pin number to rename that pin.PinLabelDialogSmCancelPinLabelDialog`bY RedoPinLabelDialogO[XSavePinLabelDialogdUndoPinLabelDialog.SNOu(tab.W(NKc z^yR.</p>@You can use the tab key to move through the labels in order.

    PinLabelDialog%1 (pQOe9...)%1 (click to change...) PrefsDialogRO[XAutosave PrefsDialogRO[XNa:Autosave every: PrefsDialogSmCancel PrefsDialog e9Snڏn\^`'Change Wheel Behavior PrefsDialogndnClear Settings PrefsDialogrColors PrefsDialogT}N Command PrefsDialog NcvConnected Highlight PrefsDialogcR6Control PrefsDialog _/fbv~Curvy vs. straight wires PrefsDialogu(General PrefsDialogLanguage PrefsDialog hnڏn\^`'Mouse Wheel Behavior PrefsDialogxn[OK PrefsDialogN:%1 bNN*z ^(SbgL)'Select a programmer (executable) for %1 PrefsDialogjY hFn؋vLN:0O`SNRcbR0^؋LN:W(bRec N CTRL.macCommand key 0This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. PrefsDialog Ng*cvUnconnected Highlight PrefsDialog^_S hc N bR~bQCNS:R+NccNbfp O``e9S~b vfsbbNN*evfpNHWhen you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? PrefsDialogRminutes PrefsDialogLN c . = nR shift.lcbnRt Alt b %1 key = )e>Fno keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom PrefsDialogNN c . = )e> Alt b %1 key = nR shift.lcbnRt Fno keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis PrefsDialogxn[Nz ^N-yd"%1"?5Are you sure you want to remove "%1" from the sketch? ProgramTabgBoard ProgramTab(Fritzingb~N R0'%1',[OM[1Fritzing is unable to find '%1', please locate it ProgramTabe^New ProgramTabyd"%1"? Remove "%1"? ProgramTabO[XSave ProgramTab b}QeNN*z ^eNSelect a program file to load ProgramTab Y R6(&C)&Copy ProgramWindow RjR(&C)&Cut ProgramWindow (&E)&Edit ProgramWindow |4(&P)&Paste ProgramWindowSepn(&P)...&Preferences... ProgramWindow Qh (&S) &Select All ProgramWindow V(&V)&View ProgramWindowgBoard ProgramWindowY R6 bCopy selection ProgramWindowRjR b Cut selection ProgramWindowJeN'%1'N.fzzeNN-`bY NO[XNNN*g,W0Rog,Ou(YVh0]File '%1' was restored from the .fzz file; save a local copy to work with an external editor. ProgramWindow6eN'%1'N.fzzeNN-`bY Ng,W0Rog,lg b~R00HFile '%1' was restored from the .fzz file; the local copy was not found. ProgramWindow|4RjRgQ[Paste clipboard contents ProgramWindow`bY Redo ProgramWindow bb@g eg,Select all text ProgramWindowf>y:z ^QsN[hF Show the application's about box ProgramWindowdUndo ProgramWindow%1\B%1 LayerQObject%1;q \B[QY1%2 %1 mask export failure (2)QObject"%1v~N[%2N-O[XvOMnyR0/%1 wires moved from their saved position in %2.QObject<b>cϏ:</b>Description:QObject<b>YT :</b> Name:QObject<b>|{W:</b> type:QObjectWg,BasicQObjectgBoardQObjectbSg BreadboardQObject bSgVBreadboard ViewQObjectcRM Bring forwardQObject^&R0RMbBring to frontQObject$N Reˏllb~R0gbYN*g 5Cannot autoroute: no board (or multiple boards) foundQObjectN SeN %1: %2.Cannot read file %1: %2.QObject$N QN4eeN %1 %2 %3.!Cannot write file temp: %1 %2 %3.QObjecte9S%1 %2vChange leg of %1,%2QObjecthgfeCheck for updatesQObjectndnClear SettingsQObject"ndb@g O[XvnzSsQs[hF0;Clear all saved settings and close this dialog immediately.QObjectcNvrConnected highlight colorQObjectc ConnectionQObjectlcb~N:fpConvert Via to BendpointQObject lcbN:~Convert to ViaQObject^\B{ Copper BottomQObject^\B{_[~Copper Bottom TraceQObject^艆Copper Fill BottomQObjectv艆Copper Fill TopQObjectv\B{ Copper TopQObjectv\B{_[~Copper Top TraceQObjectkcW(Y R6eN%1Copying file %1QObjectc Edit linkQObjectSeN%1:%2.Error reading file %1: %2.QObject"eN%1]~[XW(N:[N Yv/File %1 already exists: it won't be overwrittenQObjecteNYt...File Progress...QObject~gFrameQObjectFritzingN }QeQCN^"Fritzing cannot load the parts binQObjectcW0XkQEy[PVhGround Fill Seed EditorQObjectICICsQObjectVhIconQObjectVhV Icon ViewQObjectQeInputQObjectQcInternal ConnectionsQObjectRQe[~ Join WireQObjectSUrGg:MicrocontrollerQObjectlg cPCBN u(ge^~0%No connections (on the PCB) to route.QObjectlg cge^~0No connections to route.QObject lb~R0QCN.No parts found.QObjectlNotesQObjectTTT!Oops!QObjectQvNOtherQObjectQOutputQObject PCBVPCB ViewQObject,Rg(1)W(L%1,R%2: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObject,Rg(2)W(L%1,R%2: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectQCNPartQObjectQCN%1'%2' Part %1 '%2'QObjectQCNVP Part ImageQObjectQCNh{~ Part LabelsQObjectQCN]~W(^N-Part already in binQObjectQCNPartsQObjectg*b~R0QCNeNY9.Parts folder not found.QObjecth{~VhPin Label EditorQObject8lanNyeeT/RFritzingbMueH.bPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectu5nPowerQObjectSepn PreferencesQObjectb~RatsnestQObject~TܘRatsnest wiresQObjecth\:RulersQObject StVVSchematic ViewQObject b %1 Select %1QObjectQh %1 Select all %1QObject bb@g 'N R^~'v~#Select all 'Don't autoroute' tracesQObject bb@g R^~v~Select all autorouteable tracesQObject b[vQCNSelect locked partsQObject bgQCNSelect outdated partsQObjectcT Send backwardQObjectO aVhSensorsQObject nQh(1)(schematic %1 unexpectedly ends (1) in %2QObject$%2N-StV%1g*eR0v\>(2)(schematic %1 unexpectedly ends (2) in %2QObject$%2N-StV%1g*eR0v\>(3)(schematic %1 unexpectedly ends (3) in %2QObjectW(%2N-g*b~R0StVQCN%1!schematic part %1 not found in %2QObject StVVschematic viewQObject N _bg*[sshape delta not implementedQObject NSp[QY1%silk export failureQObjectNSp\B silkscreen layer(s), QObject gn^~\B the board outline layer, QObjecth_bq vg*[s trapezoidal pads not implementedQObjectN Ytq v_br%1unable to handle pad shape %1QObject N bS_%1unable to open %1QObject N g%1unable to parse %1QObjectN SeveNg+zunexpected end of fileQObject*W(eN%2N-SsVhN\%1vg*weN~\>1unexpected end of file in footprint %1 in file %2QObject(g*wh<_(1)in %1 from %2#unexpected format (1) in %1 from %2QObject _ue(&I)&IgnoreRecoveryDialog `bY (&R)&RecoverRecoveryDialogp<p><b>FritzingS]~])nN OFN beNvNNe9Sg S`bY 0</b></p><p>kN*eNvYNegTef>y:N0YgeNO[XN egTeN_\RQgeu(N[k0</p><p>YgNNf~ψO[X SgeveNNq6W(O`vxvN 0O`SNW(}Qe`bY eNT bf/T&vSgeveN0</p><p><b>NN bvRhN- bO```bY veN0</b></p>

    Fritzing may have crashed, but some of the changes to the following files may be recovered.

    The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.

    The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.

    Select any files you want to recover from the list below.

    RecoveryDialogeNFileRecoveryDialogN NYN Last backupRecoveryDialogN k!O[X Last savedRecoveryDialog eNg*O[Xfile not savedRecoveryDialogu5;ResistorResistoru5; resistanceResistorA0 (1030x1456)ResizableBoard A1 (728x1030)ResizableBoard A2 (515x728)ResizableBoard A3 (364x515)ResizableBoard A4 (257x364)ResizableBoard A5 (182x257)ResizableBoard A6 (128x182)ResizableBoardLedger (17x11)ResizableBoardLegal (8.5x14)ResizableBoardLetter (8.5x11)ResizableBoard`bY RevertResizableBoard[NIcustomResizableBoard ^(mm) height(mm)ResizableBoard^: %1mm height: %1mmResizableBoard Oc[kkeep aspect ratioResizableBoard_brshapeResizableBoardY'\sizeResizableBoard [^(mm) width(mm)ResizableBoard[^: %1mm width: %1mmResizableBoard[^widthRuleregDateSchematicFrameeNT FilenameSchematicFrame]z ProjectSchematicFramerHg,RevSchematicFrameSephSheetSchematicFrameegdateSchematicFramevofSchematicFrame_brshapeSchematicFrameSephsheetSchematicFramee9Sh{~N%1 %2Change label from %1 to %2SchematicSketchWidgete9Su5SN%1%2Change voltage from %1 to %2SchematicSketchWidgetSmCancelSetColorDialognN:؋v%1rMake this the default %1 colorSetColorDialogxn[OKSetColorDialogJ%1 laO`N_SNW(r`hN-v^~r`eg,N c N hSяN*f>y:0i%1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. SketchWidget%1 %2QCN %1 %2 items SketchWidget%1h{~'%2' %1 label '%2' SketchWidgetmR%1Add %1 SketchWidgete9SChange SketchWidgete9S%1vrN%2%3Change %1 color from %2 to %3 SketchWidgete9S%1N%2%3Change %1 from %2 to %3 SketchWidgete9S%1h{~N:'%2'Change %1 label to '%2' SketchWidgete9S%1v[^N%2%3Change %1 width from %2 to %3 SketchWidgete9Su5; %1 N: %2Change Resistance from %1 to %2 SketchWidgete9S[~%1vrN:%2Change color of %1 wires to %2 SketchWidgete9SVPN%1 %2Change image from %1 to %2 SketchWidgete9S؁%1vbp0Change leg bendpoint for %1. SketchWidgete9S%1vvfs0Change leg curvature for %1. SketchWidgete9S[~%1v[^%2Change width of %1 wires to %2 SketchWidgetcConnect SketchWidgetR^^vc%1Create and connect %1 SketchWidgetR^Tc[~Create and connect wire SketchWidget NΉR^~Create wire from Ratsnest SketchWidgetR dDelete ratsnest SketchWidgetSm bDeselect SketchWidget Sm bb@g  Deselect all SketchWidgete_ Disconnect SketchWidgete_b@g %1v~Disconnect all wires from %1 SketchWidgete_b@g %1yvv~"Disconnect all wires from %1 items SketchWidgetSQ Double-click SketchWidget SQR dbp&Double-click to delete this bend point SketchWidget bbbSQDrag or double-click SketchWidgetlFlip SketchWidgetPq %2 (%1) Flip %2 (%1) SketchWidgetyR%2 (%1) Move %2 (%1) SketchWidgetyR%2vyv(%1)Move %2 items (%1) SketchWidgetyRh{~ '%1'Move label '%1' SketchWidgetyR Move leg of SketchWidgetlae[WvSSNote text change SketchWidget `bY lY'\ Resize Note SketchWidgetngY'\%1 %2Resize board to %1 %2 SketchWidgetY OMh\:N:%1 %2Resize ruler to %1 %2 SketchWidgeteˏlRotate SketchWidgeteˏl%2 (%1)Rotate %2 (%1) SketchWidget b %1 Select %1 SketchWidget b%1yvSelect %1 items SketchWidgetQh  Select All SketchWidget b Selection SketchWidgetlg g*^~vc!There are no unrouted connections SketchWidget AboutBox <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>代码遵守GNU GPL v3 其他内容遵守 CreativeCommons:BY-SA <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Fritzing 的作者是: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: 特别感谢: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, 感谢 Kurt Badelt和Miguel Solis 对西班牙语的翻译, to Gianluca Urgese for the Italian translation, Gianluca Urgese 对意大利版的翻译, to Nuno Pessanha Santos for the Portuguese (European) translation, Nuno Pessanha Santos 对葡萄牙(欧洲)版的翻译, to Yuelin and Ninjia for the Chinese (Simplified) translation, Yuelin和Ninjia 对简体中文版的翻译, to Hiroshi Suzuki for the Japanese translation, Hiroshi Suzuki 对日文版的翻译, to Robert Lee for the Chinese (Traditional) translation, Robert Lee 对繁体中文版的翻译, to Vladimir Savinov for the Russian translation, Vladimir Savinov 对俄罗斯版的翻译, Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> to Josef Dustira for the Czech translation, Josef Dustira对捷克语的翻译, to Jinbuhm Kim for the Korean translation, Jinbuhm Kim对韩语的翻译, to Alexander Kaltsas for the Greek translation, Alexander Kaltsas对希腊语的翻译, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, &#313;ubom&iacute;r Ducho&#328; 对斯洛伐克语的翻译, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. to Nikolay Stankov for the Bulgarian translation, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, AutorouteProgressDialog Cancel 取消 Stop Now 现在停止 zoom and pan controls 缩放旋转控制 Best So Far Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type 产品型号 homebrew 自制 professional 专业 custom 自定义 Trace width 铜线宽度 Cancel 取消 OK 确定 Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. 0.01inch(0.254mm)的最小距离是一个好的默认值。 Note: the smaller the keepout, the slower the DRC and Autorouter will run. BinManager Parts 元件 BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty 库管理器::设置废标签:不能设置库'%1'作为dirty New bin (%1) 新建库(%1) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing Bin文件(*%1 *%2);;Fritzing Bin (*%1);;Fritzing可分享Bin (*%2) Cannot set a NULL bin as the current one 不能设置当前库为空 BinManager::updateTitle: Couldn't set the bin '%1' as dirty 库管理器::更新标题:不能把库'%1'设置dirty Select a Fritzing Parts Bin file to open 选择要打开的Fritzing元件库文件 Bin 元件库 New Bin... 新元件库... Create a new parts bin 创建新元件库 Close Bin 关闭库 Close parts bin 关闭元件库 Delete Bin 删除库 Delete parts bin 删除元件库 Save Bin 保存库 Save parts bin 保存元件库 Save Bin As... 另存库为... Save parts bin as... 另存元件库为... Export Bin... 导出库... Save parts bin in compressed format... 以压缩格式保存元件库... Rename Bin... 重命名库... Rename parts bin... 重命名元件库... Show Bin in List View 列表视图显示库 Display parts as a list 以列表显示元件 Show Bin in Icon View 图标视图显示库 Display parts as icons 以图标的形式显示库 Export Part... 导出元件... Remove Part 移除元件 Delete bin 删除库 Do you really want to delete bin '%1'? This action cannot be undone. 你确定要删除库'%1'?这个操作不能被恢复。 Read-only bin 只读库 This bin cannot be renamed. 这个库不能被重命名。 Rename bin 重命名库 Please choose a name for the bin: 请为库选择一个名字: Remove from bin 从库中移除 Searching... 查找中... Import... 导入... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) 载入Fritzing原件(.fzpz),或者 Fritzing元件库(.fzb, .fzbz) Select a Fritzing File to Open 选择要打开的Fritzing文件 Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing文件 (*%1 *%2 *%3);;Fritzing元件(*%1);;Fritzing元件库(*%2);;Fritzing分享元件库(*%3) Edit Part (new parts editor)... 编辑元件(新元件编辑器)... Find Part in Sketch Remove from Bin Unable to remove part '%1'--it is in use in a sketch Do you really want to remove '%1' from the bin? This operation cannot be undone. Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Board one layer (single-sided) 一层(单面) two layers (double-sided) 两层(双面) Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. 查看一下你的Fritziing安装文件夹parts/svg/core/pcb/中Circle_pcb.svg文件。 image file 图像文件 load image file 载入图像文件 Images 图像 Select an image file to load 选择一个载入的图像文件 due to an xml problem: %1 line:%2 column:%3 由于xml问题:%1排:%2列%3 because the xml is not correctly formatted 因为xml不是正确的格式 the <board> element contains no shape elements <board>元素包含没有形状的元素 because there are multiple <board> layers 因为有多个<board>层 because there are multiple <silkscreen> layers 因为有多个<silkscreen>层 because there is no <board> layer 因为没有<board>层 the svg contains no shape elements svg不包含形状元素 but the pcb itself will have no silkscreen layer 因为PCB本身不包含丝印层 the svg doesn't fit the custom board format svg不适合自定义板格式 Unable to load 不能载入 Unable to load image from %1 %2 不能从%1 %2中载入图像 Can load, but 不能载入,但是 The image from %1 can be loaded, but %2 Use the file? %1的图像可以被载入,但是%2 使用这个文件? A custom board svg typically has one or two silkscreen layers and one board layer. because there are multiple <silkscreen0> layers <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. BoardLogoItem shape 形状 BreadboardLogoItem color 颜色 Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint 增加曲点 Remove bendpoint 移除曲点 Straighten curve 拉直曲线 ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools 工具 &About 关于(&A) About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit 退出(&Q) Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected Critical Error About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. DRC DRC was cancelled. DRC取消了. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. 你的样板已经准备好生产:没有接插件或布线重复或者太靠近了。 The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. 你板上红色高亮的区域是接插件和连接线可能重叠或者靠一起了。 Reposition them and run the DRC again to find more problems 重排布他们,并再次运行DRC找出更多问题 Fritzing error: unable to render board svg. Fritzing错误:不能渲染板子的svg。 No traces or connectors to check 没有连线或接插件被检查 Unexpected SVG rendering failure--contact fritzing.org 不可预料的SVG渲染错误--联系fritzing.org Fritzing Fritzing %1 is overlapping (%2 layer) Too close to a border (%1 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. DRCResultsDialog DRC Results DRC结果 Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. 注意:列表中的项目和红色高亮的项目在你编辑设计的时候不会更新--你必须返回DRC。高亮在你关闭对话框的时候会消失。 Click on an item in the list to highlight of overlap it refers to. DebugDialog for debugging 测试用 DeleteDialog Also delete the file 同时删除文件 Remove 移除 Don't remove 不要移除 Dip chip label 芯片标签 FApplication Import files from previous version? 从早期版本导入? Import 导入 Do not import now 现在导入么 Fritzing failure Fritzing 出错了 Fritzing caught an exception from %1 in event %2 Fritzing 在event %2 中获得了一个 %1的意外 Fritzing caught an exception %1 from %2 in event %3 Fritzing 在event %3 中获得了一个 %2的%1意外 Do you want to import parts and bins that you have created with earlier versions of Fritzing? 你想要导入使用早期版本的Fritzing创建的元件和元件库么? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. 提示:你可以在稍后使用"帮助">"从早期版本中导入元件和元件库"菜单导入他们. Please specify an .fzz file name to save to (cancel will delete the backup) 请指定一个.fzz文件名来以便保存(取消将删除备份) Fritzing (*%1) Fritzing (*%1) Fritzing caught an exception from %1 in event %2: %3 FirstTimeHelpDialog First Time Help 首次使用帮助 <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window 关闭窗口(&C) Ctrl+W Ctrl+W Close the current sketch 关闭当前程序 %1 - %2 %1 - %2 Specify a file name 指定文件名 Save "%1" 保存 "%1" Do you want to save the changes you made in the document "%1"? 保存在文档"%1"所做的修改么? Save... 保存... Save 保存 Don't Save 不保存 Ctrl+D Ctrl+D Your changes will be lost if you don't save them. 如果不保存,所做的修改将会丢失. Cancel 取消 GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. 底面填充和覆铜填充的区别在于,在底面填充时,填充区域包含连线和连接到地的接插件。接地的姐常见通常标示为'GND'或'ground',但有时这不是关键问题。它也可能是有多重网络标号连接到一个接插件上,你应该是只想要其中的一个呗填充。 这个对话框收集了包含只标有'GND'或者'ground'标签唯一接插件,而且这些接插件已经被选为种子。 选择一个以便高亮他在草稿上的连接。 也可以使用右键选择一个作为接地填充种子的接插件,然后选择设置为接地填充种子的菜单选项。 Cancel 取消 OK 确定 OK and ground fill 确定并对地铺铜 OK and copper fill 确认并覆铜 Hole hole size 孔径 HtmlInfoView Connections 连接数 conn. 接口. connected to %n item(s) 连接到了 %n 个元件 name 名字 type 类型 (autoroutable) (可自动布线) Wire 导线 Trace wire %1 引导线%1 Properties 属性 Tags 关键词 Change the part label here 这里修改元件标签 Part breadboard view image 元件面包板视图图片 Part schematic view image 元件原理图视图图片 Part pcb view image 元件pcb视图图片 Part version number 元件版本号 Locked 锁定 Ratsnest wire 飞线连线 Change the locked state of the part in this view. A locked part can't be moved. 改变此视图中的元件锁定状态。锁定的元件不能被移动。 Sticky 粘联 Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. 改变视图中"粘联"的状态。当粘联的元件移动时,它上面的元件也会移动。 v. %1 %2 v. %1 %2 obsolete 废弃的 Placement pcb layer location rotation degrees ItemBase Part 元件 family 类族 color 颜色 resistance 电阻 voltage 电压 pin spacing 针脚距离 rated power 额定功率 rated voltage 额定电压 rated current 额定电流 version 版本 package shape 形状 maximum resistance 最大电阻 size 大小 form 组成 model part problem 模型元件问题 capacitance 电容 inductance 电感 current 电流 power 电源 part number 元件号 type 类型 model 型号 pins 针脚 spacing 空间 frequency 频率 processor 处理器 variant 变形 layers tolerance 公差 descr 描述 filename 文件名 title 标题 date 日期 rev 版本 sheet 表单 project 项目 unable to create renderer for svg %1 不能为svg%1创建渲染 file for %1 %2 not found %1 %2的文件未找到 banded top 顶部 bottom 底部 copper bottom copper top silkscreen bottom silkscreen top KicadModuleDialog Cancel 取消 OK 确定 LayerPalette show all layers 显示所有层 LinkDialog Cancel 取消 OK 确定 url: url: text: 文本: LogoItem Unable to display 不能显示 Unable to display image from %1 不能从%1显示图像 shape 形状 due to a rendering error 由于渲染错误 because the svg is empty 因为svg为空 due to an xml problem: %1 line:%2 column:%3 由于xml问题:%1 线:%2列:%3 because the file has no root element 因为文件没有root元素 because the file has no <svg> element 因为文件没有<svg>元素 for unknown reasons--possibly the image file is corrupted 因为未知原因--可能图像文件不正确 because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting 出现这个可能是因为从CorelDRAW中导出的SVG文件没有选择'提示属性'设置 text MainWindow Rotate 旋转 Share 分享 Flip 翻转 Autoroute 自动布线 Add a note 添加注释 Ready 准备好 Save %1 保存 %1 Specify a file name 指定文件名 Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable 不能将%1导出为可分享的 Fritzing Part (*%1) Fritzing元件 (*%1) Unable to export %1 to shareable sketch 不能把%1导出为可分享设计 Do you want to keep the imported parts? 保存已经导入的元件么? No connections to route 没有需要布线的连接 Routing completed 布线完成 %1 of %2 nets routed - %n connector(s) still to be routed %2中的%1网络布线完成-%n个接插件仍然需要布线 %1 - [%2] %1 - [%2] Sorry! 抱歉! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist 没有这些参数的原件. 我们努力避免这个信息,以便您可以从已有的属性的原件中选择 Swapped %1 with module %2 用模块%2替代%1 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 丢失了 '%2'层. 如何创建自定义板型的更多信息,请查看在<a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>的向导. PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG图像(*.png) JPEG Image (*.jpg) JPEG图像(*.jpg) SVG Image (*.svg) SVG图像(*.svg) Printing... 打印中... All traces have not yet been routed. 不是所有的引导线都被排布。 Do you want to proceed anyway? 无论如何都要继续么? Proceed 进行中 Cancel 取消 Sketch exported 设计已导出 Export... 导出... Exporting... 导出中... Unable to save %1 不能保存%1 Cannot print to %1 不能打印为%1 Cannot write file %1: %2. 不能写入文件%1: %2. Saved '%1' 保存了 '%1' Select a Fritzing File to Open 选择要打开的Fritzing文件 Cannot find file %1. 找不到文件%1. Cannot read file 1 %1: %2. 不能读取文件 1 %1: %2. directly loading parts 直接载入元件 loading %1 (model) 载入%1(模块) loading %1 (breadboard) 载入%1(面包板) loading %1 (pcb) 载入%1(pcb) loading %1 (schematic) 载入%1(原理图) Create a new sketch 创建新设计 &Open... 打开(&O)... Ctrl+O Ctrl+O &Save 保存(&S) Ctrl+S Ctrl+S Save the current sketch 保存当前设计 &Save As... 另存为(&S)... Shift+Ctrl+S Shift+Ctrl+S Share online... 在线分享... Post a project to the Fritzing website 向Fritzing网址发布工程 Export the visible area of the current sketch as a JPG image 导出当前程序的可见区域为JPG图像 Export the visible area of the current sketch as a PNG image 导出当前程序的可见区域为PNG图像 Export the visible area of the current sketch as a PostScript image 导出当前设计的可见区域为轮廓线图像 Export the visible area of the current sketch as a PDF image 导出当前程序的可见区域为PDF图像 Export the current sketch as an SVG image 导出当前程序的为SVG图像 List of parts (&Bill of Materials)... 元件列表(材料单)(&B)... Save a Bill of Materials (BoM)/Shopping List as text b保存材料单(BoM)/采购列表为文本 XML Netlist... XML网络表... Save a netlist in XML format 保存网络表为XML格式 Export the current sketch to Eagle CAD 导出当前设计至Eagle CAD &Print... 打印(&P)... Ctrl+P Ctrl+P Print the current view 打印当前视图 &Quit 退出(&Q) Ctrl+Q Ctrl+Q Quit the application 退出程序 &Open Example 打开例子(&O) MainWindow::populateMenuWithIndex: couldn't load example with id='%1' 主窗口::populateMenuWithIndex: 不能载入id为'%1'的例子 &Open Recent Files 打开最近文件(&O) &%1 %2 &%1 %2 Undo 撤销 Redo 恢复 &Cut 剪切(&C) Cut selection 剪切选择 &Copy 复制(&C) Copy selection 复制选择 &Paste 粘贴(&P) Paste clipboard contents 粘贴剪切板内容 &Duplicate 制作副本(&D) Ctrl+D Ctrl+D Duplicate selection 为当前选择制作副本 &Delete 删除(&D) Delete selection 删除选择 &Select All 全选(&S) Select all elements 选择所有元素 &Deselect 取消选择(&D) Deselect 取消选择 Add Note 添加注释 &Preferences... 参数设置(&P)... Show the application's about box 显示程序关于对话框 &Edit 编辑(&E) &Add to bin... 加入元件库(&A)... Add selected part to bin 将选择元件加入元件库 Disconnect All Wires 断开所有连线 Disconnect all wires connected to this connector 断开所有连接到这个接插件的连线 Update InfoView on hover 鼠标悬停时更新信息视图 Rotate the selected parts by 90 degrees clockwise 将选择的元件顺时针旋转90度 Rotate the selected parts by 180 degrees 将选择的元件旋转180度 Rotate current selection 90 degrees counter clockwise 将当前选择的元件逆时针旋转90度 &Flip Horizontal 水平翻转(&F) Flip current selection horizontally 水平翻转当前旋转 &Flip Vertical 垂直翻转(&F) Flip current selection vertically 垂直翻转当前选择 Bring to Front 提到上层 Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer 将选择对象移至所在层的正面 Bring Forward 升到上层 Ctrl+] Ctrl+} Bring selected object(s) forward in their layer 将选择的对象带到所在层的上面 Send Backward 降到下层 Ctrl+[ Ctrl+[ Send selected object(s) back in their layer 将选择对象移至所在层的下面 Send to Back 发送至下面 Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer 将选择对象移至所在层的下面 &Show All Layers 显示所有层(&S) Show all the available layers for the current view 在当前视图中显示所有可见层 &Hide All Layers 隐藏所有层(&H) Hide all the layers of the current view 隐藏当前视图的所有可见层 &Show part label 显示元件标签(&S) &Export... 导出(&E)... Export selected part 导出选择的元件 Add Bendpoint 添加拐点 Add a bendpoint to the selected wire 为选择的导线增加拐点 &Zoom In 放大(&Z) Ctrl++ Ctrl++ Zoom in 放大 Ctrl+= Ctrl+= &Zoom Out 缩小(&Z) Ctrl+- Ctrl+- Zoom out 缩小 &Fit in Window 适合窗口(&F) Ctrl+0 Ctrl+0 Fit in window 适合窗口 &Actual Size 实际大小(&A) Shift+Ctrl+0 Shift+Ctrl+0 &Show Breadboard 显示面包板(&S) Ctrl+1 Ctrl+1 Show the breadboard view 显示面包板视图 &Show Schematic 显示原理图(&S) Ctrl+2 Ctrl+2 Show the schematic view 显示原理图视图 &Show PCB 显示PCB(&S) Ctrl+3 Ctrl+3 Show the PCB view 显示PCB视图 &Minimize 最小化(&M) Ctrl+M Ctrl+M Minimize current window 最小化当前窗口 Debugger Output Debugger输出 Online Tutorials 在线指导 Ctrl+? Ctrl+? Open Fritzing help 打开Fritzing帮助 Online Projects Gallery 在线项目库 Open Fritzing examples 打开Fritzing示例 Online Parts Reference 在线元件参考 Open Parts Reference 打开元件参考 First Time Help 首次使用帮助 Check for updates... 检查更新... Check whether a newer version of Fritzing is available for download 检查是否有新版Fritzing供下载 &About 关于(&A) Display some handy Fritzing tips and tricks 显示Fritzing的一些简单的技巧和提示 &About Qt 关于 Qt(&A) Show Qt's about box 显示 Qt 的关于对话框 Report a but you've found in Fritzing 报告在Fritzing中发现的bug &Import parts and bins from old version... 从旧版本中导入元件和元件库(&I)... Import parts and bins from previous installation 从之前安装的版本中中导入元件和元件库 &File 文件(&F) &Export 导出(&E) &Part 元件(&P) Raise and Lower 升降元件 &View 视图(&V) &Window 窗口(&W) &Help 帮助(&H) Page Setup 页面设置 Sorry, "%1" has not been implemented yet 抱歉,"%1"还没有实现 Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. 你的设计中还没有包含板!请添加一块PCB以便导出至Gerber. Choose a folder for exporting 选择导出文件夹 This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. 不久后将提供将Fritzing导出至EAGEL布局的软件.如果你想要导出至更多你喜欢的EDA工具中,请让我们知道,或者提供一些贡献。 Export SVG... 导出SVG... Export Bill of Materials (BoM)... 导出材料单(BoM)... Export Netlist... 导出网络表... Select All Traces 选择所有引导线 Select all trace wires 选择所有引导线导线 Select all trace wires excluded from autorouting 选择所有被排除在自动布线外的引导线 Tidy Wires 整理线 Tidy selected wires 整理选择导线 Copper Fill 覆铜 Remove Copper Fill 移除覆铜 Remove the copper fill 移除覆铜层 Autorouting... 自动布线中... Remove Bendpoint 移除拐点 Please choose the previous Fritzing folder... 请选择上层Fritzing文件夹... You will have to restart Fritzing in order to use the imported parts 使用导入的元件必须重新启动Fritzing Remove copper fill 移除覆铜 &Wire Color 连线颜色(&W) Export Normalized SVG 导出为标准的SVG Export 1000 dpi SVG of this part in this view 导出为1000 dpi在此视图中元件的SVG图像 Export Normalized Flattened SVG 导出标准的SVG图像 Export 1000 dpi Flattened SVG of this part in this view 导出为1000 dpi在此视图中元件的SVG图像 Select outdated parts 选择过期元件 Update selected parts 更新选择的元件 No outdated parts found. All your parts are up-to-date. 未找到过期元件。 您所有的元件都是最新的。 Outdated parts 已过期元件 Successfully updated %1 part(s). Please check all views for potential side-effects. 成功更新了 %1 个元件. 请检查所有的视图以保证有正确的效果。 Update %1 part(s) 更新了 %1 个元件 No exactly matching part found; Fritzing chose the closest match. 没有找到精确的零件;Fritzing选择了一个相近的. Shell launch %1 启动框架%1 Launch %1... 启动%1... All 所有 throw test exception 抛出测试意外 throw a fake exception to see what happens 抛出一个伪意外,查看发生了什么事 Select All Jumpers 选择所有跳线 New 新建 Ctrl+N Ctrl+N Tips, Tricks and Shortcuts 技巧,诀窍和快捷键 Align to Grid 对齐至网格 Align items to grid when dragging 拖动时对齐至网格 Open programming window 打开编程窗口 Open microcontroller programming window 打开单片机编程窗口 Report a bug... 报告bug... Enable debugging log 启用调试记录 Both Layers 双层 Bottom Layer 底层 Top Layer 顶层 Backing up '%1' 备份'%1'中 Rotate current selection 45 degrees counter clockwise 逆时针旋转当前选择45度 Rotate current selection 45 degrees clockwise 顺时针旋转当前选择45度 Actual (real world physical) size 实际尺寸(真实物理尺寸) 100% Size 100%大小 100% (pixel) size 100%(像素)大小 Set both copper layers clickable 设置双面铜层可点击 Set copper top layer clickable 设置顶层铜层可点击 Set copper bottom layer clickable 设置底层铜层可点击 Copper Top and Copper Bottom layers are both active 激活上下覆铜层 Copper Top layer is active 顶层覆铜层激活 Copper Bottom layer is active 底层覆铜层激活 Autorouting Progress... 自动布线处理... File '%1' not found 未找到文件'%1' Paste in Place 粘贴到这里 Paste clipboard contents in place 将剪贴板内容粘贴到这里 Delete 删除 Routing completed using %n jumper part(s) 使用%n个跳线元件完成了布线 Delete Ratsnest Line 删除覆铜线 Delete Wire 删除导线 Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) 将选择的引导线移至板的另一面(注释:一条引导线移动了和其相关的也将移到另一面) Force Update Routing Status and Ratsnests 强制更新布线状态和覆铜 Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) 重新计算布线状态和覆铜线(在自动更新不能正确工作的情况下) Lock Part 锁定元件 Prevent a part from being moved 防止元件被移动 Select All Locked Parts 选择所有锁定元件 Select all parts that can't be moved 选择所有不能移动元件 Show Parts Bin Icon View 显示元件库图标视图 Display the parts bin in an icon view 在图标视图中显示元件库 Show Parts Bin List View 以列表视图显示元件库 Display the parts bin in a list view 在列表视图中显示元件库 Donate to Fritzing 捐赠Fritzing Open Fritzing donation web page 打开Fritzing捐赠网址 Export for PCB 导出为PCB Export the current sketch to PDF for DIY PCB production (photoresist) 导出当前项目至PDF进行DIY的PCB生产(photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) 导出当前项目至SVG进行DIY的PCB生产(photoresist) JPG... JPG... PNG... PNG... PostScript... PostScript... PDF... PDF... SVG... SVG... Eagle... Eagle... Etchable (PDF)... Etchable (SVG)... as Image 作为图像 for Production 为了生产 loading %1 %1载入中 Loading... 载入中... new sketch 新草稿 BoM Text File (*.html) BoM Text File (*.html) Extended Gerber (RS-274X)... Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production 导出当前草稿至Extended Gerber format (RS-274X)以便专业的PCB生产 Unable to save BOM file, but the text is on the clipboard. 不能保存为BOM文件,单文本仍在剪切板中。 Do not autoroute 不自动布线 When autorouting, do not rip up this trace wire, via, or jumper item 当自动布线时,不要分开这些线,飞线和跳线元件 Move to other side of the board 转到板的另一面 Select all jumper item parts 选择所有跳线项目元件 Select All Vias 选择所有Vias Select all via parts 选择所有via元件 Shift+Ctrl+D Shift+Ctrl+D Order a PCB... 获得一块PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab 获得一块从你的草稿中创建的PCB--来自传说中的Fritzing Fab Straighten Curve 拉直曲线 Straighten the curve of the selected wire 拉直选择的曲线 Select All CopperFill 选择所有覆铜 Select all copper fill items 选择所有覆铜的项目 unable to find replacement for %1. 从%1中找不到可以替换的. Ctrl+R Rotate Clockwise 顺时针旋转 Ctrl+R Alt+Ctrl+R Rotate Clockwise 顺时针旋转 Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise 顺时针旋转 Meta+Ctrl+R Shift+Ctrl+R Rotate Counterclockwise 逆时针旋转 Shift+Ctrl+R Alt+Shift+Ctrl+R Rotate Counterclockwise 逆时针旋转 Alt+Shift+Ctrl+R Meta+Shift+Ctrl+R Rotate Counterclockwise 逆时针旋转 Meta+Shift+Ctrl+R Shift+Ctrl+Tab Toggle Active Layer 锁定活动层 Shift+Ctrl+Tab Sketch exported to Gerber 导出草稿到Gerber Shift+Ctrl+A Shift+Ctrl+A Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 Ground Fill 接地填充 Fill empty regions of the copper layer--fill will include all traces connected to a GROUND 填充铜层中空的区域--填充将包含所有连接到地的线 Fill empty regions of the copper layer--not including traces connected to a GROUND 填充铜层中空的区域--填充将不包含任何连接到地的线 No copper top layer 顶层没有覆铜 The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. 顶层覆铜(copper 1)层不支持单面板。请将板转换为双面或者选择底层覆铜(copper 0)层。 No Sketch found in '%1' 未找到草稿'%1' the .fz file format is obsolete .fz文件格式已经被停止使用了 The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? .fz文件格式已经不在建议使用了。 你现在想转换'%1'为.fzz格式或者以只读格式打开它么? The conversion process will not modify '%1'. 转换处理过程不会改变'%1'。 Convert 转换 Read-only 只读 Please specify an .fzz file name to save '%1' to 请为'%1'指定一个.fzz的文件名 &Routing 布线(&R) &Create trace from ratsnest 从网孔中创建导线(&C) Create a trace from the ratsnest line 从ratsnest线中创建一根导线 &Create wire from ratsnest 从网孔中创建线(&C) Create a wire from the ratsnest line 从ratsnest线中创建一根线 Select All Wires 选择所有线 Select all wires 选择所有线 Fill empty regions of the copper layer--fill will include all traces connected to the seeds 填充覆铜层的空区域--填充将包含所有连接至种子的导线 Choose Ground Fill Seed(s)... 改变接地填充种子... Set Ground Fill Seed 设置接地填充种子 Treat this connector and its connections as a 'ground' during ground fill. 在进行接地填充时把这个接插件和与它有关的连接作为'地'. Clear Ground Fill Seeds 清除接地填充种子 Clear ground fill seeds--enable copper fill only. 清除接地填充种子--只允许覆铜填充。 Generating %1 fill... 生成%1填充... ground copper 覆铜 Show Grid 显示网格 Show the grid 显示指定的网格 Actual Size 实际尺寸 It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. 看起来不可能自动决定显示器的实际物理尺寸,所以当前'实际尺寸'的实现只是一个猜想。你最好使用一个尺子元件,然后放一个(物理上的)尺子在上面,缩放直至他们尺寸匹配。 Select All "Don't Autoroute" Traces 选择所有'不自动布线'的线 Select All Autoroutable Traces 选择所有自动布线的线 Select all trace wires that can be changed during autorouting 选择所有在自动布线时可以改变的线 Change to single layer pcb 转换为单层PCB Change to two layer pcb 转换为双层PCB Change image to %2 转换图像为%2 Gerber export can only handle one board at a time--please select the board you want to export. Gerber导出一次只能处理一片板--请选择你想导入的板子。 Sticky 粘联 If a "sticky" part is moved, parts on top of it are also moved 如果一个"粘连"元件移动了,在它上面的元件也会被移动 Set Grid Size... 设置网格尺寸... Set the size of the grid in this view 设置此视图中的网格尺寸 Set Background Color... 设置背景颜色... Set the background color of this view 设置此视图中的背景颜色 jumpers 跳线 copperfill 覆铜 vias 飞线 OK 确定 Set the grid size for %1. 设置网格大小为%1。 Grid Size: 网格大小: in in mm mm Restore Default 恢复默认值 Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) Fritzing 文件(*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing分享(*%2);;Fritzing元件(*%3);;Fritzing元件库(*%4);;Fritzing分享元件库(*%5) Your sketch does not have a board yet! Please add a PCB in order to export etchable. 你的设计还没有板子!请添加一块PCB以便导出可蚀刻的。 Etchable export can only handle one board at a time--please select the board you want to export. 可蚀刻的导出每次只能处理一块板--请选择你想导出的板子。 Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. 你的设计还没有板子!请添加一块PCB以便可以使用自动布线。 Please select the board you want to autoroute. The autorouter can only handle one board at a time. 请选择你想自动布线的板。自动布线每次只能处理一块板。 Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. 你的设计中还没有板子!请添加一块PCB以便可以使用地或铜层填充。 Please select a PCB--copper fill only works for one board at a time. 请选择一块PCB--铜填充一次只能为一块板工作。 Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. 你的设计中还没有板子!请添加一块PCB以便可以移除铜填充。 Please select a PCB--ground fill operations only work on a one board at a time. 请选择你想自动布线的板。地填充操作每次只能处理一块板。 Your sketch does not have a board yet! DRC only works with a PCB. 你的设计中还没有包含板!DRC只能在有PCB时工作. Please select a PCB. DRC only works on one board at a time. 请选择一块PCB。DRC一次只能处理一块板。 Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. 你的设计中还没有包含板!请添加一块PCB以便使用覆铜功能. Please select a PCB. Copper fill operations only work on one board at a time. 请选择一块PCB--铜填充一次只能为一块板工作。 Convert Bendpoint to Via 将曲点变为飞线 Convert the bendpoint to a via 转换一个曲点为飞线 Convert Via to Bendpoint 转换飞线为曲点 Convert the via to a bendpoint 转换飞线为曲点 Revert? 恢复? This operation can not be undone--you will lose all of your changes. Go ahead and revert? 这个操作不能被重做--将会失去所有的修改。 继续并恢复? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) 打开一个Fritzing设计(.fzz, .fz), 或载入Fritzing元件or load a Fritzing part(.fzpz),或Fritzing元件库(.fzb, .fzbz) Revert 恢复 Reload the sketch 重新载入设计 Check Loaded Traces 检查载入的线 Unrouted connections 未布线的连接 There are no unrouted connections in this view. 这个视图中没有未布线的连接。 Edit (new parts editor) 编辑(新元件编辑器) Open the new parts editor on an existing part 在一个已存在的元件上打开新元件编辑器 Show unrouted 显示未布线 Highlight all unrouted connectors 高亮所有未布线的接插件 Inspector 指示栏 Undo History 撤销历史 Breadboard 面包板 Schematic 原理图 PCB PCB Layers Couldn't get the dock widget 不能获得可停靠控件 &Delete Wire 删除线(&D) Parts Editor Help 元件编辑器帮助 Display Parts Editor help in a browser 在浏览器中显示元件编辑器帮助 The folder "%1" isn't a Fritzing installation folder 文件夹"%1"不是Fritzing安装文件夹 Design Rules Check (DRC) 设计规则检查(DRC) DRC Progress... DRC进行中... Highlights any parts that are too close together for safe board production 为安全板产品高亮任何过于接近的元件 Autoroute connections... Show/hide the label for the selected parts Hide part silkscreen Hide/show the silkscreen layer for only this part Hide part label 隐藏元件标志 Show part label Show part silkscreen Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Ctrl+4 Ctrl+4 Code Show Code Show the code (programming) view Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab Find part in sketch... Search for parts in a sketch by matching text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. SPICE Netlist... Save a netlist in SPICE format Unable to open '%1': %2 Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Export SPICE Netlist... Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Enter Text View from Above View from Below View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Delete Minus Delete selection without attached wires Delete Wire up to bendpoints Move to bottom layer Move to top layer Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom Align top and bottom bottom 底部 top 顶部 Ground Fill (%1) Copper Fill (%1) Do you want to update now? There are %n outdated part(s) in this sketch. Click to highlight unconnected parts Fabricate Welcome Dump all parts Debug dump all parts in this view Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view Display First Time Help Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. %1 background Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Test Connectors Connect all connectors to a single test part Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Rotate 45� Clockwise 顺时针旋转135° {45�?} Rotate 90� Clockwise 顺时针旋转135° {90�?} Rotate 180� 旋转 180° {180�?} Rotate 90� Counter Clockwise 逆时针旋转45° {90�?} Rotate 45� Counter Clockwise 逆时针旋转45° {45�?} Ctrl+Shift+V (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 MazeRouter Autorouter was cancelled. round %1 of: round %1 of: Unexpected SVG rendering failure--contact fritzing.org 不可预料的SVG渲染错误--联系fritzing.org best so far: %1 of %2 routed with %n vias Routing reached maximum round %1. Routing stopped! Routing complete! Routing unsuccessful; stopping at round %1. Use best so far... Preparing undo... Optimizing traces... ModelBase File save failed! 保存文件失败! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) 不能覆盖文件 '%1'. 原因是:%2 (错误代码为 %3) Unable to find the following %n part(s): 不能够找到如下%n个元件: at MysteryPart label 标签 chip label 芯片标签 NetLabel net label 网络标签 Note [write your note here] [这里写注释] PCBSketchWidget Click this connector to drag out a new trace. 点击这个接插件拖出新的引导线. Change trace layer 改变引导线层 Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. 你的设计中还没有包含板!请添加一块PCB以便使用覆铜功能. Fritzing error: unable to render board svg (1). Fritzing错误:不能渲染板svg (1). Fritzing error: unable to render copper svg (1). Fritzing错误:不能渲染铜层svg (1). Fritzing error: unable to write copper fill (1). Fritzing错误:不能写覆铜层 (1). Fritzing error: unable to write copper fill (2). Fritzing错误:不能写覆铜层 (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. 不能创建覆铜层--元件可能没有放置到PCB上。 Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. 不能创建覆铜层--元件可能放置到另外一个元件或者线上而没有放在实际PCB上。 Create Trace from Ratsnest 从预拉线中创建线 Please designate one or more ground fill seeds before doing a ground fill. 请在做接地填充前指定一个或多个接地填充种子。 Clear ground fill seeds 清除接地填充种子 %1 Fill: please select the board you want to apply fill to. %1填充:请选择你想应用填充的板。 Ground 接地 Copper 覆铜 Copper fill: please select only the board you want to fill. 覆铜:请只选择想要填充的板子。 Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. 你的设计中还没有板子!请增加一块PCB以便使用选择操作。 Please click on a PCB first--this selection operation only works for one board at a time. 请先点击一下PCB--这个选择操作每次只能对一块板起作用。 Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. 你的设计中还没有板子!请增加一块PCB以便使用选择操作。 Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. 不能将此飞线转换为曲点,因为它连接至只在底层的一个元件,另外一个元件只在顶层。 Show part silkscreen Hide part silkscreen Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: Fritzing Fab Quote Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. PEConnectorsView This is where you edit the connector metadata for the part 这里用来编辑接插件元件的元数据 number of connectors: 接插件数量: Through-hole 通孔 SMD SMD PEMainWindow Parts Editor 元件编辑器 Show Icon 显示图标 Ctrl+4 Ctrl+4 Show the icon view 显示图标视图 Ctrl+5 Ctrl+5 Show the metadata view 显示元数据视图 Show Connectors 显示接插件 Ctrl+6 Ctrl+6 Change %1 to '%2' 转换%1至%2 Change tags 转换标签 Change properties 转换属性 Change description 转换描述 Change connector %1 转换接插件%1 SVG SVG Connectors 接插件 Show in Folder 文件中显示 On the desktop, open the folder containing the current svg file. 在桌面上,打开包含当前svg文件的文件夹。 Unable to write svg to %1 不能写入svg至%1 Unable to parse fzp file %1 不能解析fzp文件%1 Icon View 图标视图 Metadata View 元数据视图 Connectors View 接插件视图 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) 图形和器件封装文件(%1 %2 %3 %4 %5);;SVG 文件 (%1);;JPEG 文件 (%2);;PNG 文件 (%3);;gEDA器件封装文件 (%4);;Kicad Module 文件 (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 图形文件 (%1 %2 %3);;SVG 文件 (%1);;JPEG 文件 (%2);;PNG 文件 (%3)%4%5 Open Image 打开图像 Copy problem 复制问题 Unable to make a local copy of: '%1' 不能建立本地副本:'%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. 你可以使用PNG或JPG图像建立你的元件,但最好使用SVG建立。 PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- PNG和JPG图像保持他们位图的属性,当缩放时看起来不好-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. 所以对于Fritzing元件最好只使用PNG和JPG作为占位符。 Use of PNG and JPG discouraged 使用PNG和JPG是不被建议的 Conversion problem 转换问题 SVG problem SVG问题 Unable to parse '%1': %2 line:%3 column:%4 不能解析'%1':%2线:%3列:%4 There are no copper layers defined in: %1. 在%1中没有定义覆铜层。 See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. 查看 <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">这个解释</a>。 <br/><br/>This will not be a problem in the next release of the Parts Editor, <br/><br/>这在下一版的元件编辑器中将不再是问题, but for now please modify the file according to the instructions in the link. 但是现在请根据下面的连接来修改文件. no schematics found in %1 在%1中未找到原理图 schematic part 原理图元件 no footprints found in %1 在%1中未找到器件封装 Relocate connector %1 重置接插件%1 &File 文件(&F) Sketch Change Warning 设计改变警告 The open sketch '%1' uses the part you are editing. 打开的设计'%1'使用了你正在编辑的元件。 Saving this part will make a change to the sketch that cannot be undone. 保存这个元件将会对设计产生不能恢复的改变。 The open sketches 打开的设计 '%1', '%1' and '%1' 和'%1' Saving this part will make a change to these sketches that cannot be undone. 保存这个元件将会对这些设计造成改变,使他不能重做。 Go ahead and save? 继续并保存? Save 保存 Cancel 取消 Move terminal point 移动末端的点 Remove connector 移除接插件 Remove %1 connectors 移除%1接插件 Save "%1" 保存 "%1" Do you want to save the changes you made in the part "%1"? 你想保存在元件"%1"中作的改变么? Your changes will be lost if you don't save them. 如果不保存,所做的修改将会丢失. untitled part 无标题元件 Add connector 添加接插件 Add %1 connectors 增加%1接插件 There is one last edit still pending. 最后的编辑还在处理中。 Duplicate 'family' property not allowed 不允许复制'family'的属性 Duplicate 'variant' property not allowed 不允许复制'variant'的属性 Close without saving? 不保存关闭? Close without saving 关闭程序且不保存 Keep working 保持工作 Icon 图标 Metadata 元数据 Remove Internal Connection 移除内部连接 Fritzing (New) Parts Editor Fritzing(新的)元件编辑器 Show Metadata 显示元数据 Show the connector metadata in a list view 在列表视图中显示元数据 Blank not allowed 不允许为空 The value of '%1' can not be blank. '%1'的值不能为空。 Change %1 to %2 把%1转变为%2 Must be unique 必须是唯一的 Variant '%1' is in use. The variant name must be unique. 变量'%1'在使用中。变量名必须是唯一的。 Duplicate problem 复制问题 Unable to load '%1' 不能载入'%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. 出现这个可能是因为从CorelDRAW中导出的SVG文件'%1'没有选择'提示属性'设置. Please re-export the SVG file using that setting, and try loading again. 请使用设置重新导出SVG文件,并在此导入。 Fonts 字体 Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Fritzing当前只支持OCRA和Droid字体--这些已经被替换为字体'%1' Unable to load image file '%1': %2 不能载入图像文件'%1': %2 Remove internal connection from '%1' 移除内部连接从'%1' Internal connections are very messed up. 内部连接太混乱了。 Add internal connection from '%1' to '%2' 增加内部连接从'%1'到'%2' The 'family' property can not be blank. 'family'属性不能为空。 A duplicate 'family' property is not allowed 不允许复制'family'属性 A duplicate 'variant' property is not allowed 不允许复制'variant'属性 This part can not be saved as-is: 这个元件不能被另存为: Do you want to keep working or close without saving? This part has %n unassigned connectors 这个元件有%n个未分配的接插件 across %n views. 交叉%n视图。 Until all connectors are assigned to SVG elements, the part will not work correctly. 直到所有的接插件分配给SVG元素,这个元件才能正确工作。 Layers Reuse breadboard image 重用面包板图像 Reuse the breadboard image in this view 在这个视图中重新使用面包板图像 Reuse schematic image 重新使用原理图 Reuse the schematic image in this view 在这个视图中重新使用原理图像 Reuse PCB image 重用PCB图像 Reuse the PCB image in this view 在这个视图中重新使用PCB图像 Make only this view visible 只让这个视图可见 The part will only be visible in this view and icon view 元件这能在此视图和图标视图中可见 This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. 这个版本的新的元件编辑器不能处理'%1'中分离的copper0和copper1层。 So editing may produce an invalid PCB view image 所已编辑可能导致无效的PCB视图图像 &Export 导出(&E) Change all connectors to %1 转变所有接插件至%1 Unable to parse '%1' 不能解析'%1' Change to %1 转变至%1 Make only %1 view visible 只使%1视图可见 Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. 现在退出元件编辑器是可以的,只要你记得之后完成分配就可以了。 Load image for view... 在视图中载入图像... Open a file to use as the image for this view of the part. 打开一个文件作为此视图中元件的图像。 Save as new part 另存为新元件 Make a copy of the part and save it in the 'My Parts' Bin 复制此元件,并把他保存'my parts'库中 &Edit 编辑(&E) This part has bendable legs. 次元件包含可弯曲的腿。 This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . 这版的元件编辑器不支持编辑可弯曲的腿,腿可能不能在面板板视图中正确的显示。 If you make changes to breadboard view, or change connector metadata, the legs may no longer work. 如果你做面包板视图的转换,或者转换元数据,腿将不再有效了。 You can safely make changes to Schematic or PCB view. 你可以安全的对原理图或PCB视图进行修改。 This warning will not be repeated in this session of Fritzing 这个警告不能在Fritzing这个阶段重复的出现 Unable to load '%1'. Please close the parts editor without saving and try again. 不能载入'%1'。请关闭元件编辑器中未保存部分并重试。 Unable to load image file '%1' 不能载入图像文件'%1' Inspector 指示栏 Unable to load fzp from %1 Unable to create new connector--you may have to start over. Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard PEMetadataView This is where you edit the metadata for the part ... 这里是编辑元件元数据的地方... Set the part's title 设置元件标题 Title 标题 Set the part's date 设置元件日期 Date 日期 Set the part's author 设置元件作者 Author 作者 Set the part's description--you can use simple html (as defined by Qt's Rich Text) 设置元件描述--你可以使用简单的html(Qt富文本定义的内容) Description 描述 Set the default part label prefix 设置默认元件标签前缀 Label 标签 Set the part's family--what other parts is this part related to 设置元件家族--这个元件有关的其他元件 Family 家族 Set the part's properties 设置元件属性 Properties 属性 Set the part's tags 设置元件关键词 Tags 关键词 Set the part's variant--this makes it unique from all other parts in the same family 设置元件的变量--这使它与同一家族其他元件相比是惟一的 Variant 变量 Set the part's url if it is described on a web page 设置元件的url如果它在网页上有描述 URL URL PESvgView width: 宽度: height: 高度: PEToolView Center 中心 N N E E S S W W Connector %1 接插件%1 Set Internal Connections 设置内部连接 Set this checkbox to edit internal connections by drawing wires 选定这个复选框通过画线来便捷内部的连接 Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector 控制接插件端点的设置。端点是线和接插件连接的地方。你也可以拖动当前接插件的十字准线 center 中心 west 西 north south east Sets the connector's terminal point to %1. 设置接插件的端点%1。 Modifies the x-coordinate of the terminal point 修改端点的x坐标 Modifies the y-coordinate of the terminal point 修改端点的y坐标 Dragging disabled 禁止拖拽 <font color='black'>Dragging enabled</font> <font color='black'>允许拖拽</font> <font color='gray'>Dragging disabled</font> <font color='gray'>禁止拖拽</font> Connector List (a checkmark means the graphic was selected) 接插件列表(对号的意思是图像被选中) Select graphic 选择图像 Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. 使用光标定位,鼠标滚轮来指定想要给当前接插件分配的SVG元素,然后按下鼠标来选择它。 Pad shape 形状 center 中心 north east south west 西 connect to 连接至 PaletteItem Edit Pin Labels 编辑针脚标签 Fritzing Fritzing Unable to proceed; unable to find top level view. 不能处理:找不到顶层视图。 Unable to proceed; part connectors do no have standard IDs. 不能处理:元件接插件没有标准的ID。 Label mismatch. Nothing was saved. 标签不匹配。什么都没保存。 hole size 孔径 advanced settings 高级设置 in in mm mm Hole Diameter 内径 Ring Thickness 外径 PartLabel Edit 编辑 Edit label text 编辑标签文字 Display Values 显示值 Flip/Rotate 翻转/旋转 Font Size 字体大小 Rotate the label by 90 degrees clockwise 将标签顺时针旋转90度 Rotate the label by 180 degrees 标签旋转180度 Rotate current selection 90 degrees counter clockwise 将当前选择逆时针旋转90度 Flip Horizontal 水平翻转 Flip label horizontally 水平翻转标签 Flip Vertical 垂直翻转 Flip label vertically 垂直翻转标签 Small Set font size to small 字体设置为小 Medium Set font size to medium 字体设置为中 Large Set font size to large 字体设置为大 Label text 标签文字 Display the text of the label 显示标签的文字 Display the value of property %1 显示属性%1的值 Set label for %1 为%1设置标签 Label text: 标签文字: Hide 隐藏 Hide part label 隐藏元件标志 Rotate the label by 45 degrees clockwise 将标签顺时针旋转45度 Rotate the label by 135 degrees clockwise 将标签顺时针旋转135度 Rotate the label by 135 degrees counter clockwise 逆时针旋转标签135度 Rotate the label by 45 degrees counter clockwise 逆时针旋转标签45度 Tiny 极小 Set font size to tiny 设置字体大小为tiny Rotate 45� Clockwise 顺时针旋转135° {45�?} Rotate 90� Clockwise 顺时针旋转135° {90�?} Rotate 135� Clockwise 顺时针旋转135° {135�?} Rotate 180� 旋转 180° {180�?} Rotate 135� Counter Clockwise 逆时针旋转45° {135�?} Rotate 90� Counter Clockwise 逆时针旋转45° {90�?} Rotate 45� Counter Clockwise 逆时针旋转45° {45�?} PartsBinPaletteWidget Untitled Bin 未命名元件 Save 保存 Specify a file name 指定文件名 Fritzing Bin (*%1) Fritzing元件(*%1) Fritzing Fritzing Cannot find file %1. 找不到文件%1. Cannot read file %1: %2. 不能读取文件 %1: %2. Do you want to save the changes you made in the bin "%1"? 保存对元件"%1"的更改么? Don't Save 不保存 Ctrl+D Ctrl+D Your changes will be lost if you don't save them. 如果不保存,所做的修改将会丢失. Add to bin 添加到元件 Do you really want to add the selected part to the bin? 确定将所选元件加入到元件库中么? Save bin "%1" 保存元件库"%1" Cancel 取消 Loading... 载入中... loading bin '%1' 载入库'%1' Change icon color... 改变图标颜色... Change the color of the icon for this bin. 改变此库图标的颜色. Select a color for this icon 为图标选择颜色 Perfboard size 大小 set board size 设置板大小 rows columns Performance Warning 性能警告 Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. 执行具有多于2000个孔的perfboards and stripboard的会慢。你确定么? 注意:这个警告在此线程中不会被重复。 Set new size 设置新大小 Cancel 取消 PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p><h2>针脚标签编辑器</h2></p> <p>Click on a label next to a pin number to rename that pin. <p>在标签上点击然后选择需要重命名的针脚. You can use the tab key to move through the labels in order.</p> 可以使用tab键在针脚之间按顺序移动.</p> Cancel 取消 Undo 撤销 Redo 恢复 Save 保存 PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Cancel 取消 OK 确定 Language 语言 Colors 颜色 %1 (click to change...) %1 (点击修改...) Connected Highlight 高亮连接的 Unconnected Highlight 高亮未连接的 Mouse Wheel Behavior 鼠标滚轮属性 Command 命令 Control 控制 Change Wheel Behavior 改变滚轮属性 Autosave 自动保存 Autosave every: 自动保存任意: minutes 分钟 no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom 不按键 = 滚动 shift键转换滚动轴 Alt 或 %1 key = 缩放 no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis 不按键 = 缩放 Alt 或 %1 key = 滚动 shift键转换滚动轴 General 通用 Curvy vs. straight wires 弯曲拉直线 Clear Settings 清除设置 When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? 当鼠标按下,拖动线或元件腿(区别于接插件或曲点)你想改变线(或腿)的曲率或者拖一个新的曲点么? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. 复选框设置默认的行为。你可以切换到非默认行为通过在拖动时按下CTRL键(mac:Command key)。 Curvy wires and legs Code View Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 为%1选择一个程序(可执行) ProgramTab Select a program file to load 选择载入一个程序文件 Fritzing is unable to find '%1', please locate it Fritzing找不到'%1',请定位它 New 新建 Save 保存 Remove "%1"? 移除"%1"? Are you sure you want to remove "%1" from the sketch? 确定从程序中移除"%1"? Code (*.%1) While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. Open Platform Board Port Serial Monitor Upload No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow &Edit 编辑(&E) Undo 撤销 Redo 恢复 &Cut 剪切(&C) Cut selection 剪切选择 &Copy 复制(&C) Copy selection 复制选择 &Paste 粘贴(&P) Paste clipboard contents 粘贴剪切板内容 &Select All 全选(&S) Select all text 选择所有文本 File '%1' was restored from the .fzz file; the local copy was not found. 文件'%1'从.fzz文件中恢复了;本地副本没有找到。 File '%1' was restored from the .fzz file; save a local copy to work with an external editor. 文件'%1'从.fzz文件中恢复了;保存了一个本地副本使用外部编辑器编辑。 &Code &View 视图(&V) Code Window Code Window - %1 No boards available &Preferences... 参数设置(&P)... Show the application's about box 显示程序关于对话框 &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller %1%2 %1%2 QObject bb bb Breadboard View 面包板视图 Preferences 参数设置 Please note that a new language setting will not take effect until the next time you run Fritzing. 注意设置一种新语言需要重新启动Fritzing才能生效. Fritzing Fritzing <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> The file '%1' is read-only; please use a different filename. 文件'%1'是只读文件;请使用一个不同的文件名. Edit link 编辑连接 Part 元件 Wire 导线 Cannot read file %1: %2. 不能读取文件 %1: %2. Parse error (1) at line %1, column %2: %3 %4 分析错误(1)在行%1,列%2: %3 %4 The file %1 is not a Fritzing file (2). 文件 %1 不是Fritzing文件(2). The file %1 is not a Fritzing file (4). 文件 %1 不是Fritzing文件(4). The file %1 is not a Fritzing file (3). 文件 %1 不是Fritzing文件(3). No parts found. 没找到元件. Parse error (2) at line %1, column %2: %3 %4 分析错误(2)在行%1,列%2: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. 在'%2'的元件'%1'没有唯一的模块id'%3'. Part already in bin 元件已经在库中 The part that you have just added, is already there, we won't add it again, right? 刚刚添加的原件已经在库中了, 不能再次添加他了,不是吗? a label 标签 a value 参数 PCB View PCB视图 pcb pcb Oops! 哦哦哦! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. 抱歉,交换机制出现了一些问题。 Fritzing仍然在工作,但不能改变元件的属性. schem 图示 Schematic View 原理图视图 %1 %2 %3 %1 %2 %3 %1 Layer %1层 Bring forward 提前 Send backward 推后 Bring to front 带到前面 Split Wire 分割导线 Join Wire 加入导线 Trace wires 引导线 Ratsnest wires 飞线和覆铜预览 Select all %1 全选%1 File Progress... 文件处理... Check for updates 检查更新 icon view 图标视图 breadboard view 面包板视图 schematic view 原理图视图 pcb view pcb视图 Icon 图标 Breadboard 面包板 Parts 元件 Wires 导线 Part Labels 元件标签 Notes 注释 Rulers 标尺 Board Unknown Layer 未知层 Select outdated parts 选择过期元件 files 文件 unable to open %1 不能打开%1 unable to parse %1 不能解析%1 parse failure in %1 解析%1失败 Sorry, Fritzing can't yet handle both pins and pads together (in %1) 对不起,Fritzing还不能处理针脚和焊盘连在一起(in%1) bad pin argument count 错误针脚参数 bad pad argument count 错误焊盘参数 footprint %1 not found in %2 在%2中未找到器件封装%1 unexpected end of file in footprint %1 in file %2 在文件%2中发现器件封装%1的未知文件结尾 unexpected format (1) in %1 from %2 未知格式(1)in %1 from %2 unexpected end of file 不可预料的文件末端 pad missing drill 丢失焊盘钻孔 pad missing attributes 丢失焊盘属性 pad missing position 丢失焊盘位置 pad missing shape 丢失焊盘形状 position missing params 位置丢失参数 drill missing params 钻孔丢失参数 drill offset not implemented 钻孔偏移未实现 drill missing ellipse params 钻孔丢失椭圆参数 attributes missing params 属性丢失参数 Sorry, can't handle pad type %1 对不起,不能处理焊盘类型%1 pad shape missing params 焊盘形状丢失参数 shape delta not implemented 三角形未实现 trapezoidal pads not implemented 梯形焊盘未实现 unable to handle pad shape %1 不能处理焊盘形状%1 failure in svg conversion 1: %1 %2 %3 svg转换失败1:%1 %2 %3 failure in svg conversion 2: %1 %2 %3 svg转换失败2:%1 %2 %3 Copying file %1 正在复制文件%1 File %1 already exists: it won't be overwritten 文件%1已经存在了:它不能够被覆盖 Silkscreen Top 丝印顶层 Silkscreen Top (Part Labels) 丝印顶层(元件标签) Copper Bottom 底层铜箔 Copper Bottom Trace 底层铜箔引导线 Copper Top 顶层铜箔 Copper Top Trace 顶层铜箔引导线 Silkscreen Bottom 丝印底层 Silkscreen Bottom (Part Labels) 丝印底层(元件标签) Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) 对不起,Fritzing还不能处理针脚和焊盘在一起的情况(in %1 in %2) bad layer mask parameter 错误的机械层参数 non-circular holes not implemented 非圆空还未实现 non-copper holes not implemented 非铜孔还未实现 Unable to parse copper: %1 %2 %3 不能解析铜层:%1 %2 %3 Parts folder not found. 未找到元件文件夹. Select %1 选择 %1 pad shape size is invalid 无效的板型尺寸 bad schematic definition %1 错误的原理图定义%1 schematic part %1 not found in %2 在%2中未找到原理图元件%1 schematic %1 unexpectedly ends (1) in %2 %2中原理图%1未预料到的尾部(1) schematic %1 unexpectedly ends (2) in %2 %2中原理图%1未预料到的尾部(2) schematic %1 unexpectedly ends (3) in %2 %2中原理图%1未预料到的尾部(3) Part Image 元件图像 Error reading file %1: %2. 读取文件%1错误:%2. Select locked parts 选择锁定的元件 Basic 基本 Input 输入 Output 输出 ICs IC Power 电源 Connection 连接 Microcontroller 单片机 Tools 工具 Frame 结构 %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 改变%1,%2的针脚 outline is empty 轮廓线是空的 the board outline layer, 板轮廓线层, silkscreen layer(s), 丝印层, copper layer(s), 覆铜层, mask layer(s), 阻焊层, Unable to translate svg curves in %1 不能改变%1中的svg曲线 silk export failure 丝印导出失败 drill export failure 钻孔导出失败 mask export failure mask导出失败 Copper Fill Bottom 底部覆铜 Copper Fill Top 顶部覆铜 Shields 扩展板 LilyPad LilyPad Other 其他 Sensors 传感器 Pin Label Editor 针脚标签编辑器 Ratsnest 预拉线 mm mm in in Cannot write file temp: %1 %2 %3. 不能写临时文件: %1 %2 %3. Cannot autoroute: no board (or multiple boards) found 不能自动旋转:没找到板(或者多个板) Set Ground Fill Seed 设置接地填充种子 Ground Fill Seed Editor 接地填充种子编辑器 %1 mask export failure (2) %1阻焊层导出失败(2) Select all 'Don't autoroute' traces 选择所有'不自动布线'的线 Select all autorouteable traces 选择所有自动布线的线 Set Grid Size 设置网格大小 There is no undo for this action, and no further warning!!!! 这些操作没有恢复,也没有更多的警告!!! Clear Settings 清除设置 No connections (on the PCB) to route. 没有连接(PCB上)用来布线。 No connections to route. 没有连接来布线。 Connected highlight color 连接高亮的颜色 Unconnected highlight color 非连接高亮的颜色 Clear all saved settings and close this dialog immediately. 清除所有保存的设置立即关闭对话框。 This action does not delete any files; it restores settings to their default values. 这个操作不删除任何文件;它恢复他们默认的设置值. Convert to Via 转换为飞线 Convert Via to Bendpoint 转换飞线为曲点 %1 wires moved from their saved position in %2. %1的线从它%2中保存的位置移动。 paste mask layer(s), 粘贴遮盖层, ii ii Icon View 图标视图 <b>id:</b> <b>id:</b> <b>Name:</b> <b>姓名:</b> Set the connectors's title 设置接插件标题 <b>Description:</b> <b>描述:</b> Set the connectors's description 设置接插件描述 Fritzing cannot load the parts bin Fritzing不能载入元件库 Internal Connections 内部连接 Set all to: 设置所有至: Pad Pad <b>type:</b> <b>类型:</b> Part %1 '%2' 元件%1'%2' Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. unable to copy file '%1' to '%2'. Autorouter Settings %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 Text %1 layer export is empty (case 2). silk layer %1 export is empty %2 ... %1 wires moved from their saved position <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> N/A QShortcut Ctrl for naming shortcut keys on menu items Ctrl Alt for naming shortcut keys on menu items Alt Shift for naming shortcut keys on menu items Shift Meta for naming shortcut keys on menu items Meta QuoteDialog For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Order your PCB from Fritzing Fab Price per board Price Copies Visit Fritzing Fab Fritzing Fab Quote The total area of the %n PCB(s) in this sketch is Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: RecoveryDialog &Recover 恢复(&R) &Ignore 忽略(&I) File 文件 Last backup 上一备份 Last saved 上次保存 file not saved 文件未保存 <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> <p><b>Fritzing可能已经崩溃了,但下面文件的一些改变有可能被恢复。</b></p><p>每个文件的备份日期和时间都显示了。如果文件被保存了,日期和时间也将被列出来用于对比。</p><p>如果他们曾经被保存过,原来的文件仍然在你的磁盘上。你可以在载入恢复文件后,选择是否覆盖原来的文件。</p><p><b>从下面的列表中选择你想要恢复的文件。</b></p> Resistor resistance 电阻 Resistor 电阻 You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape 形状 width: %1mm 宽度: %1mm height: %1mm 高度: %1mm width(mm) 宽度(mm) height(mm) 高度(mm) keep aspect ratio 保持宽高比 Revert 恢复 size 大小 custom 自定义 A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width 宽度 S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project 工程 Filename 文件名 Date 日期 Sheet 参数表 Rev 版本 of date 日期 sheet 参数表 shape 形状 SchematicSketchWidget Change voltage from %1 to %2 改变电压从%1至%2 Change label from %1 to %2 改变标签从%1 至 %2 SetColorDialog Make this the default %1 color 设置为默认的%1颜色 Cancel 取消 OK 确定 %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Pick custom %1 color Current color (%1) SketchWidget loading part 载入元件中 done loading 载入完成 %1 %2 %1 %2 %1 %2 items %1 %2元件 Select All 全选 Deselect 取消选择 Add %1 添加%1 Selection 选择 Move %2 (%1) 移动%2 (%1) Move %2 items (%1) 移动%2的项目(%1) Select %1 选择 %1 Select %1 items 选择%1项目 Disconnect 断开 Change 改变 Connect 连接 to %1 至%1 Create and connect wire 创建和连接导线 Rotate %2 (%1) 旋转%2 (%1) Rotate 旋转 Flip 翻转 Double-click 双击 Drag or double-click 拖拽或双击 or alt-drag to move the segment 或者Alt+拖动移动线段 Double-click to delete this bend point 双击删除拐点 Change %1 label to '%2' 改变%1标签为'%2' Change %1 color from %2 to %3 改变%1的颜色从%2至%3 Change color of %1 wires to %2 改变导线%1的颜色为%2 Change %1 width from %2 to %3 改变%1的宽度从%2至%3 Change width of %1 wires to %2 改变导线%1的宽度至%2 Move label '%1' 移动标签 '%1' %1 label '%2' %1标签'%2' Resize Note 恢复注释大小 Disconnect all wires from %1 断开所有自%1的连线 Disconnect all wires from %1 items 断开所有自%1项目的连线 Change Resistance from %1 to %2 改变电阻 %1 为 %2 Change image from %1 to %2 改变图像从%1 至 %2 Change %1 from %2 to %3 改变%1从%2至%3 from %1 从%1 Move leg of 移动脚 Flip %2 (%1) 倒装焊%2 (%1) Change leg curvature for %1. 改变%1的腿的曲率。 Change leg bendpoint for %1. 改变腿%1的拐点。 change pin labels 改变针脚标签 Delete ratsnest 删除覆铜 Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. 看起来像是夸层建立连接线。这种情况不应该产生:请联系开发者。 Create and connect %1 创建并连接%1 wire 线路 trace 导线 Create wire from Ratsnest 从覆铜创建线 Note text change 注意文字的变化 Unrouted connections are highlighted in yellow. 未布线的连接高亮为黄色。 There are no unrouted connections 没有未布线的连接 Unrouted connections 未布线连接 %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. %1 注意:你也可以通过在状态栏中的布线状态文本上按下鼠标触发这个显示。 Deselect all 取消选择所有 Part '%1' not found in sketch Resize board to %1 %2 重置板大小至%1 %2 show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 复位标尺为%1 %2 Add %1 parts test connectors SqliteReferenceModel The swapping mechanism is disabled for: 交换机制被禁止因为: and %1 other parts 和%1其他元件 and %1 other properties 和%1其他属性 property '%1' in part '%2' with id '%3'. id为'%3'的元件'%2'属性'%1'。 part '%1' with id '%2'; possibly because it has no 'family' property. id为'%2'的元件'1%';可能因为没有'family'属性。 Stripboard Restored 恢复 Cut 剪切 %1 %n strip(s) %1 %n 条 rows columns %1 layout SymbolPaletteItem voltage 电压 label 标签 Net labels 网络标签 Net labels cannot be blank 网络标签不能为空 TipsAndTricks Tips and Tricks 提示和技巧 Fritzing Tips and Tricks parts If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. pcb layout Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor examples Get a jump start by looking at the example circuits under File > Examples. Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. TraceWire width 宽度 Select from the dropdown, or type in any value from %1 to %2 从下拉中选择,或者从%1至%2中填入任何值 TranslatorListModel English - %1 英语 - %1 French - %1 法语 - %1 German - %1 德语 - %1 Spanish - %1 西班牙语 - %1 Japanese - %1 日语 - %1 Portuguese (European)- %1 葡萄牙语(欧洲) - %1 Portuguese (Brazilian) - %1 葡萄牙语(巴西) - %1 Hungarian - %1 匈牙利语 - %1 Dutch - %1 荷兰语 - %1 Russian - %1 俄罗斯语 - %1 Italian - %1 意大利语 - %1 Hebrew - %1 以色列语 - %1 Arabic - %1 阿拉伯语 - %1 Hindi - %1 印地语 - %1 Chinese (Simplified) - %1 中文(简体) - %1 Estonian - %1 爱沙尼亚语 - %1 Chinese (Traditional) - %1 中文(繁体) - %1 Polish - %1 波兰语 - %1 Czech - %1 捷克语 - %1 Turkish - %1 土耳其语 - %1 Swedish - %1 瑞典语 - %1 Romanian - %1 罗马尼亚语 - %1 Thai - %1 泰国语 - %1 Greek - %1 希腊文 - %1 Bulgarian - %1 保加利亚语 - %1 Galician - %1 加利西亚语 - %1 Korean - %1 韩语 - %1 Indonesian - %1 印度尼西亚语 - %1 Slovak - %1 斯洛伐克语 - %1 Bengali - %1 孟加拉语 - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Danish - %1 Macedonian - %1 Serbian - %1 Urdu - %1 UpdateDialog Close 关闭 No new versions found. 未找到新版本. A new main release is available for downloading: 新的主release 已经可以下载了: A new interim release is available for downloading: 新的过度发布版已经可以下载了: Checking... 检查中... Sorry, unable to retrieve update info 对不起,不能获得更新信息 WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Fritzing Fab Wire thin (16 mil) 薄(16 mil) standard (24 mil) 标准(24 mil) thick (32 mil) 厚(32 mil) extra thick (48 mil) 特厚(48 mil) blue red black yellow green 绿 grey white orange color 颜色 brown 棕色 purple 紫色 super fine (8 mil) 超细(8mil) extra thin (12 mil) 特细(12mil) Banded pink ochre cyan ZoomSlider % % fritzing-app-0.9.2b/translations/fritzing_zh_tw.qm000066400000000000000000001156301250202676700224420ustar00rootroot00000000000000 $}**0{2W49XR?yJJvgC#L#jL4w'5TZe>eMqNm5E^U,H^WArzBh.k͌SӒ2To O.%U_&WC>DYXqKYYqYZr/lTR#tstPNuT6y9 sS>T_f;AoR;Au\.±9±[a8a["CpqTU[3u_iFMRBi@hWw,rxu sul&|u6 D7bg$osN(V[q?3t'տxfdCgu~mIO?)(n'eY5L{Xxl zbyD;ׅbUw}lɱXII0II NIIsIISI_IcgIcIdIwyF<6dIT$~!~gKٶۘXBS:L>62};vU):g! ;Y{?2BLnO&aVb/#6eeXp qSmV}OFH7,nCTaOXBdcَ4eَhN qV7MgurX-3LQMyRN<_pM_zl#zF5D9+D[L8[LZov@9 ֣ ֣Vޛ|-6m9i'Std-3e;!HEʇk\44cchCi=*kVsNbE u6~4w4i_u?${^s(J AG0?3g[p( ,ιN2I'NeGO;YQ*4b]AfC?nfCof|NigAZi'j!vy,|Ԃw|^"T|^h b1]*Rn[A"3]:Кz% \~ w./ ^ !y 0!Sz+ Ex% Gȧu MgU Se~ lO4 uF ~ .'} NQY r<: ^ l N! .r Jg 81 ՛A {u;L ~l v 2W `* 7n !q8 !qZu #$&I CDZ Ux [>@N ^5j a4| eK{ eR k2-{ k2T~ sul NA ,K ^5 3 3 ; v" vSW 0V 0+1 K} ;'+k c3  P C %4o * *2 ? 8" N> YsI bR g=| i$e Wp P  g> L aJ w qP $r KGz  tX  / w@ L!\ %K  f Rt #& ={D O~u Wj `l3# af: eu eZB r 2 rU? z n`7 z njU "+ , ,_  /# /|d Kg 1# 9a ɠ. ?` 'K0 K n % 3Fq Ae Ae [ E c cv f vCyq #>~ (Z 15] ~Q @' _7  vwK{"(Y#/K*a. a.afT?fTow=)Pi7-nn>5$7jSNxfc=2An!4" ?uC$H&^4-u$/Y/`i,j@L^ipvgU'}$7=p&{Fk|XoT!i~f<b>z _xrHk p GNU GPL v3, QvN֐RrHk p CreativeCommons:BY-SA?GNU GPL v3 on the code and CreativeCommons:BY-SA on the restAboutBoxSmCancelAutorouteProgressDialogP\kbStop NowAutorouteProgressDialogSmCancelAutorouterSettingsDialogx[OKAutorouterSettingsDialogQCN^Bin BinManagerNQCN^{tT::setDirtyTab: q!l\ '%1' vQCN^-pupRՐN;BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty BinManagervRMQCN^N Sf/"zz"QCN^(Cannot set a NULL bin as the current one BinManagerFritzing QCN^j (*%1 *%2);;Fritzing QCN^ (*%1);;Fritzing SRNQCN^ (*%2)NFritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) BinManagereQCN^ (%1) New bin (%1) BinManagerQCNParts BinManager T}T QCN^:!Please choose a name for the bin: BinManager yQQCN^Remove from bin BinManager ydQCN^ Rename bin BinManager"xS։U_v Fritzing jSelect a Fritzing File to Open BinManagerWjImagesBoardxS։ QevWjSelect an image file to loadBoardq!lՏ QeUnable to loadBoardq!l_ %1 %2 QeWjUnable to load image from %1 %2Board QeWjload image fileBoard_brshape BoardLogoItemOrcolorBreadboardLogoItem e(&A)&About ConsoleWindow╋&Quit ConsoleWindown,fu( for debugging DebugDialogydRemove DeleteDialogfvrGj- chip labelDip sW(N S/QeDo not import now FApplicationS/QeImport FApplicationu1 rHg,S/Qe?#Import files from previous version? FApplication k!RfFirst Time HelpFirstTimeHelpDialogܕz(&C) &Close WindowFritzingWindowSmCancelFritzingWindowܕvRMvIWClose the current sketchFritzingWindow$jhH "%1" ]upRՐN f/T&[Xj?>Do you want to save the changes you made in the document "%1"?FritzingWindowN [Xj Don't SaveFritzingWindow[XjSaveFritzingWindow[Xj "%1" Save "%1"FritzingWindow [Xj...Save...FritzingWindow-[jT Specify a file nameFritzingWindowN [Xj b@g upR\1gmY1.1Your changes will be lost if you don't save them.FritzingWindowSmCancelGroundFillSeedDialogx[OKGroundFillSeedDialog (ROH})(autoroutable) HtmlInfoView#cex Connections HtmlInfoView\l`' Properties HtmlInfoViewj-Tags HtmlInfoView_\} %1 Trace wire %1 HtmlInfoViewOH}Wire HtmlInfoView#cR0 %n P QCNconnected to %n item(s) HtmlInfoViewT z1name HtmlInfoView^Wtype HtmlInfoViewQCNPartItemBaseOrcolorItemBase^R%familyItemBasehh<formItemBasegY';maximum resistanceItemBaseYWNpackageItemBasecs pin spacingItemBase[mA rated currentItemBase[R rated powerItemBase[X rated voltageItemBase; resistanceItemBase_brshapeItemBaseY'\sizeItemBase^WtypeItemBaserHg,versionItemBaseXvoltageItemBaseSmCancelKicadModuleDialogx[OKKicadModuleDialogSmCancel LinkDialogx[OK LinkDialogq!l՘oy:Unable to displayLogoItemq!l՘oy: %1 vWjUnable to display image from %1LogoItem_brshapeLogoItem<%1 of %2 }ڍOH}[b - %n P #cVh{I_OH}N-9%1 of %2 nets routed - %n connector(s) still to be routed MainWindow e(&A)&About MainWindowe Qt(&A) &About Qt MainWindow[斛Y'\(&A) &Actual Size MainWindowRQeQCN^ (&A)&Add to bin... MainWindow (&C)&Copy MainWindowRjN (&C)&Cut MainWindowR*d (&D)&Delete MainWindowSmxS (&D) &Deselect MainWindow (&D) &Duplicate MainWindow}/ (&E)&Edit MainWindowS/Q (&E)&Export MainWindowS/Q (&E) &Export... MainWindowjhH (&F)&File MainWindowzT [ (&F)&Fit in Window MainWindowl4^sI (&F)&Flip Horizontal MainWindowWvI(&F)&Flip Vertical MainWindowf (&H)&Help MainWindowb@g \d (&H)&Hide All Layers MainWindow(u1 rHg,S/QeQCNQCN^ (&I)...*&Import parts and bins from old version... MainWindowg\S (&M) &Minimize MainWindowU_{O (&O) &Open Example MainWindowgѕU_vjhH (&O)&Open Recent Files MainWindowU_ (&O)&Open... MainWindowQCN (&P)&Part MainWindowN (&P)&Paste MainWindowUY}-[ (&P)&Preferences... MainWindowRSp (&P) &Print... MainWindow╋&Quit MainWindow[Xj (&S)&Save MainWindowS[Xej (&S)... &Save As... MainWindowQhx (&S) &Select All MainWindowoy:b@g \d (&S)&Show All Layers MainWindowoy:SrH (&S)&Show Breadboard MainWindowoy: PCB (&S) &Show PCB MainWindowoy:iW (&S)&Show Schematic MainWindow oy:QCNj-&Show part label MainWindowj (&V)&View MainWindowz (&W)&Window MainWindow}ڍOr (&W) &Wire Color MainWindowe>Y' (&Z)&Zoom In MainWindow~.\ (&Z) &Zoom Out MainWindow eX_Nf Add Bendpoint MainWindoweX;Add Note MainWindowW(xSv}ڍN eX_Nf$Add a bendpoint to the selected wire MainWindowXR; Add a note MainWindowb@xQCNRQeQCN^Add selected part to bin MainWindowQhAll MainWindowb@g _\g*OH}0$All traces have not yet been routed. MainWindowROH} Autoroute MainWindowROH}...Autorouting... MainWindowSg Breadboard MainWindowTRMNc Bring Forward MainWindow b@xR eb@W(\dvTRMyRNc/Bring selected object(s) forward in their layer MainWindowb@xR neb@W(\dvgRMc0Bring selected object(s) to front of their layer MainWindow negRMcBring to Front MainWindowSmCancel MainWindowb~N R0jhH %1.Cannot find file %1. MainWindowq!lRSpR0 %1Cannot print to %1 MainWindowq!lՋj 1 %1: %2.Cannot read file 1 %1: %2. MainWindowq!l[QejhH %1: %2.Cannot write file %1: %2. MainWindowrHg,fejg...Check for updates... MainWindow" Fritzing erHg,N jgCCheck whether a newer version of Fritzing is available for download MainWindowːxS։S/QveY>Choose a folder for exporting MainWindow}QEXk Copper Fill MainWindow xSS@XJCopy selection MainWindowq!lS_P P\`cR6NCouldn't get the dock widget MainWindow ^zeIWCreate a new sketch MainWindow RjN xSS@XJ Cut selection MainWindowDebugger 8QDebugger Output MainWindowR*dxSDelete selection MainWindowSmxSDeselect MainWindowDisconnect b@g }ڍDisconnect All Wires MainWindow*Disconnect #ckdQCNvb@g }ڍ0Disconnect all wires connected to this connector MainWindow(oy: Fritzing Y}u(vcy:b]+Display some handy Fritzing tips and tricks MainWindowOuYS/QevQCN'Do you want to keep the imported parts? MainWindow x[WLDo you want to proceed anyway? MainWindowxSDuplicate selection MainWindow4N 1000 dpi SVG S/QkcbA^sSvg,QCN7Export 1000 dpi Flattened SVG of this part in this view MainWindow(N 1000 dpi SVG S/Qg,QCN-Export 1000 dpi SVG of this part in this view MainWindowS/Q BOM ...!Export Bill of Materials (BoM)... MainWindowS/Q]rRh...Export Netlist... MainWindowS/QkcbA^sSv SVGExport Normalized Flattened SVG MainWindowS/QkcSv SVGExport Normalized SVG MainWindowS/Q SVG... Export SVG... MainWindow S/Qb@xQCNExport selected part MainWindowS/QIWp SVG Wj)Export the current sketch as an SVG image MainWindowIWS/Qp Eagle CAD&Export the current sketch to Eagle CAD MainWindow"S/QIWvSS@Wp JPG Wj...-Please choose the previous Fritzing folder... MainWindow(W( Fritzing [} v|OHNP \hH&Post a project to the Fritzing website MainWindow RSpvRMjPrint the current view MainWindow RSpN-... Printing... MainWindowWLProceed MainWindowܕz _Quit the application MainWindow cК/MONRaise and Lower MainWindow\1}Ready MainWindowO\Redo MainWindow ydI_NRemove Bendpoint MainWindow yd\dQEXkRemove Copper Fill MainWindow yd\dQEXkRemove copper fill MainWindow yd\dQEXkRemove the copper fill MainWindoweˏIRotate MainWindoweˏI 180 {180?} Rotate 180� MainWindow0fBeˏI 90 {135?} {45?}Rotate 45� Clockwise MainWindow.fBeˏI 90 {45?} {45?}Rotate 45� Counter Clockwise MainWindow0fBeˏI 90 {135?} {90?}Rotate 90� Clockwise MainWindow.fBeˏI 90 {45?} {90?}Rotate 90� Counter Clockwise MainWindow.vRMxS֐R fBeˏI 90 {45 ?}5Rotate current selection 45 degrees counter clockwise MainWindowb@xR fBeˏI 905Rotate current selection 90 degrees counter clockwise MainWindowb@xQCN eˏI 180(Rotate the selected parts by 180 degrees MainWindowb@xQCN fBeˏI 901Rotate the selected parts by 90 degrees clockwise MainWindowOH}[bRouting completed MainWindowSVG Wj(*.svg)SVG Image (*.svg) MainWindow Q2[X %1Save %1 MainWindow*Q2[XQCNnU(BOM)/cnUp[Xe[Wj4Save a Bill of Materials (BoM)/Shopping List as text MainWindowN XML h<_Q2[X]rnUSave a netlist in XML format MainWindowQ2[XIWSave the current sketch MainWindow'%1' ]Q2[X Saved '%1' MainWindowiW Schematic MainWindow xSb@g _Select All Traces MainWindow"xS։U_v Fritzing jSelect a Fritzing File to Open MainWindow Qhxb@g QCNSelect all elements MainWindowxSb@g _}ڍSelect all trace wires MainWindowxSb@g _v}ڍ N ROH}0Select all trace wires excluded from autorouting MainWindowxS֐NfBvQCNSelect outdated parts MainWindowT_Nc Send Backward MainWindow b@xR eb@W(\dvT_yRNc+Send selected object(s) back in their layer MainWindow b@xR eb@W(\dvyR0g_Nc2Send selected object(s) to the back of their layer MainWindow neg_Nc Send to Back MainWindowRNShare MainWindow}N RN...Share online... MainWindowU_R ShellShell launch %1 MainWindowoy:e Qt v\ qzShow Qt's about box MainWindowoy:g,jb@g Su(\d2Show all the available layers for the current view MainWindowoy: PCB jShow the PCB view MainWindowoy:z _e\ qz Show the application's about box MainWindowoy:SrHjShow the breadboard view MainWindowoy:iWjShow the schematic view MainWindowIWS/Q...Sketch exported MainWindowbkISorry! MainWindow"bkI, "%1" \p[bU (Sorry, "%1" has not been implemented yet MainWindow-[jT Specify a file name MainWindow: %1 P QCNfebR0 jgb@g j f/T&u"uRoO\u(SSuccessfully updated %1 part(s). Please check all views for potential side-effects. MainWindowSvgj %1 : '%2' \d YOU^zˁ[vg[PY'\ s`ŊSÀ(eY[xbKQ) <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/. MainWindow\ %1 ncpj!}D %2Swapped %1 with module %2 MainWindowSs\`v Fritzing IWS/Q}f EAGLE OHrߚ Yg`^8u(v EDA ]Qw bPcOfYN T h<_vS/Q ka`TJwbP fka`s{R0This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. MainWindowett}ڍ Tidy Wires MainWindowettxSv}ڍTidy selected wires MainWindowq!l\ %1 S/QbRNh<_ Unable to export %1 as shareable MainWindow %1 q!lS/QbpRN_IW'Unable to export %1 to shareable sketch MainWindowq!lQ2[X %1Unable to save %1 MainWindow_SUndo MainWindow Undokwz  Undo History MainWindowfe{, %1 P QCNUpdate %1 part(s) MainWindowW( jIfB fe `ozUpdate InfoView on hover MainWindowfexSvQCNUpdate selected parts MainWindowXML ]rnUXML Netlist... MainWindowY'Zoom in MainWindow~.\Zoom out MainWindow vc QeQCNdirectly loading parts MainWindow Qe %1 (Sg)loading %1 (breadboard) MainWindow Qe %1 (j!}D)loading %1 (model) MainWindow Qe %1 (PCB)loading %1 (pcb) MainWindow Qe %1 (iW)loading %1 (schematic) MainWindow8q!lՉjhH %10 SVf%2 (/Nx %3)5Couldn't overwrite file '%1'. Reason: %2 (errcode %3) ModelBase [XjY1eWFile save failed! ModelBasefvrGj- chip label MysteryPartj-label MysteryPart[W(kd8Qe;][write your note here]Note dkd#cVhObfQNhe_0-Click this connector to drag out a new trace.PCBSketchWidget8Fritzing /: q!lu"rH[P svg (1)./Fritzing error: unable to render board svg (1).PCBSketchWidget6Fritzing /: q!lu" svg (1).0Fritzing error: unable to render copper svg (1).PCBSketchWidget/g (1) W({, %1 L, {, %2 k: %3 %4,Parse error (1) at line %1, column %2: %3 %4QObject>/g (2) W({, %1 L, {, %2 k: %3 %4,Parse error (2) at line %1, column %2: %3 %4QObjectQCNPartQObjectQCNj- Part LabelsQObjectQCN][XW(eQCN^QgPart already in binQObjectQCNPartsQObject,lafcۊ_ _ŘeU_R_ bMgueHbPlease note that a new language setting will not take effect until the next time you run Fritzing.QObjectUY}-[ PreferencesQObject ]\}Ratsnest wiresQObject\:RulersQObject iWjSchematic ViewQObjectx %1 Select %1QObjectxSQhv %1 Select all %1QObject xS֐NfBQCNSelect outdated partsQObject_Nc Send backwardQObject^bkIbPvncj_R6g UOL0 Fritzing SNKO\ OFkdfB `q!lՋfQCNv\l`'0}Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties.QObjectRRr\} Split WireQObject0jhH %1 N&^ Fritzing j (2).'The file %1 is not a Fritzing file (2).QObject.jhH %1 N&^ Fritzing j (3)'The file %1 is not a Fritzing file (3).QObject.jhH %1 N&^ Fritzing j (4)'The file %1 is not a Fritzing file (4).QObject0jhH '%1' vRMf/U/j!_ Ou(N T jT 0 AboutBox Version %1.%2.%3 <small>(%4%5 %6) %7 [Qt %8]</small> <a href="http://www.fritzing.org">www.fritzing.org</a> <a href="http://www.fritzing.org">www.fritzing.org</a> <b>GNU GPL v3 on the code and CreativeCommons:BY-SA on the rest <b>程式碼版權為 GNU GPL v3, 其他部分版權為 CreativeCommons:BY-SA <b>2007-%1 Fachhochschule Potsdam</b> <b>2007-%1 Fachhochschule Potsdam</b> Fritzing is made by: Prof. Reto Wettach, Andr&eacute; Kn&ouml;rig, Myriel Milicevic, Zach Eveland, Dirk van Oosterbosch, Jonathan Cohen, Marcus Paeschke, Omer Yosha, Travis Robertson, Stefan Hermann, Brendan Howell, Mariano Crowe, Johannes Landstorfer, Jenny Chowdhury, Lionel Michel, Fabian Althaus, Jannis Leidel, Bryant Mairs, Uleshka Asher, and Daniel Tzschentke. Special thanks goes out to: Jussi &Auml;ngeslev&auml;, Massimo Banzi, Ayah Bdeir, Durrell Bishop, David Cuartielles, Fabian Hemmert, Gero Herkenrath, Jeff Hoefs, Tom Hulbert, Tom Igoe, Hans-Peter Kadel, Till Savelkoul, Jan Sieber, Yaniv Steiner, Olaf Val, Michaela Vieser and Julia Werner. Thanks to Kurt Badelt and Miguel Solis for the Spanish translation, to Gianluca Urgese for the Italian translation, to Nuno Pessanha Santos for the Portuguese (European) translation, to Yuelin and Ninjia for the Chinese (Simplified) translation, to Hiroshi Suzuki for the Japanese translation, to Robert Lee for the Chinese (Traditional) translation, to Vladimir Savinov for the Russian translation, to Steven Noppe and Davy Uittenbogerd for the Dutch translation, to Josef Dustira for the Czech translation, to Jinbuhm Kim for the Korean translation, to &#313;ubom&iacute;r Ducho&#328; for the Slovak translation, to Alexander Kaltsas for the Greek translation, to Lionel Michel, Yvan Kloster, Alexandre Dussart, and Roald Baudoux for the French translation, to Cihan Mete Bahad&#x0131;r for the Turkish translation, to Nikolay Stankov for the Bulgarian translation, and to Arthur Zanona, Nuno Pessanha Santos, Leandro Nunes, and Gabriel Ferreira for the Portuguese (Brazilian) translation. Fritzing is made possible with funding from the MWFK Brandenburg, the sponsorship of the Design Department of Bauhaus-University Weimar, IxDS, an anonymous donor, Parallax, Picaxe, Sparkfun, and from each purchase of a Fritzing Starter Kit or a PCB from Fritzing Fab. Special thanks goes out as well to all the students and alpha testers who were brave enough to give Fritzing a test spin. <br /><br /><br /><br /><br /><br /><br /><br /> AutorouteProgressDialog zoom and pan controls Best So Far Cancel 取消 Stop Now 停止 Autorouter Routing canceled! Now cleaning up... AutorouterSettingsDialog Production type homebrew professional custom Keepout <b>Keepout</b> is the minimum distance between copper elements on different nets. A keepout of 0.01 inch (0.254 mm) is a good default. Note: the smaller the keepout, the slower the DRC and Autorouter will run. Trace width Cancel 取消 OK 確定 BinManager Parts 元件 BinManager::setDirtyTab: Couldn't set the bin '%1' as dirty 元件庫管理員::setDirtyTab: 無法將 '%1' 的元件庫設為異動過 BinManager::updateTitle: Couldn't set the bin '%1' as dirty New bin (%1) 開新元件庫 (%1) Select a Fritzing Parts Bin file to open Searching... Bin 元件庫 Import... Load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) New Bin... Create a new parts bin Close Bin Close parts bin Delete Bin Delete parts bin Save Bin Save parts bin Save Bin As... Save parts bin as... Export Bin... Save parts bin in compressed format... Rename Bin... Rename parts bin... Copy to Sketch Copy all the parts in the bin to a sketch Copy all to Sketch Copy all loaded parts to the sketch Show Bin in List View Display parts as a list Show Bin in Icon View Display parts as icons Edit Part (new parts editor)... Export Part... Remove Part Find Part in Sketch Delete bin Do you really want to delete bin '%1'? This action cannot be undone. Read-only bin This bin cannot be renamed. Rename bin 移除元件庫 Please choose a name for the bin: 命名元件庫: Remove from Bin Unable to remove part '%1'--it is in use in a sketch Remove from bin 移出元件庫 Do you really want to remove '%1' from the bin? This operation cannot be undone. Select a Fritzing File to Open 選取要開啟的 Fritzing 檔 Fritzing Files (*%1 *%2 *%3);;Fritzing Part (*%1);;Fritzing Bin (*%2);;Fritzing Shareable Bin (*%3) Fritzing Bin Files (*%1 *%2);;Fritzing Bin (*%1);;Fritzing Shareable Bin (*%2) Fritzing 元件庫檔 (*%1 *%2);;Fritzing 元件庫 (*%1);;Fritzing 可分享元件庫 (*%2) Cannot set a NULL bin as the current one 目前元件庫不可是"空"元件庫 Board A custom board svg typically has one or two silkscreen layers and one board layer. Have a look at the circle_pcb.svg file in your Fritzing installation folder at parts/svg/core/pcb/. one layer (single-sided) two layers (double-sided) image file load image file 載入圖檔 Images 圖檔 Select an image file to load 選取要載入的圖檔 due to an xml problem: %1 line:%2 column:%3 because the xml is not correctly formatted the <board> element contains no shape elements because there are multiple <board> layers because there are multiple <silkscreen> layers because there are multiple <silkscreen0> layers because there is no <board> layer the svg contains no shape elements but the pcb itself will have no silkscreen layer the svg doesn't fit the custom board format <b>The custom shape has been loaded, and you will see the new board shortly.</b><br/><br/> Before actual PCB production we recommend that you test your custom shape by using the 'File > Export for Production > Extended Gerber' option. Check the resulting contour file with a Gerber-viewer application to make sure the shape came out as expected.<br/><br/> The rest of this message concerns 'cutouts'. These are circular or irregularly-shaped holes that you can optionally incorporate into a custom PCB shape.<br/><br/> <b>The custom shape has no cutouts.</b> <b>The custom shape has %n cutouts.</b> <br/>However, the cutouts may not be formatted correctly. <br/><br/>If you intended your custom shape to have cutouts and you did not get the expected result, it is because Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. Unable to load 無法載入 Unable to load image from %1 %2 無法從 %1 %2 載入圖檔 Can load, but The image from %1 can be loaded, but %2 Use the file? BoardLogoItem shape 形狀 BreadboardLogoItem color 顏色 Set text color Select text color Capacitor Select from the dropdown, or type in a %1 value ConnectorItem Add bendpoint Straighten curve Remove bendpoint ConsoleSettings Settings Select Parameters BaudRate: Data bits: Parity: Stop bits: Flow control: Select Serial Port Description: Manufacturer: Serial number: Location: Vendor ID: Product ID: Apply Additional options Local echo Description: %1 Manufacturer: %1 Serial number: %1 Location: %1 Vendor Identifier: %1 Product Identifier: %1 ConsoleWindow Serial Monitor Monitor Tools &About 關於(&A) About program Alt+A About Qt C&onnect Connect to serial port Ctrl+O Ctrl+O &Disconnect Disconnect from serial port Ctrl+D Ctrl+D &Configure Configure serial port Alt+C C&lear Clear data Alt+L &Quit 離開 Ctrl+Q Ctrl+Q Connected to %1 : %2, %3, %4, %5, %6 Error Serial port open error Disconnected About Serial Monitor This terminal displays the serial communication on the selected port, usually between your computer and the connected microcontroller. Critical Error DRC DRC was cancelled. Your sketch is ready for production: there are no connectors or traces that overlap or are too close together. The areas on your board highlighted in red are connectors and traces which may overlap or be too close together. Reposition them and run the DRC again to find more problems Fritzing Fritzing Fritzing error: unable to render board svg. No traces or connectors to check Unexpected SVG rendering failure--contact fritzing.org %1 is overlapping (%2 layer) A hole in %1 may lie outside the border of the board and would be clipped. Connector %1 on %2 should have both copper top and bottom layers, but the svg only specifies one layer. Too close to a border (%1 layer) DRCResultsDialog DRC Results Click on an item in the list to highlight of overlap it refers to. Note: the list items and the red highlighting will not update as you edit your sketch--you must rerun the DRC. The highlighting will disappear when you close this dialog. DebugDialog for debugging 測試用 DeleteDialog Also delete the file Remove 移除 Don't remove Dip chip label 晶片標頭 FApplication Import files from previous version? 由舊版本匯入? Import 匯入 Do not import now 現在不匯入 Fritzing failure Fritzing caught an exception %1 from %2 in event %3 Fritzing caught an exception from %1 in event %2: %3 Fritzing caught an exception from %1 in event %2 Do you want to import parts and bins that you have created with earlier versions of Fritzing? Note: You can import them later using the "Help" > "Import parts and bins from old version..." menu action. Please specify an .fzz file name to save to (cancel will delete the backup) Fritzing (*%1) Fritzing (*%1) FirstTimeHelpDialog First Time Help 首次輔助說明 <br/>The <b>Breadboard View</b> is meant to look like a <i>real-life</i> breadboard prototype.<br/><br/>Begin by dragging a part from the Parts Bin, which is over at the top right. Then pull in more parts, connecting them by placing them on the breadboard or clicking on the connectors and dragging wires. The process is similar to how you would arrange things in the physical world. <br/><br/>After you're finished creating your sketch in the breadboard view, try the other views. You can switch views by clicking the Tabs at the top of the window. Because different views have different purposes, parts will look different in the other views. Welcome to the <b>Schematic View</b><br/><br/>This is a more abstract way to look at components and connections than the Breadboard View. You have the same elements as you have on your breadboard, they just look different. This representation is closer to the traditional diagrams used by engineers.<br/><br/>After you have drawn wires between parts, you can press &lt;Shift&gt;-click with the mouse to create bend points and tidy up your connections. The Schematic View can help you check that you have made the right connections between components. You can also print out your schematic for documentation. The <b>PCB View</b> is where you layout the components will on a physical PCB (Printed Circuit Board).<br/><br/>PCBs can be made at home or in a small lab using DIY etching processes. They also can be sent to professional PCB manufacturing services for more precise fabrication. <br/><table><tr><td>The first thing you will need is a board to place your parts on. There should already be one in your sketch, but if not, drag in the board icon from the Parts Bin. The icon matches thie image to the right: </td><td><img src=":resources/parts/svg/core/icon/rectangle_pcb.svg" /></td></tr></table><br/><br/>To lay out your PCB, arrange all the components so they fit nicely on the board. Then try to shift them around to minimize the length and confusion of connections. You can also resize rectangular boards. <br/><table><tr><td>Once the parts are sorted out, you connect them with copper traces. You can drag out a trace from individual connections or use the autorouter to generate them. The Autoroute button is at the bottom of the window. The button matches the image to the right:</td><td><img src=":resources/images/icons/toolbarAutorouteEnabled_icon.png" /></td></tr></table> FritzingWindow &Close Window 關閉視窗(&C) Ctrl+W Ctrl+W Close the current sketch 關閉目前的草圖 %1 - %2 %1 - %2 Specify a file name 設定檔名 Save "%1" 存檔 "%1" Do you want to save the changes you made in the document "%1"? 檔案 "%1" 已異動過,是否存檔? Save... 存檔... Save 存檔 Don't Save 不存檔 Ctrl+D Ctrl+D Your changes will be lost if you don't save them. 若不存檔,所有異動就會消失. Cancel 取消 GroundFillSeedDialog The difference between a 'ground fill' and plain 'copper fill' is that in a ground fill, the flooded area includes traces and connectors that are connected to 'ground' connectors. Ground connectors are usually labeled 'GND' or 'ground' but sometimes this is not the case. It also may be that there are multiple nets with a ground connector, and you might only want one of the nets to be filled. This dialog collects only connectors labeled 'GND' or 'ground', as well as connectors already chosen as seeds. Click an item to highlight its connections in the sketch. It is also possible to choose a connector as a ground fill seed by right-clicking a connector and choosing the 'Set Ground Fill Seed' context menu option. Cancel 取消 OK 確定 OK and ground fill OK and copper fill Hole hole size HtmlInfoView Connections 連接數 conn. conn. connected to %n item(s) 連接到 %n 個元件 name 名稱 Change the part label here Part breadboard view image Part schematic view image Part pcb view image Part version number Placement pcb layer Locked location rotation degrees type 類型 (autoroutable) (自動佈線) Wire 佈線 Ratsnest wire Trace wire %1 徑跡導線 %1 v. %1 %2 obsolete Properties 屬性 Change the locked state of the part in this view. A locked part can't be moved. Sticky Change the "sticky" state of the part in this view. When a sticky part is moved, objects on top of it also move. Tags 標頭 ItemBase family 類別 type 類型 model size 大小 color 顏色 resistance 電阻 capacitance inductance voltage 電壓 current power pin spacing 接腳間隔 rated power 定電力 rated voltage 定電壓 rated current 定電流 version 版本 package 套件 shape 形狀 form 表格 part number maximum resistance 最大電阻 pins spacing frequency processor variant layers tolerance descr filename title date rev sheet project banded top bottom copper bottom copper top silkscreen bottom silkscreen top Part 元件 model part problem file for %1 %2 not found unable to create renderer for svg %1 KicadModuleDialog Cancel 取消 OK 確定 LayerPalette show all layers LinkDialog url: text: Cancel 取消 OK 確定 LogoItem text shape 形狀 due to a rendering error because the svg is empty because this appears to be a SVG file exported from CorelDRAW without choosing the 'presentation attributes' setting due to an xml problem: %1 line:%2 column:%3 because the file has no root element because the file has no <svg> element for unknown reasons--possibly the image file is corrupted Unable to display 無法顯示 Unable to display image from %1 無法顯示 %1 的圖檔 MainWindow Rotate 旋轉 Share 分享 Flip 翻轉 Autoroute 自動佈線 Both Layers Bottom Layer Top Layer Add a note 增加註解 Ready 就緒 Save %1 儲存 %1 Unable to open '%1': %2 Specify a file name 設定檔名 Fritzing (*%1) Fritzing (*%1) Fritzing Fritzing Unable to export %1 as shareable 無法將 %1 匯出成分享格式 Fritzing Part (*%1) Fritzing 元件(*%1) Unable to export %1 to shareable sketch %1 無法匯出成為分享式草圖 Do you want to keep the imported parts? 保留匯入的元件? No connections to route 無連接線路可佈線 Routing completed 佈線完成 Routing completed using %n jumper part(s) Unrouted connections There are no unrouted connections in this view. %1 of %2 nets routed - %n connector(s) still to be routed %1 of %2 線路佈線完成 - %n 個連接器等待佈線中 Ctrl+R Rotate Clockwise Ctrl+R Alt+Ctrl+R Rotate Clockwise Alt+Ctrl+R Meta+Ctrl+R Rotate Clockwise Shift+Ctrl+R Rotate Counterclockwise Alt+Shift+Ctrl+R Rotate Counterclockwise Meta+Shift+Ctrl+R Rotate Counterclockwise Shift+Ctrl+Tab Toggle Active Layer Click to highlight unconnected parts Fabricate View from Above View from Below Export for PCB No Sketch found in '%1' Unable to open shareable '%1': %2 Unable to open shareable part '%1': %2 Unable to load part from '%1' MainWindow::moveToPartsFolder mainwindow missing There is already a part with id '%1' loaded into Fritzing. %1 - [%2] %1 - [%2] No copper top layer The copper top (copper 1) layer is not available on a one-sided board. Please switch the board to double-sided or choose the copper bottom (copper 0) layer. Sorry! 抱歉! No part with those characteristics. We're working to avoid this message, and only let you choose between properties that do exist 找不到特性完全一樣的元件, 正嘗試避免這訊息,現在只能讓您從現存的屬性中選取 No exactly matching part found; Fritzing chose the closest match. 找不到完全一樣的元件,Fritzing 將選個較接近的。 Change to single layer pcb Change to two layer pcb Swapped %1 with module %2 將 %1 置換為模組 %2 Change image to %2 Svg %1 is missing a '%2' layer. For more information on how to create a custom board shape, see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. Svg檔 %1 還缺 '%2' 層,如何建立自定的板子大小,詳情請參考(教學手冊) <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>. loading %1 Loading... new sketch Schematic conversion Saving this sketch will convert it to the new schematic graphics standard. Go ahead and convert? Backing up '%1' (x,y)=(%1, %2) %3 (x, y)=(%1, %2) (width, height)=(%3, %4) %5 Code Welcome PDF (*.pdf) PDF (*.pdf) PostScript (*.ps) PostScript (*.ps) PNG Image (*.png) PNG 圖檔(*.png) JPEG Image (*.jpg) JPEG 圖檔(*.jpg) SVG Image (*.svg) SVG 圖檔(*.svg) Printing... 列印中... All traces have not yet been routed. 所有徑跡尚未佈線。 Do you want to proceed anyway? 確定要執行? Proceed 執行 Cancel 取消 Sketch exported 草圖匯出... Export... 匯出... Exporting... 正在匯出... Unable to save %1 無法儲存 %1 Cannot print to %1 無法列印到 %1 Cannot write file %1: %2. 無法寫入檔案 %1: %2. Saved '%1' '%1' 已儲存 Select a Fritzing File to Open 選取要開啟的 Fritzing 檔 Cannot find file %1. 找不到檔案 %1. Cannot read file 1 %1: %2. 無法讀檔 1 %1: %2. directly loading parts 直接載入元件 loading %1 (model) 載入 %1 (模組) loading %1 (breadboard) 載入 %1 (麵包板) loading %1 (pcb) 載入 %1 (PCB) loading %1 (schematic) 載入 %1 (概要圖) JPG... PNG... PostScript... PDF... SVG... Eagle... Etchable (PDF)... Etchable (SVG)... New File '%1' not found Ctrl+N Create a new sketch 建立新草圖 &Open... 開啟 (&O) Ctrl+O Ctrl+O BoM Text File (*.html) Your sketch does not have a board yet! Please add a PCB in order to export etchable. Etchable export can only handle one board at a time--please select the board you want to export. &Save 存檔 (&S) Ctrl+S Ctrl+S Save the current sketch 儲存草圖 &Save As... 另存新檔 (&S)... Shift+Ctrl+S Shift+Ctrl+S Share online... 線上分享... Post a project to the Fritzing website 在 Fritzing 官網,發佈一個專案 Export the visible area of the current sketch as a JPG image 匯出草圖的可見區域為 JPG 圖檔 Export the visible area of the current sketch as a PNG image 匯出草圖的可見區域為 PNG 圖檔 Export the visible area of the current sketch as a PostScript image 匯出草圖的可見區域為 PostScript 圖檔 Export the visible area of the current sketch as a PDF image 匯出草圖的可見區域為 PDF 圖檔 Export the current sketch as an SVG image 匯出草圖為 SVG 圖檔 List of parts (&Bill of Materials)... 列出元件清單 (&BOM) Save a Bill of Materials (BoM)/Shopping List as text 儲存元件清單(BOM)/採購清單為存文字檔 XML Netlist... XML 巢狀清單 Save a netlist in XML format 以 XML 格式儲存巢狀清單 SPICE Netlist... Save a netlist in SPICE format Export the current sketch to Eagle CAD 草圖匯出為 Eagle CAD Extended Gerber (RS-274X)... Export the current sketch to Extended Gerber format (RS-274X) for professional PCB production Export the current sketch to PDF for DIY PCB production (photoresist) Export the current sketch to SVG for DIY PCB production (photoresist) &Print... 列印 (&P) Ctrl+P Ctrl+P Print the current view 列印目前檢視 Export SPICE Netlist... Gerber export can only handle one board at a time--please select the board you want to export. Sketch exported to Gerber Shell launch %1 啟動 Shell throw test exception throw a fake exception to see what happens &Quit 離開 Ctrl+Q Ctrl+Q Quit the application 關閉程式 &Open Example 開啟範例 (&O) All 全部 MainWindow::populateMenuWithIndex: couldn't load example with id='%1' MainWindow::populateMenuWithIndex: 無法載入 id='%1' 的範例 &Open Recent Files 最近開啟的檔案 (&O) &%1 %2 &%1 %2 Undo 復原 Redo 重作 &Cut 剪下 (&C) Cut selection 剪下選取區塊 &Copy 複製(&C) Copy selection 複製選取區塊 &Paste 貼上 (&P) Paste clipboard contents 貼上剪貼簿內容 Paste in Place Paste clipboard contents in place &Duplicate 複製 (&D) Ctrl+D Ctrl+D Duplicate selection 複製選取 &Delete 刪除 (&D) Delete selection 刪除選取 Delete Minus Delete selection without attached wires Delete Wire up to bendpoints &Select All 全選 (&S) Select all elements 全選所有元件 &Deselect 取消選取 (&D) Deselect 取消選取 Add Note 新增註解 &Preferences... 喜好設定 (&P) Show the application's about box 顯示程式關於對話視窗 Show/hide the label for the selected parts Show Code Show the code (programming) view &Edit 編輯 (&E) &Add to bin... 加入元件庫 (&A) Add selected part to bin 所選元件加入元件庫 Disconnect All Wires Disconnect 所有線路 Disconnect all wires connected to this connector Disconnect 連接此元件的所有線路 Update InfoView on hover 在鼠標翻轉時,更新訊息視窗 Export Normalized SVG 匯出正規化的 SVG Export 1000 dpi SVG of this part in this view 以 1000 dpi SVG 匯出本元件 Export Normalized Flattened SVG 匯出正規扁平化的 SVG Export 1000 dpi Flattened SVG of this part in this view 以 1000 dpi SVG 匯出正規扁平化的本元件 Lock Part Prevent a part from being moved Select All Locked Parts Select all parts that can't be moved Straighten Curve Straighten the curve of the selected wire Show Parts Bin Icon View Display the parts bin in an icon view Show Parts Bin List View Display the parts bin in a list view Donate to Fritzing Open Fritzing donation web page &Routing Shift+Ctrl+A Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier Autorouter/DRC settings... Set autorouting parameters including keepout... Shift+Ctrl+3 Shift+Ctrl+3 Shift+Ctrl+2 Shift+Ctrl+2 Shift+Ctrl+1 Shift+Ctrl+1 &Create trace from ratsnest Autoroute connections... Create a trace from the ratsnest line &Create wire from ratsnest Create a wire from the ratsnest line Do not autoroute When autorouting, do not rip up this trace wire, via, or jumper item Move to other side of the board Select All Wires Select all wires Select All CopperFill Select all copper fill items Select All "Don't Autoroute" Traces Select All Autoroutable Traces Select all trace wires that can be changed during autorouting Select all jumper item parts Select All Vias Select all via parts Fill empty regions of the copper layer--fill will include all traces connected to a GROUND Fill empty regions of the copper layer--not including traces connected to a GROUND Fill empty regions of the copper layer--fill will include all traces connected to the seeds Shift+Ctrl+D jumpers copperfill vias Do you want to update now? unable to find replacement for %1. Delete Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5) the .fz file format is obsolete The .fz file format has been deprecated. Would you like to convert '%1' to the .fzz format now or open it read-only? The conversion process will not modify '%1'. Convert Read-only Please specify an .fzz file name to save '%1' to Rotate the selected parts by 90 degrees clockwise 所選元件,順時針旋轉 90° Rotate the selected parts by 180 degrees 所選元件,旋轉 180° Rotate current selection 90 degrees counter clockwise 所選部分,逆時針旋轉 90° &Flip Horizontal 水平翻轉 (&F) Flip current selection horizontally 水平翻轉所選部分 &Flip Vertical 垂直翻轉(&F) Flip current selection vertically 垂直翻轉所選部分 Bring to Front 置於最前排 Shift+Ctrl+] Shift+Ctrl+] Bring selected object(s) to front of their layer 所選部分,置於所在層的最前排 Bring Forward 向前一排 Ctrl+] Ctrl+] Bring selected object(s) forward in their layer 所選部分,於所在層的向前移動一排 Send Backward 向後一排 Ctrl+[ Ctrl+[ Send selected object(s) back in their layer 所選部分,於所在層的向後移動一排 Send to Back 置於最後一排 Shift+Ctrl+[ Shift+Ctrl+[ Send selected object(s) to the back of their layer 所選部分,於所在層的移到最後一排 100% (pixel) size Report a bug... &Show All Layers 顯示所有層 (&S) Rotate current selection 45 degrees counter clockwise 目前選取部分,逆時針旋轉 90° {45 ?} Rotate current selection 45 degrees clockwise Revert? This operation can not be undone--you will lose all of your changes. Go ahead and revert? Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz) Revert Reload the sketch &Delete Wire Edit (new parts editor) Open the new parts editor on an existing part Sticky If a "sticky" part is moved, parts on top of it are also moved Show all the available layers for the current view 顯示本檢視所有可用層 &Hide All Layers 隱藏所有層 (&H) Hide all the layers of the current view 隱藏本檢視所有層 &Show part label 顯示元件標頭 Dump all parts Debug dump all parts in this view Align Left Align selected items at the left Align Horizontal Center Align selected items at the horizontal center Align Right Align selected items at the right Align Top Align selected items at the top Align Vertical Center Align selected items at the vertical center Align Bottom Align selected items at the bottom &Export... 匯出 (&E) Export selected part 匯出所選元件 Add Bendpoint 新增彎曲點 Add a bendpoint to the selected wire 在選取的線路上,新增彎曲點 Convert Bendpoint to Via Convert the bendpoint to a via Convert Via to Bendpoint Convert the via to a bendpoint Select outdated parts 選取過時的元件 Update selected parts 更新選取的元件 Find part in sketch... Search for parts in a sketch by matching text Open programming window Open microcontroller programming window Hide part silkscreen Hide/show the silkscreen layer for only this part &Zoom In 放大 (&Z) Ctrl++ Ctrl++ Zoom in 放大 Ctrl+= Ctrl+= &Zoom Out 縮小 (&Z) Ctrl+- Ctrl+- Zoom out 縮小 &Fit in Window 與視窗同寬 (&F) Ctrl+0 Ctrl+0 Fit in window 與視窗同寬 &Actual Size 實際大小(&A) Actual (real world physical) size 100% Size Shift+Ctrl+0 Shift+Ctrl+0 Align to Grid Align items to grid when dragging Show Grid Show the grid Set Grid Size... Set the size of the grid in this view Set Background Color... Set the background color of this view Ctrl+5 Ctrl+5 &Show Welcome Show the welcome view &Show Breadboard 顯示麵包版 (&S) Ctrl+1 Ctrl+1 Show the breadboard view 顯示麵包版檢視 &Show Schematic 顯示概要圖 (&S) Ctrl+2 Ctrl+2 Show the schematic view 顯示概要圖檢視 &Show PCB 顯示 PCB (&S) Ctrl+3 Ctrl+3 Show the PCB view 顯示 PCB 檢視 Ctrl+4 Ctrl+4 &Minimize 最小化 (&M) Ctrl+M Ctrl+M Minimize current window 最小化目前視窗 Debugger Output Debugger 輸出 Online Tutorials 線上教學 Ctrl+? Ctrl+? Open Fritzing help 開啟 Fritzing 輔助說明 Online Projects Gallery 線上專案展覽室 Open Fritzing examples 開啟 Fritzing 範例 Online Parts Reference 線上元件參考說明 Open Parts Reference 開啟元件參考說明 First Time Help 首次輔助說明 Check for updates... 版本更新檢查... Test Connectors Connect all connectors to a single test part Rotate 45� Clockwise 順時針旋轉 90° {135°?} {45�?} Rotate 90� Clockwise 順時針旋轉 90° {135°?} {90�?} Rotate 180� 旋轉 180° {180�?} Rotate 90� Counter Clockwise 逆時針旋轉 90° {45°?} {90�?} Rotate 45� Counter Clockwise 逆時針旋轉 90° {45°?} {45�?} Check whether a newer version of Fritzing is available for download Fritzing 新版本下載檢查 &About 關於(&A) Tips, Tricks and Shortcuts Display some handy Fritzing tips and tricks 顯示 Fritzing 好用的提示與技巧 Display First Time Help &About Qt 關於 Qt(&A) Show Qt's about box 顯示關於 Qt 的對話視窗 Report a but you've found in Fritzing Enable debugging log &Import parts and bins from old version... 由舊版本匯入元件與元件庫 (&I)... Import parts and bins from previous installation 匯入前次安裝的元件與元件庫 Parts Editor Help Display Parts Editor help in a browser &File 檔案 (&F) &Export 匯出 (&E) as Image for Production &Part 元件 (&P) Raise and Lower 提高/降低 Ctrl+Shift+V Align &View 檢視 (&V) &Window 視窗 (&W) Ground Fill &Help 說明 (&H) Move to bottom layer Move to top layer Delete Ratsnest Line Delete Wire Hide part label Show part label Show part silkscreen top and bottom bottom top Ground Fill (%1) Copper Fill (%1) Actual Size It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so 'actual size' as currently implemented is only a guess. Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up. Page Setup 版面設定 Sorry, "%1" has not been implemented yet 抱歉, "%1" 尚為完成喔!! Show unrouted Highlight all unrouted connectors Set Ground Fill Keepout... Set the minimum distance between ground fill and traces or connectors Design Rules Check (DRC) Highlights any parts that are too close together for safe board production Check Loaded Traces Fritzing Fab Quote... How much would it could to produce a PCB from this sketch with Fritzing Fab View from below View the PCB from the bottom layers upwards View from above View the PCB from the top layers downwards Your sketch does not have a board yet! Please add a PCB in order to use the autorouter. Please select the board you want to autoroute. The autorouter can only handle one board at a time. The folder "%1" isn't a Fritzing installation folder Your sketch does not have a board yet! Please add a PCB in order to use ground or copper fill. Please select a PCB--copper fill only works for one board at a time. Your sketch does not have a board yet! Please add a PCB in order to remove copper fill. Please select a PCB--ground fill operations only work on a one board at a time. Schematic view update There is a new graphics standard for schematic-view part images, beginning with version 0.8.6. Would you like to convert '%1' to the new standard now or open the file read-only? The conversion process will not modify '%1', until you save the file. You will have to rearrange parts and connections in schematic view, as the sizes of most part images will have changed. Consider using the Autorouter to clean up traces. Note that any custom parts will not be converted. A tool for converting 'rectangular' schematic images is available in the Parts Editor. Note: if you want to update later, there are options under the 'Part' menu for dealing with outdated parts individually. There are %n outdated part(s) in this sketch. We strongly recommend that you update these %n parts to the latest version. This may result in changes to your sketch, as parts or connectors may be shifted. OK 確定 Set the grid size for %1. Grid Size: in mm Restore Default Your sketch does not have a board yet! DRC only works with a PCB. Please select a PCB. DRC only works on one board at a time. DRC Progress... Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations. Please select a PCB. Copper fill operations only work on one board at a time. %1 background Enter Text Text will match part label, description, title, etc. Enter text to search for: Search No parts matched search term '%1'. Your sketch does not have a board yet! Please add a PCB in order to export to Gerber. 草圖還沒有版子,請先增加一個 PCB 版,才能匯出到 Gerber。 Choose a folder for exporting 請選取要匯出的資料夾 This will soon provide an export of your Fritzing sketch to the EAGLE layout software. If you'd like to have more exports to your favourite EDA tool, please let us know, or contribute. 即要將您的 Fritzing 草圖匯出給 EAGLE 佈署軟體,如果您常用的 EDA 工具,需要我們提供更多不同格式的匯出,歡迎您告知我們,更歡迎您貢獻力量。 Export SVG... 匯出 SVG... Export Bill of Materials (BoM)... 匯出 BOM ... Unable to save BOM file, but the text is on the clipboard. Export Netlist... 匯出巢狀列表... Set both copper layers clickable Set copper top layer clickable Set copper bottom layer clickable Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side) Select All Traces 選取所有徑跡 Select all trace wires 選取所有徑跡線路 Force Update Routing Status and Ratsnests Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly) Select all trace wires excluded from autorouting 選取所有徑跡的線路,不自動佈線 Select All Jumpers Tidy Wires 整理線路 Tidy selected wires 整理選取的線路 Copper Fill 銅線充填 Remove Copper Fill 移除銅層充填 Remove the copper fill 移除銅層充填 Choose Ground Fill Seed(s)... Set Ground Fill Seed Treat this connector and its connections as a 'ground' during ground fill. Clear Ground Fill Seeds Clear ground fill seeds--enable copper fill only. Copper Top and Copper Bottom layers are both active Order a PCB... Order a PCB created from your sketch--from fabulous Fritzing Fab Copper Top layer is active Copper Bottom layer is active Autorouting... 自動佈線... Autorouting Progress... Remove Bendpoint 移除轉彎點 Please choose the previous Fritzing folder... 請選前次安裝 Fritzing 的資料夾... You will have to restart Fritzing in order to use the imported parts 你必須重先開啟 Fritzing ,才能使用這些匯入的元件。 Generating %1 fill... ground copper Remove copper fill 移除銅層充填 &Wire Color 線路顏色 (&W) Launch %1... 啟動 %1... No outdated parts found. All your parts are up-to-date. 沒有發現舊元件! 您目前所使用的都是最新的元件。 Outdated parts 舊元件 Successfully updated %1 part(s). Please check all views for potential side-effects. %1 個元件更新成功。 請檢查所有檢視,是否產生副作用! Update %1 part(s) 更新第 %1 個元件 Inspector 內容 Undo History Undo歷程 Breadboard 麵包板 Schematic 概要圖 PCB PCB Layers Couldn't get the dock widget 無法取得這個停靠控制件 MazeRouter Autorouter was cancelled. best so far: %1 of %2 routed with %n vias round %1 of: Routing stopped! Use best so far... Optimizing traces... Routing complete! Routing unsuccessful; stopping at round %1. Routing reached maximum round %1. Preparing undo... Unexpected SVG rendering failure--contact fritzing.org ModelBase Unable to find the following %n part(s): at File save failed! 存檔失敗! Couldn't overwrite file '%1'. Reason: %2 (errcode %3) 無法覆蓋檔案 %1。 原因說明:%2 (錯誤代碼 %3) MysteryPart label 標頭 chip label 晶片標頭 NetLabel net label Note [write your note here] [在此輸入註解] PCBSketchWidget Create Trace from Ratsnest Click this connector to drag out a new trace. 點擊此連接器來拖曳出一條新徑跡。 Change trace layer Fritzing Fritzing Your sketch does not have a board yet! Please add a PCB in order to use copper fill. 草圖還沒有版子,請先增加一個 PCB 版,才能使用銅層充填。 %1 Fill: please select the board you want to apply fill to. Ground Copper Copper fill: please select only the board you want to fill. Please designate one or more ground fill seeds before doing a ground fill. Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Please click on a PCB first--this selection operation only works for one board at a time. Fritzing error: unable to render board svg (1). Fritzing 錯誤: 無法產製版子 svg (1). Fritzing error: unable to render copper svg (1). Fritzing 錯誤: 無法產製銅 svg (1). Fritzing error: unable to write copper fill (1). Fritzing error: unable to write copper fill (2). Unable to create copper fill--probably the part wasn't dropped onto the PCB. Unable to create copper fill--possibly the part was dropped onto another part or wire rather than the actual PCB. Clear ground fill seeds Your sketch does not have a board yet! Please add a PCB in order to use this selection operation. Unable to convert this via to a bendpoint because it is connected to a part that is only on the bottom layer and another part that is only on the top layer. Show part silkscreen Hide part silkscreen Fritzing Fab Quote Your sketch does not have a board yet. You cannot fabricate this sketch without a PCB part. Sorry, http://fab.fritzing.org is not responding to the quote request. Please check your network connection and/or try again later. Enter Keepout Keepout is in mils (.001 inches). Note that due to aliasing, distances may be too short by up to 2 mils so you may want to increase the keepout value by that much. 10 mils is a good default choice. Enter keepout value: PEConnectorsView This is where you edit the connector metadata for the part number of connectors: Through-hole SMD PEMainWindow Parts Editor 元件編輯器 SVG There is one last edit still pending. Duplicate 'family' property not allowed Duplicate 'variant' property not allowed Close without saving? Close without saving Keep working Exiting the Parts Editor now is fine, as long as you remember to finish the assignments later. Icon 圖示 Metadata Connectors 連接器 Show in Folder On the desktop, open the folder containing the current svg file. Remove Internal Connection Unable to write svg to %1 Unable to parse fzp file %1 Icon View Metadata View Connectors View Show Icon Ctrl+4 Ctrl+4 Show the icon view Ctrl+5 Ctrl+5 Show the metadata view Show Connectors Ctrl+6 Ctrl+6 Change %1 to '%2' Change description Change tags Change properties Change connector %1 Image & Footprint Files (%1 %2 %3 %4 %5);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3);;gEDA Footprint Files (%4);;Kicad Module Files (%5) Image Files (%1 %2 %3);;SVG Files (%1);;JPEG Files (%2);;PNG Files (%3)%4%5 Open Image 開啟圖檔 Copy problem Unable to make a local copy of: '%1' You may use a PNG or JPG image to construct your part, but it is better to use an SVG. PNG and JPG images retain their nature as bitmaps and do not look good when scaled-- so for Fritzing parts it is best to use PNG and JPG only as placeholders. Use of PNG and JPG discouraged Conversion problem Fritzing (New) Parts Editor Show Metadata Show the connector metadata in a list view Blank not allowed The value of '%1' can not be blank. Change %1 to %2 Must be unique Variant '%1' is in use. The variant name must be unique. Duplicate problem Unable to load '%1' The SVG file '%1' appears to have been exported from CorelDRAW without the 'presentation attributes' setting. Please re-export the SVG file using that setting, and try loading again. Fonts Fritzing currently only supports OCRA and Droid fonts--these have been substituted in for the fonts in '%1' Unable to load image file '%1': %2 SVG problem The 'family' property can not be blank. A duplicate 'family' property is not allowed A duplicate 'variant' property is not allowed This part can not be saved as-is: Do you want to keep working or close without saving? This part has %n unassigned connectors across %n views. Until all connectors are assigned to SVG elements, the part will not work correctly. Layers Reuse breadboard image Reuse the breadboard image in this view Reuse schematic image Reuse the schematic image in this view Reuse PCB image Reuse the PCB image in this view Make only this view visible The part will only be visible in this view and icon view This version of the new Parts Editor can not deal with separate copper0 and copper1 layers in '%1'. So editing may produce an invalid PCB view image Unable to parse '%1': %2 line:%3 column:%4 There are no copper layers defined in: %1. See <a href="http://fritzing.org/learning/tutorials/creating-custom-parts/providing-part-graphics/">this explanation</a>. <br/><br/>This will not be a problem in the next release of the Parts Editor, but for now please modify the file according to the instructions in the link. no schematics found in %1 schematic part no footprints found in %1 Relocate connector %1 &File 檔案 (&F) Inspector 內容 Load image for view... Open a file to use as the image for this view of the part. Convert schematic to 0.1 inch standard Convert pre-0.8.6 schematic image to new 0.1 inch standard Save as new part Make a copy of the part and save it in the 'My Parts' Bin &Export 匯出 (&E) &Edit 編輯 (&E) This part has bendable legs. This version of the Parts Editor does not yet support editing bendable legs, and the legs may not be displayed correctly in breadboard view . If you make changes to breadboard view, or change connector metadata, the legs may no longer work. You can safely make changes to Schematic or PCB view. This warning will not be repeated in this session of Fritzing Unable to load '%1'. Please close the parts editor without saving and try again. Unable to load image file '%1' Filename prefix Please enter a prefix to help you identify the part files. The names will have the form 'PREFIX_%1'. (It is not necessary to change the prefix, since a unique suffix is always added.) Sketch Change Warning The open sketch '%1' uses the part you are editing. Saving this part will make a change to the sketch that cannot be undone. The open sketches '%1', and '%1' Saving this part will make a change to these sketches that cannot be undone. Go ahead and save? Save 存檔 Cancel 取消 Move terminal point Remove connector Remove %1 connectors Save "%1" 存檔 "%1" Do you want to save the changes you made in the part "%1"? Your changes will be lost if you don't save them. untitled part Unable to load fzp from %1 Unable to create new connector--you may have to start over. Add connector 新增連接器 Add %1 connectors Remove internal connection from '%1' Change all connectors to %1 Unable to parse '%1' Change to %1 Make only %1 view visible Internal connections are very messed up. Add internal connection from '%1' to '%2' PEMetadataView This is where you edit the metadata for the part ... Set the part's title Title Set the part's date Date Set the part's author Author 作者 Set the part's description--you can use simple html (as defined by Qt's Rich Text) Description 說明 Set the default part label prefix Label 標頭 Set the part's url if it is described on a web page URL Set the part's family--what other parts is this part related to Family Set the part's variant--this makes it unique from all other parts in the same family Variant Set the part's properties Properties 屬性 Set the part's tags Tags 標頭 PESvgView width: height: PEToolView Set Internal Connections Set this checkbox to edit internal connections by drawing wires Connector List (a checkmark means the graphic was selected) Controls for setting the terminal point for a connector. The terminal point is where a wire will attach to the connector. You can also drag the crosshair of the current connector Center N E S W center west north south east Sets the connector's terminal point to %1. Modifies the x-coordinate of the terminal point Modifies the y-coordinate of the terminal point Dragging disabled <font color='black'>Dragging enabled</font> <font color='gray'>Dragging disabled</font> Connector %1 Select graphic Use the cursor location and mouse wheel to navigate to the SVG element which you want to assign to the current connector, then mouse down to select it. Pad shape 形狀 center north east south west connect to PaletteItem Edit Pin Labels Fritzing Fritzing Unable to proceed; unable to find top level view. Unable to proceed; part connectors do no have standard IDs. Label mismatch. Nothing was saved. hole size advanced settings in mm Hole Diameter Ring Thickness PartLabel Edit 編輯 Edit label text 編輯標頭文字 Hide Hide part label Display Values 顯示值 Flip/Rotate 翻轉/旋轉 Font Size 字體大小 Rotate the label by 45 degrees clockwise 標頭順時針旋轉 90° {45 ?} Rotate the label by 90 degrees clockwise 標頭順時針旋轉 90° Rotate the label by 135 degrees clockwise 標頭順時針旋轉 90° {135 ?} Rotate the label by 180 degrees 標頭順時針旋轉 180° Rotate the label by 135 degrees counter clockwise Rotate current selection 90 degrees counter clockwise 目前選取部分,逆時針旋轉 90° Rotate 45� Clockwise 順時針旋轉 90° {135°?} {45�?} Rotate 90� Clockwise 順時針旋轉 90° {135°?} {90�?} Rotate 135� Clockwise 順時針旋轉 90° {135°?} {135�?} Rotate 180� 旋轉 180° {180�?} Rotate 135� Counter Clockwise 逆時針旋轉 90° {45°?} {135�?} Rotate 90� Counter Clockwise 逆時針旋轉 90° {45°?} {90�?} Rotate 45� Counter Clockwise 逆時針旋轉 90° {45°?} {45�?} Rotate the label by 45 degrees counter clockwise Flip Horizontal 水平翻轉 Flip label horizontally 標頭水平翻轉 Flip Vertical 垂直翻轉 Flip label vertically 標頭垂直翻轉 Tiny Set font size to tiny Small Set font size to small 字型設為小 Medium Set font size to medium 字型設為中 Large Set font size to large 字型設為大 Label text 標頭文字 Display the text of the label 選示標頭文字 Display the value of property %1 顯示 %1 的屬性值 Set label for %1 設定 %1 的標頭 Label text: 標頭文字: PartsBinPaletteWidget Untitled Bin 未命名元件庫 Save 存檔 Specify a file name 設定檔名 Fritzing Bin (*%1) Fritzing 元件庫 (*%1) Fritzing Fritzing Cannot find file %1. 無此檔案: %1。 Cannot read file %1: %2. 無法讀取檔案 %1: %2. Loading... loading bin '%1' Change icon color... Change the color of the icon for this bin. Select a color for this icon Do you want to save the changes you made in the bin "%1"? 要儲存在元件庫所做的更動"%1"? Don't Save 無法儲存 Ctrl+D Ctrl+D Your changes will be lost if you don't save them. 如不存檔,所做過的異動將消失。 Save bin "%1" Cancel 取消 Add to bin 加入元件庫 Do you really want to add the selected part to the bin? 確定要將選取的元件加入元件庫? Perfboard size 大小 Performance Warning Performance of perfboards and stripboards with more than approximately 2000 holes can be slow. Are you sure ? Note: this warning will not be repeated during this session. Set new size Cancel 取消 rows columns set board size PinLabelDialog <p><h2>Pin Label Editor</h2></p> <p>Click on a label next to a pin number to rename that pin. You can use the tab key to move through the labels in order.</p> Cancel 取消 Save 存檔 Undo 復原 Redo 重作 PlatformArduino Running %1 %2 PlatformPicaxe Running %1 %2 PrefsDialog Mouse Wheel Behavior Command Control Change Wheel Behavior Cancel 取消 General Code View OK 確定 Autosave Autosave every: minutes Language 語言 Colors 顏色 %1 (click to change...) %1 (按一下變更...) Clear Settings Platform Support <b>%1</b> Location: ... You need to have <a href='%1'>%2</a> (version %3 or newer) installed. Select a programmer (executable) for %1 Connected Highlight 反白連接部分 Unconnected Highlight 反白未連接部分 no keys down = scroll shift key swaps scroll axis Alt or %1 key = zoom no keys down = zoom Alt or %1 key = scroll shift key swaps scroll axis Curvy vs. straight wires When you mouse-down and drag on a wire or the leg of a part (as opposed to a connector or a bendpoint) do you want to change the curvature of the wire (or leg) or drag out a new bendpoint? This checkbox sets the default behavior. You can switch back to the non-default behavior by holding down the Control key (Mac: Command key) when you drag. Curvy wires and legs ProgramTab Select a program file to load While it is possible to read and edit %1 programming files, it is not yet possible to use Fritzing to compile or upload these programs to a microcontroller. New Open Save 存檔 Platform Board Port Serial Monitor Upload Fritzing is unable to find '%1', please locate it Code (*.%1) Remove "%1"? Are you sure you want to remove "%1" from the sketch? No uploader for %1 specified. Go to Preferences > Code View to configure it. Uploader configured, but not found at %1 Upload finished. Upload failed with exit code %1, %2 ProgramWindow No boards available &Edit 編輯 (&E) Undo 復原 Redo 重作 &Cut 剪下 (&C) Cut selection 剪下選取區塊 &Copy 複製(&C) Copy selection 複製選取區塊 &Paste 貼上 (&P) Paste clipboard contents 貼上剪貼簿內容 &Select All 全選 (&S) Select all text &Preferences... 喜好設定 (&P) Show the application's about box 顯示程式關於對話視窗 &Code &New Tab Create a new program tab &Import Code... Alt+Ctrl+I Import a program from a file &Save Tab Alt+Ctrl+S Save the current program tab &Rename Tab Alt+Ctrl+R Alt+Ctrl+R Rename the current program tab Close Tab Alt+Ctrl+W Remove the current program tab from the sketch Platform Board Port Serial Monitor Ctrl+M Ctrl+M Monitor the serial port communication Upload Ctrl+U Upload the current program onto a microcontroller Code Window Code Window - %1 %1%2 %1%2 &View 檢視 (&V) File '%1' was restored from the .fzz file; the local copy was not found. File '%1' was restored from the .fzz file; save a local copy to work with an external editor. QObject Preferences 喜好設定 Please note that a new language setting will not take effect until the next time you run Fritzing. 注意!更換語言後,必須重新啟動後,才會生效! Connected highlight color Unconnected highlight color Clear all saved settings and close this dialog immediately. This action does not delete any files; it restores settings to their default values. There is no undo for this action, and no further warning!!!! Clear Settings Fritzing Fritzing Cannot autoroute: no board (or multiple boards) found No connections (on the PCB) to route. No connections to route. <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>&#169; 2007-%1 Fachhochschule Potsdam</font> <font face='Lucida Grande, Tahoma, Sans Serif' size='2' color='#eaf4ed'>Version %1.%2.%3 (%4%5) %6</font> The file '%1' is read-only; please use a different filename. 檔案 '%1' 目前是唯讀模式,請使用不同檔名。 Edit link 編輯連結 Part 元件 Wire 線路 Set Grid Size Cannot read file %1: %2. 無法讀取檔案 %1: %2. Parse error (1) at line %1, column %2: %3 %4 錯誤解析 (1) 在第 %1 行, 第 %2 欄: %3 %4 The file %1 is not a Fritzing file (2). 檔案 %1 並非 Fritzing 檔 (2). The file %1 is not a Fritzing file (4). 檔案 %1 並非 Fritzing 檔 (4) The file %1 is not a Fritzing file (3). 檔案 %1 並非 Fritzing 檔 (3) Cannot write file temp: %1 %2 %3. Parts folder not found. No parts found. 未發現任何元件。 Parse error (2) at line %1, column %2: %3 %4 錯誤解析 (2) 在第 %1 行, 第 %2 欄: %3 %4 The part '%1' at '%2' does not have a unique module id '%3'. 在 '%2' 的元件 '%1' 並無一個唯一的模組 ID '%3'. Basic Input Output ICs Power Connection Microcontroller Tools Shields LilyPad Other Sensors Part already in bin 元件已存在於元件庫內 The part that you have just added, is already there, we won't add it again, right? 剛新增的元件,已經存在了, 不需要再新增了,對嗎? a label 一個標頭 a value 一個值 Oops! Oops! Sorry, we have a problem with the swapping mechanism. Fritzing still works, but you won't be able to change parts properties. 抱歉!我們的置換機制還有點問題。 Fritzing 還可以運作,但此時,您無法變更元件的屬性。 bb bb Breadboard View 麵包板檢視 PCB View PCB 檢視 pcb pcb Select all 'Don't autoroute' traces Select all autorouteable traces Convert to Via Convert Via to Bendpoint schem 架構圖 Schematic View 概要圖檢視 Error reading file %1: %2. %1 %2,%3 %4 %1 %2,%3 %4 Change leg of %1,%2 %1 %2 %3 %1 %2 %3 %1 Layer %1 層 Bring forward 提前一排 Send backward 後退一排 Bring to front 提到最前排 Split Wire 分割導線 Join Wire 加入導線 Trace wires 徑跡導線 Ratsnest wires 鼠巢導線 Select all %1 選取全部的 %1 Select outdated parts 選取過時元件 Select locked parts File Progress... 檔案處理進度... Check for updates 新版檢查 icon view 圖示檢視 breadboard view 麵包板檢視 schematic view 概要圖檢視 pcb view pcb 檢視 Icon 圖示 Breadboard 麵包板 Parts 元件 Wires 導線 Part Labels 元件標頭 Ratsnest Notes 註解 Rulers 尺規 Frame Text Board Silkscreen Top Silkscreen Top (Part Labels) Copper Fill Bottom Copper Fill Top Copper Bottom Copper Bottom Trace Copper Top Copper Top Trace Silkscreen Bottom Silkscreen Bottom (Part Labels) Part Image Unknown Layer 未知層 files unable to open %1 unable to parse %1 parse failure in %1 Sorry, Fritzing can't yet handle both pins and pads together (in %1) bad pin argument count bad pad argument count Unable to parse copper: %1 %2 %3 footprint %1 not found in %2 unexpected end of file in footprint %1 in file %2 unexpected format (1) in %1 from %2 Sorry, Fritzing can't yet handle both pins and pads together (in %1 in %2) unexpected end of file pad missing drill pad missing attributes pad missing position pad missing shape position missing params drill missing params drill offset not implemented drill missing ellipse params attributes missing params bad layer mask parameter Sorry, can't handle pad type %1 pad shape missing params pad shape size is invalid shape delta not implemented trapezoidal pads not implemented non-circular holes not implemented non-copper holes not implemented unable to handle pad shape %1 failure in svg conversion 1: %1 %2 %3 failure in svg conversion 2: %1 %2 %3 Copying file %1 File %1 already exists: it won't be overwritten Select %1 選 %1 bad schematic definition %1 schematic part %1 not found in %2 schematic %1 unexpectedly ends (1) in %2 schematic %1 unexpectedly ends (2) in %2 schematic %1 unexpectedly ends (3) in %2 outline is empty the board outline layer, silkscreen layer(s), copper layer(s), mask layer(s), paste mask layer(s), Unable to translate svg curves in %1 %1 layer export is empty. exported drill file is empty exported mask layer %1 is empty exported paste mask layer is empty %1 layer: unable to save to '%2' Unable to save pick and place file: %2 silk export failure %1 layer export is empty (case 2). silk layer %1 export is empty drill export failure %1 mask export failure (2) Fritzing is unable to process the cutouts in this custom PCB shape. You may need to reload the shape SVG. Fritzing requires that you make cutouts using a shape 'subtraction' or 'difference' operation in your vector graphics editor. mask export failure Pin Label Editor mm in Set Ground Fill Seed Ground Fill Seed Editor unable to copy file '%1' to '%2'. %2 ... %1 wires moved from their saved position %1 wires moved from their saved position in %2. ii Icon View Internal Connections <b>id:</b> <b>Name:</b> Set the connectors's title <b>type:</b> <b>Description:</b> Set the connectors's description Fritzing cannot load the parts bin Set all to: Pad Part %1 '%2' Autorouter Settings N/A QShortcut Ctrl for naming shortcut keys on menu items Alt for naming shortcut keys on menu items Shift for naming shortcut keys on menu items Meta for naming shortcut keys on menu items QuoteDialog Order your PCB from Fritzing Fab Copies Please note that prices do not include shipping,<br /> possible additional taxes, or the checking fee.<br /> %1 cm%3 (%2 in%3).<br /> Use Fritzing Fab to produce a PCB from your sketch.<br /> Take advantage of our quantity discount: Visit Fritzing Fab The total area of the %n PCB(s) in this sketch is For more information on pricing see <a href='http://fab.fritzing.org/pricing'>http://fab.fritzing.org/pricing</a>. Fritzing Fab Quote Price per board Price RecoveryDialog File Last backup Last saved file not saved <p><b>Fritzing may have crashed, but some of the changes to the following files may be recovered.</b></p><p>The date and time each file was backed-up is displayed. If the file was saved, that date and time is also listed for comparison.</p><p>The original files are still on your disk, if they were ever saved. You can choose whether to overwrite the original file after you load its recovery file.</p><p><b>Select any files you want to recover from the list below.</b></p> &Recover &Ignore Resistor Resistor resistance 電阻 You can either type in a resistance value, or select one from the drop down. Format nnn.dP where P is one of 'umkMG' ResizableBoard shape 形狀 width: %1mm height: %1mm width(mm) 寬(mm) height(mm) 高(mm) keep aspect ratio Revert size 大小 custom A0 (1030x1456) A1 (728x1030) A2 (515x728) A3 (364x515) A4 (257x364) A5 (182x257) A6 (128x182) Letter (8.5x11) Legal (8.5x14) Ledger (17x11) Tabloid (11x17) Ruler width S2S Failed loading '%1', %2 line:%3 col:%4 Schematic not found for '%1' Unable to load schematic '%1' for '%2' Schematic '%1' is already using the 0.1inch standard. Missing connector %1 in '%2' schematic of '%3' Uunable to load schematic '%1' for '%2' Failed loading schematic '%1', %2 line:%3 col:%4 SchematicFrame Project Filename Date Sheet Rev shape 形狀 of date sheet SchematicSketchWidget Change label from %1 to %2 Change voltage from %1 to %2 電壓由 %1 變為 %2 SetColorDialog %1 Color... Choose %1 color: Reset to default Default color (%1) Pick custom color ... Make this the default %1 color 設此顏色為 %1 的預設顏色 Cancel 取消 OK 確定 Pick custom %1 color Current color (%1) SketchWidget loading part 元件載入中 done loading 載入完成 %1 %2 %1 %2 %1 %2 items %1 %2 項 Select All 全選 Deselect 全不選 Add %1 增加 %1 Selection 選取 Move %2 (%1) 移動 %2 (%1) Move %2 items (%1) 移動 %2 項 (%1) Select %1 選 %1 Select %1 items 選 %1 項 Disconnect 斷開 Change 變更 Connect 連接 to %1 到 %1 Create and connect wire 建立並連接導線 Rotate %2 (%1) 旋轉 %2 (%1) Note text change Rotate 旋轉 Flip 翻轉 Double-click 雙擊 Delete ratsnest from %1 Move leg of Change leg curvature for %1. Change leg bendpoint for %1. Fritzing Fritzing This seems like an attempt to create a trace across layers. This circumstance should not arise: please contact the developers. Create and connect %1 wire trace Flip %2 (%1) Drag or double-click 拖曳或雙擊 or alt-drag to move the segment 或按下 Alt 鍵,同時拖曳線段 Double-click to delete this bend point 雙擊,刪除這個轉彎點 Change %1 label to '%2' 改變 %1 標頭為 '%2' Change %1 color from %2 to %3 改變 %1 的顏色,由 %2 變為 %3 Change color of %1 wires to %2 將顏色 %1 的導線變為 %2 Change %1 width from %2 to %3 改變 %1 的寬,由 %2 變為 %3 Change width of %1 wires to %2 將寬 %1 的導線變為 %2 Move label '%1' 移動標頭 '%1' %1 label '%2' %1 標頭 '%2' show %n part label(s) hide %n part label(s) Resize ruler to %1 %2 尺規大小調為 %1 %2 {1 %2?} test connectors Resize Note 大小變更註解 Change Resistance from %1 to %2 電阻由 %1 變為 %2 Change %1 from %2 to %3 Resize board to %1 %2 將板子大小變為 %1 %2 Create wire from Ratsnest Disconnect all wires from %1 %1 的導線全部斷開 Disconnect all wires from %1 items %1 項的導線全部斷開 Change image from %1 to %2 變更圖檔 %1 為 %2 change pin labels Unrouted connections are highlighted in yellow. There are no unrouted connections Unrouted connections %1 Note: you can also trigger this display by mousing down on the routing status text in the status bar. Part '%1' not found in sketch Add %1 parts Deselect all SqliteReferenceModel The swapping mechanism is disabled for: and %1 other parts and %1 other properties property '%1' in part '%2' with id '%3'. part '%1' with id '%2'; possibly because it has no 'family' property. Stripboard Restored Cut %1 %n strip(s) rows columns %1 layout SymbolPaletteItem voltage 電壓 label 標頭 Net labels Net labels cannot be blank TipsAndTricks Fritzing Tips and Tricks Tips and Tricks 提示與技巧 Fritzing stores files for custom parts, generated parts, and for other temporary and long-term purposes in a 'local storage folder'. On Mac and Linux this is usually ~/.config/Fritzing/. Under Windows Vista and above, it is something like C:\Users\[user name]\AppData\Roaming\Fritzing\; under Windows XP is something like C:\Documents and Settings\[user name]\Application Data\Fritzing\. examples Get a jump start by looking at the example circuits under File > Examples. parts Can't find your part? Search for it by clicking the magnifier icon in the Parts Bin and type in some keywords If you can't find a part in the Parts Bin, the Generic IC is your friend. Drag it onto your sketch, then use the widgets in the Inspector to: choose from among 25 different through-hole and SMD packages; change the pin label; and--for DIPs and SIPs--change the number of pins. You can also change the pin names with the Pin Label editor An icon in the parts bin may actually represent multiple related parts. So when you drag an icon from the parts bin into a sketch, make sure you look at the inspector. The inspector will display the range of choices available for you to modify a part, or swap it for a related part. The parts bin icon will also be a little 'stack' and not just a flat icon. The Inspector Window--which lets you change the properties of parts--is only enabled for parts that are in a sketch (not for parts still in a Parts Bin). moving and selection To constrain the motion of a part to horizontal or vertical, hold down the shift key as you drag it. If you're having trouble selecting a part or a wire (segment), try selecting the part that's in the way and send it to the back: use the Raise and Lower functions on the Part menu or the context menu (right-click menu). To more precisely move a selection of parts, use the arrow keys. Shift-arrow moves by 10 units. Click on the mouse position indicator in the status bar (at the bottom) to toggle the units from in to mm to px. rotation To free-rotate a part in Breadboard or PCB view, select it, then hover your mouse near one of the corners until you see the rotate cursor. Mouse down and that corner will follow your mouse as you drag. To free-rotate a logo text or image item in PCB view hold down the Alt (Linux: meta) key and free-rotate as usual. layers and views To drag the canvas, hold down the space bar and drag with the mouse. To toggle the visibility of layer in a view, go to the view menu and choose one of the view layer items. Or open up the <b>Layers</b> palette from the <b>Window</b> menu. When you export images from Fritzing, you can choose which layers are exported. Before you choose 'Export...', go into the 'View' menu and hide the layers you don't want to be visible. part labels To edit a part label, double-click it, or use the text input widget in the inspector window. To display different properties in a part label, as well as rotate it, or change the font, right-click the label. To move a part label independently from its part, select the part first--both the part and the label will be highlighted. Once the label is selected you can drag it. wires and bendpoints To add a bendpoint to a wire, double-click where you want the bendpoint. To delete a bendpoint from a wire, double-click it. In Schematic or PCB view, if you drag from a bendpoint with the Alt (Linux: Meta) key down, you will drag out a new wire from that bendpoint. To drag a wire segment (a section of a wire between two bendpoints), drag it with the Alt (Linux: Meta) key down. If you also hold down the shift key, the wire segment will be constrained to horizontal or vertical motion. Use shift-drag on a wire end or bendpoint to constrain its wire segment to an angle of 45 degrees (or some multiple of 45 degrees). If the wire segment is connected to other wire segments, the segment you're dragging will snap to make 90 degree angles with the neighboring wire segment. connections To see all the connectors connected to a given connector, hold the mouse down on the connector--all the connections will be highlighted. Check out Parts Editor Help under the <b>Help</b> Menu. Before using the Parts Editor, see whether a Generic IC, Mystery Part, or Pin Header will do the job. Once you drop one of these into your sketch, you can change the number of pins, pin spacing, and other properties. In the Parts Editor, to select a graphic underneath another graphic, use the mouse wheel while holding down the shift key. You can use the Parts Editor to find the SVG file for a part's image for a given view. In the Parts Editor, click on the tab for that view, then use <b>Show in Folder</b> under the <b>File</b> Menu Do not store your custom part files in the Fritzing installation folder. If you upgrade Fritzing, these files will probably be deleted. Also, files in the Fritzing installation folder will not be saved in sketch (.fzz) files, so you won't be able to share them. Have your PCB quickly and easily produced with Fritzing Fab. Hover over the 'Fabricate' button to get a quote. When using the Fritzing Fab Service, If there are empty areas of the PCB that you do not want filled with copper, use the copper-blocker part. This resizable part will mask out copper fill in the rectangle it covers. notes To insert a clickable URL into a note, select some text in the note and type ctrl-l (Mac: command-l). (That's 'l' as in the first letter of 'link'.) To modify an existing link select the linked text and use ctrl-l (command-l) again. local file storage pcb layout curves and bendable legs In Breadboard view, to drag a part with bendable legs while keeping it connected to the breadboard, hold the Alt (Linux: Meta) key down when you start dragging. In Breadboard view, to drag out a wire from the end of a bendable leg, drag with the Alt (Linux: Meta) key down. In Breadboard or PCB view, to add a curve to a wire or bendable leg, drag with the Control (Mac: Command) key down. You can set whether curvy wires are the default in Preferences. Always lead a trace straight out of a pin. This helps to prevent short circuits. Through-hole parts can be traced from either side of a PCB. It makes life easier to route traces horizontally on one side of a PCB and vertically on the other side. Route traces in 45-degree angles to reduce noise. If Fritzing is missing your special part and you don't want to build one by yourself, then use pinheaders as connectors and the grid to align them. You can put your own Logo in the silkscreen of your PCB. Just use the Logo part of the core library and select your own file. SVG is the best format. To create a custom shape for your PCB, import an SVG file. To make a stylish Arduino shield in no time, switch the shape of the PCB from a rectangle to the Arduino pcb production Smaller PCBs are more affortable than larger ones. Save space and money. Use copper-blocker parts to mask out areas that you want free of copper fill. A ratsnest line (very thin 'wire') between connections in one view means that those connections are somehow connected in another view. To change trace width, select a trace then use the <b>width</b> combo box in the Inspector. You can use the drop-down or just type in a number (from 8 to 128). parts editor TraceWire Select from the dropdown, or type in any value from %1 to %2 width TranslatorListModel English - %1 英文 - %1 French - %1 法文 - %1 German - %1 德文 - %1 Spanish - %1 西班牙文 - %1 Japanese - %1 日文 - %1 Portuguese (European)- %1 葡萄牙文(歐洲) - %1 Portuguese (Brazilian) - %1 葡萄牙文(巴西) - %1 Hungarian - %1 匈牙利文 - %1 Estonian - %1 愛沙尼亞文 - %1 Dutch - %1 荷蘭文 - %1 Danish - %1 Russian - %1 俄文 - %1 Persian - %1 Slovenian - %1 Marathi - %1 Ukrainian - %1 Macedonian - %1 Serbian - %1 Urdu - %1 Italian - %1 義大利文 - %1 Hebrew - %1 希伯來文 - %1 Arabic - %1 阿拉伯文 - %1 Hindi - %1 印度文 - %1 Chinese (Simplified) - %1 簡體中文 - %1 Chinese (Traditional) - %1 Polish - %1 Czech - %1 Turkish - %1 Swedish - %1 Romanian - %1 Thai - %1 Greek - %1 Bulgarian - %1 Galician - %1 Korean - %1 Indonesian - %1 Slovak - %1 Bengali - %1 UpdateDialog Close 關閉 No new versions found. 已經是新版本。 A new main release is available for downloading: 有大改版本可供下載: A new interim release is available for downloading: 有小改版本可供下載: Checking... 檢查中... Sorry, unable to retrieve update info 抱歉!無法取得更新的訊息 WelcomeView Recent Sketches New Sketch Open Sketch Fab Shop Fritzing CreatorKit The Fritzing Creator Kit provides a fast, easy and entertaining introduction to the world of interactive electronics. order now >> Get your Creator Kit now. Fritzing Fab Fritzing Fab is an easy and affordable service for producing professional PCBs from your Fritzing sketches. produce your first pcb now >> Order your PCB now. <a href='%1'><img src='%2'/></a> Projects Blog Fritzing News. Fritzing Projects. <a href='%1'><img src='%2' /></a> No recent sketches found Unable to reach blog.fritzing.org Unable to reach friting.org/projects Tip of the Day: All Tips Next Tip Wire super fine (8 mil) extra thin (12 mil) thin (16 mil) 薄 (16mil) standard (24 mil) 標準 (24 mil) thick (32 mil) 厚 (32 mil) extra thick (48 mil) 超厚 (48 mil) blue 藍色 red 紅色 black 黑色 yellow 黃色 green 綠色 grey 灰色 white 白色 orange 橘色 ochre cyan brown purple pink color 顏色 Banded ZoomSlider % fritzing-app-0.9.2b/translations/syntax/000077500000000000000000000000001250202676700203545ustar00rootroot00000000000000fritzing-app-0.9.2b/translations/syntax/arduino.xml000066400000000000000000000274411250202676700225470ustar00rootroot00000000000000 break case continue default do else enum extern for goto if inline return sizeof struct switch typedef union while boolean byte char class double false float int long new null private protected public short signed static this throw try true unsigned void word abs acos asin atan atan2 ceil constrain cos degrees exp floor log map max min radians random randomSeed round sin sq sqrt tan bitRead bitWrite bitSet bitClear bit highByte lowByte analogReference analogRead analogWrite attachInterrupt detachInterrupt delay delayMicroseconds digitalWrite digitalRead interrupts millis micros noInterrupts noTone pinMode pulseIn shiftOut tone Serial Serial1 Serial2 Serial3 begin end read print println available flush setup loop HIGH LOW INPUT OUTPUT DEC BIN HEX OCT BYTE PI HALF_PI TWO_PI LSBFIRST MSBFIRST CHANGE FALLING RISING DEFAULT EXTERNAL INTERAL auto char const double float int long register restrict short signed static unsigned void volatile int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t wchar_t _Imaginary _Complex _Bool fritzing-app-0.9.2b/translations/syntax/picaxe.xml000066400000000000000000000643521250202676700223610ustar00rootroot00000000000000 #com #define #endrem #error #freq #gosubs #ifdef #ifndef #include #no_data #no_table #picaxe #picaxe08 #picaxe08m #picaxe08m2 #picaxe14m #picaxe14m2 #picaxe18 #picaxe18a #picaxe18m #picaxe18m2 #picaxe18x #picaxe20m #picaxe20m2 #picaxe20x2 #picaxe28 #picaxe28a #picaxe28x #picaxe28x1 #picaxe28x2 #picaxe40x #picaxe40x1 #picaxe40x2 #rem #sim #simspeed #slot #terminal #undefine backward bcdtoascii bcdtobin bintoascii bintobcd booti2c branch button calibadc calibadc10 calibfreq case clearbit compsetup count dacsetup data debug dec disablebod disconnect do doze eeprom else elseif enablebod end endif endselect exit for forward get gosub goto halt hi2cin hi2cout hi2csetup hibernate high hintsetup hpwm hpwmduty hpwmout hserin hserout hsersetup hshin hshout hspiin hspiout hspisetup i2cmaster i2cread i2cslave i2cwrite if inc infrain infrain2 infraout input irin irout kbin kbled keyin keyled let lookdown lookup loop low nap next off on output owin owout pause pauseus peek peeksfr play poke pokesfr porta portb portc portd pot pullup pulsin pulsout put pwm pwmduty pwmout random read readadc readadc10 readdac readdac10 readfirmware readi2c readmem readoutputs readowclk readowsn readpinsc readportc readrevision readsilicon readtable readtemp readtemp12 reconnect reset resetowclk restart resume return reverse run select sensor serin serout serrxd sertxd servo servopos setbit setfreq setint setintflags settimer shiftin shiftout shin shout sleep sound spiin spiout srlatch srreset srset step stop suspend swap switch switchoff switchon symbol table then tmr3setup to toggle togglebit touch tune uniin uniout until vartoascii wait while word write writei2c writemem and andnot atan bit clear cos dcd dig inv is max min mod nand ncd nob nor not or ornot rev set sin sqr xnor xor xornot a b c d b300_4 b300_8 b300_16 b300_20 b300_32 b300_40 b300_64 b600_4 b600_8 b600_16 b600_20 b600_32 b600_40 b600_64 b1200_4 b1200_8 b1200_16 b1200_20 b1200_32 b1200_40 b1200_64 b2400_4 b2400_8 b2400_16 b2400_20 b2400_32 b2400_40 b2400_64 b4800_4 b4800_8 b4800_16 b4800_20 b4800_32 b4800_40 b4800_64 b9600_4 b9600_8 b9600_16 b9600_20 b9600_32 b9600_40 b9600_64 b14400_4 b14400_8 b14400_16 b14400_20 b14400_32 b14400_40 b14400_64 b19200_4 b19200_8 b19200_16 b19200_20 b19200_32 b19200_40 b19200_64 b28800_4 b28800_8 b28800_16 b28800_20 b28800_32 b28800_40 b28800_64 b31250_4 b31250_8 b31250_16 b31250_20 b31250_32 b31250_40 b31250_64 b38400_4 b38400_8 b38400_16 b38400_20 b38400_32 b38400_40 b38400_64 b57600_4 b57600_8 b57600_16 b57600_20 b57600_32 b57600_40 b57600_64 b76800_4 b76800_8 b76800_16 b76800_20 b76800_32 b76800_40 b76800_64 b115200_4 b115200_8 b115200_16 b115200_20 b115200_32 b115200_40 b115200_64 cls cr em4 em8 em16 em20 em32 em40 em64 i2cbyte i2cword i2cfast i2cfast4 i2cfast8 i2cfast16 i2cfast20 i2cfast32 i2cfast40 i2cfast64 i2cfast_4 i2cfast_8 i2cfast_16 i2cfast_20 i2cfast_32 i2cfast_40 i2cfast_64 i2cslow i2cslow4 i2cslow8 i2cslow16 i2cslow20 i2cslow32 i2cslow40 i2cslow64 i2cslow_4 i2cslow_8 i2cslow_16 i2cslow_20 i2cslow_32 i2cslow_40 i2cslow_64 k31 k125 k250 k500 lf lsbfirst lsbfirst_h lsbfirst_l lsbpost lsbpost_h lsbpost_l lsbpre lsbpre_h lsbpre_l msbfirst_h msbfirst_l msbfirst msbpost msbpost_h msbpost_l msbpre msbpre_h msbpre_l m1 m2 m4 m8 m16 m32 m64 n300 n300_4 n600 n600_4 n600_8 n1200 n1200_4 n1200_8 n2400 n2400_4 n2400_8 n2400_16 n4800 n4800_4 n4800_8 n4800_16 n4800_32 n9600 n9600_8 n9600_16 n9600_32 n9600_64 n19200 n19200_16 n19200_32 n19200_64 n38400 n38400_32 n38400_64 n76800 n76800_64 output0 output1 output2 output3 output4 output5 output6 output7 ownoreset ownoreset_bit owresetafter owresetafter_bit owresetbefore owresetbefore_bit owresetboth owresetboth_bit owresetfirst owresetfirst_bit pwmdiv4 pwmdiv16 pwmdiv64 pwmfull_f pwmfull_r pwmhalf pwmsingle pwmhhhh pwmhlhl pwmlhlh pwmllll spifast spimedium spislow spimode00 spimode00e spimode01 spimode01e spimode10 spimode10e spimode11 spimode11e t1s_4 t1s_8 t1s_16 t1s_20 t1s_32 t1s_40 t1s_64 t300 t300_4 t600 t600_4 t600_8 t1200 t1200_4 t1200_8 t2400 t2400_4 t2400_8 t2400_16 t4800 t4800_4 t4800_8 t4800_16 t4800_32 t9600 t9600_8 t9600_16 t9600_32 t9600_64 t19200 t19200_16 t19200_32 t19200_64 t38400 t38400_32 t38400_64 t76800 t76800_64 uni_crrd uni_eral uni_rdsr uni_read uni_setal uni_wren uni_wrdi uni_write uni_wrsr adcsetup b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24 b25 b26 b27 b28 b29 b30 b31 b32 b33 b34 b35 b36 b37 b38 b39 b40 b41 b42 b43 b44 b45 b46 b47 b48 b49 b50 b51 b52 b53 b54 b55 bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8 bit9 bit10 bit11 bit12 bit13 bit14 bit15 bit16 bit17 bit18 bit19 bit20 bit21 bit22 bit23 bit24 bit25 bit26 bit27 bit28 bit29 bit30 bit31 bptr bptr0 bptr1 bptr2 bptr3 bptr4 bptr5 bptr6 bptr7 compflag compvalue dir0 dir1 dir2 dir3 dir4 dir5 dir6 dir7 dira dirb dirc dird dirs dirsa dirsc dirsd flag0 flag1 flag2 flag3 flag4 flag5 flag6 flag7 flag8 flag9 flag10 flag11 flag12 flag13 flag14 flag15 flags flagsh flagsl hi2cflag hi2clast hint0flag hint1flag hint2flag hintflag hserflag hserinflag hserinptr hserptr infra input0 input1 input2 input3 input4 input5 input6 input7 keyvalue outpin0 outpin1 outpin2 outpin3 outpin4 outpin5 outpin6 outpin7 outpina outpinb outpinc outpind outpins outpinsa outpinsc outpinsd pin0 pin1 pin2 pin3 pin4 pin5 pin6 pin7 pina pinb pinc pind pins pinsa pinsc pinsd port ptr ptr0 ptr1 ptr2 ptr3 ptr4 ptr5 ptr6 ptr7 ptr8 ptr9 ptr10 ptr11 ptr12 ptr13 ptr14 ptr15 ptrh ptrl s_w0 s_w1 s_w2 s_w3 s_w4 s_w5 s_w6 s_w7 timer timer3 toflag trisc w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15 w16 w17 w18 w19 w20 w21 w22 w23 w24 w25 w26 w27 Integer Long Single Double String Byte PTR Dword PTR Qword PTR Word PTR fritzing-app-0.9.2b/translations/syntax/styles.xml000066400000000000000000000017561250202676700224320ustar00rootroot00000000000000

    fritzing-app-0.9.2b/resources/templates/perfboard_connectorTemplate.txt000066400000000000000000000001741250202676700265720ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/perfboard_fzpTemplate.txt000066400000000000000000000025301250202676700253750ustar00rootroot00000000000000 4 JC basic single-sided perfboard 2011-06-02 Perfboard Prototyping Board Perfboard %1.%2 prototyping.perfboard.perfboard A perfboard for easily prototyping circuits %3 fritzing-app-0.9.2b/resources/templates/schematic_frame_template.txt000066400000000000000000000050111250202676700260600ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/screw_terminal_bread_template.txt000066400000000000000000000070641250202676700271330ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/templates/screw_terminal_fzpTemplate.txt000066400000000000000000000030031250202676700264430ustar00rootroot00000000000000 4 Lionel Michel Screw terminal - %1 pins 2009-10-23 fritzing core Screw Terminal %1 .percent.2 .percent.3 THT Screw terminal with %1 pins %2 fritzing-app-0.9.2b/resources/templates/stripboards.xml000066400000000000000000000073521250202676700234020ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/vias.xml000066400000000000000000000032761250202676700200130ustar00rootroot00000000000000 fritzing-app-0.9.2b/resources/zoomfactors.txt000066400000000000000000000002641250202676700214300ustar00rootroot000000000000006.25 8.3 12.5 16.6 25 33.3 50 66.6 100 150 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 fritzing-app-0.9.2b/sketches/000077500000000000000000000000001250202676700161165ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/000077500000000000000000000000001250202676700170465ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/555TouchSwitch.fzz000066400000000000000000000441411250202676700223100ustar00rootroot00000000000000PK8Dk+G}555TouchSwitch.fz}F1wd۶v̒`(zL*;nZ?2&YY>Ծ>F@d@3%WxƝl>N 'hrů|5wӫwaz6Z|dW$mBhDB^ˋh$ {e|;ϮrO]h2xw~;.:bR.WflW:QԂz"ۙ+kDژ4o"J+J5~KP\Ӈ&W۾]_:COzظzLgoKL?_z =Z9oUqpV ˭ն[ wcCIXtLH/:0xB%˯PucvOKJ{]?zձҠ=N{lJX}5e[6 _z͆黙El1G}o/ޢn4p6 Dڇ@>>04M@`Dgfo{e/v}a1;w/g]<TP `o vd}Q(OlpIfYN8n.pV<1là/mR.Nnd8Y|,sڰjBf[Wo"5WRej)QAUzz6R|X]{-vEkX"ԛ'_Hn (Tc&'KH춨T'Q"!J8T4"Fi# 2GWXU2]#}b[ пmǂ]ernb3OU+(2'-sʾl+\eZz8P͹ɜTЂ3^ߵZUsnY)Bvx+8Z'vxo7Cj+1J[;Ahdmqn)['v*lw;s9,`\U4t/Nn_EN曕^Uu߇l3u"tk|n_J+q%(m;d匟_}Pm>jy8[0yUn–8?<(=C#'g/v{Ѭ&'?'l}ۜt0x R甅g>)@\%~3P{(Ns*{4Є}~5~ FXr3x{'7&vMAbI#s;5=)D>)MwML ݦrdZK ݚcRVg-(Uµg>])@>JJ*( &*({R?)JAJ J5;;g'=kwOD-69i#na3 ]|R2?IJA̧)bD}~|@FrޓyQ|t`','v)K"Ju;&-=m)L?Kx掩KቻFs0弪Z4< LyOa S{Sx*nGe4nc"Sp>Lቻڽc2S3)[Bg>)H?iMA'6) 6){zS"? Nʼ)N;;'9f2`w{Md0,G7p eqUEo6Oy?[mg{{qr~}\ܽX9cUڂOmcqIiե&QhP5ij ʇi`tDb؋s~;̯i|XhlOf,aªxj]thabG۾6z;4npjnQh`hx„P[~ڽd6uy`?Ja7H)^uj;`ƫMj5Qi YuJt UI5j J;P4M وn[%o]H*z@{È`sW>!a:8O8LAѪ : #xTzhC!v(w> 鬚|_ټOz׳hrSq k6vϦ;оA=E?~7tF&߮+g0/7k|~%Wz/gRq)]^d˦m3 ̓tv׹2awex7;~ǝHb'w'o^sG! ɜ,|<n1`W!wԼ.>5leosAns{[M  )Km£eIjRQfP#2Ҹk5Iځ6׉sf!,x1?Х} +,5]dlٻap"P;cj\_χ wZFr;~XEz:Yu6˺{CG,=BaY cc7H/Km-hn!Q6Qz|qʐRCJ!RLBX,ZJ5Rb}GXlW&DSr*ˆ N9;shp\W -6צmjU> h0ȌeiXkIcyMh3 t;`2sC 2ƛ7 &ZYV7x-|`D=-] ;o:ޓȢϧ:}bԸĘ#!zǎ9M{}1[s cڑI^ #Q*$.0"lC.DЬ!ZW :7/9' ~G^h7Ot] 3k3wM~ ̓yb:JM+ǦϬ0$Ę3Debq&.,~V>1f,`Lirq HReiD0|e1F\Lr0C %qRZ!cͪIN\֪N.Atp4aO*iF'Z k[\cK6O]$u6a`fe vf9Wc Z1Nbd#= SQ>z۷Rr n\!r' 4ܯԳz:)\+xjs4e[}ڵTN8 #Xo  j}m>BRãJ>eT4 2fE6Bu&Ÿ.Έ$U޻$|qG.Leo 0L7$εou?6$OXRnxkѤ96hFTPqr6`Bʘ5\/D7OD#Z 6$F,i[&1PnbxJ2. 0وR*qK+!{]8)TsPSI< ع[N?1~nx9DnNddJ2DRdSφH") 4BIb0iJv NJIÜMUI#o[csQʘF7OC|~&u0m85GP_TG`qC.-BFadGχDj㠴 4Hb$i, (fE]HJVx]imCC7I ޷Eޔ뢟/6 l6G$G6|g{Q6ɚ@#I-&G!ae"F%| 4 KIRi(9& *m [ wbωP eI<(C.NzD!=n/xyZĐv (Q3G>^N n(bUΪOZ24CG)7}\!a>=%q!ͽy3ySZįxzd\:0$f #lHm1 <4BIb0i zUADP`Nz3yK?U"RfJ '\F.7Obbn_*`(_w!ؘb"IhD8R IJ%Icdԅ@F.^YBڭWF.*e/!lMS(-Txb(]GN7O, Kn'e8)΂Zd)C(~PhĐM>6^!$"x{atz;~q⍄Jz2ɭZr~_ÅH7r?MbbaʻH.:⯣O JF{+~>o#K׶/(H (ӏJ/ oOY霄l-=7O9;hή8ݧ7^4X&lqԔi)! c32M I!1?{}}m6G=z|$ڻ.PA{0LQb%TT: J" wؘ}1QdW##/d4-A"ˀA(8r:bUj0PwM%Nj뿼?}_w~?曆ϻ^_ƣ"!7ƣE=O/?~Uvq77_FErx_e/w˶; ?-oN({{x]. =Gy;Z s ٰ~ֿ6=Ec@d{ݷg_Ϧ_g|i"N|?.^B^/&]nߗnFbz.ӻҮzQ1?ݷ*O{Ҳk܎ g?v搀 FZ33ά/:?q8O߃ ̇񼳰G=tt~M:Z6`xN@ G>3ޝߎӧgm`o@ 2s ۋ^)Ozt-8-ԏw8HU=w8!(%a&D 3H]6f?Di-(ޜ&Cd[ ĵ\ڊ]Uysst0+zOvX`٦ & ;@bf-tO5ܨ6.XA^Ru$˅LJOܱg˹G5H>EzB̅,T2a7 b7FWQ-ij1Zݛ8k6ޖ6.[" VD AˉҔyĹ H&)L )U}j$qG$qqEM%F]t-4enIL[Hܭ1#wQ:4iDYQ%ٲ6\Mr! rDՈ{:M3 FrîB0$߁J [EV3juL.u 9)y8Jj, % U#UG<+\bopHBA@1Ii THɶ);|#G Eje>$Rsd .?JVcZ˚^ÔJ6pwi"K kEb"C;X#ֿ!Ig5ȳ͘MFh3u-vLݞL0YZYqf"+kzVļYUo'\ƃf8MCGz5R5s]CgDUbDOlwE^>O5i}r.IRg& p"jrdE&@~BRv T^blq%jeh/G&i>Iju`Gj5Q˜'G:ijGUwǪGdf5t8ֿH$c;.c5bE$asc-v`q8X0+ظ#+; SXFͩn|PE2ԯAy"ı= 8bbMQzP6;">"BeN hFie_gLW?h}OD;x,,| ) ٙ|bL3"2!(;-dys„&CgO2D3Gdg5@H3g@bƬ#,hmwe@i풶 x6_UيA7 IA*5qYYbMc]le.I$k5GL D50QiB eۦwM#[gC3opCgGܪ*F- *J"oRTHX"Ģǚy=F{sz ,m40KI)KApB"Z0"(IBOGV1$'VAfvpHVtp[*G S$IN%3M'$ɕ{sz0ő%=< %lcp1}x#&tE Fr-#ЛS-$4D/ibE#K$q[+Չ)MH;&6DWDW$fKJ@Td.-LmZk#Y^F WٛT &!r,%7{rz:Q㹮:");")+&.yL>6=p׿5l/}*ljAy3 x?Z^twu=zptsȯW ')ij \o?LJqa8/> 3 W[\wgǛ% 뿼?}ә?t~?|_z_uoЄzg^{Lg7f`޳'܉rcnd8[yjva<~7_U I%4͇liä7h/:Dh|!tXIL_曆׻ຉ;"$R*GCvߓIڧ?wߚ *Sy1Mְ{ߍ_?OB̭KGW ~:8ߎݷ7IvUNE/{;dB.Ͳh|0''n>wT]n@wGLH "kGa%Ё[GKҥe$"۩ݦn.Odc2Qt`]/uw5ŐS&'ԝM;wH/BS]F\M?l/)nv-NTAm] vq>RΕW nZ eJw2ߓJIACffح[ ^ZAqZ:}=4 xTI)D; ߶M8;wy Νc~V&P^[~+mMP'Krf Om:L"MeI>u2 sieI@7߆ P_ۣ+k]sԾ۸7~Y'V}_ءCA)P@ oÿc'TwD_(+\DnIZcj%*%}Yy[ȅyZy {.3ձGƙ>e' +-4uspB%um]H V޵8:zε+ucMMdB7`bUr'X< a8'. Gœ=) iT70\ jARVLdo x'L4_|r{7[x AaGS0EF<hn)S[0)PL0` XЂ-@_W/GXBa DC' It?Nc3;9 /n@С 9K9lDNm` 6Sep}mx2>@Y@ 0 )<{G00̻[K/ W92oK)MڷZO c1Ds PX0IL.`˚5 h@J1̋po5Y 4Nj4NhuqH Ai4cjl+vD3BspT_`DQP M@yR&4 ce+ qn;I#~ (3)u6@N 3s1A:H[:S: @AcsH!meẉG'U %g9 wQT6(h\='{zJb,Ř@M@@Qo^XeA=nQ,} Is@[j 栝L>P4\b0 0k% *5R+F(69S\A\" Dfn%h V 0tAȷSb/ ځq*Z*t 1 N҇B>iDAI1wA,?umH&5Ʀ@F 4Ck `y.sjCѭL' `=ʱ;] 04F LP|۹63.KrB0O{N}Kr*{mAj:XSv]Ib*Y C#afRWa\#9B7r3A;[(2!]BRa 6Xq0ۑ>'`m&w _Q9+ߞ{yc.P;b=7M5 `hvi C^L"֔U1G!'L^?a,Z?+Ex;(4U;(Zb*] H,@qJA(yBz|2h€O/l5R?&G@CFt3۶7M̩W]SH)ry1@án*&GkaG%t:c,"]/H"RK-%|P^(5]J&ca0*R y#avʠ' NC"A Nό*"ܶ| qbcxH<P/&0@ (}ߪԷ4\Wav(&͑e ' (1!ݙ;t\2%/A9^ѯ!>HzCT!Cшyi?A\ #Cdx`-uߛ[IqQ"Dyh 8.5&G(h铃 &"Cxg 0ȶ`K0"R5:v6T9tݗ@29Ǻ"оBɥwT  vL .=@|9"1Hk-ᇦRy ]hv-EO1܂bcЛаǹĉq: f{}}KI1¸KS,P1r|XJT^# !yn!D Hb FtD[ gcf/P<äϘB,;K+8"xX9#:jYjƕ /[̣SˌaNq?rS@ov?M2[A?K,Efq{*Pa,h͜rx&M,s7 @(fm(5 'B `>,K^VfR4&IQ,;`4CFߑ6&g`ˠ9"3ܶF& 1B^/8A2"8?~c. _B A8;aD}\D$F0UWڊ KT4e$tP8Ѭ1T 'jWGW 7_5v l;FOhT`Ё@;;&r c۱n[tV K !X덦 )ηMɁ"?k 0ߖI-㵻,WwiМ./+{V(hVem5=Ek%Q} nqoOp`ql2o 8G AjN|/4ޏA!%YH0Hs/A"H 誷NL2/|BaE`l ^<C܄M7AP2t%-{x񑮼A+@VpëRfqnDAn7&h lE<۾D6-$Q#:.;ueFʎҔ0'0xU*β%+i ͇rF.K~'R?y2qflҌXM2('Q'70߃fC[IaR߀z#,mwqq)KU劃W؂GX Rctiܶ2[Uӊ ]fdžZ}S}YO/YGUQ[Tl)vi/k- Um\ UP-,B T h䈁NLc.x8S^[M&@@sS+Jn$l)SFL> ɗ#COX~&If,s}K1^0őe6@s'Oefốb*\]b ( d^@S.k vFa7mw*Th@fI]J,7Ybn(vMo6!z'%ЗdOP/`b)v\8`y8 s|\ncя*x|A8v>^QДd>WkT7{2δgљY l5_wZї-7[w7鷰J4DLJ#Kĉ4SFEf. Dz1ޅM},#V! #0 `<x<;%|_x998 0y Q ~dx?.q 9$)(0~;҅,vW1݂^9p(u .^}f7]wW9u/! 4&SLfC~>roL2q_ <4OD.՞ak{Vwnէl%BW:?}=~v6Z|Mnzoonq:;oc3[~cjy?)t6M㿕V$c0Ǚ7]}yI2(pRъpm~g꽖t)\#nndjw,x\j~Q bn8n=vQGȯi)au7ttYMjף^<[{L'vGR1~-v,%$]-W)bFb2|aLm Q\tv׹6edQw/Sv-]Fqq^]UV}>xΪ_DVg&xڸ \u6ŋ6ijˈ݂#OZkVj^V]+^C4MY"`2U]ت> (ܬ$ |Vyo-t$zoNv)l'Lo Նu}G%w+fܪ>U9,ƝȞ-c[)cŵsZP&5H.ޅ%Ż< ;z# wu9G7Xypt_呷5;ROO}>;VM{B ᙑ5!njG>`"I @jf ?ہUAX&kw?"5=j .+ہ 1Vu4hBWzZGvIJHRf"Ikx F!ZlB҈hN2E¶$fT -E`TR@`IY$n"1V$rQ[)RCd%: ta.ZPô *(jfi5AdzΧVBU;q6HʂƎM?b6m飐20)+>sq!춪R}PbB[QNYux~Q1׬aDx:Rdn;$[+ CD"pUpCIL{sz8å5 ԤXoI<)FN?[8z[)YpY@ p"넒Y<H[4}8LHʽ9=DV#70}OԀG%փ[9:R+#i Xz@]ҮXB881T +$k]!)3+ I/Ix"vD~vz%5H,,0e 3SZ! M7"n"? NUs4+Qh (@icWϛGk"dBY ?cewޜ$q$7*eZw)u*'g5$G=B,)"|EuI$';)?duzp?d'OŨUBhm.zb°FW'ru 6\IW`QTbqpi]He/]; &`$H)]A\sf3w.dc"U HbܛӃI{jG{^"Wc,.}_Εk4rNc %k7!5SS/}M5,ƝW"S*:(4Ia<(4#";$ҸrojJx'q.:L:291+ό,!b fu M/6 úI$n'XY<<'4+~:Dvzu5"I,'f&mBR&t^6=^BZ<6_h5͏ak4kudzMУN{2| KU{~ĴZ7ǐU+Z0AoQl+8j}E86=#gU+iP$cḤ;WU. "YHҶ{,Z8heѸ%Nma{#K[f 2.77ȋai 4 hgLáib/F#ʽ9CR0E;k28 :j K"mf(vZUD˅mbb-_ Tk5N=AhAذKt" 1V#'@^ɟpE-0)(L"!0b-`bDo|0]Ja R+%6a)bNzk]Ϛf_ ]*IS!%ߚvaSޜ),W?/n Xo҄64$ƁeeR.̾TL?7Р iWW>L^q0\% CXd'S$NzS?jEJ|z:=A[˽9=xޒ 7̝$ڳzgJ4CXTW4CY&rx) : DvzrDtV4y|?/RyXaŘ>H"a<=DVM hrvnÝnPK8Dk+G}555TouchSwitch.fzPK? Hfritzing-app-0.9.2b/sketches/core/7Segment_direct.fzz000066400000000000000000001141351250202676700226310ustar00rootroot00000000000000PKm5D|*h7Segment_direct.fz}s8>} _m",/ V/ggwbw KUv]/L$Y0 >'3_^~7X]Eu;~<~ wO뻏/o^DfO滟_?߬߼W߼zy2_ra$WϷw.^^M?'o_/WY2Wxzns}p;ӷȻ~|zOo^G~[[[0uOwOO_]<>\OOY?lY#<ܮ?]׏_^?o|u0//f/=]߬7Ow?ܯqUz%nq3EW;z33a󞝆>_b<۩o^돟֟_6y}g\痫|yxzڼxۗھx|i}-o?'~{|)E m7շ\uT~~yEphͫoD1;3lG \|^ߘ0F+ q ZG?XaaL7g\ɢs`=VnqP &rmnSTm4{{3pg\J%RKjs)S:\bsK#v(X*$ɛ-v*''o1kyEwM<|~l//tlM¾<}1ƞ3yՊ%"Hr;_7e2Dr<=?+׋)¶ ڹyNx9"DΓcN!nIrSsѝ<;>"/r'x,ۺ(e;Nf0EO5\m%0 4cW?w~/m*LvT~G9$@f4Wx>vwwprH̟f2g+}/mLYy\$&_ʉ/$(.\nˮ]@Cp~:wP mPSqn^IM&"Ou|Dj[ZL ɔ:*<ɔ:UNd+ O{2b`,Pn9J\r:)ꁟꔉcI)s9RDIRG†'7?/ bTىۺTSQ?h j`Q59gG8ޣ?;k?l`(Q^{TFOL.+wzD\SHD=!$2r?S.Tҡ=R? =%c@!wPRz*#4s$sJEWM1}&7{0{8|$=:(Ȝa4SU]$FcsFSh&FIv)DQ48朼c|lL:&luGn FWO/O7+t|FMv6C<m$]b;?_|M J! Ey$TM6*Ӑbh箯mGݵ{2rջ̰0xx{1=;3ֿݭ nnn%XIá7_+Q^,LפWZelsV#8#?rnKFiحF\˴1ޗƱ,BjH \{V$Wz*3d8 TPN:6PivG33BIӸG [ HAƎx; xB9e12&O^f<4gqk&F:t|SdM%HM.d`%ahP@E ߬hC\\q%,^T$Oa;׆j2 u#lpɚdIР=!Jv%F;ӴH2 L&B g{h<ѴMNυ] >fg'C t>eϰQd:)i'tgCiW~?wtgog^H֗.:K7_Γ9S|isYF|JڦyK̈́n9 lӊ? G[ҽ*MydI m[3L,ǽ ]T&AN^5ӄh(%;Hd12rMGyk7A=96d:42#L@HHf6m3$HfCb63sӻDwÇ4''\7[:̭Jke"6MHVtDӣi(ħ>eMX]R#y(FTىrV)"Ҹ8M>%0Ͱcv9?x:9s0""T2(g(2ēFvigg!DՈg-&#Ùf♪Dj T, )OҼpEѴmKy,E!T̟=YJGU\YrOh{,QH<ۛvI$-C9S?9?xWEy0Q$O`E#zZ ۼ K<+I!]g)ֱL,>E-JK5ffZ= dZOՉLX Xnl1!*&fZ'&m55#r5Lӳ?ԎbYbW$uc֛EU}-EJ+TcZLƅ2Jǎ(X<ܘr6>&1.OjKJl(8Zj4w*rchNK4fZ= YU"r5N !ۏx!2"Uc->j1ȱ3'r#LgJo0NE{ĪC+t@:76Hk1BT87YGfOHHEj:< M]D)P1V E2VHp%Y5kڱDԈkԑ`#B2?LUu:2,@vz7﬏FDo E86ndbnFǿ@b_ .;WN՗탙cQ8=bR%Ip, #**+\VmƑaN d0IgF̰}vHGWBAp cxU\ΚdƄjZKh\*,ߴ~z#r5̫dwxɣ?aW}E7VlKq \"kl: KވR8;%GfOHHˮEj:. M]n @"5GUn Ԭ QvԟYmz oTDHT]M[Fb$LHc}Pbk%YRAPZ׮]>idsN؈eCQ9x މ"XfNE/X8KBB]W vHUL.ȴ\Mz@^D "ffZ@Et`(\ch2K)X] Z"r5C#!ۏ鸖IrDJK.ot0r|D gtېn,)HO$KaYP c bLcCS%Qp tVNQ'QJv1B{ֹg;%;\eL_ADN{?*+榁:և|qlDrFfxׄdR]$hH}ql JMHVdFjS HV]MgUn؞D pf,oz_Et`(ZchP"@17;޵@F_#/2:WG`BtIɕ"BlJ7̆jkErRZ>ō/ENkghUQȬ\M#8j%S+IDjO.v`"_ `5W^>,>%W"CWx;fgZD"Cd$s,[dYYQ~+"1!z'4٨滢Sy}+[qW0~?]@Np-_ 榁Hׇ(1ܽQ%Wv94scTWT`j:'JF 6 NHZ]M&PdlσϜlMR M67$  "H1wV[$xSd1#$c@7Zbbip-mKwIyiY'7N9\#Y%C_*4CϨ kȯ\M#8ZTc:%'Li$7-WDks} #Z -"3&8";WsӁ(\chlv1pE}|(ddl|ؘjRlRSIrecLuY7Fj:xc+vWY#%jGv^^>ye琲{ߤjLiزNkH;F"ZŨz||rFϏB2_-IW߈b=>NuG&68m@Cm;x] _]M SaE4XƷ)d#~GntVTq -btQcn@_.LuG9g/s?wkB+T#SƦ[~R*لC-iesӁB Z\dxsD"pcE g)r_|/ȕ398-WH.Nnlܝ&rL %•IyK/aRrme*ջ;2榑qQxiWH\M#8]T`c:'>.'g=]Gj:{y=R,hҭ?<,,Y:8sׁ+lfEz'Et Qūo+]{_o Ye=*]Mʱ?ͥP؉.)[୪o2dwZGjL6 l߶Pu8ĝ "x_ y൥kKar%`K)xlKSH; "ٓIٷr "9i7TxM `LG4( [a1P]gI[%"q{#r5:cX~C#W؛~/b{eW%͒: ࢰp84[}yg%iC(JcA!W} YQBɖ(ldloE:&cZ0&eZ9 t:6<>$[ Gj2/5St}J\wT}-h NJ' dHTy̫i'hc1±'"sgxvb+E5B8*1!8s Kl/)*I[Kѭۃ#r5ۚ+\(o'+ܠb1Pm7}XUۥUMmT!ڧ||LzzȽ Ej:8E12_'Ԙ|iA´J18Wͳs"JpI376#:p;Hd+c5Ks&U8Tj}jǸRH$E"j:Xdlh"D)ol*5yij*b$VDo `g#Hwp$d}2i@h2U ,"wDV4ϒQHzxn9(h,Tc:c*݌'w"<;td} #|DN.oc鸗ߝ{$OE?.3v_CyfPL)h?Q rzrNQŎ b#'>6[ŹH\MبBFPKy i)9A{y)^ilb]w.Gj2"c9Ӌs2R#N=h1TQ-(o&@xwPK,R]]U"r5턋xw`L-RhMJH]S패BNaÑr1GC2'%:|Ju|xāKs繨BG8DPcf@_-2-WȈEHDc:eg҄L`$ T͊{j$H\M,սң?􎦩76JҎ@+s͹4;ܽEpnc c!JFbSH7Ti:=`) VP_a+CpT }4hU_F#=Xd<QXĮY$xT} nLGNJrK 8-WiBGGPB#s۳I]^»3Zh58ћ7١TVRS" 57G!/IhSH7ׯBMH]ԕӨm"UOq UAu#su5 &yU˜#ROMzd {D4V}ȋt& u"s5 &uUxɠdd pREB)T{ 漏ltph)$c{툨l8"o{WMd]MbG8ɤ&i LQ~-"1!ٚ:Ec(,f[ɷXtzqTV}E~4vN̉ݎΚ@J8@ܼBܡI:LF'goT)ۚ.*͝;!-4)ԕ"P!܋A(+$k"u`vX#m#au5^!H3lLchȴQc5ػ 2QX x\I\MWČe nLGژXiAiAHGDC,z35TC$wMG'woD)$JsȞZwHM O]En_ZJMYD%` \A41xW$DӑzaN`Ӓcaq٪I3{`\\MT0vu%RlbX͂LGj:8-H4=tD6M˰P;MȵŊp 7#sӬ2oiΛE"ӑlbEF*M4C#r5muFJ>+,C5kyg"abwV?")HTk56D+jG(ҢtdՊ[N-]OgQV>HH0-[һpb=*+u#r5͚zal˓9oefu$h VLf94{2(Tch&K%&X| $Xe"r5" !ۏ`0-H0L1ՈU X&VYGfL+ol*`gOOHzEt ܽpnܼ(DB_o-EWtqlh(8tsMv:MQQվHtY QZn<{#Wu5 >s厒; U_Աw@M)q-$4ϕdH\$rPjkodY3& 3mqzaγHlkf&팧;4: NyMph"S8է(ͮ>9ZdScS' P!\U" 5!a-&&$*Wg]ƓѭXGx$fVԨ"<$Mбp\9VŲȱ\MhEHƎu0҉e02Maq]id߳X+jX-I\:KѯYߠ+fޒyAv=@'TK`OpvQ7E,VcՊ' 7ǻ0ˢ1-5B~FBpР cQ0jdY3Y)M!5S:9J6"F}VTw~iQDϯ,[ڊtp(dd#ؘaMM+g`]="Лb2Ej:b|)3 kƋ)Vp~ivE&17"s q-cWۊt0"!E7&XiH{'-5R,W$PHXYlZ>2ܔTVoȳY4"C,*8AgHlEj:fфOt4+,AfMe\Tnoj$ZÉL1Fl#1¥DR]1(U0+"txZGt(vƺzyȻlEj:wD] Ҏ'$]ĤKR ]\gIjŘNqtZUiI(T^{4OkI^V TJoG^eY޴Xsa9A 7s>԰*ǜM׃]t1J1!z QETl.vƲyߒi[~a?=9CLi̓Y#H4mCPYcn49}>E1<$𘛓 AW]tմ5(dl#^ODR H`}0E*;aݑ9ϋ$ZTҰ âaGR->9KhG8&aD$߁[`3b4#$cˆDŽ,i+(,E8Uw)qx#s5JnOZV}E.6+nm"aّKXf*Hc Tdq&sӱI"MAd 'd4ek\2"j y^e7FZj:,uI,)Բs׫,~+Q]ZsӡD&c^K O/@ypF>B2v @(_4'I 20K^j"cN%U@f}Fó^;O;fe'zh))3 [X<3cD#C22*1;#'h(dl^FDe 'e/Tڍ;0|ϟFYpVF3X`e3B5 km|*YhYܯ/~3ŢӧKO[;3Q7kERs$-,2I4;џv!YE? 㵓Fg>_nl@qBdIz2ne_f!L.vuFg\&}IfŌnYwrІ$Ђ۸%B)f'\C $\UO#r5];^DcB5y<xx.ōǴ5qG$Y}C0eMp.Gh9qzT+28UܫȽeBp ]FK 3ff_Ǻjؑɑk9.#!-BMz`Ʃ;>r+d@5l$JX!H\M0ǝld<@񤥆CV򼷋 CG1t !s2ffD#$c{'`t,ChsexJ$i)IPR&3琅d#*Mm*)N@ H W_QEp I 驘ׁzi`C)UG# )9;TdF9jȆ|O6, rƨ9΋"EN\*9kaQ1[)eT ŞlXJE z]Q鼖|1.܊t7B 5iGEҰ.K@ccrSH9p fX}\Twi]ev`~"Ъba3m-&bnV_k"jn:(`cho F,f`5,c)p=`aD0dB&fa$)Ce#W}}f_sEI^l~ǼzF=6"jn:zEp y\B(ff] 5L4-gl(ddl?H"1 yfC.?hV3>9؇wL&ɑ}]y|_[?ퟞ^~jϷ/o_nooW6W/߿C[7}SY!gvᬱ`"<(IQܞᒞpw9]GMԯ#!d[{U8.~ C&u[, 'I>F{EPK-)2x%dL╴8WaoU2SB9U_;ER2E3%GP"=]>h#2CF4,( L}&c3iGhs6Sչx%D:$%PP!{%MtJW$+CIۨ3J "iLIΖV|BSdBvJ|Ө:dW]#bsqJ;?ӝSL4" eSYF!$ "0\|"O?s*yL#:5ҳ2AbC${S"RTv(Y)Ei v&$#f!$uR4JBI<뤨:d?#hD;HlK$C^"=vy-!bW#2YsDXdȐY@GAmi|DH_h9(аp"Bc ?wS:sh;i\bU$r\y'=D߽O' ! >r"f>FH<)G!/~Be4ܧ֋߸OoH9B2Ls"3;d bqڧσȼBB~ D*mHx#_D;BxHRHy!4\l~TY&LRk3ot뗻y{sTTϊHcm]?l0Bjrݠ{Bt7*K!,|VT(r wTJBe:M嘡R.D`&KOB$|,'!Y޶N( Q "s5DhBi 2fA!IȘe5T"Vu.> ھN{9/D>,r! b!X\|"u&> ƅuv">Bܡm3d"Z(跅`}?̶‰"LBt܂Z[h*;dį :=,G!Y[0:dzT WF"L}BdB!c_}KMB˦R&"@JXY9>[,D:)BCH3FO,D,b/N\8 l y},!b#x.:D<i0r:D }.xM#{&:/D"Pg BE@兆Etȹig9B!_J#rԹ29d h115 x.D`g @39i">) @${.Dһg @d3 #!#~t">oF\T/萗Gw2h3asQ RP ǰ";d!bگVυΜ~. Djs/: h XL\*3'rsr(^̄$ ?Owwjޫ}7{2p_?Zw:{\\|`1 z~}r/WotWo~yr~{znNǽ~Tm+|kٞ9?ncLXD"is󿿙McY3A{}CǛwcLJYV$=ʌN'뫲v޴k3݄ֆL=o|꿿zZ??|yY?_=^?<4m,ǝW; mW0]3c_8@/ͫU[zs#g #񗗧wƢǹõbks??ݛQa o^w߭[;%htȎ[9mY4?px̣뫭!ZZQ?5=*Q\z(Jnd{Ng.uq_9l 6iýYr D±NA杔T<TlAÊ֌0l ȑA H{VARfo R&RZ@9xОC!a;\c91}\٨9RLFhӵe p]t}vY$<^q 1)4\" (fPr$cS ra &BH0D&d6O7),h0L{1 [(%1g)u#+7=#]t~n]l$$JMG[${Cىf/8"t6].tapcJOK0%A0DMac0 &6aػK.),om)*C E@,Åٙe@zx#LDp.LH0LN`Jvk" ̚s[v+YCpR^l K0u ]qllEl=TzDt0y`A.`"cpdJM> i U{/|SDKQ3:qf0:}ӣ!ҋ }:.M {w4GVZ8`T~1ya$k "Ρ(E"t6]0apdBif&) ޙ^ރJ I@E q4l]6-T<9^bdM^-w׉t~nq{N#~,kԳw\ Ƒ .=ˆV邁${ %SωܔTYm.HT 3 Bz=jnکXCt"f\$MAX;\옝l5L,RLgG @)3(b?ٿd^mfhԫu f,渫@yWs˼aUMC)H2#,d "́(馳邁${ %͌fNntjB7WvDt^Pg1g`bpu!)mU?+|9p:.Av1; H5{dDl` ȔT3jjTS:SWT4{*9 + {pOÚiꦽV{l7n!ˣTs \tF)f>1,HpM96jr[뱪gӭ5/Jzjk]c?*|10*ԇ Us#"?9$W#Z7].l`pAcnby7S퀡ں{Hh?eQ7].r`pqcvF8R㏔t))e614(e[餔*SJ)e(`K0쭂9a7{/P e{G6fP:.9°w1%,&fl'\,#lΗa; &h+쏅S7]0r`pqcvmt)9S*Rá/KyQR&g&/+4f̧K0] ssK^$v7UFnci2\ܘ[5L-:KgcG=$zbr A'쿕h3+3P"%J1\Dq1ipLʢ"xKcb 57A"+Cل)c28e1;<6P*#pǽB.tLI(Ӊ A(3֓P?mX+b|2Y!R;S&tbت34*ÅYq7hDNl`ǔ2S48eʢ aD U^KN)XY"$wH,=b %57rݽ_FX 9f}C LEl`DŽ$ Ib4Hye{g|$DK wb <ܓ9?(ms5~b#v,_>Ёt$Φ 00|LG0s/cjeIo7Lr/WotWo~yr~{zM7'燷pxӃY^~|i{~up`It78acT%QY~|?4d|jӑcoo1;Lnd٘%JLȻ凿l>x|gca\u-/W?-R3;]hu!c{ 7^0WvB<c]~}v3wջ~|zy?Yy4OkCe k|^oޒ4Ŷ7ށ|~ca_yeRKlepJ,I¼.kەL*IURIo̽cre~'5.\@ܼ,3oKndQTُ2ri?Ρ"Ddm.ˏeoW' 4fW2;+`B^ں y#Czzgv0@|] e~oB2о~Z\ni"SqoLť1g3'Ls^ҶHR hĵ kӅ_7`"D||#-_ߪH33nEf7wƝBo%̗o=%.u2YߌAp]̨.63L̴> aLTn&[3Yy/w>7kت| kÙqscLe;C ޏH%ƞ0)@05{cGlj?/kOŎՎɍ=f150LJrg$䛿3h4yQ3y>޹:rc:f_t6ب2rɋD }@gv| ǂ/.PLGG wq0GzҢ} P&y+`UPAm05m20i![ý_c9 y(lomURNTh|yk^JD"Q55{i\  z]y}񮭪r im UՑ^"ƛ/2;CCl^kx;)VBtue -o)o>\` /s. 2~k¢+Z$31cѝe @6.*k,U8E9em l S8Na\PUmEUr_sk\V kVX6q\m_0k5X$`\% y¹^=2kFQ^9L) x5Xۇ1Iܱg#g~pZViXw Qy R2uj uo_'wXG;BŊs[>ðvyOq@X6@ÇcUxC` ! t~5F-t޺HEpZLaQi ~q P 0_0@ٕHEx _߂pp#kx7fML1g#7\ݵ~FkW4vڕ~ǷɍXv/uv2YbpMEKl[B׆$rJZb$L28), lbI]dpD8|-/(fv )[хy {qQ6AyAhjAݣQ5Fm=Xa)kKAY kX Tm)^.0@SnBCNM H.: qsf:4*Å%m6.m `!6gv*Rx Wf',`a!\G[P]&pk[5+.kOY35˾֩yR͑n;`@dJnӧ ^loX9.\"f09FC`}3` omS9.N#?&XXp9l+@g@3l3!|!{'LBl t1s&S4WN@ fc (G0H[vÈ @i <9 @! xƆd^֙6N#J3V_iZ;&DjB ڌgs p 4ٚq)( U,NId~W`,r p<++L0W 1@x R``JA@HJM L34%$Seۼqϒd( N L3s;ׅb_f6e] NLBf]GxVq>aFGzH Xx5w5_Uw'[BLU97x?aIG9Ô.\f<=u"NSxҡ p3X3'lRF`,E!U[o<|?oZ!z^B,yn憟Ad@t%eSpdxRYt۽Bb_(R D b1f?`rcF=N$|׈gho)st93 Tvo7eG #0B$ `x|aKWY*ݔn3O,n`tK OR*O0³$ +33`V x6e d>aG;>Cg>¬ e` IB8@yHMa zV "73207$ B&пx-'ךaܱl$Й>F9S(ћOC԰bee5+xX*/]mja!d`\Y3.&܂_ڠ,aT),1C$p8BY#:|XbbMaqtID0.p/ *"xxQʳ$[A[b!VpXЊ^L 2_}.2KY\A%IHc{aB0OXVs|=$ `ymSN -pcS`#.C o`幬 ~n`J8# x޶)plx4FVkԀN&əׂyy t>&93:v]fTc$+Yϼ5%9"a{c$, ,6@a`ĢK3{E;(6!3u) @Ê(`x9 5SD_Q,s;n{]Y" ׻aͥ]!pӔPC.a߼`DZ"W!5 #Đ@/տY4~4^wd@^9.v' K|;(n{TX?o ꎯ*I:KjDkOP YNͳ1 eY1却cʗF|P*GS] g,5Q^3(LmM]B~?CcPDst,4Fek)av+ $8Q=dL?\28 iy8E`GHn_>Sn&1q_bϛꅷ< xw(9p4EW<[ʊַo]U-Or  pL#Do.F ҝ)J$/C;jGE^LE; `@"(4ߎ_ .P O~=VZc7b;ߖR2Ǩ@,DUh 8.׺B( h, LD1D4pRFcd_`'cAc|X,Ȟ7mr@?zYv`|-%֝W0,U:xÀDȬ,Yy}7o$FiM'ᇮ wA>k:0r=[pq)sdp[1L.1͋ĉTXVgׇuDR0n Ttqok%>C`(9+<&lXI`ʕCzFGJJ2Ę~LoxL*k@h6ðMqɆ66` tN`my{?pZ$yD* #@Fg!)`irR`NTX0 `W>%o H,ru-QsAߓۨ_y9aN \pdpdgȍ@~R>@4Agmazn p A֋E.b}˜^1.K52X`D^Ks)otU!8…B2eR poR"03 ƉE`[Jy_=1AfVuoU7̿b rHT\nKu5H|r liПElnEfQ7[Snr&M,u?i;W 3ca6ՌY X>d{ٖ#X'p6OK{%t1ImEtqXwe|3۠9"3|mş2ӈƄVZ`F09BD?\.>zNzy[TynY%5pdA08@2Qq$mݕfz˩W[ڊ K$,/󾊃# ٵruQ۟GW _XI; _Ca ױlU[Ёu ?J_ֱa3Qc2jau7]?uBJW.]E2eir +Ôm]+jpr~p/W+44V^5=J<.kpK"x ,n@}]V}*.qţ33++8`ŹFpHmcǦdHc`$C`j:lL/7( _JE`(-2!]d'Ipyq^M_ (÷830 7J)#]U " >~ñ^-Uj>["ZUXÝk``u,{TKdӫڏTkT~]WsC>ݷHeª~pXΊ-+k[>ahRRrd2Q-c[p&XmUmRT[ cdÓ'0?VFt .HFonhu~Jܮ}tu\j*W^:5S bOզm&uf_g0t&T33Լ6׬~9Rˈ5?6#|hV( 4 [TleFm^fP'kԬŨjkLl*xͨ%Q`*kFQu1Љc̥βr2]iϭ_$ŝ F 6Ekr[߈Sc)O8$қ@WL2a\ QYXfJ{p(I9~YKFjȴ&V:O#<rUfDgqd<0lgDFw"X ؗeU{r}]5\RED:<&Wldu0!jd?n82:ϼ\~»|52lxڐûئHqJlҕ—v xfiX DjxJCYы,ݲUyeOmozˋXçLVED+Twuh\ee2!Od+% `^vuPmҒ,=iYqkϢ=VϢNC cY.J}Y*w\6exPt`noZs{1%z fbtR6Uk(WW{qRu fQx00;Ȱ0̃g;/c '/O^Xv?S͏ 1kjHm.%kUΨJt;q|,j`-<=]Vek[m;5H&bRY"n1 [Ki!`T.',ǥs<~Tv`Ei'h˘&ѹeCT+ɂ-3u['ILA^ 3 }:L;anUc$i[arvajQ|R[p;0f]1Dܙuͫqɽ,enkUY[Jn `>Gej _:zykÍϮZEy YNc2ʐ_B;"Цb8.o(qJy. :^yU}ڼ)ubvmƑ13T{yg.r~}A/%M8>}ǎ"=žw%ɠ]J?)5׬#62 MʔE8<'ºf6u7*z<Ɠoc<j2E(E^"xQ/E<E^"xvQ/ୢ^"xۥ (EVQo:n`hYX]|"xQ/E(E"xQ/E<E^5{^"xQ/E(Ǣ^"xQܯ(E^"xQ/Ej!"xQ/Ej"xQ/E(E6+G"xQ/E(E^2'Ec SJڭ LS!qcjR||mHϪbO܀/w/k7C>N]5)6e&oݾs)A,qrD2󇇧O87 MNBoH*V/i>]I#$%J o>^߼<<5Eo^U(oF30.k19ߴea{Zy^2%Tv(9aJbiokW/_^}0(^]|{{wo>yblzZ'6}~1o2xy|1G'mDѽ{~4_/6ȪZ-`'><]߄ ʬSPluQ#y⢌Zzӯl0\Y1wpH@Q һ.U_s`=PlȽӻ߼VuCߤՀ_oZ7Wk6/pIg@fk&]9DI4v)[L=5Fb7Ʈ_Icׯu$kIcubҬ~ fؕj]~ؕjDR-q]5ƎvITI4vMZ6vMZF&ma3iB4v!ZLZLWuƸgTM&aQ2ݓx7(Wif\Ϧi!|\ Jف㳹HKyR/oڴ\V$ڼ(2"v_<]?_6}?qS S߿7*QX.=<^ܽꔟp͋F[ơa8FPH[+iI[=NL^4e)ࣰ5-u@ȇ7lL!R9? xXТrG8F>:YW5EM!np v(WHSy:^<4ꩁjC }D LH G~b߁߆-+6L@"\{A (g|ǡ,M$x{Co$UҾԋ Zzy6 wo؂i`JlQϵȀƄ\K񉹖W=ϩ*TzPy"kk$`ki[7f|7k-ڗ H7D"71#&ښ2;mT0jvRps[a[RaZu`sNy̚g!rljW~ ^X2 V~+yHu5CMJ#LWbx @׾e)r̗|XîH7FS)4cD#$k))ش1le$jp(mB;Ⱥ3B$㼯^aHʼsPc`ǂ޻b#;m$ _eHID`c`ϰX'#g|ZJ#(R~JOYoE"ugk )kWb#a-~m`6IBl^nBcEnٖ >rGD6n5|Ϛ]Kѵ6܋V-)Lq&]lع[f'ޅo覝-38@S7 4"P jZi}8.Q헦oyÐ} ]k]څ2Z A%y1e)Y.w0t gCFeMFe5c2iηN)I{({:acvd;q>K|dh2].;2_r m'sH%6UU/X q/l_Th2PrrMuӽtdj@K o]7EU-[v0*v"eO_jma]tP.3'՞šzڦG9P^ 5)+iŔsnx)1{2PwCAH<놊RL+AljV,]n(d#Cm,!^KgSa[ZMek[rj|o3'b[]ZI|0|c*@OOHSr|R\&{VM hoꋚ^)jr8yCYa#B-QɑO l H QT_wyE7Y#l5"Wyzj!K,?Oƅj\ĭLJqU[Ci8?ظhd)YDhf"L;PPqfbE5cEi8 w,P\ -dDt,yH#1KLTQϙX!DXlwPzFLk 8Fn b"BCB#L&)\>`$<<_ BÇ#l@<η-9L\ 'e-;*Ƅ`Nv/k%&[[NjXg@O]+[08`x#.Yسg@Sk[0ЈZG56õB},V ,2tҖúXvҬ{ִH`vc6,"4 |2;Z$)T+*t*&,rA`D]vՂ ŸvOj8lW7ٯ2VHNPƪ@S&d :,XDhh dڹB䂵t7` i9OJ4,Xˡ+PX +`D*dnlJU!^*M1W}2j_zOݲJ~K PPO dլuLWfX%GsE-PrmUG7%M=X8{Gsb"CKZfa?lo(i)~Y۠1?['U-X5RzII-=(9r ="*<}렕K^(b"CË\ mwju:pSZ…ʋ|2*\08ZleyOaˢBËZ)F.li{L rx4Ih’a1I%l)$9kJ-Y1:X'Ύ5<`GV ,彻h[͊X) [ҢTkWs5v,V$aNGzm3w^dMC% 9e{d#d}2KK S%jU~ oLkdCCɡNgشЎAPji5_іu9,rA**6rʶZX60:bVo "VYa薔.Jc eW7EW)%c"-zFQɡټ …F>kErDRSjB-&󬦐eɓ @eGN 嫊PX{/]r }O@v.*v&ꓹkgaŸ;hw"gd-eWt,2-ɲ[_!)Wɋfm?Ecdd5cj1īPjy4l޵S៽k^0+9e{p ֩k#4F:b dٹP`5M큠 4B,to7ظB(GN `1բL5@ڮwqc0ues^ p)^K`*t] BI5CZTvel<DԼؓмpeW -x;AojYurc#pC` Y|}O?~9nIG{zAx#1Gsiz/,[rle7NǝnMCbR`"7:>\5$7ODVIY$ A.`)҄Mf #BIM6'*B*6ƭ-PurjP{lETr B6iX@5LΰiAl'Bw0aG6LsY!2J 40{ha$Lsw*/"/a^;yMCw0/L\30Ȉg^eȤۜiϴ%;lWn/` ^37Bт~TRjf\Ho4tĭ-ۗ۠\Cx\}y?aɚoQSGL*#H|ۥW%gG`@,26L{^=~6v谒8N_oYJY0٥WgX}REovIRC U.D˻͋ ݡE5)6h谦 V."4… |2] 8εB `ˢBwna#lo1-h3JVqMK3ˬۻA-UILJg'{5j=N.[DXfKI'['3$N,nŭڛOJ4]ˡڅmxrՑP.BdT__o9v.pW6ٵjx}VF5b#tu z93|2rL4ț+]^Ё7Y졫_ß5W{*r1'׵@>}QSɞ%x\ - VU䧺ݭz@^xo.fg""xo³XC7j/'V +*l)Æ\% 1*v eLh ņ\5 d0+YЁYCwj/gV 2%Nha~lVTh;~s4+\D4ZF6+qTn~@[U/=Ǜ  25[!nW=>{u奤1(ە)F'^ט+WŤ30bUZ8\y e" {l2+W_0c\9[Mz/[YlVJE\%Ym o_Ӭ@8fȗ7W{9XzsŊ aobbqO[jYu դf.dVh1>ɭj3-JUKć|oR3W{*r1#;fHB=>XQ`4s'*<"PE^ѢLXj7ا,悯S z Zkn^N@S}/߱MQ9^Ҧ@PѦ٦V{6Ef7|M)cZ?,ئP"@lji`)"4]K*bT'Z bSO @6*2tdstD(%7*`谂6[j)ٰ\9Dz k n,ج *Ηg\D46|e>f5 bo.frcV*Pq]˙&jf mih~s+ZD+:FNjdI[Ŋ'T$b咽d9[JU>aB٫o1W& HU>Pa//sbe ]sʾTyEb.TzdR+/TBw1@M\ 1 ĈXmdR芵6(p/aB+aHڨ@xѭ'jmV ^#^+X-^C}=z5 cozR+wRFٯ rW Չ'1WTh~s+`Kjp)UZŸHO;wb ,Բj .Kh~j#WO__cn\^Jp"]b+ƟxiXCWh_L<"\El!A[ :Vdh[~st+>[d1ZCj/V RՑG0lVDh;~s4+\D4*rJVf:2lVdh~s4+=Y /sY~s3+L@a6+"4K."U•p #SfEZVݲYd/YAڬnhYb6奤1&ȉ㲕LUP,Vˡa+bR1*+R"mt3~'L4HC4X&݀ޣE٬P6+pܬnf; VT(UyEDRV%;Wi ׾uDˢ4gP,ocYḻ^%Z_~ۧ?_fC]A,i('!plB#bp,ZіM(dcTh`d>f]5.AbZY@.iQ;).-ae8d+#CeAtPNvtD;| x|To •{3nDh*L(Δ1.{ R7Q6UuvNɢjmTX2T9eMwպՂ*ve\j ,n'=+i̶]Q (ג' 'zY3XGA=,,6["UR?0_J@_}[ࡸ*mebվ3QcV6<ݝX¬XT׈5"3q5~?>} __>}}~Ͽշ/_<}H1q-~?PKm5D7Segment_direct.inoVmoF_1::X\"UJ6.xro~;B!vpgFo痰&܂0y PdI3+Vi-`h28 h l6o㜉/,KzTzԭՖ{ 1UxUue]МJDr.niL+O:Zf 8w69pJ{)|ŵ4yl *\m0D\׋_R٫㈦|c7j(i.MS:8U㗿E(V9Ǯ!iR '9Th fд5&9iY3Nj) u`E܊^ }Nq] 7= |e,ue:q4ϦT1R旺\#ES|e׭ S^ ug,ٔo^nGj;Y;1ŹLXýѱX#_ޓ7Dܰ<!WK7\̰uOaiq1Eo'$|K-[z(_*x5KPKm5D|*h7Segment_direct.fzPKm5D7Segment_direct.inoPKƗfritzing-app-0.9.2b/sketches/core/Amplification.fzz000066400000000000000000000175201250202676700223650ustar00rootroot00000000000000PKm5D 8*Amplification.fz][6~_Ƃp'۳ۉd8K-Qj%Q#nH"%$^ĶD!|~afqWo )8}W@}^}qm==/~Lmnƽ_Mߺ wolFfsU_7[׆`5^{~V1fֵ!G+AGhQW~oԽVJ<4",}$DFFoCxȐ-um.}C1ֵ8 :!W( R6C Q԰{GD4+qEӰͬW Ēkpnywu7{;Z76Xrf37BռW)rh~\[`Wp @zW䷶@^(b\ <`|{}C|ѕی۱pp̛lLu\PRa 0֝]'崟[ctUd }OH_-0YWcُ_8hX)UHJulF쀪Kx(Rƽ%#B4C8 S(؈XilD ]1ll %xKcG̕a 'N[XmfSQ!EpyiȣbG4]hgdjݏ_Tɧ1OKL#ș}l?@B!Pq@,KiE `wx6eP\oҵ|*ZVbJ물Sÿ*åF wOROPӫQyc^v}l_(X lgITvQ?9}"@pF&Zh7M_7^z3-VP`|3(X* SIf{]yA;<6nun꼷oj)\lL~0,i QM[wͅL@@[k]+u~|uNL*4mzPj<]ڒDuGo#ڭꌵ!Lo. l݃eA{,h ^ˌyNq`qLb8R&GKbl%Hb +n ُGrj(SKX~ykoamt˧:,YAl;Қt/<6ݺG¦[x[tMq, cfD!/'CI@D@)Rp""pf(".4{`D0DQTD,~7 JØ8d~cJ=yL2_GP\C 'AI\DP z8ͯe(dv(Ludix7=ט 5!S>1m9-<# b|27 l n@~/L8>F%܍S:R#** 9.A0MXw4bD:nB.0 iI9!Z}k^KKXaVK=̐-1Z AzWa_ 0a:FjčI#Zrk%̈́cp6#E{&kT;N38Ψ. ls88o >('Qvr8%=ƩPO-݇8|jۨ}D( Wh ԑT>"+4h0ji_b85" Px]eX z,m< Hq1)p-/1) a3a*QGacj4T>" רg4 +gƪJDu)h;l`լ>(h)hK4K*$A!!yBcP(!˲UZ%XSBĄ`(dH(G,dDѓwFgtB F$o%QZLԚ"l+9E9tfye]*ZS=+z]9~T$fU|/,Q)Q6,F-kZn $pND}?a)>Ƀ пEOد@ ]5gh*%"i#:%!!eC, msQiJF7tQhZa RKkbY\RraU^r{iX8\ͩNfcm0rwq=LRd&Ņrye[@QK紋"﷕1ʳzRSZxU4]i TN(O VSɃ׊Ps FsDOS$ i8 fHw Ek*1,g'HLQ'3..[ג`Ft pu–#BE(f([-zvPK_??{Iom$iAҰTR$M `\h9TP[b s4C/* )ZNzvuo쑲;9b{p?"7vq/7~xq~/8`1 0 oߠx[1 Z<A3/@5*r9/`J*w*T =8Sn;b8vw^tmRy4k;{2|].Vsz/?C@38ӰY|N6:,/b' kz Y,Cទj]?O[USzphL ;<Iڋw[5ṵjAq?ÄlNhw#-ORMy_@a#XREmɫ{^Eu$ H>É@*%~C7Su0+k TeJZ B(~Ov4%Js-ew#og!Gޠ)ț,- /APf 0??2as`$p?Ϻ9# LϝQE;t&tSKeZzFUL;S3U,dyE ?S"ohW 0f!\PB! ] b=+'膦Md*":{D϶ҋ0V)qqU)XE{'^yE ]P) 񒇡u 'J\n% r#\hJ:?WYW7@>Hfk2|fm m0I 5%`htR͠0PUD ۪4ʮ0=7gGܴ»JlI)fTfIN\kOeVQÆ (2S~sr:ɭ pZwq谒)xa纄*:h'{ t))$ S PRp9 C"s>[X\H<쒶O]m͙»"Iē>U ,bМ =ʻ(Gw4]3V)X^SLgK> 07q xhGhD?Q>%T WmfHTeT -]Plb0i. +Դ)a+is6GOVaǕjir%Ga!4уaňXF{l͐Z')vJ~PeJAEByV, HNRCGV -33g_Ӯxoz#L AgtjF)0ry@H ;/>v:ӮܢݙK}e̫䶯dpl}ʋ(}ȂC3^z"2ƺ* س]|Upk4zk dO36XEc'^yE3W]Myk8i.sFJ{bbF  “0U\6X~܋cYLhu ڌVY^T蒶Sڈ$1c  oC0 9f١0223SeǖGR)pJVˬ8g*L]kLY*ZT=+Z4S۵UaVu[$ 8%S{B l "R{=+Zf 6.8f[ MgÇf3hUc(jtGӥI):;2XE'}yECK> r0`^-BDylA>h@DOS.!WObm:6UDY)b'dE+4;҄hUVyY^N !] i^;w^eBwt4޸ j_<8SfeW,EE9^{xލvt./f븫jN{o6{o~l旟G݇w}|?@F?;[7=<<|~3^9HꢑB`M'*u(Wsz/!`+8,9Tԍ*k6{zNY׿e#LNKK`TNOǣ+KP{XX^ov<<߸iXz+"~烁d,>o'^.0̜N?H֟P]~ ?qP=/ $w/H EP?_;Uw HoD +$/0/b|@P P\n}HP/0 NJF߂%5;'Dw bm+ꭣ?Ukݎ=rZ޹RP^@8)eE[Nn/\t*}_zf؅F6#)XA†Az^eBmttqd"<IٔD 5uxkD'ZߥC^Ľz2ilR%o{g~SBvwA6C~y~^0Paa]J1vn% a, ~c憎@x j$jI4"Bҋiɥ=MҢLF[\bDm]fCWbťF:5SѪ.ݪ9e.F*,;ST}Xj(B_DfӓlvA?_Tt`B'T\^?0 uח3Lb IQv%zuAܩ֊"5W-ht*4,HY}߿yV}m^֙|ާUC>a%:+l D~ĻD()U]W!DZ;no)U4@ↄ!W$#{Oը+YR^fV@ei̮dOEϴ 9;YE]4 񔞆,DWՐńlΆl@ L ĪItQ`! c{,{[%*,Vt c v!˃Eį5>;3'+_7[=zor|q%E֚ߠlk{JB  zyܝ)il~|՝r.!~;\d? <ɵy^pslÛЅǂTuMT&tlAJU L(*˲d'@ G\~8:(,8XuP`u7ffOH\ް(^QiQ4eqa|CyQ89\Q8Gja|C㥎Č%*,;#k]ԌzDn՟ė(e)Ȕ"Oy4'A<<_5;2RTz.uC]h5XQ~AѪE[i8~>Հ!ԧ t$LŐk`i+S tI^)9H}DOuL2 ִꆯJTuqЂFB,\DA)<۠LE'EB@\xK|RO V'bH׵m0M +GO /OUHaM͐\_B4)r^.q/8Κu=]bSspJw  #mdJBΪ6W8b 9]5iDKqq/颒3Q9ŌBw% LG5.s%Ue0PLL LR@-X3,Pn3',\~\'Z˪g48z vM>nXI\lnODK.I2cP}BV:hI=%mVgK.Oˌ&i~Fi7 [AbGB-;bOױ. [ĥ26>}0L#|[HB:fȿ. <;\9E+E\5\ U=( CG´@/2f&.q}$`hGM6"Sw^m1jrʞjtR(Jd9Sks=]I ٭7/iռ4H+%>Njl1JLAʃ FG^9?kfc:bFqk\źU<Beͅ.i䴀)vOb(-47#Zh0dUWiPKm5D 8*Amplification.fzPK>fritzing-app-0.9.2b/sketches/core/AnalogInputFSR.fzz000066400000000000000000000360711250202676700224040ustar00rootroot00000000000000PK8DAd*8PAnalogInputFSR.fz}rGwpbT!YK-=Y{~)@Hb h$oC+m9Y$nU`PUywwN^͠uLY+FՋ>_v.'ٟ$6> ߴo/^{?EM5ɋ֯uW/]1;_Gvܿ]8S1RY:_]^ɘ+NV3Wjҽ}WM2䒲^\_**8c=rtY!֠;^=knɋzmѰ;;ߏǯn{d1s+/BsKeO''=.ѵp|;+y'2mW]?< ְ{}>I ˳ydt;x5\&_&ix֚^>4g50>"~n^&gH ;RNW|D>O%xt=p;f~h t{wcL_vӡ3 ٠|\VB/u-r%Ëˋ3v㮯۲r_fʼt18Fsޝ{.qqTA`ZyQshSd70XPU2If?_XY7TИr֯/"eP%XIw8MnZ7&PC9_=sΪZwj09)]rUncI.K [Wu]wu K綬'ɽZ]޸?D {|+[hR<;>i4Fh .1ק]]_z]_;J Lg”|xH<, >-:pYU493UkҳG=!Pဲe͑ɴ1ٗ )bMA묈Q`bTID,RF O"REzp]EΚ`.68֡6>L6;UjFi,:KNw?9y0!qXܳ$n'dw')>ծCm6`k5F/HY8lj7Z;|~tN1jCo3M0{ܿ3}Y|Whg_w/|<<7&KYhѱzSxڞ6}SN.E#9[F&d%b`|__.ȘE FZH ɸi**C%Ɣ,P ̕/Ohh$%ZIT M(@uG4>l#ڤTsZ#yZv#z;:l&eVJr\M0'#VQ)kȨy f|~ZWoy;}u:WWN燿lsǣU^E׳ lGp v*EW^%Yo;AҚ}G;t}֠߭YM&ZI}tߵϪVtN!磋-9Ԥu]v}Ͽ~NU}~LqzgL_l8t/|n0K|4n$/&P&,:zD}Cw-/죻)˸;,565O[ɗx[?u&Vw\'Gfɰu;M.Z(d4_Ukҝ%ѥٻ^-[Wk'%"r뉃?^|^ta2 dؙ&éӎJA#.kgGg[נ;oO,TaXnL8~7g GR8rfW}2Ocg rsVWB۱m҂f-8䘊)<Ƒj[F#| &$9sLADZt+Ey]ՔͰ(=[dEY+2Q|xl 4d͌lfD L,;c+RS8fvHhY񜙭W?eH&63b#J#VjIbXC8 A+RZ86x>3,"Ta`_|2V`{l )sKˏ}da>bc!|lF tˊEAX)ZUB`S{o:<yy6!hUX!=3i{=4*[SjrZO64;<_eh]+/{JLN'bx1k-J"?ujL1 -0_9'k1zǂ̣NOZ+WNJR3]0 Ԧjf m(yy2:xF(elʧRd:BsR!))3/K j..RQf⎽X퓛ê;-3e*t0 i {>b,,v8$<93x 1:bGǐzX"=HfP~iL"͹Q\h~A)$D&*SNJ;Yk증ϋy ꁖ"SvfsGV*LȿK&ڲ U&qsjIZK䤼Km%^%O*H~cO?*VL瞧]ryDU\?NN⏞"}xp}z̧:_+}==D~SrjR9hJO ®ypRz嬓H&Ngǃ&:wdӏ5Rd jVq-Xep ̔SgUQF٬*bw#xXߧƪjtZ} I*(^UP'[E pT6ҰΧc@ѐCFC:84;8\9щ;e2?<"5 #G4#)Օ$BeLl2k!bOc5{xe8f8v@-"q lF1tjCaG5k⛞l7͑&'a"e16QCIE̔-nmol@W>!)jb<۔m@GZ邃-4lȻq( l^3|l`G&EXb J'JBL;cLz\ U1ʘZ6fJ;zprޣʹ6;"U3jl<TRTR?EfZӆOzxh!a۠HurdO>4Ku~<9l5$/Y;uْ G~Ua Dzq]s!]FW7ݫq55{߳I|_̮N*fV0#`u=˞W1'Ik!>^x~z' f͠u4?V2.*vvoo?_}_~hMZWoNwyu׏?]t~ogNg&W&u7;FPǽq̋ŷEQdLδ=k}1:OZo jQ;hC?|&/۫×iZFzy\_Z(+7Ib8}?oG!{ :2Lb)b? ?~I ߤƏKwW3CeJr"-#[ܤ&|}{ʕ6a TR?f׏Xv!+2hDZh0d_*V*P?`RiTTXDR\/hy (Y8u#`eLzϏv ɤ Ag)TU)2&w5m\o?E)-hyF(|y/Wی>%`Չ嵟H^o{ m|)C<46Rc+ עwTQV m6|`˜"]ͯZBC4дsݥ"-3&vʍ>id̓B՞-4ɺ^^&JHT` Op*Wa=TYMy9ڗoﴗh. OxzIb@ݵ7# +9ʫ[O"g B0@BrX =92rB?@z1`w Q}IE^Ɂshl@}Xa!5m`D00܀<,rDJΏȮ5ZaJ#=A Hʊw}v@1`G KCHdt(h(x} p x9܈WN)9s~s8sE׎3Vvĵ.\;]l?t4{ Lx &Q_%@ J+R?x1HeB('Ly}Ѧ،O 8 c[1ލA'LԂGYvɝ{7)>oX rpGS0EF<{4X td Dj SJL,V0` h0P((+) BtjtDsީb,wbq:څTh_2a#ط Kyج^!eN}<8`Ct420=@ kF% y2aXS o@T!0W@]a,:?#|G䕢alA4 Mj~h` %Ә B rLxp'}M6"JM^>rG5hjNvYSH)|H(}p]C?^N׆J9gLϋHDċ"RT.\B9\BvS+j܇Qhg E`T F2ǕAO(2E& NmFkNϯBancŘ.%,`ꅯ 0^6^ƚ t)Isd-C0JLwKA ^⃄kX; `@"8fy# l&"{$Hc7,n$5FExHp\jLP03$%LDD4pF#gX 0ȶ`a EX5M+V6r@?zv`f Ua; HWA12IS C]s#1ⅳ19WEY<]hv͢ AnArdЭ&]Vq>qbBS Egn#y\c~. a<^5 * \඘B@0=d/ ̗2cL? =@C0gI@hu;#~Q^ 8M6*]: {@`]WYl̈́`a #ijC bCگJ94`0 `DAxw*БY`/F}<h{ T nX3sgQbZhrpהAD4nX^[!zE 6Hav1^jbRхR9dsB@Qa#4lޗngxI1(&X wW;@tl 1A`PˢT=0t7̿o1N9$*)#dȵn&1vxD4pȝEjv0NhMrh&NQnx]hʼn@ F2"t0+惇K>]A4xW'Y"FS:hLQ,;`rD!fC|30Xl4Gd~k,~T hDaB A.-8 #we(C(C7rqa: [dkDw &3Pw'  pXd#""11,~ mݕ(Uo{PubVLX)C-7zpAn@=Q*g_^+j܇m;FhTTc@1XT0c8Qnpv7]?kt!%u2Pdw2@ ei6TrEBsl*| =(\8HFoAn(u꣈ѢRD2A + NlTCPp Si2;UӊUU|͂ õۇ5?ҚӟӊBEiP;8ڧ\aP \Be TPy&Tq#:1qLmdF7ށN&,2 5)SFL! '~D& If,u/Uri6@XXkX POh;5հ8[ ].*R]Pfy2Cxk<fMJcFa7ðFd p."S"`r$[u/7ԙ g;˧c蚘B`҈LV+?Q+v`9y-:4?\vQaµ#'釽c,8e\)XpNAX5G-Fp&! xJLEo7Z^ݐoJ k{՗ B9z8/&g"#S8HB_q.s`Fݣ`r0åK\oF$6U8 aE\6_.ES0XXt) R%.Y +nYrL:׻blĐcHBɂZ0m_;߇h0q*v.`0m8 É9!nbc%c7/7 wű@4>^Sb!q犂FEi:ӹ8K@gV@g . .<הּ/[o"oᔈi:1),i\ )\ė0b kC,SvPV @Py@Gp<X|jyN25_/\bˣseCTgȉ0`I|Sm\BNp~ >0CI'`&TmFXpPR?`~9몖"73 EC\# |=(w&$VCR2^ cr 8 Q?ۋ ~\`48p4nE0! 4&SJfB~!ra(S'C0zAs ]6 )-Am?e;m~yLƝO?>_wgfɧd0(sƽsXEw)v[ѤvH`3c˻zd0]JEWn8nch9s>G}cڀ1ߜjpOH {?LhŇKȡS2h|Ű'w?._l8_ΚDw~NƣD[R_R{̖kMhrӺ e Q/z>?Cr3?r4ww#gZ#Ļ,vKqnZg9Wg=GGx>5y+Ѧ(x+C#Hجb(VYG?A)wvJbgB蕇;~x^~zx`8#V:i!r%GIQe<<;Tx rhUT%H* ?>Hv8wUԮ_׻ץP~e53~ \ߡg!{M$Țέu^{eޔ4îa}jz`GrM0KV55.AB+FadU]և*,lV{Yǖ>ҽbl8tă:}mIw^4sҝ?wMrܿ[?cfQ?N\:ƚ͝]LYكPŌ px15o&eU~dT Wk&l?ţT<оt9԰>0@ġ)͑9mY~Py-(hY qhkϞ_υi L8g;71=wtLf#Hߪ!4,l!Nyy0{L™ 0}#`vFꏰQ )p M bc, ,e7,0e}cVCw%g/]@IoP= AqӦ h9,uF'V{@g0fY0kf֬a5%{ҎԥX"N*┩U:5r0 @~%<"8E 70Txm]} rp>^]ydMI"*$ 6m_HkE] Z%)qe=z4llѰSad*cbtNUGLCƪѴJ*IK. }dB6Ǭ B[7ܬU-lَ$^6mVDwi(Nm;WȻU :gR zT3%Xv@ٿeeܞ#yTH.t6qar-Չe269Qqih~Y*x xڜL=:6;tď-YٱwQDK.V}X:isPLXfכmI&M'Ml62D$iLUB4|m#ڶL.ֶI~dXp2>. %65/f>rҲ2 Boi2iK:h";' 롣I >N vɎ߈XZ 0)7p\UlR{gbOWDFwif̎4lksz Bf#l]PK8D tAnalogInputFSR.inoTMO@ﯘcL)Nz  тP;qVZZqZT;*.͛-.p۞\`|GQvˊ OQko].D;Ck=(>zNNa +l, G. *x -i&#P0_!& 6&΅_9XఒؤRZ L&|- *LBO64HAj 3؊#9H ;Fj9I/*IR5Fh9BBȽ Đ|` N_{VF.bVГLYUV!-XJB:hzC+`[G[bQ(VAGs!+sy(B^Gv잎ᬯx<(U0anZ3.mpޅTrER玎D_{ jWQ*ey 2)eF+֗|!o6"a84`2M1٬ՠCSf 7 2>bJK!?*doiy~~{?N?hp)zހj !- sqx ʉo1Zzvy2˺Rh1Q7Iσ_v/鄘AFb3w,A?y]<&wx'PK8DAd*8PAnalogInputFSR.fzPK8D t8AnalogInputFSR.inoPK;fritzing-app-0.9.2b/sketches/core/AnalogInputOutput.fzz000066400000000000000000000373421250202676700232540ustar00rootroot00000000000000PK8DS4X>{BAnalogInputOutput.fz}ےG?`mi3d"J6Tzdj6$Q*P@5*p Pd&*֥q܏{\qa84&d0M_^_"s?|};;WwX +y q0.SMˋ}s?L7-×/ם^}몙>兊J n/:7兌┺zIz}0~,4љo?̆K(}yv=O._Mˋ?\ltC/"Gf{E?]OMϾ̦ӏu-nhKw}f?} h1|?꿙fbz ~ s_ev!_':UЅT[^e4_? ?L.ik/:w}ߴp>Gż7Ά\=P=TbYUUθy8kr}p1%!Oݫ0fb.]}~yI"D>>146P$V!9eܿvݠDA b}Zh< TPqљgС}'K߄5E  gJ@QWbߗs׶;w7Ż[:`כnv(u_2+v28_WX^yM?^I]j 5bE6fS}7_cjE%]=޲MK M7iգ"y%F%|D)BYV$mӻ. ;NIvp]$+M@5ely:jRS/CM֡S0[D)oo']j! ~+I/m!0l!ԈXC5^rNla[H#D5oS()2뭄$z ݋MYܔUr2ON :FvAX+wa$ f*֔n-;T._vl@#DӲӥ{V٩Ba@YzLy ѲQkGٲS%0b0+blKN[#HKN9S^194KSElԎWWWfu0VbjNILԘ0<Jtmk~9oKRN%̛u4`f?GZ~f@yTm "Z زCNVkI馲g #@ҒR/f=t^U1+Rav+"2Z)x8dK{tZpB*ʘQ/R98--/7\Ɩ6\wLXJ!cjK'YSȐeuG|σ6FNFGqP$qc*Ti*+c9jbɖMNΐm>:xD9+tYݽ[d~Z{Ou޼m秿W/y?]|zWwW^⯡bqcuϽ{,nǂh/XW/2p4!vzq]NW%]r7o]3ufFs08}_ަ&_s~-\W?ǿuv3;eu>}L%?tvϮGh1{A>?LmjQbo.h4zㅞ~t0,nFSn${b1ץ$6T -+9ا\pbDbɕ5rLRm}37)4IΛrMS@llmԢK] )z8jM>6icC4|4wmA0H^}>{5/^cduPC)M`/>-o^8XՌFz!w1gc6d?Cϭ@f.r(~hX\o1bE^~6n:,vA 'lU4 b1#V{L)[X[ٳ>T[P;ƙEś=s)f(9@1W\>w6};=ƳìhJ:ްαb'uw7B`@!j"-8P[x,OjaaߦWs=3_Mg[J=qB 4r/,`N1Zrˇo9K~xT*/z̐괄͇޺:;cÊf梤 4 1Dž/]JgD%SAd%E풵JCMvfsHX B )O!{+ceÈv>BqGgG3:0 tsyF;YlnMmobVLBNcv64̊sq4 +sb E>a3>yY_$Mk[o/έ%:YKv{~\XS.K<06c7U8/hh"q nUμŢgٕzWΓ6vibC7p6Jʒ-g٦ߖ$YT$W =8yvhYh=&Ro3 lyi [ϰ ^SyH1Xte{]LBs {GKZsmͤc D ƅHFF]YaKVGP9lS:os`n9i[bڑ$ +jIsŘIZɧ3f13|ϝU[h9[ gaz?dq90kG5IoҶ &ϛ1i0kی#|ϝ-cIK ԍbaLK 4"l &?L&oo`mlw'ݏɒu#0/I)D{LY[ ϛ:2{%e)p8:X173TFςv_uLYƍX)#3œ$260v%[-`rZ\SHZ#f #" T %'K3)K&A Ed9Kpg͢!GKΘה)_@Lmu9/*<-<,jEw +Pzϋ|ϝQe6XR5rڄJiKcZ$ڰPکgKx4mƏvc5ǐD+?v~%4۫χy₩Eһ&%wйGp6DRnw7:^|LCWQ}yxw+}XOpdS*E9nE+ hNPJ(Ͻ#jx߽I(>Տe sRo֐K?t}U]5'l..ziSN%h8,Gy䓌r3:$c==ac,D{DL-J)$rN9st9 3[ekx#\h=(D<٢@4КEsO9V@~3# caf XXlc/ߤ+'tB4ymu 1瞜&8B_8Ҭ ,Yߌ&Mt=h7 N1"|ʶ V(ts9Yesjհ-[p@Byڤn%(i a乮U:$-m;>ؚ#sZc;i%"L4Ɵx8ÍNw|n=yC: |enfV9Lǖ p$iZk'gj aJIZVlѤM9qu1 (X5sEfZv=Lhֵ83xSݒT>ѐ@JwҏϹ3Ib3P7i)pPZ R8C+para~ew8s$/?# ,m֭>|sK݊9dLR iiڍŊ 3hHe+KڶJKN(ϛ*<DZVlс%nE@g 51E$}(Y7A)!K>>Vߎ4AAmMkzYa=]wеؘ0mxٛ=iIpNZܛÉ99 o(SV+1g~3vd |ώi c)_&t G--o/Li)X"+sLZv|i[5a W `%1_Rʮ"z(=VacjWfmZOh)2@[6b\~q ff)k:'Βp,Trte+2qoIܕǙorݴiF{YtO%fcxT7DFK{ S^gҐ7 NΐزGd2_uT*N7\&ol_+n.osMk0lgMq}Vx#N~n̓-,lQRR&[vXzyE|OxJJ.R7Y7[7'Y&g_ܵ:j.Zfqb>J-%x#IzA9gTOnw2}ީyQjgEB_ئPjatwR9$ɗ[(vu{s"~>?}ɔJ9R7L9J-S*'Uj*fI 9RO>J+TNN;RK?˳ )zx-6KެrFrɳw;ۻSRԀNaQ܊{i۲}T]?j!x.nMahVA͞Q_>RT蠉6w!A_2Y+WKǎItMR'OI&sǫ̏u=ݸw%- (D2tT*Jg6Tt>u;T FldM˷ޮo4jz+7{[g &y2Vꣃ{RZ"cRlJ: + RS%8=Ζ>o-A@oRh?+5)J bRҸ Y?¤I-?zlH9=SZڢJdh\CԊ Rm7a-}FS+uac%k[PDSMT4U$1`$$8-LZkU6|xj1dLˋ~;LQS|08FL!&&Lʱ"kCIpRxzI]-ekCYHK[UTֽ-|ۄ慙`jb}13*~]*^Ρ֖8Ȫ>4cjKm(f(ה=V'KK6 QZvB4B!l elǐ[styvw0[ gtaooPڽRlv_a4)%J>atDXiAbx]?EԬqVk)cZ__I<2bi&lByk)~ PJAsJ**To:8rh%^FN9` "Ԅlѱ vG&sKNRe4,BZ{3r˹'Uk^kj:t1v Fݎ\j&-Ԥxzwmi[Gf : u4g*c%dm,b &o>1\HWV?*UQ7+|0}Z2էjO%J_S}q0xvrfKLssɤ|].n䉈)ueHFYf8Yˤs \,Y[~ӿr7__0G/iL 'hrUd׋%_z?}י?\w~ox2~z^wi_|yXܽ>~tv~ֿ =W zaƗ/EQd8;yraao G+%;.pG{vV!#;$Wx}GBh.=o=$4p8o׳$)SR xd(spjH*ƿp\p}IR(s5'B%~&&wv]@ ]HKb!!n"2RGЁ;#G+ilsP@KNS_D%n(J3 g#_ 9p־YLA% +7,\ۜ-OT9w -Tt϶a TR?fܷXq!콫2hDZh07d*|I+\~0@4Bw*a|*l "^B-Pv(Y8u#`cLrϏv ɤ Ag)T U u:n%5m\OE)-S^C vu4,SS$@~WA|xA/h "-3&vʍ>idq-Cd]/J/%$*0 s lr L3'`^Va0 YT Ϧݬz 4"8^`6].mw͈y  0Of}!Gr0@KQ!_=s$-{S"'t/e^9K,rRULH,ahƷPa z%:`[Pycc!IΏH5ZcZ#] )a"b̜P}@44KDfA) onxO5)܀6pSP1g8C1wz?ckgK\;s>s8:z޵+4eD]V Lx &Q_%H o%qDxq)o"y{ Rt7E& Өn^`)A"60NXVwcF (Q^;n~ ]nhr ȜG#3x#tKLΙHLZc T)9Srl (BBf D&@' It?Nc5o<1.thBC-m\f5 p oǃ( HS >>_ }MpCܵ7nvsl+.uۑjt}W zo0@[EaAL\`5 h@J1,p=+dZ]@P yp4 ptP\{"рGCP2lB0kVk\,8w3|!0HRm@f@0b~>U1tܑu ux1 cC\Fؼ𦊡ǀ$Eا":&DG த݀=+b h1 QC? @@Qxn֫~b+Bɢ!2ipKACK@ f DFR*uhj0<`r4hKD@lk =ȐEcj#łO UTy`c.)!#Uԇ::hG`H xxuWaFK ]Pq!f@+5<`SH1} w*NA #2PB8 XpA`8 'cޣ~-h~tD1|1-" DK?wM'BSܰJ>| 1\v -UeA#vAX6=w?VqP3 XHvSS5X,/.caImqF QU&y$ dU]L>-:1b$vW 0n gFГyd$HUDbaQtl8I1y\Hpz+†pXQ `b郣DbFC PkXĂڀ ؿ5%t A"u\=Nc= {`eHMp2 {%< ];! /I"tиSA4Ԇf?[G1RN@z6ʱ/Ϻ86 $GQ2MK:0r8<Xr_+Y {,əϼ%9"azc$L7m +4Ex! tg0l ސGgwYI1` @쑜D9g3OaN}b ]{z­u=Ph;bs7M5 `i C^L"֔U1G!'LvS0 \#J0vv  Gǎa4 IL~9&PwvRx>JGCnQ4/* D@01y>:W6"JL^sG5hbNvYSH)馾|B $yBB8IRt!p~w!B3"9T*"(]x&!浻aohڙ.G%cCѱ0m)0;|qe'L` WAwFkNϮ}BancŘ.ϓg0 n@Ɂ n/{ʊ_cJ}Cc:{p΀Ť9L0JLwyKA ^⃄kX; `@"8Y# |M9;DHnXIk ꦡ5Ԙ88` P2$%LDD4pF#gX > 0ȶ`a EX5O66r@?zv`ft Ma; HWA12I C]s#1ⅳ19GUY<]hv͢ AnArdЭ&mq>qb«Rܠv) )F4 *Ǝ\@xG)kD!T6$P?Pm1;a2Ҥ ̗2cL?@C0gI@hu7+? (/P&ʄah4Ʀ 2ݡS@0X^x=h[723!Xa,D@Fk8$R`NM* ؅!p t$FXE1h|Ϣ~)^@8ULal[ujxDnwkY>@4Ag(5'I`m^l(rQ/C{$v1^j #:% s.1GxQ`Y_溻&eB`)8p$IJ^]N.ӱ9t89C-~P |<¸Q:0"<8吨&L6#i hC)9(3( *Pa8N8EF{ @(NM5 7B `>xdSDyPqR*0:8A0$sEaaEhDz؃৶bMjy(n}!T ( vv%MN_*{#LtsOi~4l z*e>Qps$R/5i:N> ll:=$QoAU툝*?o#Fe!̉ ^~pHpgY(Ju <Ѣ̼O 5/  /v3d,5cYW̌XQN)RAL߃EUa!{P-ph1>"ނP{koieǥ2UW؜G8`Kէ>Fk ew/4U|͜ 5ۇ5?v\Ci:8ڧ\ahQjPe&T22j~*lPyN<Ѹ8\ p2UBS[' \JpވlM_)FL! ɳ'~D& If,m/Uri6@XXkX Nh71Ͱ8[ ].&$R]Pfy2oCxo<fMJcFa7°Fds) eY\K0 9}szsN?G,&&WL֔0YɪL:`c yn,'E3kZBB.J*wQhy*0b1$*$:8q2Va= & N 1\ DuLi(HX +ⲁry,XΊcQc5$HToaT7?Vf)fy0OۋikC`#opR %Knoxki>>DS‘Ӧ) 2O!v~=Vzl㫯 3j{OZQohJ+ %oЙ:/Y%( (XQLlN٪NS"OLĤ4D\xEq"0(bpp0s_:È . .FNAE0*0 :SѴ`]s@L~ep{`/ Q !'Ȃ%aLuq 9ISP`j+xa&0턹]$~+LHR6 6h0‚אЖy]PլZͺbѬN- q0ɚ-a .M-c0QH^Fهkqp.:xWyY`1V2 /{C,qp@\< Qox儰oX On5jSV8o]׿$$~/~] ec1~cr8r<)vemt6M_ ;1XSܒ &Khfdx?~Os*V{zߑP< &rh0o 7t'imNU(AAL >Uû<,v,h2?_>dCiHel8,}юh.JFݿˆ$LIƓQ 푙߾ʟW{$sѡeuJC g='>HSj+*h.OѲm؎v>hݫ9_ŖO>ze vISՓ,B}^T#7e\2'Nnf`#| _o6}hTd)U8o6αS%pV^!4_˫enWආ^9i^r(+i4I?U!ZUs s6mZ؝X}pUtOsx1tyѥ;izW6@GU2ֻŰiHn0u4*6ŪOK%ьR>@}-8u lXCkBMxGwSTCϝ6/?"y~jP9!}>>1?3Xl+_/ýYO|>9n<܎s?u,wMLS\^3F0 C rX8IIsUuN9yyϹ17sz8i "3jGĸ>|MlSxD؆Ldj'g &E{C j`&+iܪSX0lZb* v?EFt%X#IW;%mUlb&W3Vp8RAd#T;+VP6U HRSli)QlIZʶʦ+lf)Te3Z #ʓU'ͲU=`Ț +׆J endzbH$Q L-+ZMVnB*eL #rHr(_0,P/OpuG"C2%-͘^Ov!ƹ':V3&$-;,amJkC E`2cCIJT(lw4 nV}>td<HfhY)!$ LL"4TF9Fgav#Gj݈SMJV"XPRk遤fGvQ![N>%z)S(ɌNEc`@ }^3:9&V?ٟVo n%.JO+ې.Ƹop +Y 5d'Jڬ݉Y35 r@Z#2iYZѣMڝAZ*Zۤ,!cy=evUѲU6]Wl͑PQ'dѲG;%r}w'UXTwKzRj)j'R*R[}ތ4x$om&]F L?ULJϓ*A+sK@YPY-xtiLx 1 \1d =iiY(ܣg[ڹ5m{T*-=:H%DЄPҲbk 剹\W" 7OT;d&oX0bTKߪƴ;nV#x[_t";bvȨ@͙~mix b̰!~Sgo|/>+%~ċ6V80i4 ի[q#} W&6tcbҦ;sQ&!.;sUOTgQP`)SRTiS'vnA5LJ E0 R{BAnalogInputOutput.fzPKB>fritzing-app-0.9.2b/sketches/core/AnalogInputPot.fzz000066400000000000000000000336541250202676700225200ustar00rootroot00000000000000PKH8DVT(7uAnalogInputPot.fz}rFwj#힉qvl{ag9%"5$[˜g: E$^@  P/*T}Oףv0 'g\nƗg$7=_噄˳40OҩLgW,˳Е'ݰz2г+N{B-sPзWlw}ᡁ RuU ڐ,˳_t340>| g?Knzи`60 Y?7gz.?]q]e-mjASQ`Z_x/|94cWëH3C}99xy 2% ALAN.C\ C>ͧYr=Bd";KQ}xM?F z >6x.Idp0]SKojjMT3[oLe nNȴ6koq_wK*pv<_UbTR?B/>HS4.kͺ-Xhn&yu7hZQhN9?.?]06B]DǺ"oӟ |f#psMPElj9uDM3A%h2 4W>xۘ"J}7@#xߥ1B8vc ш!nC 6C8wی9wpLlaQ|c )ަ1Pw^w))hੴT Kڀjb{^ֹ#U!j|/ՙx`Jtek8? Zbzeb(* *Qk{S!p*ҴE ?=^z4Rt^*K rRiNeÏŅ[[mL\~sBBLJ7;Iuep뿜 ̋wY 3KUEBjyKH[Hyn@yTo "Ꙑ C%[F=-?9JztG[RBٌ)b\|!$әfՓY10B^Rz Z R^E+'_*MGR6Fo~2O_ͧ6C""bȒ@٤&p63wN`p5߈PlТ2Zhy(EGL?x$%VGNaNqцv>]QG9F%yЂVͼNZJ%70ْ6)˄@o;8."Εl<'|%mYK5 b4߾Woo|o*&nWtUeot5o^t?~>l2wҫHl>q9_?h %8DqmOIOgxClK`^ t u"ҏWY&]3o@2'[\_|//W(vt/ }PE/Ɠuo&ҾYluoz9 vM©bpbM3?Ѥ{: <gJ@Pld~5%OѠL#Pir}̒t!HP|:pyɗFp%o[Wqa68OTd'2dr{ݷY`Μyz4낾k~;wvިK a|a^#jMbA(A0,C44lTEEZW,WGF ذ,=e 6eb+2krV=$rWmxG.%,!-"3 &NIegʎU:ٺK"+u)amJu Lܫש1%b!]W|bIKF)Gz[$z]mɥ֣ɳ뮯__\0W/ É޸{1/kn O/tOCf: 8>Li3Ĕ3f0*8"pԶ,+6 *3uǹk'a4ܡmgyo*l{d6kv@Ƴ:D9r98tBpZB7H3ok_?":_;p3-m;?;$5TG;y%^׭L|<̼]JoDfpp7Ȝ·0'[O`ӓ:0uqB#$FSxg6fpY1S k@mل->9[VӆeqOb0Zj'֢J(ϖC'-{9m5޸pn{gΙ;sq.3=0޸ãOuot[m!<@/2)Of$|zӀf8/njLC]mw̿=1{U\'o}R:hǭK.T\'os ,k_2?nojk1G-Zoz~=j yR"7y}ܰ6S_OI)鋟4L?nSܡkNǭMX:iǬS#g<:o1.3} ܵiiw~Aۿx}i'ާznzv޹}YJsMqʺs}& q͊MN;@>Dst=YC?)iṠ*Dyq~Q{x}ډi⧝lnv*~ FS͔qʺs#}ifsMSN;H>s=gc!Q_d{Lׂc2RpzS~ 1Lg5!2ߘrk㭁+ueWfED Bqh}計:SDʜMInUiiQ%KC$+Y]ñ{_w8j>0Q ss0* ÐOT:% f}'DƔhI< |[ΦO'w˔ʼ)7 `4=E@6P ))#{J-ďQFI )-'mAd~԰r8jj@M)'T*4E(Y?%|V>!mO}`ގΜ4: y߹j-O]՚A|YT(xim Ou(E1!̈́*U=6-QmAeMO5싨CBJKT[P9:5쎨JÛ~'T`t,)Slv^UT68 e_so染qz ΒC̾"17⡴G[Ĕ!˜",ug5m8889<\?LX -~p}Q0êڭ$o%{mg{$gb|rl>DDe^řduU4<"JƔ5B^c8k27 T^rLPAs7s8R#G֡;V)z}zyvot3KÅ|0Mo&s}B8Ob˵l®{@is~wo>` 0Z>Aq8?31zhvl Ҁdߣ*VսQ͆j*iɅXx|;4Aq+TlPx]b ePP̓BNdGWn3"AhA6ϔao>l0ɬAgМU$[ %vnpvD_P.ƞ= ,.=irNf5T6 Vԭ UIw5/%DI;Q}W C;ٺL JLs%H)30d1"d6[ 534 '8[j2F qըms'y`&Q.9ǕzoBmls4Xj?z58/>\N~]ZȽvL-  9 D}ϯʱ'q.w+wo /& sLJS3iM9h՟?]t6_~3e2'/?/R埿ſsow2߼Ue*_u߾6 x߾Lo^t?~>l2~?\ n(؅nx4~0L{AG^$9$?FfsLBe8;zI(Ȓo> G $IӅe$Ƴ_drEtt=Y6Bͧx&0 o^*P*h) Jͤ aӉty /ߕtyP.(&X{uxy[(Dr:0KOjjen B p6>O݂KTz N.\HėQ6t,swX)ñJeLi U~;&Sˡ| pV`%3P3t%\X((D뭅f x9.=_'<U<b0!ñ-re5Hު>俸p0q2r%t3mP /T`W y,\P.*@ =yA8lx<^+yeBv Cb }١T<ƿtxB9Q>A C#5L4O[$;uA[2; ^Jc*43 1r#]Д?6e `:`1CApv*Wu*DD. }:LevDʠTwg%AoϓUYLz>Wp5%T.; =YtϜd` \s0|BBë &ޅڹ@QF̂E[!<݀(F *(C kG(ɯsi-t܆^ QYu 1#w1G.?k׈BL8zF02Th)–œ6i+.αoi"` N@oA OYfi j:3¡$$ BSaB=^[sc_,ZZ\Q貪O$ ?xDhG/ hq8v7@POg9moSTS. A2пEx@Wje_,HtZhɇ^ 4) ,+ * K5練)UG+Uy_Aւ|Ac)LۤviʺP1Aa{"'em|#ޜ#xȢWUJ ,5e; ~rcjȉR]B@F_aQZ8v jHBx\@c#*GhLF-W60.Л4Vc>2Ǻ&DC(IႧGpv^𕝀ThJ!|@1p G'b1DHu#|Q ;FVtsQxW jS7 * lqׄvŸU}lch~I [hmaG*uU"W.4&aI_R"L 28 @\ THc"+)!6qO%u}@k3x&lbE8}=z\ǁ܆{ATwD4wPht%eDCuVA5V\A Ap+W+Ggm˗VJ++Uh~.5v]\LռA . h!G񒃀)d6a*cpBeA xF.=|)@L6cpnUw*VV`` x~2H!-P}b차In\cm՛sʆ*rg(_Eا 2qڒs"K&ID3HWEP0 )@=L/bhшG2T/Jl".(55H\ L` (d AY{ et2&wSh zgnHg!(XH@k`8v?"HARIhEԧ*&:&LD'݈=ş+1hR1OqE8 `Hq|n٫`bH%:"%"8*ƂJH[Z 9jзbAM4 Bf$B&R)tlj(=`jJrhK̐Pmc{F؞d"3G(D5 Q{-c/Ay+!Z< ARA舶J)($?&AzզE=A BG)_u{Q>Ғ4aZ/ AJZ:!,OT$fU KZ*`|`_^9:8bA! LY7Ja^Va #02FZZV ^!!b N~0E$&E" C#nHPȊږBNC ]KMBC$.VNQVI|l!rFq0/z9nb/LB؁2%nJ+ZPLAmI`v`+ ). jg2ӛC RLFIA"+`+I  :XTp#4g\s;ү7 8D"[5wցO['5Lճy"z)ߕD8[A W&qh =YƣF ;T@0ՍvMP|/]0NP1L`@)`6 nN &MdRn e!аSP^^cchH9COGP^trl4 "GQuq M 9m%g#YP & xC\L8mtm&A[ g]&,Tʄ,癰lù( cr9Da0aQgJ/T Ef[ui "ŔRKJ@1hϔ0DcqL`A޵!vgG:aj8$1#A0f9'!hG[ q4x\Ď +'ٝl*:Olb :yNK ~0:A;)j@qI4/#ƖJHaJ`~_٩4wtjx'; I9 겴+ yTSE )gi~ P8A+r 1(0~uQ!"ɪL!"S.TDoڽШlp]JfS`(+.RJyivAv(D JP̉#惯AL*ޞ"Y>qRޗrTJy9˟!(Ջn4leẀ4W,f12_{JKE|qEY3dHbgl9=UoID/% #A"3 DrNQyqIGl3ԌřFr 98iǡmO@iF)X$\(S46--KXે92Qd*N,ﴢy)PJo"{ a1Z S~2EEԩbw*iӻ+٥JCWJDMC Qi2+ `c f\h45ƚ͵nj5?vyCMPu:e$BqP RFB""TʊPe!Tg#GJt1g&j "3T*=LїxmK *ܲHspJ=єD#b4AndF h✧|(I,?fJoI9ɝs 8b3IqTC):XhNAj{4cLW RFP9) RX*Y|vC}[QIXOW}#Y}PI5'˗ȣ8!*e {].&BycR %v'oM8m_[Cr4;/Dt8}AFs8 6Ń_OԼ&yS|jx̉JƁȕ1W5*,3_3^": :kTp\Pp~Ucي~q~DLLAiba%fc8E,uE|-G!eNaE0*@#(!:BSɵfE䤣&R4" Ї1g@xev.lj 9- ?6աOO4=~m/l D1 ;.?+NLR9 6(BF-cȗ<^F^PQW KM Ŕ.xì,4df1GHi#d*ʁm"2N^ҿCzSū '-{o >']bkԛWVof'7m7m~5j0mˎc7Xc||ϟ2s2^ǽѯ + Y5fWzqI2வ٤&nÏoiSeo?`Lal'@8f{溴͚2!K uZP@L!_є$E;)?.syBVvl^g>~7 m)x`V{@Xm׮<Ƴ:洇55[p8D 99a!`? BO OYB^G x'wuwEH;݆xܵaVAՁR9v[X麭V{SĮ{5fݼ^-ShWø*^^#:u7Ngxn5fכ~\Qabs%mҦ~MڀrvG'1]s\w!v,l¶vBVQg{ٓhoeaZC5xnh2K\}Bkv$<2UZ ,kw^Hlݣ7{xuwS}MV4;6U,o V\Ţ-?ʀ Iq݄L#05&W|$`SSଚ^鯣,@})0Yr=`M ܏p+σLnz3Nx =_[ߋz3-˯j$nPQPOChzYJLmT/L8;y Vo 80Xm"e 6z@Um&Ni\x^!ݣi%n  C {KI5H"T|(zO1Ek%Sl&.~FZ?+ ɟYt [6}xR'`u ưۃHsw")V?GBs`kX.ߢ 2z6H>zFYvA3%-%9pl6 -c:1![*hibkv"?0$k˖Ex#9k٭[Ȣx\o$n/ 0QiADAuLi1"C'ᓇj- l2P5Or7m|{ Zϼɞ"Cn3\s|lLqek lT&x(\f>?Q=bH;qY4Of6B:jMH2Cim(>)J֮C)c;vl98p(M滨LHf6 hYٺCvl5GٶV=I"\کI0IyJ,KZʶs$i)ێ&0E YKIppl`VT.fO (7冔u瞾ZvcWe6SNl<Co^ $-9*Ϛq l-#ҳue|=BH̖Ogf,R3eiC;29%~ F[F ?Z:shGϛmx|H-N4.ٲ5e"bkv$-5[VƧS3y`j&rE֊cf52l.C髶ypC[m 73>ZrOxl#GK[{h 2lTiDP :ԯ n5$Ըe&;v~q-%|R46!\iR=<˝K8.U (mjp& %*蠹 Xey}%?PKH8DVT(7uAnalogInputPot.fzPK?W7fritzing-app-0.9.2b/sketches/core/AnalogInputThermistor.fzz000066400000000000000000000354501250202676700241120ustar00rootroot00000000000000PK{8DU:AnalogInputThermistor.fz}G1wȩאJ6DR=26ŞEQ*P@5*ZۇW'Q#3Qɶ.%_G`:N/hB΢?9/_؜_ߎt8]>AO  t!Ϣa_HnƗgӤ7=_؝'dz`t~͇x%;~}3{㾻~|~L%Hg`xy5q&8T7PwF OD޵{wp'ϢOd48;.x9EY'ٳ7^O߾뗃{&W|Hw}dvozӯ?}_u{v>q7]8~]x;﯆ǃ_|UjW=/\]]S ̴&/x4<>|yq aN$7=_`6wvoz۟Lݱ{:P .߿ͿC/o_{W7̿WHHjj>y~9̓]Hl>r|]#:_="|?+| BMTyJnlՁM۟>_ xvTyt3ğo](/-[lȧ.DEz8/w4ףˈ= WgNkɛI!-Ǔuof9,794' F‰)TǟFi؝6~A%w;wtX~ ]w|hJƑ*KANUj;u3o kJ_kGh/ 7p $Iˎq돹w50}N-ʤ|WyrpuZ˒YD "W({z4p v3:[>Zԧt[b0biK =F?v,-ρ/BVP .c]w g7M J>hq匟ji^yEO*2GZR_aYڎ93d+'Bz' Kud*MBC|\zυ@!EɄy%"DЇ e>sf(C#>yf[Hka5FޚT_C' TI@k 7i#S (H@}3 P)NtF. k5lc5ƠT_s7 TOM5Я6?L;UΏequJ$D oь}|AlI! d:qԻj#oዳ3uyu~93=<1WzNC$,7PY~Ҟl]s_ͧ>Smq2?ѷ )>a)NYZs5_+"!RG߯H,_ .K,Bǐ-Όm\T@FX&i{%)e_6Lfш]o)66K%3rRdj5%!4,h64?tH$9ǑX7_#!xCECG>'WOhGKіwhbE_&栓R}c"6 d٤ehjsh䥻Vհ38I&3qd9ׇeRExs8L mIFBVqtYוqY3S1%T|=jHFL$>A;gVX_ݑ-+ SE^\ZSf Kl4X"atiyZM"1]xDc #myVyU.&?-۟$s}(.fT'%&8"/CV,aqE^ |%V2L5lojO׺mzmjn4ɉ~ '8iYeas+4=PL'(vu۾%=d}rdIN;_K7k'vvov0V e}rIk'xuL1 #5k)fGkjȾj#}\d~N>_|t~>9Qt 'ᯩ̛cCӎRO;_O7;Z?X-sċzy)ň-E~1Zģ5yXmɎZ$;RKɎ(+O}}a5GM_)3nfٹ_WOUZY0f<_ jl>~Py u؉"hn|X[P*wU?Wx³<^5q-g7Un.LY2 U"~>D&]N )v4Rznr"n2wIiBݿb龪Am,T+uZ |kH m +4URjA*F$D>- iȷ@R} |g**&b:IQw@OETf15H4I+mRIt0)RPn?ݲu-?;;v~عe,5` #|d Ro[bʺI݀(O`%-4I[CIKRJRm_ /$8*-EI _4BmGd9*e_}+ ۞ ,N,I78r=Oe:10M HïT U ZW׆Ο*-+B{)XliKŽ-ɰf#読RZڂJdhX}UU1_؞P*k2'-άMKIXf݉6 $himȪ-e-EK032ʈV )bJHij *ya:jVulC{T!&) qU/jfd¬FVWHP}npOCRU6V]ڟMMcTPR&TzR&K;ZzpH9bO6CKi5 R#H>d.h(9u Ǔxp0:/!q ,|ٗRٛhܻ8gg]ot~.뫗=K g>WiCM)՞Ufa^>\N~],0B6̓{=t**W 5 f^{_ Wypb¹*{Ϯz7oFoz9UN/ф<g<7o%z_._{Wѳ~:"-w?Yj>y~9̓Ӵws5ϺƮ=u/s.baq4=7ҟGߟO> GNET%$!(/7_ 7_™Tӵ:tg} *{WDFFܤ&^v?*)92s`zJy_Άg`0;ҭxoD8tt1BiY;L.$I![w쩡$9_QX&]g;ƺcʝߢC7HrYMN!_SP)Up[u5oQD15U+PAX0Hh}{A+@ 4\wie`ˌɎ]r#ztE_!hMD ̂\I5﫰U* U»i'/^A weZ /V0X/IL^;f<uzne]%@"FACHD +nD^FrcM7M,3áݘ+v|ҵ%-vx||ڹ_=-TeD]V Lx &Q_%@ J+R?x1HeB('Ly}Ѧ،O 8 c[1ލA'LԂGYvɝ{7)hX r)G# =,p-1` 2K"5j)P%@L+Z4j||!:5:aHu~1; 8xBF*4/ۂ%@Y@ 0 |1 :co5* FY9W;꘷#E]. A8LgVnyM2;V8h@sUҌ@`A}Y_ w)88!/`gAGg 0=<Xct1_\elo҈_"C1 p , dt#&w[Ci XgPg(h,I@06uvlqRPBxǀ&Eا"8&DG ੴހ=ٟ 1p4Ř@E`kLH(7U?EJt qJd_x0fL=R`P0d{@,a Y()FQJt]1F * Qd *4=ls2t@`Ȏh8Cj-FXn rJHc!ꅎN! =^]8UOCɩ_tZ^ÒP5aRfWLBt1v6A?-!zqX2G!(U[rV2 y{':7 v;OV;~,qt$e82 <)oy <`"g$ }Tq2yHT$yCkD AY`@[˩0P]0Q E h+H>8 ?A?/X9`nϠƄ(#7A 0.pc@^Fha,1n+vBŅNzl|ygѧ#c(GA;#h(G4d$pJpFmA O5|@zm;!!؊qhz@t|Z4-UU^Cg+@{=LMa z,hN#ԑ4u8пgkUw 71t&!0+7)n!3E, @bi a aN"R9g39 K]{\­udpDh3X{tx~ 1q_]Y^8M`` (}{U+h.كpv(N#Do'^ (qB$368}t\R% ҿ׀^h@$ \òCT!CшYViן; .f#A"a·ws')1*PQ' ǥdm;Q \H!?F/ f[0ƇKp EX5K+V6r@?zXvx9;!+0G81vcdpX;c`Gb Wc rDy׻ BEO1܂%̑AbcЛڷEhXյ f(إa;k9Q6*HPy!nC&G%@` r`:>ah*I} F[w{0aʀd=Be i )  o;{ew%֍LV2B< Atz[)oW#vb~0'0xU e9+i -2Fs)4l|0C23wX"4e('Q_O^"`a~m='1R[J! -m|qq)qUvǕ'QTCPp\ G~OL(QܩV|Pk|l5E>D!ִ^N+ ;-š~։. U̅X.TF B / BE-*/gB579b'q.8SA[M"@@w୓ K %?nl͔)P r|}#c.ID?"xIf,u/U8őlT' @ʡNjaq*\dUHc8@Q8+Γy[;てjRYk@?1 O-Å,.a(\؝0Ao\sC`q)YE |5%L$g*Nc En,'OE+c\ZBB.N=LZ8v+`0w~ ?+~ )H3tD1"kc(+z wWA7۲Ҵ}]%de]k\G3S8HD!Wq-s`1F`r0á[\o?Im0Eq,Šm ??Ma,XcgcQdcU$HToaT8Vf)fy/_ۋ.dg #F2तCx }b‘fS<d0'̃+[X#{pXI{mq>񔘭j8J MIsAeBQ%3+A K wVZї-7[vWpJ48),7iܧ )\ė0b kC,SvPV @Py@Gp<,d;P%k>_9== p/ Q \!'Ȃ-aLup 9IV`$p vz诰#I" ۄ  jä<ԯ%X_uU˳"83 EC\# |=(w'$V,keX[7 1(L^E|pp18qBHpt2̫,,8v2 _(82eq6q@/hn?D-Ֆ –?q7YSlzځe v}=>t?f|K>~?ίQYj8H;*n| $TyKbV YZV3ԍ֬g8PGkvDU6 eY%uYCLRT<$Y@2G-Gch30ĞTO7GeWcjGL #KiJQZb5mlC+^ \B#@uWiӓ z6pO=թ_ kW2KiAWҶiVKîi^m6xU؄}/o+GEj"(޻}q!n+Nn!XxXLiCGͣ"hu2GEk߽͑v ]cwVUM~=3ެdf',Por`nd Wge0>CmE`o(2XXg/gSs~n+v\i=,SL^֖Z?mRSYi2O_ͧ`,{zsPx◢KH.yU1,ȱ暽F t=1Ir^ UG.p~],s2gq<}2: ?)Nˢ#v,YǏ-]24(mb .V&!ƒ WbeiHՈ%Mejlu6"A>oMqƔaL C2 ?)I|b=v}S3P92Kq(f RIĦ @rt\!c~xE|j0\%VP:Eb˞?Ϳbժ)ľi@)P,i\tBA%g>sX(k,==\n3o&!4c8nukV[Ƅ<$tQwMncJ?xH|Z]ZstlTGX5;x2֍p.N]I! {DvXOv") !GwjJkwKq=d-vɰ$tI꿟$gdRAL|KSSRRJXw$3`z16-f kO4y#ڷخ) v]lu80jcD3~_aw..d,, e+ukss}r+u.JvSa=aۄm\C}UʉVDHY/H)'BI{dU?%Ok S͗TzE8 kDTَbϝhjs(x\٘`%$-{փY]hOmOT%&DZXgj9.ewXqB}"ҵcZaQ,.adUT#8Kkn<$R8i *Q3IJGclahһc[J݀K1X[O0AHs6#r6f*lHڸU2TJ9*Ѫj.Y\*P#!ȓe'qTM(ni6>'Z6KT7H;ɶ<3aU'z i9I 80/SiJ>SS%nuje,[im| ϲU '-i;8lG3FF> $8iksp,ivܪNӍaoz&8uawȖ $UU9}aqRhiYeqG'Hڍn$iybmNqka}9;x%61bUŕ asj|]VT`8Z*6xYMkCߖI&-;"dTU SL6l4_l#O k5k7`Ӝ)b %mcE;ՆRQZXVFkȣeSZF5p_&CC刟2ZнmZ'gCk4u4ܱȘHe霊$2C%hTb( mx҆jsph97PR=+)M5C1_`9$e샬jOS]!*R>*'l-]8R-[[Ủ<&8a9O.wXB vb~vJ^ubb[$iAI $-IkIZF}E?PK{8DU:AnalogInputThermistor.fzPKF:fritzing-app-0.9.2b/sketches/core/AnalogInputToServo.fzz000066400000000000000000000360431250202676700233520ustar00rootroot00000000000000PK8D"q7;$AnalogInputToServo.fz}rGwr"tډ|V3h_IA@˜g:U7ĥ`ibPUe~uoǝl>N^^Д\tr4~ywNs5-~w IД~M/ܝr>t?^|H7Gi2f4_^txOKouW߹j&E2pityyRcRۋpt}xy!S8^֠^Eޏ*_t&[aw_^t>]Ϧ'Ez6 Eg~3I'g_ǟg'wO޺7b4xLw}fv? wӏ SWb~3٥/?;|w36?*%S(Bt ٗ N <_~P_}?/fyv4vM= 3F/DNޗ kb>6R;_7)Fmvf7+]M8KnmlܷB.8 NוWs.s"ZeM/1G"V(nYo兦Aye3Ky+_*Q*D .{n8 olN뱓kNjHHV a$4MZa4u $ol}Qe13bJ}÷ֈޥ5  ?("=%P(DTҗvr\go#'!$@I/^o%(˘Nx`WvʚeԮS`& rZ .1`)V=RR٦Fv\ 1'!NYe&6U"( nrigGOgKOENS!xH pRUdE678٩bLNM'.WJ<(Y<,KR2ʬwFN)5] JiܔGG5L5Fj5{#mI Au?򶅛9 6!i9̹ԋrdTnyғǑ0}M2G>=6R&% r6 SBOOPGR:]!Pf`wnby_|_v~wo|o^{5*R}W5Y,^z>}J?t:X|1 u)o/迅kٵ>N;twNWe_]v7qGt3Z l|j{쬢^_:ss嚙\jytt[2:2>|aﲂ`9 AH֋tvNw*o$YL^bz[j·}6/]%cҙ^upv?u p_;B/:^R %!`Nz4Q68(^45"p/* e @ss6?&i+i ,#T{O tOyy}| (OXA=QX"z$zi9IE-WhޤPrJr$i -X,5D=`*էIĕ;,J[%=2aL)'5HRe8MS*9Wڼs'nN&FJT ՒҊկR<5<'!)ъVVGwp@yNF7)\U|$nJ"[;80W60&Z->REgAi ZnN[}vZX@ 5I)u>&$K qMkFic|fn Gas<'x2)Jث6_mꗴ6vĖvQb^_Y_e 'mǥM +H `oiq 1'T9$C{u oBH [߶؎?Y_3Q\j~I)"W*V^%U? IB{?vy< {Ofq8wa<9;syLx{Al#eqI|I[`*ŠhOVi l){FCIZqr5-p~V"쇟gYG6)i9 Vq3$>*Nϋ_ϋFOu+WeX=}3$S\ML+Z)6V\-Q[-3mR⧍'3[“sNkQϋ׵\ώӵ8Fi'XfP*6 -v3OcP<2>/s A9-WN^3W:f֖}Z}k?wRڜjA6矿jy2?mTٜjs}^}v~ƹvJ6>?YSm3hhyN~Y֩yўўiwn+nʸŦ26lVdd'1|TJǭk<y|**CNPf秪ѩ1g228;u0ugnMZz&ǟ=n2%i= $Tu :urLSUD\8ezZp6\h5-DKX'S \/_rOVv9 gRHj@JOnP7k>Sd&elqzuG5;Ām+[~F4׷Um4Ice-^%BpD#OgSOQSmyjӓ)Jc<#*e<ұjdpLk3rP,rM+|eTb= fޘxTn9ՓU!7 IwV24U$e\U[ +UZ$' *˂zxmk0k">fj )svZŚ<`"U0ra3+)#٪9<|<[eb )^]fZp̦ HڄZCḱW,0RGӄ8:EkFHҎ&;fH6} DVmA$fԪ)6܁q0_CpdD,tʹ14vMqZdPRqV\k)D Rk6 KJL}\VHq㏤y!Iy$yd6Dvxs $fwJ6DHe*2\Y *-<ڃy !&j[s 4M6[JL-R ZSj*#Dh;&#F'ܭ0a$rͪ'&[>`UmζYl%T^rJj8]#I"uh'Ez-$uìM,o$RM8HeGḿBZ3p5%P::Fujv[h> »rV=qR+|J-*| qZګm)K^EnY{q Ѯͤ>q ХdzmzGFx`{=g䟳MrqS$DJ[\D-~3],[I,4s~ӿ+ru_s?G˯iJ 'hr돋|ǯ|J7|3u_z߽^~f{})ìw3{`t7(M/_W+Kpw:a|_uJIJP靈EI'/㫽踂CIJEe$&_tj!7@G$R*G쇻LѽuJqh&v^鿛tH7Y^k_GBh.=o=$5p8o׳IV)~P >Ԑ˻~]T8fdd(-Q |tj4΄KduE(eu$$5vIB]g.Iںk Ixj$THTс;G+i hwɉr_sꋨ EildO?k(Zf1(𳻝[INX_TPrA¸f% kŀtOT7V J ~_("Ѭ[TnD; m/I5;mܿ4e*eB ׮ /s/=ow OvED7odz]WJ.K1 >+.3 r'ԡnE~d[*OjF8:tAj/FBw+yi +Jq+nBJS~{a w  JUP|P/[%eˊȝ<[gL2וN)n%NgƟE r[ſ7_s3}nʕ.a TR?fܷXq!콫2hDZh07d*|I+\~0@4Bw*a|*l "^B-Hy(Y8u#`cLvϏv ɤ Ag)TUu:n%5m\OE)-STu4,SS$@OWA|xA/h "-3&vʍ>idq}d]/J/%$*0 K lJ L '`^VaU0 ,YT Ϧݢz 4"8^`6].mw͈y  0ONf}!Gr0@KQ!_9~pYĹVsȩW:Ћϗ2^ĀE/DD%Fx*&x$GV؀C4A[(-0vyI2a0-a(<,rDAA$EG1zEʆHJ}v@1fw G KCHdt(xQ+;t{X hS7s~?s؍kk];[ђkWw ])%ڔM_gB{`01*,@A0,~+# ‹KY$c"+)΅6QOFuM qǂb 0O@_q{w7oSjX zGS2eF<Yx4X t Df SjL,V2d h0@bb5Д!:5:aHYuj&yu@Y@ 0 ^k஽ytt`[efK^QvcގTSuZ;q" '/ d;V8h@sUҌA`AY_!hhh0̃3ՠ@W܈@g3l0=<XV`t1_\el i/|Ez8~^l2:;𩊡㎴3U34Vh :68vpixSPBXc@x"S?X`ڣUpWnBO 1p4)Ę@U`cNH(Gp;Z  I!,vҠG0Q[31QVmg?D:"[9MOkt@t)nXeK q DCj ѕvL;T~SG ,CỀ^¸c(Й~FYI,@)z)b,bkV𰤶8~* z5'WC@#u`x5#Pα+!!P ]0b 0<9HrfrœŐȻ|9[zvg:nd9j 5# 0D)' bCN킫?a,:?}G䕢afA4 Mj~h` 5u B rLxp/}lDv5j̜1 첤+S,}H$p]C?VׅF;gLWEK"e\DQ!!:BBv[-kw(3]Jca0*R y#avʠ' NC"A N*"^\;>^;8t11],%,g`ꅯ 0^6^ t.Isd-K?` L (%(G/?5 9 C/װ0x9;!+0G81vcdfpX``Gb gc rDy  BEO1܂%Ƞ[1L1M24|xuW3䞹A_R@R0qiT8Rx׈B$<&lH~rbve/ d"ǘ~6`:Β! *hnQ#~Q^ 8M6 .ChMCd0C`60+{,nfB0Y!!ȍqHT0 C" <;XH,`]bs#<^DBShpZ7l Ԉąγz/1}ohrPjN "7X/-tdP_Hb FtDj ]Ucf,uw73Lʄ)D1RpH(]csqsZxq|aEy4p!Q͘&o$Fg 4$ (RpQfQAU8I947s4q(M&Q "k$A of%|{)7oˠ:+3TyˆbPIU *EtLA(8lyocr-/xʣA(LAb:(B30r_qA2"8?vc. EAdAqj|`2u~q `H0">."#RF]I2FU'Omń%* 2P0<C4 PDʚTxtmY*vcnPw+1z@;C5,`ǒ1H +K !X뵦 )ίMɁ"/5E  6,e`RE!˕ OGkFk:ckkU)[+zz-܀$uhax6#HIiD1 sFPHm㔏lH0Hsc $C&p 45XA& &{Ȍ"0f A` 7/r܃jP8P|F t hxUʌ}8H f_c =Ak` uD}vtRzHnr :-;U~t0?GʍRBY*βPЕ4%y W%yɟj^@_<ΐ܌]p 3V2bY'%M ~Rz[ITXA¡$F0z rCc?PEMW")W+jWp\ipbK5d-W6 גo"Z~J {B`ƖjryU5BP+hIeI5B%\F"G tbs)$ Ȍn2V jOoLX*pe(Ay# 4iLb`q0#'h$/F8pJ"@W7$A̷ pbTa6#AbaM`C;8#4l5tUțJw1@Q@ɼ-@S5)}Џ=E>-JD0Edq.$v7 H͙Aas5:,&Qa蚘R`҄LV+?Q-v`9y-:4?\vIaҵ#'{!c,8,eŃr^e,8 #i8 DJ <%xP.V"J7 nַiKdUkGs)$Q!qï89I0HpJƍR%`O'APLƢ(RX cєƢ,"vV"95A*4z R6KaM<ض0KI~fW^LM_ xQ.Yr{[5Lۗ!LD06O``WĜW~Fc5Ƕ=zopм-T0@ Дd>W4*,3u1^::KPpQp~絕}ْ~Uq~ DLӱIidN:E`QN`$|,\Xb]:0a8U^a@tΣiŻ$݁&B8" 3$^ ,8CNKØr8VZaMa sHpM=Wb mBva5˯!)7-x 6YWuYW[(aA5! 5d)[,\9[+ `񃱽$KLƱo !]t0Nc2%d&!_($2eE8t Sy4ޖj a+,>]/bkܟ/|p6_?^-w_Ɠ]馿uq3f8םێcw~_ΧCI+`;hRّg>ζnIܥTf32<ǿSڔ?x [G [ ~xZnwOq؜jvQƠ]ҫ8,FtZ$/~8,j7'_.?&_g)쫺z6e',}#ϲBH*A>fi6KLa&o]%Lfi7oMΝV)=AK2KC=W@8ԝFsZeq8vVSnZu:z|8*ce-fIY)WU:OF9~YYg;'s\ӔsbZ{NVyvspm<쓻C.?T(ļn\bIG~*S_? ? yܿ#zؗ#h<)P?;̉o0O] t?-@6Cr qU7ǵ ]Nldg@#! XP1\a,Fl'dv)Iz3tl+=U~Q^IxF(Yv$_gR.Ne%_ʴ(ۉPl'F7e^ ) o E燥JaSucƒFMU"fysNH;$I$L87cȳ%i@GȚ_H76PAEqZiqNTfl50[ >XQv }+çZ6UZ.m k}N|rg } ܊udRnQ{&~{8蒗䯢lǁt }mU* W^Xqhv绺aVu9f9όoBTu[q°ϜF1%҃#JLT6-b^TV<0£UkxR*ԯmլ͎Y#AV䊫M\1laHUG]gnŃ) q1cKxSEDzxx8I#"m#C&$#RZ#&!fgfxf #Yg.Eֺi@qV,) y$ ϛ飂GdeGEYU45LzgG i͎5형pRænTtZdjJzgԂDvpD~Ң-jz5I GU@-5ʸ2A|,29p8Zuy"YP$GkNގ&,NG[QR)t"El.q6r-NQ泾8`CT|-Zht\RNʾX'+ʩ3qikmBbOnn9RA7#u[ך,ԭLL`%rjk+Ϟ5'M"y;&y7V/~ɛ`1ijHnPEgf'tFҶvy{5tXxҲ΃7;GJ왳F$rãIpl/QHh&=‰neD1tŭG0(nےճOK\ "#O jkN@'Ե&?'Trizk{.) _R6wPK8D"q7;$AnalogInputToServo.fzPKC;fritzing-app-0.9.2b/sketches/core/Arduino-no-FTDI.fzz000066400000000000000000001054051250202676700223450ustar00rootroot00000000000000PK%8D Arduino-no-FTDI.fzr#9&zfl;;fb@TgXWVUWͩmʞٛ4D443֎پ>ƹ8/Or8 HQ$ O0?w?zq|pu{ ڐͻ/_C?o?\Ww_4mChDC^3Esw|{;?f ߟO?>MF7yՏ/ף~04~mzl/{`<ٯ/d(Qv<ˏWOsu nFޏGps/zI^ݼ<\~ `t}[xo.׷'+pv9~?\ ׿;{_0k?|+MƯF^{_|?: ;jϗWg?jO {G˜4o:'\sJxKXʼp9jGJȍ<عu7i7"/ߞޏO]_es݋(Hǯїq?sz?v?f==Ż75PmJ`,g+ BMOp:?!A;w4>ǧD%~|CX1pws6OpS=(J ҋ#SS*)A>6Wβ]P/=yxlvG-Q)nC[RܺlG% (qT4,-"sF9" #. #e;0g%y# )mq/ bgwpLFFW@ ^qW%o qFv &vǐwn\fF(`]hٍc^@fl/pTi^`Y~ - ,e{QA455mYڨi%+mZI6=.ȋKE_@U8|d1MOhSjX򲨞Eѳ›^Ңқ^C#9˦ƑmophB~=+6K;__wEEEfE^6jOȴ(q$Aۼl>B[wpb7Euew]6jCYx^ZTMVx8uKYJ+"dYXYgyѩEcupWaPoV(Īܲbrc+,UjPxhFtqkb,xceX,CuX ,Q1[&$kNnjsq75w[{buibnLHQ7-XPb6'VcxfwDD/O޾}pv9~?\y.F# qQqmTR"/"slE{j5}L?2RlgRPʜCX/>TV_ZldjYHƜWTf1Ǫʼ5]հ -ښj]v iOe鬆N܅ᱲ^1NYz f=z ›5MzɻlK:qއaM|.a'{M'|.״b@'n^v'J.Fc.;]X܅X״'=5/ɻlOpM tVev#oU6x&p.X;&[ KA*bp.-( ;D:qDӔm0R f=J(-Ci>lEEiXq̶l'%VrvR ;)mNJie;)Q4A줴ew8)W̲"2GIaùmZ +KڲќTMY~8+-ݒqt-MeQ43Rvs#5 &-'.sѲC|B<h>DҲ}|ZOXN h',A-C+C۲I-haLVx8 ozp}k[@U0CH:@E`o~hRf6d, h̄hN]jU6D]z܈/=hEbKQxOfZXSfVxSey#< L 1tזZ-Vx`ZX`Vxey#7 ud bEľB`fAA*[L˲"?`\Q@DŽ}FsM[*oY6x8bYx _X8G)xW7l.Kڜ0!bo L&A EqZx(+nN&ENx؉^Njiሗ߽Sxx?z{w?/|?OO_~h7߆.'/NO?}|ӟ:WkAN&Wg|r?;ʿݽ;܌ޏ3=񥻏0'IOO?L>_wOO6j?.&Ý/wwt Soo?aT {Ë_۫_G7<\64zw9B}7ޏ] 'w__N&>_L> c2|{}{UNӷz fx6`t3篿]^508߾L.=/jڟ 'n޹3!oA< w;~\ݸtanv$wwૉ=nrk?wtvuj ~dOsy`o|v<Md~ ~_&s;;<)6䮹8pvm?q~5L~N{{g׷_ؿr^U?rM?t`6=@jvLmN/I 0 Hb g$\+m%u=>];DD4ٮK?D-Ԁ0B,N[%:{5tec&Eu&<N~09f7-Xoo`Q+d~@E3]Tx{=˿[Jz[+Fü08TftZAs^N-_X{g)qχ n`Qy W'$| :QhՎ2]'oZzi2p!zznBSb߮:mp4Tw񄋽<]w޲}halj8.7oW4 3ʶ`J'vϛޔ5qEOp@ߢjZ[a~kophߌ%z<{mQrw5Y47$d7̺FcuS<&<&10InwDF"Mۏ+nA9|}7[]oκti1?,ex Y| &Eѯc2TZha2pY+eqަLi-.4\piKFH^8I ˾p,cG\k^l ֻ {W~Ʋm8#l2ƃULT4uW$r3|*IS݅ BcHht(0NQeƇ9U[.n<ꂌ}ƛcfl}¿U4ǬReuA_}pB1"w "Ӵ]+bŒ?ObNֵbSlTSLcb[8( l`2.'dƐٶ4uQ:R$jZepXoκ Yj5Ƞr8WT0\赟1ȟگ.X4=/wxsy{ͪ<$7yH+۬X?n9WN^,>3NgP.""xn:!.HQ_YD$ui-hvG R4"h1wӵmeVC(5=TC߇ ]j؀x2yq?WRb8-[㹢O2UzO ;<}dVnӊ! C&g|^s*.ڷBj9j"-'4]xHpvPΒRR{0>Cj5tSl"q4eMvXTH`&u&k 3d{W}LtuhCToT8{TٚXHdij>ڢncBM } zr3-,89@r,ABXIl  2aFL "777߿ %u,,Vtwh2:vEGϧDZv5r,NܜyKB,zmJz.2o?؛:U=eYen"Imm}h]ҷH ()WHZ~A"V'E>S&qTBꤱMYɪ("$bu2HIq26B@Nmu4EQd.R־whW"kl6^ei 3c²F1 _DٺSI{&&EqNVǐ(05B**c>)ROEʂ'"掋}ҍ"ܵh_^x""ZY]Wi!Z":ѲR M*$'aʲv4ۧSnraͅ UO^W9UjP4u)C=LjX*!b$c4Dcē[S<.HPM,T}KJ>XRvZ"b=ʒ_gO`hYvxDbE˜`Gl7'1Ս4eQ&>XZR7 _O2 GEd bcm 4m&htXފF>3tU;>WH& 迁r|n.sKws 6aL&Ҧ{ǽAm˜MMb IMI2vEi²T\X6D} n٨ Lr_i%EoD*;Ot>bM21 U! Ȍ :+ P/qT-7ƊDTq-ԡ,Ha(b+lZTemHu/GNE:))7˸}Pߏ_ݍή(~C^|:n Ϻk9a~bcw.=ޏ&\^%l񊒌;g@9ea*l چ.۾F UI4J Mzv6޴Vw`)v~C4dË<];"+fUNĆ cIa?5[iMI\D1 n2k'+߾4e۷悂1 ɶi%[cp%vbɸPuog_q>XJj Z#p@\ ;`KрiO,h-WXk_;9h,\wT!CɤlM&T bٷ?¡$ )w($/4;3n7?S ܾ+?w$oZ# X<4 }D{IޅIӶ)HfWsY#]X7m1hsF Ѕц]١4D()*2FPXHFDlmKȈz-.h"Mzv놉V>ǙE^EbNpd;M܌AnCcr7'QZo:gqx-HmX5@CP$3 et^@%X>Iy6Ԉ9*_C j{EWG\n|3:{sa=~c5ͥը*P_%?}=NwAobn)QF]h͵ 5fgcn2f`p]x?+pp? }#mo+_Tu[j,Bu" .U'Y:X4uRiNEANݬr)թEN4v4ƈ T(ca˄ISH V'Cbm>7H7iY>1$Dtz(zvMW6X)dik&uXD,}k>%XI.b)w3W` <6fᩈ-+3ɲd&c}l'Y`O\lL%zQ!M'^{P_rIVw E#5=:֦Jh 1KC3&#N( c+6)2Hڄ1mH'SW6aեЦlbmYB!i=B҆R)BV!+R<.eyV( {:x.Hyc$ Uj(q.A ١d3Q.IlO xprGMBLB2 :i}wE7R?[ݴTX(Q Lth @)}HL+Ra4EcV`#oU:0n؇Bd,4 TZq,$ |Ö溱 !DF1jOCF6pCwF9?oce)LWHnD(*p4-Jq.]' x2K@oJV `[@eCJ*%r$I%))D[( d 1..Z{vd4-q}E1j|<Ɠ> RjTh8i@Iwr74'U;+/hjKŒd4+TjZ( (٘34wu  Ň/p/1QGLH!eF]˛WVj4!=RH)%XxаҀ/~"d"Al`TeMV`HiXfJ+$%+쀕rGdM+zc\dZ[% ikOLg_y^ӾR-Tt#Yl**7pjCN d͉&V<)J#J&v9":w"Edss|VŕђJkᵼuhAh[}PSqR14H #;dOE5> :Z,m&D"IY/KrQeDԴ43Ki!]ѫ{NYhSYhۨjXTCZVr4 =b]!PHҮF-ߞ%3*T8Y7áI2*JsI%OxjOH[2R8%&os YQմw|5KU<9amCGU@F2fPVuv:;tV$Y3áH2*2IeJx`l2rHݮeXh=hB T mmjR<}1'v HEBuFKc =ц @uh5>&Z0$c<'T:Z,(y('\JQQţ+Zݷ0b 'XQDɞIEa2ڋv^Nb>W0$#p"'TW((AU+,s;bvFYI4.&WH'lD*p,MdqhO _ATYgEذ#ɸ̅$U,)KI&Fy,Ft54zE?kK0IE#)GIz&]r9?odTb6bI7W,r7H10qp]`6qmC#*!Bܑ!"*W-# R(Jk@#0|Gh) dz7HA0iKYr&33X;*7=aYfYQ 7#N&|1(J*ѥ:Ya7~fFh)Dp/HlIHbIkܑR Hek)Q)[Sd'l-QFh(DԊ0x̪景[b?j 5F@eK4VڪcRr\Hj 2RڔipF*S+;PRZJqJ"cXj Rڲ qIjhZ.wrRZJdmJ.ZC fVJ$dcjO^Ɵ#{cguڪcÏF-tlGf RRٔif:YYlainfF t\Z{yigfRh˂D &5 G4L-~TC*S%;$IfQVKK$1)<֊ړPreIDRrlH%k Rڔ443Y VTV {@!?j?@@ReAJRR\Hej 2Rڔ4,3S!Exj%JRJ{աR'N{i˒DuuZ*8iJHg)Aҳ)=;iyfz&-Y[I(ACڵL)fV%4Z*94ZFWRRZJ\mNzpقTV(y0%w[Zd uW*Y+BJArHj) r0Rڔ4ZؓJ]%^G(:S\mWVX$%kJR`H%k)q)[3&253]H#H#C=U{.5[\mh"nrEFҁEfxrW|-28r|-;RZ l-%T6ekn:l]l T\ڪL%UV_&‘ekܑR Hek)Q1#&/[ 1p*N|0r`vQeflnd]"he~c>8$ըXSytRvY[|`l Zml.G%e 𣒲R3hǝ&tf>.8R+KF>EFD|=[+۩AyV傔Z.C]w9rLQIZ y' wOvPZCPŽnUlƊewѕ9DFÓKG]Pq?2u려u"HM$cM@*cH5C*=32>][zhlfuSre˂m(=< 3|m2Q)`Ԩ0!r㔌fɞP$J$s*fVVxVVSi5=yzn{Q~Ou uh7~Tjvl?䃣f0r7͂T^S(WEAfbc AWRȕͲc~{C{&dT"Vw%b}JRGe```defyXq h&b8F=fیw#P[.:v;0pXs"%RBHiSFNx謌n WwX#Mc>88mរ0l #7)Un5c-5a娄,~TBC*nwLg\nWAX ԍVf/]+o BdCFpdn6*%KG \6ףҲRiYBn/5 ݴ.FHJ% PVYycᔚ.f(LRŸԋ< W,Dv<FR7tJ*sK!%PH.H[K26 xcZaL*J-kWҶ)8R,KѦXhE kIpE5JFּۣTi^qC (%’l9}\TF+uRod~USvhWb _ľRh#ZyaCP#U?iuzBj^"8J.Qjg ԬOB4z mIr[p)9Y󯬯*QÅV'uq>Ys,yY''5B8yTP$ <m NH%h #gY<Ԥڜ-[@@ʁ/zi%eHc*S)+SfO,k1ri5m,[F3j5B*MK ǝWTҖL*i֖;`nmffʗVШev>-?BBnelYP~%$YM؆RJ{T–=pC*QK"͏f@rtDO?[^}tzW_=Bu= fCZ؞|܌ޏ|G|]oْ|r9=^r]ջza52lZ ѧ/6Ax^wZѴ'-WT:L>)}vQ^؆m2 ,JfZ4uvOQm3۳U{w/ZFfb߬j&fb[x#ŕ[*%I{m۔J $@ZU;; r=OKn'fECm˪Yt(Xb%o{B0 o<*Ara TSrH KTҖA*iQr7F.j˼v5zud .͚6 Ӽu+khSBDt'NֵFL6*\5D3ŕ=<,$l9}Hm4K*q[LXq{e2HҸ$yC6m%nB\Uɷh2đ7$|QNsu+C *5PP*K&5 7?JrˢܓTRuCJ%)B̝RYy3X2]촗hcvrUn&åDp=J`Ip?T @v3)\c1-Yp1"J ?p("pn!R9$:\G}`TCnhq"R"G .ɡRɱTH*FDv㹛LJ6ba}7*yC6]M!¥95 LrJen=OjSDPr\>I%m 064I#56/~-:] 䞷DR$%e}jm_ME՞{Z۹?<ܨ۹Čp+h#%KqT"9jl~4G=1MϽ,DIQV"b4BfѫQ ,c5?+md=B*'K|7gT֖GjXR 2a˼U6Bv.ylّUfUmJ4ph1T #$IړWu~!7&ӥ&)nԕj Wet?*E;=C>ևJEC.(ZZ𪴀r>%3d/} j* +Yrպu&b gPRڣÐB-%~7]TFjh%-ft-"5bqB$u͗ڰi6ć.PI[t4@JW8LEX MX#bh":0!im%m1qmEr"%G,KԦz&23a(n/4lDxa!GW[Zt4{ j=75쪑Hi?*MKǝ[TF*K֖qT-w/1Y\k3TRWC eI;<(y~"D*S{yQ׫%&i@H]F*A[; h:/Ak`Cڕ1,Rh9"E T?#gV2 w#=<YqŎ}@G͜͏fQglC419X>j NK uﶴXl0n8Yy&$>|)o|0z:8cmXZ0{^c:_R[(INjmNwDfm[i f Emj4 qjOg2WzFnTʶ퐤R(rI,Hek PIjmyS6-^6]P]lC6\ Ik#ȕHf%:61i k@JG#u%[J9V#ܑHl?T6'5]&msմԕ NMV. DRNr'}>8]4𘈭q$;l4ѿHel)!h{dC*UK 8,lYfI7I tmo:!:=/WpdHórG$;y\J H%RL:pV/(n6IÄ[2lVk RUK>j="QbmcRJUVb=lu9(%Vw\FgrD͏fVi2^0ev82մwC^*ձ`l"Dz)NJFqDNA$!ľۆ:Z(B0'Œ&y\ HEx+.X MLHB)W_08jͻȋ@Fw#Yo]Fhj^7@nhT%8#_sꆉoFOWX[dLôE,݊GN:)&%:UZմl|L,xq,x(~\0[ϘD:$xȷv\pYZc:ueWrS$JG .1wRaڲԉ"'xd,@hab>R?T>$$#(c ^}-I5Z`JlYrq.UxA2E .r{oqA;cy8$X#Q` Q}*}9M3S8!tEPDO4JOe8leU,1}+QSYX%w&%pJQ,)3P"ˑ2uIZ ⶃ[-.J _Hm9{ZܫkY$7`T@+b^c&mWk)O"qK">%^}bY<)7xx*B +,$NL Oey,7'"SaJ}*,St>IӲq'cO-bq >!)_v _-R <$$ 5Lj %G6 CO(CD͏{ ݢSvir/8|>|ΩۄEW^rwʞ(ݠWZ4eY;̤.]on,ʦh ~kc4$iQ8Iԩ1fu*uBqۯmB$E\[4uTHڍ,W7ٸa_|m#|u׊n4gӻ~|nq&\MN e/OA#~1WIe.+|P2i++wN 1ߛiw^=|BnaXØ+>;Ajvde~|TCZL2M \Az [ģKb7D7D10iF"fqΔ[);6ڲP"G1; !5CkƠ!s{!7I6LQb bDIkʸҵ%J@H i, WWyZ" Rx,KQxI(I GH 4)h$5q -QY pBHY^"-32JQSQ2|a,?e ɺS13Qg)q#1 {%@0$9 FJʔj )YI $hSE#1<\3p!靖,:ĬHaN/_L?l*[I*s4͌4RqX'xwD.Rk6}WTA*UQh7O?ܾݣmݒ4{k{+w(<<}% D΋_d{*2LP-Yx_OO|?\|ڐ? 7gW7Ç~n?۫/ >嗯~ӿW_௯< ==_0drOOwé=htjOFis>9ņ7Ց/:};|}a?PՐ~d k/@2`0]݌×?.B0`pk _}qk0w>tԮɩnvJ20rMwaw _Wƿ)m[sqytߌ^oGgw;* r/)1wvʌ?+L=p7WIcD> =;MtQ(~tcِ42 ih־O!odײReiC/uo}%Mk_kC=~̩;Du/T挸z=pV[ݰQהy /*;r aܾfR㎕~~⌜ttZN?ipE?5;]]޵U+(ܕN cݤ4V)s j„NNzˍzyʏ}p" ^_ʦʎ^Gq+mmyx}FOȉu#{\{"چ[ioNøKeIͼ^vb*<}18*߿]c/ ?o0N:LXjSzyUP̍ }Oz߄ݷlNrNV-`7QZk̍Ċ{kA"퉼z?T~W{qfN2wg +-'m 0OkH_^Z^2;£nFkA?SLN*ܑTOP* I=~~* Wh|Ox 8#ӽtfɤ ý`Pա~$k@ڸv_Π?yF({_1~B;̸aرGN 0t)3ҾD Aqxj7$1Yݠ^? %E>UbU~ > +>5蹋=[H&0$͇<𖍁^Vqpg;$kpn ޼!D-b-Į=zK# `<`H $3w!>5# .X I,v7vNba aa/\Cz/ EފB/ &~T@,;"5ޠ3`29 *9>Rwҋf܊\DVB{EnznCtGBhϟc}mS\!.6I bS^F^:`)ys26t%uRo=6xv"%9mAk9t@JF#a뒜[,?D”3"asCمq@/r`36^s & ~$!Џ;ܱ0b cx59".99!'0'st% uq1ԏ9فy7M)j=@o_{`Z€WkJU!G!'HxWڛsпēW cwGT1FyJ']Ly Ak+<ѐ'CoA4>4߂I_[#aCe# 3vnB p&VHypԗ ap\3Ï?;N>ZgLϋHD"RSfr}>P~kܛgCtY* 8`K! d<W{mkm rӅ/t( Bc'<0=%\Vp{ك }1Wa(94Dg-^+>5Ba vSd~; |{'auf O?$!*Ep̌Qow! ?YY k FtP8 @ fTxAhϦ(C(z=0nԃtO"dqj|@2t'p0d""11,~ mܕa |t%SZ7 ~)]*0?NЮnӛ\%xC_<ߎIag8`Ǡ# gTœvl3c0ÙDpJDO_MHN@ 2ɤfuk83\`Η W| =X+4X06Vǡnq@`@qZ`9XX0aR$TQ-x9FPچKȰ2"_{2xt։t/A(ό0f>2p%1M-rA:Á9Z8"]@}=]c^c ps M; ? :}ٴ:3 lw(;@ 쪶N(7/e! ^AUwHpg P4=S&FL >/fԌ3>3c=#=aO)3ۛ~C_dO WO`O"`!/]8HDo@PE.:0/p渪vǕ'QC!(8l踺cĴQ e 5=Oמo">э *>R܏ڥ}P ʙP ўP˞P`#B=PE1RH3#3p P^s[+XJnl4SG1 g0BѣH>zD#7nH2{276s-Kd8Ɠ*DH'3hZ \.Cb d~OgてjRG?6 , 6"#sY(aEda.$IA7kfzjSѵsL\ӻ0Y:$3&fҁ?,/wWF oy@w5v&5s~ Gى\)x閱@MAX5G[4(f@ yOɟh*V" wNCmz5~zKɚ'Vr.&OEf,pDD)Z u JB n_ D>:_ IEџ",\7eo.bgsQLN$HTo`IRXqsҟl%yW+zn/]dO_{10HB75e!L( f74qXA9!\Fcc_`П;ϟSxGVOu LIs F ; Lz6_::K"(8[bIg=Zߗ7[vWzkWIi`pu܃"w &3=Mr1mC,"V0``P*oA@΃iO zzN2?$3|8_9c`{@o ,G5BNć9uK 'qHAyV[ > ʿ!4+BM0.f>)/g]rBkzjhk)ݭ YJje^ Cpr< Q? 7FzK_3 Ys0,o!V2 /pDȔᱱ˾?~ՆaK,~޿u]ֶغ=L,Ԏݻi_'wovu{hfr9~s9>辟cv0zk?6qt>|ߝǬջ:1ƙ垈~|K2_.fdлLwzFw*th|Ívۢ9F,U_i63.߼bXOmtY|jTBں+ ATnv8y-ؙ׺7Kºk;ԒT=&];[nU>nY uǫMDVĉHwͣr-|mm30u%y"e^"u;@R7Ѵv'4Mgi|޿"ܶ٣4ifJ"%citF, @x: ,-!T6eiz[[f241^iZYZIXYZ:qW2H%iǐJђ|`iҌXv)7Iei3w,MW?Zrx]gy',yg7ŎmrlQY"8ZjY8Yndɳ37bn%ĐfLQ9ʹO9UF0++䟨liVVj4;,2@*+?|TV9yV QOX%Đfl'A莚lS%cNmOE'*[jWVj4;RFee%BeebŁ#+I2Vѣ,?*+K!XNP͇z̩ҮѲpHܰ"UC$L+U7S13D*3?Tf+I/J؎mp585'4,(y")33GTYdRUY,(JevAeqiasH[S?n 'SG|R!Ѧ O y /q5'NL,%tܔi9?|rn/U$c4Sѵ hH!@*1KGK1[ 9oGaT[akvG[m[cfM1&`E (`ۤ?ã`CLN(Xfln3#R: 46nQ 3RGdX)|9HcđRbIf3nvTυǹńgḂG 66 R)2Tq %V G]QĸRٌulն5m(3Trsj/&OL rۥ Wy`H%ihIZay @zm? ɳ3٫ -vQZJ mvђD]!k-E~ŏ3$.Haa |TzB*=ѳ]t%4wH3Mk\Z,vBFqW (N*iK$GK"i;i00>*iK !uMӝ,Tcs>pz%RZYVUޖҘڬ7IGc{vtl+S. Y#(ohN% p'E,sQ%_n-ӰV:1h3H14Ĥ}|Pgœ&p+G+U&AoG7p H z zu|RZ2_t$ M7b!b-_Z1ͣ |gP9J˭ٮu r:1䘁xd1x&9>9!!ק2rNQ Nr~@k܂fKs(h]J{ JI ,(P|5P- 6mSDZJ\zy`o}\uWClvކ3- μq/W _MS Su]{6=~Lo| t -uhj,<9'e rcηRԽȂ;ԑcko}-oM`1?F_>12;0˰`wwiqZ[_zp/WC/o=74QFIwIL#q+a7>/toq54:í[ z6:)!䜤6gl$d&#ȕ^/<cgpEՖ[Ռkjɝ(G6TE7\ۡ&aW{o-hǛ'w#m%R`n@A$&Lέo~ZoZzΜ17{гm{}qu-AR81^ @2)[Y=o-iP8|j D.D]3yIdbBJ <~֞oT'*ԶZdb) Ӭsw'9>`5A=h8S߄qgFN ˬ/F8y|H:5u2>ZľWHgu#jl) D(vĬ;=5*] !7>sOK 25h$gRj+aB`ysNpMY,!6njřK@+V$VYlkTۮF7t8#},VA@p{S}8-4R7mMz@8فxgMn6!ev38§>5ٗ!<櫡PRfKo;w6-pNVdjAkj*# 2H,D+BqNsGkq*xr{Fk~F*D+ҪJq+Dإƒ;DSKKnwG?H Djh oD8(9G*7/`S,Ozsg'3)a"֏:=AI'gcDp]h,S ט:?e(άؒ $ ɨVsԎGݸ`#@QԚ;&) [)vފ'xE1'\y ݽBs`!6_Qu,D ]리~?ѻ"/c cYJPĮ^Co|X s }K7m.)9 NITѹ9 ӿ, O rF 3ab0hU`G/=Y/WCO.rkvPs=SzJXN[ST7s6h?;ٮ-9<o s`'= jʭaQa@µg? $-_ =T i(t9g o`kÅY)sS6~nGLƭ>DlA˞J8MYjb|zSIW5A+==PX p7sY6MsjFb뗴peex)7v< JnXKt-t@YMhTԏ[->u^θ|cnSc98Y A,_ =L0N#,4v2uOVwv;덍Ҫwch>HjDȹ#g: "drsi3#=l^og+mj'az }wPeoT7f> 2gSr}phaTp'95I:wHR-S-wl\{3lA;У;8r^vm=bR3kos ̶YMi#`*@֊4_,yp7RjsJNjMZ\RWhilI\{z@Smmz@%ƦXŤ$4MuN|l} f?b.4YU$:kQ%/Bh%6dcV=7_ ={Rn[,ǫ@a#HbP! |(]@r?qz}* !r-m./9j ZYWwt5Z ke^ݘ6v#CYuw-ozpA}v!}Q$Ta1>] MpܺtX{+|<4)23Fݬs@t@j?7Fz̔L=Jl$GiucFm+ަp}܋ T,ߵۅt||M|@Qo|S8=bCB(ej(i7HL^]" -f/3lj9zr/k.[dJWC kYU\ɚ8%v 8M,o^r3,=H9& inMѧ']U Gk:3_JnڍيV.gEJPx7>ia#;uN^oMl]\hi|:dq|9WNf|j>$Ԗ'>C{l/8#9;ofj!MULQ_`묝7U(BKxO9dvKݕ2l辙 :^辙}o6>i+ X0:fu% W4j(vXeA ?=ئl)(^=5a/*&n=a5MTmȜp~")DS!I*Ͷ)U,\gnt0Oz܀H[›sO>›pn4YeO/LH8[EJBN~o :@gM;i䐜1I8]z ι޸Yn,v6喍 /V_Fr G4ITˏ5,pALjhn'1nUZJ˽/` J?\LI'N婵 s WL]r T1_ĊV;\)(^)c_ͧ8>_&}8&a6L ̺ŋ;ݍnxz\-+c-k2ٹwcRqP/pW[uJEBERN?=5`\̀pUi}W|ЭĀmEmu $9#xOjg;%w/v_4R/!0r*&ȡ !<ɳoH?MϢc*rvv= ~bҏ$܋U"˜[gb^8K8:wv-9F`jrZSū0Uv3i~)ҳ~Vl~ZliQ..z'm#Q|,䫡(܍88jlL9S0|&ONd ' 䫡 |,fl)AXɆ&/(pOvL0~}9\i*km8\3@a5M/ts[82fXh ._ =Rp˭٪pژƙj'cV4"FNZiPɶ>^!nPHBn7ۀFc >!v6=E`}gxΤi'g"kh[_ m"N`lY6X g,-ܾolVZ EȚi9AjQy4q״i/y$WrҴc-cV%(oUyiy={x$g[ʹu `Z v[v[Ҷo<Mؾc_ hOXZE|ҲݟYڰ\SKnJS[nU6 Yun3'bxb[)85E *%jrڬosDh$u5iҢՇUoo_PK%8D Arduino-no-FTDI.fzPK@fritzing-app-0.9.2b/sketches/core/ArduinoISP.fzz000066400000000000000000000754541250202676700215750ustar00rootroot00000000000000PK8D`uz2 ArduinoISP.fzrƑ.D{3ލ`]Y k$KޕYG \3щ-+{* @7PUã@DSdfe~/?}X<<^~lq{y/ſ{f1{p0~UZ0QWo}rf>uw1[}2//_'o|xuybttoٟdz?^~kׯx cR^̮ox! 8j@}z1<=kWp˻/^bY8ǫ/f7oo[wݻ/7w'[xyxwt}y3oͶ+s׼2Ͽ?}ӿ-w?xtg/ۻg~pu}W߿\f gyT e>\7>cҼ2515M){C޼"rJe^7}p; 7N\ܞWӪWwo/nR//j#埿\D??֎[մl(>V֯<ݻç/O$!ZY ̹,(_>Yi"*57R^, +'FT󧰫X7-_ӿ8dOk®͑/ЦP͹$z#[tpcz2/S߲9Rsz2O\):kM3&dhP^y+x~\C䝹.$2oPQxҢ _x89P-e2or:<;\1yv+&k |wP[?y^D2œfGWYVO< ;ٳ ɓwKL3[ēWbLp4 UrKb4sT-m˦);sD-eC斱Ҳh&#m45C(y<*XD*;O&\p#$kݨ3rII=DޫfU9=#\60!|gȓGq7څm%UțfمӲwLXF`O'Y6䲁8K=3%-m2/y޶a+L6drrvG束ߪ)uxҪmWCS2ߣܪ*aϛkfFx[g➞=|eE"r,vxv!|_rv'l&nz-5m]8=%iqyrT~'(YfxkfjrSy[rr48ͼx˭xͼDnu$hu$Xnu$(\2g\Wa툶p YvQn}ywxOXbo'W-0yE:AO-4H|$mߎGI;m ;s H2Sv"JLn 8Щw`PIMyoh"LoXE;w+u$&i|NL95L=&قO)ɴ=');/@|LWԤގ)ɴ;')?$|LWk0< 3]}SVL8;EsvC%>via{9& &i4|]W;w]=8&́$㩷nNLkW៚F펦ͩ {r7HIGy'@tkNLygujNImutjNL3Ѧ9Ev{zvEBڝFi)ě3%iwfNI&ޗ91;2%iwdNIݏ9AOsŜOsj; sbžv 洄=).o辜v(;Z/'&펾izz_\NRy[ “w[NKng9Aμ`LGĔ{r6IvdݕɎ jwebyʉ {r ovOrbμCVG91iO®vC/./{ḻce釄lPNT擫Зh'Hy)dĝQ(9ygG7;qg޹I{;tz\;\E{M4V9=R:+;}1ӄHTyxG6BrT=iBʴ,yCJW=9˰ޓ)MHvDe7+ojp9MHvDe>dYjgrz)@y'wv4_NSņހ95,z =$)jÜgysrv+ĝ9d0&ΉIYn$Lsr9I ϼMfuh2/C99qOg|aS7xNNޙȬNԛ<''iy]ܵ#Nya7߿~>Ws_zqz]}yo߲'K9^;`]JKAB]猉B¹\)ҭ곭kqjsW}vx{pxoiӧ}{]?\bxomfLJ;8ת.|^Ww?a7v7o>}_|q/WO Bݹ>{xwq.7/3rwnoq0yHô<87h 2vJ Qo`c C(IЕu E1Ļ*( HU[ap+K^;kCyV˭Y= q$dF8kkRwAH+@!ϕrgw= !n+nc.d-BTkY8.JeU*䘀c^$] t6qv -_0{}IKӨ8|ί}ծ=.e>]<\_ Dˈ77wg(}O[o"n3 ޥsFIAU961PSjfBjReٝˍtV3.Ƃ IVKSp\ 3L8ަZCN8{Gd uZZgg"S{, c.#&1(3O\1eJNMt63 FiA$PJa͐m܇>߾g.-@pe ZX6) Å]C]r, o=^ݾjky?y}Jm/"ŏ^geR:6X2^g8b}L30UW[1k.1<^4ӌY["~}̱3fF ݔc;S?b̍6IJZSp3K^{.\uEA-Riި6ݞ`kYWn:|/g^F%iRs2_b).q8ۛ'; >x{S;#y{co?J3/ްKQ+55nЂk]\m`1;>;Ktf>D*M;7^*YGN#H;UKOF1+x)'qh^'mn:|RCՐ|-)an _&pL`y&fo?'ޞDmRpE YLߖn/"t+=)+εc7˴=II,,k{>qgķ[-{Ĺ,grJ>z9gkF$KNċ%eLg-Qq<#;kixzW2GbӺ0=_yEdqJ=A}O<♺T:qݥ';<>!t˂WiEKSILVNe$?O[,6;o'ZvL[c Ssz,eV'VPto> `KDFr.PD\)ۣsxpwݳΡ_#w.C;? ܃scQV\/Id:։ 7;y~i/Q>4ȦFjܻ y f-l2yLigFYnMJW,oΌMZ#YkdfNi^k$~Ljm_pT}kaby;3`D=%IkZy~RG?2U)IŊ2,\T +3,ܥvsw-BܸyI'8߷#=ƔM4oC BHG7fN#]Heu:hʮݺڶ|vn *8oR:[s^wQN2NQ-FFiMUo1rQIkFV'6%`dpj6IXh^k{)F/gFڔb{dNɀ.:N)G{89d [2w;R,+u.=}@9;P7* 4@9{22T |fk=EF5 ԇ_06 w2ruY4+Xfd=H{22t$e lJ@ٖl%2B*eƖբ4P:P#%W߂+:7a5vZaw_>>]^.Vox>jYpOW_axrx6=1?,?o~_I9 YfߔMM^ɲ8ߝzEM|zĢ(Ҫϰ9gELB0;) eEw7ox}O~zx3V0"ܗa /fwO|WVv)ѫ/׋]珺'f%+^yG]-A Vm+ =q;J.٩Guӕ剣A`eQҾٟRYS)хT i u@^1HSASu M^B.VWHSVzb4 TNҨ@<$y &S<xI#)!@X WD*-™3J4Uag2I aY$u)n͑U_WJ,u7,$5(#gu TmÞKe,& IE(G{ %K},2N TF*+KU2!iio9T§JɁ$uh>% $u7$5&" $t@mS#r$#|o Ar"xr*boF QINZSM%NY!n~ 1]z&jVP"w3[dRi"k@_o6٩ZgI0,pɂqi"t {j TN@,$ &R,UXjyC*`Ԁ.5їBLRr H֝sVZ<m9j(_NcBޫE#M]&M,p oZS@ 'f"Xj,K#RIX$uIRKReܪIĴpr;G5Rܰ_hcŰ# ?5p.NH #7u\Mj؟MN.ynA @ie!j8CNhuYchTE$'9;_@FMMLM6}#-9t/&JV$ 4ɷcKhAs|[^$c{lq)4"6n1ԕwat7T53]D ;n++]OLoVU=nAu4-f"K@_QIo6HjIWY61,dgHPR {b PN@)H>HN~x~AP>xx<[_o߶ CD+iv{n 8 {cXJG9o?8qiཀyke.J sU3tY}|sn* P>|5wE nmݑ[$Y EZd7 sp ^./0'ւgeH}ϸ2HI_z/md 2. vA;1,Xڽl^_TE 1i! c"!D2x0IRSnXڻ+#F~ƶ8a BxA?wW?3Q{R?x*lPi&ߤ0KtG D 6 ld4IG" <[?%2&D!$/ "Ѹkw442T1mYMk3Y)RY,#"u\wD^D אּQYԖO(01dװq27jqo盧D7(%S) #J;jFs\@rdsS- ;FzT@‰𑓼hS'5q g2eWA BH{rHF)bNmOj^.Ϸպ( pӺP\wl Tt)5A 6#0^& QaOT  [ps dqA>kؓ!hԌHH?x>)gi銑[)+FJώ*UYE[RL>#}( Շ=!)Rw2/Qr 5 uC,*iq:䡈(و;_<)BJVT"QSԴqQ UvLUَ0U%`3r@f:>f)0bͤ K3![n&xyTÑv li= 8}= 1&^-Z[I*Ƣge)v3iBHofx$ Y(@ NeJ70ryN"$rk+%QpKd_&*N,%d%#ӄ':"MXv@dtP8Ya3CԲ$jՂui.)]RA^>Z4+2 ˂</Nn6Gr7p#f1Hr0f`lLnCѲ\cˌwe*ZLY͈Rқmc^ns_9 FUzֺAY*qfZ{ބHtAhkw2+$fJ mp2L3?=;60j6a"51de#̚ N2,F疢Ew#UZ.odeQ\mD1wigeл(XW/KLe2فlPو h#%4v"cBI9څ[yU#v 'c%(c6IdVսJ̙FF$f`lL80`s !?0JQ@"n Uٯ,V_ PS+1fw`̢Hؾ#`;!KLXGӎ6#d#FDf2#Ȅ!.J sb1peHe4 ^2RF2*d.Εr[οHqD2?!FgM~h/,rmUkv%*}1U O0 ͒DZY0\c}j#<;v8&`lc@V6`cs4ã16V UjګJ휉B3ʱB~LX!m47 HEZɏl6KJJXnjSx2@f# DO^BZ\bApz3Rxg&FJVn@)!n.2ԼX> ƧXWwOOwx~?xqFWU쵁.uE2̍dA(:q+iINNU.qn,[s4 Me,N.%!в$P*`r0Nؐ0i]zrC5 5zǀ>?i\ tt\%Q0IPrDŲOƍ"Im(LZn'Ttr&qO6b #o9BA+(љD}mX22ANn !m,vyEj+eêRV%5URJ$k[F3;KNPMfSIuȁGDFD ܬ9iA]߬wS۞p@ bUiJX2({s(L<&#a ҶG V" =NEdmc`?#6l-v-RGkNe] VVlPXZkAfv04ZmTJFvP5N%ZF@5G3<`R%E_T( ՗B9i ;J Iٶ Q͢yP^)is?'Kt 9AYC{`g+32 9Df3anc2Ybn#k1hceLŜ~pο#GBol j M<0qDƆh%<-Jѕ4ڮGsD6k@ڶ ROڳyL&iDge+i8Ѵhjx"Vkfx A~)Y֕e]6K Z=> h ,KCdx11]@z6&djٸvRYs4ÃP>ZQ{_ZUVFn?Vo7' YjTnq!k 2Un [26D\$eIC1adIYh iv ;5G3<~ k||[pYiV薶m9C>60K3k>KCN | ':N;Ql 1@5G3<`cC4Z>ؙܞH>3!j@I{}ꃞIkFFȱY< AHr #Ɇd4@6`-Qh+VBb.ޫ9Ҝm7($%֜def`2ǁd-|ȽF^KhrF ˽D+Wڒ7M,O|ŤC/ݻ/^<=JbFŒ31?ƭ !9I@­$1="` 70i9 يʌ=D.ֽ YԙJOa$ 2F&G+2)PyU(AHlBGPs9жZ Hjf sRBx WEipZ !XqL8Սhl\ȁ̬9z)IY(eK /KdZa~0,mıVchq\yalx 2vSd6~BT0<7<9#V$ E\RtÀfR+ ɜ#3Y. G6E G %5 YP,@+6i{4 aVD&UZڶc '[SE4E#Qkfx,KFI/|-rxF#J4,iqOyN4M\F ܶcl67&t9v8z {k4I(Ap!MeE· k^TG$4!aj̉[U'e*}H"}vaXn%Q I0r홸ѣEm<I&클Ȥm[ 2!VlPt ?g 'D׶{`mL(эi#FؚA0?rl@r%FnPɑP:yƕ sKJ05r$9m,A6`b8|m|+L[ZmmLȟ;=9RI25R#2#W҄ %?;1DmZs4#&F.M.V(V]hR!4tZhg[)O7MDS U{`1㤛-[9o _J5G3<`pmS{ mKE #k{A.C6%gҲMt-#TK?%˒9$k)Bv 5NX1P GDh#s⹘[haf qO%8!n*j#F{'iZ 11T;gs9 l0Zs4#=ؙ셝Ů_nfp*Zz{Z%ڶVᘚx>%Hv!Hď%j-0FF$Hښjc~ɸrgi5a -T eQ7MDn;DncʩRhȁm A6&s]|]t쪥gscs,2?}^[|맫7nQZ-Ke ?Z\zZ^DrÅΦ?^]/?ow7/~M /~_~7J~~g/ٯ/ϿٟfF z~z뫧?~X|o./@s{2JOݼ|>fqx:췯^-fy?QUXd?ٟn޿vV[lf$/_߼ƅXI>~~a3~a3 R_߆o~>9|R[8rxy^j5cyb_-O?#3#gTuߝӲ4N:?~~-n/^,..muY? ٲxꂏ7|X,n~$8ٛJH@_ZNL~tN32)(Ҿϒ9/d7Re%)s/uo}%Mi_k%'~̩;DU/,撸R ^*oS"9/\C#wgQnD; ׌K?7Tjܱҏ^Z\wZ'}fg˰+Qpn.Ϭ8sW:'̏YrwҸ R[Tq_^K8;s+/7>Y*?щO/Dx}%R(;zۧǭ%u>#g`xR:`g3Q t謡Q* .q'5FJaz]ډQo=bpTxiCtl Fq.~/0:LX3ʭ<ԡ^)@@^Txt#vBu7{-k\6Dni3* o죴J >kĊz+A"k?T~g{qfNָBA- $L|7Anq7>RWV@eZN~لqIbVm_eĮyďŃWO;հsݝS)%"QTȗ+\}ǹ>kNC#DNtsG'b V5֗ȵ{mbƽ?S6xah ƍP6okӛy3a8&ycYce!/tC_`komYEa[6ݦZs|@q#OW}ʼvi?to^zHdEF@RJrx};7" p#^Z)n6-ᦡbΰsnvVӮl1hʹ vKkhk;ξ`9Ӯ1VҦmKȷLLJ  3,V9vN\t?C s뱗GWo(q.ziP7~) ן[+ts L2z-_[no-S ڂ-Yhʢk|+t[][ +_ @mY TR kK-а8b5 Ihj~J4j..3b.0hKlDx]zc `qM"kgV}8yef㩟7~,o0p1ny2V ʳ,kG`%uFےj tӾ6 a,3 «Op^X$$~{8o]˙ , sG)qR.LI8WcjٞcxӞHhG+&^yJ&X<ܕ5.@\7*lҀ_p"b)og)r2t<&`wYh_̓)b~6 q|mN Q™,g*.;`UA_UP}Ou+-ÍG+ ?%ykzt󮞪8(E[Ł1dCO<*,(n{dxxMn.}~Ϭ()xA9mAi:XSc%[=a]Az- )cg`YyCcq@o `#6ތc &{V] 67bp cxpHbv.1!&Аws^:ޙ@&5O z=0-a {5 #@ϼChhz_/mG+bw{`-cXCݕ* @$1=uV yx!N^hk{ٓh?R_#o#qCWKW[AMa# !o9[#>ΫubR0y{ž;agޙ>)"]H-EV"ZIݎ]JB"ݍ7GCvT0 ^q.`-7fo`^=Bz#L@Tį`kGV 6>]O%?&~ Sre=: wS 0 ;2Z7'|A[Iq ^E<Ζ5q1KmGࠄAQ͛0B"p2oh 5 "XZD*r;zH;`x909 yUvL .ށh__Á /Z#?%R%| ֵV~-&wuh\8u ꗡ27`u) )xW~i *qrXJT^ !y Cfu4˓KO?848!KRa$,lu xm2@#,0 xd^4|`0uFgma-V+4VaZrz꫕=9 qxΖׂU G3# F| ~9FPچ*KȰ2"_{2x=_P`28;8dJ!c Kˡe 0p&x'4{4l :*e>Aǵ~\eXמM{C=<πMk'YQK^ ]ܺ-Sg+r,-YpsWMY0%Mmu &FO)TEr%TVBe&&TPRF&GptBb)$ dW( + %?7RB.o)SFLk$_pp=AJ"S7`ǹ QXfI {` ܏zV-(![ L.C| dO@S5)]ڣnƳrvzdkᑅ6,l%> 1fB\r Y#'LLS3iatNVLVV X&E]].ۍ㙆2!ݼ0i%'?2Oϱ*Iqp\hn ]sOhbVDjb+2XpgT1TۖW U_H֒>+u y XRaBHTtp[e`^yXr0AJKGӿ]}$S(sVms梬ŕ9r.8`{,K>WRqsVl{,KI.+jf/] e/_{10¯ 7)>#kfokxe=CX0!/~,!p2H qpu5gk=&wsD4ΟjO+b}znT6E{9˚s9̘`–SvB00H!uRaiO z\ZN2;~HfpHr3 ;Xj@3os O {moX+tv.?SWHO* 6av&5[AXK]/a7~36" E_#L8WjOߵRj[,C lM-`3Q#׳^}i0wςK p0Sdu)a'3 .ϗOL*p SySмCwu3!lSAgu' nYd/Ow?۷Ջ>^]uwk?mֳ*0p{*Ӻi@:5,uLTsoQwy<|G9gԝ˽`/9w'to;V(=naXmz7 X84 =.81m;3T-$xG5%xA[76)X ӔA{j"O֪eM1Q\.RfZmS<j|fdbFlZmGP<m 8D_cS{jɩ֨S-9&asu?jYyj6 ZRjkYКj%oC>^Qyd[F5ժZ#Z wȕ*BD`(5 vxn{Lj7G ix_\f"d6E2t.{7&57YcL]6k]L^TVzGCT7G4r 6,/ؑÐp- V0C}b[RvDYl'+eֳ֧6P) #<ޣ rfBԖ̝>uQɌOIʩSG288.Z2BĦO.?kӭ QTW`H}OʹE,9Ҝێɂߵ,iH;=>waGQ,r Vk&)U(ojwuC9Wuj9#Ή\٪"qBshKL'LĢ;4txYT<^CR%SCg07nIVĒ$J#˫̒=B,{ m-j #Q9rY* 4~zώciJԁJtpD7{edq{!$sOFVdid>}t<HGCܡ>Aajb :*eQ2jlM $XkuD0ަhgkGfkn/95HSkJ<-zdx(F&rYћCBXG "FEMhЅтqh%Ŧ{z MkfF](LBg ~TR ggwIx8NJ'HӆL~ =N:!eר./ZY#FDzj:2U+uԘbܥ)ydj}*)O2vi2M # 'Ҟc Ghixqum=NuGhpmp0A6&6w[طn_Zd9fȚLBO; ei$X"),,Ix lx}jcaƩ|5p=[7-a,`Ao\WBܧ6&`9FXY=j#kwwW2RY2 @*~c 2XqLmAt,Byq.A6& S[15 S3XG@Ew&ErݭLma&SS1`Lm,8Y4&SKɋ;t!21QZ(B梩5kC9q4Zڦmw(n&xEdhnE@Ng >6"ioޘ#3ư?pGZs4cR@mW=K ()16?Wպ?i{smcC i#I Yz{V5 mDZ" FD"&qSkWLXe5mH+ؚF ;mspL>qVWēʱx ( %'oSn@yii`ܭ9n+K5E#ӷmx\G#^7n-zőQYxqnָ e=%an#B 6EkcY[ښ+p9,lW*OZG3TVAdG>4 UF06&6]kم #Hֆ5G3< a[#lԊTcW{QܦF 6 BK쉽&to%Ci"d^,ݸf2M@n RQd#}FeQ2jbq؊#HܚJ07rE&"S%u*8owm$EYcr V62QhKm>9&bRA!Gj iڮc̅F0)XXӓ%-diX0u -Y;I# qCjcbiv:<ʲ#%ڣ\ZC$)㺀L/Icd^\%q^s4wϔan\};Op >w yd-lMp,ȿmVaTtplV&?삂nh aH0ˎ]cbb:@.-u7%WNc' _ơ,Zǿ$lbBضـNP43& 3@ ;HA?_% H̚D0)ə!qə#Xitl!;KoDv6;+SagR "gci3ia3{. %{hq,mxAP,ms,$,2K +̮dBXv+uIіTvwnsHF13Cw =ǓQJ#Q܂,_D2JƦFq - o2Eh膊Ex\ufVIM {6G3Uܳ)~2v*.Jҵz.E~i28)nP8U}Rɑا'H?LbU*fk:d6)BZtXI2MnN//p:mXHA=!HRsZFI a'B)uLf$o Q&yK!AtHRFB䇃 G&lr/a Ԟ #Fjk%T\ QBٹ!PԜD֔h:.-Ĉ^h070a3`=M }g']SkxcSC=PC2΃l4f#!jI}'AP "Hci3,c9Ԫ T26]$4.)#t^ÿmw펫l,ܒ.tYzt>G~| w Bj:~:·2!dk`#aHOw{f=,z>.+*,z‘܇3\Ð!VuYƾ؝݆-O(X)ۤ}J9> BpaoRV@uQѲٸ)!m+C#;[ϋW\X5@+8q52z!WU#pR,rX̐ &6] nP( BmR>> B jn`\P 0Cm4Pa \Fǧ9 mA£@H+D6scKS%;Ą O28c#!2qsAČ݈!+/ë^2pױd6G3<`Nfc,D\SsJT ܴ؞-_e; 6 Nz3ym[ y趆'bǰ7)v 1뤣LU?'4LLߙUȂ0 !=d2#gʈt+`T;ax2msFoWhkfYp80 tpLA`cFt2|ӢW+NHim-rqRcC,d % z(ds4)FG&l2-0D6H? N2| lw+ Ǿ!= OIzTNM\tT⸇}Ch$|)OW$|K,M28cPi8B}@6$1x 9iB}ȧZ*$r25郓#oON٪[Sڍ9| 7'6F2uz1O 3s(rF؝{z{ŋ֖ .-|\$H4ZFwR|-AwJVRѪ{7qН=VHN/`DPrLug.P$/Zс#F\ rJWj垥x)4vU1m4!$9ϴ9+HGo#I_iZ&&1[bTSIH^hLD0ۈ8mS4EyT.[BeJV7ES"Uع)4<[I>y >IggGFLHbD꣞x~tx ;JkJ`-mb% "Hך{ga"r+$zBQ!V83&rʉv"mKm:v{F3$s{.mJEo# ;MZS^ǭY ^wVe}nC bs4@7x#wtU`XMGdp# DNڔ-`='T`ٛ4;:{rDNmD&r!9&-bRD*uCfnDF390tԑT6}Ã栎 ئod/DCH$PoNm5S;1.2dc9P]>1m 0ɥ& #HpcNܖA+1e_ʘtgGVvaQhf+jGuf" $w-@[KȞG;+ovj;&(%L?$KX`^Y]34-q5;"MOYѲq:~7sc%gpMJ6bFmt%K>}p2Ozd jVW:BfUUF2rS;@ -"@ͬCd1:BQ7,vZG!MQ#K -pE !@遤y{^>Lo i8)w@(\ IcAHuKkuw @G}^։39KWؘ]Xlh$0f 0Av<vF7fPō&WOtl}8JKcEvJ_k#|n$&*zff맷ɏ|ɯ g.d{Ҵ~#;:Z'8ZfFXFźg늪?]jQs؂\r?gY#iI+yzL­bZir7g M >-w/K6'[8`]ȁ$BSrguP,ɪa*aY5j F^3fİ+/لDӤhA"bnՊ@A] y"/tw!AkF+¸Z%M֯ymO'r`Vnix$[Fn:lms^P%ѽI ֙+Chl7Dߒ݀:\u.Fдɛedž"8Ml]w=gg~*RCI,K=#-K$$ AA#IVsϠ ~:H^[-;*UH5' GhLқH _S(V.1hu=Jʾc"TƳqzE"%+PH4.}4V4<4VovK pcHȷBWݯERԁ4L݃5:TG;goK%m^Yh\j,PttyHl<K7=5y^lnXq&a|oWJ.=8vXq2)?!Hs c 5Gу4aE~Q$ 5>@.}Y^OАELɋfT- Yxʌem=mjC8Z3DY9Bq.Q6NsO? @ D@|C-{ MPK8D`uz2 ArduinoISP.fzPK;zfritzing-app-0.9.2b/sketches/core/Barebones Arduino (stripboard).fzz000066400000000000000000001215361250202676700253460ustar00rootroot00000000000000PKt8DQ}:j!Barebones Arduino (stripboard).fzkr#I&Dh٪nޏnzTudeeo A`U$&"s9 Q$k7:, 7suSUS{/?ތ>Ogwo_1B_w糋뻏o_ߎ_.>LGw?.~A%pI؇Kjt} w__7fꯧOFx/?NN'wo~?o}5_oo_U_~<ϓ7Sݣ7_W/󫷯qFi{~jt5x5Ji #|z1nra:}Ż^>>\_i{5z} hrsYۋ=tۇo7/ᓳ5xM;k(C'>=N~#<Կ^^J#(Q}xE^Txń^\lL:^XxY^xxSE^lxqp|MLÔXU|W_]-%2K8"G$DL&f,caOoKL^Lx_\X KaI4,ɆEKed /:bË#qHq|5 YHNVUW_m|uipiPiLiH[i"5KŒ^tXaQ@,JE(#5񽍯.]_HUQUQU1v~b7I}īxQH7]xtk.^8*)Zʢ,**Sc'<^ǫx3)bqR8XV,+'3+kᅦ?hӅ O.Gß.\iN"( \z6=Mg`3a4KxfUxń^\%`lRQ 6JQ.BXP#QBոֱ LI2I-Mjib0KR1Gy(k̢ØR*Ő S}444_u|5W_Hyuqmiea]$D4$,.KcO-\'\|nŧf l [qi1 J5N]U|W_]UZP ӄʼny3my5{yv7܌ؾ@4iqgYld~7M0ӻU[aytus R o㌙__w xӍ0`G.C R$3UE L2E)Dqc=O*'n=%Ð5?rDCڎ1Ş={6A"Nc*D!M@V$BCˁ R˞٢/~:~¸Z*2H><[\8mw$(f*ן;-S6 ~𸭚£jqoh8seKr9voV Yqj"50t]ΫV$ EQ.wGD+=K {[6;/!=HbK95$He8P(B/HCMX4b7g$whF+x@[X&8Rѣ lj2A&ߚ{F$^;LQ1(MA3RsI8N=4Ɗ g=91f+fPu2Q17%?<|ϟ>>{̞As?jZlf@D e@4VvN 52L%vnQPgNF*ٍވiٍp]ca2ym/r9[uH;+d,9nVtTc3rnkYTl ]C7bG a%82CG9| 1TsYurḣŏt6%E<ڂƑ@E>etTsi;`E;];ў [mBd; ro9a r!!A s܎U=Gx2Z+/|N1O*daV$#CKX "}*>ޯɰ;Z&odXK1|xd`uHג},HD橑7=ə ek]mt{I~lTC5X0 cA~[vCZK*KN_[b_J1y,LUzS(v%s)`!t_)u[Ia#Oу G.%{vu"@]91+"GA3Hsη/V =fg<e/fDR2ؗ9+2 >#L}AB]F/YtR;@VR ހAf }1}1} \v֑7בo̬72aZ< n60mzj)uqR;WkЛ?^O{OI-9xDrKT|2ήě#o`Q"֦mTZ>"`;{&<T샬=AqsnLqC)uٟ9wԑC3̂;nɅ#7O+i:vaz-П$j;6N`{܀+=I0aNCN[86 }`!]`DI`'c@`U;]crP(‡Lcg9`{RTNg3L^X2X##wHd@(!(^fPR.")Nqf^*4VcCKv Bǔ٢\HVvgD͈ ;+ki:dmx}ygmo- [q3Le`۽ pʜzKw&MNQ4AL&<ѣ?&+S|!ڌA"h a8"vGj3raJ -5y `HdnNw'f3џp @OR@LV˒ixQ9YP* -3}bd2Jm7QirǍ25:_2u=par=j=bN"D;4m/a#{sY2нaIjF E&}Q͜+_RCwk*d2Se8T2/| 3(}A1˝߷AbTWSd8 S#dVta8Зa8s8Ř)yn̪c$CŜaT`M%@-a 7#?.Şj-rzsя/+-ޜ}q>;?\|O/߾ t"/t4 2js?wߜqxٝ`rwvp=cӳ?ϾLF7>˟W5z~3FYhM/x '+NBA+իDS6)rp;e,-:AHpEs>$;鈋EhNߜ-Fkڡ]Z(,6S񈙕B\[=-:\ɹ)UN+$p9w1JLjU\sM?ԍ w @E @F MQĮ_>3Ї4SYdzfJcsp>]{*m+OS*DOؙz2H,yo̵$rϱ$KI D4R-3ώ!x«綯.u*SM͍n^ѪwӇ7w>R^䓎ֹ}d>9~6 >.$3/_ mTZ= %K^燖?̼6:N߾ ɫ'cz'KzU)%Qh10{gm_NӟRbox@Y. uDɔ5 7mp2v#a`b7a<= ;^' y96{O5DO7^g}RΠPU 6 ][os3;;t f 0eF7Ӳ>0)ILlQE4V4G 9*+AeOW *-FPm풆U@`'ZFϕ=|kZ0}nnqo3nk+1|yľ%{c>׈e\o{NϗOg)=|^@&[h}+7BQ+a V(r0f2P) j-( N02@939VDr4m4Dd4r.9!?r]r4h ތm`5%x('. q4>at9Wp쬦sIWjtň GgY1-)YW#P.Bu_!TV'ZEQ$ L-ju;LZbP nVA9 DBS]{/,x_0Ku\Ou{X 8كuʌHLZЀJw[SPB(3: 9?meF+ `$U A)in*`cnFS6O_Noa xlL}2vz7۵'u8#L򰫰ӭ;; u׏Q}TU"vk'ZQ1 ܉V *IW@n$]e2`NM]ӎA&]?4$=&]IK3S8ZǧsaJREǑQ+ur ˜6[ 3°vU$FrjpJvGB<>/L3FlD>0ܷE>agyuZ K F 5.Q Ojf̯I󯣻/WϓO/Qh]j=՟_M?^͗XÔ<4yz]Ykg#e":T[dt 2Ea\osqw?./>^]^m2}Ȩɒ쯏^g&wg>f_|HZ?}LJRUgtys WO-Y}OO4lC:a&;Pgґc&8ab}<[bCphBσ6~?^_}|=}تJ9{.jZrkkI5Fu?OPjoONFa)3{Y3S3snmtuCwsJGs ~ z՛u^GEm4Ѵɭp¾ȍNvƉ͈7arx9{ݲɼe!%@΢s?{^"]8yV &:?Z˪7q@ .3bz)]t[;޺|[5l=os}؁֭>xa=ծwcn3E8kHnlc=0L -`hq ; aӚ%xf;y DX?Zcv«C+CIOW>系N;"{LH bJ;\`D>q'^0xi+)z[tAqV5{Mt8]BY 4 "訒UQ~ЪR(w>EY=f:L$f ']ů!:%q-IQՙĕ| 4T7ХێjZm` ]T FLj?ܰN6\m.YSp*v5sbRz:fÕ D߯ b!w@EՍ`rC4/;x L/@"^M3V!wjj~@. 7LVRMOXP*C{z+nA˟W,;gu}7z >.&) Ո3П*1 Z?gD#PV7od xqe(]kp7=/4To`EǹN_ބ$pA΅&j{ d-:n'Jwj&Z8&F,.!\1* q`)If*E#8h |]hҩ; /.V t:r.*Ŧbq; È|QЄe7(؄zl p w{Q˸GϹi|9O.'n,Ǝ'ZS3lsNyk֭_C~w#ٞ߮3c@MvfA\C;e~0D;0%ZqUԆs"{=g$QøQLIi&ZdyUfwYOOdJaTq PR^F|$H"J5%$~`V6A c };~ƢAाjSϭ&U9E[1δI=#q%Zݮ&"3SrhPW㧛7͛+a ;jEzI"P~} DhCPGdϸ$\B*B~"݉VCs^P(Z W b& !i3E,`u/Em=jVCc噻7QOǴily"LcȗJL=/Sݨۻt~,5ll&|2rabX\\(Y_ꢟ}yֿK^~TeQiY(AK߶R BpSVÞ>;I$MIOׅ#Z'ώ2[Jv yn=TXevkr QR4 P+?u|YI*C4a3>M,TFw4M* wm%/:\]qŽ{S K'ǎ=奋<ӁC(c`W,5 Koc&\"H فR, kly tf oߢ䳛Cªϫ޽]v8lP柉Tݙ+M[ a̕J؁ Zw4=pe 5'VA oDTfx$uHL"ԉZw\/Da}Q7@ 윊9uaY(1q|x-yL/6+%*lPDOi SH Ii ۛG.7w?uqt{}^yK\^^gK5.&^&}dזaOKn@a*&.a:\'t=C6kK&p,<0QÌ%}V9r P8%P_Խ37xN^QB%dòap  (y]"G!`K@BS6"u(lUXMmBB%`òap #ABl=䢤=m< T!`"/,MXQڶ{AG!`]!l¿¿K Gԝ6QӮa¿ֶ : 5NQ7f08pͨQXQؒ ^C\uH!`kFs@ߴ < [v/(+8Y& .R5 9 [`.OqqVYB֌ i07x^QXWqL0 \`3j%r$`Q*lmKDSH,T%h6(`EAe&+ElC  u'x?03h"c5 !-@j"-)0pisAeR 1 (vFBVd @ 1;N1[ Z]}̃#f!%1@D2HG2D /[%L(8Y^fA;>Rxقl%U1[xY⦅rQYB̺%f3QYwRق]YUW>iv@BVd @ 1;Nb`&fQ<8bB 1[bud 6 28{̝6Gj RaGa_k}u'˾tߐEJ0Qׂ}$%1󴍖KND"J!PWg04h r)}rG(4 iH8RXڶ{H!eɲ2 >`!Hf)C) mP_ܱvX" Qyp,]cOfUQڶ!Gb݀217d07p1g@Я%@5EY x;i8i=J}ɾmBS%_ 0 \| 8 Zik`|'BuMQڶ!Ga_݀Ʃas.B hpd_(y^8SB3V.0"c y@;A)l (~: t,@M 3!U!$%V'yhQ%UWF>1̞v̚ū-jfD}̃cf103c((=n=NqQVNRܹs> 3{2v̚u'L?P3r )lLVvF+qTٓf%L(̬8Yf`003(pomTV!#nÖ[ppـ;ȅs O{^bGtL^аmBBºƝ@6@F6F^!ʽ@"cF  /BaƯ hAkgJ k \JQBbޞNܔ Î`uG` AmƐSi],La3r5ی%*T_4*F+ t&JL@L"^L-0D1 r@؈,(R>˲ׇ<8f*la%BpTZzE@Rf`iT1EӴRgݡH 5hB%l4pPF͉yl!{+\aՕ2ԇ=xƔ2}+p2pGD 3[v/),&F?J9cH!g rP'TIZjFdtl^A2$f ᎸXC+%U%q2Uh("Iz(0S0L )an0yU\0&HZw@RZK2ZBGYt4.77 qLxXZv4FgLK(Dm G C[v/)i !3lQk0RHZC5O$#/|XbQ*dhC #pOJWv$vkk$u"'[7kd` {ɓ_fcp+4D:͜J(Kq``#.`}giaaj#f;Ѽ# +4 n#j!ChRO(Rj-ɠhU#.s x%.߂p=JC&@]Ϣ>34-e^bW -D9S6ď>;N6|VL$a3tYs4G4[j۴DHEYeDYg E 401,tVёKq[vhVv0M3# ,LW.tl2v"[ N{Vي5ڄImBz9>pֻ`v}ċτ1ĨqskD7ף;C@ߡ_(ta#+ EJh7rҹC3- !%Y;)ɢM64#rOgE`>(<ڹsOw8 9[~B^Q"u"I2c၌l/kQXK2XUAE J~*KbX舋%dRmJeBǞCn  "lB 7>N6R d85Gst)Kj6tFj"` hrG jy&Ra゜+(Kh)-| "fzg5D`GIc:Nb{e/v-R领$NV9TA-ZBš:e'(\ܠ- P4%mB"Ml>ݾ}5h%ԙq81+93q(20 PioN &9oFƝ@n1\SW،u%TiUwvtˉoEnaU)"J%reٺ'ջQ(q~XR"gk$%C9fʂ .FJncs4GZ\;cf!1Pjext}Ӈć{d kv*98ܠSg3z`1`%Vb`ph:@ jF'j]ШٚI<]CU2>Bѳt)XdRhk %!xvM0\ a3zJ1y]n;r$ {C=9`l'*ȒBЪXtddaEˈ 1X8i(( A g3‰DpB}=hHu6_Gw"w(\:_ӟ۷w?FOgg.ޝ}÷[Iw]ߜ}|dϾj~{#|N./>_By|Wnr;}~RWasOշlכh~ӳH_nG|:~:ft0yj,^Y}f_Gѥr7av}17?Oq_HJ߇k}s7{j N>^ߍoO˿SY㣛C@d^7I.􍞆d}ɣ_?\|p~54MF?ί?fFbϷn4&ǫAaa7O;H|K'ܖK^|3GlێMFW~+9??ޝzyѼSwͻ7ў}q".8E8㻀}OX!_‚s(7bXٶΗe4"TTq©.˩$1 s74Yw. j,4dDVhieKegwމtw<1~܆ϮPӟ[5]C< 4xPx5ǔfb߬cd_4':S&[YMBlt-[ͲwU2%l }W~"Vfv["P%heKuc" +l M%h[8>.;eꒉ'>A\OϬ Jݞ_s9*ߘ+Mn'(%Lsͦu3D uH pxVmiRU{kYZq8V=b\r3{3Joo~#`N擳g,kʢH RZB\Kˢ۵_Fy#ާ~q?Q7 aPzzs8+ƚhV!QZ8كZ(jUݹZ]>j-& \,bJc.92}ݾpb*"ł%ܫn8' P(j`q("DQlW FF7ÝRCJ +\ei`p<4' &O]4ʕ&<ÔN5?% ΤRzc5QvΚm%ڊ&Q M `oP`/ (OzV+1\Рnng t >XqfUCzצV!̪GX vU}\{ FLf!oƝz B,dqNḻKu2xO>(;WUKڣZ[#%HJo\R.3kX-U 2ʉC"Vt&w5Ǎ(}7-񳷊Zv6 >#G\+6A4pcIgMu&8LpJ_7Y?C7d*g2$6v[-̫"֙Wm=֡3ڼMBַV qQN7ϠHan!Ian BX3m,,Fx=]-̭Cqch37 W q[vOT)ĭ@9Y3MBPQP%q3h7V)McY[( sPܢ0Z̍[R{Jn ʩR7nꆊL<"u$-[0 SEvDk)f{:{62 3/U%P7pͦPhbxvHfd?MCַ [ VXJg,ʽtxd sDk8 u|Pv{\db3|! 鍾 HQ"14Nݭiq.-7#a؛.o6yӫe j{)~ E:DMPuJPN58ΰz0ބ*Pf!Jl*u''1iV:{2jDI`:]ۺ?J䂬!Nps¤Y_ط[db/gv$V6s(>"*-36aspmٺ”%m,aVeH%ocC ,qoo[7Hao]"Io k-{)OOL%|lJ--;CcТnֶ^RX[WpreX;6]bnkf)K$)m&D;U(̭9\[v4H][f mƀAKo,u)JD )17Db3%doC8L,Q 6,,& w%ݎO^[v4GpG0n涾^R[Wr̍s%MlܺP̎E9n5Jܭ9K w Mn1[;e_h)m}۽0dބ*7Tb3%oU"+K?J5R$J3SmamE @ kD kXRx)%E%- .ڲ9Kdn m֦AKam+u('T kC$ k"-YFf\^H[V n B2chvqpmBٺl:S$f)K )mj! ۤ21E\*Tn*Ѷh*g&n涾^R[Wrʹm̖h&@ kD k[$Q (\RBJebؒ$Tl*-;C--36msm•ۺmۢ6\b3%ޖxl{lmPrDՍP8 {֒22Vl+n k֖]H[BYHR{aJalɩ6|>c6(͆zNQ%Y kmViN6fXZ57^Zv4v!k m Jak*u' Ysp5,a3t!|j4q5!8!IJ0D+XDP (rY.?˪\- 2u@{PڛhldHGqau$@H5jA GwE0 {3Tw@e6ʽ\ յ=+K鎂Kbw{26DY^=nN6 jF~l,йQ!Gԫ,]mrD證[|vY} Y0-\h3hHE [6GstG`oPE.Xɔŕ#Tg7CS¬eL7Z-^Ÿ9 q kOC;!̨QYBBy׶ :;0٭ka3P2eF -݌V%_a3fې@U 4w FnOCb\KC۷Wn*3H$:εm;f1|B F 9kI=9OTUН۴ <n4"  G\_GaULRH?I#U~- ")+VZDJhs4GBh(. F DEJrhE6>SaA0mK~&`84 \GBRY*gLؓ [r"xJ&E&F86$Hx9ʡWU =0C$EK:x굶^QW7q/ၔlFźCj29c \|\4 *ġ,\$059Jvt| >`:m3Ɲ@A,vV> AB AkI=A0:"zar"U8搙F Yh'lGgA6͑`1G ;[ on" '.La3>֢'JxDQ5Gst)%ڕOq=h*[8bP+\!}tM[MNRfuBkX2$$D6HahbHJ8+)c،5Gst)ZhPCUHÜl)͉"[H礪 _ܺaȉ/O0Bв9Jr.[wP`GGJ1w)^&ёҚlmAT%K7'+\S…tfPBmWV>kʭUƵEwCx^U(bu37iR`\f*9#ތ]z l̨6B+brl JA1.60{WmܫX}؃}WC}Πej O8*[:V{JBP?uX#ȥ8cIOq1$r@s/}{ S;|#8ICqr&< )gBt!'tX 8f(F}lI=)3|u; lE2+ZK ˆA}l}`Wk\%08{d1P `[f*h;x;6\eCM0!TXYtĠkM\3#yU!"v+"P(Z]=N.)>z>Jh;)Ԭ%Ԭ:}Hat68rV^XAvCF\l!H_X7D-ոB. 3[3?ct`LBֶ I MEN:&abqеh%%$W9HVAaDiH&U᠛tWԩMD"yAG\nU2Fw-ogВẒw AW Z{c_N:U,P&\< [UdBb95= z ݤ}۷CˈQ1:0B1IΛc9! E ½-1 .. 2N)Az型5~d̃nr;}jv3=^mϓOӐoo_S"no[B; o[,bgD-i=ժJXy[K Bj[8a&9}>5b(ڴ=2-WR*Ypx|rS}k!zjqZ^BÜ&-|޸r\S'-j!"6>-eΓ v!KvSU\WXVp"uJicRq Q$8u r8[D"D $M۽PCBZy1Y'M n".5fqWHZXJh14CS}H!f9JUQ՝F!dGR9;zcؖ!-B%HC[G? Fj*A #VV&k{'@Jm,s6X[hsSVm$\AMDHj"%]:kI\M՞<\V,a61]Q{6ٛ]RHؚ9:nG*-*/Ib$Zʳ5TݎZ{pM7Ό&+q0qcpfJ,8[s4GGBךtMϭ͝!io(MI,ΝFJV%ZU*KCIm m[3#qHx6sbg,AI9^B7!zڕ۸;HakIJRd] _NDDma\'7zD*J\ B 9k0RBi v&{fhUMQjRu.,]?4oP(Q%()ZÐ BGhDHiGBӚ9:Z 5&{^ݚd徒@>JNhʵFCʦ] 1ٛB̆Ѐb"raK,3k"jz4uH&^(m"$:;0DN9Ƅ)Qjt %$.e(mb~XT($1Rܪ+ y-`4='z\Z׍˱40CF{C.0dtL_)lHu!'Gcav|(h!%VB4(4QY\\<4d~ ԇ=x~V9iJ-l0^ u'>3+гcHgGJ9d䂵86$fڨ^Ўr9Ja=@(0^ u'Є)RYs4GGg?^OV =C>_Oaxut7}u5}|Poo_S"no[BفJ/)N9Mn#rOvMZƵE?ZR]4Jʓp8n;cvVo7p.eآ`xrh:lN}k5RHyN2?NUԏ5ץ0Pb#I/{h=CB}љJWf=8HB3Y𵓽Eop!p ]Mgvqj7,~ ѫp* }^Չv*U^ƒXyU%5 KSiv4xxYc/tQ`;R:VD[)t*da3Y`4\O ctFUvI!Bޚ99 鍵Cqz{*Em־Dha(0*Y9LxO#@vp2,M|60,cjib1.^#e Rqʻgǝ ^z@>HPML9Y1Q)ͺWPl6Hm EZ:* &*W[nHu!h'_q/H!kLJKkPR/8]=ӵn,\C Vol,;MTcxM˔`x*Gu/@R(/BB:D>cHgGN.fS%/ . s=Sn*쯏Ӈdzˇw3o/>$b7N?N|Vx=Rb̒+E:6…|Ofi}ڜq!;s/;j=ϵڛmls+1]$xpjQeGrF?Efe;x;mu*JXcV cvǽP^uX{Rr ^rX{Kw ^\ 2{?͝񊡰W^cjE^X<7J%RީbnJt^{th9cE+3tf8wɦcXq$/| &{H6K"`'q{1>c#g[)ͥvz5jV"]x@+"ŨU5 hn݇[8 ٵE@ z@y(Cr;7 5[q #P6[nFK1v!%?;zFmז"H[Î^ޅ~9T4DLjKC# -T@ve%<9Il9/[0R' C= FbYՄhg6*4PZde Wc;"J!xB[hH$G<0 htN!Ca{KJ-63iY<[ sieC0ijV} dWm'$q/Ɛ6{xZq4a~Zs4GB_J8=\+]yx߅uDҺ4ȁ SsDGfçpD,.p1X(D E(Hs(8&`sұPP63uGfc1^q~dVk'pYqJyw/}vq+Z\΍uN?<"Ͽ&ӷ\_̯^>On>M8a3:ôn}WW%RP*vT:ӆ?^M˟ffyx={KF/GӻǷ4_/>`W{珣?7û/gg.ޝ}÷ξ_~y5svEdz=L|ó_b_6;GM&^Eba:ͧyh4~a>ͧ?܍Htkߌ|C:ͧ뛋hj9Jxyifly-;ёU#a[ƿOL&0th~xɪͽ1ӇUKy?>ux}n4$~f!_u$1kn|L53{MsWcA7HeB;S1,HNYVP?,4ы~**{NVW&&6NWgLױDpX0jP.{.yI*cL/QOt2|毟Woq={ SlEEIeCxF.6b6|!mwdgϽXq1U_"Nj?zǭuz΂_לpkd>Sz(tDx$zШG . FE|ZUÌL~9Ow~0w:i=uSEH<85|c^׾UC^-!+euc$^䋿.\V"w5Xuo+5wν˿ntb 5sr&~ L0ixEu?##Qf4K?38T2tJǷ?tq2e ^|Ÿ|^>`UD8Wx=Y# Q#pdoٮ"br`Šk"%T-SWq$i "\+ⳍW&I|%mE&̆a)Bybi4LSn+V$$ $KO-ۦn-B= " Z|I\\LzjR/;*lڦuА0{^=Ǐ‹DXfqN q jy^=x2ޠ}v Zfp]T_#z6f!͆STA&ZR`QS`[S`a,48_UajAUUkOпl|[ѨijUbf}XFGX"HqU0)NiX_l%)FdQJ& a* nO/\GNF lqMV25֗(Lxoe&-o?~lkS/q4aڼp\ތ:,v $XX{k( DdžaH |M5YH7x˖۔`Qkٛ(n_z ]&="xHJ@_E.Ft{8MKi3avbִsӎLxmmʴdӮ1%[_Bĺ%8IDljahqd+ . 5 $,Q]mĹjL,'$u g?P ӯe8Ekź {? $*sc|s4xp~﹟_hjAݢQ5F=Y4K/R`jKr% b)kY Tm)൥V-q,f|l$I :LgӨ1/ǣv%F鴐G{Ⱦ]4"va&l7ACe|̫O,Q6"Kdwj D[tҙ"(]"E<|C,[m=N5OJTW(=SY9Rw#*iUWqGIP} moD'1.sL&%;*vGL3RDXS 0=yŢJURD,*yB&#"=)rK%L\}f:Q,QӣKF`22(J%8u,$ᷡ!+>ݒ40k/ 3FX'<\0NA!cM0 d+]{)+`i姥X'|!,0,I)#\ܥ@6 ay襍f`H4(XC>Ճ S0`i3].G{Gw @fgH G kN ?%Cb>Ιc=$Hh;lC`YS#{@@k# 0xO@b]N}SY_bkG mGUЩ;(\pѰStΧR b0>5&Hw|b0$ \eR _x 0:1x6̦["u{[N۹> |d[1䍲_%-߷ eӽE;4MWGDL;Q?ZcOȏH].z(}]C.z7ݓ.FJ&H4,zŵ](? h !Rh!KT2 |+`;"=n{(OūL/g(t¯L|4A5^$+~5>U=xf@cGbU&ZH~(J 9@~Då+?hhAP(rcPO*N`^FˡI0 ~M9w ݨag붧GHSwƕ!`I68Y08H40 z#ѳ&a`A}|,@kSXX!|v`|5+d< MB?1>0hGϤpIC}$z0e/hí ]Ph ZDGw ..#NJnrNoߍѰLKUay@[%")zS.iOVR!B<lI?rm1:@x!+H D'g:#oL,I/pK\p zm^00l 0tG4\ \wht?x7~*[Ъ (,$9 ;@/~ 8hJiUE+QcA@GOXڋ+\ [з-{zd<A<[ @mړz7^[h \CPbCQ2{hE~c.K*XHdzh=%!ዂq?xAV F݅D`;; ډE`1[kϘ@PBm> | 0o1`b rT4^Hwc($?-PŒRn$n *.hAIXh;jocp&KHf|.5߻Dؙp 33s_qǞ2"ũ$c~E`w4p|`0  t8lB1QqHJ O&\t?Rj+,qR.B3 }) p6ډkrGS _chh1ch@:Dh39Af f0CXKJ߿/]Ec%!ѽK?=rm ݅*i>W+h\aZ 9=8&ni7 $&܀" Wq+,.fԋL#Xpq&;d6|tЛ(1E_<@JcJ|NQ? 2` e @F 8!w_O!7e`c80  y$ B/@8FxMN}bw'lm3,/'@-d_ƆG826Zĺ ~neQM'h?<`߃ۂ k='S[7u|{n Wf388pdĎ,j 5d Nq.v0PNOGM%[sdct}j)G҇]CݨrP:rZ^m!OtکnOڡS:UQSNգN}щc™dF3o L|lD5w D6K+FzoD>F'H=pt=aJ"dMKAfX/uҨr4UDEډv|g28TѦoB+Eb$@b_`TnR2mc5'#za&Jh!FXJA}I.]Eߌ> C?cg]>-DzhWFq}ӌ( thWe&UA\L~cxiAw o'27f<GnE60ܞa4h.\4\lqROXx%q0l',KI)kFf/]0eSFdtAl5#=C\01^8a}㸃 s(R'_zSNzzx\>C;a8.%͵YN~/Dg5nh= a|w۲vM}۴Hy1(*7iܧFE$s '22a#s;"p(ty\Z0]/di݁&a`\gA;G*!ghfxS\`~, wx'0성]~'iHBA 5.Vk p-My=QWuEѨW(I~ 0=!)R nM m B0з={2pAJ28qK p4z, YNc0v2 rQ }?}1=6Ep@.?Yin̫v~T[^}J?ӷ/oǯק_~}z~~{c?~L?'55G~M )n}yZ ܭuR~Vor*'6b4X 2ՍfݝQv(NuRaJn-zm=Wt6eQ}Ӕ*҃jQ.t[)]cw[c913EL{Tͅuk AJ¥r +S!|վk"< <LWؑ#8lUnb"=mr:guڳuӗ#=UM?VfxSiSl<"K#;ʧ8b}9bX`Y(|pIj7!1v$w};"$;̊-ӣkd+9gvźʺb}xw}e ,`< u'!Na6V-vߺLL>dpOW"Kzd9vGUC![}ztXw;t~)|֠s)^}r<^)Nrdvߺ ޢ-'bk-cOLDe0+fRl2AXIXڸݷ.Ke0'ˤMUeFɰڸ7&ն٥7E,):ZOC%}cmj^T `tr+MβsqeguJK3K'\+"uMuX=x5*QVf $$e rAE- fΐtD9[IBZڳ˱CzBKА+mi>tмհ)\9)'k&©SZYyR e) rL@Rg5T_mz#6>ȪmM0k֔HV:|5\Jz,aV$~ E6L5)t9>1JI*9SOY}Uu)#(Mt D=C)߰^Fi:&qmIcS*8]'r;Po Y#t%n+ۮbX-6;$BpPoՌ޴5V[Q͢ kČEuH*n"ߙrMkO[VXǸw WW U=,,M-i!dEu+v3t+I7 ,]{=8 AXv R֕jvˁ%E8XًYsbޯ5n}_f-d\J%’8@8R$<[n<U4Aي$$VU,VM[S',Ӧ]>\>7RBS JM %- 9ɶ8lM K5[ $,܊cۂs ʦ`;񍄢Cj _7DXM[S$|Lf'CeX{2e,mZk,ђZk8C8^^3aš4J8q!w-n?lxͦ(\IjmCמN\!Y՚\9igk.ז v߃P: đ8GXԖ$} B UX6Rщ 8kIVk=&[t ։q‘ąHr>^]^/YƕG G +]w NUpnǽ%>|_VnQ{֔#DY%9R8E8$A[@Jb(#r,VM[S)v MWltkiI/&$`+a{lS`W#Ԣ aV ,֖});DQt2+Vf֔+823ٖU<*=K3\\Ve֔bjTb`AV,Ȗ] nie9V,Ǧ)OcӮIgX^.l)+)Q1tH0;\RY-lqv 3PbovW{)*aqr]v2̢^ a^!oʫY7=>J ]{^)Ndfl-r͡~kRt6dM6޴7?3oXOt5T ƳnRYӚc տXgX/I{UFwꉕa ӝXO[S['p6Xu>! 7JU-+kĜ,b!ZǕs I8 +nyd$iI*B^moRCF(vPjit%qeczLl֔fm t,3YJubV{fYø qۮ` Zq\M4:zIzg8 ORJx|Ƣm7j~_k$5ho5ՊWa $\˫l*U{b,s֟>=꨺.rV9mMy`%P(m]i>eeo$DwTMpL[&;3)afHώ^p%Xm OXq])hitJp#b$EzÕCaA~'> Y۲Tĺ.tYKy2@kʓ|pTY%s.B݌U3|aic ݸ7Cs=~ɒ+עc )N>aIwҟ7a!n˵ mS;6ni#0VTW"BeFKeQ5$/,TG,qoNH8"ը֣:xH۹{ngjӧA{Vm+HTapm2 gk^fV>_tۅ.=uZ).V}s:-wK50EXg%qߡ5KÛsQQ(%zh9mښ,Vq*R6VtC3k;$+KX, #"$( 6]&ۊuےkf]"FHѸKjOmK?$%$۴5qmkfntNʴ䘵uI+n2 =i6U"؊3ۂtH;AB_&ƼVVj8>F9\;tya6mMqp6d? ]EB+^IJZRQ-d]bV ! Xjy˱6mԅ +H::A;aĭuEȃ=@- TuZ]n9+V֔785jX ܤ@uf]i#jeeu2niťGӈ=OZ|WDX.d b8L8737WY%8̗1Ye[SǕ;.|MXg %9ra791Jh65۪ymښLV0X̢j6@~.A_plgQ1$yvMc'mMuIԢD.V{mKybiDQvj x14s IWsκеgk9uok󋃘qx֕˂upI35ƽ_fl1.H/<,=V ^*Wɼޮ7^dJV@ a6mMypr5AU>{2Ƥ{1`fYE9,$y#S-ν!"5E,93ohoU:hZ4-N˹GXy5::Nϼe [;$+FU`gSݏ$Uw9p"YO[SK'dtܯ`TezI43;HaiݙWXBZF^)wIśܗń)S+.MSrHBܵ6,b)BMmvC ] Źx>ŷ`묘AU>ts&$dՙ`#s*uzګOH±`%+v+zŁa_%ڊikX--]V+lkcCDHkB`hAOkB5^i?OqrPZ+’d.m\u_&jtuZ'u¸ɷƜ՘?8(X,Ȗ 2*l\*t]%fp[,z1f FVcT-?Y - cAgSURezp5)WMv"MUrfy/_Cxǧ}~vҥ[7Mo+nǿ\3,dsm_Ns>aѓ?sUSNZ:ܙe O9)L S{o$T;5ʡl&lU++!n5*F9GE8%jK8Q5.L:%<&jcҭa)ך_ =~4.V"ד|} w9^9#vFM[.j>Xc\WbUa#ᶔ|y-Z(w_kӋ#0sjTĔe*aH9ʋFí J;#1rx]T6ڙ9u'ЮFHayZ(]5~KQĶ,S۴5IAݮA .H8(樵L%+fyre],8;V&,݊ۂP_֧"Ωma6mMqpm&b#rHΐ̞!#l2DRLj+9vjdLnymIܫvIN%I5OsU m '[(3!4^ >lcQ[657Y&ڊUے\IY"c۴5QɒmanR꺲͒lːw7Vw'Ƌjr+ɐ"ܲ)I~pr!f}5x+N x[$w-l3iU.'@BٺNy^5:2n@a7mMyF=GM1!Mov5A5R[a4ڄ-:t\ƳU:_YpVx<Ԛtt_`k*GbuIrk~9>tҝ׫i页p_XO[S_:36+o<1iL#I]6ۓD y [=iM !98 F-͓U̸7.Pr߱ͮށb5WO -z 1˷ʁLwZdd)Z\ٔMld}Ymδ;D,cMMV&,֊.&abbM Bwݚ Ą"++ϺmEC{$o8L86 ^nrjt.-/uːy`Yʀϸ7v{u| w>dL|o17͢_b>F#P-+ 4[}F>_p#a*2OEG,`dI+o}s=B/`vJXjF}L+in<E=UN3F딨.\XFaq{oLjBx!DHMv )A]5?8TYө+8#*2E'>#GIcLuÒօ &ߺzsRE8"٧‰r :0;3CE1I(7Jh9gp'W@ m9p)3 P_-}PKt8DQ}:j!Barebones Arduino (stripboard).fzPKOfritzing-app-0.9.2b/sketches/core/Button.fzz000066400000000000000000000352431250202676700210630ustar00rootroot00000000000000PK,8Dm&HAuGU=AQcԐOx艑A2?ul8scvIǃp|?~Kd7Qڹw,qr3 K}A|;:ovb~w:/9Gp<2]Yg>oξ'_vׯ|6ټ?'?|^̯93ژY:^]Ͽ9ӱ4sW)jڿun,} c%b<4\I!"۳rE«Q|u׿* { n7ggz['?}{{]2xۻt)]\]??k0@]^qsz 9ݸ*q|/Pͳytr7x=M|uË_Shu>ufד?LAd^jۄ~{5,2ܼJGpuzӟ[̟?!zr3OϺ?kN><}7쿙Rvo 'iP~*p8~y]|dShz_f ͼ;^zKkSmϭ`"Kvytjg<8H?B2i~kyo07BϷ历%E8ӫ7RJQUuIBjK  b9Č6`r{Nx ǧh7X Q6xy+jiaw%t@ivࢁ?E~ cEТY#͒+$'سzT8Dݳʴ*$o>/P7o ŧhȏ-XEip}Z^ X4RާhO;hL7Xh L3b$,؛fYdOp  +!R w֙'\uƅhiyy>Y1aekŝۄ5-'QKVңc/=ZB0; } ד%a(ik𿌢$}$[dR7U>M)752ggR<,99XyRMJߢ[ )@r^FB]O{<ց !잡CʘVg : [)q^>ZZ nCe<*)b h d(_Hdr{Cjޕ,ްw-Ϯ,əqS&z>\WmuU !Cl7dn}jӮh⢳mqp E 궰[%xs,wjA Er|߫zfn倕a p[4Nes8?Z ccy:iYh $ˊ}24ado<49 4EbɁ(-ܘ LDX# Ŏqn24Ul܌r{qGANxpyq%`v'&j\U ZUDPE5d.dʛ%$ήٛC~5mi53ā]#!Yɚ -'۵qIDLEZ迖6Oeb)R_/2h쫲9ؗ:0rU4U 9cab-;h']\2% $rNuЄ5>Z'8J^9Z*Ghoy >vrVDN% :TF:SdMFcp$ q:^ح%1Ө3bvb3x6= i/$-]~G!0rE:ve"WS"mZӀq[y0 YdM}S6DƁױ5OZO,Z?_%i{UK{H&GIYAGH|~Ypϟ0?wxם?n2:)_z=U1= އ2LzfXo6b~Ap5 r ]{ ƿ!_\t<Oy^?m>foѰ;4i}o*a}W.S\ӋN_Wl9}nb,{z1Lo궚Mz5G v1M^o(WnL1[k&ߣW5􉊂8̯Ns;J~nv}~wYz&߹^ Qg8w;HU<㸃]VW(oZEzs;t!`O ][^tԟVme\O=TzUw$ z۝Ǿa{Yjx]^r_ث's +\E 0 0k[&'o7"Tp*0ZkV0̉wu h*0]ԙ\iY|?0y^{L8O ׯ|s/Lipߒ֬g ݆[.|\_7*sjw*ֈv-D[Zfҧ8!7ݞPF(5G 6]^K]~H/ G o4{v%{eJ܁Wgz8YW >_0B(~\I(لI"r]cvhLfYXrirjV$:w6ײGm+-'|sꤴTn`Rjiv(_|Utnӹo$&imRi\ g}t 4e/*Ɠڽ(-'|DIK&-fqjMj/H?wuT|+W1r+V/1}:.7dNheRޟ]ou]7}: 'o1ꛯ旑8?8\dvPw?txaWWY'ABRsX#U5(iȋηht771Y3d:<~wbΫDQ%#xͲE-1 si7`9 3}n?;Ò8[i!e6)وkK%F^D*q]/() g ,sPIm!V H0@p,(Ogn"Ck>*K)[mp= .XXS{Zt\6r!V4s'0ki,O'5Il56&N@ʄVX/A5>`,TCv7H2Vz@]G(/xwJABU0 TxtKOsx**"z덩7]+%ݭċk!||\(D#@Np@iQ)6xa~` u\c4TB\}+$QS%D'Z^ZBcVv -6JRdmfr5(M ,˒ےBdU*LσA%ۼ[ï!w|@c*L]+bEIynk0#1, +>tł>K%Ԝ#8Ȣ!W:_R&A݊7n= _"rb;` !0v /( jHxEGhLJ+ЇvD0$ NXxob0!?p]%F:Yj+~V BEW߿GW8>] KDP9"8M@N!ܨ7ÍznPr3Ñ>Wvr?ckj\;^r>kIreİ}.e"7L"!}K @0 Kʐ(+q/P a`Q8? 6/hfz[!%?@/`6Ae}=.kM[ҾȪA%M=]htPon)HJ h 2S`Sc t)%[1W^^ȗtB[.IgթI)74bp9E6d_1ۡۆ!5<#l6#Pet}kW'T@ɥ @aȫn,AЭn#+yrϼ=D7/[ҭ7 1] D:O^ 4VvvtY]Rf㜢!h;Be!C jN8ե.IDI gf#]=I3m=`F< Cq&2bA\Щl̀D }P=CB?`@9̐QĄmA 6#R$70 $zv'Hi$!JTe؄(d=}!AnQ&W$?0 j 扔 ZޠX DפDD'_X2%!'䖉 9jbAM0 vE)2H @MTJ4NPx d!%CQ =*PKƀ>#'7G~$8j2hi( 'I]ܵWB#U҇;+BAz%^}&Qު؟!A/ B/?CaI,G0ʣBjfhv"LtLCYi;C!(I;.Psժ|{Ugk+Ѓ`TC,U{g2D%0.БI`}--DL1x#I?P_"fGoC"QC ]#nHQȊ  57} ;")87!Cxp,Jc 3S(&K$4P]~ )ȧ È}I`t۠+ ).ƌ jedC OFIA;f#j( 1A8vXjp#aw&m! 4Ǿ#z[Ѷء3r0=NTڷj+E*] D?BgK@<MQ R55B$^# t`Ie ;D tH19FS"ɛGOBh ŮX҉eDlKǑ8@6Hr1 ]BO:r5a %0<$H$ _3 , .#~l`XE.v'7EEC7*.B[4Y.B+J"!^L,T%X!R1t+84W2dL%fMjB3H]%{'HvM0DzBYa,?2.t‡">FQI)_!B,?u mD&MP:d9#tsjËq, "'`h=@BҋB]bj_kS:AΤK%>9Aky茿mtm$l gyn.?EŒ=eJQa\1"7Gc:E?2 PIyDpׅSH-tVꠈ! $V `D@0&m Q cy׶) A\ ñt4-r԰=H "kF%x1aXs_ T1B 9h]Ǿh:WN;(2Ut;A(9u A@KG`t8&RwR0J8!ݑh04_F%5%Z#C#9V٪(3tsx'=9}bdQ!V&)I7R Ϣ¡p\cQ??VB{g,()HEdrBD:BBn]-kwШo<-'RT\*&2%O(A2'&C?VL*֞"Y\{>. Ecӥ/t)rr}CPo3 Ժc#%G.bUurD*r-AN2[JI2J L 8e$GK/?5 yA(r2A^!JIh,/4//= DHQ5s ݈B÷L(*P$Q7!%mapPSgA(Fh$۟"2-㣩a4Тe4 vg9Ot=L;`0EgtEGQ I4A)23 Cb_q!)E1(=OÏY9IZoA3,Hƍr@֋t\0F6X/},a⥖,U)]58/ȞhNh*L#pĊ"-ڲ</hP&b-EI;A7 Itl)(1AP벷T<د(o4пq4tq19l^Hzzo+2i dC*U8$3( k*Ta9X'M"ʣ]jH|'rF X#rhT͇ bj~Ch 'X*{0:$4Hb D%H-hGGM m⊠9!3 ]{g49h  //qA2":?rX.u=N,:45! ;PC3H98* 2GQq ?Z6NJ7=:0,IIȔD䆑q0YfT,'iWVRU˷eM܎NVc|vD%;F1?*1kXE%3F}>VfXt#N.$I~]olyA.nHa!/;;)⵫,WT.2狆+ 8nO֊M*4֪SV8@[;$&4H"+.’e&0ӈSl#8MS>(M"(eG\: 2Qn&0%E(C`vPNHX=AA;{rA^@fP gB+{BHCO@#XWZg $"h 7:kl _#F$zjĦGr(tm&ؙ}-`N0'(xEU`+iK-r:F )䀼4,|4C&r3V4™,XɈe"4/d+,Q' 0٢ G)-ʍNZSq6zRTQḚ\qHʃ[i!(8MXqc5pmP^#+EMJE fZPRCYI㬠TP^*[,2K ^8O*TDP/ 5. F$T &ȑ4pLc), ڂLn2e jw^&"V2мG <0D1(-ԙB5R=BO4%MQʆ8(^jh4J! aMc98#l5rUʋJ wi$,hT'܅7ƃI ֈ~bep#0" 2"[",Ma\F0o\ C`i)TɒkbK>&#V0YSH?Di3Y۲aG)cy 񚦖2=9y'`l(#Rt XhNAX5Eh&-_#@(] CXɋ nHj>͐osK檯q$+O" ]Ӽ|?|YDb (nop~#Ŷpu5GvgoIykj]KsT #h |9dzsi.p.-Fx 9Ϟ@~ƃt^V6*KD_U52\؉g6EfVI+]}nRp=(:QvP[QEHyvZQ.k^gbZ;{;cWUx?+yCNwvFNTXh8>|/9ҡkd5τ{r;ۥ M^9=hMW>pc%m OQ:ȣ¤ㇶ6,bUቇ﬑ סTrWٲUbj‰h*Օ骴"zTz.קѻ=~hLUl>5Yj0X;S3Hy%aO( tsq"$72`"D,W.l{*8?s'h@̙`32vW!c ]69/2?09dq .JHP8&I= 1g? ` s8"` q7_;ޅ\n{ LEehnpQ!lRm"j Z)G1XoJC@ej;N;N NX_6QLK!9`T>CS(5!UK)([dpHv"ڞ9DV#g?`-qD-]k0#l{v h́Z% aEڑ sFchlю:l9Z6{hϪ=|hV(Yr`J*X?!&MBT-;Q2<6ɳ=5- 9fd{/vZ. K!, 6%g'\'_Xе\w^;Y Pd-jTL|\g_ۑ^a;Guny؆ewaHm2l2!%S wp9.BZJGiê;Z^q鰼LfDŽJIBZI+)Kxl_KK\x/ 9Cv ,9瓛oӻ R 8ڻVd#~+C[xSDe`d*Nj6d-.YJҞ tlt WwQzBNS:O?ZI Dl LM$lr'dی$␴5򭵒^8F.=b  f򘣍}< X򝒟s2Yk[ ϕ0$̟0h*v2L)2f\?DžP\('cg'AȪw? GiA5gB A \a//g(ӧF<87gxqa] g~f-՚O]l5#I5[tO| n s V~Ccj]#nG pc psp\1,[Ff+\=nKfZ*<>ON\g#DŽەZEjx(Aझs09Z!mayl'"<֎ᡣlhWj53ds-la[o(AfVK_n7x fvcҜ"9nB .5:{k4YEC=y뗴k$(8[rs)l|sմveyNoYڡ׳f(粒2ۿ g#ĜYoca5C+ryVEZV(Ydާ$ǀ~vZVУuώ Dka`}r z7(VZsPiO2;[fZ>DT CZhig]VKӨ4OسXP=*PK8D&KU Button.ino}O0W-K: 4h+M,&فk>$GFk@lUV ZjDmj(-l 5FJ@KktpFz %t5 $,D 1hS\v9YX֓M.:>i ȑvhJ#WEs KNkc`zځl{%{+XBz +{I veG0wv&W >6]:'AK]ifpkMA7'U1:eR%/Z]@iR`bS%E*=Ee>T4m;C(ij( _eS6~PE #kzyXLGoV"mZUF5eox'd?+Ic-ZEb'R }AE'͇y }7_h8v;'}'f>z@f/7H8m%Y/]V/#noE(~~T VinoV *=;zƝhIxE?E w2~>5nP?u*loSU[b0B<PK,8Dm&H,nzE j=}իy?Ǘ.,fO~*A S7}s)_ͮW37wg'3/zuf>y}{7ǫūWofg~I_>^_<]}JH߽]-^=}J\qJGNWFǕfg<,.܇foypW} /"o_>~>u}5;~{񇇻w_/n>ONj9ϸ{7ڣtw],޻7~iw7 xw4ǫ_nWn^8K]/KZQJa_׏y^b=VW3?_MuݞS!ܡUm@0\?J'޳#V_jogg!w7;^W_?YOQ_o +SovsyP"~vqnyB! ̽pJHj+ )UۮwOxynRPw}jN~X;|/ܟ.f娷pvqԡIXgͪ#nl{ rS@EB ">Qiw׷Ozzש `og-P[\?w˻c,F6߿_?,{95xӜhnVSr#R)¯N{8dC'W!=&;yn̴ƙids)٤Cδ.骏tJp_8w> ww0}VP@9%ú090U=̩v}W>7_==_Cj)E!<8APEQ|\8/Ād. 9E}Z|z*fwOV]\?޻7ϳ_nq7)Ha(okUW[}pģ'|mFe(Jl| F8W ]. (Fva! "TL K\hQS>q|`Z(y7nT=`?x3c+֧:Vr@M4Lɻk` JxDŽX\n h7hv^L|0S0E;Viv))4vtka1QZggF#eg9<V 9¼aIr0#̸W2R#9iDz_t>LF9g] Áj#>=0L- X /9v-̩=9jԬp`,G# S$72F .Er.O%TɃy#2ݿݚ'b*90۩GІxN/Wxz3-M0q&C/.je3]6sc<qֹYHY.@:U8H.oDI.]-t6bx rx9^gC cssmnMv b-~??"*Py²ntaztBcʂ70i{%9bsb֗1Rl80- 񋻫(ʾRBV[phOPF(vPR]#9=eT$:G|n[0[wG?/OxG4Fz;* !573'aϞq qV?n>~ʱFʟ'=TܿWN ш_^^o|3p7gNmʃpO`akl* S{D)j#ߜQ'~uh_.2|HMG l6pV3bfO0J1-DL8![fLp58CN8~]iέ'.MFĕvI:pvX_{]w]{yɃF?:h L!xJε,! 3;s0#)va2N'ZvvI#X#:.]@*l?-ETnnyۇ]1;^rGXJmrlah1b,|*aY!M<'tb)@҈\%&o٬-t?'`)7Z7'%B+% *bnHHa.[6FU^l|qgBZD)ZaC"YZ?r14Z=ue.7 28Q0l֔a2g֌o\=ckfn|n֘,QϸwBw.xe osU8f׾30zQB҂;4|N p3 Za(Vˏ!0J|2^|·$B7wo9m=7]9)m?qXѸVl-ɻOph}o}|N"_#P%lC .} `նTΫ6օR{d$Ɉjz:vQ*cOe$Nt7eIUatY =Dgʍ 9ׅQ~HKk7el;AZy7aN&N; -G Tp@y5H.ANlF8ɩ*5bFL]bkzmTBgIAGO^R߭ ܺ9R9?v #[}{=PS>h9)dNl}t3{[H3ĦM%M{bǐ1De+^c_S1C|Ey")t-O$y"'&xI6O7BN^v&jݥzJlfmpR xTA>26Zyy`a54="urh8w`4>]虽5/EGLؐ;YY@% F{R,)R;uEhX?׼P[+|naTZhM i0 Ee$:|}W) oځq=ºPh;?QB$v+HcBKgd-Z_\Ɖ߉xDwC Mѝ89PNg:U8) ٛK%z#/Rϩ>cVF%b׋_f-e!@x8e0^P6"ۥm.`5lܱn~]$ "iMz&!IPB^ܡ#04aGi맍>h?bi/~pETϊ7y?wﺀT-&m%s^hlۮWL/V=x]u""8=*@+ꥣjD-+-?rrzK]0p S}]0be C##-AHuym g\^[mp*d?7IfFo$$K'vQ6Jn {Ow‘8 rOaхk'?C{ ]uvul_.2|зMQ ~uS ѓ$Le?}EB}`BM2IBiD͹ 1RE})ߦJ{mvE W)u<48؈RJn LX7w)..Ja5ٙ_ N'Mƈݯ#܅ Ahmn#c)#8m9< ĸ?}h"&.q0˘َ)qչ,rr!0WR4Eat4G~H-"8|*:@N4A\' b sȡb5}E)2ZΩ焀+׻)zɁ#FD&)`SVL%hMaSC "div>Z 'EI0)HwSzV(V(hvo %3+ ]Rb i HVp#Q`ltoHtQ ⥵O%q) %Pª5R]N b8oK΍ FS"%; Dz:_BM|b|M̗b .6|s_&9e<\GOԸ$U|gMxtp+T})-WtXJdJ}4]dZ׻dJ0}]¨?# @S!BH}E 3!ݔh P|T% 133K mê3K2x2մkNGfPssŖSc;͗GCKaL{tmvt*y7efr؄s2q@ v-%U>ABa& )GCP#-SD))~HF@xC9;Uj:޲'>%KJ+S`Z lIOE}U#cZ,Ɵ5Zabǡ 0RHZco.F#BKta^EgŸ UNVJBrq x֪թq4,Ңl y C=)#-zЎ9I8 f+tLtY;4iVՓ5RBjtY 3Vx:O9ě(}{%X¤U"|ȶB ɜl8Ҍ ݆0CEGZaXdB6`XId'T̎\B*ERnHę,8eŴ@C3޴=uILu(/%}^ AD6iWI0hqy0e&lÿHE&]FNmH`ɸI^j\)gi/(V=J6 s_cppm$\ct4"1 (XWͬk`VjUaj,t2qK}ؓ`W>U|쥆㇨ѯƾPf zb2Аá( ;QSk 2ʚxA;nd":ޱ#VZAHLU˿A'B)V\,Spc4Vʼnb"f4G3:r0q0J tDT\7+YٜRiY ÐېᴌLBY*7؜V@Z)>5v]  Eu"6 rdF· ivȩxmHp5r;D[n^k}cyfÞkZVFBZ J9ťhꃞkGL{F^GZ72[Mؑ++-'bM +Ϲ,Uy@nL?vXGRt|d,{1i%E $Tq8$%rSUnG%mS1pta }y!mg]LbT@}]u8ZڥWh[7̼+2 G|wUC;2 9K\-.Ł3q/!R8ơhiO ̼̼;b-R+K6{9f0ޱ"xuѬޒ Kxc ﬇9yJdWhzSOOЫ{z{իm W睲(dEifkRsAV$l1OlnI`cڮ m‌iB΅5wȋV$CHّp%\=yqV˄J*ln8n>ceDL=;#(B))$f\BAa SKI Brfl8n}Ciά( 5䠪Ъ,$< ehǏLφÐL6$s8=y簭oY'}Z a !H0*C((ʔ rlY8xdA>#b*s1@#w8"1!( l b0e`"4+% *؂):TZԠ ԇ=9.iV4h`q 1K Bʵns_ Ǻ^Lrqiv,lu4F^9ViaEhhyQUmBmJd7UY vCtnUXq(vr1/3;ri0q0ItNK*2LHbN8܎kdGZnېlBUY$0HAStjva  4Fk,lXk/B 5v7ba82ڐk&ˆf-5Leyn1Tm3aO5-N&110k{`Vqiy'ڡX+,txȴ)}7|@[=ǧfc H#q9)9E>8#|Z(2,2*|Q:2B d>1.Eiy>^㇣`%RV~8nEkBk(vJaʓ#1q̎HZ a`d>6h9q ]BNhYZEiE|݅>6&MSƨ8jI̠>Ӱ:5 z A#XM؊*(j*Fb8CnV L.8=A}GDŽGdxB;dR6 7)NHbD923[M葙نdgf.+ 6غCH{q1\L+4Dػ^Շ},.63$1Ў& $ϲ+chLVG;d!)\49l)-r2:܀,dL3l"cs8Ë7~># @B 8taSAigmtU}Г瞛۬_{eIX5c#m@E!E?+Vpܼ[ zkƥ6J914;RJ7g0k yMf;2,Vƕ ''Ʋy9/&y3BJ20yhq$!0 y4DPaC& X FۂB[=)?$-ЎpS9ّ9ZqZ+&e.&JZT!f%>K@ީq3͆LǶ"&}l=zd#-rЎ9Y:# a9 ݥi*8L4)]  aCaG`[}rd 6 j7m1#|mHp5VoT.Rp+eb<& OMbM8vv>Ѱ/cnh  EFGvqr3AOE0a;8@;Xd:#/>(l0E4:OsZp d M|4-85yӳD i !*N:ٝ$,󝓌EJ-R5'鎎E$)h0rm* ! ȫ† ېl]Bqv;O7T eb1Ee| G2|bTV ŎSRb 툒8&MͲC"sh6[Mچdjr\*ivc"V*-Ѐ'oÞ:= =RYH)MDR؀q]1{iсvku4CF.[őo ܋qW{Nt(x-*lo[M?q)=6>I(E IJLKr00r2 Ž6y&ivȵ!HNmHp6rrH]fEUqhz\8e$)фvY!9e`A u@]0Y}buaXv8dv:K[%b], #,xR y)V܃1-RP=:)X0['D=3+8 P=3mJzt,B [ "đivYmHpFed!EsZFl*-T,mM7z-*h8 OTL"=/)C_sh(3=P2=Luoh)'_hLVG3xŊuʃ-Y QC`XGX[ׇ<9B]<׌-{$iNlX;xw}FZL-rpb9xXv 3VGôAC$F&L(XwQ IJKrq٘9z'$-9:# NԸ,@1L7WQ1ɦFiQ&8;KSQp C#dQ5;ڣĒHB;dF6 7#G~EA#mHp66l6<ej.&J 4AIIYbqYC3pOhL&ea#vBҢ yhzǎVTvÌpՇ 9-l,sZ<'iq) oDi !feǮa5%HNJ5CI^R6 7;{*XE")22)ې̎Ll J4gx"].'ȑ$%nЎ#9M6 7;v#-~9K:ޡ# LȔk"m)i&i&<;QSQбkE#c$%# !GqCFZԠ42[M؆dbtd.F-[3N7@?hű5a!= LdapɭO'CI&eq$Fڑ#3mHpfFff^7o_ƹ,E`qM}ؓfJr4aL_4c':%. ,዇e$9fȻEPH]?aQFT7P"DtGdĬ>ѵ(lܬ;҄-1VPa2LŜL[R %J;I/Bd8ȩUɂw1V5CJ#lFa)#c'-$e #)vɹ丩>jHFΓwLlC23j RJU71hCWmMOx86ѣƑA;d*6 73G i1vTlu4Gb9t+Z!mL[J49ѭ CQHJE2A٣A;hd*:ށ#S NF6 vW?J4a؉ AtL=ڑ$SQ)YH3lځ#ӲmHpZ6+,"lThZ6,E`qM}ؓcfkp$h qVwCɜš?. oSY;zkEXL'bH)hzGUB/?}I1. pœW,R-g*mQH/p>:&E6$@}ȓ^ !)?&ǽh/ʴPbdXs<ۯH3عGlE$RH[uXP- KCګѻ!q,a"wH*2*p5:2/mHd}juaz5E)dރ*&FϾԇ| tKm}Xq ʥrqQJעZIWLܘwɤoXyXc(楐yA-E8|Yy bFlk"C c_Ls)bN1iV4$ MF|q[V`W$x$)n<&4(u+l \LUtm@fl!Lͽ{ 7Z˦¼HT-)Eg2zPcK}&\ 0. BȤ|@;ju]/b#hDΆ36Py~hzC1ױ/i.LA 3 " `j[t^>smH2DگhA;nd6:ޱ# nl~8%Rl<)Df%6; CRiuM(4u,qcZoSv^G( [p@(9NBdH4GfiA2K[QR4bCbi"%ǴibZT!hNԇ}LAX7a$%"  G1FZ22 [Mﰑi* /_"AI3DCB&('!jRUiM`乌qhXSm#!*a(JmCۺ?LOUp"T* E#D\8 zZ26q&tE!#y!YFf\"z!7k( e_{|N*D1hQ5KL/P46-FŸU= )D68cbȱ̳ IhVG;x+6V&v[VNpŧ7?z~o~9=p?~,>9˷WOn9}|z>*..߼}p<ة+ ]q} iǧ7珏M?\ǫbwguħpFA<]gn3֟7w>6|x {_qq AHwn~M|wvtwTG7˧on_;uneXNZjbvpӯ׷og~/>{v1uj_wOy{|9]>}{z@ܿ=_Ufpu*28Sc9g¤w䑨9 ͯջl `b:`fviK=Lw^÷ߴX{\<<ݭ҄7hLo swF9O_r}8ybw{CD"{Ȯ{n_F\߻SԽnEo/Qꛡ;So{G9/Xϩz堇>kt QJFnoo¯,~^+$ͳt3Z{~/^~׷5ʠ9T7?!56w=N"8Nt31Idg=p7T<3Nɱg\oCDb<U:/uQw҃Yq.wC~~~8h9DxN90ܻ~yxZs)CLWȶh.[/ w\ys2֜gc-^ |Sԗ >?5Xb3ItpHzI`Rܗ"q@+Q\yj%[EexzQPWYf)(4LWD1%a{xn߿{xx1򼟼xX>fvj~uMڋ{~/n~Ѵro.CӋ Rm<0tƀZgdh/#_NwFjBsX}83ڥ:ErX1nGu>bd s3|[XρuFDwa>&{ܯa{~/m3}t,הRrqBB's@YDSNƦ:-1]H&:VAXuNtn{ 懅ZhPD"Ej4r4?2#p{k؃ltpS}@|ECB:r⻇vRHWlh7@BaO`EUW|E`u Ŧʈo~6xlC}_}SMfMCiƙGd^ @P-$SSw'QO*m/FaJ|ͧآO)liA %X,xB[ƆBƳs,?d;46Q˱U)ʱX7O6_X9؝!حHa/gq18#s-sst8'>htn{lώo#&_,Oy.O13]/X]?<ߋ P,l8P>!oJ|KƷg^-{ˏ؆pܱK};Ac`]v-g#ɣ%͙9(3|*p6T)էaV_U1mdLNiC'd|qk1yc7!scdN8XP~0Xn rl|;Ώ_w(OkK1Geh90[T]);pqx{px<&UWvd}'=^U 1$fy# <^p"|Fɬ,Gl7o?9qAPsq<89sh=D)h`ɼ8;v3]mch/{$Im C8YG|k$0L(/EKv<D,c'@Rv;|';^qoz4/kq*|-12'M!i$#KR FL$MI6g*YU3 edk% BjʻV(Q%227#m bi%yMR6Y%ĝ%J8߃!s$sh9 ,,mu414/YHƨ b.4]7D.=[BN|3PX@+(h'PՈўZNliN>se^*',92O[ϛd\2Ϥe-9eOZz 15?IIcʾ9}cwI{UbSob%q?LIܞїo5V~Aqxǯ2mW|G1ĜO-ljF-m[[H#rʄeFs Wq[[K3cBD~¸ŝlr E"n;=żRf2or V鹅ѫx^acċHi{k@.H;mI\pÙ˔$h=D&.шŽsF'O=nTr'/iKG1ں`>O !,9'ᱵIړ)"Wpv 7#)qQb/Q'%reSBIړ G-OS(l=='0rt?(>9'PӜhdҭcufdvQ; iȵ;mpG޻?24IT7Lԓ׺Lj"s%.՞vd=Nk#điM'D.iȵ"ɴ{GN;&nӎKn!bO-d=1j;ǥnrOt+$7;GۓnO=q)Gܓ'Hǂ%nӦ6=Gnfqɴ;Gۓ'nX&b?2Qm!%7׏Z`t/OCϯΞϻkDng8\#o#Ji׏Ro̧by4Ҟ\"jiMG'h'z'諽~|6l?N tHE>=P *n6M7&/loO%^'|?RO% 'iO%ZiI{MD ǧs =ya{30%mގ?:aO^k'LJ[{M;Mݘ?>oe*ךF'BqJQ|-ch~Oml=Q[ǦnO}\)m'Yi& {mDi7SiCJ{+ eISsYEnӶMcG n?hЗ+/OonY/KnҘ4o B J%|CBYeԾݟ=]}{\<<ݭ۷ oc>,N?y+⟾N_Gk?zly@a [)`!QO<]C)aˆ;2H0?sx)߯Rʀ 5}kͺVYٽ͝i3QQYE)";p_Rb+~OͣYܿWto ܴ'7 gޜ9I_Aů׋6gP) AyAM\)jYpns7~EeݬnڗKl;7nž!ՅG6F8É`ݝk) >TmZ8Dy]k5<0,BJ^ꂛ ZYr̤3/ٹ"dfnpנ7'gEt\Gws"@"D7:'My #Q$ i%R)-DG03`2PѤd0.*LB3'd4.Y\TE&t0.:Pn[*^8;楤"虍ńO}b) Fq:HL 6q>.YƔ")#`T)fPIO)xTvM҄µ7IL#3ХتK_ PXEX`xDA̩* l6Ҷ66-C"@K-) Lc/]!˼4#JBOOfD@4CJb"OTF#r^+.IbJEd´ݷS[JڗӐqU9iys;)P4)ѱ(/`#mf0idiP21#I&NRyʀ2)]dK%J)rwl{4f6v^܆n4 M鈐id2FNi'S;29 c&NN-`,T nuw@RӁtd2QC#tltLM$dȧCM)I2#XSF)S0R5Rt'ϮuL)i2:Nӑyʘ?UuNa <Е2P>PѤd0*ʇGLE3'd,*RQJb)Rd֥+]xNoѹ,᡾qqH޾th &+X22c!td6Bd.qui`\T #f INICIDԁ=ۻ?^]/n.6Ur{\<<ݭ۷ o~x3Ⱦ?9yv{n+8{&W ϯ~3k}ЗzX<>8+gY3`"`mH4~ư+$l~6ò\\-^tn5i,㾷Vik``8,7 %s08 F6)Q*q1rLsdIℒ H³DCQ]LGgG.$&,) $ lMPrG i{:( }\F7'3Yg8Ym#;"h,,i{Q4R0M]XZ φw>2-:2-[MqLv񇻷w|wv93rJv3wwk}2/'8vlq|ϯo߫ˤUCtWg翹y?zw3xx귴 -n.o~Osۧ(_v?v~zwfogzzǏG^==ԝxOt?:uxwÙӑ/f{|4 9~ioOh_܉d뛋߳|r#0N_=ns؎?L~/2L )b6|S0:|yL8Pե}W`FfFθ)o ߭ԧOB<:k?gon7g翼}{[p/{7e*yϼ.ox}bq~3ƩxnO#?g7$LA?aڽz>'̩{BXwlݱ/WМBH=>pGXw!'}̩?En*JsNFRpS_K_5ksnjpSu#WQ~D' c9jqNNʿZVX)#)Kmؕ(`7NDB'(N 1kQRe<*e$ 'Q&[x{s'/?> ohB+8r*ܽUs=ɉi@|"_Kw=Nqa :tQJ )'5 #ހ^&^B|=3<ó1| oG݋q7W܄ W/:L8ʝ<ԡ( P~^}R&|e+"+"yΘ:#zܫtJ>YyrϢEk?/U}>9sڇ?YBC a' TR??f܏X8r!'ww@w~Fk,f 0$@QϴR! J(tR~O%OcAC,:D wLyv ɤ Ak)TU%,q#\Ƶp(w W#<~o_1?ҟfu C'~2W>aH.O[POձ߹^4y*_ yu#N4 ϔ?9`7 29EDs/h~<|x@hNKkP̘ؽnFX(UvH"N+ @35Y565K`8^WaTa>TYMOWA geZ^`6q\@ݱ7# +|\yzalAȑ?9LEVj?,s$|"ߞ ݎz9= g/b"u \c#T7H.ԇզ1N?BIlmކ9 ͼplS،qǂb 02Q eձ&ߞ{_5ftAAݣ5F.=I),-@5Y3f h` `,ޫP,g!2 MmS$Nn6{y v/.@С 9K;lDvp 0OՍWep}cx2>@Y@ 0$#aTIn;][5'Y֌``5N uۑjtE[]q" '//,hY%0en@)FC@w3Dxoߐhh h0̃3ՠ@W܌@g3l0=<X&4 c p  n?I#~ (3)u6@N 3s1A:H[:S: @A1 cC\WFX@ OJߩ`ڣUr܀=ʧ_!/Rep Qp |p'PFs|~W *qRS+T"$ cȤ9C N- OsN&?P4\b0 0k% *5R+F(s (GD* Ͷ;qK2t@`Q[b_ UTy`KQ]SB]Gs^ ҃)սU=*'{!otZ^\Ò04aRV #- 70P  O 0UĒKJyV׆'/oηvvYpv$e82 <)oK$&+8#wR" Q 3|(pB!H<! hkt9*Pw5nLDTpxԄ+^V|!p~0L_r")7 YFN(.üyRJSa bF R5 F} } 0B0r$}SrB$!&,pA`: c~BaEC#Bд@t|Z2-{ D MZ >n![@L;T~SG ,C᳀^¸c83 |x̓!jX!^\/,ƮXÒDU!l#9'pm b+x~ܢ(S, !Cbh'1}3b|k=YG@VAĚJc5'M(yv^:e1yp"/V ".9E%y1HvY\3 .mx0d߯9Y%RsԝԢd?1Dz{`>"!DzBBXb,?0.t|=bhpX~ʐk$LjM@:h)A 9 ]~n`J8!O+oDdž0J`ZV޵teSׂy:}S8<X痭:>V1+Yϼ5%9"aH2n22.z3'7C@#fFcW8)*'%!P-;Ma $'(`x9Hrfrœ;!'"Ʒ_i% މ cGl~vCIV`0"-aȫ CĚR*1)po{xΏ9W#J0A4 Mj~h` w:)c*] H,1㱓st4 aEy2h€/5R?&G@CFK?qG5hiNRFOʗF8/BB8Kщ#]f stMD."UH-E]RBv_P?FrT0 Qq.Жbx8 zD1)2Ld>4̨"`)cGN071]bL?`ꅏ L|ab%.+SVߪW\  PL#Do*OĄHpglpq) ~ F/DA50 TF%[Y ֻ BEO1܂%bcЛа,<<*y.$2.M@_ qTQ QDŽ T.p[! x9T ̗2cL? tB@DO`6 d9a@PA4cp2ݡS@0X[9܃fuoi& FB$)`iFnS"(tФ] 5(~17˨_xm/Z @@#S[=5b<"7wcY$1}Ohrp#)hzn FІ Ł"509Gb`,>0S)p{ٜ Vp ]^Ig Sbp)Pxt81,cso {A5 Jϫ-)DI0 0s-^[I}?MJ[Ar8K,Ei|UX[:LX"J?+MX M"[i$I Of%|{Y ~rxY"fSKuИ$QKDEY &1}GۘbAsDf|/xşG0Qpp&1a+!HA!s80 Zdx]W,(@ Lf0O@@p FDEDbcX8@j(+RQAՉK[1aJ Fc ew_ 55kMHѷk#=).jAŖ0jr:U-BK**55"6ׄ+1Љc̥g*h 3x P(P{xd +C ֍X6ꡙ25Qnob|91%Go]ݐd2?69R(,?,Rš(\#)q@OJ0 jpQ "b&,0+Γ>MjR5EgÕ,04Edq.$IAj3KC]`~} En &k,%UK`ɂWQgVxXZBBn^zvOW[9Va82 U\)*wu(4yA8|́1>& `_"^4Y`ow}*?bAUu {)o<ݟrWgO??]-~Z4m`~lCJ;g8^ߞ}#5ΌmW[Anݼٛ757ޫC$orhfN{lN߶Rtٺrn_m*a\B0x־R]cOS* ioJ6b?_?^^[:w]}Zzz^ˢ^&iݮn/Ql2hVrQG{_~w L?>m*:ihi+iK~I{܏nLaꜬi%X4dSM꟬ܩ2BA'`CO?ࠊ%XRO)m`EL ޒ3M_,)~Xlzb5%4i6+ Shm X<듥5BOSЬiA>1dMC0Ni;tq2}MiH6ɄX ^н% 84 }TYbzDfCj֤BK^c=BVcp$DP&XNb`[hNޗ;XW`}t۹W7ZGy\!o= ]Kdžo'=#ƽTlUllڻ{)w#U隿kx%QhOE fc z=JI4]%= f.e豓=|?>܏v,‡77^==_E8/n;zӿ_^>.͔*3^ܹK^.nzl-~w/ w׷q_1}⡥:z;guj]t?vEۉxAşyÑxڴJ#jĄV=ԭW@3u_#RզA6WmUb֦݊ZZ(w]uY68M灴) KgtR۫kU̓zUs4pZ+eD#~Rd^o{0gHtZ_Y,d^<6>c;c֦IDݵJaHˣ#%4SVC97iS{M d5u+iqigbbO7 ^OWc?/Nw4 ~_ran$}m( O3'߼g?ܜ}tp?ܚ}qѷRC]Psqa_ί>Cw7gNmօYBE)NR#CMO=.ٹ#>۔a$RHIξt3%ǭv Դ `=P>PTW y{F/*[?s.GGĸ)jDdD2OCt mm 1L,#w$u4P ѮJfCV/7jɈfPwәE&' "X/O:462OC4aRheYSF/g|U\]h{c'X0r(&GF Dt<|MҶ!F#B@q_O4 Gڬa;r&mH\3 ;#3QI"Z=9=3+ YSH1maÚ (EdžLL:s+uY:Z@,| 2?//sn˹/ttrnnN؟%o_TabՑbP{Gh<2:2qƝq? CwF36:RMGV*SL6u@h '|'Mty&V4R XQ@UbǡX G2 E2 х 7(hg,4 {&laej1']&/$Yѡ*-f 2$EiUf:: dIP[C }㪱Lb3e恱&)$%isOu济l#~!4%t<)zGtk2[M'9?5=֢]H1mMOXzUaToT37jcYR=\ˢكN9;:e7[& ꍼg+y+Z"t&GeqOp$ӾQd P^y=456&WoD kE܄AQ8>ɑ]Hwa_٢6f c[lTYލaS"Fee4=؜8jDzǏ͆ĎΖyiptYȑhG4MlQ ?Z<*YtGEwN{8W)}y>S][ yE2A[?&,Gg}`rf2 CZV gMMyJdlQ cT Rfhz<`ml'[-ߣٍ+?Nв|7/VX*jFYMt:c6#ىO+ie?b{9h!zi 0k)J34[JVwc5!; &frɜom(EK@$Β1x,2OzmÜza7=۸'qe7O5cf"Afdǹ3g1=G('|,Hu'OTOTHqߥ}*=zH-~g%fG0-#*@Κ2>{<m@h*)dֳiM2Xr [a>ճCo(%`yܟ>j܂S[>xfA?D[r^?KkAy lwh* {]Sgn}i"z+rHvl<\N6c$,&8]Ӧn6$^{4zz6t4dѥwr\=mECEΝkDLCG p"VgMMS$o ']OrKJж !K!b˰1=Ζ&kTVAyr2P؏#@oX5r@ȹȌӪK7o0\yx/1x@X 9EbeX@ŘX^ߟjňx݇Ab.N9=`d5q*E[ 01zrh*ti*ctmth;+kR:LOae{^3VV"P3r@jj6 ?(i/x1r@h5[/M5Sjf,>UtNX˶!Xqtull1P2rx@* lX3oHS7{1h1e$ ܟe;6$qvW஬qro ;kQ DV%56??de{1@h*v`JH[dhY%*d;~EGP}fXF445Zq4+jFY~nH|oS.J :STFO*_ )cdiֆ=6x聁"Bj<+(Pqn?]Gl7uG4U Ap!p4r|[r5V֤-;Jj7h.ō^f8wd4z|  (eVQ΢qm 3'̞x,ۊ}>C3XY@rb}LxvdթgSl77|@*Xn =` -1(ƚc[qy._r:}cԌM]8ܳL0w j "In |I((~a1C@{@yҼ,biܭU3XZa(((ٛ6cd6<`b0wY}jÞzz[^<,Z]0x[>;`aW EZ:1*=,\Icvʠ,tM01\>EF֋M=.Ͽs@qL@ɨYٌP}Tn1i5{u^:lЅ3 0;432~fJLsĞKCН^9>ZzM OEmֹQFbgz c j Q% +0JH9&~dSjVwZY{6m&[UD-]/Jd>&uG\]*HQ-͍Z!omQ2DeclT|ņ)VߨDsJnú<̺]Hwk^Vptib,nyМV#Ni])F ;B21l1БG4S`jDUɹMM%SS /aj耩UL-Y'K sCFa:᲏U3fPqKWls3[/$[ '[`ndUʹͤ& qk^VtitQtpGÕƖsDS~G,2|M:.`5B0=:m:;#N_ x/i؇@0fE "cV31m>U] Tfmݮ=e!b#g5\Q#jVU<;hO+~;vt.,5]͊ agx7سo+yzqF|4D@ ,֒2|@ǨÍX&5}ǻke!df%K77*![wܡF֋`1\Q#zVg3<:PǸM\ vfv7",sGپƴt[wF 'ag?Ze1C- w5oLqFZ7A@ ?;>]0>- 9Di7MsE:8iAa9hom  \4DCAzFYzVqm^jV PX-4Mۑ!_[02B>XS0xrTq>]+Z􀃑<38u|yF!:ʹ|h4Jx8/{__'Τd\֜3C㚓7D*-_ Ubcv æv MxG7 qi 5%ge2.0ᚔ,>`[yO.zUnJ*wpJ̛o6-MZGl2>}oA)3}N]# NE`},`ANd;n08T<`Ȑ?ߌ O ?v d۔>K GVvYy'^ #<`e-׳{к1v ݸ:: R>¢& OLrΣxMun7f~c,+拃}3$(/쪑l|t T8!Tx}]5sR ͺs6 9ɖ ז a*0ϝ|Cv;}Ԍ{6UXQsO*jljj ~am3N.> jՅnjybc{$BS!4E}qǙh%7Y k 0%*@&olP'تԍ]TR_ު;1A  -InM3,ak*\KG`g[(.萓FiދĈVZ䀐Qs 0{S')/ T* ^Wb?@yҸGc&6^TƸ.?PK*8DjE58 CosmicRayGun.fzPK=efritzing-app-0.9.2b/sketches/core/Countdown.fzz000066400000000000000000001340301250202676700215620ustar00rootroot00000000000000PK8D^{ Countdown.fzr8};rmタp>eta3uM23TL)MRuu[+}!2RpuQR$CDswǧo1B]?>|wwyӏWwϿTXb>}U> _W}zp坫o}aWQ~w뷯_WzXk+{wݧyJ_]o)"`z`D>>|x]5[?|Aҽp7]|s7߿ UO_߼{wߟiχn<\K5׿k'_ٞ}`>P? |o~=N= v_{wWquͧzF\ǿ|XO>|~F_o׻>Tݿz?i^-%=>|O<}a[pjMYԯ_s_~?_~e3=|wǛh5Z'_OOS÷/޿;g7߼3OoOxioY뜩7~x}{X̣~pqkê؎uAkEe G˻ǧ;|×WTSOշk?RcuBcuu jy7ZiuBƉw'b;Muo]֯wWM$GM?=}f?_e_`{\H`+h| F/ig(+r{e{!˭ ^G6ƕ-TMWsO:ߴa_Y?gChe>^YqO-'7[1|qh|Wέ;9oݗ9yz·ѵJFgjI`|fc\s⦢tvHz>睮aGy|ˇ#4_7A{_OŮ܃jZ'XM?iEWMt'݊>ɓYM+C_M`o\OyЯ5GEЦy^N1%ӊ"%&qӸ@݊K^<6ͭHˢR<;]g1ixD¯%J`97߷&&Q |UxFFs2L#912"Z[bUlNO9Ԝ8˗oB718`-RbiKLfW P-E(i[bA:OWi7tqjҗoB7)hfztiIĔItZbArqygS\rPPGS28)M[O-xRuESb)e[Q\ω-{g[W u ,' jvMmk*{i{!4(,d+}RiZ<\y~E̼њ\/"owWVĸiWx.^P#e *1f4PP`A%F)qbXPI<K*Eq8}W /λȓl17aջ"|ɫWE};6BA9eqVE/ߘ76${PEoރT!XopϱjQ\=}X1I՗62VruNjN6X =Wt c߼Qb+{CUJ]2B~-_% o;c=N0?jޚ"Q0}1l&,}[^9Ѭm_Cç??E>?EO}r<З.i]2Rk+Ɨ<׿"lxG)g Ҟ]]BJ(SDD+ش*5jޞ<[mwq:i2N386*?‘XN(' Rˉ b6 3ĵ.o.ٷ8x-Z@(ybJz:Zt=}cFY}n2-^MvHWcF:'X m̃8m™^OL=hd.bxg_\ rVv:YLosҕ^eN>)ͳt3Z'c WV= ϡ/mO~*sŹiGx=)z29]3|0e?t}H(N=gYNO4R(Yz+?ZOǃ1:k)VOjTo92H-߼IB-G} ~R~yAnܻ?3<\@nG0Ы:M7foD{_AZ@,zZh2ӄ**d~KB*'IbH ZVV! |-z$ ET&#*4U :} ̖Or@q˜77ALȤ&߭GȤG3i oS2)֙^IS6.}EP6˥TbIZ]B-Sd!A0m[V.ܱS=lȪ}u] ̬)Mߚ˘$F51VSitj4KP4-LwsPO[08ZLgVq``F֥$AJՆhvR,.#K!+ SfS;bj`mݐU0eFYVbe!yco Ce[Bd'8%g#?vbpRi*aR͈ReE$J5G"A3fSĽyͬ O.55ϽI|Ѹ)XIwщp}OVr7;U!}&q%/0,kVe]y\>5DB{$[XhSY1YVP%=i"u-pϩOqEl.oϗL5H\Z Ýo>D-BXl+M5H_M usڷ.$ɘ3>2nsFED9`7IF.uKpim\{qZSKTxK1P"徉_ی.tM[}y$ө\$DBSOH0d[>ypv.ʍPz:=UP6V'`H- K!5*ɖ[!D*mٿ?z?|֯?>w?<`cz l-o='x1NSum. ?gƿ>>To ?|?AwQmt?֜b9FǪuxsz?|NPӀƟmbP $)׏׽M[NjgyvP|o3Fn*fc~1*-c_ ^ehׇ緈|&YC'6%Ӽ~}4 Ѥ8V%MhW򽽒[{T3H}|.j+7F ep?h`ۍ'pezb_}^YUֽ wx}IJ>]h+f#Pk]ɶnZ:Ft3̈ $Z[E6EIuۥ=&8>%`1>S=wJ>NJfEkg'Av;ˆkX+k;[[M-3"i qUKm3F}@`eE:ze'\u?cPf -wT-5~'`4)|WSgw%tWU~+ ֞ݺ$+[-iQ _htU6I$Xy$MC.TPn*ZϽ#%x1!,m*%SH $1o% qi]%\`s4#&4Շ/m`=Kr{@ |ϋB5N7-kJv^T(ڕ LV9y2ZNj"(sȕq> ZjU)W *+^W-պE`r^z4YV&vݍ,Hisdž(Dz&{Mwa\(-Ǟ, ?ޕ⼨r(X*Bo\>~˥u="4^_:tZDfYSv mŲ&|, *I]8 z!N{va1n?: CiC-).2]0p8MtFd,E23VUSa&0_2G,%*EZ0N^{u͎ r(2;}Y"R6hS)ZQʌuߦ%kr0\JeB&la x72pTu&Wki;֪2i1i74891{ͦ N{`n]rY拊թ&R!Rm.ѤLM'%]L^k@εj(lZ@~US.UcY; e0EDĐ=KD2{̄@f>&+.Mxt>+R$, eG]0yEpVIhTqQxfܴ &p/CS N^R=K\0FWtm$^$3QjYwQRq@n̾E㘃zۨ&eje\x\ΧqX=6 r%-éȝꐑc$s<1.:(*8}Y )f}20W2uAЍRݡX*׫$L;?Qja f DŶBa4qiF$㙅sb 34H~B"S& "g 2ʦے)k[2j>I?wu6pR!F2) F23%rHŵn5nQ̵I;ͱpBx#y88S˾ 򢂢bǞa "r`Wɗ#Z5jEte-G z$)'f}19Ktj~dA"O+;ØDrK ,mA8>,efQt 6)eeJ`3`s03/Ap:35VqpzSIIK 8V!LbE a.t%0cbHǞa B|ĤL^[ a򦟯U+>.UE=WIB<LZ<X3wUqfLa¢<-$|>, hbBJ'^FnvV"ht p4ѵ*~מZ!/޼TMRSQ#%1VȽS#*1f/{ bȽǞ%aȽ kp/SR;C:;MtF'k衢lxmWZI: ô&B=K0b쓓{䄴ijPW1cϒ0ބ{{i:+UNȾp w8z}{;d_me}Law<u Iw8Zte0>\].aZ7e$ 8#FcI[^~v|^70cR0ބ{υao^YB!DB&V%1{/^9f& B׆ܵʳ{pN~ rgIroBJ{Ī~ :=eF܋=aArp4ѵ*ͦ܎ ܫ܍hUTS4LlL"Vwj4J+$ /L6z!N{v!&ԭC ; MFxsQtUh t]t37m4Xf `|!g1*>YȬbTk6#^MWB=SUl66 kt 2%pquӦ|`_t6AMfI6N}ckmq'%Bk5x^37]`cY 2is4 pس Oڼ5hVV9픊Y O) OG]X ..UVI1#8# ʰ0Ódz0< E]h "g F'Өȶ,5V iusGq&pd:AJ唦3SZEj{Ŝ:5@R0]C? =N8_SLPd0c0 L&ICVC)z69 W0@9MtJ /T.&3E!vkm(a! 5*aS4biK yA4>Lqe54)aӐrpp7TTXSĶ\m635X_kJ͹τuw80VM4xݱ((8}Y҅Qʄ JiFMM%'|R%2r'hp4*I ~{28%[(g02 Cy]!tecHQMSG!I IʶA)wt!BG\ if4BRsW>I ÌMLm,kCasǝaaϪaǞ`L^ :o6 ZHfPj$ W0B9MtJԹCp.,/a8 uq,AX;wĸ% =攟 R g (ȶ c2X[ke^'fx`2 frN93j^:w9a |iWoGT(eJ@P@P1Dc0S&ԯqʼe|hr,_j(z).Yi┹_ui1N9LNAqJz\"iI]^]A>LU8e4*6S`ahfwKt6IMf&55hn3ca4ޘJ{֍!N{a2|%T3϶6mX9=Tx Lar8R$@i>ڱW%W^1h%+I1@y<|0R"Q% Bg (ȦPa`: PN%Le: AR夦3(fQ, dBJ<3:m6{;_#!Qr!e;h^0J9MtJ<;*rl\3yM^:Y38n_:.PKqm5#85!&*eͶ= l#Y`Tμ#TWIHGxHw:EV%K +(JyzΒ,2BX+T։Y6\i(X^QVSs fh掔mIikfkPHj $͔@)c!iCjMz_x I8xEV(fIMf=yj Z`6AJZ:@TkQMj6iwRR$l͸pmZ%b_( NƘZh4Ov~.jE5E%<&j Z"%,t.(ޫ1q⁌P@:Hcb Hs!q~;-H㙪g_O -M 3#yPMEX-.j118RYVkj8޴AKй96P'G]A:X Ti1,s1M&f12kcj. C0tALj*T˚ѮKfOјk@D%hiddvMcj"WRmʣw_ Ѐ!e1+ځN?:@f@235ȹ:NkЄ2l}\a8'8bZ;6(1-0(Ѵ6ƉU-I>GmE y*2ETfy Cj4"hG^ky:b^5xJccVa;9lUp!wgG\:GU1 }̂kdYijL.'iǞ&؈ lljIn`5] f vA];"yDWD*2>;9Ӥv;ZZg ;*J/Z ImطdcT-48liXjTou> YQ0FL66us7c4ۚj˜d! ֛M֘k@&o*" 8.u$-N Ӯ.T~G&KpUYqw||'J؂ߨ)(әdقRF Z%6 4Gey@TK!jY2BNux )mV :KIJapx 018H|}҄pNȄ/,D02liO8ۼhm?%XмPaRp4~ Iwt% ̩m)IO#p~(,$gG:_~ {ur&A^v/P~ze=/]Z <|?1jFf ^Ѭ[b[%1sśi[.c'~Q7tJXS ˚p_j!*FuȻ e@?P()'Br?j)38Ib2&0~MHF;R`'4>ʢy@ &f  2XƩ"1- Nj}\0T,B8O:6ӣ 8aVF+9gHqqڂ鮈^SǞ'a?a׼^`\0uXPbU FYV>tzٟ lƿJ]\4#&ڍ*Eg'6p&#.e;e*hdsz7N,V W1~p#Z* pd 0bO8ۼ^m7:CVmgEFbh:Jaۗ-%X+m{i&ʺ4}WڭI˂]bgp4QdXS6cTxIuoIVk7dOx: 5dD) Ls@.HfC2[d?[xQEa6GqX%k~[>E c}T.71DD4*!εwAQAj/"S+&F j "ZB 6)4FVk}AX&  kuY RVB}X`cY0:ySao sC"ZֻX\R+Ag!B'4[JdyF*c؛eB^z]fmoq.C"`*Ά 1oC1Pe naL B0) ^QSNEF3s98dc-dtBLWGqh^?)0%wjkeZM5xTò׶sމڜW~{u; 9G:H4.$!Tzp J`R(HAL!fAyt( alTg*ZX:[U aoҘ1ѩ~L8v:Ji+l%$c Ud<7kz6Mt@j!Szk² &ws7a;5yYP/ \jFFY` p G]4F3pŚ=M.M(B;ܜ Iҡ.M5FCH@KF0m,,W h+r`)E R)YC&-opm0,&Z<`Ȳ(YO00RSFPHLgYi%#*&+ zlĆ54Albv*s=JfDn~YȀ!eaA=esh)jEk+&Lm1"  b c( cDWR\x^mO3 ‚}0a~#!_Ǟ%_ cv͌`^1?L2m M>>T͗7~xze7*[ݏejp Ϛ=IAuT4oE4o S+F%|V^cב8ƊNYhAZ-g]^N(ۂ}&ncGP{Ǟw݅7 YoPr o]ǺM?\N!+{ҳ٥ҿalYN\p7 +5sݦ"T{};Ɏm$CŪ@яM;ӻ[B&$t |0[ؚK[F۲N:컭$lO\vM,Α 5Ӑ 5II/p jFNeIE#zTHِ0a/cMRsy%CLVH_%t<((ka/\ [ڵ6c~ۘPMT]WGʤ<,$[0u"ۨ}Q?d8HK/2n{L5G˲C"h&F)".h gM{d g%mgez5MtRLA n񶥵 h7huY@ M]aoTEqkس$q+\l$۪Q?[D ĭR\27 ni5DIĺ,^?MW"яجdذ|N9gVZQ>JǦ)L0< y@ &| *B.dy1OO /hm.bTFUPVײfz)_mwϏ?]N]~?\%n gWUԗ?CCZ #TeT+ܑrεኮ.'̶:L .Uu1n/ ᱪd ;!?Ձo=JRT2!uvVue!ZI:Ʉ逤,,7_I0>9Mt5Anv^$>i3ekD[ת TU)ij/C%;?~vv&|7r['r4a91k֜Hb[B 6| b[|%Al& .myqY+A%D;KnXH Jjn,bh8@KQNf_r[B 4| _Hۆ.&mlI `Όm]J/sKpBҚ,qq6X*{ ؆Ymȷɉ&Nom'b[B 6| r[|%An& 5Kt1Fd6j[T^nJŭ A-]ʏ""_*eM85L@t úgu ;.ҏ}]; clƨIhu Wwer EgCR#LZ "WD!"T~6{ 0f' ]Lc& ;. %MIUQ,x`\l8<6Z VqCEU1I\ 8q y(Ulu| %mMgl8"p6,o!NQfVLq7!Hm4L>0;]G:3KZ.Eځ|P7gA3~h0d3`*:6IP̱E{ZcJB:k I$2`>R618EmYXDvQn&)~_ _ @-[<dͳ ;#j7ffP˛Ⱥf}iԺ*i[YV/]gW@U$ S#؆.!':{91֚MV}/nA,&c]VƤ7!,* PfoU `d-t-U_D0a2`m43 p[ d'V6cIN&Dl6KXf_) ɶɍgĶ2hK hf`̛ݚHI 9o:+{kqWp!{k_o|B[msw[,%aJ \B9jYMD:7Mt-nE"of;'M&&%\f/lfLfupYMUYlɭL(2FLx$*9nY2ꠐwK򩴄Z//ǣe1658wٴI)jl dӼ]r@J/ _& frT4/pmpΉc[i#=aB>C̋<4c^+䌱Uj +X'Hk dI&Ekp4!Hοjiηqb%gR0% e]m21Z1#.0m{ҫk2J^mu`Vd=t͸lF B\ tJ\q27#1Me"&Wn6ctE7id'6Ո`  G-`YM,MeV.`_/ĩEV;Lʘ;O?qZ%s1LV͊ҥF6]ykd]#;.RMG. $kkkYtfXkpRLwRTK6 pb5 GIswÃk')[j;ڥ6HP0PLj,E_@06MtA\f⚑#q4s`(a`*챞7AkqhJRI YKȶAͦErp459m43 pZk);8uFH;L9˺r8ٜbWȚ#TZ6TX]͹T RZ|@J&p6:\fZFk-)⋯R\^ieP?a[r1_- IQEa nXK&[ [ -k$cktZmN[}&M2D: tkᶵHjjCZ'* PkSF0PB6P㔝((|Ɇ.!=-,o#8zHuH5‰LM1qj4qtѮ5Lƺv։lur %T-) ځ46Mt@-h,o)j@payoP}R7c`x`Z!;`5!QB%ˠI]JHI3=/ F3A(K!X$l gf.gD֤JsB@h[cVfV)Eh,4Fd7)z; eQUX/D.c|aSǞ%a"D0R+KBXB}c-9hk:i>ڹ6U@-F4F uZܩP NIXeIӚX(XeDc4I-$ʁlN=0@6Zw9YϘUԪHkhesRۚ^&$DqFJwtqD5xڈ Fǥ,ҿ#$Hi)-zl:fx@D/"hD2s RD:=#jلQ %Ʋ&;×`eDEݭǶL -Ir٨[\F3g<މ%LiaB(UcgѬ@?SB"HzY|hp4#`@&2ZmVw zU%Gf ⺬4Cf"jDVufFR4aяmGTZK,t`,|`lT=b@fmUoWԤV\*cݶ\GX1Li_?qUAM0Ž:RhS@~dh#sK0"$i!-zlt@J!HiDR\5k6QBU[ֱIOSDXY1{К*(Hm-lLNAz%HoDQ*sGVĥm &%;U$[6%ma7QNf_[B 6|_Iۆ&mR خ4v}m9أr `˿_ 9KGf_ VO53IRZ|Tm83l@(X%ufAN% V⸸{ :D;p0 !qLg-*S/u)1 ȒjV ;A>E&`*ϤgM/=L +*Q4k&;/ܵ.^WE4GIf_IYBvMfQD"6Mt!8h).i_ k:#4X0TǩK0&) " d4mNSY-`c:ALYN4J;g9%t=Mo^ji5őIfFbcglX5-Җ,Q x`<-pl6QmW&5AN?Ӳy!p4GM̸\a7V+53PȤG &REE5ٸ>]r #h chic1qMئ2Y|Y:Yf8["ъ5kuё.\X>ƻŽjfRS`31ϱ3N[+C `-l8 $JQh b۠"fȋmM~ߖ룗62sgY,NCRC9`0͜X(` &6r*HW|@&j`cGnmYdiV*(>o9J7@wjLd &_a%Dpn_Hb˄Shƶ#c*d %PL`L ̌Y)d+< ܅^ `0;OBPXBl`L7<Ɇ. #69Ė2mJd7#Bq,w1a ɳr{uhB^Blƙzhgay5^X<!mu TRgb_G׆%l}!4\$ɉկDw Ej658 &ATDmbuDQu= h cɍLA+p4UGKrBӹCjXDڹoA Ci䱮M$y̝V ф:1'$+ gh -zld#- G]FFA`][D;]]ݗ:r}%ńkpn7h Cv \#D itcp"/)%hBAJV I'#g8mT6nD65 b|A0 RnO"FK3h,aCu1ЄP0 \6!AH}] EK݋siBZ| (p4e,@ff!MK}µ yqa.4p5MYh\W$EdP:6BCa󯋔#c Uc.f ŗ G]>0=  9m VkunlѠJbuwjHsh^?5~y&Ylu %TMɲhY| A>&`l/iV̐&k+jVF ",ud CfSSz7@DV #h-vlxz@> gDWQ|f_vZr7ՅuK RGfD9Sc q4 P~d!mL},RD}fidۄ&2Zg1m.oLFkS9{4Q͢Hjınrv+Η&a[ɣ\$MrrDz Y 4d:_2ao{bQyq8},XMzyamj"@LۦAZ8p45lfˤfnHZ2S5mܹZD#Q? Y|`eEtP;Mg:t Whh).g,3ʌY|z[4vWjH}Bf Ƀ}n1;@%Ay5Qf0Vv^4m,3o ,.t"T6ykx3Ekj2͛V!^.um娹ĺh"Cps{6/4!a}xt8tKCP%1p}IllYZ4`B+kmE: |) Lj5t,RC Uch!0(xi(B4Ǩ/̔n<)1D4ʱ;Y8:Ѹ %TxE70N;00j&宑nS $xYLhHKe\q$2Pxԯ,4-zF*6M`+^ y $(Ǘdc3r]iobBJipweKa-ođ1ư%Xnf aф[L4 LE`/Z8h4SJۭPJIJE"% V4h W,0Mt%*\lfXk3NdX;G*󪫋k=AZ&<{WGkcV'6FAX#QD09Z6Mt=pf"2S[mΛ>uʷwWrE,S2M%2hԕq[d6%{r^IU`uUzg[B 6| r[|%An& ]m嶮TH%m51 }?>]}/w~CwV?=U뻧o>oo_v?4$TL*Ck s͉Ol!kKQS[[nSO:pN2^d3ӽ~;s|_Mh_ ff햣DԕJ嘑ur#s>-9}>x;.tv9"eqXZ-7zzw^[nT"|EKG9A8jO!"f?׻mKw4#l(}Bsz{Vyu Bнcd7:}#~Υ\竿ALwI#@ Y[NϛR[϶2K;`];~_ȴLSZӘG>8}`_0V{Ŀ0|~ǴKԋ glo1E#V߿z̤ {⟺{OjDӚ&Ƿ5'TGHiϛk̼:[NG$|?B3!^] M7FwVVz[O':]+̊YNir*/⥋'Ȟn]/R%0^6^*e/ޓ`xv9<6 )6yZm[=>61Ǒ2水wL^=WX%L`K>{B)c1Z|6+;5gP+bkK/\ Wś#.kA8W g Cr1y^-™kÊ}cK{yB*ڸHou,|{qqWnyǚUewFk a`|xU00~tH$y'ۀOg=0+< ^N}3Eb;?Eenc(W'<)/>YR8]k Ih(Q t]ېQkz{|6^i-=% ǙuŐ>T.dmL z5x&k1Sr_f0Jwm5Ie7:% Q,fuQoNcJa wz5}1~JfaamяvlnmNiS乙fcs?uIakIlǝ%^Yǥ{Y[5>x4~c bܢZ&MoZt=7^O ${eRl\ś˾lu)|rk:=ªO fg{1|c Uxf NcmK5 Nѹ}w`lLvxw2~-L2֜Pݵh!"(c;mǍ_׋b!clKl +oma:GTOˍ]_։` J;U"N}Bڮ*j;-5MZCu`' `MQ˩o%YNK7Qv?QɈO[zvNL%|$DR}8ho um 3Qmkiȴ23Z.' Ur`Y_~TsV7.zC}3+s>=m˚c@[N$pus>@jUs:.[RNؒ˞o^|yա90; '😾gs @۬|*I1*LwH IQ̪TCsmn\)f{ ?4mْrCZ5dMkܭ0uB)٥2AܳP8[.<o99w]5p–9C/<0eLOέkA?9YhΙО(]r>Чʞ@B7SD񇐙b)͔6SxY½)^<U=2cRC^a L eA61r9)Wt(['Nj"6ma]6Ybk( p pP)l7^;^#xr׫`)W /&]A&{vw~ÞnLNuչ-C uBU6hf{}Ɂ @񲟙T WJ 8.L S=6 /yWhϺ23tp}!ʹ+?s8ey ,*C; *퀀嫲}gdsKrz2? O\78QʒV8ݩx?;QcdeC-b}|uȞo>B}q(/Ohơƙ, 2 T<Ff /lA彮0Glu^&d^M *d *;eU* .|u:^plox]R·mɵ9`JL ߀}N9,6kyA,H`w[Bn@/ogDžpQ]tBKxvIn?geP~SBt"zJg _k:˲f5̇ޡ-= eH4?Te~`lz `;He8ev<muэo9ځ5e?'C9a'^0}NhlΙ, uu:e se /unA%2.Gn^% ^ آt ..L|!e[T|ȳ>Sz.>p,XDL1T8)_u;{GÈ|}=OVwv?QɈO[zv]<ͻouOǧ|޸}{_?}n>~V/_ y~융F8Q&$FnjJ .!"~t?YX{п B㒧+*hDfEqכfT}~f?uK/RwOhQ/OUOkTRE*$b6.0~1IIuWyoϏ7OW_>WsNKjG&Y|{FRM5۟t>WZ߅8e]wq{f/3pV_!?>jErù,̱Q1ż HI 1;o~t~|uȞktULFxذbjµi3RQ8_2#zH-)?2Ʉ(w*"tV#OUkȢ!BӐTאӦq<0U=#EvJ K˱Xj8 @Ȧ.ʦ"~o58*(G!SYB'Leπ]3 Θ4qWk!ԛ!ՇUPb)t]A,ݸ$RQINSh )I>8f 82bY0ıPiBB EEjh=Iƥ6 6EJ68pxᴉˍ%ǙЬ#ú_FpX-yF떭&8lvllΌh_fis qse~YUӥd́l*&T523Gv^%E͆Gd8jY4RL&N5# G5 Q9j|֠2G5zdD{\uRڋeP>7\jhhs[ QGSՄE>jJTR*&^dΣ3IwÏKcaIMf&YXvޟ{z}/gGB}6'p"ueV]9Kg.5~DOX: )dHB0qzyiF ?^:k<% )3Aeԍ3t99͖Qd*OX)|:,˥O2/!e{ˏPczDDL5cd>kTZwTa=emʮ 4HSuIS(BYc "Y\IU 31` _%3WܚnlqU|2\X)EaEjC`B(K2Y͘GCVg(q1%Ռ*sqe4!g#U U(nRc5z~Ws@U`J'3`I&T}lܚH.5[~DgLJ&BLk*ɩ)1N*Rxniԥ*)Zt%{\uKk̈́k&CPmBIUP c I2ÀGCP 'T?dev25DPe\uo*yҕR%Aݘ8]ʘ\iRrͤ|Xf#sӕTpSJ2= -Oxܬd("'Hpy\|֐2qc'4S;*ms2hJBX[Kg\DDO8lS19'<,,RNJH%R]2G͠GQ )qT3&dQe~23FTj &&pv-oخ[Z7>Ep5/xɥ(hder3]v^ =]8j6تrC)T2iwv/Wf(ᨳ8J27`23NFJ1r-lڞ\ ;#*qDs"s\j2}i/8ILܬ\{q5qy` #e %c6i1 52oi=2 iۊ0nAɹ\%miuC ʵ @f 1e{ˏQp~DHt.d>oX9vm'TcӹTPEE}R.41!&N̜ar(>RӼjl\^TXRB 'Lrj0$.d>k@Z7rus˫kRLͽ/wu{89pw𷫛W>N$N6_Nn>]|xq}Y"|gaء矂9³NJTɒik >chF'EL,"|!ܡ7ϕΝf &rL$󷣝Klxk9wr`emε8/rRі ѷu(q@FT;J-Iz@`mx$#vkGpk-y6B#Lv,,}j%\ 93m[[s`VVm.>$_L+md6 <>I&l`H&l#.vv~~{[~}>m`no9ބ/nN?]=c?u<} 0٧otէ/N]B:y<~ߵJ\̡YXcֶ"'v|s~lՍp[?YWY͏܄ϝbD{5,5ʏQaWQX,þ6{@7}d*,ل@Q.CSq^zTeiSu~}`f7n>| {8x D> >eVSU".?xFl |ǫ/Rt,g siLk=,,ѕ/MP,??I ѿN>*t|Σl! OcF8j!\8//dthҨ&[O[A$:tA(FeR/Z_;{ 71cÍtVSp#T\p'HL:Qh~uK"gB"х]^ZD^~6ay\%=7Y4/U'ԈSxڇ/Z[DhYp_81ǁⱐ}eӹ QFmFP44xS!IAkZsMӠ-@SC/X}I(GYu1Q \y/vM)t 'Ig LU%-g\RKkmw2^9--x@OYi.6KXvKDO@Y2J Qm0t#]JWDD4sHq4#1j +tߞ?.s-sYt<+&`')m%{/ކoFNԁQ|,]x!6 /M(m Ǻ&xC$C'&<UkHۍF+;_SâUz֒"..H,5KDI9፡% @KnTӧÍzǻ nH*iX3aØkvrѵovx||څO^tZM,1o]ӄM&7 &aZF&a [qE~SQ\ pJ$a ]M1p.",-6Ch`3VqǓ|} 4OH'_8pptgd AaG0MF7<]{4x*H؆), t0a xd -ѫQQ7 BpjtҐvj6>: "q8 C 9K.:lLvHM0π:2>L1YPN,$aAiKO/(|Kk2Ay1,7/K'00.)\DkX."+p/J&?*l"0b@vY\3`'kFL0GE\0KRK-QwB^"Fd-IOX +q>d{'%Eh", ?uu ѽm )IƝ38hxNgQQ^ScR%Nz(A6u<_,ql GQ j]GצtnЕINt6IN x`4Ppd}; qtELg)/{zkF6QrJBkR٣PG,2TDB$3>9p\J%A/? /DNA&:QIR$CѩѼn  I.kcI"݈Zӽeɔ ZT5ܹ $9`:3%5 Q FB4-Gd_!9`mAa`(oƒݦ*섒8u'LR"9t0"$mGdpXb8>G#B5htK8(/4\Pvi%${[`\Rar7oаbEu=OJfhYy>٥0qic-0AQ-P%G†%G*-C@ѮIb,1L`:$c _0vQ6EʀGl:'5]&XĦ0 )`֦ߣ;6{eZ>L(*)$O)@I)ӁI%A4$ҽUDdA$P_Fи~9l/,j.nhAl-gZ`<@\8; g:랕AD7!Ei%XSO4IEĶ`M*U(8 RѮ@})bT^0'^\YQ \Iװn)|P40mYN K2QdmFeC)*AZߑ6EUzpK=z,pO"R- RG?0:qŸTq5@ʓjH b':111L<6PȠjVSml4\Z >E)QtQ\64 UQŖ :ѶPZFB!!TlPeC@'ȥg&i !3d<ԞGBaf(n#5(ܲo`J1FBOHYpP?"ypuS+b<( e6DD9"rj'(sr8R3 ueF);pk|uL/YdM-?D#,mSڍ唅py2?NQZRnYzq;+ 4"=p;oTGrp ͚f4T: 8)э*‹Ln:+YuC9zCXLVED*].ɗӈE $*%:$8Z /aBItuT$I:4ƢjFXձcQ7b;kEUМ  }Y2Xi4flO0K󠢃XU ilPcHMNJIlMoc*1! &JH$Aœ7ۦXx뉎O=zcмmp3Y@M`JJk4jYYBgފ3z$t t֤*)ؠjMke-]M ˯ca"`xXG1OQQ1SR7W4b S,iP;z CG @:yx<<'5՚"ɉ3@%MQ Tȩ4hJ|S L!gOHAaO腭!.SoD"mRaa1%Xگg]z!YW[Y(i圐%5e)m-֩zS7G^a9qG)5Je%˓ObpcRH8p_Ci$SLfB~)/ǩD2P/XDm ־Yb3}>_\b!@ET]/g<˳./~ڐ cˏOW;᜝xusvqb}3M^ ܵ6c12l?|ӓV1f}~ 1H;W{fTOj0+λ4:m׮)"Y]2 TJB6fw\x!3rϝͺeR%:Ki2Sc_N#M[zi饌`4aVd]M~Mt:[Q ڿj>r_W+?\.4~M] ۱kj{b#S,[ny޿_<_ؠzc@H^Kg!4ǦWkYvX/6ռ]W9ưyUW+Wkrj S}>wēS,7oZS`(,lD2f91:223zҧf>}fltIYNڿUsVއm,6燻OWqT@T!{>_dz ۆ66/qJf,o\Zh?D|4)GrFڑ)[4yu]k8bƂ^3:OUqb 9 T#Ӥ. tWfq NA`̰9%`t$.f! Ю& v.ܑ4nN}b0ʜwʜWA][/x >k5'"(0 Z u^:$bvkzIbƮTq2o& )Uf6BcN>Pd`WjM8/affxȴo(4{l^Cd-w(Y8Cr&:Vx4iYgAH&d!!dZLȰ^4wN6"["BgJ6 {UݯJ'FAzǐ0?8)z\ҎТ .pHQy>pw=rݚ1+–o[ WTabJ0Pl!Ʃ:Lڔ9YwPwSp(OtCII6znOE([.r+ +:d.3mBrn@ڢ1\͚}*K.LxYe^=-8=,398d~7dv[{ힿ^7tO)- EI})uymM&U $Mndp '-@rsMgȘ؀灴VWdq((@LƏLi`^_fs_B.we1qӁBc6[|c!#²^JnwIŒW\.{c95t8u7d6;%4S Pp)㝳ycNj1$07N˭d6a ɻvk;Uu˸J$uE^/Sb` ݲ4=VO JmIJb  P 퓐%,NC| ԣ#̉JmhMO⭋PL :ζ=$z'uDɇLzC$ Countdown.inoWio8_1ŶR#ǒs5uEzM[,64D:7N77Cv(+Z[hJX%RR,_zX4l>(L퀰p6H|MC5'3+ag8V*՛ 94\O_&Q|cO̗I]<0'n\'Ct**Ғ 2H0sHQxVatGAʰx3 c5t-%gz1YF$_Y 1F2Ir] m$cϛr^KM,-/8r{ oф!kEBJE=a?qtgv^2ELr2QtcU5L'MS2ֹuUGiG)XӹC9͑5^2pCJS2??`n PZSkFTR07J#˷MO_om+VVkr/ '-HPвOo%b߽c`N!HR2\x^saPAQ@@n0QujhP/WF@ O%rUл>iv`k|-;hllv4l*բ jԽ*P Ck(?H,9>Ә\.gz| p wG-?|[|vƙ'㌖Lg- rA9)G\*gapPB7EឦZISb}69mf7h' ]M!IQUyR7OUa"+]x&]gy‹a}e{Y'P'%>硤=ҹV0}җrN Ue`Wcr:][sq UcQe޹hUtѳxvckk-s}>zڇΙYU $,*GϞ$J/_'298'8=xNһQ;wҫ~[z}]'.4Uu&Ndыl/UTI]-z6I C$ Countdown.inoPKufritzing-app-0.9.2b/sketches/core/DC_motor_control.fzz000066400000000000000000000561321250202676700230560ustar00rootroot00000000000000PK8DE[YDC_motor_control.fzmƱ&}#?pDZ֞&X/c霰FY-{͞ݧəQ/_v2 $Hhv[ ~y;8{\zE j4_}o?~76_ՇqSy)LL|5OݻWʑǫEfwWo#/n۫W|y;_џ|횹[,/W}_-oz cRF7Wd}5);4їO_.߻}]^?/_^N՛ǯ^{_uKݫܷNFww?ޯ>6{fջ,79k߽}-sG'5M?f s|X޻ޕ| Ǜw__TnVkԧ =(\i_f_\R2lLؘz-K/]%?]~wp;o 7z&s_\M1Uspv2Mno͊_^U:A|Cڽ=<{*vK ϖG:ƽ{LJ̫g_f *7jzw{cu=k:P.vлۊԓntS/<珳'hԎla~ljf Q5mUa/}/'Ih/XiEw-(p$Wp9EtKh{BC3\g H=:W/V.gBhġi:'@" }{SS XQ yӥ:qӖpu$}R6 x3#'x[ud򶩋vފW&yyׁ^np:ޒ-"mCx]v+E]M Eނ';ⱭH`X"ӧVpէt;~czƏ燋/vw:\1Zj-WD}ө:%vv/Xn'4yqG2@_di3$buRɨScXj,ص1kKTcGNvI@CwI@Cx] >7QC۲b[QD<MVz x DMu/"=uj SnN2fṂe9FZv&fmJ'<|h[_%fKu_MWm|)?l K ^Ogbp\^ w{S{ >AV8dOiȞBs?*i C`_|F 7>* ?wi|\oɌ{3S.g(I~Ϛ+5} P9= ҈Ux(\14^失o_NbwJ_0eYݸgUɚ{H튽Uw>2Cz "T!#F!ǣ^ :4NgK%+8a%~8 ``n0a3+bC— F1#KCҍp&pld ewSh8V=; ) 4pԼ %h)/TD "13zpMoٮӛhpƟ(HAa IJG`>ǐp< -[!ISFywDA:'Q3 {&g2>Ma M60- "'S6 ,lŰ> vؑ3؏9N>h-bH02*?{GޡFX7 eaS(RG´xj3M֊)H^JլDU e *$%zЌ%u#gKj5jH6Єa!GZL;2+?23+ ٞ(eQQYpZ_X ZQ~EBL2;;8}ʋv ;כ,EAI!Wd|9F$9da;k0:Ⱥ B 72e著UCO\DLEe d-Tt6& f~iQ&]gXg,>$q3 ]ELa“~4 9ozmi~3m`1y1*j ,**uaIx2EM;: .BѤ h0Q=Ӳ4#wɁ%NYZ6Gfi#$ Nzޜ\F \;2Q "2&2QM;wH\DD5P& ӇLѶ65EFE2KM YK;Asv$` -][fB0-ư[VCKs/C7Ws,J,;‘s-""Oh\(7vc8S12|- WpZh9i]0+x2M+NmsL 'QF0t; 9됙9c ؑYfoƏ-Vģٙ"P{ҏJ岍1K|Ŵ 4Weg*IjL2;HΛeH-4bGfgi?2;:;3=3R L .e! 鱑X3,tL66Tm\'>k&{ǑPB;+jVP`9LJd)x:mBI=!y%Zg0{'`ogwvdBsi5 KyqyފDIJT}l'e"D$׺Ci," 2f޴ mP4sZSiql iɛLCoyG^'tHpmhLѺhI04G&hi@2APlk@ CU0˙Wp(3xCMYyC׃i~XKIؤ !Ъ~9VbDȘrpE.u, ɠMT{=8-ʽOtC'~W΀܁uh;A2i`컴c׃#n[n-E4;4R*UXA*)QFLt;<98[pd$AЈ mm vlȞ e.FUV[f؝%87kpOBǴ8D :slvJ-g{BJ_Š`%%"*u(Mx6LE^TU9ж\jdm;IdhФtiZtyӀ1-O@dm5-6 +PB5h`%%**u(gMT6LEHџjρLji8Ez$yS*WgoE kIZ<ƫכVJ3Ûq6I3 U`%3 嬙C*(foFݶs[MB$[Pb覻J i qo^)-R"t&ڊ!aIJl!'5>՗A)Y?R 9ᵍm x>f{cIM摖b!bZTֺrĬ7Fʴ*e9"YaH5),F4!\3ͳl*-Nȑ޴!9q3`SUpvԼ*[0icf/9 V&U#ȾhYlHA9Hj-vFL`?XX.1ݒ[=Ya#3E +fQ[@~i-֮y411>P+zV?dcAacZt736_X!]_0/Jl(E#d)+}+wJdA2yM([INQz[@xFRrH-fm\1ɆOMԀc,{S=00+q^9V3Ka3R bR[rMgeX*^=#D~' |Zvz?џ|3~_n]N˫i=;X~\G>w|(>(fW&7..&߼ol gKow}]i8rw_ 8 c۩UDg |13g%B%+'Pv{7e/'r8>o^O=.&s_\M_h9xzchvr3+<PzpòkvuFo?yv{N9TJvAl…_e +mNgP"6ng10w瘯pٯAI^/'O?k9^^IxsnDRhf ۽.pcZ$[Y㌫ԘH@V~O}sqmz״f\Z,p@S1UhV )S0!˥zB|O8~(x3>^}sb=2){q#vWX" iis9"6Pk[q> R UAy0^D8<)]F1vblTp2u:l28FJ@nF~oo?٭n|s8nۗl>җaqm~,/obc[rS L$W{>i5Ml=т?#k.W{ޞ4 m_Ox =9zX9hZЖ}Xq=R^">ƙe>%%/ X6S¦WvUgxYv,b-ˆ2]$Mh#o7Hc'/nL qøëM,{ ΰLbƗnw=\-Y*)u'sCJM'![{N{-q !muɁU<\`Pd5I-+2mkLɽi')A v(S2ikQrd7`r|"A6xs&ktNכ#MɨS+r4h wp$)3cHeHdǹ&>OE/P\wu9S,M3=5#և- ַb~;[̙xE6W{}~E"KD)4`WU$FpM(ŝ64W L7K%! Hd=2"j(AAIEԫ}=!9'DJ(zbPdUCKD.\.$Fi==_ylRH\rvcEB"#Nۼ~"yڋ+~D]#N pՏH64Ry7WM% Gt>Qj+)AJ HtN;: QHުJ q;m޿D 6,n5$=z QȰ+D)SiOWí ]$Jlmt;qI6'zBH"v8E\duB+Jp86jn$=!QȰkD)W SiO߃7O#v(E>! \.ozob;qu~{S\5_.ٿ~:9~ +6TX) ;eVMlvP D_t^F={珳?IZE~=y-?W#^[|JUi|\oɌ{0=o{5Η/N^:_.4aٯY\gMڱ{Dj-);`ryxrW׺Է/'k;w?=KYV7g*ӊj6,"[J"_h5)Q@ I#FQCD%9,#uZGαNJ J}2F l^l[ "]f`, s--Vxsofu%IsWL;~$!s?d'_z,WUWUz?WeB\BNTxnjY0jTNV/ɪ'q fHBHTfU^6FZ؉'"Řj[} VΖ>$ &)`8lucl<l(w/ˋz*G#$8,Tu6o;$nW.gz7G/@3OE~-["rI C.5)TJUcmp1[KlQ:> ^:tFOMiD4FQZ)*S /H> KgoZAm3ʹ깵bjDKmʈ-ehEz.,V:|$E!Vf(i`h@} I&Kyh5D%,L5B I>ȪkLA_0S'OYɑSF(£rF %,uH )-!ZeBaiIW'f@IO)CJoSyi9^JVai+e/r+J(뛭.̼ gF:2{2x I j˖Бd:qáIHgtv#f$IO)cIc53'כ5LE~?XE #-qGbΔS̰˂QKf@i`ip5eI&QyҘE͊}%/̓l;\@sr73.ߛ@h8Uʸ5ŝS,4erN n ( 5MN:?<4#Jb"OS'Y] SB#+2Ӎb 5P{s\G(T8U)nʑrL%Z|Y[3DT`!s ( hm4 J)H,&,4崌vp]0ae1%)'(qT#dA%9' +TXcwG>^gW;\ڒy=b}qy7~/߽9xzdlt3Ⱦ><޻jytw~+8qj~H|͞ˈl<| 1H,q I=L.L"{wO?ܿw\ZXrpuZ>ͯ7BEñp+z%m]~3YW'I:J8W5/yluoo_ߎ>:U}-W_|X^w7_߾_o~?;Z||7߾oF_'77?~3O9|_Y.^O&>}*>7bNEw3gw_-ll<av7{t#Wog?~X,U)4/џo?nT?᣽۫hh 2Ab*ݯ73Hu/5 _ltW ʝ<С( P /*lCrCN魛L$zܫtJm_lĉ(rDn+"wQ}:נF_}>FcG +-I~PI'q?bƉV##Z fL0M?J* P* E;0>-hy(Y8u #УIRThtnzљk(w w#<=@ Oh+iwKZapSfrD"w[֠ߚ4z][+ E[~AgQQ!:^5@B|Ly A|LaL x(Zwi`.3fu7"GWOItcЌMֽEeDfAyEMEZ)5UXŲM/߾|p2p+L/I̺-mw7 +yzq>#r b gQ!8~pYĹؐo߆GNz10"u\c#TX$~@c*C$2n͸p) \iT70\ jA,X+zٻ# (`Q:v䣻S|sB` AOOX4jȊE# pҭ te*X0AS3@VV he.a2x_Bt 4AFMNh~n5.fF@^܎vA#N`/oۂ%c?k: UA0{Qef+Po^)H7'ư>$ ێx42p PXIf\`l:N+p:*inA`AS|ARqR䄳.I!(yp4h p4PL{"рGCP؄S:CoYq`T|6'i/Ez8v dt=&hw]Ci ToP"oձQƱ;P#HÓ*³<;(w*lG8+7`B!O` 1p4YtQC; 62"p[߼(Tzܠ!Y?PU<3D&́qnUP0d#X@%@QR P#)h7b30UE9NhKD@pv`xM4.Nx+fu8c' ځ~rVTy`ě0VQ0X(y4H"WVxVa} wN #2B8 X|JpFmA /5ÆmHGcih#ZJVuV# .ýhw{M#z,hN#ԑ4pu8}YNU1И~FYI1!&!ڷ_) zޅ }GlvvC`IB : ;`DZW!5pDU C`R0 c8^َ+ʼndw Q8Uh1FPESAb@b@ >J!N](p[DCO:|@f#atcl4?lĸ"صwTөW6^CH)rW=DG]KHp/T1xp?2'ܭn]@>:cLoHWDī"R+ _K*ڽhhM]Jaa+ΥF2ǕAK(2E&Uf{4џS(Oų ]5o7 le@-5sNW| =V(h8xZTg+zr0q#x`[p8 !ӈo&/4BhS>T &a2"/A"HL j(E)>Bd!0[dt;8d%xIx q"iGC 5l h#LtrOiz4l z*e>Q͑>]M2L&4H}lz\jZ(x=UvN](?oϑrԲD:0LY4%Mev F՝B KMdl5__OcI|RM2wH釪ȎBw =hL8?"ނPP?BvmV W؊E pC>Fc ew誮t5ؚkECOѶk=(.;*AƖkr2Iqxo`J_Ƃ9ai(f@D{ rRĊVdvY­5Vi= x՗Z'Vr1/S>_OOغ\,UP?L-]Y<^>,-& T;"Iꗽ֞Xnr$'Fujj^՝[mZ-O>[L+޷=?FVNrd9SA?۟Z/MVOcWOwQvxkl(q2)4|wH![onDƬJ5bIL6ҋAYjtz!Ll2NPXLm&67~Yҷ7]Ė}X ƬL5&]Xr95Z1Lɋʽz~M'8^Og",vu 2)2 ~6 D[WJm +->~a'U(i~_RJun/-l}r1z?]u~Ѫ=o5WWnΗaK'~"ެaiwW\]4QyNqAC^B(]#5*BzGC+q$(MR1  /x0@ %z"a}?fc{1nXQhNw8L8"&4Q5>ch$ MЮ*uP%F" -.NbiqmǛ%,A.Sx6WӽbJj#J$k 3yxpO-=Cg!tDX dPq*-Revٛm >O4=D 4 \ߝC;7cgbJ]i0U?|1&z`R2=lP- I/M(H;QLܚ}!tjy--iӾM~I]᭵xZ#ba /-fF)H&.ljF]15'd6d t,hȼ!F9{x:2{O@bБYZw/$ɗq`66֟VˢMKΫ޷Ή@$sR/ww`M=TgPHthe22Q]ќ/`1l1+`T-i`TX&ʻt` %Q2'lOJ[=x%)X%iш'P$MHCw+EM˞I z9])\Xe™*כY[cԎ##.hz8A}}-bdl7G* YQPI5TԐ6eB6~!!!cG&dG&d]"y2`+aT}|c$Y!rpSAҗۛv1@`e:\=`f@u|dX*SxFXl#{>ne$LWӞؗ-l>_dj\1Bl.}%¼<?bnX-je6fud߁q' x?ch0 s %TA{c\@C ^<㕧ɵ;+7\1WlMH#3A> +v'&94%7O<.9AFOn}dmǞdmpdwP9Sh#v[,m8,gPX~9ۢϱC2ukHkiDr=R `iк~ԡ#WzͶACC-{pLeNf+ u #8]sТMhFL6{*zdVAqs2c8Lmn,RzʙzblXwvp &׻ +8]HfcH#8JH=Ӳq !yi[0wEsr&z>gU$]F9.7m"Ϭ[ďLZG"9Κm9Dٛ#MPr>la-؂ߊ(w}5'sbe.a$A$GsM_,]OaF%Vvg__Oe︑[x 9rkFNTό `e-5ΜNQ8z)/>$6a$lY;5Ueod#GZLa?vdF%~d^V hD7պ%c۔FUܨ2Q5eTZDAfFvZKZ^-?%CJTa=G P"MSqk%jP8!ȕ{?=[2n'>d#WYl:2>rd (=S2fT2QZ;BPv@UZ|!YݳD2 1!ecRhW:l^Z^^"SVQ#S#Ȫ8N52g"4xYÕ/J$M(Y5'h=S4) TQ-la|1TTT☕e吚iYdgMaxqd>q:d-LA+~ߙmfZj3 N$ 4$3P涶\8|UhP^y\Tih*š B*, Q) qd!$!gB)!/wA.ob;qu~-Rիݓ5?SSՃy2YhzN#M#;t(x|?zO|;{ ?0|ι,)Lz=,R p|/N=k Ў?=F2w` \SW G_p<->枃°o mgI(Ov'2A xGIۈ`|xC/rOgxYL$&ĸ!Ȗ@A2B A 4 f5)>+mLV;}Z緶p%B] {cڐКS(EuU/Ix~{ t֞JHQ^Lm`_G⑒/)Ĝ,VK*^g*ʥ)bl2rrc7ee\N@xKxXV*gWiU\I;643G)޴P*b䤞$3$3SYh :ܳ j *T U]b'L*-&)>&9.+C3=,춰 wd]eMu0.cjς"S(bbx+Ēp!iHUnjMdmH3iv d>޴$MLT B>Km[Tjeo1"ejG5r-H2kkF2k4weKsDCY63c@2cM 2,/'PK8DE[YDC_motor_control.fzPKA\fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/000077500000000000000000000000001250202676700235015ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/000077500000000000000000000000001250202676700263135ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/000077500000000000000000000000001250202676700321775ustar00rootroot00000000000000000077500000000000000000000000001250202676700331575ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/BlinkBlink.ino000066400000000000000000000012731250202676700347300ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Blink/* Blink Schaltet eine LED im Rythmus von einer Sekunde an und aus Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // ganzzahlige Variable led wird deklariert void setup() { // die setup()-Methode wird einmal ausgeführt pinMode(led, OUTPUT); } void loop() { // die loop()-Methode wird immer wiederholt digitalWrite(led, HIGH); // schaltet die LED ein delay(1000); // hält das Programm für 1000 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(1000); // hält das Programm für 1000 Millisekunden an } 000077500000000000000000000000001250202676700333105ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/FadingFading.ino000066400000000000000000000020001250202676700351770ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Fading/* Fading dimmt eine LED langsam an und aus Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int ledPin = 9; // ledPin wird deklariert void setup(){ // die analoge Ausgabe muss nicht im Setup initialisiert werden } void loop(){ for(int leuchtwert = 0; leuchtwert <= 255; leuchtwert++) { // fadeValue wird in Fünferschritten hochgezählt analogWrite(ledPin, leuchtwert); // und als analoger Wert an die LED übertragen delay(2); // kurze Wartezeit } for(int leuchtwert = 255; leuchtwert >= 0; leuchtwert--) { // fadeValue wird in Fünferschritten runtergezählt analogWrite(ledPin, leuchtwert); // und als analoger Wert an die LED übertragen delay(2); // kurze Wartezeit } } 000077500000000000000000000000001250202676700336335ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/FlipFlopFlipFlop.ino000066400000000000000000000020661250202676700360610ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/FlipFlop/* Flip Flop schaltet mittels eines Tasters zwischen zwei LEDs hin und her Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int tasterPin=2; // Pin an dem der Taster angeschlossen ist int grueneLED=9; // Pin an dem die grüne LED angeschlossen ist int roteLED=10; // Pin an dem die rote LED angeschlossen ist void setup(){ pinMode(tasterPin, INPUT); // Taster Pin wird als INPUT initialisiert pinMode(grueneLED, OUTPUT); // LED Pin wird als OUTPUT initialisiert pinMode(roteLED, OUTPUT); // LED Pin wird als OUTPUT initialisiert } void loop(){ if (digitalRead(tasterPin)==LOW){ // wenn der Taster gedrückt ist (LOW) digitalWrite(grueneLED, HIGH); // grüne LED einschalten digitalWrite(roteLED, LOW); // rote LED abschalten } else { // sonst digitalWrite(grueneLED, LOW); // grüne LED abschalten digitalWrite(roteLED, HIGH); // rote LED einschalten } } 000077500000000000000000000000001250202676700340335ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/LauflichtLauflicht.ino000066400000000000000000000022051250202676700364540ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Lauflicht/* Lauflicht Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int pinsGesamt=8; // deklariert die ganzzahlige Variable pinsGesamt int pins[] = {2,3,4,5,6,7,8,9}; // deklariert das Array pins[] void setup() { for (int i=0; i0; i=i-1){ // Lauflicht Zurück (die äußeren LEDs werden nicht angesteuert) digitalWrite(pins[i], HIGH); // LED an der Stelle i einschalten delay(100); // hält das Programm für 100 Millisekunden an digitalWrite(pins[i], LOW); // LED an der Stelle i ausschalten } } 000077500000000000000000000000001250202676700351025ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/LichtautomatikLichtautomatik.ino000066400000000000000000000031341250202676700405740ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Lichtautomatik/* Lichtautomatik schaltet die Lichter eines Autos ja nach Helligkeit an und ab Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int lichtsensorPin = 0; // lichtsensorPin wird deklariert int scheinwerferPin = 2; // scheinwerferPin wird deklariert int schaltgrenze = 300; // ab diesem Wert wird »Dunkelheit« definiert int wartezeit = 1000; // Timer-Timeout sind 1000 Millisekunden long timer = 0; // Timervariabel wird deklariert int lichtwert; // speichert die Lichtsittuation void setup(){ Serial.begin(9600); // startet die serielle Kommunikation pinMode(scheinwerferPin,OUTPUT); // scheinwerferPin wird als OUTPUT initialisiert } void loop(){ lichtwert = analogRead(lichtsensorPin); // lichtwert wird eingelesen Serial.println(lichtwert); // lichtwert wird an die serielle Schnittstelle gesendet if (lichtwert>schaltgrenze){ // wenn die Schaltgrenze unterschritten wird timer=millis(); // timer wird auf aktuelle Zeit gesetzt digitalWrite(scheinwerferPin, HIGH); // Scheinwerfer werden eingeschalten } else if (millis()>wartezeit+timer){ // sonst wenn er Timer abgelaufen ist digitalWrite(scheinwerferPin, LOW); // werden die Scheinwerfer abgeschalten } delay(10); // Pause } 000077500000000000000000000000001250202676700333645ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/MatrixMatrix.ino000066400000000000000000000036331250202676700353440ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Matrix/* Matrix LED-Matrix zeigt ein Bild Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // Pinbelegung für Arduino UNO int reihenPins[8] = {9,3,2,12,15,11,7,6}; // Anschlüsse der Reihenpins am Arduino int spaltenPins[8] = {13,8,17,10,5,16,4,14}; // Anschlüsse der Spaltenpins am Arduino // Pinbelegung für Arduino MEGA // int reihenPins[8] = {9,3,2,12,55,11,7,6}; // Anschlüsse der Reihenpins am Arduino // int spaltenPins[8] = {13,8,57,10,5,56,4,54}; // Anschlüsse der Spaltenpins am Arduino int image[8][8]={ // Bild, das auf der Matrix gezeigt wird. 1 = LED an, 0 = LED aus {0,1,0,0,0,0,1,0}, {1,1,1,0,0,1,1,1}, {0,1,0,0,0,0,1,0}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} }; void setup(){ for (int i=0; i<8; i++){ // Alle Pins werden als OUTPUT declariert pinMode(reihenPins[i],OUTPUT); pinMode(spaltenPins[i],OUTPUT); } } void loop(){ for (int y=0; y<8; y++){ // zeilenweise werden for (int x=0; x<8; x++){ // von links nach rechts alle Einträge des Arrays geprüft if (image[x][y]==1){ // ist der Eintrag = 1 digitalWrite(spaltenPins[x],HIGH); // wird der Spaltenpin eingeschalten } else { // sonst digitalWrite(spaltenPins[x],LOW); // abgeschalten } } digitalWrite(reihenPins[y],LOW); // nun wird der Reihenpin auf LOW geschalten (da es die Kathode der LED betrifft bedeutet LOW eingeschalten: LOW = GND) delayMicroseconds(100); // das Programm hällt 100 Mikrosekunden an digitalWrite(reihenPins[y],HIGH); // danach wird der Reihenpin wieder auf HIGH (in diesem Fall also abge-) schalten } } 000077500000000000000000000000001250202676700332205ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/MotorMotor.ino000066400000000000000000000013331250202676700350270ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Motor/* Motor dreht einen Motor erst rechts, dann links herum Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int motor_A=5; int motor_B=4; int motor_Speed=3; void setup(){ pinMode(motor_A,OUTPUT); pinMode(motor_B,OUTPUT); } void loop(){ digitalWrite(motor_A,HIGH); digitalWrite(motor_B,LOW); for (int i=0; i<256; i+=5){ analogWrite(motor_Speed,i); delay(20); } for (int i=255; i>0; i-=5){ analogWrite(motor_Speed,i); delay(20); } digitalWrite(motor_A,LOW); digitalWrite(motor_B,HIGH); for (int i=0; i<256; i+=5){ analogWrite(motor_Speed,i); delay(20); } for (int i=255; i>0; i-=5){ analogWrite(motor_Speed,i); delay(20); } } 000077500000000000000000000000001250202676700342015ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/NachtlichtNachtlicht.ino000066400000000000000000000052311250202676700367720ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Nachtlicht/* Nachtlicht blendet Farben durch Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int LEDGreen=9; // LEDGreen Pins wird deklariert int LEDBlue=10; // LEDBlue Pins wird deklariert int LEDRed=11; // LEDRed Pins wird deklariert void setup(){ pinMode(LEDRed,OUTPUT); // Pin wird als OUTPUT initialisiert pinMode(LEDGreen,OUTPUT); // Pin wird als OUTPUT initialisiert pinMode(LEDBlue,OUTPUT); // Pin wird als OUTPUT initialisiert } void loop(){ for (int frame=0; frame<900; frame++){ // frame wird von 0 bis 900 hochgezählt if (frame<150) { // wenn frame < 150 > rot analogWrite(LEDRed,255); // LED wird eingeschaltet analogWrite(LEDBlue,0); // LED wird abgeschaltet analogWrite(LEDGreen,0); // LED wird abgeschaltet } else if (frame<300) { // wenn frame < 300 analogWrite(LEDRed,map(frame,150,300,255,0)); // LED wird ausgedimmt analogWrite(LEDBlue,map(frame,150,300,0,255)); // LED wird angedimmt analogWrite(LEDGreen,0); // LED wird abgeschaltet } else if (frame<450) { // wenn frame < 450 > blau analogWrite(LEDRed,0); // LED wird abgeschaltet analogWrite(LEDBlue,255); // LED wird eingeschaltet analogWrite(LEDGreen,0); // LED wird abgeschaltet } else if (frame<600) { // wenn frame < 600 analogWrite(LEDRed,0); // LED wird abgeschaltet analogWrite(LEDBlue,map(frame,450,600,255,0)); // LED wird ausgedimmt analogWrite(LEDGreen,map(frame,450,600,0,255)); // LED wird angedimmt } else if (frame<750) { // wenn frame < 750 > grün analogWrite(LEDRed,0); // LED wird abgeschaltet analogWrite(LEDBlue,0); // LED wird abgeschaltet analogWrite(LEDGreen,255); // LED wird abgeschaltet } else if (frame<900) { // wenn frame < 900 analogWrite(LEDRed,map(frame,750,900,0,255)); // LED wird angedimmt analogWrite(LEDBlue,0); // LED wird abgeschaltet analogWrite(LEDGreen,map(frame,750,900,255,0)); // LED wird ausgedimmt } delay(10); // kurze Pause } } 000077500000000000000000000000001250202676700336415ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/PingPongPingPong.ino000066400000000000000000000222321250202676700360720ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/PingPong/* Ping Pong Spiel LED-Matrix und zwei Potis für ein Pingpong Spiel Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // Pinbelegung für Arduino UNO int reihenPins[8] = {9,3,2,12,15,11,7,6}; // Anschlüsse der Reihenpins am Arduino int spaltenPins[8] = {13,8,17,10,5,16,4,14}; // Anschlüsse der Spaltenpins am Arduino // Pinbelegung für Arduino MEGA // int reihenPins[8] = {9,3,2,12,55,11,7,6}; // Anschlüsse der Reihenpins am Arduino // int spaltenPins[8] = {13,8,57,10,5,56,4,54}; // Anschlüsse der Spaltenpins am Arduino int pot1Pin=18; // Pin an dem das Potentiometer von Spieler 1 angeschlossen ist int pot2Pin=19; // Pin an dem das Potentiometer von Spieler 2 angeschlossen ist int image[8][8]={ // Bild, das auf der Matrix gezeigt wird. 1 = LED an, 0 = LED aus {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; int death[8][8]={ // Alles an {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1} }; int death2[8][8]={ // Totenkopf {0,1,1,1,1,1,0,0}, {1,1,1,1,1,1,1,0}, {1,0,0,1,0,0,1,0}, {1,1,1,1,1,1,1,0}, {0,1,1,1,1,1,0,0}, {0,1,0,1,0,1,0,0}, {0,1,0,1,0,1,0,0}, {0,0,0,0,0,0,0,0} }; int blank[8][8]={ // alles aus {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; long theTimer; // Timervariable int gameState=0; // speichert den Spielmodus int animations=300; // speichert die Dauer der Zwischenbilder float ballXSpeed = 1; // speichert die Beschleunigung in X-Richtung float ballXPosition=4; // speichert die Ballposition als reale Zahl float ballYSpeed = 0; // speichert die Beschleunigung in Y-Richtung float ballYPosition=4; // speichert die Ballposition als reale Zahl int imageYPosition; // speichert die Ballposition als ganze Zahl int imageXPosition; // speichert die Ballposition als ganze Zahl int player1Position=3; // speichert die Paddel Position von Player1 int player2Position=3; // speichert die Paddel Position von Player2 int gameSpeed; // speichert die aktuelle Spielgeschwindigkeit void setup(){ for (int i=0; i<8; i++){ // Alle Pins werden als OUTPUT deklariert pinMode(reihenPins[i],OUTPUT); pinMode(spaltenPins[i],OUTPUT); } } void draw(){ for (int y=0; y<8; y++){ // zeilenweise werden for (int x=0; x<8; x++){ // von links nach rechts alle Einträge des Arrays geprüft if (image[x][y]==1){ // ist der Eintrag = 1 digitalWrite(spaltenPins[x],HIGH); // wird der Spaltenpin eingeschalten } else { // sonst digitalWrite(spaltenPins[x],LOW); // abgeschalten } } digitalWrite(reihenPins[y],LOW); // nun wird der Reihenpin auf LOW geschalten (da es die Kathode der LED betrifft bedeutet LOW eingeschalten: LOW = GND) delayMicroseconds(1000); // das Programm hällt 1000 Mikrosekunden an digitalWrite(reihenPins[y],HIGH); // danach wird der Reihenpin wieder auf HIGH (in diesem Fall also abge-) schalten } } void update(){ switch (gameState) { // in welchem Modus befindet sich das Programm case 0: // neues Spiel memcpy(image,blank,sizeof(blank)); // Bildschirm wird gelöscht gameSpeed=300; // Spieltempo wird festgelegt ballXPosition=3; // festlegen der Ballposition ballYPosition=3; // festlegen der Ballposition ballYSpeed=0; // Ball fliegt am Anfang gerade if (random(0,2)>0){ // per Zufall nach Links oder Rechts ballXSpeed=1; } else { ballXSpeed=-1; } theTimer=millis(); gameState=1; break; case 1: // Spiel aktiv image[player1Position][0]=0; // Paddel Player 1 alte Position löschen image[player1Position+1][0]=0; // Paddel Player 1 alte Position löschen image[player2Position][7]=0; // Paddel Player 2 alte Position löschen image[player2Position+1][7]=0; // Paddel Player 2 alte Position löschen player1Position=map(analogRead(pot1Pin),0,1023,0,6); // liest die Position von Spieler 1 aus player2Position=map(analogRead(pot2Pin),0,1023,0,6); // liest die Position von Spieler 2 aus image[player1Position][0]=1; // Paddel Player 1 darstellen image[player1Position+1][0]=1; // Paddel Player 1 darstellen image[player2Position][7]=1; // Paddel Player 2 darstellen image[player2Position+1][7]=1; // Paddel Player 2 darstellen if (millis()>theTimer+gameSpeed){ // timer für Spielgeschwindigkeit if (gameSpeed>50) gameSpeed-=3; // spiel wird beschleunigt theTimer=millis(); // neuer Timer wird gesetzt image[imageYPosition][imageXPosition]=0; // alte Position wird überschrieben ballXPosition+=ballXSpeed; // Update der Position ballYPosition+=ballYSpeed; // Update der Position if (ballYPosition>=7) ballYSpeed*=-1; // Koolision unterer Rand if (ballYPosition<=0) ballYSpeed*=-1; // Koolision oberer Rand ballYPosition=constrain(ballYPosition,0,7); // verhindert, dass Werte kleiner 0 oder größer 7 erreicht werden ballXPosition=constrain(ballXPosition,0,7); // verhindert, dass Werte kleiner 0 oder größer 7 erreicht werden imageYPosition=round(ballYPosition); imageXPosition=round(ballXPosition); if ((ballXPosition>=6)&&(image[imageYPosition][7]==1)) { // wenn der Ball den Rand erreicht und das Paddel trifft ballXSpeed*=-1; // Ball wird reflektiert ballYSpeed=random(-2,3); // Abprallwinkel bekommt Zufallskomponente } if ((ballXPosition<=1)&&(image[imageYPosition][0]==1)) { // wenn der Ball den Rand erreicht und das Paddel trifft ballXSpeed*=-1; // Ball wird reflektiert ballYSpeed=random(-2,3); // Abprallwinkel bekommt Zufallskomponente } if (ballXPosition>=7){ // Ball im Aus gameState=2; // Spiel verloren Modus wird aktiviert theTimer=millis(); // neuer Timer wird gesetzt } if (ballXPosition<=0){ // Ball im Aus gameState=2; // Spiel verloren Modus wird aktiviert theTimer=millis(); // neuer Timer wird gesetzt } image[imageYPosition][imageXPosition]=1; // neue Position wird eingeschalten } break; case 2: // Spiel verloren, kurze Nachleuchtzeit if (millis()>theTimer+gameSpeed){ theTimer=millis(); gameState=3; // Spiel verloren Anzeigemodus aufrufen } break; case 3: // Spiel verloren Anzeigemodus memcpy(image,death,sizeof(death)); // Spiel verloren Bild wird aufgerufen, memcpy ist eine Funktion, die ein Array einem anderen Array gleich setzt if (millis()>theTimer+animations){ // Wartzeit gameState=0; // Spiel starten von vorn } break; } } void loop(){ update(); // alle Berechnungen sind in der update-Methode draw(); // Darstellung ist in der draw-Methode } 000077500000000000000000000000001250202676700347565ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/PotentiometerPotentiometer.ino000066400000000000000000000017131250202676700403250ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Potentiometer/* Potentiometer zwei LEDs werden mit einem Potentiometer gesteuert Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int ledGreen = 6; // LED Pin wird deklariert int ledRed = 5; // LED Pin wird deklariert int potPin = 0; // Potentiometer wird deklariert void setup(){ // werder analoge Ein- noch Ausgaben müssen im Setup initialisiert werden } void loop(){ int value = analogRead(potPin); // die Variable value speichert den Wert des Potentiometers int redValue = map(value,0,1023,0,255); // diser wird mit der Map-Funktion umgerechnet - hier von 0 bis 255, int greenValue = map(value,0,1023,255,0); // hier von 255 - 0 analogWrite(ledRed,redValue); // die umgerechneten Werte analogWrite(ledGreen,greenValue); // werden an beide LEDs gesendet } 000077500000000000000000000000001250202676700332165ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/ServoServo.ino000066400000000000000000000016161250202676700350270ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Servo/* Servo ein Potentiometer steuert die Position eines Servos Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ #include // einbinden der Servo Bibliothek (library) Servo myservo; // erzeugt ein Servo-Objekt int potpin = 0 ; // Potentiometer-Pin wird deklariert int val; // val speichert den Wert des Potentiometers zwischen void setup() { myservo.attach(9); // verbindet das Servoobjekt an Pin 9 } void loop() { val = analogRead(potpin); // Potentiometer-Wert wird ausgelesen val = map(val, 0, 1023, 0, 179); // und in den Wertebereich von 0 bis 179 überführt myservo.write(val); // stellt den Servo auf den Wert val delay(15); // wartet, damit sich der Servo drehen kann } 000077500000000000000000000000001250202676700344475ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/SynthesizerSynthesizer.ino000066400000000000000000000031771250202676700375150ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Synthesizer/* Synthesizer erzeugt eine Frequenzschema aus den Werten zweier Potientiometer Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int buzzerPin = 8; // deklariert den Pin des Piezos int potPin1 = 0; // Potentiometer 0 Pin int potPin2 = 1; // Potentiometer 1 Pin int toneHeight; // speichert die Tonhöhe zwischen int lfo; // speichert die Frequensgeschwindigkeit /* lfo bezeichnet einen "niederfrequenten Oszillator" - also eine zeitliche Frequenzänderung */ void setup() { pinMode(buzzerPin, OUTPUT); // buzzerPin wird als OUTPUT deklariert } void play(int myToneHeight) { // play-Methode digitalWrite(buzzerPin, HIGH); // Piezo wird angeschalten delayMicroseconds(myToneHeight); // Wartezeit wird durch toneHeight beeinflusst digitalWrite(buzzerPin, LOW); // Piezo wird abgeschalten delayMicroseconds(myToneHeight); // Wartezeit wird durch toneHeight beeinflusst } void loop() { toneHeight=analogRead(potPin1); // Tonhöhe ist Wert vom Potentiometer 1 lfo=analogRead(potPin2); // lfo ist Wert vom Potentiometer 1 for (int i = (lfo/10); i > 0; i--) { // Tonhöhe steigend in Abhängigkeit des lfo Wertes play(toneHeight); } delayMicroseconds(lfo); // Pause for (int i = 0; i < lfo/10; i++) { // Tonhöhe sinkend in Abhängigkeit des lfo Wertes play(toneHeight); } } 000077500000000000000000000000001250202676700336465ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_1Uebung1_1.ino000066400000000000000000000023631250202676700361070ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_1/* Übung 1_1 Blink Rhythmus Dieses programm lässt eine LED in einem Rhythmus blinken. Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // ganzzahlige Variable led wird deklariert void setup() { // die setup()-Methode wird einmal ausgeführt pinMode(led, OUTPUT); } void loop() { // die loop()-Methode wird immer wiederholt digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(1000); // hält das Programm für 1000 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(1000); // hält das Programm für 1000 Millisekunden an } 000077500000000000000000000000001250202676700340105ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_2aUebung1_2a.ino000066400000000000000000000055761250202676700364240ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_2a/* Übung 1_2 Blink SOS Blinkt ein SOS Signal: * kurz-kurz-kurz = S * lang-lang-lang = O * kurz-kurz-kurz = S Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // ganzzahlige Variable led wird deklariert void setup() { // die setup()-Methode wird einmal ausgeführt pinMode(led, OUTPUT); } void loop() { // die loop()-Methode wird immer wiederholt digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(500); // hält das Programm für 500 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, HIGH); // schaltet die LED ein delay(200); // hält das Programm für 200 Millisekunden an digitalWrite(led, LOW); // schaltet die LED ab delay(2000); // hält das Programm für 2000 Millisekunden an } 000077500000000000000000000000001250202676700340115ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_2bUebung1_2b.ino000066400000000000000000000026001250202676700364070ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung1_2b/* Übung 1_2b Blink SOS alternativer Weg Blinkt ein SOS Signal: * kurz-kurz-kurz = S * lang-lang-lang = O * kurz-kurz-kurz = S Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // ganzzahlige Variable led wird deklariert char signals[] = {'.','.','.','-','-','-','.','.','.'}; // variable speichert die Signale: . = kurz, - = lang void setup() { // die setup()-Methode wird einmal ausgeführt pinMode(led, OUTPUT); } void loop() { // die loop()-Methode wird immer wiederholt for (int i=0; i=1; i=i-1){ // Lauflicht her digitalWrite(pins[i], HIGH); // LED an der Stelle i einschalten digitalWrite(pins[7-i], HIGH); // LED an der Stelle 7-i einschalten delay(100); // hält das Programm für 100 Millisekunden an digitalWrite(pins[i], LOW); // LED an der Stelle i ausschalten digitalWrite(pins[7-i], LOW); // LED an der Stelle 7-i ausschalten } } 000077500000000000000000000000001250202676700336505ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung3_1Uebung3_1.ino000066400000000000000000000036501250202676700361130ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung3_1/* Matrix Übung LED-Matrix zeigt ein anderes Bild Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // Pinbelegung für Arduino UNO int reihenPins[8] = {9,3,2,12,15,11,7,6}; // Anschlüsse der Reihenpins am Arduino int spaltenPins[8] = {13,8,17,10,5,16,4,14}; // Anschlüsse der Spaltenpins am Arduino // Pinbelegung für Arduino MEGA // int reihenPins[8] = {9,3,2,12,55,11,7,6}; // Anschlüsse der Reihenpins am Arduino // int spaltenPins[8] = {13,8,57,10,5,56,4,54}; // Anschlüsse der Spaltenpins am Arduino int image[8][8]={ // Bild, das auf der Matrix gezeigt wird. 1 = LED an, 0 = LED aus {0,0,1,1,0,1,1,0}, {0,1,0,0,1,0,0,1}, {0,1,0,0,0,0,0,1}, {0,0,1,0,0,0,1,0}, {0,0,0,1,0,1,0,0}, {0,0,0,0,1,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; void setup(){ for (int i=0; i<8; i++){ // Alle Pins werden als OUTPUT declariert pinMode(reihenPins[i],OUTPUT); pinMode(spaltenPins[i],OUTPUT); } } void loop(){ for (int y=0; y<8; y++){ // zeilenweise werden for (int x=0; x<8; x++){ // von links nach rechts alle Einträge des Arrays geprüft if (image[x][y]==1){ // ist der Eintrag = 1 digitalWrite(spaltenPins[x],HIGH); // wird der Spaltenpin eingeschalten } else { // sonst digitalWrite(spaltenPins[x],LOW); // abgeschalten } } digitalWrite(reihenPins[y],LOW); // nun wird der Reihenpin auf LOW geschalten (da es die Kathode der LED betrifft bedeutet LOW eingeschalten: LOW = GND) delayMicroseconds(100); // das Programm hällt 100 Mikrosekunden an digitalWrite(reihenPins[y],HIGH); // danach wird der Reihenpin wieder auf HIGH (in diesem Fall also abge-) schalten } } 000077500000000000000000000000001250202676700336515ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung3_2Uebung3_2.ino000066400000000000000000000053741250202676700361220ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Uebung3_2/* Matrix Übung LED-Matrix zeigt eine kleine Animation Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // Pinbelegung für Arduino UNO int reihenPins[8] = {9,3,2,12,15,11,7,6}; // Anschlüsse der Reihenpins am Arduino int spaltenPins[8] = {13,8,17,10,5,16,4,14}; // Anschlüsse der Spaltenpins am Arduino // Pinbelegung für Arduino MEGA // int reihenPins[8] = {9,3,2,12,55,11,7,6}; // Anschlüsse der Reihenpins am Arduino // int spaltenPins[8] = {13,8,57,10,5,56,4,54}; // Anschlüsse der Spaltenpins am Arduino int imageNr=0; // welches Bild wird gerade angezeigt long timer=0; // Timervariable int timeOut=200; // wie lange soll jedes Bild angezeigt werden (ms) int image[2][8][8]={{ // erstes Bild, das auf der Matrix gezeigt wird {0,1,0,0,0,0,1,0}, {1,1,1,0,0,1,1,1}, {0,1,0,0,0,0,1,0}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} },{ // zweites Bild, das auf der Matrix gezeigt wird {1,0,1,0,0,1,0,1}, {0,1,0,0,0,0,1,0}, {1,0,1,0,0,1,0,1}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} } }; void setup(){ for (int i=0; i<8; i++){ // Alle Pins werden als OUTPUT deklariert pinMode(reihenPins[i],OUTPUT); pinMode(spaltenPins[i],OUTPUT); } } void loop(){ if (timer+timeOut= 0; leuchtwert--) { // fadeValue wird in Fünferschritten runtergezählt analogWrite(led1Pin, leuchtwert); // und als analoger Wert an die LED übertragen analogWrite(led2Pin, 255-leuchtwert); // 255-leuchtwert erzeugt genau das umgekehrte Verhalten delay(2); // kurze Wartezeit } } 000077500000000000000000000000001250202676700340435ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/WahrsagerWahrsager.ino000066400000000000000000000021351250202676700364760ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing Creator Kit/Wahrsager/* Wahrsager schaltet zwischen fünf LEDs um die Zukunft vorher zu sagen Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int pins[] = {8,9,10,11,12}; // Pins der einzelnen LEDs werden in einem Array gespeichert int tiltPin = 3; // Pin-Nummer des Neigungsschalters wird deklariert void setup() { for (int i=0; i<5; i=i+1){ pinMode(pins[i] , OUTPUT); // LED Pins werden als OUTPUTS deklariert } pinMode(tiltPin,INPUT); // Pin des Neigungsschalters wird als INPUT deklariert randomSeed(analogRead(0)); } void loop() { if (digitalRead(tiltPin)==HIGH){ // wenn der Tilt-Switch geöffnet ist for (int i=0; i<5; i=i+1){ // werden alle LEDs digitalWrite(pins[i],LOW); // abgeschalten } // sonst int myRandom=random(0,5); // eine zufällige LED wird ausgewählt digitalWrite(pins[myRandom],HIGH); // und angeschalten delay(20); // Programm macht eine kurze Pause } } fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/000077500000000000000000000000001250202676700301075ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Blink.fzz000066400000000000000000000241261250202676700317060ustar00rootroot00000000000000PK8Dg9\.&Blink.fz]ks7UڪN3SpjT(J$-; ~P$%zQ<5 ؍n{_>N:|<=jO^gt6ώ?8:Gc\|z!X熧{d՞iUK=zq>8eP H>8rhp4{K;qٽN>u:}_9bl8>?vNLg>~ 8jwPjCR~ņ^sCT.ƣKO:gۃhpi:dz黳×4?os<cq&]:fIbQ~6=f4Բ܁dt:X~ԼM-k[nY؛7u4:/xƆ7dTۜN QYꗨ&O_FyTKeLjRm-xQYϒZTket۟x۽Tc4p!vNH}:GVlԏ.GgxXzGFVh-O0u)z0y2:K+"mxeh@j6L9zǣh11Jgn%i]u~j|p+ql4s:u)j#_>k.OFTAlƸ`q?Tû)Zލ!m26AFkh>Z$ӓLժ#2އ>,*,os4=[+u89ί؃+F4N(N}6o)xnp] M2Dwsz{9doR}!z;Uy#+"8[Ft\%'TXfdFᎴ0=N)˞pa/{7* ۶;1٢s`45?vFaOVo:on'Gx{k|3 ptF|dle_OUtS*Ge6O͆y?aIⵙg&ӽ2m؁nz֛$KzAFGao8 U0 ) ]S݇($V⿽0S#a Kx J*DŽUb\N@mR| Teu4m]Kt9Ra#˒Hw\ٯ–E폚yޱD%-^_5kR6Gy,M‡)S$5-p$6LRDߣv\N$2}޹<o7]W2b1:|E}O;Z>2my[鱛E27FۅkQ9\_4y OS- yxwBIy46D U$xM-ANt 8̚Ӕt <ՖTbi<Қ e2Uu('*j9E>vL?i-֑p{u9D:-m _d夸 Ę0mOcjǟwvǟ]D|~ն{;m9d[w=Z3/mU}agB6Ua&fS:U|v{{>.d{pf}}}lOm ْhnGŧ?>?v?Mw4DBȁyb4)W9HK/(c J~Ϫ=0 y7O[t#3s~Ȭ٣ԓF^kUQ.?*g<>V^9*+Dkd9( ݾ&Aك!5({H=f<d˽g=d>v :m͇6ۙ~x?} o"T_)R+3$K6TGAJ~&7pi<ߟO<otV^Y5g3Nf^zZdt8RtiT~u.]׻eڭKO?LZ 'h>ŻQJt|:fǗ/~_eo;xCGd߾|qX^x8NJT1^ԏ7w8b>5ednt=]4݇ly/;|n<9?v:EPL?߻OVQuS7y>?DZJGRx`ukevI鿙 tD'؎Ui_ƿ?eT~Ry|0_m`2*OZQ;kZuΣɌfZޝ$x|8.W\STe5Gp(th<_ҞQ 1,]N"1d ZvEA̖]ve,גBU30ΝmsBEĒ e,{ >p񰖩mt:tڣRT>uK94pt\,'Tt!|P:cҸ{pxUԹ4Lh̀Ʉ.Xh\:ص4.Z/cg9'&6tȍwdQ& ^w#T2SPmY$r$(u3NTFdݥDW]En˖Kt+Չg?b*jo]jB.AKW, ?2HeSDIPobRAw Hd4T `,,0Ԥu(?\(ԭK t ErgDuL p{L =/Yb*`"h=N[ 0r5TUhm8AO."56 NWI݄`$P/xZHݲep Nh]LU`$ژHo*YCg- P/(ʺ\Z9w9kE}giR!Y iyȌЁ\ҐdıACJ %lJdE>Ij9̓ 0tݕBq~_F(RHҖ]hLT`X8X6 `/kTC-jqomڑ''A.ӴIpi ɍD'a=QwpV( %0@jIc_FɸJ'g w}Kӯ"'ėj$wBoAؗ,j$:e'IjјFzhEٲl]IoJg >yccP1u)(I~L]5F'ċ00 59DEc%O uK@*x0PIi ,nLƼSnM5,Xphsmj7Ԯ\Cde2rcv&Kn+%M>]B^Z B[b^!L+!E+h ' ~<-Kl?%J(-0'P&YIUclrU^vzp i6-FcF6^(5\A *W6ؖ+P-W [@fg$V # -#$ $\&5*^f^%Ҡlj::r0K6`yAlvʠ> EIe0^u9J }޽fj!XmYz+[^Dj2F1 7/guɬo !bD6Ph&,kRX.`젬o{3d6k _g"rfS*r8ui!CD $VdG=GT 6ѥ+oouѩH|KD-"W5"j$ ۊhK?n GC^$YqmKf0A d@H(E,p'0AL3UޞH7Q6Μ.鲖)b !9bYcH{<~:YD6${; ؑ\4gIA'"J.d:Sf<$q@⯠ÿ5 O#?(YnP!$*24`ue$(0a9<̞aF5:ﭣgVPQN!ƕ!A$ -(ADu0Ff@q bJ7:; ] ,5C<uybN33)+QF1N$3^܍9nIJy\߅9ZI =-t.y 4f[mhIH:C*jf22%7rj6R$D!U 6"~Pru@MW`t^QȜL.I ݦ3~L8Q'wSFhH 0Kǰ36Id]*v$2٫`"YPٻf/Fмn~y%}/=\P%3{6=1M nˑY\>(&=stnlQ/-R0A¨e,8G,s~1`&:U˭f9)@SyE4eku*^qQ&" OA3஖D]'W`[k=-&mdaW/h XV0$g-yoCXc;O@4tʹi"eF2jܤhݭH9DQY46oB$I6D#*kT0b䍫p:^h'՘ H RQE *"@h G&w9K$͉̜#Y|dk0тrPEТp3w\G9QF0PAC7riz\N‚zBq}p1:;1#JKDR9,v?6IRTMgU"mm%Z+Q<Mj T`GOjWzPIXokҏhql-?&яH Ǹ##~cְlُ-7F-ƋqwIM$#X!]W5E>,1&_{*Ew긲RhV4UU,8zq&xf rVn^\y>"4-y9g0Bbi[>&aHk\<$`(rAWwVJyK(!Gd& Iq-edK0-=2LWHCШK85ůV'ѭf v6;k̄ˈ!unhhhݤQ5Gai RɯعK}hiN&~PjT2[N)F+R)4?<|s3Gj7LL7nĪ.ZJQ Z62~)EvETě X^CpO2S-Fs 7瓧-.Wڥ)jšve*3m1j.5df-kZu̴0\*;(Tp:wz5[SrFi:]uԵ:*[5XEci:-{^cPFN5BU% %TPu-#\8Zp沶I j//LTPAᾑ rb0˭4czB#ucL=qK"yDfyUoR((lTLP9(G?drΙpnܭFM݅*WJJ,*@&|k<&mZkč4ik3p)#- 2|Wp D[tQ>8k:ef)%5 oɆ5,DɺF:\PBmnStI,l(skibUvq`c&=X+ 1)OɒfLwf|*+0%ܨ+YdfVYzn͗(۫JV>T&|ʟ._"%QyCq{sTP0^dˀ[B7FѤGawZF/$Q͵lѴmVcM--ږ-6e[4-IRс-ܒm7ݶm"jkZ.ܲ2`|"fR]qQmHsHɭոhpe8 ƜnsSk^+~vno!Stmj,UFWRq"kTQ,\3^2::[( 6(YQF\j"noHy9I((6i>F"f:Ecֶ%ږd [\~Өvhq@QL@Guk<%f.FynrB>s\ks9FV;L,<mG'i.A秭0`9cofM(Lw1BVu4گUW]u9MrWτ5V)}[l>cs.3G;K:#"ꕙ죬<.)]p%u7?Ŕ$)E(T5 yT2`.x冰#\OՁk_5jGW;~_*}2X]ޞ&ukbgAzX~S/ֹx|6kd 8+JM׿Z~%6[Wwޭ^:'ҹQ? ^:W`7u0n^N$>7gS&7zέ}!j7tްza|k^˗ɷUn^o e*TZ5-~*x?}|qVr_>iV6\9+:RoiW){xeMt<._'ӽc'Y>y:>X])[f>ݷY%t~ .׷}-á =o3<{1)bշethyw]n/u|wL)V z G\PqyiOM7-LRanNWhiE{Tv|F\/m{H车ϫ}={[4s GL4v|B⫒[4sh6o>],}e+S-Y3Rpܵ=^Aآk@_]/̋]7;Gw- [_v㭻IQؗOIL] 2'{~+=ҩY/vm/E^O'}]_h\M@JdzkO|ZjQt'2, e7a K{Md.wAӢ7mL"WFoezooy?zό~A}fci*}:lT>+!h9P{dkMҵ;#ZJM|Z_8] TC$=µk01 nMʴ})s8Dϟ]v |kĺTE\,?PK8DGrX Blink.inoQN1So/sd-i 0sziҤ3"wI#@)|.-0i 4 bJС>Sx䏤#(B,lJ(\vB A;] }GBz>=9whUgzxG/G?s1ΒL|rt[7'[_tNGzGӗ&uN3:;J#9E+-zq>̇gطe8vhtX. WR;ʇޑxko2\ O⥳|/b{6.O7 /ᙗ(sVis9beG~AJ}M/wEÊÉtx{8χG$wAp8d>Mf8yu>Ad^d *~ξ'`Cl~~mYҿ՚з ״ߍofx:;]u>^ z/~=~EU[UUokSu5xQϊ^'K%?=:#1;>d:7qx>qz-eҷ|ZǥFy>x32=|^9j)!_- RW~?;VGW.qSsN%H>yiȔ1W|`MEv>hJڗpk| Նꛮ߶}+:5 JovJ/֔>4=|䡬z ).M_GOWuWˮVU[n2 ]xܰ-+ wى\6-~ĭe5YGOQT͈bȬvO!>5VK으ۑCzJ55NI޺;ih85ľ8nB;Ae;)S]3N[Ǔ%Q_xme>+cd|>P_\&SAR7Gw2s^R6r$?g6@Bw6oU `~j^ nølnsdFCU,IdX`Ӷ'ofvf֐V/blQa5K3{: +RiR\nvO.s9^^&EG :e@,‚P?gudqG +Gk\U0w;MRB_?/ν@Vl`7]_3(֬ܘjo5[TwcnATc*UbzcKZ1O+}V5,5c}p=;Aan78;ms7nA-ܡ+ܬ}mKvWvLM+vL{3Bw]:7_:?=9ɧ|.g/}.ϸ47v&ys_.)Cd~i)퐕K=Ŵ*,<|jv GbpcӿHr;;Plg}YSո~ gq3K3&͌z!=bPgqS¥g =sbNmJMghmsRa%R#W|K?ةdS8nXlzp6g;+^A\-'D*yЩT;F o"EMgt n#Qv <;_tOpo~_|qrܞߚŴԬ>oxiVT]@詽/uS&Kq[S,[u޽'5BZ\Qy*w>wڭߏ)SDV.iHOle7e;$Ƒ].tvPtdol4y6|-٨AT2)4XIx'G#'eRdd"pϮgn0S!ST*)ϴ<+ ՛xlqkxj,F,Ɋб!4 LS[(;cgCQ.쌢}aHGQw" ӧ$4s}~Hr`|T"i6se{G'A[>UzVגHw~-+ΖY\z #Ik3kGZiy^ܖM,,,q^JȸTJpItw,mGgG:C,?El-;aPqSZ,5j5qhZ `)R\|')n)EH>$ED<&mSn@ICv}tf_'g<)kn-3?󔙈җB: zcʛ۹ -XM-+E\$d4ql7xʤupJ +ZBF5Knq㋞=m 1] GGv|NԞ+Z,Ji+C뮡UG'bĝZX\nҰ$ X^&+Xr(Xڵ!V?w43Jhcm;@+铐 hM6g&Mu.hIƕ cG!ѵMywe+ФîKۀIGZ!]%~|k F: jkLy+qB̞)[(\%ymZkm}/˫60$>r.ͦ[*fUs_kk!tm(e#etm5$_e(0b<%s,NAFS׃|1lO xy<=i88?:+@=IgҗzY .zɅ^X*o շZ• ĶlN/bM_Rݨlt?!x:g{,.]dΟ(jVv|TLY|G[U̎?{|ӫU⋴Ln&u\9@]fSٻJW +OI7>L:ښ/sv|o)g lޕ+eX'KOc[n0Cu.Ìfu3#u{ݞ'_6{ S:B}}I0:}2L\z+y!]baΈcs-{TiܾR g@ґkT]ʗUutґI7+ښn=s).5ZrYrkTkmjc3޽_C""Rz7Qtjʨ+ܢ -D]BdPh?qIv&{[m#J7 )70*jNj=Di'D>-7Brkt@l]ttm5%_]{;;\nln/FL3[mH˖w?{|-O˛'$xi>>9]V{Ն |8'glÇ'yzz T:OX^fNJ]y= ﷳ?x ;鍏bxb4ՂT2WxdOD'xfer<~&^ NzǀSg㣣I/M I<»<^;/{|z_#tGx.3z%PTql )GԒTBYMm8j/ ƅi+HØ0:`.hĨLu%P*W1P+7+M t}.|\(B#fE[E!2@(& Ud ~d\;P5٧A[8Z.(X}J(G:T Gb#W ֮ 10$=]֚ȔPUQZrCh6\`2uPQ]]^ |sW"yzżDW!ͅa( 4XD5v5)4TףC5ټ_OC٥ 򁃦Rtb%vi檺Hqp#1j +]ݡ''UBe}hz S2FȢC)+6WF񿤴Qy{cfI@J " ѶQ}iEiñSAFIA/+hH}D0BͲF&&)tFgFXhb`h!Q1FW"b] =҇(&»o.H,5KD.rC% 4ǧܨ7Íz's%ܐ6pb>6W8cch5vŸ㕏}chIz![im@*2.Dnr!o=dLB_ E&a [qEqSA\& 7H a ])L1p.S|",-Y4w+8KQ {o dA4&Lby!D#`1ƒ9C[wЯ+v8D{"[=1=HDkG蕦x*~b1OSSHDTvo4BX&0$Rd{P@QA1&( F!CS5y,#B5+EXfߤ nr4`BV#b(0j` %FQzHI~W Ga tEkF^*aMȰ8¼,)"ӼI-]dc|=Kac(Ed1_],TH,ĀRB3`'U>4ٔ S0WF\j]O_8n "t::k ^&c=(>tR{HoNo MSHy+DLs"VSb8+*@A(j-J o%{)k ^_|u;G&J7V X͉Ԕ4d;.O?,fUK!|=!{Kr1q;i+R%UjJŁv Qc!*8lI ΄cC f\i55ƚ̵cƚEK墡P^k[j2Z|iPJFTB&&TlPeMxNLc.E83Q[& R(R{D o2֍dmeq5,7˜bГ4RV$"B8LmsQ,(# ")v"9ǀ#6#j5*RM(r]pۺ ,U:Zx49\b CSF/2Lb+}zT9GwU2cV,BWL50YɚJ:dIor8yN 3+1K׎=9y'J?XH8rA%~P 5)o f4Dq"5BXPD*Ŋ(2FTY| C~[Y@XW}M3Y%}P!|YU.X)cC#7)+ao5iپ.ab)v/X"9̬AboaaN7aFq'׻Fn;7Da f&q+)b$jTR,3_3^"::kRp\lPp~cٚ~q~+DIXIiDxXe$0,b `RWrf1GԫU@ðTH`<\ x2ܵ(#'5U`E1gI*;Y6e5BNEˢWM 9$)(rm+5 10 wiodE(Hw!1M a/CW~}լϺ"E|㬫-=yhx<)wNHBYJz&DnDH(r{I1اcaaܰp[L"GU`AddJ|Ŕ_ܓrDd*8l"p(X#z[ǫ-zqi/ߗdPp:\_Odp\\/6x 04<{'5ovd<N#wXߙuoV$Zް6׷ty3vcgm絵a6K¾1 z7gE 4+/?MtR<xz__8ս_h_Mx*+::4s͇ ^,t:[VzCUG8)r06}wƱGu-xxV8D y" +l,tpخL𔍻..ݹ§ k>D#dd'h#͠J\e+uDZLoxSPgȔ4 i (#l!wܦD.HB7vuNnoYKPBShB0~Xt[do,2OZn M#>-:RBaGG["%,oMԮࣣd㫷Qc= 7:<>xtsd@X\]YLTT βܗxٞ5,$i\v|rFz5{=>ľ=o %l 5Ҙ%nx)G&O؃Κ7'qm~L t3f+k<=W9~!%"u>KVz$@=>tmGeRjَ?j47 kuHӎfM ѴɳiՉPDPK8DG br Fading.inoN1}GcBD֕^fntHm| wI3wιkFR 6{hir'KH`dp'{&GnΤSJ,ET%+G?TͳISE'&C\ '˶5[iibG>[e>*J*'7BI%^`ÞfPUd Q]U[ie[M=`jݭnSU@Me2SnRDz jRX'WlBcZ \ҰY'D⎕yTGaY XZO b7ڭc=޽`y FlipFlop.fz}r#95wm!GuִUe;e3'M(SpG\dɈ lkUDxOwq:sFSr&WoĜ_xu70G/w$5L MH<s^]N.SM7g}at?Iy2 Wgh6~s-|w~~uYjv͙JJ z3r)u_g :n{\!S\Sv9\ 2׊ ؀\ /YE­͇g񛳳yߧNl5^ܟŝA_P_iWh" Ӓa/-9q_'gF_7| xtsv"*~|}7O>oΗ4`:]F=O)߲9LU~:>L>8t7|M\Eϓ0{+b0*6ջ~sv4~8[^ոz)Z_ւWEe>4^7 4ꊘ+ͯ(eȡʜ/WO>\V/ju WB-/A-hB9~5Wn^ @--q3 g{_[tABg Q [tYĄefǓd}1zvF?q[{wQ {^\4$Z"eRve}ZNnc@[ʎ(=1V}bݪK%jәϷKOCVbL4':e오O8-Ir%Mg~\g}Z濜bn~c>f$}™͎IӚ[ Z<|]]ir:>df}©.JBZbvLЧv8vy")g/'Izm޲e[.|R/*oQW g.;']vM֧eC)/ܧ윬O89Yps><rVe2Mvp6>-"QgvRާO8MyXluyΉ\N6O8I>f0MYpnc^/u7q8|x )ݼbk]lMua-&ZvtYJwO}/L*qDI qf3fh 32̩n~.Yop1>N԰*~ W S(5x ֦ojR/{nr,5aa$_lݫB0ˊTR˱s+U׫ _cwxWi),ЯLA4m 4Q"T#f ,ҔR?&kf.R<,(D|b@R 1w rl;Enm4 xf~VcбQ{c H:@U 4LN7)xXT%D:`dzP\==QjRÑnJrPRAɩz*1)kt*\4L e,KHFWRB% rO5x4Bmhѩ4УƐ߆ջ$} ϯgzf)ʳxx{p+B'߆UT>ǩFA{Mͫ7wV"!HHXIaZO'w;m{G- @xcP,],⮔ϛ2'kp)ڟg<5 X(fE*Œ+w7dt?.d+HXʈw hʺSȚ]=ogT][w+N]9`ecq>--< ?gT~xki4}2&Q}o$482dށ (,cѩ{pW#){tt9Y6=IÅN'grr9Ʀφf&w=mU"WJj4}pϽ߇/Yyf|+s0(c' 챵4icܚ2RsKeaMր;gYUYr`S,Y$cLZ˟I٘|ׂy*He*۽e[bV.k֎6!ww`l$G%I A$W [X 6Ck*,U,]>wqp*R a3\Z[S. '~KpBc09J w?Qߪflmaa[/~̯qWE)hM=kQl1kqv*H¹^ TlY_lSL8R6v53 KR W_7N)"YzC "o0?)bQJ Q2m)\JR9cqtd>H)KBkJ4҄פobCʞJHb͉vC1 qn ֽ$ ,X]c)'0uU,b\]]”Sxpy3tBKP9A[eř~a?Yw-G洛lf?y1)[~5Hz {$/B_0`8==ؾ?61rlȾC@78Cb$F{.RL8^:3Jw1o]# $Gޯ #ŀJ"pe/pR%ss7[j~m 4 X)[<}m1 <±=N}!d hZMt81eI//-y.XR `y̅7` ߢ#5{xRŽ1w v<;vc43uLQmHv1!@H;xj*BqZR-׬UsUre\'=S3֩_XISV2P".D) [BHEHE_:2~&l_l6On'/yze[={]Wt{a0W:V&Xds8d7rs*T闱r: 7ؘ: ų7x ɳ8tFN- gHIoڍN ˎHU<*J.&84q[^gs楉\㱄8BCƮd9yFl3: b# %sg G#&XJ4[m*ȘSڃ˿HS-On+؝4b`ZT#q²Vw'NT&nPpt^t@s*:qckiM8s;nP}Lb-/F;"T`B46駅m'j03XێnF,19vd)kR'* ̘˚}2c+̏Hs]n MJ>(l(3aa GIj+qql>/Aqd6UoXx}|PcYkN>% 9x#̻(2o3$+}:4xa1HC#Kڠ4ԑi(YܚTQY$%KbtDTR9aewÚa%\rڅ5ܚ6d6܅i~* t.$M,9f)a)waDíTR3o3\e 6[7q[L7ur`±M81<*3#22rwo#,OlN-Dvx!`9ŰD8v:5Z6L Y\ ٜ-9c}`>4GmϺpɄ16jE "L$qǗHSU&Dnh)[G|bq[G!oJXO/LjJ$O)N?E`] <ɺbvB$jDUH<9ZXb9bS3%;sX5s5@®4M12Mõ' $ =0 ],8+(*h W>bkNnYU'],MfF(REw&e'b-. kሻr{O}"-k{+M__3(| "RH=;hk!& E`Ecz9+(Ke s#+[/Eay̬g$ؤ ;"A x3A]9RBzE*)B1EVf7(Ψ+78YvqoYit֞Д0VHNn\'G:54uwa-o(h<աblQ\^eu[4ClJe*fVG r6\N&Fc#g-3" +j&4LHܬ!jtf]#73LBRKhX4Y7%r& rݐ˚˚r^&>xhʊ  ]0?nN%#󆇪zidzh{kA=z $ XCQy GcDY#ҰCF` BG<ĬJ^V@LEY"4uj2F>К:XCCZ%Y! WFS ]ɚkИ YSsbKNLL^&>ѕoHlxؖ TgjY.ʴ{0r4<8D B^$G<xs mscCs%M)t=2[2#p0:m"ljit:&U/w挧֯=-RLju9~='P&+<ڣ i W F&4xb'4{K"n G^*n!g.6"xW[s` yI{ cwgleƆ0?Ⱥvn+m5ˠᩌD4WQ+؟:ʼn| Z+9_[ ,$i,w<iRb։wv@w~Dk,# bF%Tp ~ ߩ-x <^PƳp%<"G0ޝ'-82٥G??% && 0R9Teh/긅<9׀"q ?Asз4LEƏb~B_,i]} j?L[wc}!Aנ{Ϳ@=eVjs_4Z ϢB4+C6Ly ]A|LaL)^-KK/P̘k7"GW丮DD+ef|7Y׋D ̂B4UX**KU³iA 2p+Ml$ t]{3lH@ nqy{1t9rE~1`w Q}IE^ɱ46>4qJbK6a]^oLgb @ x,x7QP7`5FK^j+~a58,RxsP3=BA@(tp/]7 ^JrF%<nk?pڔMEŜ\ٵqhɵ ~kh;}y׮ҔvUXm&/3!?{`01*,@A0,~+# ‹KY$c"+)΅6QOFuM qǂb 0O@_q'w7?;x AaGS2eF<Yx4XI)-%@՘Y2d h` -ޫ((K) BtjtDU~1Vwbq8څTh_2a#ط Kyج^!͜xpe 3x [xGK`Inh]AЭ~i#-zMSۧy;RMnOjeX a:2p P(:,h Z]f!WI3g}̗RqRqBCJ3Tf]q#ÀkOBB#bhcYMh<| p  n/AbY zݳ  FL*;ToPX"`l( MC a)I0OE`uMBkVA]Y{ ?V/ Фc~T:2"ܢWĞW */-*EE_Ń1Cd!'Z9h'ObM0 DI12 @T4`xThB%Qv>`{R! C'uG~m%G(h2h0 Q]SB]G V/tt ю@zU'yx>`LN 1x 2ypUPiNhTH2h *a`V) o w[ʼ6 <O3ovvYpt$e82 <)oE `"g$ }Lq2yHT$yCkD A-Y`@[˩0PY0Q E h+H>8 ?A?/X9`nϠń(#e@1 /RJ #} 40Dx\BHVjx&h=|y{ѧ#c(GA;T#h(G4d$pJpFmA 4ǼCzSѶ鈐cl84=` Z:>Eѕa}.Wb4) DW*YʂF04RLIP7l {~x ㎡Cgf%̓!jX!^\,ƮXÒM26MH @Ȫ8/}Џ[t%b %`!<İI $`@r'Ȳ4K)â$sc&p"/V ".1E'G$ A  AFmMh.2KR D(;ƝHY !zBcq>IG J=x `v)C^nD2162qZh8ϩ -~DBc0  lc_plH&e~]Й%@%9u)i>'9vo:ZHغ$g9V䬋!0eY$Ҕ} bN/ F,obFcW8(r'xEB*(;ua $ (`x59HrfrœŐȻf>[{vg:nd9j 5# 0D)' bCN탫?a,:?}G䕢agA4 Mj~h` 5 B rLx$}lDv5j̜1 첤+S,}H$p]C?FׇF=9gLWEK"e\DQ!!:BBvS)kw(3]Jca0*R y#avʠ' NC"A N*"^\;>N;8t11],%,f`ꅯ 0^6^ t.Isd-K?` L (%(G/?5 9 C/װ0x9;!+0G81vcdfpX``Gb gc r Dy  BEO1܂%Ƞ[1L1M24,|xuW3䞹A_R@R0qiT8Rx׈B$<&lH~rbve/ d"ǘ~6`:ΒO! *h~Q#~Q^ 8M6 .ChMCd0C`60MWvYj+̄`a #ijC bCگJ94`0 `DAxv*БY`/Fyh{ T n2lԩ gNb} 䞡ԔdAD4nX^[!zE |7xA/蔉.`! E}Y~g Sbpg)PxtA;1,N朏 ,{A5 J'xhC19"LH=\hkWIf @4OQD,3׃@q@shn;!hQ-+M81hD6H7J!RL-w?#)r P #B4&ITh0 `w!,#2cs)a40P A G&1a9$ڍ\zNzB A 6!È(H` H-BEw%T'?$hPC!tP8Ѭ2T@l+krRU7eM|ݎAޭdJJv c8# ~Rc"װ0&KJf >").1&`.$:7]& I?$ذPIu+) Ed9a *t֪SV8‰[;$&8IB+¢mF0ӈbl)T &a2"/A"HL hjNL "L| BaOE` : ^!n¥_ y9Ԡ -p33!ҕ=AAа9 Dq3͑>; zA8(>F> ^ RޮjGT_})7J- aN 8` g@; @AWҔ[) 6\%RxiX<|!c+ fdIJNJJ 2w/,ݓ'p ߃jC[IaR~=މT{K;8.ER8*WԮĖ?yL6_+P(S5xk|l%-E>D!5TJK O-š>Z DBUK* *VђP˒P`kKBPE1RH3d Ԟz:TPF,fhL(7/7` 1F@OH^p =D#7nH2`oxlGNRš(\#)v@qGhjp7!"b&,0+ΓyS;て0kR5[EîȖa%"S"`r$_0Թ g'0YtML-a4!Ut0JdAor(XNr3 gx8]yt;ga/&a8KA?+~ )H3tD1E55O R£mym]%drªP5GÈ8WXAQ$\$L8%p)u0ۧѓ I(JcQb)hJcQb;EEל PYRX)_l%y?+Jn/]p&ϯA FdI(t̹K &N G"Lx00+pbNȃ+?[X#X_/8hޔx{ψRQohJ2+ doЙV⌺/Y %( Ζ(XPBʾlI٢LS"OLĤ4D\xXDq"0(bpp0sY_>È . >FNAE0*0 :SѴ`]s@L~ep{` Q !'Ȃ%aLq 9ISP`j+xa&0턹]$~+LHR1 6h0‚אЖy]QŬZ̺bxmUFxPlMHo YJ0{&n 1(Fa`l/#}pp58qBHptr̫ô,ӘL +I={LY88 .T;7epB7_fp}8~8}6y8cvvvvv8ҽś߅/WǑCI͵s8_Qّgf]v-`.=s;osEӿ9s.p#:;'V~V{on/"O))$4B ?_>qɡ{8Zϊ 0{6Ҝa43f8_%zx׻OeyQ,Nڇ{'8ǧ}ϳ8̲n]s'gvny67 Zc8B՝rx,=`7מn~NBqlEnRqf RRw.>GW0Qb$) IyHC1WD4 (yǼRiZ7HTMGb_[c8J nOM=읍ib;16)QgR4w\kXV~NuUNu9!ď`|#[YIt37R۫GgVM*[؉)_/Jȅ_k۽NL' nP_ÇErN`}nªae2G?2ItYj)<谴KDX] |$UM3@A£GQ7IM^ʱ>[oݿbv W)DJ߮T~"Ndļã;?I xk8Gㆡn_OO{wO{kL\]9d<\ F0‰j(w%ZGp$8Nv8.;"P7é3Dhl$:vф )- !&\j'4{K:Л+8ޣ3 ۍQDnPmS ~ųSJ`@f\i'HK/% +@]35CHtdKDVz5XxT -Z˃'>jܭM<.צ7x)Lbݚ`%ҶÃJdlkP 궭o¬{@ƹD' ILUEcl3dCC^"nxh NG֥r8i{Itg8h<"/;,tDNv^X^T^6Ul2cw~R70vbԏlB*%о2Dڷ(iނ[Ҿ@&̆8Z74*(*gϭlA"<8~  sǰm)OuK#N'SL탗y&24nEOb.nIkj{Yag&=!Ga1wR;DcUA'`"3vbx%ݍ:x^b͖yniȅF0 % b 4Ե`3t,VbsuY0SadDp$몭iKbήN.sL1&k@Tl(Wҵ=V>]7KZY4' .'Ee5-5\t`됥aFQn8$JNȥmۂo ;L37AZǏ$fD̾_bΑPK8DF!}6 FlipFlop.inoN@}9AޔpQQp^١L`osZVltw~7ApR&O*edx#fL= 0VyX$' s20$^s$4#^I¡b y FlipFlop.fzPK8DF!}6 >FlipFlop.inoPKs@fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/H-Bridge.fzz000066400000000000000000003427741250202676700322440ustar00rootroot00000000000000PK/xEf H-Bridge.fzmsȑ.}non3ώ~/jVX-=/Ve@P E2pDB"|2ϟ>ܝ}?>>Wݗoofǿ|X+rZ{ˌv7+c_K[}؍RWon⏫ǿ㋷O3|,|a(gOowoΞo_ ~sW_6*|o~~~S9/Jy"uݟ/>>>{t6䆙vn.Nk1S_]޿tn7q ŋW>.I"㻋狫?oggMog}~7HtǶ|gBކ[\>|s>_pٻp2/޿9{zT/noÇ~\to7}Ьu7p,ߘ|>=5‹ xy5Po~/Z}{󧧗_~p7n.޿GD[ϚMxy\\3wm5ݼeznqob?>3z2Cdv!˻ Y50M~/eIy7+?|??|KDL8*02ʿ99DV1ֹ]hTr79*9͸5{w_- ]Jn-uxqr^t.w3nL ~~pΚ3oWoj(Tיl9rx>u1ܯv [ [`؅Z3eK8$1 $}\`yѡ#2K&ƃl{SA!NegƏbՃdYd}6c^4XبX1Xrzd}(=Z 84R4'āi1,Mu`qr>`&>B4QD}]yi`Ib>vgiqīC@VAq KÁՀ,N Ia1/,I51,MG4Q꿂p$r*Yzī Rc^Wy_vZuGAnدy?+e:~!C}d֒'#^Wy_>..[ǼDi=(&6GDi0Z,, D,D>q`)`QZ}̋Sc]X,,OG$@awHc^X+Yz}P=U}dq``yqK C@~QrqAu{`yqK˓/,OG\(>e Meg %c^88| -\Z ֯z>?no|7B#~uWX/qjt)tq~cquK/./|Оem@JXaLHWqt:~Q??Wv".T2qŇS\Kvdl/>ޅBT"o=׫+sK ؃y;v3FGKQy/YuevxP} 'Yq'O+Elxq׳/."YӢOWɯQELsztjo^#j lkO̒e(hbcإ@9JwaLpW%hJ-q4׸x#%cpq+;cJDHR"X.ヅWVxaneN )&++6ߪKDre^/Ed'S2J@(AD)P.$ _BjF\%v(pGR{MY(9%r{sf0>Sve5uSf{SnpԵO'O&2I'K5k7)K&ZKew?|'\G*yE@~p>oow7Ǐm 7X92MR@jHΙ鈒TRl7 4qqNqe fKf`p?p[/vRweh^z؋VR3PBHZ_>-aZd":}iNEpȖE9]s`oMV_ln[akWmE8/DذcעPAuH;G0T .E/Ux JƠ]Oն˧Ux{tubzaet@G_׺:l?g˷軬B6P(cz&}Yqht@lk5(r@M֖ w@NW]$yS ׭O~#pP&K|tnOt_Ap%)X}yܫ9O77O/9=OT%}O_EǛ|\>} g>}'YӨլ6N39/s)\%8b量НL+R LIhlu4m$g"Sdl-❧kLP e7.g2iQrI4yO ןv.AFp.42vџ"]K w:j_te|aeMV`U7ؤ TyYciYIU2_Qjԍ"h{ks]1׻*:tVDz=%JQ`}24lX(.6mR 4|[&dd*Ogj_vㄍa$QE5?z9!DEhyBCWWW8FGsţÓ\(8. Tyx$Bam* ,` "]>yxDN'b31b44SG(4ba@9cp 7i(dR6k7=_lڑAc\DQ!%L8Tl!DjpFIu}>6yБN e_v#EaDrI;%Dؤ{3[ ݎ9UJ{ ?2RZzb}1CɁKuLR! ?Ck:p)0ʧ" 8^8XF&)& b}M9D{b1o&p!"~a~7Ͽ޿㻋狛6ۼCxk[¹y9ո M#2a`W{kxϯ#dl.?+ n~/.t4_jrr-w2-Foyi6cKJ :vx꥖QlF-_~K'Uq}s]ǕfY>ok` O7>p)L)G.񿂧@/dӘTFnҿ;kxt2\"|<~~hTkX!lbad&4妓k6wnS}$ gvBfD60dWw"KDJa*ǜ{4Y)F dy\6?g*fc$.M2x돂+5[Zgbh60=eE,XȔU$ J*kn%d,hQ6:Kr7%\R\6l\]ɷ{/y\eM Wx F"鷮~Fr:D,rX S֡S-띉S)O*2qJ+N5k7-N&bLC'ci,_ͻ߬xތ  %aN[.Ş$<2xFWNlb.nbG1Y ˩^W_FUXaEOGA#3)'S6 hTF' :|rcI !.?ZknzxQ7FPJiw@)'vh^$ZvR eq{PJ]YQ@)cҸE4F0 Qve Лc%tgR%|Suz>wMhY5dFtPc&0^]`d"~* J׬81|IoD(qhB'$r.d]X(P|e^Q }uwh*Y|X7+L n*DF)tL`aF_8)Se+J׀b@eENȃ<\R }M Js=MJboVHÜsuY]K쿽|~ x{p3z6W_MUq3LCE\ Q}E>,'ZUȺxqF^3؃H+VQW|XM%u,u֪;j.my8U#˘@#9HpkJ]#欌F2NR}ڭ# HmKcd-2SNz+ԒUBɵ+e!]TtSXl۾xM]s*}/%?b/ IjSr!"Dsݍ2<*빷WRѮ.E%EWs燻wk*o*/ۼrϷ+|4ڜIUo)SM20MKdޯUeL^4'"*aj~cޗx_)6ѲI7Ζ ?@%ajCW_F-(1Q$LNeNy NY ֽ:%,q}0EG6)\)%M5k7=R(_ԛ-Ah9eqoc0>.voX8,?[\mg ؗ)Plʬ3KOVm\vzVNb|ʳ1d ѱ6-#zIб磢qd }M.ƀqvo&]Δ;s?ƯTf&냯_?:Q#*V^-kסY}^ `"|1.=kYWl8+R:uGQ4yG1ir;zdiG/xvNܱErW)ki>KFY lm"11@gU5Y{G"~C+LqT$:z&0DZWY["Y!!Vql!%*%UٛGFP"Xu71SZmZ16C)Kj'J EhXfLˢB_]]QTJ*yEblL ׻y 7eM}2EƸHKZBFBFSC(ey9FbJԠtf-U?M옆\ږSC\X B/%]3}gonˡlN#dW͹%wV5ŶcIr}\yelbV,X[1!-(+LLd"?Wޟ+v06^a!FpwXǓ!y,Of$^𞽭JXqmYl/L 'v0-! LpN~dk>M )SjMhZP0YxAE"(ք.1 UwV^Aa*ϔ#U}ܶ^Yw,SwjRYAN|S$Y]g@RUZ9=?mQ<GSuk2sXW_vp /*5-M,~eWu, Fr24Promue8\.N&t$eIb\)=hj%ZPxk@qdkxV_v-Ⴂ[Y 8Vh\mDR HP3>tx{4㵮02j_i &)\Ixa+;> ĕZa%.`5k7)(-(0+ ~eWX{J"v,_yTj6Ӛjkb dm UĢپU[3i*ΌYCvøIG6ĸ&7{5k73(7(Wܑd,lVZT&TKӉ3t%d]扛!j1j=ڕHPѩ.4 '{U'qik$&=5k72e a,lBnj| b *&`Z"8-eҵ\ r`aM!7"ļ쬠f_r+AYvXAIhWK&iפ MJ2תb&8U^@bl 6_,L[Lb}cw,~`||)q*}'t;z nXE2NqSZTD2nQ#>oC*ZI7W[>kUF4 Hܑx3oFjw-jbRnB/Y!RYf˃'H345k7=VźXW`];)uX^6{LP8* ;|\+]՘0GHr͒oqq4R9*Y(ZP%ũV ׬t;РrY6kz)MM,Nĭ-r֧۝>n~u V"D\WׄbrM=J7%5t;Р:y*N5k7 (|$(|pNMqOp2m,X}bXӔ}_"}SM&GA$ C#S*6(w88tf[űűj%w@x-LL % row3ί-'5^D:՝0h+g<[(PXyTYV&Â8U_v`bYxUͫ.xՔU0|}E@ w"UNk;}_ ]2E6 HV>`U8U~ ׬t; 3hd2hMYU%M 3!Pw:grJp;j[1/;.c\+AS6iuUwbYELHqz/ını2j'YnJ~C RCsl]s1tTbrSx13|(Vi)`qAE0oikn%ZP,Ao$ypҲix/*@&dc,eĹ&8kP¹Mql5ugIV;EeDⰃ8T94f[",A+ͻUBh)(HK:w)_ˢ˚R3YPP@ f175k7(?0FPz x4iQA{sTLM ]<;R:A .|%mg Vqt(yeA|jvA|*djt*qAYv(A*RPD_Y3cIppڄvdMNh Yiͺ$KנQnp7TCU8Uz ׬t; 3h%.hᮀ2jcl]ԹL6h"\ӤA+Zt5=,ژrڼ3ߠw6-* 9hޡ4Ytf[b-ʂļjvԄ̫AC[a*Ph0fGO\'=1K,$W#4Mh`.)N2b[yDYV6˂XU_vpbZUbVY).M(UtTV1c+GQqbZT3],W):J'5#`iAl+^\) ^}M ^a%w&܌z)\q&W`hdX$4jNrbhמ}x~~Oa41/1RfʧC D8sxtf[%fA Dl'3&ܵ ^0[ǽY;iw{YM"bxZ~1ZZ 5XbHX«Zd3* Vxd'.; kǩ"a}MC C"b5vr팛d"j4vGF_5v}MtKd_b#qS^׫9*# P`{S^XDnʂķ2XM1gffIo_E1vq1e.3.[n|n*H^XLDa [MC xAS%] \}M s ]5ﲻ]\'FT,үY>3*.xܔs[1O+&Kkj` X$%<̤ȗc tItd  o cS8$ޡTt1f[E . N +vA\UvYECC3!G|$մ"bTIXTufQ]ˮω)m-+ B(*>rBxؔ1fADN"QOHĘly%YDdym군rb``*Zݗr~#!q媔SȁS bhAA "X}M te V[]p+9%2MW^aX$B+uV*|q,e-]`e!e+mI\:.fi=Wljĺn!'Ƚ3<5k75(•9j4LMIjIK CS]r/|!/IִE6TSɎ5* EvA\ ׬t; *h]WZr+k=%j~f zb t[l5k7}WG_Sx(nLſt^a匵F1V. >x偎S%^ZDnDZ&jdLI6( }Wey"aem^&au\L.D&&3.eɗҁ3 5Je+8AYvhA,#bP@aS/V~c]Jыgڝ>.TJwb,.mS("aW9HDf|AD.6Z6SnuOa,%= ඉE| DI}="Nu\,U&/sHee N+*X ' .׬t; .8(&7M'ML>YO^T~) {'ۉ*Z~j*DL%UJ/rgŔpP4h!AN5 ׬t; 5(d=ؔ[TTZhAAu3կ)ъI=qR Zї`!GX$K#px1p,+Sݪ D(/Fh]΅) b\}M b\pW͸vr0j[)Ƈp&E%* WG_Zp8P=vu46v偌S]SDnDЮ=m:ōC%855LJ?_~&6}sSo}o7RFjfr?7?j)~ݿ=wg?}O/.~GY=< ?Ƭ\Xnӗ3v3wcտwٿŎ;N-nt84=twowçLJgKy=2O/n.ÄPO_7 _?ǠLwwepԿK 4}/֬.5ß is<(f| Ud1V,&&FHbedD0>+ p<#廵~>C;Dl@/$E\8WiJ, ywɸo?à8<|}Wb:_=\޿WofWoߝE,:򫋋_ϯ~P"4 Ï~f珗aVopw)`C茛* 9w?}|x|>ݧw?ܟUh> o?]uv6-Z K .x7kmC`}&fx Zdkx{7LJOuuߵ=!N⊿F@N-JSl(`_Usa`,VlKsV)ùᙹz?NWJۙ oYδ h`éd&|,ylb0bkÿ\Ư-4 9뭍nb\ϥ>6U<<^~0 ΅WГUb[ }⹷ꊝqgn>ZG2e0ۈJ)σwglEe|H W\FqP.[DG ?x$Bʄ+x&|*GysQ @|*ÿ_p=-΅ ZFrVk Oi\|>mhN2AbT&÷JW3x;^L.|+zo<r`W3JU0=B7X^y' z0*RϗzD^m(rD["So 7AK7-Ti"s_9q5s!cAӀ#I`2^+݋m @vq%Sձ>t8zupx>JDpHq|koo->@=7^[|{f6~Z*g͍$?|aA]7@|Q 21Dϳ(h>Uz Н/t 2~ #GtEl@ ]-4_oQGQER`R`R`P8xj *l*ߧ UfT Z1eZQ0mb4s{n89A_$_ 0PwʳEϳ09-sYtlŕ*`_R$%y~{2|=rU/0/rQV-K,JϝR5B?" g;Pz8hb5q0]Qof05@AXkbaR£s0Lv$d#;SU 9(DzT GBHtxP=w7*lpe7M ,X3aØkvrִov*>6؎ɴ I4iԕcֵn IXW-`&a [pvSQ\`H| Rt38'nQ`Fl_+8 Zq>>AN@[8[~t`5ʺ̷|ţQ{# Vhp@׉[$%Mr;޶g3q]hwK"7o(b+-NN8 XEgnAƀDc g |!{ xA1,bM8 y;5P\ p&E JpgS`gxm@f@cv^4ܑ 6CR$`40 Iۜ; u$4<(!l1 ] FS?x;&pDl_A(xol!@& 19P~hG-}e@qoހX yK=ޣ!Y_pU" D&+qniMP03X@ͥ@Qr P#)h7m=`jJA%QΣ3?ق Y] R 04Ahν8c_ hi ӟDuh:XE}`BG$=^[x6pL$͒npJˠ[4LTA530zyMth1vsM*!a` ]ZXKa}UoWN!|_q"8ޖ;X603$/`I4&ZFb? _L$ky$7Qp 7(A MN ]7w熣ՆhDO>8 ?C;/r*%$3_@Q4.øyRkhScIwۀ+ *. hk2GWP-`O=H8Zg IB8 X|ƂpFmA 5}ݒCt B|hU#ZVm^JV-GtA|ZC :!4襛4q@ f6g;V~H1 |ȀvsRD5XF ^$\/<XD l9##p@V#ĄW4:GQ#<vI<+03"6^֌\OV3O gX{wr.kafQtN4ρ3%NbV L3 _nz||]dJMrrSw}/dAD= K{`eXM06@J= `i8SfF2i72 fŗhq T0=9^+04F) P<6-skrږ3&Q}d r6<]%t@gFwz†[WnF=aK]"^ UEGmh  @mGwI1` @b &RL ̙20&b ,ɻȬ"}Gwdg':f j8 9# 0x9+ b]N=Sh8yc;2 ' FTZa'Xk B`rLxYǘ(OqBGрkޣ $zj3 0 G`#q!xdf@5x=> |eX1䍴cƖoz4’;4~khăQ=. #:9cvYD%"iDd"ZH(>.r!!kkQ0u*Y9CT8xr8Z`D 92 8d>`4̨"0ۣQ$灏~oBal}E.R^>ꅏ |i`%.)RV~ߪyeBc~4G24D0d"y A ttH-rcI)0S*LKC" \;*"ѳ PcAɅ/as/@s*̠o{ σe < =S'V;qr;&9Y/vÇϡ?}~/u`jѥ&sWJcfWLf w7=@`b:1@amk?Z a\Y3088S$~Fk+phOz.Ѡ=rj" ῞~U˜М[L"gV߻+M☘ ! "hA OF%`H-"|'i$OQ,b,E4܂qvɿ,~4GdXD4H wJp`z01ՠ Czš$עzȂN A v@ C(ڸH H-BGseV7=:scj+,QIp*C-O Co`8D뛁`G]uZ\M%#H=iѷNɎ!)uH0Hc/A"H\ jjQZ)% E|(Cbvr% M8wA(83x3 /p,kZq^OWʹd o7AD(sdӳE9Q[D U97qt1G*R/¬~0X2gPДt-) 6\6[L/͕WD3-^\LcI~߳R4 ][dヨ*%Xmù)B- !lig/ Wj0\M8]pɈmYjH 110L<7PȠjȥVWٲat?mG뺣Q [dl ak]Y#T j~*lPeK8X Kpf2рA&R2!`ވhoZע喋FL )#]OvD&MAf}/5r4 U"5"r'1[ M.ԾR]pFxrߵh<&uZA/,Fb< 7GE< )oaZLk:c Jd4qɺ&gldB:G` rnfθ; KS.&L A1D :HaY$43cVeӗcѵƢnŅly,f,t8pLK=VRZqslLK򀤃oًaLٔ9a0G d0{S9k9C01~.0a&ăq\A9)nbMF'6 nYrWcEuxZ@LI+Yr}ּ2qzm"2[]6L[{vt/~w?|󻻋椣[,ُ+uz{͇wwXF&`+EWrdݮ᫅ȰW뮀{Q9۴bYu_?\}0cz|wq= Ǐ}7\o/?=ovOgNx_%v5Ti{~xytĿ'"}<`'Uc,8nAxu/gͩe*.[nr[n;|1ns9匕oax *GJuo_ *&*յU恨TJ.jXv ؔR]} *R˫RV?Q)ԶC776 9YːʭRY KR]@Tːr9g!kN+0:Ymm'-_R壔ՇRgߧS˖Rmi)"7?m3K|}}{79\F]).F/oaO77O總?nI_0O l׸྾}?s%L~^J/\6r 8ܤTG(Md<:,T+d&eXC񀝛]0zS a+zeñeʊP2&p7&*ɹoY,15ӇDz,ס\(zF-7߀ X˥nϭ;X Ndѣ.~˹:0=Hȁ턉kb֣,,xQٕGh)5"R#LjTJdmRȇȢGY﷜Qu h b̲k+mK'I8 =|3rCz;Q;!-GvRhU1]6qj^4c5h5?]Vߚ*Wp½=.s Ᾱ|@Z'tl/>=ŕfB6W]_ >|} rջ[ͤ,~|`EZb\Tn"K8xܛ*γ5p܈+M"\eQfRĘCd)/ mS/ a7 ˢt[q/ꖑquWcF[chQ*\Šb,Xq 1Z; ƽH[C%$" qf: -) H]'9i2Xĸ {Llk-W,ĵ5wy@Źpb\-?w)yX@͌bޥDJ>_hض-6n@\yT)+̌ Zь "\8Ԡ@W> ҿKNI%t@D%dFsWAhxUcxMY6x@W8U' ]8 ޕ8w2ɂ.5%Itcm|k2NI5E"Uν_J{RܠAZ8^z7iNeXKn`)GnvDY,bt) Fgdt &՗o][1]A-E}96\1\11(v|eXi|pq5M +-c$[Nɱzg+I]gPcRUfVCe<'Z?aK(ͫfx*ݰv՚ہL4rSqW;P0&䎊Wk@ < YwaTD/YЂ"V;s!1T\o0uH4ATGZc&bU$VP\, ^92旒֭BJ{ISrKT/r=\;a1c\;Rjzgkjf`zƛ@cq0T 0h93fYfi+V*])/t']R W[MI8AUƔ,g"XvB "\;0SNwS a50-dg.e*@w.ft@cej(Vd:)+K;^1:wCͱ?BpH4Y.y+}ف;&)H^183N0fjU1]SCج)KEzDE9z]i{@bzQZQƌ}9jvt xOtiV16GpsV^KjW2"D41 GF ΅7sMXڟ6p˞U\,=mF` fA*ї=L} >#j?aQ3=%_g:O,k3 ;|\ +/٠(U1(1TsDt3*ī^Ȳ@Y@[~cJ3UF:bU}RK++ 3ZU&8LmK+Fc bDVnD2Ȱj -{ )bLį&TY/,̄İA,WUvNjxɭn.5V+M [*V9w@,20_SÇhTWjvߏVuE5e1c$l=NlǬ @:z h?on` , d2M@PxqU_ /{7N26aѷcRPaN wJ;#M @RƂerJ24ֻ$CaJb THȠdx) ,26)]az#Y1i M+vr\: >1LR~Xv2NRE* KAdjZJqѷ$`*Ns?ơErҷƎKԚAPS)7%rKSb;z4v!骰ATj/$3J2̃DqHAt*Jj bR8 &)(2U) :姤SKSIazMukA.+)YCEj:,dsZї=Eq+ۇ_y~#&erFfʩ\cזh]NnT-ɳd(DF]΅)L,L?ba+M ba`XXK&Yg0ՁRZ$tmo6 8 K"a}2IF} 5?}e_SDqA+jo9|zj %3SuMlx;J3*Z՗ bD`KM&Ćn" ȩ2 18"d]TbJB&y@a"."u>$>4X ~2,!:6t;!:@NMf}8|Alfc;lLX<^UU\)3 ArG_j֔S1*,ap!ѰɅD ǩҰa8 ;4킆)i&lK+" W)c:Rz!l'U$ iA'Ĩ` &:8I0bjo`ǩr)mc8 :>%:.蘞RRYgZVX^# FlH!;}l,I3BKdc|M4TX+bj`ǩ M"c8 2=d2)5iCX#" 1˞SdL 5EASd DqA,z%))T/I(¹UkQڡM0@djT!{ٗ5RG{͜C.M 9d.ĿqA+vB?)ZP͆2{CV_1o<Q\g)(}G_ڿ1g|-cuu47Se`YDqA,x)SRTz~@u,`Fh'JJjPRb9դ 18"d5!3; dMHpa2omo6c @d.\jw; y7|PHlvA!.ՙO>TAkvA+bjk*kx16w{K|)W8fB <,t'B_OZ)TC4j˃ Ǧ? 〃Y> BV2 Bf$d)H)G U"!#V F%$їx̤a|V4ġ!!ASMCjV8aQ|xAԪ㩕Zٕؿ1$ll\PX mSDJ8LiWG_ɳrD xP퀃xW8U5A,l$vܔ,cg+7*IDe!HXG_  $39|jn˃8 〃(X> VS姤`nQ~T,< v"<Sj* 5t; 1N~Mem8|A䫥ɗd/6^w+捧W1Hb)N]}O&<,Ȏĸnĸʼn2 L Z8 4k\k}I>%JjwSֺ̾RRtF y)HW)詼aW_~ ,ohիdɓ=MP`恐o8Blqb/)diGzn*ؿ戴QU}dQI7[+!Ƨ 55(1N56AlDD.rJvWbbYŸDJD'Qվu,Xϻ6a^S̔Bѱ E2AIz"#/ !f6p bfy"c +[}q?PK/xEDj" H-Bridge.inoMK@+j<#E+Z*ң,i24 [Jh0232J*4$P 5>.%d$RۍpРd?H&pGPE$}N{k}0F¦\zav#4dMv{OwQNrz şgY'h`2,=jp?p8Zr^y*ErrK=[T3m8 *_ VGj !}PK/xEug6=$part.arduino-shield_r3_two_layer.fzpTQk1 ~߯0~iCa0ǥS}}i_?پdIۅX'O7a[ɔ3kѮ}(ٹv0+ krɑK]K7ɫv^e& B2[|rVM'EvЅ5L|z̆jvTkTs\z?qWLrYpu%&3=u!Kݡq0-{ѥ]g@8S'GQB_uN06Nq269Ҙbi>e--1܋_b`(J!aԃcP]G'— 0;<')a6XO۝\ Q828fM焃XqidhM.$?e+q(ͨv*C'?!.whuڸmOuNLfZ4oCtmYc/a?\9ZYŒ&:@aٝnohɇY:MeS/Y4ZܙӈvEcDъO`Ix$hBc6Csb ڳ]t xX򶍮1:h<~&V&?r?F=.tRMJE_(3ߞA2,<3P%h" ")IoDl*j&#;]]DKFgLPȀ%h&IKTdO:@_8 Jd ^BL*%%E5Ey*tV"\pTfnZH*Xctqws љɊf,^wFbaٔ$GT"o t,p ddu fqd _@ g84I$CI~#&[}SL(tLfftM +K4Di][% Z usLamoeLC'B PGy,yƪ  ¡b[L8k!ل~&&h~)dF#na0< @˪YmX֟lEJxuT,oVYwLef{:o]ÌmE)ytg/oA7Tx|J*V­D2/rCO7\jGíY*lf3|uzjZ6:+az SUd]naîFFqحaW/z*ܛ.8K95rhš]C[/v=Mq+8ra({U8WC{S:5](-4ţSGG/N=M 5GiGl X/ H-c0ҹlIH{?xTkKRzylT:b[2U4>j{V'0N |;s"щRq }_^H'Lv0)IIcSq!e IH`D1A'}!:rH`@K}VֽWsp8)I󱁃 ‰W#Tb>͚{o&=057&vv־_sI`Nf\pJ/Bd:1j4[`FONqn<[`O`Ny66<#nJ#m\bʿőh HiJJq\ʿ1*Q#R2 +tusW:5㚗UlJmMtj]B\2!|k^'T7F(j[bkdvڵB ^,4f!&2{ցD',.I%.5G0ɥ¿1.f_G ܯɣ¿1?tDfV"Rs5T7F?TRs8jRoJ1OY@*}!5AOǺt# t2iVT͑R3ңoMkݖ3) t2iVTqR3ΣoM>H]bV\TqR3oM\w0 'frHX!5c9*ƨrR"4!7DsԌߨqH{4+zC*Eo Q7FeTT!b8Ds ԌDuhVTR3~oF bҿ7蚵q+m\{Fpḕv8[sobӻ+ZHɣY{ռqkmT7+\4n=yOӨ5k֮ƭq5jܚc<Ѭhnhhnh*xyumP&@MA͛h*x,n}.xHdumP>@}]u Sϒ`3n45Gx/~x5ƈlv*ѻ>lZfE z j+j 1- b^WT9JrzWȉŸ=B 9F 9V<BQԫ,WD:?^}z]/Ŵ:V,?PK/xEE]Ş part.Battery block 9V.fzpVM0WXVX>$R%E 9:qwDoo̲߱$Gr%.%*nI|:G*:H L?hYWp2Cw^M&㺊t6 dmFlOx4 % s1ޫF$&=H攨qBKp!;@,1<鯟c事Fc朁2-fYm305nڦTBFCJ9n f*L hZ'tc!O£9*%^%=ANGf"L%jD<Ȃ1wNf㱃n6Jֈ]NxDHwI 'ssNYa~4 &ByE4up &N Qa1"K|?:E74 rE!ƻ݌6뢎6#k֊|At;קN,ȀGB--ڽ C=qӇ oq`(BZq5HĹEf3J)E%\nk;H."Lft5:\;=lE> %6Zdbm]12 bX$\Mjx},ܪ3l w[&ϴSMLU.mzVmzM6զoڼnm6tc PK/xEQVC{Y part.dc_motor.fzpVMo0 WײbŶXa+SlU YёCi|GwJ2bq(T9Rl?'/_=|o?'>8y_7>}vhgpz{On>[zEz}rOZzOOE柳7wٝ_zyg/Ngwח.~ɣO]|rv_gw|y}ݛW ڧqv/|^x?λ;~yyˋ?_v积.uqzWogw~6g~5|Qo6ū//>~/xsxrAW׿r˗~ux#sy9>?nM'ynsl^?ݧ8*z1:Wyg2^=/*~y(޼W/L^1h%~n:ͥn^ٽ^\/ΟW^kyw Q/NOn~?7=8}S{~@_]=(x?7Wzrݛ?G!vgk/em?Ƿ39/SK_K*z_a_Rҿ^>mX׻ͼoO.;/SKK.zaRҿ^>oX~o^)av)y?D/0,=JǹatCCCYJER*}.r]GPhRs">""GJF9949T\0ȡȡ,"E}D Ef)>9.r#rh(r4KatCCCYJE)=E.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29Sz\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K2]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhNu.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CY:"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GtJsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef9Ů =z' j~rkћ9w8wy#{7 a.tkћ1:w(Lwy#{7 anukћ:wx`wy#{7 avkћq;wtwy#{7 awkћ3^v2lix4LyrxN- i5^ox0 /;^4<Grn~KEoHbx07ݻ} y?FG4l]J?/~~߰`^?)av)KSCQz}g g:R*}>s}fz64KLgzp,3=GggÙNtJ/^3ӋLYJgz>ӋL/3f)>%L/>3tT|3b8iNu>k^}fz54KLgzp,3FgWÙNJ}W^ g:)gz>ӛLo3f)>-Lo>3tT|3f8iRޢ3ӛLY:Lgp,3}DgÙNJ}> g:R*}>G>|f04Kt8̇ZڏУwo0x-z>.~yOrn~?^޼ϔ'{7ϜfC9Ns,< j~΃Ӝ9Oôg<4r09<8y4Lyd<4r09<:y4Lyfc9Ns-< j~ΣӜG9OÔg'րӑ5`yf&Lyf·?έ˃k6aZ3s>5tx X^ jlMR̆wMV̜MV̜6MV̜vMR&x >MV̜ƒfMV̜6ăMV̜)vŃMRx3ƃMV̜=ǃMV̜G6Ƀ.MV̜QvʃVMR=Ns[y<3{9ߝ|4Lyfs;n9iV̜|wr0Cq 8t,X jqpMV̜>8'l´g|Cr<&g<21yt?7aZ;l9iV̜|vr094圧aJ3`sr<'g<3ßN9909t:'-لi599hyN&Lyf99霜dyN&Lyf·?''9,ل?on<{뫋wtUq{͟zrݼ޷͋/h_JnJrגywzu-xz'{$7ps|+py5d5d5d5d5j@j@j@j@j@jՐWC$Y Id5Ր$!IVC$Y Ij˫!KVC,Y YjȒՐ%!KVC,Y yy5P$HVC"Y ee5j(P$HVCjP%JVCd5TjP%JVC]^ my54jh$IVC[Y Md54jh$-d5tj%.Y ]d5tjЗWX^ Cd5 j0VVÐ!Y Cd5 j˫tAP@DuX2": r+C2Ѥ&e82 (eB)#uuR)A JXJQ%DX "WºW:XH,AD 2K%,%Dn "\.a.a/A K%D "bH1AĘ LQ&,D K "g4A$ "MX7MXGM&XD "؄%m6A M&&'D "r’r9A NI'ֱ֭D "wA O'D "uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@Q{_ԔW5e)e͵֔5e)Mٯl(( E"E⒁@Qd(2P(   E"E@q@Qd(2P( E"E@Qdd(2P( E"uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@q@q@Qd(2P(  E"E@Qdnn(2P( EK"E@Qd(2P\7дnIdIdIdIdi@@@@@@Ӻ~μ|gY.y+_caVXoMow}wֿo!qm\_M{o~ӯIdV)t)9{In޾ 8|F@߅Տ؞>DwovbN}?xQ *9>Dwgj5FPfen-#o$>$wPSvO=>6oq7woo||z؞=>Dw/>Di`jMtm_&BQ#(yȻɳ7zao?rt/|{oWoSr7ͷov]X~I>=lOeoQtwzo4Q }@&?|df˒/ZTG}I_G:y~gw?PK/xE"&_1part.L293D.fzp[8),Z&` 7ЇYmV52Id~:B$YSw]MF1>- B#M8tGBϻٶe>/1IU寍8#M4][(Ox譿sA?*dԪPT,fARf^KYjPx$mE}{yoUaPm]ڝ6'ʦ&).\=>ufOÜ_V)J( +W<ĄVNq;JO#r_+_ hy8qc:h*k֗o͟H\h*b)Y('5p9Jv4jX-Zn(P%XNP{W]KGÍ:fEsU,Q=dmhi,7tiĆ_kkrMʆ~8YzSpo֨OB|֫? 2>V+q8`K{k|c!f1C ]QJ^!r #V[ʛ@[gkKv8!DiDB&QABVUNXzgRqa5'J{Οkn;Baoh)zN[JBDA~@􊼿@0c8{PTCKB%DTT4**ՍE,H)Hh+q,>"IEinFν{y| /Q4?†@χ) E#l#l Dx`?cI(1?cTNJMu" yE7'o"iEp\hBR F|m$9D>UAkI_\ۭV{K i"(K*kHf鬆6ɒ/Y9ؗ!a-~p@7cYjZ'PK/xE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgkݶ(}{>djox8-;$sKiw,U:-$v~ZII-56 7/^~R8\^ᗷ8???_o|zxg=~<<߯_-t (x>oC?6,C_d,\o>x?~ѯZʊemqqOo|A Í$/n/}|QF痯O«ڻ׿~^>Jh=A z_>?}7]]_^ŏ Kg>?~[C|?_z}?ߟ~~supxׯ-?{qs}?zJzOiV#:a|g_ώ?'}\Q0¾Xzyv}~Nj˄(?S̐]{A/K;Y -豼Gтߨ B+󄖢  l3yUI!8Y(r:_NvYʫnǗ\7?|^U)('ӢQLEYp'JaYt3*<`K|z[rq#\^:a_:aoO8:ş2w"n"r Z$@Ky' +;p$Qnuox^Z<`$!$yIꞶHIi$ 1b.k!F67Is h7V,@!\߈yӝ46-KQcjr5?/u3c[´$,T " A/ oiy៖ - OA쪭=x_D:5okc >:64.:{; ~*?? Mp)=~j2:5ֽ m [KUCkݛgftBtNdg,ITAYޛq2}S!5ֽ +G 8 q"22 =;H7!eķ8WWoܐxmp0~<. o5z! p^Sh(%5J5zc صnMxN):'[g#矨H=ۆ܋Gy7("x'jyZ MS .1QlWMc Xÿ!^aYT,cz&dXܢ  0.) b2 nXJ20I1LDCOD6!cB;Cʬ1d 5Z_`7 C n= 0bm1 Lx`xx! n0< Q a%aa_2@Qt_5t}J׻aFc5(4.G2 z\,҂7p١^YB=Np t`BU#}Z+S\ig'U ~j?׏1>xejb`S}\#eԸWih]KzmyVP;\;!~t ~U ~^)jNw_)r?G<t_ 5ܩ3jO>1^ 4`ܨq#V4붘L 4ܨp a&]p nTs~V)wƷkV 7Aau='k2P& :ڝ-$[de5 VT.{г-Qe(l&ǯ(X<Lp=_.D UP`E¯(cm85ioj `|5_&_Vc]u5$vk0 g*P>j/ZjNw.L`?O<ـ9IcV]faklpgZXqyOAvnMsH9)7@'}<ȱ(rAz5̞{; !h2yvqT\Q?6Xb oe<š)aR 0Cfa!#[H |ݺ7  V {2Dj=~{_|mBo'#tJ/\Wy _o~@ɟ>^/ۗ>CB۹| Bd8y??]8kx[Ѫɧ:oE _'~{?~/&G?'" xX =z4<^Co_BD"!z_/^Gf#kx>/o£"!xz/Gݯ|'ݾ_޾~{A k/xFC(V⨎"YCaB[Qz?O"@g/-zѿH"G{ń?fkCƌxNWpVhq':_z!qRF ƽ$]GtNuuT.)}qK]t=a&(5M]( EדҒ1&GwϒD(W>1RgE+WiWQW>ٽrM&+7QfzDxfT^0fc^yqξpNW>4^=ŎYoontvĔSףڍϜϜrkGb{Jy ?U!$ha8L}j>$ϋ^>>F>F#%$cN,)ؽɸ.'}t2e.Gi@ |(@Geۢ>D.݁^NzL0K"꥛IߴIߨINzЙ V:_k7I6qUN;tZI*f8Q&8nCuȥm. D]KkSuSߟmBwjiԟVOqSlJEݟ*fSQ&8?ˇwt's]҉<-<7t7`g7:۾ _=b]|\>:|ѣJ>z Ξ`>D.ݯ5 \r_zjd:Mbu-79l6`f7:?;$E_`iyfO""Sg`8h?~9AX{wy޿q.F(m;}:}ٍ¢}ڽP֍]\/h"thS8pWϮ?^d_q4; 54i xċ>KU h"$x-1Yx[Ȧ'ƀ6m'9KF2@ȧ9?b!YK,x{ɬ%?!LbY?q&X<`28ȟ}/>EfM #3v,KfMc &3~E,Qf-G/ JC28ft"A1J_O m3]C&HO?7tܨpv{L-}N+w_ZƂy' v͉̀t,596'"ILDɋ?}enA jH;ѸuImD)u!#%6=.6ڭin1ޞ3GںxIc٧Vh /n5{3h58{N8{8{vm-=Vueɳ1K ãkx<{PtL՗K"t4h\_,h^E9#nDBʑ52^/Joaq^8}%ZDmӷ&Ƶ8?](Βksv 9zFV<\"+H\ 9FQ~KDɎ d$!<ۗKX$I/ɀƍP|ŲHrZeYf7wXL,2EL͢}^0&Yd8@cXAPŜm=Bk Ns<īDm<׫/f~~ y;ٗrh, &_ XcQ >s'K1SRNVV 4Ɋ0,&S(\䇓(c *ew𥾽3=\ubj$OǕ-A?=XF-Ie 7;ZIOB'ZD}C\{#/ mv~g,dlIMn4wzBR"tz94>-WɘY'(dA,OkH嘨7Z&^)Möu=&ENu8 TeG{.:EϊvQYK~$9ُI|4]LQ7;D1AtM7)n> M#Ҝ#X? Ys~c 'Nჷ4%ߘkQ>HXWfIƷ5KrM4Kƈ?>|-[iR*wQ9MB}z;SV5xdU |ݣ'}c F,:6 G`>;&#ؐCD,EM_|i*mhr W66w{tfl~..S6t/*fAbB4P&׷~s}/0ZU9}5 $Ml/I!8W'+%8PBKa?cib)%U m(TR wmz:\+K}im!Ƞ c^s5J4,mE?J%-âɑpbu\wZd-#-=%qoO_މ%i|mtDoMMЦk;hvю0FN'bdwIN' TµR]'yz {8//Ǽ'Ivbv"X}|ԣ֣ @uڣPZN-(Ԕ"UGU6( LG1$0ƣD ʣ( c8.K8 wIgy`aKk2`/ ū7!o­IBIP\](gp]oBƛ 2:/ ;Hݏݏ8VIs?iSsR(BAB'y[}YCv$kp\1Lg)Nzt (@lX'A[~~Ҙ~~3,01$1U]eIܵ$v6~_mwVs_Y $#sO̸n2z}t!5hɍ0FkLsoH@~EU_;,&lpQygz3`?8l\\31:#ѣUw$ L#1$0őF %~D@ONX+9Fp?6)4S']N0Εxew+~iw+BLÒwai4O/ݬ^ر{JkB=9okflk5<GV 4`# k-}dVhh|iJ*\Ͷؙ@ls]<-6맟~ivZgt-Ƕd[KƢ|V>~4'ۏGǚ辽|ئ5lpӚ8Ao#Z̫gW|_K9˂9g9G1RrTqq7Gj,5ċ$jo̸q⍟6ى`9UL7y Ww8+8;bi,P#fZě<ר;~x qnsexgtǏċ>34io´Ǐ/''^lƀ-L8h>syYx:x,NیrW<Ό+x|D闩D<! wAXP!r Ax"UBл_,9qhI0I[NloFXH!rB )LŃ T?N⁙g2>c)| }b$AK2F3zJMq&8GFSY( MabN" azm3F3gJ^[=iNl:سf7ںTIqQ4b7q_k9.qb+"g_1N|_/ 8b<cQL8bqJ1N 6qQYq7C-bP" YXC m&Cmllnyl#ⱍȏmcX^~Iٔp#Z9_|y&9"?9Gts_IO0qb9"'5G6ᆋ.?7G.ʉtd刜or$9"?1Gn#cnˑ̹&Y92?+Gv?ӓOqò-.>E2'Gӧ.c<$!eX@,sb ~ef}r"bU閩T<&V1ě- tN0Hn* hXu7[̙W9ᰢmenSʏU}S HV d*?PJ3a*H@B2*?P8ۯ;>kXrB !˝uB[~Y!TN Z1.CBuܿn8b T+|>%*?vPO7vz.@BsxCխt,RAD=|*?xPofϐ:=Afj8t~;7_O~7<ۏ/O|9~"FQ %t+kHBGI|$Nl pXBK-wC JN(|bqΉ#t+[d:?Н8~գ~bA "t+"t~e}W,bqΉ#t+Y#t~q椋:'Э \0(BGE< է5(ï/~z VT/d . m:iAvl\Bq`#u80\qy8auoث,]/o/WvX"Ia`-w@vGK7[׶-'%<4??HKsIۖFwDÝ%6N=gOO:\f_>,?| w+X=̟ ғbwH&+dG}-qs+:L^A,^d+Gi.z!DO7 QTpuaN/W'N.7CB`bw)m`֦CW&JZYEeip洡9B Mm$M#{p(/"ȢZ:QpduԁGeQǬI8::bU =.w#9db5r4B#jjxW0# ; ;~Hύ n^{`"PǪ@Ei rC4pkӈ Q^(JҊnȊ5 Vz",ǫipFTD2D  H ̚nDϊztNu*[xi}Y|a-ʅg XƔ(!XGh`3r̷܀ظ76 F FO*B5 ,x6`hlAlso IھY [߿';6Z3ϱz 3Z9Nvlyc`NO}l;(d?A3r:t#8a_#g6 oI2ǾYQUb?B3eyat$#򓁴oi WW^Q3OX""-ȩ>BaMƁjhXWdjE 9Finv#hDc[@VF atd:Yr#&ՔkH"ZdH xF_@$r tdG7! .+eXAVh 5XGh`F,.|oHG6Sg͋6{ZwfD/sB>uO`B?OF[2wZc~V84\9 ..<|n>sB8{-VwM&Taeel;]SS m h%K6hyhsX_yH 2v>g6^ϸa˜)E 5㺈'"T|о.B,tQ ũZl\]:@0j/,WFbLL2xW;tZp,0]&ʤG_P1[\b9&U;0"!Z:΢͉(1 'Ng;[Nz燮w,MMG﵈2æ'˅"˕#Ց~^,RiF^zSx;$^wr'X8^.ٽݨ˝N~8{-^.jLn䡺Hjd77:?BAGy-T0 1*3d 0 `/ ktb}tSL#i/D2rZr%*npH ܨ ,8!;khNVoƿTPӘ%,JFpGN 0;F=;"q$ QsC0rҒ pʺL5k)%;_`B@RH~d€ \aO^cv5HQmP̸$ap$F` S$Z!Z2r wz]%8PB"̥z&O6o;Zr,>>=O(rJUjLCQ 'M>B,9Yf7IJbpE F%X`7%_j )r%Gā7+'E&3htfUS"d氵2 +̂1iPA ځʼnf`0T9iƎFDcYcuGYT'#kF"Xr5P+UjA2,܂ j(\Kc)$E66@J㾬0gH,-hB{+ͱ͸l+g+&6p܁Pf=pcNDנf[i4Bqy۝FW@5a/-v$ d.0WiUȄjybZXe UhSՃZ3MRNJFe\#h>#Ac ݴ%((QF&)a[}!y:٬씷ú襭dq֜Xre'wM 1PLnD[((V =dSKvE Xӕdؕ]S i68;+A_~-;NXZwnT@G&+~!Up.ZlTh޳ {ԼPڰ@ < M! K,z ;x |.YXYRFA) @gDAP) @ #<:alD-  @I QB1M? LL! *RXv$H$qg6)Bؔ1~ǣتc4-U TS _% 0Ӕ 'z5[ x_s^ؿ; Xi T֘[U;GA+PAR%ƜQ XFBPckmCDP@Ƙ7_@P!j yc5,Z `֙ 2cȆTQҡ1vrH95U:.14'C)0cckS-"i` T hQj+D-jVkvVgͶp7Ϣtk,&cqq%(X,4~D蟉r3nm׈?S2n%2{D/UY*LѸQkp8!?V@Z[F!3QVX,P@e24"BbIGQDrdm _-9|A51obOy/a ےrl_Lp-K:U,Rq7q\@:K\9B 2=!LUdHnXbB~d%M݂}KlxhJZOFbpY[؆kjLl-Q#*GVWjWTê  ⊢8bAv2kx>Ǿ: úRF*VqXE*wX#fIy{(⡉ a'u -aaï{W l1'u -aa˯{vXGA랬GAlUӖ_d㟍=g@luO68sYh P^J2z$ XG1Eʆ @APW[ q%lb N5 /gdbuyeË 3$fõw' ϡc^CK]0I Kv%2ٿ.‡Kb x4 W(X 0u32]PAa0 p I.:1yoP~ " *ƤV4?Y0Ĥa;3ρg@65,k.#g;H9Ip8lX?`_ C:W!0XLUg*Lۂq9Q\s0.cEzj'Fd85sR |Uh\2F!X)L׫XHC:\Bץ21Crq2%>r_bC1Ƶȵg 5wk!U n K.IX8\vҘ)5`)pm S}U-XwPuGA3A( ~e0+js7J+e$qeW (5tNVu0`Qq`8c8 P)ٍeAX/gSg; d YvD}ZD ?]0KXQ)S!"D:Xgϳ87Ye0UaIq!θxD\`9[CV ᮬim%J yNp̵ $#";YbT1ef$ Jna~B#K=7یe Fs4ݭ㏖Ϸ^__=l2X Ta=+8|ր"62ؤq{Q+V2\$^e^ _zu b:+B_P)&it-4_Z8lampZ?ol(C&㎜dlRm*9Z`#H>8)+b >lǣ«Ip6 |W LDvǭqFbL34q7?Cq4?{ܳAө琺ko&o'ᘇm8ed4#YpQ Aw׉V|g`J!1YN0e8dwmބT q6Eض/{H~s̩F(Ċ/;ǰPuie !hhv!pf8UUu#llR8vZ F1߸.j]8T) lýc8YYj9jln囹kv6nH'8`]#Ă'LU[{r{8lݾ@w '-% sC}+wv׮Wj|SL1,x1HvlXdɘc8Hy_EĂ'sI/=+kX4ЫCޮWÂ[n J{r+duuUtu*Igܤ>?`\\-8oca˭@S79I|[]sdr]TWJ8 tpqx:e–+^Ű.n/W₼ŦѥNN # CeخoXqhan} ~gX,L|Xh3Amfȹ98M>Tl@lnJNx!$GJyov7.Ѷ"U +*gV V+xٔȰ5.9#boR`/AʰA_$`p{Β9̞)4(/4TA$^& m$  ֙Ȱ.#b$^& m$C_{Al3,|̷ӜNkI帱Ѧ&Q2f{ 7#PNs 7>T]zq9n)k(TiAw ƫt@~<%MBH*:CfRfۂ̶!e6(&,G_V2UA'4ScRĉ :| 4<7qL1aHu3!QX5zT)|N}x k`PBt^c>2!koF'}ǀ"dBYwk6Q _AF\7D힙; )05.LMT=FI}mAle߸)Mn7Q>8Ȏ) n7QT0lr&03tFNVR,i)ĖͲ́ԝ\)Sܝ&Vӳ\PtMB S)SvJ/o/R!&{;TaZ OBA6OVعQ}J:A}8A^vJQ:ۤCi*(urwW6qkb'jp֖Q>cG,B{ZҭX7pճ됉~"Kg;S]x;6OXA*_%DC)DZ+Ո#|p9Ak͈~+Tt=D٪qfW*lJDn38`*N !W㖥2RI .~"Q$R@#kM:6;(:EJl&`f;(dM' 艘ڌ鉍\>yt)~_g+\Jl .#Wxb¤ֽ7}t+9mB,:OW0ؑyePeQ\bN( 1)!b"hhRB 4,Zy4*- k /e=~R%3@Jh( D `RRvUul|ീwW Gwrs)dH/&jU8)A+ ݖZa0f,6os&f<+ IA)LلtF),XÈtMNx\308 g$AOVMh]_k-\NNP%s((QDzHw-;| 6 S;AC%j+Pڭx\Yޙ6Y8ͅQ*X\'FilOGa]2.ü!OWDO^ǮeG"܌sƢt!Pl' lv(e!/s(ݳDtVs[#j爡92Uhb Jו5w&VM@X>s Y{C2e;Mx6j?F{Ama2LnR>mAZAV%h]@kиlA׵L< {kkiVO'AfۈZЬ=AU[(9ij5ܿhzFh4\*s oly,=lI{q0s7dɰꗉc@QAYHK_E$Œ`Q|oOvϟ_ֶP?;߃P-'܃1PAts!ߔplQ7À^tɟy{eeRiP1R> /.Zu;CT ŷ"^v}`M'K[VWps"B[ᖷr\U}VZw6Fx2b&B* Ҋ_U zHHHɳYcI+!{)Gz 86(,/xw-*V Y $Ryx݀*(J` '*89NTё|r6ld\%IƾÖh 9*@KЀ\:$51I`AMwn+;וd X1'tZS3iJkJQ:)K)c34%5FNu0Y/;6PKC2kej9 Wp&=(]Mޥ 7@|pQv =s B;m`c(y]P/$p⦠3?eszBpk[p9T=l;zq'v*J0vt ePO( uPOH[{6&oֳP&KCPO*ۈUU}-l zB0ʫqI"S儲^&tLv6WOPJj"];&x5A-W))'LDrPv_۔Ϡnl=;g)Hi' Ofx_ h^hYO~9<ݪh gDyzւI`'Z I&4zYh=$A= ePMȂrB1PN8TO(OzB;`•'k_OH X<,-DZ^>,MH7yiIu-'w%c 'XStdiPҦ"@ҁzZV=!H=!'1zAfZ6Y<MQ'Z Jw WOʯ[P8gA݂B}Z܀i@hPB>TP4P۝kw,"T7\vV ng\SSPŅP6V"-.q > _6mbi̧n>mt_]5ҤP?i|-OkAna?P,((⽂B{\ M8jϒ$ ޟ>Bؑ]ٟ9$Gˇ>>;g+ n=#lODuWB~eOܤ)  cN_J!Qw;(a `̟J)&"Hqgv٠ YP6h|٠US5(|ՠW sE4D$LYxgts sh̏L$ReIbE _4kH͠ jTA͠ijdWEݹlj>棚v fٙjP0?,Q#[yigTޑE#e5.1LV ;+IgcAH[GE7%D&OM`]48$(s5.VQreW$^4ؚ,g+ldB@\5X2(;jr_K{7\bH0v+ U%*^g޼}qOs+S@}TeRA]o J{ć[*8:P3L0B Du­(:\l0J)nh%,\^vh.܋!:|H_'R~%ثHU<iVzTYE+qX;wJ*kX{EByvSHBKV*UpR-"ŴHQ;u`{T&TUhF؄D= pp8k$&0/ È) W# ¶VuXO\$)8kOj%֩drdyt[w[řNB怬a8<æZY%iF䏪B𱌩QtM2 #7͸n 'j1%/&X!o d___jLRc LvTux)k;VH)= n=S .W` L R8'lhrF?аlPCf24pl8>ٚVT@Kq6"XS *i2϶C "Ïs "-JJ_5KB$f!aڱLRd֣J7ppŚ8 d@ 'G; QSn܅hIu~TR& |`Pv Z-&+j2F#/dZAm%,- )ƹoҜ P~$ ع85+HdxE1XkTcSATcBLߪ c !F:œœpVZJ\e; ʮB![, ߭/WG쳸0H#f+'^Ku{RIy"ݤ')CMs 5C:[3t.S3^\1a& 'dٚOT1d8eC:|Re C7sH$ s& ʍ,(& 4ihbݤ!zT' 1i9C:+ ж3[ Vΐ9C(!g)C KL7eH}x)Cd ֣! 9Cy9CGAr( jimRsL5ȏ:!a( ۅ00n_'#Qح\tİncW0'I0<Ó;grGi݀(P`F9Q(3k ➽&i׹0[&h\p9Ah3Z-4a_4p<4v 3[&dL6?xڌk 6odOu9=ҩn -ң @5ZNw7t-qDu㧕k66k[8qj#Dդt7cu pðZqcw_I%嗫yYf[j8I'QLדʾ5rnu&X/3Dž#W a濣qt/r#2F9dӞN' e6& Sr+I3d h$/$ FFjǑ8Bd!I`5uic4XqS@VbpTaDτq)Q)h$7|IFc.6 $GM< _ŦÛ=| LL7NtBK,]l ^ @8t3t!h܀$` ȕ yR5Ә\^o7/Y6 p #.`jԫk3 `m@k$᯽XE[ CZ D/fb #W@ZLF,fL XJDL[l "bYAD,dDb6-Du&o6:bV-8r $DĞΣŬ[lpJxt2"1+G]abRѫXUg4̢]\=tsSK#]\uR7C43?z10ܢyGx ķQczv͢D5ҘI:AUj"t*e~dS2 ͋*E2H#q'p $[@opu9kɦGM&ڟ(ȳQnT^Zfx*8וRfJ5t44ZpsO%w#AGa^*2.{ ip%w3w$U(NRp22 + TCvmFv띉!%gknijnբz6Q֦Xsڞ3Qp5XZpaKl|5yf8N#Ɉh[[htD{mIT`guT9uE%|l3ܨZW,]fQ]ht!*~":(x v{p;OaPpou j+Y(%gxe9㏊!9Nú0DXWY27+AB !4!FCBgk[<()[(U,˒3P%ֿBS*dXSC$OU5WU66Q pk E*$a4*(d;D qK6Vp dΰ Ӣ ʸ'6<1m^}~ &w&Q*_5NEJ9rVK91_x=.$s 2+w YDPMθ*=g50~1!ݵEU,s>ڐlRwK1&y[T6*Di r`gJp#Bt.<瀔@RեgCʘi\y*#Vw.M; #U<@#܄st"P4o؝byn;ZF,Zuw"!ǕC@@LZZ$ ueԝhi P0s YɉC2m"oh u[ҔfM!hRusFHqc *b8rU(Ap, |`8׀5DpՓvJܺ*7YG(?l5ܿ0Gu+єR9ի7B`8O~`&ԟJGVnRc[^Zk*ir#ٵwèɂ @*ƾNaa%üF6OMHu!' @r0}0rSHO-S=bm%3AQ/KPCL MxiE~]hUX^Aŷ"^v}`M¸A}d|.w.Bh+"QRh^ЂQpKBh;9_RFK$J`oX6_U {HJH3c+!v!- "Cz'Q>KEDG.6T ?7^M'aR ȁ(ڃ *ރ#Z?g-4ܝqX .})ޭ6,*4rF+YH1!\"={Qg$e+N4Tr!ۿ$v{QUTJVr*Jfm1*ќ@$ݷg*% D !JQd1 D}kOWlT8>ze@x\-lZ8YS#<>om$S+3+^Z`159{Τ|4J=$SRW ~S`UhW Hzt7b DѪ@wQ8E^:>++elc{ͩ^8>n̏ުQEez)ܤ)@$ ׫X~"=o 7?P;?4IN;{&QuoNW cJ@> iLATQjչk ?.Aco\ⱼGu!jcV݌sJ[YmQ)b5imJ'R|1+F<[9W_H|t(GlM{V(rDyiWt#n^ػ, o( j5혊vPw[X[\_Z2iOs!Ү\Rb`eC 6;S} ܴ&,Z_q('YZ@g)^!R(^rL.1Twq/QZ'!^|qXYq%.!uٷGk%)1K*^4E7qob5řbybQdQ#WCc`[" 1W<_b!8ȕ+լgzp=W@2;E_;bPYPxMVFp \Y6Qpa)mH *$Z`iy5 #%pI |oW |K -ķSl8 D A/\qW & fNj"$Pn!ZT&U BɈ(;DWvL3 "XjJF ̖.Az@h(B9bv۶3XƥnR*0DPOBMay! FK/AtLlrPnfة%ʝ9?ZY2r wּ!0M{4x4Hڠ8TdII|5mK \NXil%^Eg* 25R4Bgsz;`=)N#WV'jhk=t{NBseoJ[P6dHW/~Wn~%$6W,`Ŕ>]lUi'E'(N#@`Ob ?@胯KeYiެ<I7y o:ւ,r0uf92w1VManMv&) S1`A-qUHޤ>qf rB2ZȐY)ll%EWݸ1: 6?SH8c&=X{jn@*0#[y6: ͦo Menɳ֭ڟG?2̢<Ã6sTժZN.ϰXze`pf^) x7@x}Ҁ;@]-XqT^apJDee#o 8:rDF"m!;ۓ˿:iU_`GY:ث,q]{q)yl;FL&uBT u-X,Ą>:7 .>ۉ*_Ta% {Ra5tXj9<mhi+tDydyOtnf{>?ąm=4v[}ѷxsۣ2#H' ܟ8>U:4}?;G`_ܓBXfhlO!OIE8Ǟ UT&Sfe=AejU*ɊO"l)f\2[}ƣb h1$1 6=l{k Z41eI `Iܙ7,8 a]WD92+: )R!|Al&09!pA@s5re޵=~UH$?C!8@pQ+C`ΐc|C\S1Gѡ+tnBnR2JK⃈Z t!_2l˄TDlF+n"nr 9GBƙ?1M6dt`N&Vr Ɔ; h$v7p#S8R?SƦ x3á ,1ߙMlr3OyؽV)>1oSrnG[1=U{SV637WW54uЊE K|ZrܬLҭإ[@ۂ$jbvg&־57>M-.,H`FZ *=R 9$W17z2x=*6*ٷ񐜠j||X Ʌ'W,o!drsūJ7[Ϟ5NsiJ,!|5Q•sWƯoi||ҜS#'͵ W`wC4[ ^ErX{Va< r~䶼ײ^jE|o hvP;27yO.tdX;JIt0ծC*eZd- wNlSJ~|{z ~XC|+4I<.jmæ"69MAS@GϦ{n3nbp밙c;.W.)ETj 5 yLs7}Goon vkH7Edl` 76BGK+uמ3z!IhӢЎ$%[_s= ZybJ,&LkZ0pF|:_t+3_m$//䍯WpjPA|{^4_2_n&7yR6suFteO|S`+-#xB||$xZ2$Ukۙ kl4"C 4sv#W%QX}N(nc.KԗM{ju]ԗ/b@$lR0fã(tvײމ6ģ4 S!0F#nl#ҊBnUwD,"-(/4P> .VMVW/ d yR-ٴuZnR@lTjR+6⳹^9/N ?L|o߯7V^97Ӥ?脅6 tAJވ|oegaa?B|FDt?=?|*KNJ4;pAB?_.  |B} o@+/VהӛLTympT|^eU6%fAOƧG[ך .d:2u? 2AKrXG(-sـ:!Ɔ()6*` +!~o8]|,:|Rp!ii[Fsت*OܩU< (v)!KH8x0qj^jUkXLyI/N%~õ1ռ`_ -[8dQdi["ѭR݉!]mCU:)v:w[mLZ%a-}ӄ?3GƤL l+tr5&^P 7ba?M~rP9 K2Ĭ@R ;@tz8f+ rx8@-u _=KKDe:eeB0IºT܅[<زRunjV,I݅%vbV4n`!@t-UVwD ~-wF5OrqUD:nսBsX;\`Y僩OgGReY僩x ]r?gX>x~J-w"@6U[:U/NԖ*lݲ!` [Q/+j`yuu+S` b`)$ CU. -RtKJ4/ưJ|+T -ªL±)U^//uzV沣.C̊-L^= P%=N5-Y@z -"t 1J5fqc# [(Du/4; |3v bV,n$unBd ݒUUTiV6Н)X@[d L(ԋPN4 -T܅kXy>+hx0uqnP{* -UT^.,?p-@[i@WbDQ[ HSlm,NԾ9\]\^--(ˋ syeފ/[ZJT7gL+9y{|wq*Y7ɘ"<&ј_W27#6rw _dC ^~aŰ{ͶkT=V:z%~V2!ļ17cJ,ǔhݘ˰j;ѹz6CөW{52:[U,|_/؉%>5( J6>{}ݴ+*_!f7]/Ѹ+}d*y?8CP}]Na{s灻4 R>1 kumBB߳gǔ=kN[}NzW'1[ 87Wگ+_kP<ʝ" lay7˾4OiPAP&m'6 D7Mrz4& krg;pX(MYQci*\l)MưCӰiV^~re1+b֖$]:Odǜ5 2JF8Ĉ<|p,` ܹ(KCzmPCTD#Z=T+2 jp,I(˕2AY D"/UB2Iuyp^ʿ%I!\j/F9e13Z hXN쩱wb,eYU6!NLEd/ ^滛5!nܘ $915:F&1\688"ـHnAПitbrԓ0T)*qNs/CaEJ 6gZdmM«"^-%!Eo7|\Sq%F[ h,B.'9f#WƬ 1xL xTǀH+2({72~\2ݥIÌit#9 0;;RlMj!T ȉMITUyB&c 4xjPJ3+V U.iAtXY -2=}H\c>NBG%%Q=½f٘;xxd+ĩ$<9E"YB|@`%*+LQyʪ+dQ1=[&Kt=6~!gKF3=c` 0STl2C;Xg8*v13[rw-qJ\Im2JZp_-d[)콼z,ypL@I+7|b>\.١nm2-XPKuu E$ޫ>Ȕy"תY) Yh\ %!T<e"u$djb}A7*\1 AY-swc+Cʺi[B$nE9{<zjLf(Y ҿ ,J&FL,xiH<T0_Xvl%0*a*n2vѥa `ĺL̅niPgd ԟ=Ԩo& I! T,J(:@QRLJX paa^X1%R\,ڍ|ӔZy<5;٢B䗦 X{tpaԡŝJhE#,FBǢ,8RRĽ7^ yvieʺ7(!ӽ#\9FtRVV6NG$ľ u5y7b ҭݺFٸ&as1;e|0P /d^ul0p (8?q*3_298Pk G1Uh޲D^ [$5k i=x?3@4Vj|>`Urߞ~aOמaaа0h"g J Ӑ,6mm )B)ϵɼ얠ޫEj0i(IDZ, 6a&Ӵɿ[*ɵ쓡kXAasdvL 1XF)bp'o2\}Uvg9Ӈ{l7M/i}I>M6npB`Bd#݅ +Ο)O=xy#I ˰Sh@lu8~ў g{mYo e@Z,؏j e#*lF=ZHi{nO"kabY $QjmA (OvWDRRT!磍YƙZM~D6j%Kŵ/'EBA샲β~q>1 X< 60B ;mPHAAuY0:h+yQFhOd`#FNN(؎/Y&kt>ؘ2y0ߑN푶Zs΅O;tCڵ8xDp)>`jvQ_'q&ylKvct9x>.5a⤼%XYuD|Bm)pgݘx; kFίIZhK Ӿ}#{mZ(5^s~3/ۥ"K$,S[p:.:~9KT@^GQ*4a (35(bnp-RRN9O@kTX(p3>um]lstLf54UqŠt1A6`SLc5sN2à}R=6_IJ݇hY+ DvyKsx&YY 4͵葲ͧOcOFOQ mQ 6vgXfz@t2(pyP![s.KP"ml* Y:D]Jo;vHKcQ6.uj YD]aRf~:C3ܫN,{ S[ujAr/4.Y#sK9ͺjcczb@Ui U:w ZP Zu(_2qc SbcaLvtH)4* G񵜶 .M:C|ȍ']hރz_$:؈>Dv}Kq 6o1S#8q7gnOzuyq3:z\۫˫?W\w?@agfRTܔ\?XvT/s5v7__PK/xEC$p~svg.breadboard.dc_motor_leg.svgXn#}~E0/TK`{:6;*ȣGVB!)>HMR}TH/b_m7QA̷r~}-eQ|zqa8SGO7o Q~FPoSn9ywXGoGb,.H ƋW|b^:|Xm]z/P0tR á"AkoI c_^sb7(&ѫ~X~@-\ח1ZM̷ ;Hk:"#diU*3V4P _ Kce&L"Li"94^j#m#~:FʼK UW" 92CΠ@ wbSVxVIƆ9 Ic eX#BZA1%V&cųyPs FȈ2ohk'[) 0s(m+pJ̓YɠrWJ23B!"BNpw4t\T6VyeIpY״=k*Z`BYkE3=[ aİI;;ԥL %Ct!GRpIm lqD<FԿSG4੬.Y)$}+m&mi*.O U"J>Zɷ:&wŴI7XRֳ{zkcJUnR~Zx%Э5@4^L2A9 !a,l^@҅T=.NC[[riRQM&]m84A,(_ۑPp^(Do,3B!z2Rř E%34"\3ڥNZqvӯA9FEY ^"TjL"XMEidIKI詶qr5\u-MDqS}PkǨhHPtRȭ}j],,ȸjX+IsDJsVFܐDioS~5UBHvB&j ! ! C(`=N\)|SD&tvȞFDQ:Q9.&pPCu+!d;!L!2V61ɰ.iwL;,6%hu MuqP)O)E\8f&v-WCM\cj ={rė |F%sdͦ EU>95"7ɡCTJv^vO z ћn?DxÅ5b6hTkK4p+M{G/R[<^T1m!EoduR:nGg> kVƒQTYT,>޺OڋJ1>a]S*vپ߲E f^mye,NL^,;V%'zҼ[`9? 5"W;O}LnPtpGg4{,Y"XΔұ"`/5K cEYz9auR%HcsHWFYԈʗg41unPK/xE%%k.r%svg.breadboard.Half_breadboard56a.svgݒFze557L (Gvf;$Hdhugo_ϯ߾o={v_||7勿O?믾_o޴x_ճg~7WWWu~z?_~lw}?!|yױƛi9}?~OTMu>7û??G}߼z~廷Qg߿xwy~o^nӘ7Ô< W߿{-޿~o!g<Y~)!Oϯ 7 )Я{?~^"?_ۿVAI7urvMw/0O)Ƴ+W~~~xr1&p02Mir]!z~]˗/E|6:c;1m};xO_p3eWa/?ϫ,\-E~F_V^b(/k"_k|ϯo:yym{ߞS?q0ۿ:~6kd?^\2{\_ 5q6sģb..q$ vpqOkCsOE)6L+7'k܇bēb..q&B?Opŷ^^,vqgP/aVh+\ŷY|+]<% zZ\^7Yl/)1@WozC{5| G*tqЫO`⛆ bCPc1BE Q!bE tԎ8j>@-ax*KR+vDS# mO wAEbQ jGOL5DojOQjŮ(jP'AmA5>赮Va_ ළ5Ӈ6J5LPYwAUUxpZ ZkN5p֠ O[+֐6D\<ms յRu 3tƝkP'-AU.Gi`{ 3qڡ\%?A/'vH_UIU՟>襾vD_ ׎*A z׎k#}UU(AoWU}P_;z%56׆k6D_jCm} .q˔܉FUU]k5;רzP}[_*A}K}m܁Ff;רJP}[_j@}K}m܁kN5 pר P1׃G5tt‘(lT=~?P8AFՅRU_jl46&?ب*Q[ejE}KU'*U3JolT~?8CFՏRU ~ ?Q GJRߠ"a/'Z[6HkUE Vu>6Dm TH!{ުԇƞmz#U%)doP\Ւ=QQդ措(uaN3v3w| VU__jnO> vð3 U~?1B措:5wT~?1B措A5wT%~?qUJokTRs~5';Qը>6@s5'; Qu>6@s5';Q>6@sjncO4wT)djO}Kmf=\UBU YjnJ\s39\UOe܎hn#U)o\UͭPs;~B ZTRs;~jnO4wR-*ſ*R}KN܎hzT[s'դ͝FhZT[s'U͝h*T~[s'ա͝"ƞhS~[s'U͝F=IN=a/5;MPs{N!m͝Ty>K͝'57\s'Uҟ͝T_jn4wJPs;~O)m͝T_jnO3܎UJ[3OYjnO;3܎ijQ)~"܎hn#U=*o\դ-Ps}E jTRs{jnc4WUAsU^jncO4Bmܤ TRs{iM<57ԇhn Ps{IU&U/Rs57eUknR*<ܤSRs;~)Rͭ\sO)mMB/5?ܤ*T[sjQ}K&d|TJF}T_jnOV}?Q=*ſI5>6@s2'T oknR5{=ܤ &UBۚT^jnc47E({IAsU^jncO4W C#U)do\՞UPHsUu 4W.i_j'j ~);4WKڣ?/5',7hP}Kj6ʂh*T[sgբ͝t?YΪH/5;( ~Q)~ÄjR}KmɆZ2G#E KFa/5; ){P!m͝U^jnc4wV3RDsg՟Bۚ;Շh Ϊ<5wV{=YI͝Uu okSa[YJѯ{Uuṳ*PKj\ŸT[tgU:U StUJLWNvDu̔?R]դRUe麝?q]5e\WuU_nOdWM#U]*o]U:jqnVM*mYUN6@w2'U onVE| >ݬ fբB۾U_ o7*|"YfURx0`jj fY5 Y5NjʄoVe*¿YNjʄoV}*¿mYNjʄnV*¿-YUNjʄnV*¿YUNv@vZ'UJonVu{=q]5EeadWtU^ngOTWMQY#UE*ao]U:USTHuUJܢjT[sP_J5)* {EuU:jnQSTDs*P m-=ubAs+ܢ,՞ۚ[TuVEMQY-;%5ԇ57EmQU: ܎h2G Tߠ?u¯5'L7hPk9*~FE ZT'Zs;~jʄi*RmͭFu¯5[>ܪjT[sPkmV5EeaO4ܪ T'Zs{UMQYͭ@%5ԉhnUSTDsjO mͭ:ub5[=ܪS~[sjN}OZscƚ[*q[U{NOk_82nUSt{tZ2%@L&-UN h ٭jʔݪTVե:%}'|]*SwSi[UꔀVޞPުL 孪T WN hm UTV7jUkmq* ~$U ZU'}~jʂjU!~V ߆诚GZU`Uu¯ o' \;5x̓yp<؃"(m^dB/wM@8 {!l+r's⤝xk*="e? aۊàZX/7Me@x lr'3͸%8 jʒQ*܍&eL妩/Wz0m=ja~~4*ܐ&meLVRd5qeI)jaaEV=OV)PdtA {YULe"6)=jSdU,:Y""+SLU-KC(jfBЊC@L! E!9v)=A`B@T;KC0(rPSZ[DZ²d9nF`P䠺Y""5eI)rP,LAN hEn Ej˒RZYAjeЊ 0%AU0"U:%%@9y,KH*daEI kENWVV#T%A;9R)=AeB@T+KC0(rPSZ{D29b`P䠪Y""5e )fiEVSZ{Hz)Ȫ!XYճN!hEn! EV Z "nF`Qd:%%YmhY`YEU1딀VRd5eI)jeaEuJ@+rK(rTkZ"GU U%딀VQ&, E 9F'y"G5AݡQUEu A+r(rT["G U/VQfL! E!9j)=QmB@U7KC0(rTSZ{D29v`PY""Ge)rT,QuN hEn Ejz˒R䨊YA*fЊ %Q0"V)-j˒SdU,*Y""1.KLU! (jd}Zsܡjk5\(d3i"R)=jSd,zY""jRQ4"u A+r(򨆺L! EU7KC0(Y""jRQ4"u A+r (6, EU7 #0(Y""j˒RQ0"uJ@+rK(ƻ, EU+ 0(ZY""j˒RQU0"uJ@+rK(򨆼, EU! 0(YȣZ LZC<CgUɮg $q抜XjcܡYUU)VQL! EΪ!9^)=Y텙B@U1KC0(rVլSZ{D 39n`PY""gf )rV, YճN!hEn!Ej.̒R䬺YAfЊ V%Y0"gU:%%@90KHjeaEΪuJ@+rK(rV[a"gU U%딀VRdfI)*daEVOV1Pd5(d3EVSZ{H^)Ȫ!XYN!hE! EV{a"b`QdU:Y텙B@\T7KC0(rQSZ{D 3v`PY""5f)rQ,EuN hEn E.j+̒R䢊YA*fЊ \V%E0":%%@0KHdaE.uJ@+rK(rQ[a"U \T#@֊2N^\dy~X;wȔž/2ML~<;yr'ɣ=% {:bD^gzz wtoc?buɄ] ;8\S{kPU}xOG,YxO.,Î=ၥNxOG,+㽓G;UWG)tJ#WϞmG (a';OS{kPUp1da>O;w:4=;LjQ#Lɣ%uxCI[#&L~zxtz wOryd"/3ӽ#O㵣'~+G&xoޯ~݃}GYA5}FuqxѨ}yX)#zyw䀟QG/Go8#6l zy`tz x<`tos?b];8g6[]Ǯ~נz?b=#> Î3!9ZQh0ͧCE6?G<*:g<^*:o9)їݳOC}{ {Pto?bȆ^=9.Q'k੽o8X#2q㸧cDa=# q 8 щ>; }q㞮=='C6{9ɣOo82qן} aLJf5O?xl*|3dP3:g=:o8C6CPN =}COSiTGL:yrg,tq2q/ˇq. i/ /LNq}qĈ>G|Bw>aΟmGL~ogɣo8X 2q/χiǂޟG~}3A';Ag-A6[.==^: dC I2P'{< t?b]LҎ3] iOާG>x>5}v93% }}'V};@w>agΟmG>73q7GL}#? ] sqڿz刭}}w/tDO7刑}}ܟ}N==ڳ'>6oq_O'Ow}>>&T!0U>!4U>!S#|lqw|1}v53!}}gBw|}?OsU=9~O'{ 9g=9o9X}sxF> >+~qNx>xq$ ^w_"޻/Gl_8ww_ϰx}9bFq߻xg}3<z1cCW<3+_{ #Î+ {޻|w';6zwd}œ;a{oܧo8S #FGvw_U[ m'AG}mWU{Րp$1!ji|{{Փo|ܫԇ>Î!LqR;}qR|&ۣc={ѫ>$jB(57!u?f㎏YU5ִJ~1z cVUu>qw|̪&}vܫNrܫԇ>#UUMGWm)x JkǬ:zrܫ& ytܫ pܫԅ~>N;޻jiwvB/Wx*ݟ~i{eN OegW3NGWm)xѫ>'rTj'}TQjy/S ~>&rhӎ`M4ԇ>~iji{e&r2[ݳY'ۣOثq?[R;`{˯DB;II*cd VڌVM+<ӎzDjD+ӷ(M{br쵙lzRt$5d!OR3>ԅU,cV)UeǬRP=:>f\ቜv:'}PO&+7A>q_Ǭ{b{z {Ֆ'߀vq,qR3xqR%RSM8//> _> _/ۿ%Syg_Ӵ\'sc;~?|?Ë_ݛWWcᛯno~#nAypv=dnwGtv˞۝z;tG}]gt l= lft~´B=Ivo4m=AXq>A췻AGʽ_b^?qw췻A_a+:EݏZ? /?ow7pW{h"7G{W{#Eݍ6v^ӑhA_d~}]GEݏzۋ_}__|ՇPK/xEм"$#svg.breadboard.L293D_breadboard.svgŚߎ6.i@$Y[UTҪ} a DNf{ lF‰/06p>6I^sV, ")7Y]zyP:/ti5YstYC_zvuf1NAYmg?#_M&va;K#ky=hp6n ͇dEӾKV]udzFp#,=C-6Aj/b5}s#dgXMstViRFDtEscvޖ;fP`SVPWoI1<}"eʨRh(JcYڇ*j_o۲Чˬ! c)\=-SxN[t%R@*5&~6v>B?Є"SD5)fCĭ >|eEQPEk5jYjՔNM,RŮi]y Njੈ > BDe@O8 >!M?A߮4"JU 5范tRDSY$pjk74P HrH WkI #􇆪$ѓQRa(Ra(RItJp |_M8)R)R)]Erҥ'r OT`1JC4NJC$ً$E3*5R3*5jPYMPK/xE; % f)"svg.icon.arduino_Uno_Rev3_icon.svgZko vɝ68րSȫ" _{ TDjh`\rx>ϽsW_oVWG3ݪY\\.ώfw6q_{-/۫oW_[ Vo>f緷/󇇇Wjq3sYLt[@O=VG_ˬb#\޼0)˛r݋rRJ=򷱅xKfoauz{~43$?Η򋷾_-^_' qɗedu\>T,KH4^/o vX-.׋Wuu! Ee_^ زj<~Xme߬ZZd߳5|kbUkV`-z4[OqP>A(N񇃺qؒqjuaԵ)A8m=4 txg%)j~=RߙAS*33Df&TtTqKەSD渀U@'_R'jh`w)&mrGU6'8Q`&dew*8Ql*\laiOq2c%Ӆ5{Z`(:xf0qOYQ)˄A{:Ng"j!s}`"ب jHؚP`YjD,VU"9 'OyQ(V5RLכFi慕_,5^h,5=/:杬u5{Po;g"0K;z"9P~|gfSe|F^\6QT3ywru1pٸڦkZy1NÅ]_m ;Mb̈u/1ԗd~1iŌ=N{ np}_^ @ ;KANԖ6ؗJ{%*-m:,O 8L>zI 8y yJuN.T8@^™Kܔ<+;c@&Ĭ!Po;S֩^j&jAHސ nXCVېzysULKaT,z!o(|F" X;D5bҞ5QfWj:6 %HOkrKseQ!ڟ<;qpΟ~͐?q~ǔ7q .IzLC緖ÈI{iƏM&LR|k64hh@{]Z>;۵|&GKpN޿~$wqMY93CPA>:usCPauQA[g]nv>CzMs>|܋1Hf(݇ڜFL riDwWkFL9yLOTrTCn (M 0[psύdPc7l,G Rn(q!-D! '3s5[۲բL!dQNW}#|މh@aUʉȧ*ckeb\Jqw%NBg/ ^ȶ+ʉ!#dѡabg;}4e'OM.%!t4 +m>sPϖ]9YSFqBE> IL`ݹiD( cm9J@zA6ȠٔحPyhDpAVؐMd5Tq\9Hsi[5$6f# m")˂+(*b /JиgAI0uVKD3 m#ZR 3 CXfO3M{ xN6<$sCGupE4P(C[0:+rjd'Aj-iڒ|~+6ruΰ~j^\˽o-*cJ -9b2Q!&!.%\Z` }̽ l(wC#ctVSGh+EB:1:Td@|.$S(r0".ngF<\*H` #@낕SL7eG2:fT{K"FG#K|a!@MH @(&:ws0`.kPBy,ͽ7Bɠ L$,gw,.-)K܅1:[XH݀e0f` 3DNa[خ=J}/Yz dZr``]ad}OݹD757:Pf#b|,SO}_PK/xE} svg.icon.Battery_block_9V82.svgY[S~_1Q^U3ҹ_\X\\ ߬֯?_>ΚwWW_n6h7Vc66'׫y{lƸy&2^5aTqSt8ѯz^6/Q7M&ǿof4l_M&www;;^/'ofB '^3`Εz,.GtwԐ7p5JvɫOiH]ߏnqr.fwoVJk?ǫY|zeIj.gwMyus}>׳v&^¤to{t;>̛OϨUM!zCvU9[5. E1I3*=l)U* F_%"(q;#n8t&R$$:om\K0cP"S(/4e0'4EX[磠 FdD Ym-BЎ}R^ 5-yc ^P"U B Y359Lbs*mCc^_ڽđ'29v(,6{) 7QB) 5b[˧-/ kX.=J%@[{KkN"J"p/''OHe@=J02R[ p \a)`.bg[c/E{ RsEr#40 FWy(hJd7Z0u ZgQ TzJ) GTcR>%Z ,I9<Jj>;.vp X.䒼2 RRO!u[!5vf%}Ђk_ T}`-ӮkY@I@0}f`4#d%g-笫JeQHQ[J-,V$;kF0r&.QC>ʶ@6r̶IE|֑[f6#GSPvꊄ#-,-p_0+mAJ] nڦ{uA퀓zO O(]Eo8S$ iA51Ac% F.*^s=nW?Hh#3增w$& PPlCt= FV:FօSLuEQ5ڰ6clJE(u{Nnqq6Zyq3$A YyW͹Ӥ*3(N a|BpPrˉJ0U!aW;n8*A5Xlk$XG)BE%THQ%PԶ $BꍓHvʞjvT"GlɴsaĤHM\fܓi uyB(hFJUmp&H63h(?d*K wsk/yQsb1dى_𯀦 6,A)^VE.@F9^%Z#L|`pm[fgV jAֳp:1bP{㖫l4c9«Þ\36SǷ}:Ztʑ@4gD@bQc2`D7aܾ>'T2SŹJjr",M+y|P <ždҿA:2M9Y{*q)*YJ헁3* /w˹\gT>SK bxV!;4&ny952#9nJNC=O1E.mi9=#Ӿ#0 Š`b:>T[o KQsw3?h'L7Cd *:Yk<]byg^>@ ].4֞L- 20耈>-mMu:f1w9񇃭{PA0 = 7Hoxd'{TbN0 f qgB&4.oTEŶk/f agFF*\܊P~i)Y"[ :Z%)G< :QUtm)) VWUr[Z+̅Sg0 2,k-U[6;Zw]Q;Q+;:fvi6ͧfƯɄ*4GM}Z-7ݧϋ+xZ\4Wyp:!FއPK/xE\pvsvg.icon.dc_motor.svgYr}.%a-yX)".Js{tRU&˹ o߿vw|}|O_n6_nOB{o W2zcDIgwoLp_X}s UJ)O?v7bȟ" Be_lZ+)_J^wHae.)ּ)MwR_JBϟ'}R*hܕ†8mǁ`LgL*HX<)i o MRYN&ϫy@ˀ1& ocEhӫ#藒 EgH{ #jޗ/U: '| WAX㌝H9aU|700 4ըfKB Ɏ4V5$2(<'"E3'#Cx6mŸqV0@# N \Dd87x`j =)aDs~ux.tMUUyO*\| 2܏W6* Tȅ T`'eV& D*"`4O&Lg%vAH!t2С}q@V'&# [P1Eg{6q!ut e5j$J4EXԩ7r=T_E5BZrlV׷-}VPҹza%Nh\APo&%-MMCznK{ +.4҈LmUڊhiQ1@?D6'uh3։ȍ6[OR@h2HᝩRhi{߃+y! I9IV c5O}-50ƥY+r\>c{cB:D |&#U8@sB4yw+N& u`7a6$g_eڼ C5F뛒fCf`l;nфyHڥ[yYVp*_Yw“B(:GbiS |DIԵ0º2 m L$.PP(0ҿ06.Bs3Zg#YokټrNzg` _@Ä0MxCh^"ƨ%sVlѱ A٢0Y #MѴhڵH\16U<:3/Ș=?w Y"bbBcEve% uUP?OlUmOlOj•IcT7*F;McLD%BPs͎tn.6vʼc{?b^9ѭF ar&00Q* H6ogu#j&j™yΜ|,` 9f]hDB ղ)BF~E7bT掮t${FEAS U7*5vÂ{v>tC3;ʢ]2/+W 3 '9nִZ^0'ĖY9G ̽zȮ`!1:5-9ZgWrQdOg!thSSȏj h^eQm9R>[#֔1n+iwtl9m m$pM./\| Tjg؊qm!Xy!%؍bjO-dФ2fYX;"7Ž 1Zl;Ό['t3< 7fIb+2-zgCO+(4)XW2jrV^-9Nrx% 뗜SP"DLouyAXO)05.cf% HSb 8b\:R` };׹PcъQ:iek;'5;s!-&au aDc,Q3[=S~"\(T ᐩ6WA+BW^Q'-OS~PK/xEƚ5d-svg.icon.L293D_icon.svgUn@}W~x/qdU~w-q"-f3snwyJ"*r IbN&~? (WjʴJ`VksnJغ"uDbpL,I,y `g羉9bå4^`F$a't%C\G\wM0p,,O=}e?drkaWE[5c2jO/,6 ɁMqACpi:ymc X}ȥ ?xܝ:wee.f И{l Hq4e(attl狄RpP[&%ßLoqGjf—ŷ J[ ˛^cC,Wx9dtSy7ϖja) \'q*W=9YeEbf8$ETZ:DlfCaq0$C#F[ +鄴oA*G -I\LR^x2$ZHW8ӵZe!uň+IFerԢV-2:BWG pF8o9t$eYeɞ;{q_fL%$I!&41p7DRG<%8B2MF%l5Z(e"f0N-W; re??PK/xE^y svg.pcb.arduino_Uno_Rev3_pcb.svgŝG?E/! z>D9͡$-`o$4BQbv5ZϗF菏1jYxY]\| ?{.ogw+ EH.˿J mѫ8j>m?_tZE8f6yuهoWl>tv~ֱ^Vls'7ݥOWْw1Ќjsɘudzp$cûܨIlG6el >6D|{^wv \|.uxVpzsA+cuOm#BB,ӂ #M$iBb뻫U<w*|!muw\l d[]2JdAU$9ٖo JdbSeJ!v`+`UxDckV֙ 2KN%%3P/pd'fF^6F^k_J#B 0h V0U Mrvsrà'.@ gm)!iTg\殀A#O +V(6C,+C_E>h|k2eU\ N\m梎ޕ˫J"/|@b#,%Ll%Iqn*mLW\g~c,&z+Ȍ6I2GRʕtXzofڞ}ҏսIo/%!Amm- E7>t შ[9u:`#'jȔ".H*`NR񙗤6EJ)'~!S)XlQ՗*1*:È-zИ|+ A3Yt~(-!2H0`X"ņJL&Y|\/iyfɗ=+bHNUaJOv)%Uӡ4-Ȅ'j[p DxZa˗fx-[ 2je *ʶWjA%Zj3΀2F*np KEO`]ѐT(,ָ)HsR?_ Dtei:`e2 s7ԱtZ:3i^KF'RgXåk{X,K 9TjE0v䰶qRgXO4Bt(43,(ʠU1ޖW!cWb xF9l5<0O^C Q*j,h(. mp{0jߡcO3y9`j %jߗ#W&oʑm.#.]_`By#=׀j0{Ey̨VkY,PQd @?lgyTV3l@-38{h(.`pUF/}6f- QH-b}Pcv;&y @fjf} | gvu0{Ey/+JKUfϰO*f}`Qddb_VOTXV X= B%=~mUJBы|`NMGg I gi0zj>ԻҐ}5,/7үcL;d_Ș)~#2FHVJ"{̫nv~y垙l^ם__ m̼;Ъ-m&T6}P=ݠKӭC;kh70 rխC{$e^yH;m^yHhb/XL uU{wp%c]!W*zZ6_}FL Kj_/kҏ6zOYRzun䘀hK $1첩e{6;wt!lHW'er쓝.6={6@}y<=`~EX$Wl߃AbݔS1q|?|~=RpԹ!!ي_[oKmfd8K*)c$(GwL4\@@OF|y5%=\n{mvW5z4l19 rz0M dLݓ(#dH%SJ}rSf& a\m׊|+ZL 0^@d_yD"_uA/:M kO.6}J94gC(^zO>!ȳAߓAF?lCFp dk -W p8+gy)ꔜgzEya/!_4./W==¶}\gl\xxFzu}z{5z{^?+BH!l¸m&M~))V|tyoŧg?}Wmť5V"2>}hJI}2{ `׊`'s 0gqO:92Q4q?6ǎF(bAB1w*CK bsYFlQĊ؅E)c2̞JQĆX~P / xvM Cd12VI|# XB#3&"at8vZ{pLw{JwrQy 8-<-/}~<<g^<坅yZf[PK/xE>7Ղsvg.pcb.jumper_2_100mil_pcb.svgSMO0 +L.IiCM8B$% tv6!l'{ω/jxUkkF@iڔ^Fk 3}Ե$hhM B5JTZiO7a$ٿ߱C6JJ''-UdeaF(FH4+f;;';FPuܖ}H˩By51!& %Bo.*]̾,1ƛ #E]Gȶ5ٷs,g ¶9>309m5rjEV̹j%vK1F6@0c5(,jeγbqȑaSp0ټvGX곹fL'{ڴԗE+uSii,fu{V/BVJ`frqK2Wq;0] ( 8)5}XPO:y`>~U_"b*iM+VQq3-.ۖ(u+@^x$ڱ/!S ;7$ ^O}J|L(೬Ml4@q澂 @;~Hl7M/VxߊמI\EhwUuKWz~# P?@:DzF277RWPK/xERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svg՜YsHWqU1 ȩovsxHXV"_=\"֠]Q ==7K.HVau۰t-,cň*`G׿FYi0a.0XW^Bh'ddm3nt QL, cj8].H\a@'V8d }vdq$ Lrfxd="!2čGm3#=Hqh>11Ǚh}6;Lrϵ4=&Nn|rs/)2\ygmue2Vj3BڒMӹjN6uGG0q 2e*$X`T+$s)+ZIƾ}\ f6g>%6h;̲]_rY"rښ|cqY{6'?8e`Y߾رv$|x0+s) 2%a*S]׷ PK/xE.S svg.schematic.dc_motor.svgVn8}v>ZIQ7rqqt7@[}Z(2m%C/Rb'cú sfkgh%Jy<)&*ExYO,t)sYuQ_V,[V1!Jh}_͢(kt-gU1GΖ* ze?}@jn>]_ l3O&#̶/uz&k̾,EG[;&1F&S'HM"|p4U=9TG'NmM}, C۬kbѷV:8BߧR:<$.JY!ҋZ6mbCu\n\Zĉ𢔕,WR33tTI*q0uNTeYm>}C`Sb>AenB-Noah B X.bV.N'$`N;}w!vN$KbSձ<&KulT# %vY@ &kSwlk>j MY|+3jZiڼc HSG)SE^[x2PyYG]wT4 lȋ\֤&"¦@w]t@lW@ k } \؎b`bxǨM`3Ug9s#B 4c: wmNcqxh0CxN~ ]fQXD[teBoE~>4ۭߢ >?(GRJhE6~qx/0[8)|bժ;{MX߹o}:Oz~OPK/xEf H-Bridge.fzPK/xEDj" fH-Bridge.inoPK/xEug6=$hpart.arduino-shield_r3_two_layer.fzpPK/xEW Cjpart.arduino_Uno_Rev3(fix).fzpPK/xEE]Ş upart.Battery block 9V.fzpPK/xEQVC{Y xpart.dc_motor.fzpPK/xEmY(H"kU{part.Half_breadboard.fzpPK/xE"&_1ӝpart.L293D.fzpPK/xE>6Kz.͢svg.breadboard.arduino_Uno_Rev3_breadboard.svgPK/xEx )7)svg.breadboard.Battery_block_9V85_leg.svgPK/xEC$p~ 1svg.breadboard.dc_motor_leg.svgPK/xE%%k.r%8svg.breadboard.Half_breadboard56a.svgPK/xEм"$#egsvg.breadboard.L293D_breadboard.svgPK/xE; % f)"lsvg.icon.arduino_Uno_Rev3_icon.svgPK/xE}  xsvg.icon.Battery_block_9V82.svgPK/xE\pv;svg.icon.dc_motor.svgPK/xEƚ5d-svg.icon.L293D_icon.svgPK/xE nsvg.icon.plain_pcb.svgPK/xE^y svg.pcb.arduino_Uno_Rev3_pcb.svgPK/xEqM svg.pcb.dip_16_300mil_pcb.svgPK/xE>7Ղsvg.pcb.jumper_2_100mil_pcb.svgPK/xEr#bsvg.pcb.pcb-arduino-shield-rev3.svgPK/xERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svgPK/xE4$²svg.schematic.Battery_block_9V82.svgPK/xE.S 8svg.schematic.dc_motor.svgPK/xEGq+!Asvg.schematic.L293D_schematic.svgPKAfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Lauflicht.fzz000066400000000000000000000575211250202676700325670ustar00rootroot00000000000000PKj8D&n'\1 Lauflicht.fzrH&wNϘP#PS5cY]U}&{f)SJTVRf]j_aDn$@R$AW[g}/헏wϋۇxf_opn1y}c ̾τ}6 _d/gwO] 'nOrvqw}6{}[|u{fWx7~lˇL6t&tQ4Ѣ/?]~|=\ a;ݍJ qŮ~#񧳻.W=ů>.:;7_\ٛ/_>\_˗ˋ.?z^|{qo׌qQW7WwL3}}^+yՇ_ˋx[*>|ˏ`gwW݃o?_o[of~)X?˻?<{I<=|EG>,>^^ue +3KϾ˷?bɻŏ=-ܵxZ':P|W_5e[$,)i{Z1r6#Z=䯛+ gY{ G۫ -҃fh͹Ü,=Tޒ'&bT'ڦS Zzba% +%LxrmaqSkSs쉅ń-=X’'<61KuiS SߙcO-,k鉅E,XOxmb0t}zʳgL@6\ȫfѦii~革AjIzZ_}gj<689cڶV|uFyɳKG|yXݗ/Wg?-t櫳ۈˇξxZ<?-.~?n~{\~_ܾ-5[yoXnsEBa.;֧K(agjp G"Weօ>wLZ'.|wO,񗗧ۻSzp ;=<^^ݾ־MXA.T8ꑅn%x.SFqEzko̩~Ϥ\//ֶˋ0]գCի<8P.g֣j_cwFۦչ=D$ 14퐥l9T n2ݎ5Ի%Up,YޡJ1ߪ HZZx/ kfY@\AYAv\5$GKqJ$n e$o7O/޿oyxyS<+W}|z8⫳Sh'<%bա9wlE"=?4 sϓExEZ^=V?<<}}yp0Q>~.*˕8dM'_v |Df8miŶwk ~l~C E&X//6A[U ݗץ6WdW^plU]LE߾ ӧEM%2.V-yɬM.>Ly@,~yy,_oWkv}Կ/~}[Nw2g' D%TxtCM-PS _M"=>f`Q;No[N>+c5^P Gw԰z-Ih@_m7m<'"I84?~ǯ0wٟz~qxm#BC%_\HyDaea#:Dz!=ܶ43fq( l 6_q5˭ܴ9TogOB*3{7˸r`+hKnͫe&08Ba*؝gݷ-A'g& :21f˜X*o]eQE,OKޅ_m3$W\ K? ]WZ^tq8 ZlOj.yHelOVx Bj4# '+ UYY޺kun#XSXdR3OR[$ YBiz,GExs-IDu*~ݥ -"&[ڻE y3籧3 "(2}"2w"Ȭkг$0I&#Ӡ, '+#UY]f53Dm]GVua3|3IG>Z9E9QG#'ґԞFԑ9&"\;tcWWʥVGv9 F}zt-]*jUjZ[j:<ґqܺ #6WӺԑa6I@J|$dd* {vZrI" "˜gZ'HY ru<ո62,  F?||m_`"bsku*TBߙ|$ a$ vzI!Pkj%I@暟\S@ C.8<|B*򑄄UWD,3KFFcHT޶~FjǮ$vǞܐAmXtuZ޽z3Z8! Hjǫm4޺ՙksЎ9uXdR Z}h$0gH[26rHzI9^R8vwjfRdVvPq&Ўȸ~C A^7"L# ifh5>Yo$$"JvEVa`C6~FVzi@9'h%4"L Y7CIS kHvLjgZ(O/wR?[UzgxX2??{~-}ſ#&%y.`'W:,&8 -5\*z^8@Z^3icCx|*IE2-,agEzU3{:7)t27hA,H5*ɜ+9^,lNC:̻rP Cq-Nn}S+wp(mV`R _yN#ͺM.C\7y yzd%H$=:Vx6atU7RmB\x33{m2)]:6g4cՠaTC2 1:G!zI{68-Z(@E\*I-Ha f5os_g) t1N[\5۹4!ʬ>ڹGZmfUn4W" r' zL\>@JbUVX,T2c\wKZ6~&q$#$薧DĂ@ IЕFq "I$AOKVI0Ou-acϬ$@'K"s/'u$h]j'@]6̸3~Xhr S ?'+@UZÍ5aح@+%H>b:9Ffc\{"trAbڌ]HXVJ# -#i& &x x]Ƕtr;KeOHVQ姠?;j+pt nY?g& y- >gqH~&yZK!iRGsed ,}rbc/-6NAa 6n[F@g&=t*tA'k2tqR0:3æ\9ҡWNѡ- ^H{]hM*)ڎ(E0FHRh~nq,Fz:Ytr믆LHB;}v ZB qhhzS >'+A Hak$h.A܆*$A`$A W2(1"2ן"%?Q)TBf?OLNb3~h0v}&y&Hv^WΎ]IA4geH>f9\)՟WWgͳR!ǫ?'v히\Fc2FԟҞCY/j|[eiùl0@m~sw3e;CT8쏿9hA+΄qƅd_̽-XB(flG:x?1Ϥu.6ˋ뼣<8[ .(Rm+vlM2a2S?tlK\ȭ,CfXFy<d/bz%6 wٍ'GYoU #^E#qj[eX"XV&tTl5M8 k7|9suy {^9MܵGds剕igsnDE;5;N9"3xiih)蜫_>g!-{GfOwV֦K83C;Yֵ#T4qPfOn $St8<|$n$8oD>#@>|/ԖAMuAa_DE(,~U|a\ug3bfr\\brЮ&CPAr(K+2XS qeg_9qLZ28K#" q~8Pr n:~ӳXWθhh4Q DϐY{zF^h5JbZHzFgDni3O-J(i<͌-DiC 4LJr|<䞫(qw;.q\!1mI[DҐ]'izde*.jw~%ap7D:Jkz05~fGF"jb !dI&%ܹr; jӈ;v 6Uf2I͉ANDGkD8¿y˥t%ȶ;Iԧ|͍-DiCaR5Ӝ^P[Og>2Gq q1uAmH y!KjD"MDd*\{mHP6Q Dž=YkmMBaJ*5Y>"GO %'lsZZ;?bZQuDцgHAY>2=CەGXRCD`bi]tUj[7Q4<.SxTB{Gà ~!Phr5g})f,3#! hB_];k;v v6$CCpH>@U۵GjAw)i))D[ӇhƜ&1lx4!~/?FNY;7pFlݱ;QhҲ ̌J0*_kEg%+zښCV hibL!/Y YNf)o("+;XhXDՆk@,ӇksQo$i]uE"ښL hMr&eB Ѳ!PT)YAʊZ;)fcw"fC2 e./)sFLp-+F!Kk1ק7xDL"b+D  D"_C ɒ/i_I|29;$sW]q&E'`u! ;wqFpk?AC-h 4DRkkM(ikf"`!d .fnMz"`M Al(!,̍>,,BĥEu~-g.S2/r)ILꏐwnz*u^ןy8Ȍ6~A˘Y7.6ˋ1ڭE͟ |w_B|ֺLth'_72fZDJT)u&$/2?2P6\oU*^#Q`4Ԍ#_I[eFǑbG詣8„½d#3R\x@iPloˀDF?KU&S5E%ˉ ը6;:|2PrDX$oZAN$%9 da6#8tfl&:qqL5E&^`H4urW#h+ S(DɆdA:5(Y%ЄT!(ِA,<@-g|dJsb͸3>-EgVU)'iS{J-ԛ?9h*1GAg Q!d$yDZion-Sl 6l=h۱f8D.3q鸐M1վz,W+6ǮLG)@[kqR}oweÒ񳴺)d[Qn&M`Q??!~lMBi{і\232?_̱jYrZK2.A3lMPclMqP1AKd-=9C]Dm{0n3T9G"*CTٚFqPP@1(lUȤ x||\Gmq!۽qP`dY*b2uE`rμ > PC0@Gf|5yymD̸nӺeQQУE" 8L*lNuނ$S}JOyX`]a2m3'wd]#v};\0p]GyjŃޱUDۉ pWKIU~SU;CcIol@^N'cQtz ."fkOns~?uK76xߞOp?y}}ˋwk~z?XUx|zaWgp'V<^,%X=\=ӧUuRuDǬfQFpe)& e3cZUd5g0t $T朧[WVD&s,LQ.qxஸH&僂ɩY>FJ"e&Q!1fk@WUtOF^0n,n',,kTm0ѧcoґ˄j]+7Q\S pJq*(GE|Puz'Z6:vU2Godb%DA;NL&O>5YY~*>r\Ug e+ovQH_ZD,kuA6xvm;zN= TANf U˚EݟY62G3+'Vm{4h=#R4H !AgkgCBi3=pAl!vlM Blu3>2; vEXYy3iqY n?8ҽ'ڡpڿڐq GB5[?G[M░Ɩho ˭)hMSl> ֶJ)r4iVpD# цhv8Bٚa8Z4Gɑ9ZX 6JC53&*,G5`Vb9E~V egkgCbi37hAl jlMBlɃP35.5+N%4e9cYӒ#v՚qeYRag2G@ Mφh@QfkhK ;S[=2E#5gmU8ZӔSoIp4;,p4#&su"p8ڿ8ڐqMEA5[?EkR4}eMTBJ:BefmKj`m^TyuTș!X댫Vz*0bgI8mzk'ũnC-hѲv> >h銆fF;2 +F3 ȭEDZMFom]xܦVmdq(+!vDÆabthXA4l( VѰ,Fa\cc#FQK LXBVebqZ6IbbK^;27#!dy3 *7z AT̰P|d*w4a@1RCcCarOqiXBU8hl; 6x5Q#:d-N bb}1XТc#33; YBF-bb W,<}&6@dBkfi%ss:z)8NS"e}HYE#2[-=[!c\2VEhYB=V *psTh2"iY@a9Ѳsu Z6p,-3&D"fCA!fbdbJwm4qF,*G OiZ2SbFV3)rfX3 zk4-%q2d}q8YNdrdN4vw"[5+-􁍆li50v3 cq!`d93 R7z) A)qI*g\%vU #0<+bd)H:ZsxSvĬB]jOr.C˸f{&Jo J6nx 1ـ8B[Cfb25-^Ŷ=ȽCk,v:Fx|Gfr̞PO`I<ٚsGw֎&/.䇘*Ȼ*bw hYofJiZ59ї ݭcר&Cy%%nR`BFÃ!VŘPxb5=# ՂLvƮQ9\dZ%MsQZRf֚GIsrH[M،+R2W?N(GLHe;Fo͍L(2sn*mF--clG[[ӇF2(KmszY YC dj45jng䢢e gzuq*Ɉ6ua;3xmPv RwMVoy(X\\43F@Tkg'#]w|մzMqkzd ivO- .WMs7$A\7J  ]x[bJ;[Ӈ5ꮠ6^P"achƕ)2ڿ@`r5=3xAl ~lMAE2;l@WrBltamqYfLB83eYbh)W 5=)XC/ԚNC1W:M3&Ӆha{[+vĄ(Eٚku86#s{5Y2|iz"!UٚDBhRD A7(/]2h0Bt092>!R8v)lg:e鈋>Ab2FM5k,&X\YHZI$ٚ~d &N.E'Cݫ!*$j'(TqP|̔H)cR.F'̆Aذ mrUʄ*DV{lK'@ gSBM`DYA3Q-)̙$% @NLO?=H`{2FLELk~Kfr{>K 1ZMc Q3"jR3)1!䤫x5xXcDڪiFcBLsUBe?,c\޳bYG nqV{cSB(z艢KD1꘳jzM&[C |ԴN[[zF-!Q-b0أ:n`0Nx < 8Z@ܬaImڰ#F9RtTr(^^KìGvV ȵzM+P :}[Fd4ΎLZrV| mM1MQa5=H]rPaQɺ &"C-Q"nfkzS}x◗.ƭH۝?Nj?G+q{|z⫳p'?C/ʌZp m/EƹQVK._?_^?s_؅? A,8o3lZ5sR ó/36ٌK|^o|X/G5+Ωtԯ<⋇ͥO_sϽ}?x{}}_M|zs~"~lMy%g n"i{xXF|~Zw{N#>~OVOjZecT~ B9,ܚ,/2jϦr~s?}|ߩ 0ڴܲ?Om86, ǝ̕p>YL&Y.t;Ǥ4˿0xz}wo\h_Yh -q#K(X By0kt?;Ep@e|OE=伻[]^ç(]GlPg"΁T| aZq.?.?Wy&AЇ۬0Ҹp 0& __6Qo=} <*p0FxFS~ps^s@+ -F 7h\7L6~냩?JxFKɋMsyuэ }x64Zy95B^~aGu.wG[!r@i*k/?L\;D{l "|OrПwG8 @831h+^ ]b `I{Zk#SBUF5>@K>Ԁ#I`2+٘0'/8E^xB ,a.4KAp+`YD$ )O [P\[|s6~j.$0CB']C|Q 2>"D`h!U|p nНWk7P̹o|U;Ov;--4S`4:,kj+`x¦ra>T]ϫgbص/Y!lb4sյF|c hW'8jV{ycC29L GqxsNJ-|ްO/w#]ENxQ.9h[(Ⱦ4SF2?~S6؁ZC4NZY^뷱C ~3/|F@/|#: A 1QkH: ҍnىp p>}@q'|Q04>]%@9 59p#kx=ܨ7rW xS 7 yO8sNv]ޒZj7>>w'1 ])%_"BdWyIXW-a$L28 L~1Xb8'¢f,Oي˃}_qQtygd3 Z@aCFS F2]e4xnK(PPFE(0]  x- -!^^;:uBLj"tBuy1^滐4x&4` |Ʌ)`9mR3fs\R5ܙwN,`aϡn <͡nh»WѷjzY;53oxHjϹgޞTsOѭ 1]D:r p(^T,zk 쐲9! hw&'.(Q2a0EmA& x;|oOe Zd}UP"0d= < :@;@iEn]":t0B.vpUA bt(_ @d'1b1ݰel\"#r#WՏ'p&[ G=BDW t S01Y/6Ûϡ=5?c]K2XaDt1y91GQ`ճ=RXSP1!RDpH8X] cK)g50- )Byre#ss<X 4+bi (U%h3"(Q ="){B!|^ݷ_,hH ,fO@*"" 6?Z6ʼpo4{tu>XD'P^4 @;ѻ&7US%|I71)1y-aq GDğ*=,0}O1.q&b`m;CR[n]$ 1k3JUp31Z1ZŇuԣF?cpD n@:/Q\bی H#/ 1C>`M$`eE⿨ŃE . SqK4 QlQ; 2x%xHp{q^I:w-(+h x#LTʱ'4{4b "u>EH*þ/_ z|Fm#NRƨ2G!:T;snB )KseNPQ*Ί P0t2<ΆUx)4N z] eX-{^sмJo&ۿx\R8OR- !> $/ռJ\M8]1q1eXjL\C.1CaڙڀC9#Y#M\cCw~l)QhyuPSk(5T}-Fl e/j'40jDeTkFkFEm1UFu'9Љcg&z 3x p(p{Dd g27c7-Q Te5;S=#eQz!GlSXdÊ6R(,?fJ9Q8G@DR<9&9VTE V&Om èIր~b O%nTdk䰡6E'2,b+p}U2pN簘j0YLM\킯`9Q+x& ~[{!rL<~pw(͋ ^{r#)@+GD%~T _i,8 Κ9*p$ ! ^ ȔDY1n<*Y<gKiok| u9C1`'_=q*h'8'Gx:Y68BNŞSc:) 'I,AA`+aNe'"9oTA((cB;(_CQ~4eۯV]j%UW[F(uŜ95T)m[9[0+'G1Q,BAmo^*yLpkasc ?.&x Xp Nc1%dfQ/|"m*q|l"2 偧`e#@:^m9 lYoϋ_/~ŋ~pˇOww7勖5*L^~_}շv><ݾƊd8 (kk.Iܵ6e12\kOεբs!wda+_`?"j4\؜Xu r CE Uw FXڗg~GS[&O~Y/<2Jby7_._Suw؅ZfC?\~zY}Oko:.l2ºp|yyx8q\s"~<aޅe(?JҹEqܺf9}"aӶZ]|Wj҉7yb>> RsjK+˜_oT(%5zZN/fhʏér{< nB3خa3$r}-_g_+)b4nJYm>4.l[Hooښ|$f^'kf}lf^'~k6r`f^iљ&kfwf%ɚ٭Bfޠ$ki GfyO̼kO2^myWžߓG{lHڄ[|^76YA)HjzRCB:ފ/8l0fp쿸xZ~ sYWcfᶾ| \w!_^.go Wq<˫ۗ_aKou@ 5J1q NȦC72Q ?{"@2lbb1g#867:nlgU+K;ЃHI3!ivLVSa=1pahP 4(Zz}TqF/m HyM-$C֛ltI qX{X Ls!^1[Å'ai%slCHw l| ue^apˊ2W_pk3)AQ"pv"^LqpBzW-.|euuԵ+[!USRy橈y&h5&^mg"[8 n>2Օa[3Kl7>JgcǑ(S(GS( Lauflicht.inon@~9ʼn]  (4VDK%PxbYGFMg%ћ_cǘ$X>3 <3G'L,'S&[i 9>B5fΨd& ] =)k{J'w܅OJBdL1U|xhCq=X<^/08 WNi=.,|a;2~[e9E]7 E]g^Ro2 ܲ# ,V7\\].-sD5;Fv NME߮iuBl%u޲MeY?,YW1'P]7OeǓ I0E"(wnD+dFţɄsV s]Z<7OmŠQRviK{nZx #|RŒLɪ@ YG ? }PKj8D&n'\1 Lauflicht.fzPK8D>( \Lauflicht.inoPKu^Lichtautomatik.fzz000066400000000000000000000456771250202676700335700ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/FritzingPK8D ܳOH+Lichtautomatik.fz}#Ǒ5wl3 +"glǨ5QQ*(@Wo50O8d&( 3#s#<p6M'__ф\uf47տ__=Loޏh6$&B&V^uFC8rWvW<|ʿ]qy?L{3ޛߏ㛫b շ|џ ܯ#|,R1RU~8_|}%8Cץ}8oLrKٻ CVQa\$\'wwyg:ᧇ뫫}/s'L'}rwEi ϟ er0CA٠?P]4g{~>Wס)Jx ?^3?n 7 ˫λ෻t}FN׵o;?_4>N;tY ߎ?NCu7`wTl&4hd8U~s↤`WU:vJ~ʟ91CiuC̍7[rȡ\Ӈ&7Ïn>}W6SǛw׃lxc|kx*Ikjeuѧn~c46?Zn;p0\>u>{ؔN=.%U瓓O!q ˝:%hAD%пP`hX=PsW^T~gPz=T ;8`28Yф{>G@OaS6yrϳtIu6lW;FW;!;i:{zUHm7u&+\6'-*֬嘢9iW8Q2dxqE6Jq\'NR[挜6WJq[3&>nxv28myWqvO-iQaHYFxL+eD v>m/Jmi;ɶ9mqWůZ-ssN%Ψ_R& CpzE?L3=YmŹ's_6%Cē/x6a_Vl#VJ3[f P{Iۄ}~ɖ&mĒiBy%-3UBivyO(ivt6 }-Iڅ&=e>7wɬ9$5ל3H֟$+zSgg},Lmy#i/uPEQ{.IKe~-IZ+=}>meˌv"y)i|VI`畴S{fIKe~-sKZ+=}>w)-6q V1i|I癴R{I;E~ᖹ&mÔm:ilx댓"+=m p~؟-װ%w}wTX<3=j?,̞}KQ?^(Oz?OOo7~?3ni睇؝XߕSAܟM?->kN7 hiYGjmB9&Jݽ()vIrwo덽:̺S6Yt%q3XX]`_NI?Ko2%ΡzUi.is$zaT%2 h)_&ɍ)V2'k8+dJ1HEw(5)Kz9X+tpභYAn\d^'!#2ʯPn%8' c1)2}>n ? ѝ$sUbωVdjيg0YӀɜ S3 1,{HVSB)Q}ªH~ƚXQ_/& f/$ DbψBV 5TeIOAR%fVjwcrEdNNF' &R$Df~ˆ3%fU8GLɖU%\X0TRX*sP͟N3C;5NJ~'+v)n[N1g iK*V&A2҈#}6Q6Z*G#OJG+?~_ OFZ_Ӊ?GǛwZ{wp6\q6uh3? ^]uGa矕?k ׵B|waVƴ#& v#t:NgJ5N>Pe4>=wSpSsZN^?E|8H)Ph<"9W!ԥ8I&W5=?A`ӗ;,joh]+:Rqc4c 6x8"Qq洺ƙnb:D_j€0*21 R>{ y@/==%B{;~>h>z7vb~Pr_un,-pSEU`:oϮº S緡k~cܱ1 F_ m}_\xVsMFZF-z3h+.g'jcD?𤬵ǜ&z *REe{:D N.a'>&QsUZ!/L.PKTy"Йx7ͪmUѮo˖}$l 6WHQ&6)z@hEWEg]x8BV#Ka[7˗9}or]'u SyL&򊄫gI ;>$ZL _ϯ*>6[+Y(n ))kˈoP2;j /&UB: fK׷N V3jB2tvרV&t@o9x"XӨN%odL~ue$?-\[?SKWܥ&dJu"s 2ˬ.cXIfowzR6aD2kh!X[+kJ @充hP hbbdcN m-DvލIlsJ* aXN$*&bRaMT`5΋/hP!|UuǙn v H^sGl01rƠ:f1N&J%#1Դֱ,oxbքE$44KI41iriIVZǹlz̚]g) ^tf"Jpq"EL,EZ.QEN Yaz$r$U6V@X}OU6XgZeiӋڐ%uymb xBM<#9T%DnlI ;lIU7ֱxחY2Zm1u2!].8V "+N [[&5::H 1'#gYL,YˉlPC}7:T4!,qT8MI1)1x*TJSJ=kM9 ()l"&)hYϫ|ҀNQE"yX(+#At^U}K!s!h9ZiL*ڂj¶F]E5jjo"IARwƓ,j C"7(r2Gz[9bALUgOS.gY_3iFH#tJ577謔_Ϸ@V;, 83abc"/]ۛ oyi^.V;Gfؐ4ɺn-݂&JuCIi0IiiI>ΰ$ QhpRW9%U'N2HpTmozZP6H`^-N<iWQKy7],a.]xn&GNZ,aKr^)[L7<1X8`-鿓ӦKQ;(v|DVZܽ?wkz+¢r.ctw!vmh2nqVzs,iWml L6tѱ%r`bŕD :"w>"w7>*E-na172L%,tz|ϯP,]#T;ޙ~_Slplxytj7Hr^4>a$!IϕYWlDȀ"IrHHn:eHrZdOSe4OWE?a 6Ne Ve$\2e5:^{˵s>o"U\ӛ↧&&@,ţCw)XduŦUiڧi|ꐖRM"1mZ0}0ʨp7G,$4<4uv!+vYAFPUdIŻ75IdgF+h$줥݉:HvD:xYbώm\*Rn3xSf[)1m7Ǒx+/[JX!%2:byz `EOc}Jj{s|YT* I58w3$l K(TWvȨJ8jt{vm9nicM&%KR6h E߂B 1M,L {$%pm0—ԭG,R#\\JwtyCG޸)y{/l~}џ\Fϣ];vb:ǿrBrlzGŇэkuМo'~\ Uv:Ym5Yf7{M~6t]G9nRV 3zFWfxgPӰH4Tle^`zo:OUb>G7zrTpS-\[҂sRP%WyOtw& gm3[/g4EyU[Lii6l֣Mimj0p>vOR瞅&*cۏT:lp{yy߻o?˰u߶^3]v Vxa &TI4hI%Y "O0c #V6^ `LtV@IZwɶA?ȥۇ+'W%ە9>D&*% 39UF>K# F ?e6xY}J[D2w"yi8*8IJ'hD\挲a@pV9T_n..tkFx^XL1_ZD:.BV-nT_qb%\!n6 :R]IO:%4_4vŴ4jFG"0ysU(Dzt|ԱNl,' L:VO &Kp(7jz$Rro(1*}yi|!]X"ѭhk0~_ 6g•㎎*Չ(T`ΰ ?1G$nAb.@؛ ,g&DqUlY@imTxp}o=ivR:a,£X-P# K u,$I"$,D*K}!YDPUxœ{̰Grc%moҭ&%IW$0$.vGbyYzjN*x +% {kDj^ ˔TH-.{-en)2%'C)belJ$p\ɩI{ Č۪h@t4s;jBmI% )cђJ|[I@x$ά)X{ޗچ<ɺkyۢF&2!KdruegT0\ h\7G[UP7鶫PIlP7c]7GƳ-qJnCDne!{s|mU@dbe0jTRq"u;Ren9R6l'uBLqCHD˦q%ꃑj@ʽ9>DF N5hf\+SqǂǦi}4qRg*@JgR]Ϸ Kque8[o[ [7GHVM7LXݧ6ĈqW `Iì,lBK.kɔ#Mҭe+1l7GvdfU̬!Dl~PYM(r7 M56W"R,]dg͑8۱]$ ,-Unh"G m7\TGQ;IZ$i'&-g8Lsfp VƝZ!UBInʼZ̰ ] 3`&RVK\V+\lM6D:WUkԀ&1RBlmޭ0W:c<iYǷWٱJi7l'U B"-vZMqz`"R"fjDK"]ӻOKIأgSIgSËOIaՇ Pí`F/_~?/U‰eZcܨQl0ø4G_Є|Nӛ//n{%]篿|W/z篮{]ooЄ^_?|qX<~y}ÇOf`~N'(Mn7_:? 'Yȗon|ա*! B8-:4$[|/;Dh|!z8IL_.mL&ށN&R1>??<~ ߤƏV;n̈́+Ӭ&m?—ߵ~}M\{;S5 n5=vp8{f,ֿ[sݐΞB ;^wy`6NO\&Y9-~Q |tv4N;!Ҷ,LB2^Hb8u/vI"uI}'FL=(:p{ᎤX38ACNSJPf@F)?k8)j4jrnpSu=wQD' czJ?WB_xlnJ2JI EܚufؽH`c'"m 3߲I;agoCJPVROp5a±kK˝|(*违{B{X\ wop<^]e 3'1JIeƝg& u[ҨϝTø{JeI@7d8 PwK_3s1<+\g(9^k\qGNK:1;=BnD.K"۝:chWzD~VnY"[w^[>UkP#oqo-5Pҥ61LJ>nj NЀ_>S^C v h_|LaLZˇ.-< B2cc~_q?ޡ+JB"Nr@35Y6j0/UU,{n'"8^`6_-mw͈y  0wOOzSKY? a'up$ߞ ]z9= g/b"u\c#Tc<?>-Khl@}Xa!=m`Ra0-a8ycYc!}kHF#S"Ehr1sGK(>e]%@"FX@܈7Íxǚ n@2)3áݘ+v|ֵ-vx||ڹO=ڕX"]V LȏLLJ' WťO$c"+)΅>QOFuMqǂb 02Q eٱ&O*n~tOA` `,x42hn)SY0)PkL0` XЂ-@_WP䣐0ѩ CϲS7̏i`݋1.thBC-m\f5 p Oǃ( HSw} 1  }p޼k:U@0-jSwj1oG)MZ{~GC+ M2er\V tb4tW9*i Y g)88!7`gAGg a'R!|!{ xDA14,&4 ce˂Sx7ßFbY ޺g '9߁wU w-`B9$E FٱQƱ;P#HÓ*³<;(w*Bl@Z{ J ؃P>=`%B 1܀|Mr19*P~GA>6&PFsU?+Bɢ!2ipKA'CK@ f DFR*uhf0<`r4hKD@lc ! oC'̽J >Q3V Ra{Ļ0VQz0X)D;Cë{UOCɩ_/ %kAä\T3GZ0P  O 0U9 ARޒ|ojyex;u!f8J0,nNba a^!\Cl=haC(` xQ0QyD#!n8kXA܆ր ~M7.2Kx*9{dow"3jуV.O:~PR ]KݱOr@p/p$I)H;%DXnFmh#u:)U``C<YWdž0J`Zf޵)YtiSy:}SkhtJNmKr3oUIΪHk Sƍ@FJ]9q@j`Ģ f9v"s7$QHzeCT!Cшyi; .DŽCd`:͝ƨ@ nZKF1gA(h$?F67 -éahV* G@29y'D}&BA@'$)\!rEb gc rD wA>5N+cKȑk09Ǡ7аNuP/ `b1KSb8 p«F"A1aC C&?G&@` r`:^a h,Ih`6 '?ɆsBh4Ʀd0C`6<0_[߃fu/7FB$)`iFnC"(tФ] 5(~17y/a-ι@@=S[A18yVo%O)Mз@Κ4 [ t ]06Y/v?c~/5`RхV9ds+1GxP`,ng Sbp)PxtA?1,N朏 ,zA5 J-)DE7erD{-$fǮOhПF2CO2W*CwS A^A?$6Ad3d0yìb/rw#"(8)* RޮjGTW})7J- aN 8` g@;r@AW[d) 6\KvҰx2yef,Ug<7c#^A)2A\߂^EUf!{,ph1>"ނPPoE-;8.E/w\U8]q-xԘj vt\}>1m?VPFqjZRWu,0\ z}XC#i79*t:* { [C}扖UBU,*"V31Љc̥g*h 3(=u2aX6졙2Qnob<z)Go]ݐd279R(,?f5QFRD?vS U"B+ELEY`V'8Ma֤Yk@?5 O-RD0TEdq.$v7 H͙An35:O(1YtMLg0YSdiLV+?Q.v`9y-:4?väcGN2?t,3oGp/c9ai3QL@D pSebE/2xdVmYk_%d2ªP5GÈ8WXA`r0áKܫ> Ta,X,q@~<Ma,Xcg(SBw0K[+EVtm<t'ov{EŴ N1! 78))%7<5ô}i;DS‘f) 2O!ȞxWG4cgh|<݌l-PC(}ohJR4>Y@gZ3|tft"(8[bEsZ+f.:Nc?1qaueA|X#&69uj !``p<*ÀNGӂ9W3I]2 pE Cxyt.lj 9F,cK O☂V[k-Oi'"5o$P0l: #,8Yv ImK%_ͺլ+f]ufhk!Nׄ!Kbf҄1݂^a9p( ~\`48p4nE0! 4&SJfB~!reoLY8p@\<4o^j a+,>O[KlڡUںe>ͯwoFϣuzx|}`1,=8xˏuܿv>§wJ9[9F壘d 83Z q?Kw)(F0Ũw* I(d`~_7YYne+' U Gڹkzx5WBٺ;%Z*%A@~o CG%VDGY 9?LYF%ܨOQ՗c:q_'6=77-TS`_ Gh䍫9`\+=тP 3uwG'@3DNr̨?`w?0_S3yMTKOa d2,*Ɏ~* K*ȟiS:|Ӳ;vf*pkvh, *MAK_W;>;i:G?'jJh7U`:2 Yd1_ PHݐI=i@)) WOXTHwhbHKRen8iZ gTGQNB9W< R]{[zVXe9<#Z:g5א|"/vZIBe7!Tpb-^[k%MNM[FPgjn˾eb2ip(O#:W_ՎJa!e '(D~iMP`4<= *5tX:曆nТZTsB}md? RheOHRyXZ]]ӓvT@q[7^j8':,[Vߣ 50 C"}n\hkԺ"-k;yz/Iη%8# p!R >!$Z#akY TS"a<[gKFWV֋lZ6 oU%(=J;㔥Y2Z #+c: ) q9-C")+8IYI@li5 !)S$Ҳ =EZ*HU9˥QϦfFq2ӐhՈ:"+:.FQ0)cBU`\`Ĭm訉XXU"E"9;:ĬYq,]ִ7N)lAʽ9>zDn*p~&7 ^UIfrl8H*{sUȕB[вz#2CGdduƥc$5GddGʽ9>z WHPKn8DDX|\Lichtautomatik.inoTN@|W죡% T@jZ*@ oxl}9GwkEeCH!DIķ3MNe8VSi91*ñJp=8 6pLlqTx –L( }3q9}lt"O:ϻ^!IvI"N6JPsqt@̫]gPQXㅽFPj#yP`o{[AvEWiAU` > Em{["ŅL5eq5C0.%ѭc_3$ SFM"AT+tIr]JF;7\n;ťz;- ڸ#L'dR9)Ze_]^_^<)$jTwcr- 8c',] 2}EzE܃9SQX.n16|Ŧp&4h7D+dD˫sf7ryA51i b<&11G6mՈLUYF4Bg{ߎW_:><~~6љ{Շ~ŭzDtA[c F@!%OϮV^Gs7˚'ߺJPK8D ܳOH+Lichtautomatik.fzPKn8DDX|\~HLichtautomatik.inoPK*Kfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Matrix.fzz000066400000000000000000001566701250202676700321250ustar00rootroot00000000000000PKj5Dzʗ Matrix.fzr8v.>owxtWЅzSPVP]q?? Wo>7.>޽+UPG{駧O7_oH_]]W?#O}u||o/ txa?\7.~{W0vwUW_n}q}~s?>7_wW։}zu[x3|z|_E'@GL绛qo߼?=/&޽`?=?)>x}s_ &jxw-LwY-?>=1b"w?͛c~WWGV몰}_> NSvޅV7Z%mRޑwoUFW,ɮۧ??|z/^nﯶ p7W7W]߿{ӳo_&_'?vvO/݂իë7}x* -W\7+ZyR3Ak,j}&y]kɶx&I] :e s9kd.j}&\}GZ@:$2P ouNZ d;Pt@u_VHjh)[q윲s9ik:sE1gnSޏh5p&[l,YE/:e"j<}&)\%z&I\)qU;'r#ojI*W/jcQ3I~H63IJB)H $I]&ugoĮl$3IJB)v`IzW/`M6Q `y%s;SY{Jɕ ɕ*EQ?r\?'hb]$eh7`'2-N:厠quUbI+wbga$`1T1rˤ;ùN8%_JZ;U1pkiʝqI@HfēV6#VwÕ$m&e6ivq#$ {h$ @R0vI(Pq3iґ_f#%-LtĀH$>F#kFA[FsFkNrШ'mo37zSMmįgmʎƣy6YLR{:'4ΛЈ_$x3&^I"c^4y0:g0Λ_$} ɋsCzSCLwTrNߙ,!5>8g_/$QG9MqF8wHF/'8ىg|}'f ř3S#t;g)ΛnIbhgnIb/nlyS3Wm$nͳXLA$gsY)-v\7s1>^$g/,w_\Dg֝G5IG@ߙd1#6><8gɘ_b#qI6cs>J&_bcj\ʧw?Wxaۿz}zӕ?5g;lEbS}sVZO.OS2ٿPi_mto>s KR:맋7Vo_=ۛjow5|&Gnx S ~&*$|jLZ,_]N(#b8舶$4$T@"g®m'cwv6՟^ i$0(I ã =kBHiA<.J߂ w(ƌE݆a҈◆bHݱ>mNx(Ȍ  5<&X^teY⠗L1zigGC&on\^_ NURl/ =>4 O@;_.[mEuv٭]6۰#Yead2b 6x1帥A-Iy-K㖔j{ޙOKKZDBٲKn23U}Ù]z|yhwh2]-;IZً~;S"ST2ud9hiYgF+l$ 6x<ӵ[gZhR}!uhrS0kDsm$YQV$KE^3@wDSh%qy怡7Lvҙg.4 ɫD X9fc*> <2ǜ0䴼/C2vhp~ւ*$KaRh/UF2-jŷIEdl)/ 3/ =`4>aоrwI\Ԣ Gã{dvep!%ozw-QeMyˤ*ߘ8_*ݽow{_fX꒼}'5Vj- 7ǻ7Wo?>ݼ~gk<^ 5w%S}=`m$t.>;ËO?}|sO<@{<+ۢyIGkfњHQ,AԱjIW]E 9e #ͩeVx1uX*l-pXٌ7$ ^MU%Jd|7DpEXR) K%ohqt`}֝*]vXJo83P1]l5Uj+AJ* 8Lc &cZU2%6$满SffIJJs6u翡3X W&V4b]rvwݭ1K OR[h伴nhuPh.%KV?k-Q5xVd-ѶhuI7| ~~5Hg׋ʽ1(5zjS}KͅcNLTOTa'<%:67 81Vy@:)KKq=wf.aס-IK=:4e —V*aW'*}ccˀohYNR޵. >]Ŀ=mrTm9jPY4Wx+,v6Ϝ+xxD#V[y&g!ApK0S+㭅͘QwOPVP)R8|Z+(ъAMna:h&Sb#q +;tZfYKRH6 ׼yPuw&tlJLաϸ{h? ٵVs@z!uoGg%v x>{#3H'~E:nR,;rt_䝽ӽj}ozI ؄45g:LOǐ;Ūz[sF gNa \`LW+:Ӆ*x3=>[g:#^ ;_ttp0 *vtz eDOlXٗmY`_:-g-_:'lߗmK/ts}.6;ӳ3L}:ӑOtn"#X%&;p;QKZsgozHfj>w:ۇNOޝN͑ޚ+li×4+u>?]B1Yֵ!kcIk򟳺kt ;<.vUPǕ(\Yqqa(ٕF /}}UChL}gzhgzIts3tLt${Oou;% hi7QW]4ނtF;}w^ߝntB vV7={S!M3ӟ`LOߙ=7}~G䦗+5=in^MW/27XLN_G}.:9} UN8eYыno:m]ROOWٟ8vgr:N_'ϼelyKzyM7{өԬ=9}|O]ۗ?r˕tPvP?qΥ<";ݬ ;G邆tž?=C8ST.IY !ELAEOl0;ݮϾcqVkbvϟt󲙟ٟeO~:ԑ4 u~[^o~:MoI9<ꔜ Uo\Dezv]_)f0tf٥]C[V)l᧑2v1zEB+]ohQ =i>t2zbǥ>.utNO˗:g-HKS٥~]8^ϥ~&Iz[̽ԱlzKq ԭ٠ .u]0gdz;=_0LQOvaNRf(ٖ2uݴUWk!$u ؞K`13VDR.K,Um m;1NarVsFח5K]/~xv#{z]s,u3Mœ׫X6%]Py\.uN%UHfz'S}j CKw٧ SgD+ԭ1[ǧ~^^:w(T9]xQrMDm}Q0ƥkez@pIo=IX6<ܒ6 `nEp_d7N6& &#e hf[^o8MoAylz<?=>]M ?ۡm.j/Ty=nb~䓩av_/gt%-ۿD(~މ k+=]|&lo] Ɯ9͟Һ\oMګIZ `ϛ燏[,Gy=k8(-$1@j;2o `9 \0!tB\9'=ؐ9GžaTf Ī#d ƹ j,EBKib AppCIAgAˊiVs2ӗe%,脋OK`Z5T愎ӳt_S-VHǷ(`K0Zʔ4 ')Xre)WggRSu4"[Ru̷ָ-nurيyg?uxRHGEGbq-&9)tiJQ+6t0RFEfODZ|6K+$a-N:[J!+GAXsa_X#-8/%I̱`>9"sk Yd5cIv%.LbCWp"FJdyu٬$YADTPiϙ*LwgY, .>3Y-HN5:uT|9ST愎ӳtϊj h _ u-Qɔ+6700όr hc9e\}|౔q[P ɾeB}L$B3:ɛ.c+5$oE|&~B ^o>S" ZH[82vRɴyrZl픆9NY/&.JQʰ&2ʂqQBQ۷xhj[9`̜32\1$Q' r2 =WIC؉ȂuIZs sZx9- 9߽;{ /eQ*9g9^φsR>[9`̜32\1$ QrѩsF+$"l>!,=c0rRYEBi)LA2l*4!^ PV `qú*uw혵TG;BOl'C2v[]'dE8{cӀ%Y҅PN?Gd%az)k3CNg]U$I ! NMeħADX4uIgBsewgjٴ\D4`ӿU.7J.S3uΧ4N; L2K: SDM̊@F 8Y@9Q# Ź(+6Oe< XNeD I 4X 0cg1^HƗwg":1$-2EDML,2tC $ Yd&6ʺߦd5&6oXl$.0\s1̢\Kgg\RUK|J%W-eE-ff"N,}Z\Bp6)U rP9w]>}2Hq}̴m:."^rΔ~@ *0-Po0 ^Բ/g `3@$_vL% `CNe/#y 60o}lJuH6-ׂ$*PARI "sfdf{$BZ{ -NpԇtstnD0fT^"n޿tpȉ-pƆCG&ɼDXpe{r$'f_<[T5iPFtsk67TтFRO5 )}{T#wsJe 3r(/NO$E݂#tΏr*sE݂/t.LPmPQ:_leZt~ چ]l,d,>CDtܗ| @P4N'vS,vf8#%AbY+[8)[SDҾYO9bZeJ 6+BOٟ+Y"i퓙r^a F'Ly9N/':<60JD2wH$I yfUo L!UCӇ=_б~؉!r/:=03>0,9;lA)I3f\Y4dYVf[3k]X炱hQSrx 3+V=hy瀡32)YYD5q1J8鈧V2<]`39 IX҈c!=tdy(iGF NM!dfsǁ4q{k y~xeFM??>X~ۯ_W_ti^xm eRI;L ڊǞ }PkpL=mǎ-fjh.2'[n;v) ywvY  :!)(g#džN^Oδ=*N94y9a5+y *vGiDmh*/:c?$'IsG%HC;j}6{DNG2 cHJ8 (S;qx%- בт*a,4w*6޳Zlhˆi>Jӂw,! ʲ(ţBkQѴf6JN_X h0du6 LbCCc}/!! ӳ7j69㴐5^9 }53+I753qPi}Ԭɺʜl^IG҃y:@D $Љ13 eXdIR&e)c\B"q8. ʤ,:tzZ0Lf!enZ5)s'Uv5݀T\iH$IOkD#ks)fdn:=)x$cb"f'ZCHd展g!hVwe6EU7;{fD((Zgы֦hh$IhXpdd{DNG2S bHJ>a%ڢ'eXfp05ZJe mԉ%uWTmUZthİ\z\DPz0tA AʆL)DujdڳDNS{6MbC#E&b#Y-z'`hRAmMe:MOIGpȹΟuq`p]6ӱUDґ`~@ 9,6tz)R IIGP4,8 EctaPP4'nydqJI8k1F 8Xy<Y98$IqD#3BD#$sqGJ>& x,ɖ(8m !$Re(ʼ,:t:/c8O MIG2ҙ.y) b"9P᪷,zh}^Kґ`^G6DDC$s )x$#Y m޺pMqʈ. ѼFN9ZthǬM9Cς?,9㲠Dwj8'ZNk^䊳шBPTgȉvHh "Y7 ,‡Q+-A3yT2wģW@wImOujM35;̪f'.$#D* ]w}*yA E}HUEmɴl^ IG҃X?q"'Z!ņN5C )IvEdg 58ځF?j$PH.'P!E1wkgBiيrZ"fKdhYcf91zr|!IXȧHCN4>2# >t#qAϠ.)2ȡIyXF'e>:=T&qbJ>&TǓw9 '0how&cCɐG:&CɦY rIYl0RIIDŽɐȒlK\ꀔNZT|F#[kAdC R KD!u媲EɐBHB>5GFrXlRH\Чfa (9F؁J `VaɬڅQWbV:7`"~Y J$d4d:>tjFPɐl"'!ņN;R12$ 1dab&p3D Nn;9S8RXeN6'HNZp(qD*XѱPX1X;D#)18X-]>&Qp0t>8 ˊXtZK>3cs;IVHN Zh{0YdH$Iװc՛O5FDc$2𑒴kŇ1AȒ M- VC LҊlLPR43;%iQRWfh($;Hivç O*aE3HWaA)tkDNF2G ѐbHJ> ,Ӗ.3+Q4#:QcZ13O!Rq}g\T=FbK hGY}@l&kC'pI:IoȉH&j3pGJҮ! I)=, (ՠn ͨLϢC'wg xJF0nvRUơbZ3f AlUhgxfC'6 %Hzh 8 LbC'7NJ)I{x ,HJ,98Ε%-OJP4( kZX3Ge0m>еt#S~A.Ig-b -5@iԓX#L0_O^3d *k*-RU !7,va3hkX5iȉvHeہ E]Îާyoe8鷥Y0ΡrSsB@Nr6ڿYth,C,sJFM\߼,2Vxr%,fы-ʊiXCQ6hdb9`̪)X dIbV.L̐4oEJEE(L"-,g19= )InJ3)Ҍ>(ӳS+͐BI:LѰv5"'Z#ņN4C !)IFizYfga HQt9 v5}0Qiѡ]r G  xTaՑE;Z"iH%$:b Yl"'!ņGE&jYQprJa_ Ia*IHKo$_[ugb:L?$mlXTi2-k: +#rY-9ɔ,6trVHI5xf)CA?DOvdK;s@ >)I[ +1eT}o`D/Zat$]1@D$S?bFJҮ btGAr;h?UYf;ZYd֬02+J 3ً@6m1ӦEnheNJґ 3,0(kDNF2E \aBRfX`dIɑ=g8`ڮqhjEvLI';%Q0nΟ5@iXZD3T-p&Fg>JrYT֫0C!4CD;$~fɬYaB$grariO RJlI B2/(W̨+IPE HT"Rc4*E hoxhC6"Ŕt$]C85"'Z#ņNpD)I/"rEf|an1CIW8pR %]9Yt P>nl|liǏZ_|G/Zy8BVhed:) …8$\ja…Ltr '~#~ce6-D#s"_8a#%i\ r0lEJQuk-4B΋_{Xtt2se2v۩da'(rXYR IG}a4l8lȉHgRHIa%b =(H-;ss9YK )Iĵ6Ԝ !/oL,"h9p#ɉX@cm6ܐ͍̼bC'%'"}Dr"Xy-G*!KVFdb_K3!"3O %it/:1cMJZW:D-#F7\}NIG  YMBD+$a8#%i̐ Ȃ̬$ 33oVת~㥢uz6>ӳv$V7,*.p&,r#E3(c4يC1CNA29 NΐGJm AeK ypi$yc=2QJ>"R֦5a9H YS paJN8?pFJQ^V^\=L> G7}:/P20402iȉ&Hb3yč= .J BpHBdz]Gg>:13;%i+U9۳Xf׭iHM #D.3Pt8葎;/rMFrёXld6R!1,б$[K``5 ^4+Xui2\gBW`.1.[EExRJS][f:9œӁt%S<֝aS Q'b 1%OJ"֌3Є6Z0f9uh?0"ƍtL,z `8#I!&v!'ņ É)IHY 1fsP"g2:C5NUJ>&Of,W>T,z /^#a0$X! q!'}ņP;R10$  7Jڭ:"` l (pűB vEviXlC6%iAC>N^0-#2 mDO7>zb=R$IGځEV&hs#r9Zl8RIIG05,@$S 355RP:t"2uv',2 +7Q ffݹ3Ξf{RRahَ#q]dcf:t#a!w1$ȱ:grȉ&Gf`gf$.N7$_ja0FFrw$|ƝWwIBfrDVi}/!9c,LBBnnUإZRZfRA4Ѽ5:6t}N,IG9YMDDK$Bc8#%iΐ Ȓ,J f oUɈ ǻ]qѢCgh+>3pmLZT=RiׄP@vݶ:S i;ڔ2EYRx Ԍ8ѐJ:f-gȉHh)RHI,SKraf0P4(/iȖt望REFw,:tZnIђ>1LDŽ)8RP"Pي%5+̢-fH#a!"acM9+6tRRH\Чf$_zY% U@Ntr"NHLIǐ0$i0@h'jjyX181$:`iFHd3pGJ>!yZxYV[Ke25kNf=jyhcJ>E*fQz\tiײnAe]%X8Q#Iwh^8q#9\,6taeH#%iŰ`Ȓ\l20rĢ6ewL&^"ΦKĔ k`3L66:,s֡C^$,S]CCN442 7I)iW0hF:1%^>/ɬpɘtzw(FdLD 팆D#)) YIA1/&X]tDN4A2/ >Rv? ! 2~Y L?Е9z XN IG҃YX4#DN4B27 }7"Kr 4n1 fڀN LʢC'&+5OLQhŖdE-.[JYxB:OM{ёVhud:-Y'h$.SS003؆BjXڷ1e&:ƙ5`c8nvllhΜ}ԖH$I&fX`d9 -6tzOiX`d)FKF9?T Ͽ^|x+7ŗywo?TTYGʴW6/p{su=+(U07yӇϷՅxOO__~zxϟu??#\a{L SV}L4LsT r?Ӆaߟnoo?5A]lp_&>ݵ%>t߽:nǻooއ78dgb_<=?>v'T~^Ij{&/Oo*ӳέҍÅa);_ދ#Motw=^+uh ,J]Cf24cnv%Nw'TX@{F0- S=YZJT_v \|}|{hA~wqݧ_w߿ã?~o.~/շ?|{?w;D??^pwte^"V>6?~}[/_KӽuAUa|?E~/@rǟ^qqh"J)xV- (hv#̄e-/ڧ;+g_9ݲ~Ś777ӧ(-wMu$9 cor{BDKVG@o6М^;j\Bc_>M*>lx%FgGKFWRd~@i_rۜ!j.EoXK/ a5eŔWS>s?l,N7TP;s-̓k*nsצ7r;F н_.waD"0?})w?RjweA} txmodV^n~(?DD; ^^Gykxx}C/%sH}]2mǙKa n:tQ]l5_}d^O@?L tb*<˽7`Tx?NnG탱7W\_M7XWV4n6+ȫ 7nNI}D.DnIn>Jp˽XoVv"75eOޜY탯ܻdr咚B3 -*[Ľf͏a?ڻSuGx4"[ѥ \W ~Iݗ 7H_zP?R ]n?үOs._ܡ=G9UG}G_V3p/.=b2`Bsc)= ht?/4mt*JfI<~o_1~J7LiIc'R`-Sٯu᩹桞2T,ᙫ?ڦ * Mu#N??h@h )!nk!ƿ;_S$@te?8 @.@2i]"CW˲s{e@1t2QBtnl5ؿnک0|6TYQnzoN>AQ2,p6a^ݽnn{s `nnZ/i/S "(*7+K/ =yO~zkh7r韃N|nvB `ȲQy^kᤪwxڏ_WjK$n{ӛVg_a<౬㱲֐ݔQQ&]vn{vɚ)"Ek>[wM(zkWKx]oH }F5<7?FWp㵩=vu'M=ӎwi1hʹ v7)L;Cϙv{Su-wm!i{bb%N0aa1oq+pR]C sGWo(q.̉znNjS W qmZ+?Lx[&_U\gmecԶE#kY4pnVPֶj'v+P[j dm+`6?gU(vv,B][`K}p翎yF*ȽFgƛm;0OսSeo__fǁW/a1E΍9o@3 }ݪ!v35SPg^R˼-@7_>սe=$t!-M/voy +`;UR{u7dn'K؜`ׅ% _蕦1sLKٞc~= ؃_Wx1lM3y;+k\7*l_E (3SR;exLoU w-~w t6 %H󫁀okew,T1rɯ"x"8v# v{j;o=ޫc`h9G( xk==e:G[P"  cTrO=qܲTaCqk'_(|t藁ڋg5R +x(sL64KDyQym۾v~lbuB =$ڧZnדFUM j׀[O̓G0)MP3W4~(¯t?c@ۉ3N0$xVŸ_XrBR%~֪Qͼ,ٿF`adKf e7dT}-^1 I^_{@\֡Em(oQBv &Gn /DPp7t+ Vl ^[9x =''`w9^)< f>3&V$ e.=RJѯ%[\zZY$େ__N@Z)>} ̛^bY!8DFn,uNGzG&KUyW_~gc`3-NVc f%aM"EeߵVoalpiGF<*&^:7`0J-ƻL> +o 0@@Om_Նâ`HzwSs]z/FE~w__XRyRb  a`n 'citYGs=u5/ُ[3ȖE׽geqިP'-~pԾ)C ]l@&KMyyN <~2RC0xyƳK9_@OK)GFOb"ൽÏR N]% ~WO7,lO=^(+H߽ OUhQrƞ 2 C!h,eg  .[%_r@]+ȋ +W*v%UIS5i?@қ@~_9 ݰ·VR"Dks\uP` ~dJX,EѼ  3< n_ 0mAC0i;A`~Y`]i'> 9"`&PS?1<0O" I:w 7pA 1 ~+9.@}̀կw l.!F+98 @r h7mhSYl}/$/M!AE{ aWR % *Wm!:wc$0_Ȁ_|W%Y~ a%ln xm2@#l~L<2a/|~ 06`  ;P3@~xAx`@# 6. #ÂR F\lT/.$A`W~0XۛyGNQS ^~_פ?cvQV10 `쏀>&* k"c6kb D{3L?sJRV۷.]E5eH½S_۷smvlW| =V hح[rz껕=9 qx.{.a#@ꉄL# yxO#mC6KȰ2"_{ҁxf+ zDH| Ba_|d!0[;/]4C 3U4c^r>AۍeجkϦ!Q`ۗ7/F:}_)ةKVr*5,9+ , A=hR}S祡xGqݣpwXm>MM)*AӝKȦQ'_<`!oM8? "z9'~EvMpu)6;UU WؚE 0pu{tikJ+nUT|oem֬~t?lL/o'j/>zg3va/;k'/T!Tb;2Zj~Y*lPyM.8X pxd3nʫ=u2qmZhtba1GO|)`GkLdenn KD8 Ɠ*jFR vn0 R]PDxחd<(Ϛ.jяza7ٹa{=5r瑅6,b_jv}ۨ=8lאuJFbɂik7<&K7ddN:`e^ݨ9y 4l? %$6[ ^[r#s~&;FUL)xX TQf E` ^3o)/ VdvèWǰoV@XU_HVEX `]C^>|^ۅ7A~EQ_5" ^6עEY[;ZZiqRZؖe}ԷPqsY_l%ky7{E셰 l#xЗa_ }ھ4_3 R V0M8TAbN+]_#;籖dž<~E}}L_S-1j8>7J6&hf:=?c[/Y Wpu(8P~Ww۲5f&b~ D.1p睆:E{9˚VL0aM_ԪL REOa:@UO$þ㧤w_AN~ v޹W2DXY$>K(!'!7PmpN`A b@? ] m„a ,jVA.0"E_#,zۚ>JYbW4!psUqBhԯm*  \zi0kV↵. .]0 0O;4SB%3 .o'@l8p\<)!:^ L;x2=ڮ_^Oﯶ/^nm?^4ws]z;ojo֘Oבgd>]JE[AG6ko?\Y6qb;7וVnnp=smD^ɋRm?j;h" V , T"@/}wضgU}Vݧ@Ϣʻwk z~'HrHJ w/>Rh2"#7k pz(sv|nz;UzeV7\QʄjmEMV,Ϻ[P+< Z 멕lx*juJl0/Yo,Պ%VG\U!d[ɔVǠP"Wh0o=VmNEp =>!xCabV7[RU h7, `ip:0+ǙEK}ճ V+TKβZUQV}'y5;8(X.M#I*"e>ۯq4;ڝFxuͽ'+g/P޽{}7`AJtuѦd; ,cvo>[I bOpP\>S"@9jp;z;jgLd$⌤8#̤&H'QiGHây' NkJRȭdR$P;Hx=g$aUGUWo`O =Ļ Ysn^ߤ['ʄj?nWFoG1~C>DTi(uSK]T m4w}k/,aoMDoq=ӸntiJ^w:?]|W._%LKDK׬K׬*/֚ӥ Uui朿^]Z.^]ڿakDt\$U򢊗KʾPgj"t{^Wŧ,) gK Tk*V*-Pfڋsz.-P[_[PYgK((.(A,˝-ᭆ%\m_oGJǛۧpފ?g;(E5QCq'# Vn/p/WB(8#9P>w4^tWFśk+շ;nB=[{wOdw7wϿFc[F磠AzuB?y᭲k" ؍rGO w(SGt:)M![!,CB&V;c!$xicT Jȴc`SJ>&y j,e9c37mT>n1EemW^LNVb#wxX&wT6ґvTct5t"q\n7͍c۵ !'4$#*ƒN-~]~} 7<ߛHHj̮;;3,5\Æ(ͬn>VRJ 6Vw$`Zd>ט,1V$,N'V'X@QvE_,5mg՜":;iXfiAbph{gc"XLu5OÔ> E*65 IuWHf:֘ʚ5(A]Í}k(\1ʝȚY79Rv?ń 22W(#H.o{eH._a>+ ENgeZuz hb933 ̐"I:l3 ''{wؑZ^/,Iϖ;8a4~%\#\,79y-*uIc#cLÎL"Cd+ℍ|ju`jnjUENX  LL/L4wlJmX# &6ڥXt 2ؘacHߢ$fZ=Ӳɱ1 s3$#@vȉeE! ")IHdiEYZ=T҂ @͊N-:t:GprqhK;'1.&fZjiSyR IX҈EAG{ޕ< RH\ڈdIntJJ,WoJj ZJWRmjl*SЮsD$0:~'ӱBfQĎ30L"C'ŰH:B֏) -RHYd8ENaŌ}D"XӲ$f f$Ł1UBjB[kTR H98SpN(ڜl2x>F VIGCXQZ}fQ@68RpR<$e qs9jp(h0 $,uS8_. nvdX򕏃> vp>߳"^}B5N)PZ5PbrkS{r|Ylh?@aR<,$[>gH( &v{L>LC'XBufxHzۮ‡fKe:1І:ґp6ga-ѷÆ`Fg :9҆9R14 z,In9b=S5 6>7S(μ=BnvltivT_NHGC8j>zjr>0S(NHI)XrQ0H(W#כ`f7u5̷Cg[l|k%i[G㆙fAe:lČt$=l!Y R$"3-h![HcI&[ j)pY*QH["oCe:{1ȘZLJME3͓YdTFIґt GN_Ӈ2: ˧D#fHa#%i׀C)iA˸l!ջ!ׯ'a;ZqCE12rCγSY/6672:t@FB>5EG4XA ,k˸&τ{Y |EVo!Z3ъ1Fct8|&^SqFB>5EǻZ aDL"Ceℌ}j{Je]]m$< ]/Y`ޅC IWd ɬ15]8#I^H@!4(ׄbL‰)Iޅ3]t:C )I/"Љ!.x'bXc?ګbX}2aņNma}D!Xe-8X3ak2k U'TG3nX\Q/gt% вǵgZ:5)#Cpv|94݂ƐņNV';: #惊(踼6 *wJٿ );( E:Xq#aeYS=eO%HUDG?O }:|YbD<>ڂG5B'ASm汁Q*_SvZ?U cRNbDU&<>묪Wm|k/0oְhB>s?8W,g=˜,)1!FKV!tS}^Xc) u`V1&{\Ѳv!cRǑY Z&.vAVjgDV^BOaa⢧lq,dt,_ٱaonq5wxWbZ9lx[/]m>2r%H$ bZpK{0-ڈ )خi>pǑ_Яip-}^̨]A]tOw߼;Z)`e]ٿz0SA]4${Rka(' H^8#(ߙa7*l0Mkb) 8 J1a 1Έ-X/lt^dXɊk`ɹM?_{Jt4#ە~ 0( "PM-Q^eǶ;5Eiz"5 ryk1 ,=k=]MZC[=u| V WZIOu-̀P!VV@O7 :WOpV ؟m1C0P\*;q,tB!b* _#{ !vDqfB(ٺ0O7[ 3.8hfP.==aVpիzua⢧l.dT+[Naa7@vGU %k0yS|-i|X DBG?N׿͂1 _'a 5 =e;Nj_ [ s o'0*fou=,;X1t *(vO^ClQtD"VBk_+ҮC5!cyk0>H5ļNZmyCf_*R"4%JaL'Z#ƑR[J'R2Io^ /oųBOa"l'xZ[uI {sVn0-//<gbF3CԈ sֻB!X8W;4r=]xS+(=\g*R`bD_WW֊NawIN04Iɽ=ص'L`O[ͦ>fL3h'[m _¨,For#R 0S{ 4jzVn,ϵM=0ٳt2-ƞugtmY1ykF,P^Š sxBIk/o*)j t%GO#\ '\Z¥1˫EӾ]mx, W1,\*|| I¥zaQ1#ҚpB…ʋ~2U`XѾ ,ן`͚5 =e{f0fU fYJAdZn;ijg {–njY;i`*R+['ӛ+[(h.ZrqXǢ׳@ySwԳPQS|eѲ ؀༅[LDI,ZPhiQ=e{hihFUY TF?*Z0h/ZKZLƴl8B8>zgKtEGO\0\0˚}R>C%`*ҽpa]lX#М4"'{W!]'%0++WR?[,.سtEEO5KWV,XN:4U1VsaO֬V'":RBJ ~2YJXScw^ɚ"wPV⢧lk֪\U ZWzN~yZVPZ"l︖e6;j>f-,@BE?ެY(hY`1 (Be⢧l,dԴC,m2\4e=dq Pf5lqfb,@BE?ޮX hX{Xaϼ5@qS(2j*V^a(r,YPz!+`)%Kε<>;J>fL- dze]gb͚+Y)5 5KWnw zOG'Ta>"ON[旷jCw c*+[uOXqy#zQ82_1Tek  oQA 74y?kJ6W@SD6Vyx6bvqȹ\҇V OkROkGɫ5]{i`*n}~`qׄ]ފME{RcWdAG^Z|ԔN$$T&ux]Jvjb>9i}u hD5V!ZF?\(-,'KV)^FOaZ(ШhZiY bi1K2ẁ5F?Si5:GfZ;i7@ٴ dF?nZ h3c-K 6y Ǵ@QӴj_r%}U"Z'7h-BOF_WP`\-ZefDR7S֬B(Y0qO"AUf= [<EOsr5-0cA,Dw`Z:4["6z)7]̈|YPrK L^Š [Ya`l,fԬ-õeӃBG7aݻ`A(hd1jx``zzv%Ԙ1zV R,^ǟ~?~Yn +0=3SȔHU~|`.tbs d2k ('+\4sV#liPlo4 T4*[Zİ bEq酌\J}5ouCf0zKCپҨL,Z--J4P͖F%%F tK%HOai(iiaiJ 3w^[-cYg"/|_C4Ignヾm!y3a 湘V|S{M%IǙHsC;a%bi+vB(@yRQϜg C2V#cgCOгFSҧ~I=S l\ mAaag|;8igU|(0AqP?۹ąY!;GFHM;U1 vv 3 -ǥRmL|\+yIY ROqQ6  PB*U4Ox~ %.KC(i-i%G !);N9`Un4M_!q?28J JlhPzLb)[ }cpVI1qCJoj_9eH?ff@@0 K\Be3PvJďJk ETXU}v\ICDڙܬ)ۛkg! ,jaLiZ;eI?X;H{CG,q=¢V@S7p0RSj,M_=-a32&vx&,Z1Z; ;@$3wgh(/鵳fPZ "dzs  jqb+vB(xˎxN+;p̑7)4p{p"ؤ~4145G5}off mexsj9;>Ĉ,J3Pti` L>۵ UY!ng<(fa,fBmb{{ldc qT%7Wc3+Y-ms*i7zTFHrwHfDɴ3nR|Sk)EH?_Y3Z[} bKֲB((>zʶːRle/ ^f&в۬eP ȋer:nfiD' ON%.HX dICGON*KZ4mEQ=15sK/d3#ULO5F4PI ƒVeI->ĒJ(Qtөa B(]@S~)iQ"H);f46;Z1BdYd9#e3nX|4Lo.F a?+PDHO^Bʎ-m5oeٶ8#I,i i zI WWJ) gIˇ+h('ӛ% #%NK\BOal4Դ4_KS;;]n/`~~B %ǖ0M-0,Ml_]1ǔw BS(UlN٬gP2Lo3~4H]X2J3PzBzzfgBϔΪao5*ES?;<z{|Y~&A\;,d3<*;bMˇ5 %dz`4r#i< !=e{`UO }MD4ӌ!77ߤ89CjS%}I$&x=>K(S5gU^@AO inhtlXBJW4P|w!5h1,meƗAI(~~$!g&CO+=c9۝m`*Uer3V|nɑ3 >jX2լzaңlʳPƎ(.h;Ҋl&pSlVb jy3l;32MHpx_?k e$>'ԪaBL'yh`j4}FƆ%.BX '&>zvoTiCY$HQ3Ιܾ{zـĞh Q!2 cPL|;ppq8,qBV (@z{f()eSǀ e7:UhCvvLҧ~]ӍQayce6HADc?ò$eG?a(h=^Pz2lP/nTT鈡^%C^OǷ-( iW>XĊ\,b 1N#=&;< ,JBLo30 `470cPz) =e{Q՝/DHG):_5JLC.JaU>u1XlE{XDږ7Y>,g8h}B K[BO2Lvtm`~4TFlNm-n6b(&{d8H[#CdT1_`ˇRU dzIEn4128,q>V(@zc((ecݵ R" #;-R0+;|J20NElm?(aC2:}kZ{To.@7'C,q~V%*Azc(g.lRFco9)gPz=e{F1G)^di<9Ɩ~2P0fi_F,q5–V7%HOai(ii K^0 {ʚҊŴvxߛ-JF*SF2--N?9eCU4PU443:!gPz =e{O "5,V3ۇi#[p1/ACghRҧ~]?3ƳtgD9Jҁ^],iK qPL-v %&C6;Gs;#B,qrV=A0SDjʙ,gC ^\Rh`ŽuJFu2ӫh%C[Olx{W4:\&_;i755\( F%.JX ) A^Ѿ U-`ZfDjex)'5}oi;;Z.^+hMqh\X̮3TQ#mb6B(PSwrDHE;E ;, t: +G4=hOܗlh!WWѸ~M $dzP㞵%EX ){ "5U4%AM0.R,ƛۅ*Z͔_X~Wg Z{AÅH?\FC]K\BB@ SwP(R*ϬV?fq`לOp5b(0E=~frLy7Ѡ, %dz`ҾZXj-Jl4Դʓ4#YL~~ W7Ҋ'XȞ<Ȱȋ--ÔR Shta2Lo3~32!g =e{P#гE~VXgߣg%CO3#=e{TLItM>Ė%[&JvKHkK#F,q5–V=0 SXEjZZaXڍknv*^s1ѴMִiivTҧ~QM܃VP<'@YOyG{aQ+E !=e{aU\7^l;kݝ o;ŭƭ}\L~  'BF4Gϩ@NP@ <5a~ha_Fn A+43Ddv-l!*AB=8%MñR QP2xX* ]Y?wL%o E7N\.]v <*xsJc`sZNk^YyYeVZtx:pD@içڊqQB \1(e8 K,dMsƐS;)[GkLs7?qf Sd+Avs!%פ>VK鵽_WVURSpiې\ 5*_-03QgҒE,i2IV.i%?#H$<' Pm7ZA%iF_c'aC|`He]=~k`BMo8Wᦠ^cedӑζE28;Tc)u(>4UF52S\A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$XMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKj5Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKj5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKj5Dzʗ Matrix.fzPKj5Dlԋ Matrix.inoPKj5Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKj5D,搮#]svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKj5Do#QVsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKj5D'0 Msvg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKj5DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPKfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Nachtlicht.fzz000066400000000000000000000441531250202676700327320ustar00rootroot00000000000000PK8DK BE7P Nachtlicht.fz}r#ɑ5wrlẁdGOȺǨtXUjA<@7ڟ LyJ H/swolrYo|7]}_/__{Wgۻ L_dfLdJ&#Cpw}칿.w볇}~rw?xd<<'o__|s7FW>L.7_w3\̿>WRyޠZzx~zז3eeх c~qxhΪ/.Mweczgg͜y7 οyxn8|?u2=>scM5ÑCr%33WO|:qdi_oSd5q<s_~w~z/Wwֻ~\uy{Nz?N'wgJ?~;ߜhlt3'=>>NV=O~xpީ=g>~7x?+8JDr3v7U9q5Tj._#{~eX .RvE.+̙?}8^Zbv:֠mqZ8oQK,-]z|;?~}) L {3Bi\&%#קM\>W\Ng/iK|8<5g]ϭ7C Wܨ-ZUtBqQ.[SlxOǑ/n ooI#p}4oF#}ΏOG??jň|ǭ)SM}*|Xt dn'S0A#QJ8^%WNcq Ȅ}aiGcTӎƦާ {C02av0F>al}7 c^c'')Qǭ /Wa+Onf!TO;X'v0:?a*~!TP5l$CqU|C1Jvtk*_|4xxv0|ϰ:w񚒬jXa61Q^7i}PTCG:f$ԟ?qtx=աT?d:7˘;sFTPqֻ&OuЉ7` ]?OF,5z mͤS{$Bo1A W* mWXVVZ=,ō;F$+z emSʸYTgc|0ӖTG :lð01l _:y+9Z^13$dZ&M$Ē.Hh 6!=hyƹ/ ?v2\eABG!c?g{n3-2vM1<><޻gw7}6}+zO{?/euSnDoNmZ$?}Sk@x"aw2\Kc`ͮo{[`9|"s[9ϔakVy3gaEiL x68p??*$[Z<`2Fc:{f/8~JW!V5ު 𕱘k 78# OkL;ZbRۄ(Iwa RfJY!wѱ=)Ik2?L˝ n3槶\Ԣ J<kzۋ.Ȱ~^|h@.L/ƬMN1צ"2ѝŹxb?1ɔ,X*cxQc0vcB3]0XD]B&B%suՎXvZm8ccq)ڈE5#ʽWqxfİ Si(VGlVHƆBV5EwV!ʬNU!QLP!qོ?D !2ZBh\:!UHB;xkJ$ ,rFn7bgT,1^XI_5V-t $nbP&z8鎦}T-ME22BHsMYjHP̚=2TA=8CH1h厷e*fVɄ5.x2q kIcŤjOSv\9,&+`sYM?YI?M٧ARS$n`x5 *n; smb%A%HPP*'ڄ̬jٕC͵ Ҳ0zՉ;znCB< C]f;3NFd#vrw '$s%|L<5˪fO+n$Մ%#$ՂjHd5θ L3Y0Ғ}QעH*%$5Kng4Dʰt$HS#!넨4)mvb҈,-Enz&fdUO7FOi`iJWڙ}1 ma;%rgܨF6$ ʌ5u.ݷ5< RqjOUfmE ZĽ6ddv$f(M겪QHz,x:um#c:_dej<ㆇz #m>-xb kTM,V\ ɬ"Nu6ӧZy7:2*]T:#3NmXK^"QUD®p .9"g:&rrgG o0|ITbX"r]d^|X";D2ȵ*ȉSiLf%?8W ˽AkEs9:(rFY&B}iga56$vpHIt%4ytMZsRbp k5r\at$"|$TP)uߙ鮓! .ymA߱mm 6'S뷞O;zr[z"E?-w,HS.EHϒ_ ;V7d88^hr#h~{X}Mٜ~=򕌓L(M7G#*|"Ɓ&`yRp/~I\՚H4h}Z|۱t,7I3!V <^htp#Q΄G%Ŏ3NܙftC d>,2"N;tF$SKN/G<;^<7mSqҖ7 *nٌF.HxH$}"Gbm`Gʳ}5{|v{p #y s!WPqno]`|o(nq0ʽ]8. :dFʘ͖AםW=w Ozƪ>YՓX)4Vm9l4$V%M(էBŐ~<&8yoigN? JO#ΰtQhp:L"OtkZvz'Oϴ/h_șT7X7A<4*q1I{=kė=.=΍ri%DkZ3EZK59]sP>yz\ϔh_'zXvL!Ʉt۸A4>6+Db%pjͧOg,e~O*PmKx򺹢̹b(W$#cRH9-"Hbluш1mnj-TAӊY\V@r@Y'E5r#}8ܢs)3݂LqZ”׺Hn"vsd%>\#rݹG!Ymɑ 0QkQНy8;xfu1"xLd,ݢQā>9flt9v( qH{Z fcn&ɨbRiE$)Gޚ$bMw'mVtyʢiph!*%چ2@&궗ʌIԄԢX%LW1m!ŭml pUtf l<71o,&m+,qVhDM-t4CF4'Rd8.juƏ߹/wWurx}1]߱}ͭpCB3LDP̵̮LkCa~Pxd=_o3'wa nu؆|W_u/5ŨaeW?o R2٤O*Ӑ5J\~5hdNkmX-VfrLy_E 7HeNkm.FYk4-4ya(k2F٪Ze*̼80aIF"Vnf ŹJQTfI2 1ûm  F'wXL[Ή3?CTsJ{d6:(LSJS+@#1 V$wֻu=l.'[6vX󲵗ioP⎝͎F-⎍VE۱K"-gu`w~=V==T`R5:2:Vr2 r|rܷQˢM/xB Xqvz ^񈵩A#֦mn5FM *6h93U.ht\.O#ٔqweUWBp]gb]b񯻖xemQRշ8B<]'bSQqqbnO ҌE"&BdIa[΄}u3 "`$FlUDY[ɱq6>$vpLI̭M~<-oxJ#{xwh>Իގ>~ܾ98Ɵc܏Rn蛶Zotd!B.]5Ɏ;L$q IvZd(Mk[=˩DY`^"o^UmV' mDVWp"~mynԐqܾ6TrBSVy1zFq hpj2KliMs{Fm,6~ixK oټִh^e)2=ň1Zm_V :hV>h6,ߩ<S5æf!jYu; A&P)d~JBfQFZCf毶 K/Z@Bf-!nD3kGRlY4{`k'fҤ1pY]۩2ᄁM|8Dl 2RMx2X$f(Y5Ǎ%+Pe]f*33Jw*a:Z;e7 $USO`bqӘ3lcJA&,.#6uTH"l-I"lPRlYT-,D}%Q U5m~Llә|HFҴ"DZlwFH"j-H"j-BI"ju}5J&j-rq%YHõi)C'Gw<` A GcckQ$b?6[iY5GTo̬"T,-ov|;s NH1ڸeOv'[R3q4juƨiTUn*:N4/N=[;?}_Y>L.7ŅTe-w#gf^AFZ}Xrv3|tﳧ_~3?|y~Çϙ3i{N&~.æ?9s#=J8~k{e׽e8q66=w'™zM% d: _ jf?iڍt~.8^K'/gnkfƃ MM>WRRp_};.>Gg5c:͝S C0T2* CeoEr yKYPǢn+}0rBlH "20C mΟ ,*2i1Kwn,ܤ5 /zj`]Mkw~{o9?z}Cf2\8|fsȫS wǡ9}sy14wCs@LJy/׃z|_˞;}?^ȿzAA;R1^hs\  ,\Dh&v5mdf_W?:9 o5oÛxp1vx.?)~k`GdT݈ 6u"8Ov:' ڬMIi,DApwu>nN^}iμh]!̬PB]BvZG˻O̙'1FIgƝgf u_ӨϽ\ø{KeI@P2Cg.H(T~w{gx/gck %?qW܄kM#C 'xާ  JUP{_tKj"5{[7I\W:gk-q"?+7,\ۊ-;|ӯ~5|Wpo߯=lgr塥Omfā|#ox{G}24"ڏh-4 `2CL7L+~0@4Bw*a|*l "S\/hy(Y8u #УIRr4ϸ<9Ӏ"q Asзp7LE?fI=Nl:ÔS^C vFA`7 21ED링4j9 /(M]ZyA2ˌ)]q#ztEO!'կ}d]/J/%$*0 + l* LK'`8^TaU0&TYQ%ܛ||p2p+L.IL,mw7h +yP6˿=} HߜX"YT7+\}\ k޹mj 2^VK,r폍RULNHahƷP[a f Ql |8*+g @~hL^9I"xek 0Xb#%T2. M YE xEHD nD^FqcM7MTnUM;XiӎVL`wqvc0'7jM},hMu ᫦=0F} O@A0,v+# ‹KYIA`(8D>a6HfZi ֊^n,>el=ʊcMU踟 U&G0TP0ASZ1@VV he.a2x/G(G!]1MeQ$uF1?zy vc]hH9KlD`vp 0Oԫ2>D1SN, aOas /|k7]QЭ ~e5#zCQۧy;RMnOjmX a:2p P(;,h `Z]@)zC@wNg _%D8žd,'5NN8hgAGc a'R!|!{ xDA14屬&<(. F8@g FQgS`g)u6@N 3s1AH[`v ux!)b0.2ݱ:AT11 F|`8pYAUy{ ދ[!/I)9G(x  (T~E=nP,(*"@8*L(~v2D> tps 0A=@HJ%Mt*'4%P@T?8mc }P!  F J3|gg%@KVN p8%$t0ꅎF!ΣAz0$<^ՃWa^"1 BD&IBB_?x@z @ GP`QBx|Bhr*tTjn DTpoj劢Նh+GO>8 ?A;/r")3A Q(.øyRJhScw[*.h{{Ǘm 0BЧr$|SrB$<!,vҠG0Q[s1Pִmg;D:"[M舖Ok;tsGt)nX+5qtDCh ѵ,UeA#vl {vX $$3JI 5"aR "2`w  ' a_d `YG@wqDLiXp1lyW` 0f gFГUd'iE̳H=;tp\b%ΰ](` Qb铣Db$,b ͖sxx0d".U9O]%{Ǹ锹~`#EzBXb,?0.t҆B>xAIѵwA,u?eu lH&5@F )A `Ԇ?YG1RN@` O+|ah 9ű7m*@gV]g@pTڽ:8Sk%=a[S)F=acr@/ `Ģt/G1v0^2 BRn 4Xq7!&LApb5y7B) z^C #6;;!0$+P00UȄcM)QcrhL/XcpJGCnQ4h/*t !F h^وA>E{;ͧS76ч]6(Ŋ!oO|Bt$ wMSKш#{p#zrƘHWDī"RT)RBuv᥄"z[ڇSG%3CѰ0Rty#nvʠ% FC "A F*=E@4Ag8kFr'"Nn`@#8 ņ"52=G`,0S.`{ќ8/ lJw W<àLf wW;@`b:6|Zg 07Q˪T-0o`b rTs&G)k=$ @4hO2C'e<]*Iz͡Q)tPxg4bb6_tH7JL-w?"r|"FS:h QqZDs4#m `Ny4 O g!h /acvT Azš$nnYP܁(>0:8A0$sEaaEhh rFU'ɧb2pa h0pT h'jWۣoT^O-XW_'Obڗa1i:&cG6=ܤ Dtz[)?jGT_}|7':yY`*`βPД4-) 6\6(N KMdʮ84VT4-e^HmUdQ'p7 ߃ǂ s='S[J!z'2gR JU W؊E CSi2;Uӊך+M fƆZRyKyCUP[hdl)a/j U,X)TF+B /+BEm*B59K!T@f4PɄeWmK3e*ܼo|z”D#5n2`oEhGbaM`C;|rGhl54U(Jw1@Q@ɼ@SȚ>j 6za7)ݰ=rXb CG bC kt=*'b5f'_TԘ,&g0Yd途LV?QgQ9y-4L??cj nAnaʱ#'^1';2F~S 2)EO3tf2B嘁7*ĊVdvY­mӴKdUkG !$Q!qïX0"a”áK\A$4U:+nE\6P.ES2KY},b,48p[LK_+i)WӒ< '7{EŰ lPb̑ 7)975CھOqTp$„i:q&8 :ٳ_5mu>񜘭jSIns F 7 Lk~F]ά\g+\,)xӪlEٲJS"'&bPY".<,ӸN1S8a_~=NA0LW@ayZ0cYa90@LxLrsp{` ^ ̐ad0`~LaV$0성]$~+'LBAMh0]aA͊c 8<^ͮrU-G]E1ꪋFx{P|MːK7p ZqB0~з7(<}0p`18q˂K p4 ̫ì,1V2 /2ee8t < wQoxeB7_N[(Eߍg>=f8u~3f<6\.0qx9}8\mpZE2k\0zI2HpRѕ/.:׼WV h ܳP OdaR<<<Xy[uX!8\P|׿<~jVCs|/->wO~o%~[]VV>ϛ~rRߴ!ϋ{hqlaNJ{ljFrlv#zV1=jZ,z=T-H^ Mx<= ݒVAJZ MR [9EZK UVlT-ٶjxBlS5K)fG: ײ^VAi>fՒTZڜ^<Ǿ]zq;TwLe.Ob:Í\~"!!竫xwS7x WeǙ\)0mƷQ{:8*<{C,wP$q[|n[VtnlX|wfWl3~ O f=b6 >|L {%r8؛JIR?S<-rd~c@]L -`mwIH\IޚJ Xv'WMRM$IR$˗F.MlruzIk# sG93i߉XeFl(Q)Q[sxHyN$ɃCI S #',}uPKʓ8DAN^E Nachtlicht.inor0~=BB m!MC6Ig[ISަ[^k@3m` ~Z>x_82} fjD#W5jDDC3V, Bfby Ţ=ٌcvvՔw<. |p*=:m raU@mLSy^]5qBc0v+27P)d=<&7+]v[A^'Ɋ{"WHhz"f˫צếp#1Y7tT0 #AA,Wbte§(OQt0 r轼rVMsR!DזoEe9_hi*cS$WwHB&YO5Шl<%_bqD\_>G?s//[70]CF|nwk|g R=Ea Ƚu)ϡ9\VT]|V(/.3 ]1 W!oYΙ^N11]bisט3{N-fEJVYhL*5\[ǵ/v g|=*q}IaolY<({PD~aFciIΆ~:/U!+xÍ 3G ?A3)t}/[sM<Ŕ"kDfv6O8OI} %jLyԗd^wlbZN`3R$.^~XbS.o_+/ח_n_6?(?~??㇏?}U˅ˋW^o_ǯ9b07.~\wp?wj/O^^/}Ӯ݊kKs^ҕxյ}\K/>v^ǧw_=^z/ǫ>?{v}W}}uW#o4ڈ߯[ʭ˫֟D~_}\<^?Y]Wwo7O|] À?x^B_~**_^}|9䪧7?o|v?߼{gQ|ߙ?}ÿVO/m~*r}rHs~Woz} o6o`Xo`?_!])[joeѻT]|_|#| ꟯?V?~}yUhPks=7?ićů2g]`NջKm ֵ\_|x{z5{Ow41~);dW{vyvaPgX#jîh'l9VAo'q"'ߝ1;Tp1\p 3d9T tDSp;Jtxd<*ǸI?:j'1.v' :as?;WD \m .K Rks[ВB}3P*nW/-r/ϼ_Bc{ 4=Ξvž :{[{ @ @37Ξ6)(lxϻ=b+ @#mxO{@i{O`==T8]76 :{I{@@7Ξ6 z~Iq 9@Ѓ{޵gN kpϻ,={@ioYS`ϻ w9>bf(3qxO<佧="K3rxO{:g߻כWo7mg_{πno>hH_9_vž{KY{386..nϻ !>. oO{ i|Oip=0>s9]"6 2{Y{ K86 z{~y i9lB|e@g[)mϻt>{io{S>dϻ.w ]>"f+3/#sO<$!>R ̋ @3/'tO{r@>[RU7`/~?l˫׷ǛUqWwĝ+e[}KwZiVm8ۏ_拫^^?<߾eu~ r^_Ŀ*u^s$ڲWX+ƫw؞'nfD>ܿ@y01A6'm46->M7v3 ߳ ɕ>-ķH)An&>7'.Fr&r;AA>MHRnڃMmO|Fl1Iwy.uog2v{ zϐp[c8áG n?6WߜXC1vwϏc){MٓKI\g8jyV%sS l|O9'y:%=\J{晔(!'QΠ8g? l|;yy$=I{YS&!-Zؾ3ef0np_O{%di;|~fKPh2 I`}=?r ;9bώ\=X4w^$3GKDV k,cFdߵ'fDB+^Hc|ّ#agHΑ9g% n;Oy$1>\Ic|ْ%aZ4f8ntoO{&Adޙ0|~g%N(=?Czp0|voAcʼ(=7rC -mO <ӧUq2;#$g__6CEQ*<\0J0g_aX i YK? |p~y{~x/pǏOC7{w|}s׾oC v _W⪛g> k]~\K6p=\;J~yq_^mw@GQeRҼbpS7j;)JgLӤk NWӕW(2ǤZSKeB@;n)8yҁݎDĚ}K&,`q쮜)!P~B-/;=nW"?b> <Gs}Ԙ>Z (;Guf`F}?oi 2/tB(_-$Vi֜03yL7\(!%(dGf{0XՉف.Nt^s]vQS`[qqQ2zwwgW(#*W-p2pssW=Hahy5$:|އ6ڵQVN)=.Kd1\!ElܜtL&@PL!!b*w22-TTن GLەDr#]&=ƍz=wxw\nE1u]x9<&oE1zMWLyN6yw}""SrRDɮfLJdRjS1? (R3 i+}JRiNq2M V+hqq֜3y L7B2G2]͞buԥE(c:~0>PFk "*-E2N7mW :Q QzOV.eyu-F{[sf;9$:|># mkJUڝ}+zR(4RɮfHdF1? (k)5n)U2F]pB%H%Q)* H)u餂+ \F_E!o͙f D7Vuf0PL.id|&)±PC C#_''nVwkVܾ7+yn=4o꿞~O~rkCػ!?_Q}k5waJZc7+aSz}Bܿz\p?GC^~iԳ(|0?N.67b<wɇ$P )N602w x .\\,IS,x<(IԡI &6'՘p2N,vO:"I>9> A)R,+ NJM"V dduIibO; "M/ &{v ft7x'Oc-ӹ.92E;7*\?=<\<2;DΊΫ﫟 V]\o_rB/M$wA]!qջ돯矅!al7Xn %3[*C'V}S ۿHg狿wӽjo^ݞѳ1TWZ}V7 1o' @q1mq' 8bhHR @8>-Oy;bvWq1AxMiAӺ I]`$\)Dʔ ALJdO H3R#3q:1u+ԙ}΢MĜ㨙wMj d4 M1K /FȿY0S'];[*@ᵯXYPI@Zkݟ%lj%#Ik E7H!}*I6Rf2`iL{LGV#< ?lܩ) 'S=SSW&9TiԘSM,l b&U8e/lTSM+`GSGĜD hh9h4MM<@̛cIMz"1NL)l b.Y$ӂČ4Lb4Mx8A+K3u:}ݙH),΅|XhwwQxhDOooO_{{tVt+Bȸ!73VZ] |J&Q{xR~6 ;O`@D$(D%;C⊭.üd8bZkEW:;En`dZ%n[IfwݍTƙ4K8K![fHߺ|Mֳ,B #2e}J(/@\;W\8Wu% p%D\YɖQJ9vN$-n|x\Bu\JfJ ;L p (ƕ$ힽy`!ݭny6:Vp-%R7Zv6P.[3>;N=dfc++ P) Ll41bp%Kr߯]BA[^܊ TXHYVuX!5T^ܘ@!*[5;W6Y**RIio%RG4&1Kݯy\YCŭ+n~XNR}1<ZCsFM[xK<=<\m Y'Sk],7q<<Ay5TXScN eW*OX gOiwgG?>'I,a*oww7$N*lBwwOo~n_/_V/oS>E.Xt6i|{=<}敿t2k(8%JEޘţſC"S)5UV.|7k3E+?:.?=_F7|y[ezCCБpJ`0m=~?Θ&3%´BvM1>2䓬x]D?'/ gӿrL:gR7 Sܷ:.#5'^8: g2##9D!>Du ";|A| wDv4Q o.p{G`<0?߇_p~<0 盌rۮ1FcQ'apr00wm>2grwro7 r!g=o~!'9D>z^z,6:u^f[c\Nl]bl}s9֧$J+r>5קfH-MtfW~L )"u5_xHW'gr7|M<|ac 1?h~dkɝ](K-=&0wm>f#{(9^xΗq44 c,BAXݞa |-6/o,/̎|c4kKU'|1?_|bVg3)7Ru$}:hl, y̤ ZA+KDZ$.23:&.=C7tA7̅M给l܌UP3G(yZ[IA\W2W-Hjyqus#T$wNޛ7ahV8q@5ٛgVKfDb_廮v˫MǠ6J,)Xq*.XZv[t5ޤ!ڕUM.D2L9 NG&l3ݙNEĚ}B$82kMd4'Lçl,2j9h\ml註yPzZE=/EqHe{*͞r Q iJ\x2.MIDI(S"%rRK%:^WzG8*8ݝoAqTf5#@BER3rT8EG΅'n Q:u.@LCojqTD+Iɨ)~kҐ[lYwDh7_^5&*US\fp\fJo_+114DLJNi* 9 y4b_jE,NF/fHVAc,@I24G (KI6IlIՙ`2"TIr I4D S*307!jZ:h}4u.d̴/iD<&꺨aiLJ&(bd$S#)H^tR=NU]/JDP4xi]+y饊™FUD++ xy^dTTP.Z鈟jyјKrG0:PILdNj3!u4DPGL:d<[GɭAu2T5)NxyBH xh&Vhm1 QJEo:l^D1LUI+"?+ӔHBRi! ҔG1*'xfQ,bSHA9]4C)A=]ֲzmy(ލ]|<,iXj6{.Z(P`:PU=erSzr +Ϩ2TFwʔ8*rr%I2?%ݻq!J M:jуȦR1&:IJ(+yXKGeHW<-jk{ؙ<&o7壣v )9c[zh NMs4L-%:*R3s=LYʜAGELe :Q 먹6T+wT榸r qryrT"RD #PR{[sC!0_,R(ZV2-l--nCEkApU:*d:~(KQ7::j歨BjdO2AX6waX9em#!^laE7C_9&Rju7Tm",-sH4=5sVEeqi 񁺶ֵ@t-9$4t he Գ5fojyE߇APZp=3L&V(a#-9Y(e CRmXi-Y:~NLtLIE':Rt0X]z>gl|[3>G0ѱ5r3ʐ7̊$52"Qܷl,rPZ3@+Lv~MdN\IKJ&RY9!Ώi r&FMlBHF*`5QcsZGMEHeASX\7Kq^2gtR#[IZsR깸܎NU8"TWD 4SdʮVCO%RKHSdPzi:5z)Lq5qq06.zh%DHJF:7`rz=Uꨟ Vi5hok" TA}Pfy5TD+W0/1ʪR)\e b DاYe^x?O>ȣc!rFmw@g4!> ^R8,pcn40};4(J% 98zuYULSuw'L6:,p*4 9Yh ?[ Ob|1fUa']1g 4 Qw6FV[i{~h~XH) ndپVmJU#}n¨buɪNk- xm[hp[@3`Ar9,tsW\ 8iVZ9-ɨ9:J(  YЗpQd62@ϭaZ j2RBMQ A \苶fF?tA)"З 5]Uv5̉n AKkFΕҜY-u=* j%<:1BiKe5L3 Ϋ/Ӓ.(-v^׊ϝ ;rxwo/Ë.K8֋{NlcptN,+S=PP oeXmݚy6\,M*eվAyT!-Ar-ZsNr߶7cfTr13Gt8 ;Ve8+AKLLTn<8W׻hԜ⌄g ^+K4۽{&w*P{;/PSWC{I\KIE+79AK\kf|u\T^ 'Ƙ}ěV}^Z\O2wr_݋8a2#HlJ\AKɔe7GAKvk \kKru'@jkP3ź +5=;| P'Fp4s,a.)]±:ub%(v$IVR79/uyR*R!a#LF$Ns)@BZ:ӚB_w@d>-X$ڗ )^'hp @n0`dfsJRL 03-8wm$#,s2:#m@Cـ ; kNek6!AqK@p$l]T^g+HN\=E|%Rb*eKŶr[D݋m8pEX2Qp-%Mog'(p X+o֌n `q:UNtZhS8̞l24.88u$^I3Are.%S-s:e.KPڭ'(sݮ@Lf5(9ۗm K# qNDKDv}M:y4f&@Z.-ob2Tݚ0&@t6UpD*bE4)ɬ!Dw$@9r}HsGƱu *P %bf%@ J]5 pR|sZݾg\G߮}Ų+:f,,q0V6dtYNadɕ.t}-BIB`Ne7npiY,RZ&*pʉr"hlcĸ֌I6.(o; .Dʢ ..Ipͭݚi",ruE9Npr(&BKsvA9T}e(\U jHK5|:((o)alycf%m n Aog6IPL+wr6X 9Է\IԷ1A{E,PKXAKeK7EAKtvk ܖA\Ndv9l^ ɰ*=L9)Af@j DN9dz BI&˶44p 1Ҷ%m*efiwK4(4(=J,>2fP" 6R'Li`XM:B $OPd&LIP -!FPٶmn*p:^Q"q-# P>Nc|t1?Fc`0Kkb8i1O&OdƦLI -!FƇɌ|tf$#{մҞqw*>S:FХvN|[qFLUaiSYWf,ZvhNv&HT(I8(Z7z)Yj$նa2զ܂;RA={*lL-2Gk5,#`тjXE5gzꖂ!n 9jmm2ጳԶH߲߲! +q[SfL:C|[PdgOPR0.!GPnH62*<D@:@dx`d'AngPpX Z\",\I \ %D ܖ RDd8a:b]8A{φ{q@`)$qDݻg 3` .Imp:-CPrmKg2+B &$ĉ !A`̈\;E0PhZٟLiqG \",X :\ %$ :\<>.߽xOno]4? *mHwMЁB,&%kZ՚ K)Nn*C:*lxlg'$j ؁hj[6̮܇Rtb &Z*.( Opv\ h{ڦՓ.I-]B2bNFWM(H䰈flqSjɧ&(o H'^i<έ zK ;qʔ!9{fJBas=4s<1~ҵޟR|Gd ɔM.%dZ[ uIlʜHk& dSn&q \@K+?v/AԤν tMI+I~n}knkn)57o"%nMR*b[řLڻԡ-g Zh+G4۽s1OFsHbn o)ily3&'o Pn֌n qO0զ`e|?(w3qNCI}v/Cʣ4J`AK eۜ8KAKvk V ).IoiA{3JRb} \֍ju"F\2J鄦C%v~GtdI \Y \ε[%3Z (άr(H<%2$z:7(s5=;ƽr8~b.g ί6,^3y*(u pRnH5vטAΈψ3b vO25<:47۽3.tZKXAKe1 t$q֌O`lf3&iJ;6ԇ>*8*(o; VLDe{[t% LHkO6.b ')źP\+E4۽o+vru(0\4r0y+n)Yls٦&ho PKn֌Tnלp^r6z ]Bu* Rk{'s)qH`Xo \J,dY \ϵ[3>P]3e^J;TVXdfg'sZa#x0*/=tAKJe%\5 P*771rWТP(Nb¼b?K z\vϥTE9xVowH1; dT&TT*rUT+ $Op;\",t*[~f AYuKge5qU*M7&FG7 5hkc>1zJtE%'R-@h&4%-@PB%m#it(k 55Y (Wfsi q.2ĕ%J3b(kd5IZ3n_sT.ٲ7nu*B.`ɲ\s$k֌ODp|N5NN u7fӘ x[_kƂcnU)nE"Ly* 2VLPdfEPW=mӆټ2{ZW*RUP- ,a.).c$fglݧR\T& )B'+~OjBY-hƌf]:+)K͒嘝%.[3>J0Yrmpz\g6reP@H-6ENXrD*܅lAAU#V]ђP8yc"Gs%mj  XRBeo<%.IPڭ&lrl= Ɠ \2'g5#CHkcA*9*0xM`'d&H'Rmk f3 e= -#J6` qo= 8jnUyNj5*ML(ꖒ&˖7ov%n ˡGlyvqewe0V"9p;(lj}מl,m9r81S3 i ;ٶ,bi<&E\;҄=Vg20/9.fXetM!J.{٬]-oW|(̖&]f&o @l$ .m "p"H3\Of Xݾ_q5#Ÿ2eup,ޜ-(Rcl.$=-Dp-!Hpiv BfִroKaL\ӐIFgTCS'e9ך8٘+Nk{]lOD S%,J%.J2MPڭ'hq[]8֧1.e1*GnBw2XlP>N!2PwR<حdJ(D2Ԣ[ߵtKDe[2AaK@\qKHtj:{ Zj*h jmXkz䙧XH4{Z\yɂKo)lf)hr XKo֌Թ`tÔ4uή[T-Etū9qWQm']ƚ^͉yh]C2EwAPỶlst(Akf|m a6.W΅ޓM*څveEq]-*p0PB Tpam w%C"66~&@!hiݐZZ]I)7$a+ 864۽Q+QԺVnmMXh3Xc9*L\bKIe 0-AcK\\kf|FS>IW*qk/ "ϰLL0w#hpPJE[3R+ZfwVZeԖi){݆L=%x[J,zZ J\ĵ[3>QP$nne8sL0u ݝ@ؐ&cs]{;r&87(<-6-j& -A012!EPζL"g}\]zwO0g0^\7m:i5DeYDXMXUONng5?hu} ; sKrRVT7†p3fq~@ i"u@sx7]dnHZrn]$eFv)G,J EQ\`i50NTE͆+WF"T8b4D`*Q"x,;.-I0>#K%(nݮ@rîX7i˔ t}d"°36ڢ SmXmYN H`2QJ~,[dJ[`RQ5ŭ5[>9G(gn/&%RQ@̽l6UhmSD⨼ޚTF AwK eۑ pN%n֌TnꖹZvnX‰!7Q$Z@FTM-*meJ`y92̰X%,4;ѱlM٦i~L͂3=~V]Վ䈮뙠S'wujwo/CIظ~AĭX0 (ht0L;'^dE3Ig e':Vcl5hY׬KM5_ s*FPb%3u,-(6R~A fjzxV5Kɕ-@pf`l@AI2c&'o Xɏ֌n `q6(#л=DYCq )s4=;s|l7ft40N.tIɒxŢA)(t @BnM$ X 22˜Bi2 2Ǐm%H̡%9.7Ckp]t.gp9M3Α7p=+u!w#302Զ0Yt^eƦ:[[3>H0r 2]$.R"T/݊P '{? LNN#@82^Pv~LYlST(Akf|ukrrfe|Ϳ leq^W^2ũ(s֌@J˔}BN"zGR*`2OtKɏED [[3>PPݶm3t-*OB,̅պ2E47X,G4={s+hfjng-QSmL>x"xsk2@2\J,{N曣%` \5e5\tf-qlINF/ʪ*eh@fw=Τ<")F`9JV.@BM.%P[De%Z\5ka p*UD#V8U))Qr ,F;Pࢭ)eE$pġ$ [J,{N盝%` \5]3#YO;Y*.wB5.ښ@p>w]99^%X.+r)l3(r X.nNP]3*.$LjrUKyˈ.΁j@Iɔ@}e\< /UifB=:(hq)ilf'q Xn(;Y.CU9@vX^&AG )BɤM坑%@ [5ŭ57Y-> [m,Fp}+A4}hsWE--eJ!XV "qkX4hs19:<ΥʲuNg\ϵ[3>P纻79łR:U H鿑b-KxfךH)zR)bs}ny`AK eH0Akf|u9D'' .#Q̰GG<'5c1wt8ƺqGf zί`ޖ$6j nAWVlfWCYQ<[_k£@Y5ԗC[{l ZJ,\jt% Z5SumK׆G2ZG "-s|="`H47hX5#2ƣLPDkc;-@ʎ :٪ 83h0¶} "!S=> zr5q.֖#hm֌<n#lԝt4U"N*kiғ3NrVVfz ΘcHer4={_+zSE(R3UvKYv~)VL,Akf|m %,s.Qᴔ} k^g6"q|q1N(v2&0:*9q>&s֌ϙA P:ʂ&RlIJdMl˺Ax(QR~V>X5t9%K(ILu/E t0Ye% \55,p;@,a[tHe\@fHF:?/hJx)jӡ \J,beMRmݚy65 63\]^nLkb*bN.e'Uӎ2mdRX0#r,YPv~Ը8> $38 (p (n$f f2[؋D$񙗂eh 7i7h kH) 6w)UɎ 7z PX*Sc*m[[3>Opɭ5hͬmP◡E 'Z[5cqR tDGT R]{JPRbdJݚqerlTD(()*KRttű%@R^j{H>0f#J^%@Ǣ-|-Kڭ'hnݮ98MGH)#$pyt m,R^j{vVxl{;\qB4"`n BV(`LXy \[3>Kpz:>VM!N;/̵x9inY?8-J%})bJV]d@(D)}~$Z[ߵ-%D3JPխݚ񁂋o[]7l;\#rBsic0e֌Hro1cn$ {8Z[ߵA-%@mm"\}-Fڭ%k]Df_'Mo.+"[HIdp,ڢtǼmme٣u?%b4Zћ*6!@ęP KPRrd&3NLPݚ NU8ݙoqib\)QgC ^iyN507Iֶ*ws% [J,TI [[3>Nݺn,ߜPm> m{v/t6%hl;c[J~,t|%Z5e;5Yb&qSxmX) q6(n;C [J,[b5RQ .Lڭ(hp[7đܜW6yRܕԎPg_MD8wN-8vn}kWp0PMּ 2GPR2dfMIPխݚqfVr?p+e)j@ +,\0劲OhoPYޢ+3&K{8h"11 !hn)ls;HPݚ59er(qf2J4={y3 gSmqGoEq^$ί*&K=[眙%J\5O^TnF3[EIuQb%3f9¨ %]Xr*|wo/Ìny f3f(`lN/Q`eJ-Gd6rNTPuݚa:ѹAf,Ε#oo1ҮUq4Fb֌\|;OIxiš]{WPR2%Go19o%q֌̭ܒANf<̕AVK9RG@<۬dZ8xtݢE؜kU3mNŗ1kT]{XPRBe:'2R}ݚ>99mŗR8^3\@Nb -t:Ø]sP!l*]ߵ.%Yf)QP]ݚIϯ/^V/Ooas㛝s|q==\?^ݽܿz!E%~/Oo/V_{Å.~oUIrh^nb֚xuW|zpXD_Ϊ^`a46%k#|B nzJGuń]&){{7~X?IohtK<'M҉I@5hbP`O8 f{4&=.%^)MXȕ!֨q3R?'307ӟ~ũ̑qnDU']k3RYG-քu%GsT A\eyKGnusFJJ-B2՟WzYY*2«&Ls ' %uVf%09!nڷ/oTiZ|{z|_ힶ޿>࿬>_msu ޯ^|Ǿ$Ŵ:>y. Ύ{G)ް5C֊ bI1Z2)H bg'̳,Ėx,ڢ\֤p oA9 WӓkڞVQ)'1-dR2 t-*u `9a„RS!#LpamI+C 2sZu]/ qʼnޑw[NܤtZkp/,rYIpZ\hR/:J =J iǖQ'My4B-^Zˎb2k *zLx5*ۍl䶪xux4LvzZrƈ@2͉ҌaX &gtI:"`Cfrf7wGe_ O:gË XpBɯ*L}ێ#ɑ4/eZ`гP =(egM&jtR }q#EV&La#`1;fkByX&|~# 'b>4|!|~t:VZ`$y2s-Ɗ8zs#6_yoO58apinNuDd|$Ait2/Eu~H \4xTI'ɐ0[dg$<> yFLJ,"Y>I0qiSiV1nӿQK$g1ΦYQ!7&tuh3Ш|hNOB~>4Lh̀ ]>Ѹ2x.ų1`|;&&0ҡ|3?hol:$ME2 ߛ<,)o@v ri.9эJS FDEǞ#}}ިN>扅o7{P2pwAY~6ie6|wI!tWRbnq5&y% ~xki!4LN.ûtD$#9kwGKE< G9c^,Kؔ(Y.M|<M24%])OHIk:9]M.ALqйSE~m9 KG0&6%&S@ E+LV5vGh/Y ~=")f+ ^@DMkJM L A rXjy^7\cm2H\BYբF@c#i""FZJ\!SN,nGx6v qӰ;l]3SFkdӦɩH,ԝI 6D%wA2̊kC_ʔ7xIU`$D!K2A)LgPGP3˼/s0ѩ]k ^K5LnU`\{Ӧ2b,&Gd5=}oee Ћ 4$ 7^^Σ J#sA#$J\,4I!e"/sP(rPwiD!7 —"(0[2H` I)&K6GaedgJ]{B!rhxچ}RqkoZoLlR"zQam"jcOtzW}"vnuߩF*YiT%ɄW\ՏPApVuP2[IFvRxiyy|uLn*Xω5)E+h<=;Hm_d/ ]dJ}EG_$3EBn:̀{gv>{~J4.puPJ*KۋYj( g똹0\>vPtR5`7kblkOHۗ5H7@]o7P-F[NcԹFuC#BPꄪdOmOPu+#," -@fɼ j/sLPAẑjlZУrn}#HY8SO\8D uKUyl|c5J02*Uމ;rq4ιehɕwY  ۾ ?ĪI@?u2 K(KÞ #% cY+Xޔh}Ksԭ.Nc!gLI+lar+:&:zd!}nStd, b8Qv&”DNީҏk1dzMw?J( ddƕ(+ 2^# "%\+햳ʓKaڻ=|շdIB5k˧u+b,DB[e.`ˬ\&. a&"˿s}[$\M{iE6b٢b;ڢim1 g$IEpKnӷ[*olv[J_{M/eمK6u{ 1t%Hi(F셽ye6>9Rhp-017ȸ0]^KQ}㩑S?>|i4o|C 9.bvQ8j据E͓t<쥠ꡳꈂ[?: IJ Y&K䋇]v)j%1k_kbJK.iR;܈qʣp<] k`o>5lusWiǿۇ7?kfswc{nX [|~?L\i99O|Ϗ}q]ÖdXn#ؼL#볺E .ۢxK4輷mctMuְ+9p1.he#Hs/mj%Sd(5˝~rW9Mwz9lq _OV[.~m_]1߂.ZtQ|#ڼj/ysx߾?/I>Rǟ~?h}wϷg5/v;c(y׬.8<]ϡ} 7 ~&c~/FGw%9krZ&HߐH)!cAf_lQŖ{bs;_v[liU2%od}Gw^Gwx*cNʈ>L#tO#{c;v\fL9IS^[_fٱQ^j% mes{d՚sOlJvm-SbgɤZUO􁁥8EPnJ2KMq X0WgDƨYUC*zMqQ՚[Hu{aHR-=kBE!<:.'pVzi6ܔ3=v0fS&F'm}2"TSn3B3n8'w([7U@pݨu(xg%l9fn{Mfr&'YuarLÜ48U8фϴy!ߜIڹ:\E&ףZc)c-1{)S{QԚ7ryQ+^E?[3w'YC*:BC9{r.ëXYtAh9wC+ +#%X8eLY-uiJSg^of}_"ϷɌݰoߨ=)vZCd0Zq/oWb#KS|ͺIA_*A?v{/[vr}~bV5WcNIc%m]{kVܦv {+;&vk>UJ t:\NX4Xèe}kDr_^IKDAz^W^k^w^>Q\J_?+W.p6ZDmjUׂN֥hY) SRphJI?cMTYk)b27k7\v5t,/͢NrߊɎiP{ڊwD*W7.j^Ϯ=:m#1٤dN N^}K[KMfM!O-ZPt5t3L433/Z>bm}CG͓oⰫ'76OmlVO/!s1l|6 >=#9'ݭYFFyfwgθՅ+֧pt,q {-֬W'}V=nq˺WO#iӉ^e,O+V'{ qwrxmDtd _DX:+ޝhE6OLYm9Ŋ%ay'=g2t={g|1}ݷo>?l>Mn~/#ȝo/Û!7O}珟owVZ}?aõ#Iޥxw5;bJJ߅؜R|HIt|/tR;ZOS#O?;|I?}/rȮ OntkȪ\ISj,/)▄)wR |P7N!Yt7zm6>⠹KyQ!E m ڹV,cVGnXu eՊiQrrLQ/M BƑRr6H)ۅ\TqQuI|V%Q\zD(T89\*E|&nftsIAʷJV ]ipr]>! p60gC]bSx h- vEyDܯ-jYU*wSjoNMKp͸uk+ .ʝ7Vn=Tu9Tb8Ya}qJd*),,$N#uu4_D~%xlUs"urhejxnalq509뤜䉕.jh&iP))\ O*kMj-oZ$ìMcUwR7-=sZ,CU- G3}S 2^ ;aFZ,rb祮yb?72h 1\F*'Dj%o&x$MR]vѪuM7#T'x݊ѓeQX49 [xKX/M~q$ͺow JjI- %33pҪ-v,s̤|!GH@Z]f4S:Em ӥ_.}HQ9҆:vJa񺥽 憐&ZP ;^wAMnÁ^OZVHjYP4gqὼKpOcAIB\%g[}ubuI|tWIRRkhshjVlzuhG1\ɅYή`)+Y\2m:4~lKWI@RY0RYEmTw{|$0cz+D`rnq.r*+f=Vx 4{eXuB\bڡdl4 9ᣒ. 7^7+ g2zE}ܧH]D9#TJv( P+RXjdYfnYV~}q~tqt5,%M$X7'n2NJ,gbGhӃG G3=Tv( 50QSd\^U.m *J&GJDMDt6))-E]츼RJ؆F*a5ؘ͈Gj]Vk\ =QLm vs6gnxi;?T695R*u5$ qU²$LKfKeon*/;iHU[TJG %(\c mK7h]q4u{hn4T89Ԋ,0k -ȋrV M09*u[VM -w{pC˃ߏ%] Ty[ռud2w q_0T69jޤwƝN`$vO}xj5oXVEsJt7K$߿XY儇\ItQ7:;߀\  IH͉!5 %w [tYڪAH*]SKlIgҝ.}AHUgIJȝ Fۭ4'ӕ8j[X U*S*O^KaH8 ;ɻs+MQᆣK̖,\eesM4;؋Dl+E[)۱\@RR6?+T69T6'Zּb;v;4W"ENHiL% v?M Ӵ\5 NXl.^w*X^GwsYo~/~sRRRۜpZɛ2CH/ prh=v.ݩ`H^ALu9Z܌BB{7Jrѣr9u5kUGbL M×9FwRNTf+;ى.qb&RRٜZ+e9::[s G3=ZYEv6 7}q)b#ĞJt[F5 N!ڪt X>A*WBj oF*%8UOnAYۨD~uIVkaw!h"F_8] V=gVI|~~/N㌋NeWJ;dǝTRRL*!O.J0`RSsu4R>}))ev_d?hWlK:YrL θ0 K3KL.v\U*ŜS*ŜOhĤ<2IY9]MPw"r RN*;2rZݕ[^eDЍ962疅JfJ冣W|{mn)lnrdnVTUld.HTDnY{, $@]j#(uoN 8T6vPs"J-$M#+LR oD\m^5Ei8 P)1RkK@R su%nwRf>'wBD^痃fZv%2ҷ^0Y^%}țp᫻p^5qFN,H^K;bYU.s}e*ҹ_肝>C~ԭ$rjt*߭mDT. *΀*P9Mm#:!KII-S $/hA>7$oPK8D nb$ PingPong.inoZr۸+b:8$LV'gR^@&(D*(7*;t7(fqeGHt/fءTcvTy,U 4,&Msw_ # {-"fhi?ZphNl6=;=:uw7'>myҌD$)&W:HJؗ=,B g'lȮ߇w7/2gcLO4{ sl5Spw~pyE:x[{A/l'l%Y[2D&li_N+23LbaXu,s-(N_c#˭ڃ yz&4U$"(W)3ŭJy o3 Ox.=/[ v|4"oŲܪHhxܷ ]a:LDOP-24{3`y$o, -ZJ` ,Ќh dq=B mKg< 'Q(: XFMxMw);IDHN0#l:t!1!Ў/!?U:*6} n/|0<9AN%w'}QRAcf4-˿l|Ȩ"|5Q ^ "^DEբمB(Aj$Awҿ:)itޓOy@2]D˝bc^8 cEtJ2 3n"7}ȵ&V;Pܙ˥NNd M Xa8t#FnS J)vדb6JqI{ ͥ1vGA'ku S07YY0+Tw C0(VaÆ\]iUKiVu?hy{j&/g{lqXG^`e \^ACjTŶJ3\ʢvXMR<sI8矮F.dI1-\cB."\RFw|~YEI-׌zpx\s fN l=vevK>͋'cp٦q;:͜jz5%cgU$$N#u Ql#‚V/[!NC^Eec642Wr@GyoE.!2^0׹:#8Yi(sHw2SR=HnaéE?#4Pw T9{Q|O;WEZOd?"&'1y|X;y+Idf!:cѣ dŪp.xP4BS?PӀLnPSJt6 ՐZn3kk.[DDT`шNꥋFg &nmI==T3ftT޼xX:&eZCgA{ ?A7s HVg*;K2~W gdGT>WT>"af4of~` *u}+"4W Hu):c8 `01P E<$c ґo`#BEu >R*H@:I $!)È>~ %6Ll d$ROä?" $6#G ҕo`E> P!lB p|tR p|X$&~6>GaS>B!= +H1a|#oFMu >|jkD8HP0E6,ht;WȰGaQ.f'u? CPy@ ݹE}0G-1[sCLKo2a\y{FBphl}?p>ɬ{dTT?hFfs^T2˳ 򂇫4qмvxy@5xःfT}HI` o.Gr'ch&s8b/8^aWPSsnF N~(w}?~( eBr8AA7PKV8Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgn8@\C@DԅT`HMSl؅oc12dN]|+#<IM(Oo?2:͗KN%Y|q姛K.e^\$kz2ʮȿ/*/J-{_փ&5ܽYB_.כ9,cgQkntӼ{1 m#HKZu^Mgz F; ӣXy]/cޜ}!NCхN狲 6a72rׯ<]oEf2];$M`ssAF^i(sH%6E{X~x:OӲH߾?'R|j y'*W>?rH˟BO|Z$d޼:!0[aA|BuvgdͪpĮx0_E@n\Nh\r~rGw!TC2ͬ*\nͩEK gQM4{lN90x! 0㵥M%w㿯(?βt΂A2n`콺TJ!ܒAgO Q?BPj 7%|0 4Vo@w >f| 2|/{*Zt xjac) E<$8b(70bbQ?hIHA:HC,R@)b>F.Ml d$/21I?"$6G8bG(72ĆĦ:~?dР@0~ G߿>"y`^!Ώ E?l Mu ~I?`|9,vpÂPCe!Ei 9\tqzR{˨y0A2\uq'wGliޘC/oLkrj&L:[;Wt/ӣ?PKV8DZU+Usvg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svg}]FZCc;i3Όp7s}ҮJЕe{~fd1YXrI7UɏdDƉ_/p՛dßvwo~xWO;vvpo}_=~ڙx~m/}?^vGŮ8ӫ?~ܕ<<~ox>ol_~,1ټzx&W}}wx3ߵ|܌c~qig_5A<3GlՏ/cOc?oݰsy<ưs)~x2~}{C9?v;p޼ݗv(_Ӊ|߿{ˋo?s,B-rCgXÛ޻7zhط^Eg.ƣE.wLg;:L9p Ϟ[dwmњ=|Oړm#Kz0K݃O3Y^mFCZ>I;>/ zk?yzd=\73ۭml|s߾y#q4q/o0ag;.OygC>ʿ1qgSa N=h·R?Zվ~<'_ٕm- w[C^ٻ7?=poϤ@CKݽzw'&л_I;aw)o`F{ڹ!ۋؽٹtFs?ZUݸ)OO70{fw;[Y*{a7GgUC" /*r/U2as7X$cj;m%zw ͗<9Cv͗.F@W'iѢyC3Pnى4Fs |A(Lm,8DQqpyL{ObVY3%r\RQi\f;[l|).֛͸(gU,7娏G&xLMީ9͹UH'W$ߚ8 L6)R}ljTׄ;h͌A]ӨԨ.b.N%D(ׅkiMU ǔM|37@l7x ~pFUD3jTDh;oKU4s8xaKXfEaF$1hfqQ6ZrxEd3]̉n'->dfX'v(mf Π)O gWG+ga33wRO ռ)T h@y3Q֌Qq4k0Ű2m+SYw;umI1b_i)ɋTL3;L.Q,4Y(I!S"iimT1l3Lki&;IsܝfƁabv7zIN1{\T݅ji|Q"Q_QӨ؏*qWL01k9۩kSET`W'V hPAYa9AqBgW iT]=! nMՉ9+uBV߯Vg4qC+룘Hd"| iQ9 i0_ 7O[J= .4W!$2C4kʤQ ѠԏVD]?^ 2+ iW?+m*oB}KFYtmJTHógy M5i ӠWLʰbVnuӻtN1 ѴtUu@~xRY3DCŵZ.f2ó:pV|YU0`?XlBs :Y_ P uW * Ǡ ̊bQ09׍*AGUILIJi)|@1t]S'x4&Ͱ JQ&At+hAGݬn|NW|ƱCyMC"SNVh}8iTX:"5U>ߗ 9N)NBwU~)`7`,lC+'4T>)+-W׸TrR7H*N3'Y_Rfl&/ϕ$DA/! DhDA5%D(n`oLzƫ|NvӦ{\YQ#",O߇B'<ŲdukSԑO)2CZ|)XܞOQG>Mzb#$馨zf.HwLCl䓴˓lon9{qS伱jיӕM=O՟M5~IV޻6&r/P7.Dwx n݌[>tl&͸Qѝ+:Lpd7g$;pY)?-]([م;ok](v1ZPzaB~&uc NPm5fX Bp'JZPk_mODvۺLt_lk`mݸ}xb}E.wCmI -Y nW1+I!{v%FMu2n0j^CHQƵZX7^;`hb6-wCmIt7t႙ml?UX[ju(uz1J?uWO՝Q:z1۩lKGufS+jU{fju&u)LlnJ Mխ[OՍԧsvl9qSgQ'lN:]::\}TI.JR/CխVn-USžRf]8mETSz]?Uن'5n'n\S5~bvӗRpsV tƼQaHg l]!+ 2%SD"ƕJ6n\Dm#O*Qۈӻ®OQz_LQiA2ETV>JTƕJTƕJ}ä–ӻIs/&)X*I7M8%D$(NӘq(UZ;ePY'(n a:p#޾R [Rh_J[*Оńn+gL|:;qlk$PTrdWݾvUF|(VFm|{+&ŬnTtyB){̶F)lmkB6)B)r m[vvZ/3-f[r u7N՜~)Ծ))q%jcPe'Y+*?uC$V@a3bhJ+d+J+hY+wWZunn7TY X/ cV+2b^\Y*V*16޲vqkC&tK6=Skvs UK^[^Hh/XJ$N]Bhdnm%>xAњ|]NBi֖wwAiv9A;i;+oNŴnHEPT/"ֻpM&6TJԎOA-i9AMi9tAmUִ4^8cM{?;@*S&YN<Zݨ]?F}!@Gݔn;PL/D+`ܞv~vu:z͵\c_\Ez]1a? rea]6=͸=Ӏu-jb@Oڟ`b@OoIZYPWgzp!޳n2 ڵ^6W>]kksyڵU>mQڶݙ|@V{. $zǻ!fZMujroZtv|nks1Yp~F #ɋnP?Q(V MZN>A)u;p1?@9Yګc;瓟o;u~]XViLNE{Z YթGdh{rGƾű7p=h{8_x,ww4aԛI/;`?$TA #'axȘ Y, `?? C4E+62G 0Y(g9x=ņtF/Cg.Zy,AkXLsq\^Oۑo-$of˛(8 ÷lq)#L* /7[cY,yM$qB5d`ly(礁LY,+1r(˖փlJmws28f6*j"ď<[@`L+0BQMּe"KCdLߨDU/7*1HD7>S"98SCܠ{5k}:9:sh7h"ýH"SAߞ ufcٸ(bg+ȋ4#/..5zAX{Ȅ9)) y *X!q$*3V&HX9&#Lt'6JjeP}o/qzz3hRJu@FQ<:r3'LJ00c:`T1n Xϣ"qY:8Ɉ m>tlc:L'̙L' a"= %=l=t^j&<)9.9fFso9CΫ!OIv5NI2Wۡ5:5õ] <>ϙ:H J& e[ _w(04F@&B 2`<ɐw{GbY^" ,rdAz,PxWX/6a ;Xp9$ՉoV7;(8'#S+MT!1r%!3.8,Bb9#hG1<C`FlS”B82D.p ?WU  4ech Kʰlvw5,~$Nsp+I` Xl@ 1EAj +h]h.3FÕEN2Z1G8S<"VW\k(X#&iKa6`N##xX9~yB^rՊc17!0T!(R]b#y><1D0Bz^C7#a  / fSH2EEX ~x0K8@~ )cD(J1`YĵHEsCD[,TDzNBG l,d^PYZ2cHyz$4q"hT3Đn<0e9}U{؍gz" "e, `^ИQRXC8ే`7A elApJb p> !5#Nb0ږ0NVyYR|)>ӛ.YBh%c=JL6r4;8&}B 48D>hnT8 K5rqЏݢI ",@M-!Zf2\OHK݁ @\%)gYN"oTĤ;bɓ>])=dVmVRl 2e2Q6EeM Z"T XJLd^epD{bcsd-3 Jm1m[DX|9X p2>60txUˊdz%ߑ ´ ;\';g>Vȃ9ǃe$ 󺫉t΅(sWJe_c_LmQd)OHG+]@7jAGхՁLY;Ȩ$0!85Xx{V,ښV޷"n0W0X{&4i39:{ r`pEoPɲ&S20kn sYs|+s6X.r\XH`&7AWU:Ot$sx#1Y7XJbDʯD&jMLι&ƚ1S^kbE!># aB^]Cy_ a<<17Rc˜ c.`ZB$Z/,~صR()Z P:L/,~9R[_Zi RV7M=)qߊ_Wo-~/[}3>U*Gr}!Q3xLeq4|Ӭ|F,4ڪU0Y Y?7Tk0ZӍMN+1؏ MQ3by} XAWǀZ#<)U28YOz'%&-^J=M Pq,֔v<CL25»2+7Xn3r= &CdMmZYΒ}pXWĀ @DRQK7>OO|' `hHU׺ c"7͙Z=L7ucj8[Ɲڍvj[D@Ovtc*EvOu퍂M\`0s2@''3nruK78X[/B`$k2w P[#DN*#tO9BǙ#U=#d4C?y|#3G0/Ubt<|9;f^rf<r(wl'Abg |̘K13c$FWt ]k܄ 􇼴0f(˭,3gf TGi{%QfX3ط`%J07=0ѳ<`g؉0%]=+ZOfc•;/Va,ji`/FȪsF \#s,Zr6v3kxHZm~R,|THq*0IfNF~J_, &.}J*ӣ4XÉj ~_Mppȝr;q`O,#*A ?gyܕ}`8XUFR5{ vd %\}5e40CM @ZgxM+= -OơNngE-.=lXA(MhҪc'*Ԗ|!㋔ZBE^VwM05Rr;nξ)nP]#cNuw2L*Xbh܇ub3xyڠ_R8)(X$dYAuId&]͑q{61Ok?e3k?y]尥mviIo<#dS5G6\>XcSV4N'l+m%t+:.PrOm&R%p?_{Dy|]?psz+6yAϘ of )U7;p'̢;yI.scJ>O8^IAQzw#3q4]ؕ4r4uJ ֬p);MmgM:$ 9 zz@ 6X|ˆ꠸ x~fdHg^>S ㈖d42߿Db`,fLa`Iu@d-05ʘ)!TPO =r_ *9-c}• r"w0Nu[wbdp)-C-)*f̍9rn:yȖrfT<706L4cf X/Jط;(dݿL 8FagRN#9?0# Kd$>rO0!> %\~:FfA# |O<&rIvy*wT"%SW-6 ;"l7*4׫^pC9 BjC~2[fm zi<w&Ulȼi_qHc<~icKlǰ?v\\M*8 +e0Џz/~TqI?ۄ,ZWÉ_?&7}ᅉ/~5BV/0u}_mo}^{qӣsp<#sv-_.^PKV8Dt#Spart.generic_female_pin_header_2_100mil.fzp_f222793d96fa5f12689e28b7e2567b9d_10.fzpPKI8D=*j PingPong.fzPK8D nb$ KPingPong.inoPKV8D,搮#]<svg.breadboard.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_breadboard.svgPKV8Do#Qsvg.icon.LED_Matrix_LBT2088AH Kopie.svg_b6cfe6628138023898052f2d0749a3e4_icon.svgPKV8D'0 M̹svg.pcb.LED_Matrix_LBT2088AH_pcb.svg_b6cfe6628138023898052f2d0749a3e4_pcb.svgPKV8DZU+U"svg.schematic.LED_Matrix_LBT2088AH.svg_b6cfe6628138023898052f2d0749a3e4_schematic.svgPKPotentiometer.fzz000066400000000000000000000446111250202676700334270ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/FritzingPKl8Dn_DFpPotentiometer.fz}r#G?`3d24mZML-U>X XD$J?p 3g23"==qO >f×4'hz=yx?%3_^n&O7$7~3ӷ7b0LJwʁz>U _y8zoOf`>ߍ32;|=Wa~uz~ʍJ/ɻ2S꾺,:tOwOWʎ2䆲[A퍢36"+sQpwUg/ӗ˟gNl>\o.ս_p/o>}7RW\]+jV Aʛ+st>~O)w ~q,x[_ ]>A*oܗW_=M?\M{\}i_><\ fӏ>yɹpu7y?;mMiznsj>}j_e"{kh>~3nz7{׾j4*6 ~tdx6W}殃^6i(Ce9*߸7ƌyk51ך_Sn["*sO}p=up+e)|h4JO=Tʓy^OCݏh~=>aSI 2W^ ~w9!D6TemS{J\R ˨VbEBm5Ꞻ'ۿF'_]}WkP0y?/^g E?xnFYMO[(eo,{¦s_%O 4bi'ncTNFާQmFާQO;YO4m}‰(}崓Qjs Iu{CʶsioLnQh_|\˧li4]>^=gGwetuVɱ3RTMZ龧|ߘ;1s9D(0/wWf>:oOlp?s'33%w1>^&a=WNް:z;4pjQfFS{(,Es%uy΄X5\y{_\VYu|,)o ޱ:lԝcwE*4ms )4jN (*»!Uy;jиJ?hIiN/*+-S>%ۈoY HZz, skx6!C9etl'eA&hq>mwLFqe*ʔC+ Fj20MXKb^z(/UH" HK %#z /K_}~l4}qpy4>M=>x{Es|{>8_^Jྮ o3a LΙ)^ڮ%Pf7ӧ='}`dSe4޳=wSG<\Ź?k%^] > |h`+'a#7ƻmq:y?~*d['ds 3r4rImYEŋ{Qj p{5Z0# 9@9>q*i+jCηe7]HLA Mx?qv 6-OHiZ8!P,TfYu3YkH!x(o2<(U! 2Dh|c`zSDU6ӹ nU#sxd t9҂2.rEgW"J}d<xFy$_H+)mqG[/C"3wG?䥨 . N[5zVgՑR%rJL?t.|,P[ SEM[X=|uʩ +1TKqoaA2W\@;q&cq_[4;GSU͍Ы""70Jsf8*BGd;ov* z|j|:Ob"-(/S0#gЦ]/lP~.كm{]Tۧa/R%v iYi,D4Sow:h1fNΖڞ $"#ma$Ҫ쁗*3/ؿ3Șq!s&YF? FAigx\mIS>9s}檣;x;ϧa6R}K؀.3(]]:1&(+8ISl+2*L:"X?gzD^$5($]q$nS3UEY8Y9T-(,&//'D[̛S]nl7 {E-zOmZgT\XhZZZ= B䆛DF4mCI4E»s@!bUrm.]{l9ۑę%QKJu ,g *SW8bhnB hIT$ᚽI:plNNVH;rS)X`RYX-@2 3YBD-)wN\ns.HN2$:D[i33%Qqi#]2WFp1ʉ9kZq ^m"R<iɚp!'$wplI<#X9tiP8"qƌ WY\$ɱ~$!$\c \@j ], qesx"p+D˸հj"pK9~)K"pǖD:%p1. HC I$p$y”|jGSd#T4nUoT ^3Rʦ:ēD&i[Hr֥+X.^D5*xl@O6Xs@$vk@%E;Wyƛe8m KFkK"wHۡ˕c[45>9:[HU<8=lK̴K:ܡXZe5'{hL1OȜ39MLE+fo^)iÝTBvCdKI]fR'{)zOI\˔lCկUlYA Y@wk S =Tjg^ g\ °<- vUrLbn TY0M Z`;8"Վl:(\ E\KXa@sNkvH|>Ѹs_">C I .08C6p]Lد9[ƴrg0Etm(uk&vP#9Mo *IFTpQ!XDbkۜ{$ck䬫3{H8w'Rms;Ի|rDm2e8陭r&i|<+slY.ZWJϜwX;v: $J'aS#%nayKF˝Ŵ$ tBS"o KUΛ$"fo'-=, cyϓ$_I.iNtY :LDE'O"*XԉeDcelnIR-&7 ~(cs'\StKt]B˹P$>$> ֬K>('ˇ0}KBsJY.l1[T+Awp;Pԫu۷D&qMxDlXD!(ӎ.8p%& R"qq(yVRΖ$$$ѸJ>h\ۤ˲u [Bu5qR?9 V@WjQ,0 RiZYbŌҬ\DZ\ؒu&]Uكoh[u!r9~;oy³4s%1X*?$Sŗ(|[ћM f}OE7Jx+J(E.!q%eߺĔ&p}:)u&)%h6qMLnr#I.IkexNœKm;4;$o7Il$w=38RCHU:%RLy2ѰȆF%қCIO) Dj4l'$Ih\koCH7k^J?)j)=Ezë" kYjKLNnqB"&lIٶ䬧$ \8f-Jy+A˺62!0F[fV0E3R/FX.`GmbV0–}WRKL9o ןX\PpN[Vݙɱe&V1$&@ھE'xNpNTNZQ=H aUډĭ XTΛ$$$ѷeeܝٞo7"';YڜbJJ5EL-\H!ag$@s#*p=DдHqK"q]y|D:D嚽9<$*;S9Ezr!bnIN37ɍ%aoKX\\#}O̪,X\HYfh+'ZT&Lh P˘Jɸ8%.ay\/JpHpI[1;=S79!\l.iO)ZdXp'&c`Α8Z.iXW+YY Er`Imn[hr?$q$qfo'ՕZG.KyÒGsBr:027ZEZﷁ!0RLZYv@ v6RѰ[\, ܲ6+[-{u&h818ui$P0jHGx4nB SBHٳ؆h"_+zs۾)dΞMFAXFr´r_G&6ƢƣQ2ۡߑxXaG& ؑrbˢy2I΋$/rC%*/d; %1T2E-sX+S #+5lV&)|;ub5#F Zb*[4 F^8 ]O+Li7W*m2N Y1[%ܲy8R\X}2U5lH}*Oug3S,j*yn [%\qF5/UO*g 0rތ$xzO-IoˢS=7Q[Gn;Yҹ^;,iaֲJyս9LIE4pXWAhO-B IܭK9orIsIskh۲h.C rMsch',aBIP+ ٛh`+p'4Imn0[r˷4k$Q$Qfo&i%Z{`mg֦%nI /;Ly.W|<1;l^glQl -{"UM>sɵ,KqJKL9~Jp IpMRI( =90)dN8IYLV sXr%{zOy4{aTNҎv;%.I;I4,I4ٛIqˢٝƩ73-@ENt{f (C!Ѹ (vK4N&%g:E,u *TNJbs`IbsO[څ5˚CJ&QlbsmlX-Xn3\2Ι;,ڿݰ%.q OI,IٛI"tˢcr=KY[J\jXe/B;QTY9Ɖ-gaK[j\SOΛę:9<$,=083+vb"'LmuiRr2(N},=^H ,ܐvLnn8\hr$$$ѸgBz盅hq[^.mnyRPieF~پQ,h{8iH i>WDjKx;LMTnn\rTG%1$1fo'D`{YDM<\ݏmr~;1puD Xjp+Dfj*+sM F3Xuj;t0>N\0&=noMLK.__Ҡ߇hsD٢x#9J)A 5Į A4 ٞW01MEȍX'970MލCi. KH w R"xPF~/oWjL|rucǿ~W?e9:D1z+d7uq4 W >bmڿ6m"֦$"֦8fش]s!3.Ofu[J호 m`<_ԷI`2iV~xճ+"\gh}%&t.4DnUU^E2dŢV\,P+ŰFkmSϹEsݛ3sֱ壣"FcY8kHg)H*{eFF2׿\ۡ/.+YtuBM}̾Ӓ˻#VK62~v*BcK!HES^zRL8sQK{k  ptV˻E4_1a{k8MS|ڞg:Ʃ֞pպ(vJO)Իrm1h8`Nܬ$uМ*%MXZmWZ'4U_Ę8R3ѩIzOmKngX3=ӕOX݊$N&Qh"ndSbh/ uj M. '[SX497gikv>CgGD:j-(҉OX[@q)1Ww>m&E~\oFû/?{?gû)}W?>W5,uyO_7ˏ?y>}zwd4t'^EfϚe?_OߎݽU7=N޿˾|D2z@u0ȲFCa$f_m欍&>N&哇oo Gߗ;.o͜kUyk_Md`䀛aW>%u sb8\:׼hKۻqj뻧,?[sݐ?}-xM~WINs_|_=B ф(09Q|ȴ{tp:$u/I.uiT6~rNg2Wt3pGXw!'}ͩ?En(J3"g#~u$_SЈ)?˹ z|?O@wnjwBj1":e?5VͰ[sC'(|N'A))o@YJ?I Ǯ /s/=/w OvED7 os(뽀WBvZG{H,gƀD8_Iw?Ɇ̸P؜; iPhwO>h 2Ab*aw{fx.gc %7G݋q+nBFW>|a )wtCR@T8G^=~eC/B^ȝ2*RbFOȋʍ?"A&rj ~ j5Μ퇍v*WZI~PI'q?b։7u@w~Dk,^# bFgZCJAS Sa_Zr r0SG @8<1)=.10a8=,%*@a-s (B4WQ F4 yF(|{/-i]=qpSfrD"w[֠ߚ4z-Εe:,j*D!No |A쎍A`˜" z(Ͱ]Z{@2eƔr#ztEO!DDefk-J/%$*0 k lj L+`8^TaU0 YT êz۷h8. Wx~Ib@ݱ7# +9埞~Ȝ39')HP/Ss$e]%@"FX@Ƿ܈7Íxǚn@Ji3áݘv|ҵ-vx||ڹO=5X"]V LwƯ jWɽ`$b8 ")y{ Rt7E' Өn^`)@"60NXVwcFP&jף_|LpCܱ7nkl +!uۑjt}6 ׳bVn d;V׭8h@sU܁Gf}̟@FV$F9fF:`+?מHF4Dz Ф3y(. N@ f FAQgSg)xm@f@0b~U1tܑu ux1 cC\FX@ OJߩl Qh*7`B!{O 1p4X@M@@QoV7@, UbXS[T"$cȤ9C N- sN&?P4\b0 0k% *5R+F(69S\A\" DfgYE4. @P3:c+9Z,DA;0PX%@KV?8bo:XE}`zSv4H"WVuVUOCɩ_tZ^Ò5aR #- pc`l*a` U)*o 7[ʼ2 <O3o vvYpt$e82 <)oU \`"g$ }Bq2yHT$yCkD A-Y`@[˩0Pu` &4/W64 #C$``D8R n>/P ]q (0Ч@cAt[*.Čh{} 0B0r$Cc>)b9!xDCF@/\iPp#Ψ-7_ڶ"ՈCZh)[E 7ϵ@8[A W!5Fc;KUYF*?#iqYOUa1Й~FYI 04F LPػ653+HrZ0O^}Or*wu~Y)MIz- sC#aʸhHX+0._X4>#a@=ǮpPN@= T%t=#Pw@H1 $+Pbr">9;!'Аw/r% C #6?;!p$+Q00UȄ!bM)Qsr\;Ƣ8w$@^)aDT1FPҰ t1 _ N yѐ'[ -@ >_8k09Lć Ǯ7Q ZS761,Ċ)oO|C $YV\BB8)C?nZ7N}pΘnHD"RT%JBqwᕄ"z]Ƈ@ E`T F2ǕAO(2E&U=:E:v|v qbcx|V܃a&0@톁 (}5Uoi@g  PL#Do*OĄHpglpGJ@_r4H_z C|0r +s  B$Ӵ?wA\ #  t>ܛ;IqQ"D2S"b AQ \H!3lod[0ƇahV͊* U#]e' cαPa2 *tqb|a@" ڎIZe`x/_$Fi3%:Д`` -!ЮYtZA4-h\B ^+9}]8'NWQxT0CY.$cXb읯8A(Wy(Dc†*-f1.K 2X|`DBt{ٜ P8 lz=,C 2!c QL8"% w.'frl]9buo?za\ob rHT &G);kMby4)li4,Q9(3(xUX[8LX"Ju~I 6AdKd0yìb/Ui;u|*A0AcDUfS &1}Gۘb9"3"ނPPoDW"WU*jWp\ipbk5c1O6 ךo"(z:,~.:jAŖkr:ѦP JUBe&&TPy)Tq#:1qLmdF7ށN&,83 `݈l-)SU}#c$ tuC|,Kf8H sp ~98UB+ELEY`V'>wMjR5E na#"% mYK0= 9R}szTsU_9N4,&3ia4#Ut0jdAԯrn,'ϹEa1 ֎9y|cE,3nTGpOc0kZ4KJS%_C@3FXы n8+0+wu(4yA8́duςE„%!7CW>Ii6E},Š8m:\6em,VXXti R[%5Y 3nYrbnvM^*xRP!Yp{S1KC4X]<D0L``gaaNȃ+_C=X/?w8h^x/JQД>W4*+,3mu5^::KPpPp~}ٚ~eq~ DL;_Iid8Nc {m>0 IP0l: #,8Yy Im%/g]rCP45ۃrsB2xjRj_[,C NM-c0QH^VFهcqp.:xWYY`1f2 /{V2eU86qJy-hnDՖaK,~>U/6.uw5;OJ[?Oxx|x_&Ow/ooǿ܎.o\vu{ˏ zu=|8/s6s4y7yGcE2s[^q5$w)mY i։$f9Xz/p#[W{T[+l!SܱD@M>=wYg4Y)|]9|~]ƿ-˷i{b&c%𷟾_7lT]͏y/2vqd˵# /EGnVBy6|^L䮸o~s;s*w;} ?Oz;jUl4u5Yl򩸒Vk(X߷Cۡ0'~(gCPR!y@iC@{A6@ * 9nNYH:Dk|ÊA2}>QrR-*iNlx}%i$M(rN<8a??+ă!R% [c"kmg 3MjVڣ+ $b2X_8|L2@{3^/zާ}e%^pX^t[D)JCTa_*-\6'4j֘^,5Hy`Cmtm8ԊE /~d0Vh53p]G3D%`ձ9Dc4]ݏToā A5/h!Liox npc֧ n ăS#X?>-c֧> ,|d^yK؄ waܲ C`Sufk c{Er ZrjWLF  Y*s4]g&RCzXk%_Q6G]QgmsP$AG,, r0e6Qbz'W9KVԜш *z2F"f:IkM\M셫ɞ9d9zO+ySE'6(ڜd[?@a$ڮdk neEhnHښ0i|cubnQCJbnVR&%ٞRmOV:7COYJk7mǕE =9B@J܂>x;ϧ_^̟o*;a`ihp(XD9wހ&5kYXdliAu @ck rŸ%r6wPKN8Dˋ[Potentiometer.inon0EYځl)E,H )iVX"cZtǨ#ǹw,N2{`N{0}ij8ؠJ|@䐼W O`2jR'-ng6}uP:pF}OuUV'k26j[pN_t)hPNVy(CNkC\:c~ӲeMkG_q!|[GʨVk62vWj2rC? fSmHmmܨD9h|<C3QBRoUԈ4|t$V ,~W3k ˕A $FtI $<)V7QS_2)r!%Oҹ ]Y9._ͽem-bPKl8Dn_DFpPotentiometer.fzPKN8Dˋ[GPotentiometer.inoPK}HProcessingRGB.fzz000066400000000000000000003324741250202676700332470ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/FritzingPKxE3 part.alps-starter-pot9mm.fzpVMO0+,CEզA\".W$nGK)q>I ʥIf̛_&PH'rY: MoWx)IT`Yeh9匬{O0*Mr =N$Q qڋfoΐ_\v V !E^>4|t/4M5 1!_v0'!o/`j1w۹$&s%Ț!!.ֶ 9m%ULi_0OCgRdTjFb JIg9# [_ ћdv8/ye*Ay/DH-63G:p:٦DKܱ&CPgbM%s(V;D0m &JWIIEFK2?6QMWdLENHU ꑱ:Va2mɢ:Uy+ɅS5{(E"}aA6v%T6TfR/s\ G\ƍ"]d̩&Mf>-bѳ)Ka( .z"NI߭EF~()CAd'_=M ꭧS\LrJ#39v3P\,o8Fs:wZn̻3S(Fd޶2͞&:Cqz 6=49tg?wZkan%e.O$HVHY{_"UW}1z';R6şPKxEug6=$part.arduino-shield_r3_two_layer.fzpTQk1 ~߯0~iCa0ǥS}}i_?پdIۅX'O7a[ɔ3kѮ}(ٹv0+ krɑK]K7ɫv^e& B2[|rVM'EvЅ5L|z̆jvTkTs\z?qWLrYpu%&3=u!Kݡq0-{ѥ]g@8S'GQB_uN06Nq269Ҙbi>e--1܋_b`(J!aԃcP]G'— 0;<')a6XO۝\ Q828fM焃XqidhM.$?e+q(ͨv*C'?!.whuڸmOuNLfZ4oCtmYc/a?\9ZYŒ&:@aٝnohɇY:MeS/Y4ZܙӈvEcDъO`Ix$hBc6Csb ڳ]t xX򶍮1:h<~&V&?r?F=.tRMJE_(3ߞA2,<3P%h" ")IoDl*j&#;]]DKFgLPȀ%h&IKTdO:@_8 Jd ^BL*%%E5Ey*tV"\pTfnZH*Xctqws љɊf,^wFbaٔ$GT"o t,p ddu fqd _@ g84I$CI~#&[}SL(tLfftM +K4Di][% Z usLamoeLC'B PGy,yƪ  ¡b[L8k!ل~&&h~)dF#na0< @˪YmX֟lEJxuT,oVYwLef{:o]ÌmE)ytg/oA7Tx|J*V­D2/rCO7\jGíY*lf3|uzjZ6:+az SUd]naîFFqحaW/z*ܛ.8K95rhš]C[/v=Mq+8ra({U8WC{S:5](-4ţSGG/N=M 5GiGl X/ H-c0ҹlIH{?xTkKRzylT:b[2U4>j{V'0N |;s"щRq }_^H'Lv0)IIcSq!e IH`D1A'}!:rH`@K}VֽWsp8)I󱁃 ‰W#Tb>͚{o&=057&vv־_sI`Nf\pJ/Bd:1j4[`FONqn<[`O`Ny66<#nJ#m\bʿőh HiJJq\ʿ1*Q#R2 +tusW:5㚗UlJmMtj]B\2!|k^'T7F(j[bkdvڵB ^,4f!&2{ցD',.I%.5G0ɥ¿1.f_G ܯɣ¿1?tDfV"Rs5T7F?TRs8jRoJ1OY@*}!5AOǺt# t2iVT͑R3ңoMkݖ3) t2iVTqR3ΣoM>H]bV\TqR3oM\w0 'frHX!5c9*ƨrR"4!7DsԌߨqH{4+zC*Eo Q7FeTT!b8Ds ԌDuhVTR3~oF bҿ7蚵q+m\{Fpḕv8[sobӻ+ZHɣY{ռqkmT7+\4n=yOӨ5k֮ƭq5jܚc<Ѭhnhhnh*xyumP&@MA͛h*x,n}.xHdumP>@}]u Sϒ`3n45Gx/~x5ƈlv*ѻ>lZfE z j+j 1- b^WT9JrzWȉŸ=B 9F 9V<BQԫ,WD:?^}z]/Ŵ:V,?PKxEmY(H"kpart.Half_breadboard.fzpn]G?'/_=|o?'>8y_7>}vhgpz{On>[zEz}rOZzOOE柳7wٝ_zyg/Ngwח.~ɣO]|rv_gw|y}ݛW ڧqv/|^x?λ;~yyˋ?_v积.uqzWogw~6g~5|Qo6ū//>~/xsxrAW׿r˗~ux#sy9>?nM'ynsl^?ݧ8*z1:Wyg2^=/*~y(޼W/L^1h%~n:ͥn^ٽ^\/ΟW^kyw Q/NOn~?7=8}S{~@_]=(x?7Wzrݛ?G!vgk/em?Ƿ39/SK_K*z_a_Rҿ^>mX׻ͼoO.;/SKK.zaRҿ^>oX~o^)av)y?D/0,=JǹatCCCYJER*}.r]GPhRs">""GJF9949T\0ȡȡ,"E}D Ef)>9.r#rh(r4KatCCCYJE)=E.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29Sz\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K2]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhNu.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CY:"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GtJsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef9Ů =z' j~rkћ9w8wy#{7 a.tkћ1:w(Lwy#{7 anukћ:wx`wy#{7 avkћq;wtwy#{7 awkћ3^v2lix4LyrxN- i5^ox0 /;^4<Grn~KEoHbx07ݻ} y?FG4l]J?/~~߰`^?)av)KSCQz}g g:R*}>s}fz64KLgzp,3=GggÙNtJ/^3ӋLYJgz>ӋL/3f)>%L/>3tT|3b8iNu>k^}fz54KLgzp,3FgWÙNJ}W^ g:)gz>ӛLo3f)>-Lo>3tT|3f8iRޢ3ӛLY:Lgp,3}DgÙNJ}> g:R*}>G>|f04Kt8̇ZڏУwo0x-z>.~yOrn~?^޼ϔ'{7ϜfC9Ns,< j~΃Ӝ9Oôg<4r09<8y4Lyd<4r09<:y4Lyfc9Ns-< j~ΣӜG9OÔg'րӑ5`yf&Lyf·?έ˃k6aZ3s>5tx X^ jlMR̆wMV̜MV̜6MV̜vMR&x >MV̜ƒfMV̜6ăMV̜)vŃMRx3ƃMV̜=ǃMV̜G6Ƀ.MV̜QvʃVMR=Ns[y<3{9ߝ|4Lyfs;n9iV̜|wr0Cq 8t,X jqpMV̜>8'l´g|Cr<&g<21yt?7aZ;l9iV̜|vr094圧aJ3`sr<'g<3ßN9909t:'-لi599hyN&Lyf99霜dyN&Lyf·?''9,ل?on<{뫋wtUq{͟zrݼ޷͋/h_JnJrגywzu-xz'{$7ps|+py5d5d5d5d5j@j@j@j@j@jՐWC$Y Id5Ր$!IVC$Y Ij˫!KVC,Y YjȒՐ%!KVC,Y yy5P$HVC"Y ee5j(P$HVCjP%JVCd5TjP%JVC]^ my54jh$IVC[Y Md54jh$-d5tj%.Y ]d5tjЗWX^ Cd5 j0VVÐ!Y Cd5 j˫tAP@DuX2": r+C2Ѥ&e82 (eB)#uuR)A JXJQ%DX "WºW:XH,AD 2K%,%Dn "\.a.a/A K%D "bH1AĘ LQ&,D K "g4A$ "MX7MXGM&XD "؄%m6A M&&'D "r’r9A NI'ֱ֭D "wA O'D "uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@Q{_ԔW5e)e͵֔5e)Mٯl(( E"E⒁@Qd(2P(   E"E@q@Qd(2P( E"E@Qdd(2P( E"uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@q@q@Qd(2P(  E"E@Qdnn(2P( EK"E@Qd(2P\7дnIdIdIdIdi@@@@@@Ӻ~μ|gY.y+_caVXoMow}wֿo!qm\_M{o~ӯIdV)t)9{In޾ 8|F@߅Տ؞>DwovbN}?xQ *9>Dwgj5FPfen-#o$>$wPSvO=>6oq7woo||z؞=>Dw/>Di`jMtm_&BQ#(yȻɳ7zao?rt/|{oWoSr7ͷov]X~I>=lOeoQtwzo4Q }@&?|df˒/ZTG}I_G:y~gw?PKxE:!part.led-rgb-4pin-cathode_rbg.fzpŘmo:SX~ud]Ӟ[Rlo`Z5-;` ! cm#聩rƈ(\Kyx_g~ҍ`hx4 97giM9[83.lNt׾Yx&̷GA6]`k"JUG`7;O&&(;G*h !H}K?0% \^ u} #8׏M^ nz#R^.)wT1Up?d"IIp0GI_]VN[-ZqREL㨌TUHR٬ØhƈUr F"@r&v}H(!|0Fayq(VID$E0e)3>5o)CGpu1p}y/ۅjP*'@"K0j3X:HbM%Ye6{Nc+~aJ=q'qjt{C= FGv"\`uZC;pG\)n518:OON4j8D'*dp)WBP\4V[o0<Zù,!\I Փn\IE1i !n5>L%gtG gnzJ}M0 IdJnO=hdy %Q*56%>7 y"La[ dŋg-p/ YIJŴO^aQ 5l8C/gI5LRh7]ɝEj[^j ,rVq#l\OĮRG,^^c"['36Ά*ˁ(%-b{m.mt*V3(Fv9tkSg}OO#5׵&_Q~oq-NC_Y?j%?k@gHpPKxEyg"HProcessingRGB.fz}r#G|c1C&~閺UjdS=I}@$ɪ~~FG&@B\2@K 2#|Owx2=|uAsr~z_@r99bWj&W};ٞZEg77è7.2ay6.:OçW_:?ם|*y<W^t>nP1REv0}B\qJW9|8݌{е䚨^o06Z}5=f a^T"ٹ= B;{׮+xˋ·^n4_s3^<}{.:Ƿc/'~vvjɵpǞo]I{||]]שB׿?V.//bs ?Emw`\ӫŻ 7iMI`'\ {DsB3 > jXS^ۋ-Z@;?ύUY.?YOYۤm*ˌ 44ּ?A uNSrJ='i)ZdD;~#rLOG4bx%M8XҔM\p4Y숵z&-5cJ)JlhD5% 5ȹ:'Z儈uxuԡ?z|׷'9v S8D'mOO 'i8N5:G 2& 1D'S 0D'B^\f' Slvb](K4xTd# 1鐲ㄣ QǩS 3$}E}цE}B2ohA"3q3Jb!I=-Q-a-vamIF:TҿQd#j<2*e>|WGk"1TÐ!RHe|ĸ&ؤZ*R豶zj1O'~LGl}  #Bƥ֧PO5BN,#5ȸ}T)IsR>b|^lV--dS_|S;.Zx0=Iu1GwrkabUp!5~9;\ar!s?Oۻćhd}}z&+X߅S;}5?|V(͇ S\01;SkGB"<^)s%.W5˩LŮרH6P'lx*lh$]~%4]^pgR|¨T0RbQM}@kfzd)*"UnQ 6fl.A#H8T(dŏj (8ܧb#- 1Al7%1X=[yH!U}qS&hwI|`H" G#}*^=Ŷ88D͢\5,"WL`?MT2F}OK'd4%Mhbբ' !y$la+M/mih [Pl:5#L\S:i%ɍ>I5]>$D'^YӖ=iks﷖D~-t9aY!nL &#g QL"l$X)xf4 '%TΜAy`q2,Z4| \Qyr)D-|7xGÇW܄t}33b+rk'n0Z[2>Cy "f`qJ;|d}Ț_F'ɑߐuѲ"SSOVեD8fs0d˜&svowDsxd{2[bE5s;rb$ ج1}M戰>4&T]e+v5yx0Gz|9+{)m[7g";nU5Z-4E36-4M!d5uK!dAs<ŐS #]<oӮPob5|d5Qڳ!6N>LlNJo$rAa4b-k"6kgfFhcןH"sjftH5gHrfIJ85t sMSڂGgASEXrSW,PSqjŭ!NmڊS\&rZY)N}t4"!M} ַ8q #YxpK:8j85NwdJ"R kqyW4>Dz>+mklƫbڟSZL!Lj,b((ltU:)b}dA3VcFB:BLĺռG|{@j@b= amiF,ߑd ȌJ>GvJɵXZynyO^D' IF7P'cl3 B$ ۄD%Hr[Fi-mc'.qlbբ' zchv{`znN[,2Kj}VGՕ=8ZdR熫g[$P^]X&Vhvz ,EVɋMtq%n"(&V'*נJb$ZXbF5΂Vjqͥ+LjDjݳW=[ћ{Zus772?'~YT=?*<$?rDn9:9fXќ#$WfuqMu3opu4'z[&~RzW}E$qXqZW5S` ꫛh2qvW6RMm!:bujeWu^ؤqX%.yW꼷Ss~5U`5$ז&x9 qFm_Tr}v-2vfѣl^ȤEq51rth _GٱhO9]Xkpp8$1?ChhNͅ ۮU/0k<(}5Fϲ5ȴE9m> 0z-0N؈sve7LqMQ5w ~J07j](& f{[бr yՂMQq(PreF&-X_(8K=8DMW.ސc,u 8?j}l,=Q8A'R4jC4iƪbբ' !ㄋv(63j]2ƨɍ ǃQ<f0$QFH1mXCKm? µ,5p"6CZďDVjsOumD^yN+cDג-㶵%Jl6񓁍e-bi:ell/K\ƟmQ.+.!9ႩD1mT5Ikߎ(((S5 M "ق1mAynw}}mZ#q\mIsyH03lwc8^MJMܘՐ8ӹd@W"yU.CCH^ Kq<$oGI,,}}-t,̲Dw{|xL *n$voHq&CY&̚2AFߊ(j,ҤIܟhgڤYtN&j[;9_GIMƄu# 'U 4b3:8\Œ >5ð2S&ODW EWJȯb4\ړgժbբ`{QT[{Zj>EHj W~0cbW C;oHHq0W(g76OesFR֪q-UZi'q{h3=įV1xaG:?FtK8X8dݒ@j0)'8u6}~ ?1[bS"vx3iX8~emn3¡$*WK\LF$1X[n;QmiQ:Yr^.4t$vo7hT|J o h+B̰6VV;S s@KǕ)b=(H|--:M8ȡ"$nENΊ1Df)v 9AsZH\kn&+/ΕfkrkzY~"*CHtkI"eĴ*sW%wCˤFhut:o)W()OŶ(ķ-ڢ>ۥZ6X+P݀*eҚy *L~=;BYlGT Oމ1*sZTFXq9JYuޢ9J\{)x\V,8^qy<2.Hck-1j5bsIGWl̳ppw~2u`m5JTGbUnD#~ڜ#dmnOl0JܒڭsS5I$9O)((U7g My7 Er$vȑ2^s%^a'#UŪEj.Ϫdw%Y!Oi`Ve'M,pKĹ"=y_m9P$c%Dޣ9 (n) h+2-:*V-vWsX?-[=!وl lƱLb_Q ΔkaQ&1Y!.A'E)up8Wev3ZUZt;H9F"QLvZ_UK<I(d-Z ?>R%QoaO:FhHQ5tW=x$µv^ ƙ.ڢÑתbբAGw5l$L_|1cwF$7|ZqGfJuͶ0A(w.^@GNx>oAr+}9oȐ40Ş:8v+ k*V-L\W#PhVE&ӬV76 "ܴ:QbMLm c %ڷA5[?[UZh_F[)X$U,8QvFkYPK[-LNl,*4ul,< &V7쌑M$#8 }4q\Ly$Xvy6샂6)XHrR9.^(hIb^cյ0HjL ߢ@V)i m6d"X+(!#Gxq4"^3V4ıdEVUnZ5ZUd;jsgbX͵]/ADؔe:ptOpR-Yx&#>-7̵,ȹzO$USt;hT|k>ox~Kp$Xv62˂67gba\Fܵ?Yݣ,ٜH(XT.-6(F93 &ƧgS+j!6BR=E=-Jr4k8Ҫ0< mwƈ5sq׼~,ɥ"ubځqmQQ+>-Vҭca’XHXTHX3q1֚تbբ!Gbb͡GJ2cm<(t)m,mS?/XФXM[a==wdEgRjH/)D"D3L$FXvYcPwfc-y) uZwS|-[ [UZt;H\9H\u\ͭ#yPb I:-v7a$QuEÐDŚsb%H\lUjp#q#q}p6M,vkOϭCf C2]Inoe5t`+a4Qnlw+V$N0ݢ8תbբaF\ FZ_:;גmr-`B8 'Kn~>q5[`N{rԴXXG`mH"`n 5gHL`تbբaF"` F"`}0& b4M6,O H$_pXӖC_DmƱ#uED3$ZaHjUjp",UqOq8zKDCu`p}=dz|zz&J`Wɣ|6p/Ǚh4).E%y-GBG#tXPbtݠ5JߑO5uwN3$քy59̳4GqSN[gKLE._y5rjflq 5xʽl'u>8YL:m.y.\u-s(EF]8RjQGE}Dl0nt3w| f{Ν{?g4&rJ[ 9oÛۧvsb%8'5u4?]e0 G_}AsEg] n:3_7OÿR'7׏L^n:?w߿|]^o:?ۡ9|񏗗?~?|4|;=KWt7]Q_=]}1[YuS?vz50|w{s"v3=?sکaGϿN."AW]P)T^ox0x/$Y(e_|_ܹ/RhwQ߅ɉ]`i?#K2vI.u]w6㹑NBL]gᮤZ3(%'}ͩ/K7_ nvZ}JMy-^f&/*k ڿa]3Tj|Y mբO'*}Z+%?/h֝VnEs"v85;mܿ4e*eB ׮ /s/=ow OvED7oenr}zڭpݧ^]uL'YWv͹PwF~[*OjF8:tAj/FBwg~wwbX*\o\c(::U wg;˭NK:5-Bn͈\Έ0;e/n uwgZD^|VnY"[wR[PkP#gW9sڇTP<ms$|?@~͸opyC{W;e;Јh?`o 1 #?TV*P?`RiTTDZ^\/hy (Y8u # ңIR 4N븅8׀"q ?Asз4LEƏb~Bÿ3YҺYNP6a ^޺KH 6k)C<4Rc+ ײwTYY m6_A}#e c/4j/(Mwe`ˌ)]q#ztEO!DDgF>n6S`Wa5Ua=TYMz譯߾h/4P. wxvIbunkoF# hWݍ'xr6m{9gr$oNS,dJO w=9"rB?@zR H]($"/U_3hl@}Xe!-Vm`d00@AXVX9oo#kpiHEʆH/}v@qǜ Bh{ ,"Q$V"-w7" p#8ЦnfTnU];X׎V\wqvcp* n)%TM_fB3`bUr/X,0`X VG_A,I E@WpS m0F$b3-4oX/{7`A2Q e&/.nsOY*A5MT=Yhԣ:N5@WLAi @@-1Ȋ)`S@+cm^ B1t 4ANMN~:5z_|uw G:Q,'hHB0`Õ<ڂ@^hynFvCfhE ZJ׫D4 s% NåhxHMa z,hN#ԑ4u8пg.'ת0 1t&!aV )n0,n '00oV .[b%Z.+"!^L,}qT@,{AJp+(4;6`!Ȩ-NT gn%Jq';= {`eHMp>IG J=x `v)C^nD2162qZh- n`J8!O+|yah 9wm*@g]ԕ`@pTڽ :8S~vY [f꒜u0W=14eEx! tg0l ^F ]T0b 0<ؚD9g3OaN}b Ȼ|]s >Ct4J0=@ kF% y2aXS O@T!0WXt~4\gp]+E-h*;(k1.$A @IE( yBhE@hޢ $Z0KF @|^و0xjxՠ9ucceTFOHb N¡ tUL/E' w~W.49czVD""^*E"Jȿ.|*!U{(3]J憢ca0*R y#avʠ' NC"A N*">v|v qbcXJX>)0 _ ػa`%.+l)+J*-5]8;2[  (1!>:.P ҿ׀^h@$ \!HIšhĤl4; .ׄCd`Mu><;IqQ"D2S"bJA(h$# +0`&EƂ݆Y#]N ל"о npT c*h;F&iup >vv$Fp6!'Ht*˱`|$ZC]贂i=[иt+9}WprO`37] Hi\c\@Rx׈B$<&lH~rbvLHS>$0_ D1L;ly t%_B@UiaF!x2G4P&4 uD16 e@;w^݃fuoj& 3!HR;(~DP I0$³U 5(~17Ө_a-ι@@-S[A1x;KL[ o3" k t ]06Y/6=c~/5` хZ9dsB@Ua#(i_V[&eB`)8p$EJ^]N.ӱ9wqsZVxqraEy4p!Q-l$Fg 4嵫Ӥ (Rb, @q@shn;!hQM[7^W Dqb67l 1:oCe:]h >Nʡ 3@E'(1If3ALb6<ķ19N/xʣA(LAb:(B30r_q~2"8?vc. EEdAqj|`2u~q `H0">."#RF] FU'Omń%* 2P02C PD*\*廪&|ݎAޭb*v c8# ~Vc԰0&*f >"Z1]bMDZ/5]HIty]oL e~)nHa.3)kYljМ/ +{V(hV36V9=Uk%Q@/Aa`]ݲ.-,f 3(xq~< mQLi")c.X"ނP{koiyǥȦ*+848S Aq2OD!Q[\4TUJ+ /-š>Z DgUNTV_V[#T^*/j4.r@'&1B-&cP;ɄW7b1@˗fT(Ft~#c'~D& If,m/Uri6@XXkX Nh0Ͱ8[ ].&R]Pfy2Cxg<fMJckLðk#r8) uY\K0 9R}s?5ԥ g꒘a蚘J`ҌLJpLD*w?ۍ9<`~pwpSKHeI+׎g~b㰔OTGp/c9aiNÙ(f@D rSbE/2xTx(b}[YߡvW} >*wQhy)0b1$*$:8q2Va= & N 1\ DuLi,HXձX +ⲁX4(+cq;95A*4zձR5KaM:60KI~jWT^LM^^6!']2k/C48x/`0m8 É9!nbկj^mz|A:vvSxA̖5$~CSR\YШxt&Ψ%3A >ﲶ/[o".oᔈiz'&bRY".\3Ǯ-tGǫt:Lv)a%3 !Bge0)&C0zAs ]6sb[wɓCځTnoߞFg]ysmmcCœrWf]3Gwϙpflae7nRōDv/m3wa'O~cZ}r1~^tOME)񵲸ɯ~jm}^)"h8F;ډoӪ]]|~ vEK矿Oo^s~glEᆿr>?g]Iz]ZAy߫w݌N;Bڌ d98k n{7inzv~/އ]r46f!䷶&~o ׽]Qo~f-u  8t?L_xVlwʌX @򟿼wO%> \`a?q=o5s4_]M4םL߷L3|7,l%q?NdWqulW`coYdI~Bd>Z}v4Ok2YDv2'1[IGOtam9y#7hֿ[A}ur:>է:M#W׵Hzx14mpC_]Q~hn8 c9"D쒃m?>ϵGqD=ΓB+4hepZnl2^8.d\aKq,4d<7~mɛ 5^kxq89~Sq~rojtDE}2 ܹP#'V\XT8GDMv\B%vU5Df3o4DD5MZV~b96!41RTsiAM)yx%kM UչNV|aC8&ղ B3L_>?+;m8,؁59in 8όũ?)q*AՕc?| Sj?V4cunBD\ fb5[S5QvihHwkx9iƯ%_HknhW3Ѹ#^CFFs4cH1-AZ(%J46XH,`YހeQBdY! {E3կ:[d@csI%ɣY5+@Ng6eǍZj,W3q4k .RV9H|-CV=q ȩȍd 3m렐 "ƁщsE8׫~h{#qfL% : d( i1DÍD*2ٝ6^5NEkS3NhK4,P,ͷe{"ZAG 6a#Fb_ !"ZLF!'HknWCq[jxÎ6Y}r˝8W$Pӡs>P/R,o?Zz$ rkK8H^L~\^sEĽdw5>`k|(jr" O,H,ͷ:AG͐MS`# 3_jk{&ך0#pt2_ϮЗH/PKxEqProcessingRGB.ino5A @ EsTJ-6̔L7.xUJPKxE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgkݶ(}{>djox8-;$sKiw,U:-$v~ZII-56 7/^~R8\^ᗷ8???_o|zxg=~<<߯_-t (x>oC?6,C_d,\o>x?~ѯZʊemqqOo|A Í$/n/}|QF痯O«ڻ׿~^>Jh=A z_>?}7]]_^ŏ Kg>?~[C|?_z}?ߟ~~supxׯ-?{qs}?zJzOiV#:a|g_ώ?'}\Q0¾Xzyv}~Nj˄(?S̐]{A/K;Y -豼Gтߨ B+󄖢  l3yUI!8Y(r:_NvYʫnǗ\7?|^U)('ӢQLEYp'JaYt3*<`K|z[rq#\^:a_:aoO8:ş2w"n"r Z$@Ky' +;p$Qnuox^Z<`$!$yIꞶHIi$ 1b.k!F67Is h7V,@!\߈yӝ46-KQcjr5?/u3c[´$,T " A/ oiy៖ - OA쪭=x_D:5okc >:64.:{; ~*?? Mp)=~j2:5ֽ m [KUCkݛgftBtNdg,ITAYޛq2}S!5ֽ +G 8 q"22 =;H7!eķ8WWoܐxmp0~<. o5z! p^Sh(%5J5zc صnMxN):'[g#矨H=ۆ܋Gy7("x'jyZ MS .1QlWMc Xÿ!^aYT,cz&dXܢ  0.) b2 nXJ20I1LDCOD6!cB;Cʬ1d 5Z_`7 C n= 0bm1 Lx`xx! n0< Q a%aa_2@Qt_5t}J׻aFc5(4.G2 z\,҂7p١^YB=Np t`BU#}Z+S\ig'U ~j?׏1>xejb`S}\#eԸWih]KzmyVP;\;!~t ~U ~^)jNw_)r?G<t_ 5ܩ3jO>1^ 4`ܨq#V4붘L 4ܨp a&]p nTs~V)wƷkV 7Aau='k2P& :ڝ-$[de5 VT.{г-Qe(l&ǯ(X<Lp=_.D UP`E¯(cm85ioj `|5_&_Vc]u5$vk0 g*P>j/ZjNw.L`?O<ـ9IcV]faklpgZXqyOAvnMsH9)7@'}<ȱ(rAz5̞{; !h2yvqT\Q?6Xb oe<š)aR 0Cfa!#[H |ݺ7  V {2Dj=~{_|mBo'#tJ/\Wy _o~@ɟ>^/ۗ>CB۹| Bd8y??]8kx[Ѫɧ:oE _'~{?~/&G?'" xX =z4<^Co_BD"!z_/^Gf#kx>/o£"!xz/Gݯ|'ݾ_޾~{A k/xFC(V⨎"YCaB[Qz?O"@g/-zѿH"G{ń?fkCƌxNWpVhq':_z!qRF ƽ$]GtNuuT.)}qK]t=a&(5M]( EדҒ1&GwϒD(W>1RgE+WiWQW>ٽrM&+7QfzDxfT^0fc^yqξpNW>4^=ŎYoontvĔSףڍϜϜrkGb{Jy ?U!$ha8L}j>$ϋ^>>F>F#%$cN,)ؽɸ.'}t2e.Gi@ |(@Geۢ>D.݁^NzL0K"꥛IߴIߨINzЙ V:_k7I6qUN;tZI*f8Q&8nCuȥm. D]KkSuSߟmBwjiԟVOqSlJEݟ*fSQ&8?ˇwt's]҉<-<7t7`g7:۾ _=b]|\>:|ѣJ>z Ξ`>D.ݯ5 \r_zjd:Mbu-79l6`f7:?;$E_`iyfO""Sg`8h?~9AX{wy޿q.F(m;}:}ٍ¢}ڽP֍]\/h"thS8pWϮ?^d_q4; 54i xċ>KU h"$x-1Yx[Ȧ'ƀ6m'9KF2@ȧ9?b!YK,x{ɬ%?!LbY?q&X<`28ȟ}/>EfM #3v,KfMc &3~E,Qf-G/ JC28ft"A1J_O m3]C&HO?7tܨpv{L-}N+w_ZƂy' v͉̀t,596'"ILDɋ?}enA jH;ѸuImD)u!#%6=.6ڭin1ޞ3GںxIc٧Vh /n5{3h58{N8{8{vm-=Vueɳ1K ãkx<{PtL՗K"t4h\_,h^E9#nDBʑ52^/Joaq^8}%ZDmӷ&Ƶ8?](Βksv 9zFV<\"+H\ 9FQ~KDɎ d$!<ۗKX$I/ɀƍP|ŲHrZeYf7wXL,2EL͢}^0&Yd8@cXAPŜm=Bk Ns<īDm<׫/f~~ y;ٗrh, &_ XcQ >s'K1SRNVV 4Ɋ0,&S(\䇓(c *ew𥾽3=\ubj$OǕ-A?=XF-Ie 7;ZIOB'ZD}C\{#/ mv~g,dlIMn4wzBR"tz94>-WɘY'(dA,OkH嘨7Z&^)Möu=&ENu8 TeG{.:EϊvQYK~$9ُI|4]LQ7;D1AtM7)n> M#Ҝ#X? Ys~c 'Nჷ4%ߘkQ>HXWfIƷ5KrM4Kƈ?>|-[iR*wQ9MB}z;SV5xdU |ݣ'}c F,:6 G`>;&#ؐCD,EM_|i*mhr W66w{tfl~..S6t/*fAbB4P&׷~s}/0ZU9}5 $Ml/I!8W'+%8PBKa?cib)%U m(TR wmz:\+K}im!Ƞ c^s5J4,mE?J%-âɑpbu\wZd-#-=%qoO_މ%i|mtDoMMЦk;hvю0FN'bdwIN' TµR]'yz {8//Ǽ'Ivbv"X}|ԣ֣ @uڣPZN-(Ԕ"UGU6( LG1$0ƣD ʣ( c8.K8 wIgy`aKk2`/ ū7!o­IBIP\](gp]oBƛ 2:/ ;Hݏݏ8VIs?iSsR(BAB'y[}YCv$kp\1Lg)Nzt (@lX'A[~~Ҙ~~3,01$1U]eIܵ$v6~_mwVs_Y $#sO̸n2z}t!5hɍ0FkLsoH@~EU_;,&lpQygz3`?8l\\31:#ѣUw$ L#1$0őF %~D@ONX+9Fp?6)4S']N0Εxew+~iw+BLÒwai4O/ݬ^ر{JkB=9okflk5<GV 4`# k-}dVhh|iJ*\Ͷؙ@ls]<-6맟~ivZgt-Ƕd[KƢ|V>~4'ۏGǚ辽|ئ5lpӚ8Ao#Z̫gW|_K9˂9g9G1RrTqq7Gj,5ċ$jo̸q⍟6ى`9UL7y Ww8+8;bi,P#fZě<ר;~x qnsexgtǏċ>34io´Ǐ/''^lƀ-L8h>syYx:x,NیrW<Ό+x|D闩D<! wAXP!r Ax"UBл_,9qhI0I[NloFXH!rB )LŃ T?N⁙g2>c)| }b$AK2F3zJMq&8GFSY( MabN" azm3F3gJ^[=iNl:سf7ںTIqQ4b7q_k9.qb+"g_1N|_/ 8b<cQL8bqJ1N 6qQYq7C-bP" YXC m&Cmllnyl#ⱍȏmcX^~Iٔp#Z9_|y&9"?9Gts_IO0qb9"'5G6ᆋ.?7G.ʉtd刜or$9"?1Gn#cnˑ̹&Y92?+Gv?ӓOqò-.>E2'Gӧ.c<$!eX@,sb ~ef}r"bU閩T<&V1ě- tN0Hn* hXu7[̙W9ᰢmenSʏU}S HV d*?PJ3a*H@B2*?P8ۯ;>kXrB !˝uB[~Y!TN Z1.CBuܿn8b T+|>%*?vPO7vz.@BsxCխt,RAD=|*?xPofϐ:=Afj8t~;7_O~7<ۏ/O|9~"FQ %t+kHBGI|$Nl pXBK-wC JN(|bqΉ#t+[d:?Н8~գ~bA "t+"t~e}W,bqΉ#t+Y#t~q椋:'Э \0(BGE< է5(ï/~z VT/d . m:iAvl\Bq`#u80\qy8auoث,]/o/WvX"Ia`-w@vGK7[׶-'%<4??HKsIۖFwDÝ%6N=gOO:\f_>,?| w+X=̟ ғbwH&+dG}-qs+:L^A,^d+Gi.z!DO7 QTpuaN/W'N.7CB`bw)m`֦CW&JZYEeip洡9B Mm$M#{p(/"ȢZ:QpduԁGeQǬI8::bU =.w#9db5r4B#jjxW0# ; ;~Hύ n^{`"PǪ@Ei rC4pkӈ Q^(JҊnȊ5 Vz",ǫipFTD2D  H ̚nDϊztNu*[xi}Y|a-ʅg XƔ(!XGh`3r̷܀ظ76 F FO*B5 ,x6`hlAlso IھY [߿';6Z3ϱz 3Z9Nvlyc`NO}l;(d?A3r:t#8a_#g6 oI2ǾYQUb?B3eyat$#򓁴oi WW^Q3OX""-ȩ>BaMƁjhXWdjE 9Finv#hDc[@VF atd:Yr#&ՔkH"ZdH xF_@$r tdG7! .+eXAVh 5XGh`F,.|oHG6Sg͋6{ZwfD/sB>uO`B?OF[2wZc~V84\9 ..<|n>sB8{-VwM&Taeel;]SS m h%K6hyhsX_yH 2v>g6^ϸa˜)E 5㺈'"T|о.B,tQ ũZl\]:@0j/,WFbLL2xW;tZp,0]&ʤG_P1[\b9&U;0"!Z:΢͉(1 'Ng;[Nz燮w,MMG﵈2æ'˅"˕#Ց~^,RiF^zSx;$^wr'X8^.ٽݨ˝N~8{-^.jLn䡺Hjd77:?BAGy-T0 1*3d 0 `/ ktb}tSL#i/D2rZr%*npH ܨ ,8!;khNVoƿTPӘ%,JFpGN 0;F=;"q$ QsC0rҒ pʺL5k)%;_`B@RH~d€ \aO^cv5HQmP̸$ap$F` S$Z!Z2r wz]%8PB"̥z&O6o;Zr,>>=O(rJUjLCQ 'M>B,9Yf7IJbpE F%X`7%_j )r%Gā7+'E&3htfUS"d氵2 +̂1iPA ځʼnf`0T9iƎFDcYcuGYT'#kF"Xr5P+UjA2,܂ j(\Kc)$E66@J㾬0gH,-hB{+ͱ͸l+g+&6p܁Pf=pcNDנf[i4Bqy۝FW@5a/-v$ d.0WiUȄjybZXe UhSՃZ3MRNJFe\#h>#Ac ݴ%((QF&)a[}!y:٬씷ú襭dq֜Xre'wM 1PLnD[((V =dSKvE Xӕdؕ]S i68;+A_~-;NXZwnT@G&+~!Up.ZlTh޳ {ԼPڰ@ < M! K,z ;x |.YXYRFA) @gDAP) @ #<:alD-  @I QB1M? LL! *RXv$H$qg6)Bؔ1~ǣتc4-U TS _% 0Ӕ 'z5[ x_s^ؿ; Xi T֘[U;GA+PAR%ƜQ XFBPckmCDP@Ƙ7_@P!j yc5,Z `֙ 2cȆTQҡ1vrH95U:.14'C)0cckS-"i` T hQj+D-jVkvVgͶp7Ϣtk,&cqq%(X,4~D蟉r3nm׈?S2n%2{D/UY*LѸQkp8!?V@Z[F!3QVX,P@e24"BbIGQDrdm _-9|A51obOy/a ےrl_Lp-K:U,Rq7q\@:K\9B 2=!LUdHnXbB~d%M݂}KlxhJZOFbpY[؆kjLl-Q#*GVWjWTê  ⊢8bAv2kx>Ǿ: úRF*VqXE*wX#fIy{(⡉ a'u -aaï{W l1'u -aa˯{vXGA랬GAlUӖ_d㟍=g@luO68sYh P^J2z$ XG1Eʆ @APW[ q%lb N5 /gdbuyeË 3$fõw' ϡc^CK]0I Kv%2ٿ.‡Kb x4 W(X 0u32]PAa0 p I.:1yoP~ " *ƤV4?Y0Ĥa;3ρg@65,k.#g;H9Ip8lX?`_ C:W!0XLUg*Lۂq9Q\s0.cEzj'Fd85sR |Uh\2F!X)L׫XHC:\Bץ21Crq2%>r_bC1Ƶȵg 5wk!U n K.IX8\vҘ)5`)pm S}U-XwPuGA3A( ~e0+js7J+e$qeW (5tNVu0`Qq`8c8 P)ٍeAX/gSg; d YvD}ZD ?]0KXQ)S!"D:Xgϳ87Ye0UaIq!θxD\`9[CV ᮬim%J yNp̵ $#";YbT1ef$ Jna~B#K=7یe Fs4ݭ㏖Ϸ^__=l2X Ta=+8|ր"62ؤq{Q+V2\$^e^ _zu b:+B_P)&it-4_Z8lampZ?ol(C&㎜dlRm*9Z`#H>8)+b >lǣ«Ip6 |W LDvǭqFbL34q7?Cq4?{ܳAө琺ko&o'ᘇm8ed4#YpQ Aw׉V|g`J!1YN0e8dwmބT q6Eض/{H~s̩F(Ċ/;ǰPuie !hhv!pf8UUu#llR8vZ F1߸.j]8T) lýc8YYj9jln囹kv6nH'8`]#Ă'LU[{r{8lݾ@w '-% sC}+wv׮Wj|SL1,x1HvlXdɘc8Hy_EĂ'sI/=+kX4ЫCޮWÂ[n J{r+duuUtu*Igܤ>?`\\-8oca˭@S79I|[]sdr]TWJ8 tpqx:e–+^Ű.n/W₼ŦѥNN # CeخoXqhan} ~gX,L|Xh3Amfȹ98M>Tl@lnJNx!$GJyov7.Ѷ"U +*gV V+xٔȰ5.9#boR`/AʰA_$`p{Β9̞)4(/4TA$^& m$  ֙Ȱ.#b$^& m$C_{Al3,|̷ӜNkI帱Ѧ&Q2f{ 7#PNs 7>T]zq9n)k(TiAw ƫt@~<%MBH*:CfRfۂ̶!e6(&,G_V2UA'4ScRĉ :| 4<7qL1aHu3!QX5zT)|N}x k`PBt^c>2!koF'}ǀ"dBYwk6Q _AF\7D힙; )05.LMT=FI}mAle߸)Mn7Q>8Ȏ) n7QT0lr&03tFNVR,i)ĖͲ́ԝ\)Sܝ&Vӳ\PtMB S)SvJ/o/R!&{;TaZ OBA6OVعQ}J:A}8A^vJQ:ۤCi*(urwW6qkb'jp֖Q>cG,B{ZҭX7pճ됉~"Kg;S]x;6OXA*_%DC)DZ+Ո#|p9Ak͈~+Tt=D٪qfW*lJDn38`*N !W㖥2RI .~"Q$R@#kM:6;(:EJl&`f;(dM' 艘ڌ鉍\>yt)~_g+\Jl .#Wxb¤ֽ7}t+9mB,:OW0ؑyePeQ\bN( 1)!b"hhRB 4,Zy4*- k /e=~R%3@Jh( D `RRvUul|ീwW Gwrs)dH/&jU8)A+ ݖZa0f,6os&f<+ IA)LلtF),XÈtMNx\308 g$AOVMh]_k-\NNP%s((QDzHw-;| 6 S;AC%j+Pڭx\Yޙ6Y8ͅQ*X\'FilOGa]2.ü!OWDO^ǮeG"܌sƢt!Pl' lv(e!/s(ݳDtVs[#j爡92Uhb Jו5w&VM@X>s Y{C2e;Mx6j?F{Ama2LnR>mAZAV%h]@kиlA׵L< {kkiVO'AfۈZЬ=AU[(9ij5ܿhzFh4\*s oly,=lI{q0s7dɰꗉc@QAYHK_E$Œ`Q|oOvϟ_ֶP?;߃P-'܃1PAts!ߔplQ7À^tɟy{eeRiP1R> /.Zu;CT ŷ"^v}`M'K[VWps"B[ᖷr\U}VZw6Fx2b&B* Ҋ_U zHHHɳYcI+!{)Gz 86(,/xw-*V Y $Ryx݀*(J` '*89NTё|r6ld\%IƾÖh 9*@KЀ\:$51I`AMwn+;וd X1'tZS3iJkJQ:)K)c34%5FNu0Y/;6PKC2kej9 Wp&=(]Mޥ 7@|pQv =s B;m`c(y]P/$p⦠3?eszBpk[p9T=l;zq'v*J0vt ePO( uPOH[{6&oֳP&KCPO*ۈUU}-l zB0ʫqI"S儲^&tLv6WOPJj"];&x5A-W))'LDrPv_۔Ϡnl=;g)Hi' Ofx_ h^hYO~9<ݪh gDyzւI`'Z I&4zYh=$A= ePMȂrB1PN8TO(OzB;`•'k_OH X<,-DZ^>,MH7yiIu-'w%c 'XStdiPҦ"@ҁzZV=!H=!'1zAfZ6Y<MQ'Z Jw WOʯ[P8gA݂B}Z܀i@hPB>TP4P۝kw,"T7\vV ng\SSPŅP6V"-.q > _6mbi̧n>mt_]5ҤP?i|-OkAna?P,((⽂B{\ M8jϒ$ ޟ>Bؑ]ٟ9$Gˇ>>;g+ n=#lODuWB~eOܤ)  cN_J!Qw;(a `̟J)&"Hqgv٠ YP6h|٠US5(|ՠW sE4D$LYxgts sh̏L$ReIbE _4kH͠ jTA͠ijdWEݹlj>棚v fٙjP0?,Q#[yigTޑE#e5.1LV ;+IgcAH[GE7%D&OM`]48$(s5.VQreW$^4ؚ,g+ldB@\5X2(;jr_K{7\bH0v+ U%*^g޼}qOs+S@}TeRA]o J{ć[*8:P3L0B Du­(:\l0J)nh%,\^vh.܋!:|H_'R~%ثHU<iVzTYE+qX;wJ*kX{EByvSHBKV*UpR-"ŴHQ;u`{T&TUhF؄D= pp8k$&0/ È) W# ¶VuXO\$)8kOj%֩drdyt[w[řNB怬a8<æZY%iF䏪B𱌩QtM2 #7͸n 'j1%/&X!o d___jLRc LvTux)k;VH)= n=S .W` L R8'lhrF?аlPCf24pl8>ٚVT@Kq6"XS *i2϶C "Ïs "-JJ_5KB$f!aڱLRd֣J7ppŚ8 d@ 'G; QSn܅hIu~TR& |`Pv Z-&+j2F#/dZAm%,- )ƹoҜ P~$ ع85+HdxE1XkTcSATcBLߪ c !F:œœpVZJ\e; ʮB![, ߭/WG쳸0H#f+'^Ku{RIy"ݤ')CMs 5C:[3t.S3^\1a& 'dٚOT1d8eC:|Re C7sH$ s& ʍ,(& 4ihbݤ!zT' 1i9C:+ ж3[ Vΐ9C(!g)C KL7eH}x)Cd ֣! 9Cy9CGAr( jimRsL5ȏ:!a( ۅ00n_'#Qح\tİncW0'I0<Ó;grGi݀(P`F9Q(3k ➽&i׹0[&h\p9Ah3Z-4a_4p<4v 3[&dL6?xڌk 6odOu9=ҩn -ң @5ZNw7t-qDu㧕k66k[8qj#Dդt7cu pðZqcw_I%嗫yYf[j8I'QLדʾ5rnu&X/3Dž#W a濣qt/r#2F9dӞN' e6& Sr+I3d h$/$ FFjǑ8Bd!I`5uic4XqS@VbpTaDτq)Q)h$7|IFc.6 $GM< _ŦÛ=| LL7NtBK,]l ^ @8t3t!h܀$` ȕ yR5Ә\^o7/Y6 p #.`jԫk3 `m@k$᯽XE[ CZ D/fb #W@ZLF,fL XJDL[l "bYAD,dDb6-Du&o6:bV-8r $DĞΣŬ[lpJxt2"1+G]abRѫXUg4̢]\=tsSK#]\uR7C43?z10ܢyGx ķQczv͢D5ҘI:AUj"t*e~dS2 ͋*E2H#q'p $[@opu9kɦGM&ڟ(ȳQnT^Zfx*8וRfJ5t44ZpsO%w#AGa^*2.{ ip%w3w$U(NRp22 + TCvmFv띉!%gknijnբz6Q֦Xsڞ3Qp5XZpaKl|5yf8N#Ɉh[[htD{mIT`guT9uE%|l3ܨZW,]fQ]ht!*~":(x v{p;OaPpou j+Y(%gxe9㏊!9Nú0DXWY27+AB !4!FCBgk[<()[(U,˒3P%ֿBS*dXSC$OU5WU66Q pk E*$a4*(d;D qK6Vp dΰ Ӣ ʸ'6<1m^}~ &w&Q*_5NEJ9rVK91_x=.$s 2+w YDPMθ*=g50~1!ݵEU,s>ڐlRwK1&y[T6*Di r`gJp#Bt.<瀔@RեgCʘi\y*#Vw.M; #U<@#܄st"P4o؝byn;ZF,Zuw"!ǕC@@LZZ$ ueԝhi P0s YɉC2m"oh u[ҔfM!hRusFHqc *b8rU(Ap, |`8׀5DpՓvJܺ*7YG(?l5ܿ0Gu+єR9ի7B`8O~`&ԟJGVnRc[^Zk*ir#ٵwèɂ @*ƾNaa%üF6OMHu!' @r0}0rSHO-S=bm%3AQ/KPCL MxiE~]hUX^Aŷ"^v}`M¸A}d|.w.Bh+"QRh^ЂQpKBh;9_RFK$J`oX6_U {HJH3c+!v!- "Cz'Q>KEDG.6T ?7^M'aR ȁ(ڃ *ރ#Z?g-4ܝqX .})ޭ6,*4rF+YH1!\"={Qg$e+N4Tr!ۿ$v{QUTJVr*Jfm1*ќ@$ݷg*% D !JQd1 D}kOWlT8>ze@x\-lZ8YS#<>om$S+3+^Z`159{Τ|4J=$SRW ~S`UhW Hzt7b DѪ@wQ8E^:>++elc{ͩ^8>n̏ުQEez)ܤ)@$ ׫X~"=o 7?P;?4IN;{&QuoNW cJ@> iLATQjչk ?.Aco\ⱼGu!jcV݌sJ[YmQ)b5imJ'R|1+F<[9W_H|t(GlM{V(rDyiWt#n^ػ, o( j5혊vPw[X[\_Z2iOs!Ү\Rb`eC 6;S} ܴ&,Z_q('YZ@g)^!R(^rL.1Twq/QZ'!^|qXYq%.!uٷGk%)1K*^4E7qob5řbybQdQ#WCc`[" 1W<_b!8ȕ+լgzp=W@2;E_;bPYPxMVFp \Y6Qpa)mH *$Z`iy5 #%pI |oW |K -ķSl8 D A/\qW & fNj"$Pn!ZT&U BɈ(;DWvL3 "XjJF ̖.Az@h(B9bv۶3XƥnR*0DPOBMay! FK/AtLlrPnfة%ʝ9?ZY2r wּ!0M{4x4Hڠ8TdII|5mK \NXil%^Eg* 25R4Bgsz;`=)N#WV'jhk=t{NBseoJ[P6dHW/~Wn~%$6W,`Ŕ>]lUi'E'(N#@`Ob ?@胯KeYiެ<I7y o:ւ,r0uf92w1VManMv&) S1`A-qUHޤ>qf rB2ZȐY)ll%EWݸ1: 6?SH8c&=X{jn@*0#[y6: ͦo Menɳ֭ڟG?2̢<Ã6sTժZN.ϰXze`pf^) x7@x}Ҁ;@]-XqT^apJDee#o 8:rDF"m!;ۓ˿:iU_`GY:ث,q]{q)yl;FL&uBT u-X,Ą>:7 .>ۉ*_Ta% {Ra5tXj9<mhi+tDydyOtnf{>?ąm=4v[}ѷxsۣ2#H' ܟ8>U:4}?;G`_ܓBXfhlO!OIE8Ǟ UT&Sfe=AejU*ɊO"l)f\2[}ƣb h1$1 6=l{k Z41eI `Iܙ7,8 a]WD92+: )R!|Al&09!pA@s5re޵=~UH$?C!8@pQ+C`ΐc|C\S1Gѡ+tnBnR2JK⃈Z t!_2l˄TDlF+n"nr 9GBƙ?1M6dt`N&Vr Ɔ; h$v7p#S8R?SƦ x3á ,1ߙMlr3OyؽV)>1oSrnG[1=U{SV637WW54uЊE K|ZrܬLҭإ[@ۂ$jbvg&־57>M-.,H`FZ *=R 9$W17z2x=*6*ٷ񐜠j||X Ʌ'W,o!drsūJ7[Ϟ5NsiJ,!|5Q•sWƯoi||ҜS#'͵ W`wC4[ ^ErX{Va< r~䶼ײ^jE|o hvP;27yO.tdX;JIt0ծC*eZd- wNlSJ~|{z ~XC|+4I<.jmæ"69MAS@GϦ{n3nbp밙c;.W.)ETj 5 yLs7}Goon vkH7Edl` 76BGK+uמ3z!IhӢЎ$%[_s= ZybJ,&LkZ0pF|:_t+3_m$//䍯WpjPA|{^4_2_n&7yR6suFteO|S`+-#xB||$xZ2$Ukۙ kl4"C 4sv#W%QX}N(nc.KԗM{ju]ԗ/b@$lR0fã(tvײމ6ģ4 S!0F#nl#ҊBnUwD,"-(/4P> .VMVW/ d yR-ٴuZnR@lTjR+6⳹^9/N ?L|o߯7V^97Ӥ?脅6 tAJވ|oegaa?B|FDt?=?|*KNJ4;pAB?_.  |B} o@+/VהӛLTympT|^eU6%fAOƧG[ך .d:2u? 2AKrXG(-sـ:!Ɔ()6*` +!~o8]|,:|Rp!ii[Fsت*OܩU< (v)!KH8x0qj^jUkXLyI/N%~õ1ռ`_ -[8dQdi["ѭR݉!]mCU:)v:w[mLZ%a-}ӄ?3GƤL l+tr5&^P 7ba?M~rP9 K2Ĭ@R ;@tz8f+ rx8@-u _=KKDe:eeB0IºT܅[<زRunjV,I݅%vbV4n`!@t-UVwD ~-wF5OrqUD:nսBsX;\`Y僩OgGReY僩x ]r?gX>x~J-w"@6U[:U/NԖ*lݲ!` [Q/+j`yuu+S` b`)$ CU. -RtKJ4/ưJ|+T -ªL±)U^//uzV沣.C̊-L^= P%=N5-Y@z -"t 1J5fqc# [(Du/4; |3v bV,n$unBd ݒUUTiV6Н)X@[d L(ԋPN4 -T܅kXy>+hx0uqnP{* -UT^.,?p-@[i@WbDQ[go_ϯ߾o={v_||7勿O?믾_o޴x_ճg~7WWWu~z?_~lw}?!|yױƛi9}?~OTMu>7û??G}߼z~廷Qg߿xwy~o^nӘ7Ô< W߿{-޿~o!g<Y~)!Oϯ 7 )Я{?~^"?_ۿVAI7urvMw/0O)Ƴ+W~~~xr1&p02Mir]!z~]˗/E|6:c;1m};xO_p3eWa/?ϫ,\-E~F_V^b(/k"_k|ϯo:yym{ߞS?q0ۿ:~6kd?^\2{\_ 5q6sģb..q$ vpqOkCsOE)6L+7'k܇bēb..q&B?Opŷ^^,vqgP/aVh+\ŷY|+]<% zZ\^7Yl/)1@WozC{5| G*tqЫO`⛆ bCPc1BE Q!bE tԎ8j>@-ax*KR+vDS# mO wAEbQ jGOL5DojOQjŮ(jP'AmA5>赮Va_ ළ5Ӈ6J5LPYwAUUxpZ ZkN5p֠ O[+֐6D\<ms յRu 3tƝkP'-AU.Gi`{ 3qڡ\%?A/'vH_UIU՟>襾vD_ ׎*A z׎k#}UU(AoWU}P_;z%56׆k6D_jCm} .q˔܉FUU]k5;רzP}[_*A}K}m܁Ff;רJP}[_j@}K}m܁kN5 pר P1׃G5tt‘(lT=~?P8AFՅRU_jl46&?ب*Q[ejE}KU'*U3JolT~?8CFՏRU ~ ?Q GJRߠ"a/'Z[6HkUE Vu>6Dm TH!{ުԇƞmz#U%)doP\Ւ=QQդ措(uaN3v3w| VU__jnO> vð3 U~?1B措:5wT~?1B措A5wT%~?qUJokTRs~5';Qը>6@s5'; Qu>6@s5';Q>6@sjncO4wT)djO}Kmf=\UBU YjnJ\s39\UOe܎hn#U)o\UͭPs;~B ZTRs;~jnO4wR-*ſ*R}KN܎hzT[s'դ͝FhZT[s'U͝h*T~[s'ա͝"ƞhS~[s'U͝F=IN=a/5;MPs{N!m͝Ty>K͝'57\s'Uҟ͝T_jn4wJPs;~O)m͝T_jnO3܎UJ[3OYjnO;3܎ijQ)~"܎hn#U=*o\դ-Ps}E jTRs{jnc4WUAsU^jncO4Bmܤ TRs{iM<57ԇhn Ps{IU&U/Rs57eUknR*<ܤSRs;~)Rͭ\sO)mMB/5?ܤ*T[sjQ}K&d|TJF}T_jnOV}?Q=*ſI5>6@s2'T oknR5{=ܤ &UBۚT^jnc47E({IAsU^jncO4W C#U)do\՞UPHsUu 4W.i_j'j ~);4WKڣ?/5',7hP}Kj6ʂh*T[sgբ͝t?YΪH/5;( ~Q)~ÄjR}KmɆZ2G#E KFa/5; ){P!m͝U^jnc4wV3RDsg՟Bۚ;Շh Ϊ<5wV{=YI͝Uu okSa[YJѯ{Uuṳ*PKj\ŸT[tgU:U StUJLWNvDu̔?R]դRUe麝?q]5e\WuU_nOdWM#U]*o]U:jqnVM*mYUN6@w2'U onVE| >ݬ fբB۾U_ o7*|"YfURx0`jj fY5 Y5NjʄoVe*¿YNjʄoV}*¿mYNjʄnV*¿-YUNjʄnV*¿YUNv@vZ'UJonVu{=q]5EeadWtU^ngOTWMQY#UE*ao]U:USTHuUJܢjT[sP_J5)* {EuU:jnQSTDs*P m-=ubAs+ܢ,՞ۚ[TuVEMQY-;%5ԇ57EmQU: ܎h2G Tߠ?u¯5'L7hPk9*~FE ZT'Zs;~jʄi*RmͭFu¯5[>ܪjT[sPkmV5EeaO4ܪ T'Zs{UMQYͭ@%5ԉhnUSTDsjO mͭ:ub5[=ܪS~[sjN}OZscƚ[*q[U{NOk_82nUSt{tZ2%@L&-UN h ٭jʔݪTVե:%}'|]*SwSi[UꔀVޞPުL 孪T WN hm UTV7jUkmq* ~$U ZU'}~jʂjU!~V ߆诚GZU`Uu¯ o' \;5x̓yp<؃"(m^dB/wM@8 {!l+r's⤝xk*="e? aۊàZX/7Me@x lr'3͸%8 jʒQ*܍&eL妩/Wz0m=ja~~4*ܐ&meLVRd5qeI)jaaEV=OV)PdtA {YULe"6)=jSdU,:Y""+SLU-KC(jfBЊC@L! E!9v)=A`B@T;KC0(rPSZ[DZ²d9nF`P䠺Y""5eI)rP,LAN hEn Ej˒RZYAjeЊ 0%AU0"U:%%@9y,KH*daEI kENWVV#T%A;9R)=AeB@T+KC0(rPSZ{D29b`P䠪Y""5e )fiEVSZ{Hz)Ȫ!XYճN!hEn! EV Z "nF`Qd:%%YmhY`YEU1딀VRd5eI)jeaEuJ@+rK(rTkZ"GU U%딀VQ&, E 9F'y"G5AݡQUEu A+r(rT["G U/VQfL! E!9j)=QmB@U7KC0(rTSZ{D29v`PY""Ge)rT,QuN hEn Ejz˒R䨊YA*fЊ %Q0"V)-j˒SdU,*Y""1.KLU! (jd}Zsܡjk5\(d3i"R)=jSd,zY""jRQ4"u A+r(򨆺L! EU7KC0(Y""jRQ4"u A+r (6, EU7 #0(Y""j˒RQ0"uJ@+rK(ƻ, EU+ 0(ZY""j˒RQU0"uJ@+rK(򨆼, EU! 0(YȣZ LZC<CgUɮg $q抜XjcܡYUU)VQL! EΪ!9^)=Y텙B@U1KC0(rVլSZ{D 39n`PY""gf )rV, YճN!hEn!Ej.̒R䬺YAfЊ V%Y0"gU:%%@90KHjeaEΪuJ@+rK(rV[a"gU U%딀VRdfI)*daEVOV1Pd5(d3EVSZ{H^)Ȫ!XYN!hE! EV{a"b`QdU:Y텙B@\T7KC0(rQSZ{D 3v`PY""5f)rQ,EuN hEn E.j+̒R䢊YA*fЊ \V%E0":%%@0KHdaE.uJ@+rK(rQ[a"U \T#@֊2N^\dy~X;wȔž/2ML~<;yr'ɣ=% {:bD^gzz wtoc?buɄ] ;8\S{kPU}xOG,YxO.,Î=ၥNxOG,+㽓G;UWG)tJ#WϞmG (a';OS{kPUp1da>O;w:4=;LjQ#Lɣ%uxCI[#&L~zxtz wOryd"/3ӽ#O㵣'~+G&xoޯ~݃}GYA5}FuqxѨ}yX)#zyw䀟QG/Go8#6l zy`tz x<`tos?b];8g6[]Ǯ~נz?b=#> Î3!9ZQh0ͧCE6?G<*:g<^*:o9)їݳOC}{ {Pto?bȆ^=9.Q'k੽o8X#2q㸧cDa=# q 8 щ>; }q㞮=='C6{9ɣOo82qן} aLJf5O?xl*|3dP3:g=:o8C6CPN =}COSiTGL:yrg,tq2q/ˇq. i/ /LNq}qĈ>G|Bw>aΟmGL~ogɣo8X 2q/χiǂޟG~}3A';Ag-A6[.==^: dC I2P'{< t?b]LҎ3] iOާG>x>5}v93% }}'V};@w>agΟmG>73q7GL}#? ] sqڿz刭}}w/tDO7刑}}ܟ}N==ڳ'>6oq_O'Ow}>>&T!0U>!4U>!S#|lqw|1}v53!}}gBw|}?OsU=9~O'{ 9g=9o9X}sxF> >+~qNx>xq$ ^w_"޻/Gl_8ww_ϰx}9bFq߻xg}3<z1cCW<3+_{ #Î+ {޻|w';6zwd}œ;a{oܧo8S #FGvw_U[ m'AG}mWU{Րp$1!ji|{{Փo|ܫԇ>Î!LqR;}qR|&ۣc={ѫ>$jB(57!u?f㎏YU5ִJ~1z cVUu>qw|̪&}vܫNrܫԇ>#UUMGWm)x JkǬ:zrܫ& ytܫ pܫԅ~>N;޻jiwvB/Wx*ݟ~i{eN OegW3NGWm)xѫ>'rTj'}TQjy/S ~>&rhӎ`M4ԇ>~iji{e&r2[ݳY'ۣOثq?[R;`{˯DB;II*cd VڌVM+<ӎzDjD+ӷ(M{br쵙lzRt$5d!OR3>ԅU,cV)UeǬRP=:>f\ቜv:'}PO&+7A>q_Ǭ{b{z {Ֆ'߀vq,qR3xqR%RSM8//> _> _/ۿ%Syg_Ӵ\'sc;~?|?Ë_ݛWWcᛯno~#nAypv=dnwGtv˞۝z;tG}]gt l= lft~´B=Ivo4m=AXq>A췻AGʽ_b^?qw췻A_a+:EݏZ? /?ow7pW{h"7G{W{#Eݍ6v^ӑhA_d~}]GEݏzۋ_}__|ՇPKxE-P˧D)svg.breadboard.led-rgb-4pin-anode-leg.svgWrE}vbX^;e*p *B(YX*:%qpU3;sN_ۧumn1|{\5nK'=vCwi_LN?t3/ YNӘfy<>N앷nX842"{qhphh=9'cޜ5n1''juq\bd_m\.G$3jqV6gۜgcԘ'fuqּ//^otu~l on'p*sc~^gfY4ts25uljQΏloj0olE+绳fmsHO΁üIHdwѠ}ƖRc=x!E!U50Ւ9j,ҹ/kCꂹ7 T,NKKsg5 >V;9km>hN{q-Xc{;]>XWA.( p M4alDEv ;( _^`< |Y C-DHD[9$t=<aXTR_‰ :|0_n$:qD(QNuy f)wV㤷NhNdFF샙.bKb}1!l8Ӈp> G(k5&[M:q]. ы$\$X".RUSVX!+V~zL3/s,7f߷EDL+тͨ_cvxо!,|6P'p6$uNHN7#XgQq2 fk20q*4ek%h{b /8^j0 zuopIua*7KqF ]p}Jըr7tO*E+)D*l U8AT¥@/iE8t 1D{&t/.)o*7>\\슆$NeOۚ?`Z ќAV` ^4hP-ߎ "oT.%bZDge5HwǠ:q<&'`ZEk,kH Eq=ҡdGjDO+A1}]담6TvHqI0 iݎ&p{kw-dNDWnء~AI=$ͮtQRwK"m3'Ͻ5_-E,EҷrZugwa>NO CןPKxẼ svg.breadboard.resistor_220.svgVnH }BP^4"N&-!]#+dJ%v8!UbxMޮf=o'7ۗq-ڧ.fq_5;eoMݎkTrΧ,\_:b`U_ŴVME.{Žx*v[<HKgVAZǮXeo'MW==ۦeD@dZm8"أijb]hwEfwsX{3$fƸUb, ܔ̀0~N9 p@HfoF6˾zs,jPZyKxtKiW\Gmp\3T™q.OA3+U*2`idd֐OT?bV> > UIg‘%DžɈZ5\|<Jϼˇ}2"80/sHցD@ ,sXBQtۥ?K,AHNG&z2Ɗ?Tt<^-$RKq2&8gh ykylsѭߞUэ`J9 n Yf,.w;VX ؃V,A@ J1-VTv,p9tE)@|*,v!$FҢ  s,QYUOV!9 AIX=a(Cxxۄ"%m, ),Ȟr2lztG,C#!hp=)g{AɈGVICX#O1 w{yEj`Jjn:8$߰d6( ;6 W 5*FW`KMkJڀYAα2Uq?)tdK!\p|ƔrD $ ŝbNdl@+'%k-WFm GkT_Df~ k,^ƱJ#a?=ZR:JVq T<\z1Yf&I)gP&QP)nЫwʏ4@$A;, $p!?9Nfy^uy]x:-z[Вdf'zU@xi+O#)\S\ |1@@pRct _5\PKxEie0svg.breadboard.starter-poti-small_breadboard.svg]Yo$Ǒ~m?yŒ i,Yh/'i PIqdzGDY%7 hgEeEy͟~y>o~{Ys?~gǟw_7뚿맇͗~84H 7=Y/׿||8>5}*EYϷwytB>}?B0. Ǯi>ݾycbZ1y{Ͼxx?}<.~./} ӏbvzsp:ᝲXW]{|}o5?\?;>x{R~ܾ?yo@ٮy{ys>LJ[у\TbaX&>DN?x>Oퟲby%mp; z4߳l1((O !KDR?><7=VHk=z 61[x؅2>i.N+(½!|_s,L0) tI%rՃHTO e\DOElTF%8W> sJ p2N^![-$6:LdDE90㛋Z?QX˕G/?#ڈkRi>B AKzjIH4%F4WzGvD8VvDɶV mrlѷNΈ٤rgyy)#Mf0*eTJv╥YJ؍P^MBh?io](hj}+[Ѡ[ I^ &\˙\~O":R37J\?wTd~H m%n(GbKᅆqj>=o9|GJaX# !򁰀v"; 1 Co7Ґ| ?ŋAJ80/nN@ɘ 4-\TF/{GłFY$RBl\[`FA6k(OPQPa X6`&qE\|FAJ&]Ns Luqp8AS77G9C*\N=lM Pϖ-ff\92V'777FSZE6eV%25 {aVxN~<^!ôF|+dK +Z/*͊xg,B̙7`2\)!r64[ Fsc62%jE3U-i,;C i1^ V acj(hA]+ynh8ȑ QW4˜ΊBV+wY axg<%Nܴr-j&+ҝ߈؅p tVd"9dU@ ʎ YB+g֢D^[CA00YC/|v7v0_9B/9/{<4FꤲN&9 o N\1#>!tw )9E4m.Z`_JY^ |gTD5w[C06EЪw.L)XS2LJ9VAXV3;zXA]kҝ Pപ%\j]zb;GƷa9>NOa((lMs̍)0zh 5w2-%hm,6[ ͓`y. ^ ab,(lMse,ыҖʬ" [Fc]qW;ay@ ֶK_{ɚ|9٪Ú-)lMs Z"23bc/Y7Oګz7dzZak,o),].'x;@Rؚ|5"˥;ZakcfsD֍H:-H % lFscrsG'.ߧ /d~ @h6fwW]t_ RȜ/3'w:7=lᚐi?jrj~.ʛF0Y{ up[@pU݀)ձc mD36~R#xMkj #q39$6ϽsW_oVWG3ݪY\\.ώfw6q_{-/۫oW_[ Vo>f緷/󇇇Wjq3sYLt[@O=VG_ˬb#\޼0)˛r݋rRJ=򷱅xKfoauz{~43$?Η򋷾_-^_' qɗedu\>T,KH4^/o vX-.׋Wuu! Ee_^ زj<~Xme߬ZZd߳5|kbUkV`-z4[OqP>A(N񇃺qؒqjuaԵ)A8m=4 txg%)j~=RߙAS*33Df&TtTqKەSD渀U@'_R'jh`w)&mrGU6'8Q`&dew*8Ql*\laiOq2c%Ӆ5{Z`(:xf0qOYQ)˄A{:Ng"j!s}`"ب jHؚP`YjD,VU"9 'OyQ(V5RLכFi慕_,5^h,5=/:杬u5{Po;g"0K;z"9P~|gfSe|F^\6QT3ywru1pٸڦkZy1NÅ]_m ;Mb̈u/1ԗd~1iŌ=N{ np}_^ @ ;KANԖ6ؗJ{%*-m:,O 8L>zI 8y yJuN.T8@^™Kܔ<+;c@&Ĭ!Po;S֩^j&jAHސ nXCVېzysULKaT,z!o(|F" X;D5bҞ5QfWj:6 %HOkrKseQ!ڟ<;qpΟ~͐?q~ǔ7q .IzLC緖ÈI{iƏM&LR|k64hh@{]Z>;۵|&GKpN޿~$wqMY93CPA>:usCPauQA[g]nv>CzMs>|܋1Hf(݇ڜFL riDwWkFL9yLOTrTCn (M 0[psύdPc7l,G Rn(q!-D! '3s5[۲բL!dQNW}#|މh@aUʉȧ*ckeb\Jqw%NBg/ ^ȶ+ʉ!#dѡabg;}4e'OM.%!t4 +m>sPϖ]9YSFqBE> IL`ݹiD( cm9J@zA6ȠٔحPyhDpAVؐMd5Tq\9Hsi[5$6f# m")˂+(*b /JиgAI0uVKD3 m#ZR 3 CXfO3M{ xN6<$sCGupE4P(C[0:+rjd'Aj-iڒ|~+6ruΰ~j^\˽o-*cJ -9b2Q!&!.%\Z` }̽ l(wC#ctVSGh+EB:1:Td@|.$S(r0".ngF<\*H` #@낕SL7eG2:fT{K"FG#K|a!@MH @(&:ws0`.kPBy,ͽ7Bɠ L$,gw,.-)K܅1:[XH݀e0f` 3DNa[خ=J}/Yz dZr``]ad}OݹD757:Pf#b|,SO}_PKxE svg.icon.led-rgb-4pin-anode.svgWn7}v>~16@R}*\IJ$NgZi&-"!9g8Ϟً|VQ|9]ͺbT5z7M#^Ηn9VūKh+TxsR\ܭWx,WK!8A*%tLh]N?Bl WcQ5msnۋ+Q]vӶV6j}M-4Z8Zv !lTM7T,G<y: 9 9bRJ/ONm7]*kz-wCkohPqj:U|; qr`tjw-u}?McV~H2S[3Ӥ-MNښI R{}7~j:L2s~-mBj+sFI1ؚum _U,*:RpP2%Ӡ"Nzc1{g \AC8Ll;c;mvTHK~y=H;:rqy<\t< PcPR^~ *AUyP5 ;Ѧ]OֵF.32 y@qMV-6Ac]l{i=k>}oep :/s^bl!!lzS Wod)0 \'8n?^cTb @lc%6g0M|rpS[8. 6ab@+acZMxz‡-l|l,(9= ˠw 85Nh2`%衡|qz 0*V< C8n(q^pps̓VHE" fPH(IHMΤڞk҄4FAQ T]%CO횏nҨD=Cc T2Ds<{JÖsZ5tn*K&}9zoiw(h=j(#xQCdMڒj*VY/2d`"FJfer(zkyK(1tGQB3ӆg6" |I{@X kݒ^Aaop6rr`ucvijIzБz)V|2tAm6*Ϸ&'`2A0+J8>K=Pl(Y:c&')qS۳obs1x. }PYtoPKxE nsvg.icon.plain_pcb.svg1o@ ʗ#];tjv[:ra i__*vl9H=~Nܼ<-s4vZj޴ϣ\MWjjiѮ9wiE<.Ç!#'[Lz cwxW˴0%TN#ͤyOR|`&~GM|mfY.ǗY*̳OnQ/Y=}9z<DL!jzl2766j*m lJ^=Bd}/I4Gx1!@UQu_EtTmC) B1Ƥn< G%!HEցz"<BHAa4X }RΔ(rxrO5c< {q_fL%$I!&41p7DRG<%8B2MF%l5Z(e"f0N-W; re??PKxEcE svg.icon.resistor_icon_220.svgWKoF>ۿeKξ7$p IS$(-U$Abd3E9Njȝ=xqeYF)2Ml=oVQ}Oy|]BͲJ^Tj;myELY;[V]׫_ڤ7mf[Cz_ﮒ~qEç7 ($v(ĝxnf+ FJovhj7zYeIHYdzvlV? !wy4yy[R%顮EMujM2Q:ivm 9XldzʹͦYRr&Wh)ΪO*,/EYj\jUSfYf%3+HievO|R񝟝]kaxL&B W DK/d2#~;PD+ N.cIG|%uiS*b݃B5F_C)M$cBP9a$K#.+\̈ #[4]JD9rk,9xTP (h;SKuhgIdd`iIf@!g9gl遶Ed>?Zһ e9GQrUˏq4Ld!tN7FKjr><]SjVRc*W5>s^^`pla5A'0ٵ=X1Ԭ*Zsiΰ?Еq7(nWjՈ~,6݄dv|?v*.'G!XGZ~ YMɗ˶,j{/ei>r|}&k MS Vw<}JͻovC/c\WÛp8=vW=W|y(<%Xv?GlWKɅvn皡἗kUÏow;(o~5ww~n^?N\.OSwxӃ^_Tb[^O1JA hڼ~4;쪂VUo|w:+e;KksE=s.4hv@̴wN6W<(l}dfG#c +kstW@t[.0r[@~X9=J6A#1hɑRK$'%'J<]CveKqe )쀹c !E*y$fFDTܴ&9;3x9H,mHodJ5첔cV{E㿧ʐw\|E}-~@uѕ1[w*Yh+#z@0X诲9odݛ:X-Y[ 1… n…P q? (?{#tBnV:hSlƿe :5`&ˌFFg l/,8dxxdVu,YaH~@th[d9rpQ"Ey8RO[1E>fNM|ml̖kj׻]Ejbx|hˢ{ Ϩ՗X~w{[Gӈ^L5W!uKވw4äbmsa;h@N7BJ߂47`^M+3n dπɰ۪ Zw%P VlE2;;DZVFYY3ō6|T^CUaJ]e2 3 p2 n5Nv>^?n>@`:pulcw?vLjPu0p8XTC=zK-R/=u=Sg*eZ|6>OXVReHm.?J AMY!k!Y}q!4*%j5A6P%igrKK>w9x [ 50ʁQ*0+<v¬%aD4 m!&{NjTΪV陕 i܉5#Xʢ=iWY#h*CsMîhq^f T9[?t-03+|pM2P嶦XߜCz4{<\OA FXo9WV̳8Bev3E701(LalCJM*,XW Su 6Fc#0 rrbsjhTcmv;VV`Ў.f6@\0 &kܸbvfOj D $cUP/ &% uM HI*p[d T0]T >w2 ATjWd:7Rl)GLRG4Eft0RSik$fE[DW81R'h -(q,5$߄QT 'oge.%SBNkx'ZXeĉOF1;K#*eX>k@p9eUd#ĦM)M ZhR:݀ |anc3gOK\Nu=?˜<yh͘fuaZ1Qd*дӀGT)9Y!M"Ќ#۠j1"@3&s 44&Di\/Cu"H&Mr={ÚD ڐ@v-:bx9akd%$ّ,FR.hIVn ڊAϰL# $5DsZ"YiLt:ɲ wĈ^Ȑj 8 JuvBUr'U#+="icKf4De>HLeeH5fy'e  pE+EУʺb+ی` T1B{4B"?L-rЕ?*4Qтƒ+4}Yd) -o^[rA?Fi24_3-4.vܤ$--;E>Z |P77n$ڠ04DFM4k⦯#'[Qఢe$هg_Jt8jDCT4@'TS$kRxXmsqOe @B7ӂ\\9d5hfGC'xZ6{H n&,16\tG+ӿ7Wk%љVaEH.!Ĩ lή.*NJhJRpvcpnMద%$E l= R8)z70F4 ly6Lɚ<ִ̓;[[D](M# '*e s%t[G*lmr8Ő4/%fF2T)7k7U9&.̈fz8A`[G+lebkǚT)y,5! NB{b\iU c㔍dc2h)BK8y,5aK1] cJ0JsL1]Qq [s:8\C\$dz rz%\H&je|].|ȅO$yN&,Ub6`.(%vƷ6rbJ 奂=U,@Eֆ.c[0ŔEJ7[[`i?FK/15) ${R3[[jI+w# r9ksF/q5aKZKFyiIO2Z2Kl om%-+W"reKVdڨe܁yĵd:6jkYx\뙊EZ\5H[(I::j+B` Hʵو8$V,tMF,c:o_:vKl om2v_%ݪ%"Yژe9,ަJK7ލG:|.=^#80^:TUiꝱzSUkq"s0Kc乗f[L{kln٢LWq|"N@Oh֙:尐M%s~nКXq:"/s4\&\VOҫ3;2Az+EBdž0oGwfiyr9(0i^7q'>ݦRsW_}wMo@>O5w].hgLߥ|^Xqc|$m _Mvnl }ݸi~VEdq/茀x(pGZ64H3]rd3jf繎; :pw7 |Ҿ* ѡtc~k)UHoN wAጕ Z0UZ309ՇmWEiD%E[ZnMw|"b}d 83?] Do&hF,kgL_ᛐ^V5Pq~j.?bj>#g:5=pHq CL#QN#ibz PS_ۢ(uٙpf0J,VBclHc6 |NaTf۲t_7kj}Bja +dz";20xD!)sCw);C%\OT1g5X#)BJV)ՙ+vRوI -3Ug]憗J?H/PKxEOg#svg.pcb.alps-starter-pot9mm_pcb.svgT]o0}Nŝ4HZ-Rn۞\bdHHekhTlskۇ6V01P&)Rm{/"Gw( ;iq2Uݦ@(^ٶ,l :. 6yiLfk?x?rr MfW'@<ƾ'ޜ > ˺.'5MC6cvQ.uR12E Ʉip)4&pL51~ǧ+&㈙ŃE[\rΝ5f9ǬИrK౟˘!%Jge0BVͬpˀC.W"YeXѨ٤$&U(k$)RY w46U7F%xԆqMabg*AWƗDRE%'=yDWv.hG>37>0N ]]P Q94v>S|\u\ ]T:_UUʴS#s(^>}6ś۔ou4i0]Й]+GPKxE^y svg.pcb.arduino_Uno_Rev3_pcb.svgŝG?E/! z>D9͡$-`o$4BQbv5ZϗF菏1jYxY]\| ?{.ogw+ EH.˿J mѫ8j>m?_tZE8f6yuهoWl>tv~ֱ^Vls'7ݥOWْw1Ќjsɘudzp$cûܨIlG6el >6D|{^wv \|.uxVpzsA+cuOm#BB,ӂ #M$iBb뻫U<w*|!muw\l d[]2JdAU$9ٖo JdbSeJ!v`+`UxDckV֙ 2KN%%3P/pd'fF^6F^k_J#B 0h V0U Mrvsrà'.@ gm)!iTg\殀A#O +V(6C,+C_E>h|k2eU\ N\m梎ޕ˫J"/|@b#,%Ll%Iqn*mLW\g~c,&z+Ȍ6I2GRʕtXzofڞ}ҏսIo/%!Amm- E7>t შ[9u:`#'jȔ".H*`NR񙗤6EJ)'~!S)XlQ՗*1*:È-zИ|+ A3Yt~(-!2H0`X"ņJL&Y|\/iyfɗ=+bHNUaJOv)%Uӡ4-Ȅ'j[p DxZa˗fx-[ 2je *ʶWjA%Zj3΀2F*np KEO`]ѐT(,ָ)HsR?_ Dtei:`e2 s7ԱtZ:3i^KF'RgXåk{X,K 9TjE0v䰶qRgXO4Bt(43,(ʠU1ޖW!cWb xF9l5<0O^C Q*j,h(. mp{0jߡcO3y9`j %jߗ#W&oʑm.#.]_`By#=׀j0{Ey̨VkY,PQd @?lgyTV3l@-38{h(.`pUF/}6f- QH-b}Pcv;&y @fjf} | gvu0{Ey/+JKUfϰO*f}`Qddb_VOTXV X= B%=~mUJBы|`NMGg I gi0zj>ԻҐ}5,/7үcL;d_Ș)~#2FHVJ"{̫nv~y垙l^ם__ m̼;Ъ-m&T6}P=ݠKӭC;kh70 rխC{$e^yH;m^yHhb/XL uU{wp%c]!W*zZ6_}FL Kj_/kҏ6zOYRzun䘀hK $1첩e{6;wt!lHW'er쓝.6={6@}y<=`~EX$Wl߃AbݔS1q|?|~=RpԹ!!ي_[oKmfd8K*)c$(GwL4\@@OF|y5%=\n{mvW5z4l19 rz0M dLݓ(#dH%SJ}rSf& a\m׊|+ZL 0^@d_yD"_uA/:M kO.6}J94gC(^zO>!ȳAߓAF?lCFp dk -W p8+gy)ꔜgzEya/!_4./W==¶}\gl\xxFzu}z{5z{^?+BH!l¸m&M~))V|tyoŧg?}Wmť5V"2>}hJI}2{ `׊`'s 0gqO:92Q4q?6ǎF(bAB1w*CK bsYFlQĊ؅E)c2̞JQĆX~P / xvM Cd12VI|# XB#3&"at8vZ{pLw{JwrQy 8-<O~5B|Oj-o+38dsc] ʱs2 'xdUsW[ʊq^+|g{=|? i1}WoUr 5 TJo+QSWtB];\mipVܸީȚEfmico~ PKxEr#svg.pcb.pcb-arduino-shield-rev3.svgU[o0~N~>M B5JTZiO7a$ٿ߱C6JJ''-UdeaF(FH4+f;;';FPuܖ}H˩By51!& %Bo.*]̾,1ƛ #E]Gȶ5ٷs,g ¶9>309m5rjEV̹j%vK1F6@0c5(,jeγbqȑaSp0ټvGX곹fL'{ڴԗE+uSii,fu{V/BVJ`frqK2Wq;0] ( 8)5}XPO:y`>~U_"b*iM+VQq3-.ۖ(u+@^x$ڱ/!S ;7$ ^O}J|L(೬Ml4@q澂 @;~Hl7M/VxߊמI\EhwUuKWz~# P?@:DzF277RWPKxERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svg՜YsHWqU1 ȩovsxHXV"_=\"֠]Q ==7K.HVau۰t-,cň*`G׿FYi0a.0XW^Bh'ddm3nt QL, cj8].H\a@'V8d }vdq$ Lrfxd="!2čGm3#=Hqh>11Ǚh}6;Lrϵ4=&Nn|rs/)2\ygmue2Vj3BڒMӹjN6uGG0q 2e*$X`T+$s)+ZIƾ}\ f6g>%6h;̲]_rY"rښ|cqY{6'?8e`Y߾رv$|x0+sc]|#*@,3l&US&f24dκ.>3r`1>#xD&KT嘹䜻̇ 1f]43 MBbe$ wL6zsV979Rh߬qIFFYkGQd˼3SF*F sS"=^= ߗi|43WC퐸 <SbFiu8 `t26QT ^_٢BID>8A`BQd?_juvQէWI3@'q|-&b8e 1F1tFW0={~AOi =]$ILWQmP>Cm-d>WA9Jpi5"Qhgg3%6EuysE}L,{c *O(EiRe4nU>GGa5E-I"$Q`Y/ Ts*Rf]-5faMdH8֜PR"oAwx:+W; XKFosIJT޴.{s];:^=aFX4 =i[%8TWM#e_X?m]S[AC/|O4.n{t."_'ɯؿgyYlvP 5w%xE R[/I t„R̦QDr{Ϯo-Eh=$JQ@SW񅾈6Rj-IRqmA=kBjim- {xnfeB̼4ANS3jI$UNCQ%2$Nm+l'iqT׹Cd䑹U# {F:jJ:Hj^ 8AfJ܉;.G!⣤/tAj*em[-u3;b;8]a 8XjE UvC rpBǤ`95:V=]u]H|Lb9Deߪ3vY Lm 獻)[jXwI2 I:15oJ@wݨߘr|oNtj17~G`&nM?&2,emAT].jd^m(LĴqGW31i0_̦ԦfwNm`p6h)N[A{gwSO؟=7|L5kzJXt7r?WǪ \n̙hV٨-(x4VOV|@Yp/ ]n/k%|Y+"N. lqž@)=1KTA$0%UEvn:`Vi Ō@a;ؐNlM#w R ܗ8%݂:q<%6C~l$H5QtV%ɅT_BbX.ofAp;WHB#T> ͬm^ޝx/o "x~v*ǔm7zPs_PKxETZ svg.schematic.resistor.svgݖr0} 59= $!Ȅdܙ@A1b)#8Msh9ذZ/vӢ:mM)SZu~$F/M]֨\"ѩҫ7iл8ĺuE4Mww>!SJcûS9FN}vN@y5 Lq7pO3CQz2 6D&F.pW5jSz]a(Te7ʁ2+0'i `n΁r *0,gg9>c :0h;8=$&E#lJ1I,Pżf^żf^J.$6"%-$6"%r̋̋d")FW)C }ulM-e:ml/f2\\xÈhSs)=&8z{Iwˆ+~0y="zHGwF䬮mi:|eB~RMJ6x{ e;s@Y&a G u*|/c鯊vE?t-^eGOIW) PKxE3 part.alps-starter-pot9mm.fzpPKxEug6=$Npart.arduino-shield_r3_two_layer.fzpPKxEW part.arduino_Uno_Rev3(fix).fzpPKxEmY(H"k"part.Half_breadboard.fzpPKxE:!3part.led-rgb-4pin-cathode_rbg.fzpPKxE;=R a7part.resistor.fzpPKxEyg"H:ProcessingRGB.fzPKxEqProcessingRGB.inoPKxE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgPKxE%%k.r%svg.breadboard.Half_breadboard56a.svgPKxE-P˧D)--svg.breadboard.led-rgb-4pin-anode-leg.svgPKxẼ 3svg.breadboard.resistor_220.svgPKxEie08svg.breadboard.starter-poti-small_breadboard.svgPKxE; % f)"Msvg.icon.arduino_Uno_Rev3_icon.svgPKxE 2Ysvg.icon.led-rgb-4pin-anode.svgPKxE n^svg.icon.plain_pcb.svgPKxEcE *asvg.icon.resistor_icon_220.svgPKxE2H#Wa$gsvg.icon.starter-poti-small_icon.svgPKxEOg#,{svg.pcb.alps-starter-pot9mm_pcb.svgPKxE^y }svg.pcb.arduino_Uno_Rev3_pcb.svgPKxE)/ʰ"svg.pcb.axial_lay_2_400mil_pcb.svgPKxE)-{svg.pcb.LED-TRICOLOR-THROUGHHOLE_SparkFun.svgPKxEr#zsvg.pcb.pcb-arduino-shield-rev3.svgPKxERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svgPKxEX,.ڟsvg.schematic.basic_poti.svgPKxE9&Bsvg.schematic.led-rbg-4pin-cathode.svgPKxETZ Ksvg.schematic.resistor.svgPKIݬfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Servo.fzz000066400000000000000000000415521250202676700317470ustar00rootroot00000000000000PK8D@֩Servo.fz}r#G5wZ;fd܇Z5mRLRWH$F P*Ѿ>FG^D"lR"??zh:ysASrN7ݛ\_aza a/zp_~ySN'`roO߂r/orpԭ$P 7 s37Û4u}u ?.h}7<8if h;yѻ\v7~ܼN?En6yW:M.zog^cNn;+Em6}z8~g.W0> Ow(Yު9]r߆g+g1|?|7W_f?Ѩ>_G׿MGmQ qm҉ZX|O*yix뾈3ʨbn4wnCeOn;Y^e-|z:^~7ZXezc u~O=Szx?FZ-n8}.f{{ܔN iYKTN׮b\f&HR??o)Y'{?HzjVI͆B:sUuI\n뜟g+.0ַ͞A$A|RWNZݶp{\]pI&.$JwO;F?]JNUB9)~e5ATwK(w wD%PI *uWbɣpF>ڕ|ީ.jG:3NuP2Bo!Q^jA>lQSE]4ӎJ6$:3Ou Nc~@,[A).1]tleEFz 8 }o Z̹cNeeʐ2Sc8¢vI뀑Q[PaMC4ԸP $MnB))5NSD" tw9QYs!aN'ng8 $+IF!XRHC% AAO<yL S'!m0|ݡƴLGo˔KI:QCeLݾ9!tS0VpijiU)K}Fl;6Ey"P6j*GCFdg=OJ㞲M,,4)t5CmsqN=kVxoj#rw$5Fzꈨ$呇|oDgDDaT'&jb67D~, aI14*φ04FBU+0gRBIKSE0('f uh@r΃PqRTP~@*z{{kVG[~!'R-O~02ΡJLũ9 R1YeG}ii[.-՝AН!RTi*E-hZF xҡOn %vrn >"/m@&A$N?!m{(&a`D_7ed3Ia jnnW*Ԧ*F(5sd),vf11u4GVR>磲Z A2fraS22v#(0yԴ F 9}o"ib|)))ѩ2 "1"U~ ]jz(a$ex̴1<-WZ:\T@ 0w5],o.!"GEn:rcݿx,O 40f ɜf>^;5!1s:*x1t ]DN" Bɫ7_֐nEw>'kxYVJqXHEa| Xn(qv-2%~w8M4Nx 5/Bnݡ.7An7;- \B1MYP` vQprR?FYSlCY ^޻lmu͛H)˽ՁέMKҤLl/`{sq N;̉j=6x3'$iJb;XU`2zSA"rͨ 'Nn~r/Ϯ/3W쳞Fx0_XߦSu3[ڌ6D6 qegy;>E3*GLM]RڙܓRڄŔYQn9F J۔eoޖKo%ed)\H|HP{ӛ|xκclݎ2v=آ q i?R{ӆh4 GͩU9Fji~{o״\¹8Xn._nnDV&. zH*q·dx2 7)U]~yp6ĝL.og] ,uq+(=Φ{8= ,9;O;|ϭ#pX9+2;%6Z*p<VKRnzH M,62"m˺Z#n&QDxIwXHecSuXҎwҺNI(]VMtҦB)sd%/Y'V(3rSǖ;6DvtDI4y]=1g"&T:L)q H:"U9> `p-o~AC8W[iqN=mmѺtǶ@Wj,:,n"R(ErxtkbTnVY3u$]f[&TTY8U݉Vݖ˪ٛ˶RlF`2e:vsKUyVJsݖZNZL(*6&dݖ)f3=xg$ݪL^Sjf2kؽcޱՔMwo>a`rlϟ8Yٔq`Tr#ptw(fMo]E0şOwOtˏ?y:]2Kw^f\P5=-LqD}~=]"=@ɟz^&7_φN_S읜>6@_ٍ"8O gdੇx."Wq8all8{ʞ/f߆IEeQ߳'))>M˻7Օh|3rXn:\(-$ugVMPInl<pDo>Bi;S< )e;Pirc%t{؇Py>Ut ۗ!wځXrM-5<:;iG;g] H砞8WWF=\< aB)ݾ CN^$nM щ,^'1oJKv vZ׮ K$:ő82x\h͈og9$[M&%U1D!qJO h45Рᨃs&5# sE>A#1sYkyVWT@3:Df+J#-V5BsSz"A;:V궷\ Ac*bL6 E ~%5DD DVk52_6w0XƤh4~Dcsdb*i\~w9PH-n,8 L-N]u˰ᩤe|3y;5DxD DVhk,9&[ha^É..T2 )Zs۔e~MU7)ZTjTD*WQ5ԘMų=#S Dnx<9nORU05c!ug C[HZnZqcRYgI~wjGI6S+4nI%OɊD#4&Tfc<2NbK\I\y %$.[`\ʙP92] f~L1hI$pkqP*i37AAؚf"Ye5B^7Ok6}l G$fUb&3aʹLtXU}u6"n8r4GEΔCl;hm9Qa#I=ǸȪ{0)rtyk4Dbv;E~Ĭ-̶LLXiFpF.#0(K<,(C 0i?Js,<;35X!%uIڠe_Y{>񵒵8*$ҷeOiٰoLu,2)"WFD1@OYWA. 3};, d"uC"qk?^7qk1ĭ,ĭ*$gxY_L)1J\EVd$,mTδM,uFHo}D$j^X[H[UIdo˪9{kylFqRRYpv%{EXYh*iqcIygXVD1tRX'5% ({k/,*MPS7q[n5+rNqvzJnȶg_>;V;m"Dζo? IyݽnaHm @ImUi'wnekF3RS2pHj&q1ܑ +ʏ&V[_dz+܍]h*t4PJTo0g@[ j I"}kI"}Js|4n;<s-37T&^)'|ĭCmnH܎!E )K"wkG^w[Io IoUi(m@T$N./_RD \.cAd%`4G9;CJ tєl[d71$&uV"H@H֪I"Y[652Yxe+%seR*#"g;R*imwqva\1gQiʳDye(ԭIyԭ͸$2$24પۍ[Rn5'!q:v'm,7?-2I0]MÛv JK2c,9it$Ht|J7唴 Y·tLs)5#UiJ䷂d7^o0Ximʫ7&7+}vn9յiޢ*mWq7bo%[\&GmFޗAXMNޢ FvvERfERZƷ(pr.e oƺѰ?4K pQ`hUI\]؏*|zLˍr鄑ei`b+aI HUi$-[Xkm֨+ڸJi4h?v,[(ѩjYYܪ{_+5)ŵD*D*Wp\U5ʵ3WO3Z-N,\iWf˔>;.glX%ہT%|\ZD2D2W, +x"z-g׀dp_MzcJ#d۫t%!J$nMk%.*$-[[q@JV*nUv(5mӉܯQgZH+5)ƵD2D2Wx3؃bypBފ|P6&3N!%#6r 6ؙ]ڣ;Juު{_$q&QUjX \` \UJ$p˪93-8H/ W\R&d8c[XH)#GN"dJ 9HLaDEA4$I$y$$$4HUsg[&q tj=RwTQ!Cڠ܏3 ?0;8,o_%wѻN?~wȵJ]Es﷡+wVJr u:#+[iqWtN h6s&)Z&Tnr4󥔊r]i<)+҄H!K9YߵM&Tm H[MXQ6D$ ~n?l7p5㮏d:l41 )G!;f(pC::kM]ޘ6ds:lL5ktט5LOmn2nz7apjԤM{{F=},4R\A sIKk*2bSC8wǢ7şa{4%_hr|?-?P'懷ڛ?~"'{y/~~m/z_/_^^~1~t=t7^Ce7/%Id88հxaS=R>OS8p|?p=~ڗ=w#}a4Rte xn&R1> ™L}u8yqj&u连H7YtK ѵ&6 7,݊OԜSAnGLIC0)Qϴzp' um$ºc]mRqpXBD^#q8a:[hqw8I{% _T紖+$ Ebؽ#}(|&u@f_GJ PVRop50ugN_^> s"θ'D8~C)'PU[iz}Iqac@}"ÿo{d}f}/lʝBІYw_>XPJcL ܯ\wW7w1+NJ/q+nB(c |qa))wtMQT8^*\VT'M9u9>~ Pv"Sy[gQ"ܖTnyL|>3w5ΜV^"ݻmjĆ7| N=wS#-Z fhL@KJ*4P* P?N%O !jA{@9h™#O A{wHpdC~K@L&=Lv0R9Teh/ʸI\h@ڸo?E)-hyF(|y//N`?| J@щo;D&A@n? 2@Acc+5ֹP/k-ɯ`BxYL&yA޻4 g[o])3 h~:T>|4vi}ZZuC28VZ!j׉ %6%ƓY0?7aU0^USǼH7/jҬ 0DZOH^,T4vY.{3q] ‚ f}ߥF^$F;fZ`+ОHZ4DzХ3y. A$@ g FAQgSg)u6@O3s1ߪH[;S6 @AcqH!ccw,G/U 5wy oVu*BlDz{ A(xɾb!n@&?x  ּ(4~<ш, c Is@[jo`L>Q|,\r 0kP% 5R+f(9S\C\" TngIA4.:|( @03W=`gȼ+Ds=$X1(D?MëU ^AH19KmP+ J`ZD&e)h=҂X?Ng0'%dU1 K(JQDKwѪUaA0Da{`dg30n@A$ (^"1BD ${!2 Q-b(B%H<% Lhk 9&*v5V7 "875@[k H & $&[8 *P ]v (0@mAv[A.XwėWc 0B0z$lCa>)b9%xDCF @484gr{wk;9VC#&Zdh)],]5w) WÕhzDt,X"oԑ4HuC;0g-'@Ԫ0nbL@@1`VoR`y1E K1ċpb",-$# a?dY@OqDLD,Ob@YdYfk?e*!u(y6ɂ,ҼI)]C|=aC( |QpQyD'!n@hXA‡Ҁ $X_T$g~)Kq1s|FVC섄=2X`\$&uE |=bjނpX~ I"ԘvйSA4ϩ -.bXGARN@{>ʱplhHvP؇6%3+.ԥd@pɩ3:etp@i%k3a:9=ouu0W<1k6˄UD9s@/ E{0m#PcW( xM@9 Ttr@9K!)4Xj@CmOL;Ob軶|]r>CAvg:ad9j 1# 0d)7 b! h8N8 W;(tUhx;(Kg9.$ x9&Pwو$sxJxՠ;umsXeIVFO~b"Γҡ*&bG{;Z^zrHT*RTBCs vᅆ*zWʏQhL `V F2ەH(2E&?|2 "|3x{ xq{ 1y_]y^8M`톆 }kU{j.0؃p&v(v#h>*O@QbHgl1pɌ¿hǸBc* a0 TlFsi!?wAB -Cf`6͝Ƭ@D<#b  vDD4f#QB3,_`a@j  ~F9`t= ;`<ǝFC 0O$`혙\!莯r"1ㅣ19WbEY<]ha ~b AnAȠZ1M1M24|ljz>PGc}KI1X)P1vrl8JM^# `aC {t0 aDAxw*PY`ž_A"jEc.$лd s (]d^b | =]s%ѹa znaFЇ EA8Hb FtTJ Л CuY~g)zL! "Gu+rb"D8s>[ sԲ7#+ _ķ؏A9tT3&GɅZ|@r|E1UNU *E LA(8lyoc 4[$^GQPpᅙ;>{ AzAnŦIСEGdAuj}`g \v0$sa"Q W̼QԉyC[]Zy 0<M4+ p rue"UC%<|WʏkJ~я0@??'%?&r m"ư +‹a"~zBJzerU >,eycREvJ Dž|q]yΧ٣BE *D;cpG n@eЋs<RsFQ-BxqG6d}/A#HL5xL)" | JaO3-2&!2XT|C܄C?AZzAZ@f gB+{Hg@ÞXW_'9nDଡ&h~ l豎#NJ/}TwN vNȍrԲĄ&pT? $ %MɻABchI^7Ѓ/vsd,wcEUXVI(rEB߃ޕU' B,A¡$f0{ zCc=PEM.ER*7Ė"jj \}ci2;SӊWD%QCYl?H}XC#]U%AiIP R^Nj'ZUZTY(UB_[T^R*ϕj4NrD'vc_ p2cEAS[ Jp܈4SD10ؘ͋B,-SO8$M`:A8g1_7#baN`~Cİ8Z C.r\).P `dޕx)Џm"nSa7fdK䰒! uYK H>͹Q>8kuJNd141w`҄LVVpLTw?ڍ)<~pwhpCKHH%YIKǎg~l.s](ǏJᡟƂc ¬9j1 #QLсBA/ՊQdv]«myi~%dYkGs]8HBG&Wq,s` fݓr0áS\oߍMmE-Ҋ8m8|M-R[,rgն(ĩIR[%/[ 3nƶ[r :ׇb 1 7)gaoj:DC–]<d80'+?[\#X?/whޕ |{ψJЕd1W,*ɾ,3u^::K0p 0pd}祕cْ}q} gDLӱqay!eI}y[-&69uf!``8T>aBlΣk>OI"8" !gxEv.lj9ZLmS O=̶ K˜oΩ ÿ1T BM}fXQ:~/A+f몖{]1EUFhz0lNH_ ڏ-a NM[0* /d5 s{I!KCLcƶ )] 10oOcgJLB/~ޓFǡXe}W[[:ijӯظx0_8_J[appbx߲z_?.}}`1' .=x}}p3}9ޔ{69FqflyUW] Khbd!fs%/־Ͷݽ`#bq4a}}b\{ pû/y8,Wv Q4_źee|~m_zFۯg8*85۰-Ks:\ */>ΤY$=[WTdVƳկ|Fpѿ;q6v?Ңwp2vb6mTXeWwe:YnmK .чC#|P;n>&_ѧY^|u}p4>߬]vJ"lÌϙJ(S~rKy|j,,4wdg3u;{u~7U ;rc,GZ: nWF3.]=ǬfbCnd/sf 5YӲNijtT=ƇuNWUÉ[1K RS}r,p'x{6j>pbnhT=b+Sg+Vʮ.u_EL!q5Y }׷*+&QUr-ΞyoqVʜ1K4SRpub@Mk|tϯ{`۰ ?$ aH~ŽOawNxp7w1Ѵya4h?F):l.qqqp=Z|nͺ}Sݲ ;nI֭m`};z+b1}xs}TnU_s Un:Tq ߀)mބ'Y+/jcC CijedVR:S$% |1XgK98!v\Vj'Ät&0)uWQ}%ҶI*}@Tl* Lߥ~o$ngGߞ ܨ BѵoIlKHRC֮Ugz.+8>qJ +#4m+PQ8j5a$dg^q㴸h*E>;b=Ύ'm_]"3sPK8D Servo.inouRMo0 W);0 ]aVl刱9˒!1aQV>45 HW^e?oHer2zzM(@1 C* R% OH'4;wdkQ#X\%.2ސ]A#M,E ^~e;jSG@! YY v pHáIf-gdzǽ.CGIki5ʓ9!my#@VʹWsdYsHC@|ٟЅbV&]`t'1AA-d/s'd)tt:y!4̤إF#GN氜tp]QG`#]BE!󓼯(Èb{c7jX uѨm~Xx.vb'j6hQPK8D@֩Servo.fzPK8D @Servo.inoPKmBfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Synthesizer.fzz000066400000000000000000000567321250202676700332060ustar00rootroot00000000000000PK8DK! Tpart.sparkfun-electromechanical-buzzer-ns.fzp_69129ed5bcec2b4b26eec3be62bb1125_4.fzpVMo0+YqۭIʪm˶^ j( 6 b<ϼ癱/a@SG."/U4t K؟@&Ze+t=~[ϑ1`3Sx)sN'0i`Xi"d8ID-gh;J{Ub¿6BZd#8$<S$GI-t ^%W݈vjVCM ;%NsZ ;ũYI̲XŢW]U/SNKGRO$3مt 9at> {6VH̐,S½܉͜[Wيo':N@g Lr$,cik:0w&"T;Z(rAn<^}FY(A[n |`aK —rS#K&BAj9KU[)~)݀,jRCPBJȔ&n x_xOR ޢhi=O<٦](-8b%TS!L~-\yqԦ<}bkw\AnEr8#$d"fJO*Ǜǘ~Hp7wFԒ$*9kz?I:Tʺݐ6 -INZo}񛾦瓮[NVi(AdYNvH9X+g)SPK8D0; wsvg.breadboard.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_breadboard.svgVYk@~ϯi Z IIB@!-ZWf%N~}G+-@]"ujp=2U68#;<8mJ.ur((fUmB<nRP2^1ǖ>gy=m^2@!X㺞g> N)up0z<(q} E&WMD/jz܇7EQx"M*& ta+a1-x]F2u0}l$ӆq%t9 UՂ<Ņ:Me\Iu5LٲIˉLƱʓxޤLlU= a`A.N1''`hZZķ:߰ALa:n6&4d#Q'y-`>,:KwV"}f<$b^d[pVi"'RYj:.9B'ۧADŽ  #{X%dd>0> #Czlv-{#[keyXy GUyUso' 3.J@ 4:apFdmUlkw2:x^딶4xp/]olkc4@{\G7nxś]aⶰ ;nwE1sTɮv1zP$snp<(:AEbvX~Gߕf/PK8D/= {C ksvg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgVkoH_q~H+a<-;UJJR~01*N~} u]$.sϹ͢'VkF5Hy :mk=ۼJRU!`ϷpYֺժp( 61P wʁ~p]o @"8]t/Y3+)'$,q,H$`ww$vdRYkD Wb~mDMυ%?ϒ hW4aX؂![ ٮڝ0AakX$/]-]p$(`ny؟Yl{ۚdZJ×:3 jmPdXۘIQށH[]n RM" MH kJD :as'dCVlx2=Nh Zkb3Y;E++ Y$2:*Dc7"Cb$=KcE-=fYjoX/[ iN~6` :K|5~L^OPK8D;2bsvg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svg͔Qo0+l 6$$ )r+`GM](Iej |}뇦r&AismlNJzarQ[(}G):%a}+CS^֕G+] iڌǽ&b  &,hCv#.ADqx[)]VHiVI2O'LkѪoV<9j b檕ԩB9CPlm{CUwQFKQ߭(n+.# 'H~7vU%@*@:#' > fS q!~İΈ)_n oENuMgr@kWa8LHa~ N)sd-Z,BeoyU5TAn:LyQ㕟t1y_ϗ} utAiϕ`q&Vxkp[iJ+-;KXPK8DZfF Synthesizer.fz}r#G5wm[;f@2C6u[ML?2@o?6= F523"==>#?~>L ~ݿ{u_22_[\O7 D_%&L$F^ fCp]9pZS}~v=v6__ V|[e3|=?f>ҋՅJJM.ٻի p)u_],蛇Żr0s})SPv5\ 2W7 ؄\O ||]ًAn_}.ǫߍW˟;'˿^|ryon뱔ZC򱤆ML.|.g_k\C_|M?ށbp?s}zA&oݗwׯngרtv1X.>~^x>{w?;]Mqq|snMN>}BN_e"}LN)W jv6a1 8LjDr;v?].U:렗MwM:rJʐ~ɟ791Si&N 5\9UV t$ᮛcMu{rx^0+cr8ڠ $%~v޺SRv7r?tq7]=~|) b$02Q^ >;iJ*WĽӪ^n5Ȏ0gxo>'dWvyrϳ=j^<=Nne'-)p8]8%k8#Z,pj(DT,aoޕ#젴9CAqw~[>';gjs^Ԟ`ú7%~U&t>aV`~>`7~n1k3wFF]nwϝ=w=]ny;g!~q?7~ynʻ+SIys?la<3vRa7=Y{oް\;0+~.ZDgeXUm,:DD׃l'eDv||}^U vEغ^7!1V0kg9ɻh{pu}q"F&넫u4R3XzWNJꚰꖤ ^pm?W7gru.KuNW}nWd}ΎW'q]QԿUarq2]^>WK̦~tH{S'O!{6ƧMwDQ?;Qpĉ"g|n?ϟ?Zfsw2c*$*`0Vaի.~Mw U8k@QNZsz((.2QlhrgᄍS^'Jvv(Tnn= V;E 퓼ƬWU9=JqCPPSPDVs҄RSafLe= (9D|b@R>F³t9[@ C mt&MAF y 3厥e *2‘g4t2iՎyfn, hDېFHw.l4i 4$r'(xL yhafTyp^GcCZٱTq25dTDX^ ܊p)#qܘɸP 4ZLE9:XEcBt{oX!R<4 qQF"6[|IJt$eB_4n4FCM)hǏV((,u,唶LA&z+eV(=5\_)}Yg8d eZ'4% FK9ԱB[ey-Ei qS)Tf΍<̀gE6Y@lE#HclԶ!6"x izGe- !~8vueOːy=ͥ,т6z3DǏDt[oB!U*hoa" Kd|.",_}ґF,3"EjI"X'yMaJ(E(LMl,^rQB0 LybáTD#ћ#4 @ne?6Dy@Gw  DAd[φBy 3H_i|t䓷\\<<*NZrT&B38MͅǏt[ouv@gDA)ꪀ"lP'(JT_0KИ8gB{"P D"_/CD 9my4ί.Jj>Sд֩ #;]8R&#aL?-7EAqK*uVUomeFHeDd[φ{>㞼Y3"H[ it}k'e),+ڪ%†)y}㟌$Y|Z(B[wmD\hGo}vT's"i\fd(/ay c$ybb*4n/4FGEhiē~ 9eMNEѰ2ݡeLTlxi PL3Z:jy.TJw5[Pk-{sUdURݜ)_#_"8w}8KmIdM@I\HI}rtVT'?lev ch><.%Z}܏羚.Vba<G~6QMZ)`]v ģȳf=CD$ʤv/FqE-.lKvCbvz UH:5k`DN<}3\~}j^NE;fq4,=eǜ`LIoaut}hgvayg[vu3-<[LF=fF8ֵ3Xfx7(tG9~f[!N 8<=i﷝#~-gWs=Srר9rBvs~9~Z̑~kClпL?~w>Bi .>h%Wó{0Ů@7OlpwƲm*svŨ鵼L'J\15NT+JUkAoƗ?-w>,?KbhhTm7)7WoqvutWv~4;<1q&/҇;~:J}m"xXi }_̀{4"Tj&g)3(K68M-:oHrY{ zn^슕_Y/, )"X¸_tV-] ~)^*ҰFBJ$1%*c$:FU/C1z&I/RhWOA@Wb{eJJSڄPZ§V$2}PJA0-X ѯn vtl1z|q3^}Wwv' pVJ;PhuA4~hae9:de&jm.z1?qfPעf&-#ILЉ3A}Y AHÂO@ Eer'1c *rD?aq8g}6 ͳף)ly  '*'3 HZ4DőZ’HE4M铔;Rw)s3^&HÂ4,h(SDZg؅ H-ҳa9r?{44Y3g؆VM"Uu NR>NT@TՉtD uC&! ŸN̮u WĐ:>X+ _S,,Dy'g8zy'^4t_N1t>^ԕu2aP]k3hg(ýJKJ|)$Ie$\t~*M;5"1߃tS4 LB4M%GTXV*G^Sgg3b Muǰb*m'gI~I&b[<5]l,ًɲ]&{@,٦ Hh؅_ϜYz'"~Y݃3gT9+:*MdKy({'5Wt^rEXC^:3~T^Pp/)㗧򂺘T MUM9 gǼ`to?N*MI4xQӦ^i5S@ӂQ9y?_hy;ί+L 6__A$e|^ɓfg)*쿠h"di#$azN6߼uk85y.\ҭ. Fyz^#(B}3 3w`foN?Q\g۩>H_ں5!h8ZVR8X IUɜV|rsAF1,DQhu}'U iC b6 ;&'ڈrqd>^J6> akyQ,UTSqyэ#m4WLUgQv!S)ad61BJ`wfF4UƛklÊ 6S ٔws\ 8j4,*=IA5!b+OF=x2?{qƳ_5h/aJF I(k-&̓"5^:W{S?E~)c2?&+K#$rᮡp9bϟySSDpD7NTScd(e"/ D$lؐ;Ia9Z7cGhp42G X:Im8IR:ԓ!r. v`lLsJ̲K&D$ԙmy&5!{S?@̍[)*RnU9@D[*d$mzszcm=NDtDEdkēÒK՚wE"Kk:"K+f'he&#Q _Ev֩~sgfYx&@nf$rC MC ELL+DsIlPWූaL%<*kLdgeqv$`%dU,x̝UQ)T'Vm HU]w2]7$ ɏ\m0%Ó?k%9rojC9 ]k{MV"A@G"S; ؕ?;V5uQަoH]&[6s~`a8"0VVS0w#%&0~I -kʰ"VrQ}#nLgkjvU⚚M"ʋ^ $R0$RroǑH6ԭMÉ:iO/N#4BZ9u (9(HKڕ6ҷ*VZiI8ZN2m>P a&n-%5#q$r5OZNbq͎APc֭7HW9rs\F4MVR! ΁TUm;yoM"KԮ$Ҷ#ʽAZ$mӧm-o \xdLQU֒DsŶp"k"Zm"!6Sn<;fmBYY[YDښDwM"ik<"i+~-'mYĴLF=ūY3wMM5\"9-"ʅQXR a\"yڶs':!(yՑ{#5(AyqEӏo?ލm'l3wTDžnzu{10wH(e!+zCNgnW*2&¹b{_ގ忟OwrMWdq=ꏿG{σwOo~|=jty_MWח?~L>dlt'^Ef&׫ʍFDZӑ^/|5*! Bx\ 6n /}=p'OhTj?fM}/2L)b|v~)|J?8s85N;TvkZd 7iv>ƿ%u sb4\:׼kj>]'{\Or?hke8 B&lr8ޯLq*[l wH0 Q|ȴ{t2ۋ!Q$BX?I'FL#(:qK#pGXw/~?En(J3!g#acmBVk-WS~vsǷ#֟*빿 ?a|@O|WJ+t2L?QZfX)#)[a  lD$:Aq[v:' MHi| xTIN L8vMx{yZK/"qWp|+}^P{VJ !K1 >k'ِwm@P%2H5T? 4pxJcx R{1 ^=3<ó1u難 K]#C 'x>s:1{_KJ"%;yΘ:#:dU:Ķ8E.mA. ߧ~ jgNRcG +-Cj$|?@~̸pxC[:e;Јh?`/ 1 #T3Tp~ ߩ/x|poA[@9©#O xwȤhLz0~HeP0ozk(w w#<=@ Oh+iwKZaO:Ôe]%@"FX@Ƿ܈7Íxǚ n@2)3áݘ+v|յ-vx||ڹO=ڕrX"]V LLLJ' WťO$c"+)΅>QOFuMqǂb 02Q eٱ&U;e AW=M=Yhd`?' S ` RSUa d)[@1xGG!2MaS$eF򋱙<c]H%6"}[p;'jU\"̩'P00ȹ|#cytt`vXef ^ScގTSuo4 0DZO^/,h) Z]f!WI3N?KI .I!(s<8S tōt8:V= h# (e96Ig-+5.P\ @ƻ$70HR=9̀ab#mL 6!)b0ƆΎ2ݱ:AT11 FS?`ڣUpUoBO 1p4Ř@M@@QoV7@, UbXP[T"$cȤ9C N- sN&?P4\b0 0k% *5R+F(69S\A\" Dfg i]4x+:fudVrXv`!J #,7 p:%$u0ꅎN! =^[գx>`LNFA7%m0, ]&eઠ)=҂ب=Nf0xOxJbQZ"{`vk`މ 1VnjϜe` G7H@\V#RZ7/V!"qF?7L(DE‘>FT$߂5 _7 "*8ojBrEkC1=NO VN#%318 HIe@1 /RJ #} 40Dx\BHVj'h=>|ykѧ#c(GA;4#h(G4d$p•<ڂ@jymG!!؊qhZc Z:>EҽUK]q*\D -pk RS.5vT`i:n` ZI pHgtēh7Eo'9vOLK6,:V2/Y̼U%9"ayc$L7m +uEx! tg0l( ޑ(F.fwUI1` @lON"R'0'>yG1J|{][zwg:ndj 1# 0D); bCN?a,:?Gp+E8Lh*;([1.$A @I9P:uмEH4Tag)LcG#s!xd#Fc[MͩW6Ŋ)oOf|C $(p]C?nF7N}pΘ.HDċ"RT.\BqwṄ"zS҇QhgL E`T F2ǕAO(2E&U=:Eܛ;IqQ"D,!b AQ \H!3lod[0ƇahV-* U#]e' cαPa2 *tqb|a@" ڎIe`x/_$FiK%:Д0\h,:~d4.!GԾ)BX'ƫ$<*Q.$cXbrl8JU^# !n!D#Mv|I 09C04ӱJRa 4F[s0aʀŏh!|e i8 )  VYb̈́`Y!!ȍqHT0 C" ;XxY`/F~<7Lš T n3sgVb} %Ihܰ`@#hCbG|#1O R )]h58/C6'h*!8ƒeuP<äLȘB,E;M+ E`s>Fs3Բ@7#+=_GÔaNaZ@v?MR[Ar8K" ?5xNef OQL1IrDEi#mL`y ;ghF# Z g!h /asv Azߘš$H"EdAqj|`2u~q`H0">."#RF]bN_ڊ KT4e$tP8Ѵ1T 'jWۣoTps=[:hǰ# `DaaL;6*1CxQnŰĀjt (&HA 2L*\p94\AV)hPh8Z5=Ek%QC nq@p`qlkVE $҈blƒdHx!8$/A(dF@ C@[7Or|9T q3x3!ҕ՞ t hxUʔ}8H df_c ofAXD(!Q&|<M]Վة)7J- aN 8` U e9+i -2F%Shxi<|4C23*3Ki.soAJo";>*|=Y4 .zOb 7:[hoiG+K1W)jWp\ipb 5c1O}' (TM+^.t5kACOѷk=?UBGBbKqO{^ChYjPe.Tr2Zj~Y*lPyA<88\ p2MBS['Jnbf͔)P rS1zF|c Kя! eos QYXf9Q8GRD?S jpu!"b&,0+ΓySGてP5)}Џ"nƓaFd ,N%9s= ufƪS'JL]Sh LT0Y:"9Ut0 dAorn,'OEa1&-;rJ?| 0"= Yf(ÏJᡟƂ5ai(&O P8f)2pVxp+x 5m@a2Y}baV(GQhy&0b1$*$:8qk+a}L.&, 1 ?E:(iQ$ cQb!h cQb;+EEם P}YRX)0fXl%y@с/ۋi,1! 78))57<5Cپ;DsHiq<:ٓU<;Mq?mjH MIsF' LKqFά\g[\l(xYkE_lEܦ)t 1),'i )\ė0b kC,Svv KEPy@GtM x,^<'t䚏7 '8'&\` 9FLcjS 'qLAa–Чôvzx_#Iy mBva5ˎ!)-u]R̺ͬbxoUgFx{PtNPS7t zqR0~07"}pp18qBHpt2̫2,ӘL 3I}2ey86qJy-hnD)Ձa߬>U/.5/WjSߗ忾nmx/՗׏կ鯷&=;e\gp鱇ɕ_~ltq>S~>XǮ.YIouAq;+iI=]d. p'~oRtwòigbIwUڥE}@k{r\opOdL[ۢCwk{nNXQf5QohpO6#FV#fW ~eZKa5Leae"ץRު7@Хrުú\*%%մ.qioy>'mG9; )АJ<$3 TB+ >c)g' :_ޜ2[qK_짧:, j]d Wc']DIQO+K$ ~ɽ2VU})}CфA|d*E6Q&pSĒ(^ 2Nē}@K{`$Գ3IRP}Da(ex(C@e>Ʉq0!n #T9&VK{0$͸ jpDwF:8\##/˺`Nay8v0VJ^ ]% /(!zBJ,%R-׉pжL Ra??c yF(#|-n^+=6^{vw6% Q}X0 ]{GW&ܱ:?ttb{_>i!wS5CZk~J:vNUZAHou* DG_ҮBqk4=$ځ$&Z;A0"l!:ǐ^kGbzmmj>]#)v&>:j!Q 7:Zm7D$k4}4͍Whm)]tWjqb0@Q(]c*&-zV"sׅ /̸3H iZn񉴭Y$R#ʽ@"_|^\'JU1[02"qMM|Λa-nCI(,o")rNBIjMjx$Տ"{S?DV '6"1 0 ĭk8*~?qB-8`&WJ&2k]"8XLIHyLE%R$RroꇓH6TNLXRq,wro=)B2NDZ#Pa+zSS̋Ĥ\Ex\np%r&1es}ꇒʽN"[rlyqbT z1u zIO1uDTsuae֛H0'><$=-%99b$Wi&Y5>hy.H(Չ$nfrǹĊyDgGEdmy4)7n-Ƚ7e2)Ūlxԡ^8gki"cg"cm㷓&2Z/"k&NZl(l  "rGk,`a>L7_ߘ*rIEZXY;&Q iwQ[q/>ZVNI,~H˓lζ<ykyn7rzK;~zSD%v5%$5 "/=+tD"a+~ ,}m DY+D$i1)),†>"ytM$#Q:!"$}@K{EPaĵIJ%r8@%,]:DSo'c TW*{+`6DbX"CF۞e)vZ8-em`Idj IW$ykLI v*ig'`h]fH|#",H3J}u-v*=1k q5.D[71V?mk P"Nb-ؚ%p$STɓ|qb Dڶm\ٸUQ-V!엝ccIkMI\ȷ7CKL)(1W-Ÿ%r6wPK8D{?JmSynthesizer.inon0GJ Ыi]'6 6*9$G;"26}@_lN Q4i(|ki34TK,R H2\0Am\!ҒZ~>4䄢\2lI2c4|! VUg^(Fm{A iaZ,qDn Df}Kve +x^,=M9"zr~76P7>Go(W#\Ncq.g6Q" Bz]fq X5{DG4V_XnqomtG71c-yFCN'J;? {I.M& PK8DK! Tpart.sparkfun-electromechanical-buzzer-ns.fzp_69129ed5bcec2b4b26eec3be62bb1125_4.fzpPK8D0; wnsvg.breadboard.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_breadboard.svgPK8D/= {C k>svg.icon.sparkfun-electromechanical_buzzer-12mm-ns_breadboard.svg_69129ed5bcec2b4b26eec3be62bb1125_icon.svgPK8D;2b svg.pcb.sparkfun-electromechanical_buzzer-12mm-ns_pcb.svg_69129ed5bcec2b4b26eec3be62bb1125_pcb.svgPK8DHnUl svg.schematic.sparkfun-electromechanical_buzzer_schematic.svg_69129ed5bcec2b4b26eec3be62bb1125_schematic.svgPK8DZfF Synthesizer.fzPK8D{?JmWSynthesizer.inoPKcaZTwitterSaurus.fzz000066400000000000000000002472621250202676700334450ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/FritzingPKxEug6=$part.arduino-shield_r3_two_layer.fzpTQk1 ~߯0~iCa0ǥS}}i_?پdIۅX'O7a[ɔ3kѮ}(ٹv0+ krɑK]K7ɫv^e& B2[|rVM'EvЅ5L|z̆jvTkTs\z?qWLrYpu%&3=u!Kݡq0-{ѥ]g@8S'GQB_uN06Nq269Ҙbi>e--1܋_b`(J!aԃcP]G'— 0;<')a6XO۝\ Q828fM焃XqidhM.$?e+q(ͨv*C'?!.whuڸmOuNLfZ4oCtmYc/a?\9ZYŒ&:@aٝnohɇY:MeS/Y4ZܙӈvEcDъO`Ix$hBc6Csb ڳ]t xX򶍮1:h<~&V&?r?F=.tRMJE_(3ߞA2,<3P%h" ")IoDl*j&#;]]DKFgLPȀ%h&IKTdO:@_8 Jd ^BL*%%E5Ey*tV"\pTfnZH*Xctqws љɊf,^wFbaٔ$GT"o t,p ddu fqd _@ g84I$CI~#&[}SL(tLfftM +K4Di][% Z usLamoeLC'B PGy,yƪ  ¡b[L8k!ل~&&h~)dF#na0< @˪YmX֟lEJxuT,oVYwLef{:o]ÌmE)ytg/oA7Tx|J*V­D2/rCO7\jGíY*lf3|uzjZ6:+az SUd]naîFFqحaW/z*ܛ.8K95rhš]C[/v=Mq+8ra({U8WC{S:5](-4ţSGG/N=M 5GiGl X/ H-c0ҹlIH{?xTkKRzylT:b[2U4>j{V'0N |;s"щRq }_^H'Lv0)IIcSq!e IH`D1A'}!:rH`@K}VֽWsp8)I󱁃 ‰W#Tb>͚{o&=057&vv־_sI`Nf\pJ/Bd:1j4[`FONqn<[`O`Ny66<#nJ#m\bʿőh HiJJq\ʿ1*Q#R2 +tusW:5㚗UlJmMtj]B\2!|k^'T7F(j[bkdvڵB ^,4f!&2{ցD',.I%.5G0ɥ¿1.f_G ܯɣ¿1?tDfV"Rs5T7F?TRs8jRoJ1OY@*}!5AOǺt# t2iVT͑R3ңoMkݖ3) t2iVTqR3ΣoM>H]bV\TqR3oM\w0 'frHX!5c9*ƨrR"4!7DsԌߨqH{4+zC*Eo Q7FeTT!b8Ds ԌDuhVTR3~oF bҿ7蚵q+m\{Fpḕv8[sobӻ+ZHɣY{ռqkmT7+\4n=yOӨ5k֮ƭq5jܚc<Ѭhnhhnh*xyumP&@MA͛h*x,n}.xHdumP>@}]u Sϒ`3n45Gx/~x5ƈlv*ѻ>lZfE z j+j 1- b^WT9JrzWȉŸ=B 9F 9V<BQԫ,WD:?^}z]/Ŵ:V,?PKxEmY(H"kpart.Half_breadboard.fzpn]G?'/_=|o?'>8y_7>}vhgpz{On>[zEz}rOZzOOE柳7wٝ_zyg/Ngwח.~ɣO]|rv_gw|y}ݛW ڧqv/|^x?λ;~yyˋ?_v积.uqzWogw~6g~5|Qo6ū//>~/xsxrAW׿r˗~ux#sy9>?nM'ynsl^?ݧ8*z1:Wyg2^=/*~y(޼W/L^1h%~n:ͥn^ٽ^\/ΟW^kyw Q/NOn~?7=8}S{~@_]=(x?7Wzrݛ?G!vgk/em?Ƿ39/SK_K*z_a_Rҿ^>mX׻ͼoO.;/SKK.zaRҿ^>oX~o^)av)y?D/0,=JǹatCCCYJER*}.r]GPhRs">""GJF9949T\0ȡȡ,"E}D Ef)>9.r#rh(r4KatCCCYJE)=E.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29Sz\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K2]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhNu.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CY:"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GtJsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef9Ů =z' j~rkћ9w8wy#{7 a.tkћ1:w(Lwy#{7 anukћ:wx`wy#{7 avkћq;wtwy#{7 awkћ3^v2lix4LyrxN- i5^ox0 /;^4<Grn~KEoHbx07ݻ} y?FG4l]J?/~~߰`^?)av)KSCQz}g g:R*}>s}fz64KLgzp,3=GggÙNtJ/^3ӋLYJgz>ӋL/3f)>%L/>3tT|3b8iNu>k^}fz54KLgzp,3FgWÙNJ}W^ g:)gz>ӛLo3f)>-Lo>3tT|3f8iRޢ3ӛLY:Lgp,3}DgÙNJ}> g:R*}>G>|f04Kt8̇ZڏУwo0x-z>.~yOrn~?^޼ϔ'{7ϜfC9Ns,< j~΃Ӝ9Oôg<4r09<8y4Lyd<4r09<:y4Lyfc9Ns-< j~ΣӜG9OÔg'րӑ5`yf&Lyf·?έ˃k6aZ3s>5tx X^ jlMR̆wMV̜MV̜6MV̜vMR&x >MV̜ƒfMV̜6ăMV̜)vŃMRx3ƃMV̜=ǃMV̜G6Ƀ.MV̜QvʃVMR=Ns[y<3{9ߝ|4Lyfs;n9iV̜|wr0Cq 8t,X jqpMV̜>8'l´g|Cr<&g<21yt?7aZ;l9iV̜|vr094圧aJ3`sr<'g<3ßN9909t:'-لi599hyN&Lyf99霜dyN&Lyf·?''9,ل?on<{뫋wtUq{͟zrݼ޷͋/h_JnJrגywzu-xz'{$7ps|+py5d5d5d5d5j@j@j@j@j@jՐWC$Y Id5Ր$!IVC$Y Ij˫!KVC,Y YjȒՐ%!KVC,Y yy5P$HVC"Y ee5j(P$HVCjP%JVCd5TjP%JVC]^ my54jh$IVC[Y Md54jh$-d5tj%.Y ]d5tjЗWX^ Cd5 j0VVÐ!Y Cd5 j˫tAP@DuX2": r+C2Ѥ&e82 (eB)#uuR)A JXJQ%DX "WºW:XH,AD 2K%,%Dn "\.a.a/A K%D "bH1AĘ LQ&,D K "g4A$ "MX7MXGM&XD "؄%m6A M&&'D "r’r9A NI'ֱ֭D "wA O'D "uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@Q{_ԔW5e)e͵֔5e)Mٯl(( E"E⒁@Qd(2P(   E"E@q@Qd(2P( E"E@Qdd(2P( E"uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@q@q@Qd(2P(  E"E@Qdnn(2P( EK"E@Qd(2P\7дnIdIdIdIdi@@@@@@Ӻ~μ|gY.y+_caVXoMow}wֿo!qm\_M{o~ӯIdV)t)9{In޾ 8|F@߅Տ؞>DwovbN}?xQ *9>Dwgj5FPfen-#o$>$wPSvO=>6oq7woo||z؞=>Dw/>Di`jMtm_&BQ#(yȻɳ7zao?rt/|{oWoSr7ͷov]X~I>=lOeoQtwzo4Q }@&?|df˒/ZTG}I_G:y~gw?PKxEXRH] part.servo.fzpVM0WX0CnWUJ9fº'wT.|< (L%tЩT&b'!⏧tuC$kj$w,lM}&y|SpX؄`!yQЇ0Wz#)Q^P2<𬍤jنFڿx'"6U1V]|= {^$Mm0x^)Ie% Xƍ]CM Kdj˺J;B9 脣&rMrTZI_'/*u_ tI(ψ=3tU nb|W0]\PR1:(vQK5rv{/BX/jR>7/_+ T n@Kd]}K4 TY k}P$7EӠRduvZ#k2(}ʳJR|jgzI[)ےotޗDF^S*xGeD'1(1$1Mb$[C^;"טdGeg99I6dyePKxE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgkݶ(}{>djox8-;$sKiw,U:-$v~ZII-56 7/^~R8\^ᗷ8???_o|zxg=~<<߯_-t (x>oC?6,C_d,\o>x?~ѯZʊemqqOo|A Í$/n/}|QF痯O«ڻ׿~^>Jh=A z_>?}7]]_^ŏ Kg>?~[C|?_z}?ߟ~~supxׯ-?{qs}?zJzOiV#:a|g_ώ?'}\Q0¾Xzyv}~Nj˄(?S̐]{A/K;Y -豼Gтߨ B+󄖢  l3yUI!8Y(r:_NvYʫnǗ\7?|^U)('ӢQLEYp'JaYt3*<`K|z[rq#\^:a_:aoO8:ş2w"n"r Z$@Ky' +;p$Qnuox^Z<`$!$yIꞶHIi$ 1b.k!F67Is h7V,@!\߈yӝ46-KQcjr5?/u3c[´$,T " A/ oiy៖ - OA쪭=x_D:5okc >:64.:{; ~*?? Mp)=~j2:5ֽ m [KUCkݛgftBtNdg,ITAYޛq2}S!5ֽ +G 8 q"22 =;H7!eķ8WWoܐxmp0~<. o5z! p^Sh(%5J5zc صnMxN):'[g#矨H=ۆ܋Gy7("x'jyZ MS .1QlWMc Xÿ!^aYT,cz&dXܢ  0.) b2 nXJ20I1LDCOD6!cB;Cʬ1d 5Z_`7 C n= 0bm1 Lx`xx! n0< Q a%aa_2@Qt_5t}J׻aFc5(4.G2 z\,҂7p١^YB=Np t`BU#}Z+S\ig'U ~j?׏1>xejb`S}\#eԸWih]KzmyVP;\;!~t ~U ~^)jNw_)r?G<t_ 5ܩ3jO>1^ 4`ܨq#V4붘L 4ܨp a&]p nTs~V)wƷkV 7Aau='k2P& :ڝ-$[de5 VT.{г-Qe(l&ǯ(X<Lp=_.D UP`E¯(cm85ioj `|5_&_Vc]u5$vk0 g*P>j/ZjNw.L`?O<ـ9IcV]faklpgZXqyOAvnMsH9)7@'}<ȱ(rAz5̞{; !h2yvqT\Q?6Xb oe<š)aR 0Cfa!#[H |ݺ7  V {2Dj=~{_|mBo'#tJ/\Wy _o~@ɟ>^/ۗ>CB۹| Bd8y??]8kx[Ѫɧ:oE _'~{?~/&G?'" xX =z4<^Co_BD"!z_/^Gf#kx>/o£"!xz/Gݯ|'ݾ_޾~{A k/xFC(V⨎"YCaB[Qz?O"@g/-zѿH"G{ń?fkCƌxNWpVhq':_z!qRF ƽ$]GtNuuT.)}qK]t=a&(5M]( EדҒ1&GwϒD(W>1RgE+WiWQW>ٽrM&+7QfzDxfT^0fc^yqξpNW>4^=ŎYoontvĔSףڍϜϜrkGb{Jy ?U!$ha8L}j>$ϋ^>>F>F#%$cN,)ؽɸ.'}t2e.Gi@ |(@Geۢ>D.݁^NzL0K"꥛IߴIߨINzЙ V:_k7I6qUN;tZI*f8Q&8nCuȥm. D]KkSuSߟmBwjiԟVOqSlJEݟ*fSQ&8?ˇwt's]҉<-<7t7`g7:۾ _=b]|\>:|ѣJ>z Ξ`>D.ݯ5 \r_zjd:Mbu-79l6`f7:?;$E_`iyfO""Sg`8h?~9AX{wy޿q.F(m;}:}ٍ¢}ڽP֍]\/h"thS8pWϮ?^d_q4; 54i xċ>KU h"$x-1Yx[Ȧ'ƀ6m'9KF2@ȧ9?b!YK,x{ɬ%?!LbY?q&X<`28ȟ}/>EfM #3v,KfMc &3~E,Qf-G/ JC28ft"A1J_O m3]C&HO?7tܨpv{L-}N+w_ZƂy' v͉̀t,596'"ILDɋ?}enA jH;ѸuImD)u!#%6=.6ڭin1ޞ3GںxIc٧Vh /n5{3h58{N8{8{vm-=Vueɳ1K ãkx<{PtL՗K"t4h\_,h^E9#nDBʑ52^/Joaq^8}%ZDmӷ&Ƶ8?](Βksv 9zFV<\"+H\ 9FQ~KDɎ d$!<ۗKX$I/ɀƍP|ŲHrZeYf7wXL,2EL͢}^0&Yd8@cXAPŜm=Bk Ns<īDm<׫/f~~ y;ٗrh, &_ XcQ >s'K1SRNVV 4Ɋ0,&S(\䇓(c *ew𥾽3=\ubj$OǕ-A?=XF-Ie 7;ZIOB'ZD}C\{#/ mv~g,dlIMn4wzBR"tz94>-WɘY'(dA,OkH嘨7Z&^)Möu=&ENu8 TeG{.:EϊvQYK~$9ُI|4]LQ7;D1AtM7)n> M#Ҝ#X? Ys~c 'Nჷ4%ߘkQ>HXWfIƷ5KrM4Kƈ?>|-[iR*wQ9MB}z;SV5xdU |ݣ'}c F,:6 G`>;&#ؐCD,EM_|i*mhr W66w{tfl~..S6t/*fAbB4P&׷~s}/0ZU9}5 $Ml/I!8W'+%8PBKa?cib)%U m(TR wmz:\+K}im!Ƞ c^s5J4,mE?J%-âɑpbu\wZd-#-=%qoO_މ%i|mtDoMMЦk;hvю0FN'bdwIN' TµR]'yz {8//Ǽ'Ivbv"X}|ԣ֣ @uڣPZN-(Ԕ"UGU6( LG1$0ƣD ʣ( c8.K8 wIgy`aKk2`/ ū7!o­IBIP\](gp]oBƛ 2:/ ;Hݏݏ8VIs?iSsR(BAB'y[}YCv$kp\1Lg)Nzt (@lX'A[~~Ҙ~~3,01$1U]eIܵ$v6~_mwVs_Y $#sO̸n2z}t!5hɍ0FkLsoH@~EU_;,&lpQygz3`?8l\\31:#ѣUw$ L#1$0őF %~D@ONX+9Fp?6)4S']N0Εxew+~iw+BLÒwai4O/ݬ^ر{JkB=9okflk5<GV 4`# k-}dVhh|iJ*\Ͷؙ@ls]<-6맟~ivZgt-Ƕd[KƢ|V>~4'ۏGǚ辽|ئ5lpӚ8Ao#Z̫gW|_K9˂9g9G1RrTqq7Gj,5ċ$jo̸q⍟6ى`9UL7y Ww8+8;bi,P#fZě<ר;~x qnsexgtǏċ>34io´Ǐ/''^lƀ-L8h>syYx:x,NیrW<Ό+x|D闩D<! wAXP!r Ax"UBл_,9qhI0I[NloFXH!rB )LŃ T?N⁙g2>c)| }b$AK2F3zJMq&8GFSY( MabN" azm3F3gJ^[=iNl:سf7ںTIqQ4b7q_k9.qb+"g_1N|_/ 8b<cQL8bqJ1N 6qQYq7C-bP" YXC m&Cmllnyl#ⱍȏmcX^~Iٔp#Z9_|y&9"?9Gts_IO0qb9"'5G6ᆋ.?7G.ʉtd刜or$9"?1Gn#cnˑ̹&Y92?+Gv?ӓOqò-.>E2'Gӧ.c<$!eX@,sb ~ef}r"bU閩T<&V1ě- tN0Hn* hXu7[̙W9ᰢmenSʏU}S HV d*?PJ3a*H@B2*?P8ۯ;>kXrB !˝uB[~Y!TN Z1.CBuܿn8b T+|>%*?vPO7vz.@BsxCխt,RAD=|*?xPofϐ:=Afj8t~;7_O~7<ۏ/O|9~"FQ %t+kHBGI|$Nl pXBK-wC JN(|bqΉ#t+[d:?Н8~գ~bA "t+"t~e}W,bqΉ#t+Y#t~q椋:'Э \0(BGE< է5(ï/~z VT/d . m:iAvl\Bq`#u80\qy8auoث,]/o/WvX"Ia`-w@vGK7[׶-'%<4??HKsIۖFwDÝ%6N=gOO:\f_>,?| w+X=̟ ғbwH&+dG}-qs+:L^A,^d+Gi.z!DO7 QTpuaN/W'N.7CB`bw)m`֦CW&JZYEeip洡9B Mm$M#{p(/"ȢZ:QpduԁGeQǬI8::bU =.w#9db5r4B#jjxW0# ; ;~Hύ n^{`"PǪ@Ei rC4pkӈ Q^(JҊnȊ5 Vz",ǫipFTD2D  H ̚nDϊztNu*[xi}Y|a-ʅg XƔ(!XGh`3r̷܀ظ76 F FO*B5 ,x6`hlAlso IھY [߿';6Z3ϱz 3Z9Nvlyc`NO}l;(d?A3r:t#8a_#g6 oI2ǾYQUb?B3eyat$#򓁴oi WW^Q3OX""-ȩ>BaMƁjhXWdjE 9Finv#hDc[@VF atd:Yr#&ՔkH"ZdH xF_@$r tdG7! .+eXAVh 5XGh`F,.|oHG6Sg͋6{ZwfD/sB>uO`B?OF[2wZc~V84\9 ..<|n>sB8{-VwM&Taeel;]SS m h%K6hyhsX_yH 2v>g6^ϸa˜)E 5㺈'"T|о.B,tQ ũZl\]:@0j/,WFbLL2xW;tZp,0]&ʤG_P1[\b9&U;0"!Z:΢͉(1 'Ng;[Nz燮w,MMG﵈2æ'˅"˕#Ց~^,RiF^zSx;$^wr'X8^.ٽݨ˝N~8{-^.jLn䡺Hjd77:?BAGy-T0 1*3d 0 `/ ktb}tSL#i/D2rZr%*npH ܨ ,8!;khNVoƿTPӘ%,JFpGN 0;F=;"q$ QsC0rҒ pʺL5k)%;_`B@RH~d€ \aO^cv5HQmP̸$ap$F` S$Z!Z2r wz]%8PB"̥z&O6o;Zr,>>=O(rJUjLCQ 'M>B,9Yf7IJbpE F%X`7%_j )r%Gā7+'E&3htfUS"d氵2 +̂1iPA ځʼnf`0T9iƎFDcYcuGYT'#kF"Xr5P+UjA2,܂ j(\Kc)$E66@J㾬0gH,-hB{+ͱ͸l+g+&6p܁Pf=pcNDנf[i4Bqy۝FW@5a/-v$ d.0WiUȄjybZXe UhSՃZ3MRNJFe\#h>#Ac ݴ%((QF&)a[}!y:٬씷ú襭dq֜Xre'wM 1PLnD[((V =dSKvE Xӕdؕ]S i68;+A_~-;NXZwnT@G&+~!Up.ZlTh޳ {ԼPڰ@ < M! K,z ;x |.YXYRFA) @gDAP) @ #<:alD-  @I QB1M? LL! *RXv$H$qg6)Bؔ1~ǣتc4-U TS _% 0Ӕ 'z5[ x_s^ؿ; Xi T֘[U;GA+PAR%ƜQ XFBPckmCDP@Ƙ7_@P!j yc5,Z `֙ 2cȆTQҡ1vrH95U:.14'C)0cckS-"i` T hQj+D-jVkvVgͶp7Ϣtk,&cqq%(X,4~D蟉r3nm׈?S2n%2{D/UY*LѸQkp8!?V@Z[F!3QVX,P@e24"BbIGQDrdm _-9|A51obOy/a ےrl_Lp-K:U,Rq7q\@:K\9B 2=!LUdHnXbB~d%M݂}KlxhJZOFbpY[؆kjLl-Q#*GVWjWTê  ⊢8bAv2kx>Ǿ: úRF*VqXE*wX#fIy{(⡉ a'u -aaï{W l1'u -aa˯{vXGA랬GAlUӖ_d㟍=g@luO68sYh P^J2z$ XG1Eʆ @APW[ q%lb N5 /gdbuyeË 3$fõw' ϡc^CK]0I Kv%2ٿ.‡Kb x4 W(X 0u32]PAa0 p I.:1yoP~ " *ƤV4?Y0Ĥa;3ρg@65,k.#g;H9Ip8lX?`_ C:W!0XLUg*Lۂq9Q\s0.cEzj'Fd85sR |Uh\2F!X)L׫XHC:\Bץ21Crq2%>r_bC1Ƶȵg 5wk!U n K.IX8\vҘ)5`)pm S}U-XwPuGA3A( ~e0+js7J+e$qeW (5tNVu0`Qq`8c8 P)ٍeAX/gSg; d YvD}ZD ?]0KXQ)S!"D:Xgϳ87Ye0UaIq!θxD\`9[CV ᮬim%J yNp̵ $#";YbT1ef$ Jna~B#K=7یe Fs4ݭ㏖Ϸ^__=l2X Ta=+8|ր"62ؤq{Q+V2\$^e^ _zu b:+B_P)&it-4_Z8lampZ?ol(C&㎜dlRm*9Z`#H>8)+b >lǣ«Ip6 |W LDvǭqFbL34q7?Cq4?{ܳAө琺ko&o'ᘇm8ed4#YpQ Aw׉V|g`J!1YN0e8dwmބT q6Eض/{H~s̩F(Ċ/;ǰPuie !hhv!pf8UUu#llR8vZ F1߸.j]8T) lýc8YYj9jln囹kv6nH'8`]#Ă'LU[{r{8lݾ@w '-% sC}+wv׮Wj|SL1,x1HvlXdɘc8Hy_EĂ'sI/=+kX4ЫCޮWÂ[n J{r+duuUtu*Igܤ>?`\\-8oca˭@S79I|[]sdr]TWJ8 tpqx:e–+^Ű.n/W₼ŦѥNN # CeخoXqhan} ~gX,L|Xh3Amfȹ98M>Tl@lnJNx!$GJyov7.Ѷ"U +*gV V+xٔȰ5.9#boR`/AʰA_$`p{Β9̞)4(/4TA$^& m$  ֙Ȱ.#b$^& m$C_{Al3,|̷ӜNkI帱Ѧ&Q2f{ 7#PNs 7>T]zq9n)k(TiAw ƫt@~<%MBH*:CfRfۂ̶!e6(&,G_V2UA'4ScRĉ :| 4<7qL1aHu3!QX5zT)|N}x k`PBt^c>2!koF'}ǀ"dBYwk6Q _AF\7D힙; )05.LMT=FI}mAle߸)Mn7Q>8Ȏ) n7QT0lr&03tFNVR,i)ĖͲ́ԝ\)Sܝ&Vӳ\PtMB S)SvJ/o/R!&{;TaZ OBA6OVعQ}J:A}8A^vJQ:ۤCi*(urwW6qkb'jp֖Q>cG,B{ZҭX7pճ됉~"Kg;S]x;6OXA*_%DC)DZ+Ո#|p9Ak͈~+Tt=D٪qfW*lJDn38`*N !W㖥2RI .~"Q$R@#kM:6;(:EJl&`f;(dM' 艘ڌ鉍\>yt)~_g+\Jl .#Wxb¤ֽ7}t+9mB,:OW0ؑyePeQ\bN( 1)!b"hhRB 4,Zy4*- k /e=~R%3@Jh( D `RRvUul|ീwW Gwrs)dH/&jU8)A+ ݖZa0f,6os&f<+ IA)LلtF),XÈtMNx\308 g$AOVMh]_k-\NNP%s((QDzHw-;| 6 S;AC%j+Pڭx\Yޙ6Y8ͅQ*X\'FilOGa]2.ü!OWDO^ǮeG"܌sƢt!Pl' lv(e!/s(ݳDtVs[#j爡92Uhb Jו5w&VM@X>s Y{C2e;Mx6j?F{Ama2LnR>mAZAV%h]@kиlA׵L< {kkiVO'AfۈZЬ=AU[(9ij5ܿhzFh4\*s oly,=lI{q0s7dɰꗉc@QAYHK_E$Œ`Q|oOvϟ_ֶP?;߃P-'܃1PAts!ߔplQ7À^tɟy{eeRiP1R> /.Zu;CT ŷ"^v}`M'K[VWps"B[ᖷr\U}VZw6Fx2b&B* Ҋ_U zHHHɳYcI+!{)Gz 86(,/xw-*V Y $Ryx݀*(J` '*89NTё|r6ld\%IƾÖh 9*@KЀ\:$51I`AMwn+;וd X1'tZS3iJkJQ:)K)c34%5FNu0Y/;6PKC2kej9 Wp&=(]Mޥ 7@|pQv =s B;m`c(y]P/$p⦠3?eszBpk[p9T=l;zq'v*J0vt ePO( uPOH[{6&oֳP&KCPO*ۈUU}-l zB0ʫqI"S儲^&tLv6WOPJj"];&x5A-W))'LDrPv_۔Ϡnl=;g)Hi' Ofx_ h^hYO~9<ݪh gDyzւI`'Z I&4zYh=$A= ePMȂrB1PN8TO(OzB;`•'k_OH X<,-DZ^>,MH7yiIu-'w%c 'XStdiPҦ"@ҁzZV=!H=!'1zAfZ6Y<MQ'Z Jw WOʯ[P8gA݂B}Z܀i@hPB>TP4P۝kw,"T7\vV ng\SSPŅP6V"-.q > _6mbi̧n>mt_]5ҤP?i|-OkAna?P,((⽂B{\ M8jϒ$ ޟ>Bؑ]ٟ9$Gˇ>>;g+ n=#lODuWB~eOܤ)  cN_J!Qw;(a `̟J)&"Hqgv٠ YP6h|٠US5(|ՠW sE4D$LYxgts sh̏L$ReIbE _4kH͠ jTA͠ijdWEݹlj>棚v fٙjP0?,Q#[yigTޑE#e5.1LV ;+IgcAH[GE7%D&OM`]48$(s5.VQreW$^4ؚ,g+ldB@\5X2(;jr_K{7\bH0v+ U%*^g޼}qOs+S@}TeRA]o J{ć[*8:P3L0B Du­(:\l0J)nh%,\^vh.܋!:|H_'R~%ثHU<iVzTYE+qX;wJ*kX{EByvSHBKV*UpR-"ŴHQ;u`{T&TUhF؄D= pp8k$&0/ È) W# ¶VuXO\$)8kOj%֩drdyt[w[řNB怬a8<æZY%iF䏪B𱌩QtM2 #7͸n 'j1%/&X!o d___jLRc LvTux)k;VH)= n=S .W` L R8'lhrF?аlPCf24pl8>ٚVT@Kq6"XS *i2϶C "Ïs "-JJ_5KB$f!aڱLRd֣J7ppŚ8 d@ 'G; QSn܅hIu~TR& |`Pv Z-&+j2F#/dZAm%,- )ƹoҜ P~$ ع85+HdxE1XkTcSATcBLߪ c !F:œœpVZJ\e; ʮB![, ߭/WG쳸0H#f+'^Ku{RIy"ݤ')CMs 5C:[3t.S3^\1a& 'dٚOT1d8eC:|Re C7sH$ s& ʍ,(& 4ihbݤ!zT' 1i9C:+ ж3[ Vΐ9C(!g)C KL7eH}x)Cd ֣! 9Cy9CGAr( jimRsL5ȏ:!a( ۅ00n_'#Qح\tİncW0'I0<Ó;grGi݀(P`F9Q(3k ➽&i׹0[&h\p9Ah3Z-4a_4p<4v 3[&dL6?xڌk 6odOu9=ҩn -ң @5ZNw7t-qDu㧕k66k[8qj#Dդt7cu pðZqcw_I%嗫yYf[j8I'QLדʾ5rnu&X/3Dž#W a濣qt/r#2F9dӞN' e6& Sr+I3d h$/$ FFjǑ8Bd!I`5uic4XqS@VbpTaDτq)Q)h$7|IFc.6 $GM< _ŦÛ=| LL7NtBK,]l ^ @8t3t!h܀$` ȕ yR5Ә\^o7/Y6 p #.`jԫk3 `m@k$᯽XE[ CZ D/fb #W@ZLF,fL XJDL[l "bYAD,dDb6-Du&o6:bV-8r $DĞΣŬ[lpJxt2"1+G]abRѫXUg4̢]\=tsSK#]\uR7C43?z10ܢyGx ķQczv͢D5ҘI:AUj"t*e~dS2 ͋*E2H#q'p $[@opu9kɦGM&ڟ(ȳQnT^Zfx*8וRfJ5t44ZpsO%w#AGa^*2.{ ip%w3w$U(NRp22 + TCvmFv띉!%gknijnբz6Q֦Xsڞ3Qp5XZpaKl|5yf8N#Ɉh[[htD{mIT`guT9uE%|l3ܨZW,]fQ]ht!*~":(x v{p;OaPpou j+Y(%gxe9㏊!9Nú0DXWY27+AB !4!FCBgk[<()[(U,˒3P%ֿBS*dXSC$OU5WU66Q pk E*$a4*(d;D qK6Vp dΰ Ӣ ʸ'6<1m^}~ &w&Q*_5NEJ9rVK91_x=.$s 2+w YDPMθ*=g50~1!ݵEU,s>ڐlRwK1&y[T6*Di r`gJp#Bt.<瀔@RեgCʘi\y*#Vw.M; #U<@#܄st"P4o؝byn;ZF,Zuw"!ǕC@@LZZ$ ueԝhi P0s YɉC2m"oh u[ҔfM!hRusFHqc *b8rU(Ap, |`8׀5DpՓvJܺ*7YG(?l5ܿ0Gu+єR9ի7B`8O~`&ԟJGVnRc[^Zk*ir#ٵwèɂ @*ƾNaa%üF6OMHu!' @r0}0rSHO-S=bm%3AQ/KPCL MxiE~]hUX^Aŷ"^v}`M¸A}d|.w.Bh+"QRh^ЂQpKBh;9_RFK$J`oX6_U {HJH3c+!v!- "Cz'Q>KEDG.6T ?7^M'aR ȁ(ڃ *ރ#Z?g-4ܝqX .})ޭ6,*4rF+YH1!\"={Qg$e+N4Tr!ۿ$v{QUTJVr*Jfm1*ќ@$ݷg*% D !JQd1 D}kOWlT8>ze@x\-lZ8YS#<>om$S+3+^Z`159{Τ|4J=$SRW ~S`UhW Hzt7b DѪ@wQ8E^:>++elc{ͩ^8>n̏ުQEez)ܤ)@$ ׫X~"=o 7?P;?4IN;{&QuoNW cJ@> iLATQjչk ?.Aco\ⱼGu!jcV݌sJ[YmQ)b5imJ'R|1+F<[9W_H|t(GlM{V(rDyiWt#n^ػ, o( j5혊vPw[X[\_Z2iOs!Ү\Rb`eC 6;S} ܴ&,Z_q('YZ@g)^!R(^rL.1Twq/QZ'!^|qXYq%.!uٷGk%)1K*^4E7qob5řbybQdQ#WCc`[" 1W<_b!8ȕ+լgzp=W@2;E_;bPYPxMVFp \Y6Qpa)mH *$Z`iy5 #%pI |oW |K -ķSl8 D A/\qW & fNj"$Pn!ZT&U BɈ(;DWvL3 "XjJF ̖.Az@h(B9bv۶3XƥnR*0DPOBMay! FK/AtLlrPnfة%ʝ9?ZY2r wּ!0M{4x4Hڠ8TdII|5mK \NXil%^Eg* 25R4Bgsz;`=)N#WV'jhk=t{NBseoJ[P6dHW/~Wn~%$6W,`Ŕ>]lUi'E'(N#@`Ob ?@胯KeYiެ<I7y o:ւ,r0uf92w1VManMv&) S1`A-qUHޤ>qf rB2ZȐY)ll%EWݸ1: 6?SH8c&=X{jn@*0#[y6: ͦo Menɳ֭ڟG?2̢<Ã6sTժZN.ϰXze`pf^) x7@x}Ҁ;@]-XqT^apJDee#o 8:rDF"m!;ۓ˿:iU_`GY:ث,q]{q)yl;FL&uBT u-X,Ą>:7 .>ۉ*_Ta% {Ra5tXj9<mhi+tDydyOtnf{>?ąm=4v[}ѷxsۣ2#H' ܟ8>U:4}?;G`_ܓBXfhlO!OIE8Ǟ UT&Sfe=AejU*ɊO"l)f\2[}ƣb h1$1 6=l{k Z41eI `Iܙ7,8 a]WD92+: )R!|Al&09!pA@s5re޵=~UH$?C!8@pQ+C`ΐc|C\S1Gѡ+tnBnR2JK⃈Z t!_2l˄TDlF+n"nr 9GBƙ?1M6dt`N&Vr Ɔ; h$v7p#S8R?SƦ x3á ,1ߙMlr3OyؽV)>1oSrnG[1=U{SV637WW54uЊE K|ZrܬLҭإ[@ۂ$jbvg&־57>M-.,H`FZ *=R 9$W17z2x=*6*ٷ񐜠j||X Ʌ'W,o!drsūJ7[Ϟ5NsiJ,!|5Q•sWƯoi||ҜS#'͵ W`wC4[ ^ErX{Va< r~䶼ײ^jE|o hvP;27yO.tdX;JIt0ծC*eZd- wNlSJ~|{z ~XC|+4I<.jmæ"69MAS@GϦ{n3nbp밙c;.W.)ETj 5 yLs7}Goon vkH7Edl` 76BGK+uמ3z!IhӢЎ$%[_s= ZybJ,&LkZ0pF|:_t+3_m$//䍯WpjPA|{^4_2_n&7yR6suFteO|S`+-#xB||$xZ2$Ukۙ kl4"C 4sv#W%QX}N(nc.KԗM{ju]ԗ/b@$lR0fã(tvײމ6ģ4 S!0F#nl#ҊBnUwD,"-(/4P> .VMVW/ d yR-ٴuZnR@lTjR+6⳹^9/N ?L|o߯7V^97Ӥ?脅6 tAJވ|oegaa?B|FDt?=?|*KNJ4;pAB?_.  |B} o@+/VהӛLTympT|^eU6%fAOƧG[ך .d:2u? 2AKrXG(-sـ:!Ɔ()6*` +!~o8]|,:|Rp!ii[Fsت*OܩU< (v)!KH8x0qj^jUkXLyI/N%~õ1ռ`_ -[8dQdi["ѭR݉!]mCU:)v:w[mLZ%a-}ӄ?3GƤL l+tr5&^P 7ba?M~rP9 K2Ĭ@R ;@tz8f+ rx8@-u _=KKDe:eeB0IºT܅[<زRunjV,I݅%vbV4n`!@t-UVwD ~-wF5OrqUD:nսBsX;\`Y僩OgGReY僩x ]r?gX>x~J-w"@6U[:U/NԖ*lݲ!` [Q/+j`yuu+S` b`)$ CU. -RtKJ4/ưJ|+T -ªL±)U^//uzV沣.C̊-L^= P%=N5-Y@z -"t 1J5fqc# [(Du/4; |3v bV,n$unBd ݒUUTiV6Н)X@[d L(ԋPN4 -T܅kXy>+hx0uqnP{* -UT^.,?p-@[i@WbDQ[go_ϯ߾o={v_||7勿O?믾_o޴x_ճg~7WWWu~z?_~lw}?!|yױƛi9}?~OTMu>7û??G}߼z~廷Qg߿xwy~o^nӘ7Ô< W߿{-޿~o!g<Y~)!Oϯ 7 )Я{?~^"?_ۿVAI7urvMw/0O)Ƴ+W~~~xr1&p02Mir]!z~]˗/E|6:c;1m};xO_p3eWa/?ϫ,\-E~F_V^b(/k"_k|ϯo:yym{ߞS?q0ۿ:~6kd?^\2{\_ 5q6sģb..q$ vpqOkCsOE)6L+7'k܇bēb..q&B?Opŷ^^,vqgP/aVh+\ŷY|+]<% zZ\^7Yl/)1@WozC{5| G*tqЫO`⛆ bCPc1BE Q!bE tԎ8j>@-ax*KR+vDS# mO wAEbQ jGOL5DojOQjŮ(jP'AmA5>赮Va_ ළ5Ӈ6J5LPYwAUUxpZ ZkN5p֠ O[+֐6D\<ms յRu 3tƝkP'-AU.Gi`{ 3qڡ\%?A/'vH_UIU՟>襾vD_ ׎*A z׎k#}UU(AoWU}P_;z%56׆k6D_jCm} .q˔܉FUU]k5;רzP}[_*A}K}m܁Ff;רJP}[_j@}K}m܁kN5 pר P1׃G5tt‘(lT=~?P8AFՅRU_jl46&?ب*Q[ejE}KU'*U3JolT~?8CFՏRU ~ ?Q GJRߠ"a/'Z[6HkUE Vu>6Dm TH!{ުԇƞmz#U%)doP\Ւ=QQդ措(uaN3v3w| VU__jnO> vð3 U~?1B措:5wT~?1B措A5wT%~?qUJokTRs~5';Qը>6@s5'; Qu>6@s5';Q>6@sjncO4wT)djO}Kmf=\UBU YjnJ\s39\UOe܎hn#U)o\UͭPs;~B ZTRs;~jnO4wR-*ſ*R}KN܎hzT[s'դ͝FhZT[s'U͝h*T~[s'ա͝"ƞhS~[s'U͝F=IN=a/5;MPs{N!m͝Ty>K͝'57\s'Uҟ͝T_jn4wJPs;~O)m͝T_jnO3܎UJ[3OYjnO;3܎ijQ)~"܎hn#U=*o\դ-Ps}E jTRs{jnc4WUAsU^jncO4Bmܤ TRs{iM<57ԇhn Ps{IU&U/Rs57eUknR*<ܤSRs;~)Rͭ\sO)mMB/5?ܤ*T[sjQ}K&d|TJF}T_jnOV}?Q=*ſI5>6@s2'T oknR5{=ܤ &UBۚT^jnc47E({IAsU^jncO4W C#U)do\՞UPHsUu 4W.i_j'j ~);4WKڣ?/5',7hP}Kj6ʂh*T[sgբ͝t?YΪH/5;( ~Q)~ÄjR}KmɆZ2G#E KFa/5; ){P!m͝U^jnc4wV3RDsg՟Bۚ;Շh Ϊ<5wV{=YI͝Uu okSa[YJѯ{Uuṳ*PKj\ŸT[tgU:U StUJLWNvDu̔?R]դRUe麝?q]5e\WuU_nOdWM#U]*o]U:jqnVM*mYUN6@w2'U onVE| >ݬ fբB۾U_ o7*|"YfURx0`jj fY5 Y5NjʄoVe*¿YNjʄoV}*¿mYNjʄnV*¿-YUNjʄnV*¿YUNv@vZ'UJonVu{=q]5EeadWtU^ngOTWMQY#UE*ao]U:USTHuUJܢjT[sP_J5)* {EuU:jnQSTDs*P m-=ubAs+ܢ,՞ۚ[TuVEMQY-;%5ԇ57EmQU: ܎h2G Tߠ?u¯5'L7hPk9*~FE ZT'Zs;~jʄi*RmͭFu¯5[>ܪjT[sPkmV5EeaO4ܪ T'Zs{UMQYͭ@%5ԉhnUSTDsjO mͭ:ub5[=ܪS~[sjN}OZscƚ[*q[U{NOk_82nUSt{tZ2%@L&-UN h ٭jʔݪTVե:%}'|]*SwSi[UꔀVޞPުL 孪T WN hm UTV7jUkmq* ~$U ZU'}~jʂjU!~V ߆诚GZU`Uu¯ o' \;5x̓yp<؃"(m^dB/wM@8 {!l+r's⤝xk*="e? aۊàZX/7Me@x lr'3͸%8 jʒQ*܍&eL妩/Wz0m=ja~~4*ܐ&meLVRd5qeI)jaaEV=OV)PdtA {YULe"6)=jSdU,:Y""+SLU-KC(jfBЊC@L! E!9v)=A`B@T;KC0(rPSZ[DZ²d9nF`P䠺Y""5eI)rP,LAN hEn Ej˒RZYAjeЊ 0%AU0"U:%%@9y,KH*daEI kENWVV#T%A;9R)=AeB@T+KC0(rPSZ{D29b`P䠪Y""5e )fiEVSZ{Hz)Ȫ!XYճN!hEn! EV Z "nF`Qd:%%YmhY`YEU1딀VRd5eI)jeaEuJ@+rK(rTkZ"GU U%딀VQ&, E 9F'y"G5AݡQUEu A+r(rT["G U/VQfL! E!9j)=QmB@U7KC0(rTSZ{D29v`PY""Ge)rT,QuN hEn Ejz˒R䨊YA*fЊ %Q0"V)-j˒SdU,*Y""1.KLU! (jd}Zsܡjk5\(d3i"R)=jSd,zY""jRQ4"u A+r(򨆺L! EU7KC0(Y""jRQ4"u A+r (6, EU7 #0(Y""j˒RQ0"uJ@+rK(ƻ, EU+ 0(ZY""j˒RQU0"uJ@+rK(򨆼, EU! 0(YȣZ LZC<CgUɮg $q抜XjcܡYUU)VQL! EΪ!9^)=Y텙B@U1KC0(rVլSZ{D 39n`PY""gf )rV, YճN!hEn!Ej.̒R䬺YAfЊ V%Y0"gU:%%@90KHjeaEΪuJ@+rK(rV[a"gU U%딀VRdfI)*daEVOV1Pd5(d3EVSZ{H^)Ȫ!XYN!hE! EV{a"b`QdU:Y텙B@\T7KC0(rQSZ{D 3v`PY""5f)rQ,EuN hEn E.j+̒R䢊YA*fЊ \V%E0":%%@0KHdaE.uJ@+rK(rQ[a"U \T#@֊2N^\dy~X;wȔž/2ML~<;yr'ɣ=% {:bD^gzz wtoc?buɄ] ;8\S{kPU}xOG,YxO.,Î=ၥNxOG,+㽓G;UWG)tJ#WϞmG (a';OS{kPUp1da>O;w:4=;LjQ#Lɣ%uxCI[#&L~zxtz wOryd"/3ӽ#O㵣'~+G&xoޯ~݃}GYA5}FuqxѨ}yX)#zyw䀟QG/Go8#6l zy`tz x<`tos?b];8g6[]Ǯ~נz?b=#> Î3!9ZQh0ͧCE6?G<*:g<^*:o9)їݳOC}{ {Pto?bȆ^=9.Q'k੽o8X#2q㸧cDa=# q 8 щ>; }q㞮=='C6{9ɣOo82qן} aLJf5O?xl*|3dP3:g=:o8C6CPN =}COSiTGL:yrg,tq2q/ˇq. i/ /LNq}qĈ>G|Bw>aΟmGL~ogɣo8X 2q/χiǂޟG~}3A';Ag-A6[.==^: dC I2P'{< t?b]LҎ3] iOާG>x>5}v93% }}'V};@w>agΟmG>73q7GL}#? ] sqڿz刭}}w/tDO7刑}}ܟ}N==ڳ'>6oq_O'Ow}>>&T!0U>!4U>!S#|lqw|1}v53!}}gBw|}?OsU=9~O'{ 9g=9o9X}sxF> >+~qNx>xq$ ^w_"޻/Gl_8ww_ϰx}9bFq߻xg}3<z1cCW<3+_{ #Î+ {޻|w';6zwd}œ;a{oܧo8S #FGvw_U[ m'AG}mWU{Րp$1!ji|{{Փo|ܫԇ>Î!LqR;}qR|&ۣc={ѫ>$jB(57!u?f㎏YU5ִJ~1z cVUu>qw|̪&}vܫNrܫԇ>#UUMGWm)x JkǬ:zrܫ& ytܫ pܫԅ~>N;޻jiwvB/Wx*ݟ~i{eN OegW3NGWm)xѫ>'rTj'}TQjy/S ~>&rhӎ`M4ԇ>~iji{e&r2[ݳY'ۣOثq?[R;`{˯DB;II*cd VڌVM+<ӎzDjD+ӷ(M{br쵙lzRt$5d!OR3>ԅU,cV)UeǬRP=:>f\ቜv:'}PO&+7A>q_Ǭ{b{z {Ֆ'߀vq,qR3xqR%RSM8//> _> _/ۿ%Syg_Ӵ\'sc;~?|?Ë_ݛWWcᛯno~#nAypv=dnwGtv˞۝z;tG}]gt l= lft~´B=Ivo4m=AXq>A췻AGʽ_b^?qw췻A_a+:EݏZ? /?ow7pW{h"7G{W{#Eݍ6v^ӑhA_d~}]GEݏzۋ_}__|ՇPKxEݾsvg.breadboard.servo.svgXnF}_Z\X N i>:b U$CRd'_3KhΜ9suN~Yz3_-'`,fu9_^Mʯϵ/zt?N?U]|qiQ_t<~eB01,v{lBK&1O]6ABkvx .k]%.y| .CaX>,8, =-6QRjǸ `ކJ09-SNll>hPRh \îAuJ0+a}0*ăVw?qL;SE >֚i!,'I0&WoWe2b_*>eq/jd*0e!SNEp wG fFێFbC/i2W&dYe^|3g;J }tuҘh\P_R̆Z Ýh^ҲC*}Hq))孔u#0Vc֬)>f + Ck_|,,~WHOt8ۃt;IHK( ;*#43;I~A6L+ñ%#Yr*g?~YxILP) (MU/2bTK!?o]lqA!(<qCnяÄ.h=BfKUnSA_t7jf0ej͙gpte@aJc)QS*f]Hʯa ނrhz +uA Jj%7}^5y7 Ư26Hqu35Reb~Əy4 .HMpkpYNJXci|_;2ŚhmoHhNp(8?4i׈1$_UnQRKcdGr*C>|q~FHbBRdk[`8kǽI_7tǢTߨdl-b8?=bӋ6I]|/417 VJOLѥ<,>Wwu45$PWꤤ̋;%5q|A UnB 3KЂw%:`FgIyO .#q9&hQ3 a׵ :3F3q'#ig/:}挾l ]ʩ㌉B6m,M5iA=Z1Hp?YawqgK?C{SZ&Z:8/|k >_~PKxE; % f)"svg.icon.arduino_Uno_Rev3_icon.svgZko vɝ68րSȫ" _{ TDjh`\rx>ϽsW_oVWG3ݪY\\.ώfw6q_{-/۫oW_[ Vo>f緷/󇇇Wjq3sYLt[@O=VG_ˬb#\޼0)˛r݋rRJ=򷱅xKfoauz{~43$?Η򋷾_-^_' qɗedu\>T,KH4^/o vX-.׋Wuu! Ee_^ زj<~Xme߬ZZd߳5|kbUkV`-z4[OqP>A(N񇃺qؒqjuaԵ)A8m=4 txg%)j~=RߙAS*33Df&TtTqKەSD渀U@'_R'jh`w)&mrGU6'8Q`&dew*8Ql*\laiOq2c%Ӆ5{Z`(:xf0qOYQ)˄A{:Ng"j!s}`"ب jHؚP`YjD,VU"9 'OyQ(V5RLכFi慕_,5^h,5=/:杬u5{Po;g"0K;z"9P~|gfSe|F^\6QT3ywru1pٸڦkZy1NÅ]_m ;Mb̈u/1ԗd~1iŌ=N{ np}_^ @ ;KANԖ6ؗJ{%*-m:,O 8L>zI 8y yJuN.T8@^™Kܔ<+;c@&Ĭ!Po;S֩^j&jAHސ nXCVېzysULKaT,z!o(|F" X;D5bҞ5QfWj:6 %HOkrKseQ!ڟ<;qpΟ~͐?q~ǔ7q .IzLC緖ÈI{iƏM&LR|k64hh@{]Z>;۵|&GKpN޿~$wqMY93CPA>:usCPauQA[g]nv>CzMs>|܋1Hf(݇ڜFL riDwWkFL9yLOTrTCn (M 0[psύdPc7l,G Rn(q!-D! '3s5[۲բL!dQNW}#|މh@aUʉȧ*ckeb\Jqw%NBg/ ^ȶ+ʉ!#dѡabg;}4e'OM.%!t4 +m>sPϖ]9YSFqBE> IL`ݹiD( cm9J@zA6ȠٔحPyhDpAVؐMd5Tq\9Hsi[5$6f# m")˂+(*b /JиgAI0uVKD3 m#ZR 3 CXfO3M{ xN6<$sCGupE4P(C[0:+rjd'Aj-iڒ|~+6ruΰ~j^\˽o-*cJ -9b2Q!&!.%\Z` }̽ l(wC#ctVSGh+EB:1:Td@|.$S(r0".ngF<\*H` #@낕SL7eG2:fT{K"FG#K|a!@MH @(&:ws0`.kPBy,ͽ7Bɠ L$,gw,.-)K܅1:[XH݀e0f` 3DNa[خ=J}/Yz dZr``]ad}OݹD757:Pf#b|,SO}_PKxEA.nsvg.icon.basic_servo.svgXmo\+;V6HmDDiR iGί3s{w' 󞇻;Oݗ;WJU=vտM\uf^~ͻxr8OWn._Vg֒*>cX+RZ ӻRVEg)m%)K-,HgH42W zߪL?_öp9#* ԚlH05ypǢ[IZTul@kbo.i)iwam)AZkѦBkV<<. mKXAF pdQ*%7LWWo%2pLU|X(L`%TJ+a& HypƐ,B 1)e2u4L$\0Kma#6,KNY-R`T!2bXpWsFcBq,ID=6b|KNԒgb>i5d::-H)<ZԈcd!;bEyd_~FF5y^5M,ޚm]7fn͵g#yIIVff;mϫ\R"`f5jvwT*¡JZMʹVg:Ug7'VL3腶3-0g7[oQvc jYhkk\u/U0 D{;sfu۴OsE[VP:cD HNZljI͆g""d]3~I>+ۇIVB~{<-^NMx~+:a",f0;Y^ iy{ݱݙTc$UBs %hi)!87ǽ S21d- Umh*idOӄw Wczi*k ƃ#o(3fB5=SgXWd}/ ǎq@Ty uŒ( .aa98DY e]S\d*vY5 =O%f&Nǒ Q1VQCЩQpq ZD5Y6D 3)@̤/V[8_k?gJThm2Q+Ld-um2aNNxpW)Ʉ 'q_z]4sPKxE nsvg.icon.plain_pcb.svg1o@ ʗ#];tjv[:ra i__*vl9H=~Nܼ<-s4vZj޴ϣ\MWjjiѮ9wiE<.Ç!#'[Lz cwxW˴0%TN#ͤyOR|`&~GM|mfY.ǗY*̳OnQ/Y=}9z<DL!jzl2766j*m lJ^=Bd}/I4Gx1!@UQu_EtTmC) B1Ƥn< G%!HEցz"<BHAa4X }RΔ(rxrO5c< {q_fL%$I!&41p7DRG<%8B2MF%l5Z(e"f0N-W; re??PKxE^y svg.pcb.arduino_Uno_Rev3_pcb.svgŝG?E/! z>D9͡$-`o$4BQbv5ZϗF菏1jYxY]\| ?{.ogw+ EH.˿J mѫ8j>m?_tZE8f6yuهoWl>tv~ֱ^Vls'7ݥOWْw1Ќjsɘudzp$cûܨIlG6el >6D|{^wv \|.uxVpzsA+cuOm#BB,ӂ #M$iBb뻫U<w*|!muw\l d[]2JdAU$9ٖo JdbSeJ!v`+`UxDckV֙ 2KN%%3P/pd'fF^6F^k_J#B 0h V0U Mrvsrà'.@ gm)!iTg\殀A#O +V(6C,+C_E>h|k2eU\ N\m梎ޕ˫J"/|@b#,%Ll%Iqn*mLW\g~c,&z+Ȍ6I2GRʕtXzofڞ}ҏսIo/%!Amm- E7>t შ[9u:`#'jȔ".H*`NR񙗤6EJ)'~!S)XlQ՗*1*:È-zИ|+ A3Yt~(-!2H0`X"ņJL&Y|\/iyfɗ=+bHNUaJOv)%Uӡ4-Ȅ'j[p DxZa˗fx-[ 2je *ʶWjA%Zj3΀2F*np KEO`]ѐT(,ָ)HsR?_ Dtei:`e2 s7ԱtZ:3i^KF'RgXåk{X,K 9TjE0v䰶qRgXO4Bt(43,(ʠU1ޖW!cWb xF9l5<0O^C Q*j,h(. mp{0jߡcO3y9`j %jߗ#W&oʑm.#.]_`By#=׀j0{Ey̨VkY,PQd @?lgyTV3l@-38{h(.`pUF/}6f- QH-b}Pcv;&y @fjf} | gvu0{Ey/+JKUfϰO*f}`Qddb_VOTXV X= B%=~mUJBы|`NMGg I gi0zj>ԻҐ}5,/7үcL;d_Ș)~#2FHVJ"{̫nv~y垙l^ם__ m̼;Ъ-m&T6}P=ݠKӭC;kh70 rխC{$e^yH;m^yHhb/XL uU{wp%c]!W*zZ6_}FL Kj_/kҏ6zOYRzun䘀hK $1첩e{6;wt!lHW'er쓝.6={6@}y<=`~EX$Wl߃AbݔS1q|?|~=RpԹ!!ي_[oKmfd8K*)c$(GwL4\@@OF|y5%=\n{mvW5z4l19 rz0M dLݓ(#dH%SJ}rSf& a\m׊|+ZL 0^@d_yD"_uA/:M kO.6}J94gC(^zO>!ȳAߓAF?lCFp dk -W p8+gy)ꔜgzEya/!_4./W==¶}\gl\xxFzu}z{5z{^?+BH!l¸m&M~))V|tyoŧg?}Wmť5V"2>}hJI}2{ `׊`'s 0gqO:92Q4q?6ǎF(bAB1w*CK bsYFlQĊ؅E)c2̞JQĆX~P / xvM Cd12VI|# XB#3&"at8vZ{pLw{JwrQy 8-<cP  9mm:X¤8|,.h &eMK_B^kgw[ȘF$=&[Ƽ< ޓa렿v̲-ӀLHtErEq%iF9N +wNשz^:EϮXxf4pK]:Jl|'u0 AgB7ΜKd@bgގƠ5X l_)+(/v0xsPKxEr#svg.pcb.pcb-arduino-shield-rev3.svgU[o0~N~>M B5JTZiO7a$ٿ߱C6JJ''-UdeaF(FH4+f;;';FPuܖ}H˩By51!& %Bo.*]̾,1ƛ #E]Gȶ5ٷs,g ¶9>309m5rjEV̹j%vK1F6@0c5(,jeγbqȑaSp0ټvGX곹fL'{ڴԗE+uSii,fu{V/BVJ`frqK2Wq;0] ( 8)5}XPO:y`>~U_"b*iM+VQq3-.ۖ(u+@^x$ڱ/!S ;7$ ^O}J|L(೬Ml4@q澂 @;~Hl7M/VxߊמI\EhwUuKWz~# P?@:DzF277RWPKxERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svg՜YsHWqU1 ȩovsxHXV"_=\"֠]Q ==7K.HVau۰t-,cň*`G׿FYi0a.0XW^Bh'ddm3nt QL, cj8].H\a@'V8d }vdq$ Lrfxd="!2čGm3#=Hqh>11Ǚh}6;Lrϵ4=&Nn|rs/)2\ygmue2Vj3BڒMӹjN6uGG0q 2e*$X`T+$s)+ZIƾ}\ f6g>%6h;̲]_rY"rښ|cqY{6'?8e`Y߾رv$|x0+s b q]z+|o?\zA0yWPBgM{zfkŪ:d1ӥ:$`fB!֠\J9t.MEǞ! %Yf6~LxVLcnN#܈0}>du*Aoi /P_. 6KS?7kKgf4y ޠ6iciUЯjKTF`QyQMUxVY;'xgɓN`+L 3_" |xAIV'sLw\m!fϧ{ ;dIŐ|b˝ '>y;]8鰎0¿_c#q(0W[98~+U(;ӫ dMV YMuh?$ tR5rR Py m}l+Yt}+$SZ;QPp@G->8KKZ 2$Cr&TUhH8:(ﴞ8])@J|(+@V)В1rCjUhm{ k"yNP0cGL_< ҼN#,CF k2qE2PTZqZUS50m6NV|HmHNA~vyNCwϱ!Ac6;:߼DW@]w¢U8ƕ=w*wU>!wZa$\DBE'!_3Y"}rPG؅ 3/~,K3MGo)$N8N\y/* }\N2˂Y,Y]/PKxE)C-WTwitterSaurus.fz}ksGXNnQGX-k-˻)ɿV~M$͉]UY'dUW?a?ƣ'Ο̝뛿=^`W>sssw*NhwO{]{}ؙR֠oίF'w'SNPOzpz0gM/Ik6 O+t߆JFYw WO~08]^N[WВ3f~̝3κuZwLx~RE5ίUKO> RtG~w}ͦwN7ޤߝ'fY~8W0Cדi*,Q<?ԅFЮSp|2Ǔ'?dp~}>?Lh6*/ew6=`ZW{ͭx_zFϠw37ntTP{;Š?G~VuY<+ Ź~=?c0/OicC箺_w&zڹN>A?󳿮jA~n|" *[ÜԟԵ8>d>?&Z=?f $9W)@! #}>0>VA~k]Ia< QuED,jc!_d}*Իb C]*לuM[4,ǭ5bmwΦ=TYS"xQ{MB(G]|n, -XtMŲ -Wdk:ToСr柣2Z]ٳkV`gWHHo|u՟Yt6GO %˝vfX3opIyD1ƕuC>0~B˲a_&3L>jbR\71"A`)̄ = $4=O.[K._r" !҉tA &K>W{؝kU`:xgg>\nT OwN1L|v6B{m])'l83NZg zzNӫ04s]gt,=}KT=<;=no Sċ*ىX"[Զ%o@+~ND<@mg9p-\InUk_b}>eeᘍk/'G勶 jcF G<~}9wЩV-w/jw8V5ZMQţ]G}8jt K>sɧK>&߄t7? V/S0.y,S(-ܼTae<CzS<jsE[zۿ+W2OCҢ-##\„^cċ}:7KZٹ xHvCsSzY˹xK90E+;$S4/[ߞ[ƿ9=8SHLQɜ ^l~/J ^Թo\ڰEoj^\j8S{8XCXRXWq>o5%^4>>T<aՋ iH4se5b0: Ӌ0e+bbΌ3.־t FNO3vCzۿ,u\{<[a[dz25p H1)r?3F!G̾>~7GBhבze&$N3Ra?*x43ڽw改S+O9g=}4`<о,ówU}[Kc 'wYqw396L=rNjB-\`+׿$$>CXf;qb펋N!"݄,!赾]j<ύﲚKg=spVL>~I`78~fæbMѢySx[+1dY8æ>A8 bWH?uT`:`ѰMEwC}=iݛr27 jaJ@+-62P o|[`d<Ɨٛ9Xm!kב!FþO}0hצbAGC z/Iv m|S|a]DŽKCHHxP{.'%@{m+l4k?T"sm*V/d4kt8W,D/׃8lz1O7|V[wwna侊]MgZe nS,Mz}.kclF录wXgYzl.OKo!a/<$ )h2vШVIiHls0u ;fh8أcS`9XpGj27;'ژ[xtiGhV.Qx<+]c9ud,$Z<+i4kSzpYM?xW&^//hgCV]gͮt>|xr;0˭dһ(]cqZ\tw3c쟭ز4N{~ l|y}dg?Ct6Ͳ~:.uc(ůN辞Pu4?tY[}Ȃ^_wSa~wMB뜗g6v~UȲG^B @63k^A}?o j5znXYgr!ݞ^C?D8{>hJ(A|-0iXTιH"m,& sLJ_4Z7t0=VFϿeśV_~/Z_eEoohw:WIbЛvBN,ntv|eY?OQ}}px"jq|jS}Of_ُVN'ߢk_BAz0>sui1Թ6ӹ0"Lf_g *`ád&<1a0Ez,^v/[*9뭍*1t7r]z_d&|,xhy|`6 =jIl*wRqvx<%C =ZjąʥømLk3Am2vRXE,wr8TeA^} Ox:PB^zECa0ncÿ^nȅs$>:wBpͣx,dltxP;;ЈhVh"d*!IAʵ \}C&rd*#=OCF- 8raDhSNe L U:.%7!46i&wqNcKOcF^pE/v)KXfiUNT΢ Ëp(Dᱱ5jèŮs< t2xFȢc)􋀕6_R$=z1|=req⋥\swh[(4ة(U#0$ď794v>fz@cMlffɆwE dŞ0: @ M <UShI۵Nz...;(`*ՕoBb(QNႴR)$Ht(r_P|Gpnԋ?ޕpCT͜8#~==\=㌵_Zh!!vL]%n)%F]\B^{Șj L28 7H$a ])L1p.S|",-Y4w+8K)Zq>>Y )qQnrU~F;QsvCA=ѵFW xtW[s' Q@\^<9jKj|eB]$$D9Mq1y8 =Nv!%6}{ ;&gf3LStL= $,9ԁ8F1n2A{t`]kf^Զy`ށTsQ3{ ."N܂'%/K;ֽ8G6tW|vCXa#+! ^&Xr"3DWE G=@MxI1,#&tGIqy *(B9fBQJp3) zd$'9dLwF pm! txEu E!7$my N$ԑiJE HO"+˜AuMWPtWn@!{O{J0ܑ| M*19 ?QTƃCuejTb @%5, Jcd!'$͜SXH)ͥ(HfY(92P jR4j#05E%3P2v8y۳ Y]8< , Gy쵄Ǣ_y+ZdD _%d1t$[>ddQ G$^èڬUG#!/K($5#ie)TOXTҩ 1h;#!hP$eU I+Z`|oC{E";#9 ,xa`$ FyYEH$hiU1"B($~0k H@oȀ䡡H<(4B8 !+$-BNDtb,2D(87wxH[%2B$8̗JGF b7)b&a$ ]&$"J5Yb 8F%AmCѮ4P\JKd֣1EL Frc (|$3 BF*b%'<"s qo_qD(0z?b"Z>mU:-sM fU%7b6OSSHDUvoO!lH Fnl@_(N eF!)RD<t#wMJD6MBL8@j$BLØ[bCM𓘾`@8 (X3pV[O #Y$Ɣj"E _M"H |Qr&DkJ1 ̀|x`J2Zu`4&%93ԵkYBE3R',cĸXM  |2="GO\〟:uRY6iIɈZ4iԆWqj T0Jxz=E[&9"Rq mj@]1ikes΄F̄mϼ\ S0"6הp.*9B ,j~FiQA zz* R4Z2V(axJ-s* )D¯(99yu_"}#pj;9ىQEtABpLZ")c9=9B0ڦPCCM##<;la 5 KEI?Ncuqst<R=DCyxH4 CFHcb.;.ǡ2P ^`a`ȲJ(.cH$iVR:4@9xJ? '£_`ymjM켈lMD."ST"$C$o+uqohT6@%sX8dť/Ed<!$ J B`2q`>e T3T="Y>8r"Ri T/fd dDɉ*WL#eiIb {zۊ:l jBLi'zj 6]ȰEyLt|i\9_u5˳Hou)L'. ɨ4KibVՄ1݂0=8Q%An/+38\b<t,,oK)],ô,ӘLIo2K_{VLE5qM$p.R+[u傰3'ewd``t)}..a笸^-nS0__Zaq3ڽ_&ݥR*8aG!d\=f|eLxhG>ԅ}屾rUh*$}Q{әm ^nzwOrܢ-ZX?9V|sӣzzOп0h}fz%ۋ-]ꛏGGQd[(>JR>O91'hMs2.*12.V~jm>:ߖGDYE}tj rVf7%&]ԃ;D|uc :}pY+?[/-F>Z 8z='Vo. -X~D݆O⣨ۈ׶ކx/V}/YhLD>4W"_G _-37ˢ^Pᰣa]$~Ik h !f8#!<0DŽu_2PoEF3Uɽ<$*0-2jy![GoH(+Ōdmb4S[Aʴ̮+g!XGaYZK,Ke䆯^rUIg=[Ջ^W_6:Dqp-q(hXFúOm=b-Y]5knxaFwoʥITZZG>P},0~0߰-uGQ_6*/OzDfmCS*"cBv7_k½`6UuPKxE) oTwittersaurus.ino5 0D9(Y?[]hl79y03O xal#Kqz! WjROK]czQl'뛒o|07ulÙ%dи.*ԿJiPKxEug6=$part.arduino-shield_r3_two_layer.fzpPKxEW Apart.arduino_Uno_Rev3(fix).fzpPKxEmY(H"k part.Half_breadboard.fzpPKxEXRH] R0part.servo.fzpPKxE>6Kz.2svg.breadboard.arduino_Uno_Rev3_breadboard.svgPKxE%%k.r%ƭsvg.breadboard.Half_breadboard56a.svgPKxEݾtsvg.breadboard.servo.svgPKxE; % f)"Xsvg.icon.arduino_Uno_Rev3_icon.svgPKxEA.nsvg.icon.basic_servo.svgPKxE nasvg.icon.plain_pcb.svgPKxE^y svg.pcb.arduino_Uno_Rev3_pcb.svgPKxEb9_M svg.pcb.jumper_3_100mil_pcb.svgPKxEr# svg.pcb.pcb-arduino-shield-rev3.svgPKxERN1<svg.schematic.arduino_Uno_Rev3(fix)_schematic.svgPKxEwPl;H !ssvg.schematic.servo_schematic.svgPKxE)C-WTwitterSaurus.fzPKxE) oHTwittersaurus.inoPKIVerstaerkung.fzz000066400000000000000000003131701250202676700332500ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/FritzingPKxEug6=$part.arduino-shield_r3_two_layer.fzpTQk1 ~߯0~iCa0ǥS}}i_?پdIۅX'O7a[ɔ3kѮ}(ٹv0+ krɑK]K7ɫv^e& B2[|rVM'EvЅ5L|z̆jvTkTs\z?qWLrYpu%&3=u!Kݡq0-{ѥ]g@8S'GQB_uN06Nq269Ҙbi>e--1܋_b`(J!aԃcP]G'— 0;<')a6XO۝\ Q828fM焃XqidhM.$?e+q(ͨv*C'?!.whuڸmOuNLfZ4oCtmYc/a?\9ZYŒ&:@aٝnohɇY:MeS/Y4ZܙӈvEcDъO`Ix$hBc6Csb ڳ]t xX򶍮1:h<~&V&?r?F=.tRMJE_(3ߞA2,<3P%h" ")IoDl*j&#;]]DKFgLPȀ%h&IKTdO:@_8 Jd ^BL*%%E5Ey*tV"\pTfnZH*Xctqws љɊf,^wFbaٔ$GT"o t,p ddu fqd _@ g84I$CI~#&[}SL(tLfftM +K4Di][% Z usLamoeLC'B PGy,yƪ  ¡b[L8k!ل~&&h~)dF#na0< @˪YmX֟lEJxuT,oVYwLef{:o]ÌmE)ytg/oA7Tx|J*V­D2/rCO7\jGíY*lf3|uzjZ6:+az SUd]naîFFqحaW/z*ܛ.8K95rhš]C[/v=Mq+8ra({U8WC{S:5](-4ţSGG/N=M 5GiGl X/ H-c0ҹlIH{?xTkKRzylT:b[2U4>j{V'0N |;s"щRq }_^H'Lv0)IIcSq!e IH`D1A'}!:rH`@K}VֽWsp8)I󱁃 ‰W#Tb>͚{o&=057&vv־_sI`Nf\pJ/Bd:1j4[`FONqn<[`O`Ny66<#nJ#m\bʿőh HiJJq\ʿ1*Q#R2 +tusW:5㚗UlJmMtj]B\2!|k^'T7F(j[bkdvڵB ^,4f!&2{ցD',.I%.5G0ɥ¿1.f_G ܯɣ¿1?tDfV"Rs5T7F?TRs8jRoJ1OY@*}!5AOǺt# t2iVT͑R3ңoMkݖ3) t2iVTqR3ΣoM>H]bV\TqR3oM\w0 'frHX!5c9*ƨrR"4!7DsԌߨqH{4+zC*Eo Q7FeTT!b8Ds ԌDuhVTR3~oF bҿ7蚵q+m\{Fpḕv8[sobӻ+ZHɣY{ռqkmT7+\4n=yOӨ5k֮ƭq5jܚc<Ѭhnhhnh*xyumP&@MA͛h*x,n}.xHdumP>@}]u Sϒ`3n45Gx/~x5ƈlv*ѻ>lZfE z j+j 1- b^WT9JrzWȉŸ=B 9F 9V<BQԫ,WD:?^}z]/Ŵ:V,?PKxE>L[Ԇ4 part.basic_fet_n.fzpVn0}WX~'`JPݪaҾLS' [@ HKk CRj,H('R5~MD<٦4 #xJGۻ%.{Goe[ubĊ)(tƔ~&+%G_bͻDw%l);2 3" >y!PV ێKxV(L4f7y'"kєmF B)\:!21l-p?a~ďO7+t^wƩ=fWxs;p i"JeaKbQ "JR\Ad4E2αY^YE=fgW[=vevW]&Ԃ%˜d|8a}kpcZZȘ|lWCLA#"Z)M7582}ՅhOڟt?S(39P"Yu#8EȺy3 we-Йa{sG詍zRa,$à!{G |bid4=CtI(YҶɠ2qəd&La#so5@::<ᙄO:$R%E 9:qwDoo̲߱$Gr%.%*nI|:G*:H L?hYWp2Cw^M&㺊t6 dmFlOx4 % s1ޫF$&=H攨qBKp!;@,1<鯟c事Fc朁2-fYm305nڦTBFCJ9n f*L hZ'tc!O£9*%^%=ANGf"L%jD<Ȃ1wNf㱃n6Jֈ]NxDHwI 'ssNYa~4 &ByE4up &N Qa1"K|?:E74 rE!ƻ݌6뢎6#k֊|At;קN,ȀGB--ڽ C=qӇ oq`(BZq5HĹEf3J)E%\nk;H."Lft5:\;=lE> %6Zdbm]12 bX$\Mjx},ܪ3l w[&ϴSMLU.mzVmzM6զoڼnm6tc PKxEQVC{Y part.dc_motor.fzpVMo0 WײbŶXa+SlU YёCi|GwJ2bq(T9Rl?'/_=|o?'>8y_7>}vhgpz{On>[zEz}rOZzOOE柳7wٝ_zyg/Ngwח.~ɣO]|rv_gw|y}ݛW ڧqv/|^x?λ;~yyˋ?_v积.uqzWogw~6g~5|Qo6ū//>~/xsxrAW׿r˗~ux#sy9>?nM'ynsl^?ݧ8*z1:Wyg2^=/*~y(޼W/L^1h%~n:ͥn^ٽ^\/ΟW^kyw Q/NOn~?7=8}S{~@_]=(x?7Wzrݛ?G!vgk/em?Ƿ39/SK_K*z_a_Rҿ^>mX׻ͼoO.;/SKK.zaRҿ^>oX~o^)av)y?D/0,=JǹatCCCYJER*}.r]GPhRs">""GJF9949T\0ȡȡ,"E}D Ef)>9.r#rh(r4KatCCCYJE)=E.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29Sz\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K2]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhNu.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CY:"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GtJsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef9Ů =z' j~rkћ9w8wy#{7 a.tkћ1:w(Lwy#{7 anukћ:wx`wy#{7 avkћq;wtwy#{7 awkћ3^v2lix4LyrxN- i5^ox0 /;^4<Grn~KEoHbx07ݻ} y?FG4l]J?/~~߰`^?)av)KSCQz}g g:R*}>s}fz64KLgzp,3=GggÙNtJ/^3ӋLYJgz>ӋL/3f)>%L/>3tT|3b8iNu>k^}fz54KLgzp,3FgWÙNJ}W^ g:)gz>ӛLo3f)>-Lo>3tT|3f8iRޢ3ӛLY:Lgp,3}DgÙNJ}> g:R*}>G>|f04Kt8̇ZڏУwo0x-z>.~yOrn~?^޼ϔ'{7ϜfC9Ns,< j~΃Ӝ9Oôg<4r09<8y4Lyd<4r09<:y4Lyfc9Ns-< j~ΣӜG9OÔg'րӑ5`yf&Lyf·?έ˃k6aZ3s>5tx X^ jlMR̆wMV̜MV̜6MV̜vMR&x >MV̜ƒfMV̜6ăMV̜)vŃMRx3ƃMV̜=ǃMV̜G6Ƀ.MV̜QvʃVMR=Ns[y<3{9ߝ|4Lyfs;n9iV̜|wr0Cq 8t,X jqpMV̜>8'l´g|Cr<&g<21yt?7aZ;l9iV̜|vr094圧aJ3`sr<'g<3ßN9909t:'-لi599hyN&Lyf99霜dyN&Lyf·?''9,ل?on<{뫋wtUq{͟zrݼ޷͋/h_JnJrגywzu-xz'{$7ps|+py5d5d5d5d5j@j@j@j@j@jՐWC$Y Id5Ր$!IVC$Y Ij˫!KVC,Y YjȒՐ%!KVC,Y yy5P$HVC"Y ee5j(P$HVCjP%JVCd5TjP%JVC]^ my54jh$IVC[Y Md54jh$-d5tj%.Y ]d5tjЗWX^ Cd5 j0VVÐ!Y Cd5 j˫tAP@DuX2": r+C2Ѥ&e82 (eB)#uuR)A JXJQ%DX "WºW:XH,AD 2K%,%Dn "\.a.a/A K%D "bH1AĘ LQ&,D K "g4A$ "MX7MXGM&XD "؄%m6A M&&'D "r’r9A NI'ֱ֭D "wA O'D "uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@Q{_ԔW5e)e͵֔5e)Mٯl(( E"E⒁@Qd(2P(   E"E@q@Qd(2P( E"E@Qdd(2P( E"uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@q@q@Qd(2P(  E"E@Qdnn(2P( EK"E@Qd(2P\7дnIdIdIdIdi@@@@@@Ӻ~μ|gY.y+_caVXoMow}wֿo!qm\_M{o~ӯIdV)t)9{In޾ 8|F@߅Տ؞>DwovbN}?xQ *9>Dwgj5FPfen-#o$>$wPSvO=>6oq7woo||z؞=>Dw/>Di`jMtm_&BQ#(yȻɳ7zao?rt/|{oWoSr7ͷov]X~I>=lOeoQtwzo4Q }@&?|df˒/ZTG}I_G:y~gw?PKxE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgkݶ(}{>djox8-;$sKiw,U:-$v~ZII-56 7/^~R8\^ᗷ8???_o|zxg=~<<߯_-t (x>oC?6,C_d,\o>x?~ѯZʊemqqOo|A Í$/n/}|QF痯O«ڻ׿~^>Jh=A z_>?}7]]_^ŏ Kg>?~[C|?_z}?ߟ~~supxׯ-?{qs}?zJzOiV#:a|g_ώ?'}\Q0¾Xzyv}~Nj˄(?S̐]{A/K;Y -豼Gтߨ B+󄖢  l3yUI!8Y(r:_NvYʫnǗ\7?|^U)('ӢQLEYp'JaYt3*<`K|z[rq#\^:a_:aoO8:ş2w"n"r Z$@Ky' +;p$Qnuox^Z<`$!$yIꞶHIi$ 1b.k!F67Is h7V,@!\߈yӝ46-KQcjr5?/u3c[´$,T " A/ oiy៖ - OA쪭=x_D:5okc >:64.:{; ~*?? Mp)=~j2:5ֽ m [KUCkݛgftBtNdg,ITAYޛq2}S!5ֽ +G 8 q"22 =;H7!eķ8WWoܐxmp0~<. o5z! p^Sh(%5J5zc صnMxN):'[g#矨H=ۆ܋Gy7("x'jyZ MS .1QlWMc Xÿ!^aYT,cz&dXܢ  0.) b2 nXJ20I1LDCOD6!cB;Cʬ1d 5Z_`7 C n= 0bm1 Lx`xx! n0< Q a%aa_2@Qt_5t}J׻aFc5(4.G2 z\,҂7p١^YB=Np t`BU#}Z+S\ig'U ~j?׏1>xejb`S}\#eԸWih]KzmyVP;\;!~t ~U ~^)jNw_)r?G<t_ 5ܩ3jO>1^ 4`ܨq#V4붘L 4ܨp a&]p nTs~V)wƷkV 7Aau='k2P& :ڝ-$[de5 VT.{г-Qe(l&ǯ(X<Lp=_.D UP`E¯(cm85ioj `|5_&_Vc]u5$vk0 g*P>j/ZjNw.L`?O<ـ9IcV]faklpgZXqyOAvnMsH9)7@'}<ȱ(rAz5̞{; !h2yvqT\Q?6Xb oe<š)aR 0Cfa!#[H |ݺ7  V {2Dj=~{_|mBo'#tJ/\Wy _o~@ɟ>^/ۗ>CB۹| Bd8y??]8kx[Ѫɧ:oE _'~{?~/&G?'" xX =z4<^Co_BD"!z_/^Gf#kx>/o£"!xz/Gݯ|'ݾ_޾~{A k/xFC(V⨎"YCaB[Qz?O"@g/-zѿH"G{ń?fkCƌxNWpVhq':_z!qRF ƽ$]GtNuuT.)}qK]t=a&(5M]( EדҒ1&GwϒD(W>1RgE+WiWQW>ٽrM&+7QfzDxfT^0fc^yqξpNW>4^=ŎYoontvĔSףڍϜϜrkGb{Jy ?U!$ha8L}j>$ϋ^>>F>F#%$cN,)ؽɸ.'}t2e.Gi@ |(@Geۢ>D.݁^NzL0K"꥛IߴIߨINzЙ V:_k7I6qUN;tZI*f8Q&8nCuȥm. D]KkSuSߟmBwjiԟVOqSlJEݟ*fSQ&8?ˇwt's]҉<-<7t7`g7:۾ _=b]|\>:|ѣJ>z Ξ`>D.ݯ5 \r_zjd:Mbu-79l6`f7:?;$E_`iyfO""Sg`8h?~9AX{wy޿q.F(m;}:}ٍ¢}ڽP֍]\/h"thS8pWϮ?^d_q4; 54i xċ>KU h"$x-1Yx[Ȧ'ƀ6m'9KF2@ȧ9?b!YK,x{ɬ%?!LbY?q&X<`28ȟ}/>EfM #3v,KfMc &3~E,Qf-G/ JC28ft"A1J_O m3]C&HO?7tܨpv{L-}N+w_ZƂy' v͉̀t,596'"ILDɋ?}enA jH;ѸuImD)u!#%6=.6ڭin1ޞ3GںxIc٧Vh /n5{3h58{N8{8{vm-=Vueɳ1K ãkx<{PtL՗K"t4h\_,h^E9#nDBʑ52^/Joaq^8}%ZDmӷ&Ƶ8?](Βksv 9zFV<\"+H\ 9FQ~KDɎ d$!<ۗKX$I/ɀƍP|ŲHrZeYf7wXL,2EL͢}^0&Yd8@cXAPŜm=Bk Ns<īDm<׫/f~~ y;ٗrh, &_ XcQ >s'K1SRNVV 4Ɋ0,&S(\䇓(c *ew𥾽3=\ubj$OǕ-A?=XF-Ie 7;ZIOB'ZD}C\{#/ mv~g,dlIMn4wzBR"tz94>-WɘY'(dA,OkH嘨7Z&^)Möu=&ENu8 TeG{.:EϊvQYK~$9ُI|4]LQ7;D1AtM7)n> M#Ҝ#X? Ys~c 'Nჷ4%ߘkQ>HXWfIƷ5KrM4Kƈ?>|-[iR*wQ9MB}z;SV5xdU |ݣ'}c F,:6 G`>;&#ؐCD,EM_|i*mhr W66w{tfl~..S6t/*fAbB4P&׷~s}/0ZU9}5 $Ml/I!8W'+%8PBKa?cib)%U m(TR wmz:\+K}im!Ƞ c^s5J4,mE?J%-âɑpbu\wZd-#-=%qoO_މ%i|mtDoMMЦk;hvю0FN'bdwIN' TµR]'yz {8//Ǽ'Ivbv"X}|ԣ֣ @uڣPZN-(Ԕ"UGU6( LG1$0ƣD ʣ( c8.K8 wIgy`aKk2`/ ū7!o­IBIP\](gp]oBƛ 2:/ ;Hݏݏ8VIs?iSsR(BAB'y[}YCv$kp\1Lg)Nzt (@lX'A[~~Ҙ~~3,01$1U]eIܵ$v6~_mwVs_Y $#sO̸n2z}t!5hɍ0FkLsoH@~EU_;,&lpQygz3`?8l\\31:#ѣUw$ L#1$0őF %~D@ONX+9Fp?6)4S']N0Εxew+~iw+BLÒwai4O/ݬ^ر{JkB=9okflk5<GV 4`# k-}dVhh|iJ*\Ͷؙ@ls]<-6맟~ivZgt-Ƕd[KƢ|V>~4'ۏGǚ辽|ئ5lpӚ8Ao#Z̫gW|_K9˂9g9G1RrTqq7Gj,5ċ$jo̸q⍟6ى`9UL7y Ww8+8;bi,P#fZě<ר;~x qnsexgtǏċ>34io´Ǐ/''^lƀ-L8h>syYx:x,NیrW<Ό+x|D闩D<! wAXP!r Ax"UBл_,9qhI0I[NloFXH!rB )LŃ T?N⁙g2>c)| }b$AK2F3zJMq&8GFSY( MabN" azm3F3gJ^[=iNl:سf7ںTIqQ4b7q_k9.qb+"g_1N|_/ 8b<cQL8bqJ1N 6qQYq7C-bP" YXC m&Cmllnyl#ⱍȏmcX^~Iٔp#Z9_|y&9"?9Gts_IO0qb9"'5G6ᆋ.?7G.ʉtd刜or$9"?1Gn#cnˑ̹&Y92?+Gv?ӓOqò-.>E2'Gӧ.c<$!eX@,sb ~ef}r"bU閩T<&V1ě- tN0Hn* hXu7[̙W9ᰢmenSʏU}S HV d*?PJ3a*H@B2*?P8ۯ;>kXrB !˝uB[~Y!TN Z1.CBuܿn8b T+|>%*?vPO7vz.@BsxCխt,RAD=|*?xPofϐ:=Afj8t~;7_O~7<ۏ/O|9~"FQ %t+kHBGI|$Nl pXBK-wC JN(|bqΉ#t+[d:?Н8~գ~bA "t+"t~e}W,bqΉ#t+Y#t~q椋:'Э \0(BGE< է5(ï/~z VT/d . m:iAvl\Bq`#u80\qy8auoث,]/o/WvX"Ia`-w@vGK7[׶-'%<4??HKsIۖFwDÝ%6N=gOO:\f_>,?| w+X=̟ ғbwH&+dG}-qs+:L^A,^d+Gi.z!DO7 QTpuaN/W'N.7CB`bw)m`֦CW&JZYEeip洡9B Mm$M#{p(/"ȢZ:QpduԁGeQǬI8::bU =.w#9db5r4B#jjxW0# ; ;~Hύ n^{`"PǪ@Ei rC4pkӈ Q^(JҊnȊ5 Vz",ǫipFTD2D  H ̚nDϊztNu*[xi}Y|a-ʅg XƔ(!XGh`3r̷܀ظ76 F FO*B5 ,x6`hlAlso IھY [߿';6Z3ϱz 3Z9Nvlyc`NO}l;(d?A3r:t#8a_#g6 oI2ǾYQUb?B3eyat$#򓁴oi WW^Q3OX""-ȩ>BaMƁjhXWdjE 9Finv#hDc[@VF atd:Yr#&ՔkH"ZdH xF_@$r tdG7! .+eXAVh 5XGh`F,.|oHG6Sg͋6{ZwfD/sB>uO`B?OF[2wZc~V84\9 ..<|n>sB8{-VwM&Taeel;]SS m h%K6hyhsX_yH 2v>g6^ϸa˜)E 5㺈'"T|о.B,tQ ũZl\]:@0j/,WFbLL2xW;tZp,0]&ʤG_P1[\b9&U;0"!Z:΢͉(1 'Ng;[Nz燮w,MMG﵈2æ'˅"˕#Ց~^,RiF^zSx;$^wr'X8^.ٽݨ˝N~8{-^.jLn䡺Hjd77:?BAGy-T0 1*3d 0 `/ ktb}tSL#i/D2rZr%*npH ܨ ,8!;khNVoƿTPӘ%,JFpGN 0;F=;"q$ QsC0rҒ pʺL5k)%;_`B@RH~d€ \aO^cv5HQmP̸$ap$F` S$Z!Z2r wz]%8PB"̥z&O6o;Zr,>>=O(rJUjLCQ 'M>B,9Yf7IJbpE F%X`7%_j )r%Gā7+'E&3htfUS"d氵2 +̂1iPA ځʼnf`0T9iƎFDcYcuGYT'#kF"Xr5P+UjA2,܂ j(\Kc)$E66@J㾬0gH,-hB{+ͱ͸l+g+&6p܁Pf=pcNDנf[i4Bqy۝FW@5a/-v$ d.0WiUȄjybZXe UhSՃZ3MRNJFe\#h>#Ac ݴ%((QF&)a[}!y:٬씷ú襭dq֜Xre'wM 1PLnD[((V =dSKvE Xӕdؕ]S i68;+A_~-;NXZwnT@G&+~!Up.ZlTh޳ {ԼPڰ@ < M! K,z ;x |.YXYRFA) @gDAP) @ #<:alD-  @I QB1M? LL! *RXv$H$qg6)Bؔ1~ǣتc4-U TS _% 0Ӕ 'z5[ x_s^ؿ; Xi T֘[U;GA+PAR%ƜQ XFBPckmCDP@Ƙ7_@P!j yc5,Z `֙ 2cȆTQҡ1vrH95U:.14'C)0cckS-"i` T hQj+D-jVkvVgͶp7Ϣtk,&cqq%(X,4~D蟉r3nm׈?S2n%2{D/UY*LѸQkp8!?V@Z[F!3QVX,P@e24"BbIGQDrdm _-9|A51obOy/a ےrl_Lp-K:U,Rq7q\@:K\9B 2=!LUdHnXbB~d%M݂}KlxhJZOFbpY[؆kjLl-Q#*GVWjWTê  ⊢8bAv2kx>Ǿ: úRF*VqXE*wX#fIy{(⡉ a'u -aaï{W l1'u -aa˯{vXGA랬GAlUӖ_d㟍=g@luO68sYh P^J2z$ XG1Eʆ @APW[ q%lb N5 /gdbuyeË 3$fõw' ϡc^CK]0I Kv%2ٿ.‡Kb x4 W(X 0u32]PAa0 p I.:1yoP~ " *ƤV4?Y0Ĥa;3ρg@65,k.#g;H9Ip8lX?`_ C:W!0XLUg*Lۂq9Q\s0.cEzj'Fd85sR |Uh\2F!X)L׫XHC:\Bץ21Crq2%>r_bC1Ƶȵg 5wk!U n K.IX8\vҘ)5`)pm S}U-XwPuGA3A( ~e0+js7J+e$qeW (5tNVu0`Qq`8c8 P)ٍeAX/gSg; d YvD}ZD ?]0KXQ)S!"D:Xgϳ87Ye0UaIq!θxD\`9[CV ᮬim%J yNp̵ $#";YbT1ef$ Jna~B#K=7یe Fs4ݭ㏖Ϸ^__=l2X Ta=+8|ր"62ؤq{Q+V2\$^e^ _zu b:+B_P)&it-4_Z8lampZ?ol(C&㎜dlRm*9Z`#H>8)+b >lǣ«Ip6 |W LDvǭqFbL34q7?Cq4?{ܳAө琺ko&o'ᘇm8ed4#YpQ Aw׉V|g`J!1YN0e8dwmބT q6Eض/{H~s̩F(Ċ/;ǰPuie !hhv!pf8UUu#llR8vZ F1߸.j]8T) lýc8YYj9jln囹kv6nH'8`]#Ă'LU[{r{8lݾ@w '-% sC}+wv׮Wj|SL1,x1HvlXdɘc8Hy_EĂ'sI/=+kX4ЫCޮWÂ[n J{r+duuUtu*Igܤ>?`\\-8oca˭@S79I|[]sdr]TWJ8 tpqx:e–+^Ű.n/W₼ŦѥNN # CeخoXqhan} ~gX,L|Xh3Amfȹ98M>Tl@lnJNx!$GJyov7.Ѷ"U +*gV V+xٔȰ5.9#boR`/AʰA_$`p{Β9̞)4(/4TA$^& m$  ֙Ȱ.#b$^& m$C_{Al3,|̷ӜNkI帱Ѧ&Q2f{ 7#PNs 7>T]zq9n)k(TiAw ƫt@~<%MBH*:CfRfۂ̶!e6(&,G_V2UA'4ScRĉ :| 4<7qL1aHu3!QX5zT)|N}x k`PBt^c>2!koF'}ǀ"dBYwk6Q _AF\7D힙; )05.LMT=FI}mAle߸)Mn7Q>8Ȏ) n7QT0lr&03tFNVR,i)ĖͲ́ԝ\)Sܝ&Vӳ\PtMB S)SvJ/o/R!&{;TaZ OBA6OVعQ}J:A}8A^vJQ:ۤCi*(urwW6qkb'jp֖Q>cG,B{ZҭX7pճ됉~"Kg;S]x;6OXA*_%DC)DZ+Ո#|p9Ak͈~+Tt=D٪qfW*lJDn38`*N !W㖥2RI .~"Q$R@#kM:6;(:EJl&`f;(dM' 艘ڌ鉍\>yt)~_g+\Jl .#Wxb¤ֽ7}t+9mB,:OW0ؑyePeQ\bN( 1)!b"hhRB 4,Zy4*- k /e=~R%3@Jh( D `RRvUul|ീwW Gwrs)dH/&jU8)A+ ݖZa0f,6os&f<+ IA)LلtF),XÈtMNx\308 g$AOVMh]_k-\NNP%s((QDzHw-;| 6 S;AC%j+Pڭx\Yޙ6Y8ͅQ*X\'FilOGa]2.ü!OWDO^ǮeG"܌sƢt!Pl' lv(e!/s(ݳDtVs[#j爡92Uhb Jו5w&VM@X>s Y{C2e;Mx6j?F{Ama2LnR>mAZAV%h]@kиlA׵L< {kkiVO'AfۈZЬ=AU[(9ij5ܿhzFh4\*s oly,=lI{q0s7dɰꗉc@QAYHK_E$Œ`Q|oOvϟ_ֶP?;߃P-'܃1PAts!ߔplQ7À^tɟy{eeRiP1R> /.Zu;CT ŷ"^v}`M'K[VWps"B[ᖷr\U}VZw6Fx2b&B* Ҋ_U zHHHɳYcI+!{)Gz 86(,/xw-*V Y $Ryx݀*(J` '*89NTё|r6ld\%IƾÖh 9*@KЀ\:$51I`AMwn+;וd X1'tZS3iJkJQ:)K)c34%5FNu0Y/;6PKC2kej9 Wp&=(]Mޥ 7@|pQv =s B;m`c(y]P/$p⦠3?eszBpk[p9T=l;zq'v*J0vt ePO( uPOH[{6&oֳP&KCPO*ۈUU}-l zB0ʫqI"S儲^&tLv6WOPJj"];&x5A-W))'LDrPv_۔Ϡnl=;g)Hi' Ofx_ h^hYO~9<ݪh gDyzւI`'Z I&4zYh=$A= ePMȂrB1PN8TO(OzB;`•'k_OH X<,-DZ^>,MH7yiIu-'w%c 'XStdiPҦ"@ҁzZV=!H=!'1zAfZ6Y<MQ'Z Jw WOʯ[P8gA݂B}Z܀i@hPB>TP4P۝kw,"T7\vV ng\SSPŅP6V"-.q > _6mbi̧n>mt_]5ҤP?i|-OkAna?P,((⽂B{\ M8jϒ$ ޟ>Bؑ]ٟ9$Gˇ>>;g+ n=#lODuWB~eOܤ)  cN_J!Qw;(a `̟J)&"Hqgv٠ YP6h|٠US5(|ՠW sE4D$LYxgts sh̏L$ReIbE _4kH͠ jTA͠ijdWEݹlj>棚v fٙjP0?,Q#[yigTޑE#e5.1LV ;+IgcAH[GE7%D&OM`]48$(s5.VQreW$^4ؚ,g+ldB@\5X2(;jr_K{7\bH0v+ U%*^g޼}qOs+S@}TeRA]o J{ć[*8:P3L0B Du­(:\l0J)nh%,\^vh.܋!:|H_'R~%ثHU<iVzTYE+qX;wJ*kX{EByvSHBKV*UpR-"ŴHQ;u`{T&TUhF؄D= pp8k$&0/ È) W# ¶VuXO\$)8kOj%֩drdyt[w[řNB怬a8<æZY%iF䏪B𱌩QtM2 #7͸n 'j1%/&X!o d___jLRc LvTux)k;VH)= n=S .W` L R8'lhrF?аlPCf24pl8>ٚVT@Kq6"XS *i2϶C "Ïs "-JJ_5KB$f!aڱLRd֣J7ppŚ8 d@ 'G; QSn܅hIu~TR& |`Pv Z-&+j2F#/dZAm%,- )ƹoҜ P~$ ع85+HdxE1XkTcSATcBLߪ c !F:œœpVZJ\e; ʮB![, ߭/WG쳸0H#f+'^Ku{RIy"ݤ')CMs 5C:[3t.S3^\1a& 'dٚOT1d8eC:|Re C7sH$ s& ʍ,(& 4ihbݤ!zT' 1i9C:+ ж3[ Vΐ9C(!g)C KL7eH}x)Cd ֣! 9Cy9CGAr( jimRsL5ȏ:!a( ۅ00n_'#Qح\tİncW0'I0<Ó;grGi݀(P`F9Q(3k ➽&i׹0[&h\p9Ah3Z-4a_4p<4v 3[&dL6?xڌk 6odOu9=ҩn -ң @5ZNw7t-qDu㧕k66k[8qj#Dդt7cu pðZqcw_I%嗫yYf[j8I'QLדʾ5rnu&X/3Dž#W a濣qt/r#2F9dӞN' e6& Sr+I3d h$/$ FFjǑ8Bd!I`5uic4XqS@VbpTaDτq)Q)h$7|IFc.6 $GM< _ŦÛ=| LL7NtBK,]l ^ @8t3t!h܀$` ȕ yR5Ә\^o7/Y6 p #.`jԫk3 `m@k$᯽XE[ CZ D/fb #W@ZLF,fL XJDL[l "bYAD,dDb6-Du&o6:bV-8r $DĞΣŬ[lpJxt2"1+G]abRѫXUg4̢]\=tsSK#]\uR7C43?z10ܢyGx ķQczv͢D5ҘI:AUj"t*e~dS2 ͋*E2H#q'p $[@opu9kɦGM&ڟ(ȳQnT^Zfx*8וRfJ5t44ZpsO%w#AGa^*2.{ ip%w3w$U(NRp22 + TCvmFv띉!%gknijnբz6Q֦Xsڞ3Qp5XZpaKl|5yf8N#Ɉh[[htD{mIT`guT9uE%|l3ܨZW,]fQ]ht!*~":(x v{p;OaPpou j+Y(%gxe9㏊!9Nú0DXWY27+AB !4!FCBgk[<()[(U,˒3P%ֿBS*dXSC$OU5WU66Q pk E*$a4*(d;D qK6Vp dΰ Ӣ ʸ'6<1m^}~ &w&Q*_5NEJ9rVK91_x=.$s 2+w YDPMθ*=g50~1!ݵEU,s>ڐlRwK1&y[T6*Di r`gJp#Bt.<瀔@RեgCʘi\y*#Vw.M; #U<@#܄st"P4o؝byn;ZF,Zuw"!ǕC@@LZZ$ ueԝhi P0s YɉC2m"oh u[ҔfM!hRusFHqc *b8rU(Ap, |`8׀5DpՓvJܺ*7YG(?l5ܿ0Gu+єR9ի7B`8O~`&ԟJGVnRc[^Zk*ir#ٵwèɂ @*ƾNaa%üF6OMHu!' @r0}0rSHO-S=bm%3AQ/KPCL MxiE~]hUX^Aŷ"^v}`M¸A}d|.w.Bh+"QRh^ЂQpKBh;9_RFK$J`oX6_U {HJH3c+!v!- "Cz'Q>KEDG.6T ?7^M'aR ȁ(ڃ *ރ#Z?g-4ܝqX .})ޭ6,*4rF+YH1!\"={Qg$e+N4Tr!ۿ$v{QUTJVr*Jfm1*ќ@$ݷg*% D !JQd1 D}kOWlT8>ze@x\-lZ8YS#<>om$S+3+^Z`159{Τ|4J=$SRW ~S`UhW Hzt7b DѪ@wQ8E^:>++elc{ͩ^8>n̏ުQEez)ܤ)@$ ׫X~"=o 7?P;?4IN;{&QuoNW cJ@> iLATQjչk ?.Aco\ⱼGu!jcV݌sJ[YmQ)b5imJ'R|1+F<[9W_H|t(GlM{V(rDyiWt#n^ػ, o( j5혊vPw[X[\_Z2iOs!Ү\Rb`eC 6;S} ܴ&,Z_q('YZ@g)^!R(^rL.1Twq/QZ'!^|qXYq%.!uٷGk%)1K*^4E7qob5řbybQdQ#WCc`[" 1W<_b!8ȕ+լgzp=W@2;E_;bPYPxMVFp \Y6Qpa)mH *$Z`iy5 #%pI |oW |K -ķSl8 D A/\qW & fNj"$Pn!ZT&U BɈ(;DWvL3 "XjJF ̖.Az@h(B9bv۶3XƥnR*0DPOBMay! FK/AtLlrPnfة%ʝ9?ZY2r wּ!0M{4x4Hڠ8TdII|5mK \NXil%^Eg* 25R4Bgsz;`=)N#WV'jhk=t{NBseoJ[P6dHW/~Wn~%$6W,`Ŕ>]lUi'E'(N#@`Ob ?@胯KeYiެ<I7y o:ւ,r0uf92w1VManMv&) S1`A-qUHޤ>qf rB2ZȐY)ll%EWݸ1: 6?SH8c&=X{jn@*0#[y6: ͦo Menɳ֭ڟG?2̢<Ã6sTժZN.ϰXze`pf^) x7@x}Ҁ;@]-XqT^apJDee#o 8:rDF"m!;ۓ˿:iU_`GY:ث,q]{q)yl;FL&uBT u-X,Ą>:7 .>ۉ*_Ta% {Ra5tXj9<mhi+tDydyOtnf{>?ąm=4v[}ѷxsۣ2#H' ܟ8>U:4}?;G`_ܓBXfhlO!OIE8Ǟ UT&Sfe=AejU*ɊO"l)f\2[}ƣb h1$1 6=l{k Z41eI `Iܙ7,8 a]WD92+: )R!|Al&09!pA@s5re޵=~UH$?C!8@pQ+C`ΐc|C\S1Gѡ+tnBnR2JK⃈Z t!_2l˄TDlF+n"nr 9GBƙ?1M6dt`N&Vr Ɔ; h$v7p#S8R?SƦ x3á ,1ߙMlr3OyؽV)>1oSrnG[1=U{SV637WW54uЊE K|ZrܬLҭإ[@ۂ$jbvg&־57>M-.,H`FZ *=R 9$W17z2x=*6*ٷ񐜠j||X Ʌ'W,o!drsūJ7[Ϟ5NsiJ,!|5Q•sWƯoi||ҜS#'͵ W`wC4[ ^ErX{Va< r~䶼ײ^jE|o hvP;27yO.tdX;JIt0ծC*eZd- wNlSJ~|{z ~XC|+4I<.jmæ"69MAS@GϦ{n3nbp밙c;.W.)ETj 5 yLs7}Goon vkH7Edl` 76BGK+uמ3z!IhӢЎ$%[_s= ZybJ,&LkZ0pF|:_t+3_m$//䍯WpjPA|{^4_2_n&7yR6suFteO|S`+-#xB||$xZ2$Ukۙ kl4"C 4sv#W%QX}N(nc.KԗM{ju]ԗ/b@$lR0fã(tvײމ6ģ4 S!0F#nl#ҊBnUwD,"-(/4P> .VMVW/ d yR-ٴuZnR@lTjR+6⳹^9/N ?L|o߯7V^97Ӥ?脅6 tAJވ|oegaa?B|FDt?=?|*KNJ4;pAB?_.  |B} o@+/VהӛLTympT|^eU6%fAOƧG[ך .d:2u? 2AKrXG(-sـ:!Ɔ()6*` +!~o8]|,:|Rp!ii[Fsت*OܩU< (v)!KH8x0qj^jUkXLyI/N%~õ1ռ`_ -[8dQdi["ѭR݉!]mCU:)v:w[mLZ%a-}ӄ?3GƤL l+tr5&^P 7ba?M~rP9 K2Ĭ@R ;@tz8f+ rx8@-u _=KKDe:eeB0IºT܅[<زRunjV,I݅%vbV4n`!@t-UVwD ~-wF5OrqUD:nսBsX;\`Y僩OgGReY僩x ]r?gX>x~J-w"@6U[:U/NԖ*lݲ!` [Q/+j`yuu+S` b`)$ CU. -RtKJ4/ưJ|+T -ªL±)U^//uzV沣.C̊-L^= P%=N5-Y@z -"t 1J5fqc# [(Du/4; |3v bV,n$unBd ݒUUTiV6Н)X@[d L(ԋPN4 -T܅kXy>+hx0uqnP{* -UT^.,?p-@[i@WbDQ[ HSlm,NԾ9\]\^--(ˋ syeފ/[ZJT7gL+9y{|wq*Y7ɘ"<&ј_W27#6rw _dC ^~aŰ{ͶkT=V:z%~V2!ļ17cJ,ǔhݘ˰j;ѹz6CөW{52:[U,|_/؉%>5( J6>{}ݴ+*_!f7]/Ѹ+}d*y?8CP}]Na{s灻4 R>1 kumBB߳gǔ=kN[}NzW'1[ 87Wگ+_kP<ʝ" lay7˾4OiPAP&m'6 D7Mrz4& krg;pX(MYQci*\l)MưCӰiV^~re1+b֖$]:Odǜ5 2JF8Ĉ<|p,` ܹ(KCzmPCTD#Z=T+2 jp,I(˕2AY D"/UB2Iuyp^ʿ%I!\j/F9e13Z hXN쩱wb,eYU6!NLEd/ ^滛5!nܘ $915:F&1\688"ـHnAПitbrԓ0T)*qNs/CaEJ 6gZdmM«"^-%!Eo7|\Sq%F[ h,B.'9f#WƬ 1xL xTǀH+2({72~\2ݥIÌit#9 0;;RlMj!T ȉMITUyB&c 4xjPJ3+V U.iAtXY -2=}H\c>NBG%%Q=½f٘;xxd+ĩ$<9E"YB|@`%*+LQyʪ+dQ1=[&Kt=6~!gKF3=c` 0STl2C;Xg8*v13[rw-qJ\Im2JZp_-d[)콼z,ypL@I+7|b>\.١nm2-XPKuu E$ޫ>Ȕy"תY) Yh\ %!T<e"u$djb}A7*\1 AY-swc+Cʺi[B$nE9{<zjLf(Y ҿ ,J&FL,xiH<T0_Xvl%0*a*n2vѥa `ĺL̅niPgd ԟ=Ԩo& I! T,J(:@QRLJX paa^X1%R\,ڍ|ӔZy<5;٢B䗦 X{tpaԡŝJhE#,FBǢ,8RRĽ7^ yvieʺ7(!ӽ#\9FtRVV6NG$ľ u5y7b ҭݺFٸ&as1;e|0P /d^ul0p (8?q*3_298Pk G1Uh޲D^ [$5k i=x?3@4Vj|>`Urߞ~aOמaaа0h"g J Ӑ,6mm )B)ϵɼ얠ޫEj0i(IDZ, 6a&Ӵɿ[*ɵ쓡kXAasdvL 1XF)bp'o2\}Uvg9Ӈ{l7M/i}I>M6npB`Bd#݅ +Ο)O=xy#I ˰Sh@lu8~ў g{mYo e@Z,؏j e#*lF=ZHi{nO"kabY $QjmA (OvWDRRT!磍YƙZM~D6j%Kŵ/'EBA샲β~q>1 X< 60B ;mPHAAuY0:h+yQFhOd`#FNN(؎/Y&kt>ؘ2y0ߑN푶Zs΅O;tCڵ8xDp)>`jvQ_'q&ylKvct9x>.5a⤼%XYuD|Bm)pgݘx; kFίIZhK Ӿ}#{mZ(5^s~3/ۥ"K$,S[p:.:~9KT@^GQ*4a (35(bnp-RRN9O@kTX(p3>um]lstLf54UqŠt1A6`SLc5sN2à}R=6_IJ݇hY+ DvyKsx&YY 4͵葲ͧOcOFOQ mQ 6vgXfz@t2(pyP![s.KP"ml* Y:D]Jo;vHKcQ6.uj YD]aRf~:C3ܫN,{ S[ujAr/4.Y#sK9ͺjcczb@Ui U:w ZP Zu(_2qc SbcaLvtH)4* G񵜶 .M:C|ȍ']hރz_$:؈>Dv}Kq 6o1S#8q7gnOzuyq3:z\۫˫?W\w?@agfRTܔ\?XvT/s5v7__PKxEC$p~svg.breadboard.dc_motor_leg.svgXn#}~E0/TK`{:6;*ȣGVB!)>HMR}TH/b_m7QA̷r~}-eQ|zqa8SGO7o Q~FPoSn9ywXGoGb,.H ƋW|b^:|Xm]z/P0tR á"AkoI c_^sb7(&ѫ~X~@-\ח1ZM̷ ;Hk:"#diU*3V4P _ Kce&L"Li"94^j#m#~:FʼK UW" 92CΠ@ wbSVxVIƆ9 Ic eX#BZA1%V&cųyPs FȈ2ohk'[) 0s(m+pJ̓YɠrWJ23B!"BNpw4t\T6VyeIpY״=k*Z`BYkE3=[ aİI;;ԥL %Ct!GRpIm lqD<FԿSG4੬.Y)$}+m&mi*.O U"J>Zɷ:&wŴI7XRֳ{zkcJUnR~Zx%Э5@4^L2A9 !a,l^@҅T=.NC[[riRQM&]m84A,(_ۑPp^(Do,3B!z2Rř E%34"\3ڥNZqvӯA9FEY ^"TjL"XMEidIKI詶qr5\u-MDqS}PkǨhHPtRȭ}j],,ȸjX+IsDJsVFܐDioS~5UBHvB&j ! ! C(`=N\)|SD&tvȞFDQ:Q9.&pPCu+!d;!L!2V61ɰ.iwL;,6%hu MuqP)O)E\8f&v-WCM\cj ={rė |F%sdͦ EU>95"7ɡCTJv^vO z ћn?DxÅ5b6hTkK4p+M{G/R[<^T1m!EoduR:nGg> kVƒQTYT,>޺OڋJ1>a]S*vپ߲E f^mye,NL^,;V%'zҼ[`9? 5"W;O}LnPtpGg4{,Y"XΔұ"`/5K cEYz9auR%HcsHWFYԈʗg41unPKxE%%k.r%svg.breadboard.Half_breadboard56a.svgݒFze557L (Gvf;$Hdhugo_ϯ߾o={v_||7勿O?믾_o޴x_ճg~7WWWu~z?_~lw}?!|yױƛi9}?~OTMu>7û??G}߼z~廷Qg߿xwy~o^nӘ7Ô< W߿{-޿~o!g<Y~)!Oϯ 7 )Я{?~^"?_ۿVAI7urvMw/0O)Ƴ+W~~~xr1&p02Mir]!z~]˗/E|6:c;1m};xO_p3eWa/?ϫ,\-E~F_V^b(/k"_k|ϯo:yym{ߞS?q0ۿ:~6kd?^\2{\_ 5q6sģb..q$ vpqOkCsOE)6L+7'k܇bēb..q&B?Opŷ^^,vqgP/aVh+\ŷY|+]<% zZ\^7Yl/)1@WozC{5| G*tqЫO`⛆ bCPc1BE Q!bE tԎ8j>@-ax*KR+vDS# mO wAEbQ jGOL5DojOQjŮ(jP'AmA5>赮Va_ ළ5Ӈ6J5LPYwAUUxpZ ZkN5p֠ O[+֐6D\<ms յRu 3tƝkP'-AU.Gi`{ 3qڡ\%?A/'vH_UIU՟>襾vD_ ׎*A z׎k#}UU(AoWU}P_;z%56׆k6D_jCm} .q˔܉FUU]k5;רzP}[_*A}K}m܁Ff;רJP}[_j@}K}m܁kN5 pר P1׃G5tt‘(lT=~?P8AFՅRU_jl46&?ب*Q[ejE}KU'*U3JolT~?8CFՏRU ~ ?Q GJRߠ"a/'Z[6HkUE Vu>6Dm TH!{ުԇƞmz#U%)doP\Ւ=QQդ措(uaN3v3w| VU__jnO> vð3 U~?1B措:5wT~?1B措A5wT%~?qUJokTRs~5';Qը>6@s5'; Qu>6@s5';Q>6@sjncO4wT)djO}Kmf=\UBU YjnJ\s39\UOe܎hn#U)o\UͭPs;~B ZTRs;~jnO4wR-*ſ*R}KN܎hzT[s'դ͝FhZT[s'U͝h*T~[s'ա͝"ƞhS~[s'U͝F=IN=a/5;MPs{N!m͝Ty>K͝'57\s'Uҟ͝T_jn4wJPs;~O)m͝T_jnO3܎UJ[3OYjnO;3܎ijQ)~"܎hn#U=*o\դ-Ps}E jTRs{jnc4WUAsU^jncO4Bmܤ TRs{iM<57ԇhn Ps{IU&U/Rs57eUknR*<ܤSRs;~)Rͭ\sO)mMB/5?ܤ*T[sjQ}K&d|TJF}T_jnOV}?Q=*ſI5>6@s2'T oknR5{=ܤ &UBۚT^jnc47E({IAsU^jncO4W C#U)do\՞UPHsUu 4W.i_j'j ~);4WKڣ?/5',7hP}Kj6ʂh*T[sgբ͝t?YΪH/5;( ~Q)~ÄjR}KmɆZ2G#E KFa/5; ){P!m͝U^jnc4wV3RDsg՟Bۚ;Շh Ϊ<5wV{=YI͝Uu okSa[YJѯ{Uuṳ*PKj\ŸT[tgU:U StUJLWNvDu̔?R]դRUe麝?q]5e\WuU_nOdWM#U]*o]U:jqnVM*mYUN6@w2'U onVE| >ݬ fբB۾U_ o7*|"YfURx0`jj fY5 Y5NjʄoVe*¿YNjʄoV}*¿mYNjʄnV*¿-YUNjʄnV*¿YUNv@vZ'UJonVu{=q]5EeadWtU^ngOTWMQY#UE*ao]U:USTHuUJܢjT[sP_J5)* {EuU:jnQSTDs*P m-=ubAs+ܢ,՞ۚ[TuVEMQY-;%5ԇ57EmQU: ܎h2G Tߠ?u¯5'L7hPk9*~FE ZT'Zs;~jʄi*RmͭFu¯5[>ܪjT[sPkmV5EeaO4ܪ T'Zs{UMQYͭ@%5ԉhnUSTDsjO mͭ:ub5[=ܪS~[sjN}OZscƚ[*q[U{NOk_82nUSt{tZ2%@L&-UN h ٭jʔݪTVե:%}'|]*SwSi[UꔀVޞPުL 孪T WN hm UTV7jUkmq* ~$U ZU'}~jʂjU!~V ߆诚GZU`Uu¯ o' \;5x̓yp<؃"(m^dB/wM@8 {!l+r's⤝xk*="e? aۊàZX/7Me@x lr'3͸%8 jʒQ*܍&eL妩/Wz0m=ja~~4*ܐ&meLVRd5qeI)jaaEV=OV)PdtA {YULe"6)=jSdU,:Y""+SLU-KC(jfBЊC@L! E!9v)=A`B@T;KC0(rPSZ[DZ²d9nF`P䠺Y""5eI)rP,LAN hEn Ej˒RZYAjeЊ 0%AU0"U:%%@9y,KH*daEI kENWVV#T%A;9R)=AeB@T+KC0(rPSZ{D29b`P䠪Y""5e )fiEVSZ{Hz)Ȫ!XYճN!hEn! EV Z "nF`Qd:%%YmhY`YEU1딀VRd5eI)jeaEuJ@+rK(rTkZ"GU U%딀VQ&, E 9F'y"G5AݡQUEu A+r(rT["G U/VQfL! E!9j)=QmB@U7KC0(rTSZ{D29v`PY""Ge)rT,QuN hEn Ejz˒R䨊YA*fЊ %Q0"V)-j˒SdU,*Y""1.KLU! (jd}Zsܡjk5\(d3i"R)=jSd,zY""jRQ4"u A+r(򨆺L! EU7KC0(Y""jRQ4"u A+r (6, EU7 #0(Y""j˒RQ0"uJ@+rK(ƻ, EU+ 0(ZY""j˒RQU0"uJ@+rK(򨆼, EU! 0(YȣZ LZC<CgUɮg $q抜XjcܡYUU)VQL! EΪ!9^)=Y텙B@U1KC0(rVլSZ{D 39n`PY""gf )rV, YճN!hEn!Ej.̒R䬺YAfЊ V%Y0"gU:%%@90KHjeaEΪuJ@+rK(rV[a"gU U%딀VRdfI)*daEVOV1Pd5(d3EVSZ{H^)Ȫ!XYN!hE! EV{a"b`QdU:Y텙B@\T7KC0(rQSZ{D 3v`PY""5f)rQ,EuN hEn E.j+̒R䢊YA*fЊ \V%E0":%%@0KHdaE.uJ@+rK(rQ[a"U \T#@֊2N^\dy~X;wȔž/2ML~<;yr'ɣ=% {:bD^gzz wtoc?buɄ] ;8\S{kPU}xOG,YxO.,Î=ၥNxOG,+㽓G;UWG)tJ#WϞmG (a';OS{kPUp1da>O;w:4=;LjQ#Lɣ%uxCI[#&L~zxtz wOryd"/3ӽ#O㵣'~+G&xoޯ~݃}GYA5}FuqxѨ}yX)#zyw䀟QG/Go8#6l zy`tz x<`tos?b];8g6[]Ǯ~נz?b=#> Î3!9ZQh0ͧCE6?G<*:g<^*:o9)їݳOC}{ {Pto?bȆ^=9.Q'k੽o8X#2q㸧cDa=# q 8 щ>; }q㞮=='C6{9ɣOo82qן} aLJf5O?xl*|3dP3:g=:o8C6CPN =}COSiTGL:yrg,tq2q/ˇq. i/ /LNq}qĈ>G|Bw>aΟmGL~ogɣo8X 2q/χiǂޟG~}3A';Ag-A6[.==^: dC I2P'{< t?b]LҎ3] iOާG>x>5}v93% }}'V};@w>agΟmG>73q7GL}#? ] sqڿz刭}}w/tDO7刑}}ܟ}N==ڳ'>6oq_O'Ow}>>&T!0U>!4U>!S#|lqw|1}v53!}}gBw|}?OsU=9~O'{ 9g=9o9X}sxF> >+~qNx>xq$ ^w_"޻/Gl_8ww_ϰx}9bFq߻xg}3<z1cCW<3+_{ #Î+ {޻|w';6zwd}œ;a{oܧo8S #FGvw_U[ m'AG}mWU{Րp$1!ji|{{Փo|ܫԇ>Î!LqR;}qR|&ۣc={ѫ>$jB(57!u?f㎏YU5ִJ~1z cVUu>qw|̪&}vܫNrܫԇ>#UUMGWm)x JkǬ:zrܫ& ytܫ pܫԅ~>N;޻jiwvB/Wx*ݟ~i{eN OegW3NGWm)xѫ>'rTj'}TQjy/S ~>&rhӎ`M4ԇ>~iji{e&r2[ݳY'ۣOثq?[R;`{˯DB;II*cd VڌVM+<ӎzDjD+ӷ(M{br쵙lzRt$5d!OR3>ԅU,cV)UeǬRP=:>f\ቜv:'}PO&+7A>q_Ǭ{b{z {Ֆ'߀vq,qR3xqR%RSM8//> _> _/ۿ%Syg_Ӵ\'sc;~?|?Ë_ݛWWcᛯno~#nAypv=dnwGtv˞۝z;tG}]gt l= lft~´B=Ivo4m=AXq>A췻AGʽ_b^?qw췻A_a+:EݏZ? /?ow7pW{h"7G{W{#Eݍ6v^ӑhA_d~}]GEݏzۋ_}__|ՇPKxEu56J#svg.breadboard.mosfet_n_channel.svgW[6~~yuvVìT]OBT `_eS"%c5jaTTzQV9qkYٮc[(#v_`͗p8Ѓv9!]$^Fm^0zMr_MsWVgUw!NԔa\CP0Dbl\϶ 8{}Uve(jƃg#\U鑸S:oѸ*? 'Z8쿂uYu!Eo甅0E;{ϩp<"l~%[HM~ݏ?5MJOՓ}# i\QaRg5Tdjg OIRZ0 $8ʜݭ;i $o1-jOT9TK¨HU h&'Tyi2k)? h>f:P-q':EN:{МoO#}_7uYW4ټ+OѦ.JQErF Gw$# %cf"IR}"/"q\ІgThвԪbC),\.M+% 24qsk:JI8wHšb[vH5+;aD8גNIm a?c2p.k}i yĺ z#&ND!2`(O,L1eNK5sAST:ˏ! .<@E }kBl1y)@CeA_ns"O}7>kcN< lri5։GۗՀ*ަ3 DoQA%vǬcȲYhO#Ղӄ*qA1KqGsJr`eUR:̱O)s/H_ޑ/\JCZf /<X3KX@e\=,H'>Na\VkOr-Q󤀜I+7f+ T(.uU&/ULHn2$I>4qxM@ϽsW_oVWG3ݪY\\.ώfw6q_{-/۫oW_[ Vo>f緷/󇇇Wjq3sYLt[@O=VG_ˬb#\޼0)˛r݋rRJ=򷱅xKfoauz{~43$?Η򋷾_-^_' qɗedu\>T,KH4^/o vX-.׋Wuu! Ee_^ زj<~Xme߬ZZd߳5|kbUkV`-z4[OqP>A(N񇃺qؒqjuaԵ)A8m=4 txg%)j~=RߙAS*33Df&TtTqKەSD渀U@'_R'jh`w)&mrGU6'8Q`&dew*8Ql*\laiOq2c%Ӆ5{Z`(:xf0qOYQ)˄A{:Ng"j!s}`"ب jHؚP`YjD,VU"9 'OyQ(V5RLכFi慕_,5^h,5=/:杬u5{Po;g"0K;z"9P~|gfSe|F^\6QT3ywru1pٸڦkZy1NÅ]_m ;Mb̈u/1ԗd~1iŌ=N{ np}_^ @ ;KANԖ6ؗJ{%*-m:,O 8L>zI 8y yJuN.T8@^™Kܔ<+;c@&Ĭ!Po;S֩^j&jAHސ nXCVېzysULKaT,z!o(|F" X;D5bҞ5QfWj:6 %HOkrKseQ!ڟ<;qpΟ~͐?q~ǔ7q .IzLC緖ÈI{iƏM&LR|k64hh@{]Z>;۵|&GKpN޿~$wqMY93CPA>:usCPauQA[g]nv>CzMs>|܋1Hf(݇ڜFL riDwWkFL9yLOTrTCn (M 0[psύdPc7l,G Rn(q!-D! '3s5[۲բL!dQNW}#|މh@aUʉȧ*ckeb\Jqw%NBg/ ^ȶ+ʉ!#dѡabg;}4e'OM.%!t4 +m>sPϖ]9YSFqBE> IL`ݹiD( cm9J@zA6ȠٔحPyhDpAVؐMd5Tq\9Hsi[5$6f# m")˂+(*b /JиgAI0uVKD3 m#ZR 3 CXfO3M{ xN6<$sCGupE4P(C[0:+rjd'Aj-iڒ|~+6ruΰ~j^\˽o-*cJ -9b2Q!&!.%\Z` }̽ l(wC#ctVSGh+EB:1:Td@|.$S(r0".ngF<\*H` #@낕SL7eG2:fT{K"FG#K|a!@MH @(&:ws0`.kPBy,ͽ7Bɠ L$,gw,.-)K܅1:[XH݀e0f` 3DNa[خ=J}/Yz dZr``]ad}OݹD757:Pf#b|,SO}_PKxE} svg.icon.Battery_block_9V82.svgY[S~_1Q^U3ҹ_\X\\ ߬֯?_>ΚwWW_n6h7Vc66'׫y{lƸy&2^5aTqSt8ѯz^6/Q7M&ǿof4l_M&www;;^/'ofB '^3`Εz,.GtwԐ7p5JvɫOiH]ߏnqr.fwoVJk?ǫY|zeIj.gwMyus}>׳v&^¤to{t;>̛OϨUM!zCvU9[5. E1I3*=l)U* F_%"(q;#n8t&R$$:om\K0cP"S(/4e0'4EX[磠 FdD Ym-BЎ}R^ 5-yc ^P"U B Y359Lbs*mCc^_ڽđ'29v(,6{) 7QB) 5b[˧-/ kX.=J%@[{KkN"J"p/''OHe@=J02R[ p \a)`.bg[c/E{ RsEr#40 FWy(hJd7Z0u ZgQ TzJ) GTcR>%Z ,I9<Jj>;.vp X.䒼2 RRO!u[!5vf%}Ђk_ T}`-ӮkY@I@0}f`4#d%g-笫JeQHQ[J-,V$;kF0r&.QC>ʶ@6r̶IE|֑[f6#GSPvꊄ#-,-p_0+mAJ] nڦ{uA퀓zO O(]Eo8S$ iA51Ac% F.*^s=nW?Hh#3增w$& PPlCt= FV:FօSLuEQ5ڰ6clJE(u{Nnqq6Zyq3$A YyW͹Ӥ*3(N a|BpPrˉJ0U!aW;n8*A5Xlk$XG)BE%THQ%PԶ $BꍓHvʞjvT"GlɴsaĤHM\fܓi uyB(hFJUmp&H63h(?d*K wsk/yQsb1dى_𯀦 6,A)^VE.@F9^%Z#L|`pm[fgV jAֳp:1bP{㖫l4c9«Þ\36SǷ}:Ztʑ@4gD@bQc2`D7aܾ>'T2SŹJjr",M+y|P <ždҿA:2M9Y{*q)*YJ헁3* /w˹\gT>SK bxV!;4&ny952#9nJNC=O1E.mi9=#Ӿ#0 Š`b:>T[o KQsw3?h'L7Cd *:Yk<]byg^>@ ].4֞L- 20耈>-mMu:f1w9񇃭{PA0 = 7Hoxd'{TbN0 f qgB&4.oTEŶk/f agFF*\܊P~i)Y"[ :Z%)G< :QUtm)) VWUr[Z+̅Sg0 2,k-U[6;Zw]Q;Q+;:fvi6ͧfƯɄ*4GM}Z-7ݧϋ+xZ\4Wyp:!FއPKxE\pvsvg.icon.dc_motor.svgYr}.%a-yX)".Js{tRU&˹ o߿vw|}|O_n6_nOB{o W2zcDIgwoLp_X}s UJ)O?v7bȟ" Be_lZ+)_J^wHae.)ּ)MwR_JBϟ'}R*hܕ†8mǁ`LgL*HX<)i o MRYN&ϫy@ˀ1& ocEhӫ#藒 EgH{ #jޗ/U: '| WAX㌝H9aU|700 4ըfKB Ɏ4V5$2(<'"E3'#Cx6mŸqV0@# N \Dd87x`j =)aDs~ux.tMUUyO*\| 2܏W6* Tȅ T`'eV& D*"`4O&Lg%vAH!t2С}q@V'&# [P1Eg{6q!ut e5j$J4EXԩ7r=T_E5BZrlV׷-}VPҹza%Nh\APo&%-MMCznK{ +.4҈LmUڊhiQ1@?D6'uh3։ȍ6[OR@h2HᝩRhi{߃+y! I9IV c5O}-50ƥY+r\>c{cB:D |&#U8@sB4yw+N& u`7a6$g_eڼ C5F뛒fCf`l;nфyHڥ[yYVp*_Yw“B(:GbiS |DIԵ0º2 m L$.PP(0ҿ06.Bs3Zg#YokټrNzg` _@Ä0MxCh^"ƨ%sVlѱ A٢0Y #MѴhڵH\16U<:3/Ș=?w Y"bbBcEve% uUP?OlUmOlOj•IcT7*F;McLD%BPs͎tn.6vʼc{?b^9ѭF ar&00Q* H6ogu#j&j™yΜ|,` 9f]hDB ղ)BF~E7bT掮t${FEAS U7*5vÂ{v>tC3;ʢ]2/+W 3 '9nִZ^0'ĖY9G ̽zȮ`!1:5-9ZgWrQdOg!thSSȏj h^eQm9R>[#֔1n+iwtl9m m$pM./\| Tjg؊qm!Xy!%؍bjO-dФ2fYX;"7Ž 1Zl;Ό['t3< 7fIb+2-zgCO+(4)XW2jrV^-9Nrx% 뗜SP"DLouyAXO)05.cf% HSb 8b\:R` };׹PcъQ:iek;'5;s!-&au aDc,Q3[=S~"\(T ᐩ6WA+BW^Q'-OS~PKxEwی "svg.icon.mosfet_n_channel_icon.svgVnF}b> W{VHm ^fD(H4e;{Iɔ=;{,?Am?TvPLTlڮgc#3w7wdXl}Soч{>m6!1$E>?vA_7a? HaB< *0!e@qhCGXG)fISmT=0I{{yMN#>r\SF\r3 oEM{̐Zk~Lg =%9?VM9K8sJYT벉PUqn "3\}[Cov[z nwߔ6%/f0*X[kZ S9ǒɔ smS#4 e CL2~BflL&%ecV%^d{K+FS9ajSKK"n ),P/`@h" | 蔀Utj_䍏O( n4<^K>eL`T)PGe'~q]y^[eJ:%hWW8Ul)- 2W\(.hru4zN5fXyYT1*.~\Ba PBcE4t:(%Q WG ^'s`#6T4 c{=RţYO>p!rĔ3ƬMANrdQ7&u}` tjv ;*ŕ1(gPHЀ 7`=7k%6V,>)0+JD-Q sjR91qu:輌k(`g$s, ' )"m ci? #~pp!6ovI96;#[-VU[z1Ћ>WdRM0ؗ}*6q\Jھzw-JHzC]dR@: =uӣ0;+dn{}57v- c WS?/!fd$Nµ̲zV[o^@Z:=s$} V'V5|@t}&ƹU łl8%--p \ N:/]|4Yr`^(V?CnH|#1LvlIeX_ ̝O8xbJ#{ /<7mX%E; aDƘ)$?ͿPKxE nsvg.icon.plain_pcb.svg1o@ ʗ#];tjv[:ra i__*vl9H=~Nܼ<-s4vZj޴ϣ\MWjjiѮ9wiE<.Ç!#'[Lz cwxW˴0%TN#ͤyOR|`&~GM|mfY.ǗY*̳OnQ/Y=}9z<DL!jzl2766j*m lJ^=Bd}/I4Gx1!@UQu_EtTmC) B1Ƥn< G%!HEցz"<BHAa4X }RΔ(rxrO5c< {q_fL%$I!&41p7DRG<%8B2MF%l5Z(e"f0N-W; re??PKxE^y svg.pcb.arduino_Uno_Rev3_pcb.svgŝG?E/! z>D9͡$-`o$4BQbv5ZϗF菏1jYxY]\| ?{.ogw+ EH.˿J mѫ8j>m?_tZE8f6yuهoWl>tv~ֱ^Vls'7ݥOWْw1Ќjsɘudzp$cûܨIlG6el >6D|{^wv \|.uxVpzsA+cuOm#BB,ӂ #M$iBb뻫U<w*|!muw\l d[]2JdAU$9ٖo JdbSeJ!v`+`UxDckV֙ 2KN%%3P/pd'fF^6F^k_J#B 0h V0U Mrvsrà'.@ gm)!iTg\殀A#O +V(6C,+C_E>h|k2eU\ N\m梎ޕ˫J"/|@b#,%Ll%Iqn*mLW\g~c,&z+Ȍ6I2GRʕtXzofڞ}ҏսIo/%!Amm- E7>t შ[9u:`#'jȔ".H*`NR񙗤6EJ)'~!S)XlQ՗*1*:È-zИ|+ A3Yt~(-!2H0`X"ņJL&Y|\/iyfɗ=+bHNUaJOv)%Uӡ4-Ȅ'j[p DxZa˗fx-[ 2je *ʶWjA%Zj3΀2F*np KEO`]ѐT(,ָ)HsR?_ Dtei:`e2 s7ԱtZ:3i^KF'RgXåk{X,K 9TjE0v䰶qRgXO4Bt(43,(ʠU1ޖW!cWb xF9l5<0O^C Q*j,h(. mp{0jߡcO3y9`j %jߗ#W&oʑm.#.]_`By#=׀j0{Ey̨VkY,PQd @?lgyTV3l@-38{h(.`pUF/}6f- QH-b}Pcv;&y @fjf} | gvu0{Ey/+JKUfϰO*f}`Qddb_VOTXV X= B%=~mUJBы|`NMGg I gi0zj>ԻҐ}5,/7үcL;d_Ș)~#2FHVJ"{̫nv~y垙l^ם__ m̼;Ъ-m&T6}P=ݠKӭC;kh70 rխC{$e^yH;m^yHhb/XL uU{wp%c]!W*zZ6_}FL Kj_/kҏ6zOYRzun䘀hK $1첩e{6;wt!lHW'er쓝.6={6@}y<=`~EX$Wl߃AbݔS1q|?|~=RpԹ!!ي_[oKmfd8K*)c$(GwL4\@@OF|y5%=\n{mvW5z4l19 rz0M dLݓ(#dH%SJ}rSf& a\m׊|+ZL 0^@d_yD"_uA/:M kO.6}J94gC(^zO>!ȳAߓAF?lCFp dk -W p8+gy)ꔜgzEya/!_4./W==¶}\gl\xxFzu}z{5z{^?+BH!l¸m&M~))V|tyoŧg?}Wmť5V"2>}hJI}2{ `׊`'s 0gqO:92Q4q?6ǎF(bAB1w*CK bsYFlQĊ؅E)c2̞JQĆX~P / xvM Cd12VI|# XB#3&"at8vZ{pLw{JwrQy 8-<7Ղsvg.pcb.jumper_2_100mil_pcb.svgSMO0 +L.IiCM8B$% tv6!l'{ω/jxUkkF@iڔ^Fk 3}Ե$hhM B5JTZiO7a$ٿ߱C6JJ''-UdeaF(FH4+f;;';FPuܖ}H˩By51!& %Bo.*]̾,1ƛ #E]Gȶ5ٷs,g ¶9>309m5rjEV̹j%vK1F6@0c5(,jeγbqȑaSp0ټvGX곹fL'{ڴԗE+uSii,fu{V/BVJ`frqK2Wq;0] ( 8)5}XPO:y`>~U_"b*iM+VQq3-.ۖ(u+@^x$ڱ/!S ;7$ ^O}J|L(೬Ml4@q澂 @;~Hl7M/VxߊמI\EhwUuKWz~# P?@:DzF277RWPKxE渻 svg.pcb.TO-220.svgQo )=mRqx2Rj`}"5i'cOqVp`hm\UU/x`:Tk4mT'ra,r$ ܚŒ:)%S ۠e0L&t{p.n~/m65 VA{D2Y,DVd{hMDABL_ O -$f'09 gӎΨ?lQ uv(1Ye0Y+ʬ7v}^@jwQGF)⾽g9]0Q ƿK['ddm3nt QL, cj8].H\a@'V8d }vdq$ Lrfxd="!2čGm3#=Hqh>11Ǚh}6;Lrϵ4=&Nn|rs/)2\ygmue2Vj3BڒMӹjN6uGG0q 2e*$X`T+$s)+ZIƾ}\ f6g>%6h;̲]_rY"rښ|cqY{6'?8e`Y߾رv$|x0+s) 2%a*S]׷ PKxE.S svg.schematic.dc_motor.svgVn8}v>ZIQ7rqqt7@[}Z(2m%C/Rb'cú sfkgh%Jy<)&*ExYO,t)sYuQ_V,[V1!Jh}_͢(kt-gU1GΖ* ze?}@jn>]_ l3O&#̶/uz&k̾,EG[;&1F&S'HM"|p4U=9TG'NmM}, C۬kbѷV:8BߧR:<$.JY!ҋZ6mbCu\n\Zĉ𢔕,WR33tTI*q0uNTeYm>}C`Sb>AenB-Noah B X.bV.N'$`N;}w!vN$KbSձ<&KulT# %vY@ &kSwlk>j MY|+3jZiڼc HSG)SE^[x2PyYG]wT4 lȋ\֤&"¦@w]t@lW@ k } \؎b`bxǨM`3Ug9s#B 4c: wmNcqxh0CxN~ ]PcO8qv㉍>sH<]J PyUHL?qj"++%R*~C̈lYOZ&fe|٠C%r~f3{gVSU ;7Aӏb =ޥCN!/]Ғvvb ~70+{<"j%re:Ĕ)6*w3q=;%E |%֙9Uy)@^fJhr;Fbv@0w }u߱bֲA`U:(je͉c(ajEō)hk`kƎ~)Z)ȳ*u8E/P@c8q_Uyq숶B;!dА=Ï0|:At-ObgQ9YcqYrjsǴ~ŇM”D/8]P ,;id8"prѪu8p2`D|:-DsgQN\w&{72qQ{?Mi8򶊻H# xX#s=vïɤ4ꊘ+ͯ(eLYe.|lUٵp5<Ǖy\SwpThtAmQb3_̔޻q%ţ<p Kz߉!2U^8"c+L7DPν4*h)Bkn]ԐݧoTfz3v\xΎsP: w>9h|VqN@bVϷ3`1K;[t:8T;91[>nWQf8J؜ɼ5!uaӕt,OWbcSA39IZI^u:a5u1u}Qa$F0~ZGT*pH(XibmoG0h9P;YuGj'+b(i;j$36 78P#>@C|QЫ MFi UE /.# 5{*P?Iq>a"Pr>@C}ơjn8P?8azU_w ^\Sug^6׊|r/^ N j(HY#!(Hүw? C]9^ $Vpjs0ތ},faŗdW1߂^~x<|/FeG?[2DP@ AWo6,5:3)3L/UgY^uJɛOS&5Ug`6l@q譗Q|<0-sY+]emKc eAS][{k:Xá 68v -XTI`yL|ʔ^d9& ~̟/c?HBcBT89ky8- zrHc6>O]ܵN.s̮'g_Z3׊ž2lBaː9lʽFm+?mP4jk M̡繂ud8TnToh1,Ncz+RJ)#EN1>ҺF2rxdcL Zn0u5KZîDkggGڥ႖sͨ 1/Rk=V̈2pA1,UR~J4[>/Dq6I4K{U- fFj&e*]pcjh嚷MGM> 1X_za0y)Ui5>S)KK4f lL7 Cf#, (IJe `"-iJ uu-%u5WpN^:%d {[o@~v3Ql z%v .#:zL;rK[+RvY!˂rf*r8M0YʊYC݌="3j~$?oT$8=eS 21;dxǙ$d~C8ToFpﵒ,ϓmZ$e,%)&'b洓ܤ-=s3/0(, 礼dJ}0{<엉M&L֫MjN=i]Cq$a{@.gZVg{D|m86S*d ԧ#؊MkmK9'2H +ף›gq|"z֣;) 5&&ܦ+&ge *UU &|~"'PKPa@lF&ۧ>ZfPM>S<7&\eEAE V8cG|)B2ݑjG0Ev̑^3]5"R˸€1שU+7?ʩ#5hPY)R0E+?qK玘ȥNńzTFLc! hL7X x,R 0*X\ypq *i \V,.zq>M8 L]y$<҆YIMrVv0`[HNh)6s嵵 oN;ZO`Kc,U`([00l[ |πB/p"%޸X\Lq^)^]y9V@3*0:|iwE;xt?gV?&EqOs@4{mֿ80"sfv?&?ݴ> ǯ_n';O>x:t!44&)߇_~ίHj [[|%iܴWи?8l ^A2h1K.OЩ ]yp*)ʟ//魳xu5_nZL7ݓXx⚘_*̫{$ܠ;3l;hI:[^F?MDuHCq7z線ҩ^Ԧ $P~ϓBB-WgBޤAy7Ge!ƘR[?¬N{AjKgHaΐ0r_ `z_ni9jiG&ny̯W9 [dxv?]3TLa5hhw QrQ#-[ xys'Ye⢧&ny1cE=1Ɏɢ )3_2UFpjFU05dT\?jh[{dhhֲbqS.nӬf&vYi.@BfHk(VLmy9I@ ]]1lJIXtMM :UW46 ]F&nEê:ŪVEᯜZ}P+yLj"_$@ʆ[(a4F?*|YCT;O*| iGdS".*UC*n x|FCn'%zj4+q19V KU:i(!kWE[TM 0╯4YyF$^TVHX (d40pRQt-+4u8hHWXe2եIR2x b(uöV̨JUR&"P ?IWFHtY(DRyF!5)`7)&ٱ2: ZV,.%R4Af7=ܝfcҬ|GP )%)NU H3GY*  UZPZڢM.a0: ^քbhhֲbqѓe}^Tk`4[b̲Qw.amȦV,uˀtóVm Ϛo󘜭WnQ_U6(˚;cf#thPUE6:aw GˊECO6f0Z;$U`lI0Ӹ!n97Hlwa-H8n4trUJd4oYvFC"۝pu#}cMMXw2%R/w UHdG݊0nnY uThתGÿ/3X\t;hh0J0oe&+οhqQǻ1F_G7s~'݇]vއl~1gwk&)\H,SKx!yƍ67&uT5W:n=d 7]f:%C C5磱+֯Ug){anbS׶Z@Vƶ3'Gݮ$nFxFuJ>ĨƨdoΥ zPnU`17Dv3^YGA[w٨Vlg[}"vB3>5U:Ͼk&fTW%$JTGguy[7X%i59- 4Dz(KvMa{%&H rv  "sh|..5pD$8)e|`2j5IM%O\"yq22^q=2Rn4ˊE; yh|똟h($&S$1aДuI0۬KNImXC6c622F 0q6 c ZV,.vuBL(رQSOY{LV8ӔkDqR*?gTk   cwL<> X@ @D |abB5^*;0eaG >+2'@Rґ2QJ=9R [Ez=nq_;*D~ \D¯ 9&vxL^GĖn ;~4L,LYظ j[TKqTQ*t`bhl[E]|*0!F/hزbqa`ÏE30vL&3&qNãҁ/zO]fT X`_ʿk4kYv!^<Ɉ'~6B qyeXӇ04r"pɗ}.{}d]oopmS[r4x1ISpjjLHm؁]f.uu뛫ey0xtOJQqNѼ~&%v6IxI&[wޙۄFLԉLU%_'ᎤP@CN;ͩ/C7H/BݿVk,wS.۹Eu-OQD7 cyZJ/+@Ww59Ƿ*Y\yhiS눛ā|#ox{j tG9@h07d*|I+~0@4B:0>' ZxNy"#@pݹa#z]b:z z0RTh.븅<9׀"q/R[x&"Po_1?_,i]} j?L[wc}!Aנ{Ϳ@=eVjs_4ZR\AT&EE޺4 gkGe cO4j /(M] B2cc׿oG3=T/퐌U{jЌ&zQz(!QYP`) Op<ªTa ,gvY'JeZ/V0.ILY;f<mvn#؀h!-F6a]^o\gb @ x,ctjȄd4^X a8/.e Xē0oA(8D?a67Hf[i ފ^n,>e|=ʊcM]丟EAWMdbFF,='[a td K"7j)P@FEFcm^ /G(G!]0M4ѩ CiF/󋱚<1.thBC-m\f5 p oǃ( HS >>_xMpCܱ7nEf(F0zCSۦy;RMn_԰$tie>!xQvX$3M.`jul@)FC@w3f "a /@FV$>F9fF:`+ԿמHF4DzФ3y(. N@ f _H#~ (3)g '9߁OU w-`B:$E FűQƱ;P#HÛ*R“`a v oX C 7 _@Ryp QP<ʈts^{^XD;R[T"$E_Ń1Cd!'Z9h'ObM0 DI12 @T4`xThB%Qv>`{R! C'uGql%G(hrh0JQ]SB]G V/tt ю@zU'Ex>`LN 1x xypUPiNhTH2h *a`V)Jo [ʼ1 <h_3oSw G:Q,'hHB0`Õ<ڂ@kyvJvC#Bqhhy ZJ׫:DO5 w^B @{0,nMr'100ot|-lp/ &>9*Ot h= f -mx `2jkesYBL R׎dw"0Gd5AOH+CEEnSWP'݃H?())W sB,p$I)H;%DXvAmhy: )U``C<-c@r%pZ޵,|SG<N{~S{hv˦>2j3y䬊!0ey$l)0.9>B7g9vpLQrB@3]BRa 17Xq0[1')œOᜀ0'0%ޛI=[k{vg:ndj 1# 0D)' !p h8N W;(4Ux;(kj1.$ArLx$( tмEH4Ta' `Nc'G@CF$cW{ͩ.KJ7~Eڅ/_ t䷐'U1ſx?2'ܣ 7Ш'iHD<*DJ /%dX~ B;dj(:\-Ő7f8 zD1)21|iQEڣScGkP871]bLK 3z46PrBƞiUoi@g  P4G2Tx qɕ¿hGB" aV0 TFFӲIp&=$V|x6cT vZK)F1%Q \Hl!?FV f[0Ƈa8" T  vGN`29Ǽ"оBI;8tƉÀDp#4:8q;;#^F1<~r wA>5N+cK#n09Ǡ7ochXĉ f()إa,T\@xP G)kD!T'lH~r")HS<$0_ D1L;lq t̒O! @hu,? (/PL~D eBPA4cP )  /x4K},d2B< ]%<|kԏ";Fю$c@쏀IdDaaL;Df >")fpC MR]W.SEQWlXˌx*˕ OGkFk:cmkUJ@/Lށ 0$9XW 8G #AjLB/4AajS>T &a2E 2\:rQv.ž`f!0[d B;d&$x= ~ P2ā)-g "A3@fp,R 7G"hx02k Zc=Q`mdIF> 6)oW#ve>GʍRB¬~pHpgY (JȺAa`hIi^'0/63d0ceWҌEF,$RBд{ vD>=,DT .zOb 7:C^[dqq)qUvǕ'6q!(8&Fc ewj|dž~h)!b 񏼥rP5F O0{ -š~˵DUBU*PHBPy!Tq#:qRH3d Ԟz:TPy#ghLb`8B4#CO~D& X8g1^p6#AlT& @ʡvna1[ ].&R] ( @ɼx)dMJ?k VFa7)ð+#9b CUDn9R}sWsYo.*,&&p&k*,MHdU)`c 귱}Sny`wp%$äѱ#'^1'a8K^?+~ Usb: 3QL9BtSbE/2xTx(|}[Q?vW} 3Y}baU(GQhy!0bq IT8*2V`= & `_"ҿ4z$ T4E<".(gǢƢb;9A*4z XRXqӎfyt"r{qS6yq b(1l$C NJNd oǐ/C4D08 Ĝ0|F뱊cpмx{ωBД>W4*,33rtf:KPp-Pp1~žllE\)tqRY".<,ӸNA1S8W0b kC,SvP6 SEPy@G0uM Xk\xN2h)5ANPNѹ!r",XTO8= kBpn I*P0l #,8Yq pRKSj??g]1DrUFxP|MHo ːK7 1(L^RD|pp18qBHpt ̫ø,8V2 _(2eq6qRy4xfBܙϲ=[؈!߄؍ç6p ŦAžn~+_WYS|ʝf9ov#c™t6>o4h˟q/km5GB¶x j.p#t]9tgm\܏y+9dJY!<ar={߳; .67X|_G,U1a9d+WQ~|=ݵ(}Gu}G9f?p"\CP7~*I,&9ѮJ΋;\R_R|l-uk^6:˛;:ؙp YGgL{Hrbofߊ󭯃̸(}bfTvQAE9 =Z<{% ;NuF^j}4ΟhciI[U|.+]曠Ϩ -=³4VT- %A6]QtK/RG8C]"'2aR=JXe^\w%Tй[DI_j'$PqX1ד[J[]J Vj '捍jxFwPhH݀sbr+@͕yƴLBjkٵGGrW`F]Obf Uowvɮx)d{<$*ZUNS!Q3rX\t1ʫޤXxBr 7*¦1ѣ_vÎfamQ#2o7h&VNnweI45VR'[>4[˵w]`p[dm>EE3L^l tj ,K(.yBF3tIrL&'ׂA㿽 CO4 g5Į&`x,EGs9rone{UQ3Sog7cnEՍׄDDɗb`KFf$)s%5%Dh`C$n2o-Yl}ѐ]9 yWC\Sp5j[R!)\/Mb~ħfzf:p0̆F6أ9 T}pZ|?؆Cζ68X4qnPK"d)+vL*iH&3nYl HC=$;Ǎ>oBuoAapRvCK!^]pRت wceé.Nu88 +|PKxEY)| Verstaerkung.inoMO#1 Y!qC\J+DiX$A6C83KlǩN pOt#.4 ;jxd[4qѠ =#tAIbJ8=0ypR.Q[a8)d.wiZlԜTpPe?pk|*xrEgqy$j̿{\`&|Rm然K [-TГ8 fq2*>P3g__O_op~q8=0e9,My?e#5 ki쳜Agܲ 6drρuKtmPKxEug6=$part.arduino-shield_r3_two_layer.fzpPKxEW Apart.arduino_Uno_Rev3(fix).fzpPKxE>L[Ԇ4  part.basic_fet_n.fzpPKxEE]Ş part.Battery block 9V.fzpPKxEQVC{Y apart.dc_motor.fzpPKxEmY(H"k part.Half_breadboard.fzpPKxE>6Kz.8svg.breadboard.arduino_Uno_Rev3_breadboard.svgPKxEx )7)tsvg.breadboard.Battery_block_9V85_leg.svgPKxEC$p~svg.breadboard.dc_motor_leg.svgPKxE%%k.r%ssvg.breadboard.Half_breadboard56a.svgPKxEu56J#!svg.breadboard.mosfet_n_channel.svgPKxE; % f)"svg.icon.arduino_Uno_Rev3_icon.svgPKxE} g svg.icon.Battery_block_9V82.svgPKxE\pvsvg.icon.dc_motor.svgPKxEwی "y!svg.icon.mosfet_n_channel_icon.svgPKxE n~&svg.icon.plain_pcb.svgPKxE^y (svg.pcb.arduino_Uno_Rev3_pcb.svgPKxE>7Ղj;svg.pcb.jumper_2_100mil_pcb.svgPKxEr#)=svg.pcb.pcb-arduino-shield-rev3.svgPKxE渻 R@svg.pcb.TO-220.svgPKxERN1/Bsvg.schematic.arduino_Uno_Rev3(fix)_schematic.svgPKxE4$fIsvg.schematic.Battery_block_9V82.svgPKxE.S Ksvg.schematic.dc_motor.svgPKxE8iOsvg.schematic.fet_n.svgPKxEB9SVerstaerkung.fzPKxEY)| Verstaerkung.inoPKfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Fritzing/Wahrsager.fzz000066400000000000000000002644171250202676700326030ustar00rootroot00000000000000PK#8Dyjf) Wahrsager.fzr\Ir0dcL}G$JRP6u1x"yHVj^alwfYdɬ6c'{{Duo?^/_| Ãg/>_a_7?|ɳiۿ/뾞C\O'W/0d'/~Oo:{/W/>8y~}5/޼}lc|pO탶vビΟoun9Wzx鎾y^zxӓ'%'Z,9q ֓/ۛ}pwzoof=/_<~ի{߾|,Ӈ}OzI)Ocq?>ˣ>igq < _/GZ~翿O%˟^<{pOmN~mR_K~w}?~ߞ_{n?>~3~w9ɯzӼ%7Eo|yqg__?>;6u*y7wodkrn.m嗛gsg?ӳIm.?͋o26_=~w?lw^zų݌gz{t7Օ湴sG;n_]G|x'S54Xne~YyB^.-y/ZYno6`y_KgM\]躇{O{;{~[v [lVbWl^?x"|KnGZχ굗|CuF<<}w#nks׿Ta |Tmnm7SsPwowZWww{-~ggﷰ}}egʾuJYox`Fr\F؇e$GK,2{.3uo#yj#z;Y2Ӹ.K/>, ߲>0sd y.)/ܽq:,gM}e}$|o"ս򾛊8Ja9h쯰sao?  o=^ U> 7ZWvvb)i3œ/;;N:d_d}XM{췬wlnbsB98rCʞAp B\1! ܂oiwj?cUGxW[kzq폟$5?~mtȍ#n{/z7IZg%}`~ǽTP~mCnu7IYm7IYgIYpCxq}XFqn}X6q}`&_:c͸{/f3uh߸~>ȸ>6"øo>,_~%}u/>,o7.kq,޾ɗ5,[q}XAnܞ b=a>Ԥ(׶>}ayyr{A5q}_|[ُ=$n_HmrW' #C}m7q#exYևgYXgCqOv>ԣoOևe wOևe [f wz@rmW;Qym;QukQq ckAێŽ\{wC{)C`7]r='[۽P*rZip/Sp?PG{Nԇ6흨+kQC{pomCn?YϷpz;R7sxonyś_r=Oyg>/٫o>goz_??˾y_goÕ+۽{}㦆bO-Y-U-׭=CdHK_:..:?i޾~)߃y#^J=8y̛YO>4:{ccgJq_E$5?w/C?7wí`w7Wdf|ݨ@_9qM{`tvU};L@/v+Sx/;jI:sQTYƸze,t_J>F|HP$@FYFs|*UOcTG(:r^nMu|Qy\s<?Z}z*mOcP4mwNĠ)u_Z)š(U,e]>kzvK,_<:vܾ5QhO-c3:{Dݰvwo{<Aʙ,.h#vކ+} Dro<3{i G{s/>{ퟞ>!Z}mɋ?ˋvN~7[wK!Ͼo'oLO~wK<#iG1)x1i=vV/<{ǓlVa}Jǘ4>LŬc2cuJߖ 1. ~IwiOt{n?:$-R.ZG/οo?E]u Vi/~?gdQgwA[^&-H|U$j\9:gٗʲ7n\)SI%cHAEwUi'i.Ҵgzy=>{|\٧uO,y]Al?_Ϟ9;#7 ixA=8yy>,߼W鿝xG3_z]Oğ/`Hxg^:M.6g\O̾>&s3Sꎦa.9}Y2L?aQb*4:1zcTVV1X|ؠO2(_'/~ڟ/cw1_x%/lLb}2|gٕ(Yvr DC(-Iӧi%Fwom+}eF]O9/8׺N"T⺡Dr o;W{r+wF@Cٻ}@XFhsDhwQ(p<>bY7Gl[7ʏCB~.Ͱa_mP*&% |v_ѼwUd^/Y1=*XZFcУ&gŠOShgiE#> O9<5էױ ߤ__=yo~@jW]kkԔu maTiZuɸJPZn.wZnϦ>|/ K\~q]$ֵxY[w50Q\Q\y7 k'8}V(*Mmio78'|uJkq#̗Pa#鸳wۇt[q)ߕ&9bus!aV{oSRH|b uL' mHGwۤYNl)qyڽ탊DsO7hsX[;m9}Ҕu1=jVZ0ZPѣ:g .j hMw_ir$0;xwk⓴ y ħY\UK똼3se|՘Р2ݘ?cv},whwV7Lංi_ZӺ_?@s֜Gh0uqW@n-BwAmޯ^Q`:} }xm䣬CO:m]h|.&M=Ucz_7cHBvoPBѭM؛ꅻIⵚym$ nqLj÷}G+[NOdRԣ*?her= Pg]~' 8m= P1,zu/M|||l 'azO?thXD o>ƧWn|:(ѻNiLcQ-2uFW[R!ǘD?ZcRb)~;II`h4N۸tj5. }BmcFn ͌򺥟A]{;&`ZrK睸^eC[2}ՎWNs M*=w}h(62wEQy&9~V88%1Fe NTetZzԱ5mq*F ,6MR:nw; yom@=WnxUYo!_ޒ|Mw}hh66wAqQy9ƥ>Ȧ9M;n66$.^Oƴe?2Lo'?N_>"˴n˺c3ܾǀC^{͸Ўӫy7"MWפjqאkq鄸1 =!&_kDZDѣ ?h%r H|󀴦;z¿uZV{K>+&zYwCЋGL, V޽Z[SǀPwmJ@טl+Y)}<BQGu qں/)țf?}:\?ދ8a/YcxIT3/Qճ{۷/?}^iWĴnuKY)]KjS{>ܯi9(ϱZ>Ijh&齉#9Fl_Zq9ȡ~[ߺӲS~+wfWÆ;=W&/QW[>&NՉՋuc* `?;KkLc v1ghc;e0śe]7_x7O㣢!zY#FZ&s;k{xR {=Fw\z}ݺq̾8rLޢ8Fd3DdwD%uI=Uo{Jy>1]?`>9Y$qe*ݦ;tGq-cvn>9m3m6ܬ2M?(NcHHOu hP>1ldQ[YO1.nױzݦcsI-cvn:9n3nC7zPJYјG^r=g@XsS]cg @}p[ $?5 nj\JoW{zzJ 1Kr nUr?pw#[#܂.%__ `79s^~9+g߿?V'>ql:/7oaNO}xۓo^~u2_NOOqrZ]7do˷۷~2~"i=j, 73c\'߹o>9|¿}pKIu_~s\nΞW}G2̹S?'J__͛]1~țJ; '#,gAw.O)2 y6cT~FtZGوG}o+mC;ﱜ8t:oi_O!4 (>_C47cj*S|QtM5a*AS_Vqi=#vQt?1Ji~]JZ°bu&tQn& n7VҔ~Hy: I>/:<5yQk}3{ri B:3*)%*k0fBrTjk4>V^bhiiY:}֢%A>%uѕyyNcGۤl}z˺FK=M,maK_|Ő|#I{!Z3-0-ahC4A^.!yC$7ƶqCyy]bIEwl^dq$a+JS8Z&΢USvRG,`Vm97itl&\$0Ϙ\Xe =bs ͦ G[W̊6R\͚K{T$1gbrM&GJfR\.--=sNoEZQ)iW7he ǁ6 hhc1 ~1+)2$,=HE')R6yAM%j}fd$L\] 39ɵ(tJV'CfSNTOt7W}6Q6dv mipfm2_mLߑEejED]Qq%M]g]^|ҧf\ώt>߭ etOՈR"RzFɨH:xMO DzmL<&;~r-Ҙ :&%O:M a`*%*HwލmhnbTѕ}pm5yw=W+JGbtd ->P;i5QMɓ!,Ʌ=kCNY7ټo NFm^ℿ}!_!k I9T'$qO_X$;#!ۘWE_*Lr)B(*;qjxaauEH&ߩ6mr>{8ʷU+UԉAYHvDh41W0,я; QG.hwR]LiT&V*r%Q4͓R'!S^2`mhB8jrNj;[?"_ʹf~D ,FL"rp+&^{II鵮$FOd2Y"7/!5x4vR_-7(abb}| _gfƜE+J)͞4dD̸dRV1ʥᒒ"X$:V.ʔ0^D a%*s .{oDڤ&%i_w*J]gZ,&eg i٬D;U/i8fzh8LbU z, K^$`&KP1gԓIwEUȩy`"WDxVЍɊ\fuf_4V:U "Z< TQm`&{20uEE.Ґ8|V')GOy*jHԙNRyzx~5a!;j ,0\)qv .b #۴x-uk2@kB-yX\{,d21&"R}s-0o1.-^Y;W DUIz_DBIQTQcVe,c(w3)!YTiM[?ASQ&[մms 1 IE$i jFi:FPwFҖIņ&4z))q:U-U:YFe&ɶ(mvm9E^j'4*28 V=eܴ_XQힻ<]q:xjl?adi梐#B#+Y)mnK-SmyC Q!Tr *6j^DPBcvU3YT*Eœ^5N4jmaiDEEU4 /m,%4tdeyE=hյ*%'*+so1F+M X6:D?,TyҦK&5alE]S$Ay Z$=U&F:5>Ib4S\/;83y{hAwT9 זl*d39Aՙ?RXK mmTxՁ%\pHOZLƧ}Ks6!SXAmSRqítwΌsӖzR]T{4>()"mTJ#jOrd|ty䐥{g3E,z<5A[ȋc"ITCJj (<)8IUiYѹvg8u9QE)Da+Vc S?VԘ?bi>:J(B䴆We;?WLv*hאڔs:\y d@b9+ԉ7 212ҵe{qG&neH D oJ NctMAČNDH*/`!b$M90oG6%CD4a< ↾t$7m?GKP42:F#u*-EٲJ=Qc v`3UyOr$efVK2i 5CN#3Lv'Â.~^(4dI;+$n>lD)8E(l<9ld2ՕK10$"fRHٲAacC#$gT)F26mMZAL&B逥cS֛0rHALRCv= `c\#;9 5s(e; ^REsG;"m8oYi%FXAdA#[l3 @,%K68 Ӛ0Z#}սx(iڕ)£좌"89vZŰ<&7K*:NLr;RSF̧yc usKMA&U!6F&Z[y$S˾]Ӓa[!4-Cȫ%;:P,V5B=^ EZqZRI5%xsr'guWqoA\tH 4kAKw0 \ a ע?fhP^ҠQT' u~[۬"VSU_m99HY˪g)-7I&[m`s g %mBYjjѓ2HdkH蚤[FlRV]sS"N+~ KOSC&V7VJ|RўTp>)Ymym\NDw>}1csy^&bGPJ)PX\ڲ Pusc%ªڂ'`,(xOL(pQ9;DQ\^Q|y:)J&?6RMa$Ha)Hh_PM s:Q{Q"[SNT LEjR?v זּd aL'h8%Kl^XIw{N֬dDj_QXYͳj#$N|hOhSJ~v_M %Ao\ Ef#)]'s2j˄讣 cg ѕ{0nI.F.. /LmF˪ `+OK9@cOYPGL68NSG[+Ai+B.(XHAGox#'7f#xE𶎩Bn/RDd7GMB,dMYӔ(4'auԩk%4겳VK R.mO P{ .}*g137G!\M*3S{Ne;>9RAݳͦѳwຸGK2c-ve`oSi+m<rh*2X̝9Eu^"GLԁ*-TZa ,i7!"PyQ k  \Ai/(Ti*9T?"iSvNVb VlJaB|%)aIOTU-6E^  FN*kg%޼ջZ b5l.hi3uWN|1BZ_G55ϴP3ms=&09qT2J'kgu=G–@ 655w4zBd$bϕ0YE[VI*͊oCI ,~*`6d<%apEx \UE|e K rبM!u(Ի!%pY`*}<,ѕn 3%H M+zC !(:Oْie $qNFiF)iZXPfz pt]-8jdBDxHSuმHp!4+a&f#ç`ڧyc {!K>B'im{$VeۜM2P?¦I_RؒA p&3C;w0x\GPgQFuDc3!*;`qD8dQ uO dl1t SՕpe]@`S섖>I ܴI*Ȳzخ,% q YѥجN:kqzRp+BJ8#Mayǭ+I\eӾ3QpfM4\ՍN[:MV&4U7px-\ r :8zrW|~:XF1y܇3aꊯ ['MLFvT ԍ t*ĘGfw2(=^ Yw蒂߁NGDEJawdu'έrG`QE, 1454?*Jie΁#6H$`I[%Q>)v>ED^2*Z3qkUl̖G:zj.osUMd5m6G JbIY{c@@o`#{+q1DR DO'A ʡ t ``8ʑi3pP(>BOtK|,Eu a/DTS9ӣ].5 O x̜{a+0B8Ie7v2-&|=.e.3fr7ö#P/`(58W5VT69RQ3iiTQlj4z}t׊Qe{a-7GUtϥL7@!i<DZ@eSq% ][kBC+wZ[w~%2B8ɲIBTLAe P* Z!*&Arxyd,(צ h L\bNHc/:5 lq0A ON2x(݉xۆ͋*ܒUVcE2#6 rai'R ܚB˷YqhP8yCOH$I~~;&sdgzmp#1+ש¤?%$iMA _qMN}NWImxԶ1Q6A#q$`J]- }!-fJmO5~X' 'Y7ٱBD )°D1M'!z{Ŭ٥: CsQ!M̏:v Tݞ;ݱC=VXf1f b̒$e~50?-7Wk( M( HħؽIq?-ES a7Qe U!uۿ ˥)J@^lC)l_S5 a! t07#aGk};6 l8]zT댰8T, jIX2k+ 4C+:Kѕ3E7ð# ) 5AKqwS'\ACuu]E1N03Ճ\DZM59р̖@OKUcSM=$A t o]6J8cԩ1-ʏڙH:dJm6϶ ^Y陬);R%74A<[6+dȫ{❐+o\bɮ08%)髄)yfd+kx4G;2y2699MMYv4&&_- Q!nv/pPvI*"*ɏVKZ 90j[ n.-]i oȢBǔ ڇt2LJejbHe `n;%hTH%ž#:5M3 Ct_ WT\]M V([qp6 szz>^Yl7;օbiE*ڿBPX+/:A+vsU D$B43Z$ImFLGM^=A\doEƾ9c}\U$d%km!lsҔM'F1`V6y8_ҙ*–x 4 R8'K[A0tFN ؐ(M1kb0>T-boW`f"6UÁ'tպ7* Y`Hh7N؇ 0)4w526gf+rrX[3ֆ&fpp6w)ю>oDBV*FԐ ? H}R-JD>4:A vDPl̋h_E"o].h;NO:4`Y&Cb-8]iαLJmt(Pv0]HCJbH='1.k~4W(-#N-߼*r%0atΨaiN> nj7] j9B SrR;gO9~T1)#S{paL4 oʺRS{ޝxMX]QtB-*D@- G&i|CR3<7'&F{+JM69U6vyl JiR\mOr*W\[WK;yOR84B{wl ;O(4S;rBܖj˚ NPr"KmG"58NvWr[6N;ݒ>4Qn)a mn2vKt5duV$-23V>QkCGWv3\ƴ̱%J6m# D^&|r<3*HɠE.Fl*N:C "`J;+ F>,0mHw٦شaݍ~沤nNM3? I95EyagTmHKls &zWe'kUs86w/y.r'&'M2^}1Zy'MeF|(B+(th\^QԂbCjhcb3md}>jg𙺱 OB]ħ-I0dq]fʎ;\592uzHPǥ06d;1ޫ~H@1qEjV0%Ǭ- in }Q*lpF%eK{״y~x dn* )BX(&wް0? =ږs"[5m|-Y; tFU8ft (nobz4XJ!mS(#F';PAcq(0.MQKmD0=М8م.^њ(y '{* !*S[Sh7LbԼGԒT˜:E:Yb%ܟL3> =,#.'ԍև6HxPc[<qeY [9G,Y8 VK,%ib-B.>TVACI52:7PUAtc#${RԔ邥i]<(g<: >^(5"87Rc EQBmz&*%C4^gwl*fSǸ`QGx^RyBNpBغ5<ǡo}D8e~eXJ`4d^X,E g=3Y:1N99R2$^ d#-T=h]-(hL·\XrIeg dHRPZE^Gc!>s4ϰ؁D@(KX5K\n܌bo3Gjmp:M U hM?:B%t Hb 7c*)LAU> jӥ< eTmQK [фK5)!Oyl^Ӫ);}[#RСR*hg%CUt[5DnEǑpG]:N| Pg'.sqχ<] af'"Ly(lp"UZLpk'G۰j893 Dip.Δ' ?BS{Σ+!^̲ 쿌;hAJO}zt8Cczr0jY:)L'/ܬ/%2,K',1gH. N yiLAџz(VntH1Q`#:չ|;5HH EuQڌS%5B=$*B[21 3҆Ggl-)Z {{teߜkԦ&gP؁Ȭ6'(`Qqx"iKi@ ,ٶ݉EVE1ګlDщYc>z%:FXm }3\dRwUt4}`.}(KVզ1m2Ɠ2`reU m)Ȫм d!v*9!Աub􍺯f9˨( 9 BB4Q))z6y2Ray$ok TRϩHtN)fenRICPfPuZaqXhyu'Dǩv2(x)?<o 5<@`{tDhl7K$u'D iiArH t\"M'N(ҚY](bRTGVO!AɒVsIEdkKIu@e#,4tb&Н͙uNa%#҇,jdtҡr.h:#Nq5z/.}s~iQi qB@^UH v&1$  ~0~I T3Cת4,d"J|ZʘQ(܏.o퐠$ 20cqT5 4B'  -1^O&xFz,c|]e9!jwz[] Ѿ= 'H9rdGMK uҦ4f `tEXB?b6҂ܜJYTNק^YhHFFJã3 RD& q@s3䝌@Q t(jBIozhbj# ZDhWZt܉tr<:0 P^^i2E2>) =#LT0iK+%_adno}q*bሯ4J5Gg$`$|'g1n>[sc>KQT,җ`fZntAI<d$f8~`%=8B5#.$uFjˬ(+(ѕ.ElbvŽ 7D|c9w9GtS/b9ҹjN[\'G6;ZLȍ[@1YN1JR!Lס*c$& pET7V?[ ZL @'@>ɿu!ߪ0Ylf-J%3bJzJ.ς'F: u9K蝂ƙq ۥh8H >J@7#- <ҺVAl s]9GA.(:N%$Կ0Agܶpd,m(>RBsxD^B|2k&EJO/Op-#C)Ŗ16̓>iZ{x:2Ԩ 퍼ѭX;tN/sՂ-$%0YXIU.2 kO.˓BTwL΀wJS6 9V¼qN= 9EIBdZnm%Ϙ}E-_ͿZO,bѢS#=)'{fA{fD%~sBѪn [Շ`ڡI)&Cf]b=_jNrd%4D~&Aݢ,(*|,1cTs.ѱN xPcF3GT+%>䁞Vzډ@ĩ$$F^-yK~:%$Ԗf#1?gIz 8 baKz!:_Adtxdp¸[^;_p.˳Mx!3dR"kD469y<4T[{?y˦f21GճBY]Eb:"W V>m#ѥs=n|Y(8b)E.c"'hv{m̬ %:\5-M6 f!U`@D8᳴e1CC־3YTT?mM6szEV7'5ۖ0YI)^f1 8W+1ﶎ^ihyf؝ש7k^*E'4f:1-N,~do!űOvca,CِO.LR_`%MR`ڠNr$ͻY8SM0:!j*/,*:q!=ZP뙄(bצn }VN_,s''=%bPRC9JBg/ ;q+Gp= s2B|6`ZigU;ܩgJÐ[@R.s1A;^4\լKxwnsV~NabKŤX9RRIg*q3YhqdL[QL$=!&R ?;e&-TH01O*Nu:iVmhţr=`.1+ PMЈ RP7|hO?!^Vr*򒎦:ϓ75-sh Jz+ + >e4$Wshs r[?@;JT sB<=ب-}DOOm`#\j2Ƈ)wZkcӲ^gSJ1wԸуʖ(^Ju[ޭHeEuG,Y"迃& iC;Bǩc uC)8qaZ^Z2H<6 .A +!*E,ܵr{I)y?*DÖCV1HEKҌ+;CX|48YpK6 O*驒s]F\FY&wj&ll ; BFׅފi' iP2Gb.T * g! &J;9` |K,paZ4]Bǿ^vZ;N2Bo-=Gh{['m'3X6bk9K;?9}w. (CV'|b;I%|Uc˶xB_O$[.9{"t \/6iWQ9øcE}$jeKg4r_w;y'ݩ7ds&ߌXգ1EM5& LRr*$"I `5FѢ )^d'@,:DܬgVBy+"E_.6֤́ e P'PЈ@6 '.5ޱZ8bD| T?)o;[|>؉ t7uzjwF]QԈKbcGl~zaF:;xZ,m !.'z텝Vfh(iF9_G4 acQUZ&ؔ|zx1Oih:_B+sz.4R ^^$g+D3E# !9Tz Mqc?e)i Nhӓ􉱺xNaʶ\a uFP&ѽy5o+b#ab"&MKH!X94,@P> l'(ǖ^p`R6+fi!9J= @ѕ]`'b W3FpqGnT:"ģ+MnE *6nz-P@Y߆ JyB)孹Ǣ҅g}?e0A0ψP+?X}RmE9O286/d:X4v|[Qsע:Ԇ4FN::0ti (U0!02" `b)?䳸P,fRٗLTRž+RE`,:{Ed ]P)Bg*l+jQ_hj)bVxfx z)"U:iYBXWLWPʛU;Unc3Z䜼jwv:9Л49MipExo4*]7fobeenjAeM̲5M+Ϋ cgu-\K+^,)i%%7|RVY[q`wC! R7FX/{ w"ɳA㙭vcG|CC{ ov8 Dr'/>\l9879M2LBRc]4ZtETA\("#)kŁ'{ˑ^,t; iq2hۋ#6@B5~ ZHo5_͹' cdB [ĥ[ "eD[)je*qƒp& Q},YP|.ÇW^@k~z㡓fk jtc2SڄQ !J^ui-c+ov@FZ^BƟ^r;,i^|GsÁy~& )B;q"BM60FЮ@|8C`kɅ ԭ8'?E48__w%fv_[g.F EM!5uMLN)q2X25Q#5KİIej^q1YM ?Ф#PTh4.,Y`YJP ,}3ǐWusS^<F?^ɐ4-,tvzҽ>)ӕ:NkTZ('S`懹ީMq!z*72u>>9JO Ɇ$eMUa.BpJއ 0SXks.e˳:icSx1Qm`Wi2F ;w<)sIV$FLjT%pjbZ]D']*.Up¡4CL”_nڻBqԁ{eLĖZ rhm'Rp9/ZVO4In0ih=|P1}ic @?0֓|QHQS|/g!! O'SKphUK6LNV~OB<<SeSHW孪 "|t$$y;{H%YPZȣy_ hnj;*`@UhaO;+32c,tͰ]ÀpT%I 3 Nx̀ΦECp Q7ǸAh}׋eB&1a8s mr*؜MC&3S,c)݈3OǤZpU ދQIJj[Et\cṘ2.J^sX ev xD|Bzo- VRNa/FHc(彔αγ"l*n|,hI{*~i*APc;H(P%P nNk\xb &&;!O:@%}[O^X)ҡQ "UpÉlsfnH`A gHU(5D_(<1>ƶ bMX䂺af WY[;u#a8 %%F?I9ut [D00Jn RP͸fW9S}Vҡz<rkHke}y^&隔X W/\邰W@lu<}0>땂)?v\ R&1/L+\$?kyowex>B1ժ Jb+pE7CUVTtB'n4]MwT/ Y'? ;G]ON$ EipG;m;0+p?6yW6ׅYX0D<*Įyn<5}1]=Q:EVpW 5L ;AU] \5@n.RSNѤq&TW$L"zW,/1tk}2" u~rH+Fg%2UpHyVن߹CEI U4˧HaEh9uT$uOV 97{eL &=@+h7PpcN@ 3 i1b~g7@078Бmґ&A ݹ<4X8`(_\T(f’FB6,ϗtpZg0u79q@E/J*}| ,Sm͂t!T?03a'1m/A, ]P|m@`J\e- J0v;B.0'e`m^tG`i2sv#N͕. Ԡ~ `eEgfmEJ.Tږ#\÷.r_z.>XEZ$Jt$D:|Bl0Yi@?WUwdYR dP BŠt[ [k E.PzKivQ)=ո PJ`')Ɠu6>;0Tz@6 Y1՚3l~)ef8֒fakt|ph\N=EFӄ?G?ގ1)8A)~ir? (#߾l m3hfl>Wf{AB2 $Y" ]=ϰ(cɸl:lJ}S }Lwjȸ qbɐ+*H >\"S UoL<:JOXY"IY0Lf'r RԦyJU!Fhs$cypW(𬔇 06J#A !vù˲~՟|`Qv>.(6x`޼QzƸL"-yڅn,x53ɂM<:@zg?~c)`&|B^ -<йAWXcoaL tq'Y8k0b AS?^ b6EV d0 %~T=Gyx/vGDLTۨݹv 3Gخ:7vt 7t>ڢ c< l$=`C]tž}2Rc;tLN)Jz/ˇ=0 CX=#F,Aڲ/-i{`$rg.Ă4;sU9wzܙȷe!-5mJj@`T?w%J Mbse{+ zҢrS#'"11|Gp#Uc&p¿%qӒwM@t?@֭AANpeSVQ6Ød ɃSEmš GPNÉZ+USJ Q0}xJ!#y˨0s> ?]Ão2:sCfs[Df< 9Nwmzl`}y3͢aRv1 `,'Fkݳ+EJ`jJC3FTIKA' +\i7l)ڲ}uMC3N MQ#P*A7}naF[Tڧ`Hݯ]lX鱯]>!p8to,+<LC|"=f2ܼOPC&g?SWNѹT`^9XAͫnkaWBWj%ܬMV bH;^gLXO+Uc`,^Vd8# .pRŇwc۞"g܋lX.|(;] @*"CIANz^|ؿ,7Ũr):w]ٯd"H*tT폘2ZUg܍Zqi ?zyO' ~YxZJث Zq^S,SƦ91~[_vfi\u$<YGQs+Gb죦`oXnuLk7 mD bƕ/j$v+1&{J)U|pp :  AK@1XOF~t>ʌJ0B ;k>#z;cHr(H#Xwny)? K(1{[pjMnWatO`:$6(~97@^fHS@֋ZekJT;ѳ.rGT&ur[Um.˩Rr%YZ$ye!\yrE?|h+6KWâ%In/C],lb>m.GG[VQ㶗= `<;1=NfҬybcH-#b6ۗE kx-2>2h' ??L;6VZܦ"@s5,kgF{HB2H.S%AfLq":a1vFmZCuz_WeHъ WAozmyG53Z]{yKjĵ) [p-+ƢxfP@JaqB$Gcgۍ^oBXCݛ{BYH,QK%PXp[W/P>Pjsϊ:• JW }X<3!3@nq|× 7ht),esEJL֛&Fă[QҍV& *jM_BP]ftL1xƍ0Rb[bZ ;rY4k4җqRJv*BxGrALap(v{Tܑ(v8qxNB+&BhQ|6!D(mK؂O "&>fL߫m0fXl~kXF}r6[-iO>vQzz~W^zHJl}&zd[e#&K˼#3PSh2~6+XZ"<Qe)L ^Nnр{x}޶?Z-" =#DS:<{2 1+7p)k#7-6L%$%Q= {Th&+a$4 mD@#N t 3_ G$my<<|V"^l4 0N_X:'p'@߲A?f2@'#F~Rss5 ~:>WKIEg2 vmX%+|0!UF.s@D3DhBuf*|-A!(?uF/k֟-53ۗ+4El dkcX>?Ad+/Pv6K :vItL]5U% a3zN1֩/Þ;M1Pe;_bL gi[45E3GI*XLFpʇذ/د\ y1ܛYߢxUt *E8H0YPqr2-cEÖ:{yB`f<5XjZZzQ7jڬQ;A JT ȿ fK&g"[A]4Hɯ#+SlKb0ol󺹢>OsR9kUy/ ۠lE%$he-|Rp#3yV>W9rf+2賀5;o#!bJ S㵻nf]&)ްl.5Vdiw߳G Nf *7RAB ߱0Dp3% Ɔ#)ya &5sy񦯯hB9⪐^  c. yp < Cvm b]" 8s<<5(^Uϗ7T Zft#-J-nԦLV4Զ0}4 E!W+@>T#m8tW>h[ <@ Хu/~ZZ,gTU'J {禹F $JSkIӵb4yUr{/jGK}S^07O8SuA#r :[{)`k좱.c '@Re荦ޯ J#=x%r$W) Tl%)9cJ!*̨ Fg%*EU月 * WgF6Uu䪩^ե?tЪ (R䩯L4W,ʥuKGi"[`N &R1PRc5 k4A ;˴V14$7o$/!x#΃`PeǮR`v(r ᝁ޴ kгFUZq&Zj.FUƠYۗbu-h/m;+*BEr3 ĺA+Z;B tZ?9Yot8Or؇]m]z4n= Ɲؤ 8&xwAZEә^fL7 q[ZqȓK׳v G&k֓Y[k=댭? ~9{&ΝG$`ir7=󂧀&OSЗ~8*HB:y.HV~vO 1Ơ;+*qd!Q5;y}5qfLӇ7%Gyf&KЄݲ"&IDj9bFa̛7A47ުq`.oHM +}`ܷẰoW+ip%krj'J14cXW6M[S4h/\`61!c4r%մ*C|k,9nv֡qSl /ɿ0ic[ MoɬBӸEM ;J |ocP`dWTR;VRjJaJ͇8/˟$kc:qkQx?1ijrl*?ղYBx]S(VABAx;Р䕍_r^=ڌZ]OyxC6肉=1E dERa E9WI"; XЏl%Qh Cgu.af:l\BX˛JeM+ MI)<0bpD%o+)^6-z~87`0mJ1h:R3xanӜoY[# (M6e>Cк!$:؊L:zZtϛNU3B0]LNŀ+(}:|M"왬31a I( # z4 $7\<3I0xR=9ERRiA¿=w\7;p]^N5fvvf_KL`@eMA+ߘngjcLO2Wt:;11d 9H$a&]_1cF`b1(܎"A;9P$6NuBp֦X( * Cw&Ř1EŶU$ &C,kx#_ni"= (7TAABIn* dtOJڱ(%g-7Q1)mo_vZ! ]BF"0vy;u`Š:hMFWv+7Kа}ڡ,li2p qeB$I{Aón ;^I-4{啦 `,>a6EXZSUC("7]32\ M5#\쯬fau5H|_;B31[b7(p?4Ҁ^JKL敓eǻfg*.ꐶ)kU1>i!X".yA# {E~V̔Pba3ڧ uMELX,إ;l`kޘ_zT=LOFT`ag΄2\즤*:H@49)R@[x<40e|3u0Ѵ>贊/fÆ#ř;MHpx BaF.zDqF"h"uQ|P*! ‚~|J9Mn۶,Ll|N1Sr9 @N=K"-BxfϞ {ͳO䃻- qa!|(5eP/wln1GpOD0vdK׺tLRR<(ӊ˸}Y8-zQ|FE[\qFVC؆1l!,b$])ɰ,ɠ4 +Nk ˰#Pmox s6;_l=RA7' a[UKblEL"%5LǖkӃ}ֳY6+iԷWF}~t?N$LdFv7ԨOEHi|22 }߂hQi߰AZPSU:)(unyQ=CUHLrV} Zij }h.j'9:V t 2v]aFmZ`e?TR|Eh[.ƂL'Na؛`/*)ֲr}aZHf*%RbȨy;9[3X Rsn83P8iy'Z UAz೼bϐf΢iqc]QYΪ/HCtlܡx:qmaSI @[nΨw +A%*@lnbO_`1ldx6)ʞ}%k&(atzUrȖ9 u76$є>\J`f(иEqʌdTl)4Kؖ, [E?e;D%p\=qv[#IS&V4]ֽ7I98e%!K߀Fժ8D;SЖ]I^@cfᴪ9qHppF[&pG )TR+cĘ8a_bN"ʤS-Ok"=w@an1x`]}sOZD" :aPɏ(ʆݶW.Z>a?w04u\STso%C28صOh* Ve6DfE7c2XFQuD vUܠ-h^>~x#^7xJ#X{-n4f|#ִer/ql/s1>y" ^R5L5#J(s14RuJtfZ<"񺬳7)|RciGU-STTVܲHԺӃ$! Jl㉙ժ86hP*S2 BNok/)PbA Sۗ.KjWm֮uj9܍z]H (wweF 05"p47 1I0Vql @M݌v~x5Cek%3?.V浥bC@OaFb:/E (=^M`8wo :S hNJc <: 1\W.PllsԵ QL-rЉ,H;T\l2 7^*J޵uՙU" ٯ̈́O9m+QW+\Xewl:mWqVʞMe(Y0tAcp6 sE o47N.;0Ώ#[uNN$L!ہO_ZT2mS`Zlߨ䖑q.kX_1k6NvD Þ\ pK~> w2hA{}hd;"\!ZEA0^o-`ZHyiC ܓ딘` 1zcwX[`L kS}ѮDWБFȽXE!tE&I)DTz]f" vhs#ҤC5H`B`դy.}E邾2"d\Kr^l2g0Ic0#OЀh(Ћe0Q,wr͊U9s59RsrUg3V@ V@ic>H7odǹcS HWafwη#δqH!*I1qq֮A4$P!GfG2-b\bsloMCo`#ˆ Դ0@k>&lX} (=P-Nf+i3ib1Z[@}dMA4 !܍ w u䃕 ǺGHd֋ޕ"~[Sf[cZeCVN0 10KlLZC1EEkxWt=n9jZ8QHJ4fPuk]\:XͲ /bOs([HŜ: &3!#KM:=}21G@qHРD A5-)KY+6nf7?-3􃴖<b X}8 *-Vpw+S+=Q.C58]mkd@To( Z[j>R4e'A!+H:dz@ fvӿX5K]4MSh~% fQq܅&]zp]PD fi'rKl[JϫfAcdǟdøBi.)a.{84àdz8a(;Ґt.OgmBn"YRJI (XU=֥-$,do_'+-r!wiưJɨ}Y) HIt ;n4A'8Q9 ǢlZ1}v':0 F0mo"\;UX&z @J#u/UBRHZtp Fߌs_sѷFZ>dW OL{`6ɏUΗ.6<)(0wA0_,Cx&Qgq':Bj^is@$,75bB> sZK2wGr_m -YN*Yzz$YsP71Ly ƾ>ކ:L0-OMy.ҕg4h;,U |=6Xv79.L knL `kcaBzz9:nql ތdklƒ pA!.f C0<,<70x=Rw 0ʄ6e"FfĘy[ s4+() l Nו 0vrr(_'n`abހ]M2kGI<HgE*rUCbZ:is834#gB2(+3|i[/nGC`zYI:Qm)(o>d\44>oDAAvVg}|'AA51NdܧoE <ÌF5.CN7b+v=7 Y^&">s;ӺE T/xS?lh2.^ N3tnچ[˲':̢(,1ĩ ɸ{|bON=uɒ`!bւmP9dtr/<8G+z^Og,,&g>EP?SV2 FTF*FoVdS$!7hV]H)٬MjxxQzk ci[שDJ[тFzrd_]3\ÛW gvxT ζ7-5 m],.{E3jl~cP3&)̘||Zѳ(6fQCT 7E!yZV9']dt>#(mLHt]p4AQQZPhS82FTOuH(:7ځ>1B9\:j;J>+JfZGj +ȑUD Xh6qዟ'E%W>gy0̩|gɆVVk 3ڒ{F7FRpKhX{ŶgQ6 #TFE8"'X%*f]'/Q6ya(hso?ܧ*H^#ZϑYbFGhIVl<{; ʉv%Ήۄ]g`?d@168J%6F+H?:+r>(U,v}F0[۷6:#p;7aڱ??YW07 JsenݥzPjh!B=}g*p$<8U7*u66} fѯ g@DotGP%_k]WQ ڙϫi<^B!ƴ'b#8eU YkS1هqHX^Eu`  {S, )_$\!E䮙$M~4+־}>ۿ7שZJ` 'ES+t% ɦɹ;8E丑'DgfRWoMV:|ܦ?@T#.!8 N_XtOaV1WO4Nin)XUMu_qlgMdlj"'c[ň՝"h~*V.&8ja x$QʄX0Z](zFro4f{Q Vm@  pew.|-J4@R5\l-u l͗XFӐ.}Gz911P0kZ`V4Z?8Zyapk6htǴ5:p҆a-u<*#5*cv)tY+a0'z)< }~H`]Ks=nlSnjNV=N18Jhx Uc/'B؁CŴ7<40NB{ w% v} Fbd/uZ~ebP&ѳi? *=S.@Kg>|ٓtDAۗ?\y e?Q'0Ív_J?)j;O PPQ]YH Fohla<~9~o7)MUfEamEx8#Fc ^^~P%zzp7aܱD+ {})=)sjd%Fz Ah``lg]?K=`wLj,Zf^Pʁ XJOA69px*Q m[wΎקM(AR?$$_w?Z:\kxq\_bVnV&%'}⌀:.2i)8 KXN3"B;w3:lڛW<9YݮR Yrnx5z^gΜ@]&ŖPu xؼ&oD/S&8L v t8\]ʥɎV] ɣ) DC+L]RuKJwW vܮ6wP6qۑmP!Q~C9YHY%=ipczs) kzZR$slEk%^C77zJ.ʮU;a-wRڜvEcmncoz]3mdT} Y<~_8plĄFf\,Kso:7 A-5:fl0ّRxx0zMc 1QBfI<3 :ѻop9Wnj(3:YzOQ_\G\畹X_П^ȹ)BsP=zT./?V. M`x:AG=mؙ5шu'>ʸppTg 7ȿhE#yS<$/%^i?/*OT4!{#Y0*Q!2͆zt1G)vfɥa / `DEP0321 4UqCr3@+4TuJ玤܈5}<nL~Dڷ;A#"8PeQs L0Q:w0]9'D~^Ҧpݔ@ֻ-Bŋ(h9Rsd!~6vn /0H@|X u^y:ˑ!i26X*xvZO%~(OH؎36xXWF7ћ%ixг:v qUS/xI7P):NxG7z@ z*>zP~^9:<(ԋy#@n\~Ü)L^.(͒мiRgv3̧i.$": zF?Vg+U1Qa( JC,CrڻZ66'\dQJg9m(힙] WLkl&0VX0ch@D+MpOHSU`a ̀Y!"Vϟ (k%Eu啝K;..>s6_$ҋe Wm,bRA V{/|6M@bK׈e& >+ڔxUB rjhTzڱHVw6"z3ȒRDq `8r;L 4 =ll)=Ljbd`n5  l`k'x~z3zM|{`ɵ(2w5 dHZuR.vE,Pk-'J09̪4 7ysϒZ-N9)g[Z6\gg3~fMXa=l,a, ;̎Gm0[*G0[0k: :=;Φgo^Z>lIqqZ#ձwK@@h=[:fh8>ny}5mhȉ4:xJac( ~\ɵunEE:(A Y[\%hp60a;dݾ`ZOpό[ljl=.:wz2'qF[yWl9]z(zaCtS~ ZlnL:9к2Cz /:u:YA6?5ib^~ y`q`릞Q8oz_& 6^,ֵ%fpTS,;:)>hgFZn'F@בult^/,|] VVut]?opl}'N;nc';__ /Qkӷ;y s?7g~^~̺;Txb}Iwwnco]w;zS ngh: Tѣlg\u: `7& n²S'f aw[7C0/Րh u$ ,>&d;`Y0S7,.e=;0G 2Nik5\BɼǪ-0`YlwUxd I(l[]aZh3>nԝ]H7I{Ay׸_A]lF.Vx*M{zڜ ԕR?:WA#"w=]-n}}p(GQ7 #5!qc>I&\):s^Wyd73 *{}]^LY8:kA9^tXlU Pp!CY7!4)uh ~@OR#[lԠch1Ͳ=UrRJ ׺jy%Yvɽ_7{)J4]i`S/1ٶpF}cߍ>Ve*i/mA6<ܙ &a61M6_׏cJ[$_sqf}L'5K$ b | hF}Wȓ{8yؓ@,װo [vVr4 $ XEFO}H" $&eZĉert1G,* l6MK4)cnRuٟJLA?oF#B=ernf׫3O!Uݺ\<˃g AEu3 bWrpk O%ta6A U22Z_ztN7cȿօBºp/+[lA+[Z\5*^@F~h)K0HX7tMs7jhF΄ Reop4!t#~CG;8}QXpӛߢN?g_kϘ'pyS}/iuAa Wt-idfk>OKn8+Pc;Bv'`3D8c7?1j߀ m$ƨ) Qnuy`Q9 :=@{z>!jY5 jQgNH=g#4D Q|g11₨z?邨\g;woo9Zm-8}3wp3.ĩAUAu$ NIA:nliRNv" 8mWo?1ശ ~~#@ fNjN~tަ&hoz '|Ebo3U8:ƙ(o<_dh冧ןg3|N7]*:\Er{5b`$rzL >=_m&n76K0}S ܳv9mWޓ \ si}~ { T)eIЉr+5i5Ӵ\B:0?a: (r?vN-m>2U0*D&@: PhRiY4X!14}^S%}$b`N$AwDV"86XߕL&/ F+ 3Q:1 [4% KS , U1RP*_?%Rκwғ3<{4E9azA׊MΣ Y '̈mS/Źf4޾#e,4wN^ZJLvܩ+f> EEOd'3[o(FˣKNoa_0yNv?P:1}n\ $4RByt{z=-H뙙o-l F] >Daz1`5'9E~>vDN"o${:p /-9|(9O+]wn?/.ԎPJQa 㢶Bƀ_R48X :c#Ӎ:hO0;>u?Mr7|Bu]%y՜0ᾒ}"]Jx| &Q06w8vh,S0a> 7ï,yNzj8Ͱw*3 =#+-CvmA Iw\RpA=t`M$Ɵqp·5ӯ:` 5,-ѡgZ(q{N9<\g)̐yQŃBp8 +_Z7i38 r(>wɆ3˞A7 4,iR8n1Z1[.>N:PԆ:-3]&?}z?_EI K"̲Bfd-0K_ɆFp y69A|msc)^חDC&ߥ@|G<)TяDeYxqB o S$:;ɃhxJtQEXL#۠G1NDfKg5Q@mGz+N^ 7@YKD/opw*g€&l)-^QZ2buH!I1KM!8ȘGa plވ~6d(_@y}ɓ1sºs-54"ݰ ѼSE˻CSf4ΪOٵVy13|upHd) #oϊ=s,Nzؓz3+nșWyDgsAWѱLd܋[l#p߭Acjc :.|D10s6ZK|0φ"V>Yؚ`sY_ ݦ|M d5g ̲yչ(z@J'\~<Հ\![%iYGN(JE.3:"-Vd;W\ac3;C ߠmEVcvgQyVY`dEhn+L'LNN,(3HN'g&ӊ~M49&+P3l&*H3#"DT 7";AW{xhoF%y`"M&7ADXn^AO[,GC,>tDP3!'"ADbtEБD$D;:J{;2.*}qSkgr"ӧ@I+DP:"x>zmDw4!=]"Tf* n-pkT@"(197{[靾"?W;ω92+VE+@Nt>Kpɵ!| m_ˁ| 59Hb'O ;s{o%|.bzoOlammV& 7c|Vt._u%9Eg4lXI2E^9kׯ6Exys> ZrT+،n>r&?"1m2 rhŌ!p]t <;$jɓ `#WʩJݸߕr:+L4;6^ݓ9oid2~F;urmI6_kb$͛d@&{3~/eo6h0SnKٜTZo4n:ڰ\ɉ `KJ q1Pd|S ruj+ųKgs'gLj:+1Nltl_JwjPo:?|/jvXW_4ܐS8`R^@C%}df2OcT~ܭ%wg1_ t%%$kz=}"щ+i,g&NϱSz7ql&jvlPpkFij31DZu $19dd=x8T{D(05dS 2p (dy]qx%JBG1s`(=/#U @ )mÅsО0*&G0~u=Q@f v; e%E814(n"WEiQd&0p[dlL9 Ym"FSžjʈz:m@<FS&]=uÔbXdp+?= $22QV>C^ /yw3dh/j,=j6PϾ3{>c6 CJWpT=B7$L&s%]&ԡpRyǪ!1wq!aw=[J<Ѕ nJ:/nL_s==Kb"JVN g5QJ[$gn:͏Aɝ)c  Zߨ_Pv==f4 a8!Y=HNpK d<"#r0bD<;Ɂfʄx,h;11p3uxBJL<2%x~ӷ/iOAAhCXu-06$aNbiǾp6Hlk㵘H mokO HYn<WaͳDg!֯6pa,Vd=GMCz$^pT/YN~.FbE]15%?E! ]aX9au1e!2is!R-f˄aô'ô땛YeLW W75hJb1Cd&Yq0$d/Jfó)MM@\>vP `;vnψ1~\{ibq%{"L~2K=몵r/ >ַSc" }m ]3sS'|{6iKKh4Ŷ`Ϩ;D{>!W }A0tN= ;ʡm}=ftؓۏxP傎i0L|6Iv,u;[+@N.ަm4-Y۠F u^?vȓP7(.(}tA-4_1j!<~.UNYAvkw{{ ](* km !c9)YCN 1K*JhUt'܇ <M - Jo`7̜:o8T̠^6U8ގS`FmZV%4^)+M!xCn"c-, ;#})B=7ZĘjc(`^zFI M@RO'Q:w#+lvʞgyBʫ(o^,)aū=D` @2e[+IE:Ԟt6Lox&kޠRbV3] qW%C7Y+hc9{GF\"ᖽ2C)<]º/Bd I],5h{q-9Hkg5 XU$!HC?|=>/zW7sDc\ ,,(mˉDoI9M1ylܼxfGAjЦS_]nkro,DibPqPC"퇍M CvAS*dB:ȼ7TFxQq9)؅+5Tҗ"ʀ*"ĤVaN~JçP t'+ŐS^i1/;++!si+JVSX )Dfr Y1ds_}5UCZ@ GN?݅0RX5$C!RjȡPϪ!%(T 饉jȺv"y0G4ĐB d &|TC 6!G}kCnEФKL!շMͰP! "EDcn 7dB)TYbB;z=hVWzHɗMeFzH7 r>Vi &oaw22|m;{Rsj x*"OO`h֕`7G<ޅVȝJK(,Џj&%OjF*ϼU9[zI_is\\MCOWm }VfFC OIUm\*xƫܵmz>Y)&8dF+`P[Kfus ] ١ApP )]D%W#`hZҿSf3@PVލh,34m=4\.K(;ZG1&Pn=ʵZټ 5)X4i^6߱RxkT"7q u禨քr(h /ohLr+ g|kuk%߶1*^O[@|Q*0EG0mAP* U L6.yS6tiFnJ1x+MF˽%*cpźF`%*dc iVWyUeK(].}&K;0T~ #87dȔ*AT١]ajO47/RO xp"CͱL0KrND.J]|ZbEqmohBLEo=a-T2Ws ,TH4"VHEĖZ dE@:"!Tݎ2"1XnBl*"TA!!E6VE$y* `T Պ-POo;“SE!YzEMiTH;cuW u ;^Wq I;-^%qAed-$ݳ\ - Tgl^j ˉq1,'&-03KU*_,fFK:FO0,$,;ݳk/adX#Υh!b[N[YAg-U׋]k0RxIW!d  :=%z-Mƹc[(JI+dTRj>?x%Dj4_Pb&YЩŀ\J61QJ/fP+;VwL45ꈃ.Nɳj<[+#[ fBE}AWLV)$F9e)$Ờbjڸ4 )&}LW܉bJNm!;oeCYI*oO"2,iPIGy5mj,jv\Q[*9lBͨ /a v{j2<+f=] -3/(騲 )mvB^\E1I4nM҂W],<~Z,. QȪ7,NLF3бY٠Kowg|;҂m:Ƽdzܞ.L`h{ d)8s 1FdɊ 5[ 4VC@ɋ,ߕg+nC r }if I) AelrØ?(jp7w}GE?0¸8jdB2J` 47ukA0f#a"tfuD"0 ԋQFQpKhfH[{CdY.VI}*`Mnd9 Cqiw l.RI}S`so`햆na6WwfwMfk{zZ!QfhoWw7D3R7S>$nW{2~Ң 6zr gJw ({PXSg@W{ِ Ts6|r ,Gg@]Vwx \)0Z3G_*S5Ï\0҄.9p V|Q B2J0Yp 8҆S r"pu .oho OhMF'R%I հ[RxZ{)ЁF*Hn֯&=eEؐ15!oH*'eC*ДH*``< "f #7=P,V+8 (B@ hY:$e*0@580x1_VmdԹb0c`"!c .FN71 .@QwS$jUQFrPpّF̣r(*z%+,!JS Fw;v8ئ(ㅤq,AwP YqG!EM6(/r7 ^ W)C>mJup F_P ($T@E}>SWwJXvq HX!jp !N]ʚdҬFlG^댱@w0^,5M',oJ$ gm E$@'x 㞿u&J! .TDLuFTzDeL dVs~ҵ<)eM;|sq%%V^߇3##\!@YZAr-kYԐ,~\( >۱*,c9sl.?QkQdBF{/{qZ?DoǙGoCl6 ]7\{gO4@ԎNSlqff0>.h X6:'t)Btۼu]=6iq4h\Zt{jʾF h1 %5G@`uzd4{cT<[%G ܳA mzt. ̐x:ѪS}TH(-/ۚNL@MZKZDsbA&6]o nFn2mcϾ #U`9r~TVǮq=Do)AT .`kw2m45ۯ.C1UIEvIT#:hn2hnrރ1%F}a@q$HghJ\L*ؓ9XN`ۘP+e:b`җ5߁E64P:sA@pl .aaA +D)z}^^IXfQV#+ V DYQ%mB TmLvϵUF#BVUm7ӀER'&8iM@б00\|M(x\pd\9)[o]cg@،Vƶ*V @Ij}`cDU]c,С,mbq$+p; 6 p r!l XhfEXXCv&QQ|d!*62Z/x_jSucޡ{J v,&v٢0q}'"~(5ޭmLCOb41D@8]6Z@62%T/͆ UњJ=3_ PhDQSG!EF!RAڗPL6ߔQjm̩=]mM{x(0SgOzEAJ{^pű_-DȚ !)c"Sx Mb(Fh4rhW3LZHs`3T >{EC1.QG2Wd =Rdwc/3 { DC m7@5M x`̔l 'H$S醆鞑W2.UfL~06_o+}+9k H)GC\ԍ\0RZ/\I(Qjh(]0֓l V+H!f3V-jg3MorV0ZuhL=Uvj~B x=(.ДX&Z)(2~DbH0 =E1d$6Yػd>jVZͪqV}EZ 0zQ!| [ ?! E[%rڂ2.QʞwrGMtFcyf{A$/V@NeBC &T8bFquURAl@7WCĄYT, +I1`O[iظrUEAG,znvh`pAH2z&@6Bp U͂j@P.TTTlb ɻ-!ƑB;dL.BɁ%&=^-di+| QORN' #8$GEaJ\ T Ŗo>-\.=!9+it8 XUduwj+*6)p*Q$t 9[J)#ه @Ȉm)H~we>iH{ʇY'dMšS0LkqN*-Dp*xٌmO%1E;2saP0AL_VO} gfGGboHu& r e$ "5%Xp+b?b<4Z쎗&2#M W&D1d,aǚI[q#NM`EUqxxaúzQ0{+QTE" Tn^%ĕ#SPbGbɨ8%:XU TkJ/DAe#ҹ6 2/sXp`QdJ0'ȯ6q9n+`lHrOB ?B9X` q+ X=?& qkW)76^,d R PEDL'6sAA8O"H;a7T}',=M[j.Gy4V, /GpہTRw$T5uFزUU75QnwCFΓ^kM F%9U\B3 '~ZE,ZMTDTUN{=f֌S(/kVW ]J)3GSk{JL#30 .3pٛE4H8 W@[l."v LE.D }:  oT6Njr23I,aO I$`"(2j!f,P7zSQTCxѫUСnDUDf.J!gPU3Wzd+j}GU]&U՗<WU#~+Xp-Ja7$  *B81bHQt7W442@9̈IIZ8p8&l?b$\Li`x]rȊ%F$39C;RPr3 cٯt2zK{/\6$EYC(dğL>R֪-xS{c q۟W^󣬜|/ 8\qZHmE`.Grk rbdZnGyՎ*$+p$)iQUhUޘ!+ _״zNLG!&D cn$S x"%]R^ImqW2֖R :Jð:^㱖(@"Y',mu%(E[KuS=43u3CEEX>zHLXU3aހ!͙A9 Ȩ A%Yq9cR_8vߣV-T@yd c!%U (dD23˨KwƎɏ&ŞA7au )P4NW dWВ)0^yO| H0\4l[E26dX_ ԋ+8)OՓ҄)2RɂgZ ))ԇA0&<qjș WQ L9Om%o"e 4*bs4 ё Ym7KCceСpFd0'9G - |^Mx0 4u 4 H'q #K"ݽX:+s5X/[={:=8 J/D V}C\Y[Rvb3C ;ߋ~T_.MUP*x颏)')C$p'#r!z^qK9X/b,"[*ԧ* CD}E6J*qiTIRcV,! 0^ WD7%f`i͉I%Zn64%hfqTZWO(:q >RMk7Bb/Qw:g$?9xxcf'\-]P%l,8 B0ڄ{?dC D7!gh8'˄M&*53[vFFQJhVrx/tW-/).-1$(}SU0ei8q+6zm20+QzRo:+.K}ɂ#Y?ſTe}٨Pucyx{313Q$-V-Mw aX-<8[GEmLpt@bԪj{F|vck(Z J;דW#`XTIMѠd 5ڹG|P@|d_rbfؚ&BV3RjDnГHٕ@BYaw@S 5Fb cd# %FzaM+#z(d|gyG**HG ^" ѫM"BYa'I3E BdDQ ,WT(ŗm/h? QEpjL1{X_,eVIqI(䗸$#3DXyLgķzfã)K1ɀUdȵa ڨX^3 I:憦YqĂwbL"O$-GVNb:Q0$`tYHJι7X{AnXK|#QrK&ś[^㬼J±fU!' !X(ځ aF%3UPhu֯ӥ@D@,\.LPVg %0]7M䧼򌏳;DaK JAV:Ψ(j3nhB,r4j[, R1ѐ!&Z!YĀkU| =rՓ#5*!N*g?qëwRD8XT-I@^;lN8 @"ɸmdwXGJuI@Y HVmz՞l`>)DK z?Ze ZԠ1HCc&+FIwA'e,0+ݑT-HGuQ`]*SU-bE-*M*;LgՈS%?:"H.T1΁L\o" `Dsy1uXlj Q@XLLz0*`Ahc^w$b{k UΚ5nvUɷ*a̴E'l RiBЉy\5@MĠX[;-!vbr's Iv"͓mMuSLuka5Ao+!r:dQ7¯}xt? \E%ZCWFVʪs ^\]`.̎9:9fVY]ԓrUtV^ FSb #P({2]vaC/Ș@a= H@/;Sak':B"R]!Qb-!DLMX`IFN ٬[ W1*Q9HSHʫ 8@ UDG8haHp-;;R U;Az21;YWYE@u(`1!@㙯?3 0XPU&*]Je׊*4I&FEr$'t6SoM9K"aA`|3L`!*lͶ̌ǁeVG8ҏr F&K+K]`dFBoo ]ApQ@F(8t|'+2):]7'$Br"˂gֿ5[#IYKg}vb;,̈́1QC`kFf&!E1Gm+/S~^4 D0d , qa01vԓ 7pU|`% !ׁ;fQϯ 1(PPlx CH i}UK<E69XC|xh4Bv (ghEn^Dӕm(< > *cE|lOQ;~8aMo0&c6m;zԬ ͐Yذb|%]gc{EޫURG 6{#hZ .jpJkw ds] ?pH;mu$ Õpc2a {Itq=48mC$1UiGǡKY+rf)t C<^ȗfsEП#eL@#V Gt&7bq]ґi1ϲEu<s; ص`yGHQ3d4ǽZrh2Ix=k1ɫu>8\I+^?<3@ N0 JWF۱?x>\x+ho&,|mL[>Xv/nr] b~i i7~ (ri|13l֧383qv`u^7M#sdLJ.m~B׏;uly*O?8m>j; l.3:`;E98m綍Ðv^.A3Wm๝qGhRn̨Y"*Xm:"i a?GTv8L 繨AGz*S~#Ցcsdf0 n$uV;cEhQئWCH\߃("̔8#skD_OpTmȨ;9Ϗ=hKנv +j\<Ͼmmj9}ǥxh|17OfisQ}L d^@G~uZey-Yj٫(,2rx!8n"2 >wÏ]d#qT<~G|68iGe##3Wǃf<7sV*:EYt-_εee=T/V =d12_iNY3ae<&Q1=|/՛w~8ח~.mw䇓W1ֶ8>_m.@+\\?+_xr+._oWz|񫯾U~Ǘ]W_U[_~Vf;Ȩ词x}]_h6A[y ]}Y{wð즻ν;zsGQ9d9ں՗'g._M? [mpjjS"޽99>}s|m-5t_-W/i?:{w//_ tt8wٻmMkOw5eyq)~6 Z6:bzvs 6;ex|qqw/~l2^iem?~?~;e[2бcsb.r\H7=v,+|Տ}D/oOC叿|^?4]uTNrS,bə֪$Mqn}>(n-j<2n'C>t#~ ֿ??\}y7vק1wǧm~|u4X?ev|f3bk(Nv|r͉]S{]ݚ_r*"kV\E}TϐE۬ۄQC`OpH$s(f:jɂZS!|m7,7ur~_4㳣M+?]~*[ ?_^. ߿\bſ/^~㷿[4ŋ_,~q]^ՏoN!^GXmu|훭V_<_wOmO M-yſg5 0.~S3/֍*fS>bt?e6&7||FlDٻ_o|o^4;**0&r;=^}?\t6|-Ŏ"X?V}fw7`rO,$ Xo:,Q$+oNlпEy US{5V͗}t]QЖA g-d촳`6P|e'8!bLWMxPۆ%>WtZG$G Mo"@ͧ`rp̽pŀ].[|b0B[-\k_a XyEdtjaE1[W!LC.XzUrkEm10`61.LkA 1 ^n'(;*g/@Bvi2gm e'<>[!LN), MRي ~;/t֔DsqhIN潗[#iS>)w0j2e9t@}"0L_nnWk%/ȟ£߂٫bN0W%1࢟l=Icmbuuom2spZ3R@""R4y豬QT3Mt޲EY-=ڽV{SotcK_ĉFi^R$zv.sTC2U$ r}~C& y&ĺ↫i7[K{LpqiWwvnbڙPe+CM7Cy^MUHI|n&k&5xQT95#/2ˮrvIeȔQ,V(? #o$f:RjDk *2d&Yu6 OB[!aLԢI&m,k0PD@-LTAޡ D*p]Lp,jrڅq L6ܒ2?6XXx9ji/l]TJmFTI1I6Zw]g>YT.kCU7wcv^Nz}zIp5`u9e%Xmu(_R{9EY| SPbl%m炛&kڌk)µ8966GzL=BS/$- X +;҄?_g42Qރ1T42jC7I*+;VtƠ@l<$DdžC(?(DTw)b"CW;lxN2Z3Ԣ)VC {R#>7H!rhҷlTWJjXKт?;y"5G}gxt48^2\tE$495x ^O?njgeuUKyay"N KI%@}KNe;]•0ZKpSd*tT, )4%UDn4}q"eKqd-v8ChB? ա8à(-N4h7^wd{UaYk"Pzf[B5魪={Uk*Y~yD/5 Ipţ˲ei}J+rjZjU{dI$`n_jhrn!V $%@u־4rT"YM!Ũ4j7Kk7d-\ƌDs)Z'G ʦ<&VF7cOh1Dg6u7[vH}ފCON:щ.KP@>2,bV+t qL+1wP@u wf94;GlF5oovEQr UDI(u)5&T~ӒIEA\DՅ۸u1`̶('h2X⿮05Xmd]7 p'`^QB@ݸ".`[LA\ŶurkbzKH).rdCHUj.¹WErdj@ zT4| p'F;J5-"[z$"@ӡsƧ&h.R)%l:s̷UvH@£lx|;sbL/gt$RJZ;)l%~wl@zeZÜ^i~G Cw2 :kzL-hFgI[ BE', 3`g[ mZūeiW*7byvҽ@\hIHidY4&IIn Ͳ6)}§4m!ӾRnޠnt^ ThOROOvÒB`N]xl{$f7rc(+)cSF1)L89CJ >A1ikϧoō9> KX =f`$4uso ~\INl W&xSV#Xe-o4f*' |Yp;r$*rRXNYVrnz/܌o3FM&oIhiȝqԣQtr+\[\m=Pגudtk>yN8 ˙SDT6^\1, ߜZ6'se5,oM-U K-2r01-:܌ ~A8!L%}f M'z}B=W=&BzlUacq\a'L&jL{HXm%fL? F%?V]e㷎)Yڄ{wfʛx]kQ\R|m/mjjulJ/9H&7ѽ㽤@S㊍YB]gH#g=G堜͎cZp6 sԿsF  8/ia*nؤ̌J0gK ѝx^rQjyy!eFl]EF$~Ex}j:rK8~2e797\dQ_K:}3RЫawfjz s*P4:3gFȔ,fQ=fS5j^+Z3~̏jl(FMWE1Ny{o9KLITtE,hoh$ oKN^IEi oo}W5 G WgFĢVh"<&;ye|\P%Ojv}l{X31t9'urtDlQ#FM&5m&5ͤM 4T &I-TXYB,3Yw0kl<%TGuT*P;lLc Г #̚kIfN(Y٨ /G`6k5QsrPfp0j2UNh-V*L\(+ |3#j <3 +a& {gDvnEdaUn$rXVE=`SBh7[Y{l)oͅFa>EsUfuo$&=-%^hVYfڷR| C}x~zg*T ێU GN%:8 l^JQ\9L(n̏%hXc,<^ӽ8 +l`^,&{q;ދq܋m8;TRZt}Z@8z'f.l3a###>z0Rz]1{TJa ='C4|s[d>(b{1"KיϾ,+\ha9ۈ,i%Se4񍨓d ނa&$ [C"ꛩ@@S?|RӋ/4W|s7ǧH*s_>^|$p>~,+)zo޹|'GF<'>S#k:y;&t@ B!7Ѭ~BW Y$O.nbE|?dk7e?h }v%kkǮvoNXC;W?kG:x+|xn}{X5!ѕׯW_\WU׸n[b\bv=ٽEtX_ v+ї~ד=0KjL:ՐO6Փo WG?6uڵ-z//ˋ>L~dʏ~oñCȏ}yuO.?mÞ@EsǞgNq_Kn&E\v ~Ibl^~G>ټ>'='9Pf6 S< VS w\I`Y߉{wǘy̝l;>eGQ30)"׌_5ޙݒ%"Yv:f;dIxIQ>C&dz io#;=!:!O.Cp0)G׌&If_mX̾2:5D=nJy^; dnvԞt"d-Rw9As6SIȄ{j0jfG H~"20Y2eάIl=ʡ}yoOḫ>Ȝbۣ(yGpݷ>>V'v߄. B+9wFJЮ+3qh>`̀}}kU$JAWK7lU7M93V*<"y81Ԣcv(>fzbT G+ 1h \l܉zL<@nڭ=Li{_lyӚ"12קm>mX]O%d)d$QT2e5|*ݝg#lHUݕDȺ+{6מݏ!s>Ǘ/Sc>d>?1}~uf.ն஥+' w>Lin/[fjL YB'Ȏ&=f'lNz;E“'Nz&Csb\oETEo uiS@u'4O~n\>"'&+MfDIvW tݜ;HaQޮUAE32>]2' Jfh>8j۷/ovqJʇ{K^h;xҫώ/NVv;+)TƆߥ2ͩ<^Y_WoO.׏9~tA,·+˹mCg?xx };G:6ǁ{ۇ]_ٜ< 7߿DItKO}N/> VS([IË"Ǔ30.{$nm"s=?;xnt? KC~Vq+q 3]mS+%|zsx0?}D9`և|`qk36McәݺKh1gtСj{r>vwO}+ZyWm]5n:rvO)6]\c֞ 7)vt`y>߳n`nxv7Wa與n)/.w'}ob#Y(]Cח'+?-~]sgm/!vuH+ãw٠ei>c ޻u|NLs,,A>8 #c~N{af8Ǿa.];=;[׽31_@P]{}c}yb՗ ;[QG?Hk :UAʾ)()G %SӮkt\tWA6C ]q.YPdE#Hw?yw鱁_WoyP}m7ܾe|KBCNP_V6A|iΎ}'k7KNw?Wߏqŭ ڷQ8wO Vn*j]s|`P}/gXIƿn..u۫USY'?^' F#.RBo~|w 1!Ƈ OaS"wU7D=u+g7\0~I :89?mxzwhO}+:4H:U{担kM>DͰxn7!zRs Or yN:gۯkWѰc9<0:qv4 Mv44WSJ:Bnn~a܅&BMy]Kl9g1wɒ~˕}ni@<_u\UOw=Kسꝱf|3Kn|~dn"d~tvx `1@flf 2Ҷ5z08*TYFÓƬ_tEAOmmKy>,y{5^0'vx^zPC'm|qQEl"Ĩ`]7Flu';k wS\qP=0ks7ș0qպ&|0y E0 23Mz|,iOl@=>M|I% `PF//]g~hvu R0738.Nw\=Gʯ}Wfo~I{m34UF thpg q; XЬ.ֵ <=8 ]fA %ýPaLOT. ?̻C wŻhvA9 = wFg,/uDps(:˿|fu *s\WZ|~vǓ>yc{U?QܺЮ}Oo;'nx-2w3xPUɖ[Ζz^C^Mhtx4W> GO}b4M4ukw]wd`=s殃W~s XS:t{"*~ns7;۾|A;}؅ttj*O]7M|`wE>i7=>n:̯n:}.z>ŭbB!n {b6V%B3nzi[U|&{=71wyF*k]{ܧU}ȫ=uyj Chg?"uO\ Q Jv-6ף?u* d;PQzQ\ q /1B|Z1o!6TY[,§#[f ή~8 _箮Q'*:vsԝszjwgax35owMU;\vMizRdn³W 6yJkd؃y^)g1wɒeZw8fZ)5wgGZ7Z(c>EI\]l>K}8f:N~]uYtgvnG= ~f Iۿ1fZt)=/xGM{}iV^"pP.viC6FMFF#&Xť=W8=*ڣubuyݧ^=%퇦4\~G0*̽iy+=jG<]0wsMA}o&9t&~G#[?!-<\fwrVBi,(:==?3:9@+׭ZA>|>fEh\]P*Ï"@.a'}hpc}vB.L7x׶wjԃn<Q-Vc)KKZO$[\z9Aj{?vwǾZy)^A񽑩uF72{S+Wئw5fxA C;%=s 3{YS b߁,.c n]|7 =AeFg y~G ?۾mv(0~=S]t:+\ӌ,>|U4@Q}N!rwU)_סU`1 LqrJShqs~ 0`|^:XM}98{}'#U[⺹(Y!:/Nozk|D.tܟ;? @[gk:)J,wu"otuw?N9(>lȦN\ݦk-|Iqs7)=@"G[9x݈~sU++m[\ks7⃕"s7J/#12gжGQ2gѶ|ه;l{b-Y k3]Hc}2jXB:P|خ&Ҙ\K5=J/c{Bkdv Gfm{4{%˶;x[yZ-[.Av=!hȃ̎'k{6O=@h="Vdڀ{ܣ %!}uM=ɏ/c>䘑{3qkjRyc|b,I,xpkBKH5怃5{h#":TMO[ x(Zߛ,qպ%ng.YAʐ97&ўsYܶȳM05^8NvY%5U٥$5%Mi4>&Hyō\o\$`xovFMzhn<ޛݺ2p1% n۠ɪrkY-* Q ƕmٰŗ3e\Kyv83HHyǮaw \ĘGz@*~sFN)nZ!PIh=G)Ӛj[@6 *E, 5ܨUA@yǮUY3a fW볪^gprgov_i}||9==Yeܗo^vCpߊZGO[R+O/ߊ˾p׷ւ@L4,EV{~ <˯= |-|53$GNqL癘#ź%PYnLOaa)˟s/oO̿f ]e?̑c`} mG8BPU%cCjͫ}9A5[T _$Izqg>oeBğB`Uudy&>ox޺(Q+=oQ=9+h14S#gy19S6nm1ioTz7Apk63ٝQ$Q 59rAKc^GBXwگKd9(S`| AwUg 3u7 $Ozp qZcjWShc}O{-Nd!+ @ċ[Fb2^S3LͰ̋fbfo*F\p bLKrɶsfǼQ}Oi} Dc^LdzstBt%,\JHa] Qu@ Rֆ=][ *G ,3! ɕvG ړN%F I`6b8Xgwpmjr΄:>>I-o!ύ.^"\AUQ|fF"Ȳ&=qHE EonRH, mUs&"5v,Pʱ[D+zdHnydSRUlFI݊ةew#f"|bg~޺l#JLscyZd9m6&q4j#z_:-G§95`r^Zv'XT %A,Pjn uAI of[zc1,*9&u9]'[> h< X'\e˪@gSMj5G\6,t3K)Uc bT!0bY{8}q [nl" s6i+l7w]Ö=w+B/V-Z6GX!tp|p]`.aIi/!_jd9hq\5ǽ9)e*}NV4P@: Jd%G3Flr̲m)*A#FLlh<wMN*iKǹQ5v<^:Zk>8aA>р#Y #$go| 7l3@9ހM0B[ %d`2ɜt5Q𽊻B4!;R,A3U="3K=I)4YS7aM!MZEH1){bvM%JtE㣤0#-Y0D a"" W`^ lF? 2u󈆍da :2vFm:B ˚+ G4ҒC! b?x[IPK 8Dkm)/] Wahrsager.inon@~9WT >ZѦQ*%ۣVm ]HZ"fo~;;f"Fl晐-+3*HvUO 9Ą\*pW 5KWwJhG$$ J1E]JFa ȾI:͛hgA<%)"ؼ ߆~8~9{i@Rk;Ϥ[XAf#jXM:2ϹMsR妹C )4]A1`48z k7@O/W`(j(ECt|3 ܳ_&Ѐi)iɾKOeZf&u]*. b %d^~ mF#ٔSJVH6SRљTdW(^^2uZ48z^\sɋԠ_l_:Sd/_];NQ'wZRg%_}&S귡8lJť|R~ hjǺHsI ʥIf̛_&PH'rY: MoWx)IT`Yeh9匬{O0*Mr =N$Q qڋfoΐ_\v V !E^>4|t/4M5 1!_v0'!o/`j1w۹$&s%Ț!!.ֶ 9m%ULi_0OCgRdTjFb JIg9# [_ ћdv8/ye*Ay/DH-63G:p:٦DKܱ&CPgbM%s(V;D0m &JWIIEFK2?6QMWdLENHU ꑱ:Va2mɢ:Uy+ɅS5{(E"}aA6v%T6TfR/s\ G\ƍ"]d̩&Mf>-bѳ)Ka( .z"NI߭EF~()CAd'_=M ꭧS\LrJ#39v3P\,o8Fs:wZn̻3S(Fd޶2͞&:Cqz 6=49tg?wZkan%e.O$HVHY{_"UW}1z';R6şPKǁxEug6=$part.arduino-shield_r3_two_layer.fzpTQk1 ~߯0~iCa0ǥS}}i_?پdIۅX'O7a[ɔ3kѮ}(ٹv0+ krɑK]K7ɫv^e& B2[|rVM'EvЅ5L|z̆jvTkTs\z?qWLrYpu%&3=u!Kݡq0-{ѥ]g@8S'GQB_uN06Nq269Ҙbi>e--1܋_b`(J!aԃcP]G'— 0;<')a6XO۝\ Q828fM焃XqidhM.$?e+q(ͨv*C'?!.whuڸmOuNLfZ4oCtmYc/a?\9ZYŒ&:@aٝnohɇY:MeS/Y4ZܙӈvEcDъO`Ix$hBc6Csb ڳ]t xX򶍮1:h<~&V&?r?F=.tRMJE_(3ߞA2,<3P%h" ")IoDl*j&#;]]DKFgLPȀ%h&IKTdO:@_8 Jd ^BL*%%E5Ey*tV"\pTfnZH*Xctqws љɊf,^wFbaٔ$GT"o t,p ddu fqd _@ g84I$CI~#&[}SL(tLfftM +K4Di][% Z usLamoeLC'B PGy,yƪ  ¡b[L8k!ل~&&h~)dF#na0< @˪YmX֟lEJxuT,oVYwLef{:o]ÌmE)ytg/oA7Tx|J*V­D2/rCO7\jGíY*lf3|uzjZ6:+az SUd]naîFFqحaW/z*ܛ.8K95rhš]C[/v=Mq+8ra({U8WC{S:5](-4ţSGG/N=M 5GiGl X/ H-c0ҹlIH{?xTkKRzylT:b[2U4>j{V'0N |;s"щRq }_^H'Lv0)IIcSq!e IH`D1A'}!:rH`@K}VֽWsp8)I󱁃 ‰W#Tb>͚{o&=057&vv־_sI`Nf\pJ/Bd:1j4[`FONqn<[`O`Ny66<#nJ#m\bʿőh HiJJq\ʿ1*Q#R2 +tusW:5㚗UlJmMtj]B\2!|k^'T7F(j[bkdvڵB ^,4f!&2{ցD',.I%.5G0ɥ¿1.f_G ܯɣ¿1?tDfV"Rs5T7F?TRs8jRoJ1OY@*}!5AOǺt# t2iVT͑R3ңoMkݖ3) t2iVTqR3ΣoM>H]bV\TqR3oM\w0 'frHX!5c9*ƨrR"4!7DsԌߨqH{4+zC*Eo Q7FeTT!b8Ds ԌDuhVTR3~oF bҿ7蚵q+m\{Fpḕv8[sobӻ+ZHɣY{ռqkmT7+\4n=yOӨ5k֮ƭq5jܚc<Ѭhnhhnh*xyumP&@MA͛h*x,n}.xHdumP>@}]u Sϒ`3n45Gx/~x5ƈlv*ѻ>lZfE z j+j 1- b^WT9JrzWȉŸ=B 9F 9V<BQԫ,WD:?^}z]/Ŵ:V,?PKǁxEmY(H"kpart.Half_breadboard.fzpn]G?'/_=|o?'>8y_7>}vhgpz{On>[zEz}rOZzOOE柳7wٝ_zyg/Ngwח.~ɣO]|rv_gw|y}ݛW ڧqv/|^x?λ;~yyˋ?_v积.uqzWogw~6g~5|Qo6ū//>~/xsxrAW׿r˗~ux#sy9>?nM'ynsl^?ݧ8*z1:Wyg2^=/*~y(޼W/L^1h%~n:ͥn^ٽ^\/ΟW^kyw Q/NOn~?7=8}S{~@_]=(x?7Wzrݛ?G!vgk/em?Ƿ39/SK_K*z_a_Rҿ^>mX׻ͼoO.;/SKK.zaRҿ^>oX~o^)av)y?D/0,=JǹatCCCYJER*}.r]GPhRs">""GJF9949T\0ȡȡ,"E}D Ef)>9.r#rh(r4KatCCCYJE)=E.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29T\RtK>" Ef)>]䒏%CYJE.E#rPhRsKE.\29Sz\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K"}D.R*}.r9eˆ"GJ\.rG䲡,"\l(r4K2]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhRs+E\19T\Jt+>"W Ef)>]䊏CYJED#rPhNu.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,"W\j(r4K"W}DR*}.r5U"GJ\.rG䪡,\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CYJEE#rPhRskE\39T\Ztk>" Ef)>]䚏5CY:"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GJ\.rG亡,"ף\n(r4K"}DR*}.r=u"GtJsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef)>]䆏 CYJEnD#rPhRsEn09T\Ft>"7 Ef9Ů =z' j~rkћ9w8wy#{7 a.tkћ1:w(Lwy#{7 anukћ:wx`wy#{7 avkћq;wtwy#{7 awkћ3^v2lix4LyrxN- i5^ox0 /;^4<Grn~KEoHbx07ݻ} y?FG4l]J?/~~߰`^?)av)KSCQz}g g:R*}>s}fz64KLgzp,3=GggÙNtJ/^3ӋLYJgz>ӋL/3f)>%L/>3tT|3b8iNu>k^}fz54KLgzp,3FgWÙNJ}W^ g:)gz>ӛLo3f)>-Lo>3tT|3f8iRޢ3ӛLY:Lgp,3}DgÙNJ}> g:R*}>G>|f04Kt8̇ZڏУwo0x-z>.~yOrn~?^޼ϔ'{7ϜfC9Ns,< j~΃Ӝ9Oôg<4r09<8y4Lyd<4r09<:y4Lyfc9Ns-< j~ΣӜG9OÔg'րӑ5`yf&Lyf·?έ˃k6aZ3s>5tx X^ jlMR̆wMV̜MV̜6MV̜vMR&x >MV̜ƒfMV̜6ăMV̜)vŃMRx3ƃMV̜=ǃMV̜G6Ƀ.MV̜QvʃVMR=Ns[y<3{9ߝ|4Lyfs;n9iV̜|wr0Cq 8t,X jqpMV̜>8'l´g|Cr<&g<21yt?7aZ;l9iV̜|vr094圧aJ3`sr<'g<3ßN9909t:'-لi599hyN&Lyf99霜dyN&Lyf·?''9,ل?on<{뫋wtUq{͟zrݼ޷͋/h_JnJrגywzu-xz'{$7ps|+py5d5d5d5d5j@j@j@j@j@jՐWC$Y Id5Ր$!IVC$Y Ij˫!KVC,Y YjȒՐ%!KVC,Y yy5P$HVC"Y ee5j(P$HVCjP%JVCd5TjP%JVC]^ my54jh$IVC[Y Md54jh$-d5tj%.Y ]d5tjЗWX^ Cd5 j0VVÐ!Y Cd5 j˫tAP@DuX2": r+C2Ѥ&e82 (eB)#uuR)A JXJQ%DX "WºW:XH,AD 2K%,%Dn "\.a.a/A K%D "bH1AĘ LQ&,D K "g4A$ "MX7MXGM&XD "؄%m6A M&&'D "r’r9A NI'ֱ֭D "wA O'D "uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@Q{_ԔW5e)e͵֔5e)Mٯl(( E"E⒁@Qd(2P(   E"E@q@Qd(2P( E"E@Qdd(2P( E"uuE@Qd(2P\2P( E"E⺁⺁@Qd(2P(.( E"E@q@q@Qd(2P(  E"E@Qdnn(2P( EK"E@Qd(2P\7дnIdIdIdIdi@@@@@@Ӻ~μ|gY.y+_caVXoMow}wֿo!qm\_M{o~ӯIdV)t)9{In޾ 8|F@߅Տ؞>DwovbN}?xQ *9>Dwgj5FPfen-#o$>$wPSvO=>6oq7woo||z؞=>Dw/>Di`jMtm_&BQ#(yȻɳ7zao?rt/|{oWoSr7ͷov]X~I>=lOeoQtwzo4Q }@&?|df˒/ZTG}I_G:y~gw?PKǁxE;=R part.resistor.fzpWk0޿Bl!]3l˺A,Y;Gv}z{{O&1VL&=tDR/&= FGv"\`uZC;pG\)n518:OON4j8D'*dp)WBP\4V[o0<Zù,!\I Փn\IE1i !n5>L%gtG gnzJ}M0 IdJnO=hdy %Q*56%>7 y"La[ dŋg-p/ YIJŴO^aQ 5l8C/gI5LRh7]ɝEj[^j ,rVq#l\OĮRG,^^c"['36Ά*ˁ(%-b{m.mt*V3(Fv9tkSg}OO#5׵&_Q~oq-NC_Y?j%?k@gHpPKǁxEzZ part.Tilt switch.fzpVM0ﯰ|'v%zRWtq |(1l|Pz!似?ϼ`cv2/T1uF2i\||Əh%Z7G>q<:CכM)Fq{IS@W$WObU[Sw>o&̓HH Bi^ޕZȾ<:xa]X0F!OZU>.ji&sda6G xw9J"A\/\~~x_KۢŭdS-_4y:HŐu$(6ˢkٓ" V9M%.%f?2yMla:VEPȧL%iC5I#׌:=T40#X%\w_qgPqnƕ 'CG&J߱nyނmA_,ւ=HoAzzZPKǁxE>6Kz.svg.breadboard.arduino_Uno_Rev3_breadboard.svgkݶ(}{>djox8-;$sKiw,U:-$v~ZII-56 7/^~R8\^ᗷ8???_o|zxg=~<<߯_-t (x>oC?6,C_d,\o>x?~ѯZʊemqqOo|A Í$/n/}|QF痯O«ڻ׿~^>Jh=A z_>?}7]]_^ŏ Kg>?~[C|?_z}?ߟ~~supxׯ-?{qs}?zJzOiV#:a|g_ώ?'}\Q0¾Xzyv}~Nj˄(?S̐]{A/K;Y -豼Gтߨ B+󄖢  l3yUI!8Y(r:_NvYʫnǗ\7?|^U)('ӢQLEYp'JaYt3*<`K|z[rq#\^:a_:aoO8:ş2w"n"r Z$@Ky' +;p$Qnuox^Z<`$!$yIꞶHIi$ 1b.k!F67Is h7V,@!\߈yӝ46-KQcjr5?/u3c[´$,T " A/ oiy៖ - OA쪭=x_D:5okc >:64.:{; ~*?? Mp)=~j2:5ֽ m [KUCkݛgftBtNdg,ITAYޛq2}S!5ֽ +G 8 q"22 =;H7!eķ8WWoܐxmp0~<. o5z! p^Sh(%5J5zc صnMxN):'[g#矨H=ۆ܋Gy7("x'jyZ MS .1QlWMc Xÿ!^aYT,cz&dXܢ  0.) b2 nXJ20I1LDCOD6!cB;Cʬ1d 5Z_`7 C n= 0bm1 Lx`xx! n0< Q a%aa_2@Qt_5t}J׻aFc5(4.G2 z\,҂7p١^YB=Np t`BU#}Z+S\ig'U ~j?׏1>xejb`S}\#eԸWih]KzmyVP;\;!~t ~U ~^)jNw_)r?G<t_ 5ܩ3jO>1^ 4`ܨq#V4붘L 4ܨp a&]p nTs~V)wƷkV 7Aau='k2P& :ڝ-$[de5 VT.{г-Qe(l&ǯ(X<Lp=_.D UP`E¯(cm85ioj `|5_&_Vc]u5$vk0 g*P>j/ZjNw.L`?O<ـ9IcV]faklpgZXqyOAvnMsH9)7@'}<ȱ(rAz5̞{; !h2yvqT\Q?6Xb oe<š)aR 0Cfa!#[H |ݺ7  V {2Dj=~{_|mBo'#tJ/\Wy _o~@ɟ>^/ۗ>CB۹| Bd8y??]8kx[Ѫɧ:oE _'~{?~/&G?'" xX =z4<^Co_BD"!z_/^Gf#kx>/o£"!xz/Gݯ|'ݾ_޾~{A k/xFC(V⨎"YCaB[Qz?O"@g/-zѿH"G{ń?fkCƌxNWpVhq':_z!qRF ƽ$]GtNuuT.)}qK]t=a&(5M]( EדҒ1&GwϒD(W>1RgE+WiWQW>ٽrM&+7QfzDxfT^0fc^yqξpNW>4^=ŎYoontvĔSףڍϜϜrkGb{Jy ?U!$ha8L}j>$ϋ^>>F>F#%$cN,)ؽɸ.'}t2e.Gi@ |(@Geۢ>D.݁^NzL0K"꥛IߴIߨINzЙ V:_k7I6qUN;tZI*f8Q&8nCuȥm. D]KkSuSߟmBwjiԟVOqSlJEݟ*fSQ&8?ˇwt's]҉<-<7t7`g7:۾ _=b]|\>:|ѣJ>z Ξ`>D.ݯ5 \r_zjd:Mbu-79l6`f7:?;$E_`iyfO""Sg`8h?~9AX{wy޿q.F(m;}:}ٍ¢}ڽP֍]\/h"thS8pWϮ?^d_q4; 54i xċ>KU h"$x-1Yx[Ȧ'ƀ6m'9KF2@ȧ9?b!YK,x{ɬ%?!LbY?q&X<`28ȟ}/>EfM #3v,KfMc &3~E,Qf-G/ JC28ft"A1J_O m3]C&HO?7tܨpv{L-}N+w_ZƂy' v͉̀t,596'"ILDɋ?}enA jH;ѸuImD)u!#%6=.6ڭin1ޞ3GںxIc٧Vh /n5{3h58{N8{8{vm-=Vueɳ1K ãkx<{PtL՗K"t4h\_,h^E9#nDBʑ52^/Joaq^8}%ZDmӷ&Ƶ8?](Βksv 9zFV<\"+H\ 9FQ~KDɎ d$!<ۗKX$I/ɀƍP|ŲHrZeYf7wXL,2EL͢}^0&Yd8@cXAPŜm=Bk Ns<īDm<׫/f~~ y;ٗrh, &_ XcQ >s'K1SRNVV 4Ɋ0,&S(\䇓(c *ew𥾽3=\ubj$OǕ-A?=XF-Ie 7;ZIOB'ZD}C\{#/ mv~g,dlIMn4wzBR"tz94>-WɘY'(dA,OkH嘨7Z&^)Möu=&ENu8 TeG{.:EϊvQYK~$9ُI|4]LQ7;D1AtM7)n> M#Ҝ#X? Ys~c 'Nჷ4%ߘkQ>HXWfIƷ5KrM4Kƈ?>|-[iR*wQ9MB}z;SV5xdU |ݣ'}c F,:6 G`>;&#ؐCD,EM_|i*mhr W66w{tfl~..S6t/*fAbB4P&׷~s}/0ZU9}5 $Ml/I!8W'+%8PBKa?cib)%U m(TR wmz:\+K}im!Ƞ c^s5J4,mE?J%-âɑpbu\wZd-#-=%qoO_މ%i|mtDoMMЦk;hvю0FN'bdwIN' TµR]'yz {8//Ǽ'Ivbv"X}|ԣ֣ @uڣPZN-(Ԕ"UGU6( LG1$0ƣD ʣ( c8.K8 wIgy`aKk2`/ ū7!o­IBIP\](gp]oBƛ 2:/ ;Hݏݏ8VIs?iSsR(BAB'y[}YCv$kp\1Lg)Nzt (@lX'A[~~Ҙ~~3,01$1U]eIܵ$v6~_mwVs_Y $#sO̸n2z}t!5hɍ0FkLsoH@~EU_;,&lpQygz3`?8l\\31:#ѣUw$ L#1$0őF %~D@ONX+9Fp?6)4S']N0Εxew+~iw+BLÒwai4O/ݬ^ر{JkB=9okflk5<GV 4`# k-}dVhh|iJ*\Ͷؙ@ls]<-6맟~ivZgt-Ƕd[KƢ|V>~4'ۏGǚ辽|ئ5lpӚ8Ao#Z̫gW|_K9˂9g9G1RrTqq7Gj,5ċ$jo̸q⍟6ى`9UL7y Ww8+8;bi,P#fZě<ר;~x qnsexgtǏċ>34io´Ǐ/''^lƀ-L8h>syYx:x,NیrW<Ό+x|D闩D<! wAXP!r Ax"UBл_,9qhI0I[NloFXH!rB )LŃ T?N⁙g2>c)| }b$AK2F3zJMq&8GFSY( MabN" azm3F3gJ^[=iNl:سf7ںTIqQ4b7q_k9.qb+"g_1N|_/ 8b<cQL8bqJ1N 6qQYq7C-bP" YXC m&Cmllnyl#ⱍȏmcX^~Iٔp#Z9_|y&9"?9Gts_IO0qb9"'5G6ᆋ.?7G.ʉtd刜or$9"?1Gn#cnˑ̹&Y92?+Gv?ӓOqò-.>E2'Gӧ.c<$!eX@,sb ~ef}r"bU閩T<&V1ě- tN0Hn* hXu7[̙W9ᰢmenSʏU}S HV d*?PJ3a*H@B2*?P8ۯ;>kXrB !˝uB[~Y!TN Z1.CBuܿn8b T+|>%*?vPO7vz.@BsxCխt,RAD=|*?xPofϐ:=Afj8t~;7_O~7<ۏ/O|9~"FQ %t+kHBGI|$Nl pXBK-wC JN(|bqΉ#t+[d:?Н8~գ~bA "t+"t~e}W,bqΉ#t+Y#t~q椋:'Э \0(BGE< է5(ï/~z VT/d . m:iAvl\Bq`#u80\qy8auoث,]/o/WvX"Ia`-w@vGK7[׶-'%<4??HKsIۖFwDÝ%6N=gOO:\f_>,?| w+X=̟ ғbwH&+dG}-qs+:L^A,^d+Gi.z!DO7 QTpuaN/W'N.7CB`bw)m`֦CW&JZYEeip洡9B Mm$M#{p(/"ȢZ:QpduԁGeQǬI8::bU =.w#9db5r4B#jjxW0# ; ;~Hύ n^{`"PǪ@Ei rC4pkӈ Q^(JҊnȊ5 Vz",ǫipFTD2D  H ̚nDϊztNu*[xi}Y|a-ʅg XƔ(!XGh`3r̷܀ظ76 F FO*B5 ,x6`hlAlso IھY [߿';6Z3ϱz 3Z9Nvlyc`NO}l;(d?A3r:t#8a_#g6 oI2ǾYQUb?B3eyat$#򓁴oi WW^Q3OX""-ȩ>BaMƁjhXWdjE 9Finv#hDc[@VF atd:Yr#&ՔkH"ZdH xF_@$r tdG7! .+eXAVh 5XGh`F,.|oHG6Sg͋6{ZwfD/sB>uO`B?OF[2wZc~V84\9 ..<|n>sB8{-VwM&Taeel;]SS m h%K6hyhsX_yH 2v>g6^ϸa˜)E 5㺈'"T|о.B,tQ ũZl\]:@0j/,WFbLL2xW;tZp,0]&ʤG_P1[\b9&U;0"!Z:΢͉(1 'Ng;[Nz燮w,MMG﵈2æ'˅"˕#Ց~^,RiF^zSx;$^wr'X8^.ٽݨ˝N~8{-^.jLn䡺Hjd77:?BAGy-T0 1*3d 0 `/ ktb}tSL#i/D2rZr%*npH ܨ ,8!;khNVoƿTPӘ%,JFpGN 0;F=;"q$ QsC0rҒ pʺL5k)%;_`B@RH~d€ \aO^cv5HQmP̸$ap$F` S$Z!Z2r wz]%8PB"̥z&O6o;Zr,>>=O(rJUjLCQ 'M>B,9Yf7IJbpE F%X`7%_j )r%Gā7+'E&3htfUS"d氵2 +̂1iPA ځʼnf`0T9iƎFDcYcuGYT'#kF"Xr5P+UjA2,܂ j(\Kc)$E66@J㾬0gH,-hB{+ͱ͸l+g+&6p܁Pf=pcNDנf[i4Bqy۝FW@5a/-v$ d.0WiUȄjybZXe UhSՃZ3MRNJFe\#h>#Ac ݴ%((QF&)a[}!y:٬씷ú襭dq֜Xre'wM 1PLnD[((V =dSKvE Xӕdؕ]S i68;+A_~-;NXZwnT@G&+~!Up.ZlTh޳ {ԼPڰ@ < M! K,z ;x |.YXYRFA) @gDAP) @ #<:alD-  @I QB1M? LL! *RXv$H$qg6)Bؔ1~ǣتc4-U TS _% 0Ӕ 'z5[ x_s^ؿ; Xi T֘[U;GA+PAR%ƜQ XFBPckmCDP@Ƙ7_@P!j yc5,Z `֙ 2cȆTQҡ1vrH95U:.14'C)0cckS-"i` T hQj+D-jVkvVgͶp7Ϣtk,&cqq%(X,4~D蟉r3nm׈?S2n%2{D/UY*LѸQkp8!?V@Z[F!3QVX,P@e24"BbIGQDrdm _-9|A51obOy/a ےrl_Lp-K:U,Rq7q\@:K\9B 2=!LUdHnXbB~d%M݂}KlxhJZOFbpY[؆kjLl-Q#*GVWjWTê  ⊢8bAv2kx>Ǿ: úRF*VqXE*wX#fIy{(⡉ a'u -aaï{W l1'u -aa˯{vXGA랬GAlUӖ_d㟍=g@luO68sYh P^J2z$ XG1Eʆ @APW[ q%lb N5 /gdbuyeË 3$fõw' ϡc^CK]0I Kv%2ٿ.‡Kb x4 W(X 0u32]PAa0 p I.:1yoP~ " *ƤV4?Y0Ĥa;3ρg@65,k.#g;H9Ip8lX?`_ C:W!0XLUg*Lۂq9Q\s0.cEzj'Fd85sR |Uh\2F!X)L׫XHC:\Bץ21Crq2%>r_bC1Ƶȵg 5wk!U n K.IX8\vҘ)5`)pm S}U-XwPuGA3A( ~e0+js7J+e$qeW (5tNVu0`Qq`8c8 P)ٍeAX/gSg; d YvD}ZD ?]0KXQ)S!"D:Xgϳ87Ye0UaIq!θxD\`9[CV ᮬim%J yNp̵ $#";YbT1ef$ Jna~B#K=7یe Fs4ݭ㏖Ϸ^__=l2X Ta=+8|ր"62ؤq{Q+V2\$^e^ _zu b:+B_P)&it-4_Z8lampZ?ol(C&㎜dlRm*9Z`#H>8)+b >lǣ«Ip6 |W LDvǭqFbL34q7?Cq4?{ܳAө琺ko&o'ᘇm8ed4#YpQ Aw׉V|g`J!1YN0e8dwmބT q6Eض/{H~s̩F(Ċ/;ǰPuie !hhv!pf8UUu#llR8vZ F1߸.j]8T) lýc8YYj9jln囹kv6nH'8`]#Ă'LU[{r{8lݾ@w '-% sC}+wv׮Wj|SL1,x1HvlXdɘc8Hy_EĂ'sI/=+kX4ЫCޮWÂ[n J{r+duuUtu*Igܤ>?`\\-8oca˭@S79I|[]sdr]TWJ8 tpqx:e–+^Ű.n/W₼ŦѥNN # CeخoXqhan} ~gX,L|Xh3Amfȹ98M>Tl@lnJNx!$GJyov7.Ѷ"U +*gV V+xٔȰ5.9#boR`/AʰA_$`p{Β9̞)4(/4TA$^& m$  ֙Ȱ.#b$^& m$C_{Al3,|̷ӜNkI帱Ѧ&Q2f{ 7#PNs 7>T]zq9n)k(TiAw ƫt@~<%MBH*:CfRfۂ̶!e6(&,G_V2UA'4ScRĉ :| 4<7qL1aHu3!QX5zT)|N}x k`PBt^c>2!koF'}ǀ"dBYwk6Q _AF\7D힙; )05.LMT=FI}mAle߸)Mn7Q>8Ȏ) n7QT0lr&03tFNVR,i)ĖͲ́ԝ\)Sܝ&Vӳ\PtMB S)SvJ/o/R!&{;TaZ OBA6OVعQ}J:A}8A^vJQ:ۤCi*(urwW6qkb'jp֖Q>cG,B{ZҭX7pճ됉~"Kg;S]x;6OXA*_%DC)DZ+Ո#|p9Ak͈~+Tt=D٪qfW*lJDn38`*N !W㖥2RI .~"Q$R@#kM:6;(:EJl&`f;(dM' 艘ڌ鉍\>yt)~_g+\Jl .#Wxb¤ֽ7}t+9mB,:OW0ؑyePeQ\bN( 1)!b"hhRB 4,Zy4*- k /e=~R%3@Jh( D `RRvUul|ീwW Gwrs)dH/&jU8)A+ ݖZa0f,6os&f<+ IA)LلtF),XÈtMNx\308 g$AOVMh]_k-\NNP%s((QDzHw-;| 6 S;AC%j+Pڭx\Yޙ6Y8ͅQ*X\'FilOGa]2.ü!OWDO^ǮeG"܌sƢt!Pl' lv(e!/s(ݳDtVs[#j爡92Uhb Jו5w&VM@X>s Y{C2e;Mx6j?F{Ama2LnR>mAZAV%h]@kиlA׵L< {kkiVO'AfۈZЬ=AU[(9ij5ܿhzFh4\*s oly,=lI{q0s7dɰꗉc@QAYHK_E$Œ`Q|oOvϟ_ֶP?;߃P-'܃1PAts!ߔplQ7À^tɟy{eeRiP1R> /.Zu;CT ŷ"^v}`M'K[VWps"B[ᖷr\U}VZw6Fx2b&B* Ҋ_U zHHHɳYcI+!{)Gz 86(,/xw-*V Y $Ryx݀*(J` '*89NTё|r6ld\%IƾÖh 9*@KЀ\:$51I`AMwn+;וd X1'tZS3iJkJQ:)K)c34%5FNu0Y/;6PKC2kej9 Wp&=(]Mޥ 7@|pQv =s B;m`c(y]P/$p⦠3?eszBpk[p9T=l;zq'v*J0vt ePO( uPOH[{6&oֳP&KCPO*ۈUU}-l zB0ʫqI"S儲^&tLv6WOPJj"];&x5A-W))'LDrPv_۔Ϡnl=;g)Hi' Ofx_ h^hYO~9<ݪh gDyzւI`'Z I&4zYh=$A= ePMȂrB1PN8TO(OzB;`•'k_OH X<,-DZ^>,MH7yiIu-'w%c 'XStdiPҦ"@ҁzZV=!H=!'1zAfZ6Y<MQ'Z Jw WOʯ[P8gA݂B}Z܀i@hPB>TP4P۝kw,"T7\vV ng\SSPŅP6V"-.q > _6mbi̧n>mt_]5ҤP?i|-OkAna?P,((⽂B{\ M8jϒ$ ޟ>Bؑ]ٟ9$Gˇ>>;g+ n=#lODuWB~eOܤ)  cN_J!Qw;(a `̟J)&"Hqgv٠ YP6h|٠US5(|ՠW sE4D$LYxgts sh̏L$ReIbE _4kH͠ jTA͠ijdWEݹlj>棚v fٙjP0?,Q#[yigTޑE#e5.1LV ;+IgcAH[GE7%D&OM`]48$(s5.VQreW$^4ؚ,g+ldB@\5X2(;jr_K{7\bH0v+ U%*^g޼}qOs+S@}TeRA]o J{ć[*8:P3L0B Du­(:\l0J)nh%,\^vh.܋!:|H_'R~%ثHU<iVzTYE+qX;wJ*kX{EByvSHBKV*UpR-"ŴHQ;u`{T&TUhF؄D= pp8k$&0/ È) W# ¶VuXO\$)8kOj%֩drdyt[w[řNB怬a8<æZY%iF䏪B𱌩QtM2 #7͸n 'j1%/&X!o d___jLRc LvTux)k;VH)= n=S .W` L R8'lhrF?аlPCf24pl8>ٚVT@Kq6"XS *i2϶C "Ïs "-JJ_5KB$f!aڱLRd֣J7ppŚ8 d@ 'G; QSn܅hIu~TR& |`Pv Z-&+j2F#/dZAm%,- )ƹoҜ P~$ ع85+HdxE1XkTcSATcBLߪ c !F:œœpVZJ\e; ʮB![, ߭/WG쳸0H#f+'^Ku{RIy"ݤ')CMs 5C:[3t.S3^\1a& 'dٚOT1d8eC:|Re C7sH$ s& ʍ,(& 4ihbݤ!zT' 1i9C:+ ж3[ Vΐ9C(!g)C KL7eH}x)Cd ֣! 9Cy9CGAr( jimRsL5ȏ:!a( ۅ00n_'#Qح\tİncW0'I0<Ó;grGi݀(P`F9Q(3k ➽&i׹0[&h\p9Ah3Z-4a_4p<4v 3[&dL6?xڌk 6odOu9=ҩn -ң @5ZNw7t-qDu㧕k66k[8qj#Dդt7cu pðZqcw_I%嗫yYf[j8I'QLדʾ5rnu&X/3Dž#W a濣qt/r#2F9dӞN' e6& Sr+I3d h$/$ FFjǑ8Bd!I`5uic4XqS@VbpTaDτq)Q)h$7|IFc.6 $GM< _ŦÛ=| LL7NtBK,]l ^ @8t3t!h܀$` ȕ yR5Ә\^o7/Y6 p #.`jԫk3 `m@k$᯽XE[ CZ D/fb #W@ZLF,fL XJDL[l "bYAD,dDb6-Du&o6:bV-8r $DĞΣŬ[lpJxt2"1+G]abRѫXUg4̢]\=tsSK#]\uR7C43?z10ܢyGx ķQczv͢D5ҘI:AUj"t*e~dS2 ͋*E2H#q'p $[@opu9kɦGM&ڟ(ȳQnT^Zfx*8וRfJ5t44ZpsO%w#AGa^*2.{ ip%w3w$U(NRp22 + TCvmFv띉!%gknijnբz6Q֦Xsڞ3Qp5XZpaKl|5yf8N#Ɉh[[htD{mIT`guT9uE%|l3ܨZW,]fQ]ht!*~":(x v{p;OaPpou j+Y(%gxe9㏊!9Nú0DXWY27+AB !4!FCBgk[<()[(U,˒3P%ֿBS*dXSC$OU5WU66Q pk E*$a4*(d;D qK6Vp dΰ Ӣ ʸ'6<1m^}~ &w&Q*_5NEJ9rVK91_x=.$s 2+w YDPMθ*=g50~1!ݵEU,s>ڐlRwK1&y[T6*Di r`gJp#Bt.<瀔@RեgCʘi\y*#Vw.M; #U<@#܄st"P4o؝byn;ZF,Zuw"!ǕC@@LZZ$ ueԝhi P0s YɉC2m"oh u[ҔfM!hRusFHqc *b8rU(Ap, |`8׀5DpՓvJܺ*7YG(?l5ܿ0Gu+єR9ի7B`8O~`&ԟJGVnRc[^Zk*ir#ٵwèɂ @*ƾNaa%üF6OMHu!' @r0}0rSHO-S=bm%3AQ/KPCL MxiE~]hUX^Aŷ"^v}`M¸A}d|.w.Bh+"QRh^ЂQpKBh;9_RFK$J`oX6_U {HJH3c+!v!- "Cz'Q>KEDG.6T ?7^M'aR ȁ(ڃ *ރ#Z?g-4ܝqX .})ޭ6,*4rF+YH1!\"={Qg$e+N4Tr!ۿ$v{QUTJVr*Jfm1*ќ@$ݷg*% D !JQd1 D}kOWlT8>ze@x\-lZ8YS#<>om$S+3+^Z`159{Τ|4J=$SRW ~S`UhW Hzt7b DѪ@wQ8E^:>++elc{ͩ^8>n̏ުQEez)ܤ)@$ ׫X~"=o 7?P;?4IN;{&QuoNW cJ@> iLATQjչk ?.Aco\ⱼGu!jcV݌sJ[YmQ)b5imJ'R|1+F<[9W_H|t(GlM{V(rDyiWt#n^ػ, o( j5혊vPw[X[\_Z2iOs!Ү\Rb`eC 6;S} ܴ&,Z_q('YZ@g)^!R(^rL.1Twq/QZ'!^|qXYq%.!uٷGk%)1K*^4E7qob5řbybQdQ#WCc`[" 1W<_b!8ȕ+լgzp=W@2;E_;bPYPxMVFp \Y6Qpa)mH *$Z`iy5 #%pI |oW |K -ķSl8 D A/\qW & fNj"$Pn!ZT&U BɈ(;DWvL3 "XjJF ̖.Az@h(B9bv۶3XƥnR*0DPOBMay! FK/AtLlrPnfة%ʝ9?ZY2r wּ!0M{4x4Hڠ8TdII|5mK \NXil%^Eg* 25R4Bgsz;`=)N#WV'jhk=t{NBseoJ[P6dHW/~Wn~%$6W,`Ŕ>]lUi'E'(N#@`Ob ?@胯KeYiެ<I7y o:ւ,r0uf92w1VManMv&) S1`A-qUHޤ>qf rB2ZȐY)ll%EWݸ1: 6?SH8c&=X{jn@*0#[y6: ͦo Menɳ֭ڟG?2̢<Ã6sTժZN.ϰXze`pf^) x7@x}Ҁ;@]-XqT^apJDee#o 8:rDF"m!;ۓ˿:iU_`GY:ث,q]{q)yl;FL&uBT u-X,Ą>:7 .>ۉ*_Ta% {Ra5tXj9<mhi+tDydyOtnf{>?ąm=4v[}ѷxsۣ2#H' ܟ8>U:4}?;G`_ܓBXfhlO!OIE8Ǟ UT&Sfe=AejU*ɊO"l)f\2[}ƣb h1$1 6=l{k Z41eI `Iܙ7,8 a]WD92+: )R!|Al&09!pA@s5re޵=~UH$?C!8@pQ+C`ΐc|C\S1Gѡ+tnBnR2JK⃈Z t!_2l˄TDlF+n"nr 9GBƙ?1M6dt`N&Vr Ɔ; h$v7p#S8R?SƦ x3á ,1ߙMlr3OyؽV)>1oSrnG[1=U{SV637WW54uЊE K|ZrܬLҭإ[@ۂ$jbvg&־57>M-.,H`FZ *=R 9$W17z2x=*6*ٷ񐜠j||X Ʌ'W,o!drsūJ7[Ϟ5NsiJ,!|5Q•sWƯoi||ҜS#'͵ W`wC4[ ^ErX{Va< r~䶼ײ^jE|o hvP;27yO.tdX;JIt0ծC*eZd- wNlSJ~|{z ~XC|+4I<.jmæ"69MAS@GϦ{n3nbp밙c;.W.)ETj 5 yLs7}Goon vkH7Edl` 76BGK+uמ3z!IhӢЎ$%[_s= ZybJ,&LkZ0pF|:_t+3_m$//䍯WpjPA|{^4_2_n&7yR6suFteO|S`+-#xB||$xZ2$Ukۙ kl4"C 4sv#W%QX}N(nc.KԗM{ju]ԗ/b@$lR0fã(tvײމ6ģ4 S!0F#nl#ҊBnUwD,"-(/4P> .VMVW/ d yR-ٴuZnR@lTjR+6⳹^9/N ?L|o߯7V^97Ӥ?脅6 tAJވ|oegaa?B|FDt?=?|*KNJ4;pAB?_.  |B} o@+/VהӛLTympT|^eU6%fAOƧG[ך .d:2u? 2AKrXG(-sـ:!Ɔ()6*` +!~o8]|,:|Rp!ii[Fsت*OܩU< (v)!KH8x0qj^jUkXLyI/N%~õ1ռ`_ -[8dQdi["ѭR݉!]mCU:)v:w[mLZ%a-}ӄ?3GƤL l+tr5&^P 7ba?M~rP9 K2Ĭ@R ;@tz8f+ rx8@-u _=KKDe:eeB0IºT܅[<زRunjV,I݅%vbV4n`!@t-UVwD ~-wF5OrqUD:nսBsX;\`Y僩OgGReY僩x ]r?gX>x~J-w"@6U[:U/NԖ*lݲ!` [Q/+j`yuu+S` b`)$ CU. -RtKJ4/ưJ|+T -ªL±)U^//uzV沣.C̊-L^= P%=N5-Y@z -"t 1J5fqc# [(Du/4; |3v bV,n$unBd ݒUUTiV6Н)X@[d L(ԋPN4 -T܅kXy>+hx0uqnP{* -UT^.,?p-@[i@WbDQ[go_ϯ߾o={v_||7勿O?믾_o޴x_ճg~7WWWu~z?_~lw}?!|yױƛi9}?~OTMu>7û??G}߼z~廷Qg߿xwy~o^nӘ7Ô< W߿{-޿~o!g<Y~)!Oϯ 7 )Я{?~^"?_ۿVAI7urvMw/0O)Ƴ+W~~~xr1&p02Mir]!z~]˗/E|6:c;1m};xO_p3eWa/?ϫ,\-E~F_V^b(/k"_k|ϯo:yym{ߞS?q0ۿ:~6kd?^\2{\_ 5q6sģb..q$ vpqOkCsOE)6L+7'k܇bēb..q&B?Opŷ^^,vqgP/aVh+\ŷY|+]<% zZ\^7Yl/)1@WozC{5| G*tqЫO`⛆ bCPc1BE Q!bE tԎ8j>@-ax*KR+vDS# mO wAEbQ jGOL5DojOQjŮ(jP'AmA5>赮Va_ ළ5Ӈ6J5LPYwAUUxpZ ZkN5p֠ O[+֐6D\<ms յRu 3tƝkP'-AU.Gi`{ 3qڡ\%?A/'vH_UIU՟>襾vD_ ׎*A z׎k#}UU(AoWU}P_;z%56׆k6D_jCm} .q˔܉FUU]k5;רzP}[_*A}K}m܁Ff;רJP}[_j@}K}m܁kN5 pר P1׃G5tt‘(lT=~?P8AFՅRU_jl46&?ب*Q[ejE}KU'*U3JolT~?8CFՏRU ~ ?Q GJRߠ"a/'Z[6HkUE Vu>6Dm TH!{ުԇƞmz#U%)doP\Ւ=QQդ措(uaN3v3w| VU__jnO> vð3 U~?1B措:5wT~?1B措A5wT%~?qUJokTRs~5';Qը>6@s5'; Qu>6@s5';Q>6@sjncO4wT)djO}Kmf=\UBU YjnJ\s39\UOe܎hn#U)o\UͭPs;~B ZTRs;~jnO4wR-*ſ*R}KN܎hzT[s'դ͝FhZT[s'U͝h*T~[s'ա͝"ƞhS~[s'U͝F=IN=a/5;MPs{N!m͝Ty>K͝'57\s'Uҟ͝T_jn4wJPs;~O)m͝T_jnO3܎UJ[3OYjnO;3܎ijQ)~"܎hn#U=*o\դ-Ps}E jTRs{jnc4WUAsU^jncO4Bmܤ TRs{iM<57ԇhn Ps{IU&U/Rs57eUknR*<ܤSRs;~)Rͭ\sO)mMB/5?ܤ*T[sjQ}K&d|TJF}T_jnOV}?Q=*ſI5>6@s2'T oknR5{=ܤ &UBۚT^jnc47E({IAsU^jncO4W C#U)do\՞UPHsUu 4W.i_j'j ~);4WKڣ?/5',7hP}Kj6ʂh*T[sgբ͝t?YΪH/5;( ~Q)~ÄjR}KmɆZ2G#E KFa/5; ){P!m͝U^jnc4wV3RDsg՟Bۚ;Շh Ϊ<5wV{=YI͝Uu okSa[YJѯ{Uuṳ*PKj\ŸT[tgU:U StUJLWNvDu̔?R]դRUe麝?q]5e\WuU_nOdWM#U]*o]U:jqnVM*mYUN6@w2'U onVE| >ݬ fբB۾U_ o7*|"YfURx0`jj fY5 Y5NjʄoVe*¿YNjʄoV}*¿mYNjʄnV*¿-YUNjʄnV*¿YUNv@vZ'UJonVu{=q]5EeadWtU^ngOTWMQY#UE*ao]U:USTHuUJܢjT[sP_J5)* {EuU:jnQSTDs*P m-=ubAs+ܢ,՞ۚ[TuVEMQY-;%5ԇ57EmQU: ܎h2G Tߠ?u¯5'L7hPk9*~FE ZT'Zs;~jʄi*RmͭFu¯5[>ܪjT[sPkmV5EeaO4ܪ T'Zs{UMQYͭ@%5ԉhnUSTDsjO mͭ:ub5[=ܪS~[sjN}OZscƚ[*q[U{NOk_82nUSt{tZ2%@L&-UN h ٭jʔݪTVե:%}'|]*SwSi[UꔀVޞPުL 孪T WN hm UTV7jUkmq* ~$U ZU'}~jʂjU!~V ߆诚GZU`Uu¯ o' \;5x̓yp<؃"(m^dB/wM@8 {!l+r's⤝xk*="e? aۊàZX/7Me@x lr'3͸%8 jʒQ*܍&eL妩/Wz0m=ja~~4*ܐ&meLVRd5qeI)jaaEV=OV)PdtA {YULe"6)=jSdU,:Y""+SLU-KC(jfBЊC@L! E!9v)=A`B@T;KC0(rPSZ[DZ²d9nF`P䠺Y""5eI)rP,LAN hEn Ej˒RZYAjeЊ 0%AU0"U:%%@9y,KH*daEI kENWVV#T%A;9R)=AeB@T+KC0(rPSZ{D29b`P䠪Y""5e )fiEVSZ{Hz)Ȫ!XYճN!hEn! EV Z "nF`Qd:%%YmhY`YEU1딀VRd5eI)jeaEuJ@+rK(rTkZ"GU U%딀VQ&, E 9F'y"G5AݡQUEu A+r(rT["G U/VQfL! E!9j)=QmB@U7KC0(rTSZ{D29v`PY""Ge)rT,QuN hEn Ejz˒R䨊YA*fЊ %Q0"V)-j˒SdU,*Y""1.KLU! (jd}Zsܡjk5\(d3i"R)=jSd,zY""jRQ4"u A+r(򨆺L! EU7KC0(Y""jRQ4"u A+r (6, EU7 #0(Y""j˒RQ0"uJ@+rK(ƻ, EU+ 0(ZY""j˒RQU0"uJ@+rK(򨆼, EU! 0(YȣZ LZC<CgUɮg $q抜XjcܡYUU)VQL! EΪ!9^)=Y텙B@U1KC0(rVլSZ{D 39n`PY""gf )rV, YճN!hEn!Ej.̒R䬺YAfЊ V%Y0"gU:%%@90KHjeaEΪuJ@+rK(rV[a"gU U%딀VRdfI)*daEVOV1Pd5(d3EVSZ{H^)Ȫ!XYN!hE! EV{a"b`QdU:Y텙B@\T7KC0(rQSZ{D 3v`PY""5f)rQ,EuN hEn E.j+̒R䢊YA*fЊ \V%E0":%%@0KHdaE.uJ@+rK(rQ[a"U \T#@֊2N^\dy~X;wȔž/2ML~<;yr'ɣ=% {:bD^gzz wtoc?buɄ] ;8\S{kPU}xOG,YxO.,Î=ၥNxOG,+㽓G;UWG)tJ#WϞmG (a';OS{kPUp1da>O;w:4=;LjQ#Lɣ%uxCI[#&L~zxtz wOryd"/3ӽ#O㵣'~+G&xoޯ~݃}GYA5}FuqxѨ}yX)#zyw䀟QG/Go8#6l zy`tz x<`tos?b];8g6[]Ǯ~נz?b=#> Î3!9ZQh0ͧCE6?G<*:g<^*:o9)їݳOC}{ {Pto?bȆ^=9.Q'k੽o8X#2q㸧cDa=# q 8 щ>; }q㞮=='C6{9ɣOo82qן} aLJf5O?xl*|3dP3:g=:o8C6CPN =}COSiTGL:yrg,tq2q/ˇq. i/ /LNq}qĈ>G|Bw>aΟmGL~ogɣo8X 2q/χiǂޟG~}3A';Ag-A6[.==^: dC I2P'{< t?b]LҎ3] iOާG>x>5}v93% }}'V};@w>agΟmG>73q7GL}#? ] sqڿz刭}}w/tDO7刑}}ܟ}N==ڳ'>6oq_O'Ow}>>&T!0U>!4U>!S#|lqw|1}v53!}}gBw|}?OsU=9~O'{ 9g=9o9X}sxF> >+~qNx>xq$ ^w_"޻/Gl_8ww_ϰx}9bFq߻xg}3<z1cCW<3+_{ #Î+ {޻|w';6zwd}œ;a{oܧo8S #FGvw_U[ m'AG}mWU{Րp$1!ji|{{Փo|ܫԇ>Î!LqR;}qR|&ۣc={ѫ>$jB(57!u?f㎏YU5ִJ~1z cVUu>qw|̪&}vܫNrܫԇ>#UUMGWm)x JkǬ:zrܫ& ytܫ pܫԅ~>N;޻jiwvB/Wx*ݟ~i{eN OegW3NGWm)xѫ>'rTj'}TQjy/S ~>&rhӎ`M4ԇ>~iji{e&r2[ݳY'ۣOثq?[R;`{˯DB;II*cd VڌVM+<ӎzDjD+ӷ(M{br쵙lzRt$5d!OR3>ԅU,cV)UeǬRP=:>f\ቜv:'}PO&+7A>q_Ǭ{b{z {Ֆ'߀vq,qR3xqR%RSM8//> _> _/ۿ%Syg_Ӵ\'sc;~?|?Ë_ݛWWcᛯno~#nAypv=dnwGtv˞۝z;tG}]gt l= lft~´B=Ivo4m=AXq>A췻AGʽ_b^?qw췻A_a+:EݏZ? /?ow7pW{h"7G{W{#Eݍ6v^ӑhA_d~}]GEݏzۋ_}__|ՇPKǁxẼ svg.breadboard.resistor_220.svgVnH }BP^4"N&-!]#+dJ%v8!UbxMޮf=o'7ۗq-ڧ.fq_5;eoMݎkTrΧ,\_:b`U_ŴVME.{Žx*v[<HKgVAZǮXeo'MW==ۦeD@dZm8"أijb]hwEfwsX{3$fƸUb, ܔ̀0~N9 p@HfoF6˾zs,jPZyKxtKiW\Gmp\3T™q.OA3+U*2`idd֐OT?bV> > UIg‘%DžɈZ5\|<Jϼˇ}2"80/sHցD@ ,sXBQtۥ?K,AHNG&z2Ɗ?Tt<^-$RKq2&8gh ykylsѭߞUэ`J9 n Yf,.w;VX ؃V,A@ J1-VTv,p9tE)@|*,v!$FҢ  s,QYUOV!9 AIX=a(Cxxۄ"%m, ),Ȟr2lztG,C#!hp=)g{AɈGVICX#O1 w{yEj`Jjn:8$߰d6( ;6 W 5*FW`KMkJڀYAα2Uq?)tdK!\p|ƔrD $ ŝbNdl@+'%k-WFm GkT_Df~ k,^ƱJ#a?=ZR:JVq T<\z1Yf&I)gP&QP)nЫwʏ4@$A;, $p!?9Nfy^uy]x:-z[Вdf'zU@xi+O#)\S\ |1@@pRct _5\PKǁxEie0svg.breadboard.starter-poti-small_breadboard.svg]Yo$Ǒ~m?yŒ i,Yh/'i PIqdzGDY%7 hgEeEy͟~y>o~{Ys?~gǟw_7뚿맇͗~84H 7=Y/׿||8>5}*EYϷwytB>}?B0. Ǯi>ݾycbZ1y{Ͼxx?}<.~./} ӏbvzsp:ᝲXW]{|}o5?\?;>x{R~ܾ?yo@ٮy{ys>LJ[у\TbaX&>DN?x>Oퟲby%mp; z4߳l1((O !KDR?><7=VHk=z 61[x؅2>i.N+(½!|_s,L0) tI%rՃHTO e\DOElTF%8W> sJ p2N^![-$6:LdDE90㛋Z?QX˕G/?#ڈkRi>B AKzjIH4%F4WzGvD8VvDɶV mrlѷNΈ٤rgyy)#Mf0*eTJv╥YJ؍P^MBh?io](hj}+[Ѡ[ I^ &\˙\~O":R37J\?wTd~H m%n(GbKᅆqj>=o9|GJaX# !򁰀v"; 1 Co7Ґ| ?ŋAJ80/nN@ɘ 4-\TF/{GłFY$RBl\[`FA6k(OPQPa X6`&qE\|FAJ&]Ns Luqp8AS77G9C*\N=lM Pϖ-ff\92V'777FSZE6eV%25 {aVxN~<^!ôF|+dK +Z/*͊xg,B̙7`2\)!r64[ Fsc62%jE3U-i,;C i1^ V acj(hA]+ynh8ȑ QW4˜ΊBV+wY axg<%Nܴr-j&+ҝ߈؅p tVd"9dU@ ʎ YB+g֢D^[CA00YC/|v7v0_9B/9/{<4FꤲN&9 o N\1#>!tw )9E4m.Z`_JY^ |gTD5w[C06EЪw.L)XS2LJ9VAXV3;zXA]kҝ Pപ%\j]zb;GƷa9>NOa((lMs̍)0zh 5w2-%hm,6[ ͓`y. ^ ab,(lMse,ыҖʬ" [Fc]qW;ay@ ֶK_{ɚ|9٪Ú-)lMs Z"23bc/Y7Oګz7dzZak,o),].'x;@Rؚ|5"˥;ZakcfsD֍H:-H % lFscrsG'.ߧ /d~ @h6fwW]t_ RȜ/3'w:7=lᚐi?jrj~.ʛF0Y{ up[@pU݀)ձc mD36~R#xMkj #q39$6*# aDRl_3KY7 P,D.2sY=Љvخ Ѯ~Z/'ݻ*Ϟp߯R|TU]eu}B I|]5uBI]___k#aYUrZ$Q7nQ{9Etj߭vR䵅X-&V1iT}MZh!<[I67_KպjyYZ=Jh-rffhprˌoQ mM^ja)fH࢛~jIN~,ݚJ3k0 Zܮпo+oI1 #lx8}42R52))aoa$]ԟc:OL6~ %%}ӇPTy)IF$6!t2(6l,4vFmIN*zr2ڥl7ŠB-+2Ta6EXVcӶ̾{vQ{m /!/aI%l2J [ɶ;O%LJK.I:M̎{tm׭6Vz>LݰQI'{Q/H2Х}d^p+Ds5ᔉ #"bŘ|R6pqD~H(j#X;(AY7BQ2$7B1`#6A?>6\[cumTR$ۭHPL޲JmVI0YkJ}H 4$&@IJ:XHٴ!TYvRbMV9im@%[eל&qvuTglJ&?CP3P?@ę,?)XĤBd^.; qʓ̛\Ȳ˩Pr̎b֙;:f\4 f; Ꞌy;.$q)6zY$01ɠ@3 DA,ha@e.h N*HY'GLa2 vGPoKa}ZkWiPZ0k^|%@U&ȴ7E' ]V 4 Vl^1z^o̎ϽsW_oVWG3ݪY\\.ώfw6q_{-/۫oW_[ Vo>f緷/󇇇Wjq3sYLt[@O=VG_ˬb#\޼0)˛r݋rRJ=򷱅xKfoauz{~43$?Η򋷾_-^_' qɗedu\>T,KH4^/o vX-.׋Wuu! Ee_^ زj<~Xme߬ZZd߳5|kbUkV`-z4[OqP>A(N񇃺qؒqjuaԵ)A8m=4 txg%)j~=RߙAS*33Df&TtTqKەSD渀U@'_R'jh`w)&mrGU6'8Q`&dew*8Ql*\laiOq2c%Ӆ5{Z`(:xf0qOYQ)˄A{:Ng"j!s}`"ب jHؚP`YjD,VU"9 'OyQ(V5RLכFi慕_,5^h,5=/:杬u5{Po;g"0K;z"9P~|gfSe|F^\6QT3ywru1pٸڦkZy1NÅ]_m ;Mb̈u/1ԗd~1iŌ=N{ np}_^ @ ;KANԖ6ؗJ{%*-m:,O 8L>zI 8y yJuN.T8@^™Kܔ<+;c@&Ĭ!Po;S֩^j&jAHސ nXCVېzysULKaT,z!o(|F" X;D5bҞ5QfWj:6 %HOkrKseQ!ڟ<;qpΟ~͐?q~ǔ7q .IzLC緖ÈI{iƏM&LR|k64hh@{]Z>;۵|&GKpN޿~$wqMY93CPA>:usCPauQA[g]nv>CzMs>|܋1Hf(݇ڜFL riDwWkFL9yLOTrTCn (M 0[psύdPc7l,G Rn(q!-D! '3s5[۲բL!dQNW}#|މh@aUʉȧ*ckeb\Jqw%NBg/ ^ȶ+ʉ!#dѡabg;}4e'OM.%!t4 +m>sPϖ]9YSFqBE> IL`ݹiD( cm9J@zA6ȠٔحPyhDpAVؐMd5Tq\9Hsi[5$6f# m")˂+(*b /JиgAI0uVKD3 m#ZR 3 CXfO3M{ xN6<$sCGupE4P(C[0:+rjd'Aj-iڒ|~+6ruΰ~j^\˽o-*cJ -9b2Q!&!.%\Z` }̽ l(wC#ctVSGh+EB:1:Td@|.$S(r0".ngF<\*H` #@낕SL7eG2:fT{K"FG#K|a!@MH @(&:ws0`.kPBy,ͽ7Bɠ L$,gw,.-)K܅1:[XH݀e0f` 3DNa[خ=J}/Yz dZr``]ad}OݹD757:Pf#b|,SO}_PKǁxE nsvg.icon.plain_pcb.svg1o@ ʗ#];tjv[:ra i__*vl9H=~Nܼ<-s4vZj޴ϣ\MWjjiѮ9wiE<.Ç!#'[Lz cwxW˴0%TN#ͤyOR|`&~GM|mfY.ǗY*̳OnQ/Y=}9z<DL!jzl2766j*m lJ^=Bd}/I4Gx1!@UQu_EtTmC) B1Ƥn< G%!HEցz"<BHAa4X }RΔ(rxrO5c< {q_fL%$I!&41p7DRG<%8B2MF%l5Z(e"f0N-W; re??PKǁxEcE svg.icon.resistor_icon_220.svgWKoF>ۿeKξ7$p IS$(-U$Abd3E9Njȝ=xqeYF)2Ml=oVQ}Oy|]BͲJ^Tj;myELY;[V]׫_ڤ7mf[Cz_ﮒ~qEç7 ($v(ĝxnf+ FJovhj7zYeIHYdzvlV? !wy4yy[R%顮EMujM2Q:ivm 9XldzʹͦYRr&Wh)ΪO*,/EYj\jUSfYf%3+HievO|R񝟝]kaxL&B W DK/d2#~;PD+ N.cIG|%uiS*b݃B5F_C)M$cBP9a$K#.+\̈ #[4]JD9rk,9xTP (h;SKuhgIdd`iIf@!g9gl遶Ed>?Zһ e9GQrUˏq4Ld!tN7FKjr><]SjVRc*W5>s^^`pla5A'0ٵ=X1Ԭ*Zsiΰ?Еq7(nWjՈ~,6݄dv|?v*.'G!XGZ~ YMɗ˶,j{/ei>r|}&k MS Vw<}JͻovC/c\WÛp8=vW=W|y(<%Xv?GlWKɅvn皡἗kUÏow;(o~5ww~n^?N\.OSwxӃ^_Tb[^O1JA hڼ~4;쪂VUo|w:+e;KksE=s.4hv@̴wN6W<(l}dfG#c +kstW@t[.0r[@~X9=J6A#1hɑRK$'%'J<]CveKqe )쀹c !E*y$fFDTܴ&9;3x9H,mHodJ5첔cV{E㿧ʐw\|E}-~@uѕ1[w*Yh+#z@0X诲9odݛ:X-Y[ 1… n…P q? (?{#tBnV:hSlƿe :5`&ˌFFg l/,8dxxdVu,YaH~@th[d9rpQ"Ey8RO[1E>fNM|ml̖kj׻]Ejbx|hˢ{ Ϩ՗X~w{[Gӈ^L5W!uKވw4äbmsa;h@N7BJ߂47`^M+3n dπɰ۪ Zw%P VlE2;;DZVFYY3ō6|T^CUaJ]e2 3 p2 n5Nv>^?n>@`:pulcw?vLjPu0p8XTC=zK-R/=u=Sg*eZ|6>OXVReHm.?J AMY!k!Y}q!4*%j5A6P%igrKK>w9x [ 50ʁQ*0+<v¬%aD4 m!&{NjTΪV陕 i܉5#Xʢ=iWY#h*CsMîhq^f T9[?t-03+|pM2P嶦XߜCz4{<\OA FXo9WV̳8Bev3E701(LalCJM*,XW Su 6Fc#0 rrbsjhTcmv;VV`Ў.f6@\0 &kܸbvfOj D $cUP/ &% uM HI*p[d T0]T >w2 ATjWd:7Rl)GLRG4Eft0RSik$fE[DW81R'h -(q,5$߄QT 'oge.%SBNkx'ZXeĉOF1;K#*eX>k@p9eUd#ĦM)M ZhR:݀ |anc3gOK\Nu=?˜<yh͘fuaZ1Qd*дӀGT)9Y!M"Ќ#۠j1"@3&s 44&Di\/Cu"H&Mr={ÚD ڐ@v-:bx9akd%$ّ,FR.hIVn ڊAϰL# $5DsZ"YiLt:ɲ wĈ^Ȑj 8 JuvBUr'U#+="icKf4De>HLeeH5fy'e  pE+EУʺb+ی` T1B{4B"?L-rЕ?*4Qтƒ+4}Yd) -o^[rA?Fi24_3-4.vܤ$--;E>Z |P77n$ڠ04DFM4k⦯#'[Qఢe$هg_Jt8jDCT4@'TS$kRxXmsqOe @B7ӂ\\9d5hfGC'xZ6{H n&,16\tG+ӿ7Wk%љVaEH.!Ĩ lή.*NJhJRpvcpnMద%$E l= R8)z70F4 ly6Lɚ<ִ̓;[[D](M# '*e s%t[G*lmr8Ő4/%fF2T)7k7U9&.̈fz8A`[G+lebkǚT)y,5! NB{b\iU c㔍dc2h)BK8y,5aK1] cJ0JsL1]Qq [s:8\C\$dz rz%\H&je|].|ȅO$yN&,Ub6`.(%vƷ6rbJ 奂=U,@Eֆ.c[0ŔEJ7[[`i?FK/15) ${R3[[jI+w# r9ksF/q5aKZKFyiIO2Z2Kl om%-+W"reKVdڨe܁yĵd:6jkYx\뙊EZ\5H[(I::j+B` Hʵو8$V,tMF,c:o_:vKl om2v_%ݪ%"Yژe9,ަJK7ލG:|.=^#80^:TUiꝱzSUkq"s0Kc乗f[L{kln٢LWq|"N@Oh֙:尐M%s~nКXq:"/s4\&\VOҫ3;2Az+EBdž0oGwfiyr9(0i^7q'>ݦRsW_}wMo@>O5w].hgLߥ|^Xqc|$m _Mvnl }ݸi~VEdq/茀x(pGZ64H3]rd3jf繎; :pw7 |Ҿ* ѡtc~k)UHoN wAጕ Z0UZ309ՇmWEiD%E[ZnMw|"b}d 83?] Do&hF,kgL_ᛐ^V5Pq~j.?bj>#g:5=pHq CL#QN#ibz PS_ۢ(uٙpf0J,VBclHc6 |NaTf۲t_7kj}Bja +dz";20xD!)sCw);C%\OT1g5X#)BJV)ՙ+vRوI -3Ug]憗J?H/PKǁxEB#U svg.icon.tilt_switch.svgVn7}vݾ4.ᝆ hO#+Ѝ$HJ{W1dhAcpfΙ us7j9nDF͗by3n>uy]͗n9VoW}6:_6;u/c1ˢV޹^*u4qßjF]~:}?QM7&هEӫb6Ҩv[Fwwwfns]̶# Ϋ#>]70G+Q8_lV|TF-|4/ZnXZi~9A))DǍY7zw;nvW0u1;]2YU[ 7|uNh7ld}U@ՏOp4 ?K6Vti}79|jE]V%6v6k:mǼH.ɶڽ8::ԛ`XYPc<͜vu8cnu.˹顳4'rqAP\!sykۢ3\I@QZ\c!;܊b/ؙpdvP"|,1[w LD[#e{Ѩ/E;1Gr6)L PIRc vN3m@.!&(TD2`DG1 OG˘*rWUT jdK2\{>͢1n 2d}Uv/%?\|Og)omVB!"- ڡY%u&m\@$`΄I*'窕C:^gC}V/qGVG>S;y±O TqAE{0s |ṵ̑CF<$ ̽u=傊6`A{SR2$c_ǦBϑ NpgbWY11mT:NF7'PKǁxEOg#svg.pcb.alps-starter-pot9mm_pcb.svgT]o0}Nŝ4HZ-Rn۞\bdHHekhTlskۇ6V01P&)Rm{/"Gw( ;iq2Uݦ@(^ٶ,l :. 6yiLfk?x?rr MfW'@<ƾ'ޜ > ˺.'5MC6cvQ.uR12E Ʉip)4&pL51~ǧ+&㈙ŃE[\rΝ5f9ǬИrK౟˘!%Jge0BVͬpˀC.W"YeXѨ٤$&U(k$)RY w46U7F%xԆqMabg*AWƗDRE%'=yDWv.hG>37>0N ]]P Q94v>S|\u\ ]T:_UUʴS#s(^>}6ś۔ou4i0]Й]+GPKǁxE^y svg.pcb.arduino_Uno_Rev3_pcb.svgŝG?E/! z>D9͡$-`o$4BQbv5ZϗF菏1jYxY]\| ?{.ogw+ EH.˿J mѫ8j>m?_tZE8f6yuهoWl>tv~ֱ^Vls'7ݥOWْw1Ќjsɘudzp$cûܨIlG6el >6D|{^wv \|.uxVpzsA+cuOm#BB,ӂ #M$iBb뻫U<w*|!muw\l d[]2JdAU$9ٖo JdbSeJ!v`+`UxDckV֙ 2KN%%3P/pd'fF^6F^k_J#B 0h V0U Mrvsrà'.@ gm)!iTg\殀A#O +V(6C,+C_E>h|k2eU\ N\m梎ޕ˫J"/|@b#,%Ll%Iqn*mLW\g~c,&z+Ȍ6I2GRʕtXzofڞ}ҏսIo/%!Amm- E7>t შ[9u:`#'jȔ".H*`NR񙗤6EJ)'~!S)XlQ՗*1*:È-zИ|+ A3Yt~(-!2H0`X"ņJL&Y|\/iyfɗ=+bHNUaJOv)%Uӡ4-Ȅ'j[p DxZa˗fx-[ 2je *ʶWjA%Zj3΀2F*np KEO`]ѐT(,ָ)HsR?_ Dtei:`e2 s7ԱtZ:3i^KF'RgXåk{X,K 9TjE0v䰶qRgXO4Bt(43,(ʠU1ޖW!cWb xF9l5<0O^C Q*j,h(. mp{0jߡcO3y9`j %jߗ#W&oʑm.#.]_`By#=׀j0{Ey̨VkY,PQd @?lgyTV3l@-38{h(.`pUF/}6f- QH-b}Pcv;&y @fjf} | gvu0{Ey/+JKUfϰO*f}`Qddb_VOTXV X= B%=~mUJBы|`NMGg I gi0zj>ԻҐ}5,/7үcL;d_Ș)~#2FHVJ"{̫nv~y垙l^ם__ m̼;Ъ-m&T6}P=ݠKӭC;kh70 rխC{$e^yH;m^yHhb/XL uU{wp%c]!W*zZ6_}FL Kj_/kҏ6zOYRzun䘀hK $1첩e{6;wt!lHW'er쓝.6={6@}y<=`~EX$Wl߃AbݔS1q|?|~=RpԹ!!ي_[oKmfd8K*)c$(GwL4\@@OF|y5%=\n{mvW5z4l19 rz0M dLݓ(#dH%SJ}rSf& a\m׊|+ZL 0^@d_yD"_uA/:M kO.6}J94gC(^zO>!ȳAߓAF?lCFp dk -W p8+gy)ꔜgzEya/!_4./W==¶}\gl\xxFzu}z{5z{^?+BH!l¸m&M~))V|tyoŧg?}Wmť5V"2>}hJI}2{ `׊`'s 0gqO:92Q4q?6ǎF(bAB1w*CK bsYFlQĊ؅E)c2̞JQĆX~P / xvM Cd12VI|# XB#3&"at8vZ{pLw{JwrQy 8-<7Ղsvg.pcb.jumper_2_100mil_pcb.svgSMO0 +L.IiCM8B$% tv6!l'{ω/jxUkkF@iڔ^Fk 3}Ե$hhM B5JTZiO7a$ٿ߱C6JJ''-UdeaF(FH4+f;;';FPuܖ}H˩By51!& %Bo.*]̾,1ƛ #E]Gȶ5ٷs,g ¶9>309m5rjEV̹j%vK1F6@0c5(,jeγbqȑaSp0ټvGX곹fL'{ڴԗE+uSii,fu{V/BVJ`frqK2Wq;0] ( 8)5}XPO:y`>~U_"b*iM+VQq3-.ۖ(u+@^x$ڱ/!S ;7$ ^O}J|L(೬Ml4@q澂 @;~Hl7M/VxߊמI\EhwUuKWz~# P?@:DzF277RWPKǁxERN1svg.schematic.arduino_Uno_Rev3(fix)_schematic.svg՜YsHWqU1 ȩovsxHXV"_=\"֠]Q ==7K.HVau۰t-,cň*`G׿FYi0a.0XW^Bh'ddm3nt QL, cj8].H\a@'V8d }vdq$ Lrfxd="!2čGm3#=Hqh>11Ǚh}6;Lrϵ4=&Nn|rs/)2\ygmue2Vj3BڒMӹjN6uGG0q 2e*$X`T+$s)+ZIƾ}\ f6g>%6h;̲]_rY"rښ|cqY{6'?8e`Y߾رv$|x0+sc]|#*@,3l&US&f24dκ.>3r`1>#xD&KT嘹䜻̇ 1f]43 MBbe$ wL6zsV979Rh߬qIFFYkGQd˼3SF*F sS"=^= ߗi|43WC퐸 <SbFiu8 `t26QT !SJcûS9FN}vN@y5 Lq7pO3CQz2 6D&F.pW5jSz]a(Te7ʁ2+0'i `n΁r *0,gg9>c :0h;8=$&E#lJ1I,Pżf^żf^J.$6"%-$6"%r̋̋d")FW)C }ulM-e:ml/f2\\xÈhSs)=&8z{Iwˆ+~0y="zHGwF䬮mi:|eB~RMJ6x{ e;s@Y&a G u*|/c鯊vE?t-^eGOIW) PKǁxEe svg.schematic.tilt_switch.svgUn6}vb>.`QBVA -PdZ&"D~}GMq=29:#5<7 nJ0M[??pv3aa5wzS Po12S/ˏ]CX/?^ WyW<< "@Vε0nt++ڕ)/9]:9 Zg_M4bj<ȳ, )愵;_ykn 6aF4z{a[@&U:/ʇj;aZ-JӽJu~6W{*ʕ^ΔhL.ipm;t6MQeLS乤*U1mFK3l O`_PӓkQykHi£vD/b+*ճLNgGxpOa[[Agxj?Cp$%=e@kMPإ"VSFc! $b*i)q'iog\vW+q; ?>=Wݻu ~_@ e߾ʽ^^Owd6s{U{~c@F]s5| r2`k3OWjv &˧+tW|5eOQCU%4[lN2s6}`ztx5vx?x݃$D؋CBߜHxAaà^]M u#@b/>gzǪƬh|VW_جPC9ay6r}2 Sik IJIZ3'$jJ5#!`dC  FIc1LVH#WG GSSϧMJOG B -U}TeM84!>Xhj||q}R]^ !ΚS3S9g4@nO TJO5 O6O9Nl04A>fÚphZ:}̬lU@4E>!qUH4AQpP4-8հhz:}ʁtXb:}*8XMPL^HBS ҧ$MO'&MP'e+uҙl5r=;[wYXw9Sy(K|VuD'H20h4{{^1pkt89%:bXU5$'k&̧j&G L֔d|jrqjʜ<Mڢ[ NXM*j }kb }İdMKʧj&j6-eMxW_o꒣0C?ę~ V@Oq`Z󙢢?+¨-vo'RTǃoGWo/5}?v4rҹ\Y >Np/pAǧ7Õo 0}8X-Ps*]f8 枙Z'=Q JY(i>0\wi_^NerkTo2'>_m{G#1 B <6-xFĠ(#%)-(no"KQ@t"̰1 `#u9o AW:3@!#;1Pl$E!fmP7~&ӎRI!F1n҈!C)̞idO=0VY$ A fq2ENm? 6斦7A"m M \b2 6!e*r4oyfdT>i[}LMGҙDfo0ɣčh 82\U,.zq>RhO*>i䓸u1 TԦΰ#0P \ 61L-@ lm>*ɎK :kP& +$2C\OC)`4!e㈑bqŌqF ۴+y䭦^#ű-Ce!B9-[#ENkkN*$m> '4(d/D NPϨr8́Ȍm> yTmF&EO6C -IC@$ED2ߕ^E"Gy\S,ostm)(Q P駉+XBK ;fkip#n-2i\U,.zxq$>Jh4TF*i4Ӎ0{GЯZ`gT~RdG`riB4ɂrW IU^-OyW<ӠW: Jݏ5?zYZj@d"g&!y3i62\U,.%pw<_UanhrqW%onnriO JZYP7^'r3iV-c<#Iozder6K$"y7DQ#33e0)bq"331kFT\kG|7ל\ˁ}y=TZv`>|zrybpܙ|>пy&ɦ{I AMXڱ3r(<#zM?@Ff ʅsv8|x~EWdnRrPwJ\3-2(gw\vfUq̖}_ӷ*a4R -Hum8;9MB?GGbY`.|We8~ \ZHwXUl Y~rσo!<><}\NίW_δI*'{iz߾;}{>dew`M}9 mo㫇sOѽrO8(A t5|$k5Kv5h,śq [)0FhX[qRN٪[ .nS2=:8Oy]}Rբ-F([Т\?&ÉsɴM\PQ_i,:Wެ ƾG?Ͽ(!i|guX?H墌(gB,_<- ]bO!,rX1|^`>̶m z[8K* ݓU =gq4 Rd-Rkwsy '| ȼ{?dDQr0kW@b!SsDZ`H"{FNs833)VEy {:m$0q3a]x>jUg "9k]GNø6_9G  񴍢E乪X\D8D}kl5k)o98+jVh))(#vS"ٓ퓩Եe OB(oFrFcKԯ2`F60byu|r=DJ}WZ&'lq6iUZPۺBmSlMS#vDjDA?Fz-m>Go,tXˆVú5)U&'؀o>NOĉgrPy6Xss@&m׼mj C7y qi(X3H߬ҫcaM TC{(OjjuY̽l4FܢFm{ItZ ooAFgf{nn`u6s_~K(@zO&>( MM۪m$Et[pؠE' 9຋Yo!|І݂6h~Bb604^ v(iB9d9Cd0A f3Ta8NCIz$9zi<:Uo4fit#1641gYtK7,9n~LSÇޘ&wzD aM/ϟoLr*–NW=8bB9%LXL]0ŐS5KLìQC6WNd4ت&gUSj&qBa$wTΝVڶ<3 /R/du>gtFRl]FCZ#+E =!]К%ATj{9DVD_"n ARD*hRi,ѢXU,.%ZL}xqDr^8em4vYIpZEBr-v Xݒ`OMDkR#2jZ1 DzZ%"L HΐHiBd*X\t 4xiQv4IYKkZTВB) r10:' beJp2f װn gk+N&5{#U[F&]z!_};Rm/1$֊A4LR$F4j3Xҳ$EpHz3J .Ҝ{b"d5"UFOpILhy۝h:' a^k5NXC.,ffZ a Hō>iUY=iM}zСX!L/2j+5՞9תbq#s#JZMSOBW"$ rcsR]֙|&/2rs a 5 m_ f jƒĹү̿Vn 9+Krar2SH~d j(IW2~([nx[9P1BePPW qYm\*+rp! Īՠxv/*Er9AX闬n\[`n3 awj^Ժ{RRܰDFrXCXs aaZdzX\t;ȡF # K6.s9.ĉ*Y4+) +LJ\mL|^I3ZhaNGNfϏo.7i͒.?X7Lt`b{b]*E,iucԘy0!՚תbq0#SFp#SzcYBfp+lAheD`h c6-–~}Nč>- flRdblr2ݘkd+{ΕIYMq7:0iڵD23[U,.p#LtsZ>m(7ؚ(ecWiu ѧd-Nph_ Y yȒ2,<(d!9_RηAmk@+3fLcUX*^G,7o >e"F8c6Y\k[.ZR4GrY\r7)_&[BfIbS|js qmLVM*bӧcj铤 1"5oEHd~fq ez&)r-e Ok> Srr/5$8ΦLVnt59}lE| &^#-U#L1`K{-׺aH|5gj\lUv`aG9.Y`%M~U.l "*U2RL1m9}Sc6&"35dtclXRX?8x4vVn9"hX؝R"DOg F>'2mH]n9 v+jkUv`F_οd,:c3*FM[k /dvW3q#UAF&_F&_ɗj|aΐ " NBwM'mP,X2xr-CAjM x5zbDs7jn 7\hkUvWsؑW$݉nxĴ*aIg5/TFju4 |)noïLjnz5gJ352ZU,.pdxddwe^t"lk2Db~[č>-U щmZŶa42k0\?զתbq`##/yTOz|i= p?3P,7e9A@^s#ʩڒymP_G۲wum- m1*:RRW*؏d9 eBmP|ʤl:CF٢ bqur@T& Tfw;WduF!+E˕sEk:mkwgI_*}'BzH(QgdnپJef{Cǹ&qizdڷX\t;49yLvcM:&j0iR u#Ҷ.k7זqߙy+hd `aq#3UaEfZYļ=>4hvdzGz?:}pu?xs^t^FݗO_}w"캫ۻrVPprw4M^n;G7>>>./?}T|9Khy(L M$QbNtt(up &s&Myܺvסd8u W9.]}㯃3S7ϽAΜrAY_U8D ʫB /h3Oy]US;7O`vWJ_K+Xɳkd[bq>po@?y#(ob!P yh!P FUJ:[b@O~]q nFw/ߡ@4(Asp+ N,C8W[ʟ\ ƓÛ/hA Ç7_||/4훿Hw?|ѻ{yOt-0n؟\ȫS/f+: +7:AS¡S*so:Wt8]wȿv:LEFby{;/0ld0kpZ{;0>\?~|(SSϿN."AGsY hA$Y(ej~|o^e] wv}Ge ]s%mBXwlݱ{f*z0d!BѾ{#_B!ܑ4k;D9ETy躢4}O iB5Vk,WSN˹㻞 ۇFrA¸;f% cEtoT봖/V H Npk֝VD9 mNPnA))@YJ/d50دB}˝|(*hxB;YX\ ~woڭky8S/.鲂~uqlW؂;ug4Na=2faP2]ڋQ3Y\ Kc85髣Ÿ7LS~pua w)wt]R@T8}b/TFw3?fD.gD:R0w{N)LK?"A6ſn{:lP#roߝlgr塥KmaĎ;w|#x{j tG{.& _J*tP* P⠺3efk-J/%$*0 #6өSj0ϫ0FT i=o_P.c Wx°Lv~qcH@ yןPwνiӗ B)`%,җBuX}ƹ{oC#^DNx|)@ hHAX_`klbr俀E Pu=Dc4ب߆> cכ^3 z <1+g @Mr',?:h 3v;17w G KCHdt(xP+;Gx9܈Nsv38siǗKM;[cȴ v[ghg;}hyn)%/Ual8iWɽ`€a1[ pv^\ 'a~<) \hiT7\ jA,X+zٻ= (`QV;n{X4 aE E##FN-{[3h(F ʡ@- TP EChji/K::!5:K9kUv1V7bv p {x`6. byUӇ8's $)trn;6_:@ mp~x״t+B0ۍzY=[.uۑjt}tA8LgVn4̒ `Zf!3f "2_JI%4cjl+G1Bs0T_GQP M@y,b }f˂Qx3҈_x#pC1 p ,oݳ  zL*;B:$E zAձQƱ;P#HÓ*R;6# G{\US>=`%B 1܀|Mb,sTЎ*}mNH(wV}7@, U*E!2ipK€9h'/bM7 tDI3 @T4ՠ{T8.Ja{g)8@`hQ[qĂo hDuwN 7>zQht D^V?y `LNzA7`%m- M&e`)=8R=x ,=a=qXrBPSku/fo~ ffY3720$A/+a`I0Z:^"1 BDIBB_x@z @ {P`QBx|Bhr*tTj|x/舨 E V|h!pv0t_D8R f> (/P ]~ (Цk+T\)J $'// -`O=H|SrB$T_ҠGНQ[K1QhvtD1M舖OkQ:toU虦nU~+d 1\v:g*YʂF04RLIW7 ZC!$p f%h̓.jC ',X’bDU!l đ 8c hb+x~ܢ(S`X"C p̀YdB/`#u(yW1y{Hw/VE0p!8*Ot 8{AJ0+( hv:ڀ '~Mw\dJUprS׍dw"1jpуVnjC!tt<ڃ \c2:^`6I$}S #Ak 0t+jC'Ѭ ' 0zc#_uplHeuM+:rtګANqx9<.Atd'l]39 bL/ F,n@bD +" {Gb @bb n &&)BL0&yC1f]RvOb(9ف&YtA@w !B& kJ#D@`ꏨ{xΎW#Jq`쎁7 * ;(k>.$A@IE( qBhEрkޢ $Z 0) G`#q!xd#zǮQ Zo_Yo*V y#X[U ё@'ܡ4ULG;z^1=+""RTDS ۅO%d7ѻXg BQP4, zŹ]Hƃ`2h BBd0c# 3hF;>^;8t>],%,`ꅟ t|c%.+l)+JoU;Zh.؃0;2Z O` r R (%(G/?5 9 C+װ*v@*xR+1M H $1y ݰ·{s')+PC[րRc*`Q6@Y08EtG>Jf`A}|,aդlbX!|!x9+dt M_gpX;/@Z#n?Te9twA6kVP? Gw .!FԾaLյ^ea\ HƩ_b# ȱN(Wy(Dc*-F<̴4M% @GtVL,I TNˠ6 qȆ2APA4}P ( ̿.~+[ЬM B #C|CگcJ1Ra]aTF׀4ޏO~ S{qœ T ݰe } 2S##r#Om?|b]dNBx9@U!q ]F[eB0RpHː(]N.؜Qc@-ck?Z_^0"8LS5χkiR qPXD!2W*Iz͡Qτ)7}nx]hl J#tbx"40*ij;] OeAУ "*h) 0!fȃ3YiȌ^y4 5H RZ0 =wW(C(Ch7ra8 YP܁(>0:硟 a9􈢍"Q4Wzz؃S[1`JCjy(f}.ZV ( vvMjz{4]I3_v\pcE8aG@^4JBX/ư-zQ K h!XCR]]TI7$a.3:k׍\d9n G269=h%QC&nq@`r[Յ8f F} 0xxBۘQZ4 1A2d'@S/EA BK {(C`vp`M&IҚC ) h#LtU'4x=6c^=d(n9ps$a_M1Q`]dӽ&U(x=ӻS]{9RZܜp@f@9˦F>p6Zo:Tw 5/  /^7j*3>ƢA|߽H)*AөC)E{U|w =L8?"ނPPEHۛ7\_pUvÕ#6164\}>0m?VPFqjZꨩ֌ll讑m<([-O UQCiP[hdl)a/jZ"T9bS2 5[#T WB5'9K!T@f4 P(P{ xd 3C X6ꡙ2@/77bg >F@OH>z”D#5n2`oEhGbaN`C;rpGhl54UPJw1@Q@ɼx)dMJckLݰk=9b CG' bwC Tspݟk:/~I1d41Q`2Y5?XpLD.v0r[4i~0;t~8v¤ѱ#'÷}LCw2*i,SfQfxibDcܨ+Z “[k(Ui= kw՗ɪ B9Zט!W"=C8HBcXA0"a”áSܫoFIB1Eȭ}D}QF}q;틢ꋮ95N*@Ò}%Œn6I>+".ɫc#`dH))t̙}LL. {" cgabN+X/>i}gh?݌l)PC|o86W/hT|tϨ%3YlwU[lFMe-1MG>1q;9x9H|U_=&69uj!``0UCtSqhū&$øM2S`EgAw.lj`= ć>)8``šЦðvzx_!=I$tۄ؅Ԭ:\c%_Ũ+F]u5B]o] SCRbWpjBnA0q؏BhzG.^}8f;7]YpWeyuL! i $B ޫCi86qRy-hnDjÄ_8l?O|f0o߇/yr7.oAͺn~)\]:;ծ6vp5jd f83˿] ۥTtq!2\]|ʕ׽d92 Uz~nd2s]M{U SW,}j>BR+@`4[\vA]?_Ohx8_bW׮o|x?xpݥ^^^Իzzp__}| G{m_At js|0VXq|߹=eF=Q+~?>[Y*+sly5Kكřo`NG Jޯ ޯ'U9^}&-y+~Sqȶe2~OCշ**}}2u"9}i\l+msm;oP߂ +-m;ƍ~ծ]GQzW0ԶT:IyNѰNd{f5^JtpP6jj1p^(t4~nb#$Y"^Pm-YyD֢jhﻺǾ[D4'vi9r9^'W6:|}~dr^*yuB^jF׷c$DklF+vߠ5nTfפho ,}SX j[=mJbT#:{kR-PKz۲}2XrLewJoF 8 7`~n !='|>v]C~rL7Z[N|r|1v.ڶsF2\ecKc$)ڛɵYx))v^zb/A(oA_)ܰ򛧷 HpQ s$G#u$ 6|Ӧx= r/%68eHL0V/u1e)FKzY&3@HBl0i1Rn)'DXC( Ѥ7xh&B&+=(2Z)ƞZ9U}=O a[k쑏+l*)OL= Rz Q#՟0#$ghD|-ݠ5tt]Tԣ` +w@y:SAEs EkΜɴ.ҿikрdaa-&Ro ڋ`DS⶟8 &-4eYώx-k- Ҡ(5eV+>RpR9R52NHH܊[&e`KDLmۆlM\:B6B.@ Os jLv]K N{_s!&aoX9|df̋ɼ7Ib3,Etlg7ȁ(\LU)5V=nde{ EckrB%s;ɓmitR 2fy Nr}+ck[ƍ>-^''IxT ܭ9t!* ))rO1$!#LPv^RYNaohgeJJU m<-@-0j lW7vٔS/QP@xǨ=n5}󵶔(@enBh^#(=T 2z<ֶcq5fudX&i @ Jƭ=}š dpuhLqgLpͮ4ukY2 kxDk-ƍ=}Ζ9TLvPu-LU槤+T*bk|J4T9ײ8Wre6 BX$gZ`L˓jMa}06ב$dHa@O5aeuea6 +Wiv}kvsFt9n9X3&Dp$ KI¦ -Kd;XFs2KD[_e>n3YS޴!XmJЊZd _5@H=|SLGZ,E[+-u[(ATn $Fo3 t5d |! %ɡJV^"*2;Sޫ{g7ti69dw[{y jBVڭpšʚ}@Bb;p[9nБmMs 2^,9x%|fS@ G[&_Kn9t}͓}/L6¨`Duj\0t*x%s3_o[ڀLVvL3$_&ĽL HİF^k>F^dL{ycw暈a W}3Uh+;0EwkUhUd򵳬rr/vdrd j۶j 3kvWsċ6O3mzGC l PHc9esm9L޵w28dd`YdNJs܅)5vRaR )2Z *F"O 2lq& 33 :Nc֪bqWlmմ%Jj#՟ݠ#Ƕrlkzj9\DKoPz$W*DV%j=2[U,..ZZV^Ms{ "!9up8o62[7r,8X+%?PKǁxE1oZaubertafel.ino5; AD9E 7163kZm v ^=ܥ?!+h#K2u'nGUE 7oOR~ Giۘ9j^$dи*4PKǁxE3 part.alps-starter-pot9mm.fzpPKǁxEug6=$Npart.arduino-shield_r3_two_layer.fzpPKǁxEW part.arduino_Uno_Rev3(fix).fzpPKǁxEmY(H"k"part.Half_breadboard.fzpPKǁxE;=R 3part.resistor.fzpPKǁxEzZ 6part.Tilt switch.fzpPKǁxE>6Kz.o9svg.breadboard.arduino_Uno_Rev3_breadboard.svgPKǁxE%%k.r%Zsvg.breadboard.Half_breadboard56a.svgPKǁxẼ svg.breadboard.resistor_220.svgPKǁxEie0svg.breadboard.starter-poti-small_breadboard.svgPKǁxE svg.breadboard.tilt_switch.svgPKǁxE; % f)"svg.icon.arduino_Uno_Rev3_icon.svgPKǁxE nxsvg.icon.plain_pcb.svgPKǁxEcE svg.icon.resistor_icon_220.svgPKǁxE2H#Wa$svg.icon.starter-poti-small_icon.svgPKǁxEB#U *svg.icon.tilt_switch.svgPKǁxEOg#0svg.pcb.alps-starter-pot9mm_pcb.svgPKǁxE^y 73svg.pcb.arduino_Uno_Rev3_pcb.svgPKǁxE)/ʰ"Esvg.pcb.axial_lay_2_400mil_pcb.svgPKǁxE>7ՂGsvg.pcb.jumper_2_100mil_pcb.svgPKǁxEr#Isvg.pcb.pcb-arduino-shield-rev3.svgPKǁxERN1Lsvg.schematic.arduino_Uno_Rev3(fix)_schematic.svgPKǁxEX,.Ssvg.schematic.basic_poti.svgPKǁxETZ eWsvg.schematic.resistor.svgPKǁxEe Ysvg.schematic.tilt_switch.svgPKǁxEdcD K<]Zaubertafel.fzPKǁxE1oˡZaubertafel.inoPKgfritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/000077500000000000000000000000001250202676700304275ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/RGB/000077500000000000000000000000001250202676700310415ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/RGB/RGB.pde000066400000000000000000000026451250202676700321540ustar00rootroot00000000000000import processing.serial.*; import cc.arduino.*; Arduino meinArduino; int potPin=0; int value; int redX = 20; int greenX = 20; int blueX = 20; int redPin = 9; int greenPin = 10; int bluePin = 11; int oldGreen; int oldRed; int oldBlue; void setup() { size(255,300,P3D); println(Serial.list()); // List all the available serial ports: meinArduino = new Arduino(this, Arduino.list()[4], 57600); noStroke(); } void graphics(int theValue){ colorMode(RGB,255); background(0); fill(100); rect(0,20,width,20); rect(0,60,width,20); rect(0,100,width,20); fill(255,0,0); rect(0,20,redX,20); fill(0,255,0); rect(0,60,greenX,20); fill(0,0,255); rect(0,100,blueX,20); colorMode(HSB, 100); fill(value,100,100); rect(0,160,width,height); } void draw(){ value=meinArduino.analogRead(potPin); value=(int)map(value,0,1023,0,100); if (mousePressed==true){ if ((mouseX>0)&&(mouseX<=width)){ if ((mouseY>20)&&(mouseY<40)) { redX = mouseX; } if ((mouseY>60)&&(mouseY<80)) { greenX = mouseX; } if ((mouseY>100)&&(mouseY<120)) { blueX = mouseX; } } } graphics(value); if (redX!=oldRed){ meinArduino.analogWrite(redPin,redX); oldRed=redX; } if (greenX!=oldGreen){ meinArduino.analogWrite(greenPin,greenX); oldGreen=greenX; } if (blueX!=oldBlue){ meinArduino.analogWrite(bluePin,blueX); oldBlue=blueX; } } 000077500000000000000000000000001250202676700332155ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurusTwitterSaurus.pde000066400000000000000000000144721250202676700365640ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurusimport processing.serial.*; // Einbinden der Serial Programmbibliothek import cc.arduino.*; // Einbinden der Arduino Programmbibliothek import ddf.minim.*; // Einbinden der Minim Programmbibliothek für die Soundausgabe /* TwitterSaurus Dieses Programm sucht nach einem Suchbegriff auf Twitter. Wenn ein neuer Beitrag geschrieben wird, wird ein Sound ausgelöst und ein Servo dreht sich. Er bewegt das Maul des Dinosauriers des Fritzing Creator Kits. Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit. */ String myQuery="Dino"; // Begriff, nach dem gesucht werden soll Twitter twitter; // Erzeugt ein Twitter-Objekt Query query; // Erzeugt ein Query-Objekt Arduino arduino; // Erzeugt ein Arduino-Objekt Minim minim; // Erzeugt ein Minim-Objekt AudioSample sound1; // Erzeugt ein AudioSample-Objekt PFont font; // Erzeugt ein PFont-Objekt long timer; // Timer wird angelegt int timeout=1000; // Timeout – wie oft soll geprüft werden? String lastMessage=""; // speichert die letzte Twittermeldung String currentMessage=""; // speichert die aktuelle Twittermeldung TwitterFactory twitterFactory; // Erstelle ein Twitter-Factory Objekt int servoPin=10; // Servo an Arduino-Pin void setup(){ size(400,200); // legt die Größe des Programmfensters fest ConfigurationBuilder cb = new ConfigurationBuilder(); // ConfigurationBuilder für Twitter cb.setOAuthConsumerKey("uzr17kGYqhgNDjTBNQd1qA"); // Hier muss Dein ConsumerKey eingegeben werden cb.setOAuthConsumerSecret("ZZUfCHruwv4d6Tn9uGz0UGebxfn4oQDikv3NeCbd14"); // Hier muss Dein ConsumerSecret eingegeben werden cb.setOAuthAccessToken("221060254-8MJIyVpXotDhemKaJKVN88L1FlCcndToB8y143LU"); // Hier muss Dein AccessToken eingegeben werden cb.setOAuthAccessTokenSecret("A2R7IkcSniMnBHYeRK02umHoIvrsHQAdx4NaMq6toY"); // Hier muss Dein AccessTokenSecret eingegeben werden twitterFactory = new TwitterFactory(cb.build()); // öffnet eine Verbindung zu Twitter twitter = twitterFactory.getInstance(); minim = new Minim(this); // Minim (Bibliothek für die Soundausgabe) wird initialisiert sound1 = minim.loadSample("sound1.wav"); // Sounddatei wird geladen font = loadFont("OCRAStd-14.vlw"); // Font-Datei wird geladen textFont(font); // Font wird initialisiert println(Arduino.list()); // Alle seriellen Geräte werden in einer Liste ausgegeben, die Nummer für das Arduino muss arduino = new Arduino(this, Arduino.list()[4]); // hier übergeben werden: Arduino.list()[nummer] arduino.pinMode(servoPin, Arduino.OUTPUT); // Servo Pin wird im Arduino als Output festgelegt } void alertMe(){ // Methode wird aufgerufen, wenn es eine neue Nachricht gibt sound1.trigger(); // Soundsample wird abgespielt arduino.analogWrite(servoPin, 120); // Servo wird gedreht delay(500); // warten arduino.analogWrite(servoPin, 20); // Servo wird gedreht delay(500); // warten } void twitterConnect(){ // Methode für die Verbindung zu Twitter try { // versuche Query query = new Query(myQuery); QueryResult result = twitter.search(query); for (Status status : result.getTweets()) { println("@" + status.getUser().getScreenName() + ":" + status.getText()); currentMessage="@" + status.getUser().getScreenName() + ":" + status.getText(); } } catch (TwitterException e) { // bei Fehler println("Couldn't connect: " + e); // Fehlermeldung wird ausgegeben }; } void draw(){ // draw Methode ist wie loop in Arduino if (millis()>timer+timeout){ // wenn wartezeit vorüber twitterConnect(); // Methodenaufruf timer=millis(); // timer wird neu gestartet } if (currentMessage.equals(lastMessage) == false) { // wenn aktuelle Nachricht anders als letzte Nachricht ist background(0); // Hindergrund füllen text(currentMessage, 10, 20,width-20,height-40); // Tweet als Text ausgeben alertMe(); // Methodenaufruf lastMessage=currentMessage; // letzteNachricht auf aktuelle Nachricht senden } } 000077500000000000000000000000001250202676700341275ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus/code000077500000000000000000000000001250202676700341265ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus/dataOCRAStd-14.vlw000066400000000000000000000752661250202676700363210ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus/data8  !  " #  $  %  &  ' (  )  *  + , - . /  0  1  2  3  4  5  6  7  8  9  :  ;  < = > ?  @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^ _ ` a b  c d  e f  g  h  i  j k  l  m n o p  q  r s t  u v w x y  z {  | }  ~                                                                                                                                                                        1 9:=  >  A B  CD  GH  PQ  R  S T U  X Y  Z[  ^ _ `  a  b  c d e  no  pq  x  yz  {|  }  ~                                 !   "  &  0 9   :   D   !" "  "  " "  " " "+ "H "`  "d "e %      -22 v gH27(2-T (gnN7#2#gNBvv-ZT}(g`7}2 TT}#2(gg2N``T}}#TTZTZ 7722-g27Bnv`n``7#g #N`=7gZ(}g2Z(}#vnn T2((v=-2N#n(gZn} g g g `Z`Z7#n g ggHg#7ZHT``}(g(Z`2BN`nH``=`nZg7(v g`222#7 B7`g`Z77777H22-(HvT#(H} }NH7-22222222222-27Hgggg g g g7 `(2 `-2Z#2gѾ2(g7-2-2Z``Z2 -g7-2-2g`Z27#T2-2-2g7T gN g n g g gg -B 7===N` g`2-2ѣ2-2-2Z`B72N2-2#-27T=222227===n2(22-22#(-272--HN2 v g g`(22#Z-#Z}T2N2-2-27N(2(222=22222-22(27B=H72B7n#H722#7 B7`g`n=HvnB-77g7v 7(B====B-((((-7(BBBBBH nB #nN= vngn(HnHB`Z7g27#Z#72-`-}#` Hv=-22`(2n`(2g`(2g `(2g `(2gZZ(gN}љN#} `7 v=ggg(((B772``g-(2N7#B--7v22H- g-(}72-22g222-222#2----g -`g(n---vZ72727=n2(2(g(-2222(2``Z22N2-22222(--gѣg g g g g gggѣ-gg g g g2 g n g g g ggn2 =(n# Zљ }`#B(-g2-}22BB2T(22222222222(-Z#-22H2222g--2-2Z2(22=22T#v==Z2-2v-##--T`-222272#B}22n727=2222(-22Ѱ2=g-g(-2-}Z =}`#(-7}2vH2-Tn(7# 22nv` # g g g g g g g`(-2222222222222222}(`(-22-2`-2`7Z`-7=Z(-2222}7-2 g(2 `(2 `(2 `(2n22(v#-}N# ZvB7BZTB}}H##((-22g #ZT}- ` g g g`2g#=} vH##Nv }--`ggggg`#(BTv#-}H Nv(#(-`2-v22v22v22v22v22v2-v2`2-v=H gZ Z}gN=vg````````T7-g#7vn}ggg} gя-nggggvZg-g-gnTgZцv gvgggn } 77-BBng 2g 2nBH} = =nNgnZZvgg2 HцT 772#n7Ѿnggggg`Bg Bgg -ggnn# 7=22nv-nggHBg ggg ggTg- g2Z(g`nn Zvgg g g`n7T}Tn ZN=gg g g g g gg nH#n-nggZg2Hgn7ggvg(g ZZ (7=n2gg g g g g`n7TTѰggg=ggZ`gZBg`( g#`-ZT#Z2Bg ggg ggTg- g2Z(BBngg -g -g`HHTg=gggg 7g-gTgngggNHn Bng 2g 2gBHя-2# ZZgg=7g(=g ggZT2 77#vTg v`#22ZHB2--222222- ц`TZ( g2g2g2g2g B =}BZ( g 7`- }g(7(Z(g 2gn2- g`Zg(gZ=n}g(T B T# }-B=v(N(Z H T( g 7`2 }n#2NBTN=Ѿ vg `HnZ n- ѣ gg=`}`H2gg g ѣn-}H n g g g g g g g g g g g g n--gngg`g7 `ggn-`(2 g7N==v77(2# g g 22-`` }}Z7Ѱv2-2T#(--HZH2gTB-(gg=g`ng7 nH g-7 =gn==N7--27B`` (-}T# `nH7-Z-77(BN7Bg g`}H n g g g nn= n g g g g n- gvB((#(vN(2NZvN}Tn}gTn#-77v`}Tn}}=T}`n`ngv g72 g  gngnTZNgnv}`} }-`2Z2#v=27 }NT(TZN gB7v7` BH(g#`7- 2gg````vgg g nZ77777}Tn=` n-g2g#g27`g2g2-g2gg7#Z` H(777= 7v(vn `g `gZgn}-`gnѣ#( g nB#-Z`--(ZBZZgggngљTN-`-2 -2 22222222222222}#- }-2T`72#g n g Ng}H }NTZH#TT#NZ` Hg -Z}v7TT`B}7n}v- 7v7}gZZBN}v `7nT2- }N2 nH#v=-TH n-}--- }N2 nH#v=-(vg( 2Z g-2- }N2 nH#v=-ng(7N(2- }N2 nH#v=-#-77gvv7 2- }N2 nH#v=-=яnn}ng-vѣ`}`=}=ggg((2--T-`#7nN22T(-2#-B--7v22H-gNNѾvN}v T-`}nv#Z`(n-THn#`}nv#Z`(n-(vg(2T`}vn#Z`(n--Tnn22Z#`}}#Z`(n-N}v T-Z}nvv#g g g gggѣ-THn#ZnvvѾ#g g g gggѣ-(vg(2TZ}nnv#g g g gggѣ--Tnn22Z#Zv}v#g g g gggѣ-ng(7(#(22}22ѣT(222-2B-N}v T7(}-n`n`B7nZ# gn7ZTH n-N`-n`n`B7nZ# gn7Z(vg( 2T-v`-n`n`B7nZ# gn7Zng(72((-n`n`B7nZ# gn7Z#-27gg-n(n`n`B7nZ# gn7Zg=N(`77v-27Z-=TH(###}nB} 2=}(2n}#Z((}ZN}v `7Z`2722222222-2-`TH}-Z` 2722222222-2-`(vg(=`Z}2722222222-2-`-Z--`T H-722222222-2-`TH}-Z` 27N-#n}2`g g`#=7(vZ Ѱ-Z##Zg#`B gn gv g  g==Z-g#7vn}ggg} gя`--(TB#Ѿ7vn}ggg} gя7`#v -HѾ2vn}ggg} gяn2( `#BѰ2vn}ggg} gя#-77n`Ѱ2vn}ggg} gя7 ng7n- `2}--- ZTg gяцnv-`TѰNvn} BяZ љv gvgggn } 72#-g=я=nNgnZZvgg2 HцT `--(TB==nNgnZZvgg2 HцT 7`#v -N7ц=nNgnZZvgg2 HцT #-77g`7ц =nNgnZZvgg2 HцT nvѾTvgg g g`n7T-цgTvgg g g`n7TnZ #HT Nvgg g g`n7TTT nn72Tvgg g g`n7Tn2(` #BT2ѾBg ggg ggTg- g2Z(-gBяBngg -g -g`HH`--(TBBBngg -g -g`HH7`#v -N=ѾBngg -g -g`HHn2( Z#=7цBngg -g -g`HH#-77g`7цBngg -g -g`HH2v7ZTNNT`7 -(-2 Bя}B`n ggZ(`T` -gZ( g2g2g2g2g B =}B`--(ZBZ( g2g2g2g2g B =}B7`#v -NT g2g2g2g2g B =}B#-77n`Z g2g2g2g2g B =}B`--(ZBT( g 7`2 }n#2NBTN=#-77n`Z g 7`2 }n#2NBTN=  ѰѰ}} 2#v`(N}g=N}TB gnnHvZ2-}-2g22g=2g 2HH2=Ѿ2#v`(N}g=N}TB} g #7g( HѰvZ2-}-2g22g=2g 2HH-7gTnT-7Hn=TB Z-N#n( 2ZT-g `#2=ZT#`2#( =(2--#2HHN2#N(N n-2v(g-=7B7Z-N#n( 2ZT-g `#2=ZT#`2#( =7(-2HHN2#N(N n-2v(g-B`T7vZ-v2}T2-}(22n22g2222n22n2-g22}T-n}n(# = N 2722-2=2`Z2#-2T22g =2n2=B2vB2-2}N2-`-22nBBg7TNv--n2-`72}T- = 7Z`(n7=-ZZ}22B 2g 2g22B2n#2 NTTH ` g n  n } g ` NNTT `2=(`vN(g7-B7T`NNNT-HH72 #(-TTBBgg NTTH ` g n  n } g ` TZZT  g#g(n`vN(g7-B7T`NNNT-HN72  Zvgg g g`n7Tg}ZZZZ7 ѾHvHn7=22222222222222-2n=#-nHg2 2`}ZZZZ=7= n7=22-2Z#2gv2=B2gZ2-2-2n=#-n-(22222-=-`(2 NHg2--2g2(7=n2g}TTNT` =g`n7T-v#nn` 2g 2g- 2` 2g22g# 2g`T2g 2gN2g2` 72Nn=gTH#`N2n2222=22222222222222----HZN=n``# 2g 2g- 2` 2g22g# 2g`T2g 2gN2g2` 72-(BH##`N2n2222=22222222222222----  Z=(NTN(- (2N=T7gv`(=H(2# ((  T2(T#BB- NT`-BZ ggn-`(-2(T-n-=}---`27v(-N#-2v-T-nљ7vg `g TѰg g} BяZ#22ѣ2}N2-v22g2-22N2(22=22B2- (gTn(gg2g7ggggg=(v22ѣ2}N2-v22g2-22N2(22=22B2- }`(n`Tv(gg2g7gggggNnHZ7Z2n77= n#}#v2(2--(B((Nn=nTT#NTBvT v7-v#2HZ##2n77= g#}#v2(2---H7nn-#NTBvT v2(v#2HT`2-B}T }HvvvB-v#-}(NT##7# я-Zv22T2 77#vTg v` nvvvv`vg-(ѣ72 }B`((TZHZN=n` nvvvv`BN72=n -}H`(((77 vn` 2g 2g 2g 2g 2g 2g 2g 27#(72g2 ((-#77 (#2222222222722 22}=2=-TvngHv-n` 2g 2g 2g 2g 2g 2g 2g 27#(72g2 ((}`T B-}Hg(2222222222722 22}=2=--Tnn22Z-Zg27N-#n}2`g g`-v#vn22ZTTT--``27 ZNZZ``27n#}v( }vn =N}`ngNZTZ``222ZTTT--``27 ZNZZ``2( }vn =N}`ngNZTZ``2B}T }HZ}vn#vѾ#Tg7=n-я-Zv22  vg `HnZ B-(gg=g`ng7 nH 7TvZvNѣ 7`#} -Nя-Zv-2 =HZTNT=g`nn Bng2nZ}2-}2Nng}H}n2( g #H=(#}((( #-N=T=nn2H`#g=H` TZ `g--g22v22Ѱ22-Z22-- ZZZZ`B7B`ZZZZZZ``N =n-vgZ ggggn--n ` ggggg7H--}v2-#(Z72vvBvZ-(2-2}2=7N} HZ 2- 2(2}2B2Z#n2ngѣZ` g gnH2ngѣZ`T-nH Z72272=gn`- Z`(  7` `n(TH7}=}}=}2v(`7(gnn}-=} 2}7n vTn-=7(7v2BT `B}2nN#Zg22 #gH(}-# (TnZ(TT( g2TZ-2Ng2 2v72nZ`N-gZgZ(gN}љN( H7 v=B(( }Z--222222222222222227NTvѣgN}=HgBggZT =vnnvBN-HH(n } gvZ722=BZ7gg}   T nvѰ N TT`gg g T-22g v`v(#B Z`#}gZ(`( #7nZ-g# B7(BNBB(`#-7#g=BH `7=}v} vn#T-B Tv`B v#BNB2`- Zv2#n7(7=(v(}#-gNvn ZBv`H=v#==g  -Zggg gg gg gg g nH#=7=gn g-TgBggg gg gg gg g nHOCRAStdOCRAStdsound1.wav000066400000000000000000000240201250202676700360540ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus/dataRIFF(WAVEfmt MMdata'~~zzx|sx{z~||}vz{~~uotswxvx~zw|~}|tkhiqzuxz|uejmtsfdokjhs{trnigccdsvoh_ebcbesoZYb^Xbjt}rlfcUSS^by{~{vm^UQIS^nq|{iXTHJRfio{of[JMMQfdn||oeUFGQWZi{~td[IDHRfjt~r_UMHKR]hnxqcWJ?IZbir}tgI;DR^^fsû~wdSDDQVXdn[J>LY^aenrYCADRaZh~Ƶvh_QMDPW_crlXI:ELXcd{{fM>BLZZ_ksŹkL?DLMSdtÿt\JFMSYV_lzq[L5CT[bjo{ǿubH?FOTZi{þztXIAPOValy~oROHKL]dfsbOBEKTYju~obHGV\LZclyõt_NDEHT\m{~m\H>JTYlrv~wqaPMTRVZ_woG1BIVfqwȿ~|zlZNLMOR`j{]H9HK]^iyxh[IKKY^\guoWDADNXix}mbVJNSP\fnzn\MHBTaekkunV?OUL[aguxbOHQH[dioxŶhSGHHSVfoq^X[USIT^ktƹwlZOF>O_pt||o_UTKMSdlktv]N>DK[djs{wi_MELU^hkr÷|hSEJGZ^iu}lN=9GXfjwbRQOMUV_`u½nW<9?Nddnwƹ|cNDBP\ZdqĴlcKAHOOUk~re_OCIWW]kxmUOFROTXtzeaS?ALSftjQINOQWbbn{ƽ~hZNDDKQbhrŶ~_KEJLTUeju}{fV?EKKQfo{j^JHJHTXfy{nYOEMRNXix{u]HKGJTeqzpJ:BLWbtrxŶ|t\KGKIR^qpVJ?HVahho~þ|rogO8L[ajgitze??GKYdmvvhMDJZ\_hcn|dL?CTV`fu~ǾzeQIDHKYfwf[TQKO^_dtgLIFMRegn~~r]ZVRORXks~s^K>FL\ivxljdZVJSXbgw¶xhXEA?Tgjy}wee^OJBZ^mtvƶyvfNHCFZbhv|kaF:G[aegujOH>L]Zdri^LFFY^^blw]I@?GYfn{¶zjZSLEK[^ktyiQ=DNX^_jzƷyhH8EGN_jwIJwrfYMBGZX^lrXF:?L_iev~žzo\FKEHRZfw~tm\LDEEZbq|x_QGCJW_hnsĿxsYFAJQUjorgREBTX^iqwsfUKMR[Z^i{y]F9F]_cgo¶~kZRGOMTZivr_KDGMXejtxycOFKJK^iv|jWKKOZSesq~tVEILNUcqld[NHLTant~zwnYCCNR_grxrdICNSY]sxvfVJQQ\bei~|lXJHNZhw}lbNDHMTbbm{þ¾v\G?JQY_t{hVDFTdnoleciؿoUE0-8K_qtshabvɭ|[?2,.>Wjvxnedm޿lL4($.Jet}ymefvѬ|X/$,E[mz}wkbq߼d?&"'6Ogw|oijϮrL+"-1A]tvljw~[?+#$9Ul{}tko̪nI.$".E_w|qkv㽞~c8#:UnqfmάoF(&Dc|zlft㽘~\52Trrhlө}~tL%&Fd|~nes⼚{]84Usuko~ͨ|~vJ)'Bcz~qkv澜{a<$3Rowhhҫ~|uN++D\y~nitƢz_>*-Kjyoqܴ|{vU4':Yuxqtȣ~eB*!#-Jh~{rtڶ|_;&!:VoynrͪtL*'Ca}uls߻~[:$'6QlzosӮqO4&!.C]uxv|äfJ-$%5Jfztr~ײxV1!)D[rytrƦc:$)8Hdz~srܹ~xO4$$(9Sn|rv̪~fD,""*Fbzrmݸ{|T7$"6Vttlsɦ|jD&#.Fd~yoo⺘||X8'$7TswntΩlG,*Ddz{nmz޹^86UosknѪtI%*B]x~rkzğ~^<$-MlxmqկvR8$;YtxrvȦlG(%+?]ytr|侜}}Y;!"/QnxquϫiD*#.B_w~stܾ|V8((39Jdwzqz׷jI4)'),#%1Jh|}swشtS9%,:Wqxuy˫kF0#"*B`ysn}޼yS5%!%7SlwoyέlH-$/?[uxv|ã~{[;,&!,Ng~|vwزsS8!$6Vpyv}ƤiI+-Id{zv~ڷ|\:&%6Uo{tqͩlH*.Dbxus}ܻ~\<("(7Nh~{uvҳrO3%".?Voxu}ǦbB*$1Mgw}trطvS6""/=Xoxv}̮hI,%&2E^vxt~ܻ|Y<*(+6Mh{yrxԲrS4#/BYpxu~˪gE-"$4Hdxvvۼ~uY;.'*7Tl|x~ϬqR8'!/B_szx}¤cD.(#1Kh~|urճoS9&$,=Wryx}̪fH/$$,Dby~xx޾y\=)"'3Lh~|z|Բ|lO8,**8Ws{y˧}eG/$$/Hdy||غ~vY9(()6Smxx̬}gG2&)Faxxv߻}|a>)$%1Mj~wvײ{xW8("(7Wt|svͩ~}jK6*&,B_zwx߿|cH0'%4Ri~}zѱxZ6#$3I\o~{z}ũjF,&.5Khz{xڶ~]='!,?Wo|urϮztM2%#*D^ywr|ägG,&(1Fe}~wwܸ~xY<(#%6Wt{ux̥~mO0#$1Cbyxxž~dD.!"6Lh|xyն|z]<&"-Pf{||պzbH1-4?Vn|ҳ~z^A.*2G]r{~ƫoT;-*7Kex}{ֺ|eI4.5FZfx}̷v[F84:JZm|~ȱs]D62;N]s~~ªnV>45DXht~ʽoWB;>JZiv}õ|lXIBDK[kx}~ûxl\OHLTany}}vndZUV]gqx}~wqjebchnty|}|vokhimsz~ztnjjlry~ytnllqw|}xtomnrw|~|xsooosy}|yusrtvy~~{xvvwy|~|zxxz{~}|zz{~~||}~~~~000077500000000000000000000000001250202676700332775ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus2TwitterSaurus2.pde000066400000000000000000000060561250202676700367270ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-de/Processing/TwitterSaurus2/* Just a simple Processing and Twitter thingy majiggy RobotGrrl.com Code licensed under: CC-BY */ // First step is to register your Twitter application at dev.twitter.com // Once registered, you will have the info for the OAuth tokens // You can get the Access token info by clicking on the button on the // right on your twitter app's page // Good luck, and have fun! // This is where you enter your Oauth info static String OAuthConsumerKey = "uzr17kGYqhgNDjTBNQd1qA"; static String OAuthConsumerSecret = "ZZUfCHruwv4d6Tn9uGz0UGebxfn4oQDikv3NeCbd14"; // This is where you enter your Access Token info static String AccessToken = "221060254-8MJIyVpXotDhemKaJKVN88L1FlCcndToB8y143LU"; static String AccessTokenSecret = "A2R7IkcSniMnBHYeRK02umHoIvrsHQAdx4NaMq6toY"; // Just some random variables kicking around String myTimeline; java.util.List statuses = null; User[] friends; TwitterFactory twitterFactory; //Twitter twitter; Twitter twitter = TwitterFactory.getSingleton(); RequestToken requestToken; String[] theSearchTweets = new String[11]; void setup() { size(100,100); background(0); connectTwitter(); //sendTweet("Hey from Simple Processing woop woop #loadedsith #robotgirl"); //getTimeline(); getSearchTweets(); } void draw() { background(0); } // Initial connection void connectTwitter() { ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setOAuthConsumerKey(OAuthConsumerKey); cb.setOAuthConsumerSecret( OAuthConsumerSecret ); cb.setOAuthAccessToken( AccessToken); cb.setOAuthAccessTokenSecret( AccessTokenSecret ); twitterFactory = new TwitterFactory(cb.build()); twitter = twitterFactory.getInstance(); println("connected"); } // Sending a tweet void sendTweet(String t) { try { Status status = twitter.updateStatus(t); println("Successfully updated the status to [" + status.getText() + "]."); } catch(TwitterException e) { println("Send tweet: " + e + " Status code: " + e.getStatusCode()); } } // Loading up the access token private static AccessToken loadAccessToken(){ return new AccessToken(AccessToken, AccessTokenSecret); } // Get your tweets void getTimeline() { try { statuses = twitter.getUserTimeline(); } catch(TwitterException e) { println("Get timeline: " + e + " Status code: " + e.getStatusCode()); } for(int i=0; ischaltgrenze){ // wenn die Schaltgrenze unterschritten wird timer=millis(); // timer wird auf aktuelle Zeit gesetzt digitalWrite(scheinwerferPin, HIGH); // Scheinwerfer werden eingeschalten } else if (millis()>wartezeit+timer){ // sonst wenn er Timer abgelaufen ist digitalWrite(scheinwerferPin, LOW); // werden die Scheinwerfer abgeschalten } delay(10); // Pause } 000077500000000000000000000000001250202676700331715ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/BlinkBlink.ino000066400000000000000000000012671250202676700347450ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Blink/* Blink Switching a LED on and off This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // integer variable led is declared void setup() { // the setup() method is executed only once pinMode(led, OUTPUT); // the led PIN is declared as digital output } void loop() { // the loop() method is repeated digitalWrite(led, HIGH); // switching on the led delay(1000); // stopping the program for 1000 milliseconds digitalWrite(led, LOW); // switching off the led delay(1000); // stopping the program for 1000 milliseconds } 000077500000000000000000000000001250202676700345525ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/ChaserlightsChaserlights.ino000066400000000000000000000021501250202676700376770ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Chaserlights/* chaserlights This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int pinsCount=8; // declaring the integer variable pinsCount int pins[] = {2,3,4,5,6,7,8,9}; // declaring the array pins[] void setup() { for (int i=0; i0; i=i-1){ // chasing left (except the outer leds) digitalWrite(pins[i], HIGH); // switching the LED at index i on delay(100); // stopping the program for 100 milliseconds digitalWrite(pins[i], LOW); // switching the LED at index i off } } 000077500000000000000000000000001250202676700342025ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_1Exercise1_1.ino000066400000000000000000000023651250202676700367670ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_1/* Exercise 1_1 Blink Rhythm This program is blinking an LED a rhythm. This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // integer variable led is declared void setup() { // the setup() method is executed only once pinMode(led, OUTPUT); // the led PIN is declared as digital output } void loop() { // the loop() method is repeated digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(1000); // stopping the program for 1000 milliseconds digitalWrite(led, LOW); // switching off the led delay(1000); // stopping the program for 1000 milliseconds } 000077500000000000000000000000001250202676700343445ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_2aExercise1_2a.ino000066400000000000000000000056741250202676700373010ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_2a/* Exercise 1_2 Blink SOS This program blinks SOS in Morse code with an LED: * short-short-short = S * long-long-long = O * short-short-short = S This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // integer variable led is declared void setup() { // the setup() method is executed only once pinMode(led, OUTPUT); // the led PIN is declared as digital output } void loop() { // the loop() method is repeated digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, LOW); // switching off the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, HIGH); // switching on the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, LOW); // switching off the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, HIGH); // switching on the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, LOW); // switching off the led delay(500); // stopping the program for 500 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, HIGH); // switching on the led delay(200); // stopping the program for 200 milliseconds digitalWrite(led, LOW); // switching off the led delay(2000); // stopping the program for 2000 milliseconds to have a longer break } 000077500000000000000000000000001250202676700343455ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_2bExercise1_2b.ino000066400000000000000000000027051250202676700372730ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise1_2b/* Exercise 1_2 Blink SOS an alternative way This program blinks SOS in Morse code with an LED: * short-short-short = S * long-long-long = O * short-short-short = S This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int led = 13; // integer variable led is declared char signals[] = {'.','.','.','-','-','-','.','.','.'}; // variable storing the signals: . = short, - = long void setup() { // the setup() method is executed only once pinMode(led, OUTPUT); // the led PIN is declared as digital output } void loop() { // the loop() method is repeated for (int i=0; i=1; i=i-1){ // chasing left (except the outer leds) digitalWrite(pins[i], HIGH); // switching the LED at position i on digitalWrite(pins[7-i], HIGH); // switching the LED at position 7-i on delay(100); // stopping the program for 100 milliseconds digitalWrite(pins[i], LOW); // switching the LED at position i off digitalWrite(pins[7-i], LOW); // switching the LED at position 7-i off } } 000077500000000000000000000000001250202676700342045ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise3_1Exercise3_1.ino000066400000000000000000000034261250202676700367720ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise3_1/* Matrix Exercise LED-Matrix displaying a different image This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // pin order for Arduino UNO int rowPins[8] = {9,3,2,12,15,11,7,6}; // matrix rows connected to the Arduino int colPins[8] = {13,8,17,10,5,16,4,14}; // matrix columns connected to the Arduino // pin order for Arduino MEGA // int rowPins[8] = {9,3,2,12,55,11,7,6}; // matrix rows connected to the Arduino // int colPins[8] = {13,8,57,10,5,56,4,54}; // matrix columns connected to the Arduino int image[8][8]={ // the image shown on the matrix : 1 = LED on, 0 = LED off {0,0,1,1,0,1,1,0}, {0,1,0,0,1,0,0,1}, {0,1,0,0,0,0,0,1}, {0,0,1,0,0,0,1,0}, {0,0,0,1,0,1,0,0}, {0,0,0,0,1,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; void setup(){ for (int i=0; i<8; i++){ // all pins are declared as outputs pinMode(rowPins[i],OUTPUT); pinMode(colPins[i],OUTPUT); } } void loop(){ for (int y=0; y<8; y++){ // rowwise for (int x=0; x<8; x++){ // check all entries of the array from left to right if (image[x][y]==1){ // is the entry 1 digitalWrite(colPins[x],HIGH); // switch on column pin } else { // else digitalWrite(colPins[x],LOW); // switch it off } } digitalWrite(rowPins[y],LOW); // switch the row pin to LOW (because it is the cathode of the LED; LOW means ON) delayMicroseconds(100); // stop the program for 100 milliseconds digitalWrite(colPins[y],HIGH); // switch the row pin to HIGH (this means OFF) } } 000077500000000000000000000000001250202676700342055ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise3_2Exercise3_2.ino000066400000000000000000000051471250202676700367760ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Exercise3_2/* Matrix LED-Matrix displaying a little animation This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // pin order for Arduino UNO int rowPins[8] = {9,3,2,12,15,11,7,6}; // matrix rows connected to the Arduino int colPins[8] = {13,8,17,10,5,16,4,14}; // matrix columns connected to the Arduino // pin order for Arduino MEGA // int rowPins[8] = {9,3,2,12,55,11,7,6}; // matrix rows connected to the Arduino // int colPins[8] = {13,8,57,10,5,56,4,54}; // matrix columns connected to the Arduino int imageNr=0; // stores what image is currently displayed long timer=0; // timer variable int timeOut=200; // time an image should be displayed (ms) int image[2][8][8]={{ // the first image displayed on the matrix {0,1,0,0,0,0,1,0}, {1,1,1,0,0,1,1,1}, {0,1,0,0,0,0,1,0}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} },{ // the second image displayed on the matrix {1,0,1,0,0,1,0,1}, {0,1,0,0,0,0,1,0}, {1,0,1,0,0,1,0,1}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} } }; void setup(){ for (int i=0; i<8; i++){ // all pins are declared as outputs pinMode(rowPins[i],OUTPUT); pinMode(colPins[i],OUTPUT); } } void loop(){ if (timer+timeOut= 0; fadeValue -= 5) { // fadeValue is counted down in steps of five analogWrite(led1Pin, fadeValue); // and sent to the led as an analog value analogWrite(led2Pin, 255-fadeValue); // 255-fadeValue produces the opposite fading behavior delay(2); // short stop } } 000077500000000000000000000000001250202676700333225ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/FadingFading.ino000066400000000000000000000017251250202676700352260ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Fading/* Fading fading an LED slowly on and off again This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int ledPin = 9; // ledPin is declared void setup(){ // no need to declare the analog output in the setup } void loop(){ for(int fadeValue = 0; fadeValue <= 255; fadeValue += 5) { // fadeValue is counted up in steps of five analogWrite(ledPin, fadeValue); // and sent to the led as an analog value delay(2); // short stop } for(int fadeValue = 255; fadeValue >= 0; fadeValue -= 5) { // fadeValue is counted down in steps of five analogWrite(ledPin, fadeValue); // and sent to the led as an analog value delay(2); // short stop } } 000077500000000000000000000000001250202676700336455ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/FlipFlopFlipFlop.ino000066400000000000000000000020261250202676700360670ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/FlipFlop/* Flip Flop switching between two LEDs using a button This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int buttonPin=2; // Pin where the button is attached int greenLED=9; // Pin where the green LED is attached int redLED=10; // Pin where the red LED is attached void setup(){ pinMode(buttonPin, INPUT); // button is initialised as INPUT pinMode(greenLED, OUTPUT); // green LED pin is initialised as OUTPUT pinMode(redLED, OUTPUT); // red LED pin is initialised as OUTPUT } void loop(){ if (digitalRead(buttonPin)==LOW){ // if the button is pressed (LOW) digitalWrite(greenLED, HIGH); // switch on green LED digitalWrite(redLED, LOW); // switch off red LED } else { // else (if button is not pressed) digitalWrite(greenLED, LOW); // switch off green LED digitalWrite(redLED, HIGH); // switch on red LED } } 000077500000000000000000000000001250202676700347645ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/FortunetellerFortuneteller.ino000066400000000000000000000021651250202676700403310ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Fortuneteller/* fortune teller switching between five LEDs to tell the future This example is part of the Fritzing Creator Kit: www.fritzing.org/creatorkit. */ int pins[] = {8,9,10,11,12}; // the pins of the LEDs are stored in an array int tiltPin = 3; // pin number where the tilt switch is attached void setup() { for (int i=0; i<5; i=i+1){ pinMode(pins[i] , OUTPUT); // LED pins are declared as outputs } pinMode(tiltPin,INPUT); // pin of the tilt switch is declared as input randomSeed(analogRead(0)); // initialize random number generator based on random state of pin zero } void loop() { if (digitalRead(tiltPin)==HIGH){ // when the tilt switch is open for (int i=0; i<5; i=i+1){ // all the LEDs digitalWrite(pins[i],LOW); // get switched off } // int myRandom=random(0,5); // a random LED digitalWrite(pins[myRandom],HIGH); // is switched on delay(20); // the program is waiting to breath } } 000077500000000000000000000000001250202676700333765ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/MatrixMatrix.ino000066400000000000000000000034171250202676700353560ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Matrix/* Matrix LED-Matrix displaying image This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // pin order for Arduino UNO int rowPins[8] = {9,3,2,12,15,11,7,6}; // matrix rows connected to the Arduino int colPins[8] = {13,8,17,10,5,16,4,14}; // matrix columns connected to the Arduino // pin order for Arduino MEGA // int rowPins[8] = {9,3,2,12,55,11,7,6}; // matrix rows connected to the Arduino // int colPins[8] = {13,8,57,10,5,56,4,54}; // matrix columns connected to the Arduino int image[8][8]={ // the image displayed on the matrix : 1 = LED on, 0 = LED off {0,1,0,0,0,0,1,0}, {1,1,1,0,0,1,1,1}, {0,1,0,0,0,0,1,0}, {0,0,0,1,1,0,0,0}, {0,0,0,1,1,0,0,0}, {1,0,0,0,0,0,0,1}, {0,1,1,1,1,1,1,0}, {0,0,1,1,1,1,0,0} }; void setup(){ for (int i=0; i<8; i++){ // all pins are declared as outputs pinMode(rowPins[i],OUTPUT); pinMode(colPins[i],OUTPUT); } } void loop(){ for (int y=0; y<8; y++){ // rowwise for (int x=0; x<8; x++){ // check all entries of the array from left to right if (image[x][y]==1){ // is the entry 1 digitalWrite(colPins[x],HIGH); // switch on column pin } else { // else digitalWrite(colPins[x],LOW); // switch it off } } digitalWrite(rowPins[y],LOW); // switch the row pin to LOW (because it is the cathode of the LED; LOW means ON) delayMicroseconds(100); // stop the program for 100 milliseconds digitalWrite(rowPins[y],HIGH); // switch the row pin to HIGH (this means OFF) } } 000077500000000000000000000000001250202676700332325ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/MotorMotor.ino000066400000000000000000000027561250202676700350530ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Motor/* Motor turning a motor clock then counter clock wise This example is part of the Fritzing Creator Kit: www.fritzing.org/creatorkit. */ int motor_A=6; // motor A Pin int motor_B=5; // motor B Pin int motor_Speed=3; // speed Pin void setup(){ pinMode(motor_A,OUTPUT); // pin A declared as OUTPUT pinMode(motor_B,OUTPUT); // pin B declared as OUTPUT } void loop(){ digitalWrite(motor_A,HIGH); // motor A pin switched to HIGH (+5V) digitalWrite(motor_B,LOW); // motor B pin switched to LOW (GND) for (int i=0; i<256; i+=5){ // count up to 255 in steps of five analogWrite(motor_Speed,i); // and write it as speed to the speed pin delay(20); // wait 20 ms } for (int i=255; i>0; i-=5){ // count down from 255 to 0 by 5 analogWrite(motor_Speed,i); // and write it as speed to the speed pin delay(20); // wait 20 ms } digitalWrite(motor_A,LOW); // motor A pin switched to HIGH (GND) digitalWrite(motor_B,HIGH); // motor B pin switched to LOW (+5V) for (int i=0; i<256; i+=5){ // count up to 255 in steps of five analogWrite(motor_Speed,i); // and write it as speed to the speed pin delay(20); // wait 20 ms } for (int i=255; i>0; i-=5){ // count down from 255 to 0 by 5 analogWrite(motor_Speed,i); // and write it as speed to the speed pin delay(20); // wait 20 ms } } 000077500000000000000000000000001250202676700342335ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/NightlightNightlight.ino000066400000000000000000000047161250202676700370530ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Nightlight/* night light fading through the colors of a rainbow This example is part of the Fritzing Creator Kit: www.fritzing.org/creatorkit. */ int LEDGreen=9; // LEDGreen pin declared int LEDBlue=10; // LEDBlue pin declared int LEDRed=11; // LEDRed pin declared void setup(){ pinMode(LEDRed,OUTPUT); // pin is output pinMode(LEDGreen,OUTPUT); // pin is output pinMode(LEDBlue,OUTPUT); // pin is output } void loop(){ for (int frame=0; frame<900; frame++){ // frame is counted up from 0 to 900 if (frame<150) { // if frame < 150 => red analogWrite(LEDRed,255); // LED switched on analogWrite(LEDBlue,0); // switch off LED analogWrite(LEDGreen,0); // switch off LED } else if (frame<300) { // if frame < 300 analogWrite(LEDRed,map(frame,150,300,255,0)); // fade off LED analogWrite(LEDBlue,map(frame,150,300,0,255)); // fade on LED analogWrite(LEDGreen,0); // switch off LED } else if (frame<450) { // if frame < 450 => blue analogWrite(LEDRed,0); // switch off LED analogWrite(LEDBlue,255); // switch on LED analogWrite(LEDGreen,0); // switch off LED } else if (frame<600) { // if frame < 600 analogWrite(LEDRed,0); // switch off LED analogWrite(LEDBlue,map(frame,450,600,255,0)); // fade off LED analogWrite(LEDGreen,map(frame,450,600,0,255)); // fade on LED } else if (frame<750) { // if frame < 750 => green analogWrite(LEDRed,0); // switch off LED analogWrite(LEDBlue,0); // switch off LED analogWrite(LEDGreen,255); // switch off LED } else if (frame<900) { // if frame < 900 analogWrite(LEDRed,map(frame,750,900,0,255)); // fade on LED analogWrite(LEDBlue,0); // switch off LED analogWrite(LEDGreen,map(frame,750,900,255,0)); // fade off LED } delay(10); // short break } } 000077500000000000000000000000001250202676700336535ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/PingPongPingPong.ino000066400000000000000000000206431250202676700361100ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/PingPong/* Ping Pong game LED-Matrix is used to play Ping Pong This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ // pin order for Arduino UNO int rowPins[8] = {9,3,2,12,15,11,7,6}; // matrix rows connected to the Arduino int colPins[8] = {13,8,17,10,5,16,4,14}; // matrix columns connected to the Arduino // pin order for Arduino MEGA // int rowPins[8] = {9,3,2,12,55,11,7,6}; // matrix rows connected to the Arduino // int colPins[8] = {13,8,57,10,5,56,4,54}; // matrix columns connected to the Arduino int pot1Pin=18; // declaring the pin for player 1's potentiometer int pot2Pin=19; // declaring the pin for player 2's potentiometer int image[8][8]={ // clear {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; int death[8][8]={ // all on {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1} }; int death2[8][8]={ // skull {0,1,1,1,1,1,0,0}, {1,1,1,1,1,1,1,0}, {1,0,0,1,0,0,1,0}, {1,1,1,1,1,1,1,0}, {0,1,1,1,1,1,0,0}, {0,1,0,1,0,1,0,0}, {0,1,0,1,0,1,0,0}, {0,0,0,0,0,0,0,0} }; int blank[8][8]={ // all off {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} }; long theTimer; // timer variable int gameState=0; // storing the game status int animations=300; // storing the duration of the images between the games float ballXSpeed = 1; // storing the x acceleration float ballXPosition=4; // storing the ball position as number float ballYSpeed = 0; // storing the y acceleration float ballYPosition=4; // storing the ball position as number int imageYPosition; // storing the image position as number int imageXPosition; // storing the image position as number int player1Position=3; // storing the paddle positoin of player 1 int player2Position=3; // storing the paddle positoin of player 2 int gameSpeed; // storing the current game speed void setup(){ for (int i=0; i<8; i++){ // all pins are outputs pinMode(rowPins[i],OUTPUT); pinMode(colPins[i],OUTPUT); } } void draw(){ for (int y=0; y<8; y++){ // rowwise for (int x=0; x<8; x++){ // from left to right, entries are checked if (image[x][y]==1){ // if entry equals 1 digitalWrite(colPins[x],HIGH); // the column pin is switched on } else { // else digitalWrite(colPins[x],LOW); // the column pin is switched off } } digitalWrite(rowPins[y],LOW); // switch the row pin to LOW (because it is the cathod of the LED LOW menas ON) delayMicroseconds(1000); // stop the program for 1 seconds digitalWrite(rowPins[y],HIGH); // switch the row pin to HIGH (what means OFF) } } void update(){ switch (gameState) { // switching game mode (called state machine) case 0: // new game memcpy(image,blank,sizeof(blank)); // clear screen gameSpeed=300; // set the game speed ballXPosition=3; // set ball position ballYPosition=3; // set ball position ballYSpeed=0; // ball should fly straight if (random(0,2)>0){ // but randomly left or right ballXSpeed=1; } else { ballXSpeed=-1; } theTimer=millis(); gameState=1; break; case 1: // game active image[player1Position][0]=0; // paddle player 1 clear old position image[player1Position+1][0]=0; // paddle player 1 clear old position image[player2Position][7]=0; // paddle player 2 clear old position image[player2Position+1][7]=0; // paddle player 2 clear old position player1Position=map(analogRead(pot1Pin),0,1023,0,6); // reading the position of player 1 player2Position=map(analogRead(pot2Pin),0,1023,0,6); // reading the position of player 2 image[player1Position][0]=1; // paddle player 1 display image[player1Position+1][0]=1; // paddle player 1 display image[player2Position][7]=1; // paddle player 2 display image[player2Position+1][7]=1; // paddle player 2 display if (millis()>theTimer+gameSpeed){ // timer for game speed if (gameSpeed>50) gameSpeed-=3; // accelerate game theTimer=millis(); // set new timer image[imageYPosition][imageXPosition]=0; // overwrite old position ballXPosition+=ballXSpeed; // update position ballYPosition+=ballYSpeed; // update position if (ballYPosition>=7) ballYSpeed*=-1; // collision bottom border if (ballYPosition<=0) ballYSpeed*=-1; // collision top border ballYPosition=constrain(ballYPosition,0,7); // constrain values between 0 and 7 ballXPosition=constrain(ballXPosition,0,7); // constrain values between 0 and 7 imageYPosition=round(ballYPosition); imageXPosition=round(ballXPosition); if ((ballXPosition>=6)&&(image[imageYPosition][7]==1)) { // if ball hits a paddle ballXSpeed*=-1; // reflect the ball ballYSpeed=random(-2,3); // random reflection angle } if ((ballXPosition<=1)&&(image[imageYPosition][0]==1)) { // if ball hits a paddle ballXSpeed*=-1; // reflect the ball ballYSpeed=random(-2,3); // random reflection angle } if (ballXPosition>=7){ // ball out gameState=2; // change status to lost game theTimer=millis(); // new timer is set } if (ballXPosition<=0){ // ball out gameState=2; // change status to lost game theTimer=millis(); // new timer is set } image[imageYPosition][imageXPosition]=1; // set new image position } break; case 2: // game was lost if (millis()>theTimer+gameSpeed){ // wait for a short time theTimer=millis(); gameState=3; // game state to lost game display } break; case 3: // lost game display memcpy(image,death,sizeof(death)); // show image of lost game, memcpy is a function copying one array to another if (millis()>theTimer+animations){ // wait again gameState=0; // game state change to »start a game« } break; } } void loop(){ update(); // all calculations are in the update method draw(); // all display methods are in here } 000077500000000000000000000000001250202676700347705ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/PotentiometerPotentiometer.ino000066400000000000000000000017611250202676700403420ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Potentiometer/* potentiometer two LEDs are controlled by a potentiometer This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int ledGreen = 6; // LED pin is declared int ledRed = 5; // LED pin is declared int potPin = 0; // potentiometer pin is declared void setup(){ // neither analog inputs nor outputs have to be declared in the setup } void loop(){ int value = analogRead(potPin); // this variable stores the value from the potentiometer int redValue = map(value,0,1023,0,255); // mapped from a range of 0 to 1023 to a range of 0 to 255 for the red LED, int greenValue = map(value,0,1023,255,0); // and for the green mapped to the reverse range from 255 to 0 analogWrite(ledRed,redValue); // the recalculated values are analogWrite(ledGreen,greenValue); // send to the LEDs as analog values } 000077500000000000000000000000001250202676700332305ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/ServoServo.ino000066400000000000000000000015301250202676700350340ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Servo/* Servo a potentiometer controls the position of a servo This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ #include // include the library Servo.h Servo myservo; // creates a servo object int potpin = 0 ; // potentiometer pin declaration int val; // val stores the position of the potentiometer void setup() { myservo.attach(9); // connects a servo object to pin 9 } void loop() { val = analogRead(potpin); // potentiometer value is read out val = map(val, 0, 1023, 0, 179); // and mapped to the range 0 to 179 myservo.write(val); // turning the servo to the angle in val delay(15); // give the servo time to react } 000077500000000000000000000000001250202676700344615ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/SynthesizerSynthesizer.ino000066400000000000000000000031641250202676700375230ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing Creator Kit/Synthesizer/* Synthesizer creating sound from electronics This example is part of the Fritzing Creator Kit: www.fritzing.org/creator-kit. */ int buzzerPin = 8; // piezo pin declaration int potPin1 = 0; // potentiometer 1 pin declaration int potPin2 = 1; // potentiometer 2 pin declaration int toneHeight; // store the tone height int lfo; // store the frequency speed /* lfo is a "low frequency oscillator" - so a frequency change depending on time */ void setup() { pinMode(buzzerPin, OUTPUT); // buzzerPin as output } void play(int myToneHeight) { // play method digitalWrite(buzzerPin, HIGH); // piezo is switched on delayMicroseconds(myToneHeight); // stopping time influenced by toneHeight digitalWrite(buzzerPin, LOW); // piezo is switched off delayMicroseconds(myToneHeight); // stopping time influenced by toneHeight } void loop() { toneHeight=analogRead(potPin1); // toneheight is value of potentiometer 1 lfo=analogRead(potPin2); // lfo is value of potentiometer 2 for (int i = (lfo/10); i > 0; i--) { // toneheight rising depending on lfo play(toneHeight); // execute play method } delayMicroseconds(lfo); // break for (int i = 0; i < lfo/10; i++) { // toneheight sinking depending on lfo play(toneHeight); // execute play method } } fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/000077500000000000000000000000001250202676700301215ustar00rootroot00000000000000Amplification.fzz000066400000000000000000000352671250202676700333710ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPKl5D]uݏywՙ>?k*-0? gv f/?'xa6vM N(]x7q<dՋ:z04N} K,;w'xy-W|)aY)s^#nܫ. upjw 1ꖘ[o)ewȁ\uTz!ۇ޷osalggѨOGw K~*/忿ЯzxZln0#Νq0|8%\Jثg'DBUw'ThEmXR"S"Rh]BrEZѼPKx֭^ sޛ^ F:b UԃK; ӠrI u#'N}E@ʶ7E%mp2($TiҠ] ˌ'ƿBL}sa^kkEMÈ<qwnVV/(Ev(E;#8}(HAll>gfgMsh]*,KkkCy03nKZsaሃ".$Qm$(Ju)aBbF ѠDžꕺ >5R_H!^w#:ȼ3޶q9á/{:iGRhK?\Hb1#)v4r!Qu!8žHD4.qWrǶOO|}eo2?Liz2']_QBd}?|ktJnu^]1` PC B"ʕ3\2+-BTx]vHc(po~UmZCK{<Ԟߗ4n7W/"!bW5*ocFeʨ㢍q~ &)L8L~^wף)/Ncd(שсAJ)%*b7I\o]}$46q^mUĦoU}3ŵ S<آ搉k25j ɬ:ʜ' DjJZ&Z7W=`ZB܋jFhyh0Gݍ!oMTh[?ۼE7D6_FZØXs#[ܛTնOmVP^ˠ􉁱mkg!,ƴq^1d0KOV}PwRhv1\?X7׳)hc%( 5{Dm2̨ wt(@cK,Q);ĒmE}T<уc'zİHml;(waYc y!M‹I6N2Je7H+t>^N+'! )KUH*gw(Oz.JsbS|t.]58{7kҟ"gѧ|Ӧ#]Q`KwMo]Z0\aXr:/b"=2WKKQk-c6c])ڌHԙRݿ:Ryopx}'r+%H!Ʀ>4X9 6[N $̗Z=fʫߧ҃'9f*Uɠ-lPt}C붒t}#Kꁭ#+;L5{Øyb:˹q>S865>]WP8Y)rZB^%* j<ɹ%_x,\y{ƿC m9kK% f|[.iNk8 \+!(6jilZEQUYiѼZRYSR"zQo4] TPnrSK%^*Z71F$ Sso㷃OdrAsq\> CL[Y~MMӇA~ϟGL_;GOW_f/{?y:!45&)>lPq|}3]u/ߜ6GMi ɞ)CMo~ GpOw/0~%w[ׯEĩЃCx<8 弅(t2r@=; L^{AR^)SXxow{k`t=9 \U=pPԝY|8FN-GњQ~lUh$,I귛ӖB4ߊTF9Kt,oԆR٤uԯˌ9-O:(kv4NZ4nx+4NZ4қ*d9 IY4:Wv軜}{Q'U(--z>1V_b&$w`P%]PrEoԲEeNb^l 2Os6FKꊞTn1 >%hn dK1n:>4Gҍ9_,qtη5bݝD$ (X,q@ )؉WѦfcr&x֮ 9[2wijؾر֊"v7i;/p'x3XlG;-1+eNℐs,91 1Я"-s:L{v0m6~~2>|e?>\Q.< OI߽/[?>wd$u.}'kl0o?7Ol w ~&@bCEg wFnZX۔BNGCBtKWvR޼H:% jTKcԙ6`+ST0l[}c sj~Mj 9ѦmMWm2%9 R&UVU<-:PJnn:4(Bݔt;>.s緁{RU0*-xJzG;HgW1Vڧ'j7w *>=P5VD&|&6RJJp93NGs^2$pg"XqDڂש2npQ=JVXn.bї/7I\:uuI[}FݢW{ QZHQ9VlTNUu jOqDjBY*K5h|)g"ŵk3\{΃\o7ka]#^Zqf<3:,j4J(Q;fIvtZ-X>GʋxYۺr7ףMn+.m$jsֈA x LUlCSWe̖6qjXm4eLsCڍ:)}l:)0fH|$cHp4lgC֑b9I{ #C2gm$̌\EE* qRw݁JTef 9.3;R?&3; s`6Kι0rEwfqH7 9v@Hʼn!$ !=(7(K%.(%D3 }{UʭsH ͈N-S5$[\Ua$ȹY-7[ZtE:cEtsn r"}q7D聴ܬE!$MY$8r@n&W77p3F*S- (SmʐTQ*tiv^T-7-'"7ylnEJdu7,R8I7d )8nh9Y]=,'7d!980'cqp%Yd$ƚ}Z26ߘ㒱# rdHƖ$ U!|fX]M'`dqBH9#6b!w;Z*VWtT,N8'ioB"Q1#<s`8iLx2}F.x?gs1ءsq M:/ףLff)9/.x 45 Ԙ\(VӬ!~E&Ͽu;n8=Q$G-qբ:`x0+O3yEspT4~o/u<"oE}m~Дz8a؟\/n*vvE$0xLe͠hNCU ~y_zQ _m '4͒5Gl:Ô<|p={ mSx(hl~l>WEc%uT/ $6Ly APN?,SS$@~IW~|xA/h "-3&?vo~id̯+Ѳ@3EeDfAyIMIi~d * ʒEl-~|@C)C+ f%)vތ8G-Юpݍ'xrR4˿=}I397)H_ a_ nE; ]z9|)@ ]B.Ax_`klbrGxd + =Dc4Ҹ clכ$|82+ @Mr,:?"?h+t/W6̿EPWqsG[(>e]%@"FX@܈7FvcM7M9TT>ЍkW+];ĵ%.\;]JSvK:Ua)ʄh4^X a8/.e Xē0oA(8D?a67Hf[i ފ^n,>e|=cM^]踟UJA/7k<9({4£:~NKL.LZa S KL-{5Pt 4ANMN~V]c5?zy vc]H%6"}[p;'jU\"̩'P00ȹ}}@6co5*!Fr%Swj1oG)M^ A8LgVnEM2Ur\V tb4tW9*iF >R 4Nj4NhuqHAi4cjl+nD3B{pT_`DQP M@y,+ M:ØYqT@b64>P"=?KA{rÈ TqG֙*m CR`4 qecu84b(!,1 < F Qh*+k7`B!{'{{Jbb̂sTЏ*?1P'PFs[ ĢP%%x@%B/PU<3D&́qnU0(~v2B9 ts 0A#@HJ%MX LpQ p(T2mw㞁'h Q 0tA\wVrXv`!J #0 p>8%$u`BGh DWu*'{!/ A/aIhG0)WLJt(Xj;Hb,Pj{Uk`މ 1VnjϜe` G7H@\V#RZZT/ V!"qF(DE‘>FT$?5 P]Q,rC aH & ZL80P:P ]q (0Ч@cAt[*.Čhg} 0B0r$Ce>)b9!xDCF*@4(8 gLs;ԯ7m9VCZdh)],]iVR NWÕhx@t,hN#ԑ4u8пg.'ת0 1t&!0+h7Eo _8kpr8y>:W6"LqG5hfNvYRS,}H$p?Rt!p~#B^3"%T."U]x!!TDo]34 LXsCHC~2 BCdp WAwFkN/}B8t11],%,f`n@Ɂ n/zʊW~= 3 0CqY&zR~'D;cG%S  ~ F/DA5,; `@"8捦E# |M9x"{$Hc7l׶Ǩ@D<#bJA'"B3̶`Sp EX566d9t=d0sy'D} npT c*h;F&iup >vv$F0iSx$:P#.D }kVP? p 0G݊arAojߔaL'ƫk?*$ `bKSLP1vs9Q>*HPy!nC(#M|I 09C0 41KRUݢ F0l@0M6 .ChMCd0C`60MWvYj+̄`!Ya bCگJs:hR`@. `U#1u (s87E/0Eۋs.P%кaePFGF .| U֪)[+zr0q#x`]ݼ.-,f) Fc `8?hmLR-@HA81A2d'@SugL!%(C`v`MIz qGҚT`p&DD} ñJOG73`'h~ lIGmwM'6*QGD7evU;bʏs(,91+Ww)Y>Sl5ZRI2xaJF,襤i!s@Jo"}U| {P-ph1>"ނP;joiyǥH U劃WؒGS A1G~OL(QܩVT]jj5K>6 גo"Z.g URC B cKqhr<ѪP BBe$$T%B%\FGĉcK!T@ft P(P{xdR_8@fʔ(Fy߈)=A#y11)Go]0 ems g80H D7,rh'pfXVCW Yqg(gy2oCxg<&ckaص9Dd1aYD?%8 s$͙~as5f^0YtML YdiB & +M8& ~Sv`9y-:41]yt;3`eIzR_<(ǏJs Wsb: 3QL1B阁Ŋ^dvCfQ mym]%d􉅯B9zטGsS8HD!W19I0H0%p(' O'APLƢ(RX?(Ǣ)EYE:E>]sЀfIucl7`k`I>ٿ%]0e #F2dKx iҾ>D{Hi) dO!6~=X㋯#7屳@4>3ba(74%ϕJ7 L+qF]ά\g+\,(xyme_lE\)tqRY"~xXD;E`QN`$|,\Xb]:0a*0 :hZp]s@LLr2{$^ ,!'ȂOØ'8NAa_[ k5ON8 I*P0l #,8Y~ pRK_uU"^;s EC\# |<(wMHo ː&n-c0Q񃱽$هcqp.:xWiY`q2%|LB/~ܓGʔǡXeH^ܾzSƫ a gOf,J_A!|˽͵s<GHg\usw)]O?蚭6P 7ɦw) Y櫨o΋7"~kKKhnE)˅ s^RRέ_}O_/?KVZX|[+GHI=hPjli5WUWnq>R^Ќh rSф JDƊkI* q>B^ϹMMKg`#Sy| DrabT%Dfڿof-[^9k::'Ao0 zͧH؞k01 sA:6ޒڢ{HTQbK{Ӧ^mvyV݌& X#Ɖ㳭9 i P!/Zl[ˋ!]3N8siG[|KG÷R/OATjUF֊DBnA^{c ׎3mki\S"rXlv(#9-!+E:IL$dDBJO~mjWm9d`9]}tDl3@֥[W]65"i N`|)&hA $7Y-/;6IKΉ:H/$wDJARzr)(&Ur."rrw)r/EȪ'xͣj^MѦKPHOw[? jG,X˸e8c:AutomaticLightingSystem.fzz000066400000000000000000000457701250202676700354330ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPK|8Dj ]H AutomaticLightingSystem.fz}r#Ǒqv#f/<= @P3V d*4.$Ptx/*8<gtMUg8LoG/=soan6Z|rK IMBhDBoUg4?$O+we}q3nSMWOh2xo0o:b}&7Z)pg>e/>+b4x]bMg>`h[}/:lؿs_^un_g7=s?44j@Gaw3/CB)~vzv6}j8濹^ӁaOv we{i駻Kbn~: <G g|0:|ߜ:k~._f{~gPnRvGn*̕?}8ar;:ISwxU2M_9xLg_r]L>=_N_\WK-{C%]wr-b$Dwq(a:4xB%np]D)A#?%.)VbMCUG_ڿR' ] ~W+=kQ*_9 XUWdG-&߫t}>"\{}Kcxfíڡ5r־AI^/=K5U֨Gj7Y暷Yߜ[cI˼BljmW&sA5>m_ŕ:m?eUO̥l9mV8#^wg&sM|,2d#߭q@[v  i3~?ř>mW]2$Vq}^xv +m-s⮊_Z7J.Q9 Me.a2>= gt'{ɋڊsOJn J|ʼn's_7m>B![F,99'ig*8it -sMڈ%=Ӥ?y&3dF>)&i[L0i쒶 ڥTp}JZg<>9%PB>$mi[& M{&Id}nvYsHj9g?3HWssH^ZER:uH2E=}>A!ND9$-i#&i|}-3Jډ(=2?Y%m3WN?%-i_-iޥp}3LZ g<Ǥ>Y&mgJ ?&i{[暴 S{I}nw3Ng* w z6OS_Ö@7-Z'OQaa[$Dy}~q~ଟqOb֟wGcw2c sWNq6A:ӧ`o}6hiY'jmB9&Jݽ()vIrwo덽:̺S6Yt%q3XX]`_NI?Ko2%ΡzUi.is$zaT%2 h)_&ɍ)V1'k8+dJ1HEw(5)Kz9X+tpභYAn\d^'!#2ʯPn%8' c1)2}>n ? ѝ$sUbωVdjيg0YӀɜ S3 1,{HVSB)Q}ªH~ƚXQ_/& f/$ DbψBV 5TeIOAR%fVjwcrEdNNF' &R$Df~ˆ3%fU8GLɖU%\X0TRX*sP_N3C;5NJ~'+v)n[N1g iK*V&A2҈#}6Q6Z*G#OJG?~~Z'X#-}Ӊ?Fdd8 zJ4:{ؙ^\:{ŰݟeZf;0+~c@zTim:H靈#'sk)2UYMd)\Ź?k-^]"OXKbvS4Od{tR$Z^۟ K57W.`81Ԍ1 hQ(E8[sZ]L71VJjI㌯ nze@hmyPjVϘP)_=<QhȒ@hb}!pKy4݌'W')Kkn>\}~stu1x'ti5YX{A~:toxcۘ;6F k+{/j^ըS4^B|mťD@[uTCXQ2A_lO'H)2%1YYb$Ƥeqm"5Wzrhlղ&Ty#Йfֶjevhī|Me־}6E۫Lmdr(_hE=^$|4wn .t<^f1oO˰u˜w>7ϮThM)}("Ez0C0IV,s@ΏM2kKY3pY:Jב#&,)Pf SKkepMsA-3'n=|x936hz7&s+K*H\^JbY=pTI5 ~R8:>ACbV g-.g۵ UROc8s+]c8SZQYB9\JD,i iB$MJDĤɥ%MZiя^1krvbOc6xi](iʼnTQj2$ i1XE)VQ:.Lf1$ ^P$QxZmc>e^`i#M/jCnY%,< ׫6Z[P%VZ;%U8?[!^_rfɼŸQʄt:Lu*lũJ?T֦`SU۬6tmm*'$HntS)1%rRf1Yב3,Ku` ťD6nt*fkgr8cwwY+;PuXr'ݝY&]zѦR$[6\)ՉpXDpR웎ɷ[ތUЄ762]A,n4LD;}T}XRևI0; F89%y04S9OY*WiCu4gM)g%M6EQ-Ւ0y)H$+|e$+jm)${}.5W-G+ZdB[PQ =RVFMP3-U$QFUpU53'[$RfհF".%=ܛgc#dG7zrp W8;vK 6IA1[z bkzgz-FK",Qg:LyK _Opn+0&ZנbO*N:}&vgjg0Aqֆ0I*!oeBq2a"kדzPr(e@M E;7=-)Ff bE7͕Z8S3{l=Z257<<0Xf|*CV]:5yM|mv!U~KKWmN/"++{s| LnU4{39Kfr=},SYGB~lQTdH5 pUXqNC͈XeÀiᬆ]Osé"]jYSl3I𼮘b.LuZ]Zw=,"pBԹCPc05V!l(uC'c HuJhh$ii"E,SE|}a檺QLcrYNtVM"Q0<1-*.ItPbsU4:C!vE"[#DadYF3l4+U"Q.6)aW=b$n-FHʽ9>\\)7gYM* ݫؘ4}WO}]^5m]BNX'EVxtej$U}.rD"Id4e]7 s_\5F x]ojHS VjZjӖBRKㄔڴ1pB^/_]:V]/ҍw TF v:PaŸ*VBJuޙ.Ix H]tENT?I*oxqjݙi-0[75@In%EܟنY$Etb*rIgr4xZҮXƮb~ pEvxtت;|fp bJ粣K(sQk= e`DסU,Z#bՐ.cV\f*I/;/$%#$tV%pzsLm.TJHCە|MsV8K/-mA&z #ˍ8逩缵ɴ7h8]JjLVgL'n6Z|M+nom`/ߦ+lP|3?WVL`}Ջ -yq)lV3z\lӉ!VV:cpnXop<5ōLYSn" *R-hU̠ʊ[Wr#nZn\0E8y_\ߺo?!#Vh.p\xsXeDB2^ЄJ(iVLXSOacwMo2QtμLV SF7+ DeOYb:Q墷< S̚rT"NbNܛCD:qRp]V2()&Yqq-[˦ u薒:# )`)Tn5E8ڌg[Sq5Hn9ukz$sji Y[*UX#sp yMtU6J!V~X$mDQ.UM:cI[ snF"q[MGOi'8}iM'RVEX4(H\|f ]X]֨x3p[R׼eSqO"I"+h, UHTd48I㑐TWρdĕڒ1SH8+c} g6*Չ(xI\ @I\7HrgB^v$TJDǞUpU׾#1?`6 *#{k#o5eϡ 8& q[ gP@dô-Df3qY+EtTdlM4,mRbƭN8l&jo+P۪2ٛIc[6PL%yy[бORƔ6& $TZ Z7Vq^lmGnw#qͱ&%4l)qcLdqCDfqI4ܛ#JteuJ'tَo*rNN/ V~q zI[Qj )땳*>D*K}!YDPUxœ{̰Grc%moҭ&%IW$0$.vGbyYzjN*x +% {kDj^ ˔TH-.{-en)2%'C)belJ$p\ɩI{ Č۪h@t4s;jBmI% )cђJ2x~3(-gP։)MQ"Kro'ͭl%YEpOu ,lI*cb/1V}ڂ08bwĔlcXXY[8r٬DVDVA$RUنZCxHՖ"tl:SePI34۪[(Չ&MX.I$l5H$lD"a[͐ [a.Y8kS'PҸkR"};V6)[PRՇUf^.:epq[T$PgbN%y㍺'Հ$ʕ{˖Ra4i [PpQ+rutm트J%;H.oU Y/0[d™wFuJr|쬛#T숥Ijďp[j T5LLP w4$LGM H_qIcqu9VR-hof[.EGJL:bmQ$$ʽ9>|[I@x$ά)X{ޗچ<ɺkyۢF&2!KdruegT0\ h\7G[UP7鶫PIlP7c]7GƳ-qJnCDne!{s|mU@dbe0jTRq"u;Ren9R6l'uBLqCHD˦q%ꃑj@ʽ9>DF N5hf\+SqǂǦi}4qRg*@JgR]Ϸ Kque8[o[ [7GHVM7LXݧ6ĈqW `Iì,lBK.kɔ#Mҭe+1l7GvdfU̬!Dl~PYM(r7 M56W"R,]dg͑8۱]$ ,-Unh"G m7\TGQ;IZ$i'&-g8Lsfp VƝZ!UBInʼZ̰ ] 3`&RVK\V+\lM6D:WUkԀ&1RBlmޭ0W:c<iYǷWٱJi7l'U B"-vZMqz`"R"fjDK"]ooɗf[Gwߧ=ͦ;˫Fs~+&2C W|ptȮW 'IkqFOߏp6M'_~FYg8LoG/?{?w_˛t?|ֻ;s}_w~z]&boƓYa4_kw3Jgzwpw:y珷ӛa|_uJHB7E&|yǝH:_o;_:^Ԑ'V͜i;"$R*GT=uʙ|٭pڡ[{j5!#;ܤ G1oSksgmG_'wz?g9T92pZƿp|3ʩxno+?;wq* gaxi Gi{ٶK!;ؽM*z<1e"Dс{wԟw$uǚ rלSTz膢46KYIN!ܿVk-WS~vs=֟*빿 ?a3Uj cŀtOT봖7V H ~_("֬7D; mNPN >kSR߀2?]^^z_GAVA܋o"? z/U({oݿ.K1 >7O.3<6N CݒF}S*OjF8%1L /[Y~:CQb\㊛xԕO8_=tp]ʝ<С( P߁Ew $rY/SgD̽Jv'rϢE-7_?ƙ>}BCK0*3G,>8εN4"ڏh-4 `2CL7L+~0@4Bw*a|* "B+-h(Y8u#УIR R4m<@Ok@ڸ?Rxp7L3@?nI:9#]'~2#ŷ6Sx(hlvlw4o ϢB5@B|Ly | 21ED4j9/Pne`ˌɎ}z(U 8F!d[^&JHT` Op*Wa=TYMy;oh8. Wx~Ib@ݱ7# +ܹw?=}9gr$ONS,d,*. q8Aݒ~{6t=rU/Ћϟe^K,r폍RULH ,ahP[a zKu(>e@ N]r?Xt~Dv #_lLٹ(̙. vi:̂.R @b%9?p#7k2mতbpvc~ZVv}k>qtkWcvMXm&3!{`01*,0`X VG_A<œ0oA(8D?a6HfZi ފ^n,wD-zeǎD1FK ]Pq!f@+5ܓ`SH1} wNA #2B8 X|JpFmA O5ǼCz[Ҷ鈐cl84=b Z:>EҽUK]q*\Do 5pm RS.5T`i:n` ZI pHgtēh7Eo"!DzBBXb,?0.t܇B>DAI1wA,u?eumH&5Ʀ@F 4Ck `yQ T Arg]#( j{צtf ХIN]tګINqx9yG1J|{]r >Ct420=@ cF% y2aXS w@T!0WLXt~48 W;(4U=:v Q5ԷMc*] H,1㱓³9P:uмEH4Ta)LcG#s!xd#zc;MͩWŊ)oOf|C $y/p]Kщ#p# zvΘ.HDċ"RT.\BqwṄ"z[҇QhgL E`T F2ǕAO(2E&U=:E@4Ag8kN "7lX/-tdQHb FtJEZ AY(aR&dL! "GD@"x8s>Fs3Բ@7#+_GݔaNaZ@v?MR[Ar8K" ?5xxSo^VjT$*GT4Q0q; s)a40pᅑ;Lb2!HA!s80 Zdx],(@ Lf0N@@ FDEDbcX@j(+TQAՉyS[1aJ ..!'8?c {Xm>0 ӿ1OBM0.f1$~/n~5V"ޚuՙ!;]҃,seK7t zqR0~0"}pp18qBHpt2̫<,ӘL +Iʽ2ey86q[ܾz[ī'|g>_l-5jSViol~ﯿ]Lv6Z|MӃ_~{/~Y< ywscO_~!|zĝ~4^H`3c]}$LpRъbdX?GSzB*~ Vucvq[Y}P z{GWó'PϽbU;$ҺanSʮShZSya,R[{RϟOy(Xg* P-OZjk*YNs"3\(ǚ8PJ_7βyZ.ɳZOn:Yqz_wϩt~|ގWߍ7N:lWd+ѧJZXd`c|mVKɘPm:ϟ_ GG~ d>}e\r]2Y7}џTܰ[l-|2nɛWny5¯DB/$e֟靈#9Rn3^/|=='5Pa.UZ?}u'8b2,*Ɏ~* k*iS:|Ӳ;ff*pkvh, *eAK_;>;i:G<^QM5QozAM4y~U*0hjӆ, Y☯yAfn$ʞ^U _',wo*^ ;4X1%2GҌ4Y3*Iˣcd'N!+ֻطx筰xnsx Gu8/j!D^6?n\CĵS{[JxM5{14w}e2QF`Mu>ëo*šC|Lu7X^`C>ک*r,wK,K~hɜ 8m `րeϷp*mV&{zʴm+]U2xNw-v7N[V53`dLfxk+=Ȼp htr YV5>>" ?wW;ж?;ٕS=5Oh&o7Q RLГ氶'qAYô#_KfXLZ- E5-E ;f4-%5]<=iA% Q^yXMD ԳU 83}n[`kԸ-k;yz/Gί6# l!P>h Mb:@_=,΋%~ntmKaalQ5,lV]^Bң;NYڑ! eܰX8`@i-X7Jzx&f͝DE@ WJ#27DXXgėSi ,?$NC[ JV#rD>v||ܛGϸ$uRFIä0r.VDrU"&:b\ۛccU$ffSeuEvCr;8-9"7+٪h^M,xU:X$U˱ "5͑Wm 0BȎ :y 9"#+qv/i_\#sPKZ8D|`gAutomaticLightingSystem.inoTN1|@KZR[T@ oNnsE'@|Q?o|YǾ@ٝug;#Ri91*:b ] `dR.H1`Dlc%r9>w p+K [2U'݋DoD?Q]]3hNwƢlel$ ?G{L/|:ՊZ|.xa bg^BjT(Xxv7 ݍ~T;@K4*7f > 9EmM~vŹL߲Bb!\ <2[W7*}Ln?'I SFMTc R[,*%ZM[[\n}.ĵ>~v6K4#LGdR97N:|<=jO^gt6ώ?8:GczBB)ӓGv3d'{q0WsV3c߈C1TGWG 6:ދ7ٯы~\5x~Blp=ƛxqs0z<;;|9L#y{㏣4r|יL0KLg7}|eÓ`1>RQ6ogaou營x|.c|b;ZތQն9=m|= GT+/QL^N~˦HjR#m)xQiϒXTket ۟x۽Tc4p!'>HJQ-+Ãp:cl4]y[*E;i&"w/9N4x Nj>_Vt#oIi<MOGo;=+p{)|OrW{ =[n%h'}q:u)j#քCOg*v>-R͋kSl:ТSe7/׏rͳzέgyuor7wc0NuCl SJmmsnmڶjZ7)tE#kXky]UNϣ!۶e i}hAUtUZb1͏ΩЇSR;yAIxJx]^C]~E p|~w1R`jC8ڨemdKh NO2Uzb6-:gNF]cJd[zȖ}YfvӞ=9Ƣ^cӶOݥ톣{(3d+/'c+*-}}:ErV9/|n6 LB<3iVSȈt;Pg Ld>0l/eOfvr*2[ :bzm]KlF 0H#Kw\د–E폚yޱD%-^_5kR6Gy#wmz%`e>DOR%0)o#e'E=:lUlm5+ T-zM=l/;UM!dė?=ܛצ=ʶ)dKuȦ9d+/Z`M=lF_MG{!ELך)Fz'K1k% y7U[snÑL?ndQI#Y٪lߛjEe+oJ?Ge6;n FxZ1}vB/sP`H{ y3ej7~Oنo-FNxn󕢪vv.O߂|'0}%mɥC9UQPҭu nFOǛ mVLb;6"*ȠKtq~e~(-n,_z~~28Տa7=EM/-_pS?ۿ|??י_w~7?|Q/o_Ǜ:'E狓~7 Oy?V짊~lLΊCV Ώɻ:DOtwΧEɻdzNĊͻ#RGi0g曆?&2y??DZGR`մ2Q:\tou Cq—aO}b}Q~t|Oj"pt68{uVΚ޿DyT"P~t8O~g力k۾ .%'yU_?BUS%rCƠeWlX.c9QbN VMlX_؞8wBL%X |,je-SW*0v)`G(o}"K9tv|\,'THyj%:O#Jr $*CkA+df(/isJiMt UF6jYd|ٍ*e2 4ԨN!uJJ*$CaB..Bz<+'ҁrX$+L㬂nRP&~wEWT`e}ic{VuUʮ){:22]Jt i|+HИgs Y>Ѹ<ݥlHZb\)lNƉ;r%R>R:DԑQu$ (\a815֝|?UK,K,1\7hD*NeJ]$d,/[,/w޺m_D'b(}l٭],{AY*~RieR|J'DIdPobRAv H4T@,405jR:.T@V~:B`\Y(}6QўiP%m@LeL mkF M'"Ц}!tj[&<3$"~~MB"˖IIMU`$sL$ͦJFr@wଥ"CYK9c^*ycc!0ġb")( h_!iX*Et#PLT4=&>"! ]ý$(7@ ;p[x=ܘQ~P %~Ft8|Թk7]rk'[];^FG1v񗦣\%RnK(}hɄ 12)Oy:1@Koq a\`%{ .]ᦸ4I'Sܒ<@f>mqS[ e}h$KzR\ħtxc? j \ѴAۣ-6 xe"wט2%L` S`[@LlhI^ 7Zh-0NMN$e_WiP ġ9Cc 96a}pۀM(e,O' 8JK Q (@=L`AC,'0V nK#X0R&+cjp3qV "+@dislɋf²$mk̆@v laClPZg=.U Bh<̱J,=$J: _# Shsg\ӆ*T Mr3R%ObCHC) 8?aS>g1VΰY: 6gw A07}].Nei)r䖠ES?؄D=SB!SX _H 4iX%!G AIjR@μ[E tCWI`L^# #tI!jGEA*=s)Oa#9}1e1~Ggp!uYȄhHrp(,'y8Li!WP~PyhyhioDqV}^"%U"@o 7&cXb"z[sՕD2iHuC`{űOw̕ 8$MYVrnIo"S԰XN/2.F5%UGH#E'8@du.&~h)0KP"=H2?=A϶PU?dEe .w#,I7,*'04oJ.6`E.|Q6"s`I# n%+$ Z"d%7trYbJ]Nru[Y7JGNT2)zȉȩ{DeX?".eN]C12R X?m^Ā&`37;4RС D!,Omdsn1\REL `= !xvꫮA `p2\u96- Zd@3|]ă2eKή̈́]^y[ȹ.G0U&l0.&Ыkz5D7X~EiRN ,P +m{]A1@fEYR׬ #`M^6S X G1 ,{]^7AgpnU5j` @X02,Q #c-%Z r)'.vOd2{"s|n[GNiϬHnZC+CJ6f^T. a6bW섍j s|,@)ݼ") ]m'X fYk;;LQ`Ĝ0eigfRVpb,99Hfas4I]RFRfPN^@M5JC$($sF"c[cCH|E9Let9!Kmm0Ǵ#xA&u2A20X㙛FF0H)LWރV2j_c&;gf{T,\ӡI@.DA &kFQrmt3,i{i"AFs }zb<@,G FA4o3ך*H"ܢ &hCPƢuc̗F0ѩb]5;/jNt71PD\[e)4jIp:۱֓Zcmo?= +_hpʱPѭ"9aBM$g-ٶI˱O5is-82,s9[9A[Deьۼ IV$InF%RA1":o\9l-WD6(@G9fD`砖&xYEH[[`I!)Jt(u*ZuD*IH4OW$-Jֲc+Zvwd/Zvu"۱eƨClhwt~bHzjk kt3C }yL^gpќ̫9=Mk'ckki[+K9{^ܸ 9@psխ״4f\F/#X斏j`\Z$20 9&_@jNÊ[1"o|LQX%0 9!Þ0I"n^re֠lp` f l#Lt{O4}>//c^Sjm}pkAkoLȺh\&zQV#}_ 쪏뺤'*푊ZZd+ꇫ ;@+Z-j󔕍oy[= ./`̐ڌ5S8ӍkjPԌ ߀Km~դ{.m=1{ 뜇<diˎ+jteUf'Qs! 87l鸦IZL @yH-R򱡮-ϔҷk?*JP"T5Xuر4N^j]fT0թJ߶J]Tb<_rd \K\ 3dv'gf pHYZ 1F*S1=!p%~D&Ef0V%ڀs%󥎫QQ?nAP;Q|G@t8g#Qr]mj\)q+V[A:zmZkč4ik3p)#- 2|Wp D[4P68k:?5 oɆ5,Dɺ;\PɂmnStIYfYQvEaV9'oTYUc0l#R,X 5'Kf1i܉DkVYSBC5[Efo7#Ma|̺[dojzܗOYc */th8r/s f݋lr0qK(@:lNE$..Ҋ|m)^E&wHΚ$ ,n[Wf)qm+f)zt6_enulh06RxR]qͣfmy[qQa0zqAƍ9yܥ >Ս Om?<:WT^Cʧtmj,UFSR\EYFggdtV-tp\mp"|׽}ٖ|Uq|(DIژEiF|N=E 0B1STfm[u9kLva˜2s0H`ńd[iZSy9lw@Rh$ pE3"^Q6!gfS]B.?Is =m{Ǟqىk N=+of&ل´M&*Xi KbVW]"vJFV6 )0jR+|5!\nWg2zF?uF׳WfgeXNU;`I dNs1%,r/~E=# ܭurs?}wCՌ#й"p܍0n0g53JukfǿZ_>/äU(]k8v)~*b`՟r~-*>]s-ʆ+N#xKU쥓{z4=[Gz/:LmQN|t|x8Y9n28M:Ʈ3_̦%>I?VO1u,D}UXI[ ~}cA?eyЧ9W$շethy.sŗ:f;}1SJU§Q!Tt7Vk>ORigN?;aRR=ustdꎾڸEO+ϟ3ruzA3u!Wi={[ts GL*7v|B⫒[tsh6o>],}e+S-70:g$\ ;k)^| nOsl5 wï|B̋]7;.Gw-: [_v㭻IQ藼OIdNs~+ҭY/vm/E^O'}]_h\> tjO|ZjVt'2, e7a s{Md.wAӢ7t&[Gmy"GG^|<^>;wnYQJ_cOJb#}Y[StֈRw&fF7fWAG!#6şYv (h]hl 9k6"Mԥ>gPŎ$~bG0ʬ\+se20k@l\Y8O'=q(G^ڣ$A%uMY+E]щP@cWпE)Jp*r64 MF `\Y|t<[\ l1o~z+H~L`+r݁M[oqwИ.~0Ay Brz!Y.˗ǻWg`g7Swo__~|t7<ݾ+\aBݍ>^/gᗓ廇˧nM'nOrvvw}6y}}u{fWx7~ ߆lˇL6t!<|tQ6Ѣ/?]~|<ކ\0pb3p%b׳KwVO=>Ξ:;7_\9/_>\_˗ˋ.?^|{qof;!7FϘ2N _y/| {o"]>~navs䢣Wf/_nx}캲教~'۟}6{|2Cfx?<]^ZÇ۫Ϟ㯾䡁6s?/ˮpêS~? !oiΙk殭\ܰwLό7,>H&C3/c.f]4wzw(q>kO]o55c֜M(g_:ֆ7E m$SqFRsrk TG۾kԽk4b_,!ExӿNj,<^WEzf.G*X[#T Eg4~&~@u1"jϪ6/ly-8f~iU4:i[=*+Z'csewT12eklaD(ո* $M= G$]θ-G$Hq%q6 iF$NȂdW,gڮG$Hq%̃[9tc Y{dARv\A2ď9{`#HZQF"2VL#H62?1;q_ָ=;&PmNnۜq{dw#+g#5m(!9RjK3=JSmrҿm=iGlgmk>6ee)"cM㊑ζ:ƿn4e-,uRogO%.Kz_ ޠ94~snsȢRmzKfh_YzSms #hc-,k鑅E-Xq2ɵ9OͱG3b} Kf,}c`VM1,lL}~gn=GE`=9YzdÌ1Ϟ0{d HƖYm7)9؆ܘ\1ϖ#k-XlMaqdU|}zdϐ089Z{\^}f^ 2@ƆWWGVk1ψ0$y>ln= vl;k}`gCN1il|mvfell=GjSQȤzG<699dζYt }Y'##g{d2k[+@֧dgϐG>f<Ȇnc 9zdRd #+G6(g|,1ϘϹGdm%#'~c7'hm7l=2жd GVٯGf,s#EǕէw%#dmq%~)zdjvΦ|,g yz\q5k6&.aw_^?\_t7fn#z/:ij|x49qarr7xnY8bsj( wٱ>EXFk_p.3㬇_8:R.N5?w8ո{bq<쏿<]>O>=G*֫pX%%eul*z7vQW,ԇLB}ï <:IK_^lݗstU@QRYBmV.%0HЄǶC6o2 nzM A3kpKBG.Y'Xfy(|f$ ii@rFҽd]eNorR2mgpِ-<)gϷ]D4 oϳz\_<ݾv{;O\!˯ˏ^fOgϗw'hNeZY~S)"-|ߔz#ll'sEZ^V?<<}|yp0Q>}.JNZaw2/O;_>0*bPM5B6ѡ_ˋ կ`uM'ոc>ZixUqQ@#&>xK[wENzy ._8N,/B"sXL]ЅP:%SnCSH-:>}TࢼM]=qRL?nng/*irTXx&YgWZ1<:,`ŝ6_Mme8#.HfN.燚[N%|5 XhEY#;qjr:K@s =L0"l r}'m=:V'>=kouN-ǡj-oٌ=)OZOg#`?~%>Ѽ4\n  YzOFܥ k Й-`>Vl辿jۖʐ.v( In2Ē%,[_o~UzSKݗ[޴9!|ϞUaR~~ݬq(-56( ŎsǙTCw˾m :ɾ!30IC_b8u% 8V7}-\Sz&5" a"w@G Ha:Ud^>M1p «M(izJx#U1[Wx݉B WU-JhR0٨rVxGBX}buIt{P!ꑆ~*Wҫa"b@ZVhҫ燑^u<8nvkx AƈaOWMڮyPZbtRr8 ZJ5u2gWGxBzi)GNVB''!4eĜd.!B0M㝏VBΒ{2R=ICk`IDnYZDJD6n`ۧ~OZ2PFiQ>$9F2rױ* ַ\[dg$#opr9MҐiL܉$#ϢLau!>ge -]P8Y!Y, R,@Bt-R5!qFB 9~w:R!9֓R9Gً\ 5 o)(2A9{yOگ+R=)ȵHA:v|m.=z$)x)]mrH,;dq5 qnSOCAV wE^Zт"g? !HBK*'&"{gSDV󮾞/ID>R9GًWg$"5$"KWbaf8XRku2fAqȖ!w>~F*.A6Xv,N>y뵘G$$pP!$ sܱ4rf~G8.BRąSU+7ݩ q-" *96 Ar9R^$[֐񅶞字d> EY B¿llԓ-&'Wu\:}/$]ϯ˽;'z)_ 3' &cjP;^%w/iiI3||$d6x6ܺc%Y0Bz4iǙ!~6g!I;niȢZOУn@";^0],6Uo=rp *C&xH8=^˙֫KjY١kBi|'!KQpuA4y߀04xfգP@'X%Z.~hUXӽ u0OÝW#4nu3d=ְ֏dm~ (Y?{}ЫU^οPp7{M[~hN.˫wۻ.]{1*[-Ghl/TgڕᰅX 2+{Hk2u)m,tLOE 9`^2,agU{Y)3{:79t2kA,ЬH5O*ɔ+Q8^,/B"wXL]C,iőϐ:L M},jZԧDm}U*[& z\pݏhHs[CF#z}_(?/rƥ?gHKE3ҟ)bmK$^6N6Drɶ^}c&w[WF?Rէ?;Wp?+׾-@s%l_H>|1UŲ ,8NmN.:Dj@X{[ # = [ON@6$@h5q-H&z\"R6zI^yt,;R ]A֕2{aE܁hgΌ;gf ^H1>|svh݋\n$>5D$>o ;V8. '>;G3R]) ҫH}}vl,x]N>yUsef)6.!ٚmoRGNU.dM'wXL2uhߐd㕡~dhG2tKC'zR^RmTD{hBRǥD,o ZAJte#dwɭ/&w[/3"ZUh "Bqhh~c >'@%=(6v0s=7h]k$@\$@ 2ѓ2W%>P}SB.>L}bÎlKaM m(ɝēKaʐ|svc >'>/¡gպu8g+?gv]G~CW2#뒞L(=eOOWϨ-~ܪ+F-طd qx+csgi+W(/Ȫ~" %)S62x]Uux sT\/z͍q!/{w}[ʅPX u1}`Si/Ӈ%w+ϫ:0[-(Rm+vhI2cSwl\H6J@Vx3u #<~2җm1 q FYme #^2E#qbeX="X'tjq>nszιz^9MڰG6-K1UXv9Fif:R$m# rƭY:~l6oQcpk%O,HR+y|E Iϔ?jcw'Ռ}+yhkHf~E t7 l4d\iFV4{ls *}OB1A3O)|6*dm"3k2uL.X!׽gDAWf0GayDA~LA%VL'$/IOeP ]$'KCyA\x 1qâDV<77AE; J _Vc:hk*uTb>Ӹ^l5p昙XIA-=Tz* ҊB:VT$ddtYlWNm0S6 .BxB(9Y~7b? YMYdgZn4Q\(Z[k DϐYz^h5IbZHzFDni 3揎-J(i< -D,D@ix|<˰(q;.q\!1mI[DҐ]w'iz`o SK }(%_ lMl-+QEĭ&ԚY ? b >dI&%ܹj; j][uAT/!TeS5͝H־NyDxg}^:2PTd۝deSP~G憁ii}aR5Ӝ^P[恧2uܸ p㸘* 'zOKPT)YIZ;)gc"f}2 e.+)sFLpN-+G!˭k!ק7xDL"bKD D D@%_ji}Ӿ8cIefSO ipMz{GOB,06⌜"* 1Z єhȉe5"֚C͖@>'Kw1slbv IqܴD"`@<.fna.f"-e- |Z\/s)WHL:![CfVT8ꑽ?=xmfW0Y7.V6ˋ%c[|gk՛?x{~uN2oZDJT)u!$/҇=TM=Wr٦yJL,}0 5C WqVrq:$!.zh2D8pgF*ZÆ6: I3R0IT%lk>f|r5C5(厣 _l)Q4V7[47ڙ$GA#6 "l}q2 MdZ'.MiU5(  Uo$J{dEd}R2٠dS,hB]AO Jtt3Lm:vKхUᔓ)=UM[ F4nAq(Z@r SVڛk]jT12D,{)y;t 'H ShYr劼B+iS{tdAO'9b " >d [ZcX#uܺDjHՌj[v sRoHn_;]iX#~W7El+ mqm>- "I )2ِWF' 3sHӸv: n_{;r,Q2Z(dűA mS4-1̪ TJʶg(&sf ht\gu/%"kRRݽӯ_Yĭ!J#ck0k.;Bkxgwٍ@6Mc0ڒKf5/+$s$-1 ujȁPB= !*ĺFqPP@1(lY^R<>>Iƣf^0(B 0,B1`do2@>bWN nf͋AٚQJ (/goܶ.@˞ 6{<8:àq<YU{Sy\.[R@%wjCٚcEƴ;Sn`'26XO;;8J;٠c_o !ޗE2kx_o0u7o_^ߢm5[s` W?[I\Qiխ98E6oy@/(B/nˁadh-/ &޷5 }%grPkfGm*E,3Sr eelfc8 dGк(UG(cAW7xt|Ujc'Y%iZ&X@,j$6W7XOqe2AAG*YT*P([|! & v\2K#J5L@ !)8ce)4W89")!Ќfkz@9~f9[^0-,!4lFHy3y"qYo YoU^ CvqW.$o$!yLNq= fkzqs LJޕ!-̢X.rzGZ% ͓kbC6_:BXGl- n  bdTGk&Bؘ[4hd.Ɋ3x9{WOJhهX%ev&*Dq(B,1mږhق z!bl= КE6wDfmiWnř, -"j[|0SLvLx\oǸ[""t/!o7!'x6C3 zhF-&hiHc+|]ҷq)G6\vGk[%94K8"#V h8ZBٚqibGs4>Ia5%ljh-fU\8YkkʷrL-A+F ?M\QY5f LaYtt qbgMKYWkC/˒ ;!zo7!z'x6=;!Dњ9<E[h{ٙ)WU|d:hMS惏vzN'd"™։${h+vh}Is4{ B!lQ(Z,hhbm/c_H!\.$\F$N Ee GnA7˅`%.jgl&A, Gփm\oX*8m%, Zvh蠝zN^/V⢂?a&ͣ 6.S`#mum*uF,^cqp1hv[J6c|x~~.XK0y|khLT!PAzPJӪىTn!z Nn6ϱrQLht(Bt79ي2!bOlHBݝkiTVDISh;̗Tq#bk"$fk9uivdfzC&lT)C]K&$Dو UږMnza nTRٔ6@ #R0r E#⊭9F2F(+ܭSzY Y} dj4ijnEEˆ| T!, m!TvBڠ0@7GPv5:di gMO"FiV".i.py 1;q[*].fnIvands|*vEm)iT?l!Aw͆@셒kE36LDV"Dzg=@fk TXk,];/Ct*i+(Fצi%lD)s_,C˩lխ9BuZ/hj)M?l1.DrxaoNbhL]DI9<~2`T\~{f`.vO6&v2#/O$J:[sP8Z1QC:. Ƹ^ F!'[t D {"?N٠s3džf:bHX%jS V#/BIk0gmIYTC!U vX}*հU|2"RJ-Ta6,fi4*> ?s`! ͦd0,QzY֖ʔ D ZԽ{@=H`;2LELk~Kfj{[]v%F -ަ`W͆W)IEÜAZrUR<@JBX1Z| PQm4{`o1}hycV0.qY_Ŭ`#7`+T =E!M= DQKD1꘳jzMf[} |ԴN[[X'[Bf[L{@~F;G;=v*.*`6pxpje[^-qImڰ#G9Rt\/^^KG};h }{Z&HrڕVy܄hjv-" U2Mgqe-@B+֦JfY֨ٚH]rPaQɪ &V"zC-A"n=fk %Tw{//][)֑ppVpWgس˻O͛~?~?}]2O~P,Qf?_?޽_>?˿|xyy.~ .p'p`{`㪯XtK݄M>8Ilu:WOpd|^Fk>]_<ܿLo.C (o}2{\CYj]02fio_>6 Xoo/9pm_Ķ5mvzo*?Xw/HnΉ]%d]Q_+p,P(L?N",ox7M/.S' /&[o.?^=_/Gsw\\yt~tb_?Mtw)t$ssy|xz'|#p d26.#jV(K ; #1ZfL;=no_;osp.ƾS9fwW<*8+uz$[: |;tw)@t"0ϯpi0YjՇ,wPNuaUxvLN<?Qv>d&|,y<Ĕ/CWůrpPp66K_s?_PCYLlGHaBB+hIl*wX mko;/qg>Z[2e0ˈJ)σW>glIeIWp\ă<]B:\"OmlG{sQ|*8.ϕ/d0yã~&]O[$<kx F3*ymg/Gt&\H.~ho.:Bs.=Ch p^ÿWѨ{^&} ޚoC0 A\G}hI0yބ*L'K &7..٨Dh9pBcǏk;>c^~apu.wG[!<zP4xRK:(Qkۂ/*SgΧjxL Zpʗbo׀BGpTPU%Cjڤ_0`ell"^/w%S0}hpT tpCx)iASv;|j@<tzgn,<OmZ}o תB|Z]H O =$v]G,sS,A<[^7wy 9WM>+Z5D܎͜7z>mbFɁé]́܁c)=^/0~ET  G1eZѬ6]FBc hW>'8tެx4>es GqsyOx'M>o{Oû.#'<x|(]BAd_`QکhU#]|I?)h}D!c-mLKЋ=a:;yc]c!0cUԨ#H ȋ a*]k w"5J#pe^$ o (w7*p n.p꩝3:S;ߒZj7!!wL]x'1ы])%:\[W!+|$,Ѱx&a [pyS\!x Vt48&nFl_+8 ![q>>AL\u&ï.p?#Amk2Z8g4yFN분[ U$Q LK(еP jbO8~ ռNj%1l&5vU^.& "qxpp:ޅ 6!_r1ac ط Cjyl+C;  ,,9tr39:@uL@61[~|`̼1=yR͑nw<I?II.Cm=sTCw3 LxO6^Pģ x0bX"3@WBd@b2lp3m=@<x1& 5xe&CRh61͈Y/<P#=8 \(#9?0A8t"$ Jcd%C N-I%vsN?s<<d. tLQDFR1uE5eP05E%4%fT?{&>! O$,<#3Q Ҡ O YL?LFcRq4Y"@TzПb Spi d p%iônRt3G{/13UBBsj5ϖB1d޸7N@ww X@,5;d6P {7X. I}-_^#1x$a T( `=r(HA#h|Pжr*w->n<tDtpxܥ ƟYVJ>8 ?</D9^%ݤ4_@^A.CJ5)00B_nvAȀWZ8'C< _@Sh>1*HA^g@ F$]!:,>pc; ~DzP`luPցO[U ZjK!єЭ5!zA| Bt8=Pn\lg!lH;0$ nZ $$5&FAc6"J@H _xԮX!cD l9#$pc b#P2~c¨S ,1& Xd@8HQAOPoxYX3sMO ceX*I""/^cMrDQ'(X9Pyf !n:AjX!y OW&DFysY#5I䜂Rw^S~2N "kA?aIV%߄nC! t~pR,WuOjpCp.H4I3LhDqh T0J@ A./plHu:65s@W9mM̳ lt&& wLV%l]^yk+r)a f\聾TMGpQ@/i0b+NQ%+ uh^@=n :+vP$55PJ53e,aM b 4>DGvg':ij8 kF%y2aP93 b%',CC_ y4*wd@^9 P0T Tkxy t ~ ꎯ>XNMh=@)_x `q,ACpNM~j2>ܬXF*ZB?aI`9& ? '©ߪΡQC2f&5ɺLe"37Bv ws MMݍ7;Cc,¡*.R'`r BB%0Cd-CҠ=@ǤH_> qtQEMR^>( :>ԱU ^)+Z?~OURa(p,#ln*OĂHJg|J0q)ÿ %Ǽb&} rj`TAIŮsh>o AR =e%v#>-EUHy%U%!68`q !APGe_EdA5>,s@#aHӰ(k)q S_ayJT` ԉ&y;*:$>|xh 5J?)1Ky wA95I+ۣ܂%ౢL.QmX8q]ҭBV\RBRT4*ű] .oXry,ذD"]u|Y"%jIL_<8J~Np.A۞ϏAe΀1d1AЇ4i8 Hw0k q?3hQaB4,DT@U:1vX %¹STʂH5(~6s/=a#@-3-`1x;Y|whrt3+ED nx`@0cCbC:ڣQ;E!Ft*M`ϩ\* Cp6;}^I2b *&D wY7=@pl)]cB Bl?f _i߰ :$P8/Sj$~zs+ pO2i0ƠRdm_e|}U>*paМ[&pO8DO~tW@O80hCDH7J@I{-C4x[JxXe*z0swX$1sDŰ逛 !1sGm,@gs &AhLrP: A {BXW0$'ڍ\zXNzz,:=,hD ,fO@*"" 6?Z6ʴto4{ru>ǡXD'P^4 @;ѻ&W75?=JmݓovcS{1~8f8 1Zc'R!Ce!1[dAN ^ ܞ@܄q3ءe0^H8j " >/Xj]O4y%A'S'8QbȦT1QwNo  Μػ?8F*R/̉W8RY1L%]-% OlJ`7:>̏*ڒbTyj*AJ+OIl-RCrp aKw \h55嚵kSK1O5eK˯ˆZCy3Tou0bHhu,{V8ѦQMQܨF̍*xͨ uͨ-F5ʨ$G:p$od4/ncMDpf(Cq# ia\b-3%es&k򇨕?S=v9e!=&<:?ơ%,v2ׁ(H?| Az(Qj~ ?R*/4SfqJ3<4DjdJpʬEl7, C9ߡvw} >4+Tbveec$*:$vq2'V0E}B.&1Tq@xt0;ѧɒpEU5Y _.EW닺Y//洈T@aɜJ=,7ζAX  :Wbl5a#oJRJ }tk9>C 8/0}UAagT7qMZx퉖ߞ\Ӽ;zj8,Y'PC|nJʜki稜 !``p:@A|ch_=WNq枏'Np N|O\b٠j9zLO}3$=Ͷ9JÿQIBA&5c*,ةEq/f7~j(*Bk..LᮡJibFԄͱ܂Ya:9q؏Rij{JS d^ nYt1īJ;Y0K]y|?]|={O<ݾv{|._~z0zѲ[\ϗ׳Ϸ3·wXLg!֯SXw oY ךӟ}s o\Yؖ ,:( ;V{ܻ-4j7.ÃZ}\//De!n`O?-gO7|(%|=܇.[ϼ#].zBnO;,F 2cNEV-G5O%<+q[..,cA8ZQxΕ/;8̭{+ﲝX9$B0m[,յZWNliQ8Sm}W[Xh\z3~S؝q9oC!5};?j38&}/ثS+U-̩l\t*RNSiֹK!x5tOrrhx}ܫx 26 8/*W[@zu6sN%Awl[_0e+v,kFNNq^/@,oo;:{y4i_%y~z"Vy,nLޤ!qll׸_י^Y}~ _'+(a4:Yr,?<]N5H̼J̼JKm<63|ͼƣ3sM\K5[rͼF7z ꞯűyukkG!η:߄Z RPT\dUC7 5U7Cv}Fsb4֠h=I*Or[@bzoaR]ǓqxRYrUIu'OINGIFIǬlqXΞ ͓þz$}eI=iqWnܭFںnU&p?(=H>VOj}}[7>X3~u\/.ffi) Cs)BJ)0nb,e_Acp_Lv?UȶIo.?;]q񗗧ۻ8?>.:UWj2zUS)uQbӺê9~ 8jQtŪ4uP1` Xx1Xn])3uRIkpodTh [8ME;/l3!af[b1vybqY{ zI[ if/$IT\M,8\E˯W"n6YkҼmv-I_6`×!|]lj-.K[1;kin&ċ8Ftc$3lwm}:2.+[s|W;b`%.BL*duPHz\b/~H{Wc0ml@x"\E5׫h[[b>β*:UYsʁSQ8% Sʣ᪇M"ĺAn&Z{~`+K 081gnn}[s;G$oL!zpD9rqZ{MƵk m%o!˓5 4r{i}WX .͚58Zf43Λ-hh؍'&TINhv-0K lڲ3 =]9sӮy詊6xGmk:vYz;-.X*BD )aFEOH5ut,QC58EٚcW-]D+޿;r`kzU<?#՚=bu!t fQΔf D=LҬ&>^?p!?^ҎDOq$kptfkVVGafy!Y$n_ $"d l \ /=z!2}W~Zn#'qÖy;N^2`SPvbgUƌwK +f.-F:H%S<W=g} W띴޾A!H[o&曘h2_ۺTm ̼yzZkx艻vգ'a_^ /PK8DIhChaserLights.inoMO@s;-_m. 8TZ3T"g,}݉+eL\ ܢbc,a֝ ͣ=<dtf^t oڍ&{ }%77&=1Af b`'^ܘCOXDJbRFS @ GRtKiۑEurb]ژw#Q;z8rb䮷/_\nK['ņB^QoNCŦɭ5=H)HK<2u{o݁OeMx;Y1 FYܤ5h Kc2m3g_ >b2PK8D\ʑChaserLights.fzPK8DIh\ChaserLights.inoPK{^fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/Fading.fzz000066400000000000000000000304301250202676700320440ustar00rootroot00000000000000PK8D.ں Fading.fz}rFwjbg"UtτݶӞqx잳 cԒVΓmU~ EPn$FO TUVe /lһl젗OGogI;w,u=LOJ>GBz>=9whUgzxG/G?s1ΒL|rt[7'[_tNGzGӗ&uN3:;J#9E+-zq>̇gطe8vhtX. WR;ʇޑxko2\ O⥳|/b{6.O7 /ᙗ((e0fZhry<"q'z'l2M1;Gè8}x="N'_g(T|vm>}ggx[UoS͒̄}ݽ?~Ԍq+^ԩQALczE VT$j烶ϨTjΩ} ƷPmh`ڊ>Pm۷҈c?XýAfJ/ZbMnL||0Gʚ^WQ0r.|$lt;\מ|jlUuF)Х lѲl~7e"OZܼAZ\ßx-oIی(!+n!{Sk%ɫ9t\ZC9_DSKy3 |u4w'/UmTg&+$~]PEdE yS+bsN\n_[dϛW"o6b,ک SVE+EyIy3V;WY sb?wMN ľb>|2k~g^Ex&Y[p{Hg9T(y iI3fƄdf}q9.zg/,D*XXAov>h _@q~R9fY%KQyI畻9$E8$-7\ۺJ0PF}+e)0Ap_[OI`+B ^IPnYgRD7nZc%) <n6bdKÑVo#O@[HKky+c9Xc2{OۅY;.<Zx< yo _%_fZ6XMf ;T]5n˒kYLF>m;{ffaf ium"6Yk4lLK,j,EfM90e_x0S t콿?˒(,x/qFXKg|r~e_t-%I oo Vz\ѵ9kBkɍYkVEu7 >>^tLE:R%-7=V{`CҷhUzR:׳o,{Ӌ|6pDAr*ڷdg{^i7Դhʴ\>;#wץssӓ|ǣ׸MVf /Q?ӳ?mʲ:g䊅M*ҬTZ#x6?qLKW_Ascg"<[j2LOvGҩY)iSLKRkS˷fgypt!7Fi۲q=Il%OJOLF&gAݒnM%cq[29mJ㑍8dwqz4wqR&eNF-2z32J2LnlC/ڻPψʶNIbĒbLt<--~6B(tu(Ҫݜ0?}H/~J3?,K~< 7 YG rm3GQwD|5 ߀&ݤڊ>i{&mZW0&Ti\ >vtm-]Ԛ{|QM*0:캴 ttѵ]Ǘ=`ck;g" 왲o2kP ;6z?_kCn _IrC)HlڼJbV1Wձ"Iv"_6kKEfO7/@D|OwteQ5c:z]e-Hd\fRǕ޻e6t}CڭaL1JH#y|@HM|.{>gjr@]R&pe:0#to̭ sndΕ;ͱL7*Z:6¼׾IEϟ-p.nKp-@%|X]G'try|0YYp.3rRSneJ^$("w#E-޽B$^%|/D tmhұ<>tpoޟ}ca R 6~41>_#A$ؙvBӒx#D,`Iڮw?X.fmn/ѵHGV[Pѵٯb?c韱Ն4l|_߸'͇)KqRLߍeN=>Zm+7ns:<8Yyqyx6.^]̖>].Ͽ >|~l~20KS4^졁eڕ~;X\ﱞa=.'Ͻа(['/F<^-H%xgJOdx2_qa6]&C [oīکw 8u6>:r0ē^_/sig~ϓ9֛.0,w*I~*Nܨb饓_nۇ&lćd'?iC_nTv*4v֚>4 +M~<lJ?'y "KhsḓN"I%˄2瘔.Wo|Ϧ/)OGW}_կ{~۷?} ~w{<:ROǣ^5G_V$408\x zܤTgeI㴗w=_OzO^TtO  Yh  H+W By0`=*P.7v?z;^aA!`z9p|v1-Jy5~ q4dkEQ~ u\ʌ 뇀:,~}qhruӛNIc2|/Pf?.VP%3䡈))j7ba - f֎s|T2^2 E-O1̆0!rD- M.Vj 3F_Z3VK.)zWՈSJ%&^Df}/()B^'u&6N ?[xߡ?+ Qvf2xwE*#xL_i<-rY_eW4s0{i\蟶4I1 &邶A\W}_1]Ùq?0r#]ҔϰMG(/xӛ'HL< pkWpU\˓y;ѾCuWZE^62\Eg5gF5 }x|{ U-}Nh~0y0| cz0"4b6XU" dBiPJf!ᇉAʵ \}Cҏէrdʫ#=O}$F- 8ra@`SNe L U:N%>46i& wqNcKOcF^pE/v")Ku(BtrXNT΂ S(D5jès< tYyi17bԒ*˪B<)+_! =T 2'be-OZSu+ȗ9W}-" __KtZ\̏21JCET`YS`WS`^)p0B Jq=:T]󨚞U=4ԟ] 8h*HaZ Vrhft7}HP" uoOzrR5+_&9@0%c,:JXiqeKJ%_G/Aq"?E+. @DcB3(=7wI&|A:Qs!A=ѵFW x( lD W`\Qs xtԖP Ue|"I&s5ŨMDb?p8AڅF8r\ؘ"QF!5<6IPe }cWN,$aAeFcb &丩 8wGQjkV֌`Y +>ۓjq?+f}opAd# ɋj&UrAN!kfތt#BHF ,p Pʐi  Ii,c[l+" HVx臣Оi{ &<d&tGIqeTPr6!, 4gSg6HN$3sȘ S@Bޙ 6@YCnHٝ#S# ! DV1U1(o订݄=BO{J0ܑ| M*19 ?QTƃCuejTb @%58, Jcd!'D̜SKXH)ͥ(HfY(92P jR4j#05E%3P2ܶ?yۓ Y]8< Gyi E8i W"4< AKvꕐБl#(#xjrTɞB DW$E %iQô.;O ̐E, 3 Eb\dXB!U*ZGqBWp>a[u$e2")oUĄn"F$)@_e@& d5!& aH [b$'1}Ep"?+-@OP?x1fe֔ #˒"H,21͛E6d6ȋ"]D6EKO噍N>@ n,(4VprhYcmcf_ׯ fICjb3L]%{'Dq!#k)EOzbX0OEݤ'=ݣL?))R{a?\'uEaMH:p!u@y~Imxua`J8#g'+d GQ Ժ<M +&9m-g#٠>2Lr{ q :x3э&93oMM0_= 3Y [iC8\O! @x}F>n`e|̈́@= TM@=nJ# ֌J@9hϔa"sWG/Ypj;9ّQEtABLZ")c9=9B0ڧP}}M ##<;la 5 KEI?NcuDZ¥st<R3Re"ROBL##P~TRIO5xNm"!K*bH"Iq p+r~OGUԨKUٚd]DDTI(tbYI(VDoڽШw]J#pȊK_7xLؕC$HIA@d0|4gy{E:| qtENT&3Rt`ta%'.^1ڞJ` $v8&2-S"F"1b$2_DN?&qGVc2$eL+T%WeCH.aȠ$4dm|x[G"ͼUnBˆY@8t&s:p0(aM" =;zHdDE14'_a 5P x7 QW}dNcz4AlK-XDsC zn!c!`h(CgQpRZOL>aL4'H^aU? ,btO6ZRIWsdtcPʍ՜X1IM)JAJHJo"$ b,Q#?L$7HGS 6.URThW \y bk5c1ky01L86PHjȕZScY\k[>f)Q_\.jj 嵆Kъ-#a˷։ ljD%TkBkB6Uք*K:1RX3a2 "!ϼLDf(`H^vZWrj}#) =I#eeH=aI"M ԍ$XF8!_j0%ra *߉;"rj'/s 8b32VC"Uل"W L,0+ɽrZ5ì51 ܈JޘÕ,04ed.$v?A7G.}ptXu/>j"4q od] QLD.ڍ甩<~;?ci i0yؓw"(C)7TG p^cϐiAJWM "^ ԎEJR"cKŞG0﷕ u4U' .˗ȣb $*NtH8]Z dݓrA$yc:T?t;L'QTlQmVkU[t5[5[rgJ[iHR-ܒm7m|Ab^U {1%<&1TA>RxcRP>^㘖2!&b%)$yppۘkhؾ{r{o`4osCt!& bi7"JF%E":<%&WQWk ^wY[=X7J$,KċUv)J#"p ,uM|-G!ls}dNQE 4 KE Põ`']2rP\x_D9QsīseSV+T,z%>T3O"߶[a s ~x+.F&ZMl0|2,0jQӤ_24{Eg]+R7κC׈&Ǔr$kamWjBnATd(N A.^}: Ŕ.p^eaQAiL7YL/=)GD@8&"8i);urAڙ'go|b]}9;a>^~OOi4La OãaxRoW9O_+; zYY7fuK2Zவ az}M7j9F{{^[hhӹ$#ްܭwNxV@ӛt-~o!A'N(c})Ax:{/?]ݛO|ԟNCOc=|2OHwAo74\Quө"GꌽnCp8zg{4qA['q߂gO /Bؐ ¦2LZϤ Oٸn>q 30h-7z&OXM;4w0j֍tؿyr#M6nGU;W/0isE 'xx1>v9Q&b7;Ktُ8>^RpWH_ s@J3*}uGŹOs_5Nwy>H-Uیx&R U5Zvc[޾XşѨjOF7h*xxk0=^Aӝ+|߀擝A42{Ov Ov‰f1 iĥYYi,.\=̴񶎗?u6|LIЙր>v <ym >Ot:$D[pcW_E9+n= $ ;/yZ_CZ<9oEIF˂>-eV4c#e-O~t5+R2rL >:J౏9z%8A̮pa[mG7G>dLuDO,}^B5׭m'P>-7-hg]Q30XCIKK)Iر[BP#Y舗~da,a= ;|<-p|gԮH7cH3Iq׮)qR"R#+۱m5XZ[@[ٸ$(HGv_&E8^PFhqFZ4xYn!O8"M!<;V^ @PK 8DD[P Fading.inoRN1+PXCA/*=x0zn,4feE¿;E A/{o^7(`S)uxv 9T[/8yg6>{RAƥ$ăW뺗7lvlN̓r?Y%K&Nd5^& Ody \{^;XTBP+4Ty˔sJ%:zѮ"~1?wFv W>-)I%߫Hͪ;D-e q,݄:;oV'!I֣ZaW1謎xAݟh$*&ʕR PK8D.ں Fading.fzPK 8DD[P /Fading.inoPKo0fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/Fritzing/FlipFlop.fzz000066400000000000000000000404561250202676700324000ustar00rootroot00000000000000PKB8DMr>y FlipFlop.fz}r#95wm!GuִUe;e3'(SpG\dȈ lkUDxOa6}sFSr oĜ_xu;0/w$5H MHŕ<덇s^]LOE0&<݌G˳|<9 ;Wl>_Gz8|sRcR۳h|}3L\qJWY+-zu0~zcז1ee #~q h`/nMwEcz7ggϜkz7 ο~06:{~9ld@$R]ȋK{5l 88ާW确7ʾx>V:ѻܺ_< w˳`d+wֻ~_mezǟ\ &뻷SWdsv0X?ݡ~|jZ3Wןht?4a>uGƃQlq{[`8*6ջ~sf4]7Wƌ0꒘K/)eWȑʜ/wO|*ˋat`rP}yAK廼}u_-[*jg?PoźG\I 2Už>;i"+ʗ?ڈ"A9>S"Rh_Br-+2l>k*X%;JWz KJPj; AY]K+w4}>6^4ڳ͋e-?ԼoѤ&y&]6;1awY-yFOG-Eޝvr^n"t-[mq^kiZ-j[G &S>-6Ax萼>n/e~{ZO6 ")ymY'=-Жa7JO vl*Rtfo\Ee;͉r':;&svKҧDIӹ%q/'ا오O81Ipfc>Nfq%5_첹?f}Z젴O9Aqp*>x)-G넳i9]pH}ˮ)au{ޘlxY~)k`ԋ[}ԕ{™s])g/sY퐷u)f0;'avN'윬O8ܢu&j6'즼OH󙝔)g4;)ivS'*/%ۺxp^s>-ӱmvO9=>1nS3ۘ/ ~}Mx>ͦa>]v?l-.&Y}ZN. ZݷI%5vv(1;?~ g>:i0nWgNpsAzp< ;_ aus12PjxOMM)'ԤB Z_DYj¾I7:_ۺW`VY˥VcN? MAj$eӞSX_ hh EUGXʧ%)~.MW J<,(F|b@R-5w r:Enm4 xv~Vcб[Q{k H:>vh.0nRRKuȨ,1¹F{dá{88 *#6ŷ堆rST~c/R 60%*7ThI X#0"W`vKE=jh#&SicG!#f㙫w%;!_zMYjz7Dxv:_G{\k^F`QNzAjckePEF.~3eV2eʚ wϲ,H-s\IYc7bjKIj?319T T{˶;]4צ mj1C ooؼIX${tr==n\$o?+n*t-5~*˲Yy6}bL*'A#e$D&'bPKc2ؠk򺳈V\tS* rjm Od ӯ/-1ڦ"iJw|*I* FD}vI{QWf oLf!N_‹Rxњ{֢"آc&ϳSiѥsX]߉ lٲ4p, 47D]jfVj-%8[dax[hjR"wE%D6`-UPR"!J61}TWΝgM%kKYLjlvVvLqnDu˶;7O]>R P,&8V?mm!,|T߰0h1آlm d)ڶs]pi*FR%84q(yNSxӏ۶cxs{h4/C Cbд@Spc_<^Z(TN/򊙁7` ߲#5{xRŽ5w v<9vk#`>AZ$,uޅdwY[H2 C>x(-PI W"3VёrYpфT^]]#a_=G3QN[cdʕˮhd%E h5aHJBwڬp$)Y.rnIäӠǍqP,tDx4Nm>y ~Es({.l7i  (h-@mf$TPsyiNBYH<5G᦭ZnXr岫P rO{ڣgS)3nR TA_24EAyKhKǑ1QF}\ۄMϧwaezHO;٣kxއ:Bno3 &JJ!֤R5lDz;Ɣ$ eelD* 6NB:Bqe;w9Qs i)Rە qcSòCRO@ {k"MEقyib3x0b3Аm+>pniv؈C\:~BtVb>(DƜX(D2ny~t[ZRQڙ\Q:lrM-Md>qw(XR0v`?TXl7kӂp 6Lwl Z^q{$jE6 v ilO n`rތ_[scrr?l'4U"~oũ1QW5dtWݙ C8ATU#]w}P42E[Q4f^/G:i_ l zFqƪ֜(}J4TgG*>TeɼkX,CH6# @٧CCF44"q x ?:r2 E7[*?]$pn;NLN#y9HFfF,[y,j i"y;W$<)fZi$dFgE'"3[n-*7Y̨EX*`DD"M/*ĉX CĚv8"'zޓg_*2aGKJf`hSCWL:J=42n3Zs qCe:&2X^ ,>-3 pikѲvE^,3k,.A;6iÎHr'4TBXL- kc5qfHuI2BL,Yۊ7Xnֆ+Yؤw؊}ce~2Pd!bUڄiґ=Dܬ+"tfy)rUHj -#7&DnXnִyYyYSyY$/-CY!GV֭IadPU/x qo2(qZ$u@"k;*h5wDvh؈A與UJaRs(ˢS$&NVǖZsQǽk6"~qT+$r;DQsjuA 9Ybb-83"!k 7bN b{ɉ閉Xثڄ@YDŽ؂ 7:#;NK, n)OTc`"n[{,Ѩr{Ozm<ꨗ2!tMذ,ICZL!*2N`Y/W I3F?K:GИ&DR칊M;%55 qhoܥJ V3:pRaI}H3!>u3gu$-ZŊܙ`5O*ݚ8fσ68Dէb5$ҵУQnSXj2f[^\kR;@0j2Z&w4aWn؛G-C  )"+\6+뎔Ea\Ti XRaJ(,LU,5>ClH$gkƅfݒ"<ڲhOlJ*9TjLiιn"xi\A̤ն0ʗ FCd;%Ӛx`p/LզŬH1Vm#ҶhrjOi5ab8gx]wڣ=JH޺3#s;PQ: >>ѵoHlؖ UgzY.˴{0r4<8DB^G<xngs=kzܝ_=_w5ײ:=?Lr?oΠ8|pRv^ౡù &LRI?u86Tmcjy~4A:H*׌;IsSמcc:ةxMv^x˧t_i bQv+MĖr;ًXYvc8RYvI<ĻښK"|Ʀ[flHxCk"V H:;Ja{kSאeBRKj/C ʭ=1 L^,Uk B'6aGdgٙiyzjE)ބRDD:"gjdy1rB- K@Q;_U2Ǔʺ #1$MkF"IkFbښCɋzvi)M3[MHue?ޏoԅ>/7}adQ!|y7ͼRf>(&?{n'wo?L>?cӇsF9w=&tU]M&s&M烈{gIrOO=߰2'φbA(;=SP ƓIe?L얿vYv|y9&NI҉뙳۽Scvl0}TXnl%s|Uu>˾بl4rX8F;$u߬>wvĦ%q1>2_rw~\ )@X/6x,2C wrb¹z a6}MWpz9|Cӯ/{_%Ͽ}o~єo_Z7<M^qr\/V$FwU_^zL&_J>O_'_z)|_+Hz}O.{䏽^T*z.JQ4O H% j @@9NaνB."?g ts1%wY)SGmIT˖z0)Qϴ:LHj8A} aݵu~)Ixj$THTѡ;G+i hwɉr_sꋨ EilKYC!7)DݔMp(5|-MƗVh ^[-}r̿RWRBfv#R.ĉHhwtNYr B Q&\*̽˷<ۙ ߸;Dʵ^@W(UhzHRf OkZIgƕ}aS:ԯhԗ^aܽ2faC(3Ab*tpս3R~CQ1φ5~)_p?y0;yCA)P@ *\ߡoEK"rYs*Θ:#g+RbJKȳʍ?"A$rgo3q5*gNJe*WZԦI~PI'q>bƉwv@w~Dk,# bF%Tp ~ ߩ-x <^PƳp%<"G0ޝ'-82٥G??% && 0R9Teh/긁<:׀"q ?Asз4LEƏb~B_,i]} j?Lwc}!Aנ{Ϳ@=eVjs_4Z ϢB4+} v>S^C vu4,SS$@~LWa|xA/h "-3&vڍ>9?'hM2QBP`?x2 EV ʒEl/7~|@C)C+ f%)vތ8G-ЮO;h{8gr$oNS,dJO ~E=92rB?@zR H]($"/U PVz8h| %q0.7I3 F pqtkWivUXm&2!?{`01*,@A0,~+# ‹KY$c"+)΅6QOFuM qǂb 0O@_qGw7?;x AaGS2eF<Yx4XI)-@՘Y2d h` -ޫ((+) BtjtDu~1Vwbq8څTh_2a#ط Kyج&^!͜xpe 3x [xGK`Inh]aЭ~i#-zMSۧy;RMnOjeX?$tie>!xQtX$S%0el@)FC@w3f "b /@FV$>F9fF:`+ԿמHF4DzФ3y(. N@ f _H#~ (3)g '9߁OU w-`B:$E FQƱ;P#HÛ*R“`a v _!/I!,8G(ueD:GE=@, U_RT"$cȤ9C N- sN&)>a.1@5bdIDi.Ѡ.JA}3? C@> N J >Q3dV RaĻ0VQ^ ҃!N^}`/ 0$%A7%c0, M&eઠ)=҂Xe @m'`3 0U ARޒ|jymx;w!f8*w G:Q,'hHB0`Õ<ڂ@iymC#BhY ZJ׫: DWU^Cg+@{<0]RU4i`Haec3|kUw :0+h7Eo:*Ot h= f -lx `2jkEsYBL R/E1D:ajуVO:~PR SKݵOrB,p$I)H;%D!X~Nmh#u)U``Cɩ={;etp@JF6%9˙$g]$U)F"aøOs|9n0bQ3A;k(P@ !)0X8@Cm @D@p6D'(@E޵0S@q mGl~vCI`]0"-aȫ CĚRx*1)>^Ƣ:w$@^)~DT1FP_S? t1 ~_ N <@hB-Be R/\5R?&G@CF$kW;̩.K bi?"ܗ[:K[H/U1_N<oy}hԣstUD$"^E  /$dћvW><vQPt, FŹ@[!o$!p\!b!Sd21|iQEڣSċkGiPǘ.}1 C56PrBfثRTs܅3 0C1i,ex@?"A)hGB" aAPH*E#fyi~$@_F=$V|x6w"E<$yh 8.5&G(h AQ \Hl!?FV -éahVͲ* G@29y'D}&BA@'UvL .@tCHxl 5BCUc?O`|$ZC]贂i=[иt+9}SprO`37] H".Mq?0Q QDŽ T.p[! x4C% @t7LY1/P%m/`6 '?Ɇ2Ae i( Bw ֆ?cw)=hZ7 3!Xa,D@Fk8$R`NM* ؅!p t$FXE1h|/~)^@8ULal[ujxDnwkY>@4Ag(5#Y`m^l(rQ/C{$v1^j #:e s.1GxQ`E_&eB`)8p$YJ^]N.ӱ9|89C-~P |<¸I>0"<8吨gL7#i hC)Q8(3(0*Pa9N8E&{w @(N5 7B `>xSψoʠ:+3TyˆbPIU *EtLA(8lyocr-/xwʣA(LAb:(B30r_qa2"8?vc. EAdAqj|`2u~q `H0">."#RF]I2FU'Omń%* 2P0<C4 PDʚTxtMY*oܠpVcvL%%;1?)1kX%%3cV gpC+MR_כ.E^jlXx&˕ OGkFk:ckkU)[+zz-܀$uhax6#HHiD1 sFPHm㔏lH0Hsc $C&p 45Xa& &GȌ"0f A` 7/r<jP8P|F thxUʌ}8H f_c =Ak` uD}vtRzHnrFtzS)oW#va~0'0xU e+iJ-rFK ?)4, ͐܌]p 3V2bY'%M ~RzS'p ߃jC[IaR~=މT{K,:8.ER8*WԮĖ?yL6_+P(S5xk|l%-E>D!5TJK -š>Z DBU+* *VђP˒P`kKBPE1RH3d Ԟz:TPF,fhL(7/7` 1F@OH^p =D#7nH2`oxlGNRš(\#)v@qGhjp7!"b&,0+ΓySMa֤Yk@?1 O-JD0Edq.$v? H͙aas5:~3KQa蚘R;0YSdiB & `ɂߔgQ<gqj a$0iڑw^1Mp2A9~W /2SVQf4b"kk<(+z ›GA7dڴ|՗ B9z8/&"#S8HB_q.s` Fݓ`r0åK\oFO$*EQ".(.Ǣ)EYE:E>]sjTh@fIclŠ~ymadn(v)<16!'%}k/C48;{/`0m8 É9!nblc5Ƕ=z?yS;SxFV5$~CS\IШ${δgx J,AEPpBŒVeK͖]U-1M'~b"&%":9D;˒FLpam1r*BTxT:s<垓 vd  '( CxEt.lj 9F,cK O☂V[ k5Oi'"5_a7FI( Fۅ,܀%/g]rC:P45ǃrgkBxkRj?X+4!psLW8G!5 c{I gcB耣;`^fddJXLB/dPI# eʊq6q@/hnD)Ֆ–Y0;odRwHo~ .Gcٓ7}[ha|=LQّgƖf]u-`Jz-ﬤKNqJ6գ3A\&z-ID/eJKH /|Ӎ^n'|Jz`Ǔm/"Km9'}7Pa2#ufR6$L5ȔiftX%qҮ>*Ħ GQ#(Ф}SVG/XmXu7_3?^[yoن+y"oׂL??k'}|bQG[m5 gQaۗcx27~Խ5xf] /׍=qW*qD!G2cd㒸#u3:OL6HbajMߐMP:l#evB QJ#=:"O[E6J[<A? TP:l'evB(2r\H$5|filiJZ e"[kyG풻us_%Fo;I;s7DvxPiL[|bmA;BvMvo [(8(X$ɶhmlshK-[-iAغ4P[8'm/ GGeKK@6Kyj6˦~M&uoVP&BNq~u5QvSHWFHElG/"4 ?!έl{Mfm'>9 Ι{s+[@Hq>eDp3c[#Lf:$4I Eb$Φ gSL탘6!24nOb2nEkj{]ag6=!G$b1wR[DcUm@[g`&C SDJ{uc-ƚ| K`T ( mMN]+;Cia%&Z/0Y'#:5Z6JIo> Gbښ$* ?9\f)5$a HRǪߨTpfI+ $syt>~s6lfAg9 F YfoݎC\ڕ-&dؑ>sE&_q\ A2 :NƆE */,A IE={Ny FlipFlop.fzPK!8Dˠ >FlipFlop.inoPKs@Fortuneteller.fzz000066400000000000000000002644211250202676700334400ustar00rootroot00000000000000fritzing-app-0.9.2b/sketches/core/Fritzing Creator Kit DE+EN/creator-kit-en/FritzingPK8D2" f) Fortuneteller.fzr\Ir0dcL}G$JVϡld xE򐬮~yyپ>ߙ dH$ڌ $vf˿?pqWxNΟxw_??ۿ_~xNj󓧯X}=}q:~>8yvfX|݃'_}'+'|o|ٷ=zWv~ɛgo.ο~w_ɿ|<OϞm{m'ߟ?7_?rKzx鎾zw^zxӷggߖp}b)'\<~ݏ篾~o=x?w/_7f> ?ӳPӷOBi~<9os/^W z_y屖K`/<|߾:DR'>>w^7/.^OO߃^={|n=p?In^Ͼ{o/}M~⇿?x7yv ?~;]ߜo7o/_8o ?y1ћx^\;۫g7n)??f l~wZΥͰ9;:?G~y$'S~cz~y?/~ y͗O7^>ًWn?=oSiE񫇼t庫}}.mOW{ߝͫ?f !'V[,!K[n/u4u{sQSoۯۥIw&.÷te=nϧ=]`5x~~6+nN6?Gx<|KnGZ굗|KuF<~?~۾oX6S-Zؿ~kgﷰs}egʾuJYox`Fr\F؇e$GK,2{.3uo#yj-#z;Y2Ӹ.K/>, ߲>0sd y.)ϕܽq:,gM}e}$|o"ս򾛊8Ja9h쯰sao?  o=^ -U> ZWvvb)i3œ/;;V:d_d}XM{췬wlvbsB98rCʞAp oB\1! ܂ohwj?cUGx/˗kzq%5?~mtȍn{/z7IZg%}`~ǽTz_~mCnu7IYm7IYgIYpCxq}XFqn}X6q}`&;c͸{/f3uh߸~ȸ>6"øo>,_~%}u/>,o7.kq,޾ɗ5,[q}XAnܞ b=aפ(׶>}ayyr{A5q}|[ُ=$nHmrWG }}m7q#exYևgYXgCqOvףoOևe wOևe [f wz@rmW;Qym;QukQq ckAێŽ\{w}{)C`7]r='[۽_*rZip/Sp?y_G{Nԇ6흨+kQ}{pomCn?YϷpz;R7sx劯a~q}_=|w_\^O~w6cy|/~|uvǯ޼oß7]՛go.>~_\q775]rmj٬j\žne$4|#c_/}{*o1u0\=/:?i߼zg)߃y#^/J=8yٳ7̛dz-o}{geг9TK+~~ܽ {Wy%o_Qew~]7zGUIޛ__2>{KLԶ!jsZ$ŶE]nWRe:F_w*m*-ƣ"?@igTW<QUܲy>Ϻ5a|[Gq]`q면=A 3{q :!{ ji5^SWuqY,|8tjqzG=K'A3qP{zw^ݽ B{R$S)gcߺ#;>^+[Ckc(zcP5:󅢿; G%WNj ?|ٛ??{5?|-+k#֗^̦͟N?o^\[|p?ίoZo+./}߼#N^z%SmoxwSGӎ~cS\czL1쬮~'?º1iL}Y'dbrJߖ 1. ~Iwiot;n?:(-R.Z/οųo>F]t Vi/~?'dQ'·A[^&-H|U$j\>9:gʲ3v\)SI%cHAEwUi'i.Ҵ'fy?<{ۋ}O8X&`>}}f5G2O+ i7|A=8y}/'^W鿝䣿/=ӻӳ'OΟog}m'[='YNK퓍p飾.>G唺iŻFNעd%ՏX+KD4\:Wd1[kTZmǨĸQeT_!zA(N÷nj>[z>O-3v3m {|^1eW"cwכ"r*wի+ZH_>e7YO;/-Xo߽ߖ=Xu=`]:]Re#ut_q ҭ܍9ugWO1Hșxoemqh?.ߊCϳ;u77ۆ}?}@!RZ Jc^/YEVyfHsc5rk!h=rA >I=OY%4|>I=>q&MX럞9=ѫ]uwMQS֝3dugRi=%+1Ci_ӺJw @sdōw\`[nIܛ9[];>i{S68q>}xŇwpbׇltmKunx{OyW7`Uց8>mϱ"pU}ƞ$.ӏ}.:h)ږulx}6h#_bVW ;V^>5O|mZRsxul^ئKwz:O:j^ebWވ7c;mN~ǻi?q\csJǕTu9mxo7q_\}HH hn+ѮE0_kuߎX~mioŽ?X|Wv:ͽ{ۇv[i?AMI#Z4{o3s(9#Mof9}'c:ܼnTAEߛHz,߯l>i:_ɻo{Kn--wLQ3[rh5|x;GIڴ9vuI;Iڅ<_zŷT,.骥uLލֹ2>|jLkPn|1H}u׾k"T?+̛aeW{p[괁/Miݯ9uAk#c8V ; 6tqG(0>E`zԄ>¶Q!w )OuJ8.4{*rdIS }1$}L!}UH}(ަMH]kz]$wZټ68FG>-''2mwHQ2.j'j6@8=Oʺ&><>Ma6}[{Q=Ƨnڷ?+y;>W]4X1uyP}ۇ:b#ӫ~-cLzT"GF1)18&mcR5X(> .6.}KC_}DXQ>f[5H3ng}^ b+y+.WuЖ~eW#ƼSCӣJy]Zd3 勍Lictz#FI;Nz? :mقSoz{ulzM[Bp; M۽B[P2cUnkW-$&-cӣ>y]Zl3䋍Mhc\z!FEq)%}f鎛M ?'Sĥ1mُ [>iDPeZ؇CYy7ie]ݱunc@vf\oC o~iǂ&獫kR[8kH5tB܀k/5"w@Q9K@ZSy@Zy=ߺWG-RRS=כּ!aţ&DcZkvq s+ae{-⭩c@vy% kkL6z͕qt(ףVú8RZUm{؟<wE{ߗ${Y=ś7/~W?~^iWĴnuKY)]KjS{>ܯi9 ϱZ>Ijh&齉#9Fl[q9ȡ~[ߺӲwS~+wfWÆ;=W&/QW[>$NՉՋuc* `?;skLc v1'hc;e0śe]7^x7Oモ!zYFZ&S;k{xR {=Fw\z}ݺq>8rLޢ8FdoDdwk ѦM6U(>#1H{׵LE{_BvK +9mKw1|{[4 |wmiR\f652C>D%uI=Eo{Jy>1]?`>)Y$qۻe*ݦ;tGq-cvn>>9mom6ܬ2M?(NcHHOu hP>2ldQ[YO1.nױzݦcsI-cvn>:9nonC7zPJYјG^r=g@XsS]cg @}p[$?6 nj\JoW;zzJ 1Kr nUr?pw#[#܂.%w/~ 7?bg9Fs/_?<~zNGkߟ?7׼f3_y?\g/Wqً'Ϟ_wo/"7ooΟz駟?W=L!eDzXʳ?5$gtRG]W}zŹ_?-7gOw>vm_f쉿/{OLm?߿>{u~ꅺN}EˇsʳBN(Q^v~=89Ӹν?זNm5MSe=M.͘isu(M0?VqzvG:ٽcq柧R]Ԫ]]kK.$.ʹ̈́aJ[rOv)Og>)A石G=nM?O<(5}3{ri BsgvUS)KUb;l=aͺOURŮ)T}׵U]`GKCO3"Lׄ1C]( )1?]>48DDŽ\_b7nMrCS{nm29clG=D7%\tKfZ [ITU0j7v=of[lI+ek0庿%xYvx皵e*khY 3 ڷ1ä;5mk$;aKOl?>N1,iU -R em5)=ԁI_V¡9[a?OeRٖ cݮtcNZO͓^3詒TUբӅT/RojFݪ>lmtyUzG*8 5. ?u9ٻg.:RQҥvQ Cڹ-s$I:*lXY=~F1ti^zh(?}+tw_z6I]#KЩ:qV[+?av&iѴWe&邦 }Bi &!IGID)'- d븰z9Ici yhyu^iPd6$!fe$dX$3+As%q؏e[kgvE;hWK[nv#KL5&lpdJyEʬ(.l,լ9̽IE:JRIwC{v-!7idzYۭmm*%^E>'V%U>KКvuqf_X.Pp?i9S0襌YOM%qXf -&A*=Iqʷ:-fnG$/IU385&#aIES7:2[rjΦ~奻q!i+N%4-h2h$ Pf*t(.p u%V+ Ҡ\߈+it2>>5\0$}vDnm-{,UM~F|M70HFEmw~9mc1Y.Vs,E`.,(`퍬cR}sФ&@R{؆6-Fű]7VSwlsb t$HJPa V#ێT[(Qn< R?R\ٳ1嫌Oq/nm@$i&%NڇCE|BґZ$< cgw$d3"{Cݼ r@U.eQOŞyrg߂265S /=n;5ӦMgG1_̴M\(GXNݩ@MptgpG z̏HBE݈ZD|yr}(fTt@oPHi`dgKIb^.O|)Ag))H,dMY͏l%&рN!ʙVO7܊r!;OK&z$*mCa6yU^XaѹIrGxFJ?b 3=cizˮ{di` xlP 䎦K҈0dCt8Kc  RD&p=(at䂒 }"/GLH~D2,JYk e养Nvl0R}S,B77ƎS%^IuoGId(nHi'Xͧ@ES6<ʤ&";Ws֮MyNkggzvE%h"J M+ۊL'1 NmQމ^ p8b5i[䣧C^J;;Vf afO׉OpRtFz+*!L֠jw^WMEJX@pF)YYA1q+ƴ;Tdg +ۦ Ħ$'WB7=ZIi4=[dVfK* dKNb ۪芊>RhCѕ)W;ur#7&HdqcB߄Q5`naisBҖoMо#= Ƞo𻢪<0\+^"[b+dExtEv.L̯Y#(MNՂ!=OhTɞ4 <.v]G4$Iӟd>ǃZ:$-uT^e._M{iȎ#Z3 b c0AWƎ!kUh#Ų9QU'rWb0=&PdRhUp9U* )LJH"jZmSREJxJ5bq&a*Jٰ +b-k weX&haǚn 5M&|t,ъJ8R-^68hO蓲 sAh-[BX֥fOOaiETlA5mj\BB@itomhQeZNjԝQqRၻ5 eJJNUK*NQI-v][sI{)0 rUszAr>7'u;VB.O{&Zg} 04osQHFؑx,6͖)ض<ա\ɨnXUmOKZEzov\5nH"(1ߘ,b~OfvaN'e@ȶ4ݎwUaz*by}.K[;K2  Y^Gq*Zum pt I|\cLJFyhrNozZrҽmN=-|SXH퐇R227īZ/bD* 5Ϡ#x;N6L*%(H]JEzFyv켠R"rTŪjjc|iLq{^(Iپ҅,LZC͐F S7ɰ`9DfWårǟLMnJ!.(J7i=%}R l2|HHctYLrŎR8OJDcae]iq/ JU 1yOCXPP"P:crv4ۉmR7;V4u fSHL~9lVH:SоXR-83t4/lE@qAڋ:~b{ Ym-90MvØ Op"JN*uN֬dDj_QXYͳj#$N|hOhSJ~v_M %Ao\ Ef#)]'s2j˄讣 cg ѕ{0nI.9RAݳͦѳwຸGK2c-ve`oSi+m<rh*2X̝9Eu^"GLԁ*-TZa ,i7!"PyQ k  \Ai/(Ti*9T?"iSvNVb VlJaB|%)aIOTU-6E^  FN*kg%޼ջZ b5l.hi3uWNxZsIr!#ٚgZ6j8 k*%z5{ó:#NaKX RY xٚٻz@Hch1'o%}!] awL ]bzFYx˖1]ٳ7>5)nRu`8J l,|0؅0]7E`\)ڣGcs@ "\;iWZ ҕ;'T7u=$h(EL(DEf00@A d@t* ( +ս[SB*P h1zQꚢcS=jv1J,\zRĢ-$eefE·!tZ?0cq ip08S"e"%9qilTېϋŋ:8@0]wҾ D`NlyՒ`ܦBl4tW'ݴY4-D2$cj$!E(D [ r&~?y gNUƤ"[kr5.hN­fҁ:cKIBH%H^pY l#r"=N:P3nZ el+EBY-H( a{hӶkRa*3<gzcPBjF7O@3A/gwt 0{@W+VK؎^@T;J!+ș>ѡ ; L Z{ID#A{AJѴU4ThijcdUΖ\"=ᐲwj*'i# EƯlzycH|f ymz".֙3a r<NQ$Bƴ #A[5BW@mE8H4  DjPE7&aX&:\|_uG,R"⛐ewJPTnT,uOdk7]J NJ{JlJޡrv pT }4+v#jңrݾm~f֚ Mv/[@5ы*7d%. F} nJBX1xbo:(Ӆ F UvQg,9UԺ#LM J]aTx?g vFwv!}Tɖư* 6. R0,aX-4f-Es94[ wMPUUfXT?g.+V}"&oYڪ3sT&dAwkEQfW]%VK`4rZieAqx %MTC1&-#-2* qCx/wT2[M :<&Q4/*#U׋+*ôq8$+9;[py/^тMk$ XHp@MAs#.@5"[QbMq҄yՌZ/=u&7WoBP,XI^ދo \UWr78ՒxTgjQ*ZȚ/P*TwAφQNy3N2=oNPUH),@ltIP@mL8xMdttZ.Gx͹7IG1,jxQ A<ڔwFJ>XPfz pt]-8jdBDxHSuმHp!4+a&f#ç`ڧyc {!K>B'im{$VeۜM2P?¦I_RؒA p&3C;w0x\GPgQFuDc3!*;`qD8dQ uO dl1t SՕpe]@`S섖>I ܴI*Ȳzخ,% q YѥجN:kqzRp+BJ8#Mayǭ+I\eӾ1QpfM4\ՍN[:MV&4U7px-\ r :8zrW|~:XF1y܇3aꊯ ['MLFvT ԍ t*ĘGfw2(=~V%͝ JN[ o FAKlPJVn[*Uj%s첗;8 Rb'G@oDEyu2dTs"g֪**Й-!ztx(<^KPQd4g1|v]⫚3gd5m6G JbIY{c@@o`#{+q1DR DO'A ʡ t HԠ Clt@#éyO/Jѕd -fYN5i@ˉ|;m}VEk41,euws+בR1l=CW J֝_ 7dlҿAPYT ;!DHʡIx. ^;J{9a(X N u<zLѶ8EYlh X1U-Frt)TQu?`QRFP'fXy@chtε`$m,֧*֬ٴBAp R.p-(Ƒ8T8p5H0:]hPzQ|mñ%?9$Z@+Ur#UgA(>FP"j@`mj#:ZVs+N7 PΥ%U~+FT H-XASC(Aj-|L%f39;MN'j m%DR @bsT!ƬtFPU$ŦSk, F˂9KKBTZeB¥%Dg 0I!pҀv:EH ʢu0F{ IjEGPW\D,$Y *RWK/b_3@w!YRheSII~Vh#mv,s_Bʼ0=*QL y^d?|1Avi\ETDNf:.`Nw,Po7w}DX#9) (!?[3sm)evIg:+#Sbj$$03fQ6PKw9JxDX+ ~ L*@'KaV|ԅ%d`SZLCe 8tOigmf&  HZt O3^KJhjsŒq϶Z/Q`<I夦6PN?FV 8]#L$vL֨JHTx@ d3xSH]Ḏ'}Pt`)2cQ: )t,:͐ZQ訓 O*6ê2ӴG ?D@ de(AXy=t>H9Mq 'Z'olMȊ4sOY߭}ynED5 aEi͕@5BJçodj!R#,)A;vo!eFfOKvFrBmTY:DlU`ori/>!P$TMB4o})̍HZ_G/rΡ$mׁ):#,2K#AZ銧'E,Ё*Βmt% nQ0(CJBM|e\}1qp^Yl7;օbiE*ڿBPX+/:A+vsU D$B43Z$ImFLGM^=A\doEƾ9c}\U$d%km!lsҔM'F1`V6y8_ҙ*–x 4 R8'K[A0tFN ؐ(M1kb0>T-boW`f"6UÁ'tպ7* Y`Hh7N؇ 0)4w526gf+rrX[3ֆ&fpp6w)ю>+P@SY!+eHjHg>%a"RC UXiF"hHPZsEC7i.4sSUv0B!CDӖ^´Qq%6:`K;[.$ %1G5g?+prVo^9Z^°T:gx04'c.LPAY!N}Pr)u9r ❳CҜ ST=80e &x 7Pe) ƃ)=GWT &Y, n.Cf(:JSV"DTÖg Rf#4>r!Ufndm=j@^U&jcyoX dP"BqJl*N:C "`J;+ F>,0mH7٦شaݍ~沤nNM3? I95EyagTmHKls &zWe'kUs86w/y.r'&'M2^}1Zy'MeF|(B+(th\^QԂbCjhcb3md}>jg𙺱 OB]ħ-I0dq]fʎ;\592uzHPǥ06d;1ޫ~H@1qEjV0%Ǭ- in }Q*lpF%eK{״y~x dn* )BX(&wް0? =ږs"[5m|-Y; tFU8ft (nobz4XJ!mS(#F';PAcq(0.MQKmD0=М8م.^њ(y '{* !*S[Sh7LbԼGԒT˜:E:Yb%ܟL3> =,#.'ԍև6HxPc[<Bړ]O,Mh4@m+<݀q4Զ;BF&K\鐺 ;SBBeK>ORo¿@aݲX)m$TBmGDvYiu%zOM Ȑ0<W)th6䲚lNt:bxtt?Gȳ.OhJ)EonMqNԃ!N+!ҳ6@Q.%c & 5/qeY [9G,Y8 VK,'5KH #Z]^} j4d uny@UE`)K ӄx&Q0Uy00Z9t=N}Q$j6DpOoڢ09CMTܣK4iv΢.&+UU̦q'qj,8lq1**]i'_ )!)TA/C 60A]9g6K]W9Q^D$r¤4ȡ'TJd!0X}};L`PRPZE^Gc!>s4ϰ؁D@(KX5K\n܌bo3Gjmp:M U hM?:B%t Hb 7c*)LAU> jӥ< eTmQK [фK5)!Oyl~UR]wGӥ oC;B'T(/*J kpE"ByKYkh ً#Ꮊ$u0{.,N\6yhA 42NGEVv1GQ2Dn5?ֆOapMsfP_\2N)O!P =z!b-GWBqIL)ɝN쮤eiܐhVtvO)os8`.\kЅ^%H :$Hqiz)ʀ"E&9 .'XI8U!0K1 St ldEAXE'"g6wzeyf:#)2ӐOaܶwCU8nnZD^ܬ*OS H6 %VRҘoT_`(ZX MtnHV'ko[DEOPѼpϚd<%UIb)_u,A$2Cl8nʸ ]_)M[ =\<+ z ƞb)f ͯ*c,iM8|SMc6Ft svj$'8SU@/ŋLiJkdzIT\m-dFc@f %"ZPSʆ9VWMM>?Ym2O6Qh/J#rDF6,0<(Xm#: u.bW6qe=׍HK}J\uf0ɤ ի|cAh:\

    #\9AR*VQ X: Ҋk@eU(ˠ|>`E f{ 7ӎtux{xXp8u[&ʖU!6cʜG{r*̻ut$] 3O /~/%/v۹)SHx9^:pbc0^>omΞ87~tu9s ?/nǂō#'߅kiVB$4Ql܊%Z%k( '\F@a D^TP( oe4 ؆]vbRC]zIQңnc=*sOOfI!DXvm nUֵ""(UZh !!TRH3}n?s*ɽSoLxidƦD0עzypaTp0hyAX2=WϜT0bKPuPȮh!b,*Cg٭~e떴5ϮhEVF{8gQJR`x+ܹ+†'T 2?'k& V3 >6P{liWڌӻ/?|;nm_ʆk)&''94t'GG<ھu7lK<ԓ3g^UK3ui#(xl ?F|^ L7+>{W@CCe:9048umٱv /W%MP~`z`Qkaa8PIξx*UD!5ǣcG3̙LN $y;O@`bψle>5e<=:_Gz/<=6}+/))g\نlʲґᴫP$EBtLbiCz7θe9z;JjKK0@1w l5}͆UHY w(t M_pWeeXuDz7{t?RS,{fc%%_4/]: ߀ز޻RoS,9oh8Ȃq곈֧l#a%FR@pAft+o`x̛UO(2J+ 9q8D#Wz9POqA'VeވCO҅< `OrjԺ< ,+쀫> Ϧ<(kpYgg*G<@[;FwDփ+)'FD`c/GdQ è2"PעRD~8\ #gQy&'*1!}$7D]䜙nޒ׊W;k mMC\xN]CmWvh]/7?k=g 7Ϟ$Z Oڞ[LB/"!wsE>v,XCAAzzh@EŤXl@Mo@zK_T!p#uCOJAp|`PANUAcN/hIA3NUC!@q\LA)u{OW >{4uZR0d7a5"z83-UQ~ *Ȣ,SGhK:QL :|M}yRN0Y55ijJz+SCc呹msg͚:m}w`bܰ#|&_SWsX߾}{ͪY^vqYȌǟx5jDgxCKk{ZzYEiCYY?{΢r k߰j^x湊H5`&KYI\湶Em.HHJ`MyÂJ  $DP]lVo`%Nqϰif!QzN2<²ؚ&5˰HeBXrY:pׁ"%tƧOk7xujd4(奀+[ ?9~y׿Tj} pw.輮2FGFƲ`ٮg@tY?V)gT*hfGv: Ăn~U H?uNxzg>:? \`T v/XOy⹋S6Lۥ(;TXg d׬\p .X_ב{ϟ4cagY\M}C봙T;+u1.U"l&UHwSp݆,{aZ>=y-Z6Z6h$UFOO\|yq= ?-^f/̗ypt(yn}llJ!zwi2:"X_< @:q|Xj 'ev  _()Z6lc%OPR$6T)$*T@&WaDiDhe49֍&i@9x乾 9͂ZЦzTI Z7D2jP'ڶHYG- 9 6$UFD!H$Q˙=B7rYsIǮ#lW(LÆ!=<+d8 B(ONZ-ct !X"1kVMe}^0IO)m :ru4;, N?c϶7>ޒ |ӏlxρNOoj(-9rTUYbz?Us/1Ij4jM}oadQFk21.s%&b=OM:% x kD1֑a*Ⱦ*O[X[PbE'lRyPQ4B^%gXⵤO&T=$Tl`N[[6޸n-vw޻W-YWBC/G]Ӟ}+=7mhk܂u$|w뻯t={iP`$ EE.^ض}[eyp3\:ub/Z,QMq(*`i! fJ" 5@6ofccq睟'zњFBƣK.w(k A*S(//{띷/]8{܆ZFaUTdvtH}]CCK rTeId:t׷nڰq|j~4VY~`9"ݡ"LT|Y{.*PdE`ޫ~>#N8*ÓOh5k)RU( BF&Kҗr4%gN% ̗S}ۆ@4*<Ŋ>$|(;}b@_ .nNDwdj_T^NG'a6MQOdG*A4]bp`COU4P k~JlӀGߡ ʺQ: Ԗ/59jC]|+cɳ502x묤#xpPj 8ʬGj}<#qEPwMXDTC T*Cpk~t{j$vMY:̶w@P-XtopI0Ր%6n9(ء{_tƛ*''SJpdٜZD;:f:]kOݳW_M9Svs}9i[ / 􃏎VVuϢLfXXrX)lͷ \M.+ v_ZVRP^U|ϕsYPy$=\H@8tnX{]*Ŷ'7ZpE"a!oۏ??IOʚE75?hN;/]T(F@89K0ʌ[xCs{qկxJ- ׅS׌?mQŕ%Ͼg?{I<>N paL7:thla}Ӵ!-C`wg6覍7%kts(L@Yʁ~FOtB3{\\a<u.y1)Hiee45TWח$w EZ8tr UVU^8kK3髗O^mh*p!T.NN%/[m ۗ~~}}t졕67wOLRGá[9xhŽxUcT)ӻ Vp7j #Kg1'bP~C^ >l2{ñ7ơeF@Yр(=g JzxX vX] J~0d_bidVX8QgHW\d9vVVcUFBj)Q#NB>7w^POg(W TV:(O_CJz;,eS؟1 .|Tu\2cg\T h^p74$=&H=U<762m-Oϼbűz(R D^yPwLw(L& TYlnw2uun EݕX4tCضAo0~䑍nKeMeeF8~C=t*C񱩣c;oz [3ktL6ϣReWZ?]g扽;v6ַ557j$5U4IdrOU ucCV &ʾ_7&uC(+;H9Mo[>oS6؏<@l]K+Eh$AeagǢڧ~Z7UU/+/c@M~iY+g/[7~/m0(iʙW8'CEOe2|0q@Y +(@ {(.zUU5v>sOoh Vj*f\a+)O>ً/Jѣ:oN ٪nl cf69cwXTI@WP.K17P+!MfZ(ԍX`9@{?q2Vѱ<"P"STҥ֐v35~E%{agS3;zCR;v?~*W(z"HL*e Vnֺ՞]_^mYP0%[5{WNUWh4 5_*Rdc;le>%m`M芺GlV4QL- x28PK mi!|KB%>z:d= tkk,,̟Gi&&֢P0Gme8:UTVuΞ[[קISf,*Oy}<ϊ*kJV˫+kdc/'B(Ɔ7_;`a rԄӵ@ͨ2,`0y6|`Qlቃ=:Υk3dvb$[\j5̙mHgLWy&&ץ {4U;z]kKrb?eknzS<|4))-ݻg}j}t>Mw :L 1x]oh.n?>'~ΟV坁6NMv[ϙ& cdn-BG~1s]AIk#]:rԩw~>z}DWg\.M&SP*)ihinlN2ߵwrJ2Ǡ `ZxV!6x Cp0㿌F%Yy.T2@%HkWmDpie9΍eD( kβL5+UBrvTQl{xty+!m.L e&'S6J;뙘ȚĻn@KQ}zz@₺IJiTAZJd2A|2(BL5\2E7[] P5̪2@H yl:6J6$pg#`qyɣ_xWo39m/ٿO-Θ1K"Smۮm>rw[6=9UXOtwxLUM֒UVU7"KW=ק |<6=:b+o䧂ذV9Ab`1STLgQīd-Re2% tx )#y:9#}UZ3`y%BI*9ƛ]FH, X ) }xq"OMRX%JIyUeES.ٹGO~V=wBc" ;F<P؝XˁXKΓ򹸪Rk|rFva=}Oõ(& Wv *_SXXR猬 ז*%d%ALT_=r>F'51s!a('qX UҼ˛,>.}v&?5?5[I"65>IAmcÇodņ XS[ku}S6Wy>결g,J?ٶ셞Mw7>ٳ.ww٦5gP7LV|(R|H ]*Д| aSS(?sEum|l+/\|ޔŋ{OR2z*|wޕe)>0QjmBIII*9o޲au(w*E5cuu5eR$\?\RDQcKT6Λ3010sG l?#Ꙏ(*/Tٮ3j*^}]o32>KЧ76P\*g/9)ӆi54NSe8' дzݻ?h}GEt*9L&rmX*xP(P{!Q2&0quT u =GAeuՋu;ۦϛuzgo.Ywgjla_t5o<̝wC՛*oSezsb_]cKMu%8`_9SZkρpXLw"?2ֱtqESS%ҩ sWp,=x/,,_ୱ$<]Z T4 N+Tk֮GM_TTs$RUѿ?ӪV!3 2W[VQǡ;Ϟ?601J'XlڡQ3i~Mխum`)g,Zp_؂]f-^1Xӗz~zRAYSYHo,ؤWBI€Yxh=J Qݜ vFa6&ޠS d b#<|4Ī;{ )::L5:bqqiYqy&4G̴띷XH)CZSWHGj"z· v $al ]q8'ς`Yyk«W  wdM9Fc_I}l6W};}W,Ob-Q4(y;S%+P$K=Pu}󥁡+vt϶},6XT}t(Un.O)`,1%%{hXo?Ԗ?J*n{o\Ьh4NFmS`+ZZQnҦ .<Ƣ"_Uv6eZCuzfSS#uTlV 5UupTeZEj6M@f2 -8"Bގ0 wܷgŮRP;mn `\7ˡзʚSǿP?ZS1*:/[>5vfU$65rEC sŽ-)>w,0R=JEVj+*$ 0YsYS35Q ț *x8` f m0}9 Ր GRCcÓ&.AYTիg f#%ERQqUu-UPB &z{;L5cC;xd`k mlIµA6/})D??MMNꡨ0Hՠ |Y a$MٛA~]C^x?+]rnaRD8xw7QRONN&O#+rEfr,QKR/J"Q_cr6uuٲcϝr'n@0KKޱ#x_L]z{ҹ Óɩe鋖,]}t̘}Zzagkǥ Ip)_ ƿ!#1 ڤ# 2ŞX;阎@kL# D@0 5vpG %xh, R1@@-@Cbxv$*Qxp1#J1H[}xv  Xïo?gBxtђRt,Z.7qstiPT|@]MUDJG-nf3Bb!Qu೫tDH_.Ts=k Fd== e=<;杜0*lqiOV~KJYjkb!+^[ W|x\P䠦1ٛn:daH_69 Z3겕+x?;?{b޷[ 婡H;+:oe-oA=#A ۋ]T _ny5)Dp ES̉ 9тL m)Ge7hqZVoz $EY6Q˂-zI].mxWI0mJ*fp o#pDi, 2EO/z/;{,s*ZdsG#ѼE5f~m CcwRaj~y,K0"+[GszJ5|>Ӽ"ZY<;Zt sPkaPGUh4Xxwdn-&Y D"8ʴu2 Tz_m}2_^YA1>sfYUU:$dG{~ݺaY'B/4>J<0d6#/g_y3'~߾Kw_%t,jcQmt$si8 W[[^{ wnpAsڞ 'd⢑{/ލ,YTj'ʚ57۾JtI%ctQJYL) J蒇x4QJ7)<40Pb2=TԔVٴ}$( 8_{WgUVRJϞž#wnWZYM? C4Vie`底DK֬[?:<)<745=nGB޳=S#.}Vkmo[duu>~g\m) ,`$uifwn]":(( :42Mϟ:=︭z<9JK;5INB~ϤYxe֩UhY=H4l=779Ŏf_UXRd\H/ 1E BJvR@Oz?J$p8X@#PB XcTc ueӵCd6e9ӧٜemUfRL1RԚ)2`sâZ=t胣TI_Qe%7qEV?tqIu?ƖT:(*j[j:wLܹg?((x,މK}춢xY*|3d9h5n{aܙx,0][&I-(<lZ,1[UdV@”ŢUVC ZEYj*vn Y>ڞ\نmBrgv+Mң(`UNPѲ킊"OjmGs`;..TeMKRch.7:ӳeZ644bK@X;0K/6awJ}@8/}TE0*ѡYsUh:C99:R]Қg̝1M*'G'*T=sFoױI: };n]_YUV]s3WMP%<G{X%B 6f,{( Ft(UA7կ7ްjP_D@dtolzɉj3R[͞3w-ɓ=}ceB z+-zU%D8;=! Fu%Nđ78<|-625d݊"=::8}':=g?㟴O{9^Z:|8b2lq,D7U oXg9׭G3 ]B:*wV]Tȶ]ΜpnKǴDUeKӌڦhymZ'S~;糩\>QW7z$fi0)Y$-]:P@@7H XvdM+nFٌI%]VF^dwr+/ASlym&@<סވe7ԗ WLU5*qSP0 :ji))byʴV phj`Atp)pF/M:= ]YM= <ًk%ԁ&+N酕P6;}rcz*79Re j:m5 ʮ[O?w,/ܸaUo?$R}ENUaXԕZdZ/;fܬGq==W}ٱ<`kAMߵd-7k޷>yu=Ô(بɣ$+vHGeіu @ v~ f^FS=HDAr1vI  ǰ!qSSEvw[t0aʂ'LA0iҙLIEOvrC-B:q`ZѮ:v#-}1U/.-Jv=B A 6Mro|KD,$? _;'$m(oz͵ᲄ*F?azҖBs#_x=;|ǭɞxݹϏ/zԤloC"zԸ._>]T^]޹/λ_%lkOzDRIsj". O&ގۻF `^9ۮ*/X{u}==g|e{+r$x*ǃRQOO-'8=sz12%K_ܱ뛦X~#[Xnb*{r4SҚn߼v㭙LƢv^RmӠ:8萣 Sb\$&[=bYG961ơd!3$9jlGMyh~32Rh0 84,cҹS0m DiP7j28p+E _q*;?rjL%l@Z255w,A_O PG eC~2Ȱu 'LL6 MlgsF ~Iu U5똧\9sܲ:E[VVSL:7kW-N^|lK\7u0[f4Ɨ,b,}M\]RYP `'tfEewѮ3~GW'U?>v|GU7(TIZ8{֓ʹW/_QRm=_U5u̚N»2nJz1Lty $>YDj@@Ɲ|scE.<}ڛ.Ez=()[|s2%k֤&()-;r+xV&#T@PIԀr` sf͚],)dEz9"Q^VQ ΜG?|HWw7/#_]r WW,]oKVQ>3;l3} ˖:sl拍 wsouW4}tVE#Bwx6JW(3ys}۟E+&&ڦa]!Ñ#ulu@ B" +x4- 20\ |gD'9sb| 'lnݍ;Lfw߯?_WcaLO)C,2Yp-;,Sdg|]谱" -Ě@@YGs4~#F7W@/B`[PTF 0\L3سյ}0oVL+D1’7R: 6h|U 0m@q\âlV)>8U:/YE0P4xK`trNBŶ{{I̤ie!EKԝe=+BA*09O0]7@DQ9H͚@ML `*ga@SpDe=buXlp89_TJ&kZ7~g6.}xl?1Q:]H_~{_*ti(hx^*-Zn{S[voJR;Dx-sz7|_dNsNYY hgRG ]p'wJ2S fT+Vn2mA4Mٍcv R.a硅5z6ˌ|=+ u"k0"-0"93)ڦ`Ȇ3}Tjr1C,`0ѓ´7: &ǦF"o=}q;*{tO mOt"0*zj!xK͟zxeV||oIi>QOei))-j-JJi ]FŢѣ ^ d  vMѴy_euzP֤#Q5 E9WyO+=C0?|O[YYy޽[^ozL[[åh:tYYݴ-cXQ(}jSYCt̚k},Y8s5 RXѡ.EQT,QABi${$3y 9q-]qղWT@(ur$pXp׮g}^}i} 7o|>xȎ&]~t>9vif(^-z)TL()ۂPZrd76b'ԪtÝxr{:m:\Q>K*2쮈}GS  bql-[aAR`zs I(\Ex*Z@gAoQMMp5$ ْ! %OU8}E _РCY?ΒemѶ#pѧȬK6P]vpl܅\WE-e)͓g.Qh]$-O9w3/5zyCm"Va ҏ?>Wd ةeAl@)U843<ؿ*H%.$;@T#PQUu̺O֎ki6}oj8^B_ 7}fݺMPu#7lISsKEYՁc{_]2w Ȥi#ɔ/өQ&xVV^ul2$̣|,c4UIn7j϶|o.n?w}Ą;{: )ͥSgzOYp[njmmC_WKˬKК =t:]Q^5qSL>}:*StMSTSzz>[>?+o޶-R_omΞ3Mfw_O<ǷxyRs^|E-cw9{x4yO=kڞS'wc[N>ΟǞmk7^+.ZM0%:z;6J!iuJeFDw /#,0W7t Pt淚ZB?+pb&Cm7|/).t}oΜ3gY}&{B!,C_B԰qsTZXv1ĝ$RG,yz 8`dR$/:'pEE0?枻n.Oe۷mwL/ gCLF`JoUOzmeV/-J.iyJW#0z:>S}Υ(*䋞 ߳M6PQ ͑JZbE! vt2H,?,p)=|)r\T0Rl4:L9* TØ S, F|<1uNro0Ke%$:`,PrEy`On涋T^7x>cNrKtXk{WoώkJ|Z!Gﮮ)9hֽ'OfGy(2 ,ʀ-h8% :HRC#t0Gێ9 bIbT ‚/öOx(z2ꖙt/} ーpv1gDeXEz,S)6 <ӗ jL8ya;>6gjYXt,騬`:j"Z3۰9TrpqQt̚Sq ,iasf|,hNj9Qj*Yr;E-=50iK̒ty7Y Z_?o}:q7/"9^eB;w@\> :f2):W^{}Ysz~ꭢΚ5:w۽A'sox[?DxiU.l.ڸ-~Gɓ Mͷپ5Tё| ϛ1}`gOP:v1=,+ Hhr/kKz_ =&a_҅T O@GA&C&u\HqY + x=$(-h͆[èV.6T@  //ydú\}}y$a9xzAc Q7M +'%K"k)Ѽ+۲@>ox(t! ZT< XਨǩĪ,#zd.IH0}pmgL !Ѷ{B(%iD ^TĒLiƲ->?p!=B.>5 Ph֌|.5YX@.TCf"9HsV3WTVK+lߓCCܪZPjGbp<1U;⣇l\ S04DEӧˤTWJ8|˜XTrQd&g}%)3pUYKiHEM ieX]sOmh6_8oDvϧ2:ʮs c!~AokEWg9`o 7&DWhsH˽>.SNѺiƹwܺKMcfN۵#'t:Cx4ͥ Oj3{T'p8ZSY Rɔ r|.8v.ZR3|iQc-%& :=8u/}"zL4;{+$KI5,)PU)>ky%=>Q̧(T֗ c)%>m;d;SɑꊎE -[dw[c˾_Yoڴ1i`:n.;?zӍ7\UIU?ڿ(z|KoH#3:~}@!;ʢ񶦶 's6Ą @ G-L+\ST gEҙce\EIa*/x0n!ˮ AO 8Es7e8HcFi!qni3gnS'N6N0Gq 9ד\W\]RC`% (o*oCD!*өv0`9-BNKS\"6F)狪Rfm@aphzYwʤGU*l`7-̀*eY%C!ǤCz@s@#ZZ$F& 矨.E'X9 :\6Fa A`/zX<,L2F^H sa-Ox٤  S5}d=#AIdt!>tH Q2Sly@[ŌBLu>}-%=˳l(xk;OBtr|*tՏ JغS1̹`kIUeu3Ôj*jcJ*.GUW cww7;Z||oDͤ=d?7|{ە |A(8b㠴 czR%N`; ]d:X,Q<\`@f kh 4hзs?) EBuVL, "ӦCgFz-c]+kpLn9{ˮ][/:1,"Up͉A;e'sg/#?5sj JVuk Z70044?ҙUn9fY՗Ikr~c)6*abu,JF5@VL5XT X['5 9)Rz?=G.=kֵ66,23z7Wݾtŗ??A A?-Nv> UVTҁH%ӼY`&X,_+t_ H=#,JQ Sq΍8,7~|eb5mãT:HTN+2-UU MVMzl@()͛oܰ~՚=.xy˗il⺦?o;N嗿.j9|Z/o3vס>[O;>iLOwwUe=#d<5]s  sT]U<2:yO'>gѲV Ru2(M8j- m'3;mPe!!f-wc H5eF<JHH^OĂjaA[R.jB蚹\YYE^޻egI<\%\dULɳsI:EPMpK4t`JJ~"8O숎-u52SR>T]. i i]a&NlLFYՈa؊k@vdg>`XD^v3Ђ <5z( nFQ*1$&]+hsPd$䢢b>!l.6W!KMWh,uW^ ЩrݼGe bw .*5D%}2 jxA/U1k)ꉲ3'wuQ]K,fR`ny PJ8l߶m96q]T6;4O铲~mcŢ.7lwuL߱c&)b~ua*a,8C-oڰvٯ++?~Ozw߹KHkB Gi@~H%C!'!-(n=(y`99Ӆ2Vțroa+c:aи;!or k3\8U6Rdc=|]MY4V똱 vOkOޯ)?m?xŤ3}}':Tܐ>qdP^0}Lyv;jxgYHx%ڒJ'+szEu:AwҹEh9Ȼ2B{ʞEV/)Qؑx_ܿ@lZt1dvc6D32]ρ ˅B^`یs+\Gx華ށxM݁=IM\~O=Vn MEX B.N81Kh$w=qi3wwK>ZRcRTR2)P#뾁~(l.BL"eQxNJi ^" F xyKpl>ݛ?lMvl>;x:O,GN:ZL ţ͢ʲ: L l/c<HX%gh/Rޘi{9 DY_f͵Hv@M ]RM+bP Eke_ OEˌgt\Wbes`T簧T$mmr`7PZkb1  @ָ+"F%t,=-B~L[{'³AZ iM_M07}+_`{rOԔլ%S..=-C#}ۦT\jشM !9][/fŧO2Tds 1)bhˬ\GCQ)dQ*md; Ɂp,!ˡ ,4 " $=,4`SfUUTWUB?G_yȱuc;uV\"Lv$GԈ G)0orᚇS=i d.kb@>i 2ڧz6551@+$0 \@a]  hIñ`8 i Y>KRbr t<79n#$,NŢV#O%2*WX)ׅUU"/1ReV`H}Ճ rQ$BX{K~7 }u?]5]K./نFR0Ze.flMWe27-Ӳ #߅O*0xVcA|Ӈ0zp.KltSMm'0U 3]j&}K􈒞l5gN$O%m>#4"mOp='KFxRTX? kC Rd>O£A,yEhJ>(=  -2k;):RT >O:zto?^x}5կ_G?x|ymm?[zJGT['Btǎ~iW^g_x!^[^/+ 屐Lg]v3EW7_p)}QԒsR[лb!ZL=t@k%hE4-E*<(pbm%Qx9j8d }x+CB=Z&tlnXb*Yĝ["T :lN^ZFPZtIRm& 3^Hq-]j Ih $MaI;0\b.9r{ 8bĢ _8`t10M]Ը@ء9 ;oNP Q=D]E/4 ѡ& *J(RP*):V=1 | ؊NS,|ًF*6AmJhItJUA H%F@)xyvAU؞Qق:F]2 NNUͣ\V*dG+*l.9ȓŠ/:v_k;?rmmyR]}KUs[kdzYeEEoq3sӧFD#x~Kxg{ß77 5ի>p%Kϯi?~ɒ O5gf.>mԎikTE?<+(zB0 ;,zٮMgOUm-e[o o #i.r"ӚB\:(E~*my`n-\m~dI皁, hU ÄpT׺?|?TUWzۭݽ]d6Cϟy@udEF??v:3eB\״l6λ5߼mǮ\:7<ƌ;v͟tWf$yō_x߯Sh^ry#Qu)+7:~FS"eq0$CXvƊf0EE]K P W5JR!p Ȏ!̀k:;Jh=#A0St}7/E5%`:kZ@;ӥX[04CQL y/ k NށVk2S Pt $φa!C. =2C|==BEt ỉMC$BxbyeeG^~_u߽Ğ=;-p"x^"ZJeL+[]Y{Ƈ?y5WM阫=P84O:uGƹs.3ACK%> 5扮ͦBofH,;'yLK(^#CF;agK@EOܓ`QI 0i L%]CII:";c05-'ƪTK47&k[:mFYGʙUwg]u‰2BX<\G 5?rz{oV6S-=[QiilN['OMg2uhnr$"i%f\GbU7  Iģ"hȜK:L;!ֳ $@8{VO86za׾;v9UU\.ZVVWP+0aU0 {Xe zB dT UIQW0UUrwcǎ=?[q_X:y\Dŋ}EDh.;_bL?YǨq]*7 <$al+S݁!TVV54G"u>zLJoߪ_K_}%+V74=wuƦi#7|2}lw¥T۸i,>}^Bc[f.?5c:A] ꚞ+r\؞gd]eo\}xaK0%Tº{ejñpO@{C(5p(FЋ "z( ?p`Ʒ(74JB-d_Bz#ь&F;s7҂(a*!"aH0Ԙ%j\rsCǶ6L0i}?2pi3!p R*R1CI$MZsY)xQ"/ |E$)%3G/Bfg5qLa瀛nfEU [v(~u3MrFXfCg}(Jpa`aOVрB[ E*}FJة.˄Ub=%) C]AveV $`;gDCLئ&Jd Y5>PdcVB D/Ңcg#a)ƀ ̧fؚOǣ(UbUի֌O_sZ12<Еt*/dp~=y93l[( %Ja#FX<oa)iҤy7xy%vA) Y `<`j7SIeL<]Ix*MGpXgP%n0llnwgM/<|Ϗ5ނeY~n' rigqpQ,8}hǂ2@c,pdYe^XI`ʦ!(j1IWVWG+ RX3!4ҡQJ5hMQB! A+d y*1<_ϥSȪk"Ba,Q|WAա53yH# 5" d *Eh%Lpj@I0BiL܆<8{T*t,7tfLh͌-` fuUu9*FBIm;d&O='xdt4c"|:*/]߼cԱ&FRXY]M;1,1HJرeJ++;M<&PɎ/h*JF8ꚚBxqou̙ sL3K]l[NAf_Dwڂ8G{8@U'ɪ>:"FAT 2G+RuKXtXJa! )gÖ#,D_E3_|}ov;narTikxsW wg avp`е]#‰0hяUƢeQ k1#|d ' `3%U1%g.|WǴM<53:Y z[h |d)ZEy6ܔ*\$˓=_??yhVw$GGN4YE̞qVٓE9)'j{J焎dL٠|?P[X- -ؔ9 {0-U&D!P@(Z:۹y˖D"NbQK7 xc9V p‘L3Hq]S, Gl0`_eàpqrMPWdPw Mz6T*@vCY@ _҅m-)FE\U1.ԷMho3rv!ٖ$hY5(NVW3fhd0)'lH$r(ݻDa-(ή|ʢB#[H)˯zƯ|#hd],,+/WkzϜliMmP>NTTru>VM?<$WTuw|ȢIo\sOm~//|kphڌI`U.!l`ˌ lyPۇ&*B+lo_K65}\T/9hɂ4سNҁZczF0H% -,⹁SfBsmm Z"UhyYT3AT.?gٖ;EM-C;vY)VDHEiԫjj"*+#pclh\Wmz]7XʶyEcʪ|@ĥbiE~WXn//3jE߻S/↢7Ou <{̹ jRA3c9v*REb)_(QI=mm[6mo'*zHWqĒ9"h%ήĝ:P9iwɸ))HBqVPoiZ1R*v}?]_r3O=MUQLs~#^zG=oa"΍WџsOBq_}=Zz{jj⡁ӧjњڽv^7:ȉ#T,X0' 92c΢+.CΞ|/ gN1LqrIS% L !M#נG[-lzXIBy%xmUTcv[yhk0Z>l#cS;FFF7yʌD4627 #E#1I΃ԃ8j̡ұTA/ *X X]24%>"BjtB}øEvL;ywqlo京/8|̍V&- 3g^z|}U/|'#iV%l1=޳,=iڬpb4'ʋ+ٽ+3vlO?6v섉]u}ss?Gn Fo|͍㛚&N=40o 5FL)CX SkZS=iC1_tٳqe*ZeB+D$[*%B@-r y Q Cm Y9&RQI/u՞e+# ([.j*KTW8uK23ģZ_W_șCɞ޻woVSU5Q]̛WQjUy6zV0lEŕ6f^i %D/mXapGDFĐu=##۵o{쓍Ot ?}_}Mkqk/׿* sgMCnݵȾ-?{@ܛ7@? Ԕcl{]Ӧ̘:XyléC#5S&Oj1~LZ[]rpzM_|?Yٜyxt!5- =XB!mAQk Y=qԫ^޳i/.Zk֝۶̞=ѣF2}/R!j2t_B){۞mGD??e;;/vi-v?DX1H]m0 jYø Wƚ'zXRWrT,߹w A#cUMx %ّP,! ,Rs(Hxݩ ,P$T>+ ]'j}$"(]Q.icwmutM3"e'K,TxLퟋ<\P B|C2sA=MWZthF,L!@,!pL0}Z"*HKGNQaTH}%.|0} aLItI7EW,2q bʗ_N4]*k"mlv2S#CXm{f<B XE r@dxiieXc"|W( 1;y1J'H_=H}՟.Yi_VdHە<*:< ChŏP8o)=]6:r쥿0΂9n~0!(\B0ǰ+gcRr_޻^yi}S'~:ۋ5 ]wEZy͗?w{YV^O&[ O9z%Gvi#Sf4n k"CVyLy}7TU^Ѓu̝1cv>ᎋM'P:2<'q'~+ROiUUm([[4f^^x ΅.Q0%PVPwgfLYR}B|O̙hKmcjVzy BT[&AL=`xvN%DLQl(,t)rW|-@[vT\9Kx(ھeSq ,@ק]:Sö!JXRd7܉ƥYxnRBPys;s1I8o٢s']x9psշ?k/*X%X@YC]x^mmu׼}_=#=Z1qç6kEl\%_i=uA& %AjiTiy rAV\ك kRج *R=[)ɷ*FW.QC7}UQM mknI"EFO ~d%p0WA4t=.bUyۑCtۥ蛐X(5QYu4ylv(ұc 0|@3 y'&B"E- 83CMJP#;}NUQba}_< 4g>ڳw(kkX CT# hUy0#Ƣr]֭p|~놊*WXZ%[ x=! d40*Ř bQP;m*z헞}gyW?vry3f%J7@X/~+_948v߷y][S]xѬ|*Y3g<8ey;iYh.yK.JU?q8LjkZƷ6ko4u\[uBl!JfRBŌa+W_8o]CYK#b@vшioRk_z󖷶G"!dA+T`XהPgwkk㕷]w#8(:S[TWNns>ɇ Κ;`f0 "Y`P@T,0MعP>jW-GQʑfdP܅Wؾo45kq}{vww5[*#YS;o+˪6W[ i4Va7uEUi&˃j*j(QɊ&tJb.<#}~ &tRҊ>ښ/*xfe{B3 k1 ˇ&DY*mh8Al2M&)2/ljǫDž(=Aگt)A*X@ ۤ$h,2[dmzd)Z5fJ:A9BhN(:Ndn4q' "X7b>ۣ+'冹D9EE*gZnhӦu̜?yu>ġ]G*k4k(c 2r¢<^}߭|`cfe;}eA1ڛL+] ݷ|+?z ]=5N?}R8Z0pNÛ Іr ̽|[=$2i w+a<vpϹ,u+YN kX6RLE;UuwI!JA+o[j"h$mP*B*^їH`FSB> $8V'f9Z*r[ ]_8j2Ԥ.F$ ݺho|#'M իkێ)8>aGnEm.4 :&#qKm"jɄ㛎RǬL{zXhH,\:?i+j*zEJHumM7l;',_L[>}{` FRL(GyyVw<҅(rJVΎ}[/~_q5#'z͚==} =fԦW^zu=K.֔LVSbc`YB63Žez^Яt8._W|6-ұNyd8\{ {&LVy19,Y-LG KBR ?mbU0BG-|,Cf;.XAj]!rFm,}t['[Uͤ+eoq5">NN85(5Ss*jH(򠿣$HԀߣ9f2aH0wTsG c}xMHsvp_d,|} }w=~ts/*4Wotf g|$E6^׮[jX=zCΐ@( `؁`*#ҋ.&iCWkZʠSwj$'x9=6zOߣP|G>tt(ڱߦdc⫯*_HmեBJlي;9+rW[vpΦS*^W};/k?Y/ [^nKm|od:|mr,"tcԏ؊c S_O9CWPMΥV^'ϴ=tD^P1McؙH%.2n'˕9捜>BTTf-_7Tc'L65#kw5]Ə||޲Cמ}W^#`!Jىt M$6𔕂ߗ,8?-O}մ\ /|Ӈ~F|ٶܬVsd,۔k[#  ϖsQy J< {0MĘSKQd= &P1Jib%Xԗlac:QO5Pwlݰq]A}*u:,T ])jCI(*pN% f_{.H{4xT{Mu-l&T)xe- k9&:tΩXR UK BQQU ŕ$CwmGljfVͦԘV}NJym6&&КɆk{OmTٮ9R*0M H`˖d6Z#l%@wFNG#Bt.~PʩΡJ5>[iFBsAcTԄ~e鐍f٫E h,Sy'|"%2dsq;j-`ږ(yF"79Q=ݳ'O=h՜~KTr'K|1Pl,LxR)a:L6jʼnƼ5|$" %c|AA[sb?, bE1 sHZNTGpǗ! ie .kdCW{iy7~wtu;oLJ-୷ld[_W/ŪT Q9᷊1*7sCVE^>pLצWdꛛSt$\mj~{qe765EuƋΟ9{÷NMLTGwy;7mJ|>ӟ癁S/_PC981}uPI/u-l{gn7 Ŗ֮.F[r+9k^32\32<uRlU9]Yj莨J\2khI n.IZ/?+.Yz,]$3Jҁ޼*LCka}sg϶UP j'LKfu~{,Ǜ=7'ZDEjnݲnÆx 7nh*!T$aiʢ6$&@VXJOgZCCѓvn)knhmi;AS!/UM o}>_kNEb}8ig2b[ɰRp\E߆~ͬdӎeyjqbGKӼ9l`*QJoxSҭJTp3#|Kz;6gJ.Y9;c,Moz7%rl<6K_~mYd{iW]g朓olxue[T> Mm2(b.X ,&;zt11f?Z|]jUeä#7d Tءz u̕Of2T9\ߴ3%L<+@) sT-ыҹzl0jwfxo3T֨p5֯_vK ,pqccswgwqb =z>!=FTgv\2ͪ"ȉTH猢"6ImLg4gqY 0q2cO#AGoμԤQSc-tX# D #՝ y*RL"A}~8u]VP y677[,x1Y>f$E\m@呸X#s|ϯUhQ/zEՑaj-K}ޅW⩩byJev}F3Ef:'' 0RIq#p`X=Ibmƴ8#: sW_z:L'؄r9t!PЍ7V9oid`)҅W6tlE #JҎAebH6%YHmi#C2I=T Nd*}JM{ 'Ȣ%dTon%UZ:۳* LTS#b*~ṇw_]s3Ot޴y 莙]/xo.QZQup. F>-8rМٸ­{|xkNͦ&3d }Co':+J@o_Dz(ˆ瘠/H׃ XQk0E 9A pT9 C lUҷ=; S=֍.LIvScCCBb zrIV2O;;uwٛ7L$J̙6И%Ɵ~_~}㟼yǻٳ_zg^YgOm=-?_1sކΚ۵xKcqOfK6\@={AAl TC  DϨB8I)#cZH&C`%aCtY7oBci l`}f$f0TޝojZjXi|-֮={h}=CS䞷{r*y[wtJVy|)oKNM&;oFLl P76ʫ{۽i֞Ȉ;ǂ]0l*SSc.r\z52:aJ7jJìޅ^wU^d;5EYK};2 ] ;lp@^bR2 <@vj(u(VMz׶I>L"pI V#D֧q$:I^M`׺aHu豞lg א(=|D: ':6DϮvJձG>a"(iHb0Cbb 8^k (˜ J, Aզ4mOut7 -&3NXh[u-m&ElpM~e=sNwJIH3lCcS{wl 5I3Gl\V*&5K;o'3_wM_j6_|RuuW]ZbGo{cs}?V]H',(z\,b@ \)5PurBQQRV4lapL(\t`3#^D׀]NwpQ%pz e?187B]ȓI*^So44{]N JҩaTNՕm}jv(kɴ&#S~mR3߷_s]==a߷[73:8^PΤ"ߤ¡RDΦ n*wP_[tx4g:&SV]V,b5s͹ 44LNL&z鳗W8,p{&IjB-nϮذ~y[?r#7m**\snDj@3NQI'i3cO>|.=g0:g1ʫNhYV>esi-~$pA(!4۲tL)vW /0V%0irRjRG4 VgbD gmW錪l!~Ā?^.UE v)fRuE$MQC R`C Nw|e2PUV4 MGɋ_OiRoT&ñO,=JikxgLg%SyU[KOo44T3$ˮ/NtZn똕5Jv=IWS>z㌖?*ݽm+/tWYtun+o==>pfىK]aZ{WoX\lEʼnl4,1+E9bG$l`Ut0a9я'.^n=ZU3NKc# tuз3XYR)0>qmkrb|-~3pf.ZҙNe]JH}\aUa!gYjSQ5*%[Y`Q Yxr@$a;e(KSCwB Gveð5 M+/ݹk@?e(mZ:HV%"`1H[(]7GTѠYX{siT ~M-C%OvOяCײK#J8IP\jJVAoyT*Lkf0U JZN/3GhG_EҐSQBvDJHNFU)'N kl5X~5˦wϿ}K_&dYszW/ױ`ƪ+B!JgRӧ]޸eke+ZESChnF|8c(7f*xN|8AњUCb}I%&CR1jK SXH (%NIϧJ< [`5AMsM WYՔСzi*\,&zgLkOq&y- O/T>yxc'7#2( c҉斺f)W1:T.5?wn霫 j)1хAf"LlgRd$HWqGċ pbOn zlMe-fh!OH>h%yzϜ񽻿w[~iwdܠ\O}K+Wn:sj Ϛ;64NV:-;i SI?`BC]Ba FxDM]Ɔ|Q<@W7Ҩ ׅZ$ia=C*R&eXNkct(5dw$]9^cI]v@|zD8rBcy$j QAD!ha %; 9 0D-A'ѪZTuҚRrF_?4kPQk M F[Ӽ=/ŦM9zo'-Ug24l u˄yr&Q'N ;Uk/#>qdA MN|ʛT>ygW] oj z߿g~zxoشa횖Kw􍜙pLSM\5uSvX7 AXݓf\+vPôբqQ y1ҙsC su`p^qtLgqD˪NАw 6u̶&,W {"u"Q=) ]x|S!<E5v Ӊ.Ih1ppYfo>& 1=bL sc0=kŒAЁ .tDCګopޕ#jpkcoGWWK}d(ϜӉtږ;ѳLD hP-?HeoWPYA#+}{! Ҽi=E7ܸrM/jb]K Ezz2IExUpiM)'C^|tӟ^{.bY=iQ"AJۆdrzVvteU4QƆTbdbL`Ge%ꀨ)2 Z @)4"%|mEY\bK|9~&q,2H8uz2wڬZjy`~E]:Tknن'Yu(G)sd2`g\,SR")";锦 jA,"_1U .':td!QgvxnUv ;G|>uv$=:=&bXYqe>-e߉쉉}<55=Eiđ^9thx[=%HMvG*6siN)c1v`&U,+Lr^d?ZB7D!Q y6bP D&ijn=[׉b;YՊt #xP ^ *ȣ Kf'<";b$͍mSǽ+'tL`XX>7_95+zbtCQh-3,:|`,JgvA :p,a&rZCu"x4ޱ*mmZla!Q(ԽVQv %* h4LY[y <ؑa@+t]nhUlhF[weg{gǫ'=UmioOlذqݺMI2*ۺ^|ɟ-K陗DS VY' =3V̝/~뮯4#Kpǫgvq#o\E1J1ejl,g|e&]3N݋\>uwD}iJH쇘OOY}r!sQ:D.Z#+ ,M2T28G<{ Ji@9b 5xbn.X<'3/C'b*"'(U bRho_v۷oelf2m ZkaP[ Iqdtrrx1lWkãu⍗C_|e.֪PVD{;&AC>h SIQJi z]kIяbŏ5O߱Cxe^$m&SbqBuy/),(L~LF쇀Ž2.Ȩ(LdP ][k;oʧ_~ZIEFdJo|#(Al5|LI(hau)PeHH)=6TGHQ=v~'GUK x˔%D#-y+e3I(QaR 7- E[-y U(pou?C~e;wYee_n5gn6ݨ᳣&e-ET=9=,B-C| tP@Jzr-GG]c#Quŷ=_E2DHOaF#Gɀ=aMiɗ D8gq$2&i.Br,-I-W m /: bj*@m7N7XaUZARz*;o_tCCC)AY%5]'G,6=h T3>hTf­*Y9 | x%&+ 5;H Q\e^6ķxrk¦ FQ&@UbIB/E1:,3O?{H+;{j ā-H$2A緿.?wxxh(_ޞknF.ol_jnW짿Br{$RKf/kwg l,]QTH.T.N"i/G5c WO e? c *!,O.`&=Y ֣R0 ` @CWA߄ 4QRc< ehzb5u Z%TL&KAux`?u?n^0U.645_6˽3l08t {:''&}ٯv)3~M4<_/-4K@誚jˬUʫ6mlynPgobQ<@g@jN/o[SIe8T2rr]QswcO1tI V =sKOAy/!λ@ic*Ƥr =/$X a;JXhp|]VE^">X+Dro66ETS)B:6IqϠ/ĖOؼQk^8 SCʀ.\0u$CUN!Cg4jdR1 "czө5+'sf>\ $X-QE2$.0"O|ۡ󉓬^˜2dnjq6" f*D=:xߞ7'TNP4 shϾ+NU#Q$1 +glpT?zӿ} w5Mөى|-~5lZeެu*geiF&bywl@'AR7B8L`΋$DW/&tjB8F)DŽ@XB5jm gc[t9ȃ2 O2 MLe(l1ëRO1tՀ@1K.U2, j>Kg\e-A;:+{ }PY97I9vq[ZjW}]CBItd7G:=_,u"c/2.;#V+b7;n<m1WBQ5cX0C3 {`9fS*fJ) ^t}ۻ}?wO}Y۩r׿~]wVǎ<0o" Io=qƖo;s/^h׾́dƠ߻|QD|7Ws#Ϲӟ8M BU1 pr\ӱ 9XD#'x>Sqgmp.jFPŊ3]10̲g,e$Ȭ #z / k6)E[t0=6i`[we:{fL(j}7nްtrMC#Ru7^zfjpL}]TbHxQٻ=vjYf9o^7@ Ƈ5{M۱j٩ZGPՄAHT AZSWȼ x7c0E(=(nc' #([̸PeG ̨p@vTB۷wtr"+aÌ%XS}T"2-W D$Y4%#T")r Si ,ٮ`ߣk5]oF݉ȜCyIr *Jً"TS] ]7K%0L^Ka&^LfC1T!8>1Qk= TAWGeRF-V;o(W(NΨ)qͼKW,c׻~vr?r(xt&&6cW[nҋ7s.'FFOUKrT.@ssymG̨ϭ195g:@S`e#VRY ipSAYf ĝ|?;s2k@Uzj\ `ISP l( (\DcUVP b"MHU61,Y޸AN<=Iv2EWJ{ퟪN^ Ud]&r>k+S25(Hu{pZrYkgM bgQ@t \3PaF Aa_'+a.&ngV_b7G(rS(m,J+2O7,0*٤I47gx"{O_<ԳCK-W/w}a5cc#ُ_~汑3'~pѧ[0UIe̟k~"?}?mWP-秞eW6o\t_t᮷_1sJg2k׭[n;ofk--a WK_tm\LScڔ(N 0L85c"S(pe$1lz(HH>{&t!K[V4]kCR ǃcUP 3pGO9 PRvj @{;ܽ]6o-?߽dޯn(T*g[z}nEK-,w[kÿ~pgned+RCEj|{۹湳FwriSGCUVq/5_pS 1Ϝ?X`Z8#2'@LU0otzFBfo]'`4T*]-dELS169ϨS\&:$fNC.(R(&5*MMԏ]z#lVVtD"z` E=}ddž1TR>LV/Ё15IhaY.] ҄:IMW%5X/bv6Ih)0bXd*HbHZM:M7A+؛vD*gǣ k hvTUҪACAG,K?5'7öKV.k7wzx|u EnXqՌK]g| nIhd .g3YqS}}blԩ91 # fƠͱ(bDfL_۴a{wx_GkY]lnlZ<14ژ;GO$S%^;:bS'[Ztۆ*b?qgA*O uigcPgIm$Rҍ\N5#1N D0U$j|{{޽`ή ## X3JU +.gJ Pؠ2YQ!JmoU%≿<šGDUޮ8>xyN٭[7Y]?³:Ӵӥ7uz8|HZM/w8^>o[ -kml&mq(~n֪uٺbeNYc 70)745 2Qk:=^y!ˇryiϷ:;)"H d 9aEv]ˇ\A"%wtEס(Tȏ'5x|8F9zђ˞z9[eE4]Uԁ(d}qdRϜ;~UU"ǍlC`dqaWJЛO+/Ki5yMWʫف=9;Y.ѷ.V*3c.y-C׼="^g} йaP!6Dq!qOu0V;8p A6l90=-87C@ UaUVo <hRzD]/{SIXx51)@e:fh))ET=XT}2zn%_ *&t4~b▀؜d$}5 06ulthަ|s3kaŚj=_rOnش=A0FHcvX`4y0BC`g` 3ƥe+h2n1&- 6; ,hb$9\C*`#u|wOw&=qS=rw?Wx>P?o~sUӜ*4]jӟOxѢ޽%W_gU>ΝT|K.ؤ͒R~[K{ߵ_1/D|[.jhn5wv42tVKf:>:K tU ܚ"Ůe]1p3PI) txjUc{?#GRn$rМ3~*N8#v0! !H~8FCTgN>u]g{KWohh U1K̦ڱc{{\m[o ^ϟ~?@<XogǢ%v4eJ]2_kгr*"n]aJƏ9ED:DR*h:NL2ɌCq`ixk A~PLwBiL22:,6AUW 5k8TEt );E'Ҕ pw%[N7v#ZZK2zV.oTZht>1H,uQ0L_t+~2+>a;U9z}Ψ9xf\KÀNݞwMdRyz+9s^M߳5,^0{WőP\Na —I<||4`pd~a$ ojXЂexևGb/Zw& |gufs aꆆCa}sf߾ˇGGm]mLMMfZ}Ͽ?9?9~00xf嚥ų߳yց3g}gWoόd"wg>uuYt1hmoشyL|8(d'sizϣCCEMcsʱ]:64Lʆ\CƂ{&U-m$:91a΋O#{߸{oɴ,!rQ3>D@Ul7C 0SV4-K5pjfŋ-Z$VgFkSS% s}cԄ:)xvykhW5k׾e7̙fn[S>v:˶Ji:vKRo7:Oʅ]>Cˤ$ cpOPHao)n1!h M:"Լ 0ǦM!gO\:s(}ZǮ-m]/`LV b9 \BVCALJ\tbyX_lTx3l <#l>"%ߎhV|}r4=J :":^-葤`zjdw)-Dj#+EfN;ZUK)DeX.SRF3זFb0/˴<*+R$O"-hC8eY>и?GI E5bBϥJWS׊E*餏W fN<~dV,`E8F;Ã3|Ətw8u2Dj^w?/~cy=+sKbWV̤%BV&BN3YJH @yB5E:f鳣F^3;{^yG;tcCSf;^坯;xޅtI۬ k~ U,EȲ؀k=y ䷟ yT7NJ֊l nbPP^>s.Wc'ڛU'k^o鸇1J,ڳJ֥m^7?s^ܪZ8^ QvMmbԄ]XDU"8]D*onR D llJG3Z!+˱, 5lk,S b˔&Q8z R3Lk ETܡjF4@=<Ӊg9r.E1GDnyA.h@=lBy,Yҳϖ\< Mj @Ao 6XD ăà U<BMVre)L9*+2.rc㓇\j@]ԎX?\.O+tץy˥Ӄák2ucS#c#ҳ1q5bPV$) 8zP;,aQLNv\GG';dvRQLb2>ݒA'TZ)ѡ@~N8&]C5]h345Zڊ׼*ɖ=g'qؐmWI$pũj\5AB_JY >j%2>\~皻M}\]Sb829>.2҂csTUE;c,+Q ZK򽡓L@Qʐ+}#ӓ3䤒N2 *RI艊5JWyΜ_7Y|tɬJd5^sU'&3cGOpfT{9 ^v`Uz;mL sE&&ǩBwo7kT!7r'Fo675<|>_719Z,Qiz0HS q/۵3߈0 s( }VKYQ9^Oz%3X=sNlz?w'/U?O| W^wMKKg`~CK!MK.o9cuHf.)3^cY2'OzŶJb*Ȗ`32ժt]UN͡nÓN:|gՒ9s]W !TU+ ,YtΝ:ywR٩.;8})q/B ?IY4}wrڞ,*cMt$7~s5 "HM:,S|93_oغi#&MR.r!b skݪc@rW}3t= :q!׆b h(oPW1G+S@,d'Pq5q@h`[b`X7LJڙE 8kӱ Hl.K/{wHbMHaGvAu!|Qc3!]C[}+U46$ Ӳ}quY =z|LV~?L<_5r$==,Xy5mleW9}jZ&N4ql:.?|F4B/I̘1q\cվ]ϜvnEkBzt̘;'6uA݈1:SI3nwwurzaJ,;MsgTфmak1x5~E%ѐ%S.YJgýFO,Gu?mkYlmW__~ꁾ~0f-~"e㕉qt,J'5SSM?;]vqc r} A 'n)UIGxOƵϿ/Θ7kyQLMqQcF<[oo?nE >|ptC5Y63i흇N-^8{UW=__:mAszԿR MU}|_ <`KaIzH _mI9`Z (B0DCͤ}E:-PLD5!;nȬ i XG{P0Cb,`J!6$G I};HfoHQ1Sп68)7?;ԄpT?-MI;upkozŕr GqUUtEqpp,R[{Qd`>0LҁM7O=kӧPX ,jXBz p;s~y ߽teLel %)|e<ƍw}ѣ~󑧖j_zq ]I;7i9t 0_aS͢ZEί!(8u墱$ []2uݢnLUtѤzz*-ٝ>v`i 0}P6B~AS2}*A$jEO /pw,!rm=6F\qE=fl-:xtۖ|w^7yrgwg>rlI^ AL՚+تmdUbk*uM_]ϖtAA. ,e0nDMp*8*֚Aщ5 MΰE"歮(@o\E2`4; Tx@՞X)TC9o(%Rc/ <^͡k4GS/cحϛY3… z0X ݹ+=ؾe3O=??'ؾoĩSz:>b-v T:=44Ԛ57?>yӧ>~c/},6M13;6U7cljz׎=5mX+_IJn(swl}_`+߼o87">gܮEC5D].W纺"MQ4M4TT$3PjVW]e{]-) /4nXOΝM?|VYMZWU,Q7e*{w*Jg srA, jk/_^[Exn,*'RIQS'X}3.lmטN?S@OHjvڱmǮ\2rdȶnv@&LulmYstg>P?0h#ZZJy_f͜340)W(}MW#`-,CJӻAbeėXcPET.&F9c~G0g"HQ6T* ( Vi "y}Ws'VB%1VA4Cm F2 R{Uw^}}ǞZ-`''4Qw:Tv% %h;65>0 <\BzKU(cQi)]n2YC a})p|j l  Me:e͡\mg;oRfwPɲj`ٽmYt6 RVtհpL ԖŠcb^ϥѥ'F*]Bq^Bn ɉpIm r .9_QO1{ONٌHS+ E7vCR\UҸX3 M E8sܫ/C|GZ!e.]ښS.' ] H5l&h2X$PAalbg%g2q4 o$E3aH ^V@Xp$fzU|x HLg@t\hFopQˊU-s#abm,d ̘ fG<Ɖk+7lK\)G ;ߓd(*÷ZX8D:TCx_{1iρa'ZaDm='Nz{wTo{ᆷJU\j:b:n\?=<[>>y}/ZgW㸷r]@i'ap0kL3{7~PwBةΞxμ7 &f*qf>C_PX0Yɱ\[L\dz]OlݸܙX>v U {1d@K[[JK9!B_jL7>dHnر]ϼnݤg΢H&W^{s[O6KzIϘ1sZ.b P+Q=vܯg?z!Oa1b@}ҳ{S[LJ>LEc]؈ywĘc zgctVBF@"XvPX`Qo"0 蟊"2jDId4H*&EeR%]5Ǣi-=ȫz:9} Vq_/ZJ%j(0DbEum@A#FSwAXb-K/ Tm ؅"ˎb: дEbG*3@Gl""q̋`|L٠3b ; J/ IY2a(TDn#/C-*%dwa@BP0W7/}˖}g-X|wlUbIa2"#]vׁ#[+/ɛ/?+UWΟ>uݚ[{sFj5IóG5Us,'̸zDh{==p^ۃH%v?L0ib>d*LCe(%%!T&V||tg>ӟ?hL;}=K >燗XfE*}JiWXs}:[c*mQh6T8N\N qˊrIw\c& c?EJg2}]^}u΂gsvсR&Ó( ".ZUu|q-w}ju*8L>c'545 våʍ7@=օgv1jTv5U6w%F8a%R[[mJ9v.r( Tz1 LU'HOnmH#-p,،iy3S&S(e+n*MPqv's(Ƅ1 #Φ,Q RX`D;&WJl!.57 :4fi2^)P' ?fJҡ:vP^2@tBG pm aDY:#5){#R{f ^&[EgҳmhG~T:kȺCA3ia+zv` bui;Ȃ ,&M`  ~%W ˒$ւT?zsYC1cN: {[ L-Eۢ0x6zegXL%хLQ&(jRiEe2i -w=O|Gܘo~7~ĩퟧhYrɕ9:֔ D:1Q[C͍T}TY >B+>pzabԠFLWh+F:w7S/c9`1Am:0轄[Yfc} `5$C:K0{sda,.&c8H ^X=@ < as!+ [YSU!2iIDaZuеяn#Vca+edowGOO}mo7mdUV_!wo\]fuҤ*d-;45y _tjh&SHš}Vuݻ6vjT }-5bLKbl:y", G*<FA j&klb\ "Ș]F2T&VmAG]?Wl~(G)L'8}jm=7 )cܷۗ{`H <4;JWf)1uj (>t"{,8:xE5dQ}'OZyŊGw߼~=#rA2$jCZ2e2} slm`jry (^2oΪ.{v\LoOO72$Q#;:Kl*%Z>:?MMM}_W{=_+~PUDb,hҵ TP=ikeGt_5ȓ&}I@q>Gu1OEVx W!VTs&)+@0&Ud4H:^.f1C F)Kl2M&V`rfRS43dhH:Յ렗 .8$ߗ1&R| | zsFkʦn)uML'y>ls(ՇD8ITGq g:0bTĢj gRSlth eюف BP6LNIk|QJ֕ oڼmwv޷ghn\{k_3k/nya/M#7]_hkhhU*'8u?{ʕ7|l($ 5tn|н԰ZK틬 tDVTt8!"ZeZ"dye#I1J(?"6rTE*< ]`2VbcSL#Ylj]d4 -!tgJ}(t)WucܘIWC7d֥:\Fu!xt /E.X8Qʔ95.<"ۧOpζN==6wJ~R` &o L9+xŷ7l` CkUKȿ[G튊))N^hLn<37n_pΤvT:7.峀@x+).@Q`1%&tNͤ܇eڦA<"!b28JQ AEV_Oa2,N$ۅb!:RNgx+ 6 ;wHW2QvغOڠ"RcyIVC/:m4,CBHq]# Æ,WЯ1HgWW1^Jj$ji"`آT[p5iE_jϒVtLC1(\|Ee70d` wT*wl&ϧӘ Ƃ*˜ K'(>5!Topמ.^·ί,o>Cd*eE-d`HEOM25,^O7~7Cv2icٕWr_bÁ-ol-z;v`Ϟp]x꯿44J IS|d*q5sܴ+y܅M n6IQl}]Ɩ׭}g?. QvdCdEa ſǣB4|d'|N|p$&vϮ ]jF /"QCNT(H+V7k_1B>KnX8rzsvL*g*/lIoOSUU)l[C/w~x_8uwxdtcs;Q>-_dwLjh* =R }V7 R k+5W3j#dG.BR%D d@cKv6ǣLEE:5Tpߎݻ6mo5 ^u컾nɚIeƵ5=--#s-;wʪHj2?g{SP5,`A&[;@EM!ʺ %t)32$@a&. (o 78T_["EKD?^e ,1bnut8{#ztMD:q%K} ]Ӓo /Nޱ~֕ޝ[SW?3xt2;НJRZ1 +QGs|DGA?`.+%uٰD8 p"gI?5٪z!a`>m"!cGEu5ؠ W. ^eMRCHdf0̈́dk3UiCO?bh%)r$%A:+j㺔8n*ʎ̃;3_ꊺ6%)!BY7rm1rDk&]㖣]8АLgXSkNL3u5lՉg]ߎڵy7WJ2>8(bvB}b>f#7v"w͟PC.;|-fRb2"AOm?8`UFz(SsJ%0JŚGB6UD nuHTHs|ɚ=mA<4 *#G4(:7?8ۯI3fO=3ZZ^zպ+Wn^cSSO?~{>x'~6ݚS+z/Ռp[zٳE'J@b _b % @px2VbmK 5V$E0$UHž2*u6Cǘ\ ;T\69fu1(FH Ul3/%ĸc@E}>JeNe"k 4v&H_zB|8T.)u 5"dj'* ˥ ۻEEԏl۲]+]UmU.2Xd&0t=- ~& dEMh  QqˮTSr++U,ra˼h@!+MIhT4PESH | PS*'#@RN7h ͏lم,xb|?HQXNb'H++i`j )iҫ=kK~oA*Y/,(75M;g5vr͂w۷ow~܄VXق}ة0.ζ5oD) ZEa??Hfts\\2ɔܐcہϝ7m\`&HfO?ؑ[V׺ .]Gr,@?"\,F=$ #x+.d+tsQ4ƻ` ]'9G%RDh9>j &C )& Hne؝Qvm_:wYc\qŢC[w;{յ_u3_~o-cŊ)PwxEsM_p3f-lnHT z>6͞޾LMMАS,P#S]ϡ(lU\ ~X~? B%P*X|:\fěÊ]*T/ԥmy՗7lXr}ֽ+^Q'#x16Zs}]}K,|c2, +@$d.@ ~P]x 1R3gGL;Pit+V\RӭhLWC=@-\[L=ƆԀ]@@(22m}l>ˏ=ЬpǍSڱnounٿ{L{cGU;q˖w||ߎ3]hX*E85y,] ]IlQ2l#n\S "lAb9bʤƌNeOz??۾Lm؟+m~eD =i[[k9tݞ3GNhkk3v{[7|oT`n(2@iʢx1UL4'!'AvS +1W+b/s*)4l'; qP;dH,蹾&Fƌ={LS~kƋ * |aՕL[]:<,ls>։^_8nhmln>j7t6F=BTdVkVFLj(sxyn21tˏ?A xʌit.~?Tim#[ZF;~d{ƌ gS .ڽ菛6+Ut]f6Yׁ !VaU& gimV:l$e@16VU$%Uv-E })0Rmc-=XUџ{,<[12SZ*Z&OБpt3rѡڳF m) TA_XW[744)?ܴ4\37O%t}Cma~ԄkoGtUcƍwp垼Ѐ~@6EB o <0b O$_;/dY>w0OKRI}THW%(t]vUӦ==U슚W`m$\PVF* P"`:E0>S1ԃ3L!8*oʖmN>)W,e׿l8%k=?0;ГW񆊃KϧPSmsCU&M1<$3=1X XfMP? !r7KbXK"%`JUϱp A? %&TR'޼yӑ'/͘2}M7~d.ߵ{ɳ.[TUx1Ȏ^ks$({^ y3\}'O;TȂYY),Xdg¢EKDfc'BѣǏrPNܩc+T,I3 F:\xH.Spg06ȠPv~lp!EH.S&/d+.XO1><(wPء( C D B,-d5sc ݧϝ?rLOmUp2fCh3-XD]IE?Vc5&?G3P|*JJ#E x Y\Ch0ey(,&J%u\XJ:S6KЇHj*2 4XU0|]ba-)XRRh[ˢAفBm 'hJu)dYm^cZM.*fyR@\ 7CIV2XJ;tL.09"KeJ E>B>i4d1Μ4͢^3 =ۮ[<_yՇ~]oߟJN*yk`ᎎFOjz]n_u,J-Sdm0Bbs:lCŋOLXYo45թ =. 5C8!$kLT a&[Gwkos }y+}UkZGN, rsg-w/?AUO6Ȣ].Vr<$ȣZ.*^V9H]^naŬjv>02l!>32}Mgtݠ& (` T7=RnAKcc-$2=)CS-SKuJOmu29!Ryxnsk˱]o}Xmf_|s'Oi/W,MtVXvT rgv=zB!_(lQ QIe1 53>D,w_@I.V,,B+8v*ٳ/~G6kޯϚ;8v?2?WJgK.I$3su2c|fK'Mj.)At*3O}S:""M Z&us*1&a@j)dp|-CzO9}ibѱj5ɤnh1T>~O|iD60}lZZ[}端.8Q(;չN3\^,**DE 5{`$%OVaDR:~ MQ 8Q+~m^>|bqξkn}b$pۻgk[_ݍK^&R;JL*-5{hq\T!K'P3eR{uT(baQIv规z+>mL=ࡣ٬j9O߷w7nn@D~rUյl +?Xpb LA%8{'5D96.!%cݣw1i8 Zt\|c$} LD cZCV@ T懁X y1k::p Z4 %'kIk:{:moζ;v9ң--dP rQ _g:O7 C-ۊ3ʚ gst (.m ӭX\*CS7yy{:T#F67Wl;0`{"]0 : tK,NU9gyl6aٳ55wqéuθR!Vjc D´A%߄Xifҧ W7\9?'˗^۞ڱ}'BoKm\2oÃm+G3[ };_W^4v+zṧNOj]bQ*8.`(ˢX/(&X6#1_DX_JD3I!h1 ߀ݢ!})@ %9?O_3R) wɞi.[5.޽Ǎ6q{Pvo-e &izcnL0a =dN`E {j;zUU /.,DֻDDcQE(+9Ø%4(Ѓknh$'>nء!uT5jOI>ܻohp9Rچ7\_S]{}x.E%c6_z >kvUtVTVRÖމ`d$W1Gjz]u밋JsT*P_'O/~ R}yp׮#_|ZW1)?Mfϝ7}ꔞnHXMSNٶw6/ʷ_~? mN-s-=^fBhvT|R_ɤKO=/W\YXZ3-w틗^?/+;/h٪]Ӊl^Ac l(hvb2Y?fH0}2 b 8dVëRƝ[`&+sZ,蔘 #H0JfTՠ϶쮞ÇOl|w7g߁=u ɪƖ:jU*<}NZ(Nt+E_#Qݡ (1K0;@ Rj̘t+咪(f Ld]/MX ȏIk<04l%K8ީ"+J+T^uBkghni?qŲb@ ulϏ神ʺ7^짾{8 kՆ*uhYIb_'2+@_kvt+ :S&_v<*Tzˮ.ؾe;կҍ臆Lilj|u#_Om_~ŕTT48)XE (Q́UdSGmd61焤xhJ/!I$a\ قHi9V,wqUZf#Kpz]M^5Tr"lG|ߛ7mkn}?{;ΟQe'_u\vyk80ꕏ?D}S%A6dRp!ϐW qEӪZy]sG^z~b6-X0e&ʿ n~Stm_sg fj݋Ou=P[?o,{s˧?slϹ ǿݠZtuwUԘBr  wsWĚ(bw*B<` ثhW #u*J :".QA ;Ɩ!E6Udžxd:N% j4It8xM}wӶv s uɍ tpL`(9 U F; 1P6ljEs ITA큳()ڂM,0MeeSY HUL0$u8_$t+9 kVJm.ZhNU)WJlR ]=DOLReW*k:hsSFB@Gͯ۶aruMŬ]/?؇ R)26](>pvT옦 '0R,cLfHhIڏ~eW\}W]-KE7l7}ܸbтhmhn;o,[zb~ O7V.3uƼj r}]u{ =g^79F]TF3mB}k F_ĜUXQF(3ClHrvP Wa@pAs0ùfۏRi̎_v#l-S0(V8uvG>TkΒUrl*;pK/tL ժejp@Qt-RwC~_MF=?5j1:%2XO/F&`mN mnou .CyvtJRY)23gF`a~BvX\O há;ں-|,:gDk甩%*}@6dj+ZSToޮO0 vU45=';>TV+ݝz"y[1t'F+]?{Z%|ˎP E)dδg~5'n{[= CJhPyJ)/]•D*p5ÓcK3/Oys.4p̤GF5)wUOo'ȝ`lmxuUz;w}΃]8Y@ZZ$0DVydF=\jEQ#'>8 CW`rحLh74QZ "refU\94SOHЧ@IT=93Mǽ*qWԏL/t]`b%U=QDUSHǴnm,bEq"jAyX9aiGA5+d>M/WQө*>~W*eǶTNtj++YUjcq7?w>ߘ(6~;?{ػ4uQY:80xtSF}.љmlj֮ݻz̿ttes[,jb_Ng/{ GGƇ]0ؤoUp !> g^BU`WYFE,]A'A9/H\ɐQ\6[6o~]OV?8zuzSu?ztlzĢy' X2h@ܽg_޾l 箸9L;){?Q>dž8*e`TA;o85KaDgɌ`TAX,6w5/&9=m涩N(g9W[ZV]գ>RP26:2wK'OmW{iL:FWʐ&vUٜű ~,EoA?b`JI9k{wz>ysgYj]eC89V!yo WbRV& "x#1[:)^QɤxAW!i SKwP\ I+?;.咲! ^r{чvLSJ޾>s_|Cޱ=-$Hg*E٦6n_Ǐ.]R &t:e@Bkr([;{cw|ˉ}o'ٱa&0Mp. =BF3w׽pyP7+f͌fOg_tEUUkXmjhL(ˠSlXc*2E=;cm}v|E{WX7?) X^'kA $QS v&~^ev:2>v /JZ J)ƔSt }ٍNBځRQo*Y!k^Bi^S̤JŒ0U#U+[~`w.YT?)]2 REM٠[7QzY D.8H&)E[ZtEEFd)/JҴDnTx@X@NฒC\b.kUN0خ-mS,iB9TRCʙhGUS?wRR1Go"ZU'aJF=ѿ}V2ێrd=aԊG9f2?$zJatUO/ 7ݰ_9o ?8^4B3w5[m'M)`jje -tCS 驭+v66oҳwvo24:pNp=*2|@(IjQ(M`Ed;!/`ӛƇ_}M= qP} STztӀ=@Na*,,(лHv&G#Okgی]7wԪ%)#!Il !fFC E `eOX1Vض D"+ ˂"\߱1nG,VXI%/<ӟ|s筮ʹ+b:؅}YT[‹/?;wZU2X+W-Z15YujL[؃HkʪkVS8Tr*|E`JMOB_l߅OR\t-1RYċ-!%nXdssk}.P^<+WK%+tM ӏ` WqArEԑ$1~ 4Ed,F$KDM`1(.qOC$C<0~>$S4])MRmp`C[޹}ǮW0LfssK[SkVMQq T#mJa ZQ8W7 ds) zUP|0w"U) @BFL3E=6 ,j(*IW oތK[덃F=g_v]k81NgNlƥ1Uc@q1] F`43v f)e9XLءåI,@dI6]Y V++) d6b5~ LTMw;oҎitGFF\(UKRqeo*綿zxhb|l ft. !cɡ㕵 ?>} )crʬY7}|ec k)V5& Y\Ą/sDMȘR%f"ɶ,ao' \>I6 L_}?~n^0MTW{,ww yZ¢%O}oܸrlZ.&E f<pW^uk);s:[y4ˮXB$"|Cu010v߇7yIY-~_,[ػ* м*F&TjƇ.W*Z`*6~& P8IR S8C(T:UlȋvhI~)`Z5bjXfJsA*f6445edR;v=={w5Sko>>B8-|ꀩ!V}wATsmhkg u.#;İZ"P.٦k0cfWO}d` J^r$,*ߐJfQRt+[riXt|PLQ Q𥄠禪=9H}͵J4{QY.GM r"bL>+k`R9fK^eY_ *+y#x:PExlF}fP8@ጞN? ˱prRQ ' ZB׀zر*&ɺ{\_a@H Wm nnT>k,Ju,g.Ym0]%0Zǃ炅K[]N 8uib(ל[{nٴ] :mlk1p/' 3eM5J6oued7FJQub,ab}TMEa C%]] "f %J ժ%*1rx0jhLḏCZgڼmm-S'=gSO~7my}S4u (d#` UU@-Lg#خmPA.NC2,@4&q ?]J W*B#c) gQI JBKQɰҘ~9ۥL X: )ɥ׭Y0_˿xLe'+.w{T\̘3gO>9{z@SEIr x #C>Gx_(LB%,cج97W466 5ijd aDC2)AlfҀ0ABY0;t*a{ZC&d"LQq +=F2o<1)ƌ-;g+*7{oީcMw+gվ~ٚ5eg{ٿ'?1Fzlٺm`f^O1dȠ@_@~, amrbSCyK)\0W5ݯ3/i\P(SdaHnvs@*MՊ}xSFjShU@mVHJf j~+ v6TQ Q0 B+(!Wiۼ?2%?0|0GHԙ„>CO:зF$\odttbloB_8=R˧TsHPƈ\Ou.CTr/*m(Ȫ5 \]*R]B`fD{(RNsI Rc/18DVs ! E.")=~YCJp$qn@2jB r)j'z)BdN$e z>k;[EWFg3p sBE=VۉnE}jL8gGC`y1Jt43,E4) 9?,VReG.aPY,SO=KBߨ89}VHzVD(8y?)I݋ 1#z"JBC؇9 Շjɉ2xguPS#˱i SVXRmy,*4 =t:z8"["(Μ?mku 9׳kUs޷׏>G.?k`)J'ʹT6ss,O˖ l}1=*5[W^so~~b`oݳjMd:fa,뺊IOV@pEs/=sd;nkӘ+ۦM˥{WUJZ@1kШ0GxZC9ddgU)C.0eCQp:ֈ+Y#HARz:sT"ކ^Kڳg=rrBM&Ӎ\6igyj9V.djI*kj%` PYv,z9%/yV)*Щi2zcBI QMewi]leԂ2BW @յ=:݊\> 0?MW$j EILO0L(5N+r( zh7yV`u|3ݩS4; l: }hq,QuiC!< `$"x%I %nXI>-8*=Aw5b+RkŋDDɓ 0ÞFN)Ztzbz{nxb}ߨ ϳ48Fih Oe|vѼ/iljԶK6dY\w~Wֽ{̑co^3o;׋ wmtM\{Si!Oa&SL5Q!ULkaC£kӗN\WKW^ESq~>uB\Ғ]ޢmauE9W瓭Vk^8l=ZJhžx{TU2uZ^D*BLwy UZaPe/vible{\t OD+|1VVX=2`{0Wl#W<ҏk'i,1JiW,{}\D^T,,_v鯿9&FB'``eh .Pω>dID2)4S3ƇCJL7H7P6cD#gŎ+bA&ZdU Xc {7 %&L2-*#Ϸ-(aPpdSM [_?akꜞˍƶԝw|pO.IˣÂijd:1^_+ɡ+"R@Sc?_^^zje|^~wy]slyM6{npmw' IZ9UlSD 5knwˏNoiZy?0mΌ'N$U%OCI:iIl긎ƣTHѠ4|DY^K@RI2I?&2HHL+-9Rb9}FjۨRHd _<:6=BQBr^c CtUxoRTJ nj'/A8;*gr9`4hMXzhI>bCL!P\-*۰*SJIeSb_ȁk!C+'I=16-(L#d=+teOeej\Mo(R 9v% xr |z$seUWSW:g82Id/Eʾe>Mz#ȁk2 cJg끖HUzC4muL&G2FC w4TTԿ|ΝTܾyJ \!5*5EtA)=ƝuΎfvP-m!wL;{;׭0k8e4(U Iˆ:[, (a.A&%p bD0393R} *|X1M'V_)G&1Qoeeqa B኎؜B͘6|?kh4?W{h3Gϝ?͙bJk ]'{bY.^&|o:mk6nm _|?<Džrng}oħZbrhy/"ŐX dw֎o'_ŝ?o%6811}`Mj$z PC&R. 2(G\ys\UU >1zOb;恣 !^Da9z ~+5l$TRT.t>i$ ;~CΜ?{yd״eʧMʸ`ҧ5od&My0Y(E)W| PO:~J<)PA`ˡ @5d ׅ~B!yR8\ MJ&@@]j&/CGQ1@gwFHLu>˛`~  ۖ]5_D@?Oy6TOʗ&V)ZV$xrT[,߭y:#&yL3]@;rBmנM]C~pݩZ*N G5"!ۥ2ʥSgL릴fD+)m't<{e+nXֽdٚ3'ܩoj^QB2]T6} >v+[.s]C_sC}eKv>~5ם8|w?{Z[;yoԱM2îXx0M8tB%OP̨4(bgo D4eE۳SirZC*?49jڥ=m%=s;&N&Z+~m2?9[~dΖdDCKG;g.]e.K"zV5bY({T6 Jdj*왫43yʎ=?-Y E8Gqc%!O*#%GLcG>0U]1 4q#jpν2p4! AXPnfP,$D<lS}@%a( )U=?49࿊d(I[!VK% =d}J6b(EB%D2FvmcVm]?d<S8V]k[yl"M'.ya[omݳ_J/^x>j#NChǫf.on~Sc 8}o))/eR _: O=7GΛ{#]]824VCY8օ1 aRLӄ֩M׏SL6?;ٛ=l$FClmSlĊ%Dp2\ 0 ?x!hlʽO!܍Q&V5i=rdlL O^:}iϮCnuhٳl!HeSlZ{*S3vnnҫT5/"MC8(55p<_MtW' "  nyhXjU-ġ)U=[Y *0`hd$dMEf^lc&X@y ~ҏ lá@ɩcW2tMEl:\锲nMo>{Ǟő÷mۛon5SS-Xxh۵cɒ3fIgL3sfiR*2uu~#1!fykU`&4J !jϦG6g¼tMkԬ+g/M:\N8R(O\:ߐΚٽ|3^˵ 820} G{W#Y3v\Ψ6 nlkՔٙ\ZXߛ'x!|֙t\Ux^ QYiO$-f ,^`Kߎ06!})= c#MC D +_ڐO4V;AY;4%hŦ̼EBb\.wԧ]{0IU7#pXd;0_S8I ]"w|?9G`5LG=BZ[/&P0okgTHV;Tw4Mɏ~S׿_O~%$L)Ӧ4gkJ"ݕͥ)??kktuv䛋׷k)ዟy{އ5C c??/~/\9s|kw-^Jw!ϩ*Nh0&lEMS,UMiiw ;gPk[4'rwaĤ0Gݻa,{`( kX!gI_$+vEJ5d ֞b,(2"m{LA4!1Si.L%eɓl۾gww#Af!IL-`갬'= -.LE:}c: !U$X.PV%; `tu]C\9*k)OB Z'hֺ ]GlMyGI\ JA~dUk"bث);f}4؍&/F*XC ,4/5eX*U]pTLvm\]Q HazmoͭE$0MSfr+nd*T+H@t(XMQR $^rdb>A7V`u*R3-kZ`#HEFÔƥ+ 1<U&T7ܾaz]8"0I&Fr}~s{0{?2XKQ{t5ˮ\R͘3]T[nc&U7sk@,tAY .vLᎉ1Tl[ꅵ"|@V=CP-ݝص޷Ξu~3_8y'}|#+_hԚGwaӝW.{u{=r䀞O.X2ڵo^q&&L j\KK c<Zj.L]KOl9FYG҆;{=:r%t쮖rB1u 2(S']( Y,=P q{>֝W 0Murt(\8RH*i#i`H U99YwҡsK#Um !:)@Si1}Af`+*!U'4tac(CЧjT5ALZRr,N'PFX/٥GCGZnBx G_[c7joNn ks%WLucsPgĤ"Q d% XHRGeU~X*MjJTgg*&mTjh.{.X? [:Rm˿PS}vLԦe6#5$Uױh `>Jw16|G֠rW j dV"fUR8kN}>נ D7u6u/2uj{.'(X$kWROq.ԡdwehdധd:F?sb^s}OP;v,)CYՍv~'Oxp{>&BWS]ݟ%!>k܇E1b61M"(X 5XŅ[Y?#?"iQ-!b3Tw'hf-`?-ٚUھmK6dWjjY7cZ}3 Bf3č{buS0/q ZA\5$"]SC!S?gcy>]H464;?'~?^:p`_a50;\nll+}ۭvs{xhL*VrG?Zp9=Tju-S;QhʥZw,;y/ȥzc˷^}ދ;r_~PC} BV7Z!_ GN)&g^(:0uZxbT"cvς loo>08PnU|:(Jn(q% ak /R į.4VTOU2̠ `0 v!W7""*3d&gJ:׶?Ճ<{r`bXHj:e ؐv̍fY>jG!>iJݤJ@y)0GcE]nf 7ra$Wե~]HZT :bIçh/U[ J?yPUfPAҫOATZDѥ3&,Hwx+銡8ցPHaC^Юy(Ip(:e* TS UUuZ |ˢw MMLVBOϦ)mmק%jhT)9p"\rlqzMڳ任_l=oS~a l8QLdlӅE'n*ڜZz;t7r7;Su.[`5əcգ{O;zGH%M<|ooذxfZTݙ ;N:k쑱,eziG}XwMK *ڰe1d`3F A1ߧ^5ܤ">[#\, =HU SyVba'hFH 0s&7l%#_q :hDAB?%c J.1'{bmɒsfr  9` N ըq<|P>DPAd0.aƎItP5,,CN zTTݷpӌ#'{~-89BE=3_[u5wgR> * ߢY)W]kzDiR.F~JxZ,J9[7tWݺsO>`ǒ߳[]{.\[(ەbZ5n|EЯy\}3 SŠkkz&بa)7-Tbi_]lqI#dGOABkNQŰwSDog>"v*x>%YXrpSr&'Kg.=~s<ϧf)݋: /ahCѷʊ ;`RpkNa<" ||YrB&(9 EvNj;t ՠ:NAvK*T?y\m)0U=t=V۔MàRHtY4 8؁dD<"LCf NQcC=IKQEZQpb%ls"j˳ՈJOP¦ |WB`%dUǮPgy :g&Dƚ} e$-F I7u+U'BI77ZѤ#1a.HhxLLMWJ#Ν>?oBh)jE+aiۭkj*w_q /w-wíx[G״x8!*isor;.%Nw]_`󑽅j0Xʕ3衳g 1Ktد[w/$6֦}8JEU2X '~Cs/ "h!)bR- ِš\A^*ws˿{O{r-k]MdMͤ>S?aR8if?y]/K\N[6uw߹n'^ѵaCgt޸tً*}90f@a,!)ly(#+ M0<-pITT$z2R@)aX)숪BZXAN$"J,(މGY%oVN#EК +)Dvb_v~!QʪԦN\j}f[cH:e*$> i:Hq-VpEB'MH[(SgyO&MU՝ ,UX㎊2KU4D?sv]X׿ů~Sf.8y7~pŊnooymj3{^S[ɱU,Z:۫KWzıys%Ry2c'Jz34ߟ; .nqp {,e"G?~oO'ZZ̞~b68cl]&'Ƕf0/~nae.s7[?xⱟ\'>Xk0~;7~:޻?|;kNu\W(Z#ѕHN0em$gc^4`L0V %#XF'(|}S/~//ΎEf>Ri W7H Ds8k;rD4Р!J*l֤fDR&'j'N}m[/ÇZaY3Č7+N z&u*Ȁ{iHj-2߶keae^W~ʑc1]v'A(yfP^L{3>5L:5y]2N>tݣRv*0j<$ %JDi,)e*&nLʪdv uj~P0aj@P1 Zj_DG]Qbϼ隴Z8UQycoc#RDUo,z]*k%AM$tQ:F' $LW& nͤڎm@, UB]([+tB[0v*hʱ+\ fJ)e O['z;&;&eVǴ 瘩|%LcZ]R.l}\fJ5rų7| 7\;}tS{x;eO}gǛM+W\Fe[`-6bM/Fgb4lKcQdW1 g)lg!q[a6/Nwœ waN\"_Yٵ KogۺlRoƲUӺV(ˏ?T]޶jij3Υpb|th蒬,E'ƃ C|㑼DԒXٯݱlzv,OИdfܪi==YsiC+a$BA:*tSHX#UaGؖ3&bPL.L.WVFqOa((Ev4xR<]}oh''<WXuOQNB*;v`C_Tn1[ E#e:vm)bvт͞?J($5PE񙗞QĚ ?ٷnHo [Cﻡ1ܵoM6yx~6ܴK3$+OyKG|a޽_y՗O>F2\{통ׯ.Kj\+ Ph0541~QxLΏz L4rY.&#gshhEqs˔w5rɩj]ink eCs;ISVzCslD\ X2՚|fQE2d2 mR-\8wӽG W02ZVKl2-POK)*`MI'KTg@N(T4 EP61erb 0&\@5)EO* Ĕ0ɤD>G\ZעU1h"ꩄ[%~^_T{@(OqZ׺$;TEn{t̴fcbgyfFjx JD^ȥj`qѲjӒ&Zxl"MX6$\/aTɀ?UPX#]ant0z lJaRr"_b0HK*GZ:(*eu (L I3A9H檓(YuM:𛀔oҿ/+``~X`N̢vcQLP@F< ص.Xg/ism}-ZdO_/vz7ݵGwx V{?rk<ա֬/vDMVM3DT>Uɇ 5RjznX((PPb'Q9jBat^ǟf/8nZ1oc3S578/67W͋<DabK!v"fH& Pgn YkʉÎ':` 1T3%W[U򙓻:{vRV)jcSD&RRO@F\1͗HSd6H&( t4]`G0խ.L6wl}ogxgzc]): mm-Tf<[[^|E5MoJ #Wt 7_DuMV) S~'݆8zXf͙5{M7]6w{[~/~޾-1*]zg>/,u\M 6|M UF#c5$F +lDm ˜"X/x =^mO?UkFPbF볈$OabUH(5t 9G>)-e56d9M5|7LAG mL@@I\/ tg*2z(>9P `{m 8}JHf2ꐢSsl/XX)4:l+xb z(i*UzԲx !P-Ї%IG"z*@0#6][t֦4-P׊$hnBu]?sMӤ aTKt}Y`h45U)QqJZԘ5LԹLuTxɚO6 3}_ ʷϟ;{劗-;sܩw&3LzoR)1 U>VEv]g[DVYXHMHB >>vz~<>{ο{WUl\Svh_9;Ҧ҉($lTP%K}G VbL0B 30& Ha56X~q3͘􎝳L9~lQarpdֺ˗:9$#ƒהQAMLe>16#3U5`9lqh]cc91oݟ#S1`&uNIG"D!T+zdKPL&clgtdKgz{O_e~Zma._9o\l/[\MwnƢESә|k$ O46>Ҕo5}nyo<vyuD&oӦgΜ# )r\$M,9P4gŏj2AJ`|G$c xjV $OP*UJ2ֺU{.92MW̙9m A/]$Z+ώdN{ej43+;w|kb!MyRyh25=i;OWfQ݃ ˺W}I.u# a˥}R΄,s,94]ScO[ڗΤYF\W~ɜ9؄3P՟i_;H'R&a.WʁQ`CI2Wi/k(6PVU]]8yQo|<:qlW{X醖F%fWeho:J]*{\#sgk閽SvN5!kˑyqtǦSgNܱp9lǾ:>w㵴{zgv68)j›nmժ_iй+gp8*X7d8"FVl|$ S>Ac6b@РH:6.A+:UABm%o;y:USCit`w/<[pBzj Wo j*%}H*4PP9wȂ(y&ؘ$~ܡasORS NrVjF\>fm.Vh{¦-㢷x0>Iŏbamڛ6SwU֫r\uCodz ^qr7޸zյk^5g½{9zЂ+CW|vXfΝ>gѼ<410T^4ZcIdz7~8B_r5?r.WH+*W04*k-?qgQW׾wO;ٓҒՠ_7c/ j,XsdO>gK+QVO TT45pɼ`U}\(}cȉYi3 ;?v99f{%:KlGy蕳54jqlNfmyC''5֤2+"7RY4fl̹fn 9҂ձ isZLpK"!_U0+8xm1 4RP3?8ej'] gD$tĭ[_o|(ِ3l+E" |z29,ߥL+͂˶iorqʠǴHmhnҕ2ْ|O=<k~tt,UТHec…d.;::S57^{)zboo߹֏o'/~ nywn~ͯp͚k5YvG{/^쏧uF3RdyQ.0_;2;aqUeU]!#s 6=A0v|&@(V8͘E9mMOkL/(]0V_*YWc-ڙs_i( B`qtġ\:U1m_=cLEɡ%yխD[o}7vݼ{<:(9u`]zMϚ%CrU4ZH1-Xaٶͱ:hzX+ܽH歭wg-Fbq.hzM׷vڧ}K''ڱ7?Wb 73PSPд-$ЄGV&KV2 of$&mtc=wɠq+, GA  Dϡ(L }#K<9P>8V(C-ͮ歪2Scy{eۄ|p(fj!ee -T$ LQ+f_>eTabimQdԙ'O8J{[8]B}-tJQo!}1sxg|mgksLvϮ=KaɈM-Xz-mZ\5}6\#ѿ 1ɷ ǎ8hA끃G69QP5{cyd+̭QWR~⭣kot͢{vK9Jޚk]'c5(.eCj*70W-L=(`(4{R$TU_,.&80{T81݆db=(,E:rUvbdBL$6|sC.޾{`Tp0)W D'J j"N;!*ݴN.T&'*eCI): E}"`uLL)1;<K{6YK 1eAK?Ch1H@Z W ȞJ}|$J;IdѼ*ӄ3K*.o*D/Hh&#T!dJf9$hc}Ps8 2VfR ;!cbl! e7cf@6X9`}t'*褉&Sp/0+$=4>ٗI}o:m$jP~&oiBí e 2?-.K2G.˄wҥgMmPH%*Hc̞9S0|AkV͚8SK7n7uttPxSɆ|o:ssqss+֧W.cb,x3yu_6܋ƈ&?5kekxeӱەpe2I>z LaWUUK`jH$Y/aP@߱-k7Ç^)Ux77MS.육?o~GA5˅[n_ߘp_)J񌜪Ke rŷM$a"SƜN+ɂiWAs-.7kg\,&&>bI) %4c)jf$e]/)]:7|Q [s4Ѭ6ԩ%ǠBwQ`5Ӣqaw`6WQd*: ȸ<k[]qiQ@Z\NO?r Q*# }ERҹޟod"Ƕ}ˆP"AɒkZ1dv=KjR"Mց\/gt80xЕ -ͩچ\' n۱ :Yðg,ξ7__' 뮻ɵ1AVZn/^f '~3Z}6o{QȈ֬7#~ǝm S_.JnZ"l))DF{:y&9<#f\QËΣ(l 5$4K"J)(cT:wԩ3y.Xj_:tl߆[n#GnHTjl2(3=w{s{KIjNŸJ2I,!xq(qCq(l%]*9 2rBk =cbܘ0lL>I'!HHHeG.p 90 v"2!`%@YT($LJj`)q |MFٌ3 4E#RwToXu YTcVopٷHD(.B>~>NPr{(]# 9 z"C^L")즄WWɆ2|WEtm~dʋpgLڵJ"&=Enǎ9J+-Mygް)诽yy ]h:-MiڛojS/j"(0ɪ;~iRr0 mȵ]E&T%ky6rZ5v'3ت ujzQx?k7~ Mݻ`x9&3's=WNrqϥm;weleXe)M!әC`ϩы_JQ*" Ra40u]mkm50:_2mcɴnV3g&+uJ{Mej<@33+8].*ҾN|gqe Nh2Rע*Zhu /]:t)M˖- R1% n2L^}նo>4X}cx^>Fg ?>Nmo=u]w]~ݗlmge, AZ2džF[:[[V|W^֔o[jFޏw`Α}?M]dt拲6S/l~O|ʣ|6[ԧ>xRqGFaG}I"z\!.)2cB0.dNɢ14O Ć12tN"T ٔ gHvGB$ =*jcULdž.˪jW?z ibh==u̥u:MM'JǏo;tgM Q*)r"%5-&tX/# C` PK@bXVdII|hNy@ }n\I&絘J> #/:Mހ. 0y}sV@ + ~Ӳ2c+%?_j́L5ePF lD= .Lm8KLUq}|3IPvn{œӻbJ"@N+t̊0 &(Z idhJ3}{%4(%]?UB80 @Q&u tDocn$*G e8r!tm߶(y8qP,U]0L*EۑU 8eF،G2QVgUcl%+t\t bsKKSgg'vt1 f`RI˳ɦg{y]pxݞz=7u`?/.JߒLiٚo>7LϏ3Yʓgܵg_+x|ɊO\RUo;6mLgrɔ&RfW.RQو憬V4(bS (ěU'QMPT1LON3|w5udR쟽>zsζ\+m؄-<|qcshkq^FPeJ$hg-XEKy@SLVݒ%kBzG,FLS[ʵ` l10]jQZJ\_BbL6Ǩ;?њl/6;QU R@k<Θ!`xqQGl&۷?x 'bY+T5mJK뮝z{_սjJg;?κ1(T mn =I?4mvZJ)}|d-w_?:1Y #{ RMd ;{{ί]jő1gv9ӦΚӹu_;vX#{tãC|%7~W}_/.]t+aQdQDI#Mmd`1A1fϮ%"H3@Ū  U]*.ӻ@ Kn} qђgDUu`  a1i$Đ1Tu-ئ;t+cL"Ued\vϜ>w;v8vp`R$kW|]:e*sK)}rEb(t `}߲ʐru@8ˎ.9뀛䥘)*8Ut{LS* _@U =x9H}"/5Z*tidI`$8'xCF"CESQq, 5 d9 e(Uɀ5ejkZquM}uJ_مɢQ)3@lge w/>7]+]w4OBK[Źt[_厏({UOgɸK>1<294Ew[bL%bmL_ʹ#2 OjB֙af<6<ϫ7̜յxUKjۧ״7[V,pk_NוKHrR>{N?2L=7--m}7Yֿ@N/[S,LHP85zz-]1{?Psm*juO]EPtor%$ړELE9cqd3: (Kb.TTID?rL 'ct.SС}HtYpW"S&}.JdӴ^i$%g~*[on"{A6Zer|'͉ZJi1A]Ih:aqR?q>TX_r"\(AS){1+0hyi_ʆA^׍yo{ǩ N'Bi"2.T4]g0E'[FIZ9 v)O4MQ>:> C+, et60"B.vI P88?cX R(4& \m8 k E[+\&JTSW7&qY눪 Ȣ6&7t|G{|VLu:ZcBwM8*xըPyhYpQ2i|S[dI㮍MjYˎX8 ( .#Lp1.'ƺ@'(b YiRUIG!n?ąfW6 &(P<#㦂ƆTU K&ႀ U[Uw`^fy;Q&c-z`Vr(V*)VF(OM4M()VlTdc2th&XZ-Cܽ ,e|eز¼c6آx76hjou i}4ӅF9L>{zmޅCZyz8zܾ <en=66'أG@ZGցӁρx+\,;'f a]"` kc\.6W=\)ckyp88Npfmjr|#k7|싟,#_pb|4/TfmX<Tk -P,lnb7.8x >4ә#nA47M6I4<kaizjk"acC' .#p\op B\ 5@7pJn Ψbu6EpM`åxYl*: :ѱm4Vn  ZF b ߪcnǾ2 >'7 #*Ї>klw S2ø"b{*j`u;Nvدv[T-3G4 ifYNT5>l 2ބ6VXGޯN/gE wS$h?6!A$ q9Sޓ4[9HÓ{=7B64VX4ߦ㭪J' ڹNg+ƽ $ilTURW#؈gMa_ld`MG *8? Z:  Mvبh%imEEXJ\Nє[x:˧S;F'ݟeWgߨ6W7'VxȑkVܻXeq 0 l&/r ;w랹_;{A;,?_p6LIc|so͚hzYG;W46 4MKm]/5;۶m_Ak&%h\=u)u,7)`F U iいuЮC,Sl8#w 4pLͨL%v*Lq,&~i2KFD8kPa9 #ƪ Np1#0v;iİDk5 6 @ Hi]6 ϳ{Mpp@ 2x>ҩ5&JVb:VYƭpp!a7`tX ~$5\źtuCbx갢/Q`sSX·02^ NrW@"^  BiX_:<'" /p:O{TUt GVHX<,.$+緻Z)Fe-pDž`83|,a/leQ\g|ͫc' 4r *dCt`+0웺qukp=SbU+-ղ:߱xؓ.|fd(735/wu#N:ϸ}=gXU\8F{Pz  / ;N8550?ғgHGF nqlyFdoRgbl4溆  5&/VoP'̓hvt~qǃK|ZUcUou J=ޡI@IUֶaBDblQ<-~<#.LBZ!=P/ Pvc"fC i[\-4`+ T#I+w ErtLmIPq#a1G8e.ьB ZCdUIgh:vxenoqn!*|dx2/,f0hIaV>&_)L [d~8p\hd=x aBf^!'|8*X'qj v aړo 858Iī6t*Lԏ747m]YfH`6z G6N=CO9Vj,%hۦfD"_d0k"n[ݨx׿1x|6%HR ֒D~|ۗl- _{b;ɆO DxCR9l94MzpUeIlI5;@Bt;,.ĂQieXa3UTJ<ԗDзJ @tNb[<_KKs̚o~ro$?Q(($k0H2qnw2?#G0rYk]2d~fBˌD;Wعp/Q@0J*1՞p#3!DLYz-ށ2dJ+j$'$&:$Y b)x2mi}{oyk|?Ï/k?xkU]oy^ʲr,t<9Ϲ;^p-L| QÒ,w0 nhƾp<8Lb310𾀥hqL%%4UMi/XVAc&LbRi3I 3|vN;R_ƢLTԍ=rmi uXsҦ4i:(!RVhGyżbQm| pDD.+43Nܫ#LFHDl6 U1DWU00jIgX#` x`O;[J ^=$ְ:D^ C @FuiUnBV0<04g̉Hڈ0)ۊJdZ7rx)(l]“q4.{=4S<`<*`Gpw8QFDc ,i !YK"k2`(Lt_L8^8Hpa,bS<6<DZ.`1)Tc%^VD+k9)q N: YzxP x~i}e}rJ#a- `Y9 I< ̞I+"M̄n+?|h ه߼/cD#{(B n ѯ+Vn~Z6Y"AY`t/Γlt޵^&Q@03'zɴ#܈aiQg%:IsAؖ%׉g(55bÃ[#ӌ8X2 "N^,#d#`g x'׳v=STRaT,pł4xʳf,Z3Wˮf@1\}fDVdܑb1 5hȶ׽Er̤4~%^G $r, +4ES] 7$e$R.bY$@28S_R1M4,bGXbXx[C_O!W gnAeE*iT8 r4:& %͂W,+,z[w@!UfSh>Ʒh%Lt*ΑȢ`pเ^}evDȣ~#?Zaa k*@,tdŨÝÐ 1&|bRvL6`Q)ccx%qSJYL ^CH="bPX헓(O0,z?Ĩk8N)eV4 ʒ|FoS 0ёɩq>p`DwI<ñ,65cK(!& DN,$Ix^2'VMX#8RF2V~$a "׾{w>| K˰r::oZ!+"HiL#\8:ҹG>xk+UTTY B Q ŶQ1lF,xDtLgx!|.OԆ#gfFQAY5C5 G $5xHp< P6Bބ&P|W&O Yj$y ,\%s$\"SY4i !be$k߀ߌldq'K(:K@jB>܌} So{;8NJqB! (0˳m 0&":5X?fYbhʖ8$oT\k,6`3QL87@M1f|B8wL\Ȑ@6,8ܔ<4eY{A0/q eNնBS*A2iFƆK*1,\INTVHdDvkig/bƲ\ c TJepÛd3& ifƝ6bKQS9j#L+0fc**Z&YK$ + 72c*׊,bH aSbD;S.]i~UΛ-/{3 3TYچ xEb4" ]$I?ҝ}kn# Fr(QaB%fVTHXp4TB59 Pd;Z 5sd+V4X7#8FD^48G+j^c؆%dnJƌ*iF|ccSŊJ5}D!S:T&@ܻ3krgGe)I TxNpކqYJ#X`%.=?'4^^!W|RQ<ı'RP͵e^˘flz[y@XeK(=HKb70fHwȂ2<:51xHIա׫)&oRcNg аk8cx}<"ub2W^~Օw{zoCǮ|+]߼˞W@RgPgHr"qa"%6,"IIz9%`+(7l!ZIX7MR(CKbX~:KX2pMz5lɎMME+ cˌ&Cck80bZ-AU#N+G 8i%ثTI/b[!琲8-BDU3itv&+(Cp03 ൅} !BGX&CFc7H{fBYƚfZѭLlڕf%r+SU`® r\\Xz0hR.ak Ӕ+ʦ[e֐USK~7 S?p,;(^49i2Oa[ ˰$b0-su݊YT,'q%.vc&Iwtwj|XYhAQQ7a}jږ h)4 SAZ]Y;wG=zAʦ.{ɝCBz'Lb17bwbbD)d4?ɓ?hϞ&0{@$wȆSgAb gگ]}[MHxF1;e"􆬾QI^W*(p3# cڇ[0=CJ@eNa{$y *`M;oǑ-UBsD zLdw4%dv .P y6t&?*`DTJ) v7|RjiKq-̐b5#Qxx8.o aD<%82jᴰK)aA;IIj$q(Ei8`'.𷮅S|9MkB&lՈp8T[r4Kq,1 @ u%8jԥiM'd2zmj4Rea/r9v;^mN hӱ|7gn7]عxhAURnv_ۭ 0k \D0]SDeK)3-aږw̉?Cb˸snqqGF,n?K.9M kKn.h=RPo_ػo3ww:8/>-ΰ$l`"@Ti o =6EǠC`IQSGJl'xiGtRYYԙ7歲e,2 &@i4); NU@յ򘆤 HNptOI_WS?b=!Ai`wFG?vm4 NA(P4H.jıo/.kAr^eJ!1wI51OSlI±l IY20f+P y9&)kԋ]:ilfl`FB*ߓ&]i iǯk/x® ?g'm Z;{c (xڭLttzb%ʒq##BWrUe2IHnlFK}99X$#pǺ\jkR"9T#taXziҬ)U7K1 &^WurBv"RT7UT*(ҭ3ɨ5=fSSmH˅jX0jN{=uEel%uUwX@` Lpqu &hBc~*ؚQ1V5)2>ƻPҬ`bFbk sF# 5,LNp2R9>'D$z&H,Vd>,6TH6=%U?l}PʟRl855up~B{jt4"E`#cu*=.?q?|>8;>W$U@pRjr#Yc/6O,x#y#Ǐ)a1?}ncʺ*V,]N|ɗ]Q> z_K`Fû#: u9VˀПBVrok'Z3X7͹Nߵ꺛_ܳbl%C6i4Y4#1"RA,|,E{o CQB6y2x֥{+67#H38`d\H`[ޱ۷Q[K5{[dB.3^p*V؆\rņigKNJ+m1- F%8tD(!m`SщLO+3 !u y;2aKn`)+Giq{e QOz9<΢08)%uK>k򩓁Xn(, "._(EډDdgdSD4dK8dMB^I{'P/肊=.hXF&3% ;_DP%=ҒuJA.(g}E&kMT{ՓGg7DuȆRu}&Xvbz/n̔iʉJS3PLqGW_$W&-Z *-{4JO[e0֬NZ uR jrpG6KGv\$KތѺpvI $2!Nrxԩ&K0,l^f*'I[ȺmYSmg.L ڍ+글a]m- S9Æ7qɪ3p5Xg>F2&&eaN=4yC 'P *@~u< wdX[gmK&y`jk ~ΰ9Sp@P |^ mzGLNu*[V%c S ).I+cDklnafrzvzzzrbbiʲ7*gId 8znesgW $uYԧ׮_3&[GMr'w#GN-m{xgjna]WxKv.̍fzX5|E]eqFIlԽjG<܋hDL$yCo,z5'ӈydc'cA7<QuQёXw\y~v-nyܮ=WpHWo9y}+IMf9R¿PqTnJ4D5غ5mtKo/gW,7vo.H9s{jp@XuĎr.dtMHL3 AAlKW2khe {ٶOs݈]p]P˴d"WhC)E4\sj D=W<߬XrPxOxV'Ki\i0-(5lj$ CEc"3*a2Ek +.@+< d" "E41ti˾OTLV ,!O}Űϸ=L":$Yo!ry/0 P܅%f1 Dj\ ک  ZE))$VN-D)TDU*440j*;./x|agq֤aTq}cS\Z噶`Xh\ ` @w]Xa [Fe!<.A_ķ*pّVR%-j87(H#j: xiVჍnm)HjSpTvVp"]pX1/76w&MTy_nחWΜ_]Y"p1;˞%{}٬Wut.θ@{;;_~o-ګݵwfj|dtKMokPս(< 4y6 T>9(6z]'z'_}ŗs7 IrIvrg !$f_m;#'?ǿ y凟vz\ƭ,@-۴F{,A햮~}3ۦ掅vIW!T+{,]\Ab@f:И =@Za`)աlZzw0lg7N q ځOXdπb3XFsvkS0sA&\(LGq~D4T7 c,`2k5?$ A э$G)==B] oƊ(RǼ00&Ӝ{"@IM !ICsR#p8 vJhR:ΧPԄlb#3u})Eث -DlpT6\ {*)ٟEbO~goo|wg]O1(zu+~ݻq9@W4cpBG)4R$gN%gyj }mN'ؼL- (2VZIsCOE)_E_ƚ\C VIa\'\Yk2D-_~ͳA,;vILT9F GYv LD(]z0̤Nf"YT5l>%'S<Fp(u)>O2##`eBѣP]7iՁǴq) mo7)VΆFѬβ}{.̏LGF;UfKΧ휚V櫞q=+痗,--FAFu]s 7wۜRo;.׳sW~_x[{ϪV?7#oNvv.o67x)>-'-Wٙ#w)|4 [)rϘƴtG8op>U孞mj|r ^tb%bƎLu~m6_Z鱱+#K[*s%O wæcl1~jtgZݬVy RĔ8FS藫O_`.6FF;;=}1JEjPlnm G*bNV-ڙcJhbj89>I5. $:OBkVR= RԤIZ5?MŒqdtلs4UɪCLz"b  I b T*k:5.9S_j}w/1 Iv8ŭ3kK3+| Z52)_])@ K=NW3\)nX0/.¨sf pi9GM [plgq싒_x?CkMO̧`)&nxKO'_66޽w.?xOyN?~M#5$,9xxeִ;ݏ~-fi&82Fe,4i@-),А[)Vfb>v8Y+STGޙ1KIĤP釢x݈æSŮb%6([9(P 05r8ip)y 1 Z`2ĚJ$N!8TYrLf׬X4 }ZNXopAdrv1q4 J`ߧK kQ|צwdAӔhZԫ LXѩס>BQΩ4αʋ2%'k)ɐtq+JiemdX  9([<|5hO,nhrmf'5ײ*9^:<8vauk#GN>||fmm;],?b+7WNjF>_dGرo;_rnə~wuXoxeyEJvNIOAyفMFV<k̉҇ w>鑭TPhcyo7Wac%#߮ff:sv~zԥz=]setG!Lҳ-ͺMvC52nv ,*~Ы?mAamn>m[h:7V'}oV?9=NOoJPk_L%E'PrZ%SNN+S=N3*LqEūvVMMQNʱ0P:U&ɒ 3M7D_Qg!'UP x dT\l—$.L3l|dhi MZy^=PtTz9j jDŽ{?3O(g | d6:en+O;t,>%c');7^~Ywl$pDp]w@WTBY'#M,)(X ^X-9lj PyC#8]8Wp䰕=pp&T[ڣ4 ~90"l!Taʋbʿ}w ~mrꌵ 35m|g>}_NBZo?$R"°H'JX!$3;l8-:̓RHXcGf 4,ZN9tQcXoBy {r¦7qGRyfB%f[S_EjuuهaqȹK85geV~ ;|@Hy{F6,ƢdPDÁ1 w(B)N`zc3+>,΋ٮȼ،% b@Z0ϑj TADdr旨GBp pq*R6)#~r5Lġ9\A Pk8FL6ݾi5Ķsgv>6>2ٸa6 -疖8pt7^sۻ{׵O{%N'o}ӟ HG>wW?]/GH١+Gkvw-JG-ӳ/gj;l Lh]* W\m~X8 =W|mvnfo7캨Wnnfd)$L‰ǎ^> @]ŏ,mu3lr8e4|߯7m[gSxEO|t-]*?y !昩m 菉TpήzMo7>uhw< :S;S828*]Rw ʼn-XeϜs532w(h5E3Mp)!A~T87,s>pTBUMɱ񆸎J-AN&PNuBn'T@iqj&@/'|S%bUʱ.+aEL gCbdqEm45S.I fcȻ^&j {Sa G3{ԥW]>mIv 0i.tЎQàD/xC!4|LPJ" XGE ߱TQ4|pj [æQI+3zJfP3>"J$tɤlMFn7X|JLıY2Vp3/qxU e:ym7Dp;/# ̺cš+_1-@آ%mgsI[Nh\$H*-ڻfVfv/zI8T?8$=lHl4Ti`^ Sdc_~͕;Ɩ֗r͐Le@b$Ygm^"sTp8)κI0sqD|';OIQmq9ilAC"OV2L#4m{-6-Yq>sK@٘3B9;+CB0Σ~zĸ>25'QNRl(iQ4|*Ӱ(O'Zj~cFKr[lS2[TI`UK8?~(|\B之FIĢB"E%T1>LT<R!RXv2Ej0LV J}ϵ\qa9=L9aS+!Ux>ԊBLepPTu~OA$IO:4q7Cm+p-Wɯ}~/NpmhflOx߃8K\[qSa gBH&pp++?ɡhf=(Lۜ=9EZaL8>"&\0pg*RNf[bfr44ѕ6:>/V؍/!Q/K6#R9X$>2 &ψei>HmyhE 2@i u-dGGFO}S?~M9PUz(ltrU4,ɒ-Kr-p1`q0 %%LHHH\J0n*}TGg[ֲs>v{KK J2b/~z2i4>􉆆<#;|57^C[^{Df?'+/zz%cd&2Ɏ(Zw༵n:}bsGܴ`< (z]z5 7l{o>8>wرuб]ۿ@Tf$.&e Y> 墠%MQH0:S˅LkWa]VJ4YCz{SωqhSDB*}]YjM@w%k2h"a 33GM3]JeݠbXp4ÀC'k9k~VZ>4m`I -lYkbj<@)cY%rBѠG u…rB(d!䈒b@5=Ys\HvE'P=aRML%U f*Og ox6.4}V>3}~HmTcpF  Pįd˭zF*Op]SaG D78Ȭ*hT-=O8߰H_*Bq&fǢ]͘ fyȅ6bn0 _=v C"ht S5g!Udr`A' ]f˷%R.keAn|!]Qك=!,E)C¤<q/C6Ng !D1׵,pbK>2]P?aj}gBCQ T{A&b f:0C^P*j(:|"`b2 l{6X l%-pF8A͠I  |6@=^ aR^^wmr~88 :,SA-0Xk8&ut%!׭0,B7+ Z9E\mgE__ZP_f{l4֨c"+QԏBxɱ]}-}<)z+|g7쉵[?_IG?/jG>/ v8q+ZڛNQ(3 [Ț͙vײ/Χ)*| Y{ɖ7gg3z>rŝ˒ShiR֒JsC{Kgkongeum3ҫ~oV;F cW76m\Z%93e"kU*!/mrnhB{K$S'q S3y}k ZG=Ϟ?]O,h>$0t@mjƖ}ЛsNup_$$E x p5H.dXؠ>!]Lyʤm')BiTZXڻc淊ev-g^ T˿K,l!x+((pEOcg$/*AvjM(<8P^ήS_DM- cSb+ 5 [TX\`A/9U7tR4JY$O @F$:4ħ]|RE+hErʖo1 a,ӸΕN Oj!Edh,D&rxիAhPaz0*~`_nfT)!tkCssl !ʺ2/Ug\TJFf 33+zGKwcpa+¦IIimm:2|՗:g~c s`p=]u%傉?ޮ|9_Ximɭ"_ٍ/ɊRVz_Zѝő7m9gOMLUM\sk͙\Ыnri!t\uX!.A͓lZwI=?sJL&mNZ3#3zmL'XVű}YFȵ4Mwux'0.g%eW .7RnJefjf~Ss^w=w.-ʥ7|k뇆G]z2גo6dŢTRmu.CIOh6:<S#  aS8,0 #ΰ~H'yJ-1HTo16H|q"νg#,JPAK ]cY y8(.A9aP`L&(`TX52X몃GC}M"ֵ,:nc?h4*pjc=HfPHPf(t;)Bljҋp|&ҝk˵t776)50]Ƕf5#@= W*tnb2mnnr=ѕͥ?xߩIȉPaJ5Z~v5{y{)~mi8EzE=k!5JkYu….MWܼv ^we(JBy* 3契֞[- k^q$P< +0A RRd"^61~qĘ/a)KXT48_޼ZtQpX!v6S53@ѹF9tjPybqy8?k5ɒr Uj0LqWJQyfB]wk%ػ_=zѓZQP'&tE*TZ]*鱗^~iblaJhz-jhϦ[{WollnjiNlTTkz}y!ЦtHԲ<_cUdwv9PDʖD](b;"Ee!L`rIf*z qyP zE|E "+@%jmeQF+#W/֗e,̡CrESP:EæHhçF%ia &𝎮RQڛCFQxfu鴙HLUKL)uD£hZMs-r0ULʡt*10Q7Be0^gH{3}$ Pb ԣK׃CX6h5 ˚LSt_FҌ ){2Q@>E eTr0-~0F]'@vt+pסn\2i31ٖLm@)fG&]F4dљL.OL.,.Jby24.~^*~bW@y\Ȣ7oOLpxԥ`&DZ&Q5o~ͪ浝wݿT<|k~՗Bii(QV֯ٶ,(\I&Z=/ٷZm^tEwZt\1 `?CuPDQ2T#o"DAR*X#":o~}꣖0Mف^s<:ټwW=Х[o-xXLlxjm FB*sAWbW XL5Db#)qdC[@`{=5 ̪3Đb'fA $RKvF9a7V/GGfPL44X1nUU\'qkչZ5BuNn~㞦0R,NJ8F#4!$Y+o& T&ja 0lȀ+"S H]p\s/Jc c"}T$U H] [T:,R kXف Rx1(AdhiMϻ|߳Yjٜ9i?տ^jzCccWlחvٙB*\&ѱb`;minmmS219[T禨`v`SUa#CkzA٠2.$Cs J”j%\KK\.///R]36cpyT&8`d&̍k?³6MA)EKs*ΕW\۔k5qr o{,3 }v,/׸ ^֫ ԊzrVժ? XmV\^@/bUmrPRQlQI4ªB7[؇fÊNEa{Z\5sg Y7إNwђTe)t?<[ ѡw;KF<8.B쉳}p(vՈX\ʈ.nGԕD@tP)QLdmȃf=nb*ǦaVIZ3T&_uV9ػ:*DBѶw;1dS `\s ̍>՗ ?nVnjLw PJ}HyqVg N$(t$?vd xmnа+7s9N̢"`u FKf h6 t,bQT.-W[ꎛN/qvK Q{*Vrd!<;e Qb=!{Il8*|Ts6XA^u|*i\U ?0;vct HGOn/;.cc_U0bI@ǑK6`KPfL C? YbpD ~)^P! lK|<RBRDWhu(ɀ,h\rJ;nцD^Vu$Dh:.}}fԖj4skׯimoO3 T{"`AuW-Vt9޸:ղuv(FCCrfszc |ˢN:'FQ=/)L{.r-+6si I0?͆AZ=|@D-;4bU׮f LqJ^Ai  `rcwVS(s8}XWB BGxЅt]˥%Nh*WJIL9#'Q SU_ǖs()CAĩ)(!+ Q# 00Ձ˙y"EF#=9t'YCLVZ`Ai@IFw]_j? 6 ] pMC/'JŢ3>xD "?_پ1=1'^ u>_OyhM_sˇ\'CPn(2`sEl) $HH!Ԑ7Qp8c 䍏>i,j2 bEtxIώklp, eLi*P(<4JsT?STUJY1ub!4VC̫ 4H Y xle*J5k <`I!((x{`=|t mXa'K]!] 8 Ē5V1 7eІRdf&ǎ2~O,h-i8Es u~$1R6·ǹn+}Wya<%Z%{Psun7zEE[lnB&O'NGY^ 2l&of[---m-Z.A% 9UWLHwsٙ񱩉Ūgm-ٙ;q:Wvk̆ xO76l2|B1x UloNۺfcmy"I.ӵo3'7dsmyӪ4l8;gSc"<uo1`j|\W3@n4:9W*Ֆ{SK }ȔBGwa$lwH J6r{a:`1r')砙›Xy:מO~ft:& ;}~|aqzjltt㊾/ז (bXSbajR2SOꚩswuxLۼIb.&JnIt]g qjթQOi(aLuȮ'̀b"(((P4rݭi6j,>a J ۩ oȧ2k% I@qtE4}=PSqAMz$)uCvDu/Xd1>w=0( ;р-\d~PLs`ϡ5[! fҐpRDZa7y6؋e}&Rln$DbkVZUzc7  VG: jxHBMۖMb0͙E=FBV b:AbGIE5B;.oȥx0A.5~PPݔ?J`:Tl!l<r`HF)CY'+NiK(ᯨuJi PN҈.@QU9)xXnbfIxCmCQH VFOG6:uE,W*rpf@ +֯CdS-ϡOt-U=ݭdzŪ՚Y:Hf~hc3CێB[YUj K3KKB^rM6閖l>h~^˛{_mH/ݧm3#/n޲mTho6>(no$ڔZaɆWl;4e^߻r݉N?'%/+Oۧqyhպ5.kz m/-Νyշ9:|t|\X^Ҕlo_sM5ϭg`E-mHfS}Յ96y-HRJR5wܩ:9|J4w\k.jirj\  b15! vXJ-H"'XIFcC&W <(7rWxN%=e$"ATpd  Gpڞa'oC_ ojn&5]f<:y؛,a%γ0SMFw<؋EsCI*`IQ2cn9d9% /c/XXPEJ ;:XK7;M@C}m_Z(FY: jin~~vv|^ Ioi_38ߞ|acŅř{W4ӭw徕g&G׮[:Sg>X /hwSUf;eo 07(r)nشo/P\V>7_)U5+65M-摣DƷ< RRݭ4ӿ}K׌|6TrzU3<| vO7*Ͻ\1r⍽/R܄`јԒuR2 2PfbN őչt",D3!%ڪ[K0-pO &XJ l.'ІF}bt$-AlBW ,0w) #AXW4<< F)AͯRΥ)'l"&bX*ES'W,4Ry TMPeLv6x8wrJpIg']~]}ݗzx\|9l(eF$kaȋq@ \Lzs @Xò7Hpe-%-p8Fpk+FtN]|Q\ ĐwX fC .;W0ͥťЩINq+Xy8 Hz}4tT l,=JF {MĆ`C3uɠшCQNPЪqx `W h.m຦$ ME\enIw 95NH@RM_Ǯj1HPĢmnIz '`UPq7<'6$=,F gZ蓜0YEBEswwFKe;C%k1kS/gMݽEk­;n: 1݇C[gkn4s3~ѿό4囶ug*uu_~Gi#D"٠$N.z=w[ sUjnB\us3#S|g&xЂ80.(p3)NNN JSȧ/^ڜ4515=8`t ")Z*7jR\cgM:ob[p8+^gGNN.V46\jmOg*j_LǪRSsWGkFQYQZq=4A,Ce.PE.X1krL$$ƾ XYkH (3B OϒdPu@P ʺ'+t=3aI0\kzpvb];vOtdkx ,{4|OX |E. nH4Yc%+!jdT `iu Epț[4`0!A%`5}*D p>dP@##cUl#]j^BÌjrO*6$}A-]qCI3u֫d<' bFM9Bj'ai, <+*@EԦz_Cs϶G!#( &/,^~sb\VWڵNFE+RE*p0>1,l )8A vMPXOb( N 3`zbK7>)U ~ 0[(9I]n\b3 ЧG:/k0i\dGMvY" 9b(1ڑGNasgu:rXfIzGTK `kɦoGpPsyjƆ$'4E)mt$9oxI´5Ҩ+YuEr0=pKY vcFak'R>Uܶ ֗Kf:ЬR*֪"<ڃ8R>UlQz6^j6kk~թUB-K^_}ϠVLW%3C 3s'K.[}|fEKOwwoEE$eU3ׁWw=Nک jZn=mJrɔ+g`ەUFl톋o9E-a3n]1ݹ¡7\yG.ېNj1t}ALX7 t?C^;qlK-_4M'S7=+/637ܬ&ݯ;pT( m-~OcG_VDFàQސe(m񦘧<`3,TURx̪4Xs;o}S?v 㾁mMQh~r&%+jccdU婂u{/l|xڋUxO]qMm-^>fe LANjH*]esw8&ABۼ1͌KZ :v׉bhD, "#[xDL>R|_?^Ӊ:~#3A7a2P &Fjo)e#s!of`VWÄCpd~] nPu R0&ޥQvU֕}HC %iEz3;BvB|6J S]'zgߡ"fASpvp( ǓmRy, |o H41nVuԜ1z敿-*?ꃨ}nT|J+[eH$觩LN@2rr5ϒ5w;*,EW(`5q7C!>F3I*sd'1ƁXߛ Xb 1*w27'LRlʧIVry#džcs'r['ѹȁ"tkw{Yx}]}h̨O#dZ2Oߘ攡 SSStwrrϯi&Cto*Mʵ5PWO .p /'NRvX]/Xaumދnlkm74Sazyix IsǽKւp ~nio4>{?sϽ_vFKo}n>Tx##%!n]ەeMV:錑IKDm0?ybR c4@ G0_}u-٤)|5/rlZ^oVnht3mU \ҔNUèc!pأGqH;lAEb4;@2qwgcԸt l((4i {|㵝;dž̜>߷eB<38%$%&TI3m@Cc0bۻ\-*ىBIRUciXȘ].R +J>J H\5%Q`z#L@A ues!Q `̃ ш0U!5:2abB7tZ* XE#GuvPźN̹VopT=P, kNz ͣ+}fR׬o vC?M }e":)ڡT`j&JR+D*XAIvD,]' K/*tLdq%FAWIо#_1z}td^Ib9nH]!xqzԅ[ fg:PW"=06 X\ `,)¥`9XDMYE탁Dw׺.D`PG*Pc=ARt:W?pv~Zp]f}1B.MtȞ;7: k:f 4! w{6R#]ypW2ۮ{huW5dЕ.…cS3c?ֿ*UYLZ[W]q[[WgSc6I鉉{=~b#G&+t<rt`PpIs# #bQ>ցEKYhlp}Q3(<|E@A& -3&Z`LIA;TSTD@ >&@@'"C WF[ קzP\ m^T5jnQQˆaNL359@бֶu}wܹ4Hc`Dyna0F݇X@a Ӭ f$@G2(@Ƣ 1+)”T/9L4I2DfcȇdĖXwPFSu$}nYNWӱ|B LB MqsRfdNgQ!Pj[5 ˲}؉ f*U߸U]hy.^w奔:-ֻrG3gmhl3;Μ/.-ol5/zuitt+>{fbɩ :g-=پk6 JyuʋŅ2hŬ(!J+n'><rhؤ]t67|Kq`Szt;{{)p(?گّ.%Ex U`*1#)T^-E/QN%x(Vn3ӣ5;beԷ9tŨp\lf) C"qnp" h^? @3`g "6j,ʲ/G-2CW9VԼMkvP 8n"eU>\!vږi$턮Q4ʲ!Z`nGϜxU򃉭Uw߽!^TalLAzA_;Fdω! qT"I}+/,RRImƙ_"Vx L87! Ck{? Et} +X57dF\l犟g ) j1́tdU[T;xy5f.h ᕊeWb5h~3I Įrz.9$QBF$UbҐq2[ci@3S*tH0:!1MڗB[W0F 25Ll6ՠTѨaj,D#3D$1`KpLO/q*kBc3ӳݽةag'DS3~厗6S_gTLҚ޷po&ejU[fYvͷklqX(8t63lKWK\֜HiR+3urxr˶kH->𻇺{+ ޙϴ[B*˔-јqOutOOO's3GZS&hS6nO/MS;6]qOO]Rni{~t]o"^uTύYհגoFiʵe؞fhI9o^50UYl̫bQҳ ʥ' K=z"?MWLX.QTeߡ0-/M틓mmO'|ӟ#%do#+WLe\L<XTX’e50bPL$ {!a`-58\&u?}͝?2,fDg%c_O~`[SRoiw7fi1ztWW̲U_ vkWl]953w"-Ū9\*^pl.%H!`Q2pV0㰳;d UNcG FOHk]K0U#j5uEU7=g]Q%TtSgI 1 ElOH{1RTQhzjWTS0OyTb:lGRSPMJux@}OtBF182 ޻w7 oe/_鑦dKV~}8ʬl i'BjB)n,g&E|hqS)Ne9$A*M3 JL01dAxjK 9DoBҝ1|X[`\kaBIvX;;3C_!nZH̄]Ukt[KJ0"ۓU*G?~&ϧMs8ll68)0D S<ߑvA[.i&Qs V!|RC5}a5uv-00x̛PTE]`b#=1ϖfIEc ?׳]tf \^ʔJP`- Ei&DR2h3 }p]Gv[&z;>ůV*‹ނCJb>% @Pk s:2y# S΍vcvA"piLq7X<~]!>*XS?MGY"  " Ɓ[IJ!?z]w2N(t o䅗~lȚ MՀѥop拇Zrzq\/|R0Va H~V{y<l,Q{M ؈/%Ŏfm\rl!Aܕ;UJ m̎?j*L\\:xELh4 T@771\N0; ;mR٤.8@G,<rrEf+G7BٛumrA7rEq1=PqdQXfFOcġ]SY3%<șJŦPϴvuR{ƵmT6GhUg'v>pf=\VW~49+n=}g^~>~Ss ߞHtv8˯64o]zQKv zd?3u{WVi兗zC'9s~4Sg"5^6ի9o!tKw~讻ԄN-Bb7=8ORHs Im`רT,8;2+[)YVblH̠AB'$0]9+O  JyW +C" ^pTRˆQtU:cAh?~އkౣc߼#_XqJq@5߽%PlfEjXUb !NWV#GGcEU- :xof0 BiBq$z2q#,aeRWRTC R>3b dQyTL<]Z\8TJhY5zXQ{a.kza첃Ae@zG~D/)+mXFޞUzNĘF +!}Yu 5iU|'.t2͍\GwoxWK[s^KPl^FFN><_oG/ĶK7?z۫SS}TMΗ+cGCѪ)k 6PXbkmYVs_vksm'ko5fo8b$ͤ nn E婊aiv# `Cǿ}B2"S8r%%)c|睠:?EeI!dnVꞂ聇)kT}ee}9継;N/;ۗ݅eAtDQ!&1OjħĊ15vQ"ABEmfw[O?"=Wu!),.a=ޤcW2"$9ET1*˖x* _Aj:ņı%!LZ1xQ?²\鬐:WCK%_!ts1Gߚ2>fওżL[|8,Kp9W?;UP60hߴ{dzZ3=;&50T[s,,FsTuM'O\aw *I5)l E5P!5y)fgHm'Fqd=FNA!>A1S`x n2@'k ,j Qz ;jTz>T&MH1ʆ}j[ĩlNS BB#itكW_rmMn:Ŭ@'&{OLLWBʓ}^|ᵯ}P__gGg|7?~Ο[^}ez|统>[]_ܚA( ps %v@_Z. nl}n*Top RЩ^xֶz͛ϸsl8S#軔 Ɇu;ې>yc\ifK JS!e0RU-Vڕ*qَ3,utv8R\g&Ko[z#_YW\ 텅zQ+:q=/4辢`S /:E}_)ab7a2o^55FSU;s'=(u@b2C)€ ;xla Yw= S 0;A/k!Tض ΆrcnhQL4TL4`Ibqӌ3X;G)B0y޸փ&w,Q5B:F 5nϱE7֮,ԩř=G:tԱw9L{`˃}A}Lk{K_{P9sɊ fq?gEFH@wV6>UXsnz[l]~!D0j}eOWT¾"Sjyzf)j>|t⎝|-a- <ue#[00|l=RqPu -O$4󋼠׽1g j噉v~RMVU'ӌNhSG&-\gj;;{㥭]r=sPil$C3͂wȸH5 x'KHa]1!$C. ;QM:#̨[ -!s*MXKi}vwn޺AQŹ=*\>F &L:G@3CkR\Ʈ6}g3Ƅ<~Cq55(\ hBM 8M K9 =u !aL͖tZ2- fSiT`+LFiۂRC +KE{f#F.$,aac!p nR6U[PJQlXZ xg~+Ԍ|:@ArʭU82 LfX -y~cErj%'pWhaK:ԸG F8#Vhi=)6bEiݡ;J%dHQ |BϷ[οlq&UVv[[`n cS'VLg [yU 3ijZ?ǧ3z&Hbk5ҵȋMpxʨ0TY%@sgkA Y>#(؊Gm ɺRa.qT=lkm$^+*A* z0ʺ&7dÂ[v8Ed֐Z~ e*"~ШO X x=K1Y9 X`tҰ?x3(4O2dhMa:?@&<  w'>֧{>^|΢p2Ŗ`gly[KN-[Q^Z^~n7FmXciBо=۶]|r 'xfyA^~ō쌰I+`FsOb%/+3fs tؿ榎LMvm/:|GWO5omje(AX_Uadj)UAVS[= Ew.b@Eub1!ㇽ}kȿ;I700Pl;6tsu cΣoЙ2!A hϱKf|[Ӱ80@Q1UXpHY~IDrj?$b1IJEgc0v˓OԒsP?xNښk3WA1 CŐ)SuCxaplVN, ߎ %:ʂtF0lle3K%ms9 Ā[\ *D1 _D*qHJrLT8~!\T `0Fxmö/ϝʢE*r ZU6% 8~S,^&@)!J0FR R; eӸ\Yr"* tuxk Jr<ݕK5Ru8Q̖RE N2d4k,5k*iy$(/,$s>F6b[̃s>< Aт`ǫ*]=wm7֖U&KxJAfns-[֏]qEϊKX:31Eԅrm:B bJrPWh6RxTeS-zfeHbjRDfTZ^,Z'%(Rqp> ,ph8m'mCsBjy6z F7(z~()hna|uS(`چcf*eVEe*>6=UAezzHB ݸJh=?k;s-ozSO_wMkm۲mS0;֖Nop+_ 8䒮Y4rdvrz o[Ui8-m_ K3O=r̼+hz.uv1_`a7R @AѬ6R 4JЯl޾*nXrj((2t3NZsW:8~艓}WE"=FF!;@97%`q.[,|*U2ʩr%zX`+.%]GQ76mʦJU,–FrV8?O=Qho,8_AղZl-tQI&w3ӧ[ZZ]@,,1/,Ӓ MUVMPLK:56MZ ]D<5 ؖsمi=cZ\nn Ѝzc~Vª504P:E )դQP; HD F=N'ldf:H-Q&bS`N/d!df9MPsk7;[vd`gJ-#LP+,'0斂ə^- ݧV"^Pm'%5L 1`Cp(f3:l %i8"T&ҨBL!U%*:ֵc? 5g,o1 &8`vOW '_raݤںHYJ6o{%7#xp9BArϾj+./MA.>N0eMkTx*J%$?/"(6MB7)h)-*@iL3S( 2#@JՆUD.uqM޴m@! @{t)A<ǥwBy({2] 8s el70!]ArDP.VVa% X<6Ĩ uQv {5,$C/M8×l\5ﭭ]k3 R|>MS/#/aI+\tohqz\^2ޭw>]_Vvʕ+V=kNQ_rٵFjss3;j}Gן& LCc SSz@_Ƥq=MTaQݭ-ݫV>=ytW=ȑ㝾%Zꋕ g[(2A$~`55yܠRXY', #R٫u*S3]m!2,R "r;$/$C95G 4"L9CєWp )Y\朎u^(IWC^Y`BaiUy)N%浣g d:ZL*rݙCmo_njv95d&.,9E͋ 9X`٭.8BucDV6ηmZtҞ#p6nwl^" 4UFdZsImCV ZՍlr$c TlǑ!!f Kq 38O5^vA > &นe%|u-Gf¤?;O gvl6,^ \GAnJƞK pBVvKX0Cm OJg޾F0kwx[e#) *#za-U]aa +&GSقVBEy^&qŠv:^ /yЙqGb s&bGﯜKIkjE0bhiMqt.dbӶ!\`>z]O;]- ?_JO"pd&jABaPtʘv&H!j>2:H ¢d&rqЙ}x&1Df{/ j7(kr Z,ߎ?VҐ)}+!zJPzԠXk0QqFa *gBz&=ȧ@.ЅZLR:=lV>Sf@,nE /āfÏ]n |ag.~[Vv)%zivkz8̛m䱣{U,?Nt1Y6֚gRRFkESfHTvag#j*aJ#5MrPΎƫ~㰰0Sh_zd8y|b{=mťŃ-΂hIO@9*ʖQ FFD.iY%L/8 #V@mԁҊS2~-:j`b@ `UI$&0q)uՎX\Va$w[BaQV8R ݈D,G198WCSDR`إ뙐ķSjM^:U GFTϣEJ3ljjgա;AXSWj8&%pIڻWkvB*yO/oxgo׾慙Ei!G/G4Hc] &8Mg*Ӭ>h+0_{#6%fi`~Lg u,dk6*{lحk' π(wkwwu $# x6NY'#zL  VhXf6,F4]&oa 5X˦0cbtcj`P(@ظh8aXj TRUPh@Y:R![URiEg -OdrGF-ӧoؚfhh գj׽ኻ?Xpwiet38/r E1~5*пrN7-۩ZXZX~o'loSKȱۺx5:E{* Z%  7Sy :]%4tS=ҭPzKQhbcB 1=`0evTJ&(Y"61%]ua 8a 16dCEQcinېbJ`WB @ ETڮg^r4(_6" jήsϺtq4,؁%p6G|ϴXj e;id OUOƀ - ,pQ:)qߜ'uq\>~&O7A=RF8m[Lg8z,њmYS$ɖY0 jǰDV+jc>ԗPXuLU #>G9P3Y ZСJyclJL7.]NS>*`)ݘ1=ABe*U1 $|f p4 E !o3H#-CE ? HgqBJue~cx"|HCÁQb^T 0bu@e VH"= `cmfMĉI)bF DkxՈ\>-߬=qߠfT.^ruN\ܷXYZrORknַzκ7ηRrbf*CR+fQ|J ?>+2Rw`[Q*.D܋^Tg3V*+UtE䩬.dZV^4=03[.uwvOM J{^OzP*.:K/408yˢo@F̒آ0uiX.Xt-ԈTV^yUBN\w>50Fw)r25n)lOE`ϟƒM)/ؿr}(vƩTg0qfRHv Yj =w`Z2nbC9bt}ev89DԳwPsz>=y zA)ڂ}dA!;b<,BzVx^0}ML dR7ߘ˴uN7jn00ԆqH {'xkmb\U8DdLaAʚ^O IL(t*PatqaAݴ CK؞늌Eg5L^@fL },j|3gZ%!4jcU#!g6eE% A=ڦpu[8{F8'Js.ˢ OMz%m26PoXwM&QF@N#?eJzDʒ:P㞳X%amC3f ) 8gmKxƃ8t+-Um*{_|ٹSa/u,0v,xI;oyTLXzNӒfgS3S]>zE15PRP<ϧ# $$adWX&ۡ߃A 1I zP(ves'N< OO fBE*RlRH"MR1(":9`/S[Կedcz(* n@jf B $y @I,?^&h5l֛ǤVd>"# uDEm5!VZ-Ωđ^ L뇿ˇj==cg\}孽#<=ePqVN*O={MC]X~YY>u~|5W.\,ecRcwFrȒZ>(. iSt̗ S jFRӎ?ݲ"۶8X_ië7m9V^B:3 1-ۑIa 6XՂbc(Oņ0["?L0h +̴e^e25J-"Sqv#w?AMXO{cKl f&_Xr7?A`. ho*ċF-+6IڕkqOϬxJoTͶ۪鍑MzapX ^غ2s̵X"bj O7smO3e) \a#]{֡ґd9'8ņ*C>9{>% z~ - \)e,κ!(t`1]CNW 4pM -~Ϻ6f0<}/%TGc*G;t3b`;EUńtֶ5l*tP|1:e'%ՂN>ڃ0%EH߇ΗsJhJk^;u^\&hkj}pE]??jOHQNy.qR!iN8Qh¼]`YНü9Z* ,rק2R@bq}08HR R\G|[|:ttn.e"N5ޤ,G-!$.O8vӹ~hhAR>頱I\}8aH5&҉>'1T{GY;Zَbk{g Db)K~,sHc (x>|&Fs: @Ymxh2*j2|FQ`cE趠n2@ScA2(F4/1YN/ XN z~dijȀ)+,%F0b$΂z y=|틟?S'߳jdl`dƷ#=Yw+e72apٙZ. X NEI=BX=L<1Ej0ji)ZM3Jȩ1V UΨƢ fC؆-yl-ӳGet@UǪ2bS%m<)͔cY_`Nl_4'ZKAM@Uh|it^Рʍ)2yO@ tݖ5LHl8o1"a/f )WMr^3o)g5 'VDoTzyje F |{=Cr&r# G^BtZU%P±+M#;.U|!bs#x`m`5NDJbCSTu+ 8weH lQRTk[cvkj>}zɭ,Zzu rO3̈ $ fid&lT͋:aH~` 3`*nXTBWLA#jW/ɢÍIGGJh;' M3"c ~ I(aA>6uxzJVUa9(pǨzi 8a-sQ­$`Izinqx?oogmy"}BEe}؞hG,jUXݿ i)^B)P]@@:.\2H0PqW1BF9bZ>Ow}WOtg"A @dj‹3Y93Ӛ(i 'ǏN9~yo3:rK_=<:Zzm][^Z4B 0(B, TzͭLM5T X(;.ZحaYqYM]yW/O>prK3Aq,5c .n8Kq^,FF~2'Aui~jM ٝbz":~h[n'6yNM mBRtZh,ݖ!+2Őj\~ x0?_7@5 ؀{ojKX6 ߿pR{[pp`m_S23T;(Gń_gR[cFңl1!ܸrPn$^#GzKv%[17֓ҧŞhksr' \Q٤e/8~j\wkΑ4ղУ((곧FWT/ij^!zZ7JBR1EVgҪx T V),+@ {l ۦt@b \\Im6AC xPC4u?Bd-4r YX0e0ԏp2EUҠz@&ead,CsSLg  1)!/RL]y'gZ5 X EJw$mbvJ4VE0K$ѲHqLe[EΏu%7 R$Ɂ*oξv?=L´E>][[iQ+J/={}Ȇwwuw[H{4PfA6@gcizuwt_Cf'3Z]* Π³BgJ UL820k|LCA?^MiR)嘰 /:H9kjDe/H=bq $Vţ?6a6^/P#`2w='Pl#i`Ϙl]HBl x>ׁO3Q$sՕWU4&I#"FIS`AZj[tw|~Ϯ_޽syM7>kiq]WedSqmfx'&Ue氯}nl=Y=l7Vlmɉ .c'QO=S]mt*j5Tͣ)ށ; F"z Ξjx\'3S8ըvr%HF))} XZH+Fg}xů쳷B瞟&>ð!ŐD NcUMZɆ0~р¿Y ;jYMYTq,T!4;b`c37A]z ]%6 #~Bc)NH0 QPf *DZ,3SʔC0ua?vRȦ4&7,zJPih*r`~}C;> 6O͆!S:μU>& KRa#|ҔFśI >2 niMLI$,=e,Esjsew8pk/|~ψgn蚛>kغUnޝUo1וW,ѓj*@wk]Q+sn[Xm[N)wvv vtvٝ9E)aUQG\Y)\P]C4_1P2Cd )K`V ~!=|{dh*^/X:?NLb 4H bFٖɚ,9W)!ά{P# VI0k ÐQttݣl-d[+F EMoI׍V5,S*!EFȲΒK$Wަ %Բb7 5#G&07HLcM(ŲvB̌ kp\AC[\I}h$@8FHd B:q1i; kyż 唂55&?0K7X 4aݿ7w䩩&"Id5n;s{]^j?y<fjt%쌈fafrsU~ ؎nX&!HIKX:_yh.03 :>5>:ypVjRP3=)tw([zCCvdKkzd^klW`˙81L[#C>JXX G( JT$CnqNAW{"26%l xp  iS@#1Fd*q`k` At-lM(g2z:@6:)V@.CzVK;ya%r.= cK5}[0{G>_suoۭ4Rީ,Af,rrb:qR\pau @޳ט Xjrg~û;s7^tbl5ع U v7|3+{g5JGgP<xĞva χM_1afYCIFP{N߷sSl[pkw[.tFS/ o iXu0ض7 -I w[,\2,+`x?(ԃ, FZfBq؇& YmІ&3VBh`aݥ d'5ULHA{.)b(Cz;B_BgGcA`w@ίpUGI' G *,:;=<'lJH~رUz@[auЁCIuL]L&=dF(3XfKNPmOn(SŇdrrNݩ]} ]bI=nG0`hIq$rUL?@gHbUxG"j3r P`/BՋ城e)`ꡄI󤪙S6C7Ƴ9[[H(T"rt!!"b7) =5I}D]uV]zwܮy?4˶_&EV*Ct}a*Qz1[5NOO/./J]Ʊ@HGXlPՃ䝇Mh06Ë!Rעqݵ2&>>=?lj IH 9BEj" jr ,XJJ@K`Aa3nb/*#lmꖡyi!Ɔz;c&Q,5;xZ`4HaT X9yzu}/~}~ׇn߰aku , 2aCZ(!؄&oPړ9ʈ8!A&EVo>b5߉XjAOJ=~V $=uO|뇟sO\m8`|깅bG__T=j ,2t;stW+COӓKgFGFV}{;[[kEsOu^eh9G|5B^2:6RD_^q1 NN ߲,ZbDFh0JHRxR0J ` Y%KMGBGٿ'{ HEm;w׼V֯c\X^k! 5e<^ "+8dӧNzvG[OC_}W|Ι'N}{w?r#&NP}TcEa%1jՍ}{>;v<Ͼ~wρrL* Ӱ,3 0VVlYr׬^{-Cm(<;GǢ֡9- ӑr[taC,Tuª aM@8AiUs  /{a[R;~gL (č[%98|"qCF`2 NT @5S UB.C "SW(H52h䠙D&3נ8 CٿpfP~?7o%b8@Bo?'Z?vͭZ֟{IfҡrDZ$,Y~T Y8"O 9d,++L8|`j~#_3LMGrfK>x5^<?\{ϗB{Ю{%s[szezCmݽCVӛW wtt ըWke!T@ 2Ę\tj#`ڗ }{jM[Inz\ҥ  W"_Oaƥ۸`:~¹"2&;tB(ibD )IqDg,0vj# ] }^1\ p*$d "Ζ5pG-ЙT$Xq,rͱhD4yZ=& AS>hLlI-z?I Ιw< kcdC[2\cQd5{HAy]@.$l=h^kI21(0PO` . !l*=:/#^S6YZ N3*RaNfJCG6RV ) 7tU+W>kgOۗ';75ꞠD3Z_+xs֫gz-g꼭go+KA2NONVUmxW(&Qutv흷_H}Uj_K'ַK>:3;;q#G^>pje)qkN0vmQf^5vܑC O?ıG&碘X>@HmF:vKn|ۼJͯHٸbkL^%[F2Ҋ&P_ag>_{s'O= k BU"5D<޿14__Ќ~mܙFޑO92z5'?8:~k/w0Y \:Q]Io%@y@b*ur_^vna0 D`Z:Ҡ7$J~.~o"t6[dV0WCZr, "LT1@CE0OV@^jւ%W\w$1uC SkN?5KRz ӏw$/]mcШaŊ@8Pᰤӓb7DbE&g1v]0#.dG5d Q2(0QPf>96,%Yr[+꡼IR2˩jGL -3, kh&fx4[A,TefCP4`uʡRq Q~IA9\l4B7;,hzFH;Pc'٥jXxX%n:NƩ/7:t쭯=O_q-8~ȁs3A=3دVغkxށblk_z÷ďN[PU`|W:Nn웙ܯMLt|UVSm gl횛z'&?^wpfL k+nfffa莿:1~rq~w/ώ;:(N(\#ҹ_Rvr0 }rxք jrb2K7ޖ354V ^SzoJM0ł&*3C>u=PiQV.##͌QExhDz*ncjb|Q aK5!j$-¥υ2et`Tr11` +*u.E 1*Ԍe`UabIqwzڡ5w}]Z X m4ng,OSRZUs/ݯo~t-o*ƾn6H`~BЇ=RZY;Zb0}ӱR‹O?wrv?Ief=c0ȍ:ZU eW^CXy z2cݝ׾ ak5jGBG+]\ښ~乕jDDr=iv VX}8R텰ܨ6)kO O?]h24?-7AD?nuJmўBVZ!2QZ{8:or>iLzB@ 4JG *Y{TUqHB mfLy΅üBsS t.K`b`L## AXń9 0kP!׮ & sk)2x"؈~$>8T"$oB ƭQe1*.Ӯ 7IAFPrPIts@H*3nJb(Ěը1Py~ EMG!rX ]\!dIBNB ?P'*яUlu:Ϡ J-BYJƆ &̐S SɌmU荰'A 6*>XGVCF3N#صU+ϻ`^7_GO:v[tiScrI긎NF轨t\]ÍO#Ib^P-k>co}e ouچb0rd+~-ID"‹&ꇿ?θ ϟld=vyquuĜ!vpY2eAe@j⏿g3MNۼV&G k7ڻigIpbj2-;WC1Jy:"`KRe̎Op*пۗZw=J:!ڶk `;,@~ʂ2tNZ\;Lڀʃ;f(('>J jW 3zvBb! f0vQC 45~9u3Y2tl+A fOۋ: (KQ0/ e*MZ <(m)TC=yKVx~q6dP%p.Z/\ݫg2AE?„K:z/,UgLE^t"%2g`fr=?#M?uϿTIh3蠄`d,Pze;Q>oF`z$c($?hhEkW g˂X^Rv \#m QM] A6^8դJ x:ZT %]dC\DbfN$> ]dJ8kK#K31vߡ#'']ɶ;6v_~WٺPV]R٤Ebxb|!(ã''^L`MKtU`*YmW 051dJaBkfT(B7(#5 ح. i;$ 9ӌL` F]tXAOL$k]GY@6|w|͠Q&Bnki?g˷erK{.j3]WϿ_7GN}geg!\b*`K2SX%DfSJ b:.WlLخo Pd^]T QU1uIbT4 ƒnNUV ?x#~ /^q :ؼIQlGW1(9C)]tQtnG3M nnV]J5J3cSCLJssSBhc]sFL0̫UHQf-pcx =&dSf@ Y!-Qg]Ы'1ʄ% KbďplqTYꞯ =iZ~.W60SRBP)M <{޾SԭoF@J_aw Gl |Ç՝'6RFA4tIMCwr{޿'w} wF7l9"o|yw;b\3$7pkE=*l;H M7DcT,Bkvb<;_ߵʝo\ղp!}I$giW󹡉'NLOLNW%e;vJoMVo\ YU2u=R'MϴɻטZ4+GdyfE5̳D[5${љ -Ē~?xڦAt>dt:w};Ʉ|سt~w|uIKUj##;@5֟>;V:a$ۍ1YeÏr,4C'TL<32;n1b 2h`<$ IJQО;wǧfgU$!5&dU;Xu6Hzof8Tݡx(Lo=+1K EH, 7 tP нLO_/q̢/lX`t!XY5ݢ4E)e=s DUh8Y!ŧĻom.2b4pnPtz%sdNjG?Tջ4EצON46x%ݹWnHQW)W)-照xYiى2`Ov'JEЖ(K)x)7y4EU9pUǾl栾˳=H$u`z??H`6L%aLbe벅R571~GʉdgVoқ֮UrVI1Гs֗,곒-T<%ݝUyMHht9Ch󅩹|kf' b: e*'Hc˯1%+C;1NH-L=t2(t~^s(hJ }Ňmj=jޙ4%;eQ9F =KҍH:zemzٮ3F KO1#!Gq!Wdq$)QF'.sO!q)DcLV(~'v%5ן}w7N棟HjO]'-+/w|/Z;;Ňvn>gU~]{=-n]\/LM7L'׼*"ƣqLk0-*c = e9bXFbkF&GFGN DcUvY>t?/Wldە|57_c]?^ۯ}>$S?q|a!3<0ᘀ |ef-m:L\zt!).mgFI3S"K/>v`s}ۚjeҥǏeJH S~35C. oQp,R^칎> xQ,QXzR"{c_.~'C+2D d9RI0p_B|lWwxÇX&PVLt(qA |mXTBEQ#$MO0>=0t9{ZF״z+qdB\pD$C-^էlF}^$]KV3.5¨rgA`8PMCWI8;p"C9ĄQ)y%0ˢ#T)D2EV1YWMbIGLǫe/WjnSZSVONJ%Kzzbw 4G-=9[AAݐ `ю'9z%:/LkڱS9gj|.lPWU&bB?%®ו2.PjìJh "f1\(ME]V8Ҋ. unjf#ɤ`:60 \G3=/c\\eT)[{|$%ڞ zTٔ&:ˁҒ}-OFN >1256g;|i?biVJ[Dl`MkGj*?Й0wI@v}ZqQfQ=T~Ŷ7T8Ygb(dЙ:O5Y [ c ZH7amH*LGV`Fn%H3SSpco+$̦dT}_cMl:U(GW^ TX:[.dϽSbneV*7}ְZ-˔Hxv "F|䩱tTC˜K( A|rX[]_X,DxkBU+صr UHJՐP8rxd[{w!(lh'?ЁىɢUymܸq쿴nWknZhir!`gH~YÈ34c.>U#`JJU vA&ZN9 J,uZޔE"8ؼ^x#R7@t\ l D l'P|dlrlx:;Z=0%:h %MUGF&gڶ!DA(ܪGnjjUx?zeqGs{#+zNsϽמ{~%j]FxWv\ޖW.}Op*eU>AuRbhJ!@.Z^95_ufT+P4aYbU9 VCaͤ,j씙NԄ/>2pc>L,T[v-]}Zݹ0[JV`0.|7TAwնz-&3V8]ltrvVl}NJ=֬/YC?~9ICF)^Y D"*R22$=S5+CM-+ߣ">*A2B 9d.htTŇes%N n&=':Ԧ*Wa`8ŜUb{Ue]CSG*@8(}L#e%t),Ɲ2S ( LJ/ĖT*.]]*ȉSN 1vٵkM_ tSJb2956)s GPRL"DQw|eQϻ<XfAgˎճ~%h|;ߤ"!-|0 $%x)V&qabﺽia.4>ﻮJ3? Wy"A%~Z˸Y֧oطol2vE.jO.iZuѽGF&+$7nE{\Ӗ%|}#\-rcNFS*0Ar`kZnzUD&Ѽ V<4aqBʯ2H:dM5kQAsƯ<&ǡ:3 ,X{H5mSU & U+}H+"hBhG^ SjX- !fqW3{:.XZsF51 J -ֵ4$8?<#] Vn,>O'TSN*KO4gOPSqiS{<-[[uLd3rNu]4IQ$~*01NPz{BVh@IOY[HD nrennrb?phnnbtkk6rosQGElP(f,1A#fʩ$ʪ##cב#CjP[ݵ+]RNB>;^K2ZS|IAGkADŢ4 a'e+!_bĀϞ,CñӍBwNaFuHDfـ5y*u %F(5gK`:Rxq|fF*J[M-OBg?)6i¸eQ fu( {"AiV.olŌ/ۗC٬)O?ӛ.:ֶU eCf7o23޵eBJ 9[#1=>Sι,Ć"t,C^Ϟkv-j˦Rw~3}2(9aM\Faƙk{Y*)/|ǕUcC8xI'OJej@z5t$ NTzvgswy=n=ʺ=-\Riv?מ9Yo͗vY3ZgJe F9iR-LXl 耗@\:T'6Hf]L ̴e~YL=N~c}?05=솎Eش7,\CM&L]) (l̔:8pW#_x''*WеpɒW]b๖cS/ksEl(]m >jH0Qc7nQ)]S^&&Ƥ0R30B_ Tu:Ut 9ApN׾l:Ayj3?Oa۶Rբ7sĚ[ZEӣHnnŗ+;_|f\foP(,7я|߿ZwyWm>7=A?k9gm=qYz_;So;X\wt',ϭI3KEc)rL]BЇX5KgaKJ/59ƒT}?b)V52ƿۿ%z>+rjK-{_\ߙ]ڢfBs<tab#5OGI`v(XP#MO נfZpuS蹶`-joB608<PfaOljH-̳P)W zmgJp\@ :rI$`GBHE̬PfRf"XQ;*)= :asiCrk6Et|e{/MuGV.G/T)^IQM;~5|{YM hۚ[+_-BcxkpB VH&$ aȪP* 2W(1EDRgp{dظfoa5]u V@ P:V5WJOAjStR`Lŀl>_~{c쯊Vz巶w44f2HU)Sȣb3zѭn'`2Mwb}& Bէ3I7Ca2p(^p"z&RQS++C^rU@!BP{!eP^u+}x_.nLff#ׅ`K:w-o@Paؚ$ZB]ɁKJ5K5O'[cz%^0PZnAѪl.=;Ͼ҉j } |b:⺂'ԤD]'rX>d&w8xʮ},]D]SnQ5r33|c]n옝<|WL'Yx20<JF:~];ZW~rlB/LoXN85=o_H9L!\J˕_>rpp=gĂ_<ߩT˃}ImOi~ލx1u8gJEK(hrb"jqrd་.o U4)ɲ`,YWc`BK) Y a#!lc%ƵwJMM-n>ozgoXRPٳԙ?ce b(ݔoڻWcҕ˶l+ƇfRڼea 8`LU-hm7ܙΕILW*Mx _5-nT\:n ؄+y3<ǁ(=tl @ɌMsTpTQ߂:/fS屄l{U*m2;2u`X9q0V#e1ıG  !"RdXWUR JV2A6LRCBhc;ED-]a B̈ĎH^y:W35%&IJ`@L1#2}Ion  $R!ƃ"xl,9 2 nCӌtO޷]]QP-8$!2!|_tȠ*@>!*GdO1AN8X}IM&E8j- P -;, LkGPRFh˪/C54ջEkk>.sSʴP!V.¤ZbT&da,RӠ.V%beRgIɤ.L{QΩVƇspK9L;2?ΗC4SgN=t8daC_\tjQS;Azgnh&/duc5 jA:iؽgOX,0t-a12=\nZ9:aMGr/S~Rz*(USAjR&kWTl y;b濥YjcZ91\aS|s@BAm#%3Ʀ~_8ge۶e~0R&Hv~j#NKw咖BVe;Kf]7W*+b,3V YusƺQV,Lէe_u_?LNnWv0׀/zh\ ȥb"ATn edY6d-bd&*tTUwPW2HTT΅Q*c9UF7a(+[A p ,TEJr @D9[.'VrrBɢ74zy ظ Q%u"{mE%543KM.;uW/^ wrbTP5zuժ Vq*TC`(z nYN_3ְ])39t#&'l/v`lU@{@a*{z}_Tpa*@  \a,>DU!]K{6[Sa'5XBйfD^M촩LLǖ7zO $4왨hBb1!$(?32|聽{ݷ?%w߲i)TG[[s{ůL6Q;|`Η=_89ڽ`Ŗ t-Yطv.H;_:uS6nHd{da&c~HUPh:ٚ22rDϊthAY6qOxXR q kEBk&3Sc(2?M8xB\tIP^۽h灳P,4Z6g̤D\}dxT2 s`?lji9?P5&C6V̧ßu{V.Y۳g®jqn|x>̐ TK#Io;a솭00!;P;"S Bmv+bKK :r;6.f躩RT=1x ^p PsdH %L:]F=m*\~w)YWCVY#ya8 ι/~ 񧓰!bl44zECS*żbac VOPDF+lkTlQ*n鞋,Eё l-F!_(!`*EIwDj Te:j&jmk)zhѵ7 :`Sp@WTq0H* |p%EŞBS ID16A)LB F)S88hSʅ"jD~)AXxYU ;:\+UArgJ YV[f)DUr}hflJF ߏ n-KF|KH@ҳO:ᴲ<E5k,_}7]*2!Yǔ4-4e_dⶢle񪪪zCևsTٝ J9; ^@d6 [Џoe j#)ԊXS*H<̐Ѓ!7J,6g"7 E:8n0RUaSEvr5s v~D]&UO@E 9 ">s]E (ǪI0m IWc) Og1 5W]ydJ&bY:.3Y; HP6AҪa\)aJV$Ǝքiw *ԛ8w7 <1M3a/l:TF^q֭LN<\|c}/}9Z*oz{_Rarɶ6m9w8ԍビZzzəUJS5Ϭ]|)Kz4-e |0LAˢv?!<~o{cq~/5}@%<[$o99IhRY:c)X:2dP^.XΏGWOB 6 xb;NCC˜ c7|HiӒd%7צ@ʤ$$ [.9S &BV^#8zizzΦU?_3 /c{e<|M @d`pG|ufBE|2Eu2u"?\Ln#M@ۖ M(쾅﹑zXћp\(NAGu:BPUQj @1u`hDHyN)}TZۺ m.K/>` Ke&!)+g]rov,w]0_j UD.V&YSa @E!apђK7bCU2WKdL4X (*tc Sm첢7]b0V5ꠒX(d]}3}LҪ۰`j6hY3Gh"_(}g;=Sc`e>R6BCuqb#U7&ղJ*r0ƽz&x"j5ݐj˼11YU\ - @\|2C\''=h+x=d ց{rB{aިj U)I&c)@fȦpnS3KWx)n%{{8$KF&'$c5Yʞ$z:"*ⲞFEW k4>;]dž=PxK˚ ,6̎L m''~ݾzi\k>7|丞.Z$/?&$|?~whoOO<#7=I|7=ScS' Eh|ڋ?7]{?K $g6!ˊ (x$@1 2i\bv(ށVҫ~|>,Za` D{D̵#s$.;eVi~౳\|M?}?$ $75vn)"jT3隢(V.ě}oswOMR 2nե;20|3N7n87Ux8jT]1Ju;ayp/b6JL[K|dxdxf:Nt 'O˙FWl!Oa\c $` ce|Plek]]_§{/_SpaWU*n!G` >^%h`.\O[Ah9_Hf_5f*\LƂΤ2I\kqbĈѴxXe{{h^#ǣoӅz (CCғh +l*Dq[$=}d8hVm!Ed:6d$GjMH+PbU*T7`m׌@`0(C=\Wkeq0AW^v*Uap&jIC72a!(RTөZO'2E1 L`1UIg:) ;1tbAH:[ZF{OmۖH zGC8rtcO*|'>Z_|s_Yuc߽NC DS)QL3 .@bq^}RΘ}ǿ[ݩGZkcfazPnND,G_bOQ*i/ܺ+ 2uv}]x[;Ppx'%r^0MbZI'?dA&LY\1lh~$i:;/6uARy* dF ʆ *ũ{7 ]U)g[)|j[\(UA|b>_l>z.TJ~OT/W,]ճuT|'x~׮R,拎6$Ӊl}'?r_}O?vmmZ6ajccT]̉dv@O c^:obbWd.]"c}APD}z`@QS1^Ƽ+{[OMJ軁 5(vd&4zZ"`O9C_¼3tE#2Jaj_PLCݗž^tq}[w{˂z}Xp9# ]`4]nli77o]VZ|s4ZN>?יT┝bU_Q[ (d573ھX,VahnעΞ5kvb% ?9thi{Sj ?z﷯~VZVF)ɼm_^x{_sbּ%UM1["T0T|p/}NKAρ/]8AtimϗrT .?uyGKo˕ [/+ueˑM_[O|o=Q'z_lm}$xچ[V\O%g?>F" e+z}Ph̴^kϻK2 =w}+ ;:bߜ]Wv/R*`FXHN"?/م1T2ޏV#a9ua4cl>,j,}Xs33x@nuxJ;Da YIӥUt=a Ơ)&jlhl2b//1އ_SZm٣* f ;?"%&)QwmC1#%K>YTUFܡb:Jq(i:Ų녒)F~JrTSJEbEI*F!E6dvjxAx @\bHaBTzp9Zu9fK%T/'\' !%q =j d^tz>_owwĽ#4gk :kBX:^ȫ:bS) x!߼n9~ؖJ=MV3oc^bUK(]#R9")̕zġ}mݱ9w̺1K7 {S/ўZryu26F3WY?801J#pFv6WظK'Z6Lb" Rby jIX3p>F O'jZ@o[5\+WSkw?R}޷u J>$a[F^F`V_T!Q$UnؔSJYC:`sRKQSu5#t5y%#cH":2z- Ӳ#͇0 ($/4~ o/4 (FDoO !z5 | YzTP\ 7#˳z4c?(sd3z\H2\IQV@WCB\n)3z:Jpa_[_~zvv7MgrݧoڹnWjFK#=+],\=vɥ#Ġ6Z҅O>s_ħ?9j (Wd lLe#(1Y02 uC,.&Xu\L#TtM*vd;2.joMcŠs|/2q):FYT޲RI'qee去_抟|/-}/M΁D%tz4t.L&zt;#(Nn/48r!%Ey[V+YpdK{RaHԵ5k{{o5Ke5ꀉQmRh͆Q0_˦lʙs喭)m!xs2;@84dIB(@d\" x@ q1*?-+i=j$E^u&"D8?xْˢ[.0e~a"tN rNeX[?PV:$$*R{*yE,:Ȳ}$H8x5?9 {V fl.@oe.y6.GIk&+mdWEԘ$kŌG_3 ?`ߣ=D66k>]ݣ# +s oxe x|f5DeR?Ew/$-Ta08uܺuQF 5|7B"wCog\8_)ML6D*Q\u|Zq"=l(Y 5JŸuNqflrQZ--.7__uVrw o BDI`|wG1%S'WgkOFMhr\PCI`dc5_SQ"P. ,ʧR]45~ )@Kh 4PRjspt@g p ;t0 E].B| φfh1cY@"%@' Ma;h-S8nE, 2XuYjBrޅ ]9WL!vy-HO] u*7Ef>yC︣/wMoy5|Ņ3P9<װFbKfCI_\6S´|lw2cz1{ EEbxG>֝O؝ڱn`޵ˋIvdݺnl[׽L+p-}%Ϧ|nmmHYaםslү]tQwm^_?غv dS淚 "QKsG[0F E(Ӱ̻KJQ_ԗ{r܅#G;r]WSU+Wy}TvÖ}ݒusQNxͮNW,ˁ6 3]kҺwzQU3J!ha_u e%Fձup73YMtPwǴ ֋@CAصB:%TR%9qaDmGd\Y&!(H'2=YG;OлEe]LOth7ʌ+H)q&QE*081d"K̀Z@3K?Bo@c/uej6GH-n"gCN `z0dEU#̔xZXw1tGAb@mZSb#w]ᖃgm8͝5N8uI^qs/>7q5CygP:7+oBUCzuۖMmTǦnXJhLI=h>iY͞?vclˆՌӎR2Ks ez\`kPr:Ew`yի_vs[okyL1U{K tx!W(}/A#tCmWSb 3rXؔŠo-¢cf((*2L`ԗ$.F` >LDz@p3VWeXR,pm =;P⩊V\, ؎9EX Njj0imLe (1/5K6Vy}L6UL]]ijO.)f.|D'"h|!)ٷFkiaydm[m5;h lf! 7\h3gm$7a2ę^s+:o{[_H7¥N0xTIĔI.}ᅮ^Vپ~EMҩTgw1)]w;:>ririK;'곯Wu.qК&)pIؾf$LۅчL3!%eD1SZR c-?6}jZ^p8]}Uג)ۨ2aI)>Co]%̳ < q3NP%KA=4{$6m^PuSI>Z 0f]/e>pnk!䤘FQ|m74$ _Ra)R5jqӓ3[ VgR n$ؼ8Ӫg)ꥉӮD5_O#Uѓ=;eH0н ( 1,(RNI Ԥr;UD]Ꝏ=W^56ċN Kh鯐Ĺl~qvG6u1**Wb{KQŦPAHrMl`O,夰q=ۘΒE%9Bدy:urn*aau1;cޞ6_=02Uue4=Éa@QF#*;)+4U̟7LdFs{1 7޳o_޹^X7KK>zNPHBCPٽg]w2<_ftvfcK CΩE)~*Iըټ.\Ͳ]E7F!.T,'EWu:+U+(⩺hNw+ePAi,kk) P#fyJO~:l l(- \u3%\ڠCܲ7V<Çn7l5u(AuMd܉w8ku&Ja gnNqĿ ޵TS /<̩;=W_q)4x/XnXN\$ P?У^dMRM|:6<8W~ӧ!1Aw^J'ٽ{CR83P[W8Hʰ^Ajyne1dĘm4lE|[c>o8Skx~r=LK$ */=ljMǶ3Li (儒y\=DŽ2!X-*"!|hMȔ ҵ0wFY&\r0(_et(9pDbZ3{$>XWNӉYQVݱo~の-ce<ԴE'/~+)uh(m2dm+({Qɂy\GVBd&>m#23C#(W3ƻn|&C,oA9oyP4Z_4g+ DTaINbJjX1@pVERܡ!(R\쑪+ϞʵXs48aT DPzJ>upPJvBjIo3e܎Bey~oNa s:~!J2Q=i@1D_nQk{zc1 ]z2B&q 1:)<`&F؛ze>,ؖ,/M9a}b!n}qad,AhC5ű'^RcGMI=^j3J.7E>b;t)<ڲ<6Yn}XG_Wᡩa^O !w'NOl?̳|G^=}!5if!A{\?gsSgԃ6^E XFzZ:z=NhJIDCOjlSy5f R|{ Ab!Ƭ1$r^xUG;)^ u( Al>pxi4srST0:NtI5tfC8 kJ*pā a-VH; x2Ix m-r fNp Aj~xNRc<ёՃWl:00eMף89U#TVVu*}ߧKpnM%S{ԡÑQMYGt")1Nc!N>os\:EfACdQPb o{u.T={Q쫚d;͹>uLkm{osBOc3*Ǥ]JWp_8Eoߪ,PT;-]6m uOMFc'[20c[ 'H)*p x:d(n+l;qjpFy `m۰4%0ZMBOE%-lF $j(274艃pT%t;Z%K n˥. s:ʌlua='(T!p!՛8G3nW< ʗ&ɄPzQ) iBZWt0T1TP9 3 @dL5 PE(SW%9vmD,I%:Veyvyi- eefԓOkʝ=]=:b:L06!)\8z\rp+=4˙-Y"G)i+q=kw\1SYnutjK)ݸPN8# sn [5ҨxR5CZPyB:rRKM;{ɕe-1d4(6UysjC]/m\qo4N;h=C8[dJ3q;wPǩʵ'$MdQIXs BΫX{ˆL+23淩l4[3²kđ,Z6{3tGsySޢaSOʼnB}oyEP¹i3O}l6Ʋkp-7>&?|S_۹ShY]2CADssZ#]SLCZ; 7XcOkC!T)Ry#VG* mK A5,pe>G QiaR.C)˙YF56/^5l ]<;(6iٙ%c pUY# x;-o˕۟[Ȥ 9#uW_ VC%/- v[Av֪WmVbW,^U"ޅp`>M^|Gу0TKd&{c3#l,ZA1-JnP)ApPH2vpmsWBhH~Ӑ[T `QgƬH5jqD往9tLbcca&T` ETְUN AXM`"*f$uQ.Rmt./4eٳZ !u=CYCT^~s1U@l@t񱁞\.sӬWWo[rlş9) ǶQP@7~==tJ8Dto%:-o VK'dg.-mkymꕋgO^WNLHPx RXUHZ\,.\ ؔF+W8e RFeZn[Wj8Y$_V>sta:).y~bS󪩈B"}_`f YZrI.Lx16h2K[[h4>>p 뷼ٱgw¶?W]q?6︧A CWS]ؾ:T"$h-kl#.8ҡ9djT }CM"i4ҩR֐|Ҽ^Z6E8Ns _N*Ns'g&iXRnx 27gȉ&,b>TD2zѪ9q,j,1ovdS3|WO k6aޱGޡnUg'2xR]0Ѳf}6$IBT Y PDJTQbZq1!9drpd18N(6wce@z,NtZ1_tEQvYpA951R*}ۮ|ȥK3( 1S#m[,,-UV4NZ剓TqdeAsI8z]mί,n cmag̙#WU++$>3FVi hkt8!&SfR_ 0EOө#~㯮TfR3Sj^sj T;ZQV&eJYK_66uv<>%+U`lM  C[hgnR[]]ZЩ.V=0Ro`.Uؑlzӛ͕¹q>Vb&NK}/SG??khu(.t18<Ӂ"vb)ڊr^+ȳM U{?pw幉DWD)eaʼ[6f #HU +fz 2S "FjoЗL{qdzQБE5$jWyJ>H)E?L:VL^`/$]>"9-j@oAKZ*^w1ӯپ窷>|~hZ嶞k=s撄6Y]3%^ZsL:vP?"`lpxphuIGŕvU_ҹ:=y)xo_FLXͬt%D$na`9t<;yU]HBHLgwu~R}#/|#/!ghC JŝٹFZ.3JO^(*Օ#4Dُ򅗹KtS:.-oQgDR sus驹MDŽ:gmfŗrw;;yu1p+􏞁z1m6{_bێb!7q洢kGG#?[nM^' "rmKx:T?gX-wk _/-. F! BE +x`Nu9VrÞ_ٹEi aBWfWjW-?U]3M@3_wwvѵk3fJt}/ b}a Bf`t=s ˨p>ѻH4MiP q+I =<0dkӘ;B„*tSq ᡍH !U ,4#bL`|+" MeV6 '֜K)($0Q\ DX[Y T zO`KZx ).,/-TYF9%e)'6l7=uxxo;˕(\|ӭo|ǒ;# 8G;ݯe͂j~)%yϞWΧ/<޵:Rw\I 2S Z&h^Ӊa-?$SQE>2bA3N laCu<'\:q(%X{î|AA@yСYv =qMWy|2X<.0)靧"GL)VB*a9EdCFETQlF4#IKsͬ~f tVFń=a)~;f{a&ö =Rfb;dѦkJ (0(IXF^W^3teU<贊p)QJrj, `"L%l|lsMTy\mس.:\ #=M2]^ݪ-:!~"MDoG?ٖW3fY4v 4]D>K ܦ&k(҆k$?p=p{|Բ3k!Dj.z_\*5Bf|\\ln.҆ifjs#.=R;.ZBVlIZY,r(8KHf ;BZRx^IRyjڝ)^B> 2[O(zv?/=X/6mIG4"T:wt{.,/%0i?u۫ :ۼZx*?}_Y^r}̹m߫q@R~0z?|TM c/ww_xj}g"(Ӈ +_|P|8̋< -`v|cE>#!p FuWケgxhժU׬[S(u@fGjedWmF.8v˕7pbXkl9!T@MĴ=nNЖ%JtB $KT)*A@NRuD3J bQVL%XgTE=JHT%`XPt.~ ػ;3 ݮt%D$ϡFbBJZTutI.W6_/z"zL .L@58 4K)LigmQ^nMKU-K 8_n.EOtMl8{og$%%_q G]~L?vc"bn^$(1{͛a٠UU+K3nzl7d5v?0?<vhIȦ}VD |Kb+NlQA=6Cl4ߟix"K$e}вi,kCf! `$Sꍦ$S"|M87 im3%׽0TjB`ZKNj5Iz;;f*v42< }1u1;=Qw|υ.%WR:Uo"VY],TSɦ󫕕%$ U$^=$}W5 G_w}sX-8T\BٮJƷݮTj+ɩ]ŎKv"!Jc\k`‡"O %URFjnpyUv&CM$CL_GLf˂yq6Źy7$aD"`8ڽd^YbsuQ'c׿ꕭV÷[w}m5''/][6f<[JHySDCG̩s<(pӆ8Nԙ-\*U2c{k˝qB.Ųay|̸N~/o=W<;tGQc 3Ϝ>GBo? s{䥉e,RVdô02c>_rŶ,իQne\Q4 6HeΦ"!3Puc:R-o0y#A+;Qܠ hH0 {1 MV&1֭a):A@l7nrPWyL@ mI/r,% qMP^@!zDF'4[WŻI BCd&X<8($"KyJLJ *+%OW㇮y$:^6`yn{׿v@OQ C1.M t ^8v[_qlCoVm{ns];[n| dK&TM2)s-1tCSDty@FORD!-) Q`]Y._Q(]:ub`h{8OK4S13nU bQNj֭jN9Aڂ ^AΦ年(>~S ,7p%sPa(`[)-zbPm9l&E؏c;:f*)#@DhlVraڍy#ʼn ;^+dS,0>E`񒦈08[π%f$S}8*l/;ԱEM`,Č\,0a$]*=淥Pe*أ9ZVkޘk{,8{][;o-F^_?LMD4AV:LMM%5ZA0(u6+3}=pV޳oϠAE Lz2!yS& AjoE8#V|s|>'OxQ-4Ђ:Y*q: +ϙjzչX5{?ZVLeU1 u)qEj4j5vyh+V._bo249%%~NX*1EAjX64u控^88uSO/'~jddiij}c7+0˘9X 4d" H+JH?of&g,+4;7^)al 7([_=>f/l+]r7?>OWޔ3eUiʺ:aڍ[/-хINUHFRHߪ-Z*!˓ANJ5 6UvA8BmiH4V)pQ#B@SP!YwᴊK첱 Zmӄ^ bRCyVUmD>@6%S%h11$_~̘҉P8铩Q .T]O G jj8^ŜP*03YQ <YeY0?S A,ضiMW=w;}]]tah©o|,^:!?wO<98ؿm vm]ь4aZOOw/mf6]i6 ֍RBKMoO@&Gz 95mtF5i5BgUQ^Fn(Uސ@/} SHյyfdݯz7e#,wVX.$ NLb9MXUjFzdأEghLoE@J<63 Gx ?ϑŵVHQ0nI,=kƛצs_ѩJ6ѥDДcm }LY|27"8a4G$`gc% 'IO_'зnӢEբ%!*T/Kڙl& 7 U}뮺ށbp6_ :yTo@#39([pӑs =#[wrSb&iT竵0&QNɻiYB?ˎ otV/\_\3uw^zqKG :})lU(MUV\6+9ǜ n7Lk:DDZKt(7zm۶b\)_3;[|*Q*DJZ gi\GWmoSU$ʚv|: /":TA*NU H~"K!aY*238G =|\* >VhMNJRqDVL]OYCqWL \C :$`l!&fKy 4ۘ*WW0SdCS@BDžTÜg[>[@R|?F5)KNOeE# cxE^%{]}+jltwm>}k_Ijڷz *(zw^utVk57j5` K)קw>wIw0'~|[|۽a=,-˻᧗>.[X  T(_4F]⋊%]-,g33?zfy_is羯/>HQ))~e5-:FG\u eZ:Zz;sjvsR;*M/۾_~Uљi롳kK߻ MVn@S_CCХ %f_KQ퀞6 -9q6MM U) p\.%C"NƓ=^RBLJbvߘ+ K:D .SHG^(9*0EgLRGô9 v vAZQ%{;+Yaԏ B +%. d]Ʋ=O6CvBm|'f:eY 7qe eF9%EW[)Y4Cٍ'QBnUT\UM9טٯٯ?84* xB V܅lsd:j+׭?{תի"z?QցQxP'7PQc;f҇Y?QqU*'{:Rw7KJlio-NLzœg9t>d䤺ZbbR҆2_DBFuRY٪螟) .s2l9Pi˻a()S饗PiZFU49!k*%vɪOUuyNS |%2ěuf쳟75?sF*7_:WoC`@aEHT%t=I鲀VAfձ݉yzU_{ǭ_اl~xQU^y՗. A\A8)9*ުB&#)( 4sB)&ӐT˨|K1 !'hLUQ,AL=ZPC`k8XR8QY%Uƀ7'b"L#=C;_\ZҴiC7x/ɑ K/ܲbpźÇnXYXFPG;:z w|^ۛM)+7nt=;̛Nqt[0ZdQ1<:+T,( [4F CŅݫk9V<7qEO:(gRmžml>vt%*=.=#>! bn]" 3m;oÎ~+fۃPB^6T9;*]8Y;B_3GDBd+1qr*SCOh]Nϧb<(Tl-ЂE ٩HkjIѯ!L4V:((juzвD2?dy}(SL,u7Ӭ(rjՠ\ַ>w,̔BϧoU١-h(̥fOH27+i-ZG:ZZ2R [TNL&es6H):+8C5.a)?k yƷ%5,AHn6_xn d67#Iv؋H]&dNIػ@b"ROf_1'u~x%²ZK|GPPELȾ={iY޲>OmM7-^lBqfr~~_up=omk?7rsKL̿@4+`ϓĿXu(X ]sQ5=ɤfR.?O*< NB DS(Q 'CepHsW}fB4c .<Qi )~F=lP֍:/pLB2d#ʢJ]  uT߷'ll@a).0#  ]/j~nǦK5JQK{{򥛮/}Ui)McY<+cVIdt"x iSEq ح[lk^ϴMQYG>yE89 X]dN-;X|eT[)h>uB{Ο;|N<"QAJnFqNS)+%$0(Auxȩ-+Uz֑U:.^EhU\u pkqs6=e];*狆ϻs:ZGPAS hʐݬ= !yzћvR|:JP-8Fi1tɩD *~^\ĮR/6BMO̶~Le_z{&6Q)Ǚb(钄 N UbH7R~ 0p097=WUJZΗJ6v4W-5*^͒K1lۂ;\{[:rgOjBՀ-P B G (Cb^8ޓ T Ax+Z] MS,-ݚ)ztz %e;")E]L0jXi997T4e!͔&1L~鼙9^qeFUŇd\"7,\ VpQud!̩ 0Ac!b]b`6{*kނf;~ŕ>wag23/e3!Tb<3Ǐ31 ([^j!6c1Y'^80zJƈ\IE+)|f- EU&N =ǖFT vS7M\fd.`Je5q .`H-U#X9T4#*pIxiKDMr ~V+5s_4*J_NФ2f.9~O=6#C MţR!f`m䰘!MIxQI(IbMmRRRMH}e3Zh{+]ͧ ڥj`_ZCYЌ55*Dl6 8H'-b pC_ }d`f"H[Q20̐BK['P B]XQP]%`@'#t<#}ń3;1d=.%=!XQ0" #jID?$^6aK  L!X(lR K Tc֥Rf&e\T }=oh ?9l~Piz߻`A8ʹL~ Y ʥR:D J@@4(\Ԛj D :B ?%%o"%98`E%t/BFP([J\_ix"Z5_g ξ!Aݽ?xo2Zat5eS@E #Lwܦtʽ}j\J<ժ9 ԯd%+.6EY(Gd *s V \ƾ)sZۚn!qAqh'a*3-aBƆ;(=b񍛅&s7]tSGڶmhZ4ծڰ5i@<kV=S2s)*8) GY ,d"Az*vTsҜl(⺢R95e]37wk.pqJ36uzfi=3c:J)/(Ӯ^y,OP %ߓ VbEf9lO`c!-e!n:f6N. 1{Kwd.+n--maryx|:L" 3">Flπx~%1+F\{Pp90T dC= C|.B|m@T XQbf#1qAC% w5[엟`go@׊e\{ucgFeKxAH"Z\\IlūeNj0}+(Mui9ٹR\9Rnh7vM :ev,K Ԉ P2+C/?'>e{''gv\c葄M-#ݝ9ףBLg- pafFpܝ͎UkT5jІ`xqKRTuE>/09UA]`_>UX;ƖT)d*Q}pV9ζ ; =ë.3o6GOoN]=tkK_oY  I(1݌^6- ՅVH/;0_iP՘_7OըU) >0(QZWܰ˦@}gGfJg%R%@m΍'fe*lGyP䊅PPp)tͥ@5QS $Idӌ:RV͢Mo ) F7 P #8B{ݢ Wešߥ &z@=iӢҒRUFm~dtDJclYQ=y MIC$E󐋅;YE?yUTϜ9vMC>02o1L*8vJ8ّ؞+qtKdf|(GFZ i=vSgs}57bA;%<(fP?Եpp"C1'Ü! ?R*hbb/ #&vnnio C%}R*7D]bv)5MQǧmXµdgR$,"?j!)>]7j ^m֝W[?IQ}ȹGtwR>9X%x ?1BE I3@;UR<7_*ONM)d0J20*iʹX HVKOa=Ο͡ W~ R]kvnV[tgB_Тb>Y^jTҪ03J ij܆d¤ sT>jȈ3SJ̝GFy*B0я KsGE"tR-@ '"@Ha0$ȘݻDHt1Ν۰veypRw1AH0wg*nY.R4j*UϿkWvFmznמ~wcώO8(J}^~‚~WM?4-95Ѩ7&j339H˦:;W.=]=/w+Z|vǧG׬Xz>w{W%7EM)|ay2fԾe%)C!\+!hLϷ]i}mˀtP/[<9OP$ ڻTlOjAKNӢ'1^/㈰e8O3sNVզgcwf*^z*+EN&R,) DV j')>ս>oү 2Bv)tBUKARvT< !ЊXa } 6Je}wj$5E0=/OtM+ b%YQ0C^N-gL43]zg__!˥v^C_}[;\u (2SέZųl-Ǖu]FM$,21`&3r! f;/#B̀+[2O7*Ӂgr`` Қjk[](Yns/>jsjoʽ F7I;gEIDY(f]^5t j! Z #6T& J'Z 9֥PTjTFGϝ?}~,l&K]vP"Q1@HdŸe;XPm} pmj;H=8X 8&p_ʖ~H{W'sg 8LJN6Nl9ƥʋfGO^s57iWnzA`}:VRXfb_dRnoK`g}L!X7Rb5'FRj5`B*C'Ha8J) aEiQ(4A@<^J)W$ h UȢ%Xnfaa5G.s]#qjji9U |ŗ‰n`&Wțo^:0;u2y BÔ=/>G6_Q3µ^S-SѾdŪ4ne>p6l28h!FB"rt|jي]J6%lΜ^ 00/q# WSu<5]+=%t"X1zRhA6l=}BK-@hE ߐ͡,Ο94[ʫǎ](Wt[j7 40\=Afo"Tcq22#unNBJV1qQfas[`,C7\,\l \P$&NZNEȧg =TlMf,%2FMI;Q.˒rYO :EX&B^ ?88KAHVZPҴ.K./ VݫOJ&ЎͺΥJj°Z.XPbYj>}fȉ쓿5KY{ONKWE*qk9 "j Ld睔IY@lvvcE+#&|:IHQG#SI >]\j)]c`nl8!4ЏH[i1+h|vƌ#v@B-ij;X`V E!07  ú7i 耯* ";=0RL={rbmJZ!?BU.E$uT.FNx$`hժݗ Ub˅,BRk.o{uP%-CZ3Wۖ|^_d{OۡviiMb#E%,eLY(z&GF~ jg|jnbzZ;>?;O?]/ML,f $-|U4zS̸4\ߡ#a&=zA"y"v50Qw6M hB 3xNF3yţT@h6S :ؤR2JBUR)نGGw i ?XL:㸞RV4<KPJ0HWSt!ǹ09~rpj^y n<IIo=XA,/U9;ߦR!=zT_p}XjUݲ^e]٫o{P7շt|k1Bn#9PAH/Q}ssm7ѣ A\jUX]Csr fm"R.] ~صr*KS-~*5u=CٝLIe"kO??r9|h|t*tbk6mw/)MaE=ݨ.*`+T/ jA@E|0@3|@x İuYai 1=<ɇwrRYj?e :ԇS7jAF$/K R=tD-=(4( `4#蕦诛(䦸 R{[<c6czzXh״U@^TT~X.J1zc'j5i}{X#il&[(dJQBA-<#Ѣ1Pbtk޷i^];ox'>JU[b1EAMWڅhTΧSbF9B߼륗oo<?~泳SSCz]ҙf>ywOcH-L+WصPnUx:M๦O%M *D*Uݴm԰BE׽M2v,fN( ;'Y~u R#t:27ꥴn8jJ\UBQ`gW]$r$`ۃ&XIGuz yhk̜\;Gobl5k\~֕)?vlꛗl8X?we×mg8}xxʵ[_QnV.ڱ=R3er%k B &Dt >R2+Oܢ`E|ȻW-kphEOk}7(Hr[kyglܺWns/ \1cqPR MLlT2f N/敔4rGvG'J3e#=qAS3lK[8͎ۘרxc b i^J=ENSbWq"#J.H!K%#6R,nU׶0)2v"jB0`ÌGuR V8h~QjB.CMM._]NQ9rͼھ}k6ލ6\AQ9]uh:E5%:Uh*nWS~neZH'j׫MU)HYV{:ui1eH/s-mcHFd :xXF(pbM!T@_2zBLXj5IQcbSbrmUј+TviI}+zWۤ8^D=Kzy>72)lC1,vJҚ=.ٶ=so?PwnksPثBd$|?ʺўϞ9bKjVP(>wfc/}i T6SlC㕫WzkFB鎻l4_Vd yQg!!k 61r#wg_m}_yV?u7޴br \\KwѺU+ O|Pu@oB§GRXS=fizCnqٹS+Ss/vOطE-b~æm7nstgڊtFN{F[SҹsCCe"R/^CxP47S]8UH<#0-3( e O`CEY⧈G4,D#Ò&wUYehe},*|ed*b%9t@a1%a7'+FZv ZQڞ6VTj}=]#Ǐ^㭺~ӭo\_%Z6:"{\0E8_RĘ((eɀ@a?,N5{(FtuU9XJȚFn-vwu /m|髏: {{a !L<3yJlsF*7`_)YVjC5Xd;6]zцz^Q8=9J=;;,7kMS&T~Lթ:F N(Ex N(=!"oUIwv(a / Ml hpve֘Du t^% ; "ِr|" nz%_UDAx_gSD0UE:GVvŌbPWȚ&l9闌7/RYٔn9 2D2\&WMTFQkb:m #UՔ Ugt oM׵/Vg?;(9cd\%d9΅*خR؍<bhP(o~юD?|1XZD 5"ha!PAǥ"}5`]+P+Pe4G~i$#)&i9C$RlcvrG^?=ߜUXEwk! v_)]͝5z{zBNɾΖKna?G?)frf`>5|SX/dAY4) g?7簙3IzKPFСl ۀa$ tϲe%B{O&7Gwɦ}77;QHF()lq%tЩݠpfyȶ37x鶋Vl\i"S3r9Jl{_ MD,%Ewc?Z'L%87ԙSMM QौL9'co5hL(crZT\gPpk/9q8(h$N.@fSeRa :)RЌGȐZ+߶h2eYn kP凱fʪhFqϦ$s0Wl mr ,-KƼZNftǬҞPd̽.2J"H"-YJXׅJF<= O :t C  GBg>z(}[n֓>LڡNM 9dZP[Wr{plKUVs\K}G5~3}k783~dаj6^a 8 J3_[슑I >nr7.}a+egIOΕ ˶Z "X>J- > I߅ީIo@oxέ[>uT*j-yponh'v/ ?}>SG[:9*/*t&3rŗ}{#'OΎM Wڻ so揜:rW13k6n[[[ڄ 'z#2pOJȂ@rAKђ%K绍`pIsU-/hk)9h,YR5k9`a>;A>\[Ғ5ⲯ<Vf+p\~eMO+AP:. `- #xRWO@kad^BF|U,\Cਯ]̚Hyh ig-W@f?$BD|]r0%J n0mHX2L@5zSp&L\ 5EjMJiRAAPP#(3z]x@{"4,>ҍ '~U{s@ˍd, ]WnbX$86&岅/ Ujq]z-jrR*:47d9qr1az#`*crd\[r1= o Q#qq'Njk_b':2&0t FU08!EY! 媮 2KcC箹W[ۊ|3gZwa3 IF3DL6kQN>/ڹ e3M߿#ga{XW\HeКL> ^mٳ3 4xt`[@O }9j[)KsFG /ZzeOw+_dMi֪m*ՠX%38BY\gfpi_ilzղeG_}՛n]?nMRBxXU:y-[{ G_ޙB,"cғw糊!eqT)-=U 6"cIfA!)/?{wuw.liSV:u'E3*[<ʤFJ$),P( #q(AmR^*yǃ?էlFU4塟Kń4zkA1u!b_H)N%µ;ȓf@ |YБBUCC8*#oE $,U]$$)XMRh] 氈 5&(NԀWeT"r{252]Q- cI:Q` {7|ΛoҭVLk'Zߚo*d >Րq-5yR"<Ő"[ .\għr,X\!#$]Paw+>)]Z'cd$ƕkdjs\h!ZBJUn<-UK,k5I*3S3SM?-t!̘U!tvu,+6ǿfX 7o,MtXWf@oY)[Xɺ[zՎcG񱏷uu&Y)ZJ'?Ri4vٴÆX6ܓ0νϞSMJΜXˋ׫T}xȱ[/N00g9c˗*5x쏿qmwY'3va:'^@xǿGo_}cugöMʼ.h.k=,Z'Ό ݆VM>3'nݴ /(_ 0όt6mAC" odL/t#E[DL<%pp@q*:d+#"S`[&DRd*ҪRmiHԑD'lMQRT0swvˍ$ QL_(d0H vɁX\-2BepuW~{71r f1NL+׮|O^{ ̼]b8J6>Zw,K`MhRf@TdV3}c;_PANcj_$>p$Jf%Z4WPhI @<7VoWϿ=t0쮰DLow tJJ@HURt!v|=T%mh!K"#K*D8!(X@&1vyVcZSIم J˔.5%x+fhDs_*,DUUnXN=LR cMc=.kCŚdZ.y Ee \J *O9'! I,tЦ뤂hDK=dX+gk|i&KYTelB#AV^W05_Y6_teثFkK.N2-s#feE'Iʠr Y#Zrԙ25x>.~$"$mO8 ˍ, y _:{u3K6/kZ up͖I=U+NB`m0Z6 z>fZi"j!+w揎L5 Yri\o6C%5viu7s,0jB-g`ዦijܜ.YtSッ~a>y䑯?8~5ϫϕgħ m.n $HdX"zLu׽{O}w!v[zRڼs+v\-O=/\Ft܇?Zm^Xfff;j=]H=߯ݼ1l Ua3;6Vlou4[/|yuP*#IyqWYn1P}nؒ7''ΧlPJ(D*@2714} &U‚)PP@\ "KM^>e@PSÁI-C{uVWçۧjݖ{ B 5:%|` l˶dK#i;~η~'#=}^{гCw&eCۮ%Dh -%(æ$4(tأSLLl)j3Q:#`g*B3Um#ˠזa(8WhȂBML菖LW نrí֢eZۊ9OB:ZFZUUٴ~r|.g6rĥW'Bqh!͘t|)&^;C'GU%#c`ELTJ8}WfRҶK.?t)\B"ǔ!UHZcR-6z&ٿo|A. ӴP̸oݗnliABcla]@j߶0@G&%kWE>v (k$,ȚXV < Bp,hA4RY-N!G|9PF`vR"=^b-">@4jZ&VR4U͐=gC?B YtJ>UJuq_ $=NZ ``X\ʁm^@Og T Ov6D8H3,+3ۅۻ|(lu[6߲ntϛ^Pxԧ"vF@]SN$r"H$:|nqGp24Z2Q&9i$Jٮzխ7}ͺW]#֯֊N{e! ۴S֚Zw5hBI1Qb֖ꧾk0}ZS aO/RTFF\L<3wct4PBaTd,'=ufDȇZME8 ){{ߛjzslPiujSHiA8\:'a4\mSziw{'v??׿Yz#?x}Zխ͛oG_+&w)ńT`g՗_]ӵjTanC0+0뵁II )N|nd;3u2 M|CJv;„͆滢04b'<5AO {:\B^ALZ"1KG56%x 90M|–vyZcg^G Q/Fl8pB Mkd : NIU+*`JÅGaZ4L i䳬JmivN*iGjדQ&{˷>w\54Er}ay9^%lٔYLTp3^lNŅS?G~feSzFeq:ZmB% xWbR(֮&'Z_ R=G\(BQ"+t DIBRг3Cȷ1_ d  K~\B JW!!iT J P?-0Zk&L!=-$l6Yt АcvJ@ձF Ka8ThB"%dq/Ykq2+ʦSݬ{t\<}j{r5 .O#sI>Kڰv"HUTxR230 W) ⪂XedEZ\]1P [QbqfFz V*I}O =Z04;=[GE=rHfUm R/^WkƳO9AQO7(ѧ[Y/Vx{(W\uS(eN-ђm߸(|Zi}wwO,}؞7}GF ~7cG{;]:cp^R" kE}( ?C 'L#&+BX1\\ !ugW*egFph)LFKj33#J}y V@ee! ZB44Tځn r dRťP@^K}ly ݍ4H:P &DNx,:P9 ⇑'hTT6Y=2`-6!S9QC Z2$Ii%%"ײ&ؗƾ tb uɇl$JwGcyX(³#Eox=f٪N1I`k:x}˄N%i?~U|T"իt6nΗ^uBϭf9{dWvciSh*e)s5ffJ\gtr9IY^ UVȜF^Xji%-Ab6]&F[KB*!vȒhWc [Ql Ѣ*6e(TIO%MaKy_'P%u`J ! 0eI7QFtڱkZ IX,_jQµ&pP##iR ?I16u_KϿ̮oNِQ^@wl ٞVjԠ<0}уfNL/̥;wU4ſg'>koy]J(rW |Ņm_2sЇnvXD^ qGlmǠFKi>rdi~LCpBڰޢ'jV!e+u b!\{ud1NVFY%7mϤCV5Yq@VC#%6%pQ&}Den胐B6kR3sS񸤨'STMU`ܢvVۻhg{H^g/݌5s5,`V:TkEc;eY(R{ml5OyĴ!^{_s={'Jdxw$B&V?(c< +v~ }U5<# 8~hh2 CQ=QƆA%j  }?|:W>QjXE!ozQRE[i`@/==q*v29eh9R(L`U߶sL#a]#1Mx0%l@gƤg~~qߓuQsk%v M}ﯟk56襟<3ֳ]/[5_͚ri?O^GlͶ(zOHw6ic[)! LRvMSbn(kl2|P ƛ>bq+W}C3ϝ^?&՛~T)NmY"^X /u %[ Dfk%hf!BfBE:DA0hJTHRݢz6,,gڽx@$DZ/e54̣;ȬCPMzlҝ%a,nC$[gۦivu=DPV&\tX;ahk툏&vmCRŰJuolBpi2,04 #-4M𶈄kG Mh#ҢfbS}iE.#Cls)DOLc6ٍY1`i&ܲCfl1.t%Vg>"&hxng^ I imPSyı,: w$2]bﱎV,){ԉU_JFG)H9ż$-T+ l-kFå+RلV^YOXV ?wa/ĒZ20Gցm@tW,0ծR6Hr3d= ׫g}x'~sp?ԉiMz?z'׭_@b0.x':mMՈ\9m`WMt0Nw TR$`@^LS"YCS”Ƕ(M^"0e\-[xWӠӼڊT{ t#2T"H ,#a~UӀ BuasQT̀^by2֙M3-cj~`6e N\h+Ooz 3T4w`߾{ MY ???北7quWd #O=_seԯKJk$X8{ IZX)}u8u%RLH9A&f1}nG|s^df6X1YY kS)8$YTyJxefTRAӒJu{$1N¸A*%)7xA>0 !88C! )!AX,D 0iX4Jz)E BSN$K$Ef6ϟWYX9ˢM>q Y&IPo&'vBD"uyS !~Sh0Ol^yG_.sSV:5٦j"A;Uђ2e OhvR %VnaƩc۸QhhR%!rG$ib1vPr)"sL MnEXw1 @T'/ i=ohp{N˲$нOdX&EzFB,qZ$Lxsew1׽.( Xm#IJqj \}+W͹'&'[=6VZZ6GKRo7+/>ґ69rkͅāFŷ*z8^䆪pga,ƼF^fb(&(aAІ YqeKkVU)aW,dč`Qj_>OtU6xGtᛌ(y)ZTU&A|T ;h9GMb> 8b訩$J_ah[8E7k V*%ؾ :9qB' QL4L)7TC(qx\ĨZoѭr}a&pV rn"z*T&?:n^Sߏ팍l@(B%Xڀ§[O(r* P@P`jU,R2yGґq4688T%LDG-1$fuN0dq&8oʼnT ~" C𒡙 V<~==*܄0J6 "jRNbǽ GJW`vWs$״i&ǭi1֮Ԕ!;ѩĄ5՘r@)Ws@b[:Pi4Vu[3ÜHͤAOO쒔X51OԪ t*/wc V  唗yS:Y PZ "x)=<5sB_57[ǔV$sHh54xv$&Iz'Zgb7F_Ί6 q0Y \NjR1֝!ֹv;sTA^%g[/tWMtڄıeg`ˮd?r˕ȮOE~9P;uT=YU[WR,~): !gQB[}Cj(K5>F_/d)^ԯOitzc`G\~)8hA8w8&%Osx-G~` Sc3 ?UөBE{B AbhtQ mQ(&q+ 2(T-15hLpn0V5Ϫ6-Od1a5O >b+(xAI@s vPt.$ N$D4S`% ;}M-3{#^Z~?o2zz%cf,vKH<"$ΑBߧ,4F R[MS]*zɏdYj,wz4:*U^vO ([l5\te3ԩ5+|+҇|&OwgO9c1{ [Ly .Z~ō\v鮷^q]0>* CG^$RWx) P Of(+${L0f@R7.Ljuu]Е1L^1 I_'sSMR3eUWD RWQ4Gn}$&ϽH DO cga4ĊR{ƨ:m ۴FQ@ AKmH)BY@|XѝMդ܅aɭo w ePn6c5ˉћ_jwYMx4o`]0ҥ43ƘǗ"y)=mHx? jK Ml0CS-囙2KN9G # ۳/oW|76_O_z.4_ARn +Hhز9aFlIZveJU= UnRU;~K"PS}bjfˆn6Xi&yɍ{(oK\ ҙ? `b:N.fTEB7fɈ Lp|Fh*jPCQ#32vbET6nB::?M ~]UfbE%\B +⫱l0sYeHqfmx۪%GRc1,&.ܤ q(~}~ӱnѥj;l|fv~lhdUX=9>,/̕' }//nx2̎\=%-b2(-pNdH,*6l6i\< }(dp+ d/[p pD8`>fץ;f&l4,WWr]c=xȳMJJB)i1* nuzY'KO[?~2cY-8mO1;[^!)% ulqU6b=2T[nQH%^=Ia0=#_>S/kT٬@R6G&o<NQ*(½oŝP[QVZu(7[졋6 ZhaIX|\ ] Q=㗭Y> f/|bMĝ@.U@z.̇zAc Nb$'f`/7cm[y^t Ҿ3sG09R8>/|˒}'W yO>$~XʮsžbyfN1`r!_b1YU^9b! U %1@3Z$IfAiu-SpX0 ?D]#ݔb AP؂FaB bt oɤVkz@遞Q,q*'Xb`e!ѿ=p+/KB'!+p lg1ZT (zfB䗭閚Ai$TV:=qД%)l"ЦT.3g{v Oy]ǎ-[n>g~\>x{߶miY(EKy%CB*$M=oSy,)Ww@IIGo7& HwU nQb^@8qnXPmag4|Cm4 MY`c)I31y\\JGӬ©S֎nIN1lo^셊gѬWjաѸscJ,Є'A(:`˜%B!%d.皥 IDZVmB!MgCsl߾=SS'O2Ç[&7l.KzjmظQ06(l#:wmo_;l.Z}=b}:/Q-9FqbT4fzv6*$ !kLCITܤm/Mu!w SqlIC@8@@0M=n mțǦM*jfN+F$1'aExa;ߕBt|5zG%g:nZr)R^Ֆ.:Ɵua&Iٚ03mYz[2M7UVpGwr;vَnZuP>T~[n:\>?i򲦘ڦ7!;,X3b %=-ɀUĚwۺaK ,, oP3iH##.dfNB:faTTqiá/-%Ķ :oFS=lDQ6~16{n ;h*墨M@285v}f"`h$0"]DT=V9l5k:hWTY,c?vr~nw<'DDt ͗zA`±LkoL z)N(.,,DaN``y!K*۱Mak {hr ~b0;}굑AH!MvV<$jLT 8}(q2^ܦ;Lm2em4d` WH.Sܺf+O+0 $pNYt|dK+dG’'__kζ3>OeiqA_Y`b>{`/8%1Ē~f2A:@+Ȉ,(gL*{Dժ|}X^A0!Rnt~̉c|?/v]|+|Ֆ[GW2ND)<6Ns@?Onkok˅ۯƾ4{-H'F,k%H= !F2`ÜK,HH71FfU"sVTUHi𬣔=f[W=c}&ۓ;S⭳r 58A;0TB"[@(83gLkA*ja@x?x[Uκ1rcU4J۶O+u#\jdd{7(2zۼ}O8^aK wv\2>tȖӧO w}Fn>oGPo gtMOwvnG.-q/Lw\`MpM?XIZk7qÓ'{sSS-1Wt׌];VMbkz#-V.0Me*lݢ12ܽﱟ}O~JV릋L)[H}3bQaU5jS0Ynѣ b6 jAazB#8cT =~+z*0M] @ $vS:Rݶc?L;/eLG ļ(rbp]M"R n]c i⺞!#}hXGeZ"IjB`HEcu[O߆kSheE!eA?Z3,[l^_ITgfܻw\|۫՞[&1*Z5$\\\{mGt] o 1;hSwrvGbtX]jzcwk\h~xo`V 2, $Ѝ:; <, ZiۋĚĔZmz=WͿShؒ<61y-7oۨ;/j?ߞZ }1S2X!W,}nRVQ+4+B%thú("i<` Y/~ XK X#Aۅ^e3E4QE];&}/qc+} `qrG^Xd!5$,υptnuY0/ l͎q6Rc0R/ (۸aKuǝ:٥ AU15ZSXl-鯼oZwܘ舣犉f@} jDԤw KtDڛ߸mE_5:2'^-)Q?0Fe4,3+`?K D*@16-'02iRPBi<El{2j)v.7^74S+R !ob8 xA^UBH'r c%/VI tЦj$m!Y\9@ ݠ(:M;{dޠ&»MhZ?b6}=V)Q-%1?W6ZpMG#w[Ȝ T'F?~rk [Wc71MVj6+׽n6F1;!dhn}J(.bc"6*.>}Vmt]7ްw`ѳ P A!j\FU.LtRO +zTXhBΎZv(=[ DZ_Z>ӨCn1;Ug7Oc7P`&DC GRT8S/[m[ԨU#gXB958 U*t+QQG1E(b#k."&(b}8 Zm#m N'0@P`_blB x3) >B7#K*z[UOϝZ,W)6]o~̙p`녗Tkӟ5~5>#ݐ2>H}5ʘ)S]?:X.`W7N)jl `+aERќRoprw?N,hjMvE!26XTLtY(gqn;'~[n8o5;6]s7l\./[.3?sC|r,SBl`Bg Ƹu{2`H־1Z;wd)A ԦJe]3a-CfUz̮+ÂL?652m6!O[YW:ʚ.|㊩ ؙdEU:nn20?U!Qw_5;Xnt?vebd疭uJbo,*+oJ̨~f'+":84ۧPY=AM3ůdmzU7^y뭄J}=j*m8\'FV<Əi/c+8@(ŎEVЄ*7.t4"^b)Ǝ$ 3)S}0҈GQՠߌ$0USFpGon"FtUÆ~0WMtaz_ %(J^jI EdX-SslyfIgYfXKM~f EYHL uTuV):ˍM7lQZW!_jo'L8{ηrV ~+.hܞv$t\5垯ܗD" c?vZLkGd}N4Bn4詘@A@|,L!-D U Ckl8ӦM/|tpt"{ˋ܎LiZwqrTs"2y'ee +d`_ѩR6.m7y#SAR(Ɏ)\mI"YРP=]jAb{6}vOU@b3oh PB׈š lH`˩a'PFQX)VM'0 𼨰7:>*D(1RLӧS U|^w[2^誧z3hNx@W~B>k/yŞc&GRWhRֲNerKK1hGV }3'NgS* ]1~<1fM !JeJ 3/|^~<CEdt@hc!g a~_O>Mw)Xh_c#;nj,vٽ/ja7%a_>X5P;;Pv)a`6[yo>U*rxs2T)Wm3{ =m6fƷPP,0omg_>^״T;W\zԛ:r]^;HQCRPr}G{?Ȩ[eic0?bdsл|cLUB z_|RM)!j#su$@ ~D2B7 ̨ʶk0#P۳'e̮AE<`oĨ% g.8JzS F0@JiDJpX(>b!'OGn沶ar9< {v[CUkykK tGP:=, e<"DBS\qL6Jnrb{ fQ,y0t2n[TʭfkgN8'?3Ou]Si4|sݥo|Kw͞cv|?y*J&|[~ \F(+J?-I~%btQ?-{~އ??}[&ƀhH藅liJ#EH2ב䄞mhp("hjQKLBeE$h* r8K ŠXb~}x*GffV@9u~qJKnu7ޘĦV>[}pWnnܼmo\*1CÓmS0*t(B^ KNdnT^R@/by t2ap<'>Wz+p3ܠE= ӻ}+"ﺄƶ6.]2 TeߺdIVԤkF:_B`0*ħ_.W/E PG&2:T]fԺ wG@()!:q6J, 6O; v5O_:pQYwn6uCef Z\>1U>YEWc}_\aۯ{7w~25}z|Ͽ:.hB^ yZyiKAK%LDCҧ>_`r^dtb֮.fj08qcv G/ 3kpr^ .T[u9% d24>BbmdYa˂9B d0= }8'F '0UoIYޏO{s˲,mYH@5k~ј%Ԩ1b4JAC,H ^nM}g|9G#{>[m{tpi2;ԤNuwftH3. !z4':,jޤjO &PXDpnMAY*eGܢ2Ë"\ԢQ!4p,hB(` ,( j)KRh`LA}UzRp]}1DqzбЯS.GG,q$=nTנ47F&U†r?Upf67:_9[{\buA Uϰzv 4m^[k0ŲmvoBn@:DT({'P ^D4fGN75hs2X%iW~8vy6J݋_ٸn񲥯qq_o_T(Pz*Ш69WKsIlj)g,* B\uiJcA𑗖 };.u}=<ˆG76\Pܯ$RoI4ސPH<6;f982qP3JQ@0 DA:ӨnL ,nCai&$<@E$&ϐiafZ &./1l@0]Ϥ7g誵Nmf.حoa̙ν|>?bK^m̌Lх f_W=tT͘%3WuRlĻpiby^tjt+\V<\g' JĆ/wvֶv~ɩG>=25;;55qrv~Mw';rG՗]sAx7~?~7>6|Rr˗?{p ~LR3aoPx!| cU}kop/ DX),eTSd ˅l,<7λ(=,Ҙ]R jJs*,)bW-AgʌEtFIZTDk[O/R-m:?.K.y'/- oh6:vԗuݥz((c[+UiQ>2EU#S9t">Po@\;S(+2S#]ڗ^0V'?ַ:Z>mvg4]8 uBLj"lϓrFkI!@ 6՗ Ҧ  Fѐ4ͱŁM¬#2- Z̜#QƉ3FSm>E:dvX,x/K(V)nTЋd!}h/ynRE'FFN/Z-#b#~V\R¦CwҦȱ=`sH2t5+/?/ ]m~*u/]˭8HTddo6\Kz*I_533gP;PMNMOUd(ApSTPn` BBҦZ0=,Rުl?oXb{T'Z,d}V,?RKaDFۥiJ Pcj*ii\sOwÕR(J _ 7Rw0qfy7L " Kf,Y* hpu r<(S9c>A "KŝMǦrCYj]fWeW,]Z~JGw þn{agEpc_?{׊K.׿afb:k4e%_&M IEKeƩ,EmB-]xO=}Gګ+ּt9ΩSõFm׋?훜k)$%?(:i.]LNY ;Aq؆t^/}[]'( ۦC#t`e0LPiT&0yvPsWcsn/D%Y񶙺+'{*)gUO7tPWpػ3gDӴoJE\]rGWkPZO?~d׎*Kj nƄ#s,OB=j;'6`i.옚5ʸ)6O9TXEߩTԫ-og?Vh=uh%)ƿ1bSf.KW$=r]bπQ*=!$f@Kҭ kS-VOTi!&[x1HT69!@0`k~aTcl)!Iq.jұ;Zkh=sxՊ?o)J{3/A< Uu4@r5i$0&:tt(26'5 ^S Jƫ%/2)9+k ßMW5,rq^`#O}P۲霩k4|C8+FHUJݲeK('9vRlu66EZ6=fB.N70WAgs5E,& 1r) cٰt`PG?nzGG9i'52B#`QP􂮾{jVZС'ShҲದ$:`XT0x{sHLkFTmn.[D؆a0NBi&BĩCT P5#8òĦidfF P\njT۩f$}Ͻ^`7i>2T /ĞW43 ?ZdSzRc $@Bc|'epB9@󶞥!dh1^Re%auU#>lz'GF71RP?ᙞfT fRMz тgnt#M3US4) a:Bl**d4#XY1/lA8Y -*~ԜQ]Yv,ؿ!ahcNy^dټ)dQHaI;Vрq$-<\2W8I axQ-H삕pu1{D%&+LLBF[X10(4HLLʮeBpT|YE-`̮+4_:VZܹsU 4R6Ȧr??U֒#p'/xB0P=VmtT[vrւp kӵɉ3öB 3$W&Vv˃e&:ը{Sa9P؁AQT>߬:uV߷gOjrzz>g?W.*[EWoPJ/(B,7_{~ 4~X (~ ^/ɓ7,akJK7~8s:[PY4R@AFbĬvi臼8NV>@+7f`Bq*٪ikKȍRl3s %wt-0U%0CWqvOoy~Gco{nRi6 - ?4'lt qOc6XXk9y}Ƽ<睾 y*) {)w"B/iweN?"$wJ۩6u&H!w?z91L|d9 |`3zb(S9r?(]R%&tSnخ*RRƦeC YC=mf ?QpTF`K#A`2w (ւ۔T>"jMՀf˅B>صŤ CFɏ V] ;uLU#Bސᯧ-+x_S+B6$X{TzșA}nfnny^ax[`9akl+%UR `Z7z!:Ȏ)!}D!̩Tn ́OIQ'%DQA-²P B. yXo>ޛP; jf@7S⦢4۱Q:dQ:U8Zm|M.5 j( _p;*By=S}Ƙg8*UmSK#Rpxݬ^ *eS;OZAY)/+[(|c5#z j1%qȌѿYz1$ a&AHvPSe2g4}aW?@VdPϪ#3#'*1բkeg־Q:+QCAwnvGCl9M[6RB{;{;]#.k+a]*?_~ӞSݭ.\풭\/]7t`Gˣ?r n]b@5ٷC|˙H)(RFa1| Wk22;6vFUcN'pI{nnkђ_++tEAmp$_F,BP\QKToST(a0LZA,0΂3n4Ci8 ^2rLD%?k+%y5繏cDRS Ð=e.έR"F뫳"#r*]Jb%psuon;r]s h'~ #) B8OJ)T"%$p"XQ(:yK LYB}IR m;%ݤ0f[$\Du*:%BBBVXmJt#fPc~1] 2EbXԉjMC8AfK::רWۻ{&'?5?rP|UR)՛>5`<' ~ƓKyʭ,Xa7B~jQpAn:B~OLD)suX(rqMF |k` e茄&(g f a@"$ Ipla)Q v#p}&0OXcDô(W)\/" bZ>Xi?vUJsxEm7^?i@zĎT cFXIL!lLiUu[4]8B :Yȑ.blyD&_(p)}AdFcΞGnWl&VC|'$N;*NGWGF~_sɅ jѣЌz'A,/m~U6u0Šd8?:>11CyIYa 3q? BP|ۯޅkgK.j(u践sv/<FgB)cD5j`ͪnʫ_rz*JW?g]FKלsݟz.wO:ȓ} vpxԑqEˆF,6Yin(wz^=ⓏhxYm*o'L#w `k9b x假gnvT1ӡ>U2NQW܁5vUUva^د:‰>@BJ<᪠TWIņ4OH @Ǝnl]ajXruDCKB8ԗw7~c-WxHYl<9SCQ.3I*ESgFfna[D`g%0d|HYw-OUiNKeq\0*WWR # bX]H'01M# jS)gcYZܕabI٦ܼ5 "òypDBw1S=Uȶ$TGQCd vD 'jsIm L{`HPD˵,(Xl[O[3{vɢ0AI֙|3=cp#Wl.y2p ,YNAlZ@ӜF<Zç21:\ ΅TP:FꈰAH€"^d}, 1 F>w2+ݦCd A%#,b,18%AA3MlӐAtUlpY #$P`L%p5$thr0<;?2z蜾&67A*~57srg^iCsm%4!JcJTtRxa$kũi J2R (r*RQ@(%*>MLZb\:̉Tڰ :ϬdHsJm^B7$14P8(\c[j1*DNo|g_Ҩ&=ONCR( A9K՚lm^_lقJ%#0v ۷_9?=+\ӭkuHR*ӓ#<^>pDfKk!k}|[:~姟y2woz:Jc}a~xGejuٲ(m:;H7\Rª/R}b8 T|'f2H(qm䞋7҂*͗/ز1 EPN̄ĕW5cNe9{} KǞ|y]w[K۪הېšb&vXX4@B&"f.# -r"%7jȲ|v'"NH|Q`Vb#Ǐ){_+Y0#7kaw@ bH̕JcӜv-RpQbQa҂ `I|aƁ&g4@sA@ aQ?Uo`@ =C< UPlTE1ɠOO 5N`&ND2nAL@&tAU5l˧# .qh aL&1PK֚&dd dm8׃Ͳ k!V f3ͳzC=M'^?ٙDY)Ug-M qb;fHYl!zAB0F>5TQN81,L?;.LZcgaq-(M %tLB^\zXhY(% 3̤i >K @Phz D@=EpeSkJǗܴO:;NS1i(w)$G5 !,fQabQupVڑ-ktxᛴuwPG[fF^ܷ<#UGyQ`*}Fѡ]>w,Y[o\yӎ[X*Xaß==6691vwQ ~;:&ㅰe/ jES(~]u_#nھP>[f$\;nAffkgy-bÃo`ɹA_F7ӃDՌI/~o?s|-YaaP_oz;)<\87`? i[2m^r7eB&繄]"E#0L K|G@ysk|tTw?u"} c?]{h#GWlQw%[4R\O+l̹= LO riqA)Z?/W鏽~ w¡={cˎSww5+e4LpdWĄ4?=2XPC|b#YHIՕTZp1lֶVxE =Pq&? zƦ:8" Z`}(8&+DiKnxPql*c,q #怪 ᎕A܄8QxrFD @=9kp3H=cotvw[)p -a*3UՔOLOD2rߧ1Z6Q̖#+G(Y@֔ҕIA-++BYfYT"ع$ f15PyÐvFeReo$V=D);K]Ecs)p\9 1hq8ܦ/ah@^`ttф,7f2Rrv?fjvcnjqa /eg9U-݆>&ѡN9Z&a&SRi,u\pn: %cjPuU٣sk=n˥ݨ{hB Pd:m'!e(I72zL(0(Y+"ٓ}6-c3!](LCP?9~S΁2Œc9 zJZ¬cO>p3㣇z~s4`b)0Q3@ʦ(:WnY7oh[vbFsoW75TMV,MO:zСoiNCO38E&m‹o~{zn0k18bQ;R?]*ona -X׃CM3m @=n/~،/zUSaNk(>Ru“Ų5OU{T68pN3/Ta!5?jjSU[1FA`r50!7Y 13EY'2 ޽p믣9~˦g߂UKtXz&,1ڴ6{?c(YJ0k9G6X4>36*?`f@aw5k~>+gǦ&'Uޙs2cd:JC'J~P 8Š+ ('("8ځz"{3~^GumbkMAVqڜn0M Gτ3Gjp`Ě Fg zYb+ |e? +1  tUt p 3zn>^@u]oa#cUJq#g--e !Bf*y4$罰$tNNT@ JcZ+s՚$AhI Q0{TEbz6LG ׉KO 8=B *a}0T];d=Y*!@R40T3/DfT d و0Bl< m:Vy+*/R 1C@Nkyi0!C ظdx@зӨm_лhľG\a/_4pV\J`;"vfSqn$r[ƺcSHO>vᡟHS wf,-/j}JRaF 0Cr834OutZ^'1'E^DO>~zxeMU.v]TlʏY"Dt{O03;4~Wzq/9=gE#h:äZ:tO 3+V{kW~BV-INgGGK{k{Rn[lkO-7si)˷ͻgf'{Fp׼]nEuf{|4J%z;ZLNO:SD 艣+Vkk6;p^G7]nźC0>~`g" GJWgU*\MkxupЙA >%5c,6&k.~T4Qʃ "G(خ2WQb0JB&W4H!ܫ$rVj/c4)ȘhMG&#Jլ TlbmZ=δںALbʃʯ)+޾e2WG]PȶM"ӇA<C> ?tY1o- .zAbgRkJWLWwԩOŐ)Al7YڡIeY!b'0 Gp$frpv2$A%,u(K,"l3bA;U{`B?6)MM Lskя(BVRz'ό:wMa8a9iYE!7*>%)o~vjfnAk3 T * zj)UƁgEз0c<U#laBlQeZ²tKRD7"T 3U1$NJv15N%P1] `qR(У;:Q6ݶ-K_JVk szi  i# 02a<8u& H .3V`C8tE` Jifҫٿ溥Q>СZTA;jR@ v:]*HCL*)JJM$5OXYBJjc O0cA_.oz[1;#txCO#^ikb]2Ґ!Қ̔׼\tV_92ɚJ 5V=2|o,Y>?9fMZNGFg'+24>SW} ubz&(XC&rOᓺdh3Cw))&5=pKwҁV(E9R!D 8f++#Vzݫ(G)+/:0Q* A{JY H~3pbQ2l/3 ZeKytN |pX"]3tH\ݘ+< gYmW:҃1VJ[)*}Zz+?Rvs>RL:JԂ?L֝P`R=JcT@I.=Gz,0 .PIc@>耨cV@,aw)>NI6Bvaĺ%h +0΃XE zRTd_TQv+9GS&'%=+\w]bE˵RGPUbPAtf˅>tO)]wa ${8W{ǧg4k/.2T􉡾CBjT6{?m9>qӝ'NRǡb=%w-LM=v|/Q.X?ޘ>`o;.{K_mЇO'}XsK8ٻwo07ך45C` (c%&D"65ńHw ݄l>/T(:Rۻ.{_>/QPֳzK,1ۮiGAZ,Bt cBU2(ݒi&+O(mjƒAw?HSS Nhӣ;eLᕣ9ɛf(bCP֦z V⡖b_=3s "Ab3+6<)Z;:&&  ~8]o~_a|{FHW,F玕bZֆ8qDוMخ,դ{FHS>=!"glB~e& L|xrfx*$ܓ85 l:i Tj#(P37# RNT3l.bX1M)n) EB@0)m^o̔W4DͩٳQ=jLVwŁ/~_ͭLB͍T&UPÁ^r\&Rc[X#)KYKɣ0eBE9D*L\p؊ l{Cf׊=ݵlGԥ 7@:Xӹ2LP>@1bjG =QRL\=ʁ26j^n-G Pa47T[%AtsG9rC K7J2Nn\2ӧ6$jԭ+I?0_JG{wm<=XҴayf7tJ%+w̆:KNJr W -l839uʞ-|rCc&Gz{nU7^6UU=Zf}Ð{Β?O~#O}PZrէ'R0>R0ag^ i.VFiK,Opb]r9]b،f `Vb]y׿=4z2%\J֡ F[m<W{Rc-EO'R%2@ PIc|x}߹So*F}֍k?oq9ǎ9DxBqv,@[n@BYeQfeGݏ@eH; Pu=m52xfaC1 ! TGI93NI4?` z|aN;{Z]A^2#畓`o N,=*űn;¦R& FFAh#Yj?t%j[m҂ZK@G񵨱()K2uJ :m QDtlCRgJTRj,K?¡lr'{L5P#NxЋ(/үLBJ/bci5߀9\nt9d3%I0p4Yc if 0MO%RK϶lQ(~᷿wk5ƛϻ[nEˎݙz͌!F\EsÆkp7ɀlݦCg4* baJ{RJ,SAh4|F-9JZ,$2HxQe&9#ACiQD8*"&aXhZTS Ra.FʱGoB'C|ZEՕ65PZv#eV$JS̗ 9.^uёSϽ2+:E@^s~⛷vɑdҥ]ϫK:>wNN,XԳh.'dQ AODy5VڰrC?'4,ut:RVp۷_~KV+(ŋw7[+#g~l?~væՙ>ٚā+(h8"{) ?TB%m2X!#!$_`/WQG#'4h̵m$j} NA֫Gx쬣)-=K0EQ_Oy[?X^+ grcS K܅pI .vv`v3)cM2iSv V،G?kq*QF3IuX+aWw =NOyW~)CՇ{Cl&Oݏ TK1I( ÄF"$},'啤0跗 2S.eCM/re\KOET7Z"enT`8HR \ #!^SJR NKTZtQ%؂tFb /L"ER _m>*U"0ͨ e!#&Pd`H;&*P"Xk puYi7v焅LQV]MZ?G*8#Va8DŽ^&\]waK[6n1[ ^ssͭ7[EG4jDŽP\(h2s"HfD4yL)XJF9^ĺȐpMfNҳW>2s L kIq5tQPjjPy8I)fsL_ @&Ak֢}B5 rę *Z^ U1)!qwBقݏ4j&1Xθo8Ͱ cn"b虲l^=G=΂`÷~i$mw~Kz, PEwQiZNGIFa9}ë\c>/36;˴fy TҳiÜY:/|y;~gE-\pelfTMͬZ_?wa1\6r3!N}~ڨ_Nt 2y^'m/a႕GNt#_6mI ۊzW 8Vj+<߉c ,Yg&)E#Kma*sJL(ҤY@u01zd^" C(h i#ckDc)5Lٖr'=0bj U4dS(P罬jt*kN؟US}kz+O6ezeêڋҟ?gѢ^EU=juCFiBM5({~}v _Χw<}|Deɢmۮ[6<2u(Sf#~ըRbs[X3FfƓgF>j' =fJ rs `Fa\w` Vv8l=èg*,&R}d=ΎΤвRkrboxzwg5~D݈:Ecj's\,[AL4waC: +0%5mߵOoյL.^~ӃKxId9wgu\D0GNQ[>/vQ uw)- <1rsf[uk #>]6{ ;oߝm"9룴IIEbQԷPQ#'BI/7o:c05c) e[:%bj0Df (hfRWTFk$ bIPCUCݕ`Y/:.K/Ϋ6>E~ t 402tY!aL+6/lƉ1T?M,C1už <#bq|40 Y3>-Cy*4a"4W[NAC~2yL$6u`;Bn=04zxPjZJРq$2 u.7<<377|zzln*S,lĴ\:0jm}]}]mқ93;$HI6lXf;ʅ2JQV3L|QJ7>bw5.[jE +xae^Q0X 6,Y#Hy"Y1Zgb!:Ð!?HN&^XܔV䓮R <.p(XC^b -kR8%1גoܼ) dAh`n>bL ՠ4&8RCEF /`AkfR՗6U A-r FpRIla2e~#">XCPN6 -SyC0Ӏ`1,бjj!֑E'j"{*tlus46h6 Ktn LcF2|\Q_hCai` 5(FHb;G?Ns-X<ڶ4ːC8خx†V$3j&n~#LnO?v:]w(w0WnY(,ZeW2&1`13CU CHJ`0 zR,:hi*4pM;b A1QOK/ %1:*FPSMVIت8qbm ҩj&CrqyOkQUeKggkem륗Ot*/\k]WlQ?~<^*XI3cçG~U^moXj= zCk.T+ ǨZEGP7PiY&?ᰋA+탇uj@*eHRm" en1= Z!PؑeTFƿ E 3Z(ҁ$)tBe%΀CE(lz M',ȯ.Y>Ini` kڔq,0ZK`IfFGmqP FrXJQԀ.^0rf=^jw*%U/>[t N/?A-g`K{R`nڏ}Oݏ jxF&>O_0>21;>k9|[ZzO=y#-ڸaeId w0-jo)?XzHGQZ[bfS  ėמZ5|jȜVŃS*qK F`QF4 ZP2L"0RU,$&P]L !aXRV3 xIl "{34 c 8iPcYu);f<@?! %)Ma*tuDC ;[l`Ō:Œ3x3:p`le,2'<&y@lSbte ?֒R$Tw8gqKVБc,?$YXM@-0BAa , tIu3Nh0,<Ja'컩BQLghNS 2ǶU %(-*VB%%02p;!Ky$ ,]Qr$i{z:z];ں|+NԹdڭt? 3BC0qlW7t!jRhőMuch1#Ԑ5/ (D`'Q2E?s%DS\Tx݁.)(+Q+'Af44lUTE2=;{@9B(㜂3aj!ltp2#c ФrdJeSW[rKd74>:w_-ZB3V-pi@^ii]b׭]y˖~ȟı?Sc׈|ӵ:'\ R}6[[ V9Q7 D}@yirׄ}Z32+c5LΝ3LQ|%_my)4uEAQnMEl),X6v`D7 Li\y眙sW^r'%ڬP,9 Z-KEmT1 -P]@>4@"NW4+X-۪(v Iq%)fl99sxLsgμe38h?3?7Fr}C׊ Qs\F"qZA:=o1Va(z^޺*ɓ'x'|O<؃fcAb,۷wdz|=a( 9)Iw|ʁoH=ͭ╟~鼼;wgg׶ϟ; *vo>(fpڤay+|^]=O=xNt^~r|VfUVisFJtuѹ6z?poT(Je"?`V3`apc#IlT@tC/O]|K"G4!*b9o8ʔi~V{ibGֵ!qR%YL7lz3+id˪Bq.RRdK: S~+}Oٗ^{{^7 WonEC'7߲| W@igJ] n D}oe~~"L/M+W&CWMI5힟Fvoip2."tRǘav@!+>jis?rI yHufDU›04HsQH 3|KWOEj NƪYr(28Ļ(B]xe\ECP,5=Dtn.77 ސb;*OTZ)GQ>.upMK`v= P8c5ζ$ CHTF.KAR5mEC'g>>v[9~ppyդ̲I4Wi@` sV4;BKTdty8F\F>lrf3ReN, C)O(fTm)CYg}h_qzT(d.큝WETtU H{6˛گ~RdG*#`@#=Sa,f%'>.AݔĜRΏ\*)u1Vԝ`pN{~AW6UX+$A$<c˕Q#t0E6y,nX$+r+\H'@W浚HDc̸(PI|Q%n ܍^,BXb75epMSew4i*Cګ4KL-7"R:|X?6"'B5dv?旓,ɭԪ ˄&RsD Y/J* A1ÿBJ?G>w_}o\{8z$\M<^;.z  *[)s/%ESIJ17N3M_iP*A$"*}SBqx4K_ĶU>ΖY%ے/Z{wRæ'AZ$.9{ɏ`nhPE`+N> wWϭuԉF9bs[N֕++fw횝ck)[[&5j61P.RS ^g᪊[6;"iIZr Hڪ&Q !cY SOAA-C)ȩ&_}Xx]}lBFr.mI@\@JvN[(IF@0>Rf;J5=HrK>mhʆ^XK* ҫ KHu$i䁄@U6ʪ<-&0UItA\Mͨ -)A򁢇"H94($xZ^ ne^֪\(~ ~ImBkt<P"[۹|i$a\$C% j)nr ~*ߟ8|sJ"5Cɼ)X}˩Jb>)P?N7rgAU.ÍPc><7?;/уi~;aMtfHe| ֞ @(V~D H ;3P@*%Y%qf&yhVN6,MkT$+ve9\8`;C]}K1Ld|3EGʬm܆HՋgfH[1s|Lpџk*)'A¸Fu2M=x#+-욛qhskkq¥Nu?uI9"v*t{޳ߙAFMtZ:2¹Ua`&%H[9ۗIEqb`H2g ,~,;@_5;!!Ļ>*4UVź7j J㡚S0Wܾj\Fʉ0nLg$N4Aij T*ZC Ur%v5Cs*n"6HR ۽L|g r]`SdOvKŕ=GGJJ3X'WxnIccQ2ގjDWW][BdEc%ҞZ^Ӊs0e*@C@z= a3}sH8*yran@ JUZBn'? II0Lcc*yS=ǣR\JƏ N;qID2 k](#NJZ, r WgqYW8bOjJIT_N2VޔI71•ʼ |UMWR$a*ؕJJ=mxbd'޸]("~c'B.J2S! R?VuGX@]*98I"iZZ,mC*Il7L' *? 6MU͇^D.&;*+[F-k1PŕEyx} +O;wPnL P+"BJ6UG|]+WvXJs(Or4C Ϡqa*0#TЋ>Z{T3E!toV KjfĭvdMfiuC6%C'?ȷ7ߕty;)SBݧ&#m2*Pc3=jσ?eui5ߣ'Te@*fu ۢ Zu\.qׯf#W* 5%(3(+5(I$Hb 7rq L*bK>`\(V*e@'qAR{گdfؕ', 4`*|*R1gg9To8ssX%jOTxǴ4T]q0"pG\i#YNyrn\gʢͪR8Ir!\ Ԗ.X푚kʯ783KW^}o~˫7wxmk NYmHr !"p+r.9>n%=(&RTRp`bg9xҵ~8fKG 68cd4,irЎU.1ᦖkQ!_Z-J*2pqD2+Y,pSLib)x24o*.\YZ^;3E~Ѫ;ud{{8˹k@F@Y{S))%ij"XM#-$pD[z4PZ=h L6) N}ϖ^΋Q?nAђp-\\D (\ 55T"%JExKثpn * @ eAEX^RSUH,z22YOǓ\)Jw 4LN.T+0mFyWz%H,Zu6S#0 ouf4u&ZQ9X2eۣ͵+6E` '>7]uuUIk7m*K[!$S8V,u:jWzB=KhиnբLrJő#@)NM7BVbB}L 'VU+Q ͐^cgj S z-7ZQҷ%oaTB"K 9dz,zжG{~lKEE\ ć # Rsk#$KZdMYиH ڈ 9Nِ11a\xQޫ1kbX H5,S̈`B2Aw/*FI,[Dxf#)]jp Zbp*vE<@ I|k6FQgpȂm d(ڈN/ Fʸcz9rԍhW)oFu#)-ꨑ<5< 7TLpWk#CimvPTREA9 ͕|b9dLё~"I܀œ!wX36WDZXMv)\~dptV.,Kވ鬑ʦ% ,%xٗ?_b/z<6ly)eD'BY v &]}+sC^ܗΝ*ϱ]WOJUv΍Ԁ;HR䝬,5S4O&_w$oZ,DxIU]VAӓ> 0,XסGު@W+]Om1 ѣArB%#y,uzw& -a\1K$#e࣎Pד.甔FB%y޿uw9IvK?.'eyx9p'$9f~*A!G Vr||I2%BU=r(JaMb&.CIjo$m=ڮK )ORzZBd@ Z+DPvGD,Ϟݿ2ߙ3jƺo|cI??q_dw_C50ҝw;7fʽa,Q1;Ѯ4/ʴ?wk⛯'.?Yk֙aeΊ?_|w~_w;?~ƹҾ{}΃w_Fqq2hy3PR c՘z\o6v(a-WFBm俥NFKRRKZ9<7kWm\DۙU}`t1ѥw*<{շ.8b RT'ye[X»qWSr4L#Y$Qm@+*t'WA޿֩avנd3l:HTԜ { =bP6ӌU+}u#˧3X*z3^>󓔩\4B8껗,y7+ƪ5ÒF-%#V+.̫n%f, (֏#Z)0xy+`>> 1H})OfR9 x j?@ #*XzřoPe]JƋ ~ԠF=DN[>vCQ/_cV \ME7)¹++vBKu=l*Z0s5@G4+[~>['ydyܾz}do:17  I'df Lul!H2SW‹+y*$(ª(,ZbDA zF2yYjiDa͆pC UVפF(<``UM C9=NkеB9ڵwK~?ZtWB{vL:A[tD%sN[=6)F.`k,O%~ ?|,Wͷ_o|ݞvp/uq#$|'gff8\3&>ҋK{ΰP6W6ug?_8ыw_ JESf5LհY:R)bWmhr; h1怂B|SNi'}zy7i "+h;7viΚ;ݎJo'@-gBSפ oPgwD5Ai0 gBRQFsA=;\Cl8s,p:I}`cwQb$5AjB☈SPazJADP$*_am( $}JpVB'A z.(T#`;PVkv'914i@-ӇZlX*'%vM!D3E'Nn=RIQ!??P(oUͅC7pU^ :xQ$]4tC-FEh,٪t;-l!(nYN_d.8V mV`S2ShIENDB`fritzing-app-0.9.2b/resources/images/splash/fab_slice3.png000066400000000000000000005165151250202676700235730ustar00rootroot00000000000000PNG  IHDR1LtEXtSoftwareAdobe ImageReadyqe<IDATxTwy'XUuxЍF#g0T )Rd*P({9f ;c=;ٝ9k#$$A "F9ǗC߽m4^Wu/~_jW_(=hK[rO=R"G{ o` _\ o3~ }ȣ=΃u:܏+0^.3  V^Z)_tE2faXxUo=qE$e:iעUx8ʶ=&{kǢYtGx76V2]X1 7Xxކ/v-] eyH*8%'C=FQ_4[N]։С)eպZ\_^QdmiVl&5_ܿwdhoVMebQ=G F]|WI?aOE+#IT\O+:C|䔱$oWdI3qu<1HPXv$*D@] Q$2 H-ዠD@vmz#L&]kH:z|;}o!BY9.PH ن۞kg'&S5MwqTʃ۠H)-lStemo~ǟ9Y+B_w6}<-6j |A`?P[F02;!Mwo3 %ݗNDAJټ, A`Yxgn 3g< ?,l.-́n52  ܗqxXq :4&B[OXdm YtSdlt.z@⁐FB?0X<\P1"q,tw1HL߀b#[nbh.H:l4z Ȯ#,usl|׵Z g7i슐 @WM`M0r[xaSDi⁰odXb)|mCBNrCC>%l9O3fZS㩘cpխ׾ءO{27x?[%(XukZrU_^Z(ԗfUUPӹmhjW!o~#O\,hĤz&EП>syx*mt$i^ * Y#ʭVۦ__^Xu(|4¼(aBin4XUnZXOZRpgt} _R>y'?y ={Y2SgN'e)(x {c-sdo0w(.‹>q"l?40<(r l1*n\S( vxR϶˕j,N$J؂+zRxl'Ç#(cۏ_sw2ۮU޽ˑ~ˤY|"u,Ǹ k8LW7zIq FCV['Pa \i>!$sЁʍޡA\aoi[b" `3XHN q"10D8Ǟ,$ZD+>6N&^'W_q'|+XTQzAAnǍ&30`*6"]Yȥd(8 `0sOhqpI}5v{5 ?9ԞO*\|ii;RC抅n8+ v ⣢DWv& ˁG5Gruɧ]DllZϋ0Tah\lX &y*me$ )I{z;t7on>[_YH% {GG-gD*9 ȓSGտw!L$$ϴ-KV;DGG?$'RC#{I^XY}'^{{ҥvLg_ת(!'{f}q͟)p[rBoo ILo[J$7dQ 'ҥ x,\I%Qd`_caKua,P9Z[wdf)$y( Z!E#R%SfqeȷaKxXe V}ĉ3')!@W8{RTH:UZ |z=u$c3ss+]8/*oSXzAjwY[dC"ˀAx̶\ GO;;M ^s }syW`Gb vmsks"gG}b&ؘQe6ppJH[Zk$y +I(hvaqO`7YE LYשT8}8aIzD:!p|\/& )υX`Ϯ\S{xRa%z{m}qnqva86-aW]d0xa[H#~ i2 866v`9O;P8$\FY8 &, 7l0vCNvr8,Fc76q|Ì\;Rca=(B~#Tih|qAA}wR0@MߟI[7͍3<gw5UFXBL / bBa2t:\4wĽUlC'nsةXg0CDץ "RK7'ɕk7~ϮZFjC'O?t aj[^㑽c}FCo޻;Se7zzI6tt; w~vZ6f'{u_9iS\& 쏎 3,%+,&QLXUr'ˉGW?Kg:K ]K V<{|BðRRw\ttj;7<x1" jڐB|21^kVSi6iYvHMC,Aj%[|cўb_¼vRD#0.eq R2֭.]ų\2*t@)HR!|(l BrP){XH%ue DBL Z`.@3rH cVZ>}p4((%Yl빎|jDIk&BNo5\tjSe'fy/@\x|Ӵe!ݐT6}Ru䊹l +dE[ej(*,,NL,xg $F-.:kO^=s'OR rtݰ]d674Ǟ83|)num!0GO0P"-}8ˎ>dNNӴƏbլԢD4,[jnܿzK3f@#8jtYIbzy.7G?>y,Ya6+gSžzf2!* ]Ţ丄S[c! 4AlY #;׾I`a$|6;qfI$7<y&:+ #ABoC36*Eu\# [u/?R鱻D4)L>7<4808ʕztX& zymgmnm "U9gbb*v#G= ¹~(8$B([o xV*MFAʘD{,>18*p >S'F39z@;~ek]{ M3:r tO15[SSw4\n>|҃O?4Iv::i#Q`]T}csb xre)tg|]5Z#}gWO?h")qg65|L2dz^xn`ʪ5]ˤUúqD*%NfEŴVѪ5yd.p2YZ|gDeV[-ͬ9з]9`V54 Hnp`HF@:v+2)k;fIFc]ĉ4ɳ,? ,;8\HG#@ @֛z}z;!O#8+!@ECq|(?Մ!N 49}, &HGipH\P"9#T5wvv¹c UvG~z{[}?*on,B#]P!cĐtw'yT<2 X;hM8(x2Fxo^vw__($x( z4w,n-w{z X" &fi @QZxbjze瀝*h66F$>~S'OtҮiZMQ*aY# a&Ap DOc!Kc2أ,LL|r ݣe QUU 9/@5ԖVX$ wj=E"Smms69QY+%8wZRg-k(⢸08RVU,& ?f$op YV'6]D@Em3&R,H5]80N<'C ڄS$Pa?9Fi)1)df: , >14A&M+8:,܂*BgLB| QH)Ε| J 3HD3{9u ^}J;w>7SڡCǯ "Ӡ,#<#0CsBI3kZHǺzd*B+΀ b.,vwvwD.sùN:(X;EfudHrez;w̯PȁtgWiQ*J@g<)=D &DeKL;˳ܪh۩T,JNapD1H96˳vēF Lo_@%8TrI!"A \Ð.k0?:LHh\0ۭ8",|8|S.omb/{楯>?wCD,m߿re~e3QQFEdUih&ܵ{p=5ժZ+tvB;xzfm=O58TZ[i.>&+"˂$%i}g>H>|G._ B9W?[ӴXOr==zS#q9i?'΄@&ܻ~AT#D 2CuP x^^,M4IrU + ?oxu%Ο:GG0x>0 ye";NV!g3]F\4W"縚nࠥKyIJ$tK3+#C![f<N}Yp{5݄Md_,%=bz3S@Hccc)..Ưң?0 :nJ>p4㧞|s_tӔ_GnYHpW^?$ҩ7}ᅣ `-q]Zy{]9<''\?wE--}㻯UjXݮޜ|8Å\2'+ܽ 'p<]LfI?~./W&gJۦX.`vYa րIonll'#gN?qx_.ZkcI::ej "0uҍ{}GtlUW$ͯxnY( E/ްctJ8em4A#6.|iH>&qU"2p2@Jw?w2ϼٲuUS8SW5U__Y{gmD{|.ѱRMة`8si&(Q|IP&$:~_Àn5!)' [5A#1AGo\~R;ܞYrSv >ޮ={g.^FRQYW.[TŗRkZە3O(WTn#Ҏ?uhtO>]mֵO?R-譚ڨYYo=xhF<17VcO+,?w/Lt,%Kkؘm۰e 3"2;ZC8K$9rhmuӊv};e)[YeS=#{ˍ"˩*!]jfymP*%s!9Ƃh[Buml> a6}=cG_}7/om7rHT="d,$!h~I8BLI"L(ߑ[|u>D5-s_|k/2{…7nW>yl)38ʔjsӿ-)7֯]2?3?=۷w4U%R⸋$*weEJ ӿՀ2mG±(Jl~_D:GG]øxv~ϝ>yhA9둝cv |/ca4kͶj9+FZny)Jf1ٺw݇TEU86C3aC/' )Epp쥝fqb訒k{?v;˓QM$3++_$]=p Ut[79?MԶVp3=R]}ei7p̅j~Kb >uepm>|^N02A?)e1]ǟ N(moVfBgL9v$& h_i]:[޾5S ~N ·u7VB"74НJ'@\[kPȖMO-LvG|n=ٌۜŭ߿޾\"  ;9wȱG cqؖW],t##׀,KXcO&:}s 3-Zq,ղ:Wuph7f46=JSj/}FS jɃYDGAAP΀aXG~~i x*]zύLҶ xmGr]?{WVeG#j. [oenwkWt4.UAeEh*@f3ޡaqIf,p4T*]ޘXX:|_Xhvifb ȝH.v^~oxH@% '"r467Lދ@JpYH^# ucvp97]_@!J )R";HIzVD {Y/GgΞʼX|7Q4BMIת? bΤd LPD"2J:XY #0T_`D)H򙛟^zpㄗj1kUQ KEjd B+aųFC-Q7VF2/tVҬV߾skbi)bjE([ى޽ ;N=WdnnlPBc-SC<{5)YbpGoG`4hp(Js۩\Y+DaHصm1 ;>`Z+}1#+8HĶt^ EcQG \6=GPL6'"7:0nGKXw{>. 5UP$8UkKyAEP4}B;40? J8WPpO# 5 7Fh>-FˤΏ47=(W뒵YPr>_&Ou`KLPVN28>?lZ&PlW;]|8̻z3o|pZcgc-=ʱ/<+DEyxxOf l=ݠ[;;(<2IS tNb/[ď!5z8o_H.Fvӟ{)̱92V[_s_ʗWjڍ;S>X[ؐ1+aIӁVc/ml놇(of81rh$thGΒD g39&&;Y?M>|45GO\^ %j5<RD1ۚǷ ~z 89 & X[faGz 5avބL0uS+lU q\$-.1|֌|!'kZQY+fgߘxܭwX7x_4k/FicmyinM%co[s;9B(\RC? 4 8Xx#(UIC|QA,Jj:8Ox8XZŹwVL<   wH'sp7?v{b\6zi-`|.E&G^~grd.Ke[bpILf{v=##hn|0z ^;B3An ˱4NDw !Dz dx!=SH˒Z8l\CH3|LfQөx 8훷ONe(Fe_33SSdT1Q-UJk5:h:e۵p,:qp=#ErNjɑԃ.^‰l>LCl%@oP$" ,Qw'纺{=q1α@erRZ[ k{ H"ՙƀv&qzlᮞbg`HVGү&p)-st ^4FB~DCj%t(ody`_0R RݒhYb$/Pczww6ݚ?1 $BcEo[嗞>Сȍ; 9 eX q}9O.m?Cg׷,noL(XڥO>Qbёd: hXX^_].o/?}z'Ukx t ]A^xxyTu'eIZX8 DWz 9$tshOͺf$4"Gzdf2====]o.)d;҉NS5q v>{ٳ_OS^h&`ޅu{D!XN$fbJ/A@ ,Pc <0Ϗ07! aS,?/a~k~$4@ɉ&V$V44p$F{kmar`ޡ\:zhټ$,I~V*q2xe`#IcZXjA ]{Fʳ>~sv˱|=atO\ S(','| 5X5-Ba;!:c?@RdR}Gdx&@<$@zBr `@XZɩR,{Ff}c{'4֖?x2,/:s2QD/mouD f!FP99r'APv"f*Go7nƻ: 6]]/R(uwH7}\۬6X'"6 L XR;Ę='h#bqͥOI|v贛͠vC.JqI6 ܅6)gI:CUfr5f- h7P`y^_dџcF:ΝߊJ#GL[6l{{ñZ],ۯ'IRMfaˁ J썈=XC=?ڍ+QPT/.IQ^[mNOYWFfWv6K(.c{΋/Xo6?xבh,L"U7[L&;SS`?? g;ۆKD$;q˯|cvFV#Ǹ#Z۰0"Q(T2ڱX$NȦz UTOѨDk%Zk2 a|ݢUMBt^3t#I: &x"Hr ת h{~éLٵ9+ #c,VOu .eә @,DJ[|⃋76I8$, E^PXD :>u )J2v4Ss'd2,KPR\w3>3O:=E9\ϫV,|/c#E3n ۻwãQ1_Ů%{YNbGb?UǮ;r %A<qea9AO a؃;@ub۝ ZDxlJ3%1ut死SS-MEqMӖ'<֫?)F G!m[f%E'~<"[W5<6t%$,-H׿L ƪQ I˟>ZzΉt& "Me{ݦޤr9@O4E \6뢘ЮU7X"N!#4d0;"+29g,ex\ PwxȶR~ 3 -,p?v$A2g ;U _K' \K*Yx+!m!ܠG#d Ė-ekaӶwu:h^V9Qmi^HNit6ze{#04Q )r߸}`gqM8(!Y!q( !Xܭoܾ$8Zڨ&?Ö"$pWoW<ᷲzr1v [6$&,"X"I6O@0mfQQoԫ7mJTCv^X]ϭfycܬm{GN_zTw.S"Fv}ܑW~"8p0diEUK%7p:Й5g9@-F@,ի\wW#FyV*tվZҫb1 mwzлAq %Kq,0x.ɣn&czClpЁtbb@%5͹هUX1/&Hb]B\nUҝgxCH @)=g?lСl2w 덖n"_ͲT47=30,'rhtP\6Klݸu4Zb$1vx!{ցh,vk>])m'CÃRYwL.' b^7 S&P0 d7l5oݺsc%04FMYd_o`m>I{O "Qs?eLa *`*C6%w~U:x!f~.&uvmd̂ jk:LG?Q]7Aʒ,8^ǢΞ8qL4 ?BŤ'HP),AG%pix-RxᓝUZ+ĕgwq(ŽEj03G[.7M4@?}̐ \$-d ;RDӞY%0QI 5~_Bo7İ'F IF"DYijF290̆d,mJYeJ(N%4/J`epE*cVб03` @+릮az^٩֫jj[HOIh<#I+Ukg;S`q4AUQc$<*Z[b:,lz^z J|LV$ @!V.(S'@ݺs~igc:vӝbZY_Bc D+S~+ฤ5J"S#̧_Ҋ2A f+1*v=7, ,е+HͰwY]D,fd Q(Ts"/DSǓIG=]f$yyйg^|9EJ:8I-"vfr$!N owȆ;*Iuu QYT]U52xl4JID2V+廷n?|4e.*IH9>Q8z]|t./o/< tg˸^41<6LZkmc^7<,sO>qne_MX7 ,V^ߠ150x'b>k5H$HK(t 4%EԀd`G\~/~A>jIDg&7]<4?rh|Mn]nK+ˀ$Y~#_"x,u5cz{Ң 'WH Br"KEt> / ٨v ]]JD[/RDB\>Odj" Q4:L{}c3I=|0޽/=T+n4S S(&1!S|\5ZRozUi*]s`B ze!먕;{x5ZJ,՗F14#q \&#"a (&ax л0rP/J4 H|}em2 B,,+zz}utvJ0^1ԁp\HAUHxT7V~fۯ&Rw񄋃xU:h !4coQ6 N%HgtPO$һ~AYݙ j[k457ڸd8%D҂JӱpY.߹yԬq|6ȫY:~[޾R&U/WLeSH? 屓ܯݻ:ߠ.ʵA$6g^*8*ժnY,=}ǩ\4d67v9v4F"`0*b h!M 뷦N,NOEXzxx84 p>$RmTQ^\'lG?:Xga9V8|Gxn<*%=hΤ(v[߿@_ze8haw!fRx( 0/D $H$&(çjaj(8|MUuMn fl\-aCCGs _b~e;P <Yo'y_rp ^HLuqT.Hd?ŏ`X" W6#dP$vC3(TLFcCB,Dխݛ7'MGD\%?u8ۿz[f Ut.PRQ[Ul-FӉJ=86\ƀs S/Kպgׯ-5=eR %$UCXTQ=%ÓBE=@9]\թe4E}d { < c29r({`8Zi ~i!eLPnB/s,L0d|@"W#RyrDP$apx>AF+Fl 4 ?ҍGg+U$y /t =9D$DQWeankw{ZeeH4&cStίb\T@O_k'ΞW>+ht/Gr,P S޺uMo<^=1ٍ(GŁcZ3H=񾞞!8!EkXre̎[U4C)r +FQqqBB@kZC8őJ_3@m;?yTwR^[*g k_~,DM3Ϝ/?wtvb)/,ongCM.rrgd#"a.xfl qAl(P8aZCkfPm9t&xaʥyZc1U*R!W_,vŜ*(czK{=ISGWj(/W( 7!8o`۹".>B3v~}I| =&͢6~ K!ZC:tF@V7!Y8omV%IG}q%)T5i(;wln[ 4(i\ށxk{Olݺ}WxB _y-Fp<ݍ6%1j+w3/w&A ڝ~&9wSmLh,=74MB+3^rʚiA5@' esZ]nm,#pL6Ssc~f>yxX?qܺvVΏ\ZUF"hK8['ҩD.\v{I_GWwp6$ b2/|wAXv{?!)?y?|́:mͫAQA4ͧl8jZA;]s a\XcL8?{#Jʠήc /V ?w>OOxٿ6p@50;菮_% V9{o+_"۠wO߾Nɚjo(. ckooesG,ıTyӰD}. C<^pq x'TQ]གྷml)٘<`̔bJ<ߛ:Hn7#ܪ 6;R0k5NMDRnJOOg@ː B /*هw`]@#!Y{#QYX2v# wHiGR]P:aQ,.)JZhdhfXtjK>-165\3sFAE(oZ݁"YZEb +\^ْ>vrt4@7wvZ%A' kOh,,* + Jl-H)Q~8\*m'?YGAtZ_988y$T cwo7ͪ24I ӇYq^xz öħ ]?7; _GC},+&+m8l/~mZ۠QKKk!_Uկ}M/aArB%"3+ow4 B\OO?wsxZA /^S|{0R&Ƅ#/>\ X]sr͌>W]z}gO֡##!zߐ 2% j5POBb1LCȡ4bHx0Ak vhdq?ZbmP$­Gf|1?u ޙ%2)Sӳgu@,.]]gny:{3ST~q(R 2v(F)& IiR78W&92//>nj58DC rX#^5 zLԽ-1 ,"t {`&`S "sjJݭ(kQ72wq ޳CGzܫp;KKO7wRF_“-sIu!19~hl…g`OZd*873ϼyt%SAya.TU|@V|.=/47ߌȋv׍⃙lIX t $ cbsL# 7R kv(fpq?6>ٞ)05qTiӆԦ6`D fqd*V<p 8"(xBHSK `g W/,tynW<G\*\ JAsN 0;Gg7~;nk㣣'-^$[\[uzR)G%Z֑#V@sl^nciKPGiP_7;ѡy<ဿ >ɴm4ͦ\^K ޻s׭]m{\X2M=k6۠7*Rw?^xAd5в&K[;;{kk+F"y[xL%,K.Wz~FO}W>?مgbMɿWlm9ϟ?P(4}~Tz{::{;|aPLŠGsYފEcp6^{HyNq`V<'Nj-2s=/uw!&"E~@K` >B6+KK KK&ˆ#wPTj^-8j:WPi : ],@ hC,#A6w5Hy^:,6NKPZPP/n_yJw?GGzcM!ѲZw;<мE܁h%+OߛM~ s+ݝz:21uEpPIo5)::Z=PRGU&BBq d|"sֽz"cZ @uH./9*ԀY+X1e1j:Ha2iXjٴ9(sET*pxR 6,^sBR=MBR#1 ΜmW^ ԚD-Vc 91=Z޻Q0T*ˊK W>jR6Kœg Æ6 4nQeSn< \!ʂ3z]SN_0yV|OG(Wj+}`1HUs.%#cv%x b pĖ&®xIj~EVYúPڕA'a&o)(X9f!paq#F-b\((jG{ y=/s{A .$^Uu ^X+rQg pkK* HpԤ$bmͪ*"*'NNv=D{;{:%VhzX7uԊ%]q4rn"߼ussk؉ccG—~/.lϝ}ۣɬ"K_y=kXY[B@~fgpxh@f-*(J`0iC2:,q B%fCz+t!,VΦKPxcI3Afh/-12tQ5V*P9$N5y=*^'1b))?ڃ=HPYyhXgqOTi-wLCddzks]q;sӷ{~)3Z`G%+֮NV7EbDܵ1ðz-%Y[}rA&F[x*іx$|w#]r*)@>HlX]~nދuuvn ΍:, P}mڍ;;C[s9y0xRgUwuN lcˍ(+TgYuF(ѡLSC<~Jm,`!#r818}DJCRP xRu5}]&\ b$Ih:ͻ\% GG;6W ܹzMP:11v$/)dFdV$01̠b ۋl *PԼBHp`-85VdbZ#Y,Cu%!P;Ћgǻ:m hI%u+ ޹ k3#Ik}#P\)┠קŽ䡪(~[VDXUrP*DVTɺdIӔңnO?z8^ѣd2y.-Upط Bsݶƛ<ʤ7N|Xs4[[uhoi96>z3#}mm^,PfYS̓0Q5CGV@4s= gL+W(An9It1f^.~K҇W@z$;u~o}~3N??7+}77<ȈQ1eSW*<^\Mcj^.juqmð "+U?vJ,_o^X?#׉#K|;)6FI_ΐg2<႒AWU/,m $^O0o~ҕX̥Ȃ&P8,,P۳NNj< X# Kph[{@&C-"PbZ7^e,3ޝY.Aa-Ž%pf9N7$I35NuMOpع"` $ؤG (,P!,ic7eq{Nr324"fJ6,,@Q%lBH2BhRi7p +>1 ~ $2nE W޹  v &( tꭻw_P}j NjPd,X(B A 5b]X 6ŵbChBE05Qc&v)Z*WR_kf^@MOEfwvvn LP-omn P+xrd0^>u96]yd{COx'DĈpkBC#^O6vCca$ DLK[mL Y(嫂UAj}{WgW&ABLv<>qj,Zҡ9#BS'Ղa!W=Vk{k,Y֫B6}ٷذj4rD>wд5Ǣo_Y]lwG̽l:>_8L꽏^K/;y|ɈꑵwAZ_yQvM~%0,eh⋑2 rawEDZ#ZnCv(.LjK͛l4Hɠ2CUb Zcb*(YDV݂K:<8xpͪ@=vGg|xo[ff}Rv" ECsFtss8Qh2ģ 9hb;ZJ>_ԉ / o}m9>Eq$`eYVU!ΝǠ,w8T¤{u&$ q,*Bb;aᦜZB9,CgΟ;uuc&'ޙl.+7z솕aj ECn="FbMzF ;;{<`sO LU$qlz 7Q#Gb x 1g6EAQŕL'K)xEsIJiwgkZ;qzږ14ݕ*BVWwAϲJdr]1/mʣU?ooerpicm+]^B@STq|@Wow&c3gMpζ̣x,_xNP72.g>h,bk[V@r Ɖւ^ԶUr EvGb& 5 4:YhFӸ3g84iQyߞYȈ7s[+:LJDŽպRTOBkk,yHV pch֌|R1 ֐q#|[<^_^*raq[& NFˏsh'mf"in[K_ 1`KA@2gjm' "L!B5">&_ w{*?66@-6\v91G8\Qq^\;E)UV# Jl"%&Z0b`V2DP60A!%WZX{(@(b0Q/TO>u^pgdCk>޿w˿~_axw hB&rz* (^ 6`!<5Q(Ʌ\klTө Xq]Y%dƢ9{jxIpfZ='k$wA#P[mm8{5yn^57GQɣ*]h D"ۄpGcGHdZ>HwwW(Dt<&"W[OfƇZKŲeA;r֭' |״hS \rr`5Ua8J&ZU| UpDN^RKaԺ DBa# ^%Րj% pW~|IS|5 JeK7E-o\B*yZN>yp`?wg{R}}s;U{n,=V*dL/t2qwQLBC,HZ]d6i]|Qm9msq0C`,=sHdի*յ'k+kB!:V]ࣴ5?|{RgWZyIyH2F\\XqsxaK(ł ga954O@44nj&AA_qs׮c={Hi?/`RMJO?29>ՅͺaF@fY,rmc ^-.e 3s K䩕Kzv+ f;ԌZ].EȦ7o\}&W~"Zy=D<~%-!;aV03G،C}W,?vlmlrX9%IhĞ7h2G~Du_vCr Vh0 '1κ U@↹- R&򥹙U!"Gneu|Lnky5?{lgn8zaV7 4GGܻ}k; P40PuSysdAXc(Y`,Z9Y)mR뛻;\߃ӘܡJcMl`+R,u$y;36ID} @!;985uT,8f5?8 4!};6ʶ^q Ğ4Hp=D\)j5r`_sK15$HYڶ;tL:q0*ͥŐW9szY%nldjL$^diC-) qx>K4X*"AQU^O$ӎAqhlp펲u^њr62S.=?7nXld&M&X&4NV!kҍַ|g2QBD8vа ґa=r4`hCЛV!!ز7~ `} lH5>n1 C A#A @IV,Z;6b Cƶ6U(e_cҖ m8c[ȼsg/l8H"iB\3x#+a _|G~?yЋ/RJ |RQD9v𥂔TLXt,PR 2/USLj/uvn"~6z/FrZ2 M:'yȡ5StG T+(X v^@+㯾W>_lw\!SȗJX7MtĪ&<) eчUbĥG^8wɳ B5jm 킲FROf'&åKtZ{/2P֚[(IA6DVՑ&eC ,@+(e(Y5M (82]^*³dY kDZ :3^t/ˎ9J Ych QU[`b)rmm=`v)fӲWBϯ*eʦ<4j8C\H!jm ͥh u2AS-H\ZkfP/}c]- '<=HeҜ lm{w&Q4$>z(Wu_s~GY^z_ 992gd@SOWWX iϺ@2}coOvvҙ -O1qDT uwCړŃ 2mB]!t04(& 7F-`QCXA RTPԉuGB oS*ӳN| AvA*t`NB$UV4,@mЫj d<$!P`8d8 2pgt_o[pKPmGx', \3Q@MWߞw79aQ,6%Y)!m50 Vd\tQT4^>\K!T.HP u艉 gD\ZZ]3C1IސM0wDP8`Awp$D y/ & ㆧ'Oc3P0 GIo' -bLJ68!#+Ēލ,gr//Fd+sQ#Ƞ2v6זzmHL$8H*ˠ8%! cwSۦcd:܁Q;HԱӘ96#X_ =o[D^Lmr(.U!rHpxOC@`qbSNDRt:^#%HN4 d2HTlCIr#eU@oH^!iW=£G]x:zp~'6p{ͦHS9%ww ת~i@ " 9m$SiPfAƂ1Q#;qpx@(uC`AdSmF$`vs{7/2t ȊGޥ1*ݚϫx|A4o xhx(^]*T%Brtl{AJ^i -6Y6lqWFzOgnϞ>u?:2GC BZxgsl6_3 +<9ZsaAxzKb)LKX2̡.B{ArǦcdD1%ߣwyoͪQP0;by0) hB\6FM_ıǏMNz\b!OQX,&v$ JРɪL"Oy'[Fz]UtPtegѼ4%ȝ>;z'77GN;qlG&4G#>UXT,' 49s/H^8V&_9ҍx9Xѧ-Jm˜ 7* $mTl'bm` a$~JLH/AQArFA K Q@,fKqTOaya&Rr4O@@>gÁEoxg$ews'zMHMju$^^6U'[+VIefvp`; ꓐ'B &Q̉[AUۏf?Q3` Fy K\qhGOp ϱHL?˱w!א#+]imLat9.%XHP Tda=H$rW^Z_rX[h \6u_ MbܡF%n5+JGbRZt^M个K媵R.VlAGijG.Id"qXW}n |TX zݽBAMy8Ȓ 9:FD~" M.p # rưy.A(A*W שiec/̒xBEmfv!Xg}鋟/?W7C;Bx X,^_OW{)oX&1eE5GR)zCr++)|m\Qr?tIޮחWWW^{㓙l>bZ/! &!0!Y9 Xnj[:پeXP4W,PqV6b]NsL6 {"a8 *PcJ{^WW EHz8Y#іH3 YD^ cRHy^S獯~j?jrP]<_9=>ny9ZkL! ( 8V't6P$hc`0Hr,{DMlb1;vXzÉE"氦mut;nE^Xo{O?Rd\%V8" q#,Sy٪>%vtwkN)IOz{{xх%A )wu';ka"Ku4ղL/I.=ɕX,hh;|3'_zFw.@ 荘#xth Rx $.D 10|P'\q ٶ, K6F"0! Bcx ;jR}p 0 $:%d"J z_KM{Ya݉m~W:܅h(a)6Ȝ p #6U3Bj"C,@Ʋs9M ;:!`i}7. p\,<^Xٓdi:qR* >ƹ4WDtMF-bWϷ/bү~8arl1j>??ڧT4U@ʲX-W@iniƧj+3Ӆ' YUeQVWVN4wWVMcN,hT;S/hW/ٜvGZ-ѰcAT bb93ϝ{vjbwqik ?>5V kfۘ6f̆'ŨM"^!%[SX Ԅu4U?u"t ij0a`}C, jV~==(C=`ȇ8,ܧp[qiN s~uymZ.tUlxȂ 8XnQ871v4w4X2Es>1XrZ]Q3SRX{^Pk?^gTKz9\Z*67 âȨlM%N1 ^.vc NEfx7lqe2;4C…LBJ"#M:m(Q"r\T;[_zš~K>=ug/De{mT%2|۠)ZPHp7d2[P~/lR^GWsw<9~"x7*P{լ6F=,F6ZP$Gu~fLė_];{R>N x<6(u!|n^nV˕T\Ueĉ> A#xg@Ve3z.NL\ tt|Z>L*:bMEÑѕ+ ?>P:g4 lNzkoB~W,?N/0k U,%]<䀊m=-;H@+XO5gފDtl:JuAs+zRdN*5bRGGg0x5%6B :TJ&N_;^.?W,yuy9%!D LIJij׵-|Wr}[u.|u{֭%JHbHd Kx /yg{:K=e(p0of1Vyr]`:PpM#2ahZyu^ CLCh&?xTnuwwH~^Ԣ@)ip[jCar0+]]g~ؾ?  @\XQGQ<,Ң*RlfǦglvLpjR4qד Ԛh!wߓǏ{$oC2 63JY 7өߜkA]5uV#@I U_ib X. 2Ⱥq(EѬdu U?VsaaaffEp喦T*zP+Q-xg˩+Q2lG2*xCĮ3i>effŢ/˾Fn./B;_#tфxa`8AZ[Ľ1|O9ά YvQPXi A{I1K&9KO߬y|}}]lT#H<5&íiX GtdSM{w4s!7ye @_ƣGTTSS8&^{h@RY#}s==OW֖N7]txj4XD #n/ 'VbCӇv=~i4T\~YnjJ ݳnvhh7Z('wDdQ8nzE%4!<$UYk=IF~Q,<4߈+]dk:TP<[r9𷶴ϱ Ln *loi,p1nWQigbn~kiOf蠘 ޠl"{$Vk:E8Z2# 4øA/56T*JMSA55XntuX\,//WrEp!8yh֣ r?W7J?2x<Ԫ2P -*P!<+SF4͸u[]]>Eq&u Y$`Uj2.J"z@3lъjhbֻ75z$okkto{` آVh?pbR14=5x胇ӿ[[wnAl !(K~"EJ)ECH$EPgx4?藣C!G7,V+j7/,-n]ۮgN]Y IS;rSl벉W%d6S])wWı:rc Pvĕ g v.u 0f+ Ư\Hq{@W[k%W =@i7x1rW4JvN),kQXR d$q]Z ЂFS21'Lo!]*ʵn?akxjC/f {&G@a b;llMGp~.&_!+(b\A:ZKwASo?|@/34mjr=< SzV3kf7⹲,-/uvtHhd('^!PCsW.\3g@ǬV9K]J-P`a"vv!EOO&Yk&%XM(/(~\gAT.T"C#ñX_Sbw+k|[5Si#p2k .K>yvYxOSӏf{e2yY [)OL.GZu>qk$eȼFtlGJ(`1!Og^рȡpd6*HJ,:o{\y0rꕗ=,Ñ09ac3. ?Z3J 6*>=-]y?*O/}hr :)Sf6C7(c"aLXη_VȞp5~UeX( 4٦M͉:L gU}s 775V|GkoTjgXDߩc'bс#Uh~ZsTfo?ؽnj)z8|>!.B{Lfk Yx _hc}k6iB ?6Zڞȡqd 0{J]qɹgk+ȳσ]=#Klwpm~O %9^u $ SxdM±n諫 =(m`eEAT֕*(<j5p <f,0nUwDuuq֖ƘxN W?/V1HV s:u8^V%ıd"YmTccC(Sm](nڔ5pP_FFZ-/-=)UCP v\nƈ8tpKVTm~a̅LyYR--02lv;ܹw~ԫ?|cÁ4A@'ÄO?^,;ӥ6A% 3cR2j@0/._v9y_Dѩkw==w1eMSj*@+J M) >* M5$Yz|wbay#qQM>{zӱIǼ, ᠡwc涶ײY'nj{UIJ|uu#͗Tg S5h \L6EP4$a2J\(V_ZM@ԤD Aˀ=2/x`D*09x*rpy®&$ښn: ]16b$h!qQFil! SiW ~2v(8BUC4:T] 6QawcE/gfsyP~v{hx{Am \g U]YO~iW(ߺ[rv͍J|ɹL!DBH8$b HFo\+[nJ5X˪frye{Dfv̊."τƏGi;DK$1-x\>;5=ΉRskW#h95 "4" ~WCt"V(x!![E]PP+.օLIijH8Wg8]U7X^hlO>pJ3〴򅵕_|uփ|TJbfgγ?7pHw_yP[kC<=N)b4ݴDʵKWT33?{wSSݻ:[]m-t1 bZm@Qg JMuiˢ'u3<ط% *\VA^X\@0 @yG)JX!T]X^O`n"j^L5uOpW~GK#x6 1_y}3x$ @ ņ)P̞};G}`HCfiZO^.|vOgKGWw<(6&ˊMulˋ(XP^cjCeP0BM/V~x%)*M8vU`4p۠uVU֢:N=qV\ODD%FuWX O1А*kOXt)`Du ;vEψ|D\G8Xd\,UgN;WRHI8$N\d9k!94X2ӕGãw*;t|&* QUk(w"za7qQG 42ڝnR7ՐVT/^cR'dL >0O"6`JۮKd #6M3 MxheVd6u((D eVA ټ:Zӧ̣y@14(~m^7i!ZP1 %G*6DQ5eX"5} ,BF̄j GۢGjJ)ԄKMH)t@aqWfh{KWgJH491t \^77xAK5!N uGg'O=tGsc*$ZRVV./?dk3bA mnj7lقN7J+*wvV?/. <  wxʘXPdXgxT=c'G{rƗS ]m-㵵w1(:ȼ'Gv?:<8ОN}nsBA 9 }(ހC( P82 <?xu{ 1;uhjf;'/0'uH:[-{8>xjГ/>#kAd%2$ QX&4V[׮uc B6G8I5Fecf3Xf3S@S /$# zE|8vHAI90J5~do}@ǵF1@o91;s}N;?|'Wίf痷֖6iQaNM0A58}ZZi!9:2Ms=4n8386 XLp^Q(\}9 )]GvHD#1.&!-(NZ&/<"Z_HA"d6Wd~K:8DR&!@oF3gfs΂~Ah$HRV]:wO6tOgÇAܥaK= C0(>F]!7Ű|!|^Qx0=ǟsBK쓍q a˥mK-B7N}6K#pބhȷO񶄰80 I,H=gcvBGQR\Ǐvw^MV;:(d EL\/À{ҥ_~{4iԲ/~~/~ŗ]'kvƍ_{>PEܼe0WU1^^ӠͽQ7 2xMt8 v;v $%C` 6kAhue* Ud.9H(>w4 BraG&+yZ"1,i?=#LXހi@S4R:@!UAӃQ?LL$7]\(*Z0)|#}OOjT;݉Oh/l*k<"Ȝ;HDl][]3CZ[Z >-@$)1Z9gca|lny#r;7^xV6ؖnT yfI>σ"r%Q<2L =CyQpEE7|`MHs[HB!_+co:#"PjSTY6ؑ'A3x 9Ȟ?bgN9aAa^4MiT p:CI*>TŸ~AV"A6}HJu-ߔx[ 5+ "P"Yf] -hqNN,l,oBW.tH, ,$>bdB8U4<:}{ۺ@6T4uk- L]dj=c9Z=i=]Ѓ#alRU\ "IumfmJK9뉰C<K$7t wV X?tAB *T3}(, .yJM1G[$Vʅ?6159_H28uQ4Ux,;577izGgf-BM$fxCp_|9sz8 x+>NBt.JomA`6aCBxg Y~Gȉ/lNwu3R59sjpw6"ϖ%5"܅(i9nz@߼:pEd .Bc1K]v(s\P{АhB8U3G9uBi\.ipTf%ul9Uߠ 1WNנg{CCG&5ݨi51ҌCl>!vxi.WЊiw_'_ZP4T8[sN]C Wdž4YAiBnB j۵Zo]]LQa(-I81‚rsyKs0 y#@(xA+ko߱1+[`1>D톦x`=2ex" RE\vGk,bA;tw"S'TDЁa!EU{[FC/F29@mH iF>[9WUC ]U/ֻ69vxÃ54T) xZeeqf{z:&4T@cDӉH9均_NLB M%Ϳ RTP<ޔ* ʆݑNXȏ *}Ph >.{zrOυe7ϴ_5?3已R$ ʓWDR5Z.`adYYN;{GZ}~_=;z;1=~Pء@r$= W6QCC*Z-(˭ts.޼|X8\wo˿/?g8gKZPIPn۷MM56,.t$)% 56&ճ2vOMaփ24;4: kht w]/>|NC`(Y]޾;q̉}^-)CspdϞ᥉X2mvƽ|&nrDv0殔 ,-XYh"+A3`z+]DkS@?GH5Gnv=Wg.~>||ulj!Hev;[1Rw_97X jϩՔn(lemZ J4Y^gCvjخ̀ůbxb kAJzs"vО%UWx4:xVʠ9/ i*>7_T̈́|p(,z嫭Q6B1 9٦x4gꐥ\lSǫaBa1 G&a7<ٹgjC ud[|%Wf:=4P F{p4& lWKzh?ݒDVkJk%an,:k؄R`p#{+s쵋 8'&A=IӕX/]#Z+JkXę:Xv,lW$|6߰v5d Z͢ŔB/w& ^b:6#6 6b0p Tq>9=r v iUN A)jQ9h]-Qeܧxh"^ɩV.m; RU,hPE<ʨr%s'◴*$մ ͱ8\^>Z T K˫B+iUM 'iN<2x!S2~ڗw8^Iꗷܛy\*Slm7/<6~;Wg_HxQdKyuH$`vW<'߉WVC߾`|zӧ;s]E=K?9{qKycqŗOzo0{kW_޳LxW1;4Qn)w0HQ34~LMF?f% `(a''rHC'uMHIZKTJ,ʐƒ#I |> :/]X4(Coyaz&fI g &G E1o:;*`D;P ;cg<0?i Okoijnm͖*JzѠ7KE vH(lx'tRj`F|yamИGLPԳ u)8=D \Rfm]5 |ZU5j:C02$`aKP$[LKD>đ#Q_AmCVl/=jƒ 8' IYIַoo_ؐ'V`P>uph$39 "9LԎ"N».5u+\'J(u4U!~'J3508JJc9NFDxD`?=!"MjBQvI֕䇃+Ш%Ah֎a(f\5m:n|҇~],7 j>x~^ŅͶ@?,WƖG/>^\ssH(6r`zN(Ǹѧ.|Րn;s0Hʛ_|g;+{p#!S߼1ôemgݽ'3#SC&F!J+s.Qk r5Mh'(vRrʦ,,Um@Ю*+^`yfX433յɮ6$\ Qص2k)44+{jժmkUkhr>77%s͉3E*ET#W0=_ݓ[_+̶}]]@P$QU y}7gl`8HPgKe)hjj)_soz*qڒ)" @<@=W}fEǞ9c6 ;DP%[C.( ?o}߁7o]pa_]GÔVv"8,޺Y(ښ١A"@hƈT$ЖnYqrzq~j;_qPKBAY;Swj~'ñADL{ %Օp4<^_~.*zMrVjYi8q+Wggff;˒Ýy99n,. S/=].kr[^{43=xK~fg}wcH^YȱX"f>P9_!.- 7+5ÆRzR%cDsT0خNx8h XGj6thX0B]0 xHB⬦bAjYK|Ts2B)Z !Mdq 4es [[GŹZY}vf1Y<b9U[$ld(+Ix}ujP4x;Me%"A() cn {A2;{Mp #yV62c9Ckhm,TSS3Ӌ+_ͭ-G#!(Ia5u_)nmg+ۦ^s<.gvz!7!x8s64T"WO(LV.@ DdU@=}=ٻ՚uph / z˅s_Zmspm{wRe x!BT$rm=]p~im-+-L/(AP}Cà UU{OMMOAr.KW֞kOԪsss]=j m O}&zZ;~_%4꾓@ "w޻r/n}yK:j@?JՅ񇹚y@9.L7'n~RQ;ra}d=-Mm weƯ^ijN7<QDv` pAO4/O18LL(fy<|LAok# {yzrQ Ȳ?%"d #èt5usE2e@4"1\K: )K emyjX.n5 z)J'N>uk_/tjmkO$ȷtϯ e4!2 S Xo+?|9B<:C}=jl4~O.wO< n`[[ K /}~|jbh4\Sr|~N@mrE$_{GkS2W5H 1aj>9.=]k3h/9?@|Ƭf{^Hz%ZGS%E "-mOcꗗ.;N "OnIWڦadg~g=Μ8J%&^qPQe0M2bVW;nmf2ՕO`~Eh5pZ0v.xa1gxٱ@*U+otD2vl l-L.7v{?ȡg_v?+W6766X=ͱ$}^Y5 $9P9P2fEmW𐱵oދ}٧f._yN)ܼwԳ'"Wq@m"k@C4 ( xS𞑡XkK_ OP4dC6͋\U=]hFY /UeR4ߡmIn="/x"(WG{QR PZ!1=@4$Yoֽ>r/ eU݉7$=2RG4fl}zbtP9R 0E-dIMBHtva1m[)߾xٽPG|r'߽+]XZ|Wkу3+ =M1K3A,J2@ *-MQL+{ %\No*Z9.}ԕ ZBd!%q6|uX(5Sō̍˟u5&Pl;_L}gCtô**/ Z[殞#_%UXjEMXFus=dj5#ϯ[j&;hycaV FŪ a"4>yȱ6+3َ&Aoo 1 5Һ)4q@K^ Ef͌ 9uH/ ӕ\(`u-њՍxD/ͯm'ҡc> 3+Wu΍FΘ9aDŕ{Zk߆ow;=zA%JbΐCN 蜻R58"htW?AQ.+/M5ҕ0 nۃѶمfrK^yv`-ޝwBSG As& n<b_U¤܌6itz:Y(0ZƞxA}H xCj>4BLg*MHV &+<9**+j- LM- mxhZZr^FX9nj޵N2;7}N5]m:< !P,Tr,%`z&N%Ja-w_T}b6=~+=֪ug]yb$66.;DH 2D+եEĸݮj ̯']`rSvǽ[b:ޓ% ?Wsz9ݬ.ͭf7 .MUxO?rP(ymP={{/~vve,43y3)-,YBc&TCHtܙ#_<{zFMA Q}%n)ƲZѴ,iXI(䋚Rxnd_k2lV*889k+ZꈶIJk6p8|p*[]~pP_ϗq~tk}zL@Ajbxjf˱''j㢾ECˆ 8~t !C|P*Dhfb[ln53`檅8Ė! 1 w8j֓N!_ B)xe]Z QC 5X$ M&&&[%zψN&Te2U6 ưMܱx[q:'33'JșS_ڗ>??9SOA;FCt(PաeW..4OzMլ j PJF~xL?vѓ's;?IKxgFG;m._nbomђtJc)P FC=@KZ7ˊN?Xtގ7r`nt9s@YbX͉ D. dL:8W6Kϟ>Keemv. *gҜfK"1WՎHnI=xa%M DJb4?45M/,+D0a"bͱU(ޜ2{& 4nLmp=P 7:fƓ jaPri!pb'rT-WADt]WTP4pXjs}}' ^mp $X.OO>u6׵ӄnIV7o,=K\[#S-?D4Mk4.!`%DlX5MAoBHXä$LlIIGMJŽVDEMŒB;%B'܍B\tI -@%E6}|0,_,=iAXk{Atʝ(HzV,2B,Y!fnn7m9nuyd^ߧ* /8\g>xD &3 JEީԽG E6IX(( X6^'r~O&?h-~V h9_PTnL|wq]bo{2P` )#_va ڳ6ߴiQY|Bu|̂Eh2<'uQN`[$**Ū u !q)!@׆fOE܎X" ]Z8 h,V50)*A2NV [+Rʆ} cw}(j+nd*NGJ$XΘ]X[s86Vͤ vtKzYSFm-hdthgLt s4[o|q`[RcPA=1ñ4baanas{~;]n=ؙwi-p党RB]A'deg[_~QA ހuExGw~>my* %INTHf]Қ*vY,Aa1M5"Rq5wx]Mݼ 5?eJ$JF8U<(qPD J+Yeο'ߪ]]N;_ᄶ(o}rݛQ\yog68۽-=DOD}gАC6d\ݛ|zlL-m.?ou Whi*,1 bF#U.lo,l2U뚦+|  ):{{ks =l:+ \YAmH+4Jl.ڢ<mi1l,E@=KőVjn0xj1\Mlcx hX JSp3x:Dc1`{ֽb6hkxqӨ\"xsmP: D jT}h4aWYPkkۂ |x8E&yS ƆmhRg$-0x<0dE n[[+덚FABJ#Y¬i-76 r8 }JB}(: x~h (r9` u˂ j&P^--??{;l *óԇo{/_AvR,(@*BTKj}ys{~vRCQVh$ Hw -D $vbȭ!|xI +$FU/k:id@aR*%1 V~,Jg_y>!daǙI5A|ݺ,馢d2o<{xu@bjGw\~c.Bh PJAe͈$n ˦[\r㖜"8=CGu%^=--ņFPX=:b.fP_`e#Jl $ vg_atHbvc}cw)0`/w@ x@ 4Pd@ݨr'FTr+7!7Z)oС{EɆ * Ĥ*ymvF)A}dzͦL4ÁdQ&g'zǯ{F.wHR+WPBmY6rO>); k=~D sƴLwwWM/_8tJhP' ׫ hLϼ'(Ȓ@ PDW1ίZ~zә>^\ Yc,c)>gXN&`i2k-Lc1ЌoB@ zpU".NؒVd B: h1ZX! Vh2C]Җp:^f`^"wAYH-_WZKna:pkz)uHs7/_^a4$)_{3Ϟ@}4fy4v 嵕z"ȍ1ƞ n0A7*e 470V"b-!Gd[9Z 1虌U55Skv v&rXGmzFi9 I !!l&k~ͿsS=^ϮϞkKsOu{`~qG&;io[.M"UZwߢ$2좠αf{R7>ȁnߡQ._TMNQ4-}O&;`G18>>cξh(Xfi ;7T'90:w{Bq&v/U^ηS&vih3 jXg4[\bCdhx T) &p 졎 /4vD/g5MZAnd+t*[)J *ZƱ=v˓NVּ/ϜJjܭy'{{<.:$CcBZW" >}<9<#7T7!w 0P,/^z:_uR$N(J` D񳥴m$G!_TT(t:7hǟfVO? G*HАC<%6Օ7?^B:q0UyhB4dgWQ#Oπ'D.~8W_H&?z޽Ɇl5odۏdJAX83 58V>0mC12I@SG%@8$Qf_5\X2H3FK(*` Yy`? ?G;lCJ'%Z ũQ 1 /&WEMR8F7֭$C˙fѥ!vM1_gH8ŠgdVg*\:Z9tJ\(JexWX4ՖT뺚77wweAT:e1(VGZcd-g_ Ői[`@#VC)yAU˅q0 fZ @/'t(!T J*My7,WϽ5/e>|e#ۿoUJ RK΁3gu=F }V<2n`ڜNS|to}q$DnfPVUYSP4ؠpIіqBo"UހXJiꫩ9fOooWopmMҨٝvN.>0Ȅo Q`'.(ndr+ r%p%@TdJo&DRܟ\Z9{㈄ۚߨ=.wTyo-OOwG=OrrCu$9;iP 0a̞5:W!YX_Y_Ntm:THbLJm`$U,U66yz6 |7G'.h;^`N44]nFc1Fw{~{G $rpa RJjkMtwO)h{m3KtuTLkHA鶖?Xr 3V! C wOڲhf uD_P@k* HeDth!"4"}U -*lq ܈MjhŐѝA&<~!72IeKKύVV:jZA.~u0INCp&o??h8fh8Qk Eܬ9`>}6H lbξ$A3cXw0 &&8%}m;Uz}'kz+sFۺсUkfSu!FSp MC oZ"BҖVyֱ(juzc+cmÇE[; UuCwv:ypJCQdް b{{8]??={C l +pDZbHX~X Dm.j*4=a{GSG=TK7^H-W>iN!g斷VcvA AP$45y4Ia}ivS9GWJ ĴX#fw$ SJ" oV݁doO&A`ȰKt 4miWK~ eDeΠLG%x+uePZpEkͫ/HZI4362G( J Q"$ !t0#̣48CWHTL.ZtYa_ kOCpAX3Oݲej `ONa&RX؃\gMGlO#5#?{.VfkgH$^QUXǧ N47|/h`y{F,.‡X}!3  H3kf&=3f\(lLXӗ""+DPn ,j1dɴHb$cf Mfbuw&³`v @`|ڰ{;WZĂtwgwk7ZkM}/ C3RbMyc40G * ُ|F*1 xV:i( Կ'dž|^QoLݾa8N[|j؝юDsrT834 M%fv0ʍACywuĻ"N>Z@!]u" =#e0EFS636}|n;;ٯ&Uu46!ӕ͗D$}76nNC9838RAvdJr:d:=gEɐUz=rfjwav}guǬ+"fӨ렺;;+O6곇= Yg<.7M4&" [EM1 fr޻}n8@gyBW7.}.xD2H&cpŐ x,ː3T_]T}~{B:Ԃ!eP yB.\ ]h8yVL# i 0/p:jFەF5ty<.MэkWo76 Uiz /qn M5ct_2y왡QtE;8).=ޡ~PA m cC}Q0:Q>CP$^@v1J24BBeueIvL8Q0@Mt%"ul@c,:KMl1Am!"(:- i)7"QfZ/ ]uxP$ЄF8e큁&Qni?мA$#-1 K8yoq~fiitFB ~ѐgN7?=}' s4 RTRuء<q#;[k[nt࠲T*!l<5X$՝b~yaeiq}uwY/DdZ{ۅsfhҸ/H3cLUX^˴dcdQJ}O|893>@ ܵ ^Z=ݝBG=oo &DFq\"@Kc]rǓ ZWn/V6Oc&\xv.ԝod (7uڇ#6> (Th: vwG0F-ߥΝWGC9(q-@I"Bᚬ*M9>?G1:?a tKB;)PF 5ʆv퓫\K&=1>=Xo@Owgflp*0EUyjHT!67 I7Q5@I/V= h^gr7X٬!`8z$VEwi,Ь, %ĩˢ w`FFtE̢h*jPZy:d\ךBZ޻p&gu 󆾳1hQ,:l݃?q6v=褍^ï/ Ցav 7 M. )Ԥap@i&wrMḘڣևK-Z)XB%ݹs@o,TA\pg jr_8$0 bg{{ m]\L^x!(.ec&LD=tZ,NZ.f swGێ? sxTJJ=UrZjnz)5t.ANV<=upK4uϿ{|GU%nMu嘃@­A`AjQ^~ndIJj^ Een ΂+hljѨs KV j<7ozǴzɛNa<4 p ^C:QW(2?;iL*·wTkTccÒ-p] aګo1cYH@3TT|#⣻ -2hN2M'Rn E5L^7]DfW 3$4Lô,Z2*t$fSoUL#`i2Ib!y_}HV+H/KdiŸ[J{luZ aMY6AXPn9K&:,7h 3 B%pkF.f8{hy-f 0u:Vmvg,9DS8M A=#~ٹw>9~%c;8iı>8:iQ5P=.p;s! <6?^U/7&|)+l0 iV3MHMiGTilKvEh( k=,Ǵ<0/7ufZ~@XH3I5e˷oޯm:vo3ҬTerWӵj!T &HV8s?V=hD񑁑UeUWVWf0]؜&?{nbY޾NAW{Fvmt|\h0rD j+՚\.nAve4ŏĚeP'װ;'L>zdà h]qb O BӅ坍U- CP&Ǘˏ a X0 4Rb:k}94xƏLk#^/:kqN0t—\.UtMzɓGʵ:lXZ Ȋ޳N$VNB- (^ B4LK}Un@*Oaaf%mFN)RxBI|%fbG8B~@,!LKy۸qL,"~LVtuB&[C4іmyAm1+aFւZC& \"Z/Ѡ%'@ s3OsR @.T2 N'ݷ>ٕۇN xyRIo =>Ro/b7?۝^ЪJ],ϼp:ڑ@#Z|E|əOق˟^E80ol67Rr炇dlt@ZP$Ge5dὙչu"F! eMQli QMZopྑaн  W@5EpdfApW1Z ˂!l5Ņ1N2eo;g3{Y, R&IdE[,I0Ԟ0vgȯ6z!aUS{vai FZkO M`X[`l2&"3΃-[LaahÝ"s^a}cmiih4flp@UU@.H]DdDTeA 4#\>cX͑e]3sK+ k|@ n2p{ewYLoa =d³A7Mft ~d K}05p1 Fr0E>$^D/ a ad" t "Ϣ%K6/foH&ZNvB ,'JW&g6?,SzW<]:O:HNQ|+*ͥ9SΤo]yjǂnm*2{ ޹`w}X.i#8pbVaGD |xYܻv#phˍz^N0Q 8 Y՚Gz]]\t}կ|/X(FB^G9asMYWjutvIaum}˂ܮp4)V޼gȵGզ]lu9$ }_, _a7~wm^xR:;0K7kt@Gԉ|%[oC9i667V;LJ}.lft72) tWqu5foߩ* Xzctn77((W^yI*HW ߾hޝx(93VJNɮ*Y zեJ @SH^P 78x{};=O[R@LӖϗJ9ѼсޣX7<7ёkM߸9){wˮX{_@^xB흕riՆ(` <7VAfM-B%T@fh8)ðl)`y4=5onue}a/D"𠽴5N6tvj4(6@Zfrp% Hr8637~.WiI?L&YǶ7V޾KM^3Ǟ{%U٢\U@ ,X-" Zu[MgVV77bmԐUAuL/ +0rW]ۂϟ:W_~9~ɵ8u+l.l_k{f'O ,98ZC6!4 Θ&ROͅU aQkR(9bS82`,x80 1˗(Stבω`K(U/P[׆#đI8G p1͊6;޶6@썴E]6In؏Ap(w_F =5yߩkr^WW7A ;dGѠDp : }EFd%2>'|8B4qβ %ƲAĐ!ExBcm !tVKމhn  a$N,VgnX:ƌh@ JF\d:_? ||V9|QLohukf.{%6եmP'cg.}vgF>˿tƧo);zW Ol-A^!:RE6ˀ?'wsM%bjp29zh,`rb#rSǪ7p/${w=_ȭo#9;VV?~ ⁗^}_Ӡ"T+x0v2KC}:'-S\w0uQNm3;k K0ՆԫH(gN/Tՠ]>tNZd懗Z6ITk Q@n.ʊ+f#ټ33 8^pʛ _)Bl <:::bn@\ұeYYmVU}v9=\If Qӭ C \I->yl&6ϿQ,ttT+UR3 +N?<\WT:xr*qǺhe 9ysav;uG;O)cGڻoW^yn>  I RR*:[2,<ˁtrmu~i%U*HZ˄?i:$xTGYܔH0t؁NLt5I5jʙg>yTn( u"LJS8 2fXě6[9,mZbR3,bdw(C[U2"K[+fT /(00EKot<""q=m̞ ?73%EŠ FSE3[ʨO$FעBm YאF!n)tL.g^}Ij' xQa%gє.wo.V낍F4Ţ'J+t)^T ()FL{/F Ɖ7^r2dFFGPIn~fPGQ,c7.jEkv #O?  !D=ԓaẃS?ރ&T70'+:' l,+ў\ޝ~25'^6dwI>)HA/~FO`p߁zT,}p3|?e;?{kk.u#=x\6؎Ϩbd1AgaHw&c=Nrdŷ?lȱ$.]%)K?_۸ycWW9qds8}KH댣v'_j6ӕLvv${2FNoܭ+[;kkr&pPu ڣ61qɧ1G?"+8}X§fbpŊZA[?AInR7172 ާUXxGWWꕪ$dfΝ魅P8"n zC^6J)+<Ǹ@aŲj(CX^zJE)M+E%pH?g'&ڣӽjdBG*DE9`jdrng@;=Ys Л#ǏC.}GLN=a4_7~n/?s@ {*ՊhCTZmD/k&gϱC^8LoW72j]n4"HoO30r:%F#mP,X0-GT!eB[#X4e]q~] &'mP80 oL[DІcf?XLNP?@6wgV76j&n_c3|pa+_}SwyGǒV3vV/$߿6>z#O?xϿO>L񪲱r.Arlylk5'* {lB~{R>8zHy{glc;cm.mO޻x7^=2sͧ=cyJ9^}/,?KMή5AM]ݼ|cKBWe5v GrM}5YXVe7C`;e8m}n;7/Ѯš>U1 xhb̳'FXURV7Z6MS3I.٤r]%qtFsvnk6'"AO0rN6T~7MZt+gYs<odr CJ[km:ܞ|Ch/}ζ9~78|ͭ`w> Y5/_6uV4{կ,moUjZЗvR˫KLVdAt4vl^n`~h=ߟ?kVXTWdXlȃ*6YwϽ02٢P4$i&җa*6 ]>׾{+]I$%fr"'qrL g4:_Q:pfTW}|owk|~7Tطw\Z/o2ݞLdQU *ms9 |,FBٍaŜ} EY+岵21-֛0l>_2UUfN<6>6  N7 E@Z.:0ߖJ9|:өtw˗YL#Dtd~j@<&+fEmyhBGhQ ^rRdݴC%`ԻeE,IaZ,pt-c r6pGd݁gwq=T0N=8$2*ŰT1,^)c!CPD~6nٶB.hiv:mpO$eogsIutE [JPfsqim~vT.#K=H1M V:j2Avh"zv"&KXT,02~d1J D Cjq#'ӉvMALSmap,+5Xbct,LKԲeAjĬAk=,Gy4-p5-$W+ς= "Cf{uf&M'oܜ]ީ^_K{7n܀eR<>:^x NrC໚S5, z"4lTs r.J2xp~?ؓf_ol$ dp]Ԙu; Λ"~8;hi@vktF^ۡx`I BCIG2v^_[75T!.4>Z(++ Astt9AjRhfՕz xJ(F3TU4M RC Hu&sB!Cp(>VtLh^=wYo~)p̭`rB ZX‹ޮ-/OӘ3]uu+];v;3KKW5F3PXQfXv3CvJG"~⍓గՙuЀ+G;& '(b1Кhؔ4'ww=Lv yZRS7'wf7R{f&wj]h"B0>5]˰ 3Xh F 3G$a)k4ǘ,Zw!2f+,?nVak)fXH4 N9vȾpDnfcuvA86f0Y!aCNt0aEONNb >!)<wdEwRG@H1Y Oiǽv7յ|I3H4>4<299!xB lKOn*w<DW?hGGn/ ,SxP:Zec}e}?q @9HBY wL|o~xQk]1}=-ye_>c}O@*Ci# 9Ũkꐗj,#rJZJXG-f!EYL-T+h%1i(RA;⺀i ٲY_A* Mc LY 21,΃ \v~vq`iZUkՕDs9ACnlʁsg2D!7r,GG49ӑ,BX@B[k`Kzٝ~'?:TA;zxw ԲݝqJŪ -MH?-$V#ɜ} !g,9h,8/Ù"YCRےI\WXX]^6`Ѡ-p}#cvbiz׮Tǭ.n bP,<8EĦ]" GBm X]NZr92ꀺ(ʴL` N?yd*B/J$Y GCSC/}ᱡ.S‘lw<~^)]5/;r,i(K6VЅ4KY(;lpP1,DM`4䫍7}>gg`#+V~$xeʴY,1_X i!)C7-T,=:hq,X۴,꠴1 K%6YH#^IІʚ֢ u)xVjFAZ)gB'.-,omo曒bķ$?8ǰX0tCN˻ u5@AgY/&˓YmG<'4zVwr]1{;4Mu}aK[$at k!Waf : _8PJ*|6HPg-(BB2φ/63j\l߹kN3UEZN,jJ',u }׷]hЏIDM/Kb>5$ gP di\ ;$gZnkv lZ/ e4qiwrܮK3ǎ?YȊ>1طzK-!3^ý<Ԩ/nrk '_驈|d&PW*llNL 8}P)G!dW~ߍ/mL2?>!!>ʚtjD*D:~qo#kƓ~g3lJCMifWR- CpЌ_c!ٕi/R^X]XZY)m )4 =JV!ީWf|݈525]ː^Hh QwD7mЅ|ѩ'Ldg={f>å:@ LSfw:@0cx,ݹU5xM+jBg{\?{qǞQGÕfܙ][؂^pTTuS>d,&U;N8ܝ΀l 큊gP2hcq~KsWڣq\+;D*^Ƿm-:R<{¾S}\P,VPHx J io647KzjVJ$!aЭ[ f3rⱸ DKp\K@F$3L-}žXbQ"v5ĝ F]AO݋F~8gDTQrl8A⠫s8\,gg Ņ&iԁ[XH6mXo(2̃sR[yYboF#>R J %d]w7t.)BѨO &{:ɾxݞNղ[n<'A?Jw$\<[.V Cn!6$+&4#B*`aSM*$Dy߀}6pAX!RB C$'.y+M,CmSr\Kʢ<#5# Ś$nr 9:w8s9aFRPbi@PP,Lm}5ޙh37=;L].jhy<~nU*TVg EƄlր pPi!`.lû&^9~xd|k ˑ-.]8 wO$Z}{+imI0h3I@-h?o%{xʡOu=-5DQSsP$G6CogVwT;RI^28ђ ˒ "+<=>89HB`zݹՅh׀ŘZ3DQ0BM) oxր%CTCYp=.coo]WOOz=}kP*b(bHMs;o}p-K+k}geUIwv9jk NPf20ullԚHµa :vŨ=/m /0[_'(@ZVoA8/,>6da4WbgX[M/4ɾ tP"͏OvYQ40ƙ8ԣ1ZC9Ri˲ʈ(V@0ӟ ԳsW/mv̡:mQ)q hj-14&Y8! JjxD]-X ʃU ܭo(bQD Xe\9rTQ<pMzTC6mpoCX g&:h4&Cݻ:;_8{={hXey?S?av,pv7ニ]~Oo _ VZTzO5mIejP敆%B6:so޸~}b?j=_ŭ\k@m_A^D;kwu[Ƿ՛U~{Oַ./ϴ\x PtXAT.)Hb&ӌI I@m.ff#R,C=PM/)@O& G#a:KrSi ]BY^Zۜ{_3ДQQ`4^jGvtDEayk/^Lw&bmm'^R$_pz2%m6̧11RdZ/mPg@ \hy_mRƥ/d}I? stt勵Օd{[[{사4]~8^^Y3~`iOwtn?yp~ivQXXgG a3mIx?t֩GnnNKR3H&k?Oٳ |)V]0HNCjlH6x4cO;2ݏNٷO"fXc,;+t"FS 17 #AP-X,;P- 2jXhie3, A6Y/o`yjF&2l1ԝ) AĪK4t ]dž~_;ʳ?G_|mb)+P x4-h,+M*JHp:A{4> L6E0" uc[xj)>1 Viw;vGoߝ!(ݼxrGOReYI6&'w._31b(J-J t^'GXx \*L%œ aPH#ܞA.Xwġ`$20$-o%eN%QhzuG^b'q z2U#8p$CzCӍ 4c]=s.|מd|JG6CPJH "mx0>d!_1v&A'(#hU` #u`!*ؔ;u|fqc[$pp*:x; "x2 7wyVOx`~Z@bhpeJ5-{n (:Csy( IT5IMu8𑃲bܸvʏ; NJ (Y8u\4?xh,i6"" "C+Ja!٠<mh}g8-unx:399kKi| |g7"إFCMLW LB4W(q-=+Q/A%j`4H@_BCX$瑎JTR-g$rMbZ,!$Cߐo,Ί 1fܬt7Nr㭗;$z;}N's+yF,F[/jZe%zK0z#H7bhz!}*Ş%9E-~ˌƝ:HM"h~crX/}`fyȞHɊ*@TF{O׾#7}H$H:yZՇNw^ё 2Tj$HpB/;j e14Ւ/żГ9(XfC8X|pb!pE!9:;жYaK %ҩT&iRJ.VNBCUcLwC4p}s-GToͷnzz{{;Fǝ(͞=b gk)?gC"Ҧk"p!IdE:?baG j@_ܬ,Ψr3YpÁ'$J(K)(%6>' B~PmmUU}CHCzQ*[[s/6sE3@VFMx9gAxiZ!QTMi*phP(?+-p0 b$)5ALUTIRUĞI7HMQG%.:rQ7X lvkFbm3WϟʛoA%J XLJaR "p* ^̢ZRkkٹ 4y;2QӱO^-3aߩW"p փhl.t p$ȳpxNvl|6ec ܮT!B!UXҭD|*[ Y9>sσ{J+G>;6Wi,FY ТGS/K|œ.JИ. ͽ lCyH/H`-Z^{y獩qF #;/x A ʤO\)Uj sŔ(bG0YƢxe#W+ⰃZ;mѡg /1 w[x>K[Ѳ5 %%֢bXs[KDj<DiA5qk:IK`'-j܊Q68&2e!%8fX_m(4XMT ۹l!g Ϟ/ja{e~tGQ ۻ3CFLFr]X21;kZC9uk?|\@#[Xp," "|\JZ_6|[ UeA\R$Cyv2{t 4 իҝ7kj{<919 67rMA1vh + IP!4% )dsWƁdN%{,2#2,K&,V(YhGGċZ]5AE40Hf@05;o9T3s+뜝wW弊Gt Ɱx+E-AYaaA %YªH;I+-7!/p@h78!Y@'E/ʪ佷FQ @A ?` ۓno{|fp+x m4SUA=7ùT+zVZ6-Cl$_RX 5ѐCgYxO'C0Z9lp bJ92H/}CD (ԨHz>7 jJO(vP+4 ݻb Dܷ&T|q FRzr8'}r•qV+V9z;H0F'4Cw(i3m*;26"4$G3rȉcU+{~{gZUh s&QK0 494t||{7gsEb܋vGegvZwç/\Lg7H^ Cm~xua!_324:!NΎdh bs~y\yĪ:FMkȊF`YLs} ]=s3qqxqrwxC.w9}?vC2O+BGg)Gi CYjV h`{s3cC{_;zGwt]p8)F=ۨrKzT4e`MKKxC \0㒘ˀʠR{/~7;7BXT> xۓv F7hNP^UC+ӖFs٠lnސD4=,1_WZcn=73 @ D,<U鏆|u{dP4ׅjDh a*]5HJ C`+x<^ϋ쇿m&3}P6]`C3J0T p9]MYZ[p{UUwkORxhlwZaRU}\\y|F={WqDIBBы'Kl1P;uJe|snmih ]OmMp` tb^ݒ❸Xfsʂ\X\}6әJ jˢJrv{ui}kuKlTMCaZTbن cYfP`OזVV痜n'o]~wb@8X5.=yx()/mZ;jl8ғΝB)Wt@/EgJnV^b, $Í[A0nƢ Et CK;2c"y-L#e{D38hAY+`X.6%ݼoj~p==xԇd_$HЋC;GtkLSS!?qCQ *qb'zL<>bq!]KA/CyeN!re>,Y%ah 0l &K)Z͖oT[03mdr՞AQvLTM}Th?צNheA4U ʀ\GGd,Kg2>8Hw?~ ; V4,0g cׅw߲kDZ dBp˄I w̓93q5bq֢m0194,#`t%jK/n߻3QU<o( S]peF~絿||4ypY,tMm?QjZݛJEw'þtbd?ݍX xVd?'\0ŝ{&Le*x,h2) !vMV`$Rpꚜ7_[ta=|@)Ț"\*ٵRz&1; >"k L!67/W6ˬa`G{r w%M?X,FH<ܥۼ8矝yݵT{/14Ú  }`!_RXNmZxcPXRyk1~|vaem+5fc~i#!kcqMJ ;h RNDzh_ j3ћƩv+f:wqtb='^TT?Z+ ݉YRAM^?8<W8hĂ 󜍣/}~vI7B =V)ʠ0.ˌEu %)1Qu(A<ibMY/-Tআ$e(Xvt0[nBDcB˜$ixؔK*RJNiԞ=;;zkGr/;.3FՏQ4xֵZQIM4 R_/Uum8MJ,v *;u1H > JfFdG>eEn[Ƽ:M79ftE˲ܵpt`&77a+8p@ZeCTrމ_ |ր|p Ξ6o<%( $+vp9{'w-?:^,wuwn., mm(m `g\\> C'=&ha:i3446{:1]ۀ{Kx9( Gi 6,{:h h)Ƴ X(vՕϚn@aw~?5`-|rkWoS؎I9 fU.oOD]z`WW[ױw91ٙf8os+˯O}AmJґdA VkL$;;4Y)*Th*I:|E?6ZoQ=d b6q7Q% e9Rk]=o UQwO1]<X n~t9Ol,HCF/^|7d#gg gRP+ "jOLM uZ8ͭlE&'2˷SEBHWWg{۬ ,@b1(["D#lPfo(LbM,NcN1WP!PDp BQ"=5rdAXߜ~ll)8N ASQnT\,o>sF5؛{{ީsϟL~zvvCw}j):Q i_~4VIb>عo9+tH e8uZ 6@]9wðk{zO8*.;O_ɌFG[PUņ* !ۨίn,=_/mL7P%% ԅñorkǻA (f9TA66b]r6Ƀx<ٓ bVeYWTO1"d9jt{kLD .V.TgSۡ,"-zᎺ^,Y8#Friɂ-\69 ni|"Mff+,dxc6gۇzը%tu>{!ıC}kܾqKz>Ҫ!:,\̗*sO3.?ݭ; $ =ZjZ)t&_sV ;^}$zyIW$I^KݷoAy6 bS/kޑTG2Lb1-Ik*-lsKW˛S"P05 h(ȴ&z#م=};<2>fwy.GcF8v)Z (rɽ!go_!4ʕ{mK\kWzӉ'!PTX^tK^'ٓJa{+_(RjMM[$dp' Ȩ33-M/cx6Ц%x۹8-4엧juǡ<.yf{߱ߞq->y8=}CNߝɀR%xM"y^Vjl/5)-on}K&R~!p(eY879_T+A㕷+7 ]rbwvt|tԩ\Jѯ//xۣ]4 plzVUL{clp(cM9kjjbǟάlW6eUxûv]G/ޜ<-P@R;:ŹSϞ}ǯX'];Lҷ_]D$/hjg 閰K}/Ʋ[!eq"B7c9(z=ngvYSkf&Lhqoa[~ M 2!8|a ~[*4/>^^]S%@TQS<),?{Gn'^o] tE?8u9sҭ@wMۡΩ7,vSn mwtEjЛ+k?81N9rC N_m?sMQܮտ3L^kcm)4-K?_\=.$AZ*9i6 oduYHܬV7AL$ixlt xEU6n'BI7kM苕*c1?;;;K 4HC,޽0MpnO4U7c8hP[-VK]:2һc]}.zq tZH|Hof|YXeYdQĜ#H AsW^ޛ^DW/8= 1!ګ m UjM~fbd`w&ۻJuU{(= n(YpLM jKch$jڴ5 ` x7 /nF|m\D  5h0Ȥ *2Crd0C N58*;[ ku8o\po(%Q(mM)j3{/ >Ya7g_X=8vdtw_6\8m=8*CM 48xX Lx۱Fc»Ͻ8n9йTGmjx{Ӌ],Oņqnll>[)A:^ ނ:955Q]5C^GAo4b3 SSW͠34TRÝ}PUA'#"'$޺ENMʖs [[xk./-,{$. y©ˏ?&]xxO] \(؏';? RYdR֨ 7^y[9wbwy/֊ P~wog&F7+^}{ce3ݕKm(p e.I`V& jUS7"p0Ǖsf$˗ ku "# @@H?oY_نӎqH5]C}]\ی[[MǢ]#gΎ/~r?}t{M/:͒lna%vumXZh0 9[dj/.qv=ck 3v\pAH4è=Bv1r"F;=$Yh]ͦڦ嵕F)qd?FޠyPj$=e Ҁ ·;ni p~¶'7^#-xK;G8 $\B %X !n#WYLw-OR4iS{S;z^/& \XѾOz]*iչNC+\[(!B @0j>;>xK'p\\n+Ζdr_>?әoSm58 e%MLLQRGgG]R[2y1ln|V\vK9pHW6Kxe ӬkR-"ICcC\1_(pb/DM, Xd"]S Gxyg}_E@/w#CYNi|Z#sOuXT<GlkoN]~ ǻ¹80_R>[/JRj%tvQC7"{<?qe~v>$5]=bqd,$auy55)smu=Dqwgws~-nlw~AR },Xdnbijw_o\*Oσb…]E* bPkY$?H pd<,ʅ4Š!mʙXL@| R8X诸G6AfQ.TU5ՇΜx$l 4isy{NCl `g_Ap{E %MfL϶ tkjMKhjry, BPO{JB* RLfu,ַŎa4B!H$R *`ƉDo#l7@o,=ܲtRӃ^}[}"M7UMr{Rev$^}&F XV'[?A~۶$G2mpre%l˜[24дZ{#G/rA5+FQk>ZE:USNv@H,gZ4Q#m60p/K1jl,G#%;l r,樰X)?㰌 ca \pu::-,//,y,ARoF=AI< Fӵ y:;AHnfӤ\sy嚪 J^ 4 !Ea…9yA 펐ҕůleYy#VLJןYyW.Շ~46ENT^ZXrqp  lŠ03xEhIgelj9 CdCc5Gl~<𓏱>m"7eA頙6t+wK2KArX1$R)onN13Ao4TTٰZO].} TFh5 &<(?'Yz@XvJjpLjQ.^UyMP\r3hN5-Cr&q ߱# EB3r3 dMhSӦ/l,ѻoxǞ|(jX_Y]Xojc!6EDE  /Ya> (fnTYdLc F_`{PF>: R 1)Ӡ̓吡&TdS ZZhQN-;"qĉΟuqj{Bjx,H!M_@SccE 9z6޾EP0WrǘW8@ + K)ըVDB\ʖ6wwF+_}AwEZ0=xKŭŕ]z)R8rDFFSp_׮[\ FnOͽP(].EjRWXxt7 :eh#- qquݕ/PQ|,Ϯo/-n y =BU0KCo h|ŽzpwPC+4X;Y4ѥce5 ckEI`!02QY%4 8^ZiO#ᦢ06iRIyp*_LL=J2İA1Oe#᭵F!Pm2,q\f"EiH452f\jLWW$_[ZL@7H6=shnP,z~n #^Ф*MTaDlM68NX7,~(}1``?3ƙa7c^`mʌA>=zk]䋥\oMw~ *iWB} ٯz\*JS oS@|k[dF)&]p#~j"ȆALIdZЂp:L{tR\YLbHMTYAYʻXƖC R {:\ƶC.FR#<ωt[POɸD&ŀ?vb97/ߖ,Sf.yAVCv.O΋/ = L\'9?yγ?{)=>vDGV!4cQQ-^{<f 65յ/7vv KGV 1\ChMBK9C-cj*b0q#`d`ĩ4 ga1BuU6#cHS9Qh7w?q.stC= Zzz{`+_X._XEFm"X?c;^<)KR#p[Ce(k$=wi< H4M_uDKhKU&"MlrHʲ ˁy0L]\}/`"=q~+ˏtJF FyxT0iaxg:!!qlU" a,d7LgD6+ģDu"DDtҳA@هIBVT cl(;]u"i׊G){xxT}/W3=$zdIx5|:sw@#tx];8< ;Ύ{e ; 1rEpjsӶOLjjOOq`q]WS㽏oHɀB $ evɲ@;{2_ڛKP #,T[v7j=wO?݌ŢzSWV_kp<(p3ݙx"DGo<-~)eI]VJ1.BĂ&eL~97?<22>=7o])MD!ʵX&}_x 2W?X!4ZNќǜ=U\57]P/{g/L$}s Z# `!.7_=cmh\"f.تJb™3t{ۛMEH p0ƉPes~l ޒ7Z>׷Jg.Kc/ێEc8JȅX5 +Ֆl~駷%;X]*j|>qE܃lδL&rZun$楈8VݐbB>!!NױkYXE?66&<ꩈ1^v@6H/0(=I!z3XbA$[pfvO\%K.CA~mmmkm` m(⛕W}i0XKtu$\I`ёQ )蝛[uA;k7j1󀯯UUtfzp[fme#p@|S.u@oVʠ6_?.-l:`ixyL zBD(a^Sz5lk/Wj:ļRj{v~J8%HߝYͯ_tt S( "Yj;{hPNf:Mhii\0`UQ@ f 8bsgnRJKg~nr)7M0vr-|׮\y(תu~_yx*JDbv% Bm=Ւl-UkrH&k!"(BLM H 08J3Ih,8^I ʽ$Iǽjm cm퉁HY46/>SG5b"1&> h[r5 gu :_W5>00bxX8ewƐ1:@}<|Wan+0ہcoOo vR1F2^8ڌ@`;-)`Rldc96Gf: 挒`QUBXU\/ek+=r9 Sp_>tvx534<$&Hkgѝ `klF:l}ؙ1FS%QqSpU,4s_P*l@+6,5%P),}kttB]j pݠ39\ 80ʶ4Μ!XcQ"0q}=ze ˰6::l@j2153tD.Rvz;6M\|-z1RߙQG%oꌋ-es{߫(jó~tozwxpT)5|@@+'Wo}m1}-4fSSM 1f"N$- n&D,Bp2.e\#-"E,""=cwK҈'7P'r`:E'8o#e 4(I*k&r%-x+T½۟ΞƭgGmmJa AS.]켯:yNq;h{{zf:{rݟ?\ϟCnM2 a~p9Q !o*l' M*Ih{c5=)Qt,`jMf K p ѡhyCwgf}Q-$B {{=u.|^5 nYKeUi0xnlqYsó b"{ꥇ\ZY;oRb^䗓 ;c=#UnTj>PBH:14ֱ~`f",21&Z P#q-̶[:3ȠۑP(nMmkq{;lFc0e`L$nmxwnlnxOD#aZ;Z}/t>F׭ZMQ* 8C ' KMJxmϭZ( ό .5ݙ5 PK?-}i^Qm0P (ǒ)wU5Ep/?btx|/T._YEZ6*n[ ECg="^W`JhyQՌγOh4TPObE' }}tʷ{\+VjC]h@kr0l^}Й W?{zR%θSZR8k|4-v"!PzLC82CC;4" ʇ]LPZ< *p`a=x^%//,0htu$-YƗ~6`+y4:qkoyys]lYaf-~S5Xkw>+HO{]2D:>Ãs Jz6;$%!ҋ4q8H:9[`KR{0C=cmE.\βx E5`د 0FmlFgtlumsN <բ83qpAqh".3DwY8 Od]A=s޶1^48Q NwϿÎCS)f ŀix,Ono0^.T^6UZ7ꪚW{vnH*uu-u`5lR-ĻΟzGzL֞!pwj]7!+j{oJa|jt8hZ$gKSwRԥԽzodRm6I1B@]2Yr0PI*lnr˫wNxhnQ]ّl8Vǝv`,i]BD< (rbمlQӆ'/]: ח?{w/zjZ>[cΞl(ݒJuw{ߤU<~{ ,  5U݄uudA\.Ktc k8`dIB-EXሓ`g4eƱF8McX7BafA)_[dQoִYٍh*j[߹3#_އ{j%1fhL(22/buk|Pԛ/>QU&d# pWZ]Zyu:qviWv,Dˁ|D~T5"_ Vik;'lW@c;PbOIc&,-Gw=YXUhp 1zhƁv̀DCq򜃮.m֕+s%"c\䷮zO#CHaʱAyEKᅙk(fV́k\<{b0Ck UWze_X:W*`mlxNuŴiUwA6%mywrKcigpЅ' :҂r@~~2}|rT,hLӍ,Xx _4+ aO="8Eӎo,"ќ"C6AO̭cmCԅġ6,san.,]~QAyY?ik}//Oηw@7U.27ҚNmǝhOsG\ڊB(웚^,z[m`xhqfmilB|MƃȢ:& ? G֖}haϒ=C"=-QE,X3:nU+7J:kLn,)j_;~Թq[fP7nyon`|5k֚P;4@Y\`qzf7}}?AoVM5[ĽxՅFzp,CD.%j(}݉xCcM6wvM,Xm6rh5 R% ֆߴv'gFRWbt*n5z]QD,rDH\ i`8)9 u~8E U"hVX3(0? %( X$n T#"d&UI倧ww'=O]| ;iɒ,t *6=n<o֬ds>W\|5nuuJ<#AGgXL@EhaPSM:7 EF<@C7M!B8L|dwwRI ڜ?ʃ p_(x{#:p~v\;w(㉧8R[W7@A8 .Qd 5B NFGJrPÍςD95I%mE|7:2-$ kG]iW*Wj:^\cG8>4qMqjxN{7v"M.-J"-g@%#Wk<̣m,׋f$D"Aߗ[GLg^!ݙUp䅳?ry~6i xݠP2ZC`iQ,)&5;yQ < )]l}<_)Ϯ-f@Ħ&Y ~1KdrICFz!G#T=ޫ?olltqxuF K]Zi1%~7_^jJ: ,zgI69{/(>8ܒnj4pߵGvInЦf>hyOjOPHanIirbc}'4T+KR8<^~;xOh@Y5ʵ[w^^Uf5[(VEh@i"" {%ҫՠ(w <_15oP&x *}p>[B%aBEt1MYȗ,hb+ y4-q7Dc(( !|N}IPʁHbA#}{S_mƺz x&sV fCQu#wo|ӝ=zᙗa,H &A+gTz񙗣aql:N x Se`dKnI\H"ڋ~^xC`2,]XwBgEv5("o}5MUXLA!UA}w'*/>O mvGCA%Y%%[=snw>yTX% ? "c燦?>?q?P-V 6fMɤ+OrW 0~[x'Ͼ]}Xkk{{GB&hU܏~DDoG5C'AFBr|CSB-j J#Wͣeű ՜ yc(=Hw qulKrϞS~ⵇ?(7ݝCSvkHδ-gʎ5U7cAﹱWe1jۍrWg%X9(‰.ͤn=x0 a -$M'&Zs T*s_1cCc$Sp0̋.P)[~?wuwt xVvVח*G9F6u5MT$O~ ǃOz{jw?h x^|nfKΡsMNێvD}JB 6p+CnbF# !W)_֚svwW(IhpH x8(ܠelD'ne2کtҠw$U V Vh` oeiGk}ѶGjxĩzZVu͆pGDCli;+O`-.P Tr {5KF8g?.^\*rRxXh._Y]8z%XO^!lK[/M?BIihhv؉k0.;\Ãlq*d#lQD%<)$f1HA(9rfԪJ(%}A1@4{[;[;Ӄ+_˯gJ yZ |P{ 4Q"oZrVE` ZA|5V0× Ml@l8+,t8Z,nFmorRo4Ew"ږS5M RG8Ҵ95zʕx |z/޳ ^TgNs[ij[{^}/K.Hi6}bsYMAZ+.02:Б} Rrқs?=?>Zdj#1=:2m(A C6 i{ݾnN"b]n[;{ك g{,ˑdl 5msht'AP-xJ MU5FϞ̤[xU@&9 ăP0 Y7˯OάƓIW*rRgϟ90ӄ<-Ζ앎jIE@Ԩ)b\m@^ϗ!p7 Ed]Qo8nYW&B*t;Y"[_ kHn+KD#-1TA}֝xOFDAH`4~n~xTGȩ2ksKP_{I5"Hn0Qqb QHӧlPX ׮=d M@FP Qnhnuve!ZWzӴQzptyDM zo| ruH{MӣM|b<>(4s 8,bP!ӏ؈zQ'J97yh55\@Wj2C_<5vkmbSQiKe&;PXHh:r{hb*lʻ>8jޜդ˂nx"֒h%=0?NB4-164 u%K;aB!7Ar&Ax9B@?nxv6^ܼƀ7_h7(2Z@tG"P]7Mt;n~Yt Ԇaɀe 0\%}?f5ӽ<8zs"6p%@GEø[7^z/3{bVA~h;L^ VV Oqw"/4 "xrKDGXny?/^?sdUmeBt"1ZBQ43ϋ&IsW.ҪV[[[,©&Rњi1]ڞxZ՛: Ǣ8`fp#@WogCgG[!n(mVkG9)]W4Üxk2XlےWPFȗl_~1 SBB"?rl<_K];xSl8A<,mhY-p$NX&<ǒšI8-dE`?@/| La/W$X-<ӧn~sx\U EǍf[vwWGbx ʦP,¿Vi{{@fE_kB y7{?u-HXP} \ -iss2Y'g"o^VlFq:925 G4kaz!~*pA ҬM$\88oVFtG65NYJ'zNWY N+pR>,+ ]ϗOaх;drT6dKŬ(bRQt[ ^ Wh*ί{~$b;6j fq+'f >,DYW[-|.#8fAێ=ŕ2TʂDPeb7bmnC0.veuqei R.P}ӷlL:@>}l_wZba838;X ˲10#n1-F 9 Xqbxxx}_zSjT Avٖzlmo/eڨJ᝗_(ov}{,9TCEz96&6 @y ţX"Vri,;Hڥ9g y6~.4Q FrtPؕopqr_,M#! 0f (0Y1Ѝh_okjq_=)ֶhⱨ jZ4M]W ؁˫k@w%H><,CHã,;-.Mgf3NW78hڲ,S&R,Z::4p"m`Hhlv 䓶 x' *O3~`Kps0~#p\ۈ{]h% EЗ~hʺ ]!(ܒ ~/3ЭD2ڍK ~U*5՚ .88><~4z@/T4jJhKdh#jLuS#a*(@KjhmPx6~yzXP-Ex/ /J/X`8 9R+Kۣ7/=0ܨM 6aPXyݣx'pz8ཅ¡L{4L|42apõAuc҂? AVƙZÆm"~bFi RyvzRB9{ѡ~ &xE SZk( K4fA;xGƹ(e  1/Ǵ jMS?hPf zf?=k7߾Q#~~5^^Wanےc~ٴHpIXBʝTgcyXśK?蚎BIL x m;ԉp m1ЙfN,M/k./ NX~ᖘ:25=3A5Ag" (EDwJ^Р!+.Kp鵚"z=푀$bUi%~ȴ,N)&8 p\ !xM_\=QGʆR <5@ᵽs啚* TCY1D$Xu !+VM *07jq gtk(Ļ]DG2сnu7_T*њ3V. N+bQ&ȶɒ@Si2) D4RA Cz,و :Q1KdN4-gyRfijbܡ`MeӣPclP*B/ jxC҃UJliǻ]nݺrpz# {3]܌p,Cyllw.iXR5=0G3ͯeXAb\&$9w[Дxغm -.mnUEMv>uC@T3̍:aZ=;Zc!%P-W@|0#q3v5Q'&F`ӱ}c G o./|ޭH}:Xg%[Y19DE%PDmo Q41>&mI;(6&yd,nf, 46Aq~qQ>|.Wl?`ҕbT΢( 0cm0'BQ]Mkhmͪ\0 SV| d*ޕ Z&EV*$ZB/)T_Hjne}w?|syil4P";‚ ha@2/,?%ltpN5l\9]NS&Fj̀. 7L$XCk`gpأ4IJ>ۅN庪 蚖h;xdo_8űpYwDȆ("MYwJfv. &zTH^AقWԑlYy-1[0@ninI<iăۧ7t ԗ5-TxS>U>xZ}2HHH ׎m:vq-n8b 88z2 $a'aX~ yܭۅ|)I.PԪ,ܺ3b+\\atMX!>69v 8;]٪C~K_z"**hX^Ss %hhw/u."1 %і<ҨT1 wDB`ۡ4!a3X1hGݑJi'Y4&˔c."ﯰ33EbىS %t?F "@L1 Ds%7yd#U-h'sRn;r (jCxP'z%kڜx .J;@2Wq5 " Sǝ-;%= ֳۻz [V*jO*zcǎ'[M=K P/Ͻk&c¯AJ!^nbnճCXD7tZ<|h$塮1]TiOfEöde֗7rˢp X=qI &vKM> ,Y8+'uON8NvKG ] GqÀc`8.^@y֥`JhvvvTb"s楳7oGA:m^+~햎x3DS.]HcCqb% /n CI-;<֍0ݑ"SPGw/ wX/b|ં YsD OP♳f|ѓ`@rVL3O8ۿ髩N5ٰ-.; OT?4VV7޼{cS1T>E56c169!U4  fˍn*MlGc{Ybymy=f*h(T E[PA]mȚkiΟ;wu`v5T4YpڵhwdħVkl0qf61OI`ap r`)%pe! Gaxq }"d0]}]c7n/~Rb$/A}r0U%*c7R+\H"K dcTE8=ð/l&<|>_0\ZZuVH)DszYs 3! 4E4􋯜{MrePd. E1@qX(B>flv3_|<jkPdlrq,O"!RZKK>7kJU|.`ԑ@G,t!3g6YE۪nbz"5{yii5* Gԕ\WtC])0 媬%zh"plDqaEınC~# B|: P:_=V',1EBXPxE]hǯ'ɜ!<@m2_cá V"l/7)V;doHPU Z gP[! /`і [٪F4Bk|߄LOQM! `=)y/s뗯Dܞ\~>xxZ[5h>pץDXX3[loo|M#gjOZYꭵjX\19<(ٰ色lC4pAslIV 娠ĒV cI YAd$#[`|t%n |r nU M~{OųgN O=uTn.I Zu }΁d[u5^T,֪V)9>ASŋK7_oulh @8@ҵo!W2-' 7pXAP AkчFO_>}8e#mx, &/*9%'4807y,L^nbm%yh4GxApiKxa p7YȀ^-TO|NwWWGrf ߞ{/ۦ{Z+j[ 'jjn3PXW벬j3˧oX_ʗ|'aVP8t!(ij$V4V!"%P>bÑ4Z@ (,ZZ+t& zJ'9fX?2rTXvrb )ΘlBT'6f  j\ad @XEJl1_[mlmCaPyxܮ\rXd||tG\غs嚩k +.F}Sr:}wJ>Cyǁby ׬\e4fU~]jfuD)MX"MHVp.W}d*JwtI^ML<(ш/ς'JV %v{4q]+wTK,ru{7V-`)E,cJS VKĀHbCp4rMh'NK@Ut`hGe!3FGG&9 ;2e^vا< z| @+Ҫ 9htmbjCj1060}_lkOzԖWV>ƽоb켇0h>"eKI88,'02!ێrQ3ƚlH̦p]椨wDj >B5 O~7 -./_z# ###A$>}## M[A@ŃeAv-Jm`Ҕ@,'DgR@?> Jeke\=048^=(Րԏ_}ΔxgC)zn88d>& ,ضf"{d`S~TBXWuw&c. y`v'o}_\/T{R>ThѨUHLPYqA#&i=:$A a `TI$&c&k,父=Ua!&4C$Xr@|Up8lP2ڰRE]xI5A4P(sh0E»k8ּؤaaطM,jh: 7l2zF!l0- c,g% +hH) foolw2yS ds7XkH6 Q 4#bLsB+%rO:ooG>Pyw$P!熂n?e#&ZLw,_\+ˠ^+ryd'ndϰ$xw~LdGz֖rr8$t^8{M槏Nvn{$cQsm1ɚV-W6hӒ$3 Of+2OلՅ3#H9rpzR`Gomd>ہְ^ UN>#G"RZ.z HJEYQYW!8ԩD<2x\N$U&iQEŐI}%hkzV^nT4KUJU:T.ȵ 0cnX-^Z_^MgB}Q#Db9 6qD-(4-rMQ&Q-F*6kȊ olݠ@i&&⧀ӼIEAh;.+׷֡b?a,mR04M.lRg$M1Ӎ|i &,x䠫 ;n k 䧎X_)rPX4v Ba ja\&َ!c Vc'A C;-1gѪq"$$|!Nvk%3XH {ϲT$ V$.hBJ h"6$ @" L L8R{nR MCvRc|1W$/|h2lllWNM2,fLg] }=D x7K bT eU+96;# KnV.u-;{szs4(-55w=Hj4vwﯟ}pk}n]7 [;Z;:Ӆ_xm\[2׋xG4Rb`VTMO"\]QѮ2n0ruɜ?xX++q,1ކRSSyT D4P %b| 9#e rUts4"yxܤz:lhQpf˷r"`HGU|VnꛜLVjՕ[wVV3hԿB"c8ؓiY(b68p$H`~i8x.PhPа.j7=lv"L]t`aX‡0^/[t\4'K.}6|nLU֕u ]3MN wu1naN8^UjC?艙T4 z\Bw:2Eey.i2MU+u|MqXMJ2I%KeRD,IŝMW ,'@L̑0N- fM<<:ܷG$!I,+kKZx,j*IA gs@0ző!vjq`Z E{YG sY9Q" @'?֌N~S_A>|^ׅcZ[ x}n6), @sWyͰhDݗ^zs7|}SCnWMp M4ю(OO~Xڕ䩛Ǝ}+WB}Q/W vD,E(YD BL"'MB@W|2 AщJGN9rlMwl@695n;WH}1XI4)ƤӽDFiqdfvhm8 ږ%3LwLJL`k(DؐŵZHu(Je}&8]][yQ;xx8RD^`:ٞր1)̠ Io`l3E ,7 Qx^|ኩ>s[^W jjv 2aR nI ٶ^-|~?w;6x*uԈ^zA&uVr\cfv3˺>a\/{n >nOhrO@d鵧;? `UX;Q H^ȸ"x{;ϭwy$0Ah \RRQᆠ2)b"2V_D;+Bdg͝lePfh>Ur )GpGmEΪ[K[O웤nZFG%&G$).P1E.̛?y9]jj˂8J5xmYZ]DCJCt )!z`L$Zފ;BJ3k+K9?{о٣^$BDXQ YjmR;H 069$_D"RRLn ԯmKs/shb|+{\n94Uj$'Ο$5&<Β!J[v#~0%k7:ۻ"8Óc#&ȅ0?k,72:0621!SrE2}i^+URJ'^(D|^ }eZ.7BQMU@GnȤg3aJ˩r-jj;9|pMy#at˹UTxHNk@[H Բ,y=jZ2xk*BRLGXxk9-Þmʜ fj#q<"h!&@ΖNKa;q =Aft|sA\r^^xm -ёa?A o<䗗X,wZZZtFڰX%ܦ,'Ω;rpݹ;w߼sF/GPWe}z!fJ`AP۸4 SAŗd!Hcq$w}JdSmSpPю WpŇΚâ1C9 /nqxT(Rc"DYԃGN4卝vF.TƣB]iU}Scݠ5 cοwY?zuy@[WV{%6~k+대Ͱ͝}OtNM PaP0T/o+Lзpwaj!HVRr'o o䡫 +O)Ċ@|C3='pp6[)  099<4ܟ=~^zs K+Br`DGX}}S&~+,SxGK09ryyq}$dpW\йdS'n޾੓c#cBUtj,b7plhJh2z6X * A>6hiݔRuCZ"332x #p$ A}q.c\Br{|b+kADlYN.?wK*`9Ks/|CpBUA`H8l"ex0i# J- ۺJ+<|m41;l(IU"}G5'шCS^z̏S˛` ]/@5#zJ6_o]}^}_‰<-,c>E4  p 8~/0l^DQ-}*ihL FK6$BmǾ`X Itct*Vå*&=ƔRhG\,m/m[>'g'Fz U*3O}bhphZV :#TMެ~3eqJEݞw⹧gNP5|~2bxpY畸7_囯uˍ}3zb]ro}ܚ[-AXg>񬓉vM#0di"jbȞeB$mT(8,83ȉ w|[4ydT$)3֞'Q'?deMaas\[8C]UdpaVKZ8' %[ֆ!ܜ_\][PU mn.JEFg2^q&a ,rPOGRakX pްu V@/}}Scc#C]H+IA(rJ [1+JK2Q)w28'"u#NɨwgdP-\􁦚==^ $= ɶ+ 3ȹs7޻:~# ]υeb14d`/+ɃHY;3 L/&5Eˊڀ"_7NJzᕟ={srw wwu&#"eT+HdOvj^b&*%pi 1CU,bB58el6_(PNtU1DK%J,Hi=s)'@f>4b@`n=XH 7](]kKfzzUd W}Il)Z:_dR-TiR\x2[/\hseP,f\Oo`/rn.^%ЌyKJݽ3:SGgvba7~wukusWU!KB@Hf`#(|f !3Kl) 2 ::pgv|aRĊòiQfѝ IgM&A4Mdڢa*4ATj=sf&>}*o-Wꠦ$g޹x _4 UDVa0i"/ID"^׌bkի7DYMUiݝmnɍ?nϽ=o|h'⊆*Ǻtl:'(u 9vDK Q "ӌݔa